1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-19 20:38:08 +01:00
Files
wmaker/src/misc.c
Carlos R. Mafra 1a85719971 Increase the readability of SlideWindow()
It is easier to read the computations if the variables
have shorter names. At the same time it avoids reading
the struct array elements repeatedly, so as a bonus
misc.o gets 64 bytes (0.5%) smaller

[mafra@Pilar:wmaker.git]$ size src/misc.o.*
   text    data     bss     dec     hex filename
  11125       0    4104   15229    3b7d src/misc.o.new
  11189       0    4104   15293    3bbd src/misc.o.old
2009-09-17 00:44:36 +02:00

1202 lines
25 KiB
C

/*
* Window Maker window manager
*
* Copyright (c) 1997-2003 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
#include <pwd.h>
#include <math.h>
#include <time.h>
#include <libintl.h>
#include <WINGs/WUtil.h>
#include <wraster.h>
#include "WindowMaker.h"
#include "GNUstep.h"
#include "screen.h"
#include "wcore.h"
#include "window.h"
#include "framewin.h"
#include "funcs.h"
#include "defaults.h"
#include "dialog.h"
#include "xutil.h"
#include "xmodifier.h"
/**** global variables *****/
extern WPreferences wPreferences;
extern Time LastTimestamp;
#ifdef USECPP
static void putdef(char *line, char *name, char *value)
{
if (!value) {
wwarning(_("could not define value for %s for cpp"), name);
return;
}
strcat(line, name);
strcat(line, value);
}
static void putidef(char *line, char *name, int value)
{
char tmp[64];
snprintf(tmp, sizeof(tmp), "%i", value);
strcat(line, name);
strcat(line, tmp);
}
static char *username()
{
char *tmp;
tmp = getlogin();
if (!tmp) {
struct passwd *user;
user = getpwuid(getuid());
if (!user) {
wsyserror(_("could not get password entry for UID %i"), getuid());
return NULL;
}
if (!user->pw_name) {
return NULL;
} else {
return user->pw_name;
}
}
return tmp;
}
char *MakeCPPArgs(char *path)
{
int i;
char buffer[MAXLINE], *buf, *line;
Visual *visual;
char *tmp;
line = wmalloc(MAXLINE);
*line = 0;
i = 1;
if ((buf = getenv("HOSTNAME")) != NULL) {
if (buf[0] == '(') {
wwarning(_("your machine is misconfigured. HOSTNAME is set to %s"), buf);
} else
putdef(line, " -DHOST=", buf);
} else if ((buf = getenv("HOST")) != NULL) {
if (buf[0] == '(') {
wwarning(_("your machine is misconfigured. HOST is set to %s"), buf);
} else
putdef(line, " -DHOST=", buf);
}
buf = username();
if (buf)
putdef(line, " -DUSER=", buf);
putidef(line, " -DUID=", getuid());
buf = XDisplayName(DisplayString(dpy));
putdef(line, " -DDISPLAY=", buf);
putdef(line, " -DWM_VERSION=", VERSION);
visual = DefaultVisual(dpy, DefaultScreen(dpy));
putidef(line, " -DVISUAL=", visual->class);
putidef(line, " -DDEPTH=", DefaultDepth(dpy, DefaultScreen(dpy)));
putidef(line, " -DSCR_WIDTH=", WidthOfScreen(DefaultScreenOfDisplay(dpy)));
putidef(line, " -DSCR_HEIGHT=", HeightOfScreen(DefaultScreenOfDisplay(dpy)));
/* put the dir where the menu is being read from to the
* search path */
if (path) {
tmp = wstrdup(path);
buf = strchr(tmp + 1, ' ');
if (buf) {
*buf = 0;
}
buf = strrchr(tmp, '/');
if (buf) {
*buf = 0; /* trunc filename */
putdef(line, " -I", tmp);
}
wfree(tmp);
}
/* this should be done just once, but it works this way */
strcpy(buffer, DEF_CONFIG_PATHS);
buf = strtok(buffer, ":");
do {
char fullpath[MAXLINE];
if (buf[0] != '~') {
strcpy(fullpath, buf);
} else {
char *wgethomedir();
/* home is statically allocated. Don't free it! */
char *home = wgethomedir();
strcpy(fullpath, home);
strcat(fullpath, &(buf[1]));
}
putdef(line, " -I", fullpath);
} while ((buf = strtok(NULL, ":")) != NULL);
#undef arg
#ifdef DEBUG
puts("CPP ARGS");
puts(line);
#endif
return line;
}
#endif /* USECPP */
#if 0
/*
* Is win2 below win1?
*/
static Bool isBelow(WWindow * win1, WWindow * win2)
{
int i;
WCoreWindow *tmp;
tmp = win1->frame->core->stacking->under;
while (tmp) {
if (tmp == win2->frame->core)
return True;
tmp = tmp->stacking->under;
}
for (i = win1->frame->core->stacking->window_level - 1; i >= 0; i--) {
tmp = win1->screen_ptr->stacking_list[i];
while (tmp) {
if (tmp == win2->frame->core)
return True;
tmp = tmp->stacking->under;
}
}
return True;
}
#endif
/*
* XFetchName Wrapper
*
*/
Bool wFetchName(dpy, win, winname)
Display *dpy;
Window win;
char **winname;
{
XTextProperty text_prop;
char **list;
int num;
if (XGetWMName(dpy, win, &text_prop)) {
if (text_prop.value && text_prop.nitems > 0) {
if (text_prop.encoding == XA_STRING) {
*winname = wstrdup((char *)text_prop.value);
XFree(text_prop.value);
} else {
text_prop.nitems = strlen((char *)text_prop.value);
if (XmbTextPropertyToTextList(dpy, &text_prop, &list, &num) >=
Success && num > 0 && *list) {
XFree(text_prop.value);
*winname = wstrdup(*list);
XFreeStringList(list);
} else {
*winname = wstrdup((char *)text_prop.value);
XFree(text_prop.value);
}
}
} else {
/* the title is set, but it was set to none */
*winname = wstrdup("");
}
return True;
} else {
/* the hint is probably not set */
*winname = NULL;
return False;
}
}
/*
* XGetIconName Wrapper
*
*/
Bool wGetIconName(dpy, win, iconname)
Display *dpy;
Window win;
char **iconname;
{
XTextProperty text_prop;
char **list;
int num;
if (XGetWMIconName(dpy, win, &text_prop) != 0 && text_prop.value && text_prop.nitems > 0) {
if (text_prop.encoding == XA_STRING)
*iconname = (char *)text_prop.value;
else {
text_prop.nitems = strlen((char *)text_prop.value);
if (XmbTextPropertyToTextList(dpy, &text_prop, &list, &num) >= Success && num > 0 && *list) {
XFree(text_prop.value);
*iconname = wstrdup(*list);
XFreeStringList(list);
} else
*iconname = (char *)text_prop.value;
}
return True;
}
*iconname = NULL;
return False;
}
static void eatExpose()
{
XEvent event, foo;
/* compress all expose events into a single one */
if (XCheckMaskEvent(dpy, ExposureMask, &event)) {
/* ignore other exposure events for this window */
while (XCheckWindowEvent(dpy, event.xexpose.window, ExposureMask, &foo)) ;
/* eat exposes for other windows */
eatExpose();
event.xexpose.count = 0;
XPutBackEvent(dpy, &event);
}
}
void SlideWindow(Window win, int from_x, int from_y, int to_x, int to_y)
{
time_t time0 = time(NULL);
float dx, dy, x = from_x, y = from_y, sx, sy, px, py;
int dx_is_bigger = 0;
int slide_delay, slide_steps, slide_slowdown;
/* animation parameters */
static struct {
int delay;
int steps;
int slowdown;
} apars[5] = {
{ICON_SLIDE_DELAY_UF, ICON_SLIDE_STEPS_UF, ICON_SLIDE_SLOWDOWN_UF},
{ICON_SLIDE_DELAY_F, ICON_SLIDE_STEPS_F, ICON_SLIDE_SLOWDOWN_F},
{ICON_SLIDE_DELAY_M, ICON_SLIDE_STEPS_M, ICON_SLIDE_SLOWDOWN_M},
{ICON_SLIDE_DELAY_S, ICON_SLIDE_STEPS_S, ICON_SLIDE_SLOWDOWN_S},
{ICON_SLIDE_DELAY_US, ICON_SLIDE_STEPS_US, ICON_SLIDE_SLOWDOWN_US}
};
slide_slowdown = apars[(int)wPreferences.icon_slide_speed].slowdown;
slide_steps = apars[(int)wPreferences.icon_slide_speed].steps;
slide_delay = apars[(int)wPreferences.icon_slide_speed].delay;
dx = (float)(to_x - from_x);
dy = (float)(to_y - from_y);
sx = (dx == 0 ? 0 : fabs(dx) / dx);
sy = (dy == 0 ? 0 : fabs(dy) / dy);
if (fabs(dx) > fabs(dy)) {
dx_is_bigger = 1;
}
if (dx_is_bigger) {
px = dx / slide_slowdown;
if (px < slide_steps && px > 0)
px = slide_steps;
else if (px > -slide_steps && px < 0)
px = -slide_steps;
py = (sx == 0 ? 0 : px * dy / dx);
} else {
py = dy / slide_slowdown;
if (py < slide_steps && py > 0)
py = slide_steps;
else if (py > -slide_steps && py < 0)
py = -slide_steps;
px = (sy == 0 ? 0 : py * dx / dy);
}
while (x != to_x || y != to_y) {
x += px;
y += py;
if ((px < 0 && (int)x < to_x) || (px > 0 && (int)x > to_x))
x = (float)to_x;
if ((py < 0 && (int)y < to_y) || (py > 0 && (int)y > to_y))
y = (float)to_y;
if (dx_is_bigger) {
px = px * (1.0 - 1 / (float)slide_slowdown);
if (px < slide_steps && px > 0)
px = slide_steps;
else if (px > -slide_steps && px < 0)
px = -slide_steps;
py = (sx == 0 ? 0 : px * dy / dx);
} else {
py = py * (1.0 - 1 / (float)slide_slowdown);
if (py < slide_steps && py > 0)
py = slide_steps;
else if (py > -slide_steps && py < 0)
py = -slide_steps;
px = (sy == 0 ? 0 : py * dx / dy);
}
XMoveWindow(dpy, win, (int)x, (int)y);
XFlush(dpy);
if (slide_delay > 0) {
wusleep(slide_delay * 1000L);
} else {
wusleep(10);
}
if (time(NULL) - time0 > MAX_ANIMATION_TIME)
break;
}
XMoveWindow(dpy, win, to_x, to_y);
XSync(dpy, 0);
/* compress expose events */
eatExpose();
}
char *ShrinkString(WMFont * font, char *string, int width)
{
int w, w1 = 0;
int p;
char *pos;
char *text;
int p1, p2, t;
p = strlen(string);
w = WMWidthOfString(font, string, p);
text = wmalloc(strlen(string) + 8);
strcpy(text, string);
if (w <= width)
return text;
pos = strchr(text, ' ');
if (!pos)
pos = strchr(text, ':');
if (pos) {
*pos = 0;
p = strlen(text);
w1 = WMWidthOfString(font, text, p);
if (w1 > width) {
w1 = 0;
p = 0;
*pos = ' ';
*text = 0;
} else {
*pos = 0;
width -= w1;
p++;
}
string += p;
p = strlen(string);
} else {
*text = 0;
}
strcat(text, "...");
width -= WMWidthOfString(font, "...", 3);
pos = string;
p1 = 0;
p2 = p;
t = (p2 - p1) / 2;
while (p2 > p1 && p1 != t) {
w = WMWidthOfString(font, &string[p - t], t);
if (w > width) {
p2 = t;
t = p1 + (p2 - p1) / 2;
} else if (w < width) {
p1 = t;
t = p1 + (p2 - p1) / 2;
} else
p2 = p1 = t;
}
strcat(text, &string[p - p1]);
return text;
}
char *FindImage(char *paths, char *file)
{
char *tmp, *path;
tmp = strrchr(file, ':');
if (tmp) {
*tmp = 0;
path = wfindfile(paths, file);
*tmp = ':';
}
if (!tmp || !path) {
path = wfindfile(paths, file);
}
return path;
}
static void timeoutHandler(void *data)
{
*(int *)data = 1;
}
static char *getTextSelection(WScreen * screen, Atom selection)
{
int buffer = -1;
switch (selection) {
case XA_CUT_BUFFER0:
buffer = 0;
break;
case XA_CUT_BUFFER1:
buffer = 1;
break;
case XA_CUT_BUFFER2:
buffer = 2;
break;
case XA_CUT_BUFFER3:
buffer = 3;
break;
case XA_CUT_BUFFER4:
buffer = 4;
break;
case XA_CUT_BUFFER5:
buffer = 5;
break;
case XA_CUT_BUFFER6:
buffer = 6;
break;
case XA_CUT_BUFFER7:
buffer = 7;
break;
}
if (buffer >= 0) {
char *data;
int size;
data = XFetchBuffer(dpy, &size, buffer);
return data;
} else {
char *data;
int bits;
Atom rtype;
unsigned long len, bytes;
WMHandlerID timer;
int timeout = 0;
XEvent ev;
static Atom clipboard = 0;
if (!clipboard)
clipboard = XInternAtom(dpy, "CLIPBOARD", False);
XDeleteProperty(dpy, screen->info_window, clipboard);
XConvertSelection(dpy, selection, XA_STRING, clipboard, screen->info_window, CurrentTime);
timer = WMAddTimerHandler(1000, timeoutHandler, &timeout);
while (!XCheckTypedWindowEvent(dpy, screen->info_window, SelectionNotify, &ev) && !timeout) ;
if (!timeout) {
WMDeleteTimerHandler(timer);
} else {
wwarning("selection retrieval timed out");
return NULL;
}
/* nobody owns the selection or the current owner has
* nothing to do with what we need */
if (ev.xselection.property == None) {
return NULL;
}
if (XGetWindowProperty(dpy, screen->info_window,
clipboard, 0, 1024,
False, XA_STRING, &rtype, &bits, &len,
&bytes, (unsigned char **)&data) != Success) {
return NULL;
}
if (rtype != XA_STRING || bits != 8) {
wwarning("invalid data in text selection");
if (data)
XFree(data);
return NULL;
}
return data;
}
}
static char *getselection(WScreen * scr)
{
char *tmp;
tmp = getTextSelection(scr, XA_PRIMARY);
if (!tmp)
tmp = getTextSelection(scr, XA_CUT_BUFFER0);
return tmp;
}
static char*
parseuserinputpart(char *line, int *ptr, char *endchars)
{
int depth = 0, begin;
char *value = NULL;
begin = ++*ptr;
while(line[*ptr] != '\0') {
if(line[*ptr] == '(') {
++depth;
} else if(depth > 0 && line[*ptr] == ')') {
--depth;
} else if(depth == 0 && strchr(endchars, line[*ptr]) != NULL) {
value = wmalloc(*ptr - begin + 1);
strncpy(value, line + begin, *ptr - begin);
value[*ptr - begin] = '\0';
break;
}
++*ptr;
}
return value;
}
static char*
getuserinput(WScreen *scr, char *line, int *ptr, Bool advanced)
{
char *ret = NULL, *title = NULL, *prompt = NULL, *name = NULL;
int rv;
if(line[*ptr] == '(')
title = parseuserinputpart(line, ptr, ",)");
if(title != NULL && line[*ptr] == ',')
prompt = parseuserinputpart(line, ptr, ",)");
if(prompt != NULL && line[*ptr] == ',')
name = parseuserinputpart(line, ptr, ")");
if(advanced)
rv = wAdvancedInputDialog(scr,
title ? gettext(title):_("Program Arguments"),
prompt ? gettext(prompt):_("Enter command arguments:"),
name, &ret);
else
rv = wInputDialog(scr,
title ? gettext(title):_("Program Arguments"),
prompt ? gettext(prompt):_("Enter command arguments:"),
&ret);
if(title) wfree(title);
if(prompt) wfree(prompt);
if(name) wfree(name);
return rv ? ret : NULL;
}
#define S_NORMAL 0
#define S_ESCAPE 1
#define S_OPTION 2
/*
* state input new-state output
* NORMAL % OPTION <nil>
* NORMAL \ ESCAPE <nil>
* NORMAL etc. NORMAL <input>
* ESCAPE any NORMAL <input>
* OPTION s NORMAL <selection buffer>
* OPTION w NORMAL <selected window id>
* OPTION a NORMAL <input text>
* OPTION d NORMAL <OffiX DND selection object>
* OPTION W NORMAL <current workspace>
* OPTION etc. NORMAL %<input>
*/
#define TMPBUFSIZE 64
char *ExpandOptions(WScreen * scr, char *cmdline)
{
int ptr, optr, state, len, olen;
char *out, *nout;
char *selection = NULL;
char *user_input = NULL;
#ifdef XDND
char *dropped_thing = NULL;
#endif
char tmpbuf[TMPBUFSIZE];
int slen;
len = strlen(cmdline);
olen = len + 1;
out = malloc(olen);
if (!out) {
wwarning(_("out of memory during expansion of \"%s\""));
return NULL;
}
*out = 0;
ptr = 0; /* input line pointer */
optr = 0; /* output line pointer */
state = S_NORMAL;
while (ptr < len) {
switch (state) {
case S_NORMAL:
switch (cmdline[ptr]) {
case '\\':
state = S_ESCAPE;
break;
case '%':
state = S_OPTION;
break;
default:
state = S_NORMAL;
out[optr++] = cmdline[ptr];
break;
}
break;
case S_ESCAPE:
switch (cmdline[ptr]) {
case 'n':
out[optr++] = 10;
break;
case 'r':
out[optr++] = 13;
break;
case 't':
out[optr++] = 9;
break;
default:
out[optr++] = cmdline[ptr];
}
state = S_NORMAL;
break;
case S_OPTION:
state = S_NORMAL;
switch (cmdline[ptr]) {
case 'w':
if (scr->focused_window && scr->focused_window->flags.focused) {
snprintf(tmpbuf, sizeof(tmpbuf), "0x%x",
(unsigned int)scr->focused_window->client_win);
slen = strlen(tmpbuf);
olen += slen;
nout = realloc(out, olen);
if (!nout) {
wwarning(_("out of memory during expansion of \"%w\""));
goto error;
}
out = nout;
strcat(out, tmpbuf);
optr += slen;
} else {
out[optr++] = ' ';
}
break;
case 'W':
snprintf(tmpbuf, sizeof(tmpbuf), "0x%x", (unsigned int)scr->current_workspace + 1);
slen = strlen(tmpbuf);
olen += slen;
nout = realloc(out, olen);
if (!nout) {
wwarning(_("out of memory during expansion of \"%W\""));
goto error;
}
out = nout;
strcat(out, tmpbuf);
optr += slen;
break;
case 'a':
case 'A':
ptr++;
user_input = getuserinput(scr, cmdline, &ptr, cmdline[ptr-1] == 'A');
if (user_input) {
slen = strlen(user_input);
olen += slen;
nout = realloc(out, olen);
if (!nout) {
wwarning(_("out of memory during expansion of \"%a\""));
goto error;
}
out = nout;
strcat(out, user_input);
optr += slen;
} else {
/* Not an error, but user has Canceled the dialog box.
* This will make the command to not be performed. */
goto error;
}
break;
#ifdef XDND
case 'd':
if (scr->xdestring) {
dropped_thing = wstrdup(scr->xdestring);
}
if (!dropped_thing) {
dropped_thing = get_dnd_selection(scr);
}
if (!dropped_thing) {
scr->flags.dnd_data_convertion_status = 1;
goto error;
}
slen = strlen(dropped_thing);
olen += slen;
nout = realloc(out, olen);
if (!nout) {
wwarning(_("out of memory during expansion of \"%d\""));
goto error;
}
out = nout;
strcat(out, dropped_thing);
optr += slen;
break;
#endif /* XDND */
case 's':
if (!selection) {
selection = getselection(scr);
}
if (!selection) {
wwarning(_("selection not available"));
goto error;
}
slen = strlen(selection);
olen += slen;
nout = realloc(out, olen);
if (!nout) {
wwarning(_("out of memory during expansion of \"%s\""));
goto error;
}
out = nout;
strcat(out, selection);
optr += slen;
break;
default:
out[optr++] = '%';
out[optr++] = cmdline[ptr];
}
break;
}
out[optr] = 0;
ptr++;
}
if (selection)
XFree(selection);
return out;
error:
wfree(out);
if (selection)
XFree(selection);
return NULL;
}
void ParseWindowName(WMPropList * value, char **winstance, char **wclass, char *where)
{
char *name;
*winstance = *wclass = NULL;
if (!WMIsPLString(value)) {
wwarning(_("bad window name value in %s state info"), where);
return;
}
name = WMGetFromPLString(value);
if (!name || strlen(name) == 0) {
wwarning(_("bad window name value in %s state info"), where);
return;
}
UnescapeWM_CLASS(name, winstance, wclass);
}
#if 0
static char *keysymToString(KeySym keysym, unsigned int state)
{
XKeyEvent kev;
char *buf = wmalloc(20);
int count;
kev.display = dpy;
kev.type = KeyPress;
kev.send_event = False;
kev.window = DefaultRootWindow(dpy);
kev.root = DefaultRootWindow(dpy);
kev.same_screen = True;
kev.subwindow = kev.root;
kev.serial = 0x12344321;
kev.time = CurrentTime;
kev.state = state;
kev.keycode = XKeysymToKeycode(dpy, keysym);
count = XLookupString(&kev, buf, 19, NULL, NULL);
buf[count] = 0;
return buf;
}
#endif
char *GetShortcutString(char *text)
{
char *buffer = NULL;
char *k;
int modmask = 0;
/* KeySym ksym; */
int control = 0;
char *tmp;
tmp = text = wstrdup(text);
/* get modifiers */
while ((k = strchr(text, '+')) != NULL) {
int mod;
*k = 0;
mod = wXModifierFromKey(text);
if (mod < 0) {
return wstrdup("bug");
}
modmask |= mod;
if (strcasecmp(text, "Meta") == 0) {
buffer = wstrappend(buffer, "M+");
} else if (strcasecmp(text, "Alt") == 0) {
buffer = wstrappend(buffer, "A+");
} else if (strcasecmp(text, "Shift") == 0) {
buffer = wstrappend(buffer, "Sh+");
} else if (strcasecmp(text, "Mod1") == 0) {
buffer = wstrappend(buffer, "M1+");
} else if (strcasecmp(text, "Mod2") == 0) {
buffer = wstrappend(buffer, "M2+");
} else if (strcasecmp(text, "Mod3") == 0) {
buffer = wstrappend(buffer, "M3+");
} else if (strcasecmp(text, "Mod4") == 0) {
buffer = wstrappend(buffer, "M4+");
} else if (strcasecmp(text, "Mod5") == 0) {
buffer = wstrappend(buffer, "M5+");
} else if (strcasecmp(text, "Control") == 0) {
control = 1;
} else {
buffer = wstrappend(buffer, text);
}
text = k + 1;
}
if (control) {
buffer = wstrappend(buffer, "^");
}
buffer = wstrappend(buffer, text);
/* get key */
/* ksym = XStringToKeysym(text);
tmp = keysymToString(ksym, modmask);
puts(tmp);
buffer = wstrappend(buffer, tmp);
*/
wfree(tmp);
return buffer;
}
char *EscapeWM_CLASS(char *name, char *class)
{
char *ret;
char *ename = NULL, *eclass = NULL;
int i, j, l;
if (!name && !class)
return NULL;
if (name) {
l = strlen(name);
ename = wmalloc(l * 2 + 1);
j = 0;
for (i = 0; i < l; i++) {
if (name[i] == '\\') {
ename[j++] = '\\';
} else if (name[i] == '.') {
ename[j++] = '\\';
}
ename[j++] = name[i];
}
ename[j] = 0;
}
if (class) {
l = strlen(class);
eclass = wmalloc(l * 2 + 1);
j = 0;
for (i = 0; i < l; i++) {
if (class[i] == '\\') {
eclass[j++] = '\\';
} else if (class[i] == '.') {
eclass[j++] = '\\';
}
eclass[j++] = class[i];
}
eclass[j] = 0;
}
if (ename && eclass) {
int len = strlen(ename) + strlen(eclass) + 4;
ret = wmalloc(len);
snprintf(ret, len, "%s.%s", ename, eclass);
wfree(ename);
wfree(eclass);
} else if (ename) {
ret = wstrdup(ename);
wfree(ename);
} else {
ret = wstrdup(eclass);
wfree(eclass);
}
return ret;
}
void UnescapeWM_CLASS(char *str, char **name, char **class)
{
int i, j, k, dot;
j = strlen(str);
*name = wmalloc(j);
**name = 0;
*class = wmalloc(j);
**class = 0;
/* separate string in 2 parts */
dot = -1;
for (i = 0; i < j; i++) {
if (str[i] == '\\') {
i++;
continue;
} else if (str[i] == '.') {
dot = i;
break;
}
}
/* unescape strings */
for (i = 0, k = 0; i < dot; i++) {
if (str[i] == '\\') {
continue;
} else {
(*name)[k++] = str[i];
}
}
(*name)[k] = 0;
for (i = dot + 1, k = 0; i < j; i++) {
if (str[i] == '\\') {
continue;
} else {
(*class)[k++] = str[i];
}
}
(*class)[k] = 0;
if (!*name) {
wfree(*name);
*name = NULL;
}
if (!*class) {
wfree(*class);
*class = NULL;
}
}
void SendHelperMessage(WScreen * scr, char type, int workspace, char *msg)
{
char *buffer;
int len;
int i;
char buf[16];
if (!scr->flags.backimage_helper_launched) {
return;
}
len = (msg ? strlen(msg) : 0) + (workspace >= 0 ? 4 : 0) + 1;
buffer = wmalloc(len + 5);
snprintf(buf, sizeof(buf), "%4i", len);
memcpy(buffer, buf, 4);
buffer[4] = type;
i = 5;
if (workspace >= 0) {
snprintf(buf, sizeof(buf), "%4i", workspace);
memcpy(&buffer[i], buf, 4);
i += 4;
buffer[i] = 0;
}
if (msg)
strcpy(&buffer[i], msg);
if (write(scr->helper_fd, buffer, len + 4) < 0) {
wsyserror(_("could not send message to background image helper"));
}
wfree(buffer);
}
Bool UpdateDomainFile(WDDomain * domain)
{
struct stat stbuf;
char path[PATH_MAX];
WMPropList *shared_dict, *dict;
Bool result, freeDict = False;
dict = domain->dictionary;
if (WMIsPLDictionary(domain->dictionary)) {
/* retrieve global system dictionary */
snprintf(path, sizeof(path), "%s/WindowMaker/%s", SYSCONFDIR, domain->domain_name);
if (stat(path, &stbuf) >= 0) {
shared_dict = WMReadPropListFromFile(path);
if (shared_dict) {
if (WMIsPLDictionary(shared_dict)) {
freeDict = True;
dict = WMDeepCopyPropList(domain->dictionary);
WMSubtractPLDictionaries(dict, shared_dict, True);
}
WMReleasePropList(shared_dict);
}
}
}
result = WMWritePropListToFile(dict, domain->path, True);
if (freeDict) {
WMReleasePropList(dict);
}
return result;
}
char *StrConcatDot(char *a, char *b)
{
int len;
char *str;
if (!a)
a = "";
if (!b)
b = "";
len = strlen(a) + strlen(b) + 4;
str = wmalloc(len);
snprintf(str, len, "%s.%s", a, b);
return str;
}
#define MAX_CMD_SIZE 4096
Bool GetCommandForPid(int pid, char ***argv, int *argc)
{
static char buf[MAX_CMD_SIZE];
FILE *fPtr;
int count, i, j;
Bool ok = False;
sprintf(buf, "/proc/%d/cmdline", pid);
fPtr = fopen(buf, "r");
if (fPtr) {
count = read(fileno(fPtr), buf, MAX_CMD_SIZE);
if (count > 0) {
buf[count - 1] = 0;
for (i = 0, *argc = 0; i < count; i++) {
if (buf[i] == 0) {
(*argc)++;
}
}
if ((*argc) == 0) {
*argv = NULL;
ok = False;
} else {
*argv = (char **)wmalloc(sizeof(char *) * (*argc));
(*argv)[0] = buf;
for (i = 0, j = 1; i < count; i++) {
if (buf[i] != 0)
continue;
if (i < count - 1) {
(*argv)[j++] = &buf[i + 1];
}
if (j == *argc) {
break;
}
}
ok = True;
}
}
fclose(fPtr);
}
return ok;
}
static char *getCommandForWindow(Window win, int elements)
{
char **argv, *command = NULL;
int argc;
if (XGetCommand(dpy, win, &argv, &argc)) {
if (argc > 0 && argv != NULL) {
if (elements == 0)
elements = argc;
command = wtokenjoin(argv, WMIN(argc, elements));
if (command[0] == 0) {
wfree(command);
command = NULL;
}
}
if (argv) {
XFreeStringList(argv);
}
}
return command;
}
/* Free result when done */
char *GetCommandForWindow(Window win)
{
return getCommandForWindow(win, 0);
}
/* Free result when done */
char *GetProgramNameForWindow(Window win)
{
return getCommandForWindow(win, 1);
}