]>
git.ipfire.org Git - thirdparty/newt.git/blob - entry.c
19 const char ** resultPtr
;
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 */
24 newtEntryFilter filter
;
30 static int previous_char(const char *buf
, int pos
);
31 static int next_char(const char *buf
, int pos
);
32 static void entryDraw(newtComponent co
);
33 static void entryDestroy(newtComponent co
);
34 static struct eventResult
entryEvent(newtComponent co
,
37 static struct eventResult
entryHandleKey(newtComponent co
, int key
);
39 static struct componentOps entryOps
= {
43 newtDefaultPlaceHandler
,
44 newtDefaultMappedHandler
,
47 void newtEntrySet(newtComponent co
, const char * value
, int cursorAtEnd
) {
48 struct entry
* en
= co
->data
;
50 if ((strlen(value
) + 1) > (unsigned int)en
->bufAlloced
) {
52 en
->bufAlloced
= strlen(value
) + 1;
53 en
->buf
= malloc(en
->bufAlloced
);
54 if (en
->resultPtr
) *en
->resultPtr
= en
->buf
;
56 memset(en
->buf
, 0, en
->bufAlloced
); /* clear the buffer */
57 strcpy(en
->buf
, value
);
58 en
->bufUsed
= strlen(value
);
61 en
->cursorPosition
= en
->bufUsed
;
63 en
->cursorPosition
= 0;
68 newtComponent
newtEntry(int left
, int top
, const char * initialValue
, int width
,
69 const char ** resultPtr
, int flags
) {
73 co
= malloc(sizeof(*co
));
74 en
= malloc(sizeof(struct entry
));
83 co
->destroyCallback
= NULL
;
88 en
->cursorPosition
= 0;
91 en
->bufAlloced
= width
+ 1;
94 if (!(en
->flags
& NEWT_FLAG_DISABLED
))
99 if (initialValue
&& strlen(initialValue
) > (unsigned int)width
) {
100 en
->bufAlloced
= strlen(initialValue
) + 1;
102 en
->buf
= malloc(en
->bufAlloced
);
103 en
->resultPtr
= resultPtr
;
104 if (en
->resultPtr
) *en
->resultPtr
= en
->buf
;
106 memset(en
->buf
, 0, en
->bufAlloced
);
108 strcpy(en
->buf
, initialValue
);
109 en
->bufUsed
= strlen(initialValue
);
110 en
->cursorPosition
= en
->bufUsed
;
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
);
119 en
->cursorPosition
= 0;
122 en
->cs
= NEWT_COLORSET_ENTRY
;
123 en
->csDisabled
= NEWT_COLORSET_DISENTRY
;
128 static void scroll(struct entry
*en
, int width
)
130 int r
, lv
, rv
, cntx
, cw
, cn
, nc
, pc
, ncw
, pcw
;
133 en
->firstChar
= en
->cursorPosition
;
141 if (en
->cursorPosition
< en
->firstChar
)
142 en
->firstChar
= en
->cursorPosition
;
144 cn
= next_char(en
->buf
, en
->cursorPosition
);
145 cw
= en
->cursorPosition
>= en
->bufUsed
? 1 :
146 wstrlen(en
->buf
+ en
->cursorPosition
, cn
- en
->cursorPosition
);
148 r
= wstrlen(en
->buf
+ cn
, -1);
150 lv
= wstrlen(en
->buf
+ en
->firstChar
, en
->cursorPosition
- en
->firstChar
);
151 rv
= width
- lv
- cw
;
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)))
156 nc
= next_char(en
->buf
, en
->firstChar
);
157 ncw
= wstrlen(en
->buf
+ en
->firstChar
, nc
- en
->firstChar
);
163 nc
= next_char(en
->buf
, en
->firstChar
);
164 ncw
= wstrlen(en
->buf
+ en
->firstChar
, nc
- en
->firstChar
);
169 pc
= previous_char(en
->buf
, en
->firstChar
);
170 pcw
= wstrlen(en
->buf
+ pc
, en
->firstChar
- pc
);
176 pc
= previous_char(en
->buf
, en
->firstChar
);
177 pcw
= wstrlen(en
->buf
+ pc
, en
->firstChar
- pc
);
182 static void entryDraw(newtComponent co
) {
183 struct entry
* en
= co
->data
;
189 if (!co
->isMapped
) return;
191 if (en
->flags
& NEWT_FLAG_DISABLED
)
192 SLsmg_set_color(en
->csDisabled
);
194 SLsmg_set_color(en
->cs
);
196 if (en
->flags
& NEWT_FLAG_HIDDEN
) {
197 newtGotorc(co
->top
, co
->left
);
198 for (i
= 0; i
< co
->width
; i
++)
199 SLsmg_write_char('_');
200 newtGotorc(co
->top
, co
->left
);
207 /* scroll if necessary */
208 scroll(en
, co
->width
);
210 chptr
= en
->buf
+ en
->firstChar
;
212 if (en
->flags
& NEWT_FLAG_PASSWORD
) {
213 len
= wstrlen(chptr
, -1);
214 tmpptr
= alloca(len
+ 1);
215 for (i
= 0; i
< len
; i
++)
216 memset(tmpptr
, '*', len
);
221 len
= wstrlen(chptr
, -1);
223 /* workaround for double width characters */
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('_');
232 newtGotorc(co
->top
, co
->left
);
234 if (len
<= co
->width
) {
236 SLsmg_write_string(chptr
);
237 while (i
< co
->width
) {
238 SLsmg_write_char('_');
242 SLsmg_write_nstring(chptr
, co
->width
);
244 newtGotorc(co
->top
, co
->left
+ wstrlen(en
->buf
+en
->firstChar
, en
->cursorPosition
- en
->firstChar
));
247 void newtEntrySetFlags(newtComponent co
, int flags
, enum newtFlagsSense sense
) {
248 struct entry
* en
= co
->data
;
251 en
->flags
= newtSetFlags(en
->flags
, flags
, sense
);
253 if (!(en
->flags
& NEWT_FLAG_DISABLED
))
258 newtGetrc(&row
, &col
);
260 newtGotorc(row
, col
);
263 void newtEntrySetColors(newtComponent co
, int normal
, int disabled
) {
264 struct entry
* en
= co
->data
;
267 en
->csDisabled
= disabled
;
271 static void entryDestroy(newtComponent co
) {
272 struct entry
* en
= co
->data
;
279 static struct eventResult
entryEvent(newtComponent co
,
281 struct entry
* en
= co
->data
;
282 struct eventResult er
;
285 er
.result
= ER_IGNORED
;
287 if (ev
.when
== EV_NORMAL
) {
291 if (en
->flags
& NEWT_FLAG_HIDDEN
)
292 newtGotorc(co
->top
, co
->left
);
294 newtGotorc(co
->top
, co
->left
+
295 wstrlen(en
->buf
+ en
->firstChar
, en
->cursorPosition
- en
->firstChar
));
296 er
.result
= ER_SWALLOWED
;
302 er
.result
= ER_SWALLOWED
;
304 co
->callback(co
, co
->callbackData
);
310 ch
= en
->filter(co
, en
->filterData
, ch
, en
->cursorPosition
);
311 if (ch
) er
= entryHandleKey(co
, ch
);
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
;
320 co
->left
+(en
->cursorPosition
- en
->firstChar
));
322 en
->cursorPosition
= strlen(en
->buf
);
324 co
->left
+(en
->cursorPosition
- en
->firstChar
));
334 static int previous_char(const char *buf
, int pos
)
340 len
= mblen(buf
+off
, MB_CUR_MAX
);
348 static int next_char(const char *buf
, int pos
)
350 int len
= mblen(buf
+ pos
, MB_CUR_MAX
);
356 static struct eventResult
entryHandleKey(newtComponent co
, int key
) {
357 struct entry
* en
= co
->data
;
358 struct eventResult er
;
361 er
.result
= ER_SWALLOWED
;
363 case '\r': /* Return */
364 if (en
->flags
& NEWT_FLAG_RETURNEXIT
) {
366 er
.result
= ER_EXITFORM
;
368 er
.result
= ER_NEXTCOMP
;
372 case '\001': /* ^A */
374 en
->cursorPosition
= 0;
377 case '\005': /* ^E */
379 en
->cursorPosition
= en
->bufUsed
;
382 case '\013': /* ^K */
383 en
->bufUsed
= en
->cursorPosition
;
384 memset(en
->buf
+ en
->bufUsed
, 0, en
->bufAlloced
- en
->bufUsed
);
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
);
394 case '\002': /* ^B */
396 if (en
->cursorPosition
)
397 en
->cursorPosition
= previous_char(en
->buf
, en
->cursorPosition
);
401 case NEWT_KEY_DELETE
:
402 chptr
= en
->buf
+ en
->cursorPosition
;
404 int delta
= next_char(en
->buf
, en
->cursorPosition
)-en
->cursorPosition
;
408 *(chptr
- delta
) = *chptr
;
411 memset(chptr
- delta
, 0, delta
);
417 case NEWT_KEY_BKSPC
: {
418 int prev
= previous_char(en
->buf
, en
->cursorPosition
);
419 if (en
->cursorPosition
!= prev
) {
420 /* if this isn't true, there's nothing to erase */
421 int delta
= en
->cursorPosition
- prev
;
422 chptr
= en
->buf
+ en
->cursorPosition
;
424 en
->cursorPosition
-=delta
;
426 *(chptr
- delta
) = *chptr
;
429 memset(chptr
- delta
, 0, delta
);
434 case '\006': /* ^B */
436 if (en
->cursorPosition
< en
->bufUsed
)
437 en
->cursorPosition
= next_char(en
->buf
, en
->cursorPosition
);
441 if ((key
>= 0x20 && key
<= 0x7e) || (key
>= 0x80 && key
<= 0xff)) {
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 */
451 if (l
!= -2) /* not incomplete sequence */
455 if (i
== MB_CUR_MAX
|| !SLang_input_pending(1)) {
459 s
[i
] = SLang_getkey();
462 if (!i
|| (!(en
->flags
& NEWT_FLAG_SCROLL
) && wstrlen(en
->buf
, -1) + wstrlen(s
, i
) > co
->width
)) {
463 /* FIXME this is broken */
468 if ((en
->bufUsed
+ i
) >= en
->bufAlloced
) {
469 en
->bufAlloced
+= 20;
470 en
->buf
= realloc(en
->buf
, en
->bufAlloced
);
471 if (en
->resultPtr
) *en
->resultPtr
= en
->buf
;
472 memset(en
->buf
+ en
->bufAlloced
- 20, 0, 20);
475 if (en
->cursorPosition
!= en
->bufUsed
) {
476 /* insert the new character */
477 memmove(en
->buf
+ en
->cursorPosition
+ i
, en
->buf
+ en
->cursorPosition
, en
->bufUsed
- en
->cursorPosition
);
480 for (l
= 0; l
< i
; l
++)
481 en
->buf
[en
->cursorPosition
++] = s
[l
];
483 er
.result
= ER_IGNORED
;
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
);
496 char * newtEntryGetValue(newtComponent co
) {
497 struct entry
* en
= co
->data
;
502 void newtEntrySetFilter(newtComponent co
, newtEntryFilter filter
, void * data
) {
503 struct entry
* en
= co
->data
;
505 en
->filterData
= data
;
508 int newtEntryGetCursorPosition (newtComponent co
) {
509 struct entry
* en
= co
->data
;
511 return en
->cursorPosition
;
514 void newtEntrySetCursorPosition (newtComponent co
, int position
) {
515 struct entry
* en
= co
->data
;
517 en
->cursorPosition
= position
;