Fix for wanderer losing the desktop/workbench icon list after repeated updates
[AROS.git] / workbench / system / Wanderer / Classes / iconvolumelist.c
blobd7cb00e7612f0060621c34f04cee4d7ace7c1f37
1 /*
2 Copyright 2002-2008, The AROS Development Team. All rights reserved.
3 $Id$
4 */
5 #define DEBUG 0
6 #ifndef __AROS__
7 #include "../portable_macros.h"
8 #define WANDERER_BUILTIN_ICONVOLUMELIST 1
9 #else
10 #include <aros/debug.h>
11 #endif
13 #define DEBUG_ILC_EVENTS
14 #define DEBUG_ILC_KEYEVENTS
15 #define DEBUG_ILC_ICONRENDERING
16 #define DEBUG_ILC_ICONSORTING
17 #define DEBUG_ILC_ICONSORTING_DUMP
18 #define DEBUG_ILC_ICONPOSITIONING
19 #define DEBUG_ILC_LASSO
20 #define DEBUG_ILC_MEMALLOC
22 #include <string.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <math.h>
28 #include <dos/dos.h>
29 #include <dos/datetime.h>
30 #include <dos/filehandler.h>
32 #include <exec/memory.h>
33 #include <graphics/gfx.h>
34 #include <graphics/view.h>
35 #include <graphics/rpattr.h>
36 #include <workbench/icon.h>
37 #include <workbench/workbench.h>
39 #ifdef __AROS__
40 #include <devices/rawkeycodes.h>
41 #include <clib/alib_protos.h>
42 #endif
44 #include <proto/exec.h>
45 #include <proto/graphics.h>
46 #include <proto/utility.h>
47 #include <proto/dos.h>
48 #include <proto/icon.h>
49 #include <proto/layers.h>
50 #include <proto/dos.h>
51 #include <proto/iffparse.h>
53 #ifdef __AROS__
54 #include <prefs/prefhdr.h>
55 #include <prefs/wanderer.h>
56 #else
57 #include <prefs_AROS/prefhdr.h>
58 #include <prefs_AROS/wanderer.h>
59 #endif
61 #include <proto/cybergraphics.h>
63 #ifdef __AROS__
64 #include <cybergraphx/cybergraphics.h>
65 #else
66 #include <cybergraphx_AROS/cybergraphics.h>
67 #endif
70 #if defined(__AMIGA__) && !defined(__PPC__)
71 #define NO_INLINE_STDARG
72 #endif
73 #include <proto/intuition.h>
74 #include <proto/muimaster.h>
75 #include <libraries/mui.h>
76 //#include "muimaster_intern.h"
77 //#include "support.h"
78 //#include "imspec.h"
79 #include "iconlist_attributes.h"
80 //#include "icon_attributes.h"
81 #include "iconlist.h"
82 #include "iconvolumelist_private.h"
84 #ifndef __AROS__
85 #define DEBUG 1
87 #ifdef DEBUG
88 #define D(x) if (DEBUG) x
89 #ifdef __amigaos4__
90 #define bug DebugPrintF
91 #else
92 #define bug kprintf
93 #endif
94 #else
95 #define D(...)
96 #endif
97 #endif
99 #define __DL_UNIT dl->dol_Ext.dol_AROS.dol_Unit
101 extern struct Library *MUIMasterBase;
103 /* sba: taken from SimpleFind3 */
105 struct NewDosList
107 struct List list;
108 APTR pool;
111 struct NewDOSVolumeNode
113 struct Node node;
114 STRPTR vn_VolName;
115 STRPTR vn_DevName;
116 ULONG vn_FLags;
117 struct Device *device;
118 struct Unit *unit;
119 struct MsgPort *port;
122 ///IconVolumeList__CreateDOSList()
123 static struct NewDosList *IconVolumeList__CreateDOSList(void)
125 APTR pool = CreatePool(MEMF_PUBLIC | MEMF_CLEAR,4096,4096);
127 D(bug("[IconVolList]: %s()\n", __PRETTY_FUNCTION__));
129 if (pool)
131 struct NewDosList *ndl = (struct NewDosList*)AllocPooled(pool, sizeof(struct NewDosList));
132 if (ndl)
134 struct DosList *dl = NULL;
136 NewList((struct List*)ndl);
137 ndl->pool = pool;
139 dl = LockDosList(LDF_VOLUMES|LDF_READ);
140 while(( dl = NextDosEntry(dl, LDF_VOLUMES)))
142 STRPTR vn_VolName;
144 UBYTE *dosname = (UBYTE*)AROS_BSTR_ADDR(dl->dol_Name);
145 LONG len = AROS_BSTR_strlen(dl->dol_Name);
147 if ((vn_VolName = (STRPTR)AllocPooled(pool, len + 2)))
149 struct NewDOSVolumeNode *ndn = NULL;
151 vn_VolName[len] = ':';
152 vn_VolName[len + 1] = 0;
153 strncpy(vn_VolName, dosname, len);
155 if ((ndn = (struct NewDOSVolumeNode*)AllocPooled(pool, sizeof(*ndn))))
157 ndn->vn_VolName = vn_VolName;
158 ndn->unit = __DL_UNIT;
159 D(bug("[IconVolList] %s: Registering Volume '%s' @ %p (Device '%s' @ 0x%p, Unit @ 0x%p) Type: %d\n", __PRETTY_FUNCTION__, ndn->vn_VolName, dl, dl->dol_Ext.dol_AROS.dol_Device->dd_Library.lib_Node.ln_Name, dl->dol_Ext.dol_AROS.dol_Device, ndn->unit, dl->dol_Type));
160 if (dl->dol_misc.dol_handler.dol_Startup)
162 struct FileSysStartupMsg *thisfs_SM = dl->dol_misc.dol_handler.dol_Startup;
163 D(bug("[IconVolList] %s: Startup msg @ 0x%p\n", __PRETTY_FUNCTION__, thisfs_SM));
164 D(bug("[IconVolList] %s: Startup Device @ %p, Unit %d\n", __PRETTY_FUNCTION__, thisfs_SM->fssm_Device, thisfs_SM->fssm_Unit));
167 if (dl->dol_Task != NULL)
169 ndn->port = dl->dol_Task;
170 D(bug("[IconVolList] %s: Packet Style device\n", __PRETTY_FUNCTION__));
172 #if defined(__AROS__)
173 else if (dl->dol_Ext.dol_AROS.dol_Device != NULL)
175 D(bug("[IconVolList] %s: IOFS Style device\n", __PRETTY_FUNCTION__));
176 ndn->port = dl->dol_Ext.dol_AROS.dol_Device;
178 #endif
179 else
181 D(bug("[IconVolList] %s: Unknown device type\n", __PRETTY_FUNCTION__));
183 AddTail((struct List*)ndl, (struct Node*)ndn);
187 UnLockDosList(LDF_VOLUMES|LDF_READ);
189 dl = LockDosList(LDF_DEVICES|LDF_READ);
190 while(( dl = NextDosEntry(dl, LDF_DEVICES)))
192 struct NewDOSVolumeNode *ndn = NULL;
193 char *nd_nambuf = NULL;
194 BPTR nd_lock = (BPTR)NULL;
195 struct InfoData *nd_paramblock = NULL;
197 UBYTE *dosname = (UBYTE*)AROS_BSTR_ADDR(dl->dol_Name);
198 LONG len = AROS_BSTR_strlen(dl->dol_Name);
200 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));
201 #if defined(__AROS__)
202 if ((dl->dol_Task == NULL) && (dl->dol_Ext.dol_AROS.dol_Device != NULL))
204 D(bug("[IconVolList] %s: '%s' : IOFS Device\n", __PRETTY_FUNCTION__, dosname));
206 else
207 #endif
208 if (dl->dol_Task == NULL)
210 D(bug("[IconVolList] %s: '%s' : dol_Task == NULL!\n", __PRETTY_FUNCTION__, dosname));
211 continue;
213 else
215 D(bug("[IconVolList] %s: '%s' : Packet Device\n", __PRETTY_FUNCTION__, dosname));
218 if ((nd_nambuf = AllocPooled(pool, len + 2)) != NULL)
220 strncpy(nd_nambuf, dosname, len);
221 nd_nambuf[len] = ':';
222 nd_nambuf[len + 1] = 0;
223 ////sprintf(nd_nambuf, "%s:", dosname);
225 nd_lock = NULL;
226 nd_paramblock = NULL;
228 D(bug("[IconVolList] %s: '%s' : Checking for Attached Volumes ... \n", __PRETTY_FUNCTION__, dosname));
229 /* Find the Volume attached to this device */
230 BOOL found = FALSE;
231 ndn = (struct NewDOSVolumeNode*)GetHead(ndl);
232 while ((ndn))
234 if ((ndn->port != NULL) &&
236 (ndn->port == dl->dol_Task)
237 #if defined(__AROS__)
238 || (ndn->port == dl->dol_Ext.dol_AROS.dol_Device)
239 #endif
242 if (ndn->unit)
244 if (nd_lock == NULL)
246 D(bug("[IconVolList] %s: '%s' : Attempting to Lock() device ... \n", __PRETTY_FUNCTION__, dosname));
247 if ((nd_lock = Lock(nd_nambuf, SHARED_LOCK)) == NULL)
249 D(bug("[IconVolList] %s: '%s' : Failed to obtain Lock()\n", __PRETTY_FUNCTION__, dosname));
252 if ((nd_lock) && (nd_paramblock == NULL))
254 if ((nd_paramblock = AllocMem(sizeof(struct InfoData), MEMF_CLEAR|MEMF_PUBLIC)) == NULL)
256 D(bug("[IconVolList] %s: '%s' : Failed to allocate storage for device paramblock\n", __PRETTY_FUNCTION__, dosname));
257 UnLock(nd_lock);
259 D(bug("[IconVolList] %s: Getting Info for '%s'\n", __PRETTY_FUNCTION__, nd_nambuf));
260 Info(nd_lock, nd_paramblock);
262 if (ndn->unit == __DL_UNIT)
264 if ((nd_paramblock) && (nd_paramblock->id_DiskType != ID_NO_DISK_PRESENT))
266 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)));
268 STRPTR nd_namext;
269 int nd_namext_len;
271 found = TRUE;
273 if (nd_paramblock->id_DiskState == ID_VALIDATING)
275 D(bug("[IconVolList] %s: '%s' : Validating\n", __PRETTY_FUNCTION__, nd_nambuf));
276 nd_namext = "BUSY";
277 nd_namext_len = 4;
279 else
281 if (nd_paramblock->id_DiskState == ID_WRITE_PROTECTED)
283 ndn->vn_FLags |= ICONENTRY_VOL_READONLY;
284 D(bug("[IconVolList] %s: '%s' : Volume is WRITE-PROTECTED\n", __PRETTY_FUNCTION__, nd_nambuf));
287 switch (nd_paramblock->id_DiskType)
290 case ID_UNREADABLE_DISK:
291 nd_namext = "BAD";
292 nd_namext_len = 3;
293 break;
294 case ID_NOT_REALLY_DOS:
295 nd_namext = "NDOS";
296 nd_namext_len = 4;
297 break;
298 case ID_KICKSTART_DISK:
299 nd_namext = "KICK";
300 nd_namext_len = 4;
301 break;
302 default:
303 /* A filesystem type.. ie ID_DOS_DISK */
304 nd_namext_len = 0;
305 break;
309 if (nd_namext_len > 0)
311 char *newVolName = NULL;
312 newVolName = AllocPooled(pool, strlen(ndn->vn_VolName) + nd_namext_len + 2);
313 sprintf(newVolName, "%s%s", ndn->vn_VolName, nd_namext);
314 ndn->vn_VolName = newVolName;
317 else
319 D(bug("[IconVolList] %s: '%s' : No Media Inserted (error state?)\n", __PRETTY_FUNCTION__, nd_nambuf));
321 ndn->vn_DevName = nd_nambuf;
322 D(bug("[IconVolList] %s: DeviceName set to '%s' for '%s'\n", __PRETTY_FUNCTION__, ndn->vn_DevName, ndn->vn_VolName));
324 else
326 D(bug("[IconVolList] %s: '%s' : Volume not attached to this device .. skipping\n", __PRETTY_FUNCTION__, nd_nambuf));
329 else
331 D(bug("[IconVolList] %s: '%s' : Volume '%s' is OFFLINE\n", __PRETTY_FUNCTION__, nd_nambuf, ndn->vn_VolName));
332 ndn->vn_FLags |= ICONENTRY_VOL_OFFLINE;
335 ndn = (struct NewDOSVolumeNode*)GetSucc(ndn);
336 } /* ndn */
338 if (!(found))
340 D(bug("[IconVolList] %s: '%s' : Couldnt find an associated Volume\n", __PRETTY_FUNCTION__, nd_nambuf));
343 if (nd_paramblock)
344 FreeMem(nd_paramblock, sizeof(struct InfoData));
345 if (nd_lock)
346 UnLock(nd_lock);
349 UnLockDosList(LDF_DEVICES|LDF_READ);
351 return ndl;
353 DeletePool(pool);
355 return NULL;
359 ///IconVolumeList__DestroyDOSList()
360 static void IconVolumeList__DestroyDOSList(struct NewDosList *ndl)
362 D(bug("[IconVolList]: %s()\n", __PRETTY_FUNCTION__));
363 if (ndl && ndl->pool) DeletePool(ndl->pool);
366 /* sba: End SimpleFind3 */
368 ///OM_NEW()
369 /**************************************************************************
370 OM_NEW
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,
376 // *tags = NULL;
378 D(bug("[IconVolList]: %s()\n", __PRETTY_FUNCTION__));
380 obj = (Object *)DoSuperNewTags(CLASS, obj, NULL,
381 TAG_MORE, (IPTR) message->ops_AttrList);
383 if (!obj) return FALSE;
385 data = INST_DATA(CLASS, obj);
387 SET(obj, MUIA_IconList_DisplayFlags, ICONLIST_DISP_VERTICAL);
388 SET(obj, MUIA_IconList_SortFlags, ICONLIST_SORT_MASK);
390 D(bug("[IconVolList] obj = %ld\n", obj));
391 return (IPTR)obj;
395 ///MUIM_IconList_Update()
396 /**************************************************************************
397 MUIM_IconList_Update
398 **************************************************************************/
399 IPTR IconVolumeList__MUIM_IconList_Update(struct IClass *CLASS, Object *obj, struct MUIP_IconList_Update *message)
401 //struct IconVolumeList_DATA *data = INST_DATA(CLASS, obj);
402 struct IconEntry *this_Icon = NULL;
403 struct NewDosList *ndl = NULL;
404 struct Process *me;
405 APTR oldwin;
406 char *devname = NULL;
408 D(bug("[IconVolList]: %s()\n", __PRETTY_FUNCTION__));
410 DoSuperMethodA(CLASS, obj, (Msg) message);
412 DoMethod(obj, MUIM_IconList_Clear);
414 if ((ndl = IconVolumeList__CreateDOSList()) != NULL)
416 struct NewDOSVolumeNode *nd = NULL;
418 D(bug("[IconVolList] %s: DOSList @ %p\n", __PRETTY_FUNCTION__, ndl));
419 #ifdef __AROS__
420 ForeachNode(ndl, nd)
421 #else
422 Foreach_Node(ndl, nd);
423 #endif
425 D(bug("[IconVolList] %s: DOSList Node @ %p\n", __PRETTY_FUNCTION__, nd));
426 if (nd->vn_VolName)
428 D(bug("[IconVolList] %s: Adding icon for '%s'\n", __PRETTY_FUNCTION__, nd->vn_VolName));
430 if (nd->vn_FLags & ICONENTRY_VOL_OFFLINE)
431 devname = nd->vn_VolName;
432 else
433 devname = nd->vn_DevName;
435 if ((this_Icon = (struct IconEntry *)DoMethod(obj, MUIM_IconList_CreateEntry, (IPTR)devname, (IPTR)nd->vn_VolName, (IPTR)NULL, (IPTR)NULL, ST_ROOT)) == NULL)
437 D(bug("[IconVolList] %s: Failed to Add IconEntry for '%s'\n", __PRETTY_FUNCTION__, nd->vn_VolName));
439 else
441 if (!(this_Icon->ile_Flags & ICONENTRY_FLAG_HASICON))
442 this_Icon->ile_Flags |= ICONENTRY_FLAG_HASICON;
444 if ((strcasecmp(nd->vn_VolName, "Ram Disk:")) == 0)
446 D(bug("[IconVolList] %s: Setting Ram Disk's icon node priority to 5\n", __PRETTY_FUNCTION__));
447 this_Icon->ile_IconNode.ln_Pri = 5; // Special dirs get Priority 5
449 else
451 this_Icon->ile_IconNode.ln_Pri = 1; // Fixed Media get Priority 1
454 } /* (nd->vn_VolName) */
456 IconVolumeList__DestroyDOSList(ndl);
459 /* default display/sorting flags */
460 DoMethod(obj, MUIM_IconList_Sort);
462 return 1;
466 #if WANDERER_BUILTIN_ICONVOLUMELIST
467 BOOPSI_DISPATCHER(IPTR, IconVolumeList_Dispatcher, CLASS, obj, message)
469 #if !defined(__AROS__)
470 struct IClass *CLASS = cl;
471 Msg message = msg;
472 #endif
473 switch (message->MethodID)
475 case OM_NEW: return IconVolumeList__OM_NEW(CLASS, obj, (struct opSet *)message);
476 case MUIM_IconList_Update: return IconVolumeList__MUIM_IconList_Update(CLASS,obj,(APTR)message);
479 return DoSuperMethodA(CLASS, obj, message);
481 BOOPSI_DISPATCHER_END
483 #if defined(__AROS__)
484 /* Class descriptor. */
485 const struct __MUIBuiltinClass _MUI_IconVolumeList_desc = {
486 MUIC_IconVolumeList,
487 MUIC_IconList,
488 sizeof(struct IconVolumeList_DATA),
489 (void*)IconVolumeList_Dispatcher
491 #endif
492 #else
493 #if !defined(__AROS__)
494 struct MUI_CustomClass *initIconVolumeListClass(void)
496 return (struct MUI_CustomClass *) MUI_CreateCustomClass(NULL, NULL, IconList_Class, sizeof(struct IconVolumeList_DATA), ENTRY(IconVolumeList_Dispatcher));
498 #endif
499 #endif /* WANDERER_BUILTIN_ICONVOLUMELIST */