]> git.ipfire.org Git - thirdparty/newt.git/blame - listbox.c
0.52.24
[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"
63231242 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 */
6f481af2 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
6f481af2 34 on the screen */
a61e44cc 35 int isActive; /* If we handle key events all the time, it seems
6f481af2 36 to do things even when they are supposed to be for
37 another button/whatever */
a61e44cc 38 struct items *boxItems;
0bf47501 39 int grow;
a61e44cc 40 int flags; /* flags for this listbox, right now just
6f481af2 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,
6f481af2 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)
6f481af2 66 li->sb->ops->mapped(li->sb, isMapped);
8f52cd47 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)
6f481af2 76 li->sb->ops->place(li->sb, co->left + co->width - li->bdxAdjust - 1,
4014bc65 77 co->top + li->bdyAdjust);
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))))
6f481af2 85 return NULL;
962b92a5 86
a61e44cc 87 if (!(li = malloc(sizeof(struct listbox)))) {
6f481af2 88 free(co);
89 return NULL;
a61e44cc 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 |
6f481af2 103 NEWT_FLAG_MULTIPLE | NEWT_FLAG_SHOWCURSOR);
913d0524 104
dd2f0e88 105 if (li->flags & NEWT_FLAG_BORDER) {
6f481af2 106 li->bdxAdjust = 2;
107 li->bdyAdjust = 1;
913d0524 108 }
962b92a5 109
aa564c1d 110 co->height = height;
111 li->curHeight = co->height - (2 * li->bdyAdjust);
112
0bf47501 113 if (height) {
6f481af2 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 }
0bf47501 123 } else {
6f481af2 124 li->grow = 1;
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;
c101e99e 136 co->destroyCallback = NULL;
962b92a5 137
913d0524 138 updateWidth(co, li, 5);
913d0524 139
962b92a5 140 return co;
141}
142
45f6c4fd 143static inline void updateWidth(newtComponent co, struct listbox * li,
6f481af2 144 int maxField) {
913d0524 145 li->curWidth = maxField;
146 co->width = li->curWidth + li->sbAdjust + 2 * li->bdxAdjust;
147
148 if (li->sb)
6f481af2 149 li->sb->left = co->left + co->width - li->bdxAdjust - 1;
913d0524 150}
151
d5878365 152void 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)
6f481af2 159 item = item->next, i++;
d5878365 160
161 if (item)
6f481af2 162 newtListboxSetCurrent(co, i);
d5878365 163}
164
4e9c4bb9 165void newtListboxSetCurrent(newtComponent co, int num)
166{
7ea3dccd 167 struct listbox * li = co->data;
d5878365 168
a61e44cc 169 if (num >= li->numItems)
6f481af2 170 li->currItem = li->numItems - 1;
a61e44cc 171 else if (num < 0)
6f481af2 172 li->currItem = 0;
a61e44cc 173 else
6f481af2 174 li->currItem = num;
a61e44cc 175
176 if (li->currItem < li->startShowItem)
6f481af2 177 li->startShowItem = li->currItem;
dc598586 178 else if (li->currItem - li->startShowItem > li->curHeight - 1)
6f481af2 179 li->startShowItem = li->currItem - li->curHeight + 1;
dc598586 180 if (li->startShowItem + li->curHeight > li->numItems)
6f481af2 181 li->startShowItem = li->numItems - li->curHeight;
3a779f2f 182 if(li->startShowItem < 0)
6f481af2 183 li->startShowItem = 0;
d5878365 184
4e9c4bb9 185 newtListboxRealSetCurrent(co);
186}
187
d5878365 188static void newtListboxRealSetCurrent(newtComponent co)
4e9c4bb9 189{
190 struct listbox * li = co->data;
d5878365 191
0bf47501 192 if(li->sb)
6f481af2 193 newtScrollbarSet(li->sb, li->currItem + 1, li->numItems);
913d0524 194 listboxDraw(co);
f37450e9 195 if(co->callback) co->callback(co, co->callbackData);
7ea3dccd 196}
197
913d0524 198void newtListboxSetWidth(newtComponent co, int width) {
babcb349 199 struct listbox * li = co->data;
45f6c4fd 200
e948278c 201 co->width = width;
913d0524 202 li->curWidth = co->width - li->sbAdjust - 2 * li->bdxAdjust;
babcb349 203 li->userHasSetWidth = 1;
4014bc65 204 if (li->sb)
205 li->sb->left = co->left + co->width - li->bdxAdjust - 1;
913d0524 206 listboxDraw(co);
babcb349 207}
208
2287215a 209void * newtListboxGetCurrent(newtComponent co) {
210 struct listbox * li = co->data;
2287215a 211 int i;
a61e44cc 212 struct items *item;
2287215a 213
a61e44cc 214 for(i = 0, item = li->boxItems; item != NULL && i < li->currItem;
6f481af2 215 i++, item = item->next);
2287215a 216
a61e44cc 217 if (item)
6f481af2 218 return (void *)item->data;
2287215a 219 else
6f481af2 220 return NULL;
2287215a 221}
222
dd2f0e88 223void newtListboxSelectItem(newtComponent co, const void * key,
6f481af2 224 enum newtFlagsSense sense)
46263d9e 225{
226 struct listbox * li = co->data;
227 int i;
dd2f0e88 228 struct items * item;
45f6c4fd 229
dd2f0e88 230 item = li->boxItems, i = 0;
231 while (item && item->data != key)
6f481af2 232 item = item->next, i++;
dd2f0e88 233
234 if (!item) return;
235
236 if (item->isSelected)
6f481af2 237 li->numSelected--;
dd2f0e88 238
239 switch(sense) {
6f481af2 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;
46263d9e 246 }
dd2f0e88 247
248 if (item->isSelected)
6f481af2 249 li->numSelected++;
dd2f0e88 250
913d0524 251 listboxDraw(co);
46263d9e 252}
253
254void newtListboxClearSelection(newtComponent co)
255{
256 struct items *item;
257 struct listbox * li = co->data;
258
259 for(item = li->boxItems; item != NULL;
6f481af2 260 item = item->next)
261 item->isSelected = 0;
69bf2308 262 li->numSelected = 0;
913d0524 263 listboxDraw(co);
46263d9e 264}
265
2dbc072e 266/* Free the returned array after use, but NOT the values in the array */
cb586ef6 267void ** newtListboxGetSelection(newtComponent co, int *numitems)
2dbc072e 268{
269 struct listbox * li;
270 int i;
271 void **retval;
272 struct items *item;
273
cb586ef6 274 if(!co || !numitems) return NULL;
2dbc072e 275
276 li = co->data;
277 if(!li || !li->numSelected) return NULL;
278
cb586ef6 279 retval = malloc(li->numSelected * sizeof(void *));
2dbc072e 280 for(i = 0, item = li->boxItems; item != NULL;
6f481af2 281 item = item->next)
282 if(item->isSelected)
283 retval[i++] = (void *)item->data;
cb586ef6 284 *numitems = li->numSelected;
2dbc072e 285 return retval;
286}
287
dd2f0e88 288void newtListboxSetEntry(newtComponent co, int num, const char * text) {
a61e44cc 289 struct listbox * li = co->data;
63231242 290 int i;
a61e44cc 291 struct items *item;
292
293 for(i = 0, item = li->boxItems; item != NULL && i < num;
6f481af2 294 i++, item = item->next);
a61e44cc 295
296 if(!item)
6f481af2 297 return;
3a779f2f 298 else {
6f481af2 299 free(item->text);
300 item->text = strdup(text);
3a779f2f 301 }
349586bb 302 if (li->userHasSetWidth == 0 && wstrlen(text,-1) > li->curWidth) {
6f481af2 303 updateWidth(co, li, wstrlen(text,-1));
a61e44cc 304 }
305
306 if (num >= li->startShowItem && num <= li->startShowItem + co->height)
6f481af2 307 listboxDraw(co);
a61e44cc 308}
309
a61e44cc 310void newtListboxSetData(newtComponent co, int num, void * data) {
2287215a 311 struct listbox * li = co->data;
a61e44cc 312 int i;
313 struct items *item;
2287215a 314
a61e44cc 315 for(i = 0, item = li->boxItems; item != NULL && i < num;
6f481af2 316 i++, item = item->next);
2287215a 317
3341bdc5
ML
318 if (item)
319 item->data = data;
2287215a 320}
321
dd2f0e88 322int newtListboxAppendEntry(newtComponent co, const char * text,
6f481af2 323 const void * data) {
962b92a5 324 struct listbox * li = co->data;
a61e44cc 325 struct items *item;
326
327 if(li->boxItems) {
6f481af2 328 for (item = li->boxItems; item->next != NULL; item = item->next);
962b92a5 329
6f481af2 330 item = item->next = malloc(sizeof(struct items));
a61e44cc 331 } else {
6f481af2 332 item = li->boxItems = malloc(sizeof(struct items));
962b92a5 333 }
334
349586bb 335 if (!li->userHasSetWidth && text && (wstrlen(text,-1) > li->curWidth))
6f481af2 336 updateWidth(co, li, wstrlen(text,-1));
a61e44cc 337
a507b3ec 338 item->text = strdup(text); item->data = data; item->next = NULL;
46263d9e 339 item->isSelected = 0;
45f6c4fd 340
0bf47501 341 if (li->grow)
6f481af2 342 co->height++, li->curHeight++;
962b92a5 343 li->numItems++;
a61e44cc 344
a507b3ec 345 return 0;
a61e44cc 346}
347
d4109c37 348int newtListboxInsertEntry(newtComponent co, const char * text,
6f481af2 349 const void * data, void * key) {
a61e44cc 350 struct listbox * li = co->data;
351 struct items *item, *t;
962b92a5 352
a61e44cc 353 if (li->boxItems) {
6f481af2 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 }
a507b3ec 368 } else if (key) {
6f481af2 369 return 1;
a61e44cc 370 } else {
6f481af2 371 item = li->boxItems = malloc(sizeof(struct items));
372 item->next = NULL;
a61e44cc 373 }
374
349586bb 375 if (!li->userHasSetWidth && text && (wstrlen(text,-1) > li->curWidth))
6f481af2 376 updateWidth(co, li, wstrlen(text,-1));
a61e44cc 377
a507b3ec 378 item->text = strdup(text?text:"(null)"); item->data = data;
46263d9e 379 item->isSelected = 0;
45f6c4fd 380
b9523497 381 if (li->sb)
6f481af2 382 li->sb->left = co->left + co->width - li->bdxAdjust - 1;
a61e44cc 383 li->numItems++;
46263d9e 384
913d0524 385 listboxDraw(co);
a61e44cc 386
a507b3ec 387 return 0;
962b92a5 388}
389
a507b3ec 390int newtListboxDeleteEntry(newtComponent co, void * key) {
962b92a5 391 struct listbox * li = co->data;
a507b3ec 392 int widest = 0, t;
a880525e 393 struct items *item, *item2 = NULL;
a507b3ec 394 int num;
aed35dda 395
4a93351d 396 if (li->boxItems == NULL || li->numItems <= 0)
6f481af2 397 return 0;
a61e44cc 398
a507b3ec 399 num = 0;
a61e44cc 400
a507b3ec 401 item2 = NULL, item = li->boxItems;
402 while (item && item->data != key) {
6f481af2 403 item2 = item;
404 item = item->next;
405 num++;
a507b3ec 406 }
a61e44cc 407
a507b3ec 408 if (!item)
6f481af2 409 return -1;
a61e44cc 410
a507b3ec 411 if (item2)
6f481af2 412 item2->next = item->next;
a507b3ec 413 else
6f481af2 414 li->boxItems = item->next;
a507b3ec 415
416 free(item->text);
a61e44cc 417 free(item);
418 li->numItems--;
a507b3ec 419
420 if (!li->userHasSetWidth) {
6f481af2 421 widest = 0;
422 for (item = li->boxItems; item != NULL; item = item->next)
423 if ((t = wstrlen(item->text,-1)) > widest) widest = t;
a507b3ec 424 }
425
426 if (li->currItem >= num)
6f481af2 427 li->currItem--;
a61e44cc 428
913d0524 429 if (!li->userHasSetWidth) {
6f481af2 430 updateWidth(co, li, widest);
babcb349 431 }
a61e44cc 432
913d0524 433 listboxDraw(co);
962b92a5 434
a507b3ec 435 return 0;
962b92a5 436}
437
49a541f2 438void newtListboxClear(newtComponent co)
439{
440 struct listbox * li;
441 struct items *anitem, *nextitem;
442 if(co == NULL || (li = co->data) == NULL)
6f481af2 443 return;
49a541f2 444 for(anitem = li->boxItems; anitem != NULL; anitem = nextitem) {
6f481af2 445 nextitem = anitem->next;
446 free(anitem->text);
447 free(anitem);
49a541f2 448 }
449 li->numItems = li->numSelected = li->currItem = li->startShowItem = 0;
450 li->boxItems = NULL;
45f6c4fd 451 if (!li->userHasSetWidth)
6f481af2 452 updateWidth(co, li, 5);
49a541f2 453}
454
1dcea57f 455int newtListboxItemCount(newtComponent co)
456{
457 struct listbox *li = co->data;
458 return li->numItems;
459}
460
a61e44cc 461/* If you don't want to get back the text, pass in NULL for the ptr-ptr. Same
462 goes for the data. */
463void newtListboxGetEntry(newtComponent co, int num, char **text, void **data) {
962b92a5 464 struct listbox * li = co->data;
a61e44cc 465 int i;
466 struct items *item;
467
468 if (!li->boxItems || num >= li->numItems) {
6f481af2 469 if(text)
470 *text = NULL;
471 if(data)
472 *data = NULL;
473 return;
a61e44cc 474 }
475
476 i = 0;
45f6c4fd 477 item = li->boxItems;
a61e44cc 478 while (item && i < num) {
6f481af2 479 i++, item = item->next;
a61e44cc 480 }
481
482 if (item) {
6f481af2 483 if (text)
484 *text = item->text;
485 if (data)
486 *data = (void *)item->data;
a61e44cc 487 }
488}
489
490static void listboxDraw(newtComponent co)
491{
492 struct listbox * li = co->data;
493 struct items *item;
494 int i, j;
495
913d0524 496 if (!co->isMapped) return ;
c6e478c2 497
7ff5fd71 498 newtTrashScreen();
499
dd2f0e88 500 if(li->flags & NEWT_FLAG_BORDER) {
69f73704 501 if(li->isActive)
6f481af2 502 SLsmg_set_color(NEWT_COLORSET_ACTLISTBOX);
69f73704 503 else
504 SLsmg_set_color(NEWT_COLORSET_LISTBOX);
505
913d0524 506 newtDrawBox(co->left, co->top, co->width, co->height, 0);
69f73704 507 }
0b38669d 508
aa564c1d 509 if(li->sb)
6f481af2 510 li->sb->ops->draw(li->sb);
aa564c1d 511
69f73704 512 SLsmg_set_color(NEWT_COLORSET_LISTBOX);
45f6c4fd 513
a61e44cc 514 for(i = 0, item = li->boxItems; item != NULL && i < li->startShowItem;
6f481af2 515 i++, item = item->next);
a61e44cc 516
517 j = i;
a61e44cc 518
913d0524 519 for (i = 0; item != NULL && i < li->curHeight; i++, item = item->next) {
6f481af2 520 if (!item->text) continue;
a61e44cc 521
6f481af2 522 newtGotorc(co->top + i + li->bdyAdjust, co->left + li->bdxAdjust);
523 if(j + i == li->currItem) {
9fc6a6b0 524 if(li->isActive)
6f481af2 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);
45f6c4fd 532
8e0e899c 533 SLsmg_write_nstring(item->text, li->curWidth);
a61e44cc 534
9fc6a6b0 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 }
a61e44cc 541 }
f4f5c676 542 newtGotorc(co->top + (li->currItem - li->startShowItem) + li->bdyAdjust,
543 co->left + li->bdxAdjust);
a61e44cc 544}
545
546static struct eventResult listboxEvent(newtComponent co, struct event ev) {
2287215a 547 struct eventResult er;
a61e44cc 548 struct listbox * li = co->data;
d63d1c70 549 struct items *item;
550 int i;
551
a61e44cc 552 er.result = ER_IGNORED;
45f6c4fd 553
0b38669d 554 if(ev.when == EV_EARLY || ev.when == EV_LATE) {
6f481af2 555 return er;
0b38669d 556 }
45f6c4fd 557
a61e44cc 558 switch(ev.event) {
559 case EV_KEYPRESS:
6f481af2 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;
f3de1284 651 if (ev.u.key < NEWT_KEY_EXTRA_BASE && isalpha(ev.u.key)) {
6f481af2 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 ?
3341bdc5 673 li->numItems - li->curHeight :
6f481af2 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;
45f6c4fd 683
a61e44cc 684 case EV_FOCUS:
6f481af2 685 li->isActive = 1;
686 listboxDraw(co);
687 if(li->flags & NEWT_FLAG_SHOWCURSOR)
688 newtCursorOn();
689 er.result = ER_SWALLOWED;
690 break;
a61e44cc 691
692 case EV_UNFOCUS:
6f481af2 693 li->isActive = 0;
694 listboxDraw(co);
695 if(li->flags & NEWT_FLAG_SHOWCURSOR)
696 newtCursorOff();
697 er.result = ER_SWALLOWED;
698 break;
45f6c4fd 699
700 case EV_MOUSE:
6f481af2 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 }
2287215a 752 }
962b92a5 753
a61e44cc 754 return er;
962b92a5 755}
756
757static void listboxDestroy(newtComponent co) {
758 struct listbox * li = co->data;
a61e44cc 759 struct items * item, * nextitem;
760
638f672c 761 item = li->boxItems;
a61e44cc 762
763 while (item != NULL) {
6f481af2 764 nextitem = item->next;
765 free(item->text);
766 free(item);
767 item = nextitem;
a61e44cc 768 }
962b92a5 769
a50f10e7 770 if (li->sb) li->sb->ops->destroy(li->sb);
771
962b92a5 772 free(li);
773 free(co);
774}