1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_vcl.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include <stdio.h>
32*cdf0e10cSrcweir #include <sys/types.h>
33*cdf0e10cSrcweir #include <sys/stat.h>
34*cdf0e10cSrcweir #include <fcntl.h>
35*cdf0e10cSrcweir #include <unistd.h>
36*cdf0e10cSrcweir #include <pwd.h>
37*cdf0e10cSrcweir 
38*cdf0e10cSrcweir #include "psputil.hxx"
39*cdf0e10cSrcweir #include "glyphset.hxx"
40*cdf0e10cSrcweir 
41*cdf0e10cSrcweir #include "printerjob.hxx"
42*cdf0e10cSrcweir #include "printergfx.hxx"
43*cdf0e10cSrcweir #include "vcl/ppdparser.hxx"
44*cdf0e10cSrcweir #include "vcl/strhelper.hxx"
45*cdf0e10cSrcweir #include "vcl/printerinfomanager.hxx"
46*cdf0e10cSrcweir 
47*cdf0e10cSrcweir #include "rtl/ustring.hxx"
48*cdf0e10cSrcweir #include "rtl/strbuf.hxx"
49*cdf0e10cSrcweir #include "rtl/ustrbuf.hxx"
50*cdf0e10cSrcweir 
51*cdf0e10cSrcweir #include "osl/thread.h"
52*cdf0e10cSrcweir #include "sal/alloca.h"
53*cdf0e10cSrcweir 
54*cdf0e10cSrcweir #include <algorithm>
55*cdf0e10cSrcweir #include <vector>
56*cdf0e10cSrcweir 
57*cdf0e10cSrcweir using namespace psp;
58*cdf0e10cSrcweir using namespace rtl;
59*cdf0e10cSrcweir 
60*cdf0e10cSrcweir // forward declaration
61*cdf0e10cSrcweir 
62*cdf0e10cSrcweir #define nBLOCKSIZE 0x2000
63*cdf0e10cSrcweir 
64*cdf0e10cSrcweir namespace psp
65*cdf0e10cSrcweir {
66*cdf0e10cSrcweir 
67*cdf0e10cSrcweir sal_Bool
68*cdf0e10cSrcweir AppendPS (FILE* pDst, osl::File* pSrc, sal_uChar* pBuffer,
69*cdf0e10cSrcweir           sal_uInt32 nBlockSize = nBLOCKSIZE)
70*cdf0e10cSrcweir {
71*cdf0e10cSrcweir     if ((pDst == NULL) || (pSrc == NULL))
72*cdf0e10cSrcweir         return sal_False;
73*cdf0e10cSrcweir 
74*cdf0e10cSrcweir     if (nBlockSize == 0)
75*cdf0e10cSrcweir         nBlockSize = nBLOCKSIZE;
76*cdf0e10cSrcweir     if (pBuffer == NULL)
77*cdf0e10cSrcweir         pBuffer = (sal_uChar*)alloca (nBlockSize);
78*cdf0e10cSrcweir 
79*cdf0e10cSrcweir     pSrc->setPos (osl_Pos_Absolut, 0);
80*cdf0e10cSrcweir 
81*cdf0e10cSrcweir     sal_uInt64 nIn = 0;
82*cdf0e10cSrcweir     sal_uInt64 nOut = 0;
83*cdf0e10cSrcweir     do
84*cdf0e10cSrcweir     {
85*cdf0e10cSrcweir         pSrc->read  (pBuffer, nBlockSize, nIn);
86*cdf0e10cSrcweir         if (nIn > 0)
87*cdf0e10cSrcweir             nOut = fwrite (pBuffer, 1, sal::static_int_cast<sal_uInt32>(nIn), pDst);
88*cdf0e10cSrcweir     }
89*cdf0e10cSrcweir     while ((nIn > 0) && (nIn == nOut));
90*cdf0e10cSrcweir 
91*cdf0e10cSrcweir     return sal_True;
92*cdf0e10cSrcweir }
93*cdf0e10cSrcweir 
94*cdf0e10cSrcweir } // namespace psp
95*cdf0e10cSrcweir 
96*cdf0e10cSrcweir /*
97*cdf0e10cSrcweir  * private convenience routines for file handling
98*cdf0e10cSrcweir  */
99*cdf0e10cSrcweir 
100*cdf0e10cSrcweir osl::File*
101*cdf0e10cSrcweir PrinterJob::CreateSpoolFile (const rtl::OUString& rName, const rtl::OUString& rExtension)
102*cdf0e10cSrcweir {
103*cdf0e10cSrcweir     osl::File::RC nError = osl::File::E_None;
104*cdf0e10cSrcweir     osl::File*    pFile  = NULL;
105*cdf0e10cSrcweir 
106*cdf0e10cSrcweir     rtl::OUString aFile = rName + rExtension;
107*cdf0e10cSrcweir     rtl::OUString aFileURL;
108*cdf0e10cSrcweir 	nError = osl::File::getFileURLFromSystemPath( aFile, aFileURL );
109*cdf0e10cSrcweir     if (nError != osl::File::E_None)
110*cdf0e10cSrcweir         return NULL;
111*cdf0e10cSrcweir     aFileURL = maSpoolDirName + rtl::OUString::createFromAscii ("/") + aFileURL;
112*cdf0e10cSrcweir 
113*cdf0e10cSrcweir     pFile = new osl::File (aFileURL);
114*cdf0e10cSrcweir     nError = pFile->open (OpenFlag_Read | OpenFlag_Write | OpenFlag_Create);
115*cdf0e10cSrcweir     if (nError != osl::File::E_None)
116*cdf0e10cSrcweir     {
117*cdf0e10cSrcweir         delete pFile;
118*cdf0e10cSrcweir         return NULL;
119*cdf0e10cSrcweir     }
120*cdf0e10cSrcweir 
121*cdf0e10cSrcweir     pFile->setAttributes (aFileURL,
122*cdf0e10cSrcweir                           osl_File_Attribute_OwnWrite | osl_File_Attribute_OwnRead);
123*cdf0e10cSrcweir     return pFile;
124*cdf0e10cSrcweir }
125*cdf0e10cSrcweir 
126*cdf0e10cSrcweir /*
127*cdf0e10cSrcweir  * public methods of PrinterJob: for use in PrinterGfx
128*cdf0e10cSrcweir  */
129*cdf0e10cSrcweir 
130*cdf0e10cSrcweir void
131*cdf0e10cSrcweir PrinterJob::GetScale (double &rXScale, double &rYScale) const
132*cdf0e10cSrcweir {
133*cdf0e10cSrcweir     rXScale = mfXScale;
134*cdf0e10cSrcweir     rYScale = mfYScale;
135*cdf0e10cSrcweir }
136*cdf0e10cSrcweir 
137*cdf0e10cSrcweir sal_uInt16
138*cdf0e10cSrcweir PrinterJob::GetDepth () const
139*cdf0e10cSrcweir {
140*cdf0e10cSrcweir     sal_Int32 nLevel = GetPostscriptLevel();
141*cdf0e10cSrcweir     sal_Bool  bColor = IsColorPrinter ();
142*cdf0e10cSrcweir 
143*cdf0e10cSrcweir     return nLevel > 1 && bColor ? 24 : 8;
144*cdf0e10cSrcweir }
145*cdf0e10cSrcweir 
146*cdf0e10cSrcweir sal_uInt16
147*cdf0e10cSrcweir PrinterJob::GetPostscriptLevel (const JobData *pJobData) const
148*cdf0e10cSrcweir {
149*cdf0e10cSrcweir     sal_uInt16 nPSLevel = 2;
150*cdf0e10cSrcweir 
151*cdf0e10cSrcweir     if( pJobData == NULL )
152*cdf0e10cSrcweir         pJobData = &m_aLastJobData;
153*cdf0e10cSrcweir 
154*cdf0e10cSrcweir     if( pJobData->m_nPSLevel )
155*cdf0e10cSrcweir         nPSLevel = pJobData->m_nPSLevel;
156*cdf0e10cSrcweir     else
157*cdf0e10cSrcweir         if( pJobData->m_pParser )
158*cdf0e10cSrcweir             nPSLevel = pJobData->m_pParser->getLanguageLevel();
159*cdf0e10cSrcweir 
160*cdf0e10cSrcweir     return nPSLevel;
161*cdf0e10cSrcweir }
162*cdf0e10cSrcweir 
163*cdf0e10cSrcweir sal_Bool
164*cdf0e10cSrcweir PrinterJob::IsColorPrinter () const
165*cdf0e10cSrcweir {
166*cdf0e10cSrcweir     sal_Bool bColor = sal_False;
167*cdf0e10cSrcweir 
168*cdf0e10cSrcweir     if( m_aLastJobData.m_nColorDevice )
169*cdf0e10cSrcweir         bColor = m_aLastJobData.m_nColorDevice == -1 ? sal_False : sal_True;
170*cdf0e10cSrcweir     else if( m_aLastJobData.m_pParser )
171*cdf0e10cSrcweir         bColor = m_aLastJobData.m_pParser->isColorDevice() ? sal_True : sal_False;
172*cdf0e10cSrcweir 
173*cdf0e10cSrcweir     return bColor;
174*cdf0e10cSrcweir }
175*cdf0e10cSrcweir 
176*cdf0e10cSrcweir osl::File*
177*cdf0e10cSrcweir PrinterJob::GetDocumentHeader ()
178*cdf0e10cSrcweir {
179*cdf0e10cSrcweir     return mpJobHeader;
180*cdf0e10cSrcweir }
181*cdf0e10cSrcweir 
182*cdf0e10cSrcweir osl::File*
183*cdf0e10cSrcweir PrinterJob::GetDocumentTrailer ()
184*cdf0e10cSrcweir {
185*cdf0e10cSrcweir     return mpJobTrailer;
186*cdf0e10cSrcweir }
187*cdf0e10cSrcweir 
188*cdf0e10cSrcweir osl::File*
189*cdf0e10cSrcweir PrinterJob::GetCurrentPageHeader ()
190*cdf0e10cSrcweir {
191*cdf0e10cSrcweir     return maHeaderList.back();
192*cdf0e10cSrcweir }
193*cdf0e10cSrcweir 
194*cdf0e10cSrcweir osl::File*
195*cdf0e10cSrcweir PrinterJob::GetCurrentPageBody ()
196*cdf0e10cSrcweir {
197*cdf0e10cSrcweir     return maPageList.back();
198*cdf0e10cSrcweir }
199*cdf0e10cSrcweir 
200*cdf0e10cSrcweir /*
201*cdf0e10cSrcweir  * public methods of PrinterJob: the actual job / spool handling
202*cdf0e10cSrcweir  */
203*cdf0e10cSrcweir 
204*cdf0e10cSrcweir PrinterJob::PrinterJob () :
205*cdf0e10cSrcweir         mpJobHeader( NULL ),
206*cdf0e10cSrcweir         mpJobTrailer( NULL ),
207*cdf0e10cSrcweir         m_bQuickJob( false )
208*cdf0e10cSrcweir {
209*cdf0e10cSrcweir }
210*cdf0e10cSrcweir 
211*cdf0e10cSrcweir namespace psp
212*cdf0e10cSrcweir {
213*cdf0e10cSrcweir 
214*cdf0e10cSrcweir /* check whether the given name points to a directory which is
215*cdf0e10cSrcweir    usable for the user */
216*cdf0e10cSrcweir sal_Bool
217*cdf0e10cSrcweir existsTmpDir (const char* pName)
218*cdf0e10cSrcweir {
219*cdf0e10cSrcweir     struct stat aFileStatus;
220*cdf0e10cSrcweir 
221*cdf0e10cSrcweir     if (pName == NULL)
222*cdf0e10cSrcweir         return sal_False;
223*cdf0e10cSrcweir     if (stat(pName, &aFileStatus) != 0)
224*cdf0e10cSrcweir         return sal_False;
225*cdf0e10cSrcweir     if (! S_ISDIR(aFileStatus.st_mode))
226*cdf0e10cSrcweir         return sal_False;
227*cdf0e10cSrcweir 
228*cdf0e10cSrcweir     return access(pName, W_OK | R_OK) == 0 ? sal_True : sal_False;
229*cdf0e10cSrcweir }
230*cdf0e10cSrcweir 
231*cdf0e10cSrcweir /* return the username in the given buffer */
232*cdf0e10cSrcweir sal_Bool
233*cdf0e10cSrcweir getUserName (char* pName, int nSize)
234*cdf0e10cSrcweir {
235*cdf0e10cSrcweir     struct passwd *pPWEntry;
236*cdf0e10cSrcweir     struct passwd  aPWEntry;
237*cdf0e10cSrcweir     sal_Char       pPWBuffer[256];
238*cdf0e10cSrcweir 
239*cdf0e10cSrcweir     sal_Bool bSuccess = sal_False;
240*cdf0e10cSrcweir 
241*cdf0e10cSrcweir #ifdef FREEBSD
242*cdf0e10cSrcweir         pPWEntry = getpwuid( getuid());
243*cdf0e10cSrcweir #else
244*cdf0e10cSrcweir     if (getpwuid_r(getuid(), &aPWEntry, pPWBuffer, sizeof(pPWBuffer), &pPWEntry) != 0)
245*cdf0e10cSrcweir         pPWEntry = NULL;
246*cdf0e10cSrcweir #endif
247*cdf0e10cSrcweir 
248*cdf0e10cSrcweir     if (pPWEntry != NULL && pPWEntry->pw_name != NULL)
249*cdf0e10cSrcweir     {
250*cdf0e10cSrcweir         sal_Int32 nLen = strlen(pPWEntry->pw_name);
251*cdf0e10cSrcweir         if (nLen > 0 && nLen < nSize)
252*cdf0e10cSrcweir         {
253*cdf0e10cSrcweir             memcpy (pName, pPWEntry->pw_name, nLen);
254*cdf0e10cSrcweir             pName[nLen] = '\0';
255*cdf0e10cSrcweir 
256*cdf0e10cSrcweir             bSuccess = sal_True;
257*cdf0e10cSrcweir         }
258*cdf0e10cSrcweir     }
259*cdf0e10cSrcweir 
260*cdf0e10cSrcweir     // wipe the passwd off the stack
261*cdf0e10cSrcweir     memset (pPWBuffer, 0, sizeof(pPWBuffer));
262*cdf0e10cSrcweir 
263*cdf0e10cSrcweir     return bSuccess;
264*cdf0e10cSrcweir }
265*cdf0e10cSrcweir 
266*cdf0e10cSrcweir /* remove all our temporary files, uses external program "rm", since
267*cdf0e10cSrcweir    osl functionality is inadequate */
268*cdf0e10cSrcweir void
269*cdf0e10cSrcweir removeSpoolDir (const rtl::OUString& rSpoolDir)
270*cdf0e10cSrcweir {
271*cdf0e10cSrcweir     rtl::OUString aSysPath;
272*cdf0e10cSrcweir 	if( osl::File::E_None != osl::File::getSystemPathFromFileURL( rSpoolDir, aSysPath ) )
273*cdf0e10cSrcweir 	{
274*cdf0e10cSrcweir 		// Conversion did not work, as this is quite a dangerous action,
275*cdf0e10cSrcweir 		// we should abort here ....
276*cdf0e10cSrcweir 		OSL_ENSURE( 0, "psprint: couldn't remove spool directory" );
277*cdf0e10cSrcweir 		return;
278*cdf0e10cSrcweir 	}
279*cdf0e10cSrcweir     rtl::OString aSysPathByte =
280*cdf0e10cSrcweir         rtl::OUStringToOString (aSysPath, osl_getThreadTextEncoding());
281*cdf0e10cSrcweir     sal_Char  pSystem [128];
282*cdf0e10cSrcweir     sal_Int32 nChar = 0;
283*cdf0e10cSrcweir 
284*cdf0e10cSrcweir     nChar  = psp::appendStr ("rm -rf ",     pSystem);
285*cdf0e10cSrcweir     nChar += psp::appendStr (aSysPathByte.getStr(), pSystem + nChar);
286*cdf0e10cSrcweir 
287*cdf0e10cSrcweir     if (system (pSystem) == -1)
288*cdf0e10cSrcweir         OSL_ENSURE( 0, "psprint: couldn't remove spool directory" );
289*cdf0e10cSrcweir }
290*cdf0e10cSrcweir 
291*cdf0e10cSrcweir /* creates a spool directory with a "pidgin random" value based on
292*cdf0e10cSrcweir    current system time */
293*cdf0e10cSrcweir rtl::OUString
294*cdf0e10cSrcweir createSpoolDir ()
295*cdf0e10cSrcweir {
296*cdf0e10cSrcweir     TimeValue aCur;
297*cdf0e10cSrcweir     osl_getSystemTime( &aCur );
298*cdf0e10cSrcweir     sal_Int32 nRand = aCur.Seconds ^ (aCur.Nanosec/1000);
299*cdf0e10cSrcweir 
300*cdf0e10cSrcweir     rtl::OUString aTmpDir;
301*cdf0e10cSrcweir     osl_getTempDirURL( &aTmpDir.pData );
302*cdf0e10cSrcweir 
303*cdf0e10cSrcweir     do
304*cdf0e10cSrcweir     {
305*cdf0e10cSrcweir         rtl::OUStringBuffer aDir( aTmpDir.getLength() + 16 );
306*cdf0e10cSrcweir         aDir.append( aTmpDir );
307*cdf0e10cSrcweir         aDir.appendAscii( "/psp" );
308*cdf0e10cSrcweir         aDir.append(nRand);
309*cdf0e10cSrcweir         rtl::OUString aResult = aDir.makeStringAndClear();
310*cdf0e10cSrcweir         if( osl::Directory::create( aResult ) == osl::FileBase::E_None )
311*cdf0e10cSrcweir         {
312*cdf0e10cSrcweir             osl::File::setAttributes( aResult,
313*cdf0e10cSrcweir                                         osl_File_Attribute_OwnWrite
314*cdf0e10cSrcweir                                       | osl_File_Attribute_OwnRead
315*cdf0e10cSrcweir                                       | osl_File_Attribute_OwnExe );
316*cdf0e10cSrcweir             return aResult;
317*cdf0e10cSrcweir         }
318*cdf0e10cSrcweir         nRand++;
319*cdf0e10cSrcweir     } while( nRand );
320*cdf0e10cSrcweir     return rtl::OUString();
321*cdf0e10cSrcweir }
322*cdf0e10cSrcweir 
323*cdf0e10cSrcweir } // namespace psp
324*cdf0e10cSrcweir 
325*cdf0e10cSrcweir PrinterJob::~PrinterJob ()
326*cdf0e10cSrcweir {
327*cdf0e10cSrcweir     std::list< osl::File* >::iterator pPage;
328*cdf0e10cSrcweir     for (pPage = maPageList.begin(); pPage != maPageList.end(); pPage++)
329*cdf0e10cSrcweir     {
330*cdf0e10cSrcweir         //(*pPage)->remove();
331*cdf0e10cSrcweir         delete *pPage;
332*cdf0e10cSrcweir     }
333*cdf0e10cSrcweir     for (pPage = maHeaderList.begin(); pPage != maHeaderList.end(); pPage++)
334*cdf0e10cSrcweir     {
335*cdf0e10cSrcweir         //(*pPage)->remove();
336*cdf0e10cSrcweir         delete *pPage;
337*cdf0e10cSrcweir     }
338*cdf0e10cSrcweir     // mpJobHeader->remove();
339*cdf0e10cSrcweir     delete mpJobHeader;
340*cdf0e10cSrcweir     // mpJobTrailer->remove();
341*cdf0e10cSrcweir     delete mpJobTrailer;
342*cdf0e10cSrcweir 
343*cdf0e10cSrcweir     // XXX should really call osl::remove routines
344*cdf0e10cSrcweir     if( maSpoolDirName.getLength() )
345*cdf0e10cSrcweir         removeSpoolDir (maSpoolDirName);
346*cdf0e10cSrcweir 
347*cdf0e10cSrcweir     // osl::Directory::remove (maSpoolDirName);
348*cdf0e10cSrcweir }
349*cdf0e10cSrcweir 
350*cdf0e10cSrcweir namespace psp
351*cdf0e10cSrcweir {
352*cdf0e10cSrcweir 
353*cdf0e10cSrcweir // get locale invariant, 7bit clean current local time string
354*cdf0e10cSrcweir sal_Char*
355*cdf0e10cSrcweir getLocalTime(sal_Char* pBuffer)
356*cdf0e10cSrcweir {
357*cdf0e10cSrcweir     time_t nTime = time (NULL);
358*cdf0e10cSrcweir     struct tm aTime;
359*cdf0e10cSrcweir     struct tm *pLocalTime = localtime_r (&nTime, &aTime);
360*cdf0e10cSrcweir 
361*cdf0e10cSrcweir     return asctime_r(pLocalTime, pBuffer);
362*cdf0e10cSrcweir }
363*cdf0e10cSrcweir 
364*cdf0e10cSrcweir }
365*cdf0e10cSrcweir 
366*cdf0e10cSrcweir static bool isAscii( const rtl::OUString& rStr )
367*cdf0e10cSrcweir {
368*cdf0e10cSrcweir     const sal_Unicode* pStr = rStr;
369*cdf0e10cSrcweir     sal_Int32 nLen = rStr.getLength();
370*cdf0e10cSrcweir     for( sal_Int32 i = 0; i < nLen; i++ )
371*cdf0e10cSrcweir         if( pStr[i] > 127 )
372*cdf0e10cSrcweir             return false;
373*cdf0e10cSrcweir     return true;
374*cdf0e10cSrcweir }
375*cdf0e10cSrcweir 
376*cdf0e10cSrcweir sal_Bool
377*cdf0e10cSrcweir PrinterJob::StartJob (
378*cdf0e10cSrcweir                       const rtl::OUString& rFileName,
379*cdf0e10cSrcweir                       int nMode,
380*cdf0e10cSrcweir                       const rtl::OUString& rJobName,
381*cdf0e10cSrcweir                       const rtl::OUString& rAppName,
382*cdf0e10cSrcweir                       const JobData& rSetupData,
383*cdf0e10cSrcweir                       PrinterGfx* pGraphics,
384*cdf0e10cSrcweir                       bool bIsQuickJob
385*cdf0e10cSrcweir                       )
386*cdf0e10cSrcweir {
387*cdf0e10cSrcweir     m_bQuickJob = bIsQuickJob;
388*cdf0e10cSrcweir     mnMaxWidthPt = mnMaxHeightPt = 0;
389*cdf0e10cSrcweir     mnLandscapes = mnPortraits = 0;
390*cdf0e10cSrcweir     m_pGraphics = pGraphics;
391*cdf0e10cSrcweir     InitPaperSize (rSetupData);
392*cdf0e10cSrcweir 
393*cdf0e10cSrcweir     // create file container for document header and trailer
394*cdf0e10cSrcweir     maFileName = rFileName;
395*cdf0e10cSrcweir     mnFileMode = nMode;
396*cdf0e10cSrcweir     maSpoolDirName = createSpoolDir ();
397*cdf0e10cSrcweir     maJobTitle = rJobName;
398*cdf0e10cSrcweir 
399*cdf0e10cSrcweir     rtl::OUString aExt = rtl::OUString::createFromAscii (".ps");
400*cdf0e10cSrcweir     mpJobHeader  = CreateSpoolFile (rtl::OUString::createFromAscii("psp_head"), aExt);
401*cdf0e10cSrcweir     mpJobTrailer = CreateSpoolFile (rtl::OUString::createFromAscii("psp_tail"), aExt);
402*cdf0e10cSrcweir     if( ! (mpJobHeader && mpJobTrailer) ) // existing files are removed in destructor
403*cdf0e10cSrcweir         return sal_False;
404*cdf0e10cSrcweir 
405*cdf0e10cSrcweir     // write document header according to Document Structuring Conventions (DSC)
406*cdf0e10cSrcweir     WritePS (mpJobHeader,
407*cdf0e10cSrcweir              "%!PS-Adobe-3.0\n"
408*cdf0e10cSrcweir              "%%BoundingBox: (atend)\n" );
409*cdf0e10cSrcweir 
410*cdf0e10cSrcweir     rtl::OUString aFilterWS;
411*cdf0e10cSrcweir 
412*cdf0e10cSrcweir     // Creator (this application)
413*cdf0e10cSrcweir     aFilterWS = WhitespaceToSpace( rAppName, sal_False );
414*cdf0e10cSrcweir     WritePS (mpJobHeader, "%%Creator: (");
415*cdf0e10cSrcweir     WritePS (mpJobHeader, aFilterWS);
416*cdf0e10cSrcweir     WritePS (mpJobHeader, ")\n");
417*cdf0e10cSrcweir 
418*cdf0e10cSrcweir     // For (user name)
419*cdf0e10cSrcweir     sal_Char pUserName[64];
420*cdf0e10cSrcweir     if (getUserName(pUserName, sizeof(pUserName)))
421*cdf0e10cSrcweir     {
422*cdf0e10cSrcweir         WritePS (mpJobHeader, "%%For: (");
423*cdf0e10cSrcweir         WritePS (mpJobHeader, pUserName);
424*cdf0e10cSrcweir         WritePS (mpJobHeader, ")\n");
425*cdf0e10cSrcweir     }
426*cdf0e10cSrcweir 
427*cdf0e10cSrcweir     // Creation Date (locale independent local time)
428*cdf0e10cSrcweir     sal_Char pCreationDate [256];
429*cdf0e10cSrcweir     WritePS (mpJobHeader, "%%CreationDate: (");
430*cdf0e10cSrcweir     getLocalTime(pCreationDate);
431*cdf0e10cSrcweir     for( unsigned int i = 0; i < sizeof(pCreationDate)/sizeof(pCreationDate[0]); i++ )
432*cdf0e10cSrcweir     {
433*cdf0e10cSrcweir         if( pCreationDate[i] == '\n' )
434*cdf0e10cSrcweir         {
435*cdf0e10cSrcweir             pCreationDate[i] = 0;
436*cdf0e10cSrcweir             break;
437*cdf0e10cSrcweir         }
438*cdf0e10cSrcweir     }
439*cdf0e10cSrcweir     WritePS (mpJobHeader, pCreationDate );
440*cdf0e10cSrcweir     WritePS (mpJobHeader, ")\n");
441*cdf0e10cSrcweir 
442*cdf0e10cSrcweir     // Document Title
443*cdf0e10cSrcweir     /* #i74335#
444*cdf0e10cSrcweir     * The title should be clean ascii; rJobName however may
445*cdf0e10cSrcweir     * contain any Unicode character. So implement the following
446*cdf0e10cSrcweir     * algorithm:
447*cdf0e10cSrcweir     * use rJobName, if it contains only ascii
448*cdf0e10cSrcweir     * use the filename, if it contains only ascii
449*cdf0e10cSrcweir     * else omit %%Title
450*cdf0e10cSrcweir     */
451*cdf0e10cSrcweir     aFilterWS = WhitespaceToSpace( rJobName, sal_False );
452*cdf0e10cSrcweir     rtl::OUString aTitle( aFilterWS );
453*cdf0e10cSrcweir     if( ! isAscii( aTitle ) )
454*cdf0e10cSrcweir     {
455*cdf0e10cSrcweir         sal_Int32 nIndex = 0;
456*cdf0e10cSrcweir         while( nIndex != -1 )
457*cdf0e10cSrcweir             aTitle = rFileName.getToken( 0, '/', nIndex );
458*cdf0e10cSrcweir         aTitle = WhitespaceToSpace( aTitle, sal_False );
459*cdf0e10cSrcweir         if( ! isAscii( aTitle ) )
460*cdf0e10cSrcweir             aTitle = rtl::OUString();
461*cdf0e10cSrcweir     }
462*cdf0e10cSrcweir 
463*cdf0e10cSrcweir     maJobTitle = aFilterWS;
464*cdf0e10cSrcweir     if( aTitle.getLength() )
465*cdf0e10cSrcweir     {
466*cdf0e10cSrcweir         WritePS (mpJobHeader, "%%Title: (");
467*cdf0e10cSrcweir         WritePS (mpJobHeader, aTitle);
468*cdf0e10cSrcweir         WritePS (mpJobHeader, ")\n");
469*cdf0e10cSrcweir     }
470*cdf0e10cSrcweir 
471*cdf0e10cSrcweir     // Language Level
472*cdf0e10cSrcweir     sal_Char pLevel[16];
473*cdf0e10cSrcweir     sal_Int32 nSz = getValueOf(GetPostscriptLevel(&rSetupData), pLevel);
474*cdf0e10cSrcweir     pLevel[nSz++] = '\n';
475*cdf0e10cSrcweir     pLevel[nSz  ] = '\0';
476*cdf0e10cSrcweir     WritePS (mpJobHeader, "%%LanguageLevel: ");
477*cdf0e10cSrcweir     WritePS (mpJobHeader, pLevel);
478*cdf0e10cSrcweir 
479*cdf0e10cSrcweir     // Other
480*cdf0e10cSrcweir     WritePS (mpJobHeader, "%%DocumentData: Clean7Bit\n");
481*cdf0e10cSrcweir     WritePS (mpJobHeader, "%%Pages: (atend)\n");
482*cdf0e10cSrcweir     WritePS (mpJobHeader, "%%Orientation: (atend)\n");
483*cdf0e10cSrcweir     WritePS (mpJobHeader, "%%PageOrder: Ascend\n");
484*cdf0e10cSrcweir     WritePS (mpJobHeader, "%%EndComments\n");
485*cdf0e10cSrcweir 
486*cdf0e10cSrcweir     // write Prolog
487*cdf0e10cSrcweir     writeProlog (mpJobHeader, rSetupData);
488*cdf0e10cSrcweir 
489*cdf0e10cSrcweir     // mark last job setup as not set
490*cdf0e10cSrcweir     m_aLastJobData.m_pParser = NULL;
491*cdf0e10cSrcweir     m_aLastJobData.m_aContext.setParser( NULL );
492*cdf0e10cSrcweir 
493*cdf0e10cSrcweir     return sal_True;
494*cdf0e10cSrcweir }
495*cdf0e10cSrcweir 
496*cdf0e10cSrcweir sal_Bool
497*cdf0e10cSrcweir PrinterJob::EndJob ()
498*cdf0e10cSrcweir {
499*cdf0e10cSrcweir     // no pages ? that really means no print job
500*cdf0e10cSrcweir     if( maPageList.empty() )
501*cdf0e10cSrcweir         return sal_False;
502*cdf0e10cSrcweir 
503*cdf0e10cSrcweir     // write document setup (done here because it
504*cdf0e10cSrcweir     // includes the accumulated fonts
505*cdf0e10cSrcweir     if( mpJobHeader )
506*cdf0e10cSrcweir         writeSetup( mpJobHeader, m_aDocumentJobData );
507*cdf0e10cSrcweir     m_pGraphics->OnEndJob();
508*cdf0e10cSrcweir     if( ! (mpJobHeader && mpJobTrailer) )
509*cdf0e10cSrcweir         return sal_False;
510*cdf0e10cSrcweir 
511*cdf0e10cSrcweir     // write document trailer according to Document Structuring Conventions (DSC)
512*cdf0e10cSrcweir     rtl::OStringBuffer aTrailer(512);
513*cdf0e10cSrcweir     aTrailer.append( "%%Trailer\n" );
514*cdf0e10cSrcweir     aTrailer.append( "%%BoundingBox: 0 0 " );
515*cdf0e10cSrcweir     aTrailer.append( (sal_Int32)mnMaxWidthPt );
516*cdf0e10cSrcweir     aTrailer.append( " " );
517*cdf0e10cSrcweir     aTrailer.append( (sal_Int32)mnMaxHeightPt );
518*cdf0e10cSrcweir     if( mnLandscapes > mnPortraits )
519*cdf0e10cSrcweir         aTrailer.append("\n%%Orientation: Landscape");
520*cdf0e10cSrcweir     else
521*cdf0e10cSrcweir         aTrailer.append("\n%%Orientation: Portrait");
522*cdf0e10cSrcweir     aTrailer.append( "\n%%Pages: " );
523*cdf0e10cSrcweir     aTrailer.append( (sal_Int32)maPageList.size() );
524*cdf0e10cSrcweir     aTrailer.append( "\n%%EOF\n" );
525*cdf0e10cSrcweir     WritePS (mpJobTrailer, aTrailer.getStr());
526*cdf0e10cSrcweir 
527*cdf0e10cSrcweir     /*
528*cdf0e10cSrcweir      * spool the set of files to their final destination, this is U**X dependent
529*cdf0e10cSrcweir      */
530*cdf0e10cSrcweir 
531*cdf0e10cSrcweir     FILE* pDestFILE = NULL;
532*cdf0e10cSrcweir 
533*cdf0e10cSrcweir     /* create a destination either as file or as a pipe */
534*cdf0e10cSrcweir     sal_Bool bSpoolToFile = maFileName.getLength() > 0 ? sal_True : sal_False;
535*cdf0e10cSrcweir     if (bSpoolToFile)
536*cdf0e10cSrcweir     {
537*cdf0e10cSrcweir         const rtl::OString aFileName = rtl::OUStringToOString (maFileName,
538*cdf0e10cSrcweir                                                                osl_getThreadTextEncoding());
539*cdf0e10cSrcweir         if( mnFileMode )
540*cdf0e10cSrcweir         {
541*cdf0e10cSrcweir             int nFile = open( aFileName.getStr(), O_CREAT | O_EXCL | O_RDWR, mnFileMode );
542*cdf0e10cSrcweir             if( nFile != -1 )
543*cdf0e10cSrcweir             {
544*cdf0e10cSrcweir                 pDestFILE = fdopen( nFile, "w" );
545*cdf0e10cSrcweir                 if( pDestFILE == NULL )
546*cdf0e10cSrcweir                 {
547*cdf0e10cSrcweir                     close( nFile );
548*cdf0e10cSrcweir                     unlink( aFileName.getStr() );
549*cdf0e10cSrcweir                     return sal_False;
550*cdf0e10cSrcweir                 }
551*cdf0e10cSrcweir             }
552*cdf0e10cSrcweir             else
553*cdf0e10cSrcweir                 chmod( aFileName.getStr(), mnFileMode );
554*cdf0e10cSrcweir         }
555*cdf0e10cSrcweir         if (pDestFILE == NULL)
556*cdf0e10cSrcweir             pDestFILE = fopen (aFileName.getStr(), "w");
557*cdf0e10cSrcweir 
558*cdf0e10cSrcweir         if (pDestFILE == NULL)
559*cdf0e10cSrcweir             return sal_False;
560*cdf0e10cSrcweir     }
561*cdf0e10cSrcweir     else
562*cdf0e10cSrcweir     {
563*cdf0e10cSrcweir         PrinterInfoManager& rPrinterInfoManager = PrinterInfoManager::get ();
564*cdf0e10cSrcweir         pDestFILE = rPrinterInfoManager.startSpool( m_aLastJobData.m_aPrinterName, m_bQuickJob );
565*cdf0e10cSrcweir         if (pDestFILE == NULL)
566*cdf0e10cSrcweir             return sal_False;
567*cdf0e10cSrcweir     }
568*cdf0e10cSrcweir 
569*cdf0e10cSrcweir     /* spool the document parts to the destination */
570*cdf0e10cSrcweir 
571*cdf0e10cSrcweir     sal_uChar pBuffer[ nBLOCKSIZE ];
572*cdf0e10cSrcweir 
573*cdf0e10cSrcweir     AppendPS (pDestFILE, mpJobHeader, pBuffer);
574*cdf0e10cSrcweir     mpJobHeader->close();
575*cdf0e10cSrcweir 
576*cdf0e10cSrcweir     sal_Bool bSuccess = sal_True;
577*cdf0e10cSrcweir     std::list< osl::File* >::iterator pPageBody;
578*cdf0e10cSrcweir     std::list< osl::File* >::iterator pPageHead;
579*cdf0e10cSrcweir     for (pPageBody  = maPageList.begin(), pPageHead  = maHeaderList.begin();
580*cdf0e10cSrcweir          pPageBody != maPageList.end() && pPageHead != maHeaderList.end();
581*cdf0e10cSrcweir          pPageBody++, pPageHead++)
582*cdf0e10cSrcweir     {
583*cdf0e10cSrcweir         if( *pPageHead )
584*cdf0e10cSrcweir         {
585*cdf0e10cSrcweir             osl::File::RC nError = (*pPageHead)->open(OpenFlag_Read);
586*cdf0e10cSrcweir             if (nError == osl::File::E_None)
587*cdf0e10cSrcweir             {
588*cdf0e10cSrcweir                 AppendPS (pDestFILE, *pPageHead, pBuffer);
589*cdf0e10cSrcweir                 (*pPageHead)->close();
590*cdf0e10cSrcweir             }
591*cdf0e10cSrcweir         }
592*cdf0e10cSrcweir         else
593*cdf0e10cSrcweir             bSuccess = sal_False;
594*cdf0e10cSrcweir         if( *pPageBody )
595*cdf0e10cSrcweir         {
596*cdf0e10cSrcweir             osl::File::RC nError = (*pPageBody)->open(OpenFlag_Read);
597*cdf0e10cSrcweir             if (nError == osl::File::E_None)
598*cdf0e10cSrcweir             {
599*cdf0e10cSrcweir                 AppendPS (pDestFILE, *pPageBody, pBuffer);
600*cdf0e10cSrcweir                 (*pPageBody)->close();
601*cdf0e10cSrcweir             }
602*cdf0e10cSrcweir         }
603*cdf0e10cSrcweir         else
604*cdf0e10cSrcweir             bSuccess = sal_False;
605*cdf0e10cSrcweir     }
606*cdf0e10cSrcweir 
607*cdf0e10cSrcweir     AppendPS (pDestFILE, mpJobTrailer, pBuffer);
608*cdf0e10cSrcweir     mpJobTrailer->close();
609*cdf0e10cSrcweir 
610*cdf0e10cSrcweir     /* well done */
611*cdf0e10cSrcweir 
612*cdf0e10cSrcweir     if (bSpoolToFile)
613*cdf0e10cSrcweir         fclose (pDestFILE);
614*cdf0e10cSrcweir     else
615*cdf0e10cSrcweir     {
616*cdf0e10cSrcweir         PrinterInfoManager& rPrinterInfoManager = PrinterInfoManager::get();
617*cdf0e10cSrcweir         if (0 == rPrinterInfoManager.endSpool( m_aLastJobData.m_aPrinterName,
618*cdf0e10cSrcweir 			maJobTitle, pDestFILE, m_aDocumentJobData, true ))
619*cdf0e10cSrcweir 		{
620*cdf0e10cSrcweir 			bSuccess = sal_False;
621*cdf0e10cSrcweir 		}
622*cdf0e10cSrcweir     }
623*cdf0e10cSrcweir 
624*cdf0e10cSrcweir     return bSuccess;
625*cdf0e10cSrcweir }
626*cdf0e10cSrcweir 
627*cdf0e10cSrcweir sal_Bool
628*cdf0e10cSrcweir PrinterJob::AbortJob ()
629*cdf0e10cSrcweir {
630*cdf0e10cSrcweir     m_pGraphics->OnEndJob();
631*cdf0e10cSrcweir     return sal_False;
632*cdf0e10cSrcweir }
633*cdf0e10cSrcweir 
634*cdf0e10cSrcweir void
635*cdf0e10cSrcweir PrinterJob::InitPaperSize (const JobData& rJobSetup)
636*cdf0e10cSrcweir {
637*cdf0e10cSrcweir     int nRes = rJobSetup.m_aContext.getRenderResolution ();
638*cdf0e10cSrcweir 
639*cdf0e10cSrcweir     String aPaper;
640*cdf0e10cSrcweir     int nWidth, nHeight;
641*cdf0e10cSrcweir     rJobSetup.m_aContext.getPageSize (aPaper, nWidth, nHeight);
642*cdf0e10cSrcweir 
643*cdf0e10cSrcweir     int nLeft = 0, nRight = 0, nUpper = 0, nLower = 0;
644*cdf0e10cSrcweir     const PPDParser* pParser = rJobSetup.m_aContext.getParser();
645*cdf0e10cSrcweir     if (pParser != NULL)
646*cdf0e10cSrcweir         pParser->getMargins (aPaper, nLeft, nRight, nUpper, nLower);
647*cdf0e10cSrcweir 
648*cdf0e10cSrcweir     mnResolution	= nRes;
649*cdf0e10cSrcweir 
650*cdf0e10cSrcweir     mnWidthPt       = nWidth;
651*cdf0e10cSrcweir     mnHeightPt      = nHeight;
652*cdf0e10cSrcweir 
653*cdf0e10cSrcweir     if( mnWidthPt > mnMaxWidthPt )
654*cdf0e10cSrcweir         mnMaxWidthPt = mnWidthPt;
655*cdf0e10cSrcweir     if( mnHeightPt > mnMaxHeightPt )
656*cdf0e10cSrcweir         mnMaxHeightPt = mnHeightPt;
657*cdf0e10cSrcweir 
658*cdf0e10cSrcweir     mnLMarginPt     = nLeft;
659*cdf0e10cSrcweir     mnRMarginPt     = nRight;
660*cdf0e10cSrcweir     mnTMarginPt     = nUpper;
661*cdf0e10cSrcweir     mnBMarginPt     = nLower;
662*cdf0e10cSrcweir 
663*cdf0e10cSrcweir     mfXScale        = (double)72.0 / (double)mnResolution;
664*cdf0e10cSrcweir     mfYScale        = -1.0 * (double)72.0 / (double)mnResolution;
665*cdf0e10cSrcweir }
666*cdf0e10cSrcweir 
667*cdf0e10cSrcweir 
668*cdf0e10cSrcweir sal_Bool
669*cdf0e10cSrcweir PrinterJob::StartPage (const JobData& rJobSetup)
670*cdf0e10cSrcweir {
671*cdf0e10cSrcweir     InitPaperSize (rJobSetup);
672*cdf0e10cSrcweir 
673*cdf0e10cSrcweir     rtl::OUString aPageNo = rtl::OUString::valueOf ((sal_Int32)maPageList.size()+1); // sequential page number must start with 1
674*cdf0e10cSrcweir     rtl::OUString aExt    = aPageNo + rtl::OUString::createFromAscii (".ps");
675*cdf0e10cSrcweir 
676*cdf0e10cSrcweir     osl::File* pPageHeader = CreateSpoolFile (
677*cdf0e10cSrcweir                                               rtl::OUString::createFromAscii("psp_pghead"), aExt);
678*cdf0e10cSrcweir     osl::File* pPageBody   = CreateSpoolFile (
679*cdf0e10cSrcweir                                               rtl::OUString::createFromAscii("psp_pgbody"), aExt);
680*cdf0e10cSrcweir 
681*cdf0e10cSrcweir     maHeaderList.push_back (pPageHeader);
682*cdf0e10cSrcweir     maPageList.push_back (pPageBody);
683*cdf0e10cSrcweir 
684*cdf0e10cSrcweir     if( ! (pPageHeader && pPageBody) )
685*cdf0e10cSrcweir         return sal_False;
686*cdf0e10cSrcweir 
687*cdf0e10cSrcweir     // write page header according to Document Structuring Conventions (DSC)
688*cdf0e10cSrcweir     WritePS (pPageHeader, "%%Page: ");
689*cdf0e10cSrcweir     WritePS (pPageHeader, aPageNo);
690*cdf0e10cSrcweir     WritePS (pPageHeader, " ");
691*cdf0e10cSrcweir     WritePS (pPageHeader, aPageNo);
692*cdf0e10cSrcweir     WritePS (pPageHeader, "\n");
693*cdf0e10cSrcweir 
694*cdf0e10cSrcweir     if( rJobSetup.m_eOrientation == orientation::Landscape )
695*cdf0e10cSrcweir     {
696*cdf0e10cSrcweir         WritePS (pPageHeader, "%%PageOrientation: Landscape\n");
697*cdf0e10cSrcweir         mnLandscapes++;
698*cdf0e10cSrcweir     }
699*cdf0e10cSrcweir     else
700*cdf0e10cSrcweir     {
701*cdf0e10cSrcweir         WritePS (pPageHeader, "%%PageOrientation: Portrait\n");
702*cdf0e10cSrcweir         mnPortraits++;
703*cdf0e10cSrcweir     }
704*cdf0e10cSrcweir 
705*cdf0e10cSrcweir     sal_Char  pBBox [256];
706*cdf0e10cSrcweir     sal_Int32 nChar = 0;
707*cdf0e10cSrcweir 
708*cdf0e10cSrcweir     nChar  = psp::appendStr  ("%%PageBoundingBox: ",    pBBox);
709*cdf0e10cSrcweir     nChar += psp::getValueOf (mnLMarginPt,              pBBox + nChar);
710*cdf0e10cSrcweir     nChar += psp::appendStr  (" ",                      pBBox + nChar);
711*cdf0e10cSrcweir     nChar += psp::getValueOf (mnBMarginPt,              pBBox + nChar);
712*cdf0e10cSrcweir     nChar += psp::appendStr  (" ",                      pBBox + nChar);
713*cdf0e10cSrcweir     nChar += psp::getValueOf (mnWidthPt  - mnRMarginPt, pBBox + nChar);
714*cdf0e10cSrcweir     nChar += psp::appendStr  (" ",                      pBBox + nChar);
715*cdf0e10cSrcweir     nChar += psp::getValueOf (mnHeightPt - mnTMarginPt, pBBox + nChar);
716*cdf0e10cSrcweir     nChar += psp::appendStr  ("\n",                     pBBox + nChar);
717*cdf0e10cSrcweir 
718*cdf0e10cSrcweir     WritePS (pPageHeader, pBBox);
719*cdf0e10cSrcweir 
720*cdf0e10cSrcweir     /* #i7262# #i65491# write setup only before first page
721*cdf0e10cSrcweir      *  (to %%Begin(End)Setup, instead of %%Begin(End)PageSetup)
722*cdf0e10cSrcweir      *  don't do this in StartJob since the jobsetup there may be
723*cdf0e10cSrcweir      *  different.
724*cdf0e10cSrcweir      */
725*cdf0e10cSrcweir     bool bWriteFeatures = true;
726*cdf0e10cSrcweir     if( 1 == maPageList.size() )
727*cdf0e10cSrcweir     {
728*cdf0e10cSrcweir         m_aDocumentJobData = rJobSetup;
729*cdf0e10cSrcweir         bWriteFeatures = false;
730*cdf0e10cSrcweir     }
731*cdf0e10cSrcweir 
732*cdf0e10cSrcweir     if ( writePageSetup( pPageHeader, rJobSetup, bWriteFeatures ) )
733*cdf0e10cSrcweir     {
734*cdf0e10cSrcweir         m_aLastJobData = rJobSetup;
735*cdf0e10cSrcweir         return true;
736*cdf0e10cSrcweir     }
737*cdf0e10cSrcweir 
738*cdf0e10cSrcweir     return false;
739*cdf0e10cSrcweir }
740*cdf0e10cSrcweir 
741*cdf0e10cSrcweir sal_Bool
742*cdf0e10cSrcweir PrinterJob::EndPage ()
743*cdf0e10cSrcweir {
744*cdf0e10cSrcweir     m_pGraphics->OnEndPage();
745*cdf0e10cSrcweir 
746*cdf0e10cSrcweir     osl::File* pPageHeader = maHeaderList.back();
747*cdf0e10cSrcweir     osl::File* pPageBody   = maPageList.back();
748*cdf0e10cSrcweir 
749*cdf0e10cSrcweir     if( ! (pPageBody && pPageHeader) )
750*cdf0e10cSrcweir         return sal_False;
751*cdf0e10cSrcweir 
752*cdf0e10cSrcweir     // copy page to paper and write page trailer according to DSC
753*cdf0e10cSrcweir 
754*cdf0e10cSrcweir     sal_Char pTrailer[256];
755*cdf0e10cSrcweir     sal_Int32 nChar = 0;
756*cdf0e10cSrcweir     nChar  = psp::appendStr ("grestore grestore\n", pTrailer);
757*cdf0e10cSrcweir     nChar += psp::appendStr ("showpage\n",          pTrailer + nChar);
758*cdf0e10cSrcweir     nChar += psp::appendStr ("%%PageTrailer\n\n",   pTrailer + nChar);
759*cdf0e10cSrcweir     WritePS (pPageBody, pTrailer);
760*cdf0e10cSrcweir 
761*cdf0e10cSrcweir     // this page is done for now, close it to avoid having too many open fd's
762*cdf0e10cSrcweir 
763*cdf0e10cSrcweir     pPageHeader->close();
764*cdf0e10cSrcweir     pPageBody->close();
765*cdf0e10cSrcweir 
766*cdf0e10cSrcweir     return sal_True;
767*cdf0e10cSrcweir }
768*cdf0e10cSrcweir 
769*cdf0e10cSrcweir sal_uInt32
770*cdf0e10cSrcweir PrinterJob::GetErrorCode ()
771*cdf0e10cSrcweir {
772*cdf0e10cSrcweir     /* TODO */
773*cdf0e10cSrcweir     return 0;
774*cdf0e10cSrcweir }
775*cdf0e10cSrcweir 
776*cdf0e10cSrcweir struct less_ppd_key : public ::std::binary_function<double, double, bool>
777*cdf0e10cSrcweir {
778*cdf0e10cSrcweir     bool operator()(const PPDKey* left, const PPDKey* right)
779*cdf0e10cSrcweir     { return left->getOrderDependency() < right->getOrderDependency(); }
780*cdf0e10cSrcweir };
781*cdf0e10cSrcweir 
782*cdf0e10cSrcweir static bool writeFeature( osl::File* pFile, const PPDKey* pKey, const PPDValue* pValue, bool bUseIncluseFeature )
783*cdf0e10cSrcweir {
784*cdf0e10cSrcweir     if( ! pKey || ! pValue )
785*cdf0e10cSrcweir         return true;
786*cdf0e10cSrcweir 
787*cdf0e10cSrcweir     OStringBuffer aFeature(256);
788*cdf0e10cSrcweir     aFeature.append( "[{\n" );
789*cdf0e10cSrcweir     if( bUseIncluseFeature )
790*cdf0e10cSrcweir         aFeature.append( "%%IncludeFeature:" );
791*cdf0e10cSrcweir     else
792*cdf0e10cSrcweir         aFeature.append( "%%BeginFeature:" );
793*cdf0e10cSrcweir     aFeature.append( " *" );
794*cdf0e10cSrcweir     aFeature.append( OUStringToOString( pKey->getKey(), RTL_TEXTENCODING_ASCII_US ) );
795*cdf0e10cSrcweir     aFeature.append( ' ' );
796*cdf0e10cSrcweir     aFeature.append( OUStringToOString( pValue->m_aOption, RTL_TEXTENCODING_ASCII_US ) );
797*cdf0e10cSrcweir     if( !bUseIncluseFeature )
798*cdf0e10cSrcweir     {
799*cdf0e10cSrcweir         aFeature.append( '\n' );
800*cdf0e10cSrcweir         aFeature.append( OUStringToOString( pValue->m_aValue, RTL_TEXTENCODING_ASCII_US ) );
801*cdf0e10cSrcweir         aFeature.append( "\n%%EndFeature" );
802*cdf0e10cSrcweir     }
803*cdf0e10cSrcweir     aFeature.append( "\n} stopped cleartomark\n" );
804*cdf0e10cSrcweir     sal_uInt64 nWritten = 0;
805*cdf0e10cSrcweir     return pFile->write( aFeature.getStr(), aFeature.getLength(), nWritten )
806*cdf0e10cSrcweir         || nWritten != (sal_uInt64)aFeature.getLength() ? false : true;
807*cdf0e10cSrcweir }
808*cdf0e10cSrcweir 
809*cdf0e10cSrcweir bool PrinterJob::writeFeatureList( osl::File* pFile, const JobData& rJob, bool bDocumentSetup )
810*cdf0e10cSrcweir {
811*cdf0e10cSrcweir     bool bSuccess = true;
812*cdf0e10cSrcweir     int i;
813*cdf0e10cSrcweir 
814*cdf0e10cSrcweir     // emit features ordered to OrderDependency
815*cdf0e10cSrcweir     // ignore features that are set to default
816*cdf0e10cSrcweir 
817*cdf0e10cSrcweir     // sanity check
818*cdf0e10cSrcweir     if( rJob.m_pParser == rJob.m_aContext.getParser() &&
819*cdf0e10cSrcweir         rJob.m_pParser &&
820*cdf0e10cSrcweir         ( m_aLastJobData.m_pParser == rJob.m_pParser || m_aLastJobData.m_pParser == NULL )
821*cdf0e10cSrcweir         )
822*cdf0e10cSrcweir     {
823*cdf0e10cSrcweir         int nKeys = rJob.m_aContext.countValuesModified();
824*cdf0e10cSrcweir         ::std::vector< const PPDKey* > aKeys( nKeys );
825*cdf0e10cSrcweir         for(  i = 0; i < nKeys; i++ )
826*cdf0e10cSrcweir             aKeys[i] = rJob.m_aContext.getModifiedKey( i );
827*cdf0e10cSrcweir         ::std::sort( aKeys.begin(), aKeys.end(), less_ppd_key() );
828*cdf0e10cSrcweir 
829*cdf0e10cSrcweir         for( i = 0; i < nKeys && bSuccess; i++ )
830*cdf0e10cSrcweir         {
831*cdf0e10cSrcweir             const PPDKey* pKey = aKeys[i];
832*cdf0e10cSrcweir             bool bEmit = false;
833*cdf0e10cSrcweir             if( bDocumentSetup )
834*cdf0e10cSrcweir             {
835*cdf0e10cSrcweir                 if( pKey->getSetupType()    == PPDKey::DocumentSetup )
836*cdf0e10cSrcweir                     bEmit = true;
837*cdf0e10cSrcweir             }
838*cdf0e10cSrcweir             if( pKey->getSetupType()    == PPDKey::PageSetup        ||
839*cdf0e10cSrcweir                 pKey->getSetupType()    == PPDKey::AnySetup )
840*cdf0e10cSrcweir                 bEmit = true;
841*cdf0e10cSrcweir             if( bEmit )
842*cdf0e10cSrcweir             {
843*cdf0e10cSrcweir                 const PPDValue* pValue = rJob.m_aContext.getValue( pKey );
844*cdf0e10cSrcweir                 if( pValue
845*cdf0e10cSrcweir                     && pValue->m_eType == eInvocation
846*cdf0e10cSrcweir                     && ( m_aLastJobData.m_pParser == NULL
847*cdf0e10cSrcweir                          || m_aLastJobData.m_aContext.getValue( pKey ) != pValue
848*cdf0e10cSrcweir                          || bDocumentSetup
849*cdf0e10cSrcweir                          )
850*cdf0e10cSrcweir                    )
851*cdf0e10cSrcweir                 {
852*cdf0e10cSrcweir                     // try to avoid PS level 2 feature commands if level is set to 1
853*cdf0e10cSrcweir                     if( GetPostscriptLevel( &rJob ) == 1 )
854*cdf0e10cSrcweir                     {
855*cdf0e10cSrcweir                         bool bHavePS2 =
856*cdf0e10cSrcweir                             ( pValue->m_aValue.SearchAscii( "<<" ) != STRING_NOTFOUND )
857*cdf0e10cSrcweir                             ||
858*cdf0e10cSrcweir                             ( pValue->m_aValue.SearchAscii( ">>" ) != STRING_NOTFOUND );
859*cdf0e10cSrcweir                         if( bHavePS2 )
860*cdf0e10cSrcweir                             continue;
861*cdf0e10cSrcweir                     }
862*cdf0e10cSrcweir                     bSuccess = writeFeature( pFile, pKey, pValue, PrinterInfoManager::get().getUseIncludeFeature() );
863*cdf0e10cSrcweir                 }
864*cdf0e10cSrcweir             }
865*cdf0e10cSrcweir         }
866*cdf0e10cSrcweir     }
867*cdf0e10cSrcweir     else
868*cdf0e10cSrcweir         bSuccess = false;
869*cdf0e10cSrcweir 
870*cdf0e10cSrcweir     return bSuccess;
871*cdf0e10cSrcweir }
872*cdf0e10cSrcweir 
873*cdf0e10cSrcweir bool PrinterJob::writePageSetup( osl::File* pFile, const JobData& rJob, bool bWriteFeatures )
874*cdf0e10cSrcweir {
875*cdf0e10cSrcweir     bool bSuccess = true;
876*cdf0e10cSrcweir 
877*cdf0e10cSrcweir     WritePS (pFile, "%%BeginPageSetup\n%\n");
878*cdf0e10cSrcweir     if ( bWriteFeatures )
879*cdf0e10cSrcweir         bSuccess = writeFeatureList( pFile, rJob, false );
880*cdf0e10cSrcweir     WritePS (pFile, "%%EndPageSetup\n");
881*cdf0e10cSrcweir 
882*cdf0e10cSrcweir     sal_Char  pTranslate [128];
883*cdf0e10cSrcweir     sal_Int32 nChar = 0;
884*cdf0e10cSrcweir 
885*cdf0e10cSrcweir     if( rJob.m_eOrientation == orientation::Portrait )
886*cdf0e10cSrcweir     {
887*cdf0e10cSrcweir         nChar  = psp::appendStr  ("gsave\n[",   pTranslate);
888*cdf0e10cSrcweir         nChar += psp::getValueOfDouble (        pTranslate + nChar, mfXScale, 5);
889*cdf0e10cSrcweir         nChar += psp::appendStr  (" 0 0 ",      pTranslate + nChar);
890*cdf0e10cSrcweir         nChar += psp::getValueOfDouble (        pTranslate + nChar, mfYScale, 5);
891*cdf0e10cSrcweir         nChar += psp::appendStr  (" ",          pTranslate + nChar);
892*cdf0e10cSrcweir         nChar += psp::getValueOf (mnRMarginPt,  pTranslate + nChar);
893*cdf0e10cSrcweir         nChar += psp::appendStr  (" ",          pTranslate + nChar);
894*cdf0e10cSrcweir         nChar += psp::getValueOf (mnHeightPt-mnTMarginPt,
895*cdf0e10cSrcweir                                   pTranslate + nChar);
896*cdf0e10cSrcweir         nChar += psp::appendStr  ("] concat\ngsave\n",
897*cdf0e10cSrcweir                                   pTranslate + nChar);
898*cdf0e10cSrcweir     }
899*cdf0e10cSrcweir     else
900*cdf0e10cSrcweir     {
901*cdf0e10cSrcweir         nChar  = psp::appendStr  ("gsave\n",    pTranslate);
902*cdf0e10cSrcweir         nChar += psp::appendStr  ("[ 0 ",       pTranslate + nChar);
903*cdf0e10cSrcweir         nChar += psp::getValueOfDouble (        pTranslate + nChar, -mfYScale, 5);
904*cdf0e10cSrcweir         nChar += psp::appendStr  (" ",          pTranslate + nChar);
905*cdf0e10cSrcweir         nChar += psp::getValueOfDouble (        pTranslate + nChar, mfXScale, 5);
906*cdf0e10cSrcweir         nChar += psp::appendStr  (" 0 ",        pTranslate + nChar );
907*cdf0e10cSrcweir         nChar += psp::getValueOfDouble (        pTranslate + nChar, mnLMarginPt, 5 );
908*cdf0e10cSrcweir         nChar += psp::appendStr  (" ",          pTranslate + nChar);
909*cdf0e10cSrcweir         nChar += psp::getValueOf (mnBMarginPt,  pTranslate + nChar );
910*cdf0e10cSrcweir         nChar += psp::appendStr ("] concat\ngsave\n",
911*cdf0e10cSrcweir                                  pTranslate + nChar);
912*cdf0e10cSrcweir     }
913*cdf0e10cSrcweir 
914*cdf0e10cSrcweir     WritePS (pFile, pTranslate);
915*cdf0e10cSrcweir 
916*cdf0e10cSrcweir     return bSuccess;
917*cdf0e10cSrcweir }
918*cdf0e10cSrcweir 
919*cdf0e10cSrcweir void PrinterJob::writeJobPatch( osl::File* pFile, const JobData& rJobData )
920*cdf0e10cSrcweir {
921*cdf0e10cSrcweir     if( ! PrinterInfoManager::get().getUseJobPatch() )
922*cdf0e10cSrcweir         return;
923*cdf0e10cSrcweir 
924*cdf0e10cSrcweir     const PPDKey* pKey = NULL;
925*cdf0e10cSrcweir 
926*cdf0e10cSrcweir     if( rJobData.m_pParser )
927*cdf0e10cSrcweir         pKey = rJobData.m_pParser->getKey( OUString( RTL_CONSTASCII_USTRINGPARAM( "JobPatchFile" ) ) );
928*cdf0e10cSrcweir     if( ! pKey )
929*cdf0e10cSrcweir         return;
930*cdf0e10cSrcweir 
931*cdf0e10cSrcweir     // order the patch files
932*cdf0e10cSrcweir     // according to PPD spec the JobPatchFile options must be int
933*cdf0e10cSrcweir     // and should be emitted in order
934*cdf0e10cSrcweir     std::list< sal_Int32 > patch_order;
935*cdf0e10cSrcweir     int nValueCount = pKey->countValues();
936*cdf0e10cSrcweir     for( int i = 0; i < nValueCount; i++ )
937*cdf0e10cSrcweir     {
938*cdf0e10cSrcweir         const PPDValue* pVal = pKey->getValue( i );
939*cdf0e10cSrcweir         patch_order.push_back( pVal->m_aOption.ToInt32() );
940*cdf0e10cSrcweir         if( patch_order.back() == 0 && ! pVal->m_aOption.EqualsAscii( "0" ) )
941*cdf0e10cSrcweir         {
942*cdf0e10cSrcweir             WritePS( pFile, "% Warning: left out JobPatchFile option \"" );
943*cdf0e10cSrcweir             OString aOption = OUStringToOString( pVal->m_aOption, RTL_TEXTENCODING_ASCII_US );
944*cdf0e10cSrcweir             WritePS( pFile, aOption.getStr() );
945*cdf0e10cSrcweir             WritePS( pFile,
946*cdf0e10cSrcweir                      "\"\n% as it violates the PPD spec;\n"
947*cdf0e10cSrcweir                      "% JobPatchFile options need to be numbered for ordering.\n" );
948*cdf0e10cSrcweir         }
949*cdf0e10cSrcweir     }
950*cdf0e10cSrcweir 
951*cdf0e10cSrcweir     patch_order.sort();
952*cdf0e10cSrcweir     patch_order.unique();
953*cdf0e10cSrcweir 
954*cdf0e10cSrcweir     while( patch_order.begin() != patch_order.end() )
955*cdf0e10cSrcweir     {
956*cdf0e10cSrcweir         // note: this discards patch files not adhering to the "int" scheme
957*cdf0e10cSrcweir         // as there won't be a value for them
958*cdf0e10cSrcweir         writeFeature( pFile, pKey, pKey->getValue( OUString::valueOf( patch_order.front() ) ), false );
959*cdf0e10cSrcweir         patch_order.pop_front();
960*cdf0e10cSrcweir     }
961*cdf0e10cSrcweir }
962*cdf0e10cSrcweir 
963*cdf0e10cSrcweir bool PrinterJob::writeProlog (osl::File* pFile, const JobData& rJobData )
964*cdf0e10cSrcweir {
965*cdf0e10cSrcweir     WritePS( pFile, "%%BeginProlog\n" );
966*cdf0e10cSrcweir 
967*cdf0e10cSrcweir     // JobPatchFile feature needs to be emitted at begin of prolog
968*cdf0e10cSrcweir     writeJobPatch( pFile, rJobData );
969*cdf0e10cSrcweir 
970*cdf0e10cSrcweir     static const sal_Char pProlog[] = {
971*cdf0e10cSrcweir         "%%BeginResource: procset PSPrint-Prolog 1.0 0\n"
972*cdf0e10cSrcweir         "/ISO1252Encoding [\n"
973*cdf0e10cSrcweir         "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
974*cdf0e10cSrcweir         "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
975*cdf0e10cSrcweir         "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
976*cdf0e10cSrcweir         "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
977*cdf0e10cSrcweir         "/space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quotesingle\n"
978*cdf0e10cSrcweir         "/parenleft /parenright /asterisk /plus /comma /hyphen /period /slash\n"
979*cdf0e10cSrcweir         "/zero /one /two /three /four /five /six /seven\n"
980*cdf0e10cSrcweir         "/eight /nine /colon /semicolon /less /equal /greater /question\n"
981*cdf0e10cSrcweir         "/at /A /B /C /D /E /F /G\n"
982*cdf0e10cSrcweir         "/H /I /J /K /L /M /N /O\n"
983*cdf0e10cSrcweir         "/P /Q /R /S /T /U /V /W\n"
984*cdf0e10cSrcweir         "/X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore\n"
985*cdf0e10cSrcweir         "/grave /a /b /c /d /e /f /g\n"
986*cdf0e10cSrcweir         "/h /i /j /k /l /m /n /o\n"
987*cdf0e10cSrcweir         "/p /q /r /s /t /u /v /w\n"
988*cdf0e10cSrcweir         "/x /y /z /braceleft /bar /braceright /asciitilde /unused\n"
989*cdf0e10cSrcweir         "/Euro /unused /quotesinglbase /florin /quotedblbase /ellipsis /dagger /daggerdbl\n"
990*cdf0e10cSrcweir         "/circumflex /perthousand /Scaron /guilsinglleft /OE /unused /Zcaron /unused\n"
991*cdf0e10cSrcweir         "/unused /quoteleft /quoteright /quotedblleft /quotedblright /bullet /endash /emdash\n"
992*cdf0e10cSrcweir         "/tilde /trademark /scaron /guilsinglright /oe /unused /zcaron /Ydieresis\n"
993*cdf0e10cSrcweir         "/space /exclamdown /cent /sterling /currency /yen /brokenbar /section\n"
994*cdf0e10cSrcweir         "/dieresis /copyright /ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron\n"
995*cdf0e10cSrcweir         "/degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph /periodcentered\n"
996*cdf0e10cSrcweir         "/cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf /threequarters /questiondown\n"
997*cdf0e10cSrcweir         "/Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla\n"
998*cdf0e10cSrcweir         "/Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis\n"
999*cdf0e10cSrcweir         "/Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply\n"
1000*cdf0e10cSrcweir         "/Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls\n"
1001*cdf0e10cSrcweir         "/agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla\n"
1002*cdf0e10cSrcweir         "/egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis\n"
1003*cdf0e10cSrcweir         "/eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide\n"
1004*cdf0e10cSrcweir         "/oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis] def\n"
1005*cdf0e10cSrcweir         "\n"
1006*cdf0e10cSrcweir         "/psp_definefont { exch dup findfont dup length dict begin { 1 index /FID ne\n"
1007*cdf0e10cSrcweir         "{ def } { pop pop } ifelse } forall /Encoding 3 -1 roll def\n"
1008*cdf0e10cSrcweir         "currentdict end exch pop definefont pop } def\n"
1009*cdf0e10cSrcweir         "\n"
1010*cdf0e10cSrcweir         "/pathdict dup 8 dict def load begin\n"
1011*cdf0e10cSrcweir         "/rcmd { { currentfile 1 string readstring pop 0 get dup 32 gt { exit }\n"
1012*cdf0e10cSrcweir         "{ pop } ifelse } loop dup 126 eq { pop exit } if 65 sub dup 16#3 and 1\n"
1013*cdf0e10cSrcweir         "add exch dup 16#C and -2 bitshift 16#3 and 1 add exch 16#10 and 16#10\n"
1014*cdf0e10cSrcweir         "eq 3 1 roll exch } def\n"
1015*cdf0e10cSrcweir         "/rhex { dup 1 sub exch currentfile exch string readhexstring pop dup 0\n"
1016*cdf0e10cSrcweir         "get dup 16#80 and 16#80 eq dup 3 1 roll { 16#7f and } if 2 index 0 3\n"
1017*cdf0e10cSrcweir         "-1 roll put 3 1 roll 0 0 1 5 -1 roll { 2 index exch get add 256 mul }\n"
1018*cdf0e10cSrcweir         "for 256 div exch pop exch { neg } if } def\n"
1019*cdf0e10cSrcweir         "/xcmd { rcmd exch rhex exch rhex exch 5 -1 roll add exch 4 -1 roll add\n"
1020*cdf0e10cSrcweir         "1 index 1 index 5 -1 roll { moveto } { lineto } ifelse } def end\n"
1021*cdf0e10cSrcweir         "/readpath { 0 0 pathdict begin { xcmd } loop end pop pop } def\n"
1022*cdf0e10cSrcweir         "\n"
1023*cdf0e10cSrcweir         "systemdict /languagelevel known not {\n"
1024*cdf0e10cSrcweir         "/xshow { exch dup length 0 1 3 -1 roll 1 sub { dup 3 index exch get\n"
1025*cdf0e10cSrcweir         "exch 2 index exch get 1 string dup 0 4 -1 roll put currentpoint 3 -1\n"
1026*cdf0e10cSrcweir         "roll show moveto 0 rmoveto } for pop pop } def\n"
1027*cdf0e10cSrcweir         "/rectangle { 4 -2 roll moveto 1 index 0 rlineto 0 exch rlineto neg 0\n"
1028*cdf0e10cSrcweir         "rlineto closepath } def\n"
1029*cdf0e10cSrcweir         "/rectfill { rectangle fill } def\n"
1030*cdf0e10cSrcweir         "/rectstroke { rectangle stroke } def } if\n"
1031*cdf0e10cSrcweir         "/bshow { currentlinewidth 3 1 roll currentpoint 3 index show moveto\n"
1032*cdf0e10cSrcweir         "setlinewidth false charpath stroke setlinewidth } def\n"
1033*cdf0e10cSrcweir         "/bxshow { currentlinewidth 4 1 roll setlinewidth exch dup length 1 sub\n"
1034*cdf0e10cSrcweir         "0 1 3 -1 roll { 1 string 2 index 2 index get 1 index exch 0 exch put dup\n"
1035*cdf0e10cSrcweir         "currentpoint 3 -1 roll show moveto currentpoint 3 -1 roll false charpath\n"
1036*cdf0e10cSrcweir         "stroke moveto 2 index exch get 0 rmoveto } for pop pop setlinewidth } def\n"
1037*cdf0e10cSrcweir         "\n"
1038*cdf0e10cSrcweir 		"/psp_lzwfilter { currentfile /ASCII85Decode filter /LZWDecode filter } def\n"
1039*cdf0e10cSrcweir 		"/psp_ascii85filter { currentfile /ASCII85Decode filter } def\n"
1040*cdf0e10cSrcweir 		"/psp_lzwstring { psp_lzwfilter 1024 string readstring } def\n"
1041*cdf0e10cSrcweir 		"/psp_ascii85string { psp_ascii85filter 1024 string readstring } def\n"
1042*cdf0e10cSrcweir 		"/psp_imagedict {\n"
1043*cdf0e10cSrcweir 		"/psp_bitspercomponent { 3 eq { 1 }{ 8 } ifelse } def\n"
1044*cdf0e10cSrcweir 		"/psp_decodearray { [ [0 1 0 1 0 1] [0 255] [0 1] [0 255] ] exch get }\n"
1045*cdf0e10cSrcweir 		"def 7 dict dup\n"
1046*cdf0e10cSrcweir 		"/ImageType 1 put dup\n"
1047*cdf0e10cSrcweir 		"/Width 7 -1 roll put dup\n"
1048*cdf0e10cSrcweir 		"/Height 5 index put dup\n"
1049*cdf0e10cSrcweir 		"/BitsPerComponent 4 index psp_bitspercomponent put dup\n"
1050*cdf0e10cSrcweir 		"/Decode 5 -1 roll psp_decodearray put dup\n"
1051*cdf0e10cSrcweir 		"/ImageMatrix [1 0 0 1 0 0] dup 5 8 -1 roll put put dup\n"
1052*cdf0e10cSrcweir 		"/DataSource 4 -1 roll 1 eq { psp_lzwfilter } { psp_ascii85filter } ifelse put\n"
1053*cdf0e10cSrcweir         "} def\n"
1054*cdf0e10cSrcweir         "%%EndResource\n"
1055*cdf0e10cSrcweir         "%%EndProlog\n"
1056*cdf0e10cSrcweir     };
1057*cdf0e10cSrcweir     static const sal_Char pSO52CompatProlog[] = {
1058*cdf0e10cSrcweir         "%%BeginResource: procset PSPrint-Prolog 1.0 0\n"
1059*cdf0e10cSrcweir         "/ISO1252Encoding [\n"
1060*cdf0e10cSrcweir         "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
1061*cdf0e10cSrcweir         "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
1062*cdf0e10cSrcweir         "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
1063*cdf0e10cSrcweir         "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
1064*cdf0e10cSrcweir         "/space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright\n"
1065*cdf0e10cSrcweir         "/parenleft /parenright /asterisk /plus /comma /minus /period /slash\n"
1066*cdf0e10cSrcweir         "/zero /one /two /three /four /five /six /seven\n"
1067*cdf0e10cSrcweir         "/eight /nine /colon /semicolon /less /equal /greater /question\n"
1068*cdf0e10cSrcweir         "/at /A /B /C /D /E /F /G\n"
1069*cdf0e10cSrcweir         "/H /I /J /K /L /M /N /O\n"
1070*cdf0e10cSrcweir         "/P /Q /R /S /T /U /V /W\n"
1071*cdf0e10cSrcweir         "/X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore\n"
1072*cdf0e10cSrcweir         "/grave /a /b /c /d /e /f /g\n"
1073*cdf0e10cSrcweir         "/h /i /j /k /l /m /n /o\n"
1074*cdf0e10cSrcweir         "/p /q /r /s /t /u /v /w\n"
1075*cdf0e10cSrcweir         "/x /y /z /braceleft /bar /braceright /asciitilde /unused\n"
1076*cdf0e10cSrcweir         "/Euro /unused /quotesinglbase /florin /quotedblbase /ellipsis /dagger /daggerdbl\n"
1077*cdf0e10cSrcweir         "/circumflex /perthousand /Scaron /guilsinglleft /OE /unused /Zcaron /unused\n"
1078*cdf0e10cSrcweir         "/unused /quoteleft /quoteright /quotedblleft /quotedblright /bullet /endash /emdash\n"
1079*cdf0e10cSrcweir         "/tilde /trademark /scaron /guilsinglright /oe /unused /zcaron /Ydieresis\n"
1080*cdf0e10cSrcweir         "/space /exclamdown /cent /sterling /currency /yen /brokenbar /section\n"
1081*cdf0e10cSrcweir         "/dieresis /copyright /ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron\n"
1082*cdf0e10cSrcweir         "/degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph /periodcentered\n"
1083*cdf0e10cSrcweir         "/cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf /threequarters /questiondown\n"
1084*cdf0e10cSrcweir         "/Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla\n"
1085*cdf0e10cSrcweir         "/Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis\n"
1086*cdf0e10cSrcweir         "/Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply\n"
1087*cdf0e10cSrcweir         "/Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls\n"
1088*cdf0e10cSrcweir         "/agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla\n"
1089*cdf0e10cSrcweir         "/egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis\n"
1090*cdf0e10cSrcweir         "/eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide\n"
1091*cdf0e10cSrcweir         "/oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis] def\n"
1092*cdf0e10cSrcweir         "\n"
1093*cdf0e10cSrcweir         "/psp_definefont { exch dup findfont dup length dict begin { 1 index /FID ne\n"
1094*cdf0e10cSrcweir         "{ def } { pop pop } ifelse } forall /Encoding 3 -1 roll def\n"
1095*cdf0e10cSrcweir         "currentdict end exch pop definefont pop } def\n"
1096*cdf0e10cSrcweir         "\n"
1097*cdf0e10cSrcweir         "/pathdict dup 8 dict def load begin\n"
1098*cdf0e10cSrcweir         "/rcmd { { currentfile 1 string readstring pop 0 get dup 32 gt { exit }\n"
1099*cdf0e10cSrcweir         "{ pop } ifelse } loop dup 126 eq { pop exit } if 65 sub dup 16#3 and 1\n"
1100*cdf0e10cSrcweir         "add exch dup 16#C and -2 bitshift 16#3 and 1 add exch 16#10 and 16#10\n"
1101*cdf0e10cSrcweir         "eq 3 1 roll exch } def\n"
1102*cdf0e10cSrcweir         "/rhex { dup 1 sub exch currentfile exch string readhexstring pop dup 0\n"
1103*cdf0e10cSrcweir         "get dup 16#80 and 16#80 eq dup 3 1 roll { 16#7f and } if 2 index 0 3\n"
1104*cdf0e10cSrcweir         "-1 roll put 3 1 roll 0 0 1 5 -1 roll { 2 index exch get add 256 mul }\n"
1105*cdf0e10cSrcweir         "for 256 div exch pop exch { neg } if } def\n"
1106*cdf0e10cSrcweir         "/xcmd { rcmd exch rhex exch rhex exch 5 -1 roll add exch 4 -1 roll add\n"
1107*cdf0e10cSrcweir         "1 index 1 index 5 -1 roll { moveto } { lineto } ifelse } def end\n"
1108*cdf0e10cSrcweir         "/readpath { 0 0 pathdict begin { xcmd } loop end pop pop } def\n"
1109*cdf0e10cSrcweir         "\n"
1110*cdf0e10cSrcweir         "systemdict /languagelevel known not {\n"
1111*cdf0e10cSrcweir         "/xshow { exch dup length 0 1 3 -1 roll 1 sub { dup 3 index exch get\n"
1112*cdf0e10cSrcweir         "exch 2 index exch get 1 string dup 0 4 -1 roll put currentpoint 3 -1\n"
1113*cdf0e10cSrcweir         "roll show moveto 0 rmoveto } for pop pop } def\n"
1114*cdf0e10cSrcweir         "/rectangle { 4 -2 roll moveto 1 index 0 rlineto 0 exch rlineto neg 0\n"
1115*cdf0e10cSrcweir         "rlineto closepath } def\n"
1116*cdf0e10cSrcweir         "/rectfill { rectangle fill } def\n"
1117*cdf0e10cSrcweir         "/rectstroke { rectangle stroke } def } if\n"
1118*cdf0e10cSrcweir         "/bshow { currentlinewidth 3 1 roll currentpoint 3 index show moveto\n"
1119*cdf0e10cSrcweir         "setlinewidth false charpath stroke setlinewidth } def\n"
1120*cdf0e10cSrcweir         "/bxshow { currentlinewidth 4 1 roll setlinewidth exch dup length 1 sub\n"
1121*cdf0e10cSrcweir         "0 1 3 -1 roll { 1 string 2 index 2 index get 1 index exch 0 exch put dup\n"
1122*cdf0e10cSrcweir         "currentpoint 3 -1 roll show moveto currentpoint 3 -1 roll false charpath\n"
1123*cdf0e10cSrcweir         "stroke moveto 2 index exch get 0 rmoveto } for pop pop setlinewidth } def\n"
1124*cdf0e10cSrcweir         "\n"
1125*cdf0e10cSrcweir 		"/psp_lzwfilter { currentfile /ASCII85Decode filter /LZWDecode filter } def\n"
1126*cdf0e10cSrcweir 		"/psp_ascii85filter { currentfile /ASCII85Decode filter } def\n"
1127*cdf0e10cSrcweir 		"/psp_lzwstring { psp_lzwfilter 1024 string readstring } def\n"
1128*cdf0e10cSrcweir 		"/psp_ascii85string { psp_ascii85filter 1024 string readstring } def\n"
1129*cdf0e10cSrcweir 		"/psp_imagedict {\n"
1130*cdf0e10cSrcweir 		"/psp_bitspercomponent { 3 eq { 1 }{ 8 } ifelse } def\n"
1131*cdf0e10cSrcweir 		"/psp_decodearray { [ [0 1 0 1 0 1] [0 255] [0 1] [0 255] ] exch get }\n"
1132*cdf0e10cSrcweir 		"def 7 dict dup\n"
1133*cdf0e10cSrcweir 		"/ImageType 1 put dup\n"
1134*cdf0e10cSrcweir 		"/Width 7 -1 roll put dup\n"
1135*cdf0e10cSrcweir 		"/Height 5 index put dup\n"
1136*cdf0e10cSrcweir 		"/BitsPerComponent 4 index psp_bitspercomponent put dup\n"
1137*cdf0e10cSrcweir 		"/Decode 5 -1 roll psp_decodearray put dup\n"
1138*cdf0e10cSrcweir 		"/ImageMatrix [1 0 0 1 0 0] dup 5 8 -1 roll put put dup\n"
1139*cdf0e10cSrcweir 		"/DataSource 4 -1 roll 1 eq { psp_lzwfilter } { psp_ascii85filter } ifelse put\n"
1140*cdf0e10cSrcweir         "} def\n"
1141*cdf0e10cSrcweir         "%%EndResource\n"
1142*cdf0e10cSrcweir         "%%EndProlog\n"
1143*cdf0e10cSrcweir     };
1144*cdf0e10cSrcweir     WritePS (pFile, m_pGraphics && m_pGraphics->getStrictSO52Compatibility() ? pSO52CompatProlog : pProlog);
1145*cdf0e10cSrcweir 
1146*cdf0e10cSrcweir     return true;
1147*cdf0e10cSrcweir }
1148*cdf0e10cSrcweir 
1149*cdf0e10cSrcweir bool PrinterJob::writeSetup( osl::File* pFile, const JobData& rJob )
1150*cdf0e10cSrcweir {
1151*cdf0e10cSrcweir     WritePS (pFile, "%%BeginSetup\n%\n");
1152*cdf0e10cSrcweir 
1153*cdf0e10cSrcweir     // download fonts
1154*cdf0e10cSrcweir     std::list< rtl::OString > aFonts[2];
1155*cdf0e10cSrcweir     m_pGraphics->writeResources( pFile, aFonts[0], aFonts[1] );
1156*cdf0e10cSrcweir 
1157*cdf0e10cSrcweir     for( int i = 0; i < 2; i++ )
1158*cdf0e10cSrcweir     {
1159*cdf0e10cSrcweir         if( !aFonts[i].empty() )
1160*cdf0e10cSrcweir         {
1161*cdf0e10cSrcweir             std::list< rtl::OString >::const_iterator it = aFonts[i].begin();
1162*cdf0e10cSrcweir             rtl::OStringBuffer aLine( 256 );
1163*cdf0e10cSrcweir             if( i == 0 )
1164*cdf0e10cSrcweir                 aLine.append( "%%DocumentSuppliedResources: font " );
1165*cdf0e10cSrcweir             else
1166*cdf0e10cSrcweir                 aLine.append( "%%DocumentNeededResources: font " );
1167*cdf0e10cSrcweir             aLine.append( *it );
1168*cdf0e10cSrcweir             aLine.append( "\n" );
1169*cdf0e10cSrcweir             WritePS ( pFile, aLine.getStr() );
1170*cdf0e10cSrcweir             while( (++it) != aFonts[i].end() )
1171*cdf0e10cSrcweir             {
1172*cdf0e10cSrcweir                 aLine.setLength(0);
1173*cdf0e10cSrcweir                 aLine.append( "%%+ font " );
1174*cdf0e10cSrcweir                 aLine.append( *it );
1175*cdf0e10cSrcweir                 aLine.append( "\n" );
1176*cdf0e10cSrcweir                 WritePS ( pFile, aLine.getStr() );
1177*cdf0e10cSrcweir             }
1178*cdf0e10cSrcweir         }
1179*cdf0e10cSrcweir     }
1180*cdf0e10cSrcweir 
1181*cdf0e10cSrcweir     bool bSuccess = true;
1182*cdf0e10cSrcweir     // in case of external print dialog the number of copies is prepended
1183*cdf0e10cSrcweir     // to the job, let us not complicate things by emitting our own copy count
1184*cdf0e10cSrcweir     bool bExternalDialog = PrinterInfoManager::get().checkFeatureToken( GetPrinterName(), "external_dialog" );
1185*cdf0e10cSrcweir     if( ! bExternalDialog && rJob.m_nCopies > 1 )
1186*cdf0e10cSrcweir     {
1187*cdf0e10cSrcweir         // setup code
1188*cdf0e10cSrcweir         ByteString aLine( "/#copies " );
1189*cdf0e10cSrcweir         aLine += ByteString::CreateFromInt32( rJob.m_nCopies );
1190*cdf0e10cSrcweir         aLine +=  " def\n";
1191*cdf0e10cSrcweir         sal_uInt64 nWritten = 0;
1192*cdf0e10cSrcweir         bSuccess = pFile->write( aLine.GetBuffer(), aLine.Len(), nWritten )
1193*cdf0e10cSrcweir             || nWritten != aLine.Len() ? false : true;
1194*cdf0e10cSrcweir 
1195*cdf0e10cSrcweir         if( bSuccess && GetPostscriptLevel( &rJob ) >= 2 )
1196*cdf0e10cSrcweir             WritePS (pFile, "<< /NumCopies null /Policies << /NumCopies 1 >> >> setpagedevice\n" );
1197*cdf0e10cSrcweir     }
1198*cdf0e10cSrcweir 
1199*cdf0e10cSrcweir     bool bFeatureSuccess = writeFeatureList( pFile, rJob, true );
1200*cdf0e10cSrcweir 
1201*cdf0e10cSrcweir     WritePS (pFile, "%%EndSetup\n");
1202*cdf0e10cSrcweir 
1203*cdf0e10cSrcweir     return bSuccess && bFeatureSuccess;
1204*cdf0e10cSrcweir }
1205