ref: 8362d2862d463b50e2ade72af4bf7c8f48a59ecc
parent: b9a6f09e3df40644e389b8dd0a2b7584f2f56a0b
author: cancel <cancel@cancel.fm>
date: Thu Jan 23 22:01:15 EST 2020
Change main event loop to use label/goto Save a level of nesting and mental bookkeeping. The control flow was already jumping within and outside of the loop, so we aren't making this any more complicated than it already was -- in fact, it's more simple, because now we also don't have to remember that we're in a 'for' loop.
--- a/tui_main.c
+++ b/tui_main.c
@@ -3469,9 +3469,8 @@
tui_restart_osc_udp_if_enabled(&t);
- WINDOW *cont_window = NULL;
-
- int key = KEY_RESIZE;
+ WINDOW *cont_window = NULL; // No window yet, wait for resize
+ int key = KEY_RESIZE; // Make first event a resize
wtimeout(stdscr, 0);
int cur_timeout = 0;
Usz bracketed_paste_starting_x = 0, bracketed_paste_y = 0,
@@ -3482,535 +3481,534 @@
// Send initial BPM
send_num_message(t.ged.oosc_dev, "/orca/bpm", (I32)t.ged.bpm);
- for (;;) {
- switch (key) {
- case ERR: {
- ged_do_stuff(&t.ged);
- bool drew_any = false;
- if (qnav_stack.stack_changed)
- drew_any = true;
- if (ged_is_draw_dirty(&t.ged) || drew_any) {
- werase(cont_window);
- ged_draw(&t.ged, cont_window, osoc(t.file_name), t.fancy_grid_dots,
- t.fancy_grid_rulers);
- wnoutrefresh(cont_window);
- drew_any = true;
- }
- int term_h, term_w;
- if (qnav_stack.count > 0) // todo lame, move this
- getmaxyx(stdscr, term_h, term_w);
- for (Usz i = 0; i < qnav_stack.count; ++i) {
- Qblock *qb = qnav_stack.blocks[i];
- if (qnav_stack.stack_changed) {
- bool is_frontmost = i == qnav_stack.count - 1;
- qblock_print_frame(qb, is_frontmost);
- switch (qb->tag) {
- case Qblock_type_qmsg:
- break;
- case Qblock_type_qmenu: {
- Qmenu *qm = qmenu_of(qb);
- qmenu_set_displayed_active(qm, is_frontmost);
- break;
- }
- case Qblock_type_qform:
- break;
- }
+ // Main loop. Process events as they arrive.
+event_loop:
+ switch (key) {
+ case ERR: {
+ ged_do_stuff(&t.ged);
+ bool drew_any = false;
+ if (qnav_stack.stack_changed)
+ drew_any = true;
+ if (ged_is_draw_dirty(&t.ged) || drew_any) {
+ werase(cont_window);
+ ged_draw(&t.ged, cont_window, osoc(t.file_name), t.fancy_grid_dots,
+ t.fancy_grid_rulers);
+ wnoutrefresh(cont_window);
+ drew_any = true;
+ }
+ int term_h, term_w;
+ if (qnav_stack.count > 0) // todo lame, move this
+ getmaxyx(stdscr, term_h, term_w);
+ for (Usz i = 0; i < qnav_stack.count; ++i) {
+ Qblock *qb = qnav_stack.blocks[i];
+ if (qnav_stack.stack_changed) {
+ bool is_frontmost = i == qnav_stack.count - 1;
+ qblock_print_frame(qb, is_frontmost);
+ switch (qb->tag) {
+ case Qblock_type_qmsg:
+ break;
+ case Qblock_type_qmenu: {
+ Qmenu *qm = qmenu_of(qb);
+ qmenu_set_displayed_active(qm, is_frontmost);
+ break;
}
- touchwin(qb->outer_window); // here? or after continue?
- if (term_h < 1 || term_w < 1)
- continue;
- int qbwin_h, qbwin_w;
- getmaxyx(qb->outer_window, qbwin_h, qbwin_w);
- int qbwin_endy = qb->y + qbwin_h;
- int qbwin_endx = qb->x + qbwin_w;
- if (qbwin_endy >= term_h)
- qbwin_endy = term_h - 1;
- if (qbwin_endx >= term_w)
- qbwin_endx = term_w - 1;
- if (qb->y >= qbwin_endy || qb->x >= qbwin_endx)
- continue;
- pnoutrefresh(qb->outer_window, 0, 0, qb->y, qb->x, qbwin_endy,
- qbwin_endx);
- drew_any = true;
- }
- qnav_stack.stack_changed = false;
- if (drew_any)
- doupdate();
- double secs_to_d = ged_secs_to_deadline(&t.ged);
- int new_timeout;
- // These values are tuned to work OK with the normal scheduling behavior
- // on Linux, Mac, and Windows. All of the usual caveats of trying to
- // guess what the scheduler will do apply.
- //
- // Of course, there's no guarantee about how the scheduler will work, so
- // if you are using a modified kernel or something, or the measurements
- // here are bad, or it's some OS that behaves differently than expected,
- // this won't be very good. But there's not really much we can do about
- // it, and it's better than doing nothing and burning up the CPU!
- if (t.strict_timing) {
- if (secs_to_d < ms_to_sec(0.5)) {
- new_timeout = 0;
- } else if (secs_to_d < ms_to_sec(1.5)) {
- new_timeout = 0;
- } else if (secs_to_d < ms_to_sec(3.0)) {
- new_timeout = 1;
- } else if (secs_to_d < ms_to_sec(5.0)) {
- new_timeout = 2;
- } else if (secs_to_d < ms_to_sec(7.0)) {
- new_timeout = 3;
- } else if (secs_to_d < ms_to_sec(9.0)) {
- new_timeout = 4;
- } else if (secs_to_d < ms_to_sec(11.0)) {
- new_timeout = 5;
- } else if (secs_to_d < ms_to_sec(13.0)) {
- new_timeout = 6;
- } else if (secs_to_d < ms_to_sec(15.0)) {
- new_timeout = 7;
- } else if (secs_to_d < ms_to_sec(25.0)) {
- new_timeout = 12;
- } else if (secs_to_d < ms_to_sec(50.0)) {
- new_timeout = 20;
- } else if (secs_to_d < ms_to_sec(100.0)) {
- new_timeout = 40;
- } else {
- new_timeout = 50;
+ case Qblock_type_qform:
+ break;
}
+ }
+ touchwin(qb->outer_window); // here? or after continue?
+ if (term_h < 1 || term_w < 1)
+ continue;
+ int qbwin_h, qbwin_w;
+ getmaxyx(qb->outer_window, qbwin_h, qbwin_w);
+ int qbwin_endy = qb->y + qbwin_h;
+ int qbwin_endx = qb->x + qbwin_w;
+ if (qbwin_endy >= term_h)
+ qbwin_endy = term_h - 1;
+ if (qbwin_endx >= term_w)
+ qbwin_endx = term_w - 1;
+ if (qb->y >= qbwin_endy || qb->x >= qbwin_endx)
+ continue;
+ pnoutrefresh(qb->outer_window, 0, 0, qb->y, qb->x, qbwin_endy,
+ qbwin_endx);
+ drew_any = true;
+ }
+ qnav_stack.stack_changed = false;
+ if (drew_any)
+ doupdate();
+ double secs_to_d = ged_secs_to_deadline(&t.ged);
+ int new_timeout;
+ // These values are tuned to work OK with the normal scheduling behavior
+ // on Linux, Mac, and Windows. All of the usual caveats of trying to
+ // guess what the scheduler will do apply.
+ //
+ // Of course, there's no guarantee about how the scheduler will work, so
+ // if you are using a modified kernel or something, or the measurements
+ // here are bad, or it's some OS that behaves differently than expected,
+ // this won't be very good. But there's not really much we can do about
+ // it, and it's better than doing nothing and burning up the CPU!
+ if (t.strict_timing) {
+ if (secs_to_d < ms_to_sec(0.5)) {
+ new_timeout = 0;
+ } else if (secs_to_d < ms_to_sec(1.5)) {
+ new_timeout = 0;
+ } else if (secs_to_d < ms_to_sec(3.0)) {
+ new_timeout = 1;
+ } else if (secs_to_d < ms_to_sec(5.0)) {
+ new_timeout = 2;
+ } else if (secs_to_d < ms_to_sec(7.0)) {
+ new_timeout = 3;
+ } else if (secs_to_d < ms_to_sec(9.0)) {
+ new_timeout = 4;
+ } else if (secs_to_d < ms_to_sec(11.0)) {
+ new_timeout = 5;
+ } else if (secs_to_d < ms_to_sec(13.0)) {
+ new_timeout = 6;
+ } else if (secs_to_d < ms_to_sec(15.0)) {
+ new_timeout = 7;
+ } else if (secs_to_d < ms_to_sec(25.0)) {
+ new_timeout = 12;
+ } else if (secs_to_d < ms_to_sec(50.0)) {
+ new_timeout = 20;
+ } else if (secs_to_d < ms_to_sec(100.0)) {
+ new_timeout = 40;
} else {
- if (secs_to_d < ms_to_sec(0.5)) {
- new_timeout = 0;
- } else if (secs_to_d < ms_to_sec(1.0)) {
- new_timeout = 0;
- } else if (secs_to_d < ms_to_sec(2.0)) {
- new_timeout = 1;
- } else if (secs_to_d < ms_to_sec(7.0)) {
- new_timeout = 2;
- } else if (secs_to_d < ms_to_sec(15.0)) {
- new_timeout = 5;
- } else if (secs_to_d < ms_to_sec(25.0)) {
- new_timeout = 10;
- } else if (secs_to_d < ms_to_sec(50.0)) {
- new_timeout = 20;
- } else if (secs_to_d < ms_to_sec(100.0)) {
- new_timeout = 40;
- } else {
- new_timeout = 50;
- }
+ new_timeout = 50;
}
- if (new_timeout != cur_timeout) {
- wtimeout(stdscr, new_timeout);
- cur_timeout = new_timeout;
+ } else {
+ if (secs_to_d < ms_to_sec(0.5)) {
+ new_timeout = 0;
+ } else if (secs_to_d < ms_to_sec(1.0)) {
+ new_timeout = 0;
+ } else if (secs_to_d < ms_to_sec(2.0)) {
+ new_timeout = 1;
+ } else if (secs_to_d < ms_to_sec(7.0)) {
+ new_timeout = 2;
+ } else if (secs_to_d < ms_to_sec(15.0)) {
+ new_timeout = 5;
+ } else if (secs_to_d < ms_to_sec(25.0)) {
+ new_timeout = 10;
+ } else if (secs_to_d < ms_to_sec(50.0)) {
+ new_timeout = 20;
+ } else if (secs_to_d < ms_to_sec(100.0)) {
+ new_timeout = 40;
+ } else {
+ new_timeout = 50;
+ }
+ }
+ if (new_timeout != cur_timeout) {
+ wtimeout(stdscr, new_timeout);
+ cur_timeout = new_timeout;
#if TIME_DEBUG
- spin_track_timeout = cur_timeout;
+ spin_track_timeout = cur_timeout;
#endif
- }
- goto next_getch;
}
- case KEY_RESIZE: {
- int term_h, term_w;
- getmaxyx(stdscr, term_h, term_w);
- assert(term_h >= 0 && term_w >= 0);
- int content_y = 0, content_x = 0;
- int content_h = term_h, content_w = term_w;
- if (t.hardmargin_y > 0 && term_h > t.hardmargin_y * 2 + 2) {
- content_y += t.hardmargin_y;
- content_h -= t.hardmargin_y * 2;
- }
- if (t.hardmargin_x > 0 && term_w > t.hardmargin_x * 2 + 2) {
- content_x += t.hardmargin_x;
- content_w -= t.hardmargin_x * 2;
- }
- bool remake_window = true;
+ goto next_getch;
+ }
+ case KEY_RESIZE: {
+ int term_h, term_w;
+ getmaxyx(stdscr, term_h, term_w);
+ assert(term_h >= 0 && term_w >= 0);
+ int content_y = 0, content_x = 0;
+ int content_h = term_h, content_w = term_w;
+ if (t.hardmargin_y > 0 && term_h > t.hardmargin_y * 2 + 2) {
+ content_y += t.hardmargin_y;
+ content_h -= t.hardmargin_y * 2;
+ }
+ if (t.hardmargin_x > 0 && term_w > t.hardmargin_x * 2 + 2) {
+ content_x += t.hardmargin_x;
+ content_w -= t.hardmargin_x * 2;
+ }
+ bool remake_window = true;
+ if (cont_window) {
+ int cwin_y, cwin_x, cwin_h, cwin_w;
+ getbegyx(cont_window, cwin_y, cwin_x);
+ getmaxyx(cont_window, cwin_h, cwin_w);
+ remake_window = cwin_y != content_y || cwin_x != content_x ||
+ cwin_h != content_h || cwin_w != content_w;
+ }
+ if (remake_window) {
if (cont_window) {
- int cwin_y, cwin_x, cwin_h, cwin_w;
- getbegyx(cont_window, cwin_y, cwin_x);
- getmaxyx(cont_window, cwin_h, cwin_w);
- remake_window = cwin_y != content_y || cwin_x != content_x ||
- cwin_h != content_h || cwin_w != content_w;
+ delwin(cont_window);
}
- if (remake_window) {
- if (cont_window) {
- delwin(cont_window);
- }
- wclear(stdscr);
- cont_window =
- derwin(stdscr, content_h, content_w, content_y, content_x);
- t.ged.is_draw_dirty = true;
+ wclear(stdscr);
+ cont_window = derwin(stdscr, content_h, content_w, content_y, content_x);
+ t.ged.is_draw_dirty = true;
+ }
+ // We might do this once soon after startup if the user specified neither
+ // a starting grid size or a file to open. See above (search KEY_RESIZE)
+ // for why this is kind of messy and hacky -- we'll be changing this
+ // again before too long, so we haven't made too much of an attempt to
+ // keep it non-messy.
+ if (should_autosize_grid) {
+ should_autosize_grid = false;
+ Usz new_field_h, new_field_w;
+ if (tui_suggest_nice_grid_size(&t, content_h, content_w, &new_field_h,
+ &new_field_w)) {
+ field_init_fill(&t.ged.field, (Usz)new_field_h, (Usz)new_field_w, '.');
+ mbuf_reusable_ensure_size(&t.ged.mbuf_r, new_field_h, new_field_w);
+ ged_make_cursor_visible(&t.ged);
+ } else {
+ field_init_fill(&t.ged.field, (Usz)init_grid_dim_y,
+ (Usz)init_grid_dim_x, '.');
}
- // We might do this once soon after startup if the user specified neither
- // a starting grid size or a file to open. See above (search KEY_RESIZE)
- // for why this is kind of messy and hacky -- we'll be changing this
- // again before too long, so we haven't made too much of an attempt to
- // keep it non-messy.
- if (should_autosize_grid) {
- should_autosize_grid = false;
- Usz new_field_h, new_field_w;
- if (tui_suggest_nice_grid_size(&t, content_h, content_w, &new_field_h,
- &new_field_w)) {
- field_init_fill(&t.ged.field, (Usz)new_field_h, (Usz)new_field_w,
- '.');
- mbuf_reusable_ensure_size(&t.ged.mbuf_r, new_field_h, new_field_w);
- ged_make_cursor_visible(&t.ged);
- } else {
- field_init_fill(&t.ged.field, (Usz)init_grid_dim_y,
- (Usz)init_grid_dim_x, '.');
- }
- }
- // OK to call this unconditionally -- deriving the sub-window areas is
- // more than a single comparison, and we don't want to split up or
- // duplicate the math and checks for it, so this routine will calculate
- // the stuff it needs to and then early-out if there's no further work.
- ged_set_window_size(&t.ged, content_h, content_w, t.softmargin_y,
- t.softmargin_x);
- goto next_getch;
}
+ // OK to call this unconditionally -- deriving the sub-window areas is
+ // more than a single comparison, and we don't want to split up or
+ // duplicate the math and checks for it, so this routine will calculate
+ // the stuff it needs to and then early-out if there's no further work.
+ ged_set_window_size(&t.ged, content_h, content_w, t.softmargin_y,
+ t.softmargin_x);
+ goto next_getch;
+ }
#ifndef FEAT_NOMOUSE
- case KEY_MOUSE: {
- MEVENT mevent;
- if (cont_window && getmouse(&mevent) == OK) {
- int win_y, win_x;
- int win_h, win_w;
- getbegyx(cont_window, win_y, win_x);
- getmaxyx(cont_window, win_h, win_w);
- int inwin_y = mevent.y - win_y;
- int inwin_x = mevent.x - win_x;
- if (inwin_y >= win_h)
- inwin_y = win_h - 1;
- if (inwin_y < 0)
- inwin_y = 0;
- if (inwin_x >= win_w)
- inwin_x = win_w - 1;
- if (inwin_x < 0)
- inwin_x = 0;
- ged_mouse_event(&t.ged, (Usz)inwin_y, (Usz)inwin_x, mevent.bstate);
- }
- goto next_getch;
+ case KEY_MOUSE: {
+ MEVENT mevent;
+ if (cont_window && getmouse(&mevent) == OK) {
+ int win_y, win_x;
+ int win_h, win_w;
+ getbegyx(cont_window, win_y, win_x);
+ getmaxyx(cont_window, win_h, win_w);
+ int inwin_y = mevent.y - win_y;
+ int inwin_x = mevent.x - win_x;
+ if (inwin_y >= win_h)
+ inwin_y = win_h - 1;
+ if (inwin_y < 0)
+ inwin_y = 0;
+ if (inwin_x >= win_w)
+ inwin_x = win_w - 1;
+ if (inwin_x < 0)
+ inwin_x = 0;
+ ged_mouse_event(&t.ged, (Usz)inwin_y, (Usz)inwin_x, mevent.bstate);
}
+ goto next_getch;
+ }
#endif
- }
+ }
- // If we have the menus open, we'll let the menus do what they want with
- // the input before the regular editor (which will be displayed
- // underneath.) The menus may tell us to quit, that they didn't do anything
- // with the input, or that they consumed the input and therefore we
- // shouldn't pass the input key to the rest of the editing system.
- switch (tui_drive_menus(&t, key)) {
- case Tui_menus_nothing:
- break;
- case Tui_menus_quit:
- goto quit;
- case Tui_menus_consumed_input:
+ // If we have the menus open, we'll let the menus do what they want with
+ // the input before the regular editor (which will be displayed
+ // underneath.) The menus may tell us to quit, that they didn't do anything
+ // with the input, or that they consumed the input and therefore we
+ // shouldn't pass the input key to the rest of the editing system.
+ switch (tui_drive_menus(&t, key)) {
+ case Tui_menus_nothing:
+ break;
+ case Tui_menus_quit:
+ goto quit;
+ case Tui_menus_consumed_input:
+ 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;
+ if (bracketed_paste_max_y > t.ged.ged_cursor.y)
+ t.ged.ged_cursor.h = bracketed_paste_max_y - t.ged.ged_cursor.y + 1;
+ if (bracketed_paste_max_x > t.ged.ged_cursor.x)
+ t.ged.ged_cursor.w = bracketed_paste_max_x - t.ged.ged_cursor.x + 1;
+ t.ged.needs_remarking = true;
+ t.ged.is_draw_dirty = true;
+ }
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;
- if (bracketed_paste_max_y > t.ged.ged_cursor.y)
- t.ged.ged_cursor.h = bracketed_paste_max_y - t.ged.ged_cursor.y + 1;
- if (bracketed_paste_max_x > t.ged.ged_cursor.x)
- t.ged.ged_cursor.w = bracketed_paste_max_x - t.ged.ged_cursor.x + 1;
- t.ged.needs_remarking = true;
- t.ged.is_draw_dirty = true;
- }
+ if (key == KEY_ENTER)
+ key = '\r';
+ if (key >= CHAR_MIN && key <= CHAR_MAX) {
+ if ((char)key == '\r' || (char)key == '\n') {
+ bracketed_paste_x = bracketed_paste_starting_x;
+ ++bracketed_paste_y;
goto next_getch;
}
- if (key == KEY_ENTER)
- key = '\r';
- if (key >= CHAR_MIN && key <= CHAR_MAX) {
- if ((char)key == '\r' || (char)key == '\n') {
- bracketed_paste_x = bracketed_paste_starting_x;
- ++bracketed_paste_y;
- goto next_getch;
+ if (key != ' ') {
+ char cleaned = (char)key;
+ if (!is_valid_glyph((Glyph)key))
+ cleaned = '.';
+ if (bracketed_paste_y < t.ged.field.height &&
+ bracketed_paste_x < t.ged.field.width) {
+ gbuffer_poke(t.ged.field.buffer, t.ged.field.height,
+ t.ged.field.width, bracketed_paste_y, bracketed_paste_x,
+ cleaned);
+ // Could move this out one level if we wanted the final selection
+ // size to reflect even the pasted area which didn't fit on the
+ // grid.
+ if (bracketed_paste_y > bracketed_paste_max_y)
+ bracketed_paste_max_y = bracketed_paste_y;
+ if (bracketed_paste_x > bracketed_paste_max_x)
+ bracketed_paste_max_x = bracketed_paste_x;
}
- if (key != ' ') {
- char cleaned = (char)key;
- if (!is_valid_glyph((Glyph)key))
- cleaned = '.';
- if (bracketed_paste_y < t.ged.field.height &&
- bracketed_paste_x < t.ged.field.width) {
- gbuffer_poke(t.ged.field.buffer, t.ged.field.height,
- t.ged.field.width, bracketed_paste_y,
- bracketed_paste_x, cleaned);
- // Could move this out one level if we wanted the final selection
- // size to reflect even the pasted area which didn't fit on the
- // grid.
- if (bracketed_paste_y > bracketed_paste_max_y)
- bracketed_paste_max_y = bracketed_paste_y;
- if (bracketed_paste_x > bracketed_paste_max_x)
- bracketed_paste_max_x = bracketed_paste_x;
- }
- }
- ++bracketed_paste_x;
}
- goto next_getch;
+ ++bracketed_paste_x;
}
+ goto next_getch;
+ }
- // Regular inputs when we're not in a menu and not in bracketed paste.
- 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 CTRL_PLUS('o'):
- push_open_form(osoc(t.file_name));
- break;
- case 127: // backspace in terminal.app, apparently
- case KEY_BACKSPACE:
- if (t.ged.input_mode == Ged_input_mode_append) {
- ged_dir_input(&t.ged, Ged_dir_left, 1);
- ged_input_character(&t.ged, '.');
- ged_dir_input(&t.ged, Ged_dir_left, 1);
- } else {
- ged_input_character(&t.ged, '.');
- }
- break;
- case CTRL_PLUS('z'):
- case CTRL_PLUS('u'):
- ged_input_cmd(&t.ged, Ged_input_cmd_undo);
- break;
- case '[':
- ged_adjust_rulers_relative(&t.ged, 0, -1);
- break;
- case ']':
- ged_adjust_rulers_relative(&t.ged, 0, 1);
- break;
- case '{':
- ged_adjust_rulers_relative(&t.ged, -1, 0);
- break;
- case '}':
- ged_adjust_rulers_relative(&t.ged, 1, 0);
- break;
- case '(':
- ged_resize_grid_relative(&t.ged, 0, -1);
- break;
- case ')':
- ged_resize_grid_relative(&t.ged, 0, 1);
- break;
- case '_':
- ged_resize_grid_relative(&t.ged, -1, 0);
- break;
- case '+':
- ged_resize_grid_relative(&t.ged, 1, 0);
- break;
- case '\r':
- case KEY_ENTER:
- // Currently unused. Formerly was the toggle for insert/append mode.
- break;
- case CTRL_PLUS('i'):
- case KEY_IC:
- ged_input_cmd(&t.ged, Ged_input_cmd_toggle_append_mode);
- break;
- case '/':
- // Formerly 'piano'/trigger mode toggle. We're repurposing it here to
- // input a '?' instead of a '/' because '?' opens the help guide, and it
- // might be a bad idea to take that away, since orca will take over the
- // TTY and may leave users confused. I know of at least 1 person who was
- // saved by pressing '?' after they didn't know what to do. Hmm.
- ged_input_character(&t.ged, '?');
- break;
- case '<':
- ged_adjust_bpm(&t.ged, -1);
- break;
- case '>':
- ged_adjust_bpm(&t.ged, 1);
- break;
- case CTRL_PLUS('f'):
- ged_input_cmd(&t.ged, Ged_input_cmd_step_forward);
- break;
- case CTRL_PLUS('e'):
- ged_input_cmd(&t.ged, Ged_input_cmd_toggle_show_event_list);
- break;
- case CTRL_PLUS('x'):
- ged_input_cmd(&t.ged, Ged_input_cmd_cut);
- try_send_to_gui_clipboard(&t.ged, &t.use_gui_cboard);
- break;
- case CTRL_PLUS('c'):
- ged_input_cmd(&t.ged, Ged_input_cmd_copy);
- try_send_to_gui_clipboard(&t.ged, &t.use_gui_cboard);
- break;
- case CTRL_PLUS('v'):
- if (t.use_gui_cboard) {
- bool added_hist =
- undo_history_push(&t.ged.undo_hist, &t.ged.field, t.ged.tick_num);
- Usz pasted_h, pasted_w;
- Cboard_error cberr = cboard_paste(
- t.ged.field.buffer, t.ged.field.height, t.ged.field.width,
- t.ged.ged_cursor.y, t.ged.ged_cursor.x, &pasted_h, &pasted_w);
- if (cberr) {
- if (added_hist)
- undo_history_pop(&t.ged.undo_hist, &t.ged.field, &t.ged.tick_num);
- switch (cberr) {
- case Cboard_error_none:
- break;
- case Cboard_error_unavailable:
- case Cboard_error_popen_failed:
- case Cboard_error_process_exit_error:
- break;
- }
- t.use_gui_cboard = false;
- ged_input_cmd(&t.ged, Ged_input_cmd_paste);
- } else {
- if (pasted_h > 0 && pasted_w > 0) {
- t.ged.ged_cursor.h = pasted_h;
- t.ged.ged_cursor.w = pasted_w;
- }
+ // Regular inputs when we're not in a menu and not in bracketed paste.
+ 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 CTRL_PLUS('o'):
+ push_open_form(osoc(t.file_name));
+ break;
+ case 127: // backspace in terminal.app, apparently
+ case KEY_BACKSPACE:
+ if (t.ged.input_mode == Ged_input_mode_append) {
+ ged_dir_input(&t.ged, Ged_dir_left, 1);
+ ged_input_character(&t.ged, '.');
+ ged_dir_input(&t.ged, Ged_dir_left, 1);
+ } else {
+ ged_input_character(&t.ged, '.');
+ }
+ break;
+ case CTRL_PLUS('z'):
+ case CTRL_PLUS('u'):
+ ged_input_cmd(&t.ged, Ged_input_cmd_undo);
+ break;
+ case '[':
+ ged_adjust_rulers_relative(&t.ged, 0, -1);
+ break;
+ case ']':
+ ged_adjust_rulers_relative(&t.ged, 0, 1);
+ break;
+ case '{':
+ ged_adjust_rulers_relative(&t.ged, -1, 0);
+ break;
+ case '}':
+ ged_adjust_rulers_relative(&t.ged, 1, 0);
+ break;
+ case '(':
+ ged_resize_grid_relative(&t.ged, 0, -1);
+ break;
+ case ')':
+ ged_resize_grid_relative(&t.ged, 0, 1);
+ break;
+ case '_':
+ ged_resize_grid_relative(&t.ged, -1, 0);
+ break;
+ case '+':
+ ged_resize_grid_relative(&t.ged, 1, 0);
+ break;
+ case '\r':
+ case KEY_ENTER:
+ // Currently unused. Formerly was the toggle for insert/append mode.
+ break;
+ case CTRL_PLUS('i'):
+ case KEY_IC:
+ ged_input_cmd(&t.ged, Ged_input_cmd_toggle_append_mode);
+ break;
+ case '/':
+ // Formerly 'piano'/trigger mode toggle. We're repurposing it here to
+ // input a '?' instead of a '/' because '?' opens the help guide, and it
+ // might be a bad idea to take that away, since orca will take over the
+ // TTY and may leave users confused. I know of at least 1 person who was
+ // saved by pressing '?' after they didn't know what to do. Hmm.
+ ged_input_character(&t.ged, '?');
+ break;
+ case '<':
+ ged_adjust_bpm(&t.ged, -1);
+ break;
+ case '>':
+ ged_adjust_bpm(&t.ged, 1);
+ break;
+ case CTRL_PLUS('f'):
+ ged_input_cmd(&t.ged, Ged_input_cmd_step_forward);
+ break;
+ case CTRL_PLUS('e'):
+ ged_input_cmd(&t.ged, Ged_input_cmd_toggle_show_event_list);
+ break;
+ case CTRL_PLUS('x'):
+ ged_input_cmd(&t.ged, Ged_input_cmd_cut);
+ try_send_to_gui_clipboard(&t.ged, &t.use_gui_cboard);
+ break;
+ case CTRL_PLUS('c'):
+ ged_input_cmd(&t.ged, Ged_input_cmd_copy);
+ try_send_to_gui_clipboard(&t.ged, &t.use_gui_cboard);
+ break;
+ case CTRL_PLUS('v'):
+ if (t.use_gui_cboard) {
+ bool added_hist =
+ undo_history_push(&t.ged.undo_hist, &t.ged.field, t.ged.tick_num);
+ Usz pasted_h, pasted_w;
+ Cboard_error cberr = cboard_paste(
+ t.ged.field.buffer, t.ged.field.height, t.ged.field.width,
+ t.ged.ged_cursor.y, t.ged.ged_cursor.x, &pasted_h, &pasted_w);
+ if (cberr) {
+ if (added_hist)
+ undo_history_pop(&t.ged.undo_hist, &t.ged.field, &t.ged.tick_num);
+ switch (cberr) {
+ case Cboard_error_none:
+ break;
+ case Cboard_error_unavailable:
+ case Cboard_error_popen_failed:
+ case Cboard_error_process_exit_error:
+ break;
}
- t.ged.needs_remarking = true;
- t.ged.is_draw_dirty = true;
- } else {
+ t.use_gui_cboard = false;
ged_input_cmd(&t.ged, Ged_input_cmd_paste);
- }
- break;
- case '\'':
- ged_input_cmd(&t.ged, Ged_input_cmd_toggle_selresize_mode);
- break;
- case '`':
- case '~':
- ged_input_cmd(&t.ged, Ged_input_cmd_toggle_slide_mode);
- break;
- case ' ':
- if (t.ged.input_mode == Ged_input_mode_append) {
- ged_input_character(&t.ged, '.');
} else {
- ged_input_cmd(&t.ged, Ged_input_cmd_toggle_play_pause);
+ if (pasted_h > 0 && pasted_w > 0) {
+ t.ged.ged_cursor.h = pasted_h;
+ t.ged.ged_cursor.w = pasted_w;
+ }
}
- break;
- case 27: // Escape
- // Check for escape sequences we're interested in that ncurses didn't
- // handle.
- if (bracketed_paste_sequence_getch_ungetch(stdscr) ==
- Bracketed_paste_sequence_begin) {
- is_in_bracketed_paste = true;
- undo_history_push(&t.ged.undo_hist, &t.ged.field, t.ged.tick_num);
- bracketed_paste_y = t.ged.ged_cursor.y;
- bracketed_paste_x = t.ged.ged_cursor.x;
- bracketed_paste_starting_x = bracketed_paste_x;
- bracketed_paste_max_y = bracketed_paste_y;
- bracketed_paste_max_x = bracketed_paste_x;
- break;
- }
- ged_input_cmd(&t.ged, Ged_input_cmd_escape);
- break;
-
- case 330: // delete?
+ t.ged.needs_remarking = true;
+ t.ged.is_draw_dirty = true;
+ } else {
+ ged_input_cmd(&t.ged, Ged_input_cmd_paste);
+ }
+ break;
+ case '\'':
+ ged_input_cmd(&t.ged, Ged_input_cmd_toggle_selresize_mode);
+ break;
+ case '`':
+ case '~':
+ ged_input_cmd(&t.ged, Ged_input_cmd_toggle_slide_mode);
+ break;
+ case ' ':
+ if (t.ged.input_mode == Ged_input_mode_append) {
ged_input_character(&t.ged, '.');
+ } else {
+ ged_input_cmd(&t.ged, Ged_input_cmd_toggle_play_pause);
+ }
+ break;
+ case 27: // Escape
+ // Check for escape sequences we're interested in that ncurses didn't
+ // handle.
+ if (bracketed_paste_sequence_getch_ungetch(stdscr) ==
+ Bracketed_paste_sequence_begin) {
+ is_in_bracketed_paste = true;
+ undo_history_push(&t.ged.undo_hist, &t.ged.field, t.ged.tick_num);
+ bracketed_paste_y = t.ged.ged_cursor.y;
+ bracketed_paste_x = t.ged.ged_cursor.x;
+ bracketed_paste_starting_x = bracketed_paste_x;
+ bracketed_paste_max_y = bracketed_paste_y;
+ bracketed_paste_max_x = bracketed_paste_x;
break;
+ }
+ ged_input_cmd(&t.ged, Ged_input_cmd_escape);
+ break;
- // Cursor movement
- case KEY_UP:
- case CTRL_PLUS('k'):
- ged_dir_input(&t.ged, Ged_dir_up, 1);
- break;
- case CTRL_PLUS('j'):
- case KEY_DOWN:
- ged_dir_input(&t.ged, Ged_dir_down, 1);
- break;
- case CTRL_PLUS('h'):
- case KEY_LEFT:
- ged_dir_input(&t.ged, Ged_dir_left, 1);
- break;
- case CTRL_PLUS('l'):
- case KEY_RIGHT:
- ged_dir_input(&t.ged, Ged_dir_right, 1);
- break;
+ case 330: // delete?
+ ged_input_character(&t.ged, '.');
+ break;
- // Selection size modification. These may not work in all terminals. (Only
- // tested in xterm so far.)
- case 337: // shift-up
- ged_modify_selection_size(&t.ged, -1, 0);
- break;
- case 336: // shift-down
- ged_modify_selection_size(&t.ged, 1, 0);
- break;
- case 393: // shift-left
- ged_modify_selection_size(&t.ged, 0, -1);
- break;
- case 402: // shift-right
- ged_modify_selection_size(&t.ged, 0, 1);
- break;
- case 567: // shift-control-up
- ged_modify_selection_size(&t.ged, -(int)t.ged.ruler_spacing_y, 0);
- break;
- case 526: // shift-control-down
- ged_modify_selection_size(&t.ged, (int)t.ged.ruler_spacing_y, 0);
- break;
- case 546: // shift-control-left
- ged_modify_selection_size(&t.ged, 0, -(int)t.ged.ruler_spacing_x);
- break;
- case 561: // shift-control-right
- ged_modify_selection_size(&t.ged, 0, (int)t.ged.ruler_spacing_x);
- break;
+ // Cursor movement
+ case KEY_UP:
+ case CTRL_PLUS('k'):
+ ged_dir_input(&t.ged, Ged_dir_up, 1);
+ break;
+ case CTRL_PLUS('j'):
+ case KEY_DOWN:
+ ged_dir_input(&t.ged, Ged_dir_down, 1);
+ break;
+ case CTRL_PLUS('h'):
+ case KEY_LEFT:
+ ged_dir_input(&t.ged, Ged_dir_left, 1);
+ break;
+ case CTRL_PLUS('l'):
+ case KEY_RIGHT:
+ ged_dir_input(&t.ged, Ged_dir_right, 1);
+ break;
- // Move cursor further if control is held
- case 566: // control-up
- ged_dir_input(&t.ged, Ged_dir_up, (int)t.ged.ruler_spacing_y);
- break;
- case 525: // control-down
- ged_dir_input(&t.ged, Ged_dir_down, (int)t.ged.ruler_spacing_y);
- break;
- case 545: // control-left
- ged_dir_input(&t.ged, Ged_dir_left, (int)t.ged.ruler_spacing_x);
- break;
- case 560: // control-right
- ged_dir_input(&t.ged, Ged_dir_right, (int)t.ged.ruler_spacing_x);
- break;
+ // Selection size modification. These may not work in all terminals. (Only
+ // tested in xterm so far.)
+ case 337: // shift-up
+ ged_modify_selection_size(&t.ged, -1, 0);
+ break;
+ case 336: // shift-down
+ ged_modify_selection_size(&t.ged, 1, 0);
+ break;
+ case 393: // shift-left
+ ged_modify_selection_size(&t.ged, 0, -1);
+ break;
+ case 402: // shift-right
+ ged_modify_selection_size(&t.ged, 0, 1);
+ break;
+ case 567: // shift-control-up
+ ged_modify_selection_size(&t.ged, -(int)t.ged.ruler_spacing_y, 0);
+ break;
+ case 526: // shift-control-down
+ ged_modify_selection_size(&t.ged, (int)t.ged.ruler_spacing_y, 0);
+ break;
+ case 546: // shift-control-left
+ ged_modify_selection_size(&t.ged, 0, -(int)t.ged.ruler_spacing_x);
+ break;
+ case 561: // shift-control-right
+ ged_modify_selection_size(&t.ged, 0, (int)t.ged.ruler_spacing_x);
+ break;
- // Slide selection on alt-arrow
- case 564: // alt-up
- ged_slide_selection(&t.ged, -1, 0);
- break;
- case 523: // alt-down
- ged_slide_selection(&t.ged, 1, 0);
- break;
- case 543: // alt-left
- ged_slide_selection(&t.ged, 0, -1);
- break;
- case 558: // alt-right
- ged_slide_selection(&t.ged, 0, 1);
- break;
+ // Move cursor further if control is held
+ case 566: // control-up
+ ged_dir_input(&t.ged, Ged_dir_up, (int)t.ged.ruler_spacing_y);
+ break;
+ case 525: // control-down
+ ged_dir_input(&t.ged, Ged_dir_down, (int)t.ged.ruler_spacing_y);
+ break;
+ case 545: // control-left
+ ged_dir_input(&t.ged, Ged_dir_left, (int)t.ged.ruler_spacing_x);
+ break;
+ case 560: // control-right
+ ged_dir_input(&t.ged, Ged_dir_right, (int)t.ged.ruler_spacing_x);
+ break;
- case CTRL_PLUS('d'):
- case KEY_F(1):
- push_main_menu();
- break;
- case '?':
- push_controls_msg();
- break;
- case CTRL_PLUS('g'):
- push_opers_guide_msg();
- break;
- case CTRL_PLUS('s'):
- // TODO duplicated with menu item code
- if (osolen(t.file_name) > 0) {
- try_save_with_msg(&t.ged.field, t.file_name);
- } else {
- push_save_as_form("");
- }
- break;
+ // Slide selection on alt-arrow
+ case 564: // alt-up
+ ged_slide_selection(&t.ged, -1, 0);
+ break;
+ case 523: // alt-down
+ ged_slide_selection(&t.ged, 1, 0);
+ break;
+ case 543: // alt-left
+ ged_slide_selection(&t.ged, 0, -1);
+ break;
+ case 558: // alt-right
+ ged_slide_selection(&t.ged, 0, 1);
+ break;
- default:
- if (key >= CHAR_MIN && key <= CHAR_MAX && is_valid_glyph((Glyph)key)) {
- ged_input_character(&t.ged, (char)key);
- }
+ case CTRL_PLUS('d'):
+ case KEY_F(1):
+ push_main_menu();
+ break;
+ case '?':
+ push_controls_msg();
+ break;
+ case CTRL_PLUS('g'):
+ push_opers_guide_msg();
+ break;
+ case CTRL_PLUS('s'):
+ // TODO duplicated with menu item code
+ if (osolen(t.file_name) > 0) {
+ try_save_with_msg(&t.ged.field, t.file_name);
+ } else {
+ push_save_as_form("");
+ }
+ break;
+
+ default:
+ if (key >= CHAR_MIN && key <= CHAR_MAX && is_valid_glyph((Glyph)key)) {
+ ged_input_character(&t.ged, (char)key);
+ }
#if 0
else {
fprintf(stderr, "Unknown key number: %d\n", key);
}
#endif
- break;
- }
- next_getch:
- key = wgetch(stdscr);
- if (cur_timeout != 0) {
- wtimeout(stdscr, 0);
- cur_timeout = 0;
- }
+ break;
}
+next_getch:
+ key = wgetch(stdscr);
+ if (cur_timeout != 0) {
+ wtimeout(stdscr, 0);
+ cur_timeout = 0;
+ }
+ goto event_loop;
quit:
ged_stop_all_sustained_notes(&t.ged);
qnav_deinit();