2 Copyright 2002-2009, The AROS Development Team. All rights reserved.
7 #include "../portable_macros.h"
8 #define WANDERER_BUILTIN_ICONVOLUMELIST 1
11 #include <aros/debug.h>
14 #define DEBUG_ILC_EVENTS
15 #define DEBUG_ILC_KEYEVENTS
16 #define DEBUG_ILC_ICONRENDERING
17 #define DEBUG_ILC_ICONSORTING
18 #define DEBUG_ILC_ICONSORTING_DUMP
19 #define DEBUG_ILC_ICONPOSITIONING
20 #define DEBUG_ILC_LASSO
21 #define DEBUG_ILC_MEMALLOC
30 #include <dos/datetime.h>
31 #include <dos/filehandler.h>
33 #include <exec/memory.h>
34 #include <graphics/gfx.h>
35 #include <graphics/view.h>
36 #include <graphics/rpattr.h>
37 #include <workbench/icon.h>
38 #include <workbench/workbench.h>
41 #include <devices/rawkeycodes.h>
42 #include <clib/alib_protos.h>
45 #include <proto/exec.h>
46 #include <proto/graphics.h>
47 #include <proto/utility.h>
48 #include <proto/dos.h>
49 #include <proto/icon.h>
50 #include <proto/layers.h>
51 #include <proto/dos.h>
52 #include <proto/iffparse.h>
55 #include <prefs/prefhdr.h>
56 #include <prefs/wanderer.h>
58 #include <prefs_AROS/prefhdr.h>
59 #include <prefs_AROS/wanderer.h>
62 #include <proto/cybergraphics.h>
65 #include <cybergraphx/cybergraphics.h>
67 #include <cybergraphx_AROS/cybergraphics.h>
71 #if defined(__AMIGA__) && !defined(__PPC__)
72 #define NO_INLINE_STDARG
74 #include <proto/intuition.h>
75 #include <proto/muimaster.h>
76 #include <libraries/mui.h>
77 //#include "muimaster_intern.h"
78 //#include "support.h"
80 #include "iconlist_attributes.h"
81 #include "icon_attributes.h"
83 #include "iconvolumelist_private.h"
89 #define D(x) if (DEBUG) x
91 #define bug DebugPrintF
100 #define __DL_UNIT dl->dol_Ext.dol_AROS.dol_Unit
102 extern struct Library
*MUIMasterBase
;
106 struct List dvl_List
;
112 struct Node dvn_Node
;
116 struct Device
*dvn_Device
;
117 struct Unit
*dvn_Unit
;
118 struct MsgPort
*dvn_Port
;
121 ///IconVolumeList__CreateDOSList()
122 static struct DOSVolumeList
*IconVolumeList__CreateDOSList(void)
124 APTR pool
= CreatePool(MEMF_PUBLIC
| MEMF_CLEAR
,4096,4096);
126 D(bug("[IconVolList]: %s()\n", __PRETTY_FUNCTION__
));
130 struct DOSVolumeList
*newdvl
= (struct DOSVolumeList
*)AllocPooled(pool
, sizeof(struct DOSVolumeList
));
133 struct DosList
*dl
= NULL
;
135 NewList((struct List
*)&newdvl
->dvl_List
);
136 newdvl
->dvl_Pool
= pool
;
138 dl
= LockDosList(LDF_VOLUMES
|LDF_READ
);
139 while(( dl
= NextDosEntry(dl
, LDF_VOLUMES
)))
143 UBYTE
*dosname
= (UBYTE
*)AROS_BSTR_ADDR(dl
->dol_Name
);
144 LONG len
= AROS_BSTR_strlen(dl
->dol_Name
);
146 if ((vn_VolName
= (STRPTR
)AllocPooled(newdvl
->dvl_Pool
, len
+ 2)))
148 struct DOSVolumeNode
*newdvn
= NULL
;
150 vn_VolName
[len
] = ':';
151 vn_VolName
[len
+ 1] = 0;
152 strncpy(vn_VolName
, dosname
, len
);
154 if ((newdvn
= (struct DOSVolumeNode
*)AllocPooled(newdvl
->dvl_Pool
, sizeof(*newdvn
))))
156 newdvn
->dvn_VolName
= vn_VolName
;
157 newdvn
->dvn_Unit
= __DL_UNIT
;
158 D(bug("[IconVolList] %s: Registering Volume '%s' @ %p (Device '%s' @ 0x%p, Unit @ 0x%p) Type: %d\n", __PRETTY_FUNCTION__
, newdvn
->dvn_VolName
, dl
, dl
->dol_Ext
.dol_AROS
.dol_Device
->dd_Library
.lib_Node
.ln_Name
, dl
->dol_Ext
.dol_AROS
.dol_Device
, newdvn
->dvn_Unit
, dl
->dol_Type
));
159 if (dl
->dol_misc
.dol_handler
.dol_Startup
)
161 struct FileSysStartupMsg
*thisfs_SM
= dl
->dol_misc
.dol_handler
.dol_Startup
;
162 D(bug("[IconVolList] %s: Startup msg @ 0x%p\n", __PRETTY_FUNCTION__
, thisfs_SM
));
163 D(bug("[IconVolList] %s: Startup Device @ %p, Unit %d\n", __PRETTY_FUNCTION__
, thisfs_SM
->fssm_Device
, thisfs_SM
->fssm_Unit
));
166 if (dl
->dol_Task
!= NULL
)
168 D(bug("[IconVolList] %s: Packet Style device\n", __PRETTY_FUNCTION__
));
169 newdvn
->dvn_Port
= dl
->dol_Task
;
171 #if defined(__AROS__)
172 else if (dl
->dol_Ext
.dol_AROS
.dol_Device
!= NULL
)
174 D(bug("[IconVolList] %s: IOFS Style device\n", __PRETTY_FUNCTION__
));
175 newdvn
->dvn_Port
= dl
->dol_Ext
.dol_AROS
.dol_Device
;
180 D(bug("[IconVolList] %s: Unknown device type\n", __PRETTY_FUNCTION__
));
182 AddTail((struct List
*)&newdvl
->dvl_List
, (struct Node
*)&newdvn
->dvn_Node
);
186 UnLockDosList(LDF_VOLUMES
|LDF_READ
);
188 dl
= LockDosList(LDF_DEVICES
|LDF_READ
);
189 while(( dl
= NextDosEntry(dl
, LDF_DEVICES
)))
191 struct DOSVolumeNode
*dvn
= NULL
;
192 char *nd_nambuf
= NULL
;
193 BPTR nd_lock
= (BPTR
)NULL
;
194 struct InfoData
*nd_paramblock
= NULL
;
196 UBYTE
*dosname
= (UBYTE
*)AROS_BSTR_ADDR(dl
->dol_Name
);
197 LONG len
= AROS_BSTR_strlen(dl
->dol_Name
);
199 D(bug("[IconVolList] %s: Checking Device '%s' @ %p (Device '%s' @ 0x%p, Unit @ 0x%p) Type: %d\n", __PRETTY_FUNCTION__
, dosname
, dl
, dl
->dol_Ext
.dol_AROS
.dol_Device
->dd_Library
.lib_Node
.ln_Name
, dl
->dol_Ext
.dol_AROS
.dol_Device
, __DL_UNIT
, dl
->dol_Type
));
200 #if defined(__AROS__)
201 if ((dl
->dol_Task
== NULL
) && (dl
->dol_Ext
.dol_AROS
.dol_Device
!= NULL
))
203 D(bug("[IconVolList] %s: '%s' : IOFS Device\n", __PRETTY_FUNCTION__
, dosname
));
207 if (dl
->dol_Task
== NULL
)
209 D(bug("[IconVolList] %s: '%s' : dol_Task == NULL!\n", __PRETTY_FUNCTION__
, dosname
));
214 D(bug("[IconVolList] %s: '%s' : Packet Device\n", __PRETTY_FUNCTION__
, dosname
));
217 if ((nd_nambuf
= AllocPooled(newdvl
->dvl_Pool
, len
+ 2)) != NULL
)
219 strncpy(nd_nambuf
, dosname
, len
);
220 nd_nambuf
[len
] = ':';
221 nd_nambuf
[len
+ 1] = 0;
222 ////sprintf(nd_nambuf, "%s:", dosname);
225 nd_paramblock
= NULL
;
227 D(bug("[IconVolList] %s: '%s' : Checking for Attached Volumes ... \n", __PRETTY_FUNCTION__
, dosname
));
228 /* Find the Volume attached to this device */
230 dvn
= (struct DOSVolumeNode
*)GetHead(newdvl
);
233 if ((dvn
->dvn_Port
!= NULL
) &&
235 (dvn
->dvn_Port
== dl
->dol_Task
)
236 #if defined(__AROS__)
237 || (dvn
->dvn_Port
== dl
->dol_Ext
.dol_AROS
.dol_Device
)
245 D(bug("[IconVolList] %s: '%s' : Attempting to Lock() device ... \n", __PRETTY_FUNCTION__
, dosname
));
246 if ((nd_lock
= Lock(nd_nambuf
, SHARED_LOCK
)) == NULL
)
248 D(bug("[IconVolList] %s: '%s' : Failed to obtain Lock()\n", __PRETTY_FUNCTION__
, dosname
));
251 if ((nd_lock
) && (nd_paramblock
== NULL
))
253 if ((nd_paramblock
= AllocMem(sizeof(struct InfoData
), MEMF_CLEAR
|MEMF_PUBLIC
)) == NULL
)
255 D(bug("[IconVolList] %s: '%s' : Failed to allocate storage for device paramblock\n", __PRETTY_FUNCTION__
, dosname
));
258 D(bug("[IconVolList] %s: Getting Info for '%s'\n", __PRETTY_FUNCTION__
, nd_nambuf
));
259 Info(nd_lock
, nd_paramblock
);
261 if (dvn
->dvn_Unit
== __DL_UNIT
)
263 if ((nd_paramblock
) && (nd_paramblock
->id_DiskType
!= ID_NO_DISK_PRESENT
))
265 D(bug("[IconVolList] %s: '%s' : Device unit %d, state = %x, Vol node @ %p\n", __PRETTY_FUNCTION__
, nd_nambuf
, nd_paramblock
->id_UnitNumber
, nd_paramblock
->id_DiskState
, BADDR(nd_paramblock
->id_VolumeNode
)));
271 dvn
->dvn_FLags
&= ~ICONENTRY_VOL_OFFLINE
;
273 if (nd_paramblock
->id_DiskState
== ID_VALIDATING
)
275 D(bug("[IconVolList] %s: '%s' : Validating\n", __PRETTY_FUNCTION__
, nd_nambuf
));
281 if (nd_paramblock
->id_DiskState
== ID_WRITE_PROTECTED
)
283 D(bug("[IconVolList] %s: '%s' : Volume is WRITE-PROTECTED\n", __PRETTY_FUNCTION__
, nd_nambuf
));
284 dvn
->dvn_FLags
|= ICONENTRY_VOL_READONLY
;
287 switch (nd_paramblock
->id_DiskType
)
290 case ID_UNREADABLE_DISK
:
294 case ID_NOT_REALLY_DOS
:
298 case ID_KICKSTART_DISK
:
303 /* A filesystem type.. ie ID_DOS_DISK */
309 if (nd_namext_len
> 0)
311 char *newVolName
= NULL
;
312 newVolName
= AllocPooled(newdvl
->dvl_Pool
, strlen(dvn
->dvn_VolName
) + nd_namext_len
+ 2);
313 sprintf(newVolName
, "%s%s", dvn
->dvn_VolName
, nd_namext
);
314 dvn
->dvn_VolName
= newVolName
;
319 D(bug("[IconVolList] %s: '%s' : No Media Inserted (error state?)\n", __PRETTY_FUNCTION__
, nd_nambuf
));
321 dvn
->dvn_DevName
= nd_nambuf
;
322 D(bug("[IconVolList] %s: DeviceName set to '%s' for '%s'\n", __PRETTY_FUNCTION__
, dvn
->dvn_DevName
, dvn
->dvn_VolName
));
326 D(bug("[IconVolList] %s: '%s' : Volume not attached to this device .. skipping\n", __PRETTY_FUNCTION__
, nd_nambuf
));
331 D(bug("[IconVolList] %s: '%s' : Volume '%s' is OFFLINE\n", __PRETTY_FUNCTION__
, nd_nambuf
, dvn
->dvn_VolName
));
332 dvn
->dvn_FLags
|= ICONENTRY_VOL_OFFLINE
;
335 dvn
= (struct DOSVolumeNode
*)GetSucc(dvn
);
340 D(bug("[IconVolList] %s: '%s' : Couldnt find an associated Volume\n", __PRETTY_FUNCTION__
, nd_nambuf
));
344 FreeMem(nd_paramblock
, sizeof(struct InfoData
));
349 UnLockDosList(LDF_DEVICES
|LDF_READ
);
359 ///IconVolumeList__DestroyDOSList()
360 static void IconVolumeList__DestroyDOSList(struct DOSVolumeList
*dvl
)
362 D(bug("[IconVolList]: %s()\n", __PRETTY_FUNCTION__
));
363 if (dvl
&& dvl
->dvl_Pool
) DeletePool(dvl
->dvl_Pool
);
366 /* sba: End SimpleFind3 */
369 /**************************************************************************
371 **************************************************************************/
372 IPTR
IconVolumeList__OM_NEW(struct IClass
*CLASS
, Object
*obj
, struct opSet
*message
)
374 struct IconDrawerList_DATA
*data
= NULL
;
375 // struct TagItem *tag = NULL,
378 D(bug("[IconVolList]: %s()\n", __PRETTY_FUNCTION__
));
380 obj
= (Object
*)DoSuperNewTags(CLASS
, obj
, NULL
,
381 TAG_MORE
, (IPTR
) message
->ops_AttrList
);
386 data
= INST_DATA(CLASS
, obj
);
388 SET(obj
, MUIA_IconList_DisplayFlags
, ICONLIST_DISP_VERTICAL
);
389 SET(obj
, MUIA_IconList_SortFlags
, ICONLIST_SORT_MASK
);
391 D(bug("[IconVolList] obj = %ld\n", obj
));
396 struct IconEntry
*FindIconlistIcon(struct List
*iconlist
, char *icondevname
)
398 struct IconEntry
*foundEntry
= NULL
;
400 ForeachNode(iconlist
, foundEntry
)
402 if (((strcasecmp(foundEntry
->ile_IconListEntry
.filename
, icondevname
)) == 0) ||
403 ((strcasecmp(foundEntry
->ile_IconListEntry
.label
, icondevname
)) == 0))
409 ///MUIM_IconList_Update()
410 /**************************************************************************
412 **************************************************************************/
413 IPTR
IconVolumeList__MUIM_IconList_Update(struct IClass
*CLASS
, Object
*obj
, struct MUIP_IconList_Update
*message
)
415 //struct IconVolumeList_DATA *data = INST_DATA(CLASS, obj);
416 struct IconEntry
*this_Icon
= NULL
;
417 struct DOSVolumeList
*dvl
= NULL
;
418 struct DOSVolumeNode
*dvn
= NULL
;
419 char *devname
= NULL
;
420 struct List
*iconlist
= NULL
;
421 struct List newiconlist
;
422 struct Node
*tmpNode
= NULL
;
424 D(bug("[IconVolList]: %s()\n", __PRETTY_FUNCTION__
));
426 DoSuperMethodA(CLASS
, obj
, (Msg
) message
);
428 GET(obj
, MUIA_Group_ChildList
, &iconlist
);
430 if (iconlist
!= NULL
)
432 NewList(&newiconlist
);
434 if ((dvl
= IconVolumeList__CreateDOSList()) != NULL
)
436 D(bug("[IconVolList] %s: DOSVolumeList @ %p\n", __PRETTY_FUNCTION__
, dvl
));
439 ForeachNode(dvl
, dvn
)
441 Foreach_Node(dvl
, dvn
);
444 D(bug("[IconVolList] %s: DOSVolumeNode @ %p\n", __PRETTY_FUNCTION__
, dvn
));
445 if (dvn
->dvn_VolName
)
447 D(bug("[IconVolList] %s: DOSList Entry '%s'\n", __PRETTY_FUNCTION__
, dvn
->dvn_VolName
));
449 if (dvn
->dvn_FLags
& ICONENTRY_VOL_OFFLINE
)
450 devname
= dvn
->dvn_VolName
;
452 devname
= dvn
->dvn_DevName
;
454 D(bug("[IconVolList] %s: Processing '%s'\n", __PRETTY_FUNCTION__
, devname
));
456 if ((this_Icon
= FindIconlistIcon(iconlist
, devname
)) != NULL
)
458 D(bug("[IconVolList] %s: Found existing IconEntry for '%s' @ %p\n", __PRETTY_FUNCTION__
, this_Icon
->ile_IconListEntry
.label
, this_Icon
));
459 Remove((struct Node
*)&this_Icon
->ile_IconNode
);
460 /* Compare the Icon and update as needed ... */
461 this_Icon
->ile_Flags
= ICONENTRY_FLAG_NEEDSUPDATE
;
462 AddTail(&newiconlist
, (struct Node
*)&this_Icon
->ile_IconNode
);
464 else if ((this_Icon
= (struct IconEntry
*)DoMethod(obj
, MUIM_IconList_CreateEntry
, (IPTR
)devname
, (IPTR
)dvn
->dvn_VolName
, (IPTR
)NULL
, (IPTR
)NULL
, ST_ROOT
)) != NULL
)
466 Remove((struct Node
*)&this_Icon
->ile_IconNode
);
467 D(bug("[IconVolList] %s: Created IconEntry for '%s' @ %p\n", __PRETTY_FUNCTION__
, this_Icon
->ile_IconListEntry
.label
, this_Icon
));
468 if (!(this_Icon
->ile_Flags
& ICONENTRY_FLAG_HASICON
))
469 this_Icon
->ile_Flags
|= ICONENTRY_FLAG_HASICON
;
471 if ((strcasecmp(dvn
->dvn_VolName
, "Ram Disk:")) == 0)
473 D(bug("[IconVolList] %s: Setting '%s' icon node priority to 5\n", __PRETTY_FUNCTION__
, this_Icon
->ile_IconListEntry
.label
));
474 this_Icon
->ile_IconNode
.ln_Pri
= 5; // Special dirs get Priority 5
478 this_Icon
->ile_IconNode
.ln_Pri
= 1; // Fixed Media get Priority 1
480 AddTail(&newiconlist
, (struct Node
*)&this_Icon
->ile_IconNode
);
484 D(bug("[IconVolList] %s: Failed to Add IconEntry for '%s'\n", __PRETTY_FUNCTION__
, dvn
->dvn_VolName
));
486 } /* (dvn->dvn_VolName) */
488 IconVolumeList__DestroyDOSList(dvl
);
489 ForeachNodeSafe(iconlist
, this_Icon
, tmpNode
)
491 D(bug("[IconVolList] %s: Destroying Removed IconEntry for '%s' @ %p\n", __PRETTY_FUNCTION__
, this_Icon
->ile_IconListEntry
.label
, this_Icon
));
492 //if (this_Icon->ile_Flags & ICONENTRY_FLAG_SELECTED)
493 // Remove(this_Icon->ile_SelectionNode);
495 DoMethod(obj
, MUIM_IconList_DestroyEntry
, this_Icon
);
497 ForeachNodeSafe(&newiconlist
, this_Icon
, tmpNode
)
499 AddTail(iconlist
, (struct Node
*)&this_Icon
->ile_IconNode
);
503 /* default display/sorting flags */
504 DoMethod(obj
, MUIM_IconList_Sort
);
510 #if WANDERER_BUILTIN_ICONVOLUMELIST
511 BOOPSI_DISPATCHER(IPTR
, IconVolumeList_Dispatcher
, CLASS
, obj
, message
)
513 #if !defined(__AROS__)
514 struct IClass
*CLASS
= cl
;
517 switch (message
->MethodID
)
519 case OM_NEW
: return IconVolumeList__OM_NEW(CLASS
, obj
, (struct opSet
*)message
);
520 case MUIM_IconList_Update
: return IconVolumeList__MUIM_IconList_Update(CLASS
,obj
,(APTR
)message
);
523 return DoSuperMethodA(CLASS
, obj
, message
);
525 BOOPSI_DISPATCHER_END
527 #if defined(__AROS__)
528 /* Class descriptor. */
529 const struct __MUIBuiltinClass _MUI_IconVolumeList_desc
= {
532 sizeof(struct IconVolumeList_DATA
),
533 (void*)IconVolumeList_Dispatcher
537 #if !defined(__AROS__)
538 struct MUI_CustomClass
*initIconVolumeListClass(void)
540 return (struct MUI_CustomClass
*) MUI_CreateCustomClass(NULL
, NULL
, IconList_Class
, sizeof(struct IconVolumeList_DATA
), ENTRY(IconVolumeList_Dispatcher
));
543 #endif /* WANDERER_BUILTIN_ICONVOLUMELIST */