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

[debian-devel:13951] Forward: slang, boot-floppies, and wide character support



久保田です。

最近、boot-floppies 関係が賑やかなようです。

以下のメッセージは、slang 向けのワイド文字 (全角文字のことか、
wchar_t のことかは分かりませんが) を扱うことができるための
パッチで、boot-floppies に使う用に書かれたものだそうです。
テストしてくれとのことですが、私は boot-floppies は昔に
どうしてもコンパイルできなくて挫折してしまったきりなので、
(それに、slang とは何かというのも分からない。curses みたいな
ものでしょうか) どなたか、テストしていただけないでしょうか。

# ひまができたらもう一度トライしてみようかな。まえみたいに、
# ハードディスク容量が残り100メガを切っているためにいろんな
# ことを断念したりしなくてすむようになったし (ハードディスク
# 買い換えました)。でなかったら、XFree86 とか gnome-core 
# とかのソースパッケージをもってくるなんて、こわくてできない。
# カーネルの再構築も、とちゅうでハードディスクが不足してたら
# どうしよう、って不安だったしなあ。

もとは、{debian-i18n,debian-boot,debian-www}@lists.debian.org
に流れていたものです。(なぜ -www? Adam さんだから?)

それでは、よろしくお願いします。

# ついでなので、ちょっと i18n 情報。
# (1)
# http://oss.software.ibm.com/developer/opensource/linux/patches/i18n.php
# に、bash、libreadline、grep、sed、textutils などの国際化
# パッチがあるようです。bash と libreadline については試して
# みました。ちょっと遅いですが動作してます。これのすごいところは、
# FSF にパッチが送られているところです。ということは、GNU の正式版が
# 国際化される日も近いということですね。
# (2)
# まえにアナウンスしました、XTerm の国際化ですが、私のパッチが
# Robert Brady さんのパッチに統合されました。Robert さんのパッチは
# いずれ Thomas Dickey さんの本家 XTerm に統合されるはずですので
# (過去の例のとおりに行けば)、これもいずれ XFree86 からリリース
# されることでしょう。ただし、XTerm の国際化については、Li18nux
# 方面などでも独立した開発がなされているようで、どういうところに
# 落着くのかは、わかりません。ただ、近いうちに国際化されるであろう
# ということは、言えると思います。
# (3)
# Rxvt の CVS 版が、ロケール自動判別になりました。現状の Debian の
# Rxvt は rxvt と rxvt-ml のマルチパッケージ、rxvt / krxvt / grxvt / etc
# のマルチバイナリになっていますが、これが単一のバイナリで済むように
# なります。ただし、たぶん現在の CVS 版が正式リリース版となってから
# のことでしょう。Rxvt のメジャーバージョンアップのサイクルって、
# けっこう遅そうなのですが。。。


---
久保田智広 Tomohiro KUBOTA <kubota@debian.org>
http://surfchem0.riken.go.jp/~kubota/
リニューアル中: "Introduction to I18N"
http://www.debian.org/doc/manuals/intro-i18n/


--- Begin Message ---
We need wide character support in slang for the boot-floppies so that
the install program can display wide characters, such as Japanese or
Chinese (Big5 *and* GB2312 encoding).

I have a patch from the boot-floppies archives to give slang wide
character support.  I've attached that patch.

I need to know if this patch is still needed (or alternatively, if I
should use slang1-ja instead), and if so, we need to file a bug
against the appropriate package to apply this.  Actually the patch is
against 1.4.0 rather than the newest 1.4.4, but it should probably
adapt pretty easily.

Any help, advice, bug filing, etc., would be appreciated.  Without
this, I cannot ship internationalized boot-floppies in Woody.

-- 
.....Adam Di Carlo....adam@xxxxxxxxxxxxxxxx<URL:http://www.onshored.com/>
Index: src/slang.h
===================================================================
RCS file: /usr/local/cvsroot/projects/slang14/src/slang.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- src/slang.h	2000/01/09 19:38:31	1.1.1.1
+++ src/slang.h	2000/03/18 15:17:20	1.2
@@ -1213,10 +1213,11 @@
 extern int SLtt_Msdos_Cheap_Video;
 #endif
 
-typedef unsigned short SLsmg_Char_Type;
-#define SLSMG_EXTRACT_CHAR(x) ((x) & 0xFF)
-#define SLSMG_EXTRACT_COLOR(x) (((x)>>8)&0xFF)
-#define SLSMG_BUILD_CHAR(ch,color) (((SLsmg_Char_Type)(unsigned char)(ch))|((color)<<8))
+typedef int SLsmg_Char_Type;
+#define SLSMG_EXTRACT_CHAR(x) ((x) & 0xFFFFFF)
+#define SLSMG_EXTRACT_COLOR(x) (((x)>>24)&0xFF)
+#define SLSMG_BUILD_CHAR(ch,color) (((SLsmg_Char_Type)(wchar_t)(ch))|((color)<<24))
+#define SLSMG_NOCHAR 1
 
 extern int SLtt_flush_output (void);
 extern void SLtt_set_scroll_region(int, int);
@@ -1301,7 +1302,7 @@
 
 /*{{{ SLsmg Screen Management Functions */
 
-extern void SLsmg_fill_region (int, int, unsigned int, unsigned int, unsigned char);
+extern void SLsmg_fill_region (int, int, unsigned int, unsigned int, wchar_t);
 extern void SLsmg_set_char_set (int);
 #ifndef IBMPC_SYSTEM
 extern int SLsmg_Scroll_Hash_Border;
@@ -1318,8 +1319,9 @@
 extern void SLsmg_vprintf (char *, va_list);
 extern void SLsmg_write_string (char *);
 extern void SLsmg_write_nstring (char *, unsigned int);
-extern void SLsmg_write_char (char);
+extern void SLsmg_write_char (wchar_t);
 extern void SLsmg_write_nchars (char *, unsigned int);
+extern void SLsmg_write_nwchars (wchar_t *, unsigned int);
 extern void SLsmg_write_wrapped_string (char *, int, int, unsigned int, unsigned int, int);
 extern void SLsmg_cls (void);
 extern void SLsmg_refresh (void);
Index: src/slcurses.c
===================================================================
RCS file: /usr/local/cvsroot/projects/slang14/src/slcurses.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- src/slcurses.c	2000/01/09 19:38:32	1.1.1.1
+++ src/slcurses.c	2000/03/18 15:18:04	1.2
@@ -452,10 +452,11 @@
    return 0;
 }
 
-int SLcurses_waddch (SLcurses_Window_Type *win, SLtt_Char_Type attr)
+static int SLcurses_waddch1 (SLcurses_Window_Type *win,
+			     wchar_t ch, int color)
 {
-   SLsmg_Char_Type *b, ch;
-   SLsmg_Char_Type color;
+   SLsmg_Char_Type *b, *bmin, *bmax, *c;
+   int k;
 
    if (win == NULL) return -1;
 
@@ -468,21 +469,6 @@
 
    win->modified = 1;
 
-   ch = SLSMG_EXTRACT_CHAR(attr);
-
-   if (attr == ch)
-     color = win->color;
-   else
-     {
-	/* hack to pick up the default color for graphics chars */
-	if (((attr & A_COLOR) == 0) && ((attr & A_ALTCHARSET) != 0))
-	  {
-	     /* FIXME: priority=medium: Use SLSMG_?? instead of << */
-	     attr |= win->color << 8;
-	  }
-	color = map_attr_to_object (attr);
-     }
-
    if (ch < ' ')
      {
 	if (ch == '\n')
@@ -508,17 +494,69 @@
 	/* HACK HACK!!!! */
 	if (ch == '\t') ch = ' ';
      }
+
+   k = wcwidth(ch);
+
+   if (!k)
+     return 0; /* ignore combining characters for now */
 
-   if (win->_curx >= win->ncols)
+   if (k > win->ncols)
+     return 0; /* character wider than window */
+
+   if (win->_curx + k > win->ncols) {
+     if (win->_curx < win->ncols)
+       SLcurses_wclrtoeol(win);
      do_newline (win);
+   }
+
+   bmin = win->lines[win->_cury];
+   b = bmin + win->_curx;
+   bmax = bmin + win->ncols;
+
+   /* Remove overwritten chars to left */
+   if (*b == SLSMG_NOCHAR) {
+     for (c = b - 1; c >= bmin && *c == SLSMG_NOCHAR; c--)
+       *c = SLSMG_BUILD_CHAR(' ',SLSMG_EXTRACT_COLOR(*c));
+     if (c >= bmin)
+       *c = SLSMG_BUILD_CHAR(' ',SLSMG_EXTRACT_COLOR(*c));
+   }
 
-   b = win->lines[win->_cury] + win->_curx;
    *b = SLSMG_BUILD_CHAR(ch,color);
-   win->_curx++;
+   win->_curx += k;
+   while (--k > 0)
+     *++b = SLSMG_NOCHAR;
+
+   /* Remove overwritten chars to right */
+   for (c = b + 1; c < bmax && *c == SLSMG_NOCHAR; c++)
+     *c = SLSMG_BUILD_CHAR(' ',SLSMG_EXTRACT_COLOR(*c));
 
    return 0;
 }
 
+int SLcurses_waddch (SLcurses_Window_Type *win, SLtt_Char_Type attr)
+{
+   SLsmg_Char_Type ch, color;
+
+   if (win == NULL) return -1;
+
+   ch = SLSMG_EXTRACT_CHAR(attr);
+
+   if (attr == ch)
+     color = win->color;
+   else
+     {
+	/* hack to pick up the default color for graphics chars */
+	if (((attr & A_COLOR) == 0) && ((attr & A_ALTCHARSET) != 0))
+	  {
+	     /* FIXME: priority=medium: Use SLSMG_?? instead of << */
+	     attr |= win->color << 8;
+	  }
+	color = map_attr_to_object (attr);
+     }
+
+   return SLcurses_waddch1 (win, ch, color);
+}
+
 int SLcurses_wnoutrefresh (SLcurses_Window_Type *w)
 {
    unsigned int len;
@@ -577,7 +615,7 @@
 
 int SLcurses_wclrtoeol (SLcurses_Window_Type *w)
 {
-   SLsmg_Char_Type *b, *bmax;
+   SLsmg_Char_Type *b, *bmin, *bmax, *c;
    SLsmg_Char_Type blank;
 
    if (w == NULL) return -1;
@@ -588,9 +626,17 @@
 
    blank = SLSMG_BUILD_CHAR(' ',w->color);
 
-   b = w->lines[w->_cury];
-   bmax = b + w->ncols;
-   b += w->_curx;
+   bmin = w->lines[w->_cury];
+   b = bmin + w->_curx;
+   bmax = bmin + w->ncols;
+
+   /* Remove overwritten chars to left */
+   if (b < bmax && *b == SLSMG_NOCHAR) {
+     for (c = b - 1; c >= bmin && *c == SLSMG_NOCHAR; c--)
+       *c = SLSMG_BUILD_CHAR(' ',SLSMG_EXTRACT_COLOR(*c));
+     if (c >= bmin) 
+       *c = SLSMG_BUILD_CHAR(' ',SLSMG_EXTRACT_COLOR(*c));
+   }
 
    while (b < bmax) *b++ = blank;
    return 0;
@@ -681,82 +727,20 @@
  */
 int SLcurses_waddnstr (SLcurses_Window_Type *w, char *str, int len)
 {
-   SLsmg_Char_Type *b;
-   SLsmg_Char_Type color;
-   unsigned char ch;
-   unsigned int nrows, ncols, crow, ccol;
+   int k;
+   wchar_t wc;
 
    if ((w == NULL)
        || (str == NULL))
      return -1;
 
-   w->modified = 1;
-   nrows = w->nrows;
-   ncols = w->ncols;
-   crow = w->_cury;
-   ccol = w->_curx;
-   color = w->color;
-
-   if (w->scroll_max <= nrows)
-     nrows = w->scroll_max;
-
-   if (crow >= nrows)
-     crow = 0;			       /* wrap back to top */
-
-   b = w->lines [crow] + ccol;
-
-   while (len && ((ch = (unsigned char) *str++) != 0))
+   while ((k = mbtowc (&wc, str, len)) > 0)
      {
-	len--;
-
-	if (ch == '\n')
-	  {
-	     w->_cury = crow;
-	     w->_curx = ccol;
-	     SLcurses_wclrtoeol (w);
-	     do_newline (w);
-	     crow = w->_cury;
-	     ccol = w->_curx;
-	     b = w->lines[crow];
-	     continue;
-	  }
-
-	if (ccol >= ncols)
-	  {
-	     ccol = 0;
-	     crow++;
-	     if (crow >= nrows)
-	       {
-		  w->_curx = 0;
-		  w->_cury = crow;
-		  do_newline (w);
-		  crow = w->_cury;
-		  ccol = w->_curx;
-	       }
-
-	     b = w->lines [crow];
-	  }
-
-	if (ch == '\t')
-	  {
-	     unsigned int n = ccol;
-	     n += SLsmg_Tab_Width;
-	     n = SLsmg_Tab_Width - (n % SLsmg_Tab_Width);
-	     if (ccol + n > ncols) n = ncols - len;
-	     ccol += n;
-	     while (n--)
-	       *b++ = SLSMG_BUILD_CHAR(' ',color);
-	     continue;
-	  }
-
-	*b++ = SLSMG_BUILD_CHAR(ch, color);
-	ccol++;
+	SLcurses_waddch1 (w, wc, w->color);
+	str += k;
+	len -= k;
      }
-
-   w->_curx = ccol;
-   w->_cury = crow;
-
-   return 0;
+   return k;
 }
 
 /* This routine IS NOT CORRECT.  It needs to compute the proper overlap
@@ -852,13 +836,25 @@
 
 int SLcurses_wdelch (SLcurses_Window_Type *w)
 {
-   SLsmg_Char_Type *p, *p1, *pmax;
+   SLsmg_Char_Type *p, *p1, *pmin, *pmax, *q;
 
-   p = w->lines[w->_cury];
-   pmax = p + w->ncols;
-   p += w->_curx;
-   p1 = p + 1;
+   pmin = w->lines[w->_cury];
+   p = pmin + w->_curx;
+   pmax = pmin + w->ncols;
+
+   /* Remove overwritten chars to left */
+   if (p < pmax && *p == SLSMG_NOCHAR) {
+     for (q = p - 1; q >= pmin && *q == SLSMG_NOCHAR; q--)
+       *q = SLSMG_BUILD_CHAR(' ',SLSMG_EXTRACT_COLOR(*q));
+     if (q >= pmin)
+       *q = SLSMG_BUILD_CHAR(' ',SLSMG_EXTRACT_COLOR(*q));
+   }
+
+   /* Remove overwritten chars to right */
+   for (q = p + 1; q < pmax && *q == SLSMG_NOCHAR; q++)
+     *q = SLSMG_BUILD_CHAR(' ',SLSMG_EXTRACT_COLOR(*q));
 
+   p1 = p + 1;
    while (p1 < pmax)
      {
 	*p = *p1;
@@ -884,12 +880,12 @@
 
    while (pmax > p)
      {
-	*pmax = *p1;
+	*pmax = *p1; /* Doesn't this assign beyond the end of the line? */
 	pmax = p1;
 	p1--;
      }
 
-   if (p < pmax)
+   if (p < pmax) /* How could it be? */
      *p = SLSMG_BUILD_CHAR(ch, w->color);
 
    w->modified = 1;
Index: src/sldisply.c
===================================================================
RCS file: /usr/local/cvsroot/projects/slang14/src/sldisply.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- src/sldisply.c	2000/01/09 19:38:32	1.1.1.1
+++ src/sldisply.c	2000/03/18 15:18:43	1.2
@@ -8,6 +8,7 @@
 
 #include <time.h>
 #include <ctype.h>
+#include <limits.h>
 
 #if !defined(VMS) || (__VMS_VER >= 70000000)
 # include <sys/time.h>
@@ -1354,14 +1355,11 @@
    tt_write_string("\033[?3h");
 }
 
-/* Highest bit represents the character set. */
-#define COLOR_MASK 0x7F00
-
 #if SLTT_HAS_NON_BCE_SUPPORT
-static int bce_color_eqs (unsigned int a, unsigned int b)
+static int bce_color_eqs (SLsmg_Char_Type a, SLsmg_Char_Type b)
 {
-   a = (a & COLOR_MASK) >> 8;
-   b = (b & COLOR_MASK) >> 8;
+   a = SLSMG_EXTRACT_COLOR(a) & 0x7F;
+   b = SLSMG_EXTRACT_COLOR(b) & 0x7F;
    
    if (a == b)
      return 1;
@@ -1381,15 +1379,15 @@
 }
 #define COLOR_EQS(a,b) bce_color_eqs (a,b)
 #else
-# define COLOR_OF(x) (((unsigned int)(x) & COLOR_MASK) >> 8)
+# define COLOR_OF(x) (SLSMG_EXTRACT_COLOR(x) & 0x7F)
 # define COLOR_EQS(a, b) \
    (SLtt_Use_Ansi_Colors \
     ? (Ansi_Color_Map[COLOR_OF(a)].fgbg == Ansi_Color_Map[COLOR_OF(b)].fgbg)\
     :  (Ansi_Color_Map[COLOR_OF(a)].mono == Ansi_Color_Map[COLOR_OF(b)].mono))
 #endif
 
-#define CHAR_EQS(a, b) (((a) == (b))\
-			|| ((((a) & ~COLOR_MASK) == ((b) & ~COLOR_MASK))\
+#define CHAR_EQS(a, b) ((a) == (b)\
+			|| (SLSMG_EXTRACT_CHAR(a) == SLSMG_EXTRACT_CHAR(b)\
 			    && COLOR_EQS((a), (b))))
 
 /* The whole point of this routine is to prevent writing to the last column
@@ -1418,9 +1416,49 @@
    tt_write (str, len);
 }
 
+/* FIXME: This duplicates the function above
+ */
+static void write_wstring_with_care (SLsmg_Char_Type *str, unsigned int len)
+{
+   if (str == NULL) return;
+
+   if (Automatic_Margins && (Cursor_r + 1 == SLtt_Screen_Rows))
+     {
+	if (len + (unsigned int) Cursor_c >= (unsigned int) SLtt_Screen_Cols)
+	  {
+	     /* For now, just do not write there.  Later, something more
+	      * sophisticated will be implemented.
+	      */
+	     if (SLtt_Screen_Cols > Cursor_c)
+	       {
+		  len = SLtt_Screen_Cols - Cursor_c - 1;
+		  while (len > 0 && str[len] == SLSMG_NOCHAR)
+		    --len;
+	       }
+	     else len = 0;
+	  }
+     }
+
+   while (len--)
+     {
+        SLsmg_Char_Type c = *str++;
+	char buf[MB_LEN_MAX];
+	int n;
+
+	if (c == SLSMG_NOCHAR)
+	  continue;
+
+	n = wctomb (buf, c);
+	if (n == -1)
+	  break;
+
+	tt_write(buf, n);
+     }
+}
+
 static void send_attr_str (SLsmg_Char_Type *s)
 {
-   unsigned char out[256], ch, *p;
+   SLsmg_Char_Type out[256], ch, *p;
    register SLtt_Char_Type attr;
    register SLsmg_Char_Type sh;
    int color, last_color = -1;
@@ -1428,8 +1466,8 @@
    p = out;
    while (0 != (sh = *s++))
      {
-	ch = sh & 0xFF;
-	color = ((int) sh & 0xFF00) >> 8;
+	ch = SLSMG_EXTRACT_CHAR(sh);
+	color = SLSMG_EXTRACT_COLOR(sh);
 
 #if SLTT_HAS_NON_BCE_SUPPORT
 	if (Bce_Color_Offset
@@ -1442,7 +1480,7 @@
 	     if (SLtt_Use_Ansi_Colors) attr = Ansi_Color_Map[color & 0x7F].fgbg;
 	     else attr = Ansi_Color_Map[color & 0x7F].mono;
 
-	     if (sh & 0x8000) /* alternate char set */
+	     if (SLSMG_EXTRACT_COLOR(sh) & 0x80) /* alternate char set */
 	       {
 		  if (SLtt_Use_Blink_For_ACS)
 		    {
@@ -1461,8 +1499,7 @@
 		    {
 		       if (p != out)
 			 {
-			    *p = 0;
-			    write_string_with_care ((char *) out);
+			    write_wstring_with_care (out, p-out);
 			    Cursor_c += (int) (p - out);
 			    p = out;
 			 }
@@ -1485,8 +1522,7 @@
 	  }
 	*p++ = ch;
      }
-   *p = 0;
-   if (p != out) write_string_with_care ((char *) out);
+   if (p != out) write_wstring_with_care (out, p-out);
    Cursor_c += (int) (p - out);
 }
 
@@ -1588,7 +1624,7 @@
 
 	while (qq < qmax)
 	  {
-	     if (*qq & 0xFF00)
+	     if (SLSMG_EXTRACT_COLOR(*qq))
 	       {
 		  SLtt_normal_video ();
 		  SLtt_del_eol ();
@@ -1603,7 +1639,7 @@
    /* Find where the last non-blank character on old/new screen is */
 
    space_char = ' ';
-   if ((*(pmax-1) & 0xFF) == ' ')
+   if (SLSMG_EXTRACT_CHAR(*(pmax-1)) == ' ')
      {
 	/* If we get here, then we can erase to the end of the line to create
 	 * the final space.  However, this will only work _if_ erasing will 
@@ -1654,7 +1690,7 @@
      {
 #endif
 	/* Try use use erase to bol if possible */
-	if ((Del_Bol_Str != NULL) && ((*neww & 0xFF) == 32))
+	if ((Del_Bol_Str != NULL) && (SLSMG_EXTRACT_CHAR(*neww) == 32))
 	  {
 	     SLsmg_Char_Type *p1;
 	     SLsmg_Char_Type blank;
@@ -1683,7 +1719,7 @@
 		  q = oldd + ofs;
 		  p = p1;
 		  SLtt_goto_rc (row, ofs - 1);
-		  SLtt_reverse_video (blank >> 8);
+		  SLtt_reverse_video (SLSMG_EXTRACT_COLOR (blank));
 		  tt_write_string (Del_Bol_Str);
 		  tt_write (" ", 1);
 		  Cursor_c += 1;
@@ -1871,7 +1907,7 @@
 
    if (q < qmax) 
      {
-	SLtt_reverse_video (space_char >> 8);
+	SLtt_reverse_video (SLSMG_EXTRACT_COLOR (space_char));
 	tt_write_string (Del_Eol_Str);
      }
    
Index: src/slsmg.c
===================================================================
RCS file: /usr/local/cvsroot/projects/slang14/src/slsmg.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- src/slsmg.c	2000/01/09 19:38:35	1.1.1.1
+++ src/slsmg.c	2000/03/18 15:20:00	1.2
@@ -227,22 +227,30 @@
 
 void SLsmg_write_nstring (char *str, unsigned int n)
 {
-   unsigned int width;
    char blank = ' ';
 
-   if (str == NULL) width = 0;
-   else
+   if (str != NULL)
      {
-	width = strlen (str);
-	if (width > n) width = n;
-	SLsmg_write_nchars (str, width);
+	wchar_t wc;
+	int k, w;
+
+        while ((k = mbtowc (&wc, str, -1)) > 0)
+	  {
+	     w = wcwidth(wc);
+	     if (w < 0 || w > n)
+	       break;
+	     SLsmg_write_nwchars (&wc, 1);
+	     str += k;
+	     n -= w;
+	  }
      }
-   while (width++ < n) SLsmg_write_nchars (&blank, 1);
+   while (n-- > 0) SLsmg_write_nchars (&blank, 1);
 }
 
 void SLsmg_write_wrapped_string (char *s, int r, int c,
 				 unsigned int dr, unsigned int dc,
 				 int fill)
+     /* FIXME: This function doesn't work yet - Edmund */
 {
    register char ch, *p;
    int maxc = (int) dc;
@@ -298,14 +306,12 @@
 int SLsmg_Display_Eight_Bit = 128;
 #endif
 
-void SLsmg_write_nchars (char *str, unsigned int n)
+void SLsmg_write_nwchars (wchar_t *str, unsigned int n)
 {
-   register SLsmg_Char_Type *p, old, neew, color;
-   unsigned char ch;
-   unsigned int flags;
-   int len, start_len, max_len;
-   char *str_max;
-   int newline_flag;
+  SLsmg_Char_Type *p, *prev, *q;
+  int len, max_len, w, i;
+  wchar_t ch;
+
 #ifndef IBMPC_SYSTEM
    int alt_char_set_flag;
 
@@ -314,164 +320,104 @@
 			    || (*tt_Use_Blink_For_ACS == 0)));
 #endif
 
-   if (Smg_Inited == 0) return;
+  if (Smg_Inited == 0)
+    return;
+  if (This_Row < Start_Row || This_Row >= Start_Row + Screen_Rows)
+    return;
+
+  max_len = Start_Col + Screen_Cols;
+  len = This_Col;
+  p = SL_Screen[This_Row].neew + len - Start_Col;
+  prev = 0;
 
-   str_max = str + n;
-   color = This_Color;
-
-   top:				       /* get here only on newline */
-
-   newline_flag = 0;
-   start_len = Start_Col;
-
-   if (point_visible (0) == 0) return;
-
-   len = This_Col;
-   max_len = start_len + Screen_Cols;
-
-   p = SL_Screen[This_Row].neew;
-   if (len > start_len) p += (len - start_len);
-
-   flags = SL_Screen[This_Row].flags;
-   while ((len < max_len) && (str < str_max))
-     {
-	ch = (unsigned char) *str++;
-
-#ifndef IBMPC_SYSTEM
-	if (alt_char_set_flag)
-	  ch = Alt_Char_Set [ch & 0x7F];
-#endif
-	if (((ch >= ' ') && (ch < 127))
-	    || (ch >= (unsigned char) SLsmg_Display_Eight_Bit)
+  for (i = 0; i < n; i++, str) {
+    ch = *str++;
 #ifndef IBMPC_SYSTEM
-	    || alt_char_set_flag
+    if (alt_char_set_flag)
+      ch = Alt_Char_Set[ch & 0x7F];
 #endif
-	    )
-	  {
-	     len += 1;
-	     if (len > start_len)
-	       {
-		  old = *p;
-		  neew = SLSMG_BUILD_CHAR(ch,color);
-		  if (old != neew)
-		    {
-		       flags |= TOUCHED;
-		       *p = neew;
-		    }
-		  p++;
-	       }
-	  }
+    w = wcwidth(ch);
 
-	else if ((ch == '\t') && (SLsmg_Tab_Width > 0))
-	  {
-	     n = len;
-	     n += SLsmg_Tab_Width;
-	     n = SLsmg_Tab_Width - (n % SLsmg_Tab_Width);
-	     if ((unsigned int) len + n > (unsigned int) max_len)
-	       n = (unsigned int) (max_len - len);
-	     neew = SLSMG_BUILD_CHAR(' ',color);
-	     while (n--)
-	       {
-		  len += 1;
-		  if (len > start_len)
-		    {
-		       if (*p != neew)
-			 {
-			    flags |= TOUCHED;
-			    *p = neew;
-			 }
-		       p++;
-		    }
-	       }
-	  }
-	else if ((ch == '\n')
-		 && (SLsmg_Newline_Behavior != SLSMG_NEWLINE_PRINTABLE))
-	  {
-	     newline_flag = 1;
-	     break;
-	  }
-	else if ((ch == 0x8) && SLsmg_Backspace_Moves)
-	  {
-	     if (len != 0) len--;
-	  }
+    if (w > 0) {
+      if (len + w <= max_len) {
+	if (!prev) {
+	  for (q = p; *q == SLSMG_NOCHAR; q--)
+	    *q = SLSMG_BUILD_CHAR(' ', SLSMG_EXTRACT_COLOR(*q));
+	  *q = SLSMG_BUILD_CHAR(' ', SLSMG_EXTRACT_COLOR(*q));
+	}
+	prev = p;
+	*p++ = SLSMG_BUILD_CHAR(ch, This_Color), ++len;
+	for (; --w; len++, p++)
+	  *p = SLSMG_NOCHAR;
+      }
+      else if (len < max_len) {
+	for (; len < max_len; len++, p++)
+	  *p = SLSMG_BUILD_CHAR(' ', SLSMG_EXTRACT_COLOR(*p));
+	prev = 0;
+      }
+    }
+    else if (ch == '\n' &&
+	     SLsmg_Newline_Behavior != SLSMG_NEWLINE_PRINTABLE) {
+      SL_Screen[This_Row].flags |= TOUCHED;
+      for (; len < max_len && *p == SLSMG_NOCHAR; len++, p++)
+	*p = SLSMG_BUILD_CHAR(' ', SLSMG_EXTRACT_COLOR(*p));
+      if (!SLsmg_Newline_Behavior)
+	break;
+      ++This_Row;
+      len = 0;
+      if (This_Row == Start_Row + Screen_Rows) {
+	if (SLsmg_Newline_Behavior == SLSMG_NEWLINE_SCROLLS)
+	  scroll_up();
 	else
-	  {
-	     if (ch & 0x80)
-	       {
-		  neew = SLSMG_BUILD_CHAR('~',color);
-		  len += 1;
-		  if (len > start_len)
-		    {
-		       if (*p != neew)
-			 {
-			    *p = neew;
-			    flags |= TOUCHED;
-			 }
-		       p++;
-		       if (len == max_len) break;
-		       ch &= 0x7F;
-		    }
-	       }
-
-	     len += 1;
-	     if (len > start_len)
-	       {
-		  neew = SLSMG_BUILD_CHAR('^',color);
-		  if (*p != neew)
-		    {
-		       *p = neew;
-		       flags |= TOUCHED;
-		    }
-		  p++;
-		  if (len == max_len) break;
-	       }
-
-	     if (ch == 127) ch = '?'; else ch = ch + '@';
-	     len++;
-	     if (len > start_len)
-	       {
-		  neew = SLSMG_BUILD_CHAR(ch,color);
-		  if (*p != neew)
-		    {
-		       *p = neew;
-		       flags |= TOUCHED;
-		    }
-		  p++;
-	       }
-	  }
-     }
-
-   SL_Screen[This_Row].flags = flags;
-   This_Col = len;
+	  break;
+      }
+      p = SL_Screen[This_Row].neew;
+      prev = 0;
+    }
+    else if (ch == '\t' && (SLsmg_Tab_Width > 0)) {
+      while (len < max_len) {
+	*p = SLSMG_BUILD_CHAR(' ', SLSMG_EXTRACT_COLOR(*p));
+	++p, ++len;
+	if (len % SLsmg_Tab_Width == 0)
+	  break;
+      }
+    }
+    else if ((ch == 0x8) && SLsmg_Backspace_Moves) {
+      /* not implemented */
+    }
+    else if (!w && ch) {
+      /* we could handle combining characters here, using prev */
+    }
+    else {
+      /* we should convert control characters to printable form here */
+    }
+  }
+  This_Col = len;
+  if (i == n) {
+    SL_Screen[This_Row].flags |= TOUCHED;
+    for (; len < max_len && *p == SLSMG_NOCHAR; len++, p++)
+      *p = SLSMG_BUILD_CHAR(' ', SLSMG_EXTRACT_COLOR(*p));
+  }
+}
 
-   if (SLsmg_Newline_Behavior == 0)
-     return;
+void SLsmg_write_char (wchar_t wc)
+{
+   SLsmg_write_nwchars (&wc, 1);
+}
 
-   if (newline_flag == 0)
-     {
-	while (str < str_max)
-	  {
-	     if (*str == '\n') break;
-	     str++;
-	  }
-	if (str == str_max) return;
-	str++;
-     }
+void SLsmg_write_nchars (char *str, unsigned int n)
+{
+   wchar_t wc;
+   int k;
 
-   This_Row++;
-   This_Col = 0;
-   if (This_Row == Start_Row + Screen_Rows)
+   while ((k = mbtowc (&wc, str, n)) > 0)
      {
-	if (SLsmg_Newline_Behavior == SLSMG_NEWLINE_SCROLLS) scroll_up ();
+        SLsmg_write_nwchars (&wc, 1);
+	str += k;
+	n -= k;
      }
-   goto top;
 }
 
-void SLsmg_write_char (char ch)
-{
-   SLsmg_write_nchars (&ch, 1);
-}
-
 static int Cls_Flag;
 
 void SLsmg_cls (void)
@@ -886,6 +832,8 @@
 	SL_Screen[i].old[Screen_Cols] = 0;
 	SL_Screen[i].neew[Screen_Cols] = 0;
 
+	/* FIXME: We should convert broken wide characters to spaces
+	   before calling smart_puts */
 	(*tt_smart_puts) (SL_Screen[i].neew, SL_Screen[i].old, Screen_Cols, i);
 
 	SLMEMCPY ((char *) SL_Screen[i].old, (char *) SL_Screen[i].neew,
@@ -1325,11 +1273,12 @@
    This_Row = r; This_Col = c;
 }
 
-void SLsmg_fill_region (int r, int c, unsigned int dr, unsigned int dc, unsigned char ch)
+void SLsmg_fill_region (int r, int c, unsigned int dr, unsigned int dc, wchar_t ch)
 {
-   static unsigned char hbuf[16];
+   static wchar_t hbuf[16];
    int count;
    int dcmax, rmax;
+   int i;
 
    if (Smg_Inited == 0) return;
 
@@ -1348,16 +1297,18 @@
 #if 0
    ch = Alt_Char_Set[ch];
 #endif
-   if (ch != hbuf[0]) SLMEMSET ((char *) hbuf, (char) ch, 16);
+   if (ch != hbuf[0])
+     for (i = 0; i < 16; i++)
+       hbuf[i] = ch;
 
    for (This_Row = r; This_Row < rmax; This_Row++)
      {
 	This_Col = c;
 	count = dc / 16;
-	SLsmg_write_nchars ((char *) hbuf, dc % 16);
+	SLsmg_write_nwchars (hbuf, dc % 16);
 	while (count-- > 0)
 	  {
-	     SLsmg_write_nchars ((char *) hbuf, 16);
+	     SLsmg_write_nwchars (hbuf, 16);
 	  }
      }
 
@@ -1372,14 +1323,14 @@
 void SLsmg_write_color_chars (SLsmg_Char_Type *s, unsigned int len)
 {
    SLsmg_Char_Type *smax, sh;
-   char buf[32], *b, *bmax;
+   wchar_t buf[32], *b, *bmax;
    int color, save_color;
 
    if (Smg_Inited == 0) return;
 
    smax = s + len;
    b = buf;
-   bmax = b + sizeof (buf);
+   bmax = b + sizeof (buf) / sizeof (SLsmg_Char_Type);
 
    save_color = This_Color;
 
@@ -1403,16 +1354,16 @@
 	  {
 	     if (b != buf)
 	       {
-		  SLsmg_write_nchars (buf, (int) (b - buf));
+		  SLsmg_write_nwchars (buf, (int) (b - buf));
 		  b = buf;
 	       }
 	     This_Color = color;
 	  }
-	*b++ = (char) SLSMG_EXTRACT_CHAR(sh);
+	*b++ = SLSMG_EXTRACT_CHAR(sh);
      }
 
    if (b != buf)
-     SLsmg_write_nchars (buf, (unsigned int) (b - buf));
+     SLsmg_write_nwchars (buf, (unsigned int) (b - buf));
 
    This_Color = save_color;
 }
@@ -1464,7 +1415,7 @@
 SLsmg_set_color_in_region (int color, int r, int c, unsigned int dr, unsigned int dc)
 {
    int cmax, rmax;
-   SLsmg_Char_Type char_mask;
+   int color_mask;
 
    if (Smg_Inited == 0) return;
 
@@ -1489,14 +1440,13 @@
 	  color = ((color & 0x7F) + Bce_Color_Offset) & 0x7F;
      }
 #endif
-   color = color << 8;
 
-   char_mask = 0xFF;
+   color_mask = 0;
 
 #ifndef IBMPC_SYSTEM
    if ((tt_Use_Blink_For_ACS == NULL)
        || (0 == *tt_Use_Blink_For_ACS))
-     char_mask = 0x80FF;
+     color_mask = 0x80;
 #endif
 
    while (r < rmax)
@@ -1510,7 +1460,9 @@
 
 	while (s < smax)
 	  {
-	     *s = (*s & char_mask) | color;
+	     *s = SLSMG_BUILD_CHAR(SLSMG_EXTRACT_CHAR(*s),
+				   (SLSMG_EXTRACT_COLOR(*s) & color_mask)
+				   | color);
 	     s++;
 	  }
 	r++;

--- End Message ---