Improve dockapp recognition
[wmaker-crm.git] / src / misc.c
blobf89cd71b78b8140e3de425b4f1369c6c6f0fad5c
1 /*
2 * Window Maker window manager
4 * Copyright (c) 1997-2003 Alfredo K. Kojima
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 * USA.
21 #include "wconfig.h"
23 #include <X11/Xlib.h>
24 #include <X11/Xutil.h>
25 #include <X11/Xatom.h>
26 #include <sys/stat.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <stdarg.h>
32 #include <pwd.h>
33 #include <math.h>
34 #include <time.h>
36 #include <WINGs/WUtil.h>
37 #include <wraster.h>
39 #include "WindowMaker.h"
40 #include "GNUstep.h"
41 #include "screen.h"
42 #include "wcore.h"
43 #include "window.h"
44 #include "framewin.h"
45 #include "funcs.h"
46 #include "dialog.h"
47 #include "xutil.h"
48 #include "xmodifier.h"
50 /**** global variables *****/
51 extern WPreferences wPreferences;
53 #ifdef USECPP
54 static void putdef(char *line, char *name, char *value)
56 if (!value) {
57 wwarning(_("could not define value for %s for cpp"), name);
58 return;
60 strcat(line, name);
61 strcat(line, value);
64 static void putidef(char *line, char *name, int value)
66 char tmp[64];
67 snprintf(tmp, sizeof(tmp), "%i", value);
68 strcat(line, name);
69 strcat(line, tmp);
72 static char *username(void)
74 char *tmp;
76 tmp = getlogin();
77 if (!tmp) {
78 struct passwd *user;
80 user = getpwuid(getuid());
81 if (!user) {
82 wsyserror(_("could not get password entry for UID %i"), getuid());
83 return NULL;
85 if (!user->pw_name) {
86 return NULL;
87 } else {
88 return user->pw_name;
91 return tmp;
94 char *MakeCPPArgs(char *path)
96 int i;
97 char buffer[MAXLINE], *buf, *line;
98 Visual *visual;
99 char *tmp;
101 line = wmalloc(MAXLINE);
102 *line = 0;
103 i = 1;
104 if ((buf = getenv("HOSTNAME")) != NULL) {
105 if (buf[0] == '(') {
106 wwarning(_("your machine is misconfigured. HOSTNAME is set to %s"), buf);
107 } else
108 putdef(line, " -DHOST=", buf);
109 } else if ((buf = getenv("HOST")) != NULL) {
110 if (buf[0] == '(') {
111 wwarning(_("your machine is misconfigured. HOST is set to %s"), buf);
112 } else
113 putdef(line, " -DHOST=", buf);
115 buf = username();
116 if (buf)
117 putdef(line, " -DUSER=", buf);
118 putidef(line, " -DUID=", getuid());
119 buf = XDisplayName(DisplayString(dpy));
120 putdef(line, " -DDISPLAY=", buf);
121 putdef(line, " -DWM_VERSION=", VERSION);
123 visual = DefaultVisual(dpy, DefaultScreen(dpy));
124 putidef(line, " -DVISUAL=", visual->class);
126 putidef(line, " -DDEPTH=", DefaultDepth(dpy, DefaultScreen(dpy)));
128 putidef(line, " -DSCR_WIDTH=", WidthOfScreen(DefaultScreenOfDisplay(dpy)));
129 putidef(line, " -DSCR_HEIGHT=", HeightOfScreen(DefaultScreenOfDisplay(dpy)));
131 /* put the dir where the menu is being read from to the
132 * search path */
133 if (path) {
134 tmp = wstrdup(path);
135 buf = strchr(tmp + 1, ' ');
136 if (buf) {
137 *buf = 0;
139 buf = strrchr(tmp, '/');
140 if (buf) {
141 *buf = 0; /* trunc filename */
142 putdef(line, " -I", tmp);
144 wfree(tmp);
147 /* this should be done just once, but it works this way */
148 strcpy(buffer, DEF_CONFIG_PATHS);
149 buf = strtok(buffer, ":");
151 do {
152 char fullpath[MAXLINE];
154 if (buf[0] != '~') {
155 strcpy(fullpath, buf);
156 } else {
157 /* home is statically allocated. Don't free it! */
158 char *home = wgethomedir();
160 strcpy(fullpath, home);
161 strcat(fullpath, &(buf[1]));
164 putdef(line, " -I", fullpath);
166 } while ((buf = strtok(NULL, ":")) != NULL);
168 #undef arg
169 return line;
171 #endif /* USECPP */
173 /* XFetchName Wrapper */
174 Bool wFetchName(Display *dpy, Window win, char **winname)
176 XTextProperty text_prop;
177 char **list;
178 int num;
180 if (XGetWMName(dpy, win, &text_prop)) {
181 if (text_prop.value && text_prop.nitems > 0) {
182 if (text_prop.encoding == XA_STRING) {
183 *winname = wstrdup((char *)text_prop.value);
184 XFree(text_prop.value);
185 } else {
186 text_prop.nitems = strlen((char *)text_prop.value);
187 if (XmbTextPropertyToTextList(dpy, &text_prop, &list, &num) >=
188 Success && num > 0 && *list) {
189 XFree(text_prop.value);
190 *winname = wstrdup(*list);
191 XFreeStringList(list);
192 } else {
193 *winname = wstrdup((char *)text_prop.value);
194 XFree(text_prop.value);
197 } else {
198 /* the title is set, but it was set to none */
199 *winname = wstrdup("");
201 return True;
202 } else {
203 /* the hint is probably not set */
204 *winname = NULL;
206 return False;
210 /* XGetIconName Wrapper */
211 Bool wGetIconName(Display *dpy, Window win, char **iconname)
213 XTextProperty text_prop;
214 char **list;
215 int num;
217 if (XGetWMIconName(dpy, win, &text_prop) != 0 && text_prop.value && text_prop.nitems > 0) {
218 if (text_prop.encoding == XA_STRING)
219 *iconname = (char *)text_prop.value;
220 else {
221 text_prop.nitems = strlen((char *)text_prop.value);
222 if (XmbTextPropertyToTextList(dpy, &text_prop, &list, &num) >= Success && num > 0 && *list) {
223 XFree(text_prop.value);
224 *iconname = wstrdup(*list);
225 XFreeStringList(list);
226 } else
227 *iconname = (char *)text_prop.value;
229 return True;
231 *iconname = NULL;
232 return False;
235 static void eatExpose(void)
237 XEvent event, foo;
239 /* compress all expose events into a single one */
241 if (XCheckMaskEvent(dpy, ExposureMask, &event)) {
242 /* ignore other exposure events for this window */
243 while (XCheckWindowEvent(dpy, event.xexpose.window, ExposureMask, &foo)) ;
244 /* eat exposes for other windows */
245 eatExpose();
247 event.xexpose.count = 0;
248 XPutBackEvent(dpy, &event);
252 void SlideWindow(Window win, int from_x, int from_y, int to_x, int to_y)
254 time_t time0 = time(NULL);
255 float dx, dy, x = from_x, y = from_y, sx, sy, px, py;
256 int dx_is_bigger = 0;
257 int slide_delay, slide_steps, slide_slowdown;
259 /* animation parameters */
260 static struct {
261 int delay;
262 int steps;
263 int slowdown;
264 } apars[5] = {
265 {ICON_SLIDE_DELAY_UF, ICON_SLIDE_STEPS_UF, ICON_SLIDE_SLOWDOWN_UF},
266 {ICON_SLIDE_DELAY_F, ICON_SLIDE_STEPS_F, ICON_SLIDE_SLOWDOWN_F},
267 {ICON_SLIDE_DELAY_M, ICON_SLIDE_STEPS_M, ICON_SLIDE_SLOWDOWN_M},
268 {ICON_SLIDE_DELAY_S, ICON_SLIDE_STEPS_S, ICON_SLIDE_SLOWDOWN_S},
269 {ICON_SLIDE_DELAY_US, ICON_SLIDE_STEPS_US, ICON_SLIDE_SLOWDOWN_US}
272 slide_slowdown = apars[(int)wPreferences.icon_slide_speed].slowdown;
273 slide_steps = apars[(int)wPreferences.icon_slide_speed].steps;
274 slide_delay = apars[(int)wPreferences.icon_slide_speed].delay;
276 dx = (float)(to_x - from_x);
277 dy = (float)(to_y - from_y);
278 sx = (dx == 0 ? 0 : fabs(dx) / dx);
279 sy = (dy == 0 ? 0 : fabs(dy) / dy);
281 if (fabs(dx) > fabs(dy)) {
282 dx_is_bigger = 1;
285 if (dx_is_bigger) {
286 px = dx / slide_slowdown;
287 if (px < slide_steps && px > 0)
288 px = slide_steps;
289 else if (px > -slide_steps && px < 0)
290 px = -slide_steps;
291 py = (sx == 0 ? 0 : px * dy / dx);
292 } else {
293 py = dy / slide_slowdown;
294 if (py < slide_steps && py > 0)
295 py = slide_steps;
296 else if (py > -slide_steps && py < 0)
297 py = -slide_steps;
298 px = (sy == 0 ? 0 : py * dx / dy);
301 while (x != to_x || y != to_y) {
302 x += px;
303 y += py;
304 if ((px < 0 && (int)x < to_x) || (px > 0 && (int)x > to_x))
305 x = (float)to_x;
306 if ((py < 0 && (int)y < to_y) || (py > 0 && (int)y > to_y))
307 y = (float)to_y;
309 if (dx_is_bigger) {
310 px = px * (1.0 - 1 / (float)slide_slowdown);
311 if (px < slide_steps && px > 0)
312 px = slide_steps;
313 else if (px > -slide_steps && px < 0)
314 px = -slide_steps;
315 py = (sx == 0 ? 0 : px * dy / dx);
316 } else {
317 py = py * (1.0 - 1 / (float)slide_slowdown);
318 if (py < slide_steps && py > 0)
319 py = slide_steps;
320 else if (py > -slide_steps && py < 0)
321 py = -slide_steps;
322 px = (sy == 0 ? 0 : py * dx / dy);
325 XMoveWindow(dpy, win, (int)x, (int)y);
326 XFlush(dpy);
327 if (slide_delay > 0) {
328 wusleep(slide_delay * 1000L);
329 } else {
330 wusleep(10);
332 if (time(NULL) - time0 > MAX_ANIMATION_TIME)
333 break;
335 XMoveWindow(dpy, win, to_x, to_y);
337 XSync(dpy, 0);
338 /* compress expose events */
339 eatExpose();
342 char *ShrinkString(WMFont * font, char *string, int width)
344 int w, w1 = 0;
345 int p;
346 char *pos;
347 char *text;
348 int p1, p2, t;
350 p = strlen(string);
351 w = WMWidthOfString(font, string, p);
352 text = wmalloc(strlen(string) + 8);
353 strcpy(text, string);
354 if (w <= width)
355 return text;
357 pos = strchr(text, ' ');
358 if (!pos)
359 pos = strchr(text, ':');
361 if (pos) {
362 *pos = 0;
363 p = strlen(text);
364 w1 = WMWidthOfString(font, text, p);
365 if (w1 > width) {
366 w1 = 0;
367 p = 0;
368 *pos = ' ';
369 *text = 0;
370 } else {
371 *pos = 0;
372 width -= w1;
373 p++;
375 string += p;
376 p = strlen(string);
377 } else {
378 *text = 0;
380 strcat(text, "...");
381 width -= WMWidthOfString(font, "...", 3);
382 pos = string;
383 p1 = 0;
384 p2 = p;
385 t = (p2 - p1) / 2;
386 while (p2 > p1 && p1 != t) {
387 w = WMWidthOfString(font, &string[p - t], t);
388 if (w > width) {
389 p2 = t;
390 t = p1 + (p2 - p1) / 2;
391 } else if (w < width) {
392 p1 = t;
393 t = p1 + (p2 - p1) / 2;
394 } else
395 p2 = p1 = t;
397 strcat(text, &string[p - p1]);
399 return text;
402 char *FindImage(char *paths, char *file)
404 char *tmp, *path = NULL;
406 tmp = strrchr(file, ':');
407 if (tmp) {
408 *tmp = 0;
409 path = wfindfile(paths, file);
410 *tmp = ':';
412 if (!tmp || !path) {
413 path = wfindfile(paths, file);
416 return path;
419 static void timeoutHandler(void *data)
421 *(int *)data = 1;
424 static char *getTextSelection(WScreen * screen, Atom selection)
426 int buffer = -1;
428 switch (selection) {
429 case XA_CUT_BUFFER0:
430 buffer = 0;
431 break;
432 case XA_CUT_BUFFER1:
433 buffer = 1;
434 break;
435 case XA_CUT_BUFFER2:
436 buffer = 2;
437 break;
438 case XA_CUT_BUFFER3:
439 buffer = 3;
440 break;
441 case XA_CUT_BUFFER4:
442 buffer = 4;
443 break;
444 case XA_CUT_BUFFER5:
445 buffer = 5;
446 break;
447 case XA_CUT_BUFFER6:
448 buffer = 6;
449 break;
450 case XA_CUT_BUFFER7:
451 buffer = 7;
452 break;
454 if (buffer >= 0) {
455 char *data;
456 int size;
458 data = XFetchBuffer(dpy, &size, buffer);
460 return data;
461 } else {
462 char *data;
463 int bits;
464 Atom rtype;
465 unsigned long len, bytes;
466 WMHandlerID timer;
467 int timeout = 0;
468 XEvent ev;
469 static Atom clipboard = 0;
471 if (!clipboard)
472 clipboard = XInternAtom(dpy, "CLIPBOARD", False);
474 XDeleteProperty(dpy, screen->info_window, clipboard);
476 XConvertSelection(dpy, selection, XA_STRING, clipboard, screen->info_window, CurrentTime);
478 timer = WMAddTimerHandler(1000, timeoutHandler, &timeout);
480 while (!XCheckTypedWindowEvent(dpy, screen->info_window, SelectionNotify, &ev) && !timeout) ;
482 if (!timeout) {
483 WMDeleteTimerHandler(timer);
484 } else {
485 wwarning("selection retrieval timed out");
486 return NULL;
489 /* nobody owns the selection or the current owner has
490 * nothing to do with what we need */
491 if (ev.xselection.property == None) {
492 return NULL;
495 if (XGetWindowProperty(dpy, screen->info_window,
496 clipboard, 0, 1024,
497 False, XA_STRING, &rtype, &bits, &len,
498 &bytes, (unsigned char **)&data) != Success) {
499 return NULL;
501 if (rtype != XA_STRING || bits != 8) {
502 wwarning("invalid data in text selection");
503 if (data)
504 XFree(data);
505 return NULL;
507 return data;
511 static char *getselection(WScreen * scr)
513 char *tmp;
515 tmp = getTextSelection(scr, XA_PRIMARY);
516 if (!tmp)
517 tmp = getTextSelection(scr, XA_CUT_BUFFER0);
518 return tmp;
521 static char*
522 parseuserinputpart(char *line, int *ptr, char *endchars)
524 int depth = 0, begin;
525 char *value = NULL;
526 begin = ++*ptr;
528 while(line[*ptr] != '\0') {
529 if(line[*ptr] == '(') {
530 ++depth;
531 } else if(depth > 0 && line[*ptr] == ')') {
532 --depth;
533 } else if(depth == 0 && strchr(endchars, line[*ptr]) != NULL) {
534 value = wmalloc(*ptr - begin + 1);
535 strncpy(value, line + begin, *ptr - begin);
536 value[*ptr - begin] = '\0';
537 break;
539 ++*ptr;
542 return value;
545 static char*
546 getuserinput(WScreen *scr, char *line, int *ptr, Bool advanced)
548 char *ret = NULL, *title = NULL, *prompt = NULL, *name = NULL;
549 int rv;
551 if(line[*ptr] == '(')
552 title = parseuserinputpart(line, ptr, ",)");
553 if(title != NULL && line[*ptr] == ',')
554 prompt = parseuserinputpart(line, ptr, ",)");
555 if(prompt != NULL && line[*ptr] == ',')
556 name = parseuserinputpart(line, ptr, ")");
558 if(advanced)
559 rv = wAdvancedInputDialog(scr,
560 title ? _(title):_("Program Arguments"),
561 prompt ? _(prompt):_("Enter command arguments:"),
562 name, &ret);
563 else
564 rv = wInputDialog(scr,
565 title ? _(title):_("Program Arguments"),
566 prompt ? _(prompt):_("Enter command arguments:"),
567 &ret);
569 if(title) wfree(title);
570 if(prompt) wfree(prompt);
571 if(name) wfree(name);
573 return rv ? ret : NULL;
576 #define S_NORMAL 0
577 #define S_ESCAPE 1
578 #define S_OPTION 2
581 * state input new-state output
582 * NORMAL % OPTION <nil>
583 * NORMAL \ ESCAPE <nil>
584 * NORMAL etc. NORMAL <input>
585 * ESCAPE any NORMAL <input>
586 * OPTION s NORMAL <selection buffer>
587 * OPTION w NORMAL <selected window id>
588 * OPTION a NORMAL <input text>
589 * OPTION d NORMAL <OffiX DND selection object>
590 * OPTION W NORMAL <current workspace>
591 * OPTION etc. NORMAL %<input>
593 #define TMPBUFSIZE 64
594 char *ExpandOptions(WScreen * scr, char *cmdline)
596 int ptr, optr, state, len, olen;
597 char *out, *nout;
598 char *selection = NULL;
599 char *user_input = NULL;
600 #ifdef XDND
601 char *dropped_thing = NULL;
602 #endif
603 char tmpbuf[TMPBUFSIZE];
604 int slen;
606 len = strlen(cmdline);
607 olen = len + 1;
608 out = malloc(olen);
609 if (!out) {
610 wwarning(_("out of memory during expansion of \"%s\""), cmdline);
611 return NULL;
613 *out = 0;
614 ptr = 0; /* input line pointer */
615 optr = 0; /* output line pointer */
616 state = S_NORMAL;
617 while (ptr < len) {
618 switch (state) {
619 case S_NORMAL:
620 switch (cmdline[ptr]) {
621 case '\\':
622 state = S_ESCAPE;
623 break;
624 case '%':
625 state = S_OPTION;
626 break;
627 default:
628 state = S_NORMAL;
629 out[optr++] = cmdline[ptr];
630 break;
632 break;
633 case S_ESCAPE:
634 switch (cmdline[ptr]) {
635 case 'n':
636 out[optr++] = 10;
637 break;
639 case 'r':
640 out[optr++] = 13;
641 break;
643 case 't':
644 out[optr++] = 9;
645 break;
647 default:
648 out[optr++] = cmdline[ptr];
650 state = S_NORMAL;
651 break;
652 case S_OPTION:
653 state = S_NORMAL;
654 switch (cmdline[ptr]) {
655 case 'w':
656 if (scr->focused_window && scr->focused_window->flags.focused) {
657 snprintf(tmpbuf, sizeof(tmpbuf), "0x%x",
658 (unsigned int)scr->focused_window->client_win);
659 slen = strlen(tmpbuf);
660 olen += slen;
661 nout = realloc(out, olen);
662 if (!nout) {
663 wwarning(_("out of memory during expansion of \"%%w\""));
664 goto error;
666 out = nout;
667 strcat(out, tmpbuf);
668 optr += slen;
669 } else {
670 out[optr++] = ' ';
672 break;
674 case 'W':
675 snprintf(tmpbuf, sizeof(tmpbuf), "0x%x", (unsigned int)scr->current_workspace + 1);
676 slen = strlen(tmpbuf);
677 olen += slen;
678 nout = realloc(out, olen);
679 if (!nout) {
680 wwarning(_("out of memory during expansion of \"%%W\""));
681 goto error;
683 out = nout;
684 strcat(out, tmpbuf);
685 optr += slen;
686 break;
688 case 'a':
689 case 'A':
690 ptr++;
691 user_input = getuserinput(scr, cmdline, &ptr, cmdline[ptr-1] == 'A');
692 if (user_input) {
693 slen = strlen(user_input);
694 olen += slen;
695 nout = realloc(out, olen);
696 if (!nout) {
697 wwarning(_("out of memory during expansion of \"%%a\""));
698 goto error;
700 out = nout;
701 strcat(out, user_input);
702 optr += slen;
703 } else {
704 /* Not an error, but user has Canceled the dialog box.
705 * This will make the command to not be performed. */
706 goto error;
708 break;
710 #ifdef XDND
711 case 'd':
712 if (scr->xdestring) {
713 dropped_thing = wstrdup(scr->xdestring);
715 if (!dropped_thing) {
716 dropped_thing = get_dnd_selection(scr);
718 if (!dropped_thing) {
719 scr->flags.dnd_data_convertion_status = 1;
720 goto error;
722 slen = strlen(dropped_thing);
723 olen += slen;
724 nout = realloc(out, olen);
725 if (!nout) {
726 wwarning(_("out of memory during expansion of \"%%d\""));
727 goto error;
729 out = nout;
730 strcat(out, dropped_thing);
731 optr += slen;
732 break;
733 #endif /* XDND */
735 case 's':
736 if (!selection) {
737 selection = getselection(scr);
739 if (!selection) {
740 wwarning(_("selection not available"));
741 goto error;
743 slen = strlen(selection);
744 olen += slen;
745 nout = realloc(out, olen);
746 if (!nout) {
747 wwarning(_("out of memory during expansion of \"%%s\""));
748 goto error;
750 out = nout;
751 strcat(out, selection);
752 optr += slen;
753 break;
755 default:
756 out[optr++] = '%';
757 out[optr++] = cmdline[ptr];
759 break;
761 out[optr] = 0;
762 ptr++;
764 if (selection)
765 XFree(selection);
766 return out;
768 error:
769 wfree(out);
770 if (selection)
771 XFree(selection);
772 return NULL;
775 void ParseWindowName(WMPropList * value, char **winstance, char **wclass, char *where)
777 char *name;
779 *winstance = *wclass = NULL;
781 if (!WMIsPLString(value)) {
782 wwarning(_("bad window name value in %s state info"), where);
783 return;
786 name = WMGetFromPLString(value);
787 if (!name || strlen(name) == 0) {
788 wwarning(_("bad window name value in %s state info"), where);
789 return;
792 UnescapeWM_CLASS(name, winstance, wclass);
795 #if 0
796 static char *keysymToString(KeySym keysym, unsigned int state)
798 XKeyEvent kev;
799 char *buf = wmalloc(20);
800 int count;
802 kev.display = dpy;
803 kev.type = KeyPress;
804 kev.send_event = False;
805 kev.window = DefaultRootWindow(dpy);
806 kev.root = DefaultRootWindow(dpy);
807 kev.same_screen = True;
808 kev.subwindow = kev.root;
809 kev.serial = 0x12344321;
810 kev.time = CurrentTime;
811 kev.state = state;
812 kev.keycode = XKeysymToKeycode(dpy, keysym);
813 count = XLookupString(&kev, buf, 19, NULL, NULL);
814 buf[count] = 0;
816 return buf;
818 #endif
820 char *GetShortcutString(char *text)
822 char *buffer = NULL;
823 char *k;
824 int modmask = 0;
825 /* KeySym ksym; */
826 int control = 0;
827 char *tmp;
829 tmp = text = wstrdup(text);
831 /* get modifiers */
832 while ((k = strchr(text, '+')) != NULL) {
833 int mod;
835 *k = 0;
836 mod = wXModifierFromKey(text);
837 if (mod < 0) {
838 return wstrdup("bug");
841 modmask |= mod;
843 if (strcasecmp(text, "Meta") == 0) {
844 buffer = wstrappend(buffer, "M+");
845 } else if (strcasecmp(text, "Alt") == 0) {
846 buffer = wstrappend(buffer, "A+");
847 } else if (strcasecmp(text, "Shift") == 0) {
848 buffer = wstrappend(buffer, "Sh+");
849 } else if (strcasecmp(text, "Mod1") == 0) {
850 buffer = wstrappend(buffer, "M1+");
851 } else if (strcasecmp(text, "Mod2") == 0) {
852 buffer = wstrappend(buffer, "M2+");
853 } else if (strcasecmp(text, "Mod3") == 0) {
854 buffer = wstrappend(buffer, "M3+");
855 } else if (strcasecmp(text, "Mod4") == 0) {
856 buffer = wstrappend(buffer, "M4+");
857 } else if (strcasecmp(text, "Mod5") == 0) {
858 buffer = wstrappend(buffer, "M5+");
859 } else if (strcasecmp(text, "Control") == 0) {
860 control = 1;
861 } else {
862 buffer = wstrappend(buffer, text);
864 text = k + 1;
867 if (control) {
868 buffer = wstrappend(buffer, "^");
870 buffer = wstrappend(buffer, text);
872 /* get key */
873 /* ksym = XStringToKeysym(text);
874 tmp = keysymToString(ksym, modmask);
875 puts(tmp);
876 buffer = wstrappend(buffer, tmp);
878 wfree(tmp);
880 return buffer;
883 char *EscapeWM_CLASS(char *name, char *class)
885 char *ret;
886 char *ename = NULL, *eclass = NULL;
887 int i, j, l;
889 if (!name && !class)
890 return NULL;
892 if (name) {
893 l = strlen(name);
894 ename = wmalloc(l * 2 + 1);
895 j = 0;
896 for (i = 0; i < l; i++) {
897 if (name[i] == '\\') {
898 ename[j++] = '\\';
899 } else if (name[i] == '.') {
900 ename[j++] = '\\';
902 ename[j++] = name[i];
904 ename[j] = 0;
906 if (class) {
907 l = strlen(class);
908 eclass = wmalloc(l * 2 + 1);
909 j = 0;
910 for (i = 0; i < l; i++) {
911 if (class[i] == '\\') {
912 eclass[j++] = '\\';
913 } else if (class[i] == '.') {
914 eclass[j++] = '\\';
916 eclass[j++] = class[i];
918 eclass[j] = 0;
921 if (ename && eclass) {
922 int len = strlen(ename) + strlen(eclass) + 4;
923 ret = wmalloc(len);
924 snprintf(ret, len, "%s.%s", ename, eclass);
925 wfree(ename);
926 wfree(eclass);
927 } else if (ename) {
928 ret = wstrdup(ename);
929 wfree(ename);
930 } else {
931 ret = wstrdup(eclass);
932 wfree(eclass);
935 return ret;
938 void UnescapeWM_CLASS(char *str, char **name, char **class)
940 int i, j, k, dot;
942 j = strlen(str);
943 *name = wmalloc(j);
944 **name = 0;
945 *class = wmalloc(j);
946 **class = 0;
948 /* separate string in 2 parts */
949 dot = -1;
950 for (i = 0; i < j; i++) {
951 if (str[i] == '\\') {
952 i++;
953 continue;
954 } else if (str[i] == '.') {
955 dot = i;
956 break;
960 /* unescape strings */
961 for (i = 0, k = 0; i < dot; i++) {
962 if (str[i] == '\\') {
963 continue;
964 } else {
965 (*name)[k++] = str[i];
968 (*name)[k] = 0;
970 for (i = dot + 1, k = 0; i < j; i++) {
971 if (str[i] == '\\') {
972 continue;
973 } else {
974 (*class)[k++] = str[i];
977 (*class)[k] = 0;
979 if (!*name) {
980 wfree(*name);
981 *name = NULL;
983 if (!*class) {
984 wfree(*class);
985 *class = NULL;
989 void SendHelperMessage(WScreen * scr, char type, int workspace, char *msg)
991 char *buffer;
992 int len;
993 int i;
994 char buf[16];
996 if (!scr->flags.backimage_helper_launched) {
997 return;
1000 len = (msg ? strlen(msg) : 0) + (workspace >= 0 ? 4 : 0) + 1;
1001 buffer = wmalloc(len + 5);
1002 snprintf(buf, sizeof(buf), "%4i", len);
1003 memcpy(buffer, buf, 4);
1004 buffer[4] = type;
1005 i = 5;
1006 if (workspace >= 0) {
1007 snprintf(buf, sizeof(buf), "%4i", workspace);
1008 memcpy(&buffer[i], buf, 4);
1009 i += 4;
1010 buffer[i] = 0;
1012 if (msg)
1013 strcpy(&buffer[i], msg);
1015 if (write(scr->helper_fd, buffer, len + 4) < 0) {
1016 wsyserror(_("could not send message to background image helper"));
1018 wfree(buffer);
1021 Bool UpdateDomainFile(WDDomain * domain)
1023 struct stat stbuf;
1024 char path[PATH_MAX];
1025 WMPropList *shared_dict, *dict;
1026 Bool result, freeDict = False;
1028 dict = domain->dictionary;
1029 if (WMIsPLDictionary(domain->dictionary)) {
1030 /* retrieve global system dictionary */
1031 snprintf(path, sizeof(path), "%s/WindowMaker/%s", SYSCONFDIR, domain->domain_name);
1032 if (stat(path, &stbuf) >= 0) {
1033 shared_dict = WMReadPropListFromFile(path);
1034 if (shared_dict) {
1035 if (WMIsPLDictionary(shared_dict)) {
1036 freeDict = True;
1037 dict = WMDeepCopyPropList(domain->dictionary);
1038 WMSubtractPLDictionaries(dict, shared_dict, True);
1040 WMReleasePropList(shared_dict);
1045 result = WMWritePropListToFile(dict, domain->path);
1047 if (freeDict) {
1048 WMReleasePropList(dict);
1051 return result;
1054 char *StrConcatDot(char *a, char *b)
1056 int len;
1057 char *str;
1059 if (!a)
1060 a = "";
1061 if (!b)
1062 b = "";
1064 len = strlen(a) + strlen(b) + 4;
1065 str = wmalloc(len);
1067 snprintf(str, len, "%s.%s", a, b);
1069 return str;
1072 static char *getCommandForWindow(Window win, int elements)
1074 char **argv, *command = NULL;
1075 int argc;
1077 if (XGetCommand(dpy, win, &argv, &argc)) {
1078 if (argc > 0 && argv != NULL) {
1079 if (elements == 0)
1080 elements = argc;
1081 command = wtokenjoin(argv, WMIN(argc, elements));
1082 if (command[0] == 0) {
1083 wfree(command);
1084 command = NULL;
1087 if (argv) {
1088 XFreeStringList(argv);
1092 return command;
1095 /* Free result when done */
1096 char *GetCommandForWindow(Window win)
1098 return getCommandForWindow(win, 0);
1101 /* Free result when done */
1102 char *GetProgramNameForWindow(Window win)
1104 return getCommandForWindow(win, 1);