From: ewt Date: Wed, 17 Apr 1996 00:42:02 +0000 (+0000) Subject: Initial revision X-Git-Tag: 0-1~18 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=20476098c5b4f21ccb84faf0df4fc598c6ac2ef7;p=thirdparty%2Fnewt.git Initial revision --- diff --git a/textbox.c b/textbox.c new file mode 100644 index 0000000..504ebbe --- /dev/null +++ b/textbox.c @@ -0,0 +1,188 @@ +#include +#include +#include + +#include "newt.h" +#include "newt_pr.h" + +struct textbox { + char ** lines; + int numLines; + int linesAlloced; + int doWrap; + newtComponent sb; + int topLine; +}; + +static void addLine(newtComponent co, const char * s, int len); +static void textboxDraw(newtComponent co); +static void addShortLine(newtComponent co, const char * s, int len); +static struct eventResult textboxEvent(struct newtComponent * c, + struct event ev); +static void textboxDestroy(newtComponent co); + +static struct componentOps textboxOps = { + textboxDraw, + textboxEvent, + textboxDestroy, +} ; + +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; + + tb->doWrap = flags & NEWT_TEXTBOX_WRAP; + tb->numLines = 0; + tb->linesAlloced = 0; + tb->lines = NULL; + tb->topLine = 0; + + if (flags & NEWT_TEXTBOX_SCROLL) { + co->width = width - 2; + tb->sb = newtVerticalScrollbar(co->left + co->width + 1, co->top, + co->height, COLORSET_TEXTBOX, COLORSET_TEXTBOX); + } else { + co->width = width; + tb->sb = NULL; + } + + return co; +} + +void newtTextboxSetText(newtComponent co, const char * text) { + const char * start, * end; + struct textbox * tb = co->data; + + if (tb->lines) { + free(tb->lines); + tb->numLines = 0; + } + + tb->linesAlloced = 10; + tb->lines = malloc(sizeof(char *) * 10); + + start = text; + while ((end = strchr(start, '\n'))) { + addLine(co, start, end - start); + start = end + 1; + } + + if (*start) + addLine(co, start, -1); +} + +static void addLine(newtComponent co, const char * s, int origlen) { + const char * start, * end; + int len; + struct textbox * tb = co->data; + + if (origlen < 0) origlen = strlen(s); + len = origlen; + + if (!tb->doWrap || len <= co->width) { + addShortLine(co, s, len); + } else { + /* word wrap */ + + start = s; + while (len > co->width) { + end = start + co->width - 1; + while (end > start && !isspace(*end)) end--; + + if (end == start) + end = start + co->width - 1; + + addShortLine(co, start, end - start); + + start = end + 1; + while (isspace(*start) && *start) start++; + + len = origlen - (start - s); + } + + if (*start) + addShortLine(co, start, len); + } +} + +static void addShortLine(newtComponent co, const char * s, int len) { + struct textbox * tb = co->data; + + if (tb->linesAlloced == tb->numLines) { + tb->linesAlloced += 10; + tb->lines = realloc(tb->lines, (sizeof(char *) * tb->linesAlloced)); + } + + if (len > co->width) len = co->width; + + tb->lines[tb->numLines] = malloc(co->width + 1); + strncpy(tb->lines[tb->numLines], s, len); + + while (len < co->width) tb->lines[tb->numLines][len++] = ' '; + tb->lines[tb->numLines++][len] = '\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); + } + + 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(struct 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; + } + } + + 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); +}