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->user_data = user_data;
if (schema->on_change)
schema->on_change (item);
}
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);
}
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

View File

@ -1288,6 +1288,8 @@ server_destroy (void *self)
struct app_context
{
char *attrs_defaults[ATTR_COUNT]; ///< Default terminal attributes
// Configuration:
struct config config; ///< Program configuration
@ -1380,7 +1382,10 @@ app_context_free (struct app_context *self)
{
config_free (&self->config);
for (size_t i = 0; i < ATTR_COUNT; i++)
{
free (self->attrs_defaults[i]);
free (self->attrs[i]);
}
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 -----------------------------------------------------------
// TODO: eventually add "on_change" callbacks
// TODO: "on_change" callbacks for everything
static void on_config_attribute_change (struct config_item_ *item);
static bool
config_validate_nonjunk_string
@ -1565,7 +1571,8 @@ static struct config_schema g_config_behaviour[] =
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)
#undef XX
{}
@ -1862,7 +1869,7 @@ log_message_attributed (void *user_data, const char *quote, const char *fmt,
}
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] =
{
@ -1871,19 +1878,22 @@ init_attribute (struct app_context *ctx, int id, const char *default_)
#undef XX
};
const char *user = get_config_string (ctx->config.root, table[id]);
if (user)
ctx->attrs[id] = xstrdup (user);
else
ctx->attrs[id] = xstrdup (default_);
struct app_context *ctx = item->user_data;
for (int id = 0; id < ATTR_COUNT; id++)
{
const char *user = get_config_string (ctx->config.root, table[id]);
free (ctx->attrs[id]);
ctx->attrs[id] = xstrdup (user ? user : ctx->attrs_defaults[id]);
}
}
static void
init_colors (struct app_context *ctx)
{
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 (RESET, exit_attribute_mode);
@ -1913,6 +1923,10 @@ init_colors (struct app_context *ctx)
}
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;
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);
}
end:
@ -8361,20 +8375,21 @@ load_configuration (struct app_context *ctx)
if (filename)
root = load_configuration_file (filename, &e);
else
print_status ("configuration file not found");
log_global_error (ctx, "Configuration file not found");
free (filename);
if (e)
{
print_error ("%s", e->message);
log_global_error (ctx, "#s", e->message);
error_free (e);
e = NULL;
}
config_load (&ctx->config, root ? root : config_item_object ());
ctx->isolate_buffers =
get_config_boolean (ctx->config.root, "behaviour.isolate_buffers");
if (root)
{
config_item_destroy (ctx->config.root);
ctx->config.root = NULL;
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_activate (ctx, buffer);
// This fires any "on_change" callbacks
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
// 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
init_servers (struct app_context *ctx)
load_servers (struct app_context *ctx)
{
struct config_item_ *servers =
config_item_get (ctx->config.root, "servers", NULL);
@ -8713,14 +8728,26 @@ main (int argc, char *argv[])
SSL_load_error_strings ();
atexit (ERR_free_strings);
setup_signal_handlers ();
// Bootstrap configuration, so that we can access schema items at all
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);
init_colors (&ctx);
init_poller_events (&ctx);
init_global_buffer (&ctx);
init_servers (&ctx);
// TODO: this won't be needed after adding an "on_change" callback
ctx.isolate_buffers =
get_config_boolean (ctx.config.root, "behaviour.isolate_buffers");
// 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);
input_start (&ctx.input, argv[0]);