198 lines
5.2 KiB
Diff
198 lines
5.2 KiB
Diff
Index: entry.c
|
|
===================================================================
|
|
RCS file: /usr/local/CVS/newt/entry.c,v
|
|
retrieving revision 1.40
|
|
retrieving revision 1.41
|
|
diff -u -r1.40 -r1.41
|
|
--- entry.c 11 Oct 2006 15:19:39 -0000 1.40
|
|
+++ entry.c 4 Apr 2007 15:17:51 -0000 1.41
|
|
@@ -25,6 +25,8 @@
|
|
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 @@
|
|
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 @@
|
|
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 @@
|
|
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 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 @@
|
|
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 @@
|
|
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++)
|
|
@@ -462,6 +472,10 @@
|
|
er.result = ER_IGNORED;
|
|
}
|
|
}
|
|
+
|
|
+ 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);
|
|
|