Release 970305
[wine/multimedia.git] / graphics / win16drv / init.c
blobfec0eb017e1d53ba5731e4f189823798bdaf3a78
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 DRAWMODE DrawMode;
35 static BOOL32 WIN16DRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device,
36 LPCSTR output, const DEVMODE16* initData );
37 static INT32 WIN16DRV_Escape( DC *dc, INT32 nEscape, INT32 cbInput,
38 SEGPTR lpInData, SEGPTR lpOutData );
40 static const DC_FUNCTIONS WIN16DRV_Funcs =
42 NULL, /* pArc */
43 NULL, /* pBitBlt */
44 NULL, /* pChord */
45 WIN16DRV_CreateDC, /* pCreateDC */
46 NULL, /* pDeleteDC */
47 NULL, /* pDeleteObject */
48 NULL, /* pEllipse */
49 WIN16DRV_Escape, /* pEscape */
50 NULL, /* pExcludeClipRect */
51 NULL, /* pExcludeVisRect */
52 NULL, /* pExtFloodFill */
53 WIN16DRV_ExtTextOut, /* pExtTextOut */
54 NULL, /* pGetPixel */
55 WIN16DRV_GetTextExtentPoint, /* pGetTextExtentPoint */
56 WIN16DRV_GetTextMetrics, /* pGetTextMetrics */
57 NULL, /* pIntersectClipRect */
58 NULL, /* pIntersectVisRect */
59 NULL, /* pLineTo */
60 NULL, /* pMoveToEx */
61 NULL, /* pOffsetClipRgn */
62 NULL, /* pOffsetViewportOrgEx */
63 NULL, /* pOffsetWindowOrgEx */
64 NULL, /* pPaintRgn */
65 NULL, /* pPatBlt */
66 NULL, /* pPie */
67 NULL, /* pPolyPolygon */
68 NULL, /* pPolygon */
69 NULL, /* pPolyline */
70 NULL, /* pRealizePalette */
71 NULL, /* pRectangle */
72 NULL, /* pRestoreDC */
73 NULL, /* pRoundRect */
74 NULL, /* pSaveDC */
75 NULL, /* pScaleViewportExtEx */
76 NULL, /* pScaleWindowExtEx */
77 NULL, /* pSelectClipRgn */
78 WIN16DRV_SelectObject, /* pSelectObject */
79 NULL, /* pSelectPalette */
80 NULL, /* pSetBkColor */
81 NULL, /* pSetBkMode */
82 NULL, /* pSetDeviceClipping */
83 NULL, /* pSetDIBitsToDevice */
84 NULL, /* pSetMapMode */
85 NULL, /* pSetMapperFlags */
86 NULL, /* pSetPixel */
87 NULL, /* pSetPolyFillMode */
88 NULL, /* pSetROP2 */
89 NULL, /* pSetRelAbs */
90 NULL, /* pSetStretchBltMode */
91 NULL, /* pSetTextAlign */
92 NULL, /* pSetTextCharacterExtra */
93 NULL, /* pSetTextColor */
94 NULL, /* pSetTextJustification */
95 NULL, /* pSetViewportExtEx */
96 NULL, /* pSetViewportOrgEx */
97 NULL, /* pSetWindowExtEx */
98 NULL, /* pSetWindowOrgEx */
99 NULL, /* pStretchBlt */
100 NULL /* pStretchDIBits */
104 #define MAX_PRINTER_DRIVERS 16
106 static LOADED_PRINTER_DRIVER *gapLoadedPrinterDrivers[MAX_PRINTER_DRIVERS];
109 /**********************************************************************
110 * WIN16DRV_Init
112 BOOL32 WIN16DRV_Init(void)
114 return DRIVER_RegisterDriver( NULL /* generic driver */, &WIN16DRV_Funcs );
118 /* Tempory functions, for initialising structures */
119 /* These values should be calculated, not hardcoded */
120 void InitTextXForm(LPTEXTXFORM16 lpTextXForm)
122 lpTextXForm->txfHeight = 0x0001;
123 lpTextXForm->txfWidth = 0x000c;
124 lpTextXForm->txfEscapement = 0x0000;
125 lpTextXForm->txfOrientation = 0x0000;
126 lpTextXForm->txfWeight = 0x0190;
127 lpTextXForm->txfItalic = 0x00;
128 lpTextXForm->txfUnderline = 0x00;
129 lpTextXForm->txfStrikeOut = 0x00;
130 lpTextXForm->txfOutPrecision = 0x02;
131 lpTextXForm->txfClipPrecision = 0x01;
132 lpTextXForm->txfAccelerator = 0x0001;
133 lpTextXForm->txfOverhang = 0x0000;
137 void InitDrawMode(LPDRAWMODE lpDrawMode)
139 lpDrawMode->Rop2 = 0x000d;
140 lpDrawMode->bkMode = 0x0001;
141 lpDrawMode->bkColor = 0x3fffffff;
142 lpDrawMode->TextColor = 0x20000000;
143 lpDrawMode->TBreakExtra = 0x0000;
144 lpDrawMode->BreakExtra = 0x0000;
145 lpDrawMode->BreakErr = 0x0000;
146 lpDrawMode->BreakRem = 0x0000;
147 lpDrawMode->BreakCount = 0x0000;
148 lpDrawMode->CharExtra = 0x0000;
149 lpDrawMode->LbkColor = 0x00ffffff;
150 lpDrawMode->LTextColor = 0x00000000;
153 * Thunking utility functions
156 static BOOL32 AddData(SEGPTR *pSegPtr, const void *pData, int nSize, SEGPTR Limit)
158 BOOL32 bRet = FALSE;
159 char *pBuffer = PTR_SEG_TO_LIN((*pSegPtr));
160 char *pLimit = PTR_SEG_TO_LIN(Limit);
163 if ((pBuffer + nSize) < pLimit)
165 DWORD *pdw = (DWORD *)pSegPtr;
166 SEGPTR SegPtrOld = *pSegPtr;
167 SEGPTR SegPtrNew;
169 dprintf_win16drv(stddeb, "AddData: Copying %d from %p to %p(0x%x)\n", nSize, pData, pBuffer, (UINT32)*pSegPtr);
170 memcpy(pBuffer, pData, nSize);
171 SegPtrNew = (SegPtrOld + nSize + 1);
172 *pdw = (DWORD)SegPtrNew;
174 return bRet;
178 static BOOL32 GetParamData(SEGPTR SegPtrSrc,void *pDataDest, int nSize)
180 char *pSrc = PTR_SEG_TO_LIN(SegPtrSrc);
181 char *pDest = pDataDest;
183 dprintf_win16drv(stddeb, "GetParamData: Copying %d from %lx(%lx) to %lx\n", nSize, (DWORD)pSrc, (DWORD)SegPtrSrc, (DWORD)pDataDest);
184 memcpy(pDest, pSrc, nSize);
185 return TRUE;
189 static void GetPrinterDriverFunctions(HINSTANCE16 hInst, LOADED_PRINTER_DRIVER *pLPD)
191 #define LoadPrinterDrvFunc(A,B) pLPD->fn[A] = \
192 GetProcAddress16(hInst, MAKEINTRESOURCE(B))
194 LoadPrinterDrvFunc(FUNC_CONTROL, ORD_CONTROL); /* 3 */
195 LoadPrinterDrvFunc(FUNC_ENABLE, ORD_ENABLE); /* 5 */
196 LoadPrinterDrvFunc(FUNC_ENUMDFONTS, ORD_ENUMDFONTS); /* 6 */
197 LoadPrinterDrvFunc(FUNC_REALIZEOBJECT, ORD_REALIZEOBJECT);/* 10 */
198 LoadPrinterDrvFunc(FUNC_EXTTEXTOUT, ORD_EXTTEXTOUT); /* 14 */
199 dprintf_win16drv (stddeb,"got func CONTROL 0x%p enable 0x%p enumDfonts 0x%p realizeobject 0x%p extextout 0x%p\n",
200 pLPD->fn[FUNC_CONTROL],
201 pLPD->fn[FUNC_ENABLE],
202 pLPD->fn[FUNC_ENUMDFONTS],
203 pLPD->fn[FUNC_REALIZEOBJECT],
204 pLPD->fn[FUNC_EXTTEXTOUT]);
209 static LOADED_PRINTER_DRIVER *FindPrinterDriverFromPDEVICE(SEGPTR segptrPDEVICE)
211 LOADED_PRINTER_DRIVER *pLPD = NULL;
213 /* Find the printer driver associated with this PDEVICE */
214 /* Each of the PDEVICE structures has a PDEVICE_HEADER structure */
215 /* just before it */
216 if (segptrPDEVICE != (SEGPTR)NULL)
218 PDEVICE_HEADER *pPDH = (PDEVICE_HEADER *)
219 (PTR_SEG_TO_LIN(segptrPDEVICE) - sizeof(PDEVICE_HEADER));
220 pLPD = pPDH->pLPD;
222 return pLPD;
225 static LOADED_PRINTER_DRIVER *FindPrinterDriverFromName(const char *pszDriver)
227 LOADED_PRINTER_DRIVER *pLPD = NULL;
228 int nDriverSlot = 0;
230 /* Look to see if the printer driver is already loaded */
231 while (pLPD == NULL && nDriverSlot < MAX_PRINTER_DRIVERS)
233 LOADED_PRINTER_DRIVER *ptmpLPD;
234 ptmpLPD = gapLoadedPrinterDrivers[nDriverSlot++];
235 if (ptmpLPD != NULL)
237 dprintf_win16drv(stddeb, "Comparing %s,%s\n",ptmpLPD->szDriver,pszDriver);
238 /* Found driver store info, exit loop */
239 if (lstrcmpi32A(ptmpLPD->szDriver, pszDriver) == 0)
240 pLPD = ptmpLPD;
243 if (pLPD == NULL) printf("Couldn't find driver %s\n", pszDriver);
244 return pLPD;
247 * Load a printer driver, adding it self to the list of loaded drivers.
250 static LOADED_PRINTER_DRIVER *LoadPrinterDriver(const char *pszDriver)
252 HINSTANCE16 hInst;
253 LOADED_PRINTER_DRIVER *pLPD = NULL;
254 int nDriverSlot = 0;
255 BOOL32 bSlotFound = FALSE;
257 /* First look to see if driver is loaded */
258 pLPD = FindPrinterDriverFromName(pszDriver);
259 if (pLPD != NULL)
261 /* Already loaded so increase usage count */
262 pLPD->nUsageCount++;
263 return pLPD;
266 /* Not loaded so try and find an empty slot */
267 while (!bSlotFound && nDriverSlot < MAX_PRINTER_DRIVERS)
269 if (gapLoadedPrinterDrivers[nDriverSlot] == NULL)
270 bSlotFound = TRUE;
271 else
272 nDriverSlot++;
274 if (!bSlotFound)
276 printf("Too many printers drivers loaded\n");
277 return NULL;
281 char *drvName = malloc(strlen(pszDriver)+5);
282 strcpy(drvName, pszDriver);
283 strcat(drvName, ".DRV");
284 hInst = LoadLibrary16(drvName);
286 dprintf_win16drv(stddeb, "Loaded the library\n");
289 if (hInst <= 32)
291 /* Failed to load driver */
292 fprintf(stderr, "Failed to load printer driver %s\n", pszDriver);
294 else
296 HANDLE16 hHandle;
298 /* Allocate some memory for printer driver info */
299 pLPD = malloc(sizeof(LOADED_PRINTER_DRIVER));
300 memset(pLPD, 0 , sizeof(LOADED_PRINTER_DRIVER));
302 pLPD->hInst = hInst;
303 strcpy(pLPD->szDriver,pszDriver);
305 /* Get DS for the printer module */
306 pLPD->ds_reg = hInst;
308 dprintf_win16drv(stddeb, "DS for %s is %x\n", pszDriver, pLPD->ds_reg);
310 /* Get address of printer driver functions */
311 GetPrinterDriverFunctions(hInst, pLPD);
313 /* Set initial usage count */
314 pLPD->nUsageCount = 1;
316 /* Create a thunking buffer */
317 hHandle = GlobalAlloc16(GHND, (1024 * 8));
318 pLPD->hThunk = hHandle;
319 pLPD->ThunkBufSegPtr = WIN16_GlobalLock16(hHandle);
320 pLPD->ThunkBufLimit = pLPD->ThunkBufSegPtr + (1024*8);
322 /* Update table of loaded printer drivers */
323 pLPD->nIndex = nDriverSlot;
324 gapLoadedPrinterDrivers[nDriverSlot] = pLPD;
327 return pLPD;
330 * Control (ordinal 3)
332 INT16 PRTDRV_Control(LPPDEVICE lpDestDev, WORD wfunction, SEGPTR lpInData, SEGPTR lpOutData)
334 /* wfunction == Escape code */
335 /* lpInData, lpOutData depend on code */
337 WORD wRet = 0;
338 LOADED_PRINTER_DRIVER *pLPD = NULL;
340 dprintf_win16drv(stddeb, "PRTDRV_Control: %08x 0x%x %08lx %08lx\n", (unsigned int)lpDestDev, wfunction, lpInData, lpOutData);
342 if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
344 LONG lP1, lP3, lP4;
345 WORD wP2;
347 if (pLPD->fn[FUNC_CONTROL] == NULL)
349 dprintf_win16drv(stddeb, "PRTDRV_Control: Not supported by driver\n");
350 return 0;
353 lP1 = (SEGPTR)lpDestDev;
354 wP2 = wfunction;
355 lP3 = (SEGPTR)lpInData;
356 lP4 = (SEGPTR)lpOutData;
358 wRet = CallTo16_word_lwll(pLPD->fn[FUNC_CONTROL],
359 lP1, wP2, lP3, lP4);
361 dprintf_win16drv(stddeb, "PRTDRV_Control: return %x\n", wRet);
362 return wRet;
364 return 0;
368 * Enable (ordinal 5)
370 static WORD PRTDRV_Enable(LPVOID lpDevInfo, WORD wStyle, LPCSTR lpDestDevType,
371 LPCSTR lpDeviceName, LPCSTR lpOutputFile, LPVOID lpData)
373 WORD wRet = 0;
374 LOADED_PRINTER_DRIVER *pLPD = NULL;
376 dprintf_win16drv(stddeb, "PRTDRV_Enable: %s %s\n",lpDestDevType, lpOutputFile);
378 /* Get the printer driver info */
379 if (wStyle == INITPDEVICE)
381 pLPD = FindPrinterDriverFromPDEVICE((SEGPTR)lpDevInfo);
383 else
385 pLPD = FindPrinterDriverFromName((char *)lpDeviceName);
387 if (pLPD != NULL)
389 LONG lP1, lP3, lP4, lP5;
390 WORD wP2;
391 SEGPTR SegPtr = pLPD->ThunkBufSegPtr;
392 SEGPTR Limit = pLPD->ThunkBufLimit;
393 int nSize;
395 if (pLPD->fn[FUNC_ENABLE] == NULL)
397 dprintf_win16drv(stddeb, "PRTDRV_Enable: Not supported by driver\n");
398 return 0;
401 if (wStyle == INITPDEVICE)
403 /* All ready a 16 address */
404 lP1 = (SEGPTR)lpDevInfo;
406 else
408 /* 32 bit data */
409 lP1 = SegPtr;
410 nSize = sizeof(DeviceCaps);
411 AddData(&SegPtr, lpDevInfo, nSize, Limit);
414 wP2 = wStyle;
416 lP3 = SegPtr;
417 nSize = strlen(lpDestDevType) + 1;
418 AddData(&SegPtr, lpDestDevType, nSize, Limit);
420 lP4 = SegPtr;
421 nSize = strlen(lpOutputFile) + 1;
422 AddData(&SegPtr, lpOutputFile, nSize, Limit);
424 lP5 = (LONG)lpData;
427 wRet = CallTo16_word_lwlll(pLPD->fn[FUNC_ENABLE],
428 lP1, wP2, lP3, lP4, lP5);
430 /* Get the data back */
431 if (lP1 != 0 && wStyle != INITPDEVICE)
433 nSize = sizeof(DeviceCaps);
434 GetParamData(lP1, lpDevInfo, nSize);
437 dprintf_win16drv(stddeb, "PRTDRV_Enable: return %x\n", wRet);
438 return wRet;
443 * EnumCallback (GDI.158)
445 * This is the callback function used when EnumDFonts is called.
446 * (The printer drivers uses it to pass info on available fonts).
448 * lpvClientData is the pointer passed to EnumDFonts, which points to a WEPFC
449 * structure (WEPFC = WINE_ENUM_PRINTER_FONT_CALLBACK). This structure
450 * contains infomation on how to store the data passed .
452 * There are two modes:
453 * 1) Just count the number of fonts available.
454 * 2) Store all font data passed.
456 WORD WineEnumDFontCallback(LPLOGFONT16 lpLogFont, LPTEXTMETRIC16 lpTextMetrics,
457 WORD wFontType, LONG lpvClientData)
459 int wRet = 0;
460 WEPFC *pWEPFC = (WEPFC *)lpvClientData;
462 /* Make sure we have the right structure */
463 if (pWEPFC != NULL )
465 dprintf_win16drv(stddeb, "mode is 0x%x\n",pWEPFC->nMode);
467 switch (pWEPFC->nMode)
469 /* Count how many fonts */
470 case 1:
471 pWEPFC->nCount++;
472 break;
474 /* Store the fonts in the printer driver structure */
475 case 2:
477 PRINTER_FONTS_INFO *pPFI;
479 dprintf_win16drv(stddeb, "WineEnumDFontCallback: Found %s %x\n",
480 lpLogFont->lfFaceName, wFontType);
482 pPFI = &pWEPFC->pLPD->paPrinterFonts[pWEPFC->nCount];
483 memcpy(&(pPFI->lf), lpLogFont, sizeof(LOGFONT16));
484 memcpy(&(pPFI->tm), lpTextMetrics, sizeof(TEXTMETRIC16));
485 pWEPFC->nCount++;
488 break;
490 wRet = 1;
492 dprintf_win16drv(stddeb, "WineEnumDFontCallback: returnd %d\n", wRet);
493 return wRet;
497 * EnumDFonts (ordinal 6)
499 WORD PRTDRV_EnumDFonts(LPPDEVICE lpDestDev, LPSTR lpFaceName,
500 FARPROC16 lpCallbackFunc, LPVOID lpClientData)
502 WORD wRet = 0;
503 LOADED_PRINTER_DRIVER *pLPD = NULL;
505 dprintf_win16drv(stddeb, "PRTDRV_EnumDFonts:\n");
507 if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
509 LONG lP1, lP2, lP3, lP4;
511 SEGPTR SegPtr = pLPD->ThunkBufSegPtr;
512 SEGPTR Limit = pLPD->ThunkBufLimit;
513 int nSize;
515 if (pLPD->fn[FUNC_ENUMDFONTS] == NULL)
517 dprintf_win16drv(stddeb, "PRTDRV_EnumDFonts: Not supported by driver\n");
518 return 0;
521 lP1 = (SEGPTR)lpDestDev;
523 if (lpFaceName == NULL)
525 lP2 = 0;
527 else
529 lP2 = SegPtr;
530 nSize = strlen(lpFaceName) + 1;
531 AddData(&SegPtr, lpFaceName, nSize, Limit);
534 lP3 = (LONG)lpCallbackFunc;
536 lP4 = (LONG)lpClientData;
538 wRet = CallTo16_word_llll(pLPD->fn[FUNC_ENUMDFONTS],
539 lP1, lP2, lP3, lP4);
541 else
542 printf("Failed to find device\n");
544 dprintf_win16drv(stddeb, "PRTDRV_EnumDFonts: return %x\n", wRet);
545 return wRet;
549 * RealizeObject (ordinal 10)
551 DWORD PRTDRV_RealizeObject(LPPDEVICE lpDestDev, WORD wStyle,
552 LPVOID lpInObj, LPVOID lpOutObj,
553 LPTEXTXFORM16 lpTextXForm)
555 WORD dwRet = 0;
556 LOADED_PRINTER_DRIVER *pLPD = NULL;
558 dprintf_win16drv(stddeb, "PRTDRV_RealizeObject:\n");
560 if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
562 LONG lP1, lP3, lP4, lP5;
563 WORD wP2;
564 SEGPTR SegPtr = pLPD->ThunkBufSegPtr;
565 SEGPTR Limit = pLPD->ThunkBufLimit;
566 int nSize;
568 if (pLPD->fn[FUNC_REALIZEOBJECT] == NULL)
570 dprintf_win16drv(stddeb, "PRTDRV_RealizeObject: Not supported by driver\n");
571 return 0;
574 lP1 = lpDestDev;
575 wP2 = wStyle;
577 lP3 = SegPtr;
578 switch (wStyle)
580 case 3:
581 nSize = sizeof(LOGFONT16);
582 break;
583 default:
584 printf("PRTDRV_RealizeObject: Object type %d not supported\n", wStyle);
585 nSize = 0;
588 AddData(&SegPtr, lpInObj, nSize, Limit);
590 lP4 = (LONG)lpOutObj;
592 if (lpTextXForm != NULL)
594 lP5 = SegPtr;
595 nSize = sizeof(TEXTXFORM16);
596 AddData(&SegPtr, lpTextXForm, nSize, Limit);
598 else
599 lP5 = 0L;
601 dwRet = CallTo16_long_lwlll(pLPD->fn[FUNC_REALIZEOBJECT],
602 lP1, wP2, lP3, lP4, lP5);
605 dprintf_win16drv(stddeb, "PRTDRV_RealizeObject: return %x\n", dwRet);
606 return dwRet;
610 BOOL32 WIN16DRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device, LPCSTR output,
611 const DEVMODE16* initData )
613 LOADED_PRINTER_DRIVER *pLPD;
614 WORD wRet;
615 DeviceCaps *printerDevCaps;
616 FARPROC16 pfnCallback;
617 int nPDEVICEsize;
618 PDEVICE_HEADER *pPDH;
619 WIN16DRV_PDEVICE *physDev;
620 LPDRAWMODE lpDrawMode = &DrawMode;
622 /* Realizing fonts */
623 TEXTXFORM16 TextXForm;
624 int nSize;
625 char printerEnabled[20];
626 PROFILE_GetWineIniString( "wine", "printer", "off",
627 printerEnabled, sizeof(printerEnabled) );
628 if (strcmp(printerEnabled,"on"))
630 printf("WIN16DRV_CreateDC disabled in wine.conf file\n");
631 return FALSE;
634 dprintf_win16drv(stddeb, "In creatdc for (%s,%s,%s) initData 0x%p\n",driver, device, output, initData);
636 physDev = (WIN16DRV_PDEVICE *)HeapAlloc( SystemHeap, 0, sizeof(*physDev) );
637 if (!physDev) return FALSE;
638 dc->physDev = physDev;
640 pLPD = LoadPrinterDriver(driver);
641 if (pLPD == NULL)
643 dprintf_win16drv(stddeb, "LPGDI_CreateDC: Failed to find printer driver\n");
644 HeapFree( SystemHeap, 0, physDev );
645 return FALSE;
647 dprintf_win16drv(stddeb, "windevCreateDC pLPD 0x%p\n", pLPD);
649 /* Now Get the device capabilities from the printer driver */
651 printerDevCaps = (DeviceCaps *) malloc(sizeof(DeviceCaps));
652 memset(printerDevCaps, 0, sizeof(DeviceCaps));
654 /* Get GDIINFO which is the same as a DeviceCaps structure */
655 wRet = PRTDRV_Enable(printerDevCaps, GETGDIINFO, device, driver, output,NULL);
657 /* Add this to the DC */
658 dc->w.devCaps = printerDevCaps;
659 dc->w.hVisRgn = CreateRectRgn32(0, 0, dc->w.devCaps->horzRes, dc->w.devCaps->vertRes);
660 dc->w.bitsPerPixel = dc->w.devCaps->bitsPixel;
662 printf("Got devcaps width %d height %d bits %d planes %d\n",
663 dc->w.devCaps->horzRes,
664 dc->w.devCaps->vertRes,
665 dc->w.devCaps->bitsPixel,
666 dc->w.devCaps->planes);
668 /* Now we allocate enough memory for the PDEVICE structure */
669 /* The size of this varies between printer drivers */
670 /* This PDEVICE is used by the printer DRIVER not by the GDI so must */
671 /* be accessable from 16 bit code */
672 nPDEVICEsize = dc->w.devCaps->pdeviceSize + sizeof(PDEVICE_HEADER);
674 /* TTD Shouldn't really do pointer arithmetic on segment points */
675 physDev->segptrPDEVICE = WIN16_GlobalLock16(GlobalAlloc16(GHND, nPDEVICEsize))+sizeof(PDEVICE_HEADER);
676 *(BYTE *)(PTR_SEG_TO_LIN(physDev->segptrPDEVICE)+0) = 'N';
677 *(BYTE *)(PTR_SEG_TO_LIN(physDev->segptrPDEVICE)+1) = 'B';
679 /* Set up the header */
680 pPDH = (PDEVICE_HEADER *)(PTR_SEG_TO_LIN(physDev->segptrPDEVICE) - sizeof(PDEVICE_HEADER));
681 pPDH->pLPD = pLPD;
683 dprintf_win16drv(stddeb, "PRTDRV_Enable: PDEVICE allocated %08lx\n",(DWORD)(physDev->segptrPDEVICE));
685 /* Now get the printer driver to initialise this data */
686 wRet = PRTDRV_Enable((LPVOID)physDev->segptrPDEVICE, INITPDEVICE, device, driver, output, NULL);
688 /* Now enumerate the fonts supported by the printer driver*/
689 /* GDI.158 is EnumCallback, which is called by the 16bit printer driver */
690 /* passing information on the available fonts */
691 if (pLPD->paPrinterFonts == NULL)
693 pfnCallback = MODULE_GetEntryPoint( GetModuleHandle16("GDI"), 158 );
695 if (pfnCallback != NULL)
697 WEPFC wepfc;
699 wepfc.nMode = 1;
700 wepfc.nCount = 0;
701 wepfc.pLPD = pLPD;
703 /* First count the number of fonts */
705 PRTDRV_EnumDFonts(physDev->segptrPDEVICE, NULL, pfnCallback,
706 (void *)&wepfc);
708 /* Allocate a buffer to store all of the fonts */
709 pLPD->nPrinterFonts = wepfc.nCount;
710 dprintf_win16drv(stddeb, "Got %d fonts\n",wepfc.nCount);
712 if (wepfc.nCount > 0)
715 pLPD->paPrinterFonts = malloc(sizeof(PRINTER_FONTS_INFO) * wepfc.nCount);
717 /* Now get all of the fonts */
718 wepfc.nMode = 2;
719 wepfc.nCount = 0;
720 PRTDRV_EnumDFonts(physDev->segptrPDEVICE, NULL, pfnCallback,
721 (void *)&wepfc);
726 /* Select the first font into the DC */
727 /* Set up the logfont */
728 memcpy(&physDev->lf,
729 &pLPD->paPrinterFonts[0].lf,
730 sizeof(LOGFONT16));
732 /* Set up the textmetrics */
733 memcpy(&physDev->tm,
734 &pLPD->paPrinterFonts[0].tm,
735 sizeof(TEXTMETRIC16));
737 #ifdef SUPPORT_REALIZED_FONTS
738 /* TTD should calculate this */
739 InitTextXForm(&TextXForm);
741 /* First get the size of the realized font */
742 nSize = PRTDRV_RealizeObject(physDev->segptrPDEVICE, OBJ_FONT,
743 &pLPD->paPrinterFonts[0], NULL,
744 NULL);
746 physDev->segptrFontInfo = WIN16_GlobalLock16(GlobalAlloc16(GHND, nSize));
747 /* Realize the font */
748 PRTDRV_RealizeObject(physDev->segptrPDEVICE, OBJ_FONT,
749 &pLPD->paPrinterFonts[0],
750 (LPVOID)physDev->segptrFontInfo,
751 &TextXForm);
752 /* Quick look at structure */
753 if (physDev->segptrFontInfo)
755 FONTINFO16 *p = (FONTINFO16 *)PTR_SEG_TO_LIN(physDev->segptrFontInfo);
757 dprintf_win16drv(stddeb, "T:%d VR:%d HR:%d, F:%d L:%d\n",
758 p->dfType,
759 p->dfVertRes, p->dfHorizRes,
760 p->dfFirstCHAR, p->dfLastCHAR
764 #endif
765 /* TTD Lots more to do here */
766 InitDrawMode(lpDrawMode);
768 return TRUE;
773 * Escape (GDI.38)
775 static INT32 WIN16DRV_Escape( DC *dc, INT32 nEscape, INT32 cbInput,
776 SEGPTR lpInData, SEGPTR lpOutData )
778 WIN16DRV_PDEVICE *physDev = (WIN16DRV_PDEVICE *)dc->physDev;
779 int nRet = 0;
781 /* We should really process the nEscape parameter, but for now just
782 pass it all to the driver */
783 if (dc != NULL && physDev->segptrPDEVICE != 0)
785 switch(nEscape)
787 case 0x9:
788 printf("Escape: SetAbortProc ignored\n");
789 break;
791 default:
792 nRet = PRTDRV_Control(physDev->segptrPDEVICE, nEscape,
793 lpInData, lpOutData);
796 else
797 fprintf(stderr, "Escape(nEscape = %04x)\n", nEscape);
798 return nRet;
801 DWORD PRTDRV_ExtTextOut(LPPDEVICE lpDestDev, WORD wDestXOrg, WORD wDestYOrg,
802 RECT16 *lpClipRect, LPCSTR lpString, WORD wCount,
803 SEGPTR lpFontInfo, LPDRAWMODE lpDrawMode,
804 LPTEXTXFORM16 lpTextXForm, SHORT *lpCharWidths,
805 RECT16 * lpOpaqueRect, WORD wOptions)
807 DWORD dwRet = 0;
808 LOADED_PRINTER_DRIVER *pLPD = NULL;
810 dprintf_win16drv(stddeb, "PRTDRV_ExtTextOut:\n");
812 if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
814 LONG lP1, lP4, lP5, lP7, lP8, lP9, lP10, lP11;
815 WORD wP2, wP3, wP6, wP12;
816 INT16 iP6;
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 nSize = abs(wCount);
849 dprintf_win16drv(stddeb, "Adding string size %d\n",nSize);
851 AddData(&SegPtr, lpString, nSize, Limit);
853 else
854 lP5 = 0L;
856 iP6 = wCount;
858 /* This should be realized by the driver, so in 16bit data area */
859 lP7 = lpFontInfo;
861 if (lpDrawMode != NULL)
863 lP8 = SegPtr;
864 nSize = sizeof(DRAWMODE);
865 dprintf_win16drv(stddeb, "adding lpDrawMode\n");
867 AddData(&SegPtr, lpDrawMode, nSize, Limit);
869 else
870 lP8 = 0L;
872 if (lpTextXForm != NULL)
874 lP9 = SegPtr;
875 nSize = sizeof(TEXTXFORM16);
876 dprintf_win16drv(stddeb, "Adding TextXForm\n");
877 AddData(&SegPtr, lpTextXForm, nSize, Limit);
879 else
880 lP9 = 0L;
882 if (lpCharWidths != NULL)
883 dprintf_win16drv(stddeb, "PRTDRV_ExtTextOut: Char widths not supported\n");
884 lP10 = 0;
886 if (lpOpaqueRect != NULL)
888 lP11 = SegPtr;
889 nSize = sizeof(RECT16);
890 dprintf_win16drv(stddeb, "Adding opaqueRect\n");
891 AddData(&SegPtr, lpOpaqueRect, nSize, Limit);
893 else
894 lP11 = 0L;
896 wP12 = wOptions;
897 dprintf_win16drv(stddeb, "Calling exttextout 0x%lx 0x%x 0x%x 0x%lx\n0x%lx 0x%x 0x%lx 0x%lx\n"
898 "0x%lx 0x%lx 0x%lx 0x%x\n",lP1, wP2, wP3, lP4,
899 lP5, iP6, lP7, lP8, lP9, lP10,
900 lP11, wP12);
901 dwRet = CallTo16_long_lwwllwlllllw(pLPD->fn[FUNC_EXTTEXTOUT],
902 lP1, wP2, wP3, lP4,
903 lP5, iP6, lP7, lP8, lP9, lP10,
904 lP11, wP12);
905 if (lpDrawMode)
906 GetParamData(lP8, lpDrawMode, sizeof(DRAWMODE));
908 dprintf_win16drv(stddeb, "PRTDRV_ExtTextOut: return %lx\n", dwRet);
909 return dwRet;
914 /****************** misc. printer releated functions */
917 * The following function should implement a queing system
919 #ifndef HPQ
920 #define HPQ WORD
921 #endif
922 struct hpq
924 struct hpq *next;
925 int tag;
926 int key;
929 static struct hpq *hpqueue;
931 HPQ
932 CreatePQ(int size)
934 printf("CreatePQ: %d\n",size);
935 return 1;
937 int
938 DeletePQ(HPQ hPQ)
940 printf("DeletePQ: %x\n", hPQ);
941 return 0;
943 int
944 ExtractPQ(HPQ hPQ)
946 struct hpq *queue, *prev, *current, *currentPrev;
947 int key, tag = -1;
948 currentPrev = prev = NULL;
949 queue = current = hpqueue;
950 if (current)
951 key = current->key;
953 while (current)
955 currentPrev = current;
956 current = current->next;
957 if (current)
959 if (current->key < key)
961 queue = current;
962 prev = currentPrev;
966 if (queue)
968 tag = queue->tag;
970 if (prev)
971 prev->next = queue->next;
972 else
973 hpqueue = queue->next;
974 free(queue);
977 printf("ExtractPQ: %x got tag %d key %d\n", hPQ, tag, key);
979 return tag;
982 int
983 InsertPQ(HPQ hPQ, int tag, int key)
985 struct hpq *queueItem = malloc(sizeof(struct hpq));
986 queueItem->next = hpqueue;
987 hpqueue = queueItem;
988 queueItem->key = key;
989 queueItem->tag = tag;
991 printf("InsertPQ: %x %d %d\n", hPQ, tag, key);
992 return TRUE;
995 MinPQ(HPQ hPQ)
997 printf("MinPQ: %x\n", hPQ);
998 return 0;
1001 SizePQ(HPQ hPQ, int sizechange)
1003 printf("SizePQ: %x %d\n", hPQ, sizechange);
1004 return -1;
1008 * The following functions implement part of the spooling process to
1009 * print manager. I would like to see wine have a version of print managers
1010 * that used LPR/LPD. For simplicity print jobs will be sent to a file for
1011 * now.
1013 typedef struct PRINTJOB
1015 char *pszOutput;
1016 char *pszTitle;
1017 HDC16 hDC;
1018 HANDLE16 hHandle;
1019 int nIndex;
1020 int fd;
1021 } PRINTJOB, *PPRINTJOB;
1023 #define MAX_PRINT_JOBS 1
1024 #define SP_OK 1
1026 PPRINTJOB gPrintJobsTable[MAX_PRINT_JOBS];
1029 static PPRINTJOB FindPrintJobFromHandle(HANDLE16 hHandle)
1031 return gPrintJobsTable[0];
1034 /* TTD Need to do some DOS->UNIX file conversion here */
1035 static int CreateSpoolFile(LPSTR pszOutput)
1037 int fd;
1038 char szSpoolFile[32];
1040 /* TTD convert the 'output device' into a spool file name */
1042 if (pszOutput == NULL || *pszOutput == '\0')
1043 strcpy(szSpoolFile,"lp.out");
1044 else
1045 strcpy(szSpoolFile, pszOutput);
1047 if ((fd = open(szSpoolFile, O_CREAT | O_TRUNC | O_WRONLY , 0600)) < 0)
1049 printf("Failed to create spool file %s, errno = %d\n", szSpoolFile, errno);
1051 return fd;
1054 static int FreePrintJob(HANDLE16 hJob)
1056 int nRet = SP_ERROR;
1057 PPRINTJOB pPrintJob;
1059 pPrintJob = FindPrintJobFromHandle(hJob);
1060 if (pPrintJob != NULL)
1062 gPrintJobsTable[pPrintJob->nIndex] = NULL;
1063 free(pPrintJob->pszOutput);
1064 free(pPrintJob->pszTitle);
1065 if (pPrintJob->fd >= 0) close(pPrintJob->fd);
1066 free(pPrintJob);
1067 nRet = SP_OK;
1069 return nRet;
1072 HANDLE16 OpenJob(LPSTR lpOutput, LPSTR lpTitle, HDC16 hDC)
1074 HANDLE16 hHandle = SP_ERROR;
1075 PPRINTJOB pPrintJob;
1077 dprintf_win16drv(stddeb, "OpenJob: \"%s\" \"%s\" %04x\n", lpOutput, lpTitle, hDC);
1079 pPrintJob = gPrintJobsTable[0];
1080 if (pPrintJob == NULL)
1082 int fd;
1084 /* Try an create a spool file */
1085 fd = CreateSpoolFile(lpOutput);
1086 if (fd >= 0)
1088 hHandle = 1;
1090 pPrintJob = malloc(sizeof(PRINTJOB));
1091 memset(pPrintJob, 0, sizeof(PRINTJOB));
1093 pPrintJob->pszOutput = strdup(lpOutput);
1094 pPrintJob->pszTitle = strdup(lpTitle);
1095 pPrintJob->hDC = hDC;
1096 pPrintJob->fd = fd;
1097 pPrintJob->nIndex = 0;
1098 pPrintJob->hHandle = hHandle;
1099 gPrintJobsTable[pPrintJob->nIndex] = pPrintJob;
1102 dprintf_win16drv(stddeb, "OpenJob: return %04x\n", hHandle);
1103 return hHandle;
1106 int CloseJob(HANDLE16 hJob)
1108 int nRet = SP_ERROR;
1109 PPRINTJOB pPrintJob = NULL;
1111 dprintf_win16drv(stddeb, "CloseJob: %04x\n", hJob);
1113 pPrintJob = FindPrintJobFromHandle(hJob);
1114 if (pPrintJob != NULL)
1116 /* Close the spool file */
1117 close(pPrintJob->fd);
1118 FreePrintJob(hJob);
1119 nRet = 1;
1121 return nRet;
1124 int WriteSpool(HANDLE16 hJob, LPSTR lpData, WORD cch)
1126 int nRet = SP_ERROR;
1127 PPRINTJOB pPrintJob = NULL;
1129 dprintf_win16drv(stddeb, "WriteSpool: %04x %08lx %04x\n", hJob, (DWORD)lpData, cch);
1131 pPrintJob = FindPrintJobFromHandle(hJob);
1132 if (pPrintJob != NULL && pPrintJob->fd >= 0 && cch)
1134 if (write(pPrintJob->fd, lpData, cch) != cch)
1135 nRet = SP_OUTOFDISK;
1136 else
1137 nRet = cch;
1139 return nRet;
1142 int WriteDialog(HANDLE16 hJob, LPSTR lpMsg, WORD cchMsg)
1144 int nRet = 0;
1146 dprintf_win16drv(stddeb, "WriteDialog: %04x %04x \"%s\"\n", hJob, cchMsg, lpMsg);
1148 nRet = MessageBox16(NULL, lpMsg, "Printing Error", MB_OKCANCEL);
1149 return nRet;
1152 int DeleteJob(HANDLE16 hJob, WORD wNotUsed)
1154 int nRet;
1156 dprintf_win16drv(stddeb, "DeleteJob: %04x\n", hJob);
1158 nRet = FreePrintJob(hJob);
1159 return nRet;
1163 * The following two function would allow a page to be sent to the printer
1164 * when it has been processed. For simplicity they havn't been implemented.
1165 * This means a whole job has to be processed before it is sent to the printer.
1167 int StartSpoolPage(HANDLE16 hJob)
1169 dprintf_win16drv(stddeb, "StartSpoolPage GDI.246 unimplemented\n");
1170 return 1;
1173 int EndSpoolPage(HANDLE16 hJob)
1175 dprintf_win16drv(stddeb, "EndSpoolPage GDI.247 unimplemented\n");
1176 return 1;
1180 DWORD GetSpoolJob(int nOption, LONG param)
1182 DWORD retval = 0;
1183 dprintf_win16drv(stddeb, "In GetSpoolJob param 0x%lx noption %d\n",param, nOption);
1184 return retval;