~ubuntu-branches/ubuntu/vivid/newt/vivid

« back to all changes in this revision

Viewing changes to checkboxtree.c

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2012-11-08 14:50:00 UTC
  • mfrom: (2.1.20 sid)
  • Revision ID: package-import@ubuntu.com-20121108145000-0yfrol7obct0jufq
Tags: 0.52.14-11ubuntu1
* Merge with Debian; remaining changes:
  - Port python module to python3.
  - Fix installation for multiple python3 versions.
  - Move libnewt to /lib and whiptail to /bin so they can be used by
    friendly-recovery on systems that have a separate /usr.
  - debian/libnewt0.52.install, debian/libnewt0.52.postinst,
    debian/palette => debian/palette.original:
    - move palette from /usr to /etc such that they can be edited by an
      admin.
* Configure --with-colorsfile=/etc/newt/palette.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <slang.h>
 
2
#include <stdlib.h>
 
3
#include <string.h>
 
4
 
 
5
#include "newt.h"
 
6
#include "newt_pr.h"
 
7
 
 
8
struct items {
 
9
    char * text;
 
10
    const void *data;
 
11
    unsigned char selected;
 
12
    struct items *next;
 
13
    struct items *prev;
 
14
    struct items *branch;
 
15
    int flags;
 
16
    int depth;
 
17
};
 
18
 
 
19
struct CheckboxTree {
 
20
    newtComponent sb;
 
21
    struct items * itemlist;
 
22
    struct items ** flatList, ** currItem, ** firstItem;
 
23
    int flatCount;
 
24
    int flags;
 
25
    int sbAdjust;
 
26
    int curWidth;
 
27
    int userHasSetWidth;
 
28
    int isActive;
 
29
    char * seq;
 
30
    char * result;
 
31
};
 
32
 
 
33
static void ctDraw(newtComponent c);
 
34
static void ctDestroy(newtComponent co);
 
35
static void ctPlace(newtComponent co, int newLeft, int newTop);
 
36
struct eventResult ctEvent(newtComponent co, struct event ev);
 
37
static void ctMapped(newtComponent co, int isMapped);
 
38
static struct items * findItem(struct items * items, const void * data);
 
39
static void buildFlatList(newtComponent co);
 
40
static void doBuildFlatList(struct CheckboxTree * ct, struct items * item);
 
41
static int countItems(struct items * item, int what);
 
42
static inline void updateWidth(newtComponent co, struct CheckboxTree * ct,
 
43
                                int maxField);
 
44
 
 
45
static struct componentOps ctOps = {
 
46
    ctDraw,
 
47
    ctEvent,
 
48
    ctDestroy,
 
49
    ctPlace,
 
50
    ctMapped,
 
51
} ;
 
52
 
 
53
static inline void updateWidth(newtComponent co, struct CheckboxTree * ct,
 
54
                                int maxField) {
 
55
    ct->curWidth = maxField;
 
56
    co->width = ct->curWidth + ct->sbAdjust;
 
57
 
 
58
    if (ct->sb)
 
59
        ct->sb->left = co->left + co->width - 1;
 
60
}
 
61
 
 
62
static int countItems(struct items * item, int what) {
 
63
    int count = 0;
 
64
 
 
65
    while (item) {
 
66
        if (what < 0 || (!item->branch && ((what > 0 && item->selected == what)
 
67
                    || (what == 0 && item->selected))))
 
68
            count++;
 
69
        if (item->branch && (what >= 0 || (what < 0 && item->selected)))
 
70
            count += countItems(item->branch, what);
 
71
        item = item->next;
 
72
    }
 
73
 
 
74
    return count;
 
75
}
 
76
 
 
77
static void doBuildFlatList(struct CheckboxTree * ct, struct items * item) {
 
78
    while (item) {
 
79
        ct->flatList[ct->flatCount++] = item;
 
80
        if (item->branch && item->selected) doBuildFlatList(ct, item->branch);
 
81
        item = item->next;
 
82
    }
 
83
}
 
84
 
 
85
/* FIXME: Check what happens on malloc failure.
 
86
 */
 
87
static void buildFlatList(newtComponent co) {
 
88
    struct CheckboxTree * ct = co->data;
 
89
 
 
90
    if (ct->flatList) free(ct->flatList);
 
91
    ct->flatCount = countItems(ct->itemlist, -1);
 
92
 
 
93
    ct->flatList = malloc(sizeof(*ct->flatList) * (ct->flatCount+1));
 
94
    ct->flatCount = 0;
 
95
    doBuildFlatList(ct, ct->itemlist);
 
96
    ct->flatList[ct->flatCount] = NULL;
 
97
}
 
98
 
 
99
int newtCheckboxTreeAddItem(newtComponent co, 
 
100
                            const char * text, const void * data,
 
101
                            int flags, int index, ...) {
 
102
    va_list argList;
 
103
    int numIndexes;
 
104
    int * indexes;
 
105
    int i;
 
106
 
 
107
    va_start(argList, index);
 
108
    numIndexes = 0;
 
109
    i = index;
 
110
    while (i != NEWT_ARG_LAST) {
 
111
        numIndexes++;
 
112
        i = va_arg(argList, int);
 
113
    }
 
114
 
 
115
    va_end(argList);
 
116
 
 
117
    indexes = alloca(sizeof(*indexes) * (numIndexes + 1));
 
118
    va_start(argList, index);
 
119
    numIndexes = 0;
 
120
    i = index;
 
121
    while (i != NEWT_ARG_LAST) {
 
122
        indexes[numIndexes++] = i;
 
123
        i = va_arg(argList, int);
 
124
    }
 
125
    va_end(argList);
 
126
 
 
127
    indexes[numIndexes++] = NEWT_ARG_LAST;
 
128
 
 
129
    return newtCheckboxTreeAddArray(co, text, data, flags, indexes);
 
130
}
 
131
 
 
132
static int doFindItemPath(struct items * items, void * data, int * path, 
 
133
                          int * len) {
 
134
    int where = 0;
 
135
 
 
136
    while (items) {
 
137
        if (items->data == data) {
 
138
            if (path) path[items->depth] = where;
 
139
            if (len) *len = items->depth + 1;
 
140
            return 1;
 
141
        }
 
142
 
 
143
        if (items->branch && doFindItemPath(items->branch, data, path, len)) {
 
144
            if (path) path[items->depth] = where;
 
145
            return 1;
 
146
        }
 
147
 
 
148
        items = items->next;
 
149
        where++;
 
150
    }
 
151
 
 
152
    return 0;
 
153
}
 
154
 
 
155
int * newtCheckboxTreeFindItem(newtComponent co, void * data) {
 
156
    int len;
 
157
    int * path;
 
158
    struct CheckboxTree * ct = co->data;
 
159
 
 
160
    if (!doFindItemPath(ct->itemlist, data, NULL, &len)) return NULL;
 
161
 
 
162
    path = malloc(sizeof(*path) * (len + 1));
 
163
    doFindItemPath(ct->itemlist, data, path, NULL);
 
164
    path[len] = NEWT_ARG_LAST;
 
165
 
 
166
    return path;
 
167
}
 
168
 
 
169
int newtCheckboxTreeAddArray(newtComponent co, 
 
170
                            const char * text, const void * data,
 
171
                            int flags, int * indexes) {
 
172
    struct items * curList, * newNode, * item = NULL;
 
173
    struct items ** listPtr = NULL;
 
174
    int i, index, numIndexes, width;
 
175
    struct CheckboxTree * ct = co->data;
 
176
 
 
177
    numIndexes = 0;
 
178
    while (indexes[numIndexes] != NEWT_ARG_LAST) numIndexes++;
 
179
 
 
180
    if (!ct->itemlist) {
 
181
        if (numIndexes > 1) return -1;
 
182
 
 
183
        ct->itemlist = malloc(sizeof(*ct->itemlist)); // FIXME: Error check?
 
184
        item = ct->itemlist;
 
185
        item->prev = NULL;
 
186
        item->next = NULL;
 
187
    } else {
 
188
        curList = ct->itemlist;
 
189
        listPtr = &ct->itemlist;
 
190
 
 
191
        i = 0;
 
192
        index = indexes[i];
 
193
        while (i < numIndexes) {
 
194
            item = curList;
 
195
 
 
196
            if (index == NEWT_ARG_APPEND) {
 
197
                item = NULL;
 
198
            } else {
 
199
                while (index && item) 
 
200
                    item = item->next, index--;
 
201
            }
 
202
 
 
203
            i++;
 
204
            if (i < numIndexes) {
 
205
                if (item == NULL)
 
206
                        return -1;
 
207
                curList = item->branch;
 
208
                listPtr = &item->branch;
 
209
                if (!curList && (i + 1 != numIndexes)) return -1;
 
210
 
 
211
                index = indexes[i];
 
212
            }
 
213
        }
 
214
 
 
215
        if (!curList) {                         /* create a new branch */
 
216
            item = malloc(sizeof(*curList->prev));
 
217
            item->next = item->prev = NULL;
 
218
            *listPtr = item;
 
219
        } else if (!item) {                     /* append to end */
 
220
            item = curList;
 
221
            while (item->next) item = item->next;
 
222
            item->next = malloc(sizeof(*curList->prev)); // FIXME Error check
 
223
            item->next->prev = item;
 
224
            item = item->next;
 
225
            item->next = NULL;
 
226
        } else { 
 
227
            newNode = malloc(sizeof(*newNode)); // FIXME Error check ? 
 
228
            newNode->prev = item->prev;
 
229
            newNode->next = item;
 
230
 
 
231
            if (item->prev) item->prev->next = newNode;
 
232
            item->prev = newNode;
 
233
            item = newNode;
 
234
            if (!item->prev) *listPtr = item;
 
235
        }
 
236
    }
 
237
        
 
238
    item->text = strdup(text);
 
239
    item->data = data;
 
240
    if (flags & NEWT_FLAG_SELECTED) {
 
241
        item->selected = 1;
 
242
    } else {
 
243
        item->selected = 0;
 
244
    }
 
245
    item->flags = flags;
 
246
    item->branch = NULL;
 
247
    item->depth = numIndexes - 1;
 
248
 
 
249
    i = 4 + (3 * item->depth);
 
250
    width = wstrlen(text, -1);
 
251
 
 
252
    if ((ct->userHasSetWidth == 0) && ((width + i + ct->sbAdjust) > co->width)) {
 
253
        updateWidth(co, ct, width + i);
 
254
    }
 
255
 
 
256
    return 0;
 
257
}
 
258
 
 
259
static struct items * findItem(struct items * items, const void * data) {
 
260
    struct items * i;
 
261
 
 
262
    while (items) {
 
263
        if (items->data == data) return items;
 
264
        if (items->branch) {
 
265
            i = findItem(items->branch, data);
 
266
            if (i) return i;
 
267
        }
 
268
 
 
269
        items = items->next;
 
270
    }
 
271
 
 
272
    return NULL;
 
273
}
 
274
 
 
275
static void listSelected(struct items * items, int * num, const void ** list, int seqindex) {
 
276
    while (items) {
 
277
        if ((seqindex ? items->selected==seqindex : items->selected) && !items->branch)
 
278
            list[(*num)++] = (void *) items->data;
 
279
        if (items->branch)
 
280
            listSelected(items->branch, num, list, seqindex);
 
281
        items = items->next;
 
282
    }
 
283
}
 
284
 
 
285
void newtCheckboxTreeSetWidth(newtComponent co, int width) {
 
286
    struct CheckboxTree * ct = co->data;
 
287
 
 
288
    co->width = width;
 
289
    ct->curWidth = co->width - ct->sbAdjust;
 
290
    ct->userHasSetWidth = 1;
 
291
    if (ct->sb) ct->sb->left = co->width + co->left - 1;
 
292
    ctDraw(co);
 
293
}
 
294
 
 
295
const void ** newtCheckboxTreeGetSelection(newtComponent co, int *numitems)
 
296
{
 
297
    return newtCheckboxTreeGetMultiSelection(co, numitems, 0);
 
298
}
 
299
 
 
300
const void ** newtCheckboxTreeGetMultiSelection(newtComponent co, int *numitems, char seqnum)
 
301
{
 
302
    struct CheckboxTree * ct;
 
303
    const void **retval;
 
304
    int seqindex=0;
 
305
 
 
306
    if(!co || !numitems) return NULL;
 
307
 
 
308
    ct = co->data;
 
309
        
 
310
    if (seqnum) {
 
311
            while( ct->seq[seqindex] && ( ct->seq[seqindex] != seqnum )) seqindex++;
 
312
    } else {
 
313
            seqindex = 0;
 
314
    }
 
315
 
 
316
    *numitems = countItems(ct->itemlist, seqindex);
 
317
    if (!*numitems) return NULL;
 
318
    
 
319
    retval = malloc(*numitems * sizeof(void *));
 
320
    *numitems = 0;
 
321
    listSelected(ct->itemlist, numitems, retval, seqindex);
 
322
 
 
323
    return retval;
 
324
}
 
325
 
 
326
newtComponent newtCheckboxTree(int left, int top, int height, int flags) {
 
327
        return newtCheckboxTreeMulti(left, top, height, NULL, flags);
 
328
}
 
329
 
 
330
newtComponent newtCheckboxTreeMulti(int left, int top, int height, char *seq, int flags) {
 
331
    newtComponent co;
 
332
    struct CheckboxTree * ct;
 
333
 
 
334
    co = malloc(sizeof(*co));
 
335
    ct = malloc(sizeof(struct CheckboxTree));
 
336
    co->callback = NULL;
 
337
    co->destroyCallback = NULL;
 
338
    co->data = ct;
 
339
    co->left = left;
 
340
    co->top = top;
 
341
    co->ops = &ctOps;
 
342
    co->takesFocus = 1;
 
343
    co->height = height;
 
344
    co->width = 0;
 
345
    co->isMapped = 0;
 
346
    ct->curWidth = 0;
 
347
    ct->isActive = 0;
 
348
    ct->userHasSetWidth = 0;
 
349
    ct->itemlist = NULL;
 
350
    ct->firstItem = NULL;
 
351
    ct->currItem = NULL;
 
352
    ct->flatList = NULL;
 
353
 
 
354
    ct->flags = flags;
 
355
 
 
356
    if (seq)
 
357
        ct->seq = strdup(seq);
 
358
    else
 
359
        ct->seq = strdup(" *");
 
360
    if (flags & NEWT_FLAG_SCROLL) {
 
361
        ct->sb = newtVerticalScrollbar(left, top, height,
 
362
                                       COLORSET_LISTBOX, COLORSET_ACTLISTBOX);
 
363
        ct->sbAdjust = 2;
 
364
    } else {
 
365
        ct->sb = NULL;
 
366
        ct->sbAdjust = 0;
 
367
    }
 
368
    
 
369
    return co;
 
370
}
 
371
 
 
372
static void ctMapped(newtComponent co, int isMapped) {
 
373
    struct CheckboxTree * ct = co->data;
 
374
 
 
375
    co->isMapped = isMapped;
 
376
    if (ct->sb)
 
377
        ct->sb->ops->mapped(ct->sb, isMapped);
 
378
}
 
379
 
 
380
static void ctPlace(newtComponent co, int newLeft, int newTop) {
 
381
    struct CheckboxTree * ct = co->data;
 
382
 
 
383
    co->top = newTop;
 
384
    co->left = newLeft;
 
385
 
 
386
    if (ct->sb)
 
387
        ct->sb->ops->place(ct->sb, co->left + co->width - 1, co->top);
 
388
}
 
389
 
 
390
int ctSetItem(newtComponent co, struct items *item, enum newtFlagsSense sense)
 
391
{
 
392
    struct CheckboxTree * ct = co->data;
 
393
    struct items * currItem;
 
394
    struct items * firstItem;
 
395
    
 
396
    if (!item)
 
397
        return 1;
 
398
    
 
399
    switch(sense) {
 
400
        case NEWT_FLAGS_RESET:
 
401
            item->selected = 0;
 
402
            break;
 
403
        case NEWT_FLAGS_SET:
 
404
            item->selected = 1;
 
405
            break;
 
406
        case NEWT_FLAGS_TOGGLE:
 
407
            if (item->branch)
 
408
              item->selected = !item->selected;
 
409
            else if (!(ct->flags & NEWT_CHECKBOXTREE_UNSELECTABLE)) {
 
410
                    item->selected++;
 
411
                    if (item->selected==strlen(ct->seq))
 
412
                      item->selected = 0;
 
413
            }
 
414
            break;
 
415
    }
 
416
 
 
417
    if (item->branch) {
 
418
        currItem = *ct->currItem;
 
419
        firstItem = *ct->firstItem;
 
420
 
 
421
        buildFlatList(co);
 
422
 
 
423
        ct->currItem = ct->flatList;
 
424
        while (*ct->currItem != currItem) ct->currItem++;
 
425
 
 
426
        ct->firstItem = ct->flatList;
 
427
        if (ct->flatCount > co->height) {
 
428
                struct items ** last = ct->flatList + ct->flatCount - co->height;
 
429
                while (*ct->firstItem != firstItem && ct->firstItem != last)
 
430
                    ct->firstItem++;
 
431
        }
 
432
    }
 
433
 
 
434
    return 0;
 
435
}
 
436
 
 
437
static void ctSetItems(struct items *item, int selected)
 
438
{
 
439
    for (; item; item = item->next) {
 
440
        if (!item->branch)
 
441
            item->selected = selected;
 
442
        else
 
443
            ctSetItems(item->branch, selected);
 
444
    }
 
445
}
 
446
 
 
447
static void ctDraw(newtComponent co) {
 
448
    struct CheckboxTree * ct = co->data;
 
449
    struct items ** item; 
 
450
    int i, j;
 
451
    char * spaces;
 
452
    int currRow = co->top;
 
453
 
 
454
    if (!co->isMapped) return ;
 
455
 
 
456
    if (!ct->firstItem) {
 
457
        buildFlatList(co);
 
458
        ct->firstItem = ct->currItem = ct->flatList;
 
459
    }
 
460
 
 
461
    item = ct->firstItem;
 
462
    
 
463
    i = 0;
 
464
 
 
465
    newtTrashScreen();
 
466
    
 
467
    while (*item && i < co->height) {
 
468
        newtGotorc(co->top + i, co->left);
 
469
        SLsmg_set_color(NEWT_COLORSET_LISTBOX);
 
470
        for (j = 0; j < (*item)->depth; j++)
 
471
            SLsmg_write_string("   ");
 
472
 
 
473
        if ((*item)->branch) {
 
474
            if ((*item)->selected) 
 
475
                SLsmg_write_string("<-> ");
 
476
            else
 
477
                SLsmg_write_string("<+> ");
 
478
        } else {
 
479
            if (ct->flags & NEWT_CHECKBOXTREE_HIDE_BOX) {
 
480
                if ((*item)->selected)
 
481
                    SLsmg_set_color(NEWT_COLORSET_SELLISTBOX);
 
482
                SLsmg_write_string("    ");
 
483
            } else {
 
484
                char tmp[5];
 
485
                snprintf(tmp,5,"[%c] ",ct->seq[(*item)->selected]);
 
486
                SLsmg_write_string(tmp);
 
487
            }
 
488
        }
 
489
        if (*item == *ct->currItem) {
 
490
            SLsmg_set_color(ct->isActive ?
 
491
                    NEWT_COLORSET_ACTSELLISTBOX : NEWT_COLORSET_ACTLISTBOX);
 
492
            currRow = co->top + i;
 
493
        }
 
494
 
 
495
        write_nstring_int((*item)->text, co->width - 4 - (3 * (*item)->depth), NULL);
 
496
 
 
497
        item++;
 
498
        i++;
 
499
    }
 
500
 
 
501
    /* There could be empty lines left (i.e. if the user closes an expanded
 
502
       list which is the last thing in the tree, and whose elements are
 
503
       displayed at the bottom of the screen */
 
504
    if (i < co->height) {
 
505
        spaces = alloca(co->width + 1);
 
506
        memset(spaces, ' ', co->width);
 
507
        spaces[co->width] = '\0';
 
508
        SLsmg_set_color(NEWT_COLORSET_LISTBOX);
 
509
 
 
510
        while (i < co->height) {
 
511
            newtGotorc(co->top + i, co->left);
 
512
            SLsmg_write_nstring(spaces, co->width);
 
513
            i++;
 
514
        }
 
515
    }
 
516
    
 
517
    if(ct->sb) {
 
518
        newtScrollbarSet(ct->sb, ct->currItem - ct->flatList, 
 
519
                         ct->flatCount - 1);
 
520
        ct->sb->ops->draw(ct->sb);
 
521
    }
 
522
 
 
523
    newtGotorc(currRow, co->left + 
 
524
                    (*ct->currItem ? (*ct->currItem)->depth : 0) * 3 + 4);
 
525
}
 
526
 
 
527
static void destroyItems(struct items * item) {
 
528
    struct items * nextitem;
 
529
 
 
530
    while (item != NULL) {
 
531
        nextitem = item->next;
 
532
        free(item->text);
 
533
        if (item->branch)
 
534
            destroyItems(item->branch);
 
535
        free(item);
 
536
        item = nextitem;
 
537
    }
 
538
}
 
539
 
 
540
static void ctDestroy(newtComponent co) {
 
541
    struct CheckboxTree * ct = co->data;
 
542
 
 
543
    destroyItems(ct->itemlist);
 
544
    free(ct->flatList);
 
545
    if (ct->sb)
 
546
        ct->sb->ops->destroy(ct->sb);
 
547
    free(ct->seq);
 
548
    free(ct);
 
549
    free(co);
 
550
}
 
551
 
 
552
static void ctEnsureLimits( struct CheckboxTree *ct ) {
 
553
    struct items **listEnd = ct->flatList + ct->flatCount - 1;
 
554
    if (ct->firstItem < ct->flatList)
 
555
        ct->firstItem = ct->flatList;
 
556
    if (ct->currItem < ct->flatList)
 
557
        ct->currItem = ct->flatList;
 
558
    if (ct->firstItem > listEnd) {
 
559
        ct->firstItem = listEnd;
 
560
        ct->currItem = listEnd;
 
561
    }
 
562
}
 
563
 
 
564
struct eventResult ctEvent(newtComponent co, struct event ev) {
 
565
    struct CheckboxTree * ct = co->data;
 
566
    struct eventResult er;
 
567
    struct items ** listEnd, ** lastItem;
 
568
    int key, selnum = 1;
 
569
 
 
570
    er.result = ER_IGNORED;
 
571
 
 
572
    if(ev.when == EV_EARLY || ev.when == EV_LATE) {
 
573
        return er;
 
574
    }
 
575
 
 
576
    switch(ev.event) {
 
577
    case EV_KEYPRESS:
 
578
        key = ev.u.key;
 
579
        if (key == (char) key && key != ' ') {
 
580
            for (selnum = 0; ct->seq[selnum]; selnum++)
 
581
            if (key == ct->seq[selnum])
 
582
                break;
 
583
            if (!ct->seq[selnum])
 
584
                switch (key) {
 
585
                case '-': selnum = 0; break;
 
586
                case '+':
 
587
                case '*': selnum = 1; break;
 
588
                }
 
589
            if (ct->seq[selnum])
 
590
                key = '*';
 
591
        }
 
592
        switch(key) {
 
593
        case ' ':
 
594
        case NEWT_KEY_ENTER:
 
595
            ctSetItem(co, *ct->currItem, NEWT_FLAGS_TOGGLE);
 
596
            er.result = ER_SWALLOWED;
 
597
            if (!(*ct->currItem)->branch || (*ct->currItem)->selected)
 
598
                key = NEWT_KEY_DOWN;
 
599
            else
 
600
                key = '*';
 
601
            break;
 
602
        case '*':
 
603
            if ((*ct->currItem)->branch) {
 
604
                ctSetItems((*ct->currItem)->branch, selnum);
 
605
                if (!(*ct->currItem)->selected)
 
606
                    key = NEWT_KEY_DOWN;
 
607
            } else {
 
608
                (*ct->currItem)->selected = selnum;
 
609
                key = NEWT_KEY_DOWN;
 
610
            }
 
611
            er.result = ER_SWALLOWED;
 
612
            break;
 
613
        }
 
614
        switch (key) {
 
615
        case '*':
 
616
            ctDraw(co);
 
617
            if(co->callback) co->callback(co, co->callbackData);
 
618
            return er;
 
619
        case NEWT_KEY_HOME:
 
620
            ct->currItem = ct->flatList;
 
621
            ct->firstItem = ct->flatList;
 
622
            ctDraw(co);
 
623
            if(co->callback) co->callback(co, co->callbackData);
 
624
            er.result = ER_SWALLOWED;
 
625
            return er;
 
626
        case NEWT_KEY_END:
 
627
            ct->currItem = ct->flatList + ct->flatCount - 1;
 
628
            if (ct->flatCount <= co->height)
 
629
                ct->firstItem = ct->flatList;
 
630
            else
 
631
                ct->firstItem = ct->flatList + ct->flatCount - co->height;
 
632
            ctDraw(co);
 
633
            if(co->callback) co->callback(co, co->callbackData);
 
634
            er.result = ER_SWALLOWED;
 
635
            return er;
 
636
        case NEWT_KEY_DOWN:
 
637
            if (ev.u.key != NEWT_KEY_DOWN) {
 
638
                if(co->callback) co->callback(co, co->callbackData);
 
639
                if (strlen(ct->seq) != 2) {
 
640
                    ctDraw(co);
 
641
                    return er;
 
642
                }
 
643
            }
 
644
            if ((ct->currItem - ct->flatList + 1) < ct->flatCount) {
 
645
                ct->currItem++;
 
646
 
 
647
                if (ct->currItem - ct->firstItem >= co->height) 
 
648
                    ct->firstItem++;
 
649
 
 
650
                ctDraw(co);
 
651
            } else if (ev.u.key != NEWT_KEY_DOWN)
 
652
                ctDraw(co);
 
653
            if(co->callback) co->callback(co, co->callbackData);
 
654
            er.result = ER_SWALLOWED;
 
655
            return er;
 
656
        case NEWT_KEY_UP:
 
657
            if (ct->currItem != ct->flatList) {
 
658
                ct->currItem--;
 
659
 
 
660
                if (ct->currItem < ct->firstItem)
 
661
                    ct->firstItem = ct->currItem;
 
662
                    
 
663
                ctDraw(co);
 
664
            }
 
665
            er.result = ER_SWALLOWED;
 
666
            if(co->callback) co->callback(co, co->callbackData);
 
667
            return er;
 
668
        case NEWT_KEY_PGUP:
 
669
            if (ct->firstItem - co->height < ct->flatList) {
 
670
                ct->firstItem = ct->currItem = ct->flatList;
 
671
            } else {
 
672
                ct->currItem -= co->height;
 
673
                ct->firstItem -= co->height;
 
674
            }
 
675
            ctEnsureLimits( ct );
 
676
 
 
677
            ctDraw(co);
 
678
            if(co->callback) co->callback(co, co->callbackData);
 
679
            er.result = ER_SWALLOWED;
 
680
            return er;
 
681
        case NEWT_KEY_PGDN:
 
682
            listEnd = ct->flatList + ct->flatCount - 1;
 
683
            lastItem = ct->firstItem + co->height - 1;
 
684
 
 
685
            if (lastItem + co->height > listEnd) {
 
686
                ct->firstItem = listEnd - co->height + 1;
 
687
                ct->currItem = listEnd;
 
688
            } else {
 
689
                ct->currItem += co->height;
 
690
                ct->firstItem += co->height;
 
691
            }
 
692
            ctEnsureLimits( ct );
 
693
 
 
694
            ctDraw(co);
 
695
            if(co->callback) co->callback(co, co->callbackData);
 
696
            er.result = ER_SWALLOWED;
 
697
            return er;
 
698
        }
 
699
        break;
 
700
 
 
701
    case EV_FOCUS:
 
702
        ct->isActive = 1;
 
703
        ctDraw(co);
 
704
        er.result = ER_SWALLOWED;
 
705
        break;
 
706
        
 
707
    case EV_UNFOCUS:
 
708
        ct->isActive = 0;
 
709
        ctDraw(co);
 
710
        er.result = ER_SWALLOWED;
 
711
        break;
 
712
    default:
 
713
        break;
 
714
    }
 
715
 
 
716
    return er;
 
717
}
 
718
 
 
719
const void * newtCheckboxTreeGetCurrent(newtComponent co) {
 
720
    struct CheckboxTree * ct = co->data;
 
721
 
 
722
    if (!ct->currItem) {
 
723
        if (ct->itemlist)
 
724
            return ct->itemlist->data;
 
725
        else
 
726
            return NULL;
 
727
    }
 
728
 
 
729
    return (*ct->currItem)->data;
 
730
}
 
731
 
 
732
void newtCheckboxTreeSetEntry(newtComponent co, const void * data, const char * text)
 
733
{
 
734
    struct CheckboxTree * ct;
 
735
    struct items * item;
 
736
    int i, width;
 
737
 
 
738
    if (!co) return;
 
739
    ct = co->data;
 
740
    item = findItem(ct->itemlist, data);
 
741
    if (!item) return;
 
742
 
 
743
    free(item->text);
 
744
    item->text = strdup(text);
 
745
 
 
746
    i = 4 + (3 * item->depth);
 
747
 
 
748
    width = wstrlen(text, -1);
 
749
    if ((ct->userHasSetWidth == 0) && ((width + i + ct->sbAdjust) > co->width)) {
 
750
        updateWidth(co, ct, width + i);
 
751
    }
 
752
 
 
753
    ctDraw(co);
 
754
}
 
755
 
 
756
char newtCheckboxTreeGetEntryValue(newtComponent co, const void * data)
 
757
{
 
758
    struct CheckboxTree * ct;
 
759
    struct items * item;
 
760
 
 
761
    if (!co) return -1;
 
762
    ct = co->data;
 
763
    item = findItem(ct->itemlist, data);
 
764
    if (!item) return -1;
 
765
    if (item->branch)
 
766
        return item->selected ? NEWT_CHECKBOXTREE_EXPANDED : NEWT_CHECKBOXTREE_COLLAPSED;
 
767
    else
 
768
        return ct->seq[item->selected];
 
769
}
 
770
 
 
771
void newtCheckboxTreeSetEntryValue(newtComponent co, const void * data, char value)
 
772
{
 
773
    struct CheckboxTree * ct;
 
774
    struct items * item;
 
775
    int i;
 
776
 
 
777
    if (!co) return;
 
778
    ct = co->data;
 
779
    item = findItem(ct->itemlist, data);
 
780
    if (!item || item->branch) return;
 
781
 
 
782
    for(i = 0; ct->seq[i]; i++)
 
783
        if (value == ct->seq[i])
 
784
            break;
 
785
 
 
786
    if (!ct->seq[i]) return;
 
787
    item->selected = i;
 
788
 
 
789
    ctDraw(co);
 
790
}
 
791
 
 
792
 
 
793
void newtCheckboxTreeSetCurrent(newtComponent co, void * data) {
 
794
    struct CheckboxTree * ct = co->data;
 
795
    int * path;
 
796
    int i, j;
 
797
    struct items * treeTop, * item;
 
798
 
 
799
    path = newtCheckboxTreeFindItem(co, data);
 
800
    if (!path) return;
 
801
 
 
802
    /* traverse the path and turn on all of the branches to this point */
 
803
    for (i = 0, treeTop = ct->itemlist; path[i + 1] != NEWT_ARG_LAST; i++) {
 
804
        for (j = 0, item = treeTop; j < path[i]; j++)
 
805
            item = item->next;
 
806
 
 
807
        item->selected = 1;
 
808
        treeTop = item->branch;
 
809
    }
 
810
 
 
811
    free(path);
 
812
    buildFlatList(co);
 
813
        
 
814
    item = findItem(ct->itemlist, data);
 
815
 
 
816
    i = 0;
 
817
    while (ct->flatList[i] != item) i++;
 
818
 
 
819
    /* choose the top item */
 
820
    j = i - (co->height / 2);
 
821
 
 
822
    if ((j + co->height) > ct->flatCount) 
 
823
        j = ct->flatCount - co->height;
 
824
    
 
825
    if (j < 0)
 
826
        j = 0;
 
827
 
 
828
    ct->firstItem = ct->flatList + j;
 
829
    ct->currItem = ct->flatList + i;
 
830
 
 
831
    ctDraw(co);
 
832
}