summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/cwm/Makefile9
-rw-r--r--app/cwm/calmwm.c25
-rw-r--r--app/cwm/calmwm.h54
-rw-r--r--app/cwm/conf.c293
-rw-r--r--app/cwm/cwm.1133
-rw-r--r--app/cwm/cwmrc28
-rw-r--r--app/cwm/cwmrc.5158
-rw-r--r--app/cwm/group.c8
-rw-r--r--app/cwm/kbfunc.c10
-rw-r--r--app/cwm/parse.y583
-rw-r--r--app/cwm/xevents.c7
11 files changed, 878 insertions, 430 deletions
diff --git a/app/cwm/Makefile b/app/cwm/Makefile
index fa1c08eaa..4d5e39a67 100644
--- a/app/cwm/Makefile
+++ b/app/cwm/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.4 2008/01/08 20:21:43 oga Exp $
+# $OpenBSD: Makefile,v 1.5 2008/03/23 15:09:21 simon Exp $
.include <bsd.own.mk>
@@ -8,16 +8,17 @@ PROG= cwm
SRCS= calmwm.c screen.c xmalloc.c client.c grab.c search.c \
util.c xutil.c conf.c input.c xevents.c group.c \
- kbfunc.c font.c
+ kbfunc.c font.c parse.y
-CPPFLAGS+= -I${X11BASE}/include -I${X11BASE}/include/freetype2
+CPPFLAGS+= -I${X11BASE}/include -I${X11BASE}/include/freetype2 -I${.CURDIR}
LDADD+= -L${X11BASE}/lib -lXft -lXrender -lX11 -lXau -lXdmcp \
-lfontconfig -lexpat -lfreetype -lz -lX11 -lXau -lXdmcp -lXext
MANDIR= ${X11BASE}/man/cat
+MAN= cwm.1 cwmrc.5
-CLEANFILES= cwm.cat1
+CLEANFILES= cwm.cat1 cwmrc.cat5
obj: _xenocara_obj
diff --git a/app/cwm/calmwm.c b/app/cwm/calmwm.c
index 680acb4c1..123bdcc97 100644
--- a/app/cwm/calmwm.c
+++ b/app/cwm/calmwm.c
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: calmwm.c,v 1.12 2008/03/22 15:09:45 oga Exp $
+ * $Id: calmwm.c,v 1.13 2008/03/23 15:09:21 simon Exp $
*/
#include "headers.h"
@@ -38,8 +38,7 @@ struct client_ctx_q Clientq;
int Doshape, Shape_ev;
int Starting;
struct conf Conf;
-struct fontdesc *DefaultFont;
-char *DefaultFontName;
+struct fontdesc *DefaultFont = NULL;
/* From TWM */
#define gray_width 2
@@ -53,23 +52,18 @@ int
main(int argc, char **argv)
{
int ch;
- int conf_flags = 0;
+ const char *conffile = NULL;
char *display_name = NULL;
- DefaultFontName = "sans-serif:pixelsize=14:bold";
-
- while ((ch = getopt(argc, argv, "d:sf:")) != -1) {
+ while ((ch = getopt(argc, argv, "c:d:")) != -1) {
switch (ch) {
+ case 'c':
+ conffile = optarg;
+ break;
case 'd':
display_name = optarg;
break;
- case 's':
- conf_flags |= CONF_STICKY_GROUPS;
- break;
- case 'f':
- DefaultFontName = xstrdup(optarg);
- break;
default:
usage();
}
@@ -87,8 +81,7 @@ main(int argc, char **argv)
group_init();
Starting = 1;
- conf_setup(&Conf);
- Conf.flags |= conf_flags;
+ conf_setup(&Conf, conffile);
client_setup();
x_setup(display_name);
Starting = 0;
@@ -209,7 +202,7 @@ x_setupscreen(struct screen_ctx *sc, u_int which)
GCLineWidth|GCSubwindowMode, &gv);
font_init(sc);
- DefaultFont = font_getx(sc, DefaultFontName);
+ DefaultFont = font_getx(sc, Conf.DefaultFontName);
/*
* XXX - this should *really* be in screen_init(). ordering
diff --git a/app/cwm/calmwm.h b/app/cwm/calmwm.h
index b960ed8f5..024cabe17 100644
--- a/app/cwm/calmwm.h
+++ b/app/cwm/calmwm.h
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: calmwm.h,v 1.24 2008/03/22 15:09:45 oga Exp $
+ * $Id: calmwm.h,v 1.25 2008/03/23 15:09:21 simon Exp $
*/
#ifndef _CALMWM_H_
@@ -30,6 +30,8 @@
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#define MAX(x, y) ((x) > (y) ? (x) : (y))
+#define CONFFILE ".cwmrc"
+
enum conftype {
CONF_BWIDTH, CONF_IGNORE,
};
@@ -164,6 +166,12 @@ struct client_ctx {
TAILQ_HEAD(client_ctx_q, client_ctx);
+static char *shortcut_to_name[] = {
+ "XXX", "one", "two", "three",
+ "four", "five", "six", "seven",
+ "eight", "nine"
+};
+
struct group_ctx {
TAILQ_ENTRY(group_ctx) entry;
struct client_ctx_q clients;
@@ -204,6 +212,20 @@ enum directions {
CWM_UP=0, CWM_DOWN, CWM_LEFT, CWM_RIGHT,
};
+/*
+ * Match a window.
+ */
+#define CONF_MAX_WINTITLE 256
+#define CONF_IGNORECASE 0x01
+struct winmatch {
+ TAILQ_ENTRY(winmatch) entry;
+
+ char title[CONF_MAX_WINTITLE];
+ int opts;
+};
+
+TAILQ_HEAD(winmatch_q, winmatch);
+
/* for cwm_exec */
#define CWM_EXEC_PROGRAM 0x1
#define CWM_EXEC_WM 0x2
@@ -236,16 +258,20 @@ TAILQ_HEAD(cmd_q, cmd);
/* Global configuration */
struct conf {
- struct keybinding_q keybindingq;
- struct autogroupwin_q autogroupq;
- char menu_path[MAXPATHLEN];
- struct cmd_q cmdq;
+ struct keybinding_q keybindingq;
+ struct autogroupwin_q autogroupq;
+ struct winmatch_q ignoreq;
+ char conf_path[MAXPATHLEN];
+ struct cmd_q cmdq;
- int flags;
+ int flags;
#define CONF_STICKY_GROUPS 0x0001
- char termpath[MAXPATHLEN];
- char lockpath[MAXPATHLEN];
+ char termpath[MAXPATHLEN];
+ char lockpath[MAXPATHLEN];
+
+#define DEFAULTFONTNAME "sans-serif:pixelsize=14:bold"
+ char *DefaultFontName;
};
/* Menu stuff */
@@ -397,21 +423,15 @@ struct screen_ctx *screen_current(void);
void screen_updatestackingorder(void);
void screen_infomsg(char *);
-void conf_setup(struct conf *);
+void conf_setup(struct conf *, const char *);
int conf_get_int(struct client_ctx *, enum conftype);
void conf_client(struct client_ctx *);
void conf_bindkey(struct conf *, void (*)(struct client_ctx *, void *),
int, int, int, void *);
void conf_bindname(struct conf *, char *, char *);
void conf_unbind(struct conf *, struct keybinding *);
-void conf_parsekeys(struct conf *, char *);
-void conf_parsesettings(struct conf *, char *);
-void conf_parseignores(struct conf *, char *);
-void conf_parseautogroups(struct conf *, char *);
-void conf_cmd_clear(struct conf *);
-int conf_cmd_changed(char *);
-void conf_cmd_populate(struct conf *, char *);
-void conf_cmd_refresh(struct conf *c);
+int conf_changed(char *);
+void conf_reload(struct conf *c);
char *conf_get_str(struct client_ctx *, enum conftype);
void kbfunc_client_lower(struct client_ctx *, void *);
diff --git a/app/cwm/conf.c b/app/cwm/conf.c
index f31abc4b2..d446f294b 100644
--- a/app/cwm/conf.c
+++ b/app/cwm/conf.c
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: conf.c,v 1.22 2008/03/22 15:09:45 oga Exp $
+ * $Id: conf.c,v 1.23 2008/03/23 15:09:21 simon Exp $
*/
#include "headers.h"
@@ -28,58 +28,7 @@
((tsp)->tv_sec cmp (usp)->tv_sec))
#endif
-#define CONF_MAX_WINTITLE 256
-#define CONF_IGNORECASE 0x01
-
-
-/*
- * Match a window.
- */
-struct winmatch {
- TAILQ_ENTRY(winmatch) entry;
-
- char title[CONF_MAX_WINTITLE];
- int opts;
-};
-
-TAILQ_HEAD(winmatch_q, winmatch);
-struct winmatch_q ignoreq;
-
-/* XXX - until we get a real configuration parser. */
-#define WINMATCH_ADD(queue, str) do { \
- struct winmatch *wm; \
- XCALLOC(wm, struct winmatch); \
- strlcpy(wm->title, str, sizeof(wm->title)); \
- wm->opts |= CONF_IGNORECASE; \
- TAILQ_INSERT_TAIL(queue, wm, entry); \
-} while (0)
-
-/* Initializes the command menu */
-
-void
-conf_cmd_init(struct conf *c)
-{
- TAILQ_INIT(&c->cmdq);
-}
-
-/* Removes all static entries */
-
-void
-conf_cmd_clear(struct conf *c)
-{
- struct cmd *cmd, *next;
-
- for (cmd = TAILQ_FIRST(&c->cmdq); cmd != NULL; cmd = next) {
- next = TAILQ_NEXT(cmd, entry);
-
- /* Do not remove static entries */
- if (cmd->flags & CMD_STATIC)
- continue;
-
- TAILQ_REMOVE(&c->cmdq, cmd, entry);
- free(cmd);
- }
-}
+extern struct screen_ctx *Curscreen;
/* Add an command menu entry to the end of the menu */
void
@@ -102,94 +51,45 @@ conf_cmd_add(struct conf *c, char *image, char *label, int flags)
}
int
-conf_cmd_changed(char *path)
+conf_changed(char *path)
{
-#ifdef __OpenBSD__
static struct timespec old_ts;
-#else
- static time_t old_time;
-#endif
struct stat sb;
int changed;
- /* If the directory does not exist we pretend that nothing changed */
- if (stat(path, &sb) == -1 || !(sb.st_mode & S_IFDIR))
+ /* If the file does not exist we pretend that nothing changed */
+ if (stat(path, &sb) == -1 || !(sb.st_mode & S_IFREG))
return (0);
-#ifdef __OpenBSD__
changed = !timespeccmp(&sb.st_mtimespec, &old_ts, ==);
old_ts = sb.st_mtimespec;
-#else
- changed = old_time != sb.st_mtime;
- old_time = sb.st_mtime;
-#endif
return (changed);
}
void
-conf_cmd_populate(struct conf *c, char *path)
+conf_reload(struct conf *c)
{
- DIR *dir;
- struct dirent *file;
- char fullname[PATH_MAX];
- int off;
-
- if (strlen(path) >= sizeof (fullname) - 2)
- errx(1, "directory name too long");
-
- dir = opendir(path);
- if (dir == NULL)
- err(1, "opendir");
-
- strlcpy(fullname, path, sizeof (fullname));
- off = strlen(fullname);
- if (fullname[off - 1] != '/') {
- strlcat(fullname, "/", sizeof(fullname));
- off++;
- }
-
- while ((file = readdir(dir)) != NULL) {
- char *filename = file->d_name;
- if (filename[0] == '.')
- continue;
-
- strlcpy(fullname + off, filename, sizeof(fullname) - off);
-
- /* Add a dynamic entry to the command menu */
- conf_cmd_add(c, fullname, filename, 0);
- }
-
- closedir(dir);
-
-}
+ if (!conf_changed(c->conf_path))
+ return;
-void
-conf_cmd_refresh(struct conf *c)
-{
- if (!conf_cmd_changed(c->menu_path))
+ if (parse_config(c->conf_path, c) == -1) {
+ warnx("config file %s has errors, not reloading", c->conf_path);
return;
+ }
- conf_cmd_clear(c);
- conf_cmd_populate(c, c->menu_path);
+ DefaultFont = font_getx(Curscreen, c->DefaultFontName);
}
void
-conf_setup(struct conf *c)
+conf_init(struct conf *c)
{
- char dir_keydefs[MAXPATHLEN];
- char dir_settings[MAXPATHLEN];
- char dir_ignored[MAXPATHLEN];
- char dir_autogroup[MAXPATHLEN];
- char *home = getenv("HOME");
-
- if (home == NULL)
- errx(1, "No HOME directory.");
- snprintf(c->menu_path, sizeof(c->menu_path), "%s/.calmwm", home);
-
- conf_cmd_init(c);
+ c->flags = 0;
+ TAILQ_INIT(&c->ignoreq);
+ TAILQ_INIT(&c->cmdq);
TAILQ_INIT(&c->keybindingq);
+ TAILQ_INIT(&c->autogroupq);
conf_bindname(c, "CM-Return", "terminal");
conf_bindname(c, "CM-Delete", "lock");
@@ -247,39 +147,31 @@ conf_setup(struct conf *c)
conf_bindname(c, "CS-Up", "bigptrmoveup");
conf_bindname(c, "CS-Right", "bigptrmoveright");
- snprintf(dir_keydefs, sizeof(dir_keydefs), "%s/.calmwm/.keys", home);
- if (dirent_isdir(dir_keydefs))
- conf_parsekeys(c, dir_keydefs);
-
- snprintf(dir_settings, sizeof(dir_settings),
- "%s/.calmwm/.settings", home);
- if (dirent_isdir(dir_settings))
- conf_parsesettings(c, dir_settings);
-
- TAILQ_INIT(&ignoreq);
-
- snprintf(dir_ignored, sizeof(dir_ignored), "%s/.calmwm/.ignore", home);
- if (dirent_isdir(dir_ignored))
- conf_parseignores(c, dir_ignored);
- else {
- WINMATCH_ADD(&ignoreq, "XMMS");
- WINMATCH_ADD(&ignoreq, "xwi");
- WINMATCH_ADD(&ignoreq, "xapm");
- WINMATCH_ADD(&ignoreq, "xclock");
- }
+ /* Default term/lock */
+ strlcpy(c->termpath, "xterm", sizeof(c->termpath));
+ strlcpy(c->lockpath, "xlock", sizeof(c->lockpath));
- TAILQ_INIT(&c->autogroupq);
+ c->DefaultFontName = DEFAULTFONTNAME;
+}
+
+void
+conf_setup(struct conf *c, const char *conffile)
+{
+ if (conffile == NULL) {
+ char *home = getenv("HOME");
- snprintf(dir_autogroup, sizeof(dir_autogroup),
- "%s/.calmwm/.autogroup", home);
- if (dirent_isdir(dir_autogroup))
- conf_parseautogroups(c, dir_autogroup);
+ if (home == NULL)
+ errx(1, "No HOME directory.");
- c->flags = 0;
+ snprintf(c->conf_path, sizeof(c->conf_path), "%s/%s", home,
+ CONFFILE);
+ }
+ else
+ snprintf(c->conf_path, sizeof(c->conf_path), "%s", conffile);
- /* Default term/lock */
- strlcpy(Conf.termpath, "xterm", sizeof(Conf.termpath));
- strlcpy(Conf.lockpath, "xlock", sizeof(Conf.lockpath));
+ conf_init(c);
+
+ (void)parse_config(c->conf_path, c);
}
int
@@ -294,7 +186,7 @@ conf_get_int(struct client_ctx *cc, enum conftype ctype)
/* Can wname be NULL? */
if (wname != NULL) {
- TAILQ_FOREACH(wm, &ignoreq, entry) {
+ TAILQ_FOREACH(wm, &Conf.ignoreq, entry) {
int (*cmpfun)(const char *, const char *, size_t) =
wm->opts & CONF_IGNORECASE ? strncasecmp : strncmp;
if ((*cmpfun)(wm->title, wname, strlen(wm->title)) == 0) {
@@ -393,37 +285,6 @@ struct {
};
void
-conf_parsekeys(struct conf *c, char *filename)
-{
- DIR *dir;
- struct dirent *ent;
- char buffer[MAXPATHLEN];
- char current_file[MAXPATHLEN];
-
- dir = opendir(filename);
- while ((ent = readdir(dir)) != NULL) {
- if (ent->d_name[0] == '.')
- continue;
-
- snprintf(current_file, sizeof(current_file),
- "%s/%s", filename, ent->d_name);
- if (strchr(ent->d_name, '-') == NULL && ent->d_name[0] != '[')
- continue;
- if (!dirent_islink(current_file))
- continue;
-
-
- memset(buffer, 0, MAXPATHLEN);
- if (readlink(current_file, buffer, MAXPATHLEN) < 0)
- continue;
-
- conf_bindname(c, ent->d_name, buffer);
- }
-
- closedir(dir);
-}
-
-void
conf_bindname(struct conf *c, char *name, char *binding)
{
int iter;
@@ -518,79 +379,3 @@ void conf_unbind(struct conf *c, struct keybinding *unbind)
TAILQ_REMOVE(&c->keybindingq, key, entry);
}
}
-
-void
-conf_parsesettings(struct conf *c, char *filename)
-{
- DIR *dir;
- struct dirent *ent;
-
- dir = opendir(filename);
- while ((ent = readdir(dir)) != NULL) {
- if (ent->d_name[0] == '.')
- continue;
- if (strncmp(ent->d_name, "sticky", 7)==0)
- Conf.flags |= CONF_STICKY_GROUPS;
- }
- closedir(dir);
-}
-
-void
-conf_parseignores(struct conf *c, char *filename)
-{
- DIR *dir;
- struct dirent *ent;
-
- dir = opendir(filename);
- while ((ent = readdir(dir)) != NULL) {
- if (ent->d_name[0] == '.')
- continue;
- WINMATCH_ADD(&ignoreq, ent->d_name);
- }
-
- closedir(dir);
-}
-
-void
-conf_parseautogroups(struct conf *c, char *filename)
-{
- DIR *dir;
- struct dirent *ent;
- struct autogroupwin *aw;
- char current_file[MAXPATHLEN], *p;
- char group[CALMWM_MAXNAMELEN];
- int len;
-
- dir = opendir(filename);
- while ((ent = readdir(dir)) != NULL) {
- if (ent->d_name[0] == '.')
- continue;
-
- snprintf(current_file, sizeof(current_file),
- "%s/%s", filename, ent->d_name);
- if (!dirent_islink(current_file))
- continue;
-
- if ((len = readlink(current_file,
- group, sizeof(group) - 1)) < 0)
- continue;
- group[len] = '\0';
-
- XCALLOC(aw, struct autogroupwin);
-
- if ((p = strchr(ent->d_name, ',')) == NULL) {
- aw->name = NULL;
- aw->class = xstrdup(ent->d_name);
- } else {
- *(p++) = '\0';
- aw->name = xstrdup(ent->d_name);
- aw->class = xstrdup(p);
- }
- aw->group = xstrdup(group);
-
- TAILQ_INSERT_TAIL(&c->autogroupq, aw, entry);
- }
-
- closedir(dir);
-
-}
diff --git a/app/cwm/cwm.1 b/app/cwm/cwm.1
index 886978605..f2b735e5f 100644
--- a/app/cwm/cwm.1
+++ b/app/cwm/cwm.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: cwm.1,v 1.23 2008/03/22 15:09:45 oga Exp $
+.\" $OpenBSD: cwm.1,v 1.24 2008/03/23 15:09:21 simon Exp $
.\"
.\" Copyright (c) 2004,2005 Marius Aamodt Eriksen <marius@monkey.org>
.\"
@@ -15,7 +15,7 @@
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.\" The following requests are required for all man pages.
-.Dd June 29, 2007
+.Dd $Mdocdate: March 23 2008 $
.Dt CWM 1
.Os
.Sh NAME
@@ -24,9 +24,8 @@
.Sh SYNOPSIS
.\" For a program: program [-abc] file ...
.Nm cwm
-.Op Fl s
.Op Fl d Ar display
-.Op Fl f Ar fontname
+.Op Fl c Ar file
.Sh DESCRIPTION
.Nm
is a window manager for X11 which contains many features that
@@ -132,17 +131,9 @@ are as follows:
.Bl -tag -width Ds
.It Fl d Ar display
Specify the display to use.
-.It Fl f Ar fontname
-Makes the
-.Xr Xft 3
-font string
-.Ar fontname
-the default font.
-.It Fl s
-Set sticky group mode on.
-The default behavior for new windows is to not assign any group.
-This changes the default behavior to assigning the currently selected
-group to any newly created windows.
+.It Fl c Ar file
+Specify the config file to use. Defaults to
+.Pa ~/.cwmrc .
.El
.Sh POINTER MOVEMENT
The pointer can be moved with the use of the keyboard through bindings.
@@ -205,7 +196,7 @@ perform operations on the entire group instead of just one window.
Currently, the only operation that is supported is to hide and unhide
the grouped windows.
Together with the
-.Fl s
+.Pa sticky
option, this can be used to emulate virtual desktops.
.Pp
To edit groups, use the group selection commands to toggle membership
@@ -224,7 +215,7 @@ Show list of currently defined groups.
Clicking on an item will hide/unhide that group.
.It M3
Show list of applications as defined in
-.Pa ~/.calmwm .
+.Pa ~/.cwmrc .
Clicking on an item will spawn that application.
.El
.Sh ENVIRONMENT
@@ -237,111 +228,9 @@ option is given.
.El
.Sh FILES
.Bl -tag -width Ds
-.It Pa ~/.calmwm
-Any directory entries here are shown in the application menu.
-When it is selected, the image is executed with
-.Xr execve 2 .
-One use of this is to create symbolic links for your favorite
-applications in this directory using
-.Xr ln 1 .
-.Pp
-The entries
-.Nm term
-and
-.Nm lock
-have a special meaning.
-When they exist they point to the terminal program and screen locking
-programs used by the keybindings specified above.
-The defaults for these are
-.Xr xterm 1
-and
-.Xr xlock 1 ,
-respectively.
-.It Pa ~/.calmwm/.autogroup
-Symlinks in this directory are read upon startup and control the
-automatic grouping feature, which is based on the window name and class
-properties.
-To obtain the name and class of a window, use
-.Ql xprop WM_CLASS ,
-then click on the window.
-The first quoted string is the window name; the second one is the
-window class.
-.Pp
-The name of a link can be the window class, or the window class and name
-separated by a comma.
-The link target is a group name (one, two, \&..., nine).
-For example, to make all windows in the
-.Xr xterm 1
-class go to the third group:
-.Bd -literal -offset indent
-$ ln -s three ~/.calmwm/.autogroup/XTerm
-.Ed
-.It Pa ~/.calmwm/.settings
-Files in this directory cause various configuration options to be
-set or unset.
-Currently the only setting availiable is whether or not sticky groups
-are activated.
-To activate sticky groups create a file in this directory with the name
-``sticky''.
-.It Pa ~/.calmwm/.ignore
-Any files in this directory cause
-.Nm
-to ignore programs by that name by not drawing borders around them.
-For example the command
-.Bd -literal -offset indent
-$ ln -s three ~/.calmwm/.ignore/xclock
-.Ed
-will cause any instances of
-.Xr xclock 1
-to not have borders.
-.It Pa ~/.calmwm/.keys
-Symlinks in this directory cause the creation of keyboard shortcuts.
-The default shortcuts will always be created. In case of conflict,
-user-defined shortcuts take precidence.
-The name of a link here is first the modifier keys, followed by a ``-''.
-The following modifiers are recognised:
-.Bl -tag -width Ds
-.It Pa C
-The Control key.
-.It Pa M
-The Meta key.
-.It Pa S
-The Shift key.
-.It Pa 2
-The Mod2 key.
-.It Pa 3
-The Mod3 key.
-.It Pa 4
-The Mod4 key (normally the windows key).
-.El
-The ``-'' should be followed by either a keysym name, taken from
-.Pa /usr/X11R6/include/X11/keysymdef.h ,
-or a numerical keycode value enclosed in ``[]''.
-The target of the link should be either the name of a task from the
-``name_to_kbfunc''
-structure in
-.Pa conf.c ,
-or, alternatively it should be the commandline that is wished to be executed.
-A special case is the ``unmap'' keyword, which causes any bindings using the
-named shortcut to be removed. This can be used to remove a binding which conflicts
-with an application.
-For example, to cause
-.Ic C-M-r
-to add a label to a window:
-.Bd -literal -offset indent
-$ ln -s "label" ~/.calmwm/.keys/CM-r
-.Ed
-Launch an xterm running
-.Xr top 1
-with C-S-Enter:
-.Bd -literal -offset indent
-$ ln -s "/usr/X11R6/bin/xterm -e top" ~/.calmwm/.keys/CS-Return
-.Ed
-Remove a keybinding for Mod4-o
-.Bd -literal -offset indent
-$ ln -s "unmap" 4-o
-.Ed
-.El
+.It Pa ~/.cwmrc
+.Sh SEE ALSO
+.Xr cwmrc 5
.Sh AUTHORS
.An -nosplit
.Pp
diff --git a/app/cwm/cwmrc b/app/cwm/cwmrc
new file mode 100644
index 000000000..24b6f9a2c
--- /dev/null
+++ b/app/cwm/cwmrc
@@ -0,0 +1,28 @@
+# $OpenBSD: cwmrc,v 1.1 2008/03/23 15:09:21 simon Exp $
+
+# Makes the Xft(3) font string fontname the default font
+#fontname "sans-serif:pixelsize=14:bold"
+
+# Set sticky group mode on
+#sticky no
+
+# Any entry here is shown in the application menu
+#command firefox firefox
+#command xmms xmms
+#command top "xterm -e top"
+
+# Autogroup definition
+#autogroup 3 "aterm,XTerm"
+#autogroup 3 "xterm,XTerm"
+
+# Cause cwm to ignore programs by that name by not drawing borders around them.
+#ignore XMMS
+#ignore xwi
+#ignore xapm
+#ignore xclock
+
+# Keys
+#bind CM-r "label"
+#bind CS-Return "xterm -e top"
+#bind 4-o "unmap"
+
diff --git a/app/cwm/cwmrc.5 b/app/cwm/cwmrc.5
new file mode 100644
index 000000000..fa2221364
--- /dev/null
+++ b/app/cwm/cwmrc.5
@@ -0,0 +1,158 @@
+.\" $OpenBSD: cwmrc.5,v 1.1 2008/03/23 15:09:21 simon Exp $
+.\"
+.\" Copyright (c) 2004,2005 Marius Aamodt Eriksen <marius@monkey.org>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" The following requests are required for all man pages.
+.Dd $Mdocdate: March 23 2008 $
+.Dt CWMRC 1
+.Os
+.Sh NAME
+.Nm cwmrc
+.Nd calm window manager configuration file
+.Sh DESCRIPTION
+The
+.Xr cwm 1
+window manager configuration file format.
+.Sh OPTIONS
+There are quite a few settings that affect the operation of
+.Xr cwm 1 .
+.Pp
+The following options are accepted in the configuration file:
+.Pp
+.Bl -tag -width Ds
+.It Ic fontname Ar font
+Makes the
+.Xr Xft 3
+font string
+.Ar font
+the default font.
+.It Ic sticky Ic yes Ns \&| Ns Ic no
+Set sticky group mode on.
+The default behavior for new windows is to not assign any group.
+This changes the default behavior to assigning the currrently selected
+group to any newly created windows.
+.It Ic command Ar name Ar path
+Every command entry is shown in the application menu.
+When it is selected, the image is executed with
+.Xr execve 2 .
+.Pp
+The entries
+.Nm term
+and
+.Nm lock
+have a special meaning.
+When they exist they point to the terminal program and screen locking
+programs used by the keybindings specified above.
+The defaults for these are
+.Xr xterm 1
+and
+.Xr xlock 1 ,
+respectively.
+.It Ic autogroup Ar group Dq windowclass
+.It Ic autogroup Ar group Dq windowclass,windowname
+Autogroups are read upon startup and control the
+automatic grouping feature, which is based on the window name and class
+properties.
+The group is a number between 1 and 9.
+.Pp
+To obtain the name and class of a window, use
+.Ql xprop WM_CLASS ,
+then click on the window.
+The first quoted string is the window name; the second one is the
+window class.
+.Pp
+For example, to make all windows in the
+.Xr xterm 1
+class go to the third group:
+.Bd -literal -offset indent
+autogroup 3 XTerm
+.Ed
+.It Ic ignore Ar program
+Ignore programs by that name by not drawing borders around them.
+For example the command
+.Bd -literal -offset indent
+ignore xclock
+.Ed
+will cause any instances of
+.Xr xclock 1
+to not have borders.
+.It Ic bind Ar keys Ar command
+Cause the creation of keyboard shortcuts.
+The default shortcuts will always be created. In case of conflict,
+user-defined shortcuts take precidence.
+The modifier keys come first, followed by a ``-''.
+The following modifiers are recognised:
+.Bl -tag -width Ds
+.It Pa C
+The Control key.
+.It Pa M
+The Meta key.
+.It Pa S
+The Shift key.
+.It Pa 2
+The Mod2 key.
+.It Pa 3
+The Mod3 key.
+.It Pa 4
+The Mod4 key (normally the windows key).
+.El
+The ``-'' should be followed by either a keysym name, taken from
+.Pa /usr/X11R6/include/X11/keysymdef.h ,
+or a numerical keycode value enclosed in ``[]''.
+The command should be either the name of a task from the
+``name_to_kbfunc''
+structure in
+.Pa conf.c ,
+or, alternatively it should be the commandline that is wished to be executed.
+A special case is the ``unmap'' keyword, which causes any bindings using the
+named shortcut to be removed. This can be used to remove a binding which conflicts
+with an application.
+.Pp
+For example, to cause
+.Ic C-M-r
+to add a label to a window:
+.Bd -literal -offset indent
+bind CM-r "label"
+.Ed
+.Pp
+Launch an xterm running
+.Xr top 1
+with C-S-Enter:
+.Bd -literal -offset indent
+bind CS-Return "/usr/X11R6/bin/xterm -e top"
+.Ed
+.Pp
+Remove a keybinding for Mod4-o
+.Bd -literal -offset indent
+bind 4-o "unmap"
+.Ed
+.El
+.Sh SEE ALSO
+.Xr cwm 1
+.Sh AUTHORS
+.An -nosplit
+.Pp
+.Nm
+was initially written by
+.An Marius Aamodt Eriksen Aq marius@monkey.org
+with contributions from
+.An Andy Adamson Aq dros@monkey.org ,
+.An Niels Provos Aq provos@monkey.org ,
+and
+.An Antti Nykänen Aq aon@iki.fi .
+.Sh HISTORY
+.Nm
+first appeared in
+.Ox 4.4 .
diff --git a/app/cwm/group.c b/app/cwm/group.c
index 26363eddf..b8921e002 100644
--- a/app/cwm/group.c
+++ b/app/cwm/group.c
@@ -16,7 +16,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: group.c,v 1.7 2008/03/22 21:34:07 okan Exp $
+ * $Id: group.c,v 1.8 2008/03/23 15:09:21 simon Exp $
*/
#include "headers.h"
@@ -31,12 +31,6 @@ char Group_name[256];
int Grouphideall = 0;
struct group_ctx_q Groupq;
-static char *shortcut_to_name[] = {
- "XXX", "one", "two", "three",
- "four", "five", "six", "seven",
- "eight", "nine",
-};
-
static void
_group_add(struct group_ctx *gc, struct client_ctx *cc)
{
diff --git a/app/cwm/kbfunc.c b/app/cwm/kbfunc.c
index 0993fa62b..7c2db8405 100644
--- a/app/cwm/kbfunc.c
+++ b/app/cwm/kbfunc.c
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: kbfunc.c,v 1.15 2008/03/22 15:09:45 oga Exp $
+ * $Id: kbfunc.c,v 1.16 2008/03/23 15:09:21 simon Exp $
*/
#include <paths.h>
@@ -204,7 +204,7 @@ kbfunc_menu_search(struct client_ctx *scratch, void *arg)
TAILQ_INIT(&menuq);
- conf_cmd_refresh(&Conf);
+ conf_reload(&Conf);
TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
XCALLOC(mi, struct menu);
strlcpy(mi->text, cmd->label, sizeof(mi->text));
@@ -249,14 +249,14 @@ kbfunc_cmdexec(struct client_ctx *cc, void *arg)
void
kbfunc_term(struct client_ctx *cc, void *arg)
{
- conf_cmd_refresh(&Conf);
+ conf_reload(&Conf);
u_spawn(Conf.termpath);
}
void
kbfunc_lock(struct client_ctx *cc, void *arg)
{
- conf_cmd_refresh(&Conf);
+ conf_reload(&Conf);
u_spawn(Conf.lockpath);
}
@@ -423,7 +423,7 @@ kbfunc_ssh(struct client_ctx *scratch, void *arg)
if ((mi = search_start(&menuq,
search_match_exec, NULL, "ssh", 1)) != NULL) {
- conf_cmd_refresh(&Conf);
+ conf_reload(&Conf);
l = snprintf(cmd, sizeof(cmd), "%s -e ssh %s", Conf.termpath,
mi->text);
if (l != -1 && l < sizeof(cmd))
diff --git a/app/cwm/parse.y b/app/cwm/parse.y
new file mode 100644
index 000000000..c87d4758a
--- /dev/null
+++ b/app/cwm/parse.y
@@ -0,0 +1,583 @@
+/* $OpenBSD: parse.y,v 1.1 2008/03/23 15:09:21 simon Exp $ */
+
+/*
+ * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
+ * Copyright (c) 2001 Markus Friedl. All rights reserved.
+ * Copyright (c) 2001 Daniel Hartmeier. All rights reserved.
+ * Copyright (c) 2001 Theo de Raadt. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+%{
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "headers.h"
+#include "calmwm.h"
+
+TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files);
+static struct file {
+ TAILQ_ENTRY(file) entry;
+ FILE *stream;
+ char *name;
+ int lineno;
+ int errors;
+} *file;
+struct file *pushfile(const char *);
+int popfile(void);
+int yyparse(void);
+int yylex(void);
+int yyerror(const char *, ...);
+int kw_cmp(const void *, const void *);
+int lookup(char *);
+int lgetc(int);
+int lungetc(int);
+int findeol(void);
+
+static struct conf *conf;
+
+extern char *shortcut_to_name[];
+
+typedef struct {
+ union {
+ int64_t number;
+ char *string;
+ } v;
+ int lineno;
+} YYSTYPE;
+
+%}
+
+%token FONTNAME STICKY
+%token AUTOGROUP BIND COMMAND IGNORE
+%token YES NO
+%token ERROR
+%token <v.string> STRING
+%token <v.number> NUMBER
+%type <v.number> yesno
+%type <v.string> string
+%%
+
+grammar : /* empty */
+ | grammar '\n'
+ | grammar main '\n'
+ | grammar error '\n' { file->errors++; }
+ ;
+
+string : string STRING {
+ if (asprintf(&$$, "%s %s", $1, $2) == -1) {
+ free($1);
+ free($2);
+ yyerror("string: asprintf");
+ YYERROR;
+ }
+ free($1);
+ free($2);
+ }
+ | STRING
+ ;
+
+yesno : YES { $$ = 1; }
+ | NO { $$ = 0; }
+ ;
+
+main : FONTNAME STRING {
+ if (conf->DefaultFontName != NULL &&
+ conf->DefaultFontName != DEFAULTFONTNAME)
+ free(conf->DefaultFontName);
+ if ((conf->DefaultFontName = xstrdup($2)) == NULL) {
+ free($2);
+ yyerror("string: asprintf");
+ YYERROR;
+ }
+ free($2);
+ }
+ | STICKY yesno {
+ if ($2 == 0)
+ conf->flags &= ~CONF_STICKY_GROUPS;
+ else
+ conf->flags |= CONF_STICKY_GROUPS;
+ }
+ | COMMAND STRING string {
+ conf_cmd_add(conf, $3, $2, 0);
+ free($2);
+ free($3);
+ }
+ | AUTOGROUP NUMBER STRING {
+ struct autogroupwin *aw;
+ char *p;
+
+ if ($2 < 1 || $2 > 9) {
+ free($3);
+ yyerror("autogroup number out of range: %d", $2);
+ YYERROR;
+ }
+
+ XCALLOC(aw, struct autogroupwin);
+
+ if ((p = strchr($3, ',')) == NULL) {
+ aw->name = NULL;
+ aw->class = xstrdup($3);
+ } else {
+ *(p++) = '\0';
+ aw->name = xstrdup($3);
+ aw->class = xstrdup(p);
+ }
+ aw->group = xstrdup(shortcut_to_name[$2]);
+
+ TAILQ_INSERT_TAIL(&conf->autogroupq, aw, entry);
+
+ free($3);
+ }
+ | IGNORE STRING {
+ struct winmatch *wm;
+
+ XCALLOC(wm, struct winmatch);
+ strlcpy(wm->title, $2, sizeof(wm->title));
+ wm->opts |= CONF_IGNORECASE;
+ TAILQ_INSERT_TAIL(&conf->ignoreq, wm, entry);
+
+ free($2);
+ }
+ | BIND STRING string {
+ conf_bindname(conf, $2, $3);
+ free($2);
+ free($3);
+ }
+ ;
+
+%%
+
+struct keywords {
+ const char *k_name;
+ int k_val;
+};
+
+int
+yyerror(const char *fmt, ...)
+{
+ va_list ap;
+
+ file->errors++;
+ va_start(ap, fmt);
+ fprintf(stderr, "%s:%d: ", file->name, yylval.lineno);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+ return (0);
+}
+
+int
+kw_cmp(const void *k, const void *e)
+{
+ return (strcmp(k, ((const struct keywords *)e)->k_name));
+}
+
+int
+lookup(char *s)
+{
+ /* this has to be sorted always */
+ static const struct keywords keywords[] = {
+ { "autogroup", AUTOGROUP},
+ { "bind", BIND},
+ { "command", COMMAND},
+ { "fontname", FONTNAME},
+ { "ignore", IGNORE},
+ { "no", NO},
+ { "sticky", STICKY},
+ { "yes", YES}
+ };
+ const struct keywords *p;
+
+ p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
+ sizeof(keywords[0]), kw_cmp);
+
+ if (p)
+ return (p->k_val);
+ else
+ return (STRING);
+}
+
+#define MAXPUSHBACK 128
+
+char *parsebuf;
+int parseindex;
+char pushback_buffer[MAXPUSHBACK];
+int pushback_index = 0;
+
+int
+lgetc(int quotec)
+{
+ int c, next;
+
+ if (parsebuf) {
+ /* Read character from the parsebuffer instead of input. */
+ if (parseindex >= 0) {
+ c = parsebuf[parseindex++];
+ if (c != '\0')
+ return (c);
+ parsebuf = NULL;
+ } else
+ parseindex++;
+ }
+
+ if (pushback_index)
+ return (pushback_buffer[--pushback_index]);
+
+ if (quotec) {
+ if ((c = getc(file->stream)) == EOF) {
+ yyerror("reached end of file while parsing quoted string");
+ if (popfile() == EOF)
+ return (EOF);
+ return (quotec);
+ }
+ return (c);
+ }
+
+ while ((c = getc(file->stream)) == '\\') {
+ next = getc(file->stream);
+ if (next != '\n') {
+ c = next;
+ break;
+ }
+ yylval.lineno = file->lineno;
+ file->lineno++;
+ }
+
+ while (c == EOF) {
+ if (popfile() == EOF)
+ return (EOF);
+ c = getc(file->stream);
+ }
+ return (c);
+}
+
+int
+lungetc(int c)
+{
+ if (c == EOF)
+ return (EOF);
+ if (parsebuf) {
+ parseindex--;
+ if (parseindex >= 0)
+ return (c);
+ }
+ if (pushback_index < MAXPUSHBACK-1)
+ return (pushback_buffer[pushback_index++] = c);
+ else
+ return (EOF);
+}
+
+int
+findeol(void)
+{
+ int c;
+
+ parsebuf = NULL;
+ pushback_index = 0;
+
+ /* skip to either EOF or the first real EOL */
+ while (1) {
+ c = lgetc(0);
+ if (c == '\n') {
+ file->lineno++;
+ break;
+ }
+ if (c == EOF)
+ break;
+ }
+ return (ERROR);
+}
+
+int
+yylex(void)
+{
+ char buf[8096];
+ char *p;
+ int quotec, next, c;
+ int token;
+
+ p = buf;
+ while ((c = lgetc(0)) == ' ' || c == '\t')
+ ; /* nothing */
+
+ yylval.lineno = file->lineno;
+ if (c == '#')
+ while ((c = lgetc(0)) != '\n' && c != EOF)
+ ; /* nothing */
+
+ switch (c) {
+ case '\'':
+ case '"':
+ quotec = c;
+ while (1) {
+ if ((c = lgetc(quotec)) == EOF)
+ return (0);
+ if (c == '\n') {
+ file->lineno++;
+ continue;
+ } else if (c == '\\') {
+ if ((next = lgetc(quotec)) == EOF)
+ return (0);
+ if (next == quotec || c == ' ' || c == '\t')
+ c = next;
+ else if (next == '\n')
+ continue;
+ else
+ lungetc(next);
+ } else if (c == quotec) {
+ *p = '\0';
+ break;
+ }
+ if (p + 1 >= buf + sizeof(buf) - 1) {
+ yyerror("string too long");
+ return (findeol());
+ }
+ *p++ = (char)c;
+ }
+ yylval.v.string = strdup(buf);
+ if (yylval.v.string == NULL)
+ err(1, "yylex: strdup");
+ return (STRING);
+ }
+
+#define allowed_to_end_number(x) \
+ (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
+
+ if (c == '-' || isdigit(c)) {
+ do {
+ *p++ = c;
+ if ((unsigned)(p-buf) >= sizeof(buf)) {
+ yyerror("string too long");
+ return (findeol());
+ }
+ } while ((c = lgetc(0)) != EOF && isdigit(c));
+ lungetc(c);
+ if (p == buf + 1 && buf[0] == '-')
+ goto nodigits;
+ if (c == EOF || allowed_to_end_number(c)) {
+ const char *errstr = NULL;
+
+ *p = '\0';
+ yylval.v.number = strtonum(buf, LLONG_MIN,
+ LLONG_MAX, &errstr);
+ if (errstr) {
+ yyerror("\"%s\" invalid number: %s",
+ buf, errstr);
+ return (findeol());
+ }
+ return (NUMBER);
+ } else {
+nodigits:
+ while (p > buf + 1)
+ lungetc(*--p);
+ c = *--p;
+ if (c == '-')
+ return (c);
+ }
+ }
+
+#define allowed_in_string(x) \
+ (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
+ x != '{' && x != '}' && x != '<' && x != '>' && \
+ x != '!' && x != '=' && x != '/' && x != '#' && \
+ x != ','))
+
+ if (isalnum(c) || c == ':' || c == '_' || c == '*') {
+ do {
+ *p++ = c;
+ if ((unsigned)(p-buf) >= sizeof(buf)) {
+ yyerror("string too long");
+ return (findeol());
+ }
+ } while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
+ lungetc(c);
+ *p = '\0';
+ if ((token = lookup(buf)) == STRING)
+ if ((yylval.v.string = strdup(buf)) == NULL)
+ err(1, "yylex: strdup");
+ return (token);
+ }
+ if (c == '\n') {
+ yylval.lineno = file->lineno;
+ file->lineno++;
+ }
+ if (c == EOF)
+ return (0);
+ return (c);
+}
+
+struct file *
+pushfile(const char *name)
+{
+ struct file *nfile;
+
+ if ((nfile = calloc(1, sizeof(struct file))) == NULL ||
+ (nfile->name = strdup(name)) == NULL) {
+ warn("malloc");
+ return (NULL);
+ }
+ if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
+ warn("%s", nfile->name);
+ free(nfile->name);
+ free(nfile);
+ return (NULL);
+ }
+ nfile->lineno = 1;
+ TAILQ_INSERT_TAIL(&files, nfile, entry);
+ return (nfile);
+}
+
+int
+popfile(void)
+{
+ struct file *prev;
+
+ if ((prev = TAILQ_PREV(file, files, entry)) != NULL) {
+ prev->errors += file->errors;
+ TAILQ_REMOVE(&files, file, entry);
+ fclose(file->stream);
+ free(file->name);
+ free(file);
+ file = prev;
+ return (0);
+ }
+ return (EOF);
+}
+
+void
+conf_clear(struct conf *c)
+{
+ struct autogroupwin *ag, *agnext;
+ struct keybinding *kb, *kbnext;
+ struct winmatch *wm, *wmnext;
+ struct cmd *cmd, *cmdnext;
+
+ for (cmd = TAILQ_FIRST(&c->cmdq); cmd != NULL; cmd = cmdnext) {
+ cmdnext = TAILQ_NEXT(cmd, entry);
+
+ TAILQ_REMOVE(&c->cmdq, cmd, entry);
+ free(cmd);
+ }
+
+ for (kb = TAILQ_FIRST(&c->keybindingq); kb != NULL; kb = kbnext) {
+ kbnext = TAILQ_NEXT(kb, entry);
+
+ TAILQ_REMOVE(&c->keybindingq, kb, entry);
+ free(kb);
+ }
+
+ for (ag = TAILQ_FIRST(&c->autogroupq); ag != NULL; ag = agnext) {
+ agnext = TAILQ_NEXT(ag, entry);
+
+ TAILQ_REMOVE(&c->autogroupq, ag, entry);
+ free(ag->class);
+ if (ag->name)
+ free(ag->name);
+ free(ag->group);
+ free(ag);
+ }
+
+ for (wm = TAILQ_FIRST(&c->ignoreq); wm != NULL; wm = wmnext) {
+ wmnext = TAILQ_NEXT(wm, entry);
+
+ TAILQ_REMOVE(&c->ignoreq, wm, entry);
+ free(wm);
+ }
+
+ if (c->DefaultFontName != NULL &&
+ c->DefaultFontName != DEFAULTFONTNAME)
+ free(c->DefaultFontName);
+}
+
+
+int
+parse_config(const char *filename, struct conf *xconf)
+{
+ int errors = 0;
+
+ if ((conf = malloc(sizeof(struct conf))) == NULL)
+ return (-1);
+
+ if ((file = pushfile(filename)) == NULL) {
+ free(conf);
+ return (-1);
+ }
+
+ strlcpy(conf->conf_path, filename, sizeof(conf->conf_path));
+
+ conf_init(conf);
+
+ yyparse();
+ errors = file->errors;
+ file->errors = 0;
+ popfile();
+
+ if (errors) {
+ conf_clear(conf);
+ }
+ else {
+ struct autogroupwin *ag, *agnext;
+ struct keybinding *kb, *kbnext;
+ struct winmatch *wm, *wmnext;
+ struct cmd *cmd, *cmdnext;
+
+ conf_clear(xconf);
+
+ xconf->flags = conf->flags;
+
+ for (cmd = TAILQ_FIRST(&conf->cmdq); cmd != NULL; cmd = cmdnext) {
+ cmdnext = TAILQ_NEXT(cmd, entry);
+
+ TAILQ_REMOVE(&conf->cmdq, cmd, entry);
+ TAILQ_INSERT_TAIL(&xconf->cmdq, cmd, entry);
+ }
+
+ for (kb = TAILQ_FIRST(&conf->keybindingq); kb != NULL; kb = kbnext) {
+ kbnext = TAILQ_NEXT(kb, entry);
+
+ TAILQ_REMOVE(&conf->keybindingq, kb, entry);
+ TAILQ_INSERT_TAIL(&xconf->keybindingq, kb, entry);
+ }
+
+ for (ag = TAILQ_FIRST(&conf->autogroupq); ag != NULL; ag = agnext) {
+ agnext = TAILQ_NEXT(ag, entry);
+
+ TAILQ_REMOVE(&conf->autogroupq, ag, entry);
+ TAILQ_INSERT_TAIL(&xconf->autogroupq, ag, entry);
+ }
+
+ for (wm = TAILQ_FIRST(&conf->ignoreq); wm != NULL; wm = wmnext) {
+ wmnext = TAILQ_NEXT(wm, entry);
+
+ TAILQ_REMOVE(&conf->ignoreq, wm, entry);
+ TAILQ_INSERT_TAIL(&xconf->ignoreq, wm, entry);
+ }
+
+ strlcpy(xconf->termpath, conf->termpath, sizeof(xconf->termpath));
+ strlcpy(xconf->lockpath, conf->lockpath, sizeof(xconf->lockpath));
+
+ xconf->DefaultFontName = conf->DefaultFontName;
+ }
+
+ free(conf);
+
+ return (errors ? -1 : 0);
+}
diff --git a/app/cwm/xevents.c b/app/cwm/xevents.c
index 6189ac03d..3504e0a78 100644
--- a/app/cwm/xevents.c
+++ b/app/cwm/xevents.c
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: xevents.c,v 1.7 2008/03/22 15:09:45 oga Exp $
+ * $Id: xevents.c,v 1.8 2008/03/23 15:09:21 simon Exp $
*/
/*
@@ -275,10 +275,7 @@ xev_handle_buttonpress(struct xevent *xev, XEvent *ee)
break;
case Button3: {
struct cmd *cmd;
- if (conf_cmd_changed(Conf.menu_path)) {
- conf_cmd_clear(&Conf);
- conf_cmd_populate(&Conf, Conf.menu_path);
- }
+ conf_reload(&Conf);
TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
XCALLOC(mi, struct menu);
strlcpy(mi->text, cmd->label, sizeof(mi->text));