]> git.wh0rd.org Git - nano.git/commitdiff
fix the NANO_WIDE #ifdefs again, and put display_string_len() back in
authorDavid Lawrence Ramsey <pooka109@gmail.com>
Mon, 27 Dec 2004 23:11:59 +0000 (23:11 +0000)
committerDavid Lawrence Ramsey <pooka109@gmail.com>
Mon, 27 Dec 2004 23:11:59 +0000 (23:11 +0000)
now that it doesn't corrupt memory anymore (as far as I can tell)

git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@2202 35c25a1d-7b9e-4130-9fde-d3aeb78583b8

ChangeLog
src/winio.c

index 8a160f445109d461ac48a77a1af5cdd964d13565..8137dd21ea170b630eef4fef504f0d0ded98099f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -52,12 +52,12 @@ CVS code -
          Movement and cursor display in the edit window should now work
          properly with files containing multibyte characters, and text
          display of such files should work properly some of the time.
-         New functions control_rep(), parse_char(), move_left(), and
-         move_right(); changes to do_left(), do_right(), do_delete(),
-         breakable(), break_line(), do_output(), get_buffer(),
-         unget_input(), actual_x(), strnlenpt(), display_string(),
-         titlebar(), statusbar(), onekey(), and do_credits(). (David
-         Benbennick and DLR)
+         New functions control_rep(), parse_char(), move_left(),
+         move_right(), and display_string_len(); changes to do_left(),
+         do_right(), do_delete(), breakable(), break_line(),
+         do_output(), get_buffer(), unget_input(), actual_x(),
+         strnlenpt(), display_string(), titlebar(), statusbar(),
+         onekey(), and do_credits(). (David Benbennick and DLR)
 - cut.c:
   do_cut_text()
        - If keep_cutbuffer is FALSE, only blow away the text in the
index df26baf722fe30e7d0828782cda8c89548277ef0..c9937b6c734f49f8f3295d014c6869485b71fcea 100644 (file)
@@ -1720,6 +1720,109 @@ void blank_bottombars(void)
     }
 }
 
+/* buf is a multibyte string to be displayed.  We need to expand tabs
+ * and control characters.  How many bytes do we need to display?
+ * start_col is the column of *buf (usually 0).  We display to
+ * (end_col - 1). */
+size_t display_string_len(const char *buf, size_t start_col, size_t
+       end_col)
+{
+    size_t retval = 0;
+
+    assert(buf != NULL);
+
+    /* Throughout the loop, we maintain the fact that *buf displays at
+     * column start_col. */
+    while (start_col <= end_col && *buf != '\0') {
+       int wide_buf, wide_buf_len;
+       size_t old_col = start_col;
+#ifdef NANO_WIDE
+       bool bad_char;
+#endif
+
+       wide_buf_len = parse_char(buf, &wide_buf, &start_col
+#ifdef NANO_WIDE
+               , &bad_char
+#endif
+               );
+
+#ifdef NANO_WIDE
+       /* If buf contains a null byte or an invalid multibyte
+        * character, interpret that character as though it's a wide
+        * character. */
+       if (!ISSET(NO_UTF8) && bad_char) {
+           char *bad_wide_buf = charalloc(MB_CUR_MAX);
+           int bad_wide_buf_len;
+
+           /* If we have a control character, add one byte to account
+            * for the "^" that will be displayed in front of it, and
+            * translate the character to its visible equivalent as
+            * returned by control_rep(). */
+           if (is_cntrl_char(wide_buf)) {
+               retval++;
+               wide_buf = control_rep((unsigned char)wide_buf);
+           }
+
+           /* Translate the wide character to its multibyte
+            * equivalent. */
+           bad_wide_buf_len = wctomb(bad_wide_buf, (wchar_t)wide_buf);
+
+           if (bad_wide_buf_len != -1)
+               retval += bad_wide_buf_len;
+
+           free(bad_wide_buf);
+       } else {
+#endif
+           /* If we have a tab, get its width in bytes using the
+            * current value of col. */
+           if (wide_buf == '\t')
+               retval += start_col - old_col;
+           /* If we have a control character, add one byte to account
+            * for the "^" that will be displayed in front of it, and
+            * then add the number of bytes for its visible equivalent
+            * as returned by control_rep().  If we have an invalid
+            * multibyte control character, interpret that character as
+            * though it's a normal control character. */
+           else if (is_cntrl_char(wide_buf)) {
+               char ctrl_wide_buf =
+                       control_rep((unsigned char)wide_buf);
+
+               retval++;
+               retval += parse_char(&ctrl_wide_buf, NULL, NULL
+#ifdef NANO_WIDE
+                       , NULL
+#endif
+                       );
+           /* If we have a normal character, add its width in bytes
+            * normally. */
+           } else
+#ifdef NANO_WIDE
+           /* If buf contains an invalid multibyte non-control
+            * character, interpret that character as though it's a
+            * normal non-control character. */
+           if (!ISSET(NO_UTF8) && bad_char) {
+               char *bad_wide_buf = charalloc(MB_CUR_MAX);
+               int bad_wide_buf_len;
+
+               bad_wide_buf_len = wctomb(bad_wide_buf,
+                       (wchar_t)wide_buf);
+
+               free(bad_wide_buf);
+
+               retval += bad_wide_buf_len;
+           } else
+#endif
+               retval += wide_buf_len;
+#ifdef NANO_WIDE
+       }
+
+       buf += wide_buf_len;
+#endif
+    }
+
+    return retval;
+}
+
 /* Convert buf into a string that can be displayed on screen.  The
  * caller wants to display buf starting with column start_col, and
  * extending for at most len columns.  start_col is zero-based.  len is
@@ -1755,13 +1858,8 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
 
     assert(column <= start_col);
 
-#ifdef NANO_WIDE
-    if (!ISSET(NO_UTF8))
-       alloc_len = len * MB_CUR_MAX;
-    else
-#endif
-       alloc_len = len;
-
+    alloc_len = display_string_len(buf + start_index, start_col,
+       start_col + COLS);
     converted = charalloc(alloc_len + 1);
     index = 0;
 
@@ -1787,12 +1885,18 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
                int ctrl_wide_buf_len, i;
 
                wide_buf = control_rep((unsigned char)wide_buf);
-               ctrl_wide_buf_len =
+
+#ifdef NANO_WIDE
+               if (!ISSET(NO_UTF8))
+                   ctrl_wide_buf_len = wctomb(ctrl_wide_buf,
+                       (wchar_t)wide_buf);
+               else {
+#endif
+                   ctrl_wide_buf_len = 1;
+                   ctrl_wide_buf[0] = (unsigned char)wide_buf;
 #ifdef NANO_WIDE
-                       !ISSET(NO_UTF8) ? wctomb(ctrl_wide_buf,
-                       (wchar_t)wide_buf) :
+               }
 #endif
-                       1;
 
                for (i = 0; i < ctrl_wide_buf_len; i++)
                    converted[index++] = ctrl_wide_buf[i];
@@ -1826,27 +1930,6 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
 #endif
                );
 
-#ifdef NANO_WIDE
-       if (!ISSET(NO_UTF8) && bad_char) {
-           char *bad_wide_buf = charalloc(MB_CUR_MAX);
-           int bad_wide_buf_len, i;
-
-           if (is_cntrl_char(wide_buf)) {
-               converted[index++] = '^';
-               start_col++;
-               wide_buf = control_rep((unsigned char)wide_buf);
-           }
-
-           bad_wide_buf_len = wctomb(bad_wide_buf, (wchar_t)wide_buf);
-
-           for (i = 0; i < bad_wide_buf_len; i++)
-               converted[index++] = bad_wide_buf[i];
-
-           free(bad_wide_buf);
-
-           start_col += wcwidth((wchar_t)wide_buf);
-       } else
-#endif
        if (wide_buf == '\t') {
            converted[index++] =
 #if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
@@ -1858,6 +1941,9 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
                converted[index++] = ' ';
                start_col++;
            }
+       /* If buf contains a control character, interpret it.  If it
+        * contains an invalid multibyte control character, interpret
+        * that character as though it's a normal control character. */
        } else if (is_cntrl_char(wide_buf)) {
            char *ctrl_wide_buf =
 #ifdef NANO_WIDE
@@ -1870,12 +1956,17 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
            start_col++;
            wide_buf = control_rep((unsigned char)wide_buf);
 
-           ctrl_wide_buf_len =
 #ifdef NANO_WIDE
-               !ISSET(NO_UTF8) ? wctomb(ctrl_wide_buf,
-               (wchar_t)wide_buf) :
+           if (!ISSET(NO_UTF8))
+               ctrl_wide_buf_len = wctomb(ctrl_wide_buf,
+                       (wchar_t)wide_buf);
+           else {
+#endif
+               ctrl_wide_buf_len = 1;
+               ctrl_wide_buf[0] = (unsigned char)wide_buf;
+#ifdef NANO_WIDE
+           }
 #endif
-               1;
 
            for (i = 0; i < ctrl_wide_buf_len; i++)
                converted[index++] = ctrl_wide_buf[i];
@@ -1897,10 +1988,28 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
        } else {
            int i;
 
-           for (i = 0; i < wide_buf_len; i++)
-               converted[index++] = buf[start_index + i];
+#ifdef NANO_WIDE
+           /* If buf contains an invalid multibyte non-control
+            * character, interpret that character as though it's a
+            * normal non-control character. */
+           if (!ISSET(NO_UTF8) && bad_char) {
+               char *bad_wide_buf = charalloc(MB_CUR_MAX);
+               int bad_wide_buf_len;
+
+               bad_wide_buf_len = wctomb(bad_wide_buf,
+                       (wchar_t)wide_buf);
 
+               for (i = 0; i < bad_wide_buf_len; i++)
+                   converted[index++] = bad_wide_buf[i];
+
+               free(bad_wide_buf);
+           } else {
+#endif
+               for (i = 0; i < wide_buf_len; i++)
+                   converted[index++] = buf[start_index + i];
 #ifdef NANO_WIDE
+           }
+
            if (!ISSET(NO_UTF8))
                start_col += wcwidth((wchar_t)wide_buf);
            else