Release 970215
[wine/hacks.git] / graphics / win16drv / init.c
blob3a9b7420a791ba33906241c00e16b718305ce1ea
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 NULL, /* 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 = GetProcAddress16(GetModuleHandle("GDI"),
694 (MAKEINTRESOURCE(158)));
696 if (pfnCallback != NULL)
698 WEPFC wepfc;
700 wepfc.nMode = 1;
701 wepfc.nCount = 0;
702 wepfc.pLPD = pLPD;
704 /* First count the number of fonts */
706 PRTDRV_EnumDFonts(physDev->segptrPDEVICE, NULL, pfnCallback,
707 (void *)&wepfc);
709 /* Allocate a buffer to store all of the fonts */
710 pLPD->nPrinterFonts = wepfc.nCount;
711 dprintf_win16drv(stddeb, "Got %d fonts\n",wepfc.nCount);
713 if (wepfc.nCount > 0)
716 pLPD->paPrinterFonts = malloc(sizeof(PRINTER_FONTS_INFO) * wepfc.nCount);
718 /* Now get all of the fonts */
719 wepfc.nMode = 2;
720 wepfc.nCount = 0;
721 PRTDRV_EnumDFonts(physDev->segptrPDEVICE, NULL, pfnCallback,
722 (void *)&wepfc);
727 /* Select the first font into the DC */
728 /* Set up the logfont */
729 memcpy(&physDev->lf,
730 &pLPD->paPrinterFonts[0].lf,
731 sizeof(LOGFONT16));
733 /* Set up the textmetrics */
734 memcpy(&physDev->tm,
735 &pLPD->paPrinterFonts[0].tm,
736 sizeof(TEXTMETRIC16));
738 #ifdef SUPPORT_REALIZED_FONTS
739 /* TTD should calculate this */
740 InitTextXForm(&TextXForm);
742 /* First get the size of the realized font */
743 nSize = PRTDRV_RealizeObject(physDev->segptrPDEVICE, OBJ_FONT,
744 &pLPD->paPrinterFonts[0], NULL,
745 NULL);
747 physDev->segptrFontInfo = WIN16_GlobalLock16(GlobalAlloc16(GHND, nSize));
748 /* Realize the font */
749 PRTDRV_RealizeObject(physDev->segptrPDEVICE, OBJ_FONT,
750 &pLPD->paPrinterFonts[0],
751 (LPVOID)physDev->segptrFontInfo,
752 &TextXForm);
753 /* Quick look at structure */
754 if (physDev->segptrFontInfo)
756 FONTINFO16 *p = (FONTINFO16 *)PTR_SEG_TO_LIN(physDev->segptrFontInfo);
758 dprintf_win16drv(stddeb, "T:%d VR:%d HR:%d, F:%d L:%d\n",
759 p->dfType,
760 p->dfVertRes, p->dfHorizRes,
761 p->dfFirstCHAR, p->dfLastCHAR
765 #endif
766 /* TTD Lots more to do here */
767 InitDrawMode(lpDrawMode);
769 return TRUE;
774 * Escape (GDI.38)
776 static INT32 WIN16DRV_Escape( DC *dc, INT32 nEscape, INT32 cbInput,
777 SEGPTR lpInData, SEGPTR lpOutData )
779 WIN16DRV_PDEVICE *physDev = (WIN16DRV_PDEVICE *)dc->physDev;
780 int nRet = 0;
782 /* We should really process the nEscape parameter, but for now just
783 pass it all to the driver */
784 if (dc != NULL && physDev->segptrPDEVICE != 0)
786 switch(nEscape)
788 case 0x9:
789 printf("Escape: SetAbortProc ignored\n");
790 break;
792 default:
793 nRet = PRTDRV_Control(physDev->segptrPDEVICE, nEscape,
794 lpInData, lpOutData);
797 else
798 fprintf(stderr, "Escape(nEscape = %04x)\n", nEscape);
799 return nRet;
802 DWORD PRTDRV_ExtTextOut(LPPDEVICE lpDestDev, WORD wDestXOrg, WORD wDestYOrg,
803 RECT16 *lpClipRect, LPCSTR lpString, WORD wCount,
804 SEGPTR lpFontInfo, LPDRAWMODE lpDrawMode,
805 LPTEXTXFORM16 lpTextXForm, SHORT *lpCharWidths,
806 RECT16 * lpOpaqueRect, WORD wOptions)
808 DWORD dwRet = 0;
809 LOADED_PRINTER_DRIVER *pLPD = NULL;
811 dprintf_win16drv(stddeb, "PRTDRV_ExtTextOut:\n");
813 if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
815 LONG lP1, lP4, lP5, lP7, lP8, lP9, lP10, lP11;
816 WORD wP2, wP3, wP12;
817 INT16 iP6;
819 SEGPTR SegPtr = pLPD->ThunkBufSegPtr;
820 SEGPTR Limit = pLPD->ThunkBufLimit;
821 int nSize;
823 if (pLPD->fn[FUNC_EXTTEXTOUT] == NULL)
825 dprintf_win16drv(stddeb, "PRTDRV_ExtTextOut: Not supported by driver\n");
826 return 0;
829 lP1 = lpDestDev;
830 wP2 = wDestXOrg;
831 wP3 = wDestYOrg;
833 if (lpClipRect != NULL)
835 lP4 = SegPtr;
836 nSize = sizeof(RECT16);
837 dprintf_win16drv(stddeb, "Adding lpClipRect\n");
839 AddData(&SegPtr, lpClipRect, nSize, Limit);
841 else
842 lP4 = 0L;
844 if (lpString != NULL)
846 /* TTD WARNING THIS STRING ISNT NULL TERMINATED */
847 lP5 = SegPtr;
848 nSize = strlen(lpString);
849 nSize = abs(wCount);
850 dprintf_win16drv(stddeb, "Adding string size %d\n",nSize);
852 AddData(&SegPtr, lpString, nSize, Limit);
854 else
855 lP5 = 0L;
857 iP6 = wCount;
859 /* This should be realized by the driver, so in 16bit data area */
860 lP7 = lpFontInfo;
862 if (lpDrawMode != NULL)
864 lP8 = SegPtr;
865 nSize = sizeof(DRAWMODE);
866 dprintf_win16drv(stddeb, "adding lpDrawMode\n");
868 AddData(&SegPtr, lpDrawMode, nSize, Limit);
870 else
871 lP8 = 0L;
873 if (lpTextXForm != NULL)
875 lP9 = SegPtr;
876 nSize = sizeof(TEXTXFORM16);
877 dprintf_win16drv(stddeb, "Adding TextXForm\n");
878 AddData(&SegPtr, lpTextXForm, nSize, Limit);
880 else
881 lP9 = 0L;
883 if (lpCharWidths != NULL)
884 dprintf_win16drv(stddeb, "PRTDRV_ExtTextOut: Char widths not supported\n");
885 lP10 = 0;
887 if (lpOpaqueRect != NULL)
889 lP11 = SegPtr;
890 nSize = sizeof(RECT16);
891 dprintf_win16drv(stddeb, "Adding opaqueRect\n");
892 AddData(&SegPtr, lpOpaqueRect, nSize, Limit);
894 else
895 lP11 = 0L;
897 wP12 = wOptions;
898 dprintf_win16drv(stddeb, "Calling exttextout 0x%lx 0x%x 0x%x 0x%lx\n0x%lx 0x%x 0x%lx 0x%lx\n"
899 "0x%lx 0x%lx 0x%lx 0x%x\n",lP1, wP2, wP3, lP4,
900 lP5, iP6, lP7, lP8, lP9, lP10,
901 lP11, wP12);
902 dwRet = CallTo16_long_lwwllwlllllw(pLPD->fn[FUNC_EXTTEXTOUT],
903 lP1, wP2, wP3, lP4,
904 lP5, iP6, lP7, lP8, lP9, lP10,
905 lP11, wP12);
906 if (lpDrawMode)
907 GetParamData(lP8, lpDrawMode, sizeof(DRAWMODE));
909 dprintf_win16drv(stddeb, "PRTDRV_ExtTextOut: return %lx\n", dwRet);
910 return dwRet;
915 /****************** misc. printer releated functions */
918 * The following function should implement a queing system
920 #ifndef HPQ
921 #define HPQ WORD
922 #endif
923 struct hpq
925 struct hpq *next;
926 int tag;
927 int key;
930 static struct hpq *hpqueue;
932 HPQ
933 CreatePQ(int size)
935 printf("CreatePQ: %d\n",size);
936 return 1;
938 int
939 DeletePQ(HPQ hPQ)
941 printf("DeletePQ: %x\n", hPQ);
942 return 0;
944 int
945 ExtractPQ(HPQ hPQ)
947 struct hpq *queue, *prev, *current, *currentPrev;
948 int key = 0, tag = -1;
949 currentPrev = prev = NULL;
950 queue = current = hpqueue;
951 if (current)
952 key = current->key;
954 while (current)
956 currentPrev = current;
957 current = current->next;
958 if (current)
960 if (current->key < key)
962 queue = current;
963 prev = currentPrev;
967 if (queue)
969 tag = queue->tag;
971 if (prev)
972 prev->next = queue->next;
973 else
974 hpqueue = queue->next;
975 free(queue);
978 printf("ExtractPQ: %x got tag %d key %d\n", hPQ, tag, key);
980 return tag;
983 int
984 InsertPQ(HPQ hPQ, int tag, int key)
986 struct hpq *queueItem = malloc(sizeof(struct hpq));
987 queueItem->next = hpqueue;
988 hpqueue = queueItem;
989 queueItem->key = key;
990 queueItem->tag = tag;
992 printf("InsertPQ: %x %d %d\n", hPQ, tag, key);
993 return TRUE;
996 MinPQ(HPQ hPQ)
998 printf("MinPQ: %x\n", hPQ);
999 return 0;
1002 SizePQ(HPQ hPQ, int sizechange)
1004 printf("SizePQ: %x %d\n", hPQ, sizechange);
1005 return -1;
1009 * The following functions implement part of the spooling process to
1010 * print manager. I would like to see wine have a version of print managers
1011 * that used LPR/LPD. For simplicity print jobs will be sent to a file for
1012 * now.
1014 typedef struct PRINTJOB
1016 char *pszOutput;
1017 char *pszTitle;
1018 HDC16 hDC;
1019 HANDLE16 hHandle;
1020 int nIndex;
1021 int fd;
1022 } PRINTJOB, *PPRINTJOB;
1024 #define MAX_PRINT_JOBS 1
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;