1/* 2 * Various drawing routines. 3 * 4 * These are generalized routines that are used in multiple places in the 5 * codebase. A number of other functions that are "drawing" related are 6 * left in various places through the codebase; some are only used in one 7 * file, and are left there for internal linkage, while others are 8 * part of a more abstract subdivision (e.g., the window decoration bits 9 * in win_decorations.c) and so belong there. 10 */ 11 12#include "ctwm.h" 13 14 15#include "screen.h" 16#include "gram.tab.h" 17#include "occupation.h" 18#include "vscreen.h" 19 20#include "drawing.h" 21 22 23 24/* 25 * "3D border" drawings are used all over the place, not just in the 26 * obvious usage as window borders. 27 */ 28#define FBGC(gc, fix_fore, fix_back)\ 29 Gcv.foreground = fix_fore;\ 30 Gcv.background = fix_back;\ 31 XChangeGC(dpy, gc, GCForeground|GCBackground,&Gcv) 32 33void 34Draw3DBorder(Window w, int x, int y, int width, int height, int bw, 35 ColorPair cp, ButtonState state, bool fill, bool forcebw) 36{ 37 int i; 38 XGCValues gcv; 39 unsigned long gcm; 40 41 if((width < 1) || (height < 1)) { 42 return; 43 } 44 if(Scr->Monochrome != COLOR) { 45 if(fill) { 46 gcm = GCFillStyle; 47 gcv.fill_style = FillOpaqueStippled; 48 XChangeGC(dpy, Scr->BorderGC, gcm, &gcv); 49 XFillRectangle(dpy, w, Scr->BorderGC, x, y, width, height); 50 } 51 gcm = 0; 52 gcm |= GCLineStyle; 53 gcv.line_style = (state == on) ? LineSolid : LineDoubleDash; 54 gcm |= GCFillStyle; 55 gcv.fill_style = FillSolid; 56 XChangeGC(dpy, Scr->BorderGC, gcm, &gcv); 57 for(i = 0; i < bw; i++) { 58 XDrawLine(dpy, w, Scr->BorderGC, x, y + i, 59 x + width - i - 1, y + i); 60 XDrawLine(dpy, w, Scr->BorderGC, x + i, y, 61 x + i, y + height - i - 1); 62 } 63 64 gcm = 0; 65 gcm |= GCLineStyle; 66 gcv.line_style = (state == on) ? LineDoubleDash : LineSolid; 67 gcm |= GCFillStyle; 68 gcv.fill_style = FillSolid; 69 XChangeGC(dpy, Scr->BorderGC, gcm, &gcv); 70 for(i = 0; i < bw; i++) { 71 XDrawLine(dpy, w, Scr->BorderGC, x + width - i - 1, y + i, 72 x + width - i - 1, y + height - 1); 73 XDrawLine(dpy, w, Scr->BorderGC, x + i, y + height - i - 1, 74 x + width - 1, y + height - i - 1); 75 } 76 return; 77 } 78 79 if(fill) { 80 FBGC(Scr->BorderGC, cp.back, cp.fore); 81 XFillRectangle(dpy, w, Scr->BorderGC, x, y, width, height); 82 } 83 if(Scr->BeNiceToColormap) { 84 int dashoffset = 0; 85 86 gcm = 0; 87 gcm |= GCLineStyle; 88 gcv.line_style = (forcebw) ? LineSolid : LineDoubleDash; 89 gcm |= GCBackground; 90 gcv.background = cp.back; 91 XChangeGC(dpy, Scr->BorderGC, gcm, &gcv); 92 93 if(state == on) { 94 XSetForeground(dpy, Scr->BorderGC, Scr->Black); 95 } 96 else { 97 XSetForeground(dpy, Scr->BorderGC, Scr->White); 98 } 99 for(i = 0; i < bw; i++) { 100 XDrawLine(dpy, w, Scr->BorderGC, x + i, y + dashoffset, 101 x + i, y + height - i - 1); 102 XDrawLine(dpy, w, Scr->BorderGC, x + dashoffset, y + i, 103 x + width - i - 1, y + i); 104 dashoffset = 1 - dashoffset; 105 } 106 XSetForeground(dpy, Scr->BorderGC, ((state == on) ? Scr->White : Scr->Black)); 107 for(i = 0; i < bw; i++) { 108 XDrawLine(dpy, w, Scr->BorderGC, x + i, y + height - i - 1, 109 x + width - 1, y + height - i - 1); 110 XDrawLine(dpy, w, Scr->BorderGC, x + width - i - 1, y + i, 111 x + width - i - 1, y + height - 1); 112 } 113 return; 114 } 115 if(state == on) { 116 FBGC(Scr->BorderGC, cp.shadd, cp.shadc); 117 } 118 else { 119 FBGC(Scr->BorderGC, cp.shadc, cp.shadd); 120 } 121 for(i = 0; i < bw; i++) { 122 XDrawLine(dpy, w, Scr->BorderGC, x, y + i, 123 x + width - i - 1, y + i); 124 XDrawLine(dpy, w, Scr->BorderGC, x + i, y, 125 x + i, y + height - i - 1); 126 } 127 128 if(state == on) { 129 FBGC(Scr->BorderGC, cp.shadc, cp.shadd); 130 } 131 else { 132 FBGC(Scr->BorderGC, cp.shadd, cp.shadc); 133 } 134 for(i = 0; i < bw; i++) { 135 XDrawLine(dpy, w, Scr->BorderGC, x + width - i - 1, y + i, 136 x + width - i - 1, y + height - 1); 137 XDrawLine(dpy, w, Scr->BorderGC, x + i, y + height - i - 1, 138 x + width - 1, y + height - i - 1); 139 } 140 return; 141} 142 143#undef FBGC 144 145 146 147/* 148 * Paint a button representing a workspace. This is used in the 149 * workspace manager window when it button mode, as well as in the 150 * f.occupy window. 151 */ 152void 153PaintWsButton(PWBType which, VirtualScreen *vs, Window w, 154 char *label, ColorPair cp, ButtonState state) 155{ 156 int bwidth, bheight; 157 MyFont font; 158 int hspace, vspace; 159 160 if(which == WSPCWINDOW) { 161 bwidth = vs->wsw->bwidth; 162 bheight = vs->wsw->bheight; 163 font = Scr->workSpaceMgr.buttonFont; 164 } 165 else if(which == OCCUPYWINDOW) { 166 OccupyWindow *occwin = Scr->workSpaceMgr.occupyWindow; 167 bwidth = occwin->bwidth; 168 bheight = occwin->bheight; 169 font = occwin->font; 170 } 171 else if(which == OCCUPYBUTTON) { 172 OccupyWindow *occwin = Scr->workSpaceMgr.occupyWindow; 173 bwidth = occwin->owidth; 174 bheight = occwin->bheight; 175 font = occwin->font; 176 } 177 else { 178 return; 179 } 180 181 { 182 int strWid, strHei; 183 XRectangle inc_rect; 184 XRectangle logical_rect; 185 186 XmbTextExtents(font.font_set, label, strlen(label), &inc_rect, 187 &logical_rect); 188 strHei = logical_rect.height; 189 vspace = ((bheight + strHei - font.descent) / 2); 190 strWid = logical_rect.width; 191 hspace = (bwidth - strWid) / 2; 192 } 193 194 if(hspace < (Scr->WMgrButtonShadowDepth + 1)) { 195 hspace = Scr->WMgrButtonShadowDepth + 1; 196 } 197 XClearWindow(dpy, w); 198 199 if(Scr->Monochrome == COLOR) { 200 Draw3DBorder(w, 0, 0, bwidth, bheight, Scr->WMgrButtonShadowDepth, 201 cp, state, true, false); 202 203 switch(Scr->workSpaceMgr.buttonStyle) { 204 case STYLE_NORMAL: 205 break; 206 207 case STYLE_STYLE1: 208 Draw3DBorder(w, 209 Scr->WMgrButtonShadowDepth - 1, 210 Scr->WMgrButtonShadowDepth - 1, 211 bwidth - 2 * Scr->WMgrButtonShadowDepth + 2, 212 bheight - 2 * Scr->WMgrButtonShadowDepth + 2, 213 1, cp, (state == on) ? off : on, true, false); 214 break; 215 216 case STYLE_STYLE2: 217 Draw3DBorder(w, 218 Scr->WMgrButtonShadowDepth / 2, 219 Scr->WMgrButtonShadowDepth / 2, 220 bwidth - Scr->WMgrButtonShadowDepth, 221 bheight - Scr->WMgrButtonShadowDepth, 222 1, cp, (state == on) ? off : on, true, false); 223 break; 224 225 case STYLE_STYLE3: 226 Draw3DBorder(w, 227 1, 228 1, 229 bwidth - 2, 230 bheight - 2, 231 1, cp, (state == on) ? off : on, true, false); 232 break; 233 } 234 FB(cp.fore, cp.back); 235 XmbDrawString(dpy, w, font.font_set, Scr->NormalGC, hspace, vspace, 236 label, strlen(label)); 237 } 238 else { 239 Draw3DBorder(w, 0, 0, bwidth, bheight, Scr->WMgrButtonShadowDepth, 240 cp, state, true, false); 241 if(state == on) { 242 FB(cp.fore, cp.back); 243 XmbDrawImageString(dpy, w, font.font_set, Scr->NormalGC, hspace, vspace, 244 label, strlen(label)); 245 } 246 else { 247 FB(cp.back, cp.fore); 248 XmbDrawImageString(dpy, w, font.font_set, Scr->NormalGC, hspace, vspace, 249 label, strlen(label)); 250 } 251 } 252} 253