keyboard-select with scrollback support

note: currently doesn't draw a visible selection cursor
This commit is contained in:
Daniel Micay 2012-07-09 03:10:08 -04:00
parent eefb56f24c
commit 131cb20584
1 changed files with 27 additions and 18 deletions

View File

@ -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),