-DENGINEDIR=\"$(enginedir)\" \
-DTHEMEDIR=\"$(themedir)\" \
-DDEFAULT_THEME=\"nyz\" \
--DDEFAULT_FONT=\"Sans-7\" \
-DG_LOG_DOMAIN=\"Openbox-Engine\"
engine_LTLIBRARIES=openbox.la
int ob_s_winfont_height;
int ob_s_winfont_shadow;
int ob_s_winfont_shadow_offset;
+int ob_s_winfont_shadow_tint;
ObFont *ob_s_winfont;
/* style settings - masks */
pixmap_mask *ob_s_max_set_mask;
self->icon_x = -1;
self->desk_x = -1;
self->shade_x = -1;
- self->icon_x = -1;
+ self->iconify_x = -1;
self->label_x = -1;
self->max_x = -1;
self->close_x = -1;
n = d = i = l = m = c = s = FALSE;
- if (!config_get("titlebar.layout", Config_String, &layout)) {
- layout.string = "NDSLIMC";
- config_set("titlebar.layout", Config_String, layout);
- }
+ if (!config_get("titlebar.layout", Config_String, &layout))
+ g_assert_not_reached();
/* figure out whats being shown, and the width of the label */
self->label_width = self->width - (ob_s_bevel + 1) * 2;
extern int ob_s_winfont_height;
extern int ob_s_winfont_shadow;
extern int ob_s_winfont_shadow_offset;
+extern int ob_s_winfont_shadow_tint;
extern ObFont *ob_s_winfont;
extern pixmap_mask *ob_s_max_set_mask;
XrmDatabase db = NULL;
Justify winjust;
char *winjuststr;
- ConfigValue theme, shadow, offset, font;
+ ConfigValue theme, shadow, offset, font, tint;
if (config_get("theme", Config_String, &theme)) {
db = loaddb(theme.string);
/* load the font, not from the theme file tho, its in the config */
- if (!config_get("font.shadow", Config_Bool, &shadow)) {
- shadow.bool = TRUE; /* default */
- config_set("font.shadow", Config_Bool, shadow);
- }
+ if (!config_get("font.shadow", Config_Bool, &shadow))
+ g_assert_not_reached();
ob_s_winfont_shadow = shadow.bool;
- if (!config_get("font.shadow.offset", Config_Integer, &offset) ||
- offset.integer < 0 || offset.integer >= 10) {
- offset.integer = 1; /* default */
- config_set("font.shadow.offset", Config_Integer, offset);
- }
+ if (!config_get("font.shadow.offset", Config_Integer, &offset))
+ g_assert_not_reached();
ob_s_winfont_shadow_offset = offset.integer;
- if (!config_get("font", Config_String, &font)) {
- font.string = DEFAULT_FONT;
- config_set("font", Config_String, font);
- }
+ if (!config_get("font.shadow.tint", Config_Integer, &tint))
+ g_assert_not_reached();
+ /* XXX put these checks into the config system somehow!!! */
+ if (tint.integer < -100) tint.integer = -100;
+ if (tint.integer > 100) tint.integer = 100;
+ config_set("font.shadow.tint", Config_Integer, tint);
+ ob_s_winfont_shadow_tint = tint.integer;
+ if (!config_get("font", Config_String, &font))
+ g_assert_not_reached();
ob_s_winfont = font_open(font.string);
ob_s_winfont_height = font_height(ob_s_winfont, ob_s_winfont_shadow,
ob_s_winfont_shadow_offset);
ob_a_focused_label->texture[0].data.text.shadow = ob_s_winfont_shadow;
ob_a_focused_label->texture[0].data.text.offset =
ob_s_winfont_shadow_offset;
+ ob_a_focused_label->texture[0].data.text.tint = ob_s_winfont_shadow_tint;
ob_a_focused_label->texture[0].data.text.color = ob_s_title_focused_color;
ob_a_unfocused_label->texture[0].type = Text;
ob_a_unfocused_label->texture[0].data.text.shadow = ob_s_winfont_shadow;
ob_a_unfocused_label->texture[0].data.text.offset =
ob_s_winfont_shadow_offset;
+ ob_a_unfocused_label->texture[0].data.text.tint = ob_s_winfont_shadow_tint;
ob_a_unfocused_label->texture[0].data.text.color =
ob_s_title_unfocused_color;
openbox3_LDFLAGS=-export-dynamic
openbox3_SOURCES=client.c event.c extensions.c focus.c frame.c openbox.c \
prop.c screen.c stacking.c xerror.c timer.c dispatch.c \
- engine.c plugin.c action.c grab.c lex.cparse.c config.c menu.c
+ engine.c plugin.c action.c grab.c config.c menu.c \
+ y.tab.c lex.yy.c parse.c
noinst_HEADERS=client.h event.h extensions.h focus.h frame.h geom.h gettext.h \
openbox.h prop.h screen.h stacking.h xerror.h dispatch.h \
- timer.h engine.h plugin.h action.h grab.h config.h menu.h
+ timer.h engine.h plugin.h action.h grab.h config.h menu.h parse.h
-lex.cparse.c: cparse.l
- $(FLEX) -Pcparse $^
+lex.yy.c: parse.l
+ $(FLEX) $^
+
+y.tab.c: parse.yacc
+ $(YACC) -d $<
MAINTAINERCLEANFILES= Makefile.in
"Engine",
"The name of the theming engine to be used "
"to decorate windows."));
+
config_def_set(config_def_new("theme", Config_String,
"Theme",
"The name of the theme to load with the "
"chosen engine."));
+
config_def_set(config_def_new("font", Config_String,
"Titlebar Font",
"The fontstring specifying the font to "
"be used in window titlebars."));
+ val.string = "Sans-7";
+ config_set("font", Config_String, val);
+
config_def_set(config_def_new("font.shadow", Config_Bool,
"Titlebar Font Shadow",
"Whether or not the text in the window "
"titlebars gets a drop shadow."));
+ val.bool = FALSE;
+ config_set("font.shadow", Config_Bool, val);
+
config_def_set(config_def_new("font.shadow.offset", Config_Integer,
"Titlebar Font Shadow Offset",
"The offset of the drop shadow for text "
"in the window titlebars."));
+ val.integer = 1;
+ config_set("font.shadow.offset", Config_Integer, val);
+
+ config_def_set(config_def_new("font.shadow.tint", Config_Integer,
+ "Titlebar Font Shadow Tint",
+ "The percentage of tint/opacity to give the "
+ "the shadow(from -100(white) to "
+ "100(black))."));
+ val.integer = 25;
+ config_set("font.shadow.tint", Config_Integer, val);
+
config_def_set(config_def_new("titlebar.layout", Config_String,
"Titlebar Layout",
"The ordering of the elements in the "
"window titlebars."));
+ val.string = "NDSLIMC";
+ config_set("titlebar.layout", Config_String, val);
config_def_set(config_def_new("focusNew", Config_Bool,
"Focus New Windows",
g_datalist_clear(&config_def);
}
-void config_parse()
-{
- FILE *file;
- char *path;
- gboolean load = FALSE;
-
- /* load the user rc */
- path = g_build_filename(g_get_home_dir(), ".openbox", "rc3", NULL);
- if ((file = fopen(path, "r")) != NULL) {
- cparse_go(path, file);
- fclose(file);
- load = TRUE;
- }
- g_free(path);
-
- if (!load) {
- /* load the system wide rc */
- path = g_build_filename(RCDIR, "rc3", NULL);
- if ((file = fopen(path, "r")) != NULL) {
- /*cparse_go(path, file);*/
- fclose(file);
- }
- g_free(path);
- }
-}
-
gboolean config_set(char *name, ConfigValueType type, ConfigValue value)
{
ConfigDefEntry *def;
FALSE. */
gboolean config_def_set(ConfigDefEntry *entry);
-void config_parse();
-
#endif
+++ /dev/null
-%{
-#include <glib.h>
-#include "config.h"
-
-static char *filename;
-static int lineno = 1;
-static gboolean haserror = FALSE;
-static gboolean comment = FALSE;
-static ConfigEntry entry = { NULL, -1 };
-
-static void stringvalue();
-static void numbervalue();
-static void boolvalue();
-static void identifier();
-static void newline();
-static int cparsewrap();
-%}
-
-number [0-9]+
-string \"[^"\n]*\"
-identifier [a-zA-Z][a-zA-Z0-9_.]*
-white [ \t]*
-assign {white}={white}
-bool ([tT][rR][uU][eE]|[fF][aA][lL][sS][eE]|[yY][eE][sS]|[nN][oO]|[oO][nN]|[oO][fF][fF])
-
-%%
-
-^{white}# comment = TRUE;
-{bool}/{white}\n boolvalue();
-{string}/{white}\n stringvalue();
-{number}/{white}\n numbervalue();
-^{identifier}/{assign} identifier();
-\n newline();
-=
-[ \t]
-. if (!comment) haserror = TRUE;
-
-%%
-
-static void stringvalue()
-{
- if (!comment) {
- if (!haserror && entry.name != NULL && (signed)entry.type < 0) {
- entry.type = Config_String;
- entry.value.string = g_strdup(cparsetext+1); /* drop the left quote */
- if (entry.value.string[cparseleng-2] != '"')
- g_warning("improperly terminated string on line %d",
- lineno);
- else
- entry.value.string[cparseleng-2] = '\0';
- } else
- haserror = TRUE;
- }
-}
-
-static void numbervalue()
-{
- if (!comment) {
- if (!haserror && entry.name != NULL && (signed)entry.type < 0) {
- entry.type = Config_Integer;
- entry.value.integer = atoi(cparsetext);
- } else
- haserror = TRUE;
- }
-}
-
-static void boolvalue()
-{
- if (!comment) {
- if (!haserror && entry.name != NULL && (signed)entry.type < 0) {
- entry.type = Config_Bool;
- entry.value.bool = (!g_ascii_strcasecmp("true", cparsetext) ||
- !g_ascii_strcasecmp("yes", cparsetext) ||
- !g_ascii_strcasecmp("on", cparsetext));
- } else
- haserror = TRUE;
- }
-}
-
-static void identifier()
-{
- if (!comment) {
- entry.name = g_strdup(cparsetext);
- entry.type = -1;
- }
-}
-
-static void newline()
-{
- if (!comment) {
- if (!haserror && entry.name != NULL && (signed)entry.type >= 0) {
- if (!config_set(entry.name, entry.type, entry.value))
- g_warning("Parser error in '%s' on line %d\n", filename,
- lineno);
- } else if (haserror || entry.name != NULL || (signed)entry.type >= 0) {
- g_warning("Parser error in '%s' on line %d", filename, lineno);
- }
- g_free(entry.name);
- entry.name = NULL;
- if (entry.type == Config_String)
- g_free(entry.value.string);
- entry.type = -1;
-
- haserror = FALSE;
- }
- comment = FALSE;
- ++lineno;
-}
-
-static int cparsewrap()
-{
- g_free(entry.name);
- entry.name = NULL;
- if (entry.type == Config_String)
- g_free(entry.value.string);
- return 1;
-}
-
-void cparse_go(char *fname, FILE *file)
-{
- filename = fname;
- cparsein = file;
- cparselex();
-}
#include "extensions.h"
#include "gettext.h"
#include "config.h"
+#include "parse.h"
#include "grab.h"
#include "engine.h"
#include "plugin.h"
prop_startup(); /* get atoms values for the display */
extensions_query_all(); /* find which extensions are present */
-
+
if (screen_annex()) { /* it will be ours! */
timer_startup();
config_startup();
font_startup();
plugin_startup();
+ /* startup the parsing so plugins can register sections of the rc */
+ parse_startup();
+
/* load the plugins specified in the pluginrc */
plugin_loadall();
/* parse/load user options */
- config_parse();
+ parse_rc();
+
+ /* we're done with parsing now, kill it */
+ parse_shutdown();
engine_startup();
event_startup();
--- /dev/null
+#include "parse.h"
+#include "config.h"
+
+static GHashTable *reg = NULL;
+static ParseFunc func = NULL;
+
+/* parse tokens from the [openbox] section of the rc file */
+static void parse_rc_token(ParseTokenType type, union ParseToken token);
+
+void destkey(gpointer key) { g_free(key); }
+
+void parse_startup()
+{
+ reg = g_hash_table_new_full(g_str_hash, g_str_equal, destkey, NULL);
+ func = NULL;
+
+ parse_reg_section("openbox", parse_rc_token);
+}
+
+void parse_shutdown()
+{
+ g_hash_table_destroy(reg);
+}
+
+void parse_reg_section(char *section, ParseFunc func)
+{
+ if (g_hash_table_lookup(reg, section) != NULL)
+ g_warning("duplicate request for section '%s' in the rc file",
+ section);
+ else
+ g_hash_table_insert(reg, g_ascii_strdown(section, -1), (void*)func);
+}
+
+void parse_free_token(ParseTokenType type, union ParseToken token)
+{
+ switch (type) {
+ case TOKEN_STRING:
+ g_free(token.string);
+ break;
+ case TOKEN_IDENTIFIER:
+ g_free(token.identifier);
+ break;
+ case TOKEN_REAL:
+ case TOKEN_INTEGER:
+ case TOKEN_BOOL:
+ case TOKEN_LBRACKET:
+ case TOKEN_RBRACKET:
+ case TOKEN_LBRACE:
+ case TOKEN_RBRACE:
+ case TOKEN_EQUALS:
+ case TOKEN_COMMA:
+ case TOKEN_NEWLINE:
+ break;
+ }
+}
+
+void parse_set_section(char *section)
+{
+ func = (ParseFunc)g_hash_table_lookup(reg, section);
+}
+
+void parse_token(ParseTokenType type, union ParseToken token)
+{
+ if (func != NULL)
+ func(type, token);
+}
+
+static void parse_rc_token(ParseTokenType type, union ParseToken token)
+{
+ static int got_eq = FALSE;
+ static ParseTokenType got_val = 0;
+ static char *id = NULL, *s = NULL;
+ static int i;
+ static gboolean b;
+
+ if (id == NULL) {
+ if (type == TOKEN_IDENTIFIER) {
+ id = token.identifier;
+ return;
+ } else {
+ yyerror("syntax error");
+ }
+ } else if (!got_eq) {
+ if (type == TOKEN_EQUALS) {
+ got_eq = TRUE;
+ return;
+ } else {
+ yyerror("syntax error");
+ }
+ } else if (!got_val) {
+ if (type == TOKEN_STRING) {
+ s = token.string;
+ got_val = type;
+ return;
+ } else if (type == TOKEN_BOOL) {
+ b = token.bool;
+ got_val = type;
+ return;
+ } else if (type == TOKEN_INTEGER) {
+ i = token.integer;
+ got_val = type;
+ return;
+ } else
+ yyerror("syntax error");
+ } else if (type != TOKEN_NEWLINE) {
+ yyerror("syntax error");
+ } else {
+ ConfigValue v;
+
+ switch (got_val) {
+ case TOKEN_STRING:
+ v.string = s;
+ if (!config_set(id, Config_String, v))
+ yyerror("invalid value type");
+ break;
+ case TOKEN_BOOL:
+ v.bool = b;
+ if (!config_set(id, Config_Bool, v))
+ yyerror("invalid value type");
+ break;
+ case TOKEN_INTEGER:
+ v.integer = i;
+ if (!config_set(id, Config_Integer, v))
+ yyerror("invalid value type");
+ break;
+ default:
+ g_assert_not_reached(); /* unhandled type got parsed */
+ }
+ }
+
+ g_free(id);
+ g_free(s);
+ id = s = NULL;
+ got_eq = FALSE;
+ got_val = 0;
+ parse_free_token(type, token);
+}
--- /dev/null
+#ifndef __parse_h
+#define __parse_h
+
+#include <glib.h>
+#include "y.tab.h"
+
+typedef enum {
+ TOKEN_REAL = REAL,
+ TOKEN_INTEGER = INTEGER,
+ TOKEN_STRING = STRING,
+ TOKEN_IDENTIFIER = IDENTIFIER,
+ TOKEN_BOOL = BOOL,
+ TOKEN_LBRACKET = '(',
+ TOKEN_RBRACKET = ')',
+ TOKEN_LBRACE = '{',
+ TOKEN_RBRACE = '}',
+ TOKEN_EQUALS = '=',
+ TOKEN_COMMA = ',',
+ TOKEN_NEWLINE = '\n'
+} ParseTokenType;
+
+typedef void (*ParseFunc)(ParseTokenType type, union ParseToken token);
+
+void parse_startup();
+void parse_shutdown();
+
+/* Parse the RC file
+ found in parse.yacc
+*/
+void parse_rc();
+
+void parse_reg_section(char *section, ParseFunc func);
+
+
+/* Free a parsed token's allocated memory */
+void parse_free_token(ParseTokenType type, union ParseToken token);
+
+/* Display an error message while parsing.
+ found in parse.yacc */
+void yyerror(char *err);
+
+#endif
--- /dev/null
+%{
+#include <glib.h>
+#include "y.tab.h"
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+extern void yyerror(char *err);
+
+int yylineno = 1;
+%}
+
+real [-0-9][0-9]*\.[0-9]+
+integer [-0-9][0-9]*
+string \"[^"\n]*\"
+identifier [a-zA-Z][.a-zA-Z0-9]*
+bool ([tT][rR][uU][eE]|[fF][aA][lL][sS][eE]|[yY][eE][sS]|[nN][oO]|[oO][nN]|[oO][fF][fF])
+
+%%
+
+^[ \t]*#.*\n /* comment */ { ++yylineno; }
+^[ \t]*#.* /* comment */
+^[ \t]*\n /* empty lines */ { ++yylineno; }
+[ \t] /* whitespace */
+{real} { yylval.real = atof(yytext); return REAL; }
+{integer} { yylval.integer = atoi(yytext); return INTEGER; }
+{string} { yylval.string = g_strdup(yytext+1); /* drop the left quote */
+ if (yylval.string[yyleng-2] != '"')
+ yyerror("improperly terminated string on line %d");
+ else
+ yylval.string[yyleng-2] = '\0';
+ return STRING;
+ }
+{bool} { yylval.bool = (!g_ascii_strcasecmp("true", yytext) ||
+ !g_ascii_strcasecmp("yes", yytext) ||
+ !g_ascii_strcasecmp("on", yytext));
+ return BOOL;
+ }
+{identifier} { yylval.identifier = g_strdup(yytext); return IDENTIFIER; }
+[{}()\[\]=,] { yylval.character = *yytext; return *yytext; }
+\n { yylval.character = *yytext; ++yylineno; return *yytext; }
+. { return INVALID; }
+
+%%
+
+int yywrap() {
+ return 1;
+}
--- /dev/null
+%{
+#include "parse.h"
+#ifdef HAVE_STDIO_H
+# include <stdio.h>
+#endif
+
+extern int yylex();
+
+extern int yylineno;
+extern FILE *yyin;
+
+static char *path;
+static union ParseToken t;
+
+/* in parse.c */
+void parse_token(ParseTokenType type, union ParseToken token);
+void parse_set_section(char *section);
+%}
+
+%union ParseToken {
+ float real;
+ int integer;
+ char *string;
+ char *identifier;
+ gboolean bool;
+ char character;
+}
+
+%token <real> REAL
+%token <integer> INTEGER
+%token <string> STRING
+%token <identifier> IDENTIFIER
+%token <bool> BOOL
+%token <character> '('
+%token <character> ')'
+%token <character> '{'
+%token <character> '}'
+%token <character> '='
+%token <character> ','
+%token <character> '\n'
+%token INVALID
+
+%%
+
+sections:
+ | sections '[' IDENTIFIER ']' { parse_set_section($3); } '\n' lines
+ ;
+
+lines:
+ | lines tokens '\n' { t.character = $3; parse_token(TOKEN_NEWLINE, t); }
+ ;
+
+tokens:
+ tokens token
+ | token
+ ;
+
+token:
+ REAL { t.real = $1; parse_token(TOKEN_REAL, t); }
+ | INTEGER { t.integer = $1; parse_token(TOKEN_INTEGER, t); }
+ | STRING { t.string = $1; parse_token(TOKEN_STRING, t); }
+ | IDENTIFIER { t.identifier = $1; parse_token(TOKEN_IDENTIFIER, t); }
+ | BOOL { t.bool = $1; parse_token(TOKEN_BOOL, t); }
+ | '(' { t.character = $1; parse_token(TOKEN_LBRACKET, t); }
+ | ')' { t.character = $1; parse_token(TOKEN_RBRACKET, t); }
+ | '{' { t.character = $1; parse_token(TOKEN_LBRACE, t); }
+ | '}' { t.character = $1; parse_token(TOKEN_RBRACE, t); }
+ | '=' { t.character = $1; parse_token(TOKEN_EQUALS, t); }
+ | ',' { t.character = $1; parse_token(TOKEN_COMMA, t); }
+ ;
+
+%%
+
+void yyerror(char *err) {
+ g_message("%s:%d: %s", path, yylineno, err);
+}
+
+void parse_rc()
+{
+ /* try the user's rc */
+ path = g_build_filename(g_get_home_dir(), ".openbox", "rc3", NULL);
+ if ((yyin = fopen(path, "r")) == NULL) {
+ g_free(path);
+ /* try the system wide rc */
+ path = g_build_filename(RCDIR, "rc3", NULL);
+ if ((yyin = fopen(path, "r")) == NULL) {
+ g_warning("No rc2 file found!");
+ g_free(path);
+ return;
+ }
+ }
+
+ yylineno = 1;
+
+ yyparse();
+
+ g_free(path);
+}