diff -u -r nano/src/global.c nano-patch/src/global.c --- nano/src/global.c 2004-07-29 14:49:24.000000000 -0400 +++ nano-patch/src/global.c 2004-07-29 15:01:50.000000000 -0400 @@ -80,6 +80,13 @@ sentences. */ char *quotestr = NULL; /* Quote string. The default value is set in main(). */ +#ifdef HAVE_REGEX_H +regex_t quotereg; /* Compiled quotestr regular expression. */ +int quoterc; /* Did it compile? */ +char *quoteerr = NULL; /* The error message. */ +#else +size_t quotelen; /* strlen(quotestr) */ +#endif #endif #ifndef NANO_SMALL @@ -1073,6 +1080,10 @@ #ifndef DISABLE_JUSTIFY if (quotestr != NULL) free(quotestr); +#ifdef HAVE_REGEX_H + regfree("ereg); + free(quoteerr); +#endif #endif #ifndef NANO_SMALL if (backup_dir != NULL) diff -u -r nano/src/nano.c nano-patch/src/nano.c --- nano/src/nano.c 2004-07-29 14:49:24.000000000 -0400 +++ nano-patch/src/nano.c 2004-07-29 15:09:42.000000000 -0400 @@ -1964,40 +1964,35 @@ * * Note that if !HAVE_REGEX_H then we match concatenated copies of * quotestr. */ -#ifdef HAVE_REGEX_H -size_t quote_length(const char *line, const regex_t *qreg) +size_t quote_length(const char *line) { +#ifdef HAVE_REGEX_H regmatch_t matches; - int rc = regexec(qreg, line, 1, &matches, 0); + int rc = regexec("ereg, line, 1, &matches, 0); if (rc == REG_NOMATCH || matches.rm_so == (regoff_t) -1) return 0; /* matches.rm_so should be 0, since the quote string should start with * the caret ^. */ return matches.rm_eo; -} #else /* !HAVE_REGEX_H */ -size_t quote_length(const char *line) -{ size_t qdepth = 0; - size_t qlen = strlen(quotestr); /* Compute quote depth level. */ while (!strcmp(line + qdepth, quotestr)) - qdepth += qlen; + qdepth += quotelen; return qdepth; -} #endif /* !HAVE_REGEX_H */ +} /* a_line and b_line are lines of text. The quotation part of a_line is * the first a_quote characters. Check that the quotation part of * b_line is the same. */ -int quotes_match(const char *a_line, size_t a_quote, IFREG(const char - *b_line, const regex_t *qreg)) +int quotes_match(const char *a_line, size_t a_quote, const char *b_line) { /* Here is the assumption about a_quote: */ - assert(a_quote == quote_length(IFREG(a_line, qreg))); - return a_quote == quote_length(IFREG(b_line, qreg)) && + assert(a_quote == quote_length(a_line)); + return a_quote == quote_length(b_line) && !strncmp(a_line, b_line, a_quote); } @@ -2012,6 +2007,113 @@ return b_indent <= a_indent && !strncmp(a_line, b_line, b_indent); } +/* Is foo the beginning of a paragraph? + * + * A line of text consists of a "quote part", followed by an + * "indentation part", followed by text. The functions quote_length() + * and indent_length() calculate these parts. + * + * A line is "part of a paragraph" if it has a part not in the quote + * part or the indentation. + * + * A line is "the beginning of a paragraph" if it is part of a + * paragraph and + * 1) it is the top line of the file, or + * 2) the line above it is not part of a paragraph, or + * 3) the line above it does not have precisely the same quote + * part, or + * 4) the indentation of this line is not an initial substring of + * the indentation of the previous line, or + * 5) this line has no quote part and some indentation, and + * AUTOINDENT is not set. + * The reason for number 5) is that if AUTOINDENT is not set, then an + * indented line is expected to start a paragraph, like in books. + * Thus, nano can justify an indented paragraph only if AUTOINDENT is + * turned on. */ +bool begpar(const filestruct *const foo) +{ + size_t quote_len; + size_t indent_len; + size_t temp_id_len; + + /* Case 1) */ + if (foo->prev == NULL) + return TRUE; + + quote_len = quote_length(foo->data); + indent_len = indent_length(foo->data + quote_len); + + /* Not part of a paragraph. */ + if (foo->data[quote_len + indent_len] == '\0') + return FALSE; + + /* Case 3) */ + if (!quotes_match(foo->data, quote_len, foo->prev->data)) + return TRUE; + + temp_id_len = indent_length(foo->prev->data + quote_len); + + /* Case 2) or 5) or 4). */ + if (foo->prev->data[quote_len + temp_id_len] == '\0' || + (quote_len == 0 && indent_len > 0 +#ifndef NANO_SMALL + && !ISSET(AUTOINDENT) +#endif + ) || !indents_match(foo->prev->data + quote_len, temp_id_len, + foo->data + quote_len, indent_len)) + return TRUE; + + return FALSE; +} + +/* We find the last beginning-of-paragraph line before the current line. */ +void do_para_begin(void) +{ + const filestruct *old_current = current; + const size_t old_pww = placewewant; + + current_x = 0; + placewewant = 0; + + if (current->prev != NULL) + do { + current = current->prev; + } while (!begpar(current)); + + edit_redraw(old_current, old_pww); +} + +bool inpar(const char *str) +{ + size_t quote_len = quote_length(str); + + return str[quote_len + indent_length(str + quote_len)] != '\0'; +} + +/* A line is the last line of a paragraph if it is in a paragraph, and the + * next line isn't, or is the beginning of a paragraph. We move down to + * the end of a paragraph, then one line farther. */ +void do_para_end(void) +{ + const filestruct *const old_current = current; + const size_t old_pww = placewewant; + + current_x = 0; + placewewant = 0; + + while (current->next != NULL && !inpar(current->data)) + current = current->next; + + while (current->next != NULL && inpar(current->next->data) && + !begpar(current->next)) + current = current->next; + + if (current->next != NULL) + current = current->next; + + edit_redraw(old_current, old_pww); +} + /* Put the next par_len lines, starting with first_line, in the cut * buffer, not allowing them to be concatenated. We assume there are * enough lines after first_line. We leave copies of the lines in @@ -2110,50 +2212,16 @@ return space_loc; } -/* Search a paragraph. If search_type is JUSTIFY, search for the - * beginning of the current paragraph or, if we're at the end of it, the - * beginning of the next paragraph. If search_type is BEGIN, search for - * the beginning of the current paragraph or, if we're already there, - * the beginning of the previous paragraph. If search_type is END, - * search for the end of the current paragraph or, if we're already - * there, the end of the next paragraph. Afterwards, save the quote - * length, paragraph length, and indentation length in *quote, *par, and - * *indent if they aren't NULL, and refresh the screen if do_refresh is - * TRUE. Return 0 if we found a paragraph, or 1 if there was an error - * or we didn't find a paragraph. - * - * To explain the searching algorithm, I first need to define some - * phrases about paragraphs and quotation: - * A line of text consists of a "quote part", followed by an - * "indentation part", followed by text. The functions quote_length() - * and indent_length() calculate these parts. - * - * A line is "part of a paragraph" if it has a part not in the quote - * part or the indentation. +/* Find the beginning of the current paragraph if we're in one, or the + * beginning of the next paragraph if we're not. Afterwards, save the + * quote length and paragraph length in *quote and *par. Return FALSE if + * we found a paragraph, or TRUE if there was an error or we didn't find a + * paragraph. * - * A line is "the beginning of a paragraph" if it is part of a - * paragraph and - * 1) it is the top line of the file, or - * 2) the line above it is not part of a paragraph, or - * 3) the line above it does not have precisely the same quote - * part, or - * 4) the indentation of this line is not an initial substring of - * the indentation of the previous line, or - * 5) this line has no quote part and some indentation, and - * AUTOINDENT is not set. - * The reason for number 5) is that if AUTOINDENT is not set, then an - * indented line is expected to start a paragraph, like in books. - * Thus, nano can justify an indented paragraph only if AUTOINDENT is - * turned on. - * - * A contiguous set of lines is a "paragraph" if each line is part of - * a paragraph and only the first line is the beginning of a - * paragraph. */ -int do_para_search(justbegend search_type, size_t *quote, size_t *par, - size_t *indent, int do_refresh) + * See the comment at begpar() for more about when a line is the beginning + * of a paragraph. */ +bool do_para_search(size_t *const quote, size_t *const par) { - size_t old_pww = placewewant; - const filestruct *current_save = current; size_t quote_len; /* Length of the initial quotation of the paragraph we * search. */ @@ -2165,18 +2233,9 @@ /* Generic line of text. */ #ifdef HAVE_REGEX_H - regex_t qreg; /* qreg is the compiled quotation regexp. We no - * longer care about quotestr. */ - int rc = regcomp(&qreg, quotestr, REG_EXTENDED); - - if (rc != 0) { - size_t size = regerror(rc, &qreg, NULL, 0); - char *strerror = charalloc(size); - - regerror(rc, &qreg, strerror, size); - statusbar(_("Bad quote string %s: %s"), quotestr, strerror); - free(strerror); - return 1; + if (quoterc != 0) { + statusbar(_("Bad quote string %s: %s"), quotestr, quoteerr); + return TRUE; } #endif @@ -2185,20 +2244,19 @@ current_x = 0; - quote_len = quote_length(IFREG(current->data, &qreg)); + quote_len = quote_length(current->data); indent_len = indent_length(current->data + quote_len); - /* Here we find the last or first line of the paragraph to search. - * If the current line is in a paragraph, then we move back to the - * first line of the paragraph. Otherwise, we move to the last or - * first line that is in a paragraph. */ - start_para_search: + /* Here we find the first line of the paragraph to search. + * If the current line is in a paragraph, then we move back to the + * first line of the paragraph. Otherwise, we move to the first line + * that is in a paragraph. */ if (current->data[quote_len + indent_len] != '\0') { /* This line is part of a paragraph. So we must search back to * the first line of this paragraph. First we check items 1) * and 3) above. */ - while (current->prev != NULL && quotes_match(current->data, - quote_len, IFREG(current->prev->data, &qreg))) { + while (current->prev != NULL && quotes_match(current->data, + quote_len, current->prev->data)) { size_t temp_id_len = indent_length(current->prev->data + quote_len); /* The indentation length of the previous line. */ @@ -2217,37 +2275,6 @@ current = current->prev; current_y--; } - - /* If we're searching for the beginning of the paragraph, - * we're not on the first line of the file, and we're on the - * same line we started on, move up one line and search - * again, so that we end up on the first line of the previous - * paragraph. */ - if (search_type == BEGIN && current->prev != NULL && - current == current_save) { - current = current->prev; - current_y--; - goto start_para_search; - } - } else if (search_type == BEGIN) { - /* This line is not part of a paragraph. Move up until we get - * to a non "blank" line. */ - do { - /* There is no previous paragraph, so nothing to move to. */ - if (current->prev == NULL) { - placewewant = 0; - if (do_refresh) - edit_redraw(current_save, old_pww); -#ifdef HAVE_REGEX_H - regfree(&qreg); -#endif - return 1; - } - current = current->prev; - current_y--; - quote_len = quote_length(IFREG(current->data, &qreg)); - indent_len = indent_length(current->data + quote_len); - } while (current->data[quote_len + indent_len] == '\0'); } else { /* This line is not part of a paragraph. Move down until we get * to a non "blank" line. */ @@ -2255,23 +2282,17 @@ /* There is no next paragraph, so nothing to move to. */ if (current->next == NULL) { placewewant = 0; - if (do_refresh) - edit_redraw(current_save, old_pww); -#ifdef HAVE_REGEX_H - regfree(&qreg); -#endif - return 1; + return TRUE; } current = current->next; current_y++; - quote_len = quote_length(IFREG(current->data, &qreg)); + quote_len = quote_length(current->data); indent_len = indent_length(current->data + quote_len); } while (current->data[quote_len + indent_len] == '\0'); } - /* Now current is the last line in the paragraph if we're searching - * for the beginning of it or the first line of the paragraph - * otherwise, and quote_len is the quotation length of that line. */ + /* Now current is the first line of the paragraph, and quote_len is + * the quotation length of that line. */ /* Next step, compute par_len, the number of lines in this * paragraph. */ @@ -2279,32 +2300,11 @@ par_len = 1; indent_len = indent_length(line->data + quote_len); - if (search_type == BEGIN) { - while (line->prev != NULL && quotes_match(current->data, - quote_len, IFREG(line->prev->data, &qreg))) { - size_t temp_id_len = indent_length(line->prev->data + - quote_len); + while (line->next != NULL && + quotes_match(current->data, quote_len, line->next->data)) { + size_t temp_id_len = indent_length(line->next->data + quote_len); - if (!indents_match(line->data + quote_len, indent_len, - line->prev->data + quote_len, temp_id_len) || - line->prev->data[quote_len + temp_id_len] == '\0' || - (quote_len == 0 && temp_id_len > 0 -#ifndef NANO_SMALL - && !ISSET(AUTOINDENT) -#endif - )) - break; - indent_len = temp_id_len; - line = line->prev; - par_len++; - } - } else { - while (line->next != NULL && quotes_match(current->data, - quote_len, IFREG(line->next->data, &qreg))) { - size_t temp_id_len = indent_length(line->next->data + - quote_len); - - if (!indents_match(line->data + quote_len, indent_len, + if (!indents_match(line->data + quote_len, indent_len, line->next->data + quote_len, temp_id_len) || line->next->data[quote_len + temp_id_len] == '\0' || (quote_len == 0 && temp_id_len > 0 @@ -2312,70 +2312,27 @@ && !ISSET(AUTOINDENT) #endif )) - break; - indent_len = temp_id_len; - line = line->next; - par_len++; - } + break; + indent_len = temp_id_len; + line = line->next; + par_len++; } -#ifdef HAVE_REGEX_H - /* We no longer need to check quotation. */ - regfree(&qreg); -#endif - /* Now par_len is the number of lines in this paragraph. We should * never call quotes_match() or quote_length() again. */ - /* If we're searching for the beginning of the paragraph, move up - * the number of lines in the paragraph minus one, since we want to - * end up on the first line of the paragraph. If we're searching - * for the end of the paragraph, move down the number of lines in - * the paragraph, since we want to end up on the line after the - * last line of the paragraph. */ - if (search_type == BEGIN) { - for (; par_len > 1; current_y--, par_len--) - current = current->prev; - } else if (search_type == END) { - for (; par_len > 0; current_y++, par_len--) - current = current->next; - } - - /* Refresh the screen if needed. */ - if (do_refresh) - edit_redraw(current_save, old_pww); - - /* Save the values of quote_len, par_len, and indent_len if - * needed. */ - if (quote != NULL) - *quote = quote_len; - if (par != NULL) - *par = par_len; - if (indent != NULL) - *indent = indent_len; - - return 0; -} - -void do_para_begin(void) -{ - do_para_search(BEGIN, NULL, NULL, NULL, TRUE); -} + /* Save the values of quote_len and par_len. */ + assert(quote != NULL && par != NULL); + *quote = quote_len; + *par = par_len; -void do_para_end(void) -{ - do_para_search(END, NULL, NULL, NULL, TRUE); + return FALSE; } /* If full_justify is TRUE, justify the entire file. Otherwise, justify * the current paragraph. */ void do_justify(int full_justify) { - size_t quote_len; - /* Length of the initial quotation of the paragraph we - * justify. */ - size_t par_len; - /* Number of lines in that paragraph. */ filestruct *first_par_line = NULL; /* Will be the first line of the resulting justified paragraph. * For restoring after uncut. */ @@ -2385,7 +2342,7 @@ /* When the paragraph gets modified, all lines from the changed * one down are stored in the cutbuffer. We back up the * original to restore it later. */ - int allow_respacing; + bool allow_respacing; /* Whether we should change the spacing at the end of a line * after justifying it. This should be TRUE whenever we move * to the next line after justifying the current line. */ @@ -2405,8 +2362,6 @@ int kbinput; int meta_key; - size_t indent_len; /* Generic indentation length. */ - /* If we're justifying the entire file, start at the beginning. */ if (full_justify) current = fileage; @@ -2414,18 +2369,22 @@ last_par_line = current; while (TRUE) { - /* First, search for the beginning of the current paragraph or, - * if we're at the end of it, the beginning of the next - * paragraph. Save the quote length, paragraph length, and - * indentation length and don't refresh the screen yet (since - * we'll do that after we justify). If the search failed and - * we're justifying the whole file, move the last line of the - * text we're justifying to just before the magicline, which is - * where it'll be anyway if we've searched the entire file, and - * break out of the loop; otherwise, refresh the screen and get - * out. */ - if (do_para_search(JUSTIFY, "e_len, &par_len, &indent_len, - FALSE) != 0) { + size_t quote_len; + /* Length of the initial quotation of the paragraph we + * justify. */ + size_t par_len; + /* Number of lines in that paragraph. */ + + /* Find the first line of the paragraph to be justified. That is + * the start of this paragraph if we're in one, or the start of + * the next otherwise. Save the quote length and paragraph length + * (number of lines). Don't refresh the screen yet (since we'll + * do that after we justify). If the search failed and we're + * justifying the whole file, move the last line of the text we're + * justifying to just before the magicline, which is where it'll + * be anyway if we've searched the entire file, and break out of + * the loop; otherwise, refresh the screen and get out. */ + if (do_para_search("e_len, &par_len)) { if (full_justify) { /* This should be safe in the event of filebot->prev's * being NULL, since only last_par_line->next is used if @@ -2441,6 +2400,7 @@ /* Next step, we loop through the lines of this paragraph, * justifying each one individually. */ for (; par_len > 0; current_y++, par_len--) { + size_t indent_len; /* Generic indentation length. */ size_t line_len; size_t display_len; /* The width of current in screen columns. */ @@ -3411,6 +3371,22 @@ "> " #endif ); +#ifdef HAVE_REGEX_H + quoterc = regcomp("ereg, quotestr, REG_EXTENDED); + + if (quoterc == 0) { + /* We no longer need quotestr, just quotereg. */ + free(quotestr); + quotestr = NULL; + } else { + size_t size = regerror(quoterc, "ereg, NULL, 0); + + quoteerr = charalloc(size); + regerror(quoterc, "ereg, quoteerr, size); + } +#else + quotelen = strlen(quotestr); +#endif /* !HAVE_REGEX_H */ #endif /* !DISABLE_JUSTIFY */ #ifndef DISABLE_SPELLER diff -u -r nano/src/proto.h nano-patch/src/proto.h --- nano/src/proto.h 2004-07-29 14:49:26.000000000 -0400 +++ nano-patch/src/proto.h 2004-07-29 15:11:02.000000000 -0400 @@ -51,6 +51,13 @@ extern char *punct; extern char *brackets; extern char *quotestr; +#ifdef HAVE_REGEX_H +extern regex_t quotereg; +extern int quoterc; +extern char *quoteerr; +#else +extern size_t quotelen; +#endif #endif #ifndef NANO_SMALL @@ -191,6 +198,7 @@ #ifndef NANO_SMALL void init_backup_dir(void); #endif +int copy_file(FILE *inn, FILE *out); int write_file(const char *name, int tmp, int append, int nonamechange); #ifndef NANO_SMALL int write_marked(const char *name, int tmp, int append); @@ -314,28 +322,19 @@ #endif #ifndef DISABLE_JUSTIFY void justify_format(filestruct *line, size_t skip); -#ifdef HAVE_REGEX_H -size_t quote_length(const char *line, const regex_t *qreg); -#else size_t quote_length(const char *line); -#endif -#ifdef HAVE_REGEX_H -# define IFREG(a, b) a, b -#else -# define IFREG(a, b) a -#endif -int quotes_match(const char *a_line, size_t a_quote, IFREG(const char - *b_line, const regex_t *qreg)); +int quotes_match(const char *a_line, size_t a_quote, const char *b_line); size_t indents_match(const char *a_line, size_t a_indent, const char *b_line, size_t b_indent); +bool begpar(const filestruct *const foo); +void do_para_begin(void); +bool inpar(const char *str); +void do_para_end(void); filestruct *backup_lines(filestruct *first_line, size_t par_len, size_t quote_len); int breakable(const char *line, int goal); int break_line(const char *line, int goal, int force); -int do_para_search(justbegend search_type, size_t *quote, size_t *par, - size_t *indent, int do_refresh); -void do_para_begin(void); -void do_para_end(void); +bool do_para_search(size_t *const quote, size_t *const par); void do_justify(int full_justify); void do_justify_void(void); void do_full_justify(void);