multiprogress.c: Fix `split_string' to overestimate.
authorMark Wooding <mdw@distorted.org.uk>
Fri, 25 Mar 2022 01:12:56 +0000 (01:12 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Fri, 25 Mar 2022 18:51:48 +0000 (18:51 +0000)
Doing the right thing in `advance_measure' is much harder if
`split_string' sometimes falls short of the requested bound because of
wide characters.  On the other hand, overestimating is a little tricky
because we must remember to include all of the following zero-
width (e.g., combining) characters or the prefix will just be wrong.
But it's better to do this than come up with some kludge to make
`advance_measure' sometimes advance the state even when we've not
actually reached the right position.

multiprogress.c

index f63eaa6..6945620 100644 (file)
@@ -254,16 +254,22 @@ static size_t split_string(const char *p, size_t sz,
                           unsigned *wd_out, unsigned maxwd)
 {
   struct measure m;
-  size_t lasti; unsigned lastwd;
+  size_t i; unsigned wd;
   int more;
 
   init_measure(&m, p, sz);
   for (;;) {
-    lasti = m.i; lastwd = m.wd;
+    if (!advance_measure(&m)) { *wd_out = m.wd; return (sz); }
+    if (m.wd >= maxwd) break;
+  }
+  wd = m.wd; i = m.i;
+  for (;;) {
     more = advance_measure(&m);
-    if (m.wd > maxwd) { *wd_out = lastwd; return (lasti); }
-    else if (!more) { *wd_out = m.wd; return (sz); }
+    if (m.wd > wd) break;
+    i = m.i;
+    if (!more) break;
   }
+  *wd_out = wd; return (i);
 }
 
 static int grow_linebuf(struct progress_render_state *render, size_t want)
@@ -488,7 +494,7 @@ static void advance_bar_state(struct bar_state *bar)
   const struct progress_ttyinfo *tty = render->tty;
   size_t here = bar->nextpos;
 
-  while (bar->nextpos == here) {
+  while (bar->nextpos <= here) {
     switch (bar->state) {
       case LEFT_COLOUR: set_bgcolour(tty, 3); goto right;
       case LEFT_MONO: put_sequence(tty, tty->cap.me, 1); goto right;