/* * 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 * * $XFree86: xc/programs/Xserver/hw/xfree86/xf86cfg/monitor-cfg.c,v 1.6 2001/02/21 23:37:03 paulo Exp $ */ #include "xf86config.h" #include "monitor-cfg.h" #include "screen.h" #include #include #include #include #include #include #include #include #include #include #include /* * Prototypes */ static Bool MonitorConfigCheck(void); static void MonitorHsyncCallback(Widget, XtPointer, XtPointer); static void MonitorVsyncCallback(Widget, XtPointer, XtPointer); static void MonitorSelectCardCallback(Widget, XtPointer, XtPointer); extern void DrawCables(void); /* * Initialization */ static char *hmodes[] = { "Standard VGA, 640x480 @ 60 Hz", "Super VGA, 800x600 @ 56 Hz", "1024x768 @ 87 Hz int. (no 800x600)", "1024x768 @ 87 Hz int., 800x600 @ 56 Hz", "800x600 @ 60 Hz, 640x480 @ 72 Hz", "1024x768 @ 60 Hz, 800x600 @ 72 Hz", "High Frequency SVGA, 1024x768 @ 70 Hz", "Monitor that can do 1280x1024 @ 60 Hz", "Monitor that can do 1280x1024 @ 74 Hz", "Monitor that can do 1280x1024 @ 76 Hz", "Monitor that can do 1280x1024 @ 85 Hz", "Monitor that can do 1600x1200 @ 85 Hz", "Monitor that can do 1920x1440 @ 85 Hz", "Monitor that can do 2048x1536 @ 85 Hz" }; static char *hmodes_trans[] = { "31.5", "31.5 - 35.1", "31.5, 35.5", "31.5, 35.15, 35.5", "31.5 - 37.9", "31.5 - 48.5", "31.5 - 57.0", "31.5 - 64.3", "31.5 - 79.0", "31.5 - 82.0", "31.5 - 92.0", "31.5 - 108.0", "31.5 - 128.5", "31.5 - 137.0" }; static char *vmodes [] = { "50 - 70", "50 - 90", "50 - 100", "40 - 150", }; extern Widget config; static Widget hsync, vsync, hlist, vlist, cmenu; static parser_range mon_hsync[CONF_MAX_HSYNC]; static parser_range mon_vrefresh[CONF_MAX_VREFRESH]; static int mon_n_hsync, mon_n_vrefresh; static XF86ConfDevicePtr oldcard, card; static XF86ConfMonitorPtr current_monitor; /* * Implementation */ XtPointer MonitorConfig(XtPointer conf) { XF86ConfMonitorPtr monitor = (XF86ConfMonitorPtr)conf; char monitor_name[48]; Arg args[1]; current_monitor = monitor; xf86info.cur_list = MONITOR; XtSetSensitive(back, xf86info.lists[MONITOR].cur_function > 0); XtSetSensitive(next, xf86info.lists[MONITOR].cur_function < xf86info.lists[MONITOR].num_functions - 1); (xf86info.lists[MONITOR].functions[xf86info.lists[MONITOR].cur_function]) (&xf86info); XawListUnhighlight(hlist); XawListUnhighlight(vlist); if (monitor != NULL) { XF86ConfScreenPtr screen = XF86Config->conf_screen_lst; char str[PARSER_RANGE_SIZE]; XtSetArg(args[0], XtNstring, monitor->mon_identifier); XtSetValues(ident_widget, args, 1); while (screen != NULL) { if (screen->scrn_monitor == monitor) break; screen = (XF86ConfScreenPtr)(screen->list.next); } if (screen != NULL) { oldcard = card = screen->scrn_device; XtSetArg(args[0], XtNlabel, card->dev_identifier); } else { oldcard = card = NULL; XtSetArg(args[0], XtNlabel, ""); } XtSetValues(cmenu, args, 1); mon_n_hsync = monitor->mon_n_hsync; memcpy(mon_hsync, monitor->mon_hsync, sizeof(parser_range) * mon_n_hsync); *str = '\0'; parser_range_to_string(str, mon_hsync, mon_n_hsync); XtSetArg(args[0], XtNstring, str); XtSetValues(hsync, args, 1); mon_n_vrefresh = monitor->mon_n_vrefresh; memcpy(mon_vrefresh, monitor->mon_vrefresh, sizeof(parser_range) * mon_n_vrefresh); *str = '\0'; parser_range_to_string(str, mon_vrefresh, mon_n_vrefresh); XtSetArg(args[0], XtNstring, str); XtSetValues(vsync, args, 1); } else { XF86ConfMonitorPtr monitor = XF86Config->conf_monitor_lst; int nmonitors = 0; oldcard = card = NULL; while (monitor != NULL) { ++nmonitors; monitor = (XF86ConfMonitorPtr)(monitor->list.next); } do { XmuSnprintf(monitor_name, sizeof(monitor_name), "Monitor%d", nmonitors); ++nmonitors; } while (xf86findMonitor(monitor_name, XF86Config->conf_monitor_lst)); XtSetArg(args[0], XtNstring, monitor_name); XtSetValues(ident_widget, args, 1); XtSetArg(args[0], XtNstring, ""); XtSetValues(hsync, args, 1); XtSetValues(vsync, args, 1); XtSetArg(args[0], XtNlabel, ""); XtSetValues(cmenu, args, 1); } if (ConfigLoop(MonitorConfigCheck) == True) { if (monitor == NULL) { monitor = (XF86ConfMonitorPtr) XtCalloc(1, sizeof(XF86ConfMonitorRec)); monitor->mon_identifier = XtNewString(ident_string); } memcpy(monitor->mon_hsync, mon_hsync, sizeof(parser_range) * (monitor->mon_n_hsync = mon_n_hsync)); memcpy(monitor->mon_vrefresh, mon_vrefresh, sizeof(parser_range) * (monitor->mon_n_vrefresh = mon_n_vrefresh)); if (strcasecmp(monitor->mon_identifier, ident_string)) xf86renameMonitor(XF86Config, monitor, ident_string); if (oldcard != card) { int i; for (i = 0; i < computer.num_devices; i++) if (computer.devices[i]->widget == config) break; if (computer.devices[i]->config == NULL) XF86Config->conf_monitor_lst = xf86addMonitor(XF86Config->conf_monitor_lst, monitor); computer.devices[i]->config = (XtPointer)monitor; ChangeScreen(monitor, monitor, card, oldcard); DrawCables(); } return (monitor); } return (NULL); } static Bool MonitorConfigCheck(void) { char *str; Arg args[1]; XF86ConfMonitorPtr monitor = XF86Config->conf_monitor_lst; if (ident_string == NULL || strlen(ident_string) == 0) return (False); bzero(mon_hsync, sizeof(parser_range) * CONF_MAX_HSYNC); bzero(mon_vrefresh, sizeof(parser_range) * CONF_MAX_VREFRESH); XtSetArg(args[0], XtNstring, &str); XtGetValues(hsync, args, 1); if ((mon_n_hsync = string_to_parser_range(str, mon_hsync, CONF_MAX_HSYNC)) <= 0) return (False); XtSetArg(args[0], XtNstring, &str); XtGetValues(vsync, args, 1); if ((mon_n_vrefresh = string_to_parser_range(str, mon_vrefresh, CONF_MAX_VREFRESH)) <= 0) return (False); while (monitor != NULL) { if (monitor != current_monitor && strcasecmp(ident_string, monitor->mon_identifier) == 0) return (False); monitor = (XF86ConfMonitorPtr)(monitor->list.next); } return (True); } int string_to_parser_range(char *str, parser_range *range, int nrange) { double val; int i = 0; if (str == NULL || *str == '\0' || range == NULL || nrange == 0) return (0); while (*str) { while (*str && isspace(*str)) ++str; if (!isdigit(*str)) { ++str; continue; } val = strtod(str, &str); while (*str && isspace(*str)) ++str; if (*str == ',' || *str == '\0') { if (*str) ++str; range[i].lo = range[i].hi = val; if (++i >= nrange || *str == '\0') break; continue; } else if (*str != '-') return (0); ++str; range[i].lo = val; while (*str && isspace(*str)) ++str; if ((range[i].hi = strtod(str, &str)) < range[i].lo) return (0); if (++i >= nrange) break; } return (i); } int parser_range_to_string(char *str, parser_range *range, int nrange) { int i, len; if (str == NULL || range == NULL || nrange <= 0) return (0); for (i = len = 0; i < nrange; i++) { if (i > 0) len += XmuSnprintf(str + len, PARSER_RANGE_SIZE - len, "%s", ", "); if (range[i].lo == range[i].hi) len += XmuSnprintf(str + len, PARSER_RANGE_SIZE - len, "%g", range[i].lo); else if (range[i].lo < range[i].hi) len += XmuSnprintf(str + len, PARSER_RANGE_SIZE - len, "%g - %g", range[i].lo, range[i].hi); else return (0); } return (i); } /*ARGSUSED*/ static void MonitorHsyncCallback(Widget w, XtPointer user_data, XtPointer call_data) { XawListReturnStruct *info = (XawListReturnStruct *)call_data; Arg args[1]; XtSetArg(args[0], XtNstring, hmodes_trans[info->list_index]); XtSetValues(hsync, args, 1); } /*ARGSUSED*/ static void MonitorVsyncCallback(Widget w, XtPointer user_data, XtPointer call_data) { XawListReturnStruct *info = (XawListReturnStruct *)call_data; Arg args[1]; XtSetArg(args[0], XtNstring, info->string); XtSetValues(vsync, args, 1); } /*ARGSUSED*/ static void MonitorSelectCardCallback(Widget w, XtPointer user_data, XtPointer call_data) { Arg args[1]; card = (XF86ConfDevicePtr)user_data; XtSetArg(args[0], XtNlabel, card != NULL ? card->dev_identifier : ""); XtSetValues(cmenu, args, 1); } void MonitorLayout(XF86SetupInfo *info) { static int first = 1, men; static Widget layout, menu; XF86ConfDevicePtr device = XF86Config->conf_device_lst; Widget sme; Arg args[1]; char *menuname; if (first) { Widget viewport; first = 0; layout = XtCreateWidget("monitorl", formWidgetClass, configp, NULL, 0); XtCreateManagedWidget("hlabel", labelWidgetClass, layout, NULL, 0); hsync = XtVaCreateManagedWidget("hsync", asciiTextWidgetClass, layout, XtNeditType, XawtextEdit, NULL, 0); viewport = XtCreateManagedWidget("hviewport", viewportWidgetClass, layout, NULL, 0); hlist = XtVaCreateManagedWidget("hlist", listWidgetClass, viewport, XtNlist, hmodes, XtNnumberStrings, sizeof(hmodes) / sizeof(hmodes[0]), NULL, 0); XtAddCallback(hlist, XtNcallback, MonitorHsyncCallback, NULL); XtCreateManagedWidget("vlabel", labelWidgetClass, layout, NULL, 0); vsync = XtVaCreateManagedWidget("vsync", asciiTextWidgetClass, layout, XtNeditType, XawtextEdit, NULL, 0); viewport = XtCreateManagedWidget("vviewport", viewportWidgetClass, layout, NULL, 0); vlist = XtVaCreateManagedWidget("vlist", listWidgetClass, viewport, XtNlist, vmodes, XtNnumberStrings, sizeof(vmodes) / sizeof(vmodes[0]), NULL, 0); XtAddCallback(vlist, XtNcallback, MonitorVsyncCallback, NULL); XtCreateManagedWidget("clabel", labelWidgetClass, layout, NULL, 0); cmenu = XtCreateManagedWidget("cmenu", menuButtonWidgetClass, layout, NULL, 0); XtRealizeWidget(layout); } if (menu != NULL) XtDestroyWidget(menu); /* * swaps names because XtDestroyWidget will only really destroy it * when the code returns to XtAppMainLoop */ menuname = men & 1 ? "mena" : "menb"; menu = XtCreatePopupShell(menuname, simpleMenuWidgetClass, cmenu, NULL, 0); XtSetArg(args[0], XtNmenuName, menuname); XtSetValues(cmenu, args, 1); ++men; sme = XtVaCreateManagedWidget("none", smeBSBObjectClass, menu, NULL, 0); XtAddCallback(sme, XtNcallback, MonitorSelectCardCallback, NULL); while (device != NULL) { XF86ConfScreenPtr screen = XF86Config->conf_screen_lst; Widget sme; Bool sensitive = True; while (screen != NULL) { if (screen->scrn_device == device) { sensitive = screen->scrn_monitor == NULL || screen->scrn_monitor == current_monitor; break; } screen = (XF86ConfScreenPtr)(screen->list.next); } sme = XtCreateManagedWidget(device->dev_identifier, smeBSBObjectClass, menu, NULL, 0); if (sensitive) XtAddCallback(sme, XtNcallback, MonitorSelectCardCallback, device); XtSetSensitive(sme, sensitive); device = (XF86ConfDevicePtr)(device->list.next); } XtRealizeWidget(menu); XtChangeManagedSet(¤t, 1, NULL, NULL, &layout, 1); current = layout; }