xref: /aoo41x/main/vcl/os2/source/gdi/salprn.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // use this define to disable the DJP support
29 // #define NO_DJP
30 
31 #define INCL_DOSMODULEMGR
32 #define INCL_DEV
33 #define INCL_SPL
34 #define INCL_SPLERRORS
35 #define INCL_SPLDOSPRINT
36 #define INCL_DEVDJP
37 
38 #define INCL_GPI
39 #define INCL_DOSSEMAPHORES
40 #define INCL_PM
41 #include <svpm.h>
42 #include <pmdjp.h>
43 
44 #include <string.h>
45 
46 #define _SV_SALPRN_CXX
47 #include <tools/debug.hxx>
48 #include <saldata.hxx>
49 #include <salinst.h>
50 #include <salgdi.h>
51 #include <salframe.h>
52 #include <vcl/salptype.hxx>
53 #include <salprn.h>
54 #include <vcl/print.h>
55 #include <vcl/jobset.h>
56 
57 #ifndef __H_FT2LIB
58 #include <wingdi.h>
59 #include <ft2lib.h>
60 #endif
61 
62 // =======================================================================
63 
64 // -----------------------
65 // - struct ImplFormInfo -
66 // -----------------------
67 
68 struct ImplFormInfo
69 {
70 	long					mnPaperWidth;
71 	long					mnPaperHeight;
72 #ifndef NO_DJP
73 	DJPT_PAPERSIZE			mnId;
74 #endif
75 };
76 
77 // =======================================================================
78 
79 // -----------------------
80 // - struct ImplTrayInfo -
81 // -----------------------
82 
83 struct ImplTrayInfo
84 {
85 	CHAR			maName[32];
86 	CHAR			maDisplayName[64];
87 	DJPT_TRAYTYPE	mnId;
88 
89 	ImplTrayInfo( const char* pTrayName,
90 				  const char* pTrayDisplayName )
91 	{
92 		strcpy( maName, pTrayName);
93 		strcpy( maDisplayName, pTrayDisplayName);
94 	}
95 };
96 
97 // =======================================================================
98 
99 struct ImplQueueSalSysData
100 {
101 	ByteString		maPrinterName;			// pszPrinters
102 	ByteString		maName; 				// pszName bzw. LogAddress
103 	ByteString		maOrgDriverName;		// pszDriverName (maDriverName.maDeviceName)
104 	ByteString		maDriverName;			// pszDriverName bis .
105 	ByteString		maDeviceName;			// pszDriverName nach .
106 	PDRIVDATA		mpDrivData;
107 
108 					ImplQueueSalSysData( const ByteString& rPrinterName,
109 										 const ByteString& rName,
110 										 const ByteString& rDriverName,
111 										 const ByteString& rDeviceName,
112 										 const ByteString& rOrgDriverName,
113 										 PDRIVDATA pDrivData  );
114 					~ImplQueueSalSysData();
115 };
116 
117 // -----------------------------------------------------------------------
118 
119 ImplQueueSalSysData::ImplQueueSalSysData( const ByteString& rPrinterName,
120 										  const ByteString& rName,
121 										  const ByteString& rOrgDriverName,
122 										  const ByteString& rDriverName,
123 										  const ByteString& rDeviceName,
124 										  PDRIVDATA pDrivData ) :
125 	maPrinterName( rPrinterName ),
126 	maName( rName ),
127 	maOrgDriverName( rName ),
128 	maDriverName( rDriverName ),
129 	maDeviceName( rDeviceName )
130 {
131 	if ( pDrivData )
132 	{
133 		mpDrivData = (PDRIVDATA)new BYTE[pDrivData->cb];
134 		memcpy( mpDrivData, pDrivData, pDrivData->cb );
135 	}
136 	else
137 		mpDrivData = NULL;
138 }
139 
140 // -----------------------------------------------------------------------
141 
142 ImplQueueSalSysData::~ImplQueueSalSysData()
143 {
144 	delete mpDrivData;
145 }
146 
147 // =======================================================================
148 
149 static ULONG ImplPMQueueStatusToSal( USHORT nPMStatus )
150 {
151 	ULONG nStatus = 0;
152 	if ( nPMStatus & PRQ3_PAUSED )
153 		nStatus |= QUEUE_STATUS_PAUSED;
154 	if ( nPMStatus & PRQ3_PENDING )
155 		nStatus |= QUEUE_STATUS_PENDING_DELETION;
156 	if ( !nStatus )
157 		nStatus |= QUEUE_STATUS_READY;
158 	return nStatus;
159 }
160 
161 // -----------------------------------------------------------------------
162 
163 void Os2SalInstance::GetPrinterQueueInfo( ImplPrnQueueList* pList )
164 {
165 	APIRET rc;
166 	ULONG  nNeeded;
167 	ULONG  nReturned;
168 	ULONG  nTotal;
169 
170 	// query needed size of the buffer for the QueueInfo
171 	rc = SplEnumQueue( (PSZ)NULL, 3, NULL, 0, &nReturned, &nTotal, &nNeeded, NULL );
172 	if( nNeeded == 0 )
173 		return;
174 
175 	// create the buffer for the QueueInfo
176 	PCHAR pQueueData = new CHAR[nNeeded];
177 
178 	// query QueueInfos
179 	rc = SplEnumQueue( (PSZ)NULL, 3, pQueueData, nNeeded, &nReturned, &nTotal, &nNeeded, NULL );
180 
181 	PPRQINFO3 pPrqInfo = (PPRQINFO3)pQueueData;
182 	for ( int i = 0; i < nReturned; i++ )
183 	{
184 		// create entry for the QueueInfo array
185 		SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo;
186 
187 		ByteString aOrgDriverName( pPrqInfo->pszDriverName);
188 		ByteString aName( pPrqInfo->pszName);
189 		pInfo->maDriver 	 = ::rtl::OStringToOUString (aOrgDriverName, gsl_getSystemTextEncoding());
190 		pInfo->maPrinterName = ::rtl::OStringToOUString (pPrqInfo->pszComment, gsl_getSystemTextEncoding());
191 		pInfo->maLocation	 = ::rtl::OStringToOUString (aName, gsl_getSystemTextEncoding());
192 		pInfo->mnStatus 	 = ImplPMQueueStatusToSal( pPrqInfo->fsStatus );
193 		pInfo->mnJobs		 = pPrqInfo->cJobs;
194 		// pInfo->maComment = !!!
195 
196 		// Feststellen, ob Name doppelt
197 		PPRQINFO3 pTempPrqInfo = (PPRQINFO3)pQueueData;
198 		for ( int j = 0; j < nReturned; j++ )
199 		{
200 			// Wenn Name doppelt, erweitern wir diesen um die Location
201 			if ( (j != i) &&
202 				 (strcmp( pPrqInfo->pszComment, pTempPrqInfo->pszComment ) == 0) )
203 			{
204 				pInfo->maPrinterName += ';';
205 				pInfo->maPrinterName += pInfo->maLocation;
206 			}
207 			pTempPrqInfo++;
208 		}
209 
210 		// pszDriver in DriverName (bis .) und DeviceName (nach .) aufsplitten
211 		PSZ pDriverName;
212 		PSZ pDeviceName;
213 		if ( (pDriverName = strchr( pPrqInfo->pszDriverName, '.' )) != 0 )
214 		{
215 		   *pDriverName = 0;
216 		   pDeviceName	= pDriverName + 1;
217 		}
218 		else
219 			pDeviceName = NULL;
220 
221 		// Alle Bytes hinter dem DeviceNamen auf 0 initialisieren, damit
222 		// ein memcmp vom JobSetup auch funktioniert
223 		if ( pPrqInfo->pDriverData &&
224 			 (pPrqInfo->pDriverData->cb >= sizeof( pPrqInfo->pDriverData )) )
225 		{
226 			int nDeviceNameLen = strlen( pPrqInfo->pDriverData->szDeviceName );
227 			memset( pPrqInfo->pDriverData->szDeviceName+nDeviceNameLen,
228 					0,
229 					sizeof( pPrqInfo->pDriverData->szDeviceName )-nDeviceNameLen );
230 		}
231 
232 		// save driver data and driver names
233 		ByteString aPrinterName( pPrqInfo->pszPrinters);
234 		ByteString aDriverName( pPrqInfo->pszDriverName);
235 		ByteString aDeviceName;
236 		if ( pDeviceName )
237 			aDeviceName = pDeviceName;
238 		pInfo->mpSysData = new ImplQueueSalSysData( aPrinterName, aName,
239 													aOrgDriverName,
240 													aDriverName, aDeviceName,
241 													pPrqInfo->pDriverData );
242 
243 		// add queue to the list
244 		pList->Add( pInfo );
245 
246 		// increment to next element of the QueueInfo array
247 		pPrqInfo++;
248 	}
249 
250 	delete [] pQueueData;
251 }
252 
253 // -----------------------------------------------------------------------
254 
255 void Os2SalInstance::GetPrinterQueueState( SalPrinterQueueInfo* pInfo )
256 {
257 	APIRET rc;
258 	ULONG  nNeeded;
259 	ULONG  nReturned;
260 	ULONG  nTotal;
261 
262 	// query needed size of the buffer for the QueueInfo
263 	rc = SplEnumQueue( (PSZ)NULL, 3, NULL, 0, &nReturned, &nTotal, &nNeeded, NULL );
264 	if( nNeeded == 0 )
265 		return;
266 
267 	// create the buffer for the QueueInfo
268 	PCHAR pQueueData = new CHAR[nNeeded];
269 
270 	// query QueueInfos
271 	rc = SplEnumQueue( (PSZ)NULL, 3, pQueueData, nNeeded, &nReturned, &nTotal, &nNeeded, NULL );
272 
273 	PPRQINFO3 pPrqInfo = (PPRQINFO3)pQueueData;
274 	for ( int i = 0; i < nReturned; i++ )
275 	{
276 		ImplQueueSalSysData* pSysData = (ImplQueueSalSysData*)(pInfo->mpSysData);
277 		if ( pSysData->maPrinterName.Equals( pPrqInfo->pszPrinters ) &&
278 			 pSysData->maName.Equals( pPrqInfo->pszName ) &&
279 			 pSysData->maOrgDriverName.Equals( pPrqInfo->pszDriverName ) )
280 		{
281 			pInfo->mnStatus = ImplPMQueueStatusToSal( pPrqInfo->fsStatus );
282 			pInfo->mnJobs	= pPrqInfo->cJobs;
283 			break;
284 		}
285 
286 		// increment to next element of the QueueInfo array
287 		pPrqInfo++;
288 	}
289 
290 	delete [] pQueueData;
291 }
292 
293 // -----------------------------------------------------------------------
294 
295 void Os2SalInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo* pInfo )
296 {
297 	delete ((ImplQueueSalSysData*)(pInfo->mpSysData));
298 	delete pInfo;
299 }
300 
301 // -----------------------------------------------------------------------
302 
303 XubString Os2SalInstance::GetDefaultPrinter()
304 {
305 	APIRET		rc;
306 	ULONG		nNeeded;
307 	ULONG		nReturned;
308 	ULONG		nTotal;
309 	char		szQueueName[255];
310 	XubString	aDefaultName;
311 
312 	// query default queue
313 	if ( !PrfQueryProfileString( HINI_PROFILE, SPL_INI_SPOOLER, "QUEUE", 0, szQueueName, sizeof( szQueueName ) ) )
314 		return aDefaultName;
315 
316 	// extract first queue name
317 	PSZ pStr;
318 	if ( (pStr = strchr( szQueueName, ';' )) != 0 )
319 		*pStr = 0;
320 
321 	// query needed size of the buffer for the QueueInfo
322 	rc = SplEnumQueue( (PSZ)NULL, 3, NULL, 0, &nReturned, &nTotal, &nNeeded, NULL );
323 	if ( nNeeded == 0 )
324 		return aDefaultName;
325 
326 	// create the buffer for the QueueInfo
327 	PCHAR pQueueData = new CHAR[ nNeeded ];
328 
329 	// query QueueInfos
330 	rc = SplEnumQueue ((PSZ)NULL, 3, pQueueData, nNeeded, &nReturned, &nTotal, &nNeeded, NULL );
331 
332 	// find printer name for default queue
333 	PPRQINFO3 pPrqInfo = (PPRQINFO3) pQueueData;
334 	for ( int i = 0; i < nReturned; i++ )
335 	{
336 		if ( strcmp( pPrqInfo->pszName, szQueueName ) == 0 )
337 		{
338 			aDefaultName = ::rtl::OStringToOUString (pPrqInfo->pszComment, gsl_getSystemTextEncoding());
339 
340 			// Feststellen, ob Name doppelt
341 			PPRQINFO3 pTempPrqInfo = (PPRQINFO3)pQueueData;
342 			for ( int j = 0; j < nReturned; j++ )
343 			{
344 				// Wenn Name doppelt, erweitern wir diesen um die Location
345 				if ( (j != i) &&
346 					 (strcmp( pPrqInfo->pszComment, pTempPrqInfo->pszComment ) == 0) )
347 				{
348 					String pszName( ::rtl::OStringToOUString (pPrqInfo->pszName, gsl_getSystemTextEncoding()));
349 					aDefaultName += ';';
350 					aDefaultName += pszName;
351 				}
352 				pTempPrqInfo++;
353 			}
354 			break;
355 		}
356 
357 		// increment to next element of the QueueInfo array
358 		pPrqInfo++;
359 	}
360 
361 	delete [] pQueueData;
362 
363 	return aDefaultName;
364 }
365 
366 // =======================================================================
367 
368 static void* ImplAllocPrnMemory( size_t n )
369 {
370 	return calloc( n, 1);
371 }
372 
373 // -----------------------------------------------------------------------
374 
375 inline void ImplFreePrnMemory( void* p )
376 {
377 	free( p );
378 }
379 
380 // -----------------------------------------------------------------------
381 
382 static PDRIVDATA ImplPrnDrivData( const ImplJobSetup* pSetupData )
383 {
384 	// Diese Funktion wird eingesetzt, damit Druckertreiber nicht auf
385 	// unseren Daten arbeiten, da es durch Konfigurationsprobleme
386 	// sein kann, das der Druckertreiber bei uns Daten ueberschreibt.
387 	// Durch diese vorgehensweise werden einige Abstuerze vermieden, bzw.
388 	// sind dadurch leichter zu finden
389 
390 	if ( !pSetupData->mpDriverData )
391 		return NULL;
392 
393 	DBG_ASSERT( ((PDRIVDATA)(pSetupData->mpDriverData))->cb == pSetupData->mnDriverDataLen,
394 				"ImplPrnDrivData() - SetupDataLen != DriverDataLen" );
395 
396 	PDRIVDATA pDrivData = (PDRIVDATA)ImplAllocPrnMemory( pSetupData->mnDriverDataLen );
397 	memcpy( pDrivData, pSetupData->mpDriverData, pSetupData->mnDriverDataLen );
398 	return pDrivData;
399 }
400 
401 // -----------------------------------------------------------------------
402 
403 static void ImplUpdateSetupData( const PDRIVDATA pDrivData, ImplJobSetup* pSetupData )
404 {
405 	// Diese Funktion wird eingesetzt, damit Druckertreiber nicht auf
406 	// unseren Daten arbeiten, da es durch Konfigurationsprobleme
407 	// sein kann, das der Druckertreiber bei uns Daten ueberschreibt.
408 	// Durch diese vorgehensweise werden einige Abstuerze vermieden, bzw.
409 	// sind dadurch leichter zu finden
410 
411 	if ( !pDrivData || !pDrivData->cb )
412 	{
413 		if ( pSetupData->mpDriverData )
414 			rtl_freeMemory( pSetupData->mpDriverData );
415 		pSetupData->mpDriverData = NULL;
416 		pSetupData->mnDriverDataLen = 0;
417 	}
418 	else
419 	{
420 		// Alle Bytes hinter dem DeviceNamen auf 0 initialisieren, damit
421 		// ein memcmp vom JobSetup auch funktioniert
422 		if ( pDrivData->cb >= sizeof( pDrivData ) )
423 		{
424 			int nDeviceNameLen = strlen( pDrivData->szDeviceName );
425 			memset( pDrivData->szDeviceName+nDeviceNameLen,
426 					0,
427 					sizeof( pDrivData->szDeviceName )-nDeviceNameLen );
428 		}
429 
430 		if ( pSetupData->mpDriverData )
431 		{
432 			if ( pSetupData->mnDriverDataLen != pDrivData->cb )
433 				rtl_freeMemory( pSetupData->mpDriverData );
434 			pSetupData->mpDriverData = (BYTE*)rtl_allocateMemory( pDrivData->cb);
435 		}
436 		else
437 			pSetupData->mpDriverData = (BYTE*)rtl_allocateMemory( pDrivData->cb);
438 		pSetupData->mnDriverDataLen = pDrivData->cb;
439 		memcpy( pSetupData->mpDriverData, pDrivData, pDrivData->cb );
440 	}
441 
442 	if ( pDrivData )
443 		ImplFreePrnMemory( pDrivData );
444 }
445 
446 // -----------------------------------------------------------------------
447 
448 static BOOL ImplPaperSizeEqual( long nPaperWidth1, long nPaperHeight1,
449 								long nPaperWidth2, long nPaperHeight2 )
450 {
451 	return (((nPaperWidth1 >= nPaperWidth2-1) && (nPaperWidth1 <= nPaperWidth2+1)) &&
452 			((nPaperHeight1 >= nPaperHeight2-1) && (nPaperHeight1 <= nPaperHeight2+1)));
453 }
454 
455 // -----------------------------------------------------------------------
456 
457 static BOOL ImplIsDriverDJPEnabled( HDC hDC )
458 {
459 #ifdef NO_DJP
460 	return FALSE;
461 #else
462 	// Ueber OS2-Ini kann DJP disablte werden
463 	if ( !PrfQueryProfileInt( HINI_PROFILE, SAL_PROFILE_APPNAME, SAL_PROFILE_USEDJP, 1 ) )
464 		return FALSE;
465 
466 	// Testen, ob DJP-Interface am Drucker vorhanden
467 	LONG   lQuery;
468 	APIRET rc;
469 
470 	lQuery = DEVESC_QUERYSIZE;
471 	rc = DevEscape( hDC,
472 					DEVESC_QUERYESCSUPPORT,
473 					sizeof( lQuery ),
474 					(PBYTE)&lQuery,
475 					0,
476 					(PBYTE)NULL );
477 	if ( DEV_OK != rc )
478 		return FALSE;
479 
480 	lQuery = DEVESC_QUERYJOBPROPERTIES;
481 	rc = DevEscape( hDC,
482 					DEVESC_QUERYESCSUPPORT,
483 					sizeof( lQuery ),
484 					(PBYTE)&lQuery,
485 					0,
486 					(PBYTE)NULL );
487 	if ( DEV_OK != rc )
488 		return FALSE;
489 
490 	lQuery = DEVESC_SETJOBPROPERTIES;
491 	rc = DevEscape( hDC,
492 					DEVESC_QUERYESCSUPPORT,
493 					sizeof( lQuery ),
494 					(PBYTE)&lQuery,
495 					0,
496 					(PBYTE)NULL );
497 	if ( DEV_OK != rc )
498 		return FALSE;
499 
500 	return TRUE;
501 #endif
502 }
503 
504 // -----------------------------------------------------------------------
505 
506 static void ImplFormatInputList( PDJP_ITEM pDJP, PQUERYTUPLE pTuple )
507 {
508    // Loop through the query elements
509    BOOL fContinue = TRUE;
510    do
511    {
512 	  pDJP->cb			  = sizeof (DJP_ITEM);
513 	  pDJP->ulProperty	  = pTuple->ulProperty;
514 	  pDJP->lType		  = pTuple->lType;
515 	  pDJP->ulNumReturned = 0;
516 	  pDJP->ulValue 	  = DJP_NONE;
517 
518 	  // at EOL?
519 	  fContinue = DJP_NONE != pTuple->ulProperty;
520 
521 	  // Move to next item structure and tuplet
522 	  pDJP++;
523 	  pTuple++;
524    }
525    while ( fContinue );
526 }
527 
528 // -----------------------------------------------------------------------
529 
530 static void ImplFreeFormAndTrayList( Os2SalInfoPrinter* pOs2SalInfoPrinter )
531 {
532 	if ( pOs2SalInfoPrinter->mnFormCount )
533 	{
534 		for ( USHORT i = 0; i < pOs2SalInfoPrinter->mnFormCount; i++ )
535 			delete pOs2SalInfoPrinter->mpFormArray[i];
536 		delete [] pOs2SalInfoPrinter->mpFormArray;
537 		pOs2SalInfoPrinter->mnFormCount = 0;
538 	}
539 
540 	if ( pOs2SalInfoPrinter->mnTrayCount )
541 	{
542 		for ( USHORT i = 0; i < pOs2SalInfoPrinter->mnTrayCount; i++ )
543 			delete pOs2SalInfoPrinter->mpTrayArray[i];
544 		delete [] pOs2SalInfoPrinter->mpTrayArray;
545 		pOs2SalInfoPrinter->mnTrayCount = 0;
546 	}
547 }
548 
549 // -----------------------------------------------------------------------
550 
551 static void ImplGetFormAndTrayList( Os2SalInfoPrinter* pOs2SalInfoPrinter, const ImplJobSetup* pSetupData )
552 {
553 	ImplFreeFormAndTrayList( pOs2SalInfoPrinter );
554 
555 	LONG alQuery[] =
556 	{
557 		0,					0,				// First two members of QUERYSIZE
558 		DJP_CJ_FORM,		DJP_ALL,
559 		DJP_CJ_TRAYNAME,	DJP_ALL,
560 		DJP_NONE,			DJP_NONE		// EOL marker
561 	};
562 
563 	APIRET		rc;
564 	PQUERYSIZE	pQuerySize			= (PQUERYSIZE)alQuery;
565 	PBYTE		pBuffer 			= NULL;
566 	LONG		nAlloc				= 0;
567 	PDRIVDATA	pCopyDrivData		= ImplPrnDrivData( pSetupData );
568 	LONG		nDrivDataSize		= pCopyDrivData->cb;
569 	PBYTE		pDrivData			= (PBYTE)pCopyDrivData;
570 
571 	// find out how many bytes to allocate
572 	pQuerySize->cb = sizeof( alQuery );
573 	rc = DevEscape( pOs2SalInfoPrinter->mhDC,
574 					DEVESC_QUERYSIZE,
575 					sizeof( alQuery ),
576 					(PBYTE)pQuerySize,
577 					&nDrivDataSize,
578 					pDrivData );
579 	if ( DEV_OK != rc )
580 	{
581 		ImplFreePrnMemory( pCopyDrivData );
582 		return;
583 	}
584 
585 	// allocate the memory
586 	nAlloc = pQuerySize->ulSizeNeeded;
587 	pBuffer = (PBYTE)new BYTE[nAlloc];
588 
589 	// set up the input
590 	PDJP_ITEM pDJP = (PDJP_ITEM)pBuffer;
591 	ImplFormatInputList( pDJP, pQuerySize->aTuples );
592 
593 	// do it!
594 	rc = DevEscape( pOs2SalInfoPrinter->mhDC,
595 					DEVESC_QUERYJOBPROPERTIES,
596 					nAlloc,
597 					pBuffer,
598 					&nDrivDataSize,
599 					pDrivData );
600 	ImplFreePrnMemory( pCopyDrivData );
601 
602 	if ( (DEV_OK == rc) || (DEV_WARNING == rc) )
603 	{
604 		// Loop through the query elements
605 		PQUERYTUPLE pTuple = pQuerySize->aTuples;
606 		while ( DJP_NONE != pTuple->ulProperty )
607 		{
608 			if ( pDJP->ulProperty == DJP_CJ_FORM )
609 			{
610 				if ( pDJP->ulNumReturned )
611 				{
612 					PDJPT_FORM pElm = DJP_ELEMENTP( *pDJP, DJPT_FORM );
613 
614 					pOs2SalInfoPrinter->mnFormCount = pDJP->ulNumReturned;
615 					pOs2SalInfoPrinter->mpFormArray = new PIMPLFORMINFO[pOs2SalInfoPrinter->mnFormCount];
616 					for( int i = 0; i < pDJP->ulNumReturned; i++, pElm++ )
617 					{
618 						ImplFormInfo* pInfo 	= new ImplFormInfo;
619 						pInfo->mnPaperWidth 	= pElm->hcInfo.cx;
620 						pInfo->mnPaperHeight	= pElm->hcInfo.cy;
621 						pInfo->mnId 			= pElm->djppsFormID;
622 						pOs2SalInfoPrinter->mpFormArray[i] = pInfo;
623 					}
624 				}
625 			}
626 			else if ( pDJP->ulProperty == DJP_CJ_TRAYNAME )
627 			{
628 				if ( pDJP->ulNumReturned )
629 				{
630 					PDJPT_TRAYNAME pElm = DJP_ELEMENTP( *pDJP, DJPT_TRAYNAME );
631 
632 					pOs2SalInfoPrinter->mnTrayCount = pDJP->ulNumReturned;
633 					pOs2SalInfoPrinter->mpTrayArray = new PIMPLTRAYINFO[pOs2SalInfoPrinter->mnTrayCount];
634 					for( int i = 0; i < pDJP->ulNumReturned; i++, pElm++ )
635 					{
636 						ImplTrayInfo* pInfo 	= new ImplTrayInfo( pElm->szTrayname, pElm->szDisplayTrayname );
637 						pInfo->mnId 			= pElm->djpttTrayID;
638 						pOs2SalInfoPrinter->mpTrayArray[i] = pInfo;
639 					}
640 				}
641 			}
642 
643 			pDJP = DJP_NEXT_STRUCTP( pDJP );
644 			pTuple++;
645 		}
646 	}
647 
648 	delete [] pBuffer;
649 }
650 
651 // -----------------------------------------------------------------------
652 
653 static BOOL ImplGetCurrentSettings( Os2SalInfoPrinter* pOs2SalInfoPrinter, ImplJobSetup* pSetupData )
654 {
655 	// Um den aktuellen Tray zu ermitteln, brauchen wir auch die Listen dazu
656 	if ( !pOs2SalInfoPrinter->mnFormCount )
657 		ImplGetFormAndTrayList( pOs2SalInfoPrinter, pSetupData );
658 
659 	LONG alQuery[] =
660 	{
661 		0,						0,				// First two members of QUERYSIZE
662 		DJP_SJ_ORIENTATION, 	DJP_CURRENT,
663 		DJP_CJ_FORM,			DJP_CURRENT,
664 		DJP_NONE,				DJP_NONE		// EOL marker
665 	};
666 
667 	APIRET		rc;
668 	PQUERYSIZE	pQuerySize			= (PQUERYSIZE)alQuery;
669 	PBYTE		pBuffer 			= NULL;
670 	LONG		nAlloc				= 0;
671 	PDRIVDATA	pCopyDrivData		= ImplPrnDrivData( pSetupData );
672 	LONG		nDrivDataSize		= pCopyDrivData->cb;
673 	PBYTE		pDrivData			= (PBYTE)pCopyDrivData;
674 	BOOL		bResult;
675 
676 	// find out how many bytes to allocate
677 	pQuerySize->cb = sizeof( alQuery );
678 	rc = DevEscape( pOs2SalInfoPrinter->mhDC,
679 					DEVESC_QUERYSIZE,
680 					sizeof( alQuery ),
681 					(PBYTE)pQuerySize,
682 					&nDrivDataSize,
683 					pDrivData );
684 	if ( DEV_OK != rc )
685 	{
686 		ImplFreePrnMemory( pCopyDrivData );
687 		return FALSE;
688 	}
689 
690 	// allocate the memory
691 	nAlloc = pQuerySize->ulSizeNeeded;
692 	pBuffer = (PBYTE)new BYTE[nAlloc];
693 
694 	// set up the input
695 	PDJP_ITEM pDJP = (PDJP_ITEM)pBuffer;
696 	ImplFormatInputList( pDJP, pQuerySize->aTuples );
697 
698 	rc = DevEscape( pOs2SalInfoPrinter->mhDC,
699 					DEVESC_QUERYJOBPROPERTIES,
700 					nAlloc,
701 					pBuffer,
702 					&nDrivDataSize,
703 					pDrivData );
704 	if ( (DEV_OK == rc) || (DEV_WARNING == rc) )
705 	{
706 		// aktuelle Setup-Daten uebernehmen
707 		ImplUpdateSetupData( pCopyDrivData, pSetupData );
708 
709 		// Loop through the query elements
710 		PQUERYTUPLE pTuple = pQuerySize->aTuples;
711 		while ( DJP_NONE != pTuple->ulProperty )
712 		{
713 			if ( pDJP->ulProperty == DJP_SJ_ORIENTATION )
714 			{
715 				if ( pDJP->ulNumReturned )
716 				{
717 					PDJPT_ORIENTATION pElm = DJP_ELEMENTP( *pDJP, DJPT_ORIENTATION );
718 					if ( (DJP_ORI_PORTRAIT == *pElm) || (DJP_ORI_REV_PORTRAIT == *pElm) )
719 						pSetupData->meOrientation = ORIENTATION_PORTRAIT;
720 					else
721 						pSetupData->meOrientation = ORIENTATION_LANDSCAPE;
722 				}
723 			}
724 			else if ( pDJP->ulProperty == DJP_CJ_FORM )
725 			{
726 				if ( pDJP->ulNumReturned )
727 				{
728 					PDJPT_FORM pElm = DJP_ELEMENTP( *pDJP, DJPT_FORM );
729 
730 					pSetupData->mnPaperWidth  = pElm->hcInfo.cx*100;
731 					pSetupData->mnPaperHeight = pElm->hcInfo.cy*100;
732 					switch( pElm->djppsFormID )
733 					{
734 						case DJP_PSI_A3:
735 							pSetupData->mePaperFormat = PAPER_A3;
736 							break;
737 
738 						case DJP_PSI_A4:
739 							pSetupData->mePaperFormat = PAPER_A4;
740 							break;
741 
742 						case DJP_PSI_A5:
743 							pSetupData->mePaperFormat = PAPER_A5;
744 							break;
745 
746 						case DJP_PSI_B4:
747 							pSetupData->mePaperFormat = PAPER_B4;
748 							break;
749 
750 						case DJP_PSI_B5:
751 							pSetupData->mePaperFormat = PAPER_B5;
752 							break;
753 
754 						case DJP_PSI_LETTER:
755 							pSetupData->mePaperFormat = PAPER_LETTER;
756 							break;
757 
758 						case DJP_PSI_LEGAL:
759 							pSetupData->mePaperFormat = PAPER_LEGAL;
760 							break;
761 
762 						case DJP_PSI_TABLOID:
763 							pSetupData->mePaperFormat = PAPER_TABLOID;
764 							break;
765 
766 						default:
767 							pSetupData->mePaperFormat = PAPER_USER;
768 							break;
769 					}
770 
771 					// Wir suchen zuerst ueber den Namen/Id und dann ueber die Id
772 					BOOL	bTrayFound = FALSE;
773 					USHORT	j;
774 					for ( j = 0; j < pOs2SalInfoPrinter->mnTrayCount; j++ )
775 					{
776 						if ( (pOs2SalInfoPrinter->mpTrayArray[j]->mnId == pElm->djpttTrayID) &&
777 							 (pOs2SalInfoPrinter->mpTrayArray[j]->maName == pElm->szTrayname) )
778 						{
779 							pSetupData->mnPaperBin = j;
780 							bTrayFound = TRUE;
781 							break;
782 						}
783 					}
784 					if ( !bTrayFound )
785 					{
786 						for ( j = 0; j < pOs2SalInfoPrinter->mnTrayCount; j++ )
787 						{
788 							if ( pOs2SalInfoPrinter->mpTrayArray[j]->mnId == pElm->djpttTrayID )
789 							{
790 								pSetupData->mnPaperBin = j;
791 								bTrayFound = TRUE;
792 								break;
793 							}
794 						}
795 					}
796 					// Wenn wir Ihn immer noch nicht gefunden haben, setzen
797 					// wir ihn auf DontKnow
798 					if ( !bTrayFound )
799 						pSetupData->mnPaperBin = 0xFFFF;
800 				}
801 			}
802 
803 			pDJP = DJP_NEXT_STRUCTP( pDJP );
804 			pTuple++;
805 		}
806 
807 		bResult = TRUE;
808 	}
809 	else
810 	{
811 		ImplFreePrnMemory( pCopyDrivData );
812 		bResult = FALSE;
813 	}
814 
815 	delete [] pBuffer;
816 
817 	return bResult;
818 }
819 
820 // -----------------------------------------------------------------------
821 
822 static BOOL ImplSetOrientation( HDC hPrinterDC, PDRIVDATA pDriverData,
823 								Orientation eOrientation )
824 {
825 	LONG alQuery[] =
826 	{
827 		0,						0,				// First two members of QUERYSIZE
828 		DJP_SJ_ORIENTATION, 	DJP_CURRENT,
829 		DJP_NONE,				DJP_NONE		// EOL marker
830 	};
831 
832 	APIRET		rc;
833 	PQUERYSIZE	pQuerySize		= (PQUERYSIZE)alQuery;
834 	PBYTE		pBuffer 		= NULL;
835 	LONG		nAlloc			= 0;
836 	LONG		nDrivDataSize	= pDriverData->cb;
837 
838 	// find out how many bytes to allocate
839 	pQuerySize->cb = sizeof( alQuery );
840 	rc = DevEscape( hPrinterDC,
841 					DEVESC_QUERYSIZE,
842 					sizeof( alQuery ),
843 					(PBYTE)pQuerySize,
844 					&nDrivDataSize,
845 					(PBYTE)pDriverData );
846 	if ( DEV_OK != rc )
847 		return FALSE;
848 
849 	// allocate the memory
850 	nAlloc = pQuerySize->ulSizeNeeded;
851 	pBuffer = (PBYTE)new BYTE[nAlloc];
852 
853 	// set up the input
854 	PDJP_ITEM pDJP = (PDJP_ITEM)pBuffer;
855 	ImplFormatInputList( pDJP, pQuerySize->aTuples );
856 
857 	pDJP->cb		 = sizeof( DJP_ITEM );
858 	pDJP->ulProperty = DJP_SJ_ORIENTATION;
859 	pDJP->lType 	 = DJP_CURRENT;
860 	pDJP->ulValue	 = (eOrientation == ORIENTATION_PORTRAIT)
861 						   ? DJP_ORI_PORTRAIT
862 						   : DJP_ORI_LANDSCAPE;
863 
864 	// do it!
865 	rc = DevEscape( hPrinterDC,
866 					DEVESC_SETJOBPROPERTIES,
867 					nAlloc,
868 					pBuffer,
869 					&nDrivDataSize,
870 					(PBYTE)pDriverData );
871 
872 	delete [] pBuffer;
873 
874 	return ((DEV_OK == rc) || (DEV_WARNING == rc));
875 }
876 
877 // -----------------------------------------------------------------------
878 
879 static BOOL ImplSetPaperSize( HDC hPrinterDC, PDRIVDATA pDriverData,
880 							  DJPT_PAPERSIZE nOS2PaperFormat )
881 {
882 	LONG alQuery[] =
883 	{
884 		0,						0,				// First two members of QUERYSIZE
885 		DJP_SJ_PAPERSIZE,		DJP_CURRENT,
886 		DJP_NONE,				DJP_NONE		// EOL marker
887 	};
888 
889 	APIRET		rc;
890 	PQUERYSIZE	pQuerySize		= (PQUERYSIZE)alQuery;
891 	PBYTE		pBuffer 		= NULL;
892 	LONG		nAlloc			= 0;
893 	LONG		nDrivDataSize	= pDriverData->cb;
894 
895 	// find out how many bytes to allocate
896 	pQuerySize->cb = sizeof( alQuery );
897 	rc = DevEscape( hPrinterDC,
898 					DEVESC_QUERYSIZE,
899 					sizeof( alQuery ),
900 					(PBYTE)pQuerySize,
901 					&nDrivDataSize,
902 					(PBYTE)pDriverData );
903 	if ( DEV_OK != rc )
904 		return FALSE;
905 
906 	// allocate the memory
907 	nAlloc = pQuerySize->ulSizeNeeded;
908 	pBuffer = (PBYTE)new BYTE[nAlloc];
909 
910 	// set up the input
911 	PDJP_ITEM pDJP = (PDJP_ITEM)pBuffer;
912 	PDJP_ITEM pStartDJP = pDJP;
913 	ImplFormatInputList( pDJP, pQuerySize->aTuples );
914 
915 	// Neue Daten zuweisen
916 	pDJP->cb		 = sizeof( DJP_ITEM );
917 	pDJP->ulProperty = DJP_SJ_PAPERSIZE;
918 	pDJP->lType 	 = DJP_CURRENT;
919 	pDJP->ulValue	 = nOS2PaperFormat;
920 
921 	// und setzen
922 	rc = DevEscape( hPrinterDC,
923 					DEVESC_SETJOBPROPERTIES,
924 					nAlloc,
925 					pBuffer,
926 					&nDrivDataSize,
927 					(PBYTE)pDriverData );
928 
929 	delete [] pBuffer;
930 
931 	return ((DEV_OK == rc) || (DEV_WARNING == rc));
932 }
933 
934 // -----------------------------------------------------------------------
935 
936 static BOOL ImplSetPaperBin( HDC hPrinterDC, PDRIVDATA pDriverData,
937 							 ImplTrayInfo* pTrayInfo )
938 {
939 	LONG alQuery[] =
940 	{
941 		0,						0,				// First two members of QUERYSIZE
942 		DJP_SJ_TRAYTYPE,		DJP_CURRENT,
943 		DJP_NONE,				DJP_NONE		// EOL marker
944 	};
945 
946 	APIRET		rc;
947 	PQUERYSIZE	pQuerySize		= (PQUERYSIZE)alQuery;
948 	PBYTE		pBuffer 		= NULL;
949 	LONG		nAlloc			= 0;
950 	LONG		nDrivDataSize	= pDriverData->cb;
951 
952 	// find out how many bytes to allocate
953 	pQuerySize->cb = sizeof( alQuery );
954 	rc = DevEscape( hPrinterDC,
955 					DEVESC_QUERYSIZE,
956 					sizeof( alQuery ),
957 					(PBYTE)pQuerySize,
958 					&nDrivDataSize,
959 					(PBYTE)pDriverData );
960 	if ( DEV_OK != rc )
961 		return FALSE;
962 
963 	// allocate the memory
964 	nAlloc = pQuerySize->ulSizeNeeded;
965 	pBuffer = (PBYTE)new BYTE[nAlloc];
966 
967 	// set up the input
968 	PDJP_ITEM pDJP = (PDJP_ITEM)pBuffer;
969 	ImplFormatInputList( pDJP, pQuerySize->aTuples );
970 
971 	// Neue Daten zuweisen
972 	pDJP->cb		 = sizeof( DJP_ITEM );
973 	pDJP->ulProperty = DJP_SJ_TRAYTYPE;
974 	pDJP->lType 	 = DJP_CURRENT;
975 	pDJP->ulValue	 = pTrayInfo->mnId;
976 
977 	// und setzen
978 	rc = DevEscape( hPrinterDC,
979 					DEVESC_SETJOBPROPERTIES,
980 					nAlloc,
981 					pBuffer,
982 					&nDrivDataSize,
983 					(PBYTE)pDriverData );
984 
985 	delete [] pBuffer;
986 
987 	return ((DEV_OK == rc) || (DEV_WARNING == rc));
988 }
989 
990 // =======================================================================
991 
992 static BOOL ImplSalCreateInfoPrn( Os2SalInfoPrinter* pPrinter, PDRIVDATA pDriverData,
993 								  HDC& rDC, HPS& rPS )
994 {
995 	SalData* pSalData = GetSalData();
996 
997 	// create info context
998 	DEVOPENSTRUC  devOpenStruc;
999 	memset( &devOpenStruc, 0, sizeof( devOpenStruc ) );
1000 	devOpenStruc.pszLogAddress		= (char*)pPrinter->maName.GetBuffer();
1001 	devOpenStruc.pszDriverName		= (char*)pPrinter->maDriverName.GetBuffer();
1002 	devOpenStruc.pdriv				= pDriverData;
1003 	devOpenStruc.pszDataType		= "PM_Q_STD";
1004 
1005 	HDC hDC = DevOpenDC( pSalData->mhAB, OD_INFO, "*",
1006 						 4, (PDEVOPENDATA)&devOpenStruc, (HDC)NULL);
1007 	if ( !hDC )
1008 		return FALSE;
1009 
1010 	// create presentation space
1011 	SIZEL sizel;
1012 	sizel.cx = 0;
1013 	sizel.cy = 0;
1014 	HPS hPS = Ft2CreatePS( pSalData->mhAB, hDC, &sizel, GPIA_ASSOC | GPIT_MICRO | PU_PELS );
1015 	if ( !hPS )
1016 	{
1017 		DevCloseDC( hDC );
1018 		return FALSE;
1019 	}
1020 
1021 	rDC = hDC;
1022 	rPS = hPS;
1023 	return TRUE;
1024 }
1025 
1026 // -----------------------------------------------------------------------
1027 
1028 static void ImplSalDestroyInfoPrn( Os2SalInfoPrinter* pPrinter )
1029 {
1030 	ImplSalDeInitGraphics( pPrinter->mpGraphics);
1031 	Ft2Associate( pPrinter->mhPS, 0 );
1032 	Ft2DestroyPS( pPrinter->mhPS );
1033 	DevCloseDC( pPrinter->mhDC );
1034 }
1035 
1036 // =======================================================================
1037 
1038 SalInfoPrinter* Os2SalInstance::CreateInfoPrinter( SalPrinterQueueInfo* pQueueInfo,
1039 												ImplJobSetup* pSetupData )
1040 {
1041 	ImplQueueSalSysData* pSysQueueData = (ImplQueueSalSysData*)(pQueueInfo->mpSysData);
1042 	Os2SalInfoPrinter* pPrinter = new Os2SalInfoPrinter;
1043 	pPrinter->maPrinterName	= pSysQueueData->maPrinterName;
1044 	pPrinter->maName			= pSysQueueData->maName;
1045 	pPrinter->maDriverName	= pSysQueueData->maDriverName;
1046 	pPrinter->maDeviceName	= pSysQueueData->maDeviceName;
1047 
1048 	// Nur Setup-Daten uebernehmen, wenn Treiber und Laenge der Treiberdaten
1049 	// uebereinstimmt
1050 	PDRIVDATA	pDriverData;
1051 	BOOL		bUpdateDriverData;
1052 	if ( pSetupData->mpDriverData && pSysQueueData->mpDrivData &&
1053 		 (pSetupData->mnSystem == JOBSETUP_SYSTEM_OS2) &&
1054 		 (pSetupData->mnDriverDataLen == pSysQueueData->mpDrivData->cb) &&
1055 		 (strcmp( ((PDRIVDATA)pSetupData->mpDriverData)->szDeviceName,
1056 				  pSysQueueData->mpDrivData->szDeviceName ) == 0) )
1057 	{
1058 		pDriverData = PDRIVDATA( pSetupData->mpDriverData );
1059 		bUpdateDriverData = FALSE;
1060 	}
1061 	else
1062 	{
1063 		pDriverData = pSysQueueData->mpDrivData;
1064 		bUpdateDriverData = TRUE;
1065 	}
1066 	if ( pDriverData )
1067 		pPrinter->maJobSetupDeviceName = pDriverData->szDeviceName;
1068 
1069 	if ( !ImplSalCreateInfoPrn( pPrinter, pDriverData,
1070 								pPrinter->mhDC,
1071 								pPrinter->mhPS ) )
1072 	{
1073 		delete pPrinter;
1074 		return NULL;
1075 	}
1076 
1077 	// create graphics object for output
1078 	Os2SalGraphics* pGraphics = new Os2SalGraphics;
1079 	pGraphics->mhDC				= pPrinter->mhDC;
1080 	pGraphics->mhPS				= pPrinter->mhPS;
1081 	pGraphics->mhWnd 			= 0;
1082 	pGraphics->mbPrinter 		= TRUE;
1083 	pGraphics->mbVirDev			= FALSE;
1084 	pGraphics->mbWindow			= FALSE;
1085 	pGraphics->mbScreen			= FALSE;
1086 
1087 	ImplSalInitGraphics( pGraphics );
1088 	pPrinter->mpGraphics			= pGraphics;
1089 
1090 	// check printer driver for DJP support
1091 	pPrinter->mbDJPSupported = ImplIsDriverDJPEnabled( pPrinter->mhDC );
1092 
1093 	if ( bUpdateDriverData )
1094 	{
1095 		if ( pSetupData->mpDriverData )
1096 			rtl_freeMemory( pSetupData->mpDriverData);
1097 		pSetupData->mpDriverData = (BYTE*)rtl_allocateMemory( pDriverData->cb);
1098 		memcpy( pSetupData->mpDriverData, pDriverData, pDriverData->cb );
1099 		pSetupData->mnDriverDataLen = pDriverData->cb;
1100 	}
1101 
1102 	// retrieve current settings from printer driver and store them to system independend data!
1103 	if ( pPrinter->mbDJPSupported )
1104 		ImplGetCurrentSettings( pPrinter, pSetupData );
1105 	pSetupData->mnSystem = JOBSETUP_SYSTEM_OS2;
1106 
1107 	return pPrinter;
1108 }
1109 
1110 // -----------------------------------------------------------------------
1111 
1112 void Os2SalInstance::DestroyInfoPrinter( SalInfoPrinter* pPrinter )
1113 {
1114 	delete pPrinter;
1115 }
1116 
1117 // =======================================================================
1118 
1119 Os2SalInfoPrinter::Os2SalInfoPrinter()
1120 {
1121 	mhDC					= 0;
1122 	mhPS					= 0;
1123 	mpGraphics			= NULL;
1124 	mbGraphics			= FALSE;
1125 	mbDJPSupported		= FALSE;
1126 	mnFormCount			= 0;
1127 	mpFormArray			= NULL;
1128 	mnTrayCount			= 0;
1129 	mpTrayArray			= NULL;
1130 }
1131 
1132 // -----------------------------------------------------------------------
1133 
1134 Os2SalInfoPrinter::~Os2SalInfoPrinter()
1135 {
1136 	if ( mpGraphics )
1137 	{
1138 		ImplSalDestroyInfoPrn( this );
1139 		delete mpGraphics;
1140 	}
1141 
1142 	ImplFreeFormAndTrayList( this );
1143 }
1144 
1145 // -----------------------------------------------------------------------
1146 
1147 SalGraphics* Os2SalInfoPrinter::GetGraphics()
1148 {
1149 	if ( mbGraphics )
1150 		return NULL;
1151 
1152 	if ( mpGraphics )
1153 		mbGraphics = TRUE;
1154 
1155 	return mpGraphics;
1156 }
1157 
1158 // -----------------------------------------------------------------------
1159 
1160 void Os2SalInfoPrinter::ReleaseGraphics( SalGraphics* )
1161 {
1162 	mbGraphics = FALSE;
1163 }
1164 
1165 // -----------------------------------------------------------------------
1166 
1167 BOOL Os2SalInfoPrinter::Setup( SalFrame* pFrame, ImplJobSetup* pSetupData )
1168 {
1169 	PDRIVDATA pDrivData = ImplPrnDrivData( pSetupData );
1170 	if ( !pDrivData )
1171 		return FALSE;
1172 
1173 	APIRET rc = DevPostDeviceModes( GetSalData()->mhAB, pDrivData,
1174 									maDriverName.GetBuffer(),
1175 									maDeviceName.GetBuffer(),
1176 									maPrinterName.GetBuffer(),
1177 									DPDM_POSTJOBPROP );
1178 	if ( rc == DEV_OK )
1179 	{
1180 		ImplUpdateSetupData( pDrivData, pSetupData );
1181 
1182 		// update DC and PS
1183 		HDC hDC;
1184 		HPS hPS;
1185 		if ( !ImplSalCreateInfoPrn( this, (PDRIVDATA)(pSetupData->mpDriverData), hDC, hPS ) )
1186 			return FALSE;
1187 
1188 		// Alten Printer DC/PS zerstoeren
1189 		ImplSalDestroyInfoPrn( this );
1190 
1191 		// Neue Daten setzen und initialisieren
1192 		mhDC = hDC;
1193 		mhPS = hPS;
1194 		mpGraphics->mhDC = mhDC;
1195 		mpGraphics->mhPS = mhPS;
1196 		ImplSalInitGraphics( mpGraphics );
1197 
1198 		// retrieve current settings from printer driver and store them to system independend data!
1199 		ImplFreeFormAndTrayList( this );
1200 		if ( mbDJPSupported )
1201 			ImplGetCurrentSettings( this, pSetupData );
1202 
1203 		return TRUE;
1204 	}
1205 	else
1206 	{
1207 		ImplFreePrnMemory( pDrivData );
1208 		return FALSE;
1209 	}
1210 }
1211 
1212 // -----------------------------------------------------------------------
1213 
1214 BOOL Os2SalInfoPrinter::SetPrinterData( ImplJobSetup* pSetupData )
1215 {
1216 	// Wir koennen nur Treiberdaten von OS2 setzen
1217 	if ( pSetupData->mnSystem != JOBSETUP_SYSTEM_OS2 )
1218 		return FALSE;
1219 
1220 	PDRIVDATA pNewDrivData = (PDRIVDATA)(pSetupData->mpDriverData);
1221 	if ( !pNewDrivData )
1222 		return FALSE;
1223 
1224 	// Testen, ob Printerdaten fuer den gleichen Printer uebergeben werden,
1225 	// da einige Treiber zu Abstuerzen neigen, wenn Daten von einem anderen
1226 	// Printer gesetzt werden
1227 	if ( !maJobSetupDeviceName.Equals( pNewDrivData->szDeviceName ))
1228 		return FALSE;
1229 
1230 	// update DC and PS
1231 	HDC hDC;
1232 	HPS hPS;
1233 	if ( !ImplSalCreateInfoPrn( this, pNewDrivData, hDC, hPS ) )
1234 		return FALSE;
1235 
1236 	// Alten Printer DC/PS zerstoeren
1237 	ImplSalDestroyInfoPrn( this );
1238 
1239 	// Neue Daten setzen und initialisieren
1240 	mhDC = hDC;
1241 	mhPS = hPS;
1242 	mpGraphics->mhDC = mhDC;
1243 	mpGraphics->mhPS = mhPS;
1244 	ImplSalInitGraphics( mpGraphics );
1245 
1246 	// retrieve current settings from printer driver and store them to system independend data!
1247 	ImplFreeFormAndTrayList( this );
1248 	if ( mbDJPSupported )
1249 		ImplGetCurrentSettings( this, pSetupData );
1250 
1251 	return TRUE;
1252 }
1253 
1254 // -----------------------------------------------------------------------
1255 
1256 BOOL Os2SalInfoPrinter::SetData( ULONG nFlags, ImplJobSetup* pSetupData )
1257 {
1258 	// needs DJP support
1259 	if ( !mbDJPSupported )
1260 		return FALSE;
1261 
1262 	PDRIVDATA pDrivData = ImplPrnDrivData( pSetupData );
1263 
1264 	if ( !pDrivData )
1265 		return FALSE;
1266 
1267 	BOOL bOK = FALSE;
1268 
1269 	// set orientation
1270 	if ( nFlags & SAL_JOBSET_ORIENTATION )
1271 	{
1272 		if ( ImplSetOrientation( mhDC, pDrivData, pSetupData->meOrientation ) )
1273 			bOK = TRUE;
1274 	}
1275 
1276 	// set paper size
1277 	if ( nFlags & SAL_JOBSET_PAPERSIZE )
1278 	{
1279 		// Papierformat ermitteln
1280 		DJPT_PAPERSIZE nOS2PaperFormat;
1281 		switch ( pSetupData->mePaperFormat )
1282 		{
1283 			case PAPER_A3:
1284 				nOS2PaperFormat = DJP_PSI_A3;
1285 				break;
1286 
1287 			case PAPER_A4:
1288 				nOS2PaperFormat = DJP_PSI_A4;
1289 				break;
1290 
1291 			case PAPER_A5:
1292 				nOS2PaperFormat = DJP_PSI_A5;
1293 				break;
1294 
1295 			case PAPER_B4:
1296 				nOS2PaperFormat = DJP_PSI_B4;
1297 				break;
1298 
1299 			case PAPER_B5:
1300 				nOS2PaperFormat = DJP_PSI_B5;
1301 				break;
1302 
1303 			case PAPER_LETTER:
1304 				nOS2PaperFormat = DJP_PSI_LETTER;
1305 				break;
1306 
1307 			case PAPER_LEGAL:
1308 				nOS2PaperFormat = DJP_PSI_LEGAL;
1309 				break;
1310 
1311 			case PAPER_TABLOID:
1312 				nOS2PaperFormat = DJP_PSI_TABLOID;
1313 				break;
1314 
1315 			default:
1316 				{
1317 				nOS2PaperFormat = DJP_PSI_NONE;
1318 				// OS2 rechnet in Millimetern
1319 				long nPaperWidth	 = pSetupData->mnPaperWidth  / 100;
1320 				long nPaperHeight	 = pSetupData->mnPaperHeight / 100;
1321 				// Ansonsten ueber die Papiergroesse suchen
1322 				for( int i = 0; i < mnFormCount; i++ )
1323 				{
1324 					ImplFormInfo* pFormInfo = mpFormArray[i];
1325 					if ( ImplPaperSizeEqual( nPaperWidth, nPaperHeight,
1326 											 pFormInfo->mnPaperWidth, pFormInfo->mnPaperHeight ) )
1327 					{
1328 						nOS2PaperFormat = pFormInfo->mnId;
1329 						break;
1330 					}
1331 				}
1332 				}
1333 				break;
1334 		}
1335 
1336 		if ( nOS2PaperFormat != DJP_PSI_NONE )
1337 		{
1338 			if ( ImplSetPaperSize( mhDC, pDrivData, nOS2PaperFormat ) )
1339 				bOK = TRUE;
1340 		}
1341 	}
1342 
1343 	// set paper tray
1344 	if ( (nFlags & SAL_JOBSET_PAPERBIN) && (pSetupData->mnPaperBin < mnTrayCount) )
1345 	{
1346 		if ( ImplSetPaperBin( mhDC, pDrivData,
1347 							  mpTrayArray[pSetupData->mnPaperBin] ) )
1348 			bOK = TRUE;
1349 	}
1350 
1351 	if ( bOK )
1352 	{
1353 		ImplUpdateSetupData( pDrivData, pSetupData );
1354 
1355 		// query current driver settings
1356 		ImplFreeFormAndTrayList( this );
1357 		if ( ImplGetCurrentSettings( this, pSetupData ) )
1358 		{
1359 			// update DC and PS
1360 			HDC hDC;
1361 			HPS hPS;
1362 			if ( ImplSalCreateInfoPrn( this, (PDRIVDATA)(pSetupData->mpDriverData), hDC, hPS ) )
1363 			{
1364 				// Alten Printer DC/PS zerstoeren
1365 				ImplSalDestroyInfoPrn( this );
1366 
1367 				// Neue Daten setzen und initialisieren
1368 				mhDC = hDC;
1369 				mhPS = hPS;
1370 				mpGraphics->mhDC = mhDC;
1371 				mpGraphics->mhPS = mhPS;
1372 				ImplSalInitGraphics( mpGraphics );
1373 			}
1374 			else
1375 				bOK = FALSE;
1376 		}
1377 		else
1378 			bOK = FALSE;
1379 	}
1380 
1381 	return bOK;
1382 }
1383 
1384 // -----------------------------------------------------------------------
1385 
1386 ULONG Os2SalInfoPrinter::GetPaperBinCount( const ImplJobSetup* pJobSetup )
1387 {
1388 	if ( !mbDJPSupported )
1389 		return 1;
1390 
1391 	// init paperbinlist if empty
1392 	if ( !mnTrayCount )
1393 		ImplGetFormAndTrayList( this, pJobSetup );
1394 
1395 	// Wir haben immer einen PaperTray und wenn, das eben einen ohne
1396 	// Namen
1397 	if ( !mnTrayCount )
1398 		return 1;
1399 	else
1400 		return mnTrayCount;
1401 }
1402 
1403 // -----------------------------------------------------------------------
1404 
1405 XubString Os2SalInfoPrinter::GetPaperBinName( const ImplJobSetup* pJobSetup,
1406 										  ULONG nPaperBin )
1407 {
1408 	XubString aPaperBinName;
1409 
1410 	if ( mbDJPSupported )
1411 	{
1412 		// init paperbinlist if empty
1413 		if ( !mnTrayCount )
1414 			ImplGetFormAndTrayList( this, pJobSetup );
1415 
1416 		if ( nPaperBin < mnTrayCount )
1417 			aPaperBinName = ::rtl::OStringToOUString (mpTrayArray[nPaperBin]->maDisplayName, gsl_getSystemTextEncoding());
1418 	}
1419 
1420 	return aPaperBinName;
1421 }
1422 
1423 // -----------------------------------------------------------------------
1424 
1425 ULONG Os2SalInfoPrinter::GetCapabilities( const ImplJobSetup*, USHORT nType )
1426 {
1427 	switch ( nType )
1428 	{
1429 		case PRINTER_CAPABILITIES_SUPPORTDIALOG:
1430 			return TRUE;
1431 		case PRINTER_CAPABILITIES_COPIES:
1432 			return 0xFFFF;
1433 		case PRINTER_CAPABILITIES_COLLATECOPIES:
1434 			return 0;
1435 		case PRINTER_CAPABILITIES_SETORIENTATION:
1436 		case PRINTER_CAPABILITIES_SETPAPERBIN:
1437 		case PRINTER_CAPABILITIES_SETPAPERSIZE:
1438 		case PRINTER_CAPABILITIES_SETPAPER:
1439 			return mbDJPSupported;
1440 	}
1441 
1442 	return 0;
1443 }
1444 
1445 // -----------------------------------------------------------------------
1446 
1447 void Os2SalInfoPrinter::GetPageInfo( const ImplJobSetup*,
1448 								  long& rOutWidth, long& rOutHeight,
1449 								  long& rPageOffX, long& rPageOffY,
1450 								  long& rPageWidth, long& rPageHeight )
1451 {
1452 	HDC hDC = mhDC;
1453 
1454 	// search current form
1455 	HCINFO	aInfo;
1456 	int nForms = DevQueryHardcopyCaps( hDC, 0, 0, &aInfo );
1457 	for( int i = 0; i < nForms; i++ )
1458 	{
1459 		if ( DevQueryHardcopyCaps( hDC, i, 1, &aInfo ) >= 0 )
1460 		{
1461 			if ( aInfo.flAttributes & HCAPS_CURRENT )
1462 			{
1463 				// query resolution
1464 				long nXResolution;
1465 				long nYResolution;
1466 				DevQueryCaps( hDC, CAPS_HORIZONTAL_RESOLUTION, 1, &nXResolution );
1467 				DevQueryCaps( hDC, CAPS_VERTICAL_RESOLUTION, 1, &nYResolution );
1468 				rPageOffX	= aInfo.xLeftClip * nXResolution / 1000;
1469 				rPageOffY	= (aInfo.cy-aInfo.yTopClip) * nYResolution / 1000;
1470 				rPageWidth	= aInfo.cx * nXResolution / 1000;
1471 				rPageHeight = aInfo.cy * nYResolution / 1000;
1472 				rOutWidth	= aInfo.xPels;
1473 				rOutHeight	= aInfo.yPels;
1474 				return;
1475 			}
1476 		}
1477 	}
1478 
1479 	// use device caps if no form selected/found
1480 	long lCapsWidth = 0;
1481 	long lCapsHeight = 0;
1482 	DevQueryCaps( hDC, CAPS_WIDTH, 1L, &lCapsWidth );
1483 	DevQueryCaps( hDC, CAPS_HEIGHT, 1L, &lCapsHeight );
1484 	rPageOffX	 = 0;
1485 	rPageOffY	 = 0;
1486 	rOutWidth	 = lCapsWidth;
1487 	rOutHeight	 = lCapsHeight;
1488 	rPageWidth	 = rOutWidth;
1489 	rPageHeight  = rOutHeight;
1490 }
1491 
1492 // =======================================================================
1493 
1494 static BOOL ImplIsDriverPrintDJPEnabled( HDC hDC )
1495 {
1496 #ifdef NO_DJP
1497 	return FALSE;
1498 #else
1499 	// Ueber OS2-Ini kann DJP disablte werden
1500 	if ( !PrfQueryProfileInt( HINI_PROFILE, SAL_PROFILE_APPNAME, SAL_PROFILE_PRINTDJP, 1 ) )
1501 		return FALSE;
1502 
1503 	// Testen, ob DJP-Interface am Drucker vorhanden
1504 	LONG   lQuery;
1505 	APIRET rc;
1506 
1507 	lQuery = DEVESC_QUERYSIZE;
1508 	rc = DevEscape( hDC,
1509 					DEVESC_QUERYESCSUPPORT,
1510 					sizeof( lQuery ),
1511 					(PBYTE)&lQuery,
1512 					0,
1513 					(PBYTE)NULL );
1514 	if ( DEV_OK != rc )
1515 		return FALSE;
1516 
1517 	return TRUE;
1518 #endif
1519 }
1520 
1521 // =======================================================================
1522 
1523 SalPrinter* Os2SalInstance::CreatePrinter( SalInfoPrinter* pInfoPrinter )
1524 {
1525 	Os2SalPrinter* pPrinter = new Os2SalPrinter;
1526 	pPrinter->mpInfoPrinter = static_cast<Os2SalInfoPrinter*>(pInfoPrinter);
1527 	return pPrinter;
1528 }
1529 
1530 // -----------------------------------------------------------------------
1531 
1532 void Os2SalInstance::DestroyPrinter( SalPrinter* pPrinter )
1533 {
1534 	delete pPrinter;
1535 }
1536 
1537 // =======================================================================
1538 
1539 Os2SalPrinter::Os2SalPrinter()
1540 {
1541 	mhDC					= 0;
1542 	mhPS					= 0;
1543 	mpGraphics			= NULL;
1544 	mbAbort				= FALSE;
1545 	mbPrintDJPSupported	= FALSE;
1546 }
1547 
1548 // -----------------------------------------------------------------------
1549 
1550 Os2SalPrinter::~Os2SalPrinter()
1551 {
1552 }
1553 
1554 // -----------------------------------------------------------------------
1555 
1556 BOOL Os2SalPrinter::StartJob( const XubString* pFileName,
1557 						   const XubString& rJobName,
1558 						   const XubString& rAppName,
1559 						   ULONG nCopies,
1560                            bool bCollate,
1561                            bool bDirect,
1562 						   ImplJobSetup* pSetupData )
1563 {
1564 	DEVOPENSTRUC	aDevOpenStruc;
1565 	LONG			lType;
1566 	APIRET			rc;
1567 
1568 	// prepare queue information
1569 	memset( &aDevOpenStruc, 0, sizeof( aDevOpenStruc ) );
1570 	aDevOpenStruc.pszDriverName = (PSZ)(mpInfoPrinter->maDriverName.GetBuffer());
1571 
1572 	// print into file?
1573 	if ( pFileName )
1574 	{
1575 		aDevOpenStruc.pszLogAddress = (PSZ)pFileName->GetBuffer();
1576 		aDevOpenStruc.pszDataType = "PM_Q_RAW";
1577 		lType = OD_DIRECT;
1578 	}
1579 	else
1580 	{
1581 		aDevOpenStruc.pszLogAddress = (PSZ)(mpInfoPrinter->maName.GetBuffer());
1582 		if ( PrfQueryProfileInt( HINI_PROFILE, SAL_PROFILE_APPNAME, SAL_PROFILE_PRINTRAW, 0 ) )
1583 			aDevOpenStruc.pszDataType = "PM_Q_RAW";
1584 		else
1585 			aDevOpenStruc.pszDataType = "PM_Q_STD";
1586 		lType = OD_QUEUED;
1587 	}
1588 
1589 #if 0 // YD FIXME
1590 	// Set comment (AppName nur bis zum 1. Space-Zeichen nehmen)
1591 	const xub_Unicode*	pComment = rAppName;
1592 	USHORT			nCommentLen = 0;
1593 	memset( maCommentBuf, 0, sizeof( maCommentBuf ) );
1594 	while ( (nCommentLen < 32) &&
1595 			(((*pComment >= 'a') && (*pComment <= 'z')) ||
1596 			 ((*pComment >= 'A') && (*pComment <= 'Z')) ||
1597 			 ((*pComment >= '0') && (*pComment <= '9')) ||
1598 			 (*pComment == '-')))
1599 	{
1600 		maCommentBuf[nCommentLen] = (char)(*pComment);
1601 		nCommentLen++;
1602 		pComment++;
1603 	}
1604 	aDevOpenStruc.pszComment = (PSZ)maCommentBuf;
1605 #endif
1606 	ByteString jobName( rJobName, gsl_getSystemTextEncoding());
1607 	aDevOpenStruc.pszComment = (PSZ)jobName.GetBuffer();
1608 
1609 	// Kopien
1610 	if ( nCopies > 1 )
1611 	{
1612 		// OS2 kann maximal 999 Kopien
1613 		if ( nCopies > 999 )
1614 			nCopies = 999;
1615 		sprintf( maCopyBuf, "COP=%d", nCopies);
1616 		aDevOpenStruc.pszQueueProcParams = (PSZ)maCopyBuf;
1617 	}
1618 
1619 	// open device context
1620 	SalData*	pSalData = GetSalData();
1621 	HAB 		hAB = pSalData->mhAB;
1622 	aDevOpenStruc.pdriv = (PDRIVDATA)pSetupData->mpDriverData;
1623 	mhDC = DevOpenDC( hAB,
1624 									lType,
1625 									"*",
1626 									7,
1627 									(PDEVOPENDATA)&aDevOpenStruc,
1628 									0 );
1629 	if ( mhDC == 0 )
1630 	{
1631 		ERRORID nLastError = WinGetLastError( hAB );
1632 		if ( (nLastError & 0xFFFF) == PMERR_SPL_PRINT_ABORT )
1633 			mnError = SAL_PRINTER_ERROR_ABORT;
1634 		else
1635 			mnError = SAL_PRINTER_ERROR_GENERALERROR;
1636 		return FALSE;
1637 	}
1638 
1639 	// open presentation space
1640 	SIZEL sizel;
1641 	sizel.cx = 0;
1642 	sizel.cy = 0;
1643 	mhPS = Ft2CreatePS( hAB, mhDC, &sizel, GPIA_ASSOC | GPIT_MICRO | PU_PELS );
1644 	if ( !mhPS )
1645 	{
1646 		DevCloseDC( mhDC );
1647 		mnError = SAL_PRINTER_ERROR_GENERALERROR;
1648 		return NULL;
1649 	}
1650 
1651 	// Can we print with DJP
1652 	mbPrintDJPSupported = ImplIsDriverPrintDJPEnabled( mhDC );
1653 
1654 	// JobName ermitteln und Job starten
1655 	PSZ pszJobName = NULL;
1656 	int nJobNameLen = 0;
1657 	if ( jobName.Len() > 0 )
1658 	{
1659 		pszJobName = (PSZ)jobName.GetBuffer();
1660 		nJobNameLen = jobName.Len();
1661 	}
1662 	rc = DevEscape( mhDC,
1663 					DEVESC_STARTDOC,
1664 					nJobNameLen, (PBYTE)pszJobName,
1665 					0, (PBYTE)NULL );
1666 
1667 	if ( rc != DEV_OK )
1668 	{
1669 		ERRORID nLastError = WinGetLastError( hAB );
1670 		if ( (nLastError & 0xFFFF) == PMERR_SPL_PRINT_ABORT )
1671 			mnError = SAL_PRINTER_ERROR_ABORT;
1672 		else
1673 			mnError = SAL_PRINTER_ERROR_GENERALERROR;
1674 		Ft2Associate( mhPS, NULL );
1675 		Ft2DestroyPS( mhPS );
1676 		DevCloseDC( mhDC );
1677 		return FALSE;
1678 	}
1679 
1680 	// init for first page
1681 	mbFirstPage = TRUE;
1682 	mnError = 0;
1683 
1684 	return TRUE;
1685 }
1686 
1687 // -----------------------------------------------------------------------
1688 
1689 BOOL Os2SalPrinter::EndJob()
1690 {
1691 	APIRET rc;
1692 	rc = DevEscape( mhDC,
1693 					DEVESC_ENDDOC,
1694 					0, NULL,
1695 					0, NULL);
1696 
1697 	// destroy presentation space and device context
1698 	Ft2Associate( mhPS, NULL );
1699 	Ft2DestroyPS( mhPS );
1700 	DevCloseDC( mhDC );
1701 	return TRUE;
1702 }
1703 
1704 // -----------------------------------------------------------------------
1705 
1706 BOOL Os2SalPrinter::AbortJob()
1707 {
1708 	APIRET rc;
1709 
1710 	rc = DevEscape( mhDC,
1711 					DEVESC_ABORTDOC,
1712 					0, NULL,
1713 					0, NULL );
1714 
1715 	// destroy SalGraphics
1716 	if ( mpGraphics )
1717 	{
1718 		ImplSalDeInitGraphics( mpGraphics );
1719 		delete mpGraphics;
1720 		mpGraphics = NULL;
1721 	}
1722 
1723 	// destroy presentation space and device context
1724 	Ft2Associate( mhPS, NULL );
1725 	Ft2DestroyPS( mhPS );
1726 	DevCloseDC( mhDC );
1727 	return TRUE;
1728 }
1729 
1730 // -----------------------------------------------------------------------
1731 
1732 SalGraphics* Os2SalPrinter::StartPage( ImplJobSetup* pSetupData, BOOL bNewJobSetup )
1733 {
1734 	APIRET rc;
1735 
1736 	if ( mbFirstPage )
1737 		mbFirstPage = FALSE;
1738 	else
1739 	{
1740 		PBYTE	pJobData;
1741 		LONG	nJobDataSize;
1742 		LONG	nEscape;
1743 		if ( mbPrintDJPSupported && bNewJobSetup )
1744 		{
1745 			nEscape 		= DEVESC_NEWFRAME_WPROP;
1746 			nJobDataSize	= ((PDRIVDATA)(pSetupData->mpDriverData))->cb;
1747 			pJobData		= (PBYTE)(pSetupData->mpDriverData);
1748 		}
1749 		else
1750 		{
1751 			nEscape 		= DEVESC_NEWFRAME;
1752 			nJobDataSize	= 0;
1753 			pJobData		= NULL;
1754 		}
1755 		rc = DevEscape( mhDC,
1756 						nEscape,
1757 						0, NULL,
1758 						&nJobDataSize, pJobData );
1759 
1760 		if ( rc != DEV_OK )
1761 		{
1762 			DevEscape( mhDC, DEVESC_ENDDOC, 0, NULL, 0, NULL);
1763 			Ft2Associate( mhPS, NULL );
1764 			Ft2DestroyPS( mhPS );
1765 			DevCloseDC( mhDC );
1766 			mnError = SAL_PRINTER_ERROR_GENERALERROR;
1767 			return NULL;
1768 		}
1769 	}
1770 
1771 	// create SalGraphics with copy of hPS
1772 	Os2SalGraphics* pGraphics = new Os2SalGraphics;
1773 	pGraphics->mhDC				= mhDC;
1774 	pGraphics->mhPS				= mhPS;
1775 	pGraphics->mhWnd 			= 0;
1776 	pGraphics->mbPrinter 		= TRUE;
1777 	pGraphics->mbVirDev			= FALSE;
1778 	pGraphics->mbWindow			= FALSE;
1779 	pGraphics->mbScreen			= FALSE;
1780 	pGraphics->mnHeight			= 0;
1781 	// search current form for actual page height
1782 	HCINFO	aInfo;
1783 	int 	nForms = DevQueryHardcopyCaps( mhDC, 0, 0, &aInfo );
1784 	for( int i = 0; i < nForms; i++ )
1785 	{
1786 		if ( DevQueryHardcopyCaps( mhDC, i, 1, &aInfo ) >= 0 )
1787 		{
1788 			if ( aInfo.flAttributes & HCAPS_CURRENT )
1789 				pGraphics->mnHeight	= aInfo.yPels;
1790 		}
1791 	}
1792 	// use device caps if no form selected/found
1793 	if ( !pGraphics->mnHeight )
1794 		DevQueryCaps( mhDC, CAPS_HEIGHT, 1L, &pGraphics->mnHeight );
1795 
1796 	ImplSalInitGraphics( pGraphics );
1797 	mpGraphics = pGraphics;
1798 
1799 	return pGraphics;
1800 }
1801 
1802 // -----------------------------------------------------------------------
1803 
1804 BOOL Os2SalPrinter::EndPage()
1805 {
1806 	if ( mpGraphics )
1807 	{
1808 		// destroy SalGraphics
1809 		ImplSalDeInitGraphics( mpGraphics );
1810 		delete mpGraphics;
1811 		mpGraphics = NULL;
1812 	}
1813 
1814 	return TRUE;
1815 }
1816 
1817 // -----------------------------------------------------------------------
1818 
1819 ULONG Os2SalPrinter::GetErrorCode()
1820 {
1821 	return mnError;
1822 }
1823 
1824 void Os2SalInfoPrinter::InitPaperFormats( const ImplJobSetup* pSetupData )
1825 {
1826 	printf("Os2SalInfoPrinter::InitPaperFormats\n");
1827 }
1828 int Os2SalInfoPrinter::GetLandscapeAngle( const ImplJobSetup* pSetupData )
1829 {
1830 	printf("Os2SalInfoPrinter::GetLandscapeAngle\n");
1831 	return 0;
1832 }
1833 
1834