/* * wRedraw.c * * Redrawing template windows * * © 1994-1998 Straylight */ /*----- Licensing note ----------------------------------------------------* * * This file is part of Straylight's Glass. * * Glass is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * Glass is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Glass. If not, write to the Free Software Foundation, * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*----- Header files ------------------------------------------------------*/ /* * ANSI standard headers */ #include #include #include /* * Steel headers */ #define _STDAPP #define _LOWLVL #include "steel/Steel.h" #include "steel/interface.h" #include "steel/sculptrix.h" #include "steel/bbc.h" #include "steel/coords.h" /* * Glass headers */ #include "gStruct.h" #include "gMenus.h" #include "gIcons.h" #include "glass.h" #include "gPrefs.h" #include "window.h" #include "_window.h" #include "tearEdit.h" /*----- Main code ---------------------------------------------------------*/ /* * void window__drawSelectBox(glass_windPointer *w, * int icon, * BOOL makesi, * wimp_redrawstr *r) * * Use * Draws the selection box around an icon * * Parameters * glass_windPointer *w == the window * int icon == the icon * BOOL makesi == whether we're going between a selected and main selected * icon. * wimp_redrawstr *r == the redraw structure */ #define HW window__HANDLEWIDTH void window__drawSelectBox(glass_windPointer *w, int icon, BOOL makesi, wimp_redrawstr *r) { wimp_box box; int ox=r->box.x0-r->scx; int oy=r->box.y1-r->scy; window_boundingBox(w,icon,&box); /* --- If we're in test mode, do nothing --- */ #ifndef glass_DEMO if (w->testMode) /* Blank */; else #endif /* --- If we're not renumbering, draw in all the fancy bits --- */ if (!w->renumber) { /* --- Make sure the user wants a border, and draw the right one --- */ if (gPrefs_current()->sBorder && !makesi) { window__setXORColour(w,window__SELBOXCOL); if (gPrefs_current()->sDotted) { window__makeDashPattern(0xf0); window__rectangle(ox+box.x0-wimpt_dx(), oy+box.y0-wimpt_dy(), box.x1-box.x0+wimpt_dx(), box.y1-box.y0+wimpt_dy()); } else { bbc_rectangle(ox+box.x0-wimpt_dx(), oy+box.y0-wimpt_dy(), box.x1-box.x0+wimpt_dx(), box.y1-box.y0+wimpt_dy()); } } /* --- Draw in all the drag handles --- */ if (makesi) window__colourChange(window__MSELBOXCOL,window__HANDCOL); else if (icon==window__selectedIcon()) window__setXORColour(w,window__MSELBOXCOL); else window__setXORColour(w,window__HANDCOL); /* If edges are wanted, fill them in */ if (gPrefs_current()->sEdgeHandles) { bbc_rectanglefill(ox+box.x0-wimpt_dx()-HW, oy+box.y0+(box.y1-box.y0-HW*2)/2, HW*2, HW*2); bbc_rectanglefill(ox+box.x1-HW, oy+box.y0+(box.y1-box.y0-HW*2)/2, HW*2, HW*2); bbc_rectanglefill(ox+box.x0+(box.x1-box.x0-HW*2)/2, oy+box.y0-wimpt_dy()-HW, HW*2, HW*2); bbc_rectanglefill(ox+box.x0+(box.x1-box.x0-HW*2)/2, oy+box.y1-HW, HW*2, HW*2); } /* Corners are always drawn */ bbc_rectanglefill(ox+box.x0-wimpt_dx()-HW, oy+box.y0-wimpt_dy()-HW, HW*2, HW*2); bbc_rectanglefill(ox+box.x1-HW, oy+box.y0-wimpt_dy()-HW, HW*2, HW*2); bbc_rectanglefill(ox+box.x0-wimpt_dx()-HW, oy+box.y1-HW, HW*2, HW*2); bbc_rectanglefill(ox+box.x1-HW, oy+box.y1-HW, HW*2, HW*2); } else /* --- Otherwise, we do the funny renumbering corner bits --- */ { window__setXORColour(w,window__HANDCOL); bbc_move(ox+box.x0-8,oy+box.y1-wimpt_dy()-12); bbc_drawby(0,20); bbc_drawby(20,0); bbc_move(ox+box.x1-wimpt_dx()+8,oy+box.y1-wimpt_dy()-12); bbc_drawby(0,20); bbc_drawby(-20,0); bbc_move(ox+box.x0-8,oy+box.y0+12); bbc_drawby(0,-20); bbc_drawby(20,0); bbc_move(ox+box.x1-wimpt_dx()+8,oy+box.y0+12); bbc_drawby(0,-20); bbc_drawby(-20,0); } } #undef HW /* * void window__redrawDragBox(glass_windPointer *w, * wimp_redrawstr *r, * int x, * int y) * * Use * Redraws the screen during a drag operation, either to update the window * during the drag, or to redraw the window should something silly happen * to it. * * Parameters * glass_windPointer *w == pointer to the window owning drag * wimp_redrawstr *r == pointer to current redraw * int x,int y == coordinates to draw drag relative to... */ void window__redrawDragBox(glass_windPointer *w,wimp_redrawstr *r, int x,int y) { int ox=r->box.x0-r->scx; int oy=r->box.y1-r->scy; int i; wimp_box box; int bw; int bh; int type=window__qDragType(); int sx,sy; /* --- If we don't know which window to draw in, don't --- */ if (!window__dragWind()) return; /* --- Work out what we have to draw --- */ window__dragStart(&sx,&sy); switch (type) { /* --- A selection box -- draw a rubber rectangle --- */ case window__SELECT: /* Drag out a box to select icons */ window__rectangle(sx+ox,sy+oy,x-sx,y-sy); break; /* --- We're grabbing an icon, so this is like a move --- * * * We can't actually use the main move code, because it works on all * selected icons, and the one we're drawing doesn't actually exist as * such. */ case window__GRABICON: box=window__qDragBox(); box.y1+=y-sy; box.y0+=y-sy; box.x0+=x-sx; box.x1+=x-sx; window__rectangle(ox+box.x0, oy+box.y0, box.x1-box.x0-wimpt_dx(), box.y1-box.y0-wimpt_dy()); break; /* --- Guidelines moving -- draw all the guides which are moving --- */ case window__HORGUIDE: for (i=0;iguide[i].active && w->guide[i].selected && w->guide[i].horiz) { bbc_plot(bbc_DottedBoth+bbc_MoveCursorAbs, ox+w->def->desc.w.ex.x0, oy+w->guide[i].coord+y-sy); bbc_plot(bbc_DottedBoth+bbc_DrawAbsFore, ox+w->def->desc.w.ex.x1, oy+w->guide[i].coord+y-sy); } } break; case window__VERGUIDE: for (i=0;iguide[i].active && w->guide[i].selected && !w->guide[i].horiz) { bbc_plot(bbc_DottedBoth+bbc_MoveCursorAbs, ox+w->guide[i].coord+x-sx, oy+w->def->desc.w.ex.y0); bbc_plot(bbc_DottedBoth+bbc_DrawAbsFore, ox+w->guide[i].coord+x-sx, oy+w->def->desc.w.ex.y1); } } break; /* --- Normal icon moves/resizes --- * * * We find out where the box is according to the drag-type bitfield, * and draw that for each selected icon. */ default: for (i=0;idef->desc.w.nicons;i++) { if (w->def->i[i].selected) { window_boundingBox(w,i,&box); bw=(w->def->i[i].i.box.x0-box.x0) + (box.x1-w->def->i[i].i.box.x1); bh=(w->def->i[i].i.box.y0-box.y0) + (box.y1-w->def->i[i].i.box.y1); /* --- Adjust coordinates according to drag type --- */ if (type & window__TOP) box.y1+=y-sy; if (type & window__BOTTOM) box.y0+=y-sy; if (type & window__LEFT) box.x0+=x-sx; if (type & window__RIGHT) box.x1+=x-sx; /* --- Ensure that the box is not inside-out --- */ if (type & window__TOP) { if (box.y1-box.y0box.x0-r->scx; int oy=r->box.y1-r->scy; /* --- Make Sculptrix use the right sprite area --- */ sculptrix_setSpriteArea(w->t->s); /* --- Do the redraw for each rectangle the WIMP gives us --- */ while (*more) { /* --- Draw the grid --- */ if (w->gridShow #ifndef glass_DEMO && !w->testMode #endif ) { xx=((r->g.x0-ox)/w->gridx)*w->gridx-w->gridx; yy=((r->g.y0-oy)/w->gridy)*w->gridy-w->gridy; XX=((r->g.x1-ox)/w->gridx)*w->gridx+w->gridx; YY=((r->g.y1-oy)/w->gridy)*w->gridy+w->gridy; wimp_setcolour(gPrefs_current()->gGridCol); if (gPrefs_current()->gLines) { for (x=xx;x<=XX;x+=w->gridx) { bbc_move(x+ox,yy+oy); bbc_draw(x+ox,YY+oy); } for (y=yy;y<=YY;y+=w->gridy) { bbc_move(xx+ox,y+oy); bbc_draw(XX+ox,y+oy); } } else { for (x=xx;x<=XX;x+=w->gridx) { for (y=yy;y<=YY;y+=w->gridy) bbc_plot(bbc_Point+bbc_DrawAbsFore,x+ox,y+oy); } } } /* --- Draw guidelines --- */ #ifndef glass_DEMO if (!w->testMode) #endif { for (i=0;iguide[i].active) { if (w->guide[i].selected) { wimp_setcolour(window__GDESELCOL); window__makeDashPattern(0xff); } else { wimp_setcolour(window__GUIDECOL); window__makeDashPattern(0x33); } if (w->guide[i].horiz) { bbc_plot(bbc_DottedBoth+bbc_MoveCursorAbs, ox+w->def->desc.w.ex.x0, oy+w->guide[i].coord); bbc_plot(bbc_DottedBoth+bbc_DrawAbsFore, ox+w->def->desc.w.ex.x1, oy+w->guide[i].coord); } else { bbc_plot(bbc_DottedBoth+bbc_MoveCursorAbs, ox+w->guide[i].coord, oy+w->def->desc.w.ex.y0); bbc_plot(bbc_DottedBoth+bbc_DrawAbsFore, ox+w->guide[i].coord, oy+w->def->desc.w.ex.y1); } } } } /* --- Draw the hatch pattern, if applicable --- */ if (gPrefs_current()->mDrawHatch && !(w->def->desc.w.flags & wimp_REDRAW_OK)) { wimpt_noerr(wimp_setcolour(w->def->desc.w.colours[2])); xx=((r->g.x0-ox)/48)*48-48; yy=((r->g.y0-oy)/48)*48-48; XX=((r->g.x1-ox)/48)*48+48; YY=((r->g.y1-oy)/48)*48+48; xd=YY-yy; for (x=xx-xd;x<=XX;x+=48) { bbc_move(x+ox,yy+oy); bbc_draw(x+ox+xd,YY+oy); bbc_move(x+ox+xd,yy+oy); bbc_draw(x+ox,YY+oy); } } /* --- If in test mode, draw 3D bits, and skip icon rendering --- */ #ifndef glass_DEMO if (w->testMode) { if (gPrefs_current()->sDispBorders) sculptrix_redrawWindow(r); if (gPrefs_current()->iDispBorders) interface_render3dWindow(r); if (gPrefs_current()->wDispBorders) { reg.r[1]=(int)r; os_swix(XWimpExt_Redraw,®); } wimpt_noerr(wimp_get_rectangle(r,more)); continue; } #endif /* --- Otherwise, translate coordinates for optimisation --- * * * We also bodge the rectangle a bit to include 3D borders. This is * to avoid really very slow redrawing in big windows, where we have to * pass each validation string to each of 3 modules to be parsed before * rendering... * * If this goes seriously wrong, blame someone else. The worst that is * likely to happen is that some *seriously* large borders don't get * drawn all the time. */ coords_box_toworkarea(&r->g,(coords_cvtstr *)&(r->box)); r->g.x0-=16; r->g.y0-=32; r->g.x1+=16; r->g.y1+=16; /* --- Plot 3D borders --- */ if (gPrefs_current()->iDispBorders || gPrefs_current()->wDispBorders || gPrefs_current()->sDispBorders) { for (i=0;idef->desc.w.nicons;i++) /* Plot 3D borders first */ { if (!(w->def->i[i].i.flags & wimp_IDELETED) && coords_boxesoverlap(&w->def->i[i].i.box,&r->g)) { if (gPrefs_current()->sDispBorders) sculptrix_plotIcon(&w->def->i[i].i,r); if (gPrefs_current()->iDispBorders) { reg.r[1]=(int)&(w->def->i[i].i); reg.r[0]=(int)r; os_swix(XInterface_Plot3dIcon,®); } if (gPrefs_current()->wDispBorders) { reg.r[1]=(int)&(w->def->i[i].i); reg.r[0]=0; reg.r[2]=w->h; os_swix(XWimpExt_PlotBorder,®); } } } } /* --- Plot the actual icons on top of everything --- */ for (i=0;idef->desc.w.nicons;i++) /* And then the icons */ { if (!(w->def->i[i].i.flags & wimp_IDELETED) && coords_boxesoverlap(&w->def->i[i].i.box,&r->g)) wimp_ploticon(&(w->def->i[i].i)); } /* --- Now temporary things (drawn in XOR mode) --- * * * The actual order of these is not important, seeing as the XOR nicely * over each other, and XOR as we all know is commutative. */ /* --- Bodge the graphics box to fit in the selection boxen --- */ r->g.x0-=window__HANDLEWIDTH+8; r->g.y0-=window__HANDLEWIDTH+8; r->g.x1+=window__HANDLEWIDTH+8; r->g.y1+=window__HANDLEWIDTH+8; /* --- Draw select boxes --- */ for (i=0;idef->desc.w.nicons;i++) /* Select boxes... */ { if (w->def->i[i].selected) { if (coords_boxesoverlap(&w->def->i[i].i.box,&r->g)) window__drawSelectBox(w,i,FALSE,r); } } /* --- Any drag boxen --- */ if (window__qDragType()!=-1 && w==window__dragWind()) { window__rotate(0); window__dragCoords(&x,&y); window__redrawDragBox(w,r,x,y); } /* --- Get more rectangles from the WIMP --- */ wimpt_noerr(wimp_get_rectangle(r,more)); /* Get next bit to draw */ } } /* * void window_redrawIcon(glass_windPointer *w,int icon) * * Use * Sets the WIMP up to call for a redraw of the spcified icon (i.e. it * uses Wimp_ForceRedraw). * * Parameters * glass_windPointer *w == pointer to the window owning the icon * int icon == the icon to redraw */ void window_redrawIcon(glass_windPointer *w,int icon) { wimp_redrawstr r; if (!w->h) return; r.w=w->h; window__bound(&w->def->i[icon].i,&r.box,TRUE); r.box.x0-=window__HANDLEWIDTH+4; r.box.x1+=window__HANDLEWIDTH+4; r.box.y0-=window__HANDLEWIDTH+4; r.box.y1+=window__HANDLEWIDTH+4; wimpt_noerr(wimp_force_redraw(&r)); if (w==window_selectionOwner() && icon==window__selectedIcon()) tearEdit_update(w,icon); window__updateMenu(w); } /* * void window__redrawGuide(glass_windPointer *w,int guide) * * Use * Forces a redraw of the specified guideline. * * Parameters * glass_windPointer *w == the window containing the guideline * int guide == the number of the guideline. */ void window__redrawGuide(glass_windPointer *w,int guide) { wimp_wstate s; wimp_redrawstr r; /* --- Force a redraw of the guideline --- * * * We can't realistically use Wimp_UpdateWindow because the guidelines are * drawn over by everything else. So all we do is leave a bit of the * window marked as invalid, and wait for the redraw event a bit later. */ wimpt_noerr(wimp_get_wind_state(w->h,&s)); r.w=w->h; if (w->guide[guide].horiz) { r.box.x0=s.o.x; r.box.y0=w->guide[guide].coord; r.box.x1=s.o.x+s.o.box.x1-s.o.box.x0; r.box.y1=w->guide[guide].coord+wimpt_dy(); } else { r.box.y1=s.o.y; r.box.x0=w->guide[guide].coord; r.box.y0=s.o.y-s.o.box.y1+s.o.box.y0; r.box.x1=w->guide[guide].coord+wimpt_dx(); } wimpt_noerr(wimp_force_redraw(&r)); }