Fixed codesets.
[AROS.git] / rom / intuition / gadgets.c
blob0539ef57e130e3454ac17b4227c984bfec5a9a1f
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 Copyright © 2001-2003, The MorphOS Development Team. All Rights Reserved.
4 $Id$
6 Common routines for Gadgets.
7 */
9 /**********************************************************************************************/
11 #include <exec/types.h>
12 #include <proto/intuition.h>
13 #include <intuition/intuition.h>
14 #include <intuition/cghooks.h>
15 #include <intuition/classes.h>
16 #include <intuition/classusr.h>
17 #include <intuition/imageclass.h>
18 #include <proto/graphics.h>
19 #include <proto/layers.h>
20 #include <graphics/rastport.h>
21 #include <graphics/text.h>
22 #include <graphics/gfxmacros.h>
24 #include <string.h>
26 #include "intuition_intern.h"
27 #include "gadgets.h"
29 #define DEBUG_RENDERDISABLEPATTERN(x) ;
30 #define DEBUG_ERASERELGADGETAREA(x) ;
31 #define DEBUG_SETUPGINFO(x) ;
34 /**********************************************************************************************/
36 #define EG(o) ((struct ExtGadget *)o)
37 #define IM(o) ((struct Image *)o)
39 /**********************************************************************************************/
41 /* print the label of a gadget object */
43 void printgadgetlabel(Class *cl, Object *o, struct gpRender *msg,
44 struct IntuitionBase *IntuitionBase)
46 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
47 struct RastPort *rp = msg->gpr_RPort;
48 struct IBox container;
49 UWORD *pens = msg->gpr_GInfo->gi_DrInfo->dri_Pens;
50 ULONG len, x, y;
52 if (!(EG(o)->GadgetText)) return;
54 GetGadgetIBox((struct Gadget *)o, msg->gpr_GInfo, &container);
55 //dprintf("printgadgetlabel: o %p ibox %d %d %d %d\n",o,container.Left,container.Top,container.Width,container.Height);
57 SetFont(rp, msg->gpr_GInfo->gi_DrInfo->dri_Font);
59 switch (EG(o)->Flags & GFLG_LABELMASK)
61 case GFLG_LABELITEXT:
62 /* ITexts must not to be centered! */
64 /* frbuttonclass sets fg/bg/drawmode attributes */
65 int_PrintIText(rp, EG(o)->GadgetText, container.Left,container.Top, TRUE, IntuitionBase);
66 break;
68 case GFLG_LABELSTRING:
69 len = strlen ((STRPTR) EG(o)->GadgetText);
71 if (len > 0UL)
73 ULONG x;
74 ULONG y;
76 x = container.Left + (container.Width / 2);
77 x -= LabelWidth (rp,
78 (STRPTR)EG(o)->GadgetText, len, IntuitionBase) / 2;
79 y = container.Top + (container.Height / 2) +
80 rp->Font->tf_Baseline;
81 y -= rp->Font->tf_YSize / 2;
82 SetAPen (rp, pens[TEXTPEN]);
83 Move (rp, x, y);
84 RenderLabel (rp,
85 (STRPTR) EG(o)->GadgetText, len,
86 IntuitionBase);
88 break;
90 case GFLG_LABELIMAGE:
91 /* center image position */
93 x = container.Left + ((container.Width / 2) -
94 (IM(EG(o)->GadgetText)->Width / 2)) - IM(EG(o)->GadgetText)->LeftEdge;
96 y = container.Top + ((container.Height / 2) -
97 (IM(EG(o)->GadgetText)->Height / 2)) - IM(EG(o)->GadgetText)->TopEdge;
98 //dprintf("printgadgetlabel: o %p w %d h %d x %d y %d l %d t %d\n", o,IM(EG(o)->GadgetText)->Width,IM(EG(o)->GadgetText)->Height,x,y,IM(EG(o)->GadgetText)->LeftEdge,IM(EG(o)->GadgetText)->TopEdge);
100 DrawImageState(rp, IM(EG(o)->GadgetText),
101 x, y,
102 ((EG(o)->Flags & GFLG_SELECTED) ? IDS_SELECTED : IDS_NORMAL ),
103 msg->gpr_GInfo->gi_DrInfo);
104 break;
106 } /* switch (EG(o)->Flags & GFLG_LABELMASK) */
110 /**********************************************************************************************/
112 /* Calculate the size of the Bounding Box of the gadget */
113 void CalcBBox (struct Window * window, struct Requester * req, struct Gadget * gadget,
114 struct BBox * bbox)
117 GetDomGadgetIBox(gadget, window->WScreen, window, req, (struct IBox *)bbox);
119 } /* CalcBBox */
121 /**********************************************************************************************/
123 /* Figure out the size of the gadget rectangle, taking relative
124 * positioning into account.
126 VOID GetGadgetIBox(struct Gadget *g, struct GadgetInfo *gi, struct IBox *ibox)
128 ibox->Left = g->LeftEdge;
129 ibox->Top = g->TopEdge;
130 ibox->Width = g->Width;
131 ibox->Height = g->Height;
133 if (gi)
135 if (g->Flags & GFLG_RELRIGHT)
136 ibox->Left += gi->gi_Domain.Width - 1;
138 if (g->Flags & GFLG_RELBOTTOM)
139 ibox->Top += gi->gi_Domain.Height - 1;
141 if (g->Flags & GFLG_RELWIDTH)
142 ibox->Width += gi->gi_Domain.Width;
144 if (g->Flags & GFLG_RELHEIGHT)
145 ibox->Height += gi->gi_Domain.Height;
148 DEBUG_GETGADGETIBOX(dprintf("GetGadgetIBox: Gadget 0x%lx GInfo 0x%lx Flags 0x%lx Left %ld Top %ld Width %ld Height %ld\n",
149 g, gi, g->Flags, ibox->Left, ibox->Top, ibox->Width, ibox->Height));
152 /**********************************************************************************************/
154 ULONG LabelWidth (struct RastPort * rp, STRPTR label, ULONG len,
155 struct IntuitionBase * IntuitionBase)
157 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
158 ULONG totalwidth, uscorewidth;
160 totalwidth = TextLength (rp, label, len);
161 uscorewidth = TextLength (rp, "_", 1);
163 while (len && *label)
165 if (*label == '_')
166 totalwidth -= uscorewidth;
168 label ++;
169 len --;
172 return totalwidth;
175 /**********************************************************************************************/
177 void RenderLabel (struct RastPort * rp, STRPTR label, ULONG len,
178 struct IntuitionBase * IntuitionBase)
180 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
181 ULONG renderlen;
182 ULONG uscorewidth;
184 while (*label)
186 renderlen = 0;
188 while (label[renderlen] && label[renderlen] != '_')
189 renderlen ++;
191 Text (rp, label, renderlen);
193 label += renderlen;
195 if (*label) /* '_' ? */
197 WORD cx, cy;
199 label ++; /* Skip */
201 uscorewidth = TextLength (rp, label, 1);
203 cx = rp->cp_x;
204 cy = rp->cp_y;
206 Move (rp, cx, cy+2);
207 Draw (rp, cx+uscorewidth-1, cy+2);
208 Move (rp, cx, cy);
213 /**********************************************************************************************/
215 VOID drawrect(struct RastPort *rp, WORD x1, WORD y1, WORD x2, WORD y2,
216 struct IntuitionBase *IntuitionBase)
218 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
219 Move(rp, x1, y1);
221 /* We RectFill() because it is generally faster than Draw()
222 (Draw() uses Set/GetPixel() while RectFill() can do higherlevel
223 clipping. Also it is MUCH faster in the x11gfx hidd.
226 RectFill(rp, x1, y1, x2 - 1, y1); /* Top */
227 RectFill(rp, x2, y1, x2, y2 - 1); /* Right */
228 RectFill(rp, x1 + 1, y2, x2, y2); /* Bottom */
229 RectFill(rp, x1, y1 + 1, x1, y2); /* Left */
231 return;
234 /**********************************************************************************************/
236 void GetGadgetDomain(struct Gadget *gad, struct Screen *scr, struct Window *win,
237 struct Requester *req, struct IBox *box)
239 switch (gad->GadgetType & (GTYP_GADGETTYPE & ~GTYP_SYSGADGET))
241 case GTYP_SCRGADGET:
242 box->Left = 0;
243 box->Top = 0;
244 box->Width = scr->Width;
245 box->Height = scr->Height;
247 break;
249 case GTYP_GZZGADGET:
250 /* stegerg: this means gadget is in window border! */
252 box->Left = 0;
253 box->Top = 0;
254 box->Width = win->Width;
255 box->Height = win->Height;
257 break;
259 case GTYP_REQGADGET:
260 box->Left = req->LeftEdge + win->BorderLeft;
261 box->Top = req->TopEdge + win->BorderTop;
262 box->Width = req->Width;
263 box->Height = req->Height;
265 break;
267 default:
268 if (win->Flags & WFLG_GIMMEZEROZERO)
270 /* stegerg: domain.left and domain.top must not be added
271 to gadget position when it is rendered, because gadgets
272 in the innerlayer of a gzz gadget are already shifted
273 thanks to the innerlayer. */
275 box->Left = win->BorderLeft;
276 box->Top = win->BorderTop;
278 box->Width = win->Width - win->BorderLeft - win->BorderRight;
279 box->Height = win->Height - win->BorderTop - win->BorderBottom;
282 else
284 box->Left = 0;
285 box->Top = 0;
286 box->Width = win->Width;
287 box->Height = win->Height;
291 break;
293 } /* switch (gadgettype) */
296 /**********************************************************************************************/
298 WORD GetGadgetLeft(struct Gadget *gad, struct Screen *scr, struct Window *win, struct Requester *req)
300 struct IBox box;
302 GetGadgetDomain(gad, scr, win, req, &box);
304 return gad->LeftEdge + ADDREL(gad, GFLG_RELRIGHT, (&box), Width - 1);
307 /**********************************************************************************************/
309 WORD GetGadgetTop(struct Gadget *gad, struct Screen *scr, struct Window *win, struct Requester *req)
311 struct IBox box;
313 GetGadgetDomain(gad, scr, win, req, &box);
315 return gad->TopEdge + ADDREL(gad, GFLG_RELBOTTOM, (&box), Height - 1);
318 /**********************************************************************************************/
320 WORD GetGadgetWidth(struct Gadget *gad, struct Screen *scr, struct Window *win, struct Requester *req)
322 struct IBox box;
324 GetGadgetDomain(gad, scr, win, req, &box);
326 return gad->Width + ADDREL(gad, GFLG_RELWIDTH, (&box), Width);
329 /**********************************************************************************************/
331 WORD GetGadgetHeight(struct Gadget *gad, struct Screen *scr, struct Window *win, struct Requester *req)
333 struct IBox box;
335 GetGadgetDomain(gad, scr, win, req, &box);
337 return gad->Height + ADDREL(gad, GFLG_RELHEIGHT, (&box), Height);
340 /**********************************************************************************************/
342 /* gadget box in screen coords */
343 void GetScrGadgetIBox(struct Gadget *gad, struct Screen *scr, struct Window *win,
344 struct Requester *req, struct IBox *box)
346 GetWinGadgetIBox(gad, scr, win, req, box);
348 if (win)
350 box->Left += win->LeftEdge;
351 box->Top += win->TopEdge;
355 /**********************************************************************************************/
357 /* gadget box relative to upper left window edge */
358 void GetWinGadgetIBox(struct Gadget *gad, struct Screen *scr, struct Window *win,
359 struct Requester *req, struct IBox *box)
361 struct IBox domain;
363 GetGadgetDomain(gad, scr, win, req, &domain);
365 box->Left = gad->LeftEdge;
366 box->Top = gad->TopEdge;
367 box->Width = gad->Width;
368 box->Height = gad->Height;
370 if (gad->Flags & GFLG_RELRIGHT)
371 box->Left += domain.Width - 1;
373 if (gad->Flags & GFLG_RELBOTTOM)
374 box->Top += domain.Height - 1;
376 if (gad->Flags & GFLG_RELWIDTH)
377 box->Width += domain.Width;
379 if (gad->Flags & GFLG_RELHEIGHT)
380 box->Height += domain.Height;
382 box->Left += domain.Left;
383 box->Top += domain.Top;
386 /**********************************************************************************************/
388 /* gadget box in domain coords */
389 void GetDomGadgetIBox(struct Gadget *gad, struct Screen *scr, struct Window *win,
390 struct Requester *req, struct IBox *box)
392 struct IBox domain;
394 GetWinGadgetIBox(gad, scr, win, req, box);
395 GetGadgetDomain(gad, scr, win, req, &domain);
397 box->Left -= domain.Left;
398 box->Top -= domain.Top;
401 /**********************************************************************************************/
403 /* gadget bounds in screen coords */
404 void GetScrGadgetBounds(struct Gadget *gad, struct Screen *scr, struct Window *win,
405 struct Requester *req, struct IBox *box)
407 struct IBox domain;
409 if (gad->Flags & GFLG_EXTENDED)
411 if (EG(gad)->MoreFlags & GMORE_BOUNDS)
413 GetGadgetDomain(gad, scr, win, req, &domain);
415 box->Left = domain.Left +
416 EG(gad)->BoundsLeftEdge + ADDREL(gad, GFLG_RELRIGHT, (&domain), Width - 1) +
417 (win ? win->LeftEdge : 0);
419 box->Top = domain.Top +
420 EG(gad)->BoundsTopEdge + ADDREL(gad, GFLG_RELBOTTOM, (&domain), Height - 1) +
421 (win ? win->TopEdge : 0);
423 box->Width = EG(gad)->BoundsWidth + ADDREL(gad, GFLG_RELWIDTH, (&domain), Width);
425 box->Height = EG(gad)->BoundsHeight + ADDREL(gad, GFLG_RELHEIGHT, (&domain), Height);
427 return;
429 } /* if (gad->MoreFlags & GMORE_BOUNDS) */
431 } /* if (gad->Flags & GFLG_EXTENDED) */
433 /* if gadget does not have bounds return box */
435 GetScrGadgetIBox(gad, scr, win, req, box);
438 /**********************************************************************************************/
440 /* gadget bounds relative to upper left window edge */
441 void GetWinGadgetBounds(struct Gadget *gad, struct Screen *scr, struct Window *win,
442 struct Requester *req, struct IBox *box)
444 GetScrGadgetBounds(gad, scr, win, req, box);
446 if (win)
448 box->Left -= win->LeftEdge;
449 box->Top -= win->TopEdge;
453 /**********************************************************************************************/
455 /* gadget bounds in domain coords */
456 void GetDomGadgetBounds(struct Gadget *gad, struct Screen *scr, struct Window *win,
457 struct Requester *req, struct IBox *box)
459 struct IBox domain;
461 GetWinGadgetBounds(gad, scr, win, req, box);
462 GetGadgetDomain(gad, scr, win, req, &domain);
464 box->Left -= domain.Left;
465 box->Top -= domain.Top;
468 /**********************************************************************************************/
470 void EraseRelGadgetArea(struct Window *win, struct Rectangle *clipto,
471 BOOL onlydamagelist, struct IntuitionBase *IntuitionBase)
473 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
474 struct LayersBase *LayersBase = GetPrivIBase(IntuitionBase)->LayersBase;
475 struct Gadget *gad;
476 struct Region *old_clipregion = NULL; /* shut up the compiler */
477 struct RastPort *rp, *rp2;
478 struct Layer *lay;
479 struct IBox box;
480 WORD old_scroll_x = 0, old_scroll_y = 0, i, num_loops;
482 DEBUG_ERASERELGADGETAREA(dprintf("EraseRelGadgetArea: win 0x%lx onlydamage %d\n",
483 win, onlydamagelist));
485 rp = win->RPort;
486 rp2 = win->BorderRPort;
488 if (rp->Layer == rp2->Layer)
490 num_loops = 1;
492 else
494 num_loops = 2;
495 clipto = NULL; /* Don't do any border clipping for GZZ windows */
498 for(i = 0; i < num_loops; i++, rp = rp2)
500 lay = rp->Layer;
502 LockLayer(0, lay);
504 if (!onlydamagelist)
506 old_scroll_x = lay->Scroll_X;
507 old_scroll_y = lay->Scroll_Y;
508 old_clipregion = InstallClipRegion(lay, NULL);
511 gad = win->FirstGadget;
512 while(gad)
514 BOOL checkgad = FALSE;
516 DEBUG_ERASERELGADGETAREA(dprintf("EraseRelGadgetArea: Gadget 0x%lx Flags 0x%lx Type 0x%lx Activation 0x%lx %d,%d %d×%d\n",
517 gad, gad->Flags, gad->GadgetType, gad->Activation,
518 gad->LeftEdge, gad->TopEdge, gad->Width, gad->Height));
520 if (num_loops == 1)
522 checkgad = TRUE;
524 else
526 if (i == 0)
528 if (!IS_BORDER_GADGET(gad)) checkgad = TRUE;
530 else
532 if (IS_BORDER_GADGET(gad)) checkgad = TRUE;
536 if (checkgad)
538 if (gad->Flags & (GFLG_RELRIGHT | GFLG_RELBOTTOM |
539 GFLG_RELWIDTH | GFLG_RELHEIGHT | GFLG_RELSPECIAL))
541 struct Rectangle rect;
543 GetDomGadgetBounds(gad, win->WScreen, win, NULL, &box);
545 if ((box.Width > 0) && (box.Height > 0))
547 rect.MinX = box.Left;
548 rect.MinY = box.Top;
549 rect.MaxX = box.Left + box.Width - 1;
550 rect.MaxY = box.Top + box.Height - 1;
552 if (!(lay->Flags & LAYERSUPER))
554 DEBUG_ERASERELGADGETAREA(dprintf("EraseRelGadgetArea: gad 0x%lx add (%d,%d)-(%d,%d)\n", gad, rect.MinX, rect.MinY, rect.MaxX, rect.MaxY));
556 OrRectRegion(lay->DamageList, &rect);
557 lay->Flags |= LAYERREFRESH;
560 if (!onlydamagelist)
562 if (!clipto || AndRectRect(&rect, clipto, &rect))
564 EraseRect(rp, rect.MinX, rect.MinY, rect.MaxX, rect.MaxY);
572 } /* if (checkgad) */
574 gad = gad->NextGadget;
576 } /* while(gad) */
578 if (!onlydamagelist)
580 InstallClipRegion(lay, old_clipregion);
581 lay->Scroll_X = old_scroll_x;
582 lay->Scroll_Y = old_scroll_y;
585 UnlockLayer(lay);
587 } /* for(i = 0; i < num_loops; i++, rp = rp2) */
591 /**********************************************************************************************/
593 void RenderDisabledPattern(struct RastPort *rp, struct DrawInfo *dri, WORD x1, WORD y1,
594 WORD x2, WORD y2, struct IntuitionBase *IntuitionBase)
596 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
597 UWORD pen;
598 UWORD pattern[] = { 0x8888, 0x2222 };
600 DEBUG_RENDERDISABLEPATTERN(dprintf("RenderDisabledPattern: rp 0x%lx dri 0x%lx x1 %ld y1 %ld x2 %ld y2 %ld\n",
601 rp,dri,x1,y1,x2,y2));
603 if (dri)
605 pen = dri->dri_Pens[SHADOWPEN];
607 else
609 pen = 1;
612 SetDrMd( rp, JAM1 );
613 SetAPen( rp, pen );
614 SetAfPt( rp, pattern, 1);
616 /* render disable pattern */
617 RectFill(rp, x1, y1, x2, y2);
619 SetAfPt (rp, NULL, 0);
623 /**********************************************************************************************/
625 ULONG GetGadgetState(struct Window *window, struct Gadget *gadget)
627 ULONG state = IDS_NORMAL;
629 if (IS_BORDER_GADGET(gadget)
630 && !(window->Flags & (WFLG_WINDOWACTIVE | WFLG_TOOLBOX)))
632 if (gadget->Flags & GFLG_DISABLED)
634 if (gadget->Flags & GFLG_SELECTED)
636 state = IDS_INACTIVEDISABLED; /* Hmm ... there's no INACTIVEDISABLEDSELECTED */
638 else
640 state = IDS_INACTIVEDISABLED;
643 else
645 if (gadget->Flags & GFLG_SELECTED)
647 state = IDS_INACTIVESELECTED;
649 else
651 state = IDS_INACTIVENORMAL;
655 else
657 if (gadget->Flags & GFLG_DISABLED)
659 if (gadget->Flags & GFLG_SELECTED)
661 state = IDS_SELECTEDDISABLED;
663 else
665 state = IDS_DISABLED;
668 else
670 if (gadget->Flags & GFLG_SELECTED)
672 state = IDS_SELECTED;
674 else
676 state = IDS_NORMAL;
681 return state;
684 /**********************************************************************************************/
686 void SetupGInfo(struct GadgetInfo *gi, struct Window *win, struct Requester *req,
687 struct Gadget *gad, struct IntuitionBase *IntuitionBase)
689 struct Window *tw = 0;
691 DEBUG_SETUPGINFO(dprintf("SetupGInfo: gi %p win %p req %p gadget %p (Type 0x%x)\n",
692 gi, win, req, gad, gad->GadgetType));
694 memset(gi, 0, sizeof(*gi));
696 if (req)
698 tw = req->RWindow;
700 else
702 tw = win;
705 if (tw)
707 if (IS_SCREEN_GADGET(gad))
709 gi->gi_Window = NULL;
710 gi->gi_Screen = (struct Screen *)tw;
711 gi->gi_Pens.DetailPen = 0;
712 gi->gi_Pens.BlockPen = 0;
714 else
716 gi->gi_Window = tw;
717 gi->gi_Screen = tw->WScreen;
718 gi->gi_Pens.DetailPen = tw->DetailPen;
719 gi->gi_Pens.BlockPen = tw->BlockPen;
721 gi->gi_Requester = req;
722 gi->gi_DrInfo = GetScreenDrawInfo (gi->gi_Screen);
724 SET_GI_RPORT(gi, tw, req, gad);
726 gi->gi_Layer = gi->gi_RastPort ? gi->gi_RastPort->Layer : NULL;
728 GetGadgetDomain(gad, gi->gi_Screen, gi->gi_Window, req, &gi->gi_Domain);
729 } /* if (tw) */
731 DEBUG_SETUPGINFO(dprintf("SetGInfo: Win %p Req %p RP %p Layer %p\n",
732 gi->gi_Window, gi->gi_Requester, gi->gi_RastPort, gi->gi_Layer));
735 /**********************************************************************************************/