Browse Source

Clean up bracketed paste control flow

master
cancel 5 years ago
parent
commit
d34b159e55
  1. 193
      tui_main.c

193
tui_main.c

@ -2145,6 +2145,43 @@ bool read_nxn_or_n(char const* str, int* out_a, int* out_b) {
return false; return false;
} }
typedef enum {
Bracketed_paste_sequence_none = 0,
Bracketed_paste_sequence_begin,
Bracketed_paste_sequence_end,
} Bracketed_paste_sequence;
Bracketed_paste_sequence bracketed_paste_sequence_getch_ungetch(WINDOW* win) {
int esc1 = wgetch(win);
if (esc1 == '[') {
int esc2 = wgetch(win);
if (esc2 == '2') {
int esc3 = wgetch(win);
if (esc3 == '0') {
int esc4 = wgetch(win);
// Start or end of bracketed paste
if (esc4 == '0' || esc4 == '1') {
int esc5 = wgetch(win);
if (esc5 == '~') {
switch (esc4) {
case '0':
return Bracketed_paste_sequence_begin;
case '1':
return Bracketed_paste_sequence_end;
}
}
ungetch(esc5);
}
ungetch(esc4);
}
ungetch(esc3);
}
ungetch(esc2);
}
ungetch(esc1);
return Bracketed_paste_sequence_none;
}
int main(int argc, char** argv) { int main(int argc, char** argv) {
static struct option tui_options[] = { static struct option tui_options[] = {
{"margins", required_argument, 0, Argopt_margins}, {"margins", required_argument, 0, Argopt_margins},
@ -2647,12 +2684,12 @@ int main(int argc, char** argv) {
goto next_getch; goto next_getch;
} }
#endif #endif
case CTRL_PLUS('q'):
goto quit;
} }
Qblock* qb = qnav_top_block(); Qblock* qb = qnav_top_block();
if (qb) { if (qb) {
if (key == CTRL_PLUS('q'))
goto quit;
switch (qb->tag) { switch (qb->tag) {
case Qblock_type_qmsg: { case Qblock_type_qmsg: {
Qmsg* qm = qmsg_of(qb); Qmsg* qm = qmsg_of(qb);
@ -2811,7 +2848,64 @@ int main(int argc, char** argv) {
goto next_getch; goto next_getch;
} }
// If this key input is intended to reach the grid, check to see if we're
// in bracketed paste and use alternate 'filtered input for characters'
// mode. We'll ignore most control sequences here.
if (is_in_bracketed_paste) {
if (key == 27 /* escape */) {
if (bracketed_paste_sequence_getch_ungetch(stdscr) ==
Bracketed_paste_sequence_end) {
is_in_bracketed_paste = false;
ged_state.ged_cursor.y = bracketed_paste_starting_y;
ged_state.ged_cursor.x = bracketed_paste_starting_x;
ged_cursor_confine(&ged_state.ged_cursor, ged_state.field.height,
ged_state.field.width);
ged_state.needs_remarking = true;
ged_state.is_draw_dirty = true;
}
goto next_getch;
}
if (key == KEY_ENTER)
key = '\r';
if (key >= CHAR_MIN && key <= CHAR_MAX) {
if ((char)key == '\r' || (char)key == '\n') {
if (bracketed_paste_went_off_bottom_edge)
goto next_getch;
bracketed_paste_went_off_right_edge = false;
ged_state.ged_cursor.x = bracketed_paste_starting_x;
++ged_state.ged_cursor.y; // TODO overflow check
if (ged_state.ged_cursor.y >= ged_state.field.height)
bracketed_paste_went_off_bottom_edge = true;
ged_cursor_confine(&ged_state.ged_cursor, ged_state.field.height,
ged_state.field.width);
goto next_getch;
}
if (bracketed_paste_went_off_right_edge ||
bracketed_paste_went_off_bottom_edge)
goto next_getch;
if (key != ' ') {
char cleaned = (char)key;
if (!is_valid_glyph((Glyph)key))
cleaned = '.';
gbuffer_poke(ged_state.field.buffer, ged_state.field.height,
ged_state.field.width, ged_state.ged_cursor.y,
ged_state.ged_cursor.x, cleaned);
}
++ged_state.ged_cursor.x; // TODO overflow check
if (ged_state.ged_cursor.x >= ged_state.field.width)
bracketed_paste_went_off_right_edge = true;
ged_cursor_confine(&ged_state.ged_cursor, ged_state.field.height,
ged_state.field.width);
}
goto next_getch;
}
// Regular inputs when we're not in a menu and not in bracketed paste.
switch (key) { switch (key) {
// Checking again for 'quit' here, because it's only listened for if we're
// in the menus or *not* in bracketed paste mode.
case CTRL_PLUS('q'):
goto quit;
case KEY_UP: case KEY_UP:
case CTRL_PLUS('k'): case CTRL_PLUS('k'):
ged_dir_input(&ged_state, Ged_dir_up, 1); ged_dir_input(&ged_state, Ged_dir_up, 1);
@ -2868,8 +2962,6 @@ int main(int argc, char** argv) {
break; break;
case '\r': case '\r':
case KEY_ENTER: case KEY_ENTER:
if (is_in_bracketed_paste)
goto newline_in_bracketed_paste;
// Currently unused. Formerly was the toggle for insert/append mode. // Currently unused. Formerly was the toggle for insert/append mode.
break; break;
case CTRL_PLUS('i'): case CTRL_PLUS('i'):
@ -2904,8 +2996,6 @@ int main(int argc, char** argv) {
ged_input_cmd(&ged_state, Ged_input_cmd_toggle_selresize_mode); ged_input_cmd(&ged_state, Ged_input_cmd_toggle_selresize_mode);
break; break;
case ' ': case ' ':
if (is_in_bracketed_paste)
goto key_input_in_bracketed_paste;
if (ged_state.input_mode == Ged_input_mode_append) { if (ged_state.input_mode == Ged_input_mode_append) {
ged_input_character(&ged_state, '.'); ged_input_character(&ged_state, '.');
} else { } else {
@ -2915,54 +3005,18 @@ int main(int argc, char** argv) {
case 27: { // Escape case 27: { // Escape
// Check for escape sequences we're interested in that ncurses didn't // Check for escape sequences we're interested in that ncurses didn't
// handle. // handle.
int esc1 = wgetch(stdscr); if (bracketed_paste_sequence_getch_ungetch(stdscr) ==
if (esc1 == '[') { Bracketed_paste_sequence_begin) {
int esc2 = wgetch(stdscr); is_in_bracketed_paste = true;
if (esc2 == '2') { bracketed_paste_went_off_right_edge = false;
int esc3 = wgetch(stdscr); bracketed_paste_went_off_bottom_edge = false;
if (esc3 == '0') { undo_history_push(&ged_state.undo_hist, &ged_state.field,
int esc4 = wgetch(stdscr); ged_state.tick_num);
// Start or end of bracketed paste bracketed_paste_starting_y = ged_state.ged_cursor.y;
if (esc4 == '0' || esc4 == '1') { bracketed_paste_starting_x = ged_state.ged_cursor.x;
int esc5 = wgetch(stdscr); break;
if (esc5 == '~') {
switch (esc4) {
case '0': // Enter bracketed paste
if (!is_in_bracketed_paste) {
is_in_bracketed_paste = true;
bracketed_paste_went_off_right_edge = false;
bracketed_paste_went_off_bottom_edge = false;
undo_history_push(&ged_state.undo_hist, &ged_state.field,
ged_state.tick_num);
bracketed_paste_starting_y = ged_state.ged_cursor.y;
bracketed_paste_starting_x = ged_state.ged_cursor.x;
}
goto finished_escape_sequence;
case '1': // End bracketed paste
if (is_in_bracketed_paste) {
is_in_bracketed_paste = false;
ged_state.ged_cursor.y = bracketed_paste_starting_y;
ged_state.ged_cursor.x = bracketed_paste_starting_x;
ged_cursor_confine(&ged_state.ged_cursor,
ged_state.field.height,
ged_state.field.width);
ged_state.needs_remarking = true;
ged_state.is_draw_dirty = true;
}
goto finished_escape_sequence;
}
}
ungetch(esc5);
}
ungetch(esc4);
}
ungetch(esc3);
}
ungetch(esc2);
} }
ungetch(esc1);
ged_input_cmd(&ged_state, Ged_input_cmd_escape); ged_input_cmd(&ged_state, Ged_input_cmd_escape);
finished_escape_sequence:;
} break; } break;
// Selection size modification. These may not work in all terminals. (Only // Selection size modification. These may not work in all terminals. (Only
@ -3039,41 +3093,6 @@ int main(int argc, char** argv) {
break; break;
default: default:
if (is_in_bracketed_paste) {
key_input_in_bracketed_paste:
if (key >= CHAR_MIN && key <= CHAR_MAX) {
if ((char)key == '\n') {
newline_in_bracketed_paste:
if (bracketed_paste_went_off_bottom_edge)
break;
bracketed_paste_went_off_right_edge = false;
ged_state.ged_cursor.x = bracketed_paste_starting_x;
++ged_state.ged_cursor.y; // TODO overflow check
if (ged_state.ged_cursor.y >= ged_state.field.height)
bracketed_paste_went_off_bottom_edge = true;
ged_cursor_confine(&ged_state.ged_cursor, ged_state.field.height,
ged_state.field.width);
break;
}
if (bracketed_paste_went_off_right_edge ||
bracketed_paste_went_off_bottom_edge)
break;
if (key != ' ') {
char cleaned = (char)key;
if (!is_valid_glyph((Glyph)key))
cleaned = '.';
gbuffer_poke(ged_state.field.buffer, ged_state.field.height,
ged_state.field.width, ged_state.ged_cursor.y,
ged_state.ged_cursor.x, cleaned);
}
++ged_state.ged_cursor.x; // TODO overflow check
if (ged_state.ged_cursor.x >= ged_state.field.width)
bracketed_paste_went_off_right_edge = true;
ged_cursor_confine(&ged_state.ged_cursor, ged_state.field.height,
ged_state.field.width);
}
break;
}
if (key >= CHAR_MIN && key <= CHAR_MAX && is_valid_glyph((Glyph)key)) { if (key >= CHAR_MIN && key <= CHAR_MAX && is_valid_glyph((Glyph)key)) {
ged_input_character(&ged_state, (char)key); ged_input_character(&ged_state, (char)key);
} }

Loading…
Cancel
Save