88d76fe624309c0afce34a02e84b2e1ebf41dd57
[dockapps.git] / wmbiff / wmgeneral / wmgeneral.c
blob88d76fe624309c0afce34a02e84b2e1ebf41dd57
1 /*
2 Best viewed with vim5, using ts=4
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 ---
15 14/09/1998 (Dave Clark, clarkd@skyia.com)
16 * Updated createXBMfromXPM routine
17 * Now supports >256 colors
18 11/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
19 * Removed a bug from parse_rcfile. You could
20 not use "start" in a command if a label was
21 also start.
22 * Changed the needed geometry string.
23 We don't use window size, and don't support
24 negative positions.
25 03/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
26 * Added parse_rcfile2
27 02/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
28 * Added -geometry support (untested)
29 28/08/1998 (Martijn Pieterse, pieterse@xs4all.nl)
30 * Added createXBMfromXPM routine
31 * Saves a lot of work with changing xpm's.
32 02/05/1998 (Martijn Pieterse, pieterse@xs4all.nl)
33 * changed the read_rc_file to parse_rcfile, as suggested by Marcelo E. Magallon
34 * debugged the parse_rc file.
35 30/04/1998 (Martijn Pieterse, pieterse@xs4all.nl)
36 * Ripped similar code from all the wm* programs,
37 and put them in a single file.
41 #ifdef HAVE_CONFIG_H
42 #include <config.h>
43 #endif
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <unistd.h>
48 #include <ctype.h>
49 #include <stdarg.h>
50 #include <assert.h>
52 #include <X11/Xlib.h>
53 #ifdef HAVE_X11_XPM_H
54 #include <X11/xpm.h>
55 #endif
56 #ifdef HAVE_XPM_H
57 #include <xpm.h>
58 #endif
59 #include <X11/Xutil.h> /* needed for Region on solaris? */
60 #include <X11/extensions/shape.h>
62 #include "wmgeneral.h"
64 /*****************/
65 /* X11 Variables */
66 /*****************/
68 Window Root;
69 int screen;
70 int x_fd;
71 int d_depth;
72 XSizeHints mysizehints;
73 XWMHints mywmhints;
74 Pixel back_pix, fore_pix;
75 // static const char *Geometry = "";
76 Window iconwin, win;
77 GC NormalGC;
78 XpmIcon wmgen_bkg;
79 XpmIcon wmgen_src;
80 Pixmap pixmask;
82 /*****************/
83 /* Mouse Regions */
84 /*****************/
86 typedef struct {
87 int enable;
88 int top;
89 int bottom;
90 int left;
91 int right;
92 } MOUSE_REGION;
94 MOUSE_REGION mouse_region[MAX_MOUSE_REGION];
96 /***********************/
97 /* Function Prototypes */
98 /***********************/
100 static void GetXPM(XpmIcon *, const char **);
101 Pixel GetColor(const char *);
102 void RedrawWindow(void);
103 int CheckMouseRegion(int, int);
105 /*******************************************************************************\
106 |* parse_rcfile *|
107 \*******************************************************************************/
109 void parse_rcfile(const char *filename, rckeys * keys)
112 char *p, *q;
113 char temp[128];
114 const char *tokens = " :\t\n";
115 FILE *fp;
116 int i, key;
118 fp = fopen(filename, "r");
119 if (fp) {
120 while (fgets(temp, 128, fp)) {
121 key = 0;
122 q = strdup(temp);
123 q = strtok(q, tokens);
124 while (key >= 0 && keys[key].label) {
125 if ((!strcmp(q, keys[key].label))) {
126 p = strstr(temp, keys[key].label);
127 p += strlen(keys[key].label);
128 p += strspn(p, tokens);
129 if ((i = strcspn(p, "#\n")))
130 p[i] = 0;
131 free(*keys[key].var);
132 *keys[key].var = strdup(p);
133 key = -1;
134 } else
135 key++;
137 free(q);
139 fclose(fp);
143 /*******************************************************************************\
144 |* parse_rcfile2 *|
145 \*******************************************************************************/
147 void parse_rcfile2(const char *filename, rckeys2 * keys)
150 char *p;
151 char temp[128];
152 const char *tokens = " :\t\n";
153 FILE *fp;
154 int i, key;
155 char *family = NULL;
157 fp = fopen(filename, "r");
158 if (fp) {
159 while (fgets(temp, 128, fp)) {
160 key = 0;
161 while (key >= 0 && keys[key].label) {
162 if ((p = strstr(temp, keys[key].label))) {
163 p += strlen(keys[key].label);
164 p += strspn(p, tokens);
165 if ((i = strcspn(p, "#\n")))
166 p[i] = 0;
167 free(*keys[key].var);
168 *keys[key].var = strdup(p);
169 key = -1;
170 } else
171 key++;
174 fclose(fp);
176 free(family);
180 /*******************************************************************************\
181 |* GetXPM *|
182 \*******************************************************************************/
184 static void GetXPM(XpmIcon * wmgen_local, const char *pixmap_bytes[])
187 XWindowAttributes attributes;
188 int err;
190 /* For the colormap */
191 XGetWindowAttributes(display, Root, &attributes);
192 /* despite the comment, I still don't understand...
193 attributes is subsequently unused in this function -ns 11/2002 */
195 wmgen_local->attributes.valuemask |=
196 (XpmReturnPixels | XpmReturnExtensions);
198 err = XpmCreatePixmapFromData(display, Root, (char **) pixmap_bytes,
199 &(wmgen_local->pixmap),
200 &(wmgen_local->mask),
201 &(wmgen_local->attributes));
203 if (err != XpmSuccess) {
204 fprintf(stderr,
205 "Not enough free colorcells to create pixmap from data (err=%d).\n",
206 err);
207 exit(1);
211 /*******************************************************************************\
212 |* GetColor *|
213 \*******************************************************************************/
215 Pixel GetColor(const char *name)
218 XColor color;
219 XWindowAttributes attributes;
221 XGetWindowAttributes(display, Root, &attributes);
223 color.pixel = 0;
224 if (!XParseColor(display, attributes.colormap, name, &color)) {
225 fprintf(stderr, "wm.app: GetColor() can't parse %s.\n", name);
226 } else if (!XAllocColor(display, attributes.colormap, &color)) {
227 fprintf(stderr, "wm.app: GetColor() can't allocate %s.\n", name);
229 return color.pixel;
232 /*******************************************************************************\
233 |* flush_expose *|
234 \*******************************************************************************/
236 static int flush_expose(Window w)
239 XEvent dummy;
240 int i = 0;
242 while (XCheckTypedWindowEvent(display, w, Expose, &dummy))
243 i++;
245 return i;
248 /*******************************************************************************\
249 |* RedrawWindow *|
250 \*******************************************************************************/
252 void RedrawWindow(void)
255 flush_expose(iconwin);
256 XCopyArea(display, wmgen_bkg.pixmap, iconwin, NormalGC,
257 0, 0, wmgen_bkg.attributes.width,
258 wmgen_bkg.attributes.height, 0, 0);
259 flush_expose(win);
260 XCopyArea(display, wmgen_bkg.pixmap, win, NormalGC,
261 0, 0, wmgen_bkg.attributes.width,
262 wmgen_bkg.attributes.height, 0, 0);
265 /*******************************************************************************\
266 |* RedrawWindowXY *|
267 \*******************************************************************************/
269 void RedrawWindowXY(int x, int y)
272 flush_expose(iconwin);
273 XCopyArea(display, wmgen_bkg.pixmap, iconwin, NormalGC,
274 x, y, wmgen_bkg.attributes.width,
275 wmgen_bkg.attributes.height, 0, 0);
276 flush_expose(win);
277 XCopyArea(display, wmgen_bkg.pixmap, win, NormalGC,
278 x, y, wmgen_bkg.attributes.width,
279 wmgen_bkg.attributes.height, 0, 0);
282 /*******************************************************************************\
283 |* AddMouseRegion *|
284 \*******************************************************************************/
286 void AddMouseRegion(unsigned int region_idx, int left, int top, int right,
287 int bottom)
290 if (region_idx < MAX_MOUSE_REGION) {
291 mouse_region[region_idx].enable = 1;
292 mouse_region[region_idx].top = top;
293 mouse_region[region_idx].left = left;
294 mouse_region[region_idx].bottom = bottom;
295 mouse_region[region_idx].right = right;
299 /*******************************************************************************\
300 |* CheckMouseRegion *|
301 \*******************************************************************************/
303 int CheckMouseRegion(int x, int y)
306 int i;
307 int found;
309 found = 0;
311 for (i = 0; i < MAX_MOUSE_REGION && !found; i++) {
312 if (mouse_region[i].enable &&
313 x <= mouse_region[i].right &&
314 x >= mouse_region[i].left &&
315 y <= mouse_region[i].bottom && y >= mouse_region[i].top)
316 found = 1;
318 if (!found)
319 return -1;
320 return (i - 1);
323 /*******************************************************************************\
324 |* createXBMfromXPM *|
325 \*******************************************************************************/
326 void createXBMfromXPM(char *xbm, const char **xpm, int sx, int sy)
329 int i, j, k;
330 int width, height, numcol, depth;
331 int zero = 0;
332 unsigned char bwrite;
333 int bcount;
334 int curpixel;
336 sscanf(*xpm, "%d %d %d %d", &width, &height, &numcol, &depth);
339 for (k = 0; k != depth; k++) {
340 zero <<= 8;
341 zero |= xpm[1][k];
344 for (i = numcol + 1; i < numcol + sy + 1; i++) {
345 bcount = 0;
346 bwrite = 0;
347 for (j = 0; j < sx * depth; j += depth) {
348 bwrite >>= 1;
350 curpixel = 0;
351 for (k = 0; k != depth; k++) {
352 curpixel <<= 8;
353 curpixel |= xpm[i][j + k];
356 if (curpixel != zero) {
357 bwrite += 128;
359 bcount++;
360 if (bcount == 8) {
361 *xbm = bwrite;
362 xbm++;
363 bcount = 0;
364 bwrite = 0;
370 /*******************************************************************************\
371 |* copyXPMArea *|
372 \*******************************************************************************/
374 void copyXPMArea(int src_x, int src_y, int width, int height, int dest_x,
375 int dest_y)
378 XCopyArea(display, wmgen_src.pixmap, wmgen_bkg.pixmap, NormalGC, src_x,
379 src_y, width, height, dest_x, dest_y);
383 /*******************************************************************************\
384 |* copyXBMArea *|
385 \*******************************************************************************/
387 void copyXBMArea(int src_x, int src_y, int width, int height, int dest_x,
388 int dest_y)
391 XCopyArea(display, wmgen_src.mask, wmgen_bkg.pixmap, NormalGC, src_x,
392 src_y, width, height, dest_x, dest_y);
396 /* added for wmbiff */
397 XFontStruct *f;
398 int loadFont(const char *fontname)
400 if (display != NULL) {
401 f = XLoadQueryFont(display, fontname);
402 if (f) {
403 XSetFont(display, NormalGC, f->fid);
404 return 0;
405 } else {
406 printf("couldn't set font!\n");
409 return -1;
412 void drawString(int dest_x, int dest_y, const char *string,
413 const char *colorname, const char *bgcolorname,
414 int right_justify)
416 int len = strlen(string);
417 assert(colorname != NULL);
418 XSetForeground(display, NormalGC, GetColor(colorname));
419 XSetBackground(display, NormalGC, GetColor(bgcolorname));
420 if (right_justify)
421 dest_x -= XTextWidth(f, string, len);
422 XDrawImageString(display, wmgen_bkg.pixmap, NormalGC, dest_x, dest_y,
423 string, len);
426 void eraseRect(int x, int y, int x2, int y2, const char *bgcolorname)
428 XSetForeground(display, NormalGC, GetColor(bgcolorname));
429 XFillRectangle(display, wmgen_bkg.pixmap, NormalGC, x, y, x2 - x,
430 y2 - y);
433 /* end wmbiff additions */
435 /*******************************************************************************\
436 |* setMaskXY *|
437 \*******************************************************************************/
439 void setMaskXY(int x, int y)
442 XShapeCombineMask(display, win, ShapeBounding, x, y, pixmask,
443 ShapeSet);
444 XShapeCombineMask(display, iconwin, ShapeBounding, x, y, pixmask,
445 ShapeSet);
448 /*******************************************************************************\
449 |* openXwindow *|
450 \*******************************************************************************/
451 void openXwindow(int argc, const char *argv[],
452 const char *pixmap_bytes_bkg[],
453 const char *pixmap_bytes_src[], char *pixmask_bits,
454 int pixmask_width, int pixmask_height, int notWithdrawn)
457 unsigned int borderwidth = 1;
458 XClassHint classHint;
459 const char *display_name = NULL;
460 char *wname = strdup(argv[0]);
461 XTextProperty name;
463 XGCValues gcv;
464 unsigned long gcm;
466 const char *geometry = NULL;
467 char default_geometry[128];
469 int dummy = 0;
470 int i;
472 for (i = 1; argv[i]; i++) {
473 if (!strcmp(argv[i], "-display")) {
474 display_name = argv[i + 1];
475 i++;
477 if (!strcmp(argv[i], "-geometry")) {
478 geometry = argv[i + 1];
479 i++;
483 sprintf(default_geometry, "%dx%d+0+0", pixmask_width, pixmask_height);
485 if (!(display = XOpenDisplay(display_name))) {
486 fprintf(stderr, "%s: can't open display %s\n",
487 wname, XDisplayName(display_name));
488 exit(1);
490 screen = DefaultScreen(display);
491 Root = RootWindow(display, screen);
492 d_depth = DefaultDepth(display, screen);
493 x_fd = XConnectionNumber(display);
495 /* Convert XPM to XImage */
496 GetXPM(&wmgen_bkg, pixmap_bytes_bkg);
497 GetXPM(&wmgen_src, pixmap_bytes_src);
499 /* Create a window to hold the stuff */
500 mysizehints.flags = USSize | USPosition;
501 mysizehints.x = 0;
502 mysizehints.y = 0;
504 back_pix = GetColor("black");
505 fore_pix = GetColor("cyan");
507 XWMGeometry(display, screen, geometry, default_geometry, borderwidth,
508 &mysizehints, &mysizehints.x, &mysizehints.y,
509 &mysizehints.width, &mysizehints.height, &dummy);
511 mysizehints.width = pixmask_width; /* changed 11/2002 for wmbiff non 64x64-ness */
512 mysizehints.height = pixmask_height; /* was statically 64. */
514 win = XCreateSimpleWindow(display, Root, mysizehints.x, mysizehints.y,
515 mysizehints.width, mysizehints.height,
516 borderwidth, fore_pix, back_pix);
518 iconwin =
519 XCreateSimpleWindow(display, win, mysizehints.x, mysizehints.y,
520 mysizehints.width, mysizehints.height,
521 borderwidth, fore_pix, back_pix);
523 /* Activate hints */
524 XSetWMNormalHints(display, win, &mysizehints);
525 classHint.res_name = wname;
526 classHint.res_class = wname;
527 XSetClassHint(display, win, &classHint);
529 /* Was PointerMotionMask instead of KeyPressMask, but pointer motion is irrelevant,
530 and if the user went to the trouble of giving us keypresses, the least we can do
531 is handle em... */
532 XSelectInput(display, win,
533 ButtonPressMask | ExposureMask | ButtonReleaseMask |
534 KeyPressMask | StructureNotifyMask);
535 XSelectInput(display, iconwin,
536 ButtonPressMask | ExposureMask | ButtonReleaseMask |
537 KeyPressMask | StructureNotifyMask);
539 /* wname is argv[0] */
540 if (XStringListToTextProperty(&wname, 1, &name) == 0) {
541 fprintf(stderr, "%s: can't allocate window name\n", wname);
542 exit(1);
545 XSetWMName(display, win, &name);
547 /* Create GC for drawing */
549 gcm = GCForeground | GCBackground | GCGraphicsExposures;
550 gcv.foreground = fore_pix;
551 gcv.background = back_pix;
552 gcv.graphics_exposures = 0;
553 NormalGC = XCreateGC(display, Root, gcm, &gcv);
555 /* ONLYSHAPE ON */
557 pixmask =
558 XCreateBitmapFromData(display, win, pixmask_bits, pixmask_width,
559 pixmask_height);
561 XShapeCombineMask(display, win, ShapeBounding, 0, 0, pixmask,
562 ShapeSet);
563 XShapeCombineMask(display, iconwin, ShapeBounding, 0, 0, pixmask,
564 ShapeSet);
566 /* ONLYSHAPE OFF */
568 mywmhints.initial_state = WithdrawnState;
569 mywmhints.icon_window = iconwin;
570 mywmhints.icon_x = mysizehints.x;
571 mywmhints.icon_y = mysizehints.y;
572 mywmhints.window_group = win;
573 mywmhints.flags =
574 (notWithdrawn ? 0 : StateHint) | IconWindowHint |
575 IconPositionHint | WindowGroupHint;
577 XSetWMHints(display, win, &mywmhints);
579 XSetCommand(display, win, (char **) argv, argc);
580 XMapWindow(display, win);
582 if (geometry) {
583 /* we'll silently drop width and height as well as negative positions */
584 /* mostly because I don't know how to deal with them */
586 int wx, wy, x, y;
587 int specified = XParseGeometry(geometry, &x, &y, &wx, &wy);
588 printf("%d %d %d %d\n", x, y, wx, wy);
589 if( specified & XNegative ) {
590 x = DisplayWidth(display, DefaultScreen(display)) - x - pixmask_width;
592 if( specified & YNegative ) {
593 y = DisplayHeight(display, DefaultScreen(display)) - y - pixmask_height;
595 if( specified & XValue || specified & YValue ) {
596 XMoveWindow(display, win, x, y);
597 } */
600 if (sscanf(geometry, "+%d+%d", &wx, &wy) == 2) {
601 XMoveWindow(display, win, wx, wy);
602 } else if (sscanf(geometry, "%dx%d+%d+%d", &x, &y, &wx, &wy) == 4) {
603 XMoveWindow(display, win, wx, wy);
604 } else if (sscanf(geometry, "+%d-%d", &wx, &wy) == 2) {
605 XMoveWindow(display, win, wx, 0 - wy);
606 } else {
607 fprintf(stderr, "Unsupported geometry string '%s'\n",
608 geometry);
609 exit(1);
610 } */