From: mlichvar Date: Wed, 4 Apr 2007 15:17:51 +0000 (+0000) Subject: - fix entry scrolling (#234829) X-Git-Tag: r0-52-7~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4d4a4e20308a2d50beffdbbfa6452b2ec7b98f8c;p=thirdparty%2Fnewt.git - fix entry scrolling (#234829) - fix multibyte character handling in entry --- diff --git a/entry.c b/entry.c index db8f310..0c13135 100644 --- a/entry.c +++ b/entry.c @@ -25,6 +25,8 @@ struct entry { void * filterData; }; +static int previous_char(const char *buf, int pos); +static int next_char(const char *buf, int pos); static void entryDraw(newtComponent co); static void entryDestroy(newtComponent co); static struct eventResult entryEvent(newtComponent co, @@ -103,6 +105,11 @@ newtComponent newtEntry(int left, int top, const char * initialValue, int width, strcpy(en->buf, initialValue); en->bufUsed = strlen(initialValue); en->cursorPosition = en->bufUsed; + + /* move cursor back if entry is full */ + if (en->cursorPosition && !(en->flags & NEWT_FLAG_SCROLL || + wstrlen(en->buf, -1) < co->width)) + en->cursorPosition = previous_char(en->buf, en->cursorPosition); } else { *en->buf = '\0'; en->bufUsed = 0; @@ -112,39 +119,57 @@ newtComponent newtEntry(int left, int top, const char * initialValue, int width, return co; } -static int visible_width(const char *str, int start, int end) -{ - int width = wstrlen(str + start, end-start); - int len, w = 0; - wchar_t wc; - - len = mbtowc(&wc, str+end, MB_CUR_MAX); - if (len == 0) - w = 1; - else if (len > 0) - w = wcwidth(wc); - return width + w; -} - static void scroll(struct entry *en, int width) { - wchar_t wc; - int len, w; - int newwidth = visible_width(en->buf, en->firstChar, en->cursorPosition); - - while (newwidth > width) { - len = mbtowc(&wc, en->buf+en->firstChar, MB_CUR_MAX); - if (!len) { - en->firstChar++; - break; - } - if (len < 0) - break; - w = wcwidth(wc); - if (w < 0) - break; - en->firstChar += len; - newwidth -= w; + int r, lv, rv, cntx, cw, cn, nc, pc, ncw, pcw; + + if (width <= 1) { + en->firstChar = en->cursorPosition; + return; + } + + cntx = width / 4; + if (cntx > 5) + cntx = 5; + + if (en->cursorPosition < en->firstChar) + en->firstChar = en->cursorPosition; + + cn = next_char(en->buf, en->cursorPosition); + cw = en->cursorPosition >= en->bufUsed ? 1 : + wstrlen(en->buf + en->cursorPosition, cn - en->cursorPosition); + + r = wstrlen(en->buf + cn, -1); + + lv = wstrlen(en->buf + en->firstChar, en->cursorPosition - en->firstChar); + rv = width - lv - cw; + +#define RC (ncw > 0 && (r > rv && lv - ncw >= cntx && rv < cntx)) +#define LC (pcw > 0 && (r + pcw <= rv || (lv < cntx && rv - pcw >= cntx))) + + nc = next_char(en->buf, en->firstChar); + ncw = wstrlen(en->buf + en->firstChar, nc - en->firstChar); + if (RC) { + do { + lv -= ncw; + rv += ncw; + en->firstChar = nc; + nc = next_char(en->buf, en->firstChar); + ncw = wstrlen(en->buf + en->firstChar, nc - en->firstChar); + } while (RC); + return; + } + + pc = previous_char(en->buf, en->firstChar); + pcw = wstrlen(en->buf + pc, en->firstChar - pc); + if (LC) { + do { + lv += pcw; + rv -= pcw; + en->firstChar = pc; + pc = previous_char(en->buf, en->firstChar); + pcw = wstrlen(en->buf + pc, en->firstChar - pc); + } while (LC); } } @@ -171,13 +196,8 @@ static void entryDraw(newtComponent co) { return; } - if (en->cursorPosition < en->firstChar) { - /* scroll to the left */ - en->firstChar = en->cursorPosition; - } else { - /* scroll to the right */ - scroll(en, co->width); - } + /* scroll if necessary */ + scroll(en, co->width); chptr = en->buf + en->firstChar; @@ -317,17 +337,15 @@ static int previous_char(const char *buf, int pos) static int next_char(const char *buf, int pos) { int len = mblen(buf + pos, MB_CUR_MAX); - if (len < 0) + if (len <= 0) return pos; - if (len == 0) - return ++pos; return pos+len; } static struct eventResult entryHandleKey(newtComponent co, int key) { struct entry * en = co->data; struct eventResult er; - char * chptr, * insPoint; + char * chptr; er.result = ER_SWALLOWED; switch (key) { @@ -430,7 +448,7 @@ static struct eventResult entryHandleKey(newtComponent co, int key) { s[i] = SLang_getkey(); } - if (!i || !(en->flags & NEWT_FLAG_SCROLL) && wstrlen(en->buf, -1) >= co->width) { + if (!i || (!(en->flags & NEWT_FLAG_SCROLL) && wstrlen(en->buf, -1) + wstrlen(s, i) > co->width)) { /* FIXME this is broken */ SLtt_beep(); break; @@ -440,20 +458,12 @@ static struct eventResult entryHandleKey(newtComponent co, int key) { en->bufAlloced += 20; en->buf = realloc(en->buf, en->bufAlloced); if (en->resultPtr) *en->resultPtr = en->buf; - memset(en->buf + en->bufUsed + 1, 0, 20); + memset(en->buf + en->bufAlloced - 20, 0, 20); } if (en->cursorPosition != en->bufUsed) { /* insert the new character */ - - /* chptr is the last character in the string */ - chptr = (en->buf + en->bufUsed) - 2 + i; - insPoint = en->buf + en->cursorPosition; - - while (chptr >= insPoint) { - *(chptr + i) = *chptr; - chptr--; - } + memmove(en->buf + en->cursorPosition + i, en->buf + en->cursorPosition, en->bufUsed - en->cursorPosition); } en->bufUsed += i; for (l = 0; l < i; l++) @@ -463,6 +473,10 @@ static struct eventResult entryHandleKey(newtComponent co, int key) { } } + if (en->cursorPosition == en->bufUsed && en->cursorPosition && + !(en->flags & NEWT_FLAG_SCROLL || wstrlen(en->buf, -1) < co->width)) + en->cursorPosition = previous_char(en->buf, en->cursorPosition); + entryDraw(co); return er; diff --git a/newt.spec b/newt.spec index c38e851..154ad10 100644 --- a/newt.spec +++ b/newt.spec @@ -88,6 +88,9 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/libnewt.a %changelog +- fix entry scrolling (#234829) +- fix multibyte character handling in entry + * Fri Mar 02 2007 Miroslav Lichvar - 0.52.6-1 - add newtSetColor() to allow changing individual colors - add newtPopWindowNoRefresh() (patch by Forest Bond)