]> git.ipfire.org Git - thirdparty/newt.git/blame - entry.c
install python modules to purelib and platlib
[thirdparty/newt.git] / entry.c
CommitLineData
d638bf45 1#include "config.h"
2
3#ifdef HAVE_ALLOCA_H
4#include <alloca.h>
5#endif
6
6fb96a3f 7#include <ctype.h>
139f06bc 8#include <slang.h>
6fb96a3f 9#include <stdlib.h>
fec0af06 10#include <string.h>
feef2cb5 11#include <wchar.h>
6fb96a3f 12
13#include "newt.h"
14#include "newt_pr.h"
15
16struct entry {
17 int flags;
18 char * buf;
d78245ab 19 const char ** resultPtr;
6fb96a3f 20 int bufAlloced;
6f481af2 21 int bufUsed; /* amount of the buffer that's been used */
22 int cursorPosition; /* cursor *in the string* on on screen */
23 int firstChar; /* first character position being shown */
fad2cd5f 24 newtEntryFilter filter;
25 void * filterData;
099b22e5
ML
26 int cs;
27 int csDisabled;
6fb96a3f 28};
29
4d4a4e20 30static int previous_char(const char *buf, int pos);
31static int next_char(const char *buf, int pos);
6fb96a3f 32static void entryDraw(newtComponent co);
33static void entryDestroy(newtComponent co);
45f6c4fd 34static struct eventResult entryEvent(newtComponent co,
6f481af2 35 struct event ev);
6fb96a3f 36
45c366b1 37static struct eventResult entryHandleKey(newtComponent co, int key);
6fb96a3f 38
39static struct componentOps entryOps = {
40 entryDraw,
41 entryEvent,
42 entryDestroy,
8f52cd47 43 newtDefaultPlaceHandler,
44 newtDefaultMappedHandler,
6fb96a3f 45} ;
46
d4109c37 47void newtEntrySet(newtComponent co, const char * value, int cursorAtEnd) {
8121f050 48 struct entry * en = co->data;
49
a880525e 50 if ((strlen(value) + 1) > (unsigned int)en->bufAlloced) {
6f481af2 51 free(en->buf);
52 en->bufAlloced = strlen(value) + 1;
53 en->buf = malloc(en->bufAlloced);
54 if (en->resultPtr) *en->resultPtr = en->buf;
8121f050 55 }
6f481af2 56 memset(en->buf, 0, en->bufAlloced); /* clear the buffer */
8121f050 57 strcpy(en->buf, value);
58 en->bufUsed = strlen(value);
59 en->firstChar = 0;
60 if (cursorAtEnd)
6f481af2 61 en->cursorPosition = en->bufUsed;
8121f050 62 else
6f481af2 63 en->cursorPosition = 0;
8121f050 64
65 entryDraw(co);
66} ;
67
d4109c37 68newtComponent newtEntry(int left, int top, const char * initialValue, int width,
6f481af2 69 const char ** resultPtr, int flags) {
6fb96a3f 70 newtComponent co;
71 struct entry * en;
72
73 co = malloc(sizeof(*co));
74 en = malloc(sizeof(struct entry));
75 co->data = en;
76
77 co->top = top;
78 co->left = left;
79 co->height = 1;
80 co->width = width;
8f52cd47 81 co->isMapped = 0;
f4eeb9ee 82 co->callback = NULL;
c101e99e 83 co->destroyCallback = NULL;
6fb96a3f 84
85 co->ops = &entryOps;
86
87 en->flags = flags;
88 en->cursorPosition = 0;
89 en->firstChar = 0;
90 en->bufUsed = 0;
91 en->bufAlloced = width + 1;
fad2cd5f 92 en->filter = NULL;
6fb96a3f 93
4a93351d 94 if (!(en->flags & NEWT_FLAG_DISABLED))
6f481af2 95 co->takesFocus = 1;
38f35ccd 96 else
6f481af2 97 co->takesFocus = 0;
38f35ccd 98
feef2cb5 99 if (initialValue && strlen(initialValue) > (unsigned int)width) {
100 en->bufAlloced = strlen(initialValue) + 1;
6fb96a3f 101 }
102 en->buf = malloc(en->bufAlloced);
6fb96a3f 103 en->resultPtr = resultPtr;
fad2cd5f 104 if (en->resultPtr) *en->resultPtr = en->buf;
45f6c4fd 105
6fb96a3f 106 memset(en->buf, 0, en->bufAlloced);
107 if (initialValue) {
6f481af2 108 strcpy(en->buf, initialValue);
109 en->bufUsed = strlen(initialValue);
110 en->cursorPosition = en->bufUsed;
4d4a4e20 111
112 /* move cursor back if entry is full */
113 if (en->cursorPosition && !(en->flags & NEWT_FLAG_SCROLL ||
114 wstrlen(en->buf, -1) < co->width))
115 en->cursorPosition = previous_char(en->buf, en->cursorPosition);
78d39fcf 116 } else {
6f481af2 117 *en->buf = '\0';
118 en->bufUsed = 0;
119 en->cursorPosition = 0;
6fb96a3f 120 }
121
099b22e5
ML
122 en->cs = NEWT_COLORSET_ENTRY;
123 en->csDisabled = NEWT_COLORSET_DISENTRY;
124
6fb96a3f 125 return co;
126}
127
feef2cb5 128static void scroll(struct entry *en, int width)
129{
4d4a4e20 130 int r, lv, rv, cntx, cw, cn, nc, pc, ncw, pcw;
131
132 if (width <= 1) {
133 en->firstChar = en->cursorPosition;
134 return;
135 }
136
137 cntx = width / 4;
138 if (cntx > 5)
139 cntx = 5;
140
141 if (en->cursorPosition < en->firstChar)
142 en->firstChar = en->cursorPosition;
143
144 cn = next_char(en->buf, en->cursorPosition);
145 cw = en->cursorPosition >= en->bufUsed ? 1 :
146 wstrlen(en->buf + en->cursorPosition, cn - en->cursorPosition);
147
148 r = wstrlen(en->buf + cn, -1);
149
150 lv = wstrlen(en->buf + en->firstChar, en->cursorPosition - en->firstChar);
151 rv = width - lv - cw;
152
153#define RC (ncw > 0 && (r > rv && lv - ncw >= cntx && rv < cntx))
154#define LC (pcw > 0 && (r + pcw <= rv || (lv < cntx && rv - pcw >= cntx)))
155
156 nc = next_char(en->buf, en->firstChar);
157 ncw = wstrlen(en->buf + en->firstChar, nc - en->firstChar);
158 if (RC) {
159 do {
160 lv -= ncw;
161 rv += ncw;
162 en->firstChar = nc;
163 nc = next_char(en->buf, en->firstChar);
164 ncw = wstrlen(en->buf + en->firstChar, nc - en->firstChar);
165 } while (RC);
166 return;
167 }
168
169 pc = previous_char(en->buf, en->firstChar);
170 pcw = wstrlen(en->buf + pc, en->firstChar - pc);
171 if (LC) {
172 do {
173 lv += pcw;
174 rv -= pcw;
175 en->firstChar = pc;
176 pc = previous_char(en->buf, en->firstChar);
177 pcw = wstrlen(en->buf + pc, en->firstChar - pc);
178 } while (LC);
feef2cb5 179 }
180}
181
6fb96a3f 182static void entryDraw(newtComponent co) {
183 struct entry * en = co->data;
184 int i;
185 char * chptr;
186 int len;
feef2cb5 187 char *tmpptr = NULL;
94396885 188
8f52cd47 189 if (!co->isMapped) return;
38f35ccd 190
45f6c4fd 191 if (en->flags & NEWT_FLAG_DISABLED)
099b22e5 192 SLsmg_set_color(en->csDisabled);
38f35ccd 193 else
099b22e5 194 SLsmg_set_color(en->cs);
45f6c4fd 195
4a93351d 196 if (en->flags & NEWT_FLAG_HIDDEN) {
6f481af2 197 newtGotorc(co->top, co->left);
198 for (i = 0; i < co->width; i++)
199 SLsmg_write_char('_');
200 newtGotorc(co->top, co->left);
6fb96a3f 201
6f481af2 202 return;
6fb96a3f 203 }
204
3aab8830 205 newtTrashScreen();
206
4d4a4e20 207 /* scroll if necessary */
208 scroll(en, co->width);
6fb96a3f 209
210 chptr = en->buf + en->firstChar;
20fb366a 211
212 if (en->flags & NEWT_FLAG_PASSWORD) {
2a157d55 213 len = wstrlen(chptr, -1);
214 tmpptr = alloca(len + 1);
215 for (i = 0; i < len; i++)
216 memset(tmpptr, '*', len);
217 tmpptr[len] = '\0';
6f481af2 218 chptr = tmpptr;
219 }
20fb366a 220
ce11acc8 221 len = wstrlen(chptr, -1);
45f6c4fd 222
f423597b 223 /* workaround for double width characters */
224 if (co->width > 1) {
225 i = len < co->width ? len : co->width;
226 i = i > 2 ? i - 2 : 0;
227 newtGotorc(co->top, co->left + i);
228 SLsmg_write_char('_');
229 SLsmg_write_char('_');
230 }
231
232 newtGotorc(co->top, co->left);
233
6fb96a3f 234 if (len <= co->width) {
6f481af2 235 i = len;
236 SLsmg_write_string(chptr);
237 while (i < co->width) {
238 SLsmg_write_char('_');
239 i++;
240 }
8e0e899c
ML
241 } else
242 SLsmg_write_nstring(chptr, co->width);
6fb96a3f 243
f423597b 244 newtGotorc(co->top, co->left + wstrlen(en->buf+en->firstChar, en->cursorPosition - en->firstChar));
6fb96a3f 245}
246
38f35ccd 247void newtEntrySetFlags(newtComponent co, int flags, enum newtFlagsSense sense) {
248 struct entry * en = co->data;
249 int row, col;
250
251 en->flags = newtSetFlags(en->flags, flags, sense);
252
4a93351d 253 if (!(en->flags & NEWT_FLAG_DISABLED))
6f481af2 254 co->takesFocus = 1;
38f35ccd 255 else
6f481af2 256 co->takesFocus = 0;
38f35ccd 257
258 newtGetrc(&row, &col);
259 entryDraw(co);
260 newtGotorc(row, col);
261}
262
099b22e5
ML
263void newtEntrySetColors(newtComponent co, int normal, int disabled) {
264 struct entry * en = co->data;
265
266 en->cs = normal;
267 en->csDisabled = disabled;
268 entryDraw(co);
269}
270
6fb96a3f 271static void entryDestroy(newtComponent co) {
272 struct entry * en = co->data;
273
274 free(en->buf);
275 free(en);
276 free(co);
277}
278
45f6c4fd 279static struct eventResult entryEvent(newtComponent co,
6f481af2 280 struct event ev) {
6fb96a3f 281 struct entry * en = co->data;
282 struct eventResult er;
fad2cd5f 283 int ch;
6fb96a3f 284
c00a8d1b 285 er.result = ER_IGNORED;
286
c1a075d9 287 if (ev.when == EV_NORMAL) {
6f481af2 288 switch (ev.event) {
289 case EV_FOCUS:
290 newtCursorOn();
291 if (en->flags & NEWT_FLAG_HIDDEN)
292 newtGotorc(co->top, co->left);
293 else
294 newtGotorc(co->top, co->left +
feef2cb5 295 wstrlen(en->buf + en->firstChar, en->cursorPosition - en->firstChar));
6f481af2 296 er.result = ER_SWALLOWED;
297 break;
298
299 case EV_UNFOCUS:
300 newtCursorOff();
301 newtGotorc(0, 0);
302 er.result = ER_SWALLOWED;
303 if (co->callback)
304 co->callback(co, co->callbackData);
305 break;
306
307 case EV_KEYPRESS:
308 ch = ev.u.key;
309 if (en->filter)
310 ch = en->filter(co, en->filterData, ch, en->cursorPosition);
311 if (ch) er = entryHandleKey(co, ch);
312 break;
313
314 case EV_MOUSE:
315 if ((ev.u.mouse.type == MOUSE_BUTTON_DOWN) &&
316 (en->flags ^ NEWT_FLAG_HIDDEN)) {
317 if (strlen(en->buf) >= ev.u.mouse.x - co->left) {
318 en->cursorPosition = ev.u.mouse.x - co->left;
319 newtGotorc(co->top,
320 co->left +(en->cursorPosition - en->firstChar));
321 } else {
322 en->cursorPosition = strlen(en->buf);
323 newtGotorc(co->top,
324 co->left +(en->cursorPosition - en->firstChar));
325 }
326 }
327 break;
328 }
c00a8d1b 329 }
6fb96a3f 330
331 return er;
332}
333
feef2cb5 334static int previous_char(const char *buf, int pos)
335{
336 int len = 0;
337 int off = 0;
338
339 while (off < pos) {
340 len = mblen(buf+off, MB_CUR_MAX);
341 if (len <= 0)
342 return pos;
343 off+=len;
344 }
345 return off-len;
346}
347
348static int next_char(const char *buf, int pos)
349{
350 int len = mblen(buf + pos, MB_CUR_MAX);
4d4a4e20 351 if (len <= 0)
feef2cb5 352 return pos;
feef2cb5 353 return pos+len;
354}
355
45c366b1 356static struct eventResult entryHandleKey(newtComponent co, int key) {
6fb96a3f 357 struct entry * en = co->data;
358 struct eventResult er;
4d4a4e20 359 char * chptr;
6fb96a3f 360
361 er.result = ER_SWALLOWED;
362 switch (key) {
6f481af2 363 case '\r': /* Return */
364 if (en->flags & NEWT_FLAG_RETURNEXIT) {
e5437c85 365 newtCursorOff();
6f481af2 366 er.result = ER_EXITFORM;
367 } else {
368 er.result = ER_NEXTCOMP;
369 }
370 break;
371
372 case '\001': /* ^A */
6fb96a3f 373 case NEWT_KEY_HOME:
6f481af2 374 en->cursorPosition = 0;
375 break;
6fb96a3f 376
6f481af2 377 case '\005': /* ^E */
6fb96a3f 378 case NEWT_KEY_END:
6f481af2 379 en->cursorPosition = en->bufUsed;
380 break;
6fb96a3f 381
6f481af2 382 case '\013': /* ^K */
383 en->bufUsed = en->cursorPosition;
384 memset(en->buf + en->bufUsed, 0, en->bufAlloced - en->bufUsed);
385 break;
6fb96a3f 386
feef2cb5 387 case '\025': /* ^U */
388 en->bufUsed -= en->cursorPosition;
389 memmove(en->buf, en->buf + en->cursorPosition, en->bufUsed);
390 en->cursorPosition = 0;
391 memset(en->buf + en->bufUsed, 0, en->bufAlloced - en->bufUsed);
392 break;
393
6f481af2 394 case '\002': /* ^B */
6fb96a3f 395 case NEWT_KEY_LEFT:
6f481af2 396 if (en->cursorPosition)
feef2cb5 397 en->cursorPosition = previous_char(en->buf, en->cursorPosition);
6f481af2 398 break;
6fb96a3f 399
400 case '\004':
401 case NEWT_KEY_DELETE:
6f481af2 402 chptr = en->buf + en->cursorPosition;
403 if (*chptr) {
feef2cb5 404 int delta = next_char(en->buf, en->cursorPosition)-en->cursorPosition;
405 if (delta) {
406 chptr+=delta;
407 while (*chptr) {
408 *(chptr - delta) = *chptr;
409 chptr++;
410 }
411 memset(chptr - delta, 0, delta);
412 en->bufUsed-=delta;
6f481af2 413 }
6f481af2 414 }
415 break;
6fb96a3f 416
feef2cb5 417 case NEWT_KEY_BKSPC: {
418 int prev = previous_char(en->buf, en->cursorPosition);
419 if (en->cursorPosition != prev) {
6f481af2 420 /* if this isn't true, there's nothing to erase */
feef2cb5 421 int delta = en->cursorPosition - prev;
6f481af2 422 chptr = en->buf + en->cursorPosition;
feef2cb5 423 en->bufUsed-=delta;
424 en->cursorPosition-=delta;
6f481af2 425 while (*chptr) {
feef2cb5 426 *(chptr - delta) = *chptr;
6f481af2 427 chptr++;
428 }
feef2cb5 429 memset(chptr - delta, 0, delta);
430 }
6f481af2 431 }
432 break;
433
434 case '\006': /* ^B */
6fb96a3f 435 case NEWT_KEY_RIGHT:
6f481af2 436 if (en->cursorPosition < en->bufUsed)
feef2cb5 437 en->cursorPosition = next_char(en->buf, en->cursorPosition);
6f481af2 438 break;
6fb96a3f 439
440 default:
feef2cb5 441 if ((key >= 0x20 && key <= 0x7e) || (key >= 0x80 && key <= 0xff)) {
4062a29f 442 char s[MB_CUR_MAX];
443 mbstate_t ps;
444 int i, l;
445
446 for (i = 1, s[0] = key; ; i++) {
447 memset(&ps, 0, sizeof (ps));
448 l = mbrtowc(NULL, s, i, &ps);
449 if (l == -1) /* invalid sequence */
450 i = 0;
451 if (l != -2) /* not incomplete sequence */
452 break;
453
454 /* read next byte */
455 if (i == MB_CUR_MAX || !SLang_input_pending(1)) {
456 i = 0;
457 break;
458 }
459 s[i] = SLang_getkey();
460 }
461
4d4a4e20 462 if (!i || (!(en->flags & NEWT_FLAG_SCROLL) && wstrlen(en->buf, -1) + wstrlen(s, i) > co->width)) {
feef2cb5 463 /* FIXME this is broken */
6f481af2 464 SLtt_beep();
465 break;
466 }
467
4062a29f 468 if ((en->bufUsed + i) >= en->bufAlloced) {
6f481af2 469 en->bufAlloced += 20;
470 en->buf = realloc(en->buf, en->bufAlloced);
471 if (en->resultPtr) *en->resultPtr = en->buf;
4d4a4e20 472 memset(en->buf + en->bufAlloced - 20, 0, 20);
6f481af2 473 }
474
4062a29f 475 if (en->cursorPosition != en->bufUsed) {
6f481af2 476 /* insert the new character */
4d4a4e20 477 memmove(en->buf + en->cursorPosition + i, en->buf + en->cursorPosition, en->bufUsed - en->cursorPosition);
6f481af2 478 }
4062a29f 479 en->bufUsed += i;
480 for (l = 0; l < i; l++)
481 en->buf[en->cursorPosition++] = s[l];
6f481af2 482 } else {
483 er.result = ER_IGNORED;
484 }
45f6c4fd 485 }
6fb96a3f 486
4d4a4e20 487 if (en->cursorPosition == en->bufUsed && en->cursorPosition &&
488 !(en->flags & NEWT_FLAG_SCROLL || wstrlen(en->buf, -1) < co->width))
489 en->cursorPosition = previous_char(en->buf, en->cursorPosition);
490
6fb96a3f 491 entryDraw(co);
492
493 return er;
494}
fad2cd5f 495
496char * newtEntryGetValue(newtComponent co) {
497 struct entry * en = co->data;
498
499 return en->buf;
500}
501
502void newtEntrySetFilter(newtComponent co, newtEntryFilter filter, void * data) {
503 struct entry * en = co->data;
504 en->filter = filter;
505 en->filterData = data;
506}
c8cddffd
DW
507
508int newtEntryGetCursorPosition (newtComponent co) {
509 struct entry * en = co->data;
510
511 return en->cursorPosition;
512}
513
514void newtEntrySetCursorPosition (newtComponent co, int position) {
515 struct entry * en = co->data;
516
517 en->cursorPosition = position;
518}