Hi,

I'm quite interested commit 28c161010579e59ae5d310db277f8978911ac794,
which fixes the display of multibyte unicode characters in the caption
and hardstatus lines.

I can confirm that, in fact, that commit does display utf8 characters,
such as "☮" correctly.  Thanks!

However, it does introduce a new bug, though.  It seems that the
padding introduced by %=, though isn't quite handled correctly.

You can easily test it like this:

/tmp/screenrc:
hardstatus alwayslastline
hardstatus string '☮%c%=%c'

Then, building the latest screen from git:
./screen -c /tmp/screenrc

The last line will look like this:
"☮12:56
         12:56  "

Note the two trailing whitespace characters after the final %c (time)
display.  This will scale linearly with the number of utf8 characters
you put in your hardstatus.  That is, if I put 4 x ☮, there will be 8
trailing whitespaces.

It seems to me that there is some accounting missing somewhere, among
the various places that string-length is calculated, which might
involve multi-byte characters.

I've spent a few hours fiddling with the code, as has my colleague on
CC, Kees Cook.  He's come up with the attached patch, but it's not
quite there yet.  Can anyone here give us a few pointers to nudge us
along?

-- 
:-Dustin

Dustin Kirkland
Ubuntu Core Developer
Description: padlen does not take into account the width of utf8 characters when
 creating the hardstatus output.
Author: Kees Cook <k...@ubuntu.com>

=== modified file 'src/display.c'
--- src/display.c	2010-05-11 02:52:51 +0000
+++ src/display.c	2011-01-14 17:00:21 +0000
@@ -2119,7 +2119,7 @@
 }
 
 #ifdef UTF8
-static int
+int
 strlen_onscreen(unsigned char *c, unsigned char *end)
 {
   int len = 0;
@@ -2171,6 +2171,18 @@
     }
 }
 #else
+int
+strlen_onscreen(unsigned char *c, unsigned char *end)
+{
+  int len = 0;
+  char *s = c;
+  while (*c && (!end || c < end))
+    {
+      c++; len++;
+    }
+  return len;
+}
+
 static int
 PrePutWinMsg(s, start, max)
 char *s;

=== modified file 'src/extern.h'
--- src/extern.h	2010-03-29 17:52:14 +0000
+++ src/extern.h	2011-01-14 17:01:25 +0000
@@ -315,6 +315,7 @@
 extern void  ResetIdle __P((void));
 extern void  KillBlanker __P((void));
 extern void  DisplaySleep1000 __P((int, int));
+extern int   strlen_onscreen __P((char *, char *));
 
 /* resize.c */
 extern int   ChangeWindowSize __P((struct win *, int, int, int));

=== modified file 'src/screen.c'
--- src/screen.c	2010-03-29 17:52:14 +0000
+++ src/screen.c	2011-01-14 17:04:57 +0000
@@ -2518,6 +2518,8 @@
   int truncper = 0;
   int trunclong = 0;
   struct backtick *bt;
+
+  padlen += strlen(str) - strlen_onscreen(str, NULL);
  
   if (winmsg_numrend >= 0)
     winmsg_numrend = 0;

Reply via email to