xenocara/xserver/hw/xfree86/utils/xorgcfg/text-mode.c
2006-11-26 18:13:41 +00:00

3408 lines
92 KiB
C

/*
* 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) || \
(strcmp((X), "keyboard") == 0))
#ifndef PROJECT_ROOT
#define PROJECT_ROOT "/usr"
#endif
#ifndef XKB_RULES_DIR
#ifndef __UNIXOS2__
#define XKB_RULES_DIR PROJECT_ROOT "/share/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;
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__)
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);
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);
}
}
}