Make AddMouseRegion's index unsigned
[dockapps.git] / wmmp3 / wmgeneral.c
blob6ace5c904f7e97e0b0191c63db49f81a0d8495bc
1 /*
2 Best viewed with GNU Emacs 19
4 wmgeneral was taken from wmppp.
6 It has a lot of routines which most of the wm* programs use.
8 ------------------------------------------------------------
10 Author: Martijn Pieterse (pieterse@xs4all.nl)
12 ---
13 CHANGES:
14 ---
17 14/09/1998 (Dave Clark, clarkd@skyia.com)
18 * Updated createXBMfromXPM routine
19 * Now supports >256 colors
20 11/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
21 * Removed a bug from parse_rcfile. You could
22 not use "start" in a command if a label was
23 also start.
24 * Changed the needed geometry string.
25 We don't use window size, and don't support
26 negative positions.
27 03/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
28 * Added parse_rcfile2
29 02/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
30 * Added -geometry support (untested)
31 28/08/1998 (Martijn Pieterse, pieterse@xs4all.nl)
32 * Added createXBMfromXPM routine
33 * Saves a lot of work with changing xpm's.
34 02/05/1998 (Martijn Pieterse, pieterse@xs4all.nl)
35 * changed the read_rc_file to parse_rcfile, as suggested by Marcelo E. Magallon
36 * debugged the parse_rc file.
37 30/04/1998 (Martijn Pieterse, pieterse@xs4all.nl)
38 * Ripped similar code from all the wm* programs,
39 and put them in a single file.
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <string.h>
46 #include <unistd.h>
47 #include <ctype.h>
48 #include <stdarg.h>
50 #include <X11/Xlib.h>
51 #include <X11/xpm.h>
52 #include <X11/extensions/shape.h>
54 #include "wmgeneral.h"
55 #include "charset.xpm"
57 /*****************/
58 /* X11 Variables */
59 /*****************/
61 int screen;
62 int x_fd;
63 int d_depth;
64 XSizeHints mysizehints;
65 XWMHints mywmhints;
66 Pixel back_pix, fore_pix;
67 char *Geometry = "";
68 GC NormalGC;
69 Pixmap pixmask;
71 /*****************/
72 /* Mouse Regions */
73 /*****************/
75 typedef struct {
76 int enable;
77 int top;
78 int bottom;
79 int left;
80 int right;
81 } MOUSE_REGION;
83 MOUSE_REGION mouse_region[MAX_MOUSE_REGION];
85 /***********************/
86 /* Function Prototypes */
87 /***********************/
89 static void GetXPM(XpmIcon *, char **);
90 static Pixel GetColor(char *);
91 void RedrawWindow(void);
92 void AddMouseRegion(unsigned, int, int, int, int);
93 int CheckMouseRegion(int, int);
94 void PutPixel(int, int, int);
95 int GetPixel(int, int);
97 /*******************************************************************************\
98 |* parse_rcfile *|
99 \*******************************************************************************/
101 void parse_rcfile(const char *filename, rckeys * keys)
104 char *p, *q;
105 char temp[128];
106 char *tokens = " :\t\n";
107 FILE *fp;
108 int i, key;
110 fp = fopen(filename, "r");
111 if (fp) {
112 while (fgets(temp, 128, fp)) {
113 key = 0;
114 q = strdup(temp);
115 q = strtok(q, tokens);
116 while (key >= 0 && keys[key].label) {
117 if ((!strcmp(q, keys[key].label))) {
118 p = strstr(temp, keys[key].label);
119 p += strlen(keys[key].label);
120 p += strspn(p, tokens);
121 if ((i = strcspn(p, "#\n")))
122 p[i] = 0;
123 free(*keys[key].var);
124 *keys[key].var = strdup(p);
125 key = -1;
126 } else
127 key++;
129 free(q);
131 fclose(fp);
135 /*******************************************************************************\
136 |* parse_rcfile2 *|
137 \*******************************************************************************/
139 void parse_rcfile2(const char *filename, rckeys2 * keys)
142 char *p;
143 char temp[128];
144 char *tokens = " :\t\n";
145 FILE *fp;
146 int i, key;
147 char *family = NULL;
149 fp = fopen(filename, "r");
150 if (fp) {
151 while (fgets(temp, 128, fp)) {
152 key = 0;
153 while (key >= 0 && keys[key].label) {
154 if ((p = strstr(temp, keys[key].label))) {
155 p += strlen(keys[key].label);
156 p += strspn(p, tokens);
157 if ((i = strcspn(p, "#\n")))
158 p[i] = 0;
159 free(*keys[key].var);
160 *keys[key].var = strdup(p);
161 key = -1;
162 } else
163 key++;
166 fclose(fp);
168 free(family);
172 /*******************************************************************************\
173 |* GetXPM *|
174 \*******************************************************************************/
176 static void GetXPM(XpmIcon * wmgen, char *pixmap_bytes[])
179 XWindowAttributes attributes;
180 int err;
182 /* For the colormap */
183 XGetWindowAttributes(display, Root, &attributes);
185 wmgen->attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
187 err = XpmCreatePixmapFromData(display, Root, pixmap_bytes, &(wmgen->pixmap),
188 &(wmgen->mask), &(wmgen->attributes));
190 if (err != XpmSuccess) {
191 fprintf(stderr, "Not enough free colorcells.\n");
192 exit(1);
196 /*******************************************************************************\
197 |* GetColor *|
198 \*******************************************************************************/
200 static Pixel GetColor(char *name)
203 XColor color;
204 XWindowAttributes attributes;
206 XGetWindowAttributes(display, Root, &attributes);
208 color.pixel = 0;
209 if (!XParseColor(display, attributes.colormap, name, &color)) {
210 fprintf(stderr, "wm.app: can't parse %s.\n", name);
211 } else if (!XAllocColor(display, attributes.colormap, &color)) {
212 fprintf(stderr, "wm.app: can't allocate %s.\n", name);
214 return color.pixel;
217 /*******************************************************************************\
218 |* flush_expose *|
219 \*******************************************************************************/
221 static int flush_expose(Window w)
224 XEvent dummy;
225 int i = 0;
227 while (XCheckTypedWindowEvent(display, w, Expose, &dummy))
228 i++;
230 return i;
233 /*******************************************************************************\
234 |* RedrawWindow *|
235 \*******************************************************************************/
237 void RedrawWindow(void)
240 flush_expose(iconwin);
241 XCopyArea(display, wmgen.pixmap, iconwin, NormalGC,
242 0, 0, wmgen.attributes.width, wmgen.attributes.height, 0, 0);
243 flush_expose(win);
244 XCopyArea(display, wmgen.pixmap, win, NormalGC,
245 0, 0, wmgen.attributes.width, wmgen.attributes.height, 0, 0);
248 /*******************************************************************************\
249 |* RedrawWindowXY *|
250 \*******************************************************************************/
252 void RedrawWindowXY(int x, int y)
255 flush_expose(iconwin);
256 XCopyArea(display, wmgen.pixmap, iconwin, NormalGC,
257 x, y, wmgen.attributes.width, wmgen.attributes.height, 0, 0);
258 flush_expose(win);
259 XCopyArea(display, wmgen.pixmap, win, NormalGC,
260 x, y, wmgen.attributes.width, wmgen.attributes.height, 0, 0);
263 /*******************************************************************************\
264 |* AddMouseRegion *|
265 \*******************************************************************************/
267 void AddMouseRegion(unsigned index, int left, int top, int right, int bottom)
270 if (index < MAX_MOUSE_REGION) {
271 mouse_region[index].enable = 1;
272 mouse_region[index].top = top;
273 mouse_region[index].left = left;
274 mouse_region[index].bottom = bottom;
275 mouse_region[index].right = right;
279 /*******************************************************************************\
280 |* CheckMouseRegion *|
281 \*******************************************************************************/
283 int CheckMouseRegion(int x, int y)
286 int i;
287 int found;
289 found = 0;
291 for (i = 0; i < MAX_MOUSE_REGION && !found; i++) {
292 if (mouse_region[i].enable &&
293 x <= mouse_region[i].right &&
294 x >= mouse_region[i].left &&
295 y <= mouse_region[i].bottom &&
296 y >= mouse_region[i].top)
297 found = 1;
299 if (!found)
300 return -1;
301 return (i - 1);
304 /***************************************************************************\
305 |* createXBMfromXPM *|
306 \***************************************************************************/
307 void createXBMfromXPM(char *xbm, char **xpm, int sx, int sy)
310 int i, j, k;
311 int width, height, numcol, depth;
312 int zero = 0;
313 unsigned char bwrite;
314 int bcount;
315 int curpixel;
317 sscanf(*xpm, "%d %d %d %d", &width, &height, &numcol, &depth);
320 for (k = 0; k != depth; k++) {
321 zero <<= 8;
322 zero |= xpm[1][k];
325 for (i = numcol + 1; i < numcol + sy + 1; i++) {
326 bcount = 0;
327 bwrite = 0;
328 for (j = 0; j < sx * depth; j += depth) {
329 bwrite >>= 1;
331 curpixel = 0;
332 for (k = 0; k != depth; k++) {
333 curpixel <<= 8;
334 curpixel |= xpm[i][j + k];
337 if (curpixel != zero) {
338 bwrite += 128;
340 bcount++;
341 if (bcount == 8) {
342 *xbm = bwrite;
343 xbm++;
344 bcount = 0;
345 bwrite = 0;
351 /*******************************************************************************\
352 |* copyXPMArea *|
353 \*******************************************************************************/
355 void copyXPMArea(int x, int y, int sx, int sy, int dx, int dy)
358 XCopyArea(display, wmgen.pixmap, wmgen.pixmap, NormalGC, x, y, sx, sy, dx, dy);
362 /*******************************************************************************\
363 |* copyXBMArea *|
364 \*******************************************************************************/
366 void copyXBMArea(int x, int y, int sx, int sy, int dx, int dy)
369 XCopyArea(display, wmgen.mask, wmgen.pixmap, NormalGC, x, y, sx, sy, dx, dy);
373 /*******************************************************************************\
374 |* setMaskXY *|
375 \*******************************************************************************/
377 void setMaskXY(int x, int y)
380 XShapeCombineMask(display, win, ShapeBounding, x, y, pixmask, ShapeSet);
381 XShapeCombineMask(display, iconwin, ShapeBounding, x, y, pixmask, ShapeSet);
384 /*******************************************************************************\
385 |* openXwindow *|
386 \*******************************************************************************/
387 void openXwindow(int argc, char *argv[], char *pixmap_bytes[], char *pixmask_bits, int pixmask_width, int pixmask_height)
390 unsigned int borderwidth = 1;
391 XClassHint classHint;
392 char *display_name = NULL;
393 char *wname = argv[0];
394 XTextProperty name;
396 XGCValues gcv;
397 unsigned long gcm;
399 char *geometry = NULL;
401 int dummy = 0;
402 int i, wx, wy;
404 for (i = 1; argv[i]; i++) {
405 if (!strcmp(argv[i], "-display")) {
406 display_name = argv[i + 1];
407 i++;
409 if (!strcmp(argv[i], "-geometry")) {
410 geometry = argv[i + 1];
411 i++;
415 if (!(display = XOpenDisplay(display_name))) {
416 fprintf(stderr, "%s: can't open display %s\n",
417 wname, XDisplayName(display_name));
418 exit(1);
420 screen = DefaultScreen(display);
421 Root = RootWindow(display, screen);
422 d_depth = DefaultDepth(display, screen);
423 x_fd = XConnectionNumber(display);
425 /* Convert XPM to XImage */
426 GetXPM(&wmgen, pixmap_bytes);
428 /* Create a window to hold the stuff */
429 mysizehints.flags = USSize | USPosition;
430 mysizehints.x = 0;
431 mysizehints.y = 0;
433 back_pix = GetColor("white");
434 fore_pix = GetColor("black");
436 XWMGeometry(display, screen, Geometry, NULL, borderwidth, &mysizehints,
437 &mysizehints.x, &mysizehints.y, &mysizehints.width, &mysizehints.height, &dummy);
439 mysizehints.width = 64;
440 mysizehints.height = 64;
442 win = XCreateSimpleWindow(display, Root, mysizehints.x, mysizehints.y,
443 mysizehints.width, mysizehints.height, borderwidth, fore_pix, back_pix);
445 iconwin = XCreateSimpleWindow(display, win, mysizehints.x, mysizehints.y,
446 mysizehints.width, mysizehints.height, borderwidth, fore_pix, back_pix);
448 /* Activate hints */
449 XSetWMNormalHints(display, win, &mysizehints);
450 classHint.res_name = wname;
451 classHint.res_class = wname;
452 XSetClassHint(display, win, &classHint);
454 XSelectInput(display, win, ButtonPressMask | ExposureMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask);
455 XSelectInput(display, iconwin, ButtonPressMask | ExposureMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask);
457 if (XStringListToTextProperty(&wname, 1, &name) == 0) {
458 fprintf(stderr, "%s: can't allocate window name\n", wname);
459 exit(1);
461 XSetWMName(display, win, &name);
463 /* Create GC for drawing */
465 gcm = GCForeground | GCBackground | GCGraphicsExposures;
466 gcv.foreground = fore_pix;
467 gcv.background = back_pix;
468 gcv.graphics_exposures = 0;
469 NormalGC = XCreateGC(display, Root, gcm, &gcv);
471 /* ONLYSHAPE ON */
473 pixmask = XCreateBitmapFromData(display, win, pixmask_bits, pixmask_width, pixmask_height);
475 XShapeCombineMask(display, win, ShapeBounding, 0, 0, pixmask, ShapeSet);
476 XShapeCombineMask(display, iconwin, ShapeBounding, 0, 0, pixmask, ShapeSet);
478 /* ONLYSHAPE OFF */
480 mywmhints.initial_state = WithdrawnState;
481 mywmhints.icon_window = iconwin;
482 mywmhints.icon_x = mysizehints.x;
483 mywmhints.icon_y = mysizehints.y;
484 mywmhints.window_group = win;
485 mywmhints.flags = StateHint | IconWindowHint | IconPositionHint | WindowGroupHint;
487 XSetWMHints(display, win, &mywmhints);
489 XSetCommand(display, win, argv, argc);
490 XMapWindow(display, win);
493 if (geometry) {
494 if (sscanf(geometry, "+%d+%d", &wx, &wy) != 2) {
495 fprintf(stderr, "Bad geometry string.\n");
496 exit(1);
498 XMoveWindow(display, win, wx, wy);
504 * font_init
506 void font_init()
508 GetXPM(&wmfont, charset_xpm);
511 void draw_char(char c, int x, int y)
513 int sx, sy;
514 sx = (c - 32) * 6;
515 sy = 0;
516 XCopyArea(display, wmfont.pixmap, wmgen.pixmap, NormalGC, sx, sy, 6, 7,
517 x, y);
520 void draw_string(char *s, int x, int y)
522 int i = 0;
523 int x_space = 6;
525 while (i < strlen(s)) {
526 if ((x + (x_space * i)) < 64) {
527 draw_char(s[i], x + (x_space * i), y);
529 i++;