Back to index

tetex-bin  3.0
dialog.c
Go to the documentation of this file.
00001 /*
00002  *  dialog - Display simple dialog boxes from shell scripts
00003  *
00004  *  AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
00005  *
00006  *  This program is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU General Public License
00008  *  as published by the Free Software Foundation; either version 2
00009  *  of the License, or (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  *
00020  *
00021  *  HISTORY:
00022  *
00023  *  17/12/93 - Version 0.1 released.
00024  *
00025  *  19/12/93 - menu will now scroll if there are more items than can fit
00026  *             on the screen.
00027  *           - added 'checklist', a dialog box with a list of options that
00028  *             can be turned on or off. A list of options that are on is 
00029  *             returned on exit.
00030  *
00031  *  20/12/93 - Version 0.15 released.
00032  *
00033  *  29/12/93 - Incorporated patch from Patrick J. Volkerding
00034  *             (volkerdi@mhd1.moorhead.msus.edu) that made these changes:
00035  *             - increased MAX_LEN to 2048
00036  *             - added 'infobox', equivalent to a message box without pausing
00037  *             - added option '--clear' that will clear the screen
00038  *             - Explicit line breaking when printing prompt text can be
00039  *               invoked by real newline '\n' besides the string "\n"
00040  *           - an optional parameter '--title <string>' can be used to
00041  *             specify a title string for the dialog box
00042  *
00043  *  03/01/94 - added 'textbox', a dialog box for displaying text from a file.
00044  *           - Version 0.2 released.
00045  *
00046  *  04/01/94 - some fixes and improvements for 'textbox':
00047  *             - fixed a bug that will cause a segmentation violation when a
00048  *               line is longer than MAX_LEN characters. Lines will now be
00049  *               truncated if they are longer than MAX_LEN characters.
00050  *             - removed wrefresh() from print_line(). This will increase
00051  *               efficiency of print_page() which calls print_line().
00052  *             - display current position in the form of percentage into file.
00053  *           - Version 0.21 released.
00054  *
00055  *  05/01/94 - some changes for faster screen update.
00056  *
00057  *  07/01/94 - much more flexible color settings. Can use all 16 colors
00058  *             (8 normal, 8 highlight) of the Linux console.
00059  *
00060  *  08/01/94 - added run-time configuration using configuration file.
00061  *
00062  *  09/01/94 - some minor bug fixes and cleanups for menubox, checklist and
00063  *             textbox.
00064  *
00065  *  11/01/94 - added a man page.
00066  *
00067  *  13/01/94 - some changes for easier porting to other Unix systems (tested
00068  *             on Ultrix, SunOS and HPUX)
00069  *           - Version 0.3 released.
00070  * 
00071  *  08/06/94 - Patches by Stuart Herbert - S.Herbert@shef.ac.uk
00072  *            Fixed attr_clear and the textbox stuff to work with ncurses 1.8.5
00073  *            Fixed the wordwrap routine - it'll actually wrap properly now
00074  *            Added a more 3D look to everything - having your own rc file could
00075  *              prove 'interesting' to say the least :-)
00076  *             Added radiolist option
00077  *             Added backtitle option
00078  *          - Version 0.4 released.
00079  *
00080  *  10/10/94 - Patches by Marc Ewing - marc@redhat.com
00081  *             Added --separate-output
00082  *             Added init val to inputbox
00083  *             Added guage widget
00084  */
00085 
00086 
00087 #define __DIALOG_MAIN__
00088 
00089 
00090 #include "dialog.h"
00091 #ifdef HAVE_NCURSES
00092 #include "colors.h"
00093 #endif
00094 
00095 static char *backtitle = NULL;
00096 int separate_output = 0;
00097 
00098 int main(int argc, char *argv[])
00099 {
00100   int offset = 0, clear_screen = 0, end_common_opts = 0, retval;
00101   char *title = NULL;
00102   
00103 #if defined(LOCALE)
00104   (void) setlocale(LC_ALL, "");
00105 #endif
00106 
00107   if (argc < 2) {
00108     Usage(argv[0]);
00109     exit(-1);
00110   }
00111   else if (!strcmp(argv[1], "--create-rc")) {
00112 #ifdef HAVE_NCURSES
00113     if (argc != 3) {
00114       Usage(argv[0]);
00115       exit(-1);
00116     }
00117     create_rc(argv[2]);
00118     return 0;
00119 #else
00120     fprintf(stderr, "\nThis option is currently unsupported on your system.\n");
00121     return -1;
00122 #endif
00123   }
00124 
00125   while (offset < argc-1 && !end_common_opts) {    /* Common options */
00126     if (!strcmp(argv[offset+1], "--title")) {
00127       if (argc-offset < 3 || title != NULL) {    /* No two "--title" please! */
00128         Usage(argv[0]);
00129         exit(-1);
00130       }
00131       else {
00132         title = argv[offset+2];
00133         offset += 2;
00134       }
00135     }
00136     else if (!strcmp(argv[offset+1], "--backtitle" ))
00137     {
00138       if (backtitle != NULL)
00139       {
00140         Usage(argv[0]);
00141         exit(-1);
00142       }
00143       else
00144       {
00145        backtitle = argv[offset+2];
00146        offset += 2;
00147       }
00148     }
00149     else if (!strcmp(argv[offset+1], "--separate-output" ))
00150     {
00151        separate_output = 1;
00152        offset++;
00153     }
00154     else if (!strcmp(argv[offset+1], "--clear")) {
00155       if (clear_screen) {    /* Hey, "--clear" can't appear twice! */
00156         Usage(argv[0]);
00157         exit(-1);
00158       }
00159       else if (argc == 2) {    /* we only want to clear the screen */
00160         init_dialog();
00161         refresh();    /* init_dialog() will clear the screen for us */
00162         endwin();
00163         return 0;
00164       }
00165       else {
00166         clear_screen = 1;
00167         offset++;
00168       }
00169     }
00170     else    /* no more common options */
00171       end_common_opts = 1;
00172   }
00173 
00174   if (argc-1 == offset) {    /* no more options */
00175     Usage(argv[0]);
00176     exit(-1);
00177   }
00178 
00179   /* Box options */
00180 
00181   if (!strcmp(argv[offset+1], "--yesno")) {
00182     if (argc-offset != 5) {
00183       Usage(argv[0]);
00184       exit(-1);
00185     }
00186     init_dialog();
00187     retval = dialog_yesno(title, argv[offset+2], atoi(argv[offset+3]),
00188                           atoi(argv[offset+4]));
00189 
00190     if (clear_screen) {    /* clear screen before exit */
00191       attr_clear(stdscr, LINES, COLS, screen_attr);
00192       refresh();
00193     }
00194     endwin();
00195     return retval;
00196   }
00197   else if (!strcmp(argv[offset+1], "--msgbox")) {
00198     if (argc-offset != 5) {
00199       Usage(argv[0]);
00200       exit(-1);
00201     }
00202     init_dialog();
00203     retval = dialog_msgbox(title, argv[offset+2], atoi(argv[offset+3]),
00204                            atoi(argv[offset+4]), 1);
00205 
00206     if (clear_screen) {    /* clear screen before exit */
00207       attr_clear(stdscr, LINES, COLS, screen_attr);
00208       refresh();
00209     }
00210     endwin();
00211     return retval;
00212   }
00213   else if (!strcmp(argv[offset+1], "--infobox")) {
00214     if (argc-offset != 5) {
00215       Usage(argv[0]);
00216       exit(-1);
00217     }
00218     init_dialog();
00219     retval = dialog_msgbox(title, argv[offset+2], atoi(argv[offset+3]),
00220                            atoi(argv[offset+4]), 0);
00221 
00222     if (clear_screen) {    /* clear screen before exit */
00223       attr_clear(stdscr, LINES, COLS, screen_attr);
00224       refresh();
00225     }
00226     endwin();
00227     return retval;
00228   }
00229   else if (!strcmp(argv[offset+1], "--textbox")) {
00230     if (argc-offset != 5) {
00231       Usage(argv[0]);
00232       exit(-1);
00233     }
00234     init_dialog();
00235     retval = dialog_textbox(title, argv[offset+2], atoi(argv[offset+3]),
00236                             atoi(argv[offset+4]));
00237 
00238     if (clear_screen) {    /* clear screen before exit */
00239       attr_clear(stdscr, LINES, COLS, screen_attr);
00240       refresh();
00241     }
00242     endwin();
00243     return retval;
00244   }
00245   else if (!strcmp(argv[offset+1], "--menu")) {
00246     if (argc-offset < 8 || ((argc-offset) % 2)) {
00247       Usage(argv[0]);
00248       exit(-1);
00249     }
00250     init_dialog();
00251     retval = dialog_menu(title, argv[offset+2], atoi(argv[offset+3]),
00252                          atoi(argv[offset+4]), atoi(argv[offset+5]),
00253                          (argc-offset-6)/2, argv+offset + 6);
00254 
00255     if (clear_screen) {    /* clear screen before exit */
00256       attr_clear(stdscr, LINES, COLS, screen_attr);
00257       refresh();
00258     }
00259     endwin();
00260     return retval;
00261   }
00262   else if (!strcmp(argv[offset+1], "--checklist")) {
00263     if (argc-offset < 9 || ((argc-offset-6) % 3)) {
00264       Usage(argv[0]);
00265       exit(-1);
00266     }
00267     init_dialog();
00268     retval = dialog_checklist(title, argv[offset+2], atoi(argv[offset+3]),
00269                               atoi(argv[offset+4]), atoi(argv[offset+5]),
00270                               (argc-offset-6)/3, argv+offset + 6);
00271 
00272     if (clear_screen) {    /* clear screen before exit */
00273       attr_clear(stdscr, LINES, COLS, screen_attr);
00274       refresh();
00275     }
00276     endwin();
00277     return retval;
00278   }
00279   else if (!strcmp(argv[offset+1], "--radiolist")) {
00280     if (argc-offset < 9 || ((argc-offset-6) % 3)) {
00281       Usage(argv[0]);
00282       exit(-1);
00283     }
00284     init_dialog();
00285     retval = dialog_radiolist(title, argv[offset+2], atoi(argv[offset+3]),
00286                               atoi(argv[offset+4]), atoi(argv[offset+5]),
00287                               (argc-offset-6)/3, argv+offset + 6);
00288 
00289     if (clear_screen) {    /* clear screen before exit */
00290       attr_clear(stdscr, LINES, COLS, screen_attr);
00291       refresh();
00292     }
00293     endwin();
00294     return retval;
00295   }
00296   else if (!strcmp(argv[offset+1], "--guage")) {
00297       if (argc-offset != 6) {
00298          Usage(argv[0]);
00299          exit(-1);
00300       }
00301       init_dialog();
00302       retval = dialog_guage(title,  argv[offset+2],
00303                          atoi(argv[offset+3]), atoi(argv[offset+4]),
00304                          atoi(argv[offset+5]));
00305       
00306       if (clear_screen) {    /* clear screen before exit */
00307          attr_clear(stdscr, LINES, COLS, screen_attr);
00308          refresh();
00309       }
00310       endwin();
00311       return retval;
00312   }
00313   else if (!strcmp(argv[offset+1], "--inputbox")) {
00314     if (argc-offset < 5 || argc-offset > 6) {
00315       Usage(argv[0]);
00316       exit(-1);
00317     }
00318     init_dialog();
00319     retval = dialog_inputbox(title, argv[offset+2], atoi(argv[offset+3]),
00320                              atoi(argv[offset+4]),
00321                           (argc-offset == 6) ? argv[offset+5] : (char *)NULL);
00322 
00323     if (clear_screen) {    /* clear screen before exit */
00324       attr_clear(stdscr, LINES, COLS, screen_attr);
00325       refresh();
00326     }
00327     endwin();
00328     return retval;
00329   }
00330 
00331   Usage(argv[0]);
00332   exit(-1);
00333 }
00334 /* End of main() */
00335 
00336 
00337 /*
00338  * Print program usage
00339  */
00340 void Usage(char *name)
00341 {
00342   fprintf(stderr, "\
00343 \ndialog version 0.3, by Savio Lam (lam836@cs.cuhk.hk).\
00344 \n  patched to version %s by Stuart Herbert (S.Herbert@shef.ac.uk)\
00345 \n\
00346 \n* Display dialog boxes from shell scripts *\
00347 \n\
00348 \nUsage: %s --clear\
00349 \n       %s --create-rc <file>\
00350 \n       %s [--title <title>] [--separate-output] [--backtitle <backtitle>] [--clear] <Box options>\
00351 \n\
00352 \nBox options:\
00353 \n\
00354 \n  --yesno     <text> <height> <width>\
00355 \n  --msgbox    <text> <height> <width>\
00356 \n  --infobox   <text> <height> <width>\
00357 \n  --inputbox  <text> <height> <width> [<init>]\
00358 \n  --textbox   <file> <height> <width>\
00359 \n  --menu      <text> <height> <width> <menu height> <tag1> <item1>...\
00360 \n  --checklist <text> <height> <width> <list height> <tag1> <item1> <status1>...\
00361 \n  --radiolist <text> <height> <width> <list height> <tag1> <item1> <status1>...\
00362 \n  --guage     <text> <height> <width> <percent>\n", VERSION, name, name, name);
00363 }
00364 /* End of Usage() */
00365 
00366 
00367 /*
00368  * Do some initialization for dialog
00369  */
00370 void init_dialog(void)
00371 {
00372   int i;
00373   
00374 #ifdef HAVE_NCURSES
00375   if (parse_rc() == -1)    /* Read the configuration file */
00376     exit(-1);
00377 #endif
00378 
00379   initscr();     /* Init curses */
00380   keypad(stdscr, TRUE);
00381   cbreak();
00382   noecho();
00383 
00384 #ifdef HAVE_NCURSES
00385   if (use_colors || use_shadow)    /* Set up colors */
00386     color_setup();
00387 #endif
00388 
00389   /* Set screen to screen attribute */
00390   attr_clear(stdscr, LINES, COLS, screen_attr);
00391 
00392   /* Display background title if it exists ... - SLH */
00393   if (backtitle != NULL)
00394   {
00395     wattrset(stdscr, screen_attr);
00396     wmove(stdscr, 0, 1);
00397     waddstr(stdscr,backtitle);
00398     wmove(stdscr, 1, 1);
00399     for(i=1; i<COLS-1; i++)
00400       waddch(stdscr, ACS_HLINE);
00401   }
00402   
00403   wnoutrefresh(stdscr);
00404 }
00405 /* End of init_dialog() */
00406 
00407 
00408 #ifdef HAVE_NCURSES
00409 /*
00410  * Setup for color display
00411  */
00412 void color_setup(void)
00413 {
00414   int i;
00415 
00416   if (has_colors()) {    /* Terminal supports color? */
00417     start_color();
00418 
00419     /* Initialize color pairs */
00420     for (i = 0; i < ATTRIBUTE_COUNT; i++)
00421       init_pair(i+1, color_table[i][0], color_table[i][1]);
00422 
00423     /* Setup color attributes */
00424     for (i = 0; i < ATTRIBUTE_COUNT; i++)
00425       attributes[i] = C_ATTR(color_table[i][2], i+1);
00426   }
00427 }
00428 /* End of color_setup() */
00429 #endif
00430 
00431 
00432 /*
00433  * Set window to attribute 'attr'
00434  */
00435 void attr_clear(WINDOW *win, int height, int width, chtype attr)
00436 {
00437 /* ifdef HAVE_NCURSES
00438   wattrset(win, attr);    Set window to attribute 'attr'
00439   werase(win);
00440 else */
00441   int i, j;
00442 
00443   wattrset(win, attr);    /* Set window to attribute 'attr' */
00444   for (i = 0; i < height; i++) {
00445     wmove(win, i, 0);
00446     for (j = 0; j < width; j++)
00447       waddch(win, ' ');
00448   }
00449   touchwin(win);
00450 /* endif */
00451 }
00452 /* End of attr_clear() */
00453 
00454 
00455 /*
00456  * Print a string of text in a window, automatically wrap around to the
00457  * next line if the string is too long to fit on one line. Note that the
00458  * string may contain "\n" to represent a newline character or the real
00459  * newline '\n', but in that case, auto wrap around will be disabled.
00460  */
00461 void print_autowrap(WINDOW *win, char *prompt, int width, int y, int x)
00462 {
00463   int first = 1, cur_x, cur_y;
00464   char tempstr[MAX_LEN+1], *word, *tempptr, *tempptr1;
00465 
00466   strcpy(tempstr, prompt);
00467   if ((strstr(tempstr, "\\n") != NULL) ||
00468       (strchr(tempstr, '\n') != NULL)) {    /* Prompt contains "\n" or '\n' */
00469     word = tempstr;
00470     cur_y = y;
00471     wmove(win, cur_y, x);
00472     while (1) {
00473       tempptr = strstr(word, "\\n");
00474       tempptr1 = strchr(word, '\n');
00475       if (tempptr == NULL && tempptr1 == NULL)
00476         break;
00477       else if (tempptr == NULL) {    /* No more "\n" */
00478         tempptr = tempptr1;
00479         tempptr[0] = '\0';
00480       }
00481       else if (tempptr1 == NULL) {    /* No more '\n' */
00482         tempptr[0] = '\0';
00483         tempptr++;
00484       }
00485       else {    /* Prompt contains both "\n" and '\n' */
00486         if (strlen(tempptr)-2 < strlen(tempptr1)-1) {
00487           tempptr = tempptr1;
00488           tempptr[0] = '\0';
00489         }
00490         else {
00491           tempptr[0] = '\0';
00492           tempptr++;
00493         }
00494       }
00495 
00496       waddstr(win, word);
00497       word = tempptr + 1;
00498       wmove(win, ++cur_y, x);
00499     }
00500     waddstr(win, word);
00501   }
00502   else if (strlen(tempstr) <= width-x*2) {    /* If prompt is short */
00503     wmove(win, y, (width - strlen(tempstr)) / 2);
00504     waddstr(win, tempstr);
00505   }
00506   else {
00507     cur_x = x;
00508     cur_y = y;
00509     /* Print prompt word by word, wrap around if necessary */
00510     while ((word = strtok(first ? tempstr : NULL, " ")) != NULL) {
00511       if (first)    /* First iteration */
00512         first = 0;
00513       if (cur_x+strlen(word) > width) {    /* wrap around to next line */
00514         cur_y++;
00515         cur_x = x;
00516       }
00517       wmove(win, cur_y, cur_x);
00518       waddstr(win, word);
00519       getyx(win, cur_y, cur_x);
00520       cur_x++;
00521     }
00522   }
00523 }
00524 /* End of print_autowrap() */
00525 
00526 
00527 /*
00528  * Print a button
00529  */
00530 void print_button(WINDOW *win, char *label, int y, int x, int selected)
00531 {
00532   int i, temp;
00533 
00534   wmove(win, y, x);
00535   wattrset(win, selected ? button_active_attr : button_inactive_attr);
00536   waddstr(win, "<");
00537   temp = strspn(label, " ");
00538   label += temp;
00539   wattrset(win, selected ? button_label_active_attr : button_label_inactive_attr);
00540   for (i = 0; i < temp; i++)
00541     waddch(win, ' ');
00542   wattrset(win, selected ? button_key_active_attr : button_key_inactive_attr);
00543   waddch(win, label[0]);
00544   wattrset(win, selected ? button_label_active_attr : button_label_inactive_attr);
00545   waddstr(win, label+1);
00546   wattrset(win, selected ? button_active_attr : button_inactive_attr);
00547   waddstr(win, ">");
00548   wmove(win, y, x+temp+1);
00549 }
00550 /* End of print_button() */
00551 
00552 
00553 /*
00554  * Draw a rectangular box with line drawing characters
00555  */
00556 void draw_box(WINDOW *win, int y, int x, int height, int width, chtype box, chtype border)
00557 {
00558   int i, j;
00559 
00560   wattrset(win, 0);
00561   for (i = 0; i < height; i++) {
00562     wmove(win, y + i, x);
00563     for (j = 0; j < width; j++)
00564       if (!i && !j)
00565         waddch(win, border | ACS_ULCORNER);
00566       else if (i == height-1 && !j)
00567         waddch(win, border | ACS_LLCORNER);
00568       else if (!i && j == width-1)
00569         waddch(win, box | ACS_URCORNER);
00570       else if (i == height-1 && j == width-1)
00571         waddch(win, box | ACS_LRCORNER);
00572       else if (!i)
00573         waddch(win, border | ACS_HLINE);
00574       else if (i == height-1)
00575         waddch(win, box | ACS_HLINE);
00576       else if (!j)
00577         waddch(win, border | ACS_VLINE);
00578       else if (j == width-1)
00579         waddch(win, box | ACS_VLINE);
00580       else
00581         waddch(win, box | ' ');
00582   }
00583 }
00584 /* End of draw_box() */
00585 
00586 
00587 #ifdef HAVE_NCURSES
00588 /*
00589  * Draw shadows along the right and bottom edge to give a more 3D look
00590  * to the boxes
00591  */
00592 void draw_shadow(WINDOW *win, int y, int x, int height, int width)
00593 {
00594   int i;
00595 
00596   if (has_colors()) {    /* Whether terminal supports color? */
00597     wattrset(win, shadow_attr);
00598     wmove(win, y + height, x + 2);
00599     for (i = 0; i < width; i++)
00600       waddch(win, winch(win) & A_CHARTEXT);
00601     for (i = y + 1; i < y + height + 1; i++) {
00602       wmove(win, i, x + width);
00603       waddch(win, winch(win) & A_CHARTEXT);
00604       waddch(win, winch(win) & A_CHARTEXT);
00605     }
00606     wnoutrefresh(win);
00607   }
00608 }
00609 /* End of draw_shadow() */
00610 #endif