457 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			457 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
 | 
						|
 * 
 | 
						|
 * Permission is hereby granted, free of charge, to any person obtaining a
 | 
						|
 * copy of this software and associated documentation files (the "Software"),
 | 
						|
 * to deal in the Software without restriction, including without limitation
 | 
						|
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | 
						|
 * and/or sell copies of the Software, and to permit persons to whom the
 | 
						|
 * Software is furnished to do so, subject to the following conditions:
 | 
						|
 * 
 | 
						|
 * The above copyright notice and this permission notice shall be included in
 | 
						|
 * all copies or substantial portions of the Software.
 | 
						|
 *  
 | 
						|
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 | 
						|
 * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 | 
						|
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
 | 
						|
 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
						|
 * SOFTWARE.
 | 
						|
 * 
 | 
						|
 * Except as contained in this notice, the name of Conectiva Linux shall
 | 
						|
 * not be used in advertising or otherwise to promote the sale, use or other
 | 
						|
 * dealings in this Software without prior written authorization from
 | 
						|
 * Conectiva Linux.
 | 
						|
 *
 | 
						|
 * Author: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#include "xf86config.h"
 | 
						|
#include "monitor-cfg.h"
 | 
						|
#include "screen.h"
 | 
						|
#include <X11/extensions/xf86vmode.h>
 | 
						|
#include <X11/Xaw/Form.h>
 | 
						|
#include <X11/Xaw/Simple.h>
 | 
						|
 | 
						|
#include <ctype.h>
 | 
						|
#include <X11/Xaw/Label.h>
 | 
						|
#include <X11/Xaw/AsciiText.h>
 | 
						|
#include <X11/Xaw/List.h>
 | 
						|
#include <X11/Xaw/MenuButton.h>
 | 
						|
#include <X11/Xaw/Viewport.h>
 | 
						|
#include <X11/Xaw/SimpleMenu.h>
 | 
						|
#include <X11/Xaw/SmeBSB.h>
 | 
						|
 | 
						|
/*
 | 
						|
 * 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);
 | 
						|
	viewport = XtCreateManagedWidget("hviewport", viewportWidgetClass,
 | 
						|
					 layout, NULL, 0);
 | 
						|
	hlist = XtVaCreateManagedWidget("hlist", listWidgetClass, viewport,
 | 
						|
					XtNlist, hmodes,
 | 
						|
					XtNnumberStrings, sizeof(hmodes) /
 | 
						|
					sizeof(hmodes[0]), NULL);
 | 
						|
	XtAddCallback(hlist, XtNcallback, MonitorHsyncCallback, NULL);
 | 
						|
 | 
						|
	XtCreateManagedWidget("vlabel", labelWidgetClass, layout, NULL, 0);
 | 
						|
	vsync = XtVaCreateManagedWidget("vsync", asciiTextWidgetClass, layout,
 | 
						|
					XtNeditType, XawtextEdit,
 | 
						|
					NULL);
 | 
						|
	viewport = XtCreateManagedWidget("vviewport", viewportWidgetClass,
 | 
						|
					 layout, NULL, 0);
 | 
						|
	vlist = XtVaCreateManagedWidget("vlist", listWidgetClass, viewport,
 | 
						|
					XtNlist, vmodes,
 | 
						|
					XtNnumberStrings, sizeof(vmodes) /
 | 
						|
					sizeof(vmodes[0]), NULL);
 | 
						|
	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);
 | 
						|
    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;
 | 
						|
}
 |