1/*
2 * Built-in icon building
3 *
4 * This conceptually overlaps pretty strongly with
5 * image_bitmap_builtin.c, since both are about drawing some built-in
6 * images used for internal stuff.  They're kept separate because i_b_b
7 * is backend bits for GetImage() calls for ":xpm:", "%xpm:", and ":"
8 * images, while these are called directly from the code.  Perhaps they
9 * should be subsumed under that, but they haven't been so far, so we're
10 * keeping them separate for now.
11 */
12
13#include "ctwm.h"
14
15#include <stdlib.h>
16
17#include "drawing.h"
18#include "screen.h"
19#include "iconmgr.h"
20
21#include "icons_builtin.h"
22
23
24struct Colori {
25	Pixel color;
26	Pixmap pix;
27	struct Colori *next;
28};
29
30
31/*
32 * The icons on menu items for submenus, in UseThreeDMenus and non
33 * variants.
34 */
35Pixmap
36Create3DMenuIcon(unsigned int height,
37                 unsigned int *widthp, unsigned int *heightp,
38                 ColorPair cp)
39{
40	unsigned int h, w;
41	int         i;
42	struct Colori *col;
43	static struct Colori *colori = NULL;
44
45	h = height;
46	w = h * 7 / 8;
47	if(h < 1) {
48		h = 1;
49	}
50	if(w < 1) {
51		w = 1;
52	}
53	*widthp  = w;
54	*heightp = h;
55
56	for(col = colori; col; col = col->next) {
57		if(col->color == cp.back) {
58			break;
59		}
60	}
61	if(col != NULL) {
62		return (col->pix);
63	}
64	col = malloc(sizeof(struct Colori));
65	col->color = cp.back;
66	col->pix   = XCreatePixmap(dpy, Scr->Root, h, h, Scr->d_depth);
67	col->next = colori;
68	colori = col;
69
70	Draw3DBorder(col->pix, 0, 0, w, h, 1, cp, off, true, false);
71	for(i = 3; i + 5 < h; i += 5) {
72		Draw3DBorder(col->pix, 4, i, w - 8, 3, 1, Scr->MenuC, off, true, false);
73	}
74	return (colori->pix);
75}
76
77Pixmap
78CreateMenuIcon(int height, unsigned int *widthp, unsigned int *heightp)
79{
80	int h, w;
81	int ih, iw;
82	int ix, iy;
83	int mh, mw;
84	int tw, th;
85	int lw, lh;
86	int lx, ly;
87	int lines, dly;
88	int offset;
89	int bw;
90
91	h = height;
92	w = h * 7 / 8;
93	if(h < 1) {
94		h = 1;
95	}
96	if(w < 1) {
97		w = 1;
98	}
99	*widthp = w;
100	*heightp = h;
101	if(Scr->tbpm.menu == None) {
102		Pixmap  pix;
103		GC      gc;
104
105		pix = Scr->tbpm.menu = XCreatePixmap(dpy, Scr->Root, w, h, 1);
106		gc = XCreateGC(dpy, pix, 0L, NULL);
107		XSetForeground(dpy, gc, 0L);
108		XFillRectangle(dpy, pix, gc, 0, 0, w, h);
109		XSetForeground(dpy, gc, 1L);
110		ix = 1;
111		iy = 1;
112		ih = h - iy * 2;
113		iw = w - ix * 2;
114		offset = ih / 8;
115		mh = ih - offset;
116		mw = iw - offset;
117		bw = mh / 16;
118		if(bw == 0 && mw > 2) {
119			bw = 1;
120		}
121		tw = mw - bw * 2;
122		th = mh - bw * 2;
123		XFillRectangle(dpy, pix, gc, ix, iy, mw, mh);
124		XFillRectangle(dpy, pix, gc, ix + iw - mw, iy + ih - mh, mw, mh);
125		XSetForeground(dpy, gc, 0L);
126		XFillRectangle(dpy, pix, gc, ix + bw, iy + bw, tw, th);
127		XSetForeground(dpy, gc, 1L);
128		lw = tw / 2;
129		if((tw & 1) ^ (lw & 1)) {
130			lw++;
131		}
132		lx = ix + bw + (tw - lw) / 2;
133
134		lh = th / 2 - bw;
135		if((lh & 1) ^ ((th - bw) & 1)) {
136			lh++;
137		}
138		ly = iy + bw + (th - bw - lh) / 2;
139
140		lines = 3;
141		if((lh & 1) && lh < 6) {
142			lines--;
143		}
144		dly = lh / (lines - 1);
145		while(lines--) {
146			XFillRectangle(dpy, pix, gc, lx, ly, lw, bw);
147			ly += dly;
148		}
149		XFreeGC(dpy, gc);
150	}
151	return Scr->tbpm.menu;
152}
153
154
155
156/*
157 * Icon used in the icon manager for iconified windows.
158 *
159 * For the 2d case, there's just one icon stored screen-wide, which is
160 * XCopyPlane()'d into the icon manager.  This works because it's just a
161 * 2-color thing represented as a bitmap, and we color it to match the
162 * FG/BG of the row at the time.
163 *
164 * The 3d variant is more complicated, and doesn't just use the row's
165 * FG/BG colors; it draws various shades from them.  So since each row in
166 * an icon manager may be a different FG/BG color, we have to make a new
167 * one for each row.
168 */
169
170const unsigned int im_iconified_icon_width = 11;
171const unsigned int im_iconified_icon_height = 11;
172static unsigned char im_iconified_icon_bits[] = {
173	0xff, 0x07, 0x01, 0x04, 0x0d, 0x05, 0x9d, 0x05, 0xb9, 0x04, 0x51, 0x04,
174	0xe9, 0x04, 0xcd, 0x05, 0x85, 0x05, 0x01, 0x04, 0xff, 0x07
175};
176
177Pixmap
178Create3DIconManagerIcon(ColorPair cp)
179{
180	struct Colori *col;
181	static struct Colori *colori = NULL;
182	const unsigned int w = im_iconified_icon_width;
183	const unsigned int h = im_iconified_icon_height;
184
185	/*
186	 * Keep a list of ones we've made, and if we've already made one this
187	 * color, just hand it back.
188	 */
189	for(col = colori; col; col = col->next) {
190		if(col->color == cp.back) {
191			return col->pix;
192		}
193	}
194
195	/* Don't have one this color yet, make it */
196	col = malloc(sizeof(struct Colori));
197	col->color = cp.back;
198	col->pix   = XCreatePixmap(dpy, Scr->Root, w, h, Scr->d_depth);
199	Draw3DBorder(col->pix, 0, 0, w, h, 4, cp, off, true, false);
200
201	/* Add to the cache list so we hit the above next time */
202	col->next = colori;
203	colori = col;
204
205	return colori->pix;
206}
207
208Pixmap
209Create2DIconManagerIcon(void)
210{
211	char *bits = (char *)im_iconified_icon_bits;
212	const unsigned int w = im_iconified_icon_width;
213	const unsigned int h = im_iconified_icon_height;
214
215	return XCreatePixmapFromBitmapData(dpy, Scr->Root, bits, w, h, 1, 0, 1);
216}
217