4 * Redrawing template windows
6 * © 1994-1998 Straylight
9 /*----- Licensing note ----------------------------------------------------*
11 * This file is part of Straylight's Glass.
13 * Glass is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2, or (at your option)
18 * Glass is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with Glass. If not, write to the Free Software Foundation,
25 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 /*----- Header files ------------------------------------------------------*/
31 * ANSI standard headers
44 #include "steel/Steel.h"
46 #include "steel/interface.h"
47 #include "steel/sculptrix.h"
48 #include "steel/bbc.h"
49 #include "steel/coords.h"
65 /*----- Main code ---------------------------------------------------------*/
68 * void window__drawSelectBox(glass_windPointer *w,
74 * Draws the selection box around an icon
77 * glass_windPointer *w == the window
78 * int icon == the icon
79 * BOOL makesi == whether we're going between a selected and main selected
81 * wimp_redrawstr *r == the redraw structure
84 #define HW window__HANDLEWIDTH
86 void window__drawSelectBox(glass_windPointer *w,
92 int ox=r->box.x0-r->scx;
93 int oy=r->box.y1-r->scy;
95 window_boundingBox(w,icon,&box);
97 /* --- If we're in test mode, do nothing --- */
105 /* --- If we're not renumbering, draw in all the fancy bits --- */
110 /* --- Make sure the user wants a border, and draw the right one --- */
112 if (gPrefs_current()->sBorder && !makesi)
114 window__setXORColour(w,window__SELBOXCOL);
115 if (gPrefs_current()->sDotted)
117 window__makeDashPattern(0xf0);
118 window__rectangle(ox+box.x0-wimpt_dx(),
119 oy+box.y0-wimpt_dy(),
120 box.x1-box.x0+wimpt_dx(),
121 box.y1-box.y0+wimpt_dy());
125 bbc_rectangle(ox+box.x0-wimpt_dx(),
126 oy+box.y0-wimpt_dy(),
127 box.x1-box.x0+wimpt_dx(),
128 box.y1-box.y0+wimpt_dy());
132 /* --- Draw in all the drag handles --- */
135 window__colourChange(window__MSELBOXCOL,window__HANDCOL);
136 else if (icon==window__selectedIcon())
137 window__setXORColour(w,window__MSELBOXCOL);
139 window__setXORColour(w,window__HANDCOL);
141 /* If edges are wanted, fill them in */
143 if (gPrefs_current()->sEdgeHandles)
145 bbc_rectanglefill(ox+box.x0-wimpt_dx()-HW,
146 oy+box.y0+(box.y1-box.y0-HW*2)/2,
149 bbc_rectanglefill(ox+box.x1-HW,
150 oy+box.y0+(box.y1-box.y0-HW*2)/2,
153 bbc_rectanglefill(ox+box.x0+(box.x1-box.x0-HW*2)/2,
154 oy+box.y0-wimpt_dy()-HW,
157 bbc_rectanglefill(ox+box.x0+(box.x1-box.x0-HW*2)/2,
163 /* Corners are always drawn */
165 bbc_rectanglefill(ox+box.x0-wimpt_dx()-HW,
166 oy+box.y0-wimpt_dy()-HW,
169 bbc_rectanglefill(ox+box.x1-HW,
170 oy+box.y0-wimpt_dy()-HW,
173 bbc_rectanglefill(ox+box.x0-wimpt_dx()-HW,
177 bbc_rectanglefill(ox+box.x1-HW,
184 /* --- Otherwise, we do the funny renumbering corner bits --- */
187 window__setXORColour(w,window__HANDCOL);
188 bbc_move(ox+box.x0-8,oy+box.y1-wimpt_dy()-12);
191 bbc_move(ox+box.x1-wimpt_dx()+8,oy+box.y1-wimpt_dy()-12);
194 bbc_move(ox+box.x0-8,oy+box.y0+12);
197 bbc_move(ox+box.x1-wimpt_dx()+8,oy+box.y0+12);
206 * void window__redrawDragBox(glass_windPointer *w,
212 * Redraws the screen during a drag operation, either to update the window
213 * during the drag, or to redraw the window should something silly happen
217 * glass_windPointer *w == pointer to the window owning drag
218 * wimp_redrawstr *r == pointer to current redraw
219 * int x,int y == coordinates to draw drag relative to...
222 void window__redrawDragBox(glass_windPointer *w,wimp_redrawstr *r,
225 int ox=r->box.x0-r->scx;
226 int oy=r->box.y1-r->scy;
231 int type=window__qDragType();
234 /* --- If we don't know which window to draw in, don't --- */
236 if (!window__dragWind())
239 /* --- Work out what we have to draw --- */
241 window__dragStart(&sx,&sy);
245 /* --- A selection box -- draw a rubber rectangle --- */
247 case window__SELECT: /* Drag out a box to select icons */
248 window__rectangle(sx+ox,sy+oy,x-sx,y-sy);
251 /* --- We're grabbing an icon, so this is like a move --- *
253 * We can't actually use the main move code, because it works on all
254 * selected icons, and the one we're drawing doesn't actually exist as
258 case window__GRABICON:
259 box=window__qDragBox();
264 window__rectangle(ox+box.x0,
266 box.x1-box.x0-wimpt_dx(),
267 box.y1-box.y0-wimpt_dy());
270 /* --- Guidelines moving -- draw all the guides which are moving --- */
272 case window__HORGUIDE:
273 for (i=0;i<glass_GUIDELIMIT;i++)
275 if (w->guide[i].active && w->guide[i].selected && w->guide[i].horiz)
277 bbc_plot(bbc_DottedBoth+bbc_MoveCursorAbs,
278 ox+w->def->desc.w.ex.x0,
279 oy+w->guide[i].coord+y-sy);
280 bbc_plot(bbc_DottedBoth+bbc_DrawAbsFore,
281 ox+w->def->desc.w.ex.x1,
282 oy+w->guide[i].coord+y-sy);
286 case window__VERGUIDE:
287 for (i=0;i<glass_GUIDELIMIT;i++)
289 if (w->guide[i].active && w->guide[i].selected && !w->guide[i].horiz)
291 bbc_plot(bbc_DottedBoth+bbc_MoveCursorAbs,
292 ox+w->guide[i].coord+x-sx,
293 oy+w->def->desc.w.ex.y0);
294 bbc_plot(bbc_DottedBoth+bbc_DrawAbsFore,
295 ox+w->guide[i].coord+x-sx,
296 oy+w->def->desc.w.ex.y1);
301 /* --- Normal icon moves/resizes --- *
303 * We find out where the box is according to the drag-type bitfield,
304 * and draw that for each selected icon.
308 for (i=0;i<w->def->desc.w.nicons;i++)
310 if (w->def->i[i].selected)
312 window_boundingBox(w,i,&box);
313 bw=(w->def->i[i].i.box.x0-box.x0) + (box.x1-w->def->i[i].i.box.x1);
314 bh=(w->def->i[i].i.box.y0-box.y0) + (box.y1-w->def->i[i].i.box.y1);
316 /* --- Adjust coordinates according to drag type --- */
318 if (type & window__TOP)
320 if (type & window__BOTTOM)
322 if (type & window__LEFT)
324 if (type & window__RIGHT)
327 /* --- Ensure that the box is not inside-out --- */
329 if (type & window__TOP)
331 if (box.y1-box.y0<bh)
334 if (type & window__BOTTOM)
336 if (box.y1-box.y0<bh)
339 if (type & window__LEFT)
341 if (box.x1-box.x0<bw)
344 if (type & window__RIGHT)
346 if (box.x1-box.x0<bw)
350 window__rectangle(ox+box.x0,
352 box.x1-box.x0-wimpt_dx(),
353 box.y1-box.y0-wimpt_dy());
361 * void window__redraw(glass_windPointer *w,wimp_redrawstr *r,BOOL *more)
364 * Redraws a window following a call to Wimp_UpdateWindow or
368 * glass_windPointer *w == the window to draw
369 * wimp_redrawstr *r == stuff about the redraw
370 * BOOL *more == whether there is more to do
373 void window__redraw(glass_windPointer *w,wimp_redrawstr *r,BOOL *more)
384 int ox=r->box.x0-r->scx;
385 int oy=r->box.y1-r->scy;
387 /* --- Make Sculptrix use the right sprite area --- */
389 sculptrix_setSpriteArea(w->t->s);
391 /* --- Do the redraw for each rectangle the WIMP gives us --- */
396 /* --- Draw the grid --- */
404 xx=((r->g.x0-ox)/w->gridx)*w->gridx-w->gridx;
405 yy=((r->g.y0-oy)/w->gridy)*w->gridy-w->gridy;
406 XX=((r->g.x1-ox)/w->gridx)*w->gridx+w->gridx;
407 YY=((r->g.y1-oy)/w->gridy)*w->gridy+w->gridy;
408 wimp_setcolour(gPrefs_current()->gGridCol);
409 if (gPrefs_current()->gLines)
411 for (x=xx;x<=XX;x+=w->gridx)
413 bbc_move(x+ox,yy+oy);
414 bbc_draw(x+ox,YY+oy);
416 for (y=yy;y<=YY;y+=w->gridy)
418 bbc_move(xx+ox,y+oy);
419 bbc_draw(XX+ox,y+oy);
424 for (x=xx;x<=XX;x+=w->gridx)
426 for (y=yy;y<=YY;y+=w->gridy)
427 bbc_plot(bbc_Point+bbc_DrawAbsFore,x+ox,y+oy);
432 /* --- Draw guidelines --- */
438 for (i=0;i<glass_GUIDELIMIT;i++)
440 if (w->guide[i].active)
442 if (w->guide[i].selected)
444 wimp_setcolour(window__GDESELCOL);
445 window__makeDashPattern(0xff);
449 wimp_setcolour(window__GUIDECOL);
450 window__makeDashPattern(0x33);
452 if (w->guide[i].horiz)
454 bbc_plot(bbc_DottedBoth+bbc_MoveCursorAbs,
455 ox+w->def->desc.w.ex.x0,
456 oy+w->guide[i].coord);
457 bbc_plot(bbc_DottedBoth+bbc_DrawAbsFore,
458 ox+w->def->desc.w.ex.x1,
459 oy+w->guide[i].coord);
463 bbc_plot(bbc_DottedBoth+bbc_MoveCursorAbs,
464 ox+w->guide[i].coord,
465 oy+w->def->desc.w.ex.y0);
466 bbc_plot(bbc_DottedBoth+bbc_DrawAbsFore,
467 ox+w->guide[i].coord,
468 oy+w->def->desc.w.ex.y1);
474 /* --- Draw the hatch pattern, if applicable --- */
476 if (gPrefs_current()->mDrawHatch &&
477 !(w->def->desc.w.flags & wimp_REDRAW_OK))
479 wimpt_noerr(wimp_setcolour(w->def->desc.w.colours[2]));
480 xx=((r->g.x0-ox)/48)*48-48;
481 yy=((r->g.y0-oy)/48)*48-48;
482 XX=((r->g.x1-ox)/48)*48+48;
483 YY=((r->g.y1-oy)/48)*48+48;
485 for (x=xx-xd;x<=XX;x+=48)
487 bbc_move(x+ox,yy+oy);
488 bbc_draw(x+ox+xd,YY+oy);
489 bbc_move(x+ox+xd,yy+oy);
490 bbc_draw(x+ox,YY+oy);
494 /* --- If in test mode, draw 3D bits, and skip icon rendering --- */
499 if (gPrefs_current()->sDispBorders)
500 sculptrix_redrawWindow(r);
501 if (gPrefs_current()->iDispBorders)
502 interface_render3dWindow(r);
503 if (gPrefs_current()->wDispBorders)
506 os_swix(XWimpExt_Redraw,®);
508 wimpt_noerr(wimp_get_rectangle(r,more));
513 /* --- Otherwise, translate coordinates for optimisation --- *
515 * We also bodge the rectangle a bit to include 3D borders. This is
516 * to avoid really very slow redrawing in big windows, where we have to
517 * pass each validation string to each of 3 modules to be parsed before
520 * If this goes seriously wrong, blame someone else. The worst that is
521 * likely to happen is that some *seriously* large borders don't get
522 * drawn all the time.
525 coords_box_toworkarea(&r->g,(coords_cvtstr *)&(r->box));
531 /* --- Plot 3D borders --- */
533 if (gPrefs_current()->iDispBorders ||
534 gPrefs_current()->wDispBorders ||
535 gPrefs_current()->sDispBorders)
537 for (i=0;i<w->def->desc.w.nicons;i++) /* Plot 3D borders first */
539 if (!(w->def->i[i].i.flags & wimp_IDELETED) &&
540 coords_boxesoverlap(&w->def->i[i].i.box,&r->g))
542 if (gPrefs_current()->sDispBorders)
543 sculptrix_plotIcon(&w->def->i[i].i,r);
544 if (gPrefs_current()->iDispBorders)
546 reg.r[1]=(int)&(w->def->i[i].i);
548 os_swix(XInterface_Plot3dIcon,®);
550 if (gPrefs_current()->wDispBorders)
552 reg.r[1]=(int)&(w->def->i[i].i);
555 os_swix(XWimpExt_PlotBorder,®);
561 /* --- Plot the actual icons on top of everything --- */
563 for (i=0;i<w->def->desc.w.nicons;i++) /* And then the icons */
565 if (!(w->def->i[i].i.flags & wimp_IDELETED) &&
566 coords_boxesoverlap(&w->def->i[i].i.box,&r->g))
567 wimp_ploticon(&(w->def->i[i].i));
570 /* --- Now temporary things (drawn in XOR mode) --- *
572 * The actual order of these is not important, seeing as the XOR nicely
573 * over each other, and XOR as we all know is commutative.
576 /* --- Bodge the graphics box to fit in the selection boxen --- */
578 r->g.x0-=window__HANDLEWIDTH+8;
579 r->g.y0-=window__HANDLEWIDTH+8;
580 r->g.x1+=window__HANDLEWIDTH+8;
581 r->g.y1+=window__HANDLEWIDTH+8;
583 /* --- Draw select boxes --- */
585 for (i=0;i<w->def->desc.w.nicons;i++) /* Select boxes... */
587 if (w->def->i[i].selected)
589 if (coords_boxesoverlap(&w->def->i[i].i.box,&r->g))
590 window__drawSelectBox(w,i,FALSE,r);
594 /* --- Any drag boxen --- */
596 if (window__qDragType()!=-1 && w==window__dragWind())
599 window__dragCoords(&x,&y);
600 window__redrawDragBox(w,r,x,y);
603 /* --- Get more rectangles from the WIMP --- */
605 wimpt_noerr(wimp_get_rectangle(r,more)); /* Get next bit to draw */
610 * void window_redrawIcon(glass_windPointer *w,int icon)
613 * Sets the WIMP up to call for a redraw of the spcified icon (i.e. it
614 * uses Wimp_ForceRedraw).
617 * glass_windPointer *w == pointer to the window owning the icon
618 * int icon == the icon to redraw
621 void window_redrawIcon(glass_windPointer *w,int icon)
627 window__bound(&w->def->i[icon].i,&r.box,TRUE);
628 r.box.x0-=window__HANDLEWIDTH+4;
629 r.box.x1+=window__HANDLEWIDTH+4;
630 r.box.y0-=window__HANDLEWIDTH+4;
631 r.box.y1+=window__HANDLEWIDTH+4;
632 wimpt_noerr(wimp_force_redraw(&r));
633 if (w==window_selectionOwner() && icon==window__selectedIcon())
634 tearEdit_update(w,icon);
635 window__updateMenu(w);
639 * void window__redrawGuide(glass_windPointer *w,int guide)
642 * Forces a redraw of the specified guideline.
645 * glass_windPointer *w == the window containing the guideline
646 * int guide == the number of the guideline.
649 void window__redrawGuide(glass_windPointer *w,int guide)
654 /* --- Force a redraw of the guideline --- *
656 * We can't realistically use Wimp_UpdateWindow because the guidelines are
657 * drawn over by everything else. So all we do is leave a bit of the
658 * window marked as invalid, and wait for the redraw event a bit later.
661 wimpt_noerr(wimp_get_wind_state(w->h,&s));
663 if (w->guide[guide].horiz)
666 r.box.y0=w->guide[guide].coord;
667 r.box.x1=s.o.x+s.o.box.x1-s.o.box.x0;
668 r.box.y1=w->guide[guide].coord+wimpt_dy();
673 r.box.x0=w->guide[guide].coord;
674 r.box.y0=s.o.y-s.o.box.y1+s.o.box.y0;
675 r.box.x1=w->guide[guide].coord+wimpt_dx();
677 wimpt_noerr(wimp_force_redraw(&r));