📄 dialog.c
字号:
/* * $Id: dialog.c,v 1.111 2003/11/26 22:20:28 tom Exp $ * * cdialog - Display simple dialog boxes from shell scripts * * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) * and: Thomas E. Dickey * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * 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. */#include "dialog.h"#include <string.h>#ifdef HAVE_SETLOCALE#include <locale.h>#endif#define JUMPARGS const char *t, char *av[], int *offset_addtypedef int (jumperFn) (JUMPARGS);typedef enum { o_unknown = 0 ,o_allow_close ,o_and_widget ,o_aspect ,o_auto_placement ,o_backtitle ,o_beep ,o_beep_after ,o_begin ,o_calendar ,o_cancel_label ,o_checklist ,o_clear ,o_colors ,o_cr_wrap ,o_create_rc ,o_default_item ,o_defaultno ,o_exit_label ,o_extra_button ,o_extra_label ,o_fixed_font ,o_form ,o_fselect ,o_fullbutton ,o_gauge ,o_help ,o_help_button ,o_help_label ,o_help_status ,o_icon ,o_ignore ,o_infobox ,o_input_fd ,o_inputbox ,o_inputmenu ,o_insecure ,o_item_help ,o_keep_colors ,o_keep_window ,o_max_input ,o_menu ,o_msgbox ,o_no_close ,o_no_collapse ,o_no_cr_wrap ,o_no_kill ,o_no_label ,o_no_shadow ,o_nocancel ,o_noitem ,o_ok_label ,o_output_fd ,o_passwordbox ,o_print_maxsize ,o_print_size ,o_print_version ,o_radiolist ,o_screen_center ,o_separate_output ,o_separate_widget ,o_separator ,o_shadow ,o_size_err ,o_sleep ,o_smooth ,o_stderr ,o_stdout ,o_tab_correct ,o_tab_len ,o_tailbox ,o_tailboxbg ,o_textbox ,o_timebox ,o_timeout ,o_title ,o_trim ,o_under_mouse ,o_wmclass ,o_yes_label ,o_yesno} eOptions;/* * The bits in 'pass' are used to decide which options are applicable at * different stages in the program: * 1 flags before widgets * 2 widgets * 4 non-widget options */typedef struct { const char *name; eOptions code; int pass; /* 1,2,4 or combination */ const char *help; /* NULL to suppress, non-empty to display params */} Options;typedef struct { eOptions code; int argmin, argmax; jumperFn *jumper;} Mode;static bool *dialog_opts;static char **dialog_argv;static const char *program = "dialog";static const char *const and_widget = "--and-widget";/* * The options[] table is organized this way to make it simple to maintain * a sorted list of options for the help-message. *//* *INDENT-OFF* */static const Options options[] = { { "allow-close", o_allow_close, 1, NULL }, { "and-widget", o_and_widget, 4, NULL }, { "aspect", o_aspect, 1, "<ratio>" }, { "auto-placement", o_auto_placement, 1, NULL }, { "backtitle", o_backtitle, 1, "<backtitle>" }, { "beep", o_beep, 1, "" }, { "beep-after", o_beep_after, 1, "" }, { "begin", o_begin, 1, "<y> <x>" }, { "calendar", o_calendar, 2, "<text> <height> <width> <day> <month> <year>" }, { "cancel-label", o_cancel_label, 1, "<str>" }, { "checklist", o_checklist, 2, "<text> <height> <width> <list height> <tag1> <item1> <status1>..." }, { "clear", o_clear, 1, "" }, { "colors", o_colors, 1, "" }, { "cr-wrap", o_cr_wrap, 1, "" }, { "create-rc", o_create_rc, 1, NULL }, { "default-item", o_default_item, 1, "<str>" }, { "defaultno", o_defaultno, 1, "" }, { "exit-label", o_exit_label, 1, "<str>" }, { "extra-button", o_extra_button, 1, "" }, { "extra-label", o_extra_label, 1, "<str>" }, { "fb", o_fullbutton, 1, NULL }, { "fixed-font", o_fixed_font, 1, NULL }, { "form", o_form, 2, "<text> <height> <width> <form height> <label1> <l_y1> <l_x1> <item1> <i_y1> <i_x1> <flen1> <ilen1>..." }, { "fselect", o_fselect, 2, "<filepath> <directory> <height> <width>" }, { "fullbutton", o_fullbutton, 1, NULL }, { "gauge", o_gauge, 2, "<text> <height> <width> [<percent>]" }, { "guage", o_gauge, 2, NULL }, { "help", o_help, 4, "" }, { "help-button", o_help_button, 1, "" }, { "help-label", o_help_label, 1, "<str>" }, { "help-status", o_help_status, 1, "" }, { "icon", o_icon, 1, NULL }, { "ignore", o_ignore, 1, "" }, { "infobox", o_infobox, 2, "<text> <height> <width>" }, { "input-fd", o_input_fd, 1, "<fd>" }, { "inputbox", o_inputbox, 2, "<text> <height> <width> [<init>]" }, { "inputmenu", o_inputmenu, 2, "<text> <height> <width> <menu height> <tag1> <item1>..." }, { "insecure", o_insecure, 1, "" }, { "item-help", o_item_help, 1, "" }, { "keep-colors", o_keep_colors, 1, NULL }, { "keep-window", o_keep_window, 1, "" }, { "max-input", o_max_input, 1, "<n>" }, { "menu", o_menu, 2, "<text> <height> <width> <menu height> <tag1> <item1>..." }, { "msgbox", o_msgbox, 2, "<text> <height> <width>" }, { "no-cancel", o_nocancel, 1, "" }, { "no-close", o_no_close, 1, NULL }, { "no-collapse", o_no_collapse, 1, "" }, { "no-cr-wrap", o_no_cr_wrap, 1, NULL }, { "no-kill", o_no_kill, 1, "" }, { "no-label", o_no_label, 1, "<str>" }, { "no-shadow", o_no_shadow, 1, "" }, { "nocancel", o_nocancel, 1, NULL }, /* see --no-cancel */ { "noitem", o_noitem, 1, NULL }, { "ok-label", o_ok_label, 1, "<str>" }, { "output-fd", o_output_fd, 1, "<fd>" }, { "passwordbox", o_passwordbox, 2, "<text> <height> <width> [<init>]" }, { "print-maxsize", o_print_maxsize, 1, "" }, { "print-size", o_print_size, 1, "" }, { "print-version", o_print_version, 5, "" }, { "radiolist", o_radiolist, 2, "<text> <height> <width> <list height> <tag1> <item1> <status1>..." }, { "screen-center", o_screen_center, 1, NULL }, { "separate-output",o_separate_output, 1, "" }, { "separate-widget",o_separate_widget, 1, "<str>" }, { "separator", o_separator, 1, NULL }, { "shadow", o_shadow, 1, "" }, { "size-err", o_size_err, 1, "" }, { "sleep", o_sleep, 1, "<secs>" }, { "smooth", o_smooth, 1, NULL }, { "stderr", o_stderr, 1, "" }, { "stdout", o_stdout, 1, "" }, { "tab-correct", o_tab_correct, 1, "" }, { "tab-len", o_tab_len, 1, "<n>" }, { "tailbox", o_tailbox, 2, "<file> <height> <width>" }, { "tailboxbg", o_tailboxbg, 2, "<file> <height> <width>" }, { "textbox", o_textbox, 2, "<file> <height> <width>" }, { "timebox", o_timebox, 2, "<text> <height> <width> <hour> <minute> <second>" }, { "timeout", o_timeout, 1, "<secs>" }, { "title", o_title, 1, "<title>" }, { "trim", o_trim, 1, "" }, { "under-mouse", o_under_mouse, 1, NULL }, { "version", o_print_version, 5, "" }, { "wmclass", o_wmclass, 1, NULL }, { "yes-label", o_yes_label, 1, "<str>" }, { "yesno", o_yesno, 2, "<text> <height> <width>" },};/* *INDENT-ON* *//* * Make an array showing which argv[] entries are options. Use "--" as a * special token to escape the next argument, allowing it to begin with "--". * When we find a "--" argument, also remove it from argv[] and adjust argc. * That appears to be an undocumented feature of the popt library. */static voidunescape_argv(int *argcp, char **argv){ int j, k; bool changed = FALSE; dialog_opts = calloc(*argcp + 1, sizeof(bool)); assert_ptr(dialog_opts, "unescape_argv"); dialog_argv = argv; for (j = 1; j < *argcp; j++) { bool escaped = FALSE; if (!strcmp(argv[j], "--")) { changed = TRUE; escaped = TRUE; *argcp -= 1; for (k = j; k <= *argcp; k++) argv[k] = argv[k + 1]; } if (!escaped && argv[j] != 0 && !strncmp(argv[j], "--", 2) && isalpha(argv[j][2])) { dialog_opts[j] = TRUE; } } /* if we didn't find any "--" tokens, there's no reason to do the table * lookup in isOption() */ if (!changed) { free(dialog_opts); dialog_opts = 0; }}/* * Check if the given string from main's argv is an option. */static boolisOption(const char *arg){ bool result = FALSE; if (arg != 0) { if (dialog_opts != 0) { int n; for (n = 1; dialog_argv[n] != 0; ++n) { if (dialog_argv[n] == arg) { result = dialog_opts[n]; break; } } } else if (!strncmp(arg, "--", 2) && isalpha(arg[2])) { result = TRUE; } } return result;}static eOptionslookupOption(const char *name, int pass){ unsigned n; if (isOption(name)) { name += 2; for (n = 0; n < sizeof(options) / sizeof(options[0]); n++) { if ((pass & options[n].pass) != 0 && !strcmp(name, options[n].name)) { return options[n].code; } } } return o_unknown;}static voidUsage(char *msg){ dlg_exiterr("Error: %s.\nUse --help to list options.\n\n", msg);}/* * Count arguments, stopping at the end of the argument list, or on any of our * "--" tokens. */static intarg_rest(char *argv[]){ int i = 1; /* argv[0] points to a "--" token */ while (argv[i] != 0 && (!isOption(argv[i]) || lookupOption(argv[i], 7) == o_unknown)) i++; return i;}/* * In MultiWidget this function is needed to count how many tags * a widget (menu, checklist, radiolist) has */static inthowmany_tags(char *argv[], int group){ int result = 0; int have; const char *format = "Expected %d arguments, found only %d"; char temp[80]; while (argv[0] != 0) { if (isOption(argv[0])) break; if ((have = arg_rest(argv)) < group) { sprintf(temp, format, group, have); Usage(temp); } argv += group; result++; } return result;}static intnumeric_arg(char **av, int n){ char *last = 0; int result = strtol(av[n], &last, 10); char msg[80]; if (last == 0 || *last != 0) { sprintf(msg, "Expected a number for token %d of %.20s", n, av[0]); Usage(msg); } return result;}static char *optional_str(char **av, int n, char *dft){ char *ret = dft; if (arg_rest(av) > n) ret = av[n]; return ret;}static intoptional_num(char **av, int n, int dft){ int ret = dft; if (arg_rest(av) > n) ret = numeric_arg(av, n); return ret;}/* * On AIX 4.x, we have to flush the output right away since there is a bug in * the curses package which discards stdout even when we've used newterm to * redirect output to /dev/tty. */static intshow_result(int ret){ bool either = FALSE; switch (ret) { case DLG_EXIT_OK: case DLG_EXIT_EXTRA: case DLG_EXIT_HELP: if (dialog_state.output_count > 1) { fputs(dialog_state.separate_str, dialog_state.output); either = TRUE; } if (dialog_vars.input_result[0] != '\0') { fputs(dialog_vars.input_result, dialog_state.output); either = TRUE; } if (either) { fflush(dialog_state.output); } break; } return ret;}/* * These are the program jumpers */static intj_yesno(JUMPARGS){ *offset_add = 4; return dialog_yesno(t, av[1], numeric_arg(av, 2), numeric_arg(av, 3));}static intj_msgbox(JUMPARGS){ *offset_add = 4; return dialog_msgbox(t, av[1], numeric_arg(av, 2), numeric_arg(av, 3), 1);}static intj_infobox(JUMPARGS){ *offset_add = 4; return dialog_msgbox(t, av[1], numeric_arg(av, 2), numeric_arg(av, 3), 0);}static intj_textbox(JUMPARGS){ *offset_add = 4; return dialog_textbox(t, av[1], numeric_arg(av, 2), numeric_arg(av, 3));}static intj_menu(JUMPARGS){ int tags = howmany_tags(av + 5, MENUBOX_TAGS); *offset_add = 5 + tags * MENUBOX_TAGS; return dialog_menu(t, av[1], numeric_arg(av, 2), numeric_arg(av, 3), numeric_arg(av, 4), tags, av + 5);}static intj_inputmenu(JUMPARGS){ int tags = howmany_tags(av + 5, MENUBOX_TAGS); dialog_vars.input_menu = TRUE; if (dialog_vars.max_input == 0) dialog_vars.max_input = MAX_LEN / 2; if (dialog_vars.extra_label == 0) dialog_vars.extra_label = _("Rename"); dialog_vars.extra_button = TRUE; *offset_add = 5 + tags * MENUBOX_TAGS; return dialog_menu(t, av[1], numeric_arg(av, 2), numeric_arg(av, 3), numeric_arg(av, 4), tags, av + 5);}static intj_checklist(JUMPARGS){ int tags = howmany_tags(av + 5, CHECKBOX_TAGS); *offset_add = 5 + tags * CHECKBOX_TAGS; return dialog_checklist(t, av[1], numeric_arg(av, 2), numeric_arg(av, 3), numeric_arg(av, 4), tags, av + 5, FLAG_CHECK);}static intj_radiolist(JUMPARGS){ int tags = howmany_tags(av + 5, CHECKBOX_TAGS); *offset_add = 5 + tags * CHECKBOX_TAGS; return dialog_checklist(t, av[1], numeric_arg(av, 2), numeric_arg(av, 3), numeric_arg(av, 4), tags, av + 5, FLAG_RADIO);}static intj_inputbox(JUMPARGS){ *offset_add = arg_rest(av); return dialog_inputbox(t, av[1], numeric_arg(av, 2), numeric_arg(av, 3), optional_str(av, 4, 0), 0);}static intj_passwordbox(JUMPARGS){ *offset_add = arg_rest(av); return dialog_inputbox(t, av[1], numeric_arg(av, 2), numeric_arg(av, 3), optional_str(av, 4, 0), 1);}#ifdef HAVE_XDIALOGstatic intj_calendar(JUMPARGS){ *offset_add = arg_rest(av); return dialog_calendar(t, av[1], numeric_arg(av, 2), numeric_arg(av, 3), optional_num(av, 4, -1), optional_num(av, 5, -1), optional_num(av, 6, -1));}static intj_fselect(JUMPARGS){ *offset_add = arg_rest(av); return dialog_fselect(t, av[1], numeric_arg(av, 2), numeric_arg(av, 3));}static intj_timebox(JUMPARGS){ *offset_add = arg_rest(av); return dialog_timebox(t, av[1], numeric_arg(av, 2), numeric_arg(av, 3), optional_num(av, 4, -1), optional_num(av, 5, -1), optional_num(av, 6, -1));}#endif#ifdef HAVE_FORMBOXstatic intj_form(JUMPARGS){ int tags = howmany_tags(av + 5, FORMBOX_TAGS); *offset_add = 5 + tags * FORMBOX_TAGS; return dialog_form(t, av[1], numeric_arg(av, 2), numeric_arg(av, 3), numeric_arg(av, 4), tags, av + 5);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -