degesch: start using "on_change" notifications
Terminal attributes can be changed on the fly now.
This commit is contained in:
parent
34c1df5171
commit
3a922c3c1a
18
common.c
18
common.c
|
@ -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
|
||||||
|
|
75
degesch.c
75
degesch.c
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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]);
|
const char *user = get_config_string (ctx->config.root, table[id]);
|
||||||
if (user)
|
free (ctx->attrs[id]);
|
||||||
ctx->attrs[id] = xstrdup (user);
|
ctx->attrs[id] = xstrdup (user ? user : ctx->attrs_defaults[id]);
|
||||||
else
|
}
|
||||||
ctx->attrs[id] = xstrdup (default_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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]);
|
||||||
|
|
Loading…
Reference in New Issue