diff options
Diffstat (limited to 'nx-X11/programs/Xserver/Xprint/Init.c')
-rw-r--r-- | nx-X11/programs/Xserver/Xprint/Init.c | 1934 |
1 files changed, 1934 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/Xprint/Init.c b/nx-X11/programs/Xserver/Xprint/Init.c new file mode 100644 index 000000000..0bc1cf39e --- /dev/null +++ b/nx-X11/programs/Xserver/Xprint/Init.c @@ -0,0 +1,1934 @@ +/* $Xorg: Init.c,v 1.5 2001/03/07 17:31:33 pookie Exp $ */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996-2004 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. +(c) Copyright 2003-2004 Roland Mainz <roland.mainz@nrubsig.org> + +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 HOLDERS 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 names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ +/******************************************************************* +** +** ********************************************************* +** * +** * File: printer/Init.c +** * +** * Contents: +** * The InitOutput routine here would presumably +** * be called from the normal server's InitOutput +** * after all display screens have been added. +** * There is are ifdef'd routines suitable for +** * use in building a printer-only server. Turn +** * on the "PRINTER_ONLY_SERVER" define if this is +** * to be the only ddx-level driver. +** * +** * Copyright: Copyright 1993,1995 Hewlett-Packard Company +** * +** ********************************************************* +** +********************************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <string.h> +#include <locale.h> +#ifdef __hpux +#include <sys/sysmacros.h> +#endif + +#include <X11/X.h> +#define NEED_EVENTS 1 +#include <X11/Xproto.h> +#include <servermd.h> + +#include "screenint.h" +#include "input.h" +#include "cursor.h" +#include "misc.h" +#include "windowstr.h" +#include "inputstr.h" + +#include "gcstruct.h" +#include <X11/fonts/fontstruct.h> +#include "errno.h" + +typedef char *XPointer; +#define HAVE_XPointer 1 + +#define Status int +#include <X11/Xresource.h> + +#include "DiPrint.h" +#include "attributes.h" + +#include "os.h" +#include "spooler.h" + +static void GenericScreenInit( + int index, + ScreenPtr pScreen, + int argc, + char **argv); +static Bool InitPrintDrivers( + int index, + ScreenPtr pScreen, + int argc, + char **argv); + +/* + * The following two defines are used to build the name "X*printers", where + * the "*" is replaced by the display number. This is used to construct + * the name of the default printers configuration file if the -XpFile + * command line option was not specified. + */ +#define XNPRINTERSFILEPREFIX "/X" +#define XNPRINTERSFILESUFFIX "printers" +#define XPRINTERSFILENAME "Xprinters" + +#define MODELDIRNAME "/models" +#define FONTDIRNAME "/fonts" + +#ifdef XPRASTERDDX + +static +PixmapFormatRec RasterPixmapFormats[] = { + { 1, 1, BITMAP_SCANLINE_PAD } +}; +#define NUMRASTFORMATS (sizeof RasterPixmapFormats)/(sizeof RasterPixmapFormats[0]) + +#include "raster/Raster.h" + +#endif + +#ifdef XPPCLDDX + +static +PixmapFormatRec ColorPclPixmapFormats[] = { + { 1, 1, BITMAP_SCANLINE_PAD }, + { 8, 8, BITMAP_SCANLINE_PAD }, + { 24, 32, BITMAP_SCANLINE_PAD } +}; + +#define NUMCPCLFORMATS (sizeof ColorPclPixmapFormats)/(sizeof ColorPclPixmapFormats[0]) + +#endif + +#ifdef XPMONOPCLDDX + +static +PixmapFormatRec MonoPclPixmapFormats[] = { + { 1, 1, BITMAP_SCANLINE_PAD } +}; + +#define NUMMPCLFORMATS (sizeof MonoPclPixmapFormats)/(sizeof MonoPclPixmapFormats[0]) + +#endif + +#if defined(XPPCLDDX) || defined(XPMONOPCLDDX) +#include "pcl/Pcl.h" +#endif + +#ifdef XPPSDDX + +static +PixmapFormatRec PSPixmapFormats[] = { + { 1, 1, BITMAP_SCANLINE_PAD }, + { 8, 8, BITMAP_SCANLINE_PAD }, + { 12, 16, BITMAP_SCANLINE_PAD }, + { 14, 16, BITMAP_SCANLINE_PAD }, + { 16, 16, BITMAP_SCANLINE_PAD }, + { 24, 32, BITMAP_SCANLINE_PAD } +}; + +#define NUMPSFORMATS (sizeof PSPixmapFormats)/(sizeof PSPixmapFormats[0]) + +#include "ps/Ps.h" + +#endif + +/* + * The driverInitArray contains an entry for each driver the + * server knows about. Each element contains pointers to pixmap formats, the + * driver's initialization routine, and pointers to the driver's + * attribute validation rec, and/or a driver function which + * returns the maximum medium width&height, and maximum resolution + * given a printer name. Either the validation rec OR the dimension + * function can be NULL. If the function is non-NULL then it + * will be called, and will be passed the (possibly NULL) validation rec. + * If the function is NULL, then XpGetMaxWidthHeightRes() is called. + */ +typedef struct _driverInitRec { + char *driverName; + pBFunc initFunc; + XpValidatePoolsRec *pValRec; + pVFunc dimensionsFunc; + PixmapFormatRec *pFmts; + int numFmts; +} driverInitRec; + +static driverInitRec driverInits[] = { +#ifdef XPRASTERDDX + { + "XP-RASTER", + InitializeRasterDriver, + &RasterValidatePoolsRec, + (pVFunc) NULL, + RasterPixmapFormats, + NUMRASTFORMATS + }, +#endif +#ifdef XPPCLDDX + { + "XP-PCL-COLOR", + InitializeColorPclDriver, + &PclValidatePoolsRec, + (pVFunc) NULL, + ColorPclPixmapFormats, + NUMCPCLFORMATS + }, +#endif +#ifdef XPMONOPCLDDX + { + "XP-PCL-MONO", + InitializeMonoPclDriver, + &PclValidatePoolsRec, + (pVFunc) NULL, + MonoPclPixmapFormats, + NUMMPCLFORMATS + }, +#endif +#ifdef XPPSDDX + { + "XP-POSTSCRIPT", + InitializePsDriver, + &PsValidatePoolsRec, + (pVFunc) NULL, + PSPixmapFormats, + NUMPSFORMATS + }, +#endif +}; + + +/* + * The printerDb variable points to a list of PrinterDbEntry structs + * which map printer names with screen numbers and driver names. + */ +typedef struct _printerDbEntry { + struct _printerDbEntry *next; + char *name; + char *qualifier; + int screenNum; + char *driverName; + char *desc; +} PrinterDbEntry, *PrinterDbPtr; + +static PrinterDbPtr printerDb = (PrinterDbPtr)NULL; + +/* + * The nameMap is a list used in initializing the attribute store + * for each printer. The list is freed once the printerDb is built + * and the attribute stores for all printers have been initialized. + */ +typedef struct _nameMapEntry { + struct _nameMapEntry *next; + char *name; + char *qualifier; +} NameMapEntry, *NameMapPtr; + +static NameMapPtr nameMap = (NameMapPtr)NULL; + +/* + * The driverMap is a list which provides the mapping between driver names + * and screen numbers. It is built and used + * by RehashPrinterList to correctly fill in the screenNum field in the + * printerDb entries. The list is freed before RehashPrinterList terminates. + */ +typedef struct _driverMapping { + struct _driverMapping *next; + char *driverName; + int screenNum; +} DriverMapEntry, *DriverMapPtr; + +static const char configFilePath[] = +"/etc/dt/config/print:/usr/dt/config/print"; + +static const char printServerConfigDir[] = "XPSERVERCONFIGDIR"; + +static int printScreenPrivIndex, + printWindowPrivIndex, + printGCPrivIndex; +static unsigned long printGeneration = 0; +static char *configFileName = (char *)NULL; +static Bool freeDefaultFontPath = FALSE; +static char *origFontPath = (char *)NULL; + +static Bool xprintInitGlobalsCalled = FALSE; +/* + * This function is responsible for doing initalisation of any global + * variables at an very early point of server startup (even before + * |ProcessCommandLine()|. + */ +void PrinterInitGlobals(void) +{ + extern char dispatchExceptionAtReset; /* defined in Xserver/dix/dispatch.c */ + + xprintInitGlobalsCalled = TRUE; + +#ifdef DAMAGE + /* Disable DAMAGE extension for now as it does not work with + * the Postscript DDX yet (see + * https://bugs.freedesktop.org/show_bug.cgi?id=1660) ... + * (you can enable the DAMAGE extension explicitly via + * % X +extension DAMAGE ... #) ;-( */ + { + extern Bool noDamageExtension; + noDamageExtension = TRUE; + } +#endif /* DAMAGE */ + +#ifdef SMART_SCHEDULE + /* Somehow the XF86 "smart scheduler" completely kills the Xprint DDX + * (see http://xprint.freedesktop.org/cgi-bin/bugzilla/show_bug.cgi?id=467 + * ("Xfree86's "smart scheduler" breaks Xprt") */ + SmartScheduleDisable = TRUE; +#endif /* SMART_SCHEDULE */ + + /* Disable internal screensaver for Xprint (workaround for + * http://pdx.freedesktop.org/cgi-bin/bugzilla/show_bug.cgi?id=567 ("Xorg + * Xprt starts to consume 100% CPU when being idle for some time")) */ + defaultScreenSaverTime = 0; + + /* Ensure that the maximum request size for the BIGREQUESTS extension + * is at least 8MB (see + * http://xprint.freedesktop.org/cgi-bin/bugzilla/show_bug.cgi?id=622 - "RFE: + * Xprt's default BIGREQUESTS extension buffer size should be 8MB") + */ + maxBigRequestSize = (8*1048576)-1; + + /* Xprt should not reset by default when the last client exists + * (default for Xprt is |0|, video Xservers use |DE_RESET|) */ + dispatchExceptionAtReset = 0; +} + +/* + * PrinterUseMsg() prints usage for the Xprint-specific options + */ +void PrinterUseMsg(void) +{ + XpSpoolerTypePtr curr = xpstm; + + /* Option '-XpFile' */ + ErrorF("-XpFile file specifies an alternate `Xprinters' file, rather\n"); + ErrorF(" than the default one (e.g.\n"); + ErrorF(" `${XPCONFIGDIR}/${LANG}/print/Xprinters') or\n"); + ErrorF(" `${XPCONFIGDIR}/C/print/Xprinters'.\n"); + + /* Option '-XpSpoolerType' */ + ErrorF("-XpSpoolerType string specifies a spooler type.\n"); + ErrorF(" Supported values are:\n"); + + while( curr->name != NULL ) + { + ErrorF(" - '%s'\n", curr->name); + curr++; + } + ErrorF(" (multiple values can be specified, seperated by ':',\n"); + ErrorF(" the first active spooler will be chosen).\n"); + ErrorF(" default is '%s'.\n", XPDEFAULTSPOOLERNAMELIST); +} + +/* + * PrinterOptions checks argv[i] to see if it is our command line + * option specifying a configuration file name. It returns the index + * of the next option to process. + */ +int +PrinterOptions( + int argc, + char **argv, + int i) +{ + extern void ddxUseMsg(); + if(strcmp(argv[i], "-XpFile") == 0) + { + if ((i + 1) >= argc) { + ddxUseMsg (); + return i + 2; + } + configFileName = argv[i + 1]; + return i + 2; + } + else if(strcmp(argv[i], "-XpSpoolerType") == 0) + { + if ((i + 1) >= argc) { + ddxUseMsg (); + return i + 2; + } + XpSetSpoolerTypeNameList(argv[i + 1]); + return i + 2; + } + else + { + return i; + } +} + +/************************************************************ + * GetInitFunc -- + * + * This routine is called from the InitPrintDrivers function. + * Given the name of a driver, return a pointer to the driver's + * initialization function. + * + * Results: + * Returns a pointer to the initialization function for the driver. + * + * + ************************************************************/ + +/* +typedef Bool (*pIFunc)(); +static pIFunc +GetInitFunc(driverName) +*/ + +static pBFunc GetInitFunc(char *driverName) +{ + driverInitRec *pInitRec; + int numDrivers = sizeof(driverInits)/sizeof(driverInitRec); + int i; + + for(pInitRec = driverInits, i = 0; i < numDrivers; pInitRec++, i++) + { + if( !strcmp( driverName, pInitRec->driverName ) ) + return pInitRec->initFunc; + } + + return 0; +} + +static void +GetDimFuncAndRec( + char *driverName, + XpValidatePoolsRec **pValRec, + pVFunc *dimensionsFunc) +{ + driverInitRec *pInitRec; + int numDrivers = sizeof(driverInits)/sizeof(driverInitRec); + int i; + + for(pInitRec = driverInits, i = 0; i < numDrivers; pInitRec++, i++) + { + if( !strcmp( driverName, pInitRec->driverName ) ) + { + *dimensionsFunc = pInitRec->dimensionsFunc; + *pValRec = pInitRec->pValRec; + return ; + } + } + + *dimensionsFunc = 0; + *pValRec = 0; + return; +} + +static void +FreePrinterDb(void) +{ + PrinterDbPtr pCurEntry, pNextEntry; + + for(pCurEntry = printerDb, pNextEntry = (PrinterDbPtr)NULL; + pCurEntry != (PrinterDbPtr)NULL; pCurEntry = pNextEntry) + { + pNextEntry = pCurEntry->next; + if(pCurEntry->name != (char *)NULL) + xfree(pCurEntry->name); + if(pCurEntry->desc != (char *)NULL) + xfree(pCurEntry->desc); + /* + * We don't free the driver name, because it's expected to simply + * be a pointer into the xrm database. + */ + xfree(pCurEntry); + } + printerDb = (PrinterDbPtr)NULL; +} + +/* + * AddPrinterDbName allocates an entry in the printerDb list, and + * initializes the "name". It returns TRUE if the element was + * successfully added, and FALSE if an allocation error ocurred. + * XXX AddPrinterDbName needs to check for (and not add) duplicate names. + */ +static Bool +AddPrinterDbName(char *name, char *desc) +{ + PrinterDbPtr pEntry = (PrinterDbPtr)xalloc(sizeof(PrinterDbEntry)); + + if(pEntry == (PrinterDbPtr)NULL) return FALSE; + pEntry->name = (name != NULL) ? strdup(name) : NULL; + pEntry->desc = (desc != NULL) ? strdup(desc) : NULL; + pEntry->qualifier = (char *)NULL; + + if(printerDb == (PrinterDbPtr)NULL) + { + pEntry->next = (PrinterDbPtr)NULL; + printerDb = pEntry; + } + else + { + pEntry->next = printerDb; + printerDb = pEntry; + } + return TRUE; +} + +static int +AugmentPrinterDb(const char *command) +{ + FILE *fp; + char name[256]; + int num_printers = 0; /* Number of printers we found */ + size_t namelen; + char *desc = NULL; + + fp = popen(command, "r"); + /* XXX is a 256 character limit overly restrictive for printer names? */ + while(fgets(name, 256, fp) != (char *)NULL && (namelen=strlen(name))) + { + char *option = name; + + name[namelen-1] = (char)'\0'; /* strip the \n */ + +#define XP_DESCRIPTOR "xp-printerattr.descriptor=" +#define XP_DESCRIPTOR_LEN (sizeof(XP_DESCRIPTOR)-1) + while ((option = strchr(option, '\t'))) { + option++; /* Skip the '\t' */ + if (!strncmp(option, XP_DESCRIPTOR, XP_DESCRIPTOR_LEN)) { + *(option-1) = '\0'; /* Kill the '\t' (only if we found a valid option) */ + option += XP_DESCRIPTOR_LEN; + if (*option != '\0') { + desc = option; + } + } + else + { + /* Unknown option */ + ErrorF("AugmentPrinterDb: Unknown option '%s'\n", option); + } + } + AddPrinterDbName(name, desc); + num_printers++; + } + pclose(fp); + return num_printers; +} + +/* + * FreeNameMap frees all remaining memory associated with the nameMap. + */ +static void +FreeNameMap(void) +{ + NameMapPtr pEntry, pTmp; + + for(pEntry = nameMap, pTmp = (NameMapPtr)NULL; + pEntry != (NameMapPtr)NULL; + pEntry = pTmp) + { + if(pEntry->name != (char *)NULL) + xfree(pEntry->name); + if(pEntry->qualifier != (char *)NULL) + xfree(pEntry->qualifier); + pTmp = pEntry->next; + xfree(pEntry); + } + nameMap = (NameMapPtr)NULL; +} + +/* + * AddNameMap adds an element to the nameMap linked list. + */ +static Bool +AddNameMap(char *name, char *qualifier) +{ + NameMapPtr pEntry; + + if((pEntry = (NameMapPtr)xalloc(sizeof(NameMapEntry))) == (NameMapPtr)NULL) + return FALSE; + pEntry->name = name; + pEntry->qualifier = qualifier; + pEntry->next = nameMap; + nameMap = pEntry; + return TRUE; +} + +/* + * MergeNameMap - puts the "map" names (aka qualifiers, aliases) into + * the printerDb. This should be called once, after both the printerDb + * and nameMap lists are complete. When/if MergeNameMap finds a map for + * an entry in the printerDb, the qualifier is _moved_ (not copied) to + * the printerDb. This means that the qualifier pointer in the nameMap + * is NULLed out. + */ +static void +MergeNameMap(void) +{ + NameMapPtr pMap; + PrinterDbPtr pDb; + + for(pMap = nameMap; pMap != (NameMapPtr)NULL; pMap = pMap->next) + { + for(pDb = printerDb; pDb != (PrinterDbPtr)NULL; pDb = pDb->next) + { + if(!strcmp(pMap->name, pDb->name)) + { + pDb->qualifier = pMap->qualifier; + pMap->qualifier = (char *)NULL; + } + } + } +} + +/* + * CreatePrinterAttrs causes the attribute stores to be built for + * each printer in the printerDb. + */ +static void +CreatePrinterAttrs(void) +{ + PrinterDbPtr pDb; + + for(pDb = printerDb; pDb != (PrinterDbPtr)NULL; pDb = pDb->next) + { + XpBuildAttributeStore(pDb->name, (pDb->qualifier)? + pDb->qualifier : pDb->name); + } +} + +#ifdef XPPSDDX +#define defaultDriver "XP-POSTSCRIPT" +#else +#ifdef XPPCLDDX +#define defaultDriver "XP-PCL-COLOR" +#else +#ifdef XPMONOPCLDDX +#define defaultDriver "XP-PCL-MONO" +#else +#define defaultDriver "XP-RASTER" +#endif +#endif +#endif + +/* + * StoreDriverNames - queries the attribute store for the ddx-identifier. + * if the ddx-identifier is not in the attribute database, then a default + * ddx-identifier is store in both the attribute store for the printer, + * and in the printerDb. + * The ddx-identifier is stored in the printerDb for use in initializing + * the screens. + */ +static void +StoreDriverNames(void) +{ + PrinterDbPtr pEntry; + + for(pEntry = printerDb; pEntry != (PrinterDbPtr)NULL; + pEntry = pEntry->next) + { + pEntry->driverName = (char*)XpGetPrinterAttribute(pEntry->name, + "xp-ddx-identifier"); + if(pEntry->driverName == (char *)NULL || + strlen(pEntry->driverName) == 0 || + GetInitFunc(pEntry->driverName) == (Bool(*)())NULL) + { + if (pEntry->driverName && (strlen(pEntry->driverName) != 0)) { + ErrorF("Xp Extension: Can't load driver %s\n", + pEntry->driverName); + ErrorF(" init function missing\n"); + } + + pEntry->driverName = defaultDriver; + XpAddPrinterAttribute(pEntry->name, + (pEntry->qualifier != (char *)NULL)? + pEntry->qualifier : pEntry->name, + "*xp-ddx-identifier", pEntry->driverName); + } + } +} + +/* + * StoreDescriptors - queries the attribute store for the descriptor. + * if the descriptor is not in the attribute database, then the descriptor + * from the printerDb is store in the attribute store for the printer. + */ +static void +StoreDescriptors() +{ + PrinterDbPtr pEntry; + + for(pEntry = printerDb; pEntry != (PrinterDbPtr)NULL; + pEntry = pEntry->next) + { + if (pEntry->desc != NULL) + { + XpAddPrinterAttribute(pEntry->name, + (pEntry->qualifier != (char *)NULL)? + pEntry->qualifier : pEntry->name, + "*descriptor", pEntry->desc); + } + } +} + +static char * +MbStrchr( + char *str, + int ch) +{ + size_t mbCurMax = MB_CUR_MAX; + wchar_t targetChar, curChar; + char tmpChar; + int i, numBytes, byteLen; + + if(mbCurMax <= 1) return strchr(str, ch); + + tmpChar = (char)ch; + mbtowc(&targetChar, &tmpChar, mbCurMax); + for(i = 0, numBytes = 0, byteLen = strlen(str); i < byteLen; i += numBytes) + { + numBytes = mbtowc(&curChar, &str[i], mbCurMax); + if(curChar == targetChar) return &str[i]; + } + return (char *)NULL; +} + +/* + * GetConfigFileName - Looks for a "Xprinters" file in + * $(XPRINTDIR)/$LANG/print, and then in $(XPRINTDIR)/C/print. If it + * finds such a file, it returns the path to the file. The returned + * string must be freed by the caller. + */ +static char * +GetConfigFileName(void) +{ + /* + * We need to find the system-wide file, if one exists. This + * file can be in either $(XPRINTDIR)/$LANG/print, or in + * $(PRINTDIR)/C/print, and the file itself is named "Xprinters". + */ + char *dirName, *filePath; + + /* + * Check for a LANG-specific file. + */ + if((dirName = XpGetConfigDir(TRUE))) + { + filePath = (char *)xalloc(strlen(dirName) + + strlen(XPRINTERSFILENAME) + 2); + + if(filePath == (char *)NULL) + { + xfree(dirName); + return (char *)NULL; + } + + sprintf(filePath, "%s/%s", dirName, XPRINTERSFILENAME); + xfree(dirName); + if(access(filePath, R_OK) == 0) + return filePath; + + xfree(filePath); + } + + if((dirName = XpGetConfigDir(FALSE))) + { + filePath = (char *)xalloc(strlen(dirName) + + strlen(XPRINTERSFILENAME) + 2); + if(filePath == (char *)NULL) + { + xfree(dirName); + return (char *)NULL; + } + sprintf(filePath, "%s/%s", dirName, XPRINTERSFILENAME); + xfree(dirName); + if(access(filePath, R_OK) == 0) + return filePath; + xfree(filePath); + } + return (char *)NULL; +} + +/* + * BuildPrinterDb - reads the config file if it exists, and if necessary + * executes a command such as lpstat to generate a list of printers. + * XXX + * XXX BuildPrinterDb must be rewritten to allow 16-bit characters in + * XXX printer names. The will involve replacing the use of strtok() and its + * XXX related functions. + * XXX At the same time, BuildPrinterDb and it's support routines should have + * XXX allocation error checking added. + * XXX + */ +static PrinterDbPtr +BuildPrinterDb(void) +{ + char *printerList, *augmentCmd = (char *)NULL; + Bool defaultAugment = TRUE, freeConfigFileName; + + if(configFileName && access(configFileName, R_OK) != 0) + { + ErrorF("Xp Extension: Can't open file %s\n", configFileName); + } + if(!configFileName && (configFileName = GetConfigFileName())) + freeConfigFileName = TRUE; + else + freeConfigFileName = FALSE; + + if(configFileName != (char *)NULL && access(configFileName, R_OK) == 0) + { + char line[256]; + FILE *fp = fopen(configFileName, "r"); + + while(fgets(line, 256, fp) != (char *)NULL) + { + char *tok, *ptr; + if((tok = strtok(line, " \t\012")) != (char *)NULL) + { + if(tok[0] == (char)'#') continue; + if(strcmp(tok, "Printer") == 0) + { + while((tok = strtok((char *)NULL, " \t")) != (char *)NULL) + { + if((ptr = MbStrchr(tok, '\012'))) + *ptr = (char)'\0'; + AddPrinterDbName(tok, NULL); + } + } + else if(strcmp(tok, "Map") == 0) + { + char *name, *qualifier; + + if((tok = strtok((char *)NULL, " \t\012")) == (char *)NULL) + continue; + name = strdup(tok); + if((tok = strtok((char *)NULL, " \t\012")) == (char *)NULL) + { + xfree(name); + continue; + } + qualifier = strdup(tok); + AddNameMap(name, qualifier); + } + else if(strcmp(tok, "Augment_Printer_List") == 0) + { + if((tok = strtok((char *)NULL, " \t\012")) == (char *)NULL) + continue; + + if(strcmp(tok, "%default%") == 0) + continue; + defaultAugment = FALSE; + if(strcmp(tok, "%none%") == 0) + continue; + AugmentPrinterDb(tok); + } + else + break; /* XXX Generate an error? */ + } + } + fclose(fp); + } + + if(defaultAugment == TRUE) + { + XpSpoolerTypePtr curr_spooler_type; /* spooler we are currently probing for queues */ + int num_printers_found; /* number of printers found by |AugmentPrinterDb()| */ + char *tok_lasts; /* strtok_r() position token */ + char *spnamelist; /* list of spooler names, seperated by ":" */ + char *spname; /* spooler name */ + + spnamelist = strdup(XpGetSpoolerTypeNameList()); /* strtok_r() modifies string so dup' it first */ + + for( spname = strtok_r(spnamelist, ":", &tok_lasts) ; + spname != NULL ; + spname = strtok_r(NULL, ":", &tok_lasts) ) + { + curr_spooler_type = XpSpoolerNameToXpSpoolerType(spname); + if(!curr_spooler_type) + { + FatalError("BuildPrinterDb: No spooler type entry found for '%s'.\n", spname); + } + + if(curr_spooler_type->list_queues_command == NULL || + strlen(curr_spooler_type->list_queues_command) == 0) + { + continue; + } + + num_printers_found = AugmentPrinterDb(curr_spooler_type->list_queues_command); + /* Did we found a spooler which works ? */ + if(num_printers_found > 0) + { + spooler_type = curr_spooler_type; +#ifdef DEBUG_gisburn + fprintf(stderr, "BuildPrinterDb: using '%s'.\n", spooler_type->name); +#endif /* DEBUG_gisburn */ + break; + } + } + + free(spnamelist); + } + + MergeNameMap(); + FreeNameMap(); + + /* Create the attribute stores for all printers */ + CreatePrinterAttrs(); + + /* + * Find the drivers for each printers, and store the driver names + * in the printerDb + */ + StoreDriverNames(); + StoreDescriptors(); + + if(freeConfigFileName) + { + xfree(configFileName); + configFileName = (char *)NULL; + } + + return printerDb; +} + +static void +FreeDriverMap(DriverMapPtr driverMap) +{ + DriverMapPtr pCurEntry, pNextEntry; + + for(pCurEntry = driverMap, pNextEntry = (DriverMapPtr)NULL; + pCurEntry != (DriverMapPtr)NULL; pCurEntry = pNextEntry) + { + pNextEntry = pCurEntry->next; + if(pCurEntry->driverName != (char *)NULL) + xfree(pCurEntry->driverName); + xfree(pCurEntry); + } +} + +/* + * XpRehashPrinterList rebuilds the list of printers known to the + * server. It first walks the printerDb to build a table mapping + * driver names and screen numbers, since this is not an easy mapping + * to change in the sample server. The normal configuration files are + * then read & parsed to create the new list of printers. Printers + * which require drivers other than those already initialized are + * deleted from the printerDb. This leaves attribute stores in place + * for inaccessible printers, but those stores will be cleaned up in + * the next rehash or server recycle. + */ +int +XpRehashPrinterList(void) +{ + PrinterDbPtr pEntry, pPrev; + DriverMapPtr driverMap = (DriverMapPtr)NULL, pDrvEnt; + int result; + + /* Build driverMap */ + for(pEntry = printerDb; pEntry != (PrinterDbPtr)NULL; pEntry = pEntry->next) + { + for(pDrvEnt = driverMap; pDrvEnt != (DriverMapPtr)NULL; + pDrvEnt = pDrvEnt->next) + { + if(!strcmp(pEntry->driverName, pDrvEnt->driverName)) + break; + } + + if(pDrvEnt != (DriverMapPtr)NULL) + continue; + + if((pDrvEnt = (DriverMapPtr)xalloc(sizeof(DriverMapEntry))) == + (DriverMapPtr)NULL) + { + FreeDriverMap(driverMap); + return BadAlloc; + } + pDrvEnt->driverName = strdup(pEntry->driverName); + pDrvEnt->screenNum = pEntry->screenNum; + pDrvEnt->next = driverMap; + driverMap = pDrvEnt; + } + + /* Free the old printerDb */ + FreePrinterDb(); + + /* Free/Rehash attribute stores */ + if((result = XpRehashAttributes()) != Success) + return result; + + /* Build a new printerDb */ + if(BuildPrinterDb() == (PrinterDbPtr)NULL) + return BadAlloc; + + /* Walk PrinterDb & either store screenNum, or delete printerDb entry */ + for(pEntry = printerDb, pPrev = (PrinterDbPtr)NULL; + pEntry != (PrinterDbPtr)NULL; pEntry = pEntry->next) + { + for(pDrvEnt = driverMap; pDrvEnt != (DriverMapPtr)NULL; + pDrvEnt = pDrvEnt->next) + { + if(!strcmp(printerDb->driverName, pDrvEnt->driverName)) + break; + } + + /* + * Either store the screen number, or delete the printerDb entry. + * Deleting the entry leaves orphaned attribute stores, but they'll + * get cleaned up at the next rehash or server recycle. + */ + if(pDrvEnt != (DriverMapPtr)NULL) + { + pEntry->screenNum = pDrvEnt->screenNum; + pPrev = pEntry; + } + else { + if(pPrev) + pPrev->next = pEntry->next; + else + pPrev = pEntry->next; + if(pEntry->name != (char *)NULL) + xfree(pEntry->name); + xfree(pEntry); + pEntry = pPrev; + } + } + + FreeDriverMap(driverMap); + + return Success; +} + +/* + * ValidateFontDir looks for a valid font directory for the specified + * printer model within the specified configuration directory. It returns + * the directory name, or NULL if no valid font directory was found. + * It is the caller's responsibility to free the returned font directory + * name. + */ +static char * +ValidateFontDir( + char *configDir, + char *modelName) +{ + char *pathName; + + if(!configDir || !modelName) + return (char *)NULL; + + pathName = (char *)xalloc(strlen(configDir) + strlen(MODELDIRNAME) + + strlen(modelName) + strlen(FONTDIRNAME) + + strlen("fonts.dir") + 5); + if(!pathName) + return (char *)NULL; + sprintf(pathName, "%s/%s/%s/%s/%s", configDir, MODELDIRNAME, modelName, + FONTDIRNAME, "fonts.dir"); + if(access(pathName, R_OK) != 0) + { + xfree(pathName); + return (char *)NULL; + } + pathName[strlen(pathName) - 9] = (char)'\0'; /* erase fonts.dir */ + return pathName; +} + +/* + * FindFontDir returns a pointer to the path name of the font directory + * for the specified printer model name, if such a directory exists. + * The directory contents are superficially checked for validity. + * The caller must free the returned char *. + * + * We first look in the locale-specific model-config directory, and + * then fall back to the C language model-config directory. + */ +static char * +FindFontDir( + char *modelName) +{ + char *configDir, *fontDir; + + if(!modelName || !strlen(modelName)) + return (char *)NULL; + + configDir = XpGetConfigDir(TRUE); + if((fontDir = ValidateFontDir(configDir, modelName))) + { + xfree(configDir); + return fontDir; + } + + if(configDir) + xfree(configDir); + configDir = XpGetConfigDir(FALSE); + fontDir = ValidateFontDir(configDir, modelName); + + xfree(configDir); + + return fontDir; +} + +/* + * AddToFontPath adds the specified font path element to the global + * defaultFontPath string. It adds the keyword "PRINTER:" to the front + * of the path to denote that this is a printer-specific font path + * element. + */ +static char PATH_PREFIX[] = "PRINTER:"; +static int PATH_PREFIX_LEN = sizeof(PATH_PREFIX) - 1; /* same as strlen() */ + +static void +AddToFontPath( + char *pathName) +{ + char *newPath; + Bool freeOldPath; + + if(defaultFontPath == origFontPath) + freeOldPath = FALSE; + else + freeOldPath = TRUE; + + newPath = (char *)xalloc(strlen(defaultFontPath) + strlen(pathName) + + PATH_PREFIX_LEN + 2); + + sprintf(newPath, "%s%s,%s", PATH_PREFIX, pathName, defaultFontPath); + + if(freeOldPath) + xfree(defaultFontPath); + + defaultFontPath = newPath; + return; +} + +/* + * AugmentFontPath adds printer-model-specific font path elements to + * the front of the font path global variable "defaultFontPath" (dix/globals.c). + * We can't call SetFontPath() because the font code has not yet been + * initialized when InitOutput is called (from whence this routine is called). + * + * This utilizes the static variables origFontPath and + * freeDefaultFontPath to track the original contents of defaultFontPath, + * and to properly free the modified version upon server recycle. + */ +static void +AugmentFontPath(void) +{ + char *newPath, *modelID, **allIDs = (char **)NULL; + PrinterDbPtr pDb, pDbEntry; + int numModels, i; + + if(!origFontPath) + origFontPath = defaultFontPath; + + if(freeDefaultFontPath) + { + xfree(defaultFontPath); + defaultFontPath = origFontPath; + freeDefaultFontPath = FALSE; + } + + /* + * Build a list of printer models to check for internal fonts. + */ + for(pDbEntry = printerDb, numModels = 0; + pDbEntry != (PrinterDbPtr)NULL; + pDbEntry = pDbEntry->next) + { + modelID = + (char*)XpGetPrinterAttribute(pDbEntry->name, + "xp-model-identifier"); + + if(modelID && strlen(modelID) != 0) + { + /* look for current model in the list of allIDs */ + for(i = 0; i < numModels; i++) + { + if(!strcmp(modelID, allIDs[i])) + { + modelID = (char *)NULL; + break; + } + } + } + + /* + * If this printer's model-identifier isn't in the allIDs list, + * then add it to allIDs. + */ + if(modelID && strlen(modelID) != 0) + { + allIDs = (char **)xrealloc(allIDs, (numModels+2) * sizeof(char *)); + if(allIDs == (char **)NULL) + return; + allIDs[numModels] = modelID; + allIDs[numModels + 1] = (char *)NULL; + numModels++; + } + } + + /* for each model, check for a valid font directory, and add it to + * the front of defaultFontPath. + */ + for(i = 0; allIDs != (char **)NULL && allIDs[i] != (char *)NULL; i ++) + { + char *fontDir; + if((fontDir = FindFontDir(allIDs[i]))) + { + AddToFontPath(fontDir); + xfree(fontDir); + freeDefaultFontPath = TRUE; + } + } + + if(allIDs) + xfree(allIDs); + + return; +} + +/* + * XpClientIsBitmapClient is called by the font code to find out if + * a particular client should be granted access to bitmap fonts. + * This function works by + * calling XpContextOfClient (in Xserver/Xext/xprint.c) to determine + * the context associated with the client, and then queries the context's + * attributes to determine whether the bitmap fonts should be visible. + * It looks at the value of the xp-listfonts-modes document/page attribute to + * see if xp-list-glyph-fonts has been left out of the mode list. Only + * if the xp-listfonts-modes attribute exists, and it does not contain + * xp-list-glyph-fonts does this function return FALSE. In any other + * case the funtion returns TRUE, indicating that the bitmap fonts + * should be visible to the client. + */ +Bool +XpClientIsBitmapClient( + ClientPtr client) +{ + XpContextPtr pContext; + char *mode; + + if(!(pContext = XpContextOfClient(client))) + return TRUE; + + /* + * Check the page attributes, and if it's not defined there, then + * check the document attributes. + */ + mode = XpGetOneAttribute(pContext, XPPageAttr, "xp-listfonts-modes"); + if(!mode || !strlen(mode)) + { + mode = XpGetOneAttribute(pContext, XPDocAttr, "xp-listfonts-modes"); + if(!mode || !strlen(mode)) + return TRUE; + } + + if(!strstr(mode, "xp-list-glyph-fonts")) + return FALSE; + + return TRUE; +} + +/* + * XpClientIsPrintClient is called by the font code to find out if + * a particular client has set a context which references a printer + * which utilizes a particular font path. + * This function works by calling XpContextOfClient + * (in Xserver/Xext/xprint.c) to determine the context associated with + * the client and then looks at the value of the xp-listfonts-modes + * document/page attribute to see if xp-list-internal-printer-fonts has + * been left out of the mode list. + * If the xp-listfonts-modes attribute exists, and it does not contain + * xp-list-internal-printer-fonts this function returns FALSE. + * Otherwise it looks up the font directory for the context. The font + * directory is then compared with the directory specified in the + * FontPathElement which is passed in. + */ +Bool +XpClientIsPrintClient( + ClientPtr client, + FontPathElementPtr fpe) +{ + XpContextPtr pContext; + char *mode; + char *modelID, *fontDir; + + if(!(pContext = XpContextOfClient(client))) + return FALSE; + + /* + * Check the page attributes, and if it's not defined there, then + * check the document attributes. + */ + mode = XpGetOneAttribute(pContext, XPPageAttr, "xp-listfonts-modes"); + if(!mode || !strlen(mode)) + { + mode = XpGetOneAttribute(pContext, XPDocAttr, "xp-listfonts-modes"); + } + + if(mode && strlen(mode)) + { + if(!strstr(mode, "xp-list-internal-printer-fonts")) + return FALSE; + } + + if (!fpe) + return TRUE; + + modelID = XpGetOneAttribute(pContext, XPPrinterAttr, "xp-model-identifier"); + if(!modelID || !strlen(modelID)) + return FALSE; + + if(!(fontDir = FindFontDir(modelID))) + return FALSE; + + /* + * The grunge here is to ignore the PATH_PREFIX at the front of the + * fpe->name. + */ + if(fpe->name_length < PATH_PREFIX_LEN || + (strlen(fontDir) != (fpe->name_length - PATH_PREFIX_LEN)) || + strncmp(fontDir, fpe->name + PATH_PREFIX_LEN, + fpe->name_length - PATH_PREFIX_LEN)) + { + xfree(fontDir); + return FALSE; + } + xfree(fontDir); + return TRUE; +} + +static void +AddFormats(ScreenInfo *pScreenInfo, char *driverName) +{ + int i, j; + driverInitRec *pInitRec; + int numDrivers = sizeof(driverInits)/sizeof(driverInitRec); + PixmapFormatRec *formats; + int numfmts; + + for (pInitRec = driverInits, i = 0; i < numDrivers; pInitRec++, i++) + { + if ( !strcmp( driverName, pInitRec->driverName ) ) + break; + } + if (i >= numDrivers) + return; + formats = pInitRec->pFmts; + numfmts = pInitRec->numFmts; + for (i = 0; i < numfmts && pScreenInfo->numPixmapFormats < MAXFORMATS; i++) + { + for (j = 0; j < pScreenInfo->numPixmapFormats; j++) { + if (pScreenInfo->formats[j].depth == formats[i].depth && + pScreenInfo->formats[j].bitsPerPixel == formats[i].bitsPerPixel && + pScreenInfo->formats[j].scanlinePad == formats[i].scanlinePad) + break; + } + if (j == pScreenInfo->numPixmapFormats) { + pScreenInfo->formats[j] = formats[i]; + pScreenInfo->numPixmapFormats++; + } + } +} + +/************************************************************ + * PrinterInitOutput -- + * This routine is to be called from a ddx's InitOutput + * during the server startup initialization, and when + * the server is to be reset. The routine creates the + * screens associated with configured printers by calling + * dix:AddScreen. The configuration information comes from a + * database read from the X*printers file. + * + * Results: + * The array of ScreenRec pointers referenced by + * pScreenInfo->screen is increased by the addition + * of the printer screen(s), as is the value of + * pScreenInfo->numScreens. This is done via calls + * to AddScreen() in dix. + * + ************************************************************/ + +void +PrinterInitOutput( + ScreenInfo *pScreenInfo, + int argc, + char **argv) +{ + PrinterDbPtr pDb, pDbEntry; + int driverCount = 0, i; + char **driverNames; + char *configDir; + + /* This should NEVER happen, but... */ + if( !xprintInitGlobalsCalled ) + { + FatalError("Internal error: PrinterInitGlobals() not called."); + } +#ifdef SMART_SCHEDULE + /* |PrinterInitGlobals| should have set |SmartScheduleDisable| to + * |TRUE| - if not we will trigger this safeguard. */ + if( SmartScheduleDisable != TRUE ) + { + FatalError("Internal error: XF86 smart scheduler incompatible to Xprint DDX."); + } +#endif /* SMART_SCHEDULE */ + /* Safeguard for + * http://pdx.freedesktop.org/cgi-bin/bugzilla/show_bug.cgi?id=567 ("Xorg + * Xprt starts to consume 100% CPU when being idle for some time") + * |PrinterInitGlobals| should have set |defaultScreenSaverTime| to + * |0| - if not we will trigger this trap. */ + if( defaultScreenSaverTime != 0 ) + { + FatalError("Internal screen saver must be OFF for printing."); + } + + /* Print a warnung when the maximum request size of the BIGREQUESTS + * extension is smaller than 8MB (see + * http://xprint.freedesktop.org/cgi-bin/bugzilla/show_bug.cgi?id=622) + */ + if (maxBigRequestSize < (8*1048576)-1) { + ErrorF("Xp Extension: BIGREQUESTS max. request is currently %ld bytes " + ", recommemded minimum for Xprint is 8MB.\n", (long)maxBigRequestSize); + } + + /* + * this little test is just a warning at startup to make sure + * that the config directory exists. + * + * what this ugly looking if says is that if both ways of + * calling configDir works and both directories don't exist, + * then print an error saying we can't find the non-lang one. + */ + if (((configDir = XpGetConfigDir(TRUE)) != NULL) && + (access(configDir, F_OK) == 0)) + { + xfree(configDir); + } + else if (((configDir = XpGetConfigDir(FALSE)) != NULL) && + (access(configDir, F_OK) == 0)) + { + xfree(configDir); + } + else { + /* Refuse to start when we do not have our config dir... */ + FatalError("Xp Extension: could not find config dir %s\n", + configDir ? configDir : XPRINTDIR); + } + + if(printerDb != (PrinterDbPtr)NULL) + FreePrinterDb(); + + /* + * Calling BuildPrinterDb serves to build the printer database, + * and to initialize the attribute store for each printer. + * The driver can, if it so desires, modify the attribute + * store at a later time. + */ + if((pDb = BuildPrinterDb()) == (PrinterDbPtr)NULL) return; + + /* + * We now have to decide how many screens to initialize, and call + * AddScreen for each one. The printerDb must be properly initialized + * for at least one screen's worth of printers prior to calling AddScreen + * because InitPrintDrivers reads the printerDb to determine which + * driver(s) to init on a particular screen. + * We put each driver's printers on a different + * screen, and call AddScreen for each screen/driver pair. + */ + /* count the number of printers */ + for(pDbEntry = pDb, driverCount = 0; pDbEntry != (PrinterDbPtr)NULL; + pDbEntry = pDbEntry->next, driverCount++) + ; + /* + * Allocate memory for the worst case - a driver per printer + */ + driverNames = (char **)xalloc(sizeof(char *) * driverCount); + + /* + * Assign the driver for the first printer to the first screen + */ + pDb->screenNum = screenInfo.numScreens; + driverNames[0] = pDb->driverName; + driverCount = 1; + AddFormats(pScreenInfo, pDb->driverName); + + /* + * For each printer, look to see if its driver is already assigned + * to a screen, and if so copy that screen number into the printerDb. + * Otherwise, assign a new screen number to the driver for this + * printer. + */ + for(pDbEntry = pDb; pDbEntry != (PrinterDbPtr)NULL; + pDbEntry = pDbEntry->next) + { + Bool foundMatch; + + for(i = 0, foundMatch = FALSE; i < driverCount; i++) + { + if(!strcmp(driverNames[i], pDbEntry->driverName)) + { + foundMatch = TRUE; + pDbEntry->screenNum = screenInfo.numScreens + i; + break; + } + } + if(foundMatch == FALSE) + { + driverNames[driverCount] = pDbEntry->driverName; + pDbEntry->screenNum = screenInfo.numScreens + driverCount; + AddFormats(pScreenInfo, pDbEntry->driverName); + driverCount++; + } + } + + for(i = 0; i < driverCount; i++) + { + int curScreen = screenInfo.numScreens; + if(AddScreen(InitPrintDrivers, argc, argv) < 0) + { + PrinterDbPtr pPrev; + /* + * AddScreen failed, so we pull the associated printers + * from the list. + */ + ErrorF("Xp Extension: Could not add screen for driver %s\n", + driverNames[i]); + for(pPrev = pDbEntry = printerDb; pDbEntry != (PrinterDbPtr)NULL; + pDbEntry = pDbEntry->next) + { + if(pDbEntry->screenNum == curScreen) + { + if(pPrev == printerDb) + { + printerDb = pDbEntry->next; + pPrev = printerDb; + } + else + pPrev->next = pDbEntry->next; + + xfree(pDbEntry->name); + xfree(pDbEntry); + pDbEntry = pPrev; + } + else + { + if(pDbEntry->screenNum > curScreen) + pDbEntry->screenNum--; + pPrev = pDbEntry; + } + } + } + } + + xfree(driverNames); + + AugmentFontPath(); + + if(pScreenInfo->numScreens > MAXSCREENS) + { + ErrorF("The number of printer screens requested "); + ErrorF("exceeds the allowable limit of %d screens.\n", MAXSCREENS); + ErrorF("Please reduce the number of requested printers in your "); + ErrorF("\nX%sprinters file.", display); + ErrorF("Server exiting...\n"); + exit(-1); + } +} + +/* + * InitPrintDrivers is called from dix:AddScreen. It in turn calls the + * driver initialization routine for any and all drivers which are + * implicated in supporting printers on the particular screen number + * specified by the "index" parameter. The printerDb variable is used + * to determine which printers are to be associated with a particular + * screen. + */ +static Bool +InitPrintDrivers( + int index, + ScreenPtr pScreen, + int argc, + char **argv) +{ + PrinterDbPtr pDb, pDb2; + + GenericScreenInit(index, pScreen, argc, argv); + + for(pDb = printerDb; pDb != (PrinterDbPtr)NULL; pDb = pDb->next) + { + if(pDb->screenNum == index) + { + Bool callInit = TRUE; + for(pDb2 = printerDb; pDb2 != pDb; pDb2 = pDb2->next) + { + if(!strcmp(pDb->driverName, pDb2->driverName)) + { + callInit = FALSE; + break; + } + } + if(callInit == TRUE) + { + Bool (*initFunc)(); + initFunc = GetInitFunc(pDb->driverName); + if(initFunc(index, pScreen, argc, argv) == FALSE) + { + /* XXX - What do I do if the driver's init fails? */ + } + } + } + } + return TRUE; +} + +void +_XpVoidNoop(void) +{ + return; +} + +Bool +_XpBoolNoop(void) +{ + return TRUE; +} + +/* + * GenericScreenInit - The common initializations required by all + * printer screens and drivers. It sets the screen's cursor functions + * to Noops, and computes the maximum screen (i.e. medium) dimensions. + */ + +static void +GenericScreenInit( + int index, + ScreenPtr pScreen, + int argc, + char **argv) +{ + int i; + float fWidth, fHeight, maxWidth, maxHeight; + unsigned short width, height; + PrinterDbPtr pDb, pDb2; + int res, maxRes; + + /* + * Set the cursor ops to no-op functions. + */ + pScreen->DisplayCursor = (DisplayCursorProcPtr)_XpBoolNoop; + pScreen->RealizeCursor = (RealizeCursorProcPtr)_XpBoolNoop; + pScreen->UnrealizeCursor = (UnrealizeCursorProcPtr)_XpBoolNoop; + pScreen->SetCursorPosition = (SetCursorPositionProcPtr)_XpBoolNoop; + pScreen->ConstrainCursor = (ConstrainCursorProcPtr)_XpVoidNoop; + pScreen->CursorLimits = (CursorLimitsProcPtr)_XpVoidNoop; + pScreen->RecolorCursor = (RecolorCursorProcPtr)_XpVoidNoop; + + /* + * Find the largest paper size for all the printers on the given + * screen. + */ + maxRes = 0; + maxWidth = maxHeight = 0.0; + for( pDb = printerDb; pDb != (PrinterDbPtr)NULL; pDb = pDb->next) + { + if(pDb->screenNum == index) + { + + XpValidatePoolsRec *pValRec; + pVFunc dimensionsFunc; + + GetDimFuncAndRec(pDb->driverName, &pValRec, &dimensionsFunc); + if(dimensionsFunc != (pVFunc)NULL) + dimensionsFunc(pDb->name, pValRec, &fWidth, &fHeight, &res); + else + XpGetMaxWidthHeightRes(pDb->name, pValRec, &fWidth, + &fHeight, &res); + if( res > maxRes ) + maxRes = res; + if( fWidth > maxWidth ) + maxWidth = fWidth; + if( fHeight > maxHeight ) + maxHeight = fHeight; + } + } + + width = (unsigned short) (maxWidth * maxRes / 25.4); + height = (unsigned short) (maxHeight * maxRes / 25.4); + pScreen->width = pScreen->height = ( width > height ) ? width : + height; + + pScreen->mmWidth = pScreen->mmHeight = ( maxWidth > maxHeight ) ? + (unsigned short)(maxWidth + 0.5) : + (unsigned short)(maxHeight + 0.5); +} + +/* + * QualifyName - takes an unqualified file name such as X6printers and + * a colon-separated list of directory path names such as + * /etc/opt/dt:/opt/dt/config. + * + * Returns a fully qualified file path name such as /etc/opt/dt/X6printers. + * The returned value is malloc'd, and the caller is responsible for + * freeing the associated memory. + */ +static char * +QualifyName(fileName, searchPath) + char *fileName; + char *searchPath; +{ + char * curPath = searchPath; + char * nextPath; + char * chance; + FILE *pFile; + + if (fileName == NULL || searchPath == NULL) + return NULL; + + while (1) { + if ((nextPath = strchr(curPath, ':')) != NULL) + *nextPath = 0; + + chance = (char *)xalloc(strlen(curPath) + strlen(fileName) + 2); + sprintf(chance,"%s/%s",curPath,fileName); + + /* see if we can read from the file */ + if((pFile = fopen(chance, "r")) != (FILE *)NULL) + { + fclose(pFile); + /* ... restore the colon, .... */ + if (nextPath) + *nextPath = ':'; + + return chance; + } + + xfree(chance); + + if (nextPath == NULL) /* End of path list? */ + break; + + /* try the next path */ + curPath = nextPath + 1; + } + return NULL; +} + +/* + * FillPrinterListEntry fills in a single XpDiListEntry element with data + * derived from the supplied PrinterDbPtr element. + * + * XXX A smarter (i.e. future) version of this routine might inspect the + * XXX "locale" parameter and attempt to match the "description" and + * XXX "localeName" elements of the XpDiListEntry to the specified locale. + */ +static void +FillPrinterListEntry( + XpDiListEntry *pEntry, + PrinterDbPtr pDb, + int localeLen, + char *locale) +{ + static char *localeStr = (char *)NULL; + + if(localeStr == (char *)NULL) + localeStr = strdup(setlocale(LC_ALL, (const char *)NULL)); + + pEntry->name = pDb->name; + pEntry->description = + (char*)XpGetPrinterAttribute(pDb->name, "descriptor"); + pEntry->localeName = localeStr; + pEntry->rootWinId = WindowTable[pDb->screenNum]->drawable.id; +} + +/* + * GetPrinterListInfo fills in the XpDiListEntry struct pointed to by the + * parameter pEntry with the information regarding the printer specified + * by the name and nameLen parameters. The pointers placed in the + * XpDiListEntry structure MUST NOT be freed by the caller. They are + * pointers into existing long-lived databases. + * + */ +static Bool +GetPrinterListInfo( + XpDiListEntry *pEntry, + int nameLen, + char *name, + int localeLen, + char *locale) +{ + PrinterDbPtr pDb, pDb2; + + for(pDb = printerDb; pDb != (PrinterDbPtr)NULL; pDb = pDb->next) + { + if(strlen(pDb->name) == nameLen && !strncmp(pDb->name, name, nameLen)) + { + FillPrinterListEntry(pEntry, pDb, localeLen, locale); + return TRUE; + } + } + return FALSE; +} + +/* + * XpDiFreePrinterList is the approved method of releasing memory used + * for a printer list. + */ +void +XpDiFreePrinterList(XpDiListEntry **list) +{ + int i; + + for(i = 0; list[i] != (XpDiListEntry *)NULL; i++) + xfree(list[i]); + xfree(list); +} + +/* + * XpDiGetPrinterList returns a pointer to a NULL-terminated array of + * XpDiListEntry pointers. Each entry structure contains the name, + * description, root window, and locale of a printer. The call returns + * either a list of all printers configured on the server, or it returns + * the information for one specific printer depending on the values passed + * in. Non-NULL values passed in indicate that only the information for + * the one specific printer is desired, while NULL values indicate that + * the information for all printers is desired. + */ +XpDiListEntry ** +XpDiGetPrinterList( + int nameLen, + char *name, + int localeLen, + char *locale) +{ + XpDiListEntry **pList; + + if(!nameLen || name == (char *)NULL) + { + int i; + PrinterDbPtr pDb, pDb2; + + for(pDb = printerDb, i = 0; pDb != (PrinterDbPtr)NULL; + pDb = pDb->next, i++) + ; + + if((pList = (XpDiListEntry **)xalloc((i+1) * sizeof(XpDiListEntry *))) + == (XpDiListEntry **)NULL) + return pList; + + pList[i] = (XpDiListEntry *)NULL; + for(pDb = printerDb, i = 0; pDb != (PrinterDbPtr)NULL; + pDb = pDb->next, i++) + { + if((pList[i] = (XpDiListEntry *)xalloc(sizeof(XpDiListEntry)))== + (XpDiListEntry *)NULL) + { + XpDiFreePrinterList(pList); + return (XpDiListEntry **)NULL; + } + FillPrinterListEntry(pList[i], pDb, localeLen, locale); + } + } + else + { + if((pList = (XpDiListEntry **)xalloc(2 * sizeof(XpDiListEntry *))) == + (XpDiListEntry **)NULL) + return pList; + + if((pList[0] = (XpDiListEntry *)xalloc(sizeof(XpDiListEntry))) == + (XpDiListEntry *)NULL) + { + xfree(pList); + return (XpDiListEntry **)NULL; + } + pList[1] = (XpDiListEntry *)NULL; + if(GetPrinterListInfo(pList[0], nameLen, name, localeLen, locale) == + FALSE) + { + xfree(pList[0]); + pList[0] = (XpDiListEntry *)NULL; + } + } + return pList; +} + +WindowPtr +XpDiValidatePrinter(char *printerName, int printerNameLen) +{ + PrinterDbPtr pCurEntry; + WindowPtr pWin; + + for(pCurEntry = printerDb; + pCurEntry != (PrinterDbPtr)NULL; pCurEntry = pCurEntry->next) + { + if(strlen(pCurEntry->name) == printerNameLen && + !strncmp(pCurEntry->name, printerName, printerNameLen)) + return WindowTable[pCurEntry->screenNum]; + } + return (WindowPtr)NULL; +} + +/* + * XpDiGetDriverName takes a screen index and a printer name, and returns + * a pointer to the name of the driver to be used for the specified printer + * on the specified screen. + */ +char * +XpDiGetDriverName(int index, char *printerName) +{ + + PrinterDbPtr pCurEntry; + + for(pCurEntry = printerDb; + pCurEntry != (PrinterDbPtr)NULL; pCurEntry = pCurEntry->next) + { + if(pCurEntry->screenNum == index && + !strcmp(pCurEntry->name, printerName)) + return pCurEntry->driverName; + } + + return (char *)NULL; /* XXX Should we supply a default driverName? */ +} + |