]> git.ipfire.org Git - thirdparty/newt.git/blobdiff - checkboxtree.c
install python modules to purelib and platlib
[thirdparty/newt.git] / checkboxtree.c
index f862db69df7641600b0c6a2df008af00dbb51e55..95156ebd2cce4dd28775f85d970046e6766c3608 100644 (file)
@@ -25,6 +25,7 @@ struct CheckboxTree {
     int sbAdjust;
     int curWidth;
     int userHasSetWidth;
+    int isActive;
     char * seq;
     char * result;
 };
@@ -37,8 +38,7 @@ static void ctMapped(newtComponent co, int isMapped);
 static struct items * findItem(struct items * items, const void * data);
 static void buildFlatList(newtComponent co);
 static void doBuildFlatList(struct CheckboxTree * ct, struct items * item);
-enum countWhat { COUNT_EXPOSED=0, COUNT_SELECTED=1 };
-static int countItems(struct items * item, enum countWhat justExposed);
+static int countItems(struct items * item, int what);
 static inline void updateWidth(newtComponent co, struct CheckboxTree * ct,
                                int maxField);
 
@@ -59,13 +59,14 @@ static inline void updateWidth(newtComponent co, struct CheckboxTree * ct,
        ct->sb->left = co->left + co->width - 1;
 }
 
-static int countItems(struct items * item, enum countWhat what) {
+static int countItems(struct items * item, int what) {
     int count = 0;
 
     while (item) {
-        if ((!item->branch && item->selected == what) || (what == COUNT_EXPOSED))
+       if (what < 0 || (!item->branch && ((what > 0 && item->selected == what)
+                   || (what == 0 && item->selected))))
            count++;
-       if (item->branch || (what == COUNT_EXPOSED && item->selected))
+       if (item->branch && (what >= 0 || (what < 0 && item->selected)))
            count += countItems(item->branch, what);
        item = item->next;
     }
@@ -87,7 +88,7 @@ static void buildFlatList(newtComponent co) {
     struct CheckboxTree * ct = co->data;
 
     if (ct->flatList) free(ct->flatList);
-    ct->flatCount = countItems(ct->itemlist, COUNT_EXPOSED);
+    ct->flatCount = countItems(ct->itemlist, -1);
 
     ct->flatList = malloc(sizeof(*ct->flatList) * (ct->flatCount+1));
     ct->flatCount = 0;
@@ -117,7 +118,6 @@ int newtCheckboxTreeAddItem(newtComponent co,
     va_start(argList, index);
     numIndexes = 0;
     i = index;
-    va_start(argList, index);
     while (i != NEWT_ARG_LAST) {
        indexes[numIndexes++] = i;
        i = va_arg(argList, int);
@@ -202,6 +202,8 @@ int newtCheckboxTreeAddArray(newtComponent co,
 
            i++;
            if (i < numIndexes) {
+               if (item == NULL)
+                       return -1;
                curList = item->branch;
                listPtr = &item->branch;
                if (!curList && (i + 1 != numIndexes)) return -1;
@@ -272,7 +274,7 @@ static struct items * findItem(struct items * items, const void * data) {
 
 static void listSelected(struct items * items, int * num, const void ** list, int seqindex) {
     while (items) {
-           if ((seqindex ? items->selected==seqindex : items->selected) && !items->branch)
+       if ((seqindex ? items->selected==seqindex : items->selected) && !items->branch)
            list[(*num)++] = (void *) items->data;
        if (items->branch)
            listSelected(items->branch, num, list, seqindex);
@@ -311,7 +313,7 @@ const void ** newtCheckboxTreeGetMultiSelection(newtComponent co, int *numitems,
            seqindex = 0;
     }
 
-    *numitems = countItems(ct->itemlist, (seqindex ? seqindex : COUNT_SELECTED));
+    *numitems = countItems(ct->itemlist, seqindex);
     if (!*numitems) return NULL;
     
     retval = malloc(*numitems * sizeof(void *));
@@ -332,13 +334,17 @@ newtComponent newtCheckboxTreeMulti(int left, int top, int height, char *seq, in
     co = malloc(sizeof(*co));
     ct = malloc(sizeof(struct CheckboxTree));
     co->callback = NULL;
+    co->destroyCallback = NULL;
     co->data = ct;
+    co->left = left;
+    co->top = top;
     co->ops = &ctOps;
     co->takesFocus = 1;
     co->height = height;
     co->width = 0;
     co->isMapped = 0;
     ct->curWidth = 0;
+    ct->isActive = 0;
     ct->userHasSetWidth = 0;
     ct->itemlist = NULL;
     ct->firstItem = NULL;
@@ -443,7 +449,7 @@ static void ctDraw(newtComponent co) {
     struct items ** item; 
     int i, j;
     char * spaces;
-    int currRow;
+    int currRow = co->top;
 
     if (!co->isMapped) return ;
 
@@ -460,12 +466,7 @@ static void ctDraw(newtComponent co) {
     
     while (*item && i < co->height) {
        newtGotorc(co->top + i, co->left);
-       if (*item == *ct->currItem) {
-           SLsmg_set_color(NEWT_COLORSET_ACTLISTBOX);
-           currRow = co->top + i;
-       } else
-           SLsmg_set_color(NEWT_COLORSET_LISTBOX);
-
+       SLsmg_set_color(NEWT_COLORSET_LISTBOX);
        for (j = 0; j < (*item)->depth; j++)
            SLsmg_write_string("   ");
 
@@ -477,7 +478,7 @@ static void ctDraw(newtComponent co) {
        } else {
            if (ct->flags & NEWT_CHECKBOXTREE_HIDE_BOX) {
                if ((*item)->selected)
-                   SLsmg_set_color(NEWT_COLORSET_ACTLISTBOX);
+                   SLsmg_set_color(NEWT_COLORSET_SELLISTBOX);
                SLsmg_write_string("    ");
            } else {
                char tmp[5];
@@ -485,11 +486,13 @@ static void ctDraw(newtComponent co) {
                SLsmg_write_string(tmp);
            }
        }
+       if (*item == *ct->currItem) {
+           SLsmg_set_color(ct->isActive ?
+                   NEWT_COLORSET_ACTSELLISTBOX : NEWT_COLORSET_ACTLISTBOX);
+           currRow = co->top + i;
+       }
 
-       SLsmg_write_nstring((*item)->text, co->width - 4 - 
-                                          (3 * (*item)->depth));
-
-       SLsmg_set_color(NEWT_COLORSET_LISTBOX);
+       SLsmg_write_nstring((*item)->text, co->width - 4 - (3 * (*item)->depth));
 
        item++;
        i++;
@@ -499,14 +502,16 @@ static void ctDraw(newtComponent co) {
        list which is the last thing in the tree, and whose elements are
        displayed at the bottom of the screen */
     if (i < co->height) {
-       spaces = alloca(co->width);
+       spaces = alloca(co->width + 1);
        memset(spaces, ' ', co->width);
+       spaces[co->width] = '\0';
        SLsmg_set_color(NEWT_COLORSET_LISTBOX);
-    }
-    while (i < co->height) {
-       newtGotorc(co->top + i, co->left);
-       SLsmg_write_nstring(spaces, co->width);
-       i++;
+
+       while (i < co->height) {
+           newtGotorc(co->top + i, co->left);
+           SLsmg_write_nstring(spaces, co->width);
+           i++;
+       }
     }
     
     if(ct->sb) {
@@ -515,27 +520,47 @@ static void ctDraw(newtComponent co) {
        ct->sb->ops->draw(ct->sb);
     }
 
-    newtGotorc(currRow, co->left + 1);
+    newtGotorc(currRow, co->left + 
+                   (*ct->currItem ? (*ct->currItem)->depth : 0) * 3 + 4);
 }
 
-static void ctDestroy(newtComponent co) {
-    struct CheckboxTree * ct = co->data;
-    struct items * item, * nextitem;
-
-    nextitem = item = ct->itemlist;
+static void destroyItems(struct items * item) {
+    struct items * nextitem;
 
     while (item != NULL) {
        nextitem = item->next;
        free(item->text);
+       if (item->branch)
+           destroyItems(item->branch);
        free(item);
        item = nextitem;
     }
+}
+
+static void ctDestroy(newtComponent co) {
+    struct CheckboxTree * ct = co->data;
 
+    destroyItems(ct->itemlist);
+    free(ct->flatList);
+    if (ct->sb)
+       ct->sb->ops->destroy(ct->sb);
     free(ct->seq);
     free(ct);
     free(co);
 }
 
+static void ctEnsureLimits( struct CheckboxTree *ct ) {
+    struct items **listEnd = ct->flatList + ct->flatCount - 1;
+    if (ct->firstItem < ct->flatList)
+        ct->firstItem = ct->flatList;
+    if (ct->currItem < ct->flatList)
+        ct->currItem = ct->flatList;
+    if (ct->firstItem > listEnd) {
+        ct->firstItem = listEnd;
+        ct->currItem = listEnd;
+    }
+}
+
 struct eventResult ctEvent(newtComponent co, struct event ev) {
     struct CheckboxTree * ct = co->data;
     struct eventResult er;
@@ -647,6 +672,7 @@ struct eventResult ctEvent(newtComponent co, struct event ev) {
                ct->currItem -= co->height;
                ct->firstItem -= co->height;
            }
+           ctEnsureLimits( ct );
 
            ctDraw(co);
            if(co->callback) co->callback(co, co->callbackData);
@@ -663,6 +689,7 @@ struct eventResult ctEvent(newtComponent co, struct event ev) {
                ct->currItem += co->height;
                ct->firstItem += co->height;
            }
+           ctEnsureLimits( ct );
 
            ctDraw(co);
            if(co->callback) co->callback(co, co->callbackData);
@@ -672,11 +699,13 @@ struct eventResult ctEvent(newtComponent co, struct event ev) {
        break;
 
     case EV_FOCUS:
+       ct->isActive = 1;
        ctDraw(co);
        er.result = ER_SWALLOWED;
        break;
        
     case EV_UNFOCUS:
+       ct->isActive = 0;
        ctDraw(co);
        er.result = ER_SWALLOWED;
        break;
@@ -690,7 +719,13 @@ struct eventResult ctEvent(newtComponent co, struct event ev) {
 const void * newtCheckboxTreeGetCurrent(newtComponent co) {
     struct CheckboxTree * ct = co->data;
 
-    if (!ct->currItem) return NULL;
+    if (!ct->currItem) {
+       if (ct->itemlist)
+           return ct->itemlist->data;
+       else
+           return NULL;
+    }
+
     return (*ct->currItem)->data;
 }
 
@@ -773,6 +808,7 @@ void newtCheckboxTreeSetCurrent(newtComponent co, void * data) {
        treeTop = item->branch;
     }
 
+    free(path);
     buildFlatList(co);
        
     item = findItem(ct->itemlist, data);