~ubuntu-branches/ubuntu/dapper/newt/dapper

« back to all changes in this revision

Viewing changes to listbox.c

  • Committer: Bazaar Package Importer
  • Author(s): Alastair McKinstry
  • Date: 2004-11-27 09:49:00 UTC
  • mfrom: (1.1.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20041127094900-mf7cbmb00g7t8xow
Tags: 0.51.6-20
Upgrade bug; lbnewt0.51 was supplying /usr/lib/libnewt.so in conflict
with libnewt-dev. Closes: #283185.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
#ifndef UTF8
16
 
#define strwidth strlen
17
 
#endif
18
 
 
19
 
/* Linked list of items in the listbox */
20
 
struct items {
21
 
    char * text;
22
 
    const void *data;
23
 
    unsigned char isSelected;
24
 
    struct items *next;
25
 
};
26
 
 
27
 
/* Holds all the relevant information for this listbox */
28
 
struct listbox {
29
 
    newtComponent sb;   /* Scrollbar on right side of listbox */
30
 
    int curWidth;       /* size of text w/o scrollbar or border*/
31
 
    int curHeight;      /* size of text w/o border */
32
 
    int sbAdjust;
33
 
    int bdxAdjust, bdyAdjust;
34
 
    int numItems, numSelected;
35
 
    int userHasSetWidth;
36
 
    int currItem, startShowItem; /* startShowItem is the first item displayed
37
 
                                   on the screen */
38
 
    int isActive; /* If we handle key events all the time, it seems
39
 
                     to do things even when they are supposed to be for
40
 
                     another button/whatever */
41
 
    struct items *boxItems;
42
 
    int grow;
43
 
    int flags; /* flags for this listbox, right now just
44
 
                  NEWT_FLAG_RETURNEXIT */
45
 
};
46
 
 
47
 
static void listboxDraw(newtComponent co);
48
 
static void listboxDestroy(newtComponent co);
49
 
static struct eventResult listboxEvent(newtComponent co, struct event ev);
50
 
static void newtListboxRealSetCurrent(newtComponent co);
51
 
static void listboxPlace(newtComponent co, int newLeft, int newTop);
52
 
static inline void updateWidth(newtComponent co, struct listbox * li,
53
 
                                int maxField);
54
 
static void listboxMapped(newtComponent co, int isMapped);
55
 
 
56
 
static struct componentOps listboxOps = {
57
 
    listboxDraw,
58
 
    listboxEvent,
59
 
    listboxDestroy,
60
 
    listboxPlace,
61
 
    listboxMapped,
62
 
};
63
 
 
64
 
static void listboxMapped(newtComponent co, int isMapped) {
65
 
    struct listbox * li = co->data;
66
 
 
67
 
    co->isMapped = isMapped;
68
 
    if (li->sb)
69
 
        li->sb->ops->mapped(li->sb, isMapped);
70
 
}
71
 
 
72
 
static void listboxPlace(newtComponent co, int newLeft, int newTop) {
73
 
    struct listbox * li = co->data;
74
 
 
75
 
    co->top = newTop;
76
 
    co->left = newLeft;
77
 
 
78
 
    if (li->sb)
79
 
        li->sb->ops->place(li->sb, co->left + co->width - li->bdxAdjust - 1,
80
 
                           co->top);
81
 
}
82
 
 
83
 
newtComponent newtListbox(int left, int top, int height, int flags) {
84
 
    newtComponent co, sb;
85
 
    struct listbox * li;
86
 
 
87
 
    if (!(co = malloc(sizeof(*co))))
88
 
        return NULL;
89
 
 
90
 
    if (!(li = malloc(sizeof(struct listbox)))) {
91
 
        free(co);
92
 
        return NULL;
93
 
    }
94
 
 
95
 
    li->boxItems = NULL;
96
 
    li->numItems = 0;
97
 
    li->currItem = 0;
98
 
    li->numSelected = 0;
99
 
    li->isActive = 0;
100
 
    li->userHasSetWidth = 0;
101
 
    li->startShowItem = 0;
102
 
    li->sbAdjust = 0;
103
 
    li->bdxAdjust = 0;
104
 
    li->bdyAdjust = 0;
105
 
    li->flags = flags & (NEWT_FLAG_RETURNEXIT | NEWT_FLAG_BORDER |
106
 
                         NEWT_FLAG_MULTIPLE);
107
 
 
108
 
    if (li->flags & NEWT_FLAG_BORDER) {
109
 
        li->bdxAdjust = 2;
110
 
        li->bdyAdjust = 1;
111
 
    }
112
 
 
113
 
    co->height = height;
114
 
    li->curHeight = co->height - (2 * li->bdyAdjust);
115
 
 
116
 
    if (height) {
117
 
        li->grow = 0;
118
 
        if (flags & NEWT_FLAG_SCROLL) {
119
 
            sb = newtVerticalScrollbar(left, top + li->bdyAdjust,
120
 
                                        li->curHeight,
121
 
                                        COLORSET_LISTBOX, COLORSET_ACTLISTBOX);
122
 
            li->sbAdjust = 3;
123
 
        } else {
124
 
            sb = NULL;
125
 
        }
126
 
    } else {
127
 
        li->grow = 1;
128
 
        sb = NULL;
129
 
    }
130
 
 
131
 
    li->sb = sb;
132
 
    co->data = li;
133
 
    co->isMapped = 0;
134
 
    co->left = left;
135
 
    co->top = top;
136
 
    co->ops = &listboxOps;
137
 
    co->takesFocus = 1;
138
 
    co->callback = NULL;
139
 
 
140
 
    updateWidth(co, li, 5);
141
 
 
142
 
    return co;
143
 
}
144
 
 
145
 
static inline void updateWidth(newtComponent co, struct listbox * li,
146
 
                                int maxField) {
147
 
    li->curWidth = maxField;
148
 
    co->width = li->curWidth + li->sbAdjust + 2 * li->bdxAdjust;
149
 
 
150
 
    if (li->sb)
151
 
        li->sb->left = co->left + co->width - li->bdxAdjust - 1;
152
 
}
153
 
 
154
 
void newtListboxSetCurrentByKey(newtComponent co, void * key) {
155
 
    struct listbox * li = co->data;
156
 
    struct items * item;
157
 
    int i;
158
 
 
159
 
    item = li->boxItems, i = 0;
160
 
    while (item && item->data != key)
161
 
        item = item->next, i++;
162
 
 
163
 
    if (item)
164
 
        newtListboxSetCurrent(co, i);
165
 
}
166
 
 
167
 
void newtListboxSetCurrent(newtComponent co, int num)
168
 
{
169
 
    struct listbox * li = co->data;
170
 
 
171
 
    if (num >= li->numItems)
172
 
        li->currItem = li->numItems - 1;
173
 
    else if (num < 0)
174
 
        li->currItem = 0;
175
 
    else
176
 
        li->currItem = num;
177
 
 
178
 
    if (li->currItem < li->startShowItem)
179
 
        li->startShowItem = li->currItem;
180
 
    else if (li->currItem - li->startShowItem > li->curHeight - 1)
181
 
        li->startShowItem = li->currItem - li->curHeight + 1;
182
 
    if (li->startShowItem + li->curHeight > li->numItems)
183
 
        li->startShowItem = li->numItems - li->curHeight;
184
 
    if(li->startShowItem < 0)
185
 
        li->startShowItem = 0;
186
 
 
187
 
    newtListboxRealSetCurrent(co);
188
 
}
189
 
 
190
 
static void newtListboxRealSetCurrent(newtComponent co)
191
 
{
192
 
    struct listbox * li = co->data;
193
 
 
194
 
    if(li->sb)
195
 
        newtScrollbarSet(li->sb, li->currItem + 1, li->numItems);
196
 
    listboxDraw(co);
197
 
    if(co->callback) co->callback(co, co->callbackData);
198
 
}
199
 
 
200
 
void newtListboxSetWidth(newtComponent co, int width) {
201
 
    struct listbox * li = co->data;
202
 
 
203
 
    co->width = width;
204
 
    li->curWidth = co->width - li->sbAdjust - 2 * li->bdxAdjust;
205
 
    li->userHasSetWidth = 1;
206
 
    if (li->sb) li->sb->left = co->width + co->left - 1;
207
 
    listboxDraw(co);
208
 
}
209
 
 
210
 
void * newtListboxGetCurrent(newtComponent co) {
211
 
    struct listbox * li = co->data;
212
 
    int i;
213
 
    struct items *item;
214
 
 
215
 
    for(i = 0, item = li->boxItems; item != NULL && i < li->currItem;
216
 
        i++, item = item->next);
217
 
 
218
 
    if (item)
219
 
        return (void *)item->data;
220
 
    else
221
 
        return NULL;
222
 
}
223
 
 
224
 
void newtListboxSelectItem(newtComponent co, const void * key,
225
 
        enum newtFlagsSense sense)
226
 
{
227
 
    struct listbox * li = co->data;
228
 
    int i;
229
 
    struct items * item;
230
 
 
231
 
    item = li->boxItems, i = 0;
232
 
    while (item && item->data != key)
233
 
        item = item->next, i++;
234
 
 
235
 
    if (!item) return;
236
 
 
237
 
    if (item->isSelected)
238
 
        li->numSelected--;
239
 
 
240
 
    switch(sense) {
241
 
        case NEWT_FLAGS_RESET:
242
 
                item->isSelected = 0; break;
243
 
        case NEWT_FLAGS_SET:
244
 
                item->isSelected = 1; break;
245
 
        case NEWT_FLAGS_TOGGLE:
246
 
                item->isSelected = !item->isSelected;
247
 
    }
248
 
 
249
 
    if (item->isSelected)
250
 
        li->numSelected++;
251
 
 
252
 
    listboxDraw(co);
253
 
}
254
 
 
255
 
void newtListboxClearSelection(newtComponent co)
256
 
{
257
 
    struct items *item;
258
 
    struct listbox * li = co->data;
259
 
 
260
 
    for(item = li->boxItems; item != NULL;
261
 
        item = item->next)
262
 
        item->isSelected = 0;
263
 
    li->numSelected = 0;
264
 
    listboxDraw(co);
265
 
}
266
 
 
267
 
/* Free the returned array after use, but NOT the values in the array */
268
 
void ** newtListboxGetSelection(newtComponent co, int *numitems)
269
 
{
270
 
    struct listbox * li;
271
 
    int i;
272
 
    void **retval;
273
 
    struct items *item;
274
 
 
275
 
    if(!co || !numitems) return NULL;
276
 
 
277
 
    li = co->data;
278
 
    if(!li || !li->numSelected) return NULL;
279
 
 
280
 
    retval = malloc(li->numSelected * sizeof(void *));
281
 
    for(i = 0, item = li->boxItems; item != NULL;
282
 
        item = item->next)
283
 
        if(item->isSelected)
284
 
            retval[i++] = (void *)item->data;
285
 
    *numitems = li->numSelected;
286
 
    return retval;
287
 
}
288
 
 
289
 
void newtListboxSetEntry(newtComponent co, int num, const char * text) {
290
 
    struct listbox * li = co->data;
291
 
    int i;
292
 
    struct items *item;
293
 
 
294
 
    for(i = 0, item = li->boxItems; item != NULL && i < num;
295
 
        i++, item = item->next);
296
 
 
297
 
    if(!item)
298
 
        return;
299
 
    else {
300
 
        free(item->text);
301
 
        item->text = strdup(text);
302
 
    }
303
 
    if (li->userHasSetWidth == 0 && strwidth(text) > li->curWidth) {
304
 
        updateWidth(co, li, strwidth(text));
305
 
    }
306
 
 
307
 
    if (num >= li->startShowItem && num <= li->startShowItem + co->height)
308
 
        listboxDraw(co);
309
 
}
310
 
 
311
 
void newtListboxSetData(newtComponent co, int num, void * data) {
312
 
    struct listbox * li = co->data;
313
 
    int i;
314
 
    struct items *item;
315
 
 
316
 
    for(i = 0, item = li->boxItems; item != NULL && i < num;
317
 
        i++, item = item->next);
318
 
 
319
 
    item->data = data;
320
 
}
321
 
 
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 && (strwidth(text) > li->curWidth))
336
 
        updateWidth(co, li, strwidth(text));
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
 
 
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 && (strwidth(text) > li->curWidth))
376
 
        updateWidth(co, li, strwidth(text));
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
 
 
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 = strwidth(item->text)) > 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
 
 
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
 
 
455
 
/* If you don't want to get back the text, pass in NULL for the ptr-ptr. Same
456
 
   goes for the data. */
457
 
void newtListboxGetEntry(newtComponent co, int num, char **text, void **data) {
458
 
    struct listbox * li = co->data;
459
 
    int i;
460
 
    struct items *item;
461
 
 
462
 
    if (!li->boxItems || num >= li->numItems) {
463
 
        if(text)
464
 
            *text = NULL;
465
 
        if(data)
466
 
            *data = NULL;
467
 
        return;
468
 
    }
469
 
 
470
 
    i = 0;
471
 
    item = li->boxItems;
472
 
    while (item && i < num) {
473
 
        i++, item = item->next;
474
 
    }
475
 
 
476
 
    if (item) {
477
 
        if (text)
478
 
            *text = item->text;
479
 
        if (data)
480
 
            *data = (void *)item->data;
481
 
    }
482
 
}
483
 
 
484
 
static void listboxDraw(newtComponent co)
485
 
{
486
 
    struct listbox * li = co->data;
487
 
    struct items *item;
488
 
    int i, j;
489
 
    int xadj, yadj;
490
 
 
491
 
    if (!co->isMapped) return ;
492
 
 
493
 
    if(li->flags & NEWT_FLAG_BORDER) {
494
 
      if(li->isActive)
495
 
          newtColor(NEWT_COLORSET_ACTLISTBOX);
496
 
      else
497
 
          newtColor(NEWT_COLORSET_LISTBOX);
498
 
 
499
 
      newtColor(NEWT_COLORSET_BORDER);
500
 
      newtDrawBox(co->left, co->top, co->width, co->height, 0);
501
 
      xadj = 1;
502
 
      yadj = 1;
503
 
    }
504
 
    else {
505
 
      xadj = 0;
506
 
      yadj = 0;
507
 
    }
508
 
 
509
 
    if(li->sb)
510
 
        li->sb->ops->draw(li->sb);
511
 
 
512
 
    newtColor(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
 
                newtColor(NEWT_COLORSET_ACTSELLISTBOX);
526
 
            else
527
 
                newtColor(NEWT_COLORSET_SELLISTBOX);
528
 
        } else if(li->isActive)
529
 
            newtColor(NEWT_COLORSET_ACTLISTBOX);
530
 
        else
531
 
            newtColor(NEWT_COLORSET_LISTBOX);
532
 
 
533
 
        SLsmg_write_nstring(item->text, li->curWidth);
534
 
 
535
 
    }
536
 
    newtGotorc(co->top + yadj + (li->currItem - li->startShowItem), co->left + xadj);
537
 
}
538
 
 
539
 
static struct eventResult listboxEvent(newtComponent co, struct event ev) {
540
 
    struct eventResult er;
541
 
    struct listbox * li = co->data;
542
 
    struct items *item;
543
 
    int i;
544
 
    
545
 
    er.result = ER_IGNORED;
546
 
 
547
 
    if(ev.when == EV_EARLY || ev.when == EV_LATE) {
548
 
        return er;
549
 
    }
550
 
 
551
 
    switch(ev.event) {
552
 
      case EV_KEYPRESS:
553
 
        if (!li->isActive) break;
554
 
 
555
 
        switch(ev.u.key) {
556
 
          case ' ':
557
 
            if(!(li->flags & NEWT_FLAG_MULTIPLE)) break;
558
 
            newtListboxSelectItem(co, li->boxItems[li->currItem].data,
559
 
                                  NEWT_FLAGS_TOGGLE);
560
 
            er.result = ER_SWALLOWED;
561
 
            /* We don't break here, because it is cool to be able to
562
 
               hold space to select a bunch of items in a list at once */
563
 
 
564
 
          case NEWT_KEY_DOWN:
565
 
            if(li->numItems <= 0) break;
566
 
            if(li->currItem < li->numItems - 1) {
567
 
                li->currItem++;
568
 
                if(li->currItem > (li->startShowItem + li->curHeight - 1)) {
569
 
                    li->startShowItem = li->currItem - li->curHeight + 1;
570
 
                    if(li->startShowItem + li->curHeight > li->numItems)
571
 
                        li->startShowItem = li->numItems - li->curHeight;
572
 
                }
573
 
                if(li->sb)
574
 
                    newtScrollbarSet(li->sb, li->currItem + 1, li->numItems);
575
 
                listboxDraw(co);
576
 
            }
577
 
            if(co->callback) co->callback(co, co->callbackData);
578
 
            er.result = ER_SWALLOWED;
579
 
            break;
580
 
 
581
 
          case NEWT_KEY_ENTER:
582
 
            if(li->numItems <= 0) break;
583
 
            if(li->flags & NEWT_FLAG_RETURNEXIT)
584
 
                er.result = ER_EXITFORM;
585
 
            break;
586
 
 
587
 
          case NEWT_KEY_UP:
588
 
            if(li->numItems <= 0) break;
589
 
            if(li->currItem > 0) {
590
 
                li->currItem--;
591
 
                if(li->currItem < li->startShowItem)
592
 
                    li->startShowItem = li->currItem;
593
 
                if(li->sb)
594
 
                    newtScrollbarSet(li->sb, li->currItem + 1, li->numItems);
595
 
                listboxDraw(co);
596
 
            }
597
 
            if(co->callback) co->callback(co, co->callbackData);
598
 
            er.result = ER_SWALLOWED;
599
 
            break;
600
 
 
601
 
          case NEWT_KEY_PGUP:
602
 
            if(li->numItems <= 0) break;
603
 
            li->startShowItem -= li->curHeight - 1;
604
 
            if(li->startShowItem < 0)
605
 
                li->startShowItem = 0;
606
 
            li->currItem -= li->curHeight - 1;
607
 
            if(li->currItem < 0)
608
 
                li->currItem = 0;
609
 
            newtListboxRealSetCurrent(co);
610
 
            er.result = ER_SWALLOWED;
611
 
            break;
612
 
 
613
 
          case NEWT_KEY_PGDN:
614
 
            if(li->numItems <= 0) break;
615
 
            li->startShowItem += li->curHeight;
616
 
            if(li->startShowItem > (li->numItems - li->curHeight)) {
617
 
                li->startShowItem = li->numItems - li->curHeight;
618
 
            }
619
 
            li->currItem += li->curHeight;
620
 
            if(li->currItem >= li->numItems) {
621
 
                li->currItem = li->numItems - 1;
622
 
            }
623
 
            newtListboxRealSetCurrent(co);
624
 
            er.result = ER_SWALLOWED;
625
 
            break;
626
 
 
627
 
          case NEWT_KEY_HOME:
628
 
            if(li->numItems <= 0) break;
629
 
            newtListboxSetCurrent(co, 0);
630
 
            er.result = ER_SWALLOWED;
631
 
            break;
632
 
 
633
 
          case NEWT_KEY_END:
634
 
            if(li->numItems <= 0) break;
635
 
            li->startShowItem = li->numItems - li->curHeight;
636
 
            if(li->startShowItem < 0)
637
 
                li->startShowItem = 0;
638
 
            li->currItem = li->numItems - 1;
639
 
            newtListboxRealSetCurrent(co);
640
 
            er.result = ER_SWALLOWED;
641
 
            break;
642
 
          default:
643
 
              if (li->numItems <= 0) break;
644
 
              if (ev.u.key < NEWT_KEY_EXTRA_BASE && isalpha(ev.u.key)) {
645
 
                  for(i = 0, item = li->boxItems; item != NULL &&
646
 
                          i < li->currItem; i++, item = item->next);
647
 
 
648
 
                  if (item && item->text && (toupper(*item->text) == toupper(ev.u.key))) {
649
 
                      item = item->next;
650
 
                      i++;
651
 
                  } else { 
652
 
                      item = li->boxItems;
653
 
                      i = 0;
654
 
                  }
655
 
                  while (item && item->text &&
656
 
                         toupper(*item->text) != toupper(ev.u.key)) {
657
 
                      item = item->next;
658
 
                      i++;
659
 
                  }
660
 
                  if (item) {
661
 
                      li->currItem = i;
662
 
                      if(li->currItem < li->startShowItem ||
663
 
                         li->currItem > li->startShowItem)
664
 
                          li->startShowItem =
665
 
                              li->currItem > li->numItems - li->curHeight ?
666
 
                              li->startShowItem = li->numItems - li->curHeight :
667
 
                              li->currItem;
668
 
                      if(li->sb)
669
 
                          newtScrollbarSet(li->sb, li->currItem + 1, li->numItems);
670
 
                      newtListboxRealSetCurrent(co);
671
 
                      er.result = ER_SWALLOWED;
672
 
                  }
673
 
              }
674
 
        }
675
 
        break;
676
 
 
677
 
      case EV_FOCUS:
678
 
        li->isActive = 1;
679
 
        listboxDraw(co);
680
 
        er.result = ER_SWALLOWED;
681
 
        break;
682
 
 
683
 
      case EV_UNFOCUS:
684
 
        li->isActive = 0;
685
 
        listboxDraw(co);
686
 
        er.result = ER_SWALLOWED;
687
 
        break;
688
 
 
689
 
      case EV_MOUSE:
690
 
          /* if this mouse click was within the listbox, make the current
691
 
             item the item clicked on. */
692
 
        /* Up scroll arrow */
693
 
        if (li->sb &&
694
 
            ev.u.mouse.x == co->left + co->width - li->bdxAdjust - 1 &&
695
 
            ev.u.mouse.y == co->top + li->bdyAdjust) {
696
 
            if(li->numItems <= 0) break;
697
 
            if(li->currItem > 0) {
698
 
                li->currItem--;
699
 
                if(li->currItem < li->startShowItem)
700
 
                    li->startShowItem = li->currItem;
701
 
                if(li->sb)
702
 
                    newtScrollbarSet(li->sb, li->currItem + 1, li->numItems);
703
 
                listboxDraw(co);
704
 
            }
705
 
            if(co->callback) co->callback(co, co->callbackData);
706
 
            er.result = ER_SWALLOWED;
707
 
            break;
708
 
        }
709
 
        /* Down scroll arrow */
710
 
        if (li->sb &&
711
 
            ev.u.mouse.x == co->left + co->width - li->bdxAdjust - 1 &&
712
 
            ev.u.mouse.y == co->top + co->height - li->bdyAdjust - 1) {
713
 
            if(li->numItems <= 0) break;
714
 
            if(li->currItem < li->numItems - 1) {
715
 
                li->currItem++;
716
 
                if(li->currItem > (li->startShowItem + li->curHeight - 1)) {
717
 
                    li->startShowItem = li->currItem - li->curHeight + 1;
718
 
                    if(li->startShowItem + li->curHeight > li->numItems)
719
 
                        li->startShowItem = li->numItems - li->curHeight;
720
 
                }
721
 
                if(li->sb)
722
 
                    newtScrollbarSet(li->sb, li->currItem + 1, li->numItems);
723
 
                listboxDraw(co);
724
 
            }
725
 
            if(co->callback) co->callback(co, co->callbackData);
726
 
            er.result = ER_SWALLOWED;
727
 
            break;
728
 
        }
729
 
        if ((ev.u.mouse.y >= co->top + li->bdyAdjust) &&
730
 
            (ev.u.mouse.y <= co->top + co->height - (li->bdyAdjust * 2)) &&
731
 
            (ev.u.mouse.x >= co->left + li->bdxAdjust) &&
732
 
            (ev.u.mouse.x <= co->left + co->width + (li->bdxAdjust * 2))) {
733
 
            li->currItem = li->startShowItem +
734
 
                (ev.u.mouse.y - li->bdyAdjust - co->top);
735
 
            newtListboxRealSetCurrent(co);
736
 
            listboxDraw(co);
737
 
            if(co->callback) co->callback(co, co->callbackData);
738
 
            er.result = ER_SWALLOWED;
739
 
            break;
740
 
        }
741
 
    }
742
 
 
743
 
    return er;
744
 
}
745
 
 
746
 
static void listboxDestroy(newtComponent co) {
747
 
    struct listbox * li = co->data;
748
 
    struct items * item, * nextitem;
749
 
 
750
 
    nextitem = item = li->boxItems;
751
 
 
752
 
    while (item != NULL) {
753
 
        nextitem = item->next;
754
 
        free(item->text);
755
 
        free(item);
756
 
        item = nextitem;
757
 
    }
758
 
 
759
 
    if (li->sb) li->sb->ops->destroy(li->sb);
760
 
 
761
 
    free(li);
762
 
    free(co);
763
 
}