Trivial format string fixes
[wmaker-crm.git] / src / misc.c
blob3e5a8cfcc12c1655b6fb4a6bfd6e3a321a5d9841
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>
35 #include <libintl.h>
37 #include <WINGs/WUtil.h>
38 #include <wraster.h>
40 #include "WindowMaker.h"
41 #include "GNUstep.h"
42 #include "screen.h"
43 #include "wcore.h"
44 #include "window.h"
45 #include "framewin.h"
46 #include "funcs.h"
47 #include "dialog.h"
48 #include "xutil.h"
49 #include "xmodifier.h"
51 /**** global variables *****/
53 extern WPreferences wPreferences;
55 extern Time LastTimestamp;
57 #ifdef USECPP
58 static void putdef(char *line, char *name, char *value)
60 if (!value) {
61 wwarning(_("could not define value for %s for cpp"), name);
62 return;
64 strcat(line, name);
65 strcat(line, value);
68 static void putidef(char *line, char *name, int value)
70 char tmp[64];
71 snprintf(tmp, sizeof(tmp), "%i", value);
72 strcat(line, name);
73 strcat(line, tmp);
76 static char *username()
78 char *tmp;
80 tmp = getlogin();
81 if (!tmp) {
82 struct passwd *user;
84 user = getpwuid(getuid());
85 if (!user) {
86 wsyserror(_("could not get password entry for UID %i"), getuid());
87 return NULL;
89 if (!user->pw_name) {
90 return NULL;
91 } else {
92 return user->pw_name;
95 return tmp;
98 char *MakeCPPArgs(char *path)
100 int i;
101 char buffer[MAXLINE], *buf, *line;
102 Visual *visual;
103 char *tmp;
105 line = wmalloc(MAXLINE);
106 *line = 0;
107 i = 1;
108 if ((buf = getenv("HOSTNAME")) != NULL) {
109 if (buf[0] == '(') {
110 wwarning(_("your machine is misconfigured. HOSTNAME is set to %s"), buf);
111 } else
112 putdef(line, " -DHOST=", buf);
113 } else if ((buf = getenv("HOST")) != NULL) {
114 if (buf[0] == '(') {
115 wwarning(_("your machine is misconfigured. HOST is set to %s"), buf);
116 } else
117 putdef(line, " -DHOST=", buf);
119 buf = username();
120 if (buf)
121 putdef(line, " -DUSER=", buf);
122 putidef(line, " -DUID=", getuid());
123 buf = XDisplayName(DisplayString(dpy));
124 putdef(line, " -DDISPLAY=", buf);
125 putdef(line, " -DWM_VERSION=", VERSION);
127 visual = DefaultVisual(dpy, DefaultScreen(dpy));
128 putidef(line, " -DVISUAL=", visual->class);
130 putidef(line, " -DDEPTH=", DefaultDepth(dpy, DefaultScreen(dpy)));
132 putidef(line, " -DSCR_WIDTH=", WidthOfScreen(DefaultScreenOfDisplay(dpy)));
133 putidef(line, " -DSCR_HEIGHT=", HeightOfScreen(DefaultScreenOfDisplay(dpy)));
135 /* put the dir where the menu is being read from to the
136 * search path */
137 if (path) {
138 tmp = wstrdup(path);
139 buf = strchr(tmp + 1, ' ');
140 if (buf) {
141 *buf = 0;
143 buf = strrchr(tmp, '/');
144 if (buf) {
145 *buf = 0; /* trunc filename */
146 putdef(line, " -I", tmp);
148 wfree(tmp);
151 /* this should be done just once, but it works this way */
152 strcpy(buffer, DEF_CONFIG_PATHS);
153 buf = strtok(buffer, ":");
155 do {
156 char fullpath[MAXLINE];
158 if (buf[0] != '~') {
159 strcpy(fullpath, buf);
160 } else {
161 /* home is statically allocated. Don't free it! */
162 char *home = wgethomedir();
164 strcpy(fullpath, home);
165 strcat(fullpath, &(buf[1]));
168 putdef(line, " -I", fullpath);
170 } while ((buf = strtok(NULL, ":")) != NULL);
172 #undef arg
173 return line;
175 #endif /* USECPP */
177 /* XFetchName Wrapper */
178 Bool wFetchName(Display *dpy, Window win, char **winname)
180 XTextProperty text_prop;
181 char **list;
182 int num;
184 if (XGetWMName(dpy, win, &text_prop)) {
185 if (text_prop.value && text_prop.nitems > 0) {
186 if (text_prop.encoding == XA_STRING) {
187 *winname = wstrdup((char *)text_prop.value);
188 XFree(text_prop.value);
189 } else {
190 text_prop.nitems = strlen((char *)text_prop.value);
191 if (XmbTextPropertyToTextList(dpy, &text_prop, &list, &num) >=
192 Success && num > 0 && *list) {
193 XFree(text_prop.value);
194 *winname = wstrdup(*list);
195 XFreeStringList(list);
196 } else {
197 *winname = wstrdup((char *)text_prop.value);
198 XFree(text_prop.value);
201 } else {
202 /* the title is set, but it was set to none */
203 *winname = wstrdup("");
205 return True;
206 } else {
207 /* the hint is probably not set */
208 *winname = NULL;
210 return False;
214 /* XGetIconName Wrapper */
215 Bool wGetIconName(Display *dpy, Window win, char **iconname)
217 XTextProperty text_prop;
218 char **list;
219 int num;
221 if (XGetWMIconName(dpy, win, &text_prop) != 0 && text_prop.value && text_prop.nitems > 0) {
222 if (text_prop.encoding == XA_STRING)
223 *iconname = (char *)text_prop.value;
224 else {
225 text_prop.nitems = strlen((char *)text_prop.value);
226 if (XmbTextPropertyToTextList(dpy, &text_prop, &list, &num) >= Success && num > 0 && *list) {
227 XFree(text_prop.value);
228 *iconname = wstrdup(*list);
229 XFreeStringList(list);
230 } else
231 *iconname = (char *)text_prop.value;
233 return True;
235 *iconname = NULL;
236 return False;
239 static void eatExpose()
241 XEvent event, foo;
243 /* compress all expose events into a single one */
245 if (XCheckMaskEvent(dpy, ExposureMask, &event)) {
246 /* ignore other exposure events for this window */
247 while (XCheckWindowEvent(dpy, event.xexpose.window, ExposureMask, &foo)) ;
248 /* eat exposes for other windows */
249 eatExpose();
251 event.xexpose.count = 0;
252 XPutBackEvent(dpy, &event);
256 void SlideWindow(Window win, int from_x, int from_y, int to_x, int to_y)
258 time_t time0 = time(NULL);
259 float dx, dy, x = from_x, y = from_y, sx, sy, px, py;
260 int dx_is_bigger = 0;
261 int slide_delay, slide_steps, slide_slowdown;
263 /* animation parameters */
264 static struct {
265 int delay;
266 int steps;
267 int slowdown;
268 } apars[5] = {
269 {ICON_SLIDE_DELAY_UF, ICON_SLIDE_STEPS_UF, ICON_SLIDE_SLOWDOWN_UF},
270 {ICON_SLIDE_DELAY_F, ICON_SLIDE_STEPS_F, ICON_SLIDE_SLOWDOWN_F},
271 {ICON_SLIDE_DELAY_M, ICON_SLIDE_STEPS_M, ICON_SLIDE_SLOWDOWN_M},
272 {ICON_SLIDE_DELAY_S, ICON_SLIDE_STEPS_S, ICON_SLIDE_SLOWDOWN_S},
273 {ICON_SLIDE_DELAY_US, ICON_SLIDE_STEPS_US, ICON_SLIDE_SLOWDOWN_US}
276 slide_slowdown = apars[(int)wPreferences.icon_slide_speed].slowdown;
277 slide_steps = apars[(int)wPreferences.icon_slide_speed].steps;
278 slide_delay = apars[(int)wPreferences.icon_slide_speed].delay;
280 dx = (float)(to_x - from_x);
281 dy = (float)(to_y - from_y);
282 sx = (dx == 0 ? 0 : fabs(dx) / dx);
283 sy = (dy == 0 ? 0 : fabs(dy) / dy);
285 if (fabs(dx) > fabs(dy)) {
286 dx_is_bigger = 1;
289 if (dx_is_bigger) {
290 px = dx / slide_slowdown;
291 if (px < slide_steps && px > 0)
292 px = slide_steps;
293 else if (px > -slide_steps && px < 0)
294 px = -slide_steps;
295 py = (sx == 0 ? 0 : px * dy / dx);
296 } else {
297 py = dy / slide_slowdown;
298 if (py < slide_steps && py > 0)
299 py = slide_steps;
300 else if (py > -slide_steps && py < 0)
301 py = -slide_steps;
302 px = (sy == 0 ? 0 : py * dx / dy);
305 while (x != to_x || y != to_y) {
306 x += px;
307 y += py;
308 if ((px < 0 && (int)x < to_x) || (px > 0 && (int)x > to_x))
309 x = (float)to_x;
310 if ((py < 0 && (int)y < to_y) || (py > 0 && (int)y > to_y))
311 y = (float)to_y;
313 if (dx_is_bigger) {
314 px = px * (1.0 - 1 / (float)slide_slowdown);
315 if (px < slide_steps && px > 0)
316 px = slide_steps;
317 else if (px > -slide_steps && px < 0)
318 px = -slide_steps;
319 py = (sx == 0 ? 0 : px * dy / dx);
320 } else {
321 py = py * (1.0 - 1 / (float)slide_slowdown);
322 if (py < slide_steps && py > 0)
323 py = slide_steps;
324 else if (py > -slide_steps && py < 0)
325 py = -slide_steps;
326 px = (sy == 0 ? 0 : py * dx / dy);
329 XMoveWindow(dpy, win, (int)x, (int)y);
330 XFlush(dpy);
331 if (slide_delay > 0) {
332 wusleep(slide_delay * 1000L);
333 } else {
334 wusleep(10);
336 if (time(NULL) - time0 > MAX_ANIMATION_TIME)
337 break;
339 XMoveWindow(dpy, win, to_x, to_y);
341 XSync(dpy, 0);
342 /* compress expose events */
343 eatExpose();
346 char *ShrinkString(WMFont * font, char *string, int width)
348 int w, w1 = 0;
349 int p;
350 char *pos;
351 char *text;
352 int p1, p2, t;
354 p = strlen(string);
355 w = WMWidthOfString(font, string, p);
356 text = wmalloc(strlen(string) + 8);
357 strcpy(text, string);
358 if (w <= width)
359 return text;
361 pos = strchr(text, ' ');
362 if (!pos)
363 pos = strchr(text, ':');
365 if (pos) {
366 *pos = 0;
367 p = strlen(text);
368 w1 = WMWidthOfString(font, text, p);
369 if (w1 > width) {
370 w1 = 0;
371 p = 0;
372 *pos = ' ';
373 *text = 0;
374 } else {
375 *pos = 0;
376 width -= w1;
377 p++;
379 string += p;
380 p = strlen(string);
381 } else {
382 *text = 0;
384 strcat(text, "...");
385 width -= WMWidthOfString(font, "...", 3);
386 pos = string;
387 p1 = 0;
388 p2 = p;
389 t = (p2 - p1) / 2;
390 while (p2 > p1 && p1 != t) {
391 w = WMWidthOfString(font, &string[p - t], t);
392 if (w > width) {
393 p2 = t;
394 t = p1 + (p2 - p1) / 2;
395 } else if (w < width) {
396 p1 = t;
397 t = p1 + (p2 - p1) / 2;
398 } else
399 p2 = p1 = t;
401 strcat(text, &string[p - p1]);
403 return text;
406 char *FindImage(char *paths, char *file)
408 char *tmp, *path;
410 tmp = strrchr(file, ':');
411 if (tmp) {
412 *tmp = 0;
413 path = wfindfile(paths, file);
414 *tmp = ':';
416 if (!tmp || !path) {
417 path = wfindfile(paths, file);
420 return path;
423 static void timeoutHandler(void *data)
425 *(int *)data = 1;
428 static char *getTextSelection(WScreen * screen, Atom selection)
430 int buffer = -1;
432 switch (selection) {
433 case XA_CUT_BUFFER0:
434 buffer = 0;
435 break;
436 case XA_CUT_BUFFER1:
437 buffer = 1;
438 break;
439 case XA_CUT_BUFFER2:
440 buffer = 2;
441 break;
442 case XA_CUT_BUFFER3:
443 buffer = 3;
444 break;
445 case XA_CUT_BUFFER4:
446 buffer = 4;
447 break;
448 case XA_CUT_BUFFER5:
449 buffer = 5;
450 break;
451 case XA_CUT_BUFFER6:
452 buffer = 6;
453 break;
454 case XA_CUT_BUFFER7:
455 buffer = 7;
456 break;
458 if (buffer >= 0) {
459 char *data;
460 int size;
462 data = XFetchBuffer(dpy, &size, buffer);
464 return data;
465 } else {
466 char *data;
467 int bits;
468 Atom rtype;
469 unsigned long len, bytes;
470 WMHandlerID timer;
471 int timeout = 0;
472 XEvent ev;
473 static Atom clipboard = 0;
475 if (!clipboard)
476 clipboard = XInternAtom(dpy, "CLIPBOARD", False);
478 XDeleteProperty(dpy, screen->info_window, clipboard);
480 XConvertSelection(dpy, selection, XA_STRING, clipboard, screen->info_window, CurrentTime);
482 timer = WMAddTimerHandler(1000, timeoutHandler, &timeout);
484 while (!XCheckTypedWindowEvent(dpy, screen->info_window, SelectionNotify, &ev) && !timeout) ;
486 if (!timeout) {
487 WMDeleteTimerHandler(timer);
488 } else {
489 wwarning("selection retrieval timed out");
490 return NULL;
493 /* nobody owns the selection or the current owner has
494 * nothing to do with what we need */
495 if (ev.xselection.property == None) {
496 return NULL;
499 if (XGetWindowProperty(dpy, screen->info_window,
500 clipboard, 0, 1024,
501 False, XA_STRING, &rtype, &bits, &len,
502 &bytes, (unsigned char **)&data) != Success) {
503 return NULL;
505 if (rtype != XA_STRING || bits != 8) {
506 wwarning("invalid data in text selection");
507 if (data)
508 XFree(data);
509 return NULL;
511 return data;
515 static char *getselection(WScreen * scr)
517 char *tmp;
519 tmp = getTextSelection(scr, XA_PRIMARY);
520 if (!tmp)
521 tmp = getTextSelection(scr, XA_CUT_BUFFER0);
522 return tmp;
525 static char*
526 parseuserinputpart(char *line, int *ptr, char *endchars)
528 int depth = 0, begin;
529 char *value = NULL;
530 begin = ++*ptr;
532 while(line[*ptr] != '\0') {
533 if(line[*ptr] == '(') {
534 ++depth;
535 } else if(depth > 0 && line[*ptr] == ')') {
536 --depth;
537 } else if(depth == 0 && strchr(endchars, line[*ptr]) != NULL) {
538 value = wmalloc(*ptr - begin + 1);
539 strncpy(value, line + begin, *ptr - begin);
540 value[*ptr - begin] = '\0';
541 break;
543 ++*ptr;
546 return value;
549 static char*
550 getuserinput(WScreen *scr, char *line, int *ptr, Bool advanced)
552 char *ret = NULL, *title = NULL, *prompt = NULL, *name = NULL;
553 int rv;
555 if(line[*ptr] == '(')
556 title = parseuserinputpart(line, ptr, ",)");
557 if(title != NULL && line[*ptr] == ',')
558 prompt = parseuserinputpart(line, ptr, ",)");
559 if(prompt != NULL && line[*ptr] == ',')
560 name = parseuserinputpart(line, ptr, ")");
562 if(advanced)
563 rv = wAdvancedInputDialog(scr,
564 title ? gettext(title):_("Program Arguments"),
565 prompt ? gettext(prompt):_("Enter command arguments:"),
566 name, &ret);
567 else
568 rv = wInputDialog(scr,
569 title ? gettext(title):_("Program Arguments"),
570 prompt ? gettext(prompt):_("Enter command arguments:"),
571 &ret);
573 if(title) wfree(title);
574 if(prompt) wfree(prompt);
575 if(name) wfree(name);
577 return rv ? ret : NULL;
580 #define S_NORMAL 0
581 #define S_ESCAPE 1
582 #define S_OPTION 2
585 * state input new-state output
586 * NORMAL % OPTION <nil>
587 * NORMAL \ ESCAPE <nil>
588 * NORMAL etc. NORMAL <input>
589 * ESCAPE any NORMAL <input>
590 * OPTION s NORMAL <selection buffer>
591 * OPTION w NORMAL <selected window id>
592 * OPTION a NORMAL <input text>
593 * OPTION d NORMAL <OffiX DND selection object>
594 * OPTION W NORMAL <current workspace>
595 * OPTION etc. NORMAL %<input>
597 #define TMPBUFSIZE 64
598 char *ExpandOptions(WScreen * scr, char *cmdline)
600 int ptr, optr, state, len, olen;
601 char *out, *nout;
602 char *selection = NULL;
603 char *user_input = NULL;
604 #ifdef XDND
605 char *dropped_thing = NULL;
606 #endif
607 char tmpbuf[TMPBUFSIZE];
608 int slen;
610 len = strlen(cmdline);
611 olen = len + 1;
612 out = malloc(olen);
613 if (!out) {
614 wwarning(_("out of memory during expansion of \"%s\""), cmdline);
615 return NULL;
617 *out = 0;
618 ptr = 0; /* input line pointer */
619 optr = 0; /* output line pointer */
620 state = S_NORMAL;
621 while (ptr < len) {
622 switch (state) {
623 case S_NORMAL:
624 switch (cmdline[ptr]) {
625 case '\\':
626 state = S_ESCAPE;
627 break;
628 case '%':
629 state = S_OPTION;
630 break;
631 default:
632 state = S_NORMAL;
633 out[optr++] = cmdline[ptr];
634 break;
636 break;
637 case S_ESCAPE:
638 switch (cmdline[ptr]) {
639 case 'n':
640 out[optr++] = 10;
641 break;
643 case 'r':
644 out[optr++] = 13;
645 break;
647 case 't':
648 out[optr++] = 9;
649 break;
651 default:
652 out[optr++] = cmdline[ptr];
654 state = S_NORMAL;
655 break;
656 case S_OPTION:
657 state = S_NORMAL;
658 switch (cmdline[ptr]) {
659 case 'w':
660 if (scr->focused_window && scr->focused_window->flags.focused) {
661 snprintf(tmpbuf, sizeof(tmpbuf), "0x%x",
662 (unsigned int)scr->focused_window->client_win);
663 slen = strlen(tmpbuf);
664 olen += slen;
665 nout = realloc(out, olen);
666 if (!nout) {
667 wwarning(_("out of memory during expansion of \"%%w\""));
668 goto error;
670 out = nout;
671 strcat(out, tmpbuf);
672 optr += slen;
673 } else {
674 out[optr++] = ' ';
676 break;
678 case 'W':
679 snprintf(tmpbuf, sizeof(tmpbuf), "0x%x", (unsigned int)scr->current_workspace + 1);
680 slen = strlen(tmpbuf);
681 olen += slen;
682 nout = realloc(out, olen);
683 if (!nout) {
684 wwarning(_("out of memory during expansion of \"%%W\""));
685 goto error;
687 out = nout;
688 strcat(out, tmpbuf);
689 optr += slen;
690 break;
692 case 'a':
693 case 'A':
694 ptr++;
695 user_input = getuserinput(scr, cmdline, &ptr, cmdline[ptr-1] == 'A');
696 if (user_input) {
697 slen = strlen(user_input);
698 olen += slen;
699 nout = realloc(out, olen);
700 if (!nout) {
701 wwarning(_("out of memory during expansion of \"%%a\""));
702 goto error;
704 out = nout;
705 strcat(out, user_input);
706 optr += slen;
707 } else {
708 /* Not an error, but user has Canceled the dialog box.
709 * This will make the command to not be performed. */
710 goto error;
712 break;
714 #ifdef XDND
715 case 'd':
716 if (scr->xdestring) {
717 dropped_thing = wstrdup(scr->xdestring);
719 if (!dropped_thing) {
720 dropped_thing = get_dnd_selection(scr);
722 if (!dropped_thing) {
723 scr->flags.dnd_data_convertion_status = 1;
724 goto error;
726 slen = strlen(dropped_thing);
727 olen += slen;
728 nout = realloc(out, olen);
729 if (!nout) {
730 wwarning(_("out of memory during expansion of \"%%d\""));
731 goto error;
733 out = nout;
734 strcat(out, dropped_thing);
735 optr += slen;
736 break;
737 #endif /* XDND */
739 case 's':
740 if (!selection) {
741 selection = getselection(scr);
743 if (!selection) {
744 wwarning(_("selection not available"));
745 goto error;
747 slen = strlen(selection);
748 olen += slen;
749 nout = realloc(out, olen);
750 if (!nout) {
751 wwarning(_("out of memory during expansion of \"%%s\""));
752 goto error;
754 out = nout;
755 strcat(out, selection);
756 optr += slen;
757 break;
759 default:
760 out[optr++] = '%';
761 out[optr++] = cmdline[ptr];
763 break;
765 out[optr] = 0;
766 ptr++;
768 if (selection)
769 XFree(selection);
770 return out;
772 error:
773 wfree(out);
774 if (selection)
775 XFree(selection);
776 return NULL;
779 void ParseWindowName(WMPropList * value, char **winstance, char **wclass, char *where)
781 char *name;
783 *winstance = *wclass = NULL;
785 if (!WMIsPLString(value)) {
786 wwarning(_("bad window name value in %s state info"), where);
787 return;
790 name = WMGetFromPLString(value);
791 if (!name || strlen(name) == 0) {
792 wwarning(_("bad window name value in %s state info"), where);
793 return;
796 UnescapeWM_CLASS(name, winstance, wclass);
799 #if 0
800 static char *keysymToString(KeySym keysym, unsigned int state)
802 XKeyEvent kev;
803 char *buf = wmalloc(20);
804 int count;
806 kev.display = dpy;
807 kev.type = KeyPress;
808 kev.send_event = False;
809 kev.window = DefaultRootWindow(dpy);
810 kev.root = DefaultRootWindow(dpy);
811 kev.same_screen = True;
812 kev.subwindow = kev.root;
813 kev.serial = 0x12344321;
814 kev.time = CurrentTime;
815 kev.state = state;
816 kev.keycode = XKeysymToKeycode(dpy, keysym);
817 count = XLookupString(&kev, buf, 19, NULL, NULL);
818 buf[count] = 0;
820 return buf;
822 #endif
824 char *GetShortcutString(char *text)
826 char *buffer = NULL;
827 char *k;
828 int modmask = 0;
829 /* KeySym ksym; */
830 int control = 0;
831 char *tmp;
833 tmp = text = wstrdup(text);
835 /* get modifiers */
836 while ((k = strchr(text, '+')) != NULL) {
837 int mod;
839 *k = 0;
840 mod = wXModifierFromKey(text);
841 if (mod < 0) {
842 return wstrdup("bug");
845 modmask |= mod;
847 if (strcasecmp(text, "Meta") == 0) {
848 buffer = wstrappend(buffer, "M+");
849 } else if (strcasecmp(text, "Alt") == 0) {
850 buffer = wstrappend(buffer, "A+");
851 } else if (strcasecmp(text, "Shift") == 0) {
852 buffer = wstrappend(buffer, "Sh+");
853 } else if (strcasecmp(text, "Mod1") == 0) {
854 buffer = wstrappend(buffer, "M1+");
855 } else if (strcasecmp(text, "Mod2") == 0) {
856 buffer = wstrappend(buffer, "M2+");
857 } else if (strcasecmp(text, "Mod3") == 0) {
858 buffer = wstrappend(buffer, "M3+");
859 } else if (strcasecmp(text, "Mod4") == 0) {
860 buffer = wstrappend(buffer, "M4+");
861 } else if (strcasecmp(text, "Mod5") == 0) {
862 buffer = wstrappend(buffer, "M5+");
863 } else if (strcasecmp(text, "Control") == 0) {
864 control = 1;
865 } else {
866 buffer = wstrappend(buffer, text);
868 text = k + 1;
871 if (control) {
872 buffer = wstrappend(buffer, "^");
874 buffer = wstrappend(buffer, text);
876 /* get key */
877 /* ksym = XStringToKeysym(text);
878 tmp = keysymToString(ksym, modmask);
879 puts(tmp);
880 buffer = wstrappend(buffer, tmp);
882 wfree(tmp);
884 return buffer;
887 char *EscapeWM_CLASS(char *name, char *class)
889 char *ret;
890 char *ename = NULL, *eclass = NULL;
891 int i, j, l;
893 if (!name && !class)
894 return NULL;
896 if (name) {
897 l = strlen(name);
898 ename = wmalloc(l * 2 + 1);
899 j = 0;
900 for (i = 0; i < l; i++) {
901 if (name[i] == '\\') {
902 ename[j++] = '\\';
903 } else if (name[i] == '.') {
904 ename[j++] = '\\';
906 ename[j++] = name[i];
908 ename[j] = 0;
910 if (class) {
911 l = strlen(class);
912 eclass = wmalloc(l * 2 + 1);
913 j = 0;
914 for (i = 0; i < l; i++) {
915 if (class[i] == '\\') {
916 eclass[j++] = '\\';
917 } else if (class[i] == '.') {
918 eclass[j++] = '\\';
920 eclass[j++] = class[i];
922 eclass[j] = 0;
925 if (ename && eclass) {
926 int len = strlen(ename) + strlen(eclass) + 4;
927 ret = wmalloc(len);
928 snprintf(ret, len, "%s.%s", ename, eclass);
929 wfree(ename);
930 wfree(eclass);
931 } else if (ename) {
932 ret = wstrdup(ename);
933 wfree(ename);
934 } else {
935 ret = wstrdup(eclass);
936 wfree(eclass);
939 return ret;
942 void UnescapeWM_CLASS(char *str, char **name, char **class)
944 int i, j, k, dot;
946 j = strlen(str);
947 *name = wmalloc(j);
948 **name = 0;
949 *class = wmalloc(j);
950 **class = 0;
952 /* separate string in 2 parts */
953 dot = -1;
954 for (i = 0; i < j; i++) {
955 if (str[i] == '\\') {
956 i++;
957 continue;
958 } else if (str[i] == '.') {
959 dot = i;
960 break;
964 /* unescape strings */
965 for (i = 0, k = 0; i < dot; i++) {
966 if (str[i] == '\\') {
967 continue;
968 } else {
969 (*name)[k++] = str[i];
972 (*name)[k] = 0;
974 for (i = dot + 1, k = 0; i < j; i++) {
975 if (str[i] == '\\') {
976 continue;
977 } else {
978 (*class)[k++] = str[i];
981 (*class)[k] = 0;
983 if (!*name) {
984 wfree(*name);
985 *name = NULL;
987 if (!*class) {
988 wfree(*class);
989 *class = NULL;
993 void SendHelperMessage(WScreen * scr, char type, int workspace, char *msg)
995 char *buffer;
996 int len;
997 int i;
998 char buf[16];
1000 if (!scr->flags.backimage_helper_launched) {
1001 return;
1004 len = (msg ? strlen(msg) : 0) + (workspace >= 0 ? 4 : 0) + 1;
1005 buffer = wmalloc(len + 5);
1006 snprintf(buf, sizeof(buf), "%4i", len);
1007 memcpy(buffer, buf, 4);
1008 buffer[4] = type;
1009 i = 5;
1010 if (workspace >= 0) {
1011 snprintf(buf, sizeof(buf), "%4i", workspace);
1012 memcpy(&buffer[i], buf, 4);
1013 i += 4;
1014 buffer[i] = 0;
1016 if (msg)
1017 strcpy(&buffer[i], msg);
1019 if (write(scr->helper_fd, buffer, len + 4) < 0) {
1020 wsyserror(_("could not send message to background image helper"));
1022 wfree(buffer);
1025 Bool UpdateDomainFile(WDDomain * domain)
1027 struct stat stbuf;
1028 char path[PATH_MAX];
1029 WMPropList *shared_dict, *dict;
1030 Bool result, freeDict = False;
1032 dict = domain->dictionary;
1033 if (WMIsPLDictionary(domain->dictionary)) {
1034 /* retrieve global system dictionary */
1035 snprintf(path, sizeof(path), "%s/WindowMaker/%s", SYSCONFDIR, domain->domain_name);
1036 if (stat(path, &stbuf) >= 0) {
1037 shared_dict = WMReadPropListFromFile(path);
1038 if (shared_dict) {
1039 if (WMIsPLDictionary(shared_dict)) {
1040 freeDict = True;
1041 dict = WMDeepCopyPropList(domain->dictionary);
1042 WMSubtractPLDictionaries(dict, shared_dict, True);
1044 WMReleasePropList(shared_dict);
1049 result = WMWritePropListToFile(dict, domain->path);
1051 if (freeDict) {
1052 WMReleasePropList(dict);
1055 return result;
1058 char *StrConcatDot(char *a, char *b)
1060 int len;
1061 char *str;
1063 if (!a)
1064 a = "";
1065 if (!b)
1066 b = "";
1068 len = strlen(a) + strlen(b) + 4;
1069 str = wmalloc(len);
1071 snprintf(str, len, "%s.%s", a, b);
1073 return str;
1076 #define MAX_CMD_SIZE 4096
1078 Bool GetCommandForPid(int pid, char ***argv, int *argc)
1080 static char buf[MAX_CMD_SIZE];
1081 FILE *fPtr;
1082 int count, i, j;
1083 Bool ok = False;
1085 sprintf(buf, "/proc/%d/cmdline", pid);
1086 fPtr = fopen(buf, "r");
1087 if (fPtr) {
1088 count = read(fileno(fPtr), buf, MAX_CMD_SIZE);
1089 if (count > 0) {
1090 buf[count - 1] = 0;
1091 for (i = 0, *argc = 0; i < count; i++) {
1092 if (buf[i] == 0) {
1093 (*argc)++;
1096 if ((*argc) == 0) {
1097 *argv = NULL;
1098 ok = False;
1099 } else {
1100 *argv = (char **)wmalloc(sizeof(char *) * (*argc));
1101 (*argv)[0] = buf;
1102 for (i = 0, j = 1; i < count; i++) {
1103 if (buf[i] != 0)
1104 continue;
1105 if (i < count - 1) {
1106 (*argv)[j++] = &buf[i + 1];
1108 if (j == *argc) {
1109 break;
1112 ok = True;
1115 fclose(fPtr);
1118 return ok;
1121 static char *getCommandForWindow(Window win, int elements)
1123 char **argv, *command = NULL;
1124 int argc;
1126 if (XGetCommand(dpy, win, &argv, &argc)) {
1127 if (argc > 0 && argv != NULL) {
1128 if (elements == 0)
1129 elements = argc;
1130 command = wtokenjoin(argv, WMIN(argc, elements));
1131 if (command[0] == 0) {
1132 wfree(command);
1133 command = NULL;
1136 if (argv) {
1137 XFreeStringList(argv);
1141 return command;
1144 /* Free result when done */
1145 char *GetCommandForWindow(Window win)
1147 return getCommandForWindow(win, 0);
1150 /* Free result when done */
1151 char *GetProgramNameForWindow(Window win)
1153 return getCommandForWindow(win, 1);