wmcore: set DESTDIR so binary installs correctly.
[dockapps.git] / wmbiff / wmgeneral / wmgeneral.c
blob6dfc644729652a1b22b8cc2874c5397d663f5033
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 Display *display;
69 Window Root;
70 int screen;
71 int x_fd;
72 int d_depth;
73 XSizeHints mysizehints;
74 XWMHints mywmhints;
75 Pixel back_pix, fore_pix;
76 // static const char *Geometry = "";
77 Window iconwin, win;
78 GC NormalGC;
79 XpmIcon wmgen_bkg;
80 XpmIcon wmgen_src;
81 Pixmap pixmask;
83 /*****************/
84 /* Mouse Regions */
85 /*****************/
87 typedef struct {
88 int enable;
89 int top;
90 int bottom;
91 int left;
92 int right;
93 } MOUSE_REGION;
95 MOUSE_REGION mouse_region[MAX_MOUSE_REGION];
97 /***********************/
98 /* Function Prototypes */
99 /***********************/
101 static void GetXPM(XpmIcon *, const char **);
102 Pixel GetColor(const char *);
103 void RedrawWindow(void);
104 int CheckMouseRegion(int, int);
106 /*******************************************************************************\
107 |* parse_rcfile *|
108 \*******************************************************************************/
110 void parse_rcfile(const char *filename, rckeys * keys)
113 char *p, *q;
114 char temp[128];
115 const char *tokens = " :\t\n";
116 FILE *fp;
117 int i, key;
119 fp = fopen(filename, "r");
120 if (fp) {
121 while (fgets(temp, 128, fp)) {
122 key = 0;
123 char *t = strdup(temp);
124 q = strtok(t, tokens);
125 while (key >= 0 && keys[key].label) {
126 if ((!strcmp(q, keys[key].label))) {
127 p = strstr(temp, keys[key].label);
128 p += strlen(keys[key].label);
129 p += strspn(p, tokens);
130 if ((i = strcspn(p, "#\n")))
131 p[i] = 0;
132 free(*keys[key].var);
133 *keys[key].var = strdup(p);
134 key = -1;
135 } else
136 key++;
138 free(t);
140 fclose(fp);
144 /*******************************************************************************\
145 |* parse_rcfile2 *|
146 \*******************************************************************************/
148 void parse_rcfile2(const char *filename, rckeys2 * keys)
151 char *p;
152 char temp[128];
153 const char *tokens = " :\t\n";
154 FILE *fp;
155 int i, key;
156 char *family = NULL;
158 fp = fopen(filename, "r");
159 if (fp) {
160 while (fgets(temp, 128, fp)) {
161 key = 0;
162 while (key >= 0 && keys[key].label) {
163 if ((p = strstr(temp, keys[key].label))) {
164 p += strlen(keys[key].label);
165 p += strspn(p, tokens);
166 if ((i = strcspn(p, "#\n")))
167 p[i] = 0;
168 free(*keys[key].var);
169 *keys[key].var = strdup(p);
170 key = -1;
171 } else
172 key++;
175 fclose(fp);
177 free(family);
181 /*******************************************************************************\
182 |* GetXPM *|
183 \*******************************************************************************/
185 static void GetXPM(XpmIcon * wmgen_local, const char *pixmap_bytes[])
188 XWindowAttributes attributes;
189 int err;
191 /* For the colormap */
192 XGetWindowAttributes(display, Root, &attributes);
193 /* despite the comment, I still don't understand...
194 attributes is subsequently unused in this function -ns 11/2002 */
196 wmgen_local->attributes.valuemask |=
197 (XpmReturnPixels | XpmReturnExtensions);
199 err = XpmCreatePixmapFromData(display, Root, (char **) pixmap_bytes,
200 &(wmgen_local->pixmap),
201 &(wmgen_local->mask),
202 &(wmgen_local->attributes));
204 if (err != XpmSuccess) {
205 fprintf(stderr,
206 "Not enough free colorcells to create pixmap from data (err=%d).\n",
207 err);
208 exit(1);
212 /*******************************************************************************\
213 |* GetColor *|
214 \*******************************************************************************/
216 Pixel GetColor(const char *name)
219 XColor color;
220 XWindowAttributes attributes;
222 XGetWindowAttributes(display, Root, &attributes);
224 color.pixel = 0;
225 if (!XParseColor(display, attributes.colormap, name, &color)) {
226 fprintf(stderr, "wm.app: GetColor() can't parse %s.\n", name);
227 } else if (!XAllocColor(display, attributes.colormap, &color)) {
228 fprintf(stderr, "wm.app: GetColor() can't allocate %s.\n", name);
230 return color.pixel;
233 /*******************************************************************************\
234 |* flush_expose *|
235 \*******************************************************************************/
237 static int flush_expose(Window w)
240 XEvent dummy;
241 int i = 0;
243 while (XCheckTypedWindowEvent(display, w, Expose, &dummy))
244 i++;
246 return i;
249 /*******************************************************************************\
250 |* RedrawWindow *|
251 \*******************************************************************************/
253 void RedrawWindow(void)
256 flush_expose(iconwin);
257 XCopyArea(display, wmgen_bkg.pixmap, iconwin, NormalGC,
258 0, 0, wmgen_bkg.attributes.width,
259 wmgen_bkg.attributes.height, 0, 0);
260 flush_expose(win);
261 XCopyArea(display, wmgen_bkg.pixmap, win, NormalGC,
262 0, 0, wmgen_bkg.attributes.width,
263 wmgen_bkg.attributes.height, 0, 0);
266 /*******************************************************************************\
267 |* RedrawWindowXY *|
268 \*******************************************************************************/
270 void RedrawWindowXY(int x, int y)
273 flush_expose(iconwin);
274 XCopyArea(display, wmgen_bkg.pixmap, iconwin, NormalGC,
275 x, y, wmgen_bkg.attributes.width,
276 wmgen_bkg.attributes.height, 0, 0);
277 flush_expose(win);
278 XCopyArea(display, wmgen_bkg.pixmap, win, NormalGC,
279 x, y, wmgen_bkg.attributes.width,
280 wmgen_bkg.attributes.height, 0, 0);
283 /*******************************************************************************\
284 |* AddMouseRegion *|
285 \*******************************************************************************/
287 void AddMouseRegion(unsigned int region_idx, int left, int top, int right,
288 int bottom)
291 if (region_idx < MAX_MOUSE_REGION) {
292 mouse_region[region_idx].enable = 1;
293 mouse_region[region_idx].top = top;
294 mouse_region[region_idx].left = left;
295 mouse_region[region_idx].bottom = bottom;
296 mouse_region[region_idx].right = right;
300 /*******************************************************************************\
301 |* CheckMouseRegion *|
302 \*******************************************************************************/
304 int CheckMouseRegion(int x, int y)
307 int i;
308 int found;
310 found = 0;
312 for (i = 0; i < MAX_MOUSE_REGION && !found; i++) {
313 if (mouse_region[i].enable &&
314 x <= mouse_region[i].right &&
315 x >= mouse_region[i].left &&
316 y <= mouse_region[i].bottom && y >= mouse_region[i].top)
317 found = 1;
319 if (!found)
320 return -1;
321 return (i - 1);
324 /*******************************************************************************\
325 |* createXBMfromXPM *|
326 \*******************************************************************************/
327 void createXBMfromXPM(char *xbm, const char **xpm, int sx, int sy)
330 int i, j, k;
331 int width, height, numcol, depth;
332 int zero = 0;
333 unsigned char bwrite;
334 int bcount;
335 int curpixel;
337 sscanf(*xpm, "%d %d %d %d", &width, &height, &numcol, &depth);
340 for (k = 0; k != depth; k++) {
341 zero <<= 8;
342 zero |= xpm[1][k];
345 for (i = numcol + 1; i < numcol + sy + 1; i++) {
346 bcount = 0;
347 bwrite = 0;
348 for (j = 0; j < sx * depth; j += depth) {
349 bwrite >>= 1;
351 curpixel = 0;
352 for (k = 0; k != depth; k++) {
353 curpixel <<= 8;
354 curpixel |= xpm[i][j + k];
357 if (curpixel != zero) {
358 bwrite += 128;
360 bcount++;
361 if (bcount == 8) {
362 *xbm = bwrite;
363 xbm++;
364 bcount = 0;
365 bwrite = 0;
371 /*******************************************************************************\
372 |* copyXPMArea *|
373 \*******************************************************************************/
375 void copyXPMArea(int src_x, int src_y, int width, int height, int dest_x,
376 int dest_y)
379 XCopyArea(display, wmgen_src.pixmap, wmgen_bkg.pixmap, NormalGC, src_x,
380 src_y, width, height, dest_x, dest_y);
384 /*******************************************************************************\
385 |* copyXBMArea *|
386 \*******************************************************************************/
388 void copyXBMArea(int src_x, int src_y, int width, int height, int dest_x,
389 int dest_y)
392 XCopyArea(display, wmgen_src.mask, wmgen_bkg.pixmap, NormalGC, src_x,
393 src_y, width, height, dest_x, dest_y);
397 /* added for wmbiff */
398 XFontStruct *f;
399 int loadFont(const char *fontname)
401 if (display != NULL) {
402 f = XLoadQueryFont(display, fontname);
403 if (f) {
404 XSetFont(display, NormalGC, f->fid);
405 return 0;
406 } else {
407 printf("couldn't set font!\n");
410 return -1;
413 void drawString(int dest_x, int dest_y, const char *string,
414 const char *colorname, const char *bgcolorname,
415 int right_justify)
417 int len = strlen(string);
418 assert(colorname != NULL);
419 XSetForeground(display, NormalGC, GetColor(colorname));
420 XSetBackground(display, NormalGC, GetColor(bgcolorname));
421 if (right_justify)
422 dest_x -= XTextWidth(f, string, len);
423 XDrawImageString(display, wmgen_bkg.pixmap, NormalGC, dest_x, dest_y,
424 string, len);
427 void eraseRect(int x, int y, int x2, int y2, const char *bgcolorname)
429 XSetForeground(display, NormalGC, GetColor(bgcolorname));
430 XFillRectangle(display, wmgen_bkg.pixmap, NormalGC, x, y, x2 - x,
431 y2 - y);
434 /* end wmbiff additions */
436 /*******************************************************************************\
437 |* setMaskXY *|
438 \*******************************************************************************/
440 void setMaskXY(int x, int y)
443 XShapeCombineMask(display, win, ShapeBounding, x, y, pixmask,
444 ShapeSet);
445 XShapeCombineMask(display, iconwin, ShapeBounding, x, y, pixmask,
446 ShapeSet);
449 /*******************************************************************************\
450 |* openXwindow *|
451 \*******************************************************************************/
452 void openXwindow(int argc, const char *argv[],
453 const char *pixmap_bytes_bkg[],
454 const char *pixmap_bytes_src[], char *pixmask_bits,
455 int pixmask_width, int pixmask_height, int notWithdrawn)
458 unsigned int borderwidth = 1;
459 XClassHint classHint;
460 const char *display_name = NULL;
461 char *wname = strdup(argv[0]);
462 XTextProperty name;
464 XGCValues gcv;
465 unsigned long gcm;
467 const char *geometry = NULL;
468 char default_geometry[128];
470 int dummy = 0;
471 int i;
473 if (!wname) {
474 fprintf(stderr, "Unable to allocate memory for window name!\n");
475 abort();
478 for (i = 1; argv[i]; i++) {
479 if (!strcmp(argv[i], "-display") && i < argc - 1) {
480 display_name = argv[i + 1];
481 i++;
483 if (!strcmp(argv[i], "-geometry") && i < argc - 1) {
484 geometry = argv[i + 1];
485 i++;
489 sprintf(default_geometry, "%dx%d+0+0", pixmask_width, pixmask_height);
491 if (!(display = XOpenDisplay(display_name))) {
492 fprintf(stderr, "%s: can't open display %s\n",
493 wname, XDisplayName(display_name));
494 exit(1);
496 screen = DefaultScreen(display);
497 Root = RootWindow(display, screen);
498 d_depth = DefaultDepth(display, screen);
499 x_fd = XConnectionNumber(display);
501 /* Convert XPM to XImage */
502 GetXPM(&wmgen_bkg, pixmap_bytes_bkg);
503 GetXPM(&wmgen_src, pixmap_bytes_src);
505 /* Create a window to hold the stuff */
506 mysizehints.flags = USSize | USPosition;
507 mysizehints.x = 0;
508 mysizehints.y = 0;
510 back_pix = GetColor("black");
511 fore_pix = GetColor("cyan");
513 XWMGeometry(display, screen, geometry, default_geometry, borderwidth,
514 &mysizehints, &mysizehints.x, &mysizehints.y,
515 &mysizehints.width, &mysizehints.height, &dummy);
517 mysizehints.width = pixmask_width; /* changed 11/2002 for wmbiff non 64x64-ness */
518 mysizehints.height = pixmask_height; /* was statically 64. */
520 win = XCreateSimpleWindow(display, Root, mysizehints.x, mysizehints.y,
521 mysizehints.width, mysizehints.height,
522 borderwidth, fore_pix, back_pix);
524 iconwin =
525 XCreateSimpleWindow(display, win, mysizehints.x, mysizehints.y,
526 mysizehints.width, mysizehints.height,
527 borderwidth, fore_pix, back_pix);
529 /* Activate hints */
530 XSetWMNormalHints(display, win, &mysizehints);
531 classHint.res_name = wname;
532 classHint.res_class = wname;
533 XSetClassHint(display, win, &classHint);
535 /* Was PointerMotionMask instead of KeyPressMask, but pointer motion is irrelevant,
536 and if the user went to the trouble of giving us keypresses, the least we can do
537 is handle em... */
538 XSelectInput(display, win,
539 ButtonPressMask | ExposureMask | ButtonReleaseMask |
540 KeyPressMask | StructureNotifyMask);
541 XSelectInput(display, iconwin,
542 ButtonPressMask | ExposureMask | ButtonReleaseMask |
543 KeyPressMask | StructureNotifyMask);
545 /* wname is argv[0] */
546 if (XStringListToTextProperty(&wname, 1, &name) == 0) {
547 fprintf(stderr, "%s: can't allocate window name\n", wname);
548 exit(1);
551 XSetWMName(display, win, &name);
552 XFree(name.value);
554 /* Create GC for drawing */
556 gcm = GCForeground | GCBackground | GCGraphicsExposures;
557 gcv.foreground = fore_pix;
558 gcv.background = back_pix;
559 gcv.graphics_exposures = 0;
560 NormalGC = XCreateGC(display, Root, gcm, &gcv);
562 /* ONLYSHAPE ON */
564 pixmask =
565 XCreateBitmapFromData(display, win, pixmask_bits, pixmask_width,
566 pixmask_height);
568 XShapeCombineMask(display, win, ShapeBounding, 0, 0, pixmask,
569 ShapeSet);
570 XShapeCombineMask(display, iconwin, ShapeBounding, 0, 0, pixmask,
571 ShapeSet);
573 /* ONLYSHAPE OFF */
575 mywmhints.initial_state = WithdrawnState;
576 mywmhints.icon_window = iconwin;
577 mywmhints.icon_x = mysizehints.x;
578 mywmhints.icon_y = mysizehints.y;
579 mywmhints.window_group = win;
580 mywmhints.flags =
581 (notWithdrawn ? 0 : StateHint) | IconWindowHint |
582 IconPositionHint | WindowGroupHint;
584 XSetWMHints(display, win, &mywmhints);
586 XSetCommand(display, win, (char **) argv, argc);
587 XMapWindow(display, win);
589 if (geometry) {
590 /* we'll silently drop width and height as well as negative positions */
591 /* mostly because I don't know how to deal with them */
593 int wx, wy, x, y;
594 int specified = XParseGeometry(geometry, &x, &y, &wx, &wy);
595 printf("%d %d %d %d\n", x, y, wx, wy);
596 if( specified & XNegative ) {
597 x = DisplayWidth(display, DefaultScreen(display)) - x - pixmask_width;
599 if( specified & YNegative ) {
600 y = DisplayHeight(display, DefaultScreen(display)) - y - pixmask_height;
602 if( specified & XValue || specified & YValue ) {
603 XMoveWindow(display, win, x, y);
604 } */
607 if (sscanf(geometry, "+%d+%d", &wx, &wy) == 2) {
608 XMoveWindow(display, win, wx, wy);
609 } else if (sscanf(geometry, "%dx%d+%d+%d", &x, &y, &wx, &wy) == 4) {
610 XMoveWindow(display, win, wx, wy);
611 } else if (sscanf(geometry, "+%d-%d", &wx, &wy) == 2) {
612 XMoveWindow(display, win, wx, 0 - wy);
613 } else {
614 fprintf(stderr, "Unsupported geometry string '%s'\n",
615 geometry);
616 exit(1);
617 } */
620 if (wname)
621 free(wname);