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