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