491 lines
18 KiB
C
491 lines
18 KiB
C
/*
|
|
* config.c
|
|
* Copyright © 2008 Martin Duquesnoy <xorg62@gmail.com>
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above
|
|
* copyright notice, this list of conditions and the following disclaimer
|
|
* in the documentation and/or other materials provided with the
|
|
* distribution.
|
|
* * Neither the name of the nor the names of its
|
|
* contributors may be used to endorse or promote products derived from
|
|
* this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "config_struct.h"
|
|
|
|
|
|
void
|
|
conf_init_func_list(void)
|
|
{
|
|
int i;
|
|
|
|
func_name_list_t tmp_list[] =
|
|
{
|
|
{"spawn", uicb_spawn },
|
|
{"client_kill", uicb_client_kill },
|
|
{"client_prev", uicb_client_prev },
|
|
{"client_next", uicb_client_next },
|
|
{"toggle_max", uicb_togglemax },
|
|
{"layout_next", uicb_layout_next },
|
|
{"layout_prev", uicb_layout_prev },
|
|
{"tag", uicb_tag },
|
|
{"tag_next", uicb_tag_next },
|
|
{"tag_prev", uicb_tag_prev },
|
|
{"tag_transfert", uicb_tagtransfert },
|
|
{"set_mwfact", uicb_set_mwfact },
|
|
{"set_nmaster", uicb_set_nmaster },
|
|
{"quit", uicb_quit },
|
|
{"toggle_infobar_position", uicb_infobar_togglepos },
|
|
{"mouse_move", uicb_mouse_move },
|
|
{"mouse_resize", uicb_mouse_resize },
|
|
{"client_raise", uicb_client_raise },
|
|
{"tile_switch", uicb_tile_switch },
|
|
{"toggle_free", uicb_togglefree },
|
|
{"screen_select", uicb_screen_select },
|
|
{"screen_next", uicb_screen_next },
|
|
{"screen_prev", uicb_screen_prev },
|
|
{"reload", uicb_reload },
|
|
{"launcher", uicb_launcher },
|
|
{"set_layout", uicb_set_layout },
|
|
{"menu", uicb_menu }
|
|
};
|
|
|
|
func_list = emalloc(LEN(tmp_list), sizeof(func_name_list_t));
|
|
|
|
for(i = 0; i < LEN(tmp_list); ++i)
|
|
func_list[i] = tmp_list[i];
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/* The following function are the
|
|
different configuration section. {{{
|
|
*/
|
|
void
|
|
mouse_section(MouseBinding mb[], cfg_t *cfg, int ns)
|
|
{
|
|
int i;
|
|
cfg_t *tmp;
|
|
|
|
for(i = 0; i < ns; ++i)
|
|
{
|
|
tmp = cfg_getnsec(cfg, "mouse", i);
|
|
mb[i].tag = cfg_getint(tmp, "tag");
|
|
mb[i].screen = cfg_getint(tmp, "screen");
|
|
mb[i].button = char_to_button(cfg_getstr(tmp, "button"), mouse_button_list);
|
|
mb[i].func = name_to_func(cfg_getstr(tmp, "func"), func_list);
|
|
mb[i].cmd = _strdup(alias_to_str(cfg_getstr(tmp, "cmd")));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
conf_alias_section(cfg_t *cfg_a)
|
|
{
|
|
int i;
|
|
|
|
if(cfg_size(cfg_a, "alias") < 256)
|
|
for(i = 0; i < cfg_size(cfg_a, "alias"); ++i)
|
|
{
|
|
cfgtmp = cfg_getnsec(cfg_a, "alias", i);
|
|
conf.alias[i].name = _strdup(cfg_title(cfgtmp));
|
|
conf.alias[i].content = _strdup(cfg_getstr(cfgtmp, "content"));
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr,"WMFS Configuration: Too many alias (%d) !\n", cfg_size(cfg_a, "alias"));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
conf_misc_section(cfg_t *cfg_m)
|
|
{
|
|
conf.font = alias_to_str(_strdup(cfg_getstr(cfg_m, "font")));
|
|
conf.raisefocus = cfg_getbool(cfg_m, "raisefocus");
|
|
conf.raiseswitch = cfg_getbool(cfg_m, "raiseswitch");
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
conf_bar_section(cfg_t *cfg_b)
|
|
{
|
|
conf.border.bar = cfg_getbool(cfg_b, "border");
|
|
conf.colors.bar = getcolor(alias_to_str(cfg_getstr(cfg_b, "bg")));
|
|
conf.colors.text = _strdup(alias_to_str(cfg_getstr(cfg_b, "fg")));
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
conf_root_section(cfg_t *cfg_r)
|
|
{
|
|
conf.root.background_command = _strdup(alias_to_str(cfg_getstr(cfg_r, "background_command")));
|
|
conf.root.nmouse = cfg_size(cfg_r, "mouse");
|
|
if(conf.root.nmouse)
|
|
{
|
|
conf.root.mouse = emalloc(conf.root.nmouse, sizeof(MouseBinding));
|
|
mouse_section(conf.root.mouse, cfg_r, conf.root.nmouse);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
conf_client_section(cfg_t *cfg_c)
|
|
{
|
|
int i;
|
|
cfg_t *cfgtmp2;
|
|
|
|
/* Client misc */
|
|
conf.client.borderheight = (cfg_getint(cfg_c, "border_height")) ? cfg_getint(cfg_c, "border_height") : 1;
|
|
conf.client.place_at_mouse = cfg_getbool(cfg_c, "place_at_mouse");
|
|
conf.client.bordernormal = getcolor(alias_to_str(cfg_getstr(cfg_c, "border_normal")));
|
|
conf.client.borderfocus = getcolor(alias_to_str(cfg_getstr(cfg_c, "border_focus")));
|
|
conf.client.resizecorner_normal = getcolor(alias_to_str(cfg_getstr(cfg_c, "resize_corner_normal")));
|
|
conf.client.resizecorner_focus = getcolor(alias_to_str(cfg_getstr(cfg_c, "resize_corner_focus")));
|
|
conf.client.mod |= char_to_modkey(cfg_getstr(cfg_c, "modifier"), key_list);
|
|
|
|
if((conf.client.nmouse = cfg_size(cfg_c, "mouse")))
|
|
{
|
|
conf.client.mouse = emalloc(conf.client.nmouse, sizeof(MouseBinding));
|
|
mouse_section(conf.client.mouse, cfg_c, conf.client.nmouse);
|
|
}
|
|
|
|
/* Titlebar part {{ */
|
|
cfgtmp = cfg_getsec(cfg_c, "titlebar");
|
|
conf.titlebar.height = cfg_getint(cfgtmp, "height");
|
|
conf.titlebar.stipple = cfg_getbool(cfgtmp, "stipple");
|
|
conf.titlebar.fg_normal = alias_to_str(cfg_getstr(cfgtmp, "fg_normal"));
|
|
conf.titlebar.fg_focus = alias_to_str(cfg_getstr(cfgtmp, "fg_focus"));
|
|
|
|
if((conf.titlebar.nmouse = cfg_size(cfgtmp, "mouse")))
|
|
{
|
|
conf.titlebar.mouse = emalloc(conf.titlebar.nmouse, sizeof(MouseBinding));
|
|
mouse_section(conf.titlebar.mouse, cfgtmp, conf.titlebar.nmouse);
|
|
}
|
|
|
|
/* Multi button part */
|
|
if((conf.titlebar.nbutton = cfg_size(cfgtmp, "button")))
|
|
{
|
|
conf.titlebar.button = emalloc(conf.titlebar.nbutton, sizeof(Button));
|
|
for(i = 0; i < conf.titlebar.nbutton; ++i)
|
|
{
|
|
cfgtmp2 = cfg_getnsec(cfgtmp, "button", i);
|
|
if((conf.titlebar.button[i].nmouse = cfg_size(cfgtmp2, "mouse")))
|
|
{
|
|
conf.titlebar.button[i].mouse = emalloc(conf.titlebar.button[i].nmouse, sizeof(MouseBinding));
|
|
mouse_section(conf.titlebar.button[i].mouse, cfgtmp2, conf.titlebar.button[i].nmouse);
|
|
}
|
|
}
|
|
}
|
|
/* }} */
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
conf_layout_section(cfg_t *cfg_l)
|
|
{
|
|
int i;
|
|
|
|
/* Set conf.layout NULL for conf reload */
|
|
for(i = 0; i < NUM_OF_LAYOUT; ++i)
|
|
{
|
|
conf.layout[i].symbol = NULL;
|
|
conf.layout[i].func = NULL;
|
|
}
|
|
|
|
conf.border.layout = cfg_getbool(cfg_l, "border");
|
|
conf.colors.layout_fg = _strdup(alias_to_str(cfg_getstr(cfg_l, "fg")));
|
|
conf.colors.layout_bg = getcolor(alias_to_str(cfg_getstr(cfg_l, "bg")));
|
|
|
|
if(strcmp(_strdup(alias_to_str(cfg_getstr(cfg_l, "system"))), "menu") == 0)
|
|
conf.layout_system = True;
|
|
|
|
if((conf.nlayout = cfg_size(cfg_l, "layout")) > NUM_OF_LAYOUT
|
|
|| !(conf.nlayout = cfg_size(cfg_l, "layout")))
|
|
{
|
|
fprintf(stderr, "WMFS Configuration: Too many or no layouts (%d)\n", conf.nlayout);
|
|
conf.nlayout = 1;
|
|
conf.layout[0].symbol = _strdup("TILE");
|
|
conf.layout[0].func = tile;
|
|
}
|
|
|
|
if(conf.layout_system && conf.nlayout > 1)
|
|
menu_init(&menulayout, "menulayout", conf.nlayout,
|
|
/* Colors */
|
|
conf.colors.layout_bg,
|
|
conf.colors.layout_fg,
|
|
conf.colors.bar,
|
|
conf.colors.text);
|
|
|
|
if(!conf.layout[0].symbol
|
|
&& !conf.layout[0].func)
|
|
{
|
|
for(i = 0; i < conf.nlayout; ++i)
|
|
{
|
|
cfgtmp = cfg_getnsec(cfg_l, "layout", i);
|
|
if(!name_to_func(_strdup(cfg_getstr(cfgtmp, "type")), layout_list))
|
|
{
|
|
fprintf(stderr, "WMFS Configuration: Unknow Layout type: \"%s\"\n",
|
|
_strdup(cfg_getstr(cfgtmp, "type")));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
else
|
|
{
|
|
if(conf.layout_system && conf.nlayout > 1)
|
|
menu_new_item(&menulayout.item[i],
|
|
_strdup(alias_to_str(cfg_getstr(cfgtmp, "symbol"))),
|
|
uicb_set_layout, _strdup(cfg_getstr(cfgtmp, "type")));
|
|
|
|
conf.layout[i].symbol = _strdup(alias_to_str(cfg_getstr(cfgtmp, "symbol")));
|
|
conf.layout[i].func = name_to_func(_strdup(cfg_getstr(cfgtmp, "type")), layout_list);
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
conf_tag_section(cfg_t *cfg_t)
|
|
{
|
|
int i, j, k, l = 0;
|
|
char *tmp;
|
|
|
|
/* If there is no tag in the conf or more than
|
|
* MAXTAG (32) print an error and create only one.
|
|
*/
|
|
Tag default_tag = { "WMFS",
|
|
0.50, 1, False, IB_Top,
|
|
layout_name_to_struct(conf.layout, "tile_right", conf.nlayout, layout_list) };
|
|
|
|
conf.tag_round = cfg_getbool(cfg_t, "tag_round");
|
|
conf.colors.tagselfg = _strdup(alias_to_str(cfg_getstr(cfg_t, "sel_fg")));
|
|
conf.colors.tagselbg = getcolor(alias_to_str(cfg_getstr(cfg_t, "sel_bg")));
|
|
conf.colors.tag_occupied_bg = getcolor(alias_to_str(cfg_getstr(cfg_t, "occupied_bg")));
|
|
conf.border.tag = cfg_getbool(cfg_t, "border");
|
|
|
|
/* Alloc all */
|
|
conf.ntag = emalloc(screen_count(), sizeof(int));
|
|
tags = emalloc(screen_count(), sizeof(Tag*));
|
|
|
|
for(i = 0; i < screen_count(); ++i)
|
|
tags[i] = emalloc(cfg_size(cfg_t, "tag") + 1, sizeof(Tag));
|
|
|
|
for(i = 0; i < cfg_size(cfg_t, "tag"); ++i)
|
|
{
|
|
cfgtmp = cfg_getnsec(cfg_t, "tag", i);
|
|
j = cfg_getint(cfgtmp, "screen");
|
|
if(j < 0 || j > screen_count() - 1)
|
|
j = -1;
|
|
|
|
for(k = ((j == -1) ? 0 : j);
|
|
((j == -1) ? (k < screen_count()) : !l);
|
|
((j == -1) ? ++k : --l))
|
|
{
|
|
++conf.ntag[k];
|
|
tags[k][conf.ntag[k]].name = _strdup(cfg_getstr(cfgtmp, "name"));
|
|
tags[k][conf.ntag[k]].mwfact = cfg_getfloat(cfgtmp, "mwfact");
|
|
tags[k][conf.ntag[k]].nmaster = cfg_getint(cfgtmp, "nmaster");
|
|
tags[k][conf.ntag[k]].resizehint = cfg_getbool(cfgtmp, "resizehint");
|
|
|
|
tmp = _strdup(cfg_getstr(cfgtmp, "infobar_position"));
|
|
|
|
if(!strcmp(tmp ,"none")
|
|
|| !strcmp(tmp, "hide")
|
|
|| !strcmp(tmp, "hidden"))
|
|
tags[k][conf.ntag[k]].barpos = IB_Hide;
|
|
else if(!strcmp(tmp, "bottom")
|
|
|| !strcmp(tmp, "down"))
|
|
tags[k][conf.ntag[k]].barpos = IB_Bottom;
|
|
else
|
|
tags[k][conf.ntag[k]].barpos = IB_Top;
|
|
|
|
tags[k][conf.ntag[k]].layout = layout_name_to_struct(conf.layout, cfg_getstr(cfgtmp, "layout"),
|
|
conf.nlayout, layout_list);
|
|
}
|
|
l = 0;
|
|
}
|
|
|
|
for(i = 0; i < screen_count(); ++i)
|
|
if(!conf.ntag[i] || conf.ntag[i] > MAXTAG)
|
|
{
|
|
fprintf(stderr, "WMFS Configuration: Too many or no tag"
|
|
" (%d) in the screen %d\n", conf.ntag[i], i);
|
|
|
|
conf.ntag[i] = 1;
|
|
tags[i][1] = default_tag;
|
|
}
|
|
|
|
seltag = emalloc(screen_count(), sizeof(int));
|
|
|
|
for(j = 0; j < screen_count(); ++j)
|
|
seltag[j] = 1;
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
conf_menu_section(cfg_t *cfg_m)
|
|
{
|
|
cfg_t *cfgtmp2;
|
|
int i, j;
|
|
|
|
conf.nmenu = cfg_size(cfg_m, "set_menu");
|
|
CHECK(conf.nmenu);
|
|
conf.menu = emalloc(conf.nmenu, sizeof(Menu));
|
|
|
|
for(i = 0; i < conf.nmenu; ++i)
|
|
{
|
|
cfgtmp = cfg_getnsec(cfg_m, "set_menu", i);
|
|
|
|
conf.menu[i].name = _strdup(cfg_getstr(cfgtmp, "name"));
|
|
|
|
if(!(conf.menu[i].place_at_mouse = cfg_getbool(cfgtmp, "place_at_mouse")))
|
|
{
|
|
conf.menu[i].x = cfg_getint(cfgtmp, "x");
|
|
conf.menu[i].y = cfg_getint(cfgtmp, "y");
|
|
}
|
|
|
|
conf.menu[i].colors.focus.bg = getcolor(_strdup(cfg_getstr(cfgtmp, "bg_focus")));
|
|
conf.menu[i].colors.focus.fg = _strdup(cfg_getstr(cfgtmp, "fg_focus"));
|
|
conf.menu[i].colors.normal.bg = getcolor(_strdup(cfg_getstr(cfgtmp, "bg_normal")));
|
|
conf.menu[i].colors.normal.fg = _strdup(cfg_getstr(cfgtmp, "fg_normal"));
|
|
|
|
conf.menu[i].nitem = cfg_size(cfgtmp, "item");
|
|
|
|
if(conf.menu[i].nitem)
|
|
{
|
|
conf.menu[i].item = emalloc(conf.menu[i].nitem, sizeof(MenuItem));
|
|
for(j = 0; j < cfg_size(cfgtmp, "item"); ++j)
|
|
{
|
|
cfgtmp2 = cfg_getnsec(cfgtmp, "item", j);
|
|
|
|
conf.menu[i].item[j].name = _strdup(cfg_getstr(cfgtmp2, "name"));
|
|
conf.menu[i].item[j].func = name_to_func(_strdup(cfg_getstr(cfgtmp2, "func")), func_list);
|
|
conf.menu[i].item[j].cmd = (!_strdup(alias_to_str((cfg_getstr(cfgtmp2, "cmd"))))
|
|
? NULL : _strdup(alias_to_str(cfg_getstr(cfgtmp2, "cmd"))));
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
conf_launcher_section(cfg_t *cfg_l)
|
|
{
|
|
int i;
|
|
|
|
conf.nlauncher = cfg_size(cfg_l, "set_launcher");
|
|
CHECK(conf.nlauncher);
|
|
conf.launcher = emalloc(conf.nlauncher, sizeof(Launcher));
|
|
|
|
for(i = 0; i < conf.nlauncher; ++i)
|
|
{
|
|
cfgtmp = cfg_getnsec(cfg_l, "set_launcher", i);
|
|
|
|
conf.launcher[i].name = alias_to_str(_strdup(cfg_getstr(cfgtmp, "name")));
|
|
conf.launcher[i].prompt = alias_to_str(_strdup(cfg_getstr(cfgtmp, "prompt")));
|
|
conf.launcher[i].command = alias_to_str(_strdup(cfg_getstr(cfgtmp, "command")));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
conf_keybind_section(cfg_t *cfg_k)
|
|
{
|
|
int i, j;
|
|
|
|
conf.nkeybind = cfg_size(cfg_k, "key");
|
|
keys = emalloc(conf.nkeybind, sizeof(Key));
|
|
|
|
for(i = 0; i < conf.nkeybind; ++i)
|
|
{
|
|
cfgtmp = cfg_getnsec(cfg_k, "key", i);
|
|
|
|
for(j = 0; j < cfg_size(cfgtmp, "mod"); ++j)
|
|
keys[i].mod |= char_to_modkey(cfg_getnstr(cfgtmp, "mod", j), key_list);
|
|
|
|
keys[i].keysym = XStringToKeysym(cfg_getstr(cfgtmp, "key"));
|
|
keys[i].func = name_to_func(cfg_getstr(cfgtmp, "func"), func_list);
|
|
if(keys[i].func == NULL)
|
|
{
|
|
fprintf(stderr, "WMFS Configuration error: Unknow Function \"%s\"\n",
|
|
cfg_getstr(cfgtmp, "func"));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
keys[i].cmd = (!_strdup(alias_to_str((cfg_getstr(cfgtmp, "cmd"))))
|
|
? NULL : _strdup(alias_to_str(cfg_getstr(cfgtmp, "cmd"))));
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
/** Configuration initialization
|
|
*/
|
|
void
|
|
init_conf(void)
|
|
{
|
|
int ret;
|
|
|
|
sprintf(final_path, "%s/%s", _strdup(getenv("HOME")), _strdup(FILE_NAME));
|
|
|
|
cfg = cfg_init(opts, CFGF_NONE);
|
|
ret = cfg_parse(cfg, final_path);
|
|
|
|
if(ret == CFG_FILE_ERROR || ret == CFG_PARSE_ERROR)
|
|
{
|
|
fprintf(stderr, "WMFS: parsing configuration file (%s) failed\n", final_path);
|
|
sprintf(final_path, "%s/wmfs/wmfsrc", XDG_CONFIG_DIR);
|
|
fprintf(stderr, "Use the default configuration (%s).\n", final_path);
|
|
cfg = cfg_init(opts, CFGF_NONE);
|
|
ret = cfg_parse(cfg, final_path);
|
|
}
|
|
|
|
conf_init_func_list();
|
|
|
|
conf_alias_section(cfg_getsec(cfg, "alias"));
|
|
conf_misc_section(cfg_getsec(cfg, "misc"));
|
|
conf_bar_section(cfg_getsec(cfg, "bar"));
|
|
conf_root_section(cfg_getsec(cfg, "root"));
|
|
conf_client_section(cfg_getsec(cfg, "client"));
|
|
conf_layout_section(cfg_getsec(cfg, "layouts"));
|
|
conf_tag_section(cfg_getsec(cfg, "tags"));
|
|
conf_menu_section(cfg_getsec(cfg, "menu"));
|
|
conf_launcher_section(cfg_getsec(cfg, "launcher"));
|
|
conf_keybind_section(cfg_getsec(cfg, "keys"));
|
|
|
|
cfg_free(cfg);
|
|
|
|
return;
|
|
}
|