2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
3 Copyright © 2001-2003, The MorphOS Development Team. All Rights Reserved.
7 #define DEBUG_BUILDSYSREQUEST(x)
8 #define DEBUG_FREESYSREQUEST(x)
9 #define DEBUG_SYSREQHANDLER(x)
11 /**********************************************************************************************/
12 #include <proto/exec.h>
13 #include <proto/intuition.h>
14 #include <proto/graphics.h>
15 #include <proto/keymap.h>
16 #include <proto/utility.h>
20 #include <clib/macros.h>
21 #include <exec/memory.h>
22 #include <intuition/gadgetclass.h>
23 #include <intuition/imageclass.h>
24 #include <intuition/screens.h>
25 #include <graphics/rastport.h>
26 #include <graphics/gfxmacros.h>
27 #include <utility/tagitem.h>
28 #include "intuition_intern.h"
30 extern UWORD BgPattern
[];
32 /**********************************************************************************************/
36 UWORD width
; /* width of the requester */
37 UWORD height
; /* height of the requester */
38 UWORD fontheight
; /* height of the default font */
40 int gadgets
; /* number of gadgets */
41 UWORD gadgetwidth
; /* width of a gadget */
44 /**********************************************************************************************/
46 static BOOL
buildsysreq_calculatedims(struct sysreqdims
*dims
,
48 struct IntuiText
*itext
,
50 struct IntuitionBase
*IntuitionBase
);
51 static struct Gadget
*buildsysreq_makegadgets(struct sysreqdims
*dims
,
54 struct IntuitionBase
*IntuitionBase
);
55 static void buildsysreq_draw(struct sysreqdims
*dims
, struct IntuiText
*itext
,
56 struct Window
*win
, struct Screen
*scr
,
57 struct Gadget
*gadgets
,
58 struct IntuitionBase
*IntuitionBase
);
60 static void ReqITextSize(struct Screen
*scr
, struct IntuiText
*itext
,
61 WORD
*width
, WORD
*height
,
62 struct IntuitionBase
*IntuitionBase
);
64 static void ReqPrintIText(struct Screen
*scr
, struct DrawInfo
*dri
,
65 struct RastPort
*rp
, struct IntuiText
*itext
, WORD x
, WORD y
,
66 struct IntuitionBase
*IntuitionBase
);
68 /**********************************************************************************************/
70 struct Window
*buildsysreq_intern(struct Window
*window
, STRPTR reqtitle
, struct IntuiText
*bodytext
,
71 struct IntuiText
*postext
, struct IntuiText
*negtext
,
72 ULONG IDCMPFlags
, WORD width
, WORD height
, struct IntuitionBase
*IntuitionBase
)
74 struct Screen
*scr
= NULL
, *lockedscr
= NULL
;
76 struct Gadget
*gadgets
;
77 STRPTR gadgetlabels
[3];
78 struct sysreqdims dims
;
79 struct IntRequestUserData
*requserdata
;
81 DEBUG_BUILDSYSREQUEST(dprintf("intrequest_buildsysrequest: window 0x%p body <%s> postext <%s> negtext <%s> IDCMPFlags 0x%lx width %ld height %ld\n",
83 bodytext
? (char *) bodytext
->IText
: "<NULL>",
84 (postext
&& postext
->IText
) ? (char *) postext
->IText
: "<NULL>",
85 (negtext
&& negtext
->IText
) ? (char *) negtext
->IText
: "<NULL>",
90 /* negtext and bodytest must be specified, postext is optional */
91 if (!negtext
|| !bodytext
) return NULL
;
93 /* get requester title */
95 reqtitle
= window
? window
->Title
: (STRPTR
)"System Request"; /* stegerg: should be localized */
97 /* get screen and screendrawinfo */
99 scr
= window
->WScreen
;
102 scr
= LockPubScreen(NULL
);
112 gadgetlabels
[0] = postext
->IText
;
113 gadgetlabels
[1] = negtext
->IText
;
114 gadgetlabels
[2] = NULL
;
120 gadgetlabels
[0] = negtext
->IText
;
121 gadgetlabels
[1] = NULL
;
124 /* EXPERIMENTAL: Obey user-supplied size if the text fits into it. Processed in buildsysreq_calculatedims().
125 This is experimental. Currently DisplayAlert() relies on ability to specify requester size.
126 Requester size actually determines inner text box size - sonic. */
128 dims
.height
= height
;
130 /* create everything */
132 if (buildsysreq_calculatedims(&dims
, scr
,
133 bodytext
, gadgetlabels
, IntuitionBase
))
135 gadgets
= buildsysreq_makegadgets(&dims
, gadgetlabels
, scr
, IntuitionBase
);
136 DEBUG_BUILDSYSREQUEST(dprintf("intrequest_buildsysrequest: gadgets 0x%p\n", gadgets
));
139 requserdata
= AllocVec(sizeof(struct IntRequestUserData
),
140 MEMF_ANY
|MEMF_CLEAR
);
141 DEBUG_BUILDSYSREQUEST(dprintf("intrequest_buildsysrequest: requserdata 0x%p\n", requserdata
));
144 struct TagItem win_tags
[] =
146 {WA_Width
, dims
.width
},
147 {WA_Height
, dims
.height
},
148 {WA_Left
, (scr
->Width
/2) - (dims
.width
/2) },
149 {WA_Top
, (scr
->Height
/2) - (dims
.height
/2) },
150 {WA_IDCMP
, (IDCMP_GADGETUP
| IDCMP_RAWKEY
| (IDCMPFlags
& ~IDCMP_VANILLAKEY
))},
151 {WA_Gadgets
, (IPTR
)gadgets
},
152 {WA_Title
, (IPTR
)reqtitle
},
153 {(lockedscr
? WA_PubScreen
: WA_CustomScreen
) , (IPTR
)scr
},
154 {WA_Flags
, WFLG_DRAGBAR
|
158 WFLG_SIMPLE_REFRESH*/ },
162 req
= OpenWindowTagList(NULL
, win_tags
);
163 DEBUG_BUILDSYSREQUEST(dprintf("intrequest_buildsysrequest: req 0x%p\n", req
));
166 if (lockedscr
) UnlockPubScreen(NULL
, lockedscr
);
168 req
->UserData
= (BYTE
*)requserdata
;
169 requserdata
->IDCMP
= IDCMPFlags
;
170 requserdata
->GadgetLabels
= NULL
;
171 requserdata
->Gadgets
= gadgets
;
172 requserdata
->NumGadgets
= dims
.gadgets
;
173 buildsysreq_draw(&dims
, bodytext
,
174 req
, scr
, gadgets
, IntuitionBase
);
175 DEBUG_BUILDSYSREQUEST(dprintf("intrequest_buildsysrequest: gadgets 0x%p\n", gadgets
));
180 /* opening requester failed -> free everything */
181 FreeVec(requserdata
);
183 intrequest_freegadgets(gadgets
, IntuitionBase
);
187 if (lockedscr
) UnlockPubScreen(NULL
, lockedscr
);
192 /**********************************************************************************************/
194 LONG
sysreqhandler_intern(struct Window
*window
, ULONG
*IDCMPFlagsPtr
, BOOL WaitInput
, struct IntuitionBase
*IntuitionBase
)
196 struct IntuiMessage
*msg
;
199 DEBUG_SYSREQHANDLER(dprintf("SysReqHandler: window 0x%lx IDCMPPtr 0x%lx WaitInput 0x%lx\n",
201 (ULONG
) IDCMPFlagsPtr
,
208 else if (window
== (struct Window
*)1)
218 WaitPort(window
->UserPort
);
220 while ((msg
= (struct IntuiMessage
*)GetMsg(window
->UserPort
)))
222 DEBUG_SYSREQHANDLER(dprintf("SysReqHandler: msg 0x%lx class 0x%lx\n", (ULONG
) msg
, msg
->Class
));
225 /* we don't use VANILLA (filtered from useridcmp!) to get
226 all events we need */
231 struct InputEvent ie
;
232 char rawbuffer
[RKBUFLEN
];
234 ie
.ie_Class
= IECLASS_RAWKEY
;
236 ie
.ie_Code
= msg
->Code
;
238 ie
.ie_EventAddress
= (APTR
*) *((ULONG
*)msg
->IAddress
);
240 if (KeymapBase
&& MapRawKey(&ie
,rawbuffer
,RKBUFLEN
,0))
242 if (msg
->Qualifier
& IEQUALIFIER_LCOMMAND
)
244 if (ToUpper(rawbuffer
[0]) == ToUpper(GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_ReqTrue
))
246 if (((struct IntRequestUserData
*)window
->UserData
)->NumGadgets
> 1)
256 if (ToUpper(rawbuffer
[0]) == ToUpper(GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_ReqFalse
))
266 result
= ((struct Gadget
*)msg
->IAddress
)->GadgetID
;
270 DEBUG_SYSREQHANDLER(dprintf("SysReqHandler: unknown IDCMP\n"));
273 if (msg
->Class
& ((struct IntRequestUserData
*)window
->UserData
)->IDCMP
)
275 if (IDCMPFlagsPtr
) *IDCMPFlagsPtr
= msg
->Class
;
281 ReplyMsg((struct Message
*)msg
);
283 } /* while ((msg = (struct IntuiMessage *)GetMsg(window->UserPort))) */
287 DEBUG_SYSREQHANDLER(dprintf("SysReqHandler: Result 0x%lx\n",result
));
292 /**********************************************************************************************/
294 void freesysreq_intern(struct Window
*window
, struct IntuitionBase
*IntuitionBase
)
297 struct Gadget
*gadgets
;
298 STRPTR
*gadgetlabels
;
299 struct IntRequestUserData
*requserdata
;
301 DEBUG_FREESYSREQUEST(dprintf("intrequest_freesysrequest: window 0x%lx\n", (ULONG
) window
));
303 if ((window
== NULL
) || (window
== (void *)1L))
306 scr
= window
->WScreen
;
308 requserdata
= (struct IntRequestUserData
*)window
->UserData
;
310 DEBUG_FREESYSREQUEST(dprintf("intrequest_freesysrequest: requserdata 0x%lx\n", (ULONG
) requserdata
));
312 gadgets
= requserdata
->Gadgets
;
314 DEBUG_FREESYSREQUEST(dprintf("intrequest_freesysrequest: gadgets 0x%lx\n", (ULONG
) gadgets
));
316 /* Remove gadgets before closing window to avoid conflicts with system gadgets */
317 RemoveGList(window
, gadgets
, requserdata
->NumGadgets
);
319 gadgetlabels
= requserdata
->GadgetLabels
;
321 DEBUG_FREESYSREQUEST(dprintf("intrequest_freesysrequest: gadgetlabels 0x%lx\n", (ULONG
) gadgetlabels
));
323 window
->UserData
= 0;
325 intrequest_freegadgets(gadgets
, IntuitionBase
);
326 intrequest_freelabels(gadgetlabels
, IntuitionBase
);
329 DEBUG_FREESYSREQUEST(dprintf("intrequest_freesysrequest: freeitext 0x%lx\n", (ULONG
) requserdata
->freeitext
));
330 if (requserdata
->freeitext
) intrequest_freeitext(requserdata
->Text
,IntuitionBase
);
331 if (requserdata
->backfilldata
.image
) int_FreeCustomImage(TYPE_REQUESTERCLASS
,requserdata
->dri
,IntuitionBase
);
332 if (requserdata
->Logo
) int_FreeCustomImage(TYPE_REQUESTERCLASS
,requserdata
->dri
,IntuitionBase
);
333 if (requserdata
->ReqGadgets
) FreeVec(requserdata
->ReqGadgets
);
334 if (requserdata
->dri
) FreeScreenDrawInfo(requserdata
->ReqScreen
,(struct DrawInfo
*)requserdata
->dri
);
336 FreeVec(requserdata
);
337 } /* FreeSysRequest */
339 /**********************************************************************************************/
341 /* draw the contents of the requester */
342 static void buildsysreq_draw(struct sysreqdims
*dims
, struct IntuiText
*itext
,
343 struct Window
*req
, struct Screen
*scr
,
344 struct Gadget
*gadgets
,
345 struct IntuitionBase
*IntuitionBase
)
347 struct TagItem frame_tags
[] =
349 {IA_Left
, req
->BorderLeft
+ OUTERSPACING_X
},
350 {IA_Top
, req
->BorderTop
+ OUTERSPACING_Y
},
351 {IA_Width
, req
->Width
- req
->BorderLeft
- req
->BorderRight
- OUTERSPACING_X
* 2 },
352 {IA_Height
, req
->Height
- req
->BorderTop
- req
->BorderBottom
-
353 dims
->fontheight
- OUTERSPACING_Y
* 2 -
354 TEXTGADGETSPACING
- BUTTONBORDER_Y
* 2 },
355 {IA_Recessed
, TRUE
},
356 {IA_EdgesOnly
, FALSE
},
359 struct DrawInfo
*dri
;
362 dri
= GetScreenDrawInfo(scr
);
366 SetFont(req
->RPort
, dri
->dri_Font
);
368 /* draw background pattern */
369 SetABPenDrMd(req
->RPort
,
370 dri
->dri_Pens
[SHINEPEN
], dri
->dri_Pens
[BACKGROUNDPEN
],
372 SetAfPt(req
->RPort
, BgPattern
, 1);
373 RectFill(req
->RPort
, req
->BorderLeft
,
375 req
->Width
- req
->BorderRight
,
376 req
->Height
- req
->BorderBottom
);
377 SetAfPt(req
->RPort
, NULL
, 0);
380 frame
= (struct Image
*)NewObjectA(NULL
, FRAMEICLASS
, frame_tags
);
383 DrawImageState(req
->RPort
, frame
, 0, 0, IDS_NORMAL
, dri
);
384 DisposeObject((Object
*)frame
);
388 ReqPrintIText(scr
, dri
, req
->RPort
, itext
,
389 dims
->itextleft
, req
->BorderTop
+ OUTERSPACING_Y
+ TEXTBOXBORDER_Y
,
393 RefreshGList(gadgets
, req
, NULL
, -1L);
395 FreeScreenDrawInfo(scr
, dri
);
398 /**********************************************************************************************/
400 /* calculate dimensions of the requester */
401 static BOOL
buildsysreq_calculatedims(struct sysreqdims
*dims
,
403 struct IntuiText
*itext
,
404 STRPTR
*gadgetlabels
,
405 struct IntuitionBase
*IntuitionBase
)
408 LONG currentgadget
= 0;
409 WORD itextwidth
, itextheight
;
410 UWORD textboxwidth
= 0, gadgetswidth
; /* width of upper/lower part */
413 /* calculate height of requester */
414 dims
->fontheight
= scr
->RastPort
.Font
->tf_YSize
;
416 ReqITextSize(scr
, itext
, &itextwidth
, &itextheight
, IntuitionBase
);
418 textboxheight
= scr
->WBorTop
+ dims
->fontheight
+ 1 +
431 * Ensure that text fits into requested height.
432 * Note that calculated size will override user-supplied size if the latter
433 * is not large enough, but not vice versa.
434 * This behavior is experimental. DisplayAlert() currently relies on it - sonic
435 * See also similar check for width below.
437 if (textboxheight
> dims
->height
)
438 dims
->height
= textboxheight
;
440 if (dims
->height
> scr
->Height
)
443 textboxwidth
= itextwidth
+ TEXTBOXBORDER_X
* 2;
445 /* calculate width of gadgets */
446 dims
->gadgetwidth
= 0;
447 while (gadgetlabels
[currentgadget
])
449 UWORD gadgetwidth
; /* width of current gadget */
451 gadgetwidth
= TextLength(&scr
->RastPort
, gadgetlabels
[currentgadget
],
452 strlen(gadgetlabels
[currentgadget
]));
453 if (gadgetwidth
> dims
->gadgetwidth
)
454 dims
->gadgetwidth
= gadgetwidth
;
457 dims
->gadgetwidth
+= BUTTONBORDER_X
* 2;
458 gadgetswidth
= (dims
->gadgetwidth
+ GADGETGADGETSPACING
) * dims
->gadgets
- GADGETGADGETSPACING
;
460 /* calculate width of requester and req text position */
461 dims
->itextleft
= scr
->WBorLeft
+ OUTERSPACING_X
+ TEXTBOXBORDER_X
;
462 if (textboxwidth
<= gadgetswidth
)
464 dims
->itextleft
+= (gadgetswidth
- textboxwidth
) / 2;
465 textboxwidth
= gadgetswidth
;
468 /* EXPERIMENTAL: Ensure that text fits into requested width */
469 if (textboxwidth
> dims
->width
)
470 dims
->width
= textboxwidth
;
472 dims
->width
+= OUTERSPACING_X
* 2 + scr
->WBorLeft
+ scr
->WBorRight
;
473 if (dims
->width
> scr
->Width
)
479 /**********************************************************************************************/
481 /* make all the gadgets */
482 static struct Gadget
*buildsysreq_makegadgets(struct sysreqdims
*dims
,
483 STRPTR
*gadgetlabels
,
485 struct IntuitionBase
*IntuitionBase
)
487 struct TagItem frame_tags
[] =
489 {IA_FrameType
, FRAME_BUTTON
},
490 {IA_Width
, dims
->gadgetwidth
},
491 {IA_Height
, dims
->fontheight
+ BUTTONBORDER_Y
* 2},
494 struct Gadget
*gadgetlist
, *thisgadget
= NULL
;
495 struct Image
*gadgetframe
;
497 UWORD xoffset
, restwidth
;
499 if (gadgetlabels
[0] == NULL
)
502 gadgetframe
= (struct Image
*)NewObjectA(NULL
, FRAMEICLASS
, frame_tags
);
506 restwidth
= dims
->width
- scr
->WBorLeft
- scr
->WBorRight
- OUTERSPACING_X
* 2;
507 if (dims
->gadgets
== 1)
508 xoffset
= scr
->WBorLeft
+ OUTERSPACING_X
+ (restwidth
- dims
->gadgetwidth
) / 2;
511 xoffset
= scr
->WBorLeft
+ OUTERSPACING_X
;
512 restwidth
-= dims
->gadgets
* dims
->gadgetwidth
;
517 for (currentgadget
= 0; gadgetlabels
[currentgadget
]; currentgadget
++)
519 WORD gadgetid
= (currentgadget
== (dims
->gadgets
- 1)) ? 0 : currentgadget
+ 1;
520 struct TagItem gad_tags
[] =
523 {GA_Previous
, (IPTR
)thisgadget
},
524 {GA_Left
, xoffset
},
525 {GA_Top
, dims
->height
-
526 scr
->WBorBottom
- dims
->fontheight
-
527 OUTERSPACING_Y
- BUTTONBORDER_Y
* 2 },
528 {GA_Image
, (IPTR
)gadgetframe
},
529 {GA_RelVerify
, TRUE
},
532 struct TagItem gad2_tags
[] =
534 {GA_Text
, (IPTR
)gadgetlabels
[currentgadget
] },
538 thisgadget
= NewObjectA(NULL
, FRBUTTONCLASS
, gad_tags
);
541 if (currentgadget
== 0)
542 gadgetlist
= thisgadget
;
546 intrequest_freegadgets(gadgetlist
, IntuitionBase
);
550 SetAttrsA(thisgadget
, gad2_tags
);
552 if ((currentgadget
+ 1) != dims
->gadgets
)
554 xoffset
+= dims
->gadgetwidth
+
555 restwidth
/ (dims
->gadgets
- currentgadget
- 1);
556 restwidth
-= restwidth
/ (dims
->gadgets
- currentgadget
- 1);
563 /**********************************************************************************************/
565 static void ReqITextSize(struct Screen
*scr
, struct IntuiText
*itext
,
566 WORD
*width
, WORD
*height
,
567 struct IntuitionBase
*IntuitionBase
)
576 w
= TextLength(&scr
->RastPort
, itext
->IText
, strlen(itext
->IText
));
577 h
= scr
->RastPort
.Font
->tf_YSize
;
579 if (itext
->LeftEdge
> 0) w
+= itext
->LeftEdge
;
580 if (itext
->TopEdge
> 0) h
+= itext
->TopEdge
;
582 if (w
> *width
) *width
= w
;
583 if (h
> *height
) *height
= h
;
585 itext
= itext
->NextText
;
589 /**********************************************************************************************/
591 static void ReqPrintIText(struct Screen
*scr
, struct DrawInfo
*dri
,
592 struct RastPort
*rp
, struct IntuiText
*itext
, WORD x
, WORD y
,
593 struct IntuitionBase
*IntuitionBase
)
596 SetAPen(rp
, dri
->dri_Pens
[TEXTPEN
]);
598 /* Experimental: obey font specified in supplied IntuiText structures.
599 Makes sense because coordinates specified in these structures are taken
600 into account, but i guess they are specified according to font size.
601 Currently DisplayAlert() relies on this behavior - sonic.
604 Move(rp, x + itext->LeftEdge,
605 y + itext->TopEdge + scr->RastPort.Font->tf_Baseline);
606 Text(rp, itext->IText, strlen(itext->IText));
608 itext = itext->NextText;
610 int_PrintIText(rp
, itext
, x
, y
, TRUE
, IntuitionBase
);
613 /**********************************************************************************************/