2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 Copyright © 2001-2003, The MorphOS Development Team. All Rights Reserved.
7 #define DEBUG_BUILDEASYREQUEST(x) D(x);
9 /**********************************************************************************************/
14 #include <clib/macros.h>
15 #include <aros/asmcall.h>
16 #include <proto/exec.h>
17 #include <proto/intuition.h>
18 #include <proto/graphics.h>
19 #include <exec/memory.h>
20 #include <intuition/gadgetclass.h>
21 #include <intuition/imageclass.h>
22 #include <intuition/screens.h>
23 #include <graphics/rastport.h>
24 #include <graphics/gfxmacros.h>
25 #include <utility/tagitem.h>
26 #include <aros/debug.h>
27 #include "intuition_intern.h"
29 #define OUTERSPACING_X 4
30 #define OUTERSPACING_Y 4
31 #define GADGETGADGETSPACING 8
32 #define TEXTGADGETSPACING 4
33 #define TEXTBOXBORDER_X 16
34 #define TEXTBOXBORDER_Y 4
35 #define BUTTONBORDER_X 8
36 #define BUTTONBORDER_Y 4
38 /**********************************************************************************************/
42 UWORD width
; /* width of the requester */
43 UWORD height
; /* height of the requester */
44 UWORD fontheight
; /* height of the default font */
45 UWORD fontxheight
; /* extra height */
47 WORD gadgets
; /* number of gadgets */
48 UWORD gadgetwidth
; /* width of a gadget */
51 /**********************************************************************************************/
53 static STRPTR
*buildeasyreq_makelabels(struct reqdims
*dims
,STRPTR labeltext
, APTR args
, struct IntuitionBase
*IntuitionBase
);
54 static STRPTR
buildeasyreq_formattext(STRPTR textformat
, APTR args
, APTR
*nextargptr
, struct IntuitionBase
*IntuitionBase
);
55 static BOOL
buildeasyreq_calculatedims(struct reqdims
*dims
,
59 struct IntuitionBase
*IntuitionBase
);
60 static struct Gadget
*buildeasyreq_makegadgets(struct reqdims
*dims
,
63 struct IntuitionBase
*IntuitionBase
);
64 static void buildeasyreq_draw(struct reqdims
*dims
, STRPTR text
,
65 struct Window
*win
, struct Screen
*scr
,
66 struct Gadget
*gadgets
,
67 struct IntuitionBase
*IntuitionBase
);
69 static int charsinstring(STRPTR string
, char c
);
71 /*****************************************************************************
74 #include <proto/intuition.h>
75 #include <exec/types.h>
76 #include <intuition/intuition.h>
78 AROS_LH4(struct Window
*, BuildEasyRequestArgs
,
81 AROS_LHA(struct Window
*, RefWindow
, A0
),
82 AROS_LHA(struct EasyStruct
*, easyStruct
, A1
),
83 AROS_LHA(ULONG
, IDCMP
, D0
),
84 AROS_LHA(APTR
, Args
, A3
),
87 struct IntuitionBase
*, IntuitionBase
, 99, Intuition
)
90 Opens a requester, which provides one or more choices. The control is
91 returned to the application after the requester was opened. It is
92 handled by subsequent calls to SysReqHandler() and closed by calling
96 RefWindow - A reference window. If NULL, the requester opens on
97 the default public screen.
98 easyStruct - The EasyStruct structure (<intuition/intuition.h>),
99 which describes the requester.
100 IDCMP - IDCMP flags, which should satisfy the requester, too. This is
101 useful for requesters, which want to listen to disk changes,
102 etc. Note that this is not a pointer to the flags as in
104 Args - The arguments for easyStruct->es_TextFormat.
107 Returns a pointer to the requester. Use this pointer only for calls
108 to SysReqHandler() and FreeSysRequest().
117 EasyRequestArgs(), SysReqHandler(), FreeSysRequest()
123 *****************************************************************************/
127 struct Screen
*scr
= NULL
, *lockedscr
= NULL
;
129 struct Gadget
*gadgets
;
131 STRPTR formattedtext
;
132 STRPTR
*gadgetlabels
;
134 struct IntRequestUserData
*requserdata
;
137 DEBUG_BUILDEASYREQUEST(dprintf("intrequest_buildeasyrequest: window 0x%lx easystruct 0x%lx IDCMPFlags 0x%lx args 0x%lx\n",
146 DEBUG_BUILDEASYREQUEST(dprintf("intrequest_buildeasyrequest: easy title <%s> Format <%s> Gadgets <%s>\n",
147 easyStruct
->es_Title
,
148 easyStruct
->es_TextFormat
,
149 easyStruct
->es_GadgetFormat
));
151 /* get requester title */
152 reqtitle
= easyStruct
->es_Title
;
153 if ((!reqtitle
) && (RefWindow
))
154 reqtitle
= RefWindow
->Title
;
156 if (!reqtitle
) reqtitle
= "System Request"; /* stegerg: should be localized */
158 /* get screen and screendrawinfo */
160 scr
= RefWindow
->WScreen
;
164 scr
= LockPubScreen(NULL
);
171 /* create everything */
172 formattedtext
= buildeasyreq_formattext(easyStruct
->es_TextFormat
,
178 gadgetlabels
= buildeasyreq_makelabels(&dims
,
179 easyStruct
->es_GadgetFormat
,
185 if (buildeasyreq_calculatedims(&dims
, scr
,
186 formattedtext
, gadgetlabels
, IntuitionBase
))
188 gadgets
= buildeasyreq_makegadgets(&dims
, gadgetlabels
, scr
, IntuitionBase
);
191 requserdata
= AllocVec(sizeof(struct IntRequestUserData
),
192 MEMF_ANY
|MEMF_CLEAR
);
195 struct TagItem win_tags
[] =
197 { WA_Width
, dims
.width
},
198 { WA_Height
, dims
.height
},
199 { WA_Left
, (scr
->Width
/2) - (dims
.width
/2) },
200 { WA_Top
, (scr
->Height
/2) - (dims
.height
/2) },
201 { WA_IDCMP
, IDCMP_GADGETUP
| IDCMP_RAWKEY
| (IDCMP
& ~IDCMP_VANILLAKEY
) },
202 { WA_Gadgets
, (IPTR
)gadgets
},
203 { WA_Title
, (IPTR
)reqtitle
},
204 { (lockedscr
? WA_PubScreen
: WA_CustomScreen
), (IPTR
)scr
},
205 { WA_Flags
, WFLG_DRAGBAR
|
209 WFLG_SIMPLE_REFRESH*/ },
213 req
= OpenWindowTagList(NULL
, win_tags
);
216 if (lockedscr
) UnlockPubScreen(NULL
, lockedscr
);
218 req
->UserData
= (BYTE
*)requserdata
;
219 requserdata
->IDCMP
= IDCMP
;
220 requserdata
->GadgetLabels
= gadgetlabels
;
221 requserdata
->Gadgets
= gadgets
;
222 requserdata
->NumGadgets
= dims
.gadgets
;
224 DEBUG_BUILDEASYREQUEST(dprintf("intrequest_buildeasyrequest: gadgets 0x%lx\n", (ULONG
) gadgets
));
226 buildeasyreq_draw(&dims
, formattedtext
,
227 req
, scr
, gadgets
, IntuitionBase
);
228 FreeVec(formattedtext
);
233 /* opening requester failed -> free everything */
234 FreeVec(requserdata
);
236 } /* if (requserdata) */
238 intrequest_freegadgets(gadgets
, IntuitionBase
);
242 } /* if (if (buildeasyreq_calculatedims... */
244 intrequest_freelabels(gadgetlabels
, IntuitionBase
);
246 } /* if (gadgetlabels) */
248 FreeVec(formattedtext
);
250 } /* if (formattedtext) */
252 if (lockedscr
) UnlockPubScreen(NULL
, lockedscr
);
258 } /* BuildEasyRequestArgs */
260 /**********************************************************************************************/
262 UWORD BgPattern
[2] = { 0xAAAA, 0x5555 };
264 /**********************************************************************************************/
266 /* draw the contents of the requester */
267 static void buildeasyreq_draw(struct reqdims
*dims
, STRPTR text
,
268 struct Window
*req
, struct Screen
*scr
,
269 struct Gadget
*gadgets
,
270 struct IntuitionBase
*IntuitionBase
)
272 struct TagItem frame_tags
[] =
274 {IA_Left
, req
->BorderLeft
+ OUTERSPACING_X
},
275 {IA_Top
, req
->BorderTop
+ OUTERSPACING_Y
},
276 {IA_Width
, req
->Width
- req
->BorderLeft
- req
->BorderRight
- OUTERSPACING_X
* 2 },
277 {IA_Height
, req
->Height
- req
->BorderTop
- req
->BorderBottom
-
278 dims
->fontheight
- OUTERSPACING_Y
* 2 -
279 TEXTGADGETSPACING
- BUTTONBORDER_Y
* 2 },
280 {IA_Recessed
, TRUE
},
281 {IA_EdgesOnly
, FALSE
},
284 struct DrawInfo
*dri
;
288 dri
= GetScreenDrawInfo(scr
);
292 SetFont(req
->RPort
, dri
->dri_Font
);
294 /* draw background pattern */
295 SetABPenDrMd(req
->RPort
,
296 dri
->dri_Pens
[SHINEPEN
], dri
->dri_Pens
[BACKGROUNDPEN
],
298 SetAfPt(req
->RPort
, BgPattern
, 1);
299 RectFill(req
->RPort
, req
->BorderLeft
,
301 req
->Width
- req
->BorderRight
,
302 req
->Height
- req
->BorderBottom
);
303 SetAfPt(req
->RPort
, NULL
, 0);
306 frame
= (struct Image
*)NewObjectA(NULL
, FRAMEICLASS
, frame_tags
);
309 DrawImageState(req
->RPort
, frame
, 0, 0, IDS_NORMAL
, dri
);
310 DisposeObject((Object
*)frame
);
314 SetABPenDrMd(req
->RPort
,
315 dri
->dri_Pens
[TEXTPEN
], dri
->dri_Pens
[BACKGROUNDPEN
], JAM1
);
316 for (currentline
= 1; text
[0] != '\0'; currentline
++)
321 strend
= strchr(text
, '\n');
324 length
= strend
- text
;
328 length
= strlen(text
);
333 req
->BorderTop
+ (dims
->fontheight
+ dims
->fontxheight
) * (currentline
- 1) +
334 OUTERSPACING_Y
+ TEXTBOXBORDER_Y
+ req
->RPort
->Font
->tf_Baseline
);
336 Text(req
->RPort
, text
, length
);
344 RefreshGList(gadgets
, req
, NULL
, -1L);
346 FreeScreenDrawInfo(scr
, dri
);
349 /**********************************************************************************************/
351 AROS_UFH2 (void, EasyReqPutChar
,
352 AROS_UFHA(UBYTE
, chr
, D0
),
353 AROS_UFHA(UBYTE
**,buffer
,A3
)
363 /**********************************************************************************************/
365 AROS_UFH2 (void, EasyReqCountChar
,
366 AROS_UFHA(UBYTE
, chr
, D0
),
367 AROS_UFHA(ULONG
*,counter
,A3
)
372 /* shut up the compiler */
380 /* create an array of gadgetlabels */
381 static STRPTR
*buildeasyreq_makelabels(struct reqdims
*dims
,
384 struct IntuitionBase
*IntuitionBase
)
386 STRPTR
*gadgetlabels
;
392 /* make room for pointer-array */
393 dims
->gadgets
= charsinstring(labeltext
, '|') + 1;
395 gadgetlabels
= AllocVec((dims
->gadgets
+ 1) * sizeof(STRPTR
), MEMF_ANY
);
399 gadgetlabels
[dims
->gadgets
] = NULL
;
401 /* copy label-string */
402 RawDoFmt(labeltext
, args
, (VOID_FUNC
)AROS_ASMSYMNAME(EasyReqCountChar
), &len
);
404 label
= AllocVec(len
+ 1, MEMF_ANY
);
407 FreeVec(gadgetlabels
);
412 RawDoFmt(labeltext
, args
, (VOID_FUNC
)AROS_ASMSYMNAME(EasyReqPutChar
), &lab
);
414 /* set up the pointers and insert null-bytes */
415 for (currentgadget
= 0; currentgadget
< dims
->gadgets
; currentgadget
++)
417 gadgetlabels
[currentgadget
] = label
;
419 if (currentgadget
!= (dims
->gadgets
- 1))
421 while (label
[0] != '|')
432 /**********************************************************************************************/
434 /**********************************************************************************************/
436 /* format the supplied text string by using the supplied args */
437 static STRPTR
buildeasyreq_formattext(STRPTR textformat
,
440 struct IntuitionBase
*IntuitionBase
)
447 RawDoFmt(textformat
, args
, (VOID_FUNC
)AROS_ASMSYMNAME(EasyReqCountChar
), &len
);
449 buffer
= AllocVec(len
+ 1, MEMF_ANY
| MEMF_CLEAR
);
450 if (!buffer
) return NULL
;
453 *nextargptr
= RawDoFmt(textformat
, args
, (VOID_FUNC
)AROS_ASMSYMNAME(EasyReqPutChar
), &buf
);
461 len
= strlen(textformat
) + 256;
464 buffer
= AllocVec(len
, MEMF_ANY
);
468 if (vsnprintf(buffer
, len
, textformat
, args
) < len
)
478 /**********************************************************************************************/
480 /* calculate dimensions of the requester */
481 static BOOL
buildeasyreq_calculatedims(struct reqdims
*dims
,
483 STRPTR formattedtext
,
484 STRPTR
*gadgetlabels
,
485 struct IntuitionBase
*IntuitionBase
)
488 int textlines
, line
; /* number of lines in es_TextFormat */
489 int currentgadget
= 0;
490 UWORD textboxwidth
= 0, gadgetswidth
; /* width of upper/lower part */
492 /* calculate height of requester */
493 dims
->fontheight
= scr
->RastPort
.Font
->tf_YSize
;
494 dims
->fontxheight
= dims
->fontheight
- scr
->RastPort
.Font
->tf_Baseline
;
495 if (dims
->fontxheight
< 1) dims
->fontxheight
= 1;
497 textlines
= charsinstring(formattedtext
, '\n') + 1;
498 dims
->height
= scr
->WBorTop
+ dims
->fontheight
+ 1 +
501 textlines
* (dims
->fontheight
+ dims
->fontxheight
) - dims
->fontxheight
+
510 if (dims
->height
> scr
->Height
)
513 /* calculate width of text-box */
514 textline
= formattedtext
;
515 for (line
= 0; line
<textlines
; line
++)
517 int linelen
; /* length of current text line */
518 UWORD linewidth
; /* width (pixel) of current text line */
520 if (line
== (textlines
- 1))
521 linelen
= strlen(textline
);
525 while (textline
[linelen
] != '\n')
528 linewidth
= TextLength(&scr
->RastPort
, textline
, linelen
);
529 if (linewidth
> textboxwidth
)
530 textboxwidth
= linewidth
;
531 textline
= textline
+ linelen
+ 1;
533 textboxwidth
+= TEXTBOXBORDER_X
* 2;
535 /* calculate width of gadgets */
536 dims
->gadgetwidth
= 0;
537 while (gadgetlabels
[currentgadget
])
539 UWORD gadgetwidth
; /* width of current gadget */
541 gadgetwidth
= TextLength(&scr
->RastPort
, gadgetlabels
[currentgadget
],
542 strlen(gadgetlabels
[currentgadget
]));
543 if (gadgetwidth
> dims
->gadgetwidth
)
544 dims
->gadgetwidth
= gadgetwidth
;
547 dims
->gadgetwidth
+= BUTTONBORDER_X
* 2;
548 gadgetswidth
= (dims
->gadgetwidth
+ GADGETGADGETSPACING
) * dims
->gadgets
- GADGETGADGETSPACING
;
550 /* calculate width of requester and position of requester text */
551 dims
->textleft
= scr
->WBorLeft
+ OUTERSPACING_X
+ TEXTBOXBORDER_X
;
552 if (textboxwidth
> gadgetswidth
)
554 dims
->width
= textboxwidth
;
558 dims
->textleft
+= (gadgetswidth
- textboxwidth
) / 2;
559 dims
->width
= gadgetswidth
;
561 dims
->width
+= OUTERSPACING_X
* 2 + scr
->WBorLeft
+ scr
->WBorRight
;
563 if (dims
->width
> scr
->Width
)
569 /**********************************************************************************************/
571 /* make all the gadgets */
572 static struct Gadget
*buildeasyreq_makegadgets(struct reqdims
*dims
,
573 STRPTR
*gadgetlabels
,
575 struct IntuitionBase
*IntuitionBase
)
577 struct TagItem frame_tags
[] =
579 {IA_FrameType
, FRAME_BUTTON
},
580 {IA_Width
, dims
->gadgetwidth
},
581 {IA_Height
, dims
->fontheight
+ BUTTONBORDER_Y
* 2 },
584 struct Gadget
*gadgetlist
, *thisgadget
= NULL
;
585 struct Image
*gadgetframe
;
587 UWORD xoffset
, spacing
;
588 struct DrawInfo
*dri
;
590 if (gadgetlabels
[0] == NULL
)
593 gadgetframe
= (struct Image
*)NewObjectA(NULL
, FRAMEICLASS
, frame_tags
);
597 spacing
= dims
->width
- scr
->WBorLeft
- scr
->WBorRight
- OUTERSPACING_X
* 2;
598 xoffset
= scr
->WBorLeft
+ OUTERSPACING_X
;
600 if (dims
->gadgets
== 1)
601 xoffset
+= (spacing
- dims
->gadgetwidth
) / 2;
603 spacing
= (spacing
- dims
->gadgetwidth
) / (dims
->gadgets
- 1);
605 dri
= GetScreenDrawInfo(scr
);
609 for (currentgadget
= 0; gadgetlabels
[currentgadget
]; currentgadget
++)
611 WORD gadgetid
= (currentgadget
== (dims
->gadgets
- 1)) ? 0 : currentgadget
+ 1;
612 struct TagItem gad_tags
[] =
615 {GA_Previous
, (IPTR
)thisgadget
},
616 {GA_Left
, xoffset
},
617 {GA_Top
, dims
->height
-
618 scr
->WBorBottom
- dims
->fontheight
-
619 OUTERSPACING_Y
- BUTTONBORDER_Y
* 2 },
620 {GA_Image
, (IPTR
)gadgetframe
},
621 {GA_RelVerify
, TRUE
},
622 {GA_DrawInfo
, (IPTR
)dri
},
625 struct TagItem gad2_tags
[] =
627 {GA_Text
, (IPTR
)gadgetlabels
[currentgadget
] },
631 thisgadget
= NewObjectA(NULL
, FRBUTTONCLASS
, gad_tags
);
633 if (currentgadget
== 0)
634 gadgetlist
= thisgadget
;
638 intrequest_freegadgets(gadgetlist
, IntuitionBase
);
642 SetAttrsA(thisgadget
, gad2_tags
);
647 FreeScreenDrawInfo(scr
, dri
);
652 /**********************************************************************************************/
654 static int charsinstring(STRPTR string
, char c
)
667 /**********************************************************************************************/