]> git.ipfire.org Git - thirdparty/newt.git/blob - entry.c
doesn't draw itself it top == -1
[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 };
17
18 static void entryDraw(newtComponent co);
19 static void entryDestroy(newtComponent co);
20 static struct eventResult entryEvent(struct newtComponent * co,
21 struct event ev);
22
23 static struct eventResult entryHandleKey(struct newtComponent * co, int key);
24
25 static struct componentOps entryOps = {
26 entryDraw,
27 entryEvent,
28 entryDestroy,
29 } ;
30
31 newtComponent newtEntry(int left, int top, char * initialValue, int width,
32 char ** resultPtr, int flags) {
33 newtComponent co;
34 struct entry * en;
35
36 co = malloc(sizeof(*co));
37 en = malloc(sizeof(struct entry));
38 co->data = en;
39
40 co->top = top;
41 co->left = left;
42 co->height = 1;
43 co->width = width;
44 co->takesFocus = 1;
45
46 co->ops = &entryOps;
47
48 en->flags = flags;
49 en->cursorPosition = 0;
50 en->firstChar = 0;
51 en->bufUsed = 0;
52 en->bufAlloced = width + 1;
53
54 if (initialValue && strlen(initialValue) > width) {
55 en->bufAlloced = strlen(initialValue) + 1;
56 }
57 en->buf = malloc(en->bufAlloced);
58 *resultPtr = en->buf;
59 en->resultPtr = resultPtr;
60
61 memset(en->buf, 0, en->bufAlloced);
62 if (initialValue) {
63 strcpy(en->buf, initialValue);
64 en->bufUsed = strlen(initialValue);
65 }
66
67 return co;
68 }
69
70 static void entryDraw(newtComponent co) {
71 struct entry * en = co->data;
72 int i;
73 char * chptr;
74 int len;
75
76 if (co->top == -1) return;
77
78 if (en->flags & NEWT_ENTRY_HIDDEN) {
79 newtGotorc(co->top, co->left);
80 SLsmg_set_color(COLORSET_ENTRY);
81 for (i = 0; i < co->width; i++)
82 SLsmg_write_char('_');
83 newtGotorc(co->top, co->left);
84
85 return;
86 }
87
88 newtGotorc(co->top, co->left);
89 SLsmg_set_color(COLORSET_ENTRY);
90
91 if (en->cursorPosition < en->firstChar) {
92 /* scroll to the left */
93 en->firstChar = en->cursorPosition;
94 } else if ((en->firstChar + co->width) <= en->cursorPosition) {
95 /* scroll to the right */
96 en->firstChar = en->cursorPosition - co->width + 1;
97 }
98
99 chptr = en->buf + en->firstChar;
100 len = strlen(chptr);
101
102 if (len <= co->width) {
103 i = len;
104 SLsmg_write_string(chptr);
105 while (i < co->width) {
106 SLsmg_write_char('_');
107 i++;
108 }
109 } else {
110 SLsmg_write_nstring(chptr, co->width);
111 }
112
113 newtGotorc(co->top, co->left + (en->cursorPosition - en->firstChar));
114 }
115
116 static void entryDestroy(newtComponent co) {
117 struct entry * en = co->data;
118
119 free(en->buf);
120 free(en);
121 free(co);
122 }
123
124 static struct eventResult entryEvent(struct newtComponent * co,
125 struct event ev) {
126 struct entry * en = co->data;
127 struct eventResult er;
128
129 switch (ev.event) {
130 case EV_FOCUS:
131 /*SLtt_set_cursor_visibility(0);*/
132 newtGotorc(co->top, co->left + (en->cursorPosition - en->firstChar));
133 er.result = ER_SWALLOWED;
134 break;
135
136 case EV_UNFOCUS:
137 /*SLtt_set_cursor_visibility(1);*/
138 newtGotorc(0, 0);
139 er.result = ER_SWALLOWED;
140 break;
141
142 case EV_KEYPRESS:
143 er = entryHandleKey(co, ev.u.key);
144 break;
145 }
146
147 return er;
148 }
149
150 static struct eventResult entryHandleKey(struct newtComponent * co, int key) {
151 struct entry * en = co->data;
152 struct eventResult er;
153 char * chptr, * insPoint;
154
155 er.result = ER_SWALLOWED;
156 switch (key) {
157 case '\001': /* ^A */
158 case NEWT_KEY_HOME:
159 en->cursorPosition = 0;
160 break;
161
162 case '\005': /* ^E */
163 case NEWT_KEY_END:
164 en->cursorPosition = en->bufUsed;
165 break;
166
167 case '\013': /* ^K */
168 en->bufUsed = en->cursorPosition;
169 memset(en->buf + en->bufUsed, 0, en->bufAlloced - en->bufUsed);
170 break;
171
172 case '\002': /* ^B */
173 case NEWT_KEY_LEFT:
174 if (en->cursorPosition)
175 en->cursorPosition--;
176 break;
177
178 case '\004':
179 case NEWT_KEY_DELETE:
180 chptr = en->buf + en->cursorPosition;
181 if (*chptr) {
182 chptr++;
183 while (*chptr) {
184 *(chptr - 1) = *chptr;
185 chptr++;
186 }
187 *(chptr - 1) = '\0';
188 en->bufUsed--;
189 }
190 break;
191
192 case NEWT_KEY_BKSPC:
193 if (en->cursorPosition) {
194 /* if this isn't true, there's nothing to erase */
195 chptr = en->buf + en->cursorPosition;
196 en->bufUsed--;
197 en->cursorPosition--;
198 while (*chptr) {
199 *(chptr - 1) = *chptr;
200 chptr++;
201 }
202 *(chptr - 1) = '\0';
203 }
204 break;
205
206 case '\006': /* ^B */
207 case NEWT_KEY_RIGHT:
208 if (en->cursorPosition < en->bufUsed)
209 en->cursorPosition++;
210 break;
211
212 default:
213 if ((key >= 0x20 && key <= 0x7e) || (key >= 0xa0 && key <= 0xff)) {
214 if (!(en->flags & NEWT_ENTRY_SCROLL) && en->bufUsed == co->width) {
215 SLtt_beep();
216 break;
217 }
218
219 if ((en->bufUsed + 1) == en->bufAlloced) {
220 en->bufAlloced += 20;
221 en->buf = realloc(en->buf, en->bufAlloced);
222 *en->resultPtr = en->buf;
223 memset(en->buf + en->bufUsed + 1, 0, 20);
224 }
225
226 if (en->cursorPosition == en->bufUsed) {
227 en->bufUsed++;
228 } else {
229 /* insert the new character */
230
231 /* chptr is the last character in the string */
232 chptr = (en->buf + en->bufUsed) - 1;
233 if ((en->bufUsed + 1) == en->bufAlloced) {
234 /* this string fills the buffer, so clip it */
235 chptr--;
236 } else
237 en->bufUsed++;
238
239 insPoint = en->buf + en->cursorPosition;
240
241 while (chptr >= insPoint) {
242 *(chptr + 1) = *chptr;
243 chptr--;
244 }
245
246 }
247
248 en->buf[en->cursorPosition++] = key;
249 } else {
250 er.result = ER_IGNORED;
251 }
252 }
253
254 entryDraw(co);
255
256 return er;
257 }