On Wednesday, July 3, 2013 4:06:32 PM UTC+2, Christian Wellenbrock wrote:
> 2013/7/3 Bram Moolenaar <[email protected]>
>
>
>
>
> Christian Wellenbrock wrote:
>
>
>
> > I added the MB_CHAR2LEN macro and used that instead of mb_char2len.
>
> >
>
> > Does the mb_char2bytes call need a has_mbyte check as well?
>
> >
>
> > Are there any other issues that need to resolved to bring this patch
>
> > forward?
>
>
>
> I finally had time to look at this patch. It turns out only one use of
>
> "fillchar" is handled. There are many others, they all need to be
>
> changed.
>
>
>
> Yes I also realized that shortly after. I already extended my patch to
> support multibyte fillchars in all those instances. I will test them all and
> upload the improved patch soon.
In order to test the changes I made, I started out with a patch that helped me
to find and verify 'statusline' options that show the nine different uses of
the 'fillchar'. In `1_replace_fillchars.patch` I replaced them all with the
different hardcoded placeholder characters 'a' to 'i'. Here are nine vim
invocations for each of them:
(I'm using ○ (digraph 0m) as multibyte fillchar in all invocations and 〇
(digraph 0_) als a double-width character)
[a] vim -u NONE -c "set ls=2 fcs=stl:○ stl=S%2.2(X〇%)E"
[b] vim -u NONE -c "set ls=2 fcs=stl:○ stl=S%-1(%)E"
[c] vim -u NONE -c "set ls=2 fcs=stl:○ stl=S%1(%)E"
[d] vim -u NONE -c "set ls=2 fcs=stl:○ stl=S%4PE"
[e] vim -u NONE -c "set ls=2 fcs=stl:○ stl=S%{'A\ B'}E"
[f] vim -u NONE -c "set ls=2 fcs=stl:○ stl=S%-4PE"
[g] vim -u NONE -c "set ls=2 fcs=stl:○ stl=S234567890〇%<1"
[h] vim -u NONE -c "set ls=2 fcs=stl:○ stl=S〇123456789E"
[i] vim -u NONE -c "set ls=2 fcs=stl:○ stl=S%=E"
The binary resulting from patch 1 shows these statuslines respectively:
(in a terminal that is exactly 12 characters wide)
[a] S<aE○○○○○○○○
[b] SbE○○○○○○○○○
[c] ScE○○○○○○○○○
[d] SdAllE○○○○○○
[e] SAeBE○○○○○○○
[f] SAllfE○○○○○○
[g] S234567890>
[h] <123456789Eh
[i] SiiiiiiiiiiE
Note that (almost) every statusline contains the corresponding hardcoded
'fillchar' placeholder. Except the 'g' is missing for invocation [g]. I believe
the reason for that is a bug that I fixed in `2_fix_fillchar_g.patch`. The new
binary shows the expected result:
[a] S<aE○○○○○○○○
[b] SbE○○○○○○○○○
[c] ScE○○○○○○○○○
[d] SdAllE○○○○○○
[e] SAeBE○○○○○○○
[f] SAllfE○○○○○○
[g] S234567890g>
[h] <123456789Eh
[i] SiiiiiiiiiiE
Now in `3_use_multibyte.patch` I finally added support for multibyte support
for all these fillchars:
[a] S<○E○○○○○○○○
[b] S○E○○○○○○○○○
[c] S○E○○○○○○○○○
[d] S○AllE○○○○○○
[e] SA○BE○○○○○○○
[f] SAll○E○○○○○○
[g] S234567890○>
[h] <123456789E○
[i] S○○○○○○○○○○E
Every former fillchar placeholder is now replaced by the real multibyte
fillchar.
Bonus: As I recognized a pattern that repeated itself several times, I
extracted a macro `MB_CHAR2BYTES` to simplify matters in `4_add_macro.patch`.
I'm not sure about this name regarding the advancing side effect, though. This
could obviously be renamed. Another possibility would be to remove the side
effect and add `b += MB_CHAR2LEN(fillchar);` on the caller sites.
I'm also not quite sure if the case [h] is fully tested by my invocation. There
is some code moving the subsequent items in memory, but I wasn't able to find a
'statusline', where the fillchar was somewhere in the middle of the statusline.
So I didn't really understand the intention of that logic and I might broke
that part. If someone knows a 'statusline' option where my implementation
breaks expected behaviour, I would be happy to fix it.
If there are any other issues, please let me know. Thank you!
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.
diff -r 58686d48772e src/buffer.c
--- a/src/buffer.c Wed Jul 03 22:28:36 2013 +0200
+++ b/src/buffer.c Fri Jul 05 00:36:30 2013 +0200
@@ -3699,7 +3699,7 @@
#ifdef FEAT_MBYTE
/* Fill up space left over by half a double-wide char. */
while (++l < item[groupitem[groupdepth]].minwid)
- *p++ = fillchar;
+ *p++ = 'a'; // TODO: use fillchar
#endif
/* correct the start of the items for the truncation */
@@ -3719,7 +3719,7 @@
/* fill by appending characters */
n = 0 - n;
while (l++ < n && p + 1 < out + outlen)
- *p++ = fillchar;
+ *p++ = 'b'; // TODO: use fillchar
}
else
{
@@ -3732,7 +3732,7 @@
for (n = groupitem[groupdepth] + 1; n < curitem; n++)
item[n].start += l;
for ( ; l > 0; l--)
- *t++ = fillchar;
+ *t++ = 'c'; // TODO: use fillchar
}
}
continue;
@@ -4103,7 +4103,7 @@
if (l + 1 == minwid && fillchar == '-' && VIM_ISDIGIT(*t))
*p++ = ' ';
else
- *p++ = fillchar;
+ *p++ = 'd'; // TODO: use fillchar
}
minwid = 0;
}
@@ -4116,10 +4116,10 @@
* digit follows. */
if (fillable && p[-1] == ' '
&& (!VIM_ISDIGIT(*t) || fillchar != '-'))
- p[-1] = fillchar;
+ p[-1] = 'e'; // TODO: use fillchar
}
for (; l < minwid && p + 1 < out + outlen; l++)
- *p++ = fillchar;
+ *p++ = 'f'; // TODO: use fillchar
}
else if (num >= 0)
{
@@ -4223,7 +4223,7 @@
}
/* Fill up for half a double-wide character. */
while (++width < maxwidth)
- *s++ = fillchar;
+ *s++ = 'g'; // TODO: use fillchar
}
else
#endif
@@ -4258,7 +4258,7 @@
while (++width < maxwidth)
{
s = s + STRLEN(s);
- *s++ = fillchar;
+ *s++ = 'h'; // TODO: use fillchar
*s = NUL;
}
@@ -4284,7 +4284,7 @@
p = item[l].start + maxwidth - width;
STRMOVE(p, item[l].start);
for (s = item[l].start; s < p; s++)
- *s = fillchar;
+ *s = 'i'; // TODO: use fillchar
for (l++; l < itemcnt; l++)
item[l].start += maxwidth - width;
width = maxwidth;
diff -r 58686d48772e src/buffer.c
--- a/src/buffer.c Wed Jul 03 22:28:36 2013 +0200
+++ b/src/buffer.c Fri Jul 05 00:41:39 2013 +0200
@@ -3699,7 +3699,7 @@
#ifdef FEAT_MBYTE
/* Fill up space left over by half a double-wide char. */
while (++l < item[groupitem[groupdepth]].minwid)
- *p++ = fillchar;
+ *p++ = 'a'; // TODO: use fillchar
#endif
/* correct the start of the items for the truncation */
@@ -3719,7 +3719,7 @@
/* fill by appending characters */
n = 0 - n;
while (l++ < n && p + 1 < out + outlen)
- *p++ = fillchar;
+ *p++ = 'b'; // TODO: use fillchar
}
else
{
@@ -3732,7 +3732,7 @@
for (n = groupitem[groupdepth] + 1; n < curitem; n++)
item[n].start += l;
for ( ; l > 0; l--)
- *t++ = fillchar;
+ *t++ = 'c'; // TODO: use fillchar
}
}
continue;
@@ -4103,7 +4103,7 @@
if (l + 1 == minwid && fillchar == '-' && VIM_ISDIGIT(*t))
*p++ = ' ';
else
- *p++ = fillchar;
+ *p++ = 'd'; // TODO: use fillchar
}
minwid = 0;
}
@@ -4116,10 +4116,10 @@
* digit follows. */
if (fillable && p[-1] == ' '
&& (!VIM_ISDIGIT(*t) || fillchar != '-'))
- p[-1] = fillchar;
+ p[-1] = 'e'; // TODO: use fillchar
}
for (; l < minwid && p + 1 < out + outlen; l++)
- *p++ = fillchar;
+ *p++ = 'f'; // TODO: use fillchar
}
else if (num >= 0)
{
@@ -4214,16 +4214,14 @@
{
s = out;
width = 0;
- for (;;)
+ while (width + ptr2cells(s) < maxwidth)
{
width += ptr2cells(s);
- if (width >= maxwidth)
- break;
s += (*mb_ptr2len)(s);
}
/* Fill up for half a double-wide character. */
while (++width < maxwidth)
- *s++ = fillchar;
+ *s++ = 'g'; // TODO: use fillchar
}
else
#endif
@@ -4258,7 +4256,7 @@
while (++width < maxwidth)
{
s = s + STRLEN(s);
- *s++ = fillchar;
+ *s++ = 'h'; // TODO: use fillchar
*s = NUL;
}
@@ -4284,7 +4282,7 @@
p = item[l].start + maxwidth - width;
STRMOVE(p, item[l].start);
for (s = item[l].start; s < p; s++)
- *s = fillchar;
+ *s = 'i'; // TODO: use fillchar
for (l++; l < itemcnt; l++)
item[l].start += maxwidth - width;
width = maxwidth;
diff -r 58686d48772e src/buffer.c
--- a/src/buffer.c Wed Jul 03 22:28:36 2013 +0200
+++ b/src/buffer.c Fri Jul 05 23:13:37 2013 +0200
@@ -3570,11 +3570,6 @@
if (fillchar == 0)
fillchar = ' ';
-#ifdef FEAT_MBYTE
- /* Can't handle a multi-byte fill character yet. */
- else if (mb_char2len(fillchar) > 1)
- fillchar = '-';
-#endif
/* Get line & check if empty (cursorpos will show "0-1"). Note that
* p will become invalid when getting another buffer line. */
@@ -3699,7 +3694,7 @@
#ifdef FEAT_MBYTE
/* Fill up space left over by half a double-wide char. */
while (++l < item[groupitem[groupdepth]].minwid)
- *p++ = fillchar;
+ p += (*mb_char2bytes)(fillchar, p);
#endif
/* correct the start of the items for the truncation */
@@ -3719,20 +3714,28 @@
/* fill by appending characters */
n = 0 - n;
while (l++ < n && p + 1 < out + outlen)
+#ifdef FEAT_MBYTE
+ p += (*mb_char2bytes)(fillchar, p);
+#else
*p++ = fillchar;
+#endif
}
else
{
/* fill by inserting characters */
- mch_memmove(t + n - l, t, (size_t)(p - t));
- l = n - l;
+ l = (n - l) * MB_CHAR2LEN(fillchar);
+ mch_memmove(t + l, t, (size_t)(p - t));
if (p + l >= out + outlen)
l = (long)((out + outlen) - p - 1);
p += l;
for (n = groupitem[groupdepth] + 1; n < curitem; n++)
item[n].start += l;
for ( ; l > 0; l--)
+#ifdef FEAT_MBYTE
+ t += (*mb_char2bytes)(fillchar, t);
+#else
*t++ = fillchar;
+#endif
}
}
continue;
@@ -4103,23 +4106,36 @@
if (l + 1 == minwid && fillchar == '-' && VIM_ISDIGIT(*t))
*p++ = ' ';
else
+#ifdef FEAT_MBYTE
+ p += (*mb_char2bytes)(fillchar, p);
+#else
*p++ = fillchar;
+#endif
}
minwid = 0;
}
else
minwid *= -1;
- while (*t && p + 1 < out + outlen)
+ for (; *t && p + 1 < out + outlen; t++)
{
- *p++ = *t++;
/* Change a space by fillchar, unless fillchar is '-' and a
* digit follows. */
- if (fillable && p[-1] == ' '
- && (!VIM_ISDIGIT(*t) || fillchar != '-'))
- p[-1] = fillchar;
+ if (fillable && *t == ' '
+ && (!VIM_ISDIGIT(*(t+1)) || fillchar != '-'))
+#ifdef FEAT_MBYTE
+ p += (*mb_char2bytes)(fillchar, p);
+#else
+ *p++ = fillchar;
+#endif
+ else
+ *p++ = *t;
}
for (; l < minwid && p + 1 < out + outlen; l++)
+#ifdef FEAT_MBYTE
+ p += (*mb_char2bytes)(fillchar, p);
+#else
*p++ = fillchar;
+#endif
}
else if (num >= 0)
{
@@ -4214,16 +4230,14 @@
{
s = out;
width = 0;
- for (;;)
+ while (width + ptr2cells(s) < maxwidth)
{
width += ptr2cells(s);
- if (width >= maxwidth)
- break;
s += (*mb_ptr2len)(s);
}
/* Fill up for half a double-wide character. */
while (++width < maxwidth)
- *s++ = fillchar;
+ s += (*mb_char2bytes)(fillchar, s);
}
else
#endif
@@ -4258,7 +4272,11 @@
while (++width < maxwidth)
{
s = s + STRLEN(s);
+#ifdef FEAT_MBYTE
+ s += (*mb_char2bytes)(fillchar, s);
+#else
*s++ = fillchar;
+#endif
*s = NUL;
}
@@ -4281,12 +4299,17 @@
break;
if (l < itemcnt)
{
- p = item[l].start + maxwidth - width;
+ int middlelength = (maxwidth - width) * MB_CHAR2LEN(fillchar);
+ p = item[l].start + middlelength;
STRMOVE(p, item[l].start);
- for (s = item[l].start; s < p; s++)
- *s = fillchar;
+ for (s = item[l].start; s < p;)
+#ifdef FEAT_MBYTE
+ s += (*mb_char2bytes)(fillchar, s);
+#else
+ *s++ = fillchar;
+#endif
for (l++; l < itemcnt; l++)
- item[l].start += maxwidth - width;
+ item[l].start += middlelength;
width = maxwidth;
}
}
diff -r 58686d48772e src/buffer.c
--- a/src/buffer.c Wed Jul 03 22:28:36 2013 +0200
+++ b/src/buffer.c Fri Jul 05 23:54:36 2013 +0200
@@ -3570,11 +3570,6 @@
if (fillchar == 0)
fillchar = ' ';
-#ifdef FEAT_MBYTE
- /* Can't handle a multi-byte fill character yet. */
- else if (mb_char2len(fillchar) > 1)
- fillchar = '-';
-#endif
/* Get line & check if empty (cursorpos will show "0-1"). Note that
* p will become invalid when getting another buffer line. */
@@ -3699,7 +3694,7 @@
#ifdef FEAT_MBYTE
/* Fill up space left over by half a double-wide char. */
while (++l < item[groupitem[groupdepth]].minwid)
- *p++ = fillchar;
+ MB_CHAR2BYTES(fillchar, p);
#endif
/* correct the start of the items for the truncation */
@@ -3719,20 +3714,20 @@
/* fill by appending characters */
n = 0 - n;
while (l++ < n && p + 1 < out + outlen)
- *p++ = fillchar;
+ MB_CHAR2BYTES(fillchar, p);
}
else
{
/* fill by inserting characters */
- mch_memmove(t + n - l, t, (size_t)(p - t));
- l = n - l;
+ l = (n - l) * MB_CHAR2LEN(fillchar);
+ mch_memmove(t + l, t, (size_t)(p - t));
if (p + l >= out + outlen)
l = (long)((out + outlen) - p - 1);
p += l;
for (n = groupitem[groupdepth] + 1; n < curitem; n++)
item[n].start += l;
for ( ; l > 0; l--)
- *t++ = fillchar;
+ MB_CHAR2BYTES(fillchar, t);
}
}
continue;
@@ -4103,23 +4098,24 @@
if (l + 1 == minwid && fillchar == '-' && VIM_ISDIGIT(*t))
*p++ = ' ';
else
- *p++ = fillchar;
+ MB_CHAR2BYTES(fillchar, p);
}
minwid = 0;
}
else
minwid *= -1;
- while (*t && p + 1 < out + outlen)
+ for (; *t && p + 1 < out + outlen; t++)
{
- *p++ = *t++;
/* Change a space by fillchar, unless fillchar is '-' and a
* digit follows. */
- if (fillable && p[-1] == ' '
- && (!VIM_ISDIGIT(*t) || fillchar != '-'))
- p[-1] = fillchar;
+ if (fillable && *t == ' '
+ && (!VIM_ISDIGIT(*(t+1)) || fillchar != '-'))
+ MB_CHAR2BYTES(fillchar, p);
+ else
+ *p++ = *t;
}
for (; l < minwid && p + 1 < out + outlen; l++)
- *p++ = fillchar;
+ MB_CHAR2BYTES(fillchar, p);
}
else if (num >= 0)
{
@@ -4214,16 +4210,14 @@
{
s = out;
width = 0;
- for (;;)
+ while (width + ptr2cells(s) < maxwidth)
{
width += ptr2cells(s);
- if (width >= maxwidth)
- break;
s += (*mb_ptr2len)(s);
}
/* Fill up for half a double-wide character. */
while (++width < maxwidth)
- *s++ = fillchar;
+ MB_CHAR2BYTES(fillchar, s);
}
else
#endif
@@ -4258,7 +4252,7 @@
while (++width < maxwidth)
{
s = s + STRLEN(s);
- *s++ = fillchar;
+ MB_CHAR2BYTES(fillchar, s);
*s = NUL;
}
@@ -4281,12 +4275,13 @@
break;
if (l < itemcnt)
{
- p = item[l].start + maxwidth - width;
+ int middlelength = (maxwidth - width) * MB_CHAR2LEN(fillchar);
+ p = item[l].start + middlelength;
STRMOVE(p, item[l].start);
- for (s = item[l].start; s < p; s++)
- *s = fillchar;
+ for (s = item[l].start; s < p;)
+ MB_CHAR2BYTES(fillchar, s);
for (l++; l < itemcnt; l++)
- item[l].start += maxwidth - width;
+ item[l].start += middlelength;
width = maxwidth;
}
}
diff -r 58686d48772e src/macros.h
--- a/src/macros.h Wed Jul 03 22:28:36 2013 +0200
+++ b/src/macros.h Fri Jul 05 23:54:36 2013 +0200
@@ -269,16 +269,18 @@
/* get length of multi-byte char, not including composing chars */
# define mb_cptr2len(p) (enc_utf8 ? utf_ptr2len(p) : (*mb_ptr2len)(p))
-# define MB_COPY_CHAR(f, t) if (has_mbyte) mb_copy_char(&f, &t); else *t++ = *f++
-# define MB_CHARLEN(p) (has_mbyte ? mb_charlen(p) : (int)STRLEN(p))
-# define MB_CHAR2LEN(c) (has_mbyte ? mb_char2len(c) : 1)
-# define PTR2CHAR(p) (has_mbyte ? mb_ptr2char(p) : (int)*(p))
+# define MB_COPY_CHAR(f, t) if (has_mbyte) mb_copy_char(&f, &t); else *t++ = *f++
+# define MB_CHAR2BYTES(c, b) if (has_mbyte) b += (*mb_char2bytes)(c, b); else *b++ = c
+# define MB_CHARLEN(p) (has_mbyte ? mb_charlen(p) : (int)STRLEN(p))
+# define MB_CHAR2LEN(c) (has_mbyte ? mb_char2len(c) : 1)
+# define PTR2CHAR(p) (has_mbyte ? mb_ptr2char(p) : (int)*(p))
#else
# define MB_PTR2LEN(p) 1
# define mb_ptr_adv(p) ++p
# define mb_cptr_adv(p) ++p
# define mb_ptr_back(s, p) --p
# define MB_COPY_CHAR(f, t) *t++ = *f++
+# define MB_CHAR2BYTES(c, b) *b++ = c
# define MB_CHARLEN(p) STRLEN(p)
# define MB_CHAR2LEN(c) 1
# define PTR2CHAR(p) ((int)*(p))