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