First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xfree86 / utils / xorgcfg / text-mode.c
blob0b6e65482ab5ac4ed084bf1b5d7d08fd25acfe68
1 /*
2 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
22 * Except as contained in this notice, the name of Conectiva Linux shall
23 * not be used in advertising or otherwise to promote the sale, use or other
24 * dealings in this Software without prior written authorization from
25 * Conectiva Linux.
27 * Author: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #if defined(__SCO__) || defined(__UNIXWARE__) || \
35 (defined(sun) && defined(__SVR4)) || defined(__NetBSD__)
36 #include <curses.h>
37 #else
38 #include <ncurses.h>
39 #endif
40 #include <ctype.h>
41 #include <X11/Xlib.h>
42 #include <X11/extensions/XKBstr.h>
43 #include <X11/extensions/XKBrules.h>
44 #include "cards.h"
45 #include "config.h"
46 #include "xf86config.h"
47 #include "loader.h"
49 #define IS_KBDDRIV(X) ((strcmp((X),"kbd") == 0))
51 #ifndef PROJECT_ROOT
52 #define PROJECT_ROOT "/usr"
53 #endif
55 #ifndef XKB_RULES_DIR
56 #define XKB_RULES_DIR PROJECT_ROOT "/share/X11/xkb/rules"
57 #endif
59 #define CONTROL_A 1
60 #define CONTROL_D 4
61 #define CONTROL_E 5
62 #define CONTROL_K 11
63 #define TAB 9
64 #define MIN(a, b) ((a) < (b) ? (a) : (b))
65 #define MAX(a, b) ((a) > (b) ? (a) : (b))
67 void TextMode(void);
69 static void ClearScreen(void);
70 static void PaintWindow(WINDOW*, char*, int, int, int, int);
71 static void PaintBox(WINDOW*, int, int, int, int);
72 static void PaintButton(WINDOW*, char*, int, int, int);
73 static void PrintWrap(WINDOW*, char*, int, int, int);
74 static int Dialog(char*, char*, int, int, char*, char*, int);
75 static void PaintItem(WINDOW*, char*, int, int);
76 static int DialogMenu(char*, char*, int, int, int, int, char**, char*, char*, int);
77 static void PaintCheckItem(WINDOW*, char*, int, int, int);
78 static int DialogCheckBox(char*, char*, int, int, int, int, char**, char*, char*, char*);
79 static char *DialogInput(char*, char*, int, int, char*, char*, char*, int);
80 static void PaintScroller(WINDOW*, int, int, int);
82 static int MouseConfig(void);
83 static int KeyboardConfig(void);
84 static int MonitorConfig(void);
85 static int CardConfig(void);
86 static int ScreenConfig(void);
87 static int LayoutConfig(void);
88 static int WriteXF86Config(void);
90 static XF86ConfLayoutPtr CopyLayout(XF86ConfLayoutPtr);
91 static XF86ConfAdjacencyPtr CopyAdjacency(XF86ConfAdjacencyPtr);
92 static XF86ConfInputrefPtr CopyInputref(XF86ConfInputrefPtr);
93 static XF86ConfInactivePtr CopyInactive(XF86ConfInactivePtr);
94 static void FreeLayout(XF86ConfLayoutPtr);
96 extern int string_to_parser_range(char*, parser_range*, int);
97 #define PARSER_RANGE_SIZE 256
98 /* string must have at least 256 bytes */
99 extern int parser_range_to_string(char*, parser_range*, int);
101 static Bool newconfig;
103 static chtype screen_attr = A_NORMAL;
104 static chtype dialog_attr = A_REVERSE;
105 static chtype highlight_border_attr = A_REVERSE;
106 static chtype shadow_border_attr = A_REVERSE;
107 static chtype title_attr = A_NORMAL;
108 static chtype button_active_attr = A_NORMAL;
109 static chtype button_inactive_attr = A_NORMAL;
110 static int menu_width, item_x;
111 static char Edit[] = "Edit ";
113 static char *main_menu[] = {
114 #define CONF_MOUSE 0
115 "Configure mouse",
116 #define CONF_KEYBOARD 1
117 "Configure keyboard",
118 #define CONF_MONITOR 2
119 "Configure monitor",
120 #define CONF_CARD 3
121 "Configure card",
122 #define CONF_SCREEN 4
123 "Configure screen",
124 #define CONF_LAYOUT 5
125 "Configure layout",
126 #define CONF_FINISH 6
127 "Write "__XCONFIGFILE__" and quit",
128 #define CONF_QUIT 7
129 "Quit",
132 void
133 TextMode(void)
135 static int first = 1;
136 int i, choice = CONF_MOUSE;
138 #ifdef USE_MODULES
139 if (!nomodules)
140 LoaderInitializeOptions();
141 #endif
142 initscr();
143 noecho();
144 nonl();
145 keypad(stdscr, TRUE);
147 if (first) {
148 const char *filename;
150 first = 0;
152 if (has_colors()) {
153 start_color();
154 init_pair(1, COLOR_BLACK, COLOR_BLACK);
155 screen_attr = A_BOLD | COLOR_PAIR(1);
157 init_pair(2, COLOR_BLACK, COLOR_WHITE);
158 dialog_attr = COLOR_PAIR(2);
160 init_pair(3, COLOR_BLACK, COLOR_WHITE);
161 shadow_border_attr = A_BOLD | COLOR_PAIR(3);
163 init_pair(4, COLOR_WHITE, COLOR_WHITE);
164 highlight_border_attr = A_BOLD | COLOR_PAIR(4);
166 init_pair(5, COLOR_WHITE, COLOR_BLUE);
167 title_attr = A_BOLD | COLOR_PAIR(5);
168 button_active_attr = title_attr;
170 init_pair(6, COLOR_WHITE, COLOR_BLACK);
171 button_inactive_attr = A_BOLD | COLOR_PAIR(6);
174 if ((filename = xf86openConfigFile(getuid() == 0 ?
175 CONFPATH : USER_CONFPATH,
176 XF86Config_path, NULL)) != NULL) {
177 XF86Config_path = (char *)filename;
178 if ((XF86Config = xf86readConfigFile()) == NULL) {
179 ClearScreen();
180 refresh();
181 Dialog("Configuration error",
182 "Error parsing configuration file.",
183 7, 50, " Ok ", NULL, 0);
186 if (XF86Config == NULL) {
187 XF86Config = (XF86ConfigPtr)XtCalloc(1, sizeof(XF86ConfigRec));
188 newconfig = True;
190 else
191 newconfig = False;
194 ClearScreen();
195 refresh();
197 /*CONSTCOND*/
198 while (1) {
199 int cancel = FALSE;
201 ClearScreen();
202 refresh();
203 if (Dialog( __XSERVERNAME__" Configuration",
204 "This program will create the "__XCONFIGFILE__" file, based on "
205 "menu selections you make.\n"
206 "\n"
207 #if defined(__SCO__) || defined(__UNIXWARE__)
208 "The "__XCONFIGFILE__" file usually resides in /etc. A "
209 "sample "__XCONFIGFILE__" file is supplied with "
210 #else
211 "The "__XCONFIGFILE__" file usually resides in " PROJECT_ROOT "/etc/X11 "
212 "or /etc/X11. A sample "__XCONFIGFILE__" file is supplied with "
213 #endif
214 __XSERVERNAME__"; it is configured for a standard VGA card and "
215 "monitor with 640x480 resolution. This program will ask for "
216 "a pathname when it is ready to write the file.\n"
217 "\n"
218 "You can either take the sample "__XCONFIGFILE__" as a base and "
219 "edit it for your configuration, or let this program "
220 "produce a base "__XCONFIGFILE__" file for your configuration and "
221 "fine-tune it.",
222 20, 60, " Ok ", " Cancel ", 0) != 0)
223 break;
225 while (!cancel) {
226 ClearScreen();
227 refresh();
228 switch (DialogMenu("Main menu",
229 "Choose one of the options:",
230 17, 60, 8, sizeof(main_menu) /
231 sizeof(main_menu[0]), main_menu,
232 " Ok ", " Cancel ", choice)) {
233 case CONF_MOUSE:
234 i = MouseConfig();
235 if (i > 0 && choice == CONF_MOUSE)
236 choice = CONF_KEYBOARD;
237 else if (i == 0)
238 choice = CONF_MOUSE;
239 break;
240 case CONF_KEYBOARD:
241 i = KeyboardConfig();
242 if (i > 0 && choice <= CONF_KEYBOARD)
243 choice = CONF_MONITOR;
244 else if (i == 0)
245 choice = CONF_KEYBOARD;
246 break;
247 case CONF_MONITOR:
248 i = MonitorConfig();
249 if (i > 0 && choice <= CONF_MONITOR)
250 choice = CONF_CARD;
251 else if (i == 0)
252 choice = CONF_MONITOR;
253 break;
254 case CONF_CARD:
255 i = CardConfig();
256 if (i > 0 && choice <= CONF_CARD)
257 choice = CONF_SCREEN;
258 else if (i == 0)
259 choice = CONF_CARD;
260 break;
261 case CONF_SCREEN:
262 i = ScreenConfig();
263 if (i > 0 && choice <= CONF_SCREEN)
264 choice = CONF_LAYOUT;
265 else if (i == 0)
266 choice = CONF_SCREEN;
267 break;
268 case CONF_LAYOUT:
269 i = LayoutConfig();
270 if (i > 0 && choice <= CONF_LAYOUT)
271 choice = CONF_FINISH;
272 else if (i == 0)
273 choice = CONF_LAYOUT;
274 break;
275 case CONF_FINISH:
276 if (WriteXF86Config() < 0)
277 break;
278 /*FALLTROUGH*/
279 case CONF_QUIT:
280 endwin();
281 exit(0);
282 default:
283 cancel = TRUE;
284 break;
289 endwin();
292 static int
293 WriteXF86Config(void)
295 char *xf86config;
297 ClearScreen();
298 refresh();
299 xf86config = DialogInput("Write "__XCONFIGFILE__, "Write configuration to file:",
300 10, 60, XF86Config_path ? XF86Config_path :
301 "/etc/X11/"__XCONFIGFILE__, " Ok ", " Cancel ", 0);
303 if (xf86config == NULL)
304 return (-1);
306 if (newconfig) {
307 if (XF86Config->conf_modules == NULL) {
308 static char *modules[] = {"extmod", "glx", "dri", "dbe",
309 "record", "xtrap", "type1"};
310 XF86LoadPtr load;
311 int i;
313 XF86Config->conf_modules = (XF86ConfModulePtr)
314 XtCalloc(1, sizeof(XF86ConfModuleRec));
316 XF86Config->conf_modules->mod_comment =
317 XtNewString("\tLoad \"freetype\"\n"
318 "\t# Load \"xtt\"\n");
320 for (i = 0; i < sizeof(modules) / sizeof(modules[0]); i++) {
321 load = (XF86LoadPtr)XtCalloc(1, sizeof(XF86LoadRec));
322 load->load_name = XtNewString(modules[i]);
323 XF86Config->conf_modules->mod_load_lst =
324 xf86addModule(XF86Config->conf_modules->mod_load_lst, load);
329 if (!xf86writeConfigFile(xf86config, XF86Config)) {
330 char msg[1024];
332 XmuSnprintf(msg, sizeof(msg), "Failed to write configuration file %s.",
333 xf86config);
334 ClearScreen();
335 refresh();
336 (void)Dialog("Write failed!", msg, 8, 60, " Ok ", NULL, 0);
337 XtFree(xf86config);
338 return (-1);
340 XtFree(xf86config);
342 return (1);
345 static char *protocols[] = {
346 #ifdef __SCO__
347 "OsMouse",
348 #endif
349 #ifdef WSCONS_SUPPORT
350 "wsmouse",
351 #endif
352 "Auto",
353 "SysMouse",
354 "MouseSystems",
355 "BusMouse",
356 "PS/2",
357 "Microsoft",
358 #ifndef __FreeBSD__
359 "ImPS/2",
360 "ExplorerPS/2",
361 "GlidePointPS/2",
362 "MouseManPlusPS/2",
363 "NetMousePS/2",
364 "NetScrollPS/2",
365 "ThinkingMousePS/2",
366 #endif
367 "AceCad",
368 "GlidePoint",
369 "IntelliMouse",
370 "Logitech",
371 "MMHitTab",
372 "MMSeries",
373 "MouseMan",
374 "ThinkingMouse",
377 static int
378 MouseConfig(void)
380 int i, nlist, def, proto, emul;
381 char **list = NULL, *device, *str;
382 XF86ConfInputPtr *inputs = NULL;
383 XF86ConfInputPtr input = XF86Config->conf_input_lst;
384 XF86OptionPtr option;
386 nlist = 0;
387 while (input) {
388 if (strcmp(input->inp_driver, "mouse") == 0) {
389 list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*));
390 list[nlist] = XtMalloc(sizeof(Edit) +
391 strlen(input->inp_identifier) + 1);
392 sprintf(list[nlist], "%s%s", Edit, input->inp_identifier);
393 inputs = (XF86ConfInputPtr*)XtRealloc((XtPointer)inputs, (nlist + 1) *
394 sizeof(XF86ConfInputPtr));
395 inputs[nlist] = input;
396 ++nlist;
398 input = (XF86ConfInputPtr)(input->list.next);
401 input = NULL;
403 if (nlist) {
404 list = (char**)XtRealloc((XtPointer)list, (nlist + 2) * sizeof(char*));
405 list[nlist++] = XtNewString("Add new mouse");
406 if (nlist == 2) {
407 i = strlen("Remove ") + strlen(inputs[0]->inp_identifier) + 1;
408 list[nlist] = XtMalloc(i);
409 XmuSnprintf(list[nlist], i, "Remove %s", inputs[0]->inp_identifier);
410 ++nlist;
412 else
413 list[nlist++] = XtNewString("Remove mouse");
414 ClearScreen();
415 refresh();
416 i = DialogMenu("Mouse configuration",
417 "You can edit or remove a previously configured mouse, "
418 "or add a new one.", 14, 60, 4, nlist, list,
419 " Ok ", " Cancel ", 0);
420 if (i < 0) {
421 for (i = 0; i < nlist; i++)
422 XtFree(list[i]);
423 XtFree((XtPointer)list);
424 XtFree((XtPointer)inputs);
425 return (-1);
427 if (nlist > 2 && i == nlist - 1) {
428 if (nlist > 3) {
429 for (i = 0; i < nlist - 2; i++) {
430 /* XXX Remove the "Edit " from list entries */
431 memmove(list[i], list[i] + sizeof(Edit) - 1,
432 strlen(list[i]) - sizeof(Edit) + 2);
434 ClearScreen();
435 refresh();
436 i = DialogMenu("Remove mouse",
437 "Select which mouse to remove",
438 13, 60, 4, nlist - 2, list,
439 " Remove ", " Cancel ", 0);
440 if (i < 0) {
441 for (i = 0; i < nlist; i++)
442 XtFree(list[i]);
443 XtFree((XtPointer)list);
444 XtFree((XtPointer)inputs);
445 return (-1);
447 input = inputs[i];
449 else
450 input = inputs[0];
451 for (i = 0; i < nlist; i++)
452 XtFree(list[i]);
453 XtFree((XtPointer)list);
454 XtFree((XtPointer)inputs);
455 xf86removeInput(XF86Config, input);
456 return (0);
458 if (i < nlist - 2)
459 input = inputs[i];
461 for (i = 0; i < nlist; i++)
462 XtFree(list[i]);
463 XtFree((XtPointer)list);
464 XtFree((XtPointer)inputs);
466 if (input == NULL) {
467 char label[32];
469 input = (XF86ConfInputPtr)XtCalloc(1, sizeof(XF86ConfInputRec));
470 XmuSnprintf(label, sizeof(label), "Mouse%d", nlist ? nlist - 2 : 0);
471 ClearScreen();
472 refresh();
473 input->inp_identifier =
474 DialogInput("Mouse identifier",
475 "Enter an identifier for your mouse definition:",
476 11, 40, label,
477 " Next >>", " Cancel ", 0);
478 if (input->inp_identifier == NULL) {
479 XtFree((XtPointer)input);
480 return (-1);
484 def = 0;
485 option = xf86findOption(input->inp_option_lst, "Protocol");
486 if (option)
487 for (i = 0; i < sizeof(protocols)/sizeof(protocols[0]); i++)
488 if (strcasecmp(option->opt_val, protocols[i]) == 0) {
489 def = i;
490 break;
493 ClearScreen();
494 refresh();
495 i = DialogMenu("Select mouse protocol",
496 "If you have a serial mouse, it probably will work with "
497 "the \"Auto\" protocol. But, if it is an old serial "
498 "mouse probably it is not PNP; in that case, most serial "
499 "mouses understand the \"Microsoft\" protocol.",
500 19, 60, 7, sizeof(protocols) /
501 sizeof(protocols[0]), protocols, " Next >>", " Cancel ", def);
502 if (i < 0) {
503 if (input->inp_driver == NULL) {
504 XtFree(input->inp_driver);
505 XtFree((XtPointer)input);
507 return (i);
509 proto = i;
511 def = 0;
512 if (input->inp_driver) {
513 option = xf86findOption(input->inp_option_lst, "Emulate3Buttons");
514 def = option ? 0 : 1;
516 ClearScreen();
517 refresh();
518 i = Dialog("Mouse 3 buttons emulation",
519 "If your mouse has only two buttons, it is recommended that "
520 "you enable Emulate3Buttons.\n"
521 "\n"
522 "Do you want to enable Emulate3Buttons?",
523 10, 60, " Yes ", " No ", def);
524 if (i < 0)
525 return (i);
526 emul = !i;
528 str = NULL;
529 option = xf86findOption(input->inp_option_lst, "Device");
530 if (option)
531 str = option->opt_val;
532 if (str == NULL)
533 #ifdef WSCONS_SUPPORT
534 str = "/dev/wsmouse";
535 #elif defined(__FreeBSD__) || defined(__DragonFly__)
536 str = "/dev/sysmouse";
537 #elif defined(__linux__)
538 str = "/dev/input/mice";
539 #else
540 str = "/dev/mouse";
541 #endif
543 ClearScreen();
544 refresh();
545 device = DialogInput("Select mouse device",
546 "Enter mouse device:", 10, 40, str,
547 " Finish ", " Cancel ", 0);
548 if (device == NULL) {
549 if (input->inp_driver == NULL) {
550 XtFree(input->inp_driver);
551 XtFree((XtPointer)input);
553 return (-1);
556 /* Finish mouse configuration */
557 option = xf86findOption(input->inp_option_lst, "Protocol");
558 if (option) {
559 XtFree((XtPointer)option->opt_val);
560 option->opt_val = XtNewString(protocols[proto]);
562 else
563 input->inp_option_lst = xf86addNewOption(input->inp_option_lst,
564 XtNewString("Protocol"), XtNewString(protocols[proto]));
566 option = xf86findOption(input->inp_option_lst, "Emulate3Buttons");
567 if (option && !emul) {
568 xf86removeOption(&input->inp_option_lst, "Emulate3Buttons");
570 else if (option == NULL && emul)
571 input->inp_option_lst = xf86addNewOption(input->inp_option_lst,
572 XtNewString("Emulate3Buttons"), NULL);
574 option = xf86findOption(input->inp_option_lst, "Device");
575 if (option) {
576 XtFree((XtPointer)option->opt_val);
577 option->opt_val = device;
579 else
580 input->inp_option_lst = xf86addNewOption(input->inp_option_lst,
581 XtNewString("Device"), device);
583 if (input->inp_driver == NULL) {
584 input->inp_driver = XtNewString("mouse");
585 XF86Config->conf_input_lst =
586 xf86addInput(XF86Config->conf_input_lst, input);
589 return (1);
592 static int
593 KeyboardConfig(void)
595 int i;
596 char *rulesfile;
597 static int first = 1;
598 static XkbRF_RulesPtr rules;
599 static char **models, **layouts;
600 XF86ConfInputPtr *inputs = NULL, input = XF86Config->conf_input_lst;
601 char **list = NULL, *model, *layout;
602 int nlist, def;
603 XF86OptionPtr option;
605 nlist = 0;
606 while (input) {
607 if (IS_KBDDRIV(input->inp_driver)) {
608 list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*));
609 list[nlist] = XtMalloc(sizeof(Edit) +
610 strlen(input->inp_identifier) + 1);
611 sprintf(list[nlist], "%s%s", Edit, input->inp_identifier);
612 inputs = (XF86ConfInputPtr*)XtRealloc((XtPointer)inputs, (nlist + 1) *
613 sizeof(XF86ConfInputPtr));
614 inputs[nlist] = input;
615 ++nlist;
617 input = (XF86ConfInputPtr)(input->list.next);
620 input = NULL;
622 if (nlist) {
623 list = (char**)XtRealloc((XtPointer)list, (nlist + 2) * sizeof(char*));
624 list[nlist++] = XtNewString("Add new keyboard");
625 if (nlist == 2) {
626 i = strlen("Remove ") + strlen(inputs[0]->inp_identifier) + 1;
627 list[nlist] = XtMalloc(i);
628 XmuSnprintf(list[nlist], i, "Remove %s", inputs[0]->inp_identifier);
629 ++nlist;
631 else
632 list[nlist++] = XtNewString("Remove keyboard");
633 ClearScreen();
634 refresh();
635 i = DialogMenu("Keyboard configuration",
636 "You can edit or remove a previously configured "
637 "keyboard, or add a new one.", 14, 60, 4, nlist, list,
638 " Ok ", " Cancel ", 0);
639 if (i < 0) {
640 for (i = 0; i < nlist; i++)
641 XtFree(list[i]);
642 XtFree((XtPointer)list);
643 XtFree((XtPointer)inputs);
644 return (-1);
646 if (nlist > 2 && i == nlist - 1) {
647 if (nlist > 3) {
648 for (i = 0; i < nlist - 2; i++) {
649 /* XXX Remove the "Edit " from list entries */
650 memmove(list[i], list[i] + sizeof(Edit) - 1,
651 strlen(list[i]) - sizeof(Edit) + 2);
653 ClearScreen();
654 refresh();
655 i = DialogMenu("Remove keyboard",
656 "Select which keyboard to remove",
657 13, 60, 4, nlist - 2, list,
658 " Remove ", " Cancel ", 0);
659 if (i < 0) {
660 for (i = 0; i < nlist; i++)
661 XtFree(list[i]);
662 XtFree((XtPointer)list);
663 XtFree((XtPointer)inputs);
664 return (-1);
666 input = inputs[i];
668 else
669 input = inputs[0];
670 for (i = 0; i < nlist; i++)
671 XtFree(list[i]);
672 XtFree((XtPointer)list);
673 XtFree((XtPointer)inputs);
674 xf86removeInput(XF86Config, input);
675 return (0);
677 if (i < nlist - 2)
678 input = inputs[i];
680 for (i = 0; i < nlist; i++)
681 XtFree(list[i]);
682 XtFree((XtPointer)list);
683 XtFree((XtPointer)inputs);
685 if (input == NULL) {
686 char label[32];
688 input = (XF86ConfInputPtr)XtCalloc(1, sizeof(XF86ConfInputRec));
689 XmuSnprintf(label, sizeof(label), "Keyboard%d", nlist ? nlist - 2 : 0);
690 ClearScreen();
691 refresh();
692 input->inp_identifier =
693 DialogInput("Keyboard identifier",
694 "Enter an identifier for your keyboard definition:",
695 11, 40, label,
696 " Next >>", " Cancel ", 0);
697 if (input->inp_identifier == NULL) {
698 XtFree((XtPointer)input);
699 return (-1);
703 if (first) {
704 first = 0;
705 #ifdef XFREE98_XKB
706 rulesfile = XKB_RULES_DIR "/xfree98";
707 #else
708 rulesfile = XKB_RULES_DIR "/"__XKBDEFRULES__;
709 #endif
710 rules = XkbRF_Load(rulesfile, "", True, False);
711 if (rules == NULL) {
712 ClearScreen();
713 refresh();
714 Dialog("Configuration error",
715 "XKB rules file not found.\n"
716 "\n"
717 "Keyboard XKB options will be set to default values.",
718 10, 50, " Ok ", NULL, 0);
719 if (input->inp_driver == NULL) {
720 input->inp_option_lst =
721 xf86addNewOption(input->inp_option_lst,
722 XtNewString("XkbModel"), XtNewString("pc101"));
723 input->inp_option_lst =
724 xf86addNewOption(input->inp_option_lst,
725 XtNewString("XkbLayout"), XtNewString("us"));
726 input->inp_driver = XtNewString("kbd");
727 XF86Config->conf_input_lst =
728 xf86addInput(XF86Config, input);
730 return (0);
732 models = (char**)XtMalloc(sizeof(char*) * rules->models.num_desc);
733 for (i = 0; i < rules->models.num_desc; i++)
734 models[i] = XtNewString(rules->models.desc[i].desc);
735 layouts = (char**)XtMalloc(sizeof(char*) * rules->layouts.num_desc);
736 for (i = 0; i < rules->layouts.num_desc; i++)
737 layouts[i] = XtNewString(rules->layouts.desc[i].desc);
739 else if (rules == NULL)
740 return (-1);
742 def = 0;
743 option = xf86findOption(input->inp_option_lst, "XkbModel");
744 if (option) {
745 for (i = 0; i < rules->models.num_desc; i++)
746 if (strcasecmp(option->opt_val, rules->models.desc[i].name) == 0) {
747 def = i;
748 break;
751 ClearScreen();
752 refresh();
753 i = DialogMenu("Keyboard model",
754 "Please select one of the following keyboard types that is "
755 "the better description of your keyboard. If nothing really "
756 "matches, choose \"Generic 101-key PC\".\n",
757 20, 60, 9, rules->models.num_desc,
758 models, " Next >>", " Cancel ", def);
759 if (i < 0)
760 return (i);
761 model = rules->models.desc[i].name;
763 def = 0;
764 option = xf86findOption(input->inp_option_lst, "XkbLayout");
765 if (option) {
766 for (i = 0; i < rules->layouts.num_desc; i++)
767 if (strcasecmp(option->opt_val, rules->layouts.desc[i].name) == 0) {
768 def = i;
769 break;
772 ClearScreen();
773 refresh();
774 i = DialogMenu("Keyboard layout",
775 "Select keyboard layout:",
776 20, 60, 11, rules->layouts.num_desc,
777 layouts, " Finish ", " Cancel ", def);
778 if (i < 0)
779 return (i);
780 layout = rules->layouts.desc[i].name;
782 /* Finish keyboard configuration */
783 option = xf86findOption(input->inp_option_lst, "XkbModel");
784 if (option) {
785 XtFree((XtPointer)option->opt_val);
786 option->opt_val = XtNewString(model);
788 else
789 input->inp_option_lst = xf86addNewOption(input->inp_option_lst,
790 XtNewString("XkbModel"), XtNewString(model));
792 option = xf86findOption(input->inp_option_lst, "XkbLayout");
793 if (option) {
794 XtFree((XtPointer)option->opt_val);
795 option->opt_val = XtNewString(layout);
797 else
798 input->inp_option_lst = xf86addNewOption(input->inp_option_lst,
799 XtNewString("XkbLayout"), XtNewString(layout));
801 if (input->inp_driver == NULL) {
802 input->inp_driver = XtNewString("kbd");
803 XF86Config->conf_input_lst =
804 xf86addInput(XF86Config->conf_input_lst, input);
807 return (1);
810 static char *hsync[] = {
811 #define CONF_MONITOR_HSYNC 0
812 "Enter your own horizontal sync range",
813 "31.5; Standard VGA, 640x480 @ 60 Hz",
814 "31.5 - 35.1; Super VGA, 800x600 @ 56 Hz",
815 "31.5, 35.5; 8514 Compatible, 1024x768 @ 87 Hz interlaced (no 800x600)",
816 "31.5, 35.15, 35.5; Super VGA, 1024x768 @ 87 Hz int., 800x600 @ 56 Hz",
817 "31.5 - 37.9; Extended Super VGA, 800x600 @ 60 Hz, 640x480 @ 72 Hz",
818 "31.5 - 48.5; Non-Interlaced SVGA, 1024x768 @ 60 Hz, 800x600 @ 72 Hz",
819 "31.5 - 57.0; High Frequency SVGA, 1024x768 @ 70 Hz",
820 "31.5 - 64.3; Monitor that can do 1280x1024 @ 60 Hz",
821 "31.5 - 79.0; Monitor that can do 1280x1024 @ 74 Hz",
822 "31.5 - 82.0; Monitor that can do 1280x1024 @ 76 Hz",
823 "31.5 - 92.0; Monitor that can do 1280x1024 @ 85 Hz",
824 "31.5 - 108.0; Monitor that can do 1600x1200 @ 85 Hz",
825 "31.5 - 128.5; Monitor that can do 1920x1440 @ 85 Hz",
826 "31.5 - 137.0; Monitor that can do 2048x1536 @ 85 Hz"
829 static char *vrefresh[] = {
830 #define CONF_MONITOR_VREFRESH 0
831 "Enter your own vertical sync range",
832 "50 - 70",
833 "50 - 90",
834 "50 - 100",
835 "40 - 150",
838 static int
839 MonitorConfig(void)
841 int i;
842 XF86ConfMonitorPtr *monitors = NULL, monitor = XF86Config->conf_monitor_lst;
843 char **list = NULL, *identifier = NULL, *tmp;
844 int nlist, def;
845 char hsync_str[256], vrefresh_str[256];
847 hsync_str[0] = vrefresh_str[0] = '\0';
848 nlist = 0;
849 while (monitor) {
850 list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*));
851 list[nlist] = XtMalloc(sizeof(Edit) +
852 strlen(monitor->mon_identifier) + 1);
853 sprintf(list[nlist], "%s%s", Edit, monitor->mon_identifier);
854 monitors = (XF86ConfMonitorPtr*)XtRealloc((XtPointer)monitors, (nlist + 1) *
855 sizeof(XF86ConfMonitorPtr));
856 monitors[nlist] = monitor;
857 ++nlist;
858 monitor = (XF86ConfMonitorPtr)(monitor->list.next);
861 monitor = NULL;
863 if (nlist) {
864 list = (char**)XtRealloc((XtPointer)list, (nlist + 2) * sizeof(char*));
865 list[nlist++] = XtNewString("Add new monitor");
866 if (nlist == 2) {
867 i = strlen("Remove ") + strlen(monitors[0]->mon_identifier) + 1;
868 list[nlist] = XtMalloc(i);
869 XmuSnprintf(list[nlist], i, "Remove %s", monitors[0]->mon_identifier);
870 ++nlist;
872 else
873 list[nlist++] = XtNewString("Remove monitor");
874 ClearScreen();
875 refresh();
876 i = DialogMenu("Monitor configuration",
877 "You can edit or remove a previously configured "
878 "monitor, or add a new one.", 14, 60, 4, nlist, list,
879 " Ok ", " Cancel ", 0);
880 if (i < 0) {
881 for (i = 0; i < nlist; i++)
882 XtFree(list[i]);
883 XtFree((XtPointer)list);
884 XtFree((XtPointer)monitors);
885 return (-1);
887 if (nlist > 2 && i == nlist - 1) {
888 if (nlist > 3) {
889 for (i = 0; i < nlist - 2; i++) {
890 /* XXX Remove the "Edit " from list entries */
891 memmove(list[i], list[i] + sizeof(Edit) - 1,
892 strlen(list[i]) - sizeof(Edit) + 2);
894 ClearScreen();
895 refresh();
896 i = DialogMenu("Remove monitor",
897 "Select which monitor to remove",
898 13, 60, 4, nlist - 2, list,
899 " Remove ", " Cancel ", 0);
900 if (i < 0) {
901 for (i = 0; i < nlist; i++)
902 XtFree(list[i]);
903 XtFree((XtPointer)list);
904 XtFree((XtPointer)monitors);
905 return (-1);
907 monitor = monitors[i];
909 else
910 monitor = monitors[0];
911 for (i = 0; i < nlist; i++)
912 XtFree(list[i]);
913 XtFree((XtPointer)list);
914 XtFree((XtPointer)monitors);
915 xf86removeMonitor(XF86Config, monitor);
916 return (0);
918 if (i < nlist - 2)
919 monitor = monitors[i];
921 for (i = 0; i < nlist; i++)
922 XtFree(list[i]);
923 XtFree((XtPointer)list);
924 XtFree((XtPointer)monitors);
926 if (monitor == NULL) {
927 char label[32];
929 monitor = (XF86ConfMonitorPtr)XtCalloc(1, sizeof(XF86ConfMonitorRec));
930 XmuSnprintf(label, sizeof(label), "Monitor%d", nlist ? nlist - 2 : 0);
931 ClearScreen();
932 refresh();
933 identifier =
934 DialogInput("Monitor identifier",
935 "Enter an identifier for your monitor definition:",
936 11, 40, label,
937 " Next >>", " Cancel ", 0);
938 if (identifier == NULL) {
939 XtFree((XtPointer)monitor);
940 return (-1);
944 if (monitor->mon_identifier == NULL) {
945 ClearScreen();
946 refresh();
947 i = Dialog("Monitor configuration",
948 "Now we want to set the specifications of the monitor. The "
949 "two critical parameters are the vertical refresh rate, which "
950 "is the rate at which the whole screen is refreshed, and most "
951 "importantly the horizontal sync rate, which is the rate at "
952 "which scanlines are displayed.\n"
953 "\n"
954 "The valid range for horizontal sync and vertical sync should "
955 "be documented in the manual of your monitor.",
956 15, 60, " Next >>", " Cancel ", 0);
957 if (i != 0) {
958 XtFree(identifier);
959 XtFree((XtPointer)monitor);
960 return (-1);
964 def = 0;
965 if (monitor->mon_identifier) {
966 int len;
968 parser_range_to_string(hsync_str, &(monitor->mon_hsync[0]),
969 monitor->mon_n_hsync);
970 len = strlen(hsync_str);
971 for (i = 1; i < sizeof(hsync) / sizeof(hsync[0]); i++) {
972 tmp = strchr(hsync[i], ';');
973 if (strncmp(hsync_str, hsync[i], len) == 0) {
974 def = i;
975 break;
979 if (hsync_str[0] == '\0')
980 strcpy(hsync_str, "31.5");
982 ClearScreen();
983 refresh();
984 i = DialogMenu("Monitor HorizSync",
985 "You must indicate the horizontal sync range of your "
986 "monitor. You can either select one of the predefined "
987 "ranges below that correspond to industry-standard monitor "
988 "types, or give a specific range.",
989 22, 78, 11, sizeof(hsync) /
990 sizeof(hsync[0]), hsync, " Next >>", " Cancel ", def);
991 if (i < 0) {
992 if (monitor->mon_identifier == NULL) {
993 XtFree(identifier);
994 XtFree((XtPointer)monitor);
996 return (-1);
998 if (i == CONF_MONITOR_HSYNC) {
999 ClearScreen();
1000 refresh();
1001 tmp = DialogInput("Monitor HorizSync",
1002 "Please enter the horizontal sync range of your "
1003 "monitor, in the format used in the table of monitor "
1004 "types above. You can either specify one or more "
1005 "continuous ranges (e.g. 15-25, 30-50), or one or more "
1006 "fixed sync frequencies.\n"
1007 "\n"
1008 "Horizontal sync range:", 16, 62, hsync_str,
1009 " Ok ", " Cancel ", def);
1010 if (tmp == NULL) {
1011 if (monitor->mon_identifier == NULL) {
1012 XtFree(identifier);
1013 XtFree((XtPointer)monitor);
1015 return (-1);
1017 XmuSnprintf(hsync_str, sizeof(hsync_str), "%s", tmp);
1018 XtFree(tmp);
1020 else {
1021 tmp = strchr(hsync[i], ';');
1022 strncpy(hsync_str, hsync[i], tmp - hsync[i]);
1023 hsync_str[tmp - hsync[i]] = '\0';
1026 def = 0;
1027 if (monitor->mon_identifier) {
1028 parser_range_to_string(vrefresh_str, &(monitor->mon_vrefresh[0]),
1029 monitor->mon_n_vrefresh);
1030 for (i = 1; i < sizeof(vrefresh) / sizeof(vrefresh[0]); i++) {
1031 if (strcmp(vrefresh_str, vrefresh[i]) == 0) {
1032 def = i;
1033 break;
1037 if (vrefresh_str[0] == '\0')
1038 strcpy(vrefresh_str, "50 - 70");
1039 ClearScreen();
1040 refresh();
1041 i = DialogMenu("Monitor VertRefresh",
1042 "You must indicate the vertical sync range of your monitor. "
1043 "You can either select one of the predefined ranges below "
1044 "that correspond to industry-standard monitor types, or "
1045 "give a specific range. For interlaced modes, the number "
1046 "that counts is the high one (e.g. 87 Hz rather than 43 Hz).",
1047 19, 60, 5, sizeof(vrefresh) /
1048 sizeof(vrefresh[0]), vrefresh, " Finish ", " Cancel ", def);
1049 if (i < 0) {
1050 if (monitor->mon_identifier == NULL) {
1051 XtFree(identifier);
1052 XtFree((XtPointer)monitor);
1054 return (i);
1056 if (i == CONF_MONITOR_VREFRESH) {
1057 ClearScreen();
1058 refresh();
1059 tmp = DialogInput("Monitor VertRefresh",
1060 "Vertical sync range:", 10, 50, vrefresh_str,
1061 " Done ", " Cancel ", 0);
1062 if (tmp == NULL) {
1063 if (monitor->mon_identifier == NULL) {
1064 XtFree(identifier);
1065 XtFree((XtPointer)monitor);
1067 return (-1);
1069 XmuSnprintf(vrefresh_str, sizeof(vrefresh_str), "%s", tmp);
1070 XtFree(tmp);
1072 else
1073 strcpy(vrefresh_str, vrefresh[i]);
1075 /* Finish monitor configuration */
1076 monitor->mon_n_hsync = string_to_parser_range(hsync_str,
1077 &(monitor->mon_hsync[0]), CONF_MAX_HSYNC);
1078 monitor->mon_n_vrefresh = string_to_parser_range(vrefresh_str,
1079 &(monitor->mon_vrefresh[0]), CONF_MAX_VREFRESH);
1080 if (monitor->mon_identifier == NULL) {
1081 monitor->mon_identifier = identifier;
1082 XF86Config->conf_monitor_lst =
1083 xf86addMonitor(XF86Config->conf_monitor_lst, monitor);
1086 return (1);
1089 static int
1090 CardConfig(void)
1092 int i;
1093 XF86ConfDevicePtr *devices = NULL, device = XF86Config->conf_device_lst;
1094 char **list = NULL, *identifier = NULL, *driver, *busid, *tmp;
1095 int nlist, def;
1096 CardsEntry *entry = NULL;
1097 static char **drivers;
1098 static int ndrivers;
1099 static char *xdrivers[] = {
1100 "apm",
1101 "ark",
1102 "ast",
1103 "ati",
1104 "r128",
1105 "radeon",
1106 "chips",
1107 "cirrus",
1108 "cyrix",
1109 "fbdev",
1110 "glint",
1111 "i128",
1112 "i740",
1113 "i810",
1114 "imstt",
1115 "mga",
1116 "neomagic",
1117 "nv",
1118 "rendition",
1119 "s3",
1120 "s3virge",
1121 "savage",
1122 "siliconmotion",
1123 "sis",
1124 "tdfx",
1125 "tga",
1126 "trident",
1127 "tseng",
1128 "vmware",
1129 "vga",
1130 "vesa",
1133 #ifdef USE_MODULES
1134 if (!nomodules) {
1135 xf86cfgModuleOptions *opts = module_options;
1137 drivers = NULL;
1138 ndrivers = 0;
1139 while (opts) {
1140 if (opts->type == VideoModule) {
1141 ++ndrivers;
1142 drivers = (char**)XtRealloc((XtPointer)drivers,
1143 ndrivers * sizeof(char*));
1144 /* XXX no private copy */
1145 drivers[ndrivers - 1] = opts->name;
1147 opts = opts->next;
1150 else
1151 #endif
1153 ndrivers = sizeof(xdrivers) / sizeof(xdrivers[0]);
1154 drivers = xdrivers;
1157 nlist = 0;
1158 while (device) {
1159 list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*));
1160 list[nlist] = XtMalloc(sizeof(Edit) +
1161 strlen(device->dev_identifier) + 1);
1162 sprintf(list[nlist], "%s%s", Edit, device->dev_identifier);
1163 devices = (XF86ConfDevicePtr*)XtRealloc((XtPointer)devices, (nlist + 1) *
1164 sizeof(XF86ConfDevicePtr));
1165 devices[nlist] = device;
1166 ++nlist;
1167 device = (XF86ConfDevicePtr)(device->list.next);
1170 device = NULL;
1172 if (nlist) {
1173 list = (char**)XtRealloc((XtPointer)list, (nlist + 2) * sizeof(char*));
1174 list[nlist++] = XtNewString("Add new card");
1175 if (nlist == 2) {
1176 i = strlen("Remove ") + strlen(devices[0]->dev_identifier) + 1;
1177 list[nlist] = XtMalloc(i);
1178 XmuSnprintf(list[nlist], i, "Remove %s", devices[0]->dev_identifier);
1179 ++nlist;
1181 else
1182 list[nlist++] = XtNewString("Remove device");
1183 ClearScreen();
1184 refresh();
1185 i = DialogMenu("Card configuration",
1186 "You can edit or remove a previously configured "
1187 "card, or add a new one.", 14, 60, 4, nlist, list,
1188 " Ok ", " Cancel ", 0);
1189 if (i < 0) {
1190 for (i = 0; i < nlist; i++)
1191 XtFree(list[i]);
1192 XtFree((XtPointer)list);
1193 XtFree((XtPointer)devices);
1194 return (-1);
1196 if (nlist > 2 && i == nlist - 1) {
1197 if (nlist > 3) {
1198 for (i = 0; i < nlist - 2; i++) {
1199 /* XXX Remove the "Edit " from list entries */
1200 memmove(list[i], list[i] + sizeof(Edit) - 1,
1201 strlen(list[i]) - sizeof(Edit) + 2);
1203 ClearScreen();
1204 refresh();
1205 i = DialogMenu("Remove card",
1206 "Select which card to remove",
1207 13, 60, 4, nlist - 2, list,
1208 " Remove ", " Cancel ", 0);
1209 if (i < 0) {
1210 for (i = 0; i < nlist; i++)
1211 XtFree(list[i]);
1212 XtFree((XtPointer)list);
1213 XtFree((XtPointer)devices);
1214 return (-1);
1216 device = devices[i];
1218 else
1219 device = devices[0];
1220 for (i = 0; i < nlist; i++)
1221 XtFree(list[i]);
1222 XtFree((XtPointer)list);
1223 XtFree((XtPointer)devices);
1224 xf86removeDevice(XF86Config, device);
1225 return (0);
1227 if (i < nlist - 2)
1228 device = devices[i];
1230 for (i = 0; i < nlist; i++)
1231 XtFree(list[i]);
1232 XtFree((XtPointer)list);
1233 XtFree((XtPointer)devices);
1235 if (device == NULL) {
1236 char label[32];
1238 device = (XF86ConfDevicePtr)XtCalloc(1, sizeof(XF86ConfDeviceRec));
1239 device->dev_chipid = device->dev_chiprev = device->dev_irq = -1;
1240 XmuSnprintf(label, sizeof(label), "Card%d", nlist ? nlist - 2 : 0);
1241 ClearScreen();
1242 refresh();
1243 identifier =
1244 DialogInput("Card identifier",
1245 "Enter an identifier for your card definition:",
1246 11, 40, label,
1247 " Next >>", " Cancel ", 0);
1248 if (identifier == NULL) {
1249 XtFree((XtPointer)device);
1250 return (-1);
1254 ClearScreen();
1255 refresh();
1256 if (Dialog("Card configuration",
1257 "Now we must configure video card specific settings. At this "
1258 "point you can choose to make a selection out of a database of "
1259 "video card definitions.\n"
1260 "\n"
1261 "The database entries include information about the chipset, "
1262 "what driver to run, the Ramdac and ClockChip, and comments "
1263 "that will be included in the Device section. However, a lot "
1264 "of definitions only hint about what driver to run (based on "
1265 "the chipset the card uses) and are untested.\n"
1266 "\n"
1267 "Do you want to look at the card database?",
1268 18, 60, " Yes ", " No ", device->dev_identifier != NULL) == 0) {
1269 static char **cards;
1270 static int ncards;
1272 if (cards == NULL) {
1273 ReadCardsDatabase();
1274 cards = GetCardNames(&ncards);
1275 cards = (char**)XtRealloc((XtPointer)cards,
1276 (ncards + 1) * sizeof(char*));
1277 for (i = ncards; i > 0; i--)
1278 cards[i] = cards[i - 1];
1279 cards[0] = "** Unlisted card **";
1280 ++ncards;
1282 if (device->dev_card)
1283 entry = LookupCard(device->dev_card);
1284 def = 0;
1285 if (entry) {
1286 for (i = 0; i < NumCardsEntry; i++)
1287 if (strcasecmp(CardsDB[i]->name, entry->name) == 0) {
1288 def = i + 1;
1289 break;
1291 /* make sure entry is set to null again */
1292 entry = NULL;
1295 i = DialogMenu("Card database",
1296 "Select name that better matches your card:",
1297 20, 70, 11, ncards, cards, "Next >>", " Cancel ", def);
1298 if (i > 0)
1299 entry = LookupCard(cards[i]);
1302 def = 0;
1303 tmp = device->dev_driver ? device->dev_driver : entry && entry->driver ?
1304 entry->driver : "vga";
1305 for (i = 0; i < ndrivers; i++)
1306 if (strcmp(drivers[i], tmp) == 0) {
1307 def = i;
1308 break;
1311 ClearScreen();
1312 refresh();
1313 i = DialogMenu("Card driver",
1314 "You can select the driver for your card here, or just press "
1315 "Enter to use the default/current:", 20, 50, 9,
1316 ndrivers, drivers, " Ok ", " Cancel ", def);
1317 if (i < 0) {
1318 if (device->dev_identifier == NULL) {
1319 XtFree(identifier);
1320 XtFree((XtPointer)device);
1322 return (-1);
1324 driver = ndrivers ? drivers[i] : "vga";
1326 ClearScreen();
1327 refresh();
1328 tmp = device->dev_busid ? device->dev_busid : "";
1329 busid = DialogInput("Card BusID",
1330 "You normally does not need to fill this field "
1331 "if you have only one video card:", 11, 50, tmp,
1332 " Finish ", " Cancel ", 0);
1334 /* Finish card configuration */
1335 if (entry) {
1336 XtFree(device->dev_card);
1337 device->dev_card = XtNewString(entry->name);
1338 if (entry->chipset) {
1339 XtFree(device->dev_chipset);
1340 device->dev_chipset = XtNewString(entry->chipset);
1342 if (entry->ramdac) {
1343 XtFree(device->dev_ramdac);
1344 device->dev_ramdac = XtNewString(entry->ramdac);
1346 if (entry->clockchip) {
1347 XtFree(entry->clockchip);
1348 device->dev_clockchip = XtNewString(entry->clockchip);
1351 if (busid) {
1352 XtFree(device->dev_busid);
1353 if (*busid)
1354 device->dev_busid = busid;
1355 else {
1356 device->dev_busid = NULL;
1357 XtFree(busid);
1360 XtFree(device->dev_driver);
1361 device->dev_driver = XtNewString(driver);
1362 if (device->dev_identifier == NULL) {
1363 device->dev_identifier = identifier;
1364 XF86Config->conf_device_lst =
1365 xf86addDevice(XF86Config->conf_device_lst, device);
1368 return (1);
1371 static char *depths[] = {
1372 "1 bit, monochrome",
1373 "4 bit, 16 colors",
1374 "8 bit, 256 colors",
1375 "15 bits, 32Kb colors",
1376 "16 bits, 65Kb colors",
1377 "24 bits, 16Mb colors",
1380 static char *modes[] = {
1381 "2048x1536",
1382 "1920x1440",
1383 "1800x1400",
1384 "1600x1200",
1385 "1400x1050",
1386 "1280x1024",
1387 "1280x960",
1388 "1152x864",
1389 "1024x768",
1390 "800x600",
1391 "640x480",
1392 "640x400",
1393 "512x384",
1394 "400x300",
1395 "320x240",
1396 "320x200",
1399 static int
1400 ScreenConfig(void)
1402 int i, disp_allocated;
1403 XF86ConfScreenPtr *screens = NULL, screen = XF86Config->conf_screen_lst;
1404 char **list = NULL, *identifier = NULL;
1405 int nlist, def;
1406 XF86ConfDevicePtr device = NULL;
1407 XF86ConfMonitorPtr monitor = NULL;
1408 XF86ConfDisplayPtr display;
1409 XF86ModePtr mode, ptr = NULL;
1410 char *checks;
1412 nlist = 0;
1413 while (screen) {
1414 list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*));
1415 list[nlist] = XtMalloc(sizeof(Edit) +
1416 strlen(screen->scrn_identifier) + 1);
1417 sprintf(list[nlist], "%s%s", Edit, screen->scrn_identifier);
1418 screens = (XF86ConfScreenPtr*)XtRealloc((XtPointer)screens, (nlist + 1) *
1419 sizeof(XF86ConfScreenPtr));
1420 screens[nlist] = screen;
1421 ++nlist;
1422 screen = (XF86ConfScreenPtr)(screen->list.next);
1425 screen = NULL;
1427 if (nlist) {
1428 list = (char**)XtRealloc((XtPointer)list, (nlist + 2) * sizeof(char*));
1429 list[nlist++] = XtNewString("Add new screen");
1430 if (nlist == 2) {
1431 i = strlen("Remove ") + strlen(screens[0]->scrn_identifier) + 1;
1432 list[nlist] = XtMalloc(i);
1433 XmuSnprintf(list[nlist], i, "Remove %s", screens[0]->scrn_identifier);
1434 ++nlist;
1436 else
1437 list[nlist++] = XtNewString("Remove screen");
1438 ClearScreen();
1439 refresh();
1440 i = DialogMenu("Screen configuration",
1441 "You can edit or remove a previously configured "
1442 "screen, or add a new one.", 14, 60, 4, nlist, list,
1443 " Ok ", " Cancel ", 0);
1444 if (i < 0) {
1445 for (i = 0; i < nlist; i++)
1446 XtFree(list[i]);
1447 XtFree((XtPointer)list);
1448 XtFree((XtPointer)screens);
1449 return (-1);
1451 if (nlist > 2 && i == nlist - 1) {
1452 if (nlist > 3) {
1453 for (i = 0; i < nlist - 2; i++) {
1454 /* XXX Remove the "Edit " from list entries */
1455 memmove(list[i], list[i] + sizeof(Edit) - 1,
1456 strlen(list[i]) - sizeof(Edit) + 2);
1458 ClearScreen();
1459 refresh();
1460 i = DialogMenu("Remove screen",
1461 "Select which screen to remove",
1462 13, 60, 4, nlist - 2, list,
1463 " Remove ", " Cancel ", 0);
1464 if (i < 0) {
1465 for (i = 0; i < nlist; i++)
1466 XtFree(list[i]);
1467 XtFree((XtPointer)list);
1468 XtFree((XtPointer)screens);
1469 return (-1);
1471 screen = screens[i];
1473 else
1474 screen = screens[0];
1475 for (i = 0; i < nlist; i++)
1476 XtFree(list[i]);
1477 XtFree((XtPointer)list);
1478 XtFree((XtPointer)screens);
1479 xf86removeScreen(XF86Config, screen);
1480 return (0);
1482 if (i < nlist - 2)
1483 screen = screens[i];
1485 for (i = 0; i < nlist; i++)
1486 XtFree(list[i]);
1487 XtFree((XtPointer)list);
1488 XtFree((XtPointer)screens);
1490 if (screen == NULL) {
1491 char label[256];
1492 XF86ConfDevicePtr *devices = NULL;
1493 XF86ConfMonitorPtr *monitors = NULL;
1495 device = XF86Config->conf_device_lst;
1496 monitor = XF86Config->conf_monitor_lst;
1498 if (device == NULL || monitor == NULL) {
1499 ClearScreen();
1500 refresh();
1501 Dialog("Configuration error",
1502 "You need to configure (at least) one card and one "
1503 "monitor before creating a screen definition.",
1504 9, 50, " Ok ", NULL, 0);
1506 return (-1);
1509 XmuSnprintf(label, sizeof(label), "Screen%d", nlist ? nlist - 2 : 0);
1510 ClearScreen();
1511 refresh();
1512 identifier =
1513 DialogInput("Screen identifier",
1514 "Enter an identifier for your screen definition:",
1515 11, 40, label,
1516 " Next >>", " Cancel ", 0);
1517 if (identifier == NULL)
1518 return (-1);
1520 nlist = 0;
1521 list = NULL;
1522 while (device) {
1523 list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*));
1524 list[nlist] = XtNewString(device->dev_identifier);
1525 devices = (XF86ConfDevicePtr*)XtRealloc((XtPointer)devices, (nlist + 1) *
1526 sizeof(XF86ConfDevicePtr));
1527 devices[nlist] = device;
1528 ++nlist;
1529 device = (XF86ConfDevicePtr)(device->list.next);
1531 ClearScreen();
1532 refresh();
1533 i = DialogMenu("Screen card", "Please select a video card:",
1534 13, 60, 4, nlist, list, " Next >>", " Cancel ", 0);
1535 for (def = 0; def < nlist; def++)
1536 XtFree(list[def]);
1537 XtFree((XtPointer)list);
1538 if (i < 0) {
1539 XtFree(identifier);
1540 XtFree((XtPointer)devices);
1541 return (-1);
1543 device = devices[i];
1544 XtFree((XtPointer)devices);
1546 nlist = 0;
1547 list = NULL;
1548 while (monitor) {
1549 list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*));
1550 list[nlist] = XtNewString(monitor->mon_identifier);
1551 monitors = (XF86ConfMonitorPtr*)XtRealloc((XtPointer)monitors, (nlist + 1) *
1552 sizeof(XF86ConfMonitorPtr));
1553 monitors[nlist] = monitor;
1554 ++nlist;
1555 monitor = (XF86ConfMonitorPtr)(monitor->list.next);
1557 XmuSnprintf(label, sizeof(label),
1558 "Select the monitor connected to \"%s\":",
1559 device->dev_identifier);
1560 ClearScreen();
1561 refresh();
1562 i = DialogMenu("Screen monitor", label,
1563 13, 60, 4, nlist, list, " Next >>", " Cancel ", 0);
1564 for (def = 0; def < nlist; def++)
1565 XtFree(list[def]);
1566 XtFree((XtPointer)list);
1567 if (i < 0) {
1568 XtFree(identifier);
1569 XtFree((XtPointer)monitors);
1570 return (-1);
1572 monitor = monitors[i];
1573 XtFree((XtPointer)monitors);
1575 screen = (XF86ConfScreenPtr)XtCalloc(1, sizeof(XF86ConfScreenRec));
1576 screen->scrn_device = device;
1577 screen->scrn_monitor = monitor;
1580 if (screen->scrn_defaultdepth == 1)
1581 def = 0;
1582 else if (screen->scrn_defaultdepth == 4)
1583 def = 1;
1584 else if (screen->scrn_defaultdepth == 8)
1585 def = 2;
1586 else if (screen->scrn_defaultdepth == 15)
1587 def = 3;
1588 else if (screen->scrn_defaultdepth == 16)
1589 def = 4;
1590 else if (screen->scrn_defaultdepth == 24)
1591 def = 5;
1592 else {
1593 if (screen->scrn_device && screen->scrn_device->dev_driver &&
1594 strcmp(screen->scrn_device->dev_driver, "vga") == 0)
1595 def = 1; /* 4bpp */
1596 else
1597 def = 2; /* 8bpp */
1599 ClearScreen();
1600 refresh();
1601 i = DialogMenu("Screen depth",
1602 "Please specify which color depth you want to use by default:",
1603 15, 60, 6, sizeof(depths) / sizeof(depths[0]), depths,
1604 " Next >>", " Cancel ", def);
1605 if (i < 0) {
1606 if (screen->scrn_identifier == NULL) {
1607 XtFree(identifier);
1608 XtFree((XtPointer)screen);
1610 return (-1);
1612 else
1613 /* XXX depths must begin with the depth number */
1614 screen->scrn_defaultdepth = atoi(depths[i]);
1616 def = 0; /* use def to count how many modes are selected*/
1617 nlist = 0;
1618 list = NULL;
1619 checks = XtMalloc(sizeof(modes) / sizeof(modes[0]));
1620 /* XXX list fields in the code below are not allocated */
1621 disp_allocated = 0;
1622 display = screen->scrn_display_lst;
1623 while (display && display->disp_depth != screen->scrn_defaultdepth)
1624 display = (XF86ConfDisplayPtr)(display->list.next);
1625 if (display == NULL) {
1626 display = (XF86ConfDisplayPtr)XtCalloc(1, sizeof(XF86ConfDisplayRec));
1627 display->disp_white.red = display->disp_black.red = -1;
1628 display->disp_depth = screen->scrn_defaultdepth;
1629 disp_allocated = 1;
1631 else {
1632 mode = display->disp_mode_lst;
1633 while (mode) {
1634 for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++)
1635 if (strcmp(modes[i], mode->mode_name) == 0) {
1636 break;
1639 if (i == sizeof(modes) / sizeof(modes[0])) {
1640 list = (char**)XtRealloc((XtPointer)list,
1641 (nlist + 1) * sizeof(char*));
1642 list[nlist] = mode->mode_name;
1643 checks = XtRealloc(checks, sizeof(modes) / sizeof(modes[0]) +
1644 nlist + 1);
1645 checks[nlist] = 1;
1646 ++def;
1647 nlist++;
1648 break;
1650 mode = (XF86ModePtr)(mode->list.next);
1654 for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++)
1655 checks[i + nlist] = 0;
1657 mode = display->disp_mode_lst;
1658 while (mode) {
1659 for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++)
1660 if (strcmp(modes[i], mode->mode_name) == 0) {
1661 ++def;
1662 checks[i + nlist] = 1;
1663 break;
1665 mode = (XF86ModePtr)(mode->list.next);
1668 if (nlist == 0 && def == 0)
1669 checks[7] = 1; /* 640x480 */
1670 list = (char**)XtRealloc((XtPointer)list, (nlist + sizeof(modes) /
1671 sizeof(modes[0])) * sizeof(char*));
1672 for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++)
1673 list[i + nlist] = modes[i];
1674 nlist += sizeof(modes) / sizeof(modes[0]);
1676 ClearScreen();
1677 refresh();
1678 i = DialogCheckBox("Screen modes",
1679 "Select the video modes for this screen:",
1680 17, 60, 8, sizeof(modes) / sizeof(modes[0]), modes,
1681 " Finish ", " Cancel ", checks);
1682 if (i < 0) {
1683 if (screen->scrn_identifier == NULL) {
1684 XtFree(identifier);
1685 XtFree((XtPointer)screen);
1686 XtFree((XtPointer)list);
1687 if (disp_allocated)
1688 XtFree((XtPointer)display);
1690 return (-1);
1693 mode = display->disp_mode_lst;
1694 while (mode) {
1695 ptr = (XF86ModePtr)(mode->list.next);
1696 XtFree(mode->mode_name);
1697 XtFree((XtPointer)mode);
1698 mode = ptr;
1700 display->disp_mode_lst = NULL;
1702 for (i = 0; i < nlist; i++) {
1703 if (checks[i]) {
1704 mode = (XF86ModePtr)XtCalloc(1, sizeof(XF86ModeRec));
1705 mode->mode_name = XtNewString(list[i]);
1706 if (display->disp_mode_lst == NULL)
1707 display->disp_mode_lst = ptr = mode;
1708 else {
1709 ptr->list.next = mode;
1710 ptr = mode;
1714 XtFree((XtPointer)list);
1716 if (disp_allocated) {
1717 display->list.next = NULL;
1718 if (screen->scrn_display_lst == NULL)
1719 screen->scrn_display_lst = display;
1720 else
1721 screen->scrn_display_lst->list.next = display;
1724 if (screen->scrn_identifier == NULL) {
1725 screen->scrn_identifier = identifier;
1726 screen->scrn_monitor_str = XtNewString(monitor->mon_identifier);
1727 screen->scrn_device_str = XtNewString(device->dev_identifier);
1728 XF86Config->conf_screen_lst =
1729 xf86addScreen(XF86Config->conf_screen_lst, screen);
1732 return (1);
1735 static XF86ConfAdjacencyPtr
1736 CopyAdjacency(XF86ConfAdjacencyPtr ptr)
1738 XF86ConfAdjacencyPtr adj = (XF86ConfAdjacencyPtr)
1739 XtCalloc(1, sizeof(XF86ConfAdjacencyRec));
1741 adj->adj_scrnum = ptr->adj_scrnum;
1742 adj->adj_screen = ptr->adj_screen;
1743 adj->adj_screen_str = XtNewString(ptr->adj_screen_str);
1744 adj->adj_top = ptr->adj_top;
1745 if (ptr->adj_top_str)
1746 adj->adj_top_str = XtNewString(ptr->adj_top_str);
1747 adj->adj_bottom = ptr->adj_bottom;
1748 if (ptr->adj_bottom_str)
1749 adj->adj_bottom_str = XtNewString(ptr->adj_bottom_str);
1750 adj->adj_left = ptr->adj_left;
1751 if (ptr->adj_left_str)
1752 adj->adj_left_str = XtNewString(ptr->adj_left_str);
1753 adj->adj_right = ptr->adj_right;
1754 if (ptr->adj_right_str)
1755 adj->adj_right_str = XtNewString(ptr->adj_right_str);
1756 adj->adj_where = ptr->adj_where;
1757 adj->adj_x = ptr->adj_x;
1758 adj->adj_y = ptr->adj_y;
1759 if (ptr->adj_refscreen)
1760 adj->adj_refscreen = XtNewString(ptr->adj_refscreen);
1762 return (adj);
1765 static XF86ConfInactivePtr
1766 CopyInactive(XF86ConfInactivePtr ptr)
1768 XF86ConfInactivePtr inac = (XF86ConfInactivePtr)
1769 XtCalloc(1, sizeof(XF86ConfInactiveRec));
1771 inac->inactive_device = ptr->inactive_device;
1772 if (ptr->inactive_device_str)
1773 inac->inactive_device_str = XtNewString(ptr->inactive_device_str);
1775 return (inac);
1778 static XF86ConfInputrefPtr
1779 CopyInputref(XF86ConfInputrefPtr ptr)
1781 XF86ConfInputrefPtr iref = (XF86ConfInputrefPtr)
1782 XtCalloc(1, sizeof(XF86ConfInputrefRec));
1783 XF86OptionPtr opt = ptr->iref_option_lst;
1785 iref->iref_inputdev = ptr->iref_inputdev;
1786 if (ptr->iref_inputdev_str)
1787 iref->iref_inputdev_str = XtNewString(ptr->iref_inputdev_str);
1788 while (opt) {
1789 iref->iref_option_lst = xf86addNewOption(iref->iref_option_lst,
1790 XtNewString(opt->opt_name),
1791 opt->opt_val ? XtNewString(opt->opt_val) : NULL);
1792 opt = (XF86OptionPtr)(opt->list.next);
1795 return (iref);
1798 static XF86ConfLayoutPtr
1799 CopyLayout(XF86ConfLayoutPtr ptr)
1801 XF86ConfLayoutPtr lay = (XF86ConfLayoutPtr)
1802 XtCalloc(1, sizeof(XF86ConfLayoutRec));
1803 XF86ConfAdjacencyPtr adj = ptr->lay_adjacency_lst, padj;
1804 XF86ConfInactivePtr inac = ptr->lay_inactive_lst, pinac;
1805 XF86ConfInputrefPtr iref = ptr->lay_input_lst, piref;
1806 XF86OptionPtr opt = ptr->lay_option_lst;
1808 if (ptr->lay_identifier)
1809 lay->lay_identifier = XtNewString(ptr->lay_identifier);
1810 if (adj) {
1811 padj = lay->lay_adjacency_lst = CopyAdjacency(adj);
1812 adj = (XF86ConfAdjacencyPtr)(adj->list.next);
1813 while (adj) {
1814 padj->list.next = CopyAdjacency(adj);
1815 padj = (XF86ConfAdjacencyPtr)(padj->list.next);
1816 adj = (XF86ConfAdjacencyPtr)(adj->list.next);
1819 if (inac) {
1820 pinac = lay->lay_inactive_lst = CopyInactive(inac);
1821 inac = (XF86ConfInactivePtr)(inac->list.next);
1822 while (inac) {
1823 pinac->list.next = CopyInactive(inac);
1824 pinac = (XF86ConfInactivePtr)(pinac->list.next);
1825 inac = (XF86ConfInactivePtr)(inac->list.next);
1828 if (iref) {
1829 piref = lay->lay_input_lst = CopyInputref(iref);
1830 iref = (XF86ConfInputrefPtr)(iref->list.next);
1831 while (iref) {
1832 piref->list.next = CopyInputref(iref);
1833 piref = (XF86ConfInputrefPtr)(piref->list.next);
1834 iref = (XF86ConfInputrefPtr)(iref->list.next);
1838 while (opt) {
1839 lay->lay_option_lst = xf86addNewOption(lay->lay_option_lst,
1840 XtNewString(opt->opt_name),
1841 opt->opt_val ? XtNewString(opt->opt_val) : NULL);
1842 opt = (XF86OptionPtr)(opt->list.next);
1845 return (lay);
1848 static void
1849 FreeLayout(XF86ConfLayoutPtr lay)
1851 static XF86ConfigRec xf86config;
1853 xf86config.conf_layout_lst = lay;
1854 xf86removeLayout(&xf86config, lay);
1857 static int
1858 LayoutConfig(void)
1860 int i;
1861 XF86ConfLayoutPtr *layouts = NULL, rlayout = NULL,
1862 layout = XF86Config->conf_layout_lst;
1863 XF86ConfInputPtr input = XF86Config->conf_input_lst;
1864 char **list = NULL, *identifier = NULL;
1865 XF86ConfInputPtr *mouses = NULL, *keyboards = NULL, mouse, keyboard;
1866 XF86ConfInputrefPtr iref, piref, mref, kref;
1867 XF86ConfAdjacencyPtr adj, padj;
1868 int nmouses, nkeyboards;
1869 int nlist;
1870 XF86OptionPtr option;
1871 XF86ConfScreenPtr screen, *screens;
1873 nmouses = nkeyboards = 0;
1874 while (input) {
1875 if (strcmp(input->inp_driver, "mouse") == 0) {
1876 mouses = (XF86ConfInputPtr*)XtRealloc((XtPointer)mouses,
1877 (nmouses + 1) * sizeof(XF86ConfInputPtr));
1878 mouses[nmouses] = input;
1879 ++nmouses;
1881 else if (IS_KBDDRIV(input->inp_driver)) {
1882 keyboards = (XF86ConfInputPtr*)XtRealloc((XtPointer)keyboards,
1883 (nkeyboards + 1) * sizeof(XF86ConfInputPtr));
1884 keyboards[nkeyboards] = input;
1885 ++nkeyboards;
1887 input = (XF86ConfInputPtr)(input->list.next);
1889 if (XF86Config->conf_screen_lst == NULL ||
1890 nmouses == 0 || nkeyboards == 0) {
1891 XtFree((XtPointer)mouses);
1892 XtFree((XtPointer)keyboards);
1893 ClearScreen();
1894 refresh();
1895 Dialog("Configuration error",
1896 "You need to configure (at least) one screen, mouse "
1897 "and keyboard before creating a layout definition.",
1898 9, 50, " Ok ", NULL, 0);
1899 return (-1);
1902 nlist = 0;
1903 while (layout) {
1904 list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*));
1905 list[nlist] = XtMalloc(sizeof(Edit) +
1906 strlen(layout->lay_identifier) + 1);
1907 sprintf(list[nlist], "%s%s", Edit, layout->lay_identifier);
1908 layouts = (XF86ConfLayoutPtr*)XtRealloc((XtPointer)layouts, (nlist + 1) *
1909 sizeof(XF86ConfLayoutPtr));
1910 layouts[nlist] = layout;
1911 ++nlist;
1912 layout = (XF86ConfLayoutPtr)(layout->list.next);
1915 layout = NULL;
1917 if (nlist) {
1918 list = (char**)XtRealloc((XtPointer)list, (nlist + 2) * sizeof(char*));
1919 list[nlist++] = XtNewString("Add new layout");
1920 if (nlist == 2) {
1921 i = strlen("Remove ") + strlen(layouts[0]->lay_identifier) + 1;
1922 list[nlist] = XtMalloc(i);
1923 XmuSnprintf(list[nlist], i, "Remove %s", layouts[0]->lay_identifier);
1924 ++nlist;
1926 else
1927 list[nlist++] = XtNewString("Remove layout");
1928 ClearScreen();
1929 refresh();
1930 i = DialogMenu("Layout configuration",
1931 "You can edit or remove a previously configured "
1932 "layout, or add a new one.", 14, 60, 4, nlist, list,
1933 " Ok ", " Cancel ", 0);
1934 if (i < 0) {
1935 for (i = 0; i < nlist; i++)
1936 XtFree(list[i]);
1937 XtFree((XtPointer)list);
1938 XtFree((XtPointer)layouts);
1939 XtFree((XtPointer)mouses);
1940 XtFree((XtPointer)keyboards);
1941 return (-1);
1943 if (nlist > 2 && i == nlist - 1) {
1944 if (nlist > 3) {
1945 for (i = 0; i < nlist - 2; i++) {
1946 /* XXX Remove the "Edit " from list entries */
1947 memmove(list[i], list[i] + sizeof(Edit) - 1,
1948 strlen(list[i]) - sizeof(Edit) + 2);
1950 ClearScreen();
1951 refresh();
1952 i = DialogMenu("Remove layout",
1953 "Select which layout to remove",
1954 13, 60, 4, nlist - 2, list,
1955 " Remove ", " Cancel ", 0);
1956 if (i < 0) {
1957 for (i = 0; i < nlist; i++)
1958 XtFree(list[i]);
1959 XtFree((XtPointer)list);
1960 XtFree((XtPointer)layouts);
1961 XtFree((XtPointer)mouses);
1962 XtFree((XtPointer)keyboards);
1963 return (-1);
1965 layout = layouts[i];
1967 else
1968 layout = layouts[0];
1969 for (i = 0; i < nlist; i++)
1970 XtFree(list[i]);
1971 XtFree((XtPointer)list);
1972 XtFree((XtPointer)layouts);
1973 XtFree((XtPointer)mouses);
1974 XtFree((XtPointer)keyboards);
1975 xf86removeLayout(XF86Config, layout);
1976 return (0);
1978 if (i < nlist - 2)
1979 layout = layouts[i];
1981 for (i = 0; i < nlist; i++)
1982 XtFree(list[i]);
1983 XtFree((XtPointer)list);
1984 XtFree((XtPointer)layouts);
1986 if (layout == NULL) {
1987 char label[32];
1989 layout = (XF86ConfLayoutPtr)XtCalloc(1, sizeof(XF86ConfLayoutRec));
1990 XmuSnprintf(label, sizeof(label), "Layout%d", nlist ? nlist - 2 : 0);
1991 ClearScreen();
1992 refresh();
1993 identifier =
1994 DialogInput("Layout identifier",
1995 "Enter an identifier for your layout definition:",
1996 11, 40, label,
1997 " Next >>", " Cancel ", 0);
1998 if (identifier == NULL) {
1999 XtFree((XtPointer)layout);
2000 XtFree((XtPointer)mouses);
2001 XtFree((XtPointer)keyboards);
2002 return (-1);
2005 else {
2006 /* So that we can safely change it */
2007 rlayout = layout;
2008 layout = CopyLayout(rlayout);
2012 mouse = keyboard = NULL;
2014 /* Mouse */
2015 piref = NULL;
2016 iref = layout->lay_input_lst;
2017 while (iref) {
2018 if (strcmp(iref->iref_inputdev->inp_driver, "mouse") == 0) {
2019 if (mouse == NULL)
2020 piref = iref;
2021 if (xf86findOption(iref->iref_option_lst, "CorePointer")) {
2022 mouse = iref->iref_inputdev;
2023 piref = iref;
2024 break;
2027 iref = (XF86ConfInputrefPtr)(iref->list.next);
2029 if (mouse == NULL) {
2030 if (piref) {
2031 mref = piref;
2032 mouse = piref->iref_inputdev;
2033 piref->iref_option_lst =
2034 xf86addNewOption(piref->iref_option_lst,
2035 XtNewString("CorePointer"), NULL);
2037 else {
2038 mouse = mouses[0];
2039 mref = iref = (XF86ConfInputrefPtr)XtCalloc(1, sizeof(XF86ConfInputrefRec));
2040 iref->iref_inputdev_str = XtNewString(mouse->inp_identifier);
2041 iref->iref_inputdev = mouse;
2042 iref->iref_option_lst =
2043 xf86addNewOption(iref->iref_option_lst,
2044 XtNewString("CorePointer"), NULL);
2045 iref->list.next = layout->lay_input_lst;
2046 if (layout->lay_input_lst == NULL)
2047 layout->lay_input_lst = iref;
2048 else {
2049 iref->list.next = layout->lay_input_lst;
2050 layout->lay_input_lst = iref;
2054 else
2055 mref = piref;
2057 /* XXX list fields are not allocated */
2058 if (nmouses > 1) {
2059 nlist = 0;
2060 list = (char**)XtMalloc(sizeof(char*));
2061 list[nlist++] = mouse->inp_identifier;
2062 input = XF86Config->conf_input_lst;
2063 while (input) {
2064 if (input != mouse && strcmp(input->inp_driver, "mouse") == 0) {
2065 list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*));
2066 list[nlist++] = input->inp_identifier;
2068 input = (XF86ConfInputPtr)(input->list.next);
2070 ClearScreen();
2071 refresh();
2072 i = DialogMenu("Select Core Pointer",
2073 "Select the mouse connected to you computer",
2074 12, 60, 4, nlist, list, " Ok ", " Cancel ", 0);
2075 if (i < 0) {
2076 XtFree((XtPointer)mouses);
2077 XtFree((XtPointer)keyboards);
2078 XtFree((XtPointer)list);
2079 if (layout->lay_identifier == NULL)
2080 XtFree(identifier);
2081 FreeLayout(layout);
2082 return (-1);
2084 if (i > 0) {
2085 /* Did not select the default one */
2086 iref = layout->lay_input_lst;
2087 while (iref) {
2088 if (strcasecmp(iref->iref_inputdev_str, list[i]) == 0) {
2089 if ((option = xf86findOption(iref->iref_option_lst,
2090 "SendCoreEvents")) != NULL) {
2091 XtFree(option->opt_name);
2092 option->opt_name = XtNewString("CorePointer");
2094 else
2095 iref->iref_option_lst =
2096 xf86addNewOption(iref->iref_option_lst,
2097 XtNewString("CorePointer"), NULL);
2098 option = xf86findOption(mref->iref_option_lst,
2099 "CorePointer");
2100 XtFree(option->opt_name);
2101 option->opt_name = XtNewString("SendCoreEvents");
2102 break;
2104 iref = (XF86ConfInputrefPtr)(iref->list.next);
2108 /* XXX Write code to add/remove more mouses here */
2112 /* Keyboard */
2113 piref = NULL;
2114 iref = layout->lay_input_lst;
2115 while (iref) {
2116 if (IS_KBDDRIV(iref->iref_inputdev->inp_driver)) {
2117 if (keyboard == NULL)
2118 piref = iref;
2119 if (xf86findOption(iref->iref_option_lst, "CoreKeyboard")) {
2120 keyboard = iref->iref_inputdev;
2121 piref = iref;
2122 break;
2125 iref = (XF86ConfInputrefPtr)(iref->list.next);
2127 if (keyboard == NULL) {
2128 if (piref) {
2129 kref = piref;
2130 keyboard = piref->iref_inputdev;
2131 piref->iref_option_lst =
2132 xf86addNewOption(piref->iref_option_lst,
2133 XtNewString("CoreKeyboard"), NULL);
2135 else {
2136 keyboard = keyboards[0];
2137 kref = iref = (XF86ConfInputrefPtr)XtCalloc(1, sizeof(XF86ConfInputrefRec));
2138 iref->iref_inputdev_str = XtNewString(keyboard->inp_identifier);
2139 iref->iref_inputdev = keyboard;
2140 iref->iref_option_lst =
2141 xf86addNewOption(iref->iref_option_lst,
2142 XtNewString("CoreKeyboard"), NULL);
2143 iref->list.next = layout->lay_input_lst;
2144 if (layout->lay_input_lst == NULL)
2145 layout->lay_input_lst = iref;
2146 else {
2147 iref->list.next = layout->lay_input_lst;
2148 layout->lay_input_lst = iref;
2152 else
2153 kref = piref;
2155 /* XXX list fields are not allocated */
2156 if (nkeyboards > 1) {
2157 nlist = 0;
2158 list = (char**)XtMalloc(sizeof(char*));
2159 list[nlist++] = keyboard->inp_identifier;
2160 input = XF86Config->conf_input_lst;
2161 while (input) {
2162 if (input != keyboard && IS_KBDDRIV(input->inp_driver)) {
2163 list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*));
2164 list[nlist++] = input->inp_identifier;
2166 input = (XF86ConfInputPtr)(input->list.next);
2168 ClearScreen();
2169 refresh();
2170 i = DialogMenu("Select Core Keyboard",
2171 "Select the keyboard connected to you computer",
2172 12, 60, 4, nlist, list, " Ok ", " Cancel ", 0);
2173 if (i < 0) {
2174 XtFree((XtPointer)mouses);
2175 XtFree((XtPointer)keyboards);
2176 XtFree((XtPointer)list);
2177 if (layout->lay_identifier == NULL)
2178 XtFree(identifier);
2179 FreeLayout(layout);
2180 return (-1);
2182 if (i > 0) {
2183 /* Did not select the default one */
2184 iref = layout->lay_input_lst;
2185 while (iref) {
2186 if (strcasecmp(iref->iref_inputdev_str, list[i]) == 0) {
2187 if ((option = xf86findOption(iref->iref_option_lst,
2188 "SendCoreEvents")) != NULL) {
2189 XtFree(option->opt_name);
2190 option->opt_name = XtNewString("CoreKeyboard");
2192 else
2193 iref->iref_option_lst =
2194 xf86addNewOption(iref->iref_option_lst,
2195 XtNewString("CoreKeyboard"), NULL);
2196 option = xf86findOption(kref->iref_option_lst,
2197 "CoreKeyboard");
2198 XtFree(option->opt_name);
2199 option->opt_name = XtNewString("SendCoreEvents");
2200 break;
2202 iref = (XF86ConfInputrefPtr)(iref->list.next);
2206 /* XXX Write code to add/remove more keyboards here */
2209 XtFree((XtPointer)mouses);
2210 XtFree((XtPointer)keyboards);
2212 /* Just one screen */
2213 if (XF86Config->conf_screen_lst->list.next == NULL) {
2214 ClearScreen();
2215 refresh();
2216 Dialog("Layout configuration",
2217 (nmouses > 1 || nkeyboards > 1) ?
2218 "As you have only one screen configured, I can now finish "
2219 "creating this Layout configuration."
2221 "As you have only one screen, mouse and keyboard configured, "
2222 "I can now finish creating this Layout configuration.",
2223 12, 60, " Finish ", NULL, 0);
2225 goto LayoutFinish;
2229 /* The code below just adds a screen to the right of the last
2230 * one, or allows removing a screen.
2231 * Needs some review, and adding more options.
2234 /*CONSTCOND*/
2235 while (1) {
2236 static char *screen_opts[] = {
2237 "Add a new screen to layout",
2238 "Remove screen from layout",
2239 "Finish layout configuration",
2242 ClearScreen();
2243 refresh();
2244 i = DialogMenu("Layout configuration", "Please choose one option:",
2245 12, 60, 3, sizeof(screen_opts) / sizeof(screen_opts[0]),
2246 screen_opts, " Done ", " Cancel all changes ", 2);
2248 /* cancel */
2249 if (i < 0) {
2250 XtFree(identifier);
2251 FreeLayout(layout);
2252 return (-1);
2255 /* add new screen */
2256 else if (i == 0) {
2257 nlist = 0;
2258 list = NULL;
2259 screens = NULL;
2260 screen = XF86Config->conf_screen_lst;
2261 while (screen) {
2262 adj = layout->lay_adjacency_lst;
2263 while (adj) {
2264 if (adj->adj_screen == screen)
2265 break;
2266 adj = (XF86ConfAdjacencyPtr)(adj->list.next);
2268 if (adj == NULL) {
2269 list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*));
2270 screens = (XF86ConfScreenPtr*)XtRealloc((XtPointer)screens,
2271 (nlist + 1) * sizeof(XF86ConfScreenPtr));
2272 /* NOT duplicated */
2273 list[nlist] = screen->scrn_identifier;
2274 screens[nlist] = screen;
2275 ++nlist;
2277 screen = (XF86ConfScreenPtr)(screen->list.next);
2280 if (nlist == 0)
2281 continue;
2283 ClearScreen();
2284 refresh();
2285 i = DialogMenu("Layout add screen", "Choose screen to add:",
2286 12, 60, 3, nlist, list,
2287 " Add ", " Cancel ", 0);
2288 if (i >= 0) {
2289 padj = layout->lay_adjacency_lst;
2290 adj = (XF86ConfAdjacencyPtr)
2291 XtCalloc(1, sizeof(XF86ConfAdjacencyRec));
2292 adj->adj_screen = screens[i];
2293 if (padj == NULL) {
2294 adj->adj_where = CONF_ADJ_ABSOLUTE;
2295 layout->lay_adjacency_lst = adj;
2297 else {
2298 while (padj->list.next)
2299 padj = (XF86ConfAdjacencyPtr)(padj->list.next);
2300 padj->list.next = adj;
2301 adj->adj_where = CONF_ADJ_RIGHTOF;
2302 adj->adj_refscreen =
2303 XtNewString(padj->adj_screen->scrn_identifier);
2306 XtFree((XtPointer)list);
2307 XtFree((XtPointer)screens);
2310 /* remove a screen */
2311 else if (i == 1) {
2312 nlist = 0;
2313 list = NULL;
2314 screens = NULL;
2315 adj = layout->lay_adjacency_lst;
2317 while (adj) {
2318 list = (char**)XtRealloc((XtPointer)list, (nlist + 1) * sizeof(char*));
2319 screens = (XF86ConfScreenPtr*)XtRealloc((XtPointer)screens,
2320 (nlist + 1) * sizeof(XF86ConfScreenPtr));
2321 list[nlist] = adj->adj_screen->scrn_identifier;
2322 screens[nlist] = adj->adj_screen;
2323 ++nlist;
2324 adj = (XF86ConfAdjacencyPtr)(adj->list.next);
2327 if (nlist == 0)
2328 continue;
2330 ClearScreen();
2331 refresh();
2332 i = DialogMenu("Layout remove screen", "Choose screen to remove:",
2333 12, 60, 3, nlist, list,
2334 " Remove ", " Cancel ", 0);
2336 adj = padj = layout->lay_adjacency_lst;
2337 while (adj) {
2338 if (adj->adj_screen == screens[i]) {
2339 padj = (XF86ConfAdjacencyPtr)(padj->list.next);
2340 if (padj && adj->adj_where == CONF_ADJ_RIGHTOF &&
2341 padj->adj_where == CONF_ADJ_RIGHTOF) {
2342 XtFree(padj->adj_refscreen);
2343 padj->adj_refscreen = XtNewString(adj->adj_refscreen);
2345 xf86removeAdjacency(layout, adj);
2346 break;
2348 padj = adj;
2349 adj = (XF86ConfAdjacencyPtr)(padj->list.next);
2351 XtFree((XtPointer)list);
2352 XtFree((XtPointer)screens);
2355 /* finish screen configuration */
2356 else
2357 break;
2360 LayoutFinish:
2361 if (layout->lay_adjacency_lst == NULL) {
2362 adj = (XF86ConfAdjacencyPtr)XtCalloc(1, sizeof(XF86ConfAdjacencyRec));
2363 adj->adj_screen = XF86Config->conf_screen_lst;
2364 adj->adj_screen_str = XtNewString(XF86Config->conf_screen_lst->scrn_identifier);
2365 adj->adj_where = CONF_ADJ_ABSOLUTE;
2366 layout->lay_adjacency_lst = adj;
2368 if (rlayout) {
2369 /* just edited this layout */
2370 if (nmouses > 1 || nkeyboards > 1) {
2371 XF86ConfAdjacencyPtr tadj = rlayout->lay_adjacency_lst;
2372 XF86ConfInactivePtr tinac = rlayout->lay_inactive_lst;
2373 XF86ConfInputrefPtr tinp = rlayout->lay_input_lst;
2375 rlayout->lay_adjacency_lst = layout->lay_adjacency_lst;
2376 rlayout->lay_inactive_lst = layout->lay_inactive_lst;
2377 rlayout->lay_input_lst = layout->lay_input_lst;
2379 layout->lay_adjacency_lst = tadj;
2380 layout->lay_inactive_lst = tinac;
2381 layout->lay_input_lst = tinp;
2382 FreeLayout(layout);
2384 return (0);
2386 else {
2387 layout->lay_identifier = identifier;
2388 XF86Config->conf_layout_lst =
2389 xf86addLayout(XF86Config->conf_layout_lst, layout);
2392 return (1);
2395 static void
2396 ClearScreen(void)
2398 int i, j;
2400 wattrset(stdscr, screen_attr);
2401 for (i = 0; i < LINES; i++) {
2402 wmove(stdscr, i, 0);
2403 for (j = 0; j < COLS; j++)
2404 waddch(stdscr, ACS_PLUS);
2406 touchwin(stdscr);
2409 static int
2410 Dialog(char *title, char * prompt, int height, int width,
2411 char *label1, char *label2, int button)
2413 int x, x1, x2, y, key, l1len, l2len;
2414 WINDOW *dialog;
2416 x = (COLS - width) / 2;
2417 y = (LINES - height) / 2;
2419 dialog = newwin(height, width, y, x);
2420 keypad(dialog, TRUE);
2422 PaintWindow(dialog, title, 0, 0, height, width);
2423 wattrset(dialog, dialog_attr);
2424 PrintWrap(dialog, prompt, width - 3, 2, 3);
2426 l1len = strlen(label1);
2427 if (label2)
2428 l2len = strlen(label2);
2429 else {
2430 l2len = button = 0;
2433 x1 = (width - (l1len + l2len)) / (label2 ? 3 : 2);
2434 x2 = x1 + x1 + l1len;
2435 y = height - 3;
2436 if (!button) {
2437 if (label2)
2438 PaintButton(dialog, label2, y, x2, FALSE);
2439 PaintButton(dialog, label1, y, x1, TRUE);
2441 else {
2442 PaintButton(dialog, label1, y, x1, FALSE);
2443 if (label2)
2444 PaintButton(dialog, label2, y, x2, TRUE);
2446 wrefresh(dialog);
2448 /*CONSTCOND*/
2449 while (1) {
2450 key = wgetch(dialog);
2451 switch (key) {
2452 case KEY_LEFT:
2453 case KEY_RIGHT:
2454 if (!button) {
2455 if (label2) {
2456 button = 1;
2457 PaintButton(dialog, label1, y, x1, FALSE);
2458 PaintButton(dialog, label2, y, x2, TRUE);
2462 else {
2463 if (label2) {
2464 button = 0;
2465 PaintButton(dialog, label2, y, x2, FALSE);
2466 PaintButton(dialog, label1, y, x1, TRUE);
2469 wrefresh(dialog);
2470 break;
2471 case ' ':
2472 case '\r':
2473 case '\n':
2474 delwin(dialog);
2475 return button;
2478 /*NOTREACHED*/
2481 static void
2482 PaintWindow(WINDOW *win, char *title_str, int y, int x, int height, int width)
2484 int i, j;
2486 if (title_str != NULL) {
2487 j = (width - strlen(title_str)) / 2 - 1;
2489 wattrset(win, title_attr);
2490 wmove(win, x, y);
2491 for (i = 0; i < j; i++)
2492 waddch(win, ' ');
2493 waddstr(win, title_str);
2494 for (; i < width; i++)
2495 waddch(win, ' ');
2498 wattrset(win, 0);
2500 for (i = 1; i < height; i++) {
2501 wmove(win, y + i, x);
2502 for (j = 0; j < width; j++)
2503 if (i == height - 1 && !j)
2504 waddch(win, highlight_border_attr | ACS_LLCORNER);
2505 else if (i == height - 1 && j == width - 1)
2506 waddch(win, shadow_border_attr | ACS_LRCORNER);
2507 else if (i == height - 1)
2508 waddch(win, shadow_border_attr | ACS_HLINE);
2509 else if (!j)
2510 waddch(win, highlight_border_attr | ACS_VLINE);
2511 else if (j == width - 1)
2512 waddch(win, shadow_border_attr | ACS_VLINE);
2513 else
2514 waddch(win, dialog_attr | ' ');
2519 static void
2520 PaintBox(WINDOW *win, int y, int x, int height, int width)
2522 int i, j;
2524 wattrset(win, 0);
2526 for (i = 0; i < height; i++) {
2527 wmove(win, y + i, x);
2528 for (j = 0; j < width; j++)
2529 if (!i && !j)
2530 waddch(win, shadow_border_attr | ACS_ULCORNER);
2531 else if (i == height - 1 && !j)
2532 waddch(win, shadow_border_attr | ACS_LLCORNER);
2533 else if (!i && j == width-1)
2534 waddch(win, highlight_border_attr | ACS_URCORNER);
2535 else if (i == height - 1 && j == width - 1)
2536 waddch(win, highlight_border_attr | ACS_LRCORNER);
2537 else if (!i)
2538 waddch(win, shadow_border_attr | ACS_HLINE);
2539 else if (i == height - 1)
2540 waddch(win, highlight_border_attr | ACS_HLINE);
2541 else if (!j)
2542 waddch(win, shadow_border_attr | ACS_VLINE);
2543 else if (j == width - 1)
2544 waddch(win, highlight_border_attr | ACS_VLINE);
2545 else
2546 waddch(win, dialog_attr | ' ');
2551 static void
2552 PaintButton(WINDOW *win, char *label, int y, int x, int selected)
2554 int i, temp;
2556 wmove(win, y, x);
2557 wattrset(win, selected ? button_active_attr : button_inactive_attr);
2558 waddstr(win, selected ? "[" : " ");
2559 temp = strspn(label, " ");
2560 label += temp;
2561 wattrset(win, selected ? button_active_attr : button_inactive_attr);
2562 for (i = 0; i < temp; i++)
2563 waddch(win, ' ');
2564 wattrset(win, selected ? button_active_attr : button_inactive_attr);
2565 waddch(win, label[0]);
2566 wattrset(win, selected ? button_active_attr : button_inactive_attr);
2567 waddstr(win, label + 1);
2568 wattrset(win, selected ? button_active_attr : button_inactive_attr);
2569 waddstr(win, selected ? "]" : " ");
2570 wmove(win, y, x + temp + 1);
2573 static void
2574 PrintWrap(WINDOW *win, char *prompt, int width, int y, int x)
2576 int cur_x, cur_y, len, yinc;
2577 char *word, *tempstr = XtMalloc(strlen(prompt) + 1);
2579 cur_x = x;
2580 cur_y = y;
2582 while (*prompt == '\n') {
2583 ++cur_y;
2584 ++prompt;
2587 strcpy(tempstr, prompt);
2589 for (word = strtok(tempstr, " \n"); word != NULL; word = strtok(NULL, " \n")) {
2590 yinc = 0;
2591 len = strlen(word);
2592 while (prompt[word - tempstr + len + yinc] == '\n')
2593 ++yinc;
2594 if (cur_x + strlen(word) > width) {
2595 cur_y++;
2596 cur_x = x;
2598 wmove(win, cur_y, cur_x);
2599 waddstr(win, word);
2600 getyx(win, cur_y, cur_x);
2601 if (yinc) {
2602 cur_y += yinc;
2603 cur_x = x;
2605 else
2606 cur_x++;
2609 free(tempstr);
2612 static int
2613 DialogMenu(char *title, char *prompt, int height, int width, int menu_height,
2614 int item_no, char **items, char *label1, char *label2, int choice)
2616 int i, x, y, cur_x, cur_y, box_x, box_y, key = 0, button = 0,
2617 scrlx = 0, max_choice, nscroll, max_scroll, x1, x2, l1len, l2len;
2618 WINDOW *dialog, *menu;
2620 max_choice = MIN(menu_height, item_no);
2621 max_scroll = MAX(0, item_no - max_choice);
2623 x = (COLS - width) / 2;
2624 y = (LINES - height) / 2;
2626 dialog = newwin(height, width, y, x);
2627 keypad(dialog, TRUE);
2629 PaintWindow(dialog, title, 0, 0, height, width);
2631 wattrset(dialog, dialog_attr);
2632 PrintWrap(dialog, prompt, width - 3, 2, 3);
2634 l1len = strlen(label1);
2635 l2len = strlen(label2);
2637 x1 = (width - (l1len + l2len)) / 3;
2638 x2 = x1 + x1 + l1len;
2640 menu_width = width - 6;
2641 getyx(dialog, cur_y, cur_x);
2642 box_y = cur_y + 1;
2643 box_x = (width - menu_width) / 2 - 1;
2645 menu = subwin(dialog, menu_height, menu_width, y + box_y + 1, x + box_x + 1);
2646 keypad(menu, TRUE);
2648 /* draw a box around the menu items */
2649 PaintBox(dialog, box_y, box_x, menu_height + 2, menu_width + 2);
2651 item_x = 3;
2653 if (choice > menu_height) {
2654 scrlx = MIN(max_scroll, choice);
2655 choice -= scrlx;
2658 for (i = 0; i < max_choice; i++)
2659 PaintItem(menu, items[i + scrlx], i, i == choice);
2660 PaintScroller(menu, scrlx + choice, item_no, menu_height);
2661 wnoutrefresh(menu);
2663 x = width / 2 - 11;
2664 y = height - 3;
2665 PaintButton(dialog, label2, y, x2, FALSE);
2666 PaintButton(dialog, label1, y, x1, TRUE);
2667 wrefresh(dialog);
2669 /*CONSTCOND*/
2670 while (1) {
2671 i = choice;
2672 key = wgetch(dialog);
2674 if (menu_height > 1 && key == KEY_PPAGE) {
2675 if (!choice) {
2676 if (scrlx) {
2677 /* Scroll menu down */
2678 getyx(dialog, cur_y, cur_x);
2680 nscroll = max_choice > scrlx ? -scrlx : -max_choice;
2681 scrollok(menu, TRUE);
2682 wscrl(menu, nscroll);
2683 scrollok(menu, FALSE);
2685 PaintItem(menu, items[i = scrlx + nscroll], 0, TRUE);
2686 for (++i; i <= scrlx; i++)
2687 PaintItem(menu, items[i], i - (scrlx + nscroll), FALSE);
2688 scrlx += nscroll;
2689 PaintScroller(menu, scrlx + choice, item_no, menu_height);
2690 wnoutrefresh(menu);
2691 wrefresh(dialog);
2692 continue;
2695 i = 0;
2697 else if (menu_height > 1 && key == KEY_NPAGE) {
2698 if (choice == max_choice - 1) {
2699 if (scrlx < max_scroll) {
2700 /* Scroll menu up */
2701 getyx(dialog, cur_y, cur_x);
2703 nscroll = (scrlx + max_choice > max_scroll ?
2704 max_scroll : scrlx + max_choice) - scrlx;
2705 scrollok(menu, TRUE);
2706 wscrl(menu, nscroll);
2707 scrollok(menu, FALSE);
2709 scrlx += nscroll;
2710 for (i = 0; i < max_choice - 1; i++)
2711 PaintItem(menu, items[i + scrlx], i, FALSE);
2712 PaintItem(menu, items[i + scrlx], max_choice - 1, TRUE);
2713 PaintScroller(menu, scrlx + choice, item_no, menu_height);
2714 wnoutrefresh(menu);
2715 wrefresh(dialog);
2716 continue;
2719 i = max_choice - 1;
2721 else if (key == KEY_UP) {
2722 if (!choice) {
2723 if (scrlx) {
2724 /* Scroll menu down */
2725 getyx(dialog, cur_y, cur_x);
2726 if (menu_height > 1) {
2727 PaintItem(menu, items[scrlx], 0, FALSE);
2728 scrollok(menu, TRUE);
2729 wscrl(menu, - 1);
2730 scrollok(menu, FALSE);
2732 scrlx--;
2733 PaintItem(menu, items[scrlx], 0, TRUE);
2734 PaintScroller(menu, scrlx + choice, item_no, menu_height);
2735 wnoutrefresh(menu);
2736 wrefresh(dialog);
2737 continue;
2740 else
2741 i = choice - 1;
2743 else if (key == KEY_DOWN) {
2744 if (choice == max_choice - 1) {
2745 if (scrlx + choice < item_no - 1) {
2746 /* Scroll menu up */
2747 getyx(dialog, cur_y, cur_x);
2748 if (menu_height > 1) {
2749 PaintItem(menu, items[scrlx + max_choice - 1], max_choice - 1, FALSE);
2750 scrollok(menu, TRUE);
2751 scroll(menu);
2752 scrollok(menu, FALSE);
2754 scrlx++;
2755 PaintItem(menu, items[scrlx + max_choice - 1], max_choice - 1, TRUE);
2756 PaintScroller(menu, scrlx + choice, item_no, menu_height);
2757 wnoutrefresh(menu);
2758 wrefresh(dialog);
2759 continue;
2762 else
2763 i = MIN(choice + 1, item_no - 1);
2766 if (i != choice) {
2767 getyx(dialog, cur_y, cur_x);
2768 PaintItem(menu, items[scrlx + choice], choice, FALSE);
2770 choice = i;
2771 PaintItem(menu, items[scrlx + choice], choice, TRUE);
2772 PaintScroller(menu, scrlx + choice, item_no, menu_height);
2773 wnoutrefresh(menu);
2774 wmove(dialog, cur_y, cur_x);
2775 wrefresh(dialog);
2776 continue;
2779 switch (key) {
2780 case TAB:
2781 case KEY_LEFT:
2782 case KEY_RIGHT:
2783 if (!button) {
2784 button = 1;
2785 PaintButton(dialog, label1, y, x1, FALSE);
2786 PaintButton(dialog, label2, y, x2, TRUE);
2788 else {
2789 button = 0;
2790 PaintButton(dialog, label2, y, x2, FALSE);
2791 PaintButton(dialog, label1, y, x1, TRUE);
2793 wrefresh(dialog);
2794 break;
2795 case ' ':
2796 case '\r':
2797 case '\n':
2798 delwin(dialog);
2799 return (!button ? scrlx + choice : -1);
2800 default:
2801 for (i = scrlx + choice + 1; i < item_no; i++)
2802 if (toupper(items[i][0]) == toupper(key))
2803 break;
2804 if (i == item_no) {
2805 for (i = 0; i < scrlx + choice; i++)
2806 if (toupper(items[i][0]) == toupper(key))
2807 break;
2809 getyx(dialog, cur_y, cur_x);
2810 if (i < item_no && i != scrlx + choice) {
2811 if (i >= scrlx && i < scrlx + max_choice) {
2812 /* it is already visible */
2813 PaintItem(menu, items[scrlx + choice], choice, FALSE);
2814 choice = i - scrlx;
2816 else {
2817 scrlx = MIN(i, max_scroll);
2818 choice = i - scrlx;
2819 for (i = 0; i < max_choice; i++)
2820 if (i != choice)
2821 PaintItem(menu, items[scrlx + i], i, FALSE);
2823 PaintItem(menu, items[scrlx + choice], choice, TRUE);
2824 PaintScroller(menu, scrlx + choice, item_no, menu_height);
2825 wnoutrefresh(menu);
2826 wmove(dialog, cur_y, cur_x);
2827 wrefresh(dialog);
2829 break;
2832 /*NOTREACHED*/
2835 static void
2836 PaintItem(WINDOW *win, char *item, int choice, int selected)
2838 int i;
2840 wattrset(win, selected ? title_attr : dialog_attr);
2841 wmove(win, choice, 1);
2842 for (i = 1; i < menu_width; i++)
2843 waddch(win, ' ');
2844 wmove(win, choice, item_x);
2845 wattrset(win, selected ? title_attr : dialog_attr);
2846 waddstr(win, item);
2849 static void
2850 PaintScroller(WINDOW *win, int offset, int lenght, int visible)
2852 int i, pos;
2854 if (lenght > visible)
2855 pos = (visible / (double)lenght) * offset;
2856 else
2857 pos = offset;
2858 wattrset(win, shadow_border_attr);
2859 for (i = 0; i < visible; i++) {
2860 wmove(win, i, 0);
2861 waddch(win, i == pos ? ACS_BLOCK : ACS_VLINE);
2865 static int
2866 DialogCheckBox(char *title, char *prompt, int height, int width, int menu_height,
2867 int item_no, char **items, char *label1, char *label2, char *checks)
2869 int i, x, y, cur_x, cur_y, box_x, box_y, key = 0, button = 0, choice = 0,
2870 scrlx = 0, max_choice, nscroll, max_scroll, x1, x2, l1len, l2len;
2871 WINDOW *dialog, *menu;
2873 max_choice = MIN(menu_height, item_no);
2874 max_scroll = MAX(0, item_no - max_choice);
2876 x = (COLS - width) / 2;
2877 y = (LINES - height) / 2;
2879 dialog = newwin(height, width, y, x);
2880 keypad(dialog, TRUE);
2882 PaintWindow(dialog, title, 0, 0, height, width);
2884 wattrset(dialog, dialog_attr);
2885 PrintWrap(dialog, prompt, width - 3, 2, 3);
2887 l1len = strlen(label1);
2888 l2len = strlen(label2);
2890 x1 = (width - (l1len + l2len)) / 3;
2891 x2 = x1 + x1 + l1len;
2893 menu_width = width - 6;
2894 getyx(dialog, cur_y, cur_x);
2895 box_y = cur_y + 1;
2896 box_x = (width - menu_width) / 2 - 1;
2898 menu = subwin(dialog, menu_height, menu_width, y + box_y + 1, x + box_x + 1);
2899 keypad(menu, TRUE);
2901 /* draw a box around the menu items */
2902 PaintBox(dialog, box_y, box_x, menu_height + 2, menu_width + 2);
2904 item_x = 3;
2906 for (i = 0; i < max_choice; i++)
2907 PaintCheckItem(menu, items[i + scrlx], i, i == 0, checks[i + scrlx]);
2908 PaintScroller(menu, scrlx + choice, item_no, menu_height);
2909 wnoutrefresh(menu);
2911 x = width / 2 - 11;
2912 y = height - 3;
2913 PaintButton(dialog, label2, y, x2, FALSE);
2914 PaintButton(dialog, label1, y, x1, TRUE);
2915 wrefresh(dialog);
2917 /*CONSTCOND*/
2918 while (1) {
2919 i = choice;
2920 key = wgetch(dialog);
2922 if (menu_height > 1 && key == KEY_PPAGE) {
2923 if (!choice) {
2924 if (scrlx) {
2925 /* Scroll menu down */
2926 getyx(dialog, cur_y, cur_x);
2928 nscroll = max_choice > scrlx ? -scrlx : -max_choice;
2929 scrollok(menu, TRUE);
2930 wscrl(menu, nscroll);
2931 scrollok(menu, FALSE);
2933 i = scrlx + nscroll;
2934 PaintCheckItem(menu, items[i], 0, TRUE, checks[i]);
2935 for (++i; i <= scrlx; i++)
2936 PaintCheckItem(menu, items[i], i - (scrlx + nscroll), FALSE, checks[i]);
2937 scrlx += nscroll;
2938 PaintScroller(menu, scrlx + choice, item_no, menu_height);
2939 wnoutrefresh(menu);
2940 wrefresh(dialog);
2941 continue;
2944 i = 0;
2946 else if (menu_height > 1 && key == KEY_NPAGE) {
2947 if (choice == max_choice - 1) {
2948 if (scrlx < max_scroll) {
2949 /* Scroll menu up */
2950 getyx(dialog, cur_y, cur_x);
2952 nscroll = (scrlx + max_choice > max_scroll ?
2953 max_scroll : scrlx + max_choice) - scrlx;
2954 scrollok(menu, TRUE);
2955 wscrl(menu, nscroll);
2956 scrollok(menu, FALSE);
2958 scrlx += nscroll;
2959 for (i = 0; i < max_choice - 1; i++)
2960 PaintCheckItem(menu, items[i + scrlx], i, FALSE, checks[i + scrlx]);
2961 PaintCheckItem(menu, items[i + scrlx], max_choice - 1, TRUE, checks[i + scrlx]);
2962 PaintScroller(menu, scrlx + choice, item_no, menu_height);
2963 wnoutrefresh(menu);
2964 wrefresh(dialog);
2965 continue;
2968 i = max_choice - 1;
2970 else if (key == KEY_UP) {
2971 if (!choice) {
2972 if (scrlx) {
2973 /* Scroll menu down */
2974 getyx(dialog, cur_y, cur_x);
2975 if (menu_height > 1) {
2976 PaintCheckItem(menu, items[scrlx], 0, FALSE, checks[scrlx]);
2977 scrollok(menu, TRUE);
2978 wscrl(menu, - 1);
2979 scrollok(menu, FALSE);
2981 scrlx--;
2982 PaintCheckItem(menu, items[scrlx], 0, TRUE, checks[scrlx]);
2983 PaintScroller(menu, scrlx + choice, item_no, menu_height);
2984 wnoutrefresh(menu);
2985 wrefresh(dialog);
2986 continue;
2989 else
2990 i = choice - 1;
2992 else if (key == KEY_DOWN) {
2993 if (choice == max_choice - 1) {
2994 if (scrlx + choice < item_no - 1) {
2995 /* Scroll menu up */
2996 getyx(dialog, cur_y, cur_x);
2997 if (menu_height > 1) {
2998 PaintCheckItem(menu, items[scrlx + max_choice - 1], max_choice - 1, FALSE, checks[scrlx + max_choice - 1]);
2999 scrollok(menu, TRUE);
3000 scroll(menu);
3001 scrollok(menu, FALSE);
3003 scrlx++;
3004 PaintCheckItem(menu, items[scrlx + max_choice - 1], max_choice - 1, TRUE, checks[scrlx + max_choice - 1]);
3005 PaintScroller(menu, scrlx + choice, item_no, menu_height);
3006 wnoutrefresh(menu);
3007 wrefresh(dialog);
3008 continue;
3011 else
3012 i = MIN(choice + 1, item_no - 1);
3015 if (i != choice) {
3016 getyx(dialog, cur_y, cur_x);
3017 PaintCheckItem(menu, items[scrlx + choice], choice, FALSE, checks[scrlx + choice]);
3019 choice = i;
3020 PaintCheckItem(menu, items[scrlx + choice], choice, TRUE, checks[scrlx + choice]);
3021 PaintScroller(menu, scrlx + choice, item_no, menu_height);
3022 wnoutrefresh(menu);
3023 wmove(dialog, cur_y, cur_x);
3024 wrefresh(dialog);
3025 continue;
3028 switch (key) {
3029 case TAB:
3030 case KEY_LEFT:
3031 case KEY_RIGHT:
3032 if (!button) {
3033 button = 1;
3034 PaintButton(dialog, label1, y, x1, FALSE);
3035 PaintButton(dialog, label2, y, x2, TRUE);
3037 else {
3038 button = 0;
3039 PaintButton(dialog, label2, y, x2, FALSE);
3040 PaintButton(dialog, label1, y, x1, TRUE);
3042 wrefresh(dialog);
3043 break;
3044 case ' ':
3045 getyx(dialog, cur_y, cur_x);
3046 checks[scrlx + choice] = !checks[scrlx + choice];
3047 PaintCheckItem(menu, items[scrlx + choice], choice, TRUE, checks[scrlx + choice]);
3048 wmove(dialog, cur_y, cur_x);
3049 wnoutrefresh(menu);
3050 wrefresh(dialog);
3051 break;
3052 case '\r':
3053 case '\n':
3054 delwin(dialog);
3055 return (!button ? 0 : -1);
3056 default:
3057 for (i = scrlx + choice + 1; i < item_no; i++)
3058 if (toupper(items[i][0]) == toupper(key))
3059 break;
3060 if (i == item_no) {
3061 for (i = 0; i < scrlx + choice; i++)
3062 if (toupper(items[i][0]) == toupper(key))
3063 break;
3065 getyx(dialog, cur_y, cur_x);
3066 if (i < item_no && i != scrlx + choice) {
3067 if (i >= scrlx && i < scrlx + max_choice) {
3068 /* it is already visible */
3069 PaintCheckItem(menu, items[scrlx + choice], choice, FALSE, checks[scrlx + choice]);
3070 choice = i - scrlx;
3072 else {
3073 scrlx = MIN(i, max_scroll);
3074 choice = i - scrlx;
3075 for (i = 0; i < max_choice; i++)
3076 if (i != choice)
3077 PaintCheckItem(menu, items[scrlx + i], i, FALSE, checks[scrlx + i]);
3079 PaintCheckItem(menu, items[scrlx + choice], choice, TRUE, checks[scrlx + choice]);
3080 PaintScroller(menu, scrlx + choice, item_no, menu_height);
3081 wnoutrefresh(menu);
3082 wmove(dialog, cur_y, cur_x);
3083 wrefresh(dialog);
3085 break;
3088 /*NOTREACHED*/
3091 static void
3092 PaintCheckItem(WINDOW *win, char *item, int choice, int selected, int checked)
3094 int i;
3096 wattrset(win, selected ? title_attr : dialog_attr);
3097 wmove(win, choice, 1);
3098 for (i = 1; i < menu_width; i++)
3099 waddch(win, ' ');
3100 wmove(win, choice, item_x);
3101 wattrset(win, selected ? title_attr : dialog_attr);
3102 wprintw(win, "[%c] ", checked ? 'X' : ' ');
3103 waddstr(win, item);
3106 static char *
3107 DialogInput(char *title, char *prompt, int height, int width, char *init,
3108 char *label1, char *label2, int def_button)
3110 int i, x, y, box_y, box_x, box_width, len,
3111 input_x = 0, scrlx = 0, key = 0, button = -1, x1, x2, l1len, l2len;
3112 char instr[1024 + 1];
3113 WINDOW *dialog;
3115 x = (COLS - width) / 2;
3116 y = (LINES - height) / 2;
3118 dialog = newwin(height, width, y, x);
3119 keypad(dialog, TRUE);
3121 PaintWindow(dialog, title, 0, 0, height, width);
3123 wattrset(dialog, dialog_attr);
3124 PrintWrap(dialog, prompt, width - 3, 2, 3);
3126 l1len = strlen(label1);
3127 l2len = strlen(label2);
3129 x1 = (width - (l1len + l2len)) / 3;
3130 x2 = x1 + x1 + l1len;
3132 box_width = width - 6;
3133 getyx(dialog, y, x);
3134 box_y = y + 2;
3135 box_x = (width - box_width) / 2;
3136 PaintBox(dialog, y + 1, box_x - 1, 3, box_width + 2);
3138 x = width / 2 - 11;
3139 y = height - 3;
3140 PaintButton(dialog, label2, y, x2, def_button == 1);
3141 PaintButton(dialog, label1, y, x1, def_button == 0);
3143 memset(instr, '\0', sizeof(instr));
3144 wmove(dialog, box_y, box_x);
3145 wattrset(dialog, dialog_attr);
3146 if (init)
3147 strncpy(instr, init, sizeof(instr) - 2);
3149 input_x = len = strlen(instr);
3150 if (input_x >= box_width) {
3151 scrlx = input_x - box_width + 1;
3152 input_x = box_width - 1;
3153 for (i = 0; i < box_width - 1; i++)
3154 waddch(dialog, instr[scrlx + i]);
3156 else
3157 waddstr(dialog, instr);
3159 wmove(dialog, box_y, box_x + input_x);
3161 wrefresh(dialog);
3163 while (1) {
3164 key = wgetch(dialog);
3165 if (button == -1) { /* Input box selected */
3166 switch (key) {
3167 case TAB:
3168 case KEY_UP:
3169 case KEY_DOWN:
3170 break;
3171 case KEY_LEFT:
3172 if (scrlx && !input_x) {
3173 --scrlx;
3174 wmove(dialog, box_y, box_x);
3175 for (i = 0; i < box_width; i++)
3176 waddch(dialog, instr[scrlx + input_x + i] ? instr[scrlx + input_x + i] : ' ');
3177 wmove(dialog, box_y, input_x + box_x);
3178 wrefresh(dialog);
3180 else if (input_x) {
3181 wmove(dialog, box_y, --input_x + box_x);
3182 wrefresh(dialog);
3184 continue;
3185 case KEY_RIGHT:
3186 if (input_x + scrlx < len) {
3187 if (input_x == box_width - 1) {
3188 ++scrlx;
3189 wmove(dialog, box_y, box_x);
3190 for (i = scrlx; i < scrlx + box_width; i++)
3191 waddch(dialog, instr[i] ? instr[i] : ' ');
3192 wmove(dialog, box_y, input_x + box_x);
3193 wrefresh(dialog);
3195 else {
3196 wmove(dialog, box_y, ++input_x + box_x);
3197 wrefresh(dialog);
3200 continue;
3201 case KEY_BACKSPACE:
3202 case 0177:
3203 #if defined(__SCO__) || defined(__UNIXWARE__)
3204 case '\b':
3205 #endif
3206 if (input_x || scrlx) {
3207 wattrset(dialog, dialog_attr);
3209 if (scrlx + input_x < len)
3210 memmove(instr + scrlx + input_x - 1,
3211 instr + scrlx + input_x,
3212 len - (scrlx + input_x));
3213 instr[--len] = '\0';
3215 if (!input_x) {
3216 scrlx = scrlx < box_width - 1 ? 0 : scrlx - (box_width - 1);
3217 wmove(dialog, box_y, box_x);
3218 for (i = 0; i < box_width; i++)
3219 waddch(dialog, instr[scrlx + input_x + i] ? instr[scrlx + input_x + i] : ' ');
3220 input_x = len - scrlx;
3222 else {
3223 wmove(dialog, box_y, --input_x + box_x);
3224 for (i = scrlx + input_x; i < len &&
3225 i < scrlx + box_width; i++)
3226 waddch(dialog, instr[i]);
3227 if (i < scrlx + box_width)
3228 waddch(dialog, ' ');
3230 wmove(dialog, box_y, input_x + box_x);
3231 wrefresh(dialog);
3233 continue;
3234 case KEY_HOME:
3235 case CONTROL_A:
3236 wmove(dialog, box_y, box_x);
3237 if (scrlx != 0) {
3238 scrlx = 0;
3239 for (i = 0; i < box_width; i++)
3240 waddch(dialog, instr[i] ? instr[i] : ' ');
3242 input_x = 0;
3243 wmove(dialog, box_y, box_x);
3244 wrefresh(dialog);
3245 break;
3246 case CONTROL_D:
3247 if (input_x + scrlx < len) {
3248 memmove(instr + scrlx + input_x,
3249 instr + scrlx + input_x + 1,
3250 len - (scrlx + input_x));
3251 instr[--len] = '\0';
3252 for (i = scrlx + input_x; i < len &&
3253 i < scrlx + box_width; i++)
3254 waddch(dialog, instr[i]);
3255 if (i < scrlx + box_width)
3256 waddch(dialog, ' ');
3257 wmove(dialog, box_y, input_x + box_x);
3258 wrefresh(dialog);
3260 break;
3261 case CONTROL_E:
3262 case KEY_END:
3263 if (box_width + scrlx < len) {
3264 input_x = box_width - 1;
3265 scrlx = len - box_width + 1;
3266 wmove(dialog, box_y, box_x);
3267 for (i = scrlx; i < scrlx + box_width; i++)
3268 waddch(dialog, instr[i] ? instr[i] : ' ');
3269 wmove(dialog, box_y, input_x + box_x);
3270 wrefresh(dialog);
3272 else {
3273 input_x = len - scrlx;
3274 wmove(dialog, box_y, input_x + box_x);
3275 wrefresh(dialog);
3277 break;
3278 case CONTROL_K:
3279 if (len) {
3280 for (i = input_x; i < box_width; i++)
3281 waddch(dialog, ' ');
3282 for (i = scrlx + input_x; i < len; i++)
3283 instr[i] = '\0';
3284 len = scrlx + input_x;
3285 wmove(dialog, box_y, box_x + input_x);
3286 wrefresh(dialog);
3288 break;
3289 default:
3290 if (key < 0x100 && isprint(key)) {
3291 if (scrlx + input_x < sizeof(instr) - 1) {
3292 wattrset(dialog, dialog_attr);
3293 if (scrlx + input_x < len) {
3294 memmove(instr + scrlx + input_x + 1,
3295 instr + scrlx + input_x,
3296 len - (scrlx + input_x));
3298 instr[scrlx + input_x] = key;
3299 instr[++len] = '\0';
3300 if (input_x == box_width - 1) {
3301 scrlx++;
3302 wmove(dialog, box_y, box_x);
3303 for (i = 0; i < box_width - 1; i++)
3304 waddch(dialog, instr[scrlx + i]);
3306 else {
3307 wmove(dialog, box_y, input_x++ + box_x);
3308 for (i = scrlx + input_x - 1; i < len &&
3309 i < scrlx + box_width; i++)
3310 waddch(dialog, instr[i]);
3311 wmove(dialog, box_y, input_x + box_x);
3313 wrefresh(dialog);
3315 else
3316 flash(); /* Alarm user about overflow */
3317 continue;
3322 switch (key) {
3323 case KEY_UP:
3324 case KEY_LEFT:
3325 switch (button) {
3326 case -1:
3327 button = 1; /* Indicates "Cancel" button is selected */
3328 PaintButton(dialog, label1, y, x1, FALSE);
3329 PaintButton(dialog, label2, y, x2, TRUE);
3330 wrefresh(dialog);
3331 break;
3332 case 0:
3333 button = -1; /* Indicates input box is selected */
3334 PaintButton(dialog, label2, y, x2, FALSE);
3335 PaintButton(dialog, label1, y, x1, TRUE);
3336 wmove(dialog, box_y, box_x + input_x);
3337 wrefresh(dialog);
3338 break;
3339 case 1:
3340 button = 0; /* Indicates "OK" button is selected */
3341 PaintButton(dialog, label2, y, x2, FALSE);
3342 PaintButton(dialog, label1, y, x1, TRUE);
3343 wrefresh(dialog);
3344 break;
3346 break;
3347 case TAB:
3348 case KEY_DOWN:
3349 case KEY_RIGHT:
3350 switch (button) {
3351 case -1:
3352 button = 0; /* Indicates "OK" button is selected */
3353 PaintButton(dialog, label2, y, x2, FALSE);
3354 PaintButton(dialog, label1, y, x1, TRUE);
3355 wrefresh(dialog);
3356 break;
3357 case 0:
3358 button = 1; /* Indicates "Cancel" button is selected */
3359 PaintButton(dialog, label1, y, x1, FALSE);
3360 PaintButton(dialog, label2, y, x2, TRUE);
3361 wrefresh(dialog);
3362 break;
3363 case 1:
3364 button = -1; /* Indicates input box is selected */
3365 PaintButton(dialog, label2, y, x2, FALSE);
3366 PaintButton(dialog, label1, y, x1, TRUE);
3367 wmove(dialog, box_y, box_x + input_x);
3368 wrefresh(dialog);
3369 break;
3371 break;
3372 case ' ':
3373 case '\r':
3374 case '\n':
3375 delwin(dialog);
3376 return (button != 1 ? XtNewString(instr) : NULL);