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"
30 /**********************************************************************************************/
34 UWORD width
; /* width of the requester */
35 UWORD height
; /* height of the requester */
36 UWORD fontheight
; /* height of the default font */
37 UWORD fontxheight
; /* extra height */
39 WORD gadgets
; /* number of gadgets */
40 UWORD gadgetwidth
; /* width of a gadget */
43 /**********************************************************************************************/
45 static STRPTR
*buildeasyreq_makelabels(struct reqdims
*dims
,CONST_STRPTR labeltext
, APTR args
, struct IntuitionBase
*IntuitionBase
);
46 static STRPTR
buildeasyreq_formattext(CONST_STRPTR textformat
, APTR args
, APTR
*nextargptr
, struct IntuitionBase
*IntuitionBase
);
47 static BOOL
buildeasyreq_calculatedims(struct reqdims
*dims
,
51 struct IntuitionBase
*IntuitionBase
);
52 static struct Gadget
*buildeasyreq_makegadgets(struct reqdims
*dims
,
55 struct IntuitionBase
*IntuitionBase
);
56 static void buildeasyreq_draw(struct reqdims
*dims
, STRPTR text
,
57 struct Window
*win
, struct Screen
*scr
,
58 struct Gadget
*gadgets
,
59 struct IntuitionBase
*IntuitionBase
);
61 static int charsinstring(CONST_STRPTR string
, char c
);
63 /*****************************************************************************
66 #include <proto/intuition.h>
67 #include <exec/types.h>
68 #include <intuition/intuition.h>
70 AROS_LH4(struct Window
*, BuildEasyRequestArgs
,
73 AROS_LHA(struct Window
*, RefWindow
, A0
),
74 AROS_LHA(struct EasyStruct
*, easyStruct
, A1
),
75 AROS_LHA(ULONG
, IDCMP
, D0
),
76 AROS_LHA(APTR
, Args
, A3
),
79 struct IntuitionBase
*, IntuitionBase
, 99, Intuition
)
82 Opens a requester, which provides one or more choices. The control is
83 returned to the application after the requester was opened. It is
84 handled by subsequent calls to SysReqHandler() and closed by calling
88 RefWindow - A reference window. If NULL, the requester opens on
89 the default public screen.
90 easyStruct - The EasyStruct structure (<intuition/intuition.h>),
91 which describes the requester.
92 IDCMP - IDCMP flags, which should satisfy the requester, too. This is
93 useful for requesters, which want to listen to disk changes,
94 etc. Note that this is not a pointer to the flags as in
96 Args - The arguments for easyStruct->es_TextFormat.
99 Returns a pointer to the requester. Use this pointer only for calls
100 to SysReqHandler() and FreeSysRequest().
109 EasyRequestArgs(), SysReqHandler(), FreeSysRequest()
115 *****************************************************************************/
119 struct Screen
*scr
= NULL
, *lockedscr
= NULL
;
121 struct Gadget
*gadgets
;
122 CONST_STRPTR reqtitle
;
123 STRPTR formattedtext
;
124 STRPTR
*gadgetlabels
;
126 struct IntRequestUserData
*requserdata
;
129 DEBUG_BUILDEASYREQUEST(dprintf("intrequest_buildeasyrequest: window 0x%lx easystruct 0x%lx IDCMPFlags 0x%lx args 0x%lx\n",
138 DEBUG_BUILDEASYREQUEST(dprintf("intrequest_buildeasyrequest: easy title <%s> Format <%s> Gadgets <%s>\n",
139 easyStruct
->es_Title
,
140 easyStruct
->es_TextFormat
,
141 easyStruct
->es_GadgetFormat
));
143 /* get requester title */
144 reqtitle
= easyStruct
->es_Title
;
145 if ((!reqtitle
) && (RefWindow
))
146 reqtitle
= RefWindow
->Title
;
148 if (!reqtitle
) reqtitle
= "System Request"; /* stegerg: should be localized */
150 /* get screen and screendrawinfo */
152 scr
= RefWindow
->WScreen
;
156 scr
= LockPubScreen(NULL
);
163 /* create everything */
164 formattedtext
= buildeasyreq_formattext(easyStruct
->es_TextFormat
,
170 gadgetlabels
= buildeasyreq_makelabels(&dims
,
171 easyStruct
->es_GadgetFormat
,
177 if (buildeasyreq_calculatedims(&dims
, scr
,
178 formattedtext
, gadgetlabels
, IntuitionBase
))
180 gadgets
= buildeasyreq_makegadgets(&dims
, gadgetlabels
, scr
, IntuitionBase
);
183 requserdata
= AllocVec(sizeof(struct IntRequestUserData
),
184 MEMF_ANY
|MEMF_CLEAR
);
187 struct TagItem win_tags
[] =
189 { WA_Width
, dims
.width
},
190 { WA_Height
, dims
.height
},
191 { WA_Left
, - scr
->LeftEdge
+ (scr
->ViewPort
.DWidth
/2) - (dims
.width
/2) },
192 { WA_Top
, - scr
->TopEdge
+ (scr
->ViewPort
.DHeight
/2) - (dims
.height
/2)},
193 { WA_IDCMP
, IDCMP_GADGETUP
| IDCMP_RAWKEY
| (IDCMP
& ~IDCMP_VANILLAKEY
) },
194 { WA_Gadgets
, (IPTR
)gadgets
},
195 { WA_Title
, (IPTR
)reqtitle
},
196 { (lockedscr
? WA_PubScreen
: WA_CustomScreen
), (IPTR
)scr
},
197 { WA_Flags
, WFLG_DRAGBAR
|
201 WFLG_SIMPLE_REFRESH*/ },
205 req
= OpenWindowTagList(NULL
, win_tags
);
208 if (lockedscr
) UnlockPubScreen(NULL
, lockedscr
);
210 req
->UserData
= (BYTE
*)requserdata
;
211 requserdata
->IDCMP
= IDCMP
;
212 requserdata
->GadgetLabels
= gadgetlabels
;
213 requserdata
->Gadgets
= gadgets
;
214 requserdata
->NumGadgets
= dims
.gadgets
;
216 DEBUG_BUILDEASYREQUEST(dprintf("intrequest_buildeasyrequest: gadgets 0x%lx\n", (ULONG
) gadgets
));
218 buildeasyreq_draw(&dims
, formattedtext
,
219 req
, scr
, gadgets
, IntuitionBase
);
220 FreeVec(formattedtext
);
225 /* opening requester failed -> free everything */
226 FreeVec(requserdata
);
228 } /* if (requserdata) */
230 intrequest_freegadgets(gadgets
, IntuitionBase
);
234 } /* if (if (buildeasyreq_calculatedims... */
236 intrequest_freelabels(gadgetlabels
, IntuitionBase
);
238 } /* if (gadgetlabels) */
240 FreeVec(formattedtext
);
242 } /* if (formattedtext) */
244 if (lockedscr
) UnlockPubScreen(NULL
, lockedscr
);
250 } /* BuildEasyRequestArgs */
252 /**********************************************************************************************/
254 CONST UWORD BgPattern
[2] = { 0xAAAA, 0x5555 };
256 /**********************************************************************************************/
258 /* draw the contents of the requester */
259 static void buildeasyreq_draw(struct reqdims
*dims
, STRPTR text
,
260 struct Window
*req
, struct Screen
*scr
,
261 struct Gadget
*gadgets
,
262 struct IntuitionBase
*IntuitionBase
)
264 struct TagItem frame_tags
[] =
266 {IA_Left
, req
->BorderLeft
+ OUTERSPACING_X
},
267 {IA_Top
, req
->BorderTop
+ OUTERSPACING_Y
},
268 {IA_Width
, req
->Width
- req
->BorderLeft
- req
->BorderRight
- OUTERSPACING_X
* 2 },
269 {IA_Height
, req
->Height
- req
->BorderTop
- req
->BorderBottom
-
270 dims
->fontheight
- OUTERSPACING_Y
* 2 -
271 TEXTGADGETSPACING
- BUTTONBORDER_Y
* 2 },
272 {IA_Recessed
, TRUE
},
273 {IA_EdgesOnly
, FALSE
},
276 struct DrawInfo
*dri
;
280 dri
= GetScreenDrawInfo(scr
);
284 SetFont(req
->RPort
, dri
->dri_Font
);
286 /* draw background pattern */
287 SetABPenDrMd(req
->RPort
,
288 dri
->dri_Pens
[SHINEPEN
], dri
->dri_Pens
[BACKGROUNDPEN
],
290 SetAfPt(req
->RPort
, BgPattern
, 1);
291 RectFill(req
->RPort
, req
->BorderLeft
,
293 req
->Width
- req
->BorderRight
,
294 req
->Height
- req
->BorderBottom
);
295 SetAfPt(req
->RPort
, NULL
, 0);
298 frame
= (struct Image
*)NewObjectA(NULL
, FRAMEICLASS
, frame_tags
);
301 DrawImageState(req
->RPort
, frame
, 0, 0, IDS_NORMAL
, dri
);
302 DisposeObject((Object
*)frame
);
306 SetABPenDrMd(req
->RPort
,
307 dri
->dri_Pens
[TEXTPEN
], dri
->dri_Pens
[BACKGROUNDPEN
], JAM1
);
308 for (currentline
= 1; text
[0] != '\0'; currentline
++)
313 strend
= strchr(text
, '\n');
316 length
= strend
- text
;
320 length
= strlen(text
);
325 req
->BorderTop
+ (dims
->fontheight
+ dims
->fontxheight
) * (currentline
- 1) +
326 OUTERSPACING_Y
+ TEXTBOXBORDER_Y
+ req
->RPort
->Font
->tf_Baseline
);
328 Text(req
->RPort
, text
, length
);
336 RefreshGList(gadgets
, req
, NULL
, -1L);
338 FreeScreenDrawInfo(scr
, dri
);
341 /**********************************************************************************************/
343 AROS_UFH2 (void, EasyReqPutChar
,
344 AROS_UFHA(UBYTE
, chr
, D0
),
345 AROS_UFHA(UBYTE
**,buffer
,A3
)
355 /**********************************************************************************************/
357 AROS_UFH2 (void, EasyReqCountChar
,
358 AROS_UFHA(UBYTE
, chr
, D0
),
359 AROS_UFHA(ULONG
*,counter
,A3
)
364 /* shut up the compiler */
372 /* create an array of gadgetlabels */
373 static STRPTR
*buildeasyreq_makelabels(struct reqdims
*dims
,
374 CONST_STRPTR labeltext
,
376 struct IntuitionBase
*IntuitionBase
)
378 STRPTR
*gadgetlabels
;
384 /* make room for pointer-array */
385 dims
->gadgets
= charsinstring(labeltext
, '|') + 1;
387 gadgetlabels
= AllocVec((dims
->gadgets
+ 1) * sizeof(STRPTR
), MEMF_ANY
);
391 gadgetlabels
[dims
->gadgets
] = NULL
;
393 /* copy label-string */
394 RawDoFmt(labeltext
, args
, (VOID_FUNC
)AROS_ASMSYMNAME(EasyReqCountChar
), &len
);
396 label
= AllocVec(len
+ 1, MEMF_ANY
);
399 FreeVec(gadgetlabels
);
404 RawDoFmt(labeltext
, args
, (VOID_FUNC
)AROS_ASMSYMNAME(EasyReqPutChar
), &lab
);
406 /* set up the pointers and insert null-bytes */
407 for (currentgadget
= 0; currentgadget
< dims
->gadgets
; currentgadget
++)
409 gadgetlabels
[currentgadget
] = label
;
411 if (currentgadget
!= (dims
->gadgets
- 1))
413 while (label
[0] != '|')
424 /**********************************************************************************************/
426 /**********************************************************************************************/
428 /* format the supplied text string by using the supplied args */
429 static STRPTR
buildeasyreq_formattext(CONST_STRPTR textformat
,
432 struct IntuitionBase
*IntuitionBase
)
439 RawDoFmt(textformat
, args
, (VOID_FUNC
)AROS_ASMSYMNAME(EasyReqCountChar
), &len
);
441 buffer
= AllocVec(len
+ 1, MEMF_ANY
| MEMF_CLEAR
);
442 if (!buffer
) return NULL
;
445 *nextargptr
= RawDoFmt(textformat
, args
, (VOID_FUNC
)AROS_ASMSYMNAME(EasyReqPutChar
), &buf
);
453 len
= strlen(textformat
) + 256;
456 buffer
= AllocVec(len
, MEMF_ANY
);
460 if (vsnprintf(buffer
, len
, textformat
, args
) < len
)
470 /**********************************************************************************************/
472 /* calculate dimensions of the requester */
473 static BOOL
buildeasyreq_calculatedims(struct reqdims
*dims
,
475 STRPTR formattedtext
,
476 STRPTR
*gadgetlabels
,
477 struct IntuitionBase
*IntuitionBase
)
480 int textlines
, line
; /* number of lines in es_TextFormat */
481 int currentgadget
= 0;
482 UWORD textboxwidth
= 0, gadgetswidth
; /* width of upper/lower part */
484 /* calculate height of requester */
485 dims
->fontheight
= scr
->RastPort
.Font
->tf_YSize
;
486 dims
->fontxheight
= dims
->fontheight
- scr
->RastPort
.Font
->tf_Baseline
;
487 if (dims
->fontxheight
< 1) dims
->fontxheight
= 1;
489 textlines
= charsinstring(formattedtext
, '\n') + 1;
490 dims
->height
= scr
->WBorTop
+ dims
->fontheight
+ 1 +
493 textlines
* (dims
->fontheight
+ dims
->fontxheight
) - dims
->fontxheight
+
502 if (dims
->height
> scr
->Height
)
505 /* calculate width of text-box */
506 textline
= formattedtext
;
507 for (line
= 0; line
<textlines
; line
++)
509 int linelen
; /* length of current text line */
510 UWORD linewidth
; /* width (pixel) of current text line */
512 if (line
== (textlines
- 1))
513 linelen
= strlen(textline
);
517 while (textline
[linelen
] != '\n')
520 linewidth
= TextLength(&scr
->RastPort
, textline
, linelen
);
521 if (linewidth
> textboxwidth
)
522 textboxwidth
= linewidth
;
523 textline
= textline
+ linelen
+ 1;
525 textboxwidth
+= TEXTBOXBORDER_X
* 2;
527 /* calculate width of gadgets */
528 dims
->gadgetwidth
= 0;
529 while (gadgetlabels
[currentgadget
])
531 UWORD gadgetwidth
; /* width of current gadget */
533 gadgetwidth
= TextLength(&scr
->RastPort
, gadgetlabels
[currentgadget
],
534 strlen(gadgetlabels
[currentgadget
]));
535 if (gadgetwidth
> dims
->gadgetwidth
)
536 dims
->gadgetwidth
= gadgetwidth
;
539 dims
->gadgetwidth
+= BUTTONBORDER_X
* 2;
540 gadgetswidth
= (dims
->gadgetwidth
+ GADGETGADGETSPACING
) * dims
->gadgets
- GADGETGADGETSPACING
;
542 /* calculate width of requester and position of requester text */
543 dims
->textleft
= scr
->WBorLeft
+ OUTERSPACING_X
+ TEXTBOXBORDER_X
;
544 if (textboxwidth
> gadgetswidth
)
546 dims
->width
= textboxwidth
;
550 dims
->textleft
+= (gadgetswidth
- textboxwidth
) / 2;
551 dims
->width
= gadgetswidth
;
553 dims
->width
+= OUTERSPACING_X
* 2 + scr
->WBorLeft
+ scr
->WBorRight
;
555 if (dims
->width
> scr
->Width
)
561 /**********************************************************************************************/
563 /* make all the gadgets */
564 static struct Gadget
*buildeasyreq_makegadgets(struct reqdims
*dims
,
565 STRPTR
*gadgetlabels
,
567 struct IntuitionBase
*IntuitionBase
)
569 struct TagItem frame_tags
[] =
571 {IA_FrameType
, FRAME_BUTTON
},
572 {IA_Width
, dims
->gadgetwidth
},
573 {IA_Height
, dims
->fontheight
+ BUTTONBORDER_Y
* 2 },
576 struct Gadget
*gadgetlist
, *thisgadget
= NULL
;
577 struct Image
*gadgetframe
;
579 UWORD xoffset
, spacing
;
580 struct DrawInfo
*dri
;
582 if (gadgetlabels
[0] == NULL
)
585 gadgetframe
= (struct Image
*)NewObjectA(NULL
, FRAMEICLASS
, frame_tags
);
589 spacing
= dims
->width
- scr
->WBorLeft
- scr
->WBorRight
- OUTERSPACING_X
* 2;
590 xoffset
= scr
->WBorLeft
+ OUTERSPACING_X
;
592 if (dims
->gadgets
== 1)
593 xoffset
+= (spacing
- dims
->gadgetwidth
) / 2;
595 spacing
= (spacing
- dims
->gadgetwidth
) / (dims
->gadgets
- 1);
597 dri
= GetScreenDrawInfo(scr
);
601 for (currentgadget
= 0; gadgetlabels
[currentgadget
]; currentgadget
++)
603 WORD gadgetid
= (currentgadget
== (dims
->gadgets
- 1)) ? 0 : currentgadget
+ 1;
604 struct TagItem gad_tags
[] =
607 {GA_Previous
, (IPTR
)thisgadget
},
608 {GA_Left
, xoffset
},
609 {GA_Top
, dims
->height
-
610 scr
->WBorBottom
- dims
->fontheight
-
611 OUTERSPACING_Y
- BUTTONBORDER_Y
* 2 },
612 {GA_Image
, (IPTR
)gadgetframe
},
613 {GA_RelVerify
, TRUE
},
614 {GA_DrawInfo
, (IPTR
)dri
},
617 struct TagItem gad2_tags
[] =
619 {GA_Text
, (IPTR
)gadgetlabels
[currentgadget
] },
623 thisgadget
= NewObjectA(NULL
, FRBUTTONCLASS
, gad_tags
);
625 if (currentgadget
== 0)
626 gadgetlist
= thisgadget
;
630 intrequest_freegadgets(gadgetlist
, IntuitionBase
);
634 SetAttrsA(thisgadget
, gad2_tags
);
639 FreeScreenDrawInfo(scr
, dri
);
644 /**********************************************************************************************/
646 static int charsinstring(CONST_STRPTR string
, char c
)
659 /**********************************************************************************************/