nano-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Nano-devel] [PATCH] use separate tab size for indent and align


From: Simon Arlott
Subject: [Nano-devel] [PATCH] use separate tab size for indent and align
Date: Sun, 27 Sep 2009 15:19:14 +0100
User-agent: Thunderbird 2.0.0.23 (X11/20090927)

This patch modifies 2.1.10 to allow a separate tab size to be specified
for use in alignment (the rest of the line after indentation).

It correctly handles the tabs-to-spaces option and changes the base
for alignment tabs from the start of the line to the most recent indent
tab stop, so this continues to work even though the indent ends at "*"
in this common comment format:
        /* Header       Header  Header
         * Text         Text    Text
         * Text         Text    Text
         * Text         Text    Text
         */
If the two tab sizes are the same then the tab base change won't alter
anything.

The non-editor parts of nano's displays always use the alignment tab
size. (e.g. search/filename prompts)

.nanorc Example:
        # set tabsize <indent> <align>
        set tabsize 4 8

-T on the command line always sets both sizes
(this could be changed to allow "-T <indent>[,<align>]")

The default alignment tab size is to copy the indent tab size.


Screenshots with visible whitespace are the best way to explain the
purpose of this (keeping tabs used for alignment independent of those
used for indentation):
        http://simon.arlott.org/pub/patches/nano/tabsize.htm

The /* */ indentation is mis-aligned at tab size 1, but there's no way
around that while still considering all whitespace chars as indentation.


Patch: http://simon.arlott.org/pub/patches/nano/2.1.10_multiple-tabsize.patch
(nano's coding style appears to combine 8 column tabs as a double indent
with 4 spaces for a single indent, which is not easy to use...)

This probably won't apply against 2.1.11 because of the soft wrapping
changes.

---

diff -r -U4 nano-2.1.10/src/browser.c nano-2.1.10+tabsize2/src/browser.c
--- nano-2.1.10/src/browser.c   2009-01-25 07:26:47.000000000 +0000
+++ nano-2.1.10+tabsize2/src/browser.c  2009-09-27 14:44:27.000000000 +0100
@@ -625,9 +625,9 @@
                 * this to TRUE if we have fewer than 15 columns (i.e.
                 * one column for padding, plus seven columns for a
                 * filename other than ".."). */
        char *disp = display_string(filetail, dots ? filetaillen -
-               longest + foomaxlen + 4 : 0, longest, FALSE);
+               longest + foomaxlen + 4 : 0, longest, FALSE, FALSE);
                /* If we put an ellipsis before the filename, reserve
                 * one column for padding, plus seven columns for "--",
                 * "(dir)", or the file size, plus three columns for the
                 * ellipsis. */
@@ -776,9 +776,10 @@
 
     search_init_globals();
 
     if (last_search[0] != '\0') {
-       char *disp = display_string(last_search, 0, COLS / 3, FALSE);
+       char *disp = display_string(last_search, 0, COLS / 3, FALSE,
+               FALSE);
 
        buf = charalloc(strlen(disp) + 7);
        /* We use (COLS / 3) here because we need to see more on the
         * line. */
diff -r -U4 nano-2.1.10/src/chars.c nano-2.1.10+tabsize2/src/chars.c
--- nano-2.1.10/src/chars.c     2008-09-15 04:32:35.000000000 +0100
+++ nano-2.1.10+tabsize2/src/chars.c    2009-09-27 14:46:25.000000000 +0100
@@ -373,9 +373,9 @@
 /* Parse a multibyte character from buf.  Return the number of bytes
  * used.  If chr isn't NULL, store the multibyte character in it.  If
  * col isn't NULL, store the new display width in it.  If *buf is '\t',
  * we expect col to have the current display width. */
-int parse_mbchar(const char *buf, char *chr, size_t *col)
+int parse_mbchar(const char *buf, char *chr, mblinestate *state)
 {
     int buf_mb_len;
 
     assert(buf != NULL);
@@ -401,33 +401,43 @@
                chr[i] = buf[i];
        }
 
        /* Save the column width of the wide character in col. */
-       if (col != NULL) {
+       if (state != NULL) {
+           /* Update tab type at first non-blank character. */
+           if (state->tab_type == INDENT_TAB
+                   && !is_blank_mbchar(buf)) {
+               state->tab_type = ALIGN_TAB;
+               state->tab_base = state->col
+                       - (state->col % tabsize[INDENT_TAB]);
+           }
+
            /* If we have a tab, get its width in columns using the
             * current value of col. */
            if (*buf == '\t')
-               *col += tabsize - *col % tabsize;
+               state->col += tabsize[state->tab_type]
+                       - (state->col - state->tab_base)
+                       % tabsize[state->tab_type];
            /* If we have a control character, get its width using one
             * column for the "^" that will be displayed in front of it,
             * and the width in columns of its visible equivalent as
             * returned by control_mbrep(). */
            else if (is_cntrl_mbchar(buf)) {
                char *ctrl_buf_mb = charalloc(MB_CUR_MAX);
                int ctrl_buf_mb_len;
 
-               (*col)++;
+               state->col++;
 
                ctrl_buf_mb = control_mbrep(buf, ctrl_buf_mb,
                        &ctrl_buf_mb_len);
 
-               *col += mbwidth(ctrl_buf_mb);
+               state->col += mbwidth(ctrl_buf_mb);
 
                free(ctrl_buf_mb);
            /* If we have a normal character, get its width in columns
             * normally. */
            } else
-               *col += mbwidth(buf);
+               state->col += mbwidth(buf);
        }
     } else {
 #endif
        /* Get the number of bytes in the byte character. */
@@ -436,22 +446,32 @@
        /* Save the byte character in chr. */
        if (chr != NULL)
            *chr = *buf;
 
-       if (col != NULL) {
+       if (state != NULL) {
+           /* Update tab type at first non-blank character. */
+           if (state->tab_type == INDENT_TAB
+                   && !is_blank_mbchar(buf)) {
+               state->tab_type = ALIGN_TAB;
+               state->tab_base = state->col
+                       - (state->col % tabsize[INDENT_TAB]);
+           }
+
            /* If we have a tab, get its width in columns using the
             * current value of col. */
            if (*buf == '\t')
-               *col += tabsize - *col % tabsize;
+               state->col += tabsize[state->tab_type]
+                       - (state->col - state->tab_base)
+                       % tabsize[state->tab_type];
            /* If we have a control character, it's two columns wide:
             * one column for the "^" that will be displayed in front of
             * it, and one column for its visible equivalent as returned
             * by control_mbrep(). */
            else if (is_cntrl_char((unsigned char)*buf))
-               *col += 2;
+               state->col += 2;
            /* If we have a normal character, it's one column wide. */
            else
-               (*col)++;
+               state->col++;
        }
 #ifdef ENABLE_UTF8
     }
 #endif
diff -r -U4 nano-2.1.10/src/files.c nano-2.1.10+tabsize2/src/files.c
--- nano-2.1.10/src/files.c     2009-05-03 02:40:33.000000000 +0100
+++ nano-2.1.10+tabsize2/src/files.c    2009-09-27 14:44:27.000000000 +0100
@@ -2492,9 +2492,9 @@
                    break;
                }
 
                disp = display_string(matches[match], 0, longest_name,
-                       FALSE);
+                       FALSE, FALSE);
                waddstr(edit, disp);
                free(disp);
 
                if ((match + 1) % ncols == 0)
diff -r -U4 nano-2.1.10/src/global.c nano-2.1.10+tabsize2/src/global.c
--- nano-2.1.10/src/global.c    2009-07-12 04:36:57.000000000 +0100
+++ nano-2.1.10+tabsize2/src/global.c   2009-09-27 14:44:27.000000000 +0100
@@ -123,11 +123,12 @@
 
 char *answer = NULL;
        /* The answer string used by the statusbar prompt. */
 
-ssize_t tabsize = -1;
-       /* The width of a tab in spaces.  The default value is set in
-        * main(). */
+ssize_t tabsize[2] = { -1, -1 };
+       /* The width of a tab in spaces, at the start of each line.
+        * The width of a tab in spaces, after any non-tab characters.
+        * The default value is set in main(). */
 
 #ifndef NANO_TINY
 char *backup_dir = NULL;
        /* The directory where we store backup files. */
diff -r -U4 nano-2.1.10/src/nano.c nano-2.1.10+tabsize2/src/nano.c
--- nano-2.1.10/src/nano.c      2009-07-12 04:36:57.000000000 +0100
+++ nano-2.1.10+tabsize2/src/nano.c     2009-09-27 14:44:27.000000000 +0100
@@ -2135,13 +2135,15 @@
                SET(SMOOTH_SCROLL);
                break;
 #endif
            case 'T':
-               if (!parse_num(optarg, &tabsize) || tabsize <= 0) {
+               if (!parse_num(optarg, &tabsize[INDENT_TAB])
+                       || tabsize[INDENT_TAB] <= 0) {
                    fprintf(stderr, _("Requested tab size \"%s\" is invalid"), 
optarg);
                    fprintf(stderr, "\n");
                    exit(1);
                }
+               tabsize[ALIGN_TAB] = tabsize[INDENT_TAB];
                break;
 #ifndef NANO_TINY
            case 'U':
                SET(QUICK_BLANK);
@@ -2275,9 +2277,9 @@
 #endif
 #ifndef DISABLE_SPELLER
        char *alt_speller_cpy = alt_speller;
 #endif
-       ssize_t tabsize_cpy = tabsize;
+       ssize_t tabsize_cpy[2] = { tabsize[0], tabsize[1] };
        long flags_cpy = flags;
 
 #ifndef DISABLE_OPERATINGDIR
        operating_dir = NULL;
@@ -2326,10 +2328,12 @@
            free(alt_speller);
            alt_speller = alt_speller_cpy;
        }
 #endif
-       if (tabsize_cpy != -1)
-           tabsize = tabsize_cpy;
+       if (tabsize_cpy[INDENT_TAB] != -1)
+           tabsize[INDENT_TAB] = tabsize_cpy[INDENT_TAB];
+       if (tabsize_cpy[ALIGN_TAB] != -1)
+           tabsize[ALIGN_TAB] = tabsize_cpy[ALIGN_TAB];
        flags |= flags_cpy;
     }
 #ifdef DISABLE_ROOTWRAPPING
     /* If we don't have any rcfiles, --disable-wrapping-as-root is used,
@@ -2433,10 +2437,12 @@
     }
 #endif
 
     /* If tabsize wasn't specified, set its default value. */
-    if (tabsize == -1)
-       tabsize = WIDTH_OF_TAB;
+    if (tabsize[INDENT_TAB] == -1)
+       tabsize[INDENT_TAB] = WIDTH_OF_TAB;
+    if (tabsize[ALIGN_TAB] == -1)
+       tabsize[ALIGN_TAB] = tabsize[INDENT_TAB];
 
     /* Back up the old terminal settings so that they can be restored. */
     tcgetattr(0, &oldterm);
 
diff -r -U4 nano-2.1.10/src/nano.h nano-2.1.10+tabsize2/src/nano.h
--- nano-2.1.10/src/nano.h      2009-07-03 04:51:25.000000000 +0100
+++ nano-2.1.10+tabsize2/src/nano.h     2009-09-27 14:44:27.000000000 +0100
@@ -182,8 +182,12 @@
 typedef enum {
     ADD, DEL, REPLACE, SPLIT, UNSPLIT, CUT, UNCUT, ENTER, INSERT, OTHER
 } undo_type;
 
+typedef enum {
+    INDENT_TAB, ALIGN_TAB
+} tabsize_type;
+
 #ifdef ENABLE_COLOR
 typedef struct colortype {
     short fg;
        /* This syntax's foreground color. */
@@ -448,8 +452,14 @@
     struct subnfunc *next;
        /* next item in the list */
 } subnfunc;
 
+typedef struct mblinestate {
+       size_t col;
+       tabsize_type tab_type;
+       size_t tab_base;
+} mblinestate;
+
 
 /* Bitwise flags so that we can save space (or, more correctly, not
  * waste it). */
 #define CASE_SENSITIVE                 (1<<0)
diff -r -U4 nano-2.1.10/src/prompt.c nano-2.1.10+tabsize2/src/prompt.c
--- nano-2.1.10/src/prompt.c    2009-01-25 07:26:47.000000000 +0000
+++ nano-2.1.10+tabsize2/src/prompt.c   2009-09-27 14:44:27.000000000 +0100
@@ -862,9 +862,9 @@
     waddch(bottomwin, ':');
     waddch(bottomwin, (page_start == 0) ? ' ' : '$');
 
     expanded = display_string(curranswer, page_start, COLS - start_col -
-       1, FALSE);
+       1, FALSE, FALSE);
     waddstr(bottomwin, expanded);
     free(expanded);
 
     wattroff(bottomwin, reverse_attr);
diff -r -U4 nano-2.1.10/src/proto.h nano-2.1.10+tabsize2/src/proto.h
--- nano-2.1.10/src/proto.h     2009-07-12 04:36:57.000000000 +0100
+++ nano-2.1.10+tabsize2/src/proto.h    2009-09-27 14:44:27.000000000 +0100
@@ -79,9 +79,9 @@
 #endif
 extern bool nodelay_mode;
 extern char *answer;
 
-extern ssize_t tabsize;
+extern ssize_t tabsize[2];
 
 #ifndef NANO_TINY
 extern char *backup_dir;
 #endif
@@ -172,9 +172,9 @@
 char *mbrep(const char *c, char *crep, int *crep_len);
 int mbwidth(const char *c);
 int mb_cur_max(void);
 char *make_mbchar(long chr, int *chr_mb_len);
-int parse_mbchar(const char *buf, char *chr, size_t *col);
+int parse_mbchar(const char *buf, char *chr, mblinestate *state);
 size_t move_mbleft(const char *buf, size_t pos);
 size_t move_mbright(const char *buf, size_t pos);
 #ifndef HAVE_STRCASECMP
 int nstrcasecmp(const char *s1, const char *s2);
@@ -643,8 +643,10 @@
 #endif
 #if !defined(NANO_TINY) || !defined(DISABLE_JUSTIFY)
 size_t indent_length(const char *line);
 #endif
+void calc_tabsize(const char *line, size_t current_x,
+       tabsize_type *tab_type, size_t *tab_base);
 #ifndef DISABLE_JUSTIFY
 void justify_format(filestruct *paragraph, size_t skip);
 size_t quote_length(const char *line);
 bool quotes_match(const char *a_line, size_t a_quote, const char
@@ -755,9 +757,9 @@
 void blank_statusbar(void);
 void blank_bottombars(void);
 void check_statusblank(void);
 char *display_string(const char *buf, size_t start_col, size_t len, bool
-       dollars);
+       dollars, bool indented_tabs);
 void titlebar(const char *path);
 void set_modified(void);
 void statusbar(const char *msg, ...);
 void bottombars(int menu);
diff -r -U4 nano-2.1.10/src/rcfile.c nano-2.1.10+tabsize2/src/rcfile.c
--- nano-2.1.10/src/rcfile.c    2009-07-12 07:13:34.000000000 +0100
+++ nano-2.1.10+tabsize2/src/rcfile.c   2009-09-27 14:44:27.000000000 +0100
@@ -1035,15 +1035,36 @@
                        else
 #endif
                        if (strcasecmp(rcopts[i].name,
                                "tabsize") == 0) {
-                           if (!parse_num(option, &tabsize) ||
-                               tabsize <= 0) {
+                           bool ok = TRUE;
+
+                           if (!parse_num(option,
+                                   &tabsize[INDENT_TAB])
+                                   || tabsize[INDENT_TAB] <= 0) {
                                rcfile_error(
                                        N_("Requested tab size \"%s\" is 
invalid"),
                                        option);
-                               tabsize = -1;
-                           } else
+                               tabsize[INDENT_TAB] = -1;
+                               ok = FALSE;
+                           }
+
+                           if (ptr[0] != '\0') {
+                               char *option2 = ptr;
+                               ptr = parse_next_word(ptr);
+
+                               if (!parse_num(option2,
+                                       &tabsize[ALIGN_TAB])
+                                       || tabsize[ALIGN_TAB] <= 0) {
+                                   rcfile_error(
+                                           N_("Requested second tab size 
\"%s\" is invalid"),
+                                           option2);
+                                   tabsize[ALIGN_TAB] = -1;
+                                   ok = FALSE;
+                               }
+                           }
+
+                           if (ok == TRUE)
                                free(option);
                        } else
                            assert(FALSE);
                    }
diff -r -U4 nano-2.1.10/src/search.c nano-2.1.10+tabsize2/src/search.c
--- nano-2.1.10/src/search.c    2009-02-17 02:03:41.000000000 +0000
+++ nano-2.1.10+tabsize2/src/search.c   2009-09-27 14:44:27.000000000 +0100
@@ -89,9 +89,9 @@
     int numchars;
 
     assert(str != NULL);
 
-    disp = display_string(str, 0, (COLS / 2) + 1, FALSE);
+    disp = display_string(str, 0, (COLS / 2) + 1, FALSE, FALSE);
     numchars = actual_x(disp, mbstrnlen(disp, COLS / 2));
 
     statusbar(_("\"%.*s%s\" not found"), numchars, disp,
        (disp[numchars] == '\0') ? "" : "...");
@@ -160,9 +160,10 @@
 
     search_init_globals();
 
     if (last_search[0] != '\0') {
-       char *disp = display_string(last_search, 0, COLS / 3, FALSE);
+       char *disp = display_string(last_search, 0, COLS / 3, FALSE,
+               FALSE);
 
        buf = charalloc(strlen(disp) + 7);
        /* We use (COLS / 3) here because we need to see more on the
         * line. */
@@ -774,9 +775,10 @@
        if (!replaceall) {
            size_t xpt = xplustabs();
            char *exp_word = display_string(openfile->current->data,
                xpt, strnlenpt(openfile->current->data,
-               openfile->current_x + match_len) - xpt, FALSE);
+               openfile->current_x + match_len) - xpt, FALSE,
+               TRUE);
 
            curs_set(0);
 
            do_replace_highlight(TRUE, exp_word);
diff -r -U4 nano-2.1.10/src/text.c nano-2.1.10+tabsize2/src/text.c
--- nano-2.1.10/src/text.c      2009-07-27 05:16:25.000000000 +0100
+++ nano-2.1.10+tabsize2/src/text.c     2009-09-27 14:44:27.000000000 +0100
@@ -164,13 +164,17 @@
 #ifndef NANO_TINY
     if (ISSET(TABS_TO_SPACES)) {
        char *output;
        size_t output_len = 0, new_pww = xplustabs();
+       tabsize_type tab_type;
+       size_t tab_base;
+       calc_tabsize(openfile->current->data, openfile->current_x,
+               &tab_type, &tab_base);
 
        do {
            new_pww++;
            output_len++;
-       } while (new_pww % tabsize != 0);
+       } while ((new_pww - tab_base) % tabsize[tab_type] != 0);
 
        output = charalloc(output_len + 1);
 
        charset(output, ' ', output_len);
@@ -243,10 +247,10 @@
            line_indent_len = cols;
        } else {
            /* Set the indentation to (cols / tabsize) tabs and (cols %
             * tabsize) spaces. */
-           size_t num_tabs = cols / tabsize;
-           size_t num_spaces = cols % tabsize;
+           size_t num_tabs = cols / tabsize[INDENT_TAB];
+           size_t num_spaces = cols % tabsize[INDENT_TAB];
 
            charset(line_indent, '\t', num_tabs);
            charset(line_indent + num_tabs, ' ', num_spaces);
 
@@ -346,16 +350,16 @@
 /* Indent the current line, or all lines covered by the mark if the mark
  * is on, tabsize columns. */
 void do_indent_void(void)
 {
-    do_indent(tabsize);
+    do_indent(tabsize[INDENT_TAB]);
 }
 
 /* Unindent the current line, or all lines covered by the mark if the
  * mark is on, tabsize columns. */
 void do_unindent(void)
 {
-    do_indent(-tabsize);
+    do_indent(-tabsize[INDENT_TAB]);
 }
 
 /* undo a cut, or re-do an uncut */
 void undo_cut(undo *u)
@@ -1346,16 +1350,20 @@
        /* Current tentative return value.  Index of the last blank we
         * found with short enough display width.  */
     ssize_t cur_loc = 0;
        /* Current index in line. */
-    size_t cur_pos = 0;
+    mblinestate state;
        /* Current column position in line. */
     int line_len;
 
+    state.col = 0;
+    state.tab_type = INDENT_TAB;
+    state.tab_base = 0;
+
     assert(line != NULL);
 
-    while (*line != '\0' && goal >= cur_pos) {
-       line_len = parse_mbchar(line, NULL, &cur_pos);
+    while (*line != '\0' && goal >= state.col) {
+       line_len = parse_mbchar(line, NULL, &state);
 
        if (is_blank_mbchar(line)
 #ifndef DISABLE_HELP
                || (newln && *line == '\n')
@@ -1372,9 +1380,9 @@
        line += line_len;
        cur_loc += line_len;
     }
 
-    if (goal >= cur_pos)
+    if (goal >= state.col)
        /* In fact, the whole line displays shorter than goal. */
        return cur_loc;
 
 #ifndef DISABLE_HELP
@@ -1466,8 +1474,55 @@
     return len;
 }
 #endif /* !NANO_TINY || !DISABLE_JUSTIFY */
 
+/* Calculate tab_type and tab_base at current_x in the line,
+ * but before processing the character at current_x.  The
+ * caller is expected to process current_x to determine if
+ * it ends the indent before continuing. */
+void calc_tabsize(const char *line, size_t current_x,
+       tabsize_type *tab_type, size_t *tab_base)
+{
+    mblinestate state;
+    bool at_base = FALSE;
+    char *blank_mb;
+    int blank_mb_len;
+
+    state.col = 0;
+    state.tab_type = INDENT_TAB;
+    state.tab_base = 0;
+
+    assert(line != NULL);
+
+    blank_mb = charalloc(mb_cur_max());
+
+    while (*line != '\0') {
+       size_t prev_col = state.col;
+       blank_mb_len = parse_mbchar(line, blank_mb, &state);
+
+       if (state.tab_type == ALIGN_TAB) {
+           if (current_x <= 0) {
+               state.tab_type = INDENT_TAB;
+               state.tab_base = 0;
+           }
+           break;
+       }
+
+       if (current_x <= 0)
+           break;
+
+       current_x -= blank_mb_len;
+       line += blank_mb_len;
+    }
+
+    free(blank_mb);
+
+    *tab_type = state.tab_type;
+    *tab_base = state.tab_base;
+
+    return at_base;
+}
+
 #ifndef DISABLE_JUSTIFY
 /* justify_format() replaces blanks with spaces and multiple spaces by 1
  * (except it maintains up to 2 after a character in punct optionally
  * followed by a character in brackets, and removes all from the end).
@@ -2431,9 +2486,10 @@
                word)) {
            size_t xpt = xplustabs();
            char *exp_word = display_string(openfile->current->data,
                xpt, strnlenpt(openfile->current->data,
-               openfile->current_x + match_len) - xpt, FALSE);
+               openfile->current_x + match_len) - xpt, FALSE,
+               TRUE);
 
            edit_refresh();
 
            do_replace_highlight(TRUE, exp_word);
diff -r -U4 nano-2.1.10/src/utils.c nano-2.1.10+tabsize2/src/utils.c
--- nano-2.1.10/src/utils.c     2009-06-06 05:39:12.000000000 +0100
+++ nano-2.1.10+tabsize2/src/utils.c    2009-09-27 14:44:27.000000000 +0100
@@ -481,17 +481,21 @@
 size_t actual_x(const char *s, size_t column)
 {
     size_t i = 0;
        /* The position in s, returned. */
-    size_t len = 0;
+    mblinestate state;
        /* The screen display width to s[i]. */
 
+    state.col = 0;
+    state.tab_type = INDENT_TAB;
+    state.tab_base = 0;
+
     assert(s != NULL);
 
     while (*s != '\0') {
-       int s_len = parse_mbchar(s, NULL, &len);
+       int s_len = parse_mbchar(s, NULL, &state);
 
-       if (len > column)
+       if (state.col > column)
            break;
 
        i += s_len;
        s += s_len;
@@ -504,18 +508,22 @@
  * to xplustabs().  How many columns wide are the first maxlen characters
  * of s? */
 size_t strnlenpt(const char *s, size_t maxlen)
 {
-    size_t len = 0;
+    mblinestate state;
        /* The screen display width to s[i]. */
 
     if (maxlen == 0)
        return 0;
 
+    state.col = 0;
+    state.tab_type = INDENT_TAB;
+    state.tab_base = 0;
+
     assert(s != NULL);
 
     while (*s != '\0') {
-       int s_len = parse_mbchar(s, NULL, &len);
+       int s_len = parse_mbchar(s, NULL, &state);
 
        s += s_len;
 
        if (maxlen <= s_len)
@@ -523,9 +531,9 @@
 
        maxlen -= s_len;
     }
 
-    return len;
+    return state.col;
 }
 
 /* A strlen() with tabs and multicolumn characters factored in, similar
  * to xplustabs().  How many columns wide is s? */
diff -r -U4 nano-2.1.10/src/winio.c nano-2.1.10+tabsize2/src/winio.c
--- nano-2.1.10/src/winio.c     2009-07-03 04:37:46.000000000 +0100
+++ nano-2.1.10+tabsize2/src/winio.c    2009-09-27 14:47:36.000000000 +0100
@@ -1898,9 +1898,9 @@
  * string is dynamically allocated, and should be freed.  If dollars is
  * TRUE, the caller might put "$" at the beginning or end of the line if
  * it's too long. */
 char *display_string(const char *buf, size_t start_col, size_t len, bool
-       dollars)
+       dollars, bool indented_tabs)
 {
     size_t start_index;
        /* Index in buf of the first character shown. */
     size_t column;
@@ -1910,8 +1910,12 @@
     char *converted;
        /* The string we return. */
     size_t index;
        /* Current position in converted. */
+    tabsize_type tab_type;
+       /* Current tab type. */
+    size_t tab_base;
+       /* Current tab base. */
     char *buf_mb;
     int buf_mb_len;
 
     /* If dollars is TRUE, make room for the "$" at the end of the
@@ -1926,8 +1930,15 @@
 
     start_index = actual_x(buf, start_col);
     column = strnlenpt(buf, start_index);
 
+    if (indented_tabs) {
+       calc_tabsize(buf, start_index, &tab_type, &tab_base);
+    } else {
+       tab_type = ALIGN_TAB;
+       tab_base = 0;
+    }
+
     assert(column <= start_col);
 
     /* Make sure there's enough room for the initial character, whether
      * it's a multibyte control character, a non-control multibyte
@@ -1941,9 +1952,9 @@
      *     mb_cur_max() bytes + (tabsize - 1) bytes + 1 byte ('\0')
      *
      * Since tabsize has a minimum value of 1, it can substitute for 1
      * byte above. */
-    alloc_len = (mb_cur_max() + tabsize + 1) * MAX_BUF_SIZE;
+    alloc_len = (mb_cur_max() + tabsize[tab_type] + 1) * MAX_BUF_SIZE;
     converted = charalloc(alloc_len);
 
     index = 0;
 
@@ -1952,8 +1963,14 @@
        /* We don't display all of buf[start_index] since it starts to
         * the left of the screen. */
        buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL);
 
+       /* Handle tab type changing. */
+       if (tab_type == 0 && !is_blank_mbchar(buf_mb)) {
+           tab_type = ALIGN_TAB;
+           tab_base = start_col - (start_col % tabsize[INDENT_TAB]);
+       }
+
        if (is_cntrl_mbchar(buf_mb)) {
            if (column < start_col) {
                char *ctrl_buf_mb = charalloc(mb_cur_max());
                int ctrl_buf_mb_len, i;
@@ -1988,13 +2005,21 @@
 
     while (buf[start_index] != '\0') {
        buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL);
 
+       /* Handle tab type changing. */
+       if (tab_type == 0 && !is_blank_mbchar(buf_mb)) {
+           tab_type = ALIGN_TAB;
+           tab_base = start_col - (start_col % tabsize[INDENT_TAB]);
+       }
+
        /* Make sure there's enough room for the next character, whether
         * it's a multibyte control character, a non-control multibyte
         * character, a tab character, or a null terminator. */
-       if (index + mb_cur_max() + tabsize + 1 >= alloc_len - 1) {
-           alloc_len += (mb_cur_max() + tabsize + 1) * MAX_BUF_SIZE;
+       if (index + mb_cur_max() + tabsize[tab_type] + 1
+               >= alloc_len - 1) {
+           alloc_len += (mb_cur_max() + tabsize[tab_type] + 1)
+                   * MAX_BUF_SIZE;
            converted = charealloc(converted, alloc_len);
        }
 
        /* If buf contains a tab character, interpret it. */
@@ -2008,9 +2033,9 @@
            } else
 #endif
                converted[index++] = ' ';
            start_col++;
-           while (start_col % tabsize != 0) {
+           while ((start_col - tab_base) % tabsize[tab_type] != 0) {
                converted[index++] = ' ';
                start_col++;
            }
        /* If buf contains a control character, interpret it.  If buf
@@ -2201,9 +2226,10 @@
            space -= 3;
        } else
            start_col = 0;
 
-       exppath = display_string(path, start_col, space, FALSE);
+       exppath = display_string(path, start_col, space, FALSE,
+               FALSE);
     }
 
     /* If dots is TRUE, we will display something like "File:
      * ...ename". */
@@ -2291,9 +2317,9 @@
 #endif
     bar = charalloc(mb_cur_max() * (COLS - 3));
     vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
     va_end(ap);
-    foo = display_string(bar, 0, COLS - 4, FALSE);
+    foo = display_string(bar, 0, COLS - 4, FALSE, FALSE);
 #if !defined(NANO_TINY) && defined(ENABLE_NANORC)
     if (old_whitespace)
        SET(WHITESPACE_DISPLAY);
 #endif
@@ -2839,9 +2865,10 @@
     page_start = get_page_start(index);
 
     /* Expand the line, replacing tabs with spaces, and control
      * characters with their displayed forms. */
-    converted = display_string(fileptr->data, page_start, COLS, TRUE);
+    converted = display_string(fileptr->data, page_start, COLS, TRUE,
+           TRUE);
 
     /* Paint the line. */
     edit_draw(fileptr, converted, line, page_start);
     free(converted);

-- 
Simon Arlott

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]