788 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			788 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
 | |
|  * 
 | |
|  * Permission is hereby granted, free of charge, to any person obtaining a
 | |
|  * copy of this software and associated documentation files (the "Software"),
 | |
|  * to deal in the Software without restriction, including without limitation
 | |
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | |
|  * and/or sell copies of the Software, and to permit persons to whom the
 | |
|  * Software is furnished to do so, subject to the following conditions:
 | |
|  * 
 | |
|  * The above copyright notice and this permission notice shall be included in
 | |
|  * all copies or substantial portions of the Software.
 | |
|  *  
 | |
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 | |
|  * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 | |
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
 | |
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | |
|  * SOFTWARE.
 | |
|  * 
 | |
|  * Except as contained in this notice, the name of Conectiva Linux shall
 | |
|  * not be used in advertising or otherwise to promote the sale, use or other
 | |
|  * dealings in this Software without prior written authorization from
 | |
|  * Conectiva Linux.
 | |
|  *
 | |
|  * Author: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #include "options.h"
 | |
| #include "xf86config.h"
 | |
| #include <X11/Xresource.h>
 | |
| #include <X11/Shell.h>
 | |
| #include <X11/Xaw/AsciiText.h>
 | |
| #include <X11/Xaw/List.h>
 | |
| #include <X11/Xaw/Command.h>
 | |
| #include <X11/Xaw/MenuButton.h>
 | |
| #include <X11/Xaw/Paned.h>
 | |
| #include <X11/Xaw/SimpleMenP.h>
 | |
| #include <X11/Xaw/SmeBSB.h>
 | |
| #include <X11/Xaw/Viewport.h>
 | |
| #include <ctype.h>
 | |
| 
 | |
| /*
 | |
|  * Prototypes
 | |
|  */
 | |
| static void PopdownCallback(Widget, XtPointer, XtPointer);
 | |
| static void SelectOptionCallback(Widget, XtPointer, XtPointer);
 | |
| static void AddOption(Widget, XtPointer, XtPointer);
 | |
| static void RemoveOption(Widget, XtPointer, XtPointer);
 | |
| static void UpdateOption(Widget, XtPointer, XtPointer);
 | |
| static void UpdateOptionList(void);
 | |
| #ifdef USE_MODULES
 | |
| static void AddDriverOption(Widget, XtPointer, XtPointer);
 | |
| static void SelectModuleCallback(Widget, XtPointer, XtPointer);
 | |
| static void SelectModuleOptionCallback(Widget, XtPointer, XtPointer);
 | |
| static void ModuleOptionsPopdown(Widget, XtPointer, XtPointer);
 | |
| #endif
 | |
| static Bool EnumDatabase(XrmDatabase*, XrmBindingList, XrmQuarkList,
 | |
| 			 XrmRepresentation*, XrmValue*, XPointer);
 | |
| 
 | |
| /*
 | |
|  * Initialization
 | |
|  */
 | |
| Widget optionsShell;
 | |
| static XF86OptionPtr *options;
 | |
| static Widget add, remov, update, list, name, value;
 | |
| static char *option_str;
 | |
| static int option_index, popped = False;
 | |
| static char *Options = "lib/X11/Options";
 | |
| XrmDatabase options_xrm;
 | |
| struct {
 | |
|     char *string;
 | |
|     int offset;
 | |
| } rebuild_xrm;
 | |
| #ifdef USE_MODULES
 | |
| static Widget modList, optList, desc, modOptionsShell, labelType;
 | |
| static char *module_sel;
 | |
| static char *types[] = {
 | |
|     "none", "integer", "(non null) string", "string", "real",
 | |
|     "boolean", "frequency",
 | |
| };
 | |
| #endif
 | |
| 
 | |
| /*
 | |
|  * Implementation
 | |
|  */
 | |
| #ifdef USE_MODULES
 | |
| static int
 | |
| qcmp_str(_Xconst void *a, _Xconst void *b)
 | |
| {
 | |
|     return (strcmp(*(char**)a, *(char**)b));
 | |
| }
 | |
| 
 | |
| void
 | |
| ModuleOptionsPopup(Widget w, XtPointer user_data, XtPointer call_data)
 | |
| {
 | |
|     xf86cfgModuleOptions *info = module_options;
 | |
| 
 | |
|     if (modOptionsShell == NULL) {
 | |
| 	char **ops;
 | |
| 	int nops;
 | |
| 	Widget pane, form, viewport, bottom, popdown;
 | |
| 
 | |
| 	modOptionsShell = XtCreatePopupShell("moduleOptions",
 | |
| 					     transientShellWidgetClass,
 | |
| 					     optionsShell, NULL, 0);
 | |
| 
 | |
| 	pane = XtCreateManagedWidget("pane", panedWidgetClass,
 | |
| 				     modOptionsShell, NULL, 0);
 | |
| 
 | |
| 	form = XtCreateManagedWidget("descriptions", formWidgetClass,
 | |
| 				     pane, NULL, 0);
 | |
| 	labelType = XtCreateManagedWidget("labelType", labelWidgetClass,
 | |
| 					  form, NULL, 0);
 | |
| 	XtCreateManagedWidget("module", labelWidgetClass, form, NULL, 0);
 | |
| 	viewport = XtCreateManagedWidget("viewM", viewportWidgetClass,
 | |
| 					 form, NULL, 0);
 | |
| 	ops = NULL;
 | |
| 	nops = 0;
 | |
| 	while (info) {
 | |
| 	    ++nops;
 | |
| 	    ops = (char**)XtRealloc((XtPointer)ops, sizeof(char*) * nops);
 | |
| 	    ops[nops - 1] = XtNewString(info->name);
 | |
| 	    info = info->next;
 | |
| 	}
 | |
| 	if (nops == 0) {
 | |
| 	    ops = (char**)XtMalloc(sizeof(char*));
 | |
| 	    ops[0] = XtNewString("");
 | |
| 	    nops = 1;
 | |
| 	}
 | |
| 	else
 | |
| 	    qsort(ops, nops, sizeof(char*), qcmp_str);
 | |
| 	modList = XtVaCreateManagedWidget("modL", listWidgetClass,
 | |
| 					  viewport, XtNlist, ops,
 | |
| 					  XtNnumberStrings, nops,
 | |
| 					  NULL);
 | |
| 	XtAddCallback(modList, XtNcallback, SelectModuleCallback, NULL);
 | |
| 	XtCreateManagedWidget("option", labelWidgetClass, form, NULL, 0);
 | |
| 	viewport = XtCreateManagedWidget("viewO", viewportWidgetClass,
 | |
| 					 form, NULL, 0);
 | |
| 	ops = (char**)XtMalloc(sizeof(char*));
 | |
| 	ops[0] = XtNewString("");
 | |
| 	optList = XtVaCreateManagedWidget("optL", listWidgetClass,
 | |
| 					  viewport, XtNlist, ops,
 | |
| 					  XtNnumberStrings, 1, NULL);
 | |
| 	XtAddCallback(optList, XtNcallback, SelectModuleOptionCallback, NULL);
 | |
| 	desc = XtVaCreateManagedWidget("desc", asciiTextWidgetClass,
 | |
| 				       form, XtNeditType, XawtextRead,
 | |
| 				       NULL);
 | |
| 
 | |
| 	bottom = XtCreateManagedWidget("bottom", formWidgetClass,
 | |
| 				       pane, NULL, 0);
 | |
| 	popdown = XtVaCreateManagedWidget("popdown", commandWidgetClass,
 | |
| 					bottom, NULL);
 | |
| 	XtAddCallback(popdown, XtNcallback, ModuleOptionsPopdown, NULL);
 | |
| 	XtRealizeWidget(modOptionsShell);
 | |
| 	XSetWMProtocols(DPY, XtWindow(modOptionsShell), &wm_delete_window, 1);
 | |
| 
 | |
| 	info = module_options;
 | |
|     }
 | |
| 
 | |
|     if (module_sel && *module_sel) {
 | |
| 	XawListReturnStruct list;	/* hack to call ballbacks */
 | |
| 	char **strs;
 | |
| 	int nstrs, idx = 0;
 | |
| 
 | |
| 	XtVaGetValues(modList, XtNlist, &strs, XtNnumberStrings, &nstrs, NULL);
 | |
| 	for (idx = nstrs - 1; idx > 0; idx--)
 | |
| 	    if (strcmp(module_sel, strs[idx]) == 0)
 | |
| 		break;
 | |
| 	while (info) {
 | |
| 	    if (strcmp(module_sel, info->name) == 0)
 | |
| 		break;
 | |
| 	    info = info->next;
 | |
| 	}
 | |
| 	if (info) {
 | |
| 	    list.string = info->name;
 | |
| 	    list.list_index = idx;
 | |
| 	    XawListHighlight(modList, idx);
 | |
| 	    SelectModuleCallback(modList, NULL, (XtPointer)&list);
 | |
| 	}
 | |
| 	if (option_str && *option_str) {
 | |
| 	    OptionInfoPtr opts = info->option;
 | |
| 
 | |
| 	    idx = 0;
 | |
| 	    while (opts && opts->name) {
 | |
| 		if (strcmp(opts->name, option_str) == 0)
 | |
| 		    break;
 | |
| 		++idx;
 | |
| 		++opts;
 | |
| 	    }
 | |
| 
 | |
| 	    if (opts && opts->name) {
 | |
| 		list.string = (char *)opts->name;
 | |
| 		list.list_index = idx;
 | |
| 		XawListHighlight(optList, idx);
 | |
| 		SelectModuleOptionCallback(optList, NULL, (XtPointer)&list);
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     XtPopup(modOptionsShell, XtGrabNone);
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static void
 | |
| ModuleOptionsPopdown(Widget w, XtPointer user_data, XtPointer call_data)
 | |
| {
 | |
|     XtPopdown(modOptionsShell);
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| void
 | |
| ModuleOptionsCancelAction(Widget w, XEvent *event,
 | |
| 			  String *params, Cardinal *num_params)
 | |
| {
 | |
|     ModuleOptionsPopdown(w, NULL, NULL);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| void
 | |
| CreateOptionsShell(void)
 | |
| {
 | |
|     optionsShell = XtCreatePopupShell("options", transientShellWidgetClass,
 | |
| 				      toplevel, NULL, 0);
 | |
| }
 | |
| 
 | |
| #ifdef USE_MODULES
 | |
| void
 | |
| OptionsPopup(XF86OptionPtr *opts, char *driver, OptionInfoPtr drv_opts)
 | |
| #else
 | |
| void
 | |
| OptionsPopup(XF86OptionPtr *opts)
 | |
| #endif
 | |
| {
 | |
|     static int first = 1;
 | |
| #ifdef USE_MODULES
 | |
|     static Widget button, menu;
 | |
|     static char label[256], menuName[16];
 | |
|     Widget sme;
 | |
|     char buf[256];
 | |
|     int i = 0;
 | |
|     Arg args[1];
 | |
|     static int menuN;
 | |
| #endif
 | |
| 
 | |
|     option_str = NULL;
 | |
|     options = opts;
 | |
|     if (first) {
 | |
| 	Widget pane, form, viewport, bottom, popdown;
 | |
| 
 | |
| 	first = 0;
 | |
| 
 | |
| 	if (optionsShell == NULL)
 | |
| 	    CreateOptionsShell();
 | |
| 	pane = XtCreateManagedWidget("pane", panedWidgetClass,
 | |
| 				     optionsShell, NULL, 0);
 | |
| 
 | |
| 	form = XtCreateManagedWidget("commands", formWidgetClass,
 | |
| 				     pane, NULL, 0);
 | |
| 	add = XtCreateManagedWidget("add", commandWidgetClass,
 | |
| 				    form, NULL, 0);
 | |
| 	XtAddCallback(add, XtNcallback, AddOption, NULL);
 | |
| 	remov = XtCreateManagedWidget("remove", commandWidgetClass,
 | |
| 				      form, NULL, 0);
 | |
| 	XtAddCallback(remov, XtNcallback, RemoveOption, NULL);
 | |
| 	update = XtCreateManagedWidget("update", commandWidgetClass,
 | |
| 				       form, NULL, 0);
 | |
| 	XtAddCallback(update, XtNcallback, UpdateOption, NULL);
 | |
| #ifdef USE_MODULES
 | |
| 	if (!nomodules) {
 | |
| 	    Widget command;
 | |
| 
 | |
| 	    command = XtCreateManagedWidget("help", commandWidgetClass,
 | |
| 					    form, NULL, 0);
 | |
| 	    XtAddCallback(command, XtNcallback, ModuleOptionsPopup, NULL);
 | |
| 	}
 | |
| #endif
 | |
| 	form = XtCreateManagedWidget("form", formWidgetClass,
 | |
| 				     pane, NULL, 0);
 | |
| 	XtVaCreateManagedWidget("label1", labelWidgetClass, form,
 | |
| 				XtNlabel, " Option \"",
 | |
| 				NULL);
 | |
| 	name = XtVaCreateManagedWidget("name", asciiTextWidgetClass, form,
 | |
| 				       XtNeditType, XawtextEdit,
 | |
| 				       NULL);
 | |
| 	XtVaCreateManagedWidget("label2", labelWidgetClass,
 | |
| 				form,
 | |
| 				XtNlabel, "\" \"",
 | |
| 				NULL);
 | |
| 	value = XtVaCreateManagedWidget("value", asciiTextWidgetClass, form,
 | |
| 					XtNeditType, XawtextEdit,
 | |
| 					NULL);
 | |
| 	XtVaCreateManagedWidget("label3", labelWidgetClass, form,
 | |
| 				XtNlabel, "\" ",
 | |
| 				NULL);
 | |
| 	viewport = XtCreateManagedWidget("viewport", viewportWidgetClass,
 | |
| 					 form, NULL, 0);
 | |
| 	list = XtCreateManagedWidget("list", listWidgetClass,
 | |
| 				     viewport, NULL, 0);
 | |
| 	XtAddCallback(list, XtNcallback, SelectOptionCallback, NULL);
 | |
| 	bottom = XtCreateManagedWidget("bottom", formWidgetClass,
 | |
| 				       pane, NULL, 0);
 | |
| #ifdef USE_MODULES
 | |
| 	if (!nomodules)
 | |
| 	    button = XtCreateManagedWidget("driverOpts", menuButtonWidgetClass,
 | |
| 					    bottom, NULL, 0);
 | |
| #endif
 | |
| 	popdown = XtVaCreateManagedWidget("popdown", commandWidgetClass,
 | |
| 					bottom, NULL);
 | |
| #ifdef USE_MODULES
 | |
| 	if (!nomodules)
 | |
| 	    XtVaSetValues(popdown, XtNfromHoriz, button, NULL);
 | |
| #endif
 | |
| 
 | |
| 	XtAddCallback(popdown, XtNcallback, PopdownCallback, NULL);
 | |
| 	XtRealizeWidget(optionsShell);
 | |
| 	XSetWMProtocols(DPY, XtWindow(optionsShell), &wm_delete_window, 1);
 | |
| 
 | |
| #ifdef USE_MODULES
 | |
| 	if (!nomodules) {
 | |
| 	    char *str;
 | |
| 
 | |
| 	    XtSetArg(args[0], XtNlabel, &str);
 | |
| 	    XtGetValues(button, args, 1);
 | |
| 	    XmuSnprintf(label, sizeof(label), "%s", str);
 | |
| 	}
 | |
| #endif
 | |
|     }
 | |
| 
 | |
| #ifdef USE_MODULES
 | |
|     if (!nomodules) {
 | |
| 	if (menu)
 | |
| 	    XtDestroyWidget(menu);
 | |
| 	XmuSnprintf(menuName, sizeof(menuName), "optionM%d", menuN);
 | |
| 	menuN = !menuN;
 | |
| 	menu = XtCreatePopupShell(menuName, simpleMenuWidgetClass, button,
 | |
| 				  NULL, 0);
 | |
| 	XtVaSetValues(button, XtNmenuName, menuName, NULL);
 | |
| 	if (drv_opts) {
 | |
| 	    int len, longest = 0;
 | |
| 	    char fmt[32];
 | |
| 
 | |
| 	    for (i = 0; drv_opts[i].name != NULL; i++) {
 | |
| 		len = strlen(drv_opts[i].name);
 | |
| 		if (len > longest)
 | |
| 		    longest = len;
 | |
| 	    }
 | |
| 	    XmuSnprintf(fmt, sizeof(fmt), "%c-%ds  %%s", '%', longest);
 | |
| 	    for (; drv_opts->name != NULL; drv_opts++) {
 | |
| 		char *type;
 | |
| 
 | |
| 		if (drv_opts->type >= OPTV_NONE && drv_opts->type <= OPTV_FREQ)
 | |
| 		    type = types[drv_opts->type];
 | |
| 		else
 | |
| 		    type = "UNKNOWN";
 | |
| 
 | |
| 		XmuSnprintf(buf, sizeof(buf), fmt, drv_opts->name, type);
 | |
| 		sme = XtVaCreateManagedWidget(drv_opts->name, smeBSBObjectClass,
 | |
| 					      menu, XtNlabel, buf, NULL);
 | |
| 		XtAddCallback(sme, XtNcallback, AddDriverOption, (XtPointer)drv_opts);
 | |
| 	    }
 | |
| 	}
 | |
| 	if (i) {
 | |
| 	    xf86cfgModuleOptions *mod = module_options;
 | |
| 
 | |
| 	    while (mod) {
 | |
| 		if (strcmp(mod->name, driver) == 0) {
 | |
| 		    /* don't assign to driver, as it may be a temp string */
 | |
| 		    module_sel = mod->name;
 | |
| 		    break;
 | |
| 		}
 | |
| 		mod = mod->next;
 | |
| 	    }
 | |
| 	    XmuSnprintf(buf, sizeof(buf), "%s%s", label, driver);
 | |
| 	    XtSetArg(args[0], XtNlabel, buf);
 | |
| 	    XtSetValues(button, args, 1);
 | |
| 	    XtMapWidget(button);
 | |
| 	}
 | |
| 	else
 | |
| 	    XtUnmapWidget(button);
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     UpdateOptionList();
 | |
|     popped = True;
 | |
|     XtPopup(optionsShell, XtGrabExclusive);
 | |
| 
 | |
|     while (popped)
 | |
| 	XtAppProcessEvent(XtWidgetToApplicationContext(optionsShell), XtIMAll);
 | |
| }
 | |
| 
 | |
| static void
 | |
| UpdateOptionList(void)
 | |
| {
 | |
|     Arg args[2];
 | |
|     char **ops, **oldops;
 | |
|     int nops, oldnops;
 | |
|     XF86OptionPtr opt;
 | |
| 
 | |
|     ops = NULL;
 | |
|     nops = 0;
 | |
|     XawListUnhighlight(list);
 | |
|     XtSetArg(args[0], XtNlist, &oldops);
 | |
|     XtSetArg(args[1], XtNnumberStrings, &oldnops);
 | |
|     XtGetValues(list, args, 2);
 | |
|     opt = *options;
 | |
|     while (opt != NULL) {
 | |
| 	if (nops % 16 == 0)
 | |
| 	    ops = (char**)XtRealloc((XtPointer)ops, (nops + 16) *
 | |
| 				    sizeof(char*));
 | |
| 	ops[nops++] = XtNewString(opt->opt_name);
 | |
| 	opt = (XF86OptionPtr)(opt->list.next);
 | |
|     }
 | |
|     if (nops == 0) {
 | |
| 	ops = (char**)XtMalloc(sizeof(char*));
 | |
| 	ops[0] = XtNewString("");
 | |
| 	nops = 1;
 | |
|     }
 | |
|     XtSetArg(args[0], XtNlist, ops);
 | |
|     XtSetArg(args[1], XtNnumberStrings, nops);
 | |
|     XtSetValues(list, args, 2);
 | |
|     if (oldnops > 0 &&
 | |
| 	(oldnops != 1 || XtName(list) != oldops[0])) {
 | |
| 	while (--oldnops >= 0)
 | |
| 	    XtFree(oldops[oldnops]);
 | |
| 	XtFree((XtPointer)oldops);
 | |
|     }
 | |
| 
 | |
|     XtSetArg(args[0], XtNstring, "");
 | |
|     XtSetValues(name, args, 1);
 | |
|     XtSetValues(value, args, 1);
 | |
| 
 | |
|     /* force relayout */
 | |
|     XtUnmanageChild(list);
 | |
|     XtManageChild(list);
 | |
| 
 | |
|     XtSetSensitive(remov, False);
 | |
|     XtSetSensitive(update, False);
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static void
 | |
| PopdownCallback(Widget w, XtPointer user_data, XtPointer call_data)
 | |
| {
 | |
|     XtPopdown(optionsShell);
 | |
|     popped = False;
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| void
 | |
| OptionsCancelAction(Widget w, XEvent *event,
 | |
| 		    String *params, Cardinal *num_params)
 | |
| {
 | |
|     PopdownCallback(w, NULL, NULL);
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static void
 | |
| SelectOptionCallback(Widget w, XtPointer user_data, XtPointer call_data)
 | |
| {
 | |
|     Arg args[1];
 | |
|     XF86OptionPtr option;
 | |
|     XawListReturnStruct *info = (XawListReturnStruct *)call_data;
 | |
| 
 | |
|     option_str = info->string;
 | |
|     option_index = info->list_index;
 | |
|     if ((option = xf86findOption(*options, info->string)) != NULL) {
 | |
| 	XtSetArg(args[0], XtNstring, option->opt_name);
 | |
| 	XtSetValues(name, args, 1);
 | |
| 	XtSetArg(args[0], XtNstring,
 | |
| 		 option->opt_val != NULL ? option->opt_val : "");
 | |
| 	XtSetValues(value, args, 1);
 | |
|     }
 | |
|     XtSetSensitive(remov, True);
 | |
|     XtSetSensitive(update, True);
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static void
 | |
| AddOption(Widget w, XtPointer user_data, XtPointer call_data)
 | |
| {
 | |
|     Arg args[1];
 | |
|     char *nam, *val;
 | |
| 
 | |
|     XtSetArg(args[0], XtNstring, &nam);
 | |
|     XtGetValues(name, args, 1);
 | |
|     XtSetArg(args[0], XtNstring, &val);
 | |
|     XtGetValues(value, args, 1);
 | |
|     if (xf86findOption(*options, nam) != NULL || strlen(nam) == 0)
 | |
| 	/* XXX xf86addNewOption will trash the option linked list if
 | |
| 	 * the options being added already exists.
 | |
| 	 */
 | |
| 	return;
 | |
|     *options = xf86addNewOption(*options, XtNewString(nam),
 | |
| 				val && strlen(val) ? XtNewString(val) : NULL);
 | |
|     UpdateOptionList();
 | |
| }
 | |
| 
 | |
| #ifdef USE_MODULES
 | |
| /*ARGSUSED*/
 | |
| static void
 | |
| AddDriverOption(Widget w, XtPointer user_data, XtPointer call_data)
 | |
| {
 | |
|     Arg args[1];
 | |
|     OptionInfoPtr opt = (OptionInfoPtr)user_data;
 | |
|     XF86OptionPtr option;
 | |
| 
 | |
|     option_str = (char *)opt->name;
 | |
|     XtSetArg(args[0], XtNstring, opt->name);
 | |
|     XtSetValues(name, args, 1);
 | |
|     if ((option = xf86findOption(*options, opt->name)) == NULL)
 | |
| 	XtSetArg(args[0], XtNstring, "");
 | |
|     else
 | |
| 	XtSetArg(args[0], XtNstring, option->opt_val);
 | |
|     XtSetValues(value, args, 1);
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static void
 | |
| SelectModuleCallback(Widget w, XtPointer user_data, XtPointer call_data)
 | |
| {
 | |
|     xf86cfgModuleOptions *mod = module_options;
 | |
|     XawListReturnStruct *info = (XawListReturnStruct *)call_data;
 | |
| 
 | |
|     while (mod) {
 | |
| 	if (strcmp(mod->name, info->string) == 0)
 | |
| 	    break;
 | |
| 	mod = mod->next;
 | |
|     }
 | |
| 
 | |
|     if (mod) {
 | |
| 	Arg args[2];
 | |
| 	char **list = NULL, **old;
 | |
| 	OptionInfoPtr opts = mod->option;
 | |
| 	int num = 0, oldnum;
 | |
| 
 | |
| 	module_sel = mod->name;
 | |
| 	XtSetArg(args[0], XtNlist, &old);
 | |
| 	XtSetArg(args[1], XtNnumberStrings, &oldnum);
 | |
| 	XtGetValues(optList, args, 2);
 | |
| 	while (opts && opts->name) {
 | |
| 	    ++num;
 | |
| 	    list = (char**)XtRealloc((XtPointer)list, sizeof(char*) * num);
 | |
| 	    list[num - 1] = XtNewString(opts->name);
 | |
| 	    ++opts;
 | |
| 	}
 | |
| 	if (num == 0) {
 | |
| 	    list = (char**)XtMalloc(sizeof(char*));
 | |
| 	    list[0] = XtNewString("");
 | |
| 	    num = 1;
 | |
| 	}
 | |
| 	XtSetArg(args[0], XtNlist, list);
 | |
| 	XtSetArg(args[1], XtNnumberStrings, num);
 | |
| 	XtSetValues(optList, args, 2);
 | |
| 	while (--oldnum >= 0)
 | |
| 	    XtFree(old[oldnum]);
 | |
| 	XtFree((XtPointer)old);
 | |
| 
 | |
| 	XtVaSetValues(desc, XtNstring, "", NULL);
 | |
| 	XawListUnhighlight(optList);
 | |
| 
 | |
| 	/* force relayout */
 | |
| 	XtUnmanageChild(optList);
 | |
| 	XtManageChild(optList);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void
 | |
| SelectModuleOptionCallback(Widget w, XtPointer user_data, XtPointer call_data)
 | |
| {
 | |
|     xf86cfgModuleOptions *mod = module_options;
 | |
|     XawListReturnStruct *info = (XawListReturnStruct *)call_data;
 | |
|     char *description = NULL, *type = "undefined";
 | |
|     char label[256];
 | |
| 
 | |
|     if (module_sel && info->string)
 | |
| 	description = GetOptionDescription(module_sel, info->string);
 | |
|     if (description == NULL)
 | |
| 	description = "** NO DESCRIPTION AVAILABLE **";
 | |
| 
 | |
|     XtVaSetValues(desc, XtNstring, description, NULL);
 | |
| 
 | |
|     while (mod) {
 | |
| 	if (strcmp(module_sel, mod->name) == 0)
 | |
| 	    break;
 | |
| 	mod = mod->next;
 | |
|     }
 | |
|     if (mod) {
 | |
| 	OptionInfoPtr opts = mod->option;
 | |
| 
 | |
| 	while (opts && opts->name) {
 | |
| 	    if (strcasecmp(opts->name, info->string) == 0)
 | |
| 		break;
 | |
| 	    ++opts;
 | |
| 	}
 | |
| 	if (opts && opts->name && opts->type >= OPTV_NONE &&
 | |
| 	    opts->type <= OPTV_FREQ)
 | |
| 	    type = types[opts->type];
 | |
|     }
 | |
| 
 | |
|     XmuSnprintf(label, sizeof(label), "%s.%s (%s)", module_sel, info->string,
 | |
| 	        type);
 | |
|     XtVaSetValues(labelType, XtNlabel, label, NULL);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static void
 | |
| RemoveOption(Widget w, XtPointer user_data, XtPointer call_data)
 | |
| {
 | |
|     Arg args[1];
 | |
|     char *str;
 | |
| 
 | |
|     XtSetArg(args[0], XtNstring, &str);
 | |
|     XtGetValues(name, args, 1);
 | |
|     xf86removeOption(options, str);
 | |
|     UpdateOptionList();
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static void
 | |
| UpdateOption(Widget w, XtPointer user_data, XtPointer call_data)
 | |
| {
 | |
| /*    xf86removeOption(options, option_str);
 | |
|     AddOption(w, user_data, call_data);
 | |
|     UpdateOptionList();*/
 | |
| 
 | |
|     Arg args[1];
 | |
|     char *nam, *val;
 | |
|     XF86OptionPtr option;
 | |
| 
 | |
|     XtSetArg(args[0], XtNstring, &nam);
 | |
|     XtGetValues(name, args, 1);
 | |
|     XtSetArg(args[0], XtNstring, &val);
 | |
|     XtGetValues(value, args, 1);
 | |
|     if ((option = xf86findOption(*options, option_str)) == NULL)
 | |
| 	return;
 | |
|     XtFree(option->opt_name);
 | |
|     option->opt_name = option_str = XtNewString(nam);
 | |
|     XtFree(option->opt_val);
 | |
|     if (val && strlen(val))
 | |
| 	option->opt_val = XtNewString(val);
 | |
|     else
 | |
| 	option->opt_val = NULL;
 | |
| 
 | |
|     UpdateOptionList();
 | |
|     XawListHighlight(list, option_index);
 | |
|     XtSetArg(args[0], XtNstring, option->opt_name);
 | |
|     XtSetValues(name, args, 1);
 | |
|     XtSetArg(args[0], XtNstring, option->opt_val);
 | |
|     XtSetValues(value, args, 1);
 | |
| 
 | |
|     XtSetSensitive(remov, True);
 | |
|     XtSetSensitive(update, True);
 | |
| }
 | |
| 
 | |
| /*ARGUSED*/
 | |
| static Bool
 | |
| EnumDatabase(XrmDatabase *db, XrmBindingList bindings, XrmQuarkList quarks,
 | |
| 	     XrmRepresentation *type, XrmValue *value, XPointer closure)
 | |
| {
 | |
|     char *module = XrmQuarkToString(quarks[0]),
 | |
| 	 *option = XrmQuarkToString(quarks[1]);
 | |
| 
 | |
|     /* handle *.Option: value */
 | |
|     if (module && option == NULL) {
 | |
| 	option = module;
 | |
| 	module = "*";
 | |
|     }
 | |
| 
 | |
|     /*
 | |
|      * NOTE: If the Options file is changed to support any other format than
 | |
|      *
 | |
|      *		Module.Option: description text
 | |
|      *
 | |
|      * this code will also need to be updated.
 | |
|      */
 | |
| 
 | |
|     if (module) {
 | |
| 	XrmValue xrm;
 | |
| 	char *type, *value, query[256];
 | |
| 
 | |
| 	XmuSnprintf(query, sizeof(query), "%s.%s", module, option);
 | |
| 	if (XrmGetResource(options_xrm, query, "Module.Option", &type, &xrm))
 | |
| 	    value = (char*)xrm.addr;
 | |
| 	else
 | |
| 	    value = NULL;
 | |
| 
 | |
| 	if (value) {
 | |
| 	    char *norm;
 | |
| 	    unsigned char *ptr;
 | |
| 	    int position;
 | |
| 	    int length = strlen(module) + strlen(option) + strlen(value) + 4;
 | |
| 
 | |
| 	    rebuild_xrm.string = XtRealloc(rebuild_xrm.string,
 | |
| 					   rebuild_xrm.offset + length);
 | |
| 	    position = rebuild_xrm.offset +
 | |
| 		       sprintf(rebuild_xrm.string + rebuild_xrm.offset, "%s.%s:",
 | |
| 			       module, option);
 | |
| 
 | |
| 	    /* removes underlines and spaces */
 | |
| 	    norm = strchr(rebuild_xrm.string + rebuild_xrm.offset, '.') + 1;
 | |
| 	    for (; *norm; norm++) {
 | |
| 		if (*norm == '_' || *norm == ' ' || *norm == '\t') {
 | |
| 		    memmove(norm, norm + 1, strlen(norm) + 1);
 | |
| 		    --position;
 | |
| 		    --length;
 | |
| 		}
 | |
| 	    }
 | |
| 
 | |
| 	    for (ptr = (unsigned char*)rebuild_xrm.string + rebuild_xrm.offset;
 | |
| 		 *ptr; ptr++)
 | |
| 		*ptr = tolower(*ptr);
 | |
| 	    sprintf(rebuild_xrm.string + position, "%s\n", value);
 | |
| 	    rebuild_xrm.offset += length - 1;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     return (False);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| InitializeOptionsDatabase(void)
 | |
| {
 | |
|     static int first = 1;
 | |
|     static Bool result = True;
 | |
| 
 | |
|     if (first) {
 | |
| 	XrmQuark names[2];
 | |
| 	XrmQuark classes[2];
 | |
| 
 | |
| 	first = 0;
 | |
| 	XrmInitialize();
 | |
| 	if ((options_xrm = XrmGetFileDatabase(Options)) == (XrmDatabase)0) {
 | |
| 	    fprintf(stderr, "Cannot open '%s' database.\n", Options);
 | |
| 	    return (False);
 | |
| 	}
 | |
| 
 | |
| 	/* rebuild database, using only lowercase characters */
 | |
| 	names[0] = classes[0] = names[1] = classes[1] = NULLQUARK;
 | |
| 	(void)XrmEnumerateDatabase(options_xrm, (XrmNameList)&names,
 | |
| 				   (XrmClassList)&classes, XrmEnumAllLevels,
 | |
| 				   EnumDatabase, NULL);
 | |
| 
 | |
| 	/* free previous database, as it is not guaranteed to be
 | |
|          * "case insensitive" */
 | |
| 	XrmDestroyDatabase(options_xrm);
 | |
| 
 | |
| 	/* create case insensitive database by making everything lowercase */
 | |
| 	if (rebuild_xrm.string == NULL ||
 | |
| 	    (options_xrm = XrmGetStringDatabase(rebuild_xrm.string)) ==
 | |
| 	    (XrmDatabase)0) {
 | |
| 	    fprintf(stderr, "Cannot rebuild '%s' database.\n", Options);
 | |
| 	    XtFree(rebuild_xrm.string);
 | |
| 	    return (False);
 | |
| 	}
 | |
| 	XtFree(rebuild_xrm.string);
 | |
|     }
 | |
| 
 | |
|     return (result);
 | |
| }
 | |
| 
 | |
| char *
 | |
| GetOptionDescription(char *module, char *option)
 | |
| {
 | |
|     char *type;
 | |
|     XrmValue value;
 | |
|     char query[256];
 | |
|     unsigned char *ptr;
 | |
| 
 | |
|     InitializeOptionsDatabase();
 | |
| 
 | |
|     XmuSnprintf(query, sizeof(query), "%s.%s", module, option);
 | |
|     ptr = (unsigned char*)strchr(query, '.') + 1;
 | |
|     for (; *ptr; ptr++) {
 | |
| 	if (*ptr == '_' || *ptr == ' ' || *ptr == '\t')
 | |
| 	    memmove(ptr, ptr + 1, strlen((char*)ptr) + 1);
 | |
|     }
 | |
|     for (ptr = (unsigned char*)query; *ptr; ptr++)
 | |
| 	*ptr = tolower(*ptr);
 | |
|     if (XrmGetResource(options_xrm, query, "Module.Option", &type, &value))
 | |
| 	return ((char*)value.addr);
 | |
| 
 | |
|     return (NULL);
 | |
| }
 |