fixed unclosed file bug
[wmaker-crm.git] / src / misc.c
blobf7671a30ae748efcd01500c0b354078696641813
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>
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"
53 /**** global variables *****/
55 extern WPreferences wPreferences;
57 extern Time LastTimestamp;
60 #ifdef USECPP
61 static void
62 putdef(char *line, char *name, char *value)
64 if (!value) {
65 wwarning(_("could not define value for %s for cpp"), name);
66 return;
68 strcat(line, name);
69 strcat(line, value);
74 static void
75 putidef(char *line, char *name, int value)
77 char tmp[64];
78 snprintf(tmp, sizeof(tmp), "%i", value);
79 strcat(line, name);
80 strcat(line, tmp);
84 static char*
85 username()
87 char *tmp;
89 tmp = getlogin();
90 if (!tmp) {
91 struct passwd *user;
93 user = getpwuid(getuid());
94 if (!user) {
95 wsyserror(_("could not get password entry for UID %i"), getuid());
96 return NULL;
98 if (!user->pw_name) {
99 return NULL;
100 } else {
101 return user->pw_name;
104 return tmp;
107 char *
108 MakeCPPArgs(char *path)
110 int i;
111 char buffer[MAXLINE], *buf, *line;
112 Visual *visual;
113 char *tmp;
115 line = wmalloc(MAXLINE);
116 *line = 0;
117 i=1;
118 if ((buf=getenv("HOSTNAME"))!=NULL) {
119 if (buf[0]=='(') {
120 wwarning(_("your machine is misconfigured. HOSTNAME is set to %s"),
121 buf);
122 } else
123 putdef(line, " -DHOST=", buf);
124 } else if ((buf=getenv("HOST"))!=NULL) {
125 if (buf[0]=='(') {
126 wwarning(_("your machine is misconfigured. HOST is set to %s"),
127 buf);
128 } else
129 putdef(line, " -DHOST=", buf);
131 buf = username();
132 if (buf)
133 putdef(line, " -DUSER=", buf);
134 putidef(line, " -DUID=", getuid());
135 buf = XDisplayName(DisplayString(dpy));
136 putdef(line, " -DDISPLAY=", buf);
137 putdef(line, " -DWM_VERSION=", VERSION);
139 visual = DefaultVisual(dpy, DefaultScreen(dpy));
140 putidef(line, " -DVISUAL=", visual->class);
142 putidef(line, " -DDEPTH=", DefaultDepth(dpy, DefaultScreen(dpy)));
144 putidef(line, " -DSCR_WIDTH=", WidthOfScreen(DefaultScreenOfDisplay(dpy)));
145 putidef(line, " -DSCR_HEIGHT=",
146 HeightOfScreen(DefaultScreenOfDisplay(dpy)));
148 /* put the dir where the menu is being read from to the
149 * search path */
150 if (path) {
151 tmp = wstrdup(path);
152 buf = strchr(tmp+1, ' ');
153 if (buf) {
154 *buf = 0;
156 buf = strrchr(tmp, '/');
157 if (buf) {
158 *buf = 0; /* trunc filename */
159 putdef(line, " -I", tmp);
161 wfree(tmp);
165 /* this should be done just once, but it works this way */
166 strcpy(buffer, DEF_CONFIG_PATHS);
167 buf = strtok(buffer, ":");
169 do {
170 char fullpath[MAXLINE];
172 if (buf[0]!='~') {
173 strcpy(fullpath, buf);
174 } else {
175 char * wgethomedir();
176 /* home is statically allocated. Don't free it! */
177 char *home = wgethomedir();
179 strcpy(fullpath, home);
180 strcat(fullpath, &(buf[1]));
183 putdef(line, " -I", fullpath);
185 } while ((buf = strtok(NULL, ":"))!=NULL);
187 #undef arg
188 #ifdef DEBUG
189 puts("CPP ARGS");
190 puts(line);
191 #endif
192 return line;
194 #endif /* USECPP */
199 #if 0
201 * Is win2 below win1?
203 static Bool
204 isBelow(WWindow *win1, WWindow *win2)
206 int i;
207 WCoreWindow *tmp;
209 tmp = win1->frame->core->stacking->under;
210 while (tmp) {
211 if (tmp == win2->frame->core)
212 return True;
213 tmp = tmp->stacking->under;
216 for (i=win1->frame->core->stacking->window_level-1; i>=0; i--) {
217 tmp = win1->screen_ptr->stacking_list[i];
218 while (tmp) {
219 if (tmp == win2->frame->core)
220 return True;
221 tmp = tmp->stacking->under;
224 return True;
226 #endif
231 * XFetchName Wrapper
234 Bool
235 wFetchName(dpy, win, winname)
236 Display *dpy;
237 Window win;
238 char **winname;
240 XTextProperty text_prop;
241 char **list;
242 int num;
244 if (XGetWMName(dpy, win, &text_prop)) {
245 if (text_prop.value && text_prop.nitems > 0) {
246 if (text_prop.encoding == XA_STRING) {
247 *winname = wstrdup((char *)text_prop.value);
248 XFree(text_prop.value);
249 } else {
250 text_prop.nitems = strlen((char *)text_prop.value);
251 if (XmbTextPropertyToTextList(dpy, &text_prop, &list, &num) >=
252 Success && num > 0 && *list) {
253 XFree(text_prop.value);
254 *winname = wstrdup(*list);
255 XFreeStringList(list);
256 } else {
257 *winname = wstrdup((char *)text_prop.value);
258 XFree(text_prop.value);
261 } else {
262 /* the title is set, but it was set to none */
263 *winname = wstrdup("");
265 return True;
266 } else {
267 /* the hint is probably not set */
268 *winname = NULL;
270 return False;
275 * XGetIconName Wrapper
279 Bool
280 wGetIconName(dpy, win, iconname)
281 Display *dpy;
282 Window win;
283 char **iconname;
285 XTextProperty text_prop;
286 char **list;
287 int num;
289 if (XGetWMIconName(dpy, win, &text_prop) != 0 && text_prop.value
290 && text_prop.nitems > 0) {
291 if (text_prop.encoding == XA_STRING)
292 *iconname = (char *)text_prop.value;
293 else {
294 text_prop.nitems = strlen((char *)text_prop.value);
295 if (XmbTextPropertyToTextList(dpy, &text_prop, &list, &num) >=
296 Success && num > 0 && *list) {
297 XFree(text_prop.value);
298 *iconname = wstrdup(*list);
299 XFreeStringList(list);
300 } else
301 *iconname = (char *)text_prop.value;
303 return True;
305 *iconname = NULL;
306 return False;
310 static void
311 eatExpose()
313 XEvent event, foo;
315 /* compress all expose events into a single one */
317 if (XCheckMaskEvent(dpy, ExposureMask, &event)) {
318 /* ignore other exposure events for this window */
319 while (XCheckWindowEvent(dpy, event.xexpose.window, ExposureMask,
320 &foo));
321 /* eat exposes for other windows */
322 eatExpose();
324 event.xexpose.count = 0;
325 XPutBackEvent(dpy, &event);
330 void
331 SlideWindow(Window win, int from_x, int from_y, int to_x, int to_y)
333 time_t time0 = time(NULL);
334 float dx, dy, x=from_x, y=from_y, sx, sy, px, py;
335 int dx_is_bigger=0;
337 /* animation parameters */
338 static struct {
339 int delay;
340 int steps;
341 int slowdown;
342 } apars[5] = {
343 {ICON_SLIDE_DELAY_UF, ICON_SLIDE_STEPS_UF, ICON_SLIDE_SLOWDOWN_UF},
344 {ICON_SLIDE_DELAY_F, ICON_SLIDE_STEPS_F, ICON_SLIDE_SLOWDOWN_F},
345 {ICON_SLIDE_DELAY_M, ICON_SLIDE_STEPS_M, ICON_SLIDE_SLOWDOWN_M},
346 {ICON_SLIDE_DELAY_S, ICON_SLIDE_STEPS_S, ICON_SLIDE_SLOWDOWN_S},
347 {ICON_SLIDE_DELAY_US, ICON_SLIDE_STEPS_US, ICON_SLIDE_SLOWDOWN_US}};
351 dx = (float)(to_x-from_x);
352 dy = (float)(to_y-from_y);
353 sx = (dx == 0 ? 0 : fabs(dx)/dx);
354 sy = (dy == 0 ? 0 : fabs(dy)/dy);
356 if (fabs(dx) > fabs(dy)) {
357 dx_is_bigger = 1;
360 if (dx_is_bigger) {
361 px = dx / apars[(int)wPreferences.icon_slide_speed].slowdown;
362 if (px < apars[(int)wPreferences.icon_slide_speed].steps && px > 0)
363 px = apars[(int)wPreferences.icon_slide_speed].steps;
364 else if (px > -apars[(int)wPreferences.icon_slide_speed].steps && px < 0)
365 px = -apars[(int)wPreferences.icon_slide_speed].steps;
366 py = (sx == 0 ? 0 : px*dy/dx);
367 } else {
368 py = dy / apars[(int)wPreferences.icon_slide_speed].slowdown;
369 if (py < apars[(int)wPreferences.icon_slide_speed].steps && py > 0)
370 py = apars[(int)wPreferences.icon_slide_speed].steps;
371 else if (py > -apars[(int)wPreferences.icon_slide_speed].steps && py < 0)
372 py = -apars[(int)wPreferences.icon_slide_speed].steps;
373 px = (sy == 0 ? 0 : py*dx/dy);
376 while (x != to_x || y != to_y) {
377 x += px;
378 y += py;
379 if ((px<0 && (int)x < to_x) || (px>0 && (int)x > to_x))
380 x = (float)to_x;
381 if ((py<0 && (int)y < to_y) || (py>0 && (int)y > to_y))
382 y = (float)to_y;
384 if (dx_is_bigger) {
385 px = px * (1.0 - 1/(float)apars[(int)wPreferences.icon_slide_speed].slowdown);
386 if (px < apars[(int)wPreferences.icon_slide_speed].steps && px > 0)
387 px = apars[(int)wPreferences.icon_slide_speed].steps;
388 else if (px > -apars[(int)wPreferences.icon_slide_speed].steps && px < 0)
389 px = -apars[(int)wPreferences.icon_slide_speed].steps;
390 py = (sx == 0 ? 0 : px*dy/dx);
391 } else {
392 py = py * (1.0 - 1/(float)apars[(int)wPreferences.icon_slide_speed].slowdown);
393 if (py < apars[(int)wPreferences.icon_slide_speed].steps && py > 0)
394 py = apars[(int)wPreferences.icon_slide_speed].steps;
395 else if (py > -apars[(int)wPreferences.icon_slide_speed].steps && py < 0)
396 py = -apars[(int)wPreferences.icon_slide_speed].steps;
397 px = (sy == 0 ? 0 : py*dx/dy);
400 XMoveWindow(dpy, win, (int)x, (int)y);
401 XFlush(dpy);
402 if (apars[(int)wPreferences.icon_slide_speed].delay > 0) {
403 wusleep(apars[(int)wPreferences.icon_slide_speed].delay*1000L);
404 } else {
405 wusleep(10);
407 if (time(NULL) - time0 > MAX_ANIMATION_TIME)
408 break;
410 XMoveWindow(dpy, win, to_x, to_y);
412 XSync(dpy, 0);
413 /* compress expose events */
414 eatExpose();
418 char*
419 ShrinkString(WMFont *font, char *string, int width)
421 int w, w1=0;
422 int p;
423 char *pos;
424 char *text;
425 int p1, p2, t;
427 if (wPreferences.multi_byte_text)
428 return wstrdup(string);
430 p = strlen(string);
431 w = WMWidthOfString(font, string, p);
432 text = wmalloc(strlen(string)+8);
433 strcpy(text, string);
434 if (w<=width)
435 return text;
437 pos = strchr(text, ' ');
438 if (!pos)
439 pos = strchr(text, ':');
441 if (pos) {
442 *pos = 0;
443 p = strlen(text);
444 w1 = WMWidthOfString(font, text, p);
445 if (w1 > width) {
446 w1 = 0;
447 p = 0;
448 *pos = ' ';
449 *text = 0;
450 } else {
451 *pos = 0;
452 width -= w1;
453 p++;
455 string += p;
456 p=strlen(string);
457 } else {
458 *text=0;
460 strcat(text, "...");
461 width -= WMWidthOfString(font, "...", 3);
462 pos = string;
463 p1=0;
464 p2=p;
465 t = (p2-p1)/2;
466 while (p2>p1 && p1!=t) {
467 w = WMWidthOfString(font, &string[p-t], t);
468 if (w>width) {
469 p2 = t;
470 t = p1+(p2-p1)/2;
471 } else if (w<width) {
472 p1 = t;
473 t = p1+(p2-p1)/2;
474 } else
475 p2=p1=t;
477 strcat(text, &string[p-p1]);
479 return text;
483 char*
484 FindImage(char *paths, char *file)
486 char *tmp, *path;
488 tmp = strrchr(file, ':');
489 if (tmp) {
490 *tmp = 0;
491 path = wfindfile(paths, file);
492 *tmp = ':';
494 if (!tmp || !path) {
495 path = wfindfile(paths, file);
498 return path;
502 static void
503 timeoutHandler(void *data)
505 *(int*)data = 1;
509 static char*
510 getTextSelection(WScreen *screen, Atom selection)
512 int buffer = -1;
514 switch (selection) {
515 case XA_CUT_BUFFER0:
516 buffer = 0;
517 break;
518 case XA_CUT_BUFFER1:
519 buffer = 1;
520 break;
521 case XA_CUT_BUFFER2:
522 buffer = 2;
523 break;
524 case XA_CUT_BUFFER3:
525 buffer = 3;
526 break;
527 case XA_CUT_BUFFER4:
528 buffer = 4;
529 break;
530 case XA_CUT_BUFFER5:
531 buffer = 5;
532 break;
533 case XA_CUT_BUFFER6:
534 buffer = 6;
535 break;
536 case XA_CUT_BUFFER7:
537 buffer = 7;
538 break;
540 if (buffer >= 0) {
541 char *data;
542 int size;
544 data = XFetchBuffer(dpy, &size, buffer);
546 return data;
547 } else {
548 char *data;
549 int bits;
550 Atom rtype;
551 unsigned long len, bytes;
552 WMHandlerID timer;
553 int timeout = 0;
554 XEvent ev;
555 static Atom clipboard = 0;
557 if (!clipboard)
558 clipboard = XInternAtom(dpy, "CLIPBOARD", False);
560 XDeleteProperty(dpy, screen->info_window, clipboard);
562 XConvertSelection(dpy, selection, XA_STRING,
563 clipboard, screen->info_window,
564 CurrentTime);
566 timer = WMAddTimerHandler(1000, timeoutHandler, &timeout);
568 while (!XCheckTypedWindowEvent(dpy, screen->info_window,
569 SelectionNotify, &ev) && !timeout);
571 if (!timeout) {
572 WMDeleteTimerHandler(timer);
573 } else {
574 wwarning("selection retrieval timed out");
575 return NULL;
578 /* nobody owns the selection or the current owner has
579 * nothing to do with what we need */
580 if (ev.xselection.property == None) {
581 return NULL;
584 if (XGetWindowProperty(dpy, screen->info_window,
585 clipboard, 0, 1024,
586 False, XA_STRING, &rtype, &bits, &len,
587 &bytes, (unsigned char**)&data)!=Success) {
588 return NULL;
590 if (rtype!=XA_STRING || bits!=8) {
591 wwarning("invalid data in text selection");
592 if (data)
593 XFree(data);
594 return NULL;
596 return data;
600 static char*
601 getselection(WScreen *scr)
603 char *tmp;
605 tmp = getTextSelection(scr, XA_PRIMARY);
606 if (!tmp)
607 tmp = getTextSelection(scr, XA_CUT_BUFFER0);
608 return tmp;
612 static char*
613 getuserinput(WScreen *scr, char *line, int *ptr)
615 char *ret;
616 char *title;
617 char *prompt;
618 int j, state;
619 int begin = 0;
620 #define BUFSIZE 512
621 char tbuffer[BUFSIZE], pbuffer[BUFSIZE];
624 title = _("Program Arguments");
625 prompt = _("Enter command arguments:");
626 ret = NULL;
628 #define _STARTING 0
629 #define _TITLE 1
630 #define _PROMPT 2
631 #define _DONE 3
633 state = _STARTING;
634 j = 0;
635 for (; line[*ptr]!=0 && state!=_DONE; (*ptr)++) {
636 switch (state) {
637 case _STARTING:
638 if (line[*ptr]=='(') {
639 state = _TITLE;
640 begin = *ptr+1;
641 } else {
642 state = _DONE;
644 break;
646 case _TITLE:
647 if (j <= 0 && line[*ptr]==',') {
649 j = 0;
650 if (*ptr > begin) {
651 strncpy(tbuffer, &line[begin], WMIN(*ptr-begin, BUFSIZE));
652 tbuffer[WMIN(*ptr-begin, BUFSIZE)] = 0;
653 title = (char*)tbuffer;
655 begin = *ptr+1;
656 state = _PROMPT;
658 } else if (j <= 0 && line[*ptr]==')') {
660 if (*ptr > begin) {
661 strncpy(tbuffer, &line[begin], WMIN(*ptr-begin, BUFSIZE));
662 tbuffer[WMIN(*ptr-begin, BUFSIZE)] = 0;
663 title = (char*)tbuffer;
665 state = _DONE;
667 } else if (line[*ptr]=='(') {
668 j++;
669 } else if (line[*ptr]==')') {
670 j--;
673 break;
675 case _PROMPT:
676 if (line[*ptr]==')' && j==0) {
678 if (*ptr-begin > 1) {
679 strncpy(pbuffer, &line[begin], WMIN(*ptr-begin, BUFSIZE));
680 pbuffer[WMIN(*ptr-begin, BUFSIZE)] = 0;
681 prompt = (char*)pbuffer;
683 state = _DONE;
684 } else if (line[*ptr]=='(')
685 j++;
686 else if (line[*ptr]==')')
687 j--;
688 break;
691 (*ptr)--;
692 #undef _STARTING
693 #undef _TITLE
694 #undef _PROMPT
695 #undef _DONE
697 if (!wInputDialog(scr, title, prompt, &ret))
698 return NULL;
699 else
700 return ret;
704 #define S_NORMAL 0
705 #define S_ESCAPE 1
706 #define S_OPTION 2
709 * state input new-state output
710 * NORMAL % OPTION <nil>
711 * NORMAL \ ESCAPE <nil>
712 * NORMAL etc. NORMAL <input>
713 * ESCAPE any NORMAL <input>
714 * OPTION s NORMAL <selection buffer>
715 * OPTION w NORMAL <selected window id>
716 * OPTION a NORMAL <input text>
717 * OPTION d NORMAL <OffiX DND selection object>
718 * OPTION W NORMAL <current workspace>
719 * OPTION etc. NORMAL %<input>
721 #define TMPBUFSIZE 64
722 char*
723 ExpandOptions(WScreen *scr, char *cmdline)
725 int ptr, optr, state, len, olen;
726 char *out, *nout;
727 char *selection=NULL;
728 char *user_input=NULL;
729 #ifdef XDND
730 char *dropped_thing=NULL;
731 #endif
732 char tmpbuf[TMPBUFSIZE];
733 int slen;
735 len = strlen(cmdline);
736 olen = len+1;
737 out = malloc(olen);
738 if (!out) {
739 wwarning(_("out of memory during expansion of \"%s\""));
740 return NULL;
742 *out = 0;
743 ptr = 0; /* input line pointer */
744 optr = 0; /* output line pointer */
745 state = S_NORMAL;
746 while (ptr < len) {
747 switch (state) {
748 case S_NORMAL:
749 switch (cmdline[ptr]) {
750 case '\\':
751 state = S_ESCAPE;
752 break;
753 case '%':
754 state = S_OPTION;
755 break;
756 default:
757 state = S_NORMAL;
758 out[optr++]=cmdline[ptr];
759 break;
761 break;
762 case S_ESCAPE:
763 switch (cmdline[ptr]) {
764 case 'n':
765 out[optr++]=10;
766 break;
768 case 'r':
769 out[optr++]=13;
770 break;
772 case 't':
773 out[optr++]=9;
774 break;
776 default:
777 out[optr++]=cmdline[ptr];
779 state = S_NORMAL;
780 break;
781 case S_OPTION:
782 state = S_NORMAL;
783 switch (cmdline[ptr]) {
784 case 'w':
785 if (scr->focused_window
786 && scr->focused_window->flags.focused) {
787 snprintf(tmpbuf, sizeof(tmpbuf), "0x%x",
788 (unsigned int)scr->focused_window->client_win);
789 slen = strlen(tmpbuf);
790 olen += slen;
791 nout = realloc(out,olen);
792 if (!nout) {
793 wwarning(_("out of memory during expansion of \"%w\""));
794 goto error;
796 out = nout;
797 strcat(out,tmpbuf);
798 optr+=slen;
799 } else {
800 out[optr++]=' ';
802 break;
804 case 'W':
805 snprintf(tmpbuf, sizeof(tmpbuf), "0x%x",
806 (unsigned int)scr->current_workspace + 1);
807 slen = strlen(tmpbuf);
808 olen += slen;
809 nout = realloc(out,olen);
810 if (!nout) {
811 wwarning(_("out of memory during expansion of \"%W\""));
812 goto error;
814 out = nout;
815 strcat(out,tmpbuf);
816 optr+=slen;
817 break;
819 case 'a':
820 ptr++;
821 user_input = getuserinput(scr, cmdline, &ptr);
822 if (user_input) {
823 slen = strlen(user_input);
824 olen += slen;
825 nout = realloc(out,olen);
826 if (!nout) {
827 wwarning(_("out of memory during expansion of \"%a\""));
828 goto error;
830 out = nout;
831 strcat(out,user_input);
832 optr+=slen;
833 } else {
834 /* Not an error, but user has Canceled the dialog box.
835 * This will make the command to not be performed. */
836 goto error;
838 break;
840 #ifdef XDND
841 case 'd':
842 if(scr->xdestring) {
843 dropped_thing = wstrdup(scr->xdestring);
845 if (!dropped_thing) {
846 dropped_thing = get_dnd_selection(scr);
848 if (!dropped_thing) {
849 scr->flags.dnd_data_convertion_status = 1;
850 goto error;
852 slen = strlen(dropped_thing);
853 olen += slen;
854 nout = realloc(out,olen);
855 if (!nout) {
856 wwarning(_("out of memory during expansion of \"%d\""));
857 goto error;
859 out = nout;
860 strcat(out,dropped_thing);
861 optr+=slen;
862 break;
863 #endif /* XDND */
865 case 's':
866 if (!selection) {
867 selection = getselection(scr);
869 if (!selection) {
870 wwarning(_("selection not available"));
871 goto error;
873 slen = strlen(selection);
874 olen += slen;
875 nout = realloc(out,olen);
876 if (!nout) {
877 wwarning(_("out of memory during expansion of \"%s\""));
878 goto error;
880 out = nout;
881 strcat(out,selection);
882 optr+=slen;
883 break;
885 default:
886 out[optr++]='%';
887 out[optr++]=cmdline[ptr];
889 break;
891 out[optr]=0;
892 ptr++;
894 if (selection)
895 XFree(selection);
896 return out;
898 error:
899 wfree(out);
900 if (selection)
901 XFree(selection);
902 return NULL;
906 void
907 ParseWindowName(WMPropList *value, char **winstance, char **wclass, char *where)
909 char *name;
911 *winstance = *wclass = NULL;
913 if (!WMIsPLString(value)) {
914 wwarning(_("bad window name value in %s state info"), where);
915 return;
918 name = WMGetFromPLString(value);
919 if (!name || strlen(name)==0) {
920 wwarning(_("bad window name value in %s state info"), where);
921 return;
924 UnescapeWM_CLASS(name, winstance, wclass);
928 #if 0
929 static char*
930 keysymToString(KeySym keysym, unsigned int state)
932 XKeyEvent kev;
933 char *buf = wmalloc(20);
934 int count;
936 kev.display = dpy;
937 kev.type = KeyPress;
938 kev.send_event = False;
939 kev.window = DefaultRootWindow(dpy);
940 kev.root = DefaultRootWindow(dpy);
941 kev.same_screen = True;
942 kev.subwindow = kev.root;
943 kev.serial = 0x12344321;
944 kev.time = CurrentTime;
945 kev.state = state;
946 kev.keycode = XKeysymToKeycode(dpy, keysym);
947 count = XLookupString(&kev, buf, 19, NULL, NULL);
948 buf[count] = 0;
950 return buf;
952 #endif
955 char*
956 GetShortcutString(char *text)
958 char *buffer = NULL;
959 char *k;
960 int modmask = 0;
961 /* KeySym ksym;*/
962 int control = 0;
963 char *tmp;
965 tmp = text = wstrdup(text);
967 /* get modifiers */
968 while ((k = strchr(text, '+'))!=NULL) {
969 int mod;
971 *k = 0;
972 mod = wXModifierFromKey(text);
973 if (mod<0) {
974 return wstrdup("bug");
977 modmask |= mod;
979 if (strcasecmp(text, "Meta")==0) {
980 buffer = wstrappend(buffer, "M+");
981 } else if (strcasecmp(text, "Alt")==0) {
982 buffer = wstrappend(buffer, "A+");
983 } else if (strcasecmp(text, "Shift")==0) {
984 buffer = wstrappend(buffer, "Sh+");
985 } else if (strcasecmp(text, "Mod1")==0) {
986 buffer = wstrappend(buffer, "M1+");
987 } else if (strcasecmp(text, "Mod2")==0) {
988 buffer = wstrappend(buffer, "M2+");
989 } else if (strcasecmp(text, "Mod3")==0) {
990 buffer = wstrappend(buffer, "M3+");
991 } else if (strcasecmp(text, "Mod4")==0) {
992 buffer = wstrappend(buffer, "M4+");
993 } else if (strcasecmp(text, "Mod5")==0) {
994 buffer = wstrappend(buffer, "M5+");
995 } else if (strcasecmp(text, "Control")==0) {
996 control = 1;
997 } else {
998 buffer = wstrappend(buffer, text);
1000 text = k+1;
1003 if (control) {
1004 buffer = wstrappend(buffer, "^");
1006 buffer = wstrappend(buffer, text);
1008 /* get key */
1009 /* ksym = XStringToKeysym(text);
1010 tmp = keysymToString(ksym, modmask);
1011 puts(tmp);
1012 buffer = wstrappend(buffer, tmp);
1014 wfree(tmp);
1016 return buffer;
1020 char*
1021 EscapeWM_CLASS(char *name, char *class)
1023 char *ret;
1024 char *ename = NULL, *eclass = NULL;
1025 int i, j, l;
1027 if (!name && !class)
1028 return NULL;
1030 if (name) {
1031 l = strlen(name);
1032 ename = wmalloc(l*2+1);
1033 j = 0;
1034 for (i=0; i<l; i++) {
1035 if (name[i]=='\\') {
1036 ename[j++] = '\\';
1037 } else if (name[i]=='.') {
1038 ename[j++] = '\\';
1040 ename[j++] = name[i];
1042 ename[j] = 0;
1044 if (class) {
1045 l = strlen(class);
1046 eclass = wmalloc(l*2+1);
1047 j = 0;
1048 for (i=0; i<l; i++) {
1049 if (class[i]=='\\') {
1050 eclass[j++] = '\\';
1051 } else if (class[i]=='.') {
1052 eclass[j++] = '\\';
1054 eclass[j++] = class[i];
1056 eclass[j] = 0;
1059 if (ename && eclass) {
1060 int len = strlen(ename)+strlen(eclass)+4;
1061 ret = wmalloc(len);
1062 snprintf(ret, len, "%s.%s", ename, eclass);
1063 wfree(ename);
1064 wfree(eclass);
1065 } else if (ename) {
1066 ret = wstrdup(ename);
1067 wfree(ename);
1068 } else {
1069 ret = wstrdup(eclass);
1070 wfree(eclass);
1073 return ret;
1077 void
1078 UnescapeWM_CLASS(char *str, char **name, char **class)
1080 int i, j, k, dot;
1082 j = strlen(str);
1083 *name = wmalloc(j);
1084 **name = 0;
1085 *class = wmalloc(j);
1086 **class = 0;
1088 /* separate string in 2 parts */
1089 dot = -1;
1090 for (i = 0; i < j; i++) {
1091 if (str[i]=='\\') {
1092 i++;
1093 continue;
1094 } else if (str[i]=='.') {
1095 dot = i;
1096 break;
1100 /* unescape strings */
1101 for (i=0, k=0; i < dot; i++) {
1102 if (str[i]=='\\') {
1103 continue;
1104 } else {
1105 (*name)[k++] = str[i];
1108 (*name)[k] = 0;
1110 for (i=dot+1, k=0; i<j; i++) {
1111 if (str[i]=='\\') {
1112 continue;
1113 } else {
1114 (*class)[k++] = str[i];
1117 (*class)[k] = 0;
1119 if (!*name) {
1120 wfree(*name);
1121 *name = NULL;
1123 if (!*class) {
1124 wfree(*class);
1125 *class = NULL;
1131 void
1132 SendHelperMessage(WScreen *scr, char type, int workspace, char *msg)
1134 unsigned char *buffer;
1135 int len;
1136 int i;
1137 char buf[16];
1139 if (!scr->flags.backimage_helper_launched) {
1140 return;
1143 len = (msg ? strlen(msg) : 0) + (workspace >=0 ? 4 : 0) + 1 ;
1144 buffer = wmalloc(len+5);
1145 snprintf(buf, len, "%4i", len);
1146 memcpy(buffer, buf, 4);
1147 buffer[4] = type;
1148 i = 5;
1149 if (workspace >= 0) {
1150 snprintf(buf, sizeof(buf), "%4i", workspace);
1151 memcpy(&buffer[i], buf, 4);
1152 i += 4;
1153 buffer[i] = 0;
1155 if (msg)
1156 strcpy(&buffer[i], msg);
1158 if (write(scr->helper_fd, buffer, len+4) < 0) {
1159 wsyserror(_("could not send message to background image helper"));
1161 wfree(buffer);
1165 Bool
1166 UpdateDomainFile(WDDomain *domain)
1168 struct stat stbuf;
1169 char path[PATH_MAX];
1170 WMPropList *shared_dict, *dict;
1171 Bool result, freeDict = False;
1173 dict = domain->dictionary;
1174 if (WMIsPLDictionary(domain->dictionary)) {
1175 /* retrieve global system dictionary */
1176 snprintf(path, sizeof(path), "%s/WindowMaker/%s",
1177 SYSCONFDIR, domain->domain_name);
1178 if (stat(path, &stbuf) >= 0) {
1179 shared_dict = WMReadPropListFromFile(path);
1180 if (shared_dict) {
1181 if (WMIsPLDictionary(shared_dict)) {
1182 freeDict = True;
1183 dict = WMDeepCopyPropList(domain->dictionary);
1184 WMSubtractPLDictionaries(dict, shared_dict, True);
1186 WMReleasePropList(shared_dict);
1191 result = WMWritePropListToFile(dict, domain->path, True);
1193 if (freeDict) {
1194 WMReleasePropList(dict);
1197 return result;
1201 char*
1202 StrConcatDot(char *a, char *b)
1204 int len;
1205 char *str;
1207 if (!a)
1208 a = "";
1209 if (!b)
1210 b = "";
1212 len = strlen(a)+strlen(b)+4;
1213 str = wmalloc(len);
1215 snprintf(str, len, "%s.%s", a, b);
1217 return str;
1221 Bool
1222 GetCommandForPid(int pid, char ***argv, int *argc)
1224 char buf[1024];
1225 FILE *fPtr;
1226 int count, i, j;
1227 Bool ok= False;
1229 sprintf(buf, "/proc/%d/cmdline", pid);
1230 fPtr = fopen(buf, "r");
1231 if (fPtr) {
1232 count = read(fileno(fPtr), buf, 1024);
1233 if (count > 0) {
1234 buf[count] = 0;
1235 for (i=0, *argc=0; i<count; i++) {
1236 if (buf[i] == 0) {
1237 (*argc)++;
1240 if ((*argc) == 0) {
1241 *argv = NULL;
1242 ok= False;
1243 } else {
1244 *argv = (char**) wmalloc(sizeof(char*) * (*argc));
1245 (*argv)[0] = buf;
1246 for (i=0, j=1; i<count; i++) {
1247 if (buf[i] != 0)
1248 continue;
1249 if (i < count-1) {
1250 (*argv)[j++] = &buf[i+1];
1253 ok= True;
1256 fclose(fPtr);
1259 return ok;
1263 static char*
1264 getCommandForWindow(Window win, int elements)
1266 char **argv, *command = NULL;
1267 int argc;
1269 if (XGetCommand(dpy, win, &argv, &argc)) {
1270 if (argc > 0 && argv != NULL) {
1271 if (elements==0)
1272 elements = argc;
1273 command = wtokenjoin(argv, WMIN(argc, elements));
1274 if (command[0] == 0) {
1275 wfree(command);
1276 command = NULL;
1279 if (argv) {
1280 XFreeStringList(argv);
1284 return command;
1288 /* Free result when done */
1289 char*
1290 GetCommandForWindow(Window win)
1292 return getCommandForWindow(win, 0);
1296 /* Free result when done */
1297 char*
1298 GetProgramNameForWindow(Window win)
1300 return getCommandForWindow(win, 1);