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,
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;
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);
}
}
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;
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) {
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;
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++)
}
}
+ 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;