fix properties
[AROS.git] / rom / intuition / buildeasyrequestargs_aros.c
bloba1c946343c57355273c23fbfbf3d9fa8a691ddc3
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 Copyright © 2001-2003, The MorphOS Development Team. All Rights Reserved.
4 $Id$
5 */
7 #define DEBUG_BUILDEASYREQUEST(x) D(x);
9 /**********************************************************************************************/
11 #include <stdio.h>
12 #include <stdarg.h>
13 #include <string.h>
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 /**********************************************************************************************/
32 struct reqdims
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 */
38 UWORD textleft;
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,
48 struct Screen *scr,
49 STRPTR formattedtext,
50 STRPTR *gadgetlabels,
51 struct IntuitionBase *IntuitionBase);
52 static struct Gadget *buildeasyreq_makegadgets(struct reqdims *dims,
53 STRPTR *gadgetlabels,
54 struct Screen *scr,
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 /*****************************************************************************
65 NAME */
66 #include <proto/intuition.h>
67 #include <exec/types.h>
68 #include <intuition/intuition.h>
70 AROS_LH4(struct Window *, BuildEasyRequestArgs,
72 /* SYNOPSIS */
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),
78 /* LOCATION */
79 struct IntuitionBase *, IntuitionBase, 99, Intuition)
81 /* FUNCTION
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
85 FreeSysRequest().
87 INPUTS
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
95 EasyRequestArgs().
96 Args - The arguments for easyStruct->es_TextFormat.
98 RESULT
99 Returns a pointer to the requester. Use this pointer only for calls
100 to SysReqHandler() and FreeSysRequest().
102 NOTES
104 EXAMPLE
106 BUGS
108 SEE ALSO
109 EasyRequestArgs(), SysReqHandler(), FreeSysRequest()
111 INTERNALS
113 HISTORY
115 *****************************************************************************/
117 AROS_LIBFUNC_INIT
119 struct Screen *scr = NULL, *lockedscr = NULL;
120 struct Window *req;
121 struct Gadget *gadgets;
122 CONST_STRPTR reqtitle;
123 STRPTR formattedtext;
124 STRPTR *gadgetlabels;
125 struct reqdims dims;
126 struct IntRequestUserData *requserdata;
127 APTR nextarg;
129 DEBUG_BUILDEASYREQUEST(dprintf("intrequest_buildeasyrequest: window 0x%lx easystruct 0x%lx IDCMPFlags 0x%lx args 0x%lx\n",
130 (ULONG) RefWindow,
131 (ULONG) easyStruct,
132 IDCMP,
133 (ULONG) Args));
135 if (!easyStruct)
136 return FALSE;
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 */
151 if (RefWindow)
152 scr = RefWindow->WScreen;
154 if (!scr)
156 scr = LockPubScreen(NULL);
157 if (!scr)
158 return FALSE;
160 lockedscr = scr;
163 /* create everything */
164 formattedtext = buildeasyreq_formattext(easyStruct->es_TextFormat,
165 Args,
166 &nextarg,
167 IntuitionBase);
168 if (formattedtext)
170 gadgetlabels = buildeasyreq_makelabels(&dims,
171 easyStruct->es_GadgetFormat,
172 nextarg,
173 IntuitionBase);
175 if(gadgetlabels)
177 if (buildeasyreq_calculatedims(&dims, scr,
178 formattedtext, gadgetlabels, IntuitionBase))
180 gadgets = buildeasyreq_makegadgets(&dims, gadgetlabels, scr, IntuitionBase);
181 if (gadgets)
183 requserdata = AllocVec(sizeof(struct IntRequestUserData),
184 MEMF_ANY|MEMF_CLEAR);
185 if (requserdata)
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 |
198 WFLG_DEPTHGADGET |
199 WFLG_ACTIVATE |
200 WFLG_RMBTRAP /*|
201 WFLG_SIMPLE_REFRESH*/ },
202 {TAG_DONE }
205 req = OpenWindowTagList(NULL, win_tags);
206 if (req)
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);
222 return req;
225 /* opening requester failed -> free everything */
226 FreeVec(requserdata);
228 } /* if (requserdata) */
230 intrequest_freegadgets(gadgets, IntuitionBase);
232 } /* if (gadgets) */
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);
246 return NULL;
248 AROS_LIBFUNC_EXIT
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 },
274 {TAG_DONE }
276 struct DrawInfo *dri;
277 struct Image *frame;
278 LONG currentline;
280 dri = GetScreenDrawInfo(scr);
281 if (!dri)
282 return;
284 SetFont(req->RPort, dri->dri_Font);
286 /* draw background pattern */
287 SetABPenDrMd(req->RPort,
288 dri->dri_Pens[SHINEPEN], dri->dri_Pens[BACKGROUNDPEN],
289 JAM1);
290 SetAfPt(req->RPort, BgPattern, 1);
291 RectFill(req->RPort, req->BorderLeft,
292 req->BorderTop,
293 req->Width - req->BorderRight,
294 req->Height - req->BorderBottom);
295 SetAfPt(req->RPort, NULL, 0);
297 /* draw textframe */
298 frame = (struct Image *)NewObjectA(NULL, FRAMEICLASS, frame_tags);
299 if (frame)
301 DrawImageState(req->RPort, frame, 0, 0, IDS_NORMAL, dri);
302 DisposeObject((Object *)frame);
305 /* draw text */
306 SetABPenDrMd(req->RPort,
307 dri->dri_Pens[TEXTPEN], dri->dri_Pens[BACKGROUNDPEN], JAM1);
308 for (currentline = 1; text[0] != '\0'; currentline++)
310 STRPTR strend;
311 int length;
313 strend = strchr(text, '\n');
314 if (strend)
316 length = strend - text;
318 else
320 length = strlen(text);
323 Move(req->RPort,
324 dims->textleft,
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);
330 text += length;
331 if (text[0] == '\n')
332 text++;
335 /* draw gadgets */
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)
348 AROS_USERFUNC_INIT
350 *(*buffer)++=chr;
352 AROS_USERFUNC_EXIT
355 /**********************************************************************************************/
357 AROS_UFH2 (void, EasyReqCountChar,
358 AROS_UFHA(UBYTE, chr, D0),
359 AROS_UFHA(ULONG *,counter,A3)
362 AROS_USERFUNC_INIT
364 /* shut up the compiler */
365 chr = chr;
367 (*counter)++;
369 AROS_USERFUNC_EXIT
372 /* create an array of gadgetlabels */
373 static STRPTR *buildeasyreq_makelabels(struct reqdims *dims,
374 CONST_STRPTR labeltext,
375 APTR args,
376 struct IntuitionBase *IntuitionBase)
378 STRPTR *gadgetlabels;
379 STRPTR label, lab;
380 int currentgadget;
381 ULONG len = 0;
384 /* make room for pointer-array */
385 dims->gadgets = charsinstring(labeltext, '|') + 1;
387 gadgetlabels = AllocVec((dims->gadgets + 1) * sizeof(STRPTR), MEMF_ANY);
388 if (!gadgetlabels)
389 return NULL;
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);
397 if (!label)
399 FreeVec(gadgetlabels);
400 return NULL;
403 lab = label;
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] != '|')
414 label++;
416 label[0] = '\0';
417 label++;
421 return gadgetlabels;
424 /**********************************************************************************************/
426 /**********************************************************************************************/
428 /* format the supplied text string by using the supplied args */
429 static STRPTR buildeasyreq_formattext(CONST_STRPTR textformat,
430 APTR args,
431 APTR *nextargptr,
432 struct IntuitionBase *IntuitionBase)
434 #if 1
435 STRPTR buffer;
436 STRPTR buf;
437 ULONG len = 0;
439 RawDoFmt(textformat, args, (VOID_FUNC)AROS_ASMSYMNAME(EasyReqCountChar), &len);
441 buffer = AllocVec(len + 1, MEMF_ANY | MEMF_CLEAR);
442 if (!buffer) return NULL;
444 buf = buffer;
445 *nextargptr = RawDoFmt(textformat, args, (VOID_FUNC)AROS_ASMSYMNAME(EasyReqPutChar), &buf);
447 return buffer;
449 #else
450 int len;
451 STRPTR buffer;
453 len = strlen(textformat) + 256;
454 for (;;)
456 buffer = AllocVec(len, MEMF_ANY);
457 if (!buffer)
458 return NULL;
460 if (vsnprintf(buffer, len, textformat, args) < len)
461 return buffer;
463 FreeVec(buffer);
464 len += 256;
466 #endif
470 /**********************************************************************************************/
472 /* calculate dimensions of the requester */
473 static BOOL buildeasyreq_calculatedims(struct reqdims *dims,
474 struct Screen *scr,
475 STRPTR formattedtext,
476 STRPTR *gadgetlabels,
477 struct IntuitionBase *IntuitionBase)
479 STRPTR textline;
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 +
491 OUTERSPACING_Y +
492 TEXTBOXBORDER_Y +
493 textlines * (dims->fontheight + dims->fontxheight) - dims->fontxheight +
494 TEXTBOXBORDER_Y +
495 TEXTGADGETSPACING +
496 BUTTONBORDER_Y +
497 dims->fontheight +
498 BUTTONBORDER_Y +
499 OUTERSPACING_Y +
500 scr->WBorBottom;
502 if (dims->height > scr->Height)
503 return FALSE;
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);
514 else
516 linelen = 0;
517 while (textline[linelen] != '\n')
518 linelen++;
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;
537 currentgadget++;
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;
548 else
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)
556 return FALSE;
558 return TRUE;
561 /**********************************************************************************************/
563 /* make all the gadgets */
564 static struct Gadget *buildeasyreq_makegadgets(struct reqdims *dims,
565 STRPTR *gadgetlabels,
566 struct Screen *scr,
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 },
574 {TAG_DONE }
576 struct Gadget *gadgetlist, *thisgadget = NULL;
577 struct Image *gadgetframe;
578 WORD currentgadget;
579 UWORD xoffset, spacing;
580 struct DrawInfo *dri;
582 if (gadgetlabels[0] == NULL)
583 return NULL;
585 gadgetframe = (struct Image *)NewObjectA(NULL, FRAMEICLASS, frame_tags);
586 if (!gadgetframe)
587 return NULL;
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;
594 else
595 spacing = (spacing - dims->gadgetwidth) / (dims->gadgets - 1);
597 dri = GetScreenDrawInfo(scr);
599 gadgetlist = NULL;
601 for (currentgadget = 0; gadgetlabels[currentgadget]; currentgadget++)
603 WORD gadgetid = (currentgadget == (dims->gadgets - 1)) ? 0 : currentgadget + 1;
604 struct TagItem gad_tags[] =
606 {GA_ID , gadgetid },
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 },
615 {TAG_DONE }
617 struct TagItem gad2_tags[] =
619 {GA_Text , (IPTR)gadgetlabels[currentgadget] },
620 {TAG_DONE }
623 thisgadget = NewObjectA(NULL, FRBUTTONCLASS, gad_tags);
625 if (currentgadget == 0)
626 gadgetlist = thisgadget;
628 if (!thisgadget)
630 intrequest_freegadgets(gadgetlist, IntuitionBase);
631 return NULL;
634 SetAttrsA(thisgadget, gad2_tags);
636 xoffset += spacing;
639 FreeScreenDrawInfo(scr, dri);
641 return gadgetlist;
644 /**********************************************************************************************/
646 static int charsinstring(CONST_STRPTR string, char c)
648 int count = 0;
650 while (string[0])
652 if (string[0] == c)
653 count++;
654 string++;
656 return count;
659 /**********************************************************************************************/