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