Small fix for wmaker nightly build script 2
[wmaker-crm.git] / src / misc.c
blob14fc75ef2c8c6bef2cffae57bfcb11f6233f139f
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 "defaults.h"
48 #include "dialog.h"
49 #include "xutil.h"
50 #include "xmodifier.h"
52 /**** global variables *****/
54 extern WPreferences wPreferences;
56 extern Time LastTimestamp;
58 #ifdef USECPP
59 static void putdef(char *line, char *name, char *value)
61 if (!value) {
62 wwarning(_("could not define value for %s for cpp"), name);
63 return;
65 strcat(line, name);
66 strcat(line, value);
69 static void putidef(char *line, char *name, int value)
71 char tmp[64];
72 snprintf(tmp, sizeof(tmp), "%i", value);
73 strcat(line, name);
74 strcat(line, tmp);
77 static char *username()
79 char *tmp;
81 tmp = getlogin();
82 if (!tmp) {
83 struct passwd *user;
85 user = getpwuid(getuid());
86 if (!user) {
87 wsyserror(_("could not get password entry for UID %i"), getuid());
88 return NULL;
90 if (!user->pw_name) {
91 return NULL;
92 } else {
93 return user->pw_name;
96 return tmp;
99 char *MakeCPPArgs(char *path)
101 int i;
102 char buffer[MAXLINE], *buf, *line;
103 Visual *visual;
104 char *tmp;
106 line = wmalloc(MAXLINE);
107 *line = 0;
108 i = 1;
109 if ((buf = getenv("HOSTNAME")) != NULL) {
110 if (buf[0] == '(') {
111 wwarning(_("your machine is misconfigured. HOSTNAME is set to %s"), buf);
112 } else
113 putdef(line, " -DHOST=", buf);
114 } else if ((buf = getenv("HOST")) != NULL) {
115 if (buf[0] == '(') {
116 wwarning(_("your machine is misconfigured. HOST is set to %s"), buf);
117 } else
118 putdef(line, " -DHOST=", buf);
120 buf = username();
121 if (buf)
122 putdef(line, " -DUSER=", buf);
123 putidef(line, " -DUID=", getuid());
124 buf = XDisplayName(DisplayString(dpy));
125 putdef(line, " -DDISPLAY=", buf);
126 putdef(line, " -DWM_VERSION=", VERSION);
128 visual = DefaultVisual(dpy, DefaultScreen(dpy));
129 putidef(line, " -DVISUAL=", visual->class);
131 putidef(line, " -DDEPTH=", DefaultDepth(dpy, DefaultScreen(dpy)));
133 putidef(line, " -DSCR_WIDTH=", WidthOfScreen(DefaultScreenOfDisplay(dpy)));
134 putidef(line, " -DSCR_HEIGHT=", HeightOfScreen(DefaultScreenOfDisplay(dpy)));
136 /* put the dir where the menu is being read from to the
137 * search path */
138 if (path) {
139 tmp = wstrdup(path);
140 buf = strchr(tmp + 1, ' ');
141 if (buf) {
142 *buf = 0;
144 buf = strrchr(tmp, '/');
145 if (buf) {
146 *buf = 0; /* trunc filename */
147 putdef(line, " -I", tmp);
149 wfree(tmp);
152 /* this should be done just once, but it works this way */
153 strcpy(buffer, DEF_CONFIG_PATHS);
154 buf = strtok(buffer, ":");
156 do {
157 char fullpath[MAXLINE];
159 if (buf[0] != '~') {
160 strcpy(fullpath, buf);
161 } else {
162 char *wgethomedir();
163 /* home is statically allocated. Don't free it! */
164 char *home = wgethomedir();
166 strcpy(fullpath, home);
167 strcat(fullpath, &(buf[1]));
170 putdef(line, " -I", fullpath);
172 } while ((buf = strtok(NULL, ":")) != NULL);
174 #undef arg
175 #ifdef DEBUG
176 puts("CPP ARGS");
177 puts(line);
178 #endif
179 return line;
181 #endif /* USECPP */
183 #if 0
185 * Is win2 below win1?
187 static Bool isBelow(WWindow * win1, WWindow * win2)
189 int i;
190 WCoreWindow *tmp;
192 tmp = win1->frame->core->stacking->under;
193 while (tmp) {
194 if (tmp == win2->frame->core)
195 return True;
196 tmp = tmp->stacking->under;
199 for (i = win1->frame->core->stacking->window_level - 1; i >= 0; i--) {
200 tmp = win1->screen_ptr->stacking_list[i];
201 while (tmp) {
202 if (tmp == win2->frame->core)
203 return True;
204 tmp = tmp->stacking->under;
207 return True;
209 #endif
211 /* XFetchName Wrapper */
212 Bool wFetchName(Display *dpy, Window win, char **winname)
214 XTextProperty text_prop;
215 char **list;
216 int num;
218 if (XGetWMName(dpy, win, &text_prop)) {
219 if (text_prop.value && text_prop.nitems > 0) {
220 if (text_prop.encoding == XA_STRING) {
221 *winname = wstrdup((char *)text_prop.value);
222 XFree(text_prop.value);
223 } else {
224 text_prop.nitems = strlen((char *)text_prop.value);
225 if (XmbTextPropertyToTextList(dpy, &text_prop, &list, &num) >=
226 Success && num > 0 && *list) {
227 XFree(text_prop.value);
228 *winname = wstrdup(*list);
229 XFreeStringList(list);
230 } else {
231 *winname = wstrdup((char *)text_prop.value);
232 XFree(text_prop.value);
235 } else {
236 /* the title is set, but it was set to none */
237 *winname = wstrdup("");
239 return True;
240 } else {
241 /* the hint is probably not set */
242 *winname = NULL;
244 return False;
248 /* XGetIconName Wrapper */
249 Bool wGetIconName(Display *dpy, Window win, char **iconname)
251 XTextProperty text_prop;
252 char **list;
253 int num;
255 if (XGetWMIconName(dpy, win, &text_prop) != 0 && text_prop.value && text_prop.nitems > 0) {
256 if (text_prop.encoding == XA_STRING)
257 *iconname = (char *)text_prop.value;
258 else {
259 text_prop.nitems = strlen((char *)text_prop.value);
260 if (XmbTextPropertyToTextList(dpy, &text_prop, &list, &num) >= Success && num > 0 && *list) {
261 XFree(text_prop.value);
262 *iconname = wstrdup(*list);
263 XFreeStringList(list);
264 } else
265 *iconname = (char *)text_prop.value;
267 return True;
269 *iconname = NULL;
270 return False;
273 static void eatExpose()
275 XEvent event, foo;
277 /* compress all expose events into a single one */
279 if (XCheckMaskEvent(dpy, ExposureMask, &event)) {
280 /* ignore other exposure events for this window */
281 while (XCheckWindowEvent(dpy, event.xexpose.window, ExposureMask, &foo)) ;
282 /* eat exposes for other windows */
283 eatExpose();
285 event.xexpose.count = 0;
286 XPutBackEvent(dpy, &event);
290 void SlideWindow(Window win, int from_x, int from_y, int to_x, int to_y)
292 time_t time0 = time(NULL);
293 float dx, dy, x = from_x, y = from_y, sx, sy, px, py;
294 int dx_is_bigger = 0;
295 int slide_delay, slide_steps, slide_slowdown;
297 /* animation parameters */
298 static struct {
299 int delay;
300 int steps;
301 int slowdown;
302 } apars[5] = {
303 {ICON_SLIDE_DELAY_UF, ICON_SLIDE_STEPS_UF, ICON_SLIDE_SLOWDOWN_UF},
304 {ICON_SLIDE_DELAY_F, ICON_SLIDE_STEPS_F, ICON_SLIDE_SLOWDOWN_F},
305 {ICON_SLIDE_DELAY_M, ICON_SLIDE_STEPS_M, ICON_SLIDE_SLOWDOWN_M},
306 {ICON_SLIDE_DELAY_S, ICON_SLIDE_STEPS_S, ICON_SLIDE_SLOWDOWN_S},
307 {ICON_SLIDE_DELAY_US, ICON_SLIDE_STEPS_US, ICON_SLIDE_SLOWDOWN_US}
310 slide_slowdown = apars[(int)wPreferences.icon_slide_speed].slowdown;
311 slide_steps = apars[(int)wPreferences.icon_slide_speed].steps;
312 slide_delay = apars[(int)wPreferences.icon_slide_speed].delay;
314 dx = (float)(to_x - from_x);
315 dy = (float)(to_y - from_y);
316 sx = (dx == 0 ? 0 : fabs(dx) / dx);
317 sy = (dy == 0 ? 0 : fabs(dy) / dy);
319 if (fabs(dx) > fabs(dy)) {
320 dx_is_bigger = 1;
323 if (dx_is_bigger) {
324 px = dx / slide_slowdown;
325 if (px < slide_steps && px > 0)
326 px = slide_steps;
327 else if (px > -slide_steps && px < 0)
328 px = -slide_steps;
329 py = (sx == 0 ? 0 : px * dy / dx);
330 } else {
331 py = dy / slide_slowdown;
332 if (py < slide_steps && py > 0)
333 py = slide_steps;
334 else if (py > -slide_steps && py < 0)
335 py = -slide_steps;
336 px = (sy == 0 ? 0 : py * dx / dy);
339 while (x != to_x || y != to_y) {
340 x += px;
341 y += py;
342 if ((px < 0 && (int)x < to_x) || (px > 0 && (int)x > to_x))
343 x = (float)to_x;
344 if ((py < 0 && (int)y < to_y) || (py > 0 && (int)y > to_y))
345 y = (float)to_y;
347 if (dx_is_bigger) {
348 px = px * (1.0 - 1 / (float)slide_slowdown);
349 if (px < slide_steps && px > 0)
350 px = slide_steps;
351 else if (px > -slide_steps && px < 0)
352 px = -slide_steps;
353 py = (sx == 0 ? 0 : px * dy / dx);
354 } else {
355 py = py * (1.0 - 1 / (float)slide_slowdown);
356 if (py < slide_steps && py > 0)
357 py = slide_steps;
358 else if (py > -slide_steps && py < 0)
359 py = -slide_steps;
360 px = (sy == 0 ? 0 : py * dx / dy);
363 XMoveWindow(dpy, win, (int)x, (int)y);
364 XFlush(dpy);
365 if (slide_delay > 0) {
366 wusleep(slide_delay * 1000L);
367 } else {
368 wusleep(10);
370 if (time(NULL) - time0 > MAX_ANIMATION_TIME)
371 break;
373 XMoveWindow(dpy, win, to_x, to_y);
375 XSync(dpy, 0);
376 /* compress expose events */
377 eatExpose();
380 char *ShrinkString(WMFont * font, char *string, int width)
382 int w, w1 = 0;
383 int p;
384 char *pos;
385 char *text;
386 int p1, p2, t;
388 p = strlen(string);
389 w = WMWidthOfString(font, string, p);
390 text = wmalloc(strlen(string) + 8);
391 strcpy(text, string);
392 if (w <= width)
393 return text;
395 pos = strchr(text, ' ');
396 if (!pos)
397 pos = strchr(text, ':');
399 if (pos) {
400 *pos = 0;
401 p = strlen(text);
402 w1 = WMWidthOfString(font, text, p);
403 if (w1 > width) {
404 w1 = 0;
405 p = 0;
406 *pos = ' ';
407 *text = 0;
408 } else {
409 *pos = 0;
410 width -= w1;
411 p++;
413 string += p;
414 p = strlen(string);
415 } else {
416 *text = 0;
418 strcat(text, "...");
419 width -= WMWidthOfString(font, "...", 3);
420 pos = string;
421 p1 = 0;
422 p2 = p;
423 t = (p2 - p1) / 2;
424 while (p2 > p1 && p1 != t) {
425 w = WMWidthOfString(font, &string[p - t], t);
426 if (w > width) {
427 p2 = t;
428 t = p1 + (p2 - p1) / 2;
429 } else if (w < width) {
430 p1 = t;
431 t = p1 + (p2 - p1) / 2;
432 } else
433 p2 = p1 = t;
435 strcat(text, &string[p - p1]);
437 return text;
440 char *FindImage(char *paths, char *file)
442 char *tmp, *path;
444 tmp = strrchr(file, ':');
445 if (tmp) {
446 *tmp = 0;
447 path = wfindfile(paths, file);
448 *tmp = ':';
450 if (!tmp || !path) {
451 path = wfindfile(paths, file);
454 return path;
457 static void timeoutHandler(void *data)
459 *(int *)data = 1;
462 static char *getTextSelection(WScreen * screen, Atom selection)
464 int buffer = -1;
466 switch (selection) {
467 case XA_CUT_BUFFER0:
468 buffer = 0;
469 break;
470 case XA_CUT_BUFFER1:
471 buffer = 1;
472 break;
473 case XA_CUT_BUFFER2:
474 buffer = 2;
475 break;
476 case XA_CUT_BUFFER3:
477 buffer = 3;
478 break;
479 case XA_CUT_BUFFER4:
480 buffer = 4;
481 break;
482 case XA_CUT_BUFFER5:
483 buffer = 5;
484 break;
485 case XA_CUT_BUFFER6:
486 buffer = 6;
487 break;
488 case XA_CUT_BUFFER7:
489 buffer = 7;
490 break;
492 if (buffer >= 0) {
493 char *data;
494 int size;
496 data = XFetchBuffer(dpy, &size, buffer);
498 return data;
499 } else {
500 char *data;
501 int bits;
502 Atom rtype;
503 unsigned long len, bytes;
504 WMHandlerID timer;
505 int timeout = 0;
506 XEvent ev;
507 static Atom clipboard = 0;
509 if (!clipboard)
510 clipboard = XInternAtom(dpy, "CLIPBOARD", False);
512 XDeleteProperty(dpy, screen->info_window, clipboard);
514 XConvertSelection(dpy, selection, XA_STRING, clipboard, screen->info_window, CurrentTime);
516 timer = WMAddTimerHandler(1000, timeoutHandler, &timeout);
518 while (!XCheckTypedWindowEvent(dpy, screen->info_window, SelectionNotify, &ev) && !timeout) ;
520 if (!timeout) {
521 WMDeleteTimerHandler(timer);
522 } else {
523 wwarning("selection retrieval timed out");
524 return NULL;
527 /* nobody owns the selection or the current owner has
528 * nothing to do with what we need */
529 if (ev.xselection.property == None) {
530 return NULL;
533 if (XGetWindowProperty(dpy, screen->info_window,
534 clipboard, 0, 1024,
535 False, XA_STRING, &rtype, &bits, &len,
536 &bytes, (unsigned char **)&data) != Success) {
537 return NULL;
539 if (rtype != XA_STRING || bits != 8) {
540 wwarning("invalid data in text selection");
541 if (data)
542 XFree(data);
543 return NULL;
545 return data;
549 static char *getselection(WScreen * scr)
551 char *tmp;
553 tmp = getTextSelection(scr, XA_PRIMARY);
554 if (!tmp)
555 tmp = getTextSelection(scr, XA_CUT_BUFFER0);
556 return tmp;
559 static char*
560 parseuserinputpart(char *line, int *ptr, char *endchars)
562 int depth = 0, begin;
563 char *value = NULL;
564 begin = ++*ptr;
566 while(line[*ptr] != '\0') {
567 if(line[*ptr] == '(') {
568 ++depth;
569 } else if(depth > 0 && line[*ptr] == ')') {
570 --depth;
571 } else if(depth == 0 && strchr(endchars, line[*ptr]) != NULL) {
572 value = wmalloc(*ptr - begin + 1);
573 strncpy(value, line + begin, *ptr - begin);
574 value[*ptr - begin] = '\0';
575 break;
577 ++*ptr;
580 return value;
583 static char*
584 getuserinput(WScreen *scr, char *line, int *ptr, Bool advanced)
586 char *ret = NULL, *title = NULL, *prompt = NULL, *name = NULL;
587 int rv;
589 if(line[*ptr] == '(')
590 title = parseuserinputpart(line, ptr, ",)");
591 if(title != NULL && line[*ptr] == ',')
592 prompt = parseuserinputpart(line, ptr, ",)");
593 if(prompt != NULL && line[*ptr] == ',')
594 name = parseuserinputpart(line, ptr, ")");
596 if(advanced)
597 rv = wAdvancedInputDialog(scr,
598 title ? gettext(title):_("Program Arguments"),
599 prompt ? gettext(prompt):_("Enter command arguments:"),
600 name, &ret);
601 else
602 rv = wInputDialog(scr,
603 title ? gettext(title):_("Program Arguments"),
604 prompt ? gettext(prompt):_("Enter command arguments:"),
605 &ret);
607 if(title) wfree(title);
608 if(prompt) wfree(prompt);
609 if(name) wfree(name);
611 return rv ? ret : NULL;
614 #define S_NORMAL 0
615 #define S_ESCAPE 1
616 #define S_OPTION 2
619 * state input new-state output
620 * NORMAL % OPTION <nil>
621 * NORMAL \ ESCAPE <nil>
622 * NORMAL etc. NORMAL <input>
623 * ESCAPE any NORMAL <input>
624 * OPTION s NORMAL <selection buffer>
625 * OPTION w NORMAL <selected window id>
626 * OPTION a NORMAL <input text>
627 * OPTION d NORMAL <OffiX DND selection object>
628 * OPTION W NORMAL <current workspace>
629 * OPTION etc. NORMAL %<input>
631 #define TMPBUFSIZE 64
632 char *ExpandOptions(WScreen * scr, char *cmdline)
634 int ptr, optr, state, len, olen;
635 char *out, *nout;
636 char *selection = NULL;
637 char *user_input = NULL;
638 #ifdef XDND
639 char *dropped_thing = NULL;
640 #endif
641 char tmpbuf[TMPBUFSIZE];
642 int slen;
644 len = strlen(cmdline);
645 olen = len + 1;
646 out = malloc(olen);
647 if (!out) {
648 wwarning(_("out of memory during expansion of \"%s\""));
649 return NULL;
651 *out = 0;
652 ptr = 0; /* input line pointer */
653 optr = 0; /* output line pointer */
654 state = S_NORMAL;
655 while (ptr < len) {
656 switch (state) {
657 case S_NORMAL:
658 switch (cmdline[ptr]) {
659 case '\\':
660 state = S_ESCAPE;
661 break;
662 case '%':
663 state = S_OPTION;
664 break;
665 default:
666 state = S_NORMAL;
667 out[optr++] = cmdline[ptr];
668 break;
670 break;
671 case S_ESCAPE:
672 switch (cmdline[ptr]) {
673 case 'n':
674 out[optr++] = 10;
675 break;
677 case 'r':
678 out[optr++] = 13;
679 break;
681 case 't':
682 out[optr++] = 9;
683 break;
685 default:
686 out[optr++] = cmdline[ptr];
688 state = S_NORMAL;
689 break;
690 case S_OPTION:
691 state = S_NORMAL;
692 switch (cmdline[ptr]) {
693 case 'w':
694 if (scr->focused_window && scr->focused_window->flags.focused) {
695 snprintf(tmpbuf, sizeof(tmpbuf), "0x%x",
696 (unsigned int)scr->focused_window->client_win);
697 slen = strlen(tmpbuf);
698 olen += slen;
699 nout = realloc(out, olen);
700 if (!nout) {
701 wwarning(_("out of memory during expansion of \"%w\""));
702 goto error;
704 out = nout;
705 strcat(out, tmpbuf);
706 optr += slen;
707 } else {
708 out[optr++] = ' ';
710 break;
712 case 'W':
713 snprintf(tmpbuf, sizeof(tmpbuf), "0x%x", (unsigned int)scr->current_workspace + 1);
714 slen = strlen(tmpbuf);
715 olen += slen;
716 nout = realloc(out, olen);
717 if (!nout) {
718 wwarning(_("out of memory during expansion of \"%W\""));
719 goto error;
721 out = nout;
722 strcat(out, tmpbuf);
723 optr += slen;
724 break;
726 case 'a':
727 case 'A':
728 ptr++;
729 user_input = getuserinput(scr, cmdline, &ptr, cmdline[ptr-1] == 'A');
730 if (user_input) {
731 slen = strlen(user_input);
732 olen += slen;
733 nout = realloc(out, olen);
734 if (!nout) {
735 wwarning(_("out of memory during expansion of \"%a\""));
736 goto error;
738 out = nout;
739 strcat(out, user_input);
740 optr += slen;
741 } else {
742 /* Not an error, but user has Canceled the dialog box.
743 * This will make the command to not be performed. */
744 goto error;
746 break;
748 #ifdef XDND
749 case 'd':
750 if (scr->xdestring) {
751 dropped_thing = wstrdup(scr->xdestring);
753 if (!dropped_thing) {
754 dropped_thing = get_dnd_selection(scr);
756 if (!dropped_thing) {
757 scr->flags.dnd_data_convertion_status = 1;
758 goto error;
760 slen = strlen(dropped_thing);
761 olen += slen;
762 nout = realloc(out, olen);
763 if (!nout) {
764 wwarning(_("out of memory during expansion of \"%d\""));
765 goto error;
767 out = nout;
768 strcat(out, dropped_thing);
769 optr += slen;
770 break;
771 #endif /* XDND */
773 case 's':
774 if (!selection) {
775 selection = getselection(scr);
777 if (!selection) {
778 wwarning(_("selection not available"));
779 goto error;
781 slen = strlen(selection);
782 olen += slen;
783 nout = realloc(out, olen);
784 if (!nout) {
785 wwarning(_("out of memory during expansion of \"%s\""));
786 goto error;
788 out = nout;
789 strcat(out, selection);
790 optr += slen;
791 break;
793 default:
794 out[optr++] = '%';
795 out[optr++] = cmdline[ptr];
797 break;
799 out[optr] = 0;
800 ptr++;
802 if (selection)
803 XFree(selection);
804 return out;
806 error:
807 wfree(out);
808 if (selection)
809 XFree(selection);
810 return NULL;
813 void ParseWindowName(WMPropList * value, char **winstance, char **wclass, char *where)
815 char *name;
817 *winstance = *wclass = NULL;
819 if (!WMIsPLString(value)) {
820 wwarning(_("bad window name value in %s state info"), where);
821 return;
824 name = WMGetFromPLString(value);
825 if (!name || strlen(name) == 0) {
826 wwarning(_("bad window name value in %s state info"), where);
827 return;
830 UnescapeWM_CLASS(name, winstance, wclass);
833 #if 0
834 static char *keysymToString(KeySym keysym, unsigned int state)
836 XKeyEvent kev;
837 char *buf = wmalloc(20);
838 int count;
840 kev.display = dpy;
841 kev.type = KeyPress;
842 kev.send_event = False;
843 kev.window = DefaultRootWindow(dpy);
844 kev.root = DefaultRootWindow(dpy);
845 kev.same_screen = True;
846 kev.subwindow = kev.root;
847 kev.serial = 0x12344321;
848 kev.time = CurrentTime;
849 kev.state = state;
850 kev.keycode = XKeysymToKeycode(dpy, keysym);
851 count = XLookupString(&kev, buf, 19, NULL, NULL);
852 buf[count] = 0;
854 return buf;
856 #endif
858 char *GetShortcutString(char *text)
860 char *buffer = NULL;
861 char *k;
862 int modmask = 0;
863 /* KeySym ksym; */
864 int control = 0;
865 char *tmp;
867 tmp = text = wstrdup(text);
869 /* get modifiers */
870 while ((k = strchr(text, '+')) != NULL) {
871 int mod;
873 *k = 0;
874 mod = wXModifierFromKey(text);
875 if (mod < 0) {
876 return wstrdup("bug");
879 modmask |= mod;
881 if (strcasecmp(text, "Meta") == 0) {
882 buffer = wstrappend(buffer, "M+");
883 } else if (strcasecmp(text, "Alt") == 0) {
884 buffer = wstrappend(buffer, "A+");
885 } else if (strcasecmp(text, "Shift") == 0) {
886 buffer = wstrappend(buffer, "Sh+");
887 } else if (strcasecmp(text, "Mod1") == 0) {
888 buffer = wstrappend(buffer, "M1+");
889 } else if (strcasecmp(text, "Mod2") == 0) {
890 buffer = wstrappend(buffer, "M2+");
891 } else if (strcasecmp(text, "Mod3") == 0) {
892 buffer = wstrappend(buffer, "M3+");
893 } else if (strcasecmp(text, "Mod4") == 0) {
894 buffer = wstrappend(buffer, "M4+");
895 } else if (strcasecmp(text, "Mod5") == 0) {
896 buffer = wstrappend(buffer, "M5+");
897 } else if (strcasecmp(text, "Control") == 0) {
898 control = 1;
899 } else {
900 buffer = wstrappend(buffer, text);
902 text = k + 1;
905 if (control) {
906 buffer = wstrappend(buffer, "^");
908 buffer = wstrappend(buffer, text);
910 /* get key */
911 /* ksym = XStringToKeysym(text);
912 tmp = keysymToString(ksym, modmask);
913 puts(tmp);
914 buffer = wstrappend(buffer, tmp);
916 wfree(tmp);
918 return buffer;
921 char *EscapeWM_CLASS(char *name, char *class)
923 char *ret;
924 char *ename = NULL, *eclass = NULL;
925 int i, j, l;
927 if (!name && !class)
928 return NULL;
930 if (name) {
931 l = strlen(name);
932 ename = wmalloc(l * 2 + 1);
933 j = 0;
934 for (i = 0; i < l; i++) {
935 if (name[i] == '\\') {
936 ename[j++] = '\\';
937 } else if (name[i] == '.') {
938 ename[j++] = '\\';
940 ename[j++] = name[i];
942 ename[j] = 0;
944 if (class) {
945 l = strlen(class);
946 eclass = wmalloc(l * 2 + 1);
947 j = 0;
948 for (i = 0; i < l; i++) {
949 if (class[i] == '\\') {
950 eclass[j++] = '\\';
951 } else if (class[i] == '.') {
952 eclass[j++] = '\\';
954 eclass[j++] = class[i];
956 eclass[j] = 0;
959 if (ename && eclass) {
960 int len = strlen(ename) + strlen(eclass) + 4;
961 ret = wmalloc(len);
962 snprintf(ret, len, "%s.%s", ename, eclass);
963 wfree(ename);
964 wfree(eclass);
965 } else if (ename) {
966 ret = wstrdup(ename);
967 wfree(ename);
968 } else {
969 ret = wstrdup(eclass);
970 wfree(eclass);
973 return ret;
976 void UnescapeWM_CLASS(char *str, char **name, char **class)
978 int i, j, k, dot;
980 j = strlen(str);
981 *name = wmalloc(j);
982 **name = 0;
983 *class = wmalloc(j);
984 **class = 0;
986 /* separate string in 2 parts */
987 dot = -1;
988 for (i = 0; i < j; i++) {
989 if (str[i] == '\\') {
990 i++;
991 continue;
992 } else if (str[i] == '.') {
993 dot = i;
994 break;
998 /* unescape strings */
999 for (i = 0, k = 0; i < dot; i++) {
1000 if (str[i] == '\\') {
1001 continue;
1002 } else {
1003 (*name)[k++] = str[i];
1006 (*name)[k] = 0;
1008 for (i = dot + 1, k = 0; i < j; i++) {
1009 if (str[i] == '\\') {
1010 continue;
1011 } else {
1012 (*class)[k++] = str[i];
1015 (*class)[k] = 0;
1017 if (!*name) {
1018 wfree(*name);
1019 *name = NULL;
1021 if (!*class) {
1022 wfree(*class);
1023 *class = NULL;
1027 void SendHelperMessage(WScreen * scr, char type, int workspace, char *msg)
1029 char *buffer;
1030 int len;
1031 int i;
1032 char buf[16];
1034 if (!scr->flags.backimage_helper_launched) {
1035 return;
1038 len = (msg ? strlen(msg) : 0) + (workspace >= 0 ? 4 : 0) + 1;
1039 buffer = wmalloc(len + 5);
1040 snprintf(buf, sizeof(buf), "%4i", len);
1041 memcpy(buffer, buf, 4);
1042 buffer[4] = type;
1043 i = 5;
1044 if (workspace >= 0) {
1045 snprintf(buf, sizeof(buf), "%4i", workspace);
1046 memcpy(&buffer[i], buf, 4);
1047 i += 4;
1048 buffer[i] = 0;
1050 if (msg)
1051 strcpy(&buffer[i], msg);
1053 if (write(scr->helper_fd, buffer, len + 4) < 0) {
1054 wsyserror(_("could not send message to background image helper"));
1056 wfree(buffer);
1059 Bool UpdateDomainFile(WDDomain * domain)
1061 struct stat stbuf;
1062 char path[PATH_MAX];
1063 WMPropList *shared_dict, *dict;
1064 Bool result, freeDict = False;
1066 dict = domain->dictionary;
1067 if (WMIsPLDictionary(domain->dictionary)) {
1068 /* retrieve global system dictionary */
1069 snprintf(path, sizeof(path), "%s/WindowMaker/%s", SYSCONFDIR, domain->domain_name);
1070 if (stat(path, &stbuf) >= 0) {
1071 shared_dict = WMReadPropListFromFile(path);
1072 if (shared_dict) {
1073 if (WMIsPLDictionary(shared_dict)) {
1074 freeDict = True;
1075 dict = WMDeepCopyPropList(domain->dictionary);
1076 WMSubtractPLDictionaries(dict, shared_dict, True);
1078 WMReleasePropList(shared_dict);
1083 result = WMWritePropListToFile(dict, domain->path, True);
1085 if (freeDict) {
1086 WMReleasePropList(dict);
1089 return result;
1092 char *StrConcatDot(char *a, char *b)
1094 int len;
1095 char *str;
1097 if (!a)
1098 a = "";
1099 if (!b)
1100 b = "";
1102 len = strlen(a) + strlen(b) + 4;
1103 str = wmalloc(len);
1105 snprintf(str, len, "%s.%s", a, b);
1107 return str;
1110 #define MAX_CMD_SIZE 4096
1112 Bool GetCommandForPid(int pid, char ***argv, int *argc)
1114 static char buf[MAX_CMD_SIZE];
1115 FILE *fPtr;
1116 int count, i, j;
1117 Bool ok = False;
1119 sprintf(buf, "/proc/%d/cmdline", pid);
1120 fPtr = fopen(buf, "r");
1121 if (fPtr) {
1122 count = read(fileno(fPtr), buf, MAX_CMD_SIZE);
1123 if (count > 0) {
1124 buf[count - 1] = 0;
1125 for (i = 0, *argc = 0; i < count; i++) {
1126 if (buf[i] == 0) {
1127 (*argc)++;
1130 if ((*argc) == 0) {
1131 *argv = NULL;
1132 ok = False;
1133 } else {
1134 *argv = (char **)wmalloc(sizeof(char *) * (*argc));
1135 (*argv)[0] = buf;
1136 for (i = 0, j = 1; i < count; i++) {
1137 if (buf[i] != 0)
1138 continue;
1139 if (i < count - 1) {
1140 (*argv)[j++] = &buf[i + 1];
1142 if (j == *argc) {
1143 break;
1146 ok = True;
1149 fclose(fPtr);
1152 return ok;
1155 static char *getCommandForWindow(Window win, int elements)
1157 char **argv, *command = NULL;
1158 int argc;
1160 if (XGetCommand(dpy, win, &argv, &argc)) {
1161 if (argc > 0 && argv != NULL) {
1162 if (elements == 0)
1163 elements = argc;
1164 command = wtokenjoin(argv, WMIN(argc, elements));
1165 if (command[0] == 0) {
1166 wfree(command);
1167 command = NULL;
1170 if (argv) {
1171 XFreeStringList(argv);
1175 return command;
1178 /* Free result when done */
1179 char *GetCommandForWindow(Window win)
1181 return getCommandForWindow(win, 0);
1184 /* Free result when done */
1185 char *GetProgramNameForWindow(Window win)
1187 return getCommandForWindow(win, 1);