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