disable the unrecognized nls flag
[AROS-Contrib.git] / bgui / windowclass.c
blob6ea969aed49f04a227d7f16d1589e8771f0b89c9
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 struct BaseInfo *bi;
2603 switch (ttc->ttc_Command)
2605 case TT_SHOW:
2606 wd = (WD *)ttc->ttc_UserData;
2609 * Does the tip-object have a tool-tip?
2611 tc = NULL;
2612 Get_Attr(ttc->ttc_Object, BT_ToolTip, (IPTR *)&tc);
2613 if (tc)
2616 * Copy and setup the tip.
2618 if ((tip = (UBYTE *)BGUI_AllocPoolMem(strlen(tc) + 10)))
2620 struct {
2621 ULONG a;
2622 CONST_STRPTR b;
2623 } __packed args = { BARDETAILPEN, tc };
2624 DoSPrintF(tip, "\033d%ld%s", (RAWARG)&args);
2626 else
2628 tip = tc;
2629 tc = NULL;
2632 rp = wd->wd_WindowPtr->RPort;
2635 * Set the font.
2637 of = rp->Font;
2638 FSetFont(rp, wd->wd_UsedFont);
2640 BGUI_InfoTextSize(rp, tip, (UWORD *)&ibx.Width, (UWORD *)&ibx.Height);
2641 FSetFont(rp, of);
2644 * Get mouse position.
2646 x = wd->wd_WindowPtr->MouseX;
2647 y = wd->wd_WindowPtr->MouseY;
2650 * Tool-tip width and height.
2652 ww = ibx.Width + 8;
2653 wh = ibx.Height + 4;
2656 * Open tool-tip window with it's
2657 * bottom right corner under the mouse.
2659 if ((tw = OpenWindowTags(NULL,WA_Left, wd->wd_WindowPtr->LeftEdge + x - ww,
2660 WA_Top, wd->wd_WindowPtr->TopEdge + y - wh,
2661 WA_Width, ww,
2662 WA_Height, wh,
2663 WA_IDCMP, 0,
2664 WA_Flags, WFLG_BORDERLESS|WFLG_RMBTRAP,
2665 WA_CustomScreen, wd->wd_Screen,
2666 TAG_DONE)))
2668 rp = tw->RPort;
2670 #ifdef DEBUG_BGUI
2671 if ((bi = AllocBaseInfoDebug(__FILE__,__LINE__,BI_Screen, wd->wd_Screen, BI_RastPort, rp, TAG_DONE)))
2672 #else
2673 if ((bi = AllocBaseInfo(BI_Screen, wd->wd_Screen, BI_RastPort, rp, TAG_DONE)))
2674 #endif
2677 * Set the font.
2679 of = rp->Font;
2680 BSetFont(bi, wd->wd_UsedFont);
2683 * Tip background color.
2685 BSetDrMd(bi, JAM1);
2686 BSetDPenA(bi, BARBLOCKPEN);
2687 BRectFill(bi, 1, 1, ww - 2, wh - 2);
2690 * Tip border and text.
2692 BSetDPenA(bi, BARDETAILPEN);
2693 Move(rp, 0, 0);
2694 Draw(rp, ww - 1, 0);
2695 Draw(rp, ww - 1, wh - 1);
2696 Draw(rp, 0, wh - 1);
2697 Draw(rp, 0, 0);
2700 * Render the tip.
2702 ibx.Left = 4;
2703 ibx.Top = 2;
2705 RenderText(bi, tip, &ibx);
2706 BSetFont(bi, of);
2708 FreeBaseInfo(bi);
2711 * Free copy.
2713 if (tc) BGUI_FreePoolMem(tip);
2715 break;
2717 case TT_HIDE:
2718 tw = (struct Window *)ttc->ttc_UserData;
2719 if (tw) CloseWindow(tw);
2720 break;
2723 return (IPTR)tw;
2725 REGFUNC_END
2726 static struct Hook ToolTipHook = { {NULL, NULL}, (HOOKFUNC)ToolTip_func, NULL, NULL };
2728 /// WM_CLOSETOOLTIP
2730 STATIC METHOD(WindowClassCloseTT, Msg, msg)
2732 WD *wd = INST_DATA(cl, obj);
2733 struct ttCommand ttc;
2735 if (wd->wd_ToolTip)
2737 ttc.ttc_Command = TT_HIDE;
2738 ttc.ttc_Object = wd->wd_ToolTipObject;
2739 ttc.ttc_UserData = (APTR)wd->wd_ToolTip;
2741 BGUI_CallHookPkt(wd->wd_ToolTipHook ? wd->wd_ToolTipHook : &ToolTipHook, (void *)obj, (void *)&ttc);
2743 wd->wd_ToolX = wd->wd_ToolY = -1;
2744 wd->wd_ToolTip = NULL;
2746 return (IPTR)TRUE;
2748 METHOD_END
2750 /// WM_HANDLEIDCMP
2752 * Handle a window's IDCMP messages.
2754 STATIC METHOD(WindowClassIDCMP, Msg, msg)
2756 struct IntuiMessage *imsg;
2757 struct TagItem *attr, *tag;
2758 struct MenuItem *mi;
2759 TABCYCLE *tc;
2760 WD *wd = INST_DATA(cl, obj);
2761 ULONG rc = WMHI_IGNORE, id;
2762 UWORD code;
2763 Object *obja;
2764 struct grmWhichObject grwo;
2765 struct ttCommand ttc;
2766 WORD x, y;
2767 IPTR mouseact, inhibit;
2768 BOOL forward;
2769 Object *tabbed;
2770 struct Window *w = wd->wd_WindowPtr;
2774 * No window!
2776 if (!w) return WMHI_NOMORE;
2779 * Locked out?
2781 if (!(wd->wd_Flags & WDF_LOCKOUT))
2784 * Are we in a drag-selection loop?
2785 * If so continue it.
2787 if (wd->wd_Flags & WDF_DRAGSELECT)
2789 code = wd->wd_NextSelect;
2790 imsg = NULL;
2791 goto dragSelect;
2795 * Reports on the stack?
2797 if ((id = GetIDReport(w)) != ~0)
2800 * Return the ID.
2802 return id;
2807 * Is there a message.
2809 while ((imsg = GetIMsg(wd)))
2812 * Any movement?
2815 BOOL close_tooltip;
2817 if(!(close_tooltip=(w->MouseX != wd->wd_ToolX || w->MouseY != wd->wd_ToolY)))
2819 switch(imsg->Class)
2822 case IDCMP_IDCMPUPDATE:
2823 case IDCMP_DISKINSERTED:
2824 case IDCMP_DISKREMOVED:
2825 case IDCMP_WBENCHMESSAGE:
2826 case IDCMP_INTUITICKS:
2827 break;
2828 default:
2829 close_tooltip=TRUE;
2830 break;
2833 if(close_tooltip)
2836 * Do we have a tool-tip to close?
2838 if (wd->wd_ToolTip)
2839 AsmDoMethod(obj, WM_CLOSETOOLTIP);
2840 else
2841 wd->wd_ToolTicks = 0;
2846 * Are we locked out?
2848 if (wd->wd_Flags & WDF_LOCKOUT)
2851 * Yes. Reply this message and continue.
2853 ReplyMsg((struct Message *)imsg);
2854 continue;
2858 * Call the hook for the xxxxVERIFY messages
2859 * if one exists.
2861 if (wd->wd_VerifyHook)
2863 if ((wd->wd_VerifyHookBits & imsg->Class) == imsg->Class)
2865 BGUI_CallHookPkt(wd->wd_VerifyHook, (void *)obj, (void *)imsg);
2866 ReplyMsg((struct Message *)imsg);
2867 return rc;
2872 * Call the IDCMPHook when it's available.
2875 if (wd->wd_IDCMPHook && (wd->wd_IDCMPHookBits & imsg->Class))
2877 BGUI_CallHookPkt(wd->wd_IDCMPHook, (VOID *)obj, (VOID *)imsg);
2880 code = imsg->Code;
2882 switch (imsg->Class)
2884 case IDCMP_SIZEVERIFY:
2886 * Save window size and remove
2887 * the master.
2889 wd->wd_OW = w->Width;
2890 wd->wd_OH = w->Height;
2891 if (!(wd->wd_Flags & WDF_REMOVED))
2893 wd->wd_Flags |= WDF_REMOVED;
2894 RemoveGadget(w, (struct Gadget *)wd->wd_Gadgets);
2896 break;
2898 case IDCMP_NEWSIZE:
2899 WW(kprintf("WindowClassIDCMP: received IDCMP_NEWSIZE\n"));
2901 * If we have manually removed the
2902 * master object we adjust the size
2903 * ourselves.
2905 if (wd->wd_Flags & WDF_REMOVED)
2908 * Setup new size for the master.
2910 DoSetMethodNG(wd->wd_Gadgets, GA_Left, w->BorderLeft,
2911 GA_Top, w->BorderTop,
2912 GA_RelWidth, -(w->BorderLeft + w->BorderRight ),
2913 GA_RelHeight, -(w->BorderTop + w->BorderBottom),
2914 TAG_END);
2916 * Put master back online.
2918 AddGadget(w, (struct Gadget *)wd->wd_Gadgets, -1);
2921 * Clear removed flag.
2923 wd->wd_Flags &= ~WDF_REMOVED;
2926 * Only refresh the window when the
2927 * size actually changed.
2932 if ((w->Width != wd->wd_OW) || (w->Height != wd->wd_OH))
2933 RefreshWindowFrame(w);
2935 break;
2937 case IDCMP_MOUSEBUTTONS:
2938 if ((code | IECODE_UP_PREFIX) != SELECTUP)
2941 * Preset GRM_WHICHOBJECT method.
2943 grwo.MethodID = GRM_WHICHOBJECT;
2944 grwo.grwo_Coords.X = imsg->MouseX;
2945 grwo.grwo_Coords.Y = imsg->MouseY;
2947 if ((obja = (Object *)AsmDoMethodA(wd->wd_Gadgets, (Msg)&grwo)))
2949 Get_Attr(obja, BT_MouseActivation, &mouseact);
2951 if (((mouseact & MOUSEACT_RMB_ACTIVE) && (code == IECODE_RBUTTON))
2952 || ((mouseact & MOUSEACT_MMB_ACTIVE) && (code == IECODE_MBUTTON)))
2954 SetAttrs(obja, BT_ReportID,
2955 ((mouseact & MOUSEACT_RMB_REPORT) && (code == IECODE_RBUTTON)) ||
2956 ((mouseact & MOUSEACT_MMB_REPORT) && (code == IECODE_MBUTTON)), TAG_DONE);
2958 if (wd->wd_DGMObject)
2960 DoSetMethodNG(wd->wd_DGMObject, DGM_Object, obja, DGM_IntuiMsg, imsg,TAG_END);
2961 ActivateGadget((struct Gadget *)wd->wd_DGMObject, w, NULL);
2966 break;
2968 case IDCMP_MOUSEMOVE:
2969 if (wd->wd_WindowFlags & WFLG_RMBTRAP)
2971 Forbid();
2972 wd->wd_WindowPtr->Flags |= WFLG_RMBTRAP;
2973 Permit();
2975 else
2977 mouseact = 0;
2979 * Preset GRM_WHICHOBJECT method.
2981 grwo.MethodID = GRM_WHICHOBJECT;
2982 grwo.grwo_Coords.X = imsg->MouseX;
2983 grwo.grwo_Coords.Y = imsg->MouseY;
2985 if ((obja = (Object *)AsmDoMethodA(wd->wd_Gadgets, (Msg)&grwo)))
2987 Get_Attr(obja, BT_MouseActivation, &mouseact);
2990 Forbid();
2991 if (mouseact & MOUSEACT_RMB_ACTIVE)
2993 wd->wd_WindowPtr->Flags |= WFLG_RMBTRAP;
2995 else
2997 wd->wd_WindowPtr->Flags &= ~WFLG_RMBTRAP;
2999 Permit();
3001 break;
3003 case IDCMP_ACTIVEWINDOW:
3004 rc = WMHI_ACTIVE;
3005 break;
3007 case IDCMP_INACTIVEWINDOW:
3008 rc = WMHI_INACTIVE;
3009 break;
3011 case IDCMP_CLOSEWINDOW:
3012 rc = WMHI_CLOSEWINDOW;
3013 break;
3015 case IDCMP_CHANGEWINDOW:
3016 WW(kprintf("WindowClassIDCMP: received IDCMP_CHANGEWINDOW\n"));
3017 if (wd->wd_Flags & WDF_CONSTRAINTS)
3019 WW(kprintf("WindowClassIDCMP: WDF_CONSTRAINTS is set\n"));
3020 WW(kprintf("WindowClassIDCMP: calling WindowLimits(%d,%d,%d,%d)\n",wd->wd_MinW,wd->wd_MinH,wd->wd_MaxW,wd->wd_MaxH));
3021 WindowLimits(w, wd->wd_MinW, wd->wd_MinH, wd->wd_MaxW, wd->wd_MaxH);
3022 wd->wd_Flags &= ~WDF_CONSTRAINTS;
3024 WW(kprintf("WindowClassIDCMP: calling WM_RELEASE\n"));
3025 AsmDoMethod(obj, WM_RELEASE);
3027 WW(kprintf("WindowClassIDCMP: calling WindowClassChange\n"));
3028 WindowClassChange(cl, obj, (Msg)NULL);
3029 break;
3031 case IDCMP_MENUPICK:
3033 * Menu selected?
3035 if (code != MENUNULL)
3037 dragSelect:
3039 * Get the selected item.
3041 mi = ItemAddress(wd->wd_Menus, code);
3044 * Setup the return code ID.
3046 rc = (IPTR)GTMENUITEM_USERDATA(mi);
3049 * Menu a CHECKIT item?
3051 if (mi->Flags & CHECKIT)
3053 * Fix the NewMenu array to represent
3054 * any changes in the CHECKED flag.
3056 AsmDoMethod(obj, WM_CHECKITEM, rc, mi->Flags & CHECKED);
3058 * Set up the next item and say were
3059 * drag-selecting.
3061 if (mi->NextSelect != MENUNULL)
3063 wd->wd_NextSelect = mi->NextSelect;
3064 wd->wd_Flags |= WDF_DRAGSELECT;
3065 break;
3069 * Drag-selecting is done.
3071 wd->wd_Flags &= ~WDF_DRAGSELECT;
3072 break;
3074 case IDCMP_MENUHELP:
3076 * Get the selected item.
3078 mi = ItemAddress(wd->wd_Menus, code);
3081 * Setup the return code ID.
3083 if (mi) rc = WMHI_MENUHELP | (IPTR)GTMENUITEM_USERDATA(mi);
3084 break;
3086 case IDCMP_RAWKEY:
3087 if (code == 0x45)
3090 * Close on ESC?
3092 if (wd->wd_Flags & WDF_CLOSEONESC)
3094 rc = WMHI_CLOSEWINDOW;
3095 break;
3098 if (code == 0x5F)
3101 * HELP!!!!
3103 WindowClassHelp(cl, obj, NULL);
3104 break;
3107 * See if this key triggers a gadget activation.
3109 rc = KeyGadget(cl, obj, imsg);
3111 * The KeyGadget() routine has already replied the message for us.
3113 imsg = NULL;
3114 break;
3116 case IDCMP_GADGETUP:
3117 rc = GADGET(imsg->IAddress)->GadgetID;
3118 break;
3120 case IDCMP_IDCMPUPDATE:
3122 * IDCMP_IDCMPUPDATE handles the messages from
3123 * slider, scroller objects and tab-cycling.
3125 attr = (struct TagItem *)imsg->IAddress;
3128 * GA_ID makes sure it's comes from a gadget.
3130 if ((tag = FindTagItem(GA_ID, attr)))
3133 * Pick up ID.
3135 if (!FindTagItem(STRINGA_TextVal, attr) && !FindTagItem(STRINGA_LongVal, attr))
3136 id = tag->ti_Data;
3137 else
3138 id = WMHI_IGNORE;
3140 if ((tabbed = (Object *)GetTagData(STRINGA_Tabbed, (IPTR)NULL, attr)))
3142 forward = TRUE;
3144 * Do not notify!
3146 rc = WMHI_IGNORE;
3148 else if ((tabbed = (Object *)GetTagData(STRINGA_ShiftTabbed, (IPTR)NULL, attr)))
3150 forward = FALSE;
3152 * Do not notify!
3154 rc = WMHI_IGNORE;
3156 else if ((tabbed = (Object *)GetTagData(WINDOW_ActNext, (IPTR)NULL, attr)))
3158 forward = TRUE;
3160 * Notify.
3162 rc = id;
3164 else if ((tabbed = (Object *)GetTagData(WINDOW_ActPrev, (IPTR)NULL, attr)))
3166 forward = FALSE;
3168 * Notify.
3170 rc = id;
3174 * String gadget tabbed?
3176 if (tabbed)
3179 * Check if it's in our list.
3181 if ((tc = GetCycleNode(wd, tabbed)))
3183 nextTabbed:
3184 if (forward)
3187 * Activate next or first object.
3189 if (tc != wd->wd_CycleList.cl_Last) tc = tc->tc_Next;
3190 else tc = wd->wd_CycleList.cl_First;
3192 else
3195 * Activate previous or last object.
3197 if (tc != wd->wd_CycleList.cl_First) tc = tc->tc_Prev;
3198 else tc = wd->wd_CycleList.cl_Last;
3200 Get_Attr(tc->tc_Object, BT_Inhibit, &inhibit);
3201 if ((GADGET(tc->tc_Object)->Flags & GFLG_DISABLED) || inhibit)
3202 goto nextTabbed;
3203 ActivateGadget(GADGET(tc->tc_Object), w, NULL);
3206 else
3209 * Update notification.
3211 UpdateNotification(wd, attr, id);
3213 * Setup return code.
3215 rc = id;
3218 break;
3220 case IDCMP_INTUITICKS:
3221 if ( wd->wd_ToolTip || ( ! wd->wd_ToolTickTime ))
3222 break;
3225 * Pick up mouse coordinates.
3227 x = w->MouseX;
3228 y = w->MouseY;
3231 * Preset GRM_WHICHOBJECT method.
3233 grwo.MethodID = GRM_WHICHOBJECT;
3234 grwo.grwo_Coords.X = x;
3235 grwo.grwo_Coords.Y = y;
3238 * Did the mouse position change?
3240 if (x == wd->wd_ToolX && y == wd->wd_ToolY)
3243 * Tick delay reached?
3245 if (wd->wd_ToolTicks++ == wd->wd_ToolTickTime)
3248 * Find object under the mouse.
3250 if ((wd->wd_ToolTipObject = (Object *)AsmDoMethodA(wd->wd_Gadgets, (Msg)&grwo)))
3253 * Show the tool tip.
3255 ttc.ttc_Command = TT_SHOW;
3256 ttc.ttc_Object = wd->wd_ToolTipObject;
3257 ttc.ttc_UserData = (APTR)wd;
3259 wd->wd_ToolTip = (APTR)BGUI_CallHookPkt(wd->wd_ToolTipHook ? wd->wd_ToolTipHook : &ToolTipHook,
3260 (void *)obj, (void *)&ttc);
3264 * Clear tip data.
3266 wd->wd_ToolTicks = 0;
3268 } else {
3269 wd->wd_ToolX = x;
3270 wd->wd_ToolY = y;
3272 break;
3276 * Reply the original message.
3278 if (imsg) ReplyMsg((struct Message *)imsg);
3279 if (rc != WMHI_IGNORE) return rc;
3281 return WMHI_NOMORE;
3283 METHOD_END
3285 /// WM_GADGETKEY
3287 * Add a gadget key.
3289 STATIC METHOD(WindowClassGadgetKey, struct wmGadgetKey *, wmg)
3291 // WD *wd = INST_DATA(cl, obj);
3292 Object *ob;
3295 * Only add when the object is valid.
3297 if ((ob = wmg->wmgk_Object))
3299 DoSetMethodNG(ob, BT_Key, wmg->wmgk_Key, TAG_DONE);
3301 return 1;
3303 METHOD_END
3306 * Find a menu by it's ID.
3308 STATIC ASM struct Menu *FindMenu( REG(a0) struct Menu *ptr, REG(d0) IPTR id )
3310 struct Menu *tmp;
3312 if ((tmp = ptr)) {
3313 while ( tmp ) {
3314 if ( id == ( IPTR )GTMENU_USERDATA( tmp )) return( tmp );
3315 tmp = tmp->NextMenu;
3319 return( NULL );
3323 * Find a (sub)item by it's ID.
3325 STATIC ASM struct MenuItem *FindItem( REG(a0) struct Menu *ptr, REG(d0) IPTR id )
3327 struct Menu *tmp;
3328 struct MenuItem *item, *sub;
3330 if ((tmp = ptr)) {
3331 while ( tmp ) {
3332 if ((item = tmp->FirstItem)) {
3333 while ( item ) {
3334 if ( id == ( IPTR )GTMENUITEM_USERDATA( item )) return( item );
3335 if ((sub = item->SubItem)) {
3336 while ( sub ) {
3337 if ( id == ( IPTR )GTMENUITEM_USERDATA( sub )) return( sub );
3338 sub = sub->NextItem;
3341 item = item->NextItem;
3344 tmp = tmp->NextMenu;
3348 return( NULL );
3352 * Find a NewMenu by it's ID.
3354 STATIC ASM struct NewMenu *FindNewMenu( REG(a0) struct NewMenu *nm, REG(d0) IPTR id )
3356 while ( nm->nm_Type != NM_END ) {
3357 if ( id == ( IPTR )nm->nm_UserData ) return( nm );
3358 nm++;
3361 return( NULL );
3365 * Disable a menu.
3367 STATIC METHOD(WindowClassDisableMenu, struct wmMenuAction *, wmma )
3369 WD *wd = ( WD * )INST_DATA( cl, obj );
3370 struct Menu *menu;
3371 struct MenuItem *item;
3372 struct NewMenu *newmenu;
3373 ULONG rc = FALSE;
3376 * Is the window open and
3377 * are there menus?
3379 if ( wd->wd_Menus && wd->wd_WindowPtr ) {
3381 * Remove the menus.
3383 ClearMenuStrip( wd->wd_WindowPtr );
3384 if ((menu = FindMenu( wd->wd_Menus, wmma->wmma_MenuID ))) {
3386 * Change the menu status.
3388 if ( wmma->wmma_Set ) menu->Flags &= ~MENUENABLED;
3389 else menu->Flags |= MENUENABLED;
3390 } else if ((item = FindItem( wd->wd_Menus, wmma->wmma_MenuID ))) {
3392 * Otherwise the (sub)item status.
3394 if ( wmma->wmma_Set ) item->Flags &= ~ITEMENABLED;
3395 else item->Flags |= ITEMENABLED;
3398 * Put the menus back online.
3400 ResetMenuStrip( wd->wd_WindowPtr, wd->wd_Menus );
3404 * Also change the corresponding NewMenu accoordingly.
3406 if ( wd->wd_MenuStrip ) {
3407 if (( newmenu = FindNewMenu( wd->wd_MenuStrip, wmma->wmma_MenuID ))) {
3408 rc = TRUE;
3409 if ( newmenu->nm_Type == NM_TITLE ) {
3410 if ( wmma->wmma_Set ) newmenu->nm_Flags |= NM_MENUDISABLED;
3411 else newmenu->nm_Flags &= ~NM_MENUDISABLED;
3412 } else if ( newmenu->nm_Type != NM_END ) {
3413 if ( wmma->wmma_Set ) newmenu->nm_Flags |= NM_ITEMDISABLED;
3414 else newmenu->nm_Flags &= ~NM_ITEMDISABLED;
3419 return( rc );
3421 METHOD_END
3424 * (Un)check an item.
3426 STATIC METHOD(WindowClassCheckItem, struct wmMenuAction *,wmma )
3428 WD *wd = ( WD * )INST_DATA( cl, obj );
3429 struct MenuItem *item;
3430 struct NewMenu *newmenu;
3431 ULONG rc = FALSE;
3434 * Is the window open and are there menus?
3436 if ( wd->wd_Menus && wd->wd_WindowPtr ) {
3438 * Remove the menus.
3440 ClearMenuStrip( wd->wd_WindowPtr );
3442 * Find the item and change it's
3443 * CHECKED status.
3445 if (( item = FindItem( wd->wd_Menus, wmma->wmma_MenuID ))) {
3446 if ( wmma->wmma_Set ) item->Flags |= CHECKED;
3447 else item->Flags &= ~CHECKED;
3450 * Put the menus back online.
3452 ResetMenuStrip( wd->wd_WindowPtr, wd->wd_Menus );
3456 * Change the corresponding NewMenu accoordingly.
3458 if ( wd->wd_MenuStrip ) {
3459 if (( newmenu = FindNewMenu( wd->wd_MenuStrip, wmma->wmma_MenuID ))) {
3460 rc = TRUE;
3461 if ( wmma->wmma_Set ) newmenu->nm_Flags |= CHECKED;
3462 else newmenu->nm_Flags &= ~CHECKED;
3466 return( rc );
3468 METHOD_END
3471 * Ask for the disabled status of a menu or (sub)item.
3473 STATIC METHOD(WindowClassMenuDisabled, struct wmMenuQuery *, wmmq)
3475 struct NewMenu *newmenu;
3476 WD *wd = ( WD * )INST_DATA( cl, obj );
3478 if ( wd->wd_MenuStrip ) {
3479 if (( newmenu = FindNewMenu( wd->wd_MenuStrip, wmmq->wmmq_MenuID ))) {
3480 if ( newmenu->nm_Type == NM_TITLE )
3481 return (ULONG)(newmenu->nm_Flags & NM_MENUDISABLED ? 1 : 0);
3482 else if ( newmenu->nm_Type != NM_END )
3483 return (ULONG)(newmenu->nm_Flags & NM_ITEMDISABLED ? 1 : 0);
3487 return ~0;
3489 METHOD_END
3492 * Ask for the CHECKED status of a (sub)item.
3494 STATIC METHOD(WindowClassItemChecked, struct wmMenuQuery *, wmmq)
3496 struct NewMenu *newmenu;
3497 WD *wd = ( WD * )INST_DATA( cl, obj );
3499 if ( wd->wd_MenuStrip ) {
3500 if (( newmenu = FindNewMenu( wd->wd_MenuStrip, wmmq->wmmq_MenuID )))
3501 return (ULONG)(newmenu->nm_Flags & CHECKED ? 1 : 0);
3504 return ~0;
3506 METHOD_END
3509 * Add an objects to the tab-cycle list.
3511 STATIC METHOD(WindowClassCycleOrder, struct wmTabCycleOrder *, tco)
3513 WD *wd = INST_DATA( cl, obj );
3514 TABCYCLE *tc;
3515 Object **ob = &tco->wtco_Object1;
3516 ULONG rc = 1;
3519 * Cycle through list of objects.
3521 while (*ob)
3524 * Allocate tab-cycle node.
3526 if ((tc = (TABCYCLE *)BGUI_AllocPoolMem(sizeof(TABCYCLE))))
3529 * Initialize structure.
3531 tc->tc_Object = *ob;
3533 * Setup the object for tab-cycling.
3535 DoSetMethodNG( *ob, GA_TabCycle, TRUE, ICA_TARGET, ICTARGET_IDCMP, TAG_END );
3537 * Add it to the list.
3539 AddTail(( struct List * )&wd->wd_CycleList, ( struct Node * )tc );
3540 } else
3541 rc = 0;
3542 ob++;
3544 return rc;
3546 METHOD_END
3547 /// WM_GETAPPMSG
3549 * Obtain an AppMessage.
3551 STATIC METHOD(WindowClassGetAppMsg, Msg, msg)
3553 WD *wd = INST_DATA(cl, obj);
3554 IPTR rc = 0;
3557 * Pop a message from the App port.
3559 if (wd->wd_AppPort)
3560 rc = (IPTR)GetMsg(wd->wd_AppPort);
3562 return rc;
3564 METHOD_END
3566 /// WM_ADDUPDATE
3568 * Add a target to the update notification list.
3570 STATIC METHOD(WindowClassAddUpdate, struct wmAddUpdate *, wmau)
3572 WD *wd = INST_DATA(cl, obj);
3573 UPN *up;
3574 ULONG rc = 0;
3577 * Valid target?
3579 if (wmau->wmau_Target)
3582 * Allocate node.
3584 if ((up = (UPN *)BGUI_AllocPoolMem(sizeof(UPN))))
3587 * Initialize node.
3589 up->up_ID = wmau->wmau_SourceID;
3590 up->up_Target = wmau->wmau_Target;
3591 up->up_MapList = wmau->wmau_MapList;
3593 * Add it to the list.
3595 AddTail((struct List *)&wd->wd_UpdateList, (struct Node *)up);
3596 rc = 1;
3599 return rc;
3601 METHOD_END
3603 /// WM_REPORT_ID
3605 * Report an ID.
3607 * Changes made by T.Herold: Passes task to AddIDReport
3609 STATIC METHOD(WindowClassReportID, struct wmReportID *, wmri)
3611 WD *wd = INST_DATA(cl, obj);
3612 ULONG rc = 0;
3613 struct Task *task;
3614 struct Window *w;
3616 * Get task to signal.
3618 if (wmri->wmri_Flags & WMRIF_TASK)
3619 task = wmri->wmri_SigTask;
3620 else
3621 task = wd->wd_UserPort->mp_SigTask;
3624 * Add ID node.
3626 if ((w = wd->wd_WindowPtr))
3628 rc = AddIDReport(w, wmri->wmri_ID, task);
3630 * Double-click?
3632 if (wmri->wmri_Flags & WMRIF_DOUBLE_CLICK)
3634 rc = AddIDReport(w, wmri->wmri_ID, task);
3637 * Set signal.
3639 if (task) Signal(task, (1 << wd->wd_UserPort->mp_SigBit));
3641 return rc;
3643 METHOD_END
3646 * Get a pointer to the window that signalled us.
3648 STATIC METHOD(WindowClassGetSigWin, Msg, msg )
3650 WD *wd = ( WD * )INST_DATA( cl, obj );
3651 struct Window *win;
3654 * Shared message port?
3656 if ( wd->wd_Flags & WDF_SHARED_MSGPORT ) {
3658 * Any messages at the port?
3660 if ( wd->wd_UserPort->mp_MsgList.lh_Head->ln_Succ )
3662 * Yes. Get the first.
3664 win = (( struct IntuiMessage * )wd->wd_UserPort->mp_MsgList.lh_Head )->IDCMPWindow;
3665 else
3667 * Try for the first reported ID.
3669 win = GetFirstIDReportWindow();
3670 } else
3672 * This window.
3674 win = wd->wd_WindowPtr;
3676 return (IPTR)win;
3678 METHOD_END
3681 * Remove an object from the tab-cycle list.
3683 STATIC METHOD(WindowClassRemove, struct wmRemoveObject *, wmro )
3685 WD *wd = ( WD * )INST_DATA( cl, obj );
3686 TABCYCLE *cyc;
3688 if ( wmro->wmro_Object ) {
3689 if ( wmro->wmro_Flags & WMROF_CYCLE_LIST ) {
3690 if (( cyc = GetCycleNode( wd, wmro->wmro_Object ))) {
3691 Remove(( struct Node * )cyc );
3692 BGUI_FreePoolMem( cyc );
3695 return( TRUE );
3697 return( FALSE );
3699 METHOD_END
3701 /// WM_SECURE
3703 * Secure the master gadget by removing it.
3705 STATIC METHOD(WindowClassSecure, Msg, msg)
3707 WD *wd = INST_DATA(cl, obj);
3708 ULONG rc = 0;
3709 struct Window *w;
3712 * Window Open?
3714 if ((w = wd->wd_WindowPtr))
3717 * Yes. Master gadget attached?
3719 if (!(wd->wd_Flags & WDF_REMOVED))
3722 * No. Remove it now.
3724 wd->wd_Flags |= WDF_REMOVED;
3725 RemoveGadget(w, (struct Gadget *)wd->wd_Gadgets);
3727 rc = 1;
3729 return rc;
3731 METHOD_END
3733 /// WM_RELEASE
3735 * Release the master gadget by adding it.
3737 STATIC METHOD(WindowClassRelease, Msg, msg)
3739 WD *wd = INST_DATA(cl, obj);
3740 ULONG rc = 0;
3741 struct Window *w;
3743 WW(kprintf("WindowClassRelease:\n"));
3746 * Window Open?
3748 if ((w = wd->wd_WindowPtr))
3750 WW(kprintf("WindowClassRelease: window is open\n"));
3752 * Yes. Master gadget removed?
3754 if (wd->wd_Flags & WDF_REMOVED)
3756 WW(kprintf("WindowClassRelease: WDF_REMOVED set = master gadget was removed. Calling AddGadget\n"));
3758 * Put the master back on-line.
3760 AddGadget(w, (struct Gadget *)wd->wd_Gadgets, -1);
3761 WW(kprintf("WindowClassRelease: clearing WDF_REMOVED flag\n"));
3763 wd->wd_Flags &= ~WDF_REMOVED;
3766 WW(kprintf("WindowClassRelease: calling RefreshGList: gad = %x\n", (struct Gadget *)wd->wd_Gadgets));
3768 rc = 1;
3770 return rc;
3772 METHOD_END
3774 /// WM_RELAYOUT
3776 * Relayout the GUI.
3778 STATIC METHOD(WindowClassRelayout, Msg, msg)
3780 WD *wd = INST_DATA(cl, obj);
3781 WORD newl, newt, neww, newh;
3782 UWORD min_x, min_y, max_x, max_y;
3783 BOOL lock_w = wd->wd_Flags & WDF_LOCK_WIDTH;
3784 BOOL lock_h = wd->wd_Flags & WDF_LOCK_HEIGHT;
3785 struct Window *w;
3786 struct Screen *s = wd->wd_Screen;
3788 WW(kprintf("** WindowClassRelayout\n"));
3790 * Window open?
3792 if ((w = wd->wd_WindowPtr))
3794 WW(kprintf("** WindowClassRelayout: window is open. calling WM_SECURE\n"));
3795 AsmDoMethod(obj, WM_SECURE);
3796 WW(kprintf("** WindowClassRelayout: calling WinSize\n"));
3798 if (!WinSize(wd, &min_x, &min_y))
3800 AsmDoMethod(obj, WM_RELEASE);
3801 return 0;
3803 WW(kprintf("** WindowClassRelayout: WinSize call ok min_x = %d, min_y = %d\n", min_x, min_y));
3806 * Pick up old minimum width and height.
3808 max_x = w->MaxWidth;
3809 max_y = w->MaxHeight;
3811 if (!(wd->wd_WindowFlags & WFLG_BACKDROP))
3814 * Default window position/size.
3816 newl = w->LeftEdge;
3817 newt = w->TopEdge;
3818 neww = w->Width;
3819 newh = w->Height;
3821 if (lock_w || (min_x > neww)) neww = min_x;
3822 if (lock_h || (min_y > newh)) newh = min_y;
3825 * Find out how much we have to
3826 * move the window.
3828 if ((newl + neww) > s->Width) newl = s->Width - neww;
3829 if ((newt + newh) > s->Height) newt = s->Height - newh;
3832 * Compute the new maximum values.
3834 if (neww > max_x) max_x = neww;
3835 if (newh > max_y) max_y = newh;
3838 * Re-size the window accoording to the master
3839 * minimum size change.
3842 WindowLimits(w, 1, 1, -1, -1);
3844 WW(kprintf("** WindowClassRelayout: Calling ChangeWindowBox(%d,%d,%d,%d)\n",newl,newt,neww,newh));
3846 ChangeWindowBox(w, newl, newt, neww, newh);
3848 wd->wd_MinW = lock_w ? neww : min_x;
3849 wd->wd_MinH = lock_h ? newh : min_y;
3850 wd->wd_MaxW = lock_w ? neww : max_x;
3851 wd->wd_MaxH = lock_h ? newh : max_y;
3852 WW(kprintf("** WindowClassRelayout: setting wd->wd_MinW/H to %d,%d wd->wd_MaxW/H to %d,%d\n",
3853 wd->wd_MinW,
3854 wd->wd_MinH,
3855 wd->wd_MaxW,
3856 wd->wd_MaxH));
3858 wd->wd_Flags |= WDF_CONSTRAINTS;
3860 else
3862 AsmDoMethod(obj, WM_RELEASE);
3865 return 1;
3867 METHOD_END
3869 /// WM_WHICHOBJECT
3871 * Find the object under the mouse.
3873 STATIC METHOD(WindowClassWhichObject, Msg, msg)
3875 WD *wd = INST_DATA(cl, obj);
3876 ULONG rc = 0;
3877 struct Window *w;
3878 WORD mx, my;
3881 * Window Open?
3883 if ((w = wd->wd_WindowPtr))
3886 * Pickup mouse coords.
3888 mx = w->MouseX;
3889 my = w->MouseY;
3892 * On the window?
3894 if ((mx >= 0) && (my >= 0) && (mx < w->Width) && (my < w->Height))
3896 * Let's see what the master returns to us.
3899 #ifdef __AROS__
3900 rc = AsmDoMethod(wd->wd_Gadgets, GRM_WHICHOBJECT, mx, my);
3901 #else
3902 rc = AsmDoMethod(wd->wd_Gadgets, GRM_WHICHOBJECT, (mx << 16) | my);
3903 #endif
3905 return rc;
3907 METHOD_END
3909 /// WM_LOCK, WM_UNLOCK
3911 STATIC METHOD(WindowClassLock, Msg, msg)
3913 WD *wd = INST_DATA(cl, obj);
3916 * Lock or unlock?
3918 if (msg->MethodID == WM_LOCK) wd->wd_Flags |= WDF_LOCKOUT;
3919 else wd->wd_Flags &= ~WDF_LOCKOUT;
3921 return 1;
3923 METHOD_END
3925 /// BASE_FINDKEY
3927 * Which object has the proper key?
3929 STATIC METHOD(WindowClassFindKey, struct bmFindKey *, bmfk)
3931 WD *wd = INST_DATA(cl, obj);
3932 Object *ob, *gr;
3934 if ((gr = wd->wd_Gadgets))
3936 if ((ob = (Object *)AsmDoMethodA(gr, (Msg)bmfk)))
3937 return (IPTR)ob;
3939 if ((gr = wd->wd_LBorder))
3941 if ((ob = (Object *)AsmDoMethodA(gr, (Msg)bmfk)))
3942 return (IPTR)ob;
3944 if ((gr = wd->wd_RBorder))
3946 if ((ob = (Object *)AsmDoMethodA(gr, (Msg)bmfk)))
3947 return (IPTR)ob;
3949 if ((gr = wd->wd_TBorder))
3951 if ((ob = (Object *)AsmDoMethodA(gr, (Msg)bmfk)))
3952 return (IPTR)ob;
3954 if ((gr = wd->wd_BBorder))
3956 if ((ob = (Object *)AsmDoMethodA(gr, (Msg)bmfk)))
3957 return (IPTR)ob;
3959 return (IPTR)NULL;
3961 METHOD_END
3963 /// BASE_KEYLABEL
3965 * Attach label keys to object.
3967 STATIC METHOD(WindowClassKeyLabel, struct bmKeyLabel *, bmkl)
3969 WD *wd = INST_DATA(cl, obj);
3970 Object *gr;
3972 if ((gr = wd->wd_Gadgets)) AsmDoMethodA(gr, (Msg)bmkl);
3973 if ((gr = wd->wd_LBorder)) AsmDoMethodA(gr, (Msg)bmkl);
3974 if ((gr = wd->wd_RBorder)) AsmDoMethodA(gr, (Msg)bmkl);
3975 if ((gr = wd->wd_TBorder)) AsmDoMethodA(gr, (Msg)bmkl);
3976 if ((gr = wd->wd_BBorder)) AsmDoMethodA(gr, (Msg)bmkl);
3978 return (IPTR)NULL;
3980 METHOD_END
3982 /// BASE_LOCALIZE
3984 * Localize window.
3986 STATIC METHOD(WindowClassLocalize, struct bmLocalize *, bml)
3988 WD *wd = INST_DATA(cl, obj);
3989 Object *gr;
3991 if ((gr = wd->wd_Gadgets)) AsmDoMethodA(gr, (Msg)bml);
3992 if ((gr = wd->wd_LBorder)) AsmDoMethodA(gr, (Msg)bml);
3993 if ((gr = wd->wd_RBorder)) AsmDoMethodA(gr, (Msg)bml);
3994 if ((gr = wd->wd_TBorder)) AsmDoMethodA(gr, (Msg)bml);
3995 if ((gr = wd->wd_BBorder)) AsmDoMethodA(gr, (Msg)bml);
3997 if (wd->wd_WindowTitleID) wd->wd_WindowTitle =
3998 BGUI_GetCatalogStr(bml->bml_Locale, wd->wd_WindowTitleID, wd->wd_WindowTitle);
4000 if (wd->wd_ScreenTitleID) wd->wd_ScreenTitle =
4001 BGUI_GetCatalogStr(bml->bml_Locale, wd->wd_ScreenTitleID, wd->wd_ScreenTitle);
4003 if (wd->wd_HelpTextID) wd->wd_HelpText =
4004 BGUI_GetCatalogStr(bml->bml_Locale, wd->wd_HelpTextID, wd->wd_HelpText);
4006 return (IPTR)NULL;
4008 METHOD_END
4010 /// WM_CLIP
4012 * Turn on or off buffer layering.
4014 STATIC METHOD(WindowClassClip, struct wmClip *, wmc)
4016 WD *wd = INST_DATA(cl, obj);
4017 struct RastPort *br = wd->wd_BufferRP;
4018 struct Rectangle *cr = wmc->wmc_Rectangle;
4019 struct Region *r = wd->wd_Region;
4020 struct Layer *wl;
4021 ULONG rc = 0;
4023 if (wd->wd_WindowPtr && (wl = wd->wd_WindowPtr->RPort->Layer))
4025 InstallClipRegion(wl, NULL);
4027 switch (wmc->wmc_Action)
4029 case CLIPACTION_NONE:
4030 if (br && br->Layer)
4032 wd->wd_BufferLayer = br->Layer;
4033 br->Layer = NULL;
4035 return 1;
4036 case CLIPACTION_CLEAR:
4037 ClearRegion(r);
4038 rc = 1;
4039 break;
4040 case CLIPACTION_OR:
4041 rc = OrRectRegion(r, cr);
4042 break;
4043 case CLIPACTION_AND:
4044 AndRectRegion(r, cr);
4045 rc = 1;
4046 break;
4049 if (rc)
4051 InstallClipRegion(wl, r);
4053 if (br)
4055 if (!br->Layer) br->Layer = wd->wd_BufferLayer;
4056 InstallClipRegion(br->Layer, r);
4060 return rc;
4062 METHOD_END
4064 STATIC METHOD(WindowClassSetupGadget, struct wmSetupGadget *, wmsg)
4066 WD *wd = INST_DATA(cl, obj);
4067 struct TagItem *tstate = wmsg->wmsg_Tags;
4068 struct TagItem *tag;
4070 while ((tag = NextTagItem(&tstate)))
4072 switch(tag->ti_Tag)
4074 case BT_Inhibit:
4075 AsmDoMethod(wmsg->wmsg_Object, BASE_INHIBIT, tag->ti_Tag);
4076 break;
4080 if(wd->wd_UsedFont
4081 || ((wd->wd_Flags & WDF_AUTOASPECT)
4082 && wd->wd_DrawInfo))
4084 struct TextAttr current_font;
4086 if(wd->wd_UsedFont)
4088 struct RastPort rp;
4090 InitRastPort(&rp);
4091 SetFont(&rp,wd->wd_UsedFont);
4092 AskFont(&rp,&current_font);
4095 SetAttrs(wmsg->wmsg_Object,
4096 wd->wd_UsedFont ? BT_TextAttr : TAG_IGNORE,&current_font,
4097 ((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),
4098 TAG_END);
4100 return(1);
4102 METHOD_END
4105 /// Class initialization.
4108 * Class function table.
4110 STATIC DPFUNC ClassFunc[] = {
4111 { OM_NEW, WindowClassNew },
4112 { OM_SET, WindowClassSetUpdate },
4113 { OM_UPDATE, WindowClassSetUpdate },
4114 { OM_GET, WindowClassGet },
4115 { OM_DISPOSE, WindowClassDispose },
4116 { WM_OPEN, WindowClassOpen },
4117 { WM_CLOSE, WindowClassClose },
4118 { WM_SLEEP, WindowClassSleep },
4119 { WM_WAKEUP, WindowClassWakeUp },
4120 { WM_HANDLEIDCMP, WindowClassIDCMP },
4121 { WM_GADGETKEY, WindowClassGadgetKey },
4122 { WM_DISABLEMENU, WindowClassDisableMenu },
4123 { WM_CHECKITEM, WindowClassCheckItem },
4124 { WM_MENUDISABLED, WindowClassMenuDisabled },
4125 { WM_ITEMCHECKED, WindowClassItemChecked },
4126 { WM_TABCYCLE_ORDER, WindowClassCycleOrder },
4127 { WM_GETAPPMSG, WindowClassGetAppMsg },
4128 { WM_ADDUPDATE, WindowClassAddUpdate },
4129 { WM_REPORT_ID, WindowClassReportID },
4130 { WM_GET_SIGNAL_WINDOW, WindowClassGetSigWin },
4131 { WM_REMOVE_OBJECT, WindowClassRemove },
4133 { WM_SECURE, WindowClassSecure },
4134 { WM_RELEASE, WindowClassRelease },
4135 { WM_RELAYOUT, WindowClassRelayout },
4136 { WM_WHICHOBJECT, WindowClassWhichObject },
4137 { WM_LOCK, WindowClassLock },
4138 { WM_UNLOCK, WindowClassLock },
4139 { WM_CLOSETOOLTIP, WindowClassCloseTT },
4140 { WM_CLIP, WindowClassClip },
4141 { WM_SETUPGADGET, WindowClassSetupGadget },
4143 { BASE_FINDKEY, WindowClassFindKey },
4144 { BASE_KEYLABEL, WindowClassKeyLabel },
4145 { BASE_LOCALIZE, WindowClassLocalize },
4147 { DF_END }
4151 * Simple class initialization.
4153 makeproto Class *InitWindowClass(void)
4155 return WindowClass = BGUI_MakeClass(CLASS_SuperClassBGUI, BGUI_ROOT_OBJECT,
4156 CLASS_ObjectSize, sizeof(WD),
4157 CLASS_DFTable, ClassFunc,
4158 TAG_DONE);