#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; enum type type; char value; int active, inactive; const void * data; int flags; int hasFocus; }; static void makeActive(newtComponent co); static void cbDraw(newtComponent c); static void cbDestroy(newtComponent co); struct eventResult cbEvent(newtComponent co, struct event ev); static struct componentOps cbOps = { cbDraw, cbEvent, cbDestroy, newtDefaultPlaceHandler, newtDefaultMappedHandler, } ; newtComponent newtRadiobutton(int left, int top, const char * text, int isDefault, newtComponent prevButton) { newtComponent co; newtComponent curr; struct checkbox * rb; char initialValue; if (isDefault) initialValue = '*'; else initialValue = ' '; co = newtCheckbox(left, top, text, initialValue, " *", NULL); rb = co->data; rb->type = RADIO; rb->prevButton = prevButton; for (curr = co; curr; curr = rb->prevButton) { rb = curr->data; rb->lastButton = co; } return co; } 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; } 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); } 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)); cb = malloc(sizeof(struct checkbox)); co->data = cb; cb->flags = 0; if (result) cb->result = result; else cb->result = &cb->value; 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]); co->ops = &cbOps; co->callback = NULL; co->height = 1; co->width = strlen(text) + 4; co->top = top; co->left = left; co->takesFocus = 1; return co; } 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 (!(cb->flags & NEWT_FLAG_DISABLED)) co->takesFocus = 1; else co->takesFocus = 0; newtGetrc(&row, &col); cbDraw(co); newtGotorc(row, col); } static void cbDraw(newtComponent c) { struct checkbox * cb = c->data; if (c->top == -1 || !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); switch (cb->type) { case RADIO: SLsmg_write_string("( ) "); break; case CHECK: SLsmg_write_string("[ ] "); break; default: break; } SLsmg_write_string(cb->text); if (cb->hasFocus) SLsmg_set_color(cb->active); newtGotorc(c->top, c->left + 1); SLsmg_write_char(*cb->result); } static void cbDestroy(newtComponent co) { struct checkbox * cb = co->data; free(cb->text); free(cb->seq); free(cb); free(co); } struct eventResult cbEvent(newtComponent co, struct event ev) { struct checkbox * cb = co->data; struct eventResult er; const char * cur; er.result = ER_IGNORED; er.u.focus = NULL; 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) { makeActive(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; } } else if(ev.u.key == NEWT_KEY_ENTER) { er.result = ER_IGNORED; } else { er.result = ER_IGNORED; } break; case EV_MOUSE: if (ev.u.mouse.type == MOUSE_BUTTON_DOWN) { if (cb->type == RADIO) { makeActive(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; return er; } static void makeActive(newtComponent co) { struct checkbox * cb = co->data; struct checkbox * rb; newtComponent curr; /* 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; } if (curr) { rb->value = rb->seq[0]; cbDraw(curr); } cb->value = cb->seq[1]; cbDraw(co); if (co->callback) co->callback(co, co->callbackData); }