wmfs/src/config.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;
}