Fix for a crash which happened when a document couldn't be opened.
[AROS-Contrib.git] / bgui / windowclass.c
blobb10a9fe38ae23df7d174a73234a15f46276ae641
1 /*
2 * @(#) $Header$
4 * BGUI library
5 * windowclass.c
7 * (C) Copyright 1998 Manuel Lemos.
8 * (C) Copyright 1996-1997 Ian J. Einman.
9 * (C) Copyright 1993-1996 Jaba Development.
10 * (C) Copyright 1993-1996 Jan van den Baard.
11 * All Rights Reserved.
13 * $Log$
14 * Revision 42.10 2004/06/16 20:16:48 verhaegs
15 * Use METHODPROTO, METHOD_END and REGFUNCPROTOn where needed.
17 * Revision 42.9 2003/01/18 19:10:03 chodorowski
18 * Instead of using the _AROS or __AROS preprocessor symbols, use __AROS__.
20 * Revision 42.8 2000/08/17 15:09:18 chodorowski
21 * Fixed compiler warnings.
23 * Revision 42.7 2000/08/10 17:52:47 stegerg
24 * temp fix for relayout refresh bug which only happens in AROS. temp. solved
25 * by doing a RefreshGList in windowclass.c/WindowClassRelease method.
27 * Revision 42.6 2000/07/10 16:35:49 stegerg
28 * bugfix: if a screen's size was smaller than it's OSCAN_TEXT overscan size
29 * then windows sometimes could not be created because of badly
30 * calculated coordinates.
32 * Revision 42.5 2000/07/07 17:11:50 stegerg
33 * had to change BASE_FINDKEY and GRM_WHICHOBJECT method calls
34 * for AROS (#ifdef), because of changed types in method structs
35 * (UWORD --> STACKUWORD, ...)
37 * Revision 42.4 2000/06/01 01:41:38 bergers
38 * Only 2 linker problems left: stch_l & stcu_d. Somebody might want to replace them (embraced by #ifdef __AROS__), please.
40 * Revision 42.3 2000/05/29 00:40:24 bergers
41 * Update to compile with AROS now. Should also still compile with SASC etc since I only made changes that test the define __AROS__. The compilation is still very noisy but it does the trick for the main directory. Maybe members of the BGUI team should also have a look at the compiler warnings because some could also cause problems on other systems... (Comparison always TRUE due to datatype (or something like that)). And please compile it on an Amiga to see whether it still works... Thanks.
43 * Revision 42.2 2000/05/15 19:27:03 stegerg
44 * another hundreds of REG() macro replacements in func headers/protos.
46 * Revision 42.1 2000/05/14 23:32:48 stegerg
47 * changed over 200 function headers which all use register
48 * parameters (oh boy ...), because the simple REG() macro
49 * doesn't work with AROS. And there are still hundreds
50 * of headers left to be fixed :(
52 * Many of these functions would also work with stack
53 * params, but since i have fixed every single one
54 * I encountered up to now, I guess will have to do
55 * the same for the rest.
57 * Revision 42.0 2000/05/09 22:10:42 mlemos
58 * Bumped to revision 42.0 before handing BGUI to AROS team
60 * Revision 41.11 2000/05/09 19:55:30 mlemos
61 * Merged with the branch Manuel_Lemos_fixes.
63 * Revision 41.10.2.14 2000/01/30 18:56:13 mlemos
64 * Fixed missing end tag when activating a gadget with the right or middle
65 * mouse buttons.
67 * Revision 41.10.2.13 1999/08/30 04:59:21 mlemos
68 * Added the WindowClassSetupGadget function to implement the
69 * WINDOW_SETUPGADGET method.
70 * Removed left out locale debugging statement.
72 * Revision 41.10.2.12 1999/07/28 21:04:17 mlemos
73 * Removed the RefreshWindowFrame call in WM_SECURE method because the it may
74 * cause deadlocks.
76 * Revision 41.10.2.11 1999/07/03 15:17:48 mlemos
77 * Replaced the calls to CallHookPkt to BGUI_CallHookPkt.
79 * Revision 41.10.2.10 1998/12/07 03:37:22 mlemos
80 * Fixed potential text font leak.
82 * Revision 41.10.2.9 1998/12/07 03:07:10 mlemos
83 * Replaced OpenFont and CloseFont calls by the respective BGUI debug macros.
85 * Revision 41.10.2.8 1998/11/16 20:02:28 mlemos
86 * Replaced FreeVec calls by BGUI_FreePoolMem calls.
88 * Revision 41.10.2.7 1998/09/20 22:26:31 mlemos
89 * Made a debugging statement using tprintfe use D(bug()) macro instead.
91 * Revision 41.10.2.6 1998/06/21 22:07:51 mlemos
92 * Ensured that the return code of OM_NEW is initialized just in case the
93 * master group object is NULL.
95 * Revision 41.10.2.5 1998/05/22 02:56:41 mlemos
96 * Ensured that any tooltips are closed with other relevant input events such
97 * as mouse and keyboard input.
99 * Revision 41.10.2.4 1998/04/28 14:03:07 mlemos
100 * Made WindowClass only consider IDCMP_INTUITICKS messages for tooltips.
102 * Revision 41.10.2.3 1998/04/28 02:29:34 mlemos
103 * Made HandleIDCMP method ignore IDCMP_IDCMPUPDATE messages when handling
104 * tooltips.
106 * Revision 41.10.2.2 1998/03/02 23:51:36 mlemos
107 * Switched vector allocation functions calls to BGUI allocation functions.
109 * Revision 41.10.2.1 1998/03/01 15:40:21 mlemos
110 * Added support to track BaseInfo memory leaks.
112 * Revision 41.10 1998/02/25 21:13:34 mlemos
113 * Bumping to 41.10
115 * Revision 1.1 1998/02/25 17:10:06 mlemos
116 * Ian sources
121 #define WW(x)
123 #include "include/classdefs.h"
126 * Tab-cycling.
128 typedef struct TabCycle {
129 struct TabCycle *tc_Next;
130 struct TabCycle *tc_Prev;
131 Object *tc_Object;
132 } TABCYCLE;
134 typedef struct {
135 TABCYCLE *cl_First;
136 TABCYCLE *cl_EndMark;
137 TABCYCLE *cl_Last;
138 } CYCLELIST;
141 * Update notification.
143 typedef struct UpdateN {
144 struct UpdateN *up_Next;
145 struct UpdateN *up_Prev;
146 ULONG up_ID;
147 Object *up_Target;
148 struct TagItem *up_MapList;
149 } UPN;
151 typedef struct {
152 UPN *ul_First;
153 UPN *ul_EndMark;
154 UPN *ul_Last;
155 } UPL;
158 * Object instance data.
160 typedef struct {
161 ULONG wd_Flags; /* see below */
162 struct Window *wd_WindowPtr; /* points to opened window */
163 struct Screen *wd_Screen; /* points to screen to use */
164 struct DrawInfo *wd_DrawInfo; /* the DrawInfo for this screen. */
165 UWORD wd_TextW, wd_TextH; /* Overscan dimensions. */
166 UBYTE *wd_WindowTitle; /* title of the window */
167 ULONG wd_WindowTitleID;
168 UBYTE *wd_ScreenTitle; /* active window screen title */
169 ULONG wd_ScreenTitleID;
170 UWORD wd_Position; /* positioning */
171 UWORD wd_WidthScale; /* width percentage from remaining width */
172 UWORD wd_HeightScale; /* height percentage from remaining height */
173 struct MsgPort *wd_UserPort; /* shared/normal window user port */
174 struct Menu *wd_Menus; /* created menu strip */
175 APTR wd_VisualInfo; /* visual info for menu strip */
176 struct NewMenu *wd_MenuStrip; /* points to NewMenu array */
177 UWORD wd_SizeW, wd_SizeH; /* size gadget dimensions */
178 UWORD wd_CloseW; /* close gadget width */
179 UWORD wd_DepthW; /* depth gadget width */
180 UWORD wd_ZoomW; /* zoom gadget width */
181 Object *wd_Gadgets; /* window master group */
182 UWORD wd_MasterW, wd_MasterH; /* master group sizes. */
183 Object *wd_LBorder; /* left-border group. */
184 UWORD wd_LWidth, wd_LHeight;
185 Object *wd_TBorder; /* top-border group. */
186 UWORD wd_TWidth, wd_THeight;
187 Object *wd_RBorder; /* right-border group. */
188 UWORD wd_RWidth, wd_RHeight;
189 Object *wd_BBorder; /* bottom-border group. */
190 UWORD wd_BWidth, wd_BHeight;
191 UWORD wd_Left; /* window border sizes. */
192 UWORD wd_Right;
193 UWORD wd_Top;
194 UWORD wd_Bottom;
195 WORD wd_Zoom[4]; /* WINDOW_TitleZip size. */
196 UWORD wd_MinW, wd_MinH; /* Minimum sizes. */
197 UWORD wd_MaxW, wd_MaxH; /* Maximum sizes. */
198 struct Screen *wd_PubScreen; /* points to pub screen to use. */
199 APTR wd_Lock; /* IDCMP lock */
200 struct IBox wd_FixedPos; /* pos. and size after change */
201 struct IBox wd_RelPos; /* box for relative positioning */
202 UBYTE *wd_PubScreenName; /* points to pubscreen name */
203 ULONG wd_WindowFlags; /* WFLG_xxxx */
204 ULONG wd_IDCMPFlags; /* IDCMP_xxxx */
205 ULONG wd_SleepCnt; /* sleep nest counter */
206 struct Hook *wd_HelpHook; /* help hook */
207 UBYTE *wd_HelpFile; /* amigaguide file */
208 UBYTE *wd_HelpNode; /* amigaguide node */
209 ULONG wd_HelpLine; /* amigaguide line */
210 UBYTE *wd_HelpText; /* help text */
211 ULONG wd_HelpTextID;
212 struct Hook *wd_IDCMPHook; /* IDCMP hook */
213 struct Hook *wd_VerifyHook; /* IDCMP_VERIFY hook */
214 ULONG wd_IDCMPHookBits; /* bits to trigger IDCMP hook */
215 ULONG wd_VerifyHookBits; /* bits to trigger IDCMP_VERIFY hook */
216 struct TextAttr *wd_Font; /* font to use */
217 struct TextAttr *wd_FallBackFont; /* font to fall back to if the above fails */
218 struct TextAttr *wd_MenuFont; /* font to use for the menus. */
219 struct TextFont *wd_UsedFont; /* Currently used default font. */
220 struct TextFont *wd_OrigFont; /* Original window font. */
221 CYCLELIST wd_CycleList; /* tab-cycling list */
222 UWORD wd_NextSelect; /* menu drag-selections */
223 UPL wd_UpdateList; /* list of update notification objects */
224 ULONG wd_ID; /* unique window ID */
225 struct MsgPort *wd_AppPort; /* appwindow message port */
226 struct AppWindow *wd_AppWindow; /* appwindow */
227 UWORD wd_OW, wd_OH; /* to check for a size change. */
228 struct Hook *wd_ToolTipHook; /* Custom tooltip hook. */
229 ULONG wd_ToolTicks; /* Ticks passed without mouse move. */
230 WORD wd_ToolX, wd_ToolY; /* mouse position for tool tip. */
231 ULONG wd_ToolTickTime; /* ticks to delay before showing tool tip. */
232 APTR wd_ToolTip; /* Current tool-tip. */
233 Object *wd_ToolTipObject; /* Current tool-tip object. */
234 struct Region *wd_Region; /* Clip Region. */
235 struct RastPort *wd_BufferRP; /* Buffer rastport. */
236 struct Layer *wd_BufferLayer; /* Buffer layer. */
237 UWORD wd_BRW, wd_BRH; /* Buffer rasport's size. */
238 struct bguiLocale *wd_Locale; /* Localize automatically. */
239 UBYTE *wd_Catalog; /* Catalog name. */
240 Object *wd_DGMObject; /* For sending GoActive messages. */
241 } WD;
243 #define WDF_SHARED_MSGPORT (1<<0) /* window user port is shared */
244 #define WDF_SCREEN_LOCKED (1<<1) /* we have locked a screen */
245 #define WDF_LOCK_WIDTH (1<<2) /* window width is fixed */
246 #define WDF_LOCK_HEIGHT (1<<3) /* window height is fixed */
247 #define WDF_CHANGE_VALID (1<<4) /* window FixedPos is valid */
248 #define WDF_RELBOX (1<<5) /* window is placed relative to IBox */
249 #define WDF_DRAGSELECT (1<<6) /* we are in a menu drag-select */
250 #define WDF_IS_APPWINDOW (1<<7) /* we are an AppWindow */
251 #define WDF_NO_BUFFER (1<<8) /* don't use a buffer rastport */
252 #define WDF_AUTOASPECT (1<<9) /* auto set frame thickness. */
253 #define WDF_CLOSEONESC (1<<10) /* close window when ESC is pressed. */
254 #define WDF_SHOWTITLE (1<<11) /* show screen title. */
255 #define WDF_REMOVED (1<<12) /* master gadget manually removed. */
256 #define WDF_USERTICKS (1<<13) /* user set IDCMP_INTUITICKS. */
257 #define WDF_LOCKOUT (1<<14) /* ignore all IDCMP. */
258 #define WDF_TITLEZIP (1<<15) /* Preferences zip style. */
259 #define WDF_AUTOKEYLABEL (1<<16) /* Call BASE_KEYLABEL automatically? */
260 #define WDF_FREELOCALE (1<<17) /* Call BASE_KEYLABEL automatically? */
261 #define WDF_CONSTRAINTS (1<<18) /* We have new constraints pending. */
262 #define WDF_PREBUFFER (1<<19) /* Should we render before we open? */
264 * For PackBoolTags().
266 STATIC struct TagItem boolTags[] = {
267 { WINDOW_LockWidth, WDF_LOCK_WIDTH },
268 { WINDOW_LockHeight, WDF_LOCK_HEIGHT },
269 { WINDOW_NoBufferRP, WDF_NO_BUFFER },
270 { WINDOW_PreBufferRP, WDF_PREBUFFER },
271 { WINDOW_AutoAspect, WDF_AUTOASPECT },
272 { WINDOW_CloseOnEsc, WDF_CLOSEONESC },
273 { WINDOW_ShowTitle, WDF_SHOWTITLE },
274 { WINDOW_AppWindow, WDF_IS_APPWINDOW },
275 { WINDOW_TitleZip, WDF_TITLEZIP },
276 { WINDOW_AutoKeyLabel, WDF_AUTOKEYLABEL },
277 { TAG_END }
280 STATIC struct TagItem boolTags1[] = {
281 { WINDOW_DragBar, WFLG_DRAGBAR },
282 { WINDOW_SizeGadget, WFLG_SIZEGADGET },
283 { WINDOW_CloseGadget, WFLG_CLOSEGADGET },
284 { WINDOW_DepthGadget, WFLG_DEPTHGADGET },
285 { WINDOW_SizeBottom, WFLG_SIZEBBOTTOM },
286 { WINDOW_SizeRight, WFLG_SIZEBRIGHT },
287 { WINDOW_Activate, WFLG_ACTIVATE },
288 { WINDOW_RMBTrap, WFLG_RMBTRAP },
289 { WINDOW_ReportMouse, WFLG_REPORTMOUSE },
290 { WINDOW_Borderless, WFLG_BORDERLESS },
291 { WINDOW_Backdrop, WFLG_BACKDROP },
292 { TAG_END }
295 static Class *WindowClass = NULL;
298 * Make a private copy of the NewMenu array.
300 STATIC BOOL CopyNewMenuArray( WD *wd, struct NewMenu *array )
302 struct NewMenu *ptr = array;
303 ULONG num = 0;
306 * Menu array OK?
308 if ( ! array )
309 return( TRUE );
312 * Count the number of NewMenu
313 * structure in the array.
315 while (ptr->nm_Type != NM_END)
317 num++;
318 ptr++;
322 * Include the NM_END.
324 num++;
327 * Allocate a private copy.
329 if (( wd->wd_MenuStrip = ( struct NewMenu * )BGUI_AllocPoolMem( num * sizeof( struct NewMenu )))) {
331 * Copy the array.
333 CopyMem(( void * )array, ( void * )wd->wd_MenuStrip, num * sizeof( struct NewMenu ));
334 return( TRUE );
336 return( FALSE );
340 * Find out the minumum dimensions.
342 STATIC IPTR GroupDimensions(WD *wd, Object *master, struct TextAttr *font, UWORD *minw, UWORD *minh)
344 struct TextFont *tf = NULL;
345 struct RastPort rp;
346 IPTR rc = 0;
347 struct GadgetInfo gi;
350 * Initialize the RastPort.
352 InitRastPort(&rp);
355 * Setup the font.
357 if (font)
359 if ((tf = BGUI_OpenFont(font))) FSetFont(&rp, tf);
360 else return 0;
362 DoSetMethodNG(master, BT_TextAttr, font, TAG_END);
365 if (wd)
368 * Setup fake GadgetInfo (used for the DrawInfo).
370 bzero(&gi, sizeof(gi));
371 gi.gi_RastPort = &rp;
372 gi.gi_Screen = wd->wd_Screen;
373 gi.gi_DrInfo = wd->wd_DrawInfo;
374 gi.gi_Pens.DetailPen = wd->wd_DrawInfo->dri_Pens[DETAILPEN];
375 gi.gi_Pens.BlockPen = wd->wd_DrawInfo->dri_Pens[BLOCKPEN];
378 * Send the message.
380 rc = AsmDoMethod(master, GRM_DIMENSIONS, &gi, &rp, minw, minh, 0);
384 * Close font when opened.
386 if (tf) BGUI_CloseFont(tf);
388 return rc;
393 * Back-filling hook. This hook makes sure that the window background is
394 * always BACKGROUNDPEN. The hook will only fill the areas that have grown
395 * because of a re-size and the right and bottom border of the window in it's
396 * previous position if the size has grown.
398 //STATIC SAVEDS ASM VOID BackFill_func(REG(a0) struct Hook *hook, REG(a2) struct RastPort *rp, REG(a1) BFINFO *info)
399 STATIC SAVEDS ASM REGFUNC3(VOID, BackFill_func,
400 REGPARAM(A0, struct Hook *, hook),
401 REGPARAM(A2, struct RastPort *, rp),
402 REGPARAM(A1, BFINFO *, info))
404 struct Layer *save_layer;
405 struct Window *w = NULL;
406 struct BaseInfo *bi;
409 * Do not disturb the previous window contents. When the area to fill is located in the previous GUI area
410 * we do not back fill. This makes sure the previous GUI remains visible until it is overwritten by the
411 * resized GUI.
413 if (info->bf_Layer) w = info->bf_Layer->Window;
415 if (!w || (info->bf_X > w->BorderLeft) || (info->bf_Y > w->BorderTop))
418 * NO LAYER!
420 save_layer = rp->Layer;
421 rp->Layer = NULL;
423 #ifdef DEBUG_BGUI
424 if ((bi = AllocBaseInfoDebug(__FILE__,__LINE__,BI_RastPort, rp, TAG_DONE)))
425 #else
426 if ((bi = AllocBaseInfo(BI_RastPort, rp, TAG_DONE)))
427 #endif
430 * Setup the rastport.
432 BSetDrMd(bi, JAM1);
433 BSetDPenA(bi, BACKGROUNDPEN);
436 * Fill the area.
438 BRectFillA(bi, &info->bf_Rect);
440 FreeBaseInfo(bi);
442 rp->Layer = save_layer;
445 return;
447 REGFUNC_END
449 STATIC struct Hook BackFill_hook = { {NULL, NULL}, (HOOKFUNC)BackFill_func, NULL, NULL };
452 * Set attributes.
454 STATIC METHOD(WindowClassSetUpdate, struct opSet *, ops)
456 WD *wd = INST_DATA(cl, obj);
457 struct TagItem *tstate = ops->ops_AttrList;
458 struct TagItem *tag;
459 struct Window *w = wd->wd_WindowPtr;
460 IPTR data;
463 * Set attributes.
465 while ((tag = NextTagItem(&tstate)))
467 data = tag->ti_Data;
469 switch (tag->ti_Tag)
471 case WINDOW_Screen:
472 if (!w) wd->wd_Screen = (struct Screen *)data;
473 break;
475 case WINDOW_PubScreen:
476 if (!w) wd->wd_PubScreen = (struct Screen *)data;
477 break;
479 case WINDOW_PubScreenName:
480 if (!w) wd->wd_PubScreenName = (UBYTE *)data;
481 break;
483 case WINDOW_Locale:
484 if (wd->wd_Locale && (wd->wd_Flags & WDF_FREELOCALE))
486 CloseLocale(wd->wd_Locale->bl_Locale);
487 CloseCatalog(wd->wd_Locale->bl_Catalog);
488 BGUI_FreePoolMem(wd->wd_Locale);
490 wd->wd_Catalog = NULL;
491 wd->wd_Locale = (struct bguiLocale *)data;
492 wd->wd_Flags &= ~WDF_FREELOCALE;
493 break;
495 case WINDOW_Catalog:
496 if (LocaleBase == NULL) break;
498 if (wd->wd_Locale && wd->wd_Catalog)
500 CloseLocale(wd->wd_Locale->bl_Locale);
501 CloseCatalog(wd->wd_Locale->bl_Catalog);
502 if (data == 0)
504 BGUI_FreePoolMem(wd->wd_Locale);
505 wd->wd_Locale = NULL;
506 wd->wd_Catalog = NULL;
507 break;
510 else
512 if((wd->wd_Locale = BGUI_AllocPoolMem(sizeof(struct bguiLocale))))
513 memset(wd->wd_Locale,0,sizeof(struct bguiLocale));
514 wd->wd_Flags |= WDF_FREELOCALE;
516 if (wd->wd_Locale)
518 wd->wd_Catalog = (UBYTE *)data;
519 wd->wd_Locale->bl_Locale = OpenLocale(NULL);
520 wd->wd_Locale->bl_Catalog = OpenCatalogA(NULL, wd->wd_Catalog, NULL);
522 break;
524 case WINDOW_Title:
525 wd->wd_WindowTitle = (UBYTE *)data;
526 if (w && !(wd->wd_Flags & WFLG_BORDERLESS))
528 SetWindowTitles(w, wd->wd_WindowTitle, (UBYTE *)~0);
530 * Notify the target when necessary.
532 DoNotifyMethod(obj, NULL, 0, tag->ti_Tag, data, TAG_END);
534 break;
536 case WINDOW_ScreenTitle:
537 wd->wd_ScreenTitle = (UBYTE *)data;
538 if (w)
540 SetWindowTitles(w, (UBYTE *)~0, wd->wd_ScreenTitle);
542 * Notify the target when necessary.
544 DoNotifyMethod(obj, NULL, 0, tag->ti_Tag, data, TAG_END);
546 break;
548 case WINDOW_ToolTicks:
549 wd->wd_ToolTickTime = data;
550 wd->wd_ToolTicks = 0;
552 if (wd->wd_ToolTickTime) wd->wd_IDCMPFlags |= IDCMP_INTUITICKS;
553 else
555 if (!(wd->wd_Flags & WDF_USERTICKS))
556 wd->wd_IDCMPFlags &= ~IDCMP_INTUITICKS;
558 if (w) ModifyIDCMP(w, wd->wd_IDCMPFlags);
559 break;
561 case WINDOW_Bounds:
562 if (data)
564 if (w)
566 ChangeWindowBox(w, IBOX(data)->Left, IBOX(data)->Top,
567 IBOX(data)->Width, IBOX(data)->Height);
569 else
571 wd->wd_FixedPos = *IBOX(data);
572 wd->wd_Flags |= WDF_CHANGE_VALID;
575 else
576 wd->wd_Flags &= ~WDF_CHANGE_VALID;
577 break;
579 case WINDOW_CloseOnEsc:
580 if (data) wd->wd_Flags |= WDF_CLOSEONESC;
581 else wd->wd_Flags &= ~WDF_CLOSEONESC;
582 break;
584 case WINDOW_NoVerify:
585 if (w)
587 if (data) ModifyIDCMP(w, wd->wd_IDCMPFlags & ~IDCMP_SIZEVERIFY);
588 else ModifyIDCMP(w, wd->wd_IDCMPFlags);
590 break;
592 case WINDOW_MenuFont:
593 wd->wd_MenuFont = (struct TextAttr *)data;
594 if (w && wd->wd_Menus)
596 ClearMenuStrip(w);
597 if ((!wd->wd_MenuFont) || (!LayoutMenus(wd->wd_Menus, wd->wd_VisualInfo,
598 GTMN_NewLookMenus, TRUE, GTMN_TextAttr, wd->wd_MenuFont, TAG_DONE)))
600 LayoutMenus(wd->wd_Menus, wd->wd_VisualInfo, GTMN_NewLookMenus, TRUE, TAG_END);
602 SetMenuStrip(w, wd->wd_Menus);
604 break;
606 case WINDOW_SharedPort:
607 if (!w)
609 if ((wd->wd_UserPort = (struct MsgPort *)data))
610 wd->wd_Flags |= WDF_SHARED_MSGPORT;
611 else
612 wd->wd_Flags &= ~WDF_SHARED_MSGPORT;
614 break;
618 case WINDOW_TitleID:
619 wd->wd_WindowTitleID = data;
620 break;
622 case WINDOW_ScreenTitleID:
623 wd->wd_ScreenTitleID = data;
624 break;
626 case WINDOW_HelpFile:
627 wd->wd_HelpFile = (UBYTE *)data;
628 break;
630 case WINDOW_HelpNode:
631 wd->wd_HelpNode = (UBYTE *)data;
632 break;
634 case WINDOW_HelpLine:
635 wd->wd_HelpLine = data;
636 break;
638 case WINDOW_HelpText:
639 wd->wd_HelpText = (UBYTE *)data;
640 break;
642 case WINDOW_HelpTextID:
643 wd->wd_HelpTextID = data;
644 break;
646 case WINDOW_IDCMPHook:
647 wd->wd_IDCMPHook = (struct Hook *)data;
648 break;
650 case WINDOW_VerifyHook:
651 wd->wd_VerifyHook = (struct Hook *)data;
652 break;
654 case WINDOW_IDCMPHookBits:
655 wd->wd_IDCMPHookBits = data;
656 break;
658 case WINDOW_VerifyHookBits:
659 wd->wd_VerifyHookBits = data;
660 break;
662 case WINDOW_Position:
663 wd->wd_Position = data;
664 break;
666 case WINDOW_ScaleWidth:
667 wd->wd_WidthScale = data;
668 break;
670 case WINDOW_ScaleHeight:
671 wd->wd_HeightScale = data;
672 break;
674 case WINDOW_Font:
675 wd->wd_Font = (struct TextAttr *)data;
676 break;
678 case WINDOW_FallBackFont:
679 wd->wd_FallBackFont = (struct TextAttr *)data;
680 break;
682 case WINDOW_UniqueID:
683 wd->wd_ID = data;
684 break;
687 return (IPTR)TRUE;
689 METHOD_END
691 /// OM_NEW
693 * Create a shiny new object.
695 STATIC METHOD(WindowClassNew, struct opSet *, ops)
697 WD *wd;
698 IPTR rc=0;
699 IPTR data;
700 ULONG idcmp;
701 struct TagItem *tstate;
702 struct TagItem *tag, *tags;
703 BOOL fail = FALSE;
705 Object *master, *lborder, *tborder, *rborder, *bborder;
707 tags = DefTagList(BGUI_WINDOW_OBJECT, ops->ops_AttrList);
709 master = (Object *)GetTagData(WINDOW_MasterGroup, 0, tags);
710 lborder = (Object *)GetTagData(WINDOW_LBorderGroup, 0, tags);
711 tborder = (Object *)GetTagData(WINDOW_TBorderGroup, 0, tags);
712 rborder = (Object *)GetTagData(WINDOW_RBorderGroup, 0, tags);
713 bborder = (Object *)GetTagData(WINDOW_BBorderGroup, 0, tags);
716 * For now we do not work without a master group.
720 * First we let the superclass setup an object.
722 if (master && (rc = NewSuperObject(cl, obj, tags)))
725 * Get the instance data.
727 wd = INST_DATA(cl, rc);
729 wd->wd_Gadgets = master;
730 wd->wd_LBorder = lborder;
731 wd->wd_TBorder = tborder;
732 wd->wd_RBorder = rborder;
733 wd->wd_BBorder = bborder;
735 wd->wd_DGMObject = BGUI_NewObjectA(BGUI_DGM_OBJECT, NULL);
736 wd->wd_Region = NewRegion();
739 * Initialize cycle/update lists.
741 NewList((struct List *)&wd->wd_CycleList);
742 NewList((struct List *)&wd->wd_UpdateList);
745 * Setup defaults.
747 wd->wd_Position = POS_CENTERSCREEN;
748 wd->wd_FallBackFont = &Topaz80;
749 wd->wd_ToolX = wd->wd_ToolY = -1;
750 wd->wd_Zoom[0] = wd->wd_Zoom[1] = -1;
753 * Pack user boolean tags with predefined defaults.
755 wd->wd_WindowFlags = PackBoolTags(WFLG_DRAGBAR | WFLG_SIZEGADGET | WFLG_CLOSEGADGET | WFLG_DEPTHGADGET |
756 WFLG_ACTIVATE | WFLG_NOCAREREFRESH | WFLG_SIZEBBOTTOM | WFLG_REPORTMOUSE |
757 WFLG_NEWLOOKMENUS, tags, boolTags1);
760 * Simple refresh?
762 if (!GetTagData(WINDOW_SmartRefresh, FALSE, tags)) wd->wd_WindowFlags |= WFLG_SIMPLE_REFRESH;
764 idcmp = IDCMP_RAWKEY|IDCMP_GADGETUP|IDCMP_CHANGEWINDOW|IDCMP_INACTIVEWINDOW|IDCMP_ACTIVEWINDOW|
765 IDCMP_IDCMPUPDATE|IDCMP_SIZEVERIFY|IDCMP_NEWSIZE|IDCMP_MOUSEMOVE|IDCMP_MOUSEBUTTONS|IDCMP_MENUHELP;
768 * Obtain all necessary window data.
770 tstate = tags;
771 while ((tag = NextTagItem(&tstate)))
773 data = tag->ti_Data;
775 switch (tag->ti_Tag)
777 case WINDOW_MenuStrip:
778 if (!wd->wd_MenuStrip)
780 if (!CopyNewMenuArray(wd, (struct NewMenu *)data)) fail = TRUE;
782 break;
784 case WINDOW_IDCMP:
785 wd->wd_IDCMPFlags = data;
786 if (data & IDCMP_INTUITICKS) wd->wd_Flags |= WDF_USERTICKS;
787 break;
789 case WINDOW_PosRelBox:
790 wd->wd_RelPos = *IBOX(data);
791 wd->wd_Flags |= WDF_RELBOX;
792 break;
795 AsmCoerceMethod(cl, (Object *)rc, OM_SET, tags, NULL);
797 if (!fail)
800 * Disable all system gadgets and bordergroups when this
801 * is a backdrop or borderless window.
803 if (wd->wd_WindowFlags & (WFLG_BORDERLESS|WFLG_BACKDROP))
805 wd->wd_WindowFlags &= ~(WFLG_SIZEGADGET|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|WFLG_DRAGBAR);
806 wd->wd_WindowFlags |= WFLG_BORDERLESS;
807 wd->wd_WindowTitle = NULL;
811 * Pickup the other boolean tags.
813 wd->wd_Flags = PackBoolTags(wd->wd_Flags, tags, boolTags);
816 * Pack some IDCMP flags.
818 if (wd->wd_WindowFlags & WFLG_CLOSEGADGET) idcmp |= IDCMP_CLOSEWINDOW;
819 if (wd->wd_MenuStrip) idcmp |= IDCMP_MENUPICK;
821 wd->wd_IDCMPFlags |= idcmp;
823 if (wd->wd_Locale) AsmDoMethod((Object *)rc, BASE_LOCALIZE, wd->wd_Locale);
824 if (wd->wd_Flags & WDF_AUTOKEYLABEL) AsmDoMethod((Object *)rc, BASE_KEYLABEL);
826 DoSetMethodNG(wd->wd_Gadgets, GROUP_IsMaster, TRUE, BT_Buffer, TRUE, TAG_DONE);
828 DoMultiSet(BT_ParentWindow, rc, 5, master, lborder, tborder, rborder, bborder);
830 if (lborder) DoSetMethodNG(lborder, GA_LeftBorder, TRUE, TAG_DONE);
831 if (rborder) DoSetMethodNG(rborder, GA_RightBorder, TRUE, TAG_DONE);
832 if (tborder) DoSetMethodNG(tborder, GA_TopBorder, TRUE, TAG_DONE);
833 if (bborder) DoSetMethodNG(bborder, GA_BottomBorder, TRUE, TAG_DONE);
835 else
837 AsmCoerceMethod(cl, (Object *)rc, OM_DISPOSE);
838 rc = 0;
841 if (!rc)
844 * If the window object cannot be created we
845 * dispose of the master group and border groups.
847 if (master) AsmDoMethod(master, OM_DISPOSE);
848 if (lborder) AsmDoMethod(lborder, OM_DISPOSE);
849 if (tborder) AsmDoMethod(tborder, OM_DISPOSE);
850 if (rborder) AsmDoMethod(rborder, OM_DISPOSE);
851 if (bborder) AsmDoMethod(bborder, OM_DISPOSE);
853 FreeTagItems(tags);
855 return rc;
857 METHOD_END
859 /// OM_DISPOSE
861 * Get rid of an object.
863 STATIC METHOD(WindowClassDispose, Msg, msg)
865 WD *wd = INST_DATA(cl, obj);
866 TABCYCLE *tc;
867 UPN *up;
870 * When the window is open we close it.
872 if (wd->wd_WindowPtr)
873 AsmDoMethod(obj, WM_CLOSE);
875 if (wd->wd_Locale && wd->wd_Catalog)
877 CloseLocale(wd->wd_Locale->bl_Locale);
878 CloseCatalog(wd->wd_Locale->bl_Catalog);
880 if (wd->wd_Flags & WDF_FREELOCALE)
881 BGUI_FreePoolMem(wd->wd_Locale);
884 if (wd->wd_DGMObject)
886 DisposeObject(wd->wd_DGMObject);
889 if (wd->wd_Region)
891 DisposeRegion(wd->wd_Region);
895 * Remove and delete the tab-cycle list.
897 while ((tc = (TABCYCLE *)RemHead((struct List *)&wd->wd_CycleList)))
898 BGUI_FreePoolMem(tc);
901 * Remove and delete all update targets.
903 while ((up = (UPN *)RemHead((struct List *)&wd->wd_UpdateList)))
904 BGUI_FreePoolMem(up);
907 * Free the NewMenu array.
909 if (wd->wd_MenuStrip)
910 BGUI_FreePoolMem(wd->wd_MenuStrip);
913 * Dispose of the master group and
914 * border groups.
916 if (wd->wd_Gadgets) AsmDoMethod(wd->wd_Gadgets, OM_DISPOSE);
917 if (wd->wd_LBorder) AsmDoMethod(wd->wd_LBorder, OM_DISPOSE);
918 if (wd->wd_RBorder) AsmDoMethod(wd->wd_RBorder, OM_DISPOSE);
919 if (wd->wd_BBorder) AsmDoMethod(wd->wd_BBorder, OM_DISPOSE);
920 if (wd->wd_TBorder) AsmDoMethod(wd->wd_TBorder, OM_DISPOSE);
922 if(wd->wd_UsedFont)
924 BGUI_CloseFont(wd->wd_UsedFont);
925 wd->wd_UsedFont=NULL;
928 * The superclass takes care of the rest.
930 return AsmDoSuperMethodA(cl, obj, msg);
932 METHOD_END
935 * Setup the menu strip.
937 STATIC ASM BOOL DoMenuStrip( REG(a0) WD *wd, REG(a1) struct Screen *scr )
940 * Get the visual info. (We use
941 * gadtools for the menus.)
943 if ((wd->wd_VisualInfo = GetVisualInfo( scr, TAG_END ))) {
945 * Create the menu-strip.
947 if ((wd->wd_Menus = CreateMenus( wd->wd_MenuStrip, TAG_END ))) {
949 * Layout the menu strip.
951 if ( LayoutMenus( wd->wd_Menus, wd->wd_VisualInfo, GTMN_NewLookMenus, TRUE, wd->wd_MenuFont ? GTMN_TextAttr : TAG_IGNORE, wd->wd_MenuFont, TAG_END ))
952 return( TRUE );
954 * Everything below this point means failure.
956 FreeMenus( wd->wd_Menus );
957 wd->wd_Menus = NULL;
959 FreeVisualInfo( wd->wd_VisualInfo );
960 wd->wd_VisualInfo = NULL;
962 return( FALSE );
966 * Kill the AppWindow stuff.
968 STATIC ASM VOID KillAppWindow(REG(a0) WD *wd)
970 struct Message *msg;
973 * Remove the AppWindow.
975 if (wd->wd_AppWindow)
977 RemoveAppWindow(wd->wd_AppWindow);
978 wd->wd_AppWindow = NULL;
982 * Do we have a message port?
984 if (wd->wd_AppPort)
987 * Kill all remaining messages and the port.
989 while ((msg = GetMsg(wd->wd_AppPort)))
990 ReplyMsg(msg);
992 DeleteMsgPort(wd->wd_AppPort);
993 wd->wd_AppPort = NULL;
998 * Make it an AppWindow.
1000 STATIC ASM BOOL MakeAppWindow(REG(a0) WD *wd)
1003 * Create a message port.
1005 if ((wd->wd_AppPort = CreateMsgPort()))
1008 * Create the app window.
1010 if ((wd->wd_AppWindow = AddAppWindowA(0, 0, wd->wd_WindowPtr, wd->wd_AppPort, NULL)))
1011 return TRUE;
1013 KillAppWindow(wd);
1015 return FALSE;
1019 * Compute width and height of the
1020 * system gadgets.
1022 STATIC ASM VOID SystemSize(REG(a1) WD *wd)
1024 struct TagItem tags[4];
1025 Object *image;
1026 BOOL hires = wd->wd_Screen->Flags & SCREENHIRES;
1029 * Set DrawInfo and resolution.
1031 tags[0].ti_Tag = SYSIA_Which;
1032 tags[1].ti_Tag = SYSIA_DrawInfo;
1033 tags[1].ti_Data = (IPTR)wd->wd_DrawInfo;
1034 tags[2].ti_Tag = SYSIA_Size;
1035 tags[2].ti_Data = hires ? SYSISIZE_MEDRES : SYSISIZE_LOWRES;
1036 tags[3].ti_Tag = TAG_DONE;
1039 * Sizing image.
1041 tags[0].ti_Data = SIZEIMAGE;
1042 if ((image = NewObjectA(NULL, SYSICLASS, tags)))
1044 wd->wd_SizeW = IM_BOX(image)->Width;
1045 wd->wd_SizeH = IM_BOX(image)->Height;
1046 DisposeObject(image);
1048 else
1050 wd->wd_SizeW = hires ? 18 : 13;
1051 wd->wd_SizeH = hires ? 10 : 11;
1055 * Close image.
1057 tags[0].ti_Data = CLOSEIMAGE;
1058 if ((image = NewObjectA(NULL, SYSICLASS, tags)))
1060 wd->wd_CloseW = IM_BOX(image)->Width;
1061 DisposeObject(image);
1063 else
1064 wd->wd_CloseW = hires ? 20 : 15;
1067 * Depth image.
1069 tags[0].ti_Data = DEPTHIMAGE;
1070 if ((image = NewObjectA(NULL, SYSICLASS, tags)))
1072 wd->wd_DepthW = IM_BOX(image)->Width;
1073 DisposeObject(image);
1075 else
1076 wd->wd_DepthW = hires ? 24 : 18;
1079 * Zoom image.
1081 tags[0].ti_Data = ZOOMIMAGE;
1082 if ((image = NewObjectA(NULL, SYSICLASS, tags)))
1084 wd->wd_ZoomW = IM_BOX(image)->Width;
1085 DisposeObject(image);
1087 else
1088 wd->wd_ZoomW = hires ? 24 : 18;
1092 * Query border sizes.
1094 STATIC ASM void WBorderSize(REG(a0) WD *wd, REG(a1) struct Screen *scr, REG(a2) struct TextAttr *at)
1096 UWORD wl, wt, wr, wb;
1099 * Borders available?
1101 if (!(wd->wd_WindowFlags & WFLG_BORDERLESS))
1104 * Default border sizes.
1106 wt = scr->WBorTop + scr->Font->ta_YSize + 1;
1107 wl = scr->WBorLeft;
1108 wr = scr->WBorRight;
1109 wb = scr->WBorBottom;
1112 * Get system gadget dimensions.
1114 SystemSize(wd);
1117 * Adjust for sizing gadget.
1119 if (wd->wd_WindowFlags & WFLG_SIZEGADGET)
1122 * Bottom border size gadget?
1124 if (wd->wd_WindowFlags & WFLG_SIZEBBOTTOM) wb = wd->wd_SizeH;
1125 else wr = wd->wd_SizeW;
1128 * Right border size gadget?
1130 if (wd->wd_WindowFlags & WFLG_SIZEBRIGHT) wr = wd->wd_SizeW;
1134 * Adjust for border groups.
1136 if (wd->wd_LBorder)
1138 GroupDimensions(wd, wd->wd_LBorder, at, &wd->wd_LWidth, &wd->wd_LHeight);
1139 if (wd->wd_LWidth > wl) wl = wd->wd_LWidth;
1142 if (wd->wd_TBorder)
1144 GroupDimensions(wd, wd->wd_TBorder, at, &wd->wd_TWidth, &wd->wd_THeight);
1145 if (wd->wd_THeight > wt) wt = wd->wd_THeight;
1148 if (wd->wd_RBorder)
1150 GroupDimensions(wd, wd->wd_RBorder, at, &wd->wd_RWidth, &wd->wd_RHeight);
1151 if (wd->wd_RWidth > wr) wr = wd->wd_RWidth;
1154 if (wd->wd_BBorder)
1156 GroupDimensions(wd, wd->wd_BBorder, at, &wd->wd_BWidth, &wd->wd_BHeight);
1157 if (wd->wd_BHeight > wb) wb = wd->wd_BHeight;
1161 * Set them.
1163 wd->wd_Left = wl;
1164 wd->wd_Top = wt;
1165 wd->wd_Right = wr;
1166 wd->wd_Bottom = wb;
1167 } else
1169 * No borders.
1171 wd->wd_Left = wd->wd_Top = wd->wd_Right = wd->wd_Bottom = 0;
1174 BOOL WinSize(WD *wd, UWORD *win_w, UWORD *win_h)
1176 struct TextAttr *font;
1177 BOOL thin;
1179 struct Screen *scr = wd->wd_Screen;
1181 UWORD gmw, gmh;
1182 int bw, bh, gx, gy, t1, t2;
1184 int sw = scr->Width;
1185 int sh = scr->Height;
1187 int vw = wd->wd_TextW;
1188 int vh = wd->wd_TextH;
1190 if (wd->wd_UsedFont)
1192 BGUI_CloseFont(wd->wd_UsedFont);
1193 wd->wd_UsedFont = NULL;
1197 * The screen can be smaller than the TEXT
1198 * overscan sizes. Check if this is the case.
1200 if (vw > sw) vw = sw;
1201 if (vh > sh) vh = sh;
1204 * Setup aspect dependant framing and the
1205 * window object.
1207 if (wd->wd_Flags & WDF_AUTOASPECT)
1210 * Guess aspect ratio.
1212 thin = ((wd->wd_DrawInfo->dri_Resolution.X / wd->wd_DrawInfo->dri_Resolution.Y) <= 1);
1214 DoMultiSet(FRM_ThinFrame, thin, 5, wd->wd_Gadgets, wd->wd_LBorder, wd->wd_TBorder, wd->wd_RBorder, wd->wd_BBorder);
1218 * Pick up the font to use. This will either
1219 * be the font specified with WINDOW_Font or
1220 * the screen font.
1222 font = wd->wd_Font ? wd->wd_Font : scr->Font;
1225 * When the window has grown too big for the font, the
1226 * recomputation using the fallback font will start here.
1228 reCalc:
1231 * Ask the master group to compute its
1232 * absolute minimum dimension.
1234 GroupDimensions(wd, wd->wd_Gadgets, font, (UWORD *)&gmw, (UWORD *)&gmh);
1237 * Save these.
1239 wd->wd_MasterW = gmw;
1240 wd->wd_MasterH = gmh;
1243 * Borderless windows, and backdrop for that matter,
1244 * have no borders and system gadgets so this part
1245 * of the computation can be skipped.
1247 if (!(wd->wd_WindowFlags & WFLG_BORDERLESS))
1250 * Compute border sizes.
1252 WBorderSize(wd, scr, font);
1255 * Compute totals of border gadgets.
1257 bw = wd->wd_Left + wd->wd_Right;
1258 bh = wd->wd_Top + wd->wd_Bottom;
1261 * Add the minimum window border sizes.
1263 gmw += bw;
1264 gmh += bh;
1267 * Check to see if any of the border groups
1268 * have a larger minimum width or height than
1269 * the current window size.
1271 if (wd->wd_LBorder)
1273 t1 = wd->wd_LHeight + wd->wd_Top + wd->wd_Bottom;
1274 if (t1 > gmh) gmh = t1;
1277 if (wd->wd_RBorder)
1279 t1 = wd->wd_RHeight + wd->wd_Top + wd->wd_Bottom;
1280 if (t1 > gmh) gmh = t1;
1283 if (wd->wd_TBorder)
1285 t1 = wd->wd_TWidth;
1286 if ((wd->wd_Flags & WDF_TITLEZIP) ||
1287 (wd->wd_WindowFlags & WFLG_SIZEGADGET)) t1 += wd->wd_ZoomW;
1288 if (wd->wd_WindowFlags & WFLG_DEPTHGADGET) t1 += wd->wd_DepthW;
1289 if (wd->wd_WindowFlags & WFLG_CLOSEGADGET) t1 += wd->wd_CloseW;
1290 if (t1 > gmw) gmw = t1;
1293 if (wd->wd_BBorder)
1295 t1 = wd->wd_BWidth;
1296 if (wd->wd_WindowFlags & WFLG_SIZEGADGET) t1 += wd->wd_SizeW;
1297 if (t1 > gmw) gmw = t1;
1301 * Setup master gadget dimensions.
1303 gx = wd->wd_Left;
1304 gy = wd->wd_Top;
1307 * And the border groups.
1309 if (wd->wd_LBorder)
1311 DoSetMethodNG(wd->wd_LBorder, GA_Left, 0,
1312 GA_Top, wd->wd_Top,
1313 GA_Width, wd->wd_Left,
1314 GA_RelHeight, -(wd->wd_Top),
1315 TAG_END);
1318 if (wd->wd_TBorder)
1320 t1 = wd->wd_WindowFlags & WFLG_DEPTHGADGET ? wd->wd_DepthW - 1: 0;
1321 t1 += (wd->wd_WindowFlags & WFLG_SIZEGADGET) ||
1322 (wd->wd_Flags & WDF_TITLEZIP) ? wd->wd_ZoomW - 1: 0;
1324 DoSetMethodNG(wd->wd_TBorder, GA_RelRight, -(wd->wd_TWidth + t1 - 1),
1325 GA_Top, 0,
1326 GA_Width, wd->wd_TWidth,
1327 GA_Height, wd->wd_Top,
1328 TAG_END);
1331 if (wd->wd_RBorder)
1333 t1 = wd->wd_WindowFlags & WFLG_SIZEGADGET ? wd->wd_SizeH - wd->wd_Bottom : 0;
1335 DoSetMethodNG(wd->wd_RBorder, GA_RelRight, -(wd->wd_Right - 1),
1336 GA_Top, wd->wd_Top,
1337 GA_Width, wd->wd_Right,
1338 GA_RelHeight, -(wd->wd_Top + wd->wd_Bottom + t1),
1339 TAG_END);
1342 if (wd->wd_BBorder)
1344 t1 = /*wd->wd_LBorder ?*/ wd->wd_Left /*: 0*/;
1345 t2 = wd->wd_WindowFlags & WFLG_SIZEGADGET ? wd->wd_SizeW : 0;
1347 DoSetMethodNG(wd->wd_BBorder, GA_Left, t1,
1348 GA_RelBottom, -(wd->wd_Bottom - 1),
1349 GA_RelWidth, -(t1 + t2),
1350 GA_Height, wd->wd_Bottom,
1351 TAG_END);
1354 else
1357 * No offsets necessary for
1358 * borderless windows.
1360 gx = gy = bw = bh = 0;
1364 * Set values to the master group.
1366 DoSetMethodNG(wd->wd_Gadgets, GA_Left, gx, GA_Top, gy, GA_RelWidth, -bw, GA_RelHeight, -bh, TAG_DONE);
1369 * Backdrop window?
1371 if (wd->wd_WindowFlags & WFLG_BACKDROP)
1374 * We force the window to be display
1375 * sized or display sized minus the
1376 * screen title bar.
1378 if (wd->wd_Flags & WDF_SHOWTITLE)
1380 sh = scr->Height - scr->BarHeight - 1;
1382 else
1385 * Hide title?
1387 ShowTitle(scr, FALSE);
1390 gmw = sw;
1391 gmh = sh;
1395 * Final check. Does the window fit and does
1396 * the width and height of the window read
1397 * positive values? If not retry with the
1398 * fallback font.
1400 if ((gmw > sw) || (gmh > sh))
1403 * Did it fail with the
1404 * fallback font?
1406 if (font == wd->wd_FallBackFont)
1407 return FALSE;
1410 * Retry with the fallback font.
1412 font = wd->wd_FallBackFont;
1413 goto reCalc;
1416 if ((wd->wd_UsedFont = BGUI_OpenFont(font)))
1418 *win_w = gmw;
1419 *win_h = gmh;
1421 return TRUE;
1423 return FALSE;
1426 /// WM_OPEN
1428 * Open up the window.
1430 STATIC METHOD(WindowClassOpen, Msg, msg)
1432 WD *wd = INST_DATA(cl, obj);
1433 WORD wleft = 0, wtop = 0, width = 0, height = 0, mw = 0, mh = 0;
1434 WORD vw, vh;
1435 struct Screen *pubscreen;
1436 struct Rectangle rect;
1437 struct Gadget *glist = GADGET(wd->wd_Gadgets);
1438 ULONG modeID;
1439 BOOL keepw = wd->wd_Flags & WDF_LOCK_WIDTH;
1440 BOOL keeph = wd->wd_Flags & WDF_LOCK_HEIGHT;
1441 BOOL pub = TRUE;
1442 int borders = 0;
1443 struct Window *w;
1444 struct Message *imsg;
1447 * If the window is already opened we
1448 * return a pointer to it.
1450 if ((w = wd->wd_WindowPtr))
1451 return (IPTR)w;
1454 * Link border gadgets.
1456 if (wd->wd_RBorder)
1458 GADGET(wd->wd_RBorder)->NextGadget = glist;
1459 glist = GADGET(wd->wd_RBorder);
1460 borders++;
1463 if (wd->wd_BBorder)
1465 GADGET(wd->wd_BBorder)->NextGadget = glist;
1466 glist = GADGET(wd->wd_BBorder);
1467 borders++;
1470 if (wd->wd_LBorder)
1472 GADGET(wd->wd_LBorder)->NextGadget = glist;
1473 glist = GADGET(wd->wd_LBorder);
1474 borders++;
1477 if (wd->wd_TBorder)
1479 GADGET(wd->wd_TBorder)->NextGadget = glist;
1480 glist = GADGET(wd->wd_TBorder);
1481 borders++;
1485 * Obtain a pointer to the
1486 * screen to use.
1488 if (wd->wd_Screen)
1490 pubscreen = wd->wd_Screen;
1491 pub = FALSE;
1493 else
1495 if (wd->wd_PubScreen) pubscreen = wd->wd_PubScreen;
1496 else
1499 * Lock the screen.
1501 if (!(pubscreen = LockPubScreen(wd->wd_PubScreenName)))
1503 * Fallback to the default screen
1504 * when locking failed. Should be
1505 * made optional?
1507 pubscreen = LockPubScreen(NULL);
1509 * Tell'm we locked the screen.
1511 if (pubscreen)
1512 wd->wd_Flags |= WDF_SCREEN_LOCKED;
1514 wd->wd_Screen = pubscreen;
1518 * Do we have a screen?
1520 if (!pubscreen) return 0;
1523 * Set up BDrawInfo drawinfo and pens.
1525 wd->wd_DrawInfo = GetScreenDrawInfo(pubscreen);
1528 for (i = 0; i < NUMDRIPENS; i++)
1530 wd->wd_BDI.bdi_Pens[i] = (wd->wd_BDI.bdi_DrInfo && (i < wd->wd_BDI.bdi_DrInfo->dri_NumPens)) ?
1531 wd->wd_BDI.bdi_DrInfo->dri_Pens[i] : DefDriPens[i];
1535 vw = pubscreen->Width;
1536 vh = pubscreen->Height;
1539 * Obtain the mode ID from the screen to use.
1542 if ((modeID = GetVPModeID(&pubscreen->ViewPort)) != INVALID_ID)
1545 * Find out TEXT overscan
1546 * dimensions.
1548 if (QueryOverscan(modeID, &rect, OSCAN_TEXT))
1551 * Compute TEXT overscan width and height
1552 * for this display mode.
1554 vw = rect.MaxX - rect.MinX + 1;
1555 vh = rect.MaxY - rect.MinY + 1;
1561 * Store the text overscan dimensions.
1563 wd->wd_TextW = vw;
1564 wd->wd_TextH = vh;
1566 /* AROS FIX <-> AMIGA FIX? */
1568 if (vw > pubscreen->Width) vw = pubscreen->Width;
1569 if (vh > pubscreen->Height) vh = pubscreen->Height;
1571 if (!WinSize(wd, (UWORD *)&width, (UWORD *)&height))
1572 goto failure;
1575 * Backdrop window?
1577 if (wd->wd_WindowFlags & WFLG_BACKDROP)
1580 * We force the window to be display
1581 * sized or display sized minus the
1582 * screen title bar.
1584 wleft = 0;
1586 if (wd->wd_Flags & WDF_SHOWTITLE)
1587 wtop = pubscreen->BarHeight + 1;
1588 else
1589 wtop = 0;
1591 goto forceThis;
1595 * The computed width and height are the
1596 * absolute minimum size that the window
1597 * can have. We save them here for the
1598 * window alternate (zipped) position.
1600 mw = width;
1601 mh = height;
1604 * Scale the window size?
1606 if (wd->wd_WidthScale) width += ((vw - width) * wd->wd_WidthScale) / 100;
1607 if (wd->wd_HeightScale) height += ((vh - height) * wd->wd_HeightScale) / 100;
1610 * When the window was opened before and the size is known or there
1611 * is previous size information available we use this information.
1613 if (wd->wd_Flags & WDF_CHANGE_VALID || GetWindowBounds(wd->wd_ID, &wd->wd_FixedPos))
1616 * If the width or height of the window
1617 * is fixed then we reuse the previous
1618 * values. If not we use the new values.
1620 width = keepw ? width : wd->wd_FixedPos.Width;
1621 height = keeph ? height : wd->wd_FixedPos.Height;
1624 * If the window is placed relative to a
1625 * given rectangle we place it again relative
1626 * to that rectangle. Otherwise we copy the
1627 * previous position.
1629 if (wd->wd_Flags & WDF_RELBOX)
1631 wleft = ((wd->wd_RelPos.Width - width) >> 1) + wd->wd_RelPos.Left;
1632 wtop = ((wd->wd_RelPos.Height - height) >> 1) + wd->wd_RelPos.Top;
1634 else
1636 wleft = wd->wd_FixedPos.Left;
1637 wtop = wd->wd_FixedPos.Top;
1641 * In case the font changed we need to check if the window has become
1642 * smaller than allowed and adjust if necessary.
1644 if (width < mw) width = mw;
1645 if (height < mh) height = mh;
1648 * Does the window still fit in this
1649 * situation?
1651 if (width > pubscreen->Width && mw <= pubscreen->Width) width = pubscreen->Width;
1652 if (height > pubscreen->Height && mh <= pubscreen->Height) height = pubscreen->Height;
1655 * Adjust the window position when necessary.
1657 if ((wleft + width) > pubscreen->Width) wleft = pubscreen->Width - width;
1658 if ((wtop + height) > pubscreen->Height) wtop = pubscreen->Height - height;
1660 else
1663 * Window positioned relative to a given rectangle?
1665 if (!(wd->wd_Flags & WDF_RELBOX))
1668 * What position is requested?
1670 switch (wd->wd_Position)
1672 case POS_CENTERSCREEN:
1673 wleft = ((vw - width) >> 1) - pubscreen->ViewPort.DxOffset;
1674 wtop = ((vh - height) >> 1) - pubscreen->ViewPort.DyOffset;
1675 break;
1677 case POS_CENTERMOUSE:
1678 wleft = pubscreen->MouseX - (width >> 1) - pubscreen->ViewPort.DxOffset;
1679 wtop = pubscreen->MouseY - (height >> 1) - pubscreen->ViewPort.DyOffset;
1680 break;
1683 else
1686 * Setup window according to the
1687 * rectangle.
1689 wleft = ((wd->wd_RelPos.Width - width) >> 1) + wd->wd_RelPos.Left;
1690 wtop = ((wd->wd_RelPos.Height - height) >> 1) + wd->wd_RelPos.Top;
1694 forceThis:
1697 * Do we have menus defined?
1699 if (wd->wd_MenuStrip)
1702 * Set the menus up.
1704 if (!DoMenuStrip(wd, pubscreen))
1705 goto failure;
1709 * Setup zip positions.
1711 if (wd->wd_Flags & WDF_TITLEZIP)
1714 * We always have a zoom gadget.
1716 wd->wd_Zoom[2] = wd->wd_ZoomW - 1;
1719 * Add the pixel-width of the title + 60.
1721 if (wd->wd_WindowTitle) wd->wd_Zoom[2] += TextWidth(&pubscreen->RastPort, wd->wd_WindowTitle) + 60;
1724 * And any other system gadgets.
1726 if (wd->wd_WindowFlags & WFLG_DEPTHGADGET) wd->wd_Zoom[2] += wd->wd_DepthW - 1;
1727 if (wd->wd_WindowFlags & WFLG_CLOSEGADGET) wd->wd_Zoom[2] += wd->wd_CloseW - 1;
1730 * And a top-group minimum size.
1732 if (wd->wd_TBorder) wd->wd_Zoom[2] += wd->wd_TWidth;
1735 * Title bar-height.
1737 wd->wd_Zoom[3] = wd->wd_Top;
1740 if (wd->wd_Flags & WDF_PREBUFFER) AsmDoMethod(wd->wd_Gadgets, BASE_RENDERBUFFER, pubscreen, width, height);
1743 * Open the window (finally :))
1745 w = wd->wd_WindowPtr = OpenWindowTags(NULL,
1746 WA_Left, wleft, WA_Top, wtop,
1747 WA_Width, width, WA_Height, height,
1748 WA_Flags, wd->wd_WindowFlags, WA_Gadgets, glist,
1749 WA_BackFill, &BackFill_hook, WA_RptQueue, 1,
1750 WA_MinWidth, mw, WA_MinHeight, mh,
1751 WA_MaxWidth, (wd->wd_Flags & WDF_LOCK_WIDTH) ? mw : ~0,
1752 WA_MaxHeight, (wd->wd_Flags & WDF_LOCK_HEIGHT) ? mh : ~0,
1753 wd->wd_WindowTitle ? WA_Title : TAG_IGNORE, wd->wd_WindowTitle,
1754 wd->wd_ScreenTitle ? WA_ScreenTitle : TAG_IGNORE, wd->wd_ScreenTitle,
1755 pub ? WA_PubScreen : WA_CustomScreen, pubscreen,
1756 wd->wd_Flags & WDF_TITLEZIP ? WA_Zoom : TAG_IGNORE, wd->wd_Zoom,
1757 WA_IDCMP, wd->wd_IDCMPFlags,
1758 WA_MenuHelp, TRUE, TAG_END);
1760 if (!w) goto failure;
1763 * Set the font.
1765 wd->wd_OrigFont = w->RPort->Font;
1766 FSetFont(w->RPort, wd->wd_UsedFont);
1769 * Move the top-border group to the
1770 * beginning of the list.
1772 if (borders)
1774 RemoveGList(w, glist, borders);
1775 AddGList(w, glist, 0, borders, NULL);
1779 * Save window bounds.
1781 SetWindowBounds(wd->wd_ID, (struct IBox *)&w->LeftEdge);
1784 * Setup menu-strip if one exists.
1786 if (wd->wd_Menus)
1787 SetMenuStrip(w, wd->wd_Menus );
1790 * When we have a shared MsgPort we must move any initial messages to it,
1791 * then set it up.
1793 if (wd->wd_Flags & WDF_SHARED_MSGPORT)
1796 * Set it to a flag that will not occur, to stop input without closing the port.
1798 ModifyIDCMP(w, IDCMP_REQCLEAR);
1800 while ((imsg = GetMsg(w->UserPort)))
1803 * Dump message onto the other port.
1805 PutMsg(wd->wd_UserPort, imsg);
1808 * Free intuition's port.
1810 ModifyIDCMP(w, 0);
1813 * Poke the shared port.
1815 w->UserPort = wd->wd_UserPort;
1818 * Setup the flags.
1820 ModifyIDCMP(w, wd->wd_IDCMPFlags);
1822 else
1825 * Pick up the intuition created message port.
1827 wd->wd_UserPort = w->UserPort;
1831 * If requested setup this window
1832 * as a workbench App-Window.
1834 if (wd->wd_Flags & WDF_IS_APPWINDOW)
1836 * Quietly fails.
1838 MakeAppWindow(wd);
1841 * Add window to the internal list.
1842 * Also fails quietly...
1844 AddWindow(obj, w);
1846 return (IPTR)w;
1848 failure:
1850 AsmCoerceMethod(cl, obj, WM_CLOSE);
1852 return 0;
1854 METHOD_END
1858 * Clear all messages from
1859 * the port which belong to
1860 * the window.
1862 STATIC ASM VOID ClearMsgPort( REG(a0) WD *wd )
1864 struct IntuiMessage *imsg;
1865 struct Node *succ;
1868 * Don't race intuition.
1870 Forbid();
1872 imsg = ( struct IntuiMessage * )wd->wd_UserPort->mp_MsgList.lh_Head;
1874 while ((succ = imsg->ExecMessage.mn_Node.ln_Succ)) {
1875 if ( imsg->IDCMPWindow == wd->wd_WindowPtr ) {
1876 Remove(( struct Node * )imsg );
1877 ReplyMsg(( struct Message * )imsg );
1879 imsg = ( struct IntuiMessage * )succ;
1881 Permit();
1883 /// WM_CLOSE
1885 * Close the window.
1887 STATIC METHOD(WindowClassClose, Msg, msg)
1889 WD *wd = INST_DATA(cl, obj);
1890 ULONG rc = 0;
1891 struct Window *w;
1893 if ((w = wd->wd_WindowPtr))
1896 * When a shared MsgPort is used
1897 * we clear the UserPort ptr in the window
1898 * structure.
1900 Forbid();
1901 ClearMsgPort(wd);
1902 if (wd->wd_Flags & WDF_SHARED_MSGPORT)
1904 w->UserPort = NULL;
1906 ModifyIDCMP(w, 0);
1907 Permit();
1910 * Close tool-tip window.
1912 AsmDoMethod(obj, WM_CLOSETOOLTIP);
1915 * Wakeup the window.
1917 while (wd->wd_SleepCnt)
1918 AsmDoMethod(obj, WM_WAKEUP);
1921 * AppWindow?
1923 if (wd->wd_Flags & WDF_IS_APPWINDOW)
1924 KillAppWindow(wd);
1927 * Remove the window menus.
1929 if (wd->wd_Menus) ClearMenuStrip(w);
1932 * Setup original font.
1934 FSetFont(w->RPort, wd->wd_OrigFont);
1937 * Close the window.
1939 CloseWindow(w);
1940 wd->wd_WindowPtr = NULL;
1943 * Remove it and all outstanding ID's from the internal lists.
1945 RemWindow(obj);
1946 RemoveIDReport(w);
1949 * Clear continuation flags.
1951 wd->wd_NextSelect = MENUNULL;
1952 wd->wd_Flags &= ~WDF_DRAGSELECT;
1955 * Free the menus.
1957 if (wd->wd_Menus)
1959 FreeMenus(wd->wd_Menus);
1960 wd->wd_Menus = NULL;
1963 if (wd->wd_BufferRP)
1965 wd->wd_BufferRP->Layer = wd->wd_BufferLayer;
1966 BGUI_FreeRPortBitMap(wd->wd_BufferRP);
1967 wd->wd_BufferRP = NULL;
1970 rc = 1;
1973 if (wd->wd_UsedFont)
1975 BGUI_CloseFont(wd->wd_UsedFont);
1976 wd->wd_UsedFont = NULL;
1979 if (wd->wd_VisualInfo)
1981 FreeVisualInfo(wd->wd_VisualInfo);
1982 wd->wd_VisualInfo = NULL;
1985 if (wd->wd_DrawInfo)
1987 FreeScreenDrawInfo(wd->wd_Screen, wd->wd_DrawInfo);
1988 wd->wd_DrawInfo = NULL;
1991 if (wd->wd_Flags & WDF_SCREEN_LOCKED)
1993 UnlockPubScreen(NULL, wd->wd_Screen);
1994 wd->wd_Flags &= ~WDF_SCREEN_LOCKED;
1997 if (wd->wd_PubScreenName)
1999 wd->wd_Screen = NULL;
2002 return (IPTR)rc;
2004 METHOD_END
2006 /// WM_SLEEP
2008 * Put the window to sleep.
2010 STATIC METHOD(WindowClassSleep, Msg, msg)
2012 WD *wd = INST_DATA(cl, obj);
2013 ULONG rc = 0;
2016 * Only go to sleep if the window is open.
2018 if (wd->wd_WindowPtr)
2021 * If the sleep nest counter is 0 we setup a requester
2022 * and a busy pointer.
2024 if (wd->wd_SleepCnt++ == 0)
2025 wd->wd_Lock = BGUI_LockWindow(wd->wd_WindowPtr);
2027 * Return 1 for sucess.
2029 rc = 1;
2031 return (IPTR)rc;
2033 METHOD_END
2035 /// WM_WAKEUP
2037 * Wake the window back up.
2039 STATIC METHOD(WindowClassWakeUp, Msg, msg)
2041 WD *wd = INST_DATA(cl, obj);
2042 ULONG rc = 0;
2045 * Only decrease the sleep nest counter when the
2046 * window is open _and_ the sleep nest counter is not 0.
2048 if (wd->wd_Lock)
2050 if (--wd->wd_SleepCnt == 0)
2053 * When the sleep nest counter becomes zero we remove the
2054 * requester and reset the pointer.
2056 BGUI_UnlockWindow(wd->wd_Lock);
2057 wd->wd_Lock = NULL;
2059 rc = 1;
2061 return (IPTR)rc;
2063 METHOD_END
2067 * Keep track of window bound changes.
2069 STATIC ASM ULONG WindowClassChange( REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) Msg msg )
2071 WD *wd = INST_DATA(cl, obj);
2072 ULONG rc = 0;
2073 struct Window *w;
2075 if ((w = wd->wd_WindowPtr))
2077 wd->wd_FixedPos = *IBOX(&w->LeftEdge);
2078 wd->wd_Flags |= WDF_CHANGE_VALID;
2079 rc = 1;
2081 * Save window bounds.
2083 SetWindowBounds(wd->wd_ID, (struct IBox *)&w->LeftEdge);
2085 return rc;
2089 * Get an attribute.
2091 STATIC METHOD(WindowClassGet, struct opGet *, opg)
2093 WD *wd = (WD *)INST_DATA(cl, obj);
2094 ULONG rc = 1;
2095 IPTR *store = opg->opg_Storage;
2097 struct Window *win;
2099 switch (opg->opg_AttrID)
2101 case WINDOW_GadgetOK:
2102 STORE !(wd->wd_Flags & WDF_REMOVED);
2103 break;
2105 case WINDOW_ToolTicks:
2106 STORE wd->wd_ToolTickTime;
2107 break;
2109 case WINDOW_MenuStrip:
2110 STORE wd->wd_Menus;
2111 break;
2113 case WINDOW_UserPort:
2114 if (wd->wd_WindowPtr) STORE wd->wd_UserPort;
2115 else STORE NULL;
2116 break;
2118 case WINDOW_SigMask:
2119 STORE (wd->wd_WindowPtr ? (1 << wd->wd_UserPort->mp_SigBit) : 0);
2120 break;
2122 case WINDOW_AppMask:
2123 STORE (wd->wd_AppPort ? (1 << wd->wd_AppPort->mp_SigBit) : 0);
2124 break;
2126 case WINDOW_Window:
2127 STORE wd->wd_WindowPtr;
2128 break;
2130 case WINDOW_Font:
2131 STORE wd->wd_Font;
2132 break;
2134 case WINDOW_Bounds:
2135 if ( wd->wd_WindowPtr )
2136 *(( struct IBox * )store ) = *(( struct IBox * )&wd->wd_WindowPtr->LeftEdge );
2137 else
2138 rc = 0;
2139 break;
2141 case WINDOW_Title:
2142 STORE wd->wd_WindowTitle;
2143 break;
2145 case WINDOW_ScreenTitle:
2146 STORE wd->wd_ScreenTitle;
2147 break;
2149 case WINDOW_TitleID:
2150 STORE wd->wd_WindowTitleID;
2151 break;
2153 case WINDOW_ScreenTitleID:
2154 STORE wd->wd_ScreenTitleID;
2155 break;
2157 case WINDOW_HelpTextID:
2158 STORE wd->wd_HelpTextID;
2159 break;
2161 case WINDOW_AutoAspect:
2162 STORE test(wd->wd_Flags & WDF_AUTOASPECT);
2163 break;
2165 case WINDOW_BufferRP:
2166 if ((win = wd->wd_WindowPtr) && !(wd->wd_Flags & WDF_NO_BUFFER) && (FGetDepth(win->RPort) <= 8))
2168 if ((wd->wd_BRW != win->Width) || (wd->wd_BRH != win->Height))
2170 wd->wd_BRW = win->Width;
2171 wd->wd_BRH = win->Height;
2172 if (wd->wd_BufferRP)
2174 wd->wd_BufferRP->Layer = wd->wd_BufferLayer;
2175 BGUI_FreeRPortBitMap(wd->wd_BufferRP);
2176 wd->wd_BufferRP = NULL;
2179 if (!wd->wd_BufferRP)
2181 wd->wd_BufferRP = BGUI_CreateRPortBitMap(win->RPort, wd->wd_BRW, wd->wd_BRH, 0);
2182 wd->wd_BufferLayer = wd->wd_BufferRP->Layer;
2183 wd->wd_BufferRP->Layer = NULL;
2185 STORE wd->wd_BufferRP;
2187 else
2189 STORE NULL;
2191 break;
2193 default:
2194 rc = (ULONG)AsmDoSuperMethodA(cl, obj, (Msg)opg);
2195 break;
2197 return (IPTR)rc;
2199 METHOD_END
2202 * Put out a help-request.
2204 STATIC ASM ULONG WindowClassHelp(REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) Msg msg)
2206 WD *wd = INST_DATA( cl, obj );
2207 struct bmShowHelp bsh;
2208 struct NewAmigaGuide nag = { };
2209 ULONG rc = BMHELP_FAILURE;
2210 struct Window *w;
2213 * Only when the window is open.
2215 if ((w = wd->wd_WindowPtr))
2218 * Setup a help request for the
2219 * master object.
2221 bsh.MethodID = BASE_SHOWHELP;
2222 bsh.bsh_Window = w;
2223 bsh.bsh_Requester = NULL;
2224 bsh.bsh_Mouse.X = w->MouseX;
2225 bsh.bsh_Mouse.Y = w->MouseY;
2227 * Go to sleep and send the
2228 * request.
2230 AsmDoMethod(obj, WM_SLEEP);
2233 * Any help shown by the master object?
2235 if (AsmDoMethodA(wd->wd_Gadgets, (Msg)&bsh) == BMHELP_NOT_ME)
2238 * No. Show the window help.
2240 if (wd->wd_HelpFile || wd->wd_HelpText)
2243 * Only if the mouse is located
2244 * in the window.
2246 if (bsh.bsh_Mouse.X > 0 && bsh.bsh_Mouse.Y > 0 && bsh.bsh_Mouse.X < w->Width && bsh.bsh_Mouse.Y < w->Height)
2248 if (wd->wd_HelpText)
2250 ShowHelpReq(w, wd->wd_HelpText);
2251 rc = BMHELP_OK;
2253 else
2255 nag.nag_Name = (STRPTR)wd->wd_HelpFile;
2256 nag.nag_Node = (STRPTR)wd->wd_HelpNode;
2257 nag.nag_Line = wd->wd_HelpLine;
2258 nag.nag_Screen = w->WScreen;
2260 if (DisplayAGuideInfo(&nag, TAG_END))
2261 rc = BMHELP_OK;
2267 * Wakeup the window.
2269 AsmDoMethod(obj, WM_WAKEUP);
2271 return rc;
2275 * Fill up an InputEvent structure
2276 * with RAWKEY information.
2278 STATIC ASM VOID FillIE(REG(a0) struct InputEvent *ie, REG(a1) struct IntuiMessage *imsg)
2280 ie->ie_Class = IECLASS_RAWKEY;
2281 ie->ie_Code = imsg->Code;
2282 ie->ie_Qualifier = imsg->Qualifier;
2283 ie->ie_EventAddress = imsg->IAddress ? *((APTR *)(imsg->IAddress)) : NULL;
2284 ie->ie_TimeStamp.tv_secs = imsg->Seconds;
2285 ie->ie_TimeStamp.tv_micro = imsg->Micros;
2289 * Get the first message from the
2290 * window port which belongs to the window.
2292 STATIC ASM struct IntuiMessage *GetIMsg( REG(a0) WD *wd )
2294 struct IntuiMessage *imsg;
2295 struct MsgPort *mp = wd->wd_UserPort;
2298 * No need to race intuition.
2300 Forbid();
2302 for ( imsg = ( struct IntuiMessage * )mp->mp_MsgList.lh_Head; imsg->ExecMessage.mn_Node.ln_Succ; imsg = ( struct IntuiMessage * )imsg->ExecMessage.mn_Node.ln_Succ ) {
2303 if ( imsg->IDCMPWindow == wd->wd_WindowPtr ) {
2304 Remove(( struct Node * )imsg );
2305 Permit();
2306 return( imsg );
2310 Permit();
2311 return( NULL );
2315 * Find out if an object must receive a key message.
2317 STATIC ULONG KeyGadget(Class *cl, Object *obj, struct IntuiMessage *imsg)
2320 WD *wd = INST_DATA(cl, obj);
2321 struct InputEvent ie;
2322 struct wmKeyInput wk;
2323 struct IntuiMessage *im = NULL;
2324 APTR iadd;
2325 ULONG irc, id, rc = WMHI_IGNORE;
2327 ULONG class = imsg->Class;
2328 UWORD code = imsg->Code;
2329 UWORD qual = imsg->Qualifier;
2330 UBYTE key = (UBYTE)code;
2332 struct Window *w = wd->wd_WindowPtr;
2334 Object *ob;
2337 * No menus during keyboard
2338 * activation.
2340 if (!(wd->wd_WindowFlags & WFLG_RMBTRAP))
2342 Forbid();
2343 w->Flags |= WFLG_RMBTRAP;
2344 Permit();
2348 * Initialize input event.
2350 if (code & IECODE_UP_PREFIX)
2351 goto end;
2353 FillIE(&ie, imsg);
2354 if (MapRawKey(&ie, &key, 1, NULL) == 1)
2355 code = key;
2356 else
2358 code = code | 0xFF00;
2361 #ifdef __AROS__
2362 if (!(ob = (Object *)AsmDoMethod(obj, BASE_FINDKEY, qual, code)))
2363 goto end;
2364 #else
2365 if (!(ob = (Object *)AsmDoMethod(obj, BASE_FINDKEY, (qual << 16) | code)))
2366 goto end;
2367 #endif
2370 * Initialize wmKeyInput structure.
2372 wk.MethodID = WM_KEYACTIVE;
2373 wk.wmki_IEvent = &ie;
2374 wk.wmki_ID = &id;
2375 wk.wmki_Key = &key;
2378 * Send a WM_KEYACTIVE message to the target.
2380 irc = BGUI_DoGadgetMethodA(ob, w, NULL, (Msg)&wk);
2383 * Reply the originating message.
2385 ReplyMsg((struct Message *)imsg);
2386 imsg = NULL;
2389 * Are we done?
2391 if (irc & WMKF_VERIFY)
2394 * Yes. Return the id.
2396 rc = id;
2397 goto end;
2399 else if (irc & WMKF_CANCEL)
2402 * We are cancelled :^(
2403 * Return WMHI_IGNORE.
2405 goto end;
2407 else if (irc & WMKF_ACTIVATE)
2410 * We are told to activate the
2411 * gadget through intuition channels.
2413 ClearMsgPort(wd);
2414 ActivateGadget(GADGET(ob), w, NULL);
2415 goto end;
2417 else
2420 * Boom. We are active.
2422 wk.MethodID = WM_KEYINPUT;
2424 for(;;)
2426 WaitPort(wd->wd_UserPort);
2427 while ((im = GetIMsg(wd)))
2429 class = im->Class;
2430 code = im->Code;
2431 qual = im->Qualifier;
2432 iadd = im->IAddress;
2434 switch (class)
2437 * Check out the RAWKEY event.
2439 case IDCMP_RAWKEY:
2440 if (qual & IEQUALIFIER_REPEAT) break;
2441 if ((code & IECODE_UP_PREFIX) == 0)
2443 myDoGadgetMethod(ob, w, NULL, WM_KEYINACTIVE, NULL);
2444 goto end;
2446 FillIE(&ie, im);
2447 irc = BGUI_DoGadgetMethodA(ob, wd->wd_WindowPtr, NULL, (Msg)&wk);
2448 if (irc & WMKF_VERIFY)
2450 myDoGadgetMethod(ob, w, NULL, WM_KEYINACTIVE, NULL);
2451 rc = id;
2452 goto end;
2454 else if (irc & WMKF_CANCEL)
2456 myDoGadgetMethod(ob, w, NULL, WM_KEYINACTIVE, NULL);
2457 goto end;
2459 break;
2461 case IDCMP_CLOSEWINDOW:
2463 * Pass on the close window request.
2465 myDoGadgetMethod(ob, w, NULL, WM_KEYINACTIVE, NULL);
2466 rc = WMHI_CLOSEWINDOW;
2467 goto end;
2469 case IDCMP_GADGETUP:
2471 * Pass on the gadget request.
2473 myDoGadgetMethod(ob, w, NULL, WM_KEYINACTIVE, NULL);
2474 rc = GADGET(iadd)->GadgetID;
2475 goto end;
2477 case IDCMP_INACTIVEWINDOW:
2479 * Window inactive? Abort keyboard actions.
2481 myDoGadgetMethod(ob, w, NULL, WM_KEYINACTIVE, NULL);
2482 ClearMsgPort(wd);
2483 goto end;
2485 case IDCMP_SIZEVERIFY:
2487 * Exit... NOW!
2489 myDoGadgetMethod(ob, w, NULL, WM_KEYINACTIVE, NULL);
2490 wd->wd_OW = w->Width;
2491 wd->wd_OH = w->Height;
2492 wd->wd_Flags |= WDF_REMOVED;
2493 RemoveGadget(w, (struct Gadget *)wd->wd_Gadgets);
2494 ClearMsgPort(wd);
2495 goto end;
2499 * Reply the message.
2501 ReplyMsg((struct Message *)im);
2505 end:
2508 * Reply the un-replyed messages.
2510 if (imsg) ReplyMsg((struct Message *)imsg);
2511 if (im) ReplyMsg((struct Message *)im);
2514 * Menu actions possible if they were before the keyboard stuff
2515 * and if we don't stay active.
2517 if (!(wd->wd_WindowFlags & WFLG_RMBTRAP))
2519 Forbid();
2520 w->Flags &= ~WFLG_RMBTRAP;
2521 Permit();
2523 return rc;
2527 * Find tab-cycle entry.
2529 STATIC ASM TABCYCLE *GetCycleNode( REG(a0) WD *wd, REG(a1) Object *obj )
2531 TABCYCLE *tc;
2533 for ( tc = wd->wd_CycleList.cl_First; tc->tc_Next; tc = tc->tc_Next ) {
2534 if ( tc->tc_Object == obj )
2535 return( tc );
2537 return( NULL );
2541 * Perform update notification.
2543 STATIC ASM VOID UpdateNotification( REG(a0) WD *wd, REG(a1) struct TagItem *attr, REG(d0) ULONG id )
2545 struct TagItem *clones;
2546 UPN *up;
2549 * Clone attributes.
2551 if ((clones = CloneTagItems( attr ))) {
2553 * Find target.
2555 for ( up = wd->wd_UpdateList.ul_First; up->up_Next; up = up->up_Next )
2558 * Is this the one?
2560 if ( up->up_ID == id )
2563 * Map clones when necessary.
2565 if ( up->up_MapList )
2566 MapTags( clones, up->up_MapList, TRUE );
2568 * Set attributes to the target.
2570 myDoGadgetMethod(up->up_Target, wd->wd_WindowPtr, NULL, OM_UPDATE, clones, NULL, 0);
2572 * Unmap clones when necessary.
2574 if ( up->up_MapList )
2575 UnmapTags( clones, up->up_MapList );
2579 * Free clones.
2581 FreeTagItems( clones );
2586 * Default tool tip hook.
2588 //STATIC ASM IPTR ToolTip_func(REG(a0) struct Hook *h, REG(a2) Object *obj, REG(a1) struct ttCommand *ttc)
2589 STATIC ASM REGFUNC3(IPTR, ToolTip_func,
2590 REGPARAM(A0, struct Hook *, h),
2591 REGPARAM(A2, Object *, obj),
2592 REGPARAM(A1, struct ttCommand *, ttc))
2594 WD *wd;
2595 struct Window *tw = NULL;
2596 struct TextFont *of;
2597 struct RastPort *rp;
2598 struct IBox ibx;
2599 UWORD x, y, ww, wh;
2600 UBYTE *tip, *tc;
2601 IPTR args[2];
2602 struct BaseInfo *bi;
2604 switch (ttc->ttc_Command)
2606 case TT_SHOW:
2607 wd = (WD *)ttc->ttc_UserData;
2610 * Does the tip-object have a tool-tip?
2612 tc = NULL;
2613 Get_Attr(ttc->ttc_Object, BT_ToolTip, (IPTR *)&tc);
2614 if (tc)
2617 * Copy and setup the tip.
2619 if ((tip = (UBYTE *)BGUI_AllocPoolMem(strlen(tc) + 10)))
2621 args[0] = (IPTR)BARDETAILPEN;
2622 args[1] = (IPTR)tc;
2623 DoSPrintF(tip, "\033d%ld%s", args);
2625 else
2627 tip = tc;
2628 tc = NULL;
2631 rp = wd->wd_WindowPtr->RPort;
2634 * Set the font.
2636 of = rp->Font;
2637 FSetFont(rp, wd->wd_UsedFont);
2639 BGUI_InfoTextSize(rp, tip, (UWORD *)&ibx.Width, (UWORD *)&ibx.Height);
2640 FSetFont(rp, of);
2643 * Get mouse position.
2645 x = wd->wd_WindowPtr->MouseX;
2646 y = wd->wd_WindowPtr->MouseY;
2649 * Tool-tip width and height.
2651 ww = ibx.Width + 8;
2652 wh = ibx.Height + 4;
2655 * Open tool-tip window with it's
2656 * bottom right corner under the mouse.
2658 if ((tw = OpenWindowTags(NULL,WA_Left, wd->wd_WindowPtr->LeftEdge + x - ww,
2659 WA_Top, wd->wd_WindowPtr->TopEdge + y - wh,
2660 WA_Width, ww,
2661 WA_Height, wh,
2662 WA_IDCMP, 0,
2663 WA_Flags, WFLG_BORDERLESS|WFLG_RMBTRAP,
2664 WA_CustomScreen, wd->wd_Screen,
2665 TAG_DONE)))
2667 rp = tw->RPort;
2669 #ifdef DEBUG_BGUI
2670 if ((bi = AllocBaseInfoDebug(__FILE__,__LINE__,BI_Screen, wd->wd_Screen, BI_RastPort, rp, TAG_DONE)))
2671 #else
2672 if ((bi = AllocBaseInfo(BI_Screen, wd->wd_Screen, BI_RastPort, rp, TAG_DONE)))
2673 #endif
2676 * Set the font.
2678 of = rp->Font;
2679 BSetFont(bi, wd->wd_UsedFont);
2682 * Tip background color.
2684 BSetDrMd(bi, JAM1);
2685 BSetDPenA(bi, BARBLOCKPEN);
2686 BRectFill(bi, 1, 1, ww - 2, wh - 2);
2689 * Tip border and text.
2691 BSetDPenA(bi, BARDETAILPEN);
2692 Move(rp, 0, 0);
2693 Draw(rp, ww - 1, 0);
2694 Draw(rp, ww - 1, wh - 1);
2695 Draw(rp, 0, wh - 1);
2696 Draw(rp, 0, 0);
2699 * Render the tip.
2701 ibx.Left = 4;
2702 ibx.Top = 2;
2704 RenderText(bi, tip, &ibx);
2705 BSetFont(bi, of);
2707 FreeBaseInfo(bi);
2710 * Free copy.
2712 if (tc) BGUI_FreePoolMem(tip);
2714 break;
2716 case TT_HIDE:
2717 tw = (struct Window *)ttc->ttc_UserData;
2718 if (tw) CloseWindow(tw);
2719 break;
2722 return (IPTR)tw;
2724 REGFUNC_END
2725 static struct Hook ToolTipHook = { {NULL, NULL}, (HOOKFUNC)ToolTip_func, NULL, NULL };
2727 /// WM_CLOSETOOLTIP
2729 STATIC METHOD(WindowClassCloseTT, Msg, msg)
2731 WD *wd = INST_DATA(cl, obj);
2732 struct ttCommand ttc;
2734 if (wd->wd_ToolTip)
2736 ttc.ttc_Command = TT_HIDE;
2737 ttc.ttc_Object = wd->wd_ToolTipObject;
2738 ttc.ttc_UserData = (APTR)wd->wd_ToolTip;
2740 BGUI_CallHookPkt(wd->wd_ToolTipHook ? wd->wd_ToolTipHook : &ToolTipHook, (void *)obj, (void *)&ttc);
2742 wd->wd_ToolX = wd->wd_ToolY = -1;
2743 wd->wd_ToolTip = NULL;
2745 return (IPTR)TRUE;
2747 METHOD_END
2749 /// WM_HANDLEIDCMP
2751 * Handle a window's IDCMP messages.
2753 STATIC METHOD(WindowClassIDCMP, Msg, msg)
2755 struct IntuiMessage *imsg;
2756 struct TagItem *attr, *tag;
2757 struct MenuItem *mi;
2758 TABCYCLE *tc;
2759 WD *wd = INST_DATA(cl, obj);
2760 ULONG rc = WMHI_IGNORE, id;
2761 UWORD code;
2762 Object *obja;
2763 struct grmWhichObject grwo;
2764 struct ttCommand ttc;
2765 WORD x, y;
2766 IPTR mouseact, inhibit;
2767 BOOL forward;
2768 Object *tabbed;
2769 struct Window *w = wd->wd_WindowPtr;
2773 * No window!
2775 if (!w) return WMHI_NOMORE;
2778 * Locked out?
2780 if (!(wd->wd_Flags & WDF_LOCKOUT))
2783 * Are we in a drag-selection loop?
2784 * If so continue it.
2786 if (wd->wd_Flags & WDF_DRAGSELECT)
2788 code = wd->wd_NextSelect;
2789 imsg = NULL;
2790 goto dragSelect;
2794 * Reports on the stack?
2796 if ((id = GetIDReport(w)) != ~0)
2799 * Return the ID.
2801 return id;
2806 * Is there a message.
2808 while ((imsg = GetIMsg(wd)))
2811 * Any movement?
2814 BOOL close_tooltip;
2816 if(!(close_tooltip=(w->MouseX != wd->wd_ToolX || w->MouseY != wd->wd_ToolY)))
2818 switch(imsg->Class)
2821 case IDCMP_IDCMPUPDATE:
2822 case IDCMP_DISKINSERTED:
2823 case IDCMP_DISKREMOVED:
2824 case IDCMP_WBENCHMESSAGE:
2825 case IDCMP_INTUITICKS:
2826 break;
2827 default:
2828 close_tooltip=TRUE;
2829 break;
2832 if(close_tooltip)
2835 * Do we have a tool-tip to close?
2837 if (wd->wd_ToolTip)
2838 AsmDoMethod(obj, WM_CLOSETOOLTIP);
2839 else
2840 wd->wd_ToolTicks = 0;
2845 * Are we locked out?
2847 if (wd->wd_Flags & WDF_LOCKOUT)
2850 * Yes. Reply this message and continue.
2852 ReplyMsg((struct Message *)imsg);
2853 continue;
2857 * Call the hook for the xxxxVERIFY messages
2858 * if one exists.
2860 if (wd->wd_VerifyHook)
2862 if ((wd->wd_VerifyHookBits & imsg->Class) == imsg->Class)
2864 BGUI_CallHookPkt(wd->wd_VerifyHook, (void *)obj, (void *)imsg);
2865 ReplyMsg((struct Message *)imsg);
2866 return rc;
2871 * Call the IDCMPHook when it's available.
2874 if (wd->wd_IDCMPHook && (wd->wd_IDCMPHookBits & imsg->Class))
2876 BGUI_CallHookPkt(wd->wd_IDCMPHook, (VOID *)obj, (VOID *)imsg);
2879 code = imsg->Code;
2881 switch (imsg->Class)
2883 case IDCMP_SIZEVERIFY:
2885 * Save window size and remove
2886 * the master.
2888 wd->wd_OW = w->Width;
2889 wd->wd_OH = w->Height;
2890 if (!(wd->wd_Flags & WDF_REMOVED))
2892 wd->wd_Flags |= WDF_REMOVED;
2893 RemoveGadget(w, (struct Gadget *)wd->wd_Gadgets);
2895 break;
2897 case IDCMP_NEWSIZE:
2898 WW(kprintf("WindowClassIDCMP: received IDCMP_NEWSIZE\n"));
2900 * If we have manually removed the
2901 * master object we adjust the size
2902 * ourselves.
2904 if (wd->wd_Flags & WDF_REMOVED)
2907 * Setup new size for the master.
2909 DoSetMethodNG(wd->wd_Gadgets, GA_Left, w->BorderLeft,
2910 GA_Top, w->BorderTop,
2911 GA_RelWidth, -(w->BorderLeft + w->BorderRight ),
2912 GA_RelHeight, -(w->BorderTop + w->BorderBottom),
2913 TAG_END);
2915 * Put master back online.
2917 AddGadget(w, (struct Gadget *)wd->wd_Gadgets, -1);
2920 * Clear removed flag.
2922 wd->wd_Flags &= ~WDF_REMOVED;
2925 * Only refresh the window when the
2926 * size actually changed.
2931 if ((w->Width != wd->wd_OW) || (w->Height != wd->wd_OH))
2932 RefreshWindowFrame(w);
2934 break;
2936 case IDCMP_MOUSEBUTTONS:
2937 if ((code | IECODE_UP_PREFIX) != SELECTUP)
2940 * Preset GRM_WHICHOBJECT method.
2942 grwo.MethodID = GRM_WHICHOBJECT;
2943 grwo.grwo_Coords.X = imsg->MouseX;
2944 grwo.grwo_Coords.Y = imsg->MouseY;
2946 if ((obja = (Object *)AsmDoMethodA(wd->wd_Gadgets, (Msg)&grwo)))
2948 Get_Attr(obja, BT_MouseActivation, &mouseact);
2950 if (((mouseact & MOUSEACT_RMB_ACTIVE) && (code == IECODE_RBUTTON))
2951 || ((mouseact & MOUSEACT_MMB_ACTIVE) && (code == IECODE_MBUTTON)))
2953 SetAttrs(obja, BT_ReportID,
2954 ((mouseact & MOUSEACT_RMB_REPORT) && (code == IECODE_RBUTTON)) ||
2955 ((mouseact & MOUSEACT_MMB_REPORT) && (code == IECODE_MBUTTON)), TAG_DONE);
2957 if (wd->wd_DGMObject)
2959 DoSetMethodNG(wd->wd_DGMObject, DGM_Object, obja, DGM_IntuiMsg, imsg,TAG_END);
2960 ActivateGadget((struct Gadget *)wd->wd_DGMObject, w, NULL);
2965 break;
2967 case IDCMP_MOUSEMOVE:
2968 if (wd->wd_WindowFlags & WFLG_RMBTRAP)
2970 Forbid();
2971 wd->wd_WindowPtr->Flags |= WFLG_RMBTRAP;
2972 Permit();
2974 else
2976 mouseact = 0;
2978 * Preset GRM_WHICHOBJECT method.
2980 grwo.MethodID = GRM_WHICHOBJECT;
2981 grwo.grwo_Coords.X = imsg->MouseX;
2982 grwo.grwo_Coords.Y = imsg->MouseY;
2984 if ((obja = (Object *)AsmDoMethodA(wd->wd_Gadgets, (Msg)&grwo)))
2986 Get_Attr(obja, BT_MouseActivation, &mouseact);
2989 Forbid();
2990 if (mouseact & MOUSEACT_RMB_ACTIVE)
2992 wd->wd_WindowPtr->Flags |= WFLG_RMBTRAP;
2994 else
2996 wd->wd_WindowPtr->Flags &= ~WFLG_RMBTRAP;
2998 Permit();
3000 break;
3002 case IDCMP_ACTIVEWINDOW:
3003 rc = WMHI_ACTIVE;
3004 break;
3006 case IDCMP_INACTIVEWINDOW:
3007 rc = WMHI_INACTIVE;
3008 break;
3010 case IDCMP_CLOSEWINDOW:
3011 rc = WMHI_CLOSEWINDOW;
3012 break;
3014 case IDCMP_CHANGEWINDOW:
3015 WW(kprintf("WindowClassIDCMP: received IDCMP_CHANGEWINDOW\n"));
3016 if (wd->wd_Flags & WDF_CONSTRAINTS)
3018 WW(kprintf("WindowClassIDCMP: WDF_CONSTRAINTS is set\n"));
3019 WW(kprintf("WindowClassIDCMP: calling WindowLimits(%d,%d,%d,%d)\n",wd->wd_MinW,wd->wd_MinH,wd->wd_MaxW,wd->wd_MaxH));
3020 WindowLimits(w, wd->wd_MinW, wd->wd_MinH, wd->wd_MaxW, wd->wd_MaxH);
3021 wd->wd_Flags &= ~WDF_CONSTRAINTS;
3023 WW(kprintf("WindowClassIDCMP: calling WM_RELEASE\n"));
3024 AsmDoMethod(obj, WM_RELEASE);
3026 WW(kprintf("WindowClassIDCMP: calling WindowClassChange\n"));
3027 WindowClassChange(cl, obj, (Msg)NULL);
3028 break;
3030 case IDCMP_MENUPICK:
3032 * Menu selected?
3034 if (code != MENUNULL)
3036 dragSelect:
3038 * Get the selected item.
3040 mi = ItemAddress(wd->wd_Menus, code);
3043 * Setup the return code ID.
3045 rc = (IPTR)GTMENUITEM_USERDATA(mi);
3048 * Menu a CHECKIT item?
3050 if (mi->Flags & CHECKIT)
3052 * Fix the NewMenu array to represent
3053 * any changes in the CHECKED flag.
3055 AsmDoMethod(obj, WM_CHECKITEM, rc, mi->Flags & CHECKED);
3057 * Set up the next item and say were
3058 * drag-selecting.
3060 if (mi->NextSelect != MENUNULL)
3062 wd->wd_NextSelect = mi->NextSelect;
3063 wd->wd_Flags |= WDF_DRAGSELECT;
3064 break;
3068 * Drag-selecting is done.
3070 wd->wd_Flags &= ~WDF_DRAGSELECT;
3071 break;
3073 case IDCMP_MENUHELP:
3075 * Get the selected item.
3077 mi = ItemAddress(wd->wd_Menus, code);
3080 * Setup the return code ID.
3082 if (mi) rc = WMHI_MENUHELP | (IPTR)GTMENUITEM_USERDATA(mi);
3083 break;
3085 case IDCMP_RAWKEY:
3086 if (code == 0x45)
3089 * Close on ESC?
3091 if (wd->wd_Flags & WDF_CLOSEONESC)
3093 rc = WMHI_CLOSEWINDOW;
3094 break;
3097 if (code == 0x5F)
3100 * HELP!!!!
3102 WindowClassHelp(cl, obj, NULL);
3103 break;
3106 * See if this key triggers a gadget activation.
3108 rc = KeyGadget(cl, obj, imsg);
3110 * The KeyGadget() routine has already replied the message for us.
3112 imsg = NULL;
3113 break;
3115 case IDCMP_GADGETUP:
3116 rc = GADGET(imsg->IAddress)->GadgetID;
3117 break;
3119 case IDCMP_IDCMPUPDATE:
3121 * IDCMP_IDCMPUPDATE handles the messages from
3122 * slider, scroller objects and tab-cycling.
3124 attr = (struct TagItem *)imsg->IAddress;
3127 * GA_ID makes sure it's comes from a gadget.
3129 if ((tag = FindTagItem(GA_ID, attr)))
3132 * Pick up ID.
3134 if (!FindTagItem(STRINGA_TextVal, attr) && !FindTagItem(STRINGA_LongVal, attr))
3135 id = tag->ti_Data;
3136 else
3137 id = WMHI_IGNORE;
3139 if ((tabbed = (Object *)GetTagData(STRINGA_Tabbed, (IPTR)NULL, attr)))
3141 forward = TRUE;
3143 * Do not notify!
3145 rc = WMHI_IGNORE;
3147 else if ((tabbed = (Object *)GetTagData(STRINGA_ShiftTabbed, (IPTR)NULL, attr)))
3149 forward = FALSE;
3151 * Do not notify!
3153 rc = WMHI_IGNORE;
3155 else if ((tabbed = (Object *)GetTagData(WINDOW_ActNext, (IPTR)NULL, attr)))
3157 forward = TRUE;
3159 * Notify.
3161 rc = id;
3163 else if ((tabbed = (Object *)GetTagData(WINDOW_ActPrev, (IPTR)NULL, attr)))
3165 forward = FALSE;
3167 * Notify.
3169 rc = id;
3173 * String gadget tabbed?
3175 if (tabbed)
3178 * Check if it's in our list.
3180 if ((tc = GetCycleNode(wd, tabbed)))
3182 nextTabbed:
3183 if (forward)
3186 * Activate next or first object.
3188 if (tc != wd->wd_CycleList.cl_Last) tc = tc->tc_Next;
3189 else tc = wd->wd_CycleList.cl_First;
3191 else
3194 * Activate previous or last object.
3196 if (tc != wd->wd_CycleList.cl_First) tc = tc->tc_Prev;
3197 else tc = wd->wd_CycleList.cl_Last;
3199 Get_Attr(tc->tc_Object, BT_Inhibit, &inhibit);
3200 if ((GADGET(tc->tc_Object)->Flags & GFLG_DISABLED) || inhibit)
3201 goto nextTabbed;
3202 ActivateGadget(GADGET(tc->tc_Object), w, NULL);
3205 else
3208 * Update notification.
3210 UpdateNotification(wd, attr, id);
3212 * Setup return code.
3214 rc = id;
3217 break;
3219 case IDCMP_INTUITICKS:
3220 if ( wd->wd_ToolTip || ( ! wd->wd_ToolTickTime ))
3221 break;
3224 * Pick up mouse coordinates.
3226 x = w->MouseX;
3227 y = w->MouseY;
3230 * Preset GRM_WHICHOBJECT method.
3232 grwo.MethodID = GRM_WHICHOBJECT;
3233 grwo.grwo_Coords.X = x;
3234 grwo.grwo_Coords.Y = y;
3237 * Did the mouse position change?
3239 if (x == wd->wd_ToolX && y == wd->wd_ToolY)
3242 * Tick delay reached?
3244 if (wd->wd_ToolTicks++ == wd->wd_ToolTickTime)
3247 * Find object under the mouse.
3249 if ((wd->wd_ToolTipObject = (Object *)AsmDoMethodA(wd->wd_Gadgets, (Msg)&grwo)))
3252 * Show the tool tip.
3254 ttc.ttc_Command = TT_SHOW;
3255 ttc.ttc_Object = wd->wd_ToolTipObject;
3256 ttc.ttc_UserData = (APTR)wd;
3258 wd->wd_ToolTip = (APTR)BGUI_CallHookPkt(wd->wd_ToolTipHook ? wd->wd_ToolTipHook : &ToolTipHook,
3259 (void *)obj, (void *)&ttc);
3263 * Clear tip data.
3265 wd->wd_ToolTicks = 0;
3267 } else {
3268 wd->wd_ToolX = x;
3269 wd->wd_ToolY = y;
3271 break;
3275 * Reply the original message.
3277 if (imsg) ReplyMsg((struct Message *)imsg);
3278 if (rc != WMHI_IGNORE) return rc;
3280 return WMHI_NOMORE;
3282 METHOD_END
3284 /// WM_GADGETKEY
3286 * Add a gadget key.
3288 STATIC METHOD(WindowClassGadgetKey, struct wmGadgetKey *, wmg)
3290 // WD *wd = INST_DATA(cl, obj);
3291 Object *ob;
3294 * Only add when the object is valid.
3296 if ((ob = wmg->wmgk_Object))
3298 DoSetMethodNG(ob, BT_Key, wmg->wmgk_Key, TAG_DONE);
3300 return 1;
3302 METHOD_END
3305 * Find a menu by it's ID.
3307 STATIC ASM struct Menu *FindMenu( REG(a0) struct Menu *ptr, REG(d0) IPTR id )
3309 struct Menu *tmp;
3311 if ((tmp = ptr)) {
3312 while ( tmp ) {
3313 if ( id == ( IPTR )GTMENU_USERDATA( tmp )) return( tmp );
3314 tmp = tmp->NextMenu;
3318 return( NULL );
3322 * Find a (sub)item by it's ID.
3324 STATIC ASM struct MenuItem *FindItem( REG(a0) struct Menu *ptr, REG(d0) IPTR id )
3326 struct Menu *tmp;
3327 struct MenuItem *item, *sub;
3329 if ((tmp = ptr)) {
3330 while ( tmp ) {
3331 if ((item = tmp->FirstItem)) {
3332 while ( item ) {
3333 if ( id == ( IPTR )GTMENUITEM_USERDATA( item )) return( item );
3334 if ((sub = item->SubItem)) {
3335 while ( sub ) {
3336 if ( id == ( IPTR )GTMENUITEM_USERDATA( sub )) return( sub );
3337 sub = sub->NextItem;
3340 item = item->NextItem;
3343 tmp = tmp->NextMenu;
3347 return( NULL );
3351 * Find a NewMenu by it's ID.
3353 STATIC ASM struct NewMenu *FindNewMenu( REG(a0) struct NewMenu *nm, REG(d0) IPTR id )
3355 while ( nm->nm_Type != NM_END ) {
3356 if ( id == ( IPTR )nm->nm_UserData ) return( nm );
3357 nm++;
3360 return( NULL );
3364 * Disable a menu.
3366 STATIC METHOD(WindowClassDisableMenu, struct wmMenuAction *, wmma )
3368 WD *wd = ( WD * )INST_DATA( cl, obj );
3369 struct Menu *menu;
3370 struct MenuItem *item;
3371 struct NewMenu *newmenu;
3372 ULONG rc = FALSE;
3375 * Is the window open and
3376 * are there menus?
3378 if ( wd->wd_Menus && wd->wd_WindowPtr ) {
3380 * Remove the menus.
3382 ClearMenuStrip( wd->wd_WindowPtr );
3383 if ((menu = FindMenu( wd->wd_Menus, wmma->wmma_MenuID ))) {
3385 * Change the menu status.
3387 if ( wmma->wmma_Set ) menu->Flags &= ~MENUENABLED;
3388 else menu->Flags |= MENUENABLED;
3389 } else if ((item = FindItem( wd->wd_Menus, wmma->wmma_MenuID ))) {
3391 * Otherwise the (sub)item status.
3393 if ( wmma->wmma_Set ) item->Flags &= ~ITEMENABLED;
3394 else item->Flags |= ITEMENABLED;
3397 * Put the menus back online.
3399 ResetMenuStrip( wd->wd_WindowPtr, wd->wd_Menus );
3403 * Also change the corresponding NewMenu accoordingly.
3405 if ( wd->wd_MenuStrip ) {
3406 if (( newmenu = FindNewMenu( wd->wd_MenuStrip, wmma->wmma_MenuID ))) {
3407 rc = TRUE;
3408 if ( newmenu->nm_Type == NM_TITLE ) {
3409 if ( wmma->wmma_Set ) newmenu->nm_Flags |= NM_MENUDISABLED;
3410 else newmenu->nm_Flags &= ~NM_MENUDISABLED;
3411 } else if ( newmenu->nm_Type != NM_END ) {
3412 if ( wmma->wmma_Set ) newmenu->nm_Flags |= NM_ITEMDISABLED;
3413 else newmenu->nm_Flags &= ~NM_ITEMDISABLED;
3418 return( rc );
3420 METHOD_END
3423 * (Un)check an item.
3425 STATIC METHOD(WindowClassCheckItem, struct wmMenuAction *,wmma )
3427 WD *wd = ( WD * )INST_DATA( cl, obj );
3428 struct MenuItem *item;
3429 struct NewMenu *newmenu;
3430 ULONG rc = FALSE;
3433 * Is the window open and are there menus?
3435 if ( wd->wd_Menus && wd->wd_WindowPtr ) {
3437 * Remove the menus.
3439 ClearMenuStrip( wd->wd_WindowPtr );
3441 * Find the item and change it's
3442 * CHECKED status.
3444 if (( item = FindItem( wd->wd_Menus, wmma->wmma_MenuID ))) {
3445 if ( wmma->wmma_Set ) item->Flags |= CHECKED;
3446 else item->Flags &= ~CHECKED;
3449 * Put the menus back online.
3451 ResetMenuStrip( wd->wd_WindowPtr, wd->wd_Menus );
3455 * Change the corresponding NewMenu accoordingly.
3457 if ( wd->wd_MenuStrip ) {
3458 if (( newmenu = FindNewMenu( wd->wd_MenuStrip, wmma->wmma_MenuID ))) {
3459 rc = TRUE;
3460 if ( wmma->wmma_Set ) newmenu->nm_Flags |= CHECKED;
3461 else newmenu->nm_Flags &= ~CHECKED;
3465 return( rc );
3467 METHOD_END
3470 * Ask for the disabled status of a menu or (sub)item.
3472 STATIC METHOD(WindowClassMenuDisabled, struct wmMenuQuery *, wmmq)
3474 struct NewMenu *newmenu;
3475 WD *wd = ( WD * )INST_DATA( cl, obj );
3477 if ( wd->wd_MenuStrip ) {
3478 if (( newmenu = FindNewMenu( wd->wd_MenuStrip, wmmq->wmmq_MenuID ))) {
3479 if ( newmenu->nm_Type == NM_TITLE )
3480 return (ULONG)(newmenu->nm_Flags & NM_MENUDISABLED ? 1 : 0);
3481 else if ( newmenu->nm_Type != NM_END )
3482 return (ULONG)(newmenu->nm_Flags & NM_ITEMDISABLED ? 1 : 0);
3486 return ~0;
3488 METHOD_END
3491 * Ask for the CHECKED status of a (sub)item.
3493 STATIC METHOD(WindowClassItemChecked, struct wmMenuQuery *, wmmq)
3495 struct NewMenu *newmenu;
3496 WD *wd = ( WD * )INST_DATA( cl, obj );
3498 if ( wd->wd_MenuStrip ) {
3499 if (( newmenu = FindNewMenu( wd->wd_MenuStrip, wmmq->wmmq_MenuID )))
3500 return (ULONG)(newmenu->nm_Flags & CHECKED ? 1 : 0);
3503 return ~0;
3505 METHOD_END
3508 * Add an objects to the tab-cycle list.
3510 STATIC METHOD(WindowClassCycleOrder, struct wmTabCycleOrder *, tco)
3512 WD *wd = INST_DATA( cl, obj );
3513 TABCYCLE *tc;
3514 Object **ob = &tco->wtco_Object1;
3515 ULONG rc = 1;
3518 * Cycle through list of objects.
3520 while (*ob)
3523 * Allocate tab-cycle node.
3525 if ((tc = (TABCYCLE *)BGUI_AllocPoolMem(sizeof(TABCYCLE))))
3528 * Initialize structure.
3530 tc->tc_Object = *ob;
3532 * Setup the object for tab-cycling.
3534 DoSetMethodNG( *ob, GA_TabCycle, TRUE, ICA_TARGET, ICTARGET_IDCMP, TAG_END );
3536 * Add it to the list.
3538 AddTail(( struct List * )&wd->wd_CycleList, ( struct Node * )tc );
3539 } else
3540 rc = 0;
3541 ob++;
3543 return rc;
3545 METHOD_END
3546 /// WM_GETAPPMSG
3548 * Obtain an AppMessage.
3550 STATIC METHOD(WindowClassGetAppMsg, Msg, msg)
3552 WD *wd = INST_DATA(cl, obj);
3553 IPTR rc = 0;
3556 * Pop a message from the App port.
3558 if (wd->wd_AppPort)
3559 rc = (IPTR)GetMsg(wd->wd_AppPort);
3561 return rc;
3563 METHOD_END
3565 /// WM_ADDUPDATE
3567 * Add a target to the update notification list.
3569 STATIC METHOD(WindowClassAddUpdate, struct wmAddUpdate *, wmau)
3571 WD *wd = INST_DATA(cl, obj);
3572 UPN *up;
3573 ULONG rc = 0;
3576 * Valid target?
3578 if (wmau->wmau_Target)
3581 * Allocate node.
3583 if ((up = (UPN *)BGUI_AllocPoolMem(sizeof(UPN))))
3586 * Initialize node.
3588 up->up_ID = wmau->wmau_SourceID;
3589 up->up_Target = wmau->wmau_Target;
3590 up->up_MapList = wmau->wmau_MapList;
3592 * Add it to the list.
3594 AddTail((struct List *)&wd->wd_UpdateList, (struct Node *)up);
3595 rc = 1;
3598 return rc;
3600 METHOD_END
3602 /// WM_REPORT_ID
3604 * Report an ID.
3606 * Changes made by T.Herold: Passes task to AddIDReport
3608 STATIC METHOD(WindowClassReportID, struct wmReportID *, wmri)
3610 WD *wd = INST_DATA(cl, obj);
3611 ULONG rc = 0;
3612 struct Task *task;
3613 struct Window *w;
3615 * Get task to signal.
3617 if (wmri->wmri_Flags & WMRIF_TASK)
3618 task = wmri->wmri_SigTask;
3619 else
3620 task = wd->wd_UserPort->mp_SigTask;
3623 * Add ID node.
3625 if ((w = wd->wd_WindowPtr))
3627 rc = AddIDReport(w, wmri->wmri_ID, task);
3629 * Double-click?
3631 if (wmri->wmri_Flags & WMRIF_DOUBLE_CLICK)
3633 rc = AddIDReport(w, wmri->wmri_ID, task);
3636 * Set signal.
3638 if (task) Signal(task, (1 << wd->wd_UserPort->mp_SigBit));
3640 return rc;
3642 METHOD_END
3645 * Get a pointer to the window that signalled us.
3647 STATIC METHOD(WindowClassGetSigWin, Msg, msg )
3649 WD *wd = ( WD * )INST_DATA( cl, obj );
3650 struct Window *win;
3653 * Shared message port?
3655 if ( wd->wd_Flags & WDF_SHARED_MSGPORT ) {
3657 * Any messages at the port?
3659 if ( wd->wd_UserPort->mp_MsgList.lh_Head->ln_Succ )
3661 * Yes. Get the first.
3663 win = (( struct IntuiMessage * )wd->wd_UserPort->mp_MsgList.lh_Head )->IDCMPWindow;
3664 else
3666 * Try for the first reported ID.
3668 win = GetFirstIDReportWindow();
3669 } else
3671 * This window.
3673 win = wd->wd_WindowPtr;
3675 return (IPTR)win;
3677 METHOD_END
3680 * Remove an object from the tab-cycle list.
3682 STATIC METHOD(WindowClassRemove, struct wmRemoveObject *, wmro )
3684 WD *wd = ( WD * )INST_DATA( cl, obj );
3685 TABCYCLE *cyc;
3687 if ( wmro->wmro_Object ) {
3688 if ( wmro->wmro_Flags & WMROF_CYCLE_LIST ) {
3689 if (( cyc = GetCycleNode( wd, wmro->wmro_Object ))) {
3690 Remove(( struct Node * )cyc );
3691 BGUI_FreePoolMem( cyc );
3694 return( TRUE );
3696 return( FALSE );
3698 METHOD_END
3700 /// WM_SECURE
3702 * Secure the master gadget by removing it.
3704 STATIC METHOD(WindowClassSecure, Msg, msg)
3706 WD *wd = INST_DATA(cl, obj);
3707 ULONG rc = 0;
3708 struct Window *w;
3711 * Window Open?
3713 if ((w = wd->wd_WindowPtr))
3716 * Yes. Master gadget attached?
3718 if (!(wd->wd_Flags & WDF_REMOVED))
3721 * No. Remove it now.
3723 wd->wd_Flags |= WDF_REMOVED;
3724 RemoveGadget(w, (struct Gadget *)wd->wd_Gadgets);
3726 rc = 1;
3728 return rc;
3730 METHOD_END
3732 /// WM_RELEASE
3734 * Release the master gadget by adding it.
3736 STATIC METHOD(WindowClassRelease, Msg, msg)
3738 WD *wd = INST_DATA(cl, obj);
3739 ULONG rc = 0;
3740 struct Window *w;
3742 WW(kprintf("WindowClassRelease:\n"));
3745 * Window Open?
3747 if ((w = wd->wd_WindowPtr))
3749 WW(kprintf("WindowClassRelease: window is open\n"));
3751 * Yes. Master gadget removed?
3753 if (wd->wd_Flags & WDF_REMOVED)
3755 WW(kprintf("WindowClassRelease: WDF_REMOVED set = master gadget was removed. Calling AddGadget\n"));
3757 * Put the master back on-line.
3759 AddGadget(w, (struct Gadget *)wd->wd_Gadgets, -1);
3760 WW(kprintf("WindowClassRelease: clearing WDF_REMOVED flag\n"));
3762 wd->wd_Flags &= ~WDF_REMOVED;
3765 WW(kprintf("WindowClassRelease: calling RefreshGList: gad = %x\n", (struct Gadget *)wd->wd_Gadgets));
3767 rc = 1;
3769 return rc;
3771 METHOD_END
3773 /// WM_RELAYOUT
3775 * Relayout the GUI.
3777 STATIC METHOD(WindowClassRelayout, Msg, msg)
3779 WD *wd = INST_DATA(cl, obj);
3780 WORD newl, newt, neww, newh;
3781 UWORD min_x, min_y, max_x, max_y;
3782 BOOL lock_w = wd->wd_Flags & WDF_LOCK_WIDTH;
3783 BOOL lock_h = wd->wd_Flags & WDF_LOCK_HEIGHT;
3784 struct Window *w;
3785 struct Screen *s = wd->wd_Screen;
3787 WW(kprintf("** WindowClassRelayout\n"));
3789 * Window open?
3791 if ((w = wd->wd_WindowPtr))
3793 WW(kprintf("** WindowClassRelayout: window is open. calling WM_SECURE\n"));
3794 AsmDoMethod(obj, WM_SECURE);
3795 WW(kprintf("** WindowClassRelayout: calling WinSize\n"));
3797 if (!WinSize(wd, &min_x, &min_y))
3799 AsmDoMethod(obj, WM_RELEASE);
3800 return 0;
3802 WW(kprintf("** WindowClassRelayout: WinSize call ok min_x = %d, min_y = %d\n", min_x, min_y));
3805 * Pick up old minimum width and height.
3807 max_x = w->MaxWidth;
3808 max_y = w->MaxHeight;
3810 if (!(wd->wd_WindowFlags & WFLG_BACKDROP))
3813 * Default window position/size.
3815 newl = w->LeftEdge;
3816 newt = w->TopEdge;
3817 neww = w->Width;
3818 newh = w->Height;
3820 if (lock_w || (min_x > neww)) neww = min_x;
3821 if (lock_h || (min_y > newh)) newh = min_y;
3824 * Find out how much we have to
3825 * move the window.
3827 if ((newl + neww) > s->Width) newl = s->Width - neww;
3828 if ((newt + newh) > s->Height) newt = s->Height - newh;
3831 * Compute the new maximum values.
3833 if (neww > max_x) max_x = neww;
3834 if (newh > max_y) max_y = newh;
3837 * Re-size the window accoording to the master
3838 * minimum size change.
3841 WindowLimits(w, 1, 1, -1, -1);
3843 WW(kprintf("** WindowClassRelayout: Calling ChangeWindowBox(%d,%d,%d,%d)\n",newl,newt,neww,newh));
3845 ChangeWindowBox(w, newl, newt, neww, newh);
3847 wd->wd_MinW = lock_w ? neww : min_x;
3848 wd->wd_MinH = lock_h ? newh : min_y;
3849 wd->wd_MaxW = lock_w ? neww : max_x;
3850 wd->wd_MaxH = lock_h ? newh : max_y;
3851 WW(kprintf("** WindowClassRelayout: setting wd->wd_MinW/H to %d,%d wd->wd_MaxW/H to %d,%d\n",
3852 wd->wd_MinW,
3853 wd->wd_MinH,
3854 wd->wd_MaxW,
3855 wd->wd_MaxH));
3857 wd->wd_Flags |= WDF_CONSTRAINTS;
3859 else
3861 AsmDoMethod(obj, WM_RELEASE);
3864 return 1;
3866 METHOD_END
3868 /// WM_WHICHOBJECT
3870 * Find the object under the mouse.
3872 STATIC METHOD(WindowClassWhichObject, Msg, msg)
3874 WD *wd = INST_DATA(cl, obj);
3875 ULONG rc = 0;
3876 struct Window *w;
3877 WORD mx, my;
3880 * Window Open?
3882 if ((w = wd->wd_WindowPtr))
3885 * Pickup mouse coords.
3887 mx = w->MouseX;
3888 my = w->MouseY;
3891 * On the window?
3893 if ((mx >= 0) && (my >= 0) && (mx < w->Width) && (my < w->Height))
3895 * Let's see what the master returns to us.
3898 #ifdef __AROS__
3899 rc = AsmDoMethod(wd->wd_Gadgets, GRM_WHICHOBJECT, mx, my);
3900 #else
3901 rc = AsmDoMethod(wd->wd_Gadgets, GRM_WHICHOBJECT, (mx << 16) | my);
3902 #endif
3904 return rc;
3906 METHOD_END
3908 /// WM_LOCK, WM_UNLOCK
3910 STATIC METHOD(WindowClassLock, Msg, msg)
3912 WD *wd = INST_DATA(cl, obj);
3915 * Lock or unlock?
3917 if (msg->MethodID == WM_LOCK) wd->wd_Flags |= WDF_LOCKOUT;
3918 else wd->wd_Flags &= ~WDF_LOCKOUT;
3920 return 1;
3922 METHOD_END
3924 /// BASE_FINDKEY
3926 * Which object has the proper key?
3928 STATIC METHOD(WindowClassFindKey, struct bmFindKey *, bmfk)
3930 WD *wd = INST_DATA(cl, obj);
3931 Object *ob, *gr;
3933 if ((gr = wd->wd_Gadgets))
3935 if ((ob = (Object *)AsmDoMethodA(gr, (Msg)bmfk)))
3936 return (IPTR)ob;
3938 if ((gr = wd->wd_LBorder))
3940 if ((ob = (Object *)AsmDoMethodA(gr, (Msg)bmfk)))
3941 return (IPTR)ob;
3943 if ((gr = wd->wd_RBorder))
3945 if ((ob = (Object *)AsmDoMethodA(gr, (Msg)bmfk)))
3946 return (IPTR)ob;
3948 if ((gr = wd->wd_TBorder))
3950 if ((ob = (Object *)AsmDoMethodA(gr, (Msg)bmfk)))
3951 return (IPTR)ob;
3953 if ((gr = wd->wd_BBorder))
3955 if ((ob = (Object *)AsmDoMethodA(gr, (Msg)bmfk)))
3956 return (IPTR)ob;
3958 return (IPTR)NULL;
3960 METHOD_END
3962 /// BASE_KEYLABEL
3964 * Attach label keys to object.
3966 STATIC METHOD(WindowClassKeyLabel, struct bmKeyLabel *, bmkl)
3968 WD *wd = INST_DATA(cl, obj);
3969 Object *gr;
3971 if ((gr = wd->wd_Gadgets)) AsmDoMethodA(gr, (Msg)bmkl);
3972 if ((gr = wd->wd_LBorder)) AsmDoMethodA(gr, (Msg)bmkl);
3973 if ((gr = wd->wd_RBorder)) AsmDoMethodA(gr, (Msg)bmkl);
3974 if ((gr = wd->wd_TBorder)) AsmDoMethodA(gr, (Msg)bmkl);
3975 if ((gr = wd->wd_BBorder)) AsmDoMethodA(gr, (Msg)bmkl);
3977 return (IPTR)NULL;
3979 METHOD_END
3981 /// BASE_LOCALIZE
3983 * Localize window.
3985 STATIC METHOD(WindowClassLocalize, struct bmLocalize *, bml)
3987 WD *wd = INST_DATA(cl, obj);
3988 Object *gr;
3990 if ((gr = wd->wd_Gadgets)) AsmDoMethodA(gr, (Msg)bml);
3991 if ((gr = wd->wd_LBorder)) AsmDoMethodA(gr, (Msg)bml);
3992 if ((gr = wd->wd_RBorder)) AsmDoMethodA(gr, (Msg)bml);
3993 if ((gr = wd->wd_TBorder)) AsmDoMethodA(gr, (Msg)bml);
3994 if ((gr = wd->wd_BBorder)) AsmDoMethodA(gr, (Msg)bml);
3996 if (wd->wd_WindowTitleID) wd->wd_WindowTitle =
3997 BGUI_GetCatalogStr(bml->bml_Locale, wd->wd_WindowTitleID, wd->wd_WindowTitle);
3999 if (wd->wd_ScreenTitleID) wd->wd_ScreenTitle =
4000 BGUI_GetCatalogStr(bml->bml_Locale, wd->wd_ScreenTitleID, wd->wd_ScreenTitle);
4002 if (wd->wd_HelpTextID) wd->wd_HelpText =
4003 BGUI_GetCatalogStr(bml->bml_Locale, wd->wd_HelpTextID, wd->wd_HelpText);
4005 return (IPTR)NULL;
4007 METHOD_END
4009 /// WM_CLIP
4011 * Turn on or off buffer layering.
4013 STATIC METHOD(WindowClassClip, struct wmClip *, wmc)
4015 WD *wd = INST_DATA(cl, obj);
4016 struct RastPort *br = wd->wd_BufferRP;
4017 struct Rectangle *cr = wmc->wmc_Rectangle;
4018 struct Region *r = wd->wd_Region;
4019 struct Layer *wl;
4020 ULONG rc = 0;
4022 if (wd->wd_WindowPtr && (wl = wd->wd_WindowPtr->RPort->Layer))
4024 InstallClipRegion(wl, NULL);
4026 switch (wmc->wmc_Action)
4028 case CLIPACTION_NONE:
4029 if (br && br->Layer)
4031 wd->wd_BufferLayer = br->Layer;
4032 br->Layer = NULL;
4034 return 1;
4035 case CLIPACTION_CLEAR:
4036 ClearRegion(r);
4037 rc = 1;
4038 break;
4039 case CLIPACTION_OR:
4040 rc = OrRectRegion(r, cr);
4041 break;
4042 case CLIPACTION_AND:
4043 AndRectRegion(r, cr);
4044 rc = 1;
4045 break;
4048 if (rc)
4050 InstallClipRegion(wl, r);
4052 if (br)
4054 if (!br->Layer) br->Layer = wd->wd_BufferLayer;
4055 InstallClipRegion(br->Layer, r);
4059 return rc;
4061 METHOD_END
4063 STATIC METHOD(WindowClassSetupGadget, struct wmSetupGadget *, wmsg)
4065 WD *wd = INST_DATA(cl, obj);
4066 struct TagItem *tstate = wmsg->wmsg_Tags;
4067 struct TagItem *tag;
4069 while ((tag = NextTagItem(&tstate)))
4071 switch(tag->ti_Tag)
4073 case BT_Inhibit:
4074 AsmDoMethod(wmsg->wmsg_Object, BASE_INHIBIT, tag->ti_Tag);
4075 break;
4079 if(wd->wd_UsedFont
4080 || ((wd->wd_Flags & WDF_AUTOASPECT)
4081 && wd->wd_DrawInfo))
4083 struct TextAttr current_font;
4085 if(wd->wd_UsedFont)
4087 struct RastPort rp;
4089 InitRastPort(&rp);
4090 SetFont(&rp,wd->wd_UsedFont);
4091 AskFont(&rp,&current_font);
4094 SetAttrs(wmsg->wmsg_Object,
4095 wd->wd_UsedFont ? BT_TextAttr : TAG_IGNORE,&current_font,
4096 ((wd->wd_Flags & WDF_AUTOASPECT) && wd->wd_DrawInfo) ? FRM_ThinFrame : TAG_IGNORE, ((wd->wd_DrawInfo->dri_Resolution.X / wd->wd_DrawInfo->dri_Resolution.Y) <= 1),
4097 TAG_END);
4099 return(1);
4101 METHOD_END
4104 /// Class initialization.
4107 * Class function table.
4109 STATIC DPFUNC ClassFunc[] = {
4110 { OM_NEW, WindowClassNew },
4111 { OM_SET, WindowClassSetUpdate },
4112 { OM_UPDATE, WindowClassSetUpdate },
4113 { OM_GET, WindowClassGet },
4114 { OM_DISPOSE, WindowClassDispose },
4115 { WM_OPEN, WindowClassOpen },
4116 { WM_CLOSE, WindowClassClose },
4117 { WM_SLEEP, WindowClassSleep },
4118 { WM_WAKEUP, WindowClassWakeUp },
4119 { WM_HANDLEIDCMP, WindowClassIDCMP },
4120 { WM_GADGETKEY, WindowClassGadgetKey },
4121 { WM_DISABLEMENU, WindowClassDisableMenu },
4122 { WM_CHECKITEM, WindowClassCheckItem },
4123 { WM_MENUDISABLED, WindowClassMenuDisabled },
4124 { WM_ITEMCHECKED, WindowClassItemChecked },
4125 { WM_TABCYCLE_ORDER, WindowClassCycleOrder },
4126 { WM_GETAPPMSG, WindowClassGetAppMsg },
4127 { WM_ADDUPDATE, WindowClassAddUpdate },
4128 { WM_REPORT_ID, WindowClassReportID },
4129 { WM_GET_SIGNAL_WINDOW, WindowClassGetSigWin },
4130 { WM_REMOVE_OBJECT, WindowClassRemove },
4132 { WM_SECURE, WindowClassSecure },
4133 { WM_RELEASE, WindowClassRelease },
4134 { WM_RELAYOUT, WindowClassRelayout },
4135 { WM_WHICHOBJECT, WindowClassWhichObject },
4136 { WM_LOCK, WindowClassLock },
4137 { WM_UNLOCK, WindowClassLock },
4138 { WM_CLOSETOOLTIP, WindowClassCloseTT },
4139 { WM_CLIP, WindowClassClip },
4140 { WM_SETUPGADGET, WindowClassSetupGadget },
4142 { BASE_FINDKEY, WindowClassFindKey },
4143 { BASE_KEYLABEL, WindowClassKeyLabel },
4144 { BASE_LOCALIZE, WindowClassLocalize },
4146 { DF_END }
4150 * Simple class initialization.
4152 makeproto Class *InitWindowClass(void)
4154 return WindowClass = BGUI_MakeClass(CLASS_SuperClassBGUI, BGUI_ROOT_OBJECT,
4155 CLASS_ObjectSize, sizeof(WD),
4156 CLASS_DFTable, ClassFunc,
4157 TAG_DONE);