]> git.ipfire.org Git - thirdparty/newt.git/blobdiff - checkbox.c
install python modules to purelib and platlib
[thirdparty/newt.git] / checkbox.c
index 4bc1ff7de1b5031b41c307b33433652d79d82438..159076240eacebc78a2a144b7717f13303f9353e 100644 (file)
@@ -1,32 +1,38 @@
-#include <slang/slang.h>
+#include <slang.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "newt.h"
 #include "newt_pr.h"
 
+enum type { CHECK, RADIO };
+
 struct checkbox {
     char * text;
     char * seq;
     char * result;
     newtComponent prevButton, lastButton;
-    char isRadio;
+    enum type type;
     char value;
+    int active, inactive;
+    const void * data;
+    int flags;
+    int hasFocus;
 };
 
-static void cbDrawIt(newtComponent c, int active);
-
 static void cbDraw(newtComponent c);
 static void cbDestroy(newtComponent co);
-struct eventResult cbEvent(struct newtComponent * co, struct event ev);
+struct eventResult cbEvent(newtComponent co, struct event ev);
 
 static struct componentOps cbOps = {
     cbDraw,
     cbEvent,
     cbDestroy,
+    newtDefaultPlaceHandler,
+    newtDefaultMappedHandler,
 } ;
 
-newtComponent newtRadiobutton(int left, int top, char * text, int isDefault,
+newtComponent newtRadiobutton(int left, int top, const char * text, int isDefault,
                              newtComponent prevButton) {
     newtComponent co;
     newtComponent curr;
@@ -40,7 +46,7 @@ newtComponent newtRadiobutton(int left, int top, char * text, int isDefault,
 
     co = newtCheckbox(left, top, text, initialValue, " *", NULL);
     rb = co->data;
-    rb->isRadio = 1;
+    rb->type = RADIO;
 
     rb->prevButton = prevButton;
 
@@ -52,17 +58,79 @@ newtComponent newtRadiobutton(int left, int top, char * text, int isDefault,
     return co;
 }
 
-newtComponent newtCheckbox(int left, int top, char * text, char defValue,
-                          char * seq, char * result) {
+newtComponent newtRadioGetCurrent(newtComponent setMember) {
+    struct checkbox * rb = setMember->data;
+
+    setMember = rb->lastButton;
+    rb = setMember->data;
+
+    while (rb && rb->value != '*') {
+       setMember = rb->prevButton;
+       if (!setMember)
+         return NULL;
+       rb = setMember->data;
+    }
+
+    return setMember;
+}
+
+void newtRadioSetCurrent(newtComponent setMember) {
+    struct checkbox * cb = setMember->data;
+    struct checkbox * rb;
+    newtComponent curr;
+
+    /* find the one that's turned on */
+    curr = cb->lastButton;
+    rb = curr->data;
+    while (curr && rb->value == rb->seq[0]) {
+        curr = rb->prevButton;
+        if (curr) rb = curr->data;
+    }
+    if (curr) {
+        rb->value = rb->seq[0];
+        cbDraw(curr);
+    }
+    cb->value = cb->seq[1];
+    cbDraw(setMember);
+
+    if (setMember->callback)
+        setMember->callback(setMember, setMember->callbackData);
+}
+
+char newtCheckboxGetValue(newtComponent co) {
+    struct checkbox * cb = co->data;
+
+    return cb->value;
+}
+
+void newtCheckboxSetValue(newtComponent co, char value) {
+    struct checkbox * cb = co->data;
+
+    *cb->result = value;
+    cbDraw(co);
+}
+
+/* 
+ * returns NULL on error.
+ * FIXME: Check all calls.
+ */
+newtComponent newtCheckbox(int left, int top, const char * text, char defValue,
+                          const char * seq, char * result) {
     newtComponent co;
     struct checkbox * cb;
 
     if (!seq) seq = " *";
 
     co = malloc(sizeof(*co));
+    if (co == NULL)
+       return NULL;
     cb = malloc(sizeof(struct checkbox));
+    if (cb == NULL) {
+       free(co);
+       return NULL;
+    }
     co->data = cb;
-
+    cb->flags = 0;
     if (result)
        cb->result = result;
     else
@@ -70,43 +138,86 @@ newtComponent newtCheckbox(int left, int top, char * text, char defValue,
 
     cb->text = strdup(text);
     cb->seq = strdup(seq);
+    cb->type = CHECK;
+    cb->hasFocus = 0;
+    cb->inactive = COLORSET_CHECKBOX;
+    cb->active = COLORSET_ACTCHECKBOX;
     defValue ? (*cb->result = defValue) : (*cb->result = cb->seq[0]);
-    cb->isRadio = 0;
 
     co->ops = &cbOps;
 
+    co->callback = NULL;
+    co->destroyCallback = NULL;
     co->height = 1;
-    co->width = strlen(text) + 4;
+    co->width = wstrlen(text, -1) + 4;
     co->top = top;
     co->left = left;
     co->takesFocus = 1;
+    co->isMapped = 0;
 
     return co;
 }
 
-static void cbDraw(newtComponent c) {
-    cbDrawIt(c, 0);
+void newtCheckboxSetFlags(newtComponent co, int flags, enum newtFlagsSense sense) {
+    struct checkbox * cb = co->data;
+    int row, col;
+
+    cb->flags = newtSetFlags(cb->flags, flags, sense);
+
+    // If the flag just sets a property (eg. NEWT_FLAG_RETURNEXIT),
+    // don't redraw, etc. as the component might be 'hidden' and not to
+    // be drawn (eg. in a scrolled list)
+    if (flags == NEWT_FLAG_RETURNEXIT)
+           return;
+
+    if (!(cb->flags & NEWT_FLAG_DISABLED))
+       co->takesFocus = 1;
+    else
+       co->takesFocus = 0;
+
+    newtGetrc(&row, &col);
+    cbDraw(co);
+    newtGotorc(row, col);
 }
 
-static void cbDrawIt(newtComponent c, int active) {
+static void cbDraw(newtComponent c) {
     struct checkbox * cb = c->data;
 
-    SLsmg_set_color(COLORSET_CHECKBOX);
+    if (!c->isMapped) return;
+
+    if (cb->flags & NEWT_FLAG_DISABLED) {
+       cb->inactive = NEWT_COLORSET_DISENTRY;
+       cb->active = NEWT_COLORSET_DISENTRY;
+    } else {
+       cb->inactive = COLORSET_CHECKBOX;
+       cb->active = COLORSET_ACTCHECKBOX;
+    }
+
+    SLsmg_set_color(cb->inactive);
 
     newtGotorc(c->top, c->left);
 
-    if (cb->isRadio) 
+    switch (cb->type) {
+      case RADIO:
        SLsmg_write_string("( ) ");
-    else
+       break;
+
+      case CHECK:
        SLsmg_write_string("[ ] ");
+       break;
+
+      default:
+       break;
+    }
 
     SLsmg_write_string(cb->text);
 
-    if (active) 
-       SLsmg_set_color(COLORSET_ACTCHECKBOX);
+    if (cb->hasFocus)
+       SLsmg_set_color(cb->active);
 
     newtGotorc(c->top, c->left + 1);
     SLsmg_write_char(*cb->result);
+    newtGotorc(c->top, c->left + 4);
 }
 
 static void cbDestroy(newtComponent co) {
@@ -118,58 +229,83 @@ static void cbDestroy(newtComponent co) {
     free(co);
 }
 
-struct eventResult cbEvent(struct newtComponent * co, struct event ev) {
-    struct eventResult er;
+struct eventResult cbEvent(newtComponent co, struct event ev) {
     struct checkbox * cb = co->data;
-    struct checkbox * rb;
-    newtComponent curr;
-    char * cur;
-
-    switch (ev.event) {
-      case EV_FOCUS:
-       cbDrawIt(co, 1);
-       er.result = ER_SWALLOWED;
-       break;
-
-      case EV_UNFOCUS:
-       cbDrawIt(co, 0);
-       er.result = ER_SWALLOWED;
-       break;
-
-      case EV_KEYPRESS:
-       if (ev.u.key == ' ' || ev.u.key == '\r') {
-           if (cb->isRadio) {
-               /* find the one that's turned off */
-               curr = cb->lastButton;
-               rb = curr->data;
-               while (curr && rb->value == rb->seq[0]) {
-                   curr = rb->prevButton;
-                   if (curr) rb = curr->data;
+    struct eventResult er;
+    const char * cur;
+
+    er.result = ER_IGNORED;
+
+    if (ev.when == EV_NORMAL) {
+       switch (ev.event) {
+         case EV_FOCUS:
+           cb->hasFocus = 1;
+           cbDraw(co);
+           er.result = ER_SWALLOWED;
+           break;
+
+         case EV_UNFOCUS:
+           cb->hasFocus = 0;
+           cbDraw(co);
+           er.result = ER_SWALLOWED;
+           break;
+
+         case EV_KEYPRESS:
+           if (ev.u.key == ' ') {
+               if (cb->type == RADIO) {
+                   newtRadioSetCurrent(co);
+               } else if (cb->type == CHECK) {
+                   cur = strchr(cb->seq, *cb->result);
+                   if (!cur)
+                       *cb->result = *cb->seq;
+                   else {
+                       cur++;
+                       if (! *cur)
+                           *cb->result = *cb->seq;
+                       else
+                           *cb->result = *cur;
+                   }
+                   cbDraw(co);
+                   er.result = ER_SWALLOWED;
+
+                   if (co->callback)
+                       co->callback(co, co->callbackData);
+               } else {
+                   er.result = ER_IGNORED;
                }
-               if (curr) {
-                   rb->value = rb->seq[0];
-                   cbDrawIt(curr, 0);
-               } 
-               cb->value = cb->seq[1];
-               cbDrawIt(co, 1);
+           } else if(ev.u.key == NEWT_KEY_ENTER) {
+               if (cb->flags & NEWT_FLAG_RETURNEXIT)
+                       er.result = ER_EXITFORM;
+               else
+                       er.result = ER_IGNORED;
            } else {
-               cur = strchr(cb->seq, *cb->result);
-               if (!cur)
-                   *cb->result = *cb->seq;
-               else {
-                   cur++;
-                   if (! *cur) 
+               er.result = ER_IGNORED;
+           }
+           break;
+         case EV_MOUSE:
+           if (ev.u.mouse.type == MOUSE_BUTTON_DOWN) {
+               if (cb->type == RADIO) {
+                   newtRadioSetCurrent(co);
+               } else if (cb->type == CHECK) {
+                   cur = strchr(cb->seq, *cb->result);
+                   if (!cur)
                        *cb->result = *cb->seq;
-                   else
-                       *cb->result = *cur;
+                   else {
+                       cur++;
+                       if (! *cur)
+                           *cb->result = *cb->seq;
+                       else
+                           *cb->result = *cur;
+                   }
+                   cbDraw(co);
+                   er.result = ER_SWALLOWED;
+
+                   if (co->callback)
+                       co->callback(co, co->callbackData);
                }
-               cbDrawIt(co, 1);
-               er.result = ER_SWALLOWED;
            }
-       } else {
-           er.result = ER_IGNORED;
        }
     }
 
-   return er;
+    return er;
 }