1
/* $Xorg: Init.c,v 1.5 2001/03/07 17:31:33 pookie Exp $ */
3
(c) Copyright 1996 Hewlett-Packard Company
4
(c) Copyright 1996 International Business Machines Corp.
5
(c) Copyright 1996 Sun Microsystems, Inc.
6
(c) Copyright 1996 Novell, Inc.
7
(c) Copyright 1996 Digital Equipment Corp.
8
(c) Copyright 1996 Fujitsu Limited
9
(c) Copyright 1996 Hitachi, Ltd.
11
Permission is hereby granted, free of charge, to any person obtaining a copy
12
of this software and associated documentation files (the "Software"), to deal
13
in the Software without restriction, including without limitation the rights
14
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
copies of the Software, and to permit persons to whom the Software is
16
furnished to do so, subject to the following conditions:
18
The above copyright notice and this permission notice shall be included in
19
all copies or substantial portions of the Software.
21
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
25
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
Except as contained in this notice, the names of the copyright holders shall
29
not be used in advertising or otherwise to promote the sale, use or other
30
dealings in this Software without prior written authorization from said
33
/*******************************************************************
35
** *********************************************************
37
** * File: printer/Init.c
40
** * The InitOutput routine here would presumably
41
** * be called from the normal server's InitOutput
42
** * after all display screens have been added.
43
** * There is are ifdef'd routines suitable for
44
** * use in building a printer-only server. Turn
45
** * on the "PRINTER_ONLY_SERVER" define if this is
46
** * to be the only ddx-level driver.
48
** * Copyright: Copyright 1993,1995 Hewlett-Packard Company
50
** *********************************************************
52
********************************************************************/
53
/* $XFree86: xc/programs/Xserver/Xprint/Init.c,v 1.13 2001/12/21 21:02:04 dawes Exp $ */
60
#include <sys/types.h>
65
#include <sys/sysmacros.h>
73
#include "screenint.h"
77
#include "windowstr.h"
81
#include "fonts/fontstruct.h"
84
typedef char *XPointer;
85
#define HAVE_XPointer 1
88
#include <Xresource.h>
91
#include "attributes.h"
95
static void GenericScreenInit(
100
static Bool InitPrintDrivers(
107
* The following two defines are used to build the name "X*printers", where
108
* the "*" is replaced by the display number. This is used to construct
109
* the name of the default printers configuration file if the -XpFile
110
* command line option was not specified.
112
#define XNPRINTERSFILEPREFIX "/X"
113
#define XNPRINTERSFILESUFFIX "printers"
114
#define XPRINTERSFILENAME "Xprinters"
116
#define MODELDIRNAME "/models"
117
#define FONTDIRNAME "/fonts"
120
* The string LIST_QUEUES is fed to a shell to generate an ordered
121
* list of available printers on the system. These string definitions
122
* are taken from the file PrintSubSys.C within the code for the
123
* dtprintinfo program.
126
const char *LIST_QUEUES = "lsallq | grep -v '^bsh$' | sort";
129
const char *LIST_QUEUES = "LANG=C lpstat -v | "
133
" x = match($3, /:/); "
134
" print substr($3, 1, x-1)"
138
const char *LIST_QUEUES = "LANG=C lpstat -v | "
145
const char *LIST_QUEUES = "LANG=C lpstat -v | "
149
" x = match($5, /:/); "
150
" print substr($5, 1, x-1)"
153
#if defined(CSRG_BASED) || defined(linux) || defined(ISC) || defined(__GNUC__)
154
const char *LIST_QUEUES = "LANG=C lpc status | grep -v '^\t' | "
155
"sed -e /:/s/// | sort";
157
const char *LIST_QUEUES = "LANG=C lpstat -v | "
161
" x = match($3, /:/); "
162
" print substr($3, 1, x-1)"
173
PixmapFormatRec RasterPixmapFormats[] = {
174
{ 1, 1, BITMAP_SCANLINE_PAD }
176
#define NUMRASTFORMATS (sizeof RasterPixmapFormats)/(sizeof RasterPixmapFormats[0])
178
#include "raster/Raster.h"
185
PixmapFormatRec ColorPclPixmapFormats[] = {
186
{ 1, 1, BITMAP_SCANLINE_PAD },
187
{ 8, 8, BITMAP_SCANLINE_PAD },
188
{ 24,32, BITMAP_SCANLINE_PAD }
191
#define NUMCPCLFORMATS (sizeof ColorPclPixmapFormats)/(sizeof ColorPclPixmapFormats[0])
198
PixmapFormatRec MonoPclPixmapFormats[] = {
199
{ 1, 1, BITMAP_SCANLINE_PAD }
202
#define NUMMPCLFORMATS (sizeof MonoPclPixmapFormats)/(sizeof MonoPclPixmapFormats[0])
206
#if defined(XPPCLDDX) || defined(XPMONOPCLDDX)
213
PixmapFormatRec PSPixmapFormats[] = {
214
{ 1, 1, BITMAP_SCANLINE_PAD },
215
{ 8, 8, BITMAP_SCANLINE_PAD },
216
{ 24,32, BITMAP_SCANLINE_PAD }
219
#define NUMPSFORMATS (sizeof PSPixmapFormats)/(sizeof PSPixmapFormats[0])
226
* The driverInitArray contains an entry for each driver the
227
* server knows about. Each element contains pointers to pixmap formats, the
228
* driver's initialization routine, and pointers to the driver's
229
* attribute validation rec, and/or a driver function which
230
* returns the maximum medium width&height, and maximum resolution
231
* given a printer name. Either the validation rec OR the dimension
232
* function can be NULL. If the function is non-NULL then it
233
* will be called, and will be passed the (possibly NULL) validation rec.
234
* If the function is NULL, then XpGetMaxWidthHeightRes() is called.
236
typedef struct _driverInitRec {
239
XpValidatePoolsRec *pValRec;
240
pVFunc dimensionsFunc;
241
PixmapFormatRec *pFmts;
245
static driverInitRec driverInits[] = {
249
InitializeRasterDriver,
250
&RasterValidatePoolsRec,
259
InitializeColorPclDriver,
260
&PclValidatePoolsRec,
262
ColorPclPixmapFormats,
269
InitializeMonoPclDriver,
270
&PclValidatePoolsRec,
272
MonoPclPixmapFormats,
290
* The printerDb variable points to a list of PrinterDbEntry structs
291
* which map printer names with screen numbers and driver names.
293
typedef struct _printerDbEntry {
294
struct _printerDbEntry *next;
299
} PrinterDbEntry, *PrinterDbPtr;
301
static PrinterDbPtr printerDb = (PrinterDbPtr)NULL;
304
* The nameMap is a list used in initializing the attribute store
305
* for each printer. The list is freed once the printerDb is built
306
* and the attribute stores for all printers have been initialized.
308
typedef struct _nameMapEntry {
309
struct _nameMapEntry *next;
312
} NameMapEntry, *NameMapPtr;
314
static NameMapPtr nameMap = (NameMapPtr)NULL;
317
* The driverMap is a list which provides the mapping between driver names
318
* and screen numbers. It is built and used
319
* by RehashPrinterList to correctly fill in the screenNum field in the
320
* printerDb entries. The list is freed before RehashPrinterList terminates.
322
typedef struct _driverMapping {
323
struct _driverMapping *next;
326
} DriverMapEntry, *DriverMapPtr;
328
static const char configFilePath[] =
329
"/etc/dt/config/print:/usr/dt/config/print";
331
static const char printServerConfigDir[] = "XPSERVERCONFIGDIR";
333
static char *configFileName = (char *)NULL;
334
static Bool freeDefaultFontPath = FALSE;
335
static char *origFontPath = (char *)NULL;
338
* XprintOptions checks argv[i] to see if it is our command line
339
* option specifying a configuration file name. It returns the index
340
* of the next option to process.
348
if(strcmp(argv[i], "-XpFile") == 0)
350
if ((i + 1) >= argc) {
354
configFileName = argv[i + 1];
361
/************************************************************
364
* This routine is called from the InitPrintDrivers function.
365
* Given the name of a driver, return a pointer to the driver's
366
* initialization function.
369
* Returns a pointer to the initialization function for the driver.
372
************************************************************/
375
typedef Bool (*pIFunc)();
377
GetInitFunc(driverName)
380
static pBFunc GetInitFunc(char *driverName)
382
driverInitRec *pInitRec;
383
int numDrivers = sizeof(driverInits)/sizeof(driverInitRec);
386
for(pInitRec = driverInits, i = 0; i < numDrivers; pInitRec++, i++)
388
if( !strcmp( driverName, pInitRec->driverName ) )
389
return pInitRec->initFunc;
398
XpValidatePoolsRec **pValRec,
399
pVFunc *dimensionsFunc)
401
driverInitRec *pInitRec;
402
int numDrivers = sizeof(driverInits)/sizeof(driverInitRec);
405
for(pInitRec = driverInits, i = 0; i < numDrivers; pInitRec++, i++)
407
if( !strcmp( driverName, pInitRec->driverName ) )
409
*dimensionsFunc = pInitRec->dimensionsFunc;
410
*pValRec = pInitRec->pValRec;
423
PrinterDbPtr pCurEntry, pNextEntry;
425
for(pCurEntry = printerDb, pNextEntry = 0;
426
pCurEntry != (PrinterDbPtr)NULL; pCurEntry = pNextEntry)
428
pNextEntry = pCurEntry->next;
429
if(pCurEntry->name != (char *)NULL)
430
xfree(pCurEntry->name);
432
* We don't free the driver name, because it's expected to simply
433
* be a pointer into the xrm database.
441
* AddPrinterDbName allocates an entry in the printerDb list, and
442
* initializes the "name". It returns TRUE if the element was
443
* successfully added, and FALSE if an allocation error ocurred.
444
* XXX AddPrinterDbName needs to check for (and not add) duplicate names.
447
AddPrinterDbName(char *name)
449
PrinterDbPtr pEntry = (PrinterDbPtr)xalloc(sizeof(PrinterDbEntry));
451
if(pEntry == (PrinterDbPtr)NULL) return FALSE;
452
pEntry->name = strdup(name);
453
pEntry->qualifier = (char *)NULL;
455
if(printerDb == (PrinterDbPtr)NULL)
457
pEntry->next = (PrinterDbPtr)NULL;
462
pEntry->next = printerDb;
469
AugmentPrinterDb(const char *command)
474
fp = popen(command, "r");
475
/* XXX is a 256 character limit overly restrictive for printer names? */
476
while(fgets(name, 256, fp) != (char *)NULL && strlen(name))
478
name[strlen(name) - 1] = (char)'\0'; /* strip the \n */
479
AddPrinterDbName(name);
485
* FreeNameMap frees all remaining memory associated with the nameMap.
490
NameMapPtr pEntry, pTmp;
492
for(pEntry = nameMap, pTmp = (NameMapPtr)NULL;
493
pEntry != (NameMapPtr)NULL;
496
if(pEntry->name != (char *)NULL)
498
if(pEntry->qualifier != (char *)NULL)
499
xfree(pEntry->qualifier);
503
nameMap = (NameMapPtr)NULL;
507
* AddNameMap adds an element to the nameMap linked list.
510
AddNameMap(char *name, char *qualifier)
514
if((pEntry = (NameMapPtr)xalloc(sizeof(NameMapEntry))) == (NameMapPtr)NULL)
517
pEntry->qualifier = qualifier;
518
pEntry->next = nameMap;
524
* MergeNameMap - puts the "map" names (aka qualifiers, aliases) into
525
* the printerDb. This should be called once, after both the printerDb
526
* and nameMap lists are complete. When/if MergeNameMap finds a map for
527
* an entry in the printerDb, the qualifier is _moved_ (not copied) to
528
* the printerDb. This means that the qualifier pointer in the nameMap
537
for(pMap = nameMap; pMap != (NameMapPtr)NULL; pMap = pMap->next)
539
for(pDb = printerDb; pDb != (PrinterDbPtr)NULL; pDb = pDb->next)
541
if(!strcmp(pMap->name, pDb->name))
543
pDb->qualifier = pMap->qualifier;
544
pMap->qualifier = (char *)NULL;
551
* CreatePrinterAttrs causes the attribute stores to be built for
552
* each printer in the printerDb.
555
CreatePrinterAttrs(void)
559
for(pDb = printerDb; pDb != (PrinterDbPtr)NULL; pDb = pDb->next)
561
XpBuildAttributeStore(pDb->name, (pDb->qualifier)?
562
pDb->qualifier : pDb->name);
567
#define defaultDriver "XP-POSTSCRIPT"
570
#define defaultDriver "XP-PCL-COLOR"
573
#define defaultDriver "XP-PCL-MONO"
575
#define defaultDriver "XP-RASTER"
581
* StoreDriverNames - queries the attribute store for the ddx-identifier.
582
* if the ddx-identifier is not in the attribute database, then a default
583
* ddx-identifier is store in both the attribute store for the printer,
584
* and in the printerDb.
585
* The ddx-identifier is stored in the printerDb for use in initializing
589
StoreDriverNames(void)
593
for(pEntry = printerDb; pEntry != (PrinterDbPtr)NULL;
594
pEntry = pEntry->next)
596
pEntry->driverName = (char*)XpGetPrinterAttribute(pEntry->name,
597
"xp-ddx-identifier");
598
if(pEntry->driverName == (char *)NULL ||
599
strlen(pEntry->driverName) == 0 ||
600
GetInitFunc(pEntry->driverName) == 0)
602
if (pEntry->driverName && (strlen(pEntry->driverName) != 0)) {
603
ErrorF("Xp Extension: Can't load driver %s\n",
605
ErrorF(" init function missing\n");
608
pEntry->driverName = defaultDriver;
609
XpAddPrinterAttribute(pEntry->name,
610
(pEntry->qualifier != (char *)NULL)?
611
pEntry->qualifier : pEntry->name,
612
"*xp-ddx-identifier", pEntry->driverName);
622
size_t mbCurMax = MB_CUR_MAX;
623
wchar_t targetChar, curChar;
625
int i, numBytes, byteLen;
627
if(mbCurMax <= 1) return strchr(str, ch);
630
mbtowc(&targetChar, &tmpChar, mbCurMax);
631
for(i = 0, numBytes = 0, byteLen = strlen(str); i < byteLen; i += numBytes)
633
numBytes = mbtowc(&curChar, &str[i], mbCurMax);
634
if(curChar == targetChar) return &str[i];
640
* GetConfigFileName - Looks for a "Xprinters" file in
641
* $(XPRINTDIR)/$LANG/print, and then in $(XPRINTDIR)/C/print. If it
642
* finds such a file, it returns the path to the file. The returned
643
* string must be freed by the caller.
646
GetConfigFileName(void)
649
* We need to find the system-wide file, if one exists. This
650
* file can be in either $(XPRINTDIR)/$LANG/print, or in
651
* $(PRINTDIR)/C/print, and the file itself is named "Xprinters".
653
char *dirName, *filePath;
656
* Check for a LANG-specific file.
658
if ((dirName = XpGetConfigDir(TRUE)) != 0)
660
filePath = (char *)xalloc(strlen(dirName) +
661
strlen(XPRINTERSFILENAME) + 2);
663
if(filePath == (char *)NULL)
669
sprintf(filePath, "%s/%s", dirName, XPRINTERSFILENAME);
671
if(access(filePath, R_OK) == 0)
677
if ((dirName = XpGetConfigDir(FALSE)) != 0)
679
filePath = (char *)xalloc(strlen(dirName) +
680
strlen(XPRINTERSFILENAME) + 2);
681
if(filePath == (char *)NULL)
686
sprintf(filePath, "%s/%s", dirName, XPRINTERSFILENAME);
688
if(access(filePath, R_OK) == 0)
696
* BuildPrinterDb - reads the config file if it exists, and if necessary
697
* executes a command such as lpstat to generate a list of printers.
699
* XXX BuildPrinterDb must be rewritten to allow 16-bit characters in
700
* XXX printer names. The will involve replacing the use of strtok() and its
701
* XXX related functions.
702
* XXX At the same time, BuildPrinterDb and it's support routines should have
703
* XXX allocation error checking added.
709
Bool defaultAugment = TRUE, freeConfigFileName;
711
if(configFileName && access(configFileName, R_OK) != 0)
713
ErrorF("Xp Extension: Can't open file %s\n", configFileName);
715
if(!configFileName && (configFileName = GetConfigFileName()))
716
freeConfigFileName = TRUE;
718
freeConfigFileName = FALSE;
720
if(configFileName != (char *)NULL && access(configFileName, R_OK) == 0)
723
FILE *fp = fopen(configFileName, "r");
725
while(fgets(line, 256, fp) != (char *)NULL)
728
if((tok = strtok(line, " \t\012")) != (char *)NULL)
730
if(tok[0] == (char)'#') continue;
731
if(strcmp(tok, "Printer") == 0)
733
while((tok = strtok((char *)NULL, " \t")) != (char *)NULL)
735
if ((ptr = MbStrchr(tok, '\012')) != 0)
737
AddPrinterDbName(tok);
740
else if(strcmp(tok, "Map") == 0)
742
char *name, *qualifier;
744
if((tok = strtok((char *)NULL, " \t\012")) == (char *)NULL)
747
if((tok = strtok((char *)NULL, " \t\012")) == (char *)NULL)
752
qualifier = strdup(tok);
753
AddNameMap(name, qualifier);
755
else if(strcmp(tok, "Augment_Printer_List") == 0)
757
if((tok = strtok((char *)NULL, " \t\012")) == (char *)NULL)
760
if(strcmp(tok, "%default%") == 0)
762
defaultAugment = FALSE;
763
if(strcmp(tok, "%none%") == 0)
765
AugmentPrinterDb(tok);
768
break; /* XXX Generate an error? */
774
if(defaultAugment == TRUE)
776
AugmentPrinterDb(LIST_QUEUES);
782
/* Create the attribute stores for all printers */
783
CreatePrinterAttrs();
786
* Find the drivers for each printers, and store the driver names
791
if(freeConfigFileName)
793
xfree(configFileName);
794
configFileName = (char *)NULL;
801
FreeDriverMap(DriverMapPtr driverMap)
803
DriverMapPtr pCurEntry, pNextEntry;
805
for(pCurEntry = driverMap, pNextEntry = (DriverMapPtr)NULL;
806
pCurEntry != (DriverMapPtr)NULL; pCurEntry = pNextEntry)
808
pNextEntry = pCurEntry->next;
809
if(pCurEntry->driverName != (char *)NULL)
810
xfree(pCurEntry->driverName);
816
* XpRehashPrinterList rebuilds the list of printers known to the
817
* server. It first walks the printerDb to build a table mapping
818
* driver names and screen numbers, since this is not an easy mapping
819
* to change in the sample server. The normal configuration files are
820
* then read & parsed to create the new list of printers. Printers
821
* which require drivers other than those already initialized are
822
* deleted from the printerDb. This leaves attribute stores in place
823
* for inaccessible printers, but those stores will be cleaned up in
824
* the next rehash or server recycle.
827
XpRehashPrinterList(void)
829
PrinterDbPtr pEntry, pPrev;
830
DriverMapPtr driverMap = (DriverMapPtr)NULL, pDrvEnt;
833
/* Build driverMap */
834
for(pEntry = printerDb; pEntry != (PrinterDbPtr)NULL; pEntry = pEntry->next)
836
for(pDrvEnt = driverMap; pDrvEnt != (DriverMapPtr)NULL;
837
pDrvEnt = pDrvEnt->next)
839
if(!strcmp(pEntry->driverName, pDrvEnt->driverName))
843
if(pDrvEnt != (DriverMapPtr)NULL)
846
if((pDrvEnt = (DriverMapPtr)xalloc(sizeof(DriverMapEntry))) ==
849
FreeDriverMap(driverMap);
852
pDrvEnt->driverName = strdup(pEntry->driverName);
853
pDrvEnt->screenNum = pEntry->screenNum;
854
pDrvEnt->next = driverMap;
858
/* Free the old printerDb */
861
/* Free/Rehash attribute stores */
862
if((result = XpRehashAttributes()) != Success)
865
/* Build a new printerDb */
866
if(BuildPrinterDb() == (PrinterDbPtr)NULL)
869
/* Walk PrinterDb & either store screenNum, or delete printerDb entry */
870
for(pEntry = printerDb, pPrev = (PrinterDbPtr)NULL;
871
pEntry != (PrinterDbPtr)NULL; pEntry = pEntry->next)
873
for(pDrvEnt = driverMap; pDrvEnt != (DriverMapPtr)NULL;
874
pDrvEnt = pDrvEnt->next)
876
if(!strcmp(printerDb->driverName, pDrvEnt->driverName))
881
* Either store the screen number, or delete the printerDb entry.
882
* Deleting the entry leaves orphaned attribute stores, but they'll
883
* get cleaned up at the next rehash or server recycle.
885
if(pDrvEnt != (DriverMapPtr)NULL)
887
pEntry->screenNum = pDrvEnt->screenNum;
892
pPrev->next = pEntry->next;
894
pPrev = pEntry->next;
895
if(pEntry->name != (char *)NULL)
902
FreeDriverMap(driverMap);
908
* ValidateFontDir looks for a valid font directory for the specified
909
* printer model within the specified configuration directory. It returns
910
* the directory name, or NULL if no valid font directory was found.
911
* It is the caller's responsibility to free the returned font directory
921
if(!configDir || !modelName)
924
pathName = (char *)xalloc(strlen(configDir) + strlen(MODELDIRNAME) +
925
strlen(modelName) + strlen(FONTDIRNAME) +
926
strlen("fonts.dir") + 5);
929
sprintf(pathName, "%s/%s/%s/%s/%s", configDir, MODELDIRNAME, modelName,
930
FONTDIRNAME, "fonts.dir");
931
if(access(pathName, R_OK) != 0)
936
pathName[strlen(pathName) - 9] = (char)'\0'; /* erase fonts.dir */
941
* FindFontDir returns a pointer to the path name of the font directory
942
* for the specified printer model name, if such a directory exists.
943
* The directory contents are superficially checked for validity.
944
* The caller must free the returned char *.
946
* We first look in the locale-specific model-config directory, and
947
* then fall back to the C language model-config directory.
953
char *configDir, *fontDir;
955
if(!modelName || !strlen(modelName))
958
configDir = XpGetConfigDir(TRUE);
959
if ((fontDir = ValidateFontDir(configDir, modelName)) != 0)
967
configDir = XpGetConfigDir(FALSE);
968
fontDir = ValidateFontDir(configDir, modelName);
976
* AddToFontPath adds the specified font path element to the global
977
* defaultFontPath string. It adds the keyword "PRINTER:" to the front
978
* of the path to denote that this is a printer-specific font path
981
static char PATH_PREFIX[] = "PRINTER:";
982
static int PATH_PREFIX_LEN = sizeof(PATH_PREFIX) - 1; /* same as strlen() */
991
if(defaultFontPath == origFontPath)
996
newPath = (char *)xalloc(strlen(defaultFontPath) + strlen(pathName) +
997
PATH_PREFIX_LEN + 2);
999
sprintf(newPath, "%s%s,%s", PATH_PREFIX, pathName, defaultFontPath);
1002
xfree(defaultFontPath);
1004
defaultFontPath = newPath;
1009
* AugmentFontPath adds printer-model-specific font path elements to
1010
* the front of the font path global variable "defaultFontPath" (dix/globals.c).
1011
* We can't call SetFontPath() because the font code has not yet been
1012
* initialized when InitOutput is called (from whence this routine is called).
1014
* This utilizes the static variables origFontPath and
1015
* freeDefaultFontPath to track the original contents of defaultFontPath,
1016
* and to properly free the modified version upon server recycle.
1019
AugmentFontPath(void)
1021
char *modelID, **allIDs = (char **)NULL;
1022
PrinterDbPtr pDbEntry;
1026
origFontPath = defaultFontPath;
1028
if(freeDefaultFontPath)
1030
xfree(defaultFontPath);
1031
defaultFontPath = origFontPath;
1032
freeDefaultFontPath = FALSE;
1036
* Build a list of printer models to check for internal fonts.
1038
for(pDbEntry = printerDb, numModels = 0;
1039
pDbEntry != (PrinterDbPtr)NULL;
1040
pDbEntry = pDbEntry->next)
1043
(char*)XpGetPrinterAttribute(pDbEntry->name,
1044
"xp-model-identifier");
1046
if(modelID && strlen(modelID) != 0)
1048
/* look for current model in the list of allIDs */
1049
for(i = 0; i < numModels; i++)
1051
if(!strcmp(modelID, allIDs[i]))
1053
modelID = (char *)NULL;
1060
* If this printer's model-identifier isn't in the allIDs list,
1061
* then add it to allIDs.
1063
if(modelID && strlen(modelID) != 0)
1065
allIDs = (char **)xrealloc(allIDs, (numModels+2) * sizeof(char *));
1066
if(allIDs == (char **)NULL)
1068
allIDs[numModels] = modelID;
1069
allIDs[numModels + 1] = (char *)NULL;
1074
/* for each model, check for a valid font directory, and add it to
1075
* the front of defaultFontPath.
1077
for(i = 0; allIDs != (char **)NULL && allIDs[i] != (char *)NULL; i ++)
1080
if ((fontDir = FindFontDir(allIDs[i])) != 0)
1082
AddToFontPath(fontDir);
1084
freeDefaultFontPath = TRUE;
1095
* XpClientIsBitmapClient is called by the font code to find out if
1096
* a particular client should be granted access to bitmap fonts.
1097
* This function works by
1098
* calling XpContextOfClient (in Xserver/Xext/xprint.c) to determine
1099
* the context associated with the client, and then queries the context's
1100
* attributes to determine whether the bitmap fonts should be visible.
1101
* It looks at the value of the xp-listfonts-mode document/page attribute to
1102
* see if xp-list-glyph-fonts has been left out of the mode list. Only
1103
* if the xp-listfonts-mode attribute exists, and it does not contain
1104
* xp-list-glyph-fonts does this function return FALSE. In any other
1105
* case the funtion returns TRUE, indicating that the bitmap fonts
1106
* should be visible to the client.
1109
XpClientIsBitmapClient(
1112
XpContextPtr pContext;
1115
if(!(pContext = XpContextOfClient(client)))
1119
* Check the page attributes, and if it's not defined there, then
1120
* check the document attributes.
1122
mode = XpGetOneAttribute(pContext, XPPageAttr, "xp-listfonts-mode");
1123
if(!mode || !strlen(mode))
1125
mode = XpGetOneAttribute(pContext, XPDocAttr, "xp-listfonts-mode");
1126
if(!mode || !strlen(mode))
1130
if(!strstr(mode, "xp-list-glyph-fonts"))
1136
* XpClientIsPrintClient is called by the font code to find out if
1137
* a particular client has set a context which references a printer
1138
* which utilizes a particular font path. This function works by
1139
* calling XpContextOfClient (in Xserver/Xext/xprint.c) to determine
1140
* the context associated with the client, and then looks up the
1141
* font directory for the context. The font directory is then compared
1142
* with the directory specified in the FontPathElement which is passed in.
1145
XpClientIsPrintClient(
1147
FontPathElementPtr fpe)
1149
XpContextPtr pContext;
1150
char *modelID, *fontDir;
1152
if(!(pContext = XpContextOfClient(client)))
1158
modelID = XpGetOneAttribute(pContext, XPPrinterAttr, "xp-model-identifier");
1159
if(!modelID || !strlen(modelID))
1162
if(!(fontDir = FindFontDir(modelID)))
1166
* The grunge here is to ignore the PATH_PREFIX at the front of the
1169
if(fpe->name_length < PATH_PREFIX_LEN ||
1170
(strlen(fontDir) != (unsigned)(fpe->name_length - PATH_PREFIX_LEN)) ||
1171
strncmp(fontDir, fpe->name + PATH_PREFIX_LEN,
1172
fpe->name_length - PATH_PREFIX_LEN))
1182
AddFormats(ScreenInfo *pScreenInfo, char *driverName)
1185
driverInitRec *pInitRec;
1186
int numDrivers = sizeof(driverInits)/sizeof(driverInitRec);
1187
PixmapFormatRec *formats;
1190
for (pInitRec = driverInits, i = 0; i < numDrivers; pInitRec++, i++)
1192
if ( !strcmp( driverName, pInitRec->driverName ) )
1195
if (i >= numDrivers)
1197
formats = pInitRec->pFmts;
1198
numfmts = pInitRec->numFmts;
1199
for (i = 0; i < numfmts && pScreenInfo->numPixmapFormats < MAXFORMATS; i++)
1201
for (j = 0; j < pScreenInfo->numPixmapFormats; j++) {
1202
if (pScreenInfo->formats[j].depth == formats[i].depth &&
1203
pScreenInfo->formats[j].bitsPerPixel == formats[i].bitsPerPixel &&
1204
pScreenInfo->formats[j].scanlinePad == formats[i].scanlinePad)
1207
if (j == pScreenInfo->numPixmapFormats) {
1208
pScreenInfo->formats[j] = formats[i];
1209
pScreenInfo->numPixmapFormats++;
1214
/************************************************************
1215
* PrinterInitOutput --
1216
* This routine is to be called from a ddx's InitOutput
1217
* during the server startup initialization, and when
1218
* the server is to be reset. The routine creates the
1219
* screens associated with configured printers by calling
1220
* dix:AddScreen. The configuration information comes from a
1221
* database read from the X*printers file.
1224
* The array of ScreenRec pointers referenced by
1225
* pScreenInfo->screen is increased by the addition
1226
* of the printer screen(s), as is the value of
1227
* pScreenInfo->numScreens. This is done via calls
1228
* to AddScreen() in dix.
1230
************************************************************/
1234
ScreenInfo *pScreenInfo,
1238
PrinterDbPtr pDb, pDbEntry;
1239
int driverCount = 0, i;
1244
* this little test is just a warning at startup to make sure
1245
* that the config directory exists.
1247
* what this ugly looking if says is that if both ways of
1248
* calling configDir works and both directories don't exist,
1249
* then print an error saying we can't find the non-lang one.
1251
if (((configDir = XpGetConfigDir(TRUE)) != NULL) &&
1252
(access(configDir, F_OK) == 0))
1256
else if (((configDir = XpGetConfigDir(FALSE)) != NULL) &&
1257
(access(configDir, F_OK) == 0))
1262
ErrorF("Xp Extension: could not find config dir %s\n",
1263
configDir ? configDir : XPRINTDIR);
1265
if (configDir) xfree(configDir);
1268
if(printerDb != (PrinterDbPtr)NULL)
1272
* Calling BuildPrinterDb serves to build the printer database,
1273
* and to initialize the attribute store for each printer.
1274
* The driver can, if it so desires, modify the attribute
1275
* store at a later time.
1277
if((pDb = BuildPrinterDb()) == (PrinterDbPtr)NULL) return;
1280
* We now have to decide how many screens to initialize, and call
1281
* AddScreen for each one. The printerDb must be properly initialized
1282
* for at least one screen's worth of printers prior to calling AddScreen
1283
* because InitPrintDrivers reads the printerDb to determine which
1284
* driver(s) to init on a particular screen.
1285
* We put each driver's printers on a different
1286
* screen, and call AddScreen for each screen/driver pair.
1288
/* count the number of printers */
1289
for(pDbEntry = pDb, driverCount = 0; pDbEntry != (PrinterDbPtr)NULL;
1290
pDbEntry = pDbEntry->next, driverCount++)
1293
* Allocate memory for the worst case - a driver per printer
1295
driverNames = (char **)xalloc(sizeof(char *) * driverCount);
1298
* Assign the driver for the first printer to the first screen
1300
pDb->screenNum = screenInfo.numScreens;
1301
driverNames[0] = pDb->driverName;
1303
AddFormats(pScreenInfo, pDb->driverName);
1306
* For each printer, look to see if its driver is already assigned
1307
* to a screen, and if so copy that screen number into the printerDb.
1308
* Otherwise, assign a new screen number to the driver for this
1311
for(pDbEntry = pDb; pDbEntry != (PrinterDbPtr)NULL;
1312
pDbEntry = pDbEntry->next)
1316
for(i = 0, foundMatch = FALSE; i < driverCount; i++)
1318
if(!strcmp(driverNames[i], pDbEntry->driverName))
1321
pDbEntry->screenNum = screenInfo.numScreens + i;
1325
if(foundMatch == FALSE)
1327
driverNames[driverCount] = pDbEntry->driverName;
1328
pDbEntry->screenNum = screenInfo.numScreens + driverCount;
1329
AddFormats(pScreenInfo, pDbEntry->driverName);
1334
for(i = 0; i < driverCount; i++)
1336
int curScreen = screenInfo.numScreens;
1337
if(AddScreen(InitPrintDrivers, argc, argv) < 0)
1341
* AddScreen failed, so we pull the associated printers
1344
ErrorF("Xp Extension: Could not add screen for driver %s\n",
1346
for(pPrev = pDbEntry = printerDb; pDbEntry != (PrinterDbPtr)NULL;
1347
pDbEntry = pDbEntry->next)
1349
if(pDbEntry->screenNum == curScreen)
1351
if(pPrev == printerDb)
1353
printerDb = pDbEntry->next;
1357
pPrev->next = pDbEntry->next;
1359
xfree(pDbEntry->name);
1365
if(pDbEntry->screenNum > curScreen)
1366
pDbEntry->screenNum--;
1377
if(pScreenInfo->numScreens > MAXSCREENS)
1379
ErrorF("The number of printer screens requested ");
1380
ErrorF("exceeds the allowable limit of %d screens.\n", MAXSCREENS);
1381
ErrorF("Please reduce the number of requested printers in your ");
1382
ErrorF("\nX%sprinters file.", display);
1383
ErrorF("Server exiting...\n");
1389
* InitPrintDrivers is called from dix:AddScreen. It in turn calls the
1390
* driver initialization routine for any and all drivers which are
1391
* implicated in supporting printers on the particular screen number
1392
* specified by the "index" parameter. The printerDb variable is used
1393
* to determine which printers are to be associated with a particular
1403
PrinterDbPtr pDb, pDb2;
1405
GenericScreenInit(index, pScreen, argc, argv);
1407
for(pDb = printerDb; pDb != (PrinterDbPtr)NULL; pDb = pDb->next)
1409
if(pDb->screenNum == index)
1411
Bool callInit = TRUE;
1412
for(pDb2 = printerDb; pDb2 != pDb; pDb2 = pDb2->next)
1414
if(!strcmp(pDb->driverName, pDb2->driverName))
1420
if(callInit == TRUE)
1423
initFunc = GetInitFunc(pDb->driverName);
1424
if(initFunc(index, pScreen, argc, argv) == FALSE)
1426
/* XXX - What do I do if the driver's init fails? */
1447
* GenericScreenInit - The common initializations required by all
1448
* printer screens and drivers. It sets the screen's cursor functions
1449
* to Noops, and computes the maximum screen (i.e. medium) dimensions.
1459
float fWidth, fHeight, maxWidth, maxHeight;
1460
unsigned short width, height;
1465
* Set the cursor ops to no-op functions.
1467
pScreen->DisplayCursor = (DisplayCursorProcPtr)_XpBoolNoop;
1468
pScreen->RealizeCursor = (RealizeCursorProcPtr)_XpBoolNoop;
1469
pScreen->UnrealizeCursor = (UnrealizeCursorProcPtr)_XpBoolNoop;
1470
pScreen->SetCursorPosition = (SetCursorPositionProcPtr)_XpBoolNoop;
1471
pScreen->ConstrainCursor = (ConstrainCursorProcPtr)_XpVoidNoop;
1472
pScreen->CursorLimits = (CursorLimitsProcPtr)_XpVoidNoop;
1473
pScreen->RecolorCursor = (RecolorCursorProcPtr)_XpVoidNoop;
1476
* Find the largest paper size for all the printers on the given
1480
maxWidth = maxHeight = 0.0;
1481
for( pDb = printerDb; pDb != (PrinterDbPtr)NULL; pDb = pDb->next)
1483
if(pDb->screenNum == index)
1485
XpValidatePoolsRec *pValRec;
1486
pVFunc dimensionsFunc;
1488
GetDimFuncAndRec(pDb->driverName, &pValRec, &dimensionsFunc);
1489
if(dimensionsFunc != (pVFunc)NULL)
1490
dimensionsFunc(pDb->name, pValRec, &fWidth, &fHeight, &res);
1492
XpGetMaxWidthHeightRes(pDb->name, pValRec, &fWidth,
1496
if( fWidth > maxWidth )
1498
if( fHeight > maxHeight )
1499
maxHeight = fHeight;
1503
width = (unsigned short) (maxWidth * maxRes / 25.4);
1504
height = (unsigned short) (maxHeight * maxRes / 25.4);
1505
pScreen->width = pScreen->height = ( width > height ) ? width :
1508
pScreen->mmWidth = pScreen->mmHeight = ( maxWidth > maxHeight ) ?
1509
(unsigned short)(maxWidth + 0.5) :
1510
(unsigned short)(maxHeight + 0.5);
1514
* QualifyName - takes an unqualified file name such as X6printers and
1515
* a colon-separated list of directory path names such as
1516
* /etc/opt/dt:/opt/dt/config.
1518
* Returns a fully qualified file path name such as /etc/opt/dt/X6printers.
1519
* The returned value is malloc'd, and the caller is responsible for
1520
* freeing the associated memory.
1527
char * curPath = searchPath;
1532
if (fileName == NULL || searchPath == NULL)
1536
if ((nextPath = strchr(curPath, ':')) != NULL)
1539
chance = (char *)xalloc(strlen(curPath) + strlen(fileName) + 2);
1540
sprintf(chance,"%s/%s",curPath,fileName);
1542
/* see if we can read from the file */
1543
if((pFile = fopen(chance, "r")) != (FILE *)NULL)
1546
/* ... restore the colon, .... */
1555
if (nextPath == NULL) /* End of path list? */
1558
/* try the next path */
1559
curPath = nextPath + 1;
1565
* FillPrinterListEntry fills in a single XpDiListEntry element with data
1566
* derived from the supplied PrinterDbPtr element.
1568
* XXX A smarter (i.e. future) version of this routine might inspect the
1569
* XXX "locale" parameter and attempt to match the "description" and
1570
* XXX "localeName" elements of the XpDiListEntry to the specified locale.
1573
FillPrinterListEntry(
1574
XpDiListEntry *pEntry,
1579
static char *localeStr = (char *)NULL;
1581
if(localeStr == (char *)NULL)
1582
localeStr = strdup(setlocale(LC_ALL, (const char *)NULL));
1584
pEntry->name = pDb->name;
1585
pEntry->description =
1586
(char*)XpGetPrinterAttribute(pDb->name, "descriptor");
1587
pEntry->localeName = localeStr;
1588
pEntry->rootWinId = WindowTable[pDb->screenNum]->drawable.id;
1592
* GetPrinterListInfo fills in the XpDiListEntry struct pointed to by the
1593
* parameter pEntry with the information regarding the printer specified
1594
* by the name and nameLen parameters. The pointers placed in the
1595
* XpDiListEntry structure MUST NOT be freed by the caller. They are
1596
* pointers into existing long-lived databases.
1601
XpDiListEntry *pEntry,
1609
for(pDb = printerDb; pDb != (PrinterDbPtr)NULL; pDb = pDb->next)
1611
if (strlen(pDb->name) == (unsigned)nameLen
1612
&& !strncmp(pDb->name, name, nameLen))
1614
FillPrinterListEntry(pEntry, pDb, localeLen, locale);
1622
* XpDiFreePrinterList is the approved method of releasing memory used
1623
* for a printer list.
1626
XpDiFreePrinterList(XpDiListEntry **list)
1630
for(i = 0; list[i] != (XpDiListEntry *)NULL; i++)
1636
* XpDiGetPrinterList returns a pointer to a NULL-terminated array of
1637
* XpDiListEntry pointers. Each entry structure contains the name,
1638
* description, root window, and locale of a printer. The call returns
1639
* either a list of all printers configured on the server, or it returns
1640
* the information for one specific printer depending on the values passed
1641
* in. Non-NULL values passed in indicate that only the information for
1642
* the one specific printer is desired, while NULL values indicate that
1643
* the information for all printers is desired.
1652
XpDiListEntry **pList;
1654
if(!nameLen || name == (char *)NULL)
1659
for(pDb = printerDb, i = 0; pDb != (PrinterDbPtr)NULL;
1660
pDb = pDb->next, i++)
1663
if((pList = (XpDiListEntry **)xalloc((i+1) * sizeof(XpDiListEntry *)))
1664
== (XpDiListEntry **)NULL)
1667
pList[i] = (XpDiListEntry *)NULL;
1668
for(pDb = printerDb, i = 0; pDb != (PrinterDbPtr)NULL;
1669
pDb = pDb->next, i++)
1671
if((pList[i] = (XpDiListEntry *)xalloc(sizeof(XpDiListEntry)))==
1672
(XpDiListEntry *)NULL)
1674
XpDiFreePrinterList(pList);
1675
return (XpDiListEntry **)NULL;
1677
FillPrinterListEntry(pList[i], pDb, localeLen, locale);
1682
if((pList = (XpDiListEntry **)xalloc(2 * sizeof(XpDiListEntry *))) ==
1683
(XpDiListEntry **)NULL)
1686
if((pList[0] = (XpDiListEntry *)xalloc(sizeof(XpDiListEntry))) ==
1687
(XpDiListEntry *)NULL)
1690
return (XpDiListEntry **)NULL;
1692
pList[1] = (XpDiListEntry *)NULL;
1693
if(GetPrinterListInfo(pList[0], nameLen, name, localeLen, locale) ==
1697
pList[0] = (XpDiListEntry *)NULL;
1704
XpDiValidatePrinter(char *printerName, int printerNameLen)
1706
PrinterDbPtr pCurEntry;
1708
for(pCurEntry = printerDb;
1709
pCurEntry != (PrinterDbPtr)NULL; pCurEntry = pCurEntry->next)
1711
if(strlen(pCurEntry->name) == (unsigned)printerNameLen &&
1712
!strncmp(pCurEntry->name, printerName, printerNameLen))
1713
return WindowTable[pCurEntry->screenNum];
1715
return (WindowPtr)NULL;
1719
* XpDiGetDriverName takes a screen index and a printer name, and returns
1720
* a pointer to the name of the driver to be used for the specified printer
1721
* on the specified screen.
1724
XpDiGetDriverName(int index, char *printerName)
1727
PrinterDbPtr pCurEntry;
1729
for(pCurEntry = printerDb;
1730
pCurEntry != (PrinterDbPtr)NULL; pCurEntry = pCurEntry->next)
1732
if(pCurEntry->screenNum == index &&
1733
!strcmp(pCurEntry->name, printerName))
1734
return pCurEntry->driverName;
1737
return (char *)NULL; /* XXX Should we supply a default driverName? */