WIP: Update implementing basic changes for icon class, and Fix to memory size display...
[AROS.git] / workbench / system / Wanderer / Classes / iconvolumelist.c
blob902ba1ea5de203e05604a99cc995d7884010551c
1 /*
2 Copyright 2002-2009, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #ifndef __AROS__
7 #include "../portable_macros.h"
8 #define WANDERER_BUILTIN_ICONVOLUMELIST 1
9 #else
10 #define DEBUG 0
11 #include <aros/debug.h>
12 #endif
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
23 #include <string.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <math.h>
29 #include <dos/dos.h>
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>
40 #ifdef __AROS__
41 #include <devices/rawkeycodes.h>
42 #include <clib/alib_protos.h>
43 #endif
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>
54 #ifdef __AROS__
55 #include <prefs/prefhdr.h>
56 #include <prefs/wanderer.h>
57 #else
58 #include <prefs_AROS/prefhdr.h>
59 #include <prefs_AROS/wanderer.h>
60 #endif
62 #include <proto/cybergraphics.h>
64 #ifdef __AROS__
65 #include <cybergraphx/cybergraphics.h>
66 #else
67 #include <cybergraphx_AROS/cybergraphics.h>
68 #endif
71 #if defined(__AMIGA__) && !defined(__PPC__)
72 #define NO_INLINE_STDARG
73 #endif
74 #include <proto/intuition.h>
75 #include <proto/muimaster.h>
76 #include <libraries/mui.h>
77 //#include "muimaster_intern.h"
78 //#include "support.h"
79 //#include "imspec.h"
80 #include "iconlist_attributes.h"
81 #include "icon_attributes.h"
82 #include "iconlist.h"
83 #include "iconvolumelist_private.h"
85 #ifndef __AROS__
86 #define DEBUG 1
88 #ifdef DEBUG
89 #define D(x) if (DEBUG) x
90 #ifdef __amigaos4__
91 #define bug DebugPrintF
92 #else
93 #define bug kprintf
94 #endif
95 #else
96 #define D(...)
97 #endif
98 #endif
100 #define __DL_UNIT dl->dol_Ext.dol_AROS.dol_Unit
102 extern struct Library *MUIMasterBase;
104 struct DOSVolumeList
106 struct List dvl_List;
107 APTR dvl_Pool;
110 struct DOSVolumeNode
112 struct Node dvn_Node;
113 STRPTR dvn_VolName;
114 STRPTR dvn_DevName;
115 ULONG dvn_FLags;
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__));
128 if (pool)
130 struct DOSVolumeList *newdvl = (struct DOSVolumeList*)AllocPooled(pool, sizeof(struct DOSVolumeList));
131 if (newdvl)
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)))
141 STRPTR vn_VolName;
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;
177 #endif
178 else
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));
205 else
206 #endif
207 if (dl->dol_Task == NULL)
209 D(bug("[IconVolList] %s: '%s' : dol_Task == NULL!\n", __PRETTY_FUNCTION__, dosname));
210 continue;
212 else
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);
224 nd_lock = NULL;
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 */
229 BOOL found = FALSE;
230 dvn = (struct DOSVolumeNode*)GetHead(newdvl);
231 while ((dvn))
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)
238 #endif
241 if (dvn->dvn_Unit)
243 if (nd_lock == NULL)
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));
256 UnLock(nd_lock);
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)));
267 STRPTR nd_namext;
268 int nd_namext_len;
270 found = TRUE;
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));
276 nd_namext = "BUSY";
277 nd_namext_len = 4;
279 else
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:
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(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;
317 else
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));
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, dvn->dvn_VolName));
332 dvn->dvn_FLags |= ICONENTRY_VOL_OFFLINE;
335 dvn = (struct DOSVolumeNode*)GetSucc(dvn);
336 } /* dvn */
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 newdvl;
353 DeletePool(pool);
355 return NULL;
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 */
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)
384 return FALSE;
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));
392 return (IPTR)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))
404 return foundEntry;
406 return NULL;
409 ///MUIM_IconList_Update()
410 /**************************************************************************
411 MUIM_IconList_Update
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));
438 #ifdef __AROS__
439 ForeachNode(dvl, dvn)
440 #else
441 Foreach_Node(dvl, dvn);
442 #endif
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;
451 else
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
476 else
478 this_Icon->ile_IconNode.ln_Pri = 1; // Fixed Media get Priority 1
480 AddTail(&newiconlist, (struct Node*)&this_Icon->ile_IconNode);
482 else
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);
506 return 1;
510 #if WANDERER_BUILTIN_ICONVOLUMELIST
511 BOOPSI_DISPATCHER(IPTR, IconVolumeList_Dispatcher, CLASS, obj, message)
513 #if !defined(__AROS__)
514 struct IClass *CLASS = cl;
515 Msg message = msg;
516 #endif
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 = {
530 MUIC_IconVolumeList,
531 MUIC_IconList,
532 sizeof(struct IconVolumeList_DATA),
533 (void*)IconVolumeList_Dispatcher
535 #endif
536 #else
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));
542 #endif
543 #endif /* WANDERER_BUILTIN_ICONVOLUMELIST */