]> git.ipfire.org Git - thirdparty/newt.git/blame - checkboxtree.c
- make textbox with scrollbar focusable (#83203)
[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);
1fc80395 41enum countWhat { COUNT_EXPOSED=0, COUNT_SELECTED=1 };
1e0b187b 42static int countItems(struct items * item, enum countWhat justExposed);
d8c97d41 43static inline void updateWidth(newtComponent co, struct CheckboxTree * ct,
6f481af2 44 int maxField);
f06c5a99 45
46static struct componentOps ctOps = {
47 ctDraw,
48 ctEvent,
49 ctDestroy,
50 ctPlace,
51 ctMapped,
52} ;
53
d8c97d41 54static inline void updateWidth(newtComponent co, struct CheckboxTree * ct,
6f481af2 55 int maxField) {
d8c97d41 56 ct->curWidth = maxField;
57 co->width = ct->curWidth + ct->sbAdjust;
58
59 if (ct->sb)
6f481af2 60 ct->sb->left = co->left + co->width - 1;
d8c97d41 61}
62
1e0b187b 63static int countItems(struct items * item, enum countWhat what) {
64 int count = 0;
65
66 while (item) {
1fc80395 67 if ((!item->branch && item->selected == what) || (what == COUNT_EXPOSED))
6f481af2 68 count++;
69 if (item->branch || (what == COUNT_EXPOSED && item->selected))
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);
91 ct->flatCount = countItems(ct->itemlist, COUNT_EXPOSED);
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) {
6f481af2 276 if ((seqindex ? items->selected==seqindex : items->selected) && !items->branch)
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
c895490d 315 *numitems = countItems(ct->itemlist, (seqindex ? seqindex : COUNT_SELECTED));
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;
f06c5a99 336 co->data = ct;
7588e5ba 337 co->left = left;
338 co->top = top;
f06c5a99 339 co->ops = &ctOps;
340 co->takesFocus = 1;
341 co->height = height;
342 co->width = 0;
343 co->isMapped = 0;
d8c97d41 344 ct->curWidth = 0;
9fc6a6b0 345 ct->isActive = 0;
d8c97d41 346 ct->userHasSetWidth = 0;
f06c5a99 347 ct->itemlist = NULL;
1e0b187b 348 ct->firstItem = NULL;
349 ct->currItem = NULL;
350 ct->flatList = NULL;
615bc463 351
352 ct->flags = flags;
353
354 if (seq)
6f481af2 355 ct->seq = strdup(seq);
615bc463 356 else
6f481af2 357 ct->seq = strdup(" *");
f06c5a99 358 if (flags & NEWT_FLAG_SCROLL) {
6f481af2 359 ct->sb = newtVerticalScrollbar(left, top, height,
360 COLORSET_LISTBOX, COLORSET_ACTLISTBOX);
361 ct->sbAdjust = 2;
f06c5a99 362 } else {
6f481af2 363 ct->sb = NULL;
364 ct->sbAdjust = 0;
f06c5a99 365 }
366
367 return co;
368}
369
370static void ctMapped(newtComponent co, int isMapped) {
371 struct CheckboxTree * ct = co->data;
372
373 co->isMapped = isMapped;
374 if (ct->sb)
6f481af2 375 ct->sb->ops->mapped(ct->sb, isMapped);
f06c5a99 376}
377
378static void ctPlace(newtComponent co, int newLeft, int newTop) {
379 struct CheckboxTree * ct = co->data;
380
381 co->top = newTop;
382 co->left = newLeft;
383
384 if (ct->sb)
6f481af2 385 ct->sb->ops->place(ct->sb, co->left + co->width - 1, co->top);
f06c5a99 386}
387
388int ctSetItem(newtComponent co, struct items *item, enum newtFlagsSense sense)
389{
390 struct CheckboxTree * ct = co->data;
5a6729cf 391 struct items * currItem;
392 struct items * firstItem;
f06c5a99 393
394 if (!item)
6f481af2 395 return 1;
f06c5a99 396
f06c5a99 397 switch(sense) {
6f481af2 398 case NEWT_FLAGS_RESET:
399 item->selected = 0;
400 break;
401 case NEWT_FLAGS_SET:
402 item->selected = 1;
403 break;
404 case NEWT_FLAGS_TOGGLE:
405 if (item->branch)
406 item->selected = !item->selected;
407 else if (!(ct->flags & NEWT_CHECKBOXTREE_UNSELECTABLE)) {
408 item->selected++;
409 if (item->selected==strlen(ct->seq))
410 item->selected = 0;
411 }
412 break;
f06c5a99 413 }
414
1e0b187b 415 if (item->branch) {
6f481af2 416 currItem = *ct->currItem;
417 firstItem = *ct->firstItem;
1e0b187b 418
6f481af2 419 buildFlatList(co);
1e0b187b 420
6f481af2 421 ct->currItem = ct->flatList;
422 while (*ct->currItem != currItem) ct->currItem++;
5a6729cf 423
6f481af2 424 ct->firstItem = ct->flatList;
425 if (ct->flatCount > co->height) {
426 struct items ** last = ct->flatList + ct->flatCount - co->height;
427 while (*ct->firstItem != firstItem && ct->firstItem != last)
428 ct->firstItem++;
429 }
1e0b187b 430 }
431
f06c5a99 432 return 0;
433}
434
c895490d 435static void ctSetItems(struct items *item, int selected)
436{
437 for (; item; item = item->next) {
6f481af2 438 if (!item->branch)
439 item->selected = selected;
440 else
441 ctSetItems(item->branch, selected);
c895490d 442 }
443}
f06c5a99 444
445static void ctDraw(newtComponent co) {
446 struct CheckboxTree * ct = co->data;
1e0b187b 447 struct items ** item;
1e879b7e 448 int i, j;
73390860 449 char * spaces;
feef2cb5 450 int currRow;
1e0b187b 451
452 if (!co->isMapped) return ;
453
454 if (!ct->firstItem) {
6f481af2 455 buildFlatList(co);
456 ct->firstItem = ct->currItem = ct->flatList;
f06c5a99 457 }
1e0b187b 458
459 item = ct->firstItem;
f06c5a99 460
461 i = 0;
7ff5fd71 462
463 newtTrashScreen();
464
1e0b187b 465 while (*item && i < co->height) {
6f481af2 466 newtGotorc(co->top + i, co->left);
9fc6a6b0 467 SLsmg_set_color(NEWT_COLORSET_LISTBOX);
6f481af2 468 for (j = 0; j < (*item)->depth; j++)
469 SLsmg_write_string(" ");
470
471 if ((*item)->branch) {
472 if ((*item)->selected)
473 SLsmg_write_string("<-> ");
474 else
475 SLsmg_write_string("<+> ");
476 } else {
477 if (ct->flags & NEWT_CHECKBOXTREE_HIDE_BOX) {
478 if ((*item)->selected)
9fc6a6b0 479 SLsmg_set_color(NEWT_COLORSET_SELLISTBOX);
6f481af2 480 SLsmg_write_string(" ");
481 } else {
482 char tmp[5];
483 snprintf(tmp,5,"[%c] ",ct->seq[(*item)->selected]);
484 SLsmg_write_string(tmp);
485 }
486 }
9fc6a6b0 487 if (*item == *ct->currItem) {
488 SLsmg_set_color(ct->isActive ?
489 NEWT_COLORSET_ACTSELLISTBOX : NEWT_COLORSET_ACTLISTBOX);
490 currRow = co->top + i;
491 }
6f481af2 492
10de8f4a 493 SLsmg_write_nstring((*item)->text, co->width - 4 -
494 (3 * (*item)->depth));
6f481af2 495
6f481af2 496 item++;
497 i++;
f06c5a99 498 }
73390860 499
500 /* There could be empty lines left (i.e. if the user closes an expanded
501 list which is the last thing in the tree, and whose elements are
502 displayed at the bottom of the screen */
503 if (i < co->height) {
6f481af2 504 spaces = alloca(co->width);
505 memset(spaces, ' ', co->width);
506 SLsmg_set_color(NEWT_COLORSET_LISTBOX);
73390860 507 }
508 while (i < co->height) {
6f481af2 509 newtGotorc(co->top + i, co->left);
510 SLsmg_write_nstring(spaces, co->width);
511 i++;
73390860 512 }
f06c5a99 513
514 if(ct->sb) {
6f481af2 515 newtScrollbarSet(ct->sb, ct->currItem - ct->flatList,
516 ct->flatCount - 1);
517 ct->sb->ops->draw(ct->sb);
f06c5a99 518 }
519
1e879b7e 520 newtGotorc(currRow, co->left + 1);
f06c5a99 521}
522
523static void ctDestroy(newtComponent co) {
524 struct CheckboxTree * ct = co->data;
525 struct items * item, * nextitem;
526
527 nextitem = item = ct->itemlist;
528
529 while (item != NULL) {
6f481af2 530 nextitem = item->next;
531 free(item->text);
532 free(item);
533 item = nextitem;
f06c5a99 534 }
535
1fc80395 536 free(ct->seq);
f06c5a99 537 free(ct);
538 free(co);
539}
540
21f6373f 541static void ctEnsureLimits( struct CheckboxTree *ct ) {
542 struct items **listEnd = ct->flatList + ct->flatCount - 1;
543 if (ct->firstItem < ct->flatList)
544 ct->firstItem = ct->flatList;
545 if (ct->currItem < ct->flatList)
546 ct->currItem = ct->flatList;
547 if (ct->firstItem > listEnd) {
548 ct->firstItem = listEnd;
549 ct->currItem = listEnd;
550 }
551}
552
f06c5a99 553struct eventResult ctEvent(newtComponent co, struct event ev) {
554 struct CheckboxTree * ct = co->data;
555 struct eventResult er;
1e0b187b 556 struct items ** listEnd, ** lastItem;
c895490d 557 int key, selnum = 1;
f06c5a99 558
559 er.result = ER_IGNORED;
560
561 if(ev.when == EV_EARLY || ev.when == EV_LATE) {
6f481af2 562 return er;
f06c5a99 563 }
564
565 switch(ev.event) {
566 case EV_KEYPRESS:
6f481af2 567 key = ev.u.key;
568 if (key == (char) key && key != ' ') {
569 for (selnum = 0; ct->seq[selnum]; selnum++)
570 if (key == ct->seq[selnum])
571 break;
572 if (!ct->seq[selnum])
573 switch (key) {
574 case '-': selnum = 0; break;
575 case '+':
576 case '*': selnum = 1; break;
577 }
578 if (ct->seq[selnum])
579 key = '*';
580 }
581 switch(key) {
582 case ' ':
583 case NEWT_KEY_ENTER:
584 ctSetItem(co, *ct->currItem, NEWT_FLAGS_TOGGLE);
585 er.result = ER_SWALLOWED;
586 if (!(*ct->currItem)->branch || (*ct->currItem)->selected)
587 key = NEWT_KEY_DOWN;
588 else
589 key = '*';
590 break;
591 case '*':
592 if ((*ct->currItem)->branch) {
593 ctSetItems((*ct->currItem)->branch, selnum);
594 if (!(*ct->currItem)->selected)
595 key = NEWT_KEY_DOWN;
596 } else {
597 (*ct->currItem)->selected = selnum;
598 key = NEWT_KEY_DOWN;
599 }
600 er.result = ER_SWALLOWED;
601 break;
602 }
603 switch (key) {
604 case '*':
605 ctDraw(co);
606 if(co->callback) co->callback(co, co->callbackData);
607 return er;
608 case NEWT_KEY_HOME:
609 ct->currItem = ct->flatList;
610 ct->firstItem = ct->flatList;
611 ctDraw(co);
612 if(co->callback) co->callback(co, co->callbackData);
613 er.result = ER_SWALLOWED;
614 return er;
615 case NEWT_KEY_END:
616 ct->currItem = ct->flatList + ct->flatCount - 1;
617 if (ct->flatCount <= co->height)
618 ct->firstItem = ct->flatList;
619 else
620 ct->firstItem = ct->flatList + ct->flatCount - co->height;
621 ctDraw(co);
622 if(co->callback) co->callback(co, co->callbackData);
623 er.result = ER_SWALLOWED;
624 return er;
625 case NEWT_KEY_DOWN:
626 if (ev.u.key != NEWT_KEY_DOWN) {
627 if(co->callback) co->callback(co, co->callbackData);
628 if (strlen(ct->seq) != 2) {
629 ctDraw(co);
630 return er;
631 }
632 }
633 if ((ct->currItem - ct->flatList + 1) < ct->flatCount) {
634 ct->currItem++;
635
636 if (ct->currItem - ct->firstItem >= co->height)
637 ct->firstItem++;
638
639 ctDraw(co);
640 } else if (ev.u.key != NEWT_KEY_DOWN)
641 ctDraw(co);
642 if(co->callback) co->callback(co, co->callbackData);
643 er.result = ER_SWALLOWED;
644 return er;
645 case NEWT_KEY_UP:
646 if (ct->currItem != ct->flatList) {
647 ct->currItem--;
648
649 if (ct->currItem < ct->firstItem)
650 ct->firstItem = ct->currItem;
651
652 ctDraw(co);
653 }
654 er.result = ER_SWALLOWED;
655 if(co->callback) co->callback(co, co->callbackData);
656 return er;
657 case NEWT_KEY_PGUP:
658 if (ct->firstItem - co->height < ct->flatList) {
659 ct->firstItem = ct->currItem = ct->flatList;
660 } else {
661 ct->currItem -= co->height;
662 ct->firstItem -= co->height;
663 }
21f6373f 664 ctEnsureLimits( ct );
6f481af2 665
666 ctDraw(co);
667 if(co->callback) co->callback(co, co->callbackData);
668 er.result = ER_SWALLOWED;
669 return er;
670 case NEWT_KEY_PGDN:
671 listEnd = ct->flatList + ct->flatCount - 1;
672 lastItem = ct->firstItem + co->height - 1;
673
674 if (lastItem + co->height > listEnd) {
675 ct->firstItem = listEnd - co->height + 1;
676 ct->currItem = listEnd;
677 } else {
678 ct->currItem += co->height;
679 ct->firstItem += co->height;
680 }
21f6373f 681 ctEnsureLimits( ct );
6f481af2 682
683 ctDraw(co);
684 if(co->callback) co->callback(co, co->callbackData);
685 er.result = ER_SWALLOWED;
686 return er;
687 }
688 break;
c895490d 689
f06c5a99 690 case EV_FOCUS:
9fc6a6b0 691 ct->isActive = 1;
6f481af2 692 ctDraw(co);
693 er.result = ER_SWALLOWED;
694 break;
695
f06c5a99 696 case EV_UNFOCUS:
9fc6a6b0 697 ct->isActive = 0;
6f481af2 698 ctDraw(co);
699 er.result = ER_SWALLOWED;
700 break;
f06c5a99 701 default:
6f481af2 702 break;
f06c5a99 703 }
704
705 return er;
706}
2b6641b1 707
708const void * newtCheckboxTreeGetCurrent(newtComponent co) {
709 struct CheckboxTree * ct = co->data;
710
711 if (!ct->currItem) return NULL;
712 return (*ct->currItem)->data;
713}
c895490d 714
715void newtCheckboxTreeSetEntry(newtComponent co, const void * data, const char * text)
716{
717 struct CheckboxTree * ct;
718 struct items * item;
349586bb 719 int i, width;
c895490d 720
721 if (!co) return;
722 ct = co->data;
723 item = findItem(ct->itemlist, data);
724 if (!item) return;
725
726 free(item->text);
727 item->text = strdup(text);
728
729 i = 4 + (3 * item->depth);
730
349586bb 731 width = wstrlen(text, -1);
732 if ((ct->userHasSetWidth == 0) && ((width + i + ct->sbAdjust) > co->width)) {
6f481af2 733 updateWidth(co, ct, width + i);
c895490d 734 }
735
736 ctDraw(co);
737}
738
739char newtCheckboxTreeGetEntryValue(newtComponent co, const void * data)
740{
741 struct CheckboxTree * ct;
742 struct items * item;
743
744 if (!co) return -1;
745 ct = co->data;
746 item = findItem(ct->itemlist, data);
747 if (!item) return -1;
748 if (item->branch)
6f481af2 749 return item->selected ? NEWT_CHECKBOXTREE_EXPANDED : NEWT_CHECKBOXTREE_COLLAPSED;
c895490d 750 else
6f481af2 751 return ct->seq[item->selected];
c895490d 752}
753
754void newtCheckboxTreeSetEntryValue(newtComponent co, const void * data, char value)
755{
756 struct CheckboxTree * ct;
757 struct items * item;
758 int i;
759
760 if (!co) return;
761 ct = co->data;
762 item = findItem(ct->itemlist, data);
763 if (!item || item->branch) return;
764
765 for(i = 0; ct->seq[i]; i++)
6f481af2 766 if (value == ct->seq[i])
767 break;
c895490d 768
769 if (!ct->seq[i]) return;
770 item->selected = i;
771
772 ctDraw(co);
773}
774
5160fc22 775
776void newtCheckboxTreeSetCurrent(newtComponent co, void * data) {
777 struct CheckboxTree * ct = co->data;
778 int * path;
d78245ab 779 int i, j;
5160fc22 780 struct items * treeTop, * item;
781
782 path = newtCheckboxTreeFindItem(co, data);
783 if (!path) return;
784
785 /* traverse the path and turn on all of the branches to this point */
786 for (i = 0, treeTop = ct->itemlist; path[i + 1] != NEWT_ARG_LAST; i++) {
6f481af2 787 for (j = 0, item = treeTop; j < path[i]; j++)
788 item = item->next;
5160fc22 789
6f481af2 790 item->selected = 1;
791 treeTop = item->branch;
5160fc22 792 }
793
794 buildFlatList(co);
6f481af2 795
5160fc22 796 item = findItem(ct->itemlist, data);
797
798 i = 0;
799 while (ct->flatList[i] != item) i++;
800
801 /* choose the top item */
802 j = i - (co->height / 2);
803
804 if ((j + co->height) > ct->flatCount)
6f481af2 805 j = ct->flatCount - co->height;
5160fc22 806
807 if (j < 0)
6f481af2 808 j = 0;
5160fc22 809
810 ct->firstItem = ct->flatList + j;
811 ct->currItem = ct->flatList + i;
812
813 ctDraw(co);
814}