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