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