keyboard-select with scrollback support
note: currently doesn't draw a visible selection cursor
This commit is contained in:
parent
eefb56f24c
commit
131cb20584
45
termite.c
45
termite.c
|
@ -34,6 +34,8 @@ typedef struct select_info {
|
||||||
select_mode mode;
|
select_mode mode;
|
||||||
long begin_col;
|
long begin_col;
|
||||||
long begin_row;
|
long begin_row;
|
||||||
|
long cursor_col;
|
||||||
|
long cursor_row;
|
||||||
} select_info;
|
} select_info;
|
||||||
|
|
||||||
typedef struct search_panel_info {
|
typedef struct search_panel_info {
|
||||||
|
@ -77,7 +79,7 @@ void window_title_cb(VteTerminal *vte, GtkWindow *window) {
|
||||||
gtk_window_set_title(window, t ? t : "termite");
|
gtk_window_set_title(window, t ? t : "termite");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cursor_moved_cb(VteTerminal *vte, select_info *select) {
|
static void update_selection(VteTerminal *vte, select_info *select) {
|
||||||
if (select->mode == SELECT_OFF || select->mode == SELECT_ON) {
|
if (select->mode == SELECT_OFF || select->mode == SELECT_ON) {
|
||||||
return; // not in visual mode
|
return; // not in visual mode
|
||||||
}
|
}
|
||||||
|
@ -86,8 +88,7 @@ static void cursor_moved_cb(VteTerminal *vte, select_info *select) {
|
||||||
vte_terminal_set_selection_block_mode(vte, select->mode == SELECT_VISUAL_BLOCK);
|
vte_terminal_set_selection_block_mode(vte, select->mode == SELECT_VISUAL_BLOCK);
|
||||||
|
|
||||||
const long n_columns = vte_terminal_get_column_count(vte);
|
const long n_columns = vte_terminal_get_column_count(vte);
|
||||||
long end_row, end_col;
|
long end_row = select->cursor_row, end_col = select->cursor_col;
|
||||||
vte_terminal_get_cursor_position(vte, &end_col, &end_row);
|
|
||||||
|
|
||||||
if (select->mode == SELECT_VISUAL) {
|
if (select->mode == SELECT_VISUAL) {
|
||||||
const long begin = select->begin_row * n_columns + select->begin_col;
|
const long begin = select->begin_row * n_columns + select->begin_col;
|
||||||
|
@ -122,13 +123,14 @@ static void feed_str(VteTerminal *vte, const char *s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void start_selection(VteTerminal *vte, select_info *select) {
|
static void start_selection(VteTerminal *vte, select_info *select) {
|
||||||
feed_str(vte, CSI "s"); // save cursor position
|
feed_str(vte, CSI "?25l"); // hide cursor
|
||||||
select->mode = SELECT_ON;
|
select->mode = SELECT_ON;
|
||||||
|
vte_terminal_get_cursor_position(vte, &select->cursor_col, &select->cursor_row);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void end_selection(VteTerminal *vte, select_info *select) {
|
static void end_selection(VteTerminal *vte, select_info *select) {
|
||||||
|
feed_str(vte, CSI "?25h"); // show cursor
|
||||||
vte_terminal_select_none(vte);
|
vte_terminal_select_none(vte);
|
||||||
feed_str(vte, CSI "u"); // restore cursor position
|
|
||||||
select->mode = SELECT_OFF;
|
select->mode = SELECT_OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,14 +140,20 @@ static void toggle_visual(VteTerminal *vte, select_info *select, select_mode mod
|
||||||
vte_terminal_select_none(vte);
|
vte_terminal_select_none(vte);
|
||||||
} else {
|
} else {
|
||||||
select->mode = mode;
|
select->mode = mode;
|
||||||
vte_terminal_get_cursor_position(vte, &select->begin_col, &select->begin_row);
|
select->begin_col = select->cursor_col;
|
||||||
|
select->begin_row = select->cursor_row;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cursor_move_end_of_line(VteTerminal *vte) {
|
static void move(VteTerminal *vte, select_info *select, long col, long row) {
|
||||||
char *eol = g_strdup_printf(CSI "%ldG", vte_terminal_get_column_count(vte));
|
const long end_col = vte_terminal_get_column_count(vte) - 1;
|
||||||
feed_str(vte, eol);
|
/*const long end_row = vte_terminal_get_row_count(vte) - 1;*/
|
||||||
g_free(eol);
|
|
||||||
|
select->cursor_col = CLAMP(select->cursor_col + col, 0, end_col);
|
||||||
|
select->cursor_row = MAX(select->cursor_row + row, 0);
|
||||||
|
/*select->cursor_row = CLAMP(select->cursor_row + row, 0, end_row);*/
|
||||||
|
|
||||||
|
update_selection(vte, select);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean key_press_cb(VteTerminal *vte, GdkEventKey *event, search_panel_info *info) {
|
gboolean key_press_cb(VteTerminal *vte, GdkEventKey *event, search_panel_info *info) {
|
||||||
|
@ -161,25 +169,27 @@ gboolean key_press_cb(VteTerminal *vte, GdkEventKey *event, search_panel_info *i
|
||||||
switch (event->keyval) {
|
switch (event->keyval) {
|
||||||
case GDK_KEY_Left:
|
case GDK_KEY_Left:
|
||||||
case GDK_KEY_h:
|
case GDK_KEY_h:
|
||||||
feed_str(vte, CSI "1D");
|
move(vte, &info->select, -1, 0);
|
||||||
break;
|
break;
|
||||||
case GDK_KEY_Down:
|
case GDK_KEY_Down:
|
||||||
case GDK_KEY_j:
|
case GDK_KEY_j:
|
||||||
feed_str(vte, CSI "1B");
|
move(vte, &info->select, 0, 1);
|
||||||
break;
|
break;
|
||||||
case GDK_KEY_Up:
|
case GDK_KEY_Up:
|
||||||
case GDK_KEY_k:
|
case GDK_KEY_k:
|
||||||
feed_str(vte, CSI "1A");
|
move(vte, &info->select, 0, -1);
|
||||||
break;
|
break;
|
||||||
case GDK_KEY_Right:
|
case GDK_KEY_Right:
|
||||||
case GDK_KEY_l:
|
case GDK_KEY_l:
|
||||||
feed_str(vte, CSI "1C");
|
move(vte, &info->select, 1, 0);
|
||||||
break;
|
break;
|
||||||
case GDK_KEY_asciicircum:
|
case GDK_KEY_asciicircum:
|
||||||
feed_str(vte, CSI "0G");
|
info->select.cursor_col = 0;
|
||||||
|
update_selection(vte, &info->select);
|
||||||
break;
|
break;
|
||||||
case GDK_KEY_dollar:
|
case GDK_KEY_dollar:
|
||||||
cursor_move_end_of_line(vte);
|
info->select.cursor_col = vte_terminal_get_column_count(vte) - 1;
|
||||||
|
update_selection(vte, &info->select);
|
||||||
break;
|
break;
|
||||||
case GDK_KEY_v:
|
case GDK_KEY_v:
|
||||||
toggle_visual(vte, &info->select, SELECT_VISUAL);
|
toggle_visual(vte, &info->select, SELECT_VISUAL);
|
||||||
|
@ -692,7 +702,7 @@ int main(int argc, char **argv) {
|
||||||
gtk_container_add(GTK_CONTAINER(overlay), vte);
|
gtk_container_add(GTK_CONTAINER(overlay), vte);
|
||||||
gtk_container_add(GTK_CONTAINER(window), overlay);
|
gtk_container_add(GTK_CONTAINER(window), overlay);
|
||||||
|
|
||||||
select_info select = {SELECT_OFF, 0, 0};
|
select_info select = {SELECT_OFF, 0, 0, 0, 0};
|
||||||
search_panel_info info = {vte, entry, alignment, OVERLAY_HIDDEN, select};
|
search_panel_info info = {vte, entry, alignment, OVERLAY_HIDDEN, select};
|
||||||
|
|
||||||
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
|
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
|
||||||
|
@ -700,7 +710,6 @@ int main(int argc, char **argv) {
|
||||||
g_signal_connect(vte, "key-press-event", G_CALLBACK(key_press_cb), &info);
|
g_signal_connect(vte, "key-press-event", G_CALLBACK(key_press_cb), &info);
|
||||||
g_signal_connect(entry, "key-press-event", G_CALLBACK(entry_key_press_cb), &info);
|
g_signal_connect(entry, "key-press-event", G_CALLBACK(entry_key_press_cb), &info);
|
||||||
g_signal_connect(overlay, "get-child-position", G_CALLBACK(position_overlay_cb), NULL);
|
g_signal_connect(overlay, "get-child-position", G_CALLBACK(position_overlay_cb), NULL);
|
||||||
g_signal_connect(vte, "cursor-moved", G_CALLBACK(cursor_moved_cb), &info.select);
|
|
||||||
|
|
||||||
if (clickable_url) {
|
if (clickable_url) {
|
||||||
int tag = vte_terminal_match_add_gregex(VTE_TERMINAL(vte),
|
int tag = vte_terminal_match_add_gregex(VTE_TERMINAL(vte),
|
||||||
|
|
Loading…
Reference in New Issue