bug-texinfo
[Top][All Lists]
Advanced

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

[PATCHes] Add basic multibyte charset handling to makeinfo


From: Miloslav Trmac
Subject: [PATCHes] Add basic multibyte charset handling to makeinfo
Date: Mon, 04 Dec 2006 22:11:24 +0100
User-agent: Thunderbird 1.5.0.8 (X11/20061107)

Hello,
The attached patches add support for multibyte character sets (e.g.
UTF-8) and multi-column characters (e.g. Chinese) to makeinfo.

texinfo-4.8-0xA0.patch:
Don't replace 0xA0 bytes in the input by spaces, sacrifice 036 (0x1E)
instead.  This is absolutely necessary for non-ASCII character set support.
        * makeinfo/makeinfo.h (NON_BREAKING_SPACE): New macro.
        (control_character_bit, meta_character_bit, CTL, UNCTL, META)
        (UNMETA): Remove.
        * makeinfo/makeinfo.c (add_char, flush_output): Use
        NON_BREAKING_SPACE instead of META (' ').


texinfo-4.8-makeinfo-multibyte.patch:
The rest of the multibyte support, making the various alignment and
filling operations multibyte-aware.

There are two potential problems with the patch:
* It uses the character encoding of the current locale instead of
  the character encoding specified in @documentencoding.  The patch
  needs to use the libc locale information for character widths and
  there is no portable way to specify a locale using a specific
  character set.  The alternative would be to add the character width
  database to makeinfo, which is IMHO even worse.  makeinfo will still
  work correctly if the character encoding doesn't match the current
  locale, it will only produce something similar to the output it
  produces now.
* The check for folding in add_char () is now O (current line length)
  instead of O (1).  This could be fixed by making add_char () aware of
  the inner workings of string_width (), which is rather ugly.

        * configure.ac: Test wcwidth () availability.
        * makeinfo/makeinfo.h (string_width, current_output_column): New
        declarations.
        (output_column): Remove.  All users replaced by
        current_output_column (), all modifications dropped.
        * makeinfo/makeinfo.c (string_width, current_output_column): New
        functions.
        (get_char_len): Remove.

        * makeinfo/cmds.c (cm_center)
        * makeinfo/index.c (insert_index_output_line_no, cm_printindex):
        * makeinfo/makeinfo.c (do_flush_right_indentation)
        * makeinfo/multi.c (output_multitable_row):
        Don't assume number of columns == number of bytes.


To test the effects of the patches, compare the output of makeinfo for
the attached test file.

Thanks,
        Mirek
diff -ur texinfo/makeinfo/makeinfo.c texinfo-4.8/makeinfo/makeinfo.c
--- texinfo/makeinfo/makeinfo.c 2004-12-19 18:15:42.000000000 +0100
+++ texinfo-4.8/makeinfo/makeinfo.c     2006-12-02 09:53:58.000000000 +0100
@@ -2584,7 +2584,7 @@
           character = ';';
         }
       else
-        character = META (' '); /* unmeta-d in flush_output */
+        character = NON_BREAKING_SPACE; /* restored in flush_output */
     }
 
   insertion_paragraph_closed = 0;
@@ -2922,17 +2922,11 @@
           node_line_number++;
         }
 
-      /* If we turned on the 8th bit for a space inside @w, turn it
-         back off for output.  This might be problematic, since the
-         0x80 character may be used in 8-bit character sets.  Sigh.
-         In any case, don't do this for HTML, since the nbsp character
-         is valid input and must be passed along to the browser.  */
-      if (!html && (output_paragraph[i] & meta_character_bit))
-        {
-          int temp = UNMETA (output_paragraph[i]);
-          if (temp == ' ')
-            output_paragraph[i] &= 0x7f;
-        }
+      /* If we turned on the 8th bit for a space inside @w, turn it back off
+         for output.  Don't do this for HTML, since the nbsp character is valid
+         input and must be passed along to the browser.  */
+      if (!html && output_paragraph[i] == NON_BREAKING_SPACE)
+       output_paragraph[i] = ' ';
     }
 
   fwrite (output_paragraph, 1, output_paragraph_offset, output_stream);
diff -ur texinfo/makeinfo/makeinfo.h texinfo-4.8/makeinfo/makeinfo.h
--- texinfo/makeinfo/makeinfo.h 2004-11-30 03:03:23.000000000 +0100
+++ texinfo-4.8/makeinfo/makeinfo.h     2006-12-02 09:55:43.000000000 +0100
@@ -242,13 +242,6 @@
 #define coerce_to_upper(c) ((islower(c) ? toupper(c) : (c)))
 #define coerce_to_lower(c) ((isupper(c) ? tolower(c) : (c)))
 
-#define control_character_bit 0x40 /* %01000000, must be off. */
-#define meta_character_bit 0x080/* %10000000, must be on.  */
-#define CTL(c) ((c) & (~control_character_bit))
-#define UNCTL(c) coerce_to_upper(((c)|control_character_bit))
-#define META(c) ((c) | (meta_character_bit))
-#define UNMETA(c) ((c) & (~meta_character_bit))
-
 #define whitespace(c)       ((c) == '\t' || (c) == ' ')
 #define sentence_ender(c)   ((c) == '.'  || (c) == '?' || (c) == '!')
 #define cr_or_whitespace(c) (whitespace(c) || (c) == '\r' || (c) == '\n')
@@ -282,6 +275,9 @@
 
 #define COMMAND_PREFIX '@'
 
+/* A byte value to represent a non-breaking space until flush_output (). */
+#define NON_BREAKING_SPACE 036
+
 #define END_VERBATIM "end verbatim"
 
 /* Stuff for splitting large files.  The numbers for Emacs
diff -ur texinfo/configure.ac texinfo-4.8/configure.ac
--- texinfo/configure.ac        2004-12-31 19:00:48.000000000 +0100
+++ texinfo-4.8/configure.ac    2006-12-04 20:58:24.000000000 +0100
@@ -69,7 +69,7 @@
 # that anyone compiling new texinfo still has such a thing? we'll see.
 # AC_FUNC_SETVBUF_REVERSED
 AC_CHECK_FUNCS(bzero getcwd memset setvbuf sigaction sigprocmask \
-               sigsetmask strchr)
+               sigsetmask strchr wcwidth)
 AC_REPLACE_FUNCS(memcpy memmove strdup strerror)
 
 # strcasecmp and strncasecmp, gnulib-style.
diff -ur texinfo/makeinfo/cmds.c texinfo-4.8/makeinfo/cmds.c
--- texinfo/makeinfo/cmds.c     2004-12-14 01:15:36.000000000 +0100
+++ texinfo-4.8/makeinfo/cmds.c 2006-12-02 11:59:07.000000000 +0100
@@ -1501,7 +1501,7 @@
     }
   else
     {
-      int i, start, length;
+      int i, start, length, width;
       char *line;
       int save_indented_fill = indented_fill;
       int save_filling_enabled = filling_enabled;
@@ -1530,13 +1530,14 @@
 
            output_paragraph_offset = ++i;
            length = output_paragraph_offset - start;
+          width = string_width ((char *)(output_paragraph + start), length);
 
-           if (length < (fill_column - fudge_factor))
+           if (width < (fill_column - fudge_factor))
              {
                line = xmalloc (1 + length);
                memcpy (line, (char *)(output_paragraph + start), length);
 
-               i = (fill_column - fudge_factor - length) / 2;
+               i = (fill_column - fudge_factor - width) / 2;
                output_paragraph_offset = start;
 
                while (i--)
diff -ur texinfo/makeinfo/index.c texinfo-4.8/makeinfo/index.c
--- texinfo/makeinfo/index.c    2004-11-30 03:03:23.000000000 +0100
+++ texinfo-4.8/makeinfo/index.c        2006-12-02 12:24:21.000000000 +0100
@@ -657,7 +657,7 @@
 static void
 insert_index_output_line_no (int line_number, int output_line_number_len)
 {
-  int last_column;
+  int last_column, out_line_no_width;
   int str_size = output_line_number_len + strlen (_("(line )"))
     + sizeof (NULL);
   char *out_line_no_str = (char *) xmalloc (str_size + 1);
@@ -673,16 +673,18 @@
     int i = output_paragraph_offset; 
     while (0 < i && output_paragraph[i-1] != '\n')
       i--;
-    last_column = output_paragraph_offset - i;
+    last_column = string_width ((char *)(output_paragraph + i),
+                               output_paragraph_offset - i);
   }
 
-  if (last_column + strlen (out_line_no_str) > fill_column)
+  out_line_no_width = string_width (out_line_no_str, strlen (out_line_no_str));
+  if (last_column + out_line_no_width > fill_column)
     {
       insert ('\n');
       last_column = 0;
     }
 
-  while (last_column + strlen (out_line_no_str) < fill_column)
+  while (last_column + out_line_no_width < fill_column)
     {
       insert (' ');
       last_column++;
@@ -877,7 +879,10 @@
             }
           else
             {
-              unsigned new_length = strlen (index->entry);
+#define MIN_ENTRY_COLUMNS 37
+             /* Make sure there is enough space even if index->entry has zero
+                width. */
+              unsigned new_length = strlen (index->entry) + MIN_ENTRY_COLUMNS;
 
               if (new_length < 50) /* minimum length used below */
                 new_length = 50;
@@ -894,7 +899,13 @@
                  @@ has turned into @. */
               if (!no_headers)
                 {
-                  sprintf (line, "* %-37s  ", index->entry);
+                 int width;
+
+                 width = string_width (index->entry, strlen (index->entry));
+                  sprintf (line, "* %*s  ", width < MIN_ENTRY_COLUMNS
+                          ? -(strlen (index->entry)
+                              + (MIN_ENTRY_COLUMNS - width))
+                          : 0, index->entry);
                   line[2 + strlen (index->entry)] = ':';
                   insert_string (line);
                   /* Make sure any non-macros in the node name are expanded.  
*/
diff -ur texinfo/makeinfo/insertion.c texinfo-4.8/makeinfo/insertion.c
--- texinfo/makeinfo/insertion.c        2004-11-11 19:34:28.000000000 +0100
+++ texinfo-4.8/makeinfo/insertion.c    2006-12-04 19:38:37.000000000 +0100
@@ -370,7 +370,7 @@
   else
     sprintf (temp, "%d. ", current_enumval);
 
-  indent (output_column += (current_indent - strlen (temp)));
+  indent (current_output_column () + (current_indent - strlen (temp)));
   add_word (temp);
   current_enumval++;
 }
@@ -2194,8 +2194,7 @@
 
                   if (current_item_function ())
                     {
-                      output_column = current_indent - 2;
-                      indent (output_column);
+                      indent (current_indent - 2);
 
                       /* The item marker can be given with or without
                          braces -- @bullet and @bullet{} are both ok.
@@ -2214,7 +2213,6 @@
                             execute_string ("%s", item_func);
                         }
                       insert (' ');
-                      output_column++;
                     }
                   else
                     enumerate_item ();
diff -ur texinfo/makeinfo/macro.c texinfo-4.8/makeinfo/macro.c
--- texinfo/makeinfo/macro.c    2004-04-11 19:56:47.000000000 +0200
+++ texinfo-4.8/makeinfo/macro.c        2006-12-04 19:44:46.000000000 +0100
@@ -899,13 +899,12 @@
 void
 me_execute_string_keep_state (char *execution_string, char *append_string)
 {
-  int op_orig, opcol_orig, popen_orig;
+  int op_orig, popen_orig;
   int fill_orig, newline_orig, indent_orig, meta_pos_orig;
 
   remember_itext (input_text, input_text_offset);
   op_orig = output_paragraph_offset;
   meta_pos_orig = meta_char_pos;
-  opcol_orig = output_column;
   popen_orig = paragraph_is_open;
   fill_orig = filling_enabled;
   newline_orig = last_char_was_newline;
@@ -917,7 +916,6 @@
     write_region_to_macro_output (append_string, 0, strlen (append_string));
   output_paragraph_offset = op_orig;
   meta_char_pos = meta_pos_orig;
-  output_column = opcol_orig;
   paragraph_is_open = popen_orig;
   filling_enabled = fill_orig;
   last_char_was_newline = newline_orig;
diff -ur texinfo/makeinfo/makeinfo.c texinfo-4.8/makeinfo/makeinfo.c
--- texinfo/makeinfo/makeinfo.c 2006-12-02 10:01:25.000000000 +0100
+++ texinfo-4.8/makeinfo/makeinfo.c     2006-12-04 21:30:52.000000000 +0100
@@ -39,6 +39,10 @@
 #include "toc.h"
 #include "xml.h"
 
+#ifdef HAVE_WCWIDTH
+# include <wchar.h>
+#endif
+
 /* You can change some of the behavior of Makeinfo by changing the
    following defines: */
 
@@ -1843,7 +1847,6 @@
   output_paragraph = xmalloc (paragraph_buffer_len);
   output_paragraph[0] = 0;
   output_paragraph_offset = 0;
-  output_column = 0;
   paragraph_is_open = 0;
   current_indent = 0;
   meta_char_pos = 0;
@@ -2407,37 +2410,97 @@
     }
 }
 
-static int
-get_char_len (int character)
+/* Return the number of columns necessary for displaying STRING of LEN
+   bytes. */
+int
+string_width (const char *string, size_t length)
 {
-  /* Return the printed length of the character. */
-  int len;
+#ifdef HAVE_WCWIDTH
+  int width;
 
-  switch (character)
+  mbtowc (NULL, NULL, 0);
+  width = 0;
+  while (length > 0)
     {
-    case '\t':
-      len = (output_column + 8) & 0xf7;
-      if (len > fill_column)
-        len = fill_column - output_column;
+      wchar_t wc;
+      int l, w;
+
+      l = mbtowc (&wc, string, length);
+      if (l == -1)
+       {
+         mbtowc (NULL, NULL, 0);
+         w = 1;
+         l = 1;
+       }
       else
-        len = len - output_column;
-      break;
+       {
+         if (l == 0)
+           l = 1;
+         w = wcwidth (wc);
+         if (w == -1)
+           w = 1;
+       }
+      width += w;
+      string += l;
+      length -= l;
+    }
+  return width;
+#endif
+  return length;
+}
 
-    case '\n':
-      len = fill_column - output_column;
-      break;
+/* Return the 0-based number of the current output column */
+int
+current_output_column (void)
+{
+  int i, column;
 
-    default:
-      /* ASCII control characters appear as two characters in the output
-         (e.g., ^A).  But characters with the high bit set are just one
-         on suitable terminals, so don't count them as two for line
-         breaking purposes.  */
-      if (0 <= character && character < ' ')
-        len = 2;
-      else
-        len = 1;
+  for (i = output_paragraph_offset; i > 0 && output_paragraph[i - 1] != '\n';
+       i--)
+    ;
+  column = 0;
+  while (i < output_paragraph_offset)
+    {
+      int j;
+
+      /* Find a span of non-control characters */
+      for (j = i; j < output_paragraph_offset; j++)
+       {
+         char c;
+
+         c = output_paragraph[j];
+         if ((0 <= c && c < ' ') || c == '\t')
+           break;
+       }
+      if (i < j)
+       {
+         column += string_width ((char *)(output_paragraph + i), j - i);
+         i = j;
+       }
+      if (i < output_paragraph_offset)
+       {
+         char c;
+
+         /* Handle a control character */
+         c = output_paragraph[i];
+         if (c == '\t')
+           {
+             column = (column + 8) & ~0x7;
+             if (column > fill_column)
+               column = fill_column;
+           }
+         else
+           {
+             /* ASCII control characters appear as two characters in the
+                output (e.g., ^A).  */
+             if (!(0 <= c && c < ' '))
+               abort ();
+             column += 2;
+           }
+         i++;
+       }
     }
-  return len;
+  return column;
 }
 
 void
@@ -2562,13 +2625,13 @@
      ignore close_paragraph () calls any more. */
   if (must_start_paragraph && character != '\n')
     {
+      int column;
+
       must_start_paragraph = 0;
       line_already_broken = 0;  /* The line is no longer broken. */
-      if (current_indent > output_column)
-        {
-          indent (current_indent - output_column);
-          output_column = current_indent;
-        }
+      column = current_output_column ();
+      if (current_indent > column)
+       indent (current_indent - column);
     }
 
   if (non_splitting_words
@@ -2603,17 +2666,14 @@
               flush_output ();
             }
 
-          output_column = 0;
-
           if (!no_indent && paragraph_is_open)
-            indent (output_column = current_indent);
+            indent (current_indent);
           break;
         }
       else if (end_of_sentence_p ())
         /* CHARACTER is newline, and filling is enabled. */
         {
           insert (' ');
-          output_column++;
           last_inserted_character = character;
         }
 
@@ -2631,13 +2691,12 @@
             insert ('\n');
           else
             insert (' ');
-          output_column++;
         }
       break;
 
     default: /* not at newline */
       {
-        int len = get_char_len (character);
+        int column;
         int suppress_insert = 0;
 
         if ((character == ' ') && (last_char_was_newline))
@@ -2685,8 +2744,20 @@
               }
           }
 
-        output_column += len;
-        if (output_column > fill_column)
+       output_paragraph[output_paragraph_offset] = character;
+       output_paragraph_offset++;
+       column = current_output_column ();
+       output_paragraph_offset--;
+       /* The string_width () in current_output_column () cannot predict
+          future incoming bytes.  So if output_paragraph ends in a partial
+          multibyte character, its bytes are counted as separate column
+          positions.  This may push column past fill_column, even though the
+          finished multibyte character would fit on the current line.
+
+          This is too hard to fix without modifying add_char () to recieve
+          complete multibyte characters at a time, and causes only slightly
+          incorrect paragraph filling, so we punt.  */
+        if (column > fill_column)
           {
             if (filling_enabled && !html)
               {
@@ -2773,11 +2844,6 @@
                             output_paragraph_offset += current_indent;
                             free (temp_buffer);
                           }
-                        output_column = 0;
-                        while (temp < output_paragraph_offset)
-                          output_column +=
-                            get_char_len (output_paragraph[temp++]);
-                        output_column += len;
                         break;
                       }
                   }
@@ -2870,7 +2936,6 @@
   /* Handle infinite case first. */
   if (count < 0)
     {
-      output_column = 0;
       while (output_paragraph_offset)
         {
           if (whitespace (output_paragraph[output_paragraph_offset - 1]))
@@ -2982,6 +3047,8 @@
     }
   else
     {
+      int column;
+
       /* If the insertion paragraph is closed already, then we are seeing
          two address@hidden' commands in a row.  Note that the first one we 
saw was
          handled in the first part of this if-then-else clause, and at that
@@ -2989,8 +3056,9 @@
          indentation of the current line.  However, the indentation level
          may have just changed again, so we may have to outdent the current
          line to the new indentation level. */
-      if (current_indent < output_column)
-        kill_self_indent (output_column - current_indent);
+      column = current_output_column ();
+      if (current_indent < column)
+        kill_self_indent (column - current_indent);
     }
 
   insertion_paragraph_closed = 1;
@@ -3056,7 +3124,6 @@
       flush_output ();
       paragraph_is_open = 0;
       no_indent = 0;
-      output_column = 0;
     }
 
   ignore_blank_line ();
@@ -3070,38 +3137,42 @@
   last_char_was_newline = 1;
 }
 
-/* Align the end of the text in output_paragraph with fill_column. */
+/* Align the end of the text in output_paragraph with fill_column.  The last
+   character in output_paragraph is '\n'. */
 static void
 do_flush_right_indentation (void)
 {
   char *temp;
-  int temp_len;
 
   kill_self_indent (-1);
 
   if (output_paragraph[0] != '\n')
     {
-      output_paragraph[output_paragraph_offset] = 0;
+      int width;
 
-      if (output_paragraph_offset < fill_column)
+      /* Make sure to exclude the trailing '\n', wcswidth () doesn't like
+        it. */
+      width = string_width((char *)output_paragraph,
+                          output_paragraph_offset - 1) + 1;
+      if (width < fill_column)
         {
           int i;
 
-          if (fill_column >= paragraph_buffer_len)
+          if (output_paragraph_offset + (fill_column - width)
+             >= paragraph_buffer_len)
             output_paragraph =
               xrealloc (output_paragraph,
                         (paragraph_buffer_len += fill_column));
 
-          temp_len = strlen ((char *)output_paragraph);
-          temp = xmalloc (temp_len + 1);
-          memcpy (temp, (char *)output_paragraph, temp_len);
+          temp = xmalloc (output_paragraph_offset);
+          memcpy (temp, (char *)output_paragraph, output_paragraph_offset);
 
-          for (i = 0; i < fill_column - output_paragraph_offset; i++)
+          for (i = 0; i < fill_column - width; i++)
             output_paragraph[i] = ' ';
 
-          memcpy ((char *)output_paragraph + i, temp, temp_len);
+          memcpy ((char *)output_paragraph + i, temp, output_paragraph_offset);
           free (temp);
-          output_paragraph_offset = fill_column;
+          output_paragraph_offset += i;
           adjust_braces_following (0, i);
         }
     }
@@ -3131,6 +3202,8 @@
       /* If doing indentation, then insert the appropriate amount. */
       if (!no_indent)
         {
+         int column;
+
           if (inhibit_paragraph_indentation)
             {
               amount_to_indent = current_indent;
@@ -3142,12 +3215,9 @@
           else
             amount_to_indent = current_indent + paragraph_start_indent;
 
-          if (amount_to_indent >= output_column)
-            {
-              amount_to_indent -= output_column;
-              indent (amount_to_indent);
-              output_column += amount_to_indent;
-            }
+         column = current_output_column ();
+          if (amount_to_indent >= column)
+           indent (amount_to_indent - column);
         }
     }
   else
@@ -3636,7 +3706,6 @@
       output_paragraph[end_pos] = 0;
       name = xstrdup (name);
       value = set_p (name);
-      output_column -= end_pos - start_pos;
       output_paragraph_offset = start_pos;
 
       /* Restore the previous value of meta_char_pos if the stuff
@@ -4055,7 +4124,6 @@
   /* Inhibit any real output.  */
   int start = output_paragraph_offset;
   int saved_paragraph_is_open = paragraph_is_open;
-  int saved_output_column = output_column;
 
   /* More output state to save.  */
   int saved_meta_pos = meta_char_pos;
@@ -4090,7 +4158,6 @@
 
   output_paragraph_offset = start;
   paragraph_is_open = saved_paragraph_is_open;
-  output_column = saved_output_column;
 
   meta_char_pos = saved_meta_pos;
   last_inserted_character = saved_last_char;
diff -ur texinfo/makeinfo/makeinfo.h texinfo-4.8/makeinfo/makeinfo.h
--- texinfo/makeinfo/makeinfo.h 2006-12-02 10:01:25.000000000 +0100
+++ texinfo-4.8/makeinfo/makeinfo.h     2006-12-04 19:37:28.000000000 +0100
@@ -53,9 +53,6 @@
 /* Offset into OUTPUT_PARAGRAPH. */
 DECLARE (int, output_paragraph_offset, 0);
 
-/* The output paragraph "cursor" horizontal position. */
-DECLARE (int, output_column, 0);
-
 /* Position in the output file. */
 DECLARE (int, output_position, 0);
 
@@ -358,6 +355,8 @@
   search_forward (char *string, int from),
   search_forward_until_pos (char *string, int from, int end_pos),
   next_nonwhitespace_character (void),
+  string_width (const char *string, size_t length),
+  current_output_column (void),
   fs_error (char *filename);
 
 #if defined (VA_FPRINTF) && __STDC__
diff -ur texinfo/makeinfo/multi.c texinfo-4.8/makeinfo/multi.c
--- texinfo/makeinfo/multi.c    2004-04-11 19:56:47.000000000 +0200
+++ texinfo-4.8/makeinfo/multi.c        2006-12-04 19:37:47.000000000 +0100
@@ -59,7 +59,6 @@
   unsigned char *output_paragraph;
   int output_paragraph_offset;
   int meta_char_pos;
-  int output_column;
   int paragraph_is_open;
   int current_indent;
   int fill_column;
@@ -143,7 +142,6 @@
   e->output_paragraph = output_paragraph;
   e->output_paragraph_offset = output_paragraph_offset;
   e->meta_char_pos = meta_char_pos;
-  e->output_column = output_column;
   e->paragraph_is_open = paragraph_is_open;
   e->current_indent = current_indent;
   e->fill_column = fill_column;
@@ -154,7 +152,6 @@
   output_paragraph = e->output_paragraph;
   output_paragraph_offset = e->output_paragraph_offset;
   meta_char_pos = e->meta_char_pos;
-  output_column = e->output_column;
   paragraph_is_open = e->paragraph_is_open;
   current_indent = e->current_indent;
   fill_column = e->fill_column;
@@ -467,15 +464,16 @@
           break;
         out_char (CHAR_AT (j));
       }
-      offset[i] += j + 1;       /* skip last text plus skip the newline */
-      
       /* Do not output trailing blanks if we're in the last column and
          there will be no trailing |.  */
       if (i < last_column && !vsep)
-        for (; j <= envs[i].fill_column; j++)
+        for (s = string_width ((char *)&CHAR_AT (0), j);
+            s <= envs[i].fill_column; s++)
           out_char (' ');
       if (vsep)
         out_char ('|'); /* draw column separator */
+
+      offset[i] += j + 1;       /* skip last text plus skip the newline */
     }
     out_char ('\n');    /* end of line */
     had_newline = 1;
\input texinfo @c -*- coding: utf-8 -*-
@setfilename test
@settitle test
@node Top, , (dir), (dir)

@menu
* Concept Index:: foo.
@end menu

@center 何何何何何 何何何何何

a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a 
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a 
a a a a a a a a a a a a a a a a a a a a a a a a a a a                   a a a a 
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a 
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a 
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a 
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a

@flushright
foo
何何何何何
a a a
@end flushright

@cindex foo
This is a Chinese character in UTF-8 encoding: 何何何何何 何何何何何 
何何何何何 何何何何何 何何何何何 何何何何何 何何何何何 
何何何何何 何何何何何 何何何何何 何何何何何 何何何何何 
何何何何何 何何何何何 何何何何何 何何何何何 何何何何何 
何何何何何 何.

@cindex 楠楠楠
And here is another one: 楠楠楠 楠楠楠 楠楠楠 楠楠楠 楠楠楠 楠
楠楠 楠楠楠 楠楠楠 楠楠楠 楠楠楠 楠楠楠 楠楠楠 楠楠楠 楠
楠楠 楠楠楠 楠楠楠 楠楠楠 楠楠楠 楠楠楠 楠楠楠 楠楠楠 楠
楠楠 楠楠楠 楠楠楠 楠楠楠 楠楠楠 楠楠楠 楠楠楠 楠楠楠 楠
楠楠 楠楠楠 楠楠楠 楠楠楠 楠楠楠 楠楠楠 楠楠楠 楠楠楠 楠
楠楠 楠楠楠 楠楠楠 楠楠楠 楠楠楠 楠楠楠 楠楠楠.

@multitable {12345} {1234567890} {1234}
@item a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
@tab b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b
@tab c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c
@item 何 何 何 何 何 何 何 何 何 何 何 何 何 何 何 何 何 何 
何 何 何 何 何 何
@tab 楠 楠 楠 楠 楠 楠 楠 楠 楠 楠 楠 楠 楠 楠 楠 楠 楠 楠 楠
 楠 楠 楠 楠 楠 楠
@tab 何 何 何 何 何 何 何 何 何 何 何 何 何 何 何 何 何 何 
何 何 何 何 何 何 何
@item @w{a b c d e f g h}
@tab B
@tab C
@end multitable

@node Concept Index, , , Top
@unnumbered Concept Index

@printindex cp

@bye

reply via email to

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