2 Copyright 2002-2019, 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 extern struct Library
*MUIMasterBase
;
104 struct List dvl_List
;
110 struct Node dvn_Node
;
114 struct MsgPort
*dvn_Port
;
117 static BOOL
VolumeIsOffline(struct DosList
*dl
)
119 return dl
->dol_Task
== NULL
;
122 ///IconVolumeList__CreateDOSList()
123 static struct DOSVolumeList
*IconVolumeList__CreateDOSList(void)
126 struct DosList
*dl
= NULL
;
127 struct DOSVolumeNode
*newdvn
= NULL
;
128 struct DOSVolumeList
*newdvl
= NULL
;
130 D(bug("[IconVolumeList]: %s()\n", __PRETTY_FUNCTION__
));
132 if ((pool
= CreatePool(MEMF_PUBLIC
| MEMF_CLEAR
, 4096, 4096)) != NULL
)
135 (struct DOSVolumeList
*)AllocPooled(pool
,
136 sizeof(struct DOSVolumeList
))) != NULL
)
138 NewList((struct List
*)&newdvl
->dvl_List
);
139 newdvl
->dvl_Pool
= pool
;
141 /* work around to only start scanning dos list after all */
142 /* shared locks are gone, eg. in rom/dos/getdeviceproc.c RunHandler */
143 dl
= LockDosList(LDF_VOLUMES
| LDF_WRITE
);
144 while ((dl
= NextDosEntry(dl
, LDF_VOLUMES
)))
148 UBYTE
*dosname
= (UBYTE
*) AROS_BSTR_ADDR(dl
->dol_Name
);
149 LONG len
= AROS_BSTR_strlen(dl
->dol_Name
);
151 D(bug("[IconVolumeList] Found volume %b (length %u)\n",
154 if ((vn_VolName
= AllocPooled(newdvl
->dvl_Pool
, len
+ 2)))
156 strncpy(vn_VolName
, dosname
, len
+ 1);
157 vn_VolName
[len
] = ':';
158 vn_VolName
[len
+ 1] = 0;
161 AllocPooled(newdvl
->dvl_Pool
,
162 sizeof(struct DOSVolumeNode
))))
164 newdvn
->dvn_VolName
= vn_VolName
;
166 ("[IconVolumeList] Registering Volume '%s' @ %p, Type %d, Port 0x%p\n",
167 newdvn
->dvn_VolName
, dl
, dl
->dol_Type
,
170 newdvn
->dvn_Port
= dl
->dol_Task
;
172 if (VolumeIsOffline(dl
))
175 ("[IconVolumeList] %s: Volume '%s' is OFFLINE\n",
177 newdvn
->dvn_VolName
));
179 (ICONENTRY_VOL_OFFLINE
|
180 ICONENTRY_VOL_DISABLED
);
183 if (dl
->dol_misc
.dol_handler
.dol_Startup
)
185 struct FileSysStartupMsg
*thisfs_SM
=
186 BADDR(dl
->dol_misc
.dol_handler
.dol_Startup
);
188 bug("[IconVolumeList] %s: Startup msg @ 0x%p\n",
189 __PRETTY_FUNCTION__
, thisfs_SM
);
190 bug("[IconVolumeList] %s: Startup Device @ %p, Unit %d\n", __PRETTY_FUNCTION__
, thisfs_SM
->fssm_Device
, thisfs_SM
->fssm_Unit
);
193 if (dl
->dol_Task
!= NULL
)
194 bug("[IconVolumeList] %s: Packet Style device\n", __PRETTY_FUNCTION__
);
196 bug("[IconVolumeList] %s: Unknown device type\n", __PRETTY_FUNCTION__
);
198 AddTail((struct List
*)&newdvl
->dvl_List
,
199 (struct Node
*)&newdvn
->dvn_Node
);
203 D(bug("[IconVolumeList] Finished registering volumes\n"));
204 UnLockDosList(LDF_VOLUMES
| LDF_WRITE
);
206 dl
= LockDosList(LDF_DEVICES
| LDF_READ
);
207 while ((dl
= NextDosEntry(dl
, LDF_DEVICES
)))
209 struct DOSVolumeNode
*dvn
= NULL
;
210 char *nd_nambuf
= NULL
;
211 struct InfoData
*nd_paramblock
= NULL
;
213 UBYTE
*dosname
= (UBYTE
*) AROS_BSTR_ADDR(dl
->dol_Name
);
214 LONG len
= AROS_BSTR_strlen(dl
->dol_Name
);
217 ("[IconVolumeList] %s: Checking Device '%s' @ %p (Device ",
218 __PRETTY_FUNCTION__
, dosname
, dl
));
220 if (dl
->dol_Task
== NULL
)
222 D(bug("[IconVolumeList] %s: '%s' : handler inactive!\n",
223 __PRETTY_FUNCTION__
, dosname
));
228 AllocPooled(newdvl
->dvl_Pool
, len
+ 2)) != NULL
)
230 strncpy(nd_nambuf
, dosname
, len
+ 1);
231 nd_nambuf
[len
] = ':';
232 nd_nambuf
[len
+ 1] = 0;
234 if (!IsFileSystem(nd_nambuf
))
236 FreePooled(newdvl
->dvl_Pool
, nd_nambuf
, len
+ 2);
241 AllocMem(sizeof(struct InfoData
),
242 MEMF_CLEAR
| MEMF_PUBLIC
)) != NULL
)
245 if (!DoPkt(dl
->dol_Task
, ACTION_DISK_INFO
,
246 (SIPTR
) MKBADDR(nd_paramblock
),
247 (SIPTR
) BNULL
, (SIPTR
) BNULL
,
248 (SIPTR
) BNULL
, (SIPTR
) BNULL
))
250 FreeMem(nd_paramblock
,
251 sizeof(struct InfoData
));
252 nd_paramblock
= NULL
;
259 ("[IconVolumeList] %s: Failed to allocate InfoData storage\n",
260 __PRETTY_FUNCTION__
, nd_nambuf
));
264 ("[IconVolumeList] %s: '%s' : Checking for Attached Volumes ... \n",
265 __PRETTY_FUNCTION__
, dosname
));
266 /* Find the Volume attached to this device */
269 (struct DOSVolumeNode
*)GetHead((struct List
270 *)&newdvl
->dvl_List
);
275 /* For packet handlers it's enough to compare MsgPort */
276 volfound
= dvn
->dvn_Port
== dl
->dol_Task
;
280 if (!(dvn
->dvn_Flags
& ICONENTRY_VOL_OFFLINE
))
283 && (nd_paramblock
->id_DiskType
!=
287 int nd_namext_len
= 0;
290 ("[IconVolumeList] %s: '%s' : Device unit %d, state = %x, Vol node @ %p\n",
291 __PRETTY_FUNCTION__
, nd_nambuf
,
292 nd_paramblock
->id_UnitNumber
,
293 nd_paramblock
->id_DiskState
,
295 (nd_paramblock
->id_VolumeNode
)));
299 ~(ICONENTRY_VOL_OFFLINE
|
300 ICONENTRY_VOL_DISABLED
);
302 switch (nd_paramblock
->id_DiskState
)
306 ("[IconVolumeList] %s: '%s' : Validating\n",
314 case ID_WRITE_PROTECTED
:
316 ("[IconVolumeList] %s: '%s' : Volume is WRITE-PROTECTED\n",
321 ICONENTRY_VOL_READONLY
;
325 if (nd_namext_len
> 0)
328 AllocPooled(newdvl
->dvl_Pool
,
329 strlen(dvn
->dvn_VolName
) +
334 sprintf(newVolName
, "%s%s",
337 dvn
->dvn_VolName
= newVolName
;
344 ("[IconVolumeList] %s: '%s' : No Media Inserted (error state?)\n",
349 dvn
->dvn_DevName
= nd_nambuf
;
351 ("[IconVolumeList] %s: DeviceName set to '%s' for '%s'\n",
359 ("[IconVolumeList] '%s' : Volume is offline... skipping\n",
363 dvn
= (struct DOSVolumeNode
*)GetSucc(dvn
);
369 ("[IconVolumeList] %s: '%s' : Couldn't find an associated Volume\n",
370 __PRETTY_FUNCTION__
, nd_nambuf
));
372 && (nd_paramblock
->id_DiskType
!=
376 (struct DOSVolumeNode
377 *)AllocPooled(newdvl
->dvl_Pool
,
378 sizeof(struct DOSVolumeNode
))))
381 int nd_namext_len
= 0;
383 switch (nd_paramblock
->id_DiskType
)
389 case ID_UNREADABLE_DISK
:
393 case ID_NOT_REALLY_DOS
:
397 case ID_KICKSTART_DISK
:
405 ("[IconVolumeList] %s: '%s' : disk type 0x%lx\n",
406 __PRETTY_FUNCTION__
, nd_nambuf
,
407 nd_paramblock
->id_DiskType
));
410 if (nd_namext_len
> 0)
412 if ((newdvn
->dvn_VolName
=
413 AllocPooled(newdvl
->dvl_Pool
,
415 nd_namext_len
+ 2)) != NULL
)
417 sprintf(newdvn
->dvn_VolName
, "%s%s",
418 nd_nambuf
, nd_namext
);
419 newdvn
->dvn_DevName
= nd_nambuf
;
421 ICONENTRY_VOL_DISABLED
;
422 AddTail((struct List
*)
432 ("[IconVolumeList] %s: '%s' : Unknown Condition?\n",
442 FreeMem(nd_paramblock
, sizeof(struct InfoData
));
445 UnLockDosList(LDF_DEVICES
| LDF_READ
);
456 ///IconVolumeList__DestroyDOSList()
457 static void IconVolumeList__DestroyDOSList(struct DOSVolumeList
*dvl
)
459 D(bug("[IconVolumeList]: %s()\n", __PRETTY_FUNCTION__
));
460 if (dvl
&& dvl
->dvl_Pool
)
461 DeletePool(dvl
->dvl_Pool
);
465 /* sba: End SimpleFind3 */
468 /**************************************************************************
470 **************************************************************************/
471 IPTR
IconVolumeList__OM_NEW(struct IClass
*CLASS
, Object
* obj
,
472 struct opSet
*message
)
475 struct IconDrawerList_DATA
*data
= NULL
;
477 // struct TagItem *tag = NULL,
480 D(bug("[IconVolumeList]: %s()\n", __PRETTY_FUNCTION__
));
482 obj
= (Object
*) DoSuperNewTags(CLASS
, obj
, NULL
,
483 TAG_MORE
, (IPTR
) message
->ops_AttrList
);
488 SET(obj
, MUIA_IconList_DisplayFlags
,
489 (ICONLIST_DISP_VERTICAL
| ICONLIST_DISP_MODEDEFAULT
));
490 SET(obj
, MUIA_IconList_SortFlags
, MUIV_IconList_Sort_ByName
);
492 D(bug("[IconVolumeList] obj @ %p\n", obj
));
498 static struct IconEntry
*FindIconlistVolumeIcon(struct List
*iconlist
,
499 char *icondevname
, char *iconvolname
)
501 struct IconEntry
*foundEntry
= NULL
;
503 /* First look for icons representing offline volumes which match the volume name */
504 ForeachNode(iconlist
, foundEntry
)
506 if ((foundEntry
->ie_IconListEntry
.type
== ST_ROOT
)
507 && (_volpriv(foundEntry
)->vip_FLags
& ICONENTRY_VOL_OFFLINE
)
508 && (strcasecmp(foundEntry
->ie_IconListEntry
.label
, iconvolname
) == 0))
512 /* Then, match on device name */
513 ForeachNode(iconlist
, foundEntry
)
515 if ((foundEntry
->ie_IconListEntry
.type
== ST_ROOT
)
516 && (((strcasecmp(foundEntry
->ie_IconNode
.ln_Name
, icondevname
)) == 0)
517 || ((strcasecmp(foundEntry
->ie_IconListEntry
.label
, icondevname
)) == 0)))
523 ///MUIM_IconList_Update()
524 /**************************************************************************
526 **************************************************************************/
527 IPTR
IconVolumeList__MUIM_IconList_Update(struct IClass
* CLASS
,
528 Object
* obj
, struct MUIP_IconList_Update
* message
)
530 //struct IconVolumeList_DATA *data = INST_DATA(CLASS, obj);
531 struct IconEntry
*this_Icon
= NULL
;
532 struct DOSVolumeList
*dvl
= NULL
;
533 struct DOSVolumeNode
*dvn
= NULL
;
534 char *devname
= NULL
;
535 struct List
*iconlist
= NULL
;
536 struct List newiconlist
;
537 struct Node
*tmpNode
= NULL
;
539 D(bug("[IconVolumeList]: %s()\n", __PRETTY_FUNCTION__
));
541 GET(obj
, MUIA_Family_List
, &iconlist
);
543 if (iconlist
!= NULL
)
545 NewList(&newiconlist
);
547 if ((dvl
= IconVolumeList__CreateDOSList()) != NULL
)
549 D(bug("[IconVolumeList] %s: DOSVolumeList @ %p\n",
550 __PRETTY_FUNCTION__
, dvl
));
552 ForeachNode(dvl
, dvn
)
554 D(bug("[IconVolumeList] %s: DOSVolumeNode @ %p\n",
555 __PRETTY_FUNCTION__
, dvn
));
556 if (dvn
->dvn_VolName
)
558 struct DiskObject
*volDOB
= NULL
;
560 D(bug("[IconVolumeList] %s: DOSList Entry '%s'\n",
561 __PRETTY_FUNCTION__
, dvn
->dvn_VolName
));
563 if (dvn
->dvn_Flags
& ICONENTRY_VOL_OFFLINE
)
564 devname
= dvn
->dvn_VolName
;
566 devname
= dvn
->dvn_DevName
;
568 D(bug("[IconVolumeList] %s: Processing '%s'\n",
569 __PRETTY_FUNCTION__
, devname
));
571 if ((this_Icon
= FindIconlistVolumeIcon(iconlist
, devname
, dvn
->dvn_VolName
)) != NULL
)
573 BOOL entrychanged
= FALSE
;
574 volDOB
= this_Icon
->ie_DiskObj
;
576 Remove((struct Node
*)&this_Icon
->ie_IconNode
);
579 ("[IconVolumeList] %s: Found existing IconEntry for '%s' @ %p\n",
581 this_Icon
->ie_IconListEntry
.label
,
584 /* Compare the Entry and update as needed ... */
585 if (strcmp(this_Icon
->ie_IconListEntry
.label
,
586 dvn
->dvn_VolName
) != 0)
589 if ((this_Icon
->ie_IconListEntry
.udata
) &&
590 (dvn
->dvn_Flags
!= _volpriv(this_Icon
)->vip_FLags
))
593 if ((dvn
->dvn_Flags
& ICONENTRY_VOL_DISABLED
)
598 ICONGETA_FailIfUnavailable
, FALSE
,
599 ICONGETA_GenerateImageMasks
, TRUE
,
605 D(bug("[IconVolumeList] %s: IconEntry changed - updating..\n", __PRETTY_FUNCTION__
));
607 _volpriv(this_Icon
)->vip_FLags
= dvn
->dvn_Flags
;
610 (struct IconEntry
*)DoMethod(obj
, MUIM_IconList_UpdateEntry
, this_Icon
,
611 (IPTR
) devname
, (IPTR
) dvn
->dvn_VolName
, (IPTR
) NULL
, volDOB
, ST_ROOT
);
614 AddTail(&newiconlist
,
615 (struct Node
*)&this_Icon
->ie_IconNode
);
619 struct VolumeIcon_Private
* volPrivate
= AllocMem(sizeof(struct VolumeIcon_Private
), MEMF_CLEAR
);
620 if (volPrivate
) volPrivate
->vip_FLags
= dvn
->dvn_Flags
;
622 if (dvn
->dvn_Flags
& ICONENTRY_VOL_DISABLED
)
626 ICONGETA_FailIfUnavailable
, FALSE
,
627 ICONGETA_GenerateImageMasks
, TRUE
,
631 if ((volPrivate
) && ((this_Icon
= (struct IconEntry
*)DoMethod(obj
, MUIM_IconList_CreateEntry
,
632 (IPTR
) devname
, (IPTR
) dvn
->dvn_VolName
, (IPTR
) NULL
, volDOB
,
633 ST_ROOT
, volPrivate
)) != NULL
))
636 ("[IconVolumeList] %s: Created IconEntry for '%s' @ %p\n",
638 this_Icon
->ie_IconListEntry
.label
,
641 if (!(this_Icon
->ie_Flags
&
642 ICONENTRY_FLAG_HASICON
))
643 this_Icon
->ie_Flags
|=
644 ICONENTRY_FLAG_HASICON
;
646 if ((strcasecmp(dvn
->dvn_VolName
,
650 ("[IconVolumeList] %s: Setting '%s' entry node priority to 5\n",
652 this_Icon
->ie_IconListEntry
.label
));
653 this_Icon
->ie_IconNode
.ln_Pri
= 5; // Special dirs get Priority 5
657 this_Icon
->ie_IconNode
.ln_Pri
= 2; // Fixed Media get Priority 2
659 AddTail(&newiconlist
,
660 (struct Node
*)&this_Icon
->ie_IconNode
);
665 ("[IconVolumeList] %s: Failed to Add IconEntry for '%s'\n",
668 } /* (dvn->dvn_VolName) */
670 IconVolumeList__DestroyDOSList(dvl
);
671 ForeachNodeSafe(iconlist
, this_Icon
, tmpNode
)
673 if (this_Icon
->ie_IconListEntry
.type
== ST_ROOT
)
676 ("[IconVolumeList] %s: Destroying Removed IconEntry for '%s' @ %p\n",
678 this_Icon
->ie_IconListEntry
.label
, this_Icon
));
679 Remove((struct Node
*)&this_Icon
->ie_IconNode
);
680 DoMethod(obj
, MUIM_IconList_DestroyEntry
, this_Icon
);
684 D(bug("[IconVolumeList] %s: Updating IconList\n",
685 __PRETTY_FUNCTION__
));
686 ForeachNodeSafe(&newiconlist
, this_Icon
, tmpNode
)
688 Remove((struct Node
*)&this_Icon
->ie_IconNode
);
689 DoMethod(obj
, MUIM_Family_AddTail
,
690 (struct Node
*)&this_Icon
->ie_IconNode
);
694 /* default display/sorting flags */
696 DoSuperMethodA(CLASS
, obj
, (Msg
) message
);
701 IPTR
IconVolumeList__MUIM_IconList_UpdateEntry(struct IClass
* CLASS
,
702 Object
* obj
, struct MUIP_IconList_UpdateEntry
* message
)
706 D(bug("[IconVolumeList]: %s()\n", __PRETTY_FUNCTION__
));
708 this_Icon
= DoSuperMethodA(CLASS
, obj
, (Msg
) message
);
713 IPTR
IconVolumeList__MUIM_IconList_DestroyEntry(struct IClass
* CLASS
,
714 Object
* obj
, struct MUIP_IconList_DestroyEntry
* message
)
716 struct VolumeIcon_Private
*volPrivate
= NULL
;
719 D(bug("[IconVolumeList]: %s()\n", __PRETTY_FUNCTION__
));
721 volPrivate
= message
->entry
->ie_IconListEntry
.udata
;
723 rv
= DoSuperMethodA(CLASS
, obj
, (Msg
) message
);
726 FreeMem(volPrivate
, sizeof(struct VolumeIcon_Private
));
733 /**************************************************************************
735 **************************************************************************/
736 IPTR
IconVolumeList__OM_GET(struct IClass
* CLASS
, Object
* obj
,
737 struct opGet
* message
)
739 #define STORE *(message->opg_Storage)
741 D(bug("[IconVolumeList]: %s()\n", __PRETTY_FUNCTION__
));
743 switch (message
->opg_AttrID
)
745 /* TODO: Get the version/revision from our config.. */
754 return DoSuperMethodA(CLASS
, obj
, (Msg
) message
);
760 #if WANDERER_BUILTIN_ICONVOLUMELIST
761 BOOPSI_DISPATCHER(IPTR
, IconVolumeList_Dispatcher
, CLASS
, obj
, message
)
763 #if !defined(__AROS__)
764 struct IClass
*CLASS
= cl
;
767 switch (message
->MethodID
)
770 return IconVolumeList__OM_NEW(CLASS
, obj
, (struct opSet
*)message
);
772 return IconVolumeList__OM_GET(CLASS
, obj
, (struct opGet
*)message
);
773 case MUIM_IconList_Update
:
774 return IconVolumeList__MUIM_IconList_Update(CLASS
, obj
,
775 (struct MUIP_IconList_Update
*)message
);
776 case MUIM_IconList_CreateEntry
:
777 return IconVolumeList__MUIM_IconList_CreateEntry(CLASS
, obj
,
779 case MUIM_IconList_UpdateEntry
:
780 return IconVolumeList__MUIM_IconList_UpdateEntry(CLASS
, obj
,
782 case MUIM_IconList_DestroyEntry
:
783 return IconVolumeList__MUIM_IconList_DestroyEntry(CLASS
, obj
,
787 return DoSuperMethodA(CLASS
, obj
, message
);
790 BOOPSI_DISPATCHER_END
791 #if defined(__AROS__)
792 /* Class descriptor. */
793 const struct __MUIBuiltinClass _MUI_IconVolumeList_desc
= {
796 sizeof(struct IconVolumeList_DATA
),
797 (void *)IconVolumeList_Dispatcher
801 #if !defined(__AROS__)
802 struct MUI_CustomClass
*initIconVolumeListClass(void)
804 return (struct MUI_CustomClass
*)MUI_CreateCustomClass(NULL
, NULL
,
805 IconList_Class
, sizeof(struct IconVolumeList_DATA
),
806 ENTRY(IconVolumeList_Dispatcher
));
809 #endif /* WANDERER_BUILTIN_ICONVOLUMELIST */