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