]> git.ipfire.org Git - thirdparty/newt.git/commitdiff
Initial revision
authorewt <ewt>
Tue, 18 Mar 1997 15:09:00 +0000 (15:09 +0000)
committerewt <ewt>
Tue, 18 Mar 1997 15:09:00 +0000 (15:09 +0000)
whiptail.c [new file with mode: 0644]

diff --git a/whiptail.c b/whiptail.c
new file mode 100644 (file)
index 0000000..6aba3e1
--- /dev/null
@@ -0,0 +1,578 @@
+/* a reasonable dialog */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#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;
+}