From: ewt Date: Tue, 18 Mar 1997 15:09:00 +0000 (+0000) Subject: Initial revision X-Git-Tag: v0-9~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9be6d60e8fe18c3874e6d23220669da318504d6c;p=thirdparty%2Fnewt.git Initial revision --- diff --git a/whiptail.c b/whiptail.c new file mode 100644 index 0000000..6aba3e1 --- /dev/null +++ b/whiptail.c @@ -0,0 +1,578 @@ +/* a reasonable dialog */ + +#include +#include +#include +#include +#include + +#include "newt.h" +#include "popt.h" + +enum mode { MODE_NONE, MODE_MSGBOX, MODE_YESNO, MODE_CHECKLIST, MODE_INPUTBOX, + MODE_RADIOLIST, MODE_MENU, MODE_GAUGE }; + +#define OPT_MSGBOX 1000 +#define OPT_CHECKLIST 1001 +#define OPT_YESNO 1002 +#define OPT_INPUTBOX 1003 +#define OPT_FULLBUTTONS 1004 +#define OPT_MENU 1005 +#define OPT_RADIOLIST 1006 +#define OPT_GAUGE 1007 + +#define MSGBOX_MSG 0 +#define MSGBOX_YESNO 1 + +#define FLAG_NOITEM (1 << 0) +#define FLAG_NOCANCEL (1 << 1) +#define FLAG_SEPARATE_OUTPUT (1 << 2) +#define FLAG_SCROLL_TEXT (1 << 3) + +static void usage(void) { + fprintf(stderr, "ndialog: bad parametrs (see man dialog(1) for details)\n"); + exit(1); +} + +/* globals -- ick */ +int buttonHeight = 1; +newtComponent (*makeButton)(int left, int right, char * text) = + newtCompactButton; + +void addButtons(int height, int width, newtComponent form, + newtComponent * okay, newtComponent * cancel, int flags) { + if (flags & FLAG_NOCANCEL) { + *okay = makeButton((width - 8) / 2, height - buttonHeight - 1, "Ok"); + *cancel = NULL; + newtFormAddComponent(form, *okay); + } else { + *okay = makeButton((width - 18) / 3, height - buttonHeight - 1, "Ok"); + *cancel = makeButton(((width - 18) / 3) * 2 + 9, + height - buttonHeight - 1, "Cancel"); + newtFormAddComponents(form, *okay, *cancel, NULL); + } +} + +newtComponent textbox(int maxHeight, int width, char * text, int flags, + int * height) { + newtComponent tb; + int sFlag = (flags & FLAG_SCROLL_TEXT) ? NEWT_TEXTBOX_SCROLL : 0; + int i; + char * buf, * src, * dst; + + dst = buf = alloca(strlen(text) + 1); + src = text; + while (*src) { + if (*src == '\\' && *(src + 1) == 'n') { + src += 2; + *dst++ = '\n'; + } else + *dst++ = *src++; + } + *dst++ = '\0'; + + tb = newtTextbox(1, 0, width, maxHeight, NEWT_TEXTBOX_WRAP | sFlag); + newtTextboxSetText(tb, buf); + + i = newtTextboxGetNumLines(tb); + if (i < maxHeight) { + newtTextboxSetHeight(tb, i); + maxHeight = i; + } + + *height = maxHeight; + + return tb; +} + + +int gauge(char * text, int height, int width, poptContext optCon, int fd, + int flags) { + newtComponent form, scale, tb; + int rc; + int top; + char * arg, * end; + int val; + FILE * f = fdopen(fd, "r"); + char buf[3000]; + char buf3[50]; + int i; + + setlinebuf(f); + + if (!(arg = poptGetArg(optCon))) usage(); + val = strtoul(arg, &end, 10); + if (*end) usage(); + + tb = textbox(height - 3, width - 2, text, flags, &top); + + form = newtForm(NULL, NULL, 0); + + scale = newtScale(2, height - 2, width - 4, 100); + newtScaleSet(scale, val); + + newtFormAddComponents(form, tb, scale, NULL); + + newtDrawForm(form); + newtRefresh(); + + while (fgets(buf, sizeof(buf) - 1, f)) { + buf[strlen(buf) - 1] = '\0'; + + if (!strcmp(buf, "XXX")) { + fgets(buf3, sizeof(buf3) - 1, f); + buf3[strlen(buf3) - 1] = '\0'; + arg = buf3; + + i = 0; + while (fgets(buf + i, sizeof(buf) - 1 - i, f)) { + buf[strlen(buf) - 1] = '\0'; + if (!strcmp(buf + i, "XXX")) { + *(buf + i) = '\0'; + break; + } + i = strlen(buf); + } + + newtTextboxSetText(tb, buf); + } else { + arg = buf; + } + + val = strtoul(buf, &end, 10); + if (!*end) { + newtScaleSet(scale, val); + newtDrawForm(form); + newtRefresh(); + } + } + + return rc; +} + +int inputBox(char * text, int height, int width, poptContext optCon, + int flags) { + newtComponent form, entry, okay, cancel, answer, tb; + char * val; + int rc; + int top; + + val = poptGetArg(optCon); + tb = textbox(height - 3 - buttonHeight, width - 2, + text, flags, &top); + + form = newtForm(NULL, NULL, 0); + entry = newtEntry(1, top + 1, val, width - 2, &val, + NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT); + + newtFormAddComponents(form, tb, entry, NULL); + + addButtons(height, width, form, &okay, &cancel, flags); + + answer = newtRunForm(form); + if (answer == cancel) + rc = 1; + + fprintf(stderr, "%s", val); + + return rc; +} + +int listBox(char * text, int height, int width, poptContext optCon, + int flags) { + newtComponent form, okay, tb, answer, listBox; + newtComponent cancel = NULL; + char * arg, * end; + int listHeight; + int numItems = 0; + int allocedItems = 5; + int i, top; + int rc = 0; + char buf[80], format[20]; + int maxTagWidth = 0; + int maxTextWidth = 0; + int noScrollFlag; + struct { + char * text; + char * tag; + } * itemInfo = malloc(allocedItems * sizeof(*itemInfo)); + + if (!(arg = poptGetArg(optCon))) usage(); + listHeight = strtoul(arg, &end, 10); + if (*end) usage(); + + while ((arg = poptGetArg(optCon))) { + if (allocedItems == numItems) { + allocedItems += 5; + itemInfo = realloc(itemInfo, sizeof(*itemInfo) * allocedItems); + } + + itemInfo[numItems].tag = arg; + if (!(arg = poptGetArg(optCon))) usage(); + + if (!(flags & FLAG_NOITEM)) { + itemInfo[numItems].text = arg; + } else + itemInfo[numItems].text = ""; + + if (strlen(itemInfo[numItems].text) > maxTextWidth) + maxTextWidth = strlen(itemInfo[numItems].text); + if (strlen(itemInfo[numItems].tag) > maxTagWidth) + maxTagWidth = strlen(itemInfo[numItems].tag); + + numItems++; + } + + form = newtForm(NULL, NULL, 0); + + tb = textbox(height - 4 - buttonHeight - listHeight, width - 2, + text, flags, &top); + + if (listHeight >= numItems) { + noScrollFlag = NEWT_FLAG_NOSCROLL; + i = 0; + } else { + i = 2; + } + + listBox = newtListbox(3 + ((width - 10 - maxTagWidth - maxTextWidth - i) + / 2), + top + 1, listHeight, + NEWT_FLAG_RETURNEXIT | noScrollFlag); + + sprintf(format, "%%-%ds %%s", maxTagWidth); + for (i = 0; i < numItems; i++) { + sprintf(buf, format, itemInfo[i].tag, itemInfo[i].text); + newtListboxAddEntry(listBox, buf, (void *) i); + } + + newtFormAddComponents(form, tb, listBox, NULL); + + addButtons(height, width, form, &okay, &cancel, flags); + + answer = newtRunForm(form); + if (answer == cancel) + rc = 1; + + i = (int) newtListboxGetCurrent(listBox); + fprintf(stderr, "%s", itemInfo[i].tag); + + return rc; +} + +int checkList(char * text, int height, int width, poptContext optCon, + int useRadio, int flags) { + newtComponent form, okay, tb, subform, answer; + newtComponent sb = NULL, cancel = NULL; + char * arg, * end; + int listHeight; + int numBoxes = 0; + int allocedBoxes = 5; + int i; + int rc = 0; + char buf[80], format[20]; + int maxWidth = 0; + int needSpace = 0; + int top; + struct { + char * text; + char * tag; + newtComponent comp; + } * cbInfo = malloc(allocedBoxes * sizeof(*cbInfo)); + char * cbStates = malloc(allocedBoxes * sizeof(cbStates)); + + if (!(arg = poptGetArg(optCon))) usage(); + listHeight = strtoul(arg, &end, 10); + if (*end) usage(); + + while ((arg = poptGetArg(optCon))) { + if (allocedBoxes == numBoxes) { + allocedBoxes += 5; + cbInfo = realloc(cbInfo, sizeof(*cbInfo) * allocedBoxes); + cbStates = realloc(cbStates, sizeof(*cbStates) * allocedBoxes); + } + + cbInfo[numBoxes].tag = arg; + if (!(arg = poptGetArg(optCon))) usage(); + + if (!(flags & FLAG_NOITEM)) { + cbInfo[numBoxes].text = arg; + if (!(arg = poptGetArg(optCon))) usage(); + } else + cbInfo[numBoxes].text = ""; + + if (!strcmp(arg, "1") || !strcasecmp(arg, "on") || + !strcasecmp(arg, "yes")) + cbStates[numBoxes] = '*'; + else + cbStates[numBoxes] = ' '; + + if (strlen(cbInfo[numBoxes].tag) > maxWidth) + maxWidth = strlen(cbInfo[numBoxes].tag); + + numBoxes++; + } + + form = newtForm(NULL, NULL, 0); + + if (listHeight < numBoxes) { + sb = newtVerticalScrollbar(width - 4, + height - 2 - buttonHeight - listHeight, + listHeight, NEWT_COLORSET_CHECKBOX, + NEWT_COLORSET_ACTCHECKBOX); + newtFormAddComponent(form, sb); + } + subform = newtForm(sb, NULL, 0); + newtFormSetBackground(subform, NEWT_COLORSET_CHECKBOX); + + tb = textbox(height - 4 - buttonHeight - listHeight, width - 2, + text, flags, &top); + + sprintf(format, "%%-%ds %%s", maxWidth); + for (i = 0; i < numBoxes; i++) { + sprintf(buf, format, cbInfo[i].tag, cbInfo[i].text); + + if (useRadio) + cbInfo[i].comp = newtRadiobutton(4, top + 1 + i, buf, + cbStates[i] != ' ', + i ? cbInfo[i - 1].comp : NULL); + else + cbInfo[i].comp = newtCheckbox(4, top + 1 + i, buf, + cbStates[i], NULL, cbStates + i); + + newtFormAddComponent(subform, cbInfo[i].comp); + } + + newtFormSetHeight(subform, listHeight); + newtFormSetWidth(subform, width - 10); + + newtFormAddComponents(form, tb, subform, NULL); + + addButtons(height, width, form, &okay, &cancel, flags); + + answer = newtRunForm(form); + if (answer == cancel) + rc = 1; + + if (useRadio) { + answer = newtRadioGetCurrent(cbInfo[0].comp); + for (i = 0; i < numBoxes; i++) + if (cbInfo[i].comp == answer) { + fprintf(stderr, "%s", cbInfo[i].tag); + break; + } + } else { + for (i = 0; i < numBoxes; i++) { + /* this should do proper quoting */ + if (cbStates[i] != ' ') { + if (!(flags & FLAG_SEPARATE_OUTPUT)) { + if (needSpace) putc(' ', stderr); + fprintf(stderr, "\"%s\"", cbInfo[i].tag); + needSpace = 1; + } else { + fprintf(stderr, "%s\n", cbInfo[i].tag); + } + } + } + } + + return rc; +} + +int messageBox(char * text, int height, int width, int type, int flags) { + newtComponent form, yes, tb, answer; + newtComponent no = NULL; + int tFlag = (flags & FLAG_SCROLL_TEXT) ? NEWT_TEXTBOX_SCROLL : 0; + + form = newtForm(NULL, NULL, 0); + + tb = newtTextbox(1, 1, width - 2, height - 3 - buttonHeight, + NEWT_TEXTBOX_WRAP | tFlag); + newtTextboxSetText(tb, text); + + newtFormAddComponent(form, tb); + + if (type == MSGBOX_MSG) { + yes = makeButton((width - 8) / 2, height - 1 - buttonHeight, "Ok"); + newtFormAddComponent(form, yes); + } else { + yes = makeButton((width - 16) / 3, height - 1 - buttonHeight, "Yes"); + no = makeButton(((width - 16) / 3) * 2 + 9, height - 1 - buttonHeight, + "No"); + newtFormAddComponents(form, yes, no, NULL); + } + + answer = newtRunForm(form); + + if (answer == no) + return 1; + + return 0; +} + +int main(int argc, char ** argv) { + enum mode mode = MODE_NONE; + poptContext optCon; + int arg; + char * optArg; + char * text; + char * nextArg; + char * end; + int height; + int width; + int fd; + int noCancel = 0; + int noItem = 0; + int clear = 0; + int scrollText = 0; + int rc = 1; + int flags = 0; + int separateOutput = 0; + char * title = NULL; + char * backtitle = NULL; + struct poptOption optionsTable[] = { + { "backtitle", '\0', POPT_ARG_STRING, &backtitle, 0 }, + { "checklist", '\0', 0, 0, OPT_CHECKLIST }, + { "clear", '\0', 0, &clear, 0 }, + { "inputbox", '\0', 0, 0, OPT_INPUTBOX }, + { "fb", '\0', 0, 0, OPT_FULLBUTTONS }, + { "fullbuttons", '\0', 0, 0, OPT_FULLBUTTONS }, + { "gauge", '\0', 0, 0, OPT_GAUGE }, + { "menu", '\0', 0, 0, OPT_MENU }, + { "msgbox", '\0', 0, 0, OPT_MSGBOX }, + { "nocancel", '\0', 0, &noCancel, 0 }, + { "noitem", '\0', 0, &noItem, 0 }, + { "radiolist", '\0', 0, 0, OPT_RADIOLIST }, + { "scrolltext", '\0', 0, &scrollText, 0 }, + { "separate-output", '\0', 0, &separateOutput, 0 }, + { "title", '\0', POPT_ARG_STRING, &title, 0 }, + { "yesno", '\0', 0, 0, OPT_YESNO }, + { 0, 0, 0, 0, 0 } + }; + + optCon = poptGetContext("ndialog", argc, argv, optionsTable, 0); + + while ((arg = poptGetNextOpt(optCon)) > 0) { + optArg = poptGetOptArg(optCon); + + switch (arg) { + case OPT_MENU: + if (mode != MODE_NONE) usage(); + mode = MODE_MENU; + break; + + case OPT_MSGBOX: + if (mode != MODE_NONE) usage(); + mode = MODE_MSGBOX; + break; + + case OPT_RADIOLIST: + if (mode != MODE_NONE) usage(); + mode = MODE_RADIOLIST; + break; + + case OPT_CHECKLIST: + if (mode != MODE_NONE) usage(); + mode = MODE_CHECKLIST; + break; + + case OPT_FULLBUTTONS: + buttonHeight = 3; + makeButton = newtButton; + break; + + case OPT_YESNO: + if (mode != MODE_NONE) usage(); + mode = MODE_YESNO; + break; + + case OPT_GAUGE: + if (mode != MODE_NONE) usage(); + mode = MODE_GAUGE; + break; + + case OPT_INPUTBOX: + if (mode != MODE_NONE) usage(); + mode = MODE_INPUTBOX; + break; + } + } + + if (arg < -1) { + fprintf(stderr, "%s: %s\n", + poptBadOption(optCon, POPT_BADOPTION_NOALIAS), + poptStrerror(arg)); + exit(1); + } + + if (mode == MODE_NONE) usage(); + + if (!(text = poptGetArg(optCon))) usage(); + + if (!(nextArg = poptGetArg(optCon))) usage(); + height = strtoul(nextArg, &end, 10); + if (*end) usage(); + + if (!(nextArg = poptGetArg(optCon))) usage(); + width = strtoul(nextArg, &end, 10); + if (*end) usage(); + + if (mode == MODE_GAUGE) { + fd = dup(0); + close(0); + if (open("/dev/tty", O_RDWR) != 0) perror("open /dev/tty"); + } + + newtInit(); + newtCls(); + width -= 2; + height -= 2; + newtOpenWindow((80 - width) / 2, (24 - height) / 2, width, height, title); + + if (backtitle) + newtDrawRootText(0, 0, backtitle); + + if (noCancel) flags |= FLAG_NOCANCEL; + if (noItem) flags |= FLAG_NOITEM; + if (separateOutput) flags |= FLAG_SEPARATE_OUTPUT; + if (scrollText) flags |= FLAG_SCROLL_TEXT; + + switch (mode) { + case MODE_MSGBOX: + rc = messageBox(text, height, width, MSGBOX_MSG, flags); + break; + + case MODE_YESNO: + rc = messageBox(text, height, width, MSGBOX_YESNO, flags); + break; + + case MODE_INPUTBOX: + rc = inputBox(text, height, width, optCon, flags); + break; + + case MODE_MENU: + rc = listBox(text, height, width, optCon, flags); + break; + + case MODE_RADIOLIST: + rc = checkList(text, height, width, optCon, 1, flags); + break; + + case MODE_CHECKLIST: + rc = checkList(text, height, width, optCon, 0, flags); + break; + + case MODE_GAUGE: + rc = gauge(text, height, width, optCon, fd, flags); + break; + + default: + usage(); + } + + if (clear) + newtPopWindow(); + newtFinished(); + + return rc; +}