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.
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
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
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
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
115 * Revision 1.1 1998/02/25 17:10:06 mlemos
123 #include "include/classdefs.h"
128 typedef struct TabCycle
{
129 struct TabCycle
*tc_Next
;
130 struct TabCycle
*tc_Prev
;
136 TABCYCLE
*cl_EndMark
;
141 * Update notification.
143 typedef struct UpdateN
{
144 struct UpdateN
*up_Next
;
145 struct UpdateN
*up_Prev
;
148 struct TagItem
*up_MapList
;
158 * Object instance data.
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. */
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 */
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. */
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
},
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
},
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
;
312 * Count the number of NewMenu
313 * structure in the array.
315 while (ptr
->nm_Type
!= NM_END
)
322 * Include the NM_END.
327 * Allocate a private copy.
329 if (( wd
->wd_MenuStrip
= ( struct NewMenu
* )BGUI_AllocPoolMem( num
* sizeof( struct NewMenu
)))) {
333 CopyMem(( void * )array
, ( void * )wd
->wd_MenuStrip
, num
* sizeof( struct NewMenu
));
340 * Find out the minumum dimensions.
342 STATIC IPTR
GroupDimensions(WD
*wd
, Object
*master
, struct TextAttr
*font
, UWORD
*minw
, UWORD
*minh
)
344 struct TextFont
*tf
= NULL
;
347 struct GadgetInfo gi
;
350 * Initialize the RastPort.
359 if ((tf
= BGUI_OpenFont(font
))) FSetFont(&rp
, tf
);
362 DoSetMethodNG(master
, BT_TextAttr
, font
, TAG_END
);
368 * Setup fake GadgetInfo (used for the DrawInfo).
370 bzero(&gi
, sizeof(gi
));
371 gi
.gi_RastPort
= &rp
;
372 gi
.gi_Screen
= wd
->wd_Screen
;
373 gi
.gi_DrInfo
= wd
->wd_DrawInfo
;
374 gi
.gi_Pens
.DetailPen
= wd
->wd_DrawInfo
->dri_Pens
[DETAILPEN
];
375 gi
.gi_Pens
.BlockPen
= wd
->wd_DrawInfo
->dri_Pens
[BLOCKPEN
];
380 rc
= AsmDoMethod(master
, GRM_DIMENSIONS
, &gi
, &rp
, minw
, minh
, 0);
384 * Close font when opened.
386 if (tf
) BGUI_CloseFont(tf
);
393 * Back-filling hook. This hook makes sure that the window background is
394 * always BACKGROUNDPEN. The hook will only fill the areas that have grown
395 * because of a re-size and the right and bottom border of the window in it's
396 * previous position if the size has grown.
398 //STATIC SAVEDS ASM VOID BackFill_func(REG(a0) struct Hook *hook, REG(a2) struct RastPort *rp, REG(a1) BFINFO *info)
399 STATIC SAVEDS ASM
REGFUNC3(VOID
, BackFill_func
,
400 REGPARAM(A0
, struct Hook
*, hook
),
401 REGPARAM(A2
, struct RastPort
*, rp
),
402 REGPARAM(A1
, BFINFO
*, info
))
404 struct Layer
*save_layer
;
405 struct Window
*w
= NULL
;
409 * Do not disturb the previous window contents. When the area to fill is located in the previous GUI area
410 * we do not back fill. This makes sure the previous GUI remains visible until it is overwritten by the
413 if (info
->bf_Layer
) w
= info
->bf_Layer
->Window
;
415 if (!w
|| (info
->bf_X
> w
->BorderLeft
) || (info
->bf_Y
> w
->BorderTop
))
420 save_layer
= rp
->Layer
;
424 if ((bi
= AllocBaseInfoDebug(__FILE__
,__LINE__
,BI_RastPort
, rp
, TAG_DONE
)))
426 if ((bi
= AllocBaseInfo(BI_RastPort
, rp
, TAG_DONE
)))
430 * Setup the rastport.
433 BSetDPenA(bi
, BACKGROUNDPEN
);
438 BRectFillA(bi
, &info
->bf_Rect
);
442 rp
->Layer
= save_layer
;
449 STATIC
struct Hook BackFill_hook
= { {NULL
, NULL
}, (HOOKFUNC
)BackFill_func
, NULL
, NULL
};
454 STATIC
METHOD(WindowClassSetUpdate
, struct opSet
*, ops
)
456 WD
*wd
= INST_DATA(cl
, obj
);
457 struct TagItem
*tstate
= ops
->ops_AttrList
;
459 struct Window
*w
= wd
->wd_WindowPtr
;
465 while ((tag
= NextTagItem(&tstate
)))
472 if (!w
) wd
->wd_Screen
= (struct Screen
*)data
;
475 case WINDOW_PubScreen
:
476 if (!w
) wd
->wd_PubScreen
= (struct Screen
*)data
;
479 case WINDOW_PubScreenName
:
480 if (!w
) wd
->wd_PubScreenName
= (UBYTE
*)data
;
484 if (wd
->wd_Locale
&& (wd
->wd_Flags
& WDF_FREELOCALE
))
486 CloseLocale(wd
->wd_Locale
->bl_Locale
);
487 CloseCatalog(wd
->wd_Locale
->bl_Catalog
);
488 BGUI_FreePoolMem(wd
->wd_Locale
);
490 wd
->wd_Catalog
= NULL
;
491 wd
->wd_Locale
= (struct bguiLocale
*)data
;
492 wd
->wd_Flags
&= ~WDF_FREELOCALE
;
496 if (LocaleBase
== NULL
) break;
498 if (wd
->wd_Locale
&& wd
->wd_Catalog
)
500 CloseLocale(wd
->wd_Locale
->bl_Locale
);
501 CloseCatalog(wd
->wd_Locale
->bl_Catalog
);
504 BGUI_FreePoolMem(wd
->wd_Locale
);
505 wd
->wd_Locale
= NULL
;
506 wd
->wd_Catalog
= NULL
;
512 if((wd
->wd_Locale
= BGUI_AllocPoolMem(sizeof(struct bguiLocale
))))
513 memset(wd
->wd_Locale
,0,sizeof(struct bguiLocale
));
514 wd
->wd_Flags
|= WDF_FREELOCALE
;
518 wd
->wd_Catalog
= (UBYTE
*)data
;
519 wd
->wd_Locale
->bl_Locale
= OpenLocale(NULL
);
520 wd
->wd_Locale
->bl_Catalog
= OpenCatalogA(NULL
, wd
->wd_Catalog
, NULL
);
525 wd
->wd_WindowTitle
= (UBYTE
*)data
;
526 if (w
&& !(wd
->wd_Flags
& WFLG_BORDERLESS
))
528 SetWindowTitles(w
, wd
->wd_WindowTitle
, (UBYTE
*)~0);
530 * Notify the target when necessary.
532 DoNotifyMethod(obj
, NULL
, 0, tag
->ti_Tag
, data
, TAG_END
);
536 case WINDOW_ScreenTitle
:
537 wd
->wd_ScreenTitle
= (UBYTE
*)data
;
540 SetWindowTitles(w
, (UBYTE
*)~0, wd
->wd_ScreenTitle
);
542 * Notify the target when necessary.
544 DoNotifyMethod(obj
, NULL
, 0, tag
->ti_Tag
, data
, TAG_END
);
548 case WINDOW_ToolTicks
:
549 wd
->wd_ToolTickTime
= data
;
550 wd
->wd_ToolTicks
= 0;
552 if (wd
->wd_ToolTickTime
) wd
->wd_IDCMPFlags
|= IDCMP_INTUITICKS
;
555 if (!(wd
->wd_Flags
& WDF_USERTICKS
))
556 wd
->wd_IDCMPFlags
&= ~IDCMP_INTUITICKS
;
558 if (w
) ModifyIDCMP(w
, wd
->wd_IDCMPFlags
);
566 ChangeWindowBox(w
, IBOX(data
)->Left
, IBOX(data
)->Top
,
567 IBOX(data
)->Width
, IBOX(data
)->Height
);
571 wd
->wd_FixedPos
= *IBOX(data
);
572 wd
->wd_Flags
|= WDF_CHANGE_VALID
;
576 wd
->wd_Flags
&= ~WDF_CHANGE_VALID
;
579 case WINDOW_CloseOnEsc
:
580 if (data
) wd
->wd_Flags
|= WDF_CLOSEONESC
;
581 else wd
->wd_Flags
&= ~WDF_CLOSEONESC
;
584 case WINDOW_NoVerify
:
587 if (data
) ModifyIDCMP(w
, wd
->wd_IDCMPFlags
& ~IDCMP_SIZEVERIFY
);
588 else ModifyIDCMP(w
, wd
->wd_IDCMPFlags
);
592 case WINDOW_MenuFont
:
593 wd
->wd_MenuFont
= (struct TextAttr
*)data
;
594 if (w
&& wd
->wd_Menus
)
597 if ((!wd
->wd_MenuFont
) || (!LayoutMenus(wd
->wd_Menus
, wd
->wd_VisualInfo
,
598 GTMN_NewLookMenus
, TRUE
, GTMN_TextAttr
, wd
->wd_MenuFont
, TAG_DONE
)))
600 LayoutMenus(wd
->wd_Menus
, wd
->wd_VisualInfo
, GTMN_NewLookMenus
, TRUE
, TAG_END
);
602 SetMenuStrip(w
, wd
->wd_Menus
);
606 case WINDOW_SharedPort
:
609 if ((wd
->wd_UserPort
= (struct MsgPort
*)data
))
610 wd
->wd_Flags
|= WDF_SHARED_MSGPORT
;
612 wd
->wd_Flags
&= ~WDF_SHARED_MSGPORT
;
619 wd
->wd_WindowTitleID
= data
;
622 case WINDOW_ScreenTitleID
:
623 wd
->wd_ScreenTitleID
= data
;
626 case WINDOW_HelpFile
:
627 wd
->wd_HelpFile
= (UBYTE
*)data
;
630 case WINDOW_HelpNode
:
631 wd
->wd_HelpNode
= (UBYTE
*)data
;
634 case WINDOW_HelpLine
:
635 wd
->wd_HelpLine
= data
;
638 case WINDOW_HelpText
:
639 wd
->wd_HelpText
= (UBYTE
*)data
;
642 case WINDOW_HelpTextID
:
643 wd
->wd_HelpTextID
= data
;
646 case WINDOW_IDCMPHook
:
647 wd
->wd_IDCMPHook
= (struct Hook
*)data
;
650 case WINDOW_VerifyHook
:
651 wd
->wd_VerifyHook
= (struct Hook
*)data
;
654 case WINDOW_IDCMPHookBits
:
655 wd
->wd_IDCMPHookBits
= data
;
658 case WINDOW_VerifyHookBits
:
659 wd
->wd_VerifyHookBits
= data
;
662 case WINDOW_Position
:
663 wd
->wd_Position
= data
;
666 case WINDOW_ScaleWidth
:
667 wd
->wd_WidthScale
= data
;
670 case WINDOW_ScaleHeight
:
671 wd
->wd_HeightScale
= data
;
675 wd
->wd_Font
= (struct TextAttr
*)data
;
678 case WINDOW_FallBackFont
:
679 wd
->wd_FallBackFont
= (struct TextAttr
*)data
;
682 case WINDOW_UniqueID
:
693 * Create a shiny new object.
695 STATIC
METHOD(WindowClassNew
, struct opSet
*, ops
)
701 struct TagItem
*tstate
;
702 struct TagItem
*tag
, *tags
;
705 Object
*master
, *lborder
, *tborder
, *rborder
, *bborder
;
707 tags
= DefTagList(BGUI_WINDOW_OBJECT
, ops
->ops_AttrList
);
709 master
= (Object
*)GetTagData(WINDOW_MasterGroup
, 0, tags
);
710 lborder
= (Object
*)GetTagData(WINDOW_LBorderGroup
, 0, tags
);
711 tborder
= (Object
*)GetTagData(WINDOW_TBorderGroup
, 0, tags
);
712 rborder
= (Object
*)GetTagData(WINDOW_RBorderGroup
, 0, tags
);
713 bborder
= (Object
*)GetTagData(WINDOW_BBorderGroup
, 0, tags
);
716 * For now we do not work without a master group.
720 * First we let the superclass setup an object.
722 if (master
&& (rc
= NewSuperObject(cl
, obj
, tags
)))
725 * Get the instance data.
727 wd
= INST_DATA(cl
, rc
);
729 wd
->wd_Gadgets
= master
;
730 wd
->wd_LBorder
= lborder
;
731 wd
->wd_TBorder
= tborder
;
732 wd
->wd_RBorder
= rborder
;
733 wd
->wd_BBorder
= bborder
;
735 wd
->wd_DGMObject
= BGUI_NewObjectA(BGUI_DGM_OBJECT
, NULL
);
736 wd
->wd_Region
= NewRegion();
739 * Initialize cycle/update lists.
741 NewList((struct List
*)&wd
->wd_CycleList
);
742 NewList((struct List
*)&wd
->wd_UpdateList
);
747 wd
->wd_Position
= POS_CENTERSCREEN
;
748 wd
->wd_FallBackFont
= &Topaz80
;
749 wd
->wd_ToolX
= wd
->wd_ToolY
= -1;
750 wd
->wd_Zoom
[0] = wd
->wd_Zoom
[1] = -1;
753 * Pack user boolean tags with predefined defaults.
755 wd
->wd_WindowFlags
= PackBoolTags(WFLG_DRAGBAR
| WFLG_SIZEGADGET
| WFLG_CLOSEGADGET
| WFLG_DEPTHGADGET
|
756 WFLG_ACTIVATE
| WFLG_NOCAREREFRESH
| WFLG_SIZEBBOTTOM
| WFLG_REPORTMOUSE
|
757 WFLG_NEWLOOKMENUS
, tags
, boolTags1
);
762 if (!GetTagData(WINDOW_SmartRefresh
, FALSE
, tags
)) wd
->wd_WindowFlags
|= WFLG_SIMPLE_REFRESH
;
764 idcmp
= IDCMP_RAWKEY
|IDCMP_GADGETUP
|IDCMP_CHANGEWINDOW
|IDCMP_INACTIVEWINDOW
|IDCMP_ACTIVEWINDOW
|
765 IDCMP_IDCMPUPDATE
|IDCMP_SIZEVERIFY
|IDCMP_NEWSIZE
|IDCMP_MOUSEMOVE
|IDCMP_MOUSEBUTTONS
|IDCMP_MENUHELP
;
768 * Obtain all necessary window data.
771 while ((tag
= NextTagItem(&tstate
)))
777 case WINDOW_MenuStrip
:
778 if (!wd
->wd_MenuStrip
)
780 if (!CopyNewMenuArray(wd
, (struct NewMenu
*)data
)) fail
= TRUE
;
785 wd
->wd_IDCMPFlags
= data
;
786 if (data
& IDCMP_INTUITICKS
) wd
->wd_Flags
|= WDF_USERTICKS
;
789 case WINDOW_PosRelBox
:
790 wd
->wd_RelPos
= *IBOX(data
);
791 wd
->wd_Flags
|= WDF_RELBOX
;
795 AsmCoerceMethod(cl
, (Object
*)rc
, OM_SET
, tags
, NULL
);
800 * Disable all system gadgets and bordergroups when this
801 * is a backdrop or borderless window.
803 if (wd
->wd_WindowFlags
& (WFLG_BORDERLESS
|WFLG_BACKDROP
))
805 wd
->wd_WindowFlags
&= ~(WFLG_SIZEGADGET
|WFLG_DEPTHGADGET
|WFLG_CLOSEGADGET
|WFLG_DRAGBAR
);
806 wd
->wd_WindowFlags
|= WFLG_BORDERLESS
;
807 wd
->wd_WindowTitle
= NULL
;
811 * Pickup the other boolean tags.
813 wd
->wd_Flags
= PackBoolTags(wd
->wd_Flags
, tags
, boolTags
);
816 * Pack some IDCMP flags.
818 if (wd
->wd_WindowFlags
& WFLG_CLOSEGADGET
) idcmp
|= IDCMP_CLOSEWINDOW
;
819 if (wd
->wd_MenuStrip
) idcmp
|= IDCMP_MENUPICK
;
821 wd
->wd_IDCMPFlags
|= idcmp
;
823 if (wd
->wd_Locale
) AsmDoMethod((Object
*)rc
, BASE_LOCALIZE
, wd
->wd_Locale
);
824 if (wd
->wd_Flags
& WDF_AUTOKEYLABEL
) AsmDoMethod((Object
*)rc
, BASE_KEYLABEL
);
826 DoSetMethodNG(wd
->wd_Gadgets
, GROUP_IsMaster
, TRUE
, BT_Buffer
, TRUE
, TAG_DONE
);
828 DoMultiSet(BT_ParentWindow
, rc
, 5, master
, lborder
, tborder
, rborder
, bborder
);
830 if (lborder
) DoSetMethodNG(lborder
, GA_LeftBorder
, TRUE
, TAG_DONE
);
831 if (rborder
) DoSetMethodNG(rborder
, GA_RightBorder
, TRUE
, TAG_DONE
);
832 if (tborder
) DoSetMethodNG(tborder
, GA_TopBorder
, TRUE
, TAG_DONE
);
833 if (bborder
) DoSetMethodNG(bborder
, GA_BottomBorder
, TRUE
, TAG_DONE
);
837 AsmCoerceMethod(cl
, (Object
*)rc
, OM_DISPOSE
);
844 * If the window object cannot be created we
845 * dispose of the master group and border groups.
847 if (master
) AsmDoMethod(master
, OM_DISPOSE
);
848 if (lborder
) AsmDoMethod(lborder
, OM_DISPOSE
);
849 if (tborder
) AsmDoMethod(tborder
, OM_DISPOSE
);
850 if (rborder
) AsmDoMethod(rborder
, OM_DISPOSE
);
851 if (bborder
) AsmDoMethod(bborder
, OM_DISPOSE
);
861 * Get rid of an object.
863 STATIC
METHOD(WindowClassDispose
, Msg
, msg
)
865 WD
*wd
= INST_DATA(cl
, obj
);
870 * When the window is open we close it.
872 if (wd
->wd_WindowPtr
)
873 AsmDoMethod(obj
, WM_CLOSE
);
875 if (wd
->wd_Locale
&& wd
->wd_Catalog
)
877 CloseLocale(wd
->wd_Locale
->bl_Locale
);
878 CloseCatalog(wd
->wd_Locale
->bl_Catalog
);
880 if (wd
->wd_Flags
& WDF_FREELOCALE
)
881 BGUI_FreePoolMem(wd
->wd_Locale
);
884 if (wd
->wd_DGMObject
)
886 DisposeObject(wd
->wd_DGMObject
);
891 DisposeRegion(wd
->wd_Region
);
895 * Remove and delete the tab-cycle list.
897 while ((tc
= (TABCYCLE
*)RemHead((struct List
*)&wd
->wd_CycleList
)))
898 BGUI_FreePoolMem(tc
);
901 * Remove and delete all update targets.
903 while ((up
= (UPN
*)RemHead((struct List
*)&wd
->wd_UpdateList
)))
904 BGUI_FreePoolMem(up
);
907 * Free the NewMenu array.
909 if (wd
->wd_MenuStrip
)
910 BGUI_FreePoolMem(wd
->wd_MenuStrip
);
913 * Dispose of the master group and
916 if (wd
->wd_Gadgets
) AsmDoMethod(wd
->wd_Gadgets
, OM_DISPOSE
);
917 if (wd
->wd_LBorder
) AsmDoMethod(wd
->wd_LBorder
, OM_DISPOSE
);
918 if (wd
->wd_RBorder
) AsmDoMethod(wd
->wd_RBorder
, OM_DISPOSE
);
919 if (wd
->wd_BBorder
) AsmDoMethod(wd
->wd_BBorder
, OM_DISPOSE
);
920 if (wd
->wd_TBorder
) AsmDoMethod(wd
->wd_TBorder
, OM_DISPOSE
);
924 BGUI_CloseFont(wd
->wd_UsedFont
);
925 wd
->wd_UsedFont
=NULL
;
928 * The superclass takes care of the rest.
930 return AsmDoSuperMethodA(cl
, obj
, msg
);
935 * Setup the menu strip.
937 STATIC ASM BOOL
DoMenuStrip( REG(a0
) WD
*wd
, REG(a1
) struct Screen
*scr
)
940 * Get the visual info. (We use
941 * gadtools for the menus.)
943 if ((wd
->wd_VisualInfo
= GetVisualInfo( scr
, TAG_END
))) {
945 * Create the menu-strip.
947 if ((wd
->wd_Menus
= CreateMenus( wd
->wd_MenuStrip
, TAG_END
))) {
949 * Layout the menu strip.
951 if ( LayoutMenus( wd
->wd_Menus
, wd
->wd_VisualInfo
, GTMN_NewLookMenus
, TRUE
, wd
->wd_MenuFont
? GTMN_TextAttr
: TAG_IGNORE
, wd
->wd_MenuFont
, TAG_END
))
954 * Everything below this point means failure.
956 FreeMenus( wd
->wd_Menus
);
959 FreeVisualInfo( wd
->wd_VisualInfo
);
960 wd
->wd_VisualInfo
= NULL
;
966 * Kill the AppWindow stuff.
968 STATIC ASM VOID
KillAppWindow(REG(a0
) WD
*wd
)
973 * Remove the AppWindow.
975 if (wd
->wd_AppWindow
)
977 RemoveAppWindow(wd
->wd_AppWindow
);
978 wd
->wd_AppWindow
= NULL
;
982 * Do we have a message port?
987 * Kill all remaining messages and the port.
989 while ((msg
= GetMsg(wd
->wd_AppPort
)))
992 DeleteMsgPort(wd
->wd_AppPort
);
993 wd
->wd_AppPort
= NULL
;
998 * Make it an AppWindow.
1000 STATIC ASM BOOL
MakeAppWindow(REG(a0
) WD
*wd
)
1003 * Create a message port.
1005 if ((wd
->wd_AppPort
= CreateMsgPort()))
1008 * Create the app window.
1010 if ((wd
->wd_AppWindow
= AddAppWindowA(0, 0, wd
->wd_WindowPtr
, wd
->wd_AppPort
, NULL
)))
1019 * Compute width and height of the
1022 STATIC ASM VOID
SystemSize(REG(a1
) WD
*wd
)
1024 struct TagItem tags
[4];
1026 BOOL hires
= wd
->wd_Screen
->Flags
& SCREENHIRES
;
1029 * Set DrawInfo and resolution.
1031 tags
[0].ti_Tag
= SYSIA_Which
;
1032 tags
[1].ti_Tag
= SYSIA_DrawInfo
;
1033 tags
[1].ti_Data
= (IPTR
)wd
->wd_DrawInfo
;
1034 tags
[2].ti_Tag
= SYSIA_Size
;
1035 tags
[2].ti_Data
= hires
? SYSISIZE_MEDRES
: SYSISIZE_LOWRES
;
1036 tags
[3].ti_Tag
= TAG_DONE
;
1041 tags
[0].ti_Data
= SIZEIMAGE
;
1042 if ((image
= NewObjectA(NULL
, SYSICLASS
, tags
)))
1044 wd
->wd_SizeW
= IM_BOX(image
)->Width
;
1045 wd
->wd_SizeH
= IM_BOX(image
)->Height
;
1046 DisposeObject(image
);
1050 wd
->wd_SizeW
= hires
? 18 : 13;
1051 wd
->wd_SizeH
= hires
? 10 : 11;
1057 tags
[0].ti_Data
= CLOSEIMAGE
;
1058 if ((image
= NewObjectA(NULL
, SYSICLASS
, tags
)))
1060 wd
->wd_CloseW
= IM_BOX(image
)->Width
;
1061 DisposeObject(image
);
1064 wd
->wd_CloseW
= hires
? 20 : 15;
1069 tags
[0].ti_Data
= DEPTHIMAGE
;
1070 if ((image
= NewObjectA(NULL
, SYSICLASS
, tags
)))
1072 wd
->wd_DepthW
= IM_BOX(image
)->Width
;
1073 DisposeObject(image
);
1076 wd
->wd_DepthW
= hires
? 24 : 18;
1081 tags
[0].ti_Data
= ZOOMIMAGE
;
1082 if ((image
= NewObjectA(NULL
, SYSICLASS
, tags
)))
1084 wd
->wd_ZoomW
= IM_BOX(image
)->Width
;
1085 DisposeObject(image
);
1088 wd
->wd_ZoomW
= hires
? 24 : 18;
1092 * Query border sizes.
1094 STATIC ASM
void WBorderSize(REG(a0
) WD
*wd
, REG(a1
) struct Screen
*scr
, REG(a2
) struct TextAttr
*at
)
1096 UWORD wl
, wt
, wr
, wb
;
1099 * Borders available?
1101 if (!(wd
->wd_WindowFlags
& WFLG_BORDERLESS
))
1104 * Default border sizes.
1106 wt
= scr
->WBorTop
+ scr
->Font
->ta_YSize
+ 1;
1108 wr
= scr
->WBorRight
;
1109 wb
= scr
->WBorBottom
;
1112 * Get system gadget dimensions.
1117 * Adjust for sizing gadget.
1119 if (wd
->wd_WindowFlags
& WFLG_SIZEGADGET
)
1122 * Bottom border size gadget?
1124 if (wd
->wd_WindowFlags
& WFLG_SIZEBBOTTOM
) wb
= wd
->wd_SizeH
;
1125 else wr
= wd
->wd_SizeW
;
1128 * Right border size gadget?
1130 if (wd
->wd_WindowFlags
& WFLG_SIZEBRIGHT
) wr
= wd
->wd_SizeW
;
1134 * Adjust for border groups.
1138 GroupDimensions(wd
, wd
->wd_LBorder
, at
, &wd
->wd_LWidth
, &wd
->wd_LHeight
);
1139 if (wd
->wd_LWidth
> wl
) wl
= wd
->wd_LWidth
;
1144 GroupDimensions(wd
, wd
->wd_TBorder
, at
, &wd
->wd_TWidth
, &wd
->wd_THeight
);
1145 if (wd
->wd_THeight
> wt
) wt
= wd
->wd_THeight
;
1150 GroupDimensions(wd
, wd
->wd_RBorder
, at
, &wd
->wd_RWidth
, &wd
->wd_RHeight
);
1151 if (wd
->wd_RWidth
> wr
) wr
= wd
->wd_RWidth
;
1156 GroupDimensions(wd
, wd
->wd_BBorder
, at
, &wd
->wd_BWidth
, &wd
->wd_BHeight
);
1157 if (wd
->wd_BHeight
> wb
) wb
= wd
->wd_BHeight
;
1171 wd
->wd_Left
= wd
->wd_Top
= wd
->wd_Right
= wd
->wd_Bottom
= 0;
1174 BOOL
WinSize(WD
*wd
, UWORD
*win_w
, UWORD
*win_h
)
1176 struct TextAttr
*font
;
1179 struct Screen
*scr
= wd
->wd_Screen
;
1182 int bw
, bh
, gx
, gy
, t1
, t2
;
1184 int sw
= scr
->Width
;
1185 int sh
= scr
->Height
;
1187 int vw
= wd
->wd_TextW
;
1188 int vh
= wd
->wd_TextH
;
1190 if (wd
->wd_UsedFont
)
1192 BGUI_CloseFont(wd
->wd_UsedFont
);
1193 wd
->wd_UsedFont
= NULL
;
1197 * The screen can be smaller than the TEXT
1198 * overscan sizes. Check if this is the case.
1200 if (vw
> sw
) vw
= sw
;
1201 if (vh
> sh
) vh
= sh
;
1204 * Setup aspect dependant framing and the
1207 if (wd
->wd_Flags
& WDF_AUTOASPECT
)
1210 * Guess aspect ratio.
1212 thin
= ((wd
->wd_DrawInfo
->dri_Resolution
.X
/ wd
->wd_DrawInfo
->dri_Resolution
.Y
) <= 1);
1214 DoMultiSet(FRM_ThinFrame
, thin
, 5, wd
->wd_Gadgets
, wd
->wd_LBorder
, wd
->wd_TBorder
, wd
->wd_RBorder
, wd
->wd_BBorder
);
1218 * Pick up the font to use. This will either
1219 * be the font specified with WINDOW_Font or
1222 font
= wd
->wd_Font
? wd
->wd_Font
: scr
->Font
;
1225 * When the window has grown too big for the font, the
1226 * recomputation using the fallback font will start here.
1231 * Ask the master group to compute its
1232 * absolute minimum dimension.
1234 GroupDimensions(wd
, wd
->wd_Gadgets
, font
, (UWORD
*)&gmw
, (UWORD
*)&gmh
);
1239 wd
->wd_MasterW
= gmw
;
1240 wd
->wd_MasterH
= gmh
;
1243 * Borderless windows, and backdrop for that matter,
1244 * have no borders and system gadgets so this part
1245 * of the computation can be skipped.
1247 if (!(wd
->wd_WindowFlags
& WFLG_BORDERLESS
))
1250 * Compute border sizes.
1252 WBorderSize(wd
, scr
, font
);
1255 * Compute totals of border gadgets.
1257 bw
= wd
->wd_Left
+ wd
->wd_Right
;
1258 bh
= wd
->wd_Top
+ wd
->wd_Bottom
;
1261 * Add the minimum window border sizes.
1267 * Check to see if any of the border groups
1268 * have a larger minimum width or height than
1269 * the current window size.
1273 t1
= wd
->wd_LHeight
+ wd
->wd_Top
+ wd
->wd_Bottom
;
1274 if (t1
> gmh
) gmh
= t1
;
1279 t1
= wd
->wd_RHeight
+ wd
->wd_Top
+ wd
->wd_Bottom
;
1280 if (t1
> gmh
) gmh
= t1
;
1286 if ((wd
->wd_Flags
& WDF_TITLEZIP
) ||
1287 (wd
->wd_WindowFlags
& WFLG_SIZEGADGET
)) t1
+= wd
->wd_ZoomW
;
1288 if (wd
->wd_WindowFlags
& WFLG_DEPTHGADGET
) t1
+= wd
->wd_DepthW
;
1289 if (wd
->wd_WindowFlags
& WFLG_CLOSEGADGET
) t1
+= wd
->wd_CloseW
;
1290 if (t1
> gmw
) gmw
= t1
;
1296 if (wd
->wd_WindowFlags
& WFLG_SIZEGADGET
) t1
+= wd
->wd_SizeW
;
1297 if (t1
> gmw
) gmw
= t1
;
1301 * Setup master gadget dimensions.
1307 * And the border groups.
1311 DoSetMethodNG(wd
->wd_LBorder
, GA_Left
, 0,
1313 GA_Width
, wd
->wd_Left
,
1314 GA_RelHeight
, -(wd
->wd_Top
),
1320 t1
= wd
->wd_WindowFlags
& WFLG_DEPTHGADGET
? wd
->wd_DepthW
- 1: 0;
1321 t1
+= (wd
->wd_WindowFlags
& WFLG_SIZEGADGET
) ||
1322 (wd
->wd_Flags
& WDF_TITLEZIP
) ? wd
->wd_ZoomW
- 1: 0;
1324 DoSetMethodNG(wd
->wd_TBorder
, GA_RelRight
, -(wd
->wd_TWidth
+ t1
- 1),
1326 GA_Width
, wd
->wd_TWidth
,
1327 GA_Height
, wd
->wd_Top
,
1333 t1
= wd
->wd_WindowFlags
& WFLG_SIZEGADGET
? wd
->wd_SizeH
- wd
->wd_Bottom
: 0;
1335 DoSetMethodNG(wd
->wd_RBorder
, GA_RelRight
, -(wd
->wd_Right
- 1),
1337 GA_Width
, wd
->wd_Right
,
1338 GA_RelHeight
, -(wd
->wd_Top
+ wd
->wd_Bottom
+ t1
),
1344 t1
= /*wd->wd_LBorder ?*/ wd
->wd_Left
/*: 0*/;
1345 t2
= wd
->wd_WindowFlags
& WFLG_SIZEGADGET
? wd
->wd_SizeW
: 0;
1347 DoSetMethodNG(wd
->wd_BBorder
, GA_Left
, t1
,
1348 GA_RelBottom
, -(wd
->wd_Bottom
- 1),
1349 GA_RelWidth
, -(t1
+ t2
),
1350 GA_Height
, wd
->wd_Bottom
,
1357 * No offsets necessary for
1358 * borderless windows.
1360 gx
= gy
= bw
= bh
= 0;
1364 * Set values to the master group.
1366 DoSetMethodNG(wd
->wd_Gadgets
, GA_Left
, gx
, GA_Top
, gy
, GA_RelWidth
, -bw
, GA_RelHeight
, -bh
, TAG_DONE
);
1371 if (wd
->wd_WindowFlags
& WFLG_BACKDROP
)
1374 * We force the window to be display
1375 * sized or display sized minus the
1378 if (wd
->wd_Flags
& WDF_SHOWTITLE
)
1380 sh
= scr
->Height
- scr
->BarHeight
- 1;
1387 ShowTitle(scr
, FALSE
);
1395 * Final check. Does the window fit and does
1396 * the width and height of the window read
1397 * positive values? If not retry with the
1400 if ((gmw
> sw
) || (gmh
> sh
))
1403 * Did it fail with the
1406 if (font
== wd
->wd_FallBackFont
)
1410 * Retry with the fallback font.
1412 font
= wd
->wd_FallBackFont
;
1416 if ((wd
->wd_UsedFont
= BGUI_OpenFont(font
)))
1428 * Open up the window.
1430 STATIC
METHOD(WindowClassOpen
, Msg
, msg
)
1432 WD
*wd
= INST_DATA(cl
, obj
);
1433 WORD wleft
= 0, wtop
= 0, width
= 0, height
= 0, mw
= 0, mh
= 0;
1435 struct Screen
*pubscreen
;
1436 struct Rectangle rect
;
1437 struct Gadget
*glist
= GADGET(wd
->wd_Gadgets
);
1439 BOOL keepw
= wd
->wd_Flags
& WDF_LOCK_WIDTH
;
1440 BOOL keeph
= wd
->wd_Flags
& WDF_LOCK_HEIGHT
;
1444 struct Message
*imsg
;
1447 * If the window is already opened we
1448 * return a pointer to it.
1450 if ((w
= wd
->wd_WindowPtr
))
1454 * Link border gadgets.
1458 GADGET(wd
->wd_RBorder
)->NextGadget
= glist
;
1459 glist
= GADGET(wd
->wd_RBorder
);
1465 GADGET(wd
->wd_BBorder
)->NextGadget
= glist
;
1466 glist
= GADGET(wd
->wd_BBorder
);
1472 GADGET(wd
->wd_LBorder
)->NextGadget
= glist
;
1473 glist
= GADGET(wd
->wd_LBorder
);
1479 GADGET(wd
->wd_TBorder
)->NextGadget
= glist
;
1480 glist
= GADGET(wd
->wd_TBorder
);
1485 * Obtain a pointer to the
1490 pubscreen
= wd
->wd_Screen
;
1495 if (wd
->wd_PubScreen
) pubscreen
= wd
->wd_PubScreen
;
1501 if (!(pubscreen
= LockPubScreen(wd
->wd_PubScreenName
)))
1503 * Fallback to the default screen
1504 * when locking failed. Should be
1507 pubscreen
= LockPubScreen(NULL
);
1509 * Tell'm we locked the screen.
1512 wd
->wd_Flags
|= WDF_SCREEN_LOCKED
;
1514 wd
->wd_Screen
= pubscreen
;
1518 * Do we have a screen?
1520 if (!pubscreen
) return 0;
1523 * Set up BDrawInfo drawinfo and pens.
1525 wd
->wd_DrawInfo
= GetScreenDrawInfo(pubscreen
);
1528 for (i = 0; i < NUMDRIPENS; i++)
1530 wd->wd_BDI.bdi_Pens[i] = (wd->wd_BDI.bdi_DrInfo && (i < wd->wd_BDI.bdi_DrInfo->dri_NumPens)) ?
1531 wd->wd_BDI.bdi_DrInfo->dri_Pens[i] : DefDriPens[i];
1535 vw
= pubscreen
->Width
;
1536 vh
= pubscreen
->Height
;
1539 * Obtain the mode ID from the screen to use.
1542 if ((modeID
= GetVPModeID(&pubscreen
->ViewPort
)) != INVALID_ID
)
1545 * Find out TEXT overscan
1548 if (QueryOverscan(modeID
, &rect
, OSCAN_TEXT
))
1551 * Compute TEXT overscan width and height
1552 * for this display mode.
1554 vw
= rect
.MaxX
- rect
.MinX
+ 1;
1555 vh
= rect
.MaxY
- rect
.MinY
+ 1;
1561 * Store the text overscan dimensions.
1566 /* AROS FIX <-> AMIGA FIX? */
1568 if (vw
> pubscreen
->Width
) vw
= pubscreen
->Width
;
1569 if (vh
> pubscreen
->Height
) vh
= pubscreen
->Height
;
1571 if (!WinSize(wd
, (UWORD
*)&width
, (UWORD
*)&height
))
1577 if (wd
->wd_WindowFlags
& WFLG_BACKDROP
)
1580 * We force the window to be display
1581 * sized or display sized minus the
1586 if (wd
->wd_Flags
& WDF_SHOWTITLE
)
1587 wtop
= pubscreen
->BarHeight
+ 1;
1595 * The computed width and height are the
1596 * absolute minimum size that the window
1597 * can have. We save them here for the
1598 * window alternate (zipped) position.
1604 * Scale the window size?
1606 if (wd
->wd_WidthScale
) width
+= ((vw
- width
) * wd
->wd_WidthScale
) / 100;
1607 if (wd
->wd_HeightScale
) height
+= ((vh
- height
) * wd
->wd_HeightScale
) / 100;
1610 * When the window was opened before and the size is known or there
1611 * is previous size information available we use this information.
1613 if (wd
->wd_Flags
& WDF_CHANGE_VALID
|| GetWindowBounds(wd
->wd_ID
, &wd
->wd_FixedPos
))
1616 * If the width or height of the window
1617 * is fixed then we reuse the previous
1618 * values. If not we use the new values.
1620 width
= keepw
? width
: wd
->wd_FixedPos
.Width
;
1621 height
= keeph
? height
: wd
->wd_FixedPos
.Height
;
1624 * If the window is placed relative to a
1625 * given rectangle we place it again relative
1626 * to that rectangle. Otherwise we copy the
1627 * previous position.
1629 if (wd
->wd_Flags
& WDF_RELBOX
)
1631 wleft
= ((wd
->wd_RelPos
.Width
- width
) >> 1) + wd
->wd_RelPos
.Left
;
1632 wtop
= ((wd
->wd_RelPos
.Height
- height
) >> 1) + wd
->wd_RelPos
.Top
;
1636 wleft
= wd
->wd_FixedPos
.Left
;
1637 wtop
= wd
->wd_FixedPos
.Top
;
1641 * In case the font changed we need to check if the window has become
1642 * smaller than allowed and adjust if necessary.
1644 if (width
< mw
) width
= mw
;
1645 if (height
< mh
) height
= mh
;
1648 * Does the window still fit in this
1651 if (width
> pubscreen
->Width
&& mw
<= pubscreen
->Width
) width
= pubscreen
->Width
;
1652 if (height
> pubscreen
->Height
&& mh
<= pubscreen
->Height
) height
= pubscreen
->Height
;
1655 * Adjust the window position when necessary.
1657 if ((wleft
+ width
) > pubscreen
->Width
) wleft
= pubscreen
->Width
- width
;
1658 if ((wtop
+ height
) > pubscreen
->Height
) wtop
= pubscreen
->Height
- height
;
1663 * Window positioned relative to a given rectangle?
1665 if (!(wd
->wd_Flags
& WDF_RELBOX
))
1668 * What position is requested?
1670 switch (wd
->wd_Position
)
1672 case POS_CENTERSCREEN
:
1673 wleft
= ((vw
- width
) >> 1) - pubscreen
->ViewPort
.DxOffset
;
1674 wtop
= ((vh
- height
) >> 1) - pubscreen
->ViewPort
.DyOffset
;
1677 case POS_CENTERMOUSE
:
1678 wleft
= pubscreen
->MouseX
- (width
>> 1) - pubscreen
->ViewPort
.DxOffset
;
1679 wtop
= pubscreen
->MouseY
- (height
>> 1) - pubscreen
->ViewPort
.DyOffset
;
1686 * Setup window according to the
1689 wleft
= ((wd
->wd_RelPos
.Width
- width
) >> 1) + wd
->wd_RelPos
.Left
;
1690 wtop
= ((wd
->wd_RelPos
.Height
- height
) >> 1) + wd
->wd_RelPos
.Top
;
1697 * Do we have menus defined?
1699 if (wd
->wd_MenuStrip
)
1704 if (!DoMenuStrip(wd
, pubscreen
))
1709 * Setup zip positions.
1711 if (wd
->wd_Flags
& WDF_TITLEZIP
)
1714 * We always have a zoom gadget.
1716 wd
->wd_Zoom
[2] = wd
->wd_ZoomW
- 1;
1719 * Add the pixel-width of the title + 60.
1721 if (wd
->wd_WindowTitle
) wd
->wd_Zoom
[2] += TextWidth(&pubscreen
->RastPort
, wd
->wd_WindowTitle
) + 60;
1724 * And any other system gadgets.
1726 if (wd
->wd_WindowFlags
& WFLG_DEPTHGADGET
) wd
->wd_Zoom
[2] += wd
->wd_DepthW
- 1;
1727 if (wd
->wd_WindowFlags
& WFLG_CLOSEGADGET
) wd
->wd_Zoom
[2] += wd
->wd_CloseW
- 1;
1730 * And a top-group minimum size.
1732 if (wd
->wd_TBorder
) wd
->wd_Zoom
[2] += wd
->wd_TWidth
;
1737 wd
->wd_Zoom
[3] = wd
->wd_Top
;
1740 if (wd
->wd_Flags
& WDF_PREBUFFER
) AsmDoMethod(wd
->wd_Gadgets
, BASE_RENDERBUFFER
, pubscreen
, width
, height
);
1743 * Open the window (finally :))
1745 w
= wd
->wd_WindowPtr
= OpenWindowTags(NULL
,
1746 WA_Left
, wleft
, WA_Top
, wtop
,
1747 WA_Width
, width
, WA_Height
, height
,
1748 WA_Flags
, wd
->wd_WindowFlags
, WA_Gadgets
, glist
,
1749 WA_BackFill
, &BackFill_hook
, WA_RptQueue
, 1,
1750 WA_MinWidth
, mw
, WA_MinHeight
, mh
,
1751 WA_MaxWidth
, (wd
->wd_Flags
& WDF_LOCK_WIDTH
) ? mw
: ~0,
1752 WA_MaxHeight
, (wd
->wd_Flags
& WDF_LOCK_HEIGHT
) ? mh
: ~0,
1753 wd
->wd_WindowTitle
? WA_Title
: TAG_IGNORE
, wd
->wd_WindowTitle
,
1754 wd
->wd_ScreenTitle
? WA_ScreenTitle
: TAG_IGNORE
, wd
->wd_ScreenTitle
,
1755 pub
? WA_PubScreen
: WA_CustomScreen
, pubscreen
,
1756 wd
->wd_Flags
& WDF_TITLEZIP
? WA_Zoom
: TAG_IGNORE
, wd
->wd_Zoom
,
1757 WA_IDCMP
, wd
->wd_IDCMPFlags
,
1758 WA_MenuHelp
, TRUE
, TAG_END
);
1760 if (!w
) goto failure
;
1765 wd
->wd_OrigFont
= w
->RPort
->Font
;
1766 FSetFont(w
->RPort
, wd
->wd_UsedFont
);
1769 * Move the top-border group to the
1770 * beginning of the list.
1774 RemoveGList(w
, glist
, borders
);
1775 AddGList(w
, glist
, 0, borders
, NULL
);
1779 * Save window bounds.
1781 SetWindowBounds(wd
->wd_ID
, (struct IBox
*)&w
->LeftEdge
);
1784 * Setup menu-strip if one exists.
1787 SetMenuStrip(w
, wd
->wd_Menus
);
1790 * When we have a shared MsgPort we must move any initial messages to it,
1793 if (wd
->wd_Flags
& WDF_SHARED_MSGPORT
)
1796 * Set it to a flag that will not occur, to stop input without closing the port.
1798 ModifyIDCMP(w
, IDCMP_REQCLEAR
);
1800 while ((imsg
= GetMsg(w
->UserPort
)))
1803 * Dump message onto the other port.
1805 PutMsg(wd
->wd_UserPort
, imsg
);
1808 * Free intuition's port.
1813 * Poke the shared port.
1815 w
->UserPort
= wd
->wd_UserPort
;
1820 ModifyIDCMP(w
, wd
->wd_IDCMPFlags
);
1825 * Pick up the intuition created message port.
1827 wd
->wd_UserPort
= w
->UserPort
;
1831 * If requested setup this window
1832 * as a workbench App-Window.
1834 if (wd
->wd_Flags
& WDF_IS_APPWINDOW
)
1841 * Add window to the internal list.
1842 * Also fails quietly...
1850 AsmCoerceMethod(cl
, obj
, WM_CLOSE
);
1858 * Clear all messages from
1859 * the port which belong to
1862 STATIC ASM VOID
ClearMsgPort( REG(a0
) WD
*wd
)
1864 struct IntuiMessage
*imsg
;
1868 * Don't race intuition.
1872 imsg
= ( struct IntuiMessage
* )wd
->wd_UserPort
->mp_MsgList
.lh_Head
;
1874 while ((succ
= imsg
->ExecMessage
.mn_Node
.ln_Succ
)) {
1875 if ( imsg
->IDCMPWindow
== wd
->wd_WindowPtr
) {
1876 Remove(( struct Node
* )imsg
);
1877 ReplyMsg(( struct Message
* )imsg
);
1879 imsg
= ( struct IntuiMessage
* )succ
;
1887 STATIC
METHOD(WindowClassClose
, Msg
, msg
)
1889 WD
*wd
= INST_DATA(cl
, obj
);
1893 if ((w
= wd
->wd_WindowPtr
))
1896 * When a shared MsgPort is used
1897 * we clear the UserPort ptr in the window
1902 if (wd
->wd_Flags
& WDF_SHARED_MSGPORT
)
1910 * Close tool-tip window.
1912 AsmDoMethod(obj
, WM_CLOSETOOLTIP
);
1915 * Wakeup the window.
1917 while (wd
->wd_SleepCnt
)
1918 AsmDoMethod(obj
, WM_WAKEUP
);
1923 if (wd
->wd_Flags
& WDF_IS_APPWINDOW
)
1927 * Remove the window menus.
1929 if (wd
->wd_Menus
) ClearMenuStrip(w
);
1932 * Setup original font.
1934 FSetFont(w
->RPort
, wd
->wd_OrigFont
);
1940 wd
->wd_WindowPtr
= NULL
;
1943 * Remove it and all outstanding ID's from the internal lists.
1949 * Clear continuation flags.
1951 wd
->wd_NextSelect
= MENUNULL
;
1952 wd
->wd_Flags
&= ~WDF_DRAGSELECT
;
1959 FreeMenus(wd
->wd_Menus
);
1960 wd
->wd_Menus
= NULL
;
1963 if (wd
->wd_BufferRP
)
1965 wd
->wd_BufferRP
->Layer
= wd
->wd_BufferLayer
;
1966 BGUI_FreeRPortBitMap(wd
->wd_BufferRP
);
1967 wd
->wd_BufferRP
= NULL
;
1973 if (wd
->wd_UsedFont
)
1975 BGUI_CloseFont(wd
->wd_UsedFont
);
1976 wd
->wd_UsedFont
= NULL
;
1979 if (wd
->wd_VisualInfo
)
1981 FreeVisualInfo(wd
->wd_VisualInfo
);
1982 wd
->wd_VisualInfo
= NULL
;
1985 if (wd
->wd_DrawInfo
)
1987 FreeScreenDrawInfo(wd
->wd_Screen
, wd
->wd_DrawInfo
);
1988 wd
->wd_DrawInfo
= NULL
;
1991 if (wd
->wd_Flags
& WDF_SCREEN_LOCKED
)
1993 UnlockPubScreen(NULL
, wd
->wd_Screen
);
1994 wd
->wd_Flags
&= ~WDF_SCREEN_LOCKED
;
1997 if (wd
->wd_PubScreenName
)
1999 wd
->wd_Screen
= NULL
;
2008 * Put the window to sleep.
2010 STATIC
METHOD(WindowClassSleep
, Msg
, msg
)
2012 WD
*wd
= INST_DATA(cl
, obj
);
2016 * Only go to sleep if the window is open.
2018 if (wd
->wd_WindowPtr
)
2021 * If the sleep nest counter is 0 we setup a requester
2022 * and a busy pointer.
2024 if (wd
->wd_SleepCnt
++ == 0)
2025 wd
->wd_Lock
= BGUI_LockWindow(wd
->wd_WindowPtr
);
2027 * Return 1 for sucess.
2037 * Wake the window back up.
2039 STATIC
METHOD(WindowClassWakeUp
, Msg
, msg
)
2041 WD
*wd
= INST_DATA(cl
, obj
);
2045 * Only decrease the sleep nest counter when the
2046 * window is open _and_ the sleep nest counter is not 0.
2050 if (--wd
->wd_SleepCnt
== 0)
2053 * When the sleep nest counter becomes zero we remove the
2054 * requester and reset the pointer.
2056 BGUI_UnlockWindow(wd
->wd_Lock
);
2067 * Keep track of window bound changes.
2069 STATIC ASM ULONG
WindowClassChange( REG(a0
) Class
*cl
, REG(a2
) Object
*obj
, REG(a1
) Msg msg
)
2071 WD
*wd
= INST_DATA(cl
, obj
);
2075 if ((w
= wd
->wd_WindowPtr
))
2077 wd
->wd_FixedPos
= *IBOX(&w
->LeftEdge
);
2078 wd
->wd_Flags
|= WDF_CHANGE_VALID
;
2081 * Save window bounds.
2083 SetWindowBounds(wd
->wd_ID
, (struct IBox
*)&w
->LeftEdge
);
2091 STATIC
METHOD(WindowClassGet
, struct opGet
*, opg
)
2093 WD
*wd
= (WD
*)INST_DATA(cl
, obj
);
2095 IPTR
*store
= opg
->opg_Storage
;
2099 switch (opg
->opg_AttrID
)
2101 case WINDOW_GadgetOK
:
2102 STORE
!(wd
->wd_Flags
& WDF_REMOVED
);
2105 case WINDOW_ToolTicks
:
2106 STORE wd
->wd_ToolTickTime
;
2109 case WINDOW_MenuStrip
:
2113 case WINDOW_UserPort
:
2114 if (wd
->wd_WindowPtr
) STORE wd
->wd_UserPort
;
2118 case WINDOW_SigMask
:
2119 STORE (wd
->wd_WindowPtr
? (1 << wd
->wd_UserPort
->mp_SigBit
) : 0);
2122 case WINDOW_AppMask
:
2123 STORE (wd
->wd_AppPort
? (1 << wd
->wd_AppPort
->mp_SigBit
) : 0);
2127 STORE wd
->wd_WindowPtr
;
2135 if ( wd
->wd_WindowPtr
)
2136 *(( struct IBox
* )store
) = *(( struct IBox
* )&wd
->wd_WindowPtr
->LeftEdge
);
2142 STORE wd
->wd_WindowTitle
;
2145 case WINDOW_ScreenTitle
:
2146 STORE wd
->wd_ScreenTitle
;
2149 case WINDOW_TitleID
:
2150 STORE wd
->wd_WindowTitleID
;
2153 case WINDOW_ScreenTitleID
:
2154 STORE wd
->wd_ScreenTitleID
;
2157 case WINDOW_HelpTextID
:
2158 STORE wd
->wd_HelpTextID
;
2161 case WINDOW_AutoAspect
:
2162 STORE
test(wd
->wd_Flags
& WDF_AUTOASPECT
);
2165 case WINDOW_BufferRP
:
2166 if ((win
= wd
->wd_WindowPtr
) && !(wd
->wd_Flags
& WDF_NO_BUFFER
) && (FGetDepth(win
->RPort
) <= 8))
2168 if ((wd
->wd_BRW
!= win
->Width
) || (wd
->wd_BRH
!= win
->Height
))
2170 wd
->wd_BRW
= win
->Width
;
2171 wd
->wd_BRH
= win
->Height
;
2172 if (wd
->wd_BufferRP
)
2174 wd
->wd_BufferRP
->Layer
= wd
->wd_BufferLayer
;
2175 BGUI_FreeRPortBitMap(wd
->wd_BufferRP
);
2176 wd
->wd_BufferRP
= NULL
;
2179 if (!wd
->wd_BufferRP
)
2181 wd
->wd_BufferRP
= BGUI_CreateRPortBitMap(win
->RPort
, wd
->wd_BRW
, wd
->wd_BRH
, 0);
2182 wd
->wd_BufferLayer
= wd
->wd_BufferRP
->Layer
;
2183 wd
->wd_BufferRP
->Layer
= NULL
;
2185 STORE wd
->wd_BufferRP
;
2194 rc
= (ULONG
)AsmDoSuperMethodA(cl
, obj
, (Msg
)opg
);
2202 * Put out a help-request.
2204 STATIC ASM ULONG
WindowClassHelp(REG(a0
) Class
*cl
, REG(a2
) Object
*obj
, REG(a1
) Msg msg
)
2206 WD
*wd
= INST_DATA( cl
, obj
);
2207 struct bmShowHelp bsh
;
2208 struct NewAmigaGuide nag
= { };
2209 ULONG rc
= BMHELP_FAILURE
;
2213 * Only when the window is open.
2215 if ((w
= wd
->wd_WindowPtr
))
2218 * Setup a help request for the
2221 bsh
.MethodID
= BASE_SHOWHELP
;
2223 bsh
.bsh_Requester
= NULL
;
2224 bsh
.bsh_Mouse
.X
= w
->MouseX
;
2225 bsh
.bsh_Mouse
.Y
= w
->MouseY
;
2227 * Go to sleep and send the
2230 AsmDoMethod(obj
, WM_SLEEP
);
2233 * Any help shown by the master object?
2235 if (AsmDoMethodA(wd
->wd_Gadgets
, (Msg
)&bsh
) == BMHELP_NOT_ME
)
2238 * No. Show the window help.
2240 if (wd
->wd_HelpFile
|| wd
->wd_HelpText
)
2243 * Only if the mouse is located
2246 if (bsh
.bsh_Mouse
.X
> 0 && bsh
.bsh_Mouse
.Y
> 0 && bsh
.bsh_Mouse
.X
< w
->Width
&& bsh
.bsh_Mouse
.Y
< w
->Height
)
2248 if (wd
->wd_HelpText
)
2250 ShowHelpReq(w
, wd
->wd_HelpText
);
2255 nag
.nag_Name
= (STRPTR
)wd
->wd_HelpFile
;
2256 nag
.nag_Node
= (STRPTR
)wd
->wd_HelpNode
;
2257 nag
.nag_Line
= wd
->wd_HelpLine
;
2258 nag
.nag_Screen
= w
->WScreen
;
2260 if (DisplayAGuideInfo(&nag
, TAG_END
))
2267 * Wakeup the window.
2269 AsmDoMethod(obj
, WM_WAKEUP
);
2275 * Fill up an InputEvent structure
2276 * with RAWKEY information.
2278 STATIC ASM VOID
FillIE(REG(a0
) struct InputEvent
*ie
, REG(a1
) struct IntuiMessage
*imsg
)
2280 ie
->ie_Class
= IECLASS_RAWKEY
;
2281 ie
->ie_Code
= imsg
->Code
;
2282 ie
->ie_Qualifier
= imsg
->Qualifier
;
2283 ie
->ie_EventAddress
= imsg
->IAddress
? *((APTR
*)(imsg
->IAddress
)) : NULL
;
2284 ie
->ie_TimeStamp
.tv_secs
= imsg
->Seconds
;
2285 ie
->ie_TimeStamp
.tv_micro
= imsg
->Micros
;
2289 * Get the first message from the
2290 * window port which belongs to the window.
2292 STATIC ASM
struct IntuiMessage
*GetIMsg( REG(a0
) WD
*wd
)
2294 struct IntuiMessage
*imsg
;
2295 struct MsgPort
*mp
= wd
->wd_UserPort
;
2298 * No need to race intuition.
2302 for ( imsg
= ( struct IntuiMessage
* )mp
->mp_MsgList
.lh_Head
; imsg
->ExecMessage
.mn_Node
.ln_Succ
; imsg
= ( struct IntuiMessage
* )imsg
->ExecMessage
.mn_Node
.ln_Succ
) {
2303 if ( imsg
->IDCMPWindow
== wd
->wd_WindowPtr
) {
2304 Remove(( struct Node
* )imsg
);
2315 * Find out if an object must receive a key message.
2317 STATIC ULONG
KeyGadget(Class
*cl
, Object
*obj
, struct IntuiMessage
*imsg
)
2320 WD
*wd
= INST_DATA(cl
, obj
);
2321 struct InputEvent ie
;
2322 struct wmKeyInput wk
;
2323 struct IntuiMessage
*im
= NULL
;
2325 ULONG irc
, id
, rc
= WMHI_IGNORE
;
2327 ULONG
class = imsg
->Class
;
2328 UWORD code
= imsg
->Code
;
2329 UWORD qual
= imsg
->Qualifier
;
2330 UBYTE key
= (UBYTE
)code
;
2332 struct Window
*w
= wd
->wd_WindowPtr
;
2337 * No menus during keyboard
2340 if (!(wd
->wd_WindowFlags
& WFLG_RMBTRAP
))
2343 w
->Flags
|= WFLG_RMBTRAP
;
2348 * Initialize input event.
2350 if (code
& IECODE_UP_PREFIX
)
2354 if (MapRawKey(&ie
, &key
, 1, NULL
) == 1)
2358 code
= code
| 0xFF00;
2362 if (!(ob
= (Object
*)AsmDoMethod(obj
, BASE_FINDKEY
, qual
, code
)))
2365 if (!(ob
= (Object
*)AsmDoMethod(obj
, BASE_FINDKEY
, (qual
<< 16) | code
)))
2370 * Initialize wmKeyInput structure.
2372 wk
.MethodID
= WM_KEYACTIVE
;
2373 wk
.wmki_IEvent
= &ie
;
2378 * Send a WM_KEYACTIVE message to the target.
2380 irc
= BGUI_DoGadgetMethodA(ob
, w
, NULL
, (Msg
)&wk
);
2383 * Reply the originating message.
2385 ReplyMsg((struct Message
*)imsg
);
2391 if (irc
& WMKF_VERIFY
)
2394 * Yes. Return the id.
2399 else if (irc
& WMKF_CANCEL
)
2402 * We are cancelled :^(
2403 * Return WMHI_IGNORE.
2407 else if (irc
& WMKF_ACTIVATE
)
2410 * We are told to activate the
2411 * gadget through intuition channels.
2414 ActivateGadget(GADGET(ob
), w
, NULL
);
2420 * Boom. We are active.
2422 wk
.MethodID
= WM_KEYINPUT
;
2426 WaitPort(wd
->wd_UserPort
);
2427 while ((im
= GetIMsg(wd
)))
2431 qual
= im
->Qualifier
;
2432 iadd
= im
->IAddress
;
2437 * Check out the RAWKEY event.
2440 if (qual
& IEQUALIFIER_REPEAT
) break;
2441 if ((code
& IECODE_UP_PREFIX
) == 0)
2443 myDoGadgetMethod(ob
, w
, NULL
, WM_KEYINACTIVE
, NULL
);
2447 irc
= BGUI_DoGadgetMethodA(ob
, wd
->wd_WindowPtr
, NULL
, (Msg
)&wk
);
2448 if (irc
& WMKF_VERIFY
)
2450 myDoGadgetMethod(ob
, w
, NULL
, WM_KEYINACTIVE
, NULL
);
2454 else if (irc
& WMKF_CANCEL
)
2456 myDoGadgetMethod(ob
, w
, NULL
, WM_KEYINACTIVE
, NULL
);
2461 case IDCMP_CLOSEWINDOW
:
2463 * Pass on the close window request.
2465 myDoGadgetMethod(ob
, w
, NULL
, WM_KEYINACTIVE
, NULL
);
2466 rc
= WMHI_CLOSEWINDOW
;
2469 case IDCMP_GADGETUP
:
2471 * Pass on the gadget request.
2473 myDoGadgetMethod(ob
, w
, NULL
, WM_KEYINACTIVE
, NULL
);
2474 rc
= GADGET(iadd
)->GadgetID
;
2477 case IDCMP_INACTIVEWINDOW
:
2479 * Window inactive? Abort keyboard actions.
2481 myDoGadgetMethod(ob
, w
, NULL
, WM_KEYINACTIVE
, NULL
);
2485 case IDCMP_SIZEVERIFY
:
2489 myDoGadgetMethod(ob
, w
, NULL
, WM_KEYINACTIVE
, NULL
);
2490 wd
->wd_OW
= w
->Width
;
2491 wd
->wd_OH
= w
->Height
;
2492 wd
->wd_Flags
|= WDF_REMOVED
;
2493 RemoveGadget(w
, (struct Gadget
*)wd
->wd_Gadgets
);
2499 * Reply the message.
2501 ReplyMsg((struct Message
*)im
);
2508 * Reply the un-replyed messages.
2510 if (imsg
) ReplyMsg((struct Message
*)imsg
);
2511 if (im
) ReplyMsg((struct Message
*)im
);
2514 * Menu actions possible if they were before the keyboard stuff
2515 * and if we don't stay active.
2517 if (!(wd
->wd_WindowFlags
& WFLG_RMBTRAP
))
2520 w
->Flags
&= ~WFLG_RMBTRAP
;
2527 * Find tab-cycle entry.
2529 STATIC ASM TABCYCLE
*GetCycleNode( REG(a0
) WD
*wd
, REG(a1
) Object
*obj
)
2533 for ( tc
= wd
->wd_CycleList
.cl_First
; tc
->tc_Next
; tc
= tc
->tc_Next
) {
2534 if ( tc
->tc_Object
== obj
)
2541 * Perform update notification.
2543 STATIC ASM VOID
UpdateNotification( REG(a0
) WD
*wd
, REG(a1
) struct TagItem
*attr
, REG(d0
) ULONG id
)
2545 struct TagItem
*clones
;
2551 if ((clones
= CloneTagItems( attr
))) {
2555 for ( up
= wd
->wd_UpdateList
.ul_First
; up
->up_Next
; up
= up
->up_Next
)
2560 if ( up
->up_ID
== id
)
2563 * Map clones when necessary.
2565 if ( up
->up_MapList
)
2566 MapTags( clones
, up
->up_MapList
, TRUE
);
2568 * Set attributes to the target.
2570 myDoGadgetMethod(up
->up_Target
, wd
->wd_WindowPtr
, NULL
, OM_UPDATE
, clones
, NULL
, 0);
2572 * Unmap clones when necessary.
2574 if ( up
->up_MapList
)
2575 UnmapTags( clones
, up
->up_MapList
);
2581 FreeTagItems( clones
);
2586 * Default tool tip hook.
2588 //STATIC ASM IPTR ToolTip_func(REG(a0) struct Hook *h, REG(a2) Object *obj, REG(a1) struct ttCommand *ttc)
2589 STATIC ASM
REGFUNC3(IPTR
, ToolTip_func
,
2590 REGPARAM(A0
, struct Hook
*, h
),
2591 REGPARAM(A2
, Object
*, obj
),
2592 REGPARAM(A1
, struct ttCommand
*, ttc
))
2595 struct Window
*tw
= NULL
;
2596 struct TextFont
*of
;
2597 struct RastPort
*rp
;
2601 struct BaseInfo
*bi
;
2603 switch (ttc
->ttc_Command
)
2606 wd
= (WD
*)ttc
->ttc_UserData
;
2609 * Does the tip-object have a tool-tip?
2612 Get_Attr(ttc
->ttc_Object
, BT_ToolTip
, (IPTR
*)&tc
);
2616 * Copy and setup the tip.
2618 if ((tip
= (UBYTE
*)BGUI_AllocPoolMem(strlen(tc
) + 10)))
2623 } __packed args
= { BARDETAILPEN
, tc
};
2624 DoSPrintF(tip
, "\033d%ld%s", (RAWARG
)&args
);
2632 rp
= wd
->wd_WindowPtr
->RPort
;
2638 FSetFont(rp
, wd
->wd_UsedFont
);
2640 BGUI_InfoTextSize(rp
, tip
, (UWORD
*)&ibx
.Width
, (UWORD
*)&ibx
.Height
);
2644 * Get mouse position.
2646 x
= wd
->wd_WindowPtr
->MouseX
;
2647 y
= wd
->wd_WindowPtr
->MouseY
;
2650 * Tool-tip width and height.
2653 wh
= ibx
.Height
+ 4;
2656 * Open tool-tip window with it's
2657 * bottom right corner under the mouse.
2659 if ((tw
= OpenWindowTags(NULL
,WA_Left
, wd
->wd_WindowPtr
->LeftEdge
+ x
- ww
,
2660 WA_Top
, wd
->wd_WindowPtr
->TopEdge
+ y
- wh
,
2664 WA_Flags
, WFLG_BORDERLESS
|WFLG_RMBTRAP
,
2665 WA_CustomScreen
, wd
->wd_Screen
,
2671 if ((bi
= AllocBaseInfoDebug(__FILE__
,__LINE__
,BI_Screen
, wd
->wd_Screen
, BI_RastPort
, rp
, TAG_DONE
)))
2673 if ((bi
= AllocBaseInfo(BI_Screen
, wd
->wd_Screen
, BI_RastPort
, rp
, TAG_DONE
)))
2680 BSetFont(bi
, wd
->wd_UsedFont
);
2683 * Tip background color.
2686 BSetDPenA(bi
, BARBLOCKPEN
);
2687 BRectFill(bi
, 1, 1, ww
- 2, wh
- 2);
2690 * Tip border and text.
2692 BSetDPenA(bi
, BARDETAILPEN
);
2694 Draw(rp
, ww
- 1, 0);
2695 Draw(rp
, ww
- 1, wh
- 1);
2696 Draw(rp
, 0, wh
- 1);
2705 RenderText(bi
, tip
, &ibx
);
2713 if (tc
) BGUI_FreePoolMem(tip
);
2718 tw
= (struct Window
*)ttc
->ttc_UserData
;
2719 if (tw
) CloseWindow(tw
);
2726 static struct Hook ToolTipHook
= { {NULL
, NULL
}, (HOOKFUNC
)ToolTip_func
, NULL
, NULL
};
2730 STATIC
METHOD(WindowClassCloseTT
, Msg
, msg
)
2732 WD
*wd
= INST_DATA(cl
, obj
);
2733 struct ttCommand ttc
;
2737 ttc
.ttc_Command
= TT_HIDE
;
2738 ttc
.ttc_Object
= wd
->wd_ToolTipObject
;
2739 ttc
.ttc_UserData
= (APTR
)wd
->wd_ToolTip
;
2741 BGUI_CallHookPkt(wd
->wd_ToolTipHook
? wd
->wd_ToolTipHook
: &ToolTipHook
, (void *)obj
, (void *)&ttc
);
2743 wd
->wd_ToolX
= wd
->wd_ToolY
= -1;
2744 wd
->wd_ToolTip
= NULL
;
2752 * Handle a window's IDCMP messages.
2754 STATIC
METHOD(WindowClassIDCMP
, Msg
, msg
)
2756 struct IntuiMessage
*imsg
;
2757 struct TagItem
*attr
, *tag
;
2758 struct MenuItem
*mi
;
2760 WD
*wd
= INST_DATA(cl
, obj
);
2761 ULONG rc
= WMHI_IGNORE
, id
;
2764 struct grmWhichObject grwo
;
2765 struct ttCommand ttc
;
2767 IPTR mouseact
, inhibit
;
2770 struct Window
*w
= wd
->wd_WindowPtr
;
2776 if (!w
) return WMHI_NOMORE
;
2781 if (!(wd
->wd_Flags
& WDF_LOCKOUT
))
2784 * Are we in a drag-selection loop?
2785 * If so continue it.
2787 if (wd
->wd_Flags
& WDF_DRAGSELECT
)
2789 code
= wd
->wd_NextSelect
;
2795 * Reports on the stack?
2797 if ((id
= GetIDReport(w
)) != ~0)
2807 * Is there a message.
2809 while ((imsg
= GetIMsg(wd
)))
2817 if(!(close_tooltip
=(w
->MouseX
!= wd
->wd_ToolX
|| w
->MouseY
!= wd
->wd_ToolY
)))
2822 case IDCMP_IDCMPUPDATE
:
2823 case IDCMP_DISKINSERTED
:
2824 case IDCMP_DISKREMOVED
:
2825 case IDCMP_WBENCHMESSAGE
:
2826 case IDCMP_INTUITICKS
:
2836 * Do we have a tool-tip to close?
2839 AsmDoMethod(obj
, WM_CLOSETOOLTIP
);
2841 wd
->wd_ToolTicks
= 0;
2846 * Are we locked out?
2848 if (wd
->wd_Flags
& WDF_LOCKOUT
)
2851 * Yes. Reply this message and continue.
2853 ReplyMsg((struct Message
*)imsg
);
2858 * Call the hook for the xxxxVERIFY messages
2861 if (wd
->wd_VerifyHook
)
2863 if ((wd
->wd_VerifyHookBits
& imsg
->Class
) == imsg
->Class
)
2865 BGUI_CallHookPkt(wd
->wd_VerifyHook
, (void *)obj
, (void *)imsg
);
2866 ReplyMsg((struct Message
*)imsg
);
2872 * Call the IDCMPHook when it's available.
2875 if (wd
->wd_IDCMPHook
&& (wd
->wd_IDCMPHookBits
& imsg
->Class
))
2877 BGUI_CallHookPkt(wd
->wd_IDCMPHook
, (VOID
*)obj
, (VOID
*)imsg
);
2882 switch (imsg
->Class
)
2884 case IDCMP_SIZEVERIFY
:
2886 * Save window size and remove
2889 wd
->wd_OW
= w
->Width
;
2890 wd
->wd_OH
= w
->Height
;
2891 if (!(wd
->wd_Flags
& WDF_REMOVED
))
2893 wd
->wd_Flags
|= WDF_REMOVED
;
2894 RemoveGadget(w
, (struct Gadget
*)wd
->wd_Gadgets
);
2899 WW(kprintf("WindowClassIDCMP: received IDCMP_NEWSIZE\n"));
2901 * If we have manually removed the
2902 * master object we adjust the size
2905 if (wd
->wd_Flags
& WDF_REMOVED
)
2908 * Setup new size for the master.
2910 DoSetMethodNG(wd
->wd_Gadgets
, GA_Left
, w
->BorderLeft
,
2911 GA_Top
, w
->BorderTop
,
2912 GA_RelWidth
, -(w
->BorderLeft
+ w
->BorderRight
),
2913 GA_RelHeight
, -(w
->BorderTop
+ w
->BorderBottom
),
2916 * Put master back online.
2918 AddGadget(w
, (struct Gadget
*)wd
->wd_Gadgets
, -1);
2921 * Clear removed flag.
2923 wd
->wd_Flags
&= ~WDF_REMOVED
;
2926 * Only refresh the window when the
2927 * size actually changed.
2932 if ((w
->Width
!= wd
->wd_OW
) || (w
->Height
!= wd
->wd_OH
))
2933 RefreshWindowFrame(w
);
2937 case IDCMP_MOUSEBUTTONS
:
2938 if ((code
| IECODE_UP_PREFIX
) != SELECTUP
)
2941 * Preset GRM_WHICHOBJECT method.
2943 grwo
.MethodID
= GRM_WHICHOBJECT
;
2944 grwo
.grwo_Coords
.X
= imsg
->MouseX
;
2945 grwo
.grwo_Coords
.Y
= imsg
->MouseY
;
2947 if ((obja
= (Object
*)AsmDoMethodA(wd
->wd_Gadgets
, (Msg
)&grwo
)))
2949 Get_Attr(obja
, BT_MouseActivation
, &mouseact
);
2951 if (((mouseact
& MOUSEACT_RMB_ACTIVE
) && (code
== IECODE_RBUTTON
))
2952 || ((mouseact
& MOUSEACT_MMB_ACTIVE
) && (code
== IECODE_MBUTTON
)))
2954 SetAttrs(obja
, BT_ReportID
,
2955 ((mouseact
& MOUSEACT_RMB_REPORT
) && (code
== IECODE_RBUTTON
)) ||
2956 ((mouseact
& MOUSEACT_MMB_REPORT
) && (code
== IECODE_MBUTTON
)), TAG_DONE
);
2958 if (wd
->wd_DGMObject
)
2960 DoSetMethodNG(wd
->wd_DGMObject
, DGM_Object
, obja
, DGM_IntuiMsg
, imsg
,TAG_END
);
2961 ActivateGadget((struct Gadget
*)wd
->wd_DGMObject
, w
, NULL
);
2968 case IDCMP_MOUSEMOVE
:
2969 if (wd
->wd_WindowFlags
& WFLG_RMBTRAP
)
2972 wd
->wd_WindowPtr
->Flags
|= WFLG_RMBTRAP
;
2979 * Preset GRM_WHICHOBJECT method.
2981 grwo
.MethodID
= GRM_WHICHOBJECT
;
2982 grwo
.grwo_Coords
.X
= imsg
->MouseX
;
2983 grwo
.grwo_Coords
.Y
= imsg
->MouseY
;
2985 if ((obja
= (Object
*)AsmDoMethodA(wd
->wd_Gadgets
, (Msg
)&grwo
)))
2987 Get_Attr(obja
, BT_MouseActivation
, &mouseact
);
2991 if (mouseact
& MOUSEACT_RMB_ACTIVE
)
2993 wd
->wd_WindowPtr
->Flags
|= WFLG_RMBTRAP
;
2997 wd
->wd_WindowPtr
->Flags
&= ~WFLG_RMBTRAP
;
3003 case IDCMP_ACTIVEWINDOW
:
3007 case IDCMP_INACTIVEWINDOW
:
3011 case IDCMP_CLOSEWINDOW
:
3012 rc
= WMHI_CLOSEWINDOW
;
3015 case IDCMP_CHANGEWINDOW
:
3016 WW(kprintf("WindowClassIDCMP: received IDCMP_CHANGEWINDOW\n"));
3017 if (wd
->wd_Flags
& WDF_CONSTRAINTS
)
3019 WW(kprintf("WindowClassIDCMP: WDF_CONSTRAINTS is set\n"));
3020 WW(kprintf("WindowClassIDCMP: calling WindowLimits(%d,%d,%d,%d)\n",wd
->wd_MinW
,wd
->wd_MinH
,wd
->wd_MaxW
,wd
->wd_MaxH
));
3021 WindowLimits(w
, wd
->wd_MinW
, wd
->wd_MinH
, wd
->wd_MaxW
, wd
->wd_MaxH
);
3022 wd
->wd_Flags
&= ~WDF_CONSTRAINTS
;
3024 WW(kprintf("WindowClassIDCMP: calling WM_RELEASE\n"));
3025 AsmDoMethod(obj
, WM_RELEASE
);
3027 WW(kprintf("WindowClassIDCMP: calling WindowClassChange\n"));
3028 WindowClassChange(cl
, obj
, (Msg
)NULL
);
3031 case IDCMP_MENUPICK
:
3035 if (code
!= MENUNULL
)
3039 * Get the selected item.
3041 mi
= ItemAddress(wd
->wd_Menus
, code
);
3044 * Setup the return code ID.
3046 rc
= (IPTR
)GTMENUITEM_USERDATA(mi
);
3049 * Menu a CHECKIT item?
3051 if (mi
->Flags
& CHECKIT
)
3053 * Fix the NewMenu array to represent
3054 * any changes in the CHECKED flag.
3056 AsmDoMethod(obj
, WM_CHECKITEM
, rc
, mi
->Flags
& CHECKED
);
3058 * Set up the next item and say were
3061 if (mi
->NextSelect
!= MENUNULL
)
3063 wd
->wd_NextSelect
= mi
->NextSelect
;
3064 wd
->wd_Flags
|= WDF_DRAGSELECT
;
3069 * Drag-selecting is done.
3071 wd
->wd_Flags
&= ~WDF_DRAGSELECT
;
3074 case IDCMP_MENUHELP
:
3076 * Get the selected item.
3078 mi
= ItemAddress(wd
->wd_Menus
, code
);
3081 * Setup the return code ID.
3083 if (mi
) rc
= WMHI_MENUHELP
| (IPTR
)GTMENUITEM_USERDATA(mi
);
3092 if (wd
->wd_Flags
& WDF_CLOSEONESC
)
3094 rc
= WMHI_CLOSEWINDOW
;
3103 WindowClassHelp(cl
, obj
, NULL
);
3107 * See if this key triggers a gadget activation.
3109 rc
= KeyGadget(cl
, obj
, imsg
);
3111 * The KeyGadget() routine has already replied the message for us.
3116 case IDCMP_GADGETUP
:
3117 rc
= GADGET(imsg
->IAddress
)->GadgetID
;
3120 case IDCMP_IDCMPUPDATE
:
3122 * IDCMP_IDCMPUPDATE handles the messages from
3123 * slider, scroller objects and tab-cycling.
3125 attr
= (struct TagItem
*)imsg
->IAddress
;
3128 * GA_ID makes sure it's comes from a gadget.
3130 if ((tag
= FindTagItem(GA_ID
, attr
)))
3135 if (!FindTagItem(STRINGA_TextVal
, attr
) && !FindTagItem(STRINGA_LongVal
, attr
))
3140 if ((tabbed
= (Object
*)GetTagData(STRINGA_Tabbed
, (IPTR
)NULL
, attr
)))
3148 else if ((tabbed
= (Object
*)GetTagData(STRINGA_ShiftTabbed
, (IPTR
)NULL
, attr
)))
3156 else if ((tabbed
= (Object
*)GetTagData(WINDOW_ActNext
, (IPTR
)NULL
, attr
)))
3164 else if ((tabbed
= (Object
*)GetTagData(WINDOW_ActPrev
, (IPTR
)NULL
, attr
)))
3174 * String gadget tabbed?
3179 * Check if it's in our list.
3181 if ((tc
= GetCycleNode(wd
, tabbed
)))
3187 * Activate next or first object.
3189 if (tc
!= wd
->wd_CycleList
.cl_Last
) tc
= tc
->tc_Next
;
3190 else tc
= wd
->wd_CycleList
.cl_First
;
3195 * Activate previous or last object.
3197 if (tc
!= wd
->wd_CycleList
.cl_First
) tc
= tc
->tc_Prev
;
3198 else tc
= wd
->wd_CycleList
.cl_Last
;
3200 Get_Attr(tc
->tc_Object
, BT_Inhibit
, &inhibit
);
3201 if ((GADGET(tc
->tc_Object
)->Flags
& GFLG_DISABLED
) || inhibit
)
3203 ActivateGadget(GADGET(tc
->tc_Object
), w
, NULL
);
3209 * Update notification.
3211 UpdateNotification(wd
, attr
, id
);
3213 * Setup return code.
3220 case IDCMP_INTUITICKS
:
3221 if ( wd
->wd_ToolTip
|| ( ! wd
->wd_ToolTickTime
))
3225 * Pick up mouse coordinates.
3231 * Preset GRM_WHICHOBJECT method.
3233 grwo
.MethodID
= GRM_WHICHOBJECT
;
3234 grwo
.grwo_Coords
.X
= x
;
3235 grwo
.grwo_Coords
.Y
= y
;
3238 * Did the mouse position change?
3240 if (x
== wd
->wd_ToolX
&& y
== wd
->wd_ToolY
)
3243 * Tick delay reached?
3245 if (wd
->wd_ToolTicks
++ == wd
->wd_ToolTickTime
)
3248 * Find object under the mouse.
3250 if ((wd
->wd_ToolTipObject
= (Object
*)AsmDoMethodA(wd
->wd_Gadgets
, (Msg
)&grwo
)))
3253 * Show the tool tip.
3255 ttc
.ttc_Command
= TT_SHOW
;
3256 ttc
.ttc_Object
= wd
->wd_ToolTipObject
;
3257 ttc
.ttc_UserData
= (APTR
)wd
;
3259 wd
->wd_ToolTip
= (APTR
)BGUI_CallHookPkt(wd
->wd_ToolTipHook
? wd
->wd_ToolTipHook
: &ToolTipHook
,
3260 (void *)obj
, (void *)&ttc
);
3266 wd
->wd_ToolTicks
= 0;
3276 * Reply the original message.
3278 if (imsg
) ReplyMsg((struct Message
*)imsg
);
3279 if (rc
!= WMHI_IGNORE
) return rc
;
3289 STATIC
METHOD(WindowClassGadgetKey
, struct wmGadgetKey
*, wmg
)
3291 // WD *wd = INST_DATA(cl, obj);
3295 * Only add when the object is valid.
3297 if ((ob
= wmg
->wmgk_Object
))
3299 DoSetMethodNG(ob
, BT_Key
, wmg
->wmgk_Key
, TAG_DONE
);
3306 * Find a menu by it's ID.
3308 STATIC ASM
struct Menu
*FindMenu( REG(a0
) struct Menu
*ptr
, REG(d0
) IPTR id
)
3314 if ( id
== ( IPTR
)GTMENU_USERDATA( tmp
)) return( tmp
);
3315 tmp
= tmp
->NextMenu
;
3323 * Find a (sub)item by it's ID.
3325 STATIC ASM
struct MenuItem
*FindItem( REG(a0
) struct Menu
*ptr
, REG(d0
) IPTR id
)
3328 struct MenuItem
*item
, *sub
;
3332 if ((item
= tmp
->FirstItem
)) {
3334 if ( id
== ( IPTR
)GTMENUITEM_USERDATA( item
)) return( item
);
3335 if ((sub
= item
->SubItem
)) {
3337 if ( id
== ( IPTR
)GTMENUITEM_USERDATA( sub
)) return( sub
);
3338 sub
= sub
->NextItem
;
3341 item
= item
->NextItem
;
3344 tmp
= tmp
->NextMenu
;
3352 * Find a NewMenu by it's ID.
3354 STATIC ASM
struct NewMenu
*FindNewMenu( REG(a0
) struct NewMenu
*nm
, REG(d0
) IPTR id
)
3356 while ( nm
->nm_Type
!= NM_END
) {
3357 if ( id
== ( IPTR
)nm
->nm_UserData
) return( nm
);
3367 STATIC
METHOD(WindowClassDisableMenu
, struct wmMenuAction
*, wmma
)
3369 WD
*wd
= ( WD
* )INST_DATA( cl
, obj
);
3371 struct MenuItem
*item
;
3372 struct NewMenu
*newmenu
;
3376 * Is the window open and
3379 if ( wd
->wd_Menus
&& wd
->wd_WindowPtr
) {
3383 ClearMenuStrip( wd
->wd_WindowPtr
);
3384 if ((menu
= FindMenu( wd
->wd_Menus
, wmma
->wmma_MenuID
))) {
3386 * Change the menu status.
3388 if ( wmma
->wmma_Set
) menu
->Flags
&= ~MENUENABLED
;
3389 else menu
->Flags
|= MENUENABLED
;
3390 } else if ((item
= FindItem( wd
->wd_Menus
, wmma
->wmma_MenuID
))) {
3392 * Otherwise the (sub)item status.
3394 if ( wmma
->wmma_Set
) item
->Flags
&= ~ITEMENABLED
;
3395 else item
->Flags
|= ITEMENABLED
;
3398 * Put the menus back online.
3400 ResetMenuStrip( wd
->wd_WindowPtr
, wd
->wd_Menus
);
3404 * Also change the corresponding NewMenu accoordingly.
3406 if ( wd
->wd_MenuStrip
) {
3407 if (( newmenu
= FindNewMenu( wd
->wd_MenuStrip
, wmma
->wmma_MenuID
))) {
3409 if ( newmenu
->nm_Type
== NM_TITLE
) {
3410 if ( wmma
->wmma_Set
) newmenu
->nm_Flags
|= NM_MENUDISABLED
;
3411 else newmenu
->nm_Flags
&= ~NM_MENUDISABLED
;
3412 } else if ( newmenu
->nm_Type
!= NM_END
) {
3413 if ( wmma
->wmma_Set
) newmenu
->nm_Flags
|= NM_ITEMDISABLED
;
3414 else newmenu
->nm_Flags
&= ~NM_ITEMDISABLED
;
3424 * (Un)check an item.
3426 STATIC
METHOD(WindowClassCheckItem
, struct wmMenuAction
*,wmma
)
3428 WD
*wd
= ( WD
* )INST_DATA( cl
, obj
);
3429 struct MenuItem
*item
;
3430 struct NewMenu
*newmenu
;
3434 * Is the window open and are there menus?
3436 if ( wd
->wd_Menus
&& wd
->wd_WindowPtr
) {
3440 ClearMenuStrip( wd
->wd_WindowPtr
);
3442 * Find the item and change it's
3445 if (( item
= FindItem( wd
->wd_Menus
, wmma
->wmma_MenuID
))) {
3446 if ( wmma
->wmma_Set
) item
->Flags
|= CHECKED
;
3447 else item
->Flags
&= ~CHECKED
;
3450 * Put the menus back online.
3452 ResetMenuStrip( wd
->wd_WindowPtr
, wd
->wd_Menus
);
3456 * Change the corresponding NewMenu accoordingly.
3458 if ( wd
->wd_MenuStrip
) {
3459 if (( newmenu
= FindNewMenu( wd
->wd_MenuStrip
, wmma
->wmma_MenuID
))) {
3461 if ( wmma
->wmma_Set
) newmenu
->nm_Flags
|= CHECKED
;
3462 else newmenu
->nm_Flags
&= ~CHECKED
;
3471 * Ask for the disabled status of a menu or (sub)item.
3473 STATIC
METHOD(WindowClassMenuDisabled
, struct wmMenuQuery
*, wmmq
)
3475 struct NewMenu
*newmenu
;
3476 WD
*wd
= ( WD
* )INST_DATA( cl
, obj
);
3478 if ( wd
->wd_MenuStrip
) {
3479 if (( newmenu
= FindNewMenu( wd
->wd_MenuStrip
, wmmq
->wmmq_MenuID
))) {
3480 if ( newmenu
->nm_Type
== NM_TITLE
)
3481 return (ULONG
)(newmenu
->nm_Flags
& NM_MENUDISABLED
? 1 : 0);
3482 else if ( newmenu
->nm_Type
!= NM_END
)
3483 return (ULONG
)(newmenu
->nm_Flags
& NM_ITEMDISABLED
? 1 : 0);
3492 * Ask for the CHECKED status of a (sub)item.
3494 STATIC
METHOD(WindowClassItemChecked
, struct wmMenuQuery
*, wmmq
)
3496 struct NewMenu
*newmenu
;
3497 WD
*wd
= ( WD
* )INST_DATA( cl
, obj
);
3499 if ( wd
->wd_MenuStrip
) {
3500 if (( newmenu
= FindNewMenu( wd
->wd_MenuStrip
, wmmq
->wmmq_MenuID
)))
3501 return (ULONG
)(newmenu
->nm_Flags
& CHECKED
? 1 : 0);
3509 * Add an objects to the tab-cycle list.
3511 STATIC
METHOD(WindowClassCycleOrder
, struct wmTabCycleOrder
*, tco
)
3513 WD
*wd
= INST_DATA( cl
, obj
);
3515 Object
**ob
= &tco
->wtco_Object1
;
3519 * Cycle through list of objects.
3524 * Allocate tab-cycle node.
3526 if ((tc
= (TABCYCLE
*)BGUI_AllocPoolMem(sizeof(TABCYCLE
))))
3529 * Initialize structure.
3531 tc
->tc_Object
= *ob
;
3533 * Setup the object for tab-cycling.
3535 DoSetMethodNG( *ob
, GA_TabCycle
, TRUE
, ICA_TARGET
, ICTARGET_IDCMP
, TAG_END
);
3537 * Add it to the list.
3539 AddTail(( struct List
* )&wd
->wd_CycleList
, ( struct Node
* )tc
);
3549 * Obtain an AppMessage.
3551 STATIC
METHOD(WindowClassGetAppMsg
, Msg
, msg
)
3553 WD
*wd
= INST_DATA(cl
, obj
);
3557 * Pop a message from the App port.
3560 rc
= (IPTR
)GetMsg(wd
->wd_AppPort
);
3568 * Add a target to the update notification list.
3570 STATIC
METHOD(WindowClassAddUpdate
, struct wmAddUpdate
*, wmau
)
3572 WD
*wd
= INST_DATA(cl
, obj
);
3579 if (wmau
->wmau_Target
)
3584 if ((up
= (UPN
*)BGUI_AllocPoolMem(sizeof(UPN
))))
3589 up
->up_ID
= wmau
->wmau_SourceID
;
3590 up
->up_Target
= wmau
->wmau_Target
;
3591 up
->up_MapList
= wmau
->wmau_MapList
;
3593 * Add it to the list.
3595 AddTail((struct List
*)&wd
->wd_UpdateList
, (struct Node
*)up
);
3607 * Changes made by T.Herold: Passes task to AddIDReport
3609 STATIC
METHOD(WindowClassReportID
, struct wmReportID
*, wmri
)
3611 WD
*wd
= INST_DATA(cl
, obj
);
3616 * Get task to signal.
3618 if (wmri
->wmri_Flags
& WMRIF_TASK
)
3619 task
= wmri
->wmri_SigTask
;
3621 task
= wd
->wd_UserPort
->mp_SigTask
;
3626 if ((w
= wd
->wd_WindowPtr
))
3628 rc
= AddIDReport(w
, wmri
->wmri_ID
, task
);
3632 if (wmri
->wmri_Flags
& WMRIF_DOUBLE_CLICK
)
3634 rc
= AddIDReport(w
, wmri
->wmri_ID
, task
);
3639 if (task
) Signal(task
, (1 << wd
->wd_UserPort
->mp_SigBit
));
3646 * Get a pointer to the window that signalled us.
3648 STATIC
METHOD(WindowClassGetSigWin
, Msg
, msg
)
3650 WD
*wd
= ( WD
* )INST_DATA( cl
, obj
);
3654 * Shared message port?
3656 if ( wd
->wd_Flags
& WDF_SHARED_MSGPORT
) {
3658 * Any messages at the port?
3660 if ( wd
->wd_UserPort
->mp_MsgList
.lh_Head
->ln_Succ
)
3662 * Yes. Get the first.
3664 win
= (( struct IntuiMessage
* )wd
->wd_UserPort
->mp_MsgList
.lh_Head
)->IDCMPWindow
;
3667 * Try for the first reported ID.
3669 win
= GetFirstIDReportWindow();
3674 win
= wd
->wd_WindowPtr
;
3681 * Remove an object from the tab-cycle list.
3683 STATIC
METHOD(WindowClassRemove
, struct wmRemoveObject
*, wmro
)
3685 WD
*wd
= ( WD
* )INST_DATA( cl
, obj
);
3688 if ( wmro
->wmro_Object
) {
3689 if ( wmro
->wmro_Flags
& WMROF_CYCLE_LIST
) {
3690 if (( cyc
= GetCycleNode( wd
, wmro
->wmro_Object
))) {
3691 Remove(( struct Node
* )cyc
);
3692 BGUI_FreePoolMem( cyc
);
3703 * Secure the master gadget by removing it.
3705 STATIC
METHOD(WindowClassSecure
, Msg
, msg
)
3707 WD
*wd
= INST_DATA(cl
, obj
);
3714 if ((w
= wd
->wd_WindowPtr
))
3717 * Yes. Master gadget attached?
3719 if (!(wd
->wd_Flags
& WDF_REMOVED
))
3722 * No. Remove it now.
3724 wd
->wd_Flags
|= WDF_REMOVED
;
3725 RemoveGadget(w
, (struct Gadget
*)wd
->wd_Gadgets
);
3735 * Release the master gadget by adding it.
3737 STATIC
METHOD(WindowClassRelease
, Msg
, msg
)
3739 WD
*wd
= INST_DATA(cl
, obj
);
3743 WW(kprintf("WindowClassRelease:\n"));
3748 if ((w
= wd
->wd_WindowPtr
))
3750 WW(kprintf("WindowClassRelease: window is open\n"));
3752 * Yes. Master gadget removed?
3754 if (wd
->wd_Flags
& WDF_REMOVED
)
3756 WW(kprintf("WindowClassRelease: WDF_REMOVED set = master gadget was removed. Calling AddGadget\n"));
3758 * Put the master back on-line.
3760 AddGadget(w
, (struct Gadget
*)wd
->wd_Gadgets
, -1);
3761 WW(kprintf("WindowClassRelease: clearing WDF_REMOVED flag\n"));
3763 wd
->wd_Flags
&= ~WDF_REMOVED
;
3766 WW(kprintf("WindowClassRelease: calling RefreshGList: gad = %x\n", (struct Gadget
*)wd
->wd_Gadgets
));
3778 STATIC
METHOD(WindowClassRelayout
, Msg
, msg
)
3780 WD
*wd
= INST_DATA(cl
, obj
);
3781 WORD newl
, newt
, neww
, newh
;
3782 UWORD min_x
, min_y
, max_x
, max_y
;
3783 BOOL lock_w
= wd
->wd_Flags
& WDF_LOCK_WIDTH
;
3784 BOOL lock_h
= wd
->wd_Flags
& WDF_LOCK_HEIGHT
;
3786 struct Screen
*s
= wd
->wd_Screen
;
3788 WW(kprintf("** WindowClassRelayout\n"));
3792 if ((w
= wd
->wd_WindowPtr
))
3794 WW(kprintf("** WindowClassRelayout: window is open. calling WM_SECURE\n"));
3795 AsmDoMethod(obj
, WM_SECURE
);
3796 WW(kprintf("** WindowClassRelayout: calling WinSize\n"));
3798 if (!WinSize(wd
, &min_x
, &min_y
))
3800 AsmDoMethod(obj
, WM_RELEASE
);
3803 WW(kprintf("** WindowClassRelayout: WinSize call ok min_x = %d, min_y = %d\n", min_x
, min_y
));
3806 * Pick up old minimum width and height.
3808 max_x
= w
->MaxWidth
;
3809 max_y
= w
->MaxHeight
;
3811 if (!(wd
->wd_WindowFlags
& WFLG_BACKDROP
))
3814 * Default window position/size.
3821 if (lock_w
|| (min_x
> neww
)) neww
= min_x
;
3822 if (lock_h
|| (min_y
> newh
)) newh
= min_y
;
3825 * Find out how much we have to
3828 if ((newl
+ neww
) > s
->Width
) newl
= s
->Width
- neww
;
3829 if ((newt
+ newh
) > s
->Height
) newt
= s
->Height
- newh
;
3832 * Compute the new maximum values.
3834 if (neww
> max_x
) max_x
= neww
;
3835 if (newh
> max_y
) max_y
= newh
;
3838 * Re-size the window accoording to the master
3839 * minimum size change.
3842 WindowLimits(w
, 1, 1, -1, -1);
3844 WW(kprintf("** WindowClassRelayout: Calling ChangeWindowBox(%d,%d,%d,%d)\n",newl
,newt
,neww
,newh
));
3846 ChangeWindowBox(w
, newl
, newt
, neww
, newh
);
3848 wd
->wd_MinW
= lock_w
? neww
: min_x
;
3849 wd
->wd_MinH
= lock_h
? newh
: min_y
;
3850 wd
->wd_MaxW
= lock_w
? neww
: max_x
;
3851 wd
->wd_MaxH
= lock_h
? newh
: max_y
;
3852 WW(kprintf("** WindowClassRelayout: setting wd->wd_MinW/H to %d,%d wd->wd_MaxW/H to %d,%d\n",
3858 wd
->wd_Flags
|= WDF_CONSTRAINTS
;
3862 AsmDoMethod(obj
, WM_RELEASE
);
3871 * Find the object under the mouse.
3873 STATIC
METHOD(WindowClassWhichObject
, Msg
, msg
)
3875 WD
*wd
= INST_DATA(cl
, obj
);
3883 if ((w
= wd
->wd_WindowPtr
))
3886 * Pickup mouse coords.
3894 if ((mx
>= 0) && (my
>= 0) && (mx
< w
->Width
) && (my
< w
->Height
))
3896 * Let's see what the master returns to us.
3900 rc
= AsmDoMethod(wd
->wd_Gadgets
, GRM_WHICHOBJECT
, mx
, my
);
3902 rc
= AsmDoMethod(wd
->wd_Gadgets
, GRM_WHICHOBJECT
, (mx
<< 16) | my
);
3909 /// WM_LOCK, WM_UNLOCK
3911 STATIC
METHOD(WindowClassLock
, Msg
, msg
)
3913 WD
*wd
= INST_DATA(cl
, obj
);
3918 if (msg
->MethodID
== WM_LOCK
) wd
->wd_Flags
|= WDF_LOCKOUT
;
3919 else wd
->wd_Flags
&= ~WDF_LOCKOUT
;
3927 * Which object has the proper key?
3929 STATIC
METHOD(WindowClassFindKey
, struct bmFindKey
*, bmfk
)
3931 WD
*wd
= INST_DATA(cl
, obj
);
3934 if ((gr
= wd
->wd_Gadgets
))
3936 if ((ob
= (Object
*)AsmDoMethodA(gr
, (Msg
)bmfk
)))
3939 if ((gr
= wd
->wd_LBorder
))
3941 if ((ob
= (Object
*)AsmDoMethodA(gr
, (Msg
)bmfk
)))
3944 if ((gr
= wd
->wd_RBorder
))
3946 if ((ob
= (Object
*)AsmDoMethodA(gr
, (Msg
)bmfk
)))
3949 if ((gr
= wd
->wd_TBorder
))
3951 if ((ob
= (Object
*)AsmDoMethodA(gr
, (Msg
)bmfk
)))
3954 if ((gr
= wd
->wd_BBorder
))
3956 if ((ob
= (Object
*)AsmDoMethodA(gr
, (Msg
)bmfk
)))
3965 * Attach label keys to object.
3967 STATIC
METHOD(WindowClassKeyLabel
, struct bmKeyLabel
*, bmkl
)
3969 WD
*wd
= INST_DATA(cl
, obj
);
3972 if ((gr
= wd
->wd_Gadgets
)) AsmDoMethodA(gr
, (Msg
)bmkl
);
3973 if ((gr
= wd
->wd_LBorder
)) AsmDoMethodA(gr
, (Msg
)bmkl
);
3974 if ((gr
= wd
->wd_RBorder
)) AsmDoMethodA(gr
, (Msg
)bmkl
);
3975 if ((gr
= wd
->wd_TBorder
)) AsmDoMethodA(gr
, (Msg
)bmkl
);
3976 if ((gr
= wd
->wd_BBorder
)) AsmDoMethodA(gr
, (Msg
)bmkl
);
3986 STATIC
METHOD(WindowClassLocalize
, struct bmLocalize
*, bml
)
3988 WD
*wd
= INST_DATA(cl
, obj
);
3991 if ((gr
= wd
->wd_Gadgets
)) AsmDoMethodA(gr
, (Msg
)bml
);
3992 if ((gr
= wd
->wd_LBorder
)) AsmDoMethodA(gr
, (Msg
)bml
);
3993 if ((gr
= wd
->wd_RBorder
)) AsmDoMethodA(gr
, (Msg
)bml
);
3994 if ((gr
= wd
->wd_TBorder
)) AsmDoMethodA(gr
, (Msg
)bml
);
3995 if ((gr
= wd
->wd_BBorder
)) AsmDoMethodA(gr
, (Msg
)bml
);
3997 if (wd
->wd_WindowTitleID
) wd
->wd_WindowTitle
=
3998 BGUI_GetCatalogStr(bml
->bml_Locale
, wd
->wd_WindowTitleID
, wd
->wd_WindowTitle
);
4000 if (wd
->wd_ScreenTitleID
) wd
->wd_ScreenTitle
=
4001 BGUI_GetCatalogStr(bml
->bml_Locale
, wd
->wd_ScreenTitleID
, wd
->wd_ScreenTitle
);
4003 if (wd
->wd_HelpTextID
) wd
->wd_HelpText
=
4004 BGUI_GetCatalogStr(bml
->bml_Locale
, wd
->wd_HelpTextID
, wd
->wd_HelpText
);
4012 * Turn on or off buffer layering.
4014 STATIC
METHOD(WindowClassClip
, struct wmClip
*, wmc
)
4016 WD
*wd
= INST_DATA(cl
, obj
);
4017 struct RastPort
*br
= wd
->wd_BufferRP
;
4018 struct Rectangle
*cr
= wmc
->wmc_Rectangle
;
4019 struct Region
*r
= wd
->wd_Region
;
4023 if (wd
->wd_WindowPtr
&& (wl
= wd
->wd_WindowPtr
->RPort
->Layer
))
4025 InstallClipRegion(wl
, NULL
);
4027 switch (wmc
->wmc_Action
)
4029 case CLIPACTION_NONE
:
4030 if (br
&& br
->Layer
)
4032 wd
->wd_BufferLayer
= br
->Layer
;
4036 case CLIPACTION_CLEAR
:
4041 rc
= OrRectRegion(r
, cr
);
4043 case CLIPACTION_AND
:
4044 AndRectRegion(r
, cr
);
4051 InstallClipRegion(wl
, r
);
4055 if (!br
->Layer
) br
->Layer
= wd
->wd_BufferLayer
;
4056 InstallClipRegion(br
->Layer
, r
);
4064 STATIC
METHOD(WindowClassSetupGadget
, struct wmSetupGadget
*, wmsg
)
4066 WD
*wd
= INST_DATA(cl
, obj
);
4067 struct TagItem
*tstate
= wmsg
->wmsg_Tags
;
4068 struct TagItem
*tag
;
4070 while ((tag
= NextTagItem(&tstate
)))
4075 AsmDoMethod(wmsg
->wmsg_Object
, BASE_INHIBIT
, tag
->ti_Tag
);
4081 || ((wd
->wd_Flags
& WDF_AUTOASPECT
)
4082 && wd
->wd_DrawInfo
))
4084 struct TextAttr current_font
;
4091 SetFont(&rp
,wd
->wd_UsedFont
);
4092 AskFont(&rp
,¤t_font
);
4095 SetAttrs(wmsg
->wmsg_Object
,
4096 wd
->wd_UsedFont
? BT_TextAttr
: TAG_IGNORE
,¤t_font
,
4097 ((wd
->wd_Flags
& WDF_AUTOASPECT
) && wd
->wd_DrawInfo
) ? FRM_ThinFrame
: TAG_IGNORE
, ((wd
->wd_DrawInfo
->dri_Resolution
.X
/ wd
->wd_DrawInfo
->dri_Resolution
.Y
) <= 1),
4105 /// Class initialization.
4108 * Class function table.
4110 STATIC DPFUNC ClassFunc
[] = {
4111 { OM_NEW
, WindowClassNew
},
4112 { OM_SET
, WindowClassSetUpdate
},
4113 { OM_UPDATE
, WindowClassSetUpdate
},
4114 { OM_GET
, WindowClassGet
},
4115 { OM_DISPOSE
, WindowClassDispose
},
4116 { WM_OPEN
, WindowClassOpen
},
4117 { WM_CLOSE
, WindowClassClose
},
4118 { WM_SLEEP
, WindowClassSleep
},
4119 { WM_WAKEUP
, WindowClassWakeUp
},
4120 { WM_HANDLEIDCMP
, WindowClassIDCMP
},
4121 { WM_GADGETKEY
, WindowClassGadgetKey
},
4122 { WM_DISABLEMENU
, WindowClassDisableMenu
},
4123 { WM_CHECKITEM
, WindowClassCheckItem
},
4124 { WM_MENUDISABLED
, WindowClassMenuDisabled
},
4125 { WM_ITEMCHECKED
, WindowClassItemChecked
},
4126 { WM_TABCYCLE_ORDER
, WindowClassCycleOrder
},
4127 { WM_GETAPPMSG
, WindowClassGetAppMsg
},
4128 { WM_ADDUPDATE
, WindowClassAddUpdate
},
4129 { WM_REPORT_ID
, WindowClassReportID
},
4130 { WM_GET_SIGNAL_WINDOW
, WindowClassGetSigWin
},
4131 { WM_REMOVE_OBJECT
, WindowClassRemove
},
4133 { WM_SECURE
, WindowClassSecure
},
4134 { WM_RELEASE
, WindowClassRelease
},
4135 { WM_RELAYOUT
, WindowClassRelayout
},
4136 { WM_WHICHOBJECT
, WindowClassWhichObject
},
4137 { WM_LOCK
, WindowClassLock
},
4138 { WM_UNLOCK
, WindowClassLock
},
4139 { WM_CLOSETOOLTIP
, WindowClassCloseTT
},
4140 { WM_CLIP
, WindowClassClip
},
4141 { WM_SETUPGADGET
, WindowClassSetupGadget
},
4143 { BASE_FINDKEY
, WindowClassFindKey
},
4144 { BASE_KEYLABEL
, WindowClassKeyLabel
},
4145 { BASE_LOCALIZE
, WindowClassLocalize
},
4151 * Simple class initialization.
4153 makeproto Class
*InitWindowClass(void)
4155 return WindowClass
= BGUI_MakeClass(CLASS_SuperClassBGUI
, BGUI_ROOT_OBJECT
,
4156 CLASS_ObjectSize
, sizeof(WD
),
4157 CLASS_DFTable
, ClassFunc
,