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