degesch: start using "on_change" notifications

Terminal attributes can be changed on the fly now.
This commit is contained in:
Přemysl Eric Janouch 2015-07-05 15:57:53 +02:00
parent 34c1df5171
commit 3a922c3c1a
2 changed files with 68 additions and 27 deletions

View File

@ -1911,8 +1911,6 @@ config_schema_initialize_item (struct config_schema *schema,
item->schema = schema; item->schema = schema;
item->user_data = user_data; item->user_data = user_data;
if (schema->on_change)
schema->on_change (item);
} }
static void static void
@ -1924,6 +1922,22 @@ config_schema_apply_to_object (struct config_schema *schema_array,
config_schema_initialize_item (schema_array++, object, user_data); config_schema_initialize_item (schema_array++, object, user_data);
} }
static void
config_schema_call_changed (struct config_item_ *item)
{
if (item->type == CONFIG_ITEM_OBJECT)
{
struct str_map_iter iter;
str_map_iter_init (&iter, &item->value.object);
struct config_item_ *child;
while ((child = str_map_iter_next (&iter)))
config_schema_call_changed (child);
}
else if (item->schema && item->schema->on_change)
item->schema->on_change (item);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// XXX: this doesn't necessarily have to be well designed at all // XXX: this doesn't necessarily have to be well designed at all

View File

@ -1288,6 +1288,8 @@ server_destroy (void *self)
struct app_context struct app_context
{ {
char *attrs_defaults[ATTR_COUNT]; ///< Default terminal attributes
// Configuration: // Configuration:
struct config config; ///< Program configuration struct config config; ///< Program configuration
@ -1380,7 +1382,10 @@ app_context_free (struct app_context *self)
{ {
config_free (&self->config); config_free (&self->config);
for (size_t i = 0; i < ATTR_COUNT; i++) for (size_t i = 0; i < ATTR_COUNT; i++)
{
free (self->attrs_defaults[i]);
free (self->attrs[i]); free (self->attrs[i]);
}
LIST_FOR_EACH (struct buffer, iter, self->buffers) LIST_FOR_EACH (struct buffer, iter, self->buffers)
{ {
@ -1411,7 +1416,8 @@ static bool irc_is_this_us (struct server *s, const char *prefix);
// --- Configuration ----------------------------------------------------------- // --- Configuration -----------------------------------------------------------
// TODO: eventually add "on_change" callbacks // TODO: "on_change" callbacks for everything
static void on_config_attribute_change (struct config_item_ *item);
static bool static bool
config_validate_nonjunk_string config_validate_nonjunk_string
@ -1565,7 +1571,8 @@ static struct config_schema g_config_behaviour[] =
static struct config_schema g_config_attributes[] = static struct config_schema g_config_attributes[] =
{ {
#define XX(x, y, z) { .name = y, .comment = z, .type = CONFIG_ITEM_STRING }, #define XX(x, y, z) { .name = y, .comment = z, .type = CONFIG_ITEM_STRING, \
.on_change = on_config_attribute_change },
ATTR_TABLE (XX) ATTR_TABLE (XX)
#undef XX #undef XX
{} {}
@ -1862,7 +1869,7 @@ log_message_attributed (void *user_data, const char *quote, const char *fmt,
} }
static void static void
init_attribute (struct app_context *ctx, int id, const char *default_) on_config_attribute_change (struct config_item_ *item)
{ {
static const char *table[ATTR_COUNT] = static const char *table[ATTR_COUNT] =
{ {
@ -1871,19 +1878,22 @@ init_attribute (struct app_context *ctx, int id, const char *default_)
#undef XX #undef XX
}; };
const char *user = get_config_string (ctx->config.root, table[id]); struct app_context *ctx = item->user_data;
if (user) for (int id = 0; id < ATTR_COUNT; id++)
ctx->attrs[id] = xstrdup (user); {
else const char *user = get_config_string (ctx->config.root, table[id]);
ctx->attrs[id] = xstrdup (default_); free (ctx->attrs[id]);
ctx->attrs[id] = xstrdup (user ? user : ctx->attrs_defaults[id]);
}
} }
static void static void
init_colors (struct app_context *ctx) init_colors (struct app_context *ctx)
{ {
bool have_ti = init_terminal (); bool have_ti = init_terminal ();
char **defaults = ctx->attrs_defaults;
#define INIT_ATTR(id, ti) init_attribute (ctx, ATTR_ ## id, have_ti ? (ti) : "") #define INIT_ATTR(id, ti) defaults[ATTR_ ## id] = xstrdup (have_ti ? (ti) : "")
INIT_ATTR (PROMPT, enter_bold_mode); INIT_ATTR (PROMPT, enter_bold_mode);
INIT_ATTR (RESET, exit_attribute_mode); INIT_ATTR (RESET, exit_attribute_mode);
@ -1913,6 +1923,10 @@ init_colors (struct app_context *ctx)
} }
g_log_message_real = log_message_attributed; g_log_message_real = log_message_attributed;
// Apply the default values so that we start with any formatting at all
config_schema_call_changed
(config_item_get (ctx->config.root, "attributes", NULL));
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -8343,7 +8357,7 @@ load_configuration_file (const char *filename, struct error **e)
struct error *error = NULL; struct error *error = NULL;
if (!(root = config_item_parse (data.str, data.len, false, &error))) if (!(root = config_item_parse (data.str, data.len, false, &error)))
{ {
error_set (e, "configuration parse error: %s", error->message); error_set (e, "Configuration parse error: %s", error->message);
error_free (error); error_free (error);
} }
end: end:
@ -8361,20 +8375,21 @@ load_configuration (struct app_context *ctx)
if (filename) if (filename)
root = load_configuration_file (filename, &e); root = load_configuration_file (filename, &e);
else else
print_status ("configuration file not found"); log_global_error (ctx, "Configuration file not found");
free (filename); free (filename);
if (e) if (e)
{ {
print_error ("%s", e->message); log_global_error (ctx, "#s", e->message);
error_free (e); error_free (e);
e = NULL;
} }
if (root)
config_load (&ctx->config, root ? root : config_item_object ()); {
config_item_destroy (ctx->config.root);
ctx->isolate_buffers = ctx->config.root = NULL;
get_config_boolean (ctx->config.root, "behaviour.isolate_buffers"); config_load (&ctx->config, root);
log_global_status (ctx, "Configuration loaded");
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -8408,8 +8423,8 @@ load_server_from_config (struct app_context *ctx,
buffer_add (ctx, buffer); buffer_add (ctx, buffer);
buffer_activate (ctx, buffer); buffer_activate (ctx, buffer);
// This fires any "on_change" callbacks
config_schema_apply_to_object (g_config_server, subtree, s); config_schema_apply_to_object (g_config_server, subtree, s);
config_schema_call_changed (subtree);
// XXX: is this desirable in here? I think we should do it only when // XXX: is this desirable in here? I think we should do it only when
// actually creating a new server instead of every time we load them. // actually creating a new server instead of every time we load them.
@ -8427,7 +8442,7 @@ load_server_from_config (struct app_context *ctx,
} }
static void static void
init_servers (struct app_context *ctx) load_servers (struct app_context *ctx)
{ {
struct config_item_ *servers = struct config_item_ *servers =
config_item_get (ctx->config.root, "servers", NULL); config_item_get (ctx->config.root, "servers", NULL);
@ -8713,14 +8728,26 @@ main (int argc, char *argv[])
SSL_load_error_strings (); SSL_load_error_strings ();
atexit (ERR_free_strings); atexit (ERR_free_strings);
setup_signal_handlers (); // Bootstrap configuration, so that we can access schema items at all
register_config_modules (&ctx); register_config_modules (&ctx);
config_load (&ctx.config, config_item_object ());
// The following part is a bit brittle because of interdependencies
setup_signal_handlers ();
init_colors (&ctx);
init_global_buffer (&ctx);
init_poller_events (&ctx);
load_configuration (&ctx); load_configuration (&ctx);
init_colors (&ctx); // TODO: this won't be needed after adding an "on_change" callback
init_poller_events (&ctx); ctx.isolate_buffers =
init_global_buffer (&ctx); get_config_boolean (ctx.config.root, "behaviour.isolate_buffers");
init_servers (&ctx);
// At this moment we can safely call any "on_change" callbacks
config_schema_call_changed (ctx.config.root);
// Finally, we juice the configuration for some servers to create
load_servers (&ctx);
refresh_prompt (&ctx); refresh_prompt (&ctx);
input_start (&ctx.input, argv[0]); input_start (&ctx.input, argv[0]);