From 6fb96a3f972d005717bc94bcf8836304f920d10f Mon Sep 17 00:00:00 2001 From: ewt Date: Mon, 25 Mar 1996 01:59:25 +0000 Subject: [PATCH] Initial revision --- Makefile | 32 +++++ button.c | 127 ++++++++++++++++++++ checkbox.c | 175 +++++++++++++++++++++++++++ entry.c | 255 +++++++++++++++++++++++++++++++++++++++ form.c | 158 +++++++++++++++++++++++++ newt.c | 334 ++++++++++++++++++++++++++++++++++++++++++++++++++++ newt.h | 75 ++++++++++++ newt_pr.h | 52 ++++++++ showchars.c | 44 +++++++ showkey.c | 41 +++++++ test.c | 51 ++++++++ 11 files changed, 1344 insertions(+) create mode 100644 Makefile create mode 100644 button.c create mode 100644 checkbox.c create mode 100644 entry.c create mode 100644 form.c create mode 100644 newt.c create mode 100644 newt.h create mode 100644 newt_pr.h create mode 100644 showchars.c create mode 100644 showkey.c create mode 100644 test.c 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); +} -- 2.47.2