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