Release 961222
[wine/multimedia.git] / graphics / win16drv / init.c
blob8d05cda6b8e06eafbd27f8d82dd0d47458b26dda
1 /*
2 * Windows Device Context initialisation functions
4 * Copyright 1996 John Harvey
5 */
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 "windows.h"
14 #include "module.h"
15 #include "win16drv.h"
16 #include "gdi.h"
17 #include "bitmap.h"
18 #include "heap.h"
19 #include "color.h"
20 #include "font.h"
21 #include "callback.h"
22 #include "stddebug.h"
23 #include "debug.h"
25 #define SUPPORT_REALIZED_FONTS 1
26 typedef SEGPTR LPPDEVICE;
29 #if 0
30 static BOOL16 windrvExtTextOut16( DC *dc, INT16 x, INT16 y, UINT16 flags, const RECT16 * lprect,
31 LPCSTR str, UINT16 count, const INT16 *lpDx);
32 #endif
34 static BOOL32 WIN16DRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device,
35 LPCSTR output, const DEVMODE16* initData );
36 static INT32 WIN16DRV_Escape( DC *dc, INT32 nEscape, INT32 cbInput,
37 SEGPTR lpInData, SEGPTR lpOutData );
39 static const DC_FUNCTIONS WIN16DRV_Funcs =
41 NULL, /* pArc */
42 NULL, /* pBitBlt */
43 NULL, /* pChord */
44 WIN16DRV_CreateDC, /* pCreateDC */
45 NULL, /* pDeleteDC */
46 NULL, /* pDeleteObject */
47 NULL, /* pEllipse */
48 WIN16DRV_Escape, /* pEscape */
49 NULL, /* pExcludeClipRect */
50 NULL, /* pExcludeVisRect */
51 NULL, /* pExtFloodFill */
52 NULL, /* pExtTextOut */
53 NULL, /* pFillRgn */
54 NULL, /* pFloodFill */
55 NULL, /* pFrameRgn */
56 WIN16DRV_GetTextExtentPoint, /* pGetTextExtentPoint */
57 WIN16DRV_GetTextMetrics, /* pGetTextMetrics */
58 NULL, /* pIntersectClipRect */
59 NULL, /* pIntersectVisRect */
60 NULL, /* pInvertRgn */
61 NULL, /* pLineTo */
62 NULL, /* pMoveToEx */
63 NULL, /* pOffsetClipRgn */
64 NULL, /* pOffsetViewportOrg (optional) */
65 NULL, /* pOffsetWindowOrg (optional) */
66 NULL, /* pPaintRgn */
67 NULL, /* pPatBlt */
68 NULL, /* pPie */
69 NULL, /* pPolyPolygon */
70 NULL, /* pPolygon */
71 NULL, /* pPolyline */
72 NULL, /* pRealizePalette */
73 NULL, /* pRectangle */
74 NULL, /* pRestoreDC */
75 NULL, /* pRoundRect */
76 NULL, /* pSaveDC */
77 NULL, /* pScaleViewportExt (optional) */
78 NULL, /* pScaleWindowExt (optional) */
79 NULL, /* pSelectClipRgn */
80 NULL, /* pSelectObject */
81 NULL, /* pSelectPalette */
82 NULL, /* pSetBkColor */
83 NULL, /* pSetBkMode */
84 NULL, /* pSetDeviceClipping */
85 NULL, /* pSetDIBitsToDevice */
86 NULL, /* pSetMapMode (optional) */
87 NULL, /* pSetMapperFlags */
88 NULL, /* pSetPixel */
89 NULL, /* pSetPolyFillMode */
90 NULL, /* pSetROP2 */
91 NULL, /* pSetRelAbs */
92 NULL, /* pSetStretchBltMode */
93 NULL, /* pSetTextAlign */
94 NULL, /* pSetTextCharacterExtra */
95 NULL, /* pSetTextColor */
96 NULL, /* pSetTextJustification */
97 NULL, /* pSetViewportExt (optional) */
98 NULL, /* pSetViewportOrg (optional) */
99 NULL, /* pSetWindowExt (optional) */
100 NULL, /* pSetWindowOrg (optional) */
101 NULL, /* pStretchBlt */
102 NULL, /* pStretchDIBits */
103 NULL /* pTextOut */
107 #define MAX_PRINTER_DRIVERS 16
109 static LOADED_PRINTER_DRIVER *gapLoadedPrinterDrivers[MAX_PRINTER_DRIVERS];
112 /**********************************************************************
113 * WIN16DRV_Init
115 BOOL32 WIN16DRV_Init(void)
117 return DRIVER_RegisterDriver( NULL /* generic driver */, &WIN16DRV_Funcs );
121 /* Tempory functions, for initialising structures */
122 /* These values should be calculated, not hardcoded */
123 void InitTextXForm(LPTEXTXFORM lpTextXForm)
125 lpTextXForm->txfHeight = 0x0001;
126 lpTextXForm->txfWidth = 0x000c;
127 lpTextXForm->txfEscapement = 0x0000;
128 lpTextXForm->txfOrientation = 0x0000;
129 lpTextXForm->txfWeight = 0x0190;
130 lpTextXForm->txfItalic = 0x00;
131 lpTextXForm->txfUnderline = 0x00;
132 lpTextXForm->txfStrikeOut = 0x00;
133 lpTextXForm->txfOutPrecision = 0x02;
134 lpTextXForm->txfClipPrecision = 0x01;
135 lpTextXForm->txfAccelerator = 0x0001;
136 lpTextXForm->txfOverhang = 0x0000;
140 void InitDrawMode(LPDRAWMODE lpDrawMode)
142 lpDrawMode->Rop2 = 0x000d;
143 lpDrawMode->bkMode = 0x0001;
144 lpDrawMode->bkColor = 0x3fffffff;
145 lpDrawMode->TextColor = 0x20000000;
146 lpDrawMode->TBreakExtra = 0x0000;
147 lpDrawMode->BreakExtra = 0x0000;
148 lpDrawMode->BreakErr = 0x0000;
149 lpDrawMode->BreakRem = 0x0000;
150 lpDrawMode->BreakCount = 0x0000;
151 lpDrawMode->CharExtra = 0x0000;
152 lpDrawMode->LbkColor = 0x00ffffff;
153 lpDrawMode->LTextColor = 0x00000000;
156 * Thunking utility functions
159 static BOOL32 AddData(SEGPTR *pSegPtr, const void *pData, int nSize, SEGPTR Limit)
161 BOOL32 bRet = FALSE;
162 char *pBuffer = PTR_SEG_TO_LIN((*pSegPtr));
163 char *pLimit = PTR_SEG_TO_LIN(Limit);
166 if ((pBuffer + nSize) < pLimit)
168 DWORD *pdw = (DWORD *)pSegPtr;
169 SEGPTR SegPtrOld = *pSegPtr;
170 SEGPTR SegPtrNew;
172 dprintf_win16drv(stddeb, "AddData: Copying %d from %p to %p(0x%x)\n", nSize, pData, pBuffer, (UINT32)*pSegPtr);
173 memcpy(pBuffer, pData, nSize);
174 SegPtrNew = (SegPtrOld + nSize + 1);
175 *pdw = (DWORD)SegPtrNew;
177 return bRet;
181 static BOOL32 GetParamData(SEGPTR SegPtrSrc,void *pDataDest, int nSize)
183 char *pSrc = PTR_SEG_TO_LIN(SegPtrSrc);
184 char *pDest = pDataDest;
186 dprintf_win16drv(stddeb, "GetParamData: Copying %d from %lx(%lx) to %lx\n", nSize, (DWORD)pSrc, (DWORD)SegPtrSrc, (DWORD)pDataDest);
187 memcpy(pDest, pSrc, nSize);
188 return TRUE;
192 static void GetPrinterDriverFunctions(HINSTANCE16 hInst, LOADED_PRINTER_DRIVER *pLPD)
194 #define LoadPrinterDrvFunc(A,B) pLPD->fn[A] = \
195 GetProcAddress16(hInst, MAKEINTRESOURCE(B))
197 LoadPrinterDrvFunc(FUNC_CONTROL, ORD_CONTROL); /* 3 */
198 LoadPrinterDrvFunc(FUNC_ENABLE, ORD_ENABLE); /* 5 */
199 LoadPrinterDrvFunc(FUNC_ENUMDFONTS, ORD_ENUMDFONTS); /* 6 */
200 LoadPrinterDrvFunc(FUNC_REALIZEOBJECT, ORD_REALIZEOBJECT);/* 10 */
201 LoadPrinterDrvFunc(FUNC_EXTTEXTOUT, ORD_EXTTEXTOUT); /* 14 */
202 dprintf_win16drv (stddeb,"got func CONTROL 0x%p enable 0x%p enumDfonts 0x%p realizeobject 0x%p extextout 0x%p\n",
203 pLPD->fn[FUNC_CONTROL],
204 pLPD->fn[FUNC_ENABLE],
205 pLPD->fn[FUNC_ENUMDFONTS],
206 pLPD->fn[FUNC_REALIZEOBJECT],
207 pLPD->fn[FUNC_EXTTEXTOUT]);
212 static LOADED_PRINTER_DRIVER *FindPrinterDriverFromPDEVICE(SEGPTR segptrPDEVICE)
214 LOADED_PRINTER_DRIVER *pLPD = NULL;
216 /* Find the printer driver associated with this PDEVICE */
217 /* Each of the PDEVICE structures has a PDEVICE_HEADER structure */
218 /* just before it */
219 if (segptrPDEVICE != (SEGPTR)NULL)
221 PDEVICE_HEADER *pPDH = (PDEVICE_HEADER *)
222 (PTR_SEG_TO_LIN(segptrPDEVICE) - sizeof(PDEVICE_HEADER));
223 pLPD = pPDH->pLPD;
225 return pLPD;
228 static LOADED_PRINTER_DRIVER *FindPrinterDriverFromName(const char *pszDriver)
230 LOADED_PRINTER_DRIVER *pLPD = NULL;
231 int nDriverSlot = 0;
233 /* Look to see if the printer driver is already loaded */
234 while (pLPD == NULL && nDriverSlot < MAX_PRINTER_DRIVERS)
236 LOADED_PRINTER_DRIVER *ptmpLPD;
237 ptmpLPD = gapLoadedPrinterDrivers[nDriverSlot++];
238 if (ptmpLPD != NULL)
240 dprintf_win16drv(stddeb, "Comparing %s,%s\n",ptmpLPD->szDriver,pszDriver);
241 /* Found driver store info, exit loop */
242 if (lstrcmpi32A(ptmpLPD->szDriver, pszDriver) == 0)
243 pLPD = ptmpLPD;
246 if (pLPD == NULL) printf("Couldn't find driver %s\n", pszDriver);
247 return pLPD;
250 * Load a printer driver, adding it self to the list of loaded drivers.
253 static LOADED_PRINTER_DRIVER *LoadPrinterDriver(const char *pszDriver)
255 HINSTANCE16 hInst;
256 LOADED_PRINTER_DRIVER *pLPD = NULL;
257 int nDriverSlot = 0;
258 BOOL32 bSlotFound = FALSE;
260 /* First look to see if driver is loaded */
261 pLPD = FindPrinterDriverFromName(pszDriver);
262 if (pLPD != NULL)
264 /* Already loaded so increase usage count */
265 pLPD->nUsageCount++;
266 return pLPD;
269 /* Not loaded so try and find an empty slot */
270 while (!bSlotFound && nDriverSlot < MAX_PRINTER_DRIVERS)
272 if (gapLoadedPrinterDrivers[nDriverSlot] == NULL)
273 bSlotFound = TRUE;
274 else
275 nDriverSlot++;
277 if (!bSlotFound)
279 printf("Too many printers drivers loaded\n");
280 return NULL;
284 char *drvName = malloc(strlen(pszDriver)+5);
285 strcpy(drvName, pszDriver);
286 strcat(drvName, ".DRV");
287 hInst = LoadLibrary16(drvName);
289 dprintf_win16drv(stddeb, "Loaded the library\n");
292 if (hInst <= 32)
294 /* Failed to load driver */
295 fprintf(stderr, "Failed to load printer driver %s\n", pszDriver);
297 else
299 HANDLE16 hHandle;
301 /* Allocate some memory for printer driver info */
302 pLPD = malloc(sizeof(LOADED_PRINTER_DRIVER));
303 memset(pLPD, 0 , sizeof(LOADED_PRINTER_DRIVER));
305 pLPD->hInst = hInst;
306 strcpy(pLPD->szDriver,pszDriver);
308 /* Get DS for the printer module */
309 pLPD->ds_reg = hInst;
311 dprintf_win16drv(stddeb, "DS for %s is %x\n", pszDriver, pLPD->ds_reg);
313 /* Get address of printer driver functions */
314 GetPrinterDriverFunctions(hInst, pLPD);
316 /* Set initial usage count */
317 pLPD->nUsageCount = 1;
319 /* Create a thunking buffer */
320 hHandle = GlobalAlloc16(GHND, (1024 * 8));
321 pLPD->hThunk = hHandle;
322 pLPD->ThunkBufSegPtr = WIN16_GlobalLock16(hHandle);
323 pLPD->ThunkBufLimit = pLPD->ThunkBufSegPtr + (1024*8);
325 /* Update table of loaded printer drivers */
326 pLPD->nIndex = nDriverSlot;
327 gapLoadedPrinterDrivers[nDriverSlot] = pLPD;
330 return pLPD;
333 * Control (ordinal 3)
335 INT16 PRTDRV_Control(LPPDEVICE lpDestDev, WORD wfunction, SEGPTR lpInData, SEGPTR lpOutData)
337 /* wfunction == Escape code */
338 /* lpInData, lpOutData depend on code */
340 WORD wRet = 0;
341 LOADED_PRINTER_DRIVER *pLPD = NULL;
343 dprintf_win16drv(stddeb, "PRTDRV_Control: %08x 0x%x %08lx %08lx\n", (unsigned int)lpDestDev, wfunction, lpInData, lpOutData);
345 if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
347 LONG lP1, lP3, lP4;
348 WORD wP2;
350 if (pLPD->fn[FUNC_CONTROL] == NULL)
352 dprintf_win16drv(stddeb, "PRTDRV_Control: Not supported by driver\n");
353 return 0;
356 lP1 = (SEGPTR)lpDestDev;
357 wP2 = wfunction;
358 lP3 = (SEGPTR)lpInData;
359 lP4 = (SEGPTR)lpOutData;
361 wRet = CallTo16_word_lwll(pLPD->fn[FUNC_CONTROL],
362 lP1, wP2, lP3, lP4);
364 dprintf_win16drv(stddeb, "PRTDRV_Control: return %x\n", wRet);
365 return wRet;
367 return 0;
371 * Enable (ordinal 5)
373 static WORD PRTDRV_Enable(LPVOID lpDevInfo, WORD wStyle, LPCSTR lpDestDevType,
374 LPCSTR lpDeviceName, LPCSTR lpOutputFile, LPVOID lpData)
376 WORD wRet = 0;
377 LOADED_PRINTER_DRIVER *pLPD = NULL;
379 dprintf_win16drv(stddeb, "PRTDRV_Enable: %s %s\n",lpDestDevType, lpOutputFile);
381 /* Get the printer driver info */
382 if (wStyle == INITPDEVICE)
384 pLPD = FindPrinterDriverFromPDEVICE((SEGPTR)lpDevInfo);
386 else
388 pLPD = FindPrinterDriverFromName((char *)lpDeviceName);
390 if (pLPD != NULL)
392 LONG lP1, lP3, lP4, lP5;
393 WORD wP2;
394 SEGPTR SegPtr = pLPD->ThunkBufSegPtr;
395 SEGPTR Limit = pLPD->ThunkBufLimit;
396 int nSize;
398 if (pLPD->fn[FUNC_ENABLE] == NULL)
400 dprintf_win16drv(stddeb, "PRTDRV_Enable: Not supported by driver\n");
401 return 0;
404 if (wStyle == INITPDEVICE)
406 /* All ready a 16 address */
407 lP1 = (SEGPTR)lpDevInfo;
409 else
411 /* 32 bit data */
412 lP1 = SegPtr;
413 nSize = sizeof(DeviceCaps);
414 AddData(&SegPtr, lpDevInfo, nSize, Limit);
417 wP2 = wStyle;
419 lP3 = SegPtr;
420 nSize = strlen(lpDestDevType) + 1;
421 AddData(&SegPtr, lpDestDevType, nSize, Limit);
423 lP4 = SegPtr;
424 nSize = strlen(lpOutputFile) + 1;
425 AddData(&SegPtr, lpOutputFile, nSize, Limit);
427 lP5 = (LONG)lpData;
430 wRet = CallTo16_word_lwlll(pLPD->fn[FUNC_ENABLE],
431 lP1, wP2, lP3, lP4, lP5);
433 /* Get the data back */
434 if (lP1 != 0 && wStyle != INITPDEVICE)
436 nSize = sizeof(DeviceCaps);
437 GetParamData(lP1, lpDevInfo, nSize);
440 dprintf_win16drv(stddeb, "PRTDRV_Enable: return %x\n", wRet);
441 return wRet;
446 * EnumCallback (GDI.158)
448 * This is the callback function used when EnumDFonts is called.
449 * (The printer drivers uses it to pass info on available fonts).
451 * lpvClientData is the pointer passed to EnumDFonts, which points to a WEPFC
452 * structure (WEPFC = WINE_ENUM_PRINTER_FONT_CALLBACK). This structure
453 * contains infomation on how to store the data passed .
455 * There are two modes:
456 * 1) Just count the number of fonts available.
457 * 2) Store all font data passed.
459 WORD WineEnumDFontCallback(LPLOGFONT16 lpLogFont, LPTEXTMETRIC16 lpTextMetrics,
460 WORD wFontType, LONG lpvClientData)
462 int wRet = 0;
463 WEPFC *pWEPFC = (WEPFC *)lpvClientData;
465 /* Make sure we have the right structure */
466 if (pWEPFC != NULL )
468 dprintf_win16drv(stddeb, "mode is 0x%x\n",pWEPFC->nMode);
470 switch (pWEPFC->nMode)
472 /* Count how many fonts */
473 case 1:
474 pWEPFC->nCount++;
475 break;
477 /* Store the fonts in the printer driver structure */
478 case 2:
480 PRINTER_FONTS_INFO *pPFI;
482 dprintf_win16drv(stddeb, "WineEnumDFontCallback: Found %s %x\n",
483 lpLogFont->lfFaceName, wFontType);
485 pPFI = &pWEPFC->pLPD->paPrinterFonts[pWEPFC->nCount];
486 memcpy(&(pPFI->lf), lpLogFont, sizeof(LOGFONT16));
487 memcpy(&(pPFI->tm), lpTextMetrics, sizeof(TEXTMETRIC16));
488 pWEPFC->nCount++;
491 break;
493 wRet = 1;
495 dprintf_win16drv(stddeb, "WineEnumDFontCallback: returnd %d\n", wRet);
496 return wRet;
500 * EnumDFonts (ordinal 6)
502 WORD PRTDRV_EnumDFonts(LPPDEVICE lpDestDev, LPSTR lpFaceName,
503 FARPROC16 lpCallbackFunc, LPVOID lpClientData)
505 WORD wRet = 0;
506 LOADED_PRINTER_DRIVER *pLPD = NULL;
508 dprintf_win16drv(stddeb, "PRTDRV_EnumDFonts:\n");
510 if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
512 LONG lP1, lP2, lP3, lP4;
514 SEGPTR SegPtr = pLPD->ThunkBufSegPtr;
515 SEGPTR Limit = pLPD->ThunkBufLimit;
516 int nSize;
518 if (pLPD->fn[FUNC_ENUMDFONTS] == NULL)
520 dprintf_win16drv(stddeb, "PRTDRV_EnumDFonts: Not supported by driver\n");
521 return 0;
524 lP1 = (SEGPTR)lpDestDev;
526 if (lpFaceName == NULL)
528 lP2 = 0;
530 else
532 lP2 = SegPtr;
533 nSize = strlen(lpFaceName) + 1;
534 AddData(&SegPtr, lpFaceName, nSize, Limit);
537 lP3 = (LONG)lpCallbackFunc;
539 lP4 = (LONG)lpClientData;
541 wRet = CallTo16_word_llll(pLPD->fn[FUNC_ENUMDFONTS],
542 lP1, lP2, lP3, lP4);
544 else
545 printf("Failed to find device\n");
547 dprintf_win16drv(stddeb, "PRTDRV_EnumDFonts: return %x\n", wRet);
548 return wRet;
552 * RealizeObject (ordinal 10)
554 DWORD PRTDRV_RealizeObject(LPPDEVICE lpDestDev, WORD wStyle,
555 LPVOID lpInObj, LPVOID lpOutObj,
556 LPTEXTXFORM lpTextXForm)
558 WORD dwRet = 0;
559 LOADED_PRINTER_DRIVER *pLPD = NULL;
561 dprintf_win16drv(stddeb, "PRTDRV_RealizeObject:\n");
563 if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
565 LONG lP1, lP3, lP4, lP5;
566 WORD wP2;
567 SEGPTR SegPtr = pLPD->ThunkBufSegPtr;
568 SEGPTR Limit = pLPD->ThunkBufLimit;
569 int nSize;
571 if (pLPD->fn[FUNC_REALIZEOBJECT] == NULL)
573 dprintf_win16drv(stddeb, "PRTDRV_RealizeObject: Not supported by driver\n");
574 return 0;
577 lP1 = lpDestDev;
578 wP2 = wStyle;
580 lP3 = SegPtr;
581 switch (wStyle)
583 case 3:
584 nSize = sizeof(LOGFONT16);
585 break;
586 default:
587 printf("PRTDRV_RealizeObject: Object type %d not supported\n", wStyle);
588 nSize = 0;
591 AddData(&SegPtr, lpInObj, nSize, Limit);
593 lP4 = (LONG)lpOutObj;
595 if (lpTextXForm != NULL)
597 lP5 = SegPtr;
598 nSize = sizeof(TEXTXFORM);
599 AddData(&SegPtr, lpTextXForm, nSize, Limit);
601 else
602 lP5 = 0L;
604 dwRet = CallTo16_long_lwlll(pLPD->fn[FUNC_REALIZEOBJECT],
605 lP1, wP2, lP3, lP4, lP5);
608 dprintf_win16drv(stddeb, "PRTDRV_RealizeObject: return %x\n", dwRet);
609 return dwRet;
613 BOOL32 WIN16DRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device, LPCSTR output,
614 const DEVMODE16* initData )
616 LOADED_PRINTER_DRIVER *pLPD;
617 WORD wRet;
618 DeviceCaps *printerDevCaps;
619 FARPROC16 pfnCallback;
620 int nPDEVICEsize;
621 PDEVICE_HEADER *pPDH;
622 WIN16DRV_PDEVICE *physDev;
624 /* Realizing fonts */
625 TEXTXFORM TextXForm;
626 int nSize;
627 char printerEnabled[20];
628 PROFILE_GetWineIniString( "wine", "printer", "off",
629 printerEnabled, sizeof(printerEnabled) );
630 if (strcmp(printerEnabled,"on"))
632 printf("WIN16DRV_CreateDC disabled in wine.conf file\n");
633 return FALSE;
636 dprintf_win16drv(stddeb, "In creatdc for (%s,%s,%s) initData 0x%p\n",driver, device, output, initData);
638 physDev = (WIN16DRV_PDEVICE *)HeapAlloc( SystemHeap, 0, sizeof(*physDev) );
639 if (!physDev) return FALSE;
640 dc->physDev = physDev;
642 pLPD = LoadPrinterDriver(driver);
643 if (pLPD == NULL)
645 dprintf_win16drv(stddeb, "LPGDI_CreateDC: Failed to find printer driver\n");
646 HeapFree( SystemHeap, 0, physDev );
647 return FALSE;
649 dprintf_win16drv(stddeb, "windevCreateDC pLPD 0x%p\n", pLPD);
651 /* Now Get the device capabilities from the printer driver */
653 printerDevCaps = (DeviceCaps *) malloc(sizeof(DeviceCaps));
654 memset(printerDevCaps, 0, sizeof(DeviceCaps));
656 /* Get GDIINFO which is the same as a DeviceCaps structure */
657 wRet = PRTDRV_Enable(printerDevCaps, GETGDIINFO, device, driver, output,NULL);
659 /* Add this to the DC */
660 dc->w.devCaps = printerDevCaps;
661 dc->w.hVisRgn = CreateRectRgn32(0, 0, dc->w.devCaps->horzRes, dc->w.devCaps->vertRes);
662 dc->w.bitsPerPixel = dc->w.devCaps->bitsPixel;
664 printf("Got devcaps width %d height %d bits %d planes %d\n",
665 dc->w.devCaps->horzRes,
666 dc->w.devCaps->vertRes,
667 dc->w.devCaps->bitsPixel,
668 dc->w.devCaps->planes);
670 /* Now we allocate enough memory for the PDEVICE structure */
671 /* The size of this varies between printer drivers */
672 /* This PDEVICE is used by the printer DRIVER not by the GDI so must */
673 /* be accessable from 16 bit code */
674 nPDEVICEsize = dc->w.devCaps->pdeviceSize + sizeof(PDEVICE_HEADER);
676 /* TTD Shouldn't really do pointer arithmetic on segment points */
677 physDev->segptrPDEVICE = WIN16_GlobalLock16(GlobalAlloc16(GHND, nPDEVICEsize))+sizeof(PDEVICE_HEADER);
678 *(BYTE *)(PTR_SEG_TO_LIN(physDev->segptrPDEVICE)+0) = 'N';
679 *(BYTE *)(PTR_SEG_TO_LIN(physDev->segptrPDEVICE)+1) = 'B';
681 /* Set up the header */
682 pPDH = (PDEVICE_HEADER *)(PTR_SEG_TO_LIN(physDev->segptrPDEVICE) - sizeof(PDEVICE_HEADER));
683 pPDH->pLPD = pLPD;
685 dprintf_win16drv(stddeb, "PRTDRV_Enable: PDEVICE allocated %08lx\n",(DWORD)(physDev->segptrPDEVICE));
687 /* Now get the printer driver to initialise this data */
688 wRet = PRTDRV_Enable((LPVOID)physDev->segptrPDEVICE, INITPDEVICE, device, driver, output, NULL);
690 /* Now enumerate the fonts supported by the printer driver*/
691 /* GDI.158 is EnumCallback, which is called by the 16bit printer driver */
692 /* passing information on the available fonts */
693 if (pLPD->paPrinterFonts == NULL)
695 pfnCallback = GetProcAddress16(GetModuleHandle("GDI"),
696 (MAKEINTRESOURCE(158)));
698 if (pfnCallback != NULL)
700 WEPFC wepfc;
702 wepfc.nMode = 1;
703 wepfc.nCount = 0;
704 wepfc.pLPD = pLPD;
706 /* First count the number of fonts */
708 PRTDRV_EnumDFonts(physDev->segptrPDEVICE, NULL, pfnCallback,
709 (void *)&wepfc);
711 /* Allocate a buffer to store all of the fonts */
712 pLPD->nPrinterFonts = wepfc.nCount;
713 dprintf_win16drv(stddeb, "Got %d fonts\n",wepfc.nCount);
715 if (wepfc.nCount > 0)
718 pLPD->paPrinterFonts = malloc(sizeof(PRINTER_FONTS_INFO) * wepfc.nCount);
720 /* Now get all of the fonts */
721 wepfc.nMode = 2;
722 wepfc.nCount = 0;
723 PRTDRV_EnumDFonts(physDev->segptrPDEVICE, NULL, pfnCallback,
724 (void *)&wepfc);
729 /* Select the first font into the DC */
730 /* Set up the logfont */
731 memcpy(&physDev->lf,
732 &pLPD->paPrinterFonts[0].lf,
733 sizeof(LOGFONT16));
735 /* Set up the textmetrics */
736 memcpy(&physDev->tm,
737 &pLPD->paPrinterFonts[0].tm,
738 sizeof(TEXTMETRIC16));
740 #ifdef SUPPORT_REALIZED_FONTS
741 /* TTD should calculate this */
742 InitTextXForm(&TextXForm);
744 /* First get the size of the realized font */
745 nSize = PRTDRV_RealizeObject(physDev->segptrPDEVICE, OBJ_FONT,
746 &pLPD->paPrinterFonts[0], NULL,
747 NULL);
749 physDev->segptrFontInfo = WIN16_GlobalLock16(GlobalAlloc16(GHND, nSize));
750 /* Realize the font */
751 PRTDRV_RealizeObject(physDev->segptrPDEVICE, OBJ_FONT,
752 &pLPD->paPrinterFonts[0],
753 (LPVOID)physDev->segptrFontInfo,
754 &TextXForm);
755 /* Quick look at structure */
756 if (physDev->segptrFontInfo)
758 FONTINFO *p = (FONTINFO *)PTR_SEG_TO_LIN(physDev->segptrFontInfo);
760 dprintf_win16drv(stddeb, "T:%d VR:%d HR:%d, F:%d L:%d\n",
761 p->dfType,
762 p->dfVertRes, p->dfHorizRes,
763 p->dfFirstCHAR, p->dfLastCHAR
767 #endif
768 /* TTD Lots more to do here */
770 return TRUE;
775 * Escape (GDI.38)
777 static INT32 WIN16DRV_Escape( DC *dc, INT32 nEscape, INT32 cbInput,
778 SEGPTR lpInData, SEGPTR lpOutData )
780 WIN16DRV_PDEVICE *physDev = (WIN16DRV_PDEVICE *)dc->physDev;
781 int nRet = 0;
783 /* We should really process the nEscape parameter, but for now just
784 pass it all to the driver */
785 if (dc != NULL && physDev->segptrPDEVICE != 0)
787 switch(nEscape)
789 case 0x9:
790 printf("Escape: SetAbortProc ignored\n");
791 break;
793 default:
794 nRet = PRTDRV_Control(physDev->segptrPDEVICE, nEscape,
795 lpInData, lpOutData);
798 else
799 fprintf(stderr, "Escape(nEscape = %04x)\n", nEscape);
800 return nRet;
803 DWORD PRTDRV_ExtTextOut(LPPDEVICE lpDestDev, WORD wDestXOrg, WORD wDestYOrg,
804 RECT16 *lpClipRect, LPCSTR lpString, WORD wCount,
805 SEGPTR lpFontInfo, LPDRAWMODE lpDrawMode,
806 LPTEXTXFORM lpTextXForm, SHORT *lpCharWidths,
807 RECT16 * lpOpaqueRect, WORD wOptions)
809 DWORD dwRet = 0;
810 LOADED_PRINTER_DRIVER *pLPD = NULL;
812 dprintf_win16drv(stddeb, "PRTDRV_ExtTextOut:\n");
814 if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
816 LONG lP1, lP4, lP5, lP7, lP8, lP9, lP10, lP11;
817 WORD wP2, wP3, wP6, wP12;
818 SEGPTR SegPtr = pLPD->ThunkBufSegPtr;
819 SEGPTR Limit = pLPD->ThunkBufLimit;
820 int nSize;
822 if (pLPD->fn[FUNC_EXTTEXTOUT] == NULL)
824 dprintf_win16drv(stddeb, "PRTDRV_ExtTextOut: Not supported by driver\n");
825 return 0;
828 lP1 = lpDestDev;
829 wP2 = wDestXOrg;
830 wP3 = wDestYOrg;
832 if (lpClipRect != NULL)
834 lP4 = SegPtr;
835 nSize = sizeof(RECT16);
836 dprintf_win16drv(stddeb, "Adding lpClipRect\n");
838 AddData(&SegPtr, lpClipRect, nSize, Limit);
840 else
841 lP4 = 0L;
843 if (lpString != NULL)
845 /* TTD WARNING THIS STRING ISNT NULL TERMINATED */
846 lP5 = SegPtr;
847 nSize = strlen(lpString);
848 dprintf_win16drv(stddeb, "Adding string size %d\n",nSize);
850 AddData(&SegPtr, lpString, nSize, Limit);
852 else
853 lP5 = 0L;
855 wP6 = wCount;
857 /* This should be realized by the driver, so in 16bit data area */
858 lP7 = lpFontInfo;
860 if (lpDrawMode != NULL)
862 lP8 = SegPtr;
863 nSize = sizeof(DRAWMODE);
864 dprintf_win16drv(stddeb, "adding lpDrawMode\n");
866 AddData(&SegPtr, lpDrawMode, nSize, Limit);
868 else
869 lP8 = 0L;
871 if (lpTextXForm != NULL)
873 lP9 = SegPtr;
874 nSize = sizeof(TEXTXFORM);
875 dprintf_win16drv(stddeb, "Adding TextXForm\n");
876 AddData(&SegPtr, lpTextXForm, nSize, Limit);
878 else
879 lP9 = 0L;
881 if (lpCharWidths != NULL)
882 dprintf_win16drv(stddeb, "PRTDRV_ExtTextOut: Char widths not supported\n");
883 lP10 = 0;
885 if (lpOpaqueRect != NULL)
887 lP11 = SegPtr;
888 nSize = sizeof(RECT16);
889 dprintf_win16drv(stddeb, "Adding opaqueRect\n");
890 AddData(&SegPtr, lpOpaqueRect, nSize, Limit);
892 else
893 lP11 = 0L;
895 wP12 = wOptions;
896 dprintf_win16drv(stddeb, "Calling exttextout 0x%lx 0x%x 0x%x 0x%lx\n0x%lx 0x%x 0x%lx 0x%lx\n"
897 "0x%lx 0x%lx 0x%lx 0x%x\n",lP1, wP2, wP3, lP4,
898 lP5, wP6, lP7, lP8, lP9, lP10,
899 lP11, wP12);
900 dwRet = CallTo16_long_lwwllwlllllw(pLPD->fn[FUNC_EXTTEXTOUT],
901 lP1, wP2, wP3, lP4,
902 lP5, wP6, lP7, lP8, lP9, lP10,
903 lP11, wP12);
905 dprintf_win16drv(stddeb, "PRTDRV_ExtTextOut: return %lx\n", dwRet);
906 return dwRet;
911 * ExtTextOut (GDI.351)
913 static BOOL16 windrvExtTextOut16( DC *dc, INT16 x, INT16 y, UINT16 flags, const RECT16 * lprect,
914 LPCSTR str, UINT16 count, const INT16 *lpDx)
916 WIN16DRV_PDEVICE *physDev = (WIN16DRV_PDEVICE *)dc->physDev;
917 BOOL32 bRet = 1;
918 DRAWMODE DrawMode;
919 LPDRAWMODE lpDrawMode = &DrawMode;
920 TEXTXFORM TextXForm;
921 LPTEXTXFORM lpTextXForm = &TextXForm;
922 RECT16 rcClipRect;
923 RECT16 * lpClipRect = &rcClipRect;
924 RECT16 rcOpaqueRect;
925 RECT16 *lpOpaqueRect = &rcOpaqueRect;
926 WORD wOptions = 0;
927 WORD wCount = count;
929 static BOOL32 bInit = FALSE;
933 if (count == 0)
934 return FALSE;
936 dprintf_win16drv(stddeb, "LPGDI_ExtTextOut: %04x %d %d %x %p %*s %p\n", dc->hSelf, x, y,
937 flags, lprect, count > 0 ? count : 8, str, lpDx);
939 InitTextXForm(lpTextXForm);
940 InitDrawMode(lpDrawMode);
942 if (bInit == FALSE)
944 DWORD dwRet;
946 dwRet = PRTDRV_ExtTextOut(physDev->segptrPDEVICE, 0, 0,
947 NULL, " ",
948 -1, physDev->segptrFontInfo, lpDrawMode,
949 lpTextXForm, NULL, NULL, 0);
950 bInit = TRUE;
953 if (dc != NULL)
955 DWORD dwRet;
957 dwRet = PRTDRV_ExtTextOut(physDev->segptrPDEVICE, 0, 0,
958 NULL, "0",
959 -1, physDev->segptrFontInfo, lpDrawMode,
960 lpTextXForm, NULL, NULL, 0);
962 dwRet = PRTDRV_ExtTextOut(physDev->segptrPDEVICE, 0, 0,
963 NULL, str, -wCount,
964 physDev->segptrFontInfo, lpDrawMode,
965 lpTextXForm, NULL, NULL, 0);
967 lpClipRect->left = 0;
968 lpClipRect->top = 0;
969 lpClipRect->right = 0x3fc;
970 lpClipRect->bottom = 0x42;
971 lpOpaqueRect->left = x;
972 lpOpaqueRect->top = y;
973 lpOpaqueRect->right = 0x3a1;
974 lpOpaqueRect->bottom = 0x01;
976 dwRet = PRTDRV_ExtTextOut(physDev->segptrPDEVICE, x, y,
977 lpClipRect, str,
978 wCount, physDev->segptrFontInfo, lpDrawMode,
979 lpTextXForm, lpDx, lpOpaqueRect, wOptions);
981 dwRet = PRTDRV_ExtTextOut(physDev->segptrPDEVICE, x, y,
982 NULL, str,
983 wCount, physDev->segptrFontInfo, lpDrawMode,
984 lpTextXForm, NULL, NULL, wOptions);
986 return bRet;
989 /****************** misc. printer releated functions */
992 * The following function should implement a queing system
994 #ifndef HPQ
995 #define HPQ WORD
996 #endif
997 HPQ CreatePQ(int size) { printf("CreatePQ: %d\n",size); return 1; }
998 int DeletePQ(HPQ hPQ) { printf("DeletePQ: %x\n", hPQ); return 0; }
999 int ExtractPQ(HPQ hPQ) { printf("ExtractPQ: %x\n", hPQ); return 0; }
1000 int InsertPQ(HPQ hPQ, int tag, int key)
1001 { printf("ExtractPQ: %x %d %d\n", hPQ, tag, key); return 0; }
1002 int MinPQ(HPQ hPQ) { printf("MinPQ: %x\n", hPQ); return 0; }
1003 int SizePQ(HPQ hPQ, int sizechange)
1004 { printf("SizePQ: %x %d\n", hPQ, sizechange); return -1; }
1007 * The following functions implement part of the spooling process to
1008 * print manager. I would like to see wine have a version of print managers
1009 * that used LPR/LPD. For simplicity print jobs will be sent to a file for
1010 * now.
1012 typedef struct PRINTJOB
1014 char *pszOutput;
1015 char *pszTitle;
1016 HDC16 hDC;
1017 HANDLE16 hHandle;
1018 int nIndex;
1019 int fd;
1020 } PRINTJOB, *PPRINTJOB;
1022 #define MAX_PRINT_JOBS 1
1023 #define SP_ERROR -1
1024 #define SP_OUTOFDISK -4
1025 #define SP_OK 1
1027 PPRINTJOB gPrintJobsTable[MAX_PRINT_JOBS];
1030 static PPRINTJOB FindPrintJobFromHandle(HANDLE16 hHandle)
1032 return gPrintJobsTable[0];
1035 /* TTD Need to do some DOS->UNIX file conversion here */
1036 static int CreateSpoolFile(LPSTR pszOutput)
1038 int fd;
1039 char szSpoolFile[32];
1041 /* TTD convert the 'output device' into a spool file name */
1043 if (pszOutput == NULL || *pszOutput == '\0')
1044 strcpy(szSpoolFile,"lp.out");
1045 else
1046 strcpy(szSpoolFile, pszOutput);
1048 if ((fd = open(szSpoolFile, O_CREAT | O_TRUNC | O_WRONLY , 0600)) < 0)
1050 printf("Failed to create spool file %s, errno = %d\n", szSpoolFile, errno);
1052 return fd;
1055 static int FreePrintJob(HANDLE16 hJob)
1057 int nRet = SP_ERROR;
1058 PPRINTJOB pPrintJob;
1060 pPrintJob = FindPrintJobFromHandle(hJob);
1061 if (pPrintJob != NULL)
1063 gPrintJobsTable[pPrintJob->nIndex] = NULL;
1064 free(pPrintJob->pszOutput);
1065 free(pPrintJob->pszTitle);
1066 if (pPrintJob->fd >= 0) close(pPrintJob->fd);
1067 free(pPrintJob);
1068 nRet = SP_OK;
1070 return nRet;
1073 HANDLE16 OpenJob(LPSTR lpOutput, LPSTR lpTitle, HDC16 hDC)
1075 HANDLE16 hHandle = SP_ERROR;
1076 PPRINTJOB pPrintJob;
1078 dprintf_win16drv(stddeb, "OpenJob: \"%s\" \"%s\" %04x\n", lpOutput, lpTitle, hDC);
1080 pPrintJob = gPrintJobsTable[0];
1081 if (pPrintJob == NULL)
1083 int fd;
1085 /* Try an create a spool file */
1086 fd = CreateSpoolFile(lpOutput);
1087 if (fd >= 0)
1089 hHandle = 1;
1091 pPrintJob = malloc(sizeof(PRINTJOB));
1092 memset(pPrintJob, 0, sizeof(PRINTJOB));
1094 pPrintJob->pszOutput = strdup(lpOutput);
1095 pPrintJob->pszTitle = strdup(lpTitle);
1096 pPrintJob->hDC = hDC;
1097 pPrintJob->fd = fd;
1098 pPrintJob->nIndex = 0;
1099 pPrintJob->hHandle = hHandle;
1100 gPrintJobsTable[pPrintJob->nIndex] = pPrintJob;
1103 dprintf_win16drv(stddeb, "OpenJob: return %04x\n", hHandle);
1104 return hHandle;
1107 int CloseJob(HANDLE16 hJob)
1109 int nRet = SP_ERROR;
1110 PPRINTJOB pPrintJob = NULL;
1112 dprintf_win16drv(stddeb, "CloseJob: %04x\n", hJob);
1114 pPrintJob = FindPrintJobFromHandle(hJob);
1115 if (pPrintJob != NULL)
1117 /* Close the spool file */
1118 close(pPrintJob->fd);
1119 FreePrintJob(hJob);
1120 nRet = 1;
1122 return nRet;
1125 int WriteSpool(HANDLE16 hJob, LPSTR lpData, WORD cch)
1127 int nRet = SP_ERROR;
1128 PPRINTJOB pPrintJob = NULL;
1130 dprintf_win16drv(stddeb, "WriteSpool: %04x %08lx %04x\n", hJob, (DWORD)lpData, cch);
1132 pPrintJob = FindPrintJobFromHandle(hJob);
1133 if (pPrintJob != NULL && pPrintJob->fd >= 0 && cch)
1135 if (write(pPrintJob->fd, lpData, cch) != cch)
1136 nRet = SP_OUTOFDISK;
1137 else
1138 nRet = cch;
1140 return nRet;
1143 int WriteDialog(HANDLE16 hJob, LPSTR lpMsg, WORD cchMsg)
1145 int nRet = 0;
1147 dprintf_win16drv(stddeb, "WriteDialog: %04x %04x \"%s\"\n", hJob, cchMsg, lpMsg);
1149 nRet = MessageBox16(0, lpMsg, "Printing Error", MB_OKCANCEL);
1150 return nRet;
1153 int DeleteJob(HANDLE16 hJob, WORD wNotUsed)
1155 int nRet;
1157 dprintf_win16drv(stddeb, "DeleteJob: %04x\n", hJob);
1159 nRet = FreePrintJob(hJob);
1160 return nRet;
1164 * The following two function would allow a page to be sent to the printer
1165 * when it has been processed. For simplicity they havn't been implemented.
1166 * This means a whole job has to be processed before it is sent to the printer.
1168 int StartSpoolPage(HANDLE16 hJob)
1170 dprintf_win16drv(stddeb, "StartSpoolPage GDI.246 unimplemented\n");
1171 return 1;
1174 int EndSpoolPage(HANDLE16 hJob)
1176 dprintf_win16drv(stddeb, "EndSpoolPage GDI.247 unimplemented\n");
1177 return 1;
1181 DWORD GetSpoolJob(int nOption, LONG param)
1183 DWORD retval = 0;
1184 dprintf_win16drv(stddeb, "In GetSpoolJob param 0x%lx noption %d\n",param, nOption);
1185 return retval;