aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/xfree86/utils/xorgcfg/text-mode.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/xfree86/utils/xorgcfg/text-mode.c')
-rw-r--r--xorg-server/hw/xfree86/utils/xorgcfg/text-mode.c3379
1 files changed, 3379 insertions, 0 deletions
diff --git a/xorg-server/hw/xfree86/utils/xorgcfg/text-mode.c b/xorg-server/hw/xfree86/utils/xorgcfg/text-mode.c
new file mode 100644
index 000000000..0b6e65482
--- /dev/null
+++ b/xorg-server/hw/xfree86/utils/xorgcfg/text-mode.c
@@ -0,0 +1,3379 @@
+/*
+ * 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 <pcpa@conectiva.com.br>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if defined(__SCO__) || defined(__UNIXWARE__) || \
+ (defined(sun) && defined(__SVR4)) || defined(__NetBSD__)
+#include <curses.h>
+#else
+#include <ncurses.h>
+#endif
+#include <ctype.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XKBstr.h>
+#include <X11/extensions/XKBrules.h>
+#include "cards.h"
+#include "config.h"
+#include "xf86config.h"
+#include "loader.h"
+
+#define IS_KBDDRIV(X) ((strcmp((X),"kbd") == 0))
+
+#ifndef PROJECT_ROOT
+#define PROJECT_ROOT "/usr"
+#endif
+
+#ifndef XKB_RULES_DIR
+#define XKB_RULES_DIR PROJECT_ROOT "/share/X11/xkb/rules"
+#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
+ "The "__XCONFIGFILE__" file usually resides in " PROJECT_ROOT "/etc/X11 "
+ "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 :
+ "/etc/X11/"__XCONFIGFILE__, " Ok ", " Cancel ", 0);
+
+ 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 __SCO__
+ "OsMouse",
+#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;
+ 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;
+
+ 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__) || defined(__DragonFly__)
+ str = "/dev/sysmouse";
+#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);
+
+ 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"));
+ input->inp_driver = XtNewString("kbd");
+ 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) {
+ input->inp_driver = XtNewString("kbd");
+ 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",
+ "ast",
+ "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,
+ XtNewString("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,
+ XtNewString("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);
+ }
+ }
+}