/* * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com) * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Except as contained in this notice, the name of Conectiva Linux shall * not be used in advertising or otherwise to promote the sale, use or other * dealings in this Software without prior written authorization from * Conectiva Linux. * * Author: Paulo César Pereira de Andrade * */ #include #include #include #if defined(__SCO__) || defined(__UNIXWARE__) || \ (defined(sun) && defined(__SVR4)) || defined(__NetBSD__) #include #else #include #endif #include #include #include #include #include "cards.h" #include "config.h" #include "xf86config.h" #include "loader.h" #define IS_KBDDRIV(X) ((strcmp((X),"kbd") == 0) || \ (strcmp((X), "keyboard") == 0)) #ifndef PROJECT_ROOT #define PROJECT_ROOT "/usr/X11R6" #endif #ifndef XKB_RULES_DIR #ifndef __UNIXOS2__ #define XKB_RULES_DIR PROJECT_ROOT "/lib/X11/xkb/rules" #else #define XKB_RULES_DIR XF86CONFIGDIR "/xkb/rules" #endif #endif #define CONTROL_A 1 #define CONTROL_D 4 #define CONTROL_E 5 #define CONTROL_K 11 #define TAB 9 #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) void TextMode(void); static void ClearScreen(void); static void PaintWindow(WINDOW*, char*, int, int, int, int); static void PaintBox(WINDOW*, int, int, int, int); static void PaintButton(WINDOW*, char*, int, int, int); static void PrintWrap(WINDOW*, char*, int, int, int); static int Dialog(char*, char*, int, int, char*, char*, int); static void PaintItem(WINDOW*, char*, int, int); static int DialogMenu(char*, char*, int, int, int, int, char**, char*, char*, int); static void PaintCheckItem(WINDOW*, char*, int, int, int); static int DialogCheckBox(char*, char*, int, int, int, int, char**, char*, char*, char*); static char *DialogInput(char*, char*, int, int, char*, char*, char*, int); static void PaintScroller(WINDOW*, int, int, int); static int MouseConfig(void); static int KeyboardConfig(void); static int MonitorConfig(void); static int CardConfig(void); static int ScreenConfig(void); static int LayoutConfig(void); static int WriteXF86Config(void); static XF86ConfLayoutPtr CopyLayout(XF86ConfLayoutPtr); static XF86ConfAdjacencyPtr CopyAdjacency(XF86ConfAdjacencyPtr); static XF86ConfInputrefPtr CopyInputref(XF86ConfInputrefPtr); static XF86ConfInactivePtr CopyInactive(XF86ConfInactivePtr); static void FreeLayout(XF86ConfLayoutPtr); extern int string_to_parser_range(char*, parser_range*, int); #define PARSER_RANGE_SIZE 256 /* string must have at least 256 bytes */ extern int parser_range_to_string(char*, parser_range*, int); static Bool newconfig; static chtype screen_attr = A_NORMAL; static chtype dialog_attr = A_REVERSE; static chtype highlight_border_attr = A_REVERSE; static chtype shadow_border_attr = A_REVERSE; static chtype title_attr = A_NORMAL; static chtype button_active_attr = A_NORMAL; static chtype button_inactive_attr = A_NORMAL; static int menu_width, item_x; static char Edit[] = "Edit "; static char *main_menu[] = { #define CONF_MOUSE 0 "Configure mouse", #define CONF_KEYBOARD 1 "Configure keyboard", #define CONF_MONITOR 2 "Configure monitor", #define CONF_CARD 3 "Configure card", #define CONF_SCREEN 4 "Configure screen", #define CONF_LAYOUT 5 "Configure layout", #define CONF_FINISH 6 "Write "__XCONFIGFILE__" and quit", #define CONF_QUIT 7 "Quit", }; void TextMode(void) { static int first = 1; int i, choice = CONF_MOUSE; #ifdef USE_MODULES if (!nomodules) LoaderInitializeOptions(); #endif initscr(); noecho(); nonl(); keypad(stdscr, TRUE); if (first) { const char *filename; first = 0; if (has_colors()) { start_color(); init_pair(1, COLOR_BLACK, COLOR_BLACK); screen_attr = A_BOLD | COLOR_PAIR(1); init_pair(2, COLOR_BLACK, COLOR_WHITE); dialog_attr = COLOR_PAIR(2); init_pair(3, COLOR_BLACK, COLOR_WHITE); shadow_border_attr = A_BOLD | COLOR_PAIR(3); init_pair(4, COLOR_WHITE, COLOR_WHITE); highlight_border_attr = A_BOLD | COLOR_PAIR(4); init_pair(5, COLOR_WHITE, COLOR_BLUE); title_attr = A_BOLD | COLOR_PAIR(5); button_active_attr = title_attr; init_pair(6, COLOR_WHITE, COLOR_BLACK); button_inactive_attr = A_BOLD | COLOR_PAIR(6); } if ((filename = xf86openConfigFile(getuid() == 0 ? CONFPATH : USER_CONFPATH, XF86Config_path, NULL)) != NULL) { XF86Config_path = (char *)filename; if ((XF86Config = xf86readConfigFile()) == NULL) { ClearScreen(); refresh(); Dialog("Configuration error", "Error parsing configuration file.", 7, 50, " Ok ", NULL, 0); } } if (XF86Config == NULL) { XF86Config = (XF86ConfigPtr)XtCalloc(1, sizeof(XF86ConfigRec)); newconfig = True; } else newconfig = False; } ClearScreen(); refresh(); /*CONSTCOND*/ while (1) { int cancel = FALSE; ClearScreen(); refresh(); if (Dialog( __XSERVERNAME__" Configuration", "This program will create the "__XCONFIGFILE__" file, based on " "menu selections you make.\n" "\n" #if defined(__SCO__) || defined(__UNIXWARE__) "The "__XCONFIGFILE__" file usually resides in /etc. A " "sample "__XCONFIGFILE__" file is supplied with " #else #ifndef __UNIXOS2__ "The "__XCONFIGFILE__" file usually resides in " PROJECT_ROOT "/etc/X11 " #else "The "__XCONFIGFILE__" file usually resides in "XF86CONFIGDIR" " #endif "or /etc/X11. A sample "__XCONFIGFILE__" file is supplied with " #endif __XSERVERNAME__"; it is configured for a standard VGA card and " "monitor with 640x480 resolution. This program will ask for " "a pathname when it is ready to write the file.\n" "\n" "You can either take the sample "__XCONFIGFILE__" as a base and " "edit it for your configuration, or let this program " "produce a base "__XCONFIGFILE__" file for your configuration and " "fine-tune it.", 20, 60, " Ok ", " Cancel ", 0) != 0) break; while (!cancel) { ClearScreen(); refresh(); switch (DialogMenu("Main menu", "Choose one of the options:", 17, 60, 8, sizeof(main_menu) / sizeof(main_menu[0]), main_menu, " Ok ", " Cancel ", choice)) { case CONF_MOUSE: i = MouseConfig(); if (i > 0 && choice == CONF_MOUSE) choice = CONF_KEYBOARD; else if (i == 0) choice = CONF_MOUSE; break; case CONF_KEYBOARD: i = KeyboardConfig(); if (i > 0 && choice <= CONF_KEYBOARD) choice = CONF_MONITOR; else if (i == 0) choice = CONF_KEYBOARD; break; case CONF_MONITOR: i = MonitorConfig(); if (i > 0 && choice <= CONF_MONITOR) choice = CONF_CARD; else if (i == 0) choice = CONF_MONITOR; break; case CONF_CARD: i = CardConfig(); if (i > 0 && choice <= CONF_CARD) choice = CONF_SCREEN; else if (i == 0) choice = CONF_CARD; break; case CONF_SCREEN: i = ScreenConfig(); if (i > 0 && choice <= CONF_SCREEN) choice = CONF_LAYOUT; else if (i == 0) choice = CONF_SCREEN; break; case CONF_LAYOUT: i = LayoutConfig(); if (i > 0 && choice <= CONF_LAYOUT) choice = CONF_FINISH; else if (i == 0) choice = CONF_LAYOUT; break; case CONF_FINISH: if (WriteXF86Config() < 0) break; /*FALLTROUGH*/ case CONF_QUIT: endwin(); exit(0); default: cancel = TRUE; break; } } } endwin(); } static int WriteXF86Config(void) { char *xf86config; ClearScreen(); refresh(); xf86config = DialogInput("Write "__XCONFIGFILE__, "Write configuration to file:", 10, 60, XF86Config_path ? XF86Config_path : #ifndef __UNIXOS2__ "/etc/X11/"__XCONFIGFILE__, " Ok ", " Cancel ", 0); #else XF86CONFIGDIR"/"__XCONFIGFILE__, " Ok ", " Cancel ", 0); #endif if (xf86config == NULL) return (-1); if (newconfig) { if (XF86Config->conf_modules == NULL) { static char *modules[] = {"extmod", "glx", "dri", "dbe", "record", "xtrap", "type1"}; XF86LoadPtr load; int i; XF86Config->conf_modules = (XF86ConfModulePtr) XtCalloc(1, sizeof(XF86ConfModuleRec)); XF86Config->conf_modules->mod_comment = XtNewString("\tLoad \"freetype\"\n" "\t# Load \"xtt\"\n"); for (i = 0; i < sizeof(modules) / sizeof(modules[0]); i++) { load = (XF86LoadPtr)XtCalloc(1, sizeof(XF86LoadRec)); load->load_name = XtNewString(modules[i]); XF86Config->conf_modules->mod_load_lst = xf86addModule(XF86Config->conf_modules->mod_load_lst, load); } } } if (!xf86writeConfigFile(xf86config, XF86Config)) { char msg[1024]; XmuSnprintf(msg, sizeof(msg), "Failed to write configuration file %s.", xf86config); ClearScreen(); refresh(); (void)Dialog("Write failed!", msg, 8, 60, " Ok ", NULL, 0); XtFree(xf86config); return (-1); } XtFree(xf86config); return (1); } static char *protocols[] = { #ifdef __UNIXOS2__ "OS2Mouse", #endif #ifdef __SCO__ "OsMouse", #endif #ifdef __UNIXWARE__ "Xqueue", #endif #ifdef WSCONS_SUPPORT "wsmouse", #endif "Auto", "SysMouse", "MouseSystems", "BusMouse", "PS/2", "Microsoft", #ifndef __FreeBSD__ "ImPS/2", "ExplorerPS/2", "GlidePointPS/2", "MouseManPlusPS/2", "NetMousePS/2", "NetScrollPS/2", "ThinkingMousePS/2", #endif "AceCad", "GlidePoint", "IntelliMouse", "Logitech", "MMHitTab", "MMSeries", "MouseMan", "ThinkingMouse", }; static int MouseConfig(void) { int i, nlist, def, proto, emul, wheel; char **list = NULL, *device, *str; XF86ConfInputPtr *inputs = NULL; XF86ConfInputPtr input = XF86Config->conf_input_lst; XF86OptionPtr option; nlist = 0; while (input) { if (strcmp(input->inp_driver, "mouse") == 0) { list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*)); list[nlist] = XtMalloc(sizeof(Edit) + strlen(input->inp_identifier) + 1); sprintf(list[nlist], "%s%s", Edit, input->inp_identifier); inputs = (XF86ConfInputPtr*)XtRealloc((XtPointer)inputs, (nlist + 1) * sizeof(XF86ConfInputPtr)); inputs[nlist] = input; ++nlist; } input = (XF86ConfInputPtr)(input->list.next); } input = NULL; if (nlist) { list = (char**)XtRealloc((XtPointer)list, (nlist + 2) * sizeof(char*)); list[nlist++] = XtNewString("Add new mouse"); if (nlist == 2) { i = strlen("Remove ") + strlen(inputs[0]->inp_identifier) + 1; list[nlist] = XtMalloc(i); XmuSnprintf(list[nlist], i, "Remove %s", inputs[0]->inp_identifier); ++nlist; } else list[nlist++] = XtNewString("Remove mouse"); ClearScreen(); refresh(); i = DialogMenu("Mouse configuration", "You can edit or remove a previously configured mouse, " "or add a new one.", 14, 60, 4, nlist, list, " Ok ", " Cancel ", 0); if (i < 0) { for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)inputs); return (-1); } if (nlist > 2 && i == nlist - 1) { if (nlist > 3) { for (i = 0; i < nlist - 2; i++) { /* XXX Remove the "Edit " from list entries */ memmove(list[i], list[i] + sizeof(Edit) - 1, strlen(list[i]) - sizeof(Edit) + 2); } ClearScreen(); refresh(); i = DialogMenu("Remove mouse", "Select which mouse to remove", 13, 60, 4, nlist - 2, list, " Remove ", " Cancel ", 0); if (i < 0) { for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)inputs); return (-1); } input = inputs[i]; } else input = inputs[0]; for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)inputs); xf86removeInput(XF86Config, input); return (0); } if (i < nlist - 2) input = inputs[i]; } for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)inputs); if (input == NULL) { char label[32]; input = (XF86ConfInputPtr)XtCalloc(1, sizeof(XF86ConfInputRec)); XmuSnprintf(label, sizeof(label), "Mouse%d", nlist ? nlist - 2 : 0); ClearScreen(); refresh(); input->inp_identifier = DialogInput("Mouse identifier", "Enter an identifier for your mouse definition:", 11, 40, label, " Next >>", " Cancel ", 0); if (input->inp_identifier == NULL) { XtFree((XtPointer)input); return (-1); } } def = 0; option = xf86findOption(input->inp_option_lst, "Protocol"); if (option) for (i = 0; i < sizeof(protocols)/sizeof(protocols[0]); i++) if (strcasecmp(option->opt_val, protocols[i]) == 0) { def = i; break; } ClearScreen(); refresh(); i = DialogMenu("Select mouse protocol", "If you have a serial mouse, it probably will work with " "the \"Auto\" protocol. But, if it is an old serial " "mouse probably it is not PNP; in that case, most serial " "mouses understand the \"Microsoft\" protocol.", 19, 60, 7, sizeof(protocols) / sizeof(protocols[0]), protocols, " Next >>", " Cancel ", def); if (i < 0) { if (input->inp_driver == NULL) { XtFree(input->inp_driver); XtFree((XtPointer)input); } return (i); } proto = i; def = 0; if (input->inp_driver) { option = xf86findOption(input->inp_option_lst, "Emulate3Buttons"); def = option ? 0 : 1; } ClearScreen(); refresh(); i = Dialog("Mouse 3 buttons emulation", "If your mouse has only two buttons, it is recommended that " "you enable Emulate3Buttons.\n" "\n" "Do you want to enable Emulate3Buttons?", 10, 60, " Yes ", " No ", def); if (i < 0) return (i); emul = !i; ClearScreen(); refresh(); i = Dialog("Mouse Wheel configuration", "If your mouse has a wheel, you can enable it now.\n" "\n" "Do you want to enable the mouse wheel?", 10, 60, " Yes ", " No ", def); if (i < 0) return (i); wheel = !i; str = NULL; option = xf86findOption(input->inp_option_lst, "Device"); if (option) str = option->opt_val; if (str == NULL) #ifdef WSCONS_SUPPORT str = "/dev/wsmouse"; #elif defined(__FreeBSD__) str = "/dev/sysmouse"; #elif defined(__UNIXOS2__) str = "mouse$"; #elif defined(__linux__) str = "/dev/input/mice"; #else str = "/dev/mouse"; #endif ClearScreen(); refresh(); device = DialogInput("Select mouse device", "Enter mouse device:", 10, 40, str, " Finish ", " Cancel ", 0); if (device == NULL) { if (input->inp_driver == NULL) { XtFree(input->inp_driver); XtFree((XtPointer)input); } return (-1); } /* Finish mouse configuration */ option = xf86findOption(input->inp_option_lst, "Protocol"); if (option) { XtFree((XtPointer)option->opt_val); option->opt_val = XtNewString(protocols[proto]); } else input->inp_option_lst = xf86addNewOption(input->inp_option_lst, XtNewString("Protocol"), XtNewString(protocols[proto])); option = xf86findOption(input->inp_option_lst, "Emulate3Buttons"); if (option && !emul) { xf86removeOption(&input->inp_option_lst, "Emulate3Buttons"); } else if (option == NULL && emul) input->inp_option_lst = xf86addNewOption(input->inp_option_lst, XtNewString("Emulate3Buttons"), NULL); if (wheel) { option = xf86findOption(input->inp_option_lst, "ZAxisMapping"); if (option) { XtFree((XtPointer)option->opt_val); option->opt_val = XtNewString("4 5"); } else input->inp_option_lst = xf86addNewOption(input->inp_option_lst, XtNewString("ZAxisMapping"), XtNewString("4 5")); } option = xf86findOption(input->inp_option_lst, "Device"); if (option) { XtFree((XtPointer)option->opt_val); option->opt_val = device; } else input->inp_option_lst = xf86addNewOption(input->inp_option_lst, XtNewString("Device"), device); if (input->inp_driver == NULL) { input->inp_driver = XtNewString("mouse"); XF86Config->conf_input_lst = xf86addInput(XF86Config->conf_input_lst, input); } return (1); } static int KeyboardConfig(void) { int i; char *rulesfile; static int first = 1; static XkbRF_RulesPtr rules; static char **models, **layouts; XF86ConfInputPtr *inputs = NULL, input = XF86Config->conf_input_lst; char **list = NULL, *model, *layout; int nlist, def; XF86OptionPtr option; nlist = 0; while (input) { if (IS_KBDDRIV(input->inp_driver)) { list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*)); list[nlist] = XtMalloc(sizeof(Edit) + strlen(input->inp_identifier) + 1); sprintf(list[nlist], "%s%s", Edit, input->inp_identifier); inputs = (XF86ConfInputPtr*)XtRealloc((XtPointer)inputs, (nlist + 1) * sizeof(XF86ConfInputPtr)); inputs[nlist] = input; ++nlist; } input = (XF86ConfInputPtr)(input->list.next); } input = NULL; if (nlist) { list = (char**)XtRealloc((XtPointer)list, (nlist + 2) * sizeof(char*)); list[nlist++] = XtNewString("Add new keyboard"); if (nlist == 2) { i = strlen("Remove ") + strlen(inputs[0]->inp_identifier) + 1; list[nlist] = XtMalloc(i); XmuSnprintf(list[nlist], i, "Remove %s", inputs[0]->inp_identifier); ++nlist; } else list[nlist++] = XtNewString("Remove keyboard"); ClearScreen(); refresh(); i = DialogMenu("Keyboard configuration", "You can edit or remove a previously configured " "keyboard, or add a new one.", 14, 60, 4, nlist, list, " Ok ", " Cancel ", 0); if (i < 0) { for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)inputs); return (-1); } if (nlist > 2 && i == nlist - 1) { if (nlist > 3) { for (i = 0; i < nlist - 2; i++) { /* XXX Remove the "Edit " from list entries */ memmove(list[i], list[i] + sizeof(Edit) - 1, strlen(list[i]) - sizeof(Edit) + 2); } ClearScreen(); refresh(); i = DialogMenu("Remove keyboard", "Select which keyboard to remove", 13, 60, 4, nlist - 2, list, " Remove ", " Cancel ", 0); if (i < 0) { for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)inputs); return (-1); } input = inputs[i]; } else input = inputs[0]; for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)inputs); xf86removeInput(XF86Config, input); return (0); } if (i < nlist - 2) input = inputs[i]; } for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)inputs); if (input == NULL) { char label[32]; input = (XF86ConfInputPtr)XtCalloc(1, sizeof(XF86ConfInputRec)); XmuSnprintf(label, sizeof(label), "Keyboard%d", nlist ? nlist - 2 : 0); ClearScreen(); refresh(); input->inp_identifier = DialogInput("Keyboard identifier", "Enter an identifier for your keyboard definition:", 11, 40, label, " Next >>", " Cancel ", 0); if (input->inp_identifier == NULL) { XtFree((XtPointer)input); return (-1); } } if (first) { first = 0; #ifdef XFREE98_XKB rulesfile = XKB_RULES_DIR "/xfree98"; #else rulesfile = XKB_RULES_DIR "/"__XKBDEFRULES__; #endif rules = XkbRF_Load(rulesfile, "", True, False); if (rules == NULL) { ClearScreen(); refresh(); Dialog("Configuration error", "XKB rules file not found.\n" "\n" "Keyboard XKB options will be set to default values.", 10, 50, " Ok ", NULL, 0); if (input->inp_driver == NULL) { input->inp_option_lst = xf86addNewOption(input->inp_option_lst, XtNewString("XkbModel"), XtNewString("pc101")); input->inp_option_lst = xf86addNewOption(input->inp_option_lst, XtNewString("XkbLayout"), XtNewString("us")); #if defined(USE_DEPRECATED_KEYBOARD_DRIVER) input->inp_driver = XtNewString("keyboard"); #else input->inp_driver = XtNewString("kbd"); #endif XF86Config->conf_input_lst = xf86addInput(XF86Config, input); } return (0); } models = (char**)XtMalloc(sizeof(char*) * rules->models.num_desc); for (i = 0; i < rules->models.num_desc; i++) models[i] = XtNewString(rules->models.desc[i].desc); layouts = (char**)XtMalloc(sizeof(char*) * rules->layouts.num_desc); for (i = 0; i < rules->layouts.num_desc; i++) layouts[i] = XtNewString(rules->layouts.desc[i].desc); } else if (rules == NULL) return (-1); def = 0; option = xf86findOption(input->inp_option_lst, "XkbModel"); if (option) { for (i = 0; i < rules->models.num_desc; i++) if (strcasecmp(option->opt_val, rules->models.desc[i].name) == 0) { def = i; break; } } ClearScreen(); refresh(); i = DialogMenu("Keyboard model", "Please select one of the following keyboard types that is " "the better description of your keyboard. If nothing really " "matches, choose \"Generic 101-key PC\".\n", 20, 60, 9, rules->models.num_desc, models, " Next >>", " Cancel ", def); if (i < 0) return (i); model = rules->models.desc[i].name; def = 0; option = xf86findOption(input->inp_option_lst, "XkbLayout"); if (option) { for (i = 0; i < rules->layouts.num_desc; i++) if (strcasecmp(option->opt_val, rules->layouts.desc[i].name) == 0) { def = i; break; } } ClearScreen(); refresh(); i = DialogMenu("Keyboard layout", "Select keyboard layout:", 20, 60, 11, rules->layouts.num_desc, layouts, " Finish ", " Cancel ", def); if (i < 0) return (i); layout = rules->layouts.desc[i].name; /* Finish keyboard configuration */ option = xf86findOption(input->inp_option_lst, "XkbModel"); if (option) { XtFree((XtPointer)option->opt_val); option->opt_val = XtNewString(model); } else input->inp_option_lst = xf86addNewOption(input->inp_option_lst, XtNewString("XkbModel"), XtNewString(model)); option = xf86findOption(input->inp_option_lst, "XkbLayout"); if (option) { XtFree((XtPointer)option->opt_val); option->opt_val = XtNewString(layout); } else input->inp_option_lst = xf86addNewOption(input->inp_option_lst, XtNewString("XkbLayout"), XtNewString(layout)); if (input->inp_driver == NULL) { #if defined(USE_DEPRECATED_KEYBOARD_DRIVER) input->inp_driver = XtNewString("keyboard"); #else input->inp_driver = XtNewString("kbd"); #endif XF86Config->conf_input_lst = xf86addInput(XF86Config->conf_input_lst, input); } return (1); } static char *hsync[] = { #define CONF_MONITOR_HSYNC 0 "Enter your own horizontal sync range", "31.5; Standard VGA, 640x480 @ 60 Hz", "31.5 - 35.1; Super VGA, 800x600 @ 56 Hz", "31.5, 35.5; 8514 Compatible, 1024x768 @ 87 Hz interlaced (no 800x600)", "31.5, 35.15, 35.5; Super VGA, 1024x768 @ 87 Hz int., 800x600 @ 56 Hz", "31.5 - 37.9; Extended Super VGA, 800x600 @ 60 Hz, 640x480 @ 72 Hz", "31.5 - 48.5; Non-Interlaced SVGA, 1024x768 @ 60 Hz, 800x600 @ 72 Hz", "31.5 - 57.0; High Frequency SVGA, 1024x768 @ 70 Hz", "31.5 - 64.3; Monitor that can do 1280x1024 @ 60 Hz", "31.5 - 79.0; Monitor that can do 1280x1024 @ 74 Hz", "31.5 - 82.0; Monitor that can do 1280x1024 @ 76 Hz", "31.5 - 92.0; Monitor that can do 1280x1024 @ 85 Hz", "31.5 - 108.0; Monitor that can do 1600x1200 @ 85 Hz", "31.5 - 128.5; Monitor that can do 1920x1440 @ 85 Hz", "31.5 - 137.0; Monitor that can do 2048x1536 @ 85 Hz" }; static char *vrefresh[] = { #define CONF_MONITOR_VREFRESH 0 "Enter your own vertical sync range", "50 - 70", "50 - 90", "50 - 100", "40 - 150", }; static int MonitorConfig(void) { int i; XF86ConfMonitorPtr *monitors = NULL, monitor = XF86Config->conf_monitor_lst; char **list = NULL, *identifier = NULL, *tmp; int nlist, def; char hsync_str[256], vrefresh_str[256]; hsync_str[0] = vrefresh_str[0] = '\0'; nlist = 0; while (monitor) { list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*)); list[nlist] = XtMalloc(sizeof(Edit) + strlen(monitor->mon_identifier) + 1); sprintf(list[nlist], "%s%s", Edit, monitor->mon_identifier); monitors = (XF86ConfMonitorPtr*)XtRealloc((XtPointer)monitors, (nlist + 1) * sizeof(XF86ConfMonitorPtr)); monitors[nlist] = monitor; ++nlist; monitor = (XF86ConfMonitorPtr)(monitor->list.next); } monitor = NULL; if (nlist) { list = (char**)XtRealloc((XtPointer)list, (nlist + 2) * sizeof(char*)); list[nlist++] = XtNewString("Add new monitor"); if (nlist == 2) { i = strlen("Remove ") + strlen(monitors[0]->mon_identifier) + 1; list[nlist] = XtMalloc(i); XmuSnprintf(list[nlist], i, "Remove %s", monitors[0]->mon_identifier); ++nlist; } else list[nlist++] = XtNewString("Remove monitor"); ClearScreen(); refresh(); i = DialogMenu("Monitor configuration", "You can edit or remove a previously configured " "monitor, or add a new one.", 14, 60, 4, nlist, list, " Ok ", " Cancel ", 0); if (i < 0) { for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)monitors); return (-1); } if (nlist > 2 && i == nlist - 1) { if (nlist > 3) { for (i = 0; i < nlist - 2; i++) { /* XXX Remove the "Edit " from list entries */ memmove(list[i], list[i] + sizeof(Edit) - 1, strlen(list[i]) - sizeof(Edit) + 2); } ClearScreen(); refresh(); i = DialogMenu("Remove monitor", "Select which monitor to remove", 13, 60, 4, nlist - 2, list, " Remove ", " Cancel ", 0); if (i < 0) { for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)monitors); return (-1); } monitor = monitors[i]; } else monitor = monitors[0]; for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)monitors); xf86removeMonitor(XF86Config, monitor); return (0); } if (i < nlist - 2) monitor = monitors[i]; } for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)monitors); if (monitor == NULL) { char label[32]; monitor = (XF86ConfMonitorPtr)XtCalloc(1, sizeof(XF86ConfMonitorRec)); XmuSnprintf(label, sizeof(label), "Monitor%d", nlist ? nlist - 2 : 0); ClearScreen(); refresh(); identifier = DialogInput("Monitor identifier", "Enter an identifier for your monitor definition:", 11, 40, label, " Next >>", " Cancel ", 0); if (identifier == NULL) { XtFree((XtPointer)monitor); return (-1); } } if (monitor->mon_identifier == NULL) { ClearScreen(); refresh(); i = Dialog("Monitor configuration", "Now we want to set the specifications of the monitor. The " "two critical parameters are the vertical refresh rate, which " "is the rate at which the whole screen is refreshed, and most " "importantly the horizontal sync rate, which is the rate at " "which scanlines are displayed.\n" "\n" "The valid range for horizontal sync and vertical sync should " "be documented in the manual of your monitor.", 15, 60, " Next >>", " Cancel ", 0); if (i != 0) { XtFree(identifier); XtFree((XtPointer)monitor); return (-1); } } def = 0; if (monitor->mon_identifier) { int len; parser_range_to_string(hsync_str, &(monitor->mon_hsync[0]), monitor->mon_n_hsync); len = strlen(hsync_str); for (i = 1; i < sizeof(hsync) / sizeof(hsync[0]); i++) { tmp = strchr(hsync[i], ';'); if (strncmp(hsync_str, hsync[i], len) == 0) { def = i; break; } } } if (hsync_str[0] == '\0') strcpy(hsync_str, "31.5"); ClearScreen(); refresh(); i = DialogMenu("Monitor HorizSync", "You must indicate the horizontal sync range of your " "monitor. You can either select one of the predefined " "ranges below that correspond to industry-standard monitor " "types, or give a specific range.", 22, 78, 11, sizeof(hsync) / sizeof(hsync[0]), hsync, " Next >>", " Cancel ", def); if (i < 0) { if (monitor->mon_identifier == NULL) { XtFree(identifier); XtFree((XtPointer)monitor); } return (-1); } if (i == CONF_MONITOR_HSYNC) { ClearScreen(); refresh(); tmp = DialogInput("Monitor HorizSync", "Please enter the horizontal sync range of your " "monitor, in the format used in the table of monitor " "types above. You can either specify one or more " "continuous ranges (e.g. 15-25, 30-50), or one or more " "fixed sync frequencies.\n" "\n" "Horizontal sync range:", 16, 62, hsync_str, " Ok ", " Cancel ", def); if (tmp == NULL) { if (monitor->mon_identifier == NULL) { XtFree(identifier); XtFree((XtPointer)monitor); } return (-1); } XmuSnprintf(hsync_str, sizeof(hsync_str), "%s", tmp); XtFree(tmp); } else { tmp = strchr(hsync[i], ';'); strncpy(hsync_str, hsync[i], tmp - hsync[i]); hsync_str[tmp - hsync[i]] = '\0'; } def = 0; if (monitor->mon_identifier) { parser_range_to_string(vrefresh_str, &(monitor->mon_vrefresh[0]), monitor->mon_n_vrefresh); for (i = 1; i < sizeof(vrefresh) / sizeof(vrefresh[0]); i++) { if (strcmp(vrefresh_str, vrefresh[i]) == 0) { def = i; break; } } } if (vrefresh_str[0] == '\0') strcpy(vrefresh_str, "50 - 70"); ClearScreen(); refresh(); i = DialogMenu("Monitor VertRefresh", "You must indicate the vertical sync range of your monitor. " "You can either select one of the predefined ranges below " "that correspond to industry-standard monitor types, or " "give a specific range. For interlaced modes, the number " "that counts is the high one (e.g. 87 Hz rather than 43 Hz).", 19, 60, 5, sizeof(vrefresh) / sizeof(vrefresh[0]), vrefresh, " Finish ", " Cancel ", def); if (i < 0) { if (monitor->mon_identifier == NULL) { XtFree(identifier); XtFree((XtPointer)monitor); } return (i); } if (i == CONF_MONITOR_VREFRESH) { ClearScreen(); refresh(); tmp = DialogInput("Monitor VertRefresh", "Vertical sync range:", 10, 50, vrefresh_str, " Done ", " Cancel ", 0); if (tmp == NULL) { if (monitor->mon_identifier == NULL) { XtFree(identifier); XtFree((XtPointer)monitor); } return (-1); } XmuSnprintf(vrefresh_str, sizeof(vrefresh_str), "%s", tmp); XtFree(tmp); } else strcpy(vrefresh_str, vrefresh[i]); /* Finish monitor configuration */ monitor->mon_n_hsync = string_to_parser_range(hsync_str, &(monitor->mon_hsync[0]), CONF_MAX_HSYNC); monitor->mon_n_vrefresh = string_to_parser_range(vrefresh_str, &(monitor->mon_vrefresh[0]), CONF_MAX_VREFRESH); if (monitor->mon_identifier == NULL) { monitor->mon_identifier = identifier; XF86Config->conf_monitor_lst = xf86addMonitor(XF86Config->conf_monitor_lst, monitor); } return (1); } static int CardConfig(void) { int i; XF86ConfDevicePtr *devices = NULL, device = XF86Config->conf_device_lst; char **list = NULL, *identifier = NULL, *driver, *busid, *tmp; int nlist, def; CardsEntry *entry = NULL; static char **drivers; static int ndrivers; static char *xdrivers[] = { "apm", "ark", "ati", "r128", "radeon", "chips", "cirrus", "cyrix", "fbdev", "glint", "i128", "i740", "i810", "imstt", "mga", "neomagic", "nv", "rendition", "s3", "s3virge", "savage", "siliconmotion", "sis", "tdfx", "tga", "trident", "tseng", "vmware", "vga", "vesa", }; #ifdef USE_MODULES if (!nomodules) { xf86cfgModuleOptions *opts = module_options; drivers = NULL; ndrivers = 0; while (opts) { if (opts->type == VideoModule) { ++ndrivers; drivers = (char**)XtRealloc((XtPointer)drivers, ndrivers * sizeof(char*)); /* XXX no private copy */ drivers[ndrivers - 1] = opts->name; } opts = opts->next; } } else #endif { ndrivers = sizeof(xdrivers) / sizeof(xdrivers[0]); drivers = xdrivers; } nlist = 0; while (device) { list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*)); list[nlist] = XtMalloc(sizeof(Edit) + strlen(device->dev_identifier) + 1); sprintf(list[nlist], "%s%s", Edit, device->dev_identifier); devices = (XF86ConfDevicePtr*)XtRealloc((XtPointer)devices, (nlist + 1) * sizeof(XF86ConfDevicePtr)); devices[nlist] = device; ++nlist; device = (XF86ConfDevicePtr)(device->list.next); } device = NULL; if (nlist) { list = (char**)XtRealloc((XtPointer)list, (nlist + 2) * sizeof(char*)); list[nlist++] = XtNewString("Add new card"); if (nlist == 2) { i = strlen("Remove ") + strlen(devices[0]->dev_identifier) + 1; list[nlist] = XtMalloc(i); XmuSnprintf(list[nlist], i, "Remove %s", devices[0]->dev_identifier); ++nlist; } else list[nlist++] = XtNewString("Remove device"); ClearScreen(); refresh(); i = DialogMenu("Card configuration", "You can edit or remove a previously configured " "card, or add a new one.", 14, 60, 4, nlist, list, " Ok ", " Cancel ", 0); if (i < 0) { for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)devices); return (-1); } if (nlist > 2 && i == nlist - 1) { if (nlist > 3) { for (i = 0; i < nlist - 2; i++) { /* XXX Remove the "Edit " from list entries */ memmove(list[i], list[i] + sizeof(Edit) - 1, strlen(list[i]) - sizeof(Edit) + 2); } ClearScreen(); refresh(); i = DialogMenu("Remove card", "Select which card to remove", 13, 60, 4, nlist - 2, list, " Remove ", " Cancel ", 0); if (i < 0) { for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)devices); return (-1); } device = devices[i]; } else device = devices[0]; for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)devices); xf86removeDevice(XF86Config, device); return (0); } if (i < nlist - 2) device = devices[i]; } for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)devices); if (device == NULL) { char label[32]; device = (XF86ConfDevicePtr)XtCalloc(1, sizeof(XF86ConfDeviceRec)); device->dev_chipid = device->dev_chiprev = device->dev_irq = -1; XmuSnprintf(label, sizeof(label), "Card%d", nlist ? nlist - 2 : 0); ClearScreen(); refresh(); identifier = DialogInput("Card identifier", "Enter an identifier for your card definition:", 11, 40, label, " Next >>", " Cancel ", 0); if (identifier == NULL) { XtFree((XtPointer)device); return (-1); } } ClearScreen(); refresh(); if (Dialog("Card configuration", "Now we must configure video card specific settings. At this " "point you can choose to make a selection out of a database of " "video card definitions.\n" "\n" "The database entries include information about the chipset, " "what driver to run, the Ramdac and ClockChip, and comments " "that will be included in the Device section. However, a lot " "of definitions only hint about what driver to run (based on " "the chipset the card uses) and are untested.\n" "\n" "Do you want to look at the card database?", 18, 60, " Yes ", " No ", device->dev_identifier != NULL) == 0) { static char **cards; static int ncards; if (cards == NULL) { ReadCardsDatabase(); cards = GetCardNames(&ncards); cards = (char**)XtRealloc((XtPointer)cards, (ncards + 1) * sizeof(char*)); for (i = ncards; i > 0; i--) cards[i] = cards[i - 1]; cards[0] = "** Unlisted card **"; ++ncards; } if (device->dev_card) entry = LookupCard(device->dev_card); def = 0; if (entry) { for (i = 0; i < NumCardsEntry; i++) if (strcasecmp(CardsDB[i]->name, entry->name) == 0) { def = i + 1; break; } /* make sure entry is set to null again */ entry = NULL; } i = DialogMenu("Card database", "Select name that better matches your card:", 20, 70, 11, ncards, cards, "Next >>", " Cancel ", def); if (i > 0) entry = LookupCard(cards[i]); } def = 0; tmp = device->dev_driver ? device->dev_driver : entry && entry->driver ? entry->driver : "vga"; for (i = 0; i < ndrivers; i++) if (strcmp(drivers[i], tmp) == 0) { def = i; break; } ClearScreen(); refresh(); i = DialogMenu("Card driver", "You can select the driver for your card here, or just press " "Enter to use the default/current:", 20, 50, 9, ndrivers, drivers, " Ok ", " Cancel ", def); if (i < 0) { if (device->dev_identifier == NULL) { XtFree(identifier); XtFree((XtPointer)device); } return (-1); } driver = ndrivers ? drivers[i] : "vga"; ClearScreen(); refresh(); tmp = device->dev_busid ? device->dev_busid : ""; busid = DialogInput("Card BusID", "You normally does not need to fill this field " "if you have only one video card:", 11, 50, tmp, " Finish ", " Cancel ", 0); /* Finish card configuration */ if (entry) { XtFree(device->dev_card); device->dev_card = XtNewString(entry->name); if (entry->chipset) { XtFree(device->dev_chipset); device->dev_chipset = XtNewString(entry->chipset); } if (entry->ramdac) { XtFree(device->dev_ramdac); device->dev_ramdac = XtNewString(entry->ramdac); } if (entry->clockchip) { XtFree(entry->clockchip); device->dev_clockchip = XtNewString(entry->clockchip); } } if (busid) { XtFree(device->dev_busid); if (*busid) device->dev_busid = busid; else { device->dev_busid = NULL; XtFree(busid); } } XtFree(device->dev_driver); device->dev_driver = XtNewString(driver); if (device->dev_identifier == NULL) { device->dev_identifier = identifier; XF86Config->conf_device_lst = xf86addDevice(XF86Config->conf_device_lst, device); } return (1); } static char *depths[] = { "1 bit, monochrome", "4 bit, 16 colors", "8 bit, 256 colors", "15 bits, 32Kb colors", "16 bits, 65Kb colors", "24 bits, 16Mb colors", }; static char *modes[] = { "2048x1536", "1920x1440", "1800x1400", "1600x1200", "1400x1050", "1280x1024", "1280x960", "1152x864", "1024x768", "800x600", "640x480", "640x400", "512x384", "400x300", "320x240", "320x200", }; static int ScreenConfig(void) { int i, disp_allocated; XF86ConfScreenPtr *screens = NULL, screen = XF86Config->conf_screen_lst; char **list = NULL, *identifier = NULL; int nlist, def; XF86ConfDevicePtr device = NULL; XF86ConfMonitorPtr monitor = NULL; XF86ConfDisplayPtr display; XF86ModePtr mode, ptr = NULL; char *checks; nlist = 0; while (screen) { list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*)); list[nlist] = XtMalloc(sizeof(Edit) + strlen(screen->scrn_identifier) + 1); sprintf(list[nlist], "%s%s", Edit, screen->scrn_identifier); screens = (XF86ConfScreenPtr*)XtRealloc((XtPointer)screens, (nlist + 1) * sizeof(XF86ConfScreenPtr)); screens[nlist] = screen; ++nlist; screen = (XF86ConfScreenPtr)(screen->list.next); } screen = NULL; if (nlist) { list = (char**)XtRealloc((XtPointer)list, (nlist + 2) * sizeof(char*)); list[nlist++] = XtNewString("Add new screen"); if (nlist == 2) { i = strlen("Remove ") + strlen(screens[0]->scrn_identifier) + 1; list[nlist] = XtMalloc(i); XmuSnprintf(list[nlist], i, "Remove %s", screens[0]->scrn_identifier); ++nlist; } else list[nlist++] = XtNewString("Remove screen"); ClearScreen(); refresh(); i = DialogMenu("Screen configuration", "You can edit or remove a previously configured " "screen, or add a new one.", 14, 60, 4, nlist, list, " Ok ", " Cancel ", 0); if (i < 0) { for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)screens); return (-1); } if (nlist > 2 && i == nlist - 1) { if (nlist > 3) { for (i = 0; i < nlist - 2; i++) { /* XXX Remove the "Edit " from list entries */ memmove(list[i], list[i] + sizeof(Edit) - 1, strlen(list[i]) - sizeof(Edit) + 2); } ClearScreen(); refresh(); i = DialogMenu("Remove screen", "Select which screen to remove", 13, 60, 4, nlist - 2, list, " Remove ", " Cancel ", 0); if (i < 0) { for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)screens); return (-1); } screen = screens[i]; } else screen = screens[0]; for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)screens); xf86removeScreen(XF86Config, screen); return (0); } if (i < nlist - 2) screen = screens[i]; } for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)screens); if (screen == NULL) { char label[256]; XF86ConfDevicePtr *devices = NULL; XF86ConfMonitorPtr *monitors = NULL; device = XF86Config->conf_device_lst; monitor = XF86Config->conf_monitor_lst; if (device == NULL || monitor == NULL) { ClearScreen(); refresh(); Dialog("Configuration error", "You need to configure (at least) one card and one " "monitor before creating a screen definition.", 9, 50, " Ok ", NULL, 0); return (-1); } XmuSnprintf(label, sizeof(label), "Screen%d", nlist ? nlist - 2 : 0); ClearScreen(); refresh(); identifier = DialogInput("Screen identifier", "Enter an identifier for your screen definition:", 11, 40, label, " Next >>", " Cancel ", 0); if (identifier == NULL) return (-1); nlist = 0; list = NULL; while (device) { list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*)); list[nlist] = XtNewString(device->dev_identifier); devices = (XF86ConfDevicePtr*)XtRealloc((XtPointer)devices, (nlist + 1) * sizeof(XF86ConfDevicePtr)); devices[nlist] = device; ++nlist; device = (XF86ConfDevicePtr)(device->list.next); } ClearScreen(); refresh(); i = DialogMenu("Screen card", "Please select a video card:", 13, 60, 4, nlist, list, " Next >>", " Cancel ", 0); for (def = 0; def < nlist; def++) XtFree(list[def]); XtFree((XtPointer)list); if (i < 0) { XtFree(identifier); XtFree((XtPointer)devices); return (-1); } device = devices[i]; XtFree((XtPointer)devices); nlist = 0; list = NULL; while (monitor) { list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*)); list[nlist] = XtNewString(monitor->mon_identifier); monitors = (XF86ConfMonitorPtr*)XtRealloc((XtPointer)monitors, (nlist + 1) * sizeof(XF86ConfMonitorPtr)); monitors[nlist] = monitor; ++nlist; monitor = (XF86ConfMonitorPtr)(monitor->list.next); } XmuSnprintf(label, sizeof(label), "Select the monitor connected to \"%s\":", device->dev_identifier); ClearScreen(); refresh(); i = DialogMenu("Screen monitor", label, 13, 60, 4, nlist, list, " Next >>", " Cancel ", 0); for (def = 0; def < nlist; def++) XtFree(list[def]); XtFree((XtPointer)list); if (i < 0) { XtFree(identifier); XtFree((XtPointer)monitors); return (-1); } monitor = monitors[i]; XtFree((XtPointer)monitors); screen = (XF86ConfScreenPtr)XtCalloc(1, sizeof(XF86ConfScreenRec)); screen->scrn_device = device; screen->scrn_monitor = monitor; } if (screen->scrn_defaultdepth == 1) def = 0; else if (screen->scrn_defaultdepth == 4) def = 1; else if (screen->scrn_defaultdepth == 8) def = 2; else if (screen->scrn_defaultdepth == 15) def = 3; else if (screen->scrn_defaultdepth == 16) def = 4; else if (screen->scrn_defaultdepth == 24) def = 5; else { if (screen->scrn_device && screen->scrn_device->dev_driver && strcmp(screen->scrn_device->dev_driver, "vga") == 0) def = 1; /* 4bpp */ else def = 2; /* 8bpp */ } ClearScreen(); refresh(); i = DialogMenu("Screen depth", "Please specify which color depth you want to use by default:", 15, 60, 6, sizeof(depths) / sizeof(depths[0]), depths, " Next >>", " Cancel ", def); if (i < 0) { if (screen->scrn_identifier == NULL) { XtFree(identifier); XtFree((XtPointer)screen); } return (-1); } else /* XXX depths must begin with the depth number */ screen->scrn_defaultdepth = atoi(depths[i]); def = 0; /* use def to count how many modes are selected*/ nlist = 0; list = NULL; checks = XtMalloc(sizeof(modes) / sizeof(modes[0])); /* XXX list fields in the code below are not allocated */ disp_allocated = 0; display = screen->scrn_display_lst; while (display && display->disp_depth != screen->scrn_defaultdepth) display = (XF86ConfDisplayPtr)(display->list.next); if (display == NULL) { display = (XF86ConfDisplayPtr)XtCalloc(1, sizeof(XF86ConfDisplayRec)); display->disp_white.red = display->disp_black.red = -1; display->disp_depth = screen->scrn_defaultdepth; disp_allocated = 1; } else { mode = display->disp_mode_lst; while (mode) { for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) if (strcmp(modes[i], mode->mode_name) == 0) { break; } if (i == sizeof(modes) / sizeof(modes[0])) { list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*)); list[nlist] = mode->mode_name; checks = XtRealloc(checks, sizeof(modes) / sizeof(modes[0]) + nlist + 1); checks[nlist] = 1; ++def; nlist++; break; } mode = (XF86ModePtr)(mode->list.next); } } for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) checks[i + nlist] = 0; mode = display->disp_mode_lst; while (mode) { for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) if (strcmp(modes[i], mode->mode_name) == 0) { ++def; checks[i + nlist] = 1; break; } mode = (XF86ModePtr)(mode->list.next); } if (nlist == 0 && def == 0) checks[7] = 1; /* 640x480 */ list = (char**)XtRealloc((XtPointer)list, (nlist + sizeof(modes) / sizeof(modes[0])) * sizeof(char*)); for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) list[i + nlist] = modes[i]; nlist += sizeof(modes) / sizeof(modes[0]); ClearScreen(); refresh(); i = DialogCheckBox("Screen modes", "Select the video modes for this screen:", 17, 60, 8, sizeof(modes) / sizeof(modes[0]), modes, " Finish ", " Cancel ", checks); if (i < 0) { if (screen->scrn_identifier == NULL) { XtFree(identifier); XtFree((XtPointer)screen); XtFree((XtPointer)list); if (disp_allocated) XtFree((XtPointer)display); } return (-1); } mode = display->disp_mode_lst; while (mode) { ptr = (XF86ModePtr)(mode->list.next); XtFree(mode->mode_name); XtFree((XtPointer)mode); mode = ptr; } display->disp_mode_lst = NULL; for (i = 0; i < nlist; i++) { if (checks[i]) { mode = (XF86ModePtr)XtCalloc(1, sizeof(XF86ModeRec)); mode->mode_name = XtNewString(list[i]); if (display->disp_mode_lst == NULL) display->disp_mode_lst = ptr = mode; else { ptr->list.next = mode; ptr = mode; } } } XtFree((XtPointer)list); if (disp_allocated) { display->list.next = NULL; if (screen->scrn_display_lst == NULL) screen->scrn_display_lst = display; else screen->scrn_display_lst->list.next = display; } if (screen->scrn_identifier == NULL) { screen->scrn_identifier = identifier; screen->scrn_monitor_str = XtNewString(monitor->mon_identifier); screen->scrn_device_str = XtNewString(device->dev_identifier); XF86Config->conf_screen_lst = xf86addScreen(XF86Config->conf_screen_lst, screen); } return (1); } static XF86ConfAdjacencyPtr CopyAdjacency(XF86ConfAdjacencyPtr ptr) { XF86ConfAdjacencyPtr adj = (XF86ConfAdjacencyPtr) XtCalloc(1, sizeof(XF86ConfAdjacencyRec)); adj->adj_scrnum = ptr->adj_scrnum; adj->adj_screen = ptr->adj_screen; adj->adj_screen_str = XtNewString(ptr->adj_screen_str); adj->adj_top = ptr->adj_top; if (ptr->adj_top_str) adj->adj_top_str = XtNewString(ptr->adj_top_str); adj->adj_bottom = ptr->adj_bottom; if (ptr->adj_bottom_str) adj->adj_bottom_str = XtNewString(ptr->adj_bottom_str); adj->adj_left = ptr->adj_left; if (ptr->adj_left_str) adj->adj_left_str = XtNewString(ptr->adj_left_str); adj->adj_right = ptr->adj_right; if (ptr->adj_right_str) adj->adj_right_str = XtNewString(ptr->adj_right_str); adj->adj_where = ptr->adj_where; adj->adj_x = ptr->adj_x; adj->adj_y = ptr->adj_y; if (ptr->adj_refscreen) adj->adj_refscreen = XtNewString(ptr->adj_refscreen); return (adj); } static XF86ConfInactivePtr CopyInactive(XF86ConfInactivePtr ptr) { XF86ConfInactivePtr inac = (XF86ConfInactivePtr) XtCalloc(1, sizeof(XF86ConfInactiveRec)); inac->inactive_device = ptr->inactive_device; if (ptr->inactive_device_str) inac->inactive_device_str = XtNewString(ptr->inactive_device_str); return (inac); } static XF86ConfInputrefPtr CopyInputref(XF86ConfInputrefPtr ptr) { XF86ConfInputrefPtr iref = (XF86ConfInputrefPtr) XtCalloc(1, sizeof(XF86ConfInputrefRec)); XF86OptionPtr opt = ptr->iref_option_lst; iref->iref_inputdev = ptr->iref_inputdev; if (ptr->iref_inputdev_str) iref->iref_inputdev_str = XtNewString(ptr->iref_inputdev_str); while (opt) { iref->iref_option_lst = xf86addNewOption(iref->iref_option_lst, XtNewString(opt->opt_name), opt->opt_val ? XtNewString(opt->opt_val) : NULL); opt = (XF86OptionPtr)(opt->list.next); } return (iref); } static XF86ConfLayoutPtr CopyLayout(XF86ConfLayoutPtr ptr) { XF86ConfLayoutPtr lay = (XF86ConfLayoutPtr) XtCalloc(1, sizeof(XF86ConfLayoutRec)); XF86ConfAdjacencyPtr adj = ptr->lay_adjacency_lst, padj; XF86ConfInactivePtr inac = ptr->lay_inactive_lst, pinac; XF86ConfInputrefPtr iref = ptr->lay_input_lst, piref; XF86OptionPtr opt = ptr->lay_option_lst; if (ptr->lay_identifier) lay->lay_identifier = XtNewString(ptr->lay_identifier); if (adj) { padj = lay->lay_adjacency_lst = CopyAdjacency(adj); adj = (XF86ConfAdjacencyPtr)(adj->list.next); while (adj) { padj->list.next = CopyAdjacency(adj); padj = (XF86ConfAdjacencyPtr)(padj->list.next); adj = (XF86ConfAdjacencyPtr)(adj->list.next); } } if (inac) { pinac = lay->lay_inactive_lst = CopyInactive(inac); inac = (XF86ConfInactivePtr)(inac->list.next); while (inac) { pinac->list.next = CopyInactive(inac); pinac = (XF86ConfInactivePtr)(pinac->list.next); inac = (XF86ConfInactivePtr)(inac->list.next); } } if (iref) { piref = lay->lay_input_lst = CopyInputref(iref); iref = (XF86ConfInputrefPtr)(iref->list.next); while (iref) { piref->list.next = CopyInputref(iref); piref = (XF86ConfInputrefPtr)(piref->list.next); iref = (XF86ConfInputrefPtr)(iref->list.next); } } while (opt) { lay->lay_option_lst = xf86addNewOption(lay->lay_option_lst, XtNewString(opt->opt_name), opt->opt_val ? XtNewString(opt->opt_val) : NULL); opt = (XF86OptionPtr)(opt->list.next); } return (lay); } static void FreeLayout(XF86ConfLayoutPtr lay) { static XF86ConfigRec xf86config; xf86config.conf_layout_lst = lay; xf86removeLayout(&xf86config, lay); } static int LayoutConfig(void) { int i; XF86ConfLayoutPtr *layouts = NULL, rlayout = NULL, layout = XF86Config->conf_layout_lst; XF86ConfInputPtr input = XF86Config->conf_input_lst; char **list = NULL, *identifier = NULL; XF86ConfInputPtr *mouses = NULL, *keyboards = NULL, mouse, keyboard; XF86ConfInputrefPtr iref, piref, mref, kref; XF86ConfAdjacencyPtr adj, padj; int nmouses, nkeyboards; int nlist; XF86OptionPtr option; XF86ConfScreenPtr screen, *screens; nmouses = nkeyboards = 0; while (input) { if (strcmp(input->inp_driver, "mouse") == 0) { mouses = (XF86ConfInputPtr*)XtRealloc((XtPointer)mouses, (nmouses + 1) * sizeof(XF86ConfInputPtr)); mouses[nmouses] = input; ++nmouses; } else if (IS_KBDDRIV(input->inp_driver)) { keyboards = (XF86ConfInputPtr*)XtRealloc((XtPointer)keyboards, (nkeyboards + 1) * sizeof(XF86ConfInputPtr)); keyboards[nkeyboards] = input; ++nkeyboards; } input = (XF86ConfInputPtr)(input->list.next); } if (XF86Config->conf_screen_lst == NULL || nmouses == 0 || nkeyboards == 0) { XtFree((XtPointer)mouses); XtFree((XtPointer)keyboards); ClearScreen(); refresh(); Dialog("Configuration error", "You need to configure (at least) one screen, mouse " "and keyboard before creating a layout definition.", 9, 50, " Ok ", NULL, 0); return (-1); } nlist = 0; while (layout) { list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*)); list[nlist] = XtMalloc(sizeof(Edit) + strlen(layout->lay_identifier) + 1); sprintf(list[nlist], "%s%s", Edit, layout->lay_identifier); layouts = (XF86ConfLayoutPtr*)XtRealloc((XtPointer)layouts, (nlist + 1) * sizeof(XF86ConfLayoutPtr)); layouts[nlist] = layout; ++nlist; layout = (XF86ConfLayoutPtr)(layout->list.next); } layout = NULL; if (nlist) { list = (char**)XtRealloc((XtPointer)list, (nlist + 2) * sizeof(char*)); list[nlist++] = XtNewString("Add new layout"); if (nlist == 2) { i = strlen("Remove ") + strlen(layouts[0]->lay_identifier) + 1; list[nlist] = XtMalloc(i); XmuSnprintf(list[nlist], i, "Remove %s", layouts[0]->lay_identifier); ++nlist; } else list[nlist++] = XtNewString("Remove layout"); ClearScreen(); refresh(); i = DialogMenu("Layout configuration", "You can edit or remove a previously configured " "layout, or add a new one.", 14, 60, 4, nlist, list, " Ok ", " Cancel ", 0); if (i < 0) { for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)layouts); XtFree((XtPointer)mouses); XtFree((XtPointer)keyboards); return (-1); } if (nlist > 2 && i == nlist - 1) { if (nlist > 3) { for (i = 0; i < nlist - 2; i++) { /* XXX Remove the "Edit " from list entries */ memmove(list[i], list[i] + sizeof(Edit) - 1, strlen(list[i]) - sizeof(Edit) + 2); } ClearScreen(); refresh(); i = DialogMenu("Remove layout", "Select which layout to remove", 13, 60, 4, nlist - 2, list, " Remove ", " Cancel ", 0); if (i < 0) { for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)layouts); XtFree((XtPointer)mouses); XtFree((XtPointer)keyboards); return (-1); } layout = layouts[i]; } else layout = layouts[0]; for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)layouts); XtFree((XtPointer)mouses); XtFree((XtPointer)keyboards); xf86removeLayout(XF86Config, layout); return (0); } if (i < nlist - 2) layout = layouts[i]; } for (i = 0; i < nlist; i++) XtFree(list[i]); XtFree((XtPointer)list); XtFree((XtPointer)layouts); if (layout == NULL) { char label[32]; layout = (XF86ConfLayoutPtr)XtCalloc(1, sizeof(XF86ConfLayoutRec)); XmuSnprintf(label, sizeof(label), "Layout%d", nlist ? nlist - 2 : 0); ClearScreen(); refresh(); identifier = DialogInput("Layout identifier", "Enter an identifier for your layout definition:", 11, 40, label, " Next >>", " Cancel ", 0); if (identifier == NULL) { XtFree((XtPointer)layout); XtFree((XtPointer)mouses); XtFree((XtPointer)keyboards); return (-1); } } else { /* So that we can safely change it */ rlayout = layout; layout = CopyLayout(rlayout); } mouse = keyboard = NULL; /* Mouse */ piref = NULL; iref = layout->lay_input_lst; while (iref) { if (strcmp(iref->iref_inputdev->inp_driver, "mouse") == 0) { if (mouse == NULL) piref = iref; if (xf86findOption(iref->iref_option_lst, "CorePointer")) { mouse = iref->iref_inputdev; piref = iref; break; } } iref = (XF86ConfInputrefPtr)(iref->list.next); } if (mouse == NULL) { if (piref) { mref = piref; mouse = piref->iref_inputdev; piref->iref_option_lst = xf86addNewOption(piref->iref_option_lst, XtNewString("CorePointer"), NULL); } else { mouse = mouses[0]; mref = iref = (XF86ConfInputrefPtr)XtCalloc(1, sizeof(XF86ConfInputrefRec)); iref->iref_inputdev_str = XtNewString(mouse->inp_identifier); iref->iref_inputdev = mouse; iref->iref_option_lst = xf86addNewOption(iref->iref_option_lst, XtNewString("CorePointer"), NULL); iref->list.next = layout->lay_input_lst; if (layout->lay_input_lst == NULL) layout->lay_input_lst = iref; else { iref->list.next = layout->lay_input_lst; layout->lay_input_lst = iref; } } } else mref = piref; /* XXX list fields are not allocated */ if (nmouses > 1) { nlist = 0; list = (char**)XtMalloc(sizeof(char*)); list[nlist++] = mouse->inp_identifier; input = XF86Config->conf_input_lst; while (input) { if (input != mouse && strcmp(input->inp_driver, "mouse") == 0) { list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*)); list[nlist++] = input->inp_identifier; } input = (XF86ConfInputPtr)(input->list.next); } ClearScreen(); refresh(); i = DialogMenu("Select Core Pointer", "Select the mouse connected to you computer", 12, 60, 4, nlist, list, " Ok ", " Cancel ", 0); if (i < 0) { XtFree((XtPointer)mouses); XtFree((XtPointer)keyboards); XtFree((XtPointer)list); if (layout->lay_identifier == NULL) XtFree(identifier); FreeLayout(layout); return (-1); } if (i > 0) { /* Did not select the default one */ iref = layout->lay_input_lst; while (iref) { if (strcasecmp(iref->iref_inputdev_str, list[i]) == 0) { if ((option = xf86findOption(iref->iref_option_lst, "SendCoreEvents")) != NULL) { XtFree(option->opt_name); option->opt_name = XtNewString("CorePointer"); } else iref->iref_option_lst = xf86addNewOption(iref->iref_option_lst, "CorePointer", NULL); option = xf86findOption(mref->iref_option_lst, "CorePointer"); XtFree(option->opt_name); option->opt_name = XtNewString("SendCoreEvents"); break; } iref = (XF86ConfInputrefPtr)(iref->list.next); } } /* XXX Write code to add/remove more mouses here */ } /* Keyboard */ piref = NULL; iref = layout->lay_input_lst; while (iref) { if (IS_KBDDRIV(iref->iref_inputdev->inp_driver)) { if (keyboard == NULL) piref = iref; if (xf86findOption(iref->iref_option_lst, "CoreKeyboard")) { keyboard = iref->iref_inputdev; piref = iref; break; } } iref = (XF86ConfInputrefPtr)(iref->list.next); } if (keyboard == NULL) { if (piref) { kref = piref; keyboard = piref->iref_inputdev; piref->iref_option_lst = xf86addNewOption(piref->iref_option_lst, XtNewString("CoreKeyboard"), NULL); } else { keyboard = keyboards[0]; kref = iref = (XF86ConfInputrefPtr)XtCalloc(1, sizeof(XF86ConfInputrefRec)); iref->iref_inputdev_str = XtNewString(keyboard->inp_identifier); iref->iref_inputdev = keyboard; iref->iref_option_lst = xf86addNewOption(iref->iref_option_lst, XtNewString("CoreKeyboard"), NULL); iref->list.next = layout->lay_input_lst; if (layout->lay_input_lst == NULL) layout->lay_input_lst = iref; else { iref->list.next = layout->lay_input_lst; layout->lay_input_lst = iref; } } } else kref = piref; /* XXX list fields are not allocated */ if (nkeyboards > 1) { nlist = 0; list = (char**)XtMalloc(sizeof(char*)); list[nlist++] = keyboard->inp_identifier; input = XF86Config->conf_input_lst; while (input) { if (input != keyboard && IS_KBDDRIV(input->inp_driver)) { list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*)); list[nlist++] = input->inp_identifier; } input = (XF86ConfInputPtr)(input->list.next); } ClearScreen(); refresh(); i = DialogMenu("Select Core Keyboard", "Select the keyboard connected to you computer", 12, 60, 4, nlist, list, " Ok ", " Cancel ", 0); if (i < 0) { XtFree((XtPointer)mouses); XtFree((XtPointer)keyboards); XtFree((XtPointer)list); if (layout->lay_identifier == NULL) XtFree(identifier); FreeLayout(layout); return (-1); } if (i > 0) { /* Did not select the default one */ iref = layout->lay_input_lst; while (iref) { if (strcasecmp(iref->iref_inputdev_str, list[i]) == 0) { if ((option = xf86findOption(iref->iref_option_lst, "SendCoreEvents")) != NULL) { XtFree(option->opt_name); option->opt_name = XtNewString("CoreKeyboard"); } else iref->iref_option_lst = xf86addNewOption(iref->iref_option_lst, "CoreKeyboard", NULL); option = xf86findOption(kref->iref_option_lst, "CoreKeyboard"); XtFree(option->opt_name); option->opt_name = XtNewString("SendCoreEvents"); break; } iref = (XF86ConfInputrefPtr)(iref->list.next); } } /* XXX Write code to add/remove more keyboards here */ } XtFree((XtPointer)mouses); XtFree((XtPointer)keyboards); /* Just one screen */ if (XF86Config->conf_screen_lst->list.next == NULL) { ClearScreen(); refresh(); Dialog("Layout configuration", (nmouses > 1 || nkeyboards > 1) ? "As you have only one screen configured, I can now finish " "creating this Layout configuration." : "As you have only one screen, mouse and keyboard configured, " "I can now finish creating this Layout configuration.", 12, 60, " Finish ", NULL, 0); goto LayoutFinish; } /* The code below just adds a screen to the right of the last * one, or allows removing a screen. * Needs some review, and adding more options. */ /*CONSTCOND*/ while (1) { static char *screen_opts[] = { "Add a new screen to layout", "Remove screen from layout", "Finish layout configuration", }; ClearScreen(); refresh(); i = DialogMenu("Layout configuration", "Please choose one option:", 12, 60, 3, sizeof(screen_opts) / sizeof(screen_opts[0]), screen_opts, " Done ", " Cancel all changes ", 2); /* cancel */ if (i < 0) { XtFree(identifier); FreeLayout(layout); return (-1); } /* add new screen */ else if (i == 0) { nlist = 0; list = NULL; screens = NULL; screen = XF86Config->conf_screen_lst; while (screen) { adj = layout->lay_adjacency_lst; while (adj) { if (adj->adj_screen == screen) break; adj = (XF86ConfAdjacencyPtr)(adj->list.next); } if (adj == NULL) { list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*)); screens = (XF86ConfScreenPtr*)XtRealloc((XtPointer)screens, (nlist + 1) * sizeof(XF86ConfScreenPtr)); /* NOT duplicated */ list[nlist] = screen->scrn_identifier; screens[nlist] = screen; ++nlist; } screen = (XF86ConfScreenPtr)(screen->list.next); } if (nlist == 0) continue; ClearScreen(); refresh(); i = DialogMenu("Layout add screen", "Choose screen to add:", 12, 60, 3, nlist, list, " Add ", " Cancel ", 0); if (i >= 0) { padj = layout->lay_adjacency_lst; adj = (XF86ConfAdjacencyPtr) XtCalloc(1, sizeof(XF86ConfAdjacencyRec)); adj->adj_screen = screens[i]; if (padj == NULL) { adj->adj_where = CONF_ADJ_ABSOLUTE; layout->lay_adjacency_lst = adj; } else { while (padj->list.next) padj = (XF86ConfAdjacencyPtr)(padj->list.next); padj->list.next = adj; adj->adj_where = CONF_ADJ_RIGHTOF; adj->adj_refscreen = XtNewString(padj->adj_screen->scrn_identifier); } } XtFree((XtPointer)list); XtFree((XtPointer)screens); } /* remove a screen */ else if (i == 1) { nlist = 0; list = NULL; screens = NULL; adj = layout->lay_adjacency_lst; while (adj) { list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*)); screens = (XF86ConfScreenPtr*)XtRealloc((XtPointer)screens, (nlist + 1) * sizeof(XF86ConfScreenPtr)); list[nlist] = adj->adj_screen->scrn_identifier; screens[nlist] = adj->adj_screen; ++nlist; adj = (XF86ConfAdjacencyPtr)(adj->list.next); } if (nlist == 0) continue; ClearScreen(); refresh(); i = DialogMenu("Layout remove screen", "Choose screen to remove:", 12, 60, 3, nlist, list, " Remove ", " Cancel ", 0); adj = padj = layout->lay_adjacency_lst; while (adj) { if (adj->adj_screen == screens[i]) { padj = (XF86ConfAdjacencyPtr)(padj->list.next); if (padj && adj->adj_where == CONF_ADJ_RIGHTOF && padj->adj_where == CONF_ADJ_RIGHTOF) { XtFree(padj->adj_refscreen); padj->adj_refscreen = XtNewString(adj->adj_refscreen); } xf86removeAdjacency(layout, adj); break; } padj = adj; adj = (XF86ConfAdjacencyPtr)(padj->list.next); } XtFree((XtPointer)list); XtFree((XtPointer)screens); } /* finish screen configuration */ else break; } LayoutFinish: if (layout->lay_adjacency_lst == NULL) { adj = (XF86ConfAdjacencyPtr)XtCalloc(1, sizeof(XF86ConfAdjacencyRec)); adj->adj_screen = XF86Config->conf_screen_lst; adj->adj_screen_str = XtNewString(XF86Config->conf_screen_lst->scrn_identifier); adj->adj_where = CONF_ADJ_ABSOLUTE; layout->lay_adjacency_lst = adj; } if (rlayout) { /* just edited this layout */ if (nmouses > 1 || nkeyboards > 1) { XF86ConfAdjacencyPtr tadj = rlayout->lay_adjacency_lst; XF86ConfInactivePtr tinac = rlayout->lay_inactive_lst; XF86ConfInputrefPtr tinp = rlayout->lay_input_lst; rlayout->lay_adjacency_lst = layout->lay_adjacency_lst; rlayout->lay_inactive_lst = layout->lay_inactive_lst; rlayout->lay_input_lst = layout->lay_input_lst; layout->lay_adjacency_lst = tadj; layout->lay_inactive_lst = tinac; layout->lay_input_lst = tinp; FreeLayout(layout); } return (0); } else { layout->lay_identifier = identifier; XF86Config->conf_layout_lst = xf86addLayout(XF86Config->conf_layout_lst, layout); } return (1); } static void ClearScreen(void) { int i, j; wattrset(stdscr, screen_attr); for (i = 0; i < LINES; i++) { wmove(stdscr, i, 0); for (j = 0; j < COLS; j++) waddch(stdscr, ACS_PLUS); } touchwin(stdscr); } static int Dialog(char *title, char * prompt, int height, int width, char *label1, char *label2, int button) { int x, x1, x2, y, key, l1len, l2len; WINDOW *dialog; x = (COLS - width) / 2; y = (LINES - height) / 2; dialog = newwin(height, width, y, x); keypad(dialog, TRUE); PaintWindow(dialog, title, 0, 0, height, width); wattrset(dialog, dialog_attr); PrintWrap(dialog, prompt, width - 3, 2, 3); l1len = strlen(label1); if (label2) l2len = strlen(label2); else { l2len = button = 0; } x1 = (width - (l1len + l2len)) / (label2 ? 3 : 2); x2 = x1 + x1 + l1len; y = height - 3; if (!button) { if (label2) PaintButton(dialog, label2, y, x2, FALSE); PaintButton(dialog, label1, y, x1, TRUE); } else { PaintButton(dialog, label1, y, x1, FALSE); if (label2) PaintButton(dialog, label2, y, x2, TRUE); } wrefresh(dialog); /*CONSTCOND*/ while (1) { key = wgetch(dialog); switch (key) { case KEY_LEFT: case KEY_RIGHT: if (!button) { if (label2) { button = 1; PaintButton(dialog, label1, y, x1, FALSE); PaintButton(dialog, label2, y, x2, TRUE); } } else { if (label2) { button = 0; PaintButton(dialog, label2, y, x2, FALSE); PaintButton(dialog, label1, y, x1, TRUE); } } wrefresh(dialog); break; case ' ': case '\r': case '\n': delwin(dialog); return button; } } /*NOTREACHED*/ } static void PaintWindow(WINDOW *win, char *title_str, int y, int x, int height, int width) { int i, j; if (title_str != NULL) { j = (width - strlen(title_str)) / 2 - 1; wattrset(win, title_attr); wmove(win, x, y); for (i = 0; i < j; i++) waddch(win, ' '); waddstr(win, title_str); for (; i < width; i++) waddch(win, ' '); } wattrset(win, 0); for (i = 1; i < height; i++) { wmove(win, y + i, x); for (j = 0; j < width; j++) if (i == height - 1 && !j) waddch(win, highlight_border_attr | ACS_LLCORNER); else if (i == height - 1 && j == width - 1) waddch(win, shadow_border_attr | ACS_LRCORNER); else if (i == height - 1) waddch(win, shadow_border_attr | ACS_HLINE); else if (!j) waddch(win, highlight_border_attr | ACS_VLINE); else if (j == width - 1) waddch(win, shadow_border_attr | ACS_VLINE); else waddch(win, dialog_attr | ' '); } } static void PaintBox(WINDOW *win, int y, int x, int height, int width) { int i, j; wattrset(win, 0); for (i = 0; i < height; i++) { wmove(win, y + i, x); for (j = 0; j < width; j++) if (!i && !j) waddch(win, shadow_border_attr | ACS_ULCORNER); else if (i == height - 1 && !j) waddch(win, shadow_border_attr | ACS_LLCORNER); else if (!i && j == width-1) waddch(win, highlight_border_attr | ACS_URCORNER); else if (i == height - 1 && j == width - 1) waddch(win, highlight_border_attr | ACS_LRCORNER); else if (!i) waddch(win, shadow_border_attr | ACS_HLINE); else if (i == height - 1) waddch(win, highlight_border_attr | ACS_HLINE); else if (!j) waddch(win, shadow_border_attr | ACS_VLINE); else if (j == width - 1) waddch(win, highlight_border_attr | ACS_VLINE); else waddch(win, dialog_attr | ' '); } } static void PaintButton(WINDOW *win, char *label, int y, int x, int selected) { int i, temp; wmove(win, y, x); wattrset(win, selected ? button_active_attr : button_inactive_attr); waddstr(win, selected ? "[" : " "); temp = strspn(label, " "); label += temp; wattrset(win, selected ? button_active_attr : button_inactive_attr); for (i = 0; i < temp; i++) waddch(win, ' '); wattrset(win, selected ? button_active_attr : button_inactive_attr); waddch(win, label[0]); wattrset(win, selected ? button_active_attr : button_inactive_attr); waddstr(win, label + 1); wattrset(win, selected ? button_active_attr : button_inactive_attr); waddstr(win, selected ? "]" : " "); wmove(win, y, x + temp + 1); } static void PrintWrap(WINDOW *win, char *prompt, int width, int y, int x) { int cur_x, cur_y, len, yinc; char *word, *tempstr = XtMalloc(strlen(prompt) + 1); cur_x = x; cur_y = y; while (*prompt == '\n') { ++cur_y; ++prompt; } strcpy(tempstr, prompt); for (word = strtok(tempstr, " \n"); word != NULL; word = strtok(NULL, " \n")) { yinc = 0; len = strlen(word); while (prompt[word - tempstr + len + yinc] == '\n') ++yinc; if (cur_x + strlen(word) > width) { cur_y++; cur_x = x; } wmove(win, cur_y, cur_x); waddstr(win, word); getyx(win, cur_y, cur_x); if (yinc) { cur_y += yinc; cur_x = x; } else cur_x++; } free(tempstr); } static int DialogMenu(char *title, char *prompt, int height, int width, int menu_height, int item_no, char **items, char *label1, char *label2, int choice) { int i, x, y, cur_x, cur_y, box_x, box_y, key = 0, button = 0, scrlx = 0, max_choice, nscroll, max_scroll, x1, x2, l1len, l2len; WINDOW *dialog, *menu; max_choice = MIN(menu_height, item_no); max_scroll = MAX(0, item_no - max_choice); x = (COLS - width) / 2; y = (LINES - height) / 2; dialog = newwin(height, width, y, x); keypad(dialog, TRUE); PaintWindow(dialog, title, 0, 0, height, width); wattrset(dialog, dialog_attr); PrintWrap(dialog, prompt, width - 3, 2, 3); l1len = strlen(label1); l2len = strlen(label2); x1 = (width - (l1len + l2len)) / 3; x2 = x1 + x1 + l1len; menu_width = width - 6; getyx(dialog, cur_y, cur_x); box_y = cur_y + 1; box_x = (width - menu_width) / 2 - 1; menu = subwin(dialog, menu_height, menu_width, y + box_y + 1, x + box_x + 1); keypad(menu, TRUE); /* draw a box around the menu items */ PaintBox(dialog, box_y, box_x, menu_height + 2, menu_width + 2); item_x = 3; if (choice > menu_height) { scrlx = MIN(max_scroll, choice); choice -= scrlx; } for (i = 0; i < max_choice; i++) PaintItem(menu, items[i + scrlx], i, i == choice); PaintScroller(menu, scrlx + choice, item_no, menu_height); wnoutrefresh(menu); x = width / 2 - 11; y = height - 3; PaintButton(dialog, label2, y, x2, FALSE); PaintButton(dialog, label1, y, x1, TRUE); wrefresh(dialog); /*CONSTCOND*/ while (1) { i = choice; key = wgetch(dialog); if (menu_height > 1 && key == KEY_PPAGE) { if (!choice) { if (scrlx) { /* Scroll menu down */ getyx(dialog, cur_y, cur_x); nscroll = max_choice > scrlx ? -scrlx : -max_choice; scrollok(menu, TRUE); wscrl(menu, nscroll); scrollok(menu, FALSE); PaintItem(menu, items[i = scrlx + nscroll], 0, TRUE); for (++i; i <= scrlx; i++) PaintItem(menu, items[i], i - (scrlx + nscroll), FALSE); scrlx += nscroll; PaintScroller(menu, scrlx + choice, item_no, menu_height); wnoutrefresh(menu); wrefresh(dialog); continue; } } i = 0; } else if (menu_height > 1 && key == KEY_NPAGE) { if (choice == max_choice - 1) { if (scrlx < max_scroll) { /* Scroll menu up */ getyx(dialog, cur_y, cur_x); nscroll = (scrlx + max_choice > max_scroll ? max_scroll : scrlx + max_choice) - scrlx; scrollok(menu, TRUE); wscrl(menu, nscroll); scrollok(menu, FALSE); scrlx += nscroll; for (i = 0; i < max_choice - 1; i++) PaintItem(menu, items[i + scrlx], i, FALSE); PaintItem(menu, items[i + scrlx], max_choice - 1, TRUE); PaintScroller(menu, scrlx + choice, item_no, menu_height); wnoutrefresh(menu); wrefresh(dialog); continue; } } i = max_choice - 1; } else if (key == KEY_UP) { if (!choice) { if (scrlx) { /* Scroll menu down */ getyx(dialog, cur_y, cur_x); if (menu_height > 1) { PaintItem(menu, items[scrlx], 0, FALSE); scrollok(menu, TRUE); wscrl(menu, - 1); scrollok(menu, FALSE); } scrlx--; PaintItem(menu, items[scrlx], 0, TRUE); PaintScroller(menu, scrlx + choice, item_no, menu_height); wnoutrefresh(menu); wrefresh(dialog); continue; } } else i = choice - 1; } else if (key == KEY_DOWN) { if (choice == max_choice - 1) { if (scrlx + choice < item_no - 1) { /* Scroll menu up */ getyx(dialog, cur_y, cur_x); if (menu_height > 1) { PaintItem(menu, items[scrlx + max_choice - 1], max_choice - 1, FALSE); scrollok(menu, TRUE); scroll(menu); scrollok(menu, FALSE); } scrlx++; PaintItem(menu, items[scrlx + max_choice - 1], max_choice - 1, TRUE); PaintScroller(menu, scrlx + choice, item_no, menu_height); wnoutrefresh(menu); wrefresh(dialog); continue; } } else i = MIN(choice + 1, item_no - 1); } if (i != choice) { getyx(dialog, cur_y, cur_x); PaintItem(menu, items[scrlx + choice], choice, FALSE); choice = i; PaintItem(menu, items[scrlx + choice], choice, TRUE); PaintScroller(menu, scrlx + choice, item_no, menu_height); wnoutrefresh(menu); wmove(dialog, cur_y, cur_x); wrefresh(dialog); continue; } switch (key) { case TAB: case KEY_LEFT: case KEY_RIGHT: if (!button) { button = 1; PaintButton(dialog, label1, y, x1, FALSE); PaintButton(dialog, label2, y, x2, TRUE); } else { button = 0; PaintButton(dialog, label2, y, x2, FALSE); PaintButton(dialog, label1, y, x1, TRUE); } wrefresh(dialog); break; case ' ': case '\r': case '\n': delwin(dialog); return (!button ? scrlx + choice : -1); default: for (i = scrlx + choice + 1; i < item_no; i++) if (toupper(items[i][0]) == toupper(key)) break; if (i == item_no) { for (i = 0; i < scrlx + choice; i++) if (toupper(items[i][0]) == toupper(key)) break; } getyx(dialog, cur_y, cur_x); if (i < item_no && i != scrlx + choice) { if (i >= scrlx && i < scrlx + max_choice) { /* it is already visible */ PaintItem(menu, items[scrlx + choice], choice, FALSE); choice = i - scrlx; } else { scrlx = MIN(i, max_scroll); choice = i - scrlx; for (i = 0; i < max_choice; i++) if (i != choice) PaintItem(menu, items[scrlx + i], i, FALSE); } PaintItem(menu, items[scrlx + choice], choice, TRUE); PaintScroller(menu, scrlx + choice, item_no, menu_height); wnoutrefresh(menu); wmove(dialog, cur_y, cur_x); wrefresh(dialog); } break; } } /*NOTREACHED*/ } static void PaintItem(WINDOW *win, char *item, int choice, int selected) { int i; wattrset(win, selected ? title_attr : dialog_attr); wmove(win, choice, 1); for (i = 1; i < menu_width; i++) waddch(win, ' '); wmove(win, choice, item_x); wattrset(win, selected ? title_attr : dialog_attr); waddstr(win, item); } static void PaintScroller(WINDOW *win, int offset, int lenght, int visible) { int i, pos; if (lenght > visible) pos = (visible / (double)lenght) * offset; else pos = offset; wattrset(win, shadow_border_attr); for (i = 0; i < visible; i++) { wmove(win, i, 0); waddch(win, i == pos ? ACS_BLOCK : ACS_VLINE); } } static int DialogCheckBox(char *title, char *prompt, int height, int width, int menu_height, int item_no, char **items, char *label1, char *label2, char *checks) { int i, x, y, cur_x, cur_y, box_x, box_y, key = 0, button = 0, choice = 0, scrlx = 0, max_choice, nscroll, max_scroll, x1, x2, l1len, l2len; WINDOW *dialog, *menu; max_choice = MIN(menu_height, item_no); max_scroll = MAX(0, item_no - max_choice); x = (COLS - width) / 2; y = (LINES - height) / 2; dialog = newwin(height, width, y, x); keypad(dialog, TRUE); PaintWindow(dialog, title, 0, 0, height, width); wattrset(dialog, dialog_attr); PrintWrap(dialog, prompt, width - 3, 2, 3); l1len = strlen(label1); l2len = strlen(label2); x1 = (width - (l1len + l2len)) / 3; x2 = x1 + x1 + l1len; menu_width = width - 6; getyx(dialog, cur_y, cur_x); box_y = cur_y + 1; box_x = (width - menu_width) / 2 - 1; menu = subwin(dialog, menu_height, menu_width, y + box_y + 1, x + box_x + 1); keypad(menu, TRUE); /* draw a box around the menu items */ PaintBox(dialog, box_y, box_x, menu_height + 2, menu_width + 2); item_x = 3; for (i = 0; i < max_choice; i++) PaintCheckItem(menu, items[i + scrlx], i, i == 0, checks[i + scrlx]); PaintScroller(menu, scrlx + choice, item_no, menu_height); wnoutrefresh(menu); x = width / 2 - 11; y = height - 3; PaintButton(dialog, label2, y, x2, FALSE); PaintButton(dialog, label1, y, x1, TRUE); wrefresh(dialog); /*CONSTCOND*/ while (1) { i = choice; key = wgetch(dialog); if (menu_height > 1 && key == KEY_PPAGE) { if (!choice) { if (scrlx) { /* Scroll menu down */ getyx(dialog, cur_y, cur_x); nscroll = max_choice > scrlx ? -scrlx : -max_choice; scrollok(menu, TRUE); wscrl(menu, nscroll); scrollok(menu, FALSE); i = scrlx + nscroll; PaintCheckItem(menu, items[i], 0, TRUE, checks[i]); for (++i; i <= scrlx; i++) PaintCheckItem(menu, items[i], i - (scrlx + nscroll), FALSE, checks[i]); scrlx += nscroll; PaintScroller(menu, scrlx + choice, item_no, menu_height); wnoutrefresh(menu); wrefresh(dialog); continue; } } i = 0; } else if (menu_height > 1 && key == KEY_NPAGE) { if (choice == max_choice - 1) { if (scrlx < max_scroll) { /* Scroll menu up */ getyx(dialog, cur_y, cur_x); nscroll = (scrlx + max_choice > max_scroll ? max_scroll : scrlx + max_choice) - scrlx; scrollok(menu, TRUE); wscrl(menu, nscroll); scrollok(menu, FALSE); scrlx += nscroll; for (i = 0; i < max_choice - 1; i++) PaintCheckItem(menu, items[i + scrlx], i, FALSE, checks[i + scrlx]); PaintCheckItem(menu, items[i + scrlx], max_choice - 1, TRUE, checks[i + scrlx]); PaintScroller(menu, scrlx + choice, item_no, menu_height); wnoutrefresh(menu); wrefresh(dialog); continue; } } i = max_choice - 1; } else if (key == KEY_UP) { if (!choice) { if (scrlx) { /* Scroll menu down */ getyx(dialog, cur_y, cur_x); if (menu_height > 1) { PaintCheckItem(menu, items[scrlx], 0, FALSE, checks[scrlx]); scrollok(menu, TRUE); wscrl(menu, - 1); scrollok(menu, FALSE); } scrlx--; PaintCheckItem(menu, items[scrlx], 0, TRUE, checks[scrlx]); PaintScroller(menu, scrlx + choice, item_no, menu_height); wnoutrefresh(menu); wrefresh(dialog); continue; } } else i = choice - 1; } else if (key == KEY_DOWN) { if (choice == max_choice - 1) { if (scrlx + choice < item_no - 1) { /* Scroll menu up */ getyx(dialog, cur_y, cur_x); if (menu_height > 1) { PaintCheckItem(menu, items[scrlx + max_choice - 1], max_choice - 1, FALSE, checks[scrlx + max_choice - 1]); scrollok(menu, TRUE); scroll(menu); scrollok(menu, FALSE); } scrlx++; PaintCheckItem(menu, items[scrlx + max_choice - 1], max_choice - 1, TRUE, checks[scrlx + max_choice - 1]); PaintScroller(menu, scrlx + choice, item_no, menu_height); wnoutrefresh(menu); wrefresh(dialog); continue; } } else i = MIN(choice + 1, item_no - 1); } if (i != choice) { getyx(dialog, cur_y, cur_x); PaintCheckItem(menu, items[scrlx + choice], choice, FALSE, checks[scrlx + choice]); choice = i; PaintCheckItem(menu, items[scrlx + choice], choice, TRUE, checks[scrlx + choice]); PaintScroller(menu, scrlx + choice, item_no, menu_height); wnoutrefresh(menu); wmove(dialog, cur_y, cur_x); wrefresh(dialog); continue; } switch (key) { case TAB: case KEY_LEFT: case KEY_RIGHT: if (!button) { button = 1; PaintButton(dialog, label1, y, x1, FALSE); PaintButton(dialog, label2, y, x2, TRUE); } else { button = 0; PaintButton(dialog, label2, y, x2, FALSE); PaintButton(dialog, label1, y, x1, TRUE); } wrefresh(dialog); break; case ' ': getyx(dialog, cur_y, cur_x); checks[scrlx + choice] = !checks[scrlx + choice]; PaintCheckItem(menu, items[scrlx + choice], choice, TRUE, checks[scrlx + choice]); wmove(dialog, cur_y, cur_x); wnoutrefresh(menu); wrefresh(dialog); break; case '\r': case '\n': delwin(dialog); return (!button ? 0 : -1); default: for (i = scrlx + choice + 1; i < item_no; i++) if (toupper(items[i][0]) == toupper(key)) break; if (i == item_no) { for (i = 0; i < scrlx + choice; i++) if (toupper(items[i][0]) == toupper(key)) break; } getyx(dialog, cur_y, cur_x); if (i < item_no && i != scrlx + choice) { if (i >= scrlx && i < scrlx + max_choice) { /* it is already visible */ PaintCheckItem(menu, items[scrlx + choice], choice, FALSE, checks[scrlx + choice]); choice = i - scrlx; } else { scrlx = MIN(i, max_scroll); choice = i - scrlx; for (i = 0; i < max_choice; i++) if (i != choice) PaintCheckItem(menu, items[scrlx + i], i, FALSE, checks[scrlx + i]); } PaintCheckItem(menu, items[scrlx + choice], choice, TRUE, checks[scrlx + choice]); PaintScroller(menu, scrlx + choice, item_no, menu_height); wnoutrefresh(menu); wmove(dialog, cur_y, cur_x); wrefresh(dialog); } break; } } /*NOTREACHED*/ } static void PaintCheckItem(WINDOW *win, char *item, int choice, int selected, int checked) { int i; wattrset(win, selected ? title_attr : dialog_attr); wmove(win, choice, 1); for (i = 1; i < menu_width; i++) waddch(win, ' '); wmove(win, choice, item_x); wattrset(win, selected ? title_attr : dialog_attr); wprintw(win, "[%c] ", checked ? 'X' : ' '); waddstr(win, item); } static char * DialogInput(char *title, char *prompt, int height, int width, char *init, char *label1, char *label2, int def_button) { int i, x, y, box_y, box_x, box_width, len, input_x = 0, scrlx = 0, key = 0, button = -1, x1, x2, l1len, l2len; char instr[1024 + 1]; WINDOW *dialog; x = (COLS - width) / 2; y = (LINES - height) / 2; dialog = newwin(height, width, y, x); keypad(dialog, TRUE); PaintWindow(dialog, title, 0, 0, height, width); wattrset(dialog, dialog_attr); PrintWrap(dialog, prompt, width - 3, 2, 3); l1len = strlen(label1); l2len = strlen(label2); x1 = (width - (l1len + l2len)) / 3; x2 = x1 + x1 + l1len; box_width = width - 6; getyx(dialog, y, x); box_y = y + 2; box_x = (width - box_width) / 2; PaintBox(dialog, y + 1, box_x - 1, 3, box_width + 2); x = width / 2 - 11; y = height - 3; PaintButton(dialog, label2, y, x2, def_button == 1); PaintButton(dialog, label1, y, x1, def_button == 0); memset(instr, '\0', sizeof(instr)); wmove(dialog, box_y, box_x); wattrset(dialog, dialog_attr); if (init) strncpy(instr, init, sizeof(instr) - 2); input_x = len = strlen(instr); if (input_x >= box_width) { scrlx = input_x - box_width + 1; input_x = box_width - 1; for (i = 0; i < box_width - 1; i++) waddch(dialog, instr[scrlx + i]); } else waddstr(dialog, instr); wmove(dialog, box_y, box_x + input_x); wrefresh(dialog); while (1) { key = wgetch(dialog); if (button == -1) { /* Input box selected */ switch (key) { case TAB: case KEY_UP: case KEY_DOWN: break; case KEY_LEFT: if (scrlx && !input_x) { --scrlx; wmove(dialog, box_y, box_x); for (i = 0; i < box_width; i++) waddch(dialog, instr[scrlx + input_x + i] ? instr[scrlx + input_x + i] : ' '); wmove(dialog, box_y, input_x + box_x); wrefresh(dialog); } else if (input_x) { wmove(dialog, box_y, --input_x + box_x); wrefresh(dialog); } continue; case KEY_RIGHT: if (input_x + scrlx < len) { if (input_x == box_width - 1) { ++scrlx; wmove(dialog, box_y, box_x); for (i = scrlx; i < scrlx + box_width; i++) waddch(dialog, instr[i] ? instr[i] : ' '); wmove(dialog, box_y, input_x + box_x); wrefresh(dialog); } else { wmove(dialog, box_y, ++input_x + box_x); wrefresh(dialog); } } continue; case KEY_BACKSPACE: case 0177: #if defined(__SCO__) || defined(__UNIXWARE__) case '\b': #endif if (input_x || scrlx) { wattrset(dialog, dialog_attr); if (scrlx + input_x < len) memmove(instr + scrlx + input_x - 1, instr + scrlx + input_x, len - (scrlx + input_x)); instr[--len] = '\0'; if (!input_x) { scrlx = scrlx < box_width - 1 ? 0 : scrlx - (box_width - 1); wmove(dialog, box_y, box_x); for (i = 0; i < box_width; i++) waddch(dialog, instr[scrlx + input_x + i] ? instr[scrlx + input_x + i] : ' '); input_x = len - scrlx; } else { wmove(dialog, box_y, --input_x + box_x); for (i = scrlx + input_x; i < len && i < scrlx + box_width; i++) waddch(dialog, instr[i]); if (i < scrlx + box_width) waddch(dialog, ' '); } wmove(dialog, box_y, input_x + box_x); wrefresh(dialog); } continue; case KEY_HOME: case CONTROL_A: wmove(dialog, box_y, box_x); if (scrlx != 0) { scrlx = 0; for (i = 0; i < box_width; i++) waddch(dialog, instr[i] ? instr[i] : ' '); } input_x = 0; wmove(dialog, box_y, box_x); wrefresh(dialog); break; case CONTROL_D: if (input_x + scrlx < len) { memmove(instr + scrlx + input_x, instr + scrlx + input_x + 1, len - (scrlx + input_x)); instr[--len] = '\0'; for (i = scrlx + input_x; i < len && i < scrlx + box_width; i++) waddch(dialog, instr[i]); if (i < scrlx + box_width) waddch(dialog, ' '); wmove(dialog, box_y, input_x + box_x); wrefresh(dialog); } break; case CONTROL_E: case KEY_END: if (box_width + scrlx < len) { input_x = box_width - 1; scrlx = len - box_width + 1; wmove(dialog, box_y, box_x); for (i = scrlx; i < scrlx + box_width; i++) waddch(dialog, instr[i] ? instr[i] : ' '); wmove(dialog, box_y, input_x + box_x); wrefresh(dialog); } else { input_x = len - scrlx; wmove(dialog, box_y, input_x + box_x); wrefresh(dialog); } break; case CONTROL_K: if (len) { for (i = input_x; i < box_width; i++) waddch(dialog, ' '); for (i = scrlx + input_x; i < len; i++) instr[i] = '\0'; len = scrlx + input_x; wmove(dialog, box_y, box_x + input_x); wrefresh(dialog); } break; default: if (key < 0x100 && isprint(key)) { if (scrlx + input_x < sizeof(instr) - 1) { wattrset(dialog, dialog_attr); if (scrlx + input_x < len) { memmove(instr + scrlx + input_x + 1, instr + scrlx + input_x, len - (scrlx + input_x)); } instr[scrlx + input_x] = key; instr[++len] = '\0'; if (input_x == box_width - 1) { scrlx++; wmove(dialog, box_y, box_x); for (i = 0; i < box_width - 1; i++) waddch(dialog, instr[scrlx + i]); } else { wmove(dialog, box_y, input_x++ + box_x); for (i = scrlx + input_x - 1; i < len && i < scrlx + box_width; i++) waddch(dialog, instr[i]); wmove(dialog, box_y, input_x + box_x); } wrefresh(dialog); } else flash(); /* Alarm user about overflow */ continue; } } } switch (key) { case KEY_UP: case KEY_LEFT: switch (button) { case -1: button = 1; /* Indicates "Cancel" button is selected */ PaintButton(dialog, label1, y, x1, FALSE); PaintButton(dialog, label2, y, x2, TRUE); wrefresh(dialog); break; case 0: button = -1; /* Indicates input box is selected */ PaintButton(dialog, label2, y, x2, FALSE); PaintButton(dialog, label1, y, x1, TRUE); wmove(dialog, box_y, box_x + input_x); wrefresh(dialog); break; case 1: button = 0; /* Indicates "OK" button is selected */ PaintButton(dialog, label2, y, x2, FALSE); PaintButton(dialog, label1, y, x1, TRUE); wrefresh(dialog); break; } break; case TAB: case KEY_DOWN: case KEY_RIGHT: switch (button) { case -1: button = 0; /* Indicates "OK" button is selected */ PaintButton(dialog, label2, y, x2, FALSE); PaintButton(dialog, label1, y, x1, TRUE); wrefresh(dialog); break; case 0: button = 1; /* Indicates "Cancel" button is selected */ PaintButton(dialog, label1, y, x1, FALSE); PaintButton(dialog, label2, y, x2, TRUE); wrefresh(dialog); break; case 1: button = -1; /* Indicates input box is selected */ PaintButton(dialog, label2, y, x2, FALSE); PaintButton(dialog, label1, y, x1, TRUE); wmove(dialog, box_y, box_x + input_x); wrefresh(dialog); break; } break; case ' ': case '\r': case '\n': delwin(dialog); return (button != 1 ? XtNewString(instr) : NULL); } } }