4 ** Copyright (C) 1993,94,95,96,97 Bernardo Innocenti
6 ** Graphic User Interface handling routines.
9 #include <exec/nodes.h>
10 #include <exec/memory.h>
11 #include <intuition/intuition.h>
12 #include <intuition/intuitionbase.h>
13 #include <intuition/gadgetclass.h>
14 #include <intuition/imageclass.h>
15 #include <utility/tagitem.h>
16 #include <graphics/rpattr.h>
18 #include <proto/exec.h>
19 #include <proto/dos.h>
20 #include <proto/intuition.h>
21 #include <proto/gadtools.h>
22 #include <proto/graphics.h>
23 #include <proto/layers.h>
24 #include <proto/keymap.h>
25 #include <proto/utility.h>
26 #include <proto/commodities.h>
27 #include <proto/diskfont.h>
29 #include "XModulePriv.h"
31 #include "CustomClasses.h"
35 XDEF struct Screen *Scr = NULL;
36 XDEF struct ScrInfo ScrInfo = {0};
37 XDEF APTR VisualInfo = NULL;
38 XDEF struct DrawInfo *DrawInfo = NULL;
42 TopazAttr = { "topaz.font", 8, FS_NORMAL, FPF_ROMFONT },
54 /* Window borders layout information */
55 XDEF UWORD OffX, OffY; /* X and Y offsets for window rendering */
56 XDEF WORD SizeWidth = 18, /* Dimensions of the window size gadget */
59 /* IDCMP windows support */
60 XDEF ULONG IDCMPSig = 0; /* Signal for above mentioned port */
61 XDEF ULONG Signals = SIGBREAKFLAGS; /* Signals for Wait() in main loop */
62 XDEF struct IntuiMessage IntuiMsg; /* A copy of the last received IntuiMsg */
63 XDEF struct List WindowList; /* Linked list of all open windows */
65 static UBYTE ActiveKey = 0; /* These three are used to handle */
66 static struct Gadget *ActiveGad = NULL; /* selection of button gadgets */
67 static struct Window *ActiveWin = NULL; /* with keyboard shortcuts. */
68 static struct Window *OldPrWindowPtr = (struct Window *)1L;
70 XDEF LONG LastErr = 0;
71 XDEF ULONG UniqueID; /* An ID got from GetUniqueID() */
72 XDEF UWORD WinLockCount = 0; /* Allow nesting of window locking */
73 XDEF BOOL Quit = FALSE;
74 XDEF BOOL DoNextSelect = TRUE; /* Menu selection, see menu handling code */
75 XDEF BOOL ShowRequesters = TRUE;
76 XDEF BOOL OwnScreen = FALSE; /* Are we owners or visitors? */
77 XDEF BOOL ScreenReopening = FALSE; /* Set to TRUE while reopening windows */
78 XDEF BOOL ScreenShutdown = FALSE; /* Set to TRUE while shutting down screen */
79 XDEF Class *ScrollButtonClass = NULL;
81 /* Shared IDCMP port for all windows */
82 static struct MsgPort *WinPort = NULL;
83 static Class *VImageClass = NULL;
84 static ULONG VImageUseCount = 0;
85 static struct Image *ButtonFrame = NULL;
86 static WORD ButtonFrameWidth = 0;
87 static WORD ButtonFrameHeight = 0;
90 XDEF struct WDescr WDescr[WID_COUNT] =
92 { NULL, 0, 0, (struct TagItem *)ToolBoxWinTags },
93 { NULL, 0, 0, (struct TagItem *)PrefsWinTags },
94 { NULL, 0, 0, (struct TagItem *)SongInfoWinTags },
95 { NULL, 0, 0, (struct TagItem *)InstrumentsWinTags },
96 { NULL, 0, 0, (struct TagItem *)SequenceWinTags },
97 { NULL, 0, 0, (struct TagItem *)PatternWinTags },
98 { NULL, 0, 0, (struct TagItem *)PlayWinTags },
99 { NULL, 0, 0, (struct TagItem *)SampleWinTags },
100 { NULL, 0, 0, (struct TagItem *)OptimizationWinTags },
101 { NULL, 0, 0, (struct TagItem *)SaversWinTags },
102 { NULL, 0, 0, (struct TagItem *)PattPrefsWinTags },
103 { NULL, 0, 0, (struct TagItem *)PattSizeWinTags },
104 { NULL, 0, 0, (struct TagItem *)ClearWinTags },
105 { NULL, 0, 0, (struct TagItem *)LogWinTags },
106 { NULL, 0, 0, (struct TagItem *)ProgressWinTags }
111 XDEF struct GuiSwitches GuiSwitches =
113 TRUE, /* SaveIcons */
114 TRUE, /* AskOverwrite */
116 TRUE, /* ShowAppIcon */
117 FALSE, /* UseReqTools */
118 TRUE, /* SmartRefresh */
119 TRUE, /* UseDataTypes */
120 TRUE, /* InstrSaveIcons */
121 TRUE, /* AskAutosave */
122 FALSE, /* DoBackups */
123 FALSE, /* LogToFile */
124 INST_8SVX, /* InstrSaveMode */
125 1, /* SampDrawMode */
126 XMDMF_NOTE+1, /* LogLevel */
127 0, /* AutosaveTime */
128 3, /* BackupVersions */
129 "*,#", /* BackupTemplate */
130 "CON:////XModule Log/AUTO/CLOSE/INACTIVE/SCREEN XMODULE" /* LogFile */
137 /* Wait pointer image data */
139 static __chip UWORD WaitPointer[] =
163 #endif /* OS30_ONLY */
166 /* Martin Taillefer's block pointer */
168 static UWORD __chip BlockPointer[] =
194 /* Local function prototypes */
196 static void HandleKey (void);
197 static void SelectButton (struct Window *win, struct Gadget *gad);
198 static void DeselectButton (void);
199 static void RenderWindowBorders(struct WinUserData *wud);
200 static struct WindowBorder *CreateWindowBorder (struct WinUserData *wud, UWORD left, UWORD top, UWORD width, UWORD height, ULONG bordertype);
201 static struct Gadget *CreateVImageButton (struct TagItem *tags, struct NewGadget *ng);
202 static void DeleteVImageButton (struct Gadget *g);
203 static struct Gadget *CreateGadgets (struct LayoutGadgetsArgs *lga, UWORD mode, UWORD left, UWORD top, UWORD width, UWORD height);
204 static void LayoutGadgets (struct LayoutGadgetsArgs *lga, UWORD mode);
205 static void DeleteGadgets (struct WinUserData *wud);
207 static void DeleteWUD (struct WinUserData *wud);
208 static struct WinUserData *CreateLayoutInfo (struct WinUserData *wud);
212 GLOBALCALL LONG HandleGui (void)
214 /* Handle XModule GUI - Main event handling loop */
216 ULONG recsig; /* Received Signals */
217 LONG rc = 0; /* Return Code */
220 /* This is the main event handling loop */
224 recsig = Wait (Signals);
226 if (recsig & IDCMPSig)
229 if (recsig & AudioSig)
232 if (recsig & PubPortSig)
238 if (recsig & FileReqSig)
244 if (recsig & AmigaGuideSig)
247 /* Check break signals */
248 if (recsig & SIGBREAKFLAGS)
250 if (recsig & SIGBREAKF_CTRL_C)
253 GuiSwitches.AskExit = FALSE;
257 if (recsig & SIGBREAKF_CTRL_D)
258 if (MyBroker) ActivateCxObj (MyBroker, FALSE);
260 if (recsig & SIGBREAKF_CTRL_E)
261 if (MyBroker) ActivateCxObj (MyBroker, TRUE);
263 if (recsig & SIGBREAKF_CTRL_F)
272 case ERROR_NO_FREE_STORE:
273 ShowMessage (MSG_NO_FREE_STORE);
277 ShowMessage (MSG_BREAK);
288 if (Quit && GuiSwitches.AskExit)
289 if (!ShowRequestArgs (MSG_REALLY_QUIT_XMODULE, MSG_YES_OR_NO, NULL))
295 } /* End main loop */
302 /* Intuition Event Handler. Based on GadToolsBox's HandleIDCMP() */
303 GLOBALCALL void HandleIDCMP (void)
305 struct IntuiMessage *m;
308 struct WinUserData *wud;
310 while (m = GT_GetIMsg (WinPort))
312 IntuiMsg = *m; /* Make a local copy and return message immediately */
316 win = IntuiMsg.IDCMPWindow;
317 wud = (struct WinUserData *)win->UserData;
319 switch (IntuiMsg.Class)
321 case IDCMP_REFRESHWINDOW:
323 /* TODO: Handle multiple IDCMP_REFRESHWINDOW
324 * messages sent at the same time.
327 /* Lock Layer in sizeable windows so its size
328 * won't change until we are finished rendering
331 * Newsflash: **DON'T!** Layers BeginUpdate() will already
332 * lock the window layer for us, so doing it again we would
333 * risk a complete GUI deadlock in some particular conditions...
335 /* if (win->Flags & WFLG_SIZEGADGET)
336 * LockLayer (NULL, win->WLayer);
339 if (wud->WUDFlags & WUDF_JUSTRESIZED)
341 // RefreshGadgets (wud->GList, win, NULL);
342 GT_RefreshWindow (win, NULL);
343 RefreshWindowFrame (win);
346 RenderWindowBorders (wud);
348 wud->WUDFlags &= ~WUDF_JUSTRESIZED;
352 GT_BeginRefresh (win);
355 RenderWindowBorders (wud);
357 GT_EndRefresh (win, TRUE);
360 /* if (win->Flags & WFLG_SIZEGADGET)
361 * UnlockLayer (win->WLayer);
372 struct LayoutGadgetsArgs lga;
374 ULONG SpecialTags[20];
375 UWORD newwidth, newheight;
377 /* TODO: Handle multiple IDCMP_NEWSIZE
378 * messages sent at the same time.
381 // LockLayer (NULL, win->WLayer);
383 newwidth = win->Width - win->BorderLeft - win->BorderRight;
384 newheight = win->Height - win->BorderTop - win->BorderBottom;
386 if ((wud->WindowSize.Width == newwidth) &&
387 (wud->WindowSize.Height == newheight))
389 // UnlockLayer (win->WLayer);
393 if (!(wud->WUDFlags & WUDF_CUSTOMLAYOUT))
395 /* Detatch and free old gadgets */
396 RemoveGList (win, wud->GList, -1);
399 /* Clear old window region (or what remains of it) */
400 SetAPen (win->RPort, 0);
401 SetDrMd (win->RPort, JAM1);
402 RectFill (win->RPort, win->BorderLeft, win->BorderTop,
403 min (wud->WindowSize.Width, newwidth) + win->BorderLeft - 1,
404 min (wud->WindowSize.Height, newheight) + win->BorderTop - 1);
406 wud->WindowSize.Width = newwidth;
407 wud->WindowSize.Height = newheight;
413 SetFont (&rp, wud->Font);
415 if (!CreateContext (&wud->GList))
417 // UnlockLayer (win->WLayer);
422 lga.Args = wud->LayoutArgs;
423 lga.VInfo = VisualInfo;
424 lga.PrevGad = wud->GList;
425 lga.GInfo = wud->GInfo;
429 lga.SpecialTags = SpecialTags;
431 SpecialTags[0] = GT_Underscore;
432 SpecialTags[1] = (ULONG) '_';
434 g = CreateGadgets (&lga, LAYOUTMODE_V, OffX + lga.GInfo[0].LabelWidth + HSPACING, OffY + VSPACING,
435 wud->WindowSize.Width - lga.GInfo[0].LabelWidth - HSPACING * 2,
436 wud->WindowSize.Height - VSPACING * 2);
440 // UnlockLayer (win->WLayer);
445 AddGList (win, wud->GList, -1, -1, NULL);
446 wud->WUDFlags |= WUDF_JUSTRESIZED;
449 if (wud->IDCMPFunc) wud->IDCMPFunc (wud);
451 // UnlockLayer (win->WLayer);
455 case IDCMP_CLOSEWINDOW:
456 if (wud->WindowID == WID_TOOLBOX)
464 case IDCMP_GADGETDOWN:
466 struct Gadget *gad = (struct Gadget *)IntuiMsg.IAddress;
469 if (wud->GInfo[gad->GadgetID].GKind == CHECKBOX_KIND)
473 if (check = (WORD *)(wud->GInfo[gad->GadgetID].SpecialStorage))
477 /* Execute function */
478 if (((struct Gadget *)IntuiMsg.IAddress)->UserData)
479 ((void (*)(struct WinUserData *)) gad->UserData) (wud);
485 while (IntuiMsg.Code != MENUNULL)
487 n = ItemAddress (win->MenuStrip, IntuiMsg.Code);
488 ((void (*)(struct WinUserData *))(GTMENUITEM_USERDATA(n))) (wud);
490 /* Some window operations invalidate the menu
491 * we are working on. For istance, Re-opening a
492 * window causes the old MenuStrip to be killed.
493 * The DoNextSelect flag provides a way to stop
494 * this loop and avoid a nasty crash.
501 IntuiMsg.Code = n->NextSelect;
505 case IDCMP_INACTIVEWINDOW:
507 if (wud->IDCMPFunc) wud->IDCMPFunc (wud);
511 case IDCMP_GADGETHELP:
512 HandleHelp (&IntuiMsg);
516 if (wud->IDCMPFunc) wud->IDCMPFunc (wud);
519 } /* End switch (IntuiMsg.Class) */
523 } /* End while (GT_GetIMsg ()) */
528 static void HandleKey (void)
530 struct Window *win = IntuiMsg.IDCMPWindow;
531 struct WinUserData *wud = (struct WinUserData *)win->UserData;
536 /* Handle key up for buttons */
538 if (IntuiMsg.Code & IECODE_UP_PREFIX)
540 struct Gadget *gad = ActiveGad;
543 if (gad && (ActiveKey == (IntuiMsg.Code & ~IECODE_UP_PREFIX)))
544 ((void (*)(struct WinUserData *)) gad->UserData) (wud);
549 switch (IntuiMsg.Code)
551 case 0x5F: /* HELP */
552 HandleHelp (&IntuiMsg);
559 for (i = 0; i < wud->GCount; i++)
560 if (wud->GInfo[i].GKind == LISTVIEW_KIND)
562 struct Gadget *g = wud->Gadgets[i];
563 LONG selected, oldselected, top = ~0;
566 if (GadToolsBase->lib_Version < 39)
567 selected = (LONG)(*(UWORD *)(((char *)g)+sizeof(struct Gadget)+48));
568 /* top = *(short *)(((char *)gad) + sizeof(struct Gadget) + 6); +4 ? */
570 #endif /* !OS30_ONLY */
571 GT_GetGadgetAttrs (g, win, NULL,
572 GTLV_Selected, &selected,
576 selected = (LONG)((WORD) selected); /* Extend to long */
577 oldselected = selected; /* Make a backup of it */
580 selected = top; /* Scroll Top */
584 if (IntuiMsg.Code == CURSORUP)
586 if (IntuiMsg.Qualifier & IEQUALIFIER_SHIFT)
588 else if (IntuiMsg.Qualifier & IEQUALIFIER_ALT)
593 else /* CURSORDOWN */
595 if (IntuiMsg.Qualifier & IEQUALIFIER_SHIFT)
597 else if (IntuiMsg.Qualifier & IEQUALIFIER_ALT)
603 if (selected < 0) selected = 0;
605 GT_SetGadgetAttrs (g, win, NULL,
606 (top == ~0) ? GTLV_Selected : GTLV_Top, selected,
607 (top == ~0) ? GTLV_MakeVisible : TAG_IGNORE, selected,
611 if (GadToolsBase->lib_Version < 39)
612 selected = (LONG)(*(UWORD *)(((char *)g)+sizeof(struct Gadget)+48));
614 #endif /* !OS30_ONLY */
615 GT_GetGadgetAttrs (g, win, NULL,
616 GTLV_Selected, &selected,
619 if (selected != oldselected)
621 IntuiMsg.Code = selected;
623 ((void (*)(struct WinUserData *)) g->UserData) (wud);
624 break; /* Stop for() loop */
630 if (IntuiMsg.Qualifier & IEQUALIFIER_ALT)
632 struct WinUserData *nextwud;
634 if (IntuiMsg.Qualifier & IEQUALIFIER_SHIFT)
636 /* ALT+SHIFT+TAB: Cycle windows backwards */
638 nextwud = (struct WinUserData *)wud->Link.mln_Pred;
640 if (!(nextwud->Link.mln_Pred)) /* List head? */
641 nextwud = (struct WinUserData *)WindowList.lh_TailPred;
645 /* ALT+TAB: Cycle windows */
647 nextwud = (struct WinUserData *)wud->Link.mln_Succ;
649 if (!(nextwud->Link.mln_Succ)) /* List tail? */
650 nextwud = (struct WinUserData *)WindowList.lh_Head;
653 RevealWindow (nextwud);
660 } /* End switch (IntuiMsg.Code) */
663 /* Convert the IDCMP_RAWKEY IntuiMessage to the single
664 * character representation it corresponds to. If this isn't
665 * possible (e.g. a HELP key or cursor key) then abort.
668 static struct InputEvent ie;
670 ie.ie_NextEvent = NULL;
671 ie.ie_Class = IECLASS_RAWKEY;
673 ie.ie_Code = IntuiMsg.Code;
674 ie.ie_Qualifier = IntuiMsg.Qualifier & IEQUALIFIER_CONTROL; /* Filter qualifiers. */
675 ie.ie_EventAddress = (APTR *) *((ULONG *)IntuiMsg.IAddress);
676 if (MapRawKey (&ie, &keycode, 1, NULL) != 1)
681 /* Handle IDCMP_VANILLAKEY */
683 /* Check special keys */
686 case 0x03: /* CTRL-C */
687 Signal ((struct Task *)ThisTask, SIGBREAKF_CTRL_C);
691 case 0x0D: /* RETURN */
693 for (i = 0; i < wud->GCount; i++)
694 if (wud->GInfo[i].GKind == STRING_KIND || wud->GInfo[i].GKind == INTEGER_KIND)
695 ActivateGadget (wud->Gadgets[i],win, NULL);
699 if (wud->WindowID != WID_TOOLBOX)
708 /* Look for gadget shortcuts */
711 for (i = 0; i < wud->GCount; i++)
713 if (wud->Keys[i] == keycode) /* Case insensitive compare */
715 struct Gadget *g = wud->Gadgets[i];
716 LONG disabled = FALSE;
721 if (GadToolsBase->lib_Version < 39)
722 disabled = g->Flags & GFLG_DISABLED;
724 #endif /* !OS30_ONLY */
725 GT_GetGadgetAttrs (g, win, NULL,
726 GA_Disabled, &disabled,
729 if (disabled) break; /* Stop for() loop */
731 switch (wud->GInfo[i].GKind)
734 if (!(IntuiMsg.Qualifier & IEQUALIFIER_REPEAT))
735 SelectButton (win, g);
741 if (wud->GInfo[i].SpecialStorage)
742 *((UWORD *)wud->GInfo[i].SpecialStorage) ^= 1;
744 GT_SetGadgetAttrs (g, win, NULL,
745 GTCB_Checked, !(g->Flags & GFLG_SELECTED),
749 ((void (*)(struct WinUserData *)) g->UserData) (wud);
754 ActivateGadget (g, win, NULL);
759 if (GadToolsBase->lib_Version >= 39)
760 #endif /* !OS30_ONLY */
765 /* ON V37: active = *(short *)(((char *)gad) + sizeof(struct Gadget) + 6); */
767 GT_GetGadgetAttrs (g, win, NULL,
772 act = (LONG)((UWORD)act); /* Extend to LONG */
774 if (IntuiMsg.Qualifier & IEQUALIFIER_SHIFT)
779 for (max = 0; lab[max]; max++); /* Count labels */
781 if (act >= max) act = 0;
782 else if (act < 0) act = max - 1;
784 GT_SetGadgetAttrs (g, win, NULL,
791 ((void (*)(struct WinUserData *)) g->UserData) (wud);
801 if (GadToolsBase->lib_Version < 39)
802 act = (LONG)(*(UWORD *)(((char *)g)+sizeof(struct Gadget)+24)); /* 38? */
804 #endif /* !OS30_ONLY */
806 GT_GetGadgetAttrs (g, win, NULL,
809 act = (LONG)((UWORD)act); /* Extend to LONG */
812 if (IntuiMsg.Qualifier & IEQUALIFIER_SHIFT)
817 GT_SetGadgetAttrs (g, win, NULL,
822 if (GadToolsBase->lib_Version < 39)
823 act = (LONG)(*(UWORD *)(((char *)g)+sizeof(struct Gadget)+24));
825 #endif /* !OS30_ONLY */
827 GT_GetGadgetAttrs (g, win, NULL,
830 act = (LONG)((UWORD)act); /* Extend to LONG */
836 ((void (*)(struct WinUserData *)) g->UserData) (wud);
844 if (GadToolsBase->lib_Version >= 39)
845 #endif /* !OS30_ONLY */
847 LONG min, max, level;
849 GT_GetGadgetAttrs (g, win, NULL,
856 min = (LONG)((WORD)min);
857 max = (LONG)((WORD)max);
858 level = (LONG)((WORD)level);
860 if (IntuiMsg.Qualifier & IEQUALIFIER_SHIFT)
862 if (IntuiMsg.Qualifier & IEQUALIFIER_ALT)
868 if (IntuiMsg.Qualifier & IEQUALIFIER_ALT)
873 if (level > max) level = max;
874 if (level < min) level = min;
876 GT_SetGadgetAttrs (g, win, NULL,
882 IntuiMsg.Code = level;
883 ((void (*)(struct WinUserData *)) g->UserData) (wud);
892 return; /* Stop for() loop */
897 /* There is no apparent use for this key event,
898 * let's pass the IntuiMessage to user's IDCMPFunc()...
900 if (wud->IDCMPFunc) ((void (*)(void)) wud->IDCMPFunc) ();
905 static void SelectButton (struct Window *win, struct Gadget *gad)
907 /* Selects the button gadget <gad>. This operation is illegal with
908 * GadTools gadgets, but many programs do it anyway, so this trick
909 * will probably be supported in future OS releases :-).
914 if (ActiveGad) DeselectButton();
916 gadpos = RemoveGadget (win, gad);
918 gad->Flags |= GFLG_SELECTED;
919 AddGadget (win, gad, gadpos);
920 RefreshGList (gad, win, NULL, 1);
922 ActiveKey = IntuiMsg.Code;
929 static void DeselectButton (void)
931 /* Deselects the button previously selected with SelectButton() */
935 UWORD gadpos = RemoveGadget (ActiveWin, ActiveGad);
937 ActiveGad->Flags &= ~GFLG_SELECTED;
938 AddGadget (ActiveWin, ActiveGad, gadpos);
939 RefreshGList (ActiveGad, ActiveWin, NULL, 1);
947 GLOBALCALL void LockWindows (void)
949 /* Disable user input in all windows */
951 struct WinUserData *wud;
953 struct WindowLock *lock;
956 /* Are the windows already locked? */
958 if (WinLockCount > 1) return;
960 for (wud = (struct WinUserData *) WindowList.lh_Head;
962 wud = (struct WinUserData *)wud->Link.mln_Succ)
964 if (!(win = wud->Win)) continue;
966 /* Set wait pointer */
968 if (IntuitionBase->LibNode.lib_Version < 39)
969 SetPointer (win, WaitPointer, 16, 16, -6, 0);
971 #endif /* !OS30_ONLY */
972 SetWindowPointer (win, WA_BusyPointer, TRUE, TAG_DONE);
974 /* Do not block input in Progress window */
975 if (wud->WindowID == WID_PROGRESS) continue;
977 /* Set an invisible Requester in window to block user input.
978 * We allocate 4 more bytes after the requester structure to store
979 * the IDCMP flags before modifying them. MEMF_PUBLIC is used
980 * because intuition is going to process the Requester structure.
983 if (!(lock = AllocPooled (Pool, sizeof (struct WindowLock))))
986 InitRequester (&lock->Req);
987 lock->Req.Flags = SIMPLEREQ | NOREQBACKFILL;
989 /* Disable window resizing */
990 if (win->Flags & WFLG_SIZEGADGET)
992 lock->OldMinWidth = win->MinWidth;
993 lock->OldMinHeight = win->MinHeight;
994 lock->OldMaxWidth = win->MaxWidth;
995 lock->OldMaxHeight = win->MaxHeight;
996 WindowLimits (win, win->Width, win->Height,
997 win->Width, win->Height);
1000 /* Disable IDCMP messages except IDCMP_REFRESHWINDOW events.
1001 * WARNING: ModifyIDCMP (win, 0) would free the shared port!!
1003 lock->OldIDCMPFlags = win->IDCMPFlags;
1004 ModifyIDCMP (win, IDCMP_REFRESHWINDOW);
1006 Request (&lock->Req, win);
1012 GLOBALCALL void UnlockWindows (void)
1014 /* Restore user input in all windows. */
1016 struct WinUserData *wud;
1018 struct WindowLock *lock;
1020 /* Make sure windows arn't unlocked already */
1021 if (WinLockCount) return;
1023 /* Check lock nesting */
1025 if (WinLockCount) return;
1027 for (wud = (struct WinUserData *) WindowList.lh_Head;
1029 wud = (struct WinUserData *)wud->Link.mln_Succ)
1031 if (!(win = wud->Win)) continue;
1033 if (lock = (struct WindowLock *) win->FirstRequest)
1035 /* Restore old window IDCMP */
1036 ModifyIDCMP (win, lock->OldIDCMPFlags);
1038 /* Re-enable window sizing and restore old window limits */
1039 if (win->Flags & WFLG_SIZEGADGET)
1040 WindowLimits (win, lock->OldMinWidth, lock->OldMinHeight,
1041 lock->OldMaxWidth, lock->OldMaxHeight);
1043 EndRequest (&lock->Req, wud->Win);
1044 FreePooled (Pool, lock, sizeof (struct WindowLock));
1047 /* Restore standard pointer */
1049 if (IntuitionBase->LibNode.lib_Version < 39)
1052 #endif /* !OS30_ONLY */
1053 SetWindowPointer (win, TAG_DONE);
1059 GLOBALCALL void RevealWindow (struct WinUserData *wud)
1061 WindowToFront (wud->Win);
1062 ActivateWindow (wud->Win);
1064 /* Make the window visible on the screen */
1067 if (IntuitionBase->LibNode.lib_Version >= 39)
1068 #endif /* OS30_ONLY */
1069 ScreenPosition (Scr, SPOS_MAKEVISIBLE,
1070 wud->Win->LeftEdge, wud->Win->TopEdge,
1071 wud->Win->LeftEdge + wud->Win->Width - 1,
1072 wud->Win->TopEdge + wud->Win->Height - 1);
1077 GLOBALCALL void SetGadgets (struct WinUserData *wud, LONG arg, ...)
1079 /* Update status of gadgets in the window associated to <wud>.
1080 * <arg> is the first of a -1 terminated array of commands.
1081 * Each command is represented by a pair of LONGs, where the
1082 * first LONG is the gadget number, and the second is the value
1083 * to set for that gadget, depending on the gadget type.
1088 static ULONG actions[] =
1090 TAG_IGNORE, /* GENERIC_KIND */
1091 TAG_IGNORE, /* BUTTON_KIND */
1092 GTCB_Checked, /* CHECKBOX_KIND */
1093 GTIN_Number, /* INTEGER_KIND */
1094 GTLV_Selected, /* LISTVIEW_KIND */
1095 GTMX_Active, /* MX_KIND */
1096 GTNM_Number, /* NUMBER_KIND */
1097 GTCY_Active, /* CYCLE_KIND */
1098 GTPA_Color, /* PALETTE_KIND */
1099 TAG_IGNORE, /* SCROLLER_KIND */
1100 TAG_IGNORE, /* -- reserved -- */
1101 GTSL_Level, /* SLIDER_KIND */
1102 GTST_String, /* STRING_KIND */
1103 GTTX_Text /* TEXT_KIND */
1108 GT_SetGadgetAttrs (wud->Gadgets[*cmd], wud->Win, NULL,
1109 actions[wud->GInfo[*cmd].GKind], *(cmd+1),
1118 GLOBALCALL LONG AddListViewNode (struct List *lv, CONST_STRPTR label, ...)
1120 /* Var-args stub for AddListViewNodeA */
1122 return AddListViewNodeA (lv, label, (LONG *) (&label)+1);
1127 GLOBALCALL LONG AddListViewNodeA (struct List *lv, CONST_STRPTR label, LONG *args)
1129 /* Allocate and add a new node to a ListView list. The label
1130 * is printf()-formatted and copied to a buffer just after the
1131 * node structure. Call RemListViewNode() to deallocate the node.
1134 * 0 for failure (no memory), any other value for success.
1142 VSPrintf (buf, label, args);
1146 if (!(n = AllocVecPooled (Pool, sizeof (struct Node) + strlen (label) + 1)))
1149 n->ln_Name = ((UBYTE *)n) + sizeof (struct Node);
1151 strcpy (n->ln_Name, label);
1152 n->ln_Pri = 0; /* Selected */
1161 GLOBALCALL void RemListViewNode (struct Node *n)
1164 FreeVecPooled (Pool, n);
1170 GLOBALCALL struct Image *NewImageObject (ULONG which)
1172 /* Creates a sysiclass object. */
1174 return ((struct Image *)NewObject (NULL, SYSICLASS,
1175 SYSIA_DrawInfo, DrawInfo,
1177 SYSIA_Size, Scr->Flags & SCREENHIRES ? SYSISIZE_MEDRES : SYSISIZE_LOWRES,
1180 /* NB: SYSISIZE_HIRES not yet supported. */
1185 static struct Gadget *CreateVImageButton (struct TagItem *tags, struct NewGadget *ng)
1187 /* This routine is called by the layout engine to create an IMAGEBUTTON_KIND gadget. */
1189 struct Gadget *VButton;
1190 struct Image *VImage;
1194 if (VImageClass = InitVImageClass ())
1196 if (ButtonFrame = NewObject (NULL, FRAMEICLASS,
1197 IA_FrameType, FRAME_BUTTON,
1201 struct IBox FrameBox, ContentsBox = { 0, 0, 0, 0 };
1203 DoMethod ((Object *)ButtonFrame, IM_FRAMEBOX, &ContentsBox, &FrameBox, DrawInfo, 0);
1205 ButtonFrameWidth = FrameBox.Width;
1206 ButtonFrameHeight = FrameBox.Height;
1210 FreeVImageClass (VImageClass);
1218 if (!(VImage = (struct Image *)NewObject (VImageClass, NULL,
1219 IA_Width, ng->ng_Width - ButtonFrameWidth,
1220 IA_Height, ng->ng_Height - ButtonFrameHeight,
1221 SYSIA_Which, ng->ng_Flags,
1225 if (!(VButton = (struct Gadget *)NewObject (NULL, FRBUTTONCLASS,
1226 GA_ID, ng->ng_GadgetID,
1227 GA_UserData, ng->ng_UserData,
1228 GA_Left, ng->ng_LeftEdge,
1229 GA_Top, ng->ng_TopEdge,
1230 GA_Image, ButtonFrame,
1231 GA_LabelImage, VImage,
1234 DisposeObject (VImage);
1243 static void DeleteVImageButton (struct Gadget *g)
1247 DisposeObject (g->GadgetText);
1252 if (!VImageUseCount)
1256 DisposeObject (ButtonFrame);
1262 FreeVImageClass (VImageClass);
1271 /* Gadget definition format:
1273 * VGROUP_KIND, BorderType,
1274 * HGROUP_KIND, BorderType,
1275 * IMAGEBUTTON_KIND, ClickedFunction, ImageType, Tag1, ...,
1276 * CHECKBOX_KIND, ClickedFunction, Label, Storage (UWORD *), Tag1, ...,
1277 * BUTTON_KIND, ClickedFunction, Label, Tag1, ...,
1278 * INTEGER_KIND, ClickedFunction, Label, MaxDigits, Tag1, ...,
1279 * STRING_KIND, ClickedFunction, Label, MaxChars, Tag1, ...,
1280 * TEXT_KIND, Label, NumChars, Tag1, ...,
1281 * NUMBER_KIND, Label, MaxDigits, Tag1, ...,
1282 * LISTVIEW_KIND, ClickedFunction, Label, Labels (struct List *), Tag1, ...,
1283 * MX_KIND, ClickedFunction, Label, Labels (ULONG *), Tag1, ...,
1284 * CYCLE_KIND, ClickedFunction, Label, Labels (ULONG *), Tag1, ...,
1285 * SLIDER_KIND, ClickedFunction, Label, Min, Max, LevelFormat (UBYTE *), MaxLevelLen (ULONG), Tag1, ...,
1286 * PALETTE_KIND, ClickedFunction, Label, Tags,
1291 static void LayoutGadgets (struct LayoutGadgetsArgs *lga, UWORD mode)
1293 struct GInfo *ginfo,
1294 *myginfo = &lga->GInfo[lga->Count];
1298 /* Skip this group */
1301 if (mode == LAYOUTMODE_V)
1302 myginfo->Flags |= GIF_FIXEDWIDTH;
1304 myginfo->Flags |= GIF_FIXEDHEIGHT;
1306 while (*lga->Args != ENDGROUP_KIND)
1308 ginfo = &lga->GInfo[lga->Count];
1311 switch (ginfo->GKind = *lga->Args++)
1315 if (*lga->Args++) /* Border? */
1317 LayoutGadgets (lga, (ginfo->GKind == HGROUP_KIND) ? LAYOUTMODE_H : LAYOUTMODE_V);
1319 /* Add border dimensions to group size */
1320 ginfo->MinWidth += HSPACING * 8;
1321 ginfo->Fixed.Width += HSPACING * 8;
1322 ginfo->MinHeight += VSPACING * 8;
1323 ginfo->Fixed.Height += VSPACING * 8;
1324 ginfo->Flags |= GIF_HASBORDER;
1326 else LayoutGadgets (lga, (ginfo->GKind == HGROUP_KIND) ? LAYOUTMODE_H : LAYOUTMODE_V);
1329 case IMAGEBUTTON_KIND:
1330 lga->Args++; /* Skip Clicked function */
1331 lga->Args++; /* Skip Image */
1332 ginfo->MinWidth = lga->Wud->Font->tf_XSize * 3 + 2;
1333 ginfo->MinHeight = lga->Wud->Font->tf_YSize + 4;
1334 ginfo->Flags |= GIF_FIXEDWIDTH | GIF_FIXEDHEIGHT;
1338 lga->Args++; /* Skip Clicked function */
1339 label = STR(*lga->Args++);
1340 ginfo->SpecialStorage = (void *)*lga->Args++; /* Record storage */
1341 ginfo->MinWidth = lga->Wud->Font->tf_XSize * 2 + 8;
1342 ginfo->MinHeight = lga->Wud->Font->tf_YSize + 4;
1343 ginfo->LabelWidth = TextLength (lga->DummyRast, label, strlen (label)) + LABELSPACING;
1344 ginfo->Flags = GIF_FIXEDWIDTH | GIF_FIXEDHEIGHT;
1348 lga->Args++; /* Skip Clicked function */
1349 label = STR(*lga->Args++);
1350 ginfo->MinWidth = TextLength (lga->DummyRast, label, strlen (label)) + LABELSPACING;
1351 ginfo->MinHeight = lga->Wud->Font->tf_YSize + 4;
1352 ginfo->Flags = GIF_FIXEDHEIGHT;
1360 lga->Args++; /* Skip Clicked function */
1361 if (label = STR (*lga->Args++))
1362 ginfo->LabelWidth = TextLength (lga->DummyRast, label, strlen (label)) + LABELSPACING;
1364 maxchars = *lga->Args++;
1366 ginfo->MinWidth = lga->Wud->Font->tf_XSize * min (maxchars + 1, 8) + 12;
1367 ginfo->MinHeight = lga->Wud->Font->tf_YSize + 6;
1368 ginfo->Flags = GIF_FIXEDHEIGHT;
1374 lga->Args++; /* Skip Clicked function */
1375 ginfo->MinWidth = lga->Wud->Font->tf_XSize * 16 + 16;
1376 ginfo->MinHeight = lga->Wud->Font->tf_YSize * 4 + 4;
1377 if (label = STR (*lga->Args++))
1378 ginfo->LabelWidth = TextLength (lga->DummyRast, label, strlen (label)) + LABELSPACING;
1379 ginfo->SpecialStorage = (void *)*lga->Args++; /* Record List pointer */
1385 ULONG *labels, cnt = 0;
1388 lga->Args++; /* Skip Clicked function */
1390 if (label = STR(*lga->Args++))
1391 ginfo->LabelWidth = TextLength (lga->DummyRast, label, strlen (label)) + LABELSPACING;
1393 ginfo->MinWidth = ginfo->MinHeight = 0;
1398 labels = (ULONG *) *lga->Args++;
1399 while (labels[cnt]) cnt++;
1402 /* Allocate and fill-in MX/Cycle labels array */
1404 if (!ginfo->SpecialStorage)
1405 ginfo->SpecialStorage = AllocVecPooled (Pool, (cnt + 1) * sizeof (STRPTR));
1407 if (ginfo->SpecialStorage)
1411 for (i = 0; i < cnt; i++)
1413 /* Store localized label */
1414 ((STRPTR *)(ginfo->SpecialStorage))[i] = str = STR (labels[i]);
1416 /* Calculate maximum width */
1417 ginfo->MinWidth = max (ginfo->MinWidth, TextLength (lga->DummyRast, str, strlen (str)) + LABELSPACING);
1419 if (ginfo->GKind == MX_KIND)
1420 ginfo->MinHeight += lga->Wud->Font->tf_YSize + 2;
1423 /* Terminate labels array */
1424 ((STRPTR *)(ginfo->SpecialStorage))[i] = NULL;
1427 /* add width of radio button (or cycle image) */
1428 ginfo->MinWidth += lga->Wud->Font->tf_XSize * 2 + 4;
1430 if (ginfo->GKind == MX_KIND)
1431 ginfo->Flags = GIF_FIXEDWIDTH | GIF_FIXEDHEIGHT;
1434 ginfo->Flags = GIF_FIXEDHEIGHT;
1435 ginfo->MinHeight += lga->Wud->Font->tf_YSize + 4;
1444 if (label = STR (*lga->Args++))
1445 ginfo->LabelWidth = TextLength (lga->DummyRast, label, strlen (label)) + LABELSPACING;
1447 ginfo->MinWidth = lga->Wud->Font->tf_XSize * (*lga->Args++) + 8;
1448 ginfo->MinHeight = lga->Wud->Font->tf_YSize + 4;
1449 ginfo->Flags = GIF_FIXEDHEIGHT;
1453 lga->Args++; /* Skip Clicked function */
1455 if (label = STR (*lga->Args++))
1456 ginfo->LabelWidth = TextLength (lga->DummyRast, label, strlen (label)) + LABELSPACING;
1458 lga->Args += 3; /* Skip Min, Max and LevelFormat */
1460 if (ginfo->SpecialStorage = (APTR)((*lga->Args++) * lga->Wud->Font->tf_XSize))
1461 ginfo->SpecialStorage = (APTR) ((ULONG)ginfo->SpecialStorage + 4);
1463 ginfo->MinWidth = lga->Wud->Font->tf_XSize * 8 + 8 + (ULONG)ginfo->SpecialStorage;
1464 ginfo->MinHeight = lga->Wud->Font->tf_YSize;
1465 ginfo->Flags = GIF_FIXEDHEIGHT;
1469 lga->Args++; /* Skip Clicked function */
1471 if (label = STR (*lga->Args++))
1472 ginfo->LabelWidth = TextLength (lga->DummyRast, label, strlen (label)) + LABELSPACING;
1474 ginfo->MinWidth = lga->Wud->Font->tf_XSize * 6 + 8;
1475 ginfo->MinHeight = lga->Wud->Font->tf_YSize * 3 + 4;
1479 if ((ginfo->GKind != HGROUP_KIND) && (ginfo->GKind != VGROUP_KIND))
1483 /* Go to next gadget (ie: skip tags until TAG_END) */
1484 while (*lga->Args) lga->Args += 2;
1487 /* Look for the key equivalent of this gadget. */
1492 /* Found! Now store in the key array */
1493 lga->Wud->Keys[lga->Count] = *(++c) | (1<<5); /* Lower case */
1498 if (mode == LAYOUTMODE_V)
1500 myginfo->MinHeight += ginfo->MinHeight + VSPACING;
1501 if (ginfo->Flags & GIF_HASBORDER)
1502 myginfo->MinWidth = max (myginfo->MinWidth, ginfo->MinWidth + ginfo->LabelWidth);
1505 myginfo->MinWidth = max (myginfo->MinWidth, ginfo->MinWidth);
1506 myginfo->LabelWidth = max (myginfo->LabelWidth, ginfo->LabelWidth);
1509 myginfo->Fixed.Height += VSPACING;
1510 if (ginfo->Flags & GIF_FIXEDHEIGHT)
1511 myginfo->Fixed.Height += ginfo->MinHeight;
1512 if (!(ginfo->Flags & GIF_FIXEDWIDTH))
1513 myginfo->Flags &= ~GIF_FIXEDWIDTH;
1515 else /* LAYOUTMODE_H */
1517 myginfo->MinWidth += ginfo->MinWidth + ginfo->LabelWidth + HSPACING;
1518 myginfo->MinHeight = max (myginfo->MinHeight, ginfo->MinHeight);
1519 myginfo->Fixed.Width += ginfo->LabelWidth + HSPACING;
1520 if (ginfo->Flags & GIF_FIXEDWIDTH)
1521 myginfo->Fixed.Width += ginfo->MinWidth;
1522 if (!(ginfo->Flags & GIF_FIXEDHEIGHT))
1523 myginfo->Flags &= ~GIF_FIXEDHEIGHT;
1528 } /* End while (*lga->Args != ENDGROUP_KIND) */
1531 if (mode == LAYOUTMODE_H)
1533 /* Remove extra HSPACING after last child */
1534 myginfo->MinWidth -= HSPACING;
1535 myginfo->Fixed.Width -= HSPACING;
1537 if (!(myginfo->Flags & GIF_HASBORDER))
1539 /* Align first child of HGROUP_KIND with other
1540 * gadgets in our parent group
1542 myginfo->LabelWidth = (myginfo+1)->LabelWidth;
1543 (myginfo+1)->LabelWidth = 0;
1544 myginfo->MinWidth -= myginfo->LabelWidth;
1545 myginfo->Fixed.Width -= myginfo->LabelWidth;
1548 else /* LAYOUTMODE_V */
1550 /* Remove extra VSPACING after last child */
1551 myginfo->MinHeight -= VSPACING;
1552 myginfo->Fixed.Height -= VSPACING;
1555 if (myginfo->MinWidth <= myginfo->Fixed.Width)
1556 myginfo->Flags |= GIF_FIXEDWIDTH;
1557 if (myginfo->MinHeight <= myginfo->Fixed.Height)
1558 myginfo->Flags |= GIF_FIXEDHEIGHT;
1560 lga->Args++; /* Skip ENDGROUP_KIND */
1561 lga->Count--; /* Take back one position */
1566 static struct Gadget *CreateGadgets (struct LayoutGadgetsArgs *lga, UWORD mode, UWORD left, UWORD top, UWORD width, UWORD height)
1568 struct GInfo *ginfo,
1569 *myginfo = &lga->GInfo[lga->Count];
1570 struct TagItem *Tags, *tmp;
1572 struct NewGadget ng;
1576 /* Skip this group */
1580 while (*lga->Args != ENDGROUP_KIND)
1582 ginfo = &lga->GInfo[lga->Count];
1583 Tags = (struct TagItem *)lga->SpecialTags;
1587 ng.ng_TextAttr = lga->Wud->Attr;
1588 ng.ng_GadgetID = lga->Count;
1589 ng.ng_VisualInfo = lga->VInfo;
1590 ng.ng_Flags = PLACETEXT_LEFT;
1592 if (mode == LAYOUTMODE_V)
1594 if (ginfo->Flags & GIF_FIXEDWIDTH)
1595 ng.ng_Width = ginfo->MinWidth;
1597 ng.ng_Width = width - ((ginfo->Flags & GIF_HASBORDER) ? ginfo->LabelWidth : 0);
1599 if (ginfo->Flags & GIF_FIXEDHEIGHT)
1600 ng.ng_Height = ginfo->MinHeight;
1602 ng.ng_Height = (((ULONG)(height - myginfo->Fixed.Height)) * ((ULONG)ginfo->MinHeight)) / ((ULONG)(myginfo->MinHeight - myginfo->Fixed.Height));
1604 ng.ng_LeftEdge = left + ((ginfo->Flags & GIF_HASBORDER) ? ginfo->LabelWidth : 0);
1605 ng.ng_TopEdge = top;
1606 top = ng.ng_TopEdge + ng.ng_Height + VSPACING;
1608 else /* mode == LAYOUTMODE_H */
1610 if (ginfo->Flags & GIF_FIXEDWIDTH)
1611 ng.ng_Width = ginfo->MinWidth;
1613 ng.ng_Width = (((ULONG)(width - myginfo->Fixed.Width)) * ((ULONG)ginfo->MinWidth)) / ((ULONG)(myginfo->MinWidth - myginfo->Fixed.Width));
1615 if (ginfo->Flags & GIF_FIXEDHEIGHT)
1617 /* Vertical center */
1618 ng.ng_Height = ginfo->MinHeight;
1619 ng.ng_TopEdge = top + (height - ng.ng_Height) / 2;
1623 /* Vertical stretch */
1624 ng.ng_Height = height;
1625 ng.ng_TopEdge = top;
1628 ng.ng_LeftEdge = left + ginfo->LabelWidth;
1630 left = ng.ng_LeftEdge + ng.ng_Width + HSPACING;
1633 switch (ginfo->GKind = *lga->Args++)
1636 ng.ng_UserData = (void *)(*lga->Args++);
1637 lga->SpecialTags[stc++] = XMGAD_SetupFunc;
1638 lga->SpecialTags[stc++] = (*lga->Args++);
1642 case IMAGEBUTTON_KIND:
1643 ng.ng_UserData = (void *)(*lga->Args++);
1644 ng.ng_Flags = (*lga->Args++);
1645 ng.ng_GadgetText = NULL;
1646 lga->SpecialTags[stc++] = XMGAD_SetupFunc;
1647 lga->SpecialTags[stc++] = (ULONG)CreateVImageButton;
1656 if (bordertype = *lga->Args++)
1658 if (!CreateWindowBorder (lga->Wud, ng.ng_LeftEdge - ginfo->LabelWidth, ng.ng_TopEdge,
1659 ng.ng_Width + ginfo->LabelWidth, ng.ng_Height, bordertype))
1661 if (!CreateGadgets (lga, (ginfo->GKind == VGROUP_KIND) ? LAYOUTMODE_V : LAYOUTMODE_H,
1662 ng.ng_LeftEdge + HSPACING*4, ng.ng_TopEdge + VSPACING*4,
1663 ng.ng_Width - HSPACING*8, ng.ng_Height - VSPACING*8))
1666 else if (!CreateGadgets (lga, (ginfo->GKind == VGROUP_KIND) ? LAYOUTMODE_V : LAYOUTMODE_H,
1667 ng.ng_LeftEdge, ng.ng_TopEdge, ng.ng_Width, ng.ng_Height))
1675 ng.ng_UserData = (void *)(*lga->Args++);
1676 ng.ng_GadgetText = STR(*lga->Args++);
1677 ng.ng_Flags = PLACETEXT_IN;
1681 ng.ng_UserData = (void *)(*lga->Args++);
1682 ng.ng_GadgetText = STR(*lga->Args++);
1683 lga->Args++; /* Skip storage */
1685 lga->SpecialTags[stc++] = GTCB_Checked;
1686 lga->SpecialTags[stc++] = (ginfo->SpecialStorage ? (*((UWORD *)ginfo->SpecialStorage)) : NULL);
1687 lga->SpecialTags[stc++] = GTCB_Scaled;
1688 lga->SpecialTags[stc++] = TRUE;
1692 ng.ng_UserData = (void *)(*lga->Args++);
1693 ng.ng_GadgetText = STR(*lga->Args++);
1695 /* Editing in right-justified integer gadgets
1696 * is very uncomfortable!!
1698 * lga->SpecialTags[stc++] = STRINGA_Justification;
1699 * lga->SpecialTags[stc++] = GACT_STRINGRIGHT;
1701 lga->SpecialTags[stc++] = GTIN_MaxChars;
1702 lga->SpecialTags[stc++] = *lga->Args++;
1703 lga->SpecialTags[stc++] = STRINGA_ExitHelp;
1704 lga->SpecialTags[stc++] = TRUE;
1711 ng.ng_UserData = (void *)*lga->Args++;
1712 ng.ng_GadgetText = STR(*lga->Args++);
1714 lga->SpecialTags[stc++] = GTLV_ShowSelected;
1715 lga->SpecialTags[stc++] = NULL;
1717 if (l = (struct List *)*lga->Args++)
1719 lga->SpecialTags[stc++] = GTLV_Labels;
1720 lga->SpecialTags[stc++] = (ULONG)l;
1722 // l->lh_Type = 0; /* Selected Item */
1723 // l->l_pad = 0; /* Item Count */
1727 if (GadToolsBase->lib_Version < 39)
1729 #endif /* !OS30_ONLY */
1737 ng.ng_UserData = (void *)(*lga->Args++);
1738 ng.ng_GadgetText = STR(*lga->Args++);
1743 if (ginfo->GKind == MX_KIND)
1745 /* Special kludge: MX gadgets width and height refer to
1746 * one button instead of the whole gadget.
1748 ng.ng_Width = lga->Wud->Font->tf_XSize * 2;
1749 ng.ng_Height = lga->Wud->Font->tf_YSize;
1751 ng.ng_Flags = PLACETEXT_RIGHT;
1753 lga->SpecialTags[stc++] = GTMX_Labels;
1754 lga->SpecialTags[stc++] = (ULONG)ginfo->SpecialStorage;
1755 lga->SpecialTags[stc++] = GTMX_Scaled;
1756 lga->SpecialTags[stc++] = TRUE;
1757 lga->SpecialTags[stc++] = GTMX_Spacing;
1758 lga->SpecialTags[stc++] = 2;
1762 lga->SpecialTags[stc++] = GTCY_Labels;
1763 lga->SpecialTags[stc++] = (ULONG)ginfo->SpecialStorage;
1770 ng.ng_UserData = NULL;
1771 ng.ng_GadgetText = STR(*lga->Args++);
1773 lga->Args++; /* Skip NumDigits */
1775 lga->SpecialTags[stc++] = GTNM_Border;
1776 lga->SpecialTags[stc++] = TRUE;
1778 /* Under V39 and below, GTJ_RIGHT does not work properly. */
1779 if (GadToolsBase->lib_Version > 39)
1781 lga->SpecialTags[stc++] = GTNM_Justification;
1782 lga->SpecialTags[stc++] = GTJ_RIGHT;
1787 ng.ng_UserData = NULL;
1788 ng.ng_GadgetText = STR(*lga->Args++);
1790 lga->Args++; /* Skip NumDigits */
1794 ng.ng_UserData = (void *)(*lga->Args++);
1795 ng.ng_GadgetText = STR(*lga->Args++);
1797 lga->SpecialTags[stc++] = GTPA_IndicatorWidth;
1798 lga->SpecialTags[stc++] = ng.ng_Width / 8;
1802 ng.ng_UserData = (void *)(*lga->Args++);
1803 ng.ng_GadgetText = STR(*lga->Args++);
1805 lga->SpecialTags[stc++] = GTSC_Arrows;
1806 lga->SpecialTags[stc++] = lga->Wud->Font->tf_XSize + 4;
1810 /* ClassId = STRGCLASS;
1811 lga->SpecialTags[stc++] = GA_UserData;
1812 lga->SpecialTags[stc++] = *lga->Args++;
1813 lga->SpecialTags[stc++] = GA_LabelImage;
1814 lga->SpecialTags[stc++] = *lga->Args++;
1815 lga->SpecialTags[stc++] = STRINGA_MaxChars;
1816 lga->SpecialTags[stc++] = *lga->Args++;
1817 lga->SpecialTags[stc++] = GA_Border;
1818 lga->SpecialTags[stc++] = StringFrame;
1819 lga->SpecialTags[stc++] = STRINGA_ExitHelp;
1820 lga->SpecialTags[stc++] = TRUE;
1822 ng.ng_UserData = (void *)(*lga->Args++);
1823 ng.ng_GadgetText = STR(*lga->Args++);
1825 lga->SpecialTags[stc++] = GTST_MaxChars;
1826 lga->SpecialTags[stc++] = *lga->Args++;
1827 lga->SpecialTags[stc++] = STRINGA_ExitHelp;
1828 lga->SpecialTags[stc++] = TRUE;
1832 ng.ng_UserData = (void *)(*lga->Args++);
1833 ng.ng_GadgetText = STR(*lga->Args++);
1835 lga->SpecialTags[stc++] = GTSL_Min;
1836 lga->SpecialTags[stc++] = *lga->Args++;
1837 lga->SpecialTags[stc++] = GTSL_Max;
1838 lga->SpecialTags[stc++] = *lga->Args++;
1839 lga->SpecialTags[stc++] = GTSL_LevelFormat;
1840 lga->SpecialTags[stc++] = *lga->Args++;
1841 lga->SpecialTags[stc++] = GTSL_MaxLevelLen;
1842 lga->SpecialTags[stc++] = *lga->Args++;
1843 lga->SpecialTags[stc++] = GTSL_LevelPlace;
1844 lga->SpecialTags[stc++] = PLACETEXT_RIGHT;
1845 lga->SpecialTags[stc++] = GTSL_Justification;
1846 lga->SpecialTags[stc++] = GTJ_RIGHT;
1847 lga->SpecialTags[stc++] = GA_RelVerify;
1848 lga->SpecialTags[stc++] = TRUE;
1850 ng.ng_Width -= (ULONG)ginfo->SpecialStorage;
1854 if ((ginfo->GKind != HGROUP_KIND) && (ginfo->GKind != VGROUP_KIND))
1856 if (*lga->Args != TAG_DONE)
1859 lga->SpecialTags[stc++] = TAG_MORE;
1860 lga->SpecialTags[stc] = (ULONG) lga->Args;
1862 else lga->SpecialTags[stc] = TAG_DONE;
1865 /* Go to next gadget (ie: skip tags until TAG_END) */
1866 while (*lga->Args) lga->Args += 2;
1871 /* BOOPSI Gadget. Let SetupFunc() allocate the gadget for us */
1873 if (tmp = FindTagItem (XMGAD_SetupFunc, Tags))
1875 if (lga->PrevGad->NextGadget = ((struct Gadget * (*)(struct TagItem *, struct NewGadget *)) (tmp->ti_Data)) (Tags, &ng))
1876 /* Record it into the list */
1877 lga->Wud->Gadgets[lga->Count] = lga->PrevGad->NextGadget;
1886 /* Normal GadTools gadget */
1888 if (!(lga->Wud->Gadgets[lga->Count] = CreateGadgetA (ginfo->GKind, lga->PrevGad, &ng, Tags)))
1892 lga->PrevGad = lga->Wud->Gadgets[lga->Count];
1894 } /* End if (GKind != ?GROUP_KIND */
1896 lga->Count++; /* Go to next gadget */
1899 lga->Args++; /* Skip ENDGROUP_KIND */
1900 lga->Count--; /* Take back one position */
1902 return (lga->Wud->GList);
1907 static void RenderWindowBorders (struct WinUserData *wud)
1909 struct WindowBorder *border = wud->Borders;
1913 DrawBevelBox (wud->Win->RPort,
1914 border->Size.Left, border->Size.Top,
1915 border->Size.Width, border->Size.Height,
1916 GT_VisualInfo, VisualInfo,
1917 GTBB_Recessed, TRUE,
1918 GTBB_FrameType, border->Type,
1921 border = border->NextBorder;
1927 static struct WindowBorder *CreateWindowBorder (struct WinUserData *wud,
1928 UWORD left, UWORD top, UWORD width, UWORD height, ULONG bordertype)
1930 /* Creates new WindowBorder structure and links it to the WUD passed.
1931 * Will return NULL in case of failure.
1934 struct WindowBorder *border;
1936 if (!(border = AllocPooled (Pool, sizeof (struct WindowBorder))))
1939 /* Link this border struct in WUD */
1940 border->NextBorder = wud->Borders;
1941 wud->Borders = border;
1943 /* Fill in WindowBorder structure */
1944 border->Type = bordertype;
1945 border->Size.Left = left;
1946 border->Size.Top = top;
1947 border->Size.Width = width;
1948 border->Size.Height = height;
1955 static void DeleteGadgets (struct WinUserData *wud)
1957 FreeGadgets (wud->GList); wud->GList = NULL;
1963 for (i = 0; i < wud->GCount; i++)
1965 if (wud->Gadgets[i])
1967 switch (wud->GInfo[i].GKind)
1969 case IMAGEBUTTON_KIND:
1970 DeleteVImageButton (wud->Gadgets[i]);
1982 struct WindowBorder *border = wud->Borders, *nextborder;
1986 nextborder = border->NextBorder;
1987 FreePooled (Pool, border, sizeof (struct WindowBorder));
1989 while (border = nextborder);
1991 wud->Borders = NULL;
1997 struct WinUserData *CreateWUD (ULONG id)
1999 struct WinUserData *wud;
2000 struct WDescr *wdescr = &WDescr[id];
2003 /* Create a new WUD structure for this window */
2004 if (wud = CAllocPooled (Pool, sizeof (struct WinUserData)))
2009 wud->IDCMPFlags = IDCMP_RAWKEY | IDCMP_MENUHELP |
2010 IDCMP_GADGETHELP | IDCMP_INACTIVEWINDOW;
2011 wud->Flags = WFLG_DRAGBAR | WFLG_DEPTHGADGET;
2012 wud->Title = PrgName;
2014 /* Link WUD to windows list */
2015 ADDHEAD (&WindowList, (struct Node *)wud);
2017 if (wdescr->CreationTags)
2019 struct TagItem *tstate = wdescr->CreationTags,
2022 /* Read taglist arguments */
2024 while (tag = NextTagItem (&tstate))
2025 switch (tag->ti_Tag)
2028 wud->NewMenu = (struct NewMenu *)tag->ti_Data;
2031 case XMWIN_LayoutArgs:
2032 wud->LayoutArgs = (ULONG *)tag->ti_Data;
2036 wud->GCount = tag->ti_Data;
2040 wud->Title = STR(tag->ti_Data);
2043 case XMWIN_WindowFlags:
2044 wud->Flags |= tag->ti_Data;
2047 case XMWIN_IDCMPFlags:
2048 wud->IDCMPFlags |= tag->ti_Data;
2051 case XMWIN_IDCMPFunc:
2052 wud->IDCMPFunc = (void (*)()) tag->ti_Data;
2055 case XMWIN_DropIconFunc:
2056 wud->DropIcon = (void (*)()) tag->ti_Data;
2059 case XMWIN_LayoutFunc:
2060 wud->LayoutArgs = (ULONG *)tag->ti_Data;
2061 wud->WUDFlags |= WUDF_CUSTOMLAYOUT;
2064 case XMWIN_PreOpenFunc:
2065 wud->PreOpenFunc = (LONG (*)()) tag->ti_Data;
2068 case XMWIN_PostOpenFunc:
2069 wud->PostOpenFunc = (void (*)()) tag->ti_Data;
2072 case XMWIN_PreCloseFunc:
2073 wud->PreCloseFunc = (LONG (*)()) tag->ti_Data;
2076 case XMWIN_PostCloseFunc:
2077 wud->PostCloseFunc = (void (*)()) tag->ti_Data;
2080 case XMWIN_HelpNode:
2081 wud->HelpNode = (STRPTR) tag->ti_Data;
2084 case XMWIN_UserData:
2085 wud->UserData = (APTR) tag->ti_Data;
2088 case XMWIN_LayoutCleanup:
2089 wud->LayoutCleanupFunc = (void (*)()) tag->ti_Data;
2097 if (!CreateLayoutInfo (wud))
2109 static void DeleteWUD (struct WinUserData *wud)
2113 MyCloseWindow (wud);
2115 REMOVE ((struct Node *) wud);
2118 struct WDescr *wdescr = &WDescr[wud->WindowID];
2122 if (--wdescr->UseCnt)
2124 struct WinUserData *otherwud;
2126 /* Search for another wud with same ID and set it in WDescr... */
2128 for (otherwud = (struct WinUserData *)WindowList.lh_Head;
2129 otherwud->Link.mln_Succ;
2130 otherwud = (struct WinUserData *)otherwud->Link.mln_Succ)
2131 if (otherwud->WindowID == wud->WindowID)
2133 wdescr->Wud = otherwud;
2139 DeleteLayoutInfo (wud);
2141 FreePooled (Pool, wud, sizeof (struct WinUserData));
2147 static struct WinUserData *CreateLayoutInfo (struct WinUserData *wud)
2149 struct WDescr *wdescr = &WDescr[wud->WindowID];
2153 if (wud->Font = WindowFont)
2154 wud->Attr = &WindowAttr;
2157 wud->Font = TopazFont;
2158 wud->Attr = &TopazAttr;
2162 if (wud->LayoutArgs)
2166 /* Allocate Gadgets array */
2167 if (!(wud->Gadgets = CAllocPooled (Pool,
2168 wud->GCount * sizeof (struct Gadget *))))
2172 if (wud->WUDFlags & WUDF_CUSTOMLAYOUT)
2174 if (!(wud->GList = ((struct Gadget * (*)(struct WinUserData *))
2175 wud->LayoutArgs) (wud) ))
2178 else /* Use standard layout engine */
2180 struct LayoutGadgetsArgs lga;
2184 /* Layout Phase 1 */
2190 SetFont (&rp, wud->Font);
2192 lga.DummyRast = &rp;
2193 lga.Args = wud->LayoutArgs;
2197 /* Allocate Key shortcuts array */
2198 if (!(wud->Keys = CAllocPooled (Pool, wud->GCount)))
2201 /* Allocate GInfo array */
2202 if (!(wud->GInfo = lga.GInfo = CAllocPooled (Pool, sizeof (struct GInfo) * wud->GCount)))
2205 LayoutGadgets (&lga, LAYOUTMODE_V);
2207 if ((lga.GInfo[0].Flags & (GIF_FIXEDWIDTH | GIF_FIXEDHEIGHT)) != (GIF_FIXEDWIDTH | GIF_FIXEDHEIGHT))
2209 wud->Flags |= (WFLG_SIZEGADGET | WFLG_SIZEBBOTTOM);
2210 wud->IDCMPFlags |= IDCMP_NEWSIZE;
2213 /* Force minimum size */
2214 wud->WindowSize.Width = max (wud->WindowSize.Width, lga.GInfo[0].MinWidth + lga.GInfo[0].LabelWidth + HSPACING * 2);
2215 wud->WindowSize.Height = max (wud->WindowSize.Height, lga.GInfo[0].MinHeight + VSPACING * 2);
2218 /* Reuse previous GInfo array */
2219 lga.GInfo = wud->GInfo;
2222 /* Layout Phase 2 */
2224 ULONG SpecialTags[20];
2226 SpecialTags[0] = GT_Underscore;
2227 SpecialTags[1] = (ULONG) '_';
2229 if (!CreateContext (&wud->GList))
2232 lga.Args = wud->LayoutArgs;
2233 lga.VInfo = VisualInfo;
2234 lga.PrevGad = wud->GList;
2236 lga.SpecialTags = SpecialTags;
2238 if (!CreateGadgets (&lga, LAYOUTMODE_V, OffX + lga.GInfo[0].LabelWidth + HSPACING, OffY + VSPACING,
2239 wud->WindowSize.Width - lga.GInfo[0].LabelWidth - HSPACING * 2,
2240 wud->WindowSize.Height - VSPACING * 2))
2246 if (!(wdescr->Flags & XMWINF_LOCALEDONE))
2250 /* Localize the MenuStrip */
2251 struct NewMenu *nm = wud->NewMenu;
2253 while (nm->nm_Type != NM_END)
2255 if (nm->nm_Label != (STRPTR)NM_BARLABEL)
2256 nm->nm_Label = STR ((ULONG)nm->nm_Label);
2262 wdescr->Flags |= XMWINF_LOCALEDONE;
2266 if (wud->NewMenu && (!wud->MenuStrip))
2268 if (!(wud->MenuStrip = CreateMenusA (wud->NewMenu, NULL)))
2271 if (!(LayoutMenus (wud->MenuStrip, VisualInfo,
2272 GTMN_NewLookMenus, TRUE,
2278 /* Setup zoom size */
2280 if (wud->Flags & WFLG_SIZEGADGET)
2282 wud->WindowZoom.Left = 0;
2283 wud->WindowZoom.Top = 1;
2284 wud->WindowZoom.Width = Scr->Width;
2285 wud->WindowZoom.Height = Scr->Height;
2289 wud->WindowZoom.Left = wud->WindowSize.Left;
2290 wud->WindowZoom.Top = wud->WindowSize.Top;
2292 wud->WindowZoom.Width = TextLength (&Scr->RastPort, wud->Title,
2293 strlen (wud->Title)) + 80;
2295 wud->WindowZoom.Width = 80;
2296 wud->WindowZoom.Height = Scr->WBorTop + Scr->RastPort.TxHeight + 1;
2298 /* TODO: Under V39 specifying ~0,~0 as Zoom X,Y, intuition
2299 * will only size-zoom the window. Consider implementing it...
2308 GLOBALCALL void DeleteLayoutInfo (struct WinUserData *wud)
2312 DeleteGadgets (wud);
2314 if (wud->LayoutCleanupFunc)
2315 wud->LayoutCleanupFunc (wud);
2319 FreePooled (Pool, wud->Keys, wud->GCount);
2329 /* Free gadget associated resources */
2331 for (i = 0; i < wud->GCount; i++)
2333 if (wud->Gadgets[i])
2335 switch (wud->GInfo[i].GKind)
2339 FreeVecPooled (Pool, wud->GInfo[i].SpecialStorage);
2348 FreePooled (Pool, wud->Gadgets, wud->GCount * sizeof (struct Gadget *));
2349 wud->Gadgets = NULL;
2354 FreePooled (Pool, wud->GInfo, wud->GCount * sizeof (struct GInfo));
2360 FreeMenus (wud->MenuStrip);
2361 wud->MenuStrip = NULL;
2367 GLOBALCALL struct Window *NewWindow (ULONG id)
2369 /* Create a new window using the given Window ID. */
2371 struct WDescr *wdescr = &WDescr[id];
2372 struct WinUserData *wud;
2374 if (!Scr) return NULL;
2376 /* Some windows can not be opened multiple times */
2378 if (!(wud = wdescr->Wud) || (wdescr->Flags & XMWINF_OPENMULTI))
2380 if (!(wud = CreateWUD (id)))
2384 return MyOpenWindow (wud);
2389 GLOBALCALL struct Window *MyOpenWindow (struct WinUserData *wud)
2391 /* Open & setup a window using the given WinUserData structure. */
2392 /* This function is now OBSOLETE and should be merged with NewWindow() */
2394 if (!Scr) return NULL;
2396 if (wud->PreOpenFunc)
2397 if (wud->PreOpenFunc (wud))
2399 if (wud->PreCloseFunc) wud->PreCloseFunc (wud);
2409 if (!wud->Gadgets && wud->LayoutArgs)
2410 if (!CreateLayoutInfo (wud))
2414 /* Open the Window */
2416 if (wud->Win = OpenWindowTags (NULL,
2417 WA_Left, wud->WindowSize.Left,
2418 WA_Top, wud->WindowSize.Top,
2419 WA_InnerWidth, wud->WindowSize.Width,
2420 WA_InnerHeight, wud->WindowSize.Height,
2421 WA_Gadgets, wud->GList,
2422 WA_Title, wud->Title,
2423 WA_Flags, wud->Flags,
2424 WA_Zoom, &(wud->WindowZoom),
2426 WA_HelpGroup, UniqueID,
2427 /* Set user preferred refresh method unless this window
2428 * requests simple refresh explicitly.
2430 GuiSwitches.SmartRefresh ? WA_SmartRefresh : WA_SimpleRefresh, TRUE,
2431 WA_Activate, !ScreenReopening,
2433 /* Set minimum and maximum size according to the main gadget group
2436 (wud->Flags & WFLG_SIZEGADGET) ? WA_MinWidth : TAG_IGNORE,
2437 wud->GInfo ? (wud->GInfo[0].MinWidth + Scr->WBorLeft + Scr->WBorRight) : wud->WindowSize.Width,
2438 (wud->Flags & WFLG_SIZEGADGET) ? WA_MinHeight : TAG_IGNORE,
2439 wud->GInfo ? (wud->GInfo[0].MinHeight + Scr->WBorTop + Scr->WBorBottom + Scr->Font->ta_YSize + SizeHeight + 1) : wud->WindowSize.Height,
2440 /**/ (wud->Flags & WFLG_SIZEGADGET) ? WA_MaxWidth : TAG_IGNORE,
2441 wud->GInfo ? (wud->GInfo[0].Flags & GIF_FIXEDWIDTH ? 0 : -1) : -1,
2442 (wud->Flags & WFLG_SIZEGADGET) ? WA_MaxHeight : TAG_IGNORE,
2443 wud->GInfo ? (wud->GInfo[0].Flags & GIF_FIXEDHEIGHT ? wud->GInfo[0].MinHeight : -1) : -1,
2446 WA_ScreenTitle, (ULONG)Version+6,
2447 WA_AutoAdjust, TRUE,
2449 // WA_MouseQueue, 2,
2451 WA_NewLookMenus, TRUE,
2454 WDescr[wud->WindowID].CreationTags ? TAG_MORE : TAG_DONE, WDescr[wud->WindowID].CreationTags
2457 wud->Win->UserData = (BYTE *) wud;
2458 wud->Win->UserPort = WinPort;
2460 if (ModifyIDCMP (wud->Win, wud->IDCMPFlags))
2462 /* Set default font for this window */
2463 if (wud->Font) SetFont (wud->Win->RPort, wud->Font);
2465 if (wud->MenuStrip) SetMenuStrip (wud->Win, wud->MenuStrip);
2467 /* Do initial refresh */
2468 GT_RefreshWindow (wud->Win, NULL);
2469 RenderWindowBorders (wud);
2471 /* Make the window visible on the screen */
2472 if (!ScreenReopening
2474 && (IntuitionBase->LibNode.lib_Version >= 39)
2475 #endif /* !OS30_ONLY */
2477 ScreenPosition (Scr, SPOS_MAKEVISIBLE,
2478 wud->Win->LeftEdge, wud->Win->TopEdge,
2479 wud->Win->LeftEdge + wud->Win->Width - 1,
2480 wud->Win->TopEdge + wud->Win->Height - 1);
2482 /* Make it an AppWindow if it is requested */
2483 if (wud->DropIcon) AddAppWin (wud);
2485 if (wud->PostOpenFunc)
2486 wud->PostOpenFunc (wud);
2488 wud->WUDFlags &= ~WUDF_REOPENME;
2493 /* ClearMenuStrip() -- no need to call it... */
2494 CloseWindow (wud->Win); wud->Win = NULL;
2502 /* Close a window and all related resources */
2503 GLOBALCALL void MyCloseWindow (struct WinUserData *wud)
2505 struct Window *win = wud->Win;
2506 struct Requester *req;
2512 if (wud->PreCloseFunc)
2513 if (wud->PreCloseFunc (wud))
2516 /* Cleanup locked window */
2517 if (req = win->FirstRequest)
2519 EndRequest (req, win);
2520 FreePooled (Pool, req, sizeof (struct WindowLock));
2523 /* Remove AppWindow */
2524 if (wud->AppWin) RemAppWin (wud);
2527 /* Free MenuStrip */
2530 ClearMenuStrip (win);
2531 DoNextSelect = 0; /* Do not loop any more on this window's MenuStrip */
2534 /* Now remove any pending message from the shared IDCMP port */
2539 struct Message *msg = (struct Message *) win->UserPort->mp_MsgList.lh_Head;
2541 while (succ = msg->mn_Node.ln_Succ)
2543 if (((struct IntuiMessage *)msg)->IDCMPWindow == win)
2545 REMOVE ((struct Node *)msg);
2548 msg = (struct Message *) succ;
2551 win->UserPort = NULL; /* Keep intuition from freeing our port... */
2552 ModifyIDCMP (win, 0L); /* ...and from sending us any more messages. */
2557 /* Save Window position and clear window pointer */
2559 wud->WindowSize.Left = win->LeftEdge;
2560 wud->WindowSize.Top = win->TopEdge;
2562 if (win->Flags & WFLG_SIZEGADGET)
2564 wud->WindowSize.Width = win->Width - win->BorderLeft - win->BorderRight;
2565 wud->WindowSize.Height = win->Height - win->BorderTop - win->BorderBottom;
2568 CloseWindow (win); wud->Win = NULL;
2570 if (wud->PostCloseFunc)
2571 wud->PostCloseFunc (wud);
2575 { CloseFont (wud->Font); wud->Font = NULL; }
2577 if ((WDescr[wud->WindowID].Flags & XMWINF_OPENMULTI)
2578 && (WDescr[wud->WindowID].UseCnt > 1))
2584 GLOBALCALL void ReopenWindows (void)
2586 /* Reopen windows that were previously open */
2588 struct WinUserData *wud;
2590 ScreenReopening = TRUE;
2593 for (wud = (struct WinUserData *)WindowList.lh_Head; wud->Link.mln_Succ;
2594 wud = (struct WinUserData *)wud->Link.mln_Succ)
2596 if (wud->WUDFlags & WUDF_REOPENME)
2600 ScreenReopening = FALSE;
2605 GLOBALCALL LONG SetupScreen (void)
2607 struct Screen *DefScr;
2608 struct DrawInfo *DefDri;
2610 static LONG ExtraScreenTags[] =
2613 SA_FullPalette, TRUE,
2614 SA_SharePens, TRUE, /* These three Tags are valid only under
2615 SA_LikeWorkbench, TRUE, * V39 and are properly ignored by V37.
2616 SA_MinimizeISG, TRUE, */
2617 SA_Interleaved, TRUE,
2623 /* If screen is already open, pop it to front and activate
2626 ScreenToFront (Scr);
2627 if (ThisTask->pr_WindowPtr)
2628 RevealWindow ((struct WinUserData *)(((struct Window *)(ThisTask->pr_WindowPtr))->UserData));
2634 if (!(ScrollButtonClass = InitScrollButtonClass()))
2635 return ERROR_NO_FREE_STORE;
2638 /* Try the user selected Public Screen */
2640 if (!(Scr = LockPubScreen (ScrInfo.PubScreenName[0] ? ScrInfo.PubScreenName : NULL)))
2642 /* Try to open own screen */
2644 if (ScrInfo.DisplayID)
2646 static UWORD PensArray[1] = {(UWORD)~0};
2647 ULONG *ColorTable = NULL;
2649 struct ColorSpec *ColorSpec = NULL;
2650 #endif /* !OS30_ONLY */
2653 /* Color map translation */
2655 if (ScrInfo.OwnPalette)
2658 if (IntuitionBase->LibNode.lib_Version >= 39)
2660 #endif /* !OS30_ONLY */
2661 if (ColorTable = AllocPooled (Pool, ((32 * 3) + 2) * sizeof (LONG)))
2663 ULONG *col = ColorTable,
2668 for (i = 0; i < 32; i++)
2670 tmp = (ScrInfo.Colors[i] >> 16); /* Red */
2671 tmp |= tmp << 8 | tmp << 16 | tmp << 24;
2674 tmp = (ScrInfo.Colors[i] >> 8) & 0xFF; /* Green */
2675 tmp |= tmp << 8 | tmp << 16 | tmp << 24;
2678 tmp = ScrInfo.Colors[i] & 0xFF; /* Blue */
2679 tmp |= tmp << 8 | tmp << 16 | tmp << 24;
2689 if (ColorSpec = AllocPooled (Pool, 33 * sizeof (struct ColorSpec)))
2691 for (i = 0; i < 32; i++)
2693 ColorSpec[i].ColorIndex = i;
2694 ColorSpec[i].Red = ScrInfo.Colors[i] >> 20;
2695 ColorSpec[i].Green = ScrInfo.Colors[i] >> 12 & 0xF;
2696 ColorSpec[i].Blue = ScrInfo.Colors[i] >> 4 & 0xF;
2699 ColorSpec[i].ColorIndex = -1;
2703 #endif /* !OS30_ONLY */
2706 /* Use user requested attributes for screen */
2708 Scr = OpenScreenTags (NULL,
2709 SA_Width, ScrInfo.Width,
2710 SA_Height, ScrInfo.Height,
2711 SA_Depth, ScrInfo.Depth,
2712 SA_DisplayID, ScrInfo.DisplayID,
2713 SA_Overscan, ScrInfo.OverscanType,
2714 SA_AutoScroll, ScrInfo.AutoScroll,
2715 SA_Title, ScrInfo.PubScreenName,
2716 SA_PubName, ScrInfo.PubScreenName,
2717 SA_Font, ScreenAttr.ta_Name ? &ScreenAttr : NULL,
2719 ScrInfo.OwnPalette ?
2721 ((IntuitionBase->LibNode.lib_Version >= 39) ?
2722 SA_Colors32 : SA_Colors) : TAG_IGNORE,
2723 (IntuitionBase->LibNode.lib_Version >= 39) ?
2724 (ULONG)ColorTable : (ULONG)ColorSpec,
2726 SA_Colors32 : TAG_IGNORE, ColorTable,
2727 #endif /* !OS30_ONLY */
2729 TAG_MORE, ExtraScreenTags);
2731 if (ColorTable) FreePooled (Pool, ColorTable, ((32 * 3) + 2) * sizeof (LONG));
2733 if (ColorSpec) FreePooled (Pool, ColorSpec, 33 * sizeof (struct ColorSpec));
2734 #endif /* !OS30_ONLY */
2735 if (Scr) OwnScreen = TRUE;
2740 /* Try to clone the Default (Workbench) Screen */
2742 if (!(DefScr = LockPubScreen (NULL)))
2745 return ERROR_OBJECT_NOT_FOUND;
2748 DefDri = GetScreenDrawInfo (DefScr);
2750 if (Scr = OpenScreenTags (NULL,
2751 SA_Depth, DefDri->dri_Depth,
2752 SA_DisplayID, GetVPModeID (&DefScr->ViewPort),
2753 SA_Overscan, OSCAN_TEXT,
2754 SA_AutoScroll, TRUE,
2755 SA_Title, ScrInfo.PubScreenName,
2756 SA_PubName, ScrInfo.PubScreenName,
2757 SA_Pens, DefDri->dri_Pens,
2758 TAG_MORE, ExtraScreenTags))
2760 UnlockPubScreen (NULL, DefScr);
2766 FreeScreenDrawInfo (DefScr, DefDri);
2769 /* Make our screen really public */
2770 if (OwnScreen) PubScreenStatus (Scr, 0);
2773 if (!(VisualInfo = GetVisualInfoA (Scr, NULL)))
2776 return ERROR_NO_FREE_STORE;
2779 DrawInfo = GetScreenDrawInfo (Scr);
2781 OffX = Scr->WBorLeft;
2782 OffY = Scr->RastPort.TxHeight + Scr->WBorTop + 1;
2785 if (!WindowAttr.ta_Name) CopyTextAttrPooled (Pool, Scr->Font, &WindowAttr);
2786 if (!ListAttr.ta_Name) CopyTextAttrPooled (Pool, Scr->Font, &ListAttr);
2787 if (!EditorAttr.ta_Name) CopyTextAttrPooled (Pool, &TopazAttr, &EditorAttr);
2789 if (!(TopazFont = OpenFont (&TopazAttr)))
2791 CantOpenLib (TopazAttr.ta_Name, 0);
2793 return ERROR_NO_FREE_STORE;
2798 if (!(WindowFont = OpenDiskFont (&WindowAttr)))
2799 CantOpenLib (WindowAttr.ta_Name, 0);
2800 if (!(ListFont = OpenDiskFont (&WindowAttr)))
2801 CantOpenLib (ListAttr.ta_Name, 0);
2804 /* Setup windows shared Message Port */
2805 if (!(WinPort = CreateMsgPort()))
2808 return ERROR_NO_FREE_STORE;
2810 IDCMPSig = 1 << WinPort->mp_SigBit;
2811 Signals |= IDCMPSig;
2814 /* Create a SIZEIMAGE to get the correct size
2815 * and position for the slider and arrow buttons.
2818 struct Image *sizeimage;
2820 if (sizeimage = NewImageObject (SIZEIMAGE))
2822 SizeWidth = sizeimage->Width;
2823 SizeHeight = sizeimage->Height;
2824 DisposeObject (sizeimage);
2829 if (!NewWindow (WID_TOOLBOX))
2832 return ERROR_NO_FREE_STORE;
2835 /* Set Process Window pointer for DOS requesters */
2836 OldPrWindowPtr = ThisTask->pr_WindowPtr;
2837 ThisTask->pr_WindowPtr = WDescr[WID_TOOLBOX].Wud->Win;
2841 /* Bring screen to front in case it was hidden */
2842 ScreenToFront (Scr);
2849 GLOBALCALL void CloseDownScreen (void)
2851 /* Free screen and all associated resources */
2853 struct WinUserData *wud;
2857 ScreenShutdown = TRUE;
2859 /* Close AmigaGuide help window */
2865 /* Destroy all windows */
2866 while (!IsListEmpty (&WindowList))
2867 DeleteWUD ((struct WinUserData *)WindowList.lh_Head);
2871 /* Close all windows */
2872 for (wud = (struct WinUserData *)WindowList.lh_Head; wud->Link.mln_Succ;
2873 wud = (struct WinUserData *)wud->Link.mln_Succ)
2875 MyCloseWindow (wud);
2876 DeleteLayoutInfo (wud);
2877 wud->WUDFlags |= WUDF_REOPENME;
2884 Signals &= ~IDCMPSig;
2886 DeleteMsgPort (WinPort); WinPort = NULL;
2889 FreeScreenDrawInfo (Scr, DrawInfo); DrawInfo = NULL;
2890 FreeVisualInfo (VisualInfo); VisualInfo = NULL;
2894 /* TODO: Use BuildEasyRequest()/SysReqHandler() with SA_PubSig like IPrefs */
2896 while (!CloseScreen (Scr))
2897 ShowRequestArgs (MSG_CLOSE_ALL_WINDOWS, MSG_CONTINUE, NULL);
2899 else UnlockPubScreen (NULL, Scr);
2901 if (OldPrWindowPtr != (struct Window *)1L)
2903 ThisTask->pr_WindowPtr = OldPrWindowPtr;
2904 OldPrWindowPtr = (struct Window *)1L;
2909 CloseFont (WindowFont);
2915 CloseFont (ListFont);
2921 CloseFont (TopazFont);
2925 if (ScrollButtonClass)
2927 FreeScrollButtonClass (ScrollButtonClass);
2928 ScrollButtonClass = NULL;
2933 ScreenShutdown = FALSE;