wmappkill: Add version 0.2 to repository.
[dockapps.git] / wmbiff / wmgeneral / wmgeneral.c
blobddae0d7ed17f06be32844afcb624cc0686ddf02b
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 if (!wname) {
473 fprintf(stderr, "Unable to allocate memory for window name!\n");
474 abort();
477 for (i = 1; argv[i]; i++) {
478 if (!strcmp(argv[i], "-display") && i < argc - 1) {
479 display_name = argv[i + 1];
480 i++;
482 if (!strcmp(argv[i], "-geometry") && i < argc - 1) {
483 geometry = argv[i + 1];
484 i++;
488 sprintf(default_geometry, "%dx%d+0+0", pixmask_width, pixmask_height);
490 if (!(display = XOpenDisplay(display_name))) {
491 fprintf(stderr, "%s: can't open display %s\n",
492 wname, XDisplayName(display_name));
493 exit(1);
495 screen = DefaultScreen(display);
496 Root = RootWindow(display, screen);
497 d_depth = DefaultDepth(display, screen);
498 x_fd = XConnectionNumber(display);
500 /* Convert XPM to XImage */
501 GetXPM(&wmgen_bkg, pixmap_bytes_bkg);
502 GetXPM(&wmgen_src, pixmap_bytes_src);
504 /* Create a window to hold the stuff */
505 mysizehints.flags = USSize | USPosition;
506 mysizehints.x = 0;
507 mysizehints.y = 0;
509 back_pix = GetColor("black");
510 fore_pix = GetColor("cyan");
512 XWMGeometry(display, screen, geometry, default_geometry, borderwidth,
513 &mysizehints, &mysizehints.x, &mysizehints.y,
514 &mysizehints.width, &mysizehints.height, &dummy);
516 mysizehints.width = pixmask_width; /* changed 11/2002 for wmbiff non 64x64-ness */
517 mysizehints.height = pixmask_height; /* was statically 64. */
519 win = XCreateSimpleWindow(display, Root, mysizehints.x, mysizehints.y,
520 mysizehints.width, mysizehints.height,
521 borderwidth, fore_pix, back_pix);
523 iconwin =
524 XCreateSimpleWindow(display, win, mysizehints.x, mysizehints.y,
525 mysizehints.width, mysizehints.height,
526 borderwidth, fore_pix, back_pix);
528 /* Activate hints */
529 XSetWMNormalHints(display, win, &mysizehints);
530 classHint.res_name = wname;
531 classHint.res_class = wname;
532 XSetClassHint(display, win, &classHint);
534 /* Was PointerMotionMask instead of KeyPressMask, but pointer motion is irrelevant,
535 and if the user went to the trouble of giving us keypresses, the least we can do
536 is handle em... */
537 XSelectInput(display, win,
538 ButtonPressMask | ExposureMask | ButtonReleaseMask |
539 KeyPressMask | StructureNotifyMask);
540 XSelectInput(display, iconwin,
541 ButtonPressMask | ExposureMask | ButtonReleaseMask |
542 KeyPressMask | StructureNotifyMask);
544 /* wname is argv[0] */
545 if (XStringListToTextProperty(&wname, 1, &name) == 0) {
546 fprintf(stderr, "%s: can't allocate window name\n", wname);
547 exit(1);
550 XSetWMName(display, win, &name);
551 XFree(name.value);
553 /* Create GC for drawing */
555 gcm = GCForeground | GCBackground | GCGraphicsExposures;
556 gcv.foreground = fore_pix;
557 gcv.background = back_pix;
558 gcv.graphics_exposures = 0;
559 NormalGC = XCreateGC(display, Root, gcm, &gcv);
561 /* ONLYSHAPE ON */
563 pixmask =
564 XCreateBitmapFromData(display, win, pixmask_bits, pixmask_width,
565 pixmask_height);
567 XShapeCombineMask(display, win, ShapeBounding, 0, 0, pixmask,
568 ShapeSet);
569 XShapeCombineMask(display, iconwin, ShapeBounding, 0, 0, pixmask,
570 ShapeSet);
572 /* ONLYSHAPE OFF */
574 mywmhints.initial_state = WithdrawnState;
575 mywmhints.icon_window = iconwin;
576 mywmhints.icon_x = mysizehints.x;
577 mywmhints.icon_y = mysizehints.y;
578 mywmhints.window_group = win;
579 mywmhints.flags =
580 (notWithdrawn ? 0 : StateHint) | IconWindowHint |
581 IconPositionHint | WindowGroupHint;
583 XSetWMHints(display, win, &mywmhints);
585 XSetCommand(display, win, (char **) argv, argc);
586 XMapWindow(display, win);
588 if (geometry) {
589 /* we'll silently drop width and height as well as negative positions */
590 /* mostly because I don't know how to deal with them */
592 int wx, wy, x, y;
593 int specified = XParseGeometry(geometry, &x, &y, &wx, &wy);
594 printf("%d %d %d %d\n", x, y, wx, wy);
595 if( specified & XNegative ) {
596 x = DisplayWidth(display, DefaultScreen(display)) - x - pixmask_width;
598 if( specified & YNegative ) {
599 y = DisplayHeight(display, DefaultScreen(display)) - y - pixmask_height;
601 if( specified & XValue || specified & YValue ) {
602 XMoveWindow(display, win, x, y);
603 } */
606 if (sscanf(geometry, "+%d+%d", &wx, &wy) == 2) {
607 XMoveWindow(display, win, wx, wy);
608 } else if (sscanf(geometry, "%dx%d+%d+%d", &x, &y, &wx, &wy) == 4) {
609 XMoveWindow(display, win, wx, wy);
610 } else if (sscanf(geometry, "+%d-%d", &wx, &wy) == 2) {
611 XMoveWindow(display, win, wx, 0 - wy);
612 } else {
613 fprintf(stderr, "Unsupported geometry string '%s'\n",
614 geometry);
615 exit(1);
616 } */
619 if (wname)
620 free(wname);