summaryrefslogtreecommitdiffstats
path: root/mdk-stage1/newt
diff options
context:
space:
mode:
authorGuillaume Cottenceau <gc@mandriva.com>2001-05-14 21:47:42 +0000
committerGuillaume Cottenceau <gc@mandriva.com>2001-05-14 21:47:42 +0000
commit98a18b797c63ea9baab31768ed720ad32c0004e8 (patch)
tree2d8b0d9e845b332060ac668a429ef65ca4c47ed1 /mdk-stage1/newt
parent12cf594c688f3bc3e0b26d35305d5d6db7036fc4 (diff)
downloaddrakx-98a18b797c63ea9baab31768ed720ad32c0004e8.tar
drakx-98a18b797c63ea9baab31768ed720ad32c0004e8.tar.gz
drakx-98a18b797c63ea9baab31768ed720ad32c0004e8.tar.bz2
drakx-98a18b797c63ea9baab31768ed720ad32c0004e8.tar.xz
drakx-98a18b797c63ea9baab31768ed720ad32c0004e8.zip
i can compile slang and newt with dietlibc now
Diffstat (limited to 'mdk-stage1/newt')
-rw-r--r--mdk-stage1/newt/Makefile49
-rw-r--r--mdk-stage1/newt/button.c190
-rw-r--r--mdk-stage1/newt/buttonbar.c46
-rw-r--r--mdk-stage1/newt/checkbox.c290
-rw-r--r--mdk-stage1/newt/checkboxtree.c714
-rw-r--r--mdk-stage1/newt/entry.c376
-rw-r--r--mdk-stage1/newt/form.c712
-rw-r--r--mdk-stage1/newt/grid.c389
-rw-r--r--mdk-stage1/newt/label.c81
-rw-r--r--mdk-stage1/newt/listbox.c752
-rw-r--r--mdk-stage1/newt/newt.c672
-rw-r--r--mdk-stage1/newt/newt.h362
-rw-r--r--mdk-stage1/newt/newt_pr.h82
-rw-r--r--mdk-stage1/newt/scale.c72
-rw-r--r--mdk-stage1/newt/scrollbar.c124
-rw-r--r--mdk-stage1/newt/textbox.c409
-rw-r--r--mdk-stage1/newt/windows.c275
17 files changed, 5595 insertions, 0 deletions
diff --git a/mdk-stage1/newt/Makefile b/mdk-stage1/newt/Makefile
new file mode 100644
index 000000000..c4e6a7207
--- /dev/null
+++ b/mdk-stage1/newt/Makefile
@@ -0,0 +1,49 @@
+ #******************************************************************************
+ #
+ # Guillaume Cottenceau (gc@mandrakesoft.com)
+ #
+ # Copyright 2000 MandrakeSoft
+ #
+ # This software may be freely redistributed under the terms of the GNU
+ # public license.
+ #
+ # You should have received a copy of the GNU General Public License
+ # along with this program; if not, write to the Free Software
+ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ #
+ #*****************************************************************************
+
+top_dir = ..
+
+include $(top_dir)/Makefile.common
+
+
+all: libnewt.a libnewt-DIET.a
+
+clean:
+ rm -f *.o *.a
+
+FLAGS = -Wall -Werror -Os -fomit-frame-pointer -DVERSION=\"0.50.19\" -c
+
+INCS = -I../slang
+
+
+OBJS = newt.o button.o form.o checkbox.o entry.o label.o listbox.o scrollbar.o textbox.o scale.o grid.o windows.o buttonbar.o checkboxtree.o
+OBJS-DIET = $(subst .o,-DIET.o,$(OBJS))
+
+
+libnewt.a: $(OBJS)
+ ar -cru $@ $^
+ ranlib $@
+
+libnewt-DIET.a: $(OBJS-DIET)
+ ar -cru $@ $^
+ ranlib $@
+
+
+$(OBJS): %.o: %.c
+ gcc $(FLAGS) $(GLIBC_INCLUDES) $(INCS) -c $< -o $@
+
+$(OBJS-DIET): %-DIET.o: %.c
+ gcc $(FLAGS) $(DIETLIBC_INCLUDES) $(INCS) -c $< -o $@
+
diff --git a/mdk-stage1/newt/button.c b/mdk-stage1/newt/button.c
new file mode 100644
index 000000000..1ff360dc5
--- /dev/null
+++ b/mdk-stage1/newt/button.c
@@ -0,0 +1,190 @@
+#include <slang.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "newt.h"
+#include "newt_pr.h"
+
+struct button {
+ char * text;
+ int compact;
+};
+
+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(newtComponent c,
+ struct event ev);
+static void buttonPlace(newtComponent co, int newLeft, int newTop);
+
+static struct componentOps buttonOps = {
+ buttonDraw,
+ buttonEvent,
+ buttonDestroy,
+ buttonPlace,
+ newtDefaultMappedHandler,
+} ;
+
+static newtComponent createButton(int left, int row, const char * text, int compact) {
+ newtComponent co;
+ struct button * bu;
+
+ co = malloc(sizeof(*co));
+ bu = malloc(sizeof(struct button));
+ co->data = bu;
+
+ bu->text = strdup(text);
+ bu->compact = compact;
+ co->ops = &buttonOps;
+
+ if (bu->compact) {
+ co->height = 1;
+ co->width = strlen(text) + 3;
+ } else {
+ co->height = 4;
+ co->width = strlen(text) + 5;
+ }
+
+ co->top = row;
+ co->left = left;
+ co->takesFocus = 1;
+ co->isMapped = 0;
+
+ newtGotorc(co->top, co->left);
+
+ return co;
+}
+
+newtComponent newtCompactButton(int left, int row, const char * text) {
+ return createButton(left, row, text, 1);
+}
+
+newtComponent newtButton(int left, int row, const char * text) {
+ return createButton(left, row, text, 0);
+}
+
+static void buttonDestroy(newtComponent co) {
+ struct button * bu = co->data;
+
+ free(bu->text);
+ free(bu);
+ free(co);
+}
+
+static void buttonPlace(newtComponent co, int newLeft, int newTop) {
+ co->top = newTop;
+ co->left = newLeft;
+
+ newtGotorc(co->top, co->left);
+}
+
+static void buttonDraw(newtComponent co) {
+ buttonDrawIt(co, 0, 0);
+}
+
+static void buttonDrawIt(newtComponent co, int active, int pushed) {
+ struct button * bu = co->data;
+
+ if (!co->isMapped) return;
+
+ SLsmg_set_color(NEWT_COLORSET_BUTTON);
+
+ if (bu->compact) {
+ if (active)
+ SLsmg_set_color(NEWT_COLORSET_COMPACTBUTTON);
+ else
+ SLsmg_set_color(NEWT_COLORSET_BUTTON);
+ newtGotorc(co->top+ pushed, co->left + 1 + pushed);
+ SLsmg_write_char('<');
+ SLsmg_write_string(bu->text);
+ SLsmg_write_char('>');
+ } else {
+ if (pushed) {
+ SLsmg_set_color(NEWT_COLORSET_BUTTON);
+ newtDrawBox(co->left + 1, co->top + 1, co->width - 1, 3, 0);
+
+ SLsmg_set_color(NEWT_COLORSET_WINDOW);
+ 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(NEWT_COLORSET_ACTBUTTON);
+ else
+ SLsmg_set_color(NEWT_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(newtComponent co,
+ struct event ev) {
+ struct eventResult er;
+ struct button * bu = co->data;
+
+ if (ev.when == EV_NORMAL) {
+ 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') {
+ if (!bu->compact) {
+ /* look pushed */
+ buttonDrawIt(co, 1, 1);
+ newtRefresh();
+ newtDelay(150000);
+ buttonDrawIt(co, 1, 0);
+ newtRefresh();
+ newtDelay(150000);
+ }
+
+ er.result = ER_EXITFORM;
+ } else
+ er.result = ER_IGNORED;
+ break;
+ case EV_MOUSE:
+ if (ev.u.mouse.type == MOUSE_BUTTON_DOWN &&
+ co->top <= ev.u.mouse.y &&
+ co->top + co->height - !bu->compact > ev.u.mouse.y &&
+ co->left <= ev.u.mouse.x &&
+ co->left + co->width - !bu->compact > ev.u.mouse.x) {
+ if (!bu->compact) {
+ buttonDrawIt(co, 1, 1);
+ newtRefresh();
+ newtDelay(150000);
+ buttonDrawIt(co, 1, 0);
+ newtRefresh();
+ newtDelay(150000);
+ }
+ er.result = ER_EXITFORM;
+ }
+ break;
+ }
+ } else
+ er.result = ER_IGNORED;
+
+ return er;
+}
diff --git a/mdk-stage1/newt/buttonbar.c b/mdk-stage1/newt/buttonbar.c
new file mode 100644
index 000000000..45473c9d2
--- /dev/null
+++ b/mdk-stage1/newt/buttonbar.c
@@ -0,0 +1,46 @@
+#include <stdarg.h>
+
+#include "newt.h"
+
+/* if they try and pack more then 50 buttons, screw 'em */
+newtGrid newtButtonBarv(char * button1, newtComponent * b1comp, va_list args) {
+ newtGrid grid;
+ struct buttonInfo {
+ char * name;
+ newtComponent * compPtr;
+ } buttons[50];
+ int num;
+ int i;
+
+ buttons[0].name = button1, buttons[0].compPtr = b1comp, num = 1;
+ while (1) {
+ buttons[num].name = va_arg(args, char *);
+ if (!buttons[num].name) break;
+ buttons[num].compPtr = va_arg(args, newtComponent *);
+ num++;
+ }
+
+ grid = newtCreateGrid(num, 1);
+
+ for (i = 0; i < num; i++) {
+ *buttons[i].compPtr = newtButton(-1, -1, buttons[i].name);
+ newtGridSetField(grid, i, 0, NEWT_GRID_COMPONENT,
+ *buttons[i].compPtr,
+ num ? 1 : 0, 0, 0, 0, 0, 0);
+ }
+
+ return grid;
+}
+
+newtGrid newtButtonBar(char * button1, newtComponent * b1comp, ...) {
+ va_list args;
+ newtGrid grid;
+
+ va_start(args, b1comp);
+
+ grid = newtButtonBarv(button1, b1comp, args);
+
+ va_end(args);
+
+ return grid;
+}
diff --git a/mdk-stage1/newt/checkbox.c b/mdk-stage1/newt/checkbox.c
new file mode 100644
index 000000000..eee514c98
--- /dev/null
+++ b/mdk-stage1/newt/checkbox.c
@@ -0,0 +1,290 @@
+#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;
+
+ 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);
+}
diff --git a/mdk-stage1/newt/checkboxtree.c b/mdk-stage1/newt/checkboxtree.c
new file mode 100644
index 000000000..b56bd1e9f
--- /dev/null
+++ b/mdk-stage1/newt/checkboxtree.c
@@ -0,0 +1,714 @@
+#include <slang.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "newt.h"
+#include "newt_pr.h"
+
+struct items {
+ char * text;
+ const void *data;
+ unsigned char selected;
+ struct items *next;
+ struct items *prev;
+ struct items *branch;
+ int flags;
+ int depth;
+};
+
+struct CheckboxTree {
+ newtComponent sb;
+ int curWidth; /* size of text w/o scrollbar or border*/
+ int curHeight; /* size of text w/o border */
+ struct items * itemlist;
+ struct items ** flatList, ** currItem, ** firstItem;
+ int flatCount;
+ int flags;
+ int pad;
+ char * seq;
+ char * result;
+};
+
+static void ctDraw(newtComponent c);
+static void ctDestroy(newtComponent co);
+static void ctPlace(newtComponent co, int newLeft, int newTop);
+struct eventResult ctEvent(newtComponent co, struct event ev);
+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 struct componentOps ctOps = {
+ ctDraw,
+ ctEvent,
+ ctDestroy,
+ ctPlace,
+ ctMapped,
+} ;
+
+static int countItems(struct items * item, enum countWhat what) {
+ int count = 0;
+
+ while (item) {
+ if ((!item->branch && item->selected == what) || (what == COUNT_EXPOSED))
+ count++;
+ if (item->branch || (what == COUNT_EXPOSED && item->selected))
+ count += countItems(item->branch, what);
+ item = item->next;
+ }
+
+ return count;
+}
+
+static void doBuildFlatList(struct CheckboxTree * ct, struct items * item) {
+ while (item) {
+ ct->flatList[ct->flatCount++] = item;
+ if (item->branch && item->selected) doBuildFlatList(ct, item->branch);
+ item = item->next;
+ }
+}
+
+static void buildFlatList(newtComponent co) {
+ struct CheckboxTree * ct = co->data;
+
+ if (ct->flatList) free(ct->flatList);
+ ct->flatCount = countItems(ct->itemlist, COUNT_EXPOSED);
+
+ ct->flatList = malloc(sizeof(*ct->flatList) * (ct->flatCount+1));
+ ct->flatCount = 0;
+ doBuildFlatList(ct, ct->itemlist);
+ ct->flatList[ct->flatCount] = NULL;
+}
+
+int newtCheckboxTreeAddItem(newtComponent co,
+ const char * text, const void * data,
+ int flags, int index, ...) {
+ va_list argList;
+ int numIndexes;
+ int * indexes;
+ int i;
+
+ va_start(argList, index);
+ numIndexes = 0;
+ i = index;
+ while (i != NEWT_ARG_LAST) {
+ numIndexes++;
+ i = va_arg(argList, int);
+ }
+
+ va_end(argList);
+
+ indexes = alloca(sizeof(*indexes) * (numIndexes + 1));
+ 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);
+ }
+ va_end(argList);
+
+ indexes[numIndexes++] = NEWT_ARG_LAST;
+
+ return newtCheckboxTreeAddArray(co, text, data, flags, indexes);
+}
+
+static int doFindItemPath(struct items * items, void * data, int * path,
+ int * len) {
+ int where = 0;
+
+ while (items) {
+ if (items->data == data) {
+ if (path) path[items->depth] = where;
+ if (len) *len = items->depth + 1;
+ return 1;
+ }
+
+ if (items->branch && doFindItemPath(items->branch, data, path, len)) {
+ if (path) path[items->depth] = where;
+ return 1;
+ }
+
+ items = items->next;
+ where++;
+ }
+
+ return 0;
+}
+
+int * newtCheckboxTreeFindItem(newtComponent co, void * data) {
+ int len;
+ int * path;
+ struct CheckboxTree * ct = co->data;
+
+ if (!doFindItemPath(ct->itemlist, data, NULL, &len)) return NULL;
+
+ path = malloc(sizeof(*path) * (len + 1));
+ doFindItemPath(ct->itemlist, data, path, NULL);
+ path[len] = NEWT_ARG_LAST;
+
+ return path;
+}
+
+int newtCheckboxTreeAddArray(newtComponent co,
+ const char * text, const void * data,
+ int flags, int * indexes) {
+ struct items * curList, * newNode, * item = NULL;
+ struct items ** listPtr = NULL;
+ int i, index, numIndexes;
+ struct CheckboxTree * ct = co->data;
+
+ numIndexes = 0;
+ while (indexes[numIndexes] != NEWT_ARG_LAST) numIndexes++;
+
+ if (!ct->itemlist) {
+ if (numIndexes > 1) return -1;
+
+ ct->itemlist = malloc(sizeof(*ct->itemlist));
+ item = ct->itemlist;
+ item->prev = NULL;
+ item->next = NULL;
+ } else {
+ curList = ct->itemlist;
+ listPtr = &ct->itemlist;
+
+ i = 0;
+ index = indexes[i];
+ while (i < numIndexes) {
+ item = curList;
+
+ if (index == NEWT_ARG_APPEND) {
+ item = NULL;
+ } else {
+ while (index && item)
+ item = item->next, index--;
+ }
+
+ i++;
+ if (i < numIndexes) {
+ curList = item->branch;
+ listPtr = &item->branch;
+ if (!curList && (i + 1 != numIndexes)) return -1;
+
+ index = indexes[i];
+ }
+ }
+
+ if (!curList) { /* create a new branch */
+ item = malloc(sizeof(*curList->prev));
+ item->next = item->prev = NULL;
+ *listPtr = item;
+ } else if (!item) { /* append to end */
+ item = curList;
+ while (item->next) item = item->next;
+ item->next = malloc(sizeof(*curList->prev));
+ item->next->prev = item;
+ item = item->next;
+ item->next = NULL;
+ } else {
+ newNode = malloc(sizeof(*newNode));
+ newNode->prev = item->prev;
+ newNode->next = item;
+
+ if (item->prev) item->prev->next = newNode;
+ item->prev = newNode;
+ item = newNode;
+ if (!item->prev) *listPtr = item;
+ }
+ }
+
+ item->text = strdup(text);
+ item->data = data;
+ if (flags & NEWT_FLAG_SELECTED) {
+ item->selected = 1;
+ } else {
+ item->selected = 0;
+ }
+ item->flags = flags;
+ item->branch = NULL;
+ item->depth = numIndexes - 1;
+
+ i = 4 + (3 * item->depth);
+
+ if ((strlen(text) + i + ct->pad) > co->width) {
+ co->width = strlen(text) + i + ct->pad;
+ }
+
+ return 0;
+}
+
+static struct items * findItem(struct items * items, const void * data) {
+ struct items * i;
+
+ while (items) {
+ if (items->data == data) return items;
+ if (items->branch) {
+ i = findItem(items->branch, data);
+ if (i) return i;
+ }
+
+ items = items->next;
+ }
+
+ return NULL;
+}
+
+static void listSelected(struct items * items, int * num, const void ** list, int seqindex) {
+ while (items) {
+ if ((seqindex ? items->selected==seqindex : items->selected) && !items->branch)
+ list[(*num)++] = (void *) items->data;
+ if (items->branch)
+ listSelected(items->branch, num, list, seqindex);
+ items = items->next;
+ }
+}
+
+const void ** newtCheckboxTreeGetSelection(newtComponent co, int *numitems)
+{
+ return newtCheckboxTreeGetMultiSelection(co, numitems, 0);
+}
+
+const void ** newtCheckboxTreeGetMultiSelection(newtComponent co, int *numitems, char seqnum)
+{
+ struct CheckboxTree * ct;
+ const void **retval;
+ int seqindex=0;
+
+ if(!co || !numitems) return NULL;
+
+ ct = co->data;
+
+ if (seqnum) {
+ while( ct->seq[seqindex] && ( ct->seq[seqindex] != seqnum )) seqindex++;
+ } else {
+ seqindex = 0;
+ }
+
+ *numitems = countItems(ct->itemlist, (seqindex ? seqindex : COUNT_SELECTED));
+ if (!*numitems) return NULL;
+
+ retval = malloc(*numitems * sizeof(void *));
+ *numitems = 0;
+ listSelected(ct->itemlist, numitems, retval, seqindex);
+
+ return retval;
+}
+
+newtComponent newtCheckboxTree(int left, int top, int height, int flags) {
+ return newtCheckboxTreeMulti(left, top, height, NULL, flags);
+}
+
+newtComponent newtCheckboxTreeMulti(int left, int top, int height, char *seq, int flags) {
+ newtComponent co;
+ struct CheckboxTree * ct;
+
+ co = malloc(sizeof(*co));
+ ct = malloc(sizeof(struct CheckboxTree));
+ co->callback = NULL;
+ co->data = ct;
+ co->ops = &ctOps;
+ co->takesFocus = 1;
+ co->height = height;
+ co->width = 0;
+ co->isMapped = 0;
+ ct->itemlist = NULL;
+ ct->firstItem = NULL;
+ ct->currItem = NULL;
+ ct->flatList = NULL;
+ if (seq)
+ ct->seq = strdup(seq);
+ else
+ ct->seq = strdup(" *");
+ if (flags & NEWT_FLAG_SCROLL) {
+ ct->sb = newtVerticalScrollbar(left, top, height,
+ COLORSET_LISTBOX, COLORSET_ACTLISTBOX);
+ ct->pad = 2;
+ } else {
+ ct->sb = NULL;
+ ct->pad = 0;
+ }
+
+ return co;
+}
+
+static void ctMapped(newtComponent co, int isMapped) {
+ struct CheckboxTree * ct = co->data;
+
+ co->isMapped = isMapped;
+ if (ct->sb)
+ ct->sb->ops->mapped(ct->sb, isMapped);
+}
+
+static void ctPlace(newtComponent co, int newLeft, int newTop) {
+ struct CheckboxTree * ct = co->data;
+
+ co->top = newTop;
+ co->left = newLeft;
+
+ if (ct->sb)
+ ct->sb->ops->place(ct->sb, co->left + co->width - 1, co->top);
+}
+
+int ctSetItem(newtComponent co, struct items *item, enum newtFlagsSense sense)
+{
+ struct CheckboxTree * ct = co->data;
+ struct items * currItem;
+ struct items * firstItem;
+
+ if (!item)
+ return 1;
+
+ switch(sense) {
+ case NEWT_FLAGS_RESET:
+ item->selected = 0;
+ break;
+ case NEWT_FLAGS_SET:
+ item->selected = 1;
+ break;
+ case NEWT_FLAGS_TOGGLE:
+ if (item->branch)
+ item->selected = !item->selected;
+ else {
+ item->selected++;
+ if (item->selected==strlen(ct->seq))
+ item->selected = 0;
+ }
+ break;
+ }
+
+ if (item->branch) {
+ currItem = *ct->currItem;
+ firstItem = *ct->firstItem;
+
+ buildFlatList(co);
+
+ ct->currItem = ct->flatList;
+ while (*ct->currItem != currItem) ct->currItem++;
+
+ ct->firstItem = ct->flatList;
+ if (ct->flatCount > co->height) {
+ struct items ** last = ct->flatList + ct->flatCount - co->height;
+ while (*ct->firstItem != firstItem && ct->firstItem != last)
+ ct->firstItem++;
+ }
+ }
+
+ return 0;
+}
+
+static void ctSetItems(struct items *item, int selected)
+{
+ for (; item; item = item->next) {
+ if (!item->branch)
+ item->selected = selected;
+ else
+ ctSetItems(item->branch, selected);
+ }
+}
+
+static void ctDraw(newtComponent co) {
+ struct CheckboxTree * ct = co->data;
+ struct items ** item;
+ int i, j;
+ char * spaces = NULL;
+ int currRow = -1;
+
+ if (!co->isMapped) return ;
+
+ if (!ct->firstItem) {
+ buildFlatList(co);
+ ct->firstItem = ct->currItem = ct->flatList;
+ }
+
+ item = ct->firstItem;
+
+ i = 0;
+ 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);
+
+ for (j = 0; j < (*item)->depth; j++)
+ SLsmg_write_string(" ");
+
+ if ((*item)->branch) {
+ if ((*item)->selected)
+ SLsmg_write_string("<-> ");
+ else
+ SLsmg_write_string("<+> ");
+ } else {
+ char tmp[5];
+ snprintf(tmp,5,"[%c] ",ct->seq[(*item)->selected]);
+ SLsmg_write_string(tmp);
+ }
+
+ SLsmg_write_nstring((*item)->text, co->width - 4 -
+ (3 * (*item)->depth));
+ item++;
+ i++;
+ }
+
+ /* There could be empty lines left (i.e. if the user closes an expanded
+ 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);
+ memset(spaces, ' ', co->width);
+ SLsmg_set_color(NEWT_COLORSET_LISTBOX);
+ }
+ while (i < co->height) {
+ newtGotorc(co->top + i, co->left);
+ SLsmg_write_nstring(spaces, co->width);
+ i++;
+ }
+
+ if(ct->sb) {
+ newtScrollbarSet(ct->sb, ct->currItem - ct->flatList,
+ ct->flatCount - 1);
+ ct->sb->ops->draw(ct->sb);
+ }
+
+ newtGotorc(currRow, co->left + 1);
+}
+
+static void ctDestroy(newtComponent co) {
+ struct CheckboxTree * ct = co->data;
+ struct items * item, * nextitem;
+
+ nextitem = item = ct->itemlist;
+
+ while (item != NULL) {
+ nextitem = item->next;
+ free(item->text);
+ free(item);
+ item = nextitem;
+ }
+
+ free(ct->seq);
+ free(ct);
+ free(co);
+}
+
+struct eventResult ctEvent(newtComponent co, struct event ev) {
+ struct CheckboxTree * ct = co->data;
+ struct eventResult er;
+ struct items ** listEnd, ** lastItem;
+ int key, selnum = 1;
+
+ er.result = ER_IGNORED;
+
+ if(ev.when == EV_EARLY || ev.when == EV_LATE) {
+ return er;
+ }
+
+ switch(ev.event) {
+ case EV_KEYPRESS:
+ key = ev.u.key;
+ if (key == (char) key && key != ' ') {
+ for (selnum = 0; ct->seq[selnum]; selnum++)
+ if (key == ct->seq[selnum])
+ break;
+ if (!ct->seq[selnum])
+ switch (key) {
+ case '-': selnum = 0; break;
+ case '+':
+ case '*': selnum = 1; break;
+ }
+ if (ct->seq[selnum])
+ key = '*';
+ }
+ switch(key) {
+ case ' ':
+ case NEWT_KEY_ENTER:
+ ctSetItem(co, *ct->currItem, NEWT_FLAGS_TOGGLE);
+ er.result = ER_SWALLOWED;
+ if (!(*ct->currItem)->branch || (*ct->currItem)->selected)
+ key = NEWT_KEY_DOWN;
+ else
+ key = '*';
+ break;
+ case '*':
+ if ((*ct->currItem)->branch) {
+ ctSetItems((*ct->currItem)->branch, selnum);
+ if (!(*ct->currItem)->selected)
+ key = NEWT_KEY_DOWN;
+ } else {
+ (*ct->currItem)->selected = selnum;
+ key = NEWT_KEY_DOWN;
+ }
+ er.result = ER_SWALLOWED;
+ break;
+ }
+ switch (key) {
+ case '*':
+ ctDraw(co);
+ if(co->callback) co->callback(co, co->callbackData);
+ return er;
+ case NEWT_KEY_HOME:
+ ct->currItem = ct->flatList;
+ ct->firstItem = ct->flatList;
+ ctDraw(co);
+ if(co->callback) co->callback(co, co->callbackData);
+ er.result = ER_SWALLOWED;
+ return er;
+ case NEWT_KEY_END:
+ ct->currItem = ct->flatList + ct->flatCount - 1;
+ if (ct->flatCount <= co->height)
+ ct->firstItem = ct->flatList;
+ else
+ ct->firstItem = ct->flatList + ct->flatCount - co->height;
+ ctDraw(co);
+ if(co->callback) co->callback(co, co->callbackData);
+ er.result = ER_SWALLOWED;
+ return er;
+ case NEWT_KEY_DOWN:
+ if (ev.u.key != NEWT_KEY_DOWN) {
+ if(co->callback) co->callback(co, co->callbackData);
+ if (strlen(ct->seq) != 2) {
+ ctDraw(co);
+ return er;
+ }
+ }
+ if ((ct->currItem - ct->flatList + 1) < ct->flatCount) {
+ ct->currItem++;
+
+ if (ct->currItem - ct->firstItem >= co->height)
+ ct->firstItem++;
+
+ ctDraw(co);
+ } else if (ev.u.key != NEWT_KEY_DOWN)
+ ctDraw(co);
+ if(co->callback) co->callback(co, co->callbackData);
+ er.result = ER_SWALLOWED;
+ return er;
+ case NEWT_KEY_UP:
+ if (ct->currItem != ct->flatList) {
+ ct->currItem--;
+
+ if (ct->currItem < ct->firstItem)
+ ct->firstItem = ct->currItem;
+
+ ctDraw(co);
+ }
+ er.result = ER_SWALLOWED;
+ if(co->callback) co->callback(co, co->callbackData);
+ return er;
+ case NEWT_KEY_PGUP:
+ if (ct->firstItem - co->height < ct->flatList) {
+ ct->firstItem = ct->currItem = ct->flatList;
+ } else {
+ ct->currItem -= co->height;
+ ct->firstItem -= co->height;
+ }
+
+ ctDraw(co);
+ if(co->callback) co->callback(co, co->callbackData);
+ er.result = ER_SWALLOWED;
+ return er;
+ case NEWT_KEY_PGDN:
+ listEnd = ct->flatList + ct->flatCount - 1;
+ lastItem = ct->firstItem + co->height - 1;
+
+ if (lastItem + co->height > listEnd) {
+ ct->firstItem = listEnd - co->height + 1;
+ ct->currItem = listEnd;
+ } else {
+ ct->currItem += co->height;
+ ct->firstItem += co->height;
+ }
+
+ ctDraw(co);
+ if(co->callback) co->callback(co, co->callbackData);
+ er.result = ER_SWALLOWED;
+ return er;
+ }
+ break;
+
+ case EV_FOCUS:
+ ctDraw(co);
+ er.result = ER_SWALLOWED;
+ break;
+
+ case EV_UNFOCUS:
+ ctDraw(co);
+ er.result = ER_SWALLOWED;
+ break;
+ default:
+ break;
+ }
+
+ return er;
+}
+
+const void * newtCheckboxTreeGetCurrent(newtComponent co) {
+ struct CheckboxTree * ct = co->data;
+
+ if (!ct->currItem) return NULL;
+ return (*ct->currItem)->data;
+}
+
+void newtCheckboxTreeSetEntry(newtComponent co, const void * data, const char * text)
+{
+ struct CheckboxTree * ct;
+ struct items * item;
+ int i;
+
+ if (!co) return;
+ ct = co->data;
+ item = findItem(ct->itemlist, data);
+ if (!item) return;
+
+ free(item->text);
+ item->text = strdup(text);
+
+ i = 4 + (3 * item->depth);
+
+ if ((strlen(text) + i + ct->pad) > co->width) {
+ co->width = strlen(text) + i + ct->pad;
+ }
+
+ ctDraw(co);
+}
+
+char newtCheckboxTreeGetEntryValue(newtComponent co, const void * data)
+{
+ struct CheckboxTree * ct;
+ struct items * item;
+
+ if (!co) return -1;
+ ct = co->data;
+ item = findItem(ct->itemlist, data);
+ if (!item) return -1;
+ if (item->branch)
+ return item->selected ? NEWT_CHECKBOXTREE_EXPANDED : NEWT_CHECKBOXTREE_COLLAPSED;
+ else
+ return ct->seq[item->selected];
+}
+
+void newtCheckboxTreeSetEntryValue(newtComponent co, const void * data, char value)
+{
+ struct CheckboxTree * ct;
+ struct items * item;
+ int i;
+
+ if (!co) return;
+ ct = co->data;
+ item = findItem(ct->itemlist, data);
+ if (!item || item->branch) return;
+
+ for(i = 0; ct->seq[i]; i++)
+ if (value == ct->seq[i])
+ break;
+
+ if (!ct->seq[i]) return;
+ item->selected = i;
+
+ ctDraw(co);
+}
+
diff --git a/mdk-stage1/newt/entry.c b/mdk-stage1/newt/entry.c
new file mode 100644
index 000000000..154edba71
--- /dev/null
+++ b/mdk-stage1/newt/entry.c
@@ -0,0 +1,376 @@
+#include <ctype.h>
+#include <slang.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 */
+ newtEntryFilter filter;
+ void * filterData;
+};
+
+static void entryDraw(newtComponent co);
+static void entryDestroy(newtComponent co);
+static struct eventResult entryEvent(newtComponent co,
+ struct event ev);
+
+static struct eventResult entryHandleKey(newtComponent co, int key);
+
+static struct componentOps entryOps = {
+ entryDraw,
+ entryEvent,
+ entryDestroy,
+ newtDefaultPlaceHandler,
+ newtDefaultMappedHandler,
+} ;
+
+void newtEntrySet(newtComponent co, const char * value, int cursorAtEnd) {
+ struct entry * en = co->data;
+
+ if ((strlen(value) + 1) > (unsigned int)en->bufAlloced) {
+ free(en->buf);
+ en->bufAlloced = strlen(value) + 1;
+ en->buf = malloc(en->bufAlloced);
+ if (en->resultPtr) *en->resultPtr = en->buf;
+ }
+ memset(en->buf, 0, en->bufAlloced); /* clear the buffer */
+ strcpy(en->buf, value);
+ en->bufUsed = strlen(value);
+ en->firstChar = 0;
+ if (cursorAtEnd)
+ en->cursorPosition = en->bufUsed;
+ else
+ en->cursorPosition = 0;
+
+ entryDraw(co);
+} ;
+
+newtComponent newtEntry(int left, int top, const 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->isMapped = 0;
+ co->callback = NULL;
+
+ co->ops = &entryOps;
+
+ en->flags = flags;
+ en->cursorPosition = 0;
+ en->firstChar = 0;
+ en->bufUsed = 0;
+ en->bufAlloced = width + 1;
+ en->filter = NULL;
+
+ if (!(en->flags & NEWT_FLAG_DISABLED))
+ co->takesFocus = 1;
+ else
+ co->takesFocus = 0;
+
+ if (initialValue && strlen(initialValue) > (unsigned int)width) {
+ en->bufAlloced = strlen(initialValue) + 1;
+ }
+ en->buf = malloc(en->bufAlloced);
+ en->resultPtr = resultPtr;
+ if (en->resultPtr) *en->resultPtr = en->buf;
+
+ memset(en->buf, 0, en->bufAlloced);
+ if (initialValue) {
+ strcpy(en->buf, initialValue);
+ en->bufUsed = strlen(initialValue);
+ en->cursorPosition = en->bufUsed;
+ } else {
+ *en->buf = '\0';
+ en->bufUsed = 0;
+ en->cursorPosition = 0;
+ }
+
+ return co;
+}
+
+static void entryDraw(newtComponent co) {
+ struct entry * en = co->data;
+ int i;
+ char * chptr;
+ int len;
+
+ if (!co->isMapped) return;
+
+ if (en->flags & NEWT_FLAG_DISABLED)
+ SLsmg_set_color(NEWT_COLORSET_DISENTRY);
+ else
+ SLsmg_set_color(NEWT_COLORSET_ENTRY);
+
+ if (en->flags & NEWT_FLAG_HIDDEN) {
+ newtGotorc(co->top, co->left);
+ for (i = 0; i < co->width; i++)
+ SLsmg_write_char('_');
+ newtGotorc(co->top, co->left);
+
+ return;
+ }
+
+ newtGotorc(co->top, co->left);
+
+ 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;
+
+ if (en->flags & NEWT_FLAG_PASSWORD) {
+ char *tmpptr, *p;
+
+ tmpptr = alloca(strlen(chptr+2));
+ strcpy(tmpptr, chptr);
+ for (p = tmpptr; *p; p++)
+ *p = '*';
+ chptr = tmpptr;
+ }
+
+ 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);
+ }
+
+ if (en->flags & NEWT_FLAG_HIDDEN)
+ newtGotorc(co->top, co->left);
+ else
+ newtGotorc(co->top, co->left + (en->cursorPosition - en->firstChar));
+}
+
+void newtEntrySetFlags(newtComponent co, int flags, enum newtFlagsSense sense) {
+ struct entry * en = co->data;
+ int row, col;
+
+ en->flags = newtSetFlags(en->flags, flags, sense);
+
+ if (!(en->flags & NEWT_FLAG_DISABLED))
+ co->takesFocus = 1;
+ else
+ co->takesFocus = 0;
+
+ newtGetrc(&row, &col);
+ entryDraw(co);
+ newtGotorc(row, col);
+}
+
+static void entryDestroy(newtComponent co) {
+ struct entry * en = co->data;
+
+ free(en->buf);
+ free(en);
+ free(co);
+}
+
+static struct eventResult entryEvent(newtComponent co,
+ struct event ev) {
+ struct entry * en = co->data;
+ struct eventResult er;
+ int ch;
+
+ if (ev.when == EV_NORMAL) {
+ switch (ev.event) {
+ case EV_FOCUS:
+ newtCursorOn();
+ if (en->flags & NEWT_FLAG_HIDDEN)
+ newtGotorc(co->top, co->left);
+ else
+ newtGotorc(co->top, co->left +
+ (en->cursorPosition - en->firstChar));
+ er.result = ER_SWALLOWED;
+ break;
+
+ case EV_UNFOCUS:
+ newtCursorOff();
+ newtGotorc(0, 0);
+ er.result = ER_SWALLOWED;
+ if (co->callback)
+ co->callback(co, co->callbackData);
+ break;
+
+ case EV_KEYPRESS:
+ ch = ev.u.key;
+ if (en->filter)
+ ch = en->filter(co, en->filterData, ch, en->cursorPosition);
+ if (ch) er = entryHandleKey(co, ch);
+ break;
+
+ case EV_MOUSE:
+ if ((ev.u.mouse.type == MOUSE_BUTTON_DOWN) &&
+ (en->flags ^ NEWT_FLAG_HIDDEN)) {
+ if (strlen(en->buf) >= ev.u.mouse.x - co->left) {
+ en->cursorPosition = ev.u.mouse.x - co->left;
+ newtGotorc(co->top,
+ co->left +(en->cursorPosition - en->firstChar));
+ } else {
+ en->cursorPosition = strlen(en->buf);
+ newtGotorc(co->top,
+ co->left +(en->cursorPosition - en->firstChar));
+ }
+ }
+ break;
+ }
+ } else
+ er.result = ER_IGNORED;
+
+ return er;
+}
+
+static struct eventResult entryHandleKey(newtComponent co, int key) {
+ struct entry * en = co->data;
+ struct eventResult er;
+ char * chptr, * insPoint;
+
+ er.result = ER_SWALLOWED;
+ switch (key) {
+ case '\r': /* Return */
+ if (en->flags & NEWT_FLAG_RETURNEXIT) {
+ er.result = ER_EXITFORM;
+ } else {
+ er.result = ER_NEXTCOMP;
+ }
+ break;
+
+ 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_FLAG_SCROLL) && en->bufUsed >= co->width) {
+ SLtt_beep();
+ break;
+ }
+
+ if ((en->bufUsed + 1) == en->bufAlloced) {
+ en->bufAlloced += 20;
+ en->buf = realloc(en->buf, en->bufAlloced);
+ if (en->resultPtr) *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;
+}
+
+char * newtEntryGetValue(newtComponent co) {
+ struct entry * en = co->data;
+
+ return en->buf;
+}
+
+void newtEntrySetFilter(newtComponent co, newtEntryFilter filter, void * data) {
+ struct entry * en = co->data;
+ en->filter = filter;
+ en->filterData = data;
+}
diff --git a/mdk-stage1/newt/form.c b/mdk-stage1/newt/form.c
new file mode 100644
index 000000000..4ad465e38
--- /dev/null
+++ b/mdk-stage1/newt/form.c
@@ -0,0 +1,712 @@
+#include <unistd.h>
+#include <slang.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include "newt.h"
+#include "newt_pr.h"
+
+
+/****************************************************************************
+ These forms handle vertical scrolling of components with a height of 1
+
+ Horizontal scrolling won't work, and scrolling large widgets will fail
+ miserably. It shouldn't be too hard to fix either of those if anyone
+ cares to. I only use scrolling for listboxes and text boxes though so
+ I didn't bother.
+*****************************************************************************/
+
+struct element {
+ int top, left; /* Actual, not virtual. These are translated */
+ newtComponent co; /* into actual through vertOffset */
+};
+
+struct fdInfo {
+ int fd;
+ int flags;
+};
+
+struct form {
+ int numCompsAlloced;
+ struct element * elements;
+ int numComps;
+ int currComp;
+ int fixedHeight;
+ int flags;
+ int vertOffset;
+ newtComponent vertBar, exitComp;
+ const char * help;
+ int numRows;
+ int * hotKeys;
+ int numHotKeys;
+ int background;
+ int beenSet;
+ int numFds;
+ struct fdInfo * fds;
+ int maxFd;
+ int timer; /* in milliseconds */
+ struct timeval lastTimeout;
+ void * helpTag;
+ newtCallback helpCb;
+};
+
+static void gotoComponent(struct form * form, int newComp);
+static struct eventResult formEvent(newtComponent co, struct event ev);
+static struct eventResult sendEvent(newtComponent comp, struct event ev);
+static void formPlace(newtComponent co, int left, int top);
+
+/* Global, ick */
+static newtCallback helpCallback;
+
+/* this isn't static as grid.c tests against it to find forms */
+struct componentOps formOps = {
+ newtDrawForm,
+ formEvent,
+ newtFormDestroy,
+ formPlace,
+ newtDefaultMappedHandler,
+} ;
+
+static inline int componentFits(newtComponent co, int compNum) {
+ struct form * form = co->data;
+ struct element * el = form->elements + compNum;
+
+ if ((co->top + form->vertOffset) > el->top) return 0;
+ if ((co->top + form->vertOffset + co->height) <
+ (el->top + el->co->height)) return 0;
+
+ return 1;
+}
+
+newtComponent newtForm(newtComponent vertBar, void * help, int flags) {
+ newtComponent co;
+ struct form * form;
+
+ co = malloc(sizeof(*co));
+ form = malloc(sizeof(*form));
+ co->data = form;
+ co->width = 0;
+ co->height = 0;
+ co->top = -1;
+ co->left = -1;
+ co->isMapped = 0;
+
+ co->takesFocus = 0; /* we may have 0 components */
+ co->ops = &formOps;
+
+ form->help = help;
+ form->flags = flags;
+ form->numCompsAlloced = 5;
+ form->numComps = 0;
+ form->currComp = -1;
+ form->vertOffset = 0;
+ form->fixedHeight = 0;
+ form->numRows = 0;
+ form->numFds = 0;
+ form->maxFd = 0;
+ form->fds = NULL;
+ form->beenSet = 0;
+ form->elements = malloc(sizeof(*(form->elements)) * form->numCompsAlloced);
+
+ form->background = COLORSET_WINDOW;
+ form->hotKeys = malloc(sizeof(int));
+ form->numHotKeys = 0;
+ form->timer = 0;
+ form->lastTimeout.tv_sec = form->lastTimeout.tv_usec = 0;
+ if (!(form->flags & NEWT_FLAG_NOF12)) {
+ newtFormAddHotKey(co, NEWT_KEY_F12);
+ }
+
+ if (vertBar)
+ form->vertBar = vertBar;
+ else
+ form->vertBar = NULL;
+
+ form->helpTag = help;
+ form->helpCb = helpCallback;
+
+ return co;
+}
+
+newtComponent newtFormGetCurrent(newtComponent co) {
+ struct form * form = co->data;
+
+ return form->elements[form->currComp].co;
+}
+
+void newtFormSetCurrent(newtComponent co, newtComponent subco) {
+ struct form * form = co->data;
+ int i, new;
+
+ for (i = 0; i < form->numComps; i++) {
+ if (form->elements[i].co == subco) break;
+ }
+
+ if (form->elements[i].co != subco) return;
+ new = i;
+
+ if (co->isMapped && !componentFits(co, new)) {
+ gotoComponent(form, -1);
+ form->vertOffset = form->elements[new].top - co->top - 1;
+ if (form->vertOffset > (form->numRows - co->height))
+ form->vertOffset = form->numRows - co->height;
+ }
+
+ gotoComponent(form, new);
+}
+
+void newtFormSetTimer(newtComponent co, int millisecs) {
+ struct form * form = co->data;
+
+ form->timer = millisecs;
+ form->lastTimeout.tv_usec = 0;
+ form->lastTimeout.tv_sec = 0;
+}
+
+void newtFormSetHeight(newtComponent co, int height) {
+ struct form * form = co->data;
+
+ form->fixedHeight = 1;
+ co->height = height;
+}
+
+void newtFormSetWidth(newtComponent co, int width) {
+ co->width = width;
+}
+
+void newtFormAddComponent(newtComponent co, newtComponent newco) {
+ struct form * form = co->data;
+
+ co->takesFocus = 1;
+
+ if (form->numCompsAlloced == form->numComps) {
+ form->numCompsAlloced += 5;
+ form->elements = realloc(form->elements,
+ sizeof(*(form->elements)) * form->numCompsAlloced);
+ }
+
+ /* we grab real values for these a bit later */
+ form->elements[form->numComps].left = -2;
+ form->elements[form->numComps].top = -2;
+ form->elements[form->numComps].co = newco;
+
+ if (newco->takesFocus && form->currComp == -1)
+ form->currComp = form->numComps;
+
+ form->numComps++;
+}
+
+void newtFormAddComponents(newtComponent co, ...) {
+ va_list ap;
+ newtComponent subco;
+
+ va_start(ap, co);
+
+ while ((subco = va_arg(ap, newtComponent)))
+ newtFormAddComponent(co, subco);
+
+ va_end(ap);
+}
+
+static void formPlace(newtComponent co, int left, int top) {
+ struct form * form = co->data;
+ int vertDelta, horizDelta;
+ struct element * el;
+ int i;
+
+ newtFormSetSize(co);
+
+ vertDelta = top - co->top;
+ horizDelta = left - co->left;
+ co->top = top;
+ co->left = left;
+
+ for (i = 0, el = form->elements; i < form->numComps; i++, el++) {
+ el->co->top += vertDelta;
+ el->top += vertDelta;
+ el->co->left += horizDelta;
+ el->left += horizDelta;
+ }
+}
+
+void newtDrawForm(newtComponent co) {
+ struct form * form = co->data;
+ struct element * el;
+ int i;
+
+ newtFormSetSize(co);
+
+ SLsmg_set_color(form->background);
+ newtClearBox(co->left, co->top, co->width, co->height);
+ for (i = 0, el = form->elements; i < form->numComps; i++, el++) {
+ /* the scrollbar *always* fits somewhere */
+ if (el->co == form->vertBar) {
+ el->co->ops->mapped(el->co, 1);
+ el->co->ops->draw(el->co);
+ } else {
+ /* only draw it if it'll fit on the screen vertically */
+ if (componentFits(co, i)) {
+ el->co->top = el->top - form->vertOffset;
+ el->co->ops->mapped(el->co, 1);
+ el->co->ops->draw(el->co);
+ } else {
+ el->co->ops->mapped(el->co, 0);
+ }
+ }
+ }
+
+ if (form->vertBar)
+ newtScrollbarSet(form->vertBar, form->vertOffset,
+ form->numRows - co->height);
+}
+
+static struct eventResult formEvent(newtComponent co, struct event ev) {
+ struct form * form = co->data;
+ newtComponent subco = form->elements[form->currComp].co;
+ int new, wrap = 0;
+ struct eventResult er;
+ int dir = 0, page = 0;
+ int i, num, found;
+ struct element * el;
+
+ er.result = ER_IGNORED;
+ if (!form->numComps) return er;
+
+ subco = form->elements[form->currComp].co;
+
+ switch (ev.when) {
+ case EV_EARLY:
+ if (ev.event == EV_KEYPRESS) {
+ if (ev.u.key == NEWT_KEY_TAB) {
+ er.result = ER_SWALLOWED;
+ dir = 1;
+ wrap = 1;
+ } else if (ev.u.key == NEWT_KEY_UNTAB) {
+ er.result = ER_SWALLOWED;
+ dir = -1;
+ wrap = 1;
+ }
+ }
+
+ if (form->numComps) {
+ i = form->currComp;
+ num = 0;
+ while (er.result == ER_IGNORED && num != form->numComps ) {
+ er = form->elements[i].co->ops->event(form->elements[i].co, ev);
+
+ num++;
+ i++;
+ if (i == form->numComps) i = 0;
+ }
+ }
+
+ break;
+
+ case EV_NORMAL:
+ if (ev.event == EV_MOUSE) {
+ found = 0;
+ for (i = 0, el = form->elements; i < form->numComps; i++, el++) {
+ if ((el->co->top <= ev.u.mouse.y) &&
+ (el->co->top + el->co->height > ev.u.mouse.y) &&
+ (el->co->left <= ev.u.mouse.x) &&
+ (el->co->left + el->co->width > ev.u.mouse.x)) {
+ found = 1;
+ if (el->co->takesFocus) {
+ gotoComponent(form, i);
+ subco = form->elements[form->currComp].co;
+ }
+ }
+ /* If we did not find a co to send this event to, we
+ should just swallow the event here. */
+ }
+ if (!found) {
+ er.result = ER_SWALLOWED;
+
+ return er;
+ }
+ }
+ er = subco->ops->event(subco, ev);
+ switch (er.result) {
+ case ER_NEXTCOMP:
+ er.result = ER_SWALLOWED;
+ dir = 1;
+ break;
+
+ case ER_EXITFORM:
+ form->exitComp = subco;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case EV_LATE:
+ er = subco->ops->event(subco, ev);
+
+ if (er.result == ER_IGNORED) {
+ switch (ev.u.key) {
+ case NEWT_KEY_UP:
+ case NEWT_KEY_LEFT:
+ case NEWT_KEY_BKSPC:
+ er.result = ER_SWALLOWED;
+ dir = -1;
+ break;
+
+ case NEWT_KEY_DOWN:
+ case NEWT_KEY_RIGHT:
+ er.result = ER_SWALLOWED;
+ dir = 1;
+ break;
+
+ case NEWT_KEY_PGUP:
+ er.result = ER_SWALLOWED;
+ dir = -1;
+ page = 1;
+ break;
+
+ case NEWT_KEY_PGDN:
+ er.result = ER_SWALLOWED;
+ dir = 1;
+ page = 1;
+ break;
+ }
+ }
+ }
+
+ if (dir) {
+ new = form->currComp;
+
+ if (page) {
+ new += dir * co->height;
+ if (new < 0)
+ new = 0;
+ else if (new >= form->numComps)
+ new = (form->numComps - 1);
+
+ while (!form->elements[new].co->takesFocus)
+ new = new - dir;
+ } else {
+ do {
+ new += dir;
+
+ if (wrap) {
+ if (new < 0)
+ new = form->numComps - 1;
+ else if (new >= form->numComps)
+ new = 0;
+ } else if (new < 0 || new >= form->numComps)
+ return er;
+ } while (!form->elements[new].co->takesFocus);
+ }
+
+ /* make sure this component is visible */
+ if (!componentFits(co, new)) {
+ gotoComponent(form, -1);
+
+ if (dir < 0) {
+ /* make the new component the first one */
+ form->vertOffset = form->elements[new].top - co->top;
+ } else {
+ /* make the new component the last one */
+ form->vertOffset = (form->elements[new].top +
+ form->elements[new].co->height) -
+ (co->top + co->height);
+ }
+
+ if (form->vertOffset < 0) form->vertOffset = 0;
+ if (form->vertOffset > (form->numRows - co->height))
+ form->vertOffset = form->numRows - co->height;
+
+ newtDrawForm(co);
+ }
+
+ gotoComponent(form, new);
+ er.result = ER_SWALLOWED;
+ }
+
+ return er;
+}
+
+/* this also destroys all of the components on the form */
+void newtFormDestroy(newtComponent co) {
+ newtComponent subco;
+ struct form * form = co->data;
+ int i;
+
+ /* first, destroy all of the components */
+ for (i = 0; i < form->numComps; i++) {
+ subco = form->elements[i].co;
+ if (subco->ops->destroy) {
+ subco->ops->destroy(subco);
+ } else {
+ if (subco->data) free(subco->data);
+ free(subco);
+ }
+ }
+
+ if (form->hotKeys) free(form->hotKeys);
+
+ free(form->elements);
+ free(form);
+ free(co);
+}
+
+newtComponent newtRunForm(newtComponent co) {
+ struct newtExitStruct es;
+
+ newtFormRun(co, &es);
+ if (es.reason == NEWT_EXIT_HOTKEY) {
+ if (es.u.key == NEWT_KEY_F12) {
+ es.reason = NEWT_EXIT_COMPONENT;
+ es.u.co = co;
+ } else {
+ return NULL;
+ }
+ }
+
+ return es.u.co;
+}
+
+void newtFormAddHotKey(newtComponent co, int key) {
+ struct form * form = co->data;
+
+ form->numHotKeys++;
+ form->hotKeys = realloc(form->hotKeys, sizeof(int) * form->numHotKeys);
+ form->hotKeys[form->numHotKeys - 1] = key;
+}
+
+void newtFormSetSize(newtComponent co) {
+ struct form * form = co->data;
+ int delta, i;
+ struct element * el;
+
+ if (form->beenSet) return;
+
+ form->beenSet = 1;
+
+ if (!form->numComps) return;
+
+ co->width = 0;
+ if (!form->fixedHeight) co->height = 0;
+
+ co->top = form->elements[0].co->top;
+ co->left = form->elements[0].co->left;
+ for (i = 0, el = form->elements; i < form->numComps; i++, el++) {
+ if (el->co->ops == &formOps)
+ newtFormSetSize(el->co);
+
+ el->left = el->co->left;
+ el->top = el->co->top;
+
+ if (co->left > el->co->left) {
+ delta = co->left - el->co->left;
+ co->left -= delta;
+ co->width += delta;
+ }
+
+ if (co->top > el->co->top) {
+ delta = co->top - el->co->top;
+ co->top -= delta;
+ if (!form->fixedHeight)
+ co->height += delta;
+ }
+
+ if ((co->left + co->width) < (el->co->left + el->co->width))
+ co->width = (el->co->left + el->co->width) - co->left;
+
+ if (!form->fixedHeight) {
+ if ((co->top + co->height) < (el->co->top + el->co->height))
+ co->height = (el->co->top + el->co->height) - co->top;
+ }
+
+ if ((el->co->top + el->co->height - co->top) > form->numRows) {
+ form->numRows = el->co->top + el->co->height - co->top;
+ }
+ }
+}
+
+void newtFormRun(newtComponent co, struct newtExitStruct * es) {
+ struct form * form = co->data;
+ struct event ev;
+ struct eventResult er;
+ int key, i, max;
+ int done = 0;
+ fd_set readSet, writeSet;
+ struct timeval nextTimeout, now, timeout;
+
+ newtFormSetSize(co);
+ /* draw all of the components */
+ newtDrawForm(co);
+
+ if (form->currComp == -1) {
+ gotoComponent(form, 0);
+ } else
+ gotoComponent(form, form->currComp);
+
+ while (!done) {
+ newtRefresh();
+
+ FD_ZERO(&readSet);
+ FD_ZERO(&writeSet);
+ FD_SET(0, &readSet);
+ max = form->maxFd;
+
+ for (i = 0; i < form->numFds; i++) {
+ if (form->fds[i].flags & NEWT_FD_READ)
+ FD_SET(form->fds[i].fd, &readSet);
+ if (form->fds[i].flags & NEWT_FD_WRITE)
+ FD_SET(form->fds[i].fd, &writeSet);
+ }
+
+ if (form->timer) {
+ /* Calculate when we next need to return with a timeout. Do
+ this inside the loop in case a callback resets the timer. */
+ if (!form->lastTimeout.tv_sec && !form->lastTimeout.tv_usec)
+ gettimeofday(&form->lastTimeout, NULL);
+
+ nextTimeout.tv_sec = form->lastTimeout.tv_sec +
+ (form->timer / 1000);
+ nextTimeout.tv_usec = form->lastTimeout.tv_usec +
+ (form->timer % 1000) * 1000;
+
+ gettimeofday(&now, 0);
+
+ if (now.tv_sec > nextTimeout.tv_sec) {
+ timeout.tv_sec = timeout.tv_usec = 0;
+ } else if (now.tv_sec == nextTimeout.tv_sec) {
+ timeout.tv_sec = 0;
+ if (now.tv_usec > nextTimeout.tv_usec)
+ timeout.tv_usec = 0;
+ else
+ timeout.tv_usec = nextTimeout.tv_usec - now.tv_usec;
+ } else if (now.tv_sec < nextTimeout.tv_sec) {
+ timeout.tv_sec = nextTimeout.tv_sec - now.tv_sec;
+ if (now.tv_usec > nextTimeout.tv_usec)
+ timeout.tv_sec--,
+ timeout.tv_usec = nextTimeout.tv_usec + 1000000 -
+ now.tv_usec;
+ else
+ timeout.tv_usec = nextTimeout.tv_usec - now.tv_usec;
+ }
+ } else {
+ timeout.tv_sec = timeout.tv_usec = 0;
+ }
+
+ i = select(max + 1, &readSet, &writeSet, NULL,
+ form->timer ? &timeout : NULL);
+ if (i < 0) continue; /* ?? What should we do here? */
+
+ if (i == 0) {
+ done = 1;
+ es->reason = NEWT_EXIT_TIMER;
+ gettimeofday(&form->lastTimeout, NULL);
+ } else
+ {
+ if (FD_ISSET(0, &readSet)) {
+
+ key = newtGetKey();
+
+ if (key == NEWT_KEY_RESIZE) {
+ /* newtResizeScreen(1); */
+ continue;
+ }
+
+ for (i = 0; i < form->numHotKeys; i++) {
+ if (form->hotKeys[i] == key) {
+ es->reason = NEWT_EXIT_HOTKEY;
+ es->u.key = key;
+ done = 1;
+ break;
+ }
+ }
+
+ if (key == NEWT_KEY_F1 && form->helpTag && form->helpCb)
+ form->helpCb(co, form->helpTag);
+
+ if (!done) {
+ ev.event = EV_KEYPRESS;
+ ev.u.key = key;
+
+ er = sendEvent(co, ev);
+
+ if (er.result == ER_EXITFORM) {
+ done = 1;
+ es->reason = NEWT_EXIT_COMPONENT;
+ es->u.co = form->exitComp;
+ }
+ }
+ } else {
+ es->reason = NEWT_EXIT_FDREADY;
+ done = 1;
+ }
+ }
+ }
+ newtRefresh();
+}
+
+static struct eventResult sendEvent(newtComponent co, struct event ev) {
+ struct eventResult er;
+
+ ev.when = EV_EARLY;
+ er = co->ops->event(co, ev);
+
+ if (er.result == ER_IGNORED) {
+ ev.when = EV_NORMAL;
+ er = co->ops->event(co, ev);
+ }
+
+ if (er.result == ER_IGNORED) {
+ ev.when = EV_LATE;
+ er = co->ops->event(co, ev);
+ }
+
+ return er;
+}
+
+static void gotoComponent(struct form * form, int newComp) {
+ struct event ev;
+
+ if (form->currComp != -1) {
+ ev.event = EV_UNFOCUS;
+ sendEvent(form->elements[form->currComp].co, ev);
+ }
+
+ form->currComp = newComp;
+
+ if (form->currComp != -1) {
+ ev.event = EV_FOCUS;
+ ev.when = EV_NORMAL;
+ sendEvent(form->elements[form->currComp].co, ev);
+ }
+}
+
+void newtComponentAddCallback(newtComponent co, newtCallback f, void * data) {
+ co->callback = f;
+ co->callbackData = data;
+}
+
+void newtComponentTakesFocus(newtComponent co, int val) {
+ co->takesFocus = val;
+}
+
+void newtFormSetBackground(newtComponent co, int color) {
+ struct form * form = co->data;
+
+ form->background = color;
+}
+
+void newtFormWatchFd(newtComponent co, int fd, int fdFlags) {
+ struct form * form = co->data;
+
+ form->fds = realloc(form->fds, (form->numFds + 1) * sizeof(*form->fds));
+ form->fds[form->numFds].fd = fd;
+ form->fds[form->numFds++].flags = fdFlags;
+ if (form->maxFd < fd) form->maxFd = fd;
+}
+
+void newtSetHelpCallback(newtCallback cb) {
+ helpCallback = cb;
+}
diff --git a/mdk-stage1/newt/grid.c b/mdk-stage1/newt/grid.c
new file mode 100644
index 000000000..433011396
--- /dev/null
+++ b/mdk-stage1/newt/grid.c
@@ -0,0 +1,389 @@
+#include <alloca.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "newt.h"
+#include "newt_pr.h"
+
+struct gridField {
+ enum newtGridElement type;
+ union {
+ newtGrid grid;
+ newtComponent co;
+ } u;
+ int padLeft, padTop, padRight, padBottom;
+ int anchor;
+ int flags;
+};
+
+struct grid_s {
+ int rows, cols;
+ int width, height; /* totals, -1 means unknown */
+ struct gridField ** fields;
+};
+
+/* this is a bit of a hack */
+extern struct componentOps formOps[];
+
+newtGrid newtCreateGrid(int cols, int rows) {
+ newtGrid grid;
+
+ grid = malloc(sizeof(*grid));
+ grid->rows = rows;
+ grid->cols = cols;
+
+ grid->fields = malloc(sizeof(*grid->fields) * cols);
+ while (cols--) {
+ grid->fields[cols] = malloc(sizeof(**(grid->fields)) * rows);
+ memset(grid->fields[cols], 0, sizeof(**(grid->fields)) * rows);
+ }
+
+ grid->width = grid->height = -1;
+
+ return grid;
+}
+
+void newtGridSetField(newtGrid grid, int col, int row,
+ enum newtGridElement type, void * val, int padLeft,
+ int padTop, int padRight, int padBottom, int anchor,
+ int flags) {
+ struct gridField * field = &grid->fields[col][row];
+
+ if (field->type == NEWT_GRID_SUBGRID)
+ newtGridFree(field->u.grid, 1);
+
+ field->type = type;
+ field->u.co = (void *) val;
+
+ field->padLeft = padLeft;
+ field->padRight = padRight;
+ field->padTop = padTop;
+ field->padBottom = padBottom;
+ field->anchor = anchor;
+ field->flags = flags;
+
+ grid->width = grid->height = -1;
+}
+
+static void distSpace(int extra, int items, int * list) {
+ int all, some, i;
+
+ all = extra / items;
+ some = extra % items;
+ for (i = 0; i < items; i++) {
+ list[i] += all;
+ if (some) {
+ list[i]++;
+ some--;
+ }
+ }
+}
+
+static void shuffleGrid(newtGrid grid, int left, int top, int set) {
+ struct gridField * field;
+ int row, col;
+ int i, j;
+ int minWidth, minHeight;
+ int * widths, * heights;
+ int thisLeft, thisTop;
+ int x, y, remx, remy;
+
+ widths = alloca(sizeof(*widths) * grid->cols);
+ memset(widths, 0, sizeof(*widths) * grid->cols);
+ heights = alloca(sizeof(*heights) * grid->rows);
+ memset(heights, 0, sizeof(*heights) * grid->rows);
+
+ minWidth = 0;
+ for (row = 0; row < grid->rows; row++) {
+ i = 0;
+ for (col = 0; col < grid->cols; col++) {
+ field = &grid->fields[col][row];
+ if (field->type == NEWT_GRID_SUBGRID) {
+ /* we'll have to redo this later */
+ if (field->u.grid->width == -1)
+ shuffleGrid(field->u.grid, left, top, 0);
+ j = field->u.grid->width;
+ } else if (field->type == NEWT_GRID_COMPONENT) {
+ if (field->u.co->ops == formOps)
+ newtFormSetSize(field->u.co);
+ j = field->u.co->width;
+ } else
+ j = 0;
+
+ j += field->padLeft + field->padRight;
+
+ if (j > widths[col]) widths[col] = j;
+ i += widths[col];
+ }
+
+ if (i > minWidth) minWidth = i;
+ }
+
+ minHeight = 0;
+ for (col = 0; col < grid->cols; col++) {
+ i = 0;
+ for (row = 0; row < grid->rows; row++) {
+ field = &grid->fields[col][row];
+ if (field->type == NEWT_GRID_SUBGRID) {
+ /* we'll have to redo this later */
+ if (field->u.grid->height == -1)
+ shuffleGrid(field->u.grid, 0, 0, 0);
+ j = field->u.grid->height;
+ } else if (field->type == NEWT_GRID_COMPONENT){
+ j = field->u.co->height;
+ } else
+ j = 0;
+
+ j += field->padTop + field->padBottom;
+
+ if (j > heights[row]) heights[row] = j;
+ i += heights[row];
+ }
+
+ if (i > minHeight) minHeight = i;
+ }
+
+ /* this catches the -1 case */
+ if (grid->width < minWidth) grid->width = minWidth; /* ack! */
+ if (grid->height < minHeight) grid->height = minHeight; /* ditto! */
+
+ if (!set) return;
+
+ distSpace(grid->width - minWidth, grid->cols, widths);
+ distSpace(grid->height - minHeight, grid->rows, heights);
+
+ thisTop = top;
+ for (row = 0; row < grid->rows; row++) {
+ i = 0;
+ thisLeft = left;
+ for (col = 0; col < grid->cols; col++) {
+ field = &grid->fields[col][row];
+
+ if (field->type == NEWT_GRID_EMPTY) continue;
+
+ x = thisLeft + field->padLeft;
+ remx = widths[col] - field->padLeft - field->padRight;
+ y = thisTop + field->padTop;
+ remy = heights[row] - field->padTop - field->padBottom;
+
+ if (field->type == NEWT_GRID_SUBGRID) {
+ remx -= field->u.grid->width;
+ remy -= field->u.grid->height;
+ } else if (field->type == NEWT_GRID_COMPONENT) {
+ remx -= field->u.co->width;
+ remy -= field->u.co->height;
+ }
+
+ if (!(field->flags & NEWT_GRID_FLAG_GROWX)) {
+ if (field->anchor & NEWT_ANCHOR_RIGHT)
+ x += remx;
+ else if (!(field->anchor & NEWT_ANCHOR_LEFT))
+ x += (remx / 2);
+ }
+
+ if (!(field->flags & NEWT_GRID_FLAG_GROWY)) {
+ if (field->anchor & NEWT_ANCHOR_BOTTOM)
+ y += remx;
+ else if (!(field->anchor & NEWT_ANCHOR_TOP))
+ y += (remy / 2);
+ }
+
+ if (field->type == NEWT_GRID_SUBGRID) {
+ if (field->flags & NEWT_GRID_FLAG_GROWX)
+ field->u.grid->width = widths[col] - field->padLeft
+ - field->padRight;
+ if (field->flags & NEWT_GRID_FLAG_GROWY)
+ field->u.grid->height = heights[col] - field->padTop
+ - field->padBottom;
+
+ shuffleGrid(field->u.grid, x, y, 1);
+ } else if (field->type == NEWT_GRID_COMPONENT) {
+ field->u.co->ops->place(field->u.co, x, y);
+ }
+
+ thisLeft += widths[col];
+ }
+
+ thisTop += heights[row];
+ }
+}
+
+void newtGridPlace(newtGrid grid, int left, int top) {
+ shuffleGrid(grid, left, top, 1);
+}
+
+void newtGridFree(newtGrid grid, int recurse) {
+ int row, col;
+
+ for (col = 0; col < grid->cols; col++) {
+ if (recurse) {
+ for (row = 0; row < grid->rows; row++) {
+ if (grid->fields[col][row].type == NEWT_GRID_SUBGRID)
+ newtGridFree(grid->fields[col][row].u.grid, 1);
+ }
+ }
+
+ free(grid->fields[col]);
+ }
+
+ free(grid->fields);
+ free(grid);
+}
+
+void newtGridGetSize(newtGrid grid, int * width, int * height) {
+ if (grid->width == -1 || grid->height == -1) {
+ grid->width = grid->height = -1;
+ shuffleGrid(grid, 0, 0, 1);
+ }
+
+ *width = grid->width;
+ *height = grid->height;
+}
+
+void newtGridWrappedWindow(newtGrid grid, char * title) {
+ int width, height, offset = 0;
+
+ newtGridGetSize(grid, &width, &height);
+ if (width < strlen(title) + 2) {
+ offset = ((strlen(title) + 2) - width) / 2;
+ width = strlen(title) + 2;
+ }
+ newtCenteredWindow(width + 2, height + 2, title);
+ newtGridPlace(grid, 1 + offset, 1);
+}
+
+void newtGridWrappedWindowAt(newtGrid grid, char * title, int left, int top) {
+ int width, height;
+
+ newtGridGetSize(grid, &width, &height);
+ newtOpenWindow(left, top, width + 2, height + 2, title);
+ newtGridPlace(grid, 1, 1);
+}
+
+void newtGridAddComponentsToForm(newtGrid grid, newtComponent form,
+ int recurse) {
+ int row, col;
+
+ for (col = 0; col < grid->cols; col++) {
+ for (row = 0; row < grid->rows; row++) {
+ if (grid->fields[col][row].type == NEWT_GRID_SUBGRID && recurse)
+ newtGridAddComponentsToForm(grid->fields[col][row].u.grid,
+ form, 1);
+ else if (grid->fields[col][row].type == NEWT_GRID_COMPONENT)
+ newtFormAddComponent(form, grid->fields[col][row].u.co);
+ }
+ }
+}
+
+/* this handles up to 50 items */
+static newtGrid stackem(int isVert, enum newtGridElement type1, void * what1,
+ va_list args, int close) {
+ struct item {
+ enum newtGridElement type;
+ void * what;
+ } items[50];
+ int i, num;
+ newtGrid grid;
+
+ items[0].type = type1, items[0].what = what1, num = 1;
+ while (1) {
+ items[num].type = va_arg(args, enum newtGridElement);
+ if (items[num].type == NEWT_GRID_EMPTY) break;
+
+ items[num].what = va_arg(args, void *);
+ num++;
+ }
+
+ grid = newtCreateGrid(isVert ? 1 : num, isVert ? num : 1);
+
+ for (i = 0; i < num; i++) {
+ newtGridSetField(grid, isVert ? 0 : i, isVert ? i : 0,
+ items[i].type, items[i].what,
+ close ? 0 : (i ? (isVert ? 0 : 1) : 0),
+ close ? 0 : (i ? (isVert ? 1 : 0) : 0), 0, 0, 0, 0);
+ }
+
+ return grid;
+}
+
+newtGrid newtGridHCloseStacked(enum newtGridElement type1, void * what1, ...) {
+ va_list args;
+ newtGrid grid;
+
+ va_start(args, what1);
+
+ grid = stackem(0, type1, what1, args, 1);
+
+ va_start(args, what1);
+
+ return grid;
+}
+
+newtGrid newtGridVCloseStacked(enum newtGridElement type1, void * what1, ...) {
+ va_list args;
+ newtGrid grid;
+
+ va_start(args, what1);
+
+ grid = stackem(1, type1, what1, args, 1);
+
+ va_start(args, what1);
+
+ return grid;
+}
+
+newtGrid newtGridVStacked(enum newtGridElement type1, void * what1, ...) {
+ va_list args;
+ newtGrid grid;
+
+ va_start(args, what1);
+
+ grid = stackem(1, type1, what1, args, 0);
+
+ va_start(args, what1);
+
+ return grid;
+}
+
+newtGrid newtGridHStacked(enum newtGridElement type1, void * what1, ...) {
+ va_list args;
+ newtGrid grid;
+
+ va_start(args, what1);
+
+ grid = stackem(0, type1, what1, args, 0);
+
+ va_start(args, what1);
+
+ return grid;
+}
+
+newtGrid newtGridBasicWindow(newtComponent text, newtGrid middle,
+ newtGrid buttons) {
+ newtGrid grid;
+
+ grid = newtCreateGrid(1, 3);
+ newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text,
+ 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
+ newtGridSetField(grid, 0, 1, NEWT_GRID_SUBGRID, middle,
+ 0, 1, 0, 0, 0, 0);
+ newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, buttons,
+ 0, 1, 0, 0, 0, NEWT_GRID_FLAG_GROWX);
+
+ return grid;
+}
+
+newtGrid newtGridSimpleWindow(newtComponent text, newtComponent middle,
+ newtGrid buttons) {
+ newtGrid grid;
+
+ grid = newtCreateGrid(1, 3);
+ newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text,
+ 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
+ newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, middle,
+ 0, 1, 0, 0, 0, 0);
+ newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, buttons,
+ 0, 1, 0, 0, 0, NEWT_GRID_FLAG_GROWX);
+
+ return grid;
+}
diff --git a/mdk-stage1/newt/label.c b/mdk-stage1/newt/label.c
new file mode 100644
index 000000000..f1a9cebbf
--- /dev/null
+++ b/mdk-stage1/newt/label.c
@@ -0,0 +1,81 @@
+#include <slang.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "newt.h"
+#include "newt_pr.h"
+
+struct label {
+ char * text;
+ int length;
+};
+
+static void labelDraw(newtComponent co);
+static void labelDestroy(newtComponent co);
+
+static struct componentOps labelOps = {
+ labelDraw,
+ newtDefaultEventHandler,
+ labelDestroy,
+ newtDefaultPlaceHandler,
+ newtDefaultMappedHandler,
+} ;
+
+newtComponent newtLabel(int left, int top, const char * text) {
+ newtComponent co;
+ struct label * la;
+
+ co = malloc(sizeof(*co));
+ la = malloc(sizeof(struct label));
+ co->data = la;
+
+ co->ops = &labelOps;
+
+ co->height = 1;
+ co->width = strlen(text);
+ co->top = top;
+ co->left = left;
+ co->takesFocus = 0;
+
+ la->length = strlen(text);
+ la->text = strdup(text);
+
+ return co;
+}
+
+void newtLabelSetText(newtComponent co, const char * text) {
+ int newLength;
+ struct label * la = co->data;
+
+ newLength = strlen(text);
+ if (newLength <= la->length) {
+ memset(la->text, ' ', la->length);
+ memcpy(la->text, text, newLength);
+ } else {
+ free(la->text);
+ la->text = strdup(text);
+ la->length = newLength;
+ co->width = newLength;
+ }
+
+ labelDraw(co);
+}
+
+static void labelDraw(newtComponent co) {
+ struct label * la = co->data;
+
+ if (co->isMapped == -1) return;
+
+ SLsmg_set_color(COLORSET_LABEL);
+
+ newtGotorc(co->top, co->left);
+ SLsmg_write_string(la->text);
+}
+
+static void labelDestroy(newtComponent co) {
+ struct label * la = co->data;
+
+ free(la->text);
+ free(la);
+ free(co);
+}
diff --git a/mdk-stage1/newt/listbox.c b/mdk-stage1/newt/listbox.c
new file mode 100644
index 000000000..ef276aeb4
--- /dev/null
+++ b/mdk-stage1/newt/listbox.c
@@ -0,0 +1,752 @@
+/* This goofed-up box whacked into shape by Elliot Lee <sopwith@cuc.edu>
+ (from the original listbox by Erik Troan <ewt@redhat.com>)
+ and contributed to newt for use under the LGPL license.
+ Copyright (C) 1996, 1997 Elliot Lee */
+
+#include <slang.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "newt.h"
+#include "newt_pr.h"
+
+
+/* Linked list of items in the listbox */
+struct items {
+ char * text;
+ const void *data;
+ unsigned char isSelected;
+ struct items *next;
+};
+
+/* Holds all the relevant information for this listbox */
+struct listbox {
+ newtComponent sb; /* Scrollbar on right side of listbox */
+ int curWidth; /* size of text w/o scrollbar or border*/
+ int curHeight; /* size of text w/o border */
+ int sbAdjust;
+ int bdxAdjust, bdyAdjust;
+ int numItems, numSelected;
+ int userHasSetWidth;
+ int currItem, startShowItem; /* startShowItem is the first item displayed
+ on the screen */
+ int isActive; /* If we handle key events all the time, it seems
+ to do things even when they are supposed to be for
+ another button/whatever */
+ struct items *boxItems;
+ int grow;
+ int flags; /* flags for this listbox, right now just
+ NEWT_FLAG_RETURNEXIT */
+};
+
+static void listboxDraw(newtComponent co);
+static void listboxDestroy(newtComponent co);
+static struct eventResult listboxEvent(newtComponent co, struct event ev);
+static void newtListboxRealSetCurrent(newtComponent co);
+static void listboxPlace(newtComponent co, int newLeft, int newTop);
+static inline void updateWidth(newtComponent co, struct listbox * li,
+ int maxField);
+static void listboxMapped(newtComponent co, int isMapped);
+
+static struct componentOps listboxOps = {
+ listboxDraw,
+ listboxEvent,
+ listboxDestroy,
+ listboxPlace,
+ listboxMapped,
+};
+
+static void listboxMapped(newtComponent co, int isMapped) {
+ struct listbox * li = co->data;
+
+ co->isMapped = isMapped;
+ if (li->sb)
+ li->sb->ops->mapped(li->sb, isMapped);
+}
+
+static void listboxPlace(newtComponent co, int newLeft, int newTop) {
+ struct listbox * li = co->data;
+
+ co->top = newTop;
+ co->left = newLeft;
+
+ if (li->sb)
+ li->sb->ops->place(li->sb, co->left + co->width - li->bdxAdjust - 1,
+ co->top);
+}
+
+newtComponent newtListbox(int left, int top, int height, int flags) {
+ newtComponent co, sb;
+ struct listbox * li;
+
+ if (!(co = malloc(sizeof(*co))))
+ return NULL;
+
+ if (!(li = malloc(sizeof(struct listbox)))) {
+ free(co);
+ return NULL;
+ }
+
+ li->boxItems = NULL;
+ li->numItems = 0;
+ li->currItem = 0;
+ li->numSelected = 0;
+ li->isActive = 0;
+ li->userHasSetWidth = 0;
+ li->startShowItem = 0;
+ li->sbAdjust = 0;
+ li->bdxAdjust = 0;
+ li->bdyAdjust = 0;
+ li->flags = flags & (NEWT_FLAG_RETURNEXIT | NEWT_FLAG_BORDER |
+ NEWT_FLAG_MULTIPLE);
+
+ if (li->flags & NEWT_FLAG_BORDER) {
+ li->bdxAdjust = 2;
+ li->bdyAdjust = 1;
+ }
+
+ co->height = height;
+ li->curHeight = co->height - (2 * li->bdyAdjust);
+
+ if (height) {
+ li->grow = 0;
+ if (flags & NEWT_FLAG_SCROLL) {
+ sb = newtVerticalScrollbar(left, top + li->bdyAdjust,
+ li->curHeight,
+ COLORSET_LISTBOX, COLORSET_ACTLISTBOX);
+ li->sbAdjust = 3;
+ } else {
+ sb = NULL;
+ }
+ } else {
+ li->grow = 1;
+ sb = NULL;
+ }
+
+ li->sb = sb;
+ co->data = li;
+ co->isMapped = 0;
+ co->left = left;
+ co->top = top;
+ co->ops = &listboxOps;
+ co->takesFocus = 1;
+ co->callback = NULL;
+
+ updateWidth(co, li, 5);
+
+ return co;
+}
+
+static inline void updateWidth(newtComponent co, struct listbox * li,
+ int maxField) {
+ li->curWidth = maxField;
+ co->width = li->curWidth + li->sbAdjust + 2 * li->bdxAdjust;
+
+ if (li->sb)
+ li->sb->left = co->left + co->width - li->bdxAdjust - 1;
+}
+
+void newtListboxSetCurrentByKey(newtComponent co, void * key) {
+ struct listbox * li = co->data;
+ struct items * item;
+ int i;
+
+ item = li->boxItems, i = 0;
+ while (item && item->data != key)
+ item = item->next, i++;
+
+ if (item)
+ newtListboxSetCurrent(co, i);
+}
+
+void newtListboxSetCurrent(newtComponent co, int num)
+{
+ struct listbox * li = co->data;
+
+ if (num >= li->numItems)
+ li->currItem = li->numItems - 1;
+ else if (num < 0)
+ li->currItem = 0;
+ else
+ li->currItem = num;
+
+ if (li->currItem < li->startShowItem)
+ li->startShowItem = li->currItem;
+ else if (li->currItem - li->startShowItem > li->curHeight - 1)
+ li->startShowItem = li->currItem - li->curHeight + 1;
+ if (li->startShowItem + li->curHeight > li->numItems)
+ li->startShowItem = li->numItems - li->curHeight;
+ if(li->startShowItem < 0)
+ li->startShowItem = 0;
+
+ newtListboxRealSetCurrent(co);
+}
+
+static void newtListboxRealSetCurrent(newtComponent co)
+{
+ struct listbox * li = co->data;
+
+ if(li->sb)
+ newtScrollbarSet(li->sb, li->currItem + 1, li->numItems);
+ listboxDraw(co);
+ if(co->callback) co->callback(co, co->callbackData);
+}
+
+void newtListboxSetWidth(newtComponent co, int width) {
+ struct listbox * li = co->data;
+
+ co->width = width;
+ li->curWidth = co->width - li->sbAdjust - 2 * li->bdxAdjust;
+ li->userHasSetWidth = 1;
+ if (li->sb) li->sb->left = co->width + co->left - 1;
+ listboxDraw(co);
+}
+
+void * newtListboxGetCurrent(newtComponent co) {
+ struct listbox * li = co->data;
+ int i;
+ struct items *item;
+
+ for(i = 0, item = li->boxItems; item != NULL && i < li->currItem;
+ i++, item = item->next);
+
+ if (item)
+ return (void *)item->data;
+ else
+ return NULL;
+}
+
+void newtListboxSelectItem(newtComponent co, const void * key,
+ enum newtFlagsSense sense)
+{
+ struct listbox * li = co->data;
+ int i;
+ struct items * item;
+
+ item = li->boxItems, i = 0;
+ while (item && item->data != key)
+ item = item->next, i++;
+
+ if (!item) return;
+
+ if (item->isSelected)
+ li->numSelected--;
+
+ switch(sense) {
+ case NEWT_FLAGS_RESET:
+ item->isSelected = 0; break;
+ case NEWT_FLAGS_SET:
+ item->isSelected = 1; break;
+ case NEWT_FLAGS_TOGGLE:
+ item->isSelected = !item->isSelected;
+ }
+
+ if (item->isSelected)
+ li->numSelected++;
+
+ listboxDraw(co);
+}
+
+void newtListboxClearSelection(newtComponent co)
+{
+ struct items *item;
+ struct listbox * li = co->data;
+
+ for(item = li->boxItems; item != NULL;
+ item = item->next)
+ item->isSelected = 0;
+ li->numSelected = 0;
+ listboxDraw(co);
+}
+
+/* Free the returned array after use, but NOT the values in the array */
+void ** newtListboxGetSelection(newtComponent co, int *numitems)
+{
+ struct listbox * li;
+ int i;
+ void **retval;
+ struct items *item;
+
+ if(!co || !numitems) return NULL;
+
+ li = co->data;
+ if(!li || !li->numSelected) return NULL;
+
+ retval = malloc(li->numSelected * sizeof(void *));
+ for(i = 0, item = li->boxItems; item != NULL;
+ item = item->next)
+ if(item->isSelected)
+ retval[i++] = (void *)item->data;
+ *numitems = li->numSelected;
+ return retval;
+}
+
+void newtListboxSetEntry(newtComponent co, int num, const char * text) {
+ struct listbox * li = co->data;
+ int i;
+ struct items *item;
+
+ for(i = 0, item = li->boxItems; item != NULL && i < num;
+ i++, item = item->next);
+
+ if(!item)
+ return;
+ else {
+ free(item->text);
+ item->text = strdup(text);
+ }
+ if (li->userHasSetWidth == 0 && strlen(text) > li->curWidth) {
+ updateWidth(co, li, strlen(text));
+ }
+
+ if (num >= li->startShowItem && num <= li->startShowItem + co->height)
+ listboxDraw(co);
+}
+
+void newtListboxSetData(newtComponent co, int num, void * data) {
+ struct listbox * li = co->data;
+ int i;
+ struct items *item;
+
+ for(i = 0, item = li->boxItems; item != NULL && i < num;
+ i++, item = item->next);
+
+ item->data = data;
+}
+
+int newtListboxAppendEntry(newtComponent co, const char * text,
+ const void * data) {
+ struct listbox * li = co->data;
+ struct items *item;
+
+ if(li->boxItems) {
+ for (item = li->boxItems; item->next != NULL; item = item->next);
+
+ item = item->next = malloc(sizeof(struct items));
+ } else {
+ item = li->boxItems = malloc(sizeof(struct items));
+ }
+
+ if (!li->userHasSetWidth && text && (strlen(text) > li->curWidth))
+ updateWidth(co, li, strlen(text));
+
+ item->text = strdup(text); item->data = data; item->next = NULL;
+ item->isSelected = 0;
+
+ if (li->grow)
+ co->height++, li->curHeight++;
+ li->numItems++;
+
+ return 0;
+}
+
+int newtListboxInsertEntry(newtComponent co, const char * text,
+ const void * data, void * key) {
+ struct listbox * li = co->data;
+ struct items *item, *t;
+
+ if (li->boxItems) {
+ if (key) {
+ item = li->boxItems;
+ while (item && item->data != key) item = item->next;
+
+ if (!item) return 1;
+
+ t = item->next;
+ item = item->next = malloc(sizeof(struct items));
+ item->next = t;
+ } else {
+ t = li->boxItems;
+ item = li->boxItems = malloc(sizeof(struct items));
+ item->next = t;
+ }
+ } else if (key) {
+ return 1;
+ } else {
+ item = li->boxItems = malloc(sizeof(struct items));
+ item->next = NULL;
+ }
+
+ if (!li->userHasSetWidth && text && (strlen(text) > li->curWidth))
+ updateWidth(co, li, strlen(text));
+
+ item->text = strdup(text?text:"(null)"); item->data = data;
+ item->isSelected = 0;
+
+ if (li->sb)
+ li->sb->left = co->left + co->width - li->bdxAdjust - 1;
+ li->numItems++;
+
+ listboxDraw(co);
+
+ return 0;
+}
+
+int newtListboxDeleteEntry(newtComponent co, void * key) {
+ struct listbox * li = co->data;
+ int widest = 0, t;
+ struct items *item, *item2 = NULL;
+ int num;
+
+ if (li->boxItems == NULL || li->numItems <= 0)
+ return 0;
+
+ num = 0;
+
+ item2 = NULL, item = li->boxItems;
+ while (item && item->data != key) {
+ item2 = item;
+ item = item->next;
+ num++;
+ }
+
+ if (!item)
+ return -1;
+
+ if (item2)
+ item2->next = item->next;
+ else
+ li->boxItems = item->next;
+
+ free(item->text);
+ free(item);
+ li->numItems--;
+
+ if (!li->userHasSetWidth) {
+ widest = 0;
+ for (item = li->boxItems; item != NULL; item = item->next)
+ if ((t = strlen(item->text)) > widest) widest = t;
+ }
+
+ if (li->currItem >= num)
+ li->currItem--;
+
+ if (!li->userHasSetWidth) {
+ updateWidth(co, li, widest);
+ }
+
+ listboxDraw(co);
+
+ return 0;
+}
+
+void newtListboxClear(newtComponent co)
+{
+ struct listbox * li;
+ struct items *anitem, *nextitem;
+ if(co == NULL || (li = co->data) == NULL)
+ return;
+ for(anitem = li->boxItems; anitem != NULL; anitem = nextitem) {
+ nextitem = anitem->next;
+ free(anitem->text);
+ free(anitem);
+ }
+ li->numItems = li->numSelected = li->currItem = li->startShowItem = 0;
+ li->boxItems = NULL;
+ if (!li->userHasSetWidth)
+ updateWidth(co, li, 5);
+}
+
+/* If you don't want to get back the text, pass in NULL for the ptr-ptr. Same
+ goes for the data. */
+void newtListboxGetEntry(newtComponent co, int num, char **text, void **data) {
+ struct listbox * li = co->data;
+ int i;
+ struct items *item;
+
+ if (!li->boxItems || num >= li->numItems) {
+ if(text)
+ *text = NULL;
+ if(data)
+ *data = NULL;
+ return;
+ }
+
+ i = 0;
+ item = li->boxItems;
+ while (item && i < num) {
+ i++, item = item->next;
+ }
+
+ if (item) {
+ if (text)
+ *text = item->text;
+ if (data)
+ *data = (void *)item->data;
+ }
+}
+
+static void listboxDraw(newtComponent co)
+{
+ struct listbox * li = co->data;
+ struct items *item;
+ int i, j;
+
+ if (!co->isMapped) return ;
+
+ if(li->flags & NEWT_FLAG_BORDER) {
+ if(li->isActive)
+ SLsmg_set_color(NEWT_COLORSET_ACTLISTBOX);
+ else
+ SLsmg_set_color(NEWT_COLORSET_LISTBOX);
+
+ newtDrawBox(co->left, co->top, co->width, co->height, 0);
+ }
+
+ if(li->sb)
+ li->sb->ops->draw(li->sb);
+
+ SLsmg_set_color(NEWT_COLORSET_LISTBOX);
+
+ for(i = 0, item = li->boxItems; item != NULL && i < li->startShowItem;
+ i++, item = item->next);
+
+ j = i;
+
+ for (i = 0; item != NULL && i < li->curHeight; i++, item = item->next) {
+ if (!item->text) continue;
+
+ newtGotorc(co->top + i + li->bdyAdjust, co->left + li->bdxAdjust);
+ if(j + i == li->currItem) {
+ if(item->isSelected)
+ SLsmg_set_color(NEWT_COLORSET_ACTSELLISTBOX);
+ else
+ SLsmg_set_color(NEWT_COLORSET_ACTLISTBOX);
+ } else if(item->isSelected)
+ SLsmg_set_color(NEWT_COLORSET_SELLISTBOX);
+ else
+ SLsmg_set_color(NEWT_COLORSET_LISTBOX);
+
+ SLsmg_write_nstring(item->text, li->curWidth);
+
+ }
+ newtGotorc(co->top + (li->currItem - li->startShowItem), co->left);
+}
+
+static struct eventResult listboxEvent(newtComponent co, struct event ev) {
+ struct eventResult er;
+ struct listbox * li = co->data;
+ struct items *item;
+ int i;
+
+ er.result = ER_IGNORED;
+
+ if(ev.when == EV_EARLY || ev.when == EV_LATE) {
+ return er;
+ }
+
+ switch(ev.event) {
+ case EV_KEYPRESS:
+ if (!li->isActive) break;
+
+ switch(ev.u.key) {
+ case ' ':
+ if(!(li->flags & NEWT_FLAG_MULTIPLE)) break;
+ newtListboxSelectItem(co, li->boxItems[li->currItem].data,
+ NEWT_FLAGS_TOGGLE);
+ er.result = ER_SWALLOWED;
+ /* We don't break here, because it is cool to be able to
+ hold space to select a bunch of items in a list at once */
+
+ case NEWT_KEY_DOWN:
+ if(li->numItems <= 0) break;
+ if(li->currItem < li->numItems - 1) {
+ li->currItem++;
+ if(li->currItem > (li->startShowItem + li->curHeight - 1)) {
+ li->startShowItem = li->currItem - li->curHeight + 1;
+ if(li->startShowItem + li->curHeight > li->numItems)
+ li->startShowItem = li->numItems - li->curHeight;
+ }
+ if(li->sb)
+ newtScrollbarSet(li->sb, li->currItem + 1, li->numItems);
+ listboxDraw(co);
+ }
+ if(co->callback) co->callback(co, co->callbackData);
+ er.result = ER_SWALLOWED;
+ break;
+
+ case NEWT_KEY_ENTER:
+ if(li->numItems <= 0) break;
+ if(li->flags & NEWT_FLAG_RETURNEXIT)
+ er.result = ER_EXITFORM;
+ break;
+
+ case NEWT_KEY_UP:
+ if(li->numItems <= 0) break;
+ if(li->currItem > 0) {
+ li->currItem--;
+ if(li->currItem < li->startShowItem)
+ li->startShowItem = li->currItem;
+ if(li->sb)
+ newtScrollbarSet(li->sb, li->currItem + 1, li->numItems);
+ listboxDraw(co);
+ }
+ if(co->callback) co->callback(co, co->callbackData);
+ er.result = ER_SWALLOWED;
+ break;
+
+ case NEWT_KEY_PGUP:
+ if(li->numItems <= 0) break;
+ li->startShowItem -= li->curHeight - 1;
+ if(li->startShowItem < 0)
+ li->startShowItem = 0;
+ li->currItem -= li->curHeight - 1;
+ if(li->currItem < 0)
+ li->currItem = 0;
+ newtListboxRealSetCurrent(co);
+ er.result = ER_SWALLOWED;
+ break;
+
+ case NEWT_KEY_PGDN:
+ if(li->numItems <= 0) break;
+ li->startShowItem += li->curHeight;
+ if(li->startShowItem > (li->numItems - li->curHeight)) {
+ li->startShowItem = li->numItems - li->curHeight;
+ }
+ li->currItem += li->curHeight;
+ if(li->currItem >= li->numItems) {
+ li->currItem = li->numItems - 1;
+ }
+ newtListboxRealSetCurrent(co);
+ er.result = ER_SWALLOWED;
+ break;
+
+ case NEWT_KEY_HOME:
+ if(li->numItems <= 0) break;
+ newtListboxSetCurrent(co, 0);
+ er.result = ER_SWALLOWED;
+ break;
+
+ case NEWT_KEY_END:
+ if(li->numItems <= 0) break;
+ li->startShowItem = li->numItems - li->curHeight;
+ if(li->startShowItem < 0)
+ li->startShowItem = 0;
+ li->currItem = li->numItems - 1;
+ newtListboxRealSetCurrent(co);
+ er.result = ER_SWALLOWED;
+ break;
+ default:
+ if (li->numItems <= 0) break;
+ if (ev.u.key < NEWT_KEY_EXTRA_BASE && isalpha(ev.u.key)) {
+ for(i = 0, item = li->boxItems; item != NULL &&
+ i < li->currItem; i++, item = item->next);
+
+ if (item && item->text && (toupper(*item->text) == toupper(ev.u.key))) {
+ item = item->next;
+ i++;
+ } else {
+ item = li->boxItems;
+ i = 0;
+ }
+ while (item && item->text &&
+ toupper(*item->text) != toupper(ev.u.key)) {
+ item = item->next;
+ i++;
+ }
+ if (item) {
+ li->currItem = i;
+ if(li->currItem < li->startShowItem ||
+ li->currItem > li->startShowItem)
+ li->startShowItem =
+ li->currItem > li->numItems - li->curHeight ?
+ li->startShowItem = li->numItems - li->curHeight :
+ li->currItem;
+ if(li->sb)
+ newtScrollbarSet(li->sb, li->currItem + 1, li->numItems);
+ newtListboxRealSetCurrent(co);
+ er.result = ER_SWALLOWED;
+ }
+ }
+ }
+ break;
+
+ case EV_FOCUS:
+ li->isActive = 1;
+ listboxDraw(co);
+ er.result = ER_SWALLOWED;
+ break;
+
+ case EV_UNFOCUS:
+ li->isActive = 0;
+ listboxDraw(co);
+ er.result = ER_SWALLOWED;
+ break;
+
+ case EV_MOUSE:
+ /* if this mouse click was within the listbox, make the current
+ item the item clicked on. */
+ /* Up scroll arrow */
+ if (li->sb &&
+ ev.u.mouse.x == co->left + co->width - li->bdxAdjust - 1 &&
+ ev.u.mouse.y == co->top + li->bdyAdjust) {
+ if(li->numItems <= 0) break;
+ if(li->currItem > 0) {
+ li->currItem--;
+ if(li->currItem < li->startShowItem)
+ li->startShowItem = li->currItem;
+ if(li->sb)
+ newtScrollbarSet(li->sb, li->currItem + 1, li->numItems);
+ listboxDraw(co);
+ }
+ if(co->callback) co->callback(co, co->callbackData);
+ er.result = ER_SWALLOWED;
+ break;
+ }
+ /* Down scroll arrow */
+ if (li->sb &&
+ ev.u.mouse.x == co->left + co->width - li->bdxAdjust - 1 &&
+ ev.u.mouse.y == co->top + co->height - li->bdyAdjust - 1) {
+ if(li->numItems <= 0) break;
+ if(li->currItem < li->numItems - 1) {
+ li->currItem++;
+ if(li->currItem > (li->startShowItem + li->curHeight - 1)) {
+ li->startShowItem = li->currItem - li->curHeight + 1;
+ if(li->startShowItem + li->curHeight > li->numItems)
+ li->startShowItem = li->numItems - li->curHeight;
+ }
+ if(li->sb)
+ newtScrollbarSet(li->sb, li->currItem + 1, li->numItems);
+ listboxDraw(co);
+ }
+ if(co->callback) co->callback(co, co->callbackData);
+ er.result = ER_SWALLOWED;
+ break;
+ }
+ if ((ev.u.mouse.y >= co->top + li->bdyAdjust) &&
+ (ev.u.mouse.y <= co->top + co->height - (li->bdyAdjust * 2)) &&
+ (ev.u.mouse.x >= co->left + li->bdxAdjust) &&
+ (ev.u.mouse.x <= co->left + co->width + (li->bdxAdjust * 2))) {
+ li->currItem = li->startShowItem +
+ (ev.u.mouse.y - li->bdyAdjust - co->top);
+ newtListboxRealSetCurrent(co);
+ listboxDraw(co);
+ if(co->callback) co->callback(co, co->callbackData);
+ er.result = ER_SWALLOWED;
+ break;
+ }
+ }
+
+ return er;
+}
+
+static void listboxDestroy(newtComponent co) {
+ struct listbox * li = co->data;
+ struct items * item, * nextitem;
+
+ nextitem = item = li->boxItems;
+
+ while (item != NULL) {
+ nextitem = item->next;
+ free(item->text);
+ free(item);
+ item = nextitem;
+ }
+
+ if (li->sb) li->sb->ops->destroy(li->sb);
+
+ free(li);
+ free(co);
+}
diff --git a/mdk-stage1/newt/newt.c b/mdk-stage1/newt/newt.c
new file mode 100644
index 000000000..1cfe3ac93
--- /dev/null
+++ b/mdk-stage1/newt/newt.c
@@ -0,0 +1,672 @@
+#include <slang.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/signal.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "newt.h"
+#include "newt_pr.h"
+
+struct Window {
+ int height, width, top, left;
+ short * buffer;
+ char * title;
+};
+
+struct keymap {
+ char * str;
+ int code;
+ char * tc;
+};
+
+static struct Window windowStack[20];
+static struct Window * currentWindow = NULL;
+
+static char * helplineStack[20];
+static char ** currentHelpline = NULL;
+
+static int cursorRow, cursorCol;
+static int needResize;
+static int cursorOn = 1;
+
+static const char * defaultHelpLine =
+" <Tab>/<Alt-Tab> between elements | <Space> selects | <F12> next screen"
+;
+
+const struct newtColors newtDefaultColorPalette = {
+ "cyan", "black", /* root fg, bg */
+ "black", "blue", /* border fg, bg */
+ "white", "blue", /* window fg, bg */
+ "white", "black", /* shadow fg, bg */
+ "white", "blue", /* title fg, bg */
+ "black", "cyan", /* button fg, bg */
+ "yellow", "cyan", /* active button fg, bg */
+ "yellow", "blue", /* checkbox fg, bg */
+ "blue", "brown", /* active checkbox fg, bg */
+ "yellow", "blue", /* entry box fg, bg */
+ "white", "blue", /* label fg, bg */
+ "black", "cyan", /* listbox fg, bg */
+ "yellow", "cyan", /* active listbox fg, bg */
+ "white", "blue", /* textbox fg, bg */
+ "cyan", "black", /* active textbox fg, bg */
+ "white", "blue", /* help line */
+ "yellow", "blue", /* root text */
+ "blue", /* scale full */
+ "red", /* scale empty */
+ "blue", "cyan", /* disabled entry fg, bg */
+ "white", "blue", /* compact button fg, bg */
+ "yellow", "red", /* active & sel listbox */
+ "black", "brown" /* selected listbox */
+};
+
+static const 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" },
+ { "\033[2~", NEWT_KEY_INSERT, NULL },
+
+ { "\033\t", NEWT_KEY_UNTAB, NULL },
+
+ { "\033[5~", NEWT_KEY_PGUP, NULL },
+ { "\033[6~", NEWT_KEY_PGDN, NULL },
+ { "\033V", NEWT_KEY_PGUP, "kH" },
+ { "\033v", NEWT_KEY_PGUP, "kH" },
+
+ { "\033[[A", NEWT_KEY_F1, NULL },
+ { "\033[[B", NEWT_KEY_F2, NULL },
+ { "\033[[C", NEWT_KEY_F3, NULL },
+ { "\033[[D", NEWT_KEY_F4, NULL },
+ { "\033[[E", NEWT_KEY_F5, NULL },
+
+ { "\033OP", NEWT_KEY_F1, NULL },
+ { "\033OQ", NEWT_KEY_F2, NULL },
+ { "\033OR", NEWT_KEY_F3, NULL },
+ { "\033OS", NEWT_KEY_F4, NULL },
+
+ { "\033[11~", NEWT_KEY_F1, NULL },
+ { "\033[12~", NEWT_KEY_F2, NULL },
+ { "\033[13~", NEWT_KEY_F3, NULL },
+ { "\033[14~", NEWT_KEY_F4, NULL },
+ { "\033[15~", NEWT_KEY_F5, NULL },
+ { "\033[17~", NEWT_KEY_F6, NULL },
+ { "\033[18~", NEWT_KEY_F7, NULL },
+ { "\033[19~", NEWT_KEY_F8, NULL },
+ { "\033[20~", NEWT_KEY_F9, NULL },
+ { "\033[21~", NEWT_KEY_F10, NULL },
+ { "\033[23~", NEWT_KEY_F11, NULL },
+ { "\033[24~", NEWT_KEY_F12, NULL },
+
+ { NULL, 0, NULL }, /* LEAVE this one */
+};
+static char keyPrefix = '\033';
+
+static const char * version = "Newt windowing library version " VERSION
+ " - (C) 1996-2000 Red Hat Software. "
+ "Redistributable under the term of the Library "
+ "GNU Public License. "
+ "Written by Erik Troan\n";
+
+static newtSuspendCallback suspendCallback = NULL;
+static void * suspendCallbackData = NULL;
+
+void newtSetSuspendCallback(newtSuspendCallback cb, void * data) {
+ suspendCallback = cb;
+ suspendCallbackData = data;
+}
+
+static void handleSigwinch(int signum) {
+ needResize = 1;
+}
+
+static int getkeyInterruptHook(void) {
+ return -1;
+}
+
+void newtFlushInput(void) {
+ while (SLang_input_pending(0)) {
+ SLang_getkey();
+ }
+}
+
+void newtRefresh(void) {
+ SLsmg_refresh();
+}
+
+void newtSuspend(void) {
+ SLtt_set_cursor_visibility (1);
+ SLsmg_suspend_smg();
+ SLang_reset_tty();
+ SLtt_set_cursor_visibility (cursorOn);
+}
+
+void newtResume(void) {
+ SLsmg_resume_smg ();
+ SLsmg_refresh();
+ SLang_init_tty(0, 0, 0);
+}
+
+void newtCls(void) {
+ SLsmg_set_color(NEWT_COLORSET_ROOT);
+ SLsmg_gotorc(0, 0);
+ SLsmg_erase_eos();
+
+ newtRefresh();
+}
+
+#if defined(THIS_DOESNT_WORK)
+void newtResizeScreen(int redraw) {
+ newtPushHelpLine("");
+
+ SLtt_get_screen_size();
+ SLang_init_tty(0, 0, 0);
+
+ SLsmg_touch_lines (0, SLtt_Screen_Rows - 1);
+
+ /* I don't know why I need this */
+ SLsmg_refresh();
+
+ newtPopHelpLine();
+
+ if (redraw)
+ SLsmg_refresh();
+}
+#endif
+
+int newtInit(void) {
+ char * MonoValue, * MonoEnv = "NEWT_MONO";
+
+ /* use the version variable just to be sure it gets included */
+ strlen(version);
+
+ SLtt_get_terminfo();
+ SLtt_get_screen_size();
+
+ MonoValue = getenv(MonoEnv);
+ if ( MonoValue == NULL ) {
+ SLtt_Use_Ansi_Colors = 1;
+ } else {
+ SLtt_Use_Ansi_Colors = 0;
+ }
+
+ SLsmg_init_smg();
+ SLang_init_tty(0, 0, 0);
+
+ newtSetColors(newtDefaultColorPalette);
+ newtCursorOff();
+ /*initKeymap();*/
+
+ /*memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = handleSigwinch;
+ sigaction(SIGWINCH, &sa, NULL);*/
+
+ SLsignal_intr(SIGWINCH, handleSigwinch);
+ SLang_getkey_intr_hook = getkeyInterruptHook;
+
+
+
+ return 0;
+}
+
+int newtFinished(void) {
+ SLsmg_gotorc(SLtt_Screen_Rows - 1, 0);
+ newtCursorOn();
+ SLsmg_refresh();
+ SLsmg_reset_smg();
+ SLang_reset_tty();
+
+ return 0;
+}
+
+void newtSetColors(struct newtColors colors) {
+ SLtt_set_color(NEWT_COLORSET_ROOT, "", colors.rootFg, colors.rootBg);
+ SLtt_set_color(NEWT_COLORSET_BORDER, "", colors.borderFg, colors.borderBg);
+ SLtt_set_color(NEWT_COLORSET_WINDOW, "", colors.windowFg, colors.windowBg);
+ SLtt_set_color(NEWT_COLORSET_SHADOW, "", colors.shadowFg, colors.shadowBg);
+ SLtt_set_color(NEWT_COLORSET_TITLE, "", colors.titleFg, colors.titleBg);
+ SLtt_set_color(NEWT_COLORSET_BUTTON, "", colors.buttonFg, colors.buttonBg);
+ SLtt_set_color(NEWT_COLORSET_ACTBUTTON, "", colors.actButtonFg,
+ colors.actButtonBg);
+ SLtt_set_color(NEWT_COLORSET_CHECKBOX, "", colors.checkboxFg,
+ colors.checkboxBg);
+ SLtt_set_color(NEWT_COLORSET_ACTCHECKBOX, "", colors.actCheckboxFg,
+ colors.actCheckboxBg);
+ SLtt_set_color(NEWT_COLORSET_ENTRY, "", colors.entryFg, colors.entryBg);
+ SLtt_set_color(NEWT_COLORSET_LABEL, "", colors.labelFg, colors.labelBg);
+ SLtt_set_color(NEWT_COLORSET_LISTBOX, "", colors.listboxFg,
+ colors.listboxBg);
+ SLtt_set_color(NEWT_COLORSET_ACTLISTBOX, "", colors.actListboxFg,
+ colors.actListboxBg);
+ SLtt_set_color(NEWT_COLORSET_TEXTBOX, "", colors.textboxFg,
+ colors.textboxBg);
+ SLtt_set_color(NEWT_COLORSET_ACTTEXTBOX, "", colors.actTextboxFg,
+ colors.actTextboxBg);
+ SLtt_set_color(NEWT_COLORSET_HELPLINE, "", colors.helpLineFg,
+ colors.helpLineBg);
+ SLtt_set_color(NEWT_COLORSET_ROOTTEXT, "", colors.rootTextFg,
+ colors.rootTextBg);
+
+ SLtt_set_color(NEWT_COLORSET_EMPTYSCALE, "", "black",
+ colors.emptyScale);
+ SLtt_set_color(NEWT_COLORSET_FULLSCALE, "", "black",
+ colors.fullScale);
+ SLtt_set_color(NEWT_COLORSET_DISENTRY, "", colors.disabledEntryFg,
+ colors.disabledEntryBg);
+
+ SLtt_set_color(NEWT_COLORSET_COMPACTBUTTON, "", colors.compactButtonFg,
+ colors.compactButtonBg);
+
+ SLtt_set_color(NEWT_COLORSET_ACTSELLISTBOX, "", colors.actSelListboxFg,
+ colors.actSelListboxBg);
+ SLtt_set_color(NEWT_COLORSET_SELLISTBOX, "", colors.selListboxFg,
+ colors.selListboxBg);
+}
+
+int newtGetKey(void) {
+ int key;
+ char buf[10], * chptr = buf;
+ const struct keymap * curr;
+
+ do {
+ key = SLang_getkey();
+ if (key == 0xFFFF) {
+ if (needResize)
+ return NEWT_KEY_RESIZE;
+
+ /* ignore other signals */
+ continue;
+ }
+
+ if (key == NEWT_KEY_SUSPEND && suspendCallback)
+ suspendCallback(suspendCallbackData);
+ } while (key == NEWT_KEY_SUSPEND);
+
+ switch (key) {
+ case 'v' | 0x80:
+ case 'V' | 0x80:
+ return NEWT_KEY_PGUP;
+
+ case 22:
+ return NEWT_KEY_PGDN;
+
+ return NEWT_KEY_BKSPC;
+ 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(5)) {
+ key = SLang_getkey();
+ if (key == keyPrefix) {
+ /* he hit unknown keys too many times -- start over */
+ memset(buf, 0, sizeof(buf));
+ chptr = buf;
+ }
+
+ *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,
+ const char * title) {
+ int j, row, col;
+ int n;
+ int i;
+
+ newtFlushInput();
+
+ if (!currentWindow) {
+ currentWindow = windowStack;
+ } else {
+ currentWindow++;
+ }
+
+ currentWindow->left = left;
+ currentWindow->top = top;
+ currentWindow->width = width;
+ currentWindow->height = height;
+ currentWindow->title = title ? strdup(title) : NULL;
+
+ currentWindow->buffer = malloc(sizeof(short) * (width + 3) * (height + 3));
+
+ row = top - 1;
+ col = left - 1;
+ n = 0;
+ for (j = 0; j < height + 3; j++, row++) {
+ SLsmg_gotorc(row, col);
+ SLsmg_read_raw(currentWindow->buffer + n,
+ currentWindow->width + 3);
+ n += currentWindow->width + 3;
+ }
+
+ SLsmg_set_color(NEWT_COLORSET_BORDER);
+ SLsmg_draw_box(top - 1, left - 1, height + 2, width + 2);
+
+ if (currentWindow->title) {
+ i = strlen(currentWindow->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(NEWT_COLORSET_TITLE);
+ SLsmg_write_string((char *)currentWindow->title);
+ SLsmg_set_color(NEWT_COLORSET_BORDER);
+ SLsmg_write_char(' ');
+ SLsmg_set_char_set(1);
+ SLsmg_write_char(SLSMG_LTEE_CHAR);
+ SLsmg_set_char_set(0);
+ }
+
+ SLsmg_set_color(NEWT_COLORSET_WINDOW);
+ SLsmg_fill_region(top, left, height, width, ' ');
+
+ SLsmg_set_color(NEWT_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;
+}
+
+int newtCenteredWindow(int width, int height, const char * title) {
+ int top, left;
+
+ top = (SLtt_Screen_Rows - height) / 2;
+
+ /* I don't know why, but this seems to look better */
+ if ((SLtt_Screen_Rows % 2) && (top % 2)) top--;
+
+ left = (SLtt_Screen_Cols - width) / 2;
+
+ newtOpenWindow(left, top, width, height, title);
+
+ 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_raw(currentWindow->buffer + n,
+ currentWindow->width + 3);
+ n += currentWindow->width + 3;
+ }
+
+ free(currentWindow->buffer);
+ free(currentWindow->title);
+
+ if (currentWindow == windowStack)
+ currentWindow = NULL;
+ else
+ currentWindow--;
+
+ SLsmg_set_char_set(0);
+
+ newtRefresh();
+}
+
+void newtGetWindowPos(int * x, int * y) {
+ if (currentWindow) {
+ *x = currentWindow->left;
+ *y = currentWindow->top;
+ } else
+ *x = *y = 0;
+}
+
+void newtGetrc(int * row, int * col) {
+ *row = cursorRow;
+ *col = cursorCol;
+}
+
+void newtGotorc(int newRow, int newCol) {
+ if (currentWindow) {
+ newRow += currentWindow->top;
+ newCol += currentWindow->left;
+ }
+
+ cursorRow = newRow;
+ cursorCol = newCol;
+ SLsmg_gotorc(cursorRow, cursorCol);
+}
+
+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(NEWT_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);
+}
+
+struct eventResult newtDefaultEventHandler(newtComponent c,
+ struct event ev) {
+ struct eventResult er;
+
+ er.result = ER_IGNORED;
+ return er;
+}
+
+void newtRedrawHelpLine(void) {
+ char * buf;
+
+ SLsmg_set_color(NEWT_COLORSET_HELPLINE);
+
+ buf = alloca(SLtt_Screen_Cols + 1);
+ memset(buf, ' ', SLtt_Screen_Cols);
+ buf[SLtt_Screen_Cols] = '\0';
+
+ if (currentHelpline)
+ memcpy(buf, *currentHelpline, strlen(*currentHelpline));
+
+ SLsmg_gotorc(SLtt_Screen_Rows - 1, 0);
+ SLsmg_write_string(buf);
+}
+
+void newtPushHelpLine(const char * text) {
+ if (!text)
+ text = defaultHelpLine;
+
+ if (currentHelpline)
+ (*(++currentHelpline)) = strdup(text);
+ else {
+ currentHelpline = helplineStack;
+ *currentHelpline = strdup(text);
+ }
+
+ newtRedrawHelpLine();
+}
+
+void newtPopHelpLine(void) {
+ if (!currentHelpline) return;
+
+ free(*currentHelpline);
+ if (currentHelpline == helplineStack)
+ currentHelpline = NULL;
+ else
+ currentHelpline--;
+
+ newtRedrawHelpLine();
+}
+
+void newtDrawRootText(int col, int row, const char * text) {
+ SLsmg_set_color(NEWT_COLORSET_ROOTTEXT);
+
+ if (col < 0) {
+ col = SLtt_Screen_Cols + col;
+ }
+
+ if (row < 0) {
+ row = SLtt_Screen_Rows + row;
+ }
+
+ SLsmg_gotorc(row, col);
+ SLsmg_write_string((char *)text);
+}
+
+int newtSetFlags(int oldFlags, int newFlags, enum newtFlagsSense sense) {
+ switch (sense) {
+ case NEWT_FLAGS_SET:
+ return oldFlags | newFlags;
+
+ case NEWT_FLAGS_RESET:
+ return oldFlags & (~newFlags);
+
+ case NEWT_FLAGS_TOGGLE:
+ return oldFlags ^ newFlags;
+
+ default:
+ return oldFlags;
+ }
+}
+
+void newtBell(void)
+{
+ SLtt_beep();
+}
+
+void newtGetScreenSize(int * cols, int * rows) {
+ if (rows) *rows = SLtt_Screen_Rows;
+ if (cols) *cols = SLtt_Screen_Cols;
+}
+
+void newtDefaultPlaceHandler(newtComponent c, int newLeft, int newTop) {
+ c->left = newLeft;
+ c->top = newTop;
+}
+
+void newtDefaultMappedHandler(newtComponent c, int isMapped) {
+ c->isMapped = isMapped;
+}
+
+void newtCursorOff(void) {
+ cursorOn = 0;
+ SLtt_set_cursor_visibility (cursorOn);
+}
+
+void newtCursorOn(void) {
+ cursorOn = 1;
+ SLtt_set_cursor_visibility (cursorOn);
+}
diff --git a/mdk-stage1/newt/newt.h b/mdk-stage1/newt/newt.h
new file mode 100644
index 000000000..d3fd8bedc
--- /dev/null
+++ b/mdk-stage1/newt/newt.h
@@ -0,0 +1,362 @@
+#ifndef H_NEWT
+#define H_NEWT
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdarg.h>
+
+#define NEWT_COLORSET_ROOT 2
+#define NEWT_COLORSET_BORDER 3
+#define NEWT_COLORSET_WINDOW 4
+#define NEWT_COLORSET_SHADOW 5
+#define NEWT_COLORSET_TITLE 6
+#define NEWT_COLORSET_BUTTON 7
+#define NEWT_COLORSET_ACTBUTTON 8
+#define NEWT_COLORSET_CHECKBOX 9
+#define NEWT_COLORSET_ACTCHECKBOX 10
+#define NEWT_COLORSET_ENTRY 11
+#define NEWT_COLORSET_LABEL 12
+#define NEWT_COLORSET_LISTBOX 13
+#define NEWT_COLORSET_ACTLISTBOX 14
+#define NEWT_COLORSET_TEXTBOX 15
+#define NEWT_COLORSET_ACTTEXTBOX 16
+#define NEWT_COLORSET_HELPLINE 17
+#define NEWT_COLORSET_ROOTTEXT 18
+#define NEWT_COLORSET_EMPTYSCALE 19
+#define NEWT_COLORSET_FULLSCALE 20
+#define NEWT_COLORSET_DISENTRY 21
+#define NEWT_COLORSET_COMPACTBUTTON 22
+#define NEWT_COLORSET_ACTSELLISTBOX 23
+#define NEWT_COLORSET_SELLISTBOX 24
+
+#define NEWT_ARG_LAST -100000
+#define NEWT_ARG_APPEND -1
+
+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;
+ char * labelFg, * labelBg;
+ char * listboxFg, * listboxBg;
+ char * actListboxFg, * actListboxBg;
+ char * textboxFg, * textboxBg;
+ char * actTextboxFg, * actTextboxBg;
+ char * helpLineFg, * helpLineBg;
+ char * rootTextFg, * rootTextBg;
+ char * emptyScale, * fullScale;
+ char * disabledEntryFg, * disabledEntryBg;
+ char * compactButtonFg, * compactButtonBg;
+ char * actSelListboxFg, * actSelListboxBg;
+ char * selListboxFg, * selListboxBg;
+};
+
+enum newtFlagsSense { NEWT_FLAGS_SET, NEWT_FLAGS_RESET, NEWT_FLAGS_TOGGLE };
+
+#define NEWT_FLAG_RETURNEXIT (1 << 0)
+#define NEWT_FLAG_HIDDEN (1 << 1)
+#define NEWT_FLAG_SCROLL (1 << 2)
+#define NEWT_FLAG_DISABLED (1 << 3)
+/* OBSOLETE #define NEWT_FLAG_NOSCROLL (1 << 4) for listboxes */
+#define NEWT_FLAG_BORDER (1 << 5)
+#define NEWT_FLAG_WRAP (1 << 6)
+#define NEWT_FLAG_NOF12 (1 << 7)
+#define NEWT_FLAG_MULTIPLE (1 << 8)
+#define NEWT_FLAG_SELECTED (1 << 9)
+#define NEWT_FLAG_CHECKBOX (1 << 10)
+#define NEWT_FLAG_PASSWORD (1 << 11) /* draw '*' of chars in entrybox */
+#define NEWT_FD_READ (1 << 0)
+#define NEWT_FD_WRITE (1 << 1)
+
+#define NEWT_CHECKBOXTREE_COLLAPSED '\0'
+#define NEWT_CHECKBOXTREE_EXPANDED '\1'
+#define NEWT_CHECKBOXTREE_UNSELECTED ' '
+#define NEWT_CHECKBOXTREE_SELECTED '*'
+
+/* Backwards compatibility */
+#define NEWT_LISTBOX_RETURNEXIT NEWT_FLAG_RETURNEXIT
+#define NEWT_ENTRY_SCROLL NEWT_FLAG_SCROLL
+#define NEWT_ENTRY_HIDDEN NEWT_FLAG_HIDDEN
+#define NEWT_ENTRY_RETURNEXIT NEWT_FLAG_RETURNEXIT
+#define NEWT_ENTRY_DISABLED NEWT_FLAG_DISABLED
+
+#define NEWT_TEXTBOX_WRAP NEWT_FLAG_WRAP
+#define NEWT_TEXTBOX_SCROLL NEWT_FLAG_SCROLL
+#define NEWT_FORM_NOF12 NEWT_FLAG_NOF12
+
+#define newtListboxAddEntry newtListboxAppendEntry
+
+
+typedef struct newtComponent_struct * newtComponent;
+
+extern const struct newtColors newtDefaultColorPalette;
+
+typedef void (*newtCallback)(newtComponent, void *);
+typedef void (*newtSuspendCallback)(void * data);
+
+int newtInit(void);
+int newtFinished(void);
+void newtCls(void);
+void newtResizeScreen(int redraw);
+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,
+ const char * title);
+int newtCenteredWindow(int width, int height, const char * title);
+void newtPopWindow(void);
+void newtSetColors(struct newtColors colors);
+void newtRefresh(void);
+void newtSuspend(void);
+void newtSetSuspendCallback(newtSuspendCallback cb, void * data);
+void newtSetHelpCallback(newtCallback cb);
+void newtResume(void);
+void newtPushHelpLine(const char * text);
+void newtRedrawHelpLine(void);
+void newtPopHelpLine(void);
+void newtDrawRootText(int col, int row, const char * text);
+void newtBell(void);
+void newtCursorOff(void);
+void newtCursorOn(void);
+
+/* Components */
+
+newtComponent newtCompactButton(int left, int top, const char * text);
+newtComponent newtButton(int left, int top, const char * text);
+newtComponent newtCheckbox(int left, int top, const char * text, char defValue,
+ const char * seq, char * result);
+char newtCheckboxGetValue(newtComponent co);
+void newtCheckboxSetValue(newtComponent co, char value);
+void newtCheckboxSetFlags(newtComponent co, int flags, enum newtFlagsSense sense);
+
+
+newtComponent newtRadiobutton(int left, int top, const char * text, int isDefault,
+ newtComponent prevButton);
+newtComponent newtRadioGetCurrent(newtComponent setMember);
+newtComponent newtListitem(int left, int top, const char * text, int isDefault,
+ newtComponent prevItem, const void * data, int flags);
+void newtListitemSet(newtComponent co, const char * text);
+void * newtListitemGetData(newtComponent co);
+void newtGetScreenSize(int * cols, int * rows);
+
+newtComponent newtLabel(int left, int top, const char * text);
+void newtLabelSetText(newtComponent co, const char * text);
+newtComponent newtVerticalScrollbar(int left, int top, int height,
+ int normalColorset, int thumbColorset);
+void newtScrollbarSet(newtComponent co, int where, int total);
+
+newtComponent newtListbox(int left, int top, int height, int flags);
+void * newtListboxGetCurrent(newtComponent co);
+void newtListboxSetCurrent(newtComponent co, int num);
+void newtListboxSetCurrentByKey(newtComponent co, void * key);
+void newtListboxSetEntry(newtComponent co, int num, const char * text);
+void newtListboxSetWidth(newtComponent co, int width);
+void newtListboxSetData(newtComponent co, int num, void * data);
+int newtListboxAppendEntry(newtComponent co, const char * text,
+ const void * data);
+/* Send the key to insert after, or NULL to insert at the top */
+int newtListboxInsertEntry(newtComponent co, const char * text, const void * data, void * key);
+int newtListboxDeleteEntry(newtComponent co, void * data);
+void newtListboxClear(newtComponent co); /* removes all entries from listbox */
+void newtListboxGetEntry(newtComponent co, int num, char **text, void **data);
+/* Returns an array of data pointers from items, last element is NULL */
+void **newtListboxGetSelection(newtComponent co, int *numitems);
+void newtListboxClearSelection(newtComponent co);
+void newtListboxSelectItem(newtComponent co, const void * key,
+ enum newtFlagsSense sense);
+
+newtComponent newtCheckboxTree(int left, int top, int height, int flags);
+newtComponent newtCheckboxTreeMulti(int left, int top, int height, char *seq, int flags);
+const void ** newtCheckboxTreeGetSelection(newtComponent co, int *numitems);
+const void * newtCheckboxTreeGetCurrent(newtComponent co);
+const void ** newtCheckboxTreeGetMultiSelection(newtComponent co, int *numitems, char seqnum);
+/* last item is NEWT_ARG_LAST for all of these */
+int newtCheckboxTreeAddItem(newtComponent co,
+ const char * text, const void * data,
+ int flags, int index, ...);
+int newtCheckboxTreeAddArray(newtComponent co,
+ const char * text, const void * data,
+ int flags, int * indexes);
+int * newtCheckboxTreeFindItem(newtComponent co, void * data);
+void newtCheckboxTreeSetEntry(newtComponent co, const void * data,
+ const char * text);
+char newtCheckboxTreeGetEntryValue(newtComponent co, const void * data);
+void newtCheckboxTreeSetEntryValue(newtComponent co, const void * data,
+ char value);
+
+newtComponent newtTextboxReflowed(int left, int top, char * text, int width,
+ int flexDown, int flexUp, int flags);
+newtComponent newtTextbox(int left, int top, int width, int height, int flags);
+void newtTextboxSetText(newtComponent co, const char * text);
+void newtTextboxSetHeight(newtComponent co, int height);
+int newtTextboxGetNumLines(newtComponent co);
+char * newtReflowText(char * text, int width, int flexDown, int flexUp,
+ int * actualWidth, int * actualHeight);
+
+struct newtExitStruct {
+ enum { NEWT_EXIT_HOTKEY, NEWT_EXIT_COMPONENT, NEWT_EXIT_FDREADY,
+ NEWT_EXIT_TIMER } reason;
+ union {
+ int key;
+ newtComponent co;
+ } u;
+} ;
+
+newtComponent newtForm(newtComponent vertBar, void * helpTag, int flags);
+void newtFormSetTimer(newtComponent form, int millisecs);
+void newtFormWatchFd(newtComponent form, int fd, int fdFlags);
+void newtFormSetSize(newtComponent co);
+newtComponent newtFormGetCurrent(newtComponent co);
+void newtFormSetBackground(newtComponent co, int color);
+void newtFormSetCurrent(newtComponent co, newtComponent subco);
+void newtFormAddComponent(newtComponent form, newtComponent co);
+void newtFormAddComponents(newtComponent form, ...);
+void newtFormSetHeight(newtComponent co, int height);
+void newtFormSetWidth(newtComponent co, int width);
+newtComponent newtRunForm(newtComponent form); /* obsolete */
+void newtFormRun(newtComponent co, struct newtExitStruct * es);
+void newtDrawForm(newtComponent form);
+void newtFormAddHotKey(newtComponent co, int key);
+
+typedef int (*newtEntryFilter)(newtComponent entry, void * data, int ch,
+ int cursor);
+newtComponent newtEntry(int left, int top, const char * initialValue, int width,
+ char ** resultPtr, int flags);
+void newtEntrySet(newtComponent co, const char * value, int cursorAtEnd);
+void newtEntrySetFilter(newtComponent co, newtEntryFilter filter, void * data);
+char * newtEntryGetValue(newtComponent co);
+void newtEntrySetFlags(newtComponent co, int flags, enum newtFlagsSense sense);
+
+newtComponent newtScale(int left, int top, int width, int fullValue);
+void newtScaleSet(newtComponent co, unsigned int amount);
+
+void newtComponentAddCallback(newtComponent co, newtCallback f, void * data);
+void newtComponentTakesFocus(newtComponent co, int val);
+
+/* this also destroys all of the components (including other forms) on the
+ form */
+void newtFormDestroy(newtComponent form);
+
+/* Key codes */
+
+#define NEWT_KEY_TAB '\t'
+#define NEWT_KEY_ENTER '\r'
+#define NEWT_KEY_SUSPEND '\032' /* ctrl - z*/
+#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
+#define NEWT_KEY_UNTAB NEWT_KEY_EXTRA_BASE + 10
+#define NEWT_KEY_PGUP NEWT_KEY_EXTRA_BASE + 11
+#define NEWT_KEY_PGDN NEWT_KEY_EXTRA_BASE + 12
+#define NEWT_KEY_INSERT NEWT_KEY_EXTRA_BASE + 13
+
+#define NEWT_KEY_F1 NEWT_KEY_EXTRA_BASE + 101
+#define NEWT_KEY_F2 NEWT_KEY_EXTRA_BASE + 102
+#define NEWT_KEY_F3 NEWT_KEY_EXTRA_BASE + 103
+#define NEWT_KEY_F4 NEWT_KEY_EXTRA_BASE + 104
+#define NEWT_KEY_F5 NEWT_KEY_EXTRA_BASE + 105
+#define NEWT_KEY_F6 NEWT_KEY_EXTRA_BASE + 106
+#define NEWT_KEY_F7 NEWT_KEY_EXTRA_BASE + 107
+#define NEWT_KEY_F8 NEWT_KEY_EXTRA_BASE + 108
+#define NEWT_KEY_F9 NEWT_KEY_EXTRA_BASE + 109
+#define NEWT_KEY_F10 NEWT_KEY_EXTRA_BASE + 110
+#define NEWT_KEY_F11 NEWT_KEY_EXTRA_BASE + 111
+#define NEWT_KEY_F12 NEWT_KEY_EXTRA_BASE + 112
+
+/* not really a key, but newtGetKey returns it */
+#define NEWT_KEY_RESIZE NEWT_KEY_EXTRA_BASE + 113
+
+#define NEWT_ANCHOR_LEFT (1 << 0)
+#define NEWT_ANCHOR_RIGHT (1 << 1)
+#define NEWT_ANCHOR_TOP (1 << 2)
+#define NEWT_ANCHOR_BOTTOM (1 << 3)
+
+#define NEWT_GRID_FLAG_GROWX (1 << 0)
+#define NEWT_GRID_FLAG_GROWY (1 << 1)
+
+typedef struct grid_s * newtGrid;
+enum newtGridElement { NEWT_GRID_EMPTY = 0,
+ NEWT_GRID_COMPONENT, NEWT_GRID_SUBGRID };
+
+newtGrid newtCreateGrid(int cols, int rows);
+/* TYPE, what, TYPE, what, ..., NULL */
+newtGrid newtGridVStacked(enum newtGridElement type, void * what, ...);
+newtGrid newtGridVCloseStacked(enum newtGridElement type, void * what, ...);
+newtGrid newtGridHStacked(enum newtGridElement type1, void * what1, ...);
+newtGrid newtGridHCloseStacked(enum newtGridElement type1, void * what1, ...);
+newtGrid newtGridBasicWindow(newtComponent text, newtGrid middle,
+ newtGrid buttons);
+newtGrid newtGridSimpleWindow(newtComponent text, newtComponent middle,
+ newtGrid buttons);
+void newtGridSetField(newtGrid grid, int col, int row,
+ enum newtGridElement type, void * val, int padLeft,
+ int padTop, int padRight, int padBottom, int anchor,
+ int flags);
+void newtGridPlace(newtGrid grid, int left, int top);
+#define newtGridDestroy newtGridFree
+void newtGridFree(newtGrid grid, int recurse);
+void newtGridGetSize(newtGrid grid, int * width, int * height);
+void newtGridWrappedWindow(newtGrid grid, char * title);
+void newtGridWrappedWindowAt(newtGrid grid, char * title, int left, int top);
+void newtGridAddComponentsToForm(newtGrid grid, newtComponent form,
+ int recurse);
+
+/* convienve */
+newtGrid newtButtonBarv(char * button1, newtComponent * b1comp, va_list args);
+newtGrid newtButtonBar(char * button1, newtComponent * b1comp, ...);
+
+/* automatically centered and shrink wrapped */
+void newtWinMessage(char * title, char * buttonText, char * text, ...);
+void newtWinMessagev(char * title, char * buttonText, char * text,
+ va_list argv);
+
+/* having separate calls for these two seems silly, but having two separate
+ variable length-arg lists seems like a bad idea as well */
+
+/* Returns 0 if F12 was pressed, 1 for button1, 2 for button2 */
+int newtWinChoice(char * title, char * button1, char * button2,
+ char * text, ...);
+/* Returns 0 if F12 was pressed, 1 for button1, 2 for button2,
+ 3 for button3 */
+int newtWinTernary(char * title, char * button1, char * button2,
+ char * button3, char * message, ...);
+
+/* Returns the button number pressed, 0 on F12 */
+int newtWinMenu(char * title, char * text, int suggestedWidth, int flexDown,
+ int flexUp, int maxListHeight, char ** items, int * listItem,
+ char * button1, ...);
+
+struct newtWinEntry {
+ char * text;
+ char ** value; /* may be initialized to set default */
+ int flags;
+};
+
+/* Returns the button number pressed, 0 on F12. The final values are
+ dynamically allocated, and need to be freed. */
+int newtWinEntries(char * title, char * text, int suggestedWidth, int flexDown,
+ int flexUp, int dataWidth,
+ struct newtWinEntry * items, char * button1, ...);
+
+#ifdef __cplusplus
+} /* End of extern "C" { */
+#endif
+
+#endif /* H_NEWT */
diff --git a/mdk-stage1/newt/newt_pr.h b/mdk-stage1/newt/newt_pr.h
new file mode 100644
index 000000000..76f5e2f6f
--- /dev/null
+++ b/mdk-stage1/newt/newt_pr.h
@@ -0,0 +1,82 @@
+#ifndef H_NEWT_PR
+#define H_NEWT_PR
+
+#define COLORSET_ROOT NEWT_COLORSET_ROOT
+#define COLORSET_BORDER NEWT_COLORSET_BORDER
+#define COLORSET_WINDOW NEWT_COLORSET_WINDOW
+#define COLORSET_SHADOW NEWT_COLORSET_SHADOW
+#define COLORSET_TITLE NEWT_COLORSET_TITLE
+#define COLORSET_BUTTON NEWT_COLORSET_BUTTON
+#define COLORSET_ACTBUTTON NEWT_COLORSET_ACTBUTTON
+#define COLORSET_CHECKBOX NEWT_COLORSET_CHECKBOX
+#define COLORSET_ACTCHECKBOX NEWT_COLORSET_ACTCHECKBOX
+#define COLORSET_ENTRY NEWT_COLORSET_ENTRY
+#define COLORSET_LABEL NEWT_COLORSET_LABEL
+#define COLORSET_LISTBOX NEWT_COLORSET_LISTBOX
+#define COLORSET_ACTLISTBOX NEWT_COLORSET_ACTLISTBOX
+#define COLORSET_TEXTBOX NEWT_COLORSET_TEXTBOX
+#define COLORSET_ACTTEXTBOX NEWT_COLORSET_ACTTEXTBOX
+
+int newtSetFlags(int oldFlags, int newFlags, enum newtFlagsSense sense);
+
+void newtGotorc(int row, int col);
+void newtGetrc(int * row, int * col);
+void newtGetWindowPos(int * x, int * y);
+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_struct {
+ /* common data */
+ int height, width;
+ int top, left;
+ int takesFocus;
+ int isMapped;
+
+ struct componentOps * ops;
+
+ newtCallback callback;
+ void * callbackData;
+
+ void * data;
+} ;
+
+enum eventResultTypes { ER_IGNORED, ER_SWALLOWED, ER_EXITFORM, ER_SETFOCUS,
+ ER_NEXTCOMP };
+struct eventResult {
+ enum eventResultTypes result;
+ union {
+ newtComponent focus;
+ } u;
+};
+
+enum eventTypes { EV_FOCUS, EV_UNFOCUS, EV_KEYPRESS, EV_MOUSE };
+enum eventSequence { EV_EARLY, EV_NORMAL, EV_LATE };
+
+struct event {
+ enum eventTypes event;
+ enum eventSequence when;
+ union {
+ int key;
+ struct {
+ enum { MOUSE_MOTION, MOUSE_BUTTON_DOWN, MOUSE_BUTTON_UP } type;
+ int x, y;
+ } mouse;
+ } u;
+} ;
+
+struct componentOps {
+ void (* draw)(newtComponent c);
+ struct eventResult (* event)(newtComponent c, struct event ev);
+ void (* destroy)(newtComponent c);
+ void (* place)(newtComponent c, int newLeft, int newTop);
+ void (* mapped)(newtComponent c, int isMapped);
+} ;
+
+void newtDefaultPlaceHandler(newtComponent c, int newLeft, int newTop);
+void newtDefaultMappedHandler(newtComponent c, int isMapped);
+struct eventResult newtDefaultEventHandler(newtComponent c,
+ struct event ev);
+
+#endif /* H_NEWT_PR */
diff --git a/mdk-stage1/newt/scale.c b/mdk-stage1/newt/scale.c
new file mode 100644
index 000000000..800958580
--- /dev/null
+++ b/mdk-stage1/newt/scale.c
@@ -0,0 +1,72 @@
+#include <slang.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "newt.h"
+#include "newt_pr.h"
+
+struct scale {
+ int fullValue;
+ int charsSet;
+};
+
+static void scaleDraw(newtComponent co);
+
+static struct componentOps scaleOps = {
+ scaleDraw,
+ newtDefaultEventHandler,
+ NULL,
+ newtDefaultPlaceHandler,
+ newtDefaultMappedHandler,
+} ;
+
+newtComponent newtScale(int left, int top, int width, int fullValue) {
+ newtComponent co;
+ struct scale * sc;
+
+ co = malloc(sizeof(*co));
+ sc = malloc(sizeof(struct scale));
+ co->data = sc;
+
+ co->ops = &scaleOps;
+
+ co->height = 1;
+ co->width = width;
+ co->top = top;
+ co->left = left;
+ co->takesFocus = 0;
+
+ sc->fullValue = fullValue;
+ sc->charsSet = 0;
+
+ return co;
+}
+
+void newtScaleSet(newtComponent co, unsigned int amount) {
+ struct scale * sc = co->data;
+ int newCharsSet;
+
+ newCharsSet = (amount * co->width) / sc->fullValue;
+
+ if (newCharsSet != sc->charsSet) {
+ sc->charsSet = newCharsSet;
+ scaleDraw(co);
+ }
+}
+
+static void scaleDraw(newtComponent co) {
+ struct scale * sc = co->data;
+ int i;
+
+ if (co->top == -1) return;
+
+ newtGotorc(co->top, co->left);
+
+ SLsmg_set_color(NEWT_COLORSET_FULLSCALE);
+ for (i = 0; i < sc->charsSet; i++)
+ SLsmg_write_string(" ");
+
+ SLsmg_set_color(NEWT_COLORSET_EMPTYSCALE);
+ for (i = 0; i < (co->width - sc->charsSet); i++)
+ SLsmg_write_string(" ");
+}
diff --git a/mdk-stage1/newt/scrollbar.c b/mdk-stage1/newt/scrollbar.c
new file mode 100644
index 000000000..cb4bc2757
--- /dev/null
+++ b/mdk-stage1/newt/scrollbar.c
@@ -0,0 +1,124 @@
+#include <slang.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "newt.h"
+#include "newt_pr.h"
+
+struct scrollbar {
+ int curr;
+ int cs, csThumb;
+ int arrows;
+} ;
+
+static void sbDraw(newtComponent co);
+static void sbDestroy(newtComponent co);
+static void sbDrawThumb(newtComponent co, int isOn);
+
+static struct componentOps sbOps = {
+ sbDraw,
+ newtDefaultEventHandler,
+ sbDestroy,
+ newtDefaultPlaceHandler,
+ newtDefaultMappedHandler,
+} ;
+
+void newtScrollbarSet(newtComponent co, int where, int total) {
+ struct scrollbar * sb = co->data;
+ int new;
+
+ if (sb->arrows)
+ new = (where * (co->height - 3)) / (total ? total : 1) + 1;
+ else
+ new = (where * (co->height - 1)) / (total ? total : 1);
+ if (new != sb->curr) {
+ sbDrawThumb(co, 0);
+ sb->curr = new;
+ sbDrawThumb(co, 1);
+ }
+}
+
+newtComponent newtVerticalScrollbar(int left, int top, int height,
+ int normalColorset, int thumbColorset) {
+ newtComponent co;
+ struct scrollbar * sb;
+
+ co = malloc(sizeof(*co));
+ sb = malloc(sizeof(*sb));
+ co->data = sb;
+
+ if (!strcmp(getenv("TERM"), "linux") && height >= 2) {
+ sb->arrows = 1;
+ sb->curr = 1;
+ } else {
+ sb->arrows = 0;
+ sb->curr = 0;
+ }
+ sb->cs = normalColorset;
+ sb->csThumb = thumbColorset;
+
+ co->ops = &sbOps;
+ co->isMapped = 0;
+ co->left = left;
+ co->top = top;
+ co->height = height;
+ co->width = 1;
+ co->takesFocus = 0;
+
+ return co;
+}
+
+static void sbDraw(newtComponent co) {
+ struct scrollbar * sb = co->data;
+ int i;
+
+ if (!co->isMapped) return;
+
+ SLsmg_set_color(sb->cs);
+
+ SLsmg_set_char_set(1);
+ if (sb->arrows) {
+ newtGotorc(co->top, co->left);
+ SLsmg_write_char('\x2d');
+ for (i = 1; i < co->height - 1; i++) {
+ newtGotorc(i + co->top, co->left);
+ SLsmg_write_char('\x61');
+ }
+ newtGotorc(co->top + co->height - 1, co->left);
+ SLsmg_write_char('\x2e');
+ } else {
+ for (i = 0; i < co->height; i++) {
+ newtGotorc(i + co->top, co->left);
+ SLsmg_write_char('\x61');
+ }
+ }
+
+ SLsmg_set_char_set(0);
+
+ sbDrawThumb(co, 1);
+}
+
+static void sbDrawThumb(newtComponent co, int isOn) {
+ struct scrollbar * sb = co->data;
+ char ch = isOn ? '#' : '\x61';
+
+ if (!co->isMapped) return;
+
+ newtGotorc(sb->curr + co->top, co->left);
+ SLsmg_set_char_set(1);
+
+ /*if (isOn)
+ SLsmg_set_color(sb->csThumb);
+ else*/
+ SLsmg_set_color(sb->cs);
+
+ SLsmg_write_char(ch);
+ SLsmg_set_char_set(0);
+}
+
+static void sbDestroy(newtComponent co) {
+ struct scrollbar * sb = co->data;
+
+ free(sb);
+ free(co);
+}
diff --git a/mdk-stage1/newt/textbox.c b/mdk-stage1/newt/textbox.c
new file mode 100644
index 000000000..272c9b675
--- /dev/null
+++ b/mdk-stage1/newt/textbox.c
@@ -0,0 +1,409 @@
+#include <ctype.h>
+#include <slang.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "newt.h"
+#include "newt_pr.h"
+
+struct textbox {
+ char ** lines;
+ int numLines;
+ int linesAlloced;
+ int doWrap;
+ newtComponent sb;
+ int topLine;
+ int textWidth;
+};
+
+static char * expandTabs(const char * text);
+static void textboxDraw(newtComponent co);
+static void addLine(newtComponent co, const char * s, int len);
+static void doReflow(const char * text, char ** resultPtr, int width,
+ int * badness, int * heightPtr);
+static struct eventResult textboxEvent(newtComponent c,
+ struct event ev);
+static void textboxDestroy(newtComponent co);
+static void textboxPlace(newtComponent co, int newLeft, int newTop);
+static void textboxMapped(newtComponent co, int isMapped);
+
+static struct componentOps textboxOps = {
+ textboxDraw,
+ textboxEvent,
+ textboxDestroy,
+ textboxPlace,
+ textboxMapped,
+} ;
+
+static void textboxMapped(newtComponent co, int isMapped) {
+ struct textbox * tb = co->data;
+
+ co->isMapped = isMapped;
+ if (tb->sb)
+ tb->sb->ops->mapped(tb->sb, isMapped);
+}
+
+static void textboxPlace(newtComponent co, int newLeft, int newTop) {
+ struct textbox * tb = co->data;
+
+ co->top = newTop;
+ co->left = newLeft;
+
+ if (tb->sb)
+ tb->sb->ops->place(tb->sb, co->left + co->width - 1, co->top);
+}
+
+void newtTextboxSetHeight(newtComponent co, int height) {
+ co->height = height;
+}
+
+int newtTextboxGetNumLines(newtComponent co) {
+ struct textbox * tb = co->data;
+
+ return (tb->numLines);
+}
+
+newtComponent newtTextboxReflowed(int left, int top, char * text, int width,
+ int flexDown, int flexUp, int flags) {
+ newtComponent co;
+ char * reflowedText;
+ int actWidth, actHeight;
+
+ reflowedText = newtReflowText(text, width, flexDown, flexUp,
+ &actWidth, &actHeight);
+
+ co = newtTextbox(left, top, actWidth, actHeight, NEWT_FLAG_WRAP);
+ newtTextboxSetText(co, reflowedText);
+ free(reflowedText);
+
+ return co;
+}
+
+newtComponent newtTextbox(int left, int top, int width, int height, int flags) {
+ newtComponent co;
+ struct textbox * tb;
+
+ co = malloc(sizeof(*co));
+ tb = malloc(sizeof(*tb));
+ co->data = tb;
+
+ co->ops = &textboxOps;
+
+ co->height = height;
+ co->top = top;
+ co->left = left;
+ co->takesFocus = 0;
+ co->width = width;
+
+ tb->doWrap = flags & NEWT_FLAG_WRAP;
+ tb->numLines = 0;
+ tb->linesAlloced = 0;
+ tb->lines = NULL;
+ tb->topLine = 0;
+ tb->textWidth = width;
+
+ if (flags & NEWT_FLAG_SCROLL) {
+ co->width += 2;
+ tb->sb = newtVerticalScrollbar(co->left + co->width - 1, co->top,
+ co->height, COLORSET_TEXTBOX, COLORSET_TEXTBOX);
+ } else {
+ tb->sb = NULL;
+ }
+
+ return co;
+}
+
+static char * expandTabs(const char * text) {
+ int bufAlloced = strlen(text) + 40;
+ char * buf, * dest;
+ const char * src;
+ int bufUsed = 0;
+ int linePos = 0;
+ int i;
+
+ buf = malloc(bufAlloced + 1);
+ for (src = text, dest = buf; *src; src++) {
+ if ((bufUsed + 10) > bufAlloced) {
+ bufAlloced += strlen(text) / 2;
+ buf = realloc(buf, bufAlloced + 1);
+ dest = buf + bufUsed;
+ }
+ if (*src == '\t') {
+ i = 8 - (linePos & 8);
+ memset(dest, ' ', i);
+ dest += i, bufUsed += i, linePos += i;
+ } else {
+ if (*src == '\n')
+ linePos = 0;
+ else
+ linePos++;
+
+ *dest++ = *src;
+ bufUsed++;
+ }
+ }
+
+ *dest = '\0';
+ return buf;
+}
+
+#define iseuckanji(c) (0xa1 <= (unsigned char)(c&0xff) && (unsigned char)(c&0xff) <= 0xfe)
+
+static void doReflow(const char * text, char ** resultPtr, int width,
+ int * badness, int * heightPtr) {
+ char * result = NULL;
+ const char * chptr, * end;
+ int i;
+ int howbad = 0;
+ int height = 0;
+ int kanji = 0;
+
+ if (resultPtr) {
+ /* XXX I think this will work */
+ result = malloc(strlen(text) + (strlen(text) / width) + 50);
+ *result = '\0';
+ }
+
+ while (*text) {
+ kanji = 0;
+ end = strchr(text, '\n');
+ if (!end)
+ end = text + strlen(text);
+
+ while (*text && text < end) {
+ if (end - text < width) {
+ if (result) {
+ strncat(result, text, end - text + 1);
+ strcat(result, "\n");
+ height++;
+ }
+
+ if (end - text < (width / 2))
+ howbad += ((width / 2) - (end - text)) / 2;
+ text = end;
+ if (*text) text++;
+ } else {
+ chptr = text;
+ kanji = 0;
+ for ( i = 0; i < width - 1; i++ ) {
+ if ( !iseuckanji(*chptr)) {
+ kanji = 0;
+ } else if ( kanji == 1 ) {
+ kanji = 2;
+ } else {
+ kanji = 1;
+ }
+ chptr++;
+ }
+ if (kanji == 0) {
+ while (chptr > text && !isspace(*chptr)) chptr--;
+ while (chptr > text && isspace(*chptr)) chptr--;
+ chptr++;
+ }
+
+ if (chptr-text == 1 && !isspace(*chptr))
+ chptr = text + width - 1;
+
+ if (chptr > text)
+ howbad += width - (chptr - text) + 1;
+ if (result) {
+ if (kanji == 1) {
+ strncat(result, text, chptr - text + 1);
+ chptr++;
+ kanji = 0;
+ } else {
+ strncat(result, text, chptr - text + 1);
+ }
+ strcat(result, "\n");
+ height++;
+ }
+
+ if (isspace(*chptr))
+ text = chptr + 1;
+ else
+ text = chptr;
+ while (isspace(*text)) text++;
+ }
+ }
+ }
+
+// if (result) printf("result: %s\n", result);
+
+ if (badness) *badness = howbad;
+ if (resultPtr) *resultPtr = result;
+ if (heightPtr) *heightPtr = height;
+}
+
+char * newtReflowText(char * text, int width, int flexDown, int flexUp,
+ int * actualWidth, int * actualHeight) {
+ int min, max;
+ int i;
+ char * result;
+ int minbad, minbadwidth, howbad;
+ char * expandedText;
+
+ expandedText = expandTabs(text);
+
+ if (flexDown || flexUp) {
+ min = width - flexDown;
+ max = width + flexUp;
+
+ minbad = -1;
+ minbadwidth = width;
+
+ for (i = min; i <= max; i++) {
+ doReflow(expandedText, NULL, i, &howbad, NULL);
+
+ if (minbad == -1 || howbad < minbad) {
+ minbad = howbad;
+ minbadwidth = i;
+ }
+ }
+
+ width = minbadwidth;
+ }
+
+ doReflow(expandedText, &result, width, NULL, actualHeight);
+ free(expandedText);
+ if (actualWidth) *actualWidth = width;
+ return result;
+}
+
+void newtTextboxSetText(newtComponent co, const char * text) {
+ const char * start, * end;
+ struct textbox * tb = co->data;
+ char * reflowed, * expanded;
+ int badness, height;
+
+ if (tb->lines) {
+ free(tb->lines);
+ tb->linesAlloced = tb->numLines = 0;
+ }
+
+ expanded = expandTabs(text);
+
+ if (tb->doWrap) {
+ doReflow(expanded, &reflowed, tb->textWidth, &badness, &height);
+ free(expanded);
+ expanded = reflowed;
+ }
+
+ for (start = expanded; *start; start++)
+ if (*start == '\n') tb->linesAlloced++;
+
+ /* This ++ leaves room for an ending line w/o a \n */
+ tb->linesAlloced++;
+ tb->lines = malloc(sizeof(char *) * tb->linesAlloced);
+
+ start = expanded;
+ while ((end = strchr(start, '\n'))) {
+ addLine(co, start, end - start);
+ start = end + 1;
+ }
+
+ if (*start)
+ addLine(co, start, strlen(start));
+
+ free(expanded);
+}
+
+/* This assumes the buffer is allocated properly! */
+static void addLine(newtComponent co, const char * s, int len) {
+ struct textbox * tb = co->data;
+
+ if (len > tb->textWidth) len = tb->textWidth;
+
+ tb->lines[tb->numLines] = malloc(tb->textWidth + 1);
+ memset(tb->lines[tb->numLines], ' ', tb->textWidth);
+ memcpy(tb->lines[tb->numLines], s, len);
+ tb->lines[tb->numLines++][tb->textWidth] = '\0';
+}
+
+static void textboxDraw(newtComponent c) {
+ int i;
+ struct textbox * tb = c->data;
+ int size;
+
+ if (tb->sb) {
+ size = tb->numLines - c->height;
+ newtScrollbarSet(tb->sb, tb->topLine, size ? size : 0);
+ tb->sb->ops->draw(tb->sb);
+ }
+
+ SLsmg_set_color(NEWT_COLORSET_TEXTBOX);
+
+ for (i = 0; (i + tb->topLine) < tb->numLines && i < c->height; i++) {
+ newtGotorc(c->top + i, c->left);
+ SLsmg_write_string(tb->lines[i + tb->topLine]);
+ }
+}
+
+static struct eventResult textboxEvent(newtComponent co,
+ struct event ev) {
+ struct textbox * tb = co->data;
+ struct eventResult er;
+
+ er.result = ER_IGNORED;
+
+ if (ev.when == EV_EARLY && ev.event == EV_KEYPRESS && tb->sb) {
+ switch (ev.u.key) {
+ case NEWT_KEY_UP:
+ if (tb->topLine) tb->topLine--;
+ textboxDraw(co);
+ er.result = ER_SWALLOWED;
+ break;
+
+ case NEWT_KEY_DOWN:
+ if (tb->topLine < (tb->numLines - co->height)) tb->topLine++;
+ textboxDraw(co);
+ er.result = ER_SWALLOWED;
+ break;
+
+ case NEWT_KEY_PGDN:
+ tb->topLine += co->height;
+ if (tb->topLine > (tb->numLines - co->height)) {
+ tb->topLine = tb->numLines - co->height;
+ if (tb->topLine < 0) tb->topLine = 0;
+ }
+ textboxDraw(co);
+ er.result = ER_SWALLOWED;
+ break;
+
+ case NEWT_KEY_PGUP:
+ tb->topLine -= co->height;
+ if (tb->topLine < 0) tb->topLine = 0;
+ textboxDraw(co);
+ er.result = ER_SWALLOWED;
+ break;
+ }
+ }
+ if (ev.when == EV_EARLY && ev.event == EV_MOUSE && tb->sb) {
+ /* Top scroll arrow */
+ if (ev.u.mouse.x == co->width && ev.u.mouse.y == co->top) {
+ if (tb->topLine) tb->topLine--;
+ textboxDraw(co);
+
+ er.result = ER_SWALLOWED;
+ }
+ /* Bottom scroll arrow */
+ if (ev.u.mouse.x == co->width &&
+ ev.u.mouse.y == co->top + co->height - 1) {
+ if (tb->topLine < (tb->numLines - co->height)) tb->topLine++;
+ textboxDraw(co);
+
+ er.result = ER_SWALLOWED;
+ }
+ }
+ return er;
+}
+
+static void textboxDestroy(newtComponent co) {
+ int i;
+ struct textbox * tb = co->data;
+
+ for (i = 0; i < tb->numLines; i++)
+ free(tb->lines[i]);
+ free(tb->lines);
+ free(tb);
+ free(co);
+}
diff --git a/mdk-stage1/newt/windows.c b/mdk-stage1/newt/windows.c
new file mode 100644
index 000000000..792d3ed76
--- /dev/null
+++ b/mdk-stage1/newt/windows.c
@@ -0,0 +1,275 @@
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "errno.h"
+#include "newt.h"
+
+static void * newtvwindow(char * title, char * button1, char * button2,
+ char * button3, char * message, va_list args) {
+ newtComponent b1, b2 = NULL, b3 = NULL, t, f, answer;
+ char * buf = NULL;
+ int size = 0;
+ int i = 0;
+ int scroll = 0;
+ int width, height;
+ char * flowedText;
+ newtGrid grid, buttonGrid;
+
+ do {
+ size += 1000;
+ if (buf) free(buf);
+ buf = malloc(size);
+ i = vsnprintf(buf, size, message, args);
+ } while (i >= size || i == -1);
+
+ flowedText = newtReflowText(buf, 35, 5, 5, &width, &height);
+ if (height > 6) {
+ free(flowedText);
+ flowedText = newtReflowText(buf, 60, 5, 5, &width, &height);
+ }
+ free(buf);
+
+ if (height > 12) {
+ height = 12;
+ scroll = NEWT_FLAG_SCROLL;
+ }
+ t = newtTextbox(-1, -1, width, height, NEWT_TEXTBOX_WRAP | scroll);
+ newtTextboxSetText(t, flowedText);
+ free(flowedText);
+
+ if (button3) {
+ buttonGrid = newtButtonBar(button1, &b1, button2, &b2,
+ button3, &b3, NULL);
+ } else if (button2) {
+ buttonGrid = newtButtonBar(button1, &b1, button2, &b2, NULL);
+ } else {
+ buttonGrid = newtButtonBar(button1, &b1, NULL);
+ }
+
+ newtGridSetField(buttonGrid, 0, 0, NEWT_GRID_COMPONENT, b1,
+ 0, 0, button2 ? 1 : 0, 0, 0, 0);
+
+ grid = newtCreateGrid(1, 2);
+ newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, t, 0, 0, 0, 0, 0, 0);
+ newtGridSetField(grid, 0, 1, NEWT_GRID_SUBGRID, buttonGrid,
+ 0, 1, 0, 0, 0, NEWT_GRID_FLAG_GROWX);
+ newtGridWrappedWindow(grid, title);
+
+ f = newtForm(NULL, NULL, 0);
+ newtFormAddComponents(f, t, b1, NULL);
+
+ if (button2)
+ newtFormAddComponent(f, b2);
+ if (button3)
+ newtFormAddComponent(f, b3);
+
+ answer = newtRunForm(f);
+ newtGridFree(grid, 1);
+
+ newtFormDestroy(f);
+ newtPopWindow();
+
+ if (answer == f)
+ return NULL;
+ else if (answer == b1)
+ return button1;
+ else if (answer == b2)
+ return button2;
+
+ return button3;
+}
+
+int newtWinChoice(char * title, char * button1, char * button2,
+ char * message, ...) {
+ va_list args;
+ void * rc;
+
+ va_start(args, message);
+ rc = newtvwindow(title, button1, button2, NULL, message, args);
+ va_end(args);
+
+ if (rc == button1)
+ return 1;
+ else if (rc == button2)
+ return 2;
+
+ return 0;
+}
+
+void newtWinMessage(char * title, char * buttonText, char * text, ...) {
+ va_list args;
+
+ va_start(args, text);
+ newtvwindow(title, buttonText, NULL, NULL, text, args);
+ va_end(args);
+}
+
+void newtWinMessagev(char * title, char * buttonText, char * text,
+ va_list argv) {
+ newtvwindow(title, buttonText, NULL, NULL, text, argv);
+}
+
+int newtWinTernary(char * title, char * button1, char * button2,
+ char * button3, char * message, ...) {
+ va_list args;
+ void * rc;
+
+ va_start(args, message);
+ rc = newtvwindow(title, button1, button2, button3, message, args);
+ va_end(args);
+
+ if (rc == button1)
+ return 1;
+ else if (rc == button2)
+ return 2;
+ else if (rc == button3)
+ return 3;
+
+ return 0;
+}
+
+/* only supports up to 50 buttons -- shucks! */
+int newtWinMenu(char * title, char * text, int suggestedWidth, int flexDown,
+ int flexUp, int maxListHeight, char ** items, int * listItem,
+ char * button1, ...) {
+ newtComponent textbox, listbox, result, form;
+ va_list args;
+ newtComponent buttons[50];
+ newtGrid grid, buttonBar;
+ int numButtons;
+ int i, rc;
+ int needScroll;
+ char * buttonName;
+
+ textbox = newtTextboxReflowed(-1, -1, text, suggestedWidth, flexDown,
+ flexUp, 0);
+
+ for (i = 0; items[i]; i++) ;
+ if (i < maxListHeight) maxListHeight = i;
+ needScroll = i > maxListHeight;
+
+ listbox = newtListbox(-1, -1, maxListHeight,
+ (needScroll ? NEWT_FLAG_SCROLL : 0) | NEWT_FLAG_RETURNEXIT);
+ for (i = 0; items[i]; i++) {
+ newtListboxAddEntry(listbox, items[i], (void *) i);
+ }
+
+ newtListboxSetCurrent(listbox, *listItem);
+
+ buttonName = button1, numButtons = 0;
+ va_start(args, button1);
+ while (buttonName) {
+ buttons[numButtons] = newtButton(-1, -1, buttonName);
+ numButtons++;
+ buttonName = va_arg(args, char *);
+ }
+
+ va_end(args);
+
+ buttonBar = newtCreateGrid(numButtons, 1);
+ for (i = 0; i < numButtons; i++) {
+ newtGridSetField(buttonBar, i, 0, NEWT_GRID_COMPONENT,
+ buttons[i],
+ i ? 1 : 0, 0, 0, 0, 0, 0);
+ }
+
+ grid = newtGridSimpleWindow(textbox, listbox, buttonBar);
+ newtGridWrappedWindow(grid, title);
+
+ form = newtForm(NULL, 0, 0);
+ newtGridAddComponentsToForm(grid, form, 1);
+ newtGridFree(grid, 1);
+
+ result = newtRunForm(form);
+
+ *listItem = ((long) newtListboxGetCurrent(listbox));
+
+ for (rc = 0; result != buttons[rc] && rc < numButtons; rc++);
+ if (rc == numButtons)
+ rc = 0; /* F12 or return-on-exit (which are the same for us) */
+ else
+ rc++;
+
+ newtFormDestroy(form);
+ newtPopWindow();
+
+ return rc;
+}
+
+/* only supports up to 50 buttons and entries -- shucks! */
+int newtWinEntries(char * title, char * text, int suggestedWidth, int flexDown,
+ int flexUp, int dataWidth,
+ struct newtWinEntry * items, char * button1, ...) {
+ newtComponent buttons[50], result, form, textw;
+ newtGrid grid, buttonBar, subgrid;
+ int numItems;
+ int rc, i;
+ int numButtons;
+ char * buttonName;
+ va_list args;
+
+ textw = newtTextboxReflowed(-1, -1, text, suggestedWidth, flexDown,
+ flexUp, 0);
+
+ for (numItems = 0; items[numItems].text; numItems++);
+
+ buttonName = button1, numButtons = 0;
+ va_start(args, button1);
+ while (buttonName) {
+ buttons[numButtons] = newtButton(-1, -1, buttonName);
+ numButtons++;
+ buttonName = va_arg(args, char *);
+ }
+
+ va_end(args);
+
+ buttonBar = newtCreateGrid(numButtons, 1);
+ for (i = 0; i < numButtons; i++) {
+ newtGridSetField(buttonBar, i, 0, NEWT_GRID_COMPONENT,
+ buttons[i],
+ i ? 1 : 0, 0, 0, 0, 0, 0);
+ }
+
+ subgrid = newtCreateGrid(2, numItems);
+ for (i = 0; i < numItems; i++) {
+ newtGridSetField(subgrid, 0, i, NEWT_GRID_COMPONENT,
+ newtLabel(-1, -1, items[i].text),
+ 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
+ newtGridSetField(subgrid, 1, i, NEWT_GRID_COMPONENT,
+ newtEntry(-1, -1, items[i].value ?
+ *items[i].value : NULL, dataWidth,
+ items[i].value, items[i].flags),
+ 1, 0, 0, 0, 0, 0);
+ }
+
+ grid = newtCreateGrid(1, 3);
+ form = newtForm(NULL, 0, 0);
+ newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, textw,
+ 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
+ newtGridSetField(grid, 0, 1, NEWT_GRID_SUBGRID, subgrid,
+ 0, 1, 0, 0, 0, 0);
+ newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, buttonBar,
+ 0, 1, 0, 0, 0, NEWT_GRID_FLAG_GROWX);
+ newtGridAddComponentsToForm(grid, form, 1);
+ newtGridWrappedWindow(grid, title);
+ newtGridFree(grid, 1);
+
+ result = newtRunForm(form);
+
+ for (rc = 0; rc < numItems; rc++)
+ *items[rc].value = strdup(*items[rc].value);
+
+ for (rc = 0; result != buttons[rc] && rc < numButtons; rc++);
+ if (rc == numButtons)
+ rc = 0; /* F12 */
+ else
+ rc++;
+
+ newtFormDestroy(form);
+ newtPopWindow();
+
+ return rc;
+}