From 5e8b322075377761b6942e875d0596fb493bffd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Diego=20Aur=C3=A9lio=20Mesquita?= Date: Fri, 20 Oct 2017 01:59:22 -0200 Subject: [PATCH] Implement overtype mode. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Diego Aurélio Mesquita --- src/browser.c | 2 +- src/global.c | 11 +++++++++++ src/nano.c | 32 +++++++++++++++++++++++++++++++- src/nano.h | 2 ++ src/proto.h | 6 ++++++ src/text.c | 36 ++++++++++++++++++++++++++++++++++++ src/winio.c | 33 +++++++++++++++++++++++++++++---- 7 files changed, 116 insertions(+), 6 deletions(-) diff --git a/src/browser.c b/src/browser.c index ac18b120..dbb97f61 100644 --- a/src/browser.c +++ b/src/browser.c @@ -628,7 +628,7 @@ void browser_refresh(void) /* If requested, put the cursor on the selected item and switch it on. */ if (ISSET(SHOW_CURSOR)) { wmove(edit, the_row, the_column); - curs_set(1); + unhide_cursor(); } wnoutrefresh(edit); diff --git a/src/global.c b/src/global.c index f1add3b0..bac68cb1 100644 --- a/src/global.c +++ b/src/global.c @@ -70,6 +70,9 @@ bool inhelp = FALSE; char *title = NULL; /* When not NULL: the title of the current help text. */ +bool overtype_mode = FALSE; + /* Whether we're in overtype mode */ + bool more_than_one = FALSE; /* Whether more than one buffer is or has been open. */ @@ -637,6 +640,8 @@ void shortcut_init(void) const char *nano_recordmacro_msg = N_("Start/stop recording a macro"); const char *nano_runmacro_msg = N_("Run the last recorded macro"); #endif + const char *nano_overtype_msg = + N_("Toggle overtype mode"); const char *nano_case_msg = N_("Toggle the case sensitivity of the search"); const char *nano_reverse_msg = @@ -923,6 +928,10 @@ void shortcut_init(void) add_to_funcs(do_enter, MMAIN, N_("Enter"), IFSCHELP(nano_enter_msg), BLANKAFTER, NOVIEW); + add_to_funcs(do_overtype, MMAIN, + N_("Overtype"), IFSCHELP(nano_overtype_msg), BLANKAFTER, + NOVIEW); + add_to_funcs(do_delete, MMAIN, N_("Delete"), IFSCHELP(nano_delete_msg), TOGETHER, NOVIEW); add_to_funcs(do_backspace, MMAIN, @@ -1560,6 +1569,8 @@ sc *strtosc(const char *input) else if (!strcasecmp(input, "redo")) s->scfunc = do_redo; #endif + else if (!strcasecmp(input, "overtype")) + s->scfunc = do_overtype; else if (!strcasecmp(input, "left") || !strcasecmp(input, "back")) s->scfunc = do_left; diff --git a/src/nano.c b/src/nano.c index b3888d9d..c8d8e62e 100644 --- a/src/nano.c +++ b/src/nano.c @@ -1791,6 +1791,9 @@ int do_mouse(void) void do_output(char *output, size_t output_len, bool allow_cntrls) { char onechar[MAXCHARLEN]; + char removedchar[MAXCHARLEN]; + size_t removed_len = 0; + char *removedchars = NULL; int char_len; size_t current_len = strlen(openfile->current->data); size_t i = 0; @@ -1825,6 +1828,30 @@ void do_output(char *output, size_t output_len, bool allow_cntrls) refresh_needed = TRUE; } + /* If in overtype mode, delete one char */ + if (overtype_mode && + openfile->current->data[openfile->current_x] != '\0' && + output[i] != '\n') { + int char_len = parse_mbchar(openfile->current->data + + openfile->current_x, removedchar, NULL); + size_t line_len = strlen(openfile->current->data + + openfile->current_x); + charmove(&openfile->current->data[openfile->current_x], + &openfile->current->data[openfile->current_x + char_len], + line_len - char_len + 1); + null_at(&openfile->current->data, openfile->current_x + + line_len - char_len); + openfile->totsize--; + + /* Copy removed char to buffer of removed chars */ + removedchars = charealloc(removedchars, + removed_len + char_len + 1); + null_at(&removedchars, removed_len + 1); + strncpy(removedchars + removed_len, removedchar, + char_len); + removed_len += char_len; + } + /* Make room for the new character and copy it into the line. */ openfile->current->data = charealloc(openfile->current->data, current_len + char_len + 1); @@ -1839,6 +1866,9 @@ void do_output(char *output, size_t output_len, bool allow_cntrls) #ifndef NANO_TINY add_undo(ADD); + if (overtype_mode) + add_undo_data(removedchars, removed_len); + free(removedchars); /* Note that current_x has not yet been incremented. */ if (openfile->mark_set && openfile->current == openfile->mark_begin && @@ -2479,7 +2509,7 @@ int main(int argc, char **argv) /* Create the three subwindows, based on the current screen dimensions. */ window_init(); - curs_set(0); + hide_cursor(); editwincols = COLS; diff --git a/src/nano.h b/src/nano.h index 7960d3be..e9149362 100644 --- a/src/nano.h +++ b/src/nano.h @@ -316,6 +316,8 @@ typedef struct undo { /* Where did this action begin or end. */ char *strdata; /* String type data we will use for copying the affected line back. */ + char *overtypedata; + /* String type data we will use for copying the overtyped text back. */ size_t wassize; /* The file size before the action. */ size_t newsize; diff --git a/src/proto.h b/src/proto.h index 2bc7fe7a..2cdb102c 100644 --- a/src/proto.h +++ b/src/proto.h @@ -49,6 +49,8 @@ extern bool have_palette; extern bool suppress_cursorpos; +extern bool overtype_mode; + extern message_type lastmessage; extern filestruct *pletion_line; @@ -447,6 +449,9 @@ void disable_flow_control(void); void enable_flow_control(void); void terminal_init(void); void unbound_key(int code); +void hide_cursor(void); +void unhide_cursor(void); +void do_overtype(void); int do_input(bool allow_funcs); #ifdef ENABLE_MOUSE int do_mouse(void); @@ -546,6 +551,7 @@ void do_enter(void); RETSIGTYPE cancel_command(int signal); bool execute_command(const char *command); void discard_until(const undo *thisitem, openfilestruct *thefile); +void add_undo_data(char *buffer, size_t buffer_len); void add_undo(undo_type action); void update_multiline_undo(ssize_t lineno, char *indentation); void update_undo(undo_type action); diff --git a/src/text.c b/src/text.c index d09d7c4f..a5b98c5c 100644 --- a/src/text.c +++ b/src/text.c @@ -745,6 +745,18 @@ void do_undo(void) free(f->data); f->data = data; goto_line_posx(u->lineno, u->begin); + + if (!u->overtypedata) + break; + + data = charalloc(strlen(f->data) + strlen(u->overtypedata) + 1); + strncpy(data, f->data, u->begin); + strcpy(&data[u->begin], u->overtypedata); + strcpy(&data[u->begin + strlen(u->overtypedata)], &f->data[u->begin]); + free(f->data); + f->data = data; + goto_line_posx(u->mark_begin_lineno, u->mark_begin_x); + break; case BACK: case DEL: @@ -1221,6 +1233,29 @@ void discard_until(const undo *thisitem, openfilestruct *thefile) thefile->last_action = OTHER; } +void add_undo_data(char *buffer, size_t buffer_len) +{ + size_t current_size = 0; + + if (buffer_len == 0) + return; + + if (!openfile->current_undo) + return; + + /* Adding data do overtyped data */ + if(openfile->current_undo->overtypedata) + current_size = strlen(openfile->current_undo->overtypedata); + + openfile->current_undo->overtypedata = charealloc( + openfile->current_undo->overtypedata, + current_size + buffer_len + 1); + null_at(&openfile->current_undo->overtypedata, + current_size + 1); + strncpy(openfile->current_undo->overtypedata + current_size, + buffer, buffer_len); +} + /* Add a new undo struct to the top of the current pile. */ void add_undo(undo_type action) { @@ -1259,6 +1294,7 @@ void add_undo(undo_type action) openfile->current_undo = u; } u->strdata = NULL; + u->overtypedata = NULL; u->cutbuffer = NULL; u->cutbottom = NULL; u->lineno = openfile->current->lineno; diff --git a/src/winio.c b/src/winio.c index dd717b4c..8bc5416a 100644 --- a/src/winio.c +++ b/src/winio.c @@ -113,6 +113,31 @@ void run_macro(void) } #endif /* !NANO_TINY */ +/* Hides cursor */ +void hide_cursor(void) +{ + curs_set(0); +} + +/* Unhides cursor considering overtype mode */ +void unhide_cursor(void) +{ + curs_set(overtype_mode ? 2 : 1); +} + +/* Toggles overtype mode */ +void do_overtype(void) +{ + overtype_mode = !overtype_mode; + + if (overtype_mode) + statusbar(_("Overtype mode enabled")); + else + statusbar(_("Overtype mode disabled")); + + unhide_cursor(); +} + /* Control character compatibility: * * - Ctrl-H is Backspace under ASCII, ANSI, VT100, and VT220. @@ -184,7 +209,7 @@ void get_key_buffer(WINDOW *win) doupdate(); if (reveal_cursor) - curs_set(1); + unhide_cursor(); /* Read in the first keystroke using whatever mode we're in. */ while (input == ERR) { @@ -197,7 +222,7 @@ void get_key_buffer(WINDOW *win) } #endif if (input == ERR && !waiting_mode) { - curs_set(0); + hide_cursor(); return; } @@ -209,7 +234,7 @@ void get_key_buffer(WINDOW *win) die(_("Too many errors from stdin")); } - curs_set(0); + hide_cursor(); /* Increment the length of the keystroke buffer, and save the value * of the keystroke at the end of it. */ @@ -1335,7 +1360,7 @@ int parse_escape_sequence(WINDOW *win, int kbinput) lastmessage = HUSH; if (currmenu == MMAIN) { place_the_cursor(); - curs_set(1); + unhide_cursor(); } } } -- 2.11.0