]> git.ipfire.org Git - thirdparty/newt.git/blame - listbox.c
free hotkeys
[thirdparty/newt.git] / listbox.c
CommitLineData
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 */
17struct 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 25struct 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
44static void listboxDraw(newtComponent co);
45static void listboxDestroy(newtComponent co);
46static struct eventResult listboxEvent(newtComponent co, struct event ev);
4e9c4bb9 47static void newtListboxRealSetCurrent(newtComponent co);
8f52cd47 48static void listboxPlace(newtComponent co, int newLeft, int newTop);
45f6c4fd 49static inline void updateWidth(newtComponent co, struct listbox * li,
913d0524 50 int maxField);
8f52cd47 51static void listboxMapped(newtComponent co, int isMapped);
962b92a5 52
53static struct componentOps listboxOps = {
54 listboxDraw,
55 listboxEvent,
56 listboxDestroy,
e948278c 57 listboxPlace,
8f52cd47 58 listboxMapped,
a61e44cc 59};
962b92a5 60
8f52cd47 61static 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
69static 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 80newtComponent 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 142static 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 151void 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 164void 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 187static 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 197void 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 207void * 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 221void 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
252void 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 265void ** 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 286void 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 308void 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 319int 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 345int 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 387int 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 435void 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. */
454void 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
481static 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
528static 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
735static 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}