3382 lines
		
	
	
		
			91 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			3382 lines
		
	
	
		
			91 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>
 | |
|  *
 | |
|  * $XFree86: xc/programs/Xserver/hw/xfree86/xf86cfg/text-mode.c,v 1.26 2003/11/14 02:40:22 dawes Exp $
 | |
|  */
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| #ifdef _SCO_DS
 | |
| #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"
 | |
| 
 | |
| #ifndef PROJECT_ROOT
 | |
| #define PROJECT_ROOT "/usr/X11R6"
 | |
| #endif
 | |
| 
 | |
| #ifndef __UNIXOS2__
 | |
| #define XKB_RULES_DIR PROJECT_ROOT "/lib/X11/xkb/rules"
 | |
| #else
 | |
| #define XKB_RULES_DIR XF86CONFIGDIR "/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 XF86Config 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("XFree86 Configuration",
 | |
| 		   "This program will create the XF86Config file, based on "
 | |
| 		   "menu selections you make.\n"
 | |
| 		   "\n"
 | |
| #ifndef __UNIXOS2__
 | |
| 		   "The XF86Config file usually resides in /usr/X11R6/etc/X11 "
 | |
| #else
 | |
| 		   "The XF86Config file usually resides in "XF86CONFIGDIR" "
 | |
| #endif
 | |
| 		   "or /etc/X11. A sample XF86Config file is supplied with "
 | |
| 		   "XFree86; 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 XF86Config as a base and "
 | |
| 		   "edit it for your configuration, or let this program "
 | |
| 		   "produce a base XF86Config 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 XF86Config", "Write configuration to file:",
 | |
| 			     10, 60, XF86Config_path ? XF86Config_path :
 | |
| #ifndef __UNIXOS2__
 | |
| 			     "/etc/X11/XF86Config", "  Ok  ", " Cancel ", 0);
 | |
| #else
 | |
| 			     XF86CONFIGDIR"/XF86Config", "  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", "speedo"};
 | |
| 	    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 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$";
 | |
| #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 (strcmp(input->inp_driver, "keyboard") == 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 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 "/xfree86";
 | |
| #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("keyboard");
 | |
| 		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("keyboard");
 | |
| 	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 (strcmp(input->inp_driver, "keyboard") == 0) {
 | |
| 	    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 (strcmp(iref->iref_inputdev->inp_driver, "keyboard") == 0) {
 | |
| 	    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 && strcmp(input->inp_driver, "keyboard") == 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 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 (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);
 | |
| 	}
 | |
|     }
 | |
| }
 |