Avoid unnecessary error messages.
[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 "debug.h"
19 #include "bitmap.h"
20 #include "pen.h"
21
22 #define MAX_PRINTER_DRIVERS     16
23 static LOADED_PRINTER_DRIVER *gapLoadedPrinterDrivers[MAX_PRINTER_DRIVERS];
24
25
26 static void GetPrinterDriverFunctions(HINSTANCE16 hInst, LOADED_PRINTER_DRIVER *pLPD)
27 {
28 #define LoadPrinterDrvFunc(A) pLPD->fn[FUNC_##A] = \
29       GetProcAddress16(hInst, MAKEINTRESOURCE16(ORD_##A))
30
31       LoadPrinterDrvFunc(BITBLT);
32       LoadPrinterDrvFunc(COLORINFO);
33       LoadPrinterDrvFunc(CONTROL);
34       LoadPrinterDrvFunc(DISABLE);
35       LoadPrinterDrvFunc(ENABLE);
36       LoadPrinterDrvFunc(ENUMDFONTS);
37       LoadPrinterDrvFunc(ENUMOBJ);
38       LoadPrinterDrvFunc(OUTPUT);
39       LoadPrinterDrvFunc(PIXEL);
40       LoadPrinterDrvFunc(REALIZEOBJECT);
41       LoadPrinterDrvFunc(STRBLT);
42       LoadPrinterDrvFunc(SCANLR);
43       LoadPrinterDrvFunc(DEVICEMODE);
44       LoadPrinterDrvFunc(EXTTEXTOUT);
45       LoadPrinterDrvFunc(GETCHARWIDTH);
46       LoadPrinterDrvFunc(DEVICEBITMAP);
47       LoadPrinterDrvFunc(FASTBORDER);
48       LoadPrinterDrvFunc(SETATTRIBUTE);
49       LoadPrinterDrvFunc(STRETCHBLT);
50       LoadPrinterDrvFunc(STRETCHDIBITS);
51       LoadPrinterDrvFunc(SELECTBITMAP);
52       LoadPrinterDrvFunc(BITMAPBITS);
53       LoadPrinterDrvFunc(EXTDEVICEMODE);
54       LoadPrinterDrvFunc(DEVICECAPABILITIES);
55       LoadPrinterDrvFunc(ADVANCEDSETUPDIALOG);
56       LoadPrinterDrvFunc(DIALOGFN);
57       LoadPrinterDrvFunc(PSEUDOEDIT);
58       TRACE(win16drv,"got func CONTROL 0x%p enable 0x%p enumDfonts 0x%p realizeobject 0x%p extextout 0x%p\n",
59               pLPD->fn[FUNC_CONTROL],
60               pLPD->fn[FUNC_ENABLE],
61               pLPD->fn[FUNC_ENUMDFONTS],
62               pLPD->fn[FUNC_REALIZEOBJECT],
63               pLPD->fn[FUNC_EXTTEXTOUT]);
64       
65
66 }
67
68
69 static LOADED_PRINTER_DRIVER *FindPrinterDriverFromName(const char *pszDriver)
70 {
71     LOADED_PRINTER_DRIVER *pLPD = NULL;
72     int         nDriverSlot = 0;
73
74     /* Look to see if the printer driver is already loaded */
75     while (pLPD == NULL && nDriverSlot < MAX_PRINTER_DRIVERS)
76     {
77         LOADED_PRINTER_DRIVER *ptmpLPD;
78         ptmpLPD = gapLoadedPrinterDrivers[nDriverSlot++];
79         if (ptmpLPD != NULL)
80         {
81             TRACE(win16drv, "Comparing %s,%s\n",ptmpLPD->szDriver,pszDriver);
82             /* Found driver store info, exit loop */
83             if (lstrcmpiA(ptmpLPD->szDriver, pszDriver) == 0)
84               pLPD = ptmpLPD;
85         }
86     }
87     return pLPD;
88 }
89
90 static LOADED_PRINTER_DRIVER *FindPrinterDriverFromPDEVICE(SEGPTR segptrPDEVICE)
91 {
92     LOADED_PRINTER_DRIVER *pLPD = NULL;
93
94     /* Find the printer driver associated with this PDEVICE */
95     /* Each of the PDEVICE structures has a PDEVICE_HEADER structure */
96     /* just before it */
97     if (segptrPDEVICE != (SEGPTR)NULL)
98     {
99         PDEVICE_HEADER *pPDH = (PDEVICE_HEADER *)
100           (PTR_SEG_TO_LIN(segptrPDEVICE) - sizeof(PDEVICE_HEADER)); 
101         pLPD = pPDH->pLPD;
102     }
103     return pLPD;
104 }
105
106 /* 
107  * Load a printer driver, adding it self to the list of loaded drivers.
108  */
109
110 LOADED_PRINTER_DRIVER *LoadPrinterDriver(const char *pszDriver)
111 {                                        
112     HINSTANCE16 hInst;  
113     LOADED_PRINTER_DRIVER *pLPD = NULL;
114     int         nDriverSlot = 0;
115     BOOL        bSlotFound = FALSE;
116
117     /* First look to see if driver is loaded */
118     pLPD = FindPrinterDriverFromName(pszDriver);
119     if (pLPD != NULL)
120     {
121         /* Already loaded so increase usage count */
122         pLPD->nUsageCount++;
123         return pLPD;
124     }
125
126     /* Not loaded so try and find an empty slot */
127     while (!bSlotFound && nDriverSlot < MAX_PRINTER_DRIVERS)
128     {
129         if (gapLoadedPrinterDrivers[nDriverSlot] == NULL)
130           bSlotFound = TRUE;
131         else
132           nDriverSlot++;
133     }
134     if (!bSlotFound)
135     {
136         WARN(win16drv,"Too many printers drivers loaded\n");
137         return NULL;
138     }
139
140     {
141         char *drvName = malloc(strlen(pszDriver)+5);
142         strcpy(drvName, pszDriver);
143         strcat(drvName, ".DRV");
144         hInst = LoadLibrary16(drvName);
145     }
146
147     
148     if (hInst <= 32)
149     {
150         /* Failed to load driver */
151         WARN(win16drv, "Failed to load printer driver %s\n", pszDriver);
152     } else {
153         TRACE(win16drv, "Loaded the library\n");
154         /* Allocate some memory for printer driver info */
155         pLPD = malloc(sizeof(LOADED_PRINTER_DRIVER));
156         memset(pLPD, 0 , sizeof(LOADED_PRINTER_DRIVER));
157         
158         pLPD->hInst     = hInst;
159         pLPD->szDriver  = HEAP_strdupA(SystemHeap,0,pszDriver);
160
161         /* Get DS for the printer module */
162         pLPD->ds_reg    = hInst;
163
164         TRACE(win16drv, "DS for %s is %x\n", pszDriver, pLPD->ds_reg);
165
166         /* Get address of printer driver functions */
167         GetPrinterDriverFunctions(hInst, pLPD);
168
169         /* Set initial usage count */
170         pLPD->nUsageCount = 1;
171
172         /* Update table of loaded printer drivers */
173         pLPD->nIndex = nDriverSlot;
174         gapLoadedPrinterDrivers[nDriverSlot] = pLPD;
175     }
176
177     return pLPD;
178 }
179
180 /*
181  *  Control (ordinal 3)
182  */
183 INT16 PRTDRV_Control(LPPDEVICE lpDestDev, WORD wfunction, SEGPTR lpInData, SEGPTR lpOutData)
184 {
185     /* wfunction == Escape code */
186     /* lpInData, lpOutData depend on code */
187
188     WORD wRet = 0;
189     LOADED_PRINTER_DRIVER *pLPD = NULL;
190
191     TRACE(win16drv, "%08x 0x%x %08lx %08lx\n", (unsigned int)lpDestDev, wfunction, lpInData, lpOutData);
192
193     if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
194     {
195         if (pLPD->fn[FUNC_CONTROL] == NULL)
196         {
197             WARN(win16drv, "Not supported by driver\n");
198             return 0;
199         }
200         wRet = Callbacks->CallDrvControlProc( pLPD->fn[FUNC_CONTROL], 
201                                               (SEGPTR)lpDestDev, wfunction,
202                                               lpInData, lpOutData );
203     }
204     TRACE(win16drv, "return %x\n", wRet);
205     return wRet;
206 }
207
208 /*
209  *      Enable (ordinal 5)
210  */
211 WORD PRTDRV_Enable(LPVOID lpDevInfo, WORD wStyle, LPCSTR  lpDestDevType, 
212                           LPCSTR lpDeviceName, LPCSTR lpOutputFile, LPVOID lpData)
213 {
214     WORD wRet = 0;
215     LOADED_PRINTER_DRIVER *pLPD = NULL;
216
217     TRACE(win16drv, "%s %s\n",lpDestDevType, lpOutputFile);
218
219     /* Get the printer driver info */
220     if (wStyle == INITPDEVICE)
221         pLPD = FindPrinterDriverFromPDEVICE((SEGPTR)lpDevInfo);
222     else
223         pLPD = FindPrinterDriverFromName((char *)lpDeviceName);
224     if (pLPD != NULL) {
225         LONG            lP5;
226         DeviceCaps      *lP1;
227         LPSTR           lP3,lP4;
228         WORD            wP2;
229
230         if (!pLPD->fn[FUNC_ENABLE]) {
231             WARN(win16drv, "Not supported by driver\n");
232             return 0;
233         }
234
235         if (wStyle == INITPDEVICE)
236             lP1 = (DeviceCaps*)lpDevInfo;/* 16 bit segmented ptr already */
237         else
238             lP1 = SEGPTR_NEW(DeviceCaps);
239         
240         wP2 = wStyle;
241         
242         /* SEGPTR_STRDUP handles NULL like a charm ... */
243         lP3 = SEGPTR_STRDUP(lpDestDevType);
244         lP4 = SEGPTR_STRDUP(lpOutputFile);
245         lP5 = (LONG)lpData;
246         
247         wRet = Callbacks->CallDrvEnableProc(pLPD->fn[FUNC_ENABLE], 
248                              (wStyle==INITPDEVICE)?(SEGPTR)lP1:SEGPTR_GET(lP1),
249                              wP2,
250                              SEGPTR_GET(lP3),
251                              SEGPTR_GET(lP4),
252                              lP5);
253         SEGPTR_FREE(lP3);
254         SEGPTR_FREE(lP4);
255
256         /* Get the data back */
257         if (lP1 != 0 && wStyle != INITPDEVICE) {
258             memcpy(lpDevInfo,lP1,sizeof(DeviceCaps));
259             SEGPTR_FREE(lP1);
260         }
261     }
262     TRACE(win16drv, "return %x\n", wRet);
263     return wRet;
264 }
265
266
267 /*
268  *      EnumDFonts (ordinal 6)
269  */
270 WORD PRTDRV_EnumDFonts(LPPDEVICE lpDestDev, LPSTR lpFaceName,  
271                        FARPROC16 lpCallbackFunc, LPVOID lpClientData)
272 {
273     WORD wRet = 0;
274     LOADED_PRINTER_DRIVER *pLPD = NULL;
275
276     TRACE(win16drv, "%08lx %s %p %p\n",
277                      lpDestDev, lpFaceName, lpCallbackFunc, lpClientData);
278
279     if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
280     {
281         LONG lP1, lP4;
282         LPBYTE lP2;
283
284         if (pLPD->fn[FUNC_ENUMDFONTS] == NULL) {
285             WARN(win16drv, "Not supported by driver\n");
286             return 0;
287         }
288
289         lP1 = (SEGPTR)lpDestDev;
290         if(lpFaceName)
291             lP2 = SEGPTR_STRDUP(lpFaceName);
292         else
293             lP2 = NULL;
294         lP4 = (LONG)lpClientData;
295         wRet = Callbacks->CallDrvEnumDFontsProc( pLPD->fn[FUNC_ENUMDFONTS], 
296                                 lP1, SEGPTR_GET(lP2), lpCallbackFunc, lP4);
297         if(lpFaceName)
298             SEGPTR_FREE(lP2);
299     } else 
300         WARN(win16drv,"Failed to find device\n");
301     
302     TRACE(win16drv, "return %x\n", wRet);
303     return wRet;
304 }
305 /*
306  *      EnumObj (ordinal 7)
307  */
308 BOOL16 PRTDRV_EnumObj(LPPDEVICE lpDestDev, WORD iStyle, 
309                        FARPROC16 lpCallbackFunc, LPVOID lpClientData)
310 {
311     WORD wRet = 0;
312     LOADED_PRINTER_DRIVER *pLPD = NULL;
313
314     TRACE(win16drv, "(some params - fixme)\n");
315
316     if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
317     {
318         LONG lP1, lP4;
319         FARPROC16 lP3;
320         WORD wP2;
321
322         if (pLPD->fn[FUNC_ENUMOBJ] == NULL)
323         {
324             WARN(win16drv, "Not supported by driver\n");
325             return 0;
326         }
327
328         lP1 = (SEGPTR)lpDestDev;
329         
330         wP2 = iStyle;
331
332         /* 
333          * Need to pass addres of function conversion function that will switch back to 32 bit code if necessary
334          */
335         lP3 = (FARPROC16)lpCallbackFunc; 
336
337         lP4 = (LONG)lpClientData;
338         
339         wRet = Callbacks->CallDrvEnumObjProc( pLPD->fn[FUNC_ENUMOBJ], 
340                                               lP1, wP2, lP3, lP4 );
341     }
342     else 
343         WARN(win16drv,"Failed to find device\n");
344     
345     TRACE(win16drv, "return %x\n", wRet);
346     return wRet;
347 }
348
349 /*
350  *      Output (ordinal 8)
351  */
352 WORD PRTDRV_Output(LPPDEVICE     lpDestDev,
353                    WORD          wStyle, 
354                    WORD          wCount,
355                    POINT16      *points, 
356                    LPLOGPEN16    lpPen,
357                    LPLOGBRUSH16  lpBrush,
358                    SEGPTR        lpDrawMode,
359                    HRGN          hClipRgn)
360 {
361     WORD wRet = 0;
362     LOADED_PRINTER_DRIVER *pLPD = NULL;
363     
364     TRACE(win16drv, "PRTDRV_OUTPUT %d\n", wStyle );
365     
366     if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
367     {
368         LONG lP1, lP5, lP6, lP7;
369         LPPOINT16 lP4;
370         LPRECT16 lP8;
371         WORD wP2, wP3;
372         int   nSize;
373         if (pLPD->fn[FUNC_OUTPUT] == NULL)
374         {
375             WARN(win16drv, "Not supported by driver\n");
376             return 0;
377         }
378
379         lP1 = lpDestDev;
380         wP2 = wStyle;
381         wP3 = wCount;
382         nSize = sizeof(POINT16) * wCount;
383         lP4 = (LPPOINT16 )SEGPTR_ALLOC(nSize);
384         memcpy(lP4,points,nSize);
385         lP5 = SEGPTR_GET( lpPen );
386         lP6 = SEGPTR_GET( lpBrush );
387         lP7 = lpDrawMode;
388         
389         if (hClipRgn)
390         {
391             DWORD size;
392             RGNDATA *clip;
393
394             size = GetRegionData( hClipRgn, 0, NULL );
395             clip = HeapAlloc( SystemHeap, 0, size );
396             if(!clip) 
397             {
398                 WARN(win16drv, "Can't alloc clip array in PRTDRV_Output\n");
399                 return FALSE;
400             }
401             GetRegionData( hClipRgn, size, clip );
402             if( clip->rdh.nCount == 0 )
403             {
404                 wRet = Callbacks->CallDrvOutputProc(pLPD->fn[FUNC_OUTPUT], 
405                                             lP1, wP2, wP3, SEGPTR_GET(lP4),
406                                             lP5, lP6, lP7, (SEGPTR) NULL);
407             }
408             else
409             {
410                 RECT *pRect;
411                 lP8 = SEGPTR_NEW(RECT16);
412             
413                 for(pRect = (RECT *)clip->Buffer; 
414                     pRect < (RECT *)clip->Buffer + clip->rdh.nCount; pRect++)
415                 {
416                     CONV_RECT32TO16( pRect, lP8 );
417
418                     TRACE(win16drv, "rect = %d,%d - %d,%d\n",
419                             lP8->left, lP8->top, lP8->right, lP8->bottom );
420                     wRet = Callbacks->CallDrvOutputProc(pLPD->fn[FUNC_OUTPUT], 
421                                             lP1, wP2, wP3, SEGPTR_GET(lP4),
422                                             lP5, lP6, lP7, SEGPTR_GET(lP8));
423                 }
424                 SEGPTR_FREE(lP8);
425             }
426             HeapFree( SystemHeap, 0, clip );
427         }
428         else
429         {
430             wRet = Callbacks->CallDrvOutputProc(pLPD->fn[FUNC_OUTPUT], 
431                                             lP1, wP2, wP3, SEGPTR_GET(lP4),
432                                             lP5, lP6, lP7, (SEGPTR) NULL);
433         }
434         SEGPTR_FREE(lP4);
435     }
436     TRACE(win16drv, "PRTDRV_Output return %d\n", wRet);
437     return wRet;
438 }
439
440 /* 
441  * RealizeObject (ordinal 10)
442  */
443 DWORD PRTDRV_RealizeObject(LPPDEVICE lpDestDev, WORD wStyle, 
444                            LPVOID lpInObj, LPVOID lpOutObj,
445                            SEGPTR lpTextXForm)
446 {
447     WORD dwRet = 0;
448     LOADED_PRINTER_DRIVER *pLPD = NULL;
449     
450     TRACE(win16drv, "%08lx %04x %p %p %08lx\n",
451                  lpDestDev, wStyle, lpInObj, lpOutObj, lpTextXForm);
452     
453     if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
454     {
455         LONG lP1, lP3, lP4, lP5;  
456         WORD wP2;
457         LPBYTE lpBuf = NULL;
458         unsigned int    nSize;
459
460         if (pLPD->fn[FUNC_REALIZEOBJECT] == NULL)
461         {
462             WARN(win16drv, "Not supported by driver\n");
463             return 0;
464         }
465
466         lP1 = lpDestDev;
467         wP2 = wStyle;
468         
469         switch ((INT16)wStyle)
470         {
471         case DRVOBJ_BRUSH:
472             nSize = sizeof (LOGBRUSH16);
473             break;
474         case DRVOBJ_FONT: 
475             nSize = sizeof(LOGFONT16); 
476             break;
477         case DRVOBJ_PEN:
478             nSize = sizeof(LOGPEN16); 
479             break;
480
481         case -DRVOBJ_BRUSH:
482         case -DRVOBJ_FONT: 
483         case -DRVOBJ_PEN:
484             nSize = -1;
485             break;
486
487         case DRVOBJ_PBITMAP:
488         default:
489             WARN(win16drv, "Object type %d not supported\n", wStyle);
490             nSize = 0;
491             
492         }
493
494         if(nSize != -1)
495         {
496             lpBuf = SEGPTR_ALLOC(nSize);
497             memcpy(lpBuf, lpInObj, nSize);
498             lP3 = SEGPTR_GET(lpBuf);
499         } 
500         else
501             lP3 = SEGPTR_GET( lpInObj );
502
503         lP4 = SEGPTR_GET( lpOutObj );
504
505         lP5 = lpTextXForm;
506         TRACE(win16drv, "Calling Realize %08lx %04x %08lx %08lx %08lx\n",
507                      lP1, wP2, lP3, lP4, lP5);
508         dwRet = Callbacks->CallDrvRealizeProc(pLPD->fn[FUNC_REALIZEOBJECT], 
509                                               lP1, wP2, lP3, lP4, lP5);
510         if(lpBuf)
511             SEGPTR_FREE(lpBuf);
512
513     }
514     TRACE(win16drv, "return %x\n", dwRet);
515     return dwRet;
516 }
517
518 /* 
519  * StretchBlt (ordinal 27)
520  */
521 DWORD PRTDRV_StretchBlt(LPPDEVICE lpDestDev,
522                         WORD wDestX, WORD wDestY,
523                         WORD wDestXext, WORD wDestYext, 
524                         LPPDEVICE lpSrcDev,
525                         WORD wSrcX, WORD wSrcY,
526                         WORD wSrcXext, WORD wSrcYext, 
527                         DWORD Rop3,
528                         LPLOGBRUSH16 lpBrush,
529                         SEGPTR lpDrawMode,
530                         RECT16 *lpClipRect)
531 {
532     WORD wRet = 0;
533     LOADED_PRINTER_DRIVER *pLPD = NULL;
534     
535     TRACE(win16drv, "(lots of params - fixme)\n");
536     
537     if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
538     {
539         LONG lP1,lP6, lP11, lP12, lP13;
540         LPRECT16 lP14;
541         WORD wP2, wP3, wP4, wP5, wP7, wP8, wP9, wP10;
542
543         if (pLPD->fn[FUNC_STRETCHBLT] == NULL)
544         {
545             WARN(win16drv, "Not supported by driver\n");
546             return 0;
547         }
548         lP1  = lpDestDev;
549         wP2  = wDestX;
550         wP3  = wDestY;
551         wP4  = wDestXext;
552         wP5  = wDestYext;
553         lP6  = lpSrcDev;
554         wP7  = wSrcX;
555         wP8  = wSrcY;
556         wP9  = wSrcXext;
557         wP10 = wSrcYext;
558         lP11 = Rop3;
559         lP12 = SEGPTR_GET( lpBrush );
560         lP13 = lpDrawMode;
561         if (lpClipRect != NULL)
562         {
563             lP14 = SEGPTR_NEW(RECT16);
564             memcpy(lP14,lpClipRect,sizeof(RECT16));
565
566         }
567         else
568           lP14 = 0L;
569         wRet = Callbacks->CallDrvStretchBltProc(pLPD->fn[FUNC_STRETCHBLT], 
570                                                 lP1, wP2, wP3, wP4, wP5,
571                                                 lP6, wP7, wP8, wP9, wP10, 
572                                                 lP11, lP12, lP13,
573                                                 SEGPTR_GET(lP14));
574         SEGPTR_FREE(lP14);
575         TRACE(win16drv, "Called StretchBlt ret %d\n",wRet);
576     }
577     return wRet;
578 }
579
580 DWORD PRTDRV_ExtTextOut(LPPDEVICE lpDestDev, WORD wDestXOrg, WORD wDestYOrg,
581                         RECT16 *lpClipRect, LPCSTR lpString, WORD wCount, 
582                         LPFONTINFO16 lpFontInfo, SEGPTR lpDrawMode, 
583                         SEGPTR lpTextXForm, SHORT *lpCharWidths,
584                         RECT16 *     lpOpaqueRect, WORD wOptions)
585 {
586     DWORD dwRet = 0;
587     LOADED_PRINTER_DRIVER *pLPD = NULL;
588     
589     TRACE(win16drv, "(lots of params - fixme)\n");
590     
591     if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
592     {
593         LONG            lP1, lP7, lP8, lP9, lP10;  
594         LPSTR           lP5;
595         LPRECT16        lP4,lP11;
596         WORD            wP2, wP3, wP12;
597         INT16           iP6;
598         unsigned int    nSize = -1;
599
600         if (pLPD->fn[FUNC_EXTTEXTOUT] == NULL)
601         {
602             WARN(win16drv, "Not supported by driver\n");
603             return 0;
604         }
605
606         lP1 = lpDestDev;
607         wP2 = wDestXOrg;
608         wP3 = wDestYOrg;
609         
610         if (lpClipRect != NULL) {
611             lP4 = SEGPTR_NEW(RECT16);
612             TRACE(win16drv, "Adding lpClipRect\n");
613             memcpy(lP4,lpClipRect,sizeof(RECT16));
614         } else
615           lP4 = 0L;
616
617         if (lpString != NULL) {
618             nSize = strlen(lpString);
619             if (nSize>abs(wCount))
620                 nSize = abs(wCount);
621             lP5 = SEGPTR_ALLOC(nSize+1);
622             TRACE(win16drv, "Adding lpString (nSize is %d)\n",nSize);
623             memcpy(lP5,lpString,nSize);
624             *((char *)lP5 + nSize) = '\0';
625         } else
626           lP5 = 0L;
627         
628         iP6 = wCount;
629         
630         /* This should be realized by the driver, so in 16bit data area */
631         lP7 = SEGPTR_GET( lpFontInfo );
632         lP8 = lpDrawMode;
633         lP9 = lpTextXForm;
634         
635         if (lpCharWidths != NULL) 
636           FIXME(win16drv, "Char widths not supported\n");
637         lP10 = 0;
638         
639         if (lpOpaqueRect != NULL) {
640             lP11 = SEGPTR_NEW(RECT16);
641             TRACE(win16drv, "Adding lpOpaqueRect\n");
642             memcpy(lP11,lpOpaqueRect,sizeof(RECT16));   
643         } else
644           lP11 = 0L;
645         
646         wP12 = wOptions;
647         TRACE(win16drv, "Calling ExtTextOut 0x%lx 0x%x 0x%x %p\n",
648                      lP1, wP2, wP3, lP4);
649         TRACE(win16drv, "%*s 0x%x 0x%lx 0x%lx\n",
650                      nSize,lP5, iP6, lP7, lP8);
651         TRACE(win16drv, "0x%lx 0x%lx %p 0x%x\n",
652                      lP9, lP10, lP11, wP12);
653         dwRet = Callbacks->CallDrvExtTextOutProc(pLPD->fn[FUNC_EXTTEXTOUT], 
654                                                  lP1, wP2, wP3,
655                                                  SEGPTR_GET(lP4),
656                                                  SEGPTR_GET(lP5), iP6, lP7,
657                                                  lP8, lP9, lP10,
658                                                  SEGPTR_GET(lP11), wP12);
659     }
660     TRACE(win16drv, "return %lx\n", dwRet);
661     return dwRet;
662 }
663
664 int WINAPI dmEnumDFonts16(LPPDEVICE lpDestDev, LPSTR lpFaceName, FARPROC16 lpCallbackFunc, LPVOID lpClientData)
665 {
666         /* Windows 3.1 just returns 1 */
667         return 1;
668 }
669
670 int WINAPI dmRealizeObject16(LPPDEVICE lpDestDev, INT16 wStyle, LPSTR lpInObj, LPSTR lpOutObj, SEGPTR lpTextXForm)
671 {
672     FIXME(win16drv, "(lpDestDev=%08x,wStyle=%04x,lpInObj=%08x,lpOutObj=%08x,lpTextXForm=%08x): stub\n",
673         (UINT)lpDestDev, wStyle, (UINT)lpInObj, (UINT)lpOutObj, (UINT)lpTextXForm);
674     if (wStyle < 0) { /* Free extra memory of given object's structure */
675         switch ( -wStyle ) {
676             case DRVOBJ_PEN:    {
677                                 /* LPLOGPEN16 DeletePen = (LPLOGPEN16)lpInObj; */
678
679                                 TRACE(win16drv, "DRVOBJ_PEN_delete\n");
680                                 break;
681                                 }
682             case DRVOBJ_BRUSH:  {
683                                 TRACE(win16drv, "DRVOBJ_BRUSH_delete\n");
684                                 break;
685                                 }
686             case DRVOBJ_FONT:   {
687                                 /* LPTEXTXFORM16 TextXForm
688                                         = (LPTEXTXFORM16)lpTextXForm; */
689                                 TRACE(win16drv, "DRVOBJ_FONT_delete\n");
690                                 break;
691                                 }
692             case DRVOBJ_PBITMAP:        TRACE(win16drv, "DRVOBJ_PBITMAP_delete\n");
693                                 break;
694         }
695     }
696     else { /* Realize given object */
697
698         switch (wStyle) {
699             case DRVOBJ_PEN: {
700                                 LPLOGPEN16 InPen  = (LPLOGPEN16)lpInObj;
701
702                                 TRACE(win16drv, "DRVOBJ_PEN\n");
703                                 if (lpOutObj) {
704                                     if (InPen->lopnStyle == PS_NULL) {
705                                         *(DWORD *)lpOutObj = 0;
706                                         *(WORD *)(lpOutObj+4) = InPen->lopnStyle;
707                                     }
708                                     else
709                                     if ((InPen->lopnWidth.x > 1) || (InPen->lopnStyle > PS_NULL) ) {
710                                         *(DWORD *)lpOutObj = InPen->lopnColor;
711                                         *(WORD *)(lpOutObj+4) = 0;
712                                     }
713                                     else {
714                                         *(DWORD *)lpOutObj = InPen->lopnColor & 0xffff0000;
715                                         *(WORD *)(lpOutObj+4) = InPen->lopnStyle;
716                                     }
717                                 }
718                                 return sizeof(LOGPEN16);
719                              }
720             case DRVOBJ_BRUSH: {
721                                 LPLOGBRUSH16 InBrush  = (LPLOGBRUSH16)lpInObj;
722                                 LPLOGBRUSH16 OutBrush = (LPLOGBRUSH16)lpOutObj;
723                                 /* LPPOINT16 Point = (LPPOINT16)lpTextXForm; */
724
725                                 TRACE(win16drv, "DRVOBJ_BRUSH\n");
726                                 if (!lpOutObj) return sizeof(LOGBRUSH16);
727                                 else {
728                                     OutBrush->lbStyle = InBrush->lbStyle;
729                                     OutBrush->lbColor = InBrush->lbColor;
730                                     OutBrush->lbHatch = InBrush->lbHatch;
731                                     if (InBrush->lbStyle == BS_SOLID) 
732                                     return 0x8002; /* FIXME: diff mono-color */
733                                     else return 0x8000;
734                                 }
735                                }
736             case DRVOBJ_FONT: {
737                                 /* LPTEXTXFORM16 TextXForm
738                                         = (LPTEXTXFORM16)lpTextXForm; */
739                                 TRACE(win16drv, "DRVOBJ_FONT\n");
740                                 return 0;/* DISPLAY.DRV doesn't realize fonts */
741                               }
742             case DRVOBJ_PBITMAP:        TRACE(win16drv, "DRVOBJ_PBITMAP\n");
743                                         return 0; /* create memory bitmap */
744         }
745     }
746     return 1;
747 }
748
749
750 WORD PRTDRV_GetCharWidth(LPPDEVICE lpDestDev, LPINT lpBuffer, 
751                       WORD wFirstChar, WORD wLastChar, LPFONTINFO16 lpFontInfo,
752                       SEGPTR lpDrawMode, SEGPTR lpTextXForm )
753 {
754
755     WORD wRet = 0;
756     LOADED_PRINTER_DRIVER *pLPD = NULL;
757     
758     TRACE(win16drv, "(lots of params - fixme)\n");
759     
760     if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
761     {
762         LONG            lP1, lP5, lP6, lP7;  
763         LPWORD          lP2;
764         WORD            wP3, wP4, i;
765         
766         if (pLPD->fn[FUNC_GETCHARWIDTH] == NULL)
767         {
768             WARN(win16drv, "Not supported by driver\n");
769             return 0;
770         }
771
772         lP1 = lpDestDev;
773         lP2 = SEGPTR_ALLOC( (wLastChar - wFirstChar + 1) * sizeof(WORD) );
774         wP3 = wFirstChar;
775         wP4 = wLastChar;
776         lP5 = SEGPTR_GET( lpFontInfo );
777         lP6 = lpDrawMode;
778         lP7 = lpTextXForm;
779         
780         wRet = Callbacks->CallDrvGetCharWidthProc(pLPD->fn[FUNC_GETCHARWIDTH], 
781                                                  lP1, SEGPTR_GET(lP2), wP3,
782                                                  wP4, lP5, lP6, lP7 );
783
784         for(i = 0; i <= wLastChar - wFirstChar; i++)
785             lpBuffer[i] = (INT) lP2[i];
786
787         SEGPTR_FREE(lP2);
788     }
789     return wRet;
790 }