From: Adam Rogoyski Date: Wed, 7 Jun 2000 03:56:54 +0000 (+0000) Subject: add experimental new do_wrap() and check_wrap() to imitate pico a little closer. X-Git-Tag: v0.9.11~36 X-Git-Url: https://git.wh0rd.org/?a=commitdiff_plain;h=77f36de7e9554f887e7680c1c97642ff0b588955;p=nano.git add experimental new do_wrap() and check_wrap() to imitate pico a little closer. Please try this and let me know if it doesn't work! git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@9 35c25a1d-7b9e-4130-9fde-d3aeb78583b8 --- diff --git a/nano.c b/nano.c index 799ac299..b53fb1a1 100644 --- a/nano.c +++ b/nano.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "config.h" #include "proto.h" @@ -850,8 +851,8 @@ void do_char(char ch) current->data[current_x] = ch; do_right(); - if (!ISSET(NO_WRAP)) - check_wrap(current); + if (!ISSET(NO_WRAP) && (ch != '\t')) + check_wrap(current, ch); set_modified(); check_statblank(); UNSET(KEEP_CUTBUFFER); @@ -965,98 +966,259 @@ void do_next_word(void) } -/* Actually wrap a line, called by check_wrap() */ -void do_wrap(filestruct * inptr) +void do_wrap(filestruct *inptr, char input_char) { - int i, j, chop; - char *tmp, *foo; + int i = 0; /* Index into ->data for line.*/ + int i_tabs = 0; /* Screen position of ->data[i]. */ + int last_word_end = -1; /* Location of end of last word found. */ + int current_word_start = -1; /* Location of start of current word. */ + int current_word_start_t = -1; /* Location of start of current word screen position. */ + int current_word_end = -1; /* Location of end of current word */ + int current_word_end_t = -1; /* Location of end of current word screen position. */ + int len = strlen(inptr->data); - i = actual_x(inptr, fill); + int down = 0; + int right = 0; + struct filestruct *temp = NULL; - while (inptr->data[i] != ' ' && inptr->data[i] != '\t' && i != 0) - i--; +assert (strlenpt(inptr->data) >= fill); - if (i == 0) - return; + for (i = 0, i_tabs; i < len; i++, i_tabs++) { + if (!isspace(inptr->data[i])) { + last_word_end = current_word_end; - while ((inptr->data[i] == ' ' || inptr->data[i] == '\t') && i != 0) - i--; + current_word_start = i; + current_word_start_t = i_tabs; - if (i == 0) - return; + while (!isspace(inptr->data[i]) && inptr->data[i]) { + i++; + i_tabs++; + if (inptr->data[i] < 32) + i_tabs++; + } - /* NB: This sucks */ - if (inptr->data[i] != 0) - i++; - if (inptr->data[i] != 0) - i++; + if (inptr->data[i]) { + current_word_end = i; + current_word_end_t = i_tabs; + } + else { + current_word_end = i - 1; + current_word_end_t = i_tabs - 1; + } + } - chop = i; - while ((inptr->data[i] == ' ' || inptr->data[i] == '\t') && - inptr->data[i] != 0) - i++; + if (inptr->data[i] == NANO_CONTROL_I) { + if (i_tabs % 8 != 0); + i_tabs += 8 - (i_tabs % 8); + } - if (inptr->data[i] == 0) - return; + if (current_word_end_t >= fill) + break; + } - if (ISSET(SAMELINEWRAP)) { - tmp = ¤t->data[i]; - foo = nmalloc(strlen(tmp) + strlen(current->next->data) + 1); - strcpy(foo, tmp); - strcpy(&foo[strlen(tmp)], current->next->data); - free(current->next->data); - current->next->data = foo; - *tmp = 0; - current->data[chop] = 0; - align(¤t->data); + assert (current_word_end_t >= fill); + + /* There are 4 cases of what the line could look like. + * 1) only one word on the line before wrap point. + * a) cursor is on word or before word at wrap point. + * - word starts new line. + * - keep white space on original line up to the cursor. + * *) cursor is after word at wrap point + * - either it's all white space after word, and this routine isn't called. + * - or we are actually in case 2 (2 words). + * 2) Two or more words on the line before wrap point. + * a) cursor is at a word before wrap point + * - word at wrap point starts a new line. + * - white space at end of original line is cleared. + * b) cursor is at the word at the wrap point. + * - word at wrap point starts a new line. + * 1. pressed a space. + * - white space on original line is kept to where cursor was. + * 2. pressed non space. + * - white space at end of original line is cleared. + * c) cursor is past the word at the wrap point. + * - word at wrap point starts a new line. + * 1. pressed a space. + * - white space on original line is kept to where wrap point was. + * 2. pressed a non space. + * - white space at end of original line is cleared + */ - if (current_x >= i) { - current_x = current_x - i; - current = current->next; - } - if (current->next == NULL) { - current->next = make_new_node(current); - current->next->data = nmalloc(1); - current->next->data[0] = 0; - filebot = current->next; + temp = nmalloc (sizeof (filestruct)); + + /* Category 1a: one word on the line */ + if (last_word_end == -1) { + + temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1); + strcpy(temp->data, &inptr->data[current_word_start]); + + /* Inside word, remove it from original, and move cursor to right spot. */ + if (current_x >= current_word_start) { + right = current_x - current_word_start; + current_x = 0; + down = 1; } - align(¤t->next->data); - edit_refresh(); - } else { + inptr->data = nrealloc(inptr->data, current_x + 1); + inptr->data[current_x] = 0; + } - j = current_x; - current_x = i; - do_enter(current); + /* Category 2: two or more words on the line. */ + else { - current->prev->data[chop] = 0; - align(¤t->prev->data); + /* Case 2a: cursor before word at wrap point. */ + if (current_x < current_word_start) { + temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1); + strcpy(temp->data, &inptr->data[current_word_start]); - if (j > i) { - current_x = j - i; - UNSET(SAMELINEWRAP); - } else { - current_x = j; - current = current->prev; - SET(SAMELINEWRAP); - } + i = current_word_start - 1; + while (isspace(inptr->data[i])) { + i--; + assert (i >= 0); + } + + inptr->data = nrealloc(inptr->data, i + 2); + inptr->data[i + 1] = 0; + } + + + /* Case 2b: cursor at word at wrap point. */ + else if ((current_x >= current_word_start) + && (current_x <= (current_word_end + 1))) { + temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1); + strcpy(temp->data, &inptr->data[current_word_start]); + + down = 1; + + right = current_x - current_word_start; + i = current_word_start - 1; + if (isspace(input_char)) { + current_x = current_word_start; + + inptr->data = nrealloc(inptr->data, current_word_start + 1); + inptr->data[current_word_start] = 0; + } + else { + + while (isspace(inptr->data[i])) { + i--; + assert (i >= 0); + } + inptr->data = nrealloc(inptr->data, i + 2); + inptr->data[i + 1] = 0; + } + + } + + + /* Case 2c: cursor past word at wrap point. */ + else { + temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1); + strcpy(temp->data, &inptr->data[current_word_start]); + + down = 1; + right = current_x - current_word_start; + + current_x = current_word_start; + i = current_word_start - 1; + + if (isspace(input_char)) { + + inptr->data = nrealloc(inptr->data, current_word_start + 1); + inptr->data[current_word_start] = 0; + } + else { + while (isspace(inptr->data[i])) { + i--; + assert (i >= 0); + } + inptr->data = nrealloc(inptr->data, i + 2); + inptr->data[i + 1] = 0; + } + } } + /* We pre-pend wrapped part to next line. */ + if (ISSET(SAMELINEWRAP)) { + /* Plus one for the space which concatenates the two lines together plus 1 for \0. */ + char *p = nmalloc(strlen(temp->data) + strlen(inptr->next->data) + 2); + + strcpy (p, temp->data); + strcat (p, " "); + strcat (p, inptr->next->data); + + free (inptr->next->data); + inptr->next->data = p; + + free (temp->data); + free (temp); + } + /* Else we start a new line. */ + else { + temp->prev = inptr; + temp->next = inptr->next; + + if (inptr->next) + inptr->next->prev = temp; + inptr->next = temp; + + if (!temp->next) + filebot = temp; + + SET(SAMELINEWRAP); + } + + + totlines++; + totsize++; + + renumber (inptr); + edit_update(current); + + /* Move the cursor to the new line if appropriate. */ + if (down) { + do_right(); + } + + /* Move the cursor to the correct spot in the line if appropriate. */ + while (right--) { + do_right(); + } + + edit_update(current); + reset_cursor(); + edit_refresh(); } /* Check to see if we've just caused the line to wrap to a new line */ -void check_wrap(filestruct * inptr) +void check_wrap(filestruct * inptr, char ch) { - + int len = strlenpt(inptr->data); #ifdef DEBUG fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"), inptr->data); #endif - if ((int) strlenpt(inptr->data) <= fill) + if (len <= fill) return; - else - do_wrap(inptr); + else { + int i = actual_x(inptr, fill); + + /* Do not wrap if there are no words on or after wrap point. */ + /* First check to see if we typed space and passed a word. */ + if (isspace(ch) && !isspace(inptr->data[i - 1])) + do_wrap(inptr, ch); + else { + + while (isspace(inptr->data[i]) && inptr->data[i]) + i++; + + if (!inptr->data[i]) + return; + + do_wrap(inptr, ch); + } + } } /* Stuff we do when we abort from programs and want to clean up the