Improve startup error handling.

Instead of exiting on bad conf values, continue loading and display
the first error in the status bar.
This commit is contained in:
Reginald Kennedy 2020-05-11 18:10:06 +08:00
parent 0e6b5fd965
commit 3b6fe9f09a

View file

@ -193,6 +193,11 @@ uint32_t swm_debug = 0
#define DNPRINTF(n,x...)
#endif
#define ALLOCSTR(s, x...) do { \
if (s && asprintf(s, x) == -1) \
err(1, "asprintf"); \
} while (0)
#define SWM_EWMH_ACTION_COUNT_MAX (8)
#define EWMH_F_FULLSCREEN (0x001)
#define EWMH_F_ABOVE (0x002)
@ -1127,7 +1132,6 @@ void constrain_window(struct ws_win *, struct swm_geometry *, int *);
int count_win(struct workspace *, bool);
void cursors_cleanup(void);
void cursors_load(void);
void custom_region(const char *);
void cyclerg(struct binding *, struct swm_region *, union arg *);
void cyclews(struct binding *, struct swm_region *, union arg *);
#ifdef SWM_DEBUG
@ -1241,9 +1245,9 @@ void name_workspace(struct binding *, struct swm_region *, union arg *);
void new_region(struct swm_screen *, int, int, int, int);
int parse_rgb(const char *, uint16_t *, uint16_t *, uint16_t *);
int parsebinding(const char *, uint16_t *, enum binding_type *, uint32_t *,
uint32_t *);
int parsequirks(const char *, uint32_t *, int *);
int parse_workspace_indicator(const char *, uint32_t *);
uint32_t *, char **);
int parsequirks(const char *, uint32_t *, int *, char **);
int parse_workspace_indicator(const char *, uint32_t *, char **);
void pressbutton(struct binding *, struct swm_region *, union arg *);
void priorws(struct binding *, struct swm_region *, union arg *);
#ifdef SWM_DEBUG
@ -1284,19 +1288,19 @@ void send_to_rg(struct binding *, struct swm_region *, union arg *);
void send_to_rg_relative(struct binding *, struct swm_region *, union arg *);
void send_to_ws(struct binding *, struct swm_region *, union arg *);
void set_region(struct swm_region *);
int setautorun(const char *, const char *, int);
int setautorun(const char *, const char *, int, char **);
void setbinding(uint16_t, enum binding_type, uint32_t, enum actionid,
uint32_t, const char *);
int setconfbinding(const char *, const char *, int);
int setconfcolor(const char *, const char *, int);
int setconfcolorlist(const char *, const char *, int);
int setconfmodkey(const char *, const char *, int);
int setconfquirk(const char *, const char *, int);
int setconfregion(const char *, const char *, int);
int setconfspawn(const char *, const char *, int);
int setconfvalue(const char *, const char *, int);
int setkeymapping(const char *, const char *, int);
int setlayout(const char *, const char *, int);
int setconfbinding(const char *, const char *, int, char **);
int setconfcolor(const char *, const char *, int, char **);
int setconfcolorlist(const char *, const char *, int, char **);
int setconfmodkey(const char *, const char *, int, char **);
int setconfquirk(const char *, const char *, int, char **);
int setconfregion(const char *, const char *, int, char **);
int setconfspawn(const char *, const char *, int, char **);
int setconfvalue(const char *, const char *, int, char **);
int setkeymapping(const char *, const char *, int, char **);
int setlayout(const char *, const char *, int, char **);
void setquirk(const char *, const char *, const char *, uint32_t, int);
void setscreencolor(const char *, int, int);
void setspawn(const char *, const char *, int);
@ -2287,43 +2291,6 @@ plain_stacker(struct workspace *ws)
sizeof ws->stacker);
}
void
custom_region(const char *val)
{
unsigned int x, y, w, h;
int sidx, num_screens;
xcb_screen_t *screen;
DNPRINTF(SWM_D_CONF, "%s\n", val);
num_screens = get_screen_count();
if (sscanf(val, "screen[%d]:%ux%u+%u+%u", &sidx, &w, &h, &x, &y) != 5)
errx(1, "invalid custom region, "
"should be 'screen[<n>]:<n>x<n>+<n>+<n>");
if (sidx < 1 || sidx > num_screens)
errx(1, "invalid screen index: %d out of bounds (maximum %d)",
sidx, num_screens);
sidx--;
if ((screen = get_screen(sidx)) == NULL)
errx(1, "ERROR: can't get screen %d.", sidx);
if (w < 1 || h < 1)
errx(1, "region %ux%u+%u+%u too small", w, h, x, y);
if (x > screen->width_in_pixels ||
y > screen->height_in_pixels ||
w + x > screen->width_in_pixels ||
h + y > screen->height_in_pixels) {
warnx("ignoring region %ux%u+%u+%u - not within screen "
"boundaries (%ux%u)", w, h, x, y,
screen->width_in_pixels, screen->height_in_pixels);
return;
}
new_region(&screens[sidx], x, y, w, h);
}
void
socket_setnonblock(int fd)
{
@ -8663,12 +8630,14 @@ setspawn(const char *name, const char *args, int flags)
}
int
setconfspawn(const char *selector, const char *value, int flags)
setconfspawn(const char *selector, const char *value, int flags, char **emsg)
{
char *args;
if (selector == NULL || strlen(selector) == 0)
if (selector == NULL || strlen(selector) == 0) {
ALLOCSTR(emsg, "missing selector");
return (1);
}
args = expand_tilde(value);
@ -8715,41 +8684,29 @@ validate_spawns(void)
void
setup_spawn(void)
{
setconfspawn("lock", "xlock", 0);
setconfspawn("lock", "xlock", 0, NULL);
setconfspawn("term", "xterm", 0);
setconfspawn("spawn_term", "xterm", 0);
setconfspawn("term", "xterm", 0, NULL);
setconfspawn("spawn_term", "xterm", 0, NULL);
setconfspawn("menu", "dmenu_run"
" $dmenu_bottom"
" -fn $bar_font"
" -nb $bar_color"
" -nf $bar_font_color"
" -sb $bar_color_selected"
" -sf $bar_font_color_selected", 0);
setconfspawn("menu", "dmenu_run $dmenu_bottom -fn $bar_font "
"-nb $bar_color -nf $bar_font_color -sb $bar_color_selected "
"-sf $bar_font_color_selected", 0, NULL);
setconfspawn("search", "dmenu"
" $dmenu_bottom"
" -i"
" -fn $bar_font"
" -nb $bar_color"
" -nf $bar_font_color"
" -sb $bar_color_selected"
" -sf $bar_font_color_selected", 0);
setconfspawn("search", "dmenu $dmenu_bottom -i -fn $bar_font "
"-nb $bar_color -nf $bar_font_color -sb $bar_color_selected "
"-sf $bar_font_color_selected", 0, NULL);
setconfspawn("name_workspace", "dmenu"
" $dmenu_bottom"
" -p Workspace"
" -fn $bar_font"
" -nb $bar_color"
" -nf $bar_font_color"
" -sb $bar_color_selected"
" -sf $bar_font_color_selected", 0);
setconfspawn("name_workspace", "dmenu $dmenu_bottom -p Workspace "
"-fn $bar_font -nb $bar_color -nf $bar_font_color "
"-sb $bar_color_selected -sf $bar_font_color_selected", 0, NULL);
/* These are not verified for existence, even with a binding set. */
setconfspawn("screenshot_all", "screenshot.sh full", SWM_SPAWN_OPTIONAL);
setconfspawn("screenshot_wind", "screenshot.sh window", SWM_SPAWN_OPTIONAL);
setconfspawn("initscr", "initscreen.sh", SWM_SPAWN_OPTIONAL);
setconfspawn("screenshot_all", "screenshot.sh full",
SWM_SPAWN_OPTIONAL, NULL);
setconfspawn("screenshot_wind", "screenshot.sh window",
SWM_SPAWN_OPTIONAL, NULL);
setconfspawn("initscr", "initscreen.sh", SWM_SPAWN_OPTIONAL, NULL);
}
/* bindings */
@ -8757,7 +8714,7 @@ setup_spawn(void)
#define SWM_KEY_WS "\n+ \t"
int
parsebinding(const char *bindstr, uint16_t *mod, enum binding_type *type,
uint32_t *val, uint32_t *flags)
uint32_t *val, uint32_t *flags, char **emsg)
{
char *str, *cp, *name;
KeySym ks, lks, uks;
@ -8808,6 +8765,7 @@ parsebinding(const char *bindstr, uint16_t *mod, enum binding_type *type,
*type = BTNBIND;
if (*val > 255 || *val == 0) {
DNPRINTF(SWM_D_KEY, "invalid btn %u\n", *val);
ALLOCSTR(emsg, "invalid button: %s", name);
free(str);
return (1);
}
@ -8816,6 +8774,7 @@ parsebinding(const char *bindstr, uint16_t *mod, enum binding_type *type,
ks = XStringToKeysym(name);
if (ks == NoSymbol) {
DNPRINTF(SWM_D_KEY, "invalid key %s\n", name);
ALLOCSTR(emsg, "invalid key: %s", name);
free(str);
return (1);
}
@ -8938,7 +8897,7 @@ setbinding(uint16_t mod, enum binding_type type, uint32_t val,
}
int
setconfbinding(const char *selector, const char *value, int flags)
setconfbinding(const char *selector, const char *value, int flags, char **emsg)
{
struct spawn_prog *sp;
uint32_t keybtn, opts;
@ -8952,7 +8911,8 @@ setconfbinding(const char *selector, const char *value, int flags)
DNPRINTF(SWM_D_KEY, "selector: [%s], value: [%s]\n", selector, value);
if (selector == NULL || strlen(selector) == 0) {
DNPRINTF(SWM_D_KEY, "unbind %s\n", value);
if (parsebinding(value, &mod, &type, &keybtn, &opts) == 0) {
if (parsebinding(value, &mod, &type, &keybtn, &opts,
emsg) == 0) {
setbinding(mod, type, keybtn, FN_INVALID, opts, NULL);
return (0);
} else
@ -8963,8 +8923,8 @@ setconfbinding(const char *selector, const char *value, int flags)
if (strncasecmp(selector, actions[aid].name,
SWM_FUNCNAME_LEN) == 0) {
DNPRINTF(SWM_D_KEY, "%s: match action\n", selector);
if (parsebinding(value, &mod, &type, &keybtn,
&opts) == 0) {
if (parsebinding(value, &mod, &type, &keybtn, &opts,
emsg) == 0) {
setbinding(mod, type, keybtn, aid, opts, NULL);
return (0);
} else
@ -8974,7 +8934,8 @@ setconfbinding(const char *selector, const char *value, int flags)
/* search by custom spawn name */
if ((sp = spawn_find(selector)) != NULL) {
DNPRINTF(SWM_D_KEY, "%s: match spawn\n", selector);
if (parsebinding(value, &mod, &type, &keybtn, &opts) == 0) {
if (parsebinding(value, &mod, &type, &keybtn, &opts,
emsg) == 0) {
setbinding(mod, type, keybtn, FN_SPAWN_CUSTOM, opts,
sp->name);
return (0);
@ -8982,6 +8943,7 @@ setconfbinding(const char *selector, const char *value, int flags)
return (1);
}
DNPRINTF(SWM_D_KEY, "no match\n");
ALLOCSTR(emsg, "invalid action: %s", selector);
return (1);
}
@ -9156,7 +9118,7 @@ clear_keybindings(void)
}
int
setkeymapping(const char *selector, const char *value, int flags)
setkeymapping(const char *selector, const char *value, int flags, char **emsg)
{
char *keymapping_file;
@ -9171,8 +9133,11 @@ setkeymapping(const char *selector, const char *value, int flags)
clear_keybindings();
/* load new key bindings; if it fails, revert to default bindings */
if (conf_load(keymapping_file, SWM_CONF_KEYMAPPING)) {
ALLOCSTR(emsg, "failed to load '%s'", keymapping_file);
free(keymapping_file);
clear_keybindings();
setup_keybindings();
return (1);
}
free(keymapping_file);
@ -9400,7 +9365,7 @@ struct wsi_flag {
#define SWM_FLAGS_DELIM ","
#define SWM_FLAGS_WHITESPACE " \t\n"
int
parse_workspace_indicator(const char *str, uint32_t *mode)
parse_workspace_indicator(const char *str, uint32_t *mode, char **emsg)
{
char *tmp, *cp, *name;
size_t len;
@ -9427,6 +9392,7 @@ parse_workspace_indicator(const char *str, uint32_t *mode)
}
}
if (i >= LENGTH(wsiflags)) {
ALLOCSTR(emsg, "invalid flag: %s", name);
DNPRINTF(SWM_D_CONF, "invalid flag: [%s]\n", name);
free(tmp);
return (1);
@ -9457,7 +9423,7 @@ const char *quirkname[] = {
/* SWM_Q_DELIM: retain '|' for back compat for now (2009-08-11) */
#define SWM_Q_DELIM "\n|+ \t"
int
parsequirks(const char *qstr, uint32_t *quirk, int *ws)
parsequirks(const char *qstr, uint32_t *quirk, int *ws, char **emsg)
{
char *str, *cp, *name;
int i;
@ -9494,6 +9460,7 @@ parsequirks(const char *qstr, uint32_t *quirk, int *ws)
}
if (i >= LENGTH(quirkname)) {
DNPRINTF(SWM_D_QUIRK, "invalid quirk [%s]\n", name);
ALLOCSTR(emsg, "invalid quirk: %s", name);
free(str);
return (1);
}
@ -9661,7 +9628,7 @@ unescape_selector(char *str)
}
int
setconfquirk(const char *selector, const char *value, int flags)
setconfquirk(const char *selector, const char *value, int flags, char **emsg)
{
char *str, *cp, *class;
char *instance = NULL, *name = NULL;
@ -9709,7 +9676,7 @@ setconfquirk(const char *selector, const char *value, int flags)
DNPRINTF(SWM_D_CONF, "class: %s, instance: %s, name: %s\n", class,
instance, name);
if ((retval = parsequirks(value, &qrks, &ws)) == 0)
if ((retval = parsequirks(value, &qrks, &ws, emsg)) == 0)
setquirk(class, instance, name, qrks, ws);
free(str);
@ -9797,7 +9764,7 @@ enum {
};
int
setconfvalue(const char *selector, const char *value, int flags)
setconfvalue(const char *selector, const char *value, int flags, char **emsg)
{
struct workspace *ws;
int i, ws_id, num_screens, n;
@ -9825,9 +9792,10 @@ setconfvalue(const char *selector, const char *value, int flags)
break;
case SWM_S_BAR_ENABLED_WS:
ws_id = atoi(selector) - 1;
if (ws_id < 0 || ws_id >= workspace_limit)
errx(1, "setconfvalue: bar_enabled_ws: invalid "
"workspace %d.", ws_id + 1);
if (ws_id < 0 || ws_id >= workspace_limit) {
ALLOCSTR(emsg, "invalid workspace: %d", ws_id + 1);
return (1);
}
num_screens = get_screen_count();
for (i = 0; i < num_screens; i++) {
@ -9893,8 +9861,11 @@ setconfvalue(const char *selector, const char *value, int flags)
bar_justify = SWM_BAR_JUSTIFY_CENTER;
else if (strcmp(value, "right") == 0)
bar_justify = SWM_BAR_JUSTIFY_RIGHT;
else
errx(1, "invalid bar_justify");
else {
ALLOCSTR(emsg, "invalid value: %s", value);
return (1);
}
break;
case SWM_S_BORDER_WIDTH:
border_width = atoi(value);
@ -9940,8 +9911,10 @@ setconfvalue(const char *selector, const char *value, int flags)
focus_close = SWM_STACK_ABOVE;
else if (strcmp(value, "previous") == 0)
focus_close = SWM_STACK_BELOW;
else
errx(1, "focus_close");
else {
ALLOCSTR(emsg, "invalid value: %s", value);
return (1);
}
break;
case SWM_S_FOCUS_CLOSE_WRAP:
focus_close_wrap = (atoi(value) != 0);
@ -9951,8 +9924,10 @@ setconfvalue(const char *selector, const char *value, int flags)
focus_default = SWM_STACK_TOP;
else if (strcmp(value, "first") == 0)
focus_default = SWM_STACK_BOTTOM;
else
errx(1, "focus_default");
else {
ALLOCSTR(emsg, "invalid value: %s", value);
return (1);
}
break;
case SWM_S_FOCUS_MODE:
if (strcmp(value, "default") == 0)
@ -9962,8 +9937,10 @@ setconfvalue(const char *selector, const char *value, int flags)
focus_mode = SWM_FOCUS_FOLLOW;
else if (strcmp(value, "manual") == 0)
focus_mode = SWM_FOCUS_MANUAL;
else
errx(1, "focus_mode");
else {
ALLOCSTR(emsg, "invalid value: %s", value);
return (1);
}
break;
case SWM_S_ICONIC_ENABLED:
iconic_enabled = (atoi(value) != 0);
@ -9985,12 +9962,14 @@ setconfvalue(const char *selector, const char *value, int flags)
spawn_position = SWM_STACK_ABOVE;
else if (strcmp(value, "previous") == 0)
spawn_position = SWM_STACK_BELOW;
else
errx(1, "spawn_position");
else {
ALLOCSTR(emsg, "invalid value: %s", value);
return (1);
}
break;
case SWM_S_SPAWN_TERM:
setconfspawn("term", value, 0);
setconfspawn("spawn_term", value, 0);
setconfspawn("term", value, 0, emsg);
setconfspawn("spawn_term", value, 0, emsg);
break;
case SWM_S_STACK_ENABLED:
stack_enabled = (atoi(value) != 0);
@ -10046,8 +10025,9 @@ setconfvalue(const char *selector, const char *value, int flags)
ewmh_update_desktops();
break;
case SWM_S_WORKSPACE_INDICATOR:
if (parse_workspace_indicator(value, &workspace_indicator))
errx(1, "invalid workspace_indicator");
if (parse_workspace_indicator(value, &workspace_indicator,
emsg))
return (1);
break;
case SWM_S_WORKSPACE_NAME:
if (getenv("SWM_STARTED") != NULL)
@ -10055,13 +10035,16 @@ setconfvalue(const char *selector, const char *value, int flags)
n = 0;
if (sscanf(value, "ws[%d]:%n", &ws_id, &n) != 1 || n == 0 ||
value[n] == '\0')
errx(1, "invalid entry, should be 'ws[<idx>]:name'");
value[n] == '\0') {
ALLOCSTR(emsg, "invalid syntax: %s", value);
return (1);
}
value += n;
ws_id--;
if (ws_id < 0 || ws_id >= workspace_limit)
errx(1, "setconfvalue: workspace_name: invalid "
"workspace %d.", ws_id + 1);
if (ws_id < 0 || ws_id >= workspace_limit) {
ALLOCSTR(emsg, "invalid workspace: %d", ws_id + 1);
return (1);
}
num_screens = get_screen_count();
for (i = 0; i < num_screens; ++i) {
@ -10069,20 +10052,21 @@ setconfvalue(const char *selector, const char *value, int flags)
free(ws[ws_id].name);
if ((ws[ws_id].name = strdup(value)) == NULL)
err(1, "setconfvalue: workspace_name.");
err(1, "name: strdup");
ewmh_update_desktop_names();
ewmh_get_desktop_names();
}
break;
default:
ALLOCSTR(emsg, "invalid option");
return (1);
}
return (0);
}
int
setconfmodkey(const char *selector, const char *value, int flags)
setconfmodkey(const char *selector, const char *value, int flags, char **emsg)
{
/* suppress unused warnings since vars are needed */
(void)selector;
@ -10098,13 +10082,15 @@ setconfmodkey(const char *selector, const char *value, int flags)
update_modkey(XCB_MOD_MASK_4);
else if (strncasecmp(value, "Mod5", strlen("Mod5")) == 0)
update_modkey(XCB_MOD_MASK_5);
else
else {
ALLOCSTR(emsg, "invalid value: %s", value);
return (1);
}
return (0);
}
int
setconfcolor(const char *selector, const char *value, int flags)
setconfcolor(const char *selector, const char *value, int flags, char **emsg)
{
int first, last, i = 0, num_screens;
@ -10120,8 +10106,7 @@ setconfcolor(const char *selector, const char *value, int flags)
}
if (last >= num_screens) {
add_startup_exception("invalid screen index: %d out of bounds "
"(maximum %d)", last + 1, num_screens);
ALLOCSTR(emsg, "invalid screen index: %d", last + 1);
return (1);
}
@ -10162,7 +10147,7 @@ setconfcolor(const char *selector, const char *value, int flags)
}
int
setconfcolorlist(const char *selector, const char *value, int flags)
setconfcolorlist(const char *selector, const char *value, int flags, char **emsg)
{
char *b, *str, *sp;
@ -10178,7 +10163,7 @@ setconfcolorlist(const char *selector, const char *value, int flags)
if (*b == '\0')
continue;
setconfcolor(selector, b, SWM_S_COLOR_BAR +
num_bg_colors);
num_bg_colors, emsg);
num_bg_colors++;
if (num_bg_colors == SWM_BAR_MAX_COLORS)
break;
@ -10196,7 +10181,7 @@ setconfcolorlist(const char *selector, const char *value, int flags)
if (*b == '\0')
continue;
setconfcolor(selector, b, SWM_S_COLOR_BAR_FONT +
num_fg_colors);
num_fg_colors, emsg);
num_fg_colors++;
if (num_fg_colors == SWM_BAR_MAX_COLORS)
break;
@ -10208,18 +10193,54 @@ setconfcolorlist(const char *selector, const char *value, int flags)
}
int
setconfregion(const char *selector, const char *value, int flags)
setconfregion(const char *selector, const char *value, int flags, char **emsg)
{
unsigned int x, y, w, h;
int sidx, num_screens;
xcb_screen_t *screen;
/* suppress unused warnings since vars are needed */
(void)selector;
(void)flags;
custom_region(value);
DNPRINTF(SWM_D_CONF, "%s\n", value);
num_screens = get_screen_count();
if (sscanf(value, "screen[%d]:%ux%u+%u+%u",
&sidx, &w, &h, &x, &y) != 5) {
ALLOCSTR(emsg, "invalid syntax: %s", value);
return (1);
}
if (sidx < 1 || sidx > num_screens) {
ALLOCSTR(emsg, "invalid screen index: %d", sidx);
return (1);
}
sidx--;
if ((screen = get_screen(sidx)) == NULL)
errx(1, "ERROR: unable to get screen %d.", sidx);
if (w < 1 || h < 1) {
ALLOCSTR(emsg, "invalid size: %ux%u", w, h);
return (1);
}
if (x > screen->width_in_pixels ||
y > screen->height_in_pixels ||
w + x > screen->width_in_pixels ||
h + y > screen->height_in_pixels) {
ALLOCSTR(emsg, "geometry exceeds screen boundary: %ux%u+%u+%u",
w, h, x, y);
return (1);
}
new_region(&screens[sidx], x, y, w, h);
return (0);
}
int
setautorun(const char *selector, const char *value, int flags)
setautorun(const char *selector, const char *value, int flags, char **emsg)
{
int ws_id;
char *ap, *sp, *str;
@ -10237,12 +10258,16 @@ setautorun(const char *selector, const char *value, int flags)
n = 0;
if (sscanf(value, "ws[%d]:%n", &ws_id, &n) != 1 || n == 0 ||
value[n] == '\0')
errx(1, "invalid autorun entry, should be 'ws[<idx>]:command'");
value[n] == '\0') {
ALLOCSTR(emsg, "invalid syntax: %s", value);
return (1);
}
value += n;
ws_id--;
if (ws_id < 0 || ws_id >= workspace_limit)
errx(1, "autorun: invalid workspace %d", ws_id + 1);
if (ws_id < 0 || ws_id >= workspace_limit) {
ALLOCSTR(emsg, "invalid workspace: %d", ws_id + 1);
return (1);
}
sp = str = expand_tilde(value);
@ -10292,7 +10317,7 @@ setautorun(const char *selector, const char *value, int flags)
}
int
setlayout(const char *selector, const char *value, int flags)
setlayout(const char *selector, const char *value, int flags, char **emsg)
{
struct workspace *ws;
int ws_id, i, x, mg, ma, si, ar, n;
@ -10308,14 +10333,17 @@ setlayout(const char *selector, const char *value, int flags)
n = 0;
if (sscanf(value, "ws[%d]:%d:%d:%d:%d:%n",
&ws_id, &mg, &ma, &si, &ar, &n) != 5 || n == 0 || value[n] == '\0')
errx(1, "invalid layout entry, should be 'ws[<idx>]:"
"<master_grow>:<master_add>:<stack_inc>:<always_raise>:"
"<type>'");
&ws_id, &mg, &ma, &si, &ar, &n) != 5 || n == 0 ||
value[n] == '\0') {
ALLOCSTR(emsg, "invalid syntax: %s", value);
return (1);
}
value += n;
ws_id--;
if (ws_id < 0 || ws_id >= workspace_limit)
errx(1, "layout: invalid workspace %d", ws_id + 1);
if (ws_id < 0 || ws_id >= workspace_limit) {
ALLOCSTR(emsg, "invalid workspace: %d", ws_id + 1);
return (1);
}
if (strcasecmp(value, "vertical") == 0)
st = SWM_V_STACK;
@ -10331,10 +10359,10 @@ setlayout(const char *selector, const char *value, int flags)
strcasecmp(value, "fullscreen") == 0)
/* Keep "fullscreen" for backwards compatibility. */
st = SWM_MAX_STACK;
else
errx(1, "invalid layout entry, should be 'ws[<idx>]:"
"<master_grow>:<master_add>:<stack_inc>:<always_raise>:"
"<type>'");
else {
ALLOCSTR(emsg, "invalid layout: %s", value);
return (1);
}
num_screens = get_screen_count();
for (i = 0; i < num_screens; i++) {
@ -10376,7 +10404,7 @@ setlayout(const char *selector, const char *value, int flags)
/* config options */
struct config_option {
char *name;
int (*func)(const char*, const char*, int);
int (*func)(const char*, const char*, int, char **);
int flags;
};
struct config_option configopt[] = {
@ -10478,6 +10506,7 @@ conf_load(const char *filename, int keymapping)
{
FILE *config;
char *line = NULL, *cp, *ce, *optsub, *optval = NULL;
char *emsg = NULL;
size_t linelen, lineno = 0;
int wordlen, i, optidx, count;
struct config_option *opt = NULL;
@ -10583,10 +10612,15 @@ conf_load(const char *filename, int keymapping)
--ce;
*(ce + 1) = '\0';
/* call function to deal with it all */
if (opt->func && opt->func(optsub, optval, opt->flags) != 0) {
add_startup_exception("%s: line %zd: invalid data for "
"%s", filename, lineno, opt->name);
continue;
if (opt->func && opt->func(optsub, optval, opt->flags, &emsg)) {
if (emsg) {
add_startup_exception("%s: line %zd: %s: %s",
filename, lineno, opt->name, emsg);
free(emsg);
emsg = NULL;
} else
add_startup_exception("%s: line %zd: %s",
filename, lineno, opt->name);
}
}
@ -10768,7 +10802,7 @@ reparent_window(struct ws_win *win)
DNPRINTF(SWM_D_MISC, "win %#x, frame: %#x\n", win->id, win->frame);
if ((s = get_screen(win->s->idx)) == NULL)
errx(1, "ERROR: can't get screen %d.", win->s->idx);
errx(1, "ERROR: unable to get screen %d.", win->s->idx);
wa[0] = s->black_pixel;
wa[1] =
XCB_EVENT_MASK_ENTER_WINDOW |
@ -12386,7 +12420,7 @@ enable_wm(void)
num_screens = get_screen_count();
for (i = 0; i < num_screens; i++) {
if ((sc = get_screen(i)) == NULL)
errx(1, "ERROR: can't get screen %d.", i);
errx(1, "ERROR: unable to get screen %d.", i);
DNPRINTF(SWM_D_INIT, "screen %d, root: %#x\n", i, sc->root);
wac = xcb_change_window_attributes_checked(conn, sc->root,
XCB_CW_EVENT_MASK, &val);
@ -12517,7 +12551,7 @@ scan_randr(int idx)
DNPRINTF(SWM_D_MISC, "screen: %d\n", idx);
if ((screen = get_screen(idx)) == NULL)
errx(1, "ERROR: can't get screen %d.", idx);
errx(1, "ERROR: unable to get screen %d.", idx);
num_screens = get_screen_count();
if (idx >= num_screens)
@ -12633,7 +12667,7 @@ screenchange(xcb_randr_screen_change_notify_event_t *e)
if (screens[i].root == e->root)
break;
if (i >= num_screens)
errx(1, "screenchange: screen not found");
errx(1, "screenchange: screen not found.");
/* brute force for now, just re-enumerate the regions */
scan_randr(i);
@ -12796,7 +12830,7 @@ setup_screens(void)
TAILQ_INIT(&screens[i].rl);
TAILQ_INIT(&screens[i].orl);
if ((screen = get_screen(i)) == NULL)
errx(1, "ERROR: can't get screen %d.", i);
errx(1, "ERROR: unable to get screen %d.", i);
screens[i].rate = SWM_RATE_DEFAULT;
screens[i].root = screen->root;
screens[i].depth = screen->root_depth;
@ -12955,13 +12989,13 @@ void
setup_globals(void)
{
if ((bar_fonts = strdup(SWM_BAR_FONTS)) == NULL)
err(1, "setup_globals: strdup: failed to allocate memory.");
err(1, "bar_fonts: strdup");
if ((clock_format = strdup("%a %b %d %R %Z %Y")) == NULL)
err(1, "setup_globals: strdup: failed to allocate memory.");
err(1, "clock_format: strdup");
if ((syms = xcb_key_symbols_alloc(conn)) == NULL)
errx(1, "unable to allocate key symbols");
errx(1, "unable to allocate key symbols.");
a_state = get_atom_from_string("WM_STATE");
a_prot = get_atom_from_string("WM_PROTOCOLS");
@ -13277,14 +13311,14 @@ main(int argc, char *argv[])
sigaction(SIGCHLD, &sact, NULL);
if ((display = XOpenDisplay(0)) == NULL)
errx(1, "can not open display");
errx(1, "unable to open display");
if (pledge("stdio proc exec rpath getpw", NULL) == -1)
err(1, "pledge");
conn = XGetXCBConnection(display);
if (xcb_connection_has_error(conn))
errx(1, "can not get XCB connection");
errx(1, "unable to get XCB connection");
XSetEventQueueOwner(display, XCBOwnsEventQueue);