- Added/fixed some documentation reported by winapi_check
[wine] / graphics / win16drv / prtdrv.c
1 /*
2  * Windows Device Context initialisation functions
3  *
4  * Copyright 1996,1997 John Harvey
5  */
6
7 #include <stdlib.h>
8 #include <string.h>
9 #include <sys/types.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12 #include <errno.h>
13 #include "wine/winbase16.h"
14 #include "win16drv.h"
15 #include "heap.h"
16 #include "brush.h"
17 #include "callback.h"
18 #include "debugtools.h"
19 #include "bitmap.h"
20 #include "pen.h"
21
22 DEFAULT_DEBUG_CHANNEL(win16drv)
23
24 /* ### start build ### */
25 extern WORD CALLBACK PRTDRV_CallTo16_word_lwll (FARPROC16,LONG,WORD,LONG,LONG);
26 extern WORD CALLBACK PRTDRV_CallTo16_word_lwlll (FARPROC16,LONG,WORD,LONG,LONG,
27                                                  LONG);
28 extern WORD CALLBACK PRTDRV_CallTo16_word_llll (FARPROC16,LONG,LONG,LONG,LONG);
29 extern WORD CALLBACK PRTDRV_CallTo16_word_lwwlllll (FARPROC16,LONG,WORD,WORD,
30                                                     LONG,LONG,LONG,LONG,LONG);
31 extern LONG CALLBACK PRTDRV_CallTo16_long_lwlll (FARPROC16,LONG,WORD,LONG,LONG,
32                                                  LONG);
33 extern WORD CALLBACK PRTDRV_CallTo16_word_lwwwwlwwwwllll (FARPROC16,LONG,WORD,
34                                                           WORD,WORD,WORD,LONG,
35                                                           WORD,WORD,WORD,WORD,
36                                                           LONG,LONG,LONG,LONG);
37 extern LONG CALLBACK PRTDRV_CallTo16_long_lwwllwlllllw (FARPROC16,LONG,WORD,
38                                                         WORD,LONG,LONG,WORD,
39                                                         LONG,LONG,LONG,LONG,
40                                                         LONG,WORD);
41 extern WORD CALLBACK PRTDRV_CallTo16_word_llwwlll (FARPROC16,LONG,LONG,WORD,
42                                                    WORD,LONG,LONG,LONG);
43 extern WORD CALLBACK PRTDRV_CallTo16_word_wwlllllw (FARPROC16,WORD,WORD,LONG,
44                                                     LONG,LONG,LONG,LONG,WORD);
45 extern LONG CALLBACK PRTDRV_CallTo16_long_llwll (FARPROC16,LONG,LONG,WORD,LONG,
46                                                  LONG);
47
48 /* ### stop build ### */
49
50
51 #define MAX_PRINTER_DRIVERS     16
52 static LOADED_PRINTER_DRIVER *gapLoadedPrinterDrivers[MAX_PRINTER_DRIVERS];
53
54
55 static void GetPrinterDriverFunctions(HINSTANCE16 hInst, LOADED_PRINTER_DRIVER *pLPD)
56 {
57 #define LoadPrinterDrvFunc(A) pLPD->fn[FUNC_##A] = \
58       GetProcAddress16(hInst, MAKEINTRESOURCE16(ORD_##A))
59
60       LoadPrinterDrvFunc(BITBLT);
61       LoadPrinterDrvFunc(COLORINFO);
62       LoadPrinterDrvFunc(CONTROL);
63       LoadPrinterDrvFunc(DISABLE);
64       LoadPrinterDrvFunc(ENABLE);
65       LoadPrinterDrvFunc(ENUMDFONTS);
66       LoadPrinterDrvFunc(ENUMOBJ);
67       LoadPrinterDrvFunc(OUTPUT);
68       LoadPrinterDrvFunc(PIXEL);
69       LoadPrinterDrvFunc(REALIZEOBJECT);
70       LoadPrinterDrvFunc(STRBLT);
71       LoadPrinterDrvFunc(SCANLR);
72       LoadPrinterDrvFunc(DEVICEMODE);
73       LoadPrinterDrvFunc(EXTTEXTOUT);
74       LoadPrinterDrvFunc(GETCHARWIDTH);
75       LoadPrinterDrvFunc(DEVICEBITMAP);
76       LoadPrinterDrvFunc(FASTBORDER);
77       LoadPrinterDrvFunc(SETATTRIBUTE);
78       LoadPrinterDrvFunc(STRETCHBLT);
79       LoadPrinterDrvFunc(STRETCHDIBITS);
80       LoadPrinterDrvFunc(SELECTBITMAP);
81       LoadPrinterDrvFunc(BITMAPBITS);
82       LoadPrinterDrvFunc(EXTDEVICEMODE);
83       LoadPrinterDrvFunc(DEVICECAPABILITIES);
84       LoadPrinterDrvFunc(ADVANCEDSETUPDIALOG);
85       LoadPrinterDrvFunc(DIALOGFN);
86       LoadPrinterDrvFunc(PSEUDOEDIT);
87       TRACE("got func CONTROL 0x%p enable 0x%p enumDfonts 0x%p realizeobject 0x%p extextout 0x%p\n",
88               pLPD->fn[FUNC_CONTROL],
89               pLPD->fn[FUNC_ENABLE],
90               pLPD->fn[FUNC_ENUMDFONTS],
91               pLPD->fn[FUNC_REALIZEOBJECT],
92               pLPD->fn[FUNC_EXTTEXTOUT]);
93       
94
95 }
96
97
98 static LOADED_PRINTER_DRIVER *FindPrinterDriverFromName(const char *pszDriver)
99 {
100     LOADED_PRINTER_DRIVER *pLPD = NULL;
101     int         nDriverSlot = 0;
102
103     /* Look to see if the printer driver is already loaded */
104     while (pLPD == NULL && nDriverSlot < MAX_PRINTER_DRIVERS)
105     {
106         LOADED_PRINTER_DRIVER *ptmpLPD;
107         ptmpLPD = gapLoadedPrinterDrivers[nDriverSlot++];
108         if (ptmpLPD != NULL)
109         {
110             TRACE("Comparing %s,%s\n",ptmpLPD->szDriver,pszDriver);
111             /* Found driver store info, exit loop */
112             if (strcasecmp(ptmpLPD->szDriver, pszDriver) == 0)
113               pLPD = ptmpLPD;
114         }
115     }
116     return pLPD;
117 }
118
119 static LOADED_PRINTER_DRIVER *FindPrinterDriverFromPDEVICE(SEGPTR segptrPDEVICE)
120 {
121     LOADED_PRINTER_DRIVER *pLPD = NULL;
122
123     /* Find the printer driver associated with this PDEVICE */
124     /* Each of the PDEVICE structures has a PDEVICE_HEADER structure */
125     /* just before it */
126     if (segptrPDEVICE != (SEGPTR)NULL)
127     {
128         PDEVICE_HEADER *pPDH = (PDEVICE_HEADER *)
129           ((char *) PTR_SEG_TO_LIN(segptrPDEVICE) - sizeof(PDEVICE_HEADER)); 
130         pLPD = pPDH->pLPD;
131     }
132     return pLPD;
133 }
134
135 /* 
136  * Load a printer driver, adding it self to the list of loaded drivers.
137  */
138
139 LOADED_PRINTER_DRIVER *LoadPrinterDriver(const char *pszDriver)
140 {                                        
141     HINSTANCE16 hInst;  
142     LOADED_PRINTER_DRIVER *pLPD = NULL;
143     int         nDriverSlot = 0;
144     BOOL        bSlotFound = FALSE;
145
146     /* First look to see if driver is loaded */
147     pLPD = FindPrinterDriverFromName(pszDriver);
148     if (pLPD != NULL)
149     {
150         /* Already loaded so increase usage count */
151         pLPD->nUsageCount++;
152         return pLPD;
153     }
154
155     /* Not loaded so try and find an empty slot */
156     while (!bSlotFound && nDriverSlot < MAX_PRINTER_DRIVERS)
157     {
158         if (gapLoadedPrinterDrivers[nDriverSlot] == NULL)
159           bSlotFound = TRUE;
160         else
161           nDriverSlot++;
162     }
163     if (!bSlotFound)
164     {
165         WARN("Too many printers drivers loaded\n");
166         return NULL;
167     }
168
169     {
170         char *drvName = malloc(strlen(pszDriver)+5);
171         strcpy(drvName, pszDriver);
172         strcat(drvName, ".DRV");
173         hInst = LoadLibrary16(drvName);
174     }
175
176     
177     if (hInst <= 32)
178     {
179         /* Failed to load driver */
180         WARN("Failed to load printer driver %s\n", pszDriver);
181     } else {
182         TRACE("Loaded the library\n");
183         /* Allocate some memory for printer driver info */
184         pLPD = malloc(sizeof(LOADED_PRINTER_DRIVER));
185         memset(pLPD, 0 , sizeof(LOADED_PRINTER_DRIVER));
186         
187         pLPD->hInst     = hInst;
188         pLPD->szDriver  = HEAP_strdupA(GetProcessHeap(),0,pszDriver);
189
190         /* Get DS for the printer module */
191         pLPD->ds_reg    = hInst;
192
193         TRACE("DS for %s is %x\n", pszDriver, pLPD->ds_reg);
194
195         /* Get address of printer driver functions */
196         GetPrinterDriverFunctions(hInst, pLPD);
197
198         /* Set initial usage count */
199         pLPD->nUsageCount = 1;
200
201         /* Update table of loaded printer drivers */
202         pLPD->nIndex = nDriverSlot;
203         gapLoadedPrinterDrivers[nDriverSlot] = pLPD;
204     }
205
206     return pLPD;
207 }
208
209 /*
210  *  Control (ordinal 3)
211  */
212 INT16 PRTDRV_Control(LPPDEVICE lpDestDev, WORD wfunction, SEGPTR lpInData, SEGPTR lpOutData)
213 {
214     /* wfunction == Escape code */
215     /* lpInData, lpOutData depend on code */
216
217     WORD wRet = 0;
218     LOADED_PRINTER_DRIVER *pLPD = NULL;
219
220     TRACE("%08x 0x%x %08lx %08lx\n", (unsigned int)lpDestDev, wfunction, lpInData, lpOutData);
221
222     if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
223     {
224         if (pLPD->fn[FUNC_CONTROL] == NULL)
225         {
226             WARN("Not supported by driver\n");
227             return 0;
228         }
229         wRet = PRTDRV_CallTo16_word_lwll( pLPD->fn[FUNC_CONTROL], 
230                                           (SEGPTR)lpDestDev, wfunction,
231                                           lpInData, lpOutData );
232     }
233     TRACE("return %x\n", wRet);
234     return wRet;
235 }
236
237 /*
238  *      Enable (ordinal 5)
239  */
240 WORD PRTDRV_Enable(LPVOID lpDevInfo, WORD wStyle, LPCSTR  lpDestDevType, 
241                           LPCSTR lpDeviceName, LPCSTR lpOutputFile, LPVOID lpData)
242 {
243     WORD wRet = 0;
244     LOADED_PRINTER_DRIVER *pLPD = NULL;
245
246     TRACE("%s %s\n",lpDestDevType, lpOutputFile);
247
248     /* Get the printer driver info */
249     if (wStyle == INITPDEVICE)
250         pLPD = FindPrinterDriverFromPDEVICE((SEGPTR)lpDevInfo);
251     else
252         pLPD = FindPrinterDriverFromName((char *)lpDeviceName);
253     if (pLPD != NULL) {
254         LONG            lP5;
255         DeviceCaps      *lP1;
256         LPSTR           lP3,lP4;
257         WORD            wP2;
258
259         if (!pLPD->fn[FUNC_ENABLE]) {
260             WARN("Not supported by driver\n");
261             return 0;
262         }
263
264         if (wStyle == INITPDEVICE)
265             lP1 = (DeviceCaps*)lpDevInfo;/* 16 bit segmented ptr already */
266         else
267             lP1 = SEGPTR_NEW(DeviceCaps);
268         
269         wP2 = wStyle;
270         
271         /* SEGPTR_STRDUP handles NULL like a charm ... */
272         lP3 = SEGPTR_STRDUP(lpDestDevType);
273         lP4 = SEGPTR_STRDUP(lpOutputFile);
274         lP5 = (LONG)lpData;
275         
276         wRet = PRTDRV_CallTo16_word_lwlll(pLPD->fn[FUNC_ENABLE], 
277                              (wStyle==INITPDEVICE)?(SEGPTR)lP1:SEGPTR_GET(lP1),
278                              wP2,
279                              SEGPTR_GET(lP3),
280                              SEGPTR_GET(lP4),
281                              lP5);
282         SEGPTR_FREE(lP3);
283         SEGPTR_FREE(lP4);
284
285         /* Get the data back */
286         if (lP1 != 0 && wStyle != INITPDEVICE) {
287             memcpy(lpDevInfo,lP1,sizeof(DeviceCaps));
288             SEGPTR_FREE(lP1);
289         }
290     }
291     TRACE("return %x\n", wRet);
292     return wRet;
293 }
294
295
296 /*
297  *      EnumDFonts (ordinal 6)
298  */
299 WORD PRTDRV_EnumDFonts(LPPDEVICE lpDestDev, LPSTR lpFaceName,  
300                        FARPROC16 lpCallbackFunc, LPVOID lpClientData)
301 {
302     WORD wRet = 0;
303     LOADED_PRINTER_DRIVER *pLPD = NULL;
304
305     TRACE("%08lx %s %p %p\n",
306                      lpDestDev, lpFaceName, lpCallbackFunc, lpClientData);
307
308     if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
309     {
310         LONG lP1, lP4;
311         LPBYTE lP2;
312
313         if (pLPD->fn[FUNC_ENUMDFONTS] == NULL) {
314             WARN("Not supported by driver\n");
315             return 0;
316         }
317
318         lP1 = (SEGPTR)lpDestDev;
319         if(lpFaceName)
320             lP2 = SEGPTR_STRDUP(lpFaceName);
321         else
322             lP2 = NULL;
323         lP4 = (LONG)lpClientData;
324         wRet = PRTDRV_CallTo16_word_llll( pLPD->fn[FUNC_ENUMDFONTS], 
325                                           lP1, SEGPTR_GET(lP2),
326                                           (LONG)lpCallbackFunc,lP4);
327         if(lpFaceName)
328             SEGPTR_FREE(lP2);
329     } else 
330         WARN("Failed to find device\n");
331     
332     TRACE("return %x\n", wRet);
333     return wRet;
334 }
335 /*
336  *      EnumObj (ordinal 7)
337  */
338 BOOL16 PRTDRV_EnumObj(LPPDEVICE lpDestDev, WORD iStyle, 
339                        FARPROC16 lpCallbackFunc, LPVOID lpClientData)
340 {
341     WORD wRet = 0;
342     LOADED_PRINTER_DRIVER *pLPD = NULL;
343
344     TRACE("(some params - fixme)\n");
345
346     if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
347     {
348         LONG lP1, lP3, lP4;
349         WORD wP2;
350
351         if (pLPD->fn[FUNC_ENUMOBJ] == NULL)
352         {
353             WARN("Not supported by driver\n");
354             return 0;
355         }
356
357         lP1 = (SEGPTR)lpDestDev;
358         
359         wP2 = iStyle;
360
361         /* 
362          * Need to pass addres of function conversion function that will switch back to 32 bit code if necessary
363          */
364         lP3 = (LONG)lpCallbackFunc; 
365
366         lP4 = (LONG)lpClientData;
367         
368         wRet = PRTDRV_CallTo16_word_lwll( pLPD->fn[FUNC_ENUMOBJ], 
369                                           lP1, wP2, lP3, lP4 );
370     }
371     else 
372         WARN("Failed to find device\n");
373     
374     TRACE("return %x\n", wRet);
375     return wRet;
376 }
377
378 /*
379  *      Output (ordinal 8)
380  */
381 WORD PRTDRV_Output(LPPDEVICE     lpDestDev,
382                    WORD          wStyle, 
383                    WORD          wCount,
384                    POINT16      *points, 
385                    LPLOGPEN16    lpPen,
386                    LPLOGBRUSH16  lpBrush,
387                    SEGPTR        lpDrawMode,
388                    HRGN          hClipRgn)
389 {
390     WORD wRet = 0;
391     LOADED_PRINTER_DRIVER *pLPD = NULL;
392     
393     TRACE("PRTDRV_OUTPUT %d\n", wStyle );
394     
395     if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
396     {
397         LONG lP1, lP5, lP6, lP7;
398         LPPOINT16 lP4;
399         LPRECT16 lP8;
400         WORD wP2, wP3;
401         int   nSize;
402         if (pLPD->fn[FUNC_OUTPUT] == NULL)
403         {
404             WARN("Not supported by driver\n");
405             return 0;
406         }
407
408         lP1 = lpDestDev;
409         wP2 = wStyle;
410         wP3 = wCount;
411         nSize = sizeof(POINT16) * wCount;
412         lP4 = (LPPOINT16 )SEGPTR_ALLOC(nSize);
413         memcpy(lP4,points,nSize);
414         lP5 = SEGPTR_GET( lpPen );
415         lP6 = SEGPTR_GET( lpBrush );
416         lP7 = lpDrawMode;
417         
418         if (hClipRgn)
419         {
420             DWORD size;
421             RGNDATA *clip;
422
423             size = GetRegionData( hClipRgn, 0, NULL );
424             clip = HeapAlloc( GetProcessHeap(), 0, size );
425             if(!clip) 
426             {
427                 WARN("Can't alloc clip array in PRTDRV_Output\n");
428                 return FALSE;
429             }
430             GetRegionData( hClipRgn, size, clip );
431             if( clip->rdh.nCount == 0 )
432             {
433                 wRet = PRTDRV_CallTo16_word_lwwlllll(pLPD->fn[FUNC_OUTPUT], 
434                                                      lP1, wP2, wP3,
435                                                      SEGPTR_GET(lP4),
436                                                      lP5, lP6, lP7,
437                                                      (SEGPTR) NULL);
438             }
439             else
440             {
441                 RECT *pRect;
442                 lP8 = SEGPTR_NEW(RECT16);
443             
444                 for(pRect = (RECT *)clip->Buffer; 
445                     pRect < (RECT *)clip->Buffer + clip->rdh.nCount; pRect++)
446                 {
447                     CONV_RECT32TO16( pRect, lP8 );
448
449                     TRACE("rect = %d,%d - %d,%d\n",
450                             lP8->left, lP8->top, lP8->right, lP8->bottom );
451                     wRet = PRTDRV_CallTo16_word_lwwlllll(pLPD->fn[FUNC_OUTPUT],
452                                                          lP1, wP2, wP3,
453                                                          SEGPTR_GET(lP4),
454                                                          lP5, lP6, lP7,
455                                                          SEGPTR_GET(lP8));
456                 }
457                 SEGPTR_FREE(lP8);
458             }
459             HeapFree( GetProcessHeap(), 0, clip );
460         }
461         else
462         {
463             wRet = PRTDRV_CallTo16_word_lwwlllll(pLPD->fn[FUNC_OUTPUT], 
464                                                  lP1, wP2, wP3,
465                                                  SEGPTR_GET(lP4),
466                                                  lP5, lP6, lP7, (SEGPTR) NULL);
467         }
468         SEGPTR_FREE(lP4);
469     }
470     TRACE("PRTDRV_Output return %d\n", wRet);
471     return wRet;
472 }
473
474 /* 
475  * RealizeObject (ordinal 10)
476  */
477 DWORD PRTDRV_RealizeObject(LPPDEVICE lpDestDev, WORD wStyle, 
478                            LPVOID lpInObj, LPVOID lpOutObj,
479                            SEGPTR lpTextXForm)
480 {
481     WORD dwRet = 0;
482     LOADED_PRINTER_DRIVER *pLPD = NULL;
483     
484     TRACE("%08lx %04x %p %p %08lx\n",
485                  lpDestDev, wStyle, lpInObj, lpOutObj, lpTextXForm);
486     
487     if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
488     {
489         LONG lP1, lP3, lP4, lP5;  
490         WORD wP2;
491         LPBYTE lpBuf = NULL;
492         unsigned int    nSize;
493
494         if (pLPD->fn[FUNC_REALIZEOBJECT] == NULL)
495         {
496             WARN("Not supported by driver\n");
497             return 0;
498         }
499
500         lP1 = lpDestDev;
501         wP2 = wStyle;
502         
503         switch ((INT16)wStyle)
504         {
505         case DRVOBJ_BRUSH:
506             nSize = sizeof (LOGBRUSH16);
507             break;
508         case DRVOBJ_FONT: 
509             nSize = sizeof(LOGFONT16); 
510             break;
511         case DRVOBJ_PEN:
512             nSize = sizeof(LOGPEN16); 
513             break;
514
515         case -DRVOBJ_BRUSH:
516         case -DRVOBJ_FONT: 
517         case -DRVOBJ_PEN:
518             nSize = -1;
519             break;
520
521         case DRVOBJ_PBITMAP:
522         default:
523             WARN("Object type %d not supported\n", wStyle);
524             nSize = 0;
525             
526         }
527
528         if(nSize != -1)
529         {
530             lpBuf = SEGPTR_ALLOC(nSize);
531             memcpy(lpBuf, lpInObj, nSize);
532             lP3 = SEGPTR_GET(lpBuf);
533         } 
534         else
535             lP3 = SEGPTR_GET( lpInObj );
536
537         lP4 = SEGPTR_GET( lpOutObj );
538
539         lP5 = lpTextXForm;
540         TRACE("Calling Realize %08lx %04x %08lx %08lx %08lx\n",
541                      lP1, wP2, lP3, lP4, lP5);
542         dwRet = PRTDRV_CallTo16_long_lwlll(pLPD->fn[FUNC_REALIZEOBJECT], 
543                                            lP1, wP2, lP3, lP4, lP5);
544         if(lpBuf)
545             SEGPTR_FREE(lpBuf);
546
547     }
548     TRACE("return %x\n", dwRet);
549     return dwRet;
550 }
551
552 /* 
553  * StretchBlt (ordinal 27)
554  */
555 DWORD PRTDRV_StretchBlt(LPPDEVICE lpDestDev,
556                         WORD wDestX, WORD wDestY,
557                         WORD wDestXext, WORD wDestYext, 
558                         LPPDEVICE lpSrcDev,
559                         WORD wSrcX, WORD wSrcY,
560                         WORD wSrcXext, WORD wSrcYext, 
561                         DWORD Rop3,
562                         LPLOGBRUSH16 lpBrush,
563                         SEGPTR lpDrawMode,
564                         RECT16 *lpClipRect)
565 {
566     WORD wRet = 0;
567     LOADED_PRINTER_DRIVER *pLPD = NULL;
568     
569     TRACE("(lots of params - fixme)\n");
570     
571     if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
572     {
573         LONG lP1,lP6, lP11, lP12, lP13;
574         LPRECT16 lP14;
575         WORD wP2, wP3, wP4, wP5, wP7, wP8, wP9, wP10;
576
577         if (pLPD->fn[FUNC_STRETCHBLT] == NULL)
578         {
579             WARN("Not supported by driver\n");
580             return 0;
581         }
582         lP1  = lpDestDev;
583         wP2  = wDestX;
584         wP3  = wDestY;
585         wP4  = wDestXext;
586         wP5  = wDestYext;
587         lP6  = lpSrcDev;
588         wP7  = wSrcX;
589         wP8  = wSrcY;
590         wP9  = wSrcXext;
591         wP10 = wSrcYext;
592         lP11 = Rop3;
593         lP12 = SEGPTR_GET( lpBrush );
594         lP13 = lpDrawMode;
595         if (lpClipRect != NULL)
596         {
597             lP14 = SEGPTR_NEW(RECT16);
598             memcpy(lP14,lpClipRect,sizeof(RECT16));
599
600         }
601         else
602           lP14 = 0L;
603         wRet = PRTDRV_CallTo16_word_lwwwwlwwwwllll(pLPD->fn[FUNC_STRETCHBLT], 
604                                                    lP1, wP2, wP3, wP4, wP5,
605                                                    lP6, wP7, wP8, wP9, wP10, 
606                                                    lP11, lP12, lP13,
607                                                    SEGPTR_GET(lP14));
608         SEGPTR_FREE(lP14);
609         TRACE("Called StretchBlt ret %d\n",wRet);
610     }
611     return wRet;
612 }
613
614 DWORD PRTDRV_ExtTextOut(LPPDEVICE lpDestDev, WORD wDestXOrg, WORD wDestYOrg,
615                         RECT16 *lpClipRect, LPCSTR lpString, WORD wCount, 
616                         LPFONTINFO16 lpFontInfo, SEGPTR lpDrawMode, 
617                         SEGPTR lpTextXForm, SHORT *lpCharWidths,
618                         RECT16 *     lpOpaqueRect, WORD wOptions)
619 {
620     DWORD dwRet = 0;
621     LOADED_PRINTER_DRIVER *pLPD = NULL;
622     
623     TRACE("(lots of params - fixme)\n");
624     
625     if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
626     {
627         LONG            lP1, lP7, lP8, lP9, lP10;  
628         LPSTR           lP5;
629         LPRECT16        lP4,lP11;
630         WORD            wP2, wP3, wP12;
631         INT16           iP6;
632         unsigned int    nSize = -1;
633
634         if (pLPD->fn[FUNC_EXTTEXTOUT] == NULL)
635         {
636             WARN("Not supported by driver\n");
637             return 0;
638         }
639
640         lP1 = lpDestDev;
641         wP2 = wDestXOrg;
642         wP3 = wDestYOrg;
643         
644         if (lpClipRect != NULL) {
645             lP4 = SEGPTR_NEW(RECT16);
646             TRACE("Adding lpClipRect\n");
647             memcpy(lP4,lpClipRect,sizeof(RECT16));
648         } else
649           lP4 = 0L;
650
651         if (lpString != NULL) {
652             nSize = strlen(lpString);
653             if (nSize>abs(wCount))
654                 nSize = abs(wCount);
655             lP5 = SEGPTR_ALLOC(nSize+1);
656             TRACE("Adding lpString (nSize is %d)\n",nSize);
657             memcpy(lP5,lpString,nSize);
658             *((char *)lP5 + nSize) = '\0';
659         } else
660           lP5 = 0L;
661         
662         iP6 = wCount;
663         
664         /* This should be realized by the driver, so in 16bit data area */
665         lP7 = SEGPTR_GET( lpFontInfo );
666         lP8 = lpDrawMode;
667         lP9 = lpTextXForm;
668         
669         if (lpCharWidths != NULL) 
670           FIXME("Char widths not supported\n");
671         lP10 = 0;
672         
673         if (lpOpaqueRect != NULL) {
674             lP11 = SEGPTR_NEW(RECT16);
675             TRACE("Adding lpOpaqueRect\n");
676             memcpy(lP11,lpOpaqueRect,sizeof(RECT16));   
677         } else
678           lP11 = 0L;
679         
680         wP12 = wOptions;
681         TRACE("Calling ExtTextOut 0x%lx 0x%x 0x%x %p\n",
682                      lP1, wP2, wP3, lP4);
683         TRACE("%*s 0x%x 0x%lx 0x%lx\n",
684                      nSize,lP5, iP6, lP7, lP8);
685         TRACE("0x%lx 0x%lx %p 0x%x\n",
686                      lP9, lP10, lP11, wP12);
687         dwRet = PRTDRV_CallTo16_long_lwwllwlllllw(pLPD->fn[FUNC_EXTTEXTOUT], 
688                                                   lP1, wP2, wP3,
689                                                   SEGPTR_GET(lP4),
690                                                   SEGPTR_GET(lP5), iP6, lP7,
691                                                   lP8, lP9, lP10,
692                                                   SEGPTR_GET(lP11), wP12);
693     }
694     TRACE("return %lx\n", dwRet);
695     return dwRet;
696 }
697
698 int WINAPI dmEnumDFonts16(LPPDEVICE lpDestDev, LPSTR lpFaceName, FARPROC16 lpCallbackFunc, LPVOID lpClientData)
699 {
700         /* Windows 3.1 just returns 1 */
701         return 1;
702 }
703
704 int WINAPI dmRealizeObject16(LPPDEVICE lpDestDev, INT16 wStyle, LPSTR lpInObj, LPSTR lpOutObj, SEGPTR lpTextXForm)
705 {
706     FIXME("(lpDestDev=%08x,wStyle=%04x,lpInObj=%08x,lpOutObj=%08x,lpTextXForm=%08x): stub\n",
707         (UINT)lpDestDev, wStyle, (UINT)lpInObj, (UINT)lpOutObj, (UINT)lpTextXForm);
708     if (wStyle < 0) { /* Free extra memory of given object's structure */
709         switch ( -wStyle ) {
710             case DRVOBJ_PEN:    {
711                                 /* LPLOGPEN16 DeletePen = (LPLOGPEN16)lpInObj; */
712
713                                 TRACE("DRVOBJ_PEN_delete\n");
714                                 break;
715                                 }
716             case DRVOBJ_BRUSH:  {
717                                 TRACE("DRVOBJ_BRUSH_delete\n");
718                                 break;
719                                 }
720             case DRVOBJ_FONT:   {
721                                 /* LPTEXTXFORM16 TextXForm
722                                         = (LPTEXTXFORM16)lpTextXForm; */
723                                 TRACE("DRVOBJ_FONT_delete\n");
724                                 break;
725                                 }
726             case DRVOBJ_PBITMAP:        TRACE("DRVOBJ_PBITMAP_delete\n");
727                                 break;
728         }
729     }
730     else { /* Realize given object */
731
732         switch (wStyle) {
733             case DRVOBJ_PEN: {
734                                 LPLOGPEN16 InPen  = (LPLOGPEN16)lpInObj;
735
736                                 TRACE("DRVOBJ_PEN\n");
737                                 if (lpOutObj) {
738                                     if (InPen->lopnStyle == PS_NULL) {
739                                         *(DWORD *)lpOutObj = 0;
740                                         *(WORD *)(lpOutObj+4) = InPen->lopnStyle;
741                                     }
742                                     else
743                                     if ((InPen->lopnWidth.x > 1) || (InPen->lopnStyle > PS_NULL) ) {
744                                         *(DWORD *)lpOutObj = InPen->lopnColor;
745                                         *(WORD *)(lpOutObj+4) = 0;
746                                     }
747                                     else {
748                                         *(DWORD *)lpOutObj = InPen->lopnColor & 0xffff0000;
749                                         *(WORD *)(lpOutObj+4) = InPen->lopnStyle;
750                                     }
751                                 }
752                                 return sizeof(LOGPEN16);
753                              }
754             case DRVOBJ_BRUSH: {
755                                 LPLOGBRUSH16 InBrush  = (LPLOGBRUSH16)lpInObj;
756                                 LPLOGBRUSH16 OutBrush = (LPLOGBRUSH16)lpOutObj;
757                                 /* LPPOINT16 Point = (LPPOINT16)lpTextXForm; */
758
759                                 TRACE("DRVOBJ_BRUSH\n");
760                                 if (!lpOutObj) return sizeof(LOGBRUSH16);
761                                 else {
762                                     OutBrush->lbStyle = InBrush->lbStyle;
763                                     OutBrush->lbColor = InBrush->lbColor;
764                                     OutBrush->lbHatch = InBrush->lbHatch;
765                                     if (InBrush->lbStyle == BS_SOLID) 
766                                     return 0x8002; /* FIXME: diff mono-color */
767                                     else return 0x8000;
768                                 }
769                                }
770             case DRVOBJ_FONT: {
771                                 /* LPTEXTXFORM16 TextXForm
772                                         = (LPTEXTXFORM16)lpTextXForm; */
773                                 TRACE("DRVOBJ_FONT\n");
774                                 return 0;/* DISPLAY.DRV doesn't realize fonts */
775                               }
776             case DRVOBJ_PBITMAP:        TRACE("DRVOBJ_PBITMAP\n");
777                                         return 0; /* create memory bitmap */
778         }
779     }
780     return 1;
781 }
782
783
784 WORD PRTDRV_GetCharWidth(LPPDEVICE lpDestDev, LPINT lpBuffer, 
785                       WORD wFirstChar, WORD wLastChar, LPFONTINFO16 lpFontInfo,
786                       SEGPTR lpDrawMode, SEGPTR lpTextXForm )
787 {
788
789     WORD wRet = 0;
790     LOADED_PRINTER_DRIVER *pLPD = NULL;
791     
792     TRACE("(lots of params - fixme)\n");
793     
794     if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
795     {
796         LONG            lP1, lP5, lP6, lP7;  
797         LPWORD          lP2;
798         WORD            wP3, wP4, i;
799         
800         if (pLPD->fn[FUNC_GETCHARWIDTH] == NULL)
801         {
802             WARN("Not supported by driver\n");
803             return 0;
804         }
805
806         lP1 = lpDestDev;
807         lP2 = SEGPTR_ALLOC( (wLastChar - wFirstChar + 1) * sizeof(WORD) );
808         wP3 = wFirstChar;
809         wP4 = wLastChar;
810         lP5 = SEGPTR_GET( lpFontInfo );
811         lP6 = lpDrawMode;
812         lP7 = lpTextXForm;
813         
814         wRet = PRTDRV_CallTo16_word_llwwlll(pLPD->fn[FUNC_GETCHARWIDTH], 
815                                             lP1, SEGPTR_GET(lP2), wP3,
816                                             wP4, lP5, lP6, lP7 );
817
818         for(i = 0; i <= wLastChar - wFirstChar; i++)
819             lpBuffer[i] = (INT) lP2[i];
820
821         SEGPTR_FREE(lP2);
822     }
823     return wRet;
824 }
825
826 /**************************************************************
827  *
828  *       WIN16DRV_ExtDeviceMode
829  */
830 INT WIN16DRV_ExtDeviceMode(LPSTR lpszDriver, HWND hwnd, LPDEVMODEA lpdmOutput,
831                            LPSTR lpszDevice, LPSTR lpszPort,
832                            LPDEVMODEA lpdmInput, LPSTR lpszProfile,
833                            DWORD dwMode)
834 {
835     LOADED_PRINTER_DRIVER *pLPD = LoadPrinterDriver(lpszDriver);
836     LPDEVMODEA lpSegOut = NULL, lpSegIn = NULL;
837     LPSTR lpSegDevice, lpSegPort, lpSegProfile;
838     INT16 wRet;
839     WORD wOutSize = 0, wInSize = 0;
840
841     if(!pLPD) return -1;
842
843     if(pLPD->fn[FUNC_EXTDEVICEMODE] == NULL) {
844         WARN("No EXTDEVICEMODE\n");
845         return -1;
846     }
847     lpSegDevice = SEGPTR_STRDUP(lpszDevice);
848     lpSegPort = SEGPTR_STRDUP(lpszPort);
849     lpSegProfile = SEGPTR_STRDUP(lpszProfile);
850     if(lpdmOutput) {
851       /* We don't know how big this will be so we call the driver's
852          ExtDeviceMode to find out */
853         wOutSize = PRTDRV_CallTo16_word_wwlllllw(
854                    pLPD->fn[FUNC_EXTDEVICEMODE], hwnd, pLPD->hInst, 0,
855                    SEGPTR_GET(lpSegDevice), SEGPTR_GET(lpSegPort), 0,
856                    SEGPTR_GET(lpSegProfile), 0 );
857         lpSegOut = SEGPTR_ALLOC(wOutSize);
858     }
859     if(lpdmInput) {
860       /* This time we get the information from the fields */
861         wInSize = lpdmInput->dmSize + lpdmInput->dmDriverExtra;
862         lpSegIn = SEGPTR_ALLOC(wInSize);
863         memcpy(lpSegIn, lpdmInput, wInSize);
864     }
865     wRet = PRTDRV_CallTo16_word_wwlllllw( pLPD->fn[FUNC_EXTDEVICEMODE],
866                                           hwnd, pLPD->hInst,
867                                           SEGPTR_GET(lpSegOut),
868                                           SEGPTR_GET(lpSegDevice),
869                                           SEGPTR_GET(lpSegPort),
870                                           SEGPTR_GET(lpSegIn),
871                                           SEGPTR_GET(lpSegProfile),
872                                           dwMode );
873     if(lpSegOut) {
874         memcpy(lpdmOutput, lpSegOut, wOutSize);
875         SEGPTR_FREE(lpSegOut);
876     }
877     if(lpSegIn) {
878         SEGPTR_FREE(lpSegIn);
879     }
880     SEGPTR_FREE(lpSegDevice);
881     SEGPTR_FREE(lpSegPort);
882     SEGPTR_FREE(lpSegProfile);
883     return wRet;
884 }
885
886 /**************************************************************
887  *
888  *       WIN16DRV_DeviceCapabilities
889  *
890  * This is a bit of a pain since we don't know the size of lpszOutput we have
891  * call the driver twice.
892  */
893 DWORD WIN16DRV_DeviceCapabilities(LPSTR lpszDriver, LPCSTR lpszDevice,
894                                   LPCSTR lpszPort, WORD fwCapability,
895                                   LPSTR lpszOutput, LPDEVMODEA lpDevMode)
896 {
897     LOADED_PRINTER_DRIVER *pLPD = LoadPrinterDriver(lpszDriver);
898     LPVOID lpSegdm = NULL, lpSegOut = NULL;
899     LPSTR lpSegDevice, lpSegPort;
900     DWORD dwRet;
901     INT OutputSize;
902
903     TRACE("%s,%s,%s,%d,%p,%p\n", lpszDriver, lpszDevice, lpszPort,
904           fwCapability, lpszOutput, lpDevMode);
905
906     if(!pLPD) return -1;
907
908     if(pLPD->fn[FUNC_DEVICECAPABILITIES] == NULL) {
909         WARN("No DEVICECAPABILITES\n");
910         return -1;
911     }
912     lpSegDevice = SEGPTR_STRDUP(lpszDevice);
913     lpSegPort = SEGPTR_STRDUP(lpszPort);
914
915     if(lpDevMode) {
916         lpSegdm = SEGPTR_ALLOC(lpDevMode->dmSize + lpDevMode->dmDriverExtra);
917         memcpy(lpSegdm, lpDevMode, lpDevMode->dmSize +
918                lpDevMode->dmDriverExtra);
919     }
920
921     dwRet = PRTDRV_CallTo16_long_llwll(
922             pLPD->fn[FUNC_DEVICECAPABILITIES],
923             SEGPTR_GET(lpSegDevice), SEGPTR_GET(lpSegPort),
924             fwCapability, 0, SEGPTR_GET(lpSegdm) );
925
926     if(dwRet == -1) return -1;
927
928     switch(fwCapability) {
929     case DC_BINADJUST:
930     case DC_COLLATE:
931     case DC_COLORDEVICE:
932     case DC_COPIES:
933     case DC_DRIVER:
934     case DC_DUPLEX:
935     case DC_EMF_COMPLIANT:
936     case DC_EXTRA:
937     case DC_FIELDS:
938     case DC_MANUFACTURER:
939     case DC_MAXEXTENT:
940     case DC_MINEXTENT:
941     case DC_MODEL:
942     case DC_ORIENTATION:
943     case DC_PRINTERMEM:
944     case DC_PRINTRATEUNIT:
945     case DC_SIZE:
946     case DC_TRUETYPE:
947     case DC_VERSION:
948         OutputSize = 0;
949         break;
950
951     case DC_BINNAMES:
952         OutputSize = 24 * dwRet;
953         break;
954
955     case DC_BINS:
956     case DC_PAPERS:
957         OutputSize = sizeof(WORD) * dwRet;
958         break;
959
960     case DC_DATATYPE_PRODUCED:
961         OutputSize = dwRet;
962         FIXME("%ld DataTypes supported. Don't know how long to make buffer!\n",
963               dwRet);
964         break;
965
966     case DC_ENUMRESOLUTIONS:
967         OutputSize = 2 * sizeof(LONG) * dwRet;
968         break;
969
970     case DC_FILEDEPENDENCIES:
971     case DC_MEDIAREADY:
972     case DC_PAPERNAMES:
973         OutputSize = 64 * dwRet;
974         break;
975
976     case DC_NUP:
977         OutputSize = sizeof(DWORD) * dwRet;
978         break;
979
980     case DC_PAPERSIZE:
981         OutputSize = sizeof(POINT16) * dwRet;
982         break;
983
984     case DC_PERSONALITY:
985         OutputSize = 32 * dwRet;
986         break;
987
988     default:
989         FIXME("Unsupported capability %d\n", fwCapability);
990         OutputSize = 0;
991         break;
992     }
993
994     if(OutputSize && lpszOutput) {
995         lpSegOut = SEGPTR_ALLOC(OutputSize);
996         dwRet = PRTDRV_CallTo16_long_llwll(
997                                         pLPD->fn[FUNC_DEVICECAPABILITIES],
998                                         SEGPTR_GET(lpSegDevice),
999                                         SEGPTR_GET(lpSegPort),
1000                                         fwCapability,
1001                                         SEGPTR_GET(lpSegOut),
1002                                         SEGPTR_GET(lpSegdm) );
1003         memcpy(lpszOutput, lpSegOut, OutputSize);
1004         SEGPTR_FREE(lpSegOut);
1005     }
1006
1007     if(lpSegdm) {
1008         memcpy(lpDevMode, lpSegdm, lpDevMode->dmSize +
1009                lpDevMode->dmDriverExtra);
1010         SEGPTR_FREE(lpSegdm);
1011     }
1012     SEGPTR_FREE(lpSegDevice);
1013     SEGPTR_FREE(lpSegPort);
1014     return dwRet;
1015 }