]> git.ipfire.org Git - thirdparty/newt.git/blob - entry.c
expand(1) the source to get rid of tab/space mixed indents
[thirdparty/newt.git] / entry.c
1 #include "config.h"
2
3 #ifdef HAVE_ALLOCA_H
4 #include <alloca.h>
5 #endif
6
7 #include <ctype.h>
8 #include <slang.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12 #include "newt.h"
13 #include "newt_pr.h"
14
15 struct entry {
16 int flags;
17 char * buf;
18 const char ** resultPtr;
19 int bufAlloced;
20 int bufUsed; /* amount of the buffer that's been used */
21 int cursorPosition; /* cursor *in the string* on on screen */
22 int firstChar; /* first character position being shown */
23 newtEntryFilter filter;
24 void * filterData;
25 };
26
27 static void entryDraw(newtComponent co);
28 static void entryDestroy(newtComponent co);
29 static struct eventResult entryEvent(newtComponent co,
30 struct event ev);
31
32 static struct eventResult entryHandleKey(newtComponent co, int key);
33
34 static struct componentOps entryOps = {
35 entryDraw,
36 entryEvent,
37 entryDestroy,
38 newtDefaultPlaceHandler,
39 newtDefaultMappedHandler,
40 } ;
41
42 void newtEntrySet(newtComponent co, const char * value, int cursorAtEnd) {
43 struct entry * en = co->data;
44
45 if ((strlen(value) + 1) > (unsigned int)en->bufAlloced) {
46 free(en->buf);
47 en->bufAlloced = strlen(value) + 1;
48 en->buf = malloc(en->bufAlloced);
49 if (en->resultPtr) *en->resultPtr = en->buf;
50 }
51 memset(en->buf, 0, en->bufAlloced); /* clear the buffer */
52 strcpy(en->buf, value);
53 en->bufUsed = strlen(value);
54 en->firstChar = 0;
55 if (cursorAtEnd)
56 en->cursorPosition = en->bufUsed;
57 else
58 en->cursorPosition = 0;
59
60 entryDraw(co);
61 } ;
62
63 newtComponent newtEntry(int left, int top, const char * initialValue, int width,
64 const char ** resultPtr, int flags) {
65 newtComponent co;
66 struct entry * en;
67
68 co = malloc(sizeof(*co));
69 en = malloc(sizeof(struct entry));
70 co->data = en;
71
72 co->top = top;
73 co->left = left;
74 co->height = 1;
75 co->width = width;
76 co->isMapped = 0;
77 co->callback = NULL;
78
79 co->ops = &entryOps;
80
81 en->flags = flags;
82 en->cursorPosition = 0;
83 en->firstChar = 0;
84 en->bufUsed = 0;
85 en->bufAlloced = width + 1;
86 en->filter = NULL;
87
88 if (!(en->flags & NEWT_FLAG_DISABLED))
89 co->takesFocus = 1;
90 else
91 co->takesFocus = 0;
92
93 if (initialValue && wstrlen(initialValue,-1) > (unsigned int)width) {
94 en->bufAlloced = wstrlen(initialValue,-1) + 1;
95 }
96 en->buf = malloc(en->bufAlloced);
97 en->resultPtr = resultPtr;
98 if (en->resultPtr) *en->resultPtr = en->buf;
99
100 memset(en->buf, 0, en->bufAlloced);
101 if (initialValue) {
102 strcpy(en->buf, initialValue);
103 en->bufUsed = strlen(initialValue);
104 en->cursorPosition = en->bufUsed;
105 } else {
106 *en->buf = '\0';
107 en->bufUsed = 0;
108 en->cursorPosition = 0;
109 }
110
111 return co;
112 }
113
114 static void entryDraw(newtComponent co) {
115 struct entry * en = co->data;
116 int i;
117 char * chptr;
118 int len;
119
120 if (!co->isMapped) return;
121
122 if (en->flags & NEWT_FLAG_DISABLED)
123 SLsmg_set_color(NEWT_COLORSET_DISENTRY);
124 else
125 SLsmg_set_color(NEWT_COLORSET_ENTRY);
126
127 if (en->flags & NEWT_FLAG_HIDDEN) {
128 newtGotorc(co->top, co->left);
129 for (i = 0; i < co->width; i++)
130 SLsmg_write_char('_');
131 newtGotorc(co->top, co->left);
132
133 return;
134 }
135
136 newtGotorc(co->top, co->left);
137
138 if (en->cursorPosition < en->firstChar) {
139 /* scroll to the left */
140 en->firstChar = en->cursorPosition;
141 } else if ((en->firstChar + co->width) <= en->cursorPosition) {
142 /* scroll to the right */
143 en->firstChar = en->cursorPosition - co->width + 1;
144 }
145
146 chptr = en->buf + en->firstChar;
147
148 if (en->flags & NEWT_FLAG_PASSWORD) {
149 char *tmpptr, *p;
150
151 tmpptr = alloca(strlen(chptr)+2);
152 strcpy(tmpptr, chptr);
153 for (p = tmpptr; *p; p++)
154 *p = '*';
155 chptr = tmpptr;
156 }
157
158 len = wstrlen(chptr, -1);
159
160 if (len <= co->width) {
161 i = len;
162 SLsmg_write_string(chptr);
163 while (i < co->width) {
164 SLsmg_write_char('_');
165 i++;
166 }
167 } else {
168 SLsmg_write_nstring(chptr, co->width);
169 }
170
171 if (en->flags & NEWT_FLAG_HIDDEN)
172 newtGotorc(co->top, co->left);
173 else
174 newtGotorc(co->top, co->left + (en->cursorPosition - en->firstChar));
175 }
176
177 void newtEntrySetFlags(newtComponent co, int flags, enum newtFlagsSense sense) {
178 struct entry * en = co->data;
179 int row, col;
180
181 en->flags = newtSetFlags(en->flags, flags, sense);
182
183 if (!(en->flags & NEWT_FLAG_DISABLED))
184 co->takesFocus = 1;
185 else
186 co->takesFocus = 0;
187
188 newtGetrc(&row, &col);
189 entryDraw(co);
190 newtGotorc(row, col);
191 }
192
193 static void entryDestroy(newtComponent co) {
194 struct entry * en = co->data;
195
196 free(en->buf);
197 free(en);
198 free(co);
199 }
200
201 static struct eventResult entryEvent(newtComponent co,
202 struct event ev) {
203 struct entry * en = co->data;
204 struct eventResult er;
205 int ch;
206
207 if (ev.when == EV_NORMAL) {
208 switch (ev.event) {
209 case EV_FOCUS:
210 newtCursorOn();
211 if (en->flags & NEWT_FLAG_HIDDEN)
212 newtGotorc(co->top, co->left);
213 else
214 newtGotorc(co->top, co->left +
215 (en->cursorPosition - en->firstChar));
216 er.result = ER_SWALLOWED;
217 break;
218
219 case EV_UNFOCUS:
220 newtCursorOff();
221 newtGotorc(0, 0);
222 er.result = ER_SWALLOWED;
223 if (co->callback)
224 co->callback(co, co->callbackData);
225 break;
226
227 case EV_KEYPRESS:
228 ch = ev.u.key;
229 if (en->filter)
230 ch = en->filter(co, en->filterData, ch, en->cursorPosition);
231 if (ch) er = entryHandleKey(co, ch);
232 break;
233
234 case EV_MOUSE:
235 if ((ev.u.mouse.type == MOUSE_BUTTON_DOWN) &&
236 (en->flags ^ NEWT_FLAG_HIDDEN)) {
237 if (strlen(en->buf) >= ev.u.mouse.x - co->left) {
238 en->cursorPosition = ev.u.mouse.x - co->left;
239 newtGotorc(co->top,
240 co->left +(en->cursorPosition - en->firstChar));
241 } else {
242 en->cursorPosition = strlen(en->buf);
243 newtGotorc(co->top,
244 co->left +(en->cursorPosition - en->firstChar));
245 }
246 }
247 break;
248 }
249 } else
250 er.result = ER_IGNORED;
251
252 return er;
253 }
254
255 static struct eventResult entryHandleKey(newtComponent co, int key) {
256 struct entry * en = co->data;
257 struct eventResult er;
258 char * chptr, * insPoint;
259
260 er.result = ER_SWALLOWED;
261 switch (key) {
262 case '\r': /* Return */
263 if (en->flags & NEWT_FLAG_RETURNEXIT) {
264 er.result = ER_EXITFORM;
265 } else {
266 er.result = ER_NEXTCOMP;
267 }
268 break;
269
270 case '\001': /* ^A */
271 case NEWT_KEY_HOME:
272 en->cursorPosition = 0;
273 break;
274
275 case '\005': /* ^E */
276 case NEWT_KEY_END:
277 en->cursorPosition = en->bufUsed;
278 break;
279
280 case '\013': /* ^K */
281 en->bufUsed = en->cursorPosition;
282 memset(en->buf + en->bufUsed, 0, en->bufAlloced - en->bufUsed);
283 break;
284
285 case '\002': /* ^B */
286 case NEWT_KEY_LEFT:
287 if (en->cursorPosition)
288 en->cursorPosition--;
289 break;
290
291 case '\004':
292 case NEWT_KEY_DELETE:
293 chptr = en->buf + en->cursorPosition;
294 if (*chptr) {
295 chptr++;
296 while (*chptr) {
297 *(chptr - 1) = *chptr;
298 chptr++;
299 }
300 *(chptr - 1) = '\0';
301 en->bufUsed--;
302 }
303 break;
304
305 case NEWT_KEY_BKSPC:
306 if (en->cursorPosition) {
307 /* if this isn't true, there's nothing to erase */
308 chptr = en->buf + en->cursorPosition;
309 en->bufUsed--;
310 en->cursorPosition--;
311 while (*chptr) {
312 *(chptr - 1) = *chptr;
313 chptr++;
314 }
315 *(chptr - 1) = '\0';
316 }
317 break;
318
319 case '\006': /* ^B */
320 case NEWT_KEY_RIGHT:
321 if (en->cursorPosition < en->bufUsed)
322 en->cursorPosition++;
323 break;
324
325 default:
326 if ((key >= 0x20 && key <= 0x7e) || (key >= 0xa0 && key <= 0xff)) {
327 if (!(en->flags & NEWT_FLAG_SCROLL) && en->bufUsed >= co->width) {
328 SLtt_beep();
329 break;
330 }
331
332 if ((en->bufUsed + 1) == en->bufAlloced) {
333 en->bufAlloced += 20;
334 en->buf = realloc(en->buf, en->bufAlloced);
335 if (en->resultPtr) *en->resultPtr = en->buf;
336 memset(en->buf + en->bufUsed + 1, 0, 20);
337 }
338
339 if (en->cursorPosition == en->bufUsed) {
340 en->bufUsed++;
341 } else {
342 /* insert the new character */
343
344 /* chptr is the last character in the string */
345 chptr = (en->buf + en->bufUsed) - 1;
346 if ((en->bufUsed + 1) == en->bufAlloced) {
347 /* this string fills the buffer, so clip it */
348 chptr--;
349 } else
350 en->bufUsed++;
351
352 insPoint = en->buf + en->cursorPosition;
353
354 while (chptr >= insPoint) {
355 *(chptr + 1) = *chptr;
356 chptr--;
357 }
358
359 }
360
361 en->buf[en->cursorPosition++] = key;
362 } else {
363 er.result = ER_IGNORED;
364 }
365 }
366
367 entryDraw(co);
368
369 return er;
370 }
371
372 char * newtEntryGetValue(newtComponent co) {
373 struct entry * en = co->data;
374
375 return en->buf;
376 }
377
378 void newtEntrySetFilter(newtComponent co, newtEntryFilter filter, void * data) {
379 struct entry * en = co->data;
380 en->filter = filter;
381 en->filterData = data;
382 }