use m4_normalize on the output strings to remove trailing spaces/tabs and consolidate...
[AROS.git] / workbench / c / Decoration / windowdecorclass.c
blob4caba2bb1b826aeb6974ae71fdffaef90f913ddf
1 /*
2 Copyright © 2011-2017, The AROS Development Team.
3 $Id$
4 */
6 #define DEBUG 0
7 #include <aros/debug.h>
9 #include <clib/alib_protos.h>
11 #include <intuition/windecorclass.h>
12 #include <intuition/extensions.h>
13 #include <intuition/gadgetclass.h>
14 #include <graphics/rpattr.h>
15 #include <proto/arossupport.h>
16 #include <proto/intuition.h>
17 #include <proto/utility.h>
18 #include <proto/graphics.h>
19 #include <proto/cybergraphics.h>
20 #include <proto/exec.h>
21 #include <string.h>
23 #include "windowdecorclass.h"
24 #include "screendecorclass.h"
25 #include "drawfuncs.h"
26 #include "config.h"
28 #define SETIMAGE_WIN(id) wd->img_##id=sd->di->img_##id
30 struct windecor_data
32 struct DecorConfig * dc;
34 /* Pointers to images used for sys images */
35 struct NewImage *img_close;
36 struct NewImage *img_depth;
37 struct NewImage *img_zoom;
38 struct NewImage *img_up;
39 struct NewImage *img_down;
40 struct NewImage *img_left;
41 struct NewImage *img_right;
42 struct NewImage *img_mui;
43 struct NewImage *img_popup;
44 struct NewImage *img_snapshot;
45 struct NewImage *img_iconify;
46 struct NewImage *img_lock;
48 UWORD TextAlign;
51 #define CHANGE_NO_CHANGE 0
52 #define CHANGE_SIZE_CHANGE 1 /* Whole gadget area has changed */
53 #define CHANGE_NO_SIZE_CHANGE 2 /* Size remained the same, contents has changed */
55 static ULONG HasPropGadgetChanged(struct CachedPropGadget *cached, struct wdpDrawBorderPropKnob *msg)
57 /* More restrictive tests */
59 /* If the size has changed */
60 if (cached->width != (msg->wdp_PropRect->MaxX - msg->wdp_PropRect->MinX + 1))
61 return CHANGE_SIZE_CHANGE;
62 if (cached->height != (msg->wdp_PropRect->MaxY - msg->wdp_PropRect->MinY + 1))
63 return CHANGE_SIZE_CHANGE;
65 /* If there is no cached bitmap at all (this can happen NOT only at first call) */
66 if (cached->bm == NULL)
67 return CHANGE_SIZE_CHANGE;
69 /* Less restrictive tests */
71 /* If knob position has changed */
72 if (cached->knobx != (msg->wdp_RenderRect->MinX - msg->wdp_PropRect->MinX))
73 return CHANGE_NO_SIZE_CHANGE;
74 if (cached->knoby != (msg->wdp_RenderRect->MinY - msg->wdp_PropRect->MinY))
75 return CHANGE_NO_SIZE_CHANGE;
77 /* If knob is release state has changed */
78 if (cached->gadgetflags ^ (msg->wdp_Flags & WDF_DBPK_HIT))
79 return CHANGE_NO_SIZE_CHANGE;
81 /* If the window activity status has changed */
82 if (cached->windowflags ^ (msg->wdp_Window->Flags & (WFLG_WINDOWACTIVE | WFLG_TOOLBOX)))
83 return CHANGE_NO_SIZE_CHANGE;
85 /* If knob size has changed */
86 if (cached->knobwidth != (msg->wdp_RenderRect->MaxX - msg->wdp_RenderRect->MinX + 1))
87 return CHANGE_NO_SIZE_CHANGE;
88 if (cached->knobheight != (msg->wdp_RenderRect->MaxY - msg->wdp_RenderRect->MinY + 1))
89 return CHANGE_NO_SIZE_CHANGE;
91 return CHANGE_NO_CHANGE;
94 static VOID CachePropGadget(struct CachedPropGadget *cached, struct wdpDrawBorderPropKnob *msg,
95 struct BitMap *bitmap)
97 cached->bm = bitmap;
98 cached->width = msg->wdp_PropRect->MaxX - msg->wdp_PropRect->MinX + 1;
99 cached->height = msg->wdp_PropRect->MaxY - msg->wdp_PropRect->MinY + 1;
100 cached->windowflags= (msg->wdp_Window->Flags & (WFLG_WINDOWACTIVE | WFLG_TOOLBOX));
101 cached->gadgetflags= (msg->wdp_Flags & WDF_DBPK_HIT);
102 cached->knobwidth = msg->wdp_RenderRect->MaxX - msg->wdp_RenderRect->MinX + 1;
103 cached->knobheight = msg->wdp_RenderRect->MaxY - msg->wdp_RenderRect->MinY + 1;
104 cached->knobx = msg->wdp_RenderRect->MinX - msg->wdp_PropRect->MinX;
105 cached->knoby = msg->wdp_RenderRect->MinY - msg->wdp_PropRect->MinY;
108 static ULONG HasTitleBarChanged(struct CachedTitleBar *cached, struct Window *window)
110 ULONG len = 0;
112 /* More restrictive tests */
114 /* If the window size has changed */
115 if (cached->width != window->Width)
116 return CHANGE_SIZE_CHANGE;
117 if (cached->height != window->Height)
118 return CHANGE_SIZE_CHANGE;
120 /* If there is no cached bitmap at all (this can happen NOT only at first call) */
121 if (cached->bm == NULL)
122 return CHANGE_SIZE_CHANGE;
124 /* Less restrictive tests */
126 /* If the window activity status has changed */
127 if (cached->windowflags ^ (window->Flags & (WFLG_WINDOWACTIVE | WFLG_TOOLBOX)))
128 return CHANGE_NO_SIZE_CHANGE;
130 /* If the window title/title contents has changed */
131 if (window->Title)
132 len = strlen(window->Title);
134 if (cached->titlelen != len)
135 return CHANGE_NO_SIZE_CHANGE;
137 if (cached->title)
139 /* At this point:
140 - length of both buffer is guarateed to be the same, see previous test
141 - both buffers are allocated
143 ULONG i;
144 for (i = 0; i < len; i++)
145 if (cached->title[i] != window->Title[i])
146 return CHANGE_NO_SIZE_CHANGE;
149 return CHANGE_NO_CHANGE;
152 static VOID CacheTitleBar(struct CachedTitleBar *cached, struct Window *window, struct BitMap *bitmap)
154 ULONG len = 0;
156 cached->bm = bitmap;
157 cached->width = window->Width;
158 cached->height = window->Height;
159 cached->windowflags = (window->Flags & (WFLG_WINDOWACTIVE | WFLG_TOOLBOX));
161 /* Cache the title */
162 if (window->Title)
163 len = strlen(window->Title);
165 if (cached->titlelen != len)
167 if (cached->title)
168 FreeVec(cached->title);
169 cached->title = AllocVec(len + 1, MEMF_ANY | MEMF_CLEAR);
171 cached->titlelen = len;
172 strncpy(cached->title, window->Title, len);
175 static ULONG HasTitleBarShapeChanged(struct CachedTitleBarShape *cached, struct Window *window)
177 /* More restrictive tests */
179 /* If the window size has changed */
180 if (cached->width != window->Width)
181 return CHANGE_SIZE_CHANGE;
182 if (cached->height != window->Height)
183 return CHANGE_SIZE_CHANGE;
185 /* If there is no cached shape at all (this can happen NOT only at first call) */
186 if (cached->shape == NULL)
187 return CHANGE_SIZE_CHANGE;
189 /* Less restrictive tests */
191 /* If the window activity status has changed */
192 if (cached->windowflags ^ (window->Flags & (WFLG_WINDOWACTIVE | WFLG_TOOLBOX)))
193 return CHANGE_NO_SIZE_CHANGE;
195 return CHANGE_NO_CHANGE;
198 static VOID CacheTitleBarShape(struct CachedTitleBarShape *cached, struct Window *window, struct Region *shape)
200 cached->shape = shape;
201 cached->width = window->Width;
202 cached->height = window->Height;
203 cached->windowflags = (window->Flags & (WFLG_WINDOWACTIVE | WFLG_TOOLBOX));
206 static int WriteTiledImageShape(BOOL fill, struct Window *win, struct NewLUT8Image *lut8, struct NewImage *ni, int sx, int sy, int sw, int sh, int xp, int yp, int dw, int dh)
208 int w = dw;
209 int x = xp;
210 int ddw;
212 if (!ni->ok) return xp;
214 if ((sw == 0) || (dw == 0)) return xp;
216 if (win)
218 if (x > win->Width) return xp;
219 if ((x + w) > win->Width) w = win->Width - x;
222 while (w > 0)
224 ddw = sw;
225 if (w < ddw) ddw = w;
226 WriteAlphaPixelArray(ni, lut8, sx, sy, x, yp, ddw, dh);
227 w -= ddw;
228 x += ddw;
230 return x;
233 static void getrightgadgetsdimensions(struct windecor_data *data, struct Window *win, LONG *xs, LONG *xe)
235 struct Gadget *g;
237 LONG x0 = 1000000;
238 LONG x1 = 0;
239 UWORD type;
241 for (g = win->FirstGadget; g; g = g->NextGadget)
243 if ((g->Flags & GFLG_RELRIGHT) == GFLG_RELRIGHT)
245 type = g->GadgetType & GTYP_SYSTYPEMASK;
246 if (data->dc->CloseGadgetOnRight)
248 if (((type & (GTYP_CLOSE | GTYP_WDEPTH | GTYP_WZOOM)) != 0) || (g->Activation & GACT_TOPBORDER))
250 if (g->Width > 0)
252 if ((win->Width + g->LeftEdge) < x0) x0 = win->Width + g->LeftEdge;
253 if ((win->Width + g->LeftEdge + g->Width) > x1) x1 = win->Width + g->LeftEdge + g->Width;
257 else
259 if (((type & (GTYP_WDEPTH | GTYP_WZOOM)) != 0) || (g->Activation & GACT_TOPBORDER))
261 if (g->Width > 0)
263 if ((win->Width + g->LeftEdge) < x0) x0 = win->Width + g->LeftEdge;
264 if ((win->Width + g->LeftEdge + g->Width) > x1) x1 = win->Width + g->LeftEdge + g->Width;
270 if (x0 == 1000000) x0 = 0;
271 *xs = x0;
272 *xe = x1;
275 static void getleftgadgetsdimensions(struct windecor_data *data, struct Window *win, LONG *xs, LONG *xe)
277 struct Gadget *g;
279 LONG w = 0;
280 LONG x0 = 1000000;
281 LONG x1 = 0;
282 for (g = win->FirstGadget; g; g = g->NextGadget)
284 w++;
285 if (((g->Flags & GFLG_RELRIGHT) == 0) && (g->Activation & GACT_TOPBORDER))
287 if ((g->GadgetType & GTYP_WDRAGGING) == 0)
289 if (g->Width > 0)
291 if (g->LeftEdge < x0) x0 = g->LeftEdge;
292 if ((g->LeftEdge + g->Width) > x1) x1 = g->LeftEdge + g->Width;
297 if (x0 == 1000000) x0 = 0;
298 *xs = x0;
299 *xe = x1;
302 static void DrawShapePartialTitleBar(struct WindowData *wd, struct NewLUT8Image *shape, struct windecor_data *data, struct Window *window)
304 LONG xl0, xl1, xr0, xr1, defwidth;
305 ULONG textlen = 0, titlelen = 0, textpixellen = 0;
306 struct TextExtent te;
308 BOOL hastitle;
309 BOOL hastitlebar;
310 LONG dy;
312 struct RastPort *rp = &window->WScreen->RastPort;
313 hastitle = window->Title != NULL ? TRUE : FALSE;
314 hastitlebar = (window->BorderTop > 0) ? TRUE : FALSE;
316 getleftgadgetsdimensions(data, window, &xl0, &xl1);
317 getrightgadgetsdimensions(data, window, &xr0, &xr1);
319 defwidth = (xl0 != xl1) ? data->dc->BarPreGadget_s : data->dc->BarPre_s;
320 if(xr1 == 0)
322 xr1 = window->Width - data->dc->BarPre_s;
323 xr0 = window->Width - data->dc->BarPre_s;
326 defwidth += (xl1 - xl0);
328 defwidth += data->dc->BarJoinGB_s;
329 defwidth += data->dc->BarJoinBT_s;
330 defwidth += data->dc->BarJoinTB_s;
331 defwidth += data->dc->BarJoinBG_s;
332 defwidth += (xr1 - xr0);
333 defwidth += (xr0 != xr1) ? data->dc->BarPostGadget_s : data->dc->BarPost_s;
335 if (defwidth >= window->Width) hastitle = FALSE;
337 if (hastitle)
339 titlelen = strlen(window->Title);
340 textlen = TextFit(rp, window->Title, titlelen, &te, NULL, 1, window->Width-defwidth, window->BorderTop - 2);
341 if (textlen)
343 textpixellen = te.te_Extent.MaxX - te.te_Extent.MinX + 1;
348 if (wd->img_winbar_normal->ok && hastitlebar)
350 UWORD x = 0;
351 UWORD barh = window->BorderTop;
352 struct NewImage * img_winbar_normal = wd->img_winbar_normal;
354 if (data->dc->BarHeight != barh)
355 img_winbar_normal = ScaleNewImage(wd->img_winbar_normal, wd->img_winbar_normal->w, 2 * barh);
357 if (window->Flags & (WFLG_WINDOWACTIVE | WFLG_TOOLBOX))
358 dy = 0;
359 else
360 dy = barh; /* Offset into source image */
362 if (xl0 != xl1)
364 x = WriteTiledImageShape(data->dc->FillTitleBar, window, shape,img_winbar_normal, data->dc->BarPreGadget_o, dy, data->dc->BarPreGadget_s, barh, x, 0, data->dc->BarPreGadget_s, barh);
365 if ((xl1-xl0) > 0) x = WriteTiledImageShape(data->dc->FillTitleBar, window, shape, img_winbar_normal, data->dc->BarLGadgetFill_o, dy, data->dc->BarLGadgetFill_s, barh, x, 0, xl1-xl0, barh);
367 else
369 x = WriteTiledImageShape(data->dc->FillTitleBar, window, shape, img_winbar_normal, data->dc->BarPre_o, dy, data->dc->BarPre_s, barh, x, 0, data->dc->BarPreGadget_s, barh);
371 x = WriteTiledImageShape(data->dc->FillTitleBar, window, shape, img_winbar_normal, data->dc->BarJoinGB_o, dy, data->dc->BarJoinGB_s, barh, x, 0, data->dc->BarJoinGB_s, barh);
372 if (hastitle && (textlen > 0))
374 switch(data->TextAlign)
376 case WD_DWTA_CENTER:
377 //BarLFill
378 x = WriteTiledImageShape(data->dc->FillTitleBar, window, shape, img_winbar_normal, data->dc->BarLFill_o, dy, data->dc->BarLFill_s, barh, x, 0, 60, barh);
379 break;
380 case WD_DWTA_RIGHT:
381 //BarLFill
382 break;
383 default:
384 case WD_DWTA_LEFT:
385 break;
387 x = WriteTiledImageShape(data->dc->FillTitleBar, window, shape, img_winbar_normal, data->dc->BarJoinBT_o, dy, data->dc->BarJoinBT_s, barh, x, 0, data->dc->BarJoinBT_s, barh);
388 if (textpixellen > 0) x = WriteTiledImageShape(data->dc->FillTitleBar, window, shape, img_winbar_normal, data->dc->BarTitleFill_o, dy, data->dc->BarTitleFill_s, barh, x, 0, textpixellen, barh);
389 x = WriteTiledImageShape(data->dc->FillTitleBar, window, shape, img_winbar_normal, data->dc->BarJoinTB_o, dy, data->dc->BarJoinTB_s, barh, x, 0, data->dc->BarJoinTB_s, barh);
391 x = WriteTiledImageShape(data->dc->FillTitleBar, window, shape, img_winbar_normal, data->dc->BarRFill_o, dy, data->dc->BarRFill_s, barh, x, 0, xr0 - x - data->dc->BarJoinBG_s, barh);
392 x = WriteTiledImageShape(data->dc->FillTitleBar, window, shape, img_winbar_normal, data->dc->BarJoinBG_o, dy, data->dc->BarJoinBG_s, barh, x, 0, data->dc->BarJoinBG_s, barh);
393 if ((xr1-xr0) > 0) x = WriteTiledImageShape(data->dc->FillTitleBar, window, shape, img_winbar_normal, data->dc->BarRGadgetFill_o, dy, data->dc->BarRGadgetFill_s, barh, x, 0, xr1-xr0, barh);
394 if (xr0 != xr1)
396 x = WriteTiledImageShape(data->dc->FillTitleBar, window, shape, img_winbar_normal, data->dc->BarPostGadget_o, dy, data->dc->BarPostGadget_s, barh, x, 0, data->dc->BarPostGadget_s, barh);
398 else
400 x = WriteTiledImageShape(data->dc->FillTitleBar, window, shape, img_winbar_normal, data->dc->BarPost_o, dy, data->dc->BarPost_s, barh, x, 0, data->dc->BarPost_s, barh);
403 if (data->dc->BarHeight != barh)
404 DisposeImageContainer(img_winbar_normal);
408 static VOID DrawPartialTitleBar(struct WindowData *wd, struct windecor_data *data, struct Window *window, struct RastPort *dst_rp, struct DrawInfo *dri, UWORD *pens)
410 LONG xl0, xl1, xr0, xr1, defwidth;
411 ULONG textlen = 0, titlelen = 0, textpixellen = 0;
412 struct TextExtent te;
413 struct RastPort *rp;
414 struct NewImage *ni = NULL;
416 BOOL hastitle;
417 BOOL hastitlebar;
418 UWORD textstart = 0;
419 ULONG color, s_col, e_col, arc;
420 LONG dy;
421 LONG pen = -1;
422 ULONG changetype = CHANGE_NO_CHANGE;
423 struct BitMap *cachedtitlebarbitmap = NULL;
425 changetype = HasTitleBarChanged(&wd->tbar, window);
426 if (changetype == CHANGE_SIZE_CHANGE)
428 if (wd->tbar.bm)
429 FreeBitMap(wd->tbar.bm);
430 wd->tbar.bm = NULL;
432 cachedtitlebarbitmap = wd->tbar.bm;
434 if (changetype == CHANGE_NO_CHANGE)
436 BltBitMapRastPort(cachedtitlebarbitmap, 0, 0, dst_rp, 0, 0, window->Width, window->BorderTop, 0xc0);
437 return;
440 /* Regenerate the bitmap */
441 rp = CreateRastPort();
442 if (rp)
444 /* Reuse the bitmap if there was no size change (ie. only change of state) */
445 if (changetype == CHANGE_NO_SIZE_CHANGE)
446 rp->BitMap = cachedtitlebarbitmap;
447 else
448 rp->BitMap = AllocBitMap(window->Width, window->BorderTop, 1, 0, window->WScreen->RastPort.BitMap);
450 if (rp->BitMap == NULL)
452 FreeRastPort(rp);
453 return;
456 SetFont(rp, dri->dri_Font);
458 else
459 return;
461 hastitle = window->Title != NULL ? TRUE : FALSE;
462 hastitlebar = (window->BorderTop > 0) ? TRUE : FALSE;
464 if (wd->img_border_normal->ok) ni = wd->img_border_normal;
466 if (ni == NULL) data->dc->UseGradients = TRUE;
468 color = 0x00cccccc;
470 if (window->Flags & (WFLG_WINDOWACTIVE | WFLG_TOOLBOX))
472 s_col = data->dc->ActivatedGradientColor_s;
473 e_col = data->dc->ActivatedGradientColor_e;
474 arc = data->dc->ActivatedGradientColor_a;
475 dy = 0;
476 pen = wd->ActivePen;
477 } else {
478 s_col = data->dc->DeactivatedGradientColor_s;
479 e_col = data->dc->DeactivatedGradientColor_e;
480 arc = data->dc->DeactivatedGradientColor_a;
481 dy = data->dc->BarHeight;
482 if (!data->dc->UseGradients)
484 if (wd->img_border_deactivated->ok) ni = wd->img_border_deactivated;
486 pen = wd->DeactivePen;
490 if (data->dc->FillTitleBar)
492 if (data->dc->UseGradients) FillPixelArrayGradient(pen, wd->truecolor, rp, 0, 0, window->Width - 1, window->Height - 1, 0, 0, window->Width, window->BorderTop, s_col, e_col, arc, 0, 0);
493 else HorizVertRepeatNewImage(ni, color, 0, 0, rp, 0, 0, window->Width, window->BorderTop);
496 getleftgadgetsdimensions(data, window, &xl0, &xl1);
497 getrightgadgetsdimensions(data, window, &xr0, &xr1);
498 defwidth = (xl0 != xl1) ? data->dc->BarPreGadget_s : data->dc->BarPre_s;
499 if(xr1 == 0)
501 xr1 = window->Width - data->dc->BarPre_s;
502 xr0 = window->Width - data->dc->BarPre_s;
505 defwidth += (xl1 - xl0);
507 defwidth += data->dc->BarJoinGB_s;
508 defwidth += data->dc->BarJoinBT_s;
509 defwidth += data->dc->BarJoinTB_s;
510 defwidth += data->dc->BarJoinBG_s;
511 defwidth += (xr1 - xr0);
512 defwidth += (xr0 != xr1) ? data->dc->BarPostGadget_s : data->dc->BarPost_s;
514 if (defwidth >= window->Width) hastitle = FALSE;
516 if (hastitle)
518 titlelen = strlen(window->Title);
519 textlen = TextFit(rp, window->Title, titlelen, &te, NULL, 1, window->Width-defwidth, window->BorderTop - 2);
520 if (textlen)
522 textpixellen = te.te_Extent.MaxX - te.te_Extent.MinX + 1;
526 if (wd->img_winbar_normal->ok && hastitlebar)
528 UWORD x = 0;
529 UWORD barh = window->BorderTop;
530 struct NewImage * img_winbar_normal = wd->img_winbar_normal;
532 if (data->dc->BarHeight != barh)
533 img_winbar_normal = ScaleNewImage(wd->img_winbar_normal, wd->img_winbar_normal->w, 2 * barh);
535 if (window->Flags & (WFLG_WINDOWACTIVE | WFLG_TOOLBOX))
536 dy = 0;
537 else
538 dy = barh; /* Offset into source image */
540 if (xl0 != xl1)
542 x = WriteTiledImageTitle(data->dc->FillTitleBar, window, rp, img_winbar_normal, data->dc->BarPreGadget_o, dy, data->dc->BarPreGadget_s, barh, x, 0, data->dc->BarPreGadget_s, barh);
543 if ((xl1-xl0) > 0) x = WriteTiledImageTitle(data->dc->FillTitleBar, window, rp,img_winbar_normal, data->dc->BarLGadgetFill_o, dy, data->dc->BarLGadgetFill_s, barh, x, 0, xl1-xl0, barh);
545 else
547 x = WriteTiledImageTitle(data->dc->FillTitleBar, window, rp, img_winbar_normal, data->dc->BarPre_o, dy, data->dc->BarPre_s, barh, x, 0, data->dc->BarPreGadget_s, barh);
549 x = WriteTiledImageTitle(data->dc->FillTitleBar, window, rp,img_winbar_normal, data->dc->BarJoinGB_o, dy, data->dc->BarJoinGB_s, barh, x, 0, data->dc->BarJoinGB_s, barh);
550 if (hastitle && (textlen > 0))
552 switch(data->TextAlign)
554 case WD_DWTA_CENTER:
555 //BarLFill
556 x = WriteTiledImageTitle(data->dc->FillTitleBar, window, rp, img_winbar_normal, data->dc->BarLFill_o, dy, data->dc->BarLFill_s, barh, x, 0, 60, barh);
557 break;
558 case WD_DWTA_RIGHT:
559 //BarLFill
560 break;
561 default:
562 case WD_DWTA_LEFT:
563 break;
565 x = WriteTiledImageTitle(data->dc->FillTitleBar, window, rp, img_winbar_normal, data->dc->BarJoinBT_o, dy, data->dc->BarJoinBT_s, barh, x, 0, data->dc->BarJoinBT_s, barh);
566 textstart = x;
567 if (textpixellen > 0) x = WriteTiledImageTitle(data->dc->FillTitleBar, window, rp, img_winbar_normal, data->dc->BarTitleFill_o, dy, data->dc->BarTitleFill_s, barh, x, 0, textpixellen, barh);
568 x = WriteTiledImageTitle(data->dc->FillTitleBar, window, rp, img_winbar_normal, data->dc->BarJoinTB_o, dy, data->dc->BarJoinTB_s, barh, x, 0, data->dc->BarJoinTB_s, barh);
570 /* Part right to window title */
571 x = WriteTiledImageTitle(data->dc->FillTitleBar, window, rp, img_winbar_normal, data->dc->BarRFill_o, dy, data->dc->BarRFill_s, barh, x, 0, xr0 - x - data->dc->BarJoinBG_s, barh);
572 x = WriteTiledImageTitle(data->dc->FillTitleBar, window, rp, img_winbar_normal, data->dc->BarJoinBG_o, dy, data->dc->BarJoinBG_s, barh, x, 0, data->dc->BarJoinBG_s, barh);
573 if ((xr1-xr0) > 0) x = WriteTiledImageTitle(data->dc->FillTitleBar, window, rp, img_winbar_normal, data->dc->BarRGadgetFill_o, dy, data->dc->BarRGadgetFill_s, barh, x, 0, xr1-xr0, barh);
574 if (xr0 != xr1)
576 x = WriteTiledImageTitle(data->dc->FillTitleBar, window, rp, img_winbar_normal, data->dc->BarPostGadget_o, dy, data->dc->BarPostGadget_s, barh, x, 0, data->dc->BarPostGadget_s, barh);
578 else
580 x = WriteTiledImageTitle(data->dc->FillTitleBar, window, rp, img_winbar_normal, data->dc->BarPost_o, dy, data->dc->BarPost_s, barh, x, 0, data->dc->BarPost_s, barh);
583 if (data->dc->BarHeight != barh)
584 DisposeImageContainer(img_winbar_normal);
587 if ((textlen > 0) && hastitle)
589 SetAPen(rp, pens[(window->Flags & (WFLG_WINDOWACTIVE | WFLG_TOOLBOX)) ? FILLTEXTPEN : TEXTPEN]);
590 SetDrMd(rp, JAM1);
591 UWORD tx = textstart;
592 UWORD tymax = window->BorderTop - (dri->dri_Font->tf_YSize - dri->dri_Font->tf_Baseline) - 1;
593 UWORD ty = (window->BorderTop + dri->dri_Font->tf_Baseline - 1) >> 1;
594 if (ty > tymax) ty = tymax;
596 if (!wd->truecolor || ((data->dc->TitleOutline == FALSE) && (data->dc->TitleShadow == FALSE)))
598 Move(rp, tx, ty);
599 Text(rp, window->Title, textlen);
601 else if (data->dc->TitleOutline)
604 SetSoftStyle(rp, FSF_BOLD, AskSoftStyle(rp));
605 SetRPAttrs(rp, RPTAG_PenMode, FALSE, RPTAG_FgColor, data->dc->TitleColorShadow, TAG_DONE);
607 Move(rp, tx + 1, ty ); Text(rp, window->Title, textlen);
608 Move(rp, tx + 2, ty ); Text(rp, window->Title, textlen);
609 Move(rp, tx , ty ); Text(rp, window->Title, textlen);
610 Move(rp, tx, ty + 1); Text(rp, window->Title, textlen);
611 Move(rp, tx, ty + 2); Text(rp, window->Title, textlen);
612 Move(rp, tx + 1, ty + 2); Text(rp, window->Title, textlen);
613 Move(rp, tx + 2, ty + 1); Text(rp, window->Title, textlen);
614 Move(rp, tx + 2, ty + 2); Text(rp, window->Title, textlen);
616 SetRPAttrs(rp, RPTAG_PenMode, FALSE, RPTAG_FgColor, data->dc->TitleColorText, TAG_DONE);
617 Move(rp, tx + 1, ty + 1);
618 Text(rp, window->Title, textlen);
619 SetSoftStyle(rp, FS_NORMAL, AskSoftStyle(rp));
621 else
623 SetRPAttrs(rp, RPTAG_PenMode, FALSE, RPTAG_FgColor, data->dc->TitleColorShadow, TAG_DONE);
624 Move(rp, tx + 1, ty + 1 );
625 Text(rp, window->Title, textlen);
627 SetRPAttrs(rp, RPTAG_PenMode, FALSE, RPTAG_FgColor, data->dc->TitleColorText, TAG_DONE);
628 Move(rp, tx, ty);
629 Text(rp, window->Title, textlen);
634 BltBitMapRastPort(rp->BitMap, 0, 0, dst_rp, 0, 0, window->Width, window->BorderTop, 0xc0);
636 /* Cache the actual bitmap */
637 CacheTitleBar(&wd->tbar, window, rp->BitMap);
639 FreeRastPort(rp);
642 static VOID DisposeWindowSkinning(struct windecor_data *data)
647 static BOOL InitWindowSkinning(struct windecor_data *data, struct DecorImages * di, struct DecorConfig * dc)
649 if ((!di) || (!dc))
650 return FALSE;
652 data->dc = dc;
654 data->TextAlign = WD_DWTA_LEFT;
656 /* Set pointers to gadget images, used only to get gadget sizes as they
657 are requested prior to creation of menu object */
658 data->img_close = di->img_close;
659 data->img_depth = di->img_depth;
660 data->img_zoom = di->img_zoom;
661 data->img_up = di->img_up;
662 data->img_down = di->img_down;
663 data->img_left = di->img_left;
664 data->img_right = di->img_right;
665 data->img_mui = di->img_mui;
666 data->img_popup = di->img_popup;
667 data->img_snapshot = di->img_snapshot;
668 data->img_iconify = di->img_iconify;
669 data->img_lock = di->img_lock;
671 if (data->img_close && data->img_depth && data->img_zoom && data->img_up &&
672 data->img_down && data->img_left && data->img_right)
673 return TRUE;
675 DisposeWindowSkinning(data);
676 return FALSE;
679 /**************************************************************************************************/
680 static IPTR windecor_new(Class *cl, Object *obj, struct opSet *msg)
682 struct windecor_data *data;
684 D(bug("[Decoration:Win] %s(tags @ 0x%p)\n", __func__, msg->ops_AttrList));
686 obj = (Object *)DoSuperMethodA(cl, obj, (Msg)msg);
687 if (obj)
689 data = INST_DATA(cl, obj);
691 struct DecorImages * di = (struct DecorImages *) GetTagData(WDA_DecorImages, (IPTR)NULL, msg->ops_AttrList);
692 struct DecorConfig * dc = (struct DecorConfig *) GetTagData(WDA_DecorConfig, (IPTR)NULL, msg->ops_AttrList);
694 D(bug("[Decoration:Win] %s: DecorImages @ 0x%p\n", __func__, di));
695 D(bug("[Decoration:Win] %s: DecorConfig @ 0x%p\n", __func__, dc));
697 if (!InitWindowSkinning(data, di, dc))
699 CoerceMethod(cl, obj, OM_DISPOSE);
700 obj = NULL;
704 return (IPTR)obj;
707 /**************************************************************************************************/
708 static IPTR windecor_dispose(Class *cl, Object *obj, struct opSet *msg)
710 struct windecor_data *data = INST_DATA(cl, obj);
712 DisposeWindowSkinning(data);
714 return 1;
717 /**************************************************************************************************/
718 static IPTR windecor_get(Class *cl, Object *obj, struct opGet *msg)
720 switch(msg->opg_AttrID)
722 case WDA_TrueColorOnly:
723 *msg->opg_Storage = TRUE;
724 break;
725 default:
726 return DoSuperMethodA(cl, obj, (Msg)msg);
728 return 1;
731 /**************************************************************************************************/
732 static IPTR windecor_draw_sysimage(Class *cl, Object *obj, struct wdpDrawSysImage *msg)
734 struct windecor_data *data = INST_DATA(cl, obj);
735 struct RastPort *rp = msg->wdp_RPort;
736 struct NewImage *ni = NULL;
737 struct WindowData *wd = (struct WindowData *) msg->wdp_UserBuffer;
738 LONG state = msg->wdp_State;
739 LONG left = msg->wdp_X;
740 LONG top = msg->wdp_Y;
741 LONG width = msg->wdp_Width;
742 LONG height = msg->wdp_Height;
743 WORD addx = 0;
744 WORD addy = 0;
745 BOOL isset = FALSE;
746 BOOL titlegadget = FALSE;
748 switch(msg->wdp_Which)
750 case SIZEIMAGE:
751 if (wd->img_size->ok)
753 ni = wd->img_size;
754 isset = TRUE;
755 if (data->dc->GadgetsThreeState)
756 addx = (data->dc->RightBorderGadgets - (wd->img_size->w / 3)) /2;
757 else
758 addx = (data->dc->RightBorderGadgets - (wd->img_size->w >> 2)) /2;
759 addy = (data->dc->BottomBorderGadgets - wd->img_size->h) / 2;
761 break;
763 case CLOSEIMAGE:
764 if (wd->img_close->ok)
766 ni = wd->img_close;
767 isset = TRUE;
768 titlegadget = TRUE;
770 break;
772 case MUIIMAGE:
773 if (wd->img_mui->ok)
775 ni = wd->img_mui;
776 isset = TRUE;
777 titlegadget = TRUE;
779 break;
781 case POPUPIMAGE:
782 if (wd->img_popup->ok)
784 ni = wd->img_popup;
785 isset = TRUE;
786 titlegadget = TRUE;
788 break;
790 case SNAPSHOTIMAGE:
791 if (wd->img_snapshot->ok)
793 ni = wd->img_snapshot;
794 isset = TRUE;
795 titlegadget = TRUE;
797 break;
799 case LOCKIMAGE:
800 if (wd->img_lock->ok)
802 ni = wd->img_lock;
803 isset = TRUE;
804 titlegadget = TRUE;
806 break;
808 case ICONIFYIMAGE:
809 if (wd->img_iconify->ok)
811 ni = wd->img_iconify;
812 isset = TRUE;
813 titlegadget = TRUE;
815 break;
817 case DEPTHIMAGE:
818 if (wd->img_depth->ok)
820 ni = wd->img_depth;
821 isset = TRUE;
822 titlegadget = TRUE;
824 break;
826 case ZOOMIMAGE:
827 if (wd->img_zoom->ok)
829 ni = wd->img_zoom;
830 isset = TRUE;
831 titlegadget = TRUE;
833 break;
835 case UPIMAGE:
836 ni = wd->img_up;
837 if (data->dc->GadgetsThreeState) addx = (data->dc->RightBorderGadgets - (wd->img_up->w / 3)) /2; else addx = (data->dc->RightBorderGadgets - (wd->img_up->w >> 2)) /2;
838 addy = data->dc->UpDownAddY / 2;
839 isset = TRUE;
840 break;
842 case DOWNIMAGE:
843 ni = wd->img_down;
844 if (data->dc->GadgetsThreeState) addx = (data->dc->RightBorderGadgets - (wd->img_down->w / 3)) /2; else addx = (data->dc->RightBorderGadgets - (wd->img_down->w >> 2)) /2;
845 addy = data->dc->UpDownAddY / 2;
846 isset = TRUE;
847 break;
849 case LEFTIMAGE:
850 ni = wd->img_left;
851 addx = data->dc->LeftRightAddX / 2;
852 addy = (data->dc->BottomBorderGadgets - wd->img_left->h) / 2;
853 isset = TRUE;
854 break;
856 case RIGHTIMAGE:
857 ni = wd->img_right;
858 addx = data->dc->LeftRightAddX / 2;
859 addy = (data->dc->BottomBorderGadgets - wd->img_right->h) /2;
860 isset = TRUE;
861 break;
863 default:
864 return DoSuperMethodA(cl, obj, (Msg)msg);
867 if (!isset) return DoSuperMethodA(cl, obj, (Msg)msg);
869 /* Reblit title bar */
870 if (wd && titlegadget && wd->tbar.bm)
871 BltBitMapRastPort(wd->tbar.bm, left + addx, top + addy, rp, left + addx, top + addy, width, height, 0xc0);
873 if (ni)
875 if (titlegadget)
876 DrawScaledStatefulGadgetImageToRP(rp, ni, state, left + addx, top + addy, -1, height);
877 else
878 DrawStatefulGadgetImageToRP(rp, ni, state, left + addx, top + addy);
881 return TRUE;
884 /**************************************************************************************************/
885 static IPTR windecor_draw_winborder(Class *cl, Object *obj, struct wdpDrawWinBorder *msg)
887 struct windecor_data *data = INST_DATA(cl, obj);
888 struct RastPort *rp = msg->wdp_RPort;
889 struct Window *window = msg->wdp_Window;
890 struct WindowData *wd = (struct WindowData *) msg->wdp_UserBuffer;
891 struct NewImage *ni = NULL;
892 UWORD *pens = msg->wdp_Dri->dri_Pens;
893 ULONG bc, color, s_col, e_col, arc;
894 UWORD bl, bt, br, bb, ww, wh;
895 LONG pen = -1;
897 D(bug("[Decoration:Win] %s(0x%p)\n", __func__, obj);)
898 D(bug("[Decoration:Win] %s: window @ 0x%p\n", __func__, window);)
900 if (wd->img_border_normal->ok)
901 ni = wd->img_border_normal;
903 if (ni == NULL)
904 data->dc->UseGradients = TRUE;
906 BOOL tc = wd->truecolor;
908 LONG dpen = pens[SHADOWPEN];
909 LONG lpen = pens[SHINEPEN];
910 LONG mpen = pens[SHINEPEN];
912 bl = window->BorderLeft;
913 bt = window->BorderTop;
914 bb = window->BorderBottom;
915 br = window->BorderRight;
916 ww = window->Width;
917 wh = window->Height;
919 color = 0x00cccccc;
921 if (window->Flags & (WFLG_WINDOWACTIVE | WFLG_TOOLBOX))
923 D(bug("[Decoration:Win] %s: ACTIVE\n", __func__);)
924 pen = wd->ActivePen;
925 s_col = data->dc->ActivatedGradientColor_s;
926 e_col = data->dc->ActivatedGradientColor_e;
927 arc = data->dc->ActivatedGradientColor_a;
928 bc = data->dc->BaseColors_a;
929 } else {
930 D(bug("[Decoration:Win] %s: INACTIVE\n", __func__);)
931 pen = wd->DeactivePen;
932 s_col = data->dc->DeactivatedGradientColor_s;
933 e_col = data->dc->DeactivatedGradientColor_e;
934 arc = data->dc->DeactivatedGradientColor_a;
935 bc = data->dc->BaseColors_d;
936 if (!data->dc->UseGradients)
938 if (wd->img_border_deactivated->ok) ni = wd->img_border_deactivated;
942 /* Draw title bar */
943 DrawPartialTitleBar(wd, data, window, rp, msg->wdp_Dri, pens);
945 /* Draw left, right and bottom frames */
946 if (!(msg->wdp_Flags & WDF_DWB_TOP_ONLY))
948 UBYTE * buf = NULL;
949 int overlap = 0;
951 if (data->dc->WinFrameStyle > 0)
952 overlap = 2;
954 if (data->dc->UseGradients)
956 /* Create one pixel wide buffer */
957 buf = AllocVec(1 * window->Height * 3, MEMF_ANY | MEMF_CLEAR);
959 /* Fill the buffer with gradient */
960 FillMemoryBufferRGBGradient(buf, pen, 0, 0, window->Width - 1, window->Height - 1, 0, 0,
961 1, window->Height , s_col, e_col, arc);
964 if (data->dc->UseGradients)
966 /* Reuse the buffer for blitting frames */
967 if (window->BorderLeft > overlap) HorizRepeatBuffer(buf, window->BorderTop, pen, wd->truecolor, rp,
968 0, window->BorderTop,
969 window->BorderLeft, window->Height - window->BorderTop);
970 if (window->BorderRight > overlap) HorizRepeatBuffer(buf, window->BorderTop, pen, wd->truecolor, rp,
971 window->Width - window->BorderRight, window->BorderTop,
972 window->BorderRight, window->Height - window->BorderTop);
973 if (window->BorderBottom > overlap) HorizRepeatBuffer(buf, window->Height - window->BorderBottom, pen, wd->truecolor, rp,
974 0, window->Height - window->BorderBottom,
975 window->Width, window->BorderBottom);
977 else
979 if (window->BorderLeft > overlap) HorizVertRepeatNewImage(ni, color, 0, window->BorderTop, rp,
980 0, window->BorderTop,
981 window->BorderLeft - 1, window->Height - window->BorderTop);
982 if (window->BorderRight > overlap) HorizVertRepeatNewImage(ni, color, window->Width - window->BorderRight , window->BorderTop, rp,
983 window->Width - window->BorderRight , window->BorderTop,
984 window->BorderRight, window->Height - window->BorderTop);
985 if (window->BorderBottom > overlap) HorizVertRepeatNewImage(ni, color, 0, window->Height - window->BorderBottom, rp,
986 0, window->Height - window->BorderBottom,
987 window->Width, window->BorderBottom);
990 /* Shading borders */
991 if (data->dc->WinFrameStyle > 0)
993 int bbt = bt;
995 if (bl > 0) ShadeLine(dpen, tc, data->dc->UseGradients, rp, ni, bc, data->dc->ShadeValues_d, bbt, 0, bbt, 0, wh - 1);
996 if (bb > 0) ShadeLine(dpen, tc, data->dc->UseGradients, rp, ni, bc, data->dc->ShadeValues_d, wh - 1, 0, wh - 1, ww - 1, wh - 1);
997 if (br > 0) ShadeLine(dpen, tc, data->dc->UseGradients, rp, ni, bc, data->dc->ShadeValues_d, bbt , ww - 1, bbt , ww - 1, wh - 1);
998 if (bl > 1) ShadeLine(dpen, tc, data->dc->UseGradients, rp, ni, bc, data->dc->ShadeValues_d, bbt, bl - 1, bbt, bl - 1, wh - bb);
999 if (bb > 1) ShadeLine(dpen, tc, data->dc->UseGradients, rp, ni, bc, data->dc->ShadeValues_d, wh - bb, bl - 1, wh - bb, ww - br, wh - bb);
1000 if (br > 1) ShadeLine(dpen, tc, data->dc->UseGradients, rp, ni, bc, data->dc->ShadeValues_d, bbt , ww - br, bbt , ww - br, wh - bb);
1001 if (bl > 2) ShadeLine(lpen, tc, data->dc->UseGradients, rp, ni, bc, data->dc->ShadeValues_l, bbt, 1, bbt, 1, wh - 2);
1002 if (bl > 3) {
1003 if (bb > 1) ShadeLine(mpen, tc, data->dc->UseGradients, rp, ni, bc, data->dc->ShadeValues_m, bbt, bl - 2, bbt, bl - 2, wh - bb + 1);
1004 else ShadeLine(mpen, tc, data->dc->UseGradients, rp, ni, bc, data->dc->ShadeValues_m, bbt, bl - 2, bbt, bl - 2, wh - bb);
1006 if (br > 2) ShadeLine(mpen, tc, data->dc->UseGradients, rp, ni, bc, data->dc->ShadeValues_m, bbt, ww - 2, bbt, ww - 2, wh - 2);
1007 if (bb > 2) ShadeLine(mpen, tc, data->dc->UseGradients, rp, ni, bc, data->dc->ShadeValues_m, wh - 2, 1, wh - 2, ww - 2, wh - 2);
1008 if (bb > 3) {
1009 if ((bl > 0) && (br > 0)) ShadeLine(lpen, tc, data->dc->UseGradients, rp, ni, bc, data->dc->ShadeValues_l, wh - bb + 1, bl, wh - bb + 1, ww - br, wh - bb + 1);
1011 if (br > 3) {
1012 if (bb > 1) ShadeLine(lpen, tc, data->dc->UseGradients, rp, ni, bc, data->dc->ShadeValues_l, bbt, ww - br + 1, bbt, ww - br + 1, wh - bb + 1);
1015 FreeVec(buf);
1017 return TRUE;
1020 /**************************************************************************************************/
1021 static IPTR windecor_layout_bordergadgets(Class *cl, Object *obj, struct wdpLayoutBorderGadgets *msg)
1023 struct windecor_data *data = INST_DATA(cl, obj);
1024 struct Window *window = msg->wdp_Window;
1025 struct Gadget *gadget = msg->wdp_Gadgets;
1026 struct Gadget *draggadget = NULL;
1027 struct WindowData *wd = (struct WindowData *) msg->wdp_UserBuffer;
1028 ULONG eb = msg->wdp_ExtraButtons;
1030 BOOL hasdepth;
1031 BOOL haszoom;
1032 BOOL hasclose;
1033 LONG width;
1034 LONG refheight = window->BorderTop;
1036 DoSuperMethodA(cl, obj, (Msg)msg);
1038 hasclose = (window->Flags & WFLG_CLOSEGADGET) ? TRUE : FALSE;
1039 hasdepth = (window->Flags & WFLG_DEPTHGADGET) ? TRUE : FALSE;
1040 haszoom = ((window->Flags & WFLG_HASZOOM) || ((window->Flags & WFLG_SIZEGADGET) && hasdepth)) ? TRUE : FALSE;
1043 if ((msg->wdp_Flags & WDF_LBG_SYSTEMGADGET) != 0)
1045 if (gadget->GadgetType == GTYP_CUSTOMGADGET)
1047 switch(gadget->GadgetID)
1049 case ETI_MUI:
1050 if (wd->img_mui->ok)
1052 if (data->dc->GadgetsThreeState) width = (wd->img_mui->w / 3); else width = (wd->img_mui->w >> 2);
1054 gadget->Width = width;
1055 gadget->TopEdge = (refheight - gadget->Height) / 2;
1057 if (haszoom)
1059 if (data->dc->GadgetsThreeState) width += (wd->img_zoom->w / 3); else width += (wd->img_zoom->w >> 2);
1061 if (hasclose && data->dc->CloseGadgetOnRight)
1063 if (data->dc->GadgetsThreeState) width += (wd->img_close->w / 3); else width += (wd->img_close->w >> 2);
1065 if (hasdepth)
1067 if (data->dc->GadgetsThreeState) width += (wd->img_depth->w / 3); else width += (wd->img_depth->w >> 2);
1068 gadget->LeftEdge = -data->dc->BarPostGadget_s - width;
1070 else
1072 gadget->LeftEdge = -data->dc->BarPostGadget_s - width;
1074 gadget->Flags &= ~GFLG_RELWIDTH;
1075 gadget->Flags |= GFLG_RELRIGHT;
1078 break;
1080 case ETI_PopUp:
1081 if (wd->img_popup->ok)
1083 if (data->dc->GadgetsThreeState) width = (wd->img_popup->w / 3); else width = (wd->img_popup->w >> 2);
1085 gadget->Width = width;
1086 gadget->TopEdge = (refheight - gadget->Height) / 2;
1088 if ((eb & ETG_MUI) != 0)
1090 if (wd->img_mui->ok)
1092 if (data->dc->GadgetsThreeState) width += (wd->img_mui->w / 3); else width += (wd->img_mui->w >> 2);
1096 if (haszoom)
1098 if (data->dc->GadgetsThreeState) width += (wd->img_zoom->w / 3); else width += (wd->img_zoom->w >> 2);
1101 if (hasclose && data->dc->CloseGadgetOnRight)
1103 if (data->dc->GadgetsThreeState) width += (wd->img_close->w / 3); else width += (wd->img_close->w >> 2);
1105 if (hasdepth)
1107 if (data->dc->GadgetsThreeState) width += (wd->img_depth->w / 3); else width += (wd->img_depth->w >> 2);
1108 gadget->LeftEdge = -data->dc->BarPostGadget_s - width;
1110 else
1112 gadget->LeftEdge = -data->dc->BarPostGadget_s - width;
1114 gadget->Flags &= ~GFLG_RELWIDTH;
1115 gadget->Flags |= GFLG_RELRIGHT;
1118 break;
1120 case ETI_Snapshot:
1121 if (wd->img_snapshot->ok)
1123 if (data->dc->GadgetsThreeState) width = (wd->img_snapshot->w / 3); else width = (wd->img_snapshot->w >> 2);
1125 gadget->Width = width;
1126 gadget->TopEdge = (refheight - gadget->Height) / 2;
1128 if ((eb & ETG_MUI) != 0)
1131 if (wd->img_mui->ok)
1133 if (data->dc->GadgetsThreeState) width += (wd->img_mui->w / 3); else width += (wd->img_mui->w >> 2);
1137 if ((eb & ETG_POPUP) != 0)
1139 if (wd->img_popup->ok)
1141 if (data->dc->GadgetsThreeState) width += (wd->img_popup->w / 3); else width += (wd->img_popup->w >> 2);
1145 if (haszoom)
1147 if (data->dc->GadgetsThreeState) width += (wd->img_zoom->w / 3); else width += (wd->img_zoom->w >> 2);
1150 if (hasclose && data->dc->CloseGadgetOnRight)
1152 if (data->dc->GadgetsThreeState) width += (wd->img_close->w / 3); else width += (wd->img_close->w >> 2);
1155 if (hasdepth)
1157 if (data->dc->GadgetsThreeState) width += (wd->img_depth->w / 3); else width += (wd->img_depth->w >> 2);
1158 gadget->LeftEdge = -data->dc->BarPostGadget_s - width;
1160 else
1162 gadget->LeftEdge = -data->dc->BarPostGadget_s - width;
1165 gadget->Flags &= ~GFLG_RELWIDTH;
1166 gadget->Flags |= GFLG_RELRIGHT;
1169 break;
1171 case ETI_Iconify:
1172 if (wd->img_iconify->ok)
1174 if (data->dc->GadgetsThreeState) width = (wd->img_iconify->w / 3); else width = (wd->img_iconify->w >> 2);
1176 gadget->Width = width;
1177 gadget->TopEdge = (refheight - gadget->Height) / 2;
1179 if ((eb & ETG_MUI) != 0)
1181 if (wd->img_mui->ok)
1183 if (data->dc->GadgetsThreeState) width += (wd->img_mui->w / 3); else width += (wd->img_mui->w >> 2);
1187 if ((eb & ETG_POPUP) != 0)
1189 if (wd->img_popup->ok)
1191 if (data->dc->GadgetsThreeState) width += (wd->img_popup->w / 3); else width += (wd->img_popup->w >> 2);
1195 if ((eb & ETG_SNAPSHOT) != 0)
1197 if (wd->img_snapshot->ok)
1199 if (data->dc->GadgetsThreeState) width += (wd->img_snapshot->w / 3); else width += (wd->img_snapshot->w >> 2);
1203 if (haszoom)
1205 if (data->dc->GadgetsThreeState) width += (wd->img_zoom->w / 3); else width += (wd->img_zoom->w >> 2);
1208 if (hasclose && data->dc->CloseGadgetOnRight)
1210 if (data->dc->GadgetsThreeState) width += (wd->img_close->w / 3); else width += (wd->img_close->w >> 2);
1212 if (hasdepth)
1214 if (data->dc->GadgetsThreeState) width += (wd->img_depth->w / 3); else width += (wd->img_depth->w >> 2);
1215 gadget->LeftEdge = -data->dc->BarPostGadget_s - width;
1217 else
1219 gadget->LeftEdge = -data->dc->BarPostGadget_s - width;
1221 gadget->Flags &= ~GFLG_RELWIDTH;
1222 gadget->Flags |= GFLG_RELRIGHT;
1225 break;
1227 case ETI_Lock:
1228 if (wd->img_lock->ok)
1230 if (data->dc->GadgetsThreeState) width = (wd->img_lock->w / 3); else width = (wd->img_lock->w >> 2);
1232 gadget->Width = width;
1233 gadget->TopEdge = (refheight - gadget->Height) / 2;
1235 if ((eb & ETG_MUI) != 0)
1237 if (wd->img_mui->ok)
1239 if (data->dc->GadgetsThreeState) width += (wd->img_mui->w / 3); else width += (wd->img_mui->w >> 2);
1243 if ((eb & ETG_POPUP) != 0)
1245 if (wd->img_popup->ok)
1247 if (data->dc->GadgetsThreeState) width += (wd->img_popup->w / 3); else width += (wd->img_popup->w >> 2);
1251 if ((eb & ETG_SNAPSHOT) != 0)
1253 if (wd->img_snapshot->ok)
1255 if (data->dc->GadgetsThreeState) width += (wd->img_snapshot->w / 3); else width += (wd->img_snapshot->w >> 2);
1259 if ((eb & ETG_ICONIFY) != 0)
1261 if (wd->img_iconify->ok)
1263 if (data->dc->GadgetsThreeState) width += (wd->img_iconify->w / 3); else width += (wd->img_iconify->w >> 2);
1267 if (haszoom)
1269 if (data->dc->GadgetsThreeState) width += (wd->img_zoom->w / 3); else width += (wd->img_zoom->w >> 2);
1272 if (hasclose && data->dc->CloseGadgetOnRight)
1274 if (data->dc->GadgetsThreeState) width += (wd->img_close->w / 3); else width += (wd->img_close->w >> 2);
1276 if (hasdepth)
1278 if (data->dc->GadgetsThreeState) width += (wd->img_depth->w / 3); else width += (wd->img_depth->w >> 2);
1279 gadget->LeftEdge = -data->dc->BarPostGadget_s - width;
1281 else
1283 gadget->LeftEdge = -data->dc->BarPostGadget_s - width;
1285 gadget->Flags &= ~GFLG_RELWIDTH;
1286 gadget->Flags |= GFLG_RELRIGHT;
1289 break;
1293 else
1295 switch(gadget->GadgetType & GTYP_SYSTYPEMASK)
1297 case GTYP_CLOSE:
1298 if (data->dc->GadgetsThreeState) width = (wd->img_close->w / 3); else width = (wd->img_close->w >> 2);
1299 gadget->Width = width;
1300 wd->closewidth = width;
1301 if (data->dc->CloseGadgetOnRight)
1303 gadget->Flags &= ~GFLG_RELWIDTH;
1304 gadget->Flags |= GFLG_RELRIGHT;
1305 gadget->LeftEdge = -data->dc->BarPostGadget_s - width;
1307 else
1309 gadget->LeftEdge = data->dc->BarPreGadget_s;
1311 gadget->TopEdge = (refheight - gadget->Height) / 2;
1312 break;
1314 case GTYP_WDEPTH:
1315 if (data->dc->GadgetsThreeState) width = (wd->img_depth->w / 3); else width = (wd->img_depth->w >> 2);
1316 gadget->Width = width;
1317 wd->depthwidth = width;
1318 if (hasclose && data->dc->CloseGadgetOnRight)
1320 if (data->dc->GadgetsThreeState) width += (wd->img_close->w / 3); else width += (wd->img_close->w >> 2);
1322 gadget->LeftEdge = -data->dc->BarPostGadget_s - width;
1323 gadget->TopEdge = (refheight - gadget->Height) / 2;
1324 gadget->Flags &= ~GFLG_RELWIDTH;
1325 gadget->Flags |= GFLG_RELRIGHT;
1326 break;
1328 case GTYP_WZOOM:
1329 if (data->dc->GadgetsThreeState) width = (wd->img_zoom->w / 3); else width = (wd->img_zoom->w >> 2);
1330 gadget->Width = width;
1331 wd->zoomwidth = width;
1332 gadget->TopEdge = (refheight - gadget->Height) / 2;
1333 if (hasclose && data->dc->CloseGadgetOnRight)
1335 if (data->dc->GadgetsThreeState) width += (wd->img_close->w / 3); else width += (wd->img_close->w >> 2);
1337 if (hasdepth)
1339 if (data->dc->GadgetsThreeState) width += (wd->img_depth->w / 3); else width += (wd->img_depth->w >> 2);
1340 gadget->LeftEdge = -data->dc->BarPostGadget_s - width;
1342 else
1344 gadget->LeftEdge = -data->dc->BarPostGadget_s - width;
1346 gadget->Flags &= ~GFLG_RELWIDTH;
1347 gadget->Flags |= GFLG_RELRIGHT;
1349 break;
1351 case GTYP_WDRAGGING:
1352 break;
1356 return TRUE;
1359 int sysrgad = -data->dc->BarPostGadget_s - 1;
1361 if (data->dc->CloseGadgetOnRight && hasclose) sysrgad -= wd->closewidth;
1362 if (hasdepth) sysrgad -= wd->depthwidth;
1363 if (haszoom) sysrgad -= wd->zoomwidth;
1364 while(gadget)
1366 if ((gadget->GadgetType & GTYP_SYSTYPEMASK) == 0)
1368 switch(gadget->GadgetType & GTYP_SYSTYPEMASK)
1370 case GTYP_WDRAGGING:
1371 break;
1373 default:
1374 if ((gadget->Flags & GFLG_EXTENDED) != 0)
1376 if ((((struct ExtGadget *) gadget)->MoreFlags & GMORE_BOOPSIGADGET) != 0)
1378 IPTR rtsm = 0;
1379 GetAttr(GA_RightBorder, (Object *) gadget, &rtsm);
1380 if (rtsm)
1382 if (GetAttr(PGA_Top, (Object *) gadget, &rtsm))
1384 SetAttrs((Object *) gadget, GA_RelRight, - data->dc->RightBorderGadgets + ((data->dc->RightBorderGadgets - (wd->img_verticalcontainer->w >> 1) + 1) >> 1) + 1, GA_Width, wd->img_verticalcontainer->w >> 1, TAG_DONE);
1386 else
1388 GetAttr(GA_Width, (Object *) gadget, &rtsm);
1389 SetAttrs((Object *) gadget, GA_RelRight, - data->dc->RightBorderGadgets + ((data->dc->RightBorderGadgets - rtsm + 1) >> 1) + 1, TAG_DONE);
1392 else
1394 GetAttr(GA_BottomBorder, (Object *) gadget, &rtsm);
1395 if (rtsm)
1397 if (GetAttr(PGA_Top, (Object *) gadget, &rtsm))
1399 SetAttrs((Object *) gadget, GA_RelBottom, - data->dc->BottomBorderGadgets + ((data->dc->BottomBorderGadgets - (wd->img_horizontalcontainer->h >> 1) + 1) >> 1) +1, GA_Height, (wd->img_horizontalcontainer->h >> 1), TAG_DONE);
1401 else
1403 GetAttr(GA_Height, (Object *) gadget, &rtsm);
1404 SetAttrs((Object *) gadget, GA_RelBottom, - data->dc->BottomBorderGadgets + ((data->dc->BottomBorderGadgets - rtsm + 1) >> 1) + 1, TAG_DONE);
1410 break;
1413 if (msg->wdp_Flags & WDF_LBG_MULTIPLE)
1415 gadget = gadget->NextGadget;
1417 else
1419 gadget = NULL;
1422 gadget = msg->wdp_Gadgets;
1424 while(gadget)
1426 if ((gadget->GadgetType & GTYP_SYSTYPEMASK) == 0)
1428 if ((gadget->Activation & GACT_TOPBORDER) != 0)
1430 if ((gadget->Flags & GFLG_RELRIGHT) != 0)
1432 gadget->TopEdge = (refheight - gadget->Height) / 2;
1433 sysrgad -= gadget->Width;
1434 gadget->LeftEdge = sysrgad;
1438 gadget = gadget->NextGadget;
1441 gadget = msg->wdp_Gadgets;
1443 if ((msg->wdp_Flags & WDF_LBG_SYSTEMGADGET) != 0) while(gadget)
1445 switch(gadget->GadgetType & GTYP_SYSTYPEMASK)
1447 case GTYP_WDRAGGING:
1448 gadget->Width = sysrgad;
1449 if (hasclose && !data->dc->CloseGadgetOnRight)
1451 gadget->Width -= data->dc->BarPreGadget_s;
1452 if (data->dc->GadgetsThreeState) gadget->Width -= (wd->img_close->w / 3); else gadget->Width -= (wd->img_close->w >> 2);
1454 break;
1456 gadget = gadget->NextGadget;
1459 if (draggadget)
1463 return TRUE;
1466 /**************************************************************************************************/
1467 static IPTR windecor_draw_borderpropback(Class *cl, Object *obj, struct wdpDrawBorderPropBack *msg)
1469 /* Simply return, we need to render the back in the knob method */
1470 /* because we want to use irregular (alpha images) for the sliders */
1471 return TRUE;
1474 /**************************************************************************************************/
1475 static IPTR windecor_draw_borderpropknob(Class *cl, Object *obj, struct wdpDrawBorderPropKnob *msg)
1477 struct windecor_data *data = INST_DATA(cl, obj);
1478 struct Window *window = msg->wdp_Window;
1479 struct RastPort *winrp = msg->wdp_RPort;
1480 struct WindowData *wd = (struct WindowData *) msg->wdp_UserBuffer;
1482 struct RastPort *rp;
1483 struct Gadget *gadget = msg->wdp_Gadget;
1484 struct Rectangle *r;
1485 struct PropInfo *pi = ((struct PropInfo *)gadget->SpecialInfo);
1486 struct NewImage *ni = NULL;
1487 BOOL hit = (msg->wdp_Flags & WDF_DBPK_HIT) ? TRUE : FALSE;
1488 ULONG y, x, bx0, bx1, by0, by1;
1489 LONG size;
1490 ULONG s_col, e_col, arc;
1491 LONG pen = -1;
1492 struct BitMap *cachedgadgetbitmap = NULL;
1493 ULONG changetype = CHANGE_NO_CHANGE;
1494 ULONG subimage = 0;
1496 if (!(pi->Flags & PROPNEWLOOK) || (gadget->Activation && (GACT_RIGHTBORDER | GACT_BOTTOMBORDER) == 0))
1498 return DoSuperMethodA(cl, obj, (Msg)msg);
1501 /* Detect change in gadget dimensions (which needs to trigger redraw) */
1502 if ((pi->Flags & FREEVERT) != 0)
1504 changetype = HasPropGadgetChanged(&wd->vert, msg);
1506 if (changetype == CHANGE_SIZE_CHANGE)
1508 /* Free is there was size change */
1509 if (wd->vert.bm != NULL)
1510 FreeBitMap(wd->vert.bm);
1511 wd->vert.bm = NULL;
1513 cachedgadgetbitmap = wd->vert.bm;
1515 else if ((pi->Flags & FREEHORIZ) != 0)
1517 changetype = HasPropGadgetChanged(&wd->horiz, msg);
1519 if (changetype == CHANGE_SIZE_CHANGE)
1521 /* Free is there was size change */
1522 if (wd->horiz.bm != NULL)
1523 FreeBitMap(wd->horiz.bm);
1524 wd->horiz.bm = NULL;
1526 cachedgadgetbitmap = wd->horiz.bm;
1529 else
1530 return TRUE; /* Return TRUE - after all this is not an error */
1532 /* Reuse the bitmap if that is possible */
1533 if (changetype == CHANGE_NO_CHANGE)
1535 /* Final blitting of gadget bitmap to window rast port */
1536 BltBitMapRastPort(cachedgadgetbitmap, 0, 0, winrp, msg->wdp_PropRect->MinX,
1537 msg->wdp_PropRect->MinY,
1538 msg->wdp_PropRect->MaxX - msg->wdp_PropRect->MinX + 1,
1539 msg->wdp_PropRect->MaxY - msg->wdp_PropRect->MinY + 1, 0xc0);
1540 return TRUE;
1543 /* Regenerate the bitmap */
1544 r = msg->wdp_PropRect;
1546 bx0 = r->MinX;
1547 by0 = r->MinY;
1548 bx1 = r->MaxX;
1549 by1 = r->MaxY;
1551 rp = CreateRastPort();
1552 if (rp)
1554 /* Reuse the bitmap if there was no size change (ie. only move of knob) */
1555 if (changetype == CHANGE_NO_SIZE_CHANGE)
1556 rp->BitMap = cachedgadgetbitmap;
1557 else
1558 rp->BitMap = AllocBitMap(bx1 - bx0 + 1, by1 - by0 + 1, 1, 0, window->WScreen->RastPort.BitMap);
1560 if (rp->BitMap == NULL)
1562 FreeRastPort(rp);
1563 return FALSE;
1566 else
1567 return FALSE;
1569 if (wd->img_border_normal->ok) ni = wd->img_border_normal;
1571 if (ni == NULL) data->dc->UseGradients = TRUE;
1573 if (window->Flags & (WFLG_WINDOWACTIVE | WFLG_TOOLBOX))
1575 s_col = data->dc->ActivatedGradientColor_s;
1576 e_col = data->dc->ActivatedGradientColor_e;
1577 arc = data->dc->ActivatedGradientColor_a;
1578 pen = wd->ActivePen;
1580 else
1582 s_col = data->dc->DeactivatedGradientColor_s;
1583 e_col = data->dc->DeactivatedGradientColor_e;
1584 arc = data->dc->DeactivatedGradientColor_a;
1585 if (!data->dc->UseGradients)
1587 if (wd->img_border_deactivated->ok) ni = wd->img_border_deactivated;
1589 pen = wd->DeactivePen;
1592 /* Drawing background - this solves WDM_DRAW_BORDERPROPBACK without need of
1593 reading from window when drawing container and knob */
1594 if (data->dc->UseGradients)
1596 FillPixelArrayGradient(pen, wd->truecolor, rp, 0, 0, window->Width-1, window->Height-1, 0, 0, bx1 - bx0 + 1, by1 - by0 + 1, s_col, e_col, arc, bx0, by0);
1598 else
1600 if (ni->ok)
1602 ULONG color = 0x00cccccc;
1603 HorizVertRepeatNewImage(ni, color, bx0, by0, rp, 0, 0, bx1 - bx0 + 1, by1 - by0 + 1);
1607 /* Drawing knob container */
1608 r = msg->wdp_PropRect;
1610 bx0 = 0;
1611 by0 = 0;
1612 bx1 = r->MaxX - r->MinX;
1613 by1 = r->MaxY - r->MinY;
1615 if ((pi->Flags & FREEVERT) != 0)
1617 if (window->Flags & (WFLG_WINDOWACTIVE | WFLG_TOOLBOX)) subimage = 0; else subimage = 1;
1618 y = by0;
1619 size = by1 - by0 - data->dc->ContainerTop_s - data->dc->ContainerBottom_s + 1;
1620 y = WriteTiledImageVertical(rp, wd->img_verticalcontainer, subimage, data->dc->ContainerTop_o, data->dc->ContainerTop_s, bx0, y, data->dc->ContainerTop_s);
1621 if (size > 0) y = WriteTiledImageVertical(rp, wd->img_verticalcontainer, subimage, data->dc->ContainerVertTile_o, data->dc->ContainerVertTile_s, bx0, y, size);
1623 y = WriteTiledImageVertical(rp, wd->img_verticalcontainer, subimage, data->dc->ContainerBottom_o, data->dc->ContainerBottom_s, bx0, y, data->dc->ContainerBottom_s);
1626 else if ((pi->Flags & FREEHORIZ) != 0)
1628 if (window->Flags & (WFLG_WINDOWACTIVE | WFLG_TOOLBOX)) subimage = 0; else subimage = 1;
1629 x = bx0;
1630 size = bx1 - bx0 - data->dc->ContainerLeft_s - data->dc->ContainerRight_s + 1;
1631 x = WriteTiledImageHorizontal(rp, wd->img_horizontalcontainer, subimage, data->dc->ContainerLeft_o, data->dc->ContainerLeft_s, x, by0, data->dc->ContainerLeft_s);
1632 if (size > 0) x = WriteTiledImageHorizontal(rp, wd->img_horizontalcontainer, subimage, data->dc->ContainerHorTile_o, data->dc->ContainerHorTile_s, x, by0, size);
1633 x = WriteTiledImageHorizontal(rp, wd->img_horizontalcontainer, subimage, data->dc->ContainerRight_o, data->dc->ContainerRight_s, x, by0, data->dc->ContainerRight_s);
1637 /* Drawing knob */
1638 bx0 = msg->wdp_PropRect->MinX;
1639 by0 = msg->wdp_PropRect->MinY;
1640 bx1 = msg->wdp_PropRect->MaxX;
1641 by1 = msg->wdp_PropRect->MaxY;
1643 r = msg->wdp_RenderRect;
1644 if ((pi->Flags & FREEVERT) != 0)
1646 if (hit) subimage = 1; else if (window->Flags & (WFLG_WINDOWACTIVE | WFLG_TOOLBOX)) subimage = 0; else subimage = 2;
1647 y = r->MinY - by0;
1648 size = r->MaxY - r->MinY - data->dc->KnobTop_s - data->dc->KnobBottom_s + 1;
1650 y = WriteTiledImageVertical(rp, wd->img_verticalknob, subimage, data->dc->KnobTop_o, data->dc->KnobTop_s, r->MinX - bx0, y, data->dc->KnobTop_s);
1651 if (size > 0)
1653 if (size > data->dc->KnobVertGripper_s)
1655 size = size - data->dc->KnobVertGripper_s;
1656 int size_bak = size;
1657 size = size / 2;
1658 if (size > 0) y = WriteTiledImageVertical(rp, wd->img_verticalknob, subimage, data->dc->KnobTileTop_o, data->dc->KnobTileTop_s, r->MinX - bx0, y, size);
1659 y = WriteTiledImageVertical(rp, wd->img_verticalknob, subimage, data->dc->KnobVertGripper_o, data->dc->KnobVertGripper_s, r->MinX - bx0, y, data->dc->KnobVertGripper_s);
1660 size = size_bak - size;
1661 if (size > 0) y = WriteTiledImageVertical(rp, wd->img_verticalknob, subimage, data->dc->KnobTileBottom_o, data->dc->KnobTileBottom_s, r->MinX - bx0, y, size);
1663 else
1665 y = WriteTiledImageVertical(rp, wd->img_verticalknob, subimage, data->dc->KnobTileTop_o, data->dc->KnobTileTop_s, r->MinX - bx0, y, size);
1668 y = WriteTiledImageVertical(rp, wd->img_verticalknob, subimage, data->dc->KnobBottom_o, data->dc->KnobBottom_s, r->MinX - bx0, y, data->dc->KnobBottom_s);
1670 else if ((pi->Flags & FREEHORIZ) != 0)
1672 if (hit) subimage = 1; else if (window->Flags & (WFLG_WINDOWACTIVE | WFLG_TOOLBOX)) subimage = 0; else subimage = 2;
1673 x = r->MinX - bx0;
1674 size = r->MaxX - r->MinX - data->dc->KnobLeft_s - data->dc->KnobRight_s + 1;
1675 x = WriteTiledImageHorizontal(rp, wd->img_horizontalknob, subimage, data->dc->KnobLeft_o, data->dc->KnobLeft_s, x, r->MinY - by0, data->dc->KnobLeft_s);
1677 if (size > 0)
1679 if (size > data->dc->KnobHorGripper_s)
1681 size = size - data->dc->KnobHorGripper_s;
1682 int size_bak = size;
1683 size = size / 2;
1684 if (size > 0) x = WriteTiledImageHorizontal(rp, wd->img_horizontalknob, subimage, data->dc->KnobTileLeft_o, data->dc->KnobTileLeft_s, x, r->MinY - by0, size);
1685 x = WriteTiledImageHorizontal(rp, wd->img_horizontalknob, subimage, data->dc->KnobHorGripper_o, data->dc->KnobHorGripper_s, x, r->MinY - by0, data->dc->KnobHorGripper_s);
1686 size = size_bak - size;
1687 if (size > 0) x = WriteTiledImageHorizontal(rp, wd->img_horizontalknob, subimage, data->dc->KnobTileRight_o, data->dc->KnobTileRight_s, x, r->MinY - by0, size);
1689 else
1691 x = WriteTiledImageHorizontal(rp, wd->img_horizontalknob, subimage, data->dc->KnobTileRight_o, data->dc->KnobTileRight_s, x, r->MinY - by0, size);
1694 x = WriteTiledImageHorizontal(rp, wd->img_horizontalknob, subimage, data->dc->KnobRight_o, data->dc->KnobRight_s, x, r->MinY - by0, data->dc->KnobRight_s);
1697 /* Final blitting of gadget bitmap to window rast port */
1698 BltBitMapRastPort(rp->BitMap, 0, 0, winrp, msg->wdp_PropRect->MinX,
1699 msg->wdp_PropRect->MinY,
1700 msg->wdp_PropRect->MaxX - msg->wdp_PropRect->MinX + 1,
1701 msg->wdp_PropRect->MaxY - msg->wdp_PropRect->MinY + 1, 0xc0);
1703 /* Cache the actual bitmap */
1704 if ((pi->Flags & FREEVERT) != 0)
1705 CachePropGadget(&wd->vert, msg, rp->BitMap);
1706 else if ((pi->Flags & FREEHORIZ) != 0)
1707 CachePropGadget(&wd->horiz, msg, rp->BitMap);
1709 FreeRastPort(rp);
1711 return TRUE;
1714 /**************************************************************************************************/
1715 static IPTR windecor_getdefsizes(Class *cl, Object *obj, struct wdpGetDefSizeSysImage *msg)
1717 struct windecor_data *data = INST_DATA(cl, obj);
1718 struct NewImage *n = NULL;
1719 WORD w = 0, h = 0;
1720 BOOL isset = FALSE;
1721 BOOL titlegadget = FALSE;
1723 switch(msg->wdp_Which)
1725 case SIZEIMAGE:
1726 n = NULL;
1727 w = data->dc->RightBorderGadgets;
1728 h = data->dc->BottomBorderGadgets;
1729 isset = TRUE;
1730 break;
1732 case CLOSEIMAGE:
1733 n = data->img_close;
1734 if(n) isset = TRUE;
1735 titlegadget = TRUE;
1736 break;
1738 case MUIIMAGE:
1739 n = data->img_mui;
1740 if(n) isset = TRUE;
1741 titlegadget = TRUE;
1742 break;
1744 case POPUPIMAGE:
1745 n = data->img_popup;
1746 if(n) isset = TRUE;
1747 titlegadget = TRUE;
1748 break;
1750 case SNAPSHOTIMAGE:
1751 n = data->img_snapshot;
1752 if(n) isset = TRUE;
1753 titlegadget = TRUE;
1754 break;
1756 case ICONIFYIMAGE:
1757 n = data->img_iconify;
1758 if(n) isset = TRUE;
1759 titlegadget = TRUE;
1760 break;
1762 case LOCKIMAGE:
1763 n = data->img_lock;
1764 if(n) isset = TRUE;
1765 titlegadget = TRUE;
1766 break;
1768 case UPIMAGE:
1769 n = NULL;
1770 w = data->dc->RightBorderGadgets;
1771 h = data->img_up->h + data->dc->UpDownAddY;
1772 isset = TRUE;
1773 break;
1775 case DOWNIMAGE:
1776 n = NULL;
1777 w = data->dc->RightBorderGadgets;
1778 h = data->img_down->h + data->dc->UpDownAddY;
1779 isset = TRUE;
1780 break;
1782 case LEFTIMAGE:
1783 n = NULL;
1784 if (data->dc->GadgetsThreeState) w = (data->img_left->w / 3); else w = (data->img_left->w >> 2);
1785 w += data->dc->LeftRightAddX;
1786 h = data->dc->BottomBorderGadgets;
1787 isset = TRUE;
1788 break;
1790 case RIGHTIMAGE:
1791 n = NULL;
1792 if (data->dc->GadgetsThreeState) w = (data->img_right->w / 3); else w = (data->img_right->w >> 2);
1793 w += data->dc->LeftRightAddX;
1794 h = data->dc->BottomBorderGadgets;
1795 isset = TRUE;
1796 break;
1798 case DEPTHIMAGE:
1799 n = data->img_depth;
1800 if(n) isset = TRUE;
1801 titlegadget = TRUE;
1802 break;
1804 case ZOOMIMAGE:
1805 n = data->img_zoom;
1806 if(n) isset = TRUE;
1807 titlegadget = TRUE;
1808 break;
1810 default:
1811 return FALSE;
1814 if (!isset) return DoSuperMethodA(cl, obj, (Msg) msg);
1816 if (n == NULL)
1818 *msg->wdp_Width = w;
1819 *msg->wdp_Height = h;
1821 else
1823 if (n->ok)
1825 if (data->dc->GadgetsThreeState)
1827 *msg->wdp_Width = (n->w / 3);
1828 *msg->wdp_Height = n->h;
1830 else
1832 *msg->wdp_Width = (n->w >> 2);
1833 *msg->wdp_Height = n->h;
1836 if(titlegadget && (msg->wdp_ReferenceFont->tf_YSize + 2 > data->dc->BarHeight))
1838 /* Scale height so that the gadget is not proportionally resized (so that width does not change) */
1839 *msg->wdp_Height *= msg->wdp_ReferenceFont->tf_YSize + 2;
1840 *msg->wdp_Height /= data->dc->BarHeight;
1842 } else return DoSuperMethodA(cl, obj, (Msg) msg);
1845 return TRUE;
1848 /**************************************************************************************************/
1849 static IPTR windecor_windowshape(Class *cl, Object *obj, struct wdpWindowShape *msg)
1851 struct windecor_data *data = INST_DATA(cl, obj);
1852 struct WindowData *wd = (struct WindowData *) msg->wdp_UserBuffer;
1853 struct Window *window = msg->wdp_Window;
1855 if (data->dc->BarMasking)
1857 if (HasTitleBarShapeChanged(&wd->tbarshape, window) != CHANGE_NO_CHANGE)
1859 struct NewLUT8ImageContainer *shape;
1860 struct Region * newreg = NULL;
1862 if (wd->tbarshape.shape != NULL)
1864 DisposeRegion(wd->tbarshape.shape);
1865 wd->tbarshape.shape = NULL;
1868 shape = (struct NewLUT8ImageContainer *)NewLUT8ImageContainer(window->Width, window->BorderTop);
1869 if (shape)
1871 if (window->BorderTop > 0) DrawShapePartialTitleBar(wd, (struct NewLUT8Image *)shape, data, window);
1873 newreg = RegionFromLUT8Image(msg->wdp_Width, msg->wdp_Height, (struct NewLUT8Image *)shape);
1874 DisposeLUT8ImageContainer((struct NewLUT8Image *)shape);
1876 CacheTitleBarShape(&wd->tbarshape, window, newreg);
1880 /* Make a copy of region and return it */
1881 return (IPTR)CopyRegion(wd->tbarshape.shape);
1885 if (!data->dc->BarRounded) return (IPTR) NULL;
1887 struct Region *newshape;
1889 int x2 = msg->wdp_Width-1;
1890 int y2 = msg->wdp_Height-1;
1892 if ((newshape = NewRegion()))
1894 struct Rectangle rect;
1895 BOOL success = TRUE;
1897 rect.MinX = 9;
1898 rect.MinY = 0;
1899 rect.MaxX = x2 - 9;
1900 rect.MaxY = y2;
1901 success &= OrRectRegion(newshape, &rect);
1903 rect.MinX = 6;
1904 rect.MinY = 1;
1905 rect.MaxX = x2 - 6;
1906 rect.MaxY = y2;
1907 success &= OrRectRegion(newshape, &rect);
1909 rect.MinX = 4;
1910 rect.MinY = 2;
1911 rect.MaxX = x2 - 4;
1912 rect.MaxY = y2;
1913 success &= OrRectRegion(newshape, &rect);
1915 rect.MinX = 3;
1916 rect.MinY = 3;
1917 rect.MaxX = x2 - 3;
1918 rect.MaxY = y2;
1919 success &= OrRectRegion(newshape, &rect);
1921 rect.MinX = 2;
1922 rect.MinY = 4;
1923 rect.MaxX = x2 - 2;
1924 rect.MaxY = y2;
1925 success &= OrRectRegion(newshape, &rect);
1927 rect.MinX = 1;
1928 rect.MinY = 6;
1929 rect.MaxX = x2 - 1;
1930 rect.MaxY = y2;
1931 success &= OrRectRegion(newshape, &rect);
1933 rect.MinX = 0;
1934 rect.MinY = 9;
1935 rect.MaxX = x2;
1936 rect.MaxY = y2;
1937 success &= OrRectRegion(newshape, &rect);
1939 return (IPTR) newshape;
1942 /**************************************************************************************************/
1943 static IPTR windecor_initwindow(Class *cl, Object *obj, struct wdpInitWindow *msg)
1945 struct WindowData *wd = (struct WindowData *)msg->wdp_UserBuffer;
1946 struct ScreenData *sd = (struct ScreenData *)msg->wdp_ScreenUserBuffer;
1948 wd->truecolor = msg->wdp_TrueColor;
1950 wd->ActivePen = sd->ActivePen;
1951 wd->DeactivePen = sd->DeactivePen;
1953 wd->vert.bm = NULL;
1954 wd->horiz.bm = NULL;
1956 SETIMAGE_WIN(size);
1957 SETIMAGE_WIN(close);
1958 SETIMAGE_WIN(depth);
1959 SETIMAGE_WIN(zoom);
1960 SETIMAGE_WIN(up);
1961 SETIMAGE_WIN(down);
1962 SETIMAGE_WIN(left);
1963 SETIMAGE_WIN(right);
1964 SETIMAGE_WIN(mui);
1965 SETIMAGE_WIN(popup);
1966 SETIMAGE_WIN(snapshot);
1967 SETIMAGE_WIN(iconify);
1968 SETIMAGE_WIN(lock);
1969 SETIMAGE_WIN(winbar_normal);
1970 SETIMAGE_WIN(border_normal);
1971 SETIMAGE_WIN(border_deactivated);
1972 SETIMAGE_WIN(verticalcontainer);
1973 SETIMAGE_WIN(verticalknob);
1974 SETIMAGE_WIN(horizontalcontainer);
1975 SETIMAGE_WIN(horizontalknob);
1977 return TRUE;
1980 /**************************************************************************************************/
1981 static IPTR windecor_exitwindow(Class *cl, Object *obj, struct wdpExitWindow *msg)
1983 struct WindowData *wd = (struct WindowData *) msg->wdp_UserBuffer;
1985 if (wd->vert.bm) FreeBitMap(wd->vert.bm);
1986 if (wd->horiz.bm) FreeBitMap(wd->horiz.bm);
1987 if (wd->tbar.bm) FreeBitMap(wd->tbar.bm);
1988 if (wd->tbarshape.shape) DisposeRegion(wd->tbarshape.shape);
1989 if (wd->tbar.title) FreeVec(wd->tbar.title);
1991 return TRUE;
1994 /**************************************************************************************************/
1995 static IPTR windecor_dispatcher(struct IClass *cl, Object *obj, Msg msg)
1997 IPTR retval;
1999 switch(msg->MethodID)
2001 case OM_NEW:
2002 retval = windecor_new(cl, obj, (struct opSet *)msg);
2003 break;
2005 case OM_DISPOSE:
2006 retval = windecor_dispose(cl, obj, (struct opSet *)msg);
2007 break;
2009 case OM_GET:
2010 retval = windecor_get(cl, obj, (struct opGet *)msg);
2011 break;
2013 case WDM_DRAW_SYSIMAGE:
2014 retval = windecor_draw_sysimage(cl, obj, (struct wdpDrawSysImage *)msg);
2015 break;
2017 case WDM_DRAW_WINBORDER:
2018 retval = windecor_draw_winborder(cl, obj, (struct wdpDrawWinBorder *)msg);
2019 break;
2021 case WDM_LAYOUT_BORDERGADGETS:
2022 retval = windecor_layout_bordergadgets(cl, obj, (struct wdpLayoutBorderGadgets *)msg);
2023 break;
2025 case WDM_DRAW_BORDERPROPBACK:
2026 retval = windecor_draw_borderpropback(cl, obj, (struct wdpDrawBorderPropBack *)msg);
2027 break;
2029 case WDM_DRAW_BORDERPROPKNOB:
2030 retval = windecor_draw_borderpropknob(cl, obj, (struct wdpDrawBorderPropKnob *)msg);
2031 break;
2033 case WDM_GETDEFSIZE_SYSIMAGE:
2034 retval = windecor_getdefsizes(cl, obj, (struct wdpGetDefSizeSysImage *) msg);
2035 break;
2037 case WDM_WINDOWSHAPE:
2038 retval = windecor_windowshape(cl, obj, (struct wdpWindowShape *) msg);
2039 break;
2041 case WDM_INITWINDOW:
2042 retval = windecor_initwindow(cl, obj, (struct wdpInitWindow *) msg);
2043 break;
2045 case WDM_EXITWINDOW:
2046 retval = windecor_exitwindow(cl, obj, (struct wdpExitWindow *) msg);
2047 break;
2049 default:
2050 retval = DoSuperMethodA(cl, obj, msg);
2051 break;
2054 return retval;
2057 struct IClass * MakeWindowDecorClass()
2059 struct IClass * cl = MakeClass(NULL, WINDECORCLASS, NULL, sizeof(struct windecor_data), 0);
2060 if (cl)
2062 cl->cl_Dispatcher.h_Entry = HookEntry;
2063 cl->cl_Dispatcher.h_SubEntry = (HOOKFUNC)windecor_dispatcher;
2066 return cl;