From 8df5c2f2159e3401e7367ca9aa1c25dbc9c0b55e Mon Sep 17 00:00:00 2001 From: Matthew Beaudouin-Lafon Date: Fri, 19 Apr 2019 16:27:52 -0400 Subject: [PATCH 1/4] first pass free line, featuring bad diagonals --- src/fe_modes.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++- src/fe_modes.h | 1 + src/frontend.c | 3 +- src/mode_id.h | 1 + 4 files changed, 126 insertions(+), 2 deletions(-) diff --git a/src/fe_modes.c b/src/fe_modes.c index 60e6649..14ae594 100644 --- a/src/fe_modes.c +++ b/src/fe_modes.c @@ -16,6 +16,7 @@ int (*mode_functions[])(State *, WINDOW *, WINDOW *) = { mode_picker, mode_insert, mode_pan, + mode_free_line, }; ////////////////////////////// @@ -114,7 +115,6 @@ int mode_pan(State *state, WINDOW *canvas_win, WINDOW *status_win) { state->current_mode = MODE_PICKER; return 0; } - if ((state->ch_in == KEY_LEFT) || (state->ch_in == KEY_RIGHT) || (state->ch_in == KEY_UP) || (state->ch_in == KEY_DOWN)) { view_pan_ch(state->ch_in, state->view); @@ -123,6 +123,127 @@ int mode_pan(State *state, WINDOW *canvas_win, WINDOW *status_win) { return 0; } +/* mode_free_line + * + * Move with arrows and insert character with keyboard. + */ +int mode_free_line(State *state, WINDOW *canvas_win, WINDOW *status_win) { + // handle mode changing + if (state->ch_in == KEY_TAB) { + // Clean up code + state->last_canvas_mode = MODE_INSERT; + + state->current_mode = MODE_PICKER; + return 0; + } + + // insert mode behavior + + if ((state->ch_in == KEY_LEFT) || (state->ch_in == KEY_RIGHT) || + (state->ch_in == KEY_UP) || (state->ch_in == KEY_DOWN)) { + int current_arrow = state->ch_in; + int last_arrow = state->last_arrow_direction; + + mvwaddch(canvas_win, cursor_y_to_canvas(state->cursor), + cursor_x_to_canvas(state->cursor), + free_line_arrows_to_char(last_arrow, current_arrow)); + + cursor_key_to_move(current_arrow, state->cursor, state->view); + state->last_arrow_direction = state->ch_in; + } + + // if ((state->ch_in == KEY_LEFT) || (state->ch_in == KEY_RIGHT) || + // (state->ch_in == KEY_UP) || (state->ch_in == KEY_DOWN)) { + // switch (state->ch_in) { + // case KEY_LEFT: + // cursor_move_left(state->cursor); + // mvwaddch(canvas_win, cursor_y_to_canvas(state->cursor), + // cursor_x_to_canvas(state->cursor), horizontal); + // break; + // case KEY_RIGHT: + // cursor_move_right(state->cursor); + // mvwaddch(canvas_win, cursor_y_to_canvas(state->cursor), + // cursor_x_to_canvas(state->cursor), horizontal); + // break; + // case KEY_UP: + // cursor_move_up(state->cursor); + // mvwaddch(canvas_win, cursor_y_to_canvas(state->cursor), + // cursor_x_to_canvas(state->cursor), vertical); + // break; + // case KEY_DOWN: + // cursor_move_down(state->cursor); + // mvwaddch(canvas_win, cursor_y_to_canvas(state->cursor), + // cursor_x_to_canvas(state->cursor), vertical); + // break; + // } + + // cursor_key_to_move(state->ch_in, state->cursor); + // state->last_arrow_direction = state->ch_in; + // } else { + // if (' ' <= state->ch_in && + // state->ch_in <= '~') { // check if ch is printable + // mvwaddch(canvas_win, cursor_y_to_canvas(state->cursor), + // cursor_x_to_canvas(state->cursor), state->ch_in); + // cursor_key_to_move(state->last_arrow_direction, state->cursor); + // } else if (state->ch_in == KEY_BACKSPACE) { + // cursor_key_to_move(cursor_opposite_dir(state->last_arrow_direction), + // state->cursor); + // mvwaddch(canvas_win, cursor_y_to_canvas(state->cursor), + // cursor_x_to_canvas(state->cursor), ' '); + // } else if (state->ch_in == KEY_DC) { + // mvwaddch(canvas_win, cursor_y_to_canvas(state->cursor), + // cursor_x_to_canvas(state->cursor), ' '); + // } else { + // // Print non-print characters to bottom left in status_win bar + // mvwaddch(status_win, 1, COLS - 3, state->ch_in); + // } + // } + // Move UI cursor to the right place + wmove(canvas_win, cursor_y_to_canvas(state->cursor), + cursor_x_to_canvas(state->cursor)); + + return 0; +} //////////////////////////// // SPECIFC MODE FUNCTIONS // //////////////////////////// + +/* free_line_arrows_to_char + * + * Takes the current and previous arrow directions, and returns the + * appropriate character, including diagonals. + * + * NOTE: Assumes that the input character is an arrow key + * + * Reference table: + * ^ v > < (current) + * + * ^ | | / \ + * v | | \ / + * > \ / - - + * < / \ - - + * (last) + */ +int free_line_arrows_to_char(int last_arrow, int current_arrow) { + char horizontal = '-'; + char vertical = '|'; + char diag_up = '/'; + char diag_down = '\\'; + + if ((last_arrow == KEY_UP || current_arrow == KEY_DOWN) && + (last_arrow == KEY_DOWN || current_arrow == KEY_UP)) { + // arrows are vertically parallel (top left quarter of truth table) + return vertical; + } else if ((last_arrow == KEY_LEFT || current_arrow == KEY_RIGHT) && + (last_arrow == KEY_RIGHT || current_arrow == KEY_LEFT)) { + // arrows are horizontally parallel (bottom right quarter of truth table) + return horizontal; + } else if ((last_arrow == KEY_UP && current_arrow == KEY_RIGHT) || + (last_arrow == KEY_DOWN && current_arrow == KEY_LEFT) || + (last_arrow == KEY_LEFT && current_arrow == KEY_DOWN) || + (last_arrow == KEY_RIGHT && current_arrow == KEY_UP)) { + return diag_up; + } else { + return diag_down; + } +} diff --git a/src/fe_modes.h b/src/fe_modes.h index 2c4563b..7d0d23f 100644 --- a/src/fe_modes.h +++ b/src/fe_modes.h @@ -7,6 +7,7 @@ int mode_picker(State *state, WINDOW *canvas_win, WINDOW *status_win); int mode_insert(State *state, WINDOW *canvas_win, WINDOW *status_win); int mode_pan(State *state, WINDOW *canvas_win, WINDOW *status_win); +int mode_free_line(State *state, WINDOW *canvas_win, WINDOW *status_win); extern int (*mode_functions[])(State *, WINDOW *, WINDOW *); diff --git a/src/frontend.c b/src/frontend.c index 73a22f9..61b0090 100644 --- a/src/frontend.c +++ b/src/frontend.c @@ -41,7 +41,7 @@ int main(int argc, char *argv[]) { (void)noecho(); /* don't print on getch() */ curs_set(2); - define_key("\r", KEY_ENTER); // Bind the key properly + define_key("\r", KEY_ENTER); // Bind the key properly if (has_colors()) { setup_colors(); @@ -72,6 +72,7 @@ int main(int argc, char *argv[]) { .ch_in = 0, .cursor = cursor, .current_mode = MODE_INSERT, + .last_arrow_direction = KEY_RIGHT, .last_canvas_mode = MODE_INSERT, .view = view, diff --git a/src/mode_id.h b/src/mode_id.h index 45f7c91..1104a70 100644 --- a/src/mode_id.h +++ b/src/mode_id.h @@ -9,6 +9,7 @@ typedef enum { MODE_PICKER, MODE_INSERT, MODE_PAN, + MODE_FREE_LINE, // ^ add your mode above LAST, // used to get number of elements From 9586a3adb7a980c0b7fb96f23255aa0b39a12d3b Mon Sep 17 00:00:00 2001 From: Matthew Beaudouin-Lafon Date: Tue, 23 Apr 2019 16:51:59 -0400 Subject: [PATCH 2/4] added last cursor position, doesn't work too well --- src/fe_modes.c | 97 +++++++++++++++++++++++++++----------------------- src/frontend.c | 5 ++- src/state.h | 1 + 3 files changed, 58 insertions(+), 45 deletions(-) diff --git a/src/fe_modes.c b/src/fe_modes.c index 14ae594..6a05015 100644 --- a/src/fe_modes.c +++ b/src/fe_modes.c @@ -39,6 +39,51 @@ Mode_ID return_to_canvas(int input_ch) { // State? return LAST; } +//////////////////////////// +// SPECIFC MODE FUNCTIONS // +//////////////////////////// + +/* free_line_arrows_to_char + * + * Takes the current and previous arrow directions, and returns the + * appropriate character, including diagonals. + * + * NOTE: Assumes that the input character is an arrow key + * + * Reference table: + * ^ v > < (current) + * + * ^ | | / \ + * v | | \ / + * > \ / - - + * < / \ - - + * (last) + */ +int free_line_arrows_to_char(int last_arrow, int current_arrow, + bool *erase_last_position) { + char horizontal = '-'; + char vertical = '|'; + char diag_up = '/'; + char diag_down = '\\'; + + if ((last_arrow == KEY_UP || current_arrow == KEY_DOWN) && + (last_arrow == KEY_DOWN || current_arrow == KEY_UP)) { + // arrows are vertically parallel (top left quarter of truth table) + return vertical; + } else if ((last_arrow == KEY_LEFT || current_arrow == KEY_RIGHT) && + (last_arrow == KEY_RIGHT || current_arrow == KEY_LEFT)) { + // arrows are horizontally parallel (bottom right quarter of truth table) + return horizontal; + } else if ((last_arrow == KEY_UP && current_arrow == KEY_RIGHT) || + (last_arrow == KEY_DOWN && current_arrow == KEY_LEFT) || + (last_arrow == KEY_LEFT && current_arrow == KEY_DOWN) || + (last_arrow == KEY_RIGHT && current_arrow == KEY_UP)) { + return diag_up; + } else { + return diag_down; + } +} + //////////////////// // MODE FUNCTIONS // //////////////////// @@ -144,9 +189,16 @@ int mode_free_line(State *state, WINDOW *canvas_win, WINDOW *status_win) { int current_arrow = state->ch_in; int last_arrow = state->last_arrow_direction; + bool should_erase_last_position = FALSE; mvwaddch(canvas_win, cursor_y_to_canvas(state->cursor), cursor_x_to_canvas(state->cursor), - free_line_arrows_to_char(last_arrow, current_arrow)); + free_line_arrows_to_char(last_arrow, current_arrow, + &should_erase_last_position)); + + if (should_erase_last_position) { + mvwaddch(canvas_win, cursor_y_to_canvas(state->last_cursor), + cursor_x_to_canvas(state->last_cursor), ' '); + } cursor_key_to_move(current_arrow, state->cursor, state->view); state->last_arrow_direction = state->ch_in; @@ -204,46 +256,3 @@ int mode_free_line(State *state, WINDOW *canvas_win, WINDOW *status_win) { return 0; } -//////////////////////////// -// SPECIFC MODE FUNCTIONS // -//////////////////////////// - -/* free_line_arrows_to_char - * - * Takes the current and previous arrow directions, and returns the - * appropriate character, including diagonals. - * - * NOTE: Assumes that the input character is an arrow key - * - * Reference table: - * ^ v > < (current) - * - * ^ | | / \ - * v | | \ / - * > \ / - - - * < / \ - - - * (last) - */ -int free_line_arrows_to_char(int last_arrow, int current_arrow) { - char horizontal = '-'; - char vertical = '|'; - char diag_up = '/'; - char diag_down = '\\'; - - if ((last_arrow == KEY_UP || current_arrow == KEY_DOWN) && - (last_arrow == KEY_DOWN || current_arrow == KEY_UP)) { - // arrows are vertically parallel (top left quarter of truth table) - return vertical; - } else if ((last_arrow == KEY_LEFT || current_arrow == KEY_RIGHT) && - (last_arrow == KEY_RIGHT || current_arrow == KEY_LEFT)) { - // arrows are horizontally parallel (bottom right quarter of truth table) - return horizontal; - } else if ((last_arrow == KEY_UP && current_arrow == KEY_RIGHT) || - (last_arrow == KEY_DOWN && current_arrow == KEY_LEFT) || - (last_arrow == KEY_LEFT && current_arrow == KEY_DOWN) || - (last_arrow == KEY_RIGHT && current_arrow == KEY_UP)) { - return diag_up; - } else { - return diag_down; - } -} diff --git a/src/frontend.c b/src/frontend.c index 61b0090..d3f3a5e 100644 --- a/src/frontend.c +++ b/src/frontend.c @@ -51,6 +51,7 @@ int main(int argc, char *argv[]) { status_win = create_status_win(); cursor = cursor_new(); + Cursor *last_cursor = cursor_new(); Canvas *canvas = canvas_new_blank(1000, 1000); view = view_new_startpos(canvas, 300, 300); @@ -76,6 +77,7 @@ int main(int argc, char *argv[]) { .last_arrow_direction = KEY_RIGHT, .last_canvas_mode = MODE_INSERT, .view = view, + .last_cursor = last_cursor, }; State *state = &new_state; @@ -84,8 +86,9 @@ int main(int argc, char *argv[]) { mode_functions[state->current_mode](state, canvas_win, status_win); - update_screen_size(canvas_win, status_win, cursor); + *(state->last_cursor) = *(state->cursor); + update_screen_size(canvas_win, status_win, cursor); refresh_screen(); } diff --git a/src/state.h b/src/state.h index 13858a5..3400713 100644 --- a/src/state.h +++ b/src/state.h @@ -19,6 +19,7 @@ typedef struct { Mode_ID last_canvas_mode; int last_arrow_direction; View *view; + Cursor *last_cursor; } State; #endif From 6cb68ca3e09fb8cf7479dc95fc9744b017a4c1f9 Mon Sep 17 00:00:00 2001 From: Matthew Beaudouin-Lafon Date: Tue, 23 Apr 2019 18:11:31 -0400 Subject: [PATCH 3/4] gave up on cleaning diagonal lines due to symmetry --- src/fe_modes.c | 63 +++++--------------------------------------------- src/frontend.c | 4 ++-- 2 files changed, 8 insertions(+), 59 deletions(-) diff --git a/src/fe_modes.c b/src/fe_modes.c index 6a05015..997a200 100644 --- a/src/fe_modes.c +++ b/src/fe_modes.c @@ -59,8 +59,7 @@ Mode_ID return_to_canvas(int input_ch) { // State? * < / \ - - * (last) */ -int free_line_arrows_to_char(int last_arrow, int current_arrow, - bool *erase_last_position) { +int free_line_arrows_to_char(int last_arrow, int current_arrow) { char horizontal = '-'; char vertical = '|'; char diag_up = '/'; @@ -190,67 +189,17 @@ int mode_free_line(State *state, WINDOW *canvas_win, WINDOW *status_win) { int last_arrow = state->last_arrow_direction; bool should_erase_last_position = FALSE; - mvwaddch(canvas_win, cursor_y_to_canvas(state->cursor), - cursor_x_to_canvas(state->cursor), - free_line_arrows_to_char(last_arrow, current_arrow, - &should_erase_last_position)); + front_setcharcursor(free_line_arrows_to_char(last_arrow, current_arrow)); - if (should_erase_last_position) { - mvwaddch(canvas_win, cursor_y_to_canvas(state->last_cursor), - cursor_x_to_canvas(state->last_cursor), ' '); - } + // *(state->last_cursor) = *(state->cursor); + state->last_cursor->x = state->cursor->x; + state->last_cursor->y = state->cursor->y; cursor_key_to_move(current_arrow, state->cursor, state->view); + state->last_arrow_direction = state->ch_in; } - // if ((state->ch_in == KEY_LEFT) || (state->ch_in == KEY_RIGHT) || - // (state->ch_in == KEY_UP) || (state->ch_in == KEY_DOWN)) { - // switch (state->ch_in) { - // case KEY_LEFT: - // cursor_move_left(state->cursor); - // mvwaddch(canvas_win, cursor_y_to_canvas(state->cursor), - // cursor_x_to_canvas(state->cursor), horizontal); - // break; - // case KEY_RIGHT: - // cursor_move_right(state->cursor); - // mvwaddch(canvas_win, cursor_y_to_canvas(state->cursor), - // cursor_x_to_canvas(state->cursor), horizontal); - // break; - // case KEY_UP: - // cursor_move_up(state->cursor); - // mvwaddch(canvas_win, cursor_y_to_canvas(state->cursor), - // cursor_x_to_canvas(state->cursor), vertical); - // break; - // case KEY_DOWN: - // cursor_move_down(state->cursor); - // mvwaddch(canvas_win, cursor_y_to_canvas(state->cursor), - // cursor_x_to_canvas(state->cursor), vertical); - // break; - // } - - // cursor_key_to_move(state->ch_in, state->cursor); - // state->last_arrow_direction = state->ch_in; - // } else { - // if (' ' <= state->ch_in && - // state->ch_in <= '~') { // check if ch is printable - // mvwaddch(canvas_win, cursor_y_to_canvas(state->cursor), - // cursor_x_to_canvas(state->cursor), state->ch_in); - // cursor_key_to_move(state->last_arrow_direction, state->cursor); - // } else if (state->ch_in == KEY_BACKSPACE) { - // cursor_key_to_move(cursor_opposite_dir(state->last_arrow_direction), - // state->cursor); - // mvwaddch(canvas_win, cursor_y_to_canvas(state->cursor), - // cursor_x_to_canvas(state->cursor), ' '); - // } else if (state->ch_in == KEY_DC) { - // mvwaddch(canvas_win, cursor_y_to_canvas(state->cursor), - // cursor_x_to_canvas(state->cursor), ' '); - // } else { - // // Print non-print characters to bottom left in status_win bar - // mvwaddch(status_win, 1, COLS - 3, state->ch_in); - // } - // } - // Move UI cursor to the right place wmove(canvas_win, cursor_y_to_canvas(state->cursor), cursor_x_to_canvas(state->cursor)); diff --git a/src/frontend.c b/src/frontend.c index d3f3a5e..c93fc1c 100644 --- a/src/frontend.c +++ b/src/frontend.c @@ -72,7 +72,7 @@ int main(int argc, char *argv[]) { State new_state = { .ch_in = 0, .cursor = cursor, - .current_mode = MODE_INSERT, + .current_mode = MODE_FREE_LINE, .last_arrow_direction = KEY_RIGHT, .last_canvas_mode = MODE_INSERT, @@ -86,7 +86,7 @@ int main(int argc, char *argv[]) { mode_functions[state->current_mode](state, canvas_win, status_win); - *(state->last_cursor) = *(state->cursor); + // *(state->last_cursor) = *(state->cursor); update_screen_size(canvas_win, status_win, cursor); refresh_screen(); From 13a7ed7245393fea3e34046cf54f1c3fb8d70aff Mon Sep 17 00:00:00 2001 From: Matthew Beaudouin-Lafon Date: Fri, 3 May 2019 14:35:53 -0400 Subject: [PATCH 4/4] clean up --- src/fe_modes.c | 9 +++++---- src/frontend.c | 3 ++- src/frontend.h | 1 + 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/fe_modes.c b/src/fe_modes.c index 997a200..b615732 100644 --- a/src/fe_modes.c +++ b/src/fe_modes.c @@ -181,23 +181,24 @@ int mode_free_line(State *state, WINDOW *canvas_win, WINDOW *status_win) { return 0; } - // insert mode behavior - + // free line behavior if ((state->ch_in == KEY_LEFT) || (state->ch_in == KEY_RIGHT) || (state->ch_in == KEY_UP) || (state->ch_in == KEY_DOWN)) { int current_arrow = state->ch_in; int last_arrow = state->last_arrow_direction; - bool should_erase_last_position = FALSE; front_setcharcursor(free_line_arrows_to_char(last_arrow, current_arrow)); - // *(state->last_cursor) = *(state->cursor); state->last_cursor->x = state->cursor->x; state->last_cursor->y = state->cursor->y; cursor_key_to_move(current_arrow, state->cursor, state->view); state->last_arrow_direction = state->ch_in; + } else if (state->ch_in == KEY_BACKSPACE) { + cursor_key_to_move(cursor_opposite_dir(state->last_arrow_direction), + state->cursor, state->view); + front_setcharcursor(' '); } wmove(canvas_win, cursor_y_to_canvas(state->cursor), diff --git a/src/frontend.c b/src/frontend.c index c93fc1c..13aa43c 100644 --- a/src/frontend.c +++ b/src/frontend.c @@ -72,7 +72,8 @@ int main(int argc, char *argv[]) { State new_state = { .ch_in = 0, .cursor = cursor, - .current_mode = MODE_FREE_LINE, + .current_mode = MODE_INSERT, + // .current_mode = MODE_FREE_LINE, .last_arrow_direction = KEY_RIGHT, .last_canvas_mode = MODE_INSERT, diff --git a/src/frontend.h b/src/frontend.h index 89b0a21..259f2ce 100644 --- a/src/frontend.h +++ b/src/frontend.h @@ -7,6 +7,7 @@ #define KEY_TAB '\t' #define KEY_SHIFT_TAB KEY_BTAB +// TODO: Understand delete/backspace on mac void finish(int sig); void setup_colors();