]>
Commit | Line | Data |
---|---|---|
0b38669d | 1 | /* This goofed-up box whacked into shape by Elliot Lee <sopwith@cuc.edu> |
2 | (from the original listbox by Erik Troan <ewt@redhat.com>) | |
3 | and contributed to newt for use under the LGPL license. | |
ad792351 | 4 | Copyright (C) 1996, 1997 Elliot Lee */ |
a61e44cc | 5 | |
139f06bc | 6 | #include <slang.h> |
4a93351d | 7 | #include <stdio.h> |
962b92a5 | 8 | #include <stdlib.h> |
9 | #include <string.h> | |
d63d1c70 | 10 | #include <ctype.h> |
962b92a5 | 11 | |
12 | #include "newt.h" | |
13 | #include "newt_pr.h" | |
14 | ||
a61e44cc | 15 | |
16 | /* Linked list of items in the listbox */ | |
17 | struct items { | |
a507b3ec | 18 | char * text; |
d4109c37 | 19 | const void *data; |
2dbc072e | 20 | unsigned char isSelected; |
a61e44cc | 21 | struct items *next; |
22 | }; | |
23 | ||
24 | /* Holds all the relevant information for this listbox */ | |
962b92a5 | 25 | struct listbox { |
e948278c | 26 | newtComponent sb; /* Scrollbar on right side of listbox */ |
913d0524 | 27 | int curWidth; /* size of text w/o scrollbar or border*/ |
28 | int curHeight; /* size of text w/o border */ | |
e948278c | 29 | int sbAdjust; |
913d0524 | 30 | int bdxAdjust, bdyAdjust; |
45f6c4fd | 31 | int numItems, numSelected; |
babcb349 | 32 | int userHasSetWidth; |
a61e44cc | 33 | int currItem, startShowItem; /* startShowItem is the first item displayed |
34 | on the screen */ | |
35 | int isActive; /* If we handle key events all the time, it seems | |
36 | to do things even when they are supposed to be for | |
37 | another button/whatever */ | |
38 | struct items *boxItems; | |
0bf47501 | 39 | int grow; |
a61e44cc | 40 | int flags; /* flags for this listbox, right now just |
4a93351d | 41 | NEWT_FLAG_RETURNEXIT */ |
962b92a5 | 42 | }; |
43 | ||
44 | static void listboxDraw(newtComponent co); | |
45 | static void listboxDestroy(newtComponent co); | |
46 | static struct eventResult listboxEvent(newtComponent co, struct event ev); | |
4e9c4bb9 | 47 | static void newtListboxRealSetCurrent(newtComponent co); |
8f52cd47 | 48 | static void listboxPlace(newtComponent co, int newLeft, int newTop); |
45f6c4fd | 49 | static inline void updateWidth(newtComponent co, struct listbox * li, |
913d0524 | 50 | int maxField); |
8f52cd47 | 51 | static void listboxMapped(newtComponent co, int isMapped); |
962b92a5 | 52 | |
53 | static struct componentOps listboxOps = { | |
54 | listboxDraw, | |
55 | listboxEvent, | |
56 | listboxDestroy, | |
e948278c | 57 | listboxPlace, |
8f52cd47 | 58 | listboxMapped, |
a61e44cc | 59 | }; |
962b92a5 | 60 | |
8f52cd47 | 61 | static void listboxMapped(newtComponent co, int isMapped) { |
e948278c | 62 | struct listbox * li = co->data; |
63 | ||
8f52cd47 | 64 | co->isMapped = isMapped; |
65 | if (li->sb) | |
66 | li->sb->ops->mapped(li->sb, isMapped); | |
67 | } | |
68 | ||
69 | static void listboxPlace(newtComponent co, int newLeft, int newTop) { | |
70 | struct listbox * li = co->data; | |
71 | ||
72 | co->top = newTop; | |
73 | co->left = newLeft; | |
74 | ||
75 | if (li->sb) | |
45f6c4fd | 76 | li->sb->ops->place(li->sb, co->left + co->width - li->bdxAdjust - 1, |
aa564c1d | 77 | co->top); |
e948278c | 78 | } |
79 | ||
962b92a5 | 80 | newtComponent newtListbox(int left, int top, int height, int flags) { |
b9523497 | 81 | newtComponent co, sb; |
962b92a5 | 82 | struct listbox * li; |
83 | ||
a61e44cc | 84 | if (!(co = malloc(sizeof(*co)))) |
85 | return NULL; | |
962b92a5 | 86 | |
a61e44cc | 87 | if (!(li = malloc(sizeof(struct listbox)))) { |
88 | free(co); | |
89 | return NULL; | |
90 | } | |
91 | ||
92 | li->boxItems = NULL; | |
93 | li->numItems = 0; | |
94 | li->currItem = 0; | |
2dbc072e | 95 | li->numSelected = 0; |
a61e44cc | 96 | li->isActive = 0; |
babcb349 | 97 | li->userHasSetWidth = 0; |
a61e44cc | 98 | li->startShowItem = 0; |
dc3ac6cf | 99 | li->sbAdjust = 0; |
913d0524 | 100 | li->bdxAdjust = 0; |
101 | li->bdyAdjust = 0; | |
45f6c4fd | 102 | li->flags = flags & (NEWT_FLAG_RETURNEXIT | NEWT_FLAG_BORDER | |
913d0524 | 103 | NEWT_FLAG_MULTIPLE); |
104 | ||
dd2f0e88 | 105 | if (li->flags & NEWT_FLAG_BORDER) { |
913d0524 | 106 | li->bdxAdjust = 2; |
107 | li->bdyAdjust = 1; | |
108 | } | |
962b92a5 | 109 | |
aa564c1d | 110 | co->height = height; |
111 | li->curHeight = co->height - (2 * li->bdyAdjust); | |
112 | ||
0bf47501 | 113 | if (height) { |
114 | li->grow = 0; | |
dd2f0e88 | 115 | if (flags & NEWT_FLAG_SCROLL) { |
45f6c4fd | 116 | sb = newtVerticalScrollbar(left, top + li->bdyAdjust, |
117 | li->curHeight, | |
aa564c1d | 118 | COLORSET_LISTBOX, COLORSET_ACTLISTBOX); |
e948278c | 119 | li->sbAdjust = 3; |
dd2f0e88 | 120 | } else { |
121 | sb = NULL; | |
e948278c | 122 | } |
0bf47501 | 123 | } else { |
124 | li->grow = 1; | |
b9523497 | 125 | sb = NULL; |
0bf47501 | 126 | } |
962b92a5 | 127 | |
a61e44cc | 128 | li->sb = sb; |
962b92a5 | 129 | co->data = li; |
913d0524 | 130 | co->isMapped = 0; |
962b92a5 | 131 | co->left = left; |
132 | co->top = top; | |
962b92a5 | 133 | co->ops = &listboxOps; |
134 | co->takesFocus = 1; | |
f37450e9 | 135 | co->callback = NULL; |
962b92a5 | 136 | |
913d0524 | 137 | updateWidth(co, li, 5); |
913d0524 | 138 | |
962b92a5 | 139 | return co; |
140 | } | |
141 | ||
45f6c4fd | 142 | static inline void updateWidth(newtComponent co, struct listbox * li, |
913d0524 | 143 | int maxField) { |
144 | li->curWidth = maxField; | |
145 | co->width = li->curWidth + li->sbAdjust + 2 * li->bdxAdjust; | |
146 | ||
147 | if (li->sb) | |
aa564c1d | 148 | li->sb->left = co->left + co->width - li->bdxAdjust - 1; |
913d0524 | 149 | } |
150 | ||
d5878365 | 151 | void newtListboxSetCurrentByKey(newtComponent co, void * key) { |
152 | struct listbox * li = co->data; | |
153 | struct items * item; | |
154 | int i; | |
155 | ||
156 | item = li->boxItems, i = 0; | |
157 | while (item && item->data != key) | |
158 | item = item->next, i++; | |
159 | ||
160 | if (item) | |
161 | newtListboxSetCurrent(co, i); | |
162 | } | |
163 | ||
4e9c4bb9 | 164 | void newtListboxSetCurrent(newtComponent co, int num) |
165 | { | |
7ea3dccd | 166 | struct listbox * li = co->data; |
d5878365 | 167 | |
a61e44cc | 168 | if (num >= li->numItems) |
169 | li->currItem = li->numItems - 1; | |
170 | else if (num < 0) | |
171 | li->currItem = 0; | |
172 | else | |
173 | li->currItem = num; | |
174 | ||
175 | if (li->currItem < li->startShowItem) | |
176 | li->startShowItem = li->currItem; | |
177 | else if (li->currItem - li->startShowItem > co->height - 1) | |
178 | li->startShowItem = li->currItem - co->height + 1; | |
179 | if (li->startShowItem + co->height > li->numItems) | |
180 | li->startShowItem = li->numItems - co->height; | |
3a779f2f | 181 | if(li->startShowItem < 0) |
182 | li->startShowItem = 0; | |
d5878365 | 183 | |
4e9c4bb9 | 184 | newtListboxRealSetCurrent(co); |
185 | } | |
186 | ||
d5878365 | 187 | static void newtListboxRealSetCurrent(newtComponent co) |
4e9c4bb9 | 188 | { |
189 | struct listbox * li = co->data; | |
d5878365 | 190 | |
0bf47501 | 191 | if(li->sb) |
192 | newtScrollbarSet(li->sb, li->currItem + 1, li->numItems); | |
913d0524 | 193 | listboxDraw(co); |
f37450e9 | 194 | if(co->callback) co->callback(co, co->callbackData); |
7ea3dccd | 195 | } |
196 | ||
913d0524 | 197 | void newtListboxSetWidth(newtComponent co, int width) { |
babcb349 | 198 | struct listbox * li = co->data; |
45f6c4fd | 199 | |
e948278c | 200 | co->width = width; |
913d0524 | 201 | li->curWidth = co->width - li->sbAdjust - 2 * li->bdxAdjust; |
babcb349 | 202 | li->userHasSetWidth = 1; |
6e25d997 | 203 | if (li->sb) li->sb->left = co->width + co->left - 1; |
913d0524 | 204 | listboxDraw(co); |
babcb349 | 205 | } |
206 | ||
2287215a | 207 | void * newtListboxGetCurrent(newtComponent co) { |
208 | struct listbox * li = co->data; | |
2287215a | 209 | int i; |
a61e44cc | 210 | struct items *item; |
2287215a | 211 | |
a61e44cc | 212 | for(i = 0, item = li->boxItems; item != NULL && i < li->currItem; |
213 | i++, item = item->next); | |
2287215a | 214 | |
a61e44cc | 215 | if (item) |
d4109c37 | 216 | return (void *)item->data; |
2287215a | 217 | else |
218 | return NULL; | |
219 | } | |
220 | ||
dd2f0e88 | 221 | void newtListboxSelectItem(newtComponent co, const void * key, |
69bf2308 | 222 | enum newtFlagsSense sense) |
46263d9e | 223 | { |
224 | struct listbox * li = co->data; | |
225 | int i; | |
dd2f0e88 | 226 | struct items * item; |
45f6c4fd | 227 | |
dd2f0e88 | 228 | item = li->boxItems, i = 0; |
229 | while (item && item->data != key) | |
230 | item = item->next, i++; | |
231 | ||
232 | if (!item) return; | |
233 | ||
234 | if (item->isSelected) | |
235 | li->numSelected--; | |
236 | ||
237 | switch(sense) { | |
238 | case NEWT_FLAGS_RESET: | |
239 | item->isSelected = 0; break; | |
240 | case NEWT_FLAGS_SET: | |
241 | item->isSelected = 1; break; | |
242 | case NEWT_FLAGS_TOGGLE: | |
243 | item->isSelected = !item->isSelected; | |
46263d9e | 244 | } |
dd2f0e88 | 245 | |
246 | if (item->isSelected) | |
247 | li->numSelected++; | |
248 | ||
913d0524 | 249 | listboxDraw(co); |
46263d9e | 250 | } |
251 | ||
252 | void newtListboxClearSelection(newtComponent co) | |
253 | { | |
254 | struct items *item; | |
255 | struct listbox * li = co->data; | |
256 | ||
257 | for(item = li->boxItems; item != NULL; | |
258 | item = item->next) | |
259 | item->isSelected = 0; | |
69bf2308 | 260 | li->numSelected = 0; |
913d0524 | 261 | listboxDraw(co); |
46263d9e | 262 | } |
263 | ||
2dbc072e | 264 | /* Free the returned array after use, but NOT the values in the array */ |
cb586ef6 | 265 | void ** newtListboxGetSelection(newtComponent co, int *numitems) |
2dbc072e | 266 | { |
267 | struct listbox * li; | |
268 | int i; | |
269 | void **retval; | |
270 | struct items *item; | |
271 | ||
cb586ef6 | 272 | if(!co || !numitems) return NULL; |
2dbc072e | 273 | |
274 | li = co->data; | |
275 | if(!li || !li->numSelected) return NULL; | |
276 | ||
cb586ef6 | 277 | retval = malloc(li->numSelected * sizeof(void *)); |
2dbc072e | 278 | for(i = 0, item = li->boxItems; item != NULL; |
279 | item = item->next) | |
280 | if(item->isSelected) | |
d4109c37 | 281 | retval[i++] = (void *)item->data; |
cb586ef6 | 282 | *numitems = li->numSelected; |
2dbc072e | 283 | return retval; |
284 | } | |
285 | ||
dd2f0e88 | 286 | void newtListboxSetEntry(newtComponent co, int num, const char * text) { |
a61e44cc | 287 | struct listbox * li = co->data; |
288 | int i; | |
289 | struct items *item; | |
290 | ||
291 | for(i = 0, item = li->boxItems; item != NULL && i < num; | |
292 | i++, item = item->next); | |
293 | ||
294 | if(!item) | |
295 | return; | |
3a779f2f | 296 | else { |
a507b3ec | 297 | free(item->text); |
298 | item->text = strdup(text); | |
3a779f2f | 299 | } |
913d0524 | 300 | if (li->userHasSetWidth == 0 && strlen(text) > li->curWidth) { |
301 | updateWidth(co, li, strlen(text)); | |
a61e44cc | 302 | } |
303 | ||
304 | if (num >= li->startShowItem && num <= li->startShowItem + co->height) | |
913d0524 | 305 | listboxDraw(co); |
a61e44cc | 306 | } |
307 | ||
a61e44cc | 308 | void newtListboxSetData(newtComponent co, int num, void * data) { |
2287215a | 309 | struct listbox * li = co->data; |
a61e44cc | 310 | int i; |
311 | struct items *item; | |
2287215a | 312 | |
a61e44cc | 313 | for(i = 0, item = li->boxItems; item != NULL && i < num; |
314 | i++, item = item->next); | |
2287215a | 315 | |
a61e44cc | 316 | item->data = data; |
2287215a | 317 | } |
318 | ||
dd2f0e88 | 319 | int newtListboxAppendEntry(newtComponent co, const char * text, |
a507b3ec | 320 | const void * data) { |
962b92a5 | 321 | struct listbox * li = co->data; |
a61e44cc | 322 | struct items *item; |
323 | ||
324 | if(li->boxItems) { | |
325 | for (item = li->boxItems; item->next != NULL; item = item->next); | |
962b92a5 | 326 | |
a61e44cc | 327 | item = item->next = malloc(sizeof(struct items)); |
328 | } else { | |
329 | item = li->boxItems = malloc(sizeof(struct items)); | |
962b92a5 | 330 | } |
331 | ||
913d0524 | 332 | if (!li->userHasSetWidth && text && (strlen(text) > li->curWidth)) |
333 | updateWidth(co, li, strlen(text)); | |
a61e44cc | 334 | |
a507b3ec | 335 | item->text = strdup(text); item->data = data; item->next = NULL; |
46263d9e | 336 | item->isSelected = 0; |
45f6c4fd | 337 | |
0bf47501 | 338 | if (li->grow) |
9b1b15f5 | 339 | co->height++, li->curHeight++; |
962b92a5 | 340 | li->numItems++; |
a61e44cc | 341 | |
a507b3ec | 342 | return 0; |
a61e44cc | 343 | } |
344 | ||
d4109c37 | 345 | int newtListboxInsertEntry(newtComponent co, const char * text, |
a507b3ec | 346 | const void * data, void * key) { |
a61e44cc | 347 | struct listbox * li = co->data; |
348 | struct items *item, *t; | |
962b92a5 | 349 | |
a61e44cc | 350 | if (li->boxItems) { |
a507b3ec | 351 | if (key) { |
352 | item = li->boxItems; | |
353 | while (item && item->data != key) item = item->next; | |
354 | ||
355 | if (!item) return 1; | |
356 | ||
aed35dda | 357 | t = item->next; |
358 | item = item->next = malloc(sizeof(struct items)); | |
359 | item->next = t; | |
360 | } else { | |
361 | t = li->boxItems; | |
362 | item = li->boxItems = malloc(sizeof(struct items)); | |
363 | item->next = t; | |
364 | } | |
a507b3ec | 365 | } else if (key) { |
366 | return 1; | |
a61e44cc | 367 | } else { |
368 | item = li->boxItems = malloc(sizeof(struct items)); | |
369 | item->next = NULL; | |
370 | } | |
371 | ||
913d0524 | 372 | if (!li->userHasSetWidth && text && (strlen(text) > li->curWidth)) |
373 | updateWidth(co, li, strlen(text)); | |
a61e44cc | 374 | |
a507b3ec | 375 | item->text = strdup(text?text:"(null)"); item->data = data; |
46263d9e | 376 | item->isSelected = 0; |
45f6c4fd | 377 | |
b9523497 | 378 | if (li->sb) |
aa564c1d | 379 | li->sb->left = co->left + co->width - li->bdxAdjust - 1; |
a61e44cc | 380 | li->numItems++; |
46263d9e | 381 | |
913d0524 | 382 | listboxDraw(co); |
a61e44cc | 383 | |
a507b3ec | 384 | return 0; |
962b92a5 | 385 | } |
386 | ||
a507b3ec | 387 | int newtListboxDeleteEntry(newtComponent co, void * key) { |
962b92a5 | 388 | struct listbox * li = co->data; |
a507b3ec | 389 | int widest = 0, t; |
a880525e | 390 | struct items *item, *item2 = NULL; |
a507b3ec | 391 | int num; |
aed35dda | 392 | |
4a93351d | 393 | if (li->boxItems == NULL || li->numItems <= 0) |
394 | return 0; | |
a61e44cc | 395 | |
a507b3ec | 396 | num = 0; |
a61e44cc | 397 | |
a507b3ec | 398 | item2 = NULL, item = li->boxItems; |
399 | while (item && item->data != key) { | |
400 | item2 = item; | |
401 | item = item->next; | |
402 | num++; | |
403 | } | |
a61e44cc | 404 | |
a507b3ec | 405 | if (!item) |
406 | return -1; | |
a61e44cc | 407 | |
a507b3ec | 408 | if (item2) |
a61e44cc | 409 | item2->next = item->next; |
a507b3ec | 410 | else |
411 | li->boxItems = item->next; | |
412 | ||
413 | free(item->text); | |
a61e44cc | 414 | free(item); |
415 | li->numItems--; | |
a507b3ec | 416 | |
417 | if (!li->userHasSetWidth) { | |
418 | widest = 0; | |
419 | for (item = li->boxItems; item != NULL; item = item->next) | |
420 | if ((t = strlen(item->text)) > widest) widest = t; | |
421 | } | |
422 | ||
423 | if (li->currItem >= num) | |
aed35dda | 424 | li->currItem--; |
a61e44cc | 425 | |
913d0524 | 426 | if (!li->userHasSetWidth) { |
427 | updateWidth(co, li, widest); | |
babcb349 | 428 | } |
a61e44cc | 429 | |
913d0524 | 430 | listboxDraw(co); |
962b92a5 | 431 | |
a507b3ec | 432 | return 0; |
962b92a5 | 433 | } |
434 | ||
49a541f2 | 435 | void newtListboxClear(newtComponent co) |
436 | { | |
437 | struct listbox * li; | |
438 | struct items *anitem, *nextitem; | |
439 | if(co == NULL || (li = co->data) == NULL) | |
440 | return; | |
441 | for(anitem = li->boxItems; anitem != NULL; anitem = nextitem) { | |
442 | nextitem = anitem->next; | |
a507b3ec | 443 | free(anitem->text); |
49a541f2 | 444 | free(anitem); |
445 | } | |
446 | li->numItems = li->numSelected = li->currItem = li->startShowItem = 0; | |
447 | li->boxItems = NULL; | |
45f6c4fd | 448 | if (!li->userHasSetWidth) |
913d0524 | 449 | updateWidth(co, li, 5); |
49a541f2 | 450 | } |
451 | ||
a61e44cc | 452 | /* If you don't want to get back the text, pass in NULL for the ptr-ptr. Same |
453 | goes for the data. */ | |
454 | void newtListboxGetEntry(newtComponent co, int num, char **text, void **data) { | |
962b92a5 | 455 | struct listbox * li = co->data; |
a61e44cc | 456 | int i; |
457 | struct items *item; | |
458 | ||
459 | if (!li->boxItems || num >= li->numItems) { | |
460 | if(text) | |
461 | *text = NULL; | |
462 | if(data) | |
463 | *data = NULL; | |
464 | return; | |
465 | } | |
466 | ||
467 | i = 0; | |
45f6c4fd | 468 | item = li->boxItems; |
a61e44cc | 469 | while (item && i < num) { |
470 | i++, item = item->next; | |
471 | } | |
472 | ||
473 | if (item) { | |
474 | if (text) | |
a507b3ec | 475 | *text = item->text; |
a61e44cc | 476 | if (data) |
45f6c4fd | 477 | *data = (void *)item->data; |
a61e44cc | 478 | } |
479 | } | |
480 | ||
481 | static void listboxDraw(newtComponent co) | |
482 | { | |
483 | struct listbox * li = co->data; | |
484 | struct items *item; | |
485 | int i, j; | |
486 | ||
913d0524 | 487 | if (!co->isMapped) return ; |
c6e478c2 | 488 | |
dd2f0e88 | 489 | if(li->flags & NEWT_FLAG_BORDER) { |
69f73704 | 490 | if(li->isActive) |
491 | SLsmg_set_color(NEWT_COLORSET_ACTLISTBOX); | |
492 | else | |
493 | SLsmg_set_color(NEWT_COLORSET_LISTBOX); | |
494 | ||
913d0524 | 495 | newtDrawBox(co->left, co->top, co->width, co->height, 0); |
69f73704 | 496 | } |
0b38669d | 497 | |
aa564c1d | 498 | if(li->sb) |
499 | li->sb->ops->draw(li->sb); | |
500 | ||
69f73704 | 501 | SLsmg_set_color(NEWT_COLORSET_LISTBOX); |
45f6c4fd | 502 | |
a61e44cc | 503 | for(i = 0, item = li->boxItems; item != NULL && i < li->startShowItem; |
504 | i++, item = item->next); | |
505 | ||
506 | j = i; | |
a61e44cc | 507 | |
913d0524 | 508 | for (i = 0; item != NULL && i < li->curHeight; i++, item = item->next) { |
a507b3ec | 509 | if (!item->text) continue; |
a61e44cc | 510 | |
913d0524 | 511 | newtGotorc(co->top + i + li->bdyAdjust, co->left + li->bdxAdjust); |
46263d9e | 512 | if(j + i == li->currItem) { |
513 | if(item->isSelected) | |
514 | SLsmg_set_color(NEWT_COLORSET_ACTSELLISTBOX); | |
515 | else | |
516 | SLsmg_set_color(NEWT_COLORSET_ACTLISTBOX); | |
517 | } else if(item->isSelected) | |
518 | SLsmg_set_color(NEWT_COLORSET_SELLISTBOX); | |
519 | else | |
520 | SLsmg_set_color(NEWT_COLORSET_LISTBOX); | |
45f6c4fd | 521 | |
a507b3ec | 522 | SLsmg_write_nstring(item->text, li->curWidth); |
a61e44cc | 523 | |
a61e44cc | 524 | } |
0b38669d | 525 | newtGotorc(co->top + (li->currItem - li->startShowItem), co->left); |
a61e44cc | 526 | } |
527 | ||
528 | static struct eventResult listboxEvent(newtComponent co, struct event ev) { | |
2287215a | 529 | struct eventResult er; |
a61e44cc | 530 | struct listbox * li = co->data; |
d63d1c70 | 531 | struct items *item; |
532 | int i; | |
533 | ||
a61e44cc | 534 | er.result = ER_IGNORED; |
45f6c4fd | 535 | |
0b38669d | 536 | if(ev.when == EV_EARLY || ev.when == EV_LATE) { |
537 | return er; | |
538 | } | |
45f6c4fd | 539 | |
a61e44cc | 540 | switch(ev.event) { |
541 | case EV_KEYPRESS: | |
542 | if (!li->isActive) break; | |
543 | ||
544 | switch(ev.u.key) { | |
46263d9e | 545 | case ' ': |
546 | if(!(li->flags & NEWT_FLAG_MULTIPLE)) break; | |
45f6c4fd | 547 | newtListboxSelectItem(co, li->boxItems[li->currItem].data, |
dd2f0e88 | 548 | NEWT_FLAGS_TOGGLE); |
69bf2308 | 549 | er.result = ER_SWALLOWED; |
550 | /* We don't break here, because it is cool to be able to | |
551 | hold space to select a bunch of items in a list at once */ | |
552 | ||
553 | case NEWT_KEY_DOWN: | |
554 | if(li->numItems <= 0) break; | |
555 | if(li->currItem < li->numItems - 1) { | |
556 | li->currItem++; | |
913d0524 | 557 | if(li->currItem > (li->startShowItem + li->curHeight - 1)) { |
558 | li->startShowItem = li->currItem - li->curHeight + 1; | |
559 | if(li->startShowItem + li->curHeight > li->numItems) | |
560 | li->startShowItem = li->numItems - li->curHeight; | |
69bf2308 | 561 | } |
562 | if(li->sb) | |
563 | newtScrollbarSet(li->sb, li->currItem + 1, li->numItems); | |
564 | listboxDraw(co); | |
565 | } | |
566 | if(co->callback) co->callback(co, co->callbackData); | |
46263d9e | 567 | er.result = ER_SWALLOWED; |
568 | break; | |
569 | ||
a61e44cc | 570 | case NEWT_KEY_ENTER: |
4e9c4bb9 | 571 | if(li->numItems <= 0) break; |
572 | if(li->flags & NEWT_FLAG_RETURNEXIT) | |
a61e44cc | 573 | er.result = ER_EXITFORM; |
574 | break; | |
575 | ||
576 | case NEWT_KEY_UP: | |
4e9c4bb9 | 577 | if(li->numItems <= 0) break; |
a61e44cc | 578 | if(li->currItem > 0) { |
579 | li->currItem--; | |
580 | if(li->currItem < li->startShowItem) | |
581 | li->startShowItem = li->currItem; | |
0bf47501 | 582 | if(li->sb) |
583 | newtScrollbarSet(li->sb, li->currItem + 1, li->numItems); | |
a61e44cc | 584 | listboxDraw(co); |
585 | } | |
f37450e9 | 586 | if(co->callback) co->callback(co, co->callbackData); |
a61e44cc | 587 | er.result = ER_SWALLOWED; |
588 | break; | |
589 | ||
a61e44cc | 590 | case NEWT_KEY_PGUP: |
4e9c4bb9 | 591 | if(li->numItems <= 0) break; |
913d0524 | 592 | li->startShowItem -= li->curHeight - 1; |
4e9c4bb9 | 593 | if(li->startShowItem < 0) |
594 | li->startShowItem = 0; | |
913d0524 | 595 | li->currItem -= li->curHeight - 1; |
4e9c4bb9 | 596 | if(li->currItem < 0) |
597 | li->currItem = 0; | |
598 | newtListboxRealSetCurrent(co); | |
a61e44cc | 599 | er.result = ER_SWALLOWED; |
600 | break; | |
601 | ||
602 | case NEWT_KEY_PGDN: | |
4e9c4bb9 | 603 | if(li->numItems <= 0) break; |
913d0524 | 604 | li->startShowItem += li->curHeight; |
605 | if(li->startShowItem > (li->numItems - li->curHeight)) { | |
606 | li->startShowItem = li->numItems - li->curHeight; | |
4e9c4bb9 | 607 | } |
913d0524 | 608 | li->currItem += li->curHeight; |
d63d1c70 | 609 | if(li->currItem >= li->numItems) { |
4e9c4bb9 | 610 | li->currItem = li->numItems - 1; |
611 | } | |
612 | newtListboxRealSetCurrent(co); | |
a61e44cc | 613 | er.result = ER_SWALLOWED; |
614 | break; | |
f37450e9 | 615 | |
3a779f2f | 616 | case NEWT_KEY_HOME: |
4e9c4bb9 | 617 | if(li->numItems <= 0) break; |
3a779f2f | 618 | newtListboxSetCurrent(co, 0); |
619 | er.result = ER_SWALLOWED; | |
620 | break; | |
f37450e9 | 621 | |
3a779f2f | 622 | case NEWT_KEY_END: |
4e9c4bb9 | 623 | if(li->numItems <= 0) break; |
ae5aa3ac | 624 | li->startShowItem = li->numItems - li->curHeight; |
50c7eaa1 | 625 | if(li->startShowItem < 0) |
626 | li->startShowItem = 0; | |
ae5aa3ac | 627 | li->currItem = li->numItems - 1; |
628 | newtListboxRealSetCurrent(co); | |
3a779f2f | 629 | er.result = ER_SWALLOWED; |
630 | break; | |
a61e44cc | 631 | default: |
d63d1c70 | 632 | if (isalpha(ev.u.key)) { |
633 | ||
634 | for(i = 0, item = li->boxItems; item != NULL && | |
635 | i < li->currItem; i++, item = item->next); | |
636 | ||
637 | if (item->text && (toupper(*item->text) == toupper(ev.u.key))) { | |
638 | item = item->next; | |
639 | i++; | |
640 | } else { | |
641 | item = li->boxItems; | |
642 | i = 0; | |
643 | } | |
644 | while (item && item->text && | |
645 | toupper(*item->text) != toupper(ev.u.key)) { | |
646 | item = item->next; | |
647 | i++; | |
648 | } | |
649 | if (item) { | |
650 | li->currItem = i; | |
651 | if(li->currItem < li->startShowItem || | |
652 | li->currItem > li->startShowItem) | |
b6a38a40 | 653 | li->startShowItem = |
654 | li->currItem > li->numItems - li->curHeight ? | |
655 | li->startShowItem = li->numItems - li->curHeight : | |
656 | li->currItem; | |
d63d1c70 | 657 | if(li->sb) |
658 | newtScrollbarSet(li->sb, li->currItem + 1, li->numItems); | |
659 | newtListboxRealSetCurrent(co); | |
660 | er.result = ER_SWALLOWED; | |
661 | } | |
662 | } | |
a61e44cc | 663 | } |
664 | break; | |
45f6c4fd | 665 | |
a61e44cc | 666 | case EV_FOCUS: |
a61e44cc | 667 | li->isActive = 1; |
0b38669d | 668 | listboxDraw(co); |
a61e44cc | 669 | er.result = ER_SWALLOWED; |
670 | break; | |
671 | ||
672 | case EV_UNFOCUS: | |
673 | li->isActive = 0; | |
3a779f2f | 674 | listboxDraw(co); |
a61e44cc | 675 | er.result = ER_SWALLOWED; |
676 | break; | |
45f6c4fd | 677 | |
678 | case EV_MOUSE: | |
679 | /* if this mouse click was within the listbox, make the current | |
680 | item the item clicked on. */ | |
681 | /* Up scroll arrow */ | |
682 | if (li->sb && | |
683 | ev.u.mouse.x == co->left + co->width - li->bdxAdjust - 1 && | |
684 | ev.u.mouse.y == co->top + li->bdyAdjust) { | |
685 | if(li->numItems <= 0) break; | |
686 | if(li->currItem > 0) { | |
687 | li->currItem--; | |
688 | if(li->currItem < li->startShowItem) | |
689 | li->startShowItem = li->currItem; | |
690 | if(li->sb) | |
691 | newtScrollbarSet(li->sb, li->currItem + 1, li->numItems); | |
692 | listboxDraw(co); | |
693 | } | |
694 | if(co->callback) co->callback(co, co->callbackData); | |
695 | er.result = ER_SWALLOWED; | |
696 | break; | |
697 | } | |
698 | /* Down scroll arrow */ | |
699 | if (li->sb && | |
700 | ev.u.mouse.x == co->left + co->width - li->bdxAdjust - 1 && | |
701 | ev.u.mouse.y == co->top + co->height - li->bdyAdjust - 1) { | |
702 | if(li->numItems <= 0) break; | |
703 | if(li->currItem < li->numItems - 1) { | |
704 | li->currItem++; | |
705 | if(li->currItem > (li->startShowItem + li->curHeight - 1)) { | |
706 | li->startShowItem = li->currItem - li->curHeight + 1; | |
707 | if(li->startShowItem + li->curHeight > li->numItems) | |
708 | li->startShowItem = li->numItems - li->curHeight; | |
709 | } | |
710 | if(li->sb) | |
711 | newtScrollbarSet(li->sb, li->currItem + 1, li->numItems); | |
712 | listboxDraw(co); | |
713 | } | |
714 | if(co->callback) co->callback(co, co->callbackData); | |
715 | er.result = ER_SWALLOWED; | |
716 | break; | |
717 | } | |
718 | if ((ev.u.mouse.y >= co->top + li->bdyAdjust) && | |
719 | (ev.u.mouse.y <= co->top + co->height - (li->bdyAdjust * 2)) && | |
720 | (ev.u.mouse.x >= co->left + li->bdxAdjust) && | |
721 | (ev.u.mouse.x <= co->left + co->width + (li->bdxAdjust * 2))) { | |
722 | li->currItem = li->startShowItem + | |
723 | (ev.u.mouse.y - li->bdyAdjust - co->top); | |
724 | newtListboxRealSetCurrent(co); | |
725 | listboxDraw(co); | |
726 | if(co->callback) co->callback(co, co->callbackData); | |
727 | er.result = ER_SWALLOWED; | |
728 | break; | |
729 | } | |
2287215a | 730 | } |
962b92a5 | 731 | |
a61e44cc | 732 | return er; |
962b92a5 | 733 | } |
734 | ||
735 | static void listboxDestroy(newtComponent co) { | |
736 | struct listbox * li = co->data; | |
a61e44cc | 737 | struct items * item, * nextitem; |
738 | ||
739 | nextitem = item = li->boxItems; | |
740 | ||
741 | while (item != NULL) { | |
742 | nextitem = item->next; | |
a507b3ec | 743 | free(item->text); |
a61e44cc | 744 | free(item); |
745 | item = nextitem; | |
746 | } | |
962b92a5 | 747 | |
962b92a5 | 748 | free(li); |
749 | free(co); | |
750 | } |