Fix typo causing incorrect desktop sorting
[AROS.git] / workbench / system / Wanderer / panel_statusbar.c
blob46664d000b8a2afd7439f42a91f4ab44e733db5a
1 /*
2 Copyright 2004-2010, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include "portable_macros.h"
7 #ifdef __AROS__
8 #define MUIMASTER_YES_INLINE_STDARG
9 #endif
11 #ifdef __AROS__
12 #define DEBUG 0
13 #include <aros/debug.h>
14 #endif
16 #include <exec/types.h>
17 #include <libraries/mui.h>
19 #ifdef __AROS__
20 #include <zune/customclasses.h>
21 #else
22 #include <zune_AROS/customclasses.h>
23 #endif
25 #include <proto/utility.h>
27 #include <proto/graphics.h>
29 #include <proto/exec.h>
30 #include <proto/datatypes.h>
32 #include <dos/dos.h>
33 #include <proto/dos.h>
35 #include <proto/icon.h>
37 #include <stdio.h>
38 #include <string.h>
40 #include <intuition/screens.h>
41 #include <datatypes/pictureclass.h>
42 #include <clib/macros.h>
44 #ifdef __AROS__
45 #include <clib/alib_protos.h>
47 #include <prefs/wanderer.h>
48 #else
49 #include <prefs_AROS/wanderer.h>
50 #endif
52 #if defined(__AMIGA__) && !defined(__PPC__)
53 #define NO_INLINE_STDARG
54 #endif
55 #ifndef _PROTO_INTUITION_H
56 #include <proto/intuition.h>
57 #endif
58 #include <proto/muimaster.h>
60 #include "Classes/iconlist.h"
61 #include "Classes/iconlistview.h"
62 #include "Classes/iconlist_attributes.h"
63 #include "Classes/icon_attributes.h"
64 #include "wanderer.h"
65 #include "wandererprefs.h"
67 #include "iconwindow.h"
68 #include "iconwindow_attributes.h"
70 extern struct List iconwindow_Extensions;
72 /*** Private Data *********************************************************/
74 static CONST_STRPTR extension_Name = "IconWindow StatusBar Extension";
75 static CONST_STRPTR extension_PrefsFile = "ENV:SYS/Wanderer/statusbar.prefs";
76 static STRPTR extension_PrefsData;
77 static struct iconWindow_Extension panelStatusBar__Extension;
78 static struct List panelStatusBar__StatusBars;
79 static struct NotifyRequest panelStatusBar__PrefsNotifyRequest;
80 static Object *panelStatusBar__PrefsNotificationObject;
82 struct panel_StatusBar_DATA
84 struct Node iwp_Node;
85 IPTR iwp_Flags;
86 Object *iwp_StatusBar_StatusBarObj;
87 Object *iwp_StatusBar_StatusTextObj;
88 #ifdef __AROS__
89 struct Hook iwp_StatusBar_updateHook;
90 #else
91 struct Hook *iwp_StatusBar_updateHook;
92 #endif
95 ///ExpandEnvName()
96 /* Expand a passed in env: string to its full location */
97 /* Wanderer doesnt free this mem at the moment but should
98 incase it is every closed */
99 static STRPTR ExpandEnvName(STRPTR env_path)
101 BOOL ok = FALSE;
102 char tmp_envbuff[1024];
103 STRPTR fullpath = NULL;
104 BPTR env_lock = (BPTR) NULL;
106 env_lock = Lock("ENV:", SHARED_LOCK);
107 if (env_lock)
109 if (NameFromLock(env_lock, tmp_envbuff, 256)) ok = TRUE;
110 UnLock(env_lock);
113 if (ok)
115 if ((fullpath = AllocVec(strlen(tmp_envbuff) + strlen(env_path) + 1 + 1 - 4, MEMF_CLEAR | MEMF_PUBLIC)) != NULL)
117 strcpy(fullpath, tmp_envbuff);
118 AddPart(fullpath, env_path + 4, 1019);
119 return fullpath;
123 //We couldnt expand it so just use as is ..
124 return env_path;
128 const UBYTE MSG_MEM_G[] = "GB";
129 const UBYTE MSG_MEM_M[] = "MB";
130 const UBYTE MSG_MEM_K[] = "KB";
131 const UBYTE MSG_MEM_B[] = "Bytes";
133 ///FmtSizeToString()
134 static void FmtSizeToString(UBYTE *buf, ULONG num)
136 UQUAD d;
137 UBYTE *ch;
138 struct
140 IPTR val;
141 IPTR dec;
142 } array =
144 num,
148 if (num >= 1073741824)
150 //Gigabytes
151 array.val = num >> 30;
152 d = ((UQUAD)num * 10 + 536870912) / 1073741824;
153 array.dec = d % 10;
154 ch = MSG_MEM_G;
156 else if (num >= 1048576)
158 //Megabytes
159 array.val = num >> 20;
160 d = ((UQUAD)num * 10 + 524288) / 1048576;
161 array.dec = d % 10;
162 ch = MSG_MEM_M;
164 else if (num >= 1024)
166 //Kilobytes
167 array.val = num >> 10;
168 d = (num * 10 + 512) / 1024;
169 array.dec = d % 10;
170 ch = MSG_MEM_K;
172 else
174 //Bytes
175 array.val = num;
176 array.dec = 0;
177 d = 0;
178 ch = MSG_MEM_B;
181 if (!array.dec && (d > array.val * 10))
183 array.val++;
186 RawDoFmt(array.dec ? "%lu.%lu" : "%lu", &array, NULL, buf);
188 while (*buf)
190 buf++;
193 sprintf(buf, " %s", ch);
197 /*** Hook functions *********************************************************/
198 static
199 ///panelStatusBar__HookFunc_UpdateStatusFunc()
200 #ifdef __AROS__
201 AROS_UFH3(
202 void, panelStatusBar__HookFunc_UpdateStatusFunc,
203 AROS_UFHA(struct Hook *, hook, A0),
204 AROS_UFHA(APTR *, obj, A2),
205 AROS_UFHA(APTR, param, A1)
208 #else
209 HOOKPROTO(panelStatusBar__HookFunc_UpdateStatusFunc, void, APTR *obj, APTR param)
211 #endif
212 AROS_USERFUNC_INIT
214 /* Get data */
215 Object *self = ( Object *)obj;
216 Class *CLASS = *( Class **)param;
217 struct panel_StatusBar_DATA *panelStatusBarPrivate = NULL;
219 SETUP_ICONWINDOW_INST_DATA;
221 D(bug("[IW.statusbar]: %s()\n", __PRETTY_FUNCTION__));
223 /* Only change dir if it is a valid directory/volume */
224 if ((panelStatusBarPrivate = (struct panel_StatusBar_DATA *)data->iwd_BottomPanel.iwp_PanelPrivate) != NULL)
226 if (panelStatusBarPrivate->iwp_Node.ln_Name != extension_Name)
227 return;
229 struct List *iconList = NULL;
230 struct IconEntry *icon = NULL;
231 UBYTE status_str[1024];
232 UBYTE size_str[256];
234 int files = 0, dirs = 0, hidden = 0;
235 ULONG size = 0;
237 GET(data->iwd_IconListObj, MUIA_Family_List, &iconList);
238 if (iconList)
240 ForeachNode(iconList, icon)
242 if (icon->ie_Flags & ICONENTRY_FLAG_VISIBLE)
244 if (icon->ie_IconListEntry.type == ST_USERDIR)
246 dirs += 1;
248 else
250 files += 1;
251 if (icon->ie_FileInfoBlock)
253 size += icon->ie_FileInfoBlock->fib_Size;
254 D(bug("[IW.statusbar] %s: '%s' FIB Size = %d bytes\n", __PRETTY_FUNCTION__, icon->ie_IconNode.ln_Name, icon->ie_FileInfoBlock->fib_Size));
258 else
260 hidden += 1;
264 int previous = 0;
265 if (files > 0)
267 FmtSizeToString(size_str, size);
268 sprintf(status_str, " %s in %d files", size_str, files);
269 previous = strlen(status_str);
271 if (dirs > 0)
273 sprintf(status_str + previous, "%s%d drawers", (previous > 0) ? ", " : " " , dirs);
274 previous = strlen(status_str);
276 if (hidden > 0)
278 sprintf(status_str + previous, " (%d hidden)", hidden);
279 previous = strlen(status_str);
282 if (previous > 0)
284 SET(panelStatusBarPrivate->iwp_StatusBar_StatusTextObj, MUIA_Text_Contents, (IPTR)status_str);
286 else
288 SET(panelStatusBarPrivate->iwp_StatusBar_StatusTextObj, MUIA_Text_Contents, (IPTR)"");
292 AROS_USERFUNC_EXIT
294 #ifndef __AROS__
295 MakeStaticHook(StatusBar_updateHook, panelStatusBar__HookFunc_UpdateStatusFunc);
296 #endif
298 /*** Main Functions ****************************************************************/
300 #define STATUSBAR_PREFSSIZE 1024
301 static IPTR panelStatusBar__HandleFSUpdate(Object *WandererObj, struct NotifyMessage *msg)
303 if (GetVar(extension_PrefsFile, extension_PrefsData, STATUSBAR_PREFSSIZE, GVF_GLOBAL_ONLY) != -1)
305 D(bug("[IW.statusbar] %s: Prefs contain '%s'\n", __PRETTY_FUNCTION__, extension_PrefsData));
306 if ((strcasecmp(extension_PrefsData, "True")) == 0)
308 SET(panelStatusBar__PrefsNotificationObject, MUIA_ShowMe, TRUE);
310 else
312 SET(panelStatusBar__PrefsNotificationObject, MUIA_ShowMe, FALSE);
315 return NULL;
318 ///panelStatusBar__PrefsSetup()
319 static IPTR panelStatusBar__PrefsSetup(Class *CLASS, Object *self, struct opSet *message)
321 IPTR panelStatusBarFSNotifyPort = 0;
322 struct panel_StatusBar_DATA *panelStatusBarPrivate = NULL;
323 struct List *panelStatusBarFSNotifyList = NULL;
325 SETUP_ICONWINDOW_INST_DATA;
327 panelStatusBarFSNotifyPort = GetTagData(MUIA_Wanderer_FileSysNotifyPort, (IPTR) NULL, message->ops_AttrList);
328 panelStatusBarFSNotifyList = GetTagData(MUIA_Wanderer_FileSysNotifyList, (IPTR) NULL, message->ops_AttrList);
330 D(bug("[IW.statusbar]: %s()\n", __PRETTY_FUNCTION__));
332 if ((panelStatusBarPrivate = (struct panel_StatusBar_DATA *)data->iwd_BottomPanel.iwp_PanelPrivate) != (IPTR)NULL)
334 if (panelStatusBarPrivate->iwp_Node.ln_Name != extension_Name)
335 return NULL;
337 extension_PrefsData = AllocVec(STATUSBAR_PREFSSIZE, MEMF_CLEAR);
339 /* Setup notification on prefs file --------------------------------*/
340 struct Wanderer_FSHandler *_prefsNotifyHandler = NULL;
342 if ((_prefsNotifyHandler = AllocMem(sizeof(struct Wanderer_FSHandler), MEMF_CLEAR)) != NULL)
344 _prefsNotifyHandler->fshn_Node.ln_Name = ExpandEnvName(extension_PrefsFile);
345 panelStatusBar__PrefsNotifyRequest.nr_Name = _prefsNotifyHandler->fshn_Node.ln_Name;
346 panelStatusBar__PrefsNotifyRequest.nr_Flags = NRF_SEND_MESSAGE;
347 panelStatusBar__PrefsNotifyRequest.nr_stuff.nr_Msg.nr_Port = panelStatusBarFSNotifyPort;
348 _prefsNotifyHandler->HandleFSUpdate = panelStatusBar__HandleFSUpdate;
350 if (StartNotify(&panelStatusBar__PrefsNotifyRequest))
352 D(bug("[IW.statusbar]%s: Prefs-notification setup on '%s'\n", __PRETTY_FUNCTION__, panelStatusBar__PrefsNotifyRequest.nr_Name));
354 else
356 D(bug("[IW.statusbar] %s: FAILED to setup Prefs-notification!\n", __PRETTY_FUNCTION__));
358 AddTail(panelStatusBarFSNotifyList, &_prefsNotifyHandler->fshn_Node);
360 #ifdef __AROS__
361 panelStatusBar__PrefsNotificationObject = (Object *)NotifyObject, End;
362 #else
363 panelStatusBar__PrefsNotificationObject = MUI_NewObject(MUIC_Notify, TAG_DONE);
364 #endif
365 if (GetVar(extension_PrefsFile, extension_PrefsData, STATUSBAR_PREFSSIZE, GVF_GLOBAL_ONLY) != -1)
367 D(bug("[IW.statusbar] %s: Prefs contain '%s'\n", __PRETTY_FUNCTION__, extension_PrefsData));
373 ///panelStatusBar__Setup()
374 static IPTR panelStatusBar__Setup(Class *CLASS, Object *self, struct opSet *message)
376 SETUP_ICONWINDOW_INST_DATA;
378 Object *panel_StatusBar = NULL,
379 *panelStatusBar_TextStatus = NULL;
381 struct panel_StatusBar_DATA *panelStatusBarPrivate = NULL;
383 if (!(!(data->iwd_Flags & IWDFLAG_ISROOT) && data->iwd_BottomPanel.iwp_PanelContainerObj))
384 return NULL;
386 D(bug("[IW.statusbar]: %s()\n", __PRETTY_FUNCTION__));
388 if (data->iwd_BottomPanel.iwp_PanelPrivate == NULL)
390 if ((data->iwd_BottomPanel.iwp_PanelPrivate = AllocVec(sizeof(struct panel_StatusBar_DATA), MEMF_CLEAR)) == NULL)
391 return;
393 panelStatusBarPrivate = (struct panel_StatusBar_DATA *)data->iwd_BottomPanel.iwp_PanelPrivate;
394 panelStatusBarPrivate->iwp_Node.ln_Name = extension_Name;
396 /* Create the "StatusBar" panel object .. */
397 panel_StatusBar = MUI_NewObject(MUIC_Group,
398 MUIA_InnerLeft,(0),
399 MUIA_InnerRight,(0),
400 MUIA_InnerTop,(0),
401 MUIA_InnerBottom,(0),
402 MUIA_Frame, MUIV_Frame_None,
403 Child, (IPTR)MUI_NewObject(MUIC_Group, MUIA_Group_Horiz, TRUE ,
404 MUIA_InnerLeft,(0),
405 MUIA_InnerRight,(0),
406 MUIA_InnerTop,(0),
407 MUIA_InnerBottom,(0),
408 MUIA_Group_Spacing, 0,
409 MUIA_FixHeight, 1,
410 MUIA_Frame, MUIV_Frame_None,
411 MUIA_Background, MUII_SHADOW,
412 Child, (IPTR)MUI_NewObject(MUIC_Rectangle,
413 MUIA_Frame, MUIV_Frame_None,
414 TAG_DONE),
415 TAG_DONE),
416 Child, (IPTR)MUI_NewObject(MUIC_Group, MUIA_Group_Horiz, TRUE ,
417 MUIA_InnerLeft,(4),
418 MUIA_InnerRight,(4),
419 MUIA_InnerTop,(4),
420 MUIA_InnerBottom,(4),
421 MUIA_Frame, MUIV_Frame_None,
422 MUIA_Weight, 100,
423 Child, (IPTR)MUI_NewObject(MUIC_Group, MUIA_Group_Horiz, TRUE ,
424 MUIA_InnerLeft,(0),
425 MUIA_InnerRight,(0),
426 MUIA_InnerTop,(0),
427 MUIA_InnerBottom,(0),
428 MUIA_Weight, 100,
429 Child, (IPTR)( panelStatusBar_TextStatus = MUI_NewObject(MUIC_Text,
430 MUIA_Font, MUIV_Font_Tiny,
431 MUIA_Text_Contents, (IPTR)"",
432 TAG_DONE) ),
433 TAG_DONE),
434 TAG_DONE),
435 TAG_DONE);
437 /* Got a StatusBarPanel? setup notifies and other values are
438 copied to the data of the object */
439 if ( panel_StatusBar != NULL )
441 D(bug("[IW.statusbar] %s: StatusBar Obj @ 0x%p\n", __PRETTY_FUNCTION__, panel_StatusBar));
443 panelStatusBarPrivate->iwp_StatusBar_StatusTextObj = panelStatusBar_TextStatus;
444 panelStatusBarPrivate->iwp_StatusBar_StatusBarObj = panel_StatusBar;
446 if (DoMethod(data->iwd_BottomPanel.iwp_PanelGroupObj, MUIM_Group_InitChange ))
448 DoMethod(data->iwd_BottomPanel.iwp_PanelGroupObj, OM_ADDMEMBER, (IPTR)panel_StatusBar);
449 if (data->iwd_BottomPanel.iwp_PanelGroupSpacerObj)
451 DoMethod(data->iwd_BottomPanel.iwp_PanelGroupObj, OM_REMMEMBER, (IPTR)data->iwd_BottomPanel.iwp_PanelGroupSpacerObj);
452 data->iwd_BottomPanel.iwp_PanelGroupSpacerObj = NULL;
455 DoMethod(data->iwd_BottomPanel.iwp_PanelGroupObj, MUIM_Group_ExitChange);
458 if (panelStatusBarPrivate->iwp_StatusBar_StatusBarObj)
460 #ifdef __AROS__
461 panelStatusBarPrivate->iwp_StatusBar_updateHook.h_Entry = ( HOOKFUNC )panelStatusBar__HookFunc_UpdateStatusFunc;
462 #else
463 panelStatusBarPrivate->iwp_StatusBar_updateHook= &StatusBar_updateHook;
464 #endif
465 DoMethod (
466 data->iwd_IconListObj, MUIM_Notify, MUIA_IconList_Changed, MUIV_EveryTime,
467 (IPTR)self, 3, MUIM_CallHook, &panelStatusBarPrivate->iwp_StatusBar_updateHook, (IPTR)CLASS
470 if (!(panelStatusBar__PrefsNotificationObject))
471 panelStatusBar__PrefsSetup(CLASS, self, message);
473 DoMethod
475 panelStatusBar__PrefsNotificationObject, MUIM_Notify, MUIA_ShowMe, MUIV_EveryTime,
476 (IPTR)data->iwd_BottomPanel.iwp_PanelContainerObj, 3, MUIM_Set, MUIA_ShowMe, MUIV_TriggerValue
479 if ((strcasecmp(extension_PrefsData, "True")) == 0)
481 SET(data->iwd_BottomPanel.iwp_PanelContainerObj, MUIA_ShowMe, TRUE);
484 AddTail(&panelStatusBar__StatusBars, &panelStatusBarPrivate->iwp_Node);
487 else
489 panelStatusBarPrivate->iwp_StatusBar_StatusBarObj = NULL;
495 ///panelStatusBar__Cleanup()
496 static IPTR panelStatusBar__Cleanup(Class *CLASS, Object *self, struct opSet *message)
498 SETUP_ICONWINDOW_INST_DATA;
499 struct panel_StatusBar_DATA *panelStatusBarPrivate;
501 D(bug("[IW.statusbar]: %s()\n", __PRETTY_FUNCTION__));
503 if ((panelStatusBarPrivate = (struct panel_StatusBar_DATA *)data->iwd_TopPanel.iwp_PanelPrivate) != (IPTR)NULL)
505 if (panelStatusBarPrivate->iwp_Node.ln_Name != extension_Name)
506 return NULL;
508 if (panelStatusBar__PrefsNotificationObject)
510 DoMethod
512 panelStatusBar__PrefsNotificationObject, MUIM_KillNotifyObj, MUIA_ShowMe,
513 (IPTR)data->iwd_BottomPanel.iwp_PanelContainerObj
517 return NULL;
521 ///panelStatusBar__OM_GET()
522 static IPTR panelStatusBar__OM_GET(Class *CLASS, Object *self, struct opGet *message)
524 SETUP_ICONWINDOW_INST_DATA;
526 struct panel_StatusBar_DATA *panelStatusBarPrivate = NULL;
527 IPTR *store = message->opg_Storage;
528 IPTR rv = FALSE;
530 D(bug("[IW.statusbar]: %s()\n", __PRETTY_FUNCTION__));
532 if ((panelStatusBarPrivate = (struct panel_StatusBar_DATA *)data->iwd_BottomPanel.iwp_PanelPrivate) != (IPTR)NULL)
534 if (panelStatusBarPrivate->iwp_Node.ln_Name != extension_Name)
535 return rv;
537 switch (message->opg_AttrID)
541 return rv;
545 ///OM_SET()
546 static IPTR panelStatusBar__OM_SET(Class *CLASS, Object *self, struct opSet *message)
548 SETUP_ICONWINDOW_INST_DATA;
550 struct panel_StatusBar_DATA *panelStatusBarPrivate = NULL;
551 struct TagItem *tstate = message->ops_AttrList, *tag;
552 BOOL UpdateIconlist = FALSE;
553 IPTR focusicon = (IPTR) NULL;
554 IPTR rv = FALSE;
556 D(bug("[IW.statusbar]: %s()\n", __PRETTY_FUNCTION__));
558 if ((panelStatusBarPrivate = (struct panel_StatusBar_DATA *)data->iwd_BottomPanel.iwp_PanelPrivate) != (IPTR)NULL)
560 if (panelStatusBarPrivate->iwp_Node.ln_Name != extension_Name)
561 return rv;
563 while ((tag = NextTagItem((TAGITEM)&tstate)) != NULL)
565 switch (tag->ti_Tag)
567 /*case MUIA_IconWindowExt_ToolBar_Enabled:
568 if ((!(data->iwd_Flags & IWDFLAG_ISROOT)) && (data->iwd_BottomPanel.iwp_PanelContainerObj))
570 // remove statusbar
571 if (!(( BOOL )tag->ti_Data))
573 if (panelStatusBarPrivate->iwp_StatusBar_StatusBarObj != NULL)
575 data->iwd_BottomPanel.iwp_PanelGroupSpacerObj = HSpace(0);
577 SET(data->iwd_BottomPanel.iwp_PanelContainerObj, MUIA_Frame, MUIV_Frame_None);
578 SET(data->iwd_BottomPanel.iwp_PanelContainerObj, MUIA_Group_Spacing, 0);
580 if ((data->iwd_BottomPanel.iwp_PanelGroupSpacerObj) && (DoMethod(data->iwd_BottomPanel.iwp_PanelGroupObj, MUIM_Group_InitChange)))
582 DoMethod(data->iwd_BottomPanel.iwp_PanelGroupObj, OM_REMMEMBER, (IPTR)panelStatusBarPrivate->iwp_StatusBar_StatusBarObj);
583 DoMethod(data->iwd_BottomPanel.iwp_PanelGroupObj, OM_ADDMEMBER, (IPTR)data->iwd_BottomPanel.iwp_PanelGroupSpacerObj);
584 DoMethod(data->iwd_BottomPanel.iwp_PanelGroupObj, MUIM_Group_ExitChange);
585 panelStatusBarPrivate->iwp_StatusBar_StatusBarObj = NULL;
589 else
591 // setup statusbar
592 if (panelStatusBarPrivate->iwp_StatusBar_StatusBarObj == NULL)
594 Object *prefs = NULL;
595 GET(_app(self), MUIA_Wanderer_Prefs, &prefs);
596 panelStatusBar__Setup(CLASS, self, prefs);
600 break;*/
604 return rv;
607 #define PANELSTATUSBAR_PRIORITY 10
609 IPTR panelStatusBar__Init()
611 D(bug("[IW.statusbar]: %s()\n", __PRETTY_FUNCTION__));
613 panelStatusBar__Extension.iwe_Node.ln_Pri = PANELSTATUSBAR_PRIORITY;
614 panelStatusBar__Extension.iwe_Node.ln_Name = extension_Name;
615 panelStatusBar__Extension.iwe_Setup = panelStatusBar__Setup;
616 panelStatusBar__Extension.iwe_Cleanup = panelStatusBar__Cleanup;
617 panelStatusBar__Extension.iwe_Set = panelStatusBar__OM_SET;
618 panelStatusBar__Extension.iwe_Get = panelStatusBar__OM_GET;
620 NewList(&panelStatusBar__StatusBars);
622 Enqueue(&iconwindow_Extensions, (struct Node *)&panelStatusBar__Extension);
624 D(bug("[IconWindow] %s: Added Extension '%s' @ %p to list @ %p\n", __PRETTY_FUNCTION__, panelStatusBar__Extension.iwe_Node.ln_Name, &panelStatusBar__Extension.iwe_Node, &iconwindow_Extensions));
626 return TRUE;
629 ADD2INIT(panelStatusBar__Init, PANELSTATUSBAR_PRIORITY);