Get rid of cropline(), use wtrimspace() instead
[wmaker-crm.git] / src / misc.c
blob3381c2a0a0c728e381a0ff464bff935bd1fd7f2e
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 <strings.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 werror(_("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 char buffer[MAXLINE], *buf, *line;
97 Visual *visual;
98 char *tmp;
100 line = wmalloc(MAXLINE);
101 *line = 0;
102 if ((buf = getenv("HOSTNAME")) != NULL) {
103 if (buf[0] == '(') {
104 wwarning(_("your machine is misconfigured. HOSTNAME is set to %s"), buf);
105 } else
106 putdef(line, " -DHOST=", buf);
107 } else if ((buf = getenv("HOST")) != NULL) {
108 if (buf[0] == '(') {
109 wwarning(_("your machine is misconfigured. HOST is set to %s"), buf);
110 } else
111 putdef(line, " -DHOST=", buf);
113 buf = username();
114 if (buf)
115 putdef(line, " -DUSER=", buf);
116 putidef(line, " -DUID=", getuid());
117 buf = XDisplayName(DisplayString(dpy));
118 putdef(line, " -DDISPLAY=", buf);
119 putdef(line, " -DWM_VERSION=", VERSION);
121 visual = DefaultVisual(dpy, DefaultScreen(dpy));
122 putidef(line, " -DVISUAL=", visual->class);
124 putidef(line, " -DDEPTH=", DefaultDepth(dpy, DefaultScreen(dpy)));
126 putidef(line, " -DSCR_WIDTH=", WidthOfScreen(DefaultScreenOfDisplay(dpy)));
127 putidef(line, " -DSCR_HEIGHT=", HeightOfScreen(DefaultScreenOfDisplay(dpy)));
129 /* put the dir where the menu is being read from to the
130 * search path */
131 if (path) {
132 tmp = wstrdup(path);
133 buf = strchr(tmp + 1, ' ');
134 if (buf) {
135 *buf = 0;
137 buf = strrchr(tmp, '/');
138 if (buf) {
139 *buf = 0; /* trunc filename */
140 putdef(line, " -I", tmp);
142 wfree(tmp);
145 /* this should be done just once, but it works this way */
146 strcpy(buffer, DEF_CONFIG_PATHS);
147 buf = strtok(buffer, ":");
149 do {
150 char fullpath[MAXLINE];
152 if (buf[0] != '~') {
153 strcpy(fullpath, buf);
154 } else {
155 /* home is statically allocated. Don't free it! */
156 char *home = wgethomedir();
158 strcpy(fullpath, home);
159 strcat(fullpath, &(buf[1]));
162 putdef(line, " -I", fullpath);
164 } while ((buf = strtok(NULL, ":")) != NULL);
166 #undef arg
167 return line;
169 #endif /* USECPP */
171 /* XFetchName Wrapper */
172 Bool wFetchName(Display *dpy, Window win, char **winname)
174 XTextProperty text_prop;
175 char **list;
176 int num;
178 if (XGetWMName(dpy, win, &text_prop)) {
179 if (text_prop.value && text_prop.nitems > 0) {
180 if (text_prop.encoding == XA_STRING) {
181 *winname = wstrdup((char *)text_prop.value);
182 XFree(text_prop.value);
183 } else {
184 text_prop.nitems = strlen((char *)text_prop.value);
185 if (XmbTextPropertyToTextList(dpy, &text_prop, &list, &num) >=
186 Success && num > 0 && *list) {
187 XFree(text_prop.value);
188 *winname = wstrdup(*list);
189 XFreeStringList(list);
190 } else {
191 *winname = wstrdup((char *)text_prop.value);
192 XFree(text_prop.value);
195 } else {
196 /* the title is set, but it was set to none */
197 *winname = wstrdup("");
199 return True;
200 } else {
201 /* the hint is probably not set */
202 *winname = NULL;
204 return False;
208 /* XGetIconName Wrapper */
209 Bool wGetIconName(Display *dpy, Window win, char **iconname)
211 XTextProperty text_prop;
212 char **list;
213 int num;
215 if (XGetWMIconName(dpy, win, &text_prop) != 0 && text_prop.value && text_prop.nitems > 0) {
216 if (text_prop.encoding == XA_STRING)
217 *iconname = (char *)text_prop.value;
218 else {
219 text_prop.nitems = strlen((char *)text_prop.value);
220 if (XmbTextPropertyToTextList(dpy, &text_prop, &list, &num) >= Success && num > 0 && *list) {
221 XFree(text_prop.value);
222 *iconname = wstrdup(*list);
223 XFreeStringList(list);
224 } else
225 *iconname = (char *)text_prop.value;
227 return True;
229 *iconname = NULL;
230 return False;
233 static void eatExpose(void)
235 XEvent event, foo;
237 /* compress all expose events into a single one */
239 if (XCheckMaskEvent(dpy, ExposureMask, &event)) {
240 /* ignore other exposure events for this window */
241 while (XCheckWindowEvent(dpy, event.xexpose.window, ExposureMask, &foo)) ;
242 /* eat exposes for other windows */
243 eatExpose();
245 event.xexpose.count = 0;
246 XPutBackEvent(dpy, &event);
250 void SlideWindow(Window win, int from_x, int from_y, int to_x, int to_y)
252 time_t time0 = time(NULL);
253 float dx, dy, x = from_x, y = from_y, sx, sy, px, py;
254 int dx_is_bigger = 0;
255 int slide_delay, slide_steps, slide_slowdown;
257 /* animation parameters */
258 static struct {
259 int delay;
260 int steps;
261 int slowdown;
262 } apars[5] = {
263 {ICON_SLIDE_DELAY_UF, ICON_SLIDE_STEPS_UF, ICON_SLIDE_SLOWDOWN_UF},
264 {ICON_SLIDE_DELAY_F, ICON_SLIDE_STEPS_F, ICON_SLIDE_SLOWDOWN_F},
265 {ICON_SLIDE_DELAY_M, ICON_SLIDE_STEPS_M, ICON_SLIDE_SLOWDOWN_M},
266 {ICON_SLIDE_DELAY_S, ICON_SLIDE_STEPS_S, ICON_SLIDE_SLOWDOWN_S},
267 {ICON_SLIDE_DELAY_US, ICON_SLIDE_STEPS_US, ICON_SLIDE_SLOWDOWN_US}
270 slide_slowdown = apars[(int)wPreferences.icon_slide_speed].slowdown;
271 slide_steps = apars[(int)wPreferences.icon_slide_speed].steps;
272 slide_delay = apars[(int)wPreferences.icon_slide_speed].delay;
274 dx = (float)(to_x - from_x);
275 dy = (float)(to_y - from_y);
276 sx = (dx == 0 ? 0 : fabs(dx) / dx);
277 sy = (dy == 0 ? 0 : fabs(dy) / dy);
279 if (fabs(dx) > fabs(dy)) {
280 dx_is_bigger = 1;
283 if (dx_is_bigger) {
284 px = dx / slide_slowdown;
285 if (px < slide_steps && px > 0)
286 px = slide_steps;
287 else if (px > -slide_steps && px < 0)
288 px = -slide_steps;
289 py = (sx == 0 ? 0 : px * dy / dx);
290 } else {
291 py = dy / slide_slowdown;
292 if (py < slide_steps && py > 0)
293 py = slide_steps;
294 else if (py > -slide_steps && py < 0)
295 py = -slide_steps;
296 px = (sy == 0 ? 0 : py * dx / dy);
299 while (x != to_x || y != to_y) {
300 x += px;
301 y += py;
302 if ((px < 0 && (int)x < to_x) || (px > 0 && (int)x > to_x))
303 x = (float)to_x;
304 if ((py < 0 && (int)y < to_y) || (py > 0 && (int)y > to_y))
305 y = (float)to_y;
307 if (dx_is_bigger) {
308 px = px * (1.0 - 1 / (float)slide_slowdown);
309 if (px < slide_steps && px > 0)
310 px = slide_steps;
311 else if (px > -slide_steps && px < 0)
312 px = -slide_steps;
313 py = (sx == 0 ? 0 : px * dy / dx);
314 } else {
315 py = py * (1.0 - 1 / (float)slide_slowdown);
316 if (py < slide_steps && py > 0)
317 py = slide_steps;
318 else if (py > -slide_steps && py < 0)
319 py = -slide_steps;
320 px = (sy == 0 ? 0 : py * dx / dy);
323 XMoveWindow(dpy, win, (int)x, (int)y);
324 XFlush(dpy);
325 if (slide_delay > 0) {
326 wusleep(slide_delay * 1000L);
327 } else {
328 wusleep(10);
330 if (time(NULL) - time0 > MAX_ANIMATION_TIME)
331 break;
333 XMoveWindow(dpy, win, to_x, to_y);
335 XSync(dpy, 0);
336 /* compress expose events */
337 eatExpose();
340 char *ShrinkString(WMFont * font, char *string, int width)
342 int w, w1 = 0;
343 int p;
344 char *pos;
345 char *text;
346 int p1, p2, t;
348 p = strlen(string);
349 w = WMWidthOfString(font, string, p);
350 text = wmalloc(strlen(string) + 8);
351 strcpy(text, string);
352 if (w <= width)
353 return text;
355 pos = strchr(text, ' ');
356 if (!pos)
357 pos = strchr(text, ':');
359 if (pos) {
360 *pos = 0;
361 p = strlen(text);
362 w1 = WMWidthOfString(font, text, p);
363 if (w1 > width) {
364 w1 = 0;
365 p = 0;
366 *pos = ' ';
367 *text = 0;
368 } else {
369 *pos = 0;
370 width -= w1;
371 p++;
373 string += p;
374 p = strlen(string);
375 } else {
376 *text = 0;
378 strcat(text, "...");
379 width -= WMWidthOfString(font, "...", 3);
380 pos = string;
381 p1 = 0;
382 p2 = p;
383 t = (p2 - p1) / 2;
384 while (p2 > p1 && p1 != t) {
385 w = WMWidthOfString(font, &string[p - t], t);
386 if (w > width) {
387 p2 = t;
388 t = p1 + (p2 - p1) / 2;
389 } else if (w < width) {
390 p1 = t;
391 t = p1 + (p2 - p1) / 2;
392 } else
393 p2 = p1 = t;
395 strcat(text, &string[p - p1]);
397 return text;
400 char *FindImage(char *paths, char *file)
402 char *tmp, *path = NULL;
404 tmp = strrchr(file, ':');
405 if (tmp) {
406 *tmp = 0;
407 path = wfindfile(paths, file);
408 *tmp = ':';
410 if (!tmp || !path) {
411 path = wfindfile(paths, file);
414 return path;
417 static void timeoutHandler(void *data)
419 *(int *)data = 1;
422 static char *getTextSelection(WScreen * screen, Atom selection)
424 int buffer = -1;
426 switch (selection) {
427 case XA_CUT_BUFFER0:
428 buffer = 0;
429 break;
430 case XA_CUT_BUFFER1:
431 buffer = 1;
432 break;
433 case XA_CUT_BUFFER2:
434 buffer = 2;
435 break;
436 case XA_CUT_BUFFER3:
437 buffer = 3;
438 break;
439 case XA_CUT_BUFFER4:
440 buffer = 4;
441 break;
442 case XA_CUT_BUFFER5:
443 buffer = 5;
444 break;
445 case XA_CUT_BUFFER6:
446 buffer = 6;
447 break;
448 case XA_CUT_BUFFER7:
449 buffer = 7;
450 break;
452 if (buffer >= 0) {
453 char *data;
454 int size;
456 data = XFetchBuffer(dpy, &size, buffer);
458 return data;
459 } else {
460 char *data;
461 int bits;
462 Atom rtype;
463 unsigned long len, bytes;
464 WMHandlerID timer;
465 int timeout = 0;
466 XEvent ev;
467 static Atom clipboard = 0;
469 if (!clipboard)
470 clipboard = XInternAtom(dpy, "CLIPBOARD", False);
472 XDeleteProperty(dpy, screen->info_window, clipboard);
474 XConvertSelection(dpy, selection, XA_STRING, clipboard, screen->info_window, CurrentTime);
476 timer = WMAddTimerHandler(1000, timeoutHandler, &timeout);
478 while (!XCheckTypedWindowEvent(dpy, screen->info_window, SelectionNotify, &ev) && !timeout) ;
480 if (!timeout) {
481 WMDeleteTimerHandler(timer);
482 } else {
483 wwarning("selection retrieval timed out");
484 return NULL;
487 /* nobody owns the selection or the current owner has
488 * nothing to do with what we need */
489 if (ev.xselection.property == None) {
490 return NULL;
493 if (XGetWindowProperty(dpy, screen->info_window,
494 clipboard, 0, 1024,
495 False, XA_STRING, &rtype, &bits, &len,
496 &bytes, (unsigned char **)&data) != Success) {
497 return NULL;
499 if (rtype != XA_STRING || bits != 8) {
500 wwarning("invalid data in text selection");
501 if (data)
502 XFree(data);
503 return NULL;
505 return data;
509 static char *getselection(WScreen * scr)
511 char *tmp;
513 tmp = getTextSelection(scr, XA_PRIMARY);
514 if (!tmp)
515 tmp = getTextSelection(scr, XA_CUT_BUFFER0);
516 return tmp;
519 static char*
520 parseuserinputpart(char *line, int *ptr, char *endchars)
522 int depth = 0, begin;
523 char *value = NULL;
524 begin = ++*ptr;
526 while(line[*ptr] != '\0') {
527 if(line[*ptr] == '(') {
528 ++depth;
529 } else if(depth > 0 && line[*ptr] == ')') {
530 --depth;
531 } else if(depth == 0 && strchr(endchars, line[*ptr]) != NULL) {
532 value = wmalloc(*ptr - begin + 1);
533 strncpy(value, line + begin, *ptr - begin);
534 value[*ptr - begin] = '\0';
535 break;
537 ++*ptr;
540 return value;
543 static char*
544 getuserinput(WScreen *scr, char *line, int *ptr, Bool advanced)
546 char *ret = NULL, *title = NULL, *prompt = NULL, *name = NULL;
547 int rv;
549 if(line[*ptr] == '(')
550 title = parseuserinputpart(line, ptr, ",)");
551 if(title != NULL && line[*ptr] == ',')
552 prompt = parseuserinputpart(line, ptr, ",)");
553 if(prompt != NULL && line[*ptr] == ',')
554 name = parseuserinputpart(line, ptr, ")");
556 if(advanced)
557 rv = wAdvancedInputDialog(scr,
558 title ? _(title):_("Program Arguments"),
559 prompt ? _(prompt):_("Enter command arguments:"),
560 name, &ret);
561 else
562 rv = wInputDialog(scr,
563 title ? _(title):_("Program Arguments"),
564 prompt ? _(prompt):_("Enter command arguments:"),
565 &ret);
567 if(title) wfree(title);
568 if(prompt) wfree(prompt);
569 if(name) wfree(name);
571 return rv ? ret : NULL;
574 #define S_NORMAL 0
575 #define S_ESCAPE 1
576 #define S_OPTION 2
579 * state input new-state output
580 * NORMAL % OPTION <nil>
581 * NORMAL \ ESCAPE <nil>
582 * NORMAL etc. NORMAL <input>
583 * ESCAPE any NORMAL <input>
584 * OPTION s NORMAL <selection buffer>
585 * OPTION w NORMAL <selected window id>
586 * OPTION a NORMAL <input text>
587 * OPTION d NORMAL <OffiX DND selection object>
588 * OPTION W NORMAL <current workspace>
589 * OPTION etc. NORMAL %<input>
591 #define TMPBUFSIZE 64
592 char *ExpandOptions(WScreen * scr, char *cmdline)
594 int ptr, optr, state, len, olen;
595 char *out, *nout;
596 char *selection = NULL;
597 char *user_input = NULL;
598 #ifdef XDND
599 char *dropped_thing = NULL;
600 #endif
601 char tmpbuf[TMPBUFSIZE];
602 int slen;
604 len = strlen(cmdline);
605 olen = len + 1;
606 out = malloc(olen);
607 if (!out) {
608 wwarning(_("out of memory during expansion of \"%s\""), cmdline);
609 return NULL;
611 *out = 0;
612 ptr = 0; /* input line pointer */
613 optr = 0; /* output line pointer */
614 state = S_NORMAL;
615 while (ptr < len) {
616 switch (state) {
617 case S_NORMAL:
618 switch (cmdline[ptr]) {
619 case '\\':
620 state = S_ESCAPE;
621 break;
622 case '%':
623 state = S_OPTION;
624 break;
625 default:
626 state = S_NORMAL;
627 out[optr++] = cmdline[ptr];
628 break;
630 break;
631 case S_ESCAPE:
632 switch (cmdline[ptr]) {
633 case 'n':
634 out[optr++] = 10;
635 break;
637 case 'r':
638 out[optr++] = 13;
639 break;
641 case 't':
642 out[optr++] = 9;
643 break;
645 default:
646 out[optr++] = cmdline[ptr];
648 state = S_NORMAL;
649 break;
650 case S_OPTION:
651 state = S_NORMAL;
652 switch (cmdline[ptr]) {
653 case 'w':
654 if (scr->focused_window && scr->focused_window->flags.focused) {
655 snprintf(tmpbuf, sizeof(tmpbuf), "0x%x",
656 (unsigned int)scr->focused_window->client_win);
657 slen = strlen(tmpbuf);
658 olen += slen;
659 nout = realloc(out, olen);
660 if (!nout) {
661 wwarning(_("out of memory during expansion of \"%%w\""));
662 goto error;
664 out = nout;
665 strcat(out, tmpbuf);
666 optr += slen;
667 } else {
668 out[optr++] = ' ';
670 break;
672 case 'W':
673 snprintf(tmpbuf, sizeof(tmpbuf), "0x%x", (unsigned int)scr->current_workspace + 1);
674 slen = strlen(tmpbuf);
675 olen += slen;
676 nout = realloc(out, olen);
677 if (!nout) {
678 wwarning(_("out of memory during expansion of \"%%W\""));
679 goto error;
681 out = nout;
682 strcat(out, tmpbuf);
683 optr += slen;
684 break;
686 case 'a':
687 case 'A':
688 ptr++;
689 user_input = getuserinput(scr, cmdline, &ptr, cmdline[ptr-1] == 'A');
690 if (user_input) {
691 slen = strlen(user_input);
692 olen += slen;
693 nout = realloc(out, olen);
694 if (!nout) {
695 wwarning(_("out of memory during expansion of \"%%a\""));
696 goto error;
698 out = nout;
699 strcat(out, user_input);
700 optr += slen;
701 } else {
702 /* Not an error, but user has Canceled the dialog box.
703 * This will make the command to not be performed. */
704 goto error;
706 break;
708 #ifdef XDND
709 case 'd':
710 if (scr->xdestring) {
711 dropped_thing = wstrdup(scr->xdestring);
713 if (!dropped_thing) {
714 dropped_thing = get_dnd_selection(scr);
716 if (!dropped_thing) {
717 scr->flags.dnd_data_convertion_status = 1;
718 goto error;
720 slen = strlen(dropped_thing);
721 olen += slen;
722 nout = realloc(out, olen);
723 if (!nout) {
724 wwarning(_("out of memory during expansion of \"%%d\""));
725 goto error;
727 out = nout;
728 strcat(out, dropped_thing);
729 optr += slen;
730 break;
731 #endif /* XDND */
733 case 's':
734 if (!selection) {
735 selection = getselection(scr);
737 if (!selection) {
738 wwarning(_("selection not available"));
739 goto error;
741 slen = strlen(selection);
742 olen += slen;
743 nout = realloc(out, olen);
744 if (!nout) {
745 wwarning(_("out of memory during expansion of \"%%s\""));
746 goto error;
748 out = nout;
749 strcat(out, selection);
750 optr += slen;
751 break;
753 default:
754 out[optr++] = '%';
755 out[optr++] = cmdline[ptr];
757 break;
759 out[optr] = 0;
760 ptr++;
762 if (selection)
763 XFree(selection);
764 return out;
766 error:
767 wfree(out);
768 if (selection)
769 XFree(selection);
770 return NULL;
773 void ParseWindowName(WMPropList * value, char **winstance, char **wclass, char *where)
775 char *name;
777 *winstance = *wclass = NULL;
779 if (!WMIsPLString(value)) {
780 wwarning(_("bad window name value in %s state info"), where);
781 return;
784 name = WMGetFromPLString(value);
785 if (!name || strlen(name) == 0) {
786 wwarning(_("bad window name value in %s state info"), where);
787 return;
790 UnescapeWM_CLASS(name, winstance, wclass);
793 #if 0
794 static char *keysymToString(KeySym keysym, unsigned int state)
796 XKeyEvent kev;
797 char *buf = wmalloc(20);
798 int count;
800 kev.display = dpy;
801 kev.type = KeyPress;
802 kev.send_event = False;
803 kev.window = DefaultRootWindow(dpy);
804 kev.root = DefaultRootWindow(dpy);
805 kev.same_screen = True;
806 kev.subwindow = kev.root;
807 kev.serial = 0x12344321;
808 kev.time = CurrentTime;
809 kev.state = state;
810 kev.keycode = XKeysymToKeycode(dpy, keysym);
811 count = XLookupString(&kev, buf, 19, NULL, NULL);
812 buf[count] = 0;
814 return buf;
816 #endif
818 char *GetShortcutString(char *text)
820 char *buffer = NULL;
821 char *k;
822 int modmask = 0;
823 /* KeySym ksym; */
824 int control = 0;
825 char *tmp;
827 tmp = text = wstrdup(text);
829 /* get modifiers */
830 while ((k = strchr(text, '+')) != NULL) {
831 int mod;
833 *k = 0;
834 mod = wXModifierFromKey(text);
835 if (mod < 0) {
836 return wstrdup("bug");
839 modmask |= mod;
841 if (strcasecmp(text, "Meta") == 0) {
842 buffer = wstrappend(buffer, "M+");
843 } else if (strcasecmp(text, "Alt") == 0) {
844 buffer = wstrappend(buffer, "A+");
845 } else if (strcasecmp(text, "Shift") == 0) {
846 buffer = wstrappend(buffer, "Sh+");
847 } else if (strcasecmp(text, "Mod1") == 0) {
848 buffer = wstrappend(buffer, "M1+");
849 } else if (strcasecmp(text, "Mod2") == 0) {
850 buffer = wstrappend(buffer, "M2+");
851 } else if (strcasecmp(text, "Mod3") == 0) {
852 buffer = wstrappend(buffer, "M3+");
853 } else if (strcasecmp(text, "Mod4") == 0) {
854 buffer = wstrappend(buffer, "M4+");
855 } else if (strcasecmp(text, "Mod5") == 0) {
856 buffer = wstrappend(buffer, "M5+");
857 } else if (strcasecmp(text, "Control") == 0) {
858 control = 1;
859 } else {
860 buffer = wstrappend(buffer, text);
862 text = k + 1;
865 if (control) {
866 buffer = wstrappend(buffer, "^");
868 buffer = wstrappend(buffer, text);
870 /* get key */
871 /* ksym = XStringToKeysym(text);
872 tmp = keysymToString(ksym, modmask);
873 puts(tmp);
874 buffer = wstrappend(buffer, tmp);
876 wfree(tmp);
878 return buffer;
881 char *EscapeWM_CLASS(char *name, char *class)
883 char *ret;
884 char *ename = NULL, *eclass = NULL;
885 int i, j, l;
887 if (!name && !class)
888 return NULL;
890 if (name) {
891 l = strlen(name);
892 ename = wmalloc(l * 2 + 1);
893 j = 0;
894 for (i = 0; i < l; i++) {
895 if (name[i] == '\\') {
896 ename[j++] = '\\';
897 } else if (name[i] == '.') {
898 ename[j++] = '\\';
900 ename[j++] = name[i];
902 ename[j] = 0;
904 if (class) {
905 l = strlen(class);
906 eclass = wmalloc(l * 2 + 1);
907 j = 0;
908 for (i = 0; i < l; i++) {
909 if (class[i] == '\\') {
910 eclass[j++] = '\\';
911 } else if (class[i] == '.') {
912 eclass[j++] = '\\';
914 eclass[j++] = class[i];
916 eclass[j] = 0;
919 if (ename && eclass) {
920 int len = strlen(ename) + strlen(eclass) + 4;
921 ret = wmalloc(len);
922 snprintf(ret, len, "%s.%s", ename, eclass);
923 wfree(ename);
924 wfree(eclass);
925 } else if (ename) {
926 ret = wstrdup(ename);
927 wfree(ename);
928 } else {
929 ret = wstrdup(eclass);
930 wfree(eclass);
933 return ret;
936 void UnescapeWM_CLASS(char *str, char **name, char **class)
938 int i, j, k, dot;
940 j = strlen(str);
941 *name = wmalloc(j);
942 **name = 0;
943 *class = wmalloc(j);
944 **class = 0;
946 /* separate string in 2 parts */
947 dot = -1;
948 for (i = 0; i < j; i++) {
949 if (str[i] == '\\') {
950 i++;
951 continue;
952 } else if (str[i] == '.') {
953 dot = i;
954 break;
958 /* unescape strings */
959 for (i = 0, k = 0; i < dot; i++) {
960 if (str[i] == '\\') {
961 continue;
962 } else {
963 (*name)[k++] = str[i];
966 (*name)[k] = 0;
968 for (i = dot + 1, k = 0; i < j; i++) {
969 if (str[i] == '\\') {
970 continue;
971 } else {
972 (*class)[k++] = str[i];
975 (*class)[k] = 0;
977 if (!*name) {
978 wfree(*name);
979 *name = NULL;
981 if (!*class) {
982 wfree(*class);
983 *class = NULL;
987 void SendHelperMessage(WScreen * scr, char type, int workspace, char *msg)
989 char *buffer;
990 int len;
991 int i;
992 char buf[16];
994 if (!scr->flags.backimage_helper_launched) {
995 return;
998 len = (msg ? strlen(msg) : 0) + (workspace >= 0 ? 4 : 0) + 1;
999 buffer = wmalloc(len + 5);
1000 snprintf(buf, sizeof(buf), "%4i", len);
1001 memcpy(buffer, buf, 4);
1002 buffer[4] = type;
1003 i = 5;
1004 if (workspace >= 0) {
1005 snprintf(buf, sizeof(buf), "%4i", workspace);
1006 memcpy(&buffer[i], buf, 4);
1007 i += 4;
1008 buffer[i] = 0;
1010 if (msg)
1011 strcpy(&buffer[i], msg);
1013 if (write(scr->helper_fd, buffer, len + 4) < 0) {
1014 werror(_("could not send message to background image helper"));
1016 wfree(buffer);
1019 Bool UpdateDomainFile(WDDomain * domain)
1021 struct stat stbuf;
1022 char path[PATH_MAX];
1023 WMPropList *shared_dict, *dict;
1024 Bool result, freeDict = False;
1026 dict = domain->dictionary;
1027 if (WMIsPLDictionary(domain->dictionary)) {
1028 /* retrieve global system dictionary */
1029 snprintf(path, sizeof(path), "%s/WindowMaker/%s", SYSCONFDIR, domain->domain_name);
1030 if (stat(path, &stbuf) >= 0) {
1031 shared_dict = WMReadPropListFromFile(path);
1032 if (shared_dict) {
1033 if (WMIsPLDictionary(shared_dict)) {
1034 freeDict = True;
1035 dict = WMDeepCopyPropList(domain->dictionary);
1036 WMSubtractPLDictionaries(dict, shared_dict, True);
1038 WMReleasePropList(shared_dict);
1043 result = WMWritePropListToFile(dict, domain->path);
1045 if (freeDict) {
1046 WMReleasePropList(dict);
1049 return result;
1052 char *StrConcatDot(char *a, char *b)
1054 int len;
1055 char *str;
1057 if (!a)
1058 a = "";
1059 if (!b)
1060 b = "";
1062 len = strlen(a) + strlen(b) + 4;
1063 str = wmalloc(len);
1065 snprintf(str, len, "%s.%s", a, b);
1067 return str;
1070 static char *getCommandForWindow(Window win, int elements)
1072 char **argv, *command = NULL;
1073 int argc;
1075 if (XGetCommand(dpy, win, &argv, &argc)) {
1076 if (argc > 0 && argv != NULL) {
1077 if (elements == 0)
1078 elements = argc;
1079 command = wtokenjoin(argv, WMIN(argc, elements));
1080 if (command[0] == 0) {
1081 wfree(command);
1082 command = NULL;
1085 if (argv) {
1086 XFreeStringList(argv);
1090 return command;
1093 /* Free result when done */
1094 char *GetCommandForWindow(Window win)
1096 return getCommandForWindow(win, 0);
1099 /* Free result when done */
1100 char *GetProgramNameForWindow(Window win)
1102 return getCommandForWindow(win, 1);