xF: add date change marker
Also rename and reorganise attributes to match xC better.
This commit is contained in:
@@ -303,38 +303,39 @@ struct binding
|
||||
|
||||
// --- Display model -----------------------------------------------------------
|
||||
|
||||
#define ATTRIBUTE_TABLE(XX) \
|
||||
XX (NORMAL, -1, -1, 0) \
|
||||
XX (CHROME, -1, 255, A_UNDERLINE) \
|
||||
XX (TIME, 250, 255, A_DIM) \
|
||||
XX (CURRENT, 0, 255, 0) \
|
||||
XX (ACTIVITY, -1, -1, A_BOLD) \
|
||||
XX (HIGHLIGHT, 202, -1, A_BOLD) \
|
||||
XX (UNREAD, 202, -1, 0) \
|
||||
XX (JOIN, 108, -1, 0) \
|
||||
XX (PART, 138, -1, 0) \
|
||||
XX (ERROR, 1, -1, A_BOLD) \
|
||||
XX (ACTION, 1, -1, 0) \
|
||||
XX (LEAKED, 248, -1, 0) \
|
||||
XX (LINK, 21, -1, A_UNDERLINE) \
|
||||
XX (PROMPT, -1, 255, A_BOLD) \
|
||||
XX (SCROLLBAR, 250, -1, 0) \
|
||||
XX (IRC_0, 16, -1, 0) \
|
||||
XX (IRC_1, 124, -1, 0) \
|
||||
XX (IRC_2, 34, -1, 0) \
|
||||
XX (IRC_3, 142, -1, 0) \
|
||||
XX (IRC_4, 19, -1, 0) \
|
||||
XX (IRC_5, 127, -1, 0) \
|
||||
XX (IRC_6, 37, -1, 0) \
|
||||
XX (IRC_7, 252, -1, 0) \
|
||||
XX (IRC_8, 245, -1, 0) \
|
||||
XX (IRC_9, 196, -1, 0) \
|
||||
XX (IRC_10, 46, -1, 0) \
|
||||
XX (IRC_11, 226, -1, 0) \
|
||||
XX (IRC_12, 21, -1, 0) \
|
||||
XX (IRC_13, 201, -1, 0) \
|
||||
XX (IRC_14, 51, -1, 0) \
|
||||
XX (IRC_15, 231, -1, 0)
|
||||
#define ATTRIBUTE_TABLE(XX) \
|
||||
XX (NORMAL, -1, -1, 0) \
|
||||
XX (CHROME, -1, 255, A_UNDERLINE) \
|
||||
XX (SCROLLBAR, 250, -1, 0) \
|
||||
XX (PROMPT, -1, 255, A_BOLD) \
|
||||
XX (DATE_CHANGE, -1, -1, A_BOLD) \
|
||||
XX (READ_MARKER, 202, -1, 0) \
|
||||
XX (BUFFER_CURRENT, 0, 255, 0) \
|
||||
XX (BUFFER_ACTIVITY, -1, -1, A_BOLD) \
|
||||
XX (BUFFER_HIGHLIGHT, 202, -1, A_BOLD) \
|
||||
XX (ERROR, 1, -1, A_BOLD) \
|
||||
XX (EXTERNAL, 248, -1, 0) \
|
||||
XX (TIMESTAMP, 250, 255, A_DIM) \
|
||||
XX (ACTION, 1, -1, 0) \
|
||||
XX (LINK, 21, -1, A_UNDERLINE) \
|
||||
XX (JOIN, 108, -1, 0) \
|
||||
XX (PART, 138, -1, 0) \
|
||||
XX (IRC_0, 16, -1, 0) \
|
||||
XX (IRC_1, 124, -1, 0) \
|
||||
XX (IRC_2, 34, -1, 0) \
|
||||
XX (IRC_3, 142, -1, 0) \
|
||||
XX (IRC_4, 19, -1, 0) \
|
||||
XX (IRC_5, 127, -1, 0) \
|
||||
XX (IRC_6, 37, -1, 0) \
|
||||
XX (IRC_7, 252, -1, 0) \
|
||||
XX (IRC_8, 245, -1, 0) \
|
||||
XX (IRC_9, 196, -1, 0) \
|
||||
XX (IRC_10, 46, -1, 0) \
|
||||
XX (IRC_11, 226, -1, 0) \
|
||||
XX (IRC_12, 21, -1, 0) \
|
||||
XX (IRC_13, 201, -1, 0) \
|
||||
XX (IRC_14, 51, -1, 0) \
|
||||
XX (IRC_15, 231, -1, 0)
|
||||
|
||||
enum app_attribute
|
||||
{
|
||||
@@ -368,7 +369,7 @@ app_init_line_item_colors (void)
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
enum { UNREAD_MARKER_HEIGHT = 1 };
|
||||
enum { READ_MARKER_HEIGHT = 1 };
|
||||
|
||||
enum app_widget_id
|
||||
{
|
||||
@@ -478,6 +479,8 @@ static struct
|
||||
int transcript_width; ///< Width used by buffer line wrapping
|
||||
int transcript_height; ///< Current buffer content height
|
||||
|
||||
struct poller_timer date_change_event;
|
||||
|
||||
struct line_editor editor; ///< Message editor
|
||||
char *editor_running_for; ///< Buffer name being edited externally
|
||||
char *editor_filename; ///< File being edited by the user
|
||||
@@ -554,7 +557,7 @@ app_measure_buffer_line (struct buffer_line *line, const struct str *text)
|
||||
line->wraps = xcalloc (MAX (line->chunks_len, 1), sizeof *line->wraps);
|
||||
|
||||
size_t chunk_start = 0, i = 0;
|
||||
chtype base = line->leaked ? g_attrs[ATTRIBUTE_LEAKED].attrs : 0;
|
||||
chtype base = line->leaked ? g_attrs[ATTRIBUTE_EXTERNAL].attrs : 0;
|
||||
while (chunk_start < text->len)
|
||||
{
|
||||
size_t chunk_end = chunk_start +
|
||||
@@ -650,7 +653,7 @@ app_recheck_current_highlight (void)
|
||||
}
|
||||
|
||||
static bool
|
||||
buffer_has_unread_marker (const struct buffer *self)
|
||||
buffer_has_read_marker (const struct buffer *self)
|
||||
{
|
||||
return self->lines
|
||||
&& (self->new_messages || self->new_unimportant_messages);
|
||||
@@ -692,11 +695,11 @@ app_push_buffer_line (struct buffer *b,
|
||||
&& (b == current || leak_to_active);
|
||||
bool visible = !g.log.visible && !current->scroll_offset
|
||||
&& (b == current || leak_to_active);
|
||||
bool current_had_unread = buffer_has_unread_marker (current);
|
||||
bool current_had_unread = buffer_has_read_marker (current);
|
||||
// TODO: Also discount an unmapped/minimized window once XUI exposes that.
|
||||
|
||||
LIST_APPEND_WITH_TAIL (b->lines, b->lines_tail, line);
|
||||
if (!(visible || leak_to_active) || buffer_has_unread_marker (b))
|
||||
if (!(visible || leak_to_active) || buffer_has_read_marker (b))
|
||||
{
|
||||
if (line->is_unimportant || leak_to_active)
|
||||
b->new_unimportant_messages++;
|
||||
@@ -709,7 +712,7 @@ app_push_buffer_line (struct buffer *b,
|
||||
leaked->leaked = true;
|
||||
buffer_line_finalize (leaked);
|
||||
LIST_APPEND_WITH_TAIL (current->lines, current->lines_tail, leaked);
|
||||
if (!visible || buffer_has_unread_marker (current))
|
||||
if (!visible || buffer_has_read_marker (current))
|
||||
{
|
||||
if (leaked->is_unimportant)
|
||||
current->new_unimportant_messages++;
|
||||
@@ -723,8 +726,8 @@ app_push_buffer_line (struct buffer *b,
|
||||
if (displayed)
|
||||
current->scroll_offset += app_buffer_line_height
|
||||
(leak_to_active ? current->lines_tail : line);
|
||||
if (!current_had_unread && buffer_has_unread_marker (current))
|
||||
current->scroll_offset += UNREAD_MARKER_HEIGHT;
|
||||
if (!current_had_unread && buffer_has_read_marker (current))
|
||||
current->scroll_offset += READ_MARKER_HEIGHT;
|
||||
}
|
||||
|
||||
buffer_pop_excess_lines (b);
|
||||
@@ -802,6 +805,53 @@ app_log_handler (void *user_data, const char *quote, const char *fmt,
|
||||
in_processing = false;
|
||||
}
|
||||
|
||||
// --- Date change -------------------------------------------------------------
|
||||
|
||||
static bool
|
||||
app_date_changed (time_t when, struct tm *last, bool *have_last)
|
||||
{
|
||||
struct tm current = {};
|
||||
if (!localtime_r (&when, ¤t))
|
||||
return false;
|
||||
|
||||
bool changed = !*have_last
|
||||
|| last->tm_year != current.tm_year
|
||||
|| last->tm_mon != current.tm_mon
|
||||
|| last->tm_mday != current.tm_mday;
|
||||
|
||||
*last = current;
|
||||
*have_last = true;
|
||||
return changed;
|
||||
}
|
||||
|
||||
static void
|
||||
app_rearm_date_change_timer (void)
|
||||
{
|
||||
struct tm tm_ = {};
|
||||
const time_t now = time (NULL);
|
||||
if (!localtime_r (&now, &tm_))
|
||||
return;
|
||||
|
||||
tm_.tm_sec = tm_.tm_min = tm_.tm_hour = 0;
|
||||
tm_.tm_mday++;
|
||||
tm_.tm_isdst = -1;
|
||||
|
||||
const time_t midnight = mktime (&tm_);
|
||||
if (midnight == (time_t) -1 || midnight <= now)
|
||||
return;
|
||||
|
||||
int64_t delay = (int64_t) (midnight - now) * 1000 + 1;
|
||||
poller_timer_set (&g.date_change_event, MIN (delay, INT_MAX));
|
||||
}
|
||||
|
||||
static void
|
||||
app_on_date_change_timer (void *user_data)
|
||||
{
|
||||
(void) user_data;
|
||||
xui_invalidate ();
|
||||
app_rearm_date_change_timer ();
|
||||
}
|
||||
|
||||
// --- Editor ------------------------------------------------------------------
|
||||
|
||||
static void
|
||||
@@ -2480,11 +2530,11 @@ app_make_buffer_row (struct buffer *b, int index)
|
||||
{
|
||||
enum app_attribute attribute = ATTRIBUTE_NORMAL;
|
||||
if (b == g.buffer_current)
|
||||
attribute = ATTRIBUTE_CURRENT;
|
||||
attribute = ATTRIBUTE_BUFFER_CURRENT;
|
||||
else if (b->highlighted)
|
||||
attribute = ATTRIBUTE_HIGHLIGHT;
|
||||
attribute = ATTRIBUTE_BUFFER_HIGHLIGHT;
|
||||
else if (b->new_messages)
|
||||
attribute = ATTRIBUTE_ACTIVITY;
|
||||
attribute = ATTRIBUTE_BUFFER_ACTIVITY;
|
||||
|
||||
char *label = b != g.buffer_current && b->new_messages
|
||||
? xstrdup_printf ("%s (%u)", b->buffer_name, b->new_messages)
|
||||
@@ -2583,12 +2633,37 @@ static struct widget *
|
||||
app_make_mark (const struct buffer_line *line)
|
||||
{
|
||||
chtype attrs = line->leaked
|
||||
? g_attrs[ATTRIBUTE_LEAKED].attrs
|
||||
? g_attrs[ATTRIBUTE_EXTERNAL].attrs
|
||||
: g_attrs[app_mark_attribute (line->rendition)].attrs;
|
||||
return app_label_attrs (attrs, XUI_ATTR_MONOSPACE,
|
||||
app_line_mark (line->rendition), false);
|
||||
}
|
||||
|
||||
static const char *
|
||||
app_format_date (time_t when)
|
||||
{
|
||||
static char date[64];
|
||||
struct tm tm = {};
|
||||
|
||||
*date = '\0';
|
||||
if (localtime_r (&when, &tm))
|
||||
strftime (date, sizeof date, "%x", &tm);
|
||||
return date;
|
||||
}
|
||||
|
||||
static struct widget *
|
||||
app_make_date_change_marker (time_t when)
|
||||
{
|
||||
struct layout row = {};
|
||||
app_push (&row, app_padding (ATTRIBUTE_NORMAL, 0.25));
|
||||
app_push (&row, app_label (ATTRIBUTE_DATE_CHANGE,
|
||||
app_format_date (when), true));
|
||||
app_push (&row, app_padding (ATTRIBUTE_NORMAL, 0.25));
|
||||
struct widget *marker = xui_hbox (row.head);
|
||||
marker->height = g_xui.vunit;
|
||||
return marker;
|
||||
}
|
||||
|
||||
static const char *
|
||||
app_format_line_timestamp (const struct buffer_line *line)
|
||||
{
|
||||
@@ -2605,14 +2680,15 @@ app_format_line_timestamp (const struct buffer_line *line)
|
||||
static struct widget *
|
||||
app_make_line_timestamp (const struct buffer_line *line)
|
||||
{
|
||||
return app_label (ATTRIBUTE_TIME, app_format_line_timestamp (line), false);
|
||||
return app_label (ATTRIBUTE_TIMESTAMP, app_format_line_timestamp (line),
|
||||
false);
|
||||
}
|
||||
|
||||
static void
|
||||
app_wrap_buffer_line_to_width (struct buffer_line *line, int width)
|
||||
{
|
||||
struct widget *timestamp = app_make_line_timestamp (line);
|
||||
struct widget *time_padding = app_padding (ATTRIBUTE_TIME, 0.25);
|
||||
struct widget *time_padding = app_padding (ATTRIBUTE_TIMESTAMP, 0.25);
|
||||
struct widget *mark = app_make_mark (line);
|
||||
struct widget *padding = app_padding (ATTRIBUTE_NORMAL, 0.25);
|
||||
|
||||
@@ -2659,7 +2735,7 @@ app_make_line (struct buffer_line *line)
|
||||
// XXX: We still use too much ATTRIBUTE_NORMAL, which basically names
|
||||
// the <-1, -1> colour pair. We don't use it with line items as a default
|
||||
// because then links attribute application would get blocked.
|
||||
chtype base = line->leaked ? g_attrs[ATTRIBUTE_LEAKED].attrs : 0;
|
||||
chtype base = line->leaked ? g_attrs[ATTRIBUTE_EXTERNAL].attrs : 0;
|
||||
struct layout rows = {};
|
||||
for (size_t i = 0; i < line->wraps_len; i++)
|
||||
{
|
||||
@@ -2675,46 +2751,46 @@ app_make_line (struct buffer_line *line)
|
||||
|
||||
struct layout timestamps = {};
|
||||
app_push (×tamps, app_make_line_timestamp (line));
|
||||
struct widget *filler = app_label (ATTRIBUTE_TIME, "", false);
|
||||
struct widget *filler = app_label (ATTRIBUTE_TIMESTAMP, "", false);
|
||||
filler->height = -1;
|
||||
app_push (×tamps, filler);
|
||||
|
||||
struct layout columns = {};
|
||||
app_push (&columns, app_padding (ATTRIBUTE_TIME, 0.25));
|
||||
app_push (&columns, app_padding (ATTRIBUTE_TIMESTAMP, 0.25));
|
||||
app_push (&columns, xui_vbox (timestamps.head));
|
||||
app_push (&columns, app_padding (ATTRIBUTE_TIME, 0.25));
|
||||
app_push (&columns, app_padding (ATTRIBUTE_TIMESTAMP, 0.25));
|
||||
app_push (&columns, content);
|
||||
return xui_hbox (columns.head);
|
||||
}
|
||||
|
||||
static void
|
||||
tui_render_unread_marker (struct widget *self)
|
||||
tui_render_read_marker (struct widget *self)
|
||||
{
|
||||
struct row_buffer buffer = row_buffer_make ();
|
||||
for (int i = 0; i < self->width; i++)
|
||||
row_buffer_append_c (&buffer, '-',
|
||||
i < 8 ? g_attrs[ATTRIBUTE_TIME].attrs : self->attrs);
|
||||
i < 8 ? g_attrs[ATTRIBUTE_TIMESTAMP].attrs : self->attrs);
|
||||
tui_flush_buffer (self, 0, &buffer);
|
||||
}
|
||||
|
||||
static struct widget *
|
||||
app_make_unread_marker (void)
|
||||
app_make_read_marker (void)
|
||||
{
|
||||
if (g_xui.ui == &tui_ui)
|
||||
{
|
||||
struct widget *marker = xcalloc (1, sizeof *marker + 1);
|
||||
marker->on_render = tui_render_unread_marker;
|
||||
marker->attrs = g_attrs[ATTRIBUTE_UNREAD].attrs;
|
||||
marker->on_render = tui_render_read_marker;
|
||||
marker->attrs = g_attrs[ATTRIBUTE_READ_MARKER].attrs;
|
||||
marker->width = -1;
|
||||
marker->height = UNREAD_MARKER_HEIGHT;
|
||||
marker->height = READ_MARKER_HEIGHT;
|
||||
return marker;
|
||||
}
|
||||
|
||||
// Reversing swaps the orange foreground into the padding background.
|
||||
struct widget *marker = g_xui.ui->padding
|
||||
(g_attrs[ATTRIBUTE_UNREAD].attrs | A_REVERSE, 0, 0);
|
||||
(g_attrs[ATTRIBUTE_READ_MARKER].attrs | A_REVERSE, 0, 0);
|
||||
marker->width = -1;
|
||||
marker->height = UNREAD_MARKER_HEIGHT;
|
||||
marker->height = READ_MARKER_HEIGHT;
|
||||
return marker;
|
||||
}
|
||||
|
||||
@@ -2793,7 +2869,7 @@ app_append_log_rows (struct layout *rows)
|
||||
}
|
||||
|
||||
static int
|
||||
app_append_buffer_rows (struct layout *rows)
|
||||
app_append_buffer_rows (struct layout *rows, time_t now)
|
||||
{
|
||||
struct buffer *b = g.buffer_current;
|
||||
if (!b)
|
||||
@@ -2806,28 +2882,39 @@ app_append_buffer_rows (struct layout *rows)
|
||||
marker_before = line;
|
||||
|
||||
struct transcript_slice slice = app_make_transcript_slice ();
|
||||
struct tm last_date = {};
|
||||
bool have_last_date = false;
|
||||
LIST_FOR_EACH (struct buffer_line, line, b->lines)
|
||||
{
|
||||
if (line == marker_before
|
||||
&& app_transcript_row_is_visible (&slice, UNREAD_MARKER_HEIGHT))
|
||||
app_push (rows, app_make_unread_marker ());
|
||||
if (buffer_line_is_visible (b, line)
|
||||
&& app_transcript_row_is_visible (&slice,
|
||||
app_wrapped_line_height (line)))
|
||||
&& app_transcript_row_is_visible (&slice, READ_MARKER_HEIGHT))
|
||||
app_push (rows, app_make_read_marker ());
|
||||
if (!buffer_line_is_visible (b, line))
|
||||
continue;
|
||||
|
||||
time_t when = line->when / 1000;
|
||||
if (app_date_changed (when, &last_date, &have_last_date)
|
||||
&& app_transcript_row_is_visible (&slice, g_xui.vunit))
|
||||
app_push (rows, app_make_date_change_marker (when));
|
||||
if (app_transcript_row_is_visible
|
||||
(&slice, app_wrapped_line_height (line)))
|
||||
app_push (rows, app_make_line (line));
|
||||
}
|
||||
if (have_last_date && app_date_changed (now, &last_date, &have_last_date)
|
||||
&& app_transcript_row_is_visible (&slice, g_xui.vunit))
|
||||
app_push (rows, app_make_date_change_marker (now));
|
||||
return app_transcript_slice_offset (&slice);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
static struct widget *
|
||||
app_make_transcript (void)
|
||||
app_make_transcript (time_t now)
|
||||
{
|
||||
struct layout rows = {};
|
||||
int offset = g.log.visible
|
||||
? app_append_log_rows (&rows)
|
||||
: app_append_buffer_rows (&rows);
|
||||
: app_append_buffer_rows (&rows, now);
|
||||
|
||||
struct widget *transcript = xui_vbox (rows.head);
|
||||
transcript->on_allocated = app_on_viewport_allocated;
|
||||
@@ -2838,7 +2925,7 @@ app_make_transcript (void)
|
||||
}
|
||||
|
||||
static int
|
||||
app_transcript_height_at (int width)
|
||||
app_transcript_height_at (int width, time_t now)
|
||||
{
|
||||
uint64_t height = 0;
|
||||
if (g.log.visible)
|
||||
@@ -2855,14 +2942,22 @@ app_transcript_height_at (int width)
|
||||
if (!buffer)
|
||||
return 0;
|
||||
|
||||
height = buffer_has_unread_marker (buffer) ? UNREAD_MARKER_HEIGHT : 0;
|
||||
height = buffer_has_read_marker (buffer) ? READ_MARKER_HEIGHT : 0;
|
||||
|
||||
struct tm last_date = {};
|
||||
bool have_last_date = false;
|
||||
LIST_FOR_EACH (struct buffer_line, line, buffer->lines)
|
||||
{
|
||||
if (!buffer_line_is_visible (buffer, line))
|
||||
continue;
|
||||
|
||||
if (app_date_changed (line->when / 1000, &last_date, &have_last_date))
|
||||
height += g_xui.vunit;
|
||||
app_wrap_buffer_line_to_width (line, width);
|
||||
height += app_wrapped_line_height (line);
|
||||
}
|
||||
if (have_last_date && app_date_changed (now, &last_date, &have_last_date))
|
||||
height += g_xui.vunit;
|
||||
return MIN ((uint64_t) INT_MAX, height);
|
||||
}
|
||||
|
||||
@@ -2873,19 +2968,22 @@ app_make_middle (void)
|
||||
struct widget *buffer_list =
|
||||
app_push (&columns, app_make_buffer_list ());
|
||||
|
||||
// Let's not race against time.
|
||||
time_t now = time (NULL);
|
||||
|
||||
// XXX: We know when something changes, so we could cache this.
|
||||
int width = MAX (0, g_xui.width - buffer_list->width);
|
||||
int height = app_transcript_height_at (width);
|
||||
int height = app_transcript_height_at (width, now);
|
||||
if (height > app_viewport_height ())
|
||||
{
|
||||
width = MAX (0, width - app_scrollbar_width ());
|
||||
height = app_transcript_height_at (width);
|
||||
height = app_transcript_height_at (width, now);
|
||||
}
|
||||
g.transcript_width = width;
|
||||
g.transcript_height = height;
|
||||
|
||||
struct layout viewport = {};
|
||||
app_push (&viewport, app_make_transcript ());
|
||||
app_push (&viewport, app_make_transcript (now));
|
||||
struct widget *scrollbar = app_make_scrollbar (WIDGET_TRANSCRIPT_SCROLLBAR);
|
||||
if (scrollbar)
|
||||
app_push (&viewport, scrollbar);
|
||||
@@ -3432,14 +3530,26 @@ app_external_editor_make_transcript (void)
|
||||
for (size_t i = 0; i < g.log.lines_len; i++)
|
||||
app_external_editor_append_line
|
||||
(&transcript, g.log.lines[i], false);
|
||||
return transcript;
|
||||
}
|
||||
else
|
||||
|
||||
struct buffer *buffer = g.buffer_current;
|
||||
struct tm last_date = {};
|
||||
bool have_last_date = false;
|
||||
LIST_FOR_EACH (struct buffer_line, line, buffer->lines)
|
||||
{
|
||||
struct buffer *buffer = g.buffer_current;
|
||||
LIST_FOR_EACH (struct buffer_line, line, buffer->lines)
|
||||
if (buffer_line_is_visible (buffer, line))
|
||||
app_external_editor_append_line (&transcript, line, true);
|
||||
if (!buffer_line_is_visible (buffer, line))
|
||||
continue;
|
||||
|
||||
time_t when = line->when / 1000;
|
||||
if (app_date_changed (when, &last_date, &have_last_date))
|
||||
str_append_printf (&transcript, "%s\n", app_format_date (when));
|
||||
app_external_editor_append_line (&transcript, line, true);
|
||||
}
|
||||
|
||||
time_t now = time (NULL);
|
||||
if (have_last_date && app_date_changed (now, &last_date, &have_last_date))
|
||||
str_append_printf (&transcript, "%s\n", app_format_date (now));
|
||||
return transcript;
|
||||
}
|
||||
|
||||
@@ -4140,6 +4250,11 @@ app_init_context (const char *host, const char *port)
|
||||
{
|
||||
poller_init (&g.poller);
|
||||
app_editor_init ();
|
||||
|
||||
g.date_change_event = poller_timer_make (&g.poller);
|
||||
g.date_change_event.dispatcher = app_on_date_change_timer;
|
||||
app_rearm_date_change_timer ();
|
||||
|
||||
struct error *e = NULL;
|
||||
if (!(g.link_re = regex_compile (g_link_pattern, REG_EXTENDED, &e)))
|
||||
exit_fatal ("Failed to compile link regex: %s", e->message);
|
||||
@@ -4248,7 +4363,9 @@ main (int argc, char *argv[])
|
||||
exit_fatal ("missing port number/service name");
|
||||
|
||||
if (!setlocale (LC_CTYPE, ""))
|
||||
print_warning ("failed to set the locale");
|
||||
print_warning ("failed to set the character locale");
|
||||
if (!setlocale (LC_TIME, ""))
|
||||
print_warning ("failed to set the time locale");
|
||||
|
||||
app_init_context (host, port);
|
||||
free (address);
|
||||
|
||||
Reference in New Issue
Block a user