diff options
Diffstat (limited to 'hw/xfree86/utils/xorgcfg/expert.c')
-rw-r--r-- | hw/xfree86/utils/xorgcfg/expert.c | 4860 |
1 files changed, 4860 insertions, 0 deletions
diff --git a/hw/xfree86/utils/xorgcfg/expert.c b/hw/xfree86/utils/xorgcfg/expert.c new file mode 100644 index 000000000..b9890b32b --- /dev/null +++ b/hw/xfree86/utils/xorgcfg/expert.c @@ -0,0 +1,4860 @@ +/* + * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com) + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Conectiva Linux shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from + * Conectiva Linux. + * + * Author: Paulo César Pereira de Andrade <pcpa@conectiva.com.br> + * + * $XFree86: xc/programs/Xserver/hw/xfree86/xf86cfg/expert.c,v 1.14 2003/02/07 05:46:53 paulo Exp $ + */ + +#include "config.h" +#include "xf86config.h" +#include "options.h" +#include "screen.h" +#include "vidmode.h" +#include "monitor-cfg.h" +#include <X11/Shell.h> +#include <X11/CompositeP.h> +#include <X11/Xaw/AsciiText.h> +#include <X11/Xaw/Box.h> +#include <X11/Xaw/Command.h> +#include <X11/Xaw/Form.h> +#include <X11/Xaw/Label.h> +#include <X11/Xaw/MenuButton.h> +#include <X11/Xaw/Paned.h> +#include <X11/Xaw/Panner.h> +#include <X11/Xaw/Porthole.h> +#include <X11/Xaw/SimpleMenu.h> +#include <X11/Xaw/SmeBSB.h> +#include <X11/Xaw/Toggle.h> +#include <X11/Xaw/Tree.h> +#include <ctype.h> + +/* + * Types + */ +typedef struct _TreeNode TreeNode; +typedef union _TreeData TreeData; +typedef void (*NodeDeleteFunc)(TreeNode*); +typedef void (*NodeUpdateFunc)(TreeNode*); + +union _TreeData { + struct { + Widget text; + } files; + struct { + Widget text; + XF86LoadPtr load; + } module; + struct { + Widget text; + XF86ConfModesPtr modes; + } modes; + struct { + Widget text, value; + XF86ConfModeLinePtr modeline; + } modeline; + struct { + Widget text, vendor, board, busid, driver; + XF86ConfVideoAdaptorPtr video; + } video; + struct { + Widget text; + XF86ConfVideoPortPtr port; + } port; + struct { + Widget text, vendor, model, width, height, hsync, vrefresh, + gammaRed, gammaGreen, gammaBlue; + XF86ConfMonitorPtr monitor; + } monitor; + struct { + Widget menu; + XF86ConfModesLinkPtr modeslink; + } modeslink; + struct { + Widget text, vendor, board, chipset, busid, card, driver, ramdac, + dacSpeed, videoRam, textClockFreq, biosBase, memBase, ioBase, + clockChip, devClock, chipId, chipRev, irq, screen; + XF86ConfDevicePtr device; + } device; + struct { + Widget text, defaultDepth, defaultBpp, defaultFbBpp, + monitor, device; + XF86ConfScreenPtr screen; + } screen; + struct { + Widget menu; + XF86ConfAdaptorLinkPtr adaptorlink; + } adaptorlink; + struct { + Widget viewport, c_virtual, depth, bpp, visual, weight, black, white; + XF86ConfDisplayPtr display; + } display; + struct { + Widget text; + XF86ModePtr mode; + } mode; + struct { + Widget text; + XF86ConfInputPtr input; + } input; + struct { + Widget text; + XF86ConfLayoutPtr layout; + } layout; + struct { + Widget menu, button, scrnum, adjx, adjy; + XF86ConfScreenPtr screen; + XF86ConfAdjacencyPtr adjacency; + } adjacency; + struct { + Widget menu; + XF86ConfInputrefPtr inputref; + } inputref; + struct { + Widget text; + XF86ConfVendorPtr vendor; + } vendor; + struct { + Widget text; + XF86ConfVendSubPtr vendsub; + } vendsub; + struct { + Widget name, group, mode; + XF86ConfDRIPtr dri; + } dri; + struct { + Widget count, size, flags; + XF86ConfBuffersPtr buffers; + } buffers; +}; + +struct _TreeNode { + Widget node, toggle, treeParent; + TreeNode *parent, *child, *next; + TreeData *data; + NodeDeleteFunc destroy; + NodeUpdateFunc update; +}; + +/* + * Prototypes + */ +static Bool ExpertInitialize(void); +static TreeNode *NewNode(TreeNode*, Widget, Widget, Widget, TreeData*); +static void DeleteNode(TreeNode*); +static void DestroyCallback(Widget, XtPointer, XtPointer); +static void PannerCallback(Widget, XtPointer, XtPointer); +static void PortholeCallback(Widget, XtPointer, XtPointer); +static void ToggleCallback(Widget, XtPointer, XtPointer); +static void ToggleNode(TreeNode*, Bool); +static void ToggleNodeRecursive(TreeNode*); +static void OptionsCallback(Widget, XtPointer, XtPointer); +static void RelayoutTree(void); +static void PopdownCallback(Widget, XtPointer, XtPointer); +static void UpdateConfig(TreeNode*); +static void DestroyTree(TreeNode*); + +static void CreateFiles(TreeNode*); +static void CreateFilesField(TreeNode*, char*, char*); +static void UpdateFiles(TreeNode*); + +static void CreateFontPath(TreeNode*, char*); +static Widget CreateFontPathField(TreeNode*, char*, Bool); +static void FontPathChanged(TreeNode*); +static void NewFontPathCallback(Widget, XtPointer, XtPointer); +static void FontPathCallback(Widget, XtPointer, XtPointer); + +static void CreateModulePath(TreeNode*, char*); +static Widget CreateModulePathField(TreeNode*, char*, Bool); +static void ModulePathChanged(TreeNode*); +static void NewModulePathCallback(Widget, XtPointer, XtPointer); + +static void CreateModule(TreeNode*, XF86LoadPtr); +static void CreateModuleField(TreeNode*, Bool); +static void ModuleDestroy(TreeNode*); +static void NewModuleCallback(Widget, XtPointer, XtPointer); + +static void CreateModes(TreeNode*, XF86ConfModesPtr); +static void CreateModesField(TreeNode*, Bool); +static void ModesDestroy(TreeNode*); +static void NewModesCallback(Widget, XtPointer, XtPointer); +static void CreateModesModeLine(TreeNode*, XF86ConfModeLinePtr); +static void ModesModeLineDestroy(TreeNode*); +static void NewModesModeLineCallback(Widget, XtPointer, XtPointer); + +static void CreateModeLineField(TreeNode*, Bool, Bool); +static XF86ConfModeLinePtr ParseModeLine(char*, char*); + +static void CreateVideoAdaptor(TreeNode*, XF86ConfVideoAdaptorPtr); +static void CreateVideoAdaptorField(TreeNode*, Bool); +static void VideoAdaptorDestroy(TreeNode*); +static void NewVideoAdaptorCallback(Widget, XtPointer, XtPointer); +static void VideoAdaptorUpdate(TreeNode*); +static void CreateVideoPort(TreeNode*, XF86ConfVideoPortPtr); +static void CreateVideoPortField(TreeNode*, Bool); +static void VideoPortDestroy(TreeNode*); +static void NewVideoPortCallback(Widget, XtPointer, XtPointer); + +static void CreateMonitor(TreeNode*, XF86ConfMonitorPtr); +static void CreateMonitorField(TreeNode*, Bool); +static void MonitorDestroy(TreeNode*); +static void NewMonitorCallback(Widget, XtPointer, XtPointer); +static void MonitorUpdate(TreeNode*); +static void CreateMonitorModeLine(TreeNode*, XF86ConfModeLinePtr); +static void MonitorModeLineDestroy(TreeNode*); +static void NewMonitorModeLineCallback(Widget, XtPointer, XtPointer); +static void CreateMonitorModes(TreeNode*, XF86ConfModesLinkPtr); +static void CreateMonitorModesField(TreeNode*, Bool); +static void MonitorModesLinkDestroy(TreeNode*); +static void NewMonitorModesCallback(Widget, XtPointer, XtPointer); + +static void CreateDevice(TreeNode*, XF86ConfDevicePtr); +static void CreateDeviceField(TreeNode*, Bool); +static void NewDeviceCallback(Widget, XtPointer, XtPointer); +static void DeviceDestroy(TreeNode*); +static void DeviceUpdate(TreeNode*); + +static void CreateScreen(TreeNode*, XF86ConfScreenPtr); +static void CreateScreenField(TreeNode*, Bool); +static void NewScreenCallback(Widget, XtPointer, XtPointer); +static void ScreenDestroy(TreeNode*); +static void ScreenUpdate(TreeNode*); +static void CreateScreenAdaptor(TreeNode*, XF86ConfAdaptorLinkPtr); +static void CreateScreenAdaptorField(TreeNode*, Bool); +static void NewScreenAdaptorCallback(Widget, XtPointer, XtPointer); +static void ScreenAdaptorDestroy(TreeNode*); +static void CreateScreenDisplay(TreeNode*, XF86ConfDisplayPtr); +static void CreateScreenDisplayField(TreeNode*, Bool); +static void NewScreenDisplayCallback(Widget, XtPointer, XtPointer); +static void ScreenDisplayDestroy(TreeNode*); +static void ScreenDisplayUpdate(TreeNode*); +static void CreateDisplayMode(TreeNode*, XF86ModePtr); +static void CreateDisplayModeField(TreeNode*, Bool); +static void NewDisplayModeCallback(Widget, XtPointer, XtPointer); +static void DisplayModeDestroy(TreeNode*); + +static void CreateInput(TreeNode*, XF86ConfInputPtr); +static void CreateInputField(TreeNode*, Bool); +static void InputDestroy(TreeNode*); +static void NewInputCallback(Widget, XtPointer, XtPointer); +static void InputUpdate(TreeNode*); + +static void CreateLayout(TreeNode*, XF86ConfLayoutPtr); +static void CreateLayoutField(TreeNode*, Bool); +static void LayoutDestroy(TreeNode*); +static void NewLayoutCallback(Widget, XtPointer, XtPointer); +static void CreateAdjacency(TreeNode*, XF86ConfAdjacencyPtr); +static void CreateAdjacencyField(TreeNode*, Bool); +static void AdjacencyDestroy(TreeNode*); +static void NewAdjacencyCallback(Widget, XtPointer, XtPointer); +static void AdjacencyMenuCallback(Widget, XtPointer, XtPointer); +static void AdjacencyToggleCallback(Widget, XtPointer, XtPointer); +static void CreateInputref(TreeNode*, XF86ConfInputrefPtr); +static void CreateInputrefField(TreeNode*, Bool); +static void InputrefDestroy(TreeNode*); +static void NewInputrefCallback(Widget, XtPointer, XtPointer); + +static void CreateVendor(TreeNode*, XF86ConfVendorPtr); +static void CreateVendorField(TreeNode*, Bool); +static void VendorDestroy(TreeNode*); +static void NewVendorCallback(Widget, XtPointer, XtPointer); +static void CreateVendorSub(TreeNode*, XF86ConfVendSubPtr); +static void CreateVendorSubField(TreeNode*, Bool); +static void NewVendorSubCallback(Widget, XtPointer, XtPointer); +static void VendorSubDestroy(TreeNode*); +static void VendorSubUpdate(TreeNode*); + +static void CreateDRI(TreeNode*, XF86ConfDRIPtr); +static void CreateDRIField(TreeNode*); +static void DRIUpdate(TreeNode*); + +static void CreateBuffers(TreeNode*, XF86ConfBuffersPtr); +static void CreateBuffersField(TreeNode*, Bool); +static void BuffersDestroy(TreeNode*); +static void NewBuffersCallback(Widget, XtPointer, XtPointer); +static void BuffersUpdate(TreeNode*); + +extern void RemoveDeviceCallback(Widget, XtPointer, XtPointer); + +/* interface.c */ +extern void InitializeDevices(void); +extern void SelectLayoutCallback(Widget, XtPointer, XtPointer); +extern void UpdateMenuDeviceList(int); +extern void SetConfigModeCallback(Widget, XtPointer, XtPointer); +extern void DefaultLayoutCallback(Widget, XtPointer, XtPointer); +extern void RemoveLayoutCallback(Widget, XtPointer, XtPointer); + +/* + * Initialization + */ +static Widget shell, expert, tree, panner; +extern Widget work, optionsShell, config, layoutp, topMenu; +extern xf86cfgDevice cpu_device; +static TreeNode *mainNode, *monitorTree, *screenTree, *layoutTree; + +/* + * Implementation + */ +void +ExpertConfigureStart(void) +{ + ExpertInitialize(); + + XtPopup(shell, XtGrabExclusive); + if (optionsShell == NULL) + CreateOptionsShell(); + XtVaSetValues(optionsShell, XtNtransientFor, shell, NULL, 0); +} + +void +ExpertConfigureEnd(void) +{ + int i, save_config_mode = config_mode; + Widget sme, layopt, layoutsme = NULL; + XF86ConfLayoutPtr lay; + + XtVaSetValues(optionsShell, XtNtransientFor, toplevel, NULL, 0); + XtPopdown(shell); + + /* Need to do this to avoid all code elsewhere needing to update the + * "expert" widget tree + */ + UpdateConfig(mainNode); + DestroyTree(mainNode); + XtDestroyWidget(shell); + expert = NULL; + + if (save_config_mode != CONFIG_LAYOUT) + SetConfigModeCallback(topMenu, (XtPointer)CONFIG_LAYOUT, NULL); + + /* Reset everything as the "expert" interface can do almost anything + * to the configuration. + */ + for (i = 0; i < computer.num_screens; i++) { + XtDestroyWidget(computer.screens[i]->widget); + XtFree((XtPointer)computer.screens[i]); + } + XtFree((XtPointer)computer.screens); + computer.screens = NULL; + computer.num_screens = 0; + + for (i = 0; i < computer.num_devices; i++) { + XtDestroyWidget(computer.devices[i]->widget); + XtFree((XtPointer)computer.devices[i]); + } + XtFree((XtPointer)computer.devices); + computer.devices = NULL; + computer.num_devices = 0; + + for (i = 0; i < computer.num_layouts; i++) { + XtFree((XtPointer)computer.layouts[i]->position); + XtFree((XtPointer)computer.layouts[i]); + } + XtFree((XtPointer)computer.layouts); + computer.layouts = NULL; + computer.num_layouts = 0; + + for (i = 0; i < computer.num_vidmodes; i++) + XtFree((XtPointer)computer.vidmodes[i]); + XtFree((XtPointer)computer.vidmodes); + computer.vidmodes = NULL; + computer.num_vidmodes = 0; + + /* Reinitialize devices/screens */ + InitializeDevices(); + UpdateMenuDeviceList(MOUSE); + UpdateMenuDeviceList(KEYBOARD); + UpdateMenuDeviceList(CARD); + UpdateMenuDeviceList(MONITOR); + + /* Update layout menu */ + /* first entry is "New server layout" */ + for (i = 1; i < ((CompositeWidget)layoutp)->composite.num_children; i++) + XtDestroyWidget(((CompositeWidget)layoutp)->composite.children[i]); + for (i = 0; i < layoutp->core.num_popups; i++) + XtDestroyWidget(layoutp->core.popup_list[i]); + lay = XF86Config->conf_layout_lst; + while (lay != NULL) { + sme = XtVaCreateManagedWidget("sme", smeBSBObjectClass, + layoutp, + XtNlabel, lay->lay_identifier, + XtNmenuName, lay->lay_identifier, + XtNleftBitmap, menuPixmap, + NULL, 0); + XtAddCallback(sme, XtNcallback, SelectLayoutCallback, (XtPointer)lay); + if (layoutsme == NULL) + layoutsme = sme; + layopt = XtCreatePopupShell(lay->lay_identifier, simpleMenuWidgetClass, + layoutp, NULL, 0); + sme = XtCreateManagedWidget("default", smeBSBObjectClass, + layopt, NULL, 0); + XtAddCallback(sme, XtNcallback, DefaultLayoutCallback, NULL); + sme = XtCreateManagedWidget("remove", smeBSBObjectClass, + layopt, NULL, 0); + XtAddCallback(sme, XtNcallback, RemoveLayoutCallback, NULL); + XtRealizeWidget(layopt); + + lay = (XF86ConfLayoutPtr)(lay->list.next); + } + computer.layout = NULL; + SelectLayoutCallback(layoutsme, + XF86Config->conf_layout_lst, NULL); + + + if (XF86Config->conf_flags && XF86Config->conf_flags->flg_option_lst) + SetTip(&cpu_device); + for (i = 0; i < computer.num_devices; i++) + SetTip(computer.devices[i]); + + /* Reinitialize vidmodes */ + InitializeVidmodes(); + + if (save_config_mode != CONFIG_LAYOUT) + SetConfigModeCallback(topMenu, (XtPointer)(long)save_config_mode, NULL); +} + +/*ARGSUSED*/ +void +ExpertCloseAction(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + ExpertConfigureEnd(); +} + +/*ARGSUSED*/ +void +ExpertCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + ExpertConfigureStart(); +} + +/*ARGSUSED*/ +static void +PopdownCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + ExpertConfigureEnd(); +} + +/* Files */ +static void +CreateFiles(TreeNode *files) +{ + XF86ConfFilesPtr file = XF86Config->conf_files; + TreeNode *node, *fontpath, *modulepath; + Widget w; + char *value; + + value = file->file_logfile ? file->file_logfile : ""; + node = NewNode(files, NULL, NULL, files->node, + (TreeData*)XtCalloc(1, sizeof(TreeData))); + CreateFilesField(node, "LogFile", value); + files->child = node; + files->update = UpdateFiles; + + if (XF86RGB_path) + value = XF86RGB_path; + else + value = file->file_rgbpath ? file->file_rgbpath : ""; + node->next = NewNode(files, NULL, NULL, files->node, + (TreeData*)XtCalloc(1, sizeof(TreeData))); + node = node->next; + CreateFilesField(node, "RgbPath", value); + + w = XtVaCreateManagedWidget("ModulePath", toggleWidgetClass, tree, + XtNtreeParent, files->node, NULL, 0); + node->next = modulepath = NewNode(files, w, w, files->node, NULL); + node = node->next; + CreateModulePath(modulepath, NULL); + + w = XtVaCreateManagedWidget("FontPath", toggleWidgetClass, tree, + XtNtreeParent, files->node, NULL, 0); + node->next = fontpath = NewNode(files, w, w, files->node, NULL); + node = node->next; + CreateFontPath(fontpath, NULL); +} + +static void +CreateFilesField(TreeNode *node, char *name, char *value) +{ + Widget box, label, text; + + box = XtVaCreateManagedWidget(name, boxWidgetClass, tree, + XtNtreeParent, node->node, NULL, 0); + node->node = box; + label = XtVaCreateManagedWidget("label", labelWidgetClass, box, + XtNlabel, name, NULL, 0); + text = XtVaCreateManagedWidget("value", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, XtNstring, value, + NULL, 0); + node->data->files.text = text; +} + +static void +UpdateFiles(TreeNode *files) +{ + char *str; + + /* LogFile */ + files = files->child; + XtVaGetValues(files->data->files.text, XtNstring, &str, NULL, 0); + XtFree(XF86Config->conf_files->file_logfile); + if (*str) + XF86Config->conf_files->file_logfile = XtNewString(str); + else + XF86Config->conf_files->file_logfile = NULL; + + /* LogFile */ + files = files->next; + XtVaGetValues(files->data->files.text, XtNstring, &str, NULL, 0); + XtFree(XF86Config->conf_files->file_rgbpath); + if (*str) + XF86Config->conf_files->file_rgbpath = XtNewString(str); + else + XF86Config->conf_files->file_rgbpath = NULL; +} + +/* FontPath */ +/* Don't need to set the update tree field, as it is already set + * as the destroy field */ +static void +CreateFontPath(TreeNode *fontpath, char *path) +{ + TreeNode *prev = NULL, *node; + Widget w; + + if (path == NULL) { + if (XF86Font_path) { + path = XtNewString(XF86Font_path); + if (XF86Config->conf_files && XF86Config->conf_files->file_fontpath) { + XtFree(XF86Config->conf_files->file_fontpath); + XF86Config->conf_files->file_fontpath = XtNewString(path); + } + } + else if (XF86Config->conf_files && XF86Config->conf_files->file_fontpath) + path = XtNewString(XF86Config->conf_files->file_fontpath); + } + else { + path = XtNewString(path); + if ((prev = fontpath->child) != NULL) + while (prev->next) + prev = prev->next; + } + + if (path) { + char *s; + + for (s = strtok(path, ","); s != NULL; s = strtok(NULL, ",")) { + node = NewNode(fontpath, NULL, NULL, fontpath->node, NULL); + node->destroy = FontPathChanged; + w = CreateFontPathField(node, s, False); + if (fontpath->child == NULL) + fontpath->child = node; + else + prev->next = node; + prev = node; + } + XtFree(path); + } + + node = NewNode(fontpath, NULL, NULL, fontpath->node, NULL); + w = CreateFontPathField(node, "", True); + if (fontpath->child == NULL) + fontpath->child = node; + else + prev->next = node; +} + +static Widget +CreateFontPathField(TreeNode *fontpath, char *value, Bool addnew) +{ + Widget box, command, text; + TreeData *data; + + box = XtVaCreateWidget("fontpath", formWidgetClass, tree, + XtNtreeParent, fontpath->treeParent, NULL, 0); + fontpath->node = box; + if (!addnew) { + command = XtCreateManagedWidget("remove", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, DestroyCallback, + (XtPointer)fontpath); + command = XtCreateManagedWidget("up", commandWidgetClass, box, NULL, 0); + XtAddCallback(command, XtNcallback, FontPathCallback, + (XtPointer)fontpath); + command = XtCreateManagedWidget("down", commandWidgetClass, box, NULL, 0); + XtAddCallback(command, XtNcallback, FontPathCallback, + (XtPointer)fontpath); + text = XtVaCreateManagedWidget("value", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, value, NULL, 0); + } + else { + command = XtCreateManagedWidget("new", commandWidgetClass, box, NULL, 0); + XtAddCallback(command, XtNcallback, NewFontPathCallback, + (XtPointer)fontpath); + text = XtVaCreateManagedWidget("valueNew", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, value, NULL, 0); + } + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->files.text = text; + fontpath->data = data; + + if (fontpath->treeParent && XtIsRealized(fontpath->treeParent)) + XtRealizeWidget(box); + XtManageChild(box); + + return (box); +} + +static void +FontPathChanged(TreeNode *node) +{ + TreeNode *parent = node->parent; + char *fontpath = NULL, *str; + Arg args[1]; + int pos = 0, len; + + /* last node is the "new" */ + for (node = parent->child; node->next != NULL; node = node->next) { + if (pos) + fontpath[pos++] = ','; + XtSetArg(args[0], XtNstring, &str); + XtGetValues(node->data->files.text, args, 1); + len = strlen(str) + 2; + fontpath = XtRealloc(fontpath, pos + len); + strcpy(fontpath + pos, str); + pos += len - 2; + } + + if (XF86Config->conf_files->file_fontpath) + XtFree(XF86Config->conf_files->file_fontpath); + XF86Config->conf_files->file_fontpath = fontpath; +} + +static void +NewFontPathCallback(Widget unused, XtPointer user_data, XtPointer call_data) +{ + TreeNode *fontpath, *node = (TreeNode*)user_data; + Arg args[1]; + char *str; + + XtSetArg(args[0], XtNstring, &str); + XtGetValues(node->data->files.text, args, 1); + if (*str == '\0') + return; + + fontpath = node->parent; + DeleteNode(node); + CreateFontPath(fontpath, str); + + FontPathChanged(fontpath->child); + RelayoutTree(); +} + +/*ARGSUSED*/ +static void +FontPathCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + TreeNode *parent, *node, *fontpath = (TreeNode*)user_data; + char *t1, *t2; + Widget w1, w2; + + parent = fontpath->parent; + node = parent->child; + if (!node->next->next) + return; + if (strcmp(XtName(w), "up") == 0) { + if (node == fontpath) + while (node->next->next) + node = node->next; + else + while (node && node->next != fontpath) + node = node->next; + } + else { + if (fontpath->next->next) + node = fontpath->next; + /* else is already correct */ + } + + w1 = node->data->files.text; + w2 = fontpath->data->files.text; + + XtVaGetValues(w1, XtNstring, &t1, NULL); + XtVaGetValues(w2, XtNstring, &t2, NULL); + t1 = XtNewString(t1); + XtVaSetValues(w1, XtNstring, t2, NULL); + XtVaSetValues(w2, XtNstring, t1, NULL); + XtFree(t1); +} + + +/* ModulePath */ +/* Don't need to set the update tree field, as it is already set + * as the destroy field */ +static void +CreateModulePath(TreeNode *modulepath, char *path) +{ + TreeNode *prev = NULL, *node; + Widget w; + + if (path == NULL) { + if (XF86Module_path) { + path = XtNewString(XF86Module_path); + if (XF86Config->conf_files && XF86Config->conf_files->file_modulepath) { + XtFree(XF86Config->conf_files->file_modulepath); + XF86Config->conf_files->file_modulepath = XtNewString(path); + } + } + else if (XF86Config->conf_files && XF86Config->conf_files->file_modulepath) + path = XtNewString(XF86Config->conf_files->file_modulepath); + } + else { + path = XtNewString(path); + if ((prev = modulepath->child) != NULL) + while (prev->next) + prev = prev->next; + } + + if (path) { + char *s; + + for (s = strtok(path, ","); s != NULL; s = strtok(NULL, ",")) { + node = NewNode(modulepath, NULL, NULL, modulepath->node, NULL); + node->destroy = ModulePathChanged; + w = CreateModulePathField(node, s, False); + if (modulepath->child == NULL) + modulepath->child = node; + else + prev->next = node; + prev = node; + } + XtFree(path); + } + + node = NewNode(modulepath, NULL, NULL, modulepath->node, NULL); + w = CreateModulePathField(node, "", True); + if (modulepath->child == NULL) + modulepath->child = node; + else + prev->next = node; +} + +static Widget +CreateModulePathField(TreeNode *modulepath, char *value, Bool addnew) +{ + Widget box, command, text; + TreeData *data; + + box = XtVaCreateWidget("modulepath", formWidgetClass, tree, + XtNtreeParent, modulepath->treeParent, NULL, 0); + modulepath->node = box; + if (!addnew) { + command = XtCreateManagedWidget("remove", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, DestroyCallback, + (XtPointer)modulepath); + text = XtVaCreateManagedWidget("value", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, value, NULL, 0); + } + else { + command = XtCreateManagedWidget("new", commandWidgetClass, box, NULL, 0); + XtAddCallback(command, XtNcallback, NewModulePathCallback, + (XtPointer)modulepath); + text = XtVaCreateManagedWidget("valueNew", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, value, NULL, 0); + } + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->files.text = text; + modulepath->data = data; + + if (modulepath->treeParent && XtIsRealized(modulepath->treeParent)) + XtRealizeWidget(box); + XtManageChild(box); + + return (box); +} + +static void +ModulePathChanged(TreeNode *node) +{ + TreeNode *parent = node->parent; + char *modulepath = NULL, *str; + Arg args[1]; + int pos = 0, len; + + /* last node is the "new" */ + for (node = parent->child; node->next != NULL; node = node->next) { + if (pos) + modulepath[pos++] = ','; + XtSetArg(args[0], XtNstring, &str); + XtGetValues(node->data->files.text, args, 1); + len = strlen(str) + 2; + modulepath = XtRealloc(modulepath, pos + len); + strcpy(modulepath + pos, str); + pos += len - 2; + } + + if (XF86Config->conf_files->file_modulepath) + XtFree(XF86Config->conf_files->file_modulepath); + XF86Config->conf_files->file_modulepath = modulepath; +} + +static void +NewModulePathCallback(Widget unused, XtPointer user_data, XtPointer call_data) +{ + TreeNode *modulepath, *node = (TreeNode*)user_data; + Arg args[1]; + char *str; + + XtSetArg(args[0], XtNstring, &str); + XtGetValues(node->data->files.text, args, 1); + if (*str == '\0') + return; + + modulepath = node->parent; + DeleteNode(node); + CreateModulePath(modulepath, str); + + ModulePathChanged(modulepath->child); + RelayoutTree(); +} + +/* Module */ +static void +CreateModule(TreeNode *module, XF86LoadPtr load) +{ + TreeNode *prev, *node; + TreeData *data; + + if ((prev = module->child) != NULL) + while (prev->next) + prev = prev->next; + + while (load) { + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->module.load = load; + node = NewNode(module, NULL, NULL, module->node, data); + node->destroy = ModuleDestroy; + CreateModuleField(node, False); + if (module->child == NULL) + module->child = node; + else + prev->next = node; + prev = node; + load = (XF86LoadPtr)(load->list.next); + } + + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + node = NewNode(module, NULL, NULL, module->node, data); + CreateModuleField(node, True); + if (module->child == NULL) + module->child = node; + else + prev->next = node; +} + +static void +CreateModuleField(TreeNode *node, Bool addnew) +{ + Widget box, command, label; + + box = XtVaCreateWidget("module", formWidgetClass, tree, + XtNtreeParent, node->treeParent, NULL, 0); + node->node = box; + + if (!addnew) { + XF86OptionPtr *options; + XF86LoadPtr load = node->data->module.load; + + options = &(load->load_opt); + command = XtCreateManagedWidget("remove", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, DestroyCallback, (XtPointer)node); + command = XtCreateManagedWidget("options", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, OptionsCallback, (XtPointer)options); + label = XtVaCreateManagedWidget("label", labelWidgetClass, box, + XtNlabel, load->load_name, NULL, 0); + } + else { + command = XtCreateManagedWidget("new", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, NewModuleCallback, (XtPointer)node); + label = XtVaCreateManagedWidget("value", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + NULL, 0); + node->data->module.text = label; + } + if (XtIsRealized(node->treeParent)) + XtRealizeWidget(box); + XtManageChild(box); +} + +/*ARGUSED*/ +static void +ModuleDestroy(TreeNode *node) +{ + if (node->data->module.load) + xf86removeModule(XF86Config, node->data->module.load); +} + +/*ARGSUSED*/ +static void +NewModuleCallback(Widget unused, XtPointer user_data, XtPointer call_data) +{ + TreeNode *module, *node = (TreeNode*)user_data; + XF86LoadPtr load; + Arg args[1]; + char *label; + + XtSetArg(args[0], XtNstring, &label); + XtGetValues(node->data->module.text, args, 1); + if (*label == '\0') + return; + + module = node->parent; + DeleteNode(node); + load = (XF86LoadPtr)XtCalloc(1, sizeof(XF86LoadRec)); + load->load_name = XtNewString(label); + XF86Config->conf_modules->mod_load_lst = + xf86addModule(XF86Config->conf_modules->mod_load_lst, load); + + CreateModule(module, load); + RelayoutTree(); +} + +/* Modes */ +static void +CreateModes(TreeNode *parent, XF86ConfModesPtr modes) +{ + TreeNode *node, *prev; + TreeData *data; + + if ((prev = parent->child) != NULL) + while (prev->next) + prev = prev->next; + + while (modes) { + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->modes.modes = modes; + node = NewNode(parent, NULL, NULL, parent->node, data); + node->destroy = ModesDestroy; + CreateModesField(node, False); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + + modes = (XF86ConfModesPtr)(modes->list.next); + } + + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + node = NewNode(parent, NULL, NULL, parent->node, data); + CreateModesField(node, True); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; +} + +static void +CreateModesField(TreeNode *node, Bool addnew) +{ + Widget box, command, label; + + box = XtVaCreateWidget("modes", formWidgetClass, tree, + XtNtreeParent, node->treeParent, NULL, 0); + node->node = box; + + if (!addnew) { + XF86ConfModesPtr modes = node->data->modes.modes; + + command = XtCreateManagedWidget("remove", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, DestroyCallback, (XtPointer)node); + label = XtVaCreateManagedWidget("mode", toggleWidgetClass, box, + XtNlabel, modes->modes_identifier, + XtNstate, True, + NULL, 0); + node->toggle = label; + XtAddCallback(label, XtNcallback, ToggleCallback, (XtPointer)node); + CreateModesModeLine(node, node->data->modes.modes->mon_modeline_lst); + } + else { + command = XtCreateManagedWidget("new", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, NewModesCallback, (XtPointer)node); + label = XtVaCreateManagedWidget("value", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + NULL, 0); + node->data->modes.text = label; + } + if (XtIsRealized(node->treeParent)) + XtRealizeWidget(box); + XtManageChild(box); +} + +/*ARGUSED*/ +static void +ModesDestroy(TreeNode *node) +{ + if (node->data->modes.modes) { + int i; + TreeNode *mon = monitorTree->child; + + /* last one is the "new" entry */ + while (mon && mon->next) { + /* UseModes is the second entry */ + TreeNode *mod = mon->child->next->child; + CompositeWidget composite; + + while (mod && mod->next) { + TreeNode *next = mod->next; + + if (mod && strcmp(mod->data->modeslink.modeslink->ml_modes_str, + node->data->modes.modes->modes_identifier) == 0) + /* Needs to do string comparison because may be deleting + * a "test" Modes section, with no Modelines. + */ + DeleteNode(mod); + mod = next; + } + composite = (CompositeWidget)mod->data->modeslink.menu; + + for (i = 0; i < composite->composite.num_children; ++i) + if (strcmp(XtName(composite->composite.children[i]), + node->data->modes.modes->modes_identifier) == 0) + XtDestroyWidget(composite->composite.children[i]); + + mon = mon->next; + } + + xf86removeModes(XF86Config, node->data->modes.modes); + } +} + +/*ARGSUSED*/ +static void +NewModesCallback(Widget unused, XtPointer user_data, XtPointer call_data) +{ + TreeNode *parent, *node = (TreeNode*)user_data; + XF86ConfModesPtr modes; + Arg args[1]; + char *label; + + XtSetArg(args[0], XtNstring, &label); + XtGetValues(node->data->modes.text, args, 1); + if (*label == '\0') + return; + + parent = node->parent; + DeleteNode(node); + modes = (XF86ConfModesPtr)XtCalloc(1, sizeof(XF86ConfModesRec)); + modes->modes_identifier = XtNewString(label); + XF86Config->conf_modes_lst = + xf86addModes(XF86Config->conf_modes_lst, modes); + + { + TreeNode *mon = monitorTree->child; + Widget sme; + + /* last one is the "new" entry */ + while (mon && mon->next) { + /* UseModes is the second entry */ + TreeNode *mod = mon->child->next->child; + + while (mod && mod->next) + mod = mod->next; + + sme = XtCreateManagedWidget(modes->modes_identifier, + smeBSBObjectClass, + mod->data->modeslink.menu, NULL, 0); + XtAddCallback(sme, XtNcallback, NewMonitorModesCallback, + (XtPointer)mod); + + mon = mon->next; + } + } + + CreateModes(parent, modes); + RelayoutTree(); +} + +static void +CreateModesModeLine(TreeNode *parent, XF86ConfModeLinePtr modeline) +{ + TreeNode *node, *prev; + TreeData *data; + + if ((prev = parent->child) != NULL) + while (prev->next) + prev = prev->next; + + while (modeline) { + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->modeline.modeline = modeline; + node = NewNode(parent, NULL, NULL, parent->node, data); + node->destroy = ModesModeLineDestroy; + CreateModeLineField(node, False, False); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + modeline = (XF86ConfModeLinePtr)(modeline->list.next); + } + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + node = NewNode(parent, NULL, NULL, parent->node, data); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + CreateModeLineField(node, True, False); +} + +/* This function should allow creating modelines for the + Mode and Monitor section */ +static void +CreateModeLineField(TreeNode *node, Bool addnew, Bool monitor) +{ + Widget box, command; + char buf[512], tmp[32]; + + box = XtVaCreateWidget("modeline", formWidgetClass, tree, + XtNtreeParent, node->treeParent, NULL, 0); + node->node = box; + + if (!addnew) { + XF86ConfModeLinePtr mod = node->data->modeline.modeline; + + command = XtCreateManagedWidget("remove", commandWidgetClass, + box, NULL, 0); + XtAddCallback(command, XtNcallback, DestroyCallback, (XtPointer)node); + XtVaCreateManagedWidget("label", labelWidgetClass, box, + XtNlabel, mod->ml_identifier, NULL, 0); + + XmuSnprintf(buf, sizeof(buf), "%g %d %d %d %d %d %d %d %d", + mod->ml_clock / 1000., mod->ml_hdisplay, mod->ml_hsyncstart, + mod->ml_hsyncend, mod->ml_htotal, mod->ml_vdisplay, + mod->ml_vsyncstart, mod->ml_vsyncend, mod->ml_vtotal); + if (mod->ml_flags & XF86CONF_INTERLACE) + strcat(buf, " interlace"); + if (mod->ml_flags & XF86CONF_PHSYNC) + strcat(buf, " +hsync"); + if (mod->ml_flags & XF86CONF_NHSYNC) + strcat(buf, " -hsync"); + if (mod->ml_flags & XF86CONF_PVSYNC) + strcat(buf, " +vsync"); + if (mod->ml_flags & XF86CONF_NVSYNC) + strcat(buf, " -vsync"); + if (mod->ml_flags & XF86CONF_CSYNC) + strcat(buf, " composite"); + if (mod->ml_flags & XF86CONF_PCSYNC) + strcat(buf, " +csync"); + if (mod->ml_flags & XF86CONF_NCSYNC) + strcat(buf, " -csync"); + if (mod->ml_flags & XF86CONF_DBLSCAN) + strcat(buf, " doublescan"); + if (mod->ml_flags & XF86CONF_BCAST) + strcat(buf, " bcast"); + if (mod->ml_flags & XF86CONF_HSKEW) { + XmuSnprintf(tmp, sizeof(tmp), " hskew %d", mod->ml_hskew); + strcat(buf, tmp); + } + if (mod->ml_flags & XF86CONF_VSCAN) { + XmuSnprintf(tmp, sizeof(tmp), " vscan %d", mod->ml_vscan); + strcat(buf, tmp); + } + if (mod->ml_flags & XF86CONF_CUSTOM) + strcat(buf, " custom"); + node->data->modeline.value = + XtVaCreateManagedWidget("modeline", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, NULL, 0); + } + else { + *buf = '\0'; + command = XtCreateManagedWidget("new", commandWidgetClass, + box, NULL, 0); + XtAddCallback(command, XtNcallback, monitor ? + NewMonitorModeLineCallback : NewModesModeLineCallback, + (XtPointer)node); + node->data->modeline.text = + XtVaCreateManagedWidget("value", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, NULL, 0); + node->data->modeline.value = + XtVaCreateManagedWidget("modelineNew", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, NULL, 0); + } + if (XtIsRealized(node->treeParent)) + XtRealizeWidget(box); + XtManageChild(box); +} + +/*ARGUSED*/ +static void +ModesModeLineDestroy(TreeNode *node) +{ + if (node->data->modeline.modeline) + xf86removeModesModeLine(node->parent->data->modes.modes, + node->data->modeline.modeline); +} + +/*ARGSUSED*/ +static void +NewModesModeLineCallback(Widget unused, XtPointer user_data, XtPointer call_data) +{ + TreeNode *parent, *node = (TreeNode*)user_data; + XF86ConfModeLinePtr modeline; + Arg args[1]; + char *ident, *value; + + XtSetArg(args[0], XtNstring, &ident); + XtGetValues(node->data->modeline.text, args, 1); + XtSetArg(args[0], XtNstring, &value); + XtGetValues(node->data->modeline.value, args, 1); + if (*ident == '\0' || *value == '\0') + return; + + parent = node->parent; + DeleteNode(node); + modeline = ParseModeLine(ident, value); + parent->data->modes.modes->mon_modeline_lst = + xf86addModeLine(parent->data->modes.modes->mon_modeline_lst, modeline); + + CreateModesModeLine(parent, modeline); + RelayoutTree(); +} + +static XF86ConfModeLinePtr +ParseModeLine(char *identifier, char *modeline) +{ + XF86ConfModeLinePtr ml = (XF86ConfModeLinePtr) + XtCalloc(1, sizeof(XF86ConfModeLineRec)); + char *s, *ptr = modeline; + + /* Identifier */ + ml->ml_identifier = XtNewString(identifier); + + ml->ml_clock = (int)(strtod(ptr, &ptr) * 1000.0 + 0.5); + while (*ptr && isspace(*ptr)) ++ptr; + + ml->ml_hdisplay = strtol(ptr, &ptr, 10); + while (*ptr && isspace(*ptr)) ++ptr; + + ml->ml_hsyncstart = strtol(ptr, &ptr, 10); + while (*ptr && isspace(*ptr)) ++ptr; + + ml->ml_hsyncend = strtol(ptr, &ptr, 10); + while (*ptr && isspace(*ptr)) ++ptr; + + ml->ml_htotal = strtol(ptr, &ptr, 10); + while (*ptr && isspace(*ptr)) ++ptr; + + ml->ml_vdisplay = strtol(ptr, &ptr, 10); + while (*ptr && isspace(*ptr)) ++ptr; + + ml->ml_vsyncstart = strtol(ptr, &ptr, 10); + while (*ptr && isspace(*ptr)) ++ptr; + + ml->ml_vsyncend = strtol(ptr, &ptr, 10); + while (*ptr && isspace(*ptr)) ++ptr; + + ml->ml_vtotal = strtol(ptr, &ptr, 10); + while (*ptr && isspace(*ptr)) ++ptr; + + s = ptr; + while (*s) { + *s = tolower(*s); + ++s; + } + s = ptr; + + while (*ptr) { + while (*s && isspace(*s)) + s++; + ptr = s; + while (*s && !isspace(*s)) + s++; + + if (s != ptr) { + Bool done = *s == '\0'; + + *s = '\0'; + if (strcmp(ptr, "interlace") == 0) + ml->ml_flags |= XF86CONF_INTERLACE; + else if (strcmp(ptr, "+hsync") == 0) + ml->ml_flags |= XF86CONF_PHSYNC; + else if (strcmp(ptr, "-hsync") == 0) + ml->ml_flags |= XF86CONF_NHSYNC; + else if (strcmp(ptr, "+vsync") == 0) + ml->ml_flags |= XF86CONF_PVSYNC; + else if (strcmp(ptr, "-vsync") == 0) + ml->ml_flags |= XF86CONF_NVSYNC; + else if (strcmp(ptr, "composite") == 0) + ml->ml_flags |= XF86CONF_CSYNC; + else if (strcmp(ptr, "+csync") == 0) + ml->ml_flags |= XF86CONF_PCSYNC; + else if (strcmp(ptr, "-csync") == 0) + ml->ml_flags |= XF86CONF_NCSYNC; + else if (strcmp(ptr, "doublescan") == 0) + ml->ml_flags |= XF86CONF_DBLSCAN; + else if (strcmp(ptr, "bcast") == 0) + ml->ml_flags |= XF86CONF_BCAST; + else if (strcmp(ptr, "hskew") == 0) { + ++s; + while (*s && isspace(*s)) + ++s; + ptr = s; + while (*s && !isspace(*s)) + ++s; + if (ptr != s) { + ml->ml_hskew = strtol(ptr, &s, 10); + ml->ml_flags |= XF86CONF_HSKEW; + --s; + } + } + else if (strcmp(ptr, "vscan") == 0) { + ++s; + while (*s && isspace(*s)) + ++s; + ptr = s; + while (*s && !isspace(*s)) + ++s; + if (ptr != s) { + ml->ml_vscan = strtol(ptr, &s, 10); + ml->ml_flags |= XF86CONF_VSCAN; + --s; + } + } + else if (strcmp(ptr, "custom") == 0) + ml->ml_flags |= XF86CONF_CUSTOM; + ++s; + if (done) + break; + ptr = s; + } + } + + return (ml); +} + +/* VideoAdpator */ +static void +CreateVideoAdaptor(TreeNode *parent, XF86ConfVideoAdaptorPtr video) +{ + TreeNode *node, *prev; + TreeData *data; + + if ((prev = parent->child) != NULL) + while (prev->next) + prev = prev->next; + + while (video) { + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->video.video = video; + node = NewNode(parent, NULL, NULL, parent->node, data); + node->destroy = VideoAdaptorDestroy; + node->update = VideoAdaptorUpdate; + CreateVideoAdaptorField(node, False); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + + video = (XF86ConfVideoAdaptorPtr)(video->list.next); + } + + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + node = NewNode(parent, NULL, NULL, parent->node, data); + CreateVideoAdaptorField(node, True); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; +} + +static void +CreateVideoAdaptorField(TreeNode *node, Bool addnew) +{ + Widget box, command, label; + + box = XtVaCreateWidget("video", formWidgetClass, tree, + XtNtreeParent, node->treeParent, NULL, 0); + node->node = box; + + if (!addnew) { + char *str; + TreeNode *port; + XF86ConfVideoAdaptorPtr video = node->data->video.video; + + command = XtCreateManagedWidget("remove", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, DestroyCallback, (XtPointer)node); + command = XtCreateManagedWidget("options", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, OptionsCallback, + (XtPointer)&(video->va_option_lst)); + label = XtVaCreateManagedWidget("adaptor", labelWidgetClass, box, + XtNlabel, video->va_identifier, + NULL, 0); + + XtCreateManagedWidget("vendorL", labelWidgetClass, box, NULL, 0); + str = video->va_vendor ? video->va_vendor : ""; + node->data->video.vendor = + XtVaCreateManagedWidget("vendor", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, str, + NULL, 0); + + XtCreateManagedWidget("boardL", labelWidgetClass, box, NULL, 0); + str = video->va_board ? video->va_board : ""; + node->data->video.board = + XtVaCreateManagedWidget("board", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, str, + NULL, 0); + + XtCreateManagedWidget("busidL", labelWidgetClass, box, NULL, 0); + str = video->va_busid ? video->va_busid : ""; + node->data->video.busid = + XtVaCreateManagedWidget("busid", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, str, + NULL, 0); + + XtCreateManagedWidget("driverL", labelWidgetClass, box, NULL, 0); + str = video->va_driver ? video->va_driver : ""; + node->data->video.driver = + XtVaCreateManagedWidget("driver", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, str, + NULL, 0); + + label = XtVaCreateManagedWidget("VideoPort", toggleWidgetClass, tree, + XtNstate, True, + XtNtreeParent, box, + NULL, 0); + port = NewNode(node, label, label, node->node, NULL); + node->child = port; + CreateVideoPort(port, video->va_port_lst); + } + else { + command = XtCreateManagedWidget("new", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, NewVideoAdaptorCallback, + (XtPointer)node); + label = XtVaCreateManagedWidget("value", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + NULL, 0); + node->data->video.text = label; + } + if (XtIsRealized(node->treeParent)) + XtRealizeWidget(box); + XtManageChild(box); +} + +/*ARGUSED*/ +static void +VideoAdaptorDestroy(TreeNode *node) +{ + if (node->data->video.video) { + int i; + TreeNode *scrn = screenTree->child; + + /* last one is the "new" entry */ + while (scrn && scrn->next) { + /* VideoAdator is the first entry */ + TreeNode *ad = scrn->child->child; + CompositeWidget composite; + + while (ad && ad->next) { + TreeNode *next = ad->next; + + if (ad && strcmp(ad->data->adaptorlink.adaptorlink->al_adaptor_str, + node->data->video.video->va_identifier) == 0) + DeleteNode(ad); + ad = next; + } + composite = (CompositeWidget)ad->data->adaptorlink.menu; + + for (i = 0; i < composite->composite.num_children; ++i) + if (strcmp(XtName(composite->composite.children[i]), + node->data->video.video->va_identifier) == 0) + XtDestroyWidget(composite->composite.children[i]); + + scrn = scrn->next; + } + + xf86removeVideoAdaptor(XF86Config, node->data->video.video); + } +} + +/*ARGSUSED*/ +static void +NewVideoAdaptorCallback(Widget unused, XtPointer user_data, XtPointer call_data) +{ + TreeNode *parent, *node = (TreeNode*)user_data; + XF86ConfVideoAdaptorPtr video; + Arg args[1]; + char *label; + + XtSetArg(args[0], XtNstring, &label); + XtGetValues(node->data->video.text, args, 1); + if (*label == '\0') + return; + + parent = node->parent; + DeleteNode(node); + video = (XF86ConfVideoAdaptorPtr) + XtCalloc(1, sizeof(XF86ConfVideoAdaptorRec)); + video->va_identifier = XtNewString(label); + XF86Config->conf_videoadaptor_lst = + xf86addVideoAdaptor(XF86Config->conf_videoadaptor_lst, video); + + { + TreeNode *scrn = screenTree->child; + Widget sme; + + /* last one is the "new" entry */ + while (scrn && scrn->next) { + /* VideoAdaptor is the first entry */ + TreeNode *ad = scrn->child->child; + + while (ad && ad->next) + ad = ad->next; + + sme = XtCreateManagedWidget(video->va_identifier, + smeBSBObjectClass, + ad->data->adaptorlink.menu, NULL, 0); + XtAddCallback(sme, XtNcallback, NewScreenAdaptorCallback, + (XtPointer)ad); + + scrn = scrn->next; + } + } + + CreateVideoAdaptor(parent, video); + RelayoutTree(); +} + +static void +VideoAdaptorUpdate(TreeNode *node) +{ + char *str; + + /* vendor */ + XtVaGetValues(node->data->video.vendor, XtNstring, &str, NULL, 0); + XtFree(node->data->video.video->va_vendor); + if (*str) + node->data->video.video->va_vendor = XtNewString(str); + else + node->data->video.video->va_vendor = NULL; + + /* board */ + XtVaGetValues(node->data->video.board, XtNstring, &str, NULL, 0); + XtFree(node->data->video.video->va_board); + if (*str) + node->data->video.video->va_board = XtNewString(str); + else + node->data->video.video->va_board = NULL; + + /* busid */ + XtVaGetValues(node->data->video.busid, XtNstring, &str, NULL, 0); + XtFree(node->data->video.video->va_busid); + if (*str) + node->data->video.video->va_busid = XtNewString(str); + else + node->data->video.video->va_busid = NULL; + + /* driver */ + XtVaGetValues(node->data->video.driver, XtNstring, &str, NULL, 0); + XtFree(node->data->video.video->va_driver); + if (*str) + node->data->video.video->va_driver = XtNewString(str); + else + node->data->video.video->va_driver = NULL; +} + +static void +CreateVideoPort(TreeNode *parent, XF86ConfVideoPortPtr port) +{ + TreeNode *prev, *node; + TreeData *data; + + if ((prev = parent->child) != NULL) + while (prev->next) + prev = prev->next; + + while (port) { + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->port.port = port; + node = NewNode(parent, NULL, NULL, parent->node, data); + node->destroy = VideoPortDestroy; + CreateVideoPortField(node, False); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + port = (XF86ConfVideoPortPtr)(port->list.next); + } + + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + node = NewNode(parent, NULL, NULL, parent->node, data); + CreateVideoPortField(node, True); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; +} + +static void +CreateVideoPortField(TreeNode *node, Bool addnew) +{ + Widget box, command, label; + + box = XtVaCreateWidget("port", formWidgetClass, tree, + XtNtreeParent, node->treeParent, NULL, 0); + node->node = box; + + if (!addnew) { + XF86OptionPtr *options; + XF86ConfVideoPortPtr port = node->data->port.port; + + options = &(port->vp_option_lst); + command = XtCreateManagedWidget("remove", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, DestroyCallback, (XtPointer)node); + command = XtCreateManagedWidget("options", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, OptionsCallback, (XtPointer)options); + label = XtVaCreateManagedWidget("label", labelWidgetClass, box, + XtNlabel, port->vp_identifier, NULL, 0); + } + else { + command = XtCreateManagedWidget("new", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, NewVideoPortCallback, (XtPointer)node); + label = XtVaCreateManagedWidget("value", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + NULL, 0); + node->data->port.text = label; + } + if (XtIsRealized(node->treeParent)) + XtRealizeWidget(box); + XtManageChild(box); +} + +/*ARGUSED*/ +static void +VideoPortDestroy(TreeNode *node) +{ + if (node->data->port.port) + xf86removeVideoPort(node->parent->parent->data->video.video, + node->data->port.port); +} + +/*ARGSUSED*/ +static void +NewVideoPortCallback(Widget unused, XtPointer user_data, XtPointer call_data) +{ + TreeNode *video, *node = (TreeNode*)user_data; + XF86ConfVideoPortPtr port; + Arg args[1]; + char *label; + + XtSetArg(args[0], XtNstring, &label); + XtGetValues(node->data->port.text, args, 1); + if (*label == '\0') + return; + + video = node->parent->parent; + DeleteNode(node); + port = (XF86ConfVideoPortPtr)XtCalloc(1, sizeof(XF86ConfVideoPortRec)); + port->vp_identifier = XtNewString(label); + video->data->video.video->va_port_lst = + xf86addVideoPort(video->data->video.video->va_port_lst, port); + + CreateVideoPort(video, port); + RelayoutTree(); +} + +/* Monitor */ +static void +CreateMonitor(TreeNode *parent, XF86ConfMonitorPtr mon) +{ + TreeNode *prev, *node; + TreeData *data; + + if ((prev = parent->child) != NULL) + while (prev->next) + prev = prev->next; + + while (mon) { + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->monitor.monitor = mon; + node = NewNode(parent, NULL, NULL, parent->node, data); + node->destroy = MonitorDestroy; + node->update = MonitorUpdate; + CreateMonitorField(node, False); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + mon = (XF86ConfMonitorPtr)(mon->list.next); + } + + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + node = NewNode(parent, NULL, NULL, parent->node, data); + CreateMonitorField(node, True); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; +} + +static void +CreateMonitorField(TreeNode *node, Bool addnew) +{ + Widget box, command, label; + + box = XtVaCreateWidget("monitor", formWidgetClass, tree, + XtNtreeParent, node->treeParent, NULL, 0); + node->node = box; + + if (!addnew) { + char *str, buf[256]; + XF86OptionPtr *options; + XF86ConfMonitorPtr mon = node->data->monitor.monitor; + Widget useModes; + TreeNode *modeline, *modes, *prev; + + options = &(mon->mon_option_lst); + command = XtCreateManagedWidget("remove", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, DestroyCallback, (XtPointer)node); + command = XtCreateManagedWidget("options", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, OptionsCallback, (XtPointer)options); + label = XtVaCreateManagedWidget("label", labelWidgetClass, box, + XtNlabel, mon->mon_identifier, NULL, 0); + + XtCreateManagedWidget("vendorL", labelWidgetClass, box, NULL, 0); + str = mon->mon_vendor ? mon->mon_vendor : ""; + node->data->monitor.vendor = + XtVaCreateManagedWidget("vendor", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, str, + NULL, 0); + + XtCreateManagedWidget("modelnameL", labelWidgetClass, box, NULL, 0); + str = mon->mon_modelname ? mon->mon_modelname : ""; + node->data->monitor.model = + XtVaCreateManagedWidget("modelname", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, str, + NULL, 0); + + XtCreateManagedWidget("widthL", labelWidgetClass, box, NULL, 0); + if (mon->mon_width) + XmuSnprintf(buf, sizeof(buf), "%d", mon->mon_width); + else + *buf = '\0'; + node->data->monitor.width = + XtVaCreateManagedWidget("width", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, + NULL, 0); + + XtCreateManagedWidget("heightL", labelWidgetClass, box, NULL, 0); + if (mon->mon_height) + XmuSnprintf(buf, sizeof(buf), "%d", mon->mon_height); + else + *buf = '\0'; + node->data->monitor.height = + XtVaCreateManagedWidget("height", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, + NULL, 0); + + XtCreateManagedWidget("hsyncL", labelWidgetClass, box, NULL, 0); + if (mon->mon_n_hsync > 0) + parser_range_to_string(buf, &(mon->mon_hsync[0]), + mon->mon_n_hsync); + else + *buf = '\0'; + node->data->monitor.hsync = + XtVaCreateManagedWidget("hsync", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, + NULL, 0); + + XtCreateManagedWidget("vrefreshL", labelWidgetClass, box, NULL, 0); + if (mon->mon_n_vrefresh > 0) + parser_range_to_string(buf, &(mon->mon_vrefresh[0]), + mon->mon_n_vrefresh); + else + *buf = '\0'; + node->data->monitor.vrefresh = + XtVaCreateManagedWidget("vrefresh", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, + NULL, 0); + + XtCreateManagedWidget("gammaRedL", labelWidgetClass, box, NULL, 0); + if (mon->mon_gamma_red) + XmuSnprintf(buf, sizeof(buf), "%g", mon->mon_gamma_red); + else + *buf = '\0'; + node->data->monitor.gammaRed = + XtVaCreateManagedWidget("gammaRed", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, + NULL, 0); + + XtCreateManagedWidget("gammaGreenL", labelWidgetClass, box, NULL, 0); + if (mon->mon_gamma_green) + XmuSnprintf(buf, sizeof(buf), "%g", mon->mon_gamma_green); + else + *buf = '\0'; + node->data->monitor.gammaGreen = + XtVaCreateManagedWidget("gammaGreen", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, + NULL, 0); + + XtCreateManagedWidget("gammaBlueL", labelWidgetClass, box, NULL, 0); + if (mon->mon_gamma_blue) + XmuSnprintf(buf, sizeof(buf), "%g", mon->mon_gamma_blue); + else + *buf = '\0'; + node->data->monitor.gammaBlue = + XtVaCreateManagedWidget("gammaBlue", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, + NULL, 0); + + if ((prev = node->child) != NULL) + while (prev->next) + prev = prev->next; + command = XtVaCreateManagedWidget("ModeLine", toggleWidgetClass, tree, + XtNstate, True, + XtNtreeParent, box, NULL, 0); + modeline = NewNode(node, command, command, node->node, NULL); + CreateMonitorModeLine(modeline, + node->data->monitor.monitor->mon_modeline_lst); + if (prev == NULL) + prev = node->child = modeline; + else { + prev->next = modeline; + prev = prev->next; + } + + useModes = XtVaCreateManagedWidget("UseModes", toggleWidgetClass, tree, + XtNstate, True, + XtNtreeParent, box, NULL, 0); + prev->next = modes = NewNode(node, useModes, useModes, node->node, NULL); + CreateMonitorModes(modes, + node->data->monitor.monitor->mon_modes_sect_lst); + } + else { + command = XtCreateManagedWidget("new", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, NewMonitorCallback, (XtPointer)node); + label = XtVaCreateManagedWidget("value", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + NULL, 0); + node->data->monitor.text = label; + } + if (XtIsRealized(node->treeParent)) + XtRealizeWidget(box); + XtManageChild(box); +} + +static void +MonitorDestroy(TreeNode *node) +{ + int i; + TreeNode *sc = screenTree; + + for (i = 0; i < computer.num_devices; i++) + if ((XF86ConfMonitorPtr)(computer.devices[i]->config) == + node->data->monitor.monitor) { + config = computer.devices[i]->widget; + RemoveDeviceCallback(NULL, NULL, NULL); + } + + if (sc) { + TreeNode *prev; + + sc = prev = sc->child; + while (sc->next) { + TreeNode *next = sc->next; + + if (sc->data->screen.screen->scrn_monitor == + node->data->monitor.monitor) { + XtDestroyWidget(sc->node); + + if (sc->child) + DestroyTree(sc->child); + if (sc->data) + XtFree((XtPointer)sc->data); + XtFree((XtPointer)sc); + + if (sc == screenTree->child) + sc = prev = next = screenTree->child = next; + else + prev->next = sc = next; + continue; + } + prev = sc; + sc = next; + } + } +} + +static void +NewMonitorCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + TreeNode *parent, *node = (TreeNode*)user_data; + XF86ConfMonitorPtr mon; + Arg args[1]; + char *label; + + XtSetArg(args[0], XtNstring, &label); + XtGetValues(node->data->monitor.text, args, 1); + if (*label == '\0') + return; + + parent = node->parent; + DeleteNode(node); + mon = (XF86ConfMonitorPtr)XtCalloc(1, sizeof(XF86ConfMonitorRec)); + mon->mon_identifier = XtNewString(label); + XF86Config->conf_monitor_lst = + xf86addMonitor(XF86Config->conf_monitor_lst, mon); + + CreateMonitor(parent, mon); + + RelayoutTree(); +} + +static void +MonitorUpdate(TreeNode *node) +{ + char *str; + + /* vendor */ + XtVaGetValues(node->data->monitor.vendor, XtNstring, &str, NULL, 0); + XtFree(node->data->monitor.monitor->mon_vendor); + if (*str) + node->data->monitor.monitor->mon_vendor = XtNewString(str); + else + node->data->monitor.monitor->mon_vendor = NULL; + + /* model */ + XtVaGetValues(node->data->monitor.model, XtNstring, &str, NULL, 0); + XtFree(node->data->monitor.monitor->mon_modelname); + if (*str) + node->data->monitor.monitor->mon_modelname = XtNewString(str); + else + node->data->monitor.monitor->mon_modelname = NULL; + + /* width */ + XtVaGetValues(node->data->monitor.width, XtNstring, &str, NULL, 0); + node->data->monitor.monitor->mon_width = strtoul(str, NULL, 0); + + /* height */ + XtVaGetValues(node->data->monitor.height, XtNstring, &str, NULL, 0); + node->data->monitor.monitor->mon_height = strtoul(str, NULL, 0); + + /* hsync */ + XtVaGetValues(node->data->monitor.hsync, XtNstring, &str, NULL, 0); + node->data->monitor.monitor->mon_n_hsync = + string_to_parser_range(str, + &(node->data->monitor.monitor->mon_hsync[0]), + CONF_MAX_HSYNC); + + /* vrefresh */ + XtVaGetValues(node->data->monitor.vrefresh, XtNstring, &str, NULL, 0); + node->data->monitor.monitor->mon_n_vrefresh = + string_to_parser_range(str, + &(node->data->monitor.monitor->mon_vrefresh[0]), + CONF_MAX_VREFRESH); + + /* gammaRed */ + XtVaGetValues(node->data->monitor.gammaRed, XtNstring, &str, NULL, 0); + node->data->monitor.monitor->mon_gamma_red = strtod(str, NULL); + + /* gammaGreen */ + XtVaGetValues(node->data->monitor.gammaGreen, XtNstring, &str, NULL, 0); + node->data->monitor.monitor->mon_gamma_green = strtod(str, NULL); + + /* gammaBlue */ + XtVaGetValues(node->data->monitor.gammaBlue, XtNstring, &str, NULL, 0); + node->data->monitor.monitor->mon_gamma_blue = strtod(str, NULL); +} + +static void +CreateMonitorModeLine(TreeNode *parent, XF86ConfModeLinePtr modeline) +{ + TreeNode *node, *prev; + TreeData *data; + + if ((prev = parent->child) != NULL) + while (prev->next) + prev = prev->next; + + while (modeline) { + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->modeline.modeline = modeline; + node = NewNode(parent, NULL, NULL, parent->node, data); + node->destroy = MonitorModeLineDestroy; + CreateModeLineField(node, False, True); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + modeline = (XF86ConfModeLinePtr)(modeline->list.next); + } + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + node = NewNode(parent, NULL, NULL, parent->node, data); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + CreateModeLineField(node, True, True); +} + +/*ARGUSED*/ +static void +MonitorModeLineDestroy(TreeNode *node) +{ + if (node->data->modeline.modeline) + xf86removeMonitorModeLine(node->parent->parent->data->monitor.monitor, + node->data->modeline.modeline); +} + +/*ARGSUSED*/ +static void +NewMonitorModeLineCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + TreeNode *parent, *node = (TreeNode*)user_data; + XF86ConfModeLinePtr modeline; + Arg args[1]; + char *ident, *value; + + XtSetArg(args[0], XtNstring, &ident); + XtGetValues(node->data->modeline.text, args, 1); + XtSetArg(args[0], XtNstring, &value); + XtGetValues(node->data->modeline.value, args, 1); + if (*ident == '\0' || *value == '\0') + return; + + parent = node->parent; + DeleteNode(node); + modeline = ParseModeLine(ident, value); + parent->parent->data->monitor.monitor->mon_modeline_lst = + xf86addModeLine(parent->parent->data->monitor.monitor->mon_modeline_lst, + modeline); + + CreateMonitorModeLine(parent, modeline); + RelayoutTree(); +} + +static void +CreateMonitorModes(TreeNode *parent, XF86ConfModesLinkPtr lnk) +{ + TreeNode *node, *prev; + TreeData *data; + + if ((prev = parent->child) != NULL) + while (prev->next) + prev = prev->next; + + while (lnk) { + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->modeslink.modeslink = lnk; + node = NewNode(parent, NULL, NULL, parent->node, data); + node->destroy = MonitorModesLinkDestroy; + CreateMonitorModesField(node, False); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + lnk = (XF86ConfModesLinkPtr)(lnk->list.next); + } + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + node = NewNode(parent, NULL, NULL, parent->node, data); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + CreateMonitorModesField(node, True); +} + +static void +CreateMonitorModesField(TreeNode *node, Bool addnew) +{ + Widget box, command, label; + + box = XtVaCreateWidget("modes", formWidgetClass, tree, + XtNtreeParent, node->treeParent, NULL, 0); + node->node = box; + + if (!addnew) { + XF86ConfModesLinkPtr lnk = node->data->modeslink.modeslink; + + command = XtCreateManagedWidget("remove", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, DestroyCallback, (XtPointer)node); + label = XtVaCreateManagedWidget("mode", labelWidgetClass, box, + XtNlabel, lnk->ml_modes_str, NULL, 0); + } + else { + Widget sme; + XF86ConfModesPtr ptr = XF86Config->conf_modes_lst; + + command = XtVaCreateManagedWidget("new", menuButtonWidgetClass, box, + XtNmenuName, "modesMenu", NULL, 0); + node->data->modeslink.menu = + XtVaCreatePopupShell("modesMenu", simpleMenuWidgetClass, box, + XtNleftMargin, 1, XtNrightMargin, 1, + XtNtopMargin, 1, XtNbottomMargin, 1, + NULL, 0); + while (ptr) { + sme = XtCreateManagedWidget(ptr->modes_identifier, smeBSBObjectClass, + node->data->modeslink.menu, NULL, 0); + XtAddCallback(sme, XtNcallback, NewMonitorModesCallback, + (XtPointer)node); + ptr = (XF86ConfModesPtr)(ptr->list.next); + } + } + if (XtIsRealized(node->treeParent)) + XtRealizeWidget(box); + XtManageChild(box); +} + +/*ARGUSED*/ +static void +MonitorModesLinkDestroy(TreeNode *node) +{ + if (node->data->modeslink.modeslink) + xf86removeMonitorModesLink(node->parent->parent->data->monitor.monitor, + node->data->modeslink.modeslink); +} + +/*ARGSUSED*/ +static void +NewMonitorModesCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + TreeNode *parent, *node = (TreeNode*)user_data; + XF86ConfModesLinkPtr link; + char *ident = XtName(w); + + parent = node->parent; + DeleteNode(node); + link = (XF86ConfModesLinkPtr)XtCalloc(1, sizeof(XF86ConfModesLinkRec)); + link->ml_modes_str = XtNewString(ident); + parent->parent->data->monitor.monitor->mon_modes_sect_lst = + xf86addModesLink(parent->parent->data->monitor.monitor->mon_modes_sect_lst, + link); + + CreateMonitorModes(parent, link); + RelayoutTree(); +} + +/* Device */ +static void +CreateDevice(TreeNode *parent, XF86ConfDevicePtr dev) +{ + TreeNode *prev, *node; + TreeData *data; + + if ((prev = parent->child) != NULL) + while (prev->next) + prev = prev->next; + + while (dev) { + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->device.device = dev; + node = NewNode(parent, NULL, NULL, parent->node, data); + node->destroy = DeviceDestroy; + node->update = DeviceUpdate; + CreateDeviceField(node, False); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + dev = (XF86ConfDevicePtr)(dev->list.next); + } + + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + node = NewNode(parent, NULL, NULL, parent->node, data); + CreateDeviceField(node, True); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; +} + +static void +CreateDeviceField(TreeNode *node, Bool addnew) +{ + Widget box, command, label; + + box = XtVaCreateWidget("device", formWidgetClass, tree, + XtNtreeParent, node->treeParent, NULL, 0); + node->node = box; + + if (!addnew) { + int i, tmp, len; + char buf[1024], *str; + XF86OptionPtr *options; + XF86ConfDevicePtr dev = node->data->device.device; + + options = &(dev->dev_option_lst); + command = XtCreateManagedWidget("remove", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, DestroyCallback, (XtPointer)node); + command = XtCreateManagedWidget("options", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, OptionsCallback, (XtPointer)options); + label = XtVaCreateManagedWidget("label", labelWidgetClass, box, + XtNlabel, dev->dev_identifier, NULL, 0); + + XtCreateManagedWidget("vendorL", labelWidgetClass, box, NULL, 0); + str = dev->dev_vendor ? dev->dev_vendor : ""; + node->data->device.vendor = + XtVaCreateManagedWidget("vendor", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, str, + NULL, 0); + + XtCreateManagedWidget("boardL", labelWidgetClass, box, NULL, 0); + str = dev->dev_board ? dev->dev_board : ""; + node->data->device.board = + XtVaCreateManagedWidget("board", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, str, + NULL, 0); + + XtCreateManagedWidget("chipsetL", labelWidgetClass, box, NULL, 0); + str = dev->dev_chipset ? dev->dev_chipset : ""; + node->data->device.chipset = + XtVaCreateManagedWidget("chipset", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, str, + NULL, 0); + + XtCreateManagedWidget("busidL", labelWidgetClass, box, NULL, 0); + str = dev->dev_busid ? dev->dev_busid : ""; + node->data->device.busid = + XtVaCreateManagedWidget("busid", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, str, + NULL, 0); + + XtCreateManagedWidget("cardL", labelWidgetClass, box, NULL, 0); + str = dev->dev_card ? dev->dev_card : ""; + node->data->device.card = + XtVaCreateManagedWidget("card", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, str, + NULL, 0); + + XtCreateManagedWidget("driverL", labelWidgetClass, box, NULL, 0); + str = dev->dev_driver ? dev->dev_driver : ""; + node->data->device.driver = + XtVaCreateManagedWidget("driver", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, str, + NULL, 0); + + XtCreateManagedWidget("ramdacL", labelWidgetClass, box, NULL, 0); + str = dev->dev_ramdac ? dev->dev_ramdac : ""; + node->data->device.ramdac = + XtVaCreateManagedWidget("ramdac", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, str, + NULL, 0); + + XtCreateManagedWidget("dacSpeedL", labelWidgetClass, box, NULL, 0); + if (dev->dev_dacSpeeds[0] > 0) { + for (i = len = 0; i < CONF_MAXDACSPEEDS && + dev->dev_dacSpeeds[i] > 0; i++) { + tmp = XmuSnprintf(buf + len, sizeof(buf) - len, "%g ", + dev->dev_dacSpeeds[i] / 1000.); + len += tmp; + } + } + else + *buf = '\0'; + node->data->device.dacSpeed = + XtVaCreateManagedWidget("dacSpeed", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, + NULL, 0); + + XtCreateManagedWidget("videoRamL", labelWidgetClass, box, NULL, 0); + if (dev->dev_videoram) + XmuSnprintf(buf, sizeof(buf), "%d", dev->dev_videoram); + else + *buf = '\0'; + node->data->device.videoRam = + XtVaCreateManagedWidget("videoRam", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, + NULL, 0); + + XtCreateManagedWidget("textClockFreqL", labelWidgetClass, box, NULL, 0); + if (dev->dev_textclockfreq) + XmuSnprintf(buf, sizeof(buf), "%.1f", + (double)dev->dev_textclockfreq / 1000.0); + else + *buf = '\0'; + node->data->device.textClockFreq = + XtVaCreateManagedWidget("textClockFreq", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, + NULL, 0); + + XtCreateManagedWidget("biosBaseL", labelWidgetClass, box, NULL, 0); + if (dev->dev_bios_base) + XmuSnprintf(buf, sizeof(buf), "0x%lx", dev->dev_bios_base); + else + *buf = '\0'; + node->data->device.biosBase = + XtVaCreateManagedWidget("biosBase", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, + NULL, 0); + + XtCreateManagedWidget("memBaseL", labelWidgetClass, box, NULL, 0); + if (dev->dev_mem_base) + XmuSnprintf(buf, sizeof(buf), "0x%lx", dev->dev_mem_base); + else + *buf = '\0'; + node->data->device.memBase = + XtVaCreateManagedWidget("memBase", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, + NULL, 0); + + XtCreateManagedWidget("ioBaseL", labelWidgetClass, box, NULL, 0); + if (dev->dev_io_base) + XmuSnprintf(buf, sizeof(buf), "0x%lx", dev->dev_io_base); + else + *buf = '\0'; + node->data->device.ioBase = + XtVaCreateManagedWidget("ioBase", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, + NULL, 0); + + XtCreateManagedWidget("clockChipL", labelWidgetClass, box, NULL, 0); + str = dev->dev_clockchip ? dev->dev_clockchip : ""; + node->data->device.clockChip = + XtVaCreateManagedWidget("clockChip", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, str, + NULL, 0); + + *buf = '\0'; + for (i = len = 0; i < dev->dev_clocks; i++) { + tmp = XmuSnprintf(buf + len, sizeof(buf) - len, "%.1f ", + (double)dev->dev_clock[i] / 1000.0); + len += tmp; + } + XtCreateManagedWidget("devClockL", labelWidgetClass, box, NULL, 0); + node->data->device.devClock = + XtVaCreateManagedWidget("devClock", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, + NULL, 0); + + XtCreateManagedWidget("chipIdL", labelWidgetClass, box, NULL, 0); + if (dev->dev_chipid != -1) + XmuSnprintf(buf, sizeof(buf), "0x%x", dev->dev_chipid); + else + *buf = '\0'; + node->data->device.chipId = + XtVaCreateManagedWidget("chipId", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, + NULL, 0); + + XtCreateManagedWidget("chipRevL", labelWidgetClass, box, NULL, 0); + if (dev->dev_chiprev != -1) + XmuSnprintf(buf, sizeof(buf), "0x%x", dev->dev_chiprev); + else + *buf = '\0'; + node->data->device.chipRev = + XtVaCreateManagedWidget("chipRev", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, + NULL, 0); + + XtCreateManagedWidget("irqL", labelWidgetClass, box, NULL, 0); + if (dev->dev_irq != -1) + XmuSnprintf(buf, sizeof(buf), "%d", dev->dev_irq); + else + *buf = '\0'; + node->data->device.irq = + XtVaCreateManagedWidget("irq", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, + NULL, 0); + + XtCreateManagedWidget("screenL", labelWidgetClass, box, NULL, 0); + if (dev->dev_screen > 0) + XmuSnprintf(buf, sizeof(buf), "%d", dev->dev_screen); + else + *buf = '\0'; + node->data->device.screen = + XtVaCreateManagedWidget("screen", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, + NULL, 0); + } + else { + command = XtCreateManagedWidget("new", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, NewDeviceCallback, (XtPointer)node); + label = XtVaCreateManagedWidget("value", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + NULL, 0); + node->data->device.text = label; + } + if (XtIsRealized(node->treeParent)) + XtRealizeWidget(box); + XtManageChild(box); +} + +static void +NewDeviceCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + TreeNode *parent, *node = (TreeNode*)user_data; + XF86ConfDevicePtr dev; + Arg args[1]; + char *label; + + XtSetArg(args[0], XtNstring, &label); + XtGetValues(node->data->device.text, args, 1); + if (*label == '\0') + return; + + parent = node->parent; + DeleteNode(node); + dev = (XF86ConfDevicePtr)XtCalloc(1, sizeof(XF86ConfDeviceRec)); + dev->dev_identifier = XtNewString(label); + dev->dev_chipid = -1; + dev->dev_chiprev = -1; + dev->dev_irq = -1; + + XF86Config->conf_device_lst = + xf86addDevice(XF86Config->conf_device_lst, dev); + + CreateDevice(parent, dev); + + RelayoutTree(); +} + +static void +DeviceDestroy(TreeNode *node) +{ + int i; + TreeNode *sc = screenTree; + + for (i = 0; i < computer.num_devices; i++) + if ((XF86ConfDevicePtr)(computer.devices[i]->config) == + node->data->device.device) { + config = computer.devices[i]->widget; + RemoveDeviceCallback(NULL, NULL, NULL); + } + + if (sc) { + TreeNode *prev; + + sc = prev = sc->child; + while (sc->next) { + TreeNode *next = sc->next; + + if (sc->data->screen.screen->scrn_monitor == + node->data->monitor.monitor) { + XtDestroyWidget(sc->node); + + if (sc->child) + DestroyTree(sc->child); + if (sc->data) + XtFree((XtPointer)sc->data); + XtFree((XtPointer)sc); + + if (sc == screenTree->child) + sc = prev = next = screenTree->child = next; + else + prev->next = sc = next; + continue; + } + prev = sc; + sc = next; + } + } +} + +static void +DeviceUpdate(TreeNode *node) +{ + int i; + char *str, *tmp; + + /* vendor */ + XtVaGetValues(node->data->device.vendor, XtNstring, &str, NULL, 0); + XtFree(node->data->device.device->dev_vendor); + if (*str) + node->data->device.device->dev_vendor = XtNewString(str); + else + node->data->device.device->dev_vendor = NULL; + + /* board */ + XtVaGetValues(node->data->device.board, XtNstring, &str, NULL, 0); + XtFree(node->data->device.device->dev_board); + if (*str) + node->data->device.device->dev_board = XtNewString(str); + else + node->data->device.device->dev_board = NULL; + + /* chipset */ + XtVaGetValues(node->data->device.chipset, XtNstring, &str, NULL, 0); + XtFree(node->data->device.device->dev_chipset); + if (*str) + node->data->device.device->dev_chipset = XtNewString(str); + else + node->data->device.device->dev_chipset = NULL; + + /* busid */ + XtVaGetValues(node->data->device.busid, XtNstring, &str, NULL, 0); + XtFree(node->data->device.device->dev_busid); + if (*str) + node->data->device.device->dev_busid = XtNewString(str); + else + node->data->device.device->dev_busid = NULL; + + /* card */ + XtVaGetValues(node->data->device.card, XtNstring, &str, NULL, 0); + XtFree(node->data->device.device->dev_card); + if (*str) + node->data->device.device->dev_card = XtNewString(str); + else + node->data->device.device->dev_card = NULL; + + /* driver */ + XtVaGetValues(node->data->device.driver, XtNstring, &str, NULL, 0); + XtFree(node->data->device.device->dev_driver); + if (*str) + node->data->device.device->dev_driver = XtNewString(str); + else + node->data->device.device->dev_driver = NULL; + + /* ramdac */ + XtVaGetValues(node->data->device.ramdac, XtNstring, &str, NULL, 0); + XtFree(node->data->device.device->dev_ramdac); + if (*str) + node->data->device.device->dev_ramdac = XtNewString(str); + else + node->data->device.device->dev_ramdac = NULL; + + /* dacSpeed */ + tmp = NULL; + XtVaGetValues(node->data->device.dacSpeed, XtNstring, &str, NULL, 0); + for (i = 0; i < CONF_MAXDACSPEEDS && str != tmp; i++) { + if ((node->data->device.device->dev_dacSpeeds[i] = + (strtod(str, &tmp) * 1000. + .5)) == 0) + break; + str = tmp; + while (isspace(*str)) + ++str; + } + + /* videoRam */ + XtVaGetValues(node->data->device.videoRam, XtNstring, &str, NULL, 0); + node->data->device.device->dev_videoram = strtoul(str, NULL, 0); + + /* textClockFreq */ + XtVaGetValues(node->data->device.textClockFreq, XtNstring, &str, NULL, 0); + node->data->device.device->dev_textclockfreq = + strtod(str, NULL) * 1000. + .5; + + /* biosBase */ + XtVaGetValues(node->data->device.biosBase, XtNstring, &str, NULL, 0); + node->data->device.device->dev_bios_base = strtoul(str, NULL, 0); + + /* memBase */ + XtVaGetValues(node->data->device.memBase, XtNstring, &str, NULL, 0); + node->data->device.device->dev_mem_base = strtoul(str, NULL, 0); + + /* ioBase */ + XtVaGetValues(node->data->device.ioBase, XtNstring, &str, NULL, 0); + node->data->device.device->dev_io_base = strtoul(str, NULL, 0); + + /* clockChip */ + XtVaGetValues(node->data->device.clockChip, XtNstring, &str, NULL, 0); + XtFree(node->data->device.device->dev_clockchip); + if (*str) + node->data->device.device->dev_clockchip = XtNewString(str); + else + node->data->device.device->dev_clockchip = NULL; + + /* devSpeed */ + tmp = NULL; + XtVaGetValues(node->data->device.devClock, XtNstring, &str, NULL, 0); + for (i = 0; i < CONF_MAXCLOCKS && str != tmp; i++) { + if ((node->data->device.device->dev_clock[i] = + (strtod(str, &tmp) * 1000. + .5)) == 0) + break; + str = tmp; + while (isspace(*str)) + ++str; + } + node->data->device.device->dev_clocks = i; + + /* chipId */ + XtVaGetValues(node->data->device.chipId, XtNstring, &str, NULL, 0); + if (*str) + node->data->device.device->dev_chipid = strtoul(str, NULL, 0); + else + node->data->device.device->dev_chipid = -1; + + /* chipRev */ + XtVaGetValues(node->data->device.chipRev, XtNstring, &str, NULL, 0); + if (*str) + node->data->device.device->dev_chiprev = strtoul(str, NULL, 0); + else + node->data->device.device->dev_chiprev = -1; + + /* irq */ + XtVaGetValues(node->data->device.irq, XtNstring, &str, NULL, 0); + if (*str) + node->data->device.device->dev_irq = strtoul(str, NULL, 0); + else + node->data->device.device->dev_irq = -1; + + /* screen */ + XtVaGetValues(node->data->device.screen, XtNstring, &str, NULL, 0); + if (*str) + node->data->device.device->dev_screen = strtoul(str, NULL, 0); + else + node->data->device.device->dev_screen = -1; +} + +/* Screen */ +static void +CreateScreen(TreeNode *parent, XF86ConfScreenPtr scrn) +{ + TreeNode *prev, *node; + TreeData *data; + + if ((prev = parent->child) != NULL) + while (prev->next) + prev = prev->next; + + while (scrn) { + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->screen.screen = scrn; + node = NewNode(parent, NULL, NULL, parent->node, data); + node->destroy = ScreenDestroy; + node->update = ScreenUpdate; + CreateScreenField(node, False); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + scrn = (XF86ConfScreenPtr)(scrn->list.next); + } + + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + node = NewNode(parent, NULL, NULL, parent->node, data); + CreateScreenField(node, True); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; +} + +static void +CreateScreenField(TreeNode *node, Bool addnew) +{ + Widget box, command, label; + + box = XtVaCreateWidget("screen", formWidgetClass, tree, + XtNtreeParent, node->treeParent, NULL, 0); + node->node = box; + + if (!addnew) { + char buf[256], *str; + XF86OptionPtr *options; + TreeNode *adaptor, *display; + XF86ConfScreenPtr scrn = node->data->screen.screen; + + options = &(scrn->scrn_option_lst); + command = XtCreateManagedWidget("remove", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, DestroyCallback, (XtPointer)node); + command = XtCreateManagedWidget("options", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, OptionsCallback, (XtPointer)options); + label = XtVaCreateManagedWidget("label", labelWidgetClass, box, + XtNlabel, scrn->scrn_identifier, NULL, 0); + + XtCreateManagedWidget("defaultDepthL", labelWidgetClass, box, NULL, 0); + if (scrn->scrn_defaultdepth) + XmuSnprintf(buf, sizeof(buf), "%d", scrn->scrn_defaultdepth); + else + *buf = '\0'; + node->data->screen.defaultDepth = + XtVaCreateManagedWidget("defaultDepth", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, + NULL, 0); + + XtCreateManagedWidget("defaultBppL", labelWidgetClass, box, NULL, 0); + if (scrn->scrn_defaultbpp) + XmuSnprintf(buf, sizeof(buf), "%d", scrn->scrn_defaultbpp); + else + *buf = '\0'; + node->data->screen.defaultBpp = + XtVaCreateManagedWidget("defaultBpp", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, + NULL, 0); + + XtCreateManagedWidget("defaultFbBppL", labelWidgetClass, box, NULL, 0); + if (scrn->scrn_defaultfbbpp) + XmuSnprintf(buf, sizeof(buf), "%d", scrn->scrn_defaultfbbpp); + else + *buf = '\0'; + node->data->screen.defaultFbBpp = + XtVaCreateManagedWidget("defaultFbBpp", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, + NULL, 0); + + XtCreateManagedWidget("monitorL", labelWidgetClass, box, NULL, 0); + str = scrn->scrn_monitor_str ? scrn->scrn_monitor_str : ""; + node->data->screen.monitor = + XtVaCreateManagedWidget("monitor", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, str, + NULL, 0); + + XtCreateManagedWidget("deviceL", labelWidgetClass, box, NULL, 0); + str = scrn->scrn_device_str ? scrn->scrn_device_str : ""; + node->data->screen.device = + XtVaCreateManagedWidget("device", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, str, + NULL, 0); + + command = XtVaCreateManagedWidget("videoAdaptor", toggleWidgetClass, + tree, XtNstate, True, + XtNtreeParent, box, NULL, 0); + adaptor = NewNode(node, command, command, node->node, NULL); + CreateScreenAdaptor(adaptor, scrn->scrn_adaptor_lst); + node->child = adaptor; + + command = XtVaCreateManagedWidget("Display", toggleWidgetClass, + tree, XtNstate, True, + XtNtreeParent, box, NULL, 0); + display = NewNode(node, command, command, node->node, NULL); + CreateScreenDisplay(display, scrn->scrn_display_lst); + adaptor->next = display; + } + else { + command = XtCreateManagedWidget("new", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, NewScreenCallback, (XtPointer)node); + label = XtVaCreateManagedWidget("value", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + NULL, 0); + node->data->screen.text = label; + } + if (XtIsRealized(node->treeParent)) + XtRealizeWidget(box); + XtManageChild(box); +} + +static void +NewScreenCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + TreeNode *parent, *node = (TreeNode*)user_data; + XF86ConfScreenPtr scrn; + Arg args[1]; + char *label; + + XtSetArg(args[0], XtNstring, &label); + XtGetValues(node->data->screen.text, args, 1); + if (*label == '\0') + return; + + parent = node->parent; + DeleteNode(node); + scrn = (XF86ConfScreenPtr)XtCalloc(1, sizeof(XF86ConfScreenRec)); + scrn->scrn_identifier = XtNewString(label); + XF86Config->conf_screen_lst = + xf86addScreen(XF86Config->conf_screen_lst, scrn); + + { + TreeNode *lay = layoutTree->child; + Widget sme; + + /* last one is the "new" entry */ + while (lay && lay->next != NULL) { + /* Adjacency is the first entry */ + TreeNode *adj = lay->child->child; + + while (adj != NULL) { + sme = XtCreateManagedWidget(label, smeBSBObjectClass, + adj->data->adjacency.menu, NULL, 0); + XtAddCallback(sme, XtNcallback, adj->next != NULL ? + AdjacencyMenuCallback : NewAdjacencyCallback, + (XtPointer)adj); + adj = adj->next; + } + lay = lay->next; + } + } + + CreateScreen(parent, scrn); + + RelayoutTree(); +} + +static void +ScreenDestroy(TreeNode *node) +{ + if (node->data->screen.screen) { + int i; + TreeNode *lay = layoutTree->child; + + /* last one is the "new" entry */ + while (lay && lay->next) { + /* Adjacency is the first entry */ + TreeNode *adj = lay->child->child; + CompositeWidget composite; + + while (adj) { + TreeNode *next = adj->next; + + composite = (CompositeWidget)adj->data->adjacency.menu; + + for (i = 0; i < composite->composite.num_children; ++i) + if (strcmp(XtName(composite->composite.children[i]), + node->data->screen.screen->scrn_identifier) == 0) { + XtDestroyWidget(composite->composite.children[i]); + break; + } + + if (adj->data->adjacency.screen == node->data->screen.screen) + DeleteNode(adj); + + adj = next; + } + + lay = lay->next; + } + + for (i = 0; i < computer.num_screens; i++) + if (computer.screens[i]->screen == node->data->screen.screen) { + config = computer.screens[i]->widget; + RemoveDeviceCallback(NULL, NULL, NULL); + } + + /* for the case of screens added and removed in the expert dialog */ + xf86removeScreen(XF86Config, node->data->screen.screen); + } +} + +static void +ScreenUpdate(TreeNode *node) +{ + char *str; + + /* defautDepth */ + XtVaGetValues(node->data->screen.defaultDepth, XtNstring, &str, NULL, 0); + node->data->screen.screen->scrn_defaultdepth = strtoul(str, NULL, 0); + + /* defautBpp */ + XtVaGetValues(node->data->screen.defaultBpp, XtNstring, &str, NULL, 0); + node->data->screen.screen->scrn_defaultbpp = strtoul(str, NULL, 0); + + /* defautFbBpp */ + XtVaGetValues(node->data->screen.defaultFbBpp, XtNstring, &str, NULL, 0); + node->data->screen.screen->scrn_defaultfbbpp = strtoul(str, NULL, 0); + + + /* XXX Monitor and Device should be changed to a menu interface */ + /* monitor */ + XtVaGetValues(node->data->screen.monitor, XtNstring, &str, NULL, 0); + XtFree(node->data->screen.screen->scrn_monitor_str); + if (*str) + node->data->screen.screen->scrn_monitor_str = XtNewString(str); + else + node->data->screen.screen->scrn_monitor_str = NULL; + + /* XXX Monitor and Device should be changed to a menu interface */ + /* device */ + XtVaGetValues(node->data->screen.device, XtNstring, &str, NULL, 0); + XtFree(node->data->screen.screen->scrn_device_str); + if (*str) + node->data->screen.screen->scrn_device_str = XtNewString(str); + else + node->data->screen.screen->scrn_device_str = NULL; +} + +static void +CreateScreenAdaptor(TreeNode *parent, XF86ConfAdaptorLinkPtr lnk) +{ + TreeNode *node, *prev; + TreeData *data; + + if ((prev = parent->child) != NULL) + while (prev->next) + prev = prev->next; + + while (lnk) { + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->adaptorlink.adaptorlink = lnk; + node = NewNode(parent, NULL, NULL, parent->node, data); + node->destroy = ScreenAdaptorDestroy; + CreateScreenAdaptorField(node, False); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + lnk = (XF86ConfAdaptorLinkPtr)(lnk->list.next); + } + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + node = NewNode(parent, NULL, NULL, parent->node, data); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + CreateScreenAdaptorField(node, True); +} + +static void +CreateScreenAdaptorField(TreeNode *node, Bool addnew) +{ + Widget box, command, label; + + box = XtVaCreateWidget("adaptor", formWidgetClass, tree, + XtNtreeParent, node->treeParent, NULL, 0); + node->node = box; + + if (!addnew) { + XF86ConfAdaptorLinkPtr lnk = node->data->adaptorlink.adaptorlink; + + command = XtCreateManagedWidget("remove", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, DestroyCallback, (XtPointer)node); + label = XtVaCreateManagedWidget("label", labelWidgetClass, box, + XtNlabel, lnk->al_adaptor_str, NULL, 0); + } + else { + Widget sme; + XF86ConfVideoAdaptorPtr ptr = XF86Config->conf_videoadaptor_lst; + + command = XtVaCreateManagedWidget("new", menuButtonWidgetClass, box, + XtNmenuName, "adaptorMenu", NULL, 0); + node->data->adaptorlink.menu = + XtVaCreatePopupShell("adaptorMenu", simpleMenuWidgetClass, box, + XtNleftMargin, 1, XtNrightMargin, 1, + XtNtopMargin, 1, XtNbottomMargin, 1, + NULL, 0); + while (ptr) { + sme = XtCreateManagedWidget(ptr->va_identifier, smeBSBObjectClass, + node->data->adaptorlink.menu, NULL, 0); + XtAddCallback(sme, XtNcallback, NewScreenAdaptorCallback, + (XtPointer)node); + ptr = (XF86ConfVideoAdaptorPtr)(ptr->list.next); + } + } + if (XtIsRealized(node->treeParent)) + XtRealizeWidget(box); + XtManageChild(box); +} + +/*ARGSUSED*/ +static void +NewScreenAdaptorCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + TreeNode *parent, *node = (TreeNode*)user_data; + XF86ConfAdaptorLinkPtr link; + char *ident = XtName(w); + + parent = node->parent; + DeleteNode(node); + link = (XF86ConfAdaptorLinkPtr)XtCalloc(1, sizeof(XF86ConfAdaptorLinkRec)); + link->al_adaptor_str = XtNewString(ident); + parent->parent->data->screen.screen->scrn_adaptor_lst = + xf86addScreenAdaptor(parent->parent->data->screen.screen->scrn_adaptor_lst, + link); + + CreateScreenAdaptor(parent, link); + RelayoutTree(); +} + +/*ARGUSED*/ +static void +ScreenAdaptorDestroy(TreeNode *node) +{ + if (node->data->adaptorlink.adaptorlink) + xf86removeScreenAdaptorLink(node->parent->parent->data->screen.screen, + node->data->adaptorlink.adaptorlink); +} + +static void +CreateScreenDisplay(TreeNode *parent, XF86ConfDisplayPtr dsp) +{ + TreeNode *node, *prev; + TreeData *data; + + if ((prev = parent->child) != NULL) + while (prev->next) + prev = prev->next; + + while (dsp) { + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->display.display = dsp; + node = NewNode(parent, NULL, NULL, parent->node, data); + node->destroy = ScreenDisplayDestroy; + node->update = ScreenDisplayUpdate; + CreateScreenDisplayField(node, False); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + dsp = (XF86ConfDisplayPtr)(dsp->list.next); + } + node = NewNode(parent, NULL, NULL, parent->node, NULL); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + CreateScreenDisplayField(node, True); +} + +static void +CreateScreenDisplayField(TreeNode *node, Bool addnew) +{ + Widget box, command; + + box = XtVaCreateWidget("display", formWidgetClass, tree, + XtNtreeParent, node->treeParent, NULL, 0); + node->node = box; + + if (!addnew) { + char *str, buf[256]; + XF86OptionPtr *options; + XF86ConfDisplayPtr dsp = node->data->display.display; + TreeNode *modes; + + command = XtCreateManagedWidget("remove", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, DestroyCallback, (XtPointer)node); + options = &(dsp->disp_option_lst); + command = XtCreateManagedWidget("options", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, OptionsCallback, (XtPointer)options); + + XtCreateManagedWidget("viewportL", labelWidgetClass, box, NULL, 0); + if (dsp->disp_frameX0 != 0 || dsp->disp_frameY0 != 0) + XmuSnprintf(buf, sizeof(buf), "%d %d", dsp->disp_frameX0, dsp->disp_frameY0); + else + *buf = '\0'; + node->data->display.viewport = + XtVaCreateManagedWidget("viewport", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, NULL, 0); + + XtCreateManagedWidget("virtualL", labelWidgetClass, box, NULL, 0); + if (dsp->disp_virtualX != 0 || dsp->disp_virtualY != 0) + XmuSnprintf(buf, sizeof(buf), "%d %d", dsp->disp_virtualX, dsp->disp_virtualY); + else + *buf = '\0'; + node->data->display.c_virtual = + XtVaCreateManagedWidget("virtual", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, NULL, 0); + + XtCreateManagedWidget("depthL", labelWidgetClass, box, NULL, 0); + if (dsp->disp_depth != 0) + XmuSnprintf(buf, sizeof(buf), "%d", dsp->disp_depth); + else + *buf = '\0'; + node->data->display.depth = + XtVaCreateManagedWidget("depth", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, NULL, 0); + + XtCreateManagedWidget("bppL", labelWidgetClass, box, NULL, 0); + if (dsp->disp_bpp != 0) + XmuSnprintf(buf, sizeof(buf), "%d", dsp->disp_bpp); + else + *buf = '\0'; + node->data->display.bpp = + XtVaCreateManagedWidget("bpp", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, NULL, 0); + + XtCreateManagedWidget("visualL", labelWidgetClass, box, NULL, 0); + str = dsp->disp_visual != NULL ? dsp->disp_visual : ""; + node->data->display.visual = + XtVaCreateManagedWidget("visual", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, str, NULL, 0); + + XtCreateManagedWidget("weightL", labelWidgetClass, box, NULL, 0); + if (dsp->disp_weight.red > 0) + XmuSnprintf(buf, sizeof(buf), "%d %d %d", + dsp->disp_weight.red, dsp->disp_weight.green, dsp->disp_weight.blue); + else + *buf = '\0'; + node->data->display.weight = + XtVaCreateManagedWidget("weight", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, NULL, 0); + + XtCreateManagedWidget("blackL", labelWidgetClass, box, NULL, 0); + if (dsp->disp_black.red >= 0) + XmuSnprintf(buf, sizeof(buf), "0x%04x 0x%04x 0x%04x", + dsp->disp_black.red, dsp->disp_black.green, dsp->disp_black.blue); + else + *buf = '\0'; + node->data->display.black = + XtVaCreateManagedWidget("black", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, NULL, 0); + + XtCreateManagedWidget("whiteL", labelWidgetClass, box, NULL, 0); + if (dsp->disp_white.red >= 0) + XmuSnprintf(buf, sizeof(buf), "0x%04x 0x%04x 0x%04x", + dsp->disp_white.red, dsp->disp_white.green, dsp->disp_white.blue); + else + *buf = '\0'; + node->data->display.white = + XtVaCreateManagedWidget("white", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, NULL, 0); + + command = XtVaCreateManagedWidget("Modes", toggleWidgetClass, tree, + XtNstate, True, XtNtreeParent, box, + NULL, 0); + modes = NewNode(node, command, command, node->node, NULL); + node->child = modes; + CreateDisplayMode(modes, dsp->disp_mode_lst); + } + else { + command = XtCreateManagedWidget("new", commandWidgetClass, box, NULL, 0); + XtAddCallback(command, XtNcallback, NewScreenDisplayCallback, + (XtPointer)node); + } + if (XtIsRealized(node->treeParent)) + XtRealizeWidget(box); + XtManageChild(box); +} + +/*ARGSUSED*/ +static void +NewScreenDisplayCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + TreeNode *parent, *node = (TreeNode*)user_data; + XF86ConfDisplayPtr dsp; + + parent = node->parent; + DeleteNode(node); + dsp = (XF86ConfDisplayPtr)XtCalloc(1, sizeof(XF86ConfDisplayRec)); + dsp->disp_black.red = dsp->disp_black.green = dsp->disp_black.blue = + dsp->disp_white.red = dsp->disp_white.green = dsp->disp_white.blue = -1; + parent->parent->data->screen.screen->scrn_display_lst = + xf86addScreenDisplay(parent->parent->data->screen.screen->scrn_display_lst, + dsp); + + CreateScreenDisplay(parent, dsp); + RelayoutTree(); +} + +static void +ScreenDisplayDestroy(TreeNode *node) +{ + if (node->data->display.display) + xf86removeScreenDisplay(node->parent->parent->data->screen.screen, + node->data->display.display); +} + +static void +ScreenDisplayUpdate(TreeNode *node) +{ + char *str, *tmp; + int x, y; + + /* viewport */ + XtVaGetValues(node->data->display.viewport, XtNstring, &str, NULL, 0); + if (sscanf(str, "%d %d", &x, &y) == 2) { + node->data->display.display->disp_frameX0 = x; + node->data->display.display->disp_frameY0 = y; + } + + /* virtual */ + XtVaGetValues(node->data->display.c_virtual, XtNstring, &str, NULL, 0); + if (sscanf(str, "%d %d", &x, &y) == 2) { + node->data->display.display->disp_virtualX = x; + node->data->display.display->disp_virtualY = y; + } + + /* depth */ + XtVaGetValues(node->data->display.depth, XtNstring, &str, NULL, 0); + node->data->display.display->disp_depth = strtoul(str, NULL, 0); + + /* bpp */ + XtVaGetValues(node->data->display.bpp, XtNstring, &str, NULL, 0); + node->data->display.display->disp_bpp = strtoul(str, NULL, 0); + + /* visual */ + XtVaGetValues(node->data->display.visual, XtNstring, &str, NULL, 0); + XtFree(node->data->display.display->disp_visual); + if (*str) + node->data->display.display->disp_visual = XtNewString(str); + else + node->data->display.display->disp_visual = NULL; + + /* weight */ + XtVaGetValues(node->data->display.weight, XtNstring, &str, NULL, 0); + node->data->display.display->disp_weight.red = strtoul(str, &tmp, 0); + if (str == tmp) + node->data->display.display->disp_weight.red = 0; + else { + str = tmp; + while (isspace(*str)) + ++str; + node->data->display.display->disp_weight.green = strtoul(str, &tmp, 0); + if (str != tmp) { + str = tmp; + while (isspace(*str)) + ++str; + node->data->display.display->disp_weight.blue = strtoul(str, &tmp, 0); + } + } + + /* black */ + XtVaGetValues(node->data->display.black, XtNstring, &str, NULL, 0); + node->data->display.display->disp_black.red = strtoul(str, &tmp, 0); + if (str == tmp) + node->data->display.display->disp_black.red = -1; + else { + str = tmp; + while (isspace(*str)) + ++str; + node->data->display.display->disp_black.green = strtoul(str, &tmp, 0); + if (str != tmp) { + str = tmp; + while (isspace(*str)) + ++str; + node->data->display.display->disp_black.blue = strtoul(str, &tmp, 0); + } + } + + /* white */ + XtVaGetValues(node->data->display.white, XtNstring, &str, NULL, 0); + node->data->display.display->disp_white.red = strtoul(str, &tmp, 0); + if (str == tmp) + node->data->display.display->disp_white.red = -1; + else { + str = tmp; + while (isspace(*str)) + ++str; + node->data->display.display->disp_white.green = strtoul(str, &tmp, 0); + if (str != tmp) { + str = tmp; + while (isspace(*str)) + ++str; + node->data->display.display->disp_white.blue = strtoul(str, &tmp, 0); + } + } +} + +static void +CreateDisplayMode(TreeNode *parent, XF86ModePtr modes) +{ + TreeNode *node, *prev; + TreeData *data; + + if ((prev = parent->child) != NULL) + while (prev->next) + prev = prev->next; + + while (modes) { + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->mode.mode = modes; + node = NewNode(parent, NULL, NULL, parent->node, data); + node->destroy = DisplayModeDestroy; + CreateDisplayModeField(node, False); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + modes = (XF86ModePtr)(modes->list.next); + } + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + node = NewNode(parent, NULL, NULL, parent->node, data); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + CreateDisplayModeField(node, True); +} + +static void +CreateDisplayModeField(TreeNode *node, Bool addnew) +{ + Widget box, command, text; + + box = XtVaCreateWidget("mode", formWidgetClass, tree, + XtNtreeParent, node->treeParent, NULL, 0); + node->node = box; + if (!addnew) { + XF86ModePtr mode = node->data->mode.mode; + + command = XtCreateManagedWidget("remove", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, DestroyCallback, + (XtPointer)node); + text = XtVaCreateManagedWidget("label", labelWidgetClass, box, + XtNlabel, mode->mode_name, NULL, 0); + } + else { + command = XtCreateManagedWidget("new", commandWidgetClass, box, NULL, 0); + XtAddCallback(command, XtNcallback, NewDisplayModeCallback, + (XtPointer)node); + text = XtVaCreateManagedWidget("value", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, NULL, 0); + } + node->data->mode.text = text; + if (node->treeParent && XtIsRealized(node->treeParent)) + XtRealizeWidget(box); + XtManageChild(box); +} + +/*ARGSUSED*/ +static void +NewDisplayModeCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + TreeNode *parent, *node = (TreeNode*)user_data; + XF86ModePtr mode; + Arg args[1]; + char *ident; + + XtSetArg(args[0], XtNstring, &ident); + XtGetValues(node->data->mode.text, args, 1); + if (*ident == '\0') + return; + + parent = node->parent; + DeleteNode(node); + mode = (XF86ModePtr)XtCalloc(1, sizeof(XF86ModeRec)); + mode->mode_name = XtNewString(ident); + parent->parent->data->display.display->disp_mode_lst = + xf86addDisplayMode(parent->parent->data->display.display->disp_mode_lst, + mode); + + CreateDisplayMode(parent, mode); + RelayoutTree(); +} + +/*ARGUSED*/ +static void +DisplayModeDestroy(TreeNode *node) +{ + if (node->data->mode.mode) + xf86removeDisplayMode(node->parent->parent->data->display.display, + node->data->mode.mode); +} + +/* Input */ +static void +CreateInput(TreeNode *parent, XF86ConfInputPtr input) +{ + TreeNode *prev, *node; + TreeData *data; + + if ((prev = parent->child) != NULL) + while (prev->next) + prev = prev->next; + + while (input) { + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->input.input = input; + node = NewNode(parent, NULL, NULL, parent->node, data); + node->destroy = InputDestroy; + node->update = InputUpdate; + CreateInputField(node, False); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + input = (XF86ConfInputPtr)(input->list.next); + } + + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + node = NewNode(parent, NULL, NULL, parent->node, data); + CreateInputField(node, True); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; +} + +static void +CreateInputField(TreeNode *node, Bool addnew) +{ + Widget box, command; + + box = XtVaCreateWidget("input", formWidgetClass, tree, + XtNtreeParent, node->treeParent, NULL, 0); + node->node = box; + + if (!addnew) { + char *str; + XF86OptionPtr *options; + XF86ConfInputPtr inp = node->data->input.input; + + command = XtCreateManagedWidget("remove", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, DestroyCallback, (XtPointer)node); + options = &(inp->inp_option_lst); + command = XtCreateManagedWidget("options", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, OptionsCallback, (XtPointer)options); + XtVaCreateManagedWidget("label", labelWidgetClass, box, + XtNlabel, inp->inp_identifier, NULL, 0); + + XtCreateManagedWidget("driverL", labelWidgetClass, box, NULL, 0); + str = inp->inp_driver != NULL ? inp->inp_driver : ""; + node->data->input.text = + XtVaCreateManagedWidget("driver", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, str, NULL, 0); + } + else { + command = XtCreateManagedWidget("new", commandWidgetClass, box, NULL, 0); + XtAddCallback(command, XtNcallback, NewInputCallback, + (XtPointer)node); + node->data->input.text = + XtVaCreateManagedWidget("value", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, NULL, 0); + } + if (XtIsRealized(node->treeParent)) + XtRealizeWidget(box); + XtManageChild(box); +} + +/*ARGSUSED*/ +static void +NewInputCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + TreeNode *parent, *node = (TreeNode*)user_data; + XF86ConfInputPtr input; + Arg args[1]; + char *ident; + + XtSetArg(args[0], XtNstring, &ident); + XtGetValues(node->data->input.text, args, 1); + if (*ident == '\0') + return; + + parent = node->parent; + DeleteNode(node); + input = (XF86ConfInputPtr)XtCalloc(1, sizeof(XF86ConfInputRec)); + input->inp_identifier = XtNewString(ident); + XF86Config->conf_input_lst = + xf86addInput(XF86Config->conf_input_lst, input); + + { + TreeNode *lay = layoutTree->child; + Widget sme; + + /* last one is the "new" entry */ + while (lay && lay->next != NULL) { + /* Inputref is the second entry */ + TreeNode *iref = lay->child->next->child; + + while (iref && iref->next) + iref = iref->next; + sme = XtCreateManagedWidget(ident, smeBSBObjectClass, + iref->data->inputref.menu, NULL, 0); + XtAddCallback(sme, XtNcallback, NewInputrefCallback, + (XtPointer)iref); + lay = lay->next; + } + } + + CreateInput(parent, input); + RelayoutTree(); +} + +/*ARGUSED*/ +static void +InputDestroy(TreeNode *node) +{ + if (node->data->input.input) { + int i; + TreeNode *lay = layoutTree->child; + + /* last one is the "new" entry */ + while (lay && lay->next) { + /* Inputref is the second entry */ + TreeNode *iref = lay->child->next->child; + CompositeWidget composite; + + while (iref && iref->next) { + TreeNode *next = iref->next; + + if (iref && strcmp(iref->data->inputref.inputref->iref_inputdev_str, + node->data->input.input->inp_identifier) == 0) + DeleteNode(iref); + iref = next; + } + + composite = (CompositeWidget)iref->data->inputref.menu; + + for (i = 0; i < composite->composite.num_children; ++i) + if (strcmp(XtName(composite->composite.children[i]), + node->data->input.input->inp_identifier) == 0) + XtDestroyWidget(composite->composite.children[i]); + + lay = lay->next; + } + + for (i = 0; i < computer.num_devices; i++) + if ((XF86ConfInputPtr)(computer.devices[i]->config) == + node->data->input.input) { + config = computer.devices[i]->widget; + RemoveDeviceCallback(NULL, NULL, NULL); + } + } +} + +static void +InputUpdate(TreeNode *node) +{ + char *str; + + /* vendor */ + XtVaGetValues(node->data->input.text, XtNstring, &str, NULL, 0); + XtFree(node->data->input.input->inp_driver); + if (*str) + node->data->input.input->inp_driver = XtNewString(str); + else + node->data->input.input->inp_driver = NULL; +} + +/* Layout */ +static void +CreateLayout(TreeNode *parent, XF86ConfLayoutPtr lay) +{ + TreeNode *prev, *node; + TreeData *data; + + if ((prev = parent->child) != NULL) + while (prev->next) + prev = prev->next; + + while (lay) { + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->layout.layout = lay; + node = NewNode(parent, NULL, NULL, parent->node, data); + node->destroy = LayoutDestroy; + CreateLayoutField(node, False); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + lay = (XF86ConfLayoutPtr)(lay->list.next); + } + + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + node = NewNode(parent, NULL, NULL, parent->node, data); + CreateLayoutField(node, True); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; +} + +static void +CreateLayoutField(TreeNode *node, Bool addnew) +{ + Widget box, command, label; + + box = XtVaCreateWidget("layout", formWidgetClass, tree, + XtNtreeParent, node->treeParent, NULL, 0); + node->node = box; + + if (!addnew) { + TreeNode *adjacency, *inputref; + XF86OptionPtr *options; + XF86ConfLayoutPtr lay = node->data->layout.layout; + + options = &(lay->lay_option_lst); + command = XtCreateManagedWidget("remove", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, DestroyCallback, (XtPointer)node); + command = XtCreateManagedWidget("options", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, OptionsCallback, (XtPointer)options); + label = XtVaCreateManagedWidget("label", labelWidgetClass, box, + XtNlabel, lay->lay_identifier, NULL, 0); + + command = XtVaCreateManagedWidget("Adjacency", toggleWidgetClass, tree, + XtNstate, True, XtNtreeParent, box, + NULL, 0); + adjacency = NewNode(node, command, command, box, NULL); + node->child = adjacency; + CreateAdjacency(adjacency, lay->lay_adjacency_lst); + + command = XtVaCreateManagedWidget("Inputref", toggleWidgetClass, tree, + XtNstate, True, XtNtreeParent, box, + NULL, 0); + inputref = NewNode(node, command, command, box, NULL); + adjacency->next = inputref; + CreateInputref(inputref, lay->lay_input_lst); + } + else { + command = XtCreateManagedWidget("new", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, NewLayoutCallback, (XtPointer)node); + label = XtVaCreateManagedWidget("value", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + NULL, 0); + node->data->layout.text = label; + } + if (XtIsRealized(node->treeParent)) + XtRealizeWidget(box); + XtManageChild(box); +} + +/*ARGUSED*/ +static void +LayoutDestroy(TreeNode *node) +{ + if (node->data->layout.layout) + xf86removeLayout(XF86Config, node->data->layout.layout); +} + +/*ARGSUSED*/ +static void +NewLayoutCallback(Widget unused, XtPointer user_data, XtPointer call_data) +{ + TreeNode *parent, *node = (TreeNode*)user_data; + XF86ConfLayoutPtr lay; + Arg args[1]; + char *label; + + XtSetArg(args[0], XtNstring, &label); + XtGetValues(node->data->layout.text, args, 1); + if (*label == '\0') + return; + + parent = node->parent; + DeleteNode(node); + lay = (XF86ConfLayoutPtr)XtCalloc(1, sizeof(XF86ConfLayoutRec)); + lay->lay_identifier = XtNewString(label); + XF86Config->conf_layout_lst = xf86addLayout(XF86Config->conf_layout_lst, lay); + + CreateLayout(parent, lay); + RelayoutTree(); +} + +static void +CreateAdjacency(TreeNode *parent, XF86ConfAdjacencyPtr adj) +{ + TreeNode *prev, *node; + TreeData *data; + + if ((prev = parent->child) != NULL) + while (prev->next) + prev = prev->next; + + while (adj) { + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->adjacency.screen = adj ? adj->adj_screen : NULL; + data->adjacency.adjacency = adj; + node = NewNode(parent, NULL, NULL, parent->node, data); + node->destroy = AdjacencyDestroy; + CreateAdjacencyField(node, False); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + adj = (XF86ConfAdjacencyPtr)(adj->list.next); + } + + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + node = NewNode(parent, NULL, NULL, parent->node, data); + CreateAdjacencyField(node, True); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; +} + +static void +CreateAdjacencyField(TreeNode *node, Bool addnew) +{ + Widget box, command, label, sme; + XF86ConfScreenPtr ptr = XF86Config->conf_screen_lst; + + box = XtVaCreateWidget("adjacency", formWidgetClass, tree, + XtNtreeParent, node->treeParent, NULL, 0); + node->node = box; + + node->data->adjacency.menu = + XtVaCreatePopupShell("screenMenu", simpleMenuWidgetClass, box, + XtNleftMargin, 1, XtNrightMargin, 1, + XtNtopMargin, 1, XtNbottomMargin, 1, + NULL, 0); + while (ptr) { + sme = XtCreateManagedWidget(ptr->scrn_identifier, smeBSBObjectClass, + node->data->adjacency.menu, NULL, 0); + XtAddCallback(sme, XtNcallback, !addnew ? + AdjacencyMenuCallback : NewAdjacencyCallback, + (XtPointer)node); + ptr = (XF86ConfScreenPtr)(ptr->list.next); + } + + if (!addnew) { + char buf[32]; + Cardinal width, height; + Widget left, right, above, below, relative, absolute; + XF86ConfAdjacencyPtr adj = node->data->adjacency.adjacency; + + command = XtCreateManagedWidget("remove", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, DestroyCallback, (XtPointer)node); + label = XtVaCreateManagedWidget("label", labelWidgetClass, box, + XtNlabel, adj->adj_screen->scrn_identifier, + NULL, 0); + + XtCreateManagedWidget("scrnumL", labelWidgetClass, box, NULL, 0); + if (adj->adj_scrnum >= 0) + XmuSnprintf(buf, sizeof(buf), "%d", adj->adj_scrnum); + else + *buf = 0; + node->data->adjacency.scrnum = + XtVaCreateManagedWidget("scrnum", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, NULL, 0); + above = XtVaCreateManagedWidget("above", toggleWidgetClass, box, + XtNstate, adj->adj_where == CONF_ADJ_ABOVE ? + True : False, NULL, 0); + XtAddCallback(above, XtNcallback, AdjacencyToggleCallback, (XtPointer)node); + left = XtVaCreateManagedWidget("leftOf", toggleWidgetClass, box, + XtNradioGroup, above, + XtNstate, adj->adj_where == CONF_ADJ_LEFTOF ? + True : False, NULL, 0); + XtAddCallback(left, XtNcallback, AdjacencyToggleCallback, (XtPointer)node); + + node->data->adjacency.button = + XtVaCreateManagedWidget("screen", menuButtonWidgetClass, box, + XtNmenuName, "screenMenu", NULL, 0); + + right = XtVaCreateManagedWidget("rightOf", toggleWidgetClass, box, + XtNradioGroup, left, + XtNstate, adj->adj_where == CONF_ADJ_RIGHTOF ? + True : False, NULL, 0); + XtAddCallback(right, XtNcallback, AdjacencyToggleCallback, (XtPointer)node); + below = XtVaCreateManagedWidget("below", toggleWidgetClass, box, + XtNradioGroup, right, + XtNstate, adj->adj_where == CONF_ADJ_BELOW ? + True : False, NULL, 0); + XtAddCallback(below, XtNcallback, AdjacencyToggleCallback, (XtPointer)node); + relative = XtVaCreateManagedWidget("relative", toggleWidgetClass, box, + XtNradioGroup, below, + XtNstate, adj->adj_where == CONF_ADJ_RELATIVE ? + True : False, NULL, 0); + XtAddCallback(relative, XtNcallback, AdjacencyToggleCallback, (XtPointer)node); + absolute = XtVaCreateManagedWidget("absolute", toggleWidgetClass, box, + XtNradioGroup, relative, + XtNstate, adj->adj_where == CONF_ADJ_ABSOLUTE ? + True : False, NULL, 0); + XtAddCallback(absolute, XtNcallback, AdjacencyToggleCallback, (XtPointer)node); + + XtCreateManagedWidget("adjxL", labelWidgetClass, box, NULL, 0); + XmuSnprintf(buf, sizeof(buf), "%d", adj->adj_x); + node->data->adjacency.adjx = + XtVaCreateManagedWidget("adjx", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, NULL, 0); + + XtCreateManagedWidget("adjyL", labelWidgetClass, box, NULL, 0); + XmuSnprintf(buf, sizeof(buf), "%d", adj->adj_y); + node->data->adjacency.adjy = + XtVaCreateManagedWidget("adjy", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, + XtNstring, buf, NULL, 0); + + XtVaGetValues(node->data->adjacency.button, XtNwidth, &width, + XtNheight, &height, NULL, 0); + if (adj->adj_where > CONF_ADJ_ABSOLUTE && + adj->adj_where <= CONF_ADJ_RELATIVE) + XtVaSetValues(node->data->adjacency.button, XtNlabel, + adj->adj_refscreen, XtNwidth, width, + XtNheight, height, NULL, 0); + else + XtVaSetValues(node->data->adjacency.button, XtNlabel, "", + XtNwidth, width, XtNheight, height, NULL, 0); + } + else + XtVaCreateManagedWidget("new", menuButtonWidgetClass, box, + XtNmenuName, "screenMenu", NULL, 0); + + if (XtIsRealized(node->treeParent)) + XtRealizeWidget(box); + XtManageChild(box); +} + +static void +AdjacencyDestroy(TreeNode *node) +{ + if (node->data->adjacency.adjacency) + xf86removeAdjacency(node->parent->parent->data->layout.layout, + node->data->adjacency.adjacency); +} + +/*ARGSUSED*/ +static void +NewAdjacencyCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + TreeNode *parent, *node = (TreeNode*)user_data; + XF86ConfAdjacencyPtr adj; + char *ident = XtName(w); + + parent = node->parent; + DeleteNode(node); + adj = (XF86ConfAdjacencyPtr)XtCalloc(1, sizeof(XF86ConfAdjacencyRec)); + adj->adj_screen = xf86findScreen(ident, XF86Config->conf_screen_lst); + if (adj->adj_screen) + adj->adj_screen_str = XtNewString(adj->adj_screen->scrn_identifier); + parent->parent->data->layout.layout->lay_adjacency_lst = + xf86addAdjacency(parent->parent->data->layout.layout->lay_adjacency_lst, + adj); + + CreateAdjacency(parent, adj); + RelayoutTree(); +} + +/*ARGUSED*/ +static void +AdjacencyMenuCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + TreeNode *node = (TreeNode*)user_data; + XF86ConfAdjacencyPtr adj = node->data->adjacency.adjacency; + + XtFree(adj->adj_refscreen); + adj->adj_refscreen = XtNewString(XtName(w)); + XtVaSetValues(node->data->adjacency.button, XtNlabel, XtName(w), NULL, 0); +} + +static void +AdjacencyToggleCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + TreeNode *node = (TreeNode*)user_data; + XF86ConfAdjacencyPtr adj = node->data->adjacency.adjacency; + char *x, *y; + + if ((Bool)(long)call_data == False) + return; + + XtVaGetValues(node->data->adjacency.adjx, XtNstring, &x, NULL, 0); + XtVaGetValues(node->data->adjacency.adjy, XtNstring, &y, NULL, 0); + + adj->adj_x = strtol(x, NULL, 0); + adj->adj_y = strtol(y, NULL, 0); + + if (strcmp(XtName(w), "absolute") == 0) { + XtVaSetValues(node->data->adjacency.button, XtNlabel, "", NULL, 0); + adj->adj_where = CONF_ADJ_ABSOLUTE; + return; + } + if (strcmp(XtName(w), "relative") == 0) + adj->adj_where = CONF_ADJ_RELATIVE; + else if (strcmp(XtName(w), "leftOf") == 0) + adj->adj_where = CONF_ADJ_LEFTOF; + else if (strcmp(XtName(w), "rightOf") == 0) + adj->adj_where = CONF_ADJ_RIGHTOF; + else if (strcmp(XtName(w), "above") == 0) + adj->adj_where = CONF_ADJ_ABOVE; + else if (strcmp(XtName(w), "below") == 0) + adj->adj_where = CONF_ADJ_BELOW; +} + +/* Inputref */ +static void +CreateInputref(TreeNode *parent, XF86ConfInputrefPtr input) +{ + TreeNode *prev, *node; + TreeData *data; + + if ((prev = parent->child) != NULL) + while (prev->next) + prev = prev->next; + + while (input) { + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->inputref.inputref = input; + node = NewNode(parent, NULL, NULL, parent->node, data); + node->destroy = InputrefDestroy; + CreateInputrefField(node, False); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + input = (XF86ConfInputrefPtr)(input->list.next); + } + + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + node = NewNode(parent, NULL, NULL, parent->node, data); + CreateInputrefField(node, True); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; +} + +static void +CreateInputrefField(TreeNode *node, Bool addnew) +{ + Widget box, command; + + box = XtVaCreateWidget("inputref", formWidgetClass, tree, + XtNtreeParent, node->treeParent, NULL, 0); + node->node = box; + + if (!addnew) { + XF86OptionPtr *options; + XF86ConfInputrefPtr inp = node->data->inputref.inputref; + + command = XtCreateManagedWidget("remove", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, DestroyCallback, (XtPointer)node); + options = &(inp->iref_option_lst); + command = XtCreateManagedWidget("options", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, OptionsCallback, (XtPointer)options); + XtVaCreateManagedWidget("label", labelWidgetClass, box, + XtNlabel, inp->iref_inputdev_str, NULL, 0); + } + else { + Widget sme; + XF86ConfInputPtr ptr = XF86Config->conf_input_lst; + + XtVaCreateManagedWidget("new", menuButtonWidgetClass, box, + XtNmenuName, "inputMenu", NULL, 0); + node->data->inputref.menu = + XtVaCreatePopupShell("inputMenu", simpleMenuWidgetClass, box, + XtNleftMargin, 1, XtNrightMargin, 1, + XtNtopMargin, 1, XtNbottomMargin, 1, + NULL, 0); + + while (ptr) { + sme = XtCreateManagedWidget(ptr->inp_identifier, smeBSBObjectClass, + node->data->inputref.menu, NULL, 0); + XtAddCallback(sme, XtNcallback, NewInputrefCallback, + (XtPointer)node); + ptr = (XF86ConfInputPtr)(ptr->list.next); + } + } + if (XtIsRealized(node->treeParent)) + XtRealizeWidget(box); + XtManageChild(box); +} + +/*ARGSUSED*/ +static void +NewInputrefCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + TreeNode *parent, *node = (TreeNode*)user_data; + XF86ConfInputrefPtr input; + char *ident = XtName(w); + + parent = node->parent; + DeleteNode(node); + input = (XF86ConfInputrefPtr)XtCalloc(1, sizeof(XF86ConfInputrefRec)); + input->iref_inputdev_str = XtNewString(ident); + parent->parent->data->layout.layout->lay_input_lst = + xf86addInputref(parent->parent->data->layout.layout->lay_input_lst, input); + + CreateInputref(parent, input); + RelayoutTree(); +} + +/*ARGUSED*/ +static void +InputrefDestroy(TreeNode *node) +{ + if (node->data->inputref.inputref) + xf86removeInputRef(node->parent->parent->data->layout.layout, node->data->inputref.inputref->iref_inputdev); +} + +/* Vendor */ +static void +CreateVendor(TreeNode *parent, XF86ConfVendorPtr vendor) +{ + TreeNode *prev, *node; + TreeData *data; + + if ((prev = parent->child) != NULL) + while (prev->next) + prev = prev->next; + + while (vendor) { + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->vendor.vendor = vendor; + node = NewNode(parent, NULL, NULL, parent->node, data); + node->destroy = VendorDestroy; + CreateVendorField(node, False); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + vendor = (XF86ConfVendorPtr)(vendor->list.next); + } + + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + node = NewNode(parent, NULL, NULL, parent->node, data); + CreateVendorField(node, True); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; +} + +static void +CreateVendorField(TreeNode *node, Bool addnew) +{ + Widget box, command; + + box = XtVaCreateWidget("vendor", formWidgetClass, tree, + XtNtreeParent, node->treeParent, NULL, 0); + node->node = box; + + if (!addnew) { + TreeNode *sub; + XF86OptionPtr *options; + XF86ConfVendorPtr vendor = node->data->vendor.vendor; + + command = XtCreateManagedWidget("remove", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, DestroyCallback, (XtPointer)node); + options = &(vendor->vnd_option_lst); + command = XtCreateManagedWidget("options", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, OptionsCallback, (XtPointer)options); + XtVaCreateManagedWidget("label", labelWidgetClass, box, + XtNlabel, vendor->vnd_identifier, NULL, 0); + + command = XtVaCreateManagedWidget("VendSub", toggleWidgetClass, tree, + XtNstate, True, + XtNtreeParent, box, + NULL, 0); + sub = NewNode(node, command, command, box, NULL); + node->child = sub; + CreateVendorSub(sub, vendor->vnd_sub_lst); + } + else { + command = XtCreateManagedWidget("new", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, NewVendorCallback, (XtPointer)node); + node->data->vendor.text = + XtVaCreateManagedWidget("value", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, NULL, 0); + } + if (XtIsRealized(node->treeParent)) + XtRealizeWidget(box); + XtManageChild(box); +} + +static void +VendorDestroy(TreeNode *node) +{ + if (node->data->vendor.vendor) + xf86removeVendor(XF86Config, node->data->vendor.vendor); +} + +static void +NewVendorCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + TreeNode *parent, *node = (TreeNode*)user_data; + XF86ConfVendorPtr vnd; + Arg args[1]; + char *label; + + XtSetArg(args[0], XtNstring, &label); + XtGetValues(node->data->vendor.text, args, 1); + if (*label == '\0') + return; + + parent = node->parent; + DeleteNode(node); + vnd = (XF86ConfVendorPtr)XtCalloc(1, sizeof(XF86ConfVendorRec)); + vnd->vnd_identifier = XtNewString(label); + XF86Config->conf_vendor_lst = xf86addVendor(XF86Config->conf_vendor_lst, vnd); + + CreateVendor(parent, vnd); + RelayoutTree(); +} + +/* VendorSub */ +static void +CreateVendorSub(TreeNode *parent, XF86ConfVendSubPtr vendor) +{ + TreeNode *prev, *node; + TreeData *data; + + if ((prev = parent->child) != NULL) + while (prev->next) + prev = prev->next; + + while (vendor) { + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->vendsub.vendsub = vendor; + node = NewNode(parent, NULL, NULL, parent->node, data); + node->destroy = VendorSubDestroy; + node->update = VendorSubUpdate; + CreateVendorSubField(node, False); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + vendor = (XF86ConfVendSubPtr)(vendor->list.next); + } + + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + node = NewNode(parent, NULL, NULL, parent->node, data); + CreateVendorSubField(node, True); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; +} + +static void +CreateVendorSubField(TreeNode *node, Bool addnew) +{ + Widget box, command; + + box = XtVaCreateWidget("vendorSub", formWidgetClass, tree, + XtNtreeParent, node->treeParent, NULL, 0); + node->node = box; + + if (!addnew) { + XF86OptionPtr *options; + XF86ConfVendSubPtr vendor = node->data->vendsub.vendsub; + + command = XtCreateManagedWidget("remove", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, DestroyCallback, (XtPointer)node); + options = &(vendor->vs_option_lst); + command = XtCreateManagedWidget("options", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, OptionsCallback, (XtPointer)options); + XtVaCreateManagedWidget("label", labelWidgetClass, box, + XtNlabel, vendor->vs_identifier, NULL, 0); + + XtCreateManagedWidget("nameL", labelWidgetClass, box, NULL, 0); + node->data->vendsub.text = + XtVaCreateManagedWidget("name", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, XtNstring, + vendor->vs_name ? vendor->vs_name : "", + NULL, 0); + } + else { + command = XtCreateManagedWidget("new", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, NewVendorSubCallback, (XtPointer)node); + node->data->vendsub.text = + XtVaCreateManagedWidget("value", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, NULL, 0); + } + if (XtIsRealized(node->treeParent)) + XtRealizeWidget(box); + XtManageChild(box); +} + +static void +VendorSubDestroy(TreeNode *node) +{ + if (node->data->vendsub.vendsub) + xf86removeVendorSub(node->parent->parent->data->vendor.vendor, + node->data->vendsub.vendsub); +} + +static void +VendorSubUpdate(TreeNode *node) +{ + char *str; + + XtVaGetValues(node->data->vendsub.text, XtNstring, &str, NULL, 0); + XtFree(node->data->vendsub.vendsub->vs_name); + if (*str) + node->data->vendsub.vendsub->vs_name = XtNewString(str); + else + node->data->vendsub.vendsub->vs_name = NULL; +} + +static void +NewVendorSubCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + TreeNode *parent, *node = (TreeNode*)user_data; + XF86ConfVendSubPtr vnd; + Arg args[1]; + char *label; + + XtSetArg(args[0], XtNstring, &label); + XtGetValues(node->data->vendsub.text, args, 1); + if (*label == '\0') + return; + + parent = node->parent; + DeleteNode(node); + vnd = (XF86ConfVendSubPtr)XtCalloc(1, sizeof(XF86ConfVendSubRec)); + vnd->vs_identifier = XtNewString(label); + parent->parent->data->vendor.vendor->vnd_sub_lst = + xf86addVendorSub(parent->parent->data->vendor.vendor->vnd_sub_lst, vnd); + + CreateVendorSub(parent, vnd); + RelayoutTree(); +} + +/* DRI */ +static void +CreateDRI(TreeNode *parent, XF86ConfDRIPtr dri) +{ + TreeNode *node; + TreeData *data; + + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->dri.dri = dri; + node = NewNode(parent, NULL, NULL, parent->node, data); + parent->child = node; + node->update = DRIUpdate; + CreateDRIField(node); +} + +static void +CreateDRIField(TreeNode *node) +{ + Widget box, toggle; + XF86ConfDRIPtr dri = node->data->dri.dri; + TreeNode *buffers; + char buf[32]; + + box = XtVaCreateWidget("dri", formWidgetClass, tree, + XtNtreeParent, node->treeParent, NULL, 0); + node->node = box; + XtCreateManagedWidget("nameL", labelWidgetClass, box, NULL, 0); + node->data->dri.name = + XtVaCreateManagedWidget("name", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, XtNstring, + dri->dri_group_name ? dri->dri_group_name : "", + NULL, 0); + + XtCreateManagedWidget("groupL", labelWidgetClass, box, NULL, 0); + if (dri->dri_group >= 0) + XmuSnprintf(buf, sizeof(buf), "%d", dri->dri_group); + else + *buf = '\0'; + node->data->dri.group = + XtVaCreateManagedWidget("group", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, XtNstring, buf, + NULL, 0); + + XtCreateManagedWidget("modeL", labelWidgetClass, box, NULL, 0); + if (dri->dri_mode > 0) + XmuSnprintf(buf, sizeof(buf), "0%o", dri->dri_mode); + else + *buf = '\0'; + node->data->dri.mode = + XtVaCreateManagedWidget("mode", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, XtNstring, buf, + NULL, 0); + + toggle = XtVaCreateManagedWidget("Buffers", toggleWidgetClass, tree, + XtNstate, True, XtNtreeParent, box, + NULL, 0); + buffers = NewNode(node, toggle, toggle, box, NULL); + node->child = buffers; + CreateBuffers(buffers, dri->dri_buffers_lst); + + if (XtIsRealized(node->treeParent)) + XtRealizeWidget(box); + XtManageChild(box); +} + +static void +DRIUpdate(TreeNode *node) +{ + char *str; + + /* name */ + XtVaGetValues(node->data->dri.name, XtNstring, &str, NULL, 0); + XtFree(node->data->dri.dri->dri_group_name); + if (*str) + node->data->dri.dri->dri_group_name = XtNewString(str); + else + node->data->dri.dri->dri_group_name = NULL; + + /* group */ + XtVaGetValues(node->data->dri.group, XtNstring, &str, NULL, 0); + if (*str) + node->data->dri.dri->dri_group = strtoul(str, NULL, 0); + else + node->data->dri.dri->dri_group = -1; + + /* mode */ + XtVaGetValues(node->data->dri.mode, XtNstring, &str, NULL, 0); + node->data->dri.dri->dri_mode = strtoul(str, NULL, 0); +} + +/* Buffers */ +static void +CreateBuffers(TreeNode *parent, XF86ConfBuffersPtr buf) +{ + TreeNode *node, *prev; + TreeData *data; + + if ((prev = parent->child) != NULL) + while (prev->next) + prev = prev->next; + + while (buf) { + data = (TreeData*)XtCalloc(1, sizeof(TreeData)); + data->buffers.buffers = buf; + node = NewNode(parent, NULL, NULL, parent->node, data); + node->destroy = BuffersDestroy; + node->update = BuffersUpdate; + CreateBuffersField(node, False); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; + prev = node; + + buf = (XF86ConfBuffersPtr)(buf->list.next); + } + node = NewNode(parent, NULL, NULL, parent->node, NULL); + CreateBuffersField(node, True); + if (parent->child == NULL) + parent->child = node; + else + prev->next = node; +} + +static void +CreateBuffersField(TreeNode *node, Bool addnew) +{ + Widget box, command; + + box = XtVaCreateWidget("buffers", formWidgetClass, tree, + XtNtreeParent, node->treeParent, NULL, 0); + node->node = box; + + if (!addnew) { + char str[32]; + XF86ConfBuffersPtr buf = node->data->buffers.buffers; + + command = XtCreateManagedWidget("remove", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, DestroyCallback, (XtPointer)node); + + XtCreateManagedWidget("countL", labelWidgetClass, box, NULL, 0); + XmuSnprintf(str, sizeof(str), "%d", buf->buf_count); + node->data->buffers.count = + XtVaCreateManagedWidget("count", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, XtNstring, str, + NULL, 0); + + XtCreateManagedWidget("sizeL", labelWidgetClass, box, NULL, 0); + XmuSnprintf(str, sizeof(str), "%d", buf->buf_size); + node->data->buffers.size = + XtVaCreateManagedWidget("size", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, XtNstring, str, + NULL, 0); + + XtCreateManagedWidget("flagsL", labelWidgetClass, box, NULL, 0); + node->data->buffers.flags = + XtVaCreateManagedWidget("flags", asciiTextWidgetClass, box, + XtNeditType, XawtextEdit, XtNstring, + buf->buf_flags ? buf->buf_flags : "", + NULL, 0); + } + else { + command = XtCreateManagedWidget("new", commandWidgetClass, box, + NULL, 0); + XtAddCallback(command, XtNcallback, NewBuffersCallback, (XtPointer)node); + } + if (XtIsRealized(node->treeParent)) + XtRealizeWidget(box); + XtManageChild(box); +} + +/*ARGUSED*/ +static void +BuffersDestroy(TreeNode *node) +{ + if (node->data->buffers.buffers) + xf86removeBuffers(XF86Config->conf_dri, node->data->buffers.buffers); +} + +/*ARGSUSED*/ +static void +NewBuffersCallback(Widget unused, XtPointer user_data, XtPointer call_data) +{ + TreeNode *parent, *node = (TreeNode*)user_data; + XF86ConfBuffersPtr buf; + + parent = node->parent; + DeleteNode(node); + buf = (XF86ConfBuffersPtr)XtCalloc(1, sizeof(XF86ConfBuffersRec)); + XF86Config->conf_dri->dri_buffers_lst = + xf86addBuffers(XF86Config->conf_dri->dri_buffers_lst, buf); + + CreateBuffers(parent, buf); + RelayoutTree(); +} + +static void +BuffersUpdate(TreeNode *node) +{ + char *str; + + /* count */ + XtVaGetValues(node->data->buffers.count, XtNstring, &str, NULL, 0); + node->data->buffers.buffers->buf_count = strtoul(str, NULL, 0); + + /* size */ + XtVaGetValues(node->data->buffers.size, XtNstring, &str, NULL, 0); + node->data->buffers.buffers->buf_size = strtoul(str, NULL, 0); + + /* flags */ + XtVaGetValues(node->data->buffers.flags, XtNstring, &str, NULL, 0); + if (*str) + node->data->buffers.buffers->buf_flags = XtNewString(str); + else + node->data->buffers.buffers->buf_flags = NULL; +} + +static TreeNode * +NewNode(TreeNode *parent, Widget node, Widget toggle, Widget treeParent, + TreeData *data) +{ + TreeNode *tree = (TreeNode*)XtCalloc(1, sizeof(TreeNode)); + + tree->parent = parent; + tree->node = node; + if ((tree->toggle = toggle) != NULL) + XtAddCallback(toggle, XtNcallback, ToggleCallback, (XtPointer)tree); + tree->treeParent = treeParent; + tree->data = data; + + return (tree); +} + +static void +DeleteNode(TreeNode *node) +{ + TreeNode *ptr = node->child; + + while (ptr != NULL) { + TreeNode *next = ptr->next; + + DeleteNode(ptr); + ptr = next; + } + + if (node->parent && node->parent->child == node) + node->parent->child = node->next; + else if (node->parent) { + for (ptr = node->parent->child; ptr && ptr->next != node; + ptr = ptr->next) + ; + if (ptr) + ptr->next = node->next; + } + + if (node->destroy) + (node->destroy)(node); + if (node->data) + XtFree((XtPointer)node->data); + + /* sets treeParent to NULL so that RelayoutTree works correctly, + * as the tree will properly calculate it's new size. + */ + XtVaSetValues(node->node, XtNtreeParent, NULL, NULL, 0); + + XtDestroyWidget(node->node); + XtFree((XtPointer)node); +} + +/*ARGUSED*/ +static void +DestroyCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + TreeNode *node = (TreeNode*)user_data; + + DeleteNode(node); + RelayoutTree(); +} + +static void +ToggleNodeRecursive(TreeNode *node) +{ + while (node) { + if (!XtIsRealized(node->node)) + XtRealizeWidget(node->node); + XtVaSetValues(node->node, XtNtreeParent, node->treeParent, NULL, 0); + XtManageChild(node->node); + + if (node->child && !node->toggle) + ToggleNodeRecursive(node->child); + + node = node->next; + } +} + +static void +ToggleNode(TreeNode *node, Bool toggle) +{ + while (node) { + if (toggle) { + if (!XtIsRealized(node->node)) + XtRealizeWidget(node->node); + XtVaSetValues(node->node, XtNtreeParent, node->treeParent, NULL, 0); + XtManageChild(node->node); + + if (node->child && !node->toggle) + ToggleNodeRecursive(node->child); + } + else { + if (node->child) + ToggleNode(node->child, False); + XtVaSetValues(node->node, XtNtreeParent, NULL, NULL, 0); + XtUnmanageChild(node->node); + if (node->toggle) + XtVaSetValues(node->toggle, XtNstate, False, NULL, 0); + } + node = node->next; + } +} + +/* + * XXX This callback can show side effects in the way it is called. If + * the structure holding the XF86OptionPtr is reallocated, a bogus pointer + * will be passed to this callback. + */ +static void +OptionsCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + XF86OptionPtr *options = (XF86OptionPtr*)user_data; + +#ifdef USE_MODULES + OptionsPopup(options, NULL, NULL); +#else + OptionsPopup(options); +#endif +} + +static void +RelayoutTree(void) +{ + Arg args[4]; + Dimension sliderWidth, sliderHeight, canvasWidth, canvasHeight; + + XtSetArg(args[0], XtNwidth, &sliderWidth); + XtSetArg(args[1], XtNheight, &sliderHeight); + XtGetValues(shell, args, 2); + + XtSetArg(args[2], XtNwidth, &canvasWidth); + XtSetArg(args[3], XtNheight, &canvasHeight); + XtGetValues(tree, args + 2, 2); + + XtSetArg(args[0], XtNsliderWidth, sliderWidth); + XtSetArg(args[1], XtNsliderHeight, sliderHeight); + XtSetArg(args[2], XtNcanvasWidth, canvasWidth); + XtSetArg(args[3], XtNcanvasHeight, canvasHeight); + XtSetValues(panner, args, 4); +} + +static void +ToggleCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + TreeNode *nodeParent = (TreeNode*)user_data; + + if (nodeParent->child) { + if (XtIsRealized(tree)) + XtUnmapWidget(tree); + ToggleNode(nodeParent->child, (Bool)(long)call_data); + RelayoutTree(); + if (XtIsRealized(tree)) + XtMapWidget(tree); + } +} + +/*ARGSUSED*/ +static void +PannerCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + Arg args[2]; + XawPannerReport *rep = (XawPannerReport *)call_data; + + XtSetArg (args[0], XtNx, -rep->slider_x); + XtSetArg (args[1], XtNy, -rep->slider_y); + XtSetValues(tree, args, 2); +} + +/*ARGSUSED*/ +static void +PortholeCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + XawPannerReport *rep = (XawPannerReport*)call_data; + Arg args[6]; + Cardinal n = 2; + + XtSetArg (args[0], XtNsliderX, rep->slider_x); + XtSetArg (args[1], XtNsliderY, rep->slider_y); + if (rep->changed != (XawPRSliderX | XawPRSliderY)) { + XtSetArg (args[2], XtNsliderWidth, rep->slider_width); + XtSetArg (args[3], XtNsliderHeight, rep->slider_height); + XtSetArg (args[4], XtNcanvasWidth, rep->canvas_width); + XtSetArg (args[5], XtNcanvasHeight, rep->canvas_height); + n = 6; + } + XtSetValues(panner, args, n); +} + +static void +DestroyTree(TreeNode *node) +{ + while (node) { + TreeNode *next = node->next; + if (node->child) + DestroyTree(node->child); + + if (node->data) + XtFree((XtPointer)node->data); + XtFree((XtPointer)node); + + node = next; + } +} + +static void +UpdateConfig(TreeNode *node) +{ + while (node) { + if (node->child) + UpdateConfig(node->child); + if (node->update) + (node->update)(node); + node = node->next; + } +} + +static Bool +ExpertInitialize(void) +{ + Widget paned, vpane, close, config, files, modules, flags, video, modes, + monitor, device, screen, input, layout, vendor, dri; + Arg args[4]; + Dimension width, height, canvasWidth, canvasHeight; + TreeNode *node; + + if (expert != NULL) + return (False); + + shell = XtCreatePopupShell("Expert", transientShellWidgetClass, + toplevel, NULL, 0); + paned = XtVaCreateManagedWidget("paned", panedWidgetClass, shell, + XtNorientation, XtorientHorizontal, NULL, 0); + vpane = XtCreateManagedWidget("vpane", panedWidgetClass, paned, NULL, 0); + panner = XtCreateManagedWidget ("panner", pannerWidgetClass, vpane, NULL, 0); + close = XtCreateManagedWidget("close", commandWidgetClass, vpane, NULL, 0); + XtAddCallback(close, XtNcallback, PopdownCallback, NULL); + + expert = XtCreateManagedWidget("expert", portholeWidgetClass, paned, NULL, 0); + XtAddCallback(expert, XtNreportCallback, PortholeCallback, NULL); + XtAddCallback(panner, XtNreportCallback, PannerCallback, NULL); + tree = XtCreateManagedWidget("tree", treeWidgetClass, expert, NULL, 0); + + config = XtVaCreateManagedWidget("XF86Config", toggleWidgetClass, tree, + XtNstate, True, NULL, 0); + mainNode = NewNode(NULL, config, config, NULL, NULL); + + files = XtVaCreateManagedWidget("Files", toggleWidgetClass, tree, + XtNtreeParent, config, NULL, 0); + node = NewNode(mainNode, files, files, config, NULL); + mainNode->child = node; + CreateFiles(node); + + modules = XtVaCreateManagedWidget("Module", toggleWidgetClass, tree, + XtNtreeParent, config, NULL, 0); + node->next = NewNode(mainNode, modules, modules, config, NULL); + node = node->next; + CreateModule(node, XF86Config->conf_modules ? + XF86Config->conf_modules->mod_load_lst : NULL); + + flags = XtVaCreateManagedWidget("ServerFlags", commandWidgetClass, tree, + XtNtreeParent, config, NULL, 0); + node->next = NewNode(mainNode, flags, NULL, config, NULL); + node = node->next; + if (XF86Config->conf_flags == NULL) + XF86Config->conf_flags = (XF86ConfFlagsPtr) + XtCalloc(1, sizeof(XF86ConfFlagsRec)); + XtAddCallback(flags, XtNcallback, OptionsCallback, + (XtPointer)&(XF86Config->conf_flags->flg_option_lst)); + + video = XtVaCreateManagedWidget("VideoAdaptor", toggleWidgetClass, tree, + XtNtreeParent, config, NULL, 0); + node->next = NewNode(mainNode, video, video, config, NULL); + node = node->next; + CreateVideoAdaptor(node, XF86Config->conf_videoadaptor_lst); + + modes = XtVaCreateManagedWidget("Mode", toggleWidgetClass, tree, + XtNtreeParent, config, NULL, 0); + node->next = NewNode(mainNode, modes, modes, config, NULL); + node = node->next; + CreateModes(node, XF86Config->conf_modes_lst); + + monitor = XtVaCreateManagedWidget("Monitor", toggleWidgetClass, tree, + XtNtreeParent, config, NULL, 0); + node->next = NewNode(mainNode, monitor, monitor, config, NULL); + node = node->next; + CreateMonitor(monitorTree = node, XF86Config->conf_monitor_lst); + + device = XtVaCreateManagedWidget("Device", toggleWidgetClass, tree, + XtNtreeParent, config, NULL, 0); + node->next = NewNode(mainNode, device, device, config, NULL); + node = node->next; + CreateDevice(node, XF86Config->conf_device_lst); + + screen = XtVaCreateManagedWidget("Screen", toggleWidgetClass, tree, + XtNtreeParent, config, NULL, 0); + node->next = NewNode(mainNode, screen, screen, config, NULL); + node = node->next; + CreateScreen(screenTree = node, XF86Config->conf_screen_lst); + + input = XtVaCreateManagedWidget("Input", toggleWidgetClass, tree, + XtNtreeParent, config, NULL, 0); + node->next = NewNode(mainNode, input, input, config, NULL); + node = node->next; + CreateInput(node, XF86Config->conf_input_lst); + + layout = XtVaCreateManagedWidget("Layout", toggleWidgetClass, tree, + XtNtreeParent, config, NULL, 0); + node->next = NewNode(mainNode, layout, layout, config, NULL); + node = node->next; + CreateLayout(layoutTree = node, XF86Config->conf_layout_lst); + + vendor = XtVaCreateManagedWidget("Vendor", toggleWidgetClass, tree, + XtNtreeParent, config, NULL, 0); + node->next = NewNode(mainNode, vendor, vendor, config, NULL); + node = node->next; + CreateVendor(node, XF86Config->conf_vendor_lst); + + dri = XtVaCreateManagedWidget("DRI", toggleWidgetClass, tree, + XtNtreeParent, config, NULL, 0); + node->next = NewNode(mainNode, dri, dri, config, NULL); + node = node->next; + if (XF86Config->conf_dri == NULL) + XF86Config->conf_dri = (XF86ConfDRIPtr) + XtCalloc(1, sizeof(XF86ConfDRIRec)); + CreateDRI(node, XF86Config->conf_dri); + + XtRealizeWidget(shell); + + XtSetArg(args[0], XtNwidth, &width); + XtSetArg(args[1], XtNheight, &height); + XtGetValues(shell, args, 2); + XtSetArg(args[0], XtNwidth, width); + XtSetArg(args[1], XtNheight, height); + XtSetValues(expert, args, 2); + + XtSetArg(args[0], XtNsliderWidth, width); + XtSetArg(args[1], XtNsliderHeight, height); + XtSetArg(args[2], XtNwidth, &canvasWidth); + XtSetArg(args[3], XtNheight, &canvasHeight); + XtGetValues(tree, args + 2, 2); + XtSetArg(args[2], XtNcanvasWidth, canvasWidth); + XtSetArg(args[3], XtNcanvasHeight, canvasHeight); + XtSetValues(panner, args, 4); + + /* needs to do the apparently NOP code bellow to correctly layout the + * tree widget */ + + /* close all open entries */ + ToggleCallback(config, mainNode, (XtPointer)0); + /* open first level */ + ToggleCallback(config, mainNode, (XtPointer)1); + + XSetWMProtocols(DPY, XtWindow(shell), &wm_delete_window, 1); + + return (True); +} |