Home | History | Annotate | Line # | Download | only in dist
      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 
     33 void
     34 Draw3DBorder(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  */
    152 void
    153 PaintWsButton(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