]> git.ipfire.org Git - thirdparty/newt.git/blob - entry.c
removed newtEntryAddCallback(), changed callback logic to use component
[thirdparty/newt.git] / entry.c
1 #include <ctype.h>
2 #include <slang/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(struct newtComponent * co,
22 struct event ev);
23
24 static struct eventResult entryHandleKey(struct newtComponent * co, int key);
25
26 static struct componentOps entryOps = {
27 entryDraw,
28 entryEvent,
29 entryDestroy,
30 } ;
31
32 void newtEntrySet(newtComponent co, char * value, int cursorAtEnd) {
33 struct entry * en = co->data;
34
35 if ((strlen(value) + 1) > en->bufAlloced) {
36 free(en->buf);
37 en->bufAlloced = strlen(value) + 1;
38 en->buf = malloc(en->bufAlloced);
39 *en->resultPtr = en->buf;
40 }
41 memset(en->buf, 0, en->bufAlloced); /* clear the buffer */
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 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 (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 static void entryDraw(newtComponent co) {
95 struct entry * en = co->data;
96 int i;
97 char * chptr;
98 int len;
99
100 if (co->top == -1) return;
101
102 if (en->flags & NEWT_ENTRY_HIDDEN) {
103 newtGotorc(co->top, co->left);
104 SLsmg_set_color(COLORSET_ENTRY);
105 for (i = 0; i < co->width; i++)
106 SLsmg_write_char('_');
107 newtGotorc(co->top, co->left);
108
109 return;
110 }
111
112 newtGotorc(co->top, co->left);
113 SLsmg_set_color(COLORSET_ENTRY);
114
115 if (en->cursorPosition < en->firstChar) {
116 /* scroll to the left */
117 en->firstChar = en->cursorPosition;
118 } else if ((en->firstChar + co->width) <= en->cursorPosition) {
119 /* scroll to the right */
120 en->firstChar = en->cursorPosition - co->width + 1;
121 }
122
123 chptr = en->buf + en->firstChar;
124 len = strlen(chptr);
125
126 if (len <= co->width) {
127 i = len;
128 SLsmg_write_string(chptr);
129 while (i < co->width) {
130 SLsmg_write_char('_');
131 i++;
132 }
133 } else {
134 SLsmg_write_nstring(chptr, co->width);
135 }
136
137 if (en->flags & NEWT_ENTRY_HIDDEN)
138 newtGotorc(co->top, co->left);
139 else
140 newtGotorc(co->top, co->left + (en->cursorPosition - en->firstChar));
141 }
142
143 static void entryDestroy(newtComponent co) {
144 struct entry * en = co->data;
145
146 free(en->buf);
147 free(en);
148 free(co);
149 }
150
151 static struct eventResult entryEvent(struct newtComponent * co,
152 struct event ev) {
153 struct entry * en = co->data;
154 struct eventResult er;
155
156 if (ev.when == EV_NORMAL) {
157 switch (ev.event) {
158 case EV_FOCUS:
159 /*SLtt_set_cursor_visibility(0);*/
160 if (en->flags & NEWT_ENTRY_HIDDEN)
161 newtGotorc(co->top, co->left);
162 else
163 newtGotorc(co->top, co->left +
164 (en->cursorPosition - en->firstChar));
165 er.result = ER_SWALLOWED;
166 break;
167
168 case EV_UNFOCUS:
169 /*SLtt_set_cursor_visibility(1);*/
170 newtGotorc(0, 0);
171 er.result = ER_SWALLOWED;
172 if (co->callback) co->callback(co, co->callbackData);
173 break;
174
175 case EV_KEYPRESS:
176 er = entryHandleKey(co, ev.u.key);
177 break;
178 }
179 } else
180 er.result = ER_IGNORED;
181
182 return er;
183 }
184
185 static struct eventResult entryHandleKey(struct newtComponent * co, int key) {
186 struct entry * en = co->data;
187 struct eventResult er;
188 char * chptr, * insPoint;
189
190 er.result = ER_SWALLOWED;
191 switch (key) {
192 case '\r': /* Return */
193 if (en->flags & NEWT_ENTRY_RETURNEXIT) {
194 er.result = ER_EXITFORM;
195 } else {
196 er.result = ER_NEXTCOMP;
197 }
198 break;
199
200 case '\001': /* ^A */
201 case NEWT_KEY_HOME:
202 en->cursorPosition = 0;
203 break;
204
205 case '\005': /* ^E */
206 case NEWT_KEY_END:
207 en->cursorPosition = en->bufUsed;
208 break;
209
210 case '\013': /* ^K */
211 en->bufUsed = en->cursorPosition;
212 memset(en->buf + en->bufUsed, 0, en->bufAlloced - en->bufUsed);
213 break;
214
215 case '\002': /* ^B */
216 case NEWT_KEY_LEFT:
217 if (en->cursorPosition)
218 en->cursorPosition--;
219 break;
220
221 case '\004':
222 case NEWT_KEY_DELETE:
223 chptr = en->buf + en->cursorPosition;
224 if (*chptr) {
225 chptr++;
226 while (*chptr) {
227 *(chptr - 1) = *chptr;
228 chptr++;
229 }
230 *(chptr - 1) = '\0';
231 en->bufUsed--;
232 }
233 break;
234
235 case NEWT_KEY_BKSPC:
236 if (en->cursorPosition) {
237 /* if this isn't true, there's nothing to erase */
238 chptr = en->buf + en->cursorPosition;
239 en->bufUsed--;
240 en->cursorPosition--;
241 while (*chptr) {
242 *(chptr - 1) = *chptr;
243 chptr++;
244 }
245 *(chptr - 1) = '\0';
246 }
247 break;
248
249 case '\006': /* ^B */
250 case NEWT_KEY_RIGHT:
251 if (en->cursorPosition < en->bufUsed)
252 en->cursorPosition++;
253 break;
254
255 default:
256 if ((key >= 0x20 && key <= 0x7e) || (key >= 0xa0 && key <= 0xff)) {
257 if (!(en->flags & NEWT_ENTRY_SCROLL) && en->bufUsed == co->width) {
258 SLtt_beep();
259 break;
260 }
261
262 if ((en->bufUsed + 1) == en->bufAlloced) {
263 en->bufAlloced += 20;
264 en->buf = realloc(en->buf, en->bufAlloced);
265 *en->resultPtr = en->buf;
266 memset(en->buf + en->bufUsed + 1, 0, 20);
267 }
268
269 if (en->cursorPosition == en->bufUsed) {
270 en->bufUsed++;
271 } else {
272 /* insert the new character */
273
274 /* chptr is the last character in the string */
275 chptr = (en->buf + en->bufUsed) - 1;
276 if ((en->bufUsed + 1) == en->bufAlloced) {
277 /* this string fills the buffer, so clip it */
278 chptr--;
279 } else
280 en->bufUsed++;
281
282 insPoint = en->buf + en->cursorPosition;
283
284 while (chptr >= insPoint) {
285 *(chptr + 1) = *chptr;
286 chptr--;
287 }
288
289 }
290
291 en->buf[en->cursorPosition++] = key;
292 } else {
293 er.result = ER_IGNORED;
294 }
295 }
296
297 entryDraw(co);
298
299 return er;
300 }