|
|
|
@@ -1298,6 +1298,7 @@ static struct app_context
|
|
|
|
|
|
|
|
|
|
|
|
struct poller_timer message_timer; ///< Message timeout
|
|
|
|
struct poller_timer message_timer; ///< Message timeout
|
|
|
|
char *message; ///< Message to show in the statusbar
|
|
|
|
char *message; ///< Message to show in the statusbar
|
|
|
|
|
|
|
|
char *message_detail; ///< Non-emphasized part
|
|
|
|
|
|
|
|
|
|
|
|
// Connection:
|
|
|
|
// Connection:
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1700,6 +1701,7 @@ app_free_context (void)
|
|
|
|
poller_curl_free (&g.poller_curl);
|
|
|
|
poller_curl_free (&g.poller_curl);
|
|
|
|
poller_free (&g.poller);
|
|
|
|
poller_free (&g.poller);
|
|
|
|
free (g.message);
|
|
|
|
free (g.message);
|
|
|
|
|
|
|
|
free (g.message_detail);
|
|
|
|
|
|
|
|
|
|
|
|
if (g.tk)
|
|
|
|
if (g.tk)
|
|
|
|
termo_destroy (g.tk);
|
|
|
|
termo_destroy (g.tk);
|
|
|
|
@@ -1834,7 +1836,7 @@ app_layout_song_info (void)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (album)
|
|
|
|
if (album)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
app_push (&l, g.ui->label (attrs[0], " from " + !artist));
|
|
|
|
app_push (&l, g.ui->label (attrs[0], &" from "[!artist]));
|
|
|
|
app_push (&l, g.ui->label (attrs[1], album));
|
|
|
|
app_push (&l, g.ui->label (attrs[1], album));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1980,28 +1982,17 @@ app_layout_tabs (void)
|
|
|
|
static void
|
|
|
|
static void
|
|
|
|
app_layout_header (void)
|
|
|
|
app_layout_header (void)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
if (g.client.state == MPD_CONNECTED)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct layout l = {};
|
|
|
|
struct layout lt = {};
|
|
|
|
app_push_fill (&l, g.ui->padding (APP_ATTR (NORMAL), 0, 0.125));
|
|
|
|
app_push_fill (<, g.ui->padding (APP_ATTR (NORMAL), 0, 0.125));
|
|
|
|
app_flush_layout (&l);
|
|
|
|
app_flush_layout (<);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (g.client.state)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
case MPD_CONNECTED:
|
|
|
|
|
|
|
|
app_layout_status ();
|
|
|
|
app_layout_status ();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MPD_CONNECTING:
|
|
|
|
|
|
|
|
app_layout_text ("Connecting to MPD...", APP_ATTR (NORMAL));
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MPD_DISCONNECTED:
|
|
|
|
|
|
|
|
app_layout_text ("Disconnected", APP_ATTR (NORMAL));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
struct layout lb = {};
|
|
|
|
struct layout l = {};
|
|
|
|
app_push_fill (&lb, g.ui->padding (APP_ATTR (NORMAL), 0, 0.125));
|
|
|
|
app_push_fill (&l, g.ui->padding (APP_ATTR (NORMAL), 0, 0.125));
|
|
|
|
app_flush_layout (&lb);
|
|
|
|
app_flush_layout (&l);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
app_layout_tabs ();
|
|
|
|
app_layout_tabs ();
|
|
|
|
@@ -2012,7 +2003,7 @@ app_layout_header (void)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
static int
|
|
|
|
app_visible_items (void)
|
|
|
|
app_visible_items_height (void)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct widget *list = NULL;
|
|
|
|
struct widget *list = NULL;
|
|
|
|
LIST_FOR_EACH (struct widget, w, g.widgets.head)
|
|
|
|
LIST_FOR_EACH (struct widget, w, g.widgets.head)
|
|
|
|
@@ -2022,7 +2013,13 @@ app_visible_items (void)
|
|
|
|
hard_assert (list != NULL);
|
|
|
|
hard_assert (list != NULL);
|
|
|
|
|
|
|
|
|
|
|
|
// The raw number of items that would have fit on the terminal
|
|
|
|
// The raw number of items that would have fit on the terminal
|
|
|
|
return MAX (0, list->height / g.ui_vunit);
|
|
|
|
return MAX (0, list->height);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
|
|
|
app_visible_items (void)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return app_visible_items_height () / g.ui_vunit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Figure out scrollbar appearance. @a s is the minimal slider length as well
|
|
|
|
/// Figure out scrollbar appearance. @a s is the minimal slider length as well
|
|
|
|
@@ -2030,7 +2027,7 @@ app_visible_items (void)
|
|
|
|
struct scrollbar { long length, start; }
|
|
|
|
struct scrollbar { long length, start; }
|
|
|
|
app_compute_scrollbar (struct tab *tab, long visible, long s)
|
|
|
|
app_compute_scrollbar (struct tab *tab, long visible, long s)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
long top = tab->item_top, total = tab->item_count;
|
|
|
|
long top = s * tab->item_top, total = s * tab->item_count;
|
|
|
|
if (total < visible)
|
|
|
|
if (total < visible)
|
|
|
|
return (struct scrollbar) { 0, 0 };
|
|
|
|
return (struct scrollbar) { 0, 0 };
|
|
|
|
if (visible == 1)
|
|
|
|
if (visible == 1)
|
|
|
|
@@ -2040,7 +2037,7 @@ app_compute_scrollbar (struct tab *tab, long visible, long s)
|
|
|
|
|
|
|
|
|
|
|
|
// Only be at the top or bottom when the top or bottom item can be seen.
|
|
|
|
// Only be at the top or bottom when the top or bottom item can be seen.
|
|
|
|
// The algorithm isn't optimal but it's a bitch to get right.
|
|
|
|
// The algorithm isn't optimal but it's a bitch to get right.
|
|
|
|
double available_length = s * visible - 2 - s + 1;
|
|
|
|
double available_length = visible - 2 - s + 1;
|
|
|
|
|
|
|
|
|
|
|
|
double lenf = s + available_length * visible / total, length = 0.;
|
|
|
|
double lenf = s + available_length * visible / total, length = 0.;
|
|
|
|
long offset = 1 + available_length * top / total + modf (lenf, &length);
|
|
|
|
long offset = 1 + available_length * top / total + modf (lenf, &length);
|
|
|
|
@@ -2048,7 +2045,7 @@ app_compute_scrollbar (struct tab *tab, long visible, long s)
|
|
|
|
if (top == 0)
|
|
|
|
if (top == 0)
|
|
|
|
return (struct scrollbar) { length, 0 };
|
|
|
|
return (struct scrollbar) { length, 0 };
|
|
|
|
if (top + visible >= total)
|
|
|
|
if (top + visible >= total)
|
|
|
|
return (struct scrollbar) { length, s * visible - length };
|
|
|
|
return (struct scrollbar) { length, visible - length };
|
|
|
|
|
|
|
|
|
|
|
|
return (struct scrollbar) { length, offset };
|
|
|
|
return (struct scrollbar) { length, offset };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@@ -2097,7 +2094,7 @@ app_sublayout_list (struct widget *list)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct tab *tab = g.active_tab;
|
|
|
|
struct tab *tab = g.active_tab;
|
|
|
|
int to_show = MIN ((int) tab->item_count - tab->item_top,
|
|
|
|
int to_show = MIN ((int) tab->item_count - tab->item_top,
|
|
|
|
list->height / g.ui_vunit);
|
|
|
|
ceil ((double) list->height / g.ui_vunit));
|
|
|
|
|
|
|
|
|
|
|
|
struct layout l = {};
|
|
|
|
struct layout l = {};
|
|
|
|
for (int row = 0; row < to_show; row++)
|
|
|
|
for (int row = 0; row < to_show; row++)
|
|
|
|
@@ -2239,25 +2236,36 @@ static void
|
|
|
|
app_layout_statusbar (void)
|
|
|
|
app_layout_statusbar (void)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct layout l = {};
|
|
|
|
struct layout l = {};
|
|
|
|
|
|
|
|
chtype attrs[2] = { APP_ATTR (NORMAL), APP_ATTR (HIGHLIGHT) };
|
|
|
|
if (g.message)
|
|
|
|
if (g.message)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
app_push (&l, g.ui->padding (APP_ATTR (NORMAL), 0.25, 1))
|
|
|
|
app_push (&l, g.ui->padding (attrs[0], 0.25, 1));
|
|
|
|
->id = WIDGET_MESSAGE;
|
|
|
|
if (!g.message_detail)
|
|
|
|
app_push_fill (&l, g.ui->label (APP_ATTR (HIGHLIGHT), g.message))
|
|
|
|
app_push_fill (&l, g.ui->label (attrs[1], g.message));
|
|
|
|
->id = WIDGET_MESSAGE;
|
|
|
|
else
|
|
|
|
app_push (&l, g.ui->padding (APP_ATTR (NORMAL), 0.25, 1))
|
|
|
|
{
|
|
|
|
->id = WIDGET_MESSAGE;
|
|
|
|
app_push (&l, g.ui->label (attrs[1], g.message));
|
|
|
|
|
|
|
|
app_push_fill (&l, g.ui->label (attrs[0], g.message_detail));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
app_push (&l, g.ui->padding (attrs[0], 0.25, 1));
|
|
|
|
|
|
|
|
|
|
|
|
app_flush_layout (&l);
|
|
|
|
app_flush_layout (&l);
|
|
|
|
|
|
|
|
LIST_FOR_EACH (struct widget, w, l.head)
|
|
|
|
|
|
|
|
w->id = WIDGET_MESSAGE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (g.editor.line)
|
|
|
|
else if (g.editor.line)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
app_push (&l, g.ui->padding (APP_ATTR (NORMAL), 0.25, 1));
|
|
|
|
app_push (&l, g.ui->padding (attrs[0], 0.25, 1));
|
|
|
|
app_push (&l, g.ui->editor (APP_ATTR (HIGHLIGHT)));
|
|
|
|
app_push (&l, g.ui->editor (attrs[1]));
|
|
|
|
app_push (&l, g.ui->padding (APP_ATTR (NORMAL), 0.25, 1));
|
|
|
|
app_push (&l, g.ui->padding (attrs[0], 0.25, 1));
|
|
|
|
app_flush_layout (&l);
|
|
|
|
app_flush_layout (&l);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (g.client.state == MPD_CONNECTED)
|
|
|
|
else if (g.client.state == MPD_CONNECTED)
|
|
|
|
app_layout_mpd_status ();
|
|
|
|
app_layout_mpd_status ();
|
|
|
|
|
|
|
|
else if (g.client.state == MPD_CONNECTING)
|
|
|
|
|
|
|
|
app_layout_text ("Connecting to MPD...", attrs[0]);
|
|
|
|
|
|
|
|
else if (g.client.state == MPD_DISCONNECTED)
|
|
|
|
|
|
|
|
app_layout_text ("Disconnected", attrs[0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
@@ -2375,6 +2383,27 @@ app_move_selection (int diff)
|
|
|
|
return result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
|
|
app_show_message (char *message, char *detail)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
cstr_set (&g.message, message);
|
|
|
|
|
|
|
|
cstr_set (&g.message_detail, detail);
|
|
|
|
|
|
|
|
poller_timer_set (&g.message_timer, 5000);
|
|
|
|
|
|
|
|
app_invalidate ();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
|
|
app_hide_message (void)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!g.message)
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cstr_set (&g.message, NULL);
|
|
|
|
|
|
|
|
cstr_set (&g.message_detail, NULL);
|
|
|
|
|
|
|
|
poller_timer_reset (&g.message_timer);
|
|
|
|
|
|
|
|
app_invalidate ();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
static void
|
|
|
|
@@ -2558,17 +2587,6 @@ app_mpd_toggle (const char *name)
|
|
|
|
return MPD_SIMPLE (name, value ? "0" : "1");
|
|
|
|
return MPD_SIMPLE (name, value ? "0" : "1");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
|
|
app_hide_message (void)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (g.message)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
cstr_set (&g.message, NULL);
|
|
|
|
|
|
|
|
poller_timer_reset (&g.message_timer);
|
|
|
|
|
|
|
|
app_invalidate ();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
static bool
|
|
|
|
app_process_action (enum action action)
|
|
|
|
app_process_action (enum action action)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@@ -2606,7 +2624,8 @@ app_process_action (enum action action)
|
|
|
|
app_hide_message ();
|
|
|
|
app_hide_message ();
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
print_error ("can't do that here: %s", g_action_descriptions[action]);
|
|
|
|
print_error ("\"%s\" is not allowed here",
|
|
|
|
|
|
|
|
g_action_descriptions[action]);
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
case ACTION_MULTISELECT:
|
|
|
|
case ACTION_MULTISELECT:
|
|
|
|
@@ -2738,7 +2757,8 @@ app_editor_process_action (enum action action)
|
|
|
|
g.editor.on_end = NULL;
|
|
|
|
g.editor.on_end = NULL;
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
print_error ("can't do that here: %s", g_action_descriptions[action]);
|
|
|
|
print_error ("\"%s\" is not allowed here",
|
|
|
|
|
|
|
|
g_action_descriptions[action]);
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
case ACTION_EDITOR_B_CHAR:
|
|
|
|
case ACTION_EDITOR_B_CHAR:
|
|
|
|
@@ -2818,9 +2838,8 @@ app_process_left_mouse_click (struct widget *w, int x, int y, int modifiers)
|
|
|
|
else if (tab->item_mark < 0)
|
|
|
|
else if (tab->item_mark < 0)
|
|
|
|
tab->item_mark = tab->item_selected;
|
|
|
|
tab->item_mark = tab->item_selected;
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: Probably will need to fix up item->top
|
|
|
|
|
|
|
|
// for partially visible items in X11.
|
|
|
|
|
|
|
|
tab->item_selected = row_index + tab->item_top;
|
|
|
|
tab->item_selected = row_index + tab->item_top;
|
|
|
|
|
|
|
|
app_ensure_selection_visible ();
|
|
|
|
app_invalidate ();
|
|
|
|
app_invalidate ();
|
|
|
|
|
|
|
|
|
|
|
|
if (modifiers & APP_KEYMOD_DOUBLE_CLICK)
|
|
|
|
if (modifiers & APP_KEYMOD_DOUBLE_CLICK)
|
|
|
|
@@ -2831,7 +2850,7 @@ app_process_left_mouse_click (struct widget *w, int x, int y, int modifiers)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct tab *tab = g.active_tab;
|
|
|
|
struct tab *tab = g.active_tab;
|
|
|
|
int visible_items = app_visible_items ();
|
|
|
|
int visible_items = app_visible_items ();
|
|
|
|
tab->item_top = (float) y / w->height
|
|
|
|
tab->item_top = (double) y / w->height
|
|
|
|
* (int) tab->item_count - visible_items / 2;
|
|
|
|
* (int) tab->item_count - visible_items / 2;
|
|
|
|
app_invalidate ();
|
|
|
|
app_invalidate ();
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
@@ -2927,6 +2946,8 @@ g_normal_defaults[] =
|
|
|
|
{ "C-l", ACTION_REDRAW },
|
|
|
|
{ "C-l", ACTION_REDRAW },
|
|
|
|
{ "M-Tab", ACTION_TAB_LAST },
|
|
|
|
{ "M-Tab", ACTION_TAB_LAST },
|
|
|
|
{ "F1", ACTION_TAB_HELP },
|
|
|
|
{ "F1", ACTION_TAB_HELP },
|
|
|
|
|
|
|
|
{ "S-Tab", ACTION_TAB_PREVIOUS },
|
|
|
|
|
|
|
|
{ "Tab", ACTION_TAB_NEXT },
|
|
|
|
{ "C-Left", ACTION_TAB_PREVIOUS },
|
|
|
|
{ "C-Left", ACTION_TAB_PREVIOUS },
|
|
|
|
{ "C-Right", ACTION_TAB_NEXT },
|
|
|
|
{ "C-Right", ACTION_TAB_NEXT },
|
|
|
|
{ "C-PageUp", ACTION_TAB_PREVIOUS },
|
|
|
|
{ "C-PageUp", ACTION_TAB_PREVIOUS },
|
|
|
|
@@ -2962,6 +2983,7 @@ g_normal_defaults[] =
|
|
|
|
{ "Enter", ACTION_CHOOSE },
|
|
|
|
{ "Enter", ACTION_CHOOSE },
|
|
|
|
{ "Delete", ACTION_DELETE },
|
|
|
|
{ "Delete", ACTION_DELETE },
|
|
|
|
{ "d", ACTION_DELETE },
|
|
|
|
{ "d", ACTION_DELETE },
|
|
|
|
|
|
|
|
{ "?", ACTION_DESCRIBE },
|
|
|
|
{ "M-Up", ACTION_UP },
|
|
|
|
{ "M-Up", ACTION_UP },
|
|
|
|
{ "Backspace", ACTION_UP },
|
|
|
|
{ "Backspace", ACTION_UP },
|
|
|
|
{ "v", ACTION_MULTISELECT },
|
|
|
|
{ "v", ACTION_MULTISELECT },
|
|
|
|
@@ -3086,9 +3108,28 @@ app_init_bindings (const char *keymap,
|
|
|
|
return a;
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
|
|
|
app_strfkey (const termo_key_t *key)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// For display purposes, this is highly desirable
|
|
|
|
|
|
|
|
int flags = termo_get_flags (g.tk);
|
|
|
|
|
|
|
|
termo_set_flags (g.tk, flags | TERMO_FLAG_SPACESYMBOL);
|
|
|
|
|
|
|
|
termo_key_t fixed = *key;
|
|
|
|
|
|
|
|
termo_canonicalise (g.tk, &fixed);
|
|
|
|
|
|
|
|
termo_set_flags (g.tk, flags);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char buf[16] = "";
|
|
|
|
|
|
|
|
termo_strfkey_utf8 (g.tk, buf, sizeof buf, &fixed, TERMO_FORMAT_ALTISMETA);
|
|
|
|
|
|
|
|
return xstrdup (buf);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
static bool
|
|
|
|
app_process_termo_event (termo_key_t *event)
|
|
|
|
app_process_termo_event (termo_key_t *event)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
char *formatted = app_strfkey (event);
|
|
|
|
|
|
|
|
print_debug ("%s", formatted);
|
|
|
|
|
|
|
|
free (formatted);
|
|
|
|
|
|
|
|
|
|
|
|
bool handled = false;
|
|
|
|
bool handled = false;
|
|
|
|
if ((handled = event->type == TERMO_TYPE_FOCUS))
|
|
|
|
if ((handled = event->type == TERMO_TYPE_FOCUS))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@@ -3238,6 +3279,12 @@ current_tab_on_action (enum action action)
|
|
|
|
tab->item_mark = -1;
|
|
|
|
tab->item_mark = -1;
|
|
|
|
return map && (id = compact_map_find (map, "id"))
|
|
|
|
return map && (id = compact_map_find (map, "id"))
|
|
|
|
&& MPD_SIMPLE ("playid", id);
|
|
|
|
&& MPD_SIMPLE ("playid", id);
|
|
|
|
|
|
|
|
case ACTION_DESCRIBE:
|
|
|
|
|
|
|
|
if (!map || !(id = compact_map_find (map, "file")))
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app_show_message (xstrdup ("Path: "), xstrdup (id));
|
|
|
|
|
|
|
|
return true;
|
|
|
|
case ACTION_DELETE:
|
|
|
|
case ACTION_DELETE:
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct mpd_client *c = &g.client;
|
|
|
|
struct mpd_client *c = &g.client;
|
|
|
|
@@ -3652,6 +3699,12 @@ library_tab_on_action (enum action action)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tab->item_mark = -1;
|
|
|
|
tab->item_mark = -1;
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
|
|
|
|
case ACTION_DESCRIBE:
|
|
|
|
|
|
|
|
if (!*x->path)
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app_show_message (xstrdup ("Path: "), xstrdup (x->path));
|
|
|
|
|
|
|
|
return true;
|
|
|
|
case ACTION_UP:
|
|
|
|
case ACTION_UP:
|
|
|
|
{
|
|
|
|
{
|
|
|
|
char *parent = library_tab_parent ();
|
|
|
|
char *parent = library_tab_parent ();
|
|
|
|
@@ -3990,6 +4043,9 @@ streams_tab_on_action (enum action action)
|
|
|
|
case ACTION_MPD_ADD:
|
|
|
|
case ACTION_MPD_ADD:
|
|
|
|
streams_tab_process (uri, false, &e);
|
|
|
|
streams_tab_process (uri, false, &e);
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ACTION_DESCRIBE:
|
|
|
|
|
|
|
|
app_show_message (xstrdup (uri), NULL);
|
|
|
|
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@@ -4103,32 +4159,26 @@ help_tab_on_action (enum action action)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct tab *tab = &g_help_tab.super;
|
|
|
|
struct tab *tab = &g_help_tab.super;
|
|
|
|
if (tab->item_selected < 0
|
|
|
|
if (tab->item_selected < 0
|
|
|
|
|| tab->item_selected >= (int) g_help_tab.actions_len
|
|
|
|
|| tab->item_selected >= (int) g_help_tab.actions_len)
|
|
|
|
|| action != ACTION_CHOOSE)
|
|
|
|
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
action = g_help_tab.actions[tab->item_selected];
|
|
|
|
enum action a = g_help_tab.actions[tab->item_selected];
|
|
|
|
if (action == ACTION_NONE || action == ACTION_CHOOSE /* avoid recursion */)
|
|
|
|
if (!a)
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (action == ACTION_DESCRIBE)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
char *name = xstrdup (g_action_names[a]);
|
|
|
|
|
|
|
|
cstr_transform (name, tolower_ascii);
|
|
|
|
|
|
|
|
app_show_message (xstrdup ("Configuration name: "), name);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action != ACTION_CHOOSE || a == ACTION_CHOOSE /* avoid recursion */)
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
// XXX: We can't propagate failure to ring the terminal/X11 bell, but we
|
|
|
|
// XXX: We can't propagate failure to ring the terminal/X11 bell, but we
|
|
|
|
// don't want to let our caller show a bad "can't do that" message either.
|
|
|
|
// don't want to let our caller show a bad "can't do that" message either.
|
|
|
|
return app_process_action (action), true;
|
|
|
|
return app_process_action (a), true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
|
|
help_tab_strfkey (const termo_key_t *key, struct strv *out)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// For display purposes, this is highly desirable
|
|
|
|
|
|
|
|
int flags = termo_get_flags (g.tk);
|
|
|
|
|
|
|
|
termo_set_flags (g.tk, flags | TERMO_FLAG_SPACESYMBOL);
|
|
|
|
|
|
|
|
termo_key_t fixed = *key;
|
|
|
|
|
|
|
|
termo_canonicalise (g.tk, &fixed);
|
|
|
|
|
|
|
|
termo_set_flags (g.tk, flags);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char buf[16];
|
|
|
|
|
|
|
|
termo_strfkey_utf8 (g.tk, buf, sizeof buf, &fixed, TERMO_FORMAT_ALTISMETA);
|
|
|
|
|
|
|
|
strv_append (out, buf);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
static void
|
|
|
|
@@ -4152,7 +4202,7 @@ help_tab_group (struct binding *keys, size_t len, struct strv *out,
|
|
|
|
struct strv ass = strv_make ();
|
|
|
|
struct strv ass = strv_make ();
|
|
|
|
for (size_t k = 0; k < len; k++)
|
|
|
|
for (size_t k = 0; k < len; k++)
|
|
|
|
if (keys[k].action == i)
|
|
|
|
if (keys[k].action == i)
|
|
|
|
help_tab_strfkey (&keys[k].decoded, &ass);
|
|
|
|
strv_append_owned (&ass, app_strfkey (&keys[k].decoded));
|
|
|
|
if (ass.len)
|
|
|
|
if (ass.len)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
char *joined = strv_join (&ass, ", ");
|
|
|
|
char *joined = strv_join (&ass, ", ");
|
|
|
|
@@ -4953,6 +5003,7 @@ app_on_reconnect (void *user_data)
|
|
|
|
mpd_queue_reconnect ();
|
|
|
|
mpd_queue_reconnect ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free (address);
|
|
|
|
free (address);
|
|
|
|
|
|
|
|
app_invalidate ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// --- TUI ---------------------------------------------------------------------
|
|
|
|
// --- TUI ---------------------------------------------------------------------
|
|
|
|
@@ -5119,7 +5170,7 @@ tui_render_scrollbar (struct widget *self)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct scrollbar bar = app_compute_scrollbar (tab, visible_items, 8);
|
|
|
|
struct scrollbar bar = app_compute_scrollbar (tab, visible_items * 8, 8);
|
|
|
|
bar.length += bar.start;
|
|
|
|
bar.length += bar.start;
|
|
|
|
|
|
|
|
|
|
|
|
int start_part = bar.start % 8; bar.start /= 8;
|
|
|
|
int start_part = bar.start % 8; bar.start /= 8;
|
|
|
|
@@ -5515,55 +5566,56 @@ x11_make_label (chtype attrs, const char *label)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// On a 20x20 raster to make it feasible to design on paper.
|
|
|
|
// On a 20x20 raster to make it feasible to design on paper.
|
|
|
|
static const XPointDouble x11_stop = {INFINITY, INFINITY},
|
|
|
|
#define X11_STOP {INFINITY, INFINITY}
|
|
|
|
|
|
|
|
static const XPointDouble
|
|
|
|
x11_icon_previous[] =
|
|
|
|
x11_icon_previous[] =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
{10, 0}, {0, 10}, {10, 20}, x11_stop,
|
|
|
|
{10, 0}, {0, 10}, {10, 20}, X11_STOP,
|
|
|
|
{20, 0}, {10, 10}, {20, 20}, x11_stop, x11_stop,
|
|
|
|
{20, 0}, {10, 10}, {20, 20}, X11_STOP, X11_STOP,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
x11_icon_pause[] =
|
|
|
|
x11_icon_pause[] =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
{1, 0}, {7, 0}, {7, 20}, {1, 20}, x11_stop,
|
|
|
|
{1, 0}, {7, 0}, {7, 20}, {1, 20}, X11_STOP,
|
|
|
|
{13, 0}, {19, 0}, {19, 20}, {13, 20}, x11_stop, x11_stop,
|
|
|
|
{13, 0}, {19, 0}, {19, 20}, {13, 20}, X11_STOP, X11_STOP,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
x11_icon_play[] =
|
|
|
|
x11_icon_play[] =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
{0, 0}, {20, 10}, {0, 20}, x11_stop, x11_stop,
|
|
|
|
{0, 0}, {20, 10}, {0, 20}, X11_STOP, X11_STOP,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
x11_icon_stop[] =
|
|
|
|
x11_icon_stop[] =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
{0, 0}, {20, 0}, {20, 20}, {0, 20}, x11_stop, x11_stop,
|
|
|
|
{0, 0}, {20, 0}, {20, 20}, {0, 20}, X11_STOP, X11_STOP,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
x11_icon_next[] =
|
|
|
|
x11_icon_next[] =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
{0, 0}, {10, 10}, {0, 20}, x11_stop,
|
|
|
|
{0, 0}, {10, 10}, {0, 20}, X11_STOP,
|
|
|
|
{10, 0}, {20, 10}, {10, 20}, x11_stop, x11_stop,
|
|
|
|
{10, 0}, {20, 10}, {10, 20}, X11_STOP, X11_STOP,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
x11_icon_repeat[] =
|
|
|
|
x11_icon_repeat[] =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
{0, 12}, {0, 6}, {3, 3}, {13, 3}, {13, 0}, {20, 4.5},
|
|
|
|
{0, 12}, {0, 6}, {3, 3}, {13, 3}, {13, 0}, {20, 4.5},
|
|
|
|
{13, 9}, {13, 6}, {3, 6}, {3, 10}, x11_stop,
|
|
|
|
{13, 9}, {13, 6}, {3, 6}, {3, 10}, X11_STOP,
|
|
|
|
{0, 15.5}, {7, 11}, {7, 14}, {17, 14}, {17, 10}, {20, 8},
|
|
|
|
{0, 15.5}, {7, 11}, {7, 14}, {17, 14}, {17, 10}, {20, 8},
|
|
|
|
{20, 14}, {17, 17}, {7, 17}, {7, 20}, x11_stop, x11_stop,
|
|
|
|
{20, 14}, {17, 17}, {7, 17}, {7, 20}, X11_STOP, X11_STOP,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
x11_icon_random[] =
|
|
|
|
x11_icon_random[] =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
{0, 6}, {0, 3}, {5, 3}, {6, 4.5}, {4, 7.5}, {3, 6}, x11_stop,
|
|
|
|
{0, 6}, {0, 3}, {5, 3}, {6, 4.5}, {4, 7.5}, {3, 6}, X11_STOP,
|
|
|
|
{9, 15.5}, {11, 12.5}, {12, 14}, {13, 14}, {13, 11}, {20, 15.5},
|
|
|
|
{9, 15.5}, {11, 12.5}, {12, 14}, {13, 14}, {13, 11}, {20, 15.5},
|
|
|
|
{13, 20}, {13, 17}, {10, 17}, x11_stop,
|
|
|
|
{13, 20}, {13, 17}, {10, 17}, X11_STOP,
|
|
|
|
{0, 17}, {0, 14}, {3, 14}, {10, 3}, {13, 3}, {13, 0}, {20, 4.5},
|
|
|
|
{0, 17}, {0, 14}, {3, 14}, {10, 3}, {13, 3}, {13, 0}, {20, 4.5},
|
|
|
|
{13, 9}, {13, 6}, {12, 6}, {5, 17}, x11_stop, x11_stop,
|
|
|
|
{13, 9}, {13, 6}, {12, 6}, {5, 17}, X11_STOP, X11_STOP,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
x11_icon_single[] =
|
|
|
|
x11_icon_single[] =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
{7, 6}, {7, 4}, {9, 2}, {12, 2}, {12, 15}, {14, 15}, {14, 18},
|
|
|
|
{7, 6}, {7, 4}, {9, 2}, {12, 2}, {12, 15}, {14, 15}, {14, 18},
|
|
|
|
{7, 18}, {7, 15}, {9, 15}, {9, 6}, x11_stop, x11_stop,
|
|
|
|
{7, 18}, {7, 15}, {9, 15}, {9, 6}, X11_STOP, X11_STOP,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
x11_icon_consume[] =
|
|
|
|
x11_icon_consume[] =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
{0, 13}, {0, 7}, {4, 3}, {10, 3}, {14, 7}, {5, 10}, {14, 13},
|
|
|
|
{0, 13}, {0, 7}, {4, 3}, {10, 3}, {14, 7}, {5, 10}, {14, 13},
|
|
|
|
{10, 17}, {4, 17}, x11_stop,
|
|
|
|
{10, 17}, {4, 17}, X11_STOP,
|
|
|
|
{16, 12}, {16, 8}, {20, 8}, {20, 12}, x11_stop, x11_stop,
|
|
|
|
{16, 12}, {16, 8}, {20, 8}, {20, 12}, X11_STOP, X11_STOP,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static const XPointDouble *
|
|
|
|
static const XPointDouble *
|
|
|
|
@@ -5739,10 +5791,8 @@ x11_render_scrollbar (struct widget *self)
|
|
|
|
x11_render_padding (self);
|
|
|
|
x11_render_padding (self);
|
|
|
|
|
|
|
|
|
|
|
|
struct tab *tab = g.active_tab;
|
|
|
|
struct tab *tab = g.active_tab;
|
|
|
|
// FIXME: This isn't an integer number in this case.
|
|
|
|
|
|
|
|
int visible_items = app_visible_items ();
|
|
|
|
|
|
|
|
struct scrollbar bar =
|
|
|
|
struct scrollbar bar =
|
|
|
|
app_compute_scrollbar (tab, visible_items, g.ui_vunit);
|
|
|
|
app_compute_scrollbar (tab, app_visible_items_height (), g.ui_vunit);
|
|
|
|
|
|
|
|
|
|
|
|
XRenderFillRectangle (g.dpy, PictOpSrc, g.x11_pixmap_picture,
|
|
|
|
XRenderFillRectangle (g.dpy, PictOpSrc, g.x11_pixmap_picture,
|
|
|
|
x11_fg_attrs (self->attrs),
|
|
|
|
x11_fg_attrs (self->attrs),
|
|
|
|
@@ -5762,17 +5812,22 @@ x11_make_scrollbar (chtype attrs)
|
|
|
|
return w;
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: Handle partial items, otherwise this is the same as tui_render_list().
|
|
|
|
|
|
|
|
static void
|
|
|
|
static void
|
|
|
|
x11_render_list (struct widget *self)
|
|
|
|
x11_render_list (struct widget *self)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
x11_render_padding (self);
|
|
|
|
// We could do that for all widgets, but it would be kind-of pointless.
|
|
|
|
|
|
|
|
XRenderSetPictureClipRectangles (g.dpy, g.x11_pixmap_picture, 0, 0,
|
|
|
|
|
|
|
|
&(XRectangle) { self->x, self->y, self->width, self->height }, 1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
x11_render_padding (self);
|
|
|
|
LIST_FOR_EACH (struct widget, w, self->on_sublayout (self))
|
|
|
|
LIST_FOR_EACH (struct widget, w, self->on_sublayout (self))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
w->on_render (w);
|
|
|
|
w->on_render (w);
|
|
|
|
free (w);
|
|
|
|
free (w);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
XRenderChangePicture (g.dpy, g.x11_pixmap_picture, CPClipMask,
|
|
|
|
|
|
|
|
&(XRenderPictureAttributes) { .clip_mask = None });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static struct widget *
|
|
|
|
static struct widget *
|
|
|
|
@@ -5901,6 +5956,7 @@ x11_convert_keysym (KeySym keysym)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
case XK_BackSpace: return TERMO_SYM_BACKSPACE;
|
|
|
|
case XK_BackSpace: return TERMO_SYM_BACKSPACE;
|
|
|
|
case XK_Tab: return TERMO_SYM_TAB;
|
|
|
|
case XK_Tab: return TERMO_SYM_TAB;
|
|
|
|
|
|
|
|
case XK_ISO_Left_Tab: return TERMO_SYM_TAB;
|
|
|
|
case XK_Return: return TERMO_SYM_ENTER;
|
|
|
|
case XK_Return: return TERMO_SYM_ENTER;
|
|
|
|
case XK_Escape: return TERMO_SYM_ESCAPE;
|
|
|
|
case XK_Escape: return TERMO_SYM_ESCAPE;
|
|
|
|
|
|
|
|
|
|
|
|
@@ -6011,8 +6067,14 @@ on_x11_keypress (XEvent *e)
|
|
|
|
memcpy (k.multibyte, p, MIN (cp_len, sizeof k.multibyte - 1));
|
|
|
|
memcpy (k.multibyte, p, MIN (cp_len, sizeof k.multibyte - 1));
|
|
|
|
p += cp_len;
|
|
|
|
p += cp_len;
|
|
|
|
|
|
|
|
|
|
|
|
// This is unfortunate, but probably in the right place.
|
|
|
|
// This is all unfortunate, but probably in the right place.
|
|
|
|
if (cp >= 32)
|
|
|
|
if (!cp)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
k.code.codepoint = ' ';
|
|
|
|
|
|
|
|
if (ev->state & ShiftMask)
|
|
|
|
|
|
|
|
k.modifiers |= TERMO_KEYMOD_SHIFT;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (cp >= 32)
|
|
|
|
k.code.codepoint = cp;
|
|
|
|
k.code.codepoint = cp;
|
|
|
|
else if (ev->state & ShiftMask)
|
|
|
|
else if (ev->state & ShiftMask)
|
|
|
|
k.code.codepoint = cp + 64;
|
|
|
|
k.code.codepoint = cp + 64;
|
|
|
|
@@ -6078,11 +6140,8 @@ x11_process_press (int x, int y, int button, int modifiers)
|
|
|
|
cstr_set (&g.x11_selection, text);
|
|
|
|
cstr_set (&g.x11_selection, text);
|
|
|
|
XSetSelectionOwner (g.dpy, XInternAtom (g.dpy, "CLIPBOARD", False),
|
|
|
|
XSetSelectionOwner (g.dpy, XInternAtom (g.dpy, "CLIPBOARD", False),
|
|
|
|
g.x11_window, CurrentTime);
|
|
|
|
g.x11_window, CurrentTime);
|
|
|
|
|
|
|
|
app_show_message (xstrdup ("Text copied to clipboard: "),
|
|
|
|
cstr_set (&g.message,
|
|
|
|
xstrdup (g.x11_selection));
|
|
|
|
xstrdup_printf ("Text copied to clipboard: %s", g.x11_selection));
|
|
|
|
|
|
|
|
poller_timer_set (&g.message_timer, 5000);
|
|
|
|
|
|
|
|
app_invalidate ();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
out:
|
|
|
|
@@ -6148,6 +6207,7 @@ on_x11_selection_request (XSelectionRequestEvent *ev)
|
|
|
|
Atom xa_utf8 = XInternAtom (g.dpy, "UTF8_STRING", False);
|
|
|
|
Atom xa_utf8 = XInternAtom (g.dpy, "UTF8_STRING", False);
|
|
|
|
Atom targets[] = { xa_targets, XA_STRING, xa_compound_text, xa_utf8 };
|
|
|
|
Atom targets[] = { xa_targets, XA_STRING, xa_compound_text, xa_utf8 };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
XEvent response = {};
|
|
|
|
bool ok = false;
|
|
|
|
bool ok = false;
|
|
|
|
Atom property = ev->property ? ev->property : ev->target;
|
|
|
|
Atom property = ev->property ? ev->property : ev->target;
|
|
|
|
if (!g.x11_selection)
|
|
|
|
if (!g.x11_selection)
|
|
|
|
@@ -6182,7 +6242,6 @@ on_x11_selection_request (XSelectionRequestEvent *ev)
|
|
|
|
XFree (text.value);
|
|
|
|
XFree (text.value);
|
|
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
out:
|
|
|
|
XEvent response = {};
|
|
|
|
|
|
|
|
response.xselection.type = SelectionNotify;
|
|
|
|
response.xselection.type = SelectionNotify;
|
|
|
|
// XXX: We should check it against the event causing XSetSelectionOwner().
|
|
|
|
// XXX: We should check it against the event causing XSetSelectionOwner().
|
|
|
|
response.xselection.time = ev->time;
|
|
|
|
response.xselection.time = ev->time;
|
|
|
|
@@ -6585,6 +6644,7 @@ app_on_message_timer (void *user_data)
|
|
|
|
(void) user_data;
|
|
|
|
(void) user_data;
|
|
|
|
|
|
|
|
|
|
|
|
cstr_set (&g.message, NULL);
|
|
|
|
cstr_set (&g.message, NULL);
|
|
|
|
|
|
|
|
cstr_set (&g.message_detail, NULL);
|
|
|
|
app_invalidate ();
|
|
|
|
app_invalidate ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -6601,12 +6661,13 @@ app_log_handler (void *user_data, const char *quote, const char *fmt,
|
|
|
|
|
|
|
|
|
|
|
|
struct str message = str_make ();
|
|
|
|
struct str message = str_make ();
|
|
|
|
str_append (&message, quote);
|
|
|
|
str_append (&message, quote);
|
|
|
|
|
|
|
|
size_t quote_len = message.len;
|
|
|
|
str_append_vprintf (&message, fmt, ap);
|
|
|
|
str_append_vprintf (&message, fmt, ap);
|
|
|
|
|
|
|
|
|
|
|
|
// Show it to the user, then maybe log it elsewhere as well.
|
|
|
|
// Show it prettified to the user, then maybe log it elsewhere as well.
|
|
|
|
cstr_set (&g.message, xstrdup (message.str));
|
|
|
|
message.str[0] = toupper_ascii (message.str[0]);
|
|
|
|
poller_timer_set (&g.message_timer, 5000);
|
|
|
|
app_show_message (xstrndup (message.str, quote_len),
|
|
|
|
app_invalidate ();
|
|
|
|
xstrdup (message.str + quote_len));
|
|
|
|
|
|
|
|
|
|
|
|
if (g_verbose_mode && (g.ui != &tui_ui || !isatty (STDERR_FILENO)))
|
|
|
|
if (g_verbose_mode && (g.ui != &tui_ui || !isatty (STDERR_FILENO)))
|
|
|
|
fprintf (stderr, "%s\n", message.str);
|
|
|
|
fprintf (stderr, "%s\n", message.str);
|
|
|
|
|