Fix internationalized format string warnings
[wmaker-crm.git] / src / misc.c
blob7790edb9ee6034ae05500f55f9a6ad96480b51b0
1 /*
2 * Window Maker window manager
4 * Copyright (c) 1997-2003 Alfredo K. Kojima
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 * USA.
21 #include "wconfig.h"
23 #include <X11/Xlib.h>
24 #include <X11/Xutil.h>
25 #include <X11/Xatom.h>
26 #include <sys/stat.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <stdarg.h>
32 #include <pwd.h>
33 #include <math.h>
34 #include <time.h>
36 #include <WINGs/WUtil.h>
37 #include <wraster.h>
39 #include "WindowMaker.h"
40 #include "GNUstep.h"
41 #include "screen.h"
42 #include "wcore.h"
43 #include "window.h"
44 #include "framewin.h"
45 #include "funcs.h"
46 #include "dialog.h"
47 #include "xutil.h"
48 #include "xmodifier.h"
50 /**** global variables *****/
52 extern WPreferences wPreferences;
54 extern Time LastTimestamp;
56 #ifdef USECPP
57 static void putdef(char *line, char *name, char *value)
59 if (!value) {
60 wwarning(_("could not define value for %s for cpp"), name);
61 return;
63 strcat(line, name);
64 strcat(line, value);
67 static void putidef(char *line, char *name, int value)
69 char tmp[64];
70 snprintf(tmp, sizeof(tmp), "%i", value);
71 strcat(line, name);
72 strcat(line, tmp);
75 static char *username()
77 char *tmp;
79 tmp = getlogin();
80 if (!tmp) {
81 struct passwd *user;
83 user = getpwuid(getuid());
84 if (!user) {
85 wsyserror(_("could not get password entry for UID %i"), getuid());
86 return NULL;
88 if (!user->pw_name) {
89 return NULL;
90 } else {
91 return user->pw_name;
94 return tmp;
97 char *MakeCPPArgs(char *path)
99 int i;
100 char buffer[MAXLINE], *buf, *line;
101 Visual *visual;
102 char *tmp;
104 line = wmalloc(MAXLINE);
105 *line = 0;
106 i = 1;
107 if ((buf = getenv("HOSTNAME")) != NULL) {
108 if (buf[0] == '(') {
109 wwarning(_("your machine is misconfigured. HOSTNAME is set to %s"), buf);
110 } else
111 putdef(line, " -DHOST=", buf);
112 } else if ((buf = getenv("HOST")) != NULL) {
113 if (buf[0] == '(') {
114 wwarning(_("your machine is misconfigured. HOST is set to %s"), buf);
115 } else
116 putdef(line, " -DHOST=", buf);
118 buf = username();
119 if (buf)
120 putdef(line, " -DUSER=", buf);
121 putidef(line, " -DUID=", getuid());
122 buf = XDisplayName(DisplayString(dpy));
123 putdef(line, " -DDISPLAY=", buf);
124 putdef(line, " -DWM_VERSION=", VERSION);
126 visual = DefaultVisual(dpy, DefaultScreen(dpy));
127 putidef(line, " -DVISUAL=", visual->class);
129 putidef(line, " -DDEPTH=", DefaultDepth(dpy, DefaultScreen(dpy)));
131 putidef(line, " -DSCR_WIDTH=", WidthOfScreen(DefaultScreenOfDisplay(dpy)));
132 putidef(line, " -DSCR_HEIGHT=", HeightOfScreen(DefaultScreenOfDisplay(dpy)));
134 /* put the dir where the menu is being read from to the
135 * search path */
136 if (path) {
137 tmp = wstrdup(path);
138 buf = strchr(tmp + 1, ' ');
139 if (buf) {
140 *buf = 0;
142 buf = strrchr(tmp, '/');
143 if (buf) {
144 *buf = 0; /* trunc filename */
145 putdef(line, " -I", tmp);
147 wfree(tmp);
150 /* this should be done just once, but it works this way */
151 strcpy(buffer, DEF_CONFIG_PATHS);
152 buf = strtok(buffer, ":");
154 do {
155 char fullpath[MAXLINE];
157 if (buf[0] != '~') {
158 strcpy(fullpath, buf);
159 } else {
160 /* home is statically allocated. Don't free it! */
161 char *home = wgethomedir();
163 strcpy(fullpath, home);
164 strcat(fullpath, &(buf[1]));
167 putdef(line, " -I", fullpath);
169 } while ((buf = strtok(NULL, ":")) != NULL);
171 #undef arg
172 return line;
174 #endif /* USECPP */
176 /* XFetchName Wrapper */
177 Bool wFetchName(Display *dpy, Window win, char **winname)
179 XTextProperty text_prop;
180 char **list;
181 int num;
183 if (XGetWMName(dpy, win, &text_prop)) {
184 if (text_prop.value && text_prop.nitems > 0) {
185 if (text_prop.encoding == XA_STRING) {
186 *winname = wstrdup((char *)text_prop.value);
187 XFree(text_prop.value);
188 } else {
189 text_prop.nitems = strlen((char *)text_prop.value);
190 if (XmbTextPropertyToTextList(dpy, &text_prop, &list, &num) >=
191 Success && num > 0 && *list) {
192 XFree(text_prop.value);
193 *winname = wstrdup(*list);
194 XFreeStringList(list);
195 } else {
196 *winname = wstrdup((char *)text_prop.value);
197 XFree(text_prop.value);
200 } else {
201 /* the title is set, but it was set to none */
202 *winname = wstrdup("");
204 return True;
205 } else {
206 /* the hint is probably not set */
207 *winname = NULL;
209 return False;
213 /* XGetIconName Wrapper */
214 Bool wGetIconName(Display *dpy, Window win, char **iconname)
216 XTextProperty text_prop;
217 char **list;
218 int num;
220 if (XGetWMIconName(dpy, win, &text_prop) != 0 && text_prop.value && text_prop.nitems > 0) {
221 if (text_prop.encoding == XA_STRING)
222 *iconname = (char *)text_prop.value;
223 else {
224 text_prop.nitems = strlen((char *)text_prop.value);
225 if (XmbTextPropertyToTextList(dpy, &text_prop, &list, &num) >= Success && num > 0 && *list) {
226 XFree(text_prop.value);
227 *iconname = wstrdup(*list);
228 XFreeStringList(list);
229 } else
230 *iconname = (char *)text_prop.value;
232 return True;
234 *iconname = NULL;
235 return False;
238 static void eatExpose()
240 XEvent event, foo;
242 /* compress all expose events into a single one */
244 if (XCheckMaskEvent(dpy, ExposureMask, &event)) {
245 /* ignore other exposure events for this window */
246 while (XCheckWindowEvent(dpy, event.xexpose.window, ExposureMask, &foo)) ;
247 /* eat exposes for other windows */
248 eatExpose();
250 event.xexpose.count = 0;
251 XPutBackEvent(dpy, &event);
255 void SlideWindow(Window win, int from_x, int from_y, int to_x, int to_y)
257 time_t time0 = time(NULL);
258 float dx, dy, x = from_x, y = from_y, sx, sy, px, py;
259 int dx_is_bigger = 0;
260 int slide_delay, slide_steps, slide_slowdown;
262 /* animation parameters */
263 static struct {
264 int delay;
265 int steps;
266 int slowdown;
267 } apars[5] = {
268 {ICON_SLIDE_DELAY_UF, ICON_SLIDE_STEPS_UF, ICON_SLIDE_SLOWDOWN_UF},
269 {ICON_SLIDE_DELAY_F, ICON_SLIDE_STEPS_F, ICON_SLIDE_SLOWDOWN_F},
270 {ICON_SLIDE_DELAY_M, ICON_SLIDE_STEPS_M, ICON_SLIDE_SLOWDOWN_M},
271 {ICON_SLIDE_DELAY_S, ICON_SLIDE_STEPS_S, ICON_SLIDE_SLOWDOWN_S},
272 {ICON_SLIDE_DELAY_US, ICON_SLIDE_STEPS_US, ICON_SLIDE_SLOWDOWN_US}
275 slide_slowdown = apars[(int)wPreferences.icon_slide_speed].slowdown;
276 slide_steps = apars[(int)wPreferences.icon_slide_speed].steps;
277 slide_delay = apars[(int)wPreferences.icon_slide_speed].delay;
279 dx = (float)(to_x - from_x);
280 dy = (float)(to_y - from_y);
281 sx = (dx == 0 ? 0 : fabs(dx) / dx);
282 sy = (dy == 0 ? 0 : fabs(dy) / dy);
284 if (fabs(dx) > fabs(dy)) {
285 dx_is_bigger = 1;
288 if (dx_is_bigger) {
289 px = dx / slide_slowdown;
290 if (px < slide_steps && px > 0)
291 px = slide_steps;
292 else if (px > -slide_steps && px < 0)
293 px = -slide_steps;
294 py = (sx == 0 ? 0 : px * dy / dx);
295 } else {
296 py = dy / slide_slowdown;
297 if (py < slide_steps && py > 0)
298 py = slide_steps;
299 else if (py > -slide_steps && py < 0)
300 py = -slide_steps;
301 px = (sy == 0 ? 0 : py * dx / dy);
304 while (x != to_x || y != to_y) {
305 x += px;
306 y += py;
307 if ((px < 0 && (int)x < to_x) || (px > 0 && (int)x > to_x))
308 x = (float)to_x;
309 if ((py < 0 && (int)y < to_y) || (py > 0 && (int)y > to_y))
310 y = (float)to_y;
312 if (dx_is_bigger) {
313 px = px * (1.0 - 1 / (float)slide_slowdown);
314 if (px < slide_steps && px > 0)
315 px = slide_steps;
316 else if (px > -slide_steps && px < 0)
317 px = -slide_steps;
318 py = (sx == 0 ? 0 : px * dy / dx);
319 } else {
320 py = py * (1.0 - 1 / (float)slide_slowdown);
321 if (py < slide_steps && py > 0)
322 py = slide_steps;
323 else if (py > -slide_steps && py < 0)
324 py = -slide_steps;
325 px = (sy == 0 ? 0 : py * dx / dy);
328 XMoveWindow(dpy, win, (int)x, (int)y);
329 XFlush(dpy);
330 if (slide_delay > 0) {
331 wusleep(slide_delay * 1000L);
332 } else {
333 wusleep(10);
335 if (time(NULL) - time0 > MAX_ANIMATION_TIME)
336 break;
338 XMoveWindow(dpy, win, to_x, to_y);
340 XSync(dpy, 0);
341 /* compress expose events */
342 eatExpose();
345 char *ShrinkString(WMFont * font, char *string, int width)
347 int w, w1 = 0;
348 int p;
349 char *pos;
350 char *text;
351 int p1, p2, t;
353 p = strlen(string);
354 w = WMWidthOfString(font, string, p);
355 text = wmalloc(strlen(string) + 8);
356 strcpy(text, string);
357 if (w <= width)
358 return text;
360 pos = strchr(text, ' ');
361 if (!pos)
362 pos = strchr(text, ':');
364 if (pos) {
365 *pos = 0;
366 p = strlen(text);
367 w1 = WMWidthOfString(font, text, p);
368 if (w1 > width) {
369 w1 = 0;
370 p = 0;
371 *pos = ' ';
372 *text = 0;
373 } else {
374 *pos = 0;
375 width -= w1;
376 p++;
378 string += p;
379 p = strlen(string);
380 } else {
381 *text = 0;
383 strcat(text, "...");
384 width -= WMWidthOfString(font, "...", 3);
385 pos = string;
386 p1 = 0;
387 p2 = p;
388 t = (p2 - p1) / 2;
389 while (p2 > p1 && p1 != t) {
390 w = WMWidthOfString(font, &string[p - t], t);
391 if (w > width) {
392 p2 = t;
393 t = p1 + (p2 - p1) / 2;
394 } else if (w < width) {
395 p1 = t;
396 t = p1 + (p2 - p1) / 2;
397 } else
398 p2 = p1 = t;
400 strcat(text, &string[p - p1]);
402 return text;
405 char *FindImage(char *paths, char *file)
407 char *tmp, *path;
409 tmp = strrchr(file, ':');
410 if (tmp) {
411 *tmp = 0;
412 path = wfindfile(paths, file);
413 *tmp = ':';
415 if (!tmp || !path) {
416 path = wfindfile(paths, file);
419 return path;
422 static void timeoutHandler(void *data)
424 *(int *)data = 1;
427 static char *getTextSelection(WScreen * screen, Atom selection)
429 int buffer = -1;
431 switch (selection) {
432 case XA_CUT_BUFFER0:
433 buffer = 0;
434 break;
435 case XA_CUT_BUFFER1:
436 buffer = 1;
437 break;
438 case XA_CUT_BUFFER2:
439 buffer = 2;
440 break;
441 case XA_CUT_BUFFER3:
442 buffer = 3;
443 break;
444 case XA_CUT_BUFFER4:
445 buffer = 4;
446 break;
447 case XA_CUT_BUFFER5:
448 buffer = 5;
449 break;
450 case XA_CUT_BUFFER6:
451 buffer = 6;
452 break;
453 case XA_CUT_BUFFER7:
454 buffer = 7;
455 break;
457 if (buffer >= 0) {
458 char *data;
459 int size;
461 data = XFetchBuffer(dpy, &size, buffer);
463 return data;
464 } else {
465 char *data;
466 int bits;
467 Atom rtype;
468 unsigned long len, bytes;
469 WMHandlerID timer;
470 int timeout = 0;
471 XEvent ev;
472 static Atom clipboard = 0;
474 if (!clipboard)
475 clipboard = XInternAtom(dpy, "CLIPBOARD", False);
477 XDeleteProperty(dpy, screen->info_window, clipboard);
479 XConvertSelection(dpy, selection, XA_STRING, clipboard, screen->info_window, CurrentTime);
481 timer = WMAddTimerHandler(1000, timeoutHandler, &timeout);
483 while (!XCheckTypedWindowEvent(dpy, screen->info_window, SelectionNotify, &ev) && !timeout) ;
485 if (!timeout) {
486 WMDeleteTimerHandler(timer);
487 } else {
488 wwarning("selection retrieval timed out");
489 return NULL;
492 /* nobody owns the selection or the current owner has
493 * nothing to do with what we need */
494 if (ev.xselection.property == None) {
495 return NULL;
498 if (XGetWindowProperty(dpy, screen->info_window,
499 clipboard, 0, 1024,
500 False, XA_STRING, &rtype, &bits, &len,
501 &bytes, (unsigned char **)&data) != Success) {
502 return NULL;
504 if (rtype != XA_STRING || bits != 8) {
505 wwarning("invalid data in text selection");
506 if (data)
507 XFree(data);
508 return NULL;
510 return data;
514 static char *getselection(WScreen * scr)
516 char *tmp;
518 tmp = getTextSelection(scr, XA_PRIMARY);
519 if (!tmp)
520 tmp = getTextSelection(scr, XA_CUT_BUFFER0);
521 return tmp;
524 static char*
525 parseuserinputpart(char *line, int *ptr, char *endchars)
527 int depth = 0, begin;
528 char *value = NULL;
529 begin = ++*ptr;
531 while(line[*ptr] != '\0') {
532 if(line[*ptr] == '(') {
533 ++depth;
534 } else if(depth > 0 && line[*ptr] == ')') {
535 --depth;
536 } else if(depth == 0 && strchr(endchars, line[*ptr]) != NULL) {
537 value = wmalloc(*ptr - begin + 1);
538 strncpy(value, line + begin, *ptr - begin);
539 value[*ptr - begin] = '\0';
540 break;
542 ++*ptr;
545 return value;
548 static char*
549 getuserinput(WScreen *scr, char *line, int *ptr, Bool advanced)
551 char *ret = NULL, *title = NULL, *prompt = NULL, *name = NULL;
552 int rv;
554 if(line[*ptr] == '(')
555 title = parseuserinputpart(line, ptr, ",)");
556 if(title != NULL && line[*ptr] == ',')
557 prompt = parseuserinputpart(line, ptr, ",)");
558 if(prompt != NULL && line[*ptr] == ',')
559 name = parseuserinputpart(line, ptr, ")");
561 if(advanced)
562 rv = wAdvancedInputDialog(scr,
563 title ? _(title):_("Program Arguments"),
564 prompt ? _(prompt):_("Enter command arguments:"),
565 name, &ret);
566 else
567 rv = wInputDialog(scr,
568 title ? _(title):_("Program Arguments"),
569 prompt ? _(prompt):_("Enter command arguments:"),
570 &ret);
572 if(title) wfree(title);
573 if(prompt) wfree(prompt);
574 if(name) wfree(name);
576 return rv ? ret : NULL;
579 #define S_NORMAL 0
580 #define S_ESCAPE 1
581 #define S_OPTION 2
584 * state input new-state output
585 * NORMAL % OPTION <nil>
586 * NORMAL \ ESCAPE <nil>
587 * NORMAL etc. NORMAL <input>
588 * ESCAPE any NORMAL <input>
589 * OPTION s NORMAL <selection buffer>
590 * OPTION w NORMAL <selected window id>
591 * OPTION a NORMAL <input text>
592 * OPTION d NORMAL <OffiX DND selection object>
593 * OPTION W NORMAL <current workspace>
594 * OPTION etc. NORMAL %<input>
596 #define TMPBUFSIZE 64
597 char *ExpandOptions(WScreen * scr, char *cmdline)
599 int ptr, optr, state, len, olen;
600 char *out, *nout;
601 char *selection = NULL;
602 char *user_input = NULL;
603 #ifdef XDND
604 char *dropped_thing = NULL;
605 #endif
606 char tmpbuf[TMPBUFSIZE];
607 int slen;
609 len = strlen(cmdline);
610 olen = len + 1;
611 out = malloc(olen);
612 if (!out) {
613 wwarning(_("out of memory during expansion of \"%s\""), cmdline);
614 return NULL;
616 *out = 0;
617 ptr = 0; /* input line pointer */
618 optr = 0; /* output line pointer */
619 state = S_NORMAL;
620 while (ptr < len) {
621 switch (state) {
622 case S_NORMAL:
623 switch (cmdline[ptr]) {
624 case '\\':
625 state = S_ESCAPE;
626 break;
627 case '%':
628 state = S_OPTION;
629 break;
630 default:
631 state = S_NORMAL;
632 out[optr++] = cmdline[ptr];
633 break;
635 break;
636 case S_ESCAPE:
637 switch (cmdline[ptr]) {
638 case 'n':
639 out[optr++] = 10;
640 break;
642 case 'r':
643 out[optr++] = 13;
644 break;
646 case 't':
647 out[optr++] = 9;
648 break;
650 default:
651 out[optr++] = cmdline[ptr];
653 state = S_NORMAL;
654 break;
655 case S_OPTION:
656 state = S_NORMAL;
657 switch (cmdline[ptr]) {
658 case 'w':
659 if (scr->focused_window && scr->focused_window->flags.focused) {
660 snprintf(tmpbuf, sizeof(tmpbuf), "0x%x",
661 (unsigned int)scr->focused_window->client_win);
662 slen = strlen(tmpbuf);
663 olen += slen;
664 nout = realloc(out, olen);
665 if (!nout) {
666 wwarning(_("out of memory during expansion of \"%%w\""));
667 goto error;
669 out = nout;
670 strcat(out, tmpbuf);
671 optr += slen;
672 } else {
673 out[optr++] = ' ';
675 break;
677 case 'W':
678 snprintf(tmpbuf, sizeof(tmpbuf), "0x%x", (unsigned int)scr->current_workspace + 1);
679 slen = strlen(tmpbuf);
680 olen += slen;
681 nout = realloc(out, olen);
682 if (!nout) {
683 wwarning(_("out of memory during expansion of \"%%W\""));
684 goto error;
686 out = nout;
687 strcat(out, tmpbuf);
688 optr += slen;
689 break;
691 case 'a':
692 case 'A':
693 ptr++;
694 user_input = getuserinput(scr, cmdline, &ptr, cmdline[ptr-1] == 'A');
695 if (user_input) {
696 slen = strlen(user_input);
697 olen += slen;
698 nout = realloc(out, olen);
699 if (!nout) {
700 wwarning(_("out of memory during expansion of \"%%a\""));
701 goto error;
703 out = nout;
704 strcat(out, user_input);
705 optr += slen;
706 } else {
707 /* Not an error, but user has Canceled the dialog box.
708 * This will make the command to not be performed. */
709 goto error;
711 break;
713 #ifdef XDND
714 case 'd':
715 if (scr->xdestring) {
716 dropped_thing = wstrdup(scr->xdestring);
718 if (!dropped_thing) {
719 dropped_thing = get_dnd_selection(scr);
721 if (!dropped_thing) {
722 scr->flags.dnd_data_convertion_status = 1;
723 goto error;
725 slen = strlen(dropped_thing);
726 olen += slen;
727 nout = realloc(out, olen);
728 if (!nout) {
729 wwarning(_("out of memory during expansion of \"%%d\""));
730 goto error;
732 out = nout;
733 strcat(out, dropped_thing);
734 optr += slen;
735 break;
736 #endif /* XDND */
738 case 's':
739 if (!selection) {
740 selection = getselection(scr);
742 if (!selection) {
743 wwarning(_("selection not available"));
744 goto error;
746 slen = strlen(selection);
747 olen += slen;
748 nout = realloc(out, olen);
749 if (!nout) {
750 wwarning(_("out of memory during expansion of \"%%s\""));
751 goto error;
753 out = nout;
754 strcat(out, selection);
755 optr += slen;
756 break;
758 default:
759 out[optr++] = '%';
760 out[optr++] = cmdline[ptr];
762 break;
764 out[optr] = 0;
765 ptr++;
767 if (selection)
768 XFree(selection);
769 return out;
771 error:
772 wfree(out);
773 if (selection)
774 XFree(selection);
775 return NULL;
778 void ParseWindowName(WMPropList * value, char **winstance, char **wclass, char *where)
780 char *name;
782 *winstance = *wclass = NULL;
784 if (!WMIsPLString(value)) {
785 wwarning(_("bad window name value in %s state info"), where);
786 return;
789 name = WMGetFromPLString(value);
790 if (!name || strlen(name) == 0) {
791 wwarning(_("bad window name value in %s state info"), where);
792 return;
795 UnescapeWM_CLASS(name, winstance, wclass);
798 #if 0
799 static char *keysymToString(KeySym keysym, unsigned int state)
801 XKeyEvent kev;
802 char *buf = wmalloc(20);
803 int count;
805 kev.display = dpy;
806 kev.type = KeyPress;
807 kev.send_event = False;
808 kev.window = DefaultRootWindow(dpy);
809 kev.root = DefaultRootWindow(dpy);
810 kev.same_screen = True;
811 kev.subwindow = kev.root;
812 kev.serial = 0x12344321;
813 kev.time = CurrentTime;
814 kev.state = state;
815 kev.keycode = XKeysymToKeycode(dpy, keysym);
816 count = XLookupString(&kev, buf, 19, NULL, NULL);
817 buf[count] = 0;
819 return buf;
821 #endif
823 char *GetShortcutString(char *text)
825 char *buffer = NULL;
826 char *k;
827 int modmask = 0;
828 /* KeySym ksym; */
829 int control = 0;
830 char *tmp;
832 tmp = text = wstrdup(text);
834 /* get modifiers */
835 while ((k = strchr(text, '+')) != NULL) {
836 int mod;
838 *k = 0;
839 mod = wXModifierFromKey(text);
840 if (mod < 0) {
841 return wstrdup("bug");
844 modmask |= mod;
846 if (strcasecmp(text, "Meta") == 0) {
847 buffer = wstrappend(buffer, "M+");
848 } else if (strcasecmp(text, "Alt") == 0) {
849 buffer = wstrappend(buffer, "A+");
850 } else if (strcasecmp(text, "Shift") == 0) {
851 buffer = wstrappend(buffer, "Sh+");
852 } else if (strcasecmp(text, "Mod1") == 0) {
853 buffer = wstrappend(buffer, "M1+");
854 } else if (strcasecmp(text, "Mod2") == 0) {
855 buffer = wstrappend(buffer, "M2+");
856 } else if (strcasecmp(text, "Mod3") == 0) {
857 buffer = wstrappend(buffer, "M3+");
858 } else if (strcasecmp(text, "Mod4") == 0) {
859 buffer = wstrappend(buffer, "M4+");
860 } else if (strcasecmp(text, "Mod5") == 0) {
861 buffer = wstrappend(buffer, "M5+");
862 } else if (strcasecmp(text, "Control") == 0) {
863 control = 1;
864 } else {
865 buffer = wstrappend(buffer, text);
867 text = k + 1;
870 if (control) {
871 buffer = wstrappend(buffer, "^");
873 buffer = wstrappend(buffer, text);
875 /* get key */
876 /* ksym = XStringToKeysym(text);
877 tmp = keysymToString(ksym, modmask);
878 puts(tmp);
879 buffer = wstrappend(buffer, tmp);
881 wfree(tmp);
883 return buffer;
886 char *EscapeWM_CLASS(char *name, char *class)
888 char *ret;
889 char *ename = NULL, *eclass = NULL;
890 int i, j, l;
892 if (!name && !class)
893 return NULL;
895 if (name) {
896 l = strlen(name);
897 ename = wmalloc(l * 2 + 1);
898 j = 0;
899 for (i = 0; i < l; i++) {
900 if (name[i] == '\\') {
901 ename[j++] = '\\';
902 } else if (name[i] == '.') {
903 ename[j++] = '\\';
905 ename[j++] = name[i];
907 ename[j] = 0;
909 if (class) {
910 l = strlen(class);
911 eclass = wmalloc(l * 2 + 1);
912 j = 0;
913 for (i = 0; i < l; i++) {
914 if (class[i] == '\\') {
915 eclass[j++] = '\\';
916 } else if (class[i] == '.') {
917 eclass[j++] = '\\';
919 eclass[j++] = class[i];
921 eclass[j] = 0;
924 if (ename && eclass) {
925 int len = strlen(ename) + strlen(eclass) + 4;
926 ret = wmalloc(len);
927 snprintf(ret, len, "%s.%s", ename, eclass);
928 wfree(ename);
929 wfree(eclass);
930 } else if (ename) {
931 ret = wstrdup(ename);
932 wfree(ename);
933 } else {
934 ret = wstrdup(eclass);
935 wfree(eclass);
938 return ret;
941 void UnescapeWM_CLASS(char *str, char **name, char **class)
943 int i, j, k, dot;
945 j = strlen(str);
946 *name = wmalloc(j);
947 **name = 0;
948 *class = wmalloc(j);
949 **class = 0;
951 /* separate string in 2 parts */
952 dot = -1;
953 for (i = 0; i < j; i++) {
954 if (str[i] == '\\') {
955 i++;
956 continue;
957 } else if (str[i] == '.') {
958 dot = i;
959 break;
963 /* unescape strings */
964 for (i = 0, k = 0; i < dot; i++) {
965 if (str[i] == '\\') {
966 continue;
967 } else {
968 (*name)[k++] = str[i];
971 (*name)[k] = 0;
973 for (i = dot + 1, k = 0; i < j; i++) {
974 if (str[i] == '\\') {
975 continue;
976 } else {
977 (*class)[k++] = str[i];
980 (*class)[k] = 0;
982 if (!*name) {
983 wfree(*name);
984 *name = NULL;
986 if (!*class) {
987 wfree(*class);
988 *class = NULL;
992 void SendHelperMessage(WScreen * scr, char type, int workspace, char *msg)
994 char *buffer;
995 int len;
996 int i;
997 char buf[16];
999 if (!scr->flags.backimage_helper_launched) {
1000 return;
1003 len = (msg ? strlen(msg) : 0) + (workspace >= 0 ? 4 : 0) + 1;
1004 buffer = wmalloc(len + 5);
1005 snprintf(buf, sizeof(buf), "%4i", len);
1006 memcpy(buffer, buf, 4);
1007 buffer[4] = type;
1008 i = 5;
1009 if (workspace >= 0) {
1010 snprintf(buf, sizeof(buf), "%4i", workspace);
1011 memcpy(&buffer[i], buf, 4);
1012 i += 4;
1013 buffer[i] = 0;
1015 if (msg)
1016 strcpy(&buffer[i], msg);
1018 if (write(scr->helper_fd, buffer, len + 4) < 0) {
1019 wsyserror(_("could not send message to background image helper"));
1021 wfree(buffer);
1024 Bool UpdateDomainFile(WDDomain * domain)
1026 struct stat stbuf;
1027 char path[PATH_MAX];
1028 WMPropList *shared_dict, *dict;
1029 Bool result, freeDict = False;
1031 dict = domain->dictionary;
1032 if (WMIsPLDictionary(domain->dictionary)) {
1033 /* retrieve global system dictionary */
1034 snprintf(path, sizeof(path), "%s/WindowMaker/%s", SYSCONFDIR, domain->domain_name);
1035 if (stat(path, &stbuf) >= 0) {
1036 shared_dict = WMReadPropListFromFile(path);
1037 if (shared_dict) {
1038 if (WMIsPLDictionary(shared_dict)) {
1039 freeDict = True;
1040 dict = WMDeepCopyPropList(domain->dictionary);
1041 WMSubtractPLDictionaries(dict, shared_dict, True);
1043 WMReleasePropList(shared_dict);
1048 result = WMWritePropListToFile(dict, domain->path);
1050 if (freeDict) {
1051 WMReleasePropList(dict);
1054 return result;
1057 char *StrConcatDot(char *a, char *b)
1059 int len;
1060 char *str;
1062 if (!a)
1063 a = "";
1064 if (!b)
1065 b = "";
1067 len = strlen(a) + strlen(b) + 4;
1068 str = wmalloc(len);
1070 snprintf(str, len, "%s.%s", a, b);
1072 return str;
1075 static char *getCommandForWindow(Window win, int elements)
1077 char **argv, *command = NULL;
1078 int argc;
1080 if (XGetCommand(dpy, win, &argv, &argc)) {
1081 if (argc > 0 && argv != NULL) {
1082 if (elements == 0)
1083 elements = argc;
1084 command = wtokenjoin(argv, WMIN(argc, elements));
1085 if (command[0] == 0) {
1086 wfree(command);
1087 command = NULL;
1090 if (argv) {
1091 XFreeStringList(argv);
1095 return command;
1098 /* Free result when done */
1099 char *GetCommandForWindow(Window win)
1101 return getCommandForWindow(win, 0);
1104 /* Free result when done */
1105 char *GetProgramNameForWindow(Window win)
1107 return getCommandForWindow(win, 1);