drawing.c revision 0bbfda8a
10bbfda8aSnia/*
20bbfda8aSnia * Various drawing routines.
30bbfda8aSnia *
40bbfda8aSnia * These are generalized routines that are used in multiple places in the
50bbfda8aSnia * codebase.  A number of other functions that are "drawing" related are
60bbfda8aSnia * left in various places through the codebase; some are only used in one
70bbfda8aSnia * file, and are left there for internal linkage, while others are
80bbfda8aSnia * part of a more abstract subdivision (e.g., the window decoration bits
90bbfda8aSnia * in win_decorations.c) and so belong there.
100bbfda8aSnia */
110bbfda8aSnia
120bbfda8aSnia#include "ctwm.h"
130bbfda8aSnia
140bbfda8aSnia
150bbfda8aSnia#include "screen.h"
160bbfda8aSnia#include "gram.tab.h"
170bbfda8aSnia#include "occupation.h"
180bbfda8aSnia#include "vscreen.h"
190bbfda8aSnia
200bbfda8aSnia#include "drawing.h"
210bbfda8aSnia
220bbfda8aSnia
230bbfda8aSnia
240bbfda8aSnia/*
250bbfda8aSnia * "3D border" drawings are used all over the place, not just in the
260bbfda8aSnia * obvious usage as window borders.
270bbfda8aSnia */
280bbfda8aSnia#define FBGC(gc, fix_fore, fix_back)\
290bbfda8aSnia    Gcv.foreground = fix_fore;\
300bbfda8aSnia    Gcv.background = fix_back;\
310bbfda8aSnia    XChangeGC(dpy, gc, GCForeground|GCBackground,&Gcv)
320bbfda8aSnia
330bbfda8aSniavoid
340bbfda8aSniaDraw3DBorder(Window w, int x, int y, int width, int height, int bw,
350bbfda8aSnia             ColorPair cp, ButtonState state, bool fill, bool forcebw)
360bbfda8aSnia{
370bbfda8aSnia	int           i;
380bbfda8aSnia	XGCValues     gcv;
390bbfda8aSnia	unsigned long gcm;
400bbfda8aSnia
410bbfda8aSnia	if((width < 1) || (height < 1)) {
420bbfda8aSnia		return;
430bbfda8aSnia	}
440bbfda8aSnia	if(Scr->Monochrome != COLOR) {
450bbfda8aSnia		if(fill) {
460bbfda8aSnia			gcm = GCFillStyle;
470bbfda8aSnia			gcv.fill_style = FillOpaqueStippled;
480bbfda8aSnia			XChangeGC(dpy, Scr->BorderGC, gcm, &gcv);
490bbfda8aSnia			XFillRectangle(dpy, w, Scr->BorderGC, x, y, width, height);
500bbfda8aSnia		}
510bbfda8aSnia		gcm  = 0;
520bbfda8aSnia		gcm |= GCLineStyle;
530bbfda8aSnia		gcv.line_style = (state == on) ? LineSolid : LineDoubleDash;
540bbfda8aSnia		gcm |= GCFillStyle;
550bbfda8aSnia		gcv.fill_style = FillSolid;
560bbfda8aSnia		XChangeGC(dpy, Scr->BorderGC, gcm, &gcv);
570bbfda8aSnia		for(i = 0; i < bw; i++) {
580bbfda8aSnia			XDrawLine(dpy, w, Scr->BorderGC, x,                 y + i,
590bbfda8aSnia			          x + width - i - 1, y + i);
600bbfda8aSnia			XDrawLine(dpy, w, Scr->BorderGC, x + i,                  y,
610bbfda8aSnia			          x + i, y + height - i - 1);
620bbfda8aSnia		}
630bbfda8aSnia
640bbfda8aSnia		gcm  = 0;
650bbfda8aSnia		gcm |= GCLineStyle;
660bbfda8aSnia		gcv.line_style = (state == on) ? LineDoubleDash : LineSolid;
670bbfda8aSnia		gcm |= GCFillStyle;
680bbfda8aSnia		gcv.fill_style = FillSolid;
690bbfda8aSnia		XChangeGC(dpy, Scr->BorderGC, gcm, &gcv);
700bbfda8aSnia		for(i = 0; i < bw; i++) {
710bbfda8aSnia			XDrawLine(dpy, w, Scr->BorderGC, x + width - i - 1,          y + i,
720bbfda8aSnia			          x + width - i - 1, y + height - 1);
730bbfda8aSnia			XDrawLine(dpy, w, Scr->BorderGC, x + i,         y + height - i - 1,
740bbfda8aSnia			          x + width - 1, y + height - i - 1);
750bbfda8aSnia		}
760bbfda8aSnia		return;
770bbfda8aSnia	}
780bbfda8aSnia
790bbfda8aSnia	if(fill) {
800bbfda8aSnia		FBGC(Scr->BorderGC, cp.back, cp.fore);
810bbfda8aSnia		XFillRectangle(dpy, w, Scr->BorderGC, x, y, width, height);
820bbfda8aSnia	}
830bbfda8aSnia	if(Scr->BeNiceToColormap) {
840bbfda8aSnia		int dashoffset = 0;
850bbfda8aSnia
860bbfda8aSnia		gcm  = 0;
870bbfda8aSnia		gcm |= GCLineStyle;
880bbfda8aSnia		gcv.line_style = (forcebw) ? LineSolid : LineDoubleDash;
890bbfda8aSnia		gcm |= GCBackground;
900bbfda8aSnia		gcv.background = cp.back;
910bbfda8aSnia		XChangeGC(dpy, Scr->BorderGC, gcm, &gcv);
920bbfda8aSnia
930bbfda8aSnia		if(state == on) {
940bbfda8aSnia			XSetForeground(dpy, Scr->BorderGC, Scr->Black);
950bbfda8aSnia		}
960bbfda8aSnia		else {
970bbfda8aSnia			XSetForeground(dpy, Scr->BorderGC, Scr->White);
980bbfda8aSnia		}
990bbfda8aSnia		for(i = 0; i < bw; i++) {
1000bbfda8aSnia			XDrawLine(dpy, w, Scr->BorderGC, x + i,     y + dashoffset,
1010bbfda8aSnia			          x + i, y + height - i - 1);
1020bbfda8aSnia			XDrawLine(dpy, w, Scr->BorderGC, x + dashoffset,    y + i,
1030bbfda8aSnia			          x + width - i - 1, y + i);
1040bbfda8aSnia			dashoffset = 1 - dashoffset;
1050bbfda8aSnia		}
1060bbfda8aSnia		XSetForeground(dpy, Scr->BorderGC, ((state == on) ? Scr->White : Scr->Black));
1070bbfda8aSnia		for(i = 0; i < bw; i++) {
1080bbfda8aSnia			XDrawLine(dpy, w, Scr->BorderGC, x + i,         y + height - i - 1,
1090bbfda8aSnia			          x + width - 1, y + height - i - 1);
1100bbfda8aSnia			XDrawLine(dpy, w, Scr->BorderGC, x + width - i - 1,          y + i,
1110bbfda8aSnia			          x + width - i - 1, y + height - 1);
1120bbfda8aSnia		}
1130bbfda8aSnia		return;
1140bbfda8aSnia	}
1150bbfda8aSnia	if(state == on) {
1160bbfda8aSnia		FBGC(Scr->BorderGC, cp.shadd, cp.shadc);
1170bbfda8aSnia	}
1180bbfda8aSnia	else             {
1190bbfda8aSnia		FBGC(Scr->BorderGC, cp.shadc, cp.shadd);
1200bbfda8aSnia	}
1210bbfda8aSnia	for(i = 0; i < bw; i++) {
1220bbfda8aSnia		XDrawLine(dpy, w, Scr->BorderGC, x,                 y + i,
1230bbfda8aSnia		          x + width - i - 1, y + i);
1240bbfda8aSnia		XDrawLine(dpy, w, Scr->BorderGC, x + i,                  y,
1250bbfda8aSnia		          x + i, y + height - i - 1);
1260bbfda8aSnia	}
1270bbfda8aSnia
1280bbfda8aSnia	if(state == on) {
1290bbfda8aSnia		FBGC(Scr->BorderGC, cp.shadc, cp.shadd);
1300bbfda8aSnia	}
1310bbfda8aSnia	else             {
1320bbfda8aSnia		FBGC(Scr->BorderGC, cp.shadd, cp.shadc);
1330bbfda8aSnia	}
1340bbfda8aSnia	for(i = 0; i < bw; i++) {
1350bbfda8aSnia		XDrawLine(dpy, w, Scr->BorderGC, x + width - i - 1,          y + i,
1360bbfda8aSnia		          x + width - i - 1, y + height - 1);
1370bbfda8aSnia		XDrawLine(dpy, w, Scr->BorderGC, x + i,         y + height - i - 1,
1380bbfda8aSnia		          x + width - 1, y + height - i - 1);
1390bbfda8aSnia	}
1400bbfda8aSnia	return;
1410bbfda8aSnia}
1420bbfda8aSnia
1430bbfda8aSnia#undef FBGC
1440bbfda8aSnia
1450bbfda8aSnia
1460bbfda8aSnia
1470bbfda8aSnia/*
1480bbfda8aSnia * Paint a button representing a workspace.  This is used in the
1490bbfda8aSnia * workspace manager window when it button mode, as well as in the
1500bbfda8aSnia * f.occupy window.
1510bbfda8aSnia */
1520bbfda8aSniavoid
1530bbfda8aSniaPaintWsButton(PWBType which, VirtualScreen *vs, Window w,
1540bbfda8aSnia              char *label, ColorPair cp, ButtonState state)
1550bbfda8aSnia{
1560bbfda8aSnia	int    bwidth, bheight;
1570bbfda8aSnia	MyFont font;
1580bbfda8aSnia	int    hspace, vspace;
1590bbfda8aSnia
1600bbfda8aSnia	if(which == WSPCWINDOW) {
1610bbfda8aSnia		bwidth  = vs->wsw->bwidth;
1620bbfda8aSnia		bheight = vs->wsw->bheight;
1630bbfda8aSnia		font    = Scr->workSpaceMgr.buttonFont;
1640bbfda8aSnia	}
1650bbfda8aSnia	else if(which == OCCUPYWINDOW) {
1660bbfda8aSnia		OccupyWindow *occwin = Scr->workSpaceMgr.occupyWindow;
1670bbfda8aSnia		bwidth  = occwin->bwidth;
1680bbfda8aSnia		bheight = occwin->bheight;
1690bbfda8aSnia		font    = occwin->font;
1700bbfda8aSnia	}
1710bbfda8aSnia	else if(which == OCCUPYBUTTON) {
1720bbfda8aSnia		OccupyWindow *occwin = Scr->workSpaceMgr.occupyWindow;
1730bbfda8aSnia		bwidth  = occwin->owidth;
1740bbfda8aSnia		bheight = occwin->bheight;
1750bbfda8aSnia		font    = occwin->font;
1760bbfda8aSnia	}
1770bbfda8aSnia	else {
1780bbfda8aSnia		return;
1790bbfda8aSnia	}
1800bbfda8aSnia
1810bbfda8aSnia	{
1820bbfda8aSnia		int        strWid, strHei;
1830bbfda8aSnia		XRectangle inc_rect;
1840bbfda8aSnia		XRectangle logical_rect;
1850bbfda8aSnia
1860bbfda8aSnia		XmbTextExtents(font.font_set, label, strlen(label), &inc_rect,
1870bbfda8aSnia		               &logical_rect);
1880bbfda8aSnia		strHei = logical_rect.height;
1890bbfda8aSnia		vspace = ((bheight + strHei - font.descent) / 2);
1900bbfda8aSnia		strWid = logical_rect.width;
1910bbfda8aSnia		hspace = (bwidth - strWid) / 2;
1920bbfda8aSnia	}
1930bbfda8aSnia
1940bbfda8aSnia	if(hspace < (Scr->WMgrButtonShadowDepth + 1)) {
1950bbfda8aSnia		hspace = Scr->WMgrButtonShadowDepth + 1;
1960bbfda8aSnia	}
1970bbfda8aSnia	XClearWindow(dpy, w);
1980bbfda8aSnia
1990bbfda8aSnia	if(Scr->Monochrome == COLOR) {
2000bbfda8aSnia		Draw3DBorder(w, 0, 0, bwidth, bheight, Scr->WMgrButtonShadowDepth,
2010bbfda8aSnia		             cp, state, true, false);
2020bbfda8aSnia
2030bbfda8aSnia		switch(Scr->workSpaceMgr.buttonStyle) {
2040bbfda8aSnia			case STYLE_NORMAL:
2050bbfda8aSnia				break;
2060bbfda8aSnia
2070bbfda8aSnia			case STYLE_STYLE1:
2080bbfda8aSnia				Draw3DBorder(w,
2090bbfda8aSnia				             Scr->WMgrButtonShadowDepth - 1,
2100bbfda8aSnia				             Scr->WMgrButtonShadowDepth - 1,
2110bbfda8aSnia				             bwidth  - 2 * Scr->WMgrButtonShadowDepth + 2,
2120bbfda8aSnia				             bheight - 2 * Scr->WMgrButtonShadowDepth + 2,
2130bbfda8aSnia				             1, cp, (state == on) ? off : on, true, false);
2140bbfda8aSnia				break;
2150bbfda8aSnia
2160bbfda8aSnia			case STYLE_STYLE2:
2170bbfda8aSnia				Draw3DBorder(w,
2180bbfda8aSnia				             Scr->WMgrButtonShadowDepth / 2,
2190bbfda8aSnia				             Scr->WMgrButtonShadowDepth / 2,
2200bbfda8aSnia				             bwidth  - Scr->WMgrButtonShadowDepth,
2210bbfda8aSnia				             bheight - Scr->WMgrButtonShadowDepth,
2220bbfda8aSnia				             1, cp, (state == on) ? off : on, true, false);
2230bbfda8aSnia				break;
2240bbfda8aSnia
2250bbfda8aSnia			case STYLE_STYLE3:
2260bbfda8aSnia				Draw3DBorder(w,
2270bbfda8aSnia				             1,
2280bbfda8aSnia				             1,
2290bbfda8aSnia				             bwidth  - 2,
2300bbfda8aSnia				             bheight - 2,
2310bbfda8aSnia				             1, cp, (state == on) ? off : on, true, false);
2320bbfda8aSnia				break;
2330bbfda8aSnia		}
2340bbfda8aSnia		FB(cp.fore, cp.back);
2350bbfda8aSnia		XmbDrawString(dpy, w, font.font_set, Scr->NormalGC, hspace, vspace,
2360bbfda8aSnia		              label, strlen(label));
2370bbfda8aSnia	}
2380bbfda8aSnia	else {
2390bbfda8aSnia		Draw3DBorder(w, 0, 0, bwidth, bheight, Scr->WMgrButtonShadowDepth,
2400bbfda8aSnia		             cp, state, true, false);
2410bbfda8aSnia		if(state == on) {
2420bbfda8aSnia			FB(cp.fore, cp.back);
2430bbfda8aSnia			XmbDrawImageString(dpy, w, font.font_set, Scr->NormalGC, hspace, vspace,
2440bbfda8aSnia			                   label, strlen(label));
2450bbfda8aSnia		}
2460bbfda8aSnia		else {
2470bbfda8aSnia			FB(cp.back, cp.fore);
2480bbfda8aSnia			XmbDrawImageString(dpy, w, font.font_set, Scr->NormalGC, hspace, vspace,
2490bbfda8aSnia			                   label, strlen(label));
2500bbfda8aSnia		}
2510bbfda8aSnia	}
2520bbfda8aSnia}
253