Avoid icon change to default on winspector save
[wmaker-crm.git] / src / misc.c
blob9922ea2341b3518eac74c6815a973886e236194a
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 /* XFetchName Wrapper */
54 Bool wFetchName(Display *dpy, Window win, char **winname)
56 XTextProperty text_prop;
57 char **list;
58 int num;
60 if (XGetWMName(dpy, win, &text_prop)) {
61 if (text_prop.value && text_prop.nitems > 0) {
62 if (text_prop.encoding == XA_STRING) {
63 *winname = wstrdup((char *)text_prop.value);
64 XFree(text_prop.value);
65 } else {
66 text_prop.nitems = strlen((char *)text_prop.value);
67 if (XmbTextPropertyToTextList(dpy, &text_prop, &list, &num) >=
68 Success && num > 0 && *list) {
69 XFree(text_prop.value);
70 *winname = wstrdup(*list);
71 XFreeStringList(list);
72 } else {
73 *winname = wstrdup((char *)text_prop.value);
74 XFree(text_prop.value);
77 } else {
78 /* the title is set, but it was set to none */
79 *winname = wstrdup("");
81 return True;
82 } else {
83 /* the hint is probably not set */
84 *winname = NULL;
86 return False;
90 /* XGetIconName Wrapper */
91 Bool wGetIconName(Display *dpy, Window win, char **iconname)
93 XTextProperty text_prop;
94 char **list;
95 int num;
97 if (XGetWMIconName(dpy, win, &text_prop) != 0 && text_prop.value && text_prop.nitems > 0) {
98 if (text_prop.encoding == XA_STRING)
99 *iconname = (char *)text_prop.value;
100 else {
101 text_prop.nitems = strlen((char *)text_prop.value);
102 if (XmbTextPropertyToTextList(dpy, &text_prop, &list, &num) >= Success && num > 0 && *list) {
103 XFree(text_prop.value);
104 *iconname = wstrdup(*list);
105 XFreeStringList(list);
106 } else
107 *iconname = (char *)text_prop.value;
109 return True;
111 *iconname = NULL;
112 return False;
115 static void eatExpose(void)
117 XEvent event, foo;
119 /* compress all expose events into a single one */
121 if (XCheckMaskEvent(dpy, ExposureMask, &event)) {
122 /* ignore other exposure events for this window */
123 while (XCheckWindowEvent(dpy, event.xexpose.window, ExposureMask, &foo)) ;
124 /* eat exposes for other windows */
125 eatExpose();
127 event.xexpose.count = 0;
128 XPutBackEvent(dpy, &event);
132 void move_window(Window win, int from_x, int from_y, int to_x, int to_y)
134 #ifdef ANIMATIONS
135 if (wPreferences.no_animations)
136 XMoveWindow(dpy, win, to_x, to_y);
137 else
138 SlideWindow(win, from_x, from_y, to_x, to_y);
139 #else
140 XMoveWindow(dpy, win, to_x, to_y);
141 #endif
144 void SlideWindow(Window win, int from_x, int from_y, int to_x, int to_y)
146 time_t time0 = time(NULL);
147 float dx, dy, x = from_x, y = from_y, sx, sy, px, py;
148 int dx_is_bigger = 0;
149 int slide_delay, slide_steps, slide_slowdown;
151 /* animation parameters */
152 static struct {
153 int delay;
154 int steps;
155 int slowdown;
156 } apars[5] = {
157 {ICON_SLIDE_DELAY_UF, ICON_SLIDE_STEPS_UF, ICON_SLIDE_SLOWDOWN_UF},
158 {ICON_SLIDE_DELAY_F, ICON_SLIDE_STEPS_F, ICON_SLIDE_SLOWDOWN_F},
159 {ICON_SLIDE_DELAY_M, ICON_SLIDE_STEPS_M, ICON_SLIDE_SLOWDOWN_M},
160 {ICON_SLIDE_DELAY_S, ICON_SLIDE_STEPS_S, ICON_SLIDE_SLOWDOWN_S},
161 {ICON_SLIDE_DELAY_US, ICON_SLIDE_STEPS_US, ICON_SLIDE_SLOWDOWN_US}
164 slide_slowdown = apars[(int)wPreferences.icon_slide_speed].slowdown;
165 slide_steps = apars[(int)wPreferences.icon_slide_speed].steps;
166 slide_delay = apars[(int)wPreferences.icon_slide_speed].delay;
168 dx = (float)(to_x - from_x);
169 dy = (float)(to_y - from_y);
170 sx = (dx == 0 ? 0 : fabs(dx) / dx);
171 sy = (dy == 0 ? 0 : fabs(dy) / dy);
173 if (fabs(dx) > fabs(dy)) {
174 dx_is_bigger = 1;
177 if (dx_is_bigger) {
178 px = dx / slide_slowdown;
179 if (px < slide_steps && px > 0)
180 px = slide_steps;
181 else if (px > -slide_steps && px < 0)
182 px = -slide_steps;
183 py = (sx == 0 ? 0 : px * dy / dx);
184 } else {
185 py = dy / slide_slowdown;
186 if (py < slide_steps && py > 0)
187 py = slide_steps;
188 else if (py > -slide_steps && py < 0)
189 py = -slide_steps;
190 px = (sy == 0 ? 0 : py * dx / dy);
193 while (x != to_x || y != to_y) {
194 x += px;
195 y += py;
196 if ((px < 0 && (int)x < to_x) || (px > 0 && (int)x > to_x))
197 x = (float)to_x;
198 if ((py < 0 && (int)y < to_y) || (py > 0 && (int)y > to_y))
199 y = (float)to_y;
201 if (dx_is_bigger) {
202 px = px * (1.0 - 1 / (float)slide_slowdown);
203 if (px < slide_steps && px > 0)
204 px = slide_steps;
205 else if (px > -slide_steps && px < 0)
206 px = -slide_steps;
207 py = (sx == 0 ? 0 : px * dy / dx);
208 } else {
209 py = py * (1.0 - 1 / (float)slide_slowdown);
210 if (py < slide_steps && py > 0)
211 py = slide_steps;
212 else if (py > -slide_steps && py < 0)
213 py = -slide_steps;
214 px = (sy == 0 ? 0 : py * dx / dy);
217 XMoveWindow(dpy, win, (int)x, (int)y);
218 XFlush(dpy);
219 if (slide_delay > 0) {
220 wusleep(slide_delay * 1000L);
221 } else {
222 wusleep(10);
224 if (time(NULL) - time0 > MAX_ANIMATION_TIME)
225 break;
227 XMoveWindow(dpy, win, to_x, to_y);
229 XSync(dpy, 0);
230 /* compress expose events */
231 eatExpose();
234 char *ShrinkString(WMFont * font, char *string, int width)
236 int w, w1 = 0;
237 int p;
238 char *pos;
239 char *text;
240 int p1, p2, t;
242 p = strlen(string);
243 w = WMWidthOfString(font, string, p);
244 text = wmalloc(strlen(string) + 8);
245 strcpy(text, string);
246 if (w <= width)
247 return text;
249 pos = strchr(text, ' ');
250 if (!pos)
251 pos = strchr(text, ':');
253 if (pos) {
254 *pos = 0;
255 p = strlen(text);
256 w1 = WMWidthOfString(font, text, p);
257 if (w1 > width) {
258 w1 = 0;
259 p = 0;
260 *pos = ' ';
261 *text = 0;
262 } else {
263 *pos = 0;
264 width -= w1;
265 p++;
267 string += p;
268 p = strlen(string);
269 } else {
270 *text = 0;
272 strcat(text, "...");
273 width -= WMWidthOfString(font, "...", 3);
274 pos = string;
275 p1 = 0;
276 p2 = p;
277 t = (p2 - p1) / 2;
278 while (p2 > p1 && p1 != t) {
279 w = WMWidthOfString(font, &string[p - t], t);
280 if (w > width) {
281 p2 = t;
282 t = p1 + (p2 - p1) / 2;
283 } else if (w < width) {
284 p1 = t;
285 t = p1 + (p2 - p1) / 2;
286 } else
287 p2 = p1 = t;
289 strcat(text, &string[p - p1]);
291 return text;
294 char *FindImage(char *paths, char *file)
296 char *tmp, *path = NULL;
298 tmp = strrchr(file, ':');
299 if (tmp) {
300 *tmp = 0;
301 path = wfindfile(paths, file);
302 *tmp = ':';
304 if (!tmp || !path)
305 path = wfindfile(paths, file);
307 return path;
310 static void timeoutHandler(void *data)
312 *(int *)data = 1;
315 static char *getTextSelection(WScreen * screen, Atom selection)
317 int buffer = -1;
319 switch (selection) {
320 case XA_CUT_BUFFER0:
321 buffer = 0;
322 break;
323 case XA_CUT_BUFFER1:
324 buffer = 1;
325 break;
326 case XA_CUT_BUFFER2:
327 buffer = 2;
328 break;
329 case XA_CUT_BUFFER3:
330 buffer = 3;
331 break;
332 case XA_CUT_BUFFER4:
333 buffer = 4;
334 break;
335 case XA_CUT_BUFFER5:
336 buffer = 5;
337 break;
338 case XA_CUT_BUFFER6:
339 buffer = 6;
340 break;
341 case XA_CUT_BUFFER7:
342 buffer = 7;
343 break;
345 if (buffer >= 0) {
346 char *data;
347 int size;
349 data = XFetchBuffer(dpy, &size, buffer);
351 return data;
352 } else {
353 char *data;
354 int bits;
355 Atom rtype;
356 unsigned long len, bytes;
357 WMHandlerID timer;
358 int timeout = 0;
359 XEvent ev;
360 static Atom clipboard = 0;
362 if (!clipboard)
363 clipboard = XInternAtom(dpy, "CLIPBOARD", False);
365 XDeleteProperty(dpy, screen->info_window, clipboard);
367 XConvertSelection(dpy, selection, XA_STRING, clipboard, screen->info_window, CurrentTime);
369 timer = WMAddTimerHandler(1000, timeoutHandler, &timeout);
371 while (!XCheckTypedWindowEvent(dpy, screen->info_window, SelectionNotify, &ev) && !timeout) ;
373 if (!timeout) {
374 WMDeleteTimerHandler(timer);
375 } else {
376 wwarning("selection retrieval timed out");
377 return NULL;
380 /* nobody owns the selection or the current owner has
381 * nothing to do with what we need */
382 if (ev.xselection.property == None) {
383 return NULL;
386 if (XGetWindowProperty(dpy, screen->info_window,
387 clipboard, 0, 1024,
388 False, XA_STRING, &rtype, &bits, &len,
389 &bytes, (unsigned char **)&data) != Success) {
390 return NULL;
392 if (rtype != XA_STRING || bits != 8) {
393 wwarning("invalid data in text selection");
394 if (data)
395 XFree(data);
396 return NULL;
398 return data;
402 static char *getselection(WScreen * scr)
404 char *tmp;
406 tmp = getTextSelection(scr, XA_PRIMARY);
407 if (!tmp)
408 tmp = getTextSelection(scr, XA_CUT_BUFFER0);
409 return tmp;
412 static char*
413 parseuserinputpart(char *line, int *ptr, char *endchars)
415 int depth = 0, begin;
416 char *value = NULL;
417 begin = ++*ptr;
419 while(line[*ptr] != '\0') {
420 if(line[*ptr] == '(') {
421 ++depth;
422 } else if(depth > 0 && line[*ptr] == ')') {
423 --depth;
424 } else if(depth == 0 && strchr(endchars, line[*ptr]) != NULL) {
425 value = wmalloc(*ptr - begin + 1);
426 strncpy(value, line + begin, *ptr - begin);
427 value[*ptr - begin] = '\0';
428 break;
430 ++*ptr;
433 return value;
436 static char*
437 getuserinput(WScreen *scr, char *line, int *ptr, Bool advanced)
439 char *ret = NULL, *title = NULL, *prompt = NULL, *name = NULL;
440 int rv;
442 if(line[*ptr] == '(')
443 title = parseuserinputpart(line, ptr, ",)");
444 if(title != NULL && line[*ptr] == ',')
445 prompt = parseuserinputpart(line, ptr, ",)");
446 if(prompt != NULL && line[*ptr] == ',')
447 name = parseuserinputpart(line, ptr, ")");
449 if(advanced)
450 rv = wAdvancedInputDialog(scr,
451 title ? _(title):_("Program Arguments"),
452 prompt ? _(prompt):_("Enter command arguments:"),
453 name, &ret);
454 else
455 rv = wInputDialog(scr,
456 title ? _(title):_("Program Arguments"),
457 prompt ? _(prompt):_("Enter command arguments:"),
458 &ret);
460 if(title) wfree(title);
461 if(prompt) wfree(prompt);
462 if(name) wfree(name);
464 return rv ? ret : NULL;
467 #define S_NORMAL 0
468 #define S_ESCAPE 1
469 #define S_OPTION 2
472 * state input new-state output
473 * NORMAL % OPTION <nil>
474 * NORMAL \ ESCAPE <nil>
475 * NORMAL etc. NORMAL <input>
476 * ESCAPE any NORMAL <input>
477 * OPTION s NORMAL <selection buffer>
478 * OPTION w NORMAL <selected window id>
479 * OPTION a NORMAL <input text>
480 * OPTION d NORMAL <OffiX DND selection object>
481 * OPTION W NORMAL <current workspace>
482 * OPTION etc. NORMAL %<input>
484 #define TMPBUFSIZE 64
485 char *ExpandOptions(WScreen * scr, char *cmdline)
487 int ptr, optr, state, len, olen;
488 char *out, *nout;
489 char *selection = NULL;
490 char *user_input = NULL;
491 #ifdef XDND
492 char *dropped_thing = NULL;
493 #endif
494 char tmpbuf[TMPBUFSIZE];
495 int slen;
497 len = strlen(cmdline);
498 olen = len + 1;
499 out = malloc(olen);
500 if (!out) {
501 wwarning(_("out of memory during expansion of \"%s\""), cmdline);
502 return NULL;
504 *out = 0;
505 ptr = 0; /* input line pointer */
506 optr = 0; /* output line pointer */
507 state = S_NORMAL;
508 while (ptr < len) {
509 switch (state) {
510 case S_NORMAL:
511 switch (cmdline[ptr]) {
512 case '\\':
513 state = S_ESCAPE;
514 break;
515 case '%':
516 state = S_OPTION;
517 break;
518 default:
519 state = S_NORMAL;
520 out[optr++] = cmdline[ptr];
521 break;
523 break;
524 case S_ESCAPE:
525 switch (cmdline[ptr]) {
526 case 'n':
527 out[optr++] = 10;
528 break;
530 case 'r':
531 out[optr++] = 13;
532 break;
534 case 't':
535 out[optr++] = 9;
536 break;
538 default:
539 out[optr++] = cmdline[ptr];
541 state = S_NORMAL;
542 break;
543 case S_OPTION:
544 state = S_NORMAL;
545 switch (cmdline[ptr]) {
546 case 'w':
547 if (scr->focused_window && scr->focused_window->flags.focused) {
548 snprintf(tmpbuf, sizeof(tmpbuf), "0x%x",
549 (unsigned int)scr->focused_window->client_win);
550 slen = strlen(tmpbuf);
551 olen += slen;
552 nout = realloc(out, olen);
553 if (!nout) {
554 wwarning(_("out of memory during expansion of \"%%w\""));
555 goto error;
557 out = nout;
558 strcat(out, tmpbuf);
559 optr += slen;
560 } else {
561 out[optr++] = ' ';
563 break;
565 case 'W':
566 snprintf(tmpbuf, sizeof(tmpbuf), "0x%x", (unsigned int)scr->current_workspace + 1);
567 slen = strlen(tmpbuf);
568 olen += slen;
569 nout = realloc(out, olen);
570 if (!nout) {
571 wwarning(_("out of memory during expansion of \"%%W\""));
572 goto error;
574 out = nout;
575 strcat(out, tmpbuf);
576 optr += slen;
577 break;
579 case 'a':
580 case 'A':
581 ptr++;
582 user_input = getuserinput(scr, cmdline, &ptr, cmdline[ptr-1] == 'A');
583 if (user_input) {
584 slen = strlen(user_input);
585 olen += slen;
586 nout = realloc(out, olen);
587 if (!nout) {
588 wwarning(_("out of memory during expansion of \"%%a\""));
589 goto error;
591 out = nout;
592 strcat(out, user_input);
593 optr += slen;
594 } else {
595 /* Not an error, but user has Canceled the dialog box.
596 * This will make the command to not be performed. */
597 goto error;
599 break;
601 #ifdef XDND
602 case 'd':
603 if (scr->xdestring) {
604 dropped_thing = wstrdup(scr->xdestring);
606 if (!dropped_thing) {
607 dropped_thing = get_dnd_selection(scr);
609 if (!dropped_thing) {
610 scr->flags.dnd_data_convertion_status = 1;
611 goto error;
613 slen = strlen(dropped_thing);
614 olen += slen;
615 nout = realloc(out, olen);
616 if (!nout) {
617 wwarning(_("out of memory during expansion of \"%%d\""));
618 goto error;
620 out = nout;
621 strcat(out, dropped_thing);
622 optr += slen;
623 break;
624 #endif /* XDND */
626 case 's':
627 if (!selection) {
628 selection = getselection(scr);
630 if (!selection) {
631 wwarning(_("selection not available"));
632 goto error;
634 slen = strlen(selection);
635 olen += slen;
636 nout = realloc(out, olen);
637 if (!nout) {
638 wwarning(_("out of memory during expansion of \"%%s\""));
639 goto error;
641 out = nout;
642 strcat(out, selection);
643 optr += slen;
644 break;
646 default:
647 out[optr++] = '%';
648 out[optr++] = cmdline[ptr];
650 break;
652 out[optr] = 0;
653 ptr++;
655 if (selection)
656 XFree(selection);
657 return out;
659 error:
660 wfree(out);
661 if (selection)
662 XFree(selection);
663 return NULL;
666 void ParseWindowName(WMPropList * value, char **winstance, char **wclass, char *where)
668 char *name;
670 *winstance = *wclass = NULL;
672 if (!WMIsPLString(value)) {
673 wwarning(_("bad window name value in %s state info"), where);
674 return;
677 name = WMGetFromPLString(value);
678 if (!name || strlen(name) == 0) {
679 wwarning(_("bad window name value in %s state info"), where);
680 return;
683 UnescapeWM_CLASS(name, winstance, wclass);
686 #if 0
687 static char *keysymToString(KeySym keysym, unsigned int state)
689 XKeyEvent kev;
690 char *buf = wmalloc(20);
691 int count;
693 kev.display = dpy;
694 kev.type = KeyPress;
695 kev.send_event = False;
696 kev.window = DefaultRootWindow(dpy);
697 kev.root = DefaultRootWindow(dpy);
698 kev.same_screen = True;
699 kev.subwindow = kev.root;
700 kev.serial = 0x12344321;
701 kev.time = CurrentTime;
702 kev.state = state;
703 kev.keycode = XKeysymToKeycode(dpy, keysym);
704 count = XLookupString(&kev, buf, 19, NULL, NULL);
705 buf[count] = 0;
707 return buf;
709 #endif
711 char *GetShortcutString(char *text)
713 char *buffer = NULL;
714 char *k;
715 int modmask = 0;
716 /* KeySym ksym; */
717 int control = 0;
718 char *tmp;
720 tmp = text = wstrdup(text);
722 /* get modifiers */
723 while ((k = strchr(text, '+')) != NULL) {
724 int mod;
726 *k = 0;
727 mod = wXModifierFromKey(text);
728 if (mod < 0) {
729 return wstrdup("bug");
732 modmask |= mod;
734 if (strcasecmp(text, "Meta") == 0) {
735 buffer = wstrappend(buffer, "M+");
736 } else if (strcasecmp(text, "Alt") == 0) {
737 buffer = wstrappend(buffer, "A+");
738 } else if (strcasecmp(text, "Shift") == 0) {
739 buffer = wstrappend(buffer, "Sh+");
740 } else if (strcasecmp(text, "Mod1") == 0) {
741 buffer = wstrappend(buffer, "M1+");
742 } else if (strcasecmp(text, "Mod2") == 0) {
743 buffer = wstrappend(buffer, "M2+");
744 } else if (strcasecmp(text, "Mod3") == 0) {
745 buffer = wstrappend(buffer, "M3+");
746 } else if (strcasecmp(text, "Mod4") == 0) {
747 buffer = wstrappend(buffer, "M4+");
748 } else if (strcasecmp(text, "Mod5") == 0) {
749 buffer = wstrappend(buffer, "M5+");
750 } else if (strcasecmp(text, "Control") == 0) {
751 control = 1;
752 } else {
753 buffer = wstrappend(buffer, text);
755 text = k + 1;
758 if (control) {
759 buffer = wstrappend(buffer, "^");
761 buffer = wstrappend(buffer, text);
763 /* get key */
764 /* ksym = XStringToKeysym(text);
765 tmp = keysymToString(ksym, modmask);
766 puts(tmp);
767 buffer = wstrappend(buffer, tmp);
769 wfree(tmp);
771 return buffer;
774 char *EscapeWM_CLASS(char *name, char *class)
776 char *ret;
777 char *ename = NULL, *eclass = NULL;
778 int i, j, l;
780 if (!name && !class)
781 return NULL;
783 if (name) {
784 l = strlen(name);
785 ename = wmalloc(l * 2 + 1);
786 j = 0;
787 for (i = 0; i < l; i++) {
788 if (name[i] == '\\') {
789 ename[j++] = '\\';
790 } else if (name[i] == '.') {
791 ename[j++] = '\\';
793 ename[j++] = name[i];
795 ename[j] = 0;
797 if (class) {
798 l = strlen(class);
799 eclass = wmalloc(l * 2 + 1);
800 j = 0;
801 for (i = 0; i < l; i++) {
802 if (class[i] == '\\') {
803 eclass[j++] = '\\';
804 } else if (class[i] == '.') {
805 eclass[j++] = '\\';
807 eclass[j++] = class[i];
809 eclass[j] = 0;
812 if (ename && eclass) {
813 int len = strlen(ename) + strlen(eclass) + 4;
814 ret = wmalloc(len);
815 snprintf(ret, len, "%s.%s", ename, eclass);
816 wfree(ename);
817 wfree(eclass);
818 } else if (ename) {
819 ret = wstrdup(ename);
820 wfree(ename);
821 } else {
822 ret = wstrdup(eclass);
823 wfree(eclass);
826 return ret;
829 void UnescapeWM_CLASS(char *str, char **name, char **class)
831 int i, j, k, dot;
833 j = strlen(str);
834 *name = wmalloc(j);
835 **name = 0;
836 *class = wmalloc(j);
837 **class = 0;
839 /* separate string in 2 parts */
840 dot = -1;
841 for (i = 0; i < j; i++) {
842 if (str[i] == '\\') {
843 i++;
844 continue;
845 } else if (str[i] == '.') {
846 dot = i;
847 break;
851 /* unescape strings */
852 for (i = 0, k = 0; i < dot; i++) {
853 if (str[i] == '\\') {
854 continue;
855 } else {
856 (*name)[k++] = str[i];
859 (*name)[k] = 0;
861 for (i = dot + 1, k = 0; i < j; i++) {
862 if (str[i] == '\\') {
863 continue;
864 } else {
865 (*class)[k++] = str[i];
868 (*class)[k] = 0;
870 if (!*name) {
871 wfree(*name);
872 *name = NULL;
874 if (!*class) {
875 wfree(*class);
876 *class = NULL;
880 void SendHelperMessage(WScreen * scr, char type, int workspace, char *msg)
882 char *buffer;
883 int len;
884 int i;
885 char buf[16];
887 if (!scr->flags.backimage_helper_launched) {
888 return;
891 len = (msg ? strlen(msg) : 0) + (workspace >= 0 ? 4 : 0) + 1;
892 buffer = wmalloc(len + 5);
893 snprintf(buf, sizeof(buf), "%4i", len);
894 memcpy(buffer, buf, 4);
895 buffer[4] = type;
896 i = 5;
897 if (workspace >= 0) {
898 snprintf(buf, sizeof(buf), "%4i", workspace);
899 memcpy(&buffer[i], buf, 4);
900 i += 4;
901 buffer[i] = 0;
903 if (msg)
904 strcpy(&buffer[i], msg);
906 if (write(scr->helper_fd, buffer, len + 4) < 0) {
907 werror(_("could not send message to background image helper"));
909 wfree(buffer);
912 Bool UpdateDomainFile(WDDomain * domain)
914 struct stat stbuf;
915 char path[PATH_MAX];
916 WMPropList *shared_dict, *dict;
917 Bool result, freeDict = False;
919 dict = domain->dictionary;
920 if (WMIsPLDictionary(domain->dictionary)) {
921 /* retrieve global system dictionary */
922 snprintf(path, sizeof(path), "%s/WindowMaker/%s", SYSCONFDIR, domain->domain_name);
923 if (stat(path, &stbuf) >= 0) {
924 shared_dict = WMReadPropListFromFile(path);
925 if (shared_dict) {
926 if (WMIsPLDictionary(shared_dict)) {
927 freeDict = True;
928 dict = WMDeepCopyPropList(domain->dictionary);
929 WMSubtractPLDictionaries(dict, shared_dict, True);
931 WMReleasePropList(shared_dict);
936 result = WMWritePropListToFile(dict, domain->path);
938 if (freeDict) {
939 WMReleasePropList(dict);
942 return result;
945 char *StrConcatDot(char *a, char *b)
947 int len;
948 char *str;
950 if (!a)
951 a = "";
952 if (!b)
953 b = "";
955 len = strlen(a) + strlen(b) + 4;
956 str = wmalloc(len);
958 snprintf(str, len, "%s.%s", a, b);
960 return str;
963 static char *getCommandForWindow(Window win, int elements)
965 char **argv, *command = NULL;
966 int argc;
968 if (XGetCommand(dpy, win, &argv, &argc)) {
969 if (argc > 0 && argv != NULL) {
970 if (elements == 0)
971 elements = argc;
972 command = wtokenjoin(argv, WMIN(argc, elements));
973 if (command[0] == 0) {
974 wfree(command);
975 command = NULL;
978 if (argv) {
979 XFreeStringList(argv);
983 return command;
986 /* Free result when done */
987 char *GetCommandForWindow(Window win)
989 return getCommandForWindow(win, 0);