revert between 56095 -> 55830 in arch
[AROS.git] / workbench / system / Workbook / wbwindow.c
blobb906f124715030364be7f3605907c1639bed46d4
1 /*
2 Copyright © 2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Workbook Window Class
6 Lang: english
7 */
9 #define DEBUG 0
10 #include <aros/debug.h>
12 #include <string.h>
13 #include <limits.h>
14 #include <intuition/icclass.h>
16 #include <proto/dos.h>
17 #include <proto/exec.h>
18 #include <proto/intuition.h>
19 #include <proto/utility.h>
20 #include <proto/gadtools.h>
21 #include <proto/workbench.h>
22 #include <proto/graphics.h>
23 #include <proto/layers.h>
24 #include <proto/icon.h>
26 #include <intuition/classusr.h>
27 #include <libraries/gadtools.h>
28 #include <exec/rawfmt.h>
30 #include "workbook_intern.h"
31 #include "workbook_menu.h"
32 #include "classes.h"
34 #include <clib/boopsistubs.h>
36 static inline WORD max(WORD a, WORD b)
38 return (a > b) ? a : b;
41 struct wbWindow_Icon {
42 struct MinNode wbwiNode;
43 Object *wbwiObject;
46 struct wbWindow {
47 STRPTR Path;
48 BPTR Lock;
49 struct Window *Window;
50 struct Menu *Menu;
51 Object *ScrollH;
52 Object *ScrollV;
53 Object *Area; /* Virual area of icons */
54 Object *Set; /* Set of icons */
55 APTR FilterHook;
57 ULONG Flags;
58 IPTR Tick;
60 /* Temporary path buffer */
61 TEXT PathBuffer[PATH_MAX];
62 TEXT ScreenTitle[256];
64 /* List of icons in this window */
65 struct MinList IconList;
68 #define WBWF_USERPORT (1 << 0) /* Window has a custom port */
70 #define Broken NM_ITEMDISABLED |
72 static const struct NewMenu WBWindow_menu[] = {
73 WBMENU_TITLE(WBMENU_WB),
74 WBMENU_ITEM(WBMENU_WB_BACKDROP),
75 WBMENU_ITEM(WBMENU_WB_EXECUTE),
76 WBMENU_ITEM(WBMENU_WB_SHELL),
77 WBMENU_ITEM(WBMENU_WB_ABOUT),
78 WBMENU_BAR,
79 WBMENU_ITEM(WBMENU_WB_QUIT),
80 WBMENU_ITEM(WBMENU_WB_SHUTDOWN),
81 WBMENU_TITLE(WBMENU_WN),
82 WBMENU_ITEM(WBMENU_WN_NEW_DRAWER),
83 WBMENU_ITEM(WBMENU_WN_OPEN_PARENT),
84 WBMENU_ITEM(WBMENU_WN_UPDATE),
85 WBMENU_ITEM(WBMENU_WN_SELECT_ALL),
86 WBMENU_ITEM(WBMENU_WN_SELECT_NONE),
87 WBMENU_SUBTITLE(WBMENU_WN__SNAP),
88 WBMENU_SUBITEM(WBMENU_WN__SNAP_WINDOW),
89 WBMENU_SUBITEM(WBMENU_WN__SNAP_ALL),
90 WBMENU_SUBTITLE(WBMENU_WN__SHOW),
91 WBMENU_SUBITEM(WBMENU_WN__SHOW_ICONS),
92 WBMENU_SUBITEM(WBMENU_WN__SHOW_ALL),
93 WBMENU_SUBTITLE(WBMENU_WN__VIEW),
94 WBMENU_SUBITEM(WBMENU_WN__VIEW_ICON),
95 WBMENU_SUBITEM(WBMENU_WN__VIEW_DETAILS),
96 WBMENU_TITLE(WBMENU_IC),
97 WBMENU_ITEM(WBMENU_IC_OPEN),
98 WBMENU_ITEM(WBMENU_IC_COPY),
99 WBMENU_ITEM(WBMENU_IC_RENAME),
100 WBMENU_ITEM(WBMENU_IC_INFO),
101 WBMENU_BAR,
102 WBMENU_ITEM(WBMENU_IC_SNAPSHOT),
103 WBMENU_ITEM(WBMENU_IC_UNSNAPSHOT),
104 WBMENU_ITEM(WBMENU_IC_LEAVE_OUT),
105 WBMENU_ITEM(WBMENU_IC_PUT_AWAY),
106 WBMENU_BAR,
107 WBMENU_ITEM(WBMENU_IC_DELETE),
108 WBMENU_ITEM(WBMENU_IC_FORMAT),
109 WBMENU_ITEM(WBMENU_IC_EMPTY_TRASH),
110 { NM_END },
113 static BOOL wbMenuEnable(Class *cl, Object *obj, int id, BOOL onoff)
115 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
116 struct wbWindow *my = INST_DATA(cl, obj);
117 int i, menu = -1, item = -1, sub = -1;
118 UWORD MenuNumber = MENUNULL;
119 BOOL rc = FALSE;
121 for (i = 0; WBWindow_menu[i].nm_Type != NM_END; i++) {
122 const struct NewMenu *nm = &WBWindow_menu[i];
124 switch (nm->nm_Type) {
125 case NM_TITLE:
126 menu++;
127 item = -1;
128 sub = -1;
129 break;
130 case IM_ITEM:
131 case NM_ITEM:
132 item++;
133 sub = -1;
134 break;
135 case IM_SUB:
136 case NM_SUB:
137 sub++;
138 break;
141 if (nm->nm_UserData == (APTR)(IPTR)id) {
142 MenuNumber = FULLMENUNUM(menu, item, sub);
143 break;
147 if (MenuNumber != MENUNULL) {
148 if (onoff)
149 OnMenu(my->Window, MenuNumber);
150 else
151 OffMenu(my->Window, MenuNumber);
153 rc = TRUE;
156 return rc;
159 AROS_UFH3(ULONG, wbFilterIcons_Hook,
160 AROS_UFHA(struct Hook*, hook, A0),
161 AROS_UFHA(struct ExAllData*, ead, A2),
162 AROS_UFHA(LONG *, type, A1))
164 AROS_USERFUNC_INIT
165 int i;
167 if (stricmp(ead->ed_Name, "disk.info") == 0)
168 return FALSE;
170 i = strlen(ead->ed_Name);
171 if (i >= 5 && stricmp(&ead->ed_Name[i-5], ".info") == 0) {
172 ead->ed_Name[i-5] = 0;
173 return TRUE;
176 if (stricmp(ead->ed_Name, ".backdrop") == 0)
177 return FALSE;
179 return FALSE;
181 AROS_USERFUNC_EXIT
184 AROS_UFH3(ULONG, wbFilterAll_Hook,
185 AROS_UFHA(struct Hook*, hook, A0),
186 AROS_UFHA(struct ExAllData*, ead, A2),
187 AROS_UFHA(LONG *, type, A1))
189 AROS_USERFUNC_INIT
191 int i;
193 if (stricmp(ead->ed_Name, "disk.info") == 0)
194 return FALSE;
196 i = strlen(ead->ed_Name);
197 if (i >= 5 && stricmp(&ead->ed_Name[i-5], ".info") == 0) {
198 ead->ed_Name[i-5] = 0;
199 return TRUE;
202 if (stricmp(ead->ed_Name, ".backdrop") == 0)
203 return FALSE;
205 return TRUE;
207 AROS_USERFUNC_EXIT
210 static int wbwiIconCmp(Class *cl, Object *obj, Object *a, Object *b)
212 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
214 CONST_STRPTR al = NULL, bl = NULL;
216 GetAttr(WBIA_Label, a, (IPTR *)&al);
217 GetAttr(WBIA_Label, b, (IPTR *)&bl);
219 if (al == bl)
220 return 0;
222 if (al == NULL)
223 return 1;
225 if (bl == NULL)
226 return -1;
228 return Stricmp(al, bl);
231 static void wbwiAppend(Class *cl, Object *obj, Object *iobj)
233 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
234 struct wbWindow *my = INST_DATA(cl, obj);
235 struct wbWindow_Icon *wbwi;
237 wbwi = AllocMem(sizeof(*wbwi), MEMF_ANY);
238 if (!wbwi) {
239 DisposeObject(iobj);
240 } else {
241 struct wbWindow_Icon *tmp, *pred = NULL;
242 wbwi->wbwiObject = iobj;
244 /* Insert in Alpha order */
245 ForeachNode(&my->IconList, tmp) {
246 if (wbwiIconCmp(cl, obj, tmp->wbwiObject, wbwi->wbwiObject) == 0) {
247 DisposeObject(iobj);
248 return;
250 if (wbwiIconCmp(cl, obj, tmp->wbwiObject, wbwi->wbwiObject) < 0)
251 break;
252 pred = tmp;
255 Insert((struct List *)&my->IconList, (struct Node *)wbwi, (struct Node *)pred);
259 static void wbAddFiles(Class *cl, Object *obj)
261 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
262 struct wbWindow *my = INST_DATA(cl, obj);
263 struct ExAllControl *eac;
264 struct ExAllData *ead;
265 const ULONG eadSize = sizeof(struct ExAllData) + 1024;
266 TEXT *path;
267 int file_part;
269 path = AllocVec(1024, MEMF_ANY);
270 if (!path)
271 return;
273 if (!NameFromLock(my->Lock, path, 1024)) {
274 FreeVec(path);
276 file_part = strlen(path);
278 ead = AllocVec(eadSize, MEMF_CLEAR);
279 if (ead != NULL) {
280 eac = AllocDosObject(DOS_EXALLCONTROL, NULL);
281 if (eac != NULL) {
282 struct Hook hook;
283 BOOL more = TRUE;
285 hook.h_Entry = my->FilterHook;
286 hook.h_SubEntry = NULL;
287 hook.h_Data = wb;
289 eac->eac_MatchFunc = &hook;
290 while (more) {
291 struct ExAllData *tmp = ead;
292 int i;
294 more = ExAll(my->Lock, ead, eadSize, ED_NAME, eac);
295 for (i = 0; i < eac->eac_Entries; i++, tmp=tmp->ed_Next) {
296 Object *iobj;
297 path[file_part] = 0;
298 if (AddPart(path, tmp->ed_Name, 1024)) {
299 iobj = NewObject(WBIcon, NULL,
300 WBIA_File, path,
301 WBIA_Label, tmp->ed_Name,
302 WBIA_Screen, my->Window->WScreen,
303 TAG_END);
304 if (iobj != NULL)
305 wbwiAppend(cl, obj, iobj);
309 FreeDosObject(DOS_EXALLCONTROL, eac);
311 FreeVec(ead);
314 FreeVec(path);
317 static void wbAddVolumeIcons(Class *cl, Object *obj)
319 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
320 struct wbWindow *my = INST_DATA(cl, obj);
321 struct DosList *dl;
322 char text[NAME_MAX];
324 /* Add all the DOS disks */
325 dl = LockDosList(LDF_VOLUMES | LDF_READ);
327 if (dl != BNULL) {
328 struct DosList *tdl;
330 tdl = dl;
331 while ((tdl = NextDosEntry(tdl, LDF_VOLUMES))) {
332 Object *iobj;
334 CopyMem(AROS_BSTR_ADDR(tdl->dol_Name), text, AROS_BSTR_strlen(tdl->dol_Name));
335 CopyMem(":",&text[AROS_BSTR_strlen(tdl->dol_Name)],2);
337 iobj = NewObject(WBIcon, NULL,
338 WBIA_File, text,
339 WBIA_Label, AROS_BSTR_ADDR(tdl->dol_Name),
340 WBIA_Screen, my->Window->WScreen,
341 TAG_END);
342 D(bug("Volume: %s => %p\n", text, iobj));
343 if (iobj)
344 wbwiAppend(cl, obj, iobj);
346 UnLockDosList(LDF_VOLUMES | LDF_READ);
350 static void wbAddAppIcons(Class *cl, Object *obj)
352 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
353 struct wbWindow *my = INST_DATA(cl, obj);
354 struct DiskObject *icon;
355 char text[NAME_MAX];
357 /* Add all the AppIcons */
358 icon = NULL;
359 while ((icon = GetNextAppIcon(icon, &text[0]))) {
360 Object *iobj = NewObject(WBIcon, NULL,
361 WBIA_Icon, icon,
362 WBIA_Screen, my->Window->WScreen,
363 TAG_END);
364 if (iobj != NULL)
365 wbwiAppend(cl, obj, iobj);
369 static void wbRedimension(Class *cl, Object *obj)
371 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
372 struct wbWindow *my = INST_DATA(cl, obj);
373 struct Window *win = my->Window;
374 struct IBox real; /* pos & size of the inner window area */
375 IPTR setWidth = 0, setHeight = 0;
377 real.Left = win->BorderLeft;
378 real.Top = win->BorderTop;
379 real.Width = win->Width - (win->BorderLeft + win->BorderRight);
380 real.Height= win->Height- (win->BorderTop + win->BorderBottom);
382 D(bug("%s: Real (%d,%d) %dx%d\n", __func__,
383 real.Left, real.Top, real.Width, real.Height));
384 D(bug("%s: Border (%d,%d) %dx%d\n", __func__,
385 my->Window->BorderLeft, my->Window->BorderTop,
386 my->Window->BorderRight, my->Window->BorderBottom));
388 SetAttrs(my->Area, GA_Top, real.Top,
389 GA_Left, real.Left,
390 GA_Width, real.Width,
391 GA_Height, real.Height,
392 TAG_END);
394 SetAttrs(my->ScrollH, PGA_Visible, real.Width,
395 GA_Left, real.Left,
396 GA_RelBottom, -(my->Window->BorderBottom - 2),
397 GA_Width, real.Width,
398 GA_Height, my->Window->BorderBottom - 3,
399 TAG_END);
401 SetAttrs(my->ScrollV, PGA_Visible, real.Height,
402 GA_RelRight, -(my->Window->BorderRight - 2),
403 GA_Top, real.Top,
404 GA_Width, my->Window->BorderRight - 3,
405 GA_Height, real.Height,
406 TAG_END);
408 GetAttr(GA_Width, my->Set, &setWidth);
409 GetAttr(GA_Height, my->Set, &setHeight);
410 UpdateAttrs(obj, NULL, 0,
411 WBVA_VirtWidth, setWidth,
412 WBVA_VirtHeight, setHeight,
413 TAG_END);
415 /* Clear the background to the right of the icons*/
416 if (setWidth < real.Width) {
417 SetAPen(win->RPort,0);
418 RectFill(win->RPort, win->BorderLeft + setWidth, win->BorderTop,
419 win->Width - win->BorderRight - 1,
420 win->Height - win->BorderBottom - 1);
421 } else {
422 setWidth = real.Width;
425 /* Clear the background beneath the icons*/
426 if (setHeight < real.Height) {
427 SetAPen(win->RPort,0);
428 RectFill(win->RPort, win->BorderLeft, win->BorderTop + setHeight,
429 setWidth - win->BorderRight - 1,
430 win->Height - win->BorderBottom - 1);
435 /* Rescan the Lock for new entries */
436 static void wbRescan(Class *cl, Object *obj)
438 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
439 struct wbWindow *my = INST_DATA(cl, obj);
440 struct wbWindow_Icon *wbwi;
442 /* We're going to busy for a while */
443 D(bug("BUSY....\n"));
444 SetWindowPointer(my->Window, WA_BusyPointer, TRUE, TAG_END);
446 /* Remove and undisplay any existing icons */
447 while ((wbwi = (struct wbWindow_Icon *)REMHEAD(&my->IconList)) != NULL) {
448 DoMethod(my->Set, OM_REMMEMBER, wbwi->wbwiObject);
449 DisposeObject(wbwi->wbwiObject);
450 FreeMem(wbwi, sizeof(*wbwi));
453 /* Scan for new icons, and add them to the list
455 if (my->Lock == BNULL) {
456 /* Root window */
457 wbAddVolumeIcons(cl, obj);
458 wbAddAppIcons(cl, obj);
459 } else {
460 /* Directory window */
461 wbAddFiles(cl, obj);
464 /* Display the new icons */
465 ForeachNode(&my->IconList, wbwi)
466 DoMethod(my->Set, OM_ADDMEMBER, wbwi->wbwiObject);
468 /* Adjust the scrolling regions */
469 wbRedimension(cl, obj);
471 /* Return the point back to normal */
472 SetWindowPointer(my->Window, WA_BusyPointer, FALSE, TAG_END);
473 D(bug("Not BUSY....\n"));
477 const struct TagItem scrollv2window[] = {
478 { PGA_Top, WBVA_VirtTop },
479 { TAG_END, 0 },
481 const struct TagItem scrollh2window[] = {
482 { PGA_Top, WBVA_VirtLeft },
483 { TAG_END, 0 },
486 static void wbFixBorders(struct Window *win)
488 int bb, br;
490 bb = 16 - win->BorderBottom;
491 br = 16 - win->BorderRight;
493 win->BorderBottom += bb;
494 win->BorderRight += br;
497 static IPTR WBWindowNew(Class *cl, Object *obj, struct opSet *ops)
499 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
500 struct wbWindow *my;
501 struct MsgPort *userport;
502 CONST_STRPTR path;
503 ULONG idcmp;
504 IPTR rc = 0;
505 APTR vis;
506 struct wbWindow_Icon *wbwi;
508 rc = DoSuperMethodA(cl, obj, (Msg)ops);
509 if (rc == 0)
510 return rc;
512 obj = (Object *)rc;
513 my = INST_DATA(cl, obj);
515 NEWLIST(&my->IconList);
516 my->FilterHook = wbFilterIcons_Hook;
518 path = (CONST_STRPTR)GetTagData(WBWA_Path, (IPTR)NULL, ops->ops_AttrList);
519 if (path == NULL) {
520 my->Lock = BNULL;
521 my->Path = NULL;
522 } else {
523 my->Lock = Lock(path, SHARED_LOCK);
524 if (my->Lock == BNULL)
525 goto error;
527 my->Path = AllocVec(strlen(path)+1, MEMF_ANY);
528 if (my->Path == NULL)
529 goto error;
531 strcpy(my->Path, path);
534 /* Create icon set */
535 my->Set = NewObject(WBSet, NULL,
536 TAG_END);
538 idcmp = IDCMP_MENUPICK | IDCMP_INTUITICKS;
539 if (my->Path == NULL) {
540 my->Window = OpenWindowTags(NULL,
541 WA_IDCMP, 0,
542 WA_Backdrop, TRUE,
543 WA_WBenchWindow, TRUE,
544 WA_Borderless, TRUE,
545 WA_Activate, TRUE,
546 WA_SmartRefresh, TRUE,
547 WA_NewLookMenus, TRUE,
548 WA_PubScreen, NULL,
549 TAG_MORE, ops->ops_AttrList );
550 my->Window->BorderTop = my->Window->WScreen->BarHeight+1;
551 } else {
552 struct DiskObject *icon;
553 struct NewWindow *nwin = NULL;
554 struct TagItem extra[] = {
555 { WA_Left, 64 },
556 { WA_Top, 64 },
557 { WA_Width, 200, },
558 { WA_Height, 150, },
559 { TAG_MORE, (IPTR)ops->ops_AttrList },
562 icon = GetDiskObjectNew(my->Path);
563 if (icon == NULL)
564 goto error;
566 if (icon->do_DrawerData) {
567 nwin = &icon->do_DrawerData->dd_NewWindow;
568 D(bug("%s: NewWindow %p\n", __func__, nwin));
569 extra[0].ti_Tag = TAG_MORE;
570 extra[0].ti_Data = (IPTR)ops->ops_AttrList;
573 idcmp |= IDCMP_NEWSIZE | IDCMP_CLOSEWINDOW;
574 my->Window = OpenWindowTags(nwin,
575 WA_IDCMP, 0,
576 WA_MinWidth, 100,
577 WA_MinHeight, 100,
578 WA_MaxWidth, ~0,
579 WA_MaxHeight, ~0,
580 WA_Backdrop, FALSE,
581 WA_WBenchWindow, TRUE,
582 WA_Title, my->Path,
583 WA_SmartRefresh, TRUE,
584 WA_SizeGadget, TRUE,
585 WA_DragBar, TRUE,
586 WA_DepthGadget, TRUE,
587 WA_CloseGadget, TRUE,
588 WA_Activate, TRUE,
589 WA_NewLookMenus, TRUE,
590 WA_AutoAdjust, TRUE,
591 WA_PubScreen, NULL,
592 TAG_MORE, (IPTR)&extra[0] );
594 if (my->Window)
595 wbFixBorders(my->Window);
597 FreeDiskObject(icon);
600 if (!my->Window)
601 goto error;
603 /* If we want a shared port, do it. */
604 userport = (struct MsgPort *)GetTagData(WBWA_UserPort, (IPTR)NULL, ops->ops_AttrList);
605 if (userport) {
606 my->Flags |= WBWF_USERPORT;
607 my->Window->UserPort = userport;
609 ModifyIDCMP(my->Window, idcmp);
611 /* The gadgets' layout will be performed during wbRedimension
613 AddGadget(my->Window, (struct Gadget *)(my->Area = NewObject(WBVirtual, NULL,
614 WBVA_Gadget, (IPTR)my->Set,
615 TAG_END)), 0);
617 /* Add the verical scrollbar */
618 AddGadget(my->Window, (struct Gadget *)(my->ScrollV = NewObject(NULL, "propgclass",
619 GA_RightBorder, TRUE,
621 ICA_TARGET, (IPTR)obj,
622 ICA_MAP, (IPTR)scrollv2window,
623 PGA_Freedom, FREEVERT,
624 PGA_NewLook, TRUE,
625 PGA_Borderless, TRUE,
626 PGA_Total, 1,
627 PGA_Visible, 1,
628 PGA_Top, 0,
629 TAG_END)), 0);
631 /* Add the horizontal scrollbar */
632 AddGadget(my->Window, (struct Gadget *)(my->ScrollH = NewObject(NULL, "propgclass",
633 ICA_TARGET, (IPTR)obj,
634 ICA_MAP, (IPTR)scrollh2window,
635 PGA_Freedom, FREEHORIZ,
636 PGA_NewLook, TRUE,
637 PGA_Borderless, TRUE,
638 PGA_Total, 1,
639 PGA_Visible, 1,
640 PGA_Top, 0,
641 TAG_END)), 0);
643 /* Send first intuitick */
644 DoMethod(obj, WBWM_INTUITICK);
646 my->Menu = CreateMenusA((struct NewMenu *)WBWindow_menu, NULL);
647 if (my->Menu == NULL)
648 goto error;
650 vis = GetVisualInfo(my->Window->WScreen, TAG_END);
651 LayoutMenus(my->Menu, vis, TAG_END);
652 FreeVisualInfo(vis);
654 SetMenuStrip(my->Window, my->Menu);
656 /* Disable opening the parent for root window
657 * and disk paths.
659 if (my->Lock == BNULL) {
660 wbMenuEnable(cl, obj, WBMENU_ID(WBMENU_WN_OPEN_PARENT), FALSE);
661 } else {
662 BPTR lock = ParentDir(my->Lock);
663 if (lock == BNULL) {
664 wbMenuEnable(cl, obj, WBMENU_ID(WBMENU_WN_OPEN_PARENT), FALSE);
665 } else {
666 UnLock(lock);
670 SetAttrs(my->Set, WBSA_MaxWidth, my->Window->Width - (my->Window->BorderLeft + my->Window->BorderRight));
671 RefreshGadgets(my->Window->FirstGadget, my->Window, NULL);
673 wbRescan(cl, obj);
675 return rc;
677 error:
678 while ((wbwi = (APTR)GetHead(&my->IconList))) {
679 Remove((struct Node *)wbwi);
680 FreeMem(wbwi, sizeof(*wbwi));
683 if (my->Set)
684 DisposeObject(my->Set);
686 if (my->Window)
687 CloseWindow(my->Window);
689 if (my->Path)
690 FreeVec(my->Path);
692 if (my->Lock != BNULL)
693 UnLock(my->Lock);
695 DoSuperMethod(cl, obj, OM_DISPOSE, 0);
696 return 0;
699 static IPTR WBWindowDispose(Class *cl, Object *obj, Msg msg)
701 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
702 struct wbWindow *my = INST_DATA(cl, obj);
703 struct wbWindow_Icon *wbwi;
705 ClearMenuStrip(my->Window);
706 FreeMenus(my->Menu);
708 /* If we have a custom user port, be paranoid.
709 * See the Autodocs for CloseWindow().
711 if (my->Flags & WBWF_USERPORT) {
712 struct IntuiMessage *msg;
713 struct Node *succ;
715 Forbid();
716 msg = (APTR)my->Window->UserPort->mp_MsgList.lh_Head;
717 while ((succ = msg->ExecMessage.mn_Node.ln_Succ )) {
718 if (msg->IDCMPWindow == my->Window) {
719 Remove((APTR)msg);
720 ReplyMsg((struct Message *)msg);
723 msg = (struct IntuiMessage *) succ;
726 my->Window->UserPort = NULL;
727 ModifyIDCMP(my->Window, 0);
729 Permit();
732 /* We won't need our list of icons anymore */
733 while ((wbwi = (APTR)GetHead(&my->IconList))) {
734 Remove((struct Node *)wbwi);
735 FreeMem(wbwi, sizeof(*wbwi));
738 /* As a side effect, this will close all the
739 * gadgets attached to it.
741 CloseWindow(my->Window);
743 /* .. except for my->Set */
744 DisposeObject(my->Set);
746 if (my->Path)
747 FreeVec(my->Path);
749 if (my->Lock != BNULL)
750 UnLock(my->Lock);
752 return DoSuperMethodA(cl, obj, msg);
755 // OM_GET
756 static IPTR WBWindowGet(Class *cl, Object *obj, struct opGet *opg)
758 struct wbWindow *my = INST_DATA(cl, obj);
759 IPTR rc = TRUE;
761 switch (opg->opg_AttrID) {
762 case WBWA_Path:
763 *(opg->opg_Storage) = (IPTR)my->Path;
764 break;
765 case WBWA_Window:
766 *(opg->opg_Storage) = (IPTR)my->Window;
767 break;
768 default:
769 rc = DoSuperMethodA(cl, obj, (Msg)opg);
770 break;
773 return rc;
776 // OM_UPDATE
777 static IPTR WBWindowUpdate(Class *cl, Object *obj, struct opUpdate *opu)
779 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
780 struct wbWindow *my = INST_DATA(cl, obj);
781 struct TagItem *tstate;
782 struct TagItem *tag;
783 IPTR rc;
785 rc = DoSuperMethodA(cl, obj, (Msg)opu);
787 /* Also send these to the Area */
788 rc |= DoMethodA(my->Area, (Msg)opu);
790 /* Update scrollbars if needed */
791 tstate = opu->opu_AttrList;
792 while ((tag = NextTagItem(&tstate))) {
793 switch (tag->ti_Tag) {
794 case WBVA_VirtLeft:
795 rc = TRUE;
796 break;
797 case WBVA_VirtTop:
798 rc = TRUE;
799 break;
800 case WBVA_VirtWidth:
801 SetAttrs(my->ScrollH, PGA_Total, tag->ti_Data, TAG_END);
802 rc = TRUE;
803 break;
804 case WBVA_VirtHeight:
805 SetAttrs(my->ScrollV, PGA_Total, tag->ti_Data, TAG_END);
806 rc = TRUE;
807 break;
811 if (rc && !(opu->opu_Flags & OPUF_INTERIM))
812 RefreshGadgets(my->Window->FirstGadget, my->Window, NULL);
814 return rc;
817 // WBWM_NEWSIZE
818 static IPTR WBWindowNewSize(Class *cl, Object *obj, Msg msg)
820 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
821 struct wbWindow *my = INST_DATA(cl, obj);
822 struct Window *win = my->Window;
823 struct Region *clip;
825 SetAttrs(my->Set, WBSA_MaxWidth, win->Width - (win->BorderLeft + win->BorderRight));
827 /* Clip to the window for drawing */
828 clip = wbClipWindow(wb, win);
829 wbRedimension(cl, obj);
830 wbUnclipWindow(wb, win, clip);
832 return 0;
835 static IPTR WBWindowRefresh(Class *cl, Object *obj, Msg msg)
837 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
838 struct wbWindow *my = INST_DATA(cl, obj);
839 struct Window *win = my->Window;
841 BeginRefresh(win);
842 EndRefresh(win, TRUE);
844 return 0;
847 static void NewCLI(Class *cl, Object *obj)
849 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
850 struct wbWindow *my = INST_DATA(cl, obj);
852 BPTR dir;
854 SetWindowPointer(my->Window, WA_BusyPointer, TRUE, TAG_END);
855 dir = CurrentDir(my->Lock);
856 Execute("", BNULL, BNULL);
857 CurrentDir(dir);
858 SetWindowPointer(my->Window, WA_BusyPointer, FALSE, TAG_END);
861 static IPTR WBWindowForSelectedIcons(Class *cl, Object *obj, IPTR MethodID)
863 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
864 struct wbWindow *my = INST_DATA(cl, obj);
865 struct wbWindow_Icon *wbwi;
866 IPTR rc = 0;
868 ForeachNode(&my->IconList, wbwi) {
869 IPTR selected = FALSE;
871 GetAttr(GA_Selected, wbwi->wbwiObject, &selected);
872 if (selected)
873 rc |= DoMethodA(wbwi->wbwiObject, (Msg)&MethodID);
876 return rc;
879 // WBWM_MENUPICK
880 static IPTR WBWindowMenuPick(Class *cl, Object *obj, struct wbwm_MenuPick *wbwmp)
882 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
883 struct wbWindow *my = INST_DATA(cl, obj);
884 struct MenuItem *item = wbwmp->wbwmp_MenuItem;
885 BPTR lock;
886 BOOL rc = TRUE;
888 switch (WBMENU_ITEM_ID(item)) {
889 case WBMENU_ID(WBMENU_WN_OPEN_PARENT):
890 if (my->Lock != BNULL) {
891 lock = ParentDir(my->Lock);
892 if (NameFromLock(lock, my->PathBuffer, sizeof(my->PathBuffer))) {
893 OpenWorkbenchObject(my->PathBuffer, TAG_END);
895 UnLock(lock);
897 break;
898 case WBMENU_ID(WBMENU_WN__SHOW_ICONS):
899 my->FilterHook = wbFilterIcons_Hook;
900 wbRescan(cl, obj);
901 break;
902 case WBMENU_ID(WBMENU_WN__SHOW_ALL):
903 my->FilterHook = wbFilterAll_Hook;
904 wbRescan(cl, obj);
905 break;
906 case WBMENU_ID(WBMENU_WB_SHELL):
907 NewCLI(cl, obj);
908 break;
909 case WBMENU_ID(WBMENU_IC_OPEN):
910 rc = WBWindowForSelectedIcons(cl, obj, WBIM_Open);
911 break;
912 case WBMENU_ID(WBMENU_IC_COPY):
913 rc = WBWindowForSelectedIcons(cl, obj, WBIM_Copy);
914 break;
915 case WBMENU_ID(WBMENU_IC_RENAME):
916 rc = WBWindowForSelectedIcons(cl, obj, WBIM_Rename);
917 break;
918 case WBMENU_ID(WBMENU_IC_INFO):
919 rc = WBWindowForSelectedIcons(cl, obj, WBIM_Info);
920 break;
921 case WBMENU_ID(WBMENU_IC_SNAPSHOT):
922 rc = WBWindowForSelectedIcons(cl, obj, WBIM_Snapshot);
923 break;
924 case WBMENU_ID(WBMENU_IC_UNSNAPSHOT):
925 rc = WBWindowForSelectedIcons(cl, obj, WBIM_Unsnapshot);
926 break;
927 case WBMENU_ID(WBMENU_IC_LEAVE_OUT):
928 rc = WBWindowForSelectedIcons(cl, obj, WBIM_Leave_Out);
929 break;
930 case WBMENU_ID(WBMENU_IC_PUT_AWAY):
931 rc = WBWindowForSelectedIcons(cl, obj, WBIM_Put_Away);
932 break;
933 case WBMENU_ID(WBMENU_IC_DELETE):
934 rc = WBWindowForSelectedIcons(cl, obj, WBIM_Delete);
935 break;
936 case WBMENU_ID(WBMENU_IC_FORMAT):
937 rc = WBWindowForSelectedIcons(cl, obj, WBIM_Format);
938 break;
939 case WBMENU_ID(WBMENU_IC_EMPTY_TRASH):
940 rc = WBWindowForSelectedIcons(cl, obj, WBIM_Empty_Trash);
941 break;
942 default:
943 rc = FALSE;
944 break;
947 return rc;
950 // WBWM_INTUITICK
951 static IPTR WBWindowIntuiTick(Class *cl, Object *obj, Msg msg)
953 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
954 struct wbWindow *my = INST_DATA(cl, obj);
955 IPTR rc = FALSE;
957 if (my->Tick == 0) {
958 ULONG val[5];
960 val[0] = WB_VERSION;
961 val[1] = WB_REVISION;
962 val[2] = AvailMem(MEMF_CHIP) / 1024;
963 val[3] = AvailMem(MEMF_FAST) / 1024;
964 val[4] = AvailMem(MEMF_ANY) / 1024;
966 /* Update the window's title */
967 RawDoFmt("Workbook %ld.%ld Chip: %ldk, Fast: %ldk, Any: %ldk", (RAWARG)val,
968 RAWFMTFUNC_STRING, my->ScreenTitle);
970 SetWindowTitles(my->Window, (CONST_STRPTR)-1, my->ScreenTitle);
971 rc = TRUE;
974 /* Approx 10 IntuiTicks per second */
975 my->Tick = (my->Tick + 1) % 10;
977 return rc;
980 static IPTR dispatcher(Class *cl, Object *obj, Msg msg)
982 IPTR rc = 0;
984 switch (msg->MethodID) {
985 case OM_NEW: rc = WBWindowNew(cl, obj, (APTR)msg); break;
986 case OM_DISPOSE: rc = WBWindowDispose(cl, obj, (APTR)msg); break;
987 case OM_GET: rc = WBWindowGet(cl, obj, (APTR)msg); break;
988 case OM_UPDATE: rc = WBWindowUpdate(cl, obj, (APTR)msg); break;
989 case WBWM_NEWSIZE: rc = WBWindowNewSize(cl, obj, (APTR)msg); break;
990 case WBWM_MENUPICK: rc = WBWindowMenuPick(cl, obj, (APTR)msg); break;
991 case WBWM_INTUITICK: rc = WBWindowIntuiTick(cl, obj, (APTR)msg); break;
992 case WBWM_REFRESH: rc = WBWindowRefresh(cl, obj, (APTR)msg); break;
993 default: rc = DoSuperMethodA(cl, obj, msg); break;
996 return rc;
999 Class *WBWindow_MakeClass(struct WorkbookBase *wb)
1001 Class *cl;
1003 cl = MakeClass( NULL, "rootclass", NULL,
1004 sizeof(struct wbWindow),
1006 if (cl != NULL) {
1007 cl->cl_Dispatcher.h_Entry = HookEntry;
1008 cl->cl_Dispatcher.h_SubEntry = dispatcher;
1009 cl->cl_Dispatcher.h_Data = NULL;
1010 cl->cl_UserData = (IPTR)wb;
1013 return cl;