From 3e71c420d667d444e723e57a5a7ff992cd06adeb Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Tue, 10 Aug 2010 01:31:23 +0200 Subject: [PATCH 01/41] Client: Add "all" cmd option to clientlist uicb function to display all client in menu instead only in current tag --- src/client.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/client.c b/src/client.c index b251c8a..406495f 100644 --- a/src/client.c +++ b/src/client.c @@ -1342,13 +1342,17 @@ uicb_clientlist(uicb_t cmd) { int i, d, u, x, y; int n = 0; + Bool all = False; Window w; Client *c = NULL; screen_get_sel(); + if(cmd && !strcmp(cmd, "all")) + all = True; + for(c = clients; c; c = c->next) - if(!ishide(c, selscreen)) + if(!ishide(c, selscreen) || all) ++n; if(n > 0) @@ -1364,7 +1368,7 @@ uicb_clientlist(uicb_t cmd) conf.colors.text); for(i = 0, c = clients; c; c = c->next) - if(!ishide(c, selscreen)) + if(!ishide(c, selscreen) || all) { sprintf(clist_index[i].key, "%d", i); clist_index[i].client = c; @@ -1401,6 +1405,12 @@ uicb_client_select(uicb_t cmd) for(i = 0; i < MAXCLIST && clist_index[i].client; ++i) if(!strcmp(cmd, clist_index[i].key)) { + if(clist_index[i].client->screen != selscreen) + screen_set_sel(clist_index[i].client->screen); + + if(clist_index[i].client->tag != seltag[clist_index[i].client->screen]) + tag_set(clist_index[i].client->tag); + client_focus(clist_index[i].client); client_raise(clist_index[i].client); From 7a1bfb48f5464bd3918e107f9e8e4f7f8774a2c6 Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Tue, 10 Aug 2010 01:37:37 +0200 Subject: [PATCH 02/41] Menu: Set clientlist menu alignement to left for better visibility --- src/client.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/client.c b/src/client.c index 406495f..fa032d7 100644 --- a/src/client.c +++ b/src/client.c @@ -1367,6 +1367,8 @@ uicb_clientlist(uicb_t cmd) conf.colors.bar, conf.colors.text); + clientlist.align = MA_Left; + for(i = 0, c = clients; c; c = c->next) if(!ishide(c, selscreen) || all) { From a496d77f9e06d6ce71aae5157c5b95c6be211bd2 Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Tue, 10 Aug 2010 02:40:06 +0200 Subject: [PATCH 03/41] Conf: Add [rules] section. (Feature #34 requested by markand CHACHA) clients option, autofree and automax option are DEPRECATED but works for some revision. --- src/client.c | 28 ++++++++++++++++++++++++++++ src/config.c | 33 ++++++++++++++++++++++++++++++++- src/structs.h | 19 +++++++++++++++++++ src/wmfs.c | 1 + wmfsrc.in | 16 ++++++++++++++++ 5 files changed, 96 insertions(+), 1 deletion(-) diff --git a/src/client.c b/src/client.c index fa032d7..d9171ef 100644 --- a/src/client.c +++ b/src/client.c @@ -997,6 +997,8 @@ client_set_rules(Client *c) XGetClassHint(dpy, c->win, &xch); + /* Following features is DEPRECATED, will be removed in some revision. {{{ */ + /* Auto free */ if(conf.client.autofree && ((xch.res_name && strstr(conf.client.autofree, xch.res_name)) || (xch.res_class && strstr(conf.client.autofree, xch.res_class)))) @@ -1030,6 +1032,32 @@ client_set_rules(Client *c) tags[c->screen][c->tag].layout.func(c->screen); } + /* }}} */ + + /* Apply Rule if class || instance || role match */ + for(i = 0; i < conf.nrule; ++i) + { + if((xch.res_class && conf.rule[i].class && !strcmp(xch.res_class, conf.rule[i].class)) + || (xch.res_name && conf.rule[i].instance && !strcmp(xch.res_name, conf.rule[i].instance))) + { + if(conf.rule[i].screen != -1) + c->screen = conf.rule[i].screen; + + if(conf.rule[i].tag != -1) + c->tag = conf.rule[i].tag; + + if(conf.rule[i].free) + c->flags |= FreeFlag; + + if(conf.rule[i].max) + { + client_maximize(c); + c->flags |= MaxFlag; + } + } + } + + return; } diff --git a/src/config.c b/src/config.c index 89626f6..9bf9d2c 100644 --- a/src/config.c +++ b/src/config.c @@ -605,6 +605,36 @@ conf_tag_section(void) return; } +void +conf_rule_section(void) +{ + int i; + struct conf_sec *rules, **rule; + + rules = fetch_section_first(NULL, "rules"); + + rule = fetch_section(rules, "rule"); + + CHECK((conf.nrule = fetch_section_count(rule))); + + conf.rule = emalloc(conf.nrule, sizeof(Rule)); + + for(i = 0; i < conf.nrule; ++i) + { + conf.rule[i].class = fetch_opt_first(rule[i], "", "class").str; + conf.rule[i].instance = fetch_opt_first(rule[i], "", "instance").str; + conf.rule[i].role = fetch_opt_first(rule[i], "", "role").str; + conf.rule[i].screen = fetch_opt_first(rule[i], "-1", "screen").num; + conf.rule[i].tag = fetch_opt_first(rule[i], "-1", "tag").num; + conf.rule[i].free = fetch_opt_first(rule[i], "false", "free").bool; + conf.rule[i].max = fetch_opt_first(rule[i], "false", "max").bool; + } + + free(rule); + + return; +} + void conf_menu_section(void) { @@ -618,7 +648,7 @@ conf_menu_section(void) CHECK((conf.nmenu = fetch_section_count(set_menu))); - conf.menu = calloc(conf.nmenu, sizeof(Menu)); + conf.menu = emalloc(conf.nmenu, sizeof(Menu)); for(i = 0; i < conf.nmenu; ++i) { @@ -756,6 +786,7 @@ init_conf(void) conf_client_section(); conf_layout_section(); conf_tag_section(); + conf_rule_section(); conf_menu_section(); conf_launcher_section(); conf_keybind_section(); diff --git a/src/structs.h b/src/structs.h index 5da0fe4..b47e4ef 100644 --- a/src/structs.h +++ b/src/structs.h @@ -350,8 +350,25 @@ typedef struct { char *name; char *content; + char *role; + int screen; + int tag; + Bool free; + Bool max; } Alias; +/* Rule struct */ +typedef struct +{ + char *class; + char *instance; + char *role; + int screen; + int tag; + Bool free; + Bool max; +} Rule; + /* Configuration structure */ typedef struct { @@ -460,6 +477,7 @@ typedef struct Layout layout[NUM_OF_LAYOUT]; Menu *menu; Launcher *launcher; + Rule *rule; int *ntag; Bool tag_round; Bool client_round; @@ -472,6 +490,7 @@ typedef struct int nlayout; int nmenu; int nlauncher; + int nrule; } Conf; typedef struct diff --git a/src/wmfs.c b/src/wmfs.c index 5ccb47e..fc11c6f 100644 --- a/src/wmfs.c +++ b/src/wmfs.c @@ -118,6 +118,7 @@ quit(void) } IFREE(conf.launcher); + IFREE(conf.rule); IFREE(conf.bars.mouse); IFREE(conf.selbar.mouse); diff --git a/wmfsrc.in b/wmfsrc.in index b58ee46..92fbfeb 100644 --- a/wmfsrc.in +++ b/wmfsrc.in @@ -127,6 +127,7 @@ #[mouse] [/mouse] Possible multi mouse section [/tag] + # clients option is *DEPRECATED* but works, see [rules] section [tag] name = "two" clients = {"Browser"} [/tag] [tag] name = "three" [/tag] [tag] name = "four" [/tag] @@ -161,6 +162,7 @@ # Modifier for mouse use modifier = "Alt" + # *DEPRECATED* but works, see [rules] section # Set automatic free or max client # autofree = "xterm|MPlayer" # automax = "Navigator" @@ -195,6 +197,20 @@ [/titlebar] [/client] +[rules] + # Example of rule for Mplayer + [rule] + + class = "MPlayer" # First part of WM_CLASS + instance = "xv" # Seconf part of WM_CLASS, not needed if first part is correct + # role = "" # WM_WINDOW_ROLE (will be implemented) + screen = 0 # Screen to use + tag = 2 # Tag number of apps + free = true # Set automatic free client + max = false # Set automatic maximized client + [/rule] +[/rules] + [menu] # Default menu, binded on the root window, button 3. [set_menu] From d8d09f9e1af23b6b46922b04648c3b9a119f09be Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Tue, 10 Aug 2010 02:47:14 +0200 Subject: [PATCH 04/41] Struct: Fix mistake in Alias struct --- src/structs.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/structs.h b/src/structs.h index b47e4ef..845efb6 100644 --- a/src/structs.h +++ b/src/structs.h @@ -350,11 +350,6 @@ typedef struct { char *name; char *content; - char *role; - int screen; - int tag; - Bool free; - Bool max; } Alias; /* Rule struct */ From 5d7f4a238297d24e8110f8866d8c18892592bdbe Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Tue, 10 Aug 2010 03:22:22 +0200 Subject: [PATCH 05/41] Config: Add WM_WINDOW_ROLE match in rule section --- src/client.c | 21 +++++++++++++++++---- wmfsrc.in | 2 +- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/client.c b/src/client.c index d9171ef..36c0f0a 100644 --- a/src/client.c +++ b/src/client.c @@ -987,7 +987,11 @@ void client_set_rules(Client *c) { XClassHint xch = { 0 }; - int i, j, k; + int i, j, k, f; + Atom rf; + ulong n, il; + uchar *data = NULL; + char wwrole[256] = { 0 }; if(conf.ignore_next_client_rules) { @@ -995,9 +999,18 @@ client_set_rules(Client *c) return; } + /* Get WM_CLASS */ XGetClassHint(dpy, c->win, &xch); - /* Following features is DEPRECATED, will be removed in some revision. {{{ */ + /* Get WM_WINDOW_ROLE */ + if(XGetWindowProperty(dpy, c->win, ATOM("WM_WINDOW_ROLE"), 0L, 0x7FFFFFFFL, False, + XA_STRING, &rf, &f, &n, &il, &data) == Success && data) + { + strcpy(wwrole, (char*)data); + XFree(data); + } + + /* Following features is *DEPRECATED*, will be removed in some revision. {{{ */ /* Auto free */ if(conf.client.autofree && ((xch.res_name && strstr(conf.client.autofree, xch.res_name)) @@ -1038,7 +1051,8 @@ client_set_rules(Client *c) for(i = 0; i < conf.nrule; ++i) { if((xch.res_class && conf.rule[i].class && !strcmp(xch.res_class, conf.rule[i].class)) - || (xch.res_name && conf.rule[i].instance && !strcmp(xch.res_name, conf.rule[i].instance))) + || (xch.res_name && conf.rule[i].instance && !strcmp(xch.res_name, conf.rule[i].instance)) + || (strlen(wwrole) && conf.rule[i].role && !strcmp(wwrole, conf.rule[i].role))) { if(conf.rule[i].screen != -1) c->screen = conf.rule[i].screen; @@ -1057,7 +1071,6 @@ client_set_rules(Client *c) } } - return; } diff --git a/wmfsrc.in b/wmfsrc.in index 92fbfeb..afe0cb5 100644 --- a/wmfsrc.in +++ b/wmfsrc.in @@ -203,7 +203,7 @@ class = "MPlayer" # First part of WM_CLASS instance = "xv" # Seconf part of WM_CLASS, not needed if first part is correct - # role = "" # WM_WINDOW_ROLE (will be implemented) + # role = "" # WM_WINDOW_ROLE screen = 0 # Screen to use tag = 2 # Tag number of apps free = true # Set automatic free client From ec2c2f6337d1418f509b665bf74d5881ba73972a Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Tue, 10 Aug 2010 03:38:53 +0200 Subject: [PATCH 06/41] Client: Fixes details in client_set_rule --- src/client.c | 8 ++++++++ wmfsrc.in | 5 ++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/client.c b/src/client.c index 36c0f0a..0a5c04d 100644 --- a/src/client.c +++ b/src/client.c @@ -1068,6 +1068,14 @@ client_set_rules(Client *c) client_maximize(c); c->flags |= MaxFlag; } + + if(c->tag != seltag[selscreen]) + { + tags[c->screen][c->tag].request_update = True; + client_focus(NULL); + } + + tags[c->screen][c->tag].layout.func(c->screen); } } diff --git a/wmfsrc.in b/wmfsrc.in index afe0cb5..daf22d4 100644 --- a/wmfsrc.in +++ b/wmfsrc.in @@ -200,9 +200,8 @@ [rules] # Example of rule for Mplayer [rule] - - class = "MPlayer" # First part of WM_CLASS - instance = "xv" # Seconf part of WM_CLASS, not needed if first part is correct + instance = "xv" # First part of WM_CLASS + class = "MPlayer" # Seconf part of WM_CLASS, not needed if first part is correct # role = "" # WM_WINDOW_ROLE screen = 0 # Screen to use tag = 2 # Tag number of apps From 86b20ba79922b6c6446c6f96244fc8a07a9ddae6 Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Tue, 10 Aug 2010 10:45:01 +0200 Subject: [PATCH 07/41] Client: Fix role usage in rule section --- src/client.c | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/src/client.c b/src/client.c index 0a5c04d..751908c 100644 --- a/src/client.c +++ b/src/client.c @@ -1051,31 +1051,33 @@ client_set_rules(Client *c) for(i = 0; i < conf.nrule; ++i) { if((xch.res_class && conf.rule[i].class && !strcmp(xch.res_class, conf.rule[i].class)) - || (xch.res_name && conf.rule[i].instance && !strcmp(xch.res_name, conf.rule[i].instance)) - || (strlen(wwrole) && conf.rule[i].role && !strcmp(wwrole, conf.rule[i].role))) + || (xch.res_name && conf.rule[i].instance && !strcmp(xch.res_name, conf.rule[i].instance))) { - if(conf.rule[i].screen != -1) - c->screen = conf.rule[i].screen; - - if(conf.rule[i].tag != -1) - c->tag = conf.rule[i].tag; - - if(conf.rule[i].free) - c->flags |= FreeFlag; - - if(conf.rule[i].max) + if((strlen(wwrole) && conf.rule[i].role && !strcmp(wwrole, conf.rule[i].role)) || !strlen(wwrole)) { - client_maximize(c); - c->flags |= MaxFlag; - } + if(conf.rule[i].screen != -1) + c->screen = conf.rule[i].screen; - if(c->tag != seltag[selscreen]) - { - tags[c->screen][c->tag].request_update = True; - client_focus(NULL); - } + if(conf.rule[i].tag != -1) + c->tag = conf.rule[i].tag; - tags[c->screen][c->tag].layout.func(c->screen); + if(conf.rule[i].free) + c->flags |= FreeFlag; + + if(conf.rule[i].max) + { + client_maximize(c); + c->flags |= MaxFlag; + } + + if(c->tag != seltag[selscreen]) + { + tags[c->screen][c->tag].request_update = True; + client_focus(NULL); + } + + tags[c->screen][c->tag].layout.func(c->screen); + } } } From 695cf697908155981dd20a4335da63b3b0ffc770 Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Tue, 10 Aug 2010 14:21:17 +0200 Subject: [PATCH 08/41] Client: Fixed wm_window_role condition in rules function --- src/client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client.c b/src/client.c index 751908c..4daefe7 100644 --- a/src/client.c +++ b/src/client.c @@ -1053,7 +1053,7 @@ client_set_rules(Client *c) if((xch.res_class && conf.rule[i].class && !strcmp(xch.res_class, conf.rule[i].class)) || (xch.res_name && conf.rule[i].instance && !strcmp(xch.res_name, conf.rule[i].instance))) { - if((strlen(wwrole) && conf.rule[i].role && !strcmp(wwrole, conf.rule[i].role)) || !strlen(wwrole)) + if((strlen(wwrole) && conf.rule[i].role && !strcmp(wwrole, conf.rule[i].role)) || (!strlen(wwrole) || !conf.rule[i].role)) { if(conf.rule[i].screen != -1) c->screen = conf.rule[i].screen; @@ -1070,7 +1070,7 @@ client_set_rules(Client *c) c->flags |= MaxFlag; } - if(c->tag != seltag[selscreen]) + if(c->tag != seltag[c->screen]) { tags[c->screen][c->tag].request_update = True; client_focus(NULL); From 5d9ad3e1dbc38a9d66d3eff34998e14d923e2207 Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Tue, 10 Aug 2010 14:22:03 +0200 Subject: [PATCH 09/41] Client: Fix mistake --- src/client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.c b/src/client.c index 4daefe7..d915cf4 100644 --- a/src/client.c +++ b/src/client.c @@ -1070,7 +1070,7 @@ client_set_rules(Client *c) c->flags |= MaxFlag; } - if(c->tag != seltag[c->screen]) + if(c->tag != seltag[selscreen]) { tags[c->screen][c->tag].request_update = True; client_focus(NULL); From dc2e571e5e4047ae05d980d833f269c110b499bb Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Thu, 12 Aug 2010 19:57:00 +0200 Subject: [PATCH 10/41] Config: Fix UGLY mistake (lenght -> length, thanks chacha) --- src/config.c | 2 +- src/infobar.c | 8 ++++---- src/structs.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/config.c b/src/config.c index 9bf9d2c..9843abd 100644 --- a/src/config.c +++ b/src/config.c @@ -219,7 +219,7 @@ conf_bar_section(void) conf.selbar.bg = getcolor(fetch_opt_first(selbar, barbg, "bg").str); conf.selbar.fg = fetch_opt_first(selbar, conf.colors.text, "fg").str; - conf.selbar.maxlenght = fetch_opt_first(selbar, "-1", "max_lenght").num; + conf.selbar.maxlength = fetch_opt_first(selbar, "-1", "max_length").num; mouse = fetch_section(selbar, "mouse"); diff --git a/src/infobar.c b/src/infobar.c index 8cd45d5..22f1f6f 100644 --- a/src/infobar.c +++ b/src/infobar.c @@ -188,12 +188,12 @@ infobar_draw_selbar(int sc) else if(sel && !infobar[sc].selbar->mapped) barwin_map(infobar[sc].selbar); - if(conf.selbar.maxlenght >= 0 && sel) + if(conf.selbar.maxlength >= 0 && sel) { - str = emalloc(conf.selbar.maxlenght + 4, sizeof(char)); - strncpy(str, sel->title, conf.selbar.maxlenght); + str = emalloc(conf.selbar.maxlength + 4, sizeof(char)); + strncpy(str, sel->title, conf.selbar.maxlength); - if(strlen(sel->title) > conf.selbar.maxlenght) + if(strlen(sel->title) > conf.selbar.maxlength) strcat(str, "..."); } diff --git a/src/structs.h b/src/structs.h index 845efb6..089f08b 100644 --- a/src/structs.h +++ b/src/structs.h @@ -414,7 +414,7 @@ typedef struct { char *fg; uint bg; - int maxlenght; + int maxlength; MouseBinding *mouse; int nmouse; } selbar; From 7b0113ab6e427a15e955ae90b6bec9618d8a354a Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Thu, 12 Aug 2010 20:23:09 +0200 Subject: [PATCH 11/41] Config: Fix mistaken option --- wmfsrc.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wmfsrc.in b/wmfsrc.in index daf22d4..12134b0 100644 --- a/wmfsrc.in +++ b/wmfsrc.in @@ -37,7 +37,7 @@ fg = "#D4D4ff" # Cut title lenght - # max_lenght = 25 + # max_length = 25 [mouse] button = "3" func = "clientlist" [/mouse] [mouse] button = "4" func = "client_next" [/mouse] From 5017c4ced569407009ad00f68033ea0e23ab5c12 Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Thu, 12 Aug 2010 21:58:28 +0200 Subject: [PATCH 12/41] Config: Apply PeVe/mseed patch: layout_button_width option in [layouts] section. Thanks to them. --- src/config.c | 1 + src/infobar.c | 6 +++--- src/launcher.c | 2 +- src/structs.h | 1 + wmfsrc.in | 5 ++++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/config.c b/src/config.c index 9843abd..0714721 100644 --- a/src/config.c +++ b/src/config.c @@ -393,6 +393,7 @@ conf_layout_section(void) layouts = fetch_section_first(NULL, "layouts"); + conf.layout_button_width = fetch_opt_first(layouts, "O", "layout_button_width").num; conf.border.layout = fetch_opt_first(layouts, "false", "border").bool; conf.colors.layout_fg = fetch_opt_first(layouts, "#ffffff", "fg").str; conf.colors.layout_bg = getcolor((fetch_opt_first(layouts, "#000000", "bg").str)); diff --git a/src/infobar.c b/src/infobar.c index 22f1f6f..eeda99d 100644 --- a/src/infobar.c +++ b/src/infobar.c @@ -95,7 +95,7 @@ infobar_init(void) /* Create layout switch barwindow */ infobar[sc].layout_button = barwin_create(infobar[sc].bar->win, ((conf.layout_placement) ? 0 : (j + PAD / 2)), 0, - textw(tags[sc][seltag[sc]].layout.symbol) + PAD, + ((conf.layout_button_width > 0) ? conf.layout_button_width : (textw(tags[sc][seltag[sc]].layout.symbol) + PAD)), infobar[sc].geo.height, conf.colors.layout_bg, conf.colors.layout_fg, False, False, conf.border.layout); @@ -159,7 +159,7 @@ infobar_draw_layout(int sc) if(!conf.layout_placement) barwin_move(infobar[sc].layout_button, infobar[sc].tags_board->geo.width + PAD / 2, 0); - barwin_resize(infobar[sc].layout_button, textw(tags[sc][seltag[sc]].layout.symbol) + PAD, infobar[sc].geo.height); + barwin_resize(infobar[sc].layout_button, ((conf.layout_button_width > 0) ? conf.layout_button_width : (textw(tags[sc][seltag[sc]].layout.symbol) + PAD)), infobar[sc].geo.height); barwin_refresh_color(infobar[sc].layout_button); if(tags[sc][seltag[sc]].layout.symbol) @@ -225,7 +225,7 @@ infobar_draw_taglist(int sc) Bool is_occupied[MAXTAG + 1]; if(conf.layout_placement) - barwin_move(infobar[sc].tags_board, textw(tags[sc][seltag[sc]].layout.symbol) + PAD * 1.5, 0); + barwin_move(infobar[sc].tags_board, ((conf.layout_button_width > 0) ? conf.layout_button_width : (textw(tags[sc][seltag[sc]].layout.symbol) + PAD)) + PAD / 2, 0); for(i = 0; i < MAXTAG; i++) is_occupied[i] = False; diff --git a/src/launcher.c b/src/launcher.c index 2f0d1fa..629b21f 100644 --- a/src/launcher.c +++ b/src/launcher.c @@ -61,7 +61,7 @@ launcher_execute(Launcher *launcher) x = (conf.layout_placement) ? (infobar[selscreen].tags_board->geo.x + infobar[selscreen].tags_board->geo.width) - : (infobar[selscreen].layout_button->geo.x + textw(tags[selscreen][seltag[selscreen]].layout.symbol) + PAD); + : (infobar[selscreen].layout_button->geo.x + infobar[selscreen].layout_button->geo.width); XGrabKeyboard(dpy, ROOT, True, GrabModeAsync, GrabModeAsync, CurrentTime); diff --git a/src/structs.h b/src/structs.h index 089f08b..2e78232 100644 --- a/src/structs.h +++ b/src/structs.h @@ -469,6 +469,7 @@ typedef struct } systray; Alias alias[256]; uint mouse_tag_action[TagActionLast]; + int layout_button_width; Layout layout[NUM_OF_LAYOUT]; Menu *menu; Launcher *launcher; diff --git a/wmfsrc.in b/wmfsrc.in index 12134b0..e83bbe7 100644 --- a/wmfsrc.in +++ b/wmfsrc.in @@ -36,7 +36,7 @@ bg = "#191919" fg = "#D4D4ff" - # Cut title lenght + # Cut title length # max_length = 25 [mouse] button = "3" func = "clientlist" [/mouse] @@ -65,6 +65,9 @@ # Symbol displayed for the selected layout in the list selected_layout_symbol = "*" + # Width of layout button + # layout_button_width = x + # Tiling layouts. [layout] type = "tile_right" symbol = "RIGHT" [/layout] [layout] type = "tile_left" symbol = "LEFT" [/layout] From 179c94f26f11de063601c736b3e96ddbf4bedc0c Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Fri, 13 Aug 2010 03:11:44 +0200 Subject: [PATCH 13/41] Menu: Apply PeVe/mseed path: Menu optimisation/improvment and some fixation --- src/barwin.c | 20 ++++++++++++++++++++ src/draw.c | 10 ++++++++-- src/menu.c | 37 +++++++++++++++++++++++++++---------- src/wmfs.h | 5 ++++- 4 files changed, 59 insertions(+), 13 deletions(-) diff --git a/src/barwin.c b/src/barwin.c index 2b0fad9..7cdd641 100644 --- a/src/barwin.c +++ b/src/barwin.c @@ -123,6 +123,26 @@ barwin_draw_text(BarWindow *bw, int x, int y, char *text) return; } +/** Draw text in a Barwindow +*/ +void +barwin_draw_image_ofset_text(BarWindow *bw, int x, int y, char *text, int x_image_ofset, int y_image_ofset) +{ + if(!text) + return; + + /* Background color of the text if there is stipple */ + if(bw->stipple) + draw_rectangle(bw->dr, x - 4, 0, textw(text) + 8, bw->geo.height, bw->bg); + + /* Draw text */ + draw_image_ofset_text(bw->dr, x, y, bw->fg, 0, text, x_image_ofset, y_image_ofset); + + barwin_refresh(bw); + + return; +} + /** Delete a BarWindow * \param bw BarWindow pointer */ diff --git a/src/draw.c b/src/draw.c index 872a278..9ee9680 100644 --- a/src/draw.c +++ b/src/draw.c @@ -32,6 +32,12 @@ #include "wmfs.h" +void +draw_text(Drawable d, int x, int y, char* fg, int pad, char *str) +{ + draw_image_ofset_text(d, x, y, fg, pad, str, 0, 0); +} + /** Draw a string in a Drawable * \param d Drawable * \param x X position @@ -41,7 +47,7 @@ * \param str String that will be draw */ void -draw_text(Drawable d, int x, int y, char* fg, int pad, char *str) +draw_image_ofset_text(Drawable d, int x, int y, char* fg, int pad, char *str, int x_image_ofset, int y_image_ofset) { XftColor xftcolor; XftDraw *xftd; @@ -65,7 +71,7 @@ draw_text(Drawable d, int x, int y, char* fg, int pad, char *str) sw = systray_get_width(); for(i = 0; i < ni; ++i) - draw_image(d, im[i].x - sw, im[i].y, im[i].w, im[i].h, im[i].name); + draw_image(d, x_image_ofset + im[i].x - sw, y_image_ofset + im[i].y, im[i].w, im[i].h, im[i].name); } #endif /* HAVE_IMLIB */ diff --git a/src/menu.c b/src/menu.c index a2b289a..ece0138 100644 --- a/src/menu.c +++ b/src/menu.c @@ -68,7 +68,11 @@ menu_draw(Menu menu, int x, int y) BarWindow *item[menu.nitem]; BarWindow *frame; - width = menu_get_longer_string(menu.item, menu.nitem) + PAD * 3; + int chcklen = 0; + if(menu_get_checkstring_needed(menu.item, menu.nitem)) + chcklen = textw(conf.selected_layout_symbol) + PAD / 3; + + width = menu_get_longer_string(menu.item, menu.nitem) + chcklen + textw(">") + PAD * 3; height = menu.nitem * (INFOBARH - SHADH); /* Frame barwin */ @@ -99,7 +103,7 @@ menu_draw(Menu menu, int x, int y) barwin_map(item[i]); barwin_refresh_color(item[i]); - menu_draw_item_name(&menu, i, item); + menu_draw_item_name(&menu, i, item, chcklen); barwin_refresh(item[i]); } @@ -209,6 +213,9 @@ Bool menu_activate_item(Menu *menu, int i) { int j, x, y; + int chcklen = 0; + if(menu_get_checkstring_needed(menu->item, menu->nitem)) + chcklen = textw(conf.selected_layout_symbol) + PAD / 3; if(menu->item[i].submenu) { @@ -216,7 +223,7 @@ menu_activate_item(Menu *menu, int i) if(!strcmp(menu->item[i].submenu, conf.menu[j].name)) { y = menu->y + ((i - 1) * INFOBARH + PAD) - SHADH * 2; - x = menu->x + menu_get_longer_string(menu->item, menu->nitem) + PAD * 3; + x = menu->x + menu_get_longer_string(menu->item, menu->nitem) + chcklen + textw(">") + PAD * 3; menu_draw(conf.menu[j], x, y); @@ -238,6 +245,10 @@ menu_focus_item(Menu *menu, int item, BarWindow *winitem[]) { int i; + int chcklen = 0; + if(menu_get_checkstring_needed(menu->item, menu->nitem)) + chcklen = textw(conf.selected_layout_symbol) + PAD / 3; + menu->focus_item = item; if(menu->focus_item > menu->nitem - 1) @@ -251,7 +262,7 @@ menu_focus_item(Menu *menu, int item, BarWindow *winitem[]) winitem[i]->bg = ((i == menu->focus_item) ? menu->colors.focus.bg : menu->colors.normal.bg); barwin_refresh_color(winitem[i]); - menu_draw_item_name(menu, i, winitem); + menu_draw_item_name(menu, i, winitem, chcklen); barwin_refresh(winitem[i]); } @@ -259,29 +270,29 @@ menu_focus_item(Menu *menu, int item, BarWindow *winitem[]) } void -menu_draw_item_name(Menu *menu, int item, BarWindow *winitem[]) +menu_draw_item_name(Menu *menu, int item, BarWindow *winitem[], int chcklen) { int x; - int width = menu_get_longer_string(menu->item, menu->nitem); + int width = menu_get_longer_string(menu->item, menu->nitem) + chcklen + PAD / 3; switch(menu->align) { case MA_Left: - x = PAD * 3 / 2; + x = chcklen + PAD / 2; break; case MA_Right: x = width - textw(menu->item[item].name) + PAD * 3 / 2; break; default: case MA_Center: - x = width / 2 - textw(menu->item[item].name) / 2 + PAD * 3 / 2; + x = (width - (chcklen + PAD / 3)) / 2 - textw(menu->item[item].name) / 2 + chcklen + PAD / 3; break; } - barwin_draw_text(winitem[item], x, FHINFOBAR, menu->item[item].name); + barwin_draw_image_ofset_text(winitem[item], x, FHINFOBAR, menu->item[item].name, chcklen + PAD / 2, 0); if(menu->item[item].check) if(menu->item[item].check(menu->item[item].cmd)) - barwin_draw_text(winitem[item], PAD / 3, FHINFOBAR, conf.selected_layout_symbol); + barwin_draw_image_ofset_text(winitem[item], PAD / 3, FHINFOBAR, conf.selected_layout_symbol, PAD / 3, 0); if(menu->item[item].submenu) barwin_draw_text(winitem[item], width + PAD * 2, FHINFOBAR, ">"); @@ -340,3 +351,9 @@ menu_clear(Menu *menu) return; } +Bool +menu_get_checkstring_needed(MenuItem *mi, int nitem) +{ + return True; +} + diff --git a/src/wmfs.h b/src/wmfs.h index f3c0033..f0a1a98 100644 --- a/src/wmfs.h +++ b/src/wmfs.h @@ -122,6 +122,7 @@ BarWindow *barwin_create(Window parent, Bool stipple, Bool border); void barwin_draw_text(BarWindow *bw, int x, int y, char *text); +void barwin_draw_image_ofset_text(BarWindow *bw, int x, int y, char *text, int x_image_ofset, int y_image_ofset); void barwin_delete(BarWindow *bw); void barwin_delete_subwin(BarWindow *bw); void barwin_map(BarWindow *bw); @@ -135,6 +136,7 @@ void barwin_refresh(BarWindow *bw); /* draw.c */ void draw_text(Drawable d, int x, int y, char* fg, int pad, char *str); +void draw_image_ofset_text(Drawable d, int x, int y, char* fg, int pad, char *str, int x_image_ofset, int y_image_ofset); void draw_rectangle(Drawable dr, int x, int y, uint w, uint h, uint color); void draw_graph(Drawable dr, int x, int y, uint w, uint h, uint color, char *data); @@ -258,10 +260,11 @@ void menu_draw(Menu menu, int x, int y); Bool menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[]); Bool menu_activate_item(Menu *menu, int i); void menu_focus_item(Menu *menu, int item, BarWindow *winitem[]); -void menu_draw_item_name(Menu *menu, int item, BarWindow *winitem[]); +void menu_draw_item_name(Menu *menu, int item, BarWindow *winitem[], int chcklen); int menu_get_longer_string(MenuItem *mi, int nitem); void uicb_menu(uicb_t cmd); void menu_clear(Menu *menu); +Bool menu_get_checkstring_needed(MenuItem *mi, int nitem); /* launcher.c */ void launcher_execute(Launcher *launcher); From cf565c9b57526125e37ab0855cf75ba4dbe08677 Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Wed, 18 Aug 2010 13:36:55 +0200 Subject: [PATCH 14/41] Config: Apply mseed/PeVe great patch: Add conf split with @include "file". Thanks to Czech WMFS dev team :) --- src/parse/parse.c | 118 ++++++++++++++++++++++++++++++++++++++++++---- src/parse/parse.h | 7 +++ 2 files changed, 115 insertions(+), 10 deletions(-) diff --git a/src/parse/parse.c b/src/parse/parse.c index 65dba6e..8abad3c 100644 --- a/src/parse/parse.c +++ b/src/parse/parse.c @@ -223,35 +223,130 @@ get_kw_name(enum conf_type type) } #endif -int -get_conf(const char *name) +char * +load_file(const char *name) { int fd; struct stat st; char *buf; - struct conf_sec *s; + char *buffer; if (!name) - return (-1); + return NULL; - if ((fd = open(name, O_RDONLY)) == -1 || - stat(name, &st) == -1) + if ((fd = open(name, O_RDONLY)) == -1 || stat(name, &st) == -1) { - warn("%s", name); - return (-1); + warn("%s not read", name); + return NULL; } buf = (char*)mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, SEEK_SET); if (buf == (char*) MAP_FAILED) - return -1; + return NULL; - get_keyword(buf, st.st_size); + buffer = strdup(buf); munmap(buf, st.st_size); close(fd); warnx("%s read", name); + return buffer; +} + +int +get_conf(const char *name) +{ + char *buf; + struct conf_sec *s; + char inc[] = "@include \""; + char inc_end[] = "\""; + char *pos = NULL; + char *pos_end = NULL; + char *tmpname = NULL; + char *tmpbuf = NULL; + char *buffer = NULL; + + char *xpos = NULL; + char *xend = NULL; + int xl; + + char *inc_list = NULL; + char *tmp_inc_list = NULL; + char *incname = NULL; + char *tmp_inc = NULL; + + if (!name) + return (-1); + + /* remember name for duplicity include */ + tmp_inc = strdup(name); + incname = patht(tmp_inc); + free(tmp_inc); + inc_list = (char *) malloc(sizeof(char) * (strlen(incname) + 3)); + strcpy(inc_list, "["); + strcat(inc_list, incname); + strcat(inc_list, "]"); + buf = load_file(incname); + + if(!buf) + return (-1); + + pos = strstr(buf, inc); + + while(pos && (strlen(buf) > 0)) + { + xpos = strstr(buf, inc); + xpos = xpos + strlen(inc); + xend = strstr(xpos, inc_end); + xl = xend - xpos; + tmpname = (char *)malloc(sizeof(char) * (xl + 1)); + strncpy(tmpname, xpos, xl); + memset(tmpname + xl, 0, sizeof(char)); + pos_end = xend + strlen(inc_end); + + /* test and remember tmpname for duplicity include */ + incname = patht(tmpname); + tmp_inc = (char *) malloc(sizeof(char) * (strlen(incname) + 3)); + strcpy(tmp_inc, "["); + strcat(tmp_inc, incname); + strcat(tmp_inc, "]"); + tmpbuf = NULL; + + if(!strstr(inc_list, tmp_inc)) + { + tmp_inc_list = (char *) malloc(sizeof(char) * (strlen(tmp_inc) + strlen(inc_list) + 5)); + strcpy(tmp_inc_list, "\r\n"); + strcat(tmp_inc_list, inc_list); + strcat(tmp_inc_list, tmp_inc); + strcat(tmp_inc_list, "\r\n"); + free(inc_list); + + inc_list = tmp_inc_list; + + tmpbuf = load_file(incname); + } + + free(tmpname); + + if(!tmpbuf) + tmpbuf = strdup(""); + + buffer = (char *)malloc(sizeof(char) * (strlen(buf) + strlen(tmpbuf) + 1)); + strncpy(buffer, buf, (pos - buf)); + strcat(buffer, tmpbuf); + strcat(buffer, pos_end); + free(buf); + + if(tmpbuf) + free(tmpbuf); + + buf = buffer; + pos = strstr(buf, inc); + } + + get_keyword(buf, strlen(buf)); + file.name = name; curk = TAILQ_FIRST(&keywords); @@ -270,6 +365,9 @@ get_conf(const char *name) break; } } + + free(buf); + return 0; } diff --git a/src/parse/parse.h b/src/parse/parse.h index 78bc737..9d5b9d5 100644 --- a/src/parse/parse.h +++ b/src/parse/parse.h @@ -44,6 +44,13 @@ struct opt_type { char *str; }; +/* + * Load all text from file + * return new char* on succes - needs to use free() to delete + * return NULL on failure + */ +char * load_file(const char *name); + /* * Create config from file * return -1 on failure From e9ffab7d62af052c84e3a254ddf233f9b031652c Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Wed, 18 Aug 2010 19:41:47 +0200 Subject: [PATCH 15/41] Client: Fix client_get_prev/next not working when screen switching with mouse --- src/client.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/client.c b/src/client.c index d915cf4..c769cb1 100644 --- a/src/client.c +++ b/src/client.c @@ -93,6 +93,8 @@ client_get_next(void) { Client *c = NULL; + screen_get_sel(); + if(!sel || ishide(sel, selscreen)) return NULL; @@ -112,6 +114,8 @@ client_get_prev(void) { Client *c = NULL, *d; + screen_get_sel(); + if(!sel || ishide(sel, selscreen)) return NULL; @@ -745,6 +749,9 @@ client_manage(Window w, XWindowAttributes *wa, Bool ar) if(!conf.client.set_new_win_master) layout_set_client_master(c); + + cient_moveresize(c, c->geo, False); + return c; } @@ -1104,6 +1111,8 @@ client_update_attributes(Client *c) XChangeProperty(dpy, c->win, ATOM("_WMFS_ISFREE"), XA_CARDINAL, 32, PropModeReplace, (uchar*)&f, 1); + c->screen = screen_get_with_geo(c->geo.x, c->geo.y); + return; } From ce8238fb203629868df87c1f187116a52b85aca2 Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Wed, 18 Aug 2010 21:29:48 +0200 Subject: [PATCH 16/41] Client: Fix mistake in function name --- src/client.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/client.c b/src/client.c index c769cb1..d51b44a 100644 --- a/src/client.c +++ b/src/client.c @@ -749,9 +749,6 @@ client_manage(Window w, XWindowAttributes *wa, Bool ar) if(!conf.client.set_new_win_master) layout_set_client_master(c); - - cient_moveresize(c, c->geo, False); - return c; } From dce3b8eb3c31eb3af7ecef3a25297e33944af9b5 Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Wed, 18 Aug 2010 21:32:39 +0200 Subject: [PATCH 17/41] Client: Fix screen setting in client_set_attributes --- src/client.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/client.c b/src/client.c index d51b44a..904b008 100644 --- a/src/client.c +++ b/src/client.c @@ -1108,8 +1108,6 @@ client_update_attributes(Client *c) XChangeProperty(dpy, c->win, ATOM("_WMFS_ISFREE"), XA_CARDINAL, 32, PropModeReplace, (uchar*)&f, 1); - c->screen = screen_get_with_geo(c->geo.x, c->geo.y); - return; } From 4f42436098b6b356246df48c0aaa6dc7d67c5dde Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Wed, 18 Aug 2010 23:42:31 +0200 Subject: [PATCH 18/41] Config: Apply second patch of mseed/PeVe about conf split: Can comment @include line in conf. --- src/parse/parse.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/parse/parse.c b/src/parse/parse.c index 8abad3c..878226c 100644 --- a/src/parse/parse.c +++ b/src/parse/parse.c @@ -275,6 +275,8 @@ get_conf(const char *name) char *tmp_inc_list = NULL; char *incname = NULL; char *tmp_inc = NULL; + char *rem_inc_tmp = NULL; + Bool rem = False; if (!name) return (-1); @@ -296,6 +298,20 @@ get_conf(const char *name) while(pos && (strlen(buf) > 0)) { + rem_inc_tmp = pos; + rem = False; + while(buf > rem_inc_tmp) + { + if((rem_inc_tmp[0] == '\n') || (rem_inc_tmp[0] == '\r')) + break; + if(rem_inc_tmp[0] == '#') + { + rem = True; + break; + } + rem_inc_tmp = rem_inc_tmp - sizeof(char); + } + xpos = strstr(buf, inc); xpos = xpos + strlen(inc); xend = strstr(xpos, inc_end); @@ -313,7 +329,7 @@ get_conf(const char *name) strcat(tmp_inc, "]"); tmpbuf = NULL; - if(!strstr(inc_list, tmp_inc)) + if(!strstr(inc_list, tmp_inc) && !rem) { tmp_inc_list = (char *) malloc(sizeof(char) * (strlen(tmp_inc) + strlen(inc_list) + 5)); strcpy(tmp_inc_list, "\r\n"); @@ -334,6 +350,7 @@ get_conf(const char *name) buffer = (char *)malloc(sizeof(char) * (strlen(buf) + strlen(tmpbuf) + 1)); strncpy(buffer, buf, (pos - buf)); + memset(buffer + (pos - buf), 0, sizeof(char)); strcat(buffer, tmpbuf); strcat(buffer, pos_end); free(buf); From 578b62ec094561ac63edd30b71ff198d86cd3dc1 Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Wed, 18 Aug 2010 23:43:20 +0200 Subject: [PATCH 19/41] Update version --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index becc390..64df248 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,7 +52,7 @@ set(wmfs_src add_executable(wmfs ${wmfs_src}) # Set the version -set(VERSION "WMFS-201006") +set(VERSION "WMFS-201008") # FLAGS set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -ansi") From e9b409b564f27dc4a1e13f5b88ff44d230737ba0 Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Wed, 18 Aug 2010 23:45:12 +0200 Subject: [PATCH 20/41] Config: Put example in default conf --- wmfsrc.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wmfsrc.in b/wmfsrc.in index e83bbe7..a1170c3 100644 --- a/wmfsrc.in +++ b/wmfsrc.in @@ -3,6 +3,9 @@ # ~/.config/wmfs/wmfsrc and edit it. # +# Include file to split configuration +# @include "~/.config/wmfs/menu-wmfsrc" + [misc] font = "dejavu-10" raisefocus = false From ce4575ee048e3203ca3a742cf3b37d2a23e11484 Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Fri, 20 Aug 2010 06:19:19 +0200 Subject: [PATCH 21/41] Event: Focus client before click on titlebar buttons --- src/event.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/event.c b/src/event.c index 6429e96..d7da88e 100644 --- a/src/event.c +++ b/src/event.c @@ -65,7 +65,10 @@ buttonpress(XButtonEvent *ev) for(i = 0; i < conf.titlebar.button[n].nmouse; ++i) if(ev->button == conf.titlebar.button[n].mouse[i].button) if(conf.titlebar.button[n].mouse[i].func) + { + client_focus(c); conf.titlebar.button[n].mouse[i].func(conf.titlebar.button[n].mouse[i].cmd); + } /* Frame Resize Area */ if((c = client_gb_resize(ev->window))) From e6db51d8fd03adc66f9f5de3a1722fbf0cdfa698 Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Sat, 21 Aug 2010 13:38:25 +0200 Subject: [PATCH 22/41] CMake: Add scarabeus patch (rewrite of CMakeLists.h), fix warning --- CMakeLists.txt | 382 ++++++++++++++++++------------------------------ src/config.h.in | 17 +-- src/wmfs.h | 2 +- wmfs.doxygen.in | 2 +- wmfsrc.in | 3 +- 5 files changed, 149 insertions(+), 257 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 64df248..ad0532e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,273 +1,169 @@ # -*- mode: cmake -*- -#Cmakelists.txt -# Minimum version of CMake -cmake_minimum_required(VERSION 2.6) + +# Minimal version of CMake +cmake_minimum_required(VERSION 2.6.0) +cmake_minimum_required(VERSION 2.6.0 FATAL_ERROR) if(COMMAND cmake_policy) - cmake_policy(VERSION 2.6) -endif() + cmake_policy(SET CMP0003 NEW) +endif(COMMAND cmake_policy) -CONFIGURE_FILE( - "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" - IMMEDIATE @ONLY) +# set some default options +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH} ) +set(CMAKE_COLOR_MAKEFILE ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) +set(CMAKE_BUILD_TYPE_SHARED_LIBS ON) +set(CMAKE_C_FLAGS $ENV{CFLAGS}) +set(CMAKE_CXX_FLAGS $ENV{CXXFLAGS}) +set(CMAKE_LINK_FLAGS $ENV{LDFLAGS}) -ADD_CUSTOM_TARGET(uninstall - "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") +# include macros +include(MacroConfigureFile) -# Source and build dirs -set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) -set(BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}) +# uninstall +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY ) +add_custom_target( uninstall + "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" ) # Project name - wmfs set(PROJECT_NAME wmfs) +set(VERSION "WMFS-201008") project(${PROJECT_NAME} C) -# Definition of the wmfs source -set(wmfs_src - src/parse/parse.c - src/barwin.c - src/client.c - src/config.c - src/ - src/draw.c - src/event.c - src/ewmh.c - src/frame.c - src/getinfo.c - src/infobar.c - src/init.c - src/launcher.c - src/layout.c - src/menu.c - src/mouse.c - src/screen.c - src/status.c - src/systray.c - src/tag.c - src/util.c - src/viwmfs.c - src/wmfs.c) +find_package(PkgConfig REQUIRED) +# required packages +pkg_check_modules(FREETYPE REQUIRED freetype2) +pkg_check_modules(X11 REQUIRED x11) +pkg_check_modules(XFT REQUIRED xft) -# Set the executable from the wmfs_src -add_executable(wmfs ${wmfs_src}) - -# Set the version -set(VERSION "WMFS-201008") - -# FLAGS -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -ansi") - -# Linker FLAGS - -set(DEFAULT_LDFLAGS "-L /usr/local/lib -lpthread") - -if(CMAKE_SYSTEM_NAME MATCHES NetBSD) - message("-- NetBSD system found - Using /usr/pkg/lib for linker") - set(LDFLAGS "${DEFAULT_LDFLAGS} -L /usr/pkg/lib") -else(CMAKE_SYSTEM_NAME MATCHES NetBSD) - set(LDFLAGS ${DEFAULT_LDFLAGS}) -endif(CMAKE_SYSTEM_NAME MATCHES NetBSD) - -set_target_properties(wmfs PROPERTIES LINK_FLAGS ${LDFLAGS}) -# Includes dir for libs in build_dir include_directories( - ${BUILD_DIR}/src - ) + ${FREETYPE_INCLUDE_DIRS} + ${X11_INCLUDE_DIRS} + ${XFT_INCLUDE_DIRS} +) -# Package find -find_package(Freetype) -if(FREETYPE_FOUND) - include_directories(${FREETYPE_INCLUDE_DIRS}) -else (FREETYPE_FOUND) - message(FATAL_ERROR "Could not find Freetype") -endif (FREETYPE_FOUND) +set(CMAKE_LINK_LIBRARIES + ${FREETYPE_LIBRARIES} + ${X11_LIBRARIES} + ${XFT_LIBRARIES} + -lpthread +) -find_package(X11) -if(X11_FOUND) - include_directories(${X11_INCLUDE_DIR}) -else (X11_FOUND) - message(FATAL_ERROR "Could not find X11") -endif (X11_FOUND) +# options +option(BUILD_DOC "Generate documentation using doxygen" OFF) +option(WITH_XINERAMA "Build with Xinerama support" ON) +option(WITH_XRANDR "Build with Xrandr support" ON) +option(WITH_IMLIB2 "Build with Imlib2 support" ON) -# Link Libraries -set(LIBRARIES_TO_LINK - ${FREETYPE_LIBRARIES} - ${X11_LIBRARIES} - Xft) +# optional finders +if(WITH_XINERAMA) + add_definitions(-DHAVE_XINIERAMA) + pkg_check_modules(XINERAMA REQUIRED xinerama) + include_directories(${XINERAMA_INCLUDE_DIRS}) + set(CMAKE_LINK_LIBRARIES ${XINERAMA_LIBRARIES} ${CMAKE_LINK_LIBRARIES}) +else(WITH_XINERAMA) + message(STATUS "Not building with Xinerama support") +endif(WITH_XINERAMA) -# Includes -include(FindDoxygen) -include(FindPkgConfig) +if(WITH_XRANDR) + add_definitions(-DHAVE_XRANDR) + pkg_check_modules(XRANDR REQUIRED xrandr) + include_directories(${XRANDR_INCLUDE_DIRS}) + set(CMAKE_LINK_LIBRARIES ${XRANDR_LIBRARIES} ${CMAKE_LINK_LIBRARIES}) +else(WITH_XRANDR) + message(STATUS "Not building with Xrandr support") +endif(WITH_XRANDR) -# Use pkgconfig to get required libraries -pkg_check_modules(WMFS_REQUIRED REQUIRED - x11 - freetype2 - xft) +if(WITH_IMLIB2) + add_definitions(-DHAVE_IMLIB) + pkg_check_modules(IMLIB2 REQUIRED imlib2) + include_directories(${IMLIB2_INCLUDE_DIRS}) + set(CMAKE_LINK_LIBRARIES ${IMLIB2_LIBRARIES} ${CMAKE_LINK_LIBRARIES}) +else(WITH_IMLIB2) + message(STATUS "Not building with Imlib2 support") +endif(WITH_IMLIB2) -# Optional dependencies check +set(CMAKE_SYSCONFDIR ${CMAKE_INSTALL_PREFIX}/etc/ CACHE PATH "Config directory") +set(CMAKE_XDGCONFDIR ${CMAKE_SYSCONFDIR}/xdg/ CACHE PATH "XDG config directory") +set(CMAKE_DATADIR ${CMAKE_INSTALL_PREFIX}/share/ CACHE PATH "Data directory") +set(CMAKE_DOCDIR ${CMAKE_INSTALL_PREFIX}/share/doc/${PROJECT_NAME}-${VERSION} CACHE PATH "Data directory") -# Check for xinerama -pkg_check_modules(HAVE_XINERAMA xinerama) -if(HAVE_XINERAMA_FOUND) - set(WMFS_HAVE_XINERAMA "#define HAVE_XINERAMA") - set(LIBRARIES_TO_LINK ${LIBRARIES_TO_LINK} Xinerama) -else() - set(WMFS_HAVE_XINERAMA "") -endif() +# set default terminal for user +set(WMFS_TERM xterm) -# Check for xrandr -pkg_check_modules(HAVE_XRANDR xrandr) -if(HAVE_XRANDR_FOUND) - set(WMFS_HAVE_XRANDR "#define HAVE_XRANDR") - set(LIBRARIES_TO_LINK ${LIBRARIES_TO_LINK} Xrandr) -else() - set(WMFS_HAVE_XRANDR "") -endif() - -# Check for Imlib -pkg_check_modules(HAVE_IMLIB imlib2) -if(HAVE_IMLIB_FOUND) - set(WMFS_HAVE_IMLIB "#define HAVE_IMLIB") - set(LIBRARIES_TO_LINK ${LIBRARIES_TO_LINK} Imlib2) -else() - set(WMFS_HAVE_IMLIB "") -endif() - -target_link_libraries(wmfs ${LIBRARIES_TO_LINK}) - -# Messages -message("Project version: ${VERSION}") -message("Using these CFLAGS: ${CMAKE_C_FLAGS}") -message("Using these LDFLAGS: ${LDFLAGS}") -message("Linking with theses libraries : ${LIBRARIES_TO_LINK}") - -# Generating man page -find_program(GZIP_EXECUTABLE gzip) -if(NOT GZIP_EXECUTABLE) - message(STATUS "Looking for gzip -- not found") - message(STATUS "Could not generating man page") -else() - message(STATUS "Looking for gzip -- ${GZIP_EXECUTABLE}") - message(STATUS "Generating man page") - set(WMFS_MAN1_FILES ${BUILD_DIR}/wmfs.1.gz) - execute_process( - COMMAND ${GZIP_EXECUTABLE} -c wmfs.1 - WORKING_DIRECTORY ${SOURCE_DIR} - OUTPUT_FILE ${WMFS_MAN1_FILES}) -endif() - -# Generating CHANGELOG -find_program(GIT_EXECUTABLE git) -if(EXISTS ${SOURCE_DIR}/.git/HEAD AND GIT_EXECUTABLE) - message(STATUS "Looking for git -- ${GIT_EXECUTABLE}") - message(STATUS "Git dir -- Generating changelog...") - set(PROJECT_CHANGELOG ${SOURCE_DIR}/changelog) - execute_process( - COMMAND ${GIT_EXECUTABLE} log - WORKING_DIRECTORY ${SOURCE_DIR} - OUTPUT_FILE ${PROJECT_CHANGELOG}) -else() - message(STATUS "Looking for git -- not found") - message(STATUS "Could not generating changelog") -endif() - -# sets -# {{{ Install path and configuration variables -if(DEFINED PREFIX) - set(PREFIX ${PREFIX} CACHE PATH "install prefix") - set(CMAKE_INSTALL_PREFIX ${PREFIX}) -else() - set(PREFIX ${CMAKE_INSTALL_PREFIX} CACHE PATH "install prefix") -endif() - -#If a sysconfdir is specified, use it instead -#of the default configuration dir. -if(DEFINED SYSCONFDIR) - set(SYSCONFDIR ${SYSCONFDIR} CACHE PATH "config directory") -else() - set(SYSCONFDIR /etc CACHE PATH "config directory") -endif() - -#If an XDG Config Dir is specificed, use it instead -#of the default XDG configuration dir. -if(DEFINED XDG_CONFIG_DIR) - set(XDG_CONFIG_DIR ${XDG_CONFIG_SYS} CACHE PATH "xdg config directory") -else() - set(XDG_CONFIG_DIR ${SYSCONFDIR}/xdg CACHE PATH "xdg config directory") -endif() - -# setting WMFS_XSESSION_PATH -if(DEFINED WMFS_XSESSION_PATH) - set(WMFS_XSESSION_PATH ${WMFS_XSESSION_PATH} CACHE PATH "wmfs xsessions directory") -else() - set(WMFS_XSESSION_PATH ${PREFIX}/share/xsessions CACHE PATH "wmfs xsessions directory") -endif() - -if(DEFINED WMFS_MAN_PATH) - set(WMFS_MAN_PATH ${WMFS_MAN_PATH} CACHE PATH "wmfs manpage directory") -else() - set(WMFS_MAN_PATH ${PREFIX}/share/man CACHE PATH "wmfs manpage directory") -endif() - -if(DOXYGEN_EXECUTABLE) - add_custom_target(doc - COMMAND ${DOXYGEN_EXECUTABLE} ${SOURCE_DIR}/wmfs.doxygen - WORKING_DIRECTORY ${BUILD_DIR}) -endif() - -find_program(URXVT_EXECUTABLE urxvt) -if(URXVT_EXECUTABLE) - set(WMFS_TERM urxvt) -else() - set(WMFS_TERM xterm) -endif() - -# Remplace strings in configs -set(WMFS_VERSION ${VERSION}) -set(WMFS_COMPILE_MACHINE ${CMAKE_SYSTEM_PROCESSOR}) -set(WMFS_COMPILE_BY $ENV{USER}) -set(WMFS_COMPILE_FLAGS ${CMAKE_C_FLAGS}) -set(WMFS_LINKED_LIBS ${LIBRARIES_TO_LINK}) -set(WMFS_SYSCONFDIR ${XDG_CONFIG_DIR}/${PROJECT_NAME}) -set(WMFS_SOURCE_DIR ${SOURCE_DIR}) - -# Configure files -set(wmfs_configure_files +# configure files +set(CONFIGURE_FILES src/config.h.in wmfs.doxygen.in wmfsrc.in) +foreach(file ${CONFIGURE_FILES}) + ConfigureFile(${file}) +endforeach(file) -macro(a_configure_file file) - string(REGEX REPLACE ".in\$" "" outfile ${file}) - message(STATUS "Configuring ${outfile}") - configure_file(${SOURCE_DIR}/${file} - ${SOURCE_DIR}/${outfile} - ESCAPE_QUOTE - @ONLY) -endmacro() +# add the source directory +add_subdirectory(src) -foreach(file ${wmfs_configure_files}) - a_configure_file(${file}) -endforeach() +# documentation +if(BUILD_DOC) + find_package(Doxygen REQUIRED) + if(DOXYGEN_FOUND) + add_custom_target(doc + COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/wmfs.doxygen + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + else(DOXYGEN_FOUND) + MESSAGE(FATAL_ERROR "Doxygen executable not found") + endif(DOXYGEN_FOUND) +endif(BUILD_DOC) -set(PROJECT_DATA_PATH share/${PROJECT_NAME}) -set(PROJECT_TODO ${SOURCE_DIR}/TODO) -set(PROJECT_README ${SOURCE_DIR}/README) -set(PROJECT_DEFAULT_CONF ${SOURCE_DIR}/wmfsrc) +# Generating ChangeLog only for live version, for release we generate it to tarball +if(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/ChangeLog) + find_program(GIT_EXECUTABLE git) + if(EXISTS ${CMAKE_SOURCE_DIR}/.git/HEAD AND GIT_EXECUTABLE) + message(STATUS "<<< Generating ChangeLog... >>>") + execute_process( + COMMAND ${GIT_EXECUTABLE} log + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + OUTPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/ChangeLog) + else(EXISTS ${CMAKE_SOURCE_DIR}/.git/HEAD AND GIT_EXECUTABLE) + message(STATUS "No ChangeLog present and git not found") + message(STATUS "<<< Will not generate ChangeLog >>>") + endif(EXISTS ${CMAKE_SOURCE_DIR}/.git/HEAD AND GIT_EXECUTABLE) +endif(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/ChangeLog) -# installs -install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin) +# manpage (compression handled by system not by us) +install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/wmfs.1 DESTINATION ${CMAKE_DATADIR}/man/man1) -if(WMFS_MAN1_FILES) - install(FILES ${WMFS_MAN1_FILES} DESTINATION ${WMFS_MAN_PATH}/man1) -endif() +# install docs +# changelog || can have 2 locations based on whether we generate it or not +if(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/ChangeLog) + set(WMFS_DOCS ${CMAKE_CURRENT_BINARY_DIR}/ChangeLog ${WMFS_DOCS}) +endif(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/ChangeLog) +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/ChangeLog) + set(WMFS_DOCS ${CMAKE_CURRENT_SOURCE_DIR}/ChangeLog ${WMFS_DOCS}) +endif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/ChangeLog) +set(WMFS_DOCS + ${CMAKE_CURRENT_SOURCE_DIR}/TODO + ${CMAKE_CURRENT_SOURCE_DIR}/README + ${WMFS_DOCS} +) +install(FILES ${WMFS_DOCS} DESTINATION ${CMAKE_DOCDIR}) -if(PROJECT_CHANGELOG) - install(FILES ${PROJECT_CHANGELOG} DESTINATION ${PROJECT_DATA_PATH}) -endif() +# config file +install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/wmfsrc DESTINATION ${CMAKE_SYSCONFDIR}/${PROJECT_NAME}) -install(FILES ${PROJECT_TODO} ${PROJECT_README} - ${PROJECT_DEFAULT_CONF} DESTINATION ${PROJECT_DATA_PATH}) -install(FILES ${PROJECT_DEFAULT_CONF} DESTINATION ${WMFS_SYSCONFDIR}) -install(FILES "wmfs.desktop" DESTINATION ${WMFS_XSESSION_PATH}) +# xsession +install(FILES "wmfs.desktop" DESTINATION ${CMAKE_DATADIR}/xsessions) + +# Status messages +message(STATUS "<<< ${PROJECT_NAME} ${VERSION} configuration >>> + Build type ${CMAKE_BUILD_TYPE} + Install path ${CMAKE_INSTALL_PREFIX} + Compiler flags: + C ${CMAKE_C_FLAGS} + C++ ${CMAKE_CXX_FLAGS} + Linker flags: + Executable ${CMAKE_EXE_LINKER_FLAGS} + Module ${CMAKE_MODULE_LINKER_FLAGS} + Shared ${CMAKE_SHARED_LINKER_FLAGS}\n") diff --git a/src/config.h.in b/src/config.h.in index e409351..25a9a69 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -35,16 +35,11 @@ #include "wmfs.h" -#define WMFS_VERSION "@WMFS_VERSION@" -#define WMFS_COMPILE_MACHINE "@WMFS_COMPILE_MACHINE@" -#define WMFS_COMPILE_BY "@WMFS_COMPILE_BY@" -#define WMFS_COMPILE_FLAGS "@WMFS_COMPILE_FLAGS@" -#define WMFS_LINKED_LIBS "@WMFS_LINKED_LIBS@" -#define XDG_CONFIG_DIR "@XDG_CONFIG_DIR@" - -/* Optional dependencies */ -@WMFS_HAVE_XINERAMA@ -@WMFS_HAVE_XRANDR@ -@WMFS_HAVE_IMLIB@ +#define WMFS_VERSION "@VERSION@" +#define WMFS_COMPILE_MACHINE "@CMAKE_SYSTEM_PROCESSOR@" +#define WMFS_COMPILE_BY "@ENV{USER}@" +#define WMFS_COMPILE_FLAGS "@CMAKE_C_FLAGS@" +#define WMFS_LINKED_LIBS "@CMAKE_LINK_LIBRARIES@" +#define XDG_CONFIG_DIR "@CMAKE_XDGCONFDIR@" #endif /* CONFIG_H */ diff --git a/src/wmfs.h b/src/wmfs.h index f0a1a98..0054a3b 100644 --- a/src/wmfs.h +++ b/src/wmfs.h @@ -34,7 +34,7 @@ #define WMFS_H #define _BSD_SOURCE /* vsnprintf */ -#define _POSIX_SOURCE /* kill */ + /* Lib headers */ #include #include diff --git a/wmfs.doxygen.in b/wmfs.doxygen.in index 602c1fc..583a59b 100644 --- a/wmfs.doxygen.in +++ b/wmfs.doxygen.in @@ -73,7 +73,7 @@ WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- -INPUT = @SOURCE_DIR@/src +INPUT = @CMAKE_CURRENT_SOURCE_DIR@/src INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.c \ *.h \ diff --git a/wmfsrc.in b/wmfsrc.in index a1170c3..0511bb2 100644 --- a/wmfsrc.in +++ b/wmfsrc.in @@ -8,7 +8,8 @@ [misc] font = "dejavu-10" - raisefocus = false + raisefocus = true + focus_follow_mouse = true # focus_pointer_click: click on unfocused client area: # true -- default, set focus From e254f762111f262101e9b3931abb4b69a185b96b Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Sat, 21 Aug 2010 13:42:30 +0200 Subject: [PATCH 23/41] Revert "CMake: Add scarabeus patch (rewrite of CMakeLists.h), fix warning" This reverts commit e6db51d8fd03adc66f9f5de3a1722fbf0cdfa698. --- CMakeLists.txt | 382 ++++++++++++++++++++++++++++++------------------ src/config.h.in | 17 ++- src/wmfs.h | 2 +- wmfs.doxygen.in | 2 +- wmfsrc.in | 3 +- 5 files changed, 257 insertions(+), 149 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ad0532e..64df248 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,169 +1,273 @@ # -*- mode: cmake -*- - -# Minimal version of CMake -cmake_minimum_required(VERSION 2.6.0) -cmake_minimum_required(VERSION 2.6.0 FATAL_ERROR) +#Cmakelists.txt +# Minimum version of CMake +cmake_minimum_required(VERSION 2.6) if(COMMAND cmake_policy) - cmake_policy(SET CMP0003 NEW) -endif(COMMAND cmake_policy) + cmake_policy(VERSION 2.6) +endif() -# set some default options -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH} ) -set(CMAKE_COLOR_MAKEFILE ON) -set(CMAKE_INCLUDE_CURRENT_DIR ON) -set(CMAKE_BUILD_TYPE_SHARED_LIBS ON) -set(CMAKE_C_FLAGS $ENV{CFLAGS}) -set(CMAKE_CXX_FLAGS $ENV{CXXFLAGS}) -set(CMAKE_LINK_FLAGS $ENV{LDFLAGS}) +CONFIGURE_FILE( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) -# include macros -include(MacroConfigureFile) +ADD_CUSTOM_TARGET(uninstall + "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") -# uninstall -configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" - IMMEDIATE @ONLY ) -add_custom_target( uninstall - "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" ) +# Source and build dirs +set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}) # Project name - wmfs set(PROJECT_NAME wmfs) -set(VERSION "WMFS-201008") project(${PROJECT_NAME} C) -find_package(PkgConfig REQUIRED) -# required packages -pkg_check_modules(FREETYPE REQUIRED freetype2) -pkg_check_modules(X11 REQUIRED x11) -pkg_check_modules(XFT REQUIRED xft) +# Definition of the wmfs source +set(wmfs_src + src/parse/parse.c + src/barwin.c + src/client.c + src/config.c + src/ + src/draw.c + src/event.c + src/ewmh.c + src/frame.c + src/getinfo.c + src/infobar.c + src/init.c + src/launcher.c + src/layout.c + src/menu.c + src/mouse.c + src/screen.c + src/status.c + src/systray.c + src/tag.c + src/util.c + src/viwmfs.c + src/wmfs.c) +# Set the executable from the wmfs_src +add_executable(wmfs ${wmfs_src}) + +# Set the version +set(VERSION "WMFS-201008") + +# FLAGS +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -ansi") + +# Linker FLAGS + +set(DEFAULT_LDFLAGS "-L /usr/local/lib -lpthread") + +if(CMAKE_SYSTEM_NAME MATCHES NetBSD) + message("-- NetBSD system found - Using /usr/pkg/lib for linker") + set(LDFLAGS "${DEFAULT_LDFLAGS} -L /usr/pkg/lib") +else(CMAKE_SYSTEM_NAME MATCHES NetBSD) + set(LDFLAGS ${DEFAULT_LDFLAGS}) +endif(CMAKE_SYSTEM_NAME MATCHES NetBSD) + +set_target_properties(wmfs PROPERTIES LINK_FLAGS ${LDFLAGS}) +# Includes dir for libs in build_dir include_directories( - ${FREETYPE_INCLUDE_DIRS} - ${X11_INCLUDE_DIRS} - ${XFT_INCLUDE_DIRS} -) + ${BUILD_DIR}/src + ) -set(CMAKE_LINK_LIBRARIES - ${FREETYPE_LIBRARIES} - ${X11_LIBRARIES} - ${XFT_LIBRARIES} - -lpthread -) +# Package find +find_package(Freetype) +if(FREETYPE_FOUND) + include_directories(${FREETYPE_INCLUDE_DIRS}) +else (FREETYPE_FOUND) + message(FATAL_ERROR "Could not find Freetype") +endif (FREETYPE_FOUND) -# options -option(BUILD_DOC "Generate documentation using doxygen" OFF) -option(WITH_XINERAMA "Build with Xinerama support" ON) -option(WITH_XRANDR "Build with Xrandr support" ON) -option(WITH_IMLIB2 "Build with Imlib2 support" ON) +find_package(X11) +if(X11_FOUND) + include_directories(${X11_INCLUDE_DIR}) +else (X11_FOUND) + message(FATAL_ERROR "Could not find X11") +endif (X11_FOUND) -# optional finders -if(WITH_XINERAMA) - add_definitions(-DHAVE_XINIERAMA) - pkg_check_modules(XINERAMA REQUIRED xinerama) - include_directories(${XINERAMA_INCLUDE_DIRS}) - set(CMAKE_LINK_LIBRARIES ${XINERAMA_LIBRARIES} ${CMAKE_LINK_LIBRARIES}) -else(WITH_XINERAMA) - message(STATUS "Not building with Xinerama support") -endif(WITH_XINERAMA) +# Link Libraries +set(LIBRARIES_TO_LINK + ${FREETYPE_LIBRARIES} + ${X11_LIBRARIES} + Xft) -if(WITH_XRANDR) - add_definitions(-DHAVE_XRANDR) - pkg_check_modules(XRANDR REQUIRED xrandr) - include_directories(${XRANDR_INCLUDE_DIRS}) - set(CMAKE_LINK_LIBRARIES ${XRANDR_LIBRARIES} ${CMAKE_LINK_LIBRARIES}) -else(WITH_XRANDR) - message(STATUS "Not building with Xrandr support") -endif(WITH_XRANDR) +# Includes +include(FindDoxygen) +include(FindPkgConfig) -if(WITH_IMLIB2) - add_definitions(-DHAVE_IMLIB) - pkg_check_modules(IMLIB2 REQUIRED imlib2) - include_directories(${IMLIB2_INCLUDE_DIRS}) - set(CMAKE_LINK_LIBRARIES ${IMLIB2_LIBRARIES} ${CMAKE_LINK_LIBRARIES}) -else(WITH_IMLIB2) - message(STATUS "Not building with Imlib2 support") -endif(WITH_IMLIB2) +# Use pkgconfig to get required libraries +pkg_check_modules(WMFS_REQUIRED REQUIRED + x11 + freetype2 + xft) -set(CMAKE_SYSCONFDIR ${CMAKE_INSTALL_PREFIX}/etc/ CACHE PATH "Config directory") -set(CMAKE_XDGCONFDIR ${CMAKE_SYSCONFDIR}/xdg/ CACHE PATH "XDG config directory") -set(CMAKE_DATADIR ${CMAKE_INSTALL_PREFIX}/share/ CACHE PATH "Data directory") -set(CMAKE_DOCDIR ${CMAKE_INSTALL_PREFIX}/share/doc/${PROJECT_NAME}-${VERSION} CACHE PATH "Data directory") +# Optional dependencies check -# set default terminal for user -set(WMFS_TERM xterm) +# Check for xinerama +pkg_check_modules(HAVE_XINERAMA xinerama) +if(HAVE_XINERAMA_FOUND) + set(WMFS_HAVE_XINERAMA "#define HAVE_XINERAMA") + set(LIBRARIES_TO_LINK ${LIBRARIES_TO_LINK} Xinerama) +else() + set(WMFS_HAVE_XINERAMA "") +endif() -# configure files -set(CONFIGURE_FILES +# Check for xrandr +pkg_check_modules(HAVE_XRANDR xrandr) +if(HAVE_XRANDR_FOUND) + set(WMFS_HAVE_XRANDR "#define HAVE_XRANDR") + set(LIBRARIES_TO_LINK ${LIBRARIES_TO_LINK} Xrandr) +else() + set(WMFS_HAVE_XRANDR "") +endif() + +# Check for Imlib +pkg_check_modules(HAVE_IMLIB imlib2) +if(HAVE_IMLIB_FOUND) + set(WMFS_HAVE_IMLIB "#define HAVE_IMLIB") + set(LIBRARIES_TO_LINK ${LIBRARIES_TO_LINK} Imlib2) +else() + set(WMFS_HAVE_IMLIB "") +endif() + +target_link_libraries(wmfs ${LIBRARIES_TO_LINK}) + +# Messages +message("Project version: ${VERSION}") +message("Using these CFLAGS: ${CMAKE_C_FLAGS}") +message("Using these LDFLAGS: ${LDFLAGS}") +message("Linking with theses libraries : ${LIBRARIES_TO_LINK}") + +# Generating man page +find_program(GZIP_EXECUTABLE gzip) +if(NOT GZIP_EXECUTABLE) + message(STATUS "Looking for gzip -- not found") + message(STATUS "Could not generating man page") +else() + message(STATUS "Looking for gzip -- ${GZIP_EXECUTABLE}") + message(STATUS "Generating man page") + set(WMFS_MAN1_FILES ${BUILD_DIR}/wmfs.1.gz) + execute_process( + COMMAND ${GZIP_EXECUTABLE} -c wmfs.1 + WORKING_DIRECTORY ${SOURCE_DIR} + OUTPUT_FILE ${WMFS_MAN1_FILES}) +endif() + +# Generating CHANGELOG +find_program(GIT_EXECUTABLE git) +if(EXISTS ${SOURCE_DIR}/.git/HEAD AND GIT_EXECUTABLE) + message(STATUS "Looking for git -- ${GIT_EXECUTABLE}") + message(STATUS "Git dir -- Generating changelog...") + set(PROJECT_CHANGELOG ${SOURCE_DIR}/changelog) + execute_process( + COMMAND ${GIT_EXECUTABLE} log + WORKING_DIRECTORY ${SOURCE_DIR} + OUTPUT_FILE ${PROJECT_CHANGELOG}) +else() + message(STATUS "Looking for git -- not found") + message(STATUS "Could not generating changelog") +endif() + +# sets +# {{{ Install path and configuration variables +if(DEFINED PREFIX) + set(PREFIX ${PREFIX} CACHE PATH "install prefix") + set(CMAKE_INSTALL_PREFIX ${PREFIX}) +else() + set(PREFIX ${CMAKE_INSTALL_PREFIX} CACHE PATH "install prefix") +endif() + +#If a sysconfdir is specified, use it instead +#of the default configuration dir. +if(DEFINED SYSCONFDIR) + set(SYSCONFDIR ${SYSCONFDIR} CACHE PATH "config directory") +else() + set(SYSCONFDIR /etc CACHE PATH "config directory") +endif() + +#If an XDG Config Dir is specificed, use it instead +#of the default XDG configuration dir. +if(DEFINED XDG_CONFIG_DIR) + set(XDG_CONFIG_DIR ${XDG_CONFIG_SYS} CACHE PATH "xdg config directory") +else() + set(XDG_CONFIG_DIR ${SYSCONFDIR}/xdg CACHE PATH "xdg config directory") +endif() + +# setting WMFS_XSESSION_PATH +if(DEFINED WMFS_XSESSION_PATH) + set(WMFS_XSESSION_PATH ${WMFS_XSESSION_PATH} CACHE PATH "wmfs xsessions directory") +else() + set(WMFS_XSESSION_PATH ${PREFIX}/share/xsessions CACHE PATH "wmfs xsessions directory") +endif() + +if(DEFINED WMFS_MAN_PATH) + set(WMFS_MAN_PATH ${WMFS_MAN_PATH} CACHE PATH "wmfs manpage directory") +else() + set(WMFS_MAN_PATH ${PREFIX}/share/man CACHE PATH "wmfs manpage directory") +endif() + +if(DOXYGEN_EXECUTABLE) + add_custom_target(doc + COMMAND ${DOXYGEN_EXECUTABLE} ${SOURCE_DIR}/wmfs.doxygen + WORKING_DIRECTORY ${BUILD_DIR}) +endif() + +find_program(URXVT_EXECUTABLE urxvt) +if(URXVT_EXECUTABLE) + set(WMFS_TERM urxvt) +else() + set(WMFS_TERM xterm) +endif() + +# Remplace strings in configs +set(WMFS_VERSION ${VERSION}) +set(WMFS_COMPILE_MACHINE ${CMAKE_SYSTEM_PROCESSOR}) +set(WMFS_COMPILE_BY $ENV{USER}) +set(WMFS_COMPILE_FLAGS ${CMAKE_C_FLAGS}) +set(WMFS_LINKED_LIBS ${LIBRARIES_TO_LINK}) +set(WMFS_SYSCONFDIR ${XDG_CONFIG_DIR}/${PROJECT_NAME}) +set(WMFS_SOURCE_DIR ${SOURCE_DIR}) + +# Configure files +set(wmfs_configure_files src/config.h.in wmfs.doxygen.in wmfsrc.in) -foreach(file ${CONFIGURE_FILES}) - ConfigureFile(${file}) -endforeach(file) -# add the source directory -add_subdirectory(src) +macro(a_configure_file file) + string(REGEX REPLACE ".in\$" "" outfile ${file}) + message(STATUS "Configuring ${outfile}") + configure_file(${SOURCE_DIR}/${file} + ${SOURCE_DIR}/${outfile} + ESCAPE_QUOTE + @ONLY) +endmacro() -# documentation -if(BUILD_DOC) - find_package(Doxygen REQUIRED) - if(DOXYGEN_FOUND) - add_custom_target(doc - COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/wmfs.doxygen - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - else(DOXYGEN_FOUND) - MESSAGE(FATAL_ERROR "Doxygen executable not found") - endif(DOXYGEN_FOUND) -endif(BUILD_DOC) +foreach(file ${wmfs_configure_files}) + a_configure_file(${file}) +endforeach() -# Generating ChangeLog only for live version, for release we generate it to tarball -if(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/ChangeLog) - find_program(GIT_EXECUTABLE git) - if(EXISTS ${CMAKE_SOURCE_DIR}/.git/HEAD AND GIT_EXECUTABLE) - message(STATUS "<<< Generating ChangeLog... >>>") - execute_process( - COMMAND ${GIT_EXECUTABLE} log - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - OUTPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/ChangeLog) - else(EXISTS ${CMAKE_SOURCE_DIR}/.git/HEAD AND GIT_EXECUTABLE) - message(STATUS "No ChangeLog present and git not found") - message(STATUS "<<< Will not generate ChangeLog >>>") - endif(EXISTS ${CMAKE_SOURCE_DIR}/.git/HEAD AND GIT_EXECUTABLE) -endif(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/ChangeLog) +set(PROJECT_DATA_PATH share/${PROJECT_NAME}) +set(PROJECT_TODO ${SOURCE_DIR}/TODO) +set(PROJECT_README ${SOURCE_DIR}/README) +set(PROJECT_DEFAULT_CONF ${SOURCE_DIR}/wmfsrc) -# manpage (compression handled by system not by us) -install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/wmfs.1 DESTINATION ${CMAKE_DATADIR}/man/man1) +# installs +install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin) -# install docs -# changelog || can have 2 locations based on whether we generate it or not -if(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/ChangeLog) - set(WMFS_DOCS ${CMAKE_CURRENT_BINARY_DIR}/ChangeLog ${WMFS_DOCS}) -endif(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/ChangeLog) -if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/ChangeLog) - set(WMFS_DOCS ${CMAKE_CURRENT_SOURCE_DIR}/ChangeLog ${WMFS_DOCS}) -endif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/ChangeLog) -set(WMFS_DOCS - ${CMAKE_CURRENT_SOURCE_DIR}/TODO - ${CMAKE_CURRENT_SOURCE_DIR}/README - ${WMFS_DOCS} -) -install(FILES ${WMFS_DOCS} DESTINATION ${CMAKE_DOCDIR}) +if(WMFS_MAN1_FILES) + install(FILES ${WMFS_MAN1_FILES} DESTINATION ${WMFS_MAN_PATH}/man1) +endif() -# config file -install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/wmfsrc DESTINATION ${CMAKE_SYSCONFDIR}/${PROJECT_NAME}) +if(PROJECT_CHANGELOG) + install(FILES ${PROJECT_CHANGELOG} DESTINATION ${PROJECT_DATA_PATH}) +endif() -# xsession -install(FILES "wmfs.desktop" DESTINATION ${CMAKE_DATADIR}/xsessions) - -# Status messages -message(STATUS "<<< ${PROJECT_NAME} ${VERSION} configuration >>> - Build type ${CMAKE_BUILD_TYPE} - Install path ${CMAKE_INSTALL_PREFIX} - Compiler flags: - C ${CMAKE_C_FLAGS} - C++ ${CMAKE_CXX_FLAGS} - Linker flags: - Executable ${CMAKE_EXE_LINKER_FLAGS} - Module ${CMAKE_MODULE_LINKER_FLAGS} - Shared ${CMAKE_SHARED_LINKER_FLAGS}\n") +install(FILES ${PROJECT_TODO} ${PROJECT_README} + ${PROJECT_DEFAULT_CONF} DESTINATION ${PROJECT_DATA_PATH}) +install(FILES ${PROJECT_DEFAULT_CONF} DESTINATION ${WMFS_SYSCONFDIR}) +install(FILES "wmfs.desktop" DESTINATION ${WMFS_XSESSION_PATH}) diff --git a/src/config.h.in b/src/config.h.in index 25a9a69..e409351 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -35,11 +35,16 @@ #include "wmfs.h" -#define WMFS_VERSION "@VERSION@" -#define WMFS_COMPILE_MACHINE "@CMAKE_SYSTEM_PROCESSOR@" -#define WMFS_COMPILE_BY "@ENV{USER}@" -#define WMFS_COMPILE_FLAGS "@CMAKE_C_FLAGS@" -#define WMFS_LINKED_LIBS "@CMAKE_LINK_LIBRARIES@" -#define XDG_CONFIG_DIR "@CMAKE_XDGCONFDIR@" +#define WMFS_VERSION "@WMFS_VERSION@" +#define WMFS_COMPILE_MACHINE "@WMFS_COMPILE_MACHINE@" +#define WMFS_COMPILE_BY "@WMFS_COMPILE_BY@" +#define WMFS_COMPILE_FLAGS "@WMFS_COMPILE_FLAGS@" +#define WMFS_LINKED_LIBS "@WMFS_LINKED_LIBS@" +#define XDG_CONFIG_DIR "@XDG_CONFIG_DIR@" + +/* Optional dependencies */ +@WMFS_HAVE_XINERAMA@ +@WMFS_HAVE_XRANDR@ +@WMFS_HAVE_IMLIB@ #endif /* CONFIG_H */ diff --git a/src/wmfs.h b/src/wmfs.h index 0054a3b..f0a1a98 100644 --- a/src/wmfs.h +++ b/src/wmfs.h @@ -34,7 +34,7 @@ #define WMFS_H #define _BSD_SOURCE /* vsnprintf */ - +#define _POSIX_SOURCE /* kill */ /* Lib headers */ #include #include diff --git a/wmfs.doxygen.in b/wmfs.doxygen.in index 583a59b..602c1fc 100644 --- a/wmfs.doxygen.in +++ b/wmfs.doxygen.in @@ -73,7 +73,7 @@ WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- -INPUT = @CMAKE_CURRENT_SOURCE_DIR@/src +INPUT = @SOURCE_DIR@/src INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.c \ *.h \ diff --git a/wmfsrc.in b/wmfsrc.in index 0511bb2..a1170c3 100644 --- a/wmfsrc.in +++ b/wmfsrc.in @@ -8,8 +8,7 @@ [misc] font = "dejavu-10" - raisefocus = true - + raisefocus = false focus_follow_mouse = true # focus_pointer_click: click on unfocused client area: # true -- default, set focus From 9055a55d582b22f2659489aadd3bb77e2e073e91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Chv=C3=A1tal?= Date: Sat, 21 Aug 2010 13:28:15 +0200 Subject: [PATCH 24/41] Use cmake properly, basically complete cmake build system rewrite. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomáš Chvátal --- CMakeLists.txt | 382 +++++++++---------------- cmake/cmake_uninstall.cmake.in | 21 ++ cmake/modules/MacroConfigureFile.cmake | 8 + src/CMakeLists.txt | 34 +++ src/config.h.in | 17 +- wmfs.doxygen.in | 2 +- 6 files changed, 209 insertions(+), 255 deletions(-) create mode 100755 cmake/cmake_uninstall.cmake.in create mode 100644 cmake/modules/MacroConfigureFile.cmake create mode 100644 src/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 64df248..ad0532e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,273 +1,169 @@ # -*- mode: cmake -*- -#Cmakelists.txt -# Minimum version of CMake -cmake_minimum_required(VERSION 2.6) + +# Minimal version of CMake +cmake_minimum_required(VERSION 2.6.0) +cmake_minimum_required(VERSION 2.6.0 FATAL_ERROR) if(COMMAND cmake_policy) - cmake_policy(VERSION 2.6) -endif() + cmake_policy(SET CMP0003 NEW) +endif(COMMAND cmake_policy) -CONFIGURE_FILE( - "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" - IMMEDIATE @ONLY) +# set some default options +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH} ) +set(CMAKE_COLOR_MAKEFILE ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) +set(CMAKE_BUILD_TYPE_SHARED_LIBS ON) +set(CMAKE_C_FLAGS $ENV{CFLAGS}) +set(CMAKE_CXX_FLAGS $ENV{CXXFLAGS}) +set(CMAKE_LINK_FLAGS $ENV{LDFLAGS}) -ADD_CUSTOM_TARGET(uninstall - "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") +# include macros +include(MacroConfigureFile) -# Source and build dirs -set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) -set(BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}) +# uninstall +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY ) +add_custom_target( uninstall + "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" ) # Project name - wmfs set(PROJECT_NAME wmfs) +set(VERSION "WMFS-201008") project(${PROJECT_NAME} C) -# Definition of the wmfs source -set(wmfs_src - src/parse/parse.c - src/barwin.c - src/client.c - src/config.c - src/ - src/draw.c - src/event.c - src/ewmh.c - src/frame.c - src/getinfo.c - src/infobar.c - src/init.c - src/launcher.c - src/layout.c - src/menu.c - src/mouse.c - src/screen.c - src/status.c - src/systray.c - src/tag.c - src/util.c - src/viwmfs.c - src/wmfs.c) +find_package(PkgConfig REQUIRED) +# required packages +pkg_check_modules(FREETYPE REQUIRED freetype2) +pkg_check_modules(X11 REQUIRED x11) +pkg_check_modules(XFT REQUIRED xft) -# Set the executable from the wmfs_src -add_executable(wmfs ${wmfs_src}) - -# Set the version -set(VERSION "WMFS-201008") - -# FLAGS -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -ansi") - -# Linker FLAGS - -set(DEFAULT_LDFLAGS "-L /usr/local/lib -lpthread") - -if(CMAKE_SYSTEM_NAME MATCHES NetBSD) - message("-- NetBSD system found - Using /usr/pkg/lib for linker") - set(LDFLAGS "${DEFAULT_LDFLAGS} -L /usr/pkg/lib") -else(CMAKE_SYSTEM_NAME MATCHES NetBSD) - set(LDFLAGS ${DEFAULT_LDFLAGS}) -endif(CMAKE_SYSTEM_NAME MATCHES NetBSD) - -set_target_properties(wmfs PROPERTIES LINK_FLAGS ${LDFLAGS}) -# Includes dir for libs in build_dir include_directories( - ${BUILD_DIR}/src - ) + ${FREETYPE_INCLUDE_DIRS} + ${X11_INCLUDE_DIRS} + ${XFT_INCLUDE_DIRS} +) -# Package find -find_package(Freetype) -if(FREETYPE_FOUND) - include_directories(${FREETYPE_INCLUDE_DIRS}) -else (FREETYPE_FOUND) - message(FATAL_ERROR "Could not find Freetype") -endif (FREETYPE_FOUND) +set(CMAKE_LINK_LIBRARIES + ${FREETYPE_LIBRARIES} + ${X11_LIBRARIES} + ${XFT_LIBRARIES} + -lpthread +) -find_package(X11) -if(X11_FOUND) - include_directories(${X11_INCLUDE_DIR}) -else (X11_FOUND) - message(FATAL_ERROR "Could not find X11") -endif (X11_FOUND) +# options +option(BUILD_DOC "Generate documentation using doxygen" OFF) +option(WITH_XINERAMA "Build with Xinerama support" ON) +option(WITH_XRANDR "Build with Xrandr support" ON) +option(WITH_IMLIB2 "Build with Imlib2 support" ON) -# Link Libraries -set(LIBRARIES_TO_LINK - ${FREETYPE_LIBRARIES} - ${X11_LIBRARIES} - Xft) +# optional finders +if(WITH_XINERAMA) + add_definitions(-DHAVE_XINIERAMA) + pkg_check_modules(XINERAMA REQUIRED xinerama) + include_directories(${XINERAMA_INCLUDE_DIRS}) + set(CMAKE_LINK_LIBRARIES ${XINERAMA_LIBRARIES} ${CMAKE_LINK_LIBRARIES}) +else(WITH_XINERAMA) + message(STATUS "Not building with Xinerama support") +endif(WITH_XINERAMA) -# Includes -include(FindDoxygen) -include(FindPkgConfig) +if(WITH_XRANDR) + add_definitions(-DHAVE_XRANDR) + pkg_check_modules(XRANDR REQUIRED xrandr) + include_directories(${XRANDR_INCLUDE_DIRS}) + set(CMAKE_LINK_LIBRARIES ${XRANDR_LIBRARIES} ${CMAKE_LINK_LIBRARIES}) +else(WITH_XRANDR) + message(STATUS "Not building with Xrandr support") +endif(WITH_XRANDR) -# Use pkgconfig to get required libraries -pkg_check_modules(WMFS_REQUIRED REQUIRED - x11 - freetype2 - xft) +if(WITH_IMLIB2) + add_definitions(-DHAVE_IMLIB) + pkg_check_modules(IMLIB2 REQUIRED imlib2) + include_directories(${IMLIB2_INCLUDE_DIRS}) + set(CMAKE_LINK_LIBRARIES ${IMLIB2_LIBRARIES} ${CMAKE_LINK_LIBRARIES}) +else(WITH_IMLIB2) + message(STATUS "Not building with Imlib2 support") +endif(WITH_IMLIB2) -# Optional dependencies check +set(CMAKE_SYSCONFDIR ${CMAKE_INSTALL_PREFIX}/etc/ CACHE PATH "Config directory") +set(CMAKE_XDGCONFDIR ${CMAKE_SYSCONFDIR}/xdg/ CACHE PATH "XDG config directory") +set(CMAKE_DATADIR ${CMAKE_INSTALL_PREFIX}/share/ CACHE PATH "Data directory") +set(CMAKE_DOCDIR ${CMAKE_INSTALL_PREFIX}/share/doc/${PROJECT_NAME}-${VERSION} CACHE PATH "Data directory") -# Check for xinerama -pkg_check_modules(HAVE_XINERAMA xinerama) -if(HAVE_XINERAMA_FOUND) - set(WMFS_HAVE_XINERAMA "#define HAVE_XINERAMA") - set(LIBRARIES_TO_LINK ${LIBRARIES_TO_LINK} Xinerama) -else() - set(WMFS_HAVE_XINERAMA "") -endif() +# set default terminal for user +set(WMFS_TERM xterm) -# Check for xrandr -pkg_check_modules(HAVE_XRANDR xrandr) -if(HAVE_XRANDR_FOUND) - set(WMFS_HAVE_XRANDR "#define HAVE_XRANDR") - set(LIBRARIES_TO_LINK ${LIBRARIES_TO_LINK} Xrandr) -else() - set(WMFS_HAVE_XRANDR "") -endif() - -# Check for Imlib -pkg_check_modules(HAVE_IMLIB imlib2) -if(HAVE_IMLIB_FOUND) - set(WMFS_HAVE_IMLIB "#define HAVE_IMLIB") - set(LIBRARIES_TO_LINK ${LIBRARIES_TO_LINK} Imlib2) -else() - set(WMFS_HAVE_IMLIB "") -endif() - -target_link_libraries(wmfs ${LIBRARIES_TO_LINK}) - -# Messages -message("Project version: ${VERSION}") -message("Using these CFLAGS: ${CMAKE_C_FLAGS}") -message("Using these LDFLAGS: ${LDFLAGS}") -message("Linking with theses libraries : ${LIBRARIES_TO_LINK}") - -# Generating man page -find_program(GZIP_EXECUTABLE gzip) -if(NOT GZIP_EXECUTABLE) - message(STATUS "Looking for gzip -- not found") - message(STATUS "Could not generating man page") -else() - message(STATUS "Looking for gzip -- ${GZIP_EXECUTABLE}") - message(STATUS "Generating man page") - set(WMFS_MAN1_FILES ${BUILD_DIR}/wmfs.1.gz) - execute_process( - COMMAND ${GZIP_EXECUTABLE} -c wmfs.1 - WORKING_DIRECTORY ${SOURCE_DIR} - OUTPUT_FILE ${WMFS_MAN1_FILES}) -endif() - -# Generating CHANGELOG -find_program(GIT_EXECUTABLE git) -if(EXISTS ${SOURCE_DIR}/.git/HEAD AND GIT_EXECUTABLE) - message(STATUS "Looking for git -- ${GIT_EXECUTABLE}") - message(STATUS "Git dir -- Generating changelog...") - set(PROJECT_CHANGELOG ${SOURCE_DIR}/changelog) - execute_process( - COMMAND ${GIT_EXECUTABLE} log - WORKING_DIRECTORY ${SOURCE_DIR} - OUTPUT_FILE ${PROJECT_CHANGELOG}) -else() - message(STATUS "Looking for git -- not found") - message(STATUS "Could not generating changelog") -endif() - -# sets -# {{{ Install path and configuration variables -if(DEFINED PREFIX) - set(PREFIX ${PREFIX} CACHE PATH "install prefix") - set(CMAKE_INSTALL_PREFIX ${PREFIX}) -else() - set(PREFIX ${CMAKE_INSTALL_PREFIX} CACHE PATH "install prefix") -endif() - -#If a sysconfdir is specified, use it instead -#of the default configuration dir. -if(DEFINED SYSCONFDIR) - set(SYSCONFDIR ${SYSCONFDIR} CACHE PATH "config directory") -else() - set(SYSCONFDIR /etc CACHE PATH "config directory") -endif() - -#If an XDG Config Dir is specificed, use it instead -#of the default XDG configuration dir. -if(DEFINED XDG_CONFIG_DIR) - set(XDG_CONFIG_DIR ${XDG_CONFIG_SYS} CACHE PATH "xdg config directory") -else() - set(XDG_CONFIG_DIR ${SYSCONFDIR}/xdg CACHE PATH "xdg config directory") -endif() - -# setting WMFS_XSESSION_PATH -if(DEFINED WMFS_XSESSION_PATH) - set(WMFS_XSESSION_PATH ${WMFS_XSESSION_PATH} CACHE PATH "wmfs xsessions directory") -else() - set(WMFS_XSESSION_PATH ${PREFIX}/share/xsessions CACHE PATH "wmfs xsessions directory") -endif() - -if(DEFINED WMFS_MAN_PATH) - set(WMFS_MAN_PATH ${WMFS_MAN_PATH} CACHE PATH "wmfs manpage directory") -else() - set(WMFS_MAN_PATH ${PREFIX}/share/man CACHE PATH "wmfs manpage directory") -endif() - -if(DOXYGEN_EXECUTABLE) - add_custom_target(doc - COMMAND ${DOXYGEN_EXECUTABLE} ${SOURCE_DIR}/wmfs.doxygen - WORKING_DIRECTORY ${BUILD_DIR}) -endif() - -find_program(URXVT_EXECUTABLE urxvt) -if(URXVT_EXECUTABLE) - set(WMFS_TERM urxvt) -else() - set(WMFS_TERM xterm) -endif() - -# Remplace strings in configs -set(WMFS_VERSION ${VERSION}) -set(WMFS_COMPILE_MACHINE ${CMAKE_SYSTEM_PROCESSOR}) -set(WMFS_COMPILE_BY $ENV{USER}) -set(WMFS_COMPILE_FLAGS ${CMAKE_C_FLAGS}) -set(WMFS_LINKED_LIBS ${LIBRARIES_TO_LINK}) -set(WMFS_SYSCONFDIR ${XDG_CONFIG_DIR}/${PROJECT_NAME}) -set(WMFS_SOURCE_DIR ${SOURCE_DIR}) - -# Configure files -set(wmfs_configure_files +# configure files +set(CONFIGURE_FILES src/config.h.in wmfs.doxygen.in wmfsrc.in) +foreach(file ${CONFIGURE_FILES}) + ConfigureFile(${file}) +endforeach(file) -macro(a_configure_file file) - string(REGEX REPLACE ".in\$" "" outfile ${file}) - message(STATUS "Configuring ${outfile}") - configure_file(${SOURCE_DIR}/${file} - ${SOURCE_DIR}/${outfile} - ESCAPE_QUOTE - @ONLY) -endmacro() +# add the source directory +add_subdirectory(src) -foreach(file ${wmfs_configure_files}) - a_configure_file(${file}) -endforeach() +# documentation +if(BUILD_DOC) + find_package(Doxygen REQUIRED) + if(DOXYGEN_FOUND) + add_custom_target(doc + COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/wmfs.doxygen + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + else(DOXYGEN_FOUND) + MESSAGE(FATAL_ERROR "Doxygen executable not found") + endif(DOXYGEN_FOUND) +endif(BUILD_DOC) -set(PROJECT_DATA_PATH share/${PROJECT_NAME}) -set(PROJECT_TODO ${SOURCE_DIR}/TODO) -set(PROJECT_README ${SOURCE_DIR}/README) -set(PROJECT_DEFAULT_CONF ${SOURCE_DIR}/wmfsrc) +# Generating ChangeLog only for live version, for release we generate it to tarball +if(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/ChangeLog) + find_program(GIT_EXECUTABLE git) + if(EXISTS ${CMAKE_SOURCE_DIR}/.git/HEAD AND GIT_EXECUTABLE) + message(STATUS "<<< Generating ChangeLog... >>>") + execute_process( + COMMAND ${GIT_EXECUTABLE} log + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + OUTPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/ChangeLog) + else(EXISTS ${CMAKE_SOURCE_DIR}/.git/HEAD AND GIT_EXECUTABLE) + message(STATUS "No ChangeLog present and git not found") + message(STATUS "<<< Will not generate ChangeLog >>>") + endif(EXISTS ${CMAKE_SOURCE_DIR}/.git/HEAD AND GIT_EXECUTABLE) +endif(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/ChangeLog) -# installs -install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin) +# manpage (compression handled by system not by us) +install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/wmfs.1 DESTINATION ${CMAKE_DATADIR}/man/man1) -if(WMFS_MAN1_FILES) - install(FILES ${WMFS_MAN1_FILES} DESTINATION ${WMFS_MAN_PATH}/man1) -endif() +# install docs +# changelog || can have 2 locations based on whether we generate it or not +if(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/ChangeLog) + set(WMFS_DOCS ${CMAKE_CURRENT_BINARY_DIR}/ChangeLog ${WMFS_DOCS}) +endif(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/ChangeLog) +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/ChangeLog) + set(WMFS_DOCS ${CMAKE_CURRENT_SOURCE_DIR}/ChangeLog ${WMFS_DOCS}) +endif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/ChangeLog) +set(WMFS_DOCS + ${CMAKE_CURRENT_SOURCE_DIR}/TODO + ${CMAKE_CURRENT_SOURCE_DIR}/README + ${WMFS_DOCS} +) +install(FILES ${WMFS_DOCS} DESTINATION ${CMAKE_DOCDIR}) -if(PROJECT_CHANGELOG) - install(FILES ${PROJECT_CHANGELOG} DESTINATION ${PROJECT_DATA_PATH}) -endif() +# config file +install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/wmfsrc DESTINATION ${CMAKE_SYSCONFDIR}/${PROJECT_NAME}) -install(FILES ${PROJECT_TODO} ${PROJECT_README} - ${PROJECT_DEFAULT_CONF} DESTINATION ${PROJECT_DATA_PATH}) -install(FILES ${PROJECT_DEFAULT_CONF} DESTINATION ${WMFS_SYSCONFDIR}) -install(FILES "wmfs.desktop" DESTINATION ${WMFS_XSESSION_PATH}) +# xsession +install(FILES "wmfs.desktop" DESTINATION ${CMAKE_DATADIR}/xsessions) + +# Status messages +message(STATUS "<<< ${PROJECT_NAME} ${VERSION} configuration >>> + Build type ${CMAKE_BUILD_TYPE} + Install path ${CMAKE_INSTALL_PREFIX} + Compiler flags: + C ${CMAKE_C_FLAGS} + C++ ${CMAKE_CXX_FLAGS} + Linker flags: + Executable ${CMAKE_EXE_LINKER_FLAGS} + Module ${CMAKE_MODULE_LINKER_FLAGS} + Shared ${CMAKE_SHARED_LINKER_FLAGS}\n") diff --git a/cmake/cmake_uninstall.cmake.in b/cmake/cmake_uninstall.cmake.in new file mode 100755 index 0000000..cd4c9d8 --- /dev/null +++ b/cmake/cmake_uninstall.cmake.in @@ -0,0 +1,21 @@ +IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") +ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + +FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) +STRING(REGEX REPLACE "\n" ";" files "${files}") +FOREACH(file ${files}) + MESSAGE(STATUS "Uninstalling: \"$ENV{DESTDIR}${file}\"") + IF(EXISTS "$ENV{DESTDIR}${file}") + EXEC_PROGRAM( + "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval + ) + IF(NOT "${rm_retval}" STREQUAL 0) + MESSAGE(FATAL_ERROR "Problem when removing: \"$ENV{DESTDIR}${file}\"") + ENDIF(NOT "${rm_retval}" STREQUAL 0) + ELSE(EXISTS "$ENV{DESTDIR}${file}") + MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") + ENDIF(EXISTS "$ENV{DESTDIR}${file}") +ENDFOREACH(file) diff --git a/cmake/modules/MacroConfigureFile.cmake b/cmake/modules/MacroConfigureFile.cmake new file mode 100644 index 0000000..b2ae132 --- /dev/null +++ b/cmake/modules/MacroConfigureFile.cmake @@ -0,0 +1,8 @@ +macro(ConfigureFile file) + string(REGEX REPLACE ".in\$" "" outfile ${file}) + message(STATUS "<<< Configuring ${outfile} >>>") + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${file} + ${CMAKE_CURRENT_BINARY_DIR}/${outfile} + ESCAPE_QUOTE + @ONLY) +endmacro(ConfigureFile) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..7af0c54 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,34 @@ +# -*- mode: cmake -*- + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/parse) + +SET(WMFS_SOURCES + parse/parse.c + barwin.c + client.c + config.c + draw.c + event.c + ewmh.c + frame.c + getinfo.c + infobar.c + init.c + launcher.c + layout.c + menu.c + mouse.c + screen.c + status.c + systray.c + tag.c + util.c + viwmfs.c + wmfs.c +) + +add_executable(${PROJECT_NAME} ${WMFS_SOURCES}) +target_link_libraries(${PROJECT_NAME} ${CMAKE_LINK_LIBRARIES}) +INSTALL ( TARGETS ${PROJECT_NAME} + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib${LIB_SUFFIX} ) \ No newline at end of file diff --git a/src/config.h.in b/src/config.h.in index e409351..25a9a69 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -35,16 +35,11 @@ #include "wmfs.h" -#define WMFS_VERSION "@WMFS_VERSION@" -#define WMFS_COMPILE_MACHINE "@WMFS_COMPILE_MACHINE@" -#define WMFS_COMPILE_BY "@WMFS_COMPILE_BY@" -#define WMFS_COMPILE_FLAGS "@WMFS_COMPILE_FLAGS@" -#define WMFS_LINKED_LIBS "@WMFS_LINKED_LIBS@" -#define XDG_CONFIG_DIR "@XDG_CONFIG_DIR@" - -/* Optional dependencies */ -@WMFS_HAVE_XINERAMA@ -@WMFS_HAVE_XRANDR@ -@WMFS_HAVE_IMLIB@ +#define WMFS_VERSION "@VERSION@" +#define WMFS_COMPILE_MACHINE "@CMAKE_SYSTEM_PROCESSOR@" +#define WMFS_COMPILE_BY "@ENV{USER}@" +#define WMFS_COMPILE_FLAGS "@CMAKE_C_FLAGS@" +#define WMFS_LINKED_LIBS "@CMAKE_LINK_LIBRARIES@" +#define XDG_CONFIG_DIR "@CMAKE_XDGCONFDIR@" #endif /* CONFIG_H */ diff --git a/wmfs.doxygen.in b/wmfs.doxygen.in index 602c1fc..583a59b 100644 --- a/wmfs.doxygen.in +++ b/wmfs.doxygen.in @@ -73,7 +73,7 @@ WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- -INPUT = @SOURCE_DIR@/src +INPUT = @CMAKE_CURRENT_SOURCE_DIR@/src INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.c \ *.h \ From 59d9dcdc9397c10fe53f5f1bd467d236954392b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Chv=C3=A1tal?= Date: Sat, 21 Aug 2010 20:07:55 +0200 Subject: [PATCH 25/41] Fixup xinerama define. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ad0532e..fb4745c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,7 +59,7 @@ option(WITH_IMLIB2 "Build with Imlib2 support" ON) # optional finders if(WITH_XINERAMA) - add_definitions(-DHAVE_XINIERAMA) + add_definitions(-DHAVE_XINERAMA) pkg_check_modules(XINERAMA REQUIRED xinerama) include_directories(${XINERAMA_INCLUDE_DIRS}) set(CMAKE_LINK_LIBRARIES ${XINERAMA_LIBRARIES} ${CMAKE_LINK_LIBRARIES}) From 3b60e23f9f3971dfcd7291ba9d9726e2724a7bcb Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Sat, 21 Aug 2010 20:30:03 +0200 Subject: [PATCH 26/41] Remove warning --- src/wmfs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wmfs.h b/src/wmfs.h index f0a1a98..0054a3b 100644 --- a/src/wmfs.h +++ b/src/wmfs.h @@ -34,7 +34,7 @@ #define WMFS_H #define _BSD_SOURCE /* vsnprintf */ -#define _POSIX_SOURCE /* kill */ + /* Lib headers */ #include #include From 52bfa713dfd69a1c1b5819ac7ee485eda17520ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Chv=C3=A1tal?= Date: Sat, 21 Aug 2010 20:00:19 +0200 Subject: [PATCH 27/41] Fix username settings in conf.h --- CMakeLists.txt | 3 +++ src/config.h.in | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fb4745c..0f0118e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,6 +92,9 @@ set(CMAKE_DOCDIR ${CMAKE_INSTALL_PREFIX}/share/doc/${PROJECT_NAME}-${VERSION} CA # set default terminal for user set(WMFS_TERM xterm) +# get the user compiling this thing +SET(USERNAME $ENV{USER}) + # configure files set(CONFIGURE_FILES diff --git a/src/config.h.in b/src/config.h.in index 25a9a69..77d88bd 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -37,7 +37,7 @@ #define WMFS_VERSION "@VERSION@" #define WMFS_COMPILE_MACHINE "@CMAKE_SYSTEM_PROCESSOR@" -#define WMFS_COMPILE_BY "@ENV{USER}@" +#define WMFS_COMPILE_BY "@USERNAME@" #define WMFS_COMPILE_FLAGS "@CMAKE_C_FLAGS@" #define WMFS_LINKED_LIBS "@CMAKE_LINK_LIBRARIES@" #define XDG_CONFIG_DIR "@CMAKE_XDGCONFDIR@" From a1d134a1b704a766ba6d7b188f805140392c1c30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Chv=C3=A1tal?= Date: Sat, 21 Aug 2010 19:52:53 +0200 Subject: [PATCH 28/41] Drop duped file. --- cmake_uninstall.cmake.in | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 cmake_uninstall.cmake.in diff --git a/cmake_uninstall.cmake.in b/cmake_uninstall.cmake.in deleted file mode 100644 index df95fb9..0000000 --- a/cmake_uninstall.cmake.in +++ /dev/null @@ -1,21 +0,0 @@ -IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") - MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") -ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") - -FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) -STRING(REGEX REPLACE "\n" ";" files "${files}") -FOREACH(file ${files}) - MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") - IF(EXISTS "$ENV{DESTDIR}${file}") - EXEC_PROGRAM( - "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" - OUTPUT_VARIABLE rm_out - RETURN_VALUE rm_retval - ) - IF(NOT "${rm_retval}" STREQUAL 0) - MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") - ENDIF(NOT "${rm_retval}" STREQUAL 0) - ELSE(EXISTS "$ENV{DESTDIR}${file}") - MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") - ENDIF(EXISTS "$ENV{DESTDIR}${file}") -ENDFOREACH(file) From 1eeb5e167ecbd32608aeefd35619b790b191577b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Chv=C3=A1tal?= Date: Sat, 21 Aug 2010 21:00:46 +0200 Subject: [PATCH 29/41] Fixup one more source/binary dir missmatch --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f0118e..4ed1164 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,8 +113,8 @@ if(BUILD_DOC) find_package(Doxygen REQUIRED) if(DOXYGEN_FOUND) add_custom_target(doc - COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/wmfs.doxygen - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/wmfs.doxygen + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) else(DOXYGEN_FOUND) MESSAGE(FATAL_ERROR "Doxygen executable not found") endif(DOXYGEN_FOUND) From 3644bc736ba9de024054ef63ed3d521608249367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Chv=C3=A1tal?= Date: Sat, 21 Aug 2010 20:53:22 +0200 Subject: [PATCH 30/41] Fix typo in wmfsrc pathspec. --- CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ed1164..90791b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,7 +95,6 @@ set(WMFS_TERM xterm) # get the user compiling this thing SET(USERNAME $ENV{USER}) - # configure files set(CONFIGURE_FILES src/config.h.in @@ -154,7 +153,7 @@ set(WMFS_DOCS install(FILES ${WMFS_DOCS} DESTINATION ${CMAKE_DOCDIR}) # config file -install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/wmfsrc DESTINATION ${CMAKE_SYSCONFDIR}/${PROJECT_NAME}) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/wmfsrc DESTINATION ${CMAKE_SYSCONFDIR}/${PROJECT_NAME}) # xsession install(FILES "wmfs.desktop" DESTINATION ${CMAKE_DATADIR}/xsessions) From fd9cedd695196073b81ce487c6a848934f34f2b2 Mon Sep 17 00:00:00 2001 From: Philippe Pepiot Date: Fri, 27 Aug 2010 03:06:30 +0200 Subject: [PATCH 31/41] Parser: simplification, don't abuse of macros (work in progress) --- src/parse/parse.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/parse/parse.c b/src/parse/parse.c index 878226c..3e263c9 100644 --- a/src/parse/parse.c +++ b/src/parse/parse.c @@ -28,13 +28,6 @@ extern char *__progname; -#define TOKEN(t) \ - do { \ - kw->type = (t); \ - TAILQ_INSERT_TAIL(&keywords, kw, entry); \ - kw = malloc(sizeof(*kw)); \ - } while (0) - #define NEW_WORD() \ do { \ if (j > 0) { \ @@ -43,7 +36,7 @@ extern char *__progname; TAILQ_INSERT_TAIL(&stack, e, entry); \ e = malloc(sizeof(*e)); \ j = 0; \ - TOKEN(WORD); \ + push_keyword(WORD); \ } \ } while (0) @@ -67,6 +60,7 @@ struct conf_state { }; static void get_keyword(const char *buf, size_t n); +static void push_keyword(enum conf_type); static void pop_keyword(void); static void pop_stack(void); static void syntax(const char *, ...); @@ -135,7 +129,7 @@ get_keyword(const char *buf, size_t n) if (buf[i] == '[' && s.quote == False) { NEW_WORD(); - TOKEN((buf[i+1] == '/') ? SEC_END : SEC_START); + push_keyword((buf[i+1] == '/') ? SEC_END : SEC_START); if (buf[i+1] == '/') i++; continue; @@ -148,13 +142,13 @@ get_keyword(const char *buf, size_t n) if (buf[i] == '{' && s.quote == False) { NEW_WORD(); - TOKEN(LIST_START); + push_keyword(LIST_START); continue; } if (buf[i] == '}' && s.quote == False) { NEW_WORD(); - TOKEN(LIST_END); + push_keyword(LIST_END); continue; } @@ -165,7 +159,7 @@ get_keyword(const char *buf, size_t n) if (buf[i] == '=' && s.quote == False) { NEW_WORD(); - TOKEN(EQUAL); + push_keyword(EQUAL); continue; } @@ -180,6 +174,15 @@ get_keyword(const char *buf, size_t n) } } +static void +push_keyword(enum conf_type type) +{ + struct conf_keyword *kw; + kw = emalloc(1, sizeof(*kw)); + kw->type = type; + TAILQ_INSERT_TAIL(&keywords, kw, entry); +} + #ifdef DEBUG static void print_kw_tree(void) From 4f1742eef9eb84dd953223cf9b84f50dac0dabd9 Mon Sep 17 00:00:00 2001 From: Philippe Pepiot Date: Sat, 28 Aug 2010 20:40:54 +0200 Subject: [PATCH 32/41] Parser: recode / independant from wmfs code / @include works, closes #21 --- src/CMakeLists.txt | 3 +- src/parse/api.c | 234 ++++++++++++ src/parse/parse.c | 895 ++++++++++++++++----------------------------- src/parse/parse.h | 23 +- 4 files changed, 556 insertions(+), 599 deletions(-) create mode 100644 src/parse/api.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7af0c54..24a540e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,6 +4,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/parse) SET(WMFS_SOURCES parse/parse.c + parse/api.c barwin.c client.c config.c @@ -31,4 +32,4 @@ add_executable(${PROJECT_NAME} ${WMFS_SOURCES}) target_link_libraries(${PROJECT_NAME} ${CMAKE_LINK_LIBRARIES}) INSTALL ( TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin - LIBRARY DESTINATION lib${LIB_SUFFIX} ) \ No newline at end of file + LIBRARY DESTINATION lib${LIB_SUFFIX} ) diff --git a/src/parse/api.c b/src/parse/api.c new file mode 100644 index 0000000..0284dcd --- /dev/null +++ b/src/parse/api.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2010 Philippe Pepiot + * + * 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. + */ + +#define _BSD_SOURCE +#include +#include +#include + +#include "parse.h" + +extern TAILQ_HEAD(, conf_sec) config; + +static const struct opt_type opt_type_null = { 0, 0, False, NULL }; + +static struct opt_type +string_to_opt(char *s) +{ + struct opt_type ret = opt_type_null; + + if (!s || !strlen(s)) + return ret; + + ret.num = strtol(s, (char**)NULL, 10); + ret.fnum = strtod(s, NULL); + + if (!strcmp(s, "true") || !strcmp(s, "True") || + !strcmp(s, "TRUE") || !strcmp(s, "1")) + ret.bool = True; + else + ret.bool = False; + + ret.str = s; + + return ret; +} + + +void +print_unused(struct conf_sec *sec) +{ + struct conf_sec *s; + struct conf_opt *o; + + if (!sec) + { + TAILQ_FOREACH(s, &config, entry) + print_unused(s); + return; + } + + SLIST_FOREACH(o, &sec->optlist, entry) + if (o->used == False) + warnx("%s:%d, unused param %s", + o->filename, o->line, o->name); + + TAILQ_FOREACH(s, &sec->sub, entry) + if (!TAILQ_EMPTY(&s->sub)) + print_unused(s); +} + +void +free_conf(struct conf_sec *sec) +{ + struct conf_sec *s; + struct conf_opt *o; + size_t n; + + if (!sec) + { + TAILQ_FOREACH(s, &config, entry) + { + free(s->name); + free_conf(s); + free(s); + } + return; + } + + while (!SLIST_EMPTY(&sec->optlist)) + { + o = SLIST_FIRST(&sec->optlist); + SLIST_REMOVE_HEAD(&sec->optlist, entry); + free(o->name); + + for (n = 0; o->val[n]; n++) + free(o->val[n]); + + free(o); + } + + while (!TAILQ_EMPTY(&sec->sub)) + { + s = TAILQ_FIRST(&sec->sub); + TAILQ_REMOVE(&sec->sub, s, entry); + free_conf(s); + } + +} + +struct conf_sec ** +fetch_section(struct conf_sec *s, char *name) +{ + struct conf_sec **ret; + struct conf_sec *sec; + size_t i = 0; + + if (!name) + return NULL; + + if (!s) { + ret = xcalloc(2, sizeof(struct conf_sec *)); + TAILQ_FOREACH(sec, &config, entry) + if (!strcmp(sec->name, name)) { + ret[0] = sec; + ret[1] = NULL; + break; + } + } + else { + ret = xcalloc(s->nsub+1, sizeof(struct conf_sec *)); + TAILQ_FOREACH(sec, &s->sub, entry) { + if (!strcmp(sec->name, name) && i < s->nsub) + ret[i++] = sec; + } + ret[i] = NULL; + } + return ret; +} + +struct conf_sec * +fetch_section_first(struct conf_sec *s, char *name) +{ + struct conf_sec *sec, *ret = NULL; + + if (!name) + return NULL; + + if (!s) + { + TAILQ_FOREACH(sec, &config, entry) + if(sec->name && !strcmp(sec->name, name)) { + ret = sec; + break; + } + } + else + { + TAILQ_FOREACH(sec, &s->sub, entry) + if (sec->name && !strcmp(sec->name, name)) { + ret = sec; + break; + } + } + + return ret; +} + +size_t +fetch_section_count(struct conf_sec **s) +{ + size_t ret; + for (ret = 0; s[ret]; ret++); + return ret; +} + +struct opt_type * +fetch_opt(struct conf_sec *s, char *dfl, char *name) +{ + struct conf_opt *o; + struct opt_type *ret; + size_t i = 0; + + if (!name) + return NULL; + + ret = xcalloc(10, sizeof(struct opt_type)); + + if (s) { + SLIST_FOREACH(o, &s->optlist, entry) + if (!strcmp(o->name, name)) { + while (o->val[i]) { + o->used = True; + ret[i] = string_to_opt(o->val[i]); + i++; + } + ret[i] = opt_type_null; + return ret; + } + } + + ret[0] = string_to_opt(dfl); + ret[1] = opt_type_null; + + return ret; +} + +struct opt_type +fetch_opt_first(struct conf_sec *s, char *dfl, char *name) +{ + struct conf_opt *o; + + if (!name) + return opt_type_null; + else if (s) + SLIST_FOREACH(o, &s->optlist, entry) + if (!strcmp(o->name, name)) { + o->used = True; + return string_to_opt(o->val[0]); + } + return string_to_opt(dfl); +} + +size_t +fetch_opt_count(struct opt_type *o) +{ + size_t ret; + for(ret = 0; o[ret].str; ret++); + return ret; +} + + diff --git a/src/parse/parse.c b/src/parse/parse.c index 3e263c9..d2f97df 100644 --- a/src/parse/parse.c +++ b/src/parse/parse.c @@ -18,89 +18,150 @@ #include #include #include +#include +#include #include #include #include #include +#include #include -#include "../wmfs.h" +#include "parse.h" extern char *__progname; -#define NEW_WORD() \ - do { \ - if (j > 0) { \ - e->name[j] = '\0'; \ - e->line = file.line; \ - TAILQ_INSERT_TAIL(&stack, e, entry); \ - e = malloc(sizeof(*e)); \ - j = 0; \ - push_keyword(WORD); \ - } \ - } while (0) - -enum conf_type { SEC_START, SEC_END, WORD, EQUAL, LIST_START, LIST_END, NONE }; - -struct conf_keyword { - enum conf_type type; - TAILQ_ENTRY(conf_keyword) entry; -}; - -struct conf_stack { - char name[BUFSIZ]; - int line; - TAILQ_ENTRY(conf_stack) entry; -}; - -struct conf_state { - Bool quote; - Bool comment; - char quote_char; -}; - -static void get_keyword(const char *buf, size_t n); -static void push_keyword(enum conf_type); -static void pop_keyword(void); -static void pop_stack(void); -static void syntax(const char *, ...); -static struct conf_sec *get_section(void); -static struct conf_opt *get_option(void); -static struct opt_type string_to_opt(char *); -#ifdef DEBUG -static void print_kw_tree(void); -static char * get_kw_name(enum conf_type); -#endif - -static TAILQ_HEAD(, conf_keyword) keywords; -static TAILQ_HEAD(, conf_stack) stack; -static TAILQ_HEAD(, conf_sec) config; -static struct conf_keyword *curk; /* current keyword */ -static struct conf_stack *curw; /* current word */ -static const struct opt_type opt_type_null = { 0, 0, False, NULL }; +enum keyword_t { SEC_START, SEC_END, INCLUDE, WORD, EQUAL, LIST_START, LIST_END, NONE }; static struct { const char *name; + enum keyword_t type; +} kw_t_name[] = { + {"SEC_START", SEC_START}, + {"SEC_END", SEC_END}, + {"INCLUDE", INCLUDE}, + {"WORD", WORD}, + {"EQUAL", EQUAL}, + {"LIST_START", LIST_START}, + {"LIST_END", LIST_END}, + {"NONE", NONE}, +}; + +struct files { + char *name; + struct files *parent; +}; + +struct keyword { + enum keyword_t type; + /* if WORD */ int line; -} file = { NULL, 1 }; + struct files *file; + char *name; + struct keyword *next; +}; -static void -get_keyword(const char *buf, size_t n) +struct state { + bool_t quote; + bool_t comment; + char quote_char; +}; + +/* TO REMOVE (use a identifier for config and fallback XDG in api functions) */ +TAILQ_HEAD(, conf_sec) config; + +static struct keyword * +push_keyword(struct keyword *tail, enum keyword_t type, char *buf, size_t *offset, struct files *file, int line) { - struct conf_keyword *kw; - size_t j, i; - struct conf_state s = { False, False, '\0' }; - struct conf_stack *e; + struct keyword *kw; + int i = 0; - TAILQ_INIT(&stack); - TAILQ_INIT(&keywords); - kw = emalloc(1, sizeof(*kw)); - e = emalloc(1, sizeof(*e)); + if (type == WORD && *offset == 0) + return tail; + + kw = xcalloc(1, sizeof(*kw)); + kw->type = type; + kw->line = line; + kw->file = file; + kw->next = NULL; + + if (*offset != 0) { + buf[*offset] = '\0'; + if (!strcmp(buf, INCLUDE_CMD)) + type = kw->type = INCLUDE; + else + kw->name = strdup(buf); + *offset = 0; + } + else + kw->name = NULL; + + if (tail) + tail->next = kw; + +#ifdef DEBUG + for (i = 0; kw_t_name[i].type != NONE; i++) { + if (kw_t_name[i].type == kw->type) { + warnx("%s %s %s:%d\n", kw_t_name[i].name, + (kw->name) ? kw->name : "", + kw->file->name, kw->line); + } + } +#endif + + return kw; +} + +#define PUSH_KEYWORD(type) tail = push_keyword(tail, type, bufname, &j, file, line) +static struct keyword * +parse_keywords(const char *filename) +{ + int fd; + struct stat st; + char *buf; + + struct keyword *head = NULL; + struct keyword *tail = NULL; + struct files *file; + enum keyword_t type; /* keyword type to push */ + struct state s = { False, False, '\0'}; + char *bufname; + char path[PATH_MAX]; + size_t i, j; + int line; + + + if ((fd = open(filename, O_RDONLY)) == -1 || stat(filename, &st) == -1) { + warn("%s", filename); + return NULL; + } + + buf = (char *)mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, SEEK_SET); + + if (buf == (char*)MAP_FAILED) { + warn("%s", filename); + return NULL; + } + + if (!realpath(filename, path)) { + warn("%s", filename); + return NULL; + } + + file = xcalloc(1, sizeof(*file)); + file->name = strdup(path); + file->parent = NULL; + + bufname = xcalloc(1, sizeof(*bufname) * BUFSIZ); + + + for(i = 0, j = 0, line = 1; i < (size_t)st.st_size; i++) { + + if (tail && !head) + head = tail; - for(i = 0, j = 0; i < n; i++) - { if (buf[i] == '\n' && s.comment == True) { - file.line++; + line++; s.comment = False; continue; } @@ -114,7 +175,8 @@ get_keyword(const char *buf, size_t n) continue; if (buf[i] == s.quote_char && s.quote == True) { - NEW_WORD(); + /* end of quotted string */ + PUSH_KEYWORD(WORD); s.quote = False; continue; } @@ -122,621 +184,276 @@ get_keyword(const char *buf, size_t n) if ((buf[i] == '"' || buf[i] == '\'') && s.quote == False) { + PUSH_KEYWORD(WORD); + /* begin quotted string */ s.quote_char = buf[i]; s.quote = True; continue; } if (buf[i] == '[' && s.quote == False) { - NEW_WORD(); - push_keyword((buf[i+1] == '/') ? SEC_END : SEC_START); - if (buf[i+1] == '/') + PUSH_KEYWORD(WORD); + if (buf[i+1] == '/') { + i +=2; + type = SEC_END; + } + else { i++; - continue; - } + type = SEC_START; + } - if (buf[i] == ']' && s.quote == False) { - NEW_WORD(); + while (buf[i] != ']') { + if (i >= (size_t)st.st_size) + { + /* TODO ERREUR */ + } + bufname[j++] = buf[i++]; + } + PUSH_KEYWORD(type); continue; } if (buf[i] == '{' && s.quote == False) { - NEW_WORD(); - push_keyword(LIST_START); + PUSH_KEYWORD(WORD); + PUSH_KEYWORD(LIST_START); continue; } if (buf[i] == '}' && s.quote == False) { - NEW_WORD(); - push_keyword(LIST_END); + PUSH_KEYWORD(WORD); + PUSH_KEYWORD(LIST_END); continue; } if (buf[i] == ',' && s.quote == False) { - NEW_WORD(); + PUSH_KEYWORD(WORD); continue; } if (buf[i] == '=' && s.quote == False) { - NEW_WORD(); - push_keyword(EQUAL); + PUSH_KEYWORD(WORD); + PUSH_KEYWORD(EQUAL); continue; } if (strchr("\t\n ", buf[i]) && s.quote == False) { - NEW_WORD(); + PUSH_KEYWORD(WORD); + if (buf[i] == '\n') - file.line++; + line++; + continue; } - e->name[j++] = buf[i]; + bufname[j++] = buf[i]; } + munmap(buf, st.st_size); + warnx("%s read", file->name); + return head; } static void -push_keyword(enum conf_type type) +syntax(struct keyword *kw, const char *fmt, ...) { - struct conf_keyword *kw; - kw = emalloc(1, sizeof(*kw)); - kw->type = type; - TAILQ_INSERT_TAIL(&keywords, kw, entry); + va_list args; + + fprintf(stderr, "%s: %s:%d", __progname, kw->file->name, kw->line); + if (kw->name) + fprintf(stderr, ", near '%s'", kw->name); + fprintf(stderr, ": "); + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + + fprintf(stderr, "\n"); + + exit(EXIT_FAILURE); } -#ifdef DEBUG -static void -print_kw_tree(void) +static struct keyword * +include(struct keyword *head) { - struct conf_keyword *k; - struct conf_stack *s; + struct keyword *kw; + struct keyword *tail; + struct files *file; - s = TAILQ_FIRST(&stack); + head = head->next; - TAILQ_FOREACH(k, &keywords, entry) - printf("%s ", get_kw_name(k->type)); - printf("\n"); + if (!head || head->type != WORD) + syntax(head, "missing filename to include"); + + if (!(kw = parse_keywords(head->name))) { + warnx("no config fond in include file %s", head->name); + return head->next; + } + + kw->file->parent = head->file; + head = head->next; + + /* detect circular include */ + for (file = kw->file->parent; file != NULL; file = file->parent) + { + if (!strcmp(file->name, kw->file->name)) + syntax(kw, "circular include of %s", kw->file->name); + } + + if (kw) { + for (tail = kw; tail->next; tail = tail->next); + tail->next = head; + } + + return kw; } -static char * -get_kw_name(enum conf_type type) +static struct conf_opt * +get_option(struct keyword **head) { - switch (type) { - case SEC_START: - return ("SEC_START"); - break; - case SEC_END: - return ("SEC_END"); + struct conf_opt *o; + size_t j = 0; + struct keyword *kw = *head; + + o = xcalloc(1, sizeof(*o)); + o->name = kw->name; + o->used = False; + o->line = kw->line; + o->filename = kw->file->name; + + kw = kw->next; + + if (kw->type != EQUAL) + syntax(kw, "missing '=' here"); + + kw = kw->next; + + if (!kw) + syntax(kw, "missing value"); + + + switch (kw->type) { + case INCLUDE: + kw = include(kw); break; case WORD: - return ("WORD"); + o->val[0] = kw->name; + o->val[1] = NULL; + kw = kw->next; break; case LIST_START: - return ("LIST_START "); - break; - case LIST_END: - return ("LIST_END "); - break; - case EQUAL: - return ("EQUAL "); + kw = kw->next; + while (kw && kw->type != LIST_END) { + switch (kw->type) { + case WORD: + if (j > 9) + syntax(kw, "too much values in list"); + o->val[j++] = kw->name; + kw = kw->next; + break; + case INCLUDE: + kw = include(kw); + break; + default: + syntax(kw, "declaration into a list"); + break; + } + } + + if (!kw) + syntax(kw, "list unclosed"); + + kw = kw->next; break; default: - return ("NONE "); + syntax(kw, "missing value"); break; } -} -#endif -char * -load_file(const char *name) -{ - int fd; - struct stat st; - char *buf; - char *buffer; - - if (!name) - return NULL; - - if ((fd = open(name, O_RDONLY)) == -1 || stat(name, &st) == -1) - { - warn("%s not read", name); - return NULL; - } - - buf = (char*)mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, SEEK_SET); - - if (buf == (char*) MAP_FAILED) - return NULL; - - buffer = strdup(buf); - - munmap(buf, st.st_size); - close(fd); - warnx("%s read", name); - - return buffer; -} - -int -get_conf(const char *name) -{ - char *buf; - struct conf_sec *s; - char inc[] = "@include \""; - char inc_end[] = "\""; - char *pos = NULL; - char *pos_end = NULL; - char *tmpname = NULL; - char *tmpbuf = NULL; - char *buffer = NULL; - - char *xpos = NULL; - char *xend = NULL; - int xl; - - char *inc_list = NULL; - char *tmp_inc_list = NULL; - char *incname = NULL; - char *tmp_inc = NULL; - char *rem_inc_tmp = NULL; - Bool rem = False; - - if (!name) - return (-1); - - /* remember name for duplicity include */ - tmp_inc = strdup(name); - incname = patht(tmp_inc); - free(tmp_inc); - inc_list = (char *) malloc(sizeof(char) * (strlen(incname) + 3)); - strcpy(inc_list, "["); - strcat(inc_list, incname); - strcat(inc_list, "]"); - buf = load_file(incname); - - if(!buf) - return (-1); - - pos = strstr(buf, inc); - - while(pos && (strlen(buf) > 0)) - { - rem_inc_tmp = pos; - rem = False; - while(buf > rem_inc_tmp) - { - if((rem_inc_tmp[0] == '\n') || (rem_inc_tmp[0] == '\r')) - break; - if(rem_inc_tmp[0] == '#') - { - rem = True; - break; - } - rem_inc_tmp = rem_inc_tmp - sizeof(char); - } - - xpos = strstr(buf, inc); - xpos = xpos + strlen(inc); - xend = strstr(xpos, inc_end); - xl = xend - xpos; - tmpname = (char *)malloc(sizeof(char) * (xl + 1)); - strncpy(tmpname, xpos, xl); - memset(tmpname + xl, 0, sizeof(char)); - pos_end = xend + strlen(inc_end); - - /* test and remember tmpname for duplicity include */ - incname = patht(tmpname); - tmp_inc = (char *) malloc(sizeof(char) * (strlen(incname) + 3)); - strcpy(tmp_inc, "["); - strcat(tmp_inc, incname); - strcat(tmp_inc, "]"); - tmpbuf = NULL; - - if(!strstr(inc_list, tmp_inc) && !rem) - { - tmp_inc_list = (char *) malloc(sizeof(char) * (strlen(tmp_inc) + strlen(inc_list) + 5)); - strcpy(tmp_inc_list, "\r\n"); - strcat(tmp_inc_list, inc_list); - strcat(tmp_inc_list, tmp_inc); - strcat(tmp_inc_list, "\r\n"); - free(inc_list); - - inc_list = tmp_inc_list; - - tmpbuf = load_file(incname); - } - - free(tmpname); - - if(!tmpbuf) - tmpbuf = strdup(""); - - buffer = (char *)malloc(sizeof(char) * (strlen(buf) + strlen(tmpbuf) + 1)); - strncpy(buffer, buf, (pos - buf)); - memset(buffer + (pos - buf), 0, sizeof(char)); - strcat(buffer, tmpbuf); - strcat(buffer, pos_end); - free(buf); - - if(tmpbuf) - free(tmpbuf); - - buf = buffer; - pos = strstr(buf, inc); - } - - get_keyword(buf, strlen(buf)); - - file.name = name; - - curk = TAILQ_FIRST(&keywords); - curw = TAILQ_FIRST(&stack); - - TAILQ_INIT(&config); - - while (!TAILQ_EMPTY(&keywords)) { - switch (curk->type) { - case SEC_START: - s = get_section(); - TAILQ_INSERT_TAIL(&config, s, entry); - break; - default: - syntax("out of any section"); - break; - } - } - - free(buf); - - return 0; + *head = kw; + return o; } static struct conf_sec * -get_section(void) +get_section(struct keyword **head) { struct conf_sec *s; struct conf_opt *o; struct conf_sec *sub; + struct keyword *kw = *head; - s = emalloc(1, sizeof(*s)); - s->name = strdup(curw->name); + s = xcalloc(1, sizeof(*s)); + s->name = kw->name; TAILQ_INIT(&s->sub); SLIST_INIT(&s->optlist); - pop_stack(); - pop_keyword(); + kw = kw->next; - if (!curk || curk->type != WORD) - syntax("missing section name"); - pop_keyword(); - - while (!TAILQ_EMPTY(&keywords) && curk->type != SEC_END) { - switch (curk->type) { + while (kw && kw->type != SEC_END) { + switch (kw->type) { + case INCLUDE: + kw = include(kw); + break; + case SEC_START: + sub = get_section(&kw); + TAILQ_INSERT_TAIL(&s->sub, sub, entry); + s->nsub++; + break; case WORD: - o = get_option(); + o = get_option(&kw); SLIST_INSERT_HEAD(&s->optlist, o, entry); s->nopt++; break; - case SEC_START: - sub = get_section(); - TAILQ_INSERT_TAIL(&s->sub, sub, entry); - s->nsub++; - case SEC_END: - break; default: - syntax("syntax error"); + syntax(kw, "syntax error"); break; } } - pop_keyword(); - if (curk && curk->type != WORD) - syntax("missing end-section name"); + if (!kw || strcmp(kw->name, s->name)) + syntax(kw, "missing end section %s", s->name); - if (!curk || strcmp(curw->name, s->name)) - syntax("non-closed section '%s'", s->name); + kw = kw->next; + *head = kw; - pop_stack(); - pop_keyword(); return s; } - -static struct conf_opt * -get_option(void) -{ - struct conf_opt *o; - size_t j = 0; - - o = emalloc(1, sizeof(*o)); - o->name = strdup(curw->name); - o->used = False; - o->line = curw->line; - pop_stack(); - pop_keyword(); - - if (!curk || curk->type != EQUAL) - syntax("missing '=' here"); - - pop_keyword(); - - if (!curk) - syntax("syntax error"); - - switch (curk->type) { - case WORD: - o->val[0] = strdup(curw->name); - o->val[1] = NULL; - pop_stack(); - break; - case LIST_START: - pop_keyword(); - while (curk && curk->type != LIST_END) { - if (curk->type != WORD) - syntax("declaration into a list"); - o->val[j++] = strdup(curw->name); - pop_stack(); - pop_keyword(); - } - o->val[j] = NULL; - break; - default: - syntax("syntax error"); - break; - } - pop_keyword(); - return o; -} - - -static void -pop_keyword(void) -{ - if (curk) - { - TAILQ_REMOVE(&keywords, curk, entry); -#ifdef DEBUG - warnx("%s", get_kw_name(curk->type)); -#endif - free(curk); - - curk = TAILQ_FIRST(&keywords); - } -} - -static void -pop_stack(void) -{ - if (curw) - { - TAILQ_REMOVE(&stack, curw, entry); -#ifdef DEBUG - warnx("%s", curw->name); -#endif - free(curw); - - curw = TAILQ_FIRST(&stack); - } -} - -static void -syntax(const char *fmt, ...) -{ - va_list args; - - if (curw) - fprintf(stderr, "%s: %s:%d, near '%s', ", - __progname, file.name, curw->line, curw->name); - else - fprintf(stderr, "%s: %s: ", __progname, file.name); - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); - exit(EXIT_FAILURE); -} - -void -print_unused(struct conf_sec *sec) +int +get_conf(const char *filename) { struct conf_sec *s; - struct conf_opt *o; + struct keyword *head, *kw; - if (!sec) - { - TAILQ_FOREACH(s, &config, entry) - print_unused(s); - return; - } + kw = head = parse_keywords(filename); + if (!head) + return -1; /* TODO ERREUR */ - SLIST_FOREACH(o, &sec->optlist, entry) - if (o->used == False) - warnx("%s:%d, unused param %s", - file.name, o->line, o->name); + TAILQ_INIT(&config); - TAILQ_FOREACH(s, &sec->sub, entry) - if (!TAILQ_EMPTY(&s->sub)) - print_unused(s); -} - -void -free_conf(struct conf_sec *sec) -{ - struct conf_sec *s; - struct conf_opt *o; - size_t n; - - if (!sec) - { - TAILQ_FOREACH(s, &config, entry) - { - free(s->name); - free_conf(s); - free(s); - } - return; - } - - while (!SLIST_EMPTY(&sec->optlist)) - { - o = SLIST_FIRST(&sec->optlist); - SLIST_REMOVE_HEAD(&sec->optlist, entry); - free(o->name); - - for (n = 0; o->val[n]; n++) - free(o->val[n]); - - free(o); - } - - while (!TAILQ_EMPTY(&sec->sub)) - { - s = TAILQ_FIRST(&sec->sub); - TAILQ_REMOVE(&sec->sub, s, entry); - free_conf(s); - } - -} - -struct conf_sec ** -fetch_section(struct conf_sec *s, char *name) -{ - struct conf_sec **ret; - struct conf_sec *sec; - size_t i = 0; - - if (!name) - return NULL; - - if (!s) { - ret = emalloc(2, sizeof(struct conf_sec *)); - TAILQ_FOREACH(sec, &config, entry) - if (!strcmp(sec->name, name)) { - ret[0] = sec; - ret[1] = NULL; + while (kw) { + switch (kw->type) { + case INCLUDE: + kw = include(kw); + break; + case SEC_START: + s = get_section(&kw); + TAILQ_INSERT_TAIL(&config, s, entry); + break; + default: + syntax(kw, "out of any section"); break; - } - } - else { - ret = emalloc(s->nsub+1, sizeof(struct conf_sec *)); - TAILQ_FOREACH(sec, &s->sub, entry) { - if (!strcmp(sec->name, name) && i < s->nsub) - ret[i++] = sec; } - ret[i] = NULL; } - return ret; + return 0; } -struct conf_sec * -fetch_section_first(struct conf_sec *s, char *name) + +void * +xcalloc(size_t nmemb, size_t size) { - struct conf_sec *sec, *ret = NULL; + void *ret; - if (!name) - return NULL; - - if (!s) - { - TAILQ_FOREACH(sec, &config, entry) - if(sec->name && !strcmp(sec->name, name)) { - ret = sec; - break; - } - } - else - { - TAILQ_FOREACH(sec, &s->sub, entry) - if (sec->name && !strcmp(sec->name, name)) { - ret = sec; - break; - } - } + if (!(ret = calloc(nmemb, size))) + warn("calloc"); return ret; } - -size_t -fetch_section_count(struct conf_sec **s) -{ - size_t ret; - for (ret = 0; s[ret]; ret++); - return ret; -} - -struct opt_type * -fetch_opt(struct conf_sec *s, char *dfl, char *name) -{ - struct conf_opt *o; - struct opt_type *ret; - size_t i = 0; - - if (!name) - return NULL; - - ret = emalloc(10, sizeof(struct opt_type)); - - if (s) { - SLIST_FOREACH(o, &s->optlist, entry) - if (!strcmp(o->name, name)) { - while (o->val[i]) { - o->used = True; - ret[i] = string_to_opt(o->val[i]); - i++; - } - ret[i] = opt_type_null; - return ret; - } - } - - ret[0] = string_to_opt(dfl); - ret[1] = opt_type_null; - - return ret; -} - -struct opt_type -fetch_opt_first(struct conf_sec *s, char *dfl, char *name) -{ - struct conf_opt *o; - - if (!name) - return opt_type_null; - else if (s) - SLIST_FOREACH(o, &s->optlist, entry) - if (!strcmp(o->name, name)) { - o->used = True; - return string_to_opt(o->val[0]); - } - return string_to_opt(dfl); -} - -size_t -fetch_opt_count(struct opt_type *o) -{ - size_t ret; - for(ret = 0; o[ret].str; ret++); - return ret; -} - -static struct opt_type -string_to_opt(char *s) -{ - struct opt_type ret = opt_type_null; - - if (!s || !strlen(s)) - return ret; - - ret.num = strtol(s, (char**)NULL, 10); - ret.fnum = strtod(s, NULL); - - if (!strcmp(s, "true") || !strcmp(s, "True") || - !strcmp(s, "TRUE") || !strcmp(s, "1")) - ret.bool = True; - else - ret.bool = False; - - ret.str = s; - - return ret; -} - diff --git a/src/parse/parse.h b/src/parse/parse.h index 9d5b9d5..915e88d 100644 --- a/src/parse/parse.h +++ b/src/parse/parse.h @@ -19,12 +19,20 @@ #include +#define INCLUDE_CMD "@include" + +#define False 0 +#define True 1 + +#define bool_t int + struct conf_opt { char *name; char *val[10]; size_t nval; - Bool used; + bool_t used; int line; + char *filename; SLIST_ENTRY(conf_opt) entry; }; @@ -40,17 +48,10 @@ struct conf_sec { struct opt_type { long int num; float fnum; - Bool bool; + bool_t bool; char *str; }; -/* - * Load all text from file - * return new char* on succes - needs to use free() to delete - * return NULL on failure - */ -char * load_file(const char *name); - /* * Create config from file * return -1 on failure @@ -114,4 +115,8 @@ struct opt_type *fetch_opt(struct conf_sec *, char *, char *); */ size_t fetch_opt_count(struct opt_type *); + +/* wrapper for calloc */ +void *xcalloc(size_t, size_t); + #endif /* PARSE_H */ From 36aa4ce43aee772e193ce7bf75de43cfc7866a68 Mon Sep 17 00:00:00 2001 From: Philippe Pepiot Date: Sat, 28 Aug 2010 21:26:42 +0200 Subject: [PATCH 33/41] Parser: when @include path can be prefixed by "~" or be relative to parent file directory. refs #21 --- src/parse/parse.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/parse/parse.c b/src/parse/parse.c index d2f97df..dd4ee6c 100644 --- a/src/parse/parse.c +++ b/src/parse/parse.c @@ -14,6 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#define _GNU_SOURCE #define _BSD_SOURCE #include #include @@ -22,6 +23,8 @@ #include #include #include +#include +#include #include #include #include @@ -277,13 +280,34 @@ include(struct keyword *head) struct keyword *kw; struct keyword *tail; struct files *file; + struct passwd *user; + char *filename = NULL; + char *base = NULL; head = head->next; if (!head || head->type != WORD) syntax(head, "missing filename to include"); - if (!(kw = parse_keywords(head->name))) { + /* replace ~ by user directory */ + if (head->name && head->name[0] == '~') { + if ( (user = getpwuid(getuid())) && user->pw_dir) + asprintf(&filename, "%s%s", user->pw_dir, head->name+1); + else if (getenv("HOME")) + asprintf(&filename, "%s%s", getenv("HOME"), head->name+1); + else /* to warning ? */ + filename = head->name; + } + /* relative path from parent file */ + else if (head->name && head->name[0] != '/') { + base = strdup(kw->file->parent->name); + asprintf(&filename, "%s/%s", dirname(base), head->name); + free(base); + } + else + filename = head->name; + + if (!(kw = parse_keywords(filename))) { warnx("no config fond in include file %s", head->name); return head->next; } From 839ebeaf2bece364cf576b891498bf613b0fd300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radek=20T=C5=99=C3=AD=C5=A1ka?= Date: Sat, 28 Aug 2010 23:08:29 +0200 Subject: [PATCH 34/41] Launcher: autocompletion alphabetical sort from PeVe --- src/launcher.c | 32 ++++++++++++++++++++++---------- src/util.c | 7 +++++++ src/wmfs.h | 2 +- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/launcher.c b/src/launcher.c index 629b21f..0a1ea2c 100644 --- a/src/launcher.c +++ b/src/launcher.c @@ -37,7 +37,6 @@ #include "wmfs.h" - static char *complete_on_command(char*, size_t); static char *complete_on_files(char*, size_t); @@ -256,7 +255,10 @@ complete_on_command(char *start, size_t hits) char *ret = NULL; DIR *dir; struct dirent *content; - size_t count = 0; + + char **namelist = NULL; + int n = 0; + void *temp = NULL; if (!getenv("PATH") || !start || hits <= 0) return NULL; @@ -265,27 +267,37 @@ complete_on_command(char *start, size_t hits) dirname = strtok(path, ":"); /* recursively open PATH */ - while (dirname) + while (dirname != NULL) { if ((dir = opendir(dirname))) { while ((content = readdir(dir))) - if (!strncmp(content->d_name, start, strlen(start)) && ++count == hits) + { + if(strncmp(content->d_name, ".", 1)) { - ret = _strdup(content->d_name + strlen(start)); - break; + if (!strncmp(content->d_name, start, strlen(start))) + { + temp = realloc(namelist, ++n * sizeof(*namelist)); + if ( temp != NULL ) + namelist = temp; + namelist[n-1] = strdup(content->d_name); + } } + } closedir(dir); } - - if (ret) - break; - dirname = strtok(NULL, ":"); } + qsort(namelist, n, sizeof(char *), qsort_string_compare); free(path); + if(n > 0) + ret = _strdup(namelist[((hits > 0) ? hits - 1 : 0) % n] + strlen(start)); + int i; + for(i = 0; i < n; i++) + free(namelist[i]); + free(namelist); return ret; } diff --git a/src/util.c b/src/util.c index e1e8b1c..8314f48 100644 --- a/src/util.c +++ b/src/util.c @@ -356,3 +356,10 @@ patht(char *path) return ret; } + +int +qsort_string_compare (const void * a, const void * b) +{ + return (strcmp(*(char **)a, *(char **)b)); +} + diff --git a/src/wmfs.h b/src/wmfs.h index 0054a3b..c5da5c1 100644 --- a/src/wmfs.h +++ b/src/wmfs.h @@ -300,7 +300,7 @@ void swap_ptr(void **x, void **y); void uicb_spawn(uicb_t); char *clean_value(char *str); char* patht(char *path); - +int qsort_string_compare (const void * a, const void * b); #ifdef HAVE_IMLIB int parse_image_block(ImageAttr *im, char *str); From 3366ec835f605778e3943d8b0dc33ce435ad8f6a Mon Sep 17 00:00:00 2001 From: Philippe Pepiot Date: Sat, 28 Aug 2010 23:44:49 +0200 Subject: [PATCH 35/41] Parser and launcher: check asprintf return --- src/launcher.c | 22 ++++++++++------------ src/parse/parse.c | 23 ++++++++++++++++++++--- src/parse/parse.h | 2 ++ 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/launcher.c b/src/launcher.c index 0a1ea2c..e2191f8 100644 --- a/src/launcher.c +++ b/src/launcher.c @@ -30,11 +30,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* conforming to glib use _GNU_SOURCE for asprintf declaration */ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - #include "wmfs.h" static char *complete_on_command(char*, size_t); @@ -257,7 +252,7 @@ complete_on_command(char *start, size_t hits) struct dirent *content; char **namelist = NULL; - int n = 0; + int n = 0, i; void *temp = NULL; if (!getenv("PATH") || !start || hits <= 0) @@ -291,12 +286,15 @@ complete_on_command(char *start, size_t hits) qsort(namelist, n, sizeof(char *), qsort_string_compare); free(path); + if(n > 0) + { ret = _strdup(namelist[((hits > 0) ? hits - 1 : 0) % n] + strlen(start)); - int i; - for(i = 0; i < n; i++) - free(namelist[i]); + for(i = 0; i < n; i++) + free(namelist[i]); + } + free(namelist); return ret; } @@ -331,7 +329,7 @@ complete_on_files(char *start, size_t hits) { /* remplace ~ by $HOME in dirname */ if (!strncmp(p, "~/", 2) && getenv("HOME")) - asprintf(&dirname, "%s%s", getenv("HOME"), p+1); + xasprintf(&dirname, "%s%s", getenv("HOME"), p+1); else dirname = _strdup(p); @@ -362,12 +360,12 @@ complete_on_files(char *start, size_t hits) if (!strncmp(content->d_name, p, strlen(p)) && ++count == hits) { /* If it's a directory append '/' to the completion */ - asprintf(&filepath, "%s/%s", path, content->d_name); + xasprintf(&filepath, "%s/%s", path, content->d_name); if (filepath && stat(filepath, &st) != -1) { if (S_ISDIR(st.st_mode)) - asprintf(&ret, "%s/", content->d_name + strlen(p)); + xasprintf(&ret, "%s/", content->d_name + strlen(p)); else ret = _strdup(content->d_name + strlen(p)); } diff --git a/src/parse/parse.c b/src/parse/parse.c index dd4ee6c..9f0d52f 100644 --- a/src/parse/parse.c +++ b/src/parse/parse.c @@ -292,16 +292,16 @@ include(struct keyword *head) /* replace ~ by user directory */ if (head->name && head->name[0] == '~') { if ( (user = getpwuid(getuid())) && user->pw_dir) - asprintf(&filename, "%s%s", user->pw_dir, head->name+1); + xasprintf(&filename, "%s%s", user->pw_dir, head->name+1); else if (getenv("HOME")) - asprintf(&filename, "%s%s", getenv("HOME"), head->name+1); + xasprintf(&filename, "%s%s", getenv("HOME"), head->name+1); else /* to warning ? */ filename = head->name; } /* relative path from parent file */ else if (head->name && head->name[0] != '/') { base = strdup(kw->file->parent->name); - asprintf(&filename, "%s/%s", dirname(base), head->name); + xasprintf(&filename, "%s/%s", dirname(base), head->name); free(base); } else @@ -471,6 +471,7 @@ get_conf(const char *filename) } +/* calloc wrapper */ void * xcalloc(size_t nmemb, size_t size) { @@ -481,3 +482,19 @@ xcalloc(size_t nmemb, size_t size) return ret; } + +/* asprintf wrapper */ +int +xasprintf(char **strp, const char *fmt, ...) +{ + int ret; + va_list args; + + va_start(args, fmt); + ret = vasprintf(strp, fmt, args); + va_end(args); + + if (ret == -1) + err(EXIT_FAILURE, "asprintf"); + return ret; +} diff --git a/src/parse/parse.h b/src/parse/parse.h index 915e88d..87ef368 100644 --- a/src/parse/parse.h +++ b/src/parse/parse.h @@ -118,5 +118,7 @@ size_t fetch_opt_count(struct opt_type *); /* wrapper for calloc */ void *xcalloc(size_t, size_t); +/* wrapper for asprintf */ +int xasprintf(char **, const char *, ...); #endif /* PARSE_H */ From 8816bd6753f6632fc99b744ce5443ab6161a1720 Mon Sep 17 00:00:00 2001 From: Philippe Pepiot Date: Sat, 28 Aug 2010 23:47:47 +0200 Subject: [PATCH 36/41] Spawn: check write() --- src/util.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/util.c b/src/util.c index 8314f48..31807ca 100644 --- a/src/util.c +++ b/src/util.c @@ -241,7 +241,10 @@ spawn(const char *format, ...) execl(sh, sh, "-c", cmd, (char*)NULL); exit(EXIT_FAILURE); } - write(p[1], &pid, sizeof(pid_t)); + + if (sizeof(pid_t) != write(p[1], &pid, sizeof(pid_t))) + warn("write"); + close(p[1]); exit(EXIT_SUCCESS); } From 4a3952f54f16068cd9d5c0401402e9942c1adc1f Mon Sep 17 00:00:00 2001 From: Philippe Pepiot Date: Mon, 30 Aug 2010 19:37:04 +0200 Subject: [PATCH 37/41] Parser: errors on calloc fail or buffer overflow --- src/parse/parse.c | 60 +++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/src/parse/parse.c b/src/parse/parse.c index 9f0d52f..880a5c5 100644 --- a/src/parse/parse.c +++ b/src/parse/parse.c @@ -36,6 +36,7 @@ extern char *__progname; enum keyword_t { SEC_START, SEC_END, INCLUDE, WORD, EQUAL, LIST_START, LIST_END, NONE }; +#ifdef DEBUG static struct { const char *name; enum keyword_t type; @@ -49,6 +50,7 @@ static struct { {"LIST_END", LIST_END}, {"NONE", NONE}, }; +#endif struct files { char *name; @@ -115,6 +117,26 @@ push_keyword(struct keyword *tail, enum keyword_t type, char *buf, size_t *offse return kw; } +static void +syntax(struct keyword *kw, const char *fmt, ...) +{ + va_list args; + + fprintf(stderr, "%s: %s:%d", __progname, kw->file->name, kw->line); + if (kw->name) + fprintf(stderr, ", near '%s'", kw->name); + fprintf(stderr, ": "); + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + + fprintf(stderr, "\n"); + + exit(EXIT_FAILURE); +} + + #define PUSH_KEYWORD(type) tail = push_keyword(tail, type, bufname, &j, file, line) static struct keyword * parse_keywords(const char *filename) @@ -205,11 +227,15 @@ parse_keywords(const char *filename) type = SEC_START; } + /* get section name */ while (buf[i] != ']') { - if (i >= (size_t)st.st_size) - { - /* TODO ERREUR */ + + if (i >= ((size_t)st.st_size-1) || j >= (BUFSIZ-1)) { + bufname[j] = '\0'; + syntax(NULL, "word too long in %s:%d near '%s'", + file->name, line, bufname); } + bufname[j++] = buf[i++]; } PUSH_KEYWORD(type); @@ -248,6 +274,12 @@ parse_keywords(const char *filename) continue; } + if (j >= (BUFSIZ - 1)) { + bufname[j] = '\0'; + syntax(NULL, "word too long in %s:%d near '%s'", + file->name, line, bufname); + } + bufname[j++] = buf[i]; } munmap(buf, st.st_size); @@ -255,25 +287,6 @@ parse_keywords(const char *filename) return head; } -static void -syntax(struct keyword *kw, const char *fmt, ...) -{ - va_list args; - - fprintf(stderr, "%s: %s:%d", __progname, kw->file->name, kw->line); - if (kw->name) - fprintf(stderr, ", near '%s'", kw->name); - fprintf(stderr, ": "); - - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); - - fprintf(stderr, "\n"); - - exit(EXIT_FAILURE); -} - static struct keyword * include(struct keyword *head) { @@ -478,7 +491,7 @@ xcalloc(size_t nmemb, size_t size) void *ret; if (!(ret = calloc(nmemb, size))) - warn("calloc"); + err(EXIT_FAILURE, "calloc"); return ret; } @@ -496,5 +509,6 @@ xasprintf(char **strp, const char *fmt, ...) if (ret == -1) err(EXIT_FAILURE, "asprintf"); + return ret; } From 3841e55f82895d56e55cdebd60c9b2fbbe84452f Mon Sep 17 00:00:00 2001 From: Philippe Pepiot Date: Mon, 30 Aug 2010 19:50:38 +0200 Subject: [PATCH 38/41] Parser: Use defined Bool or create one --- src/parse/parse.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/parse/parse.h b/src/parse/parse.h index 87ef368..8b1497e 100644 --- a/src/parse/parse.h +++ b/src/parse/parse.h @@ -21,10 +21,11 @@ #define INCLUDE_CMD "@include" -#define False 0 -#define True 1 - -#define bool_t int +#if defined(Bool) +#define bool_t Bool +#else +typedef enum { False, True } bool_t; +#endif /* Bool */ struct conf_opt { char *name; From 5aeeae41985790a2e83b003b50d15be265825391 Mon Sep 17 00:00:00 2001 From: Philippe Pepiot Date: Tue, 31 Aug 2010 00:55:51 +0200 Subject: [PATCH 39/41] Parse: when syntax error, fallback to default config, fixes #45 --- src/config.c | 4 +- src/parse/api.c | 39 ------- src/parse/parse.c | 275 +++++++++++++++++++++++++++++++--------------- src/parse/parse.h | 5 +- src/wmfs.c | 2 +- 5 files changed, 193 insertions(+), 132 deletions(-) diff --git a/src/config.c b/src/config.c index 0714721..6739f77 100644 --- a/src/config.c +++ b/src/config.c @@ -181,7 +181,8 @@ void conf_bar_section(void) { struct conf_sec *bar, **mouse, *selbar, *systray; - char *barbg, sc = screen_count(); + char *barbg; + int sc = screen_count(); bar = fetch_section_first(NULL, "bar"); @@ -230,7 +231,6 @@ conf_bar_section(void) } free(mouse); - free(barbg); return; } diff --git a/src/parse/api.c b/src/parse/api.c index 0284dcd..592dbf4 100644 --- a/src/parse/api.c +++ b/src/parse/api.c @@ -71,45 +71,6 @@ print_unused(struct conf_sec *sec) print_unused(s); } -void -free_conf(struct conf_sec *sec) -{ - struct conf_sec *s; - struct conf_opt *o; - size_t n; - - if (!sec) - { - TAILQ_FOREACH(s, &config, entry) - { - free(s->name); - free_conf(s); - free(s); - } - return; - } - - while (!SLIST_EMPTY(&sec->optlist)) - { - o = SLIST_FIRST(&sec->optlist); - SLIST_REMOVE_HEAD(&sec->optlist, entry); - free(o->name); - - for (n = 0; o->val[n]; n++) - free(o->val[n]); - - free(o); - } - - while (!TAILQ_EMPTY(&sec->sub)) - { - s = TAILQ_FIRST(&sec->sub); - TAILQ_REMOVE(&sec->sub, s, entry); - free_conf(s); - } - -} - struct conf_sec ** fetch_section(struct conf_sec *s, char *name) { diff --git a/src/parse/parse.c b/src/parse/parse.c index 880a5c5..bf1371f 100644 --- a/src/parse/parse.c +++ b/src/parse/parse.c @@ -122,8 +122,12 @@ syntax(struct keyword *kw, const char *fmt, ...) { va_list args; - fprintf(stderr, "%s: %s:%d", __progname, kw->file->name, kw->line); - if (kw->name) + fprintf(stderr, "%s:", __progname); + + if (kw && kw->file && kw->file->name) + fprintf(stderr, "%s:%d", kw->file->name, kw->line); + + if (kw && kw->name) fprintf(stderr, ", near '%s'", kw->name); fprintf(stderr, ": "); @@ -132,8 +136,6 @@ syntax(struct keyword *kw, const char *fmt, ...) va_end(args); fprintf(stderr, "\n"); - - exit(EXIT_FAILURE); } @@ -154,6 +156,7 @@ parse_keywords(const char *filename) char path[PATH_MAX]; size_t i, j; int line; + bool_t error = False; if ((fd = open(filename, O_RDONLY)) == -1 || stat(filename, &st) == -1) { @@ -161,28 +164,27 @@ parse_keywords(const char *filename) return NULL; } - buf = (char *)mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, SEEK_SET); - - if (buf == (char*)MAP_FAILED) { - warn("%s", filename); - return NULL; - } - if (!realpath(filename, path)) { warn("%s", filename); return NULL; } file = xcalloc(1, sizeof(*file)); + bufname = xcalloc(1, sizeof(*bufname) * BUFSIZ); file->name = strdup(path); file->parent = NULL; - bufname = xcalloc(1, sizeof(*bufname) * BUFSIZ); + buf = (char *)mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, SEEK_SET); + + if (buf == (char*)MAP_FAILED) { + warn("%s", filename); + return NULL; + } for(i = 0, j = 0, line = 1; i < (size_t)st.st_size; i++) { - if (tail && !head) + if (!head && tail) head = tail; if (buf[i] == '\n' && s.comment == True) { @@ -199,94 +201,106 @@ parse_keywords(const char *filename) if (s.comment == True) continue; - if (buf[i] == s.quote_char && s.quote == True) { + if (s.quote == True && buf[i] == s.quote_char) { /* end of quotted string */ PUSH_KEYWORD(WORD); s.quote = False; continue; } - if ((buf[i] == '"' || buf[i] == '\'') && - s.quote == False) - { - PUSH_KEYWORD(WORD); - /* begin quotted string */ - s.quote_char = buf[i]; - s.quote = True; - continue; - } - - if (buf[i] == '[' && s.quote == False) { - PUSH_KEYWORD(WORD); - if (buf[i+1] == '/') { - i +=2; - type = SEC_END; - } - else { - i++; - type = SEC_START; + if (s.quote == False) { + if ((buf[i] == '"' || buf[i] == '\'')) { + PUSH_KEYWORD(WORD); + /* begin quotted string */ + s.quote_char = buf[i]; + s.quote = True; + continue; } - /* get section name */ - while (buf[i] != ']') { - - if (i >= ((size_t)st.st_size-1) || j >= (BUFSIZ-1)) { - bufname[j] = '\0'; - syntax(NULL, "word too long in %s:%d near '%s'", - file->name, line, bufname); + if (buf[i] == '[') { + PUSH_KEYWORD(WORD); + if (buf[i+1] == '/') { + i +=2; + type = SEC_END; + } + else { + i++; + type = SEC_START; } - bufname[j++] = buf[i++]; + /* get section name */ + while (buf[i] != ']') { + + if (i >= ((size_t)st.st_size-1) || j >= (BUFSIZ-1)) { + bufname[j] = '\0'; + syntax(NULL, "word too long in %s:%d near '%s'", + file->name, line, bufname); + error = True; + break; + } + + bufname[j++] = buf[i++]; + } + PUSH_KEYWORD(type); + continue; } - PUSH_KEYWORD(type); - continue; - } - if (buf[i] == '{' && s.quote == False) { - PUSH_KEYWORD(WORD); - PUSH_KEYWORD(LIST_START); - continue; - } + if (buf[i] == '{') { + PUSH_KEYWORD(WORD); + PUSH_KEYWORD(LIST_START); + continue; + } - if (buf[i] == '}' && s.quote == False) { - PUSH_KEYWORD(WORD); - PUSH_KEYWORD(LIST_END); - continue; - } + if (buf[i] == '}') { + PUSH_KEYWORD(WORD); + PUSH_KEYWORD(LIST_END); + continue; + } - if (buf[i] == ',' && s.quote == False) { - PUSH_KEYWORD(WORD); - continue; - } + if (buf[i] == ',') { + PUSH_KEYWORD(WORD); + continue; + } - if (buf[i] == '=' && s.quote == False) { - PUSH_KEYWORD(WORD); - PUSH_KEYWORD(EQUAL); - continue; - } + if (buf[i] == '=') { + PUSH_KEYWORD(WORD); + PUSH_KEYWORD(EQUAL); + continue; + } - if (strchr("\t\n ", buf[i]) && s.quote == False) { - PUSH_KEYWORD(WORD); + if (strchr("\t\n ", buf[i])) { + PUSH_KEYWORD(WORD); - if (buf[i] == '\n') - line++; + if (buf[i] == '\n') + line++; - continue; - } + continue; + } + } /* s.quote == False */ if (j >= (BUFSIZ - 1)) { bufname[j] = '\0'; syntax(NULL, "word too long in %s:%d near '%s'", file->name, line, bufname); + error = True; + break; } bufname[j++] = buf[i]; } + munmap(buf, st.st_size); + free(bufname); warnx("%s read", file->name); - return head; + + return (error ? NULL: head); } +/* + * return NULL on failure and head->next if + * no config found (of file doesn't exist) + * NOTE to devs: head->name is the file to include + */ static struct keyword * include(struct keyword *head) { @@ -299,8 +313,10 @@ include(struct keyword *head) head = head->next; - if (!head || head->type != WORD) + if (!head || head->type != WORD) { syntax(head, "missing filename to include"); + return NULL; + } /* replace ~ by user directory */ if (head->name && head->name[0] == '~') { @@ -322,19 +338,29 @@ include(struct keyword *head) if (!(kw = parse_keywords(filename))) { warnx("no config fond in include file %s", head->name); - return head->next; + + if (filename != head->name) + free(filename); + + return NULL; } kw->file->parent = head->file; - head = head->next; /* detect circular include */ - for (file = kw->file->parent; file != NULL; file = file->parent) - { - if (!strcmp(file->name, kw->file->name)) + for (file = kw->file->parent; file != NULL; file = file->parent) { + if (!strcmp(file->name, kw->file->name)) { syntax(kw, "circular include of %s", kw->file->name); + + if (filename != head->name) + free(filename); + + return NULL; + } } + head = head->next; + if (kw) { for (tail = kw; tail->next; tail = tail->next); tail->next = head; @@ -343,6 +369,20 @@ include(struct keyword *head) return kw; } +static void * +free_opt(struct conf_opt *o) +{ + int i; + if (o) { + if (o->name) + free(o->name); + for (i = 0; o->val[i]; i++) + free(o->val[i]); + free(o); + } + return NULL; +} + static struct conf_opt * get_option(struct keyword **head) { @@ -358,18 +398,23 @@ get_option(struct keyword **head) kw = kw->next; - if (kw->type != EQUAL) + if (kw->type != EQUAL) { syntax(kw, "missing '=' here"); + return free_opt(o); + } kw = kw->next; - if (!kw) + if (!kw) { syntax(kw, "missing value"); + return free_opt(o); + } switch (kw->type) { case INCLUDE: - kw = include(kw); + if (!(kw = include(kw))) + return free_opt(o); break; case WORD: o->val[0] = kw->name; @@ -381,27 +426,34 @@ get_option(struct keyword **head) while (kw && kw->type != LIST_END) { switch (kw->type) { case WORD: - if (j > 9) + if (j > (PARSE_MAX_LIST - 1)) { syntax(kw, "too much values in list"); + return free_opt(o); + } o->val[j++] = kw->name; kw = kw->next; break; case INCLUDE: - kw = include(kw); + if (!(kw = include(kw))) + return free_opt(o); break; default: syntax(kw, "declaration into a list"); + return free_opt(o); break; } } - if (!kw) + if (!kw) { syntax(kw, "list unclosed"); + return free_opt(o); + } kw = kw->next; break; default: syntax(kw, "missing value"); + return free_opt(o); break; } @@ -409,6 +461,29 @@ get_option(struct keyword **head) return o; } +static void * +free_sec(struct conf_sec *sec) +{ + struct conf_opt *o; + struct conf_sec *s; + + if (sec) { + while (!SLIST_EMPTY(&sec->optlist)) { + o = SLIST_FIRST(&sec->optlist); + SLIST_REMOVE_HEAD(&sec->optlist, entry); + free_opt(o); + } + while (!TAILQ_EMPTY(&sec->sub)) { + s = TAILQ_FIRST(&sec->sub); + TAILQ_REMOVE(&sec->sub, s, entry); + free_sec(s); + } + free(sec->name); + free(sec); + } + return NULL; +} + static struct conf_sec * get_section(struct keyword **head) { @@ -427,26 +502,32 @@ get_section(struct keyword **head) while (kw && kw->type != SEC_END) { switch (kw->type) { case INCLUDE: - kw = include(kw); + if (!(kw = include(kw))) + return free_sec(s); break; case SEC_START: - sub = get_section(&kw); + if (!(sub = get_section(&kw))) + return free_sec(s); TAILQ_INSERT_TAIL(&s->sub, sub, entry); s->nsub++; break; case WORD: - o = get_option(&kw); + if (!(o = get_option(&kw))) + return free_sec(s); SLIST_INSERT_HEAD(&s->optlist, o, entry); s->nopt++; break; default: syntax(kw, "syntax error"); + return free_sec(s); break; } } - if (!kw || strcmp(kw->name, s->name)) + if (!kw || strcmp(kw->name, s->name)) { syntax(kw, "missing end section %s", s->name); + return free_sec(s); + } kw = kw->next; *head = kw; @@ -454,6 +535,20 @@ get_section(struct keyword **head) return s; } +int +free_conf(void) +{ + struct conf_sec *s; + struct keyword *kw = NULL; + + while (!TAILQ_EMPTY(&config)) { + s = TAILQ_FIRST(&config); + TAILQ_REMOVE(&config, s, entry); + free_sec(s); + } + return -1; +} + int get_conf(const char *filename) { @@ -461,6 +556,7 @@ get_conf(const char *filename) struct keyword *head, *kw; kw = head = parse_keywords(filename); + if (!head) return -1; /* TODO ERREUR */ @@ -469,14 +565,17 @@ get_conf(const char *filename) while (kw) { switch (kw->type) { case INCLUDE: - kw = include(kw); + if (!(kw = include(kw))) + return free_conf(); break; case SEC_START: - s = get_section(&kw); + if (!(s = get_section(&kw))) + return free_conf(); TAILQ_INSERT_TAIL(&config, s, entry); break; default: syntax(kw, "out of any section"); + return free_conf(); break; } } diff --git a/src/parse/parse.h b/src/parse/parse.h index 8b1497e..8a0f9f2 100644 --- a/src/parse/parse.h +++ b/src/parse/parse.h @@ -20,6 +20,7 @@ #include #define INCLUDE_CMD "@include" +#define PARSE_MAX_LIST 10 #if defined(Bool) #define bool_t Bool @@ -29,7 +30,7 @@ typedef enum { False, True } bool_t; struct conf_opt { char *name; - char *val[10]; + char *val[PARSE_MAX_LIST]; size_t nval; bool_t used; int line; @@ -70,7 +71,7 @@ void print_unused(struct conf_sec *s); * WARNING: This make all string * returned by fetch_(opt|section)(_first) unusable. */ -void free_conf(struct conf_sec *s); +int free_conf(void); /* * Get all subsection matching the given name on the given diff --git a/src/wmfs.c b/src/wmfs.c index fc11c6f..d1c666a 100644 --- a/src/wmfs.c +++ b/src/wmfs.c @@ -126,7 +126,7 @@ quit(void) IFREE(conf.client.mouse); IFREE(conf.root.mouse); - free_conf(NULL); + free_conf(); XSync(dpy, False); XCloseDisplay(dpy); From c6469260de807487fa13467351bbf8f7f23cd1c4 Mon Sep 17 00:00:00 2001 From: Philippe Pepiot Date: Tue, 31 Aug 2010 00:59:35 +0200 Subject: [PATCH 40/41] Cmake: put default config in XDGCONFDIR --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 90791b2..ac3e474 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -153,7 +153,7 @@ set(WMFS_DOCS install(FILES ${WMFS_DOCS} DESTINATION ${CMAKE_DOCDIR}) # config file -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/wmfsrc DESTINATION ${CMAKE_SYSCONFDIR}/${PROJECT_NAME}) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/wmfsrc DESTINATION ${CMAKE_XDGCONFDIR}/${PROJECT_NAME}) # xsession install(FILES "wmfs.desktop" DESTINATION ${CMAKE_DATADIR}/xsessions) From b91db6b431fb2fd49c23a53a2c5cb3d78b5aa853 Mon Sep 17 00:00:00 2001 From: Philippe Pepiot Date: Tue, 31 Aug 2010 01:55:42 +0200 Subject: [PATCH 41/41] Parser: free keywords list and free files --- src/parse/parse.c | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/src/parse/parse.c b/src/parse/parse.c index bf1371f..1f074a6 100644 --- a/src/parse/parse.c +++ b/src/parse/parse.c @@ -74,6 +74,7 @@ struct state { /* TO REMOVE (use a identifier for config and fallback XDG in api functions) */ TAILQ_HEAD(, conf_sec) config; +static struct keyword *keywords = NULL; static struct keyword * push_keyword(struct keyword *tail, enum keyword_t type, char *buf, size_t *offset, struct files *file, int line) @@ -372,14 +373,8 @@ include(struct keyword *head) static void * free_opt(struct conf_opt *o) { - int i; - if (o) { - if (o->name) - free(o->name); - for (i = 0; o->val[i]; i++) - free(o->val[i]); + if (o) free(o); - } return NULL; } @@ -478,7 +473,6 @@ free_sec(struct conf_sec *sec) TAILQ_REMOVE(&sec->sub, s, entry); free_sec(s); } - free(sec->name); free(sec); } return NULL; @@ -539,13 +533,42 @@ int free_conf(void) { struct conf_sec *s; - struct keyword *kw = NULL; + struct keyword *kw, *nkw; + struct files **f = NULL; + int i, nf = 0; while (!TAILQ_EMPTY(&config)) { s = TAILQ_FIRST(&config); TAILQ_REMOVE(&config, s, entry); free_sec(s); } + + kw = keywords; + + while (kw) { + nkw = kw->next; + + if (kw->name) + free(kw->name); + + for (i = 0; i < nf; i++) { + if (f[i] == kw->file) { + if (!(f = realloc(f, sizeof(*f) * (++i)))) + err(EXIT_FAILURE, "realloc"); + f[i-1] = kw->file; + } + } + + kw = nkw; + } + + if (nf > 0) { + for (i = 0; i < nf; i++) { + free(f[i]->name); + free(f[i]); + } + free(f); + } return -1; } @@ -560,6 +583,8 @@ get_conf(const char *filename) if (!head) return -1; /* TODO ERREUR */ + keywords = head; + TAILQ_INIT(&config); while (kw) {