diff --git a/src/cut.c b/src/cut.c index 0341c598..fd72bf50 100644 --- a/src/cut.c +++ b/src/cut.c @@ -24,6 +24,189 @@ #include +/* Delete the character under the cursor. */ +void do_deletion(undo_type action) +{ +#ifndef NANO_TINY + size_t old_amount = 0; +#endif + + openfile->placewewant = xplustabs(); + + /* When in the middle of a line, delete the current character. */ + if (openfile->current->data[openfile->current_x] != '\0') { + int char_len = parse_mbchar(openfile->current->data + + openfile->current_x, NULL, NULL); + size_t line_len = strlen(openfile->current->data + + openfile->current_x); +#ifndef NANO_TINY + /* If the type of action changed or the cursor moved to a different + * line, create a new undo item, otherwise update the existing item. */ + if (action != openfile->last_action || + openfile->current->lineno != openfile->current_undo->lineno) + add_undo(action); + else + update_undo(action); + + if (ISSET(SOFTWRAP)) + old_amount = number_of_chunks_in(openfile->current); +#endif + /* Move the remainder of the line "in", over the current character. */ + charmove(&openfile->current->data[openfile->current_x], + &openfile->current->data[openfile->current_x + char_len], + line_len - char_len + 1); +#ifndef NANO_TINY + /* Adjust the mark if it is after the cursor on the current line. */ + if (openfile->mark == openfile->current && + openfile->mark_x > openfile->current_x) + openfile->mark_x -= char_len; +#endif + /* Otherwise, when not at end of buffer, join this line with the next. */ + } else if (openfile->current != openfile->filebot) { + filestruct *joining = openfile->current->next; + + /* If there is a magic line, and we're before it: don't eat it. */ + if (joining == openfile->filebot && openfile->current_x != 0 && + !ISSET(NO_NEWLINES)) { +#ifndef NANO_TINY + if (action == BACK) + add_undo(BACK); +#endif + return; + } + +#ifndef NANO_TINY + add_undo(action); +#endif + /* Add the contents of the next line to those of the current one. */ + openfile->current->data = charealloc(openfile->current->data, + strlen(openfile->current->data) + strlen(joining->data) + 1); + strcat(openfile->current->data, joining->data); + +#ifndef NANO_TINY + /* Adjust the mark if it was on the line that was "eaten". */ + if (openfile->mark == joining) { + openfile->mark = openfile->current; + openfile->mark_x += openfile->current_x; + } +#endif + unlink_node(joining); + renumber(openfile->current); + + /* Two lines were joined, so we need to refresh the screen. */ + refresh_needed = TRUE; + } else + /* We're at the end-of-file: nothing to do. */ + return; + + /* Adjust the file size, and remember it for a possible redo. */ + openfile->totsize--; +#ifndef NANO_TINY + openfile->current_undo->newsize = openfile->totsize; + + /* If the number of screen rows that a softwrapped line occupies + * has changed, we need a full refresh. */ + if (ISSET(SOFTWRAP) && refresh_needed == FALSE && + number_of_chunks_in(openfile->current) != old_amount) + refresh_needed = TRUE; +#endif + + set_modified(); +} + +/* Delete the character under the cursor. */ +void do_delete(void) +{ +#ifndef NANO_TINY + if (openfile->mark && ISSET(LET_THEM_ZAP)) + zap_text(); + else +#endif + do_deletion(DEL); +} + +/* Backspace over one character. That is, move the cursor left one + * character, and then delete the character under the cursor. */ +void do_backspace(void) +{ +#ifndef NANO_TINY + if (openfile->mark && ISSET(LET_THEM_ZAP)) + zap_text(); + else +#endif + if (openfile->current != openfile->fileage || openfile->current_x > 0) { + do_left(); + do_deletion(BACK); + } +} + +#ifndef NANO_TINY +/* Delete text from the cursor until the first start of a word to + * the right, or to the left when backward is true. */ +void do_cutword(bool backward) +{ + /* Remember the current cursor position. */ + filestruct *is_current = openfile->current; + size_t is_current_x = openfile->current_x; + + /* Remember where the cutbuffer is and then make it seem blank. */ + filestruct *is_cutbuffer = cutbuffer; + filestruct *is_cutbottom = cutbottom; + cutbuffer = NULL; + cutbottom = NULL; + + /* Move the cursor to a word start, to the left or to the right. + * If that word is on another line and the cursor was not already + * on the edge of the original line, then put the cursor on that + * edge instead, so that lines will not be joined unexpectedly. */ + if (backward) { + do_prev_word(ISSET(WORD_BOUNDS)); + if (openfile->current != is_current) { + if (is_current_x > 0) { + openfile->current = is_current; + openfile->current_x = 0; + } else + openfile->current_x = strlen(openfile->current->data); + } + } else { + do_next_word(FALSE, ISSET(WORD_BOUNDS)); + if (openfile->current != is_current && + is_current->data[is_current_x] != '\0') { + openfile->current = is_current; + openfile->current_x = strlen(is_current->data); + } + } + + /* Set the mark at the start of that word. */ + openfile->mark = openfile->current; + openfile->mark_x = openfile->current_x; + + /* Put the cursor back where it was, so an undo will put it there too. */ + openfile->current = is_current; + openfile->current_x = is_current_x; + + /* Now kill the marked region and a word is gone. */ + do_cut_text_void(); + + /* Discard the cut word and restore the cutbuffer. */ + free_filestruct(cutbuffer); + cutbuffer = is_cutbuffer; + cutbottom = is_cutbottom; +} + +/* Delete a word leftward. */ +void do_cut_prev_word(void) +{ + do_cutword(TRUE); +} + +/* Delete a word rightward. */ +void do_cut_next_word(void) +{ + do_cutword(FALSE); +} +#endif /* !NANO_TINY */ + /* If we aren't on the last line of the file, move all the text of the * current line, plus the newline at the end, into the cutbuffer. If we * are, move all of the text of the current line into the cutbuffer. In diff --git a/src/proto.h b/src/proto.h index 65890134..b7f9f500 100644 --- a/src/proto.h +++ b/src/proto.h @@ -243,7 +243,11 @@ void precalc_multicolorinfo(void); #endif /* Most functions in cut.c. */ +void do_delete(void); +void do_backspace(void); #ifndef NANO_TINY +void do_cut_prev_word(void); +void do_cut_next_word(void); void cut_marked(bool *right_side_up); #endif void do_cut_text(bool copy_text, bool marked, bool cut_till_eof, bool append); @@ -492,12 +496,6 @@ void do_find_bracket(void); #ifndef NANO_TINY void do_mark(void); #endif -void do_delete(void); -void do_backspace(void); -#ifndef NANO_TINY -void do_cut_prev_word(void); -void do_cut_next_word(void); -#endif void do_tab(void); #ifndef NANO_TINY void do_indent(void); diff --git a/src/text.c b/src/text.c index c6de624a..e0e52eb0 100644 --- a/src/text.c +++ b/src/text.c @@ -76,189 +76,6 @@ char *invocation_error(const char *name) } #endif -/* Delete the character under the cursor. */ -void do_deletion(undo_type action) -{ -#ifndef NANO_TINY - size_t old_amount = 0; -#endif - - openfile->placewewant = xplustabs(); - - /* When in the middle of a line, delete the current character. */ - if (openfile->current->data[openfile->current_x] != '\0') { - int char_len = parse_mbchar(openfile->current->data + - openfile->current_x, NULL, NULL); - size_t line_len = strlen(openfile->current->data + - openfile->current_x); -#ifndef NANO_TINY - /* If the type of action changed or the cursor moved to a different - * line, create a new undo item, otherwise update the existing item. */ - if (action != openfile->last_action || - openfile->current->lineno != openfile->current_undo->lineno) - add_undo(action); - else - update_undo(action); - - if (ISSET(SOFTWRAP)) - old_amount = number_of_chunks_in(openfile->current); -#endif - /* Move the remainder of the line "in", over the current character. */ - charmove(&openfile->current->data[openfile->current_x], - &openfile->current->data[openfile->current_x + char_len], - line_len - char_len + 1); -#ifndef NANO_TINY - /* Adjust the mark if it is after the cursor on the current line. */ - if (openfile->mark == openfile->current && - openfile->mark_x > openfile->current_x) - openfile->mark_x -= char_len; -#endif - /* Otherwise, when not at end of buffer, join this line with the next. */ - } else if (openfile->current != openfile->filebot) { - filestruct *joining = openfile->current->next; - - /* If there is a magic line, and we're before it: don't eat it. */ - if (joining == openfile->filebot && openfile->current_x != 0 && - !ISSET(NO_NEWLINES)) { -#ifndef NANO_TINY - if (action == BACK) - add_undo(BACK); -#endif - return; - } - -#ifndef NANO_TINY - add_undo(action); -#endif - /* Add the contents of the next line to those of the current one. */ - openfile->current->data = charealloc(openfile->current->data, - strlen(openfile->current->data) + strlen(joining->data) + 1); - strcat(openfile->current->data, joining->data); - -#ifndef NANO_TINY - /* Adjust the mark if it was on the line that was "eaten". */ - if (openfile->mark == joining) { - openfile->mark = openfile->current; - openfile->mark_x += openfile->current_x; - } -#endif - unlink_node(joining); - renumber(openfile->current); - - /* Two lines were joined, so we need to refresh the screen. */ - refresh_needed = TRUE; - } else - /* We're at the end-of-file: nothing to do. */ - return; - - /* Adjust the file size, and remember it for a possible redo. */ - openfile->totsize--; -#ifndef NANO_TINY - openfile->current_undo->newsize = openfile->totsize; - - /* If the number of screen rows that a softwrapped line occupies - * has changed, we need a full refresh. */ - if (ISSET(SOFTWRAP) && refresh_needed == FALSE && - number_of_chunks_in(openfile->current) != old_amount) - refresh_needed = TRUE; -#endif - - set_modified(); -} - -/* Delete the character under the cursor. */ -void do_delete(void) -{ -#ifndef NANO_TINY - if (openfile->mark && ISSET(LET_THEM_ZAP)) - zap_text(); - else -#endif - do_deletion(DEL); -} - -/* Backspace over one character. That is, move the cursor left one - * character, and then delete the character under the cursor. */ -void do_backspace(void) -{ -#ifndef NANO_TINY - if (openfile->mark && ISSET(LET_THEM_ZAP)) - zap_text(); - else -#endif - if (openfile->current != openfile->fileage || openfile->current_x > 0) { - do_left(); - do_deletion(BACK); - } -} - -#ifndef NANO_TINY -/* Delete text from the cursor until the first start of a word to - * the right, or to the left when backward is true. */ -void do_cutword(bool backward) -{ - /* Remember the current cursor position. */ - filestruct *is_current = openfile->current; - size_t is_current_x = openfile->current_x; - - /* Remember where the cutbuffer is and then make it seem blank. */ - filestruct *is_cutbuffer = cutbuffer; - filestruct *is_cutbottom = cutbottom; - cutbuffer = NULL; - cutbottom = NULL; - - /* Move the cursor to a word start, to the left or to the right. - * If that word is on another line and the cursor was not already - * on the edge of the original line, then put the cursor on that - * edge instead, so that lines will not be joined unexpectedly. */ - if (backward) { - do_prev_word(ISSET(WORD_BOUNDS)); - if (openfile->current != is_current) { - if (is_current_x > 0) { - openfile->current = is_current; - openfile->current_x = 0; - } else - openfile->current_x = strlen(openfile->current->data); - } - } else { - do_next_word(FALSE, ISSET(WORD_BOUNDS)); - if (openfile->current != is_current && - is_current->data[is_current_x] != '\0') { - openfile->current = is_current; - openfile->current_x = strlen(is_current->data); - } - } - - /* Set the mark at the start of that word. */ - openfile->mark = openfile->current; - openfile->mark_x = openfile->current_x; - - /* Put the cursor back where it was, so an undo will put it there too. */ - openfile->current = is_current; - openfile->current_x = is_current_x; - - /* Now kill the marked region and a word is gone. */ - do_cut_text_void(); - - /* Discard the cut word and restore the cutbuffer. */ - free_filestruct(cutbuffer); - cutbuffer = is_cutbuffer; - cutbottom = is_cutbottom; -} - -/* Delete a word leftward. */ -void do_cut_prev_word(void) -{ - do_cutword(TRUE); -} - -/* Delete a word rightward. */ -void do_cut_next_word(void) -{ - do_cutword(FALSE); -} -#endif /* !NANO_TINY */ - /* Insert a tab. If the TABS_TO_SPACES flag is set, insert the number * of spaces that a tab would normally take up. */ void do_tab(void)