This should solve an error which made the nightly build fail with:
[AROS-Contrib.git] / bgui / windowclass.c
blob2df36af8340a500551ef881081232740fe35208e
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 ULONG GroupDimensions(Object *master, struct TextAttr *font, UWORD *minw, UWORD *minh)
344 struct TextFont *tf = NULL;
345 struct RastPort rp;
346 ULONG rc;
347 struct GadgetInfo gi;
348 WD *wd;
349 BC *bc = BASE_DATA(master);
352 * Initialize the RastPort.
354 InitRastPort(&rp);
357 * Setup the font.
359 if (font)
361 if (tf = BGUI_OpenFont(font)) FSetFont(&rp, tf);
362 else return 0;
364 DoSetMethodNG(master, BT_TextAttr, font, TAG_END);
367 if (bc->bc_Window)
369 wd = INST_DATA(WindowClass, bc->bc_Window);
372 * Setup fake GadgetInfo (used for the DrawInfo).
374 bzero(&gi, sizeof(gi));
375 gi.gi_RastPort = &rp;
376 gi.gi_Screen = wd->wd_Screen;
377 gi.gi_DrInfo = wd->wd_DrawInfo;
378 gi.gi_Pens.DetailPen = wd->wd_DrawInfo->dri_Pens[DETAILPEN];
379 gi.gi_Pens.BlockPen = wd->wd_DrawInfo->dri_Pens[BLOCKPEN];
382 * Send the message.
384 rc = AsmDoMethod(master, GRM_DIMENSIONS, &gi, &rp, minw, minh, 0);
388 * Close font when opened.
390 if (tf) BGUI_CloseFont(tf);
392 return rc;
397 * Back-filling hook. This hook makes sure that the window background is
398 * always BACKGROUNDPEN. The hook will only fill the areas that have grown
399 * because of a re-size and the right and bottom border of the window in it's
400 * previous position if the size has grown.
402 //STATIC SAVEDS ASM VOID BackFill_func(REG(a0) struct Hook *hook, REG(a2) struct RastPort *rp, REG(a1) BFINFO *info)
403 STATIC SAVEDS ASM REGFUNC3(VOID, BackFill_func,
404 REGPARAM(A0, struct Hook *, hook),
405 REGPARAM(A2, struct RastPort *, rp),
406 REGPARAM(A1, BFINFO *, info))
408 struct Layer *save_layer;
409 struct Window *w = NULL;
410 struct BaseInfo *bi;
413 * Do not disturb the previous window contents. When the area to fill is located in the previous GUI area
414 * we do not back fill. This makes sure the previous GUI remains visible until it is overwritten by the
415 * resized GUI.
417 if (info->bf_Layer) w = info->bf_Layer->Window;
419 if (!w || (info->bf_X > w->BorderLeft) || (info->bf_Y > w->BorderTop))
422 * NO LAYER!
424 save_layer = rp->Layer;
425 rp->Layer = NULL;
427 #ifdef DEBUG_BGUI
428 if (bi = AllocBaseInfoDebug(__FILE__,__LINE__,BI_RastPort, rp, TAG_DONE))
429 #else
430 if (bi = AllocBaseInfo(BI_RastPort, rp, TAG_DONE))
431 #endif
434 * Setup the rastport.
436 BSetDrMd(bi, JAM1);
437 BSetDPenA(bi, BACKGROUNDPEN);
440 * Fill the area.
442 BRectFillA(bi, &info->bf_Rect);
444 FreeBaseInfo(bi);
446 rp->Layer = save_layer;
449 REGFUNC_END
451 STATIC struct Hook BackFill_hook = { NULL, NULL, (FUNCPTR)BackFill_func, NULL, NULL };
454 * Set attributes.
456 METHOD(WindowClassSetUpdate, struct opSet *, ops)
458 WD *wd = INST_DATA(cl, obj);
459 struct TagItem *tstate = ops->ops_AttrList, *tag;
460 struct Window *w = wd->wd_WindowPtr;
461 ULONG data;
464 * Set attributes.
466 while (tag = NextTagItem(&tstate))
468 data = tag->ti_Data;
470 switch (tag->ti_Tag)
472 case WINDOW_Screen:
473 if (!w) wd->wd_Screen = (struct Screen *)data;
474 break;
476 case WINDOW_PubScreen:
477 if (!w) wd->wd_PubScreen = (struct Screen *)data;
478 break;
480 case WINDOW_PubScreenName:
481 if (!w) wd->wd_PubScreenName = (UBYTE *)data;
482 break;
484 case WINDOW_Locale:
485 if (wd->wd_Locale && (wd->wd_Flags & WDF_FREELOCALE))
487 CloseLocale(wd->wd_Locale->bl_Locale);
488 CloseCatalog(wd->wd_Locale->bl_Catalog);
489 BGUI_FreePoolMem(wd->wd_Locale);
491 wd->wd_Catalog = NULL;
492 wd->wd_Locale = (struct bguiLocale *)data;
493 wd->wd_Flags &= ~WDF_FREELOCALE;
494 break;
496 case WINDOW_Catalog:
497 if (LocaleBase == NULL) break;
499 if (wd->wd_Locale && wd->wd_Catalog)
501 CloseLocale(wd->wd_Locale->bl_Locale);
502 CloseCatalog(wd->wd_Locale->bl_Catalog);
503 if (data == NULL)
505 BGUI_FreePoolMem(wd->wd_Locale);
506 wd->wd_Locale = NULL;
507 wd->wd_Catalog = NULL;
508 break;
511 else
513 if((wd->wd_Locale = BGUI_AllocPoolMem(sizeof(struct bguiLocale))))
514 memset(wd->wd_Locale,0,sizeof(struct bguiLocale));
515 wd->wd_Flags |= WDF_FREELOCALE;
517 if (wd->wd_Locale)
519 wd->wd_Catalog = (UBYTE *)data;
520 wd->wd_Locale->bl_Locale = OpenLocale(NULL);
521 wd->wd_Locale->bl_Catalog = OpenCatalogA(NULL, wd->wd_Catalog, NULL);
523 break;
525 case WINDOW_Title:
526 wd->wd_WindowTitle = (UBYTE *)data;
527 if (w && !(wd->wd_Flags & WFLG_BORDERLESS))
529 SetWindowTitles(w, wd->wd_WindowTitle, (UBYTE *)~0);
531 * Notify the target when necessary.
533 DoNotifyMethod(obj, NULL, 0, tag->ti_Tag, data, TAG_END);
535 break;
537 case WINDOW_ScreenTitle:
538 wd->wd_ScreenTitle = (UBYTE *)data;
539 if (w)
541 SetWindowTitles(w, (UBYTE *)~0, wd->wd_ScreenTitle);
543 * Notify the target when necessary.
545 DoNotifyMethod(obj, NULL, 0, tag->ti_Tag, data, TAG_END);
547 break;
549 case WINDOW_ToolTicks:
550 wd->wd_ToolTickTime = data;
551 wd->wd_ToolTicks = 0;
553 if (wd->wd_ToolTickTime) wd->wd_IDCMPFlags |= IDCMP_INTUITICKS;
554 else
556 if (!(wd->wd_Flags & WDF_USERTICKS))
557 wd->wd_IDCMPFlags &= ~IDCMP_INTUITICKS;
559 if (w) ModifyIDCMP(w, wd->wd_IDCMPFlags);
560 break;
562 case WINDOW_Bounds:
563 if (data)
565 if (w)
567 ChangeWindowBox(w, IBOX(data)->Left, IBOX(data)->Top,
568 IBOX(data)->Width, IBOX(data)->Height);
570 else
572 wd->wd_FixedPos = *IBOX(data);
573 wd->wd_Flags |= WDF_CHANGE_VALID;
576 else
577 wd->wd_Flags &= ~WDF_CHANGE_VALID;
578 break;
580 case WINDOW_CloseOnEsc:
581 if (data) wd->wd_Flags |= WDF_CLOSEONESC;
582 else wd->wd_Flags &= ~WDF_CLOSEONESC;
583 break;
585 case WINDOW_NoVerify:
586 if (w)
588 if (data) ModifyIDCMP(w, wd->wd_IDCMPFlags & ~IDCMP_SIZEVERIFY);
589 else ModifyIDCMP(w, wd->wd_IDCMPFlags);
591 break;
593 case WINDOW_MenuFont:
594 wd->wd_MenuFont = (struct TextAttr *)data;
595 if (w && wd->wd_Menus)
597 ClearMenuStrip(w);
598 if ((!wd->wd_MenuFont) || (!LayoutMenus(wd->wd_Menus, wd->wd_VisualInfo,
599 GTMN_NewLookMenus, TRUE, GTMN_TextAttr, wd->wd_MenuFont, TAG_DONE)))
601 LayoutMenus(wd->wd_Menus, wd->wd_VisualInfo, GTMN_NewLookMenus, TRUE, TAG_END);
603 SetMenuStrip(w, wd->wd_Menus);
605 break;
607 case WINDOW_SharedPort:
608 if (!w)
610 if (wd->wd_UserPort = (struct MsgPort *)data)
611 wd->wd_Flags |= WDF_SHARED_MSGPORT;
612 else
613 wd->wd_Flags &= ~WDF_SHARED_MSGPORT;
615 break;
619 case WINDOW_TitleID:
620 wd->wd_WindowTitleID = data;
621 break;
623 case WINDOW_ScreenTitleID:
624 wd->wd_ScreenTitleID = data;
625 break;
627 case WINDOW_HelpFile:
628 wd->wd_HelpFile = (UBYTE *)data;
629 break;
631 case WINDOW_HelpNode:
632 wd->wd_HelpNode = (UBYTE *)data;
633 break;
635 case WINDOW_HelpLine:
636 wd->wd_HelpLine = data;
637 break;
639 case WINDOW_HelpText:
640 wd->wd_HelpText = (UBYTE *)data;
641 break;
643 case WINDOW_HelpTextID:
644 wd->wd_HelpTextID = data;
645 break;
647 case WINDOW_IDCMPHook:
648 wd->wd_IDCMPHook = (struct Hook *)data;
649 break;
651 case WINDOW_VerifyHook:
652 wd->wd_VerifyHook = (struct Hook *)data;
653 break;
655 case WINDOW_IDCMPHookBits:
656 wd->wd_IDCMPHookBits = data;
657 break;
659 case WINDOW_VerifyHookBits:
660 wd->wd_VerifyHookBits = data;
661 break;
663 case WINDOW_Position:
664 wd->wd_Position = data;
665 break;
667 case WINDOW_ScaleWidth:
668 wd->wd_WidthScale = data;
669 break;
671 case WINDOW_ScaleHeight:
672 wd->wd_HeightScale = data;
673 break;
675 case WINDOW_Font:
676 wd->wd_Font = (struct TextAttr *)data;
677 break;
679 case WINDOW_FallBackFont:
680 wd->wd_FallBackFont = (struct TextAttr *)data;
681 break;
683 case WINDOW_UniqueID:
684 wd->wd_ID = data;
685 break;
688 return 1;
690 METHOD_END
692 /// OM_NEW
694 * Create a shiny new object.
696 METHOD(WindowClassNew, struct opSet *, ops)
698 WD *wd;
699 struct TagItem *tstate, *tag, *tags;
700 ULONG rc=0, data, idcmp;
701 BOOL fail = FALSE;
703 Object *master, *lborder, *tborder, *rborder, *bborder;
705 tags = DefTagList(BGUI_WINDOW_OBJECT, ops->ops_AttrList);
707 master = (Object *)GetTagData(WINDOW_MasterGroup, NULL, tags);
708 lborder = (Object *)GetTagData(WINDOW_LBorderGroup, NULL, tags);
709 tborder = (Object *)GetTagData(WINDOW_TBorderGroup, NULL, tags);
710 rborder = (Object *)GetTagData(WINDOW_RBorderGroup, NULL, tags);
711 bborder = (Object *)GetTagData(WINDOW_BBorderGroup, NULL, tags);
714 * For now we do not work without a master group.
718 * First we let the superclass setup an object.
720 if (master && (rc = NewSuperObject(cl, obj, tags)))
723 * Get the instance data.
725 wd = INST_DATA(cl, rc);
727 wd->wd_Gadgets = master;
728 wd->wd_LBorder = lborder;
729 wd->wd_TBorder = tborder;
730 wd->wd_RBorder = rborder;
731 wd->wd_BBorder = bborder;
733 wd->wd_DGMObject = BGUI_NewObjectA(BGUI_DGM_OBJECT, NULL);
734 wd->wd_Region = NewRegion();
737 * Initialize cycle/update lists.
739 NewList((struct List *)&wd->wd_CycleList);
740 NewList((struct List *)&wd->wd_UpdateList);
743 * Setup defaults.
745 wd->wd_Position = POS_CENTERSCREEN;
746 wd->wd_FallBackFont = &Topaz80;
747 wd->wd_ToolX = wd->wd_ToolY = -1;
748 wd->wd_Zoom[0] = wd->wd_Zoom[1] = -1;
751 * Pack user boolean tags with predefined defaults.
753 wd->wd_WindowFlags = PackBoolTags(WFLG_DRAGBAR | WFLG_SIZEGADGET | WFLG_CLOSEGADGET | WFLG_DEPTHGADGET |
754 WFLG_ACTIVATE | WFLG_NOCAREREFRESH | WFLG_SIZEBBOTTOM | WFLG_REPORTMOUSE |
755 WFLG_NEWLOOKMENUS, tags, boolTags1);
758 * Simple refresh?
760 if (!GetTagData(WINDOW_SmartRefresh, FALSE, tags)) wd->wd_WindowFlags |= WFLG_SIMPLE_REFRESH;
762 idcmp = IDCMP_RAWKEY|IDCMP_GADGETUP|IDCMP_CHANGEWINDOW|IDCMP_INACTIVEWINDOW|IDCMP_ACTIVEWINDOW|
763 IDCMP_IDCMPUPDATE|IDCMP_SIZEVERIFY|IDCMP_NEWSIZE|IDCMP_MOUSEMOVE|IDCMP_MOUSEBUTTONS|IDCMP_MENUHELP;
766 * Obtain all necessary window data.
768 tstate = tags;
769 while (tag = NextTagItem(&tstate))
771 data = tag->ti_Data;
773 switch (tag->ti_Tag)
775 case WINDOW_MenuStrip:
776 if (!wd->wd_MenuStrip)
778 if (!CopyNewMenuArray(wd, (struct NewMenu *)data)) fail = TRUE;
780 break;
782 case WINDOW_IDCMP:
783 wd->wd_IDCMPFlags = data;
784 if (data & IDCMP_INTUITICKS) wd->wd_Flags |= WDF_USERTICKS;
785 break;
787 case WINDOW_PosRelBox:
788 wd->wd_RelPos = *IBOX(data);
789 wd->wd_Flags |= WDF_RELBOX;
790 break;
793 AsmCoerceMethod(cl, (Object *)rc, OM_SET, tags, NULL);
795 if (!fail)
798 * Disable all system gadgets and bordergroups when this
799 * is a backdrop or borderless window.
801 if (wd->wd_WindowFlags & (WFLG_BORDERLESS|WFLG_BACKDROP))
803 wd->wd_WindowFlags &= ~(WFLG_SIZEGADGET|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|WFLG_DRAGBAR);
804 wd->wd_WindowFlags |= WFLG_BORDERLESS;
805 wd->wd_WindowTitle = NULL;
809 * Pickup the other boolean tags.
811 wd->wd_Flags = PackBoolTags(wd->wd_Flags, tags, boolTags);
814 * Pack some IDCMP flags.
816 if (wd->wd_WindowFlags & WFLG_CLOSEGADGET) idcmp |= IDCMP_CLOSEWINDOW;
817 if (wd->wd_MenuStrip) idcmp |= IDCMP_MENUPICK;
819 wd->wd_IDCMPFlags |= idcmp;
821 if (wd->wd_Locale) AsmDoMethod((Object *)rc, BASE_LOCALIZE, wd->wd_Locale);
822 if (wd->wd_Flags & WDF_AUTOKEYLABEL) AsmDoMethod((Object *)rc, BASE_KEYLABEL);
824 DoSetMethodNG(wd->wd_Gadgets, GROUP_IsMaster, TRUE, BT_Buffer, TRUE, TAG_DONE);
826 DoMultiSet(BT_ParentWindow, rc, 5, master, lborder, tborder, rborder, bborder);
828 if (lborder) DoSetMethodNG(lborder, GA_LeftBorder, TRUE, TAG_DONE);
829 if (rborder) DoSetMethodNG(rborder, GA_RightBorder, TRUE, TAG_DONE);
830 if (tborder) DoSetMethodNG(tborder, GA_TopBorder, TRUE, TAG_DONE);
831 if (bborder) DoSetMethodNG(bborder, GA_BottomBorder, TRUE, TAG_DONE);
833 else
835 AsmCoerceMethod(cl, (Object *)rc, OM_DISPOSE);
836 rc = 0;
839 if (!rc)
842 * If the window object cannot be created we
843 * dispose of the master group and border groups.
845 if (master) AsmDoMethod(master, OM_DISPOSE);
846 if (lborder) AsmDoMethod(lborder, OM_DISPOSE);
847 if (tborder) AsmDoMethod(tborder, OM_DISPOSE);
848 if (rborder) AsmDoMethod(rborder, OM_DISPOSE);
849 if (bborder) AsmDoMethod(bborder, OM_DISPOSE);
851 FreeTagItems(tags);
853 return rc;
855 METHOD_END
857 /// OM_DISPOSE
859 * Get rid of an object.
861 METHOD(WindowClassDispose, Msg, msg)
863 WD *wd = INST_DATA(cl, obj);
864 TABCYCLE *tc;
865 UPN *up;
868 * When the window is open we close it.
870 if (wd->wd_WindowPtr)
871 AsmDoMethod(obj, WM_CLOSE);
873 if (wd->wd_Locale && wd->wd_Catalog)
875 CloseLocale(wd->wd_Locale->bl_Locale);
876 CloseCatalog(wd->wd_Locale->bl_Catalog);
878 if (wd->wd_Flags & WDF_FREELOCALE)
879 BGUI_FreePoolMem(wd->wd_Locale);
882 if (wd->wd_DGMObject)
884 DisposeObject(wd->wd_DGMObject);
887 if (wd->wd_Region)
889 DisposeRegion(wd->wd_Region);
893 * Remove and delete the tab-cycle list.
895 while (tc = (TABCYCLE *)RemHead((struct List *)&wd->wd_CycleList))
896 BGUI_FreePoolMem(tc);
899 * Remove and delete all update targets.
901 while (up = (UPN *)RemHead((struct List *)&wd->wd_UpdateList))
902 BGUI_FreePoolMem(up);
905 * Free the NewMenu array.
907 if (wd->wd_MenuStrip)
908 BGUI_FreePoolMem(wd->wd_MenuStrip);
911 * Dispose of the master group and
912 * border groups.
914 if (wd->wd_Gadgets) AsmDoMethod(wd->wd_Gadgets, OM_DISPOSE);
915 if (wd->wd_LBorder) AsmDoMethod(wd->wd_LBorder, OM_DISPOSE);
916 if (wd->wd_RBorder) AsmDoMethod(wd->wd_RBorder, OM_DISPOSE);
917 if (wd->wd_BBorder) AsmDoMethod(wd->wd_BBorder, OM_DISPOSE);
918 if (wd->wd_TBorder) AsmDoMethod(wd->wd_TBorder, OM_DISPOSE);
920 if(wd->wd_UsedFont)
922 BGUI_CloseFont(wd->wd_UsedFont);
923 wd->wd_UsedFont=NULL;
926 * The superclass takes care of the rest.
928 return AsmDoSuperMethodA(cl, obj, msg);
930 METHOD_END
933 * Setup the menu strip.
935 //STATIC ASM BOOL DoMenuStrip( REG(a0) WD *wd, REG(a1) struct Screen *scr )
936 STATIC ASM REGFUNC2(BOOL, DoMenuStrip,
937 REGPARAM(A0, WD *, wd),
938 REGPARAM(A1, struct Screen *, scr))
941 * Get the visual info. (We use
942 * gadtools for the menus.)
944 if ( wd->wd_VisualInfo = GetVisualInfo( scr, TAG_END )) {
946 * Create the menu-strip.
948 if ( wd->wd_Menus = CreateMenus( wd->wd_MenuStrip, TAG_END )) {
950 * Layout the menu strip.
952 if ( LayoutMenus( wd->wd_Menus, wd->wd_VisualInfo, GTMN_NewLookMenus, TRUE, wd->wd_MenuFont ? GTMN_TextAttr : TAG_IGNORE, wd->wd_MenuFont, TAG_END ))
953 return( TRUE );
955 * Everything below this point means failure.
957 FreeMenus( wd->wd_Menus );
958 wd->wd_Menus = NULL;
960 FreeVisualInfo( wd->wd_VisualInfo );
961 wd->wd_VisualInfo = NULL;
963 return( FALSE );
965 REGFUNC_END
968 * Kill the AppWindow stuff.
970 //STATIC ASM VOID KillAppWindow(REG(a0) WD *wd)
971 STATIC ASM REGFUNC1(VOID, KillAppWindow,
972 REGPARAM(A0, WD *, wd))
974 struct Message *msg;
977 * Remove the AppWindow.
979 if (wd->wd_AppWindow)
981 #ifdef __AROS__
982 #warning Commented RemoveAppWindow
983 #else
984 RemoveAppWindow(wd->wd_AppWindow);
985 #endif
986 wd->wd_AppWindow = NULL;
990 * Do we have a message port?
992 if (wd->wd_AppPort)
995 * Kill all remaining messages and the port.
997 while (msg = GetMsg(wd->wd_AppPort))
998 ReplyMsg(msg);
1000 DeleteMsgPort(wd->wd_AppPort);
1001 wd->wd_AppPort = NULL;
1004 REGFUNC_END
1007 * Make it an AppWindow.
1009 //STATIC ASM BOOL MakeAppWindow(REG(a0) WD *wd)
1010 STATIC ASM REGFUNC1(BOOL, MakeAppWindow,
1011 REGPARAM(A0, WD *, wd))
1014 * Create a message port.
1016 if (wd->wd_AppPort = CreateMsgPort())
1019 * Create the app window.
1021 #ifdef __AROS__
1022 #warning Commented AddAppWindowA
1023 #else
1024 if (wd->wd_AppWindow = AddAppWindowA(0, 0, wd->wd_WindowPtr, wd->wd_AppPort, NULL))
1025 return TRUE;
1026 #endif
1028 KillAppWindow(wd);
1030 return FALSE;
1032 REGFUNC_END
1035 * Compute width and height of the
1036 * system gadgets.
1038 //STATIC ASM VOID SystemSize(REG(a1) WD *wd)
1039 STATIC ASM REGFUNC1(VOID, SystemSize,
1040 REGPARAM(A1, WD *,wd))
1042 struct TagItem tags[4];
1043 Object *image;
1044 BOOL hires = wd->wd_Screen->Flags & SCREENHIRES;
1047 * Set DrawInfo and resolution.
1049 tags[0].ti_Tag = SYSIA_Which;
1050 tags[1].ti_Tag = SYSIA_DrawInfo;
1051 tags[1].ti_Data = (ULONG)wd->wd_DrawInfo;
1052 tags[2].ti_Tag = SYSIA_Size;
1053 tags[2].ti_Data = hires ? SYSISIZE_MEDRES : SYSISIZE_LOWRES;
1054 tags[3].ti_Tag = TAG_DONE;
1057 * Sizing image.
1059 tags[0].ti_Data = SIZEIMAGE;
1060 if (image = NewObjectA(NULL, SYSICLASS, tags))
1062 wd->wd_SizeW = IM_BOX(image)->Width;
1063 wd->wd_SizeH = IM_BOX(image)->Height;
1064 DisposeObject(image);
1066 else
1068 wd->wd_SizeW = hires ? 18 : 13;
1069 wd->wd_SizeH = hires ? 10 : 11;
1073 * Close image.
1075 tags[0].ti_Data = CLOSEIMAGE;
1076 if (image = NewObjectA(NULL, SYSICLASS, tags))
1078 wd->wd_CloseW = IM_BOX(image)->Width;
1079 DisposeObject(image);
1081 else
1082 wd->wd_CloseW = hires ? 20 : 15;
1085 * Depth image.
1087 tags[0].ti_Data = DEPTHIMAGE;
1088 if (image = NewObjectA(NULL, SYSICLASS, tags))
1090 wd->wd_DepthW = IM_BOX(image)->Width;
1091 DisposeObject(image);
1093 else
1094 wd->wd_DepthW = hires ? 24 : 18;
1097 * Zoom image.
1099 tags[0].ti_Data = ZOOMIMAGE;
1100 if (image = NewObjectA(NULL, SYSICLASS, tags))
1102 wd->wd_ZoomW = IM_BOX(image)->Width;
1103 DisposeObject(image);
1105 else
1106 wd->wd_ZoomW = hires ? 24 : 18;
1108 REGFUNC_END
1111 * Query border sizes.
1113 //STATIC ASM void WBorderSize(REG(a0) WD *wd, REG(a1) struct Screen *scr, REG(a2) struct TextAttr *at)
1114 STATIC ASM REGFUNC3(void, WBorderSize,
1115 REGPARAM(A0, WD *, wd),
1116 REGPARAM(A1, struct Screen *, scr),
1117 REGPARAM(A2, struct TextAttr *, at))
1119 UWORD wl, wt, wr, wb;
1122 * Borders available?
1124 if (!(wd->wd_WindowFlags & WFLG_BORDERLESS))
1127 * Default border sizes.
1129 wt = scr->WBorTop + scr->Font->ta_YSize + 1;
1130 wl = scr->WBorLeft;
1131 wr = scr->WBorRight;
1132 wb = scr->WBorBottom;
1135 * Get system gadget dimensions.
1137 SystemSize(wd);
1140 * Adjust for sizing gadget.
1142 if (wd->wd_WindowFlags & WFLG_SIZEGADGET)
1145 * Bottom border size gadget?
1147 if (wd->wd_WindowFlags & WFLG_SIZEBBOTTOM) wb = wd->wd_SizeH;
1148 else wr = wd->wd_SizeW;
1151 * Right border size gadget?
1153 if (wd->wd_WindowFlags & WFLG_SIZEBRIGHT) wr = wd->wd_SizeW;
1157 * Adjust for border groups.
1159 if (wd->wd_LBorder)
1161 GroupDimensions(wd->wd_LBorder, at, &wd->wd_LWidth, &wd->wd_LHeight);
1162 if (wd->wd_LWidth > wl) wl = wd->wd_LWidth;
1165 if (wd->wd_TBorder)
1167 GroupDimensions(wd->wd_TBorder, at, &wd->wd_TWidth, &wd->wd_THeight);
1168 if (wd->wd_THeight > wt) wt = wd->wd_THeight;
1171 if (wd->wd_RBorder)
1173 GroupDimensions(wd->wd_RBorder, at, &wd->wd_RWidth, &wd->wd_RHeight);
1174 if (wd->wd_RWidth > wr) wr = wd->wd_RWidth;
1177 if (wd->wd_BBorder)
1179 GroupDimensions(wd->wd_BBorder, at, &wd->wd_BWidth, &wd->wd_BHeight);
1180 if (wd->wd_BHeight > wb) wb = wd->wd_BHeight;
1184 * Set them.
1186 wd->wd_Left = wl;
1187 wd->wd_Top = wt;
1188 wd->wd_Right = wr;
1189 wd->wd_Bottom = wb;
1190 } else
1192 * No borders.
1194 wd->wd_Left = wd->wd_Top = wd->wd_Right = wd->wd_Bottom = 0;
1196 REGFUNC_END
1198 BOOL WinSize(WD *wd, UWORD *win_w, UWORD *win_h)
1200 struct TextAttr *font;
1201 BOOL thin;
1203 struct Screen *scr = wd->wd_Screen;
1205 UWORD gmw, gmh;
1206 int bw, bh, gx, gy, t1, t2;
1208 int sw = scr->Width;
1209 int sh = scr->Height;
1211 int vw = wd->wd_TextW;
1212 int vh = wd->wd_TextH;
1214 if (wd->wd_UsedFont)
1216 BGUI_CloseFont(wd->wd_UsedFont);
1217 wd->wd_UsedFont = NULL;
1221 * The screen can be smaller than the TEXT
1222 * overscan sizes. Check if this is the case.
1224 if (vw > sw) vw = sw;
1225 if (vh > sh) vh = sh;
1228 * Setup aspect dependant framing and the
1229 * window object.
1231 if (wd->wd_Flags & WDF_AUTOASPECT)
1234 * Guess aspect ratio.
1236 thin = ((wd->wd_DrawInfo->dri_Resolution.X / wd->wd_DrawInfo->dri_Resolution.Y) <= 1);
1238 DoMultiSet(FRM_ThinFrame, thin, 5, wd->wd_Gadgets, wd->wd_LBorder, wd->wd_TBorder, wd->wd_RBorder, wd->wd_BBorder);
1242 * Pick up the font to use. This will either
1243 * be the font specified with WINDOW_Font or
1244 * the screen font.
1246 font = wd->wd_Font ? wd->wd_Font : scr->Font;
1249 * When the window has grown too big for the font, the
1250 * recomputation using the fallback font will start here.
1252 reCalc:
1255 * Ask the master group to compute its
1256 * absolute minimum dimension.
1258 GroupDimensions(wd->wd_Gadgets, font, (UWORD *)&gmw, (UWORD *)&gmh);
1261 * Save these.
1263 wd->wd_MasterW = gmw;
1264 wd->wd_MasterH = gmh;
1267 * Borderless windows, and backdrop for that matter,
1268 * have no borders and system gadgets so this part
1269 * of the computation can be skipped.
1271 if (!(wd->wd_WindowFlags & WFLG_BORDERLESS))
1274 * Compute border sizes.
1276 WBorderSize(wd, scr, font);
1279 * Compute totals of border gadgets.
1281 bw = wd->wd_Left + wd->wd_Right;
1282 bh = wd->wd_Top + wd->wd_Bottom;
1285 * Add the minimum window border sizes.
1287 gmw += bw;
1288 gmh += bh;
1291 * Check to see if any of the border groups
1292 * have a larger minimum width or height than
1293 * the current window size.
1295 if (wd->wd_LBorder)
1297 t1 = wd->wd_LHeight + wd->wd_Top + wd->wd_Bottom;
1298 if (t1 > gmh) gmh = t1;
1301 if (wd->wd_RBorder)
1303 t1 = wd->wd_RHeight + wd->wd_Top + wd->wd_Bottom;
1304 if (t1 > gmh) gmh = t1;
1307 if (wd->wd_TBorder)
1309 t1 = wd->wd_TWidth;
1310 if ((wd->wd_Flags & WDF_TITLEZIP) ||
1311 (wd->wd_WindowFlags & WFLG_SIZEGADGET)) t1 += wd->wd_ZoomW;
1312 if (wd->wd_WindowFlags & WFLG_DEPTHGADGET) t1 += wd->wd_DepthW;
1313 if (wd->wd_WindowFlags & WFLG_CLOSEGADGET) t1 += wd->wd_CloseW;
1314 if (t1 > gmw) gmw = t1;
1317 if (wd->wd_BBorder)
1319 t1 = wd->wd_BWidth;
1320 if (wd->wd_WindowFlags & WFLG_SIZEGADGET) t1 += wd->wd_SizeW;
1321 if (t1 > gmw) gmw = t1;
1325 * Setup master gadget dimensions.
1327 gx = wd->wd_Left;
1328 gy = wd->wd_Top;
1331 * And the border groups.
1333 if (wd->wd_LBorder)
1335 DoSetMethodNG(wd->wd_LBorder, GA_Left, 0,
1336 GA_Top, wd->wd_Top,
1337 GA_Width, wd->wd_Left,
1338 GA_RelHeight, -(wd->wd_Top),
1339 TAG_END);
1342 if (wd->wd_TBorder)
1344 t1 = wd->wd_WindowFlags & WFLG_DEPTHGADGET ? wd->wd_DepthW - 1: 0;
1345 t1 += (wd->wd_WindowFlags & WFLG_SIZEGADGET) ||
1346 (wd->wd_Flags & WDF_TITLEZIP) ? wd->wd_ZoomW - 1: 0;
1348 DoSetMethodNG(wd->wd_TBorder, GA_RelRight, -(wd->wd_TWidth + t1 - 1),
1349 GA_Top, 0,
1350 GA_Width, wd->wd_TWidth,
1351 GA_Height, wd->wd_Top,
1352 TAG_END);
1355 if (wd->wd_RBorder)
1357 t1 = wd->wd_WindowFlags & WFLG_SIZEGADGET ? wd->wd_SizeH - wd->wd_Bottom : 0;
1359 DoSetMethodNG(wd->wd_RBorder, GA_RelRight, -(wd->wd_Right - 1),
1360 GA_Top, wd->wd_Top,
1361 GA_Width, wd->wd_Right,
1362 GA_RelHeight, -(wd->wd_Top + wd->wd_Bottom + t1),
1363 TAG_END);
1366 if (wd->wd_BBorder)
1368 t1 = /*wd->wd_LBorder ?*/ wd->wd_Left /*: 0*/;
1369 t2 = wd->wd_WindowFlags & WFLG_SIZEGADGET ? wd->wd_SizeW : 0;
1371 DoSetMethodNG(wd->wd_BBorder, GA_Left, t1,
1372 GA_RelBottom, -(wd->wd_Bottom - 1),
1373 GA_RelWidth, -(t1 + t2),
1374 GA_Height, wd->wd_Bottom,
1375 TAG_END);
1378 else
1381 * No offsets necessary for
1382 * borderless windows.
1384 gx = gy = bw = bh = 0;
1388 * Set values to the master group.
1390 DoSetMethodNG(wd->wd_Gadgets, GA_Left, gx, GA_Top, gy, GA_RelWidth, -bw, GA_RelHeight, -bh, TAG_DONE);
1393 * Backdrop window?
1395 if (wd->wd_WindowFlags & WFLG_BACKDROP)
1398 * We force the window to be display
1399 * sized or display sized minus the
1400 * screen title bar.
1402 if (wd->wd_Flags & WDF_SHOWTITLE)
1404 sh = scr->Height - scr->BarHeight - 1;
1406 else
1409 * Hide title?
1411 ShowTitle(scr, FALSE);
1414 gmw = sw;
1415 gmh = sh;
1419 * Final check. Does the window fit and does
1420 * the width and height of the window read
1421 * positive values? If not retry with the
1422 * fallback font.
1424 if ((gmw > sw) || (gmh > sh))
1427 * Did it fail with the
1428 * fallback font?
1430 if (font == wd->wd_FallBackFont)
1431 return FALSE;
1434 * Retry with the fallback font.
1436 font = wd->wd_FallBackFont;
1437 goto reCalc;
1440 if (wd->wd_UsedFont = BGUI_OpenFont(font))
1442 *win_w = gmw;
1443 *win_h = gmh;
1445 return TRUE;
1447 return FALSE;
1450 /// WM_OPEN
1452 * Open up the window.
1454 METHOD(WindowClassOpen, Msg, msg)
1456 WD *wd = INST_DATA(cl, obj);
1457 WORD wleft = 0, wtop = 0, width = 0, height = 0, mw, mh;
1458 WORD vw, vh;
1459 struct Screen *pubscreen;
1460 struct Rectangle rect;
1461 struct Gadget *glist = GADGET(wd->wd_Gadgets);
1462 ULONG modeID;
1463 BOOL keepw = wd->wd_Flags & WDF_LOCK_WIDTH;
1464 BOOL keeph = wd->wd_Flags & WDF_LOCK_HEIGHT;
1465 BOOL pub = TRUE;
1466 int borders = 0;
1467 struct Window *w;
1468 struct Message *imsg;
1471 * If the window is already opened we
1472 * return a pointer to it.
1474 if (w = wd->wd_WindowPtr)
1475 return (ULONG)w;
1478 * Link border gadgets.
1480 if (wd->wd_RBorder)
1482 GADGET(wd->wd_RBorder)->NextGadget = glist;
1483 glist = GADGET(wd->wd_RBorder);
1484 borders++;
1487 if (wd->wd_BBorder)
1489 GADGET(wd->wd_BBorder)->NextGadget = glist;
1490 glist = GADGET(wd->wd_BBorder);
1491 borders++;
1494 if (wd->wd_LBorder)
1496 GADGET(wd->wd_LBorder)->NextGadget = glist;
1497 glist = GADGET(wd->wd_LBorder);
1498 borders++;
1501 if (wd->wd_TBorder)
1503 GADGET(wd->wd_TBorder)->NextGadget = glist;
1504 glist = GADGET(wd->wd_TBorder);
1505 borders++;
1509 * Obtain a pointer to the
1510 * screen to use.
1512 if (wd->wd_Screen)
1514 pubscreen = wd->wd_Screen;
1515 pub = FALSE;
1517 else
1519 if (wd->wd_PubScreen) pubscreen = wd->wd_PubScreen;
1520 else
1523 * Lock the screen.
1525 if (!(pubscreen = LockPubScreen(wd->wd_PubScreenName)))
1527 * Fallback to the default screen
1528 * when locking failed. Should be
1529 * made optional?
1531 pubscreen = LockPubScreen(NULL);
1533 * Tell'm we locked the screen.
1535 if (pubscreen)
1536 wd->wd_Flags |= WDF_SCREEN_LOCKED;
1538 wd->wd_Screen = pubscreen;
1542 * Do we have a screen?
1544 if (!pubscreen) return 0;
1547 * Set up BDrawInfo drawinfo and pens.
1549 wd->wd_DrawInfo = GetScreenDrawInfo(pubscreen);
1552 for (i = 0; i < NUMDRIPENS; i++)
1554 wd->wd_BDI.bdi_Pens[i] = (wd->wd_BDI.bdi_DrInfo && (i < wd->wd_BDI.bdi_DrInfo->dri_NumPens)) ?
1555 wd->wd_BDI.bdi_DrInfo->dri_Pens[i] : DefDriPens[i];
1559 vw = pubscreen->Width;
1560 vh = pubscreen->Height;
1563 * Obtain the mode ID from the screen to use.
1566 if ((modeID = GetVPModeID(&pubscreen->ViewPort)) != INVALID_ID)
1569 * Find out TEXT overscan
1570 * dimensions.
1572 if (QueryOverscan(modeID, &rect, OSCAN_TEXT))
1575 * Compute TEXT overscan width and height
1576 * for this display mode.
1578 vw = rect.MaxX - rect.MinX + 1;
1579 vh = rect.MaxY - rect.MinY + 1;
1585 * Store the text overscan dimensions.
1587 wd->wd_TextW = vw;
1588 wd->wd_TextH = vh;
1590 /* AROS FIX <-> AMIGA FIX? */
1592 if (vw > pubscreen->Width) vw = pubscreen->Width;
1593 if (vh > pubscreen->Height) vh = pubscreen->Height;
1595 if (!WinSize(wd, (UWORD *)&width, (UWORD *)&height))
1596 goto failure;
1599 * Backdrop window?
1601 if (wd->wd_WindowFlags & WFLG_BACKDROP)
1604 * We force the window to be display
1605 * sized or display sized minus the
1606 * screen title bar.
1608 wleft = 0;
1610 if (wd->wd_Flags & WDF_SHOWTITLE)
1611 wtop = pubscreen->BarHeight + 1;
1612 else
1613 wtop = 0;
1615 goto forceThis;
1619 * The computed width and height are the
1620 * absolute minimum size that the window
1621 * can have. We save them here for the
1622 * window alternate (zipped) position.
1624 mw = width;
1625 mh = height;
1628 * Scale the window size?
1630 if (wd->wd_WidthScale) width += ((vw - width) * wd->wd_WidthScale) / 100;
1631 if (wd->wd_HeightScale) height += ((vh - height) * wd->wd_HeightScale) / 100;
1634 * When the window was opened before and the size is known or there
1635 * is previous size information available we use this information.
1637 if (wd->wd_Flags & WDF_CHANGE_VALID || GetWindowBounds(wd->wd_ID, &wd->wd_FixedPos))
1640 * If the width or height of the window
1641 * is fixed then we reuse the previous
1642 * values. If not we use the new values.
1644 width = keepw ? width : wd->wd_FixedPos.Width;
1645 height = keeph ? height : wd->wd_FixedPos.Height;
1648 * If the window is placed relative to a
1649 * given rectangle we place it again relative
1650 * to that rectangle. Otherwise we copy the
1651 * previous position.
1653 if (wd->wd_Flags & WDF_RELBOX)
1655 wleft = ((wd->wd_RelPos.Width - width) >> 1) + wd->wd_RelPos.Left;
1656 wtop = ((wd->wd_RelPos.Height - height) >> 1) + wd->wd_RelPos.Top;
1658 else
1660 wleft = wd->wd_FixedPos.Left;
1661 wtop = wd->wd_FixedPos.Top;
1665 * In case the font changed we need to check if the window has become
1666 * smaller than allowed and adjust if necessary.
1668 if (width < mw) width = mw;
1669 if (height < mh) height = mh;
1672 * Does the window still fit in this
1673 * situation?
1675 if (width > pubscreen->Width && mw <= pubscreen->Width) width = pubscreen->Width;
1676 if (height > pubscreen->Height && mh <= pubscreen->Height) height = pubscreen->Height;
1679 * Adjust the window position when necessary.
1681 if ((wleft + width) > pubscreen->Width) wleft = pubscreen->Width - width;
1682 if ((wtop + height) > pubscreen->Height) wtop = pubscreen->Height - height;
1684 else
1687 * Window positioned relative to a given rectangle?
1689 if (!(wd->wd_Flags & WDF_RELBOX))
1692 * What position is requested?
1694 switch (wd->wd_Position)
1696 case POS_CENTERSCREEN:
1697 wleft = ((vw - width) >> 1) - pubscreen->ViewPort.DxOffset;
1698 wtop = ((vh - height) >> 1) - pubscreen->ViewPort.DyOffset;
1699 break;
1701 case POS_CENTERMOUSE:
1702 wleft = pubscreen->MouseX - (width >> 1) - pubscreen->ViewPort.DxOffset;
1703 wtop = pubscreen->MouseY - (height >> 1) - pubscreen->ViewPort.DyOffset;
1704 break;
1707 else
1710 * Setup window according to the
1711 * rectangle.
1713 wleft = ((wd->wd_RelPos.Width - width) >> 1) + wd->wd_RelPos.Left;
1714 wtop = ((wd->wd_RelPos.Height - height) >> 1) + wd->wd_RelPos.Top;
1718 forceThis:
1721 * Do we have menus defined?
1723 if (wd->wd_MenuStrip)
1726 * Set the menus up.
1728 if (!DoMenuStrip(wd, pubscreen))
1729 goto failure;
1733 * Setup zip positions.
1735 if (wd->wd_Flags & WDF_TITLEZIP)
1738 * We always have a zoom gadget.
1740 wd->wd_Zoom[2] = wd->wd_ZoomW - 1;
1743 * Add the pixel-width of the title + 60.
1745 if (wd->wd_WindowTitle) wd->wd_Zoom[2] += TextWidth(&pubscreen->RastPort, wd->wd_WindowTitle) + 60;
1748 * And any other system gadgets.
1750 if (wd->wd_WindowFlags & WFLG_DEPTHGADGET) wd->wd_Zoom[2] += wd->wd_DepthW - 1;
1751 if (wd->wd_WindowFlags & WFLG_CLOSEGADGET) wd->wd_Zoom[2] += wd->wd_CloseW - 1;
1754 * And a top-group minimum size.
1756 if (wd->wd_TBorder) wd->wd_Zoom[2] += wd->wd_TWidth;
1759 * Title bar-height.
1761 wd->wd_Zoom[3] = wd->wd_Top;
1764 if (wd->wd_Flags & WDF_PREBUFFER) AsmDoMethod(wd->wd_Gadgets, BASE_RENDERBUFFER, pubscreen, width, height);
1767 * Open the window (finally :))
1769 w = wd->wd_WindowPtr = OpenWindowTags(NULL,
1770 WA_Left, wleft, WA_Top, wtop,
1771 WA_Width, width, WA_Height, height,
1772 WA_Flags, wd->wd_WindowFlags, WA_Gadgets, glist,
1773 WA_BackFill, &BackFill_hook, WA_RptQueue, 1,
1774 WA_MinWidth, mw, WA_MinHeight, mh,
1775 WA_MaxWidth, (wd->wd_Flags & WDF_LOCK_WIDTH) ? mw : ~0,
1776 WA_MaxHeight, (wd->wd_Flags & WDF_LOCK_HEIGHT) ? mh : ~0,
1777 wd->wd_WindowTitle ? WA_Title : TAG_IGNORE, wd->wd_WindowTitle,
1778 wd->wd_ScreenTitle ? WA_ScreenTitle : TAG_IGNORE, wd->wd_ScreenTitle,
1779 pub ? WA_PubScreen : WA_CustomScreen, pubscreen,
1780 wd->wd_Flags & WDF_TITLEZIP ? WA_Zoom : TAG_IGNORE, wd->wd_Zoom,
1781 WA_IDCMP, wd->wd_IDCMPFlags,
1782 WA_MenuHelp, TRUE, TAG_END);
1784 if (!w) goto failure;
1787 * Set the font.
1789 wd->wd_OrigFont = w->RPort->Font;
1790 FSetFont(w->RPort, wd->wd_UsedFont);
1793 * Move the top-border group to the
1794 * beginning of the list.
1796 if (borders)
1798 RemoveGList(w, glist, borders);
1799 AddGList(w, glist, 0, borders, NULL);
1803 * Save window bounds.
1805 SetWindowBounds(wd->wd_ID, (struct IBox *)&w->LeftEdge);
1808 * Setup menu-strip if one exists.
1810 if (wd->wd_Menus)
1811 SetMenuStrip(w, wd->wd_Menus );
1814 * When we have a shared MsgPort we must move any initial messages to it,
1815 * then set it up.
1817 if (wd->wd_Flags & WDF_SHARED_MSGPORT)
1820 * Set it to a flag that will not occur, to stop input without closing the port.
1822 ModifyIDCMP(w, IDCMP_REQCLEAR);
1824 while (imsg = GetMsg(w->UserPort))
1827 * Dump message onto the other port.
1829 PutMsg(wd->wd_UserPort, imsg);
1832 * Free intuition's port.
1834 ModifyIDCMP(w, 0);
1837 * Poke the shared port.
1839 w->UserPort = wd->wd_UserPort;
1842 * Setup the flags.
1844 ModifyIDCMP(w, wd->wd_IDCMPFlags);
1846 else
1849 * Pick up the intuition created message port.
1851 wd->wd_UserPort = w->UserPort;
1855 * If requested setup this window
1856 * as a workbench App-Window.
1858 if (wd->wd_Flags & WDF_IS_APPWINDOW)
1860 * Quietly fails.
1862 MakeAppWindow(wd);
1865 * Add window to the internal list.
1866 * Also fails quietly...
1868 AddWindow(obj, w);
1870 return (ULONG)w;
1872 failure:
1874 AsmCoerceMethod(cl, obj, WM_CLOSE);
1876 return 0;
1878 METHOD_END
1882 * Clear all messages from
1883 * the port which belong to
1884 * the window.
1886 //STATIC ASM VOID ClearMsgPort( REG(a0) WD *wd )
1887 STATIC ASM REGFUNC1(VOID, ClearMsgPort,
1888 REGPARAM(A0, WD *, wd))
1890 struct IntuiMessage *imsg;
1891 struct Node *succ;
1894 * Don't race intuition.
1896 Forbid();
1898 imsg = ( struct IntuiMessage * )wd->wd_UserPort->mp_MsgList.lh_Head;
1900 while ( succ = imsg->ExecMessage.mn_Node.ln_Succ ) {
1901 if ( imsg->IDCMPWindow == wd->wd_WindowPtr ) {
1902 Remove(( struct Node * )imsg );
1903 ReplyMsg(( struct Message * )imsg );
1905 imsg = ( struct IntuiMessage * )succ;
1907 Permit();
1909 REGFUNC_END
1910 /// WM_CLOSE
1912 * Close the window.
1914 METHOD(WindowClassClose, Msg, msg)
1916 WD *wd = INST_DATA(cl, obj);
1917 ULONG rc = 0;
1918 struct Window *w;
1920 if (w = wd->wd_WindowPtr)
1923 * When a shared MsgPort is used
1924 * we clear the UserPort ptr in the window
1925 * structure.
1927 Forbid();
1928 ClearMsgPort(wd);
1929 if (wd->wd_Flags & WDF_SHARED_MSGPORT)
1931 w->UserPort = NULL;
1933 ModifyIDCMP(w, 0);
1934 Permit();
1937 * Close tool-tip window.
1939 AsmDoMethod(obj, WM_CLOSETOOLTIP);
1942 * Wakeup the window.
1944 while (wd->wd_SleepCnt)
1945 AsmDoMethod(obj, WM_WAKEUP);
1948 * AppWindow?
1950 if (wd->wd_Flags & WDF_IS_APPWINDOW)
1951 KillAppWindow(wd);
1954 * Remove the window menus.
1956 if (wd->wd_Menus) ClearMenuStrip(w);
1959 * Setup original font.
1961 FSetFont(w->RPort, wd->wd_OrigFont);
1964 * Close the window.
1966 CloseWindow(w);
1967 wd->wd_WindowPtr = NULL;
1970 * Remove it and all outstanding ID's from the internal lists.
1972 RemWindow(obj);
1973 RemoveIDReport(w);
1976 * Clear continuation flags.
1978 wd->wd_NextSelect = MENUNULL;
1979 wd->wd_Flags &= ~WDF_DRAGSELECT;
1982 * Free the menus.
1984 if (wd->wd_Menus)
1986 FreeMenus(wd->wd_Menus);
1987 wd->wd_Menus = NULL;
1990 if (wd->wd_BufferRP)
1992 wd->wd_BufferRP->Layer = wd->wd_BufferLayer;
1993 BGUI_FreeRPortBitMap(wd->wd_BufferRP);
1994 wd->wd_BufferRP = NULL;
1997 rc = 1;
2000 if (wd->wd_UsedFont)
2002 BGUI_CloseFont(wd->wd_UsedFont);
2003 wd->wd_UsedFont = NULL;
2006 if (wd->wd_VisualInfo)
2008 FreeVisualInfo(wd->wd_VisualInfo);
2009 wd->wd_VisualInfo = NULL;
2012 if (wd->wd_DrawInfo)
2014 FreeScreenDrawInfo(wd->wd_Screen, wd->wd_DrawInfo);
2015 wd->wd_DrawInfo = NULL;
2018 if (wd->wd_Flags & WDF_SCREEN_LOCKED)
2020 UnlockPubScreen(NULL, wd->wd_Screen);
2021 wd->wd_Flags &= ~WDF_SCREEN_LOCKED;
2024 if (wd->wd_PubScreenName)
2026 wd->wd_Screen = NULL;
2029 return rc;
2031 METHOD_END
2033 /// WM_SLEEP
2035 * Put the window to sleep.
2037 METHOD(WindowClassSleep, Msg, msg)
2039 WD *wd = INST_DATA(cl, obj);
2040 ULONG rc = 0;
2043 * Only go to sleep if the window is open.
2045 if (wd->wd_WindowPtr)
2048 * If the sleep nest counter is 0 we setup a requester
2049 * and a busy pointer.
2051 if (wd->wd_SleepCnt++ == 0)
2052 wd->wd_Lock = BGUI_LockWindow(wd->wd_WindowPtr);
2054 * Return 1 for sucess.
2056 rc = 1;
2058 return rc;
2060 METHOD_END
2062 /// WM_WAKEUP
2064 * Wake the window back up.
2066 METHOD(WindowClassWakeUp, Msg, msg)
2068 WD *wd = INST_DATA(cl, obj);
2069 ULONG rc = 0;
2072 * Only decrease the sleep nest counter when the
2073 * window is open _and_ the sleep nest counter is not 0.
2075 if (wd->wd_Lock)
2077 if (--wd->wd_SleepCnt == 0)
2080 * When the sleep nest counter becomes zero we remove the
2081 * requester and reset the pointer.
2083 BGUI_UnlockWindow(wd->wd_Lock);
2084 wd->wd_Lock = NULL;
2086 rc = 1;
2088 return rc;
2090 METHOD_END
2094 * Keep track of window bound changes.
2096 //STATIC ASM ULONG WindowClassChange( REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) Msg msg )
2097 STATIC ASM REGFUNC3(ULONG, WindowClassChange,
2098 REGPARAM(A0, Class *, cl),
2099 REGPARAM(A2, Object *, obj),
2100 REGPARAM(A1, Msg, msg))
2102 WD *wd = INST_DATA(cl, obj);
2103 ULONG rc = 0;
2104 struct Window *w;
2106 if (w = wd->wd_WindowPtr)
2108 wd->wd_FixedPos = *IBOX(&w->LeftEdge);
2109 wd->wd_Flags |= WDF_CHANGE_VALID;
2110 rc = 1;
2112 * Save window bounds.
2114 SetWindowBounds(wd->wd_ID, (struct IBox *)&w->LeftEdge);
2116 return rc;
2118 REGFUNC_END
2121 * Get an attribute.
2123 //STATIC ASM ULONG WindowClassGet(REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) struct opGet *opg)
2124 STATIC ASM REGFUNC3(ULONG, WindowClassGet,
2125 REGPARAM(A0, Class *, cl),
2126 REGPARAM(A2, Object *, obj),
2127 REGPARAM(A1, struct opGet *, opg))
2129 WD *wd = (WD *)INST_DATA(cl, obj);
2130 ULONG rc = 1, *store = opg->opg_Storage;
2132 struct Window *win;
2134 switch (opg->opg_AttrID)
2136 case WINDOW_GadgetOK:
2137 STORE !(wd->wd_Flags & WDF_REMOVED);
2138 break;
2140 case WINDOW_ToolTicks:
2141 STORE wd->wd_ToolTickTime;
2142 break;
2144 case WINDOW_MenuStrip:
2145 STORE wd->wd_Menus;
2146 break;
2148 case WINDOW_UserPort:
2149 if (wd->wd_WindowPtr) STORE wd->wd_UserPort;
2150 else STORE NULL;
2151 break;
2153 case WINDOW_SigMask:
2154 STORE (wd->wd_WindowPtr ? (1 << wd->wd_UserPort->mp_SigBit) : 0);
2155 break;
2157 case WINDOW_AppMask:
2158 STORE (wd->wd_AppPort ? (1 << wd->wd_AppPort->mp_SigBit) : 0);
2159 break;
2161 case WINDOW_Window:
2162 STORE wd->wd_WindowPtr;
2163 break;
2165 case WINDOW_Font:
2166 STORE wd->wd_Font;
2167 break;
2169 case WINDOW_Bounds:
2170 if ( wd->wd_WindowPtr )
2171 *(( struct IBox * )store ) = *(( struct IBox * )&wd->wd_WindowPtr->LeftEdge );
2172 else
2173 rc = 0;
2174 break;
2176 case WINDOW_Title:
2177 STORE wd->wd_WindowTitle;
2178 break;
2180 case WINDOW_ScreenTitle:
2181 STORE wd->wd_ScreenTitle;
2182 break;
2184 case WINDOW_TitleID:
2185 STORE wd->wd_WindowTitleID;
2186 break;
2188 case WINDOW_ScreenTitleID:
2189 STORE wd->wd_ScreenTitleID;
2190 break;
2192 case WINDOW_HelpTextID:
2193 STORE wd->wd_HelpTextID;
2194 break;
2196 case WINDOW_AutoAspect:
2197 STORE test(wd->wd_Flags & WDF_AUTOASPECT);
2198 break;
2200 case WINDOW_BufferRP:
2201 if ((win = wd->wd_WindowPtr) && !(wd->wd_Flags & WDF_NO_BUFFER) && (FGetDepth(win->RPort) <= 8))
2203 if ((wd->wd_BRW != win->Width) || (wd->wd_BRH != win->Height))
2205 wd->wd_BRW = win->Width;
2206 wd->wd_BRH = win->Height;
2207 if (wd->wd_BufferRP)
2209 wd->wd_BufferRP->Layer = wd->wd_BufferLayer;
2210 BGUI_FreeRPortBitMap(wd->wd_BufferRP);
2211 wd->wd_BufferRP = NULL;
2214 if (!wd->wd_BufferRP)
2216 wd->wd_BufferRP = BGUI_CreateRPortBitMap(win->RPort, wd->wd_BRW, wd->wd_BRH, 0);
2217 wd->wd_BufferLayer = wd->wd_BufferRP->Layer;
2218 wd->wd_BufferRP->Layer = NULL;
2220 STORE wd->wd_BufferRP;
2222 else
2224 STORE NULL;
2226 break;
2228 default:
2229 rc = AsmDoSuperMethodA(cl, obj, (Msg)opg);
2230 break;
2232 return rc;
2234 REGFUNC_END
2237 * Put out a help-request.
2239 METHOD(WindowClassHelp, Msg, msg)
2241 WD *wd = INST_DATA( cl, obj );
2242 struct bmShowHelp bsh;
2243 #ifdef __AROS__
2244 #warning Commented the following line
2245 #else
2246 struct NewAmigaGuide nag = { NULL };
2247 #endif
2248 ULONG rc = BMHELP_FAILURE;
2249 struct Window *w;
2252 * Only when the window is open.
2254 if (w = wd->wd_WindowPtr)
2257 * Setup a help request for the
2258 * master object.
2260 bsh.MethodID = BASE_SHOWHELP;
2261 bsh.bsh_Window = w;
2262 bsh.bsh_Requester = NULL;
2263 bsh.bsh_Mouse.X = w->MouseX;
2264 bsh.bsh_Mouse.Y = w->MouseY;
2266 * Go to sleep and send the
2267 * request.
2269 AsmDoMethod(obj, WM_SLEEP);
2272 * Any help shown by the master object?
2274 if (AsmDoMethodA(wd->wd_Gadgets, (Msg)&bsh) == BMHELP_NOT_ME)
2277 * No. Show the window help.
2279 if (wd->wd_HelpFile || wd->wd_HelpText)
2282 * Only if the mouse is located
2283 * in the window.
2285 if (bsh.bsh_Mouse.X > 0 && bsh.bsh_Mouse.Y > 0 && bsh.bsh_Mouse.X < w->Width && bsh.bsh_Mouse.Y < w->Height)
2287 if (wd->wd_HelpText)
2289 ShowHelpReq(w, wd->wd_HelpText);
2290 rc = BMHELP_OK;
2292 else
2294 #ifdef __AROS__
2295 #warning Commented the following lines
2296 #else
2297 nag.nag_Name = (STRPTR)wd->wd_HelpFile;
2298 nag.nag_Node = (STRPTR)wd->wd_HelpNode;
2299 nag.nag_Line = wd->wd_HelpLine;
2300 nag.nag_Screen = w->WScreen;
2302 if (DisplayAGuideInfo(&nag, NULL))
2303 rc = BMHELP_OK;
2304 #endif
2310 * Wakeup the window.
2312 AsmDoMethod(obj, WM_WAKEUP);
2314 return rc;
2316 METHOD_END
2319 * Fill up an InputEvent structure
2320 * with RAWKEY information.
2322 //STATIC ASM VOID FillIE(REG(a0) struct InputEvent *ie, REG(a1) struct IntuiMessage *imsg)
2323 STATIC ASM REGFUNC2(VOID, FillIE,
2324 REGPARAM(A0, struct InputEvent *, ie),
2325 REGPARAM(A1, struct IntuiMessage *, imsg))
2327 ie->ie_Class = IECLASS_RAWKEY;
2328 ie->ie_Code = imsg->Code;
2329 ie->ie_Qualifier = imsg->Qualifier;
2330 ie->ie_EventAddress = imsg->IAddress ? *((APTR *)(imsg->IAddress)) : NULL;
2331 ie->ie_TimeStamp.tv_secs = imsg->Seconds;
2332 ie->ie_TimeStamp.tv_micro = imsg->Micros;
2334 REGFUNC_END
2337 * Get the first message from the
2338 * window port which belongs to the window.
2340 //STATIC ASM struct IntuiMessage *GetIMsg( REG(a0) WD *wd )
2341 STATIC ASM REGFUNC1(struct IntuiMessage *, GetIMsg,
2342 REGPARAM(A0, WD *, wd))
2344 struct IntuiMessage *imsg;
2345 struct MsgPort *mp = wd->wd_UserPort;
2348 * No need to race intuition.
2350 Forbid();
2352 for ( imsg = ( struct IntuiMessage * )mp->mp_MsgList.lh_Head; imsg->ExecMessage.mn_Node.ln_Succ; imsg = ( struct IntuiMessage * )imsg->ExecMessage.mn_Node.ln_Succ ) {
2353 if ( imsg->IDCMPWindow == wd->wd_WindowPtr ) {
2354 Remove(( struct Node * )imsg );
2355 Permit();
2356 return( imsg );
2360 Permit();
2361 return( NULL );
2363 REGFUNC_END
2366 * Find out if an object must receive a key message.
2368 STATIC ULONG KeyGadget(Class *cl, Object *obj, struct IntuiMessage *imsg)
2371 WD *wd = INST_DATA(cl, obj);
2372 struct InputEvent ie;
2373 struct wmKeyInput wk;
2374 struct IntuiMessage *im = NULL;
2375 APTR iadd;
2376 ULONG irc, id, rc = WMHI_IGNORE;
2378 ULONG class = imsg->Class;
2379 UWORD code = imsg->Code;
2380 UWORD qual = imsg->Qualifier;
2381 UBYTE key = (UBYTE)code;
2383 struct Window *w = wd->wd_WindowPtr;
2385 Object *ob;
2388 * No menus during keyboard
2389 * activation.
2391 if (!(wd->wd_WindowFlags & WFLG_RMBTRAP))
2393 Forbid();
2394 w->Flags |= WFLG_RMBTRAP;
2395 Permit();
2399 * Initialize input event.
2401 if (code & IECODE_UP_PREFIX)
2402 goto end;
2404 FillIE(&ie, imsg);
2405 if (MapRawKey(&ie, &key, 1, NULL) == 1)
2406 code = key;
2407 else
2409 code = code | 0xFF00;
2412 #ifdef __AROS__
2413 if (!(ob = (Object *)AsmDoMethod(obj, BASE_FINDKEY, qual, code)))
2414 goto end;
2415 #else
2416 if (!(ob = (Object *)AsmDoMethod(obj, BASE_FINDKEY, (qual << 16) | code)))
2417 goto end;
2418 #endif
2421 * Initialize wmKeyInput structure.
2423 wk.MethodID = WM_KEYACTIVE;
2424 wk.wmki_IEvent = &ie;
2425 wk.wmki_ID = &id;
2426 wk.wmki_Key = &key;
2429 * Send a WM_KEYACTIVE message to the target.
2431 irc = BGUI_DoGadgetMethodA(ob, w, NULL, (Msg)&wk);
2434 * Reply the originating message.
2436 ReplyMsg((struct Message *)imsg);
2437 imsg = NULL;
2440 * Are we done?
2442 if (irc & WMKF_VERIFY)
2445 * Yes. Return the id.
2447 rc = id;
2448 goto end;
2450 else if (irc & WMKF_CANCEL)
2453 * We are cancelled :^(
2454 * Return WMHI_IGNORE.
2456 goto end;
2458 else if (irc & WMKF_ACTIVATE)
2461 * We are told to activate the
2462 * gadget through intuition channels.
2464 ClearMsgPort(wd);
2465 ActivateGadget(GADGET(ob), w, NULL);
2466 goto end;
2468 else
2471 * Boom. We are active.
2473 wk.MethodID = WM_KEYINPUT;
2475 for(;;)
2477 WaitPort(wd->wd_UserPort);
2478 while (im = GetIMsg(wd))
2480 class = im->Class;
2481 code = im->Code;
2482 qual = im->Qualifier;
2483 iadd = im->IAddress;
2485 switch (class)
2488 * Check out the RAWKEY event.
2490 case IDCMP_RAWKEY:
2491 if (qual & IEQUALIFIER_REPEAT) break;
2492 if ((code & IECODE_UP_PREFIX) == 0)
2494 myDoGadgetMethod(ob, w, NULL, WM_KEYINACTIVE, NULL);
2495 goto end;
2497 FillIE(&ie, im);
2498 irc = BGUI_DoGadgetMethodA(ob, wd->wd_WindowPtr, NULL, (Msg)&wk);
2499 if (irc & WMKF_VERIFY)
2501 myDoGadgetMethod(ob, w, NULL, WM_KEYINACTIVE, NULL);
2502 rc = id;
2503 goto end;
2505 else if (irc & WMKF_CANCEL)
2507 myDoGadgetMethod(ob, w, NULL, WM_KEYINACTIVE, NULL);
2508 goto end;
2510 break;
2512 case IDCMP_CLOSEWINDOW:
2514 * Pass on the close window request.
2516 myDoGadgetMethod(ob, w, NULL, WM_KEYINACTIVE, NULL);
2517 rc = WMHI_CLOSEWINDOW;
2518 goto end;
2520 case IDCMP_GADGETUP:
2522 * Pass on the gadget request.
2524 myDoGadgetMethod(ob, w, NULL, WM_KEYINACTIVE, NULL);
2525 rc = GADGET(iadd)->GadgetID;
2526 goto end;
2528 case IDCMP_INACTIVEWINDOW:
2530 * Window inactive? Abort keyboard actions.
2532 myDoGadgetMethod(ob, w, NULL, WM_KEYINACTIVE, NULL);
2533 ClearMsgPort(wd);
2534 goto end;
2536 case IDCMP_SIZEVERIFY:
2538 * Exit... NOW!
2540 myDoGadgetMethod(ob, w, NULL, WM_KEYINACTIVE, NULL);
2541 wd->wd_OW = w->Width;
2542 wd->wd_OH = w->Height;
2543 wd->wd_Flags |= WDF_REMOVED;
2544 RemoveGadget(w, (struct Gadget *)wd->wd_Gadgets);
2545 ClearMsgPort(wd);
2546 goto end;
2550 * Reply the message.
2552 ReplyMsg((struct Message *)im);
2556 end:
2559 * Reply the un-replyed messages.
2561 if (imsg) ReplyMsg((struct Message *)imsg);
2562 if (im) ReplyMsg((struct Message *)im);
2565 * Menu actions possible if they were before the keyboard stuff
2566 * and if we don't stay active.
2568 if (!(wd->wd_WindowFlags & WFLG_RMBTRAP))
2570 Forbid();
2571 w->Flags &= ~WFLG_RMBTRAP;
2572 Permit();
2574 return rc;
2578 * Find tab-cycle entry.
2580 //STATIC ASM TABCYCLE *GetCycleNode( REG(a0) WD *wd, REG(a1) Object *obj )
2581 STATIC ASM REGFUNC2(TABCYCLE *, GetCycleNode,
2582 REGPARAM(A0, WD *, wd),
2583 REGPARAM(A1, Object *, obj))
2585 TABCYCLE *tc;
2587 for ( tc = wd->wd_CycleList.cl_First; tc->tc_Next; tc = tc->tc_Next ) {
2588 if ( tc->tc_Object == obj )
2589 return( tc );
2591 return( NULL );
2593 REGFUNC_END
2596 * Perform update notification.
2598 //STATIC ASM VOID UpdateNotification( REG(a0) WD *wd, REG(a1) struct TagItem *attr, REG(d0) ULONG id )
2599 STATIC ASM REGFUNC3(VOID, UpdateNotification,
2600 REGPARAM(A0, WD *, wd),
2601 REGPARAM(A1, struct TagItem *, attr),
2602 REGPARAM(D0, ULONG, id))
2604 struct TagItem *clones;
2605 UPN *up;
2608 * Clone attributes.
2610 if ( clones = CloneTagItems( attr )) {
2612 * Find target.
2614 for ( up = wd->wd_UpdateList.ul_First; up->up_Next; up = up->up_Next )
2617 * Is this the one?
2619 if ( up->up_ID == id )
2622 * Map clones when necessary.
2624 if ( up->up_MapList )
2625 MapTags( clones, up->up_MapList, TRUE );
2627 * Set attributes to the target.
2629 myDoGadgetMethod(up->up_Target, wd->wd_WindowPtr, NULL, OM_UPDATE, clones, NULL, 0);
2631 * Unmap clones when necessary.
2633 if ( up->up_MapList )
2634 UnmapTags( clones, up->up_MapList );
2638 * Free clones.
2640 FreeTagItems( clones );
2643 REGFUNC_END
2648 * Default tool tip hook.
2650 //STATIC ASM ULONG ToolTip_func(REG(a0) struct Hook *h, REG(a2) Object *obj, REG(a1) struct ttCommand *ttc)
2651 STATIC ASM REGFUNC3(ULONG, ToolTip_func,
2652 REGPARAM(A0, struct Hook *, h),
2653 REGPARAM(A2, Object *, obj),
2654 REGPARAM(A1, struct ttCommand *, ttc))
2656 WD *wd;
2657 struct Window *tw = NULL;
2658 struct TextFont *of;
2659 struct RastPort *rp;
2660 struct IBox ibx;
2661 UWORD x, y, ww, wh;
2662 UBYTE *tip, *tc;
2663 ULONG args[2];
2664 struct BaseInfo *bi;
2666 switch (ttc->ttc_Command)
2668 case TT_SHOW:
2669 wd = (WD *)ttc->ttc_UserData;
2672 * Does the tip-object have a tool-tip?
2674 tc = NULL;
2675 Get_Attr(ttc->ttc_Object, BT_ToolTip, (ULONG *)&tc);
2676 if (tc)
2679 * Copy and setup the tip.
2681 if (tip = (UBYTE *)BGUI_AllocPoolMem(strlen(tc) + 10))
2683 args[0] = BARDETAILPEN;
2684 args[1] = (ULONG)tc;
2685 DoSPrintF(tip, "\033d%ld%s", args);
2687 else
2689 tip = tc;
2690 tc = NULL;
2693 rp = wd->wd_WindowPtr->RPort;
2696 * Set the font.
2698 of = rp->Font;
2699 FSetFont(rp, wd->wd_UsedFont);
2701 BGUI_InfoTextSize(rp, tip, (UWORD *)&ibx.Width, (UWORD *)&ibx.Height);
2702 FSetFont(rp, of);
2705 * Get mouse position.
2707 x = wd->wd_WindowPtr->MouseX;
2708 y = wd->wd_WindowPtr->MouseY;
2711 * Tool-tip width and height.
2713 ww = ibx.Width + 8;
2714 wh = ibx.Height + 4;
2717 * Open tool-tip window with it's
2718 * bottom right corner under the mouse.
2720 if (tw = OpenWindowTags(NULL, WA_Left, wd->wd_WindowPtr->LeftEdge + x - ww,
2721 WA_Top, wd->wd_WindowPtr->TopEdge + y - wh,
2722 WA_Width, ww,
2723 WA_Height, wh,
2724 WA_IDCMP, 0,
2725 WA_Flags, WFLG_BORDERLESS|WFLG_RMBTRAP,
2726 WA_CustomScreen, wd->wd_Screen,
2727 TAG_DONE))
2729 rp = tw->RPort;
2731 #ifdef DEBUG_BGUI
2732 if (bi = AllocBaseInfoDebug(__FILE__,__LINE__,BI_Screen, wd->wd_Screen, BI_RastPort, rp, TAG_DONE))
2733 #else
2734 if (bi = AllocBaseInfo(BI_Screen, wd->wd_Screen, BI_RastPort, rp, TAG_DONE))
2735 #endif
2738 * Set the font.
2740 of = rp->Font;
2741 BSetFont(bi, wd->wd_UsedFont);
2744 * Tip background color.
2746 BSetDrMd(bi, JAM1);
2747 BSetDPenA(bi, BARBLOCKPEN);
2748 BRectFill(bi, 1, 1, ww - 2, wh - 2);
2751 * Tip border and text.
2753 BSetDPenA(bi, BARDETAILPEN);
2754 Move(rp, 0, 0);
2755 Draw(rp, ww - 1, 0);
2756 Draw(rp, ww - 1, wh - 1);
2757 Draw(rp, 0, wh - 1);
2758 Draw(rp, 0, 0);
2761 * Render the tip.
2763 ibx.Left = 4;
2764 ibx.Top = 2;
2766 RenderText(bi, tip, &ibx);
2767 BSetFont(bi, of);
2769 FreeBaseInfo(bi);
2772 * Free copy.
2774 if (tc) BGUI_FreePoolMem(tip);
2776 break;
2778 case TT_HIDE:
2779 tw = (struct Window *)ttc->ttc_UserData;
2780 if (tw) CloseWindow(tw);
2781 break;
2784 return (ULONG)tw;
2786 REGFUNC_END
2787 static struct Hook ToolTipHook = { NULL, NULL, (HOOKFUNC)ToolTip_func, NULL, NULL };
2789 /// WM_CLOSETOOLTIP
2791 METHOD(WindowClassCloseTT, Msg, msg)
2793 WD *wd = INST_DATA(cl, obj);
2794 struct ttCommand ttc;
2796 if (wd->wd_ToolTip)
2798 ttc.ttc_Command = TT_HIDE;
2799 ttc.ttc_Object = wd->wd_ToolTipObject;
2800 ttc.ttc_UserData = (APTR)wd->wd_ToolTip;
2802 BGUI_CallHookPkt(wd->wd_ToolTipHook ? wd->wd_ToolTipHook : &ToolTipHook, (void *)obj, (void *)&ttc);
2804 wd->wd_ToolX = wd->wd_ToolY = -1;
2805 wd->wd_ToolTip = NULL;
2807 return 1;
2809 METHOD_END
2811 /// WM_HANDLEIDCMP
2813 * Handle a window's IDCMP messages.
2815 METHOD(WindowClassIDCMP, Msg, msg)
2817 struct IntuiMessage *imsg;
2818 struct TagItem *attr, *tag;
2819 struct MenuItem *mi;
2820 TABCYCLE *tc;
2821 WD *wd = INST_DATA(cl, obj);
2822 ULONG rc = WMHI_IGNORE, inhibit, id;
2823 UWORD code;
2824 Object *obja;
2825 struct grmWhichObject grwo;
2826 struct ttCommand ttc;
2827 WORD x, y;
2828 ULONG mouseact;
2829 BOOL forward;
2830 Object *tabbed;
2831 struct Window *w = wd->wd_WindowPtr;
2835 * No window!
2837 if (!w) return WMHI_NOMORE;
2840 * Locked out?
2842 if (!(wd->wd_Flags & WDF_LOCKOUT))
2845 * Are we in a drag-selection loop?
2846 * If so continue it.
2848 if (wd->wd_Flags & WDF_DRAGSELECT)
2850 code = wd->wd_NextSelect;
2851 imsg = NULL;
2852 goto dragSelect;
2856 * Reports on the stack?
2858 if ((id = GetIDReport(w)) != ~0)
2861 * Return the ID.
2863 return id;
2868 * Is there a message.
2870 while (imsg = GetIMsg(wd))
2873 * Any movement?
2876 BOOL close_tooltip;
2878 if(!(close_tooltip=(w->MouseX != wd->wd_ToolX || w->MouseY != wd->wd_ToolY)))
2880 switch(imsg->Class)
2883 case IDCMP_IDCMPUPDATE:
2884 case IDCMP_DISKINSERTED:
2885 case IDCMP_DISKREMOVED:
2886 case IDCMP_WBENCHMESSAGE:
2887 case IDCMP_INTUITICKS:
2888 break;
2889 default:
2890 close_tooltip=TRUE;
2891 break;
2894 if(close_tooltip)
2897 * Do we have a tool-tip to close?
2899 if (wd->wd_ToolTip)
2900 AsmDoMethod(obj, WM_CLOSETOOLTIP);
2901 else
2902 wd->wd_ToolTicks = 0;
2907 * Are we locked out?
2909 if (wd->wd_Flags & WDF_LOCKOUT)
2912 * Yes. Reply this message and continue.
2914 ReplyMsg((struct Message *)imsg);
2915 continue;
2919 * Call the hook for the xxxxVERIFY messages
2920 * if one exists.
2922 if (wd->wd_VerifyHook)
2924 if ((wd->wd_VerifyHookBits & imsg->Class) == imsg->Class)
2926 BGUI_CallHookPkt(wd->wd_VerifyHook, (void *)obj, (void *)imsg);
2927 ReplyMsg((struct Message *)imsg);
2928 return rc;
2933 * Call the IDCMPHook when it's available.
2936 if (wd->wd_IDCMPHook && (wd->wd_IDCMPHookBits & imsg->Class))
2938 BGUI_CallHookPkt(wd->wd_IDCMPHook, (VOID *)obj, (VOID *)imsg);
2941 code = imsg->Code;
2943 switch (imsg->Class)
2945 case IDCMP_SIZEVERIFY:
2947 * Save window size and remove
2948 * the master.
2950 wd->wd_OW = w->Width;
2951 wd->wd_OH = w->Height;
2952 if (!(wd->wd_Flags & WDF_REMOVED))
2954 wd->wd_Flags |= WDF_REMOVED;
2955 RemoveGadget(w, (struct Gadget *)wd->wd_Gadgets);
2957 break;
2959 case IDCMP_NEWSIZE:
2960 WW(kprintf("WindowClassIDCMP: received IDCMP_NEWSIZE\n"));
2962 * If we have manually removed the
2963 * master object we adjust the size
2964 * ourselves.
2966 if (wd->wd_Flags & WDF_REMOVED)
2969 * Setup new size for the master.
2971 DoSetMethodNG(wd->wd_Gadgets, GA_Left, w->BorderLeft,
2972 GA_Top, w->BorderTop,
2973 GA_RelWidth, -(w->BorderLeft + w->BorderRight ),
2974 GA_RelHeight, -(w->BorderTop + w->BorderBottom),
2975 TAG_END);
2977 * Put master back online.
2979 AddGadget(w, (struct Gadget *)wd->wd_Gadgets, -1);
2982 * Clear removed flag.
2984 wd->wd_Flags &= ~WDF_REMOVED;
2987 * Only refresh the window when the
2988 * size actually changed.
2993 if ((w->Width != wd->wd_OW) || (w->Height != wd->wd_OH))
2994 RefreshWindowFrame(w);
2996 break;
2998 case IDCMP_MOUSEBUTTONS:
2999 if ((code | IECODE_UP_PREFIX) != SELECTUP)
3002 * Preset GRM_WHICHOBJECT method.
3004 grwo.MethodID = GRM_WHICHOBJECT;
3005 grwo.grwo_Coords.X = imsg->MouseX;
3006 grwo.grwo_Coords.Y = imsg->MouseY;
3008 if (obja = (Object *)AsmDoMethodA(wd->wd_Gadgets, (Msg)&grwo))
3010 Get_Attr(obja, BT_MouseActivation, &mouseact);
3012 if ((mouseact & MOUSEACT_RMB_ACTIVE) && (code == IECODE_RBUTTON)
3013 || (mouseact & MOUSEACT_MMB_ACTIVE) && (code == IECODE_MBUTTON))
3015 SetAttrs(obja, BT_ReportID,
3016 ((mouseact & MOUSEACT_RMB_REPORT) && (code == IECODE_RBUTTON)) ||
3017 ((mouseact & MOUSEACT_MMB_REPORT) && (code == IECODE_MBUTTON)), TAG_DONE);
3019 if (wd->wd_DGMObject)
3021 DoSetMethodNG(wd->wd_DGMObject, DGM_Object, obja, DGM_IntuiMsg, imsg,TAG_END);
3022 ActivateGadget((struct Gadget *)wd->wd_DGMObject, w, NULL);
3027 break;
3029 case IDCMP_MOUSEMOVE:
3030 if (wd->wd_WindowFlags & WFLG_RMBTRAP)
3032 Forbid();
3033 wd->wd_WindowPtr->Flags |= WFLG_RMBTRAP;
3034 Permit();
3036 else
3038 mouseact = 0;
3040 * Preset GRM_WHICHOBJECT method.
3042 grwo.MethodID = GRM_WHICHOBJECT;
3043 grwo.grwo_Coords.X = imsg->MouseX;
3044 grwo.grwo_Coords.Y = imsg->MouseY;
3046 if (obja = (Object *)AsmDoMethodA(wd->wd_Gadgets, (Msg)&grwo))
3048 Get_Attr(obja, BT_MouseActivation, &mouseact);
3051 Forbid();
3052 if (mouseact & MOUSEACT_RMB_ACTIVE)
3054 wd->wd_WindowPtr->Flags |= WFLG_RMBTRAP;
3056 else
3058 wd->wd_WindowPtr->Flags &= ~WFLG_RMBTRAP;
3060 Permit();
3062 break;
3064 case IDCMP_ACTIVEWINDOW:
3065 rc = WMHI_ACTIVE;
3066 break;
3068 case IDCMP_INACTIVEWINDOW:
3069 rc = WMHI_INACTIVE;
3070 break;
3072 case IDCMP_CLOSEWINDOW:
3073 rc = WMHI_CLOSEWINDOW;
3074 break;
3076 case IDCMP_CHANGEWINDOW:
3077 WW(kprintf("WindowClassIDCMP: received IDCMP_CHANGEWINDOW\n"));
3078 if (wd->wd_Flags & WDF_CONSTRAINTS)
3080 WW(kprintf("WindowClassIDCMP: WDF_CONSTRAINTS is set\n"));
3081 WW(kprintf("WindowClassIDCMP: calling WindowLimits(%d,%d,%d,%d)\n",wd->wd_MinW,wd->wd_MinH,wd->wd_MaxW,wd->wd_MaxH));
3082 WindowLimits(w, wd->wd_MinW, wd->wd_MinH, wd->wd_MaxW, wd->wd_MaxH);
3083 wd->wd_Flags &= ~WDF_CONSTRAINTS;
3085 WW(kprintf("WindowClassIDCMP: calling WM_RELEASE\n"));
3086 AsmDoMethod(obj, WM_RELEASE);
3088 WW(kprintf("WindowClassIDCMP: calling WindowClassChange\n"));
3089 WindowClassChange(cl, obj, (Msg)NULL);
3090 break;
3092 case IDCMP_MENUPICK:
3094 * Menu selected?
3096 if (code != MENUNULL)
3098 dragSelect:
3100 * Get the selected item.
3102 mi = ItemAddress(wd->wd_Menus, code);
3105 * Setup the return code ID.
3107 rc = (ULONG)GTMENUITEM_USERDATA(mi);
3110 * Menu a CHECKIT item?
3112 if (mi->Flags & CHECKIT)
3114 * Fix the NewMenu array to represent
3115 * any changes in the CHECKED flag.
3117 AsmDoMethod(obj, WM_CHECKITEM, rc, mi->Flags & CHECKED);
3119 * Set up the next item and say were
3120 * drag-selecting.
3122 if (mi->NextSelect != MENUNULL)
3124 wd->wd_NextSelect = mi->NextSelect;
3125 wd->wd_Flags |= WDF_DRAGSELECT;
3126 break;
3130 * Drag-selecting is done.
3132 wd->wd_Flags &= ~WDF_DRAGSELECT;
3133 break;
3135 case IDCMP_MENUHELP:
3137 * Get the selected item.
3139 mi = ItemAddress(wd->wd_Menus, code);
3142 * Setup the return code ID.
3144 if (mi) rc = WMHI_MENUHELP | (ULONG)GTMENUITEM_USERDATA(mi);
3145 break;
3147 case IDCMP_RAWKEY:
3148 if (code == 0x45)
3151 * Close on ESC?
3153 if (wd->wd_Flags & WDF_CLOSEONESC)
3155 rc = WMHI_CLOSEWINDOW;
3156 break;
3159 if (code == 0x5F)
3162 * HELP!!!!
3164 WindowClassHelp(cl, obj, (Msg)NULL);
3165 break;
3168 * See if this key triggers a gadget activation.
3170 rc = KeyGadget(cl, obj, imsg);
3172 * The KeyGadget() routine has already replied the message for us.
3174 imsg = NULL;
3175 break;
3177 case IDCMP_GADGETUP:
3178 rc = GADGET(imsg->IAddress)->GadgetID;
3179 break;
3181 case IDCMP_IDCMPUPDATE:
3183 * IDCMP_IDCMPUPDATE handles the messages from
3184 * slider, scroller objects and tab-cycling.
3186 attr = (struct TagItem *)imsg->IAddress;
3189 * GA_ID makes sure it's comes from a gadget.
3191 if (tag = FindTagItem(GA_ID, attr))
3194 * Pick up ID.
3196 if (!FindTagItem(STRINGA_TextVal, attr) && !FindTagItem(STRINGA_LongVal, attr))
3197 id = tag->ti_Data;
3198 else
3199 id = WMHI_IGNORE;
3201 if (tabbed = (Object *)GetTagData(STRINGA_Tabbed, NULL, attr))
3203 forward = TRUE;
3205 * Do not notify!
3207 rc = WMHI_IGNORE;
3209 else if (tabbed = (Object *)GetTagData(STRINGA_ShiftTabbed, NULL, attr))
3211 forward = FALSE;
3213 * Do not notify!
3215 rc = WMHI_IGNORE;
3217 else if (tabbed = (Object *)GetTagData(WINDOW_ActNext, NULL, attr))
3219 forward = TRUE;
3221 * Notify.
3223 rc = id;
3225 else if (tabbed = (Object *)GetTagData(WINDOW_ActPrev, NULL, attr))
3227 forward = FALSE;
3229 * Notify.
3231 rc = id;
3235 * String gadget tabbed?
3237 if (tabbed)
3240 * Check if it's in our list.
3242 if (tc = GetCycleNode(wd, tabbed))
3244 nextTabbed:
3245 if (forward)
3248 * Activate next or first object.
3250 if (tc != wd->wd_CycleList.cl_Last) tc = tc->tc_Next;
3251 else tc = wd->wd_CycleList.cl_First;
3253 else
3256 * Activate previous or last object.
3258 if (tc != wd->wd_CycleList.cl_First) tc = tc->tc_Prev;
3259 else tc = wd->wd_CycleList.cl_Last;
3261 Get_Attr(tc->tc_Object, BT_Inhibit, &inhibit);
3262 if ((GADGET(tc->tc_Object)->Flags & GFLG_DISABLED) || inhibit)
3263 goto nextTabbed;
3264 ActivateGadget(GADGET(tc->tc_Object), w, NULL);
3267 else
3270 * Update notification.
3272 UpdateNotification(wd, attr, id);
3274 * Setup return code.
3276 rc = id;
3279 break;
3281 case IDCMP_INTUITICKS:
3282 if ( wd->wd_ToolTip || ( ! wd->wd_ToolTickTime ))
3283 break;
3286 * Pick up mouse coordinates.
3288 x = w->MouseX;
3289 y = w->MouseY;
3292 * Preset GRM_WHICHOBJECT method.
3294 grwo.MethodID = GRM_WHICHOBJECT;
3295 grwo.grwo_Coords.X = x;
3296 grwo.grwo_Coords.Y = y;
3299 * Did the mouse position change?
3301 if (x == wd->wd_ToolX && y == wd->wd_ToolY)
3304 * Tick delay reached?
3306 if (wd->wd_ToolTicks++ == wd->wd_ToolTickTime)
3309 * Find object under the mouse.
3311 if (wd->wd_ToolTipObject = (Object *)AsmDoMethodA(wd->wd_Gadgets, (Msg)&grwo))
3314 * Show the tool tip.
3316 ttc.ttc_Command = TT_SHOW;
3317 ttc.ttc_Object = wd->wd_ToolTipObject;
3318 ttc.ttc_UserData = (APTR)wd;
3320 wd->wd_ToolTip = (APTR)BGUI_CallHookPkt(wd->wd_ToolTipHook ? wd->wd_ToolTipHook : &ToolTipHook,
3321 (void *)obj, (void *)&ttc);
3325 * Clear tip data.
3327 wd->wd_ToolTicks = 0;
3329 } else {
3330 wd->wd_ToolX = x;
3331 wd->wd_ToolY = y;
3333 break;
3337 * Reply the original message.
3339 if (imsg) ReplyMsg((struct Message *)imsg);
3340 if (rc != WMHI_IGNORE) return rc;
3342 return WMHI_NOMORE;
3344 METHOD_END
3346 /// WM_GADGETKEY
3348 * Add a gadget key.
3350 METHOD(WindowClassGadgetKey, struct wmGadgetKey *, wmg)
3352 // WD *wd = INST_DATA(cl, obj);
3353 Object *ob;
3356 * Only add when the object is valid.
3358 if (ob = wmg->wmgk_Object)
3360 DoSetMethodNG(ob, BT_Key, wmg->wmgk_Key, TAG_DONE);
3362 return 1;
3364 METHOD_END
3367 * Find a menu by it's ID.
3369 //STATIC ASM struct Menu *FindMenu( REG(a0) struct Menu *ptr, REG(d0) ULONG id )
3370 STATIC ASM REGFUNC2(struct Menu *, FindMenu,
3371 REGPARAM(A0, struct Menu *, ptr),
3372 REGPARAM(D0, ULONG, id))
3374 struct Menu *tmp;
3376 if ( tmp = ptr ) {
3377 while ( tmp ) {
3378 if ( id == ( ULONG )GTMENU_USERDATA( tmp )) return( tmp );
3379 tmp = tmp->NextMenu;
3383 return( NULL );
3385 REGFUNC_END
3388 * Find a (sub)item by it's ID.
3390 //STATIC ASM struct MenuItem *FindItem( REG(a0) struct Menu *ptr, REG(d0) ULONG id )
3391 STATIC ASM REGFUNC2(struct MenuItem *, FindItem,
3392 REGPARAM(A0, struct Menu *, ptr),
3393 REGPARAM(D0, ULONG, id))
3395 struct Menu *tmp;
3396 struct MenuItem *item, *sub;
3398 if ( tmp = ptr ) {
3399 while ( tmp ) {
3400 if ( item = tmp->FirstItem ) {
3401 while ( item ) {
3402 if ( id == ( ULONG )GTMENUITEM_USERDATA( item )) return( item );
3403 if ( sub = item->SubItem ) {
3404 while ( sub ) {
3405 if ( id == ( ULONG )GTMENUITEM_USERDATA( sub )) return( sub );
3406 sub = sub->NextItem;
3409 item = item->NextItem;
3412 tmp = tmp->NextMenu;
3416 return( NULL );
3418 REGFUNC_END
3421 * Find a NewMenu by it's ID.
3423 //STATIC ASM struct NewMenu *FindNewMenu( REG(a0) struct NewMenu *nm, REG(d0) ULONG id )
3424 STATIC ASM REGFUNC2(struct NewMenu *, FindNewMenu,
3425 REGPARAM(A0, struct NewMenu *, nm),
3426 REGPARAM(D0, ULONG, id))
3428 while ( nm->nm_Type != NM_END ) {
3429 if ( id == ( ULONG )nm->nm_UserData ) return( nm );
3430 nm++;
3433 return( NULL );
3435 REGFUNC_END
3438 * Disable a menu.
3440 //STATIC ASM ULONG WindowClassDisableMenu( REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) struct wmMenuAction *wmma )
3441 STATIC ASM REGFUNC3(ULONG, WindowClassDisableMenu,
3442 REGPARAM(A0, Class *, cl),
3443 REGPARAM(A2, Object *, obj),
3444 REGPARAM(A1, struct wmMenuAction *, wmma))
3446 WD *wd = ( WD * )INST_DATA( cl, obj );
3447 struct Menu *menu;
3448 struct MenuItem *item;
3449 struct NewMenu *newmenu;
3450 ULONG rc = FALSE;
3453 * Is the window open and
3454 * are there menus?
3456 if ( wd->wd_Menus && wd->wd_WindowPtr ) {
3458 * Remove the menus.
3460 ClearMenuStrip( wd->wd_WindowPtr );
3461 if ( menu = FindMenu( wd->wd_Menus, wmma->wmma_MenuID )) {
3463 * Change the menu status.
3465 if ( wmma->wmma_Set ) menu->Flags &= ~MENUENABLED;
3466 else menu->Flags |= MENUENABLED;
3467 } else if ( item = FindItem( wd->wd_Menus, wmma->wmma_MenuID )) {
3469 * Otherwise the (sub)item status.
3471 if ( wmma->wmma_Set ) item->Flags &= ~ITEMENABLED;
3472 else item->Flags |= ITEMENABLED;
3475 * Put the menus back online.
3477 ResetMenuStrip( wd->wd_WindowPtr, wd->wd_Menus );
3481 * Also change the corresponding NewMenu accoordingly.
3483 if ( wd->wd_MenuStrip ) {
3484 if ( newmenu = FindNewMenu( wd->wd_MenuStrip, wmma->wmma_MenuID )) {
3485 rc = TRUE;
3486 if ( newmenu->nm_Type == NM_TITLE ) {
3487 if ( wmma->wmma_Set ) newmenu->nm_Flags |= NM_MENUDISABLED;
3488 else newmenu->nm_Flags &= ~NM_MENUDISABLED;
3489 } else if ( newmenu->nm_Type != NM_END ) {
3490 if ( wmma->wmma_Set ) newmenu->nm_Flags |= NM_ITEMDISABLED;
3491 else newmenu->nm_Flags &= ~NM_ITEMDISABLED;
3496 return( rc );
3498 REGFUNC_END
3501 * (Un)check an item.
3503 //STATIC ASM ULONG WindowClassCheckItem( REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) struct wmMenuAction *wmma )
3504 STATIC ASM REGFUNC3(ULONG, WindowClassCheckItem,
3505 REGPARAM(A0, Class *, cl),
3506 REGPARAM(A2, Object *, obj),
3507 REGPARAM(A1, struct wmMenuAction *, wmma))
3509 WD *wd = ( WD * )INST_DATA( cl, obj );
3510 struct MenuItem *item;
3511 struct NewMenu *newmenu;
3512 ULONG rc = FALSE;
3515 * Is the window open and are there menus?
3517 if ( wd->wd_Menus && wd->wd_WindowPtr ) {
3519 * Remove the menus.
3521 ClearMenuStrip( wd->wd_WindowPtr );
3523 * Find the item and change it's
3524 * CHECKED status.
3526 if ( item = FindItem( wd->wd_Menus, wmma->wmma_MenuID )) {
3527 if ( wmma->wmma_Set ) item->Flags |= CHECKED;
3528 else item->Flags &= ~CHECKED;
3531 * Put the menus back online.
3533 ResetMenuStrip( wd->wd_WindowPtr, wd->wd_Menus );
3537 * Change the corresponding NewMenu accoordingly.
3539 if ( wd->wd_MenuStrip ) {
3540 if ( newmenu = FindNewMenu( wd->wd_MenuStrip, wmma->wmma_MenuID )) {
3541 rc = TRUE;
3542 if ( wmma->wmma_Set ) newmenu->nm_Flags |= CHECKED;
3543 else newmenu->nm_Flags &= ~CHECKED;
3547 return( rc );
3549 REGFUNC_END
3552 * Ask for the disabled status of a menu or (sub)item.
3554 //STATIC ASM ULONG WindowClassMenuDisabled( REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) struct wmMenuQuery *wmmq )
3555 STATIC ASM REGFUNC3(ULONG, WindowClassMenuDisabled,
3556 REGPARAM(A0, Class *, cl),
3557 REGPARAM(A2, Object *, obj),
3558 REGPARAM(A1, struct wmMenuQuery *, wmmq))
3560 struct NewMenu *newmenu;
3561 WD *wd = ( WD * )INST_DATA( cl, obj );
3563 if ( wd->wd_MenuStrip ) {
3564 if ( newmenu = FindNewMenu( wd->wd_MenuStrip, wmmq->wmmq_MenuID )) {
3565 if ( newmenu->nm_Type == NM_TITLE )
3566 return (ULONG)(newmenu->nm_Flags & NM_MENUDISABLED ? 1 : 0);
3567 else if ( newmenu->nm_Type != NM_END )
3568 return (ULONG)(newmenu->nm_Flags & NM_ITEMDISABLED ? 1 : 0);
3572 return ~0;
3574 REGFUNC_END
3577 * Ask for the CHECKED status of a (sub)item.
3579 //STATIC ASM ULONG WindowClassItemChecked( REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) struct wmMenuQuery *wmmq )
3580 STATIC ASM REGFUNC3(ULONG, WindowClassItemChecked,
3581 REGPARAM(A0, Class *, cl),
3582 REGPARAM(A2, Object *, obj),
3583 REGPARAM(A1, struct wmMenuQuery *, wmmq))
3585 struct NewMenu *newmenu;
3586 WD *wd = ( WD * )INST_DATA( cl, obj );
3588 if ( wd->wd_MenuStrip ) {
3589 if ( newmenu = FindNewMenu( wd->wd_MenuStrip, wmmq->wmmq_MenuID ))
3590 return (ULONG)(newmenu->nm_Flags & CHECKED ? 1 : 0);
3593 return ~0;
3595 REGFUNC_END
3598 * Add an objects to the tab-cycle list.
3600 METHOD(WindowClassCycleOrder, struct wmTabCycleOrder *, tco)
3602 WD *wd = INST_DATA( cl, obj );
3603 TABCYCLE *tc;
3604 Object **ob = &tco->wtco_Object1;
3605 ULONG rc = 1;
3608 * Cycle through list of objects.
3610 while (*ob)
3613 * Allocate tab-cycle node.
3615 if (tc = (TABCYCLE *)BGUI_AllocPoolMem(sizeof(TABCYCLE)))
3618 * Initialize structure.
3620 tc->tc_Object = *ob;
3622 * Setup the object for tab-cycling.
3624 DoSetMethodNG( *ob, GA_TabCycle, TRUE, ICA_TARGET, ICTARGET_IDCMP, TAG_END );
3626 * Add it to the list.
3628 AddTail(( struct List * )&wd->wd_CycleList, ( struct Node * )tc );
3629 } else
3630 rc = 0;
3631 ob++;
3633 return rc;
3635 METHOD_END
3636 /// WM_GETAPPMSG
3638 * Obtain an AppMessage.
3640 METHOD(WindowClassGetAppMsg, Msg, msg)
3642 WD *wd = INST_DATA(cl, obj);
3643 ULONG rc = 0;
3646 * Pop a message from the App port.
3648 if (wd->wd_AppPort)
3649 rc = (ULONG)GetMsg(wd->wd_AppPort);
3651 return rc;
3653 METHOD_END
3655 /// WM_ADDUPDATE
3657 * Add a target to the update notification list.
3659 METHOD(WindowClassAddUpdate, struct wmAddUpdate *, wmau)
3661 WD *wd = INST_DATA(cl, obj);
3662 UPN *up;
3663 ULONG rc = 0;
3666 * Valid target?
3668 if (wmau->wmau_Target)
3671 * Allocate node.
3673 if (up = (UPN *)BGUI_AllocPoolMem(sizeof(UPN)))
3676 * Initialize node.
3678 up->up_ID = wmau->wmau_SourceID;
3679 up->up_Target = wmau->wmau_Target;
3680 up->up_MapList = wmau->wmau_MapList;
3682 * Add it to the list.
3684 AddTail((struct List *)&wd->wd_UpdateList, (struct Node *)up);
3685 rc = 1;
3688 return rc;
3690 METHOD_END
3692 /// WM_REPORT_ID
3694 * Report an ID.
3696 * Changes made by T.Herold: Passes task to AddIDReport
3698 METHOD(WindowClassReportID, struct wmReportID *, wmri)
3700 WD *wd = INST_DATA(cl, obj);
3701 ULONG rc = 0;
3702 struct Task *task;
3703 struct Window *w;
3705 * Get task to signal.
3707 if (wmri->wmri_Flags & WMRIF_TASK)
3708 task = wmri->wmri_SigTask;
3709 else
3710 task = wd->wd_UserPort->mp_SigTask;
3713 * Add ID node.
3715 if (w = wd->wd_WindowPtr)
3717 rc = AddIDReport(w, wmri->wmri_ID, task);
3719 * Double-click?
3721 if (wmri->wmri_Flags & WMRIF_DOUBLE_CLICK)
3723 rc = AddIDReport(w, wmri->wmri_ID, task);
3726 * Set signal.
3728 if (task) Signal(task, (1 << wd->wd_UserPort->mp_SigBit));
3730 return rc;
3732 METHOD_END
3735 * Get a pointer to the window that signalled us.
3737 METHOD(WindowClassGetSigWin, Msg, msg )
3739 WD *wd = ( WD * )INST_DATA( cl, obj );
3740 struct Window *win;
3743 * Shared message port?
3745 if ( wd->wd_Flags & WDF_SHARED_MSGPORT ) {
3747 * Any messages at the port?
3749 if ( wd->wd_UserPort->mp_MsgList.lh_Head->ln_Succ )
3751 * Yes. Get the first.
3753 win = (( struct IntuiMessage * )wd->wd_UserPort->mp_MsgList.lh_Head )->IDCMPWindow;
3754 else
3756 * Try for the first reported ID.
3758 win = GetFirstIDReportWindow();
3759 } else
3761 * This window.
3763 win = wd->wd_WindowPtr;
3765 return(( ULONG )win );
3767 METHOD_END
3770 * Remove an object from the tab-cycle list.
3772 METHOD(WindowClassRemove, struct wmRemoveObject *, wmro )
3774 WD *wd = ( WD * )INST_DATA( cl, obj );
3775 TABCYCLE *cyc;
3777 if ( wmro->wmro_Object ) {
3778 if ( wmro->wmro_Flags & WMROF_CYCLE_LIST ) {
3779 if ( cyc = GetCycleNode( wd, wmro->wmro_Object )) {
3780 Remove(( struct Node * )cyc );
3781 BGUI_FreePoolMem( cyc );
3784 return( TRUE );
3786 return( FALSE );
3788 METHOD_END
3790 /// WM_SECURE
3792 * Secure the master gadget by removing it.
3794 METHOD(WindowClassSecure, Msg, msg)
3796 WD *wd = INST_DATA(cl, obj);
3797 ULONG rc = 0;
3798 struct Window *w;
3801 * Window Open?
3803 if (w = wd->wd_WindowPtr)
3806 * Yes. Master gadget attached?
3808 if (!(wd->wd_Flags & WDF_REMOVED))
3811 * No. Remove it now.
3813 wd->wd_Flags |= WDF_REMOVED;
3814 RemoveGadget(w, (struct Gadget *)wd->wd_Gadgets);
3816 rc = 1;
3818 return rc;
3820 METHOD_END
3822 /// WM_RELEASE
3824 * Release the master gadget by adding it.
3826 METHOD(WindowClassRelease, Msg, msg)
3828 WD *wd = INST_DATA(cl, obj);
3829 ULONG rc = 0;
3830 struct Window *w;
3832 WW(kprintf("WindowClassRelease:\n"));
3835 * Window Open?
3837 if (w = wd->wd_WindowPtr)
3839 WW(kprintf("WindowClassRelease: window is open\n"));
3841 * Yes. Master gadget removed?
3843 if (wd->wd_Flags & WDF_REMOVED)
3845 WW(kprintf("WindowClassRelease: WDF_REMOVED set = master gadget was removed. Calling AddGadget\n"));
3847 * Put the master back on-line.
3849 AddGadget(w, (struct Gadget *)wd->wd_Gadgets, -1);
3850 WW(kprintf("WindowClassRelease: clearing WDF_REMOVED flag\n"));
3852 wd->wd_Flags &= ~WDF_REMOVED;
3855 WW(kprintf("WindowClassRelease: calling RefreshGList: gad = %x\n", (struct Gadget *)wd->wd_Gadgets));
3857 #warning temp AROS fix to fix refresh problem after an automatic window-resize done by BGUI
3858 #ifdef __AROS__
3859 RefreshGList((struct Gadget *)wd->wd_Gadgets, w, 0, 1);
3860 #endif
3862 rc = 1;
3864 return rc;
3866 METHOD_END
3868 /// WM_RELAYOUT
3870 * Relayout the GUI.
3872 METHOD(WindowClassRelayout, Msg, msg)
3874 WD *wd = INST_DATA(cl, obj);
3875 WORD newl, newt, neww, newh;
3876 UWORD min_x, min_y, max_x, max_y;
3877 BOOL lock_w = wd->wd_Flags & WDF_LOCK_WIDTH;
3878 BOOL lock_h = wd->wd_Flags & WDF_LOCK_HEIGHT;
3879 struct Window *w;
3880 struct Screen *s = wd->wd_Screen;
3882 WW(kprintf("** WindowClassRelayout\n"));
3884 * Window open?
3886 if (w = wd->wd_WindowPtr)
3888 WW(kprintf("** WindowClassRelayout: window is open. calling WM_SECURE\n"));
3889 AsmDoMethod(obj, WM_SECURE);
3890 WW(kprintf("** WindowClassRelayout: calling WinSize\n"));
3892 if (!WinSize(wd, &min_x, &min_y))
3894 AsmDoMethod(obj, WM_RELEASE);
3895 return 0;
3897 WW(kprintf("** WindowClassRelayout: WinSize call ok min_x = %d, min_y = %d\n", min_x, min_y));
3900 * Pick up old minimum width and height.
3902 max_x = w->MaxWidth;
3903 max_y = w->MaxHeight;
3905 if (!(wd->wd_WindowFlags & WFLG_BACKDROP))
3908 * Default window position/size.
3910 newl = w->LeftEdge;
3911 newt = w->TopEdge;
3912 neww = w->Width;
3913 newh = w->Height;
3915 if (lock_w || (min_x > neww)) neww = min_x;
3916 if (lock_h || (min_y > newh)) newh = min_y;
3919 * Find out how much we have to
3920 * move the window.
3922 if ((newl + neww) > s->Width) newl = s->Width - neww;
3923 if ((newt + newh) > s->Height) newt = s->Height - newh;
3926 * Compute the new maximum values.
3928 if (neww > max_x) max_x = neww;
3929 if (newh > max_y) max_y = newh;
3932 * Re-size the window accoording to the master
3933 * minimum size change.
3936 WindowLimits(w, 1, 1, -1, -1);
3938 WW(kprintf("** WindowClassRelayout: Calling ChangeWindowBox(%d,%d,%d,%d)\n",newl,newt,neww,newh));
3940 ChangeWindowBox(w, newl, newt, neww, newh);
3942 wd->wd_MinW = lock_w ? neww : min_x;
3943 wd->wd_MinH = lock_h ? newh : min_y;
3944 wd->wd_MaxW = lock_w ? neww : max_x;
3945 wd->wd_MaxH = lock_h ? newh : max_y;
3946 WW(kprintf("** WindowClassRelayout: setting wd->wd_MinW/H to %d,%d wd->wd_MaxW/H to %d,%d\n",
3947 wd->wd_MinW,
3948 wd->wd_MinH,
3949 wd->wd_MaxW,
3950 wd->wd_MaxH));
3952 wd->wd_Flags |= WDF_CONSTRAINTS;
3954 else
3956 AsmDoMethod(obj, WM_RELEASE);
3959 return 1;
3961 METHOD_END
3963 /// WM_WHICHOBJECT
3965 * Find the object under the mouse.
3967 METHOD(WindowClassWhichObject, Msg, msg)
3969 WD *wd = INST_DATA(cl, obj);
3970 ULONG rc = 0;
3971 struct Window *w;
3972 WORD mx, my;
3975 * Window Open?
3977 if (w = wd->wd_WindowPtr)
3980 * Pickup mouse coords.
3982 mx = w->MouseX;
3983 my = w->MouseY;
3986 * On the window?
3988 if ((mx >= 0) && (my >= 0) && (mx < w->Width) && (my < w->Height))
3990 * Let's see what the master returns to us.
3993 #ifdef __AROS__
3994 rc = AsmDoMethod(wd->wd_Gadgets, GRM_WHICHOBJECT, mx, my);
3995 #else
3996 rc = AsmDoMethod(wd->wd_Gadgets, GRM_WHICHOBJECT, (mx << 16) | my);
3997 #endif
3999 return rc;
4001 METHOD_END
4003 /// WM_LOCK, WM_UNLOCK
4005 METHOD(WindowClassLock, Msg, msg)
4007 WD *wd = INST_DATA(cl, obj);
4010 * Lock or unlock?
4012 if (msg->MethodID == WM_LOCK) wd->wd_Flags |= WDF_LOCKOUT;
4013 else wd->wd_Flags &= ~WDF_LOCKOUT;
4015 return 1;
4017 METHOD_END
4019 /// BASE_FINDKEY
4021 * Which object has the proper key?
4023 METHOD(WindowClassFindKey, struct bmFindKey *, bmfk)
4025 WD *wd = INST_DATA(cl, obj);
4026 Object *ob, *gr;
4028 if (gr = wd->wd_Gadgets)
4030 if (ob = (Object *)AsmDoMethodA(gr, (Msg)bmfk))
4031 return (ULONG)ob;
4033 if (gr = wd->wd_LBorder)
4035 if (ob = (Object *)AsmDoMethodA(gr, (Msg)bmfk))
4036 return (ULONG)ob;
4038 if (gr = wd->wd_RBorder)
4040 if (ob = (Object *)AsmDoMethodA(gr, (Msg)bmfk))
4041 return (ULONG)ob;
4043 if (gr = wd->wd_TBorder)
4045 if (ob = (Object *)AsmDoMethodA(gr, (Msg)bmfk))
4046 return (ULONG)ob;
4048 if (gr = wd->wd_BBorder)
4050 if (ob = (Object *)AsmDoMethodA(gr, (Msg)bmfk))
4051 return (ULONG)ob;
4053 return NULL;
4055 METHOD_END
4057 /// BASE_KEYLABEL
4059 * Attach label keys to object.
4061 METHOD(WindowClassKeyLabel, struct bmKeyLabel *, bmkl)
4063 WD *wd = INST_DATA(cl, obj);
4064 Object *gr;
4066 if (gr = wd->wd_Gadgets) AsmDoMethodA(gr, (Msg)bmkl);
4067 if (gr = wd->wd_LBorder) AsmDoMethodA(gr, (Msg)bmkl);
4068 if (gr = wd->wd_RBorder) AsmDoMethodA(gr, (Msg)bmkl);
4069 if (gr = wd->wd_TBorder) AsmDoMethodA(gr, (Msg)bmkl);
4070 if (gr = wd->wd_BBorder) AsmDoMethodA(gr, (Msg)bmkl);
4072 return NULL;
4074 METHOD_END
4076 /// BASE_LOCALIZE
4078 * Localize window.
4080 METHOD(WindowClassLocalize, struct bmLocalize *, bml)
4082 WD *wd = INST_DATA(cl, obj);
4083 Object *gr;
4085 if (gr = wd->wd_Gadgets) AsmDoMethodA(gr, (Msg)bml);
4086 if (gr = wd->wd_LBorder) AsmDoMethodA(gr, (Msg)bml);
4087 if (gr = wd->wd_RBorder) AsmDoMethodA(gr, (Msg)bml);
4088 if (gr = wd->wd_TBorder) AsmDoMethodA(gr, (Msg)bml);
4089 if (gr = wd->wd_BBorder) AsmDoMethodA(gr, (Msg)bml);
4091 if (wd->wd_WindowTitleID) wd->wd_WindowTitle =
4092 BGUI_GetCatalogStr(bml->bml_Locale, wd->wd_WindowTitleID, wd->wd_WindowTitle);
4094 if (wd->wd_ScreenTitleID) wd->wd_ScreenTitle =
4095 BGUI_GetCatalogStr(bml->bml_Locale, wd->wd_ScreenTitleID, wd->wd_ScreenTitle);
4097 if (wd->wd_HelpTextID) wd->wd_HelpText =
4098 BGUI_GetCatalogStr(bml->bml_Locale, wd->wd_HelpTextID, wd->wd_HelpText);
4100 return NULL;
4102 METHOD_END
4104 /// WM_CLIP
4106 * Turn on or off buffer layering.
4108 METHOD(WindowClassClip, struct wmClip *, wmc)
4110 WD *wd = INST_DATA(cl, obj);
4111 struct RastPort *br = wd->wd_BufferRP;
4112 struct Rectangle *cr = wmc->wmc_Rectangle;
4113 struct Region *r = wd->wd_Region;
4114 struct Layer *wl;
4115 ULONG rc = 0;
4117 if (wd->wd_WindowPtr && (wl = wd->wd_WindowPtr->RPort->Layer))
4119 InstallClipRegion(wl, NULL);
4121 switch (wmc->wmc_Action)
4123 case CLIPACTION_NONE:
4124 if (br && br->Layer)
4126 wd->wd_BufferLayer = br->Layer;
4127 br->Layer = NULL;
4129 return 1;
4130 case CLIPACTION_CLEAR:
4131 ClearRegion(r);
4132 rc = 1;
4133 break;
4134 case CLIPACTION_OR:
4135 rc = OrRectRegion(r, cr);
4136 break;
4137 case CLIPACTION_AND:
4138 AndRectRegion(r, cr);
4139 rc = 1;
4140 break;
4143 if (rc)
4145 InstallClipRegion(wl, r);
4147 if (br)
4149 if (!br->Layer) br->Layer = wd->wd_BufferLayer;
4150 InstallClipRegion(br->Layer, r);
4154 return rc;
4156 METHOD_END
4158 METHOD(WindowClassSetupGadget, struct wmSetupGadget *, wmsg)
4160 WD *wd = INST_DATA(cl, obj);
4161 struct TagItem *tstate = wmsg->wmsg_Tags, *tag;
4163 while (tag = NextTagItem(&tstate))
4165 switch(tag->ti_Tag)
4167 case BT_Inhibit:
4168 AsmDoMethod(wmsg->wmsg_Object, BASE_INHIBIT, tag->ti_Tag);
4169 break;
4173 if(wd->wd_UsedFont
4174 || ((wd->wd_Flags & WDF_AUTOASPECT)
4175 && wd->wd_DrawInfo))
4177 struct TextAttr current_font;
4179 if(wd->wd_UsedFont)
4181 struct RastPort rp;
4183 InitRastPort(&rp);
4184 SetFont(&rp,wd->wd_UsedFont);
4185 AskFont(&rp,&current_font);
4188 SetAttrs(wmsg->wmsg_Object,
4189 wd->wd_UsedFont ? BT_TextAttr : TAG_IGNORE,&current_font,
4190 ((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),
4191 TAG_END);
4193 return(1);
4195 METHOD_END
4198 /// Class initialization.
4201 * Class function table.
4203 STATIC DPFUNC ClassFunc[] = {
4204 OM_NEW, (FUNCPTR)WindowClassNew,
4205 OM_SET, (FUNCPTR)WindowClassSetUpdate,
4206 OM_UPDATE, (FUNCPTR)WindowClassSetUpdate,
4207 OM_GET, (FUNCPTR)WindowClassGet,
4208 OM_DISPOSE, (FUNCPTR)WindowClassDispose,
4209 WM_OPEN, (FUNCPTR)WindowClassOpen,
4210 WM_CLOSE, (FUNCPTR)WindowClassClose,
4211 WM_SLEEP, (FUNCPTR)WindowClassSleep,
4212 WM_WAKEUP, (FUNCPTR)WindowClassWakeUp,
4213 WM_HANDLEIDCMP, (FUNCPTR)WindowClassIDCMP,
4214 WM_GADGETKEY, (FUNCPTR)WindowClassGadgetKey,
4215 WM_DISABLEMENU, (FUNCPTR)WindowClassDisableMenu,
4216 WM_CHECKITEM, (FUNCPTR)WindowClassCheckItem,
4217 WM_MENUDISABLED, (FUNCPTR)WindowClassMenuDisabled,
4218 WM_ITEMCHECKED, (FUNCPTR)WindowClassItemChecked,
4219 WM_TABCYCLE_ORDER, (FUNCPTR)WindowClassCycleOrder,
4220 WM_GETAPPMSG, (FUNCPTR)WindowClassGetAppMsg,
4221 WM_ADDUPDATE, (FUNCPTR)WindowClassAddUpdate,
4222 WM_REPORT_ID, (FUNCPTR)WindowClassReportID,
4223 WM_GET_SIGNAL_WINDOW, (FUNCPTR)WindowClassGetSigWin,
4224 WM_REMOVE_OBJECT, (FUNCPTR)WindowClassRemove,
4226 WM_SECURE, (FUNCPTR)WindowClassSecure,
4227 WM_RELEASE, (FUNCPTR)WindowClassRelease,
4228 WM_RELAYOUT, (FUNCPTR)WindowClassRelayout,
4229 WM_WHICHOBJECT, (FUNCPTR)WindowClassWhichObject,
4230 WM_LOCK, (FUNCPTR)WindowClassLock,
4231 WM_UNLOCK, (FUNCPTR)WindowClassLock,
4232 WM_CLOSETOOLTIP, (FUNCPTR)WindowClassCloseTT,
4233 WM_CLIP, (FUNCPTR)WindowClassClip,
4234 WM_SETUPGADGET, (FUNCPTR)WindowClassSetupGadget,
4236 BASE_FINDKEY, (FUNCPTR)WindowClassFindKey,
4237 BASE_KEYLABEL, (FUNCPTR)WindowClassKeyLabel,
4238 BASE_LOCALIZE, (FUNCPTR)WindowClassLocalize,
4240 DF_END, NULL
4244 * Simple class initialization.
4246 makeproto Class *InitWindowClass(void)
4248 return WindowClass = BGUI_MakeClass(CLASS_SuperClassBGUI, BGUI_ROOT_OBJECT,
4249 CLASS_ObjectSize, sizeof(WD),
4250 CLASS_DFTable, ClassFunc,
4251 TAG_DONE);