Update local copy of GPLv2 and FSF address in copyrights
[wmaker-crm.git] / src / misc.c
blob05022975c0e08601d85bfe2ebb253291283387a7
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 along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "wconfig.h"
22 #include <X11/Xlib.h>
23 #include <X11/Xutil.h>
24 #include <X11/Xatom.h>
25 #include <sys/stat.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <stdarg.h>
31 #include <pwd.h>
32 #include <math.h>
33 #include <time.h>
35 #include <WINGs/WUtil.h>
36 #include <wraster.h>
38 #include "WindowMaker.h"
39 #include "GNUstep.h"
40 #include "screen.h"
41 #include "wcore.h"
42 #include "window.h"
43 #include "framewin.h"
44 #include "funcs.h"
45 #include "dialog.h"
46 #include "xutil.h"
47 #include "xmodifier.h"
49 /**** global variables *****/
50 extern WPreferences wPreferences;
52 #ifdef USECPP
53 static void putdef(char *line, char *name, char *value)
55 if (!value) {
56 wwarning(_("could not define value for %s for cpp"), name);
57 return;
59 strcat(line, name);
60 strcat(line, value);
63 static void putidef(char *line, char *name, int value)
65 char tmp[64];
66 snprintf(tmp, sizeof(tmp), "%i", value);
67 strcat(line, name);
68 strcat(line, tmp);
71 static char *username(void)
73 char *tmp;
75 tmp = getlogin();
76 if (!tmp) {
77 struct passwd *user;
79 user = getpwuid(getuid());
80 if (!user) {
81 werror(_("could not get password entry for UID %i"), getuid());
82 return NULL;
84 if (!user->pw_name) {
85 return NULL;
86 } else {
87 return user->pw_name;
90 return tmp;
93 char *MakeCPPArgs(char *path)
95 int i;
96 char buffer[MAXLINE], *buf, *line;
97 Visual *visual;
98 char *tmp;
100 line = wmalloc(MAXLINE);
101 *line = 0;
102 i = 1;
103 if ((buf = getenv("HOSTNAME")) != NULL) {
104 if (buf[0] == '(') {
105 wwarning(_("your machine is misconfigured. HOSTNAME is set to %s"), buf);
106 } else
107 putdef(line, " -DHOST=", buf);
108 } else if ((buf = getenv("HOST")) != NULL) {
109 if (buf[0] == '(') {
110 wwarning(_("your machine is misconfigured. HOST is set to %s"), buf);
111 } else
112 putdef(line, " -DHOST=", buf);
114 buf = username();
115 if (buf)
116 putdef(line, " -DUSER=", buf);
117 putidef(line, " -DUID=", getuid());
118 buf = XDisplayName(DisplayString(dpy));
119 putdef(line, " -DDISPLAY=", buf);
120 putdef(line, " -DWM_VERSION=", VERSION);
122 visual = DefaultVisual(dpy, DefaultScreen(dpy));
123 putidef(line, " -DVISUAL=", visual->class);
125 putidef(line, " -DDEPTH=", DefaultDepth(dpy, DefaultScreen(dpy)));
127 putidef(line, " -DSCR_WIDTH=", WidthOfScreen(DefaultScreenOfDisplay(dpy)));
128 putidef(line, " -DSCR_HEIGHT=", HeightOfScreen(DefaultScreenOfDisplay(dpy)));
130 /* put the dir where the menu is being read from to the
131 * search path */
132 if (path) {
133 tmp = wstrdup(path);
134 buf = strchr(tmp + 1, ' ');
135 if (buf) {
136 *buf = 0;
138 buf = strrchr(tmp, '/');
139 if (buf) {
140 *buf = 0; /* trunc filename */
141 putdef(line, " -I", tmp);
143 wfree(tmp);
146 /* this should be done just once, but it works this way */
147 strcpy(buffer, DEF_CONFIG_PATHS);
148 buf = strtok(buffer, ":");
150 do {
151 char fullpath[MAXLINE];
153 if (buf[0] != '~') {
154 strcpy(fullpath, buf);
155 } else {
156 /* home is statically allocated. Don't free it! */
157 char *home = wgethomedir();
159 strcpy(fullpath, home);
160 strcat(fullpath, &(buf[1]));
163 putdef(line, " -I", fullpath);
165 } while ((buf = strtok(NULL, ":")) != NULL);
167 #undef arg
168 return line;
170 #endif /* USECPP */
172 /* XFetchName Wrapper */
173 Bool wFetchName(Display *dpy, Window win, char **winname)
175 XTextProperty text_prop;
176 char **list;
177 int num;
179 if (XGetWMName(dpy, win, &text_prop)) {
180 if (text_prop.value && text_prop.nitems > 0) {
181 if (text_prop.encoding == XA_STRING) {
182 *winname = wstrdup((char *)text_prop.value);
183 XFree(text_prop.value);
184 } else {
185 text_prop.nitems = strlen((char *)text_prop.value);
186 if (XmbTextPropertyToTextList(dpy, &text_prop, &list, &num) >=
187 Success && num > 0 && *list) {
188 XFree(text_prop.value);
189 *winname = wstrdup(*list);
190 XFreeStringList(list);
191 } else {
192 *winname = wstrdup((char *)text_prop.value);
193 XFree(text_prop.value);
196 } else {
197 /* the title is set, but it was set to none */
198 *winname = wstrdup("");
200 return True;
201 } else {
202 /* the hint is probably not set */
203 *winname = NULL;
205 return False;
209 /* XGetIconName Wrapper */
210 Bool wGetIconName(Display *dpy, Window win, char **iconname)
212 XTextProperty text_prop;
213 char **list;
214 int num;
216 if (XGetWMIconName(dpy, win, &text_prop) != 0 && text_prop.value && text_prop.nitems > 0) {
217 if (text_prop.encoding == XA_STRING)
218 *iconname = (char *)text_prop.value;
219 else {
220 text_prop.nitems = strlen((char *)text_prop.value);
221 if (XmbTextPropertyToTextList(dpy, &text_prop, &list, &num) >= Success && num > 0 && *list) {
222 XFree(text_prop.value);
223 *iconname = wstrdup(*list);
224 XFreeStringList(list);
225 } else
226 *iconname = (char *)text_prop.value;
228 return True;
230 *iconname = NULL;
231 return False;
234 static void eatExpose(void)
236 XEvent event, foo;
238 /* compress all expose events into a single one */
240 if (XCheckMaskEvent(dpy, ExposureMask, &event)) {
241 /* ignore other exposure events for this window */
242 while (XCheckWindowEvent(dpy, event.xexpose.window, ExposureMask, &foo)) ;
243 /* eat exposes for other windows */
244 eatExpose();
246 event.xexpose.count = 0;
247 XPutBackEvent(dpy, &event);
251 void SlideWindow(Window win, int from_x, int from_y, int to_x, int to_y)
253 time_t time0 = time(NULL);
254 float dx, dy, x = from_x, y = from_y, sx, sy, px, py;
255 int dx_is_bigger = 0;
256 int slide_delay, slide_steps, slide_slowdown;
258 /* animation parameters */
259 static struct {
260 int delay;
261 int steps;
262 int slowdown;
263 } apars[5] = {
264 {ICON_SLIDE_DELAY_UF, ICON_SLIDE_STEPS_UF, ICON_SLIDE_SLOWDOWN_UF},
265 {ICON_SLIDE_DELAY_F, ICON_SLIDE_STEPS_F, ICON_SLIDE_SLOWDOWN_F},
266 {ICON_SLIDE_DELAY_M, ICON_SLIDE_STEPS_M, ICON_SLIDE_SLOWDOWN_M},
267 {ICON_SLIDE_DELAY_S, ICON_SLIDE_STEPS_S, ICON_SLIDE_SLOWDOWN_S},
268 {ICON_SLIDE_DELAY_US, ICON_SLIDE_STEPS_US, ICON_SLIDE_SLOWDOWN_US}
271 slide_slowdown = apars[(int)wPreferences.icon_slide_speed].slowdown;
272 slide_steps = apars[(int)wPreferences.icon_slide_speed].steps;
273 slide_delay = apars[(int)wPreferences.icon_slide_speed].delay;
275 dx = (float)(to_x - from_x);
276 dy = (float)(to_y - from_y);
277 sx = (dx == 0 ? 0 : fabs(dx) / dx);
278 sy = (dy == 0 ? 0 : fabs(dy) / dy);
280 if (fabs(dx) > fabs(dy)) {
281 dx_is_bigger = 1;
284 if (dx_is_bigger) {
285 px = dx / slide_slowdown;
286 if (px < slide_steps && px > 0)
287 px = slide_steps;
288 else if (px > -slide_steps && px < 0)
289 px = -slide_steps;
290 py = (sx == 0 ? 0 : px * dy / dx);
291 } else {
292 py = dy / slide_slowdown;
293 if (py < slide_steps && py > 0)
294 py = slide_steps;
295 else if (py > -slide_steps && py < 0)
296 py = -slide_steps;
297 px = (sy == 0 ? 0 : py * dx / dy);
300 while (x != to_x || y != to_y) {
301 x += px;
302 y += py;
303 if ((px < 0 && (int)x < to_x) || (px > 0 && (int)x > to_x))
304 x = (float)to_x;
305 if ((py < 0 && (int)y < to_y) || (py > 0 && (int)y > to_y))
306 y = (float)to_y;
308 if (dx_is_bigger) {
309 px = px * (1.0 - 1 / (float)slide_slowdown);
310 if (px < slide_steps && px > 0)
311 px = slide_steps;
312 else if (px > -slide_steps && px < 0)
313 px = -slide_steps;
314 py = (sx == 0 ? 0 : px * dy / dx);
315 } else {
316 py = py * (1.0 - 1 / (float)slide_slowdown);
317 if (py < slide_steps && py > 0)
318 py = slide_steps;
319 else if (py > -slide_steps && py < 0)
320 py = -slide_steps;
321 px = (sy == 0 ? 0 : py * dx / dy);
324 XMoveWindow(dpy, win, (int)x, (int)y);
325 XFlush(dpy);
326 if (slide_delay > 0) {
327 wusleep(slide_delay * 1000L);
328 } else {
329 wusleep(10);
331 if (time(NULL) - time0 > MAX_ANIMATION_TIME)
332 break;
334 XMoveWindow(dpy, win, to_x, to_y);
336 XSync(dpy, 0);
337 /* compress expose events */
338 eatExpose();
341 char *ShrinkString(WMFont * font, char *string, int width)
343 int w, w1 = 0;
344 int p;
345 char *pos;
346 char *text;
347 int p1, p2, t;
349 p = strlen(string);
350 w = WMWidthOfString(font, string, p);
351 text = wmalloc(strlen(string) + 8);
352 strcpy(text, string);
353 if (w <= width)
354 return text;
356 pos = strchr(text, ' ');
357 if (!pos)
358 pos = strchr(text, ':');
360 if (pos) {
361 *pos = 0;
362 p = strlen(text);
363 w1 = WMWidthOfString(font, text, p);
364 if (w1 > width) {
365 w1 = 0;
366 p = 0;
367 *pos = ' ';
368 *text = 0;
369 } else {
370 *pos = 0;
371 width -= w1;
372 p++;
374 string += p;
375 p = strlen(string);
376 } else {
377 *text = 0;
379 strcat(text, "...");
380 width -= WMWidthOfString(font, "...", 3);
381 pos = string;
382 p1 = 0;
383 p2 = p;
384 t = (p2 - p1) / 2;
385 while (p2 > p1 && p1 != t) {
386 w = WMWidthOfString(font, &string[p - t], t);
387 if (w > width) {
388 p2 = t;
389 t = p1 + (p2 - p1) / 2;
390 } else if (w < width) {
391 p1 = t;
392 t = p1 + (p2 - p1) / 2;
393 } else
394 p2 = p1 = t;
396 strcat(text, &string[p - p1]);
398 return text;
401 char *FindImage(char *paths, char *file)
403 char *tmp, *path = NULL;
405 tmp = strrchr(file, ':');
406 if (tmp) {
407 *tmp = 0;
408 path = wfindfile(paths, file);
409 *tmp = ':';
411 if (!tmp || !path) {
412 path = wfindfile(paths, file);
415 return path;
418 static void timeoutHandler(void *data)
420 *(int *)data = 1;
423 static char *getTextSelection(WScreen * screen, Atom selection)
425 int buffer = -1;
427 switch (selection) {
428 case XA_CUT_BUFFER0:
429 buffer = 0;
430 break;
431 case XA_CUT_BUFFER1:
432 buffer = 1;
433 break;
434 case XA_CUT_BUFFER2:
435 buffer = 2;
436 break;
437 case XA_CUT_BUFFER3:
438 buffer = 3;
439 break;
440 case XA_CUT_BUFFER4:
441 buffer = 4;
442 break;
443 case XA_CUT_BUFFER5:
444 buffer = 5;
445 break;
446 case XA_CUT_BUFFER6:
447 buffer = 6;
448 break;
449 case XA_CUT_BUFFER7:
450 buffer = 7;
451 break;
453 if (buffer >= 0) {
454 char *data;
455 int size;
457 data = XFetchBuffer(dpy, &size, buffer);
459 return data;
460 } else {
461 char *data;
462 int bits;
463 Atom rtype;
464 unsigned long len, bytes;
465 WMHandlerID timer;
466 int timeout = 0;
467 XEvent ev;
468 static Atom clipboard = 0;
470 if (!clipboard)
471 clipboard = XInternAtom(dpy, "CLIPBOARD", False);
473 XDeleteProperty(dpy, screen->info_window, clipboard);
475 XConvertSelection(dpy, selection, XA_STRING, clipboard, screen->info_window, CurrentTime);
477 timer = WMAddTimerHandler(1000, timeoutHandler, &timeout);
479 while (!XCheckTypedWindowEvent(dpy, screen->info_window, SelectionNotify, &ev) && !timeout) ;
481 if (!timeout) {
482 WMDeleteTimerHandler(timer);
483 } else {
484 wwarning("selection retrieval timed out");
485 return NULL;
488 /* nobody owns the selection or the current owner has
489 * nothing to do with what we need */
490 if (ev.xselection.property == None) {
491 return NULL;
494 if (XGetWindowProperty(dpy, screen->info_window,
495 clipboard, 0, 1024,
496 False, XA_STRING, &rtype, &bits, &len,
497 &bytes, (unsigned char **)&data) != Success) {
498 return NULL;
500 if (rtype != XA_STRING || bits != 8) {
501 wwarning("invalid data in text selection");
502 if (data)
503 XFree(data);
504 return NULL;
506 return data;
510 static char *getselection(WScreen * scr)
512 char *tmp;
514 tmp = getTextSelection(scr, XA_PRIMARY);
515 if (!tmp)
516 tmp = getTextSelection(scr, XA_CUT_BUFFER0);
517 return tmp;
520 static char*
521 parseuserinputpart(char *line, int *ptr, char *endchars)
523 int depth = 0, begin;
524 char *value = NULL;
525 begin = ++*ptr;
527 while(line[*ptr] != '\0') {
528 if(line[*ptr] == '(') {
529 ++depth;
530 } else if(depth > 0 && line[*ptr] == ')') {
531 --depth;
532 } else if(depth == 0 && strchr(endchars, line[*ptr]) != NULL) {
533 value = wmalloc(*ptr - begin + 1);
534 strncpy(value, line + begin, *ptr - begin);
535 value[*ptr - begin] = '\0';
536 break;
538 ++*ptr;
541 return value;
544 static char*
545 getuserinput(WScreen *scr, char *line, int *ptr, Bool advanced)
547 char *ret = NULL, *title = NULL, *prompt = NULL, *name = NULL;
548 int rv;
550 if(line[*ptr] == '(')
551 title = parseuserinputpart(line, ptr, ",)");
552 if(title != NULL && line[*ptr] == ',')
553 prompt = parseuserinputpart(line, ptr, ",)");
554 if(prompt != NULL && line[*ptr] == ',')
555 name = parseuserinputpart(line, ptr, ")");
557 if(advanced)
558 rv = wAdvancedInputDialog(scr,
559 title ? _(title):_("Program Arguments"),
560 prompt ? _(prompt):_("Enter command arguments:"),
561 name, &ret);
562 else
563 rv = wInputDialog(scr,
564 title ? _(title):_("Program Arguments"),
565 prompt ? _(prompt):_("Enter command arguments:"),
566 &ret);
568 if(title) wfree(title);
569 if(prompt) wfree(prompt);
570 if(name) wfree(name);
572 return rv ? ret : NULL;
575 #define S_NORMAL 0
576 #define S_ESCAPE 1
577 #define S_OPTION 2
580 * state input new-state output
581 * NORMAL % OPTION <nil>
582 * NORMAL \ ESCAPE <nil>
583 * NORMAL etc. NORMAL <input>
584 * ESCAPE any NORMAL <input>
585 * OPTION s NORMAL <selection buffer>
586 * OPTION w NORMAL <selected window id>
587 * OPTION a NORMAL <input text>
588 * OPTION d NORMAL <OffiX DND selection object>
589 * OPTION W NORMAL <current workspace>
590 * OPTION etc. NORMAL %<input>
592 #define TMPBUFSIZE 64
593 char *ExpandOptions(WScreen * scr, char *cmdline)
595 int ptr, optr, state, len, olen;
596 char *out, *nout;
597 char *selection = NULL;
598 char *user_input = NULL;
599 #ifdef XDND
600 char *dropped_thing = NULL;
601 #endif
602 char tmpbuf[TMPBUFSIZE];
603 int slen;
605 len = strlen(cmdline);
606 olen = len + 1;
607 out = malloc(olen);
608 if (!out) {
609 wwarning(_("out of memory during expansion of \"%s\""), cmdline);
610 return NULL;
612 *out = 0;
613 ptr = 0; /* input line pointer */
614 optr = 0; /* output line pointer */
615 state = S_NORMAL;
616 while (ptr < len) {
617 switch (state) {
618 case S_NORMAL:
619 switch (cmdline[ptr]) {
620 case '\\':
621 state = S_ESCAPE;
622 break;
623 case '%':
624 state = S_OPTION;
625 break;
626 default:
627 state = S_NORMAL;
628 out[optr++] = cmdline[ptr];
629 break;
631 break;
632 case S_ESCAPE:
633 switch (cmdline[ptr]) {
634 case 'n':
635 out[optr++] = 10;
636 break;
638 case 'r':
639 out[optr++] = 13;
640 break;
642 case 't':
643 out[optr++] = 9;
644 break;
646 default:
647 out[optr++] = cmdline[ptr];
649 state = S_NORMAL;
650 break;
651 case S_OPTION:
652 state = S_NORMAL;
653 switch (cmdline[ptr]) {
654 case 'w':
655 if (scr->focused_window && scr->focused_window->flags.focused) {
656 snprintf(tmpbuf, sizeof(tmpbuf), "0x%x",
657 (unsigned int)scr->focused_window->client_win);
658 slen = strlen(tmpbuf);
659 olen += slen;
660 nout = realloc(out, olen);
661 if (!nout) {
662 wwarning(_("out of memory during expansion of \"%%w\""));
663 goto error;
665 out = nout;
666 strcat(out, tmpbuf);
667 optr += slen;
668 } else {
669 out[optr++] = ' ';
671 break;
673 case 'W':
674 snprintf(tmpbuf, sizeof(tmpbuf), "0x%x", (unsigned int)scr->current_workspace + 1);
675 slen = strlen(tmpbuf);
676 olen += slen;
677 nout = realloc(out, olen);
678 if (!nout) {
679 wwarning(_("out of memory during expansion of \"%%W\""));
680 goto error;
682 out = nout;
683 strcat(out, tmpbuf);
684 optr += slen;
685 break;
687 case 'a':
688 case 'A':
689 ptr++;
690 user_input = getuserinput(scr, cmdline, &ptr, cmdline[ptr-1] == 'A');
691 if (user_input) {
692 slen = strlen(user_input);
693 olen += slen;
694 nout = realloc(out, olen);
695 if (!nout) {
696 wwarning(_("out of memory during expansion of \"%%a\""));
697 goto error;
699 out = nout;
700 strcat(out, user_input);
701 optr += slen;
702 } else {
703 /* Not an error, but user has Canceled the dialog box.
704 * This will make the command to not be performed. */
705 goto error;
707 break;
709 #ifdef XDND
710 case 'd':
711 if (scr->xdestring) {
712 dropped_thing = wstrdup(scr->xdestring);
714 if (!dropped_thing) {
715 dropped_thing = get_dnd_selection(scr);
717 if (!dropped_thing) {
718 scr->flags.dnd_data_convertion_status = 1;
719 goto error;
721 slen = strlen(dropped_thing);
722 olen += slen;
723 nout = realloc(out, olen);
724 if (!nout) {
725 wwarning(_("out of memory during expansion of \"%%d\""));
726 goto error;
728 out = nout;
729 strcat(out, dropped_thing);
730 optr += slen;
731 break;
732 #endif /* XDND */
734 case 's':
735 if (!selection) {
736 selection = getselection(scr);
738 if (!selection) {
739 wwarning(_("selection not available"));
740 goto error;
742 slen = strlen(selection);
743 olen += slen;
744 nout = realloc(out, olen);
745 if (!nout) {
746 wwarning(_("out of memory during expansion of \"%%s\""));
747 goto error;
749 out = nout;
750 strcat(out, selection);
751 optr += slen;
752 break;
754 default:
755 out[optr++] = '%';
756 out[optr++] = cmdline[ptr];
758 break;
760 out[optr] = 0;
761 ptr++;
763 if (selection)
764 XFree(selection);
765 return out;
767 error:
768 wfree(out);
769 if (selection)
770 XFree(selection);
771 return NULL;
774 void ParseWindowName(WMPropList * value, char **winstance, char **wclass, char *where)
776 char *name;
778 *winstance = *wclass = NULL;
780 if (!WMIsPLString(value)) {
781 wwarning(_("bad window name value in %s state info"), where);
782 return;
785 name = WMGetFromPLString(value);
786 if (!name || strlen(name) == 0) {
787 wwarning(_("bad window name value in %s state info"), where);
788 return;
791 UnescapeWM_CLASS(name, winstance, wclass);
794 #if 0
795 static char *keysymToString(KeySym keysym, unsigned int state)
797 XKeyEvent kev;
798 char *buf = wmalloc(20);
799 int count;
801 kev.display = dpy;
802 kev.type = KeyPress;
803 kev.send_event = False;
804 kev.window = DefaultRootWindow(dpy);
805 kev.root = DefaultRootWindow(dpy);
806 kev.same_screen = True;
807 kev.subwindow = kev.root;
808 kev.serial = 0x12344321;
809 kev.time = CurrentTime;
810 kev.state = state;
811 kev.keycode = XKeysymToKeycode(dpy, keysym);
812 count = XLookupString(&kev, buf, 19, NULL, NULL);
813 buf[count] = 0;
815 return buf;
817 #endif
819 char *GetShortcutString(char *text)
821 char *buffer = NULL;
822 char *k;
823 int modmask = 0;
824 /* KeySym ksym; */
825 int control = 0;
826 char *tmp;
828 tmp = text = wstrdup(text);
830 /* get modifiers */
831 while ((k = strchr(text, '+')) != NULL) {
832 int mod;
834 *k = 0;
835 mod = wXModifierFromKey(text);
836 if (mod < 0) {
837 return wstrdup("bug");
840 modmask |= mod;
842 if (strcasecmp(text, "Meta") == 0) {
843 buffer = wstrappend(buffer, "M+");
844 } else if (strcasecmp(text, "Alt") == 0) {
845 buffer = wstrappend(buffer, "A+");
846 } else if (strcasecmp(text, "Shift") == 0) {
847 buffer = wstrappend(buffer, "Sh+");
848 } else if (strcasecmp(text, "Mod1") == 0) {
849 buffer = wstrappend(buffer, "M1+");
850 } else if (strcasecmp(text, "Mod2") == 0) {
851 buffer = wstrappend(buffer, "M2+");
852 } else if (strcasecmp(text, "Mod3") == 0) {
853 buffer = wstrappend(buffer, "M3+");
854 } else if (strcasecmp(text, "Mod4") == 0) {
855 buffer = wstrappend(buffer, "M4+");
856 } else if (strcasecmp(text, "Mod5") == 0) {
857 buffer = wstrappend(buffer, "M5+");
858 } else if (strcasecmp(text, "Control") == 0) {
859 control = 1;
860 } else {
861 buffer = wstrappend(buffer, text);
863 text = k + 1;
866 if (control) {
867 buffer = wstrappend(buffer, "^");
869 buffer = wstrappend(buffer, text);
871 /* get key */
872 /* ksym = XStringToKeysym(text);
873 tmp = keysymToString(ksym, modmask);
874 puts(tmp);
875 buffer = wstrappend(buffer, tmp);
877 wfree(tmp);
879 return buffer;
882 char *EscapeWM_CLASS(char *name, char *class)
884 char *ret;
885 char *ename = NULL, *eclass = NULL;
886 int i, j, l;
888 if (!name && !class)
889 return NULL;
891 if (name) {
892 l = strlen(name);
893 ename = wmalloc(l * 2 + 1);
894 j = 0;
895 for (i = 0; i < l; i++) {
896 if (name[i] == '\\') {
897 ename[j++] = '\\';
898 } else if (name[i] == '.') {
899 ename[j++] = '\\';
901 ename[j++] = name[i];
903 ename[j] = 0;
905 if (class) {
906 l = strlen(class);
907 eclass = wmalloc(l * 2 + 1);
908 j = 0;
909 for (i = 0; i < l; i++) {
910 if (class[i] == '\\') {
911 eclass[j++] = '\\';
912 } else if (class[i] == '.') {
913 eclass[j++] = '\\';
915 eclass[j++] = class[i];
917 eclass[j] = 0;
920 if (ename && eclass) {
921 int len = strlen(ename) + strlen(eclass) + 4;
922 ret = wmalloc(len);
923 snprintf(ret, len, "%s.%s", ename, eclass);
924 wfree(ename);
925 wfree(eclass);
926 } else if (ename) {
927 ret = wstrdup(ename);
928 wfree(ename);
929 } else {
930 ret = wstrdup(eclass);
931 wfree(eclass);
934 return ret;
937 void UnescapeWM_CLASS(char *str, char **name, char **class)
939 int i, j, k, dot;
941 j = strlen(str);
942 *name = wmalloc(j);
943 **name = 0;
944 *class = wmalloc(j);
945 **class = 0;
947 /* separate string in 2 parts */
948 dot = -1;
949 for (i = 0; i < j; i++) {
950 if (str[i] == '\\') {
951 i++;
952 continue;
953 } else if (str[i] == '.') {
954 dot = i;
955 break;
959 /* unescape strings */
960 for (i = 0, k = 0; i < dot; i++) {
961 if (str[i] == '\\') {
962 continue;
963 } else {
964 (*name)[k++] = str[i];
967 (*name)[k] = 0;
969 for (i = dot + 1, k = 0; i < j; i++) {
970 if (str[i] == '\\') {
971 continue;
972 } else {
973 (*class)[k++] = str[i];
976 (*class)[k] = 0;
978 if (!*name) {
979 wfree(*name);
980 *name = NULL;
982 if (!*class) {
983 wfree(*class);
984 *class = NULL;
988 void SendHelperMessage(WScreen * scr, char type, int workspace, char *msg)
990 char *buffer;
991 int len;
992 int i;
993 char buf[16];
995 if (!scr->flags.backimage_helper_launched) {
996 return;
999 len = (msg ? strlen(msg) : 0) + (workspace >= 0 ? 4 : 0) + 1;
1000 buffer = wmalloc(len + 5);
1001 snprintf(buf, sizeof(buf), "%4i", len);
1002 memcpy(buffer, buf, 4);
1003 buffer[4] = type;
1004 i = 5;
1005 if (workspace >= 0) {
1006 snprintf(buf, sizeof(buf), "%4i", workspace);
1007 memcpy(&buffer[i], buf, 4);
1008 i += 4;
1009 buffer[i] = 0;
1011 if (msg)
1012 strcpy(&buffer[i], msg);
1014 if (write(scr->helper_fd, buffer, len + 4) < 0) {
1015 werror(_("could not send message to background image helper"));
1017 wfree(buffer);
1020 Bool UpdateDomainFile(WDDomain * domain)
1022 struct stat stbuf;
1023 char path[PATH_MAX];
1024 WMPropList *shared_dict, *dict;
1025 Bool result, freeDict = False;
1027 dict = domain->dictionary;
1028 if (WMIsPLDictionary(domain->dictionary)) {
1029 /* retrieve global system dictionary */
1030 snprintf(path, sizeof(path), "%s/WindowMaker/%s", SYSCONFDIR, domain->domain_name);
1031 if (stat(path, &stbuf) >= 0) {
1032 shared_dict = WMReadPropListFromFile(path);
1033 if (shared_dict) {
1034 if (WMIsPLDictionary(shared_dict)) {
1035 freeDict = True;
1036 dict = WMDeepCopyPropList(domain->dictionary);
1037 WMSubtractPLDictionaries(dict, shared_dict, True);
1039 WMReleasePropList(shared_dict);
1044 result = WMWritePropListToFile(dict, domain->path);
1046 if (freeDict) {
1047 WMReleasePropList(dict);
1050 return result;
1053 char *StrConcatDot(char *a, char *b)
1055 int len;
1056 char *str;
1058 if (!a)
1059 a = "";
1060 if (!b)
1061 b = "";
1063 len = strlen(a) + strlen(b) + 4;
1064 str = wmalloc(len);
1066 snprintf(str, len, "%s.%s", a, b);
1068 return str;
1071 static char *getCommandForWindow(Window win, int elements)
1073 char **argv, *command = NULL;
1074 int argc;
1076 if (XGetCommand(dpy, win, &argv, &argc)) {
1077 if (argc > 0 && argv != NULL) {
1078 if (elements == 0)
1079 elements = argc;
1080 command = wtokenjoin(argv, WMIN(argc, elements));
1081 if (command[0] == 0) {
1082 wfree(command);
1083 command = NULL;
1086 if (argv) {
1087 XFreeStringList(argv);
1091 return command;
1094 /* Free result when done */
1095 char *GetCommandForWindow(Window win)
1097 return getCommandForWindow(win, 0);
1100 /* Free result when done */
1101 char *GetProgramNameForWindow(Window win)
1103 return getCommandForWindow(win, 1);