|
|
|
|
File: [XFree86 CVS] / xc / programs / Xserver / hw / xfree86 / common / xf86Config.c
(download)
Revision: 3.296, Thu May 1 15:13:22 2008 UTC (5 years ago) by tsi Branch: MAIN CVS Tags: xf-4_8_0-bindist, xf-4_8_0, xf-4_8-branch, xf-4_7_99_31, xf-4_7_99_30, xf-4_7_99_29, xf-4_7_99_28, xf-4_7_99_27, xf-4_7_99_26, xf-4_7_99_25, xf-4_7_99_24, xf-4_7_99_23, xf-4_7_99_22, xf-4_7_99_21, xf-4_7_99_20, xf-4_7_99_19, xf-4_7_99_18, xf-4_7_99_17, HEAD Changes since 3.295: +1 -2 lines 43. Mitigate brokenness in /dev/console redirection on Solaris. Should this
redirection fail, redirect the server's stderr to the log to avoid screen
corruption due to the server's own console output. (Marc La France).
|
/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Config.c,v 3.295tsi Exp $ */
/*
* Loosely based on code bearing the following copyright:
*
* Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
*/
/*
* Copyright (c) 1992-2006 by The XFree86 Project, Inc.
* All rights reserved.
*
* 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:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution, and in the same place and form as other copyright,
* license and disclaimer information.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment: "This product
* includes software developed by The XFree86 Project, Inc
* (http://www.xfree86.org/) and its contributors", in the same
* place and form as other third-party acknowledgments. Alternately,
* this acknowledgment may appear in the software itself, in the
* same form and location as other such third-party acknowledgments.
*
* 4. Except as contained in this notice, the name of The XFree86
* Project, Inc shall not be used in advertising or otherwise to
* promote the sale, use or other dealings in this Software without
* prior written authorization from The XFree86 Project, Inc.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE XFREE86 PROJECT, INC OR ITS CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright 1997 by Metro Link, Inc.
*
* 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
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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 the copyright holder(s)
* and author(s) shall not be used in advertising or otherwise to promote
* the sale, use or other dealings in this Software without prior written
* authorization from the copyright holder(s) and author(s).
*/
/*
* Copyright © 2003, 2004, 2005 David H. Dawes.
* Copyright © 2003, 2004, 2005 X-Oz Technologies.
* All rights reserved.
*
* 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:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment: "This product
* includes software developed by X-Oz Technologies
* (http://www.x-oz.com/)." Alternately, this acknowledgment may
* appear in the software itself, if and wherever such third-party
* acknowledgments normally appear.
*
* 4. Except as contained in this notice, the name of X-Oz
* Technologies shall not be used in advertising or otherwise to
* promote the sale, use or other dealings in this Software without
* prior written authorization from X-Oz Technologies.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL X-OZ TECHNOLOGIES OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
*
* Authors:
* Dirk Hohndel <hohndel@XFree86.Org>
* David Dawes <dawes@XFree86.Org>
* Marc La France <tsi@XFree86.Org>
* Egbert Eich <eich@XFree86.Org>
* ... and others
*/
#include <sys/types.h>
#include <grp.h>
#ifdef __UNIXOS2__
#define I_NEED_OS2_H
#endif
#include "xf86.h"
#include "xf86Parser.h"
#include "xf86tokens.h"
#include "xf86Config.h"
#include "xf86Priv.h"
#include "xf86_OSlib.h"
#include "globals.h"
#ifdef XKB
#define XKB_IN_SERVER
#include <X11/extensions/XKBsrv.h>
#endif
#ifdef RENDER
#include "picture.h"
#endif
#if (defined(i386) || defined(__i386__)) && \
(defined(__FreeBSD__) || defined(__NetBSD__) || defined(linux) || \
(defined(SVR4) && !defined(sun)) || defined(__GNU__))
#define SUPPORT_PC98
#endif
/*
* These paths define the way the config file search is done. The escape
* sequences are documented in parser/scan.c.
*/
#ifndef ROOT_CONFIGPATH
#define ROOT_CONFIGPATH "%A," "%R," \
"/etc/X11/%R," "%P/etc/X11/%R," \
"%E," "%F," \
"/etc/X11/%F," "%P/etc/X11/%F," \
"%D/%X," \
"/etc/X11/%X-%M," "/etc/X11/%X," "/etc/%X," \
"%P/etc/X11/%X.%H," "%P/etc/X11/%X-%M," \
"%P/etc/X11/%X," \
"%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," \
"%P/lib/X11/%X"
#endif
#ifndef USER_CONFIGPATH
#define USER_CONFIGPATH "/etc/X11/%S," "%P/etc/X11/%S," \
"/etc/X11/%G," "%P/etc/X11/%G," \
"/etc/X11/%X-%M," "/etc/X11/%X," "/etc/%X," \
"%P/etc/X11/%X.%H," "%P/etc/X11/%X-%M," \
"%P/etc/X11/%X," \
"%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," \
"%P/lib/X11/%X"
#endif
#ifndef PROJECTROOT
#define PROJECTROOT "/usr/X11R6"
#endif
/* Forward declarations */
static MonPtr convertMonitor(MonPtr pMonitor,
const XF86ConfMonitorRec *confMonitor);
static IDevPtr convertInputDevice(IDevPtr input,
const XF86ConfInputRec *confInput);
static DispPtr convertDisplay(DispPtr pDisplay,
const XF86ConfDisplayRec *confDisplay);
static confModulesPtr convertModules(confModulesPtr modules,
const XF86ConfModuleRec* confModules);
static Bool addDefaultModes(MonPtr pMonitor);
static confDRIPtr configDRI(ConfigHandle handle, const XF86ConfDRIRec *driConf,
MessageType from);
static const confXvAdaptorRec *getNextActiveXvAdaptor(ConfigDataHandle prev);
static const confScreenRec *getNextActiveScreen(ConfigDataHandle prev);
static void
xf86ConfigError(const char *msg, ...)
{
va_list ap;
ErrorF("\nConfig Error:\n");
va_start(ap, msg);
VErrorF(msg, ap);
va_end(ap);
ErrorF("\n");
return;
}
static const XF86ConfigRec *
ConfigHandleToConfigRead(ConfigHandle handle)
{
/* For now, effectively ignore the pseudo handles. */
if (handle == DEFAULT_CONFIG ||
handle == CMDLINE_CONFIG || handle == BUILDTIME_CONFIG ||
handle == ACTIVE_CONFIG)
return xf86Info.config;
else
return handle;
}
#ifdef NOTYET
static XF86ConfigPtr
ConfigHandleToConfigWrite(ConfigHandle handle)
{
if (handle == DEFAULT_CONFIG)
return (XF86ConfigPtr)xf86Info.config;
else
return (XF86ConfigPtr)handle;
}
#endif
static void
xf86FreeStringArray(char **s, int n)
{
int i;
if (!s)
return;
for (i = 0; i < n; i++) {
xfree(s[i]);
s[i] = NULL;
}
xfree(s);
}
static char **
xf86DupStringArray(char **src, int n)
{
int i;
char **dst;
if (n < 1)
return NULL;
dst = xcalloc(n, sizeof(*dst));
if (!dst)
return NULL;
for (i = 0; i < n; i++) {
dst[i] = xstrdup(src[i]);
if (src[i] && !dst[i]) {
xf86FreeStringArray(dst, n);
return NULL;
}
}
return dst;
}
confLoadModulePtr
xf86ConfAllocLoadModule()
{
confLoadModulePtr pLoad;
pLoad = xcalloc(1, sizeof(*pLoad));
return pLoad;
}
void
xf86ConfFreeLoadModuleData(confLoadModulePtr pLoad)
{
if (!pLoad)
return;
if (pLoad->name) {
xfree(pLoad->name);
pLoad->name = NULL;
}
if (pLoad->options) {
xf86OptionListFree(pLoad->options);
pLoad->options = NULL;
}
}
confLoadModulePtr
xf86ConfDupLoadModule(const confLoadModuleRec *pLoad)
{
confLoadModulePtr l;
if (!pLoad)
return NULL;
l = xf86ConfAllocLoadModule();
if (!l)
return NULL;
l->name = xstrdup(pLoad->name);
if (pLoad->name && !l->name) {
xf86ConfFreeLoadModuleData(l);
xfree(l);
return NULL;
}
l->options = xf86OptionListDup(pLoad->options);
if (pLoad->options && !l->options) {
xf86ConfFreeLoadModuleData(l);
xfree(l);
return NULL;
}
return l;
}
static confLoadModulePtr
convertLoadModule(confLoadModulePtr pLoad, const XF86LoadRec *loadConf)
{
if (!pLoad || !loadConf)
return NULL;
pLoad->name = xstrdup(loadConf->load_name);
if (loadConf->load_name && !pLoad->name) {
xf86ConfFreeLoadModuleData(pLoad);
return NULL;
}
pLoad->options = xf86OptionListDup(loadConf->load_opt);
if (loadConf->load_opt && !pLoad->options) {
xf86ConfFreeLoadModuleData(pLoad);
return NULL;
}
return pLoad;
}
confModulesPtr
xf86ConfAllocModules()
{
confModulesPtr pModules;
pModules = xcalloc(1, sizeof(*pModules));
pModules->handle = pModules;
return pModules;
}
void
xf86ConfFreeModulesData(confModulesPtr pModules)
{
int i;
if (!pModules)
return;
if (pModules->identifier) {
xfree(pModules->identifier);
pModules->identifier = NULL;
}
if (pModules->options) {
xf86OptionListFree(pModules->options);
pModules->options = NULL;
}
if (pModules->modules) {
for (i = 0; i < pModules->numModules; i++) {
xf86ConfFreeLoadModuleData(pModules->modules[i]);
xfree(pModules->modules[i]);
pModules->modules[i] = NULL;
}
xfree(pModules->modules);
pModules->modules = NULL;
}
pModules->numModules = 0;
}
confModulesPtr
xf86ConfDupModules(const confModulesRec *pModules)
{
confModulesPtr m;
int i;
if (!pModules)
return NULL;
m = xf86ConfAllocModules();
if (!m)
return NULL;
m->handle = pModules->handle;
m->identifier = xstrdup(pModules->identifier);
if (pModules->identifier && !m->identifier) {
xf86ConfFreeModulesData(m);
xfree(m);
return NULL;
}
m->options = xf86OptionListDup(pModules->options);
if (pModules->options && !m->options) {
xf86ConfFreeModulesData(m);
xfree(m);
return NULL;
}
m->numModules = pModules->numModules;
if (m->numModules > 0 && pModules->modules) {
m->modules = xcalloc(m->numModules, sizeof(confLoadModulePtr));
if (!m->modules) {
xf86ConfFreeModulesData(m);
xfree(m);
return NULL;
}
for (i = 0; i < m->numModules; i++) {
m->modules[i] = xf86ConfDupLoadModule(pModules->modules[i]);
if (pModules->modules[i] && !m->modules[i]) {
xf86ConfFreeModulesData(m);
xfree(m);
return NULL;
}
}
}
return m;
}
static confModulesPtr
convertModules(confModulesPtr pModules, const XF86ConfModuleRec* confModules)
{
XF86LoadPtr lp;
int count, i;
if (!pModules || !confModules)
return NULL;
pModules->handle = confModules;
pModules->identifier = xstrdup(confModules->mod_identifier);
if (confModules->mod_identifier && !pModules->identifier) {
xf86ConfFreeModulesData(pModules);
return NULL;
}
pModules->options = xf86OptionListDup(confModules->mod_option_lst);
if (confModules->mod_option_lst && !pModules->options) {
xf86ConfFreeModulesData(pModules);
return NULL;
}
/* Count how many module load references there are. */
lp = confModules->mod_load_lst;
count = 0;
while (lp) {
count++;
lp = lp->list.next;
}
pModules->numModules = count;
if (count > 0) {
pModules->modules = xcalloc(count, sizeof(confLoadModulePtr));
if (!pModules->modules) {
xf86ConfFreeModulesData(pModules);
return NULL;
}
lp = confModules->mod_load_lst;
for (i = 0; i < count; i++) {
pModules->modules[i] = xf86ConfAllocLoadModule();
if (!pModules->modules[i]) {
xf86ConfFreeModulesData(pModules);
return NULL;
}
if (!convertLoadModule(pModules->modules[i], lp)) {
xf86ConfFreeModulesData(pModules);
return NULL;
}
lp = lp->list.next;
}
}
return pModules;
}
confModulesPtr
xf86ConfGetModulesByName(ConfigHandle handle, const char *name)
{
const XF86ConfigRec *pConfig;
const XF86ConfModuleRec *m;
confModulesPtr pModules = NULL;
if (!name)
return NULL;
pConfig = ConfigHandleToConfigRead(handle);
for (m = pConfig->conf_modules_lst; m; m = m->list.next) {
if (xf86nameCompare(m->mod_identifier, name) == 0)
break;
}
if (m) {
pModules = xf86ConfAllocModules();
if (pModules) {
if (convertModules(pModules, m))
return pModules;
else
xfree(pModules);
}
}
return NULL;
}
confModulesPtr
xf86ConfGetNextModules(ConfigHandle handle,
ConfigDataHandle prevModulesHandle)
{
const XF86ConfigRec *pConfig;
const XF86ConfModuleRec *m;
confModulesPtr pModules = NULL;
/* The active special case. */
if (handle == ACTIVE_CONFIG) {
if (!prevModulesHandle)
return xf86ConfDupModules(xf86Info.confModules);
else
return NULL;
}
pConfig = ConfigHandleToConfigRead(handle);
if (!prevModulesHandle) {
m = pConfig->conf_modules_lst;
} else {
for (m = pConfig->conf_modules_lst; m; m = m->list.next) {
if (m == prevModulesHandle) {
m = m->list.next;
break;
}
}
}
if (m) {
pModules = xf86ConfAllocModules();
if (pModules) {
if (convertModules(pModules, m))
return pModules;
else
xfree(pModules);
}
}
return NULL;
}
confModulesPtr
xf86ConfCombineModulesData(const confModulesRec *src1,
const confModulesRec *src2)
{
confModulesPtr dst = NULL;
pointer opt1 = NULL, opt2 = NULL;
int i, j;
dst = xf86ConfAllocModules();
if (!dst)
return NULL;
dst->numModules = 0;
if (src1)
dst->numModules = src1->numModules;
if (src2)
dst->numModules += src2->numModules;
if (dst->numModules > 0) {
dst->modules = xcalloc(dst->numModules, sizeof(confLoadModulePtr));
if (!dst->modules) {
xf86ConfFreeModulesData(dst);
xfree(dst);
return NULL;
}
j = 0;
if (src1) {
for (i = 0; i < src1->numModules; i++) {
dst->modules[j] = xf86ConfAllocLoadModule();
if (!dst->modules) {
xf86ConfFreeModulesData(dst);
xfree(dst);
return NULL;
}
dst->modules[j]->name = xstrdup(src1->modules[i]->name);
dst->modules[j]->options =
xf86OptionListDup(src1->modules[i]->options);
j++;
}
}
if (src2) {
for (i = 0; i < src2->numModules; i++) {
dst->modules[j] = xf86ConfAllocLoadModule();
if (!dst->modules) {
xf86ConfFreeModulesData(dst);
xfree(dst);
return NULL;
}
dst->modules[j]->name = xstrdup(src2->modules[i]->name);
dst->modules[j]->options =
xf86OptionListDup(src2->modules[i]->options);
j++;
}
}
}
if (src1)
opt1 = xf86OptionListDup(src1->options);
if (src2)
opt2 = xf86OptionListDup(src2->options);
dst->options = xf86OptionListMerge(opt2, opt1);
dst->handle = dst;
return dst;
}
/*
* Process the Modules sections, combining them into a single list of modules
* to load explicitly.
*/
static confModulesPtr
configModules(ConfigHandle handle, const XF86ConfModuleRec *confModules,
MessageType from)
{
confModulesPtr m = NULL, m1, m2;
const void *mh;
if (confModules) {
m = xf86ConfAllocModules();
if (!m)
return NULL;
if (!convertModules(m, confModules)) {
xfree(m);
return NULL;
}
} else {
m1 = xf86ConfGetNextModules(handle, NULL);
if (m1) {
mh = m1->handle;
do {
m2 = xf86ConfGetNextModules(handle, mh);
if (m2) {
mh = m2->handle;
m = xf86ConfCombineModulesData(m1, m2);
xf86ConfFreeModulesData(m1);
xf86ConfFreeModulesData(m2);
xfree(m1);
xfree(m2);
if (!m)
return NULL;
m1 = m;
} else {
m = m1;
mh = NULL;
}
} while (mh);
}
}
if (!m)
m = xf86ConfAllocModules();
return m;
}
void
xf86ModulelistFree(const char **moduleList, pointer *optList)
{
int i;
if (moduleList) {
for (i = 0; moduleList[i]; i++)
xfree(moduleList[i]);
xfree(moduleList);
}
if (optList) {
for (i = 0; optList[i]; i++)
xf86OptionListFree(optList[i]);
xfree(optList);
}
}
const char **
xf86ModulelistFromConfig(pointer **optList)
{
const char **moduleArray = NULL;
pointer *optArray = NULL;
int i, n;
if (!optList)
return NULL;
if (xf86Info.confModules && xf86Info.confModules->numModules > 0) {
n = xf86Info.confModules->numModules;
moduleArray = xcalloc(n + 1, sizeof(*moduleArray));
optArray = xcalloc(n + 1, sizeof(*optArray));
for (i = 0; i < n; i++) {
moduleArray[i] = xstrdup(xf86Info.confModules->modules[i]->name);
if (!moduleArray[i]) {
xf86ModulelistFree(moduleArray, optArray);
return NULL;
}
optArray[i] =
xf86OptionListDup(xf86Info.confModules->modules[i]->options);
if (xf86Info.confModules->modules[i]->options && !optArray[i]) {
xf86ModulelistFree(moduleArray, optArray);
return NULL;
}
}
moduleArray[n] = NULL;
optArray[n] = NULL;
}
*optList = optArray;
return moduleArray;
}
const char **
xf86DriverlistFromConfig()
{
int count = 0;
int i, j;
const char **modulearray;
screenLayoutPtr pScreenLayout;
if (!xf86Info.serverLayout)
return NULL;
count = xf86Info.serverLayout->numScreens +
xf86Info.serverLayout->numInactives;
if (count == 0)
return NULL;
modulearray = xnfalloc((count + 1) * sizeof(char*));
j = 0;
for (i = 0; i < xf86Info.serverLayout->numScreens; i++) {
pScreenLayout = xf86Info.serverLayout->screenLayouts[i];
modulearray[j] = pScreenLayout->screen->device->driver;
j++;
}
for (i = 0; i < xf86Info.serverLayout->numInactives; i++) {
modulearray[j] = xf86Info.serverLayout->inactiveDevs[i]->driver;
j++;
}
modulearray[j] = NULL;
/* Remove duplicates */
for (i = 0; i < count; i++) {
for (j = 0; j < i; j++) {
if (xf86NameCmp(modulearray[j], modulearray[i]) == 0) {
modulearray[i] = "";
break;
}
}
}
return modulearray;
}
Bool
xf86BuiltinInputDriver(const char *name)
{
if (xf86NameCmp(name, "keyboard") == 0)
return TRUE;
else
return FALSE;
}
const char **
xf86InputDriverlistFromConfig()
{
int i;
const char **modulearray;
if (!xf86Info.serverLayout)
return NULL;
if (xf86Info.serverLayout->numInputs == 0)
return NULL;
modulearray = xnfalloc((xf86Info.serverLayout->numInputs + 1) *
sizeof(char*));
for (i = 0; i < xf86Info.serverLayout->numInputs; i++) {
if (!xf86BuiltinInputDriver(
xf86Info.serverLayout->inputDevs[i]->driver))
modulearray[i] = xf86Info.serverLayout->inputDevs[i]->driver;
else
modulearray[i] = "";
}
modulearray[i] = NULL;
/* Remove duplicates. */
for (i = 0; i < xf86Info.serverLayout->numInputs; i++) {
int j;
for (j = 0; j < i; j++) {
if (xf86NameCmp(modulearray[j], modulearray[i]) == 0) {
modulearray[i] = "";
break;
}
}
}
return modulearray;
}
/*
* Generate a compiled-in list of driver names. This is used to produce a
* consistent probe order. For the loader server, we also look for vendor-
* provided modules, pre-pending them to our own list.
*/
static const char **
GenerateDriverlist(char * dirname, char * drivernames)
{
char *cp, **driverlist;
int count;
/* Count the number needed */
count = 0;
cp = drivernames;
while (*cp) {
while (*cp && isspace(*cp)) cp++;
if (!*cp) break;
count++;
while (*cp && !isspace(*cp)) cp++;
}
if (!count)
return NULL;
/* Now allocate the array of pointers to 0-terminated driver names */
driverlist = (char **)xnfalloc((count + 1) * sizeof(char *));
count = 0;
cp = drivernames;
while (*cp) {
while (*cp && isspace(*cp)) cp++;
if (!*cp) break;
driverlist[count++] = cp;
while (*cp && !isspace(*cp)) cp++;
if (!*cp) break;
*cp++ = 0;
}
driverlist[count] = NULL;
#ifdef XFree86LOADER
{
const char *subdirs[] = {NULL, NULL};
static const char *patlist[] = {"(.*)_drv\\.so", "(.*)_drv\\.o", NULL};
char **dlist, **clist, **dcp, **ccp;
int size;
subdirs[0] = dirname;
/* Get module list */
dlist = LoaderListDirs(subdirs, patlist);
if (!dlist) {
xfree(driverlist);
return NULL; /* No modules, no list */
}
clist = driverlist;
/* The resulting list cannot be longer than the module list */
for (dcp = dlist, count = 0; *dcp++; count++);
driverlist = (char **)xnfalloc((size = count + 1) * sizeof(char *));
/* First, add modules not in compiled-in list */
for (count = 0, dcp = dlist; *dcp; dcp++) {
for (ccp = clist; ; ccp++) {
if (!*ccp) {
driverlist[count++] = *dcp;
if (count >= size)
driverlist = (char**)
xnfrealloc(driverlist, ++size * sizeof(char*));
break;
}
if (!strcmp(*ccp, *dcp))
break;
}
}
/* Next, add compiled-in names that are also modules */
for (ccp = clist; *ccp; ccp++) {
for (dcp = dlist; *dcp; dcp++) {
if (!strcmp(*ccp, *dcp)) {
driverlist[count++] = *ccp;
if (count >= size)
driverlist = (char**)
xnfrealloc(driverlist, ++size * sizeof(char*));
break;
}
}
}
driverlist[count] = NULL;
xfree(clist);
xfree(dlist);
}
#endif /* XFree86LOADER */
return (const char **)driverlist;
}
const char **
xf86DriverlistFromCompile(void)
{
static const char **driverlist = NULL;
static Bool generated = FALSE;
/* This string is modified in-place */
static char drivernames[] = DRIVERS;
if (!generated) {
generated = TRUE;
driverlist = GenerateDriverlist("drivers", drivernames);
}
return driverlist;
}
const char **
xf86InputDriverlistFromCompile(void)
{
static const char **driverlist = NULL;
static Bool generated = FALSE;
/* This string is modified in-place */
static char drivernames[] = IDRIVERS;
if (!generated) {
generated = TRUE;
driverlist = GenerateDriverlist("input", drivernames);
}
return driverlist;
}
confFilesPtr
xf86ConfAllocFiles()
{
confFilesPtr pFiles;
pFiles = xcalloc(1, sizeof(*pFiles));
pFiles->fontPathFrom = X_NONE;
pFiles->rgbPathFrom = X_NONE;
pFiles->modulePathFrom = X_NONE;
pFiles->logFileFrom = X_NONE;
pFiles->inputDeviceListFrom = X_NONE;
pFiles->handle = pFiles;
return pFiles;
}
void
xf86ConfFreeFilesData(confFilesPtr pFiles)
{
if (!pFiles)
return;
if (pFiles->identifier) {
xfree(pFiles->identifier);
pFiles->identifier = NULL;
}
if (pFiles->logFile) {
xfree(pFiles->logFile);
pFiles->logFile = NULL;
}
if (pFiles->rgbPath) {
xfree(pFiles->rgbPath);
pFiles->rgbPath = NULL;
}
if (pFiles->modulePath) {
xfree(pFiles->modulePath);
pFiles->modulePath = NULL;
}
if (pFiles->inputDeviceList) {
xfree(pFiles->inputDeviceList);
pFiles->inputDeviceList = NULL;
}
if (pFiles->fontPath) {
xfree(pFiles->fontPath);
pFiles->fontPath = NULL;
}
if (pFiles->options) {
xf86OptionListFree(pFiles->options);
pFiles->options = NULL;
}
}
confFilesPtr
xf86ConfDupFiles(const confFilesRec *pFiles)
{
confFilesPtr f;
if (!pFiles)
return NULL;
f = xf86ConfAllocFiles();
if (!f)
return NULL;
f->handle = pFiles->handle;
f->identifier = xstrdup(pFiles->identifier);
if (pFiles->identifier && !f->identifier) {
xf86ConfFreeFilesData(f);
xfree(f);
return NULL;
}
f->logFile = xstrdup(pFiles->logFile);
if (pFiles->logFile && !f->logFile) {
xf86ConfFreeFilesData(f);
xfree(f);
return NULL;
}
f->rgbPath = xstrdup(pFiles->rgbPath);
if (pFiles->rgbPath && !f->rgbPath) {
xf86ConfFreeFilesData(f);
xfree(f);
return NULL;
}
f->modulePath = xstrdup(pFiles->modulePath);
if (pFiles->modulePath && !f->modulePath) {
xf86ConfFreeFilesData(f);
xfree(f);
return NULL;
}
f->inputDeviceList = xstrdup(pFiles->inputDeviceList);
if (pFiles->inputDeviceList && !f->inputDeviceList) {
xf86ConfFreeFilesData(f);
xfree(f);
return NULL;
}
f->fontPath = xstrdup(pFiles->fontPath);
if (pFiles->fontPath && !f->fontPath) {
xf86ConfFreeFilesData(f);
xfree(f);
return NULL;
}
f->options = xf86OptionListDup(pFiles->options);
if (pFiles->options && !f->options) {
xf86ConfFreeFilesData(f);
xfree(f);
return NULL;
}
return f;
}
/*
* Convert a Files section from the parser's format to the server's format.
*/
static confFilesPtr
convertFiles(confFilesPtr pFiles, const XF86ConfFilesRec *filesConf)
{
if (!pFiles || !filesConf)
return NULL;
pFiles->handle = filesConf;
pFiles->identifier = xstrdup(filesConf->file_identifier);
if (filesConf->file_identifier && !pFiles->identifier) {
xf86ConfFreeFilesData(pFiles);
return NULL;
}
pFiles->logFile = xstrdup(filesConf->file_logfile);
if (filesConf->file_logfile && !pFiles->logFile) {
xf86ConfFreeFilesData(pFiles);
return NULL;
}
pFiles->rgbPath = xstrdup(filesConf->file_rgbpath);
if (filesConf->file_rgbpath && !pFiles->rgbPath) {
xf86ConfFreeFilesData(pFiles);
return NULL;
}
pFiles->modulePath = xstrdup(filesConf->file_modulepath);
if (filesConf->file_modulepath && !pFiles->modulePath) {
xf86ConfFreeFilesData(pFiles);
return NULL;
}
pFiles->inputDeviceList = xstrdup(filesConf->file_inputdevs);
if (filesConf->file_inputdevs && !pFiles->inputDeviceList) {
xf86ConfFreeFilesData(pFiles);
return NULL;
}
pFiles->fontPath = xstrdup(filesConf->file_fontpath);
if (filesConf->file_fontpath && !pFiles->fontPath) {
xf86ConfFreeFilesData(pFiles);
return NULL;
}
pFiles->options = xf86OptionListDup(filesConf->file_option_lst);
if (filesConf->file_option_lst && !pFiles->options) {
xf86ConfFreeFilesData(pFiles);
return NULL;
}
return pFiles;
}
confFilesPtr
xf86ConfGetFilesByName(ConfigHandle handle, const char *name)
{
const XF86ConfigRec *pConfig;
XF86ConfFilesPtr f;
confFilesPtr pFiles = NULL;
if (!name)
return NULL;
pConfig = ConfigHandleToConfigRead(handle);
for (f = pConfig->conf_files_lst; f; f = f->list.next) {
if (xf86nameCompare(f->file_identifier, name) == 0)
break;
}
if (f) {
pFiles = xf86ConfAllocFiles();
if (pFiles) {
if (convertFiles(pFiles, f))
return pFiles;
else
xfree(pFiles);
}
}
return NULL;
}
confFilesPtr
xf86ConfGetNextFiles(ConfigHandle handle, ConfigDataHandle prevFilesHandle)
{
const XF86ConfigRec *pConfig;
XF86ConfFilesPtr f;
confFilesPtr pFiles = NULL;
/* Check for these special cases first. */
if (handle == CMDLINE_CONFIG || handle == BUILDTIME_CONFIG ||
handle == ACTIVE_CONFIG) {
if (prevFilesHandle)
return NULL;
else {
const confFilesRec *fd;
if (handle == ACTIVE_CONFIG)
return xf86ConfDupFiles(xf86FilePaths);
else if (handle == CMDLINE_CONFIG)
fd = &xf86FileCmdline;
else
fd = &xf86FileDefaults;
pFiles = xf86ConfCombineFilesData(fd, X_NONE, NULL, X_NONE);
if (!pFiles)
return NULL;
return pFiles;
}
}
pConfig = ConfigHandleToConfigRead(handle);
if (!prevFilesHandle) {
f = pConfig->conf_files_lst;
} else {
for (f = pConfig->conf_files_lst; f; f = f->list.next) {
if (f == prevFilesHandle) {
f = f->list.next;
break;
}
}
}
if (f) {
pFiles = xf86ConfAllocFiles();
if (pFiles) {
if (convertFiles(pFiles, f))
return pFiles;
else
xfree(pFiles);
}
}
return NULL;
}
confFilesPtr
xf86ConfCombineFilesData(const confFilesRec *src1, MessageType m1,
const confFilesRec *src2, MessageType m2)
{
pointer opt1 = NULL, opt2 = NULL;
confFilesPtr dst = NULL;
dst = xf86ConfAllocFiles();
if (!dst)
return NULL;
if (src1 && src1->logFile) {
dst->logFile = xstrdup(src1->logFile);
dst->logFileFrom = (m1 != X_NONE ? m1 : src1->logFileFrom);
} else if (src2 && src2->logFile) {
dst->logFile = xstrdup(src2->logFile);
dst->logFileFrom = (m2 != X_NONE ? m2 : src2->logFileFrom);
}
if (!dst->logFile && ((src1 && src1->logFile) ||
(src2 && src2->logFile))) {
xf86ConfFreeFilesData(dst);
xfree(dst);
return NULL;
}
if (src1 && src1->rgbPath) {
dst->rgbPath = xstrdup(src1->rgbPath);
dst->rgbPathFrom = (m1 != X_NONE ? m1 : src1->rgbPathFrom);
} else if (src2 && src2->rgbPath) {
dst->rgbPath = xstrdup(src2->rgbPath);
dst->rgbPathFrom = (m2 != X_NONE ? m2 : src2->rgbPathFrom);
}
if (!dst->rgbPath && ((src1 && src1->rgbPath) ||
(src2 && src2->rgbPath))) {
xf86ConfFreeFilesData(dst);
xfree(dst);
return NULL;
}
if (src1 && src1->modulePath) {
dst->modulePath = xstrdup(src1->modulePath);
dst->modulePathFrom = (m1 != X_NONE ? m1 : src1->modulePathFrom);
} else if (src2 && src2->modulePath) {
dst->modulePath = xstrdup(src2->modulePath);
dst->modulePathFrom = (m2 != X_NONE ? m2 : src2->modulePathFrom);
}
if (!dst->modulePath && ((src1 && src1->modulePath) ||
(src2 && src2->modulePath))) {
xf86ConfFreeFilesData(dst);
xfree(dst);
return NULL;
}
if (src1 && src1->fontPath) {
dst->fontPath = xstrdup(src1->fontPath);
dst->fontPathFrom = (m1 != X_NONE ? m1 : src1->fontPathFrom);
} else if (src2 && src2->fontPath) {
dst->fontPath = xstrdup(src2->fontPath);
dst->fontPathFrom = (m2 != X_NONE ? m2 : src2->fontPathFrom);
}
if (!dst->fontPath && ((src1 && src1->fontPath) ||
(src2 && src2->fontPath))) {
xf86ConfFreeFilesData(dst);
xfree(dst);
return NULL;
}
if (src1 && src1->inputDeviceList) {
dst->inputDeviceList = xstrdup(src1->inputDeviceList);
dst->inputDeviceListFrom =
(m1 != X_NONE ? m1 : src1->inputDeviceListFrom);
} else if (src2 && src2->inputDeviceList) {
dst->inputDeviceList = xstrdup(src2->inputDeviceList);
dst->inputDeviceListFrom =
(m2 != X_NONE ? m2 : src2->inputDeviceListFrom);
}
if (!dst->inputDeviceList && ((src1 && src1->inputDeviceList) ||
(src2 && src2->inputDeviceList))) {
xf86ConfFreeFilesData(dst);
xfree(dst);
return NULL;
}
if (src1)
opt1 = xf86OptionListDup(src1->options);
if (src2)
opt2 = xf86OptionListDup(src2->options);
dst->options = xf86OptionListMerge(opt2, opt1);
dst->handle = dst;
return dst;
}
/*
* xf86GetPathElem --
* Extract a single element from the font path string starting at
* pnt. The font path element will be returned, and pnt will be
* updated to point to the start of the next element, or set to
* NULL if there are no more.
*/
static char *
xf86GetPathElem(char **pnt)
{
char *p1;
p1 = *pnt;
*pnt = strchr(*pnt, ',');
if (*pnt) {
**pnt = '\0';
(*pnt)++;
}
return p1;
}
/*
* xf86ValidateFontPath --
* Validates the user-specified font path. Each element that
* begins with a '/' is checked to make sure the directory exists.
* If the directory exists, the existence of a file named 'fonts.dir'
* is checked. If either check fails, an error is printed and the
* element is removed from the font path.
*/
#define DIR_FILE "/fonts.dir"
static char *
xf86ValidateFontPath(const char *p)
{
char *tmp_path, *out_pnt, *path_elem, *next, *p1, *dir_elem, *path;
struct stat stat_buf;
Bool ok;
int dirlen;
path = xstrdup(p);
if (!path)
return NULL;
tmp_path = xcalloc(1, strlen(path) + 1);
if (!tmp_path)
return NULL;
out_pnt = tmp_path;
path_elem = NULL;
next = path;
while (next) {
path_elem = xf86GetPathElem(&next);
if (*path_elem == '/') {
#ifndef __UNIXOS2__
dir_elem = xcalloc(1, strlen(path_elem) + 1);
if (!dir_elem) {
xfree(tmp_path);
return NULL;
}
if ((p1 = strchr(path_elem, ':')))
#else
/* OS/2 must prepend X11ROOT */
path_elem = (char*)__XOS2RedirRoot(path_elem);
dir_elem = xcalloc(1, strlen(path_elem) + 1);
if (!dir_elem) {
xfree(tmp_path);
return NULL;
}
if ((p1 = strchr(path_elem + 2, ':')))
#endif
dirlen = p1 - path_elem;
else
dirlen = strlen(path_elem);
strncpy(dir_elem, path_elem, dirlen);
dir_elem[dirlen] = '\0';
ok = (stat(dir_elem, &stat_buf) == 0 && S_ISDIR(stat_buf.st_mode));
if (!ok) {
xf86Msg(X_WARNING,
"The directory \"%s\" does not exist.\n", dir_elem);
xf86ErrorF("\tEntry deleted from font path.\n");
xfree(dir_elem);
continue;
} else {
p1 = xalloc(strlen(dir_elem) + strlen(DIR_FILE) + 1);
if (!p1) {
xfree(dir_elem);
xfree(tmp_path);
return NULL;
}
strcpy(p1, dir_elem);
strcat(p1, DIR_FILE);
ok = (stat(p1, &stat_buf) == 0 && S_ISREG(stat_buf.st_mode));
xfree(p1);
if (!ok) {
xf86Msg(X_WARNING,
"\"fonts.dir\" not found (or not valid) in "
"\"%s\".\n", dir_elem);
xf86ErrorF("\tEntry deleted from font path.\n");
xf86ErrorF("\t(Run 'mkfontdir' on \"%s\").\n", dir_elem);
xfree(dir_elem);
continue;
}
}
xfree(dir_elem);
}
/*
* Either an OK directory, or a font server name. So add it to
* the path.
*/
if (out_pnt != tmp_path)
*out_pnt++ = ',';
strcat(out_pnt, path_elem);
out_pnt += strlen(path_elem);
}
return tmp_path;
}
static confFilesPtr
configFiles(ConfigHandle handle, const XF86ConfFilesRec *filesConf,
MessageType from)
{
confFilesPtr f = NULL, f1, f2;
const void *fh;
/*
* If filesConf is supplied explicitly, use it. Otherwise combine all
* of the Files data.
*/
if (filesConf) {
f = xf86ConfAllocFiles();
if (!f)
return NULL;
if (!(f = convertFiles(f, filesConf))) {
xfree(f);
return NULL;
}
} else {
f1 = xf86ConfGetNextFiles(handle, NULL);
if (f1) {
fh = f1->handle;
do {
f2 = xf86ConfGetNextFiles(handle, fh);
if (f2) {
fh = f2->handle;
f = xf86ConfCombineFilesData(f1, from, f2, from);
xf86ConfFreeFilesData(f1);
xf86ConfFreeFilesData(f2);
xfree(f1);
xfree(f2);
if (!f)
return NULL;
f1 = f;
} else {
f = f1;
fh = NULL;
}
} while (fh);
}
}
/*
* Combine the config file data with the defaults and command line
* options.
*/
f1 = f;
f = xf86ConfCombineFilesData(&xf86FileCmdline, X_CMDLINE, f1, from);
xf86ConfFreeFilesData(f1);
xfree(f1);
if (!f)
return NULL;
f1 = f;
f = xf86ConfCombineFilesData(f1, X_NONE, &xf86FileDefaults, X_DEFAULT);
xf86ConfFreeFilesData(f1);
xfree(f1);
if (!f)
return NULL;
f->identifier = xstrdup("<combined>");
xf86ConfFreeFilesData(xf86FilePaths);
xf86FilePaths = f;
/* Validate/print path info. */
{
char *fp;
fp = xf86ValidateFontPath(xf86FilePaths->fontPath);
xfree(xf86FilePaths->fontPath);
if (fp && *fp) {
xf86FilePaths->fontPath = fp;
defaultFontPath = fp;
} else {
xf86Msg(X_WARNING, "FontPath is completely invalid. "
"Using compiled-in default.\n");
xf86FilePaths->fontPath = xstrdup(defaultFontPath);
if (!xf86FilePaths->fontPath)
return NULL;
xf86FilePaths->fontPathFrom = X_DEFAULT;
}
}
/* Fatal error if no valid font path is found. */
if (!defaultFontPath || !*defaultFontPath)
FatalError("No valid FontPath could be found.");
xf86Msg(xf86FilePaths->fontPathFrom, "FontPath set to \"%s\"\n",
xf86FilePaths->fontPath);
rgbPath = xnfstrdup(xf86FilePaths->rgbPath);
xf86Msg(xf86FilePaths->rgbPathFrom, "RgbPath set to \"%s\"\n",
xf86FilePaths->rgbPath);
if (xf86FilePaths->inputDeviceList) {
xf86Msg(xf86FilePaths->inputDeviceListFrom,
"Input device list set to \"%s\"\n",
xf86FilePaths->inputDeviceList);
}
xf86Msg(xf86FilePaths->modulePathFrom, "ModulePath set to \"%s\"\n",
xf86FilePaths->modulePath);
#if 0
/* LogFile */
/*
* XXX The problem with this is that the log file is already open.
* One option might be to copy the exiting contents to the new location.
* and re-open it. The down side is that the default location would
* already have been overwritten. Another option would be to start with
* unique temporary location, then copy it once the correct name is known.
* A problem with this is what happens if the server exits before that
* happens.
*/
xf86Msg(xf86FilePaths->logFileFrom, "Log file set to \"%s\"\n",
xf86FilePaths->logFile);
#endif
return xf86FilePaths;
}
confFlagsPtr
xf86ConfAllocServerFlags()
{
confFlagsPtr pFlags;
pFlags = xcalloc(1, sizeof(*pFlags));
pFlags->handle = pFlags;
return pFlags;
}
void
xf86ConfFreeServerFlagsData(confFlagsPtr pFlags)
{
if (!pFlags)
return;
if (pFlags->identifier) {
xfree(pFlags->identifier);
pFlags->identifier = NULL;
}
if (pFlags->options) {
xf86OptionListFree(pFlags->options);
pFlags->options = NULL;
}
}
confFlagsPtr
xf86ConfDupServerFlags(const confFlagsRec *pFlags)
{
confFlagsPtr f;
if (!pFlags)
return NULL;
f = xf86ConfAllocServerFlags();
if (!f)
return NULL;
f->handle = pFlags->handle;
f->identifier = xstrdup(pFlags->identifier);
if (pFlags->identifier && !f->identifier) {
xf86ConfFreeServerFlagsData(f);
xfree(f);
return NULL;
}
f->options = xf86OptionListDup(pFlags->options);
if (pFlags->options && !f->options) {
xf86ConfFreeServerFlagsData(f);
xfree(f);
return NULL;
}
return f;
}
/*
* Convert a Files section from the parser's format to the server's format.
*/
static confFlagsPtr
convertServerFlags(confFlagsPtr pFlags, const XF86ConfFlagsRec *flagsConf)
{
if (!pFlags || !flagsConf)
return NULL;
pFlags->handle = flagsConf;
pFlags->identifier = xstrdup(flagsConf->flg_identifier);
if (flagsConf->flg_identifier && !pFlags->identifier) {
xf86ConfFreeServerFlagsData(pFlags);
return NULL;
}
pFlags->options = xf86OptionListDup(flagsConf->flg_option_lst);
if (flagsConf->flg_option_lst && !pFlags->options) {
xf86ConfFreeServerFlagsData(pFlags);
return NULL;
}
return pFlags;
}
confFlagsPtr
xf86ConfGetServerFlagsByName(ConfigHandle handle, const char *name)
{
const XF86ConfigRec *pConfig;
const XF86ConfFlagsRec *f;
confFlagsPtr pFlags = NULL;
if (!name)
return NULL;
pConfig = ConfigHandleToConfigRead(handle);
for (f = pConfig->conf_flags_lst; f; f = f->list.next) {
if (xf86nameCompare(f->flg_identifier, name) == 0)
break;
}
if (f) {
pFlags = xf86ConfAllocServerFlags();
if (pFlags) {
if (convertServerFlags(pFlags, f))
return pFlags;
else
xfree(pFlags);
}
}
return NULL;
}
confFlagsPtr
xf86ConfGetNextServerFlags(ConfigHandle handle,
ConfigDataHandle prevFlagsHandle)
{
const XF86ConfigRec *pConfig;
const XF86ConfFlagsRec *f;
confFlagsPtr pFlags = NULL;
/* The active special case. */
if (handle == ACTIVE_CONFIG) {
if (!prevFlagsHandle)
return xf86ConfDupServerFlags(xf86Info.confFlags);
else
return NULL;
}
pConfig = ConfigHandleToConfigRead(handle);
if (!prevFlagsHandle) {
f = pConfig->conf_flags_lst;
} else {
for (f = pConfig->conf_flags_lst; f; f = f->list.next) {
if (f == prevFlagsHandle) {
f = f->list.next;
break;
}
}
}
if (f) {
pFlags = xf86ConfAllocServerFlags();
if (pFlags) {
if (convertServerFlags(pFlags, f))
return pFlags;
else
xfree(pFlags);
}
}
return NULL;
}
confFlagsPtr
xf86ConfCombineServerFlagsData(const confFlagsRec *src1,
const confFlagsRec *src2)
{
confFlagsPtr dst = NULL;
pointer opt1 = NULL, opt2 = NULL;
dst = xf86ConfAllocServerFlags();
if (!dst)
return NULL;
if (src1)
opt1 = xf86OptionListDup(src1->options);
if (src2)
opt2 = xf86OptionListDup(src2->options);
dst->options = xf86OptionListMerge(opt2, opt1);
return dst;
}
typedef enum {
FLAG_NOTRAPSIGNALS,
FLAG_DONTVTSWITCH,
FLAG_DONTZAP,
FLAG_DONTZOOM,
FLAG_DISABLEVIDMODE,
FLAG_ALLOWNONLOCAL,
FLAG_DISABLEMODINDEV,
FLAG_MODINDEVALLOWNONLOCAL,
FLAG_ALLOWMOUSEOPENFAIL,
FLAG_VTINIT,
FLAG_VTSYSREQ,
FLAG_XKBDISABLE,
FLAG_PCIPROBE1,
FLAG_PCIPROBE2,
FLAG_PCIFORCECONFIG1,
FLAG_PCIFORCECONFIG2,
FLAG_PCIFORCENONE,
FLAG_PCIOSCONFIG,
FLAG_SAVER_BLANKTIME,
FLAG_DPMS_STANDBYTIME,
FLAG_DPMS_SUSPENDTIME,
FLAG_DPMS_OFFTIME,
FLAG_PIXMAP,
FLAG_PC98,
FLAG_ESTIMATE_SIZES_AGGRESSIVELY,
FLAG_NOPM,
FLAG_XINERAMA,
FLAG_ALLOW_DEACTIVATE_GRABS,
FLAG_ALLOW_CLOSEDOWN_GRABS,
FLAG_LOG,
FLAG_RENDER_COLORMAP_MODE,
FLAG_HANDLE_SPECIAL_KEYS,
FLAG_RANDR
} FlagValues;
static OptionInfoRec FlagOptions[] = {
{ FLAG_NOTRAPSIGNALS, "NoTrapSignals", OPTV_BOOLEAN,
{0}, FALSE },
{ FLAG_DONTVTSWITCH, "DontVTSwitch", OPTV_BOOLEAN,
{0}, FALSE },
{ FLAG_DONTZAP, "DontZap", OPTV_BOOLEAN,
{0}, FALSE },
{ FLAG_DONTZOOM, "DontZoom", OPTV_BOOLEAN,
{0}, FALSE },
{ FLAG_DISABLEVIDMODE, "DisableVidModeExtension", OPTV_BOOLEAN,
{0}, FALSE },
{ FLAG_ALLOWNONLOCAL, "AllowNonLocalXvidtune", OPTV_BOOLEAN,
{0}, FALSE },
{ FLAG_DISABLEMODINDEV, "DisableModInDev", OPTV_BOOLEAN,
{0}, FALSE },
{ FLAG_MODINDEVALLOWNONLOCAL, "AllowNonLocalModInDev", OPTV_BOOLEAN,
{0}, FALSE },
{ FLAG_ALLOWMOUSEOPENFAIL, "AllowMouseOpenFail", OPTV_BOOLEAN,
{0}, FALSE },
{ FLAG_VTINIT, "VTInit", OPTV_STRING,
{0}, FALSE },
{ FLAG_VTSYSREQ, "VTSysReq", OPTV_BOOLEAN,
{0}, FALSE },
{ FLAG_XKBDISABLE, "XkbDisable", OPTV_BOOLEAN,
{0}, FALSE },
{ FLAG_PCIPROBE1, "PciProbe1" , OPTV_BOOLEAN,
{0}, FALSE },
{ FLAG_PCIPROBE2, "PciProbe2", OPTV_BOOLEAN,
{0}, FALSE },
{ FLAG_PCIFORCECONFIG1, "PciForceConfig1", OPTV_BOOLEAN,
{0}, FALSE },
{ FLAG_PCIFORCECONFIG2, "PciForceConfig2", OPTV_BOOLEAN,
{0}, FALSE },
{ FLAG_PCIFORCENONE, "PciForceNone", OPTV_BOOLEAN,
{0}, FALSE },
{ FLAG_PCIOSCONFIG, "PciOsConfig", OPTV_BOOLEAN,
{0}, FALSE },
{ FLAG_SAVER_BLANKTIME, "BlankTime" , OPTV_INTEGER,
{0}, FALSE },
{ FLAG_DPMS_STANDBYTIME, "StandbyTime", OPTV_INTEGER,
{0}, FALSE },
{ FLAG_DPMS_SUSPENDTIME, "SuspendTime", OPTV_INTEGER,
{0}, FALSE },
{ FLAG_DPMS_OFFTIME, "OffTime", OPTV_INTEGER,
{0}, FALSE },
{ FLAG_PIXMAP, "Pixmap", OPTV_INTEGER,
{0}, FALSE },
{ FLAG_PC98, "PC98", OPTV_BOOLEAN,
{0}, FALSE },
{ FLAG_ESTIMATE_SIZES_AGGRESSIVELY,"EstimateSizesAggressively",OPTV_INTEGER,
{0}, FALSE },
{ FLAG_NOPM, "NoPM", OPTV_BOOLEAN,
{0}, FALSE },
{ FLAG_XINERAMA, "Xinerama", OPTV_BOOLEAN,
{0}, FALSE },
{ FLAG_ALLOW_DEACTIVATE_GRABS,"AllowDeactivateGrabs", OPTV_BOOLEAN,
{0}, FALSE },
{ FLAG_ALLOW_CLOSEDOWN_GRABS, "AllowClosedownGrabs", OPTV_BOOLEAN,
{0}, FALSE },
{ FLAG_LOG, "Log", OPTV_STRING,
{0}, FALSE },
{ FLAG_RENDER_COLORMAP_MODE, "RenderColormapMode", OPTV_STRING,
{0}, FALSE },
{ FLAG_HANDLE_SPECIAL_KEYS, "HandleSpecialKeys", OPTV_STRING,
{0}, FALSE },
{ FLAG_RANDR, "RandR", OPTV_BOOLEAN,
{0}, FALSE },
{ -1, NULL, OPTV_NONE,
{0}, FALSE },
};
#if defined(i386) || defined(__i386__)
static Bool
detectPC98(void)
{
#ifdef SUPPORT_PC98
unsigned char buf[2];
if (xf86ReadBIOS(0xf8000, 0xe80, buf, 2) != 2)
return FALSE;
if ((buf[0] == 0x98) && (buf[1] == 0x21))
return TRUE;
else
return FALSE;
#else
return FALSE;
#endif
}
#endif /* __i386__ */
static confFlagsPtr
configServerFlags(ConfigHandle handle, const XF86ConfFlagsPtr flagsConf,
XF86OptionPtr layoutOpts, MessageType from)
{
confFlagsPtr f = NULL, f1, f2;
const void *fh;
pointer opt1, opt2;
int i;
Pix24Flags pix24 = Pix24DontCare;
Bool value;
/*
* If flagsConf is supplied explicitly, use it. Otherwise combine all of
* the ServerFlags data.
*/
if (flagsConf) {
f = xf86ConfAllocServerFlags();
if (!f)
return NULL;
if (!(f = convertServerFlags(f, flagsConf))) {
xfree(f);
return NULL;
}
} else {
f1 = xf86ConfGetNextServerFlags(handle, NULL);
if (f1) {
fh = f1->handle;
do {
f2 = xf86ConfGetNextServerFlags(handle, fh);
if (f2) {
fh = f2->handle;
f = xf86ConfCombineServerFlagsData(f1, f2);
xf86ConfFreeServerFlagsData(f1);
xf86ConfFreeServerFlagsData(f2);
xfree(f1);
xfree(f2);
if (!f)
return NULL;
f1 = f;
} else {
f = f1;
fh = NULL;
}
} while (fh);
}
}
if (!f)
f = xf86ConfAllocServerFlags();
if (!f)
return NULL;
/*
* Merge the ServerLayout and ServerFlags options. The former have
* precedence over the latter.
*/
if (layoutOpts) {
opt1 = xf86OptionListDup(layoutOpts);
opt2 = xf86OptionListDup(f->options);
f->options = xf86OptionListMerge(opt2, opt1);
}
xf86ProcessOptions(-1, f->options, FlagOptions);
xf86GetOptValBool(FlagOptions, FLAG_NOTRAPSIGNALS, &xf86Info.notrapSignals);
xf86GetOptValBool(FlagOptions, FLAG_DONTVTSWITCH, &xf86Info.dontVTSwitch);
xf86GetOptValBool(FlagOptions, FLAG_DONTZAP, &xf86Info.dontZap);
xf86GetOptValBool(FlagOptions, FLAG_DONTZOOM, &xf86Info.dontZoom);
xf86GetOptValBool(FlagOptions, FLAG_ALLOW_DEACTIVATE_GRABS,
&(xf86Info.grabInfo.allowDeactivate));
xf86GetOptValBool(FlagOptions, FLAG_ALLOW_CLOSEDOWN_GRABS,
&(xf86Info.grabInfo.allowClosedown));
/*
* Set things up based on the config file information. Some of these
* settings may be overridden later when the command line options are
* checked.
*/
#ifdef XF86VIDMODE
if (xf86GetOptValBool(FlagOptions, FLAG_DISABLEVIDMODE, &value))
xf86Info.vidModeEnabled = !value;
if (xf86GetOptValBool(FlagOptions, FLAG_ALLOWNONLOCAL, &value))
xf86Info.vidModeAllowNonLocal = value;
#endif
#ifdef XF86MISC
if (xf86GetOptValBool(FlagOptions, FLAG_DISABLEMODINDEV, &value))
xf86Info.miscModInDevEnabled = !value;
if (xf86GetOptValBool(FlagOptions, FLAG_MODINDEVALLOWNONLOCAL, &value))
xf86Info.miscModInDevAllowNonLocal = value;
#endif
if (xf86GetOptValBool(FlagOptions, FLAG_ALLOWMOUSEOPENFAIL, &value))
xf86Info.allowMouseOpenFail = value;
if (xf86GetOptValBool(FlagOptions, FLAG_VTSYSREQ, &value)) {
#ifdef USE_VT_SYSREQ
xf86Info.vtSysreq = value;
xf86Msg(X_CONFIG, "VTSysReq %s\n", value ? "enabled" : "disabled");
#else
if (value)
xf86Msg(X_WARNING, "VTSysReq is not supported on this OS.\n");
#endif
}
if (xf86GetOptValBool(FlagOptions, FLAG_XKBDISABLE, &value)) {
#ifdef XKB
noXkbExtension = value;
xf86Msg(X_CONFIG, "Xkb %s\n", value ? "disabled" : "enabled");
#else
if (!value)
xf86Msg(X_WARNING, "Xserver doesn't support XKB.\n");
#endif
}
xf86Info.vtinit = xf86GetOptValString(FlagOptions, FLAG_VTINIT);
if (xf86IsOptionSet(FlagOptions, FLAG_PCIPROBE1))
xf86Info.pciFlags = PCIProbe1;
if (xf86IsOptionSet(FlagOptions, FLAG_PCIPROBE2))
xf86Info.pciFlags = PCIProbe2;
if (xf86IsOptionSet(FlagOptions, FLAG_PCIFORCECONFIG1))
xf86Info.pciFlags = PCIForceConfig1;
if (xf86IsOptionSet(FlagOptions, FLAG_PCIFORCECONFIG2))
xf86Info.pciFlags = PCIForceConfig2;
if (xf86IsOptionSet(FlagOptions, FLAG_PCIOSCONFIG))
xf86Info.pciFlags = PCIOsConfig;
if (xf86IsOptionSet(FlagOptions, FLAG_PCIFORCENONE))
xf86Info.pciFlags = PCIForceNone;
xf86Info.pmFlag = TRUE;
if (xf86GetOptValBool(FlagOptions, FLAG_NOPM, &value))
xf86Info.pmFlag = !value;
{
const char *s;
if ((s = xf86GetOptValString(FlagOptions, FLAG_LOG))) {
if (!xf86NameCmp(s,"flush")) {
xf86Msg(X_CONFIG, "Flushing logfile enabled\n");
LogSetParameter(XLOG_FLUSH, TRUE);
} else if (!xf86NameCmp(s,"sync")) {
xf86Msg(X_CONFIG, "Syncing logfile enabled\n");
LogSetParameter(XLOG_SYNC, TRUE);
} else {
xf86Msg(X_WARNING,"Unknown Log option.\n");
}
}
}
#ifdef RENDER
{
const char *s;
if ((s = xf86GetOptValString(FlagOptions, FLAG_RENDER_COLORMAP_MODE))){
int policy = PictureParseCmapPolicy (s);
if (policy == PictureCmapPolicyInvalid)
xf86Msg(X_WARNING, "Unknown colormap policy \"%s\".\n", s);
else
{
xf86Msg(X_CONFIG, "Render colormap policy set to %s\n", s);
PictureCmapPolicy = policy;
}
}
}
#endif
{
const char *s;
if ((s = xf86GetOptValString(FlagOptions, FLAG_HANDLE_SPECIAL_KEYS))) {
if (!xf86NameCmp(s,"always")) {
xf86Msg(X_CONFIG, "Always handling special keys in DDX\n");
xf86Info.ddxSpecialKeys = SKAlways;
} else if (!xf86NameCmp(s,"whenneeded")) {
xf86Msg(X_CONFIG, "Special keys handled in DDX only if needed\n");
xf86Info.ddxSpecialKeys = SKWhenNeeded;
} else if (!xf86NameCmp(s,"never")) {
xf86Msg(X_CONFIG, "Never handling special keys in DDX\n");
xf86Info.ddxSpecialKeys = SKNever;
} else {
xf86Msg(X_WARNING,"Unknown HandleSpecialKeys option.\n");
}
}
}
#ifdef RANDR
xf86Info.disableRandR = FALSE;
xf86Info.randRFrom = X_DEFAULT;
if (xf86GetOptValBool(FlagOptions, FLAG_RANDR, &value)) {
xf86Info.disableRandR = !value;
xf86Info.randRFrom = X_CONFIG;
}
#endif
/* Allow negative values */
xf86GetOptValInteger(FlagOptions, FLAG_ESTIMATE_SIZES_AGGRESSIVELY,
&xf86Info.estimateSizesAggressively);
i = -1;
xf86GetOptValInteger(FlagOptions, FLAG_SAVER_BLANKTIME, &i);
if (i >= 0)
ScreenSaverTime = defaultScreenSaverTime = i * MILLI_PER_MIN;
#ifdef DPMSExtension
i = -1;
xf86GetOptValInteger(FlagOptions, FLAG_DPMS_STANDBYTIME, &i);
if (i >= 0)
DPMSStandbyTime = defaultDPMSStandbyTime = i * MILLI_PER_MIN;
i = -1;
xf86GetOptValInteger(FlagOptions, FLAG_DPMS_SUSPENDTIME, &i);
if (i >= 0)
DPMSSuspendTime = defaultDPMSSuspendTime = i * MILLI_PER_MIN;
i = -1;
xf86GetOptValInteger(FlagOptions, FLAG_DPMS_OFFTIME, &i);
if (i >= 0)
DPMSOffTime = defaultDPMSOffTime = i * MILLI_PER_MIN;
#endif
i = -1;
xf86GetOptValInteger(FlagOptions, FLAG_PIXMAP, &i);
switch (i) {
case 24:
pix24 = Pix24Use24;
break;
case 32:
pix24 = Pix24Use32;
break;
case -1:
break;
default:
xf86ConfigError("Pixmap option's value (%d) must be 24 or 32\n", i);
return FALSE;
}
if (xf86Pix24 != Pix24DontCare) {
xf86Info.pixmap24 = xf86Pix24;
xf86Info.pix24From = X_CMDLINE;
} else if (pix24 != Pix24DontCare) {
xf86Info.pixmap24 = pix24;
xf86Info.pix24From = X_CONFIG;
} else {
xf86Info.pixmap24 = Pix24DontCare;
xf86Info.pix24From = X_DEFAULT;
}
#if defined(i386) || defined(__i386__)
if (xf86GetOptValBool(FlagOptions, FLAG_PC98, &value)) {
xf86Info.pc98 = value;
if (value) {
xf86Msg(X_CONFIG, "Japanese PC98 architecture\n");
}
} else
if (detectPC98()) {
xf86Info.pc98 = TRUE;
xf86Msg(X_PROBED, "Japanese PC98 architecture\n");
}
#endif
#ifdef PANORAMIX
from = X_DEFAULT;
if (!noPanoramiXExtension)
from = X_CMDLINE;
else if (xf86GetOptValBool(FlagOptions, FLAG_XINERAMA, &value)) {
noPanoramiXExtension = !value;
from = X_CONFIG;
}
if (!noPanoramiXExtension)
xf86Msg(from, "Xinerama: enabled.\n");
#endif
xf86ShowUnusedOptionsVerb(-1, f->options, 3);
return f;
}
/*
* XXX This function is temporary, and will be removed when the keyboard
* driver is converted into a regular input driver.
*/
static Bool
configInputKbd(IDevPtr pIDev)
{
char *s;
MessageType from = X_DEFAULT;
Bool customKeycodesDefault = FALSE;
int verb = 0;
/* Initialize defaults */
xf86Info.xleds = 0L;
xf86Info.kbdDelay = 500;
xf86Info.kbdRate = 30;
xf86Info.kbdProc = NULL;
xf86Info.vtinit = NULL;
xf86Info.vtSysreq = VT_SYSREQ_DEFAULT;
#if defined(SVR4) && defined(i386)
xf86Info.panix106 = FALSE;
#endif
xf86Info.kbdCustomKeycodes = FALSE;
#ifdef WSCONS_SUPPORT
xf86Info.kbdFd = -1;
#endif
#ifdef XKB
if (!xf86IsPc98()) {
xf86Info.xkbrules = "xfree86";
xf86Info.xkbmodel = "pc105";
xf86Info.xkblayout = "us";
xf86Info.xkbvariant = NULL;
xf86Info.xkboptions = NULL;
} else {
xf86Info.xkbrules = "xfree98";
xf86Info.xkbmodel = "pc98";
xf86Info.xkblayout = "nec/jp";
xf86Info.xkbvariant = NULL;
xf86Info.xkboptions = NULL;
}
xf86Info.xkbcomponents_specified = FALSE;
/* Should discourage the use of these. */
xf86Info.xkbkeymap = NULL;
xf86Info.xkbtypes = NULL;
xf86Info.xkbcompat = NULL;
xf86Info.xkbkeycodes = NULL;
xf86Info.xkbsymbols = NULL;
xf86Info.xkbgeometry = NULL;
#endif
s = xf86SetStrOption(pIDev->commonOptions, "Protocol", "standard");
if (xf86NameCmp(s, "standard") == 0) {
xf86Info.kbdProc = xf86KbdProc;
xf86Info.kbdEvents = xf86KbdEvents;
xfree(s);
} else if (xf86NameCmp(s, "xqueue") == 0) {
#ifdef XQUEUE
xf86Info.kbdProc = xf86XqueKbdProc;
xf86Info.kbdEvents = xf86XqueEvents;
xf86Msg(X_CONFIG, "Xqueue selected for keyboard input.\n");
#endif
xfree(s);
#ifdef WSCONS_SUPPORT
} else if (xf86NameCmp(s, "wskbd") == 0) {
xf86Info.kbdProc = xf86KbdProc;
xf86Info.kbdEvents = xf86WSKbdEvents;
xfree(s);
s = xf86SetStrOption(pIDev->commonOptions, "Device", NULL);
xf86Msg(X_CONFIG, "Keyboard: Protocol: wskbd\n");
if (!s) {
xf86ConfigError("A \"device\" option is required with"
" the \"wskbd\" keyboard protocol.");
return FALSE;
}
xf86Info.kbdFd = open(s, O_RDWR | O_NONBLOCK | O_EXCL);
if (xf86Info.kbdFd == -1) {
xf86ConfigError("cannot open \"%s\"", s);
xfree(s);
return FALSE;
}
xfree(s);
/* Find out keyboard type. */
if (ioctl(xf86Info.kbdFd, WSKBDIO_GTYPE, &xf86Info.wsKbdType) == -1) {
xf86ConfigError("Cannot get keyboard type.");
close(xf86Info.kbdFd);
return FALSE;
}
switch (xf86Info.wsKbdType) {
case WSKBD_TYPE_PC_XT:
xf86Msg(X_PROBED, "Keyboard type: XT\n");
break;
case WSKBD_TYPE_PC_AT:
xf86Msg(X_PROBED, "Keyboard type: AT\n");
break;
case WSKBD_TYPE_USB:
xf86Msg(X_PROBED, "Keyboard type: USB\n");
break;
#ifdef WSKBD_TYPE_ADB
case WSKBD_TYPE_ADB:
xf86Msg(X_PROBED, "Keyboard type: ADB\n");
break;
#endif
#ifdef WSKBD_TYPE_SUN
case WSKBD_TYPE_SUN:
xf86Msg(X_PROBED, "Keyboard type: Sun\n");
break;
#endif
#ifdef WSKBD_TYPE_SUN5
case WSKBD_TYPE_SUN5:
xf86Msg(X_PROBED, "Keyboard type: Sun5\n");
break;
#endif
default:
xf86Msg(X_PROBED, "Keyboard type: unknown (%d)\n",
xf86Info.wsKbdType);
}
#endif
} else {
xf86ConfigError("\"%s\" is not a valid keyboard protocol name.", s);
xfree(s);
return FALSE;
}
s = xf86SetStrOption(pIDev->commonOptions, "AutoRepeat", NULL);
if (s) {
if (sscanf(s, "%d %d", &xf86Info.kbdDelay, &xf86Info.kbdRate) != 2) {
xf86ConfigError("\"%s\" is not a valid AutoRepeat value", s);
xfree(s);
return FALSE;
}
xfree(s);
}
s = xf86SetStrOption(pIDev->commonOptions, "XLeds", NULL);
if (s) {
char *l, *end;
unsigned int i;
l = strtok(s, " \t\n");
while (l) {
i = strtoul(l, &end, 0);
if (*end == '\0')
xf86Info.xleds |= 1L << (i - 1);
else {
xf86ConfigError("\"%s\" is not a valid XLeds value", l);
xfree(s);
return FALSE;
}
l = strtok(NULL, " \t\n");
}
xfree(s);
}
#ifdef XKB
from = X_DEFAULT;
if (noXkbExtension)
from = X_CMDLINE;
else if (xf86FindOption(pIDev->commonOptions, "XkbDisable")) {
xf86Msg(X_WARNING, "KEYBOARD: XKB should be disabled in the "
"ServerFlags section instead\n"
"\tof in the \"keyboard\" InputDevice section.\n");
noXkbExtension =
xf86SetBoolOption(pIDev->commonOptions, "XkbDisable", FALSE);
from = X_CONFIG;
}
if (noXkbExtension)
xf86Msg(from, "XKB: disabled.\n");
#define NULL_IF_EMPTY(s) (s[0] ? s : (xfree(s), (char *)NULL))
if (!noXkbExtension && !XkbInitialMap) {
if ((s = xf86SetStrOption(pIDev->commonOptions, "XkbKeymap", NULL))) {
xf86Info.xkbkeymap = NULL_IF_EMPTY(s);
xf86Msg(X_CONFIG, "XKB: keymap: \"%s\" "
"(overrides other XKB settings)\n", xf86Info.xkbkeymap);
} else {
if ((s = xf86SetStrOption(pIDev->commonOptions, "XkbCompat",
NULL))) {
xf86Info.xkbcompat = NULL_IF_EMPTY(s);
xf86Info.xkbcomponents_specified = TRUE;
xf86Msg(X_CONFIG, "XKB: compat: \"%s\"\n", s);
}
if ((s = xf86SetStrOption(pIDev->commonOptions, "XkbTypes",
NULL))) {
xf86Info.xkbtypes = NULL_IF_EMPTY(s);
xf86Info.xkbcomponents_specified = TRUE;
xf86Msg(X_CONFIG, "XKB: types: \"%s\"\n", s);
}
if ((s = xf86SetStrOption(pIDev->commonOptions, "XkbKeycodes",
NULL))) {
xf86Info.xkbkeycodes = NULL_IF_EMPTY(s);
xf86Info.xkbcomponents_specified = TRUE;
xf86Msg(X_CONFIG, "XKB: keycodes: \"%s\"\n", s);
}
if ((s = xf86SetStrOption(pIDev->commonOptions, "XkbGeometry",
NULL))) {
xf86Info.xkbgeometry = NULL_IF_EMPTY(s);
xf86Info.xkbcomponents_specified = TRUE;
xf86Msg(X_CONFIG, "XKB: geometry: \"%s\"\n", s);
}
if ((s = xf86SetStrOption(pIDev->commonOptions, "XkbSymbols",
NULL))) {
xf86Info.xkbsymbols = NULL_IF_EMPTY(s);
xf86Info.xkbcomponents_specified = TRUE;
xf86Msg(X_CONFIG, "XKB: symbols: \"%s\"\n", s);
}
if ((s = xf86SetStrOption(pIDev->commonOptions, "XkbRules",
NULL))) {
xf86Info.xkbrules = NULL_IF_EMPTY(s);
xf86Info.xkbcomponents_specified = TRUE;
xf86Msg(X_CONFIG, "XKB: rules: \"%s\"\n", s);
}
if ((s = xf86SetStrOption(pIDev->commonOptions, "XkbModel",
NULL))) {
xf86Info.xkbmodel = NULL_IF_EMPTY(s);
xf86Info.xkbcomponents_specified = TRUE;
xf86Msg(X_CONFIG, "XKB: model: \"%s\"\n", s);
}
if ((s = xf86SetStrOption(pIDev->commonOptions, "XkbLayout",
NULL))) {
xf86Info.xkblayout = NULL_IF_EMPTY(s);
xf86Info.xkbcomponents_specified = TRUE;
xf86Msg(X_CONFIG, "XKB: layout: \"%s\"\n", s);
}
if ((s = xf86SetStrOption(pIDev->commonOptions, "XkbVariant",
NULL))) {
xf86Info.xkbvariant = NULL_IF_EMPTY(s);
xf86Info.xkbcomponents_specified = TRUE;
xf86Msg(X_CONFIG, "XKB: variant: \"%s\"\n", s);
}
if ((s = xf86SetStrOption(pIDev->commonOptions, "XkbOptions",
NULL))) {
xf86Info.xkboptions = NULL_IF_EMPTY(s);
xf86Info.xkbcomponents_specified = TRUE;
xf86Msg(X_CONFIG, "XKB: options: \"%s\"\n", s);
}
}
}
#undef NULL_IF_EMPTY
#endif
#if defined(SVR4) && defined(i386)
if ((xf86Info.panix106 =
xf86SetBoolOption(pIDev->commonOptions, "Panix106", FALSE))) {
xf86Msg(X_CONFIG, "PANIX106: enabled\n");
}
#endif
/*
* This was once a compile time option (ASSUME_CUSTOM_KEYCODES)
* defaulting to 1 on Linux/PPC. It is no longer necessary, but for
* backwards compatibility we provide 'Option "CustomKeycodes"'
* and try to autoprobe on Linux/PPC.
*/
from = X_DEFAULT;
verb = 2;
#if defined(__linux__) && defined(__powerpc__)
{
FILE *f;
f = fopen("/proc/sys/dev/mac_hid/keyboard_sends_linux_keycodes","r");
if (f) {
if (fgetc(f) == '0') {
customKeycodesDefault = TRUE;
from = X_PROBED;
verb = 1;
}
fclose(f);
}
}
#endif
if (xf86FindOption(pIDev->commonOptions, "CustomKeycodes")) {
from = X_CONFIG;
verb = 1;
}
xf86Info.kbdCustomKeycodes =
xf86SetBoolOption(pIDev->commonOptions, "CustomKeycodes",
customKeycodesDefault);
xf86MsgVerb(from, verb, "Keyboard: CustomKeycode %s.\n",
xf86Info.kbdCustomKeycodes ? "enabled" : "disabled");
return TRUE;
}
/*
* Locate the core input devices. These can be specified/located in
* the following ways, in order of priority:
*
* 1. The InputDevices named by the -pointer and -keyboard command line
* options.
* 2. The "CorePointer" and "CoreKeyboard" InputDevices referred to by
* the active ServerLayout.
* 3. The first InputDevices marked as "CorePointer" and "CoreKeyboard".
* 4. The first InputDevices that use the 'mouse' and 'keyboard' or 'kbd'
* drivers.
* 5. Default devices with an empty (default) configuration. These defaults
* will reference the 'mouse' and 'keyboard' drivers.
*/
static Bool
checkCoreInputDevices(ConfigHandle handle, serverLayoutPtr pServerLayout,
Bool implicitLayout)
{
int i, j, n;
IDevPtr corePointer = NULL, coreKeyboard = NULL;
Bool foundPointer = FALSE, foundKeyboard = FALSE;
const char *pointerMsg = NULL, *keyboardMsg = NULL;
IDevPtr indp, pIDev = NULL;
XF86ConfInputRec defPtr, defKbd;
pointer opt1 = NULL, opt2 = NULL;
/*
* First check if a core pointer or core keyboard have been specified
* in the active ServerLayout. If more than one is specified for either,
* remove the core attribute from the later ones.
*/
for (i = 0; i < pServerLayout->numInputs; i++) {
indp = pServerLayout->inputDevs[i];
if (!indp)
continue;
opt1 = opt2 = NULL;
if (indp->commonOptions &&
xf86CheckBoolOption(indp->commonOptions, "CorePointer", FALSE)) {
opt1 = indp->commonOptions;
}
if (indp->extraOptions &&
xf86CheckBoolOption(indp->extraOptions, "CorePointer", FALSE)) {
opt2 = indp->extraOptions;
}
if (opt1 || opt2) {
if (!corePointer) {
corePointer = indp;
corePointer->from = X_CONFIG;
} else {
if (opt1)
xf86ReplaceBoolOption(opt1, "CorePointer", FALSE);
if (opt2)
xf86ReplaceBoolOption(opt2, "CorePointer", FALSE);
xf86Msg(X_WARNING, "Duplicate core pointer devices. "
"Removing core pointer attribute from \"%s\".\n",
indp->identifier);
}
}
opt1 = opt2 = NULL;
if (indp->commonOptions &&
xf86CheckBoolOption(indp->commonOptions, "CoreKeyboard", FALSE)) {
opt1 = indp->commonOptions;
}
if (indp->extraOptions &&
xf86CheckBoolOption(indp->extraOptions, "CoreKeyboard", FALSE)) {
opt2 = indp->extraOptions;
}
if (opt1 || opt2) {
if (!coreKeyboard) {
coreKeyboard = indp;
coreKeyboard->from = X_CONFIG;
} else {
if (opt1)
xf86ReplaceBoolOption(opt1, "CoreKeyboard", FALSE);
if (opt2)
xf86ReplaceBoolOption(opt2, "CoreKeyboard", FALSE);
xf86Msg(X_WARNING, "Duplicate core keyboard devices. "
"Removing core keyboard attribute from \"%s\".\n",
indp->identifier);
}
}
}
/* 1. Check for the -pointer command line option. */
if (xf86PointerName) {
pIDev = xf86ConfGetInputDeviceByName(handle, xf86PointerName);
if (!pIDev) {
xf86Msg(X_ERROR, "No InputDevice section called \"%s\".\n",
xf86PointerName);
return FALSE;
}
pIDev->from = X_CMDLINE;
/*
* If one was already specified in the ServerLayout, it needs to be
* removed.
*/
if (corePointer) {
for (i = 0; i < pServerLayout->numInputs; i++) {
indp = pServerLayout->inputDevs[i];
if (indp == corePointer) {
xf86ConfFreeInputDeviceData(indp);
pServerLayout->numInputs--;
for (j = i; j < pServerLayout->numInputs; j++) {
pServerLayout->inputDevs[j] =
pServerLayout->inputDevs[j + 1];
}
pServerLayout->inputDevs[j] = NULL;
break;
}
}
}
corePointer = NULL;
foundPointer = TRUE;
}
/* 2. ServerLayout-specified core pointer. */
if (corePointer) {
foundPointer = TRUE;
corePointer->from = X_CONFIG;
}
/* 3. First core pointer device. */
if (!foundPointer) {
pIDev = xf86ConfGetInputDeviceByOption(handle, "CorePointer");
if (pIDev) {
foundPointer = TRUE;
pIDev->from = X_DEFAULT;
pointerMsg = "first core pointer device";
}
}
/*
* 4. First pointer named CONF_IMPLICIT_POINTER or with 'mouse' as
* the driver.
*/
if (!foundPointer) {
pIDev = xf86ConfGetInputDeviceByName(handle, CONF_IMPLICIT_POINTER);
if (!pIDev)
pIDev = xf86ConfGetInputDeviceByDriver(handle, "mouse");
if (pIDev) {
foundPointer = TRUE;
pIDev->from = X_DEFAULT;
pointerMsg = "first mouse device";
}
}
/* 5. Built-in default. */
if (!foundPointer) {
bzero(&defPtr, sizeof(defPtr));
defPtr.inp_identifier = xstrdup("<default pointer>");
defPtr.inp_driver = xstrdup("mouse");
pIDev = xf86ConfAllocInputDevice();
if (pIDev) {
if (!convertInputDevice(pIDev, &defPtr)) {
xfree(pIDev);
pIDev = NULL;
} else {
foundPointer = TRUE;
pIDev->from = X_DEFAULT;
pointerMsg = "default mouse configuration";
}
}
}
/* Add the core pointer device to the layout, and set it to Core. */
if (foundPointer && pIDev) {
IDevPtr *newDevs;
char **newNames;
pointer *newOpts;
n = pServerLayout->numInputs++;
newDevs = xrealloc(pServerLayout->inputDevs,
pServerLayout->numInputs * sizeof(*newDevs));
if (!newDevs) {
xf86Msg(X_ERROR, "Allocation of new input device list failed.\n");
return FALSE;
}
pServerLayout->inputDevs = newDevs;
newNames = xrealloc(pServerLayout->inputNames,
pServerLayout->numInputs * sizeof(newDevs));
if (!newNames) {
xf86Msg(X_ERROR, "Allocation of new input device list failed.\n");
return FALSE;
}
pServerLayout->inputNames = newNames;
newOpts = xrealloc(pServerLayout->inputExtraOptions,
pServerLayout->numInputs * sizeof(*newOpts));
if (!newOpts) {
xf86Msg(X_ERROR, "Allocation of new input device list failed.\n");
return FALSE;
}
pServerLayout->inputExtraOptions = newOpts;
pIDev->extraOptions = xf86addNewOption(NULL, "CorePointer", NULL);
pServerLayout->inputDevs[n] = pIDev;
pServerLayout->inputNames[n] = xstrdup(pIDev->identifier);
pServerLayout->inputExtraOptions[n] =
xf86OptionListDup(pIDev->extraOptions);
pIDev = NULL;
}
if (!foundPointer) {
/* This shouldn't happen. */
xf86Msg(X_ERROR, "Cannot locate a core pointer device.\n");
return FALSE;
}
/* 1. Check for the -keyboard command line option. */
if (xf86KeyboardName) {
pIDev = xf86ConfGetInputDeviceByName(handle, xf86KeyboardName);
if (!pIDev) {
xf86Msg(X_ERROR, "No InputDevice section called \"%s\".\n",
xf86KeyboardName);
return FALSE;
}
pIDev->from = X_CMDLINE;
/*
* If one was already specified in the ServerLayout, it needs to be
* removed.
*/
if (coreKeyboard) {
for (i = 0; i < pServerLayout->numInputs; i++) {
indp = pServerLayout->inputDevs[i];
if (indp == coreKeyboard) {
xf86ConfFreeInputDeviceData(indp);
pServerLayout->numInputs--;
for (j = i; j < pServerLayout->numInputs; j++) {
pServerLayout->inputDevs[j] =
pServerLayout->inputDevs[j + 1];
}
pServerLayout->inputDevs[j] = NULL;
break;
}
}
}
coreKeyboard = NULL;
foundKeyboard = TRUE;
}
/* 2. ServerLayout-specified core keyboard. */
if (coreKeyboard) {
foundKeyboard = TRUE;
coreKeyboard->from = X_CONFIG;
}
/* 3. First core keyboard device. */
if (!foundKeyboard) {
pIDev = xf86ConfGetInputDeviceByOption(handle, "CoreKeyboard");
if (pIDev) {
foundKeyboard = TRUE;
pIDev->from = X_DEFAULT;
keyboardMsg = "first core keyboard device";
}
}
/*
* 4. First keyboard named CONF_IMPLICIT_KEYBOARD, or with 'keyboard'
* or 'kbd' as the driver.
*/
if (!foundKeyboard) {
pIDev = xf86ConfGetInputDeviceByName(handle, CONF_IMPLICIT_KEYBOARD);
if (!pIDev)
pIDev = xf86ConfGetInputDeviceByDriver(handle, "keyboard");
if (!pIDev)
pIDev = xf86ConfGetInputDeviceByDriver(handle, "kbd");
if (pIDev) {
foundKeyboard = TRUE;
pIDev->from = X_DEFAULT;
keyboardMsg = "first keyboard device";
}
}
/* 5. Built-in default. */
if (!foundKeyboard) {
bzero(&defKbd, sizeof(defKbd));
defKbd.inp_identifier = xstrdup("<default keyboard>");
defKbd.inp_driver = xstrdup("keyboard");
pIDev = xf86ConfAllocInputDevice();
if (pIDev) {
if (!convertInputDevice(pIDev, &defKbd)) {
xfree(pIDev);
pIDev = NULL;
} else {
foundKeyboard = TRUE;
pIDev->from = X_DEFAULT;
keyboardMsg = "default keyboard configuration";
}
}
}
/* Add the core keyboard device to the layout, and set it to Core. */
if (foundKeyboard && pIDev) {
if (!xf86NameCmp(pIDev->driver, "keyboard"))
foundKeyboard = configInputKbd(pIDev);
if (foundKeyboard) {
IDevPtr *newDevs;
char **newNames;
pointer *newOpts;
n = pServerLayout->numInputs++;
newDevs = xrealloc(pServerLayout->inputDevs,
pServerLayout->numInputs * sizeof(*newDevs));
if (!newDevs) {
xf86Msg(X_ERROR,
"Allocation of new input device list failed.\n");
return FALSE;
}
pServerLayout->inputDevs = newDevs;
newNames = xrealloc(pServerLayout->inputNames,
pServerLayout->numInputs * sizeof(newDevs));
if (!newNames) {
xf86Msg(X_ERROR,
"Allocation of new input device list failed.\n");
return FALSE;
}
pServerLayout->inputNames = newNames;
newOpts = xrealloc(pServerLayout->inputExtraOptions,
pServerLayout->numInputs * sizeof(*newOpts));
if (!newOpts) {
xf86Msg(X_ERROR,
"Allocation of new input device list failed.\n");
return FALSE;
}
pServerLayout->inputExtraOptions = newOpts;
pIDev->extraOptions = xf86addNewOption(NULL, "CoreKeyboard", NULL);
pServerLayout->inputDevs[n] = pIDev;
pServerLayout->inputNames[n] = xstrdup(pIDev->identifier);
pServerLayout->inputExtraOptions[n] =
xf86OptionListDup(pIDev->extraOptions);
pIDev = NULL;
}
}
if (!foundKeyboard) {
/* This shouldn't happen. */
xf86Msg(X_ERROR, "Cannot locate a core keyboard device.\n");
return FALSE;
}
if (pointerMsg) {
xf86Msg(X_WARNING, "The core pointer device wasn't specified "
"explicitly in the layout.\n"
"\tUsing the %s.\n", pointerMsg);
}
if (keyboardMsg) {
xf86Msg(X_WARNING, "The core keyboard device wasn't specified "
"explicitly in the layout.\n"
"\tUsing the %s.\n", keyboardMsg);
}
return TRUE;
}
screenLayoutPtr
xf86ConfAllocScreenLayout()
{
screenLayoutPtr pScreenLayout;
pScreenLayout = xcalloc(1, sizeof(*pScreenLayout));
pScreenLayout->where = PosAbsolute;
pScreenLayout->x = -1;
pScreenLayout->y = -1;
return pScreenLayout;
}
void
xf86ConfFreeScreenLayoutData(screenLayoutPtr pScreenLayout)
{
if (!pScreenLayout)
return;
if (pScreenLayout->screen) {
xf86ConfFreeScreenData(pScreenLayout->screen);
pScreenLayout->screen = NULL;
}
if (pScreenLayout->refname) {
xfree(pScreenLayout->refname);
pScreenLayout->refname = NULL;
}
if (pScreenLayout->screenName) {
xfree(pScreenLayout->screenName);
pScreenLayout->screenName = NULL;
}
pScreenLayout->refscreen = NULL;
}
screenLayoutPtr
xf86ConfDupScreenLayout(const screenLayoutRec *pScreenLayout, int depth)
{
screenLayoutPtr s;
if (!pScreenLayout)
return NULL;
s = xf86ConfAllocScreenLayout();
if (!s)
return NULL;
s->screenName = xstrdup(pScreenLayout->screenName);
if (pScreenLayout->screenName && !s->screenName) {
xf86ConfFreeScreenLayoutData(s);
xfree(s);
return NULL;
}
s->screenNum = pScreenLayout->screenNum;
s->x = pScreenLayout->x;
s->y = pScreenLayout->y;
s->refname = xstrdup(pScreenLayout->refname);
if (pScreenLayout->refname && !s->refname) {
xf86ConfFreeScreenLayoutData(s);
xfree(s);
return NULL;
}
s->where = pScreenLayout->where;
if (depth > 0) {
s->screen = xf86ConfDupScreen(pScreenLayout->screen, depth - 1);
s->refscreen = pScreenLayout->refscreen;
}
return s;
}
static screenLayoutPtr
convertScreenLayout(screenLayoutPtr pScreenLayout,
const XF86ConfAdjacencyRec *adjacency)
{
if (!pScreenLayout)
return NULL;
pScreenLayout->screenName = xstrdup(adjacency->adj_screen_str);
if (adjacency->adj_screen_str && !pScreenLayout->screenName) {
xf86ConfFreeScreenLayoutData(pScreenLayout);
return NULL;
}
pScreenLayout->screenNum = adjacency->adj_scrnum;
pScreenLayout->x = adjacency->adj_x;
pScreenLayout->y = adjacency->adj_y;
pScreenLayout->refname = xstrdup(adjacency->adj_refscreen);
if (adjacency->adj_refscreen && !pScreenLayout->refname) {
xf86ConfFreeScreenLayoutData(pScreenLayout);
return NULL;
}
switch (adjacency->adj_where) {
case CONF_ADJ_ABSOLUTE:
pScreenLayout->where = PosAbsolute;
break;
case CONF_ADJ_RIGHTOF:
pScreenLayout->where = PosRightOf;
break;
case CONF_ADJ_LEFTOF:
pScreenLayout->where = PosLeftOf;
break;
case CONF_ADJ_ABOVE:
pScreenLayout->where = PosAbove;
break;
case CONF_ADJ_BELOW:
pScreenLayout->where = PosBelow;
break;
case CONF_ADJ_RELATIVE:
pScreenLayout->where = PosRelative;
break;
case CONF_ADJ_OBSOLETE:
xf86Msg(X_ERROR,
"Obsolete screen layout encountered for screen \"%s\".\n"
"\tThis is no longer supported. "
"Default positioning will be used.\n",
pScreenLayout->screenName);
pScreenLayout->where = PosAbsolute;
pScreenLayout->x = -1;
pScreenLayout->y = -1;
break;
}
return pScreenLayout;
}
serverLayoutPtr
xf86ConfAllocServerLayout()
{
serverLayoutPtr pServerLayout;
pServerLayout = xcalloc(1, sizeof(*pServerLayout));
pServerLayout->handle = pServerLayout;
pServerLayout->from = X_NONE;
return pServerLayout;
}
void
xf86ConfFreeServerLayoutData(serverLayoutPtr pServerLayout)
{
int i;
if (!pServerLayout)
return;
if (pServerLayout->screenLayouts) {
for (i = 0; i < pServerLayout->numScreens; i++) {
xf86ConfFreeScreenLayoutData(pServerLayout->screenLayouts[i]);
xfree(pServerLayout->screenLayouts[i]);
pServerLayout->screenLayouts[i] = NULL;
}
xfree(pServerLayout->screenLayouts);
pServerLayout->screenLayouts = NULL;
}
pServerLayout->numScreens = 0;
if (pServerLayout->inactiveNames) {
for (i = 0; i < pServerLayout->numInactives; i++) {
xfree(pServerLayout->inactiveNames[i]);
pServerLayout->inactiveNames[i] = NULL;
}
xfree(pServerLayout->inactiveNames);
pServerLayout->inactiveNames = NULL;
}
if (pServerLayout->inactiveDevs) {
for (i = 0; i < pServerLayout->numInactives; i++) {
xf86ConfFreeGraphicsDeviceData(pServerLayout->inactiveDevs[i]);
xfree(pServerLayout->inactiveDevs[i]);
pServerLayout->inactiveDevs[i] = NULL;
}
xfree(pServerLayout->inactiveDevs);
pServerLayout->inactiveDevs = NULL;
}
pServerLayout->numInactives = 0;
if (pServerLayout->inputNames) {
for (i = 0; i < pServerLayout->numInputs; i++) {
xfree(pServerLayout->inputNames[i]);
pServerLayout->inputNames[i] = NULL;
}
xfree(pServerLayout->inputNames);
pServerLayout->inputNames = NULL;
}
if (pServerLayout->inputExtraOptions) {
for (i = 0; i < pServerLayout->numInputs; i++) {
xf86OptionListFree(pServerLayout->inputExtraOptions[i]);
pServerLayout->inputExtraOptions[i] = NULL;
}
xfree(pServerLayout->inputExtraOptions);
pServerLayout->inputExtraOptions = NULL;
}
if (pServerLayout->inputDevs) {
for (i = 0; i < pServerLayout->numInputs; i++) {
xf86ConfFreeInputDeviceData(pServerLayout->inputDevs[i]);
xfree(pServerLayout->inputDevs[i]);
pServerLayout->inputDevs[i] = NULL;
}
xfree(pServerLayout->inputDevs);
pServerLayout->inputDevs = NULL;
}
pServerLayout->numInputs = 0;
if (pServerLayout->id) {
xfree(pServerLayout->id);
pServerLayout->id = NULL;
}
if (pServerLayout->options) {
xf86OptionListFree(pServerLayout->options);
pServerLayout->options = NULL;
}
}
serverLayoutPtr
xf86ConfDupServerLayout(const serverLayoutRec *pServerLayout, int depth)
{
serverLayoutPtr s;
int i;
if (!pServerLayout)
return NULL;
s = xf86ConfAllocServerLayout();
if (!s)
return NULL;
s->handle = pServerLayout->handle;
s->from = pServerLayout->from;
s->numScreens = pServerLayout->numScreens;
if (s->numScreens > 0) {
s->screenLayouts = xcalloc(s->numScreens, sizeof(screenLayoutPtr));
if (!s->screenLayouts) {
xfree(s);
return NULL;
}
for (i = 0; i < s->numScreens; i++) {
s->screenLayouts[i] =
xf86ConfDupScreenLayout(pServerLayout->screenLayouts[i], depth);
if (!s->screenLayouts[i]) {
xf86ConfFreeServerLayoutData(s);
xfree(s);
return NULL;
}
}
}
s->numInactives = pServerLayout->numInactives;
if (s->numInactives > 0) {
s->inactiveNames = xf86DupStringArray(pServerLayout->inactiveNames,
pServerLayout->numInactives);
if (pServerLayout->inactiveNames && !s->inactiveNames) {
xf86ConfFreeServerLayoutData(s);
xfree(s);
return NULL;
}
if (depth > 0) {
s->inactiveDevs = xcalloc(s->numInactives, sizeof(GDevPtr));
if (!s->inactiveDevs) {
xf86ConfFreeServerLayoutData(s);
xfree(s);
return NULL;
}
for (i = 0; i < s->numInactives; i++) {
s->inactiveDevs[i] =
xf86ConfDupGraphicsDevice(pServerLayout->inactiveDevs[i]);
if (pServerLayout->inactiveDevs[i] && !s->inactiveDevs[i]) {
xf86ConfFreeServerLayoutData(s);
xfree(s);
return NULL;
}
}
}
}
s->numInputs = pServerLayout->numInputs;
if (s->numInputs > 0) {
s->inputNames = xf86DupStringArray(pServerLayout->inputNames,
pServerLayout->numInputs);
if (pServerLayout->inputNames && !s->inputNames) {
xf86ConfFreeServerLayoutData(s);
xfree(s);
return NULL;
}
if (pServerLayout->inputExtraOptions) {
s->inputExtraOptions = xcalloc(s->numInputs, sizeof(pointer));
if (!s->inputExtraOptions) {
xf86ConfFreeServerLayoutData(s);
xfree(s);
return NULL;
}
for (i = 0; i < s->numInputs; i++) {
s->inputExtraOptions[i] =
xf86OptionListDup(pServerLayout->inputExtraOptions[i]);
if (pServerLayout->inputExtraOptions[i] &&
!s->inputExtraOptions[i]) {
xf86ConfFreeServerLayoutData(s);
xfree(s);
return NULL;
}
}
}
if (depth > 0) {
s->inputDevs = xcalloc(s->numInputs, sizeof(IDevPtr));
if (!s->inputDevs) {
xf86ConfFreeServerLayoutData(s);
xfree(s);
return NULL;
}
for (i = 0; i < s->numInputs; i++) {
s->inputDevs[i] =
xf86ConfDupInputDevice(pServerLayout->inputDevs[i], depth);
if (pServerLayout->inputDevs[i] && !s->inputDevs[i]) {
xf86ConfFreeServerLayoutData(s);
xfree(s);
return NULL;
}
}
}
}
s->id = xstrdup(pServerLayout->id);
if (pServerLayout->id && !s->id) {
xf86ConfFreeServerLayoutData(s);
xfree(s);
return NULL;
}
s->options = xf86OptionListDup(pServerLayout->options);
if (pServerLayout->options && !s->options) {
xf86ConfFreeServerLayoutData(s);
xfree(s);
return NULL;
}
return s;
}
/*
* Convert a ServerLayout section from the parser's format to the server's
* format.
*/
static serverLayoutPtr
convertServerLayout(serverLayoutPtr pServerLayout,
const XF86ConfLayoutRec *confLayout)
{
XF86ConfAdjacencyPtr adjp;
XF86ConfInactivePtr idp;
XF86ConfInputrefPtr irp;
int count = 0;
if (!pServerLayout || !confLayout)
return NULL;
pServerLayout->handle = confLayout;
adjp = confLayout->lay_adjacency_lst;
/*
* We know that each screen is referenced exactly once on the left side
* of a Screen statement in the ServerLayout section. So to allocate
* the right size for the array we do a quick walk of the list to figure
* out how many screens we have.
*/
while (adjp) {
count++;
adjp = adjp->list.next;
}
pServerLayout->numScreens = count;
xf86MsgVerb(X_INFO, 5, "Found %d screen%s in the layout section \"%s\".\n",
count, PLURAL(count), confLayout->lay_identifier);
if (count) {
pServerLayout->screenLayouts = xcalloc(count, sizeof(screenLayoutPtr));
if (!pServerLayout->screenLayouts)
return NULL;
adjp = confLayout->lay_adjacency_lst;
count = 0;
while (adjp) {
pServerLayout->screenLayouts[count] = xf86ConfAllocScreenLayout();
if (!pServerLayout->screenLayouts[count]) {
xf86ConfFreeServerLayoutData(pServerLayout);
return NULL;
}
if (!convertScreenLayout(pServerLayout->screenLayouts[count],
adjp)) {
xf86ConfFreeServerLayoutData(pServerLayout);
return NULL;
}
if (pServerLayout->screenLayouts[count]->screenNum < 0)
pServerLayout->screenLayouts[count]->screenNum = count;
count++;
adjp = adjp->list.next;
}
}
/*
* Count the number of inactive devices.
* XXX Do we still need these?
*/
count = 0;
idp = confLayout->lay_inactive_lst;
while (idp) {
count++;
idp = idp->list.next;
}
pServerLayout->numInactives = count;
xf86MsgVerb(X_INFO, 5,
"Found %d inactive device%s in the layout section \"%s\".\n",
count, PLURAL(count), confLayout->lay_identifier);
if (count > 0) {
pServerLayout->inactiveNames = xcalloc(count, sizeof(char *));
if (!pServerLayout->inactiveNames) {
xf86ConfFreeServerLayoutData(pServerLayout);
return NULL;
}
count = 0;
while (idp) {
pServerLayout->inactiveNames[count] =
xstrdup(idp->inactive_device_str);
if (idp->inactive_device_str &&
!pServerLayout->inactiveNames[count]) {
xf86ConfFreeServerLayoutData(pServerLayout);
return NULL;
}
count++;
idp = idp->list.next;
}
}
/*
* Count the number of input devices.
*/
count = 0;
irp = confLayout->lay_input_lst;
while (irp) {
count++;
irp = irp->list.next;
}
pServerLayout->numInputs = count;
xf86MsgVerb(X_INFO, 5,
"Found %d input device%s in the layout section \"%s\".\n",
count, PLURAL(count), confLayout->lay_identifier);
if (count > 0) {
pServerLayout->inputNames = xcalloc(count, sizeof(char *));
if (!pServerLayout->inputNames) {
xf86ConfFreeServerLayoutData(pServerLayout);
return NULL;
}
pServerLayout->inputExtraOptions = xcalloc(count, sizeof(pointer));
if (!pServerLayout->inputExtraOptions) {
xf86ConfFreeServerLayoutData(pServerLayout);
return NULL;
}
count = 0;
irp = confLayout->lay_input_lst;
while (irp) {
pServerLayout->inputNames[count] = xstrdup(irp->iref_inputdev_str);
if (irp->iref_inputdev_str && !pServerLayout->inputNames[count]) {
xf86ConfFreeServerLayoutData(pServerLayout);
return NULL;
}
pServerLayout->inputExtraOptions[count] =
xf86OptionListDup(irp->iref_option_lst);
if (irp->iref_option_lst &&
!pServerLayout->inputExtraOptions[count]) {
xf86ConfFreeServerLayoutData(pServerLayout);
return NULL;
}
count++;
irp = irp->list.next;
}
}
pServerLayout->id = xstrdup(confLayout->lay_identifier);
if (confLayout->lay_identifier && !pServerLayout->id) {
xf86ConfFreeServerLayoutData(pServerLayout);
return NULL;
}
pServerLayout->options = xf86OptionListDup(confLayout->lay_option_lst);
if (confLayout->lay_option_lst && !pServerLayout->options) {
xf86ConfFreeServerLayoutData(pServerLayout);
return NULL;
}
return pServerLayout;
}
serverLayoutPtr
xf86ConfGetServerLayoutByName(ConfigHandle handle, const char *name, int depth)
{
const XF86ConfigRec *pConfig;
XF86ConfLayoutPtr l;
serverLayoutPtr pServerLayout = NULL;
if (!name)
return NULL;
pConfig = ConfigHandleToConfigRead(handle);
for (l = pConfig->conf_layout_lst; l; l = l->list.next) {
if (xf86nameCompare(l->lay_identifier, name) == 0) {
break;
}
}
if (l) {
pServerLayout = xf86ConfAllocServerLayout();
if (pServerLayout) {
if (!convertServerLayout(pServerLayout, l)) {
xfree(pServerLayout);
return NULL;
}
if (depth > 0) {
if (!xf86ConfResolveServerLayout(handle,
pServerLayout, depth)) {
xf86ConfFreeServerLayoutData(pServerLayout);
xfree(pServerLayout);
return NULL;
}
}
return pServerLayout;
}
}
return NULL;
}
serverLayoutPtr
xf86ConfGetNextServerLayout(ConfigHandle handle,
ConfigDataHandle prevLayoutHandle, int depth)
{
const XF86ConfigRec *pConfig;
XF86ConfLayoutPtr l;
serverLayoutPtr pServerLayout = NULL;
/* The special active case. */
if (handle == ACTIVE_CONFIG) {
if (!prevLayoutHandle)
return xf86ConfDupServerLayout(xf86Info.serverLayout, depth);
else
return NULL;
}
pConfig = ConfigHandleToConfigRead(handle);
if (!prevLayoutHandle) {
l = pConfig->conf_layout_lst;
} else {
for (l = pConfig->conf_layout_lst; l; l = l->list.next) {
if (l == prevLayoutHandle) {
l = l->list.next;
break;
}
}
}
if (l) {
pServerLayout = xf86ConfAllocServerLayout();
if (pServerLayout) {
if (!convertServerLayout(pServerLayout, l)) {
xfree(pServerLayout);
return NULL;
}
if (depth > 0) {
if (!xf86ConfResolveServerLayout(handle,
pServerLayout, depth)) {
xf86ConfFreeServerLayoutData(pServerLayout);
xfree(pServerLayout);
return NULL;
}
}
return pServerLayout;
}
}
return NULL;
}
static void
resolveServerLayoutCleanup(serverLayoutPtr pServerLayout)
{
int i;
if (pServerLayout->screenLayouts) {
for (i = 0; i < pServerLayout->numScreens; i++) {
if (pServerLayout->screenLayouts[i]) {
xf86ConfFreeScreenData(pServerLayout->screenLayouts[i]->screen);
pServerLayout->screenLayouts[i]->screen = NULL;
}
}
}
if (pServerLayout->inactiveDevs) {
for (i = 0; i < pServerLayout->numInactives; i++) {
xf86ConfFreeGraphicsDeviceData(pServerLayout->inactiveDevs[i]);
pServerLayout->inactiveDevs[i] = NULL;
}
xfree(pServerLayout->inactiveDevs);
}
if (pServerLayout->inputDevs) {
for (i = 0; i < pServerLayout->numInputs; i++) {
xf86ConfFreeInputDeviceData(pServerLayout->inputDevs[i]);
pServerLayout->inputDevs[i] = NULL;
}
xfree(pServerLayout->inputDevs);
}
}
serverLayoutPtr
xf86ConfResolveServerLayout(ConfigHandle handle, serverLayoutPtr pServerLayout,
int depth)
{
screenLayoutPtr *ppScreenLayout;
int i = 0, j;
if (!pServerLayout || depth < 1)
return pServerLayout;
resolveServerLayoutCleanup(pServerLayout);
if (!pServerLayout->screenLayouts)
return pServerLayout;
ppScreenLayout = pServerLayout->screenLayouts;
for (i = 0; i < pServerLayout->numScreens; i++) {
if (!ppScreenLayout[i]->screenName)
continue;
ppScreenLayout[i]->screen =
xf86ConfGetScreenByName(handle, ppScreenLayout[i]->screenName,
depth - 1);
if (!ppScreenLayout[i]->screen)
continue;
ppScreenLayout[i]->screen->screennum = ppScreenLayout[i]->screenNum;
}
/* Fill in the refscreen value. */
for (i = 0; i < pServerLayout->numScreens; i++) {
for (j = 0; j < pServerLayout->numScreens; j++) {
if (ppScreenLayout[i]->refname &&
strcmp(ppScreenLayout[i]->refname,
ppScreenLayout[j]->screenName) == 0) {
ppScreenLayout[i]->refscreen = ppScreenLayout[j]->screen;
}
}
if (ppScreenLayout[i]->where != PosAbsolute &&
!ppScreenLayout[i]->refscreen) {
xf86Msg(X_WARNING,
"Screen \"%s\" doesn't exist: deleting placement.\n",
ppScreenLayout[i]->refname);
ppScreenLayout[i]->where = PosAbsolute;
ppScreenLayout[i]->x = -1;
ppScreenLayout[i]->y = -1;
}
}
/* Inactive devices. */
if (pServerLayout->numInactives > 0 && pServerLayout->inactiveNames) {
pServerLayout->inactiveDevs =
xcalloc(pServerLayout->numInactives, sizeof(GDevPtr));
if (!pServerLayout->inactiveDevs) {
resolveServerLayoutCleanup(pServerLayout);
return NULL;
}
for (i = 0; i < pServerLayout->numInactives; i++) {
if (!pServerLayout->inactiveNames[i])
continue;
pServerLayout->inactiveDevs[i] =
xf86ConfGetGraphicsDeviceByName(handle,
pServerLayout->inactiveNames[i]);
}
}
/* Input devices. */
if (pServerLayout->numInputs > 0 && pServerLayout->inputNames) {
pServerLayout->inputDevs =
xcalloc(pServerLayout->numInputs, sizeof(IDevPtr));
if (!pServerLayout->inputDevs) {
resolveServerLayoutCleanup(pServerLayout);
return NULL;
}
for (i = 0; i < pServerLayout->numInputs; i++) {
if (!pServerLayout->inputNames[i])
continue;
pServerLayout->inputDevs[i] =
xf86ConfGetInputDeviceByName(handle,
pServerLayout->inputNames[i]);
if (!pServerLayout->inputDevs[i])
continue;
if (pServerLayout->inputExtraOptions) {
pServerLayout->inputDevs[i]->extraOptions =
xf86OptionListDup(pServerLayout->inputExtraOptions[i]);
if (pServerLayout->inputExtraOptions[i] &&
!pServerLayout->inputDevs[i]->extraOptions) {
resolveServerLayoutCleanup(pServerLayout);
return NULL;
}
}
}
}
return pServerLayout;
}
int
xf86ConfCheckResolvedServerLayout(const serverLayoutRec *pServerLayout,
int depth, Bool strict)
{
int i;
Bool failures = 0;
screenLayoutPtr *ppScreenLayout;
if (!pServerLayout || depth < 1)
return 0;
ppScreenLayout = pServerLayout->screenLayouts;
for (i = 0; i < pServerLayout->numScreens; i++) {
if (!ppScreenLayout[i]->screenName)
continue;
if (ppScreenLayout[i]->screen) {
failures +=
xf86ConfCheckResolvedScreen(ppScreenLayout[i]->screen,
depth - 1, strict);
} else {
xf86Msg(X_ERROR, "No Screen \"%s\" "
"(referenced by ServerLayout \"%s\").\n",
ppScreenLayout[i]->screenName, pServerLayout->id);
failures++;
}
}
if (strict && pServerLayout->numScreens == 0) {
xf86Msg(X_ERROR, "No Screen references in ServerLayout \"%s\".\n",
pServerLayout->id);
failures++;
}
if (pServerLayout->numInactives > 0 && pServerLayout->inactiveNames) {
for (i = 0; i < pServerLayout->numInactives; i++) {
if (!pServerLayout->inactiveNames[i])
continue;
if (!pServerLayout->inactiveDevs[i]) {
xf86Msg(X_ERROR, "No Device \"%s\" "
"(referenced by ServerLayout \"%s\").\n",
pServerLayout->inactiveNames[i], pServerLayout->id);
failures++;
}
}
}
if (pServerLayout->numInputs > 0 && pServerLayout->inputNames) {
for (i = 0; i < pServerLayout->numInputs; i++) {
if (!pServerLayout->inputNames[i])
continue;
if (!pServerLayout->inputDevs[i]) {
xf86Msg(X_ERROR, "No Input Device \"%s\" "
"(referenced by ServerLayout \"%s\").\n",
pServerLayout->inputNames[i], pServerLayout->id);
failures++;
}
}
} else if (strict) {
xf86Msg(X_ERROR, "No Input Device references in ServerLayout \"%s\".\n",
pServerLayout->id);
failures++;
}
return failures;
}
/*
* Figure out which layout is active, and fill in the config data for
* everything that it references.
*/
static serverLayoutPtr
configServerLayout(ConfigHandle handle, char *defaultLayout)
{
int i;
const char *name = NULL;
serverLayoutPtr pServerLayout;
/*
* Find the active ServerLayout section. The order of priority is:
*
* 1. Name specified by the -layout command line option.
* 2. Name specified by the DefaultServerLayout config option.
* 3. The first ServerLayout section.
*/
if (xf86LayoutName)
name = xf86LayoutName;
else if (defaultLayout)
name = defaultLayout;
if (name) {
pServerLayout = xf86ConfGetServerLayoutByName(handle, name,
CONFIG_RESOLVE_ALL);
if (!pServerLayout) {
xf86Msg(X_ERROR, "No ServerLayout section called \"%s\".\n", name);
return NULL;
}
pServerLayout->from = xf86LayoutName ? X_CMDLINE : X_CONFIG;
} else {
pServerLayout = xf86ConfGetNextServerLayout(handle, NULL,
CONFIG_RESOLVE_ALL);
if (!pServerLayout) {
xf86Msg(X_ERROR, "No ServerLayout sections found.\n");
return NULL;
}
pServerLayout->from = X_DEFAULT;
}
if (pServerLayout->numScreens <= 0) {
xf86Msg(X_ERROR, "No Screens in ServerLayout \"%s\".\n",
pServerLayout->id);
xf86ConfFreeServerLayoutData(pServerLayout);
xfree(pServerLayout);
return NULL;
}
/* Special case handling for the built-in keyboard device. */
if (pServerLayout->inputDevs) {
for (i = 0; i < pServerLayout->numInputs; i++) {
IDevPtr pIDev = pServerLayout->inputDevs[i];
if (pIDev && !xf86NameCmp(pIDev->driver, "keyboard")) {
if (!configInputKbd(pIDev)) {
xf86ConfFreeServerLayoutData(pServerLayout);
xfree(pServerLayout);
return NULL;
}
}
}
}
if (!checkCoreInputDevices(handle, pServerLayout, FALSE)) {
xf86ConfFreeServerLayoutData(pServerLayout);
xfree(pServerLayout);
return NULL;
}
return pServerLayout;
}
/*
* No ServerLayout section, so find the first Screen section and set that up as
* the only active screen.
*/
static serverLayoutPtr
configImpliedServerLayout(ConfigHandle handle, const char *screenName)
{
confScreenPtr s;
screenLayoutPtr pScreenLayout;
serverLayoutPtr pServerLayout;
/*
* Find the active Screen section in the absence of a ServerLayout
* section, or when a Screen section is specified explicitly with
* the '-screen' option. The order of priority is:
*
* 1. Name specified by the -screen command line option.
* 2. The first Screen section.
*/
if (screenName) {
s = xf86ConfGetScreenByName(handle, screenName, CONFIG_RESOLVE_ALL);
if (!s) {
xf86Msg(X_ERROR, "No Screen section called \"%s\".\n", screenName);
return NULL;
}
} else {
s = xf86ConfGetNextScreen(handle, NULL, CONFIG_RESOLVE_ALL);
if (!s) {
xf86Msg(X_ERROR, "No Screen sections found.\n");
return NULL;
}
}
pServerLayout = xf86ConfAllocServerLayout();
if (!pServerLayout) {
xf86ConfFreeScreenData(s);
xfree(s);
return NULL;
}
/* With an implied ServerLayout, there is exactly one screen. */
pServerLayout->screenLayouts = xcalloc(1, sizeof(serverLayoutPtr));
if (!pServerLayout->screenLayouts) {
xf86ConfFreeScreenData(s);
xfree(s);
xfree(pServerLayout);
return NULL;
}
pServerLayout->numScreens = 1;
pScreenLayout = xf86ConfAllocScreenLayout();
if (!pScreenLayout) {
xf86ConfFreeScreenData(s);
xfree(s);
xf86ConfFreeServerLayoutData(pServerLayout);
xfree(pServerLayout);
return NULL;
}
pServerLayout->screenLayouts[0] = pScreenLayout;
pScreenLayout->screen = s;
pScreenLayout->screenName = xstrdup(s->id);
if (s->id && !pScreenLayout->screenName) {
xf86ConfFreeServerLayoutData(pServerLayout);
xfree(pServerLayout);
return NULL;
}
pServerLayout->id = xstrdup("(implicit)");
if (!pServerLayout->id) {
xf86ConfFreeServerLayoutData(pServerLayout);
xfree(pServerLayout);
return NULL;
}
pServerLayout->from = X_DEFAULT;
/* Find implied core devices. */
if (!checkCoreInputDevices(handle, pServerLayout, TRUE)) {
xf86ConfFreeServerLayoutData(pServerLayout);
xfree(pServerLayout);
return NULL;
}
return pServerLayout;
}
confXvPortPtr
xf86ConfAllocXvPort()
{
confXvPortPtr pPort;
pPort = xcalloc(1, sizeof(*pPort));
pPort->handle = pPort;
return pPort;
}
void
xf86ConfFreeXvPortData(confXvPortPtr pPort)
{
if (!pPort)
return;
if (pPort->identifier) {
xfree(pPort->identifier);
pPort->identifier = NULL;
}
if (pPort->options) {
xf86OptionListFree(pPort->options);
pPort->options = NULL;
}
}
confXvPortPtr
xf86ConfDupXvPort(const confXvPortRec *pPort)
{
confXvPortPtr p;
if (!pPort)
return NULL;
p = xf86ConfAllocXvPort();
if (!p)
return NULL;
p->handle = pPort->handle;
p->identifier = xstrdup(pPort->identifier);
if (pPort->identifier && !p->identifier) {
xf86ConfFreeXvPortData(p);
xfree(p);
return NULL;
}
p->options = xf86OptionListDup(pPort->options);
if (pPort->options && !p->options) {
xf86ConfFreeXvPortData(p);
xfree(p);
return NULL;
}
return p;
}
static confXvPortPtr
convertXvPort(confXvPortPtr pPort, const XF86ConfVideoPortRec *confPort)
{
if (!pPort || ! confPort)
return NULL;
pPort->handle = confPort;
pPort->identifier = xstrdup(confPort->vp_identifier);
if (confPort->vp_identifier && !pPort->identifier) {
xf86ConfFreeXvPortData(pPort);
return NULL;
}
pPort->options = xf86OptionListDup(confPort->vp_option_lst);
if (confPort->vp_option_lst && !pPort->options) {
xf86ConfFreeXvPortData(pPort);
return NULL;
}
return pPort;
}
confXvAdaptorPtr
xf86ConfAllocXvAdaptor()
{
confXvAdaptorPtr pAdaptor;
pAdaptor = xcalloc(1, sizeof(*pAdaptor));
pAdaptor->handle = pAdaptor;
return pAdaptor;
}
void
xf86ConfFreeXvAdaptorData(confXvAdaptorPtr pAdaptor)
{
int i;
if (!pAdaptor)
return;
if (pAdaptor->identifier) {
xfree(pAdaptor->identifier);
pAdaptor->identifier = NULL;
}
if (pAdaptor->xvPorts) {
for (i = 0; i < pAdaptor->numports; i++) {
xf86ConfFreeXvPortData(pAdaptor->xvPorts[i]);
xfree(pAdaptor->xvPorts[i]);
pAdaptor->xvPorts[i] = NULL;
}
xfree(pAdaptor->xvPorts);
pAdaptor->xvPorts = NULL;
}
pAdaptor->numports = 0;
if (pAdaptor->options) {
xf86OptionListFree(pAdaptor->options);
pAdaptor->options = NULL;
}
}
confXvAdaptorPtr
xf86ConfDupXvAdaptor(const confXvAdaptorRec *pAdaptor)
{
int i;
confXvAdaptorPtr a;
if (!pAdaptor)
return NULL;
a = xf86ConfAllocXvAdaptor();
if (!a)
return NULL;
a->handle = pAdaptor->handle;
a->identifier = xstrdup(pAdaptor->identifier);
if (pAdaptor->identifier && !a->identifier) {
xf86ConfFreeXvAdaptorData(a);
xfree(a);
return NULL;
}
a->options = xf86OptionListDup(pAdaptor->options);
if (pAdaptor->options && !a->options) {
xf86ConfFreeXvAdaptorData(a);
xfree(a);
return NULL;
}
a->numports = pAdaptor->numports;
if (a->numports > 0) {
a->xvPorts = xcalloc(a->numports, sizeof(confXvPortPtr));
if (!a->xvPorts) {
xf86ConfFreeXvAdaptorData(a);
xfree(a);
return NULL;
}
for (i = 0; i < a->numports; i++) {
a->xvPorts[i] = xf86ConfDupXvPort(pAdaptor->xvPorts[i]);
if (pAdaptor->xvPorts[i] && !a->xvPorts[i]) {
xf86ConfFreeXvAdaptorData(a);
xfree(a);
return NULL;
}
}
}
return a;
}
static confXvAdaptorPtr
convertXvAdaptor(confXvAdaptorPtr pAdaptor,
const XF86ConfVideoAdaptorRec *confAdaptor)
{
int count = 0;
XF86ConfVideoPortPtr confPort;
if (!pAdaptor || ! confAdaptor)
return NULL;
pAdaptor->handle = confAdaptor;
pAdaptor->identifier = xstrdup(confAdaptor->va_identifier);
if (confAdaptor->va_identifier && !pAdaptor->identifier) {
xf86ConfFreeXvAdaptorData(pAdaptor);
return NULL;
}
pAdaptor->options = xf86OptionListDup(confAdaptor->va_option_lst);
if (confAdaptor->va_option_lst && !pAdaptor->options) {
xf86ConfFreeXvAdaptorData(pAdaptor);
return NULL;
}
#if 0
if (conf_adaptor->va_busid || conf_adaptor->va_driver) {
xf86Msg(X_CONFIG, "| | Unsupported device type, skipping entry\n");
return FALSE;
}
#endif
/*
* Figure out how many videoport subsections there are and fill them in.
*/
confPort = confAdaptor->va_port_lst;
while (confPort) {
count++;
confPort = confPort->list.next;
}
if (count > 0) {
pAdaptor->xvPorts = xcalloc(count, sizeof(confXvAdaptorPtr));
if (!pAdaptor->xvPorts) {
xf86ConfFreeXvAdaptorData(pAdaptor);
return NULL;
}
pAdaptor->numports = count;
count = 0;
confPort = confAdaptor->va_port_lst;
while (confPort) {
pAdaptor->xvPorts[count] = xf86ConfAllocXvPort();
if (!pAdaptor->xvPorts[count]) {
xf86ConfFreeXvAdaptorData(pAdaptor);
return NULL;
}
if (!convertXvPort(pAdaptor->xvPorts[count], confPort)) {
xf86ConfFreeXvAdaptorData(pAdaptor);
return NULL;
}
count++;
confPort = confPort->list.next;
}
}
return pAdaptor;
}
confXvAdaptorPtr
xf86ConfGetXvAdaptorByName(ConfigHandle handle, const char *name)
{
const XF86ConfigRec *pConfig;
XF86ConfVideoAdaptorPtr a;
confXvAdaptorPtr pAdaptor = NULL;
if (!name)
return NULL;
pConfig = ConfigHandleToConfigRead(handle);
for (a = pConfig->conf_videoadaptor_lst; a; a = a->list.next) {
if (xf86nameCompare(a->va_identifier, name) == 0) {
break;
}
}
if (a) {
pAdaptor = xf86ConfAllocXvAdaptor();
if (pAdaptor) {
if (convertXvAdaptor(pAdaptor, a))
return pAdaptor;
else
xfree(pAdaptor);
}
}
return NULL;
}
static const confXvAdaptorRec *
getNextActiveXvAdaptor(ConfigDataHandle prev)
{
const confScreenRec *pConfScreen = NULL;
int i = 0;
Bool found = FALSE;
while ((pConfScreen = getNextActiveScreen(pConfScreen))) {
for (i = 0; i < pConfScreen->numXvAdaptors; i++) {
if (!prev) {
found = TRUE;
break;
} else if (pConfScreen->xvAdaptorList &&
pConfScreen->xvAdaptorList[i]->handle == prev) {
i++;
found = TRUE;
break;
}
}
if (found) {
if (i < pConfScreen->numXvAdaptors)
break;
else {
prev = NULL;
found = FALSE;
}
}
}
if (found)
return pConfScreen->xvAdaptorList[i];
else
return NULL;
}
confXvAdaptorPtr
xf86ConfGetNextXvAdaptor(ConfigHandle handle,
ConfigDataHandle prevAdaptorHandle)
{
const XF86ConfigRec *pConfig;
XF86ConfVideoAdaptorPtr a;
confXvAdaptorPtr pAdaptor = NULL;
if (handle == ACTIVE_CONFIG)
return xf86ConfDupXvAdaptor(getNextActiveXvAdaptor(prevAdaptorHandle));
pConfig = ConfigHandleToConfigRead(handle);
if (!prevAdaptorHandle) {
a = pConfig->conf_videoadaptor_lst;
} else {
for (a = pConfig->conf_videoadaptor_lst; a; a = a->list.next) {
if (a == prevAdaptorHandle) {
a = a->list.next;
break;
}
}
}
if (a) {
pAdaptor = xf86ConfAllocXvAdaptor();
if (pAdaptor) {
if (convertXvAdaptor(pAdaptor, a))
return pAdaptor;
else
xfree(pAdaptor);
}
}
return NULL;
}
confScreenPtr
xf86ConfAllocScreen()
{
confScreenPtr pConfScreen;
pConfScreen = xcalloc(1, sizeof(*pConfScreen));
pConfScreen->screennum = -1;
pConfScreen->handle = pConfScreen;
return pConfScreen;
}
void
xf86ConfFreeScreenData(confScreenPtr pConfScreen)
{
int i;
if (!pConfScreen)
return;
if (pConfScreen->id) {
xfree(pConfScreen->id);
pConfScreen->id = NULL;
}
if (pConfScreen->monitorNames) {
for (i = 0; i < pConfScreen->numMonitors; i++) {
xfree(pConfScreen->monitorNames[i]);
pConfScreen->monitorNames[i] = NULL;
}
xfree(pConfScreen->monitorNames);
pConfScreen->monitorNames = NULL;
}
if (pConfScreen->monitorNums) {
xfree(pConfScreen->monitorNums);
pConfScreen->monitorNums = NULL;
}
if (pConfScreen->monitors) {
for (i = 0; i < pConfScreen->numMonitors; i++) {
xf86ConfFreeMonitorData(pConfScreen->monitors[i]);
if (pConfScreen->monitor == pConfScreen->monitors[i])
pConfScreen->monitor = NULL;
xfree(pConfScreen->monitors[i]);
pConfScreen->monitors[i] = NULL;
}
xfree(pConfScreen->monitors);
pConfScreen->monitors = NULL;
}
pConfScreen->numMonitors = 0;
if (pConfScreen->monitor) {
xf86ConfFreeMonitorData(pConfScreen->monitor);
xfree(pConfScreen->monitor);
pConfScreen->monitor = NULL;
}
if (pConfScreen->deviceName) {
xfree(pConfScreen->deviceName);
pConfScreen->deviceName = NULL;
}
if (pConfScreen->device) {
xf86ConfFreeGraphicsDeviceData(pConfScreen->device);
xfree(pConfScreen->device);
pConfScreen->device = NULL;
}
if (pConfScreen->displayList) {
for (i = 0; i < pConfScreen->numdisplays; i++) {
xf86ConfFreeDisplayData(pConfScreen->displayList[i]);
xfree(pConfScreen->displayList[i]);
pConfScreen->displayList[i] = NULL;
}
xfree(pConfScreen->displayList);
pConfScreen->displayList = NULL;
}
pConfScreen->numdisplays = 0;
if (pConfScreen->xvAdaptorNames) {
for (i = 0; i < pConfScreen->numXvAdaptors; i++) {
xfree(pConfScreen->xvAdaptorNames[i]);
pConfScreen->xvAdaptorNames[i] = NULL;
}
xfree(pConfScreen->xvAdaptorNames);
pConfScreen->xvAdaptorNames = NULL;
}
if (pConfScreen->xvAdaptorList) {
for (i = 0; i < pConfScreen->numXvAdaptors; i++) {
xf86ConfFreeXvAdaptorData(pConfScreen->xvAdaptorList[i]);
xfree(pConfScreen->xvAdaptorList[i]);
pConfScreen->xvAdaptorList[i] = NULL;
}
xfree(pConfScreen->xvAdaptorList);
pConfScreen->xvAdaptorList = NULL;
}
pConfScreen->numXvAdaptors = 0;
if (pConfScreen->options) {
xf86OptionListFree(pConfScreen->options);
pConfScreen->options = NULL;
}
}
confScreenPtr
xf86ConfDupScreen(const confScreenRec *pConfScreen, int depth)
{
int i;
confScreenPtr s;
if (!pConfScreen)
return NULL;
s = xf86ConfAllocScreen();
if (!s)
return NULL;
s->handle = pConfScreen->handle;
s->id = xstrdup(pConfScreen->id);
if (pConfScreen->id && !s->id) {
xf86ConfFreeScreenData(s);
xfree(s);
return NULL;
}
s->deviceName = xstrdup(pConfScreen->deviceName);
if (pConfScreen->deviceName && !s->deviceName) {
xf86ConfFreeScreenData(s);
xfree(s);
return NULL;
}
s->defaultdepth = pConfScreen->defaultdepth;
s->defaultbpp = pConfScreen->defaultbpp;
s->defaultfbbpp = pConfScreen->defaultfbbpp;
s->screennum = pConfScreen->screennum;
s->numMonitors = pConfScreen->numMonitors;
if (s->numMonitors > 0) {
s->monitorNames = xf86DupStringArray(pConfScreen->monitorNames,
s->numMonitors);
if (pConfScreen->monitorNames && !s->monitorNames) {
xf86ConfFreeScreenData(s);
xfree(s);
return NULL;
}
if (pConfScreen->monitorNums) {
s->monitorNums = xcalloc(s->numMonitors, sizeof(int));
if (!s->monitorNums) {
xf86ConfFreeScreenData(s);
xfree(s);
return NULL;
}
memcpy(s->monitorNums, pConfScreen->monitorNums,
s->numMonitors * sizeof(int));
}
if (depth > 0 && pConfScreen->monitors) {
s->monitors = xcalloc(s->numMonitors, sizeof(MonPtr));
if (!s->monitors) {
xf86ConfFreeScreenData(s);
xfree(s);
return NULL;
}
for (i = 0; i < s->numMonitors; i++) {
s->monitors[i] =
xf86ConfDupMonitor(pConfScreen->monitors[i], depth - 1);
if (pConfScreen->monitors[i] && !s->monitors[i]) {
xf86ConfFreeScreenData(s);
xfree(s);
return NULL;
}
}
s->monitor = s->monitors[0];
}
}
if (pConfScreen->device) {
if (depth > 0) {
s->device = xf86ConfDupGraphicsDevice(pConfScreen->device);
if (!s->device) {
xf86ConfFreeScreenData(s);
xfree(s);
return NULL;
}
} else {
s->device = xf86ConfAllocGraphicsDevice();
if (!s->device) {
xf86ConfFreeScreenData(s);
xfree(s);
return NULL;
}
s->device->identifier = xstrdup(pConfScreen->device->identifier);
if (pConfScreen->device->identifier && !s->device->identifier) {
xf86ConfFreeScreenData(s);
xfree(s);
return NULL;
}
}
}
s->options = xf86OptionListDup(pConfScreen->options);
if (pConfScreen->options && !s->options) {
xf86ConfFreeScreenData(s);
xfree(s);
return NULL;
}
s->numdisplays = pConfScreen->numdisplays;
if (s->numdisplays > 0 && pConfScreen->displayList) {
s->displayList = xcalloc(s->numdisplays, sizeof(DispPtr));
if (!s->displayList) {
xf86ConfFreeScreenData(s);
xfree(s);
return NULL;
}
for (i = 0; i < s->numdisplays; i++) {
s->displayList[i] = xf86ConfDupDisplay(pConfScreen->displayList[i]);
if (pConfScreen->displayList[i] && !s->displayList[i]) {
xf86ConfFreeScreenData(s);
xfree(s);
return NULL;
}
}
}
s->numXvAdaptors = pConfScreen->numXvAdaptors;
if (s->numXvAdaptors > 0) {
s->xvAdaptorNames = xf86DupStringArray(pConfScreen->xvAdaptorNames,
s->numXvAdaptors);
if (pConfScreen->xvAdaptorNames && !s->xvAdaptorNames) {
xf86ConfFreeScreenData(s);
xfree(s);
return NULL;
}
if (depth > 0) {
s->xvAdaptorList =
xcalloc(s->numXvAdaptors, sizeof(confXvAdaptorPtr));
if (!s->xvAdaptorList) {
xf86ConfFreeScreenData(s);
xfree(s);
return NULL;
}
for (i = 0; i < s->numXvAdaptors; i++) {
s->xvAdaptorList[i] =
xf86ConfDupXvAdaptor(pConfScreen->xvAdaptorList[i]);
if (pConfScreen->xvAdaptorList[i] && !s->xvAdaptorList[i]) {
xf86ConfFreeScreenData(s);
xfree(s);
return NULL;
}
}
}
}
return s;
}
static void
resolveScreenCleanup(confScreenPtr pConfScreen, Bool cleanMonNames)
{
int i;
if (pConfScreen->monitors) {
for (i = 0; i < pConfScreen->numMonitors; i++)
xf86ConfFreeMonitorData(pConfScreen->monitors[i]);
xfree(pConfScreen->monitors);
pConfScreen->monitors = NULL;
}
if (cleanMonNames) {
if (pConfScreen->monitorNames) {
for (i = 0; i < pConfScreen->numMonitors; i++)
xfree(pConfScreen->monitorNames[i]);
xfree(pConfScreen->monitorNames);
pConfScreen->monitorNames = NULL;
}
if (pConfScreen->monitorNums) {
xfree(pConfScreen->monitorNums);
pConfScreen->monitorNums = NULL;
}
pConfScreen->numMonitors = 0;
}
if (pConfScreen->device) {
xf86ConfFreeGraphicsDeviceData(pConfScreen->device);
pConfScreen->device = NULL;
}
if (pConfScreen->xvAdaptorList) {
for (i = 0; i < pConfScreen->numXvAdaptors; i++)
xf86ConfFreeXvAdaptorData(pConfScreen->xvAdaptorList[i]);
xfree(pConfScreen->xvAdaptorList);
pConfScreen->xvAdaptorList = NULL;
}
}
confScreenPtr
xf86ConfResolveScreen(ConfigHandle handle, confScreenPtr pConfScreen,
int depth)
{
int i;
Bool defaultMonitor = FALSE;
if (!pConfScreen || depth < 1)
return pConfScreen;
/* Clean out any fields that we will be filling in. */
resolveScreenCleanup(pConfScreen, FALSE);
if (pConfScreen->numMonitors > 0 && pConfScreen->monitorNames) {
pConfScreen->monitors =
xcalloc(pConfScreen->numMonitors, sizeof(MonPtr));
if (!pConfScreen->monitors)
return NULL;
for (i = 0; i < pConfScreen->numMonitors; i++) {
if (!pConfScreen->monitorNames[i])
continue;
pConfScreen->monitors[i] =
xf86ConfGetMonitorByName(handle, pConfScreen->monitorNames[i],
depth - 1);
if (!pConfScreen->monitors[i]) {
continue;
}
if (pConfScreen->monitorNums[i])
pConfScreen->monitors[i]->monitorNum =
pConfScreen->monitorNums[i];
}
} else {
/* If no monitor is specified, create a default one. */
XF86ConfMonitorRec defMon;
MonPtr newMonitor;
bzero(&defMon, sizeof(defMon));
defMon.mon_identifier = xstrdup("<default monitor>");
/*
* TARGET_REFRESH_RATE may be defined to effectively limit the
* default resolution to the largest that has a "good" refresh
* rate.
*/
#ifdef TARGET_REFRESH_RATE
defMon.mon_option_lst = xf86ReplaceRealOption(defMon.mon_option_lst,
"TargetRefresh",
TARGET_REFRESH_RATE);
#endif
pConfScreen->numMonitors = 1;
pConfScreen->monitorNames = xcalloc(1, sizeof(char *));
pConfScreen->monitorNums = xcalloc(1, sizeof(int));
pConfScreen->monitors = xcalloc(1, sizeof(MonPtr));
newMonitor = xcalloc(1, sizeof(*newMonitor));
if (!pConfScreen->monitorNames || !pConfScreen->monitorNums ||
!pConfScreen->monitors || !newMonitor) {
resolveScreenCleanup(pConfScreen, TRUE);
xfree(newMonitor);
return NULL;
}
if (!convertMonitor(newMonitor, &defMon)) {
resolveScreenCleanup(pConfScreen, TRUE);
xfree(newMonitor);
return NULL;
}
if (depth - 1 > 0) {
if (!xf86ConfResolveMonitor(handle, newMonitor)) {
resolveScreenCleanup(pConfScreen, TRUE);
xfree(newMonitor);
return NULL;
}
}
newMonitor->defaultMon = TRUE;
pConfScreen->monitors[0] = newMonitor;
pConfScreen->monitorNums[0] = newMonitor->monitorNum;
pConfScreen->monitorNames[0] = xstrdup(newMonitor->id);
if (newMonitor->id && !pConfScreen->monitorNames[0]) {
resolveScreenCleanup(pConfScreen, TRUE);
return NULL;
}
defaultMonitor = TRUE;
}
if (pConfScreen->monitors)
pConfScreen->monitor = pConfScreen->monitors[0];
if (defaultMonitor) {
xf86MsgVerb(X_INFO, 5,
"Created %d default Monitor%s for the "
"Screen section \"%s\".\n",
pConfScreen->numMonitors, PLURAL(pConfScreen->numMonitors),
pConfScreen->id);
} else {
xf86MsgVerb(X_INFO, 5,
"Found %d Monitor%s in the Screen section \"%s\".\n",
pConfScreen->numMonitors, PLURAL(pConfScreen->numMonitors),
pConfScreen->id);
}
pConfScreen->device =
xf86ConfGetGraphicsDeviceByName(handle, pConfScreen->deviceName);
if (pConfScreen->device) {
pConfScreen->device->active = TRUE;
pConfScreen->device->myScreenSection = pConfScreen;
}
if (pConfScreen->numXvAdaptors > 0 && pConfScreen->xvAdaptorNames) {
pConfScreen->xvAdaptorList =
xcalloc(pConfScreen->numXvAdaptors, sizeof(confXvAdaptorPtr));
if (!pConfScreen->xvAdaptorList) {
resolveScreenCleanup(pConfScreen, defaultMonitor);
return NULL;
}
for (i = 0; i < pConfScreen->numXvAdaptors; i++) {
pConfScreen->xvAdaptorList[i] =
xf86ConfGetXvAdaptorByName(handle,
pConfScreen->xvAdaptorNames[i]);
}
}
if (defaultMonitor) {
xf86Msg(X_WARNING, "No monitor specified for screen \"%s\".\n"
"\tUsing a default monitor configuration.\n", pConfScreen->id);
}
return pConfScreen;
}
int
xf86ConfCheckResolvedScreen(const confScreenRec *pConfScreen, int depth,
Bool strict)
{
int i;
int failures = 0;
if (!pConfScreen || depth < 1)
return 0;
if (pConfScreen->numMonitors > 0 && pConfScreen->monitorNames) {
for (i = 0; i < pConfScreen->numMonitors; i++) {
if (!pConfScreen->monitorNames[i])
continue;
if (pConfScreen->monitors && pConfScreen->monitors[i]) {
failures +=
xf86ConfCheckResolvedMonitor(pConfScreen->monitors[i],
depth - 1, strict);
} else {
xf86Msg(X_ERROR, "No Monitor \"%s\" "
"(referenced by Screen \"%s\").\n",
pConfScreen->monitorNames[i], pConfScreen->id);
failures++;
}
}
} else if (strict) {
xf86Msg(X_ERROR, "No Monitor references in Screen \"%s\".\n",
pConfScreen->id);
failures++;
}
if (pConfScreen->deviceName) {
if (!pConfScreen->device) {
xf86Msg(X_ERROR, "No Device \"%s\" "
"(referenced by Screen \"%s\").\n",
pConfScreen->deviceName, pConfScreen->id);
failures++;
}
} else if (strict) {
xf86Msg(X_ERROR, "No Device references in Screen \"%s\".\n",
pConfScreen->id);
failures++;
}
if (pConfScreen->numXvAdaptors > 0 && pConfScreen->xvAdaptorNames) {
for (i = 0; i < pConfScreen->numXvAdaptors; i++) {
if (!pConfScreen->xvAdaptorNames[i])
continue;
if (!pConfScreen->xvAdaptorList || !pConfScreen->xvAdaptorList[i]) {
xf86Msg(X_ERROR, "No VideoAdaptor \"%s\" "
"(referenced by Screen \"%s\").\n",
pConfScreen->xvAdaptorNames[i], pConfScreen->id);
failures++;
}
}
}
return failures;
}
/*
* assignIndices takes an array of numbers indexed by config file ordering
* and assigns values to the unassigned (negative) values. The values
* assigned begin with the largest already-assigned value + 1, and the
* unassigned values are incremented in config file order.
*
* Note: duplicate already-assigned values are not resolved. This is typically
* a configuration error, but handling such things is up to the driver, and
* optional.
*
* Examples:
*
* 1. {-1, 0, -1, 1} -> {2, 0, 3, 1}
* 2. {0, 1, 2, 1} -> {0, 1, 2, 1}
* 3. {1, 3, -1, 5} -> {1, 3, 6, 5}
*/
static void
assignIndices(int *mapping, int count)
{
int i;
int max = -1;
/* First pass: find largest assigned value. */
for (i = 0; i < count; i++) {
if (mapping[i] > max)
max = mapping[i];
}
/* Second pass: assign values to unassigned slots. */
for (i = 0; i < count; i++) {
if (mapping[i] < 0)
mapping[i] = ++max;
}
}
static confScreenPtr
convertScreen(confScreenPtr pConfScreen, const XF86ConfScreenRec *confScreen)
{
int count;
XF86ConfDisplayPtr dispptr;
XF86ConfAdaptorLinkPtr conf_adaptor;
XF86ConfMonitorListPtr mlistp;
int i;
int *mapping;
if (!pConfScreen || !confScreen)
return NULL;
pConfScreen->handle = confScreen;
pConfScreen->id = xstrdup(confScreen->scrn_identifier);
if (confScreen->scrn_identifier && !pConfScreen->id) {
xf86ConfFreeScreenData(pConfScreen);
return NULL;
}
pConfScreen->defaultdepth = confScreen->scrn_defaultdepth;
pConfScreen->defaultbpp = confScreen->scrn_defaultbpp;
pConfScreen->defaultfbbpp = confScreen->scrn_defaultfbbpp;
pConfScreen->screennum = -1;
/* Figure out how many monitor references there are. */
mlistp = confScreen->scrn_monitor_lst;
count = 0;
while (mlistp) {
count++;
mlistp = mlistp->list.next;
}
pConfScreen->numMonitors = count;
if (count > 0) {
pConfScreen->monitorNames = xcalloc(count, sizeof(char *));
if (!pConfScreen->monitorNames) {
xf86ConfFreeScreenData(pConfScreen);
return NULL;
}
mapping = xcalloc(count, sizeof(int));
if (!mapping) {
xf86ConfFreeScreenData(pConfScreen);
return NULL;
}
mlistp = confScreen->scrn_monitor_lst;
for (i = 0; i < count; i++) {
mapping[i] = mlistp->monitor_num;
mlistp = mlistp->list.next;
}
assignIndices(mapping, count);
pConfScreen->monitorNums = mapping;
mlistp = confScreen->scrn_monitor_lst;
for (i = 0; i < count; i++) {
pConfScreen->monitorNames[i] = xstrdup(mlistp->monitor_str);
if (mlistp->monitor_str && !pConfScreen->monitorNames[i]) {
xf86ConfFreeScreenData(pConfScreen);
return NULL;
}
mlistp = mlistp->list.next;
}
}
pConfScreen->deviceName = xstrdup(confScreen->scrn_device_str);
if (confScreen->scrn_device_str && !pConfScreen->deviceName) {
xf86ConfFreeScreenData(pConfScreen);
return NULL;
}
pConfScreen->options = xf86OptionListDup(confScreen->scrn_option_lst);
if (confScreen->scrn_option_lst && !pConfScreen->options) {
xf86ConfFreeScreenData(pConfScreen);
return NULL;
}
/* Figure out how many display subsections there are, and allocate them. */
dispptr = confScreen->scrn_display_lst;
count = 0;
while (dispptr) {
count++;
dispptr = dispptr->list.next;
}
pConfScreen->numdisplays = count;
if (count > 0) {
pConfScreen->displayList = xcalloc(count, sizeof(DispPtr));
if (!pConfScreen->displayList) {
xf86ConfFreeScreenData(pConfScreen);
return NULL;
}
count = 0;
dispptr = confScreen->scrn_display_lst;
while (dispptr) {
pConfScreen->displayList[count] = xf86ConfAllocDisplay();
if (!pConfScreen->displayList[count]) {
xf86ConfFreeScreenData(pConfScreen);
return NULL;
}
if (!convertDisplay(pConfScreen->displayList[count], dispptr)) {
xf86ConfFreeScreenData(pConfScreen);
return NULL;
}
count++;
dispptr = dispptr->list.next;
}
}
/*
* Figure out how many videoadaptor references there.
*/
count = 0;
conf_adaptor = confScreen->scrn_adaptor_lst;
while (conf_adaptor) {
count++;
conf_adaptor = conf_adaptor->list.next;
}
pConfScreen->numXvAdaptors = count;
if (count > 0) {
pConfScreen->xvAdaptorNames = xcalloc(count, sizeof(char *));
if (!pConfScreen->xvAdaptorNames) {
xf86ConfFreeScreenData(pConfScreen);
return NULL;
}
conf_adaptor = confScreen->scrn_adaptor_lst;
count = 0;
while (conf_adaptor) {
pConfScreen->xvAdaptorNames[count] =
xstrdup(conf_adaptor->al_adaptor_str);
if (conf_adaptor->al_adaptor_str &&
!pConfScreen->xvAdaptorNames[count]) {
xf86ConfFreeScreenData(pConfScreen);
return NULL;
}
count++;
conf_adaptor = conf_adaptor->list.next;
}
}
return pConfScreen;
}
confScreenPtr
xf86ConfGetScreenByName(ConfigHandle handle, const char *name, int depth)
{
const XF86ConfigRec *pConfig;
XF86ConfScreenPtr s;
confScreenPtr pConfScreen = NULL;
if (!name)
return NULL;
pConfig = ConfigHandleToConfigRead(handle);
for (s = pConfig->conf_screen_lst; s; s = s->list.next) {
if (xf86nameCompare(s->scrn_identifier, name) == 0) {
break;
}
}
if (s) {
pConfScreen = xf86ConfAllocScreen();
if (pConfScreen) {
if (!convertScreen(pConfScreen, s)) {
xfree(pConfScreen);
return NULL;
}
if (depth > 0) {
if (!xf86ConfResolveScreen(handle, pConfScreen, depth)) {
xf86ConfFreeScreenData(pConfScreen);
xfree(pConfScreen);
return NULL;
}
}
return pConfScreen;
}
}
return NULL;
}
static const confScreenRec *
getNextActiveScreen(ConfigDataHandle prev)
{
int i;
Bool found = FALSE;
for (i = 0; i < xf86Info.serverLayout->numScreens; i++) {
if (!prev) {
found = TRUE;
break;
} else if (xf86Info.serverLayout->screenLayouts[i]->screen->handle ==
prev) {
i++;
found = TRUE;
break;
}
}
if (found && i < xf86Info.serverLayout->numScreens)
return xf86Info.serverLayout->screenLayouts[i]->screen;
else
return NULL;
}
confScreenPtr
xf86ConfGetNextScreen(ConfigHandle handle, ConfigDataHandle prevScreenHandle,
int depth)
{
const XF86ConfigRec *pConfig;
XF86ConfScreenPtr s;
confScreenPtr pConfScreen = NULL;
if (handle == ACTIVE_CONFIG)
return xf86ConfDupScreen(getNextActiveScreen(prevScreenHandle), depth);
pConfig = ConfigHandleToConfigRead(handle);
if (!prevScreenHandle) {
s = pConfig->conf_screen_lst;
} else {
for (s = pConfig->conf_screen_lst; s; s = s->list.next) {
if (s == prevScreenHandle) {
s = s->list.next;
break;
}
}
}
if (s) {
pConfScreen = xf86ConfAllocScreen();
if (pConfScreen) {
if (!convertScreen(pConfScreen, s)) {
xfree(pConfScreen);
return NULL;
}
if (depth > 0) {
if (!xf86ConfResolveScreen(handle, pConfScreen, depth)) {
xf86ConfFreeScreenData(pConfScreen);
xfree(pConfScreen);
return NULL;
}
}
return pConfScreen;
}
}
return NULL;
}
DisplayModePtr
xf86ConfAllocMode()
{
DisplayModePtr pMode;
pMode = xcalloc(1, sizeof(*pMode));
return pMode;
}
void
xf86ConfFreeModeData(DisplayModePtr pMode)
{
if (!pMode)
return;
if (pMode->name) {
xfree(pMode->name);
pMode->name = NULL;
}
return;
}
DisplayModePtr
xf86ConfDupMode(const DisplayModeRec *pMode, int depth)
{
DisplayModePtr m;
if (!pMode)
return NULL;
m = xf86ConfAllocMode();
if (!m)
return NULL;
if (depth > 0) {
*m = *pMode;
m->prev = NULL;
m->next = NULL;
m->name = NULL;
} else {
m->Clock = pMode->Clock;
m->HDisplay = pMode->HDisplay;
m->HSyncStart = pMode->HSyncStart;
m->HSyncEnd = pMode->HSyncEnd;
m->HTotal = pMode->HTotal;
m->VDisplay = pMode->VDisplay;
m->VSyncStart = pMode->VSyncStart;
m->VSyncEnd = pMode->VSyncEnd;
m->VTotal = pMode->VTotal;
m->Flags = pMode->Flags;
m->HSkew = pMode->HSkew;
m->VScan = pMode->VScan;
}
m->name = xstrdup(pMode->name);
if (pMode->name && !m->name) {
xf86ConfFreeModeData(m);
xfree(m);
return NULL;
}
return m;
}
DisplayModePtr
xf86ConfAllocModeList(int n)
{
DisplayModePtr pModes, prev = NULL, first = NULL, last = NULL;
int i;
if (n <= 0)
return NULL;
for (i = 0; i < n; i++) {
pModes = xf86ConfAllocMode();
if (!pModes) {
xf86ConfFreeModeList(first);
return NULL;
}
if (prev) {
prev->next = pModes;
pModes->prev = prev;
}
if (!first)
first = pModes;
prev = last = pModes;
}
/* Pass back the 'last' value through first->prev. */
if (first)
first->prev = last;
return first;
}
void
xf86ConfFreeModeList(DisplayModePtr pModes)
{
DisplayModePtr m, next, first;
if (!pModes)
return;
m = first = pModes;
do {
next = m->next;
xf86ConfFreeModeData(m);
xfree(m);
m = next;
} while (m && m != first);
}
DisplayModePtr
xf86ConfDupModeList(const DisplayModeRec *pModes, int depth)
{
DisplayModePtr m, prev = NULL, first = NULL, last = NULL;
const DisplayModeRec *pModeFirst;
if (!pModes)
return NULL;
pModeFirst = pModes;
do {
m = xf86ConfDupMode(pModes, depth);
if (!m) {
xf86ConfFreeModeList(first);
return NULL;
}
if (prev) {
prev->next = m;
m->prev = prev;
}
if (!first)
first = m;
prev = last = m;
pModes = pModes->next;
} while (pModes && pModes != pModeFirst);
/* Pass back the 'last' value through first->prev. */
if (first)
first->prev = last;
return first;
}
static DisplayModePtr
convertMode(DisplayModePtr pMode, const XF86ConfModeLineRec *confMode)
{
if (!pMode || !confMode)
return NULL;
pMode->type = 0;
pMode->Clock = confMode->ml_clock;
pMode->HDisplay = confMode->ml_hdisplay;
pMode->HSyncStart = confMode->ml_hsyncstart;
pMode->HSyncEnd = confMode->ml_hsyncend;
pMode->HTotal = confMode->ml_htotal;
pMode->VDisplay = confMode->ml_vdisplay;
pMode->VSyncStart = confMode->ml_vsyncstart;
pMode->VSyncEnd = confMode->ml_vsyncend;
pMode->VTotal = confMode->ml_vtotal;
pMode->Flags = confMode->ml_flags;
pMode->HSkew = confMode->ml_hskew;
pMode->VScan = confMode->ml_vscan;
pMode->name = xstrdup(confMode->ml_identifier);
if (confMode->ml_identifier && !pMode->name) {
xf86ConfFreeModeData(pMode);
return NULL;
}
return pMode;
}
confModeSetPtr
xf86ConfAllocModeSet()
{
confModeSetPtr pModeSet;
pModeSet = xcalloc(1, sizeof(*pModeSet));
pModeSet->handle = pModeSet;
return pModeSet;
}
void
xf86ConfFreeModeSetData(confModeSetPtr pModeSet)
{
if (!pModeSet)
return;
if (pModeSet->identifier) {
xfree(pModeSet->identifier);
pModeSet->identifier = NULL;
}
if (pModeSet->options) {
xf86OptionListFree(pModeSet->options);
pModeSet->options = NULL;
}
if (pModeSet->modes) {
xf86ConfFreeModeList(pModeSet->modes);
pModeSet->modes = NULL;
}
}
confModeSetPtr
xf86ConfDupModeSet(const confModeSetRec *pModeSet, int depth)
{
confModeSetPtr ms;
if (!pModeSet)
return NULL;
ms = xf86ConfAllocModeSet();
if (!ms)
return NULL;
ms->handle = pModeSet->handle;
ms->identifier = xstrdup(pModeSet->identifier);
if (pModeSet->identifier && !ms->identifier) {
xf86ConfFreeModeSetData(ms);
xfree(ms);
return NULL;
}
ms->options = xf86OptionListDup(pModeSet->options);
if (pModeSet->options && !ms->options) {
xf86ConfFreeModeSetData(ms);
xfree(ms);
return NULL;
}
ms->modes = xf86ConfDupModeList(pModeSet->modes, depth);
if (pModeSet->modes && !ms->modes) {
xf86ConfFreeModeSetData(ms);
xfree(ms);
return NULL;
}
/*
* Note: As per xf86ConfDupModeList(), the last value is passed
* back through ms->modes->prev.
*/
return ms;
}
static confModeSetPtr
convertModeSet(confModeSetPtr pModeSet, const XF86ConfModesRec *confModeSet)
{
DisplayModePtr m;
XF86ConfModeLinePtr cmlp;
int count;
if (!pModeSet || !confModeSet)
return NULL;
pModeSet->handle = confModeSet;
pModeSet->identifier = xstrdup(confModeSet->modes_identifier);
if (confModeSet->modes_identifier && !pModeSet->identifier) {
xf86ConfFreeModeSetData(pModeSet);
return NULL;
}
pModeSet->options = xf86OptionListDup(confModeSet->modes_option_lst);
if (confModeSet->modes_option_lst && !pModeSet->options) {
xf86ConfFreeModeSetData(pModeSet);
return NULL;
}
pModeSet->modes = NULL;
/* Cound the number of modes. */
cmlp = confModeSet->mon_modeline_lst;
count = 0;
while (cmlp) {
count++;
cmlp = cmlp->list.next;
}
if (count > 0) {
pModeSet->modes = xf86ConfAllocModeList(count);
if (!pModeSet->modes) {
xf86ConfFreeModeSetData(pModeSet);
return NULL;
}
cmlp = confModeSet->mon_modeline_lst;
m = pModeSet->modes;
while (cmlp && m) {
if (!convertMode(m, cmlp)) {
xf86ConfFreeModeSetData(pModeSet);
return NULL;
}
cmlp = cmlp->list.next;
m = m->next;
}
}
/*
* Note: As per xf86ConfAllocModeList(), the last value is passed
* back through pModeSet->modes->prev.
*/
return pModeSet;
}
confModeSetPtr
xf86ConfGetModeSetByName(ConfigHandle handle, const char *name)
{
const XF86ConfigRec *pConfig;
XF86ConfModesPtr cmp;
confModeSetPtr pModeSet = NULL;
if (!name)
return NULL;
pConfig = ConfigHandleToConfigRead(handle);
for (cmp = pConfig->conf_modes_lst; cmp; cmp = cmp->list.next) {
if (xf86nameCompare(cmp->modes_identifier, name) == 0) {
break;
}
}
if (cmp) {
pModeSet = xf86ConfAllocModeSet();
if (pModeSet) {
if (convertModeSet(pModeSet, cmp))
return pModeSet;
else
xfree(pModeSet);
}
}
return NULL;
}
confModeSetPtr
xf86ConfGetNextModeSet(ConfigHandle handle, ConfigDataHandle prevModeSetHandle)
{
const XF86ConfigRec *pConfig;
XF86ConfModesPtr cmp;
confModeSetPtr pModeSet = NULL;
if (handle == ACTIVE_CONFIG)
return NULL;
pConfig = ConfigHandleToConfigRead(handle);
if (!prevModeSetHandle) {
cmp = pConfig->conf_modes_lst;
} else {
for (cmp = pConfig->conf_modes_lst; cmp; cmp = cmp->list.next) {
if (cmp == prevModeSetHandle) {
cmp = cmp->list.next;
break;
}
}
}
if (cmp) {
pModeSet = xf86ConfAllocModeSet();
if (pModeSet) {
if (convertModeSet(pModeSet, cmp))
return pModeSet;
else
xfree(pModeSet);
}
}
return NULL;
}
MonPtr
xf86ConfAllocMonitor()
{
MonPtr pMonitor;
pMonitor = xcalloc(1, sizeof(*pMonitor));
pMonitor->handle = pMonitor;
return pMonitor;
}
void
xf86ConfFreeMonitorData(MonPtr pMonitor)
{
int i;
if (!pMonitor)
return;
if (pMonitor->id) {
xfree(pMonitor->id);
pMonitor->id = NULL;
}
if (pMonitor->vendor) {
xfree(pMonitor->vendor);
pMonitor->vendor = NULL;
}
if (pMonitor->model) {
xfree(pMonitor->model);
pMonitor->model = NULL;
}
if (pMonitor->modeSetNames) {
for (i = 0; i < pMonitor->numModeSetNames; i++) {
if (pMonitor->modeSetNames[i]) {
xfree(pMonitor->modeSetNames[i]);
pMonitor->modeSetNames[i] = NULL;
}
}
xfree(pMonitor->modeSetNames);
pMonitor->modeSetNames = NULL;
}
pMonitor->numModeSetNames = 0;
if (pMonitor->Modes) {
xf86ConfFreeModeList(pMonitor->Modes);
pMonitor->Modes = NULL;
pMonitor->Last = NULL;
}
if (pMonitor->options) {
xf86OptionListFree(pMonitor->options);
pMonitor->options = NULL;
}
}
MonPtr
xf86ConfDupMonitor(const MonRec *pMonitor, int depth)
{
int i;
MonPtr m;
if (!pMonitor)
return NULL;
m = xf86ConfAllocMonitor();
if (!m)
return NULL;
m->handle = pMonitor->handle;
m->defaultMon = pMonitor->defaultMon;
m->flags = pMonitor->flags;
m->id = xstrdup(pMonitor->id);
if (pMonitor->id && !m->id) {
xf86ConfFreeMonitorData(m);
xfree(m);
return NULL;
}
m->vendor = xstrdup(pMonitor->vendor);
if (pMonitor->vendor && !m->vendor) {
xf86ConfFreeMonitorData(m);
xfree(m);
return NULL;
}
m->model = xstrdup(pMonitor->model);
if (pMonitor->model && !m->model) {
xf86ConfFreeMonitorData(m);
xfree(m);
return NULL;
}
m->Modes = xf86ConfDupModeList(pMonitor->Modes, depth);
if (pMonitor->Modes && !m->Modes) {
xf86ConfFreeMonitorData(m);
xfree(m);
return NULL;
}
if (m->Modes) {
m->Last = m->Modes->prev;
m->Modes->prev = NULL;
}
m->gamma = pMonitor->gamma;
m->widthmm = pMonitor->widthmm;
m->heightmm = pMonitor->heightmm;
m->options = xf86OptionListDup(pMonitor->options);
if (pMonitor->options && !m->options) {
xf86ConfFreeMonitorData(m);
xfree(m);
return NULL;
}
memcpy(m->hsync, pMonitor->hsync, sizeof(m->hsync));
memcpy(m->vrefresh, pMonitor->vrefresh, sizeof(m->vrefresh));
m->nHsync = pMonitor->nHsync;
m->nVrefresh = pMonitor->nVrefresh;
m->numModeSetNames = pMonitor->numModeSetNames;
if (m->numModeSetNames > 0 && pMonitor->modeSetNames) {
m->modeSetNames = xcalloc(m->numModeSetNames + 1, sizeof(char *));
if (!m->modeSetNames) {
xf86ConfFreeMonitorData(m);
xfree(m);
return NULL;
}
for (i = 0; i < m->numModeSetNames; i++) {
m->modeSetNames[i] = xstrdup(pMonitor->modeSetNames[i]);
if (pMonitor->modeSetNames[i] && !m->modeSetNames[i]) {
xf86ConfFreeMonitorData(m);
xfree(m);
return NULL;
}
}
}
return m;
}
MonPtr
xf86ConfResolveMonitor(ConfigHandle handle, MonPtr pMonitor)
{
confModeSetPtr pModeSet;
DisplayModePtr modes = NULL, last = NULL;
DisplayModePtr localModes, localLast;
int i;
if (!pMonitor)
return NULL;
localModes = pMonitor->Modes;
localLast = pMonitor->Last;
pMonitor->Modes = NULL;
pMonitor->Last = NULL;
/* Put the UseModes references first. */
if (pMonitor->modeSetNames && pMonitor->numModeSetNames > 0) {
for (i = 0; i < pMonitor->numModeSetNames; i++) {
if (!pMonitor->modeSetNames[i])
continue;
pModeSet =
xf86ConfGetModeSetByName(handle, pMonitor->modeSetNames[i]);
if (!pModeSet) {
continue;
}
modes = pModeSet->modes;
pModeSet->modes = NULL;
xf86ConfFreeModeSetData(pModeSet);
xfree(pModeSet);
pModeSet = NULL;
if (modes) {
last = modes->prev;
modes->prev = pMonitor->Last;
if (!pMonitor->Modes)
pMonitor->Modes = modes;
else
pMonitor->Last->next = modes;
pMonitor->Last = last;
}
}
}
/* Add back in the local modelines. */
if (localModes) {
localModes->prev = pMonitor->Last;
if (!pMonitor->Modes)
pMonitor->Modes = localModes;
else
pMonitor->Last->next = localModes;
pMonitor->Last = localLast;
}
/* Add the (VESA) default modes. */
if (!addDefaultModes(pMonitor)) {
xf86Msg(X_WARNING, "Could not add default built-in modes.\n");
}
return pMonitor;
}
int
xf86ConfCheckResolvedMonitor(const MonRec *pMonitor, int depth, Bool strict)
{
int failures = 0;
if (!pMonitor || depth < 1)
return 0;
if (strict && (!pMonitor->Modes || !pMonitor->Last)) {
xf86Msg(X_ERROR, "No modes for Monitor \"%s\".\n", pMonitor->id);
failures++;
}
return failures;
}
static MonPtr
convertMonitor(MonPtr pMonitor, const XF86ConfMonitorRec *confMonitor)
{
int count, i;
XF86ConfModesLinkPtr modesLink;
Gamma zeros = {0.0, 0.0, 0.0};
float badgamma = 0.0;
XF86ConfModeLinePtr cmodep;
DisplayModePtr mode;
if (!pMonitor || !confMonitor)
return NULL;
pMonitor->handle = confMonitor;
pMonitor->id = xstrdup(confMonitor->mon_identifier);
if (confMonitor->mon_identifier && !pMonitor->id) {
xf86ConfFreeMonitorData(pMonitor);
return NULL;
}
pMonitor->vendor = xstrdup(confMonitor->mon_vendor);
if (confMonitor->mon_vendor && !pMonitor->vendor) {
xf86ConfFreeMonitorData(pMonitor);
return NULL;
}
pMonitor->model = xstrdup(confMonitor->mon_modelname);
if (confMonitor->mon_modelname && !pMonitor->model) {
xf86ConfFreeMonitorData(pMonitor);
return NULL;
}
pMonitor->Modes = NULL;
pMonitor->Last = NULL;
pMonitor->gamma = zeros;
pMonitor->widthmm = confMonitor->mon_width;
pMonitor->heightmm = confMonitor->mon_height;
pMonitor->options = xf86OptionListDup(confMonitor->mon_option_lst);
if (confMonitor->mon_option_lst && !pMonitor->options) {
xf86ConfFreeMonitorData(pMonitor);
return NULL;
}
for (i = 0; i < confMonitor->mon_n_hsync; i++) {
pMonitor->hsync[i].hi = confMonitor->mon_hsync[i].hi;
pMonitor->hsync[i].lo = confMonitor->mon_hsync[i].lo;
}
pMonitor->nHsync = confMonitor->mon_n_hsync;
for (i = 0; i < confMonitor->mon_n_vrefresh; i++) {
pMonitor->vrefresh[i].hi = confMonitor->mon_vrefresh[i].hi;
pMonitor->vrefresh[i].lo = confMonitor->mon_vrefresh[i].lo;
}
pMonitor->nVrefresh = confMonitor->mon_n_vrefresh;
if (confMonitor->mon_gamma_red > GAMMA_ZERO)
pMonitor->gamma.red = confMonitor->mon_gamma_red;
if (confMonitor->mon_gamma_green > GAMMA_ZERO)
pMonitor->gamma.green = confMonitor->mon_gamma_green;
if (confMonitor->mon_gamma_blue > GAMMA_ZERO)
pMonitor->gamma.blue = confMonitor->mon_gamma_blue;
/* Check that the gamma values are within range. */
if (pMonitor->gamma.red > GAMMA_ZERO &&
(pMonitor->gamma.red < GAMMA_MIN ||
pMonitor->gamma.red > GAMMA_MAX)) {
badgamma = pMonitor->gamma.red;
} else if (pMonitor->gamma.green > GAMMA_ZERO &&
(pMonitor->gamma.green < GAMMA_MIN ||
pMonitor->gamma.green > GAMMA_MAX)) {
badgamma = pMonitor->gamma.green;
} else if (pMonitor->gamma.blue > GAMMA_ZERO &&
(pMonitor->gamma.blue < GAMMA_MIN ||
pMonitor->gamma.blue > GAMMA_MAX)) {
badgamma = pMonitor->gamma.blue;
}
if (badgamma > GAMMA_ZERO) {
xf86ConfigError("Gamma value %.f is out of range (%.2f - %.1f)\n",
badgamma, GAMMA_MIN, GAMMA_MAX);
xf86ConfFreeMonitorData(pMonitor);
return NULL;
}
/* Count the UseModes references. */
count = 0;
modesLink = confMonitor->mon_modes_sect_lst;
while (modesLink) {
count++;
modesLink = modesLink->list.next;
}
pMonitor->numModeSetNames = count;
if (count > 0) {
pMonitor->modeSetNames = xcalloc(count + 1, sizeof(char *));
if (!pMonitor->modeSetNames) {
xf86ConfFreeMonitorData(pMonitor);
return NULL;
}
modesLink = confMonitor->mon_modes_sect_lst;
count = 0;
while (modesLink) {
pMonitor->modeSetNames[count] = xstrdup(modesLink->ml_modes_str);
if (modesLink->ml_modes_str && !pMonitor->modeSetNames[count]) {
xf86ConfFreeMonitorData(pMonitor);
return NULL;
}
count++;
modesLink = modesLink->list.next;
}
}
cmodep = confMonitor->mon_modeline_lst;
count = 0;
while (cmodep) {
count++;
cmodep = cmodep->list.next;
}
if (count > 0) {
pMonitor->Modes = xf86ConfAllocModeList(count);
if (!pMonitor->Modes) {
xf86ConfFreeMonitorData(pMonitor);
return NULL;
}
cmodep = confMonitor->mon_modeline_lst;
mode = pMonitor->Modes;
while (cmodep && mode) {
if (!convertMode(mode, cmodep)) {
xf86ConfFreeMonitorData(pMonitor);
return NULL;
}
cmodep = cmodep->list.next;
mode = mode->next;
}
}
if (pMonitor->Modes) {
pMonitor->Last = pMonitor->Modes->prev;
pMonitor->Modes->prev = NULL;
}
return pMonitor;
}
MonPtr
xf86ConfGetMonitorByName(ConfigHandle handle, const char *name, int depth)
{
const XF86ConfigRec *pConfig;
XF86ConfMonitorPtr m;
MonPtr pMonitor = NULL;
if (!name)
return NULL;
pConfig = ConfigHandleToConfigRead(handle);
for (m = pConfig->conf_monitor_lst; m; m = m->list.next) {
if (xf86nameCompare(m->mon_identifier, name) == 0) {
break;
}
}
if (m) {
pMonitor = xf86ConfAllocMonitor();
if (pMonitor) {
if (!convertMonitor(pMonitor, m)) {
xfree(pMonitor);
return NULL;
}
if (depth > 0) {
if (!xf86ConfResolveMonitor(handle, pMonitor)) {
xf86ConfFreeMonitorData(pMonitor);
xfree(pMonitor);
return NULL;
}
}
return pMonitor;
}
}
return NULL;
}
static const MonRec *
getNextActiveMonitor(ConfigDataHandle prev)
{
const confScreenRec *pConfScreen = NULL;
int i = 0;
Bool found = FALSE;
while ((pConfScreen = getNextActiveScreen(pConfScreen))) {
for (i = 0; i < pConfScreen->numMonitors; i++) {
if (!prev) {
found = TRUE;
break;
} else if (pConfScreen->monitors[i]->handle == prev) {
i++;
found = TRUE;
break;
}
}
if (found) {
if (i < pConfScreen->numMonitors)
break;
else {
prev = NULL;
found = FALSE;
}
}
}
if (found)
return pConfScreen->monitors[i];
else
return NULL;
}
MonPtr
xf86ConfGetNextMonitor(ConfigHandle handle, ConfigDataHandle prevMonitorHandle,
int depth)
{
const XF86ConfigRec *pConfig;
XF86ConfMonitorPtr m;
MonPtr pMonitor = NULL;
if (handle == ACTIVE_CONFIG)
return xf86ConfDupMonitor(getNextActiveMonitor(prevMonitorHandle),
depth);
pConfig = ConfigHandleToConfigRead(handle);
if (!prevMonitorHandle) {
m = pConfig->conf_monitor_lst;
} else {
for (m = pConfig->conf_monitor_lst; m; m = m->list.next) {
if (m == prevMonitorHandle) {
m = m->list.next;
break;
}
}
}
if (m) {
pMonitor = xf86ConfAllocMonitor();
if (pMonitor) {
if (!convertMonitor(pMonitor, m)) {
xfree(pMonitor);
return NULL;
}
if (depth > 0) {
if (!xf86ConfResolveMonitor(handle, pMonitor)) {
xf86ConfFreeMonitorData(pMonitor);
xfree(pMonitor);
return NULL;
}
}
return pMonitor;
}
}
return NULL;
}
static int
lookupVisual(const char *visname)
{
int i;
if (!visname || !*visname)
return -1;
for (i = 0; i <= DirectColor; i++) {
if (!xf86nameCompare(visname, xf86VisualNames[i]))
break;
}
if (i <= DirectColor)
return i;
return -1;
}
DispPtr
xf86ConfAllocDisplay()
{
DispPtr pDisplay;
rgb noColour = {(unsigned int)-1, (unsigned int)-1, (unsigned int)-1};
pDisplay = xcalloc(1, sizeof(*pDisplay));
pDisplay->monitorNum = -1;
pDisplay->frameX0 = -1;
pDisplay->frameY0 = -1;
pDisplay->blackColour = noColour;
pDisplay->whiteColour = noColour;
pDisplay->defaultVisual = -1;
return pDisplay;
}
void
xf86ConfFreeDisplayData(DispPtr pDisplay)
{
int i;
if (!pDisplay)
return;
if (pDisplay->modes) {
for (i = 0; pDisplay->modes[i]; i++) {
xfree(pDisplay->modes[i]);
pDisplay->modes[i] = NULL;
}
xfree(pDisplay->modes);
pDisplay->modes = NULL;
}
if (pDisplay->options) {
xf86OptionListFree(pDisplay->options);
pDisplay->options = NULL;
}
}
DispPtr
xf86ConfDupDisplay(const DispRec *pDisplay)
{
DispPtr d;
char **p;
int i, count;
if (!pDisplay)
return NULL;
d = xf86ConfAllocDisplay();
if (!d)
return NULL;
*d = *pDisplay;
d->options = NULL;
d->modes = NULL;
d->options = xf86OptionListDup(pDisplay->options);
if (pDisplay->options && !d->options) {
xf86ConfFreeDisplayData(d);
xfree(d);
return NULL;
}
p = pDisplay->modes;
count = 0;
while (*p) {
count++;
p++;
}
d->modes = xcalloc(count + 1, sizeof(char*));
if (!d->modes) {
xf86ConfFreeDisplayData(d);
xfree(d);
return NULL;
}
for (i = 0; i < count; i++) {
d->modes[i] = xstrdup(pDisplay->modes[i]);
if (pDisplay->modes[i] && !d->modes[i]) {
xf86ConfFreeDisplayData(d);
xfree(d);
return NULL;
}
}
return d;
}
static DispPtr
convertDisplay(DispPtr pDisplay, const XF86ConfDisplayRec *confDisplay)
{
int count = 0;
XF86ModePtr mode;
if (!pDisplay || !confDisplay)
return NULL;
pDisplay->handle = confDisplay;
pDisplay->frameX0 = confDisplay->disp_frameX0;
pDisplay->frameY0 = confDisplay->disp_frameY0;
pDisplay->virtualX = confDisplay->disp_virtualX;
pDisplay->virtualY = confDisplay->disp_virtualY;
pDisplay->depth = confDisplay->disp_depth;
pDisplay->fbbpp = confDisplay->disp_bpp;
pDisplay->weight.red = confDisplay->disp_weight.red;
pDisplay->weight.green = confDisplay->disp_weight.green;
pDisplay->weight.blue = confDisplay->disp_weight.blue;
pDisplay->blackColour.red = confDisplay->disp_black.red;
pDisplay->blackColour.green = confDisplay->disp_black.green;
pDisplay->blackColour.blue = confDisplay->disp_black.blue;
pDisplay->whiteColour.red = confDisplay->disp_white.red;
pDisplay->whiteColour.green = confDisplay->disp_white.green;
pDisplay->whiteColour.blue = confDisplay->disp_white.blue;
pDisplay->options = xf86OptionListDup(confDisplay->disp_option_lst);
if (confDisplay->disp_option_lst && !pDisplay->options) {
xf86ConfFreeDisplayData(pDisplay);
return NULL;
}
pDisplay->monitorNum = confDisplay->monitor_num;
if (confDisplay->disp_visual) {
pDisplay->defaultVisual = lookupVisual(confDisplay->disp_visual);
if (pDisplay->defaultVisual == -1) {
xf86ConfigError("Invalid visual name: \"%s\"",
confDisplay->disp_visual);
return FALSE;
}
} else {
pDisplay->defaultVisual = -1;
}
/* Hook in the modes. */
mode = confDisplay->disp_mode_lst;
while (mode) {
count++;
mode = mode->list.next;
}
pDisplay->modes = xcalloc(count + 1, sizeof(char*));
if (!pDisplay->modes) {
xf86ConfFreeDisplayData(pDisplay);
return NULL;
}
mode = confDisplay->disp_mode_lst;
count = 0;
while (mode) {
pDisplay->modes[count] = xstrdup(mode->mode_name);
if (mode->mode_name && !pDisplay->modes[count]) {
xf86ConfFreeDisplayData(pDisplay);
return NULL;
}
count++;
mode = mode->list.next;
}
return pDisplay;
}
GDevPtr
xf86ConfAllocGraphicsDevice()
{
GDevPtr pGDev;
pGDev = xcalloc(1, sizeof(*pGDev));
pGDev->chipID = -1;
pGDev->chipRev = -1;
pGDev->screen = -1;
pGDev->handle = pGDev;
return pGDev;
}
void
xf86ConfFreeGraphicsDeviceData(GDevPtr pGDev)
{
if (!pGDev)
return;
if (pGDev->identifier) {
xfree(pGDev->identifier);
pGDev->identifier = NULL;
}
if (pGDev->vendor) {
xfree(pGDev->vendor);
pGDev->vendor = NULL;
}
if (pGDev->board) {
xfree(pGDev->board);
pGDev->board = NULL;
}
if (pGDev->chipset) {
xfree(pGDev->chipset);
pGDev->chipset = NULL;
}
if (pGDev->ramdac) {
xfree(pGDev->ramdac);
pGDev->ramdac = NULL;
}
if (pGDev->driver) {
xfree(pGDev->driver);
pGDev->driver = NULL;
}
if (pGDev->clockchip) {
xfree(pGDev->clockchip);
pGDev->clockchip = NULL;
}
if (pGDev->busID) {
xfree(pGDev->busID);
pGDev->busID = NULL;
}
if (pGDev->options) {
xf86OptionListFree(pGDev->options);
pGDev->options = NULL;
}
}
GDevPtr
xf86ConfDupGraphicsDevice(const GDevRec *pGDev)
{
GDevPtr g;
if (!pGDev)
return NULL;
g = xf86ConfAllocGraphicsDevice();
if (!g)
return NULL;
g->handle = pGDev->handle;
g->identifier = xstrdup(pGDev->identifier);
if (pGDev->identifier && !g->identifier) {
xf86ConfFreeGraphicsDeviceData(g);
xfree(g);
return NULL;
}
g->vendor = xstrdup(pGDev->vendor);
if (pGDev->vendor && !g->vendor) {
xf86ConfFreeGraphicsDeviceData(g);
xfree(g);
return NULL;
}
g->board = xstrdup(pGDev->board);
if (pGDev->board && !g->board) {
xf86ConfFreeGraphicsDeviceData(g);
xfree(g);
return NULL;
}
g->chipset = xstrdup(pGDev->chipset);
if (pGDev->chipset && !g->chipset) {
xf86ConfFreeGraphicsDeviceData(g);
xfree(g);
return NULL;
}
g->ramdac = xstrdup(pGDev->ramdac);
if (pGDev->ramdac && !g->ramdac) {
xf86ConfFreeGraphicsDeviceData(g);
xfree(g);
return NULL;
}
g->driver = xstrdup(pGDev->driver);
if (pGDev->driver && !g->driver) {
xf86ConfFreeGraphicsDeviceData(g);
xfree(g);
return NULL;
}
g->videoRam = pGDev->videoRam;
g->BiosBase = pGDev->BiosBase;
g->MemBase = pGDev->MemBase;
g->IOBase = pGDev->IOBase;
g->clockchip = xstrdup(pGDev->clockchip);
if (pGDev->clockchip && !g->clockchip) {
xf86ConfFreeGraphicsDeviceData(g);
xfree(g);
return NULL;
}
g->busID = xstrdup(pGDev->busID);
if (pGDev->busID && !g->busID) {
xf86ConfFreeGraphicsDeviceData(g);
xfree(g);
return NULL;
}
g->textClockFreq = pGDev->textClockFreq;
g->chipID = pGDev->chipID;
g->chipRev = pGDev->chipRev;
g->options = xf86OptionListDup(pGDev->options);
if (pGDev->options && !g->options) {
xf86ConfFreeGraphicsDeviceData(g);
xfree(g);
return NULL;
}
g->irq = pGDev->irq;
g->screen = pGDev->screen;
memcpy(g->dacSpeeds, pGDev->dacSpeeds, sizeof(g->dacSpeeds));
g->numclocks = pGDev->numclocks;
memcpy(g->clock, pGDev->clock, sizeof(g->clock));
g->claimed = pGDev->claimed;
return g;
}
static GDevPtr
convertGraphicsDevice(GDevPtr pGDev, const XF86ConfDeviceRec *confDevice)
{
int i;
if (!pGDev || !confDevice)
return NULL;
pGDev->handle = confDevice;
pGDev->identifier = xstrdup(confDevice->dev_identifier);
if (confDevice->dev_identifier && !pGDev->identifier) {
xf86ConfFreeGraphicsDeviceData(pGDev);
return NULL;
}
pGDev->vendor = xstrdup(confDevice->dev_vendor);
if (confDevice->dev_vendor && !pGDev->vendor) {
xf86ConfFreeGraphicsDeviceData(pGDev);
return NULL;
}
pGDev->board = xstrdup(confDevice->dev_board);
if (confDevice->dev_board && !pGDev->board) {
xf86ConfFreeGraphicsDeviceData(pGDev);
return NULL;
}
pGDev->chipset = xstrdup(confDevice->dev_chipset);
if (confDevice->dev_chipset && !pGDev->chipset) {
xf86ConfFreeGraphicsDeviceData(pGDev);
return NULL;
}
pGDev->ramdac = xstrdup(confDevice->dev_ramdac);
if (confDevice->dev_ramdac && !pGDev->ramdac) {
xf86ConfFreeGraphicsDeviceData(pGDev);
return NULL;
}
pGDev->driver = xstrdup(confDevice->dev_driver);
if (confDevice->dev_driver && !pGDev->driver) {
xf86ConfFreeGraphicsDeviceData(pGDev);
return NULL;
}
pGDev->videoRam = confDevice->dev_videoram;
pGDev->BiosBase = confDevice->dev_bios_base;
pGDev->MemBase = confDevice->dev_mem_base;
pGDev->IOBase = confDevice->dev_io_base;
pGDev->clockchip = xstrdup(confDevice->dev_clockchip);
if (confDevice->dev_clockchip && !pGDev->clockchip) {
xf86ConfFreeGraphicsDeviceData(pGDev);
return NULL;
}
pGDev->busID = xstrdup(confDevice->dev_busid);
if (confDevice->dev_busid && !pGDev->busID) {
xf86ConfFreeGraphicsDeviceData(pGDev);
return NULL;
}
pGDev->textClockFreq = confDevice->dev_textclockfreq;
pGDev->chipID = confDevice->dev_chipid;
pGDev->chipRev = confDevice->dev_chiprev;
pGDev->options = xf86OptionListDup(confDevice->dev_option_lst);
if (confDevice->dev_option_lst && !pGDev->options) {
xf86ConfFreeGraphicsDeviceData(pGDev);
return NULL;
}
pGDev->irq = confDevice->dev_irq;
pGDev->screen = confDevice->dev_screen;
for (i = 0; i < MAXDACSPEEDS; i++) {
if (i < CONF_MAXDACSPEEDS)
pGDev->dacSpeeds[i] = confDevice->dev_dacSpeeds[i];
else
pGDev->dacSpeeds[i] = 0;
}
pGDev->numclocks = confDevice->dev_clocks;
if (pGDev->numclocks > MAXCLOCKS)
pGDev->numclocks = MAXCLOCKS;
for (i = 0; i < pGDev->numclocks; i++) {
pGDev->clock[i] = confDevice->dev_clock[i];
}
pGDev->claimed = FALSE;
return pGDev;
}
GDevPtr
xf86ConfGetGraphicsDeviceByName(ConfigHandle handle, const char *name)
{
const XF86ConfigRec *pConfig;
XF86ConfDevicePtr d;
GDevPtr pGDev = NULL;
if (!name)
return NULL;
pConfig = ConfigHandleToConfigRead(handle);
for (d = pConfig->conf_device_lst; d; d = d->list.next) {
if (xf86nameCompare(d->dev_identifier, name) == 0) {
break;
}
}
if (d) {
pGDev = xf86ConfAllocGraphicsDevice();
if (pGDev) {
if (convertGraphicsDevice(pGDev, d))
return pGDev;
else
xfree(pGDev);
}
}
return NULL;
}
static const GDevRec *
getNextActiveGraphicsDevice(ConfigDataHandle prev)
{
const confScreenRec *pConfScreen = NULL;
Bool found = FALSE;
while ((pConfScreen = getNextActiveScreen(pConfScreen))) {
if (!prev) {
found = TRUE;
break;
} else if (pConfScreen->device->handle == prev) {
pConfScreen = getNextActiveScreen(pConfScreen);
found = TRUE;;
break;
}
}
if (found && pConfScreen)
return pConfScreen->device;
else
return NULL;
}
GDevPtr
xf86ConfGetNextGraphicsDevice(ConfigHandle handle,
ConfigDataHandle prevDeviceHandle)
{
const XF86ConfigRec *pConfig;
XF86ConfDevicePtr d;
GDevPtr pGDev = NULL;
if (handle == ACTIVE_CONFIG)
return xf86ConfDupGraphicsDevice(
getNextActiveGraphicsDevice(prevDeviceHandle));
pConfig = ConfigHandleToConfigRead(handle);
if (!prevDeviceHandle) {
d = pConfig->conf_device_lst;
} else {
for (d = pConfig->conf_device_lst; d; d = d->list.next) {
if (d == prevDeviceHandle) {
d = d->list.next;
break;
}
}
}
if (d) {
pGDev = xf86ConfAllocGraphicsDevice();
if (pGDev) {
if (convertGraphicsDevice(pGDev, d))
return pGDev;
else
xfree(pGDev);
}
}
return NULL;
}
confDRIBufferPtr
xf86ConfAllocDRIBuffer()
{
confDRIBufferPtr pDriBuf;
pDriBuf = xcalloc(1, sizeof(*pDriBuf));
return pDriBuf;
}
void
xf86ConfFreeDRIBufferData(confDRIBufferPtr pDriBuf)
{
if (!pDriBuf)
return;
}
confDRIBufferPtr
xf86ConfDupDRIBuffer(const confDRIBufferRec *pDriBuf)
{
confDRIBufferPtr b;
if (!pDriBuf)
return NULL;
b = xf86ConfAllocDRIBuffer();
b->count = pDriBuf->count;
b->size = pDriBuf->size;
b->flags = pDriBuf->flags;
return b;
}
confDRIPtr
xf86ConfAllocDRI()
{
confDRIPtr pDri;
pDri = xcalloc(1, sizeof(*pDri));
pDri->group = -1;
pDri->mode = 0;
pDri->handle = pDri;
return pDri;
}
void
xf86ConfFreeDRIData(confDRIPtr pDri)
{
int i;
if (!pDri)
return;
if (pDri->id) {
xfree(pDri->id);
pDri->id = NULL;
}
if (pDri->groupName) {
xfree(pDri->groupName);
pDri->groupName = NULL;
}
if (pDri->options) {
xf86OptionListFree(pDri->options);
pDri->options = NULL;
}
if (pDri->bufsList) {
for (i = 0; i < pDri->bufs_count; i++) {
xf86ConfFreeDRIBufferData(pDri->bufsList[i]);
xfree(pDri->bufsList[i]);
pDri->bufsList[i] = NULL;
}
xfree(pDri->bufsList);
pDri->bufsList = NULL;
}
pDri->bufs_count = 0;
}
confDRIPtr
xf86ConfDupDRI(const confDRIRec *pDri)
{
confDRIPtr d;
int i;
if (!pDri)
return NULL;
d = xf86ConfAllocDRI();
if (!d)
return NULL;
d->handle = pDri->handle;
d->id = xstrdup(pDri->id);
if (pDri->id && !d->id) {
xf86ConfFreeDRIData(d);
xfree(d);
return NULL;
}
d->options = xf86OptionListDup(pDri->options);
if (pDri->options && !d->options) {
xf86ConfFreeDRIData(d);
xfree(d);
return NULL;
}
d->groupName = xstrdup(pDri->groupName);
if (pDri->groupName && !d->groupName) {
xf86ConfFreeDRIData(d);
xfree(d);
return NULL;
}
d->group = pDri->group;
d->mode = pDri->mode;
d->bufs_count = pDri->bufs_count;
if (d->bufs_count > 0 && pDri->bufsList) {
d->bufsList = xcalloc(d->bufs_count, sizeof(confDRIBufferPtr));
if (!d->bufsList) {
xf86ConfFreeDRIData(d);
xfree(d);
return NULL;
}
for (i = 0; i < d->bufs_count; i++) {
d->bufsList[i] = xf86ConfDupDRIBuffer(pDri->bufsList[i]);
if (!d->bufsList[i]) {
xf86ConfFreeDRIData(d);
xfree(d);
return NULL;
}
}
}
return d;
}
static confDRIBufferPtr
convertDRIBuffer(confDRIBufferPtr pDriBuf, const XF86ConfBuffersRec *bufConf)
{
if (!pDriBuf || !bufConf)
return NULL;
pDriBuf->count = bufConf->buf_count;
pDriBuf->size = bufConf->buf_size;
/*
* FIXME: Flags not implemented. These could be used, for example,
* to specify a contiguous block and/or write-combining cache policy.
*/
pDriBuf->flags = XF86DRI_NO_FLAGS;
return pDriBuf;
}
static confDRIPtr
convertDRI(confDRIPtr pDri, const XF86ConfDRIRec *driConf)
{
struct group *groupId;
const XF86ConfBuffersRec *db;
int count, i;
if (!pDri || !driConf)
return NULL;
pDri->handle = driConf;
pDri->id = xstrdup(driConf->dri_identifier);
if (driConf->dri_identifier && !pDri->id) {
xf86ConfFreeDRIData(pDri);
return NULL;
}
pDri->options = xf86OptionListDup(driConf->dri_option_lst);
if (driConf->dri_option_lst && !pDri->options) {
xf86ConfFreeDRIData(pDri);
return NULL;
}
if (driConf->dri_group_name) {
pDri->groupName = xstrdup(driConf->dri_group_name);
if (!pDri->groupName) {
xf86ConfFreeDRIData(pDri);
return NULL;
}
if ((groupId = getgrnam(driConf->dri_group_name)))
pDri->group = groupId->gr_gid;
} else {
if (driConf->dri_group >= 0)
pDri->group = driConf->dri_group;
}
pDri->mode = driConf->dri_mode;
/* Count how many buffers references there are. */
count = 0;
db = driConf->dri_buffers_lst;
while (db) {
count++;
db = db->list.next;
}
pDri->bufs_count = count;
if (count > 0) {
pDri->bufsList = xcalloc(1, sizeof(confDRIBufferPtr));
if (!pDri->bufsList) {
xf86ConfFreeDRIData(pDri);
return NULL;
}
db = driConf->dri_buffers_lst;
for (i = 0; i < count; i++) {
pDri->bufsList[i] = xf86ConfAllocDRIBuffer();
if (!convertDRIBuffer(pDri->bufsList[i], db)) {
xf86ConfFreeDRIData(pDri);
return NULL;
}
}
}
return pDri;
}
confDRIPtr
xf86ConfGetDRIByName(ConfigHandle handle, const char *name)
{
const XF86ConfigRec *pConfig;
XF86ConfDRIPtr d;
confDRIPtr pDri = NULL;
if (!name)
return NULL;
pConfig = ConfigHandleToConfigRead(handle);
for (d = pConfig->conf_dri_lst; d; d = d->list.next) {
if (xf86nameCompare(d->dri_identifier, name) == 0)
break;
}
if (d) {
pDri = xf86ConfAllocDRI();
if (pDri) {
if (convertDRI(pDri, d))
return pDri;
else
xfree(pDri);
}
}
return NULL;
}
confDRIPtr
xf86ConfGetNextDRI(ConfigHandle handle, ConfigDataHandle prevDRIHandle)
{
const XF86ConfigRec *pConfig;
XF86ConfDRIPtr d;
confDRIPtr pDri = NULL;
if (handle == ACTIVE_CONFIG) {
if (!prevDRIHandle)
return xf86ConfDupDRI(&xf86ConfigDRI);
else
return NULL;
}
pConfig = ConfigHandleToConfigRead(handle);
if (!prevDRIHandle) {
d = pConfig->conf_dri_lst;
} else {
for (d = pConfig->conf_dri_lst; d; d = d->list.next) {
if (d == prevDRIHandle) {
d = d->list.next;
break;
}
}
}
if (d) {
pDri = xf86ConfAllocDRI();
if (pDri) {
if (convertDRI(pDri, d))
return pDri;
else
xfree(pDri);
}
}
return NULL;
}
static confDRIPtr
configDRI(ConfigHandle handle, const XF86ConfDRIRec *driConf, MessageType from)
{
confDRIPtr d = NULL;
/* If driConf is supplied, us it. If not, use the first DRI section. */
if (driConf) {
d = xf86ConfAllocDRI();
if (!d)
return NULL;
if (!(d = convertDRI(d, driConf))) {
xfree(d);
return NULL;
}
} else {
d = xf86ConfGetNextDRI(handle, NULL);
}
/* If no DRI section found, create the default. */
if (!d) {
d = xf86ConfAllocDRI();
}
return d;
}
IDevPtr
xf86ConfAllocInputDevice()
{
IDevPtr pIDev;
pIDev = xcalloc(1, sizeof(*pIDev));
pIDev->handle = pIDev;
pIDev->from = X_NONE;
return pIDev;
}
void
xf86ConfFreeInputDeviceData(IDevPtr pIDev)
{
if (!pIDev)
return;
if (pIDev->identifier) {
xfree(pIDev->identifier);
pIDev->identifier = NULL;
}
if (pIDev->driver) {
xfree(pIDev->driver);
pIDev->driver = NULL;
}
if (pIDev->commonOptions) {
xf86OptionListFree(pIDev->commonOptions);
pIDev->commonOptions = NULL;
}
if (pIDev->extraOptions) {
xf86OptionListFree(pIDev->extraOptions);
pIDev->extraOptions = NULL;
}
return;
}
IDevPtr
xf86ConfDupInputDevice(const IDevRec *pIDev, int depth)
{
IDevPtr i;
if (!pIDev)
return NULL;
i = xf86ConfAllocInputDevice();
if (!i)
return NULL;
i->handle = pIDev->handle;
i->from = pIDev->from;
i->identifier = xstrdup(pIDev->identifier);
if (pIDev->identifier && !i->identifier) {
xf86ConfFreeInputDeviceData(i);
xfree(i);
return NULL;
}
i->driver = xstrdup(pIDev->driver);
if (pIDev->driver && !i->driver) {
xf86ConfFreeInputDeviceData(i);
xfree(i);
return NULL;
}
i->commonOptions = xf86OptionListDup(pIDev->commonOptions);
if (pIDev->commonOptions && !i->commonOptions) {
xf86ConfFreeInputDeviceData(i);
xfree(i);
return NULL;
}
if (depth > 0) {
i->extraOptions = xf86OptionListDup(pIDev->extraOptions);
if (pIDev->extraOptions && !i->extraOptions) {
xf86ConfFreeInputDeviceData(i);
xfree(i);
return NULL;
}
}
return i;
}
static IDevPtr
convertInputDevice(IDevPtr pIDev, const XF86ConfInputRec *confInput)
{
if (!pIDev || !confInput)
return NULL;
pIDev->handle = confInput;
pIDev->from = X_CONFIG;
pIDev->identifier = xstrdup(confInput->inp_identifier);
if (confInput->inp_identifier && !pIDev->identifier) {
xf86ConfFreeInputDeviceData(pIDev);
return NULL;
}
pIDev->driver = xstrdup(confInput->inp_driver);
if (confInput->inp_driver && !pIDev->driver) {
xf86ConfFreeInputDeviceData(pIDev);
return NULL;
}
pIDev->commonOptions = xf86OptionListDup(confInput->inp_option_lst);
if (confInput->inp_option_lst && !pIDev->commonOptions) {
xf86ConfFreeInputDeviceData(pIDev);
return NULL;
}
pIDev->extraOptions = NULL;
return pIDev;
}
IDevPtr
xf86ConfGetInputDeviceByName(ConfigHandle handle, const char *name)
{
const XF86ConfigRec *pConfig;
XF86ConfInputPtr i;
IDevPtr pIDev = NULL;
if (!name)
return NULL;
pConfig = ConfigHandleToConfigRead(handle);
for (i = pConfig->conf_input_lst; i; i = i->list.next) {
if (xf86nameCompare(i->inp_identifier, name) == 0) {
break;
}
}
if (i) {
pIDev = xf86ConfAllocInputDevice();
if (pIDev) {
if (convertInputDevice(pIDev, i))
return pIDev;
else
xfree(pIDev);
}
}
return NULL;
}
static const IDevRec *
getNextActiveInputDevice(ConfigDataHandle prev)
{
int i;
Bool found = FALSE;
for (i = 0; i < xf86Info.serverLayout->numInputs; i++) {
if (!prev) {
found = TRUE;
break;
} else if (xf86Info.serverLayout->inputDevs[i]->handle == prev) {
i++;
found = TRUE;
break;
}
}
if (found && i < xf86Info.serverLayout->numInputs)
return xf86Info.serverLayout->inputDevs[i];
else
return NULL;
}
IDevPtr
xf86ConfGetNextInputDevice(ConfigHandle handle, ConfigDataHandle prevIDevHandle,
int depth)
{
const XF86ConfigRec *pConfig;
XF86ConfInputPtr i;
IDevPtr pIDev = NULL;
if (handle == ACTIVE_CONFIG)
return xf86ConfDupInputDevice(getNextActiveInputDevice(prevIDevHandle),
depth);
pConfig = ConfigHandleToConfigRead(handle);
if (!prevIDevHandle) {
i = pConfig->conf_input_lst;
} else {
for (i = pConfig->conf_input_lst; i; i = i->list.next) {
if (i == prevIDevHandle) {
i = i->list.next;
break;
}
}
}
if (i) {
pIDev = xf86ConfAllocInputDevice();
if (pIDev) {
if (convertInputDevice(pIDev, i))
return pIDev;
else
xfree(pIDev);
}
}
return NULL;
}
IDevPtr
xf86ConfGetInputDeviceByDriver(ConfigHandle handle, const char *driver)
{
const XF86ConfigRec *pConfig;
XF86ConfInputPtr i;
IDevPtr pIDev = NULL;
if (!driver)
return NULL;
pConfig = ConfigHandleToConfigRead(handle);
for (i = pConfig->conf_input_lst; i; i = i->list.next) {
if (xf86nameCompare(i->inp_driver, driver) == 0) {
break;
}
}
if (i) {
pIDev = xf86ConfAllocInputDevice();
if (pIDev) {
if (convertInputDevice(pIDev, i))
return pIDev;
else
xfree(pIDev);
}
}
return NULL;
}
IDevPtr
xf86ConfGetInputDeviceByOption(ConfigHandle handle, const char *option)
{
const XF86ConfigRec *pConfig;
XF86ConfInputPtr i;
IDevPtr pIDev = NULL;
if (!option)
return NULL;
pConfig = ConfigHandleToConfigRead(handle);
for (i = pConfig->conf_input_lst; i; i = i->list.next) {
if (xf86CheckBoolOption(i->inp_option_lst, option, FALSE)) {
break;
}
}
if (i) {
pIDev = xf86ConfAllocInputDevice();
if (pIDev) {
if (convertInputDevice(pIDev, i))
return pIDev;
else
xfree(pIDev);
}
}
return NULL;
}
confVendorSubPtr
xf86ConfAllocVendorSub()
{
confVendorSubPtr pVendorSub;
pVendorSub = xcalloc(1, sizeof(*pVendorSub));
pVendorSub->handle = pVendorSub;
return pVendorSub;
}
void
xf86ConfFreeVendorSubData(confVendorSubPtr pVendorSub)
{
if (!pVendorSub)
return;
if (pVendorSub->identifier) {
xfree(pVendorSub->identifier);
pVendorSub->identifier = NULL;
}
if (pVendorSub->name) {
xfree(pVendorSub->name);
pVendorSub->name = NULL;
}
if (pVendorSub->options) {
xf86OptionListFree(pVendorSub->options);
pVendorSub->options = NULL;
}
}
confVendorSubPtr
xf86ConfDupVendorSub(const confVendorSubRec *pVendorSub)
{
confVendorSubPtr sv;
if (!pVendorSub)
return NULL;
sv = xf86ConfAllocVendorSub();
if (!sv)
return NULL;
sv->handle = pVendorSub->handle;
sv->identifier = xstrdup(pVendorSub->identifier);
if (pVendorSub->identifier && !sv->identifier) {
xf86ConfFreeVendorSubData(sv);
xfree(sv);
return NULL;
}
sv->name = xstrdup(pVendorSub->name);
if (pVendorSub->name && !sv->name) {
xf86ConfFreeVendorSubData(sv);
xfree(sv);
return NULL;
}
sv->options = xf86OptionListDup(pVendorSub->options);
if (pVendorSub->options && !sv->options) {
xf86ConfFreeVendorSubData(sv);
xfree(sv);
return NULL;
}
return sv;
}
/*
* Convert a Vendor subsection from the parser's format to the server's format.
*/
static confVendorSubPtr
convertVendorSub(confVendorSubPtr pVendorSub,
const XF86ConfVendSubRec *vendorSubConf)
{
if (!pVendorSub || !vendorSubConf)
return NULL;
pVendorSub->handle = vendorSubConf;
pVendorSub->identifier = xstrdup(vendorSubConf->vs_identifier);
if (vendorSubConf->vs_identifier && !pVendorSub->identifier) {
xf86ConfFreeVendorSubData(pVendorSub);
return NULL;
}
pVendorSub->name = xstrdup(vendorSubConf->vs_name);
if (vendorSubConf->vs_name && !pVendorSub->name) {
xf86ConfFreeVendorSubData(pVendorSub);
return NULL;
}
pVendorSub->options = xf86OptionListDup(vendorSubConf->vs_option_lst);
if (vendorSubConf->vs_option_lst && !pVendorSub->options) {
xf86ConfFreeVendorSubData(pVendorSub);
return NULL;
}
return pVendorSub;
}
confVendorPtr
xf86ConfAllocVendor()
{
confVendorPtr pVendor;
pVendor = xcalloc(1, sizeof(*pVendor));
pVendor->handle = pVendor;
return pVendor;
}
void
xf86ConfFreeVendorData(confVendorPtr pVendor)
{
int i;
if (!pVendor)
return;
if (pVendor->identifier) {
xfree(pVendor->identifier);
pVendor->identifier = NULL;
}
if (pVendor->vendorName) {
xfree(pVendor->vendorName);
pVendor->vendorName = NULL;
}
if (pVendor->options) {
xf86OptionListFree(pVendor->options);
pVendor->options = NULL;
}
if (pVendor->subs) {
for (i = 0; i < pVendor->numSubs; i++) {
xf86ConfFreeVendorSubData(pVendor->subs[i]);
xfree(pVendor->subs[i]);
pVendor->subs[i] = NULL;
}
xfree(pVendor->subs);
pVendor->subs = NULL;
}
pVendor->numSubs = 0;
}
confVendorPtr
xf86ConfDupVendor(const confVendorRec *pVendor)
{
confVendorPtr v;
int i;
if (!pVendor)
return NULL;
v = xf86ConfAllocVendor();
if (!v)
return NULL;
v->handle = pVendor->handle;
v->identifier = xstrdup(pVendor->identifier);
if (pVendor->identifier && !v->identifier) {
xf86ConfFreeVendorData(v);
xfree(v);
return NULL;
}
v->vendorName = xstrdup(pVendor->vendorName);
if (pVendor->vendorName && !v->vendorName) {
xf86ConfFreeVendorData(v);
xfree(v);
return NULL;
}
v->options = xf86OptionListDup(pVendor->options);
if (pVendor->options && !v->options) {
xf86ConfFreeVendorData(v);
xfree(v);
return NULL;
}
v->numSubs = pVendor->numSubs;
if (v->numSubs && pVendor->subs) {
v->subs = xcalloc(v->numSubs, sizeof(confVendorSubPtr));
if (!v->subs) {
xf86ConfFreeVendorData(v);
xfree(v);
return NULL;
}
for (i = 0; i < v->numSubs; i++) {
v->subs[i] = xf86ConfDupVendorSub(pVendor->subs[i]);
if (!v->subs[i]) {
xf86ConfFreeVendorData(v);
xfree(v);
return NULL;
}
}
}
return v;
}
/*
* Convert a Vendor section from the parser's format to the server's format.
*/
static confVendorPtr
convertVendor(confVendorPtr pVendor, const XF86ConfVendorRec *vendorConf)
{
XF86ConfVendSubPtr vsp;
int count, i;
if (!pVendor || !vendorConf)
return NULL;
pVendor->handle = vendorConf;
pVendor->identifier = xstrdup(vendorConf->vnd_identifier);
if (vendorConf->vnd_identifier && !pVendor->identifier) {
xf86ConfFreeVendorData(pVendor);
return NULL;
}
pVendor->vendorName = xstrdup(vendorConf->vnd_name);
if (vendorConf->vnd_name && !pVendor->vendorName) {
xf86ConfFreeVendorData(pVendor);
return NULL;
}
pVendor->options = xf86OptionListDup(vendorConf->vnd_option_lst);
if (vendorConf->vnd_option_lst && !pVendor->options) {
xf86ConfFreeVendorData(pVendor);
return NULL;
}
/* Count how many vendor subsections there are. */
vsp = vendorConf->vnd_sub_lst;
count = 0;
while (vsp) {
count++;
vsp = vsp->list.next;
}
pVendor->numSubs = count;
if (count > 0) {
pVendor->subs = xcalloc(count, sizeof(confVendorSubPtr));
if (!pVendor->subs) {
xf86ConfFreeVendorData(pVendor);
return NULL;
}
vsp = vendorConf->vnd_sub_lst;
for (i = 0; i < count; i++) {
pVendor->subs[i] = xf86ConfAllocVendorSub();
if (!pVendor->subs[i]) {
xf86ConfFreeVendorData(pVendor);
return NULL;
}
if (!convertVendorSub(pVendor->subs[i], vsp)) {
xf86ConfFreeVendorData(pVendor);
return NULL;
}
vsp = vsp->list.next;
}
}
return pVendor;
}
confVendorPtr
xf86ConfGetVendorByName(ConfigHandle handle, const char *name)
{
const XF86ConfigRec *pConfig;
XF86ConfVendorPtr v;
confVendorPtr pVendor = NULL;
if (!name)
return NULL;
pConfig = ConfigHandleToConfigRead(handle);
for (v = pConfig->conf_vendor_lst; v; v = v->list.next) {
if (xf86nameCompare(v->vnd_identifier, name) == 0)
break;
}
if (v) {
pVendor = xf86ConfAllocVendor();
if (pVendor) {
if (convertVendor(pVendor, v))
return pVendor;
else
xfree(pVendor);
}
}
return NULL;
}
confVendorPtr
xf86ConfGetVendorByVendorName(ConfigHandle handle, const char *vname)
{
const XF86ConfigRec *pConfig;
XF86ConfVendorPtr v;
confVendorPtr pVendor = NULL;
if (!vname)
return NULL;
pConfig = ConfigHandleToConfigRead(handle);
for (v = pConfig->conf_vendor_lst; v; v = v->list.next) {
if (xf86nameCompare(v->vnd_name, vname) == 0)
break;
}
if (v) {
pVendor = xf86ConfAllocVendor();
if (pVendor) {
if (convertVendor(pVendor, v))
return pVendor;
else
xfree(pVendor);
}
}
return NULL;
}
confVendorPtr
xf86ConfGetNextVendor(ConfigHandle handle, ConfigDataHandle prevVendorHandle)
{
const XF86ConfigRec *pConfig;
XF86ConfVendorPtr v;
confVendorPtr pVendor = NULL;
if (handle == ACTIVE_CONFIG)
return NULL;
pConfig = ConfigHandleToConfigRead(handle);
if (!prevVendorHandle) {
v = pConfig->conf_vendor_lst;
} else {
for (v = pConfig->conf_vendor_lst; v; v = v->list.next) {
if (v == prevVendorHandle) {
v = v->list.next;
break;
}
}
}
if (v) {
pVendor = xf86ConfAllocVendor();
if (pVendor) {
if (convertVendor(pVendor, v))
return pVendor;
else
xfree(pVendor);
}
}
return NULL;
}
static Bool
addDefaultModes(MonPtr pMonitor)
{
DisplayModePtr mode;
int i = 0;
while (xf86DefaultModes[i].name != NULL) {
if (!xf86ModeIsPresent(xf86DefaultModes[i].name, pMonitor->Modes,
0, M_T_DEFAULT)) {
do {
mode = xnfalloc(sizeof(DisplayModeRec));
memcpy(mode, &xf86DefaultModes[i], sizeof(DisplayModeRec));
if (xf86DefaultModes[i].name)
mode->name = xnfstrdup(xf86DefaultModes[i].name);
xf86AddModeToMonitor(pMonitor, mode);
i++;
} while((xf86DefaultModes[i].name != NULL) &&
(!strcmp(xf86DefaultModes[i].name,
xf86DefaultModes[i-1].name)));
} else
i++;
}
return TRUE;
}
/* Load a config file. */
ConfigStatus
xf86LoadConfigFile(const char *filename, Bool append)
{
char *searchpath;
MessageType from = X_DEFAULT;
XF86ConfigPtr pConfig;
pConfig = (XF86ConfigPtr)xf86Info.config;
/* Free any previously allocated config. */
if (!append && pConfig) {
xf86freeConfig(pConfig);
xf86Info.config = pConfig = NULL;
}
if (!PRIVS_ELEVATED)
searchpath = ROOT_CONFIGPATH;
else
searchpath = USER_CONFIGPATH;
if (!filename) {
if (xf86ConfigFile)
from = X_CMDLINE;
filename = xf86openConfigFile(searchpath, xf86ConfigFile, PROJECTROOT);
if (filename) {
xf86MsgVerb(from, 0, "Using config file: \"%s\".\n", filename);
xf86ConfigFile = xnfstrdup(filename);
} else {
xf86Msg(X_ERROR, "Unable to locate/open config file.");
if (xf86ConfigFile)
xf86ErrorFVerb(0, ": \"%s\"", xf86ConfigFile);
xf86ErrorFVerb(0, "\n");
return CONFIG_NOFILE;
}
}
if (!(xf86Info.config = xf86parseConfigFile(pConfig))) {
xf86Msg(X_ERROR, "Problem parsing the config file \"%s\".\n",
filename);
return CONFIG_PARSE_ERROR;
}
xf86closeConfigFile ();
return CONFIG_OK;
}
Bool
xf86CheckForLayoutOrScreen(ConfigHandle handle)
{
const XF86ConfigRec *pConfig;
pConfig = ConfigHandleToConfigRead(handle);
if (pConfig && (pConfig->conf_layout_lst || pConfig->conf_screen_lst)) {
return TRUE;
}
return FALSE;
}
static void
printLayoutSummary(const serverLayoutRec *pServerLayout)
{
int i, j;
screenLayoutPtr pScreenLayout;
IDevPtr pIDev;
GDevPtr pGDev;
if (!pServerLayout)
return;
xf86Msg(pServerLayout->from, "ServerLayout \"%s\"\n", pServerLayout->id);
for (i = 0; i < pServerLayout->numScreens; i++) {
if (!pServerLayout->screenLayouts[i])
continue;
pScreenLayout = pServerLayout->screenLayouts[i];
if (pScreenLayout->screen) {
char *position = NULL;
switch (pScreenLayout->where) {
case PosAbsolute:
xasprintf(&position, "(%d, %d)", pScreenLayout->x,
pScreenLayout->y);
break;
case PosRightOf:
xasprintf(&position, "Right of \"%s\"", pScreenLayout->refname);
break;
case PosLeftOf:
xasprintf(&position, "Left of \"%s\"", pScreenLayout->refname);
break;
case PosAbove:
xasprintf(&position,"Above \"%s\"", pScreenLayout->refname);
break;
case PosBelow:
xasprintf(&position, "Below \"%s\"", pScreenLayout->refname);
break;
case PosRelative:
xasprintf(&position, "(%d, %d) relative to \"%s\"",
pScreenLayout->x, pScreenLayout->y,
pScreenLayout->refname);
break;
default:
position = NULL;
break;
}
xf86Msg(xf86ScreenName ? X_CMDLINE : X_DEFAULT,
"|-->Screen \"%s\" (%d) %s\n", pScreenLayout->screen->id,
pScreenLayout->screen->screennum, EMPTYIFNULL(position));
if (position)
xfree(position);
if (pScreenLayout->screen->device) {
xf86Msg(X_CONFIG, "| |-->Device \"%s\"\n",
pScreenLayout->screen->device->identifier);
}
if (pScreenLayout->screen->monitors) {
for (j = 0; j < pScreenLayout->screen->numMonitors; j++) {
if (pScreenLayout->screen->monitors[j]) {
xf86Msg(pScreenLayout->screen->monitors[j]->defaultMon ?
X_DEFAULT : X_CONFIG,
"| |-->Monitor \"%s\" (%d)\n",
pScreenLayout->screen->monitors[j]->id,
pScreenLayout->screen->monitors[j]->monitorNum);
}
}
}
if (pScreenLayout->screen->xvAdaptorList) {
for (j = 0; j < pScreenLayout->screen->numXvAdaptors; j++) {
xf86Msg(X_CONFIG, "| |-->VideoAdaptor \"%s\"\n",
pScreenLayout->screen->xvAdaptorList[j]->identifier);
}
}
}
}
if (pServerLayout->inputDevs) {
for (i = 0; i < pServerLayout->numInputs; i++) {
pIDev = pServerLayout->inputDevs[i];
if (pIDev) {
xf86Msg(pIDev->from, "|-->Input Device \"%s\"\n",
pIDev->identifier);
}
}
}
if (pServerLayout->inactiveDevs) {
for (i = 0; i < pServerLayout->numInactives; i++) {
pGDev = pServerLayout->inactiveDevs[i];
if (pGDev) {
xf86Msg(X_CONFIG, "|-->Inactive Device \"%s\"\n",
pGDev->identifier);
}
}
}
}
/*
* Process the configuration data from the parser.
*/
ConfigStatus
xf86ProcessConfiguration()
{
const XF86ConfigRec *pConfig;
confDRIPtr dri;
int i;
pConfig = ConfigHandleToConfigRead(DEFAULT_CONFIG);
if (!pConfig) {
xf86Msg(X_ERROR, "No configuration to process.\n");
return CONFIG_PARSE_ERROR;
}
/*
* Convert the information contained in the parser structures into our
* own structures.
*/
/* First check if a layout section is present, and if it is valid. */
if (!pConfig->conf_layout_lst || xf86ScreenName) {
if (xf86ScreenName == NULL) {
xf86Msg(X_WARNING,
"No Layout section. Using the first Screen section.\n");
}
xf86Info.serverLayout =
configImpliedServerLayout(DEFAULT_CONFIG, xf86ScreenName);
} else {
char *defaultLayout = NULL;
if (pConfig->conf_flags_lst) {
pointer optlist =
pConfig->conf_flags_lst->flg_option_lst;
if (optlist && xf86FindOption(optlist, "defaultserverlayout")) {
defaultLayout =
xf86SetStrOption(optlist, "defaultserverlayout", NULL);
}
}
xf86Info.serverLayout = configServerLayout(DEFAULT_CONFIG,
defaultLayout);
}
if (!xf86Info.serverLayout) {
xf86Msg(X_ERROR, "Unable to determine the screen layout.\n");
return CONFIG_PARSE_ERROR;
}
printLayoutSummary(xf86Info.serverLayout);
i = xf86ConfCheckResolvedServerLayout(xf86Info.serverLayout,
CONFIG_RESOLVE_ALL, TRUE);
if (i > 0) {
xf86Msg(X_ERROR, "%d error%s in resolving the ServerLayout \"%s\".\n",
i, PLURAL(i), xf86Info.serverLayout->id);
return CONFIG_PARSE_ERROR;
}
/* Now process everything else */
xf86Info.confFiles = configFiles(DEFAULT_CONFIG, NULL, X_CONFIG);
if (!xf86Info.confFiles) {
xf86Msg(X_ERROR, "Unable to process the Files data.\n");
return CONFIG_PARSE_ERROR;
}
xf86Info.confFlags = configServerFlags(DEFAULT_CONFIG, NULL,
xf86Info.serverLayout->options,
X_CONFIG);
if (!xf86Info.confFlags) {
xf86Msg(X_ERROR, "Unable to process the ServerFlags data.\n");
return CONFIG_PARSE_ERROR;
}
xf86Info.confModules = configModules(DEFAULT_CONFIG, NULL, X_CONFIG);
if (!xf86Info.confModules) {
xf86Msg(X_ERROR, "Unable to process the Modules data.\n");
return CONFIG_PARSE_ERROR;
}
dri = configDRI(DEFAULT_CONFIG, NULL, X_CONFIG);
if (!dri) {
xf86Msg(X_ERROR, "Unable to process the DRI data.\n");
return CONFIG_PARSE_ERROR;
} else {
xf86ConfigDRI = *dri;
xfree(dri);
}
/*
* Handle some command line options that can override some of the
* ServerFlags settings.
*/
#ifdef XF86VIDMODE
if (xf86VidModeDisabled)
xf86Info.vidModeEnabled = FALSE;
if (xf86VidModeAllowNonLocal)
xf86Info.vidModeAllowNonLocal = TRUE;
#endif
#ifdef XF86MISC
if (xf86MiscModInDevDisabled)
xf86Info.miscModInDevEnabled = FALSE;
if (xf86MiscModInDevAllowNonLocal)
xf86Info.miscModInDevAllowNonLocal = TRUE;
#endif
if (xf86AllowMouseOpenFail)
xf86Info.allowMouseOpenFail = TRUE;
return CONFIG_OK;
}
/* These make the equivalent parser functions visible to the common layer. */
Bool
xf86PathIsAbsolute(const char *path)
{
return (xf86pathIsAbsolute(path) != 0);
}
Bool
xf86PathIsSafe(const char *path)
{
return (xf86pathIsSafe(path) != 0);
}
|
Powered by ViewCVS 0.9.2 |