diff --git a/src/fe_modes.c b/src/fe_modes.c index 8d17a5f..a8527e7 100644 --- a/src/fe_modes.c +++ b/src/fe_modes.c @@ -122,6 +122,25 @@ void switch_mode(Mode_ID new_mode, State *state) { refresh_screen(); } +Mode_ID add_mod_canvas_mode(Mode_ID mode, int n) { + int mode_first = MODE_PICKER + 1; // beginning of selectable modes + int mode_list_end = LAST; // length of total mode list + + if (mode < mode_first || mode_list_end <= mode) { + logd("mode \"%s\" is not a canvas mode", mode); + return mode; + } + + // loop properly between mode_first and last mode + return ((mode - mode_first) + n) % (mode_list_end - mode_first) + mode_first; +} + +Mode_ID next_canvas_mode(Mode_ID mode) { return add_mod_canvas_mode(mode, 1); } + +Mode_ID previous_canvas_mode(Mode_ID mode) { + return add_mod_canvas_mode(mode, -1); +} + /* Handler run in frontend main loop. * * Interprets keypresses, manages global keys, and passes data to modes. @@ -148,12 +167,26 @@ int master_handler(State *state, WINDOW *canvas_win, WINDOW *status_win) { } else if (c == KEY_TAB) { // switching modes if (state->current_mode == MODE_PICKER && state->last_canvas_mode != MODE_PICKER) { - logd("Reverting to last mode\n"); - switch_mode(state->last_canvas_mode, state); + state->last_canvas_mode = next_canvas_mode(state->last_canvas_mode); + + // update mode_picker() to redraw the highlight + state->ch_in = c; + call_mode(state->current_mode, NEW_KEY, state); } else { switch_mode(MODE_PICKER, state); } return 0; + } else if (c == KEY_SHIFT_TAB) { + if (state->current_mode == MODE_PICKER && + state->last_canvas_mode != MODE_PICKER) { + state->last_canvas_mode = previous_canvas_mode(state->last_canvas_mode); + + // update mode_picker() to redraw the highlight + state->ch_in = c; + call_mode(state->current_mode, NEW_KEY, state); + } else { + switch_mode(MODE_PICKER, state); + } } else if (c == KEY_NPAGE || c == KEY_PPAGE || c == KEY_SLEFT || c == KEY_SRIGHT) { // shift view down/up/left/right @@ -271,18 +304,40 @@ int mode_picker(reason_t reason, State *state) { int num_left = sizeof(msg) / sizeof(char); char buffer[16]; + + // these variables are used to reverse-video the current canvas mode + int selected_x = 0; + int selected_num_char = -1; + bool found_selected = FALSE; for (int i = mode_first; i < mode_list_end; i++) { int num_to_write = snprintf(buffer, sizeof(buffer) / sizeof(char), - "%i: %s|", i - mode_first + 1, modes[i].name); + " [%i] %s ", i - mode_first + 1, modes[i].name); + if (num_left - num_to_write < 0) { break; } strncat(msg, buffer, num_to_write); num_left -= num_to_write; + + // Find the current canvas mode + if (state->last_canvas_mode == i) { + found_selected = TRUE; + selected_num_char = num_to_write; + } + + // Keep track of where the selected mode text starts in the window + if (!found_selected) { + selected_x += num_to_write; + } } print_mode_win(msg); + // Reverse-video the current canvas mode + if (selected_num_char != -1) { + highlight_mode_text(selected_x, selected_num_char); + } + // INTERPRET KEYS if (reason == NEW_KEY) { // only accept characters within the bounds of the list @@ -291,6 +346,9 @@ int mode_picker(reason_t reason, State *state) { Mode_ID new_mode = mode_first + state->ch_in - '1'; switch_mode(new_mode, state); return 0; + } else if (state->ch_in == KEY_ENTER) { + switch_mode(state->last_canvas_mode, state); + return 0; } } return 0; diff --git a/src/frontend.c b/src/frontend.c index 7276e61..41b2843 100644 --- a/src/frontend.c +++ b/src/frontend.c @@ -528,6 +528,12 @@ int print_mode_win(char *format, ...) { return res; } +/* Reverse-video the text starting at x in mode window, for num_ch characters. + */ +void highlight_mode_text(int x, int num_ch) { + mvwchgat(status_interface->mode_win, 0, x, num_ch, A_REVERSE, 0, NULL); +} + /* Update the info subwindow in status_win with relevant info. * * Prints the current mode, cursor coordinates, and canvas dimensions diff --git a/src/frontend.h b/src/frontend.h index 6558fc8..c61a46f 100644 --- a/src/frontend.h +++ b/src/frontend.h @@ -30,6 +30,7 @@ void destroy_win(); int print_msg_win(char *format, ...); int print_info_win(char *format, ...); +void highlight_mode_text(int x, int num_ch); int print_mode_win(char *format, ...); void update_info_win(const Mode_ID current_mode, const int x, const int y, const int w, const int h);