Source-Changes-HG archive

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

[src/trunk]: src/lib/libcurses Fix for PR lib/55433



details:   https://anonhg.NetBSD.org/src/rev/9a9f02f81994
branches:  trunk
changeset: 1026257:9a9f02f81994
user:      blymn <blymn%NetBSD.org@localhost>
date:      Mon Nov 15 06:27:06 2021 +0000

description:
Fix for PR lib/55433

Correct the behaviour for ins_wstr:
* Properly check the string will fit by processing any special
  characters present when preforming the check.
* Simplify the routine by removing code that duplicates the code in
  _cursesi_addwchar and just call _cursesi_addwchar.

diffstat:

 lib/libcurses/ins_wstr.c |  375 +++++++++++++++++++++++++++++-----------------
 1 files changed, 232 insertions(+), 143 deletions(-)

diffs (truncated from 429 to 300 lines):

diff -r e57678fecaf1 -r 9a9f02f81994 lib/libcurses/ins_wstr.c
--- a/lib/libcurses/ins_wstr.c  Sun Nov 14 21:18:30 2021 +0000
+++ b/lib/libcurses/ins_wstr.c  Mon Nov 15 06:27:06 2021 +0000
@@ -1,4 +1,4 @@
-/*   $NetBSD: ins_wstr.c,v 1.17 2021/09/06 07:45:48 rin Exp $ */
+/*   $NetBSD: ins_wstr.c,v 1.18 2021/11/15 06:27:06 blymn Exp $ */
 
 /*
  * Copyright (c) 2005 The NetBSD Foundation Inc.
@@ -36,7 +36,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: ins_wstr.c,v 1.17 2021/09/06 07:45:48 rin Exp $");
+__RCSID("$NetBSD: ins_wstr.c,v 1.18 2021/11/15 06:27:06 blymn Exp $");
 #endif                                           /* not lint */
 
 #include <string.h>
@@ -133,8 +133,9 @@
        __LDATA  *start, *temp1, *temp2;
        __LINE    *lnp;
        const wchar_t *scp;
-       int width, len, sx, x, y, cw, pcw, newx;
-       nschar_t *np;
+       cchar_t cc;
+       wchar_t *lstr, *slstr;
+       int i, width, len, lx, sx, x, y, tx, ty, cw, pcw, newx, tn, w;
        wchar_t ws[] = L"               ";
 
        /* check for leading non-spacing character */
@@ -146,171 +147,259 @@
        if (!cw)
                return ERR;
 
+       lstr = malloc(sizeof(wchar_t) * win->maxx);
+       if (lstr == NULL)
+               return ERR;
+
        scp = wstr + 1;
        width = cw;
        len = 1;
        n--;
+       y = win->cury;
+       x = win->curx;
+       tn = n;
+
+       /*
+        * Firstly, make sure the string will fit...
+        */
        while (*scp) {
-               int w;
-               if (!n)
+               if (!tn)
                        break;
+               switch (*scp) {
+                       case L'\b':
+                               if (--x < 0)
+                                       x = 0;
+                               cw = wcwidth(*(scp - 1));
+                               if (cw < 0)
+                                       cw = 1;
+                               width -= cw;
+                               scp++;
+                               continue;;
+
+                       case L'\r':
+                               width = 0;
+                               x = 0;
+                               scp++;
+                               continue;
+
+                       case L'\n':
+                               if (y == win->scr_b) {
+                                       if (!(win->flags & __SCROLLOK)) {
+                                               free(lstr);
+                                               return ERR;
+                                       }
+                               }
+                               y++;
+                               scp++;
+                               continue;
+
+                       case L'\t':
+                               w = min(win->maxx - x, TABSIZE - (x % TABSIZE));
+                               width += w * wcwidth(ws[0]);
+                               x += w * wcwidth(ws[0]);
+                               scp++;
+                               continue;
+               }
                w = wcwidth(*scp);
                if (w < 0)
                        w = 1;
-               n--, len++, width += w;
+               tn--, width += w;
                scp++;
        }
        __CTRACE(__CTRACE_INPUT, "wins_nwstr: width=%d,len=%d\n", width, len);
 
-       if (cw > win->maxx - win->curx + 1)
+       if (width > win->maxx - win->curx + 1) {
+               free(lstr);
                return ERR;
-       start = &win->alines[win->cury]->line[win->curx];
-       sx = win->curx;
-       lnp = win->alines[win->cury];
-       pcw = WCOL(*start);
-       if (pcw < 0) {
-               sx += pcw;
-               start += pcw;
-       }
-       __CTRACE(__CTRACE_INPUT, "wins_nwstr: start@(%d)\n", sx);
-       pcw = WCOL(*start);
-       lnp->flags |= __ISDIRTY;
-       newx = sx + win->ch_off;
-       if (newx < *lnp->firstchp)
-               *lnp->firstchp = newx;
-#ifdef DEBUG
-       {
-               __CTRACE(__CTRACE_INPUT, "========before=======\n");
-               for (x = 0; x < win->maxx; x++)
-                       __CTRACE(__CTRACE_INPUT,
-                           "wins_nwstr: (%d,%d)=(%x,%x,%p)\n",
-                           win->cury, x,
-                           win->alines[win->cury]->line[x].ch,
-                           win->alines[win->cury]->line[x].attr,
-                           win->alines[win->cury]->line[x].nsp);
-       }
-#endif /* DEBUG */
-
-       /* shift all complete characters */
-       if (sx + width + pcw <= win->maxx) {
-               __CTRACE(__CTRACE_INPUT, "wins_nwstr: shift all characters\n");
-               temp1 = &win->alines[win->cury]->line[win->maxx - 1];
-               temp2 = temp1 - width;
-               pcw = WCOL(*(temp2 + 1));
-               if (pcw < 0) {
-                       __CTRACE(__CTRACE_INPUT,
-                           "wins_nwstr: clear from %d to EOL(%d)\n",
-                           win->maxx + pcw, win->maxx - 1);
-                       temp2 += pcw;
-                       while (temp1 > temp2 + width) {
-                               temp1->ch = (wchar_t)btowc((int) win->bch);
-                               if (_cursesi_copy_nsp(win->bnsp, temp1) == ERR)
-                                       return ERR;
-                               temp1->attr = win->battr;
-                               SET_WCOL(*temp1, 1);
-                               __CTRACE(__CTRACE_INPUT,
-                                   "wins_nwstr: empty cell(%p)\n", temp1);
-                               temp1--;
-                       }
-               }
-               while (temp2 >= start) {
-                       (void)memcpy(temp1, temp2, sizeof(__LDATA));
-                       temp1--, temp2--;
-               }
-#ifdef DEBUG
-               {
-                       __CTRACE(__CTRACE_INPUT, "=====after shift====\n");
-                       for (x = 0; x < win->maxx; x++)
-                               __CTRACE(__CTRACE_INPUT,
-                                   "wins_nwstr: (%d,%d)=(%x,%x,%p)\n",
-                                   win->cury, x,
-                                   win->alines[win->cury]->line[x].ch,
-                                   win->alines[win->cury]->line[x].attr,
-                                   win->alines[win->cury]->line[x].nsp);
-               }
-#endif /* DEBUG */
        }
 
-       /* update string columns */
+       scp = wstr;
        x = win->curx;
        y = win->cury;
-       for (scp = wstr, temp1 = start; len; len--, scp++) {
-               switch (*scp) {
-                       case L'\b':
-                               if (--x < 0)
+       len = 0;
+       width = 0;
+       slstr = lstr;
+
+       while (*scp && n) {
+               lstr = slstr;
+               lx = x;
+               while (*scp) {
+                       if (!n)
+                               break;
+                       switch (*scp) {
+                               case L'\b':
+                                       if (--x < 0)
+                                               x = 0;
+                                       if (--len < 0)
+                                               len = 0;
+                                       cw = wcwidth(*(scp - 1));
+                                       if (cw < 0)
+                                               cw = 1;
+                                       width -= cw;
+                                       scp++;
+                                       if (lstr != slstr)
+                                               lstr--;
+                                       continue;;
+
+                               case L'\r':
+                                       width = 0;
+                                       len = 0;
                                        x = 0;
-                               win->curx = x;
-                               continue;;
-                       case L'\r':
-                               win->curx = 0;
-                               continue;
-                       case L'\n':
-                               wclrtoeol(win);
-                               if (y == win->scr_b) {
-                                       if (!(win->flags & __SCROLLOK))
-                                               return ERR;
-                                       scroll(win);
-                               }
-                               continue;
-                       case L'\t':
-                               if (wins_nwstr(win, ws,
-                                   min(win->maxx - x, TABSIZE - (x % TABSIZE)))
-                                   == ERR)
-                                       return ERR;
-                               continue;
+                                       scp++;
+                                       lstr = slstr;
+                                       continue;
+
+                               case L'\n':
+                                       goto loopdone;
+                                       break;
+
+                               case L'\t':
+                                       w = min(win->maxx - x,
+                                           TABSIZE - (x % TABSIZE));
+                                       width += w * wcwidth(ws[0]);
+                                       x += w * wcwidth(ws[0]);
+                                       len += w;
+                                       scp++;
+                                       for (i = 0; i < w; i++ ) {
+                                               *lstr = *ws;
+                                               lstr++;
+                                       }
+                                       continue;
+                       }
+                       w = wcwidth(*scp);
+                       if (w < 0)
+                               w = 1;
+                       *lstr = *scp;
+                       n--, len++, width += w;
+                       scp++, lstr++;
                }
-               cw = wcwidth(*scp);
-               if (cw < 0)
-                       cw = 1;
-               if (cw) {
-                       /* 1st column */
-                       temp1->ch = (wchar_t)*scp;
-                       temp1->attr = win->wattr;
-                       SET_WCOL(*temp1, cw);
-                       temp1->nsp = NULL;
+
+loopdone:
+               start = &win->alines[y]->line[x];
+               sx = x;
+               lnp = win->alines[y];
+               pcw = WCOL(*start);
+               if (pcw < 0) {
+                       sx += pcw;
+                       start += pcw;
+               }
+               __CTRACE(__CTRACE_INPUT, "wins_nwstr: start@(%d)\n", sx);
+               pcw = WCOL(*start);
+               lnp->flags |= __ISDIRTY;
+               newx = sx + win->ch_off;
+               if (newx < *lnp->firstchp)
+                       *lnp->firstchp = newx;
+#ifdef DEBUG
+               {
+                       __CTRACE(__CTRACE_INPUT, "========before=======\n");
+                       for (i = 0; i < win->maxx; i++)
                        __CTRACE(__CTRACE_INPUT,
-                           "wins_nwstr: add spacing char(%x)\n", temp1->ch);
-                       temp2 = temp1++;
-                       if (cw > 1) {
-                               x = -1;
-                               while (temp1 < temp2 + cw) {
-                                       /* the rest columns */
-                                       temp1->ch = (wchar_t)*scp;
-                                       temp1->attr = win->wattr;
-                                       temp1->nsp = NULL;
-                                       SET_WCOL(*temp1, x);
-                                       temp1++, x--;
+                                   "wins_nwstr: (%d,%d)=(%x,%x,%p)\n",
+                                   y, i, win->alines[y]->line[i].ch,
+                                   win->alines[y]->line[i].attr,
+                                   win->alines[y]->line[i].nsp);
+               }
+#endif /* DEBUG */



Home | Main Index | Thread Index | Old Index