From: ewt Date: Mon, 25 Mar 1996 01:59:25 +0000 (+0000) Subject: Initial revision X-Git-Tag: 0-1~53 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6fb96a3f972d005717bc94bcf8836304f920d10f;p=thirdparty%2Fnewt.git Initial revision --- 6fb96a3f972d005717bc94bcf8836304f920d10f diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..811994c --- /dev/null +++ b/Makefile @@ -0,0 +1,32 @@ +OBJS = newt.o test.o button.o form.o checkbox.o entry.o +LIBS = -lslang -lm -lefence +CFLAGS = -g -Wall + +PROGS = test + +SOURCES = $(subst .o,.c,$(OBJS)) + +ifeq (.depend,$(wildcard .depend)) +TARGET=$(PROGS) +else +TARGET=depend $(PROGS) +endif + +all: $(TARGET) + +test: $(OBJS) + gcc -g -o test $(OBJS) $(LIBS) + +veryclean: clean + rm -f .depend + +clean: + rm -f $(PROGS) $(OBJS) core + +depend: + $(CPP) $(CFLAGS) -M $(SOURCES) > .depend + +ifeq (.depend,$(wildcard .depend)) +include .depend +endif + diff --git a/button.c b/button.c new file mode 100644 index 0000000..f29c30c --- /dev/null +++ b/button.c @@ -0,0 +1,127 @@ +#include +#include + +#include "newt.h" +#include "newt_pr.h" + +struct button { + char * text; + char bgColor; +}; + +static void buttonDrawIt(newtComponent co, int active, int pushed); +static void buttonDrawText(newtComponent co, int active, int pushed); + +static void buttonDraw(newtComponent c); +static void buttonDestroy(newtComponent co); +static struct eventResult buttonEvent(struct newtComponent * c, + struct event ev); + +static struct componentOps buttonOps = { + buttonDraw, + buttonEvent, + buttonDestroy, +} ; + +newtComponent newtButton(int left, int row, char * text) { + newtComponent co; + struct button * bu; + + co = malloc(sizeof(*co)); + bu = malloc(sizeof(struct button)); + co->data = bu; + + bu->text = strdup(text); + co->ops = &buttonOps; + + co->height = 4; + co->width = strlen(text) + 5; + co->top = row; + co->left = left; + co->takesFocus = 1; + + newtGotorc(co->top, co->left); + bu->bgColor = (SLsmg_char_at() >> 8) & 0xFF; + + return co; +} + +static void buttonDestroy(newtComponent co) { + struct button * bu = co->data; + + free(bu->text); + free(bu); + free(co); +} + +static void buttonDraw(newtComponent co) { + buttonDrawIt(co, 0, 0); +} + +static void buttonDrawIt(newtComponent co, int active, int pushed) { + struct button * bu = co->data; + + SLsmg_set_color(COLORSET_BUTTON); + if (pushed) { + SLsmg_set_color(COLORSET_BUTTON); + newtDrawBox(co->left + 1, co->top + 1, co->width - 1, 3, 0); + + SLsmg_set_color(bu->bgColor); + newtClearBox(co->left, co->top, co->width, 1); + newtClearBox(co->left, co->top, 1, co->height); + } else { + newtDrawBox(co->left, co->top, co->width - 1, 3, 1); + } + + buttonDrawText(co, active, pushed); +} + +static void buttonDrawText(newtComponent co, int active, int pushed) { + struct button * bu = co->data; + + if (pushed) pushed = 1; + + if (active) + SLsmg_set_color(COLORSET_ACTBUTTON); + else + SLsmg_set_color(COLORSET_BUTTON); + + newtGotorc(co->top + 1 + pushed, co->left + 1 + pushed); + SLsmg_write_char(' '); + SLsmg_write_string(bu->text); + SLsmg_write_char(' '); +} + +static struct eventResult buttonEvent(struct newtComponent * co, + struct event ev) { + struct eventResult er; + + switch (ev.event) { + case EV_FOCUS: + buttonDrawIt(co, 1, 0); + er.result = ER_SWALLOWED; + break; + + case EV_UNFOCUS: + buttonDrawIt(co, 0, 0); + er.result = ER_SWALLOWED; + break; + + case EV_KEYPRESS: + if (ev.u.key == ' ' || ev.u.key == '\r') { + /* look pushed */ + buttonDrawIt(co, 1, 1); + newtRefresh(); + newtDelay(300000); + buttonDrawIt(co, 1, 0); + newtRefresh(); + newtDelay(300000); + + er.result = ER_EXITFORM; + } else + er.result = ER_IGNORED; + break; + } + + return er; +} diff --git a/checkbox.c b/checkbox.c new file mode 100644 index 0000000..4bc1ff7 --- /dev/null +++ b/checkbox.c @@ -0,0 +1,175 @@ +#include +#include +#include + +#include "newt.h" +#include "newt_pr.h" + +struct checkbox { + char * text; + char * seq; + char * result; + newtComponent prevButton, lastButton; + char isRadio; + char value; +}; + +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); + +static struct componentOps cbOps = { + cbDraw, + cbEvent, + cbDestroy, +} ; + +newtComponent newtRadiobutton(int left, int top, 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->isRadio = 1; + + rb->prevButton = prevButton; + + for (curr = co; curr; curr = rb->prevButton) { + rb = curr->data; + rb->lastButton = co; + } + + return co; +} + +newtComponent newtCheckbox(int left, int top, char * text, char defValue, + char * seq, char * result) { + newtComponent co; + struct checkbox * cb; + + if (!seq) seq = " *"; + + co = malloc(sizeof(*co)); + cb = malloc(sizeof(struct checkbox)); + co->data = cb; + + if (result) + cb->result = result; + else + cb->result = &cb->value; + + cb->text = strdup(text); + cb->seq = strdup(seq); + defValue ? (*cb->result = defValue) : (*cb->result = cb->seq[0]); + cb->isRadio = 0; + + co->ops = &cbOps; + + co->height = 1; + co->width = strlen(text) + 4; + co->top = top; + co->left = left; + co->takesFocus = 1; + + return co; +} + +static void cbDraw(newtComponent c) { + cbDrawIt(c, 0); +} + +static void cbDrawIt(newtComponent c, int active) { + struct checkbox * cb = c->data; + + SLsmg_set_color(COLORSET_CHECKBOX); + + newtGotorc(c->top, c->left); + + if (cb->isRadio) + SLsmg_write_string("( ) "); + else + SLsmg_write_string("[ ] "); + + SLsmg_write_string(cb->text); + + if (active) + SLsmg_set_color(COLORSET_ACTCHECKBOX); + + 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(struct newtComponent * co, struct event ev) { + struct eventResult er; + 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; + } + if (curr) { + rb->value = rb->seq[0]; + cbDrawIt(curr, 0); + } + cb->value = cb->seq[1]; + cbDrawIt(co, 1); + } else { + cur = strchr(cb->seq, *cb->result); + if (!cur) + *cb->result = *cb->seq; + else { + cur++; + if (! *cur) + *cb->result = *cb->seq; + else + *cb->result = *cur; + } + cbDrawIt(co, 1); + er.result = ER_SWALLOWED; + } + } else { + er.result = ER_IGNORED; + } + } + + return er; +} diff --git a/entry.c b/entry.c new file mode 100644 index 0000000..7ab4b4d --- /dev/null +++ b/entry.c @@ -0,0 +1,255 @@ +#include +#include +#include + +#include "newt.h" +#include "newt_pr.h" + +struct entry { + int flags; + char * buf; + char ** resultPtr; + int bufAlloced; + int bufUsed; /* amount of the buffer that's been used */ + int cursorPosition; /* cursor *in the string* on on screen */ + int firstChar; /* first character position being shown */ +}; + +static void entryDraw(newtComponent co); +static void entryDestroy(newtComponent co); +static struct eventResult entryEvent(struct newtComponent * co, + struct event ev); + +static struct eventResult entryHandleKey(struct newtComponent * co, int key); + +static struct componentOps entryOps = { + entryDraw, + entryEvent, + entryDestroy, +} ; + +newtComponent newtEntry(int left, int top, char * initialValue, int width, + char ** resultPtr, int flags) { + newtComponent co; + struct entry * en; + + co = malloc(sizeof(*co)); + en = malloc(sizeof(struct entry)); + co->data = en; + + co->top = top; + co->left = left; + co->height = 1; + co->width = width; + co->takesFocus = 1; + + co->ops = &entryOps; + + en->flags = flags; + en->cursorPosition = 0; + en->firstChar = 0; + en->bufUsed = 0; + en->bufAlloced = width + 1; + + if (initialValue && strlen(initialValue) > width) { + en->bufAlloced = strlen(initialValue) + 1; + } + en->buf = malloc(en->bufAlloced); + *resultPtr = en->buf; + en->resultPtr = resultPtr; + + memset(en->buf, 0, en->bufAlloced); + if (initialValue) { + strcpy(en->buf, initialValue); + en->bufUsed = strlen(initialValue); + } + + return co; +} + +static void entryDraw(newtComponent co) { + struct entry * en = co->data; + int i; + char * chptr; + int len; + + if (en->flags & NEWT_ENTRY_HIDDEN) { + newtGotorc(co->top, co->left); + SLsmg_set_color(COLORSET_ENTRY); + for (i = 0; i < co->width; i++) + SLsmg_write_char('_'); + newtGotorc(co->top, co->left); + + return; + } + + newtGotorc(co->top, co->left); + SLsmg_set_color(COLORSET_ENTRY); + + if (en->cursorPosition < en->firstChar) { + /* scroll to the left */ + en->firstChar = en->cursorPosition; + } else if ((en->firstChar + co->width) <= en->cursorPosition) { + /* scroll to the right */ + en->firstChar = en->cursorPosition - co->width + 1; + } + + chptr = en->buf + en->firstChar; + len = strlen(chptr); + + if (len <= co->width) { + i = len; + SLsmg_write_string(chptr); + while (i < co->width) { + SLsmg_write_char('_'); + i++; + } + } else { + SLsmg_write_nstring(chptr, co->width); + } + + newtGotorc(co->top, co->left + (en->cursorPosition - en->firstChar)); +} + +static void entryDestroy(newtComponent co) { + struct entry * en = co->data; + + free(en->buf); + free(en); + free(co); +} + +static struct eventResult entryEvent(struct newtComponent * co, + struct event ev) { + struct entry * en = co->data; + struct eventResult er; + + switch (ev.event) { + case EV_FOCUS: + /*SLtt_set_cursor_visibility(0);*/ + newtGotorc(co->top, co->left + (en->cursorPosition - en->firstChar)); + er.result = ER_SWALLOWED; + break; + + case EV_UNFOCUS: + /*SLtt_set_cursor_visibility(1);*/ + newtGotorc(0, 0); + er.result = ER_SWALLOWED; + break; + + case EV_KEYPRESS: + er = entryHandleKey(co, ev.u.key); + break; + } + + return er; +} + +static struct eventResult entryHandleKey(struct newtComponent * co, int key) { + struct entry * en = co->data; + struct eventResult er; + char * chptr, * insPoint; + + er.result = ER_SWALLOWED; + switch (key) { + case '\001': /* ^A */ + case NEWT_KEY_HOME: + en->cursorPosition = 0; + break; + + case '\005': /* ^E */ + case NEWT_KEY_END: + en->cursorPosition = en->bufUsed; + break; + + case '\013': /* ^K */ + en->bufUsed = en->cursorPosition; + memset(en->buf + en->bufUsed, 0, en->bufAlloced - en->bufUsed); + break; + + case '\002': /* ^B */ + case NEWT_KEY_LEFT: + if (en->cursorPosition) + en->cursorPosition--; + break; + + case '\004': + case NEWT_KEY_DELETE: + chptr = en->buf + en->cursorPosition; + if (*chptr) { + chptr++; + while (*chptr) { + *(chptr - 1) = *chptr; + chptr++; + } + *(chptr - 1) = '\0'; + en->bufUsed--; + } + break; + + case NEWT_KEY_BKSPC: + if (en->cursorPosition) { + /* if this isn't true, there's nothing to erase */ + chptr = en->buf + en->cursorPosition; + en->bufUsed--; + en->cursorPosition--; + while (*chptr) { + *(chptr - 1) = *chptr; + chptr++; + } + *(chptr - 1) = '\0'; + } + break; + + case '\006': /* ^B */ + case NEWT_KEY_RIGHT: + if (en->cursorPosition < en->bufUsed) + en->cursorPosition++; + break; + + default: + if ((key >= 0x20 && key <= 0x7e) || (key >= 0xa0 && key <= 0xff)) { + if (!(en->flags & NEWT_ENTRY_SCROLL) && en->bufUsed == co->width) { + SLtt_beep(); + break; + } + + if ((en->bufUsed + 1) == en->bufAlloced) { + en->bufAlloced += 20; + en->buf = realloc(en->buf, en->bufAlloced); + *en->resultPtr = en->buf; + memset(en->buf + en->bufUsed + 1, 0, 20); + } + + if (en->cursorPosition == en->bufUsed) { + en->bufUsed++; + } else { + /* insert the new character */ + + /* chptr is the last character in the string */ + chptr = (en->buf + en->bufUsed) - 1; + if ((en->bufUsed + 1) == en->bufAlloced) { + /* this string fills the buffer, so clip it */ + chptr--; + } else + en->bufUsed++; + + insPoint = en->buf + en->cursorPosition; + + while (chptr >= insPoint) { + *(chptr + 1) = *chptr; + chptr--; + } + + } + + en->buf[en->cursorPosition++] = key; + } else { + er.result = ER_IGNORED; + } + } + + entryDraw(co); + + return er; +} diff --git a/form.c b/form.c new file mode 100644 index 0000000..fe6dcfe --- /dev/null +++ b/form.c @@ -0,0 +1,158 @@ +#include +#include + +#include "newt.h" +#include "newt_pr.h" + +struct newtForm { + int numCompsAlloced; + newtComponent * comps; + int numComps; + int currComp; +}; + +newtForm newtCreateForm(void) { + newtForm form; + + form = malloc(sizeof(*form)); + form->numCompsAlloced = 5; + form->numComps = 0; + form->currComp = -1; + form->comps = malloc(sizeof(*(form->comps)) * form->numCompsAlloced); + + return form; +} + +static void gotoComponent(newtForm form, int newComp); + +void newtAddComponentToForm(newtForm form, newtComponent co) { + if (form->numCompsAlloced == form->numComps) { + form->numCompsAlloced += 5; + form->comps = realloc(form->comps, + sizeof(*(form->comps)) * form->numCompsAlloced); + } + + form->comps[form->numComps++] = co; +} + +void newtAddComponentsToForm(newtForm form, ...) { + va_list ap; + newtComponent co; + + va_start(ap, form); + + while ((co = va_arg(ap, newtComponent))) + newtAddComponentToForm(form, co); + + va_end(ap); +} + +newtComponent newtRunForm(newtForm form) { + int i; + newtComponent co; + struct event ev; + struct eventResult er; + int key, new; + + /* first, draw all of the components */ + for (i = 0; i < form->numComps; i++) { + co = form->comps[i]; + co->ops->draw(co); + } + + if (form->currComp == -1) + gotoComponent(form, 0); + + do { + co = form->comps[form->currComp]; + + /*newtGotorc(0, 0);*/ + newtRefresh(); + key = newtGetKey(); + + er.result = ER_IGNORED; + + /* handle system wide events */ + switch (key) { + case NEWT_KEY_TAB: + new = form->currComp + 1; + if (new == form->numComps) new = 0; + gotoComponent(form, new); + er.result = ER_SWALLOWED; + break; + } + + /* handle component specific events */ + if (er.result == ER_IGNORED) { + ev.event = EV_KEYPRESS; + ev.u.key = key; + er = co->ops->event(co, ev); + } + + /* handle default events */ + if (er.result == ER_IGNORED) { + switch (key) { + case NEWT_KEY_UP: + case NEWT_KEY_LEFT: + case NEWT_KEY_BKSPC: + if (form->currComp == 0) + new = form->numComps - 1; + else + new = form->currComp - 1; + + gotoComponent(form, new); + break; + + case NEWT_KEY_DOWN: + case NEWT_KEY_RIGHT: + case NEWT_KEY_ENTER: + new = form->currComp + 1; + if (new == form->numComps) new = 0; + gotoComponent(form, new); + break; + } + } + + } while (er.result != ER_EXITFORM); + + newtRefresh(); + + return form->comps[form->currComp]; +} + +/* this also destroys all of the components on the form */ +void newtDestroyForm(newtForm form) { + int i; + newtComponent co; + + /* first, destroy all of the components */ + for (i = 0; i < form->numComps; i++) { + co = form->comps[i]; + if (co->ops->destroy) { + co->ops->destroy(co); + } else { + if (co->data) free(co->data); + free(co); + } + } + + free(form->comps); + free(form); +} + +static void gotoComponent(newtForm form, int newComp) { + newtComponent co; + struct event ev; + + if (form->currComp != -1) { + ev.event = EV_UNFOCUS; + co = form->comps[form->currComp]; + co->ops->event(co, ev); + } + + form->currComp = newComp; + + ev.event = EV_FOCUS; + co = form->comps[form->currComp]; + co->ops->event(co, ev); +} diff --git a/newt.c b/newt.c new file mode 100644 index 0000000..0ce8c29 --- /dev/null +++ b/newt.c @@ -0,0 +1,334 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "newt.h" +#include "newt_pr.h" + +/* this function will be in a future version of slang - I'll just prototype + it myself for now XXX */ +void SLsmg_write_color_chars (unsigned short *s, unsigned int len); + +struct Window { + int height, width, top, left; + short * buffer; +}; + +struct keymap { + char * str; + int code; + char * tc; +}; + +struct Window windowStack[20]; +struct Window * currentWindow = NULL; + +struct newtColors newtDefaultColorPalette = { + "white", "blue", /* root fg, bg */ + "black", "lightgray", /* border fg, bg */ + "black", "lightgray", /* window fg, bg */ + "white", "black", /* shadow fg, bg */ + "red", "lightgray", /* title fg, bg */ + "blue", "magenta", /* button fg, bg */ + "magenta", "blue", /* active button fg, bg */ + "black", "green", /* checkbox fg, fg */ + "green", "black", /* active checkbox fg, bg */ + "yellow", "red", /* entry box fg, bg */ +}; + +struct keymap keymap[] = { + { "\033OA", NEWT_KEY_UP, "kh" }, + { "\033[A", NEWT_KEY_UP, "ku" }, + { "\033OB", NEWT_KEY_DOWN, "kd" }, + { "\033[B", NEWT_KEY_DOWN, "kd" }, + { "\033[C", NEWT_KEY_RIGHT, "kr" }, + { "\033OC", NEWT_KEY_RIGHT, "kr" }, + { "\033[D", NEWT_KEY_LEFT, "kl" }, + { "\033OD", NEWT_KEY_LEFT, "kl" }, + { "\033[H", NEWT_KEY_HOME, "kh" }, + { "\033[1~", NEWT_KEY_HOME, "kh" }, + { "\033Ow", NEWT_KEY_END, "kH" }, + { "\033[4~", NEWT_KEY_END, "kH" }, + + { "\033[3~", NEWT_KEY_DELETE, "kl" }, + + { NULL, 0, NULL }, /* LEAVE this one */ +}; +char keyPrefix = '\033'; + +void newtRefresh(void) { + SLsmg_refresh(); +} + +void newtCls(void) { + SLsmg_set_color(COLORSET_ROOT); + SLsmg_gotorc(0, 0); + SLsmg_erase_eos(); + + newtRefresh(); +} + +int newtInit(void) { + SLtt_get_terminfo(); + + SLtt_Use_Ansi_Colors = 1; + + SLsmg_init_smg(); + SLang_init_tty(0, 0, 0); + + newtSetColors(newtDefaultColorPalette); + /*initKeymap();*/ + + /*SLtt_set_cursor_visibility(0);*/ + + return 0; +} + +int newtFinished(void) { + SLsmg_gotorc(SLtt_Screen_Rows - 1, 0); + SLsmg_refresh(); + SLsmg_reset_smg(); + SLang_reset_tty(); + + return 0; +} + +void newtSetColors(struct newtColors colors) { + SLtt_set_color(COLORSET_ROOT, "", colors.rootFg, colors.rootBg); + SLtt_set_color(COLORSET_BORDER, "", colors.borderFg, colors.borderBg); + SLtt_set_color(COLORSET_WINDOW, "", colors.windowFg, colors.windowBg); + SLtt_set_color(COLORSET_SHADOW, "", colors.shadowFg, colors.shadowBg); + SLtt_set_color(COLORSET_TITLE, "", colors.titleFg, colors.titleBg); + SLtt_set_color(COLORSET_BUTTON, "", colors.buttonFg, colors.buttonBg); + SLtt_set_color(COLORSET_ACTBUTTON, "", colors.actButtonFg, + colors.actButtonBg); + SLtt_set_color(COLORSET_CHECKBOX, "", colors.checkboxFg, colors.checkboxBg); + SLtt_set_color(COLORSET_ACTCHECKBOX, "", colors.actCheckboxFg, + colors.actCheckboxBg); + SLtt_set_color(COLORSET_ENTRY, "", colors.entryFg, colors.entryBg); +} + +int newtGetKey(void) { + int key; + char buf[10], * chptr = buf; + struct keymap * curr; + + key = SLang_getkey(); + + switch (key) { + case 0x7f: + return NEWT_KEY_BKSPC; + + case 0x08: + return NEWT_KEY_BKSPC; + + default: + if (key != keyPrefix) return key; + } + + memset(buf, 0, sizeof(buf)); + + *chptr++ = key; + while (SLang_input_pending(1)) { + key = SLang_getkey(); + *chptr++ = key; + + /* this search should use bsearch(), but when we only look through + a list of 20 (or so) keymappings, it's probably faster just to + do a inline linear search */ + + for (curr = keymap; curr->code; curr++) { + if (curr->str) { + if (!strcmp(curr->str, buf)) + return curr->code; + } + } + } + + for (curr = keymap; curr->code; curr++) { + if (curr->str) { + if (!strcmp(curr->str, buf)) + return curr->code; + } + } + + /* Looks like we were a bit overzealous in reading characters. Return + just the first character, and put everything else back in the buffer + for later */ + + chptr--; + while (chptr > buf) + SLang_ungetkey(*chptr--); + + return *chptr; +} + +void newtWaitForKey(void) { + newtRefresh(); + + SLang_getkey(); + newtClearKeyBuffer(); +} + +void newtClearKeyBuffer(void) { + while (SLang_input_pending(1)) { + SLang_getkey(); + } +} + +int newtOpenWindow(int left, int top, int width, int height, + char * title) { + int i, j, row, col; + int n = 0; + + if (!currentWindow) { + currentWindow = windowStack; + } else { + currentWindow++; + } + + currentWindow->left = left; + currentWindow->top = top; + currentWindow->width = width; + currentWindow->height = height; + + currentWindow->buffer = malloc(sizeof(short) * (width + 3) * (height + 3)); + + row = top - 1; + for (j = 0; j < height + 3; j++, row++) { + col = left - 1; + for (i = 0; i < width + 3; i++, col++) { + SLsmg_gotorc(row, col); + currentWindow->buffer[n++] = SLsmg_char_at(); + } + } + + SLsmg_set_color(COLORSET_BORDER); + SLsmg_draw_box(top - 1, left - 1, height + 2, width + 2); + + if (title) { + i = strlen(title) + 4; + i = ((width - i) / 2) + left; + SLsmg_gotorc(top - 1, i); + SLsmg_set_char_set(1); + SLsmg_write_char(SLSMG_RTEE_CHAR); + SLsmg_set_char_set(0); + SLsmg_write_char(' '); + SLsmg_set_color(COLORSET_TITLE); + SLsmg_write_string(title); + SLsmg_set_color(COLORSET_BORDER); + SLsmg_write_char(' '); + SLsmg_set_char_set(1); + SLsmg_write_char(SLSMG_LTEE_CHAR); + SLsmg_set_char_set(0); + } + + SLsmg_set_color(COLORSET_WINDOW); + SLsmg_fill_region(top, left, height, width, ' '); + + SLsmg_set_color(COLORSET_SHADOW); + SLsmg_fill_region(top + height + 1, left, 1, width + 2, ' '); + SLsmg_fill_region(top, left + width + 1, height + 1, 1, ' '); + + for (i = top; i < (top + height + 1); i++) { + SLsmg_gotorc(i, left + width + 1); + SLsmg_write_string(" "); + } + + return 0; +} + +void newtPopWindow(void) { + int j, row, col; + int n = 0; + + row = col = 0; + + row = currentWindow->top - 1; + col = currentWindow->left - 1; + for (j = 0; j < currentWindow->height + 3; j++, row++) { + SLsmg_gotorc(row, col); + SLsmg_write_color_chars(currentWindow->buffer + n, + currentWindow->width + 3); + n += currentWindow->width + 3; + } + + free(currentWindow->buffer); + + if (currentWindow == windowStack) + currentWindow = NULL; + else + currentWindow--; + + SLsmg_set_char_set(0); + + newtRefresh(); +} + +void newtGotorc(int row, int col) { + if (!currentWindow) + SLsmg_gotorc(row, col); + else + SLsmg_gotorc(row + currentWindow->top, col + currentWindow->left); +} + +void newtDrawBox(int left, int top, int width, int height, int shadow) { + if (currentWindow) { + top += currentWindow->top; + left += currentWindow->left; + } + + SLsmg_draw_box(top, left, height, width); + + if (shadow) { + SLsmg_set_color(COLORSET_SHADOW); + SLsmg_fill_region(top + height, left + 1, 1, width - 1, ' '); + SLsmg_fill_region(top + 1, left + width, height, 1, ' '); + } +} + +void newtClearBox(int left, int top, int width, int height) { + if (currentWindow) { + top += currentWindow->top; + left += currentWindow->left; + } + + SLsmg_fill_region(top, left, height, width, ' '); +} + +#if 0 +/* This doesn't seem to work quite right. I don't know why not, but when + I rsh from an rxvt into a box and run this code, the machine returns + console key's (\033[B) rather then xterm ones (\033OB). */ +static void initKeymap(void) { + struct keymap * curr; + + for (curr = keymap; curr->code; curr++) { + if (!curr->str) + curr->str = SLtt_tgetstr(curr->tc); + } + + /* Newt's keymap handling is a bit broken. It assumes that any extended + keystrokes begin with ESC. If you're using a homebrek terminal you + will probably need to fix this, or just yell at me and I'll be so + ashamed of myself for doing it this way I'll fix it */ + + keyPrefix = 0x1b; /* ESC */ +} +#endif + +void newtDelay(int usecs) { + fd_set set; + struct timeval tv; + + FD_ZERO(&set); + + tv.tv_sec = usecs / 1000000; + tv.tv_usec = usecs % 1000000; + + select(0, &set, &set, &set, &tv); +} diff --git a/newt.h b/newt.h new file mode 100644 index 0000000..820e67c --- /dev/null +++ b/newt.h @@ -0,0 +1,75 @@ +#ifndef H_NEWT +#define H_NEWT + +struct newtColors { + char * rootFg, * rootBg; + char * borderFg, * borderBg; + char * windowFg, * windowBg; + char * shadowFg, * shadowBg; + char * titleFg, * titleBg; + char * buttonFg, * buttonBg; + char * actButtonFg, * actButtonBg; + char * checkboxFg, * checkboxBg; + char * actCheckboxFg, * actCheckboxBg; + char * entryFg, * entryBg; +}; + +extern struct newtColors newtDefaultColorPalette; + +int newtInit(void); +int newtFinished(void); +void newtCls(void); +void newtWaitForKey(void); +void newtClearKeyBuffer(void); +void newtDelay(int usecs); +/* top, left are *not* counting the border */ +int newtOpenWindow(int left, int top, int width, int height, + char * title); +void newtPopWindow(void); +void newtSetColors(struct newtColors colors); +void newtRefresh(void); + +/* Components */ + +typedef struct newtComponent * newtComponent; +typedef struct newtForm * newtForm; + +newtComponent newtButton(int left, int top, char * text); +newtComponent newtCheckbox(int left, int top, char * text, char defValue, + char * seq, char * result); +newtComponent newtRadiobutton(int left, int top, char * text, int isDefault, + newtComponent prevButton); + +#define NEWT_ENTRY_SCROLL (1 << 0) +#define NEWT_ENTRY_HIDDEN (1 << 1) + +newtComponent newtEntry(int left, int top, char * initialValue, int width, + char ** resultPtr, int flags); + +/* Forms */ + +newtForm newtCreateForm(void); +void newtAddComponentToForm(newtForm form, newtComponent co); +void newtAddComponentsToForm(newtForm form, ...); +newtComponent newtRunForm(newtForm form); + +/* this also destroys all of the components on the form */ +void newtDestroyForm(newtForm form); + +/* Key codes */ + +#define NEWT_KEY_TAB '\t' +#define NEWT_KEY_ENTER '\r' +#define NEWT_KEY_RETURN NEWT_KEY_ENTER + +#define NEWT_KEY_EXTRA_BASE 0x8000 +#define NEWT_KEY_UP NEWT_KEY_EXTRA_BASE + 1 +#define NEWT_KEY_DOWN NEWT_KEY_EXTRA_BASE + 2 +#define NEWT_KEY_LEFT NEWT_KEY_EXTRA_BASE + 4 +#define NEWT_KEY_RIGHT NEWT_KEY_EXTRA_BASE + 5 +#define NEWT_KEY_BKSPC NEWT_KEY_EXTRA_BASE + 6 +#define NEWT_KEY_DELETE NEWT_KEY_EXTRA_BASE + 7 +#define NEWT_KEY_HOME NEWT_KEY_EXTRA_BASE + 8 +#define NEWT_KEY_END NEWT_KEY_EXTRA_BASE + 9 + +#endif /* H_NEWT */ diff --git a/newt_pr.h b/newt_pr.h new file mode 100644 index 0000000..e8dfbff --- /dev/null +++ b/newt_pr.h @@ -0,0 +1,52 @@ +#ifndef H_NEWT_PR +#define H_NEWT_PR + +#define COLORSET_ROOT 2 +#define COLORSET_BORDER 3 +#define COLORSET_WINDOW 4 +#define COLORSET_SHADOW 5 +#define COLORSET_TITLE 6 +#define COLORSET_BUTTON 7 +#define COLORSET_ACTBUTTON 8 +#define COLORSET_CHECKBOX 9 +#define COLORSET_ACTCHECKBOX 10 +#define COLORSET_ENTRY 11 + +void newtGotorc(int row, int col); +void newtDrawBox(int left, int top, int width, int height, int shadow); +void newtClearBox(int left, int top, int width, int height); + +int newtGetKey(void); + +struct newtComponent { + /* common data */ + int height, width; + int top, left; + int takesFocus; + + struct componentOps * ops; + + void * data; +} ; + +enum eventResultTypes { ER_IGNORED, ER_SWALLOWED, ER_EXITFORM }; +struct eventResult { + enum eventResultTypes result; +}; + +enum eventTypes { EV_FOCUS, EV_UNFOCUS, EV_KEYPRESS }; + +struct event { + enum eventTypes event; + union { + int key; + } u; +} ; + +struct componentOps { + void (* draw)(struct newtComponent * c); + struct eventResult (* event)(struct newtComponent * c, struct event ev); + void (* destroy)(struct newtComponent * c); +} ; + +#endif /* H_NEWT_PR */ diff --git a/showchars.c b/showchars.c new file mode 100644 index 0000000..0fc117f --- /dev/null +++ b/showchars.c @@ -0,0 +1,44 @@ +#include + +void printall(int offset) { + int n = 0; + int i, j; + + SLsmg_gotorc(0, offset); + SLsmg_write_string(" 0 1 2 3 4 5 6 7 8 9 A B C D E F"); + for (i = 0; i < 16; i++) { + SLsmg_gotorc(i + 1, offset); + SLsmg_printf("%x", i); + for (j = 0; j < 16; j++) { + SLsmg_gotorc(i + 1, (j + 1) * 2 + offset); + SLsmg_write_char(n++); + } + } +} + +int main(void) { + char n = 0; + + SLtt_get_terminfo(); + + SLtt_Use_Ansi_Colors = 1; + + SLsmg_init_smg(); + SLang_init_tty(4, 0, 0); + + SLsmg_cls(); + + printall(0); + SLsmg_set_char_set(1); + printall(40); + + SLsmg_refresh(); + SLang_getkey(); + + SLsmg_gotorc(SLtt_Screen_Rows - 1, 0); + SLsmg_refresh(); + SLsmg_reset_smg(); + SLang_reset_tty(); + + return 0; +} diff --git a/showkey.c b/showkey.c new file mode 100644 index 0000000..51d9193 --- /dev/null +++ b/showkey.c @@ -0,0 +1,41 @@ +#include +#include + +int main(void) { + char n = 0; + int i; + char * buf; + + SLtt_get_terminfo(); + SLang_init_tty(4, 0, 0); + + buf = SLtt_tgetstr("ku"); + if (!buf) { + printf("termcap entry not found for kl\n\r"); + } else { + printf("termcap entry found for kl: ", buf); + while (*buf) { + printf("0x%02x ", *buf++); + } + printf("\n\r"); + } + + printf("\n\r"); + + printf("Press a key: "); + fflush(stdout); + + SLang_input_pending(50); + + printf("\n\r"); + printf("You pressed: "); + + while (SLang_input_pending(1)) { + i = SLang_getkey(); + printf("0x%02x ", i); + } + + printf("\n\r"); + + SLang_reset_tty(); +} diff --git a/test.c b/test.c new file mode 100644 index 0000000..6329d40 --- /dev/null +++ b/test.c @@ -0,0 +1,51 @@ +#include +#include +#include + +#include "newt.h" + +void main(void) { + newtComponent b1, b2, c1, c2, r1, r2, r3, e1, e2, e3; + newtForm f; + char result, result2; + char * enr1, * enr2, * enr3; + + newtInit(); + newtCls(); + + newtOpenWindow(2, 5, 30, 10, "first window"); + newtOpenWindow(20, 10, 40, 13, "window 2"); + + f = newtCreateForm(); + + b1 = newtButton(3, 1, "Push me"); + b2 = newtButton(18, 1, "Not me"); + c1 = newtCheckbox(3, 6, "Check here", ' ', NULL, &result); + c2 = newtCheckbox(3, 7, "Not here ", '*', NULL, &result2); + r1 = newtRadiobutton(20, 6, "Choice 1", 0, NULL); + r2 = newtRadiobutton(20, 7, "Choice 2", 1, r1); + r3 = newtRadiobutton(20, 8, "Choice 3", 0, r2); + + e1 = newtEntry(3, 10, "", 20, &enr1, 0); + e2 = newtEntry(3, 11, "Default", 20, &enr2, NEWT_ENTRY_SCROLL); + e3 = newtEntry(3, 12, NULL, 20, &enr3, NEWT_ENTRY_HIDDEN); + + newtAddComponentsToForm(f, b1, b2, c1, c2, NULL); + newtAddComponentsToForm(f, r1, r2, r3, e1, e2, e3, NULL); + + newtRunForm(f); + + enr1 = strdup(enr1); + enr2 = strdup(enr2); + enr3 = strdup(enr3); + + newtDestroyForm(f); + + newtPopWindow(); + newtPopWindow(); + newtFinished(); + + printf("got string 1: %s\n", enr1); + printf("got string 2: %s\n", enr2); + printf("got string 3: %s\n", enr3); +}