1
0
mirror of https://github.com/gryf/wmaker.git synced 2026-01-09 23:34:14 +01:00

Spice up setstyle

- convert to getopt
- tidy xsendevent
- modify hackPathInTexture() so that:
  - it properly figures where the style file is
  - if it's under the user's home directory, that part of the path
    is changed to `~' - this makes your wm configuration usable on
    systems with a network home, used on systems where home is /home,
    or /u, or /export/home, or whatever.

XXX: there's a note WINGs/findfile.c:wexpandpath() stating that
`too many functions handle a return value of NULL incorrectly'. this is
so true. so if anyone is looking for a small project to sink their
teeth in...
This commit is contained in:
Tamas TEVESZ
2010-04-01 03:32:14 +02:00
committed by Carlos R. Mafra
parent 1bc042c172
commit 859338fd83

View File

@@ -22,12 +22,20 @@
#define PROG_VERSION "setstyle (Window Maker) 0.6"
#include <stdlib.h>
#include <stdio.h>
#ifdef __GLIBC__
#define _GNU_SOURCE /* getopt_long */
#endif
#include <sys/stat.h>
#include <unistd.h>
#include <getopt.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <WINGs/WUtil.h>
#include "../src/wconfig.h"
@@ -97,6 +105,12 @@ static Bool isFontOption(char *option)
return False;
}
/*
* finds elements in `texture' that reference external files,
* prepends `prefix' to these files. `prefix' is a path component
* that qualifies the external references to be absolute, possibly
* pending further expansion
*/
void hackPathInTexture(WMPropList * texture, char *prefix)
{
WMPropList *type;
@@ -107,12 +121,14 @@ void hackPathInTexture(WMPropList * texture, char *prefix)
t = WMGetFromPLString(type);
if (t == NULL)
return;
if (strcasecmp(t, "tpixmap") == 0
|| strcasecmp(t, "spixmap") == 0
|| strcasecmp(t, "mpixmap") == 0
|| strcasecmp(t, "cpixmap") == 0
|| strcasecmp(t, "tvgradient") == 0
|| strcasecmp(t, "thgradient") == 0 || strcasecmp(t, "tdgradient") == 0) {
if (strcasecmp(t, "tpixmap") == 0 ||
strcasecmp(t, "spixmap") == 0 ||
strcasecmp(t, "mpixmap") == 0 ||
strcasecmp(t, "cpixmap") == 0 ||
strcasecmp(t, "tvgradient") == 0 ||
strcasecmp(t, "thgradient") == 0 ||
strcasecmp(t, "tdgradient") == 0) {
WMPropList *file;
char buffer[4018];
@@ -122,6 +138,7 @@ void hackPathInTexture(WMPropList * texture, char *prefix)
/* replace path with full path */
WMDeleteFromPLArray(texture, 1);
WMInsertInPLArray(texture, 1, WMCreatePLString(buffer));
} else if (strcasecmp(t, "bitmap") == 0) {
WMPropList *file;
char buffer[4018];
@@ -334,16 +351,19 @@ void hackStyle(WMPropList * style)
}
}
void print_help()
void print_help(int print_usage, int exitval)
{
printf("Usage: %s [OPTIONS] FILE\n", __progname);
puts("Reads style/theme configuration from FILE and updates Window Maker.");
puts("");
puts(" --no-fonts ignore font related options");
puts(" --no-cursors ignore cursor related options");
puts(" --ignore <option> ignore changes in the specified option");
puts(" -h, --help display this help and exit");
puts(" -v, --version output version information and exit");
if (print_usage) {
puts("Reads style/theme configuration from FILE and updates Window Maker.");
puts("");
puts(" --no-fonts ignore font related options");
puts(" --no-cursors ignore cursor related options");
puts(" --ignore <option> ignore changes in the specified option");
puts(" -h, --help display this help and exit");
puts(" -v, --version output version information and exit");
}
exit(exitval);
}
int main(int argc, char **argv)
@@ -351,47 +371,52 @@ int main(int argc, char **argv)
WMPropList *prop, *style;
char *path;
char *file = NULL;
struct stat statbuf;
int i;
struct stat st;
int i, ch, ignflag = 0;
int ignoreCount = 0;
char *ignoreList[MAX_OPTIONS];
XEvent ev;
dpy = XOpenDisplay("");
struct option longopts[] = {
{ "version", no_argument, NULL, 'v' },
{ "help", no_argument, NULL, 'h' },
{ "no-fonts", no_argument, &ignoreFonts, 1 },
{ "no-cursors", no_argument, &ignoreCursors, 1 },
{ "ignore", required_argument, &ignflag, 1 },
{ NULL, 0, NULL, 0 }
};
if (argc < 2) {
printf("%s: missing argument\n", __progname);
printf("Try '%s --help' for more information\n", __progname);
exit(1);
}
for (i = 1; i < argc; i++) {
if (strcmp("--ignore", argv[i]) == 0) {
i++;
if (i == argc) {
printf("%s: missing argument for option --ignore\n", __progname);
exit(1);
}
ignoreList[ignoreCount++] = argv[i];
} else if (strcmp("--no-fonts", argv[i]) == 0) {
ignoreFonts = 1;
} else if (strcmp("--no-cursors", argv[i]) == 0) {
ignoreCursors = 1;
} else if (strcmp("-v", argv[i]) == 0 || strcmp("--version", argv[i]) == 0) {
puts(PROG_VERSION);
exit(0);
} else if (strcmp("-h", argv[i]) == 0 || strcmp("--help", argv[i]) == 0) {
print_help();
exit(0);
} else {
if (file) {
printf("%s: invalid argument '%s'\n", __progname, argv[i]);
printf("Try '%s --help' for more information\n", __progname);
exit(1);
}
file = argv[i];
while ((ch = getopt_long(argc, argv, "hv", longopts, NULL)) != -1)
switch(ch) {
case 'v':
puts(PROG_VERSION);
return 0;
/* NOTREACHED */
case 'h':
print_help(1, 0);
/* NOTREACHED */
case 0:
if (ignflag) {
if (ignoreCount >= MAX_OPTIONS) {
printf("Maximum %d `ignore' arguments\n", MAX_OPTIONS);
return 1;
}
ignoreList[ignoreCount++] = optarg;
ignflag = 0;
};
break;
default:
print_help(0, 1);
/* NOTREACHED */
}
}
argc -= optind;
argv += optind;
if (argc != 1)
print_help(0, 1);
file = argv[0];
WMPLSetCaseSensitive(False);
@@ -401,65 +426,62 @@ int main(int argc, char **argv)
if (!prop) {
perror(path);
printf("%s: could not load WindowMaker configuration file.\n", __progname);
exit(1);
return 1;
}
if (stat(file, &statbuf) < 0) {
if (stat(file, &st) < 0) {
perror(file);
exit(1);
return 1;
}
if (S_ISDIR(statbuf.st_mode)) {
char buffer[4018];
char *prefix;
/* theme pack */
if (S_ISDIR(st.st_mode)) { /* theme pack */
char buf[PATH_MAX];
char *homedir;
if (*argv[argc - 1] != '/') {
if (!getcwd(buffer, 4000)) {
printf("%s: complete path for %s is too long\n", __progname, file);
exit(1);
}
if (strlen(buffer) + strlen(file) > 4000) {
printf("%s: complete path for %s is too long\n", __progname, file);
exit(1);
}
strcat(buffer, "/");
} else {
buffer[0] = 0;
if (realpath(file, buf) == NULL) {
perror(file);
return 1;
}
strcat(buffer, file);
strncat(buf, "/style", sizeof(buf) - strlen(buf) - 1);
prefix = malloc(strlen(buffer) + 10);
if (!prefix) {
printf("%s: out of memory\n", __progname);
exit(1);
if (stat(buf, &st) != 0 || !S_ISREG(st.st_mode)) { /* maybe symlink too? */
printf("%s: %s: style file not found or not a file\n", __progname, buf);
return 1;
}
strcpy(prefix, buffer);
strcat(buffer, "/style");
style = WMReadPropListFromFile(buffer);
style = WMReadPropListFromFile(buf);
if (!style) {
perror(buffer);
perror(buf);
printf("%s: could not load style file.\n", __progname);
exit(1);
return 1;
}
hackPaths(style, prefix);
free(prefix);
} else {
/* normal style file */
buf[strlen(buf) - 6 /* strlen("/style") */] = '\0';
homedir = wstrdup(wgethomedir());
if (strlen(homedir) > 1 && /* this is insane, wgethomedir() returns `/' on error */
strncmp(homedir, buf, strlen(homedir)) == 0) {
/* theme pack is under ${HOME}; exchange ${HOME} part
* for `~' so it gets portable references to the user home dir */
*buf = '~';
memmove(buf + 1, buf + strlen(homedir), strlen(buf) - strlen(homedir) + 1);
}
wfree(homedir);
hackPaths(style, buf); /* this will prefix pixmaps in the style
* with absolute(ish) references */
} else { /* normal style file */
style = WMReadPropListFromFile(file);
if (!style) {
perror(file);
printf("%s:could not load style file.\n", __progname);
exit(1);
return 1;
}
}
if (!WMIsPLDictionary(style)) {
printf("%s: '%s' is not a style file/theme\n", __progname, file);
exit(1);
return 1;
}
hackStyle(style);
@@ -473,27 +495,20 @@ int main(int argc, char **argv)
WMMergePLDictionaries(prop, style, True);
WMWritePropListToFile(prop, path);
{
XEvent ev;
if (dpy) {
int i;
char *msg = "Reconfigure";
dpy = XOpenDisplay("");
if (dpy) {
memset(&ev, 0, sizeof(XEvent));
memset(&ev, 0, sizeof(XEvent));
ev.xclient.type = ClientMessage;
ev.xclient.message_type = XInternAtom(dpy, "_WINDOWMAKER_COMMAND", False);
ev.xclient.window = DefaultRootWindow(dpy);
ev.xclient.format = 8;
strncpy(ev.xclient.data.b, "Reconfigure", sizeof(ev.xclient.data.b));
ev.xclient.type = ClientMessage;
ev.xclient.message_type = XInternAtom(dpy, "_WINDOWMAKER_COMMAND", False);
ev.xclient.window = DefaultRootWindow(dpy);
ev.xclient.format = 8;
for (i = 0; i <= strlen(msg); i++) {
ev.xclient.data.b[i] = msg[i];
}
XSendEvent(dpy, DefaultRootWindow(dpy), False, SubstructureRedirectMask, &ev);
XFlush(dpy);
}
XSendEvent(dpy, DefaultRootWindow(dpy), False, SubstructureRedirectMask, &ev);
XFlush(dpy);
}
exit(0);
return 0;
}