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
updateWidth(newtComponent co,struct CheckboxTree * ct,int maxField)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
countItems(struct items * item,int what)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
doBuildFlatList(struct CheckboxTree * ct,struct items * item)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 */
buildFlatList(newtComponent co)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
newtCheckboxTreeAddItem(newtComponent co,const char * text,const void * data,int flags,int index,...)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
doFindItemPath(struct items * items,void * data,int * path,int * len)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
newtCheckboxTreeFindItem(newtComponent co,void * data)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
newtCheckboxTreeAddArray(newtComponent co,const char * text,const void * data,int flags,int * indexes)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
findItem(struct items * items,const void * data)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
listSelected(struct items * items,int * num,const void ** list,int seqindex)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
newtCheckboxTreeSetWidth(newtComponent co,int width)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
newtCheckboxTreeGetSelection(newtComponent co,int * numitems)295 const void ** newtCheckboxTreeGetSelection(newtComponent co, int *numitems)
296 {
297 return newtCheckboxTreeGetMultiSelection(co, numitems, 0);
298 }
299
newtCheckboxTreeGetMultiSelection(newtComponent co,int * numitems,char seqnum)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
newtCheckboxTree(int left,int top,int height,int flags)326 newtComponent newtCheckboxTree(int left, int top, int height, int flags) {
327 return newtCheckboxTreeMulti(left, top, height, NULL, flags);
328 }
329
newtCheckboxTreeMulti(int left,int top,int height,char * seq,int flags)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
ctMapped(newtComponent co,int isMapped)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
ctPlace(newtComponent co,int newLeft,int newTop)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
ctSetItem(newtComponent co,struct items * item,enum newtFlagsSense sense)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
ctSetItems(struct items * item,int selected)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
ctDraw(newtComponent co)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 SLsmg_write_nstring((*item)->text, co->width - 4 - (3 * (*item)->depth));
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
destroyItems(struct items * item)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
ctDestroy(newtComponent co)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
ctEnsureLimits(struct CheckboxTree * ct)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
ctEvent(newtComponent co,struct event ev)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
newtCheckboxTreeGetCurrent(newtComponent co)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
newtCheckboxTreeSetEntry(newtComponent co,const void * data,const char * text)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
newtCheckboxTreeGetEntryValue(newtComponent co,const void * data)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
newtCheckboxTreeSetEntryValue(newtComponent co,const void * data,char value)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
newtCheckboxTreeSetCurrent(newtComponent co,void * data)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 }
833