|
|
/******************************Module*Header*******************************\
* Module Name: output.c * * * * Client side stubs for graphics output calls. * * * * Created: 05-Jun-1991 01:41:18 * * Author: Charles Whitmer [chuckwh] * * * * Copyright (c) 1991-1999 Microsoft Corporation * \**************************************************************************/
#include "precomp.h"
#pragma hdrstop
// 2 seconds is way way too long for either non-preemptive wow apps or
// an input-synchronized journal situation (like w/mstest). 1/20 a second
// is much better - scottlu
//#define CALLBACK_INTERVAL 2000
// Even better - 1/4 a second
// scottlu
#define CALLBACK_INTERVAL 250
extern BOOL MF_WriteEscape(HDC hdc, int nEscape, int nCount, LPCSTR lpInData, int type );
//
// WINBUG #82877 2-7-2000 bhouse Need to move definition of ETO_NULL_PRCL
//
#define ETO_NULL_PRCL 0x80000000
ULONG GdiBatchLimit = 20;
const XFORM xformIdentity = { 1.00000000f, 0.00000000f, 0.00000000f, 1.00000000f, 0.00000000f, 0.00000000f };
/******************************Public*Routine******************************\
* AngleArc * * * * Client side stub. Copies all LDC attributes into the message. * * * * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
BOOL META WINAPI AngleArc( HDC hdc, int x, int y, DWORD r, FLOAT eA, FLOAT eB ) { BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return(bRet);
DC_PLDC(hdc,pldc,bRet);
if ((pldc->iType == LO_METADC) && !MF_AngleArc(hdc,x,y,r,eA,eB) ) return(bRet);
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
return(NtGdiAngleArc(hdc,x,y,r,FLOATARG(eA),FLOATARG(eB))); }
/******************************Public*Routine******************************\
* Arc * * * * Client side stub. Copies all LDC attributes into the message. * * * * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
BOOL META WINAPI Arc ( HDC hdc, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 ) { BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return (MF16_RecordParms9(hdc,x1,y1,x2,y2,x3,y3,x4,y4,META_ARC));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC) { if (!MF_ArcChordPie(hdc,x1,y1,x2,y2,x3,y3,x4,y4,EMR_ARC)) return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
return(NtGdiArcInternal(ARCTYPE_ARC,hdc,x1,y1,x2,y2,x3,y3,x4,y4));
}
/******************************Public*Routine******************************\
* ArcTo * * * * Client side stub. Copies all LDC attributes into the message. * * * * 12-Sep-1991 -by- J. Andrew Goossen [andrewgo] * * Wrote it. Cloned it from Arc. * \**************************************************************************/
BOOL META WINAPI ArcTo( HDC hdc, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 ) { BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return(bRet);
DC_PLDC(hdc,pldc,bRet);
if ((pldc->iType == LO_METADC) && !MF_ArcChordPie(hdc,x1,y1,x2,y2,x3,y3,x4,y4,EMR_ARCTO)) { return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
return(NtGdiArcInternal(ARCTYPE_ARCTO,hdc,x1,y1,x2,y2,x3,y3,x4,y4));
}
/******************************Public*Routine******************************\
* LineTo * * * * Client side stub. Copies all LDC attributes into the message. * * * * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
BOOL META WINAPI LineTo(HDC hdc,int x,int y) { BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return (MF16_RecordParms3(hdc,x,y,META_LINETO));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC) { if (!MF_SetDD(hdc,(DWORD)x,(DWORD)y,EMR_LINETO)) return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
return(NtGdiLineTo(hdc,x,y));
}
/******************************Public*Routine******************************\
* Chord * * * * Client side stub. Copies all LDC attributes into the message. * * * * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
BOOL META WINAPI Chord( HDC hdc, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 ) { BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return (MF16_RecordParms9(hdc,x1,y1,x2,y2,x3,y3,x4,y4,META_CHORD));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC) { if (!MF_ArcChordPie(hdc,x1,y1,x2,y2,x3,y3,x4,y4,EMR_CHORD)) return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
return(NtGdiArcInternal(ARCTYPE_CHORD,hdc,x1,y1,x2,y2,x3,y3,x4,y4));
}
/******************************Public*Routine******************************\
* Ellipse * * * * Client side stub. Copies all LDC attributes into the message. * * * * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
BOOL META WINAPI Ellipse(HDC hdc,int x1,int y1,int x2,int y2) { BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return (MF16_RecordParms5(hdc,x1,y1,x2,y2,META_ELLIPSE));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC) { if (!MF_EllipseRect(hdc,x1,y1,x2,y2,EMR_ELLIPSE)) return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
return(NtGdiEllipse(hdc,x1,y1,x2,y2));
}
/******************************Public*Routine******************************\
* Pie * * * * Client side stub. Copies all LDC attributes into the message. * * * * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
BOOL META WINAPI Pie( HDC hdc, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 ) { BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return (MF16_RecordParms9(hdc,x1,y1,x2,y2,x3,y3,x4,y4,META_PIE));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC) { if (!MF_ArcChordPie(hdc,x1,y1,x2,y2,x3,y3,x4,y4,EMR_PIE)) return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
return(NtGdiArcInternal(ARCTYPE_PIE,hdc,x1,y1,x2,y2,x3,y3,x4,y4));
}
/******************************Public*Routine******************************\
* Rectangle * * * * Client side stub. Copies all LDC attributes into the message. * * * * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
BOOL META WINAPI Rectangle(HDC hdc,int x1,int y1,int x2,int y2) { BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return (MF16_RecordParms5(hdc,x1,y1,x2,y2,META_RECTANGLE));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC) { if (!MF_EllipseRect(hdc,x1,y1,x2,y2,EMR_RECTANGLE)) return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
return(NtGdiRectangle(hdc,x1,y1,x2,y2));
}
/******************************Public*Routine******************************\
* RoundRect * * * * Client side stub. Copies all LDC attributes into the message. * * * * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
BOOL META WINAPI RoundRect( HDC hdc, int x1, int y1, int x2, int y2, int x3, int y3 ) { BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return (MF16_RecordParms7(hdc,x1,y1,x2,y2,x3,y3,META_ROUNDRECT));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC) { if (!MF_RoundRect(hdc,x1,y1,x2,y2,x3,y3)) return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
return(NtGdiRoundRect(hdc,x1,y1,x2,y2,x3,y3));
}
/******************************Public*Routine******************************\
* PatBlt * * * * Client side stub. Copies all LDC attributes into the message. * * * * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
BOOL META WINAPI PatBlt( HDC hdc, int x, int y, int cx, int cy, DWORD rop ) { BOOL bRet = FALSE; PDC_ATTR pdca;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return(MF16_RecordParmsWWWWD(hdc,(WORD)x,(WORD)y,(WORD)cx,(WORD)cy,rop,META_PATBLT));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC) { if (!MF_AnyBitBlt(hdc,x,y,cx,cy,(LPPOINT)NULL,(HDC)NULL,0,0,0,0,(HBITMAP)NULL,0,0,rop,EMR_BITBLT)) return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
PSHARED_GET_VALIDATE(pdca,hdc,DC_TYPE);
BEGIN_BATCH_HDC(hdc,pdca,BatchTypePatBlt,BATCHPATBLT);
//
// check DC to see if call can be batched, all DCs in use
// by the client must have a valid dc_attr
//
pBatch->rop4 = rop; pBatch->x = x; pBatch->y = y; pBatch->cx = cx; pBatch->cy = cy; pBatch->hbr = pdca->hbrush; pBatch->TextColor = (ULONG)pdca->crForegroundClr; pBatch->BackColor = (ULONG)pdca->crBackgroundClr; pBatch->DCBrushColor = (ULONG)pdca->crDCBrushClr; pBatch->IcmBrushColor = (ULONG)pdca->IcmBrushColor; pBatch->ptlViewportOrg = pdca->ptlViewportOrg; pBatch->ulTextColor = pdca->ulForegroundClr; pBatch->ulBackColor = pdca->ulBackgroundClr; pBatch->ulDCBrushColor = pdca->ulDCBrushClr;
COMPLETE_BATCH_COMMAND();
return(TRUE);
UNBATCHED_COMMAND:
return(NtGdiPatBlt(hdc,x,y,cx,cy,rop)); }
/******************************Public*Routine******************************\
* PolyPatBlt * * Arguments: * * hdc - dest DC * rop - ROP for all patblt elements * pPoly - pointer to array of PPOLYPATBLT structures * Count - number of polypatblts * Mode - mode for all polypatblts * * Return Value: * * BOOL Status * \**************************************************************************/
BOOL META WINAPI PolyPatBlt( HDC hdc, DWORD rop, PPOLYPATBLT pPoly, DWORD Count, DWORD Mode ) { BOOL bRet = FALSE; PDC_ATTR pdca;
FIXUP_HANDLE(hdc);
PSHARED_GET_VALIDATE(pdca,hdc,DC_TYPE);
// If ICM is enabled, we need to select the brush onto the DC in
// client side, so that ICM can translate brush color to DC color
// space. thus we can not use Batch, here. because Batch will selet
// the brush onto the DC in kernel side. so, there is no chance to
// ICM will be invoked.
if (IS_ALTDC_TYPE(hdc) || (pdca && IS_ICM_INSIDEDC(pdca->lIcmMode))) { ULONG Index; HBRUSH hOld = 0;
for (Index=0;Index<Count;Index++) { //
// select brush, save first to restore
//
if (Index == 0) { hOld = SelectObject(hdc,(HBRUSH)pPoly[0].BrClr.hbr); } else { SelectObject(hdc,(HBRUSH)pPoly[Index].BrClr.hbr); }
bRet = PatBlt(hdc, pPoly[Index].x, pPoly[Index].y, pPoly[Index].cx, pPoly[Index].cy, rop ); }
//
// restore brush if needed
//
if (hOld) { SelectObject(hdc,hOld); } } else { RESETUSERPOLLCOUNT();
if ((Count != 0) && (pPoly != NULL) && (Mode == PPB_BRUSH)) { USHORT uSize;
if (Count > (MAXUSHORT / sizeof(POLYPATBLT))) goto UNBATCHED_COMMAND;
//
// size of batched structure
//
uSize = (USHORT)(Count * sizeof(POLYPATBLT));
uSize += (USHORT)sizeof(BATCHPOLYPATBLT);
if (uSize < (USHORT)sizeof(BATCHPOLYPATBLT)) goto UNBATCHED_COMMAND; BEGIN_BATCH_HDC_SIZE(hdc,pdca,BatchTypePolyPatBlt,BATCHPOLYPATBLT,uSize);
pBatch->rop4 = rop; pBatch->Count = Count; pBatch->Mode = Mode; pBatch->TextColor = (ULONG)pdca->crForegroundClr; pBatch->BackColor = (ULONG)pdca->crBackgroundClr; pBatch->DCBrushColor = (ULONG)pdca->crDCBrushClr; pBatch->ptlViewportOrg = pdca->ptlViewportOrg; pBatch->ulTextColor = pdca->ulForegroundClr; pBatch->ulBackColor = pdca->ulBackgroundClr; pBatch->ulDCBrushColor = pdca->ulDCBrushClr;
memcpy(&pBatch->ulBuffer[0],pPoly,Count*sizeof(POLYPATBLT));
//
// if the first hbr entry is NULL, copy in current hbr so
// it is remembered.
//
if (((PPOLYPATBLT)(&pBatch->ulBuffer[0]))->BrClr.hbr == NULL) { ((PPOLYPATBLT)(&pBatch->ulBuffer[0]))->BrClr.hbr = pdca->hbrush; }
bRet = TRUE;
COMPLETE_BATCH_COMMAND();
UNBATCHED_COMMAND:
if (!bRet) { bRet = NtGdiPolyPatBlt(hdc,rop,pPoly,Count,Mode); } } }
return(bRet); }
/******************************Public*Routine******************************\
* BitBlt * * * * Client side stub. Copies all LDC attributes into the message. * * * * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
BOOL META WINAPI BitBlt( HDC hdc, int x, int y, int cx, int cy, HDC hdcSrc, int x1, int y1, DWORD rop ) { BOOL bRet = FALSE;
//
// if this call redueces to PatBlt, then let PatBlt
// do the metafile and/or output.
//
if ((((rop << 2) ^ rop) & 0x00CC0000) == 0) { return(PatBlt(hdc,x,y,cx,cy,rop)); }
//
// Src is required by ROP, do bitblt
//
FIXUP_HANDLE(hdc); FIXUP_HANDLE(hdcSrc);
if (gbICMEnabledOnceBefore) { PDC_ATTR pdcattr, pdcattrSrc;
PSHARED_GET_VALIDATE(pdcattr,hdc,DC_TYPE); PSHARED_GET_VALIDATE(pdcattrSrc,hdcSrc,DC_TYPE);
//
// if source DC has DIB section, and destination DC is ICM turned on
// do ICM-aware BitBlt.
//
if (pdcattr && pdcattrSrc) { if (IS_ICM_INSIDEDC(pdcattr->lIcmMode) && (bDIBSectionSelected(pdcattrSrc) || (IS_ICM_LAZY_CORRECTION(pdcattrSrc->lIcmMode) && (GetDCDWord(hdc,DDW_ISMEMDC,FALSE) == FALSE)))) { if (IcmStretchBlt(hdc,x,y,cx,cy,hdcSrc,x1,y1,cx,cy,rop,pdcattr,pdcattrSrc)) { return (TRUE); } } } }
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return (MF16_BitBlt(hdc,x,y,cx,cy,hdcSrc,x1,y1,rop));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC) { if (!MF_AnyBitBlt(hdc,x,y,cx,cy,(LPPOINT)NULL,hdcSrc,x1,y1,cx,cy,(HBITMAP)NULL,0,0,rop,EMR_BITBLT)) return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
//
// Define _WINDOWBLT_NOTIFICATION_ to turn on Window BLT notification.
// This notification will set a special flag in the SURFOBJ passed to
// drivers when the DrvCopyBits operation is called to move a window.
//
// See also:
// ntgdi\gre\maskblt.cxx
//
#ifdef _WINDOWBLT_NOTIFICATION_
return(NtGdiBitBlt(hdc,x,y,cx,cy,hdcSrc,x1,y1,rop,(COLORREF)-1,0)); #else
return(NtGdiBitBlt(hdc,x,y,cx,cy,hdcSrc,x1,y1,rop,(COLORREF)-1)); #endif
}
/******************************Public*Routine******************************\
* StretchBlt * * * * Client side stub. Copies all LDC attributes into the message. * * * * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
BOOL META WINAPI StretchBlt( HDC hdc, int x, int y, int cx, int cy, HDC hdcSrc, int x1, int y1, int cx1, int cy1, DWORD rop ) { BOOL bRet = FALSE;
FIXUP_HANDLE(hdc); FIXUP_HANDLEZ(hdcSrc);
if (gbICMEnabledOnceBefore) { PDC_ATTR pdcattr, pdcattrSrc;
PSHARED_GET_VALIDATE(pdcattr,hdc,DC_TYPE); PSHARED_GET_VALIDATE(pdcattrSrc,hdcSrc,DC_TYPE);
//
// if source DC has DIB section, and destination DC is ICM turned on
// do ICM-aware BitBlt.
//
if (pdcattr && pdcattrSrc) { if (IS_ICM_INSIDEDC(pdcattr->lIcmMode) && (bDIBSectionSelected(pdcattrSrc) || (IS_ICM_LAZY_CORRECTION(pdcattrSrc->lIcmMode) && (GetDCDWord(hdc,DDW_ISMEMDC,FALSE) == FALSE)))) { if (IcmStretchBlt(hdc,x,y,cx,cy,hdcSrc,x1,y1,cx1,cy1,rop,pdcattr,pdcattrSrc)) { return (TRUE); } } } }
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return (MF16_StretchBlt(hdc,x,y,cx,cy,hdcSrc,x1,y1,cx1,cy1,rop));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC) { if (!MF_AnyBitBlt(hdc,x,y,cx,cy,(LPPOINT)NULL,hdcSrc,x1,y1,cx1,cy1,(HBITMAP)NULL,0,0,rop,EMR_STRETCHBLT)) return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
return(NtGdiStretchBlt(hdc,x,y,cx,cy,hdcSrc,x1,y1,cx1,cy1,rop,(COLORREF)-1)); }
/******************************Public*Routine******************************\
* PlgBlt * * * * Client side stub. Copies all LDC attributes into the message. * * * * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
BOOL META WINAPI PlgBlt( HDC hdc, CONST POINT *pptl, HDC hdcSrc, int x1, int y1, int x2, int y2, HBITMAP hbm, int xMask, int yMask ) { BOOL bRet = FALSE;
FIXUP_HANDLE(hdc); FIXUP_HANDLEZ(hdcSrc); FIXUP_HANDLEZ(hbm);
// Check out the source DC and the mask(OPTIONAL).
if (!hdcSrc || IS_METADC16_TYPE(hdcSrc)) return(FALSE);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return(FALSE);
DC_PLDC(hdc,pldc,bRet);
if ((pldc->iType == LO_METADC) && !MF_AnyBitBlt(hdc,0,0,0,0,pptl,hdcSrc,x1,y1,x2,y2,hbm,xMask,yMask,0xCCAA0000,EMR_PLGBLT)) { return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
return(NtGdiPlgBlt(hdc,(POINT *)pptl,hdcSrc,x1,y1,x2,y2,hbm,xMask,yMask, GetBkColor(hdcSrc)));
}
/******************************Public*Routine******************************\
* MaskBlt * * * * Client side stub. Copies all LDC attributes into the message. * * * * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
BOOL META WINAPI MaskBlt( HDC hdc, int x, int y, int cx, int cy, HDC hdcSrc, int x1, int y1, HBITMAP hbm, int x2, int y2, DWORD rop ) { BOOL bRet = FALSE; ULONG crBackColor;
FIXUP_HANDLE(hdc); FIXUP_HANDLEZ(hdcSrc); FIXUP_HANDLEZ(hbm);
// Check out the source DC and the mask(OPTIONAL).
if (!hdcSrc || IS_METADC16_TYPE(hdcSrc)) return(FALSE);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return(FALSE);
DC_PLDC(hdc,pldc,bRet);
if ((pldc->iType == LO_METADC) && !MF_AnyBitBlt(hdc,x,y,cx,cy,(LPPOINT)NULL,hdcSrc,x1,y1,cx,cy,hbm,x2,y2,rop,EMR_MASKBLT)) { return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
crBackColor = GetBkColor(hdcSrc);
RESETUSERPOLLCOUNT();
// WINBUG #82879 2-7-2000 bhouse Possible bug in MaskBlt
// Old Comment:
// - GetBkColor should be performed in the kernel
// Not a problem. GetBkColor() picks up the color from the PEB DCattr cache.
return(NtGdiMaskBlt(hdc,x,y,cx,cy,hdcSrc,x1,y1,hbm,x2,y2,rop,crBackColor)); }
/******************************Public*Routine******************************\
* ExtFloodFill * * * * Client side stub. Copies all LDC attributes into the message. * * * * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
BOOL META WINAPI ExtFloodFill( HDC hdc, int x, int y, COLORREF color, UINT iMode ) { BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return(MF16_RecordParmsWWDW(hdc,(WORD)x,(WORD)y,(DWORD)color,(WORD)iMode,META_EXTFLOODFILL));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC) { if (!MF_ExtFloodFill(hdc,x,y,color,iMode)) return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
//
// if the specified COLORREF is not palette index,
// we need to do color conversion, when ICM is enabled.
//
if (!(color & 0x01000000)) { PDC_ATTR pdcattr;
PSHARED_GET_VALIDATE(pdcattr,hdc,DC_TYPE);
if (pdcattr && bNeedTranslateColor(pdcattr)) { COLORREF NewColor;
if (IcmTranslateCOLORREF(hdc,pdcattr,color,&NewColor,ICM_FORWARD)) { color = NewColor; } } }
return(NtGdiExtFloodFill(hdc,x,y,color,iMode)); }
/******************************Public*Routine******************************\
* FloodFill * * * * Just passes the call to the more general ExtFloodFill. * * * * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
BOOL WINAPI FloodFill(HDC hdc,int x,int y,COLORREF color) { return(ExtFloodFill(hdc,x,y,color,FLOODFILLBORDER)); }
/******************************Public*Routine******************************\
* PaintRgn * * * * Client side stub. Copies all LDC attributes into the message. * * * * 23-11-94 -by- Lingyun Wang [lingyunw] * Now hrgn is server side handle * * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
BOOL META WINAPI PaintRgn(HDC hdc,HRGN hrgn) { BOOL bRet = FALSE;
FIXUP_HANDLE(hdc); FIXUP_HANDLE(hrgn);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return(MF16_DrawRgn(hdc,hrgn,(HBRUSH)0,0,0,META_PAINTREGION));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC) { if (!MF_InvertPaintRgn(hdc,hrgn,EMR_PAINTRGN)) return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
return(NtGdiFillRgn(hdc,hrgn,(HBRUSH)GetDCObject(hdc,LO_BRUSH_TYPE)));
}
/******************************Public*Routine******************************\
* bBatchTextOut * * Attempt to batch a textout call on TEB * * Arguments: * * * * Return Value: * * TRUE means call is batched, FALSE means call could not be batched * * 18-Oct-1995 -by- Mark Enstrom [marke] * \**************************************************************************/
//
// full DWORDS!
//
#define MAX_BATCH_CCHAR ((GDI_BATCH_SIZE - sizeof(BATCHTEXTOUT)) & 0xfffffff0)
#define MAX_BATCH_WCHAR MAX_BATCH_CCHAR / 2
BOOL bBatchTextOut( HDC hdc, LONG x, LONG y, UINT fl, CONST RECT *prcl, LPCWSTR pwsz, CONST INT *pdx, UINT UnicodeCharCount, UINT ByteCount, DWORD dwCodePage ) { BOOL bRet = FALSE; ULONG AlignedByteCount; USHORT usSize; ULONG cjPdx; PDC_ATTR pdca;
AlignedByteCount = (ByteCount + sizeof(PVOID) - 1) & ~(sizeof(PVOID)-1); if( AlignedByteCount < ByteCount ) goto UNBATCHED_COMMAND; // arithmetic overflow
//
// account for pdx space if needed
//
if (pdx != NULL) { cjPdx = UnicodeCharCount * sizeof(INT); if (fl & ETO_PDY) cjPdx *= 2; if ((AlignedByteCount+cjPdx) < AlignedByteCount || BALLOC_OVERFLOW1(UnicodeCharCount,INT)) goto UNBATCHED_COMMAND; // arithmetic overflow
AlignedByteCount += cjPdx; }
usSize = (USHORT)(sizeof(BATCHTEXTOUT) + AlignedByteCount); if (usSize < AlignedByteCount) goto UNBATCHED_COMMAND; // arithmetic overflow
PSHARED_GET_VALIDATE(pdca,hdc,DC_TYPE);
BEGIN_BATCH_HDC_SIZE(hdc,pdca,BatchTypeTextOut,BATCHTEXTOUT,usSize);
if (pdca->lTextAlign & TA_UPDATECP) { goto UNBATCHED_COMMAND; }
pBatch->TextColor = (ULONG)pdca->crForegroundClr; pBatch->BackColor = (ULONG)pdca->crBackgroundClr; pBatch->BackMode = (ULONG)((pdca->lBkMode == OPAQUE) ? OPAQUE : TRANSPARENT); pBatch->ulTextColor = pdca->ulForegroundClr; pBatch->ulBackColor = pdca->ulBackgroundClr; pBatch->x = x; pBatch->y = y; pBatch->fl = fl; pBatch->cChar = UnicodeCharCount; pBatch->PdxOffset = 0; pBatch->dwCodePage = dwCodePage; pBatch->hlfntNew = pdca->hlfntNew; pBatch->flTextAlign = pdca->flTextAlign; pBatch->ptlViewportOrg = pdca->ptlViewportOrg;
//
// copy output RECT if needed
//
if (prcl != NULL) { pBatch->rcl.left = prcl->left; pBatch->rcl.top = prcl->top; pBatch->rcl.right = prcl->right; pBatch->rcl.bottom = prcl->bottom; } else { pBatch->fl |= ETO_NULL_PRCL; }
//
// copy characters
//
if (ByteCount) { RtlCopyMemory((PUCHAR)&pBatch->ulBuffer[0],(PUCHAR)pwsz,ByteCount); }
//
// copy pdx array
//
if (pdx != NULL) { //
// start pdx at INT aligned offset after WCAHR data
//
pBatch->PdxOffset = (ByteCount + 3) & 0xfffffffc;
RtlCopyMemory((PUCHAR)&pBatch->ulBuffer[0] + pBatch->PdxOffset, (PUCHAR)pdx, cjPdx); }
bRet = TRUE;
COMPLETE_BATCH_COMMAND();
UNBATCHED_COMMAND:
return(bRet); }
/******************************Public*Routine******************************\
* * BOOL META WINAPI ExtTextOutW * * similar to traditional ExtTextOut, except that it takes UNICODE string * * History: * Thu 28-Apr-1994 -by- Patrick Haluptzok [patrickh] * Special Case 0 char case for Winbench4.0 * * 05-Aug-1991 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL META WINAPI ExtTextOutW( HDC hdc, int x, int y, UINT fl, CONST RECT *prcl, LPCWSTR pwsz, UINT c, // count of bytes = 2 * (# of WCHAR's)
CONST INT *pdx ) { BOOL bRet = FALSE; BOOL bEMFDriverComment = FALSE;
if ((fl & ETO_PDY) && !pdx) return FALSE;
// if we do not know what to do with the rectangle, ignore it.
if (prcl && !(fl & (ETO_OPAQUE | ETO_CLIPPED))) { prcl = NULL; } if (!prcl) { fl &= ~(ETO_CLIPPED | ETO_OPAQUE); // ignore flags if no rect, win95 compat
}
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return (MF16_ExtTextOut(hdc,x,y,fl,prcl,(LPCSTR)pwsz,c,pdx,TRUE));
DC_PLDC(hdc,pldc,bRet);
// if we are EMF spooling then metafile glyph index calls, otherwise don't
// if we are EMF spooling then metafile glyph index calls, otherwise don't
/*
LDC_META_PRINT ETO_GLYPH_INDEX ETO_IGNORELANGUAGE gbLpk MetaFileTheCall 0 0 0 0 1 0 0 0 1 1 0 0 1 0 1 Case1 0 0 1 1 0
Case2 0 1 0 0 0 0 1 0 1 1 <-Win95 Compatability Case2 0 1 1 0 0 0 1 1 1 1 <-Win95 Compatability
1 0 0 0 1 Case3 1 0 0 1 0 1 0 1 0 1 1 0 1 1 1
1 1 0 0 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 1
*/ // Now we will metafile the glyph index call (i.e. with ETO_GLYPH_INDEX) for ExtTextOutW.
// This is to support MS OutLook-97/BiDi, since it DEPENDS on this feature!!. Win95/BiDi allowed
// metafiling of GIs on ETOW, but rejects GIs metafiling calls to ETOA.
// This is not neat, but we have to do it to support our Apps.
if (pldc->iType == LO_METADC) { BOOL bPrintToEMFDriver = pldc->pUMPD ? pldc->pUMPD->dwFlags & UMPDFLAG_METAFILE_DRIVER : FALSE;
BOOL bLpkEmfCase1 = !(pldc->fl & LDC_META_PRINT) && !(fl & ETO_GLYPH_INDEX) && (fl & ETO_IGNORELANGUAGE) && gbLpk;
BOOL bLpkEmfCase2 = !(pldc->fl & LDC_META_PRINT) && (fl & ETO_GLYPH_INDEX) && !gbLpk;
BOOL bLpkEmfCase3 = (pldc->fl & LDC_META_PRINT) && !(fl & ETO_GLYPH_INDEX) && !(fl & ETO_IGNORELANGUAGE) && gbLpk;
// Record a special comment containing the original
// Unicode string for the ExtTextOutW call
if (bLpkEmfCase3 && bPrintToEMFDriver) { ULONG nSize = 3*sizeof(DWORD) + c*sizeof(WCHAR); DWORD *lpData;
// double check that we didn't have an arithmetic overflow
// in the calculation of nSize -- if so, lpData can have
// a buffer overflow
if( c >= (MAXIMUM_POOL_ALLOC - 3*sizeof(DWORD) - 3)/sizeof(WCHAR)) { GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } lpData = LOCALALLOC(ROUNDUP_DWORDALIGN(nSize));
if (lpData) { lpData[0] = GDICOMMENT_IDENTIFIER; lpData[1] = GDICOMMENT_UNICODE_STRING; lpData[2] = c; // number of wchars in the unicode string
RtlCopyMemory((PBYTE)(lpData+3), pwsz, c*sizeof(WCHAR));
if (!MF_GdiComment(hdc,nSize,(PBYTE)lpData)) { LOCALFREE(lpData); return bRet; }
LOCALFREE(lpData);
bEMFDriverComment = TRUE; } }
if (!bLpkEmfCase1 && !bLpkEmfCase2 && !bLpkEmfCase3 && !MF_ExtTextOut(hdc,x,y,fl,prcl,(LPCSTR) pwsz,c,pdx,EMR_EXTTEXTOUTW)) { return(bRet); }
}
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
#ifdef LANGPACK
if(gbLpk && !(fl & ETO_GLYPH_INDEX) && !(fl & ETO_IGNORELANGUAGE)) { bRet = ((*fpLpkExtTextOut)(hdc, x, y, fl, prcl, pwsz, c, pdx, -1));
if (bEMFDriverComment) { DWORD lpData[2];
lpData[0] = GDICOMMENT_IDENTIFIER; lpData[1] = GDICOMMENT_UNICODE_END;
bRet = MF_GdiComment(hdc,2*sizeof(DWORD),(PBYTE)lpData);
ASSERTGDI(bRet, "failed to write the GDICOMMENT_UNICODE_END comment\n"); }
return(bRet); } #endif
bRet = FALSE;
if (c <= MAX_BATCH_WCHAR) { if ((c == 0) && (prcl != NULL)) { if (fl & ETO_OPAQUE) { //
// attempt to batch the text out rect
//
PDC_ATTR pdca;
PSHARED_GET_VALIDATE(pdca,hdc,DC_TYPE);
if ((pdca != NULL) && !(pdca->lTextAlign & TA_UPDATECP)) { BEGIN_BATCH_HDC(hdc,pdca,BatchTypeTextOutRect,BATCHTEXTOUTRECT);
pBatch->BackColor = pdca->crBackgroundClr; pBatch->fl = fl; pBatch->rcl.left = prcl->left; pBatch->rcl.top = prcl->top; pBatch->rcl.right = prcl->right; pBatch->rcl.bottom = prcl->bottom; pBatch->ptlViewportOrg = pdca->ptlViewportOrg; pBatch->ulBackColor = pdca->ulBackgroundClr;
bRet = TRUE;
COMPLETE_BATCH_COMMAND(); } } else { bRet = TRUE; } } else { bRet = bBatchTextOut(hdc, x, y, fl, (LPRECT)prcl, (LPWSTR)pwsz, pdx, c, 2 * c, 0); } }
UNBATCHED_COMMAND:
if (!bRet) { bRet = NtGdiExtTextOutW(hdc, x, y, fl, (LPRECT)prcl, (LPWSTR)pwsz, c, (LPINT)pdx, 0); }
return(bRet); }
/******************************Public*Routine******************************\
* PolyTextOutW * * Arguments: * * hdc - handle to device context * ppt - pointer to array of POLYTEXTW * nstrings - length of POLYTEXTW array * * Return Value: * * status * * History: * 7/31/92 -by- Paul Butzi and Eric Kutter * \**************************************************************************/
BOOL META WINAPI PolyTextOutW(HDC hdc,CONST POLYTEXTW *ppt,INT nstrings) {
BOOL bRet = FALSE; CONST POLYTEXTW *pp;
FIXUP_HANDLE(hdc);
if (nstrings == 0) { bRet = TRUE; } else if (nstrings < 0) { GdiSetLastError(ERROR_INVALID_PARAMETER); bRet = FALSE; } else {
//
// Search for error case with string with non-0 length but sting == NULL
//
for ( pp = ppt; pp < (ppt + nstrings); pp += 1 ) { if ( pp->lpstr == NULL) { //
// return failure if they have a non 0 length string with NULL
//
if (pp->n != 0) { GdiSetLastError(ERROR_INVALID_PARAMETER); return(FALSE); } } }
//
// If we need to metafile, or print
//
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) { return ( MF16_PolyTextOut( hdc, (CONST POLYTEXTA*) ppt, nstrings, TRUE // mrType == EMR_POLYTEXTOUTW
) ); }
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC) { if ( !MF_PolyTextOut( hdc, (CONST POLYTEXTA*) ppt, nstrings, EMR_POLYTEXTOUTW ) ) return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) { vSAPCallback(pldc); }
if (pldc->fl & LDC_DOC_CANCELLED) { return(bRet); }
if (pldc->fl & LDC_CALL_STARTPAGE) { StartPage(hdc); } }
bRet = NtGdiPolyTextOutW(hdc,(POLYTEXTW *)ppt,nstrings, 0); }
return(bRet); }
/******************************Public*Routine******************************\
* PolyTextOutA * * Arguments: * * hdc - handle to device context * ppt - pointer to array of POLYTEXTA * nstrings - length of POLYTEXTA array * * Return Value: * * status * * History: * 7/31/92 -by- Paul Butzi and Eric Kutter * \**************************************************************************/
BOOL META WINAPI PolyTextOutA(HDC hdc, CONST POLYTEXTA *ppt, INT nstrings) {
//
// Convert text to UNICODE and make call
//
POLYTEXTW *pp, *pPolyTextW;
UINT szTotal = 0; INT cjdx; BOOL bRet = FALSE; BOOL bDBCSCodePage; int i; PVOID pCharBuffer; PBYTE pj; DWORD dwCodePage;
FIXUP_HANDLE(hdc);
if (nstrings == 0) { return(TRUE); }
if (nstrings < 0) { GdiSetLastError(ERROR_INVALID_PARAMETER); return(FALSE); }
//
// Figure out the size needed
//
pPolyTextW = (POLYTEXTW*) ppt;
if( BALLOC_OVERFLOW1(nstrings,POLYTEXTW) ) { GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } szTotal = sizeof(POLYTEXTW) * nstrings;
for ( pp = pPolyTextW; pp < (pPolyTextW + nstrings); pp ++) { if (pp->lpstr != NULL) { if( BALLOC_OVERFLOW1(pp->n,WCHAR) || (szTotal + pp->n*sizeof(WCHAR)) < szTotal ) { GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } szTotal += pp->n * sizeof(WCHAR);
if ( pp->pdx != NULL ) { cjdx = pp->n * sizeof(int); if (pp->uiFlags & ETO_PDY) cjdx *= 2;
if( (szTotal + cjdx) < szTotal ) { GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } szTotal += cjdx; } } else { //
// return failure if they have a non 0 length string with NULL
//
if (pp->n != 0) { GdiSetLastError(ERROR_INVALID_PARAMETER); return(FALSE); } } }
//
// If we need to metafile, or print
//
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) { return ( MF16_PolyTextOut( hdc, (CONST POLYTEXTA*) pPolyTextW, nstrings, FALSE ) ); }
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC) { if ( !MF_PolyTextOut( hdc, (CONST POLYTEXTA*) pPolyTextW, nstrings, EMR_POLYTEXTOUTA ) ) return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) { vSAPCallback(pldc); }
if (pldc->fl & LDC_DOC_CANCELLED) { return(bRet); }
if (pldc->fl & LDC_CALL_STARTPAGE) { StartPage(hdc); } }
//
// alloc memory for WHCAR structures
//
pCharBuffer = LOCALALLOC(szTotal);
if (pCharBuffer == NULL) { return(FALSE); }
RtlCopyMemory(pCharBuffer, (PBYTE) pPolyTextW, nstrings*sizeof(POLYTEXTW)); pp = (POLYTEXTW *)pCharBuffer;
//
// now copy the stuff into the buffer
//
pj = (PBYTE)pCharBuffer + nstrings*sizeof(POLYTEXTW);
dwCodePage = GetCodePage(hdc);
bDBCSCodePage = IS_ANY_DBCS_CODEPAGE(dwCodePage);
for ( i = 0; i < nstrings; i += 1 ) { if ((pp[i].pdx != NULL) && (pp[i].lpstr != NULL)) { // patch pdx
cjdx = pp[i].n * sizeof(INT); if (pp[i].uiFlags & ETO_PDY) cjdx *= 2;
if(bDBCSCodePage) { ConvertDxArray(dwCodePage, (char*) pp[i].lpstr, pp[i].pdx, pp[i].n, (int*) pj, pp[i].uiFlags & ETO_PDY ); } else { RtlCopyMemory(pj,pp[i].pdx,cjdx); }
pp[i].pdx = (int *)pj;
pj += cjdx; } }
for ( i = 0; i < nstrings; i += 1 ) { if ( pp[i].lpstr != NULL ) { pp[i].n = MultiByteToWideChar(dwCodePage, 0, (LPSTR) pp[i].lpstr, pp[i].n, (LPWSTR) pj, pp[i].n*sizeof(WCHAR));
// patch lpstr
pp[i].lpstr = (LPWSTR)pj;
pj += pp[i].n * sizeof(WCHAR); } }
//
// send off the message and cleanup
//
bRet = NtGdiPolyTextOutW(hdc,(POLYTEXTW *)pCharBuffer,nstrings,dwCodePage);
LOCALFREE(pCharBuffer);
return(bRet); }
/******************************Public*Routine******************************\
* * BOOL META WINAPI TextOutW * * * * History: * 07-Aug-1991 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL META WINAPI TextOutW( HDC hdc, int x, int y, LPCWSTR pwsz, int c ) { BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if ((c <= 0) || (pwsz == (LPCWSTR) NULL)) { if (c == 0) return(TRUE);
GdiSetLastError(ERROR_INVALID_PARAMETER); return(FALSE); }
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return(MF16_TextOut(hdc,x,y,(LPCSTR) pwsz,c,TRUE));
DC_PLDC(hdc,pldc,bRet);
if((pldc->iType == LO_METADC) && (!(pldc->fl & LDC_META_PRINT) || !gbLpk)) {
if (!MF_ExtTextOut(hdc,x,y,0,(LPRECT)NULL,(LPCSTR) pwsz,c,(LPINT)NULL,EMR_EXTTEXTOUTW)) return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
#ifdef LANGPACK
if(gbLpk) { return((*fpLpkExtTextOut)(hdc, x, y, 0, NULL, pwsz, c, 0, -1)); } #endif
if ((c <= MAX_BATCH_WCHAR) && (GdiBatchLimit > 1)) { bRet = bBatchTextOut(hdc, x, y, 0, (LPRECT)NULL, (LPWSTR)pwsz, NULL, c, 2 *c, 0); }
if (!bRet) { bRet = NtGdiExtTextOutW(hdc, x, y, 0, 0, (LPWSTR)pwsz, c, 0, 0); }
return(bRet);
}
/******************************Public*Routine******************************\
* * DWORD GetCodePage(HDC hdc) * * Effects: returns the code page of the font selected in the dc * * History: * 23-May-1995 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
DWORD GetCodePage(HDC hdc) { PDC_ATTR pDcAttr;
FIXUP_HANDLE(hdc);
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
if (pDcAttr) {
if (!(pDcAttr->ulDirty_ & DIRTY_CHARSET)) return (0x0000ffff & pDcAttr->iCS_CP); // mask charset
} else { GdiSetLastError(ERROR_INVALID_PARAMETER); return guintAcp; // reasonable default;
}
// we end up here if the code page attributes are dirty so that
// we have to call to the kernel, force the mapping and retrieve
// the code page and char set of the font selected in the dc:
return (0x0000ffff & NtGdiGetCharSet(hdc)); // mask charset
}
/******************************Public*Routine******************************\
* * BOOL META WINAPI ExtTextOutA * History: * 07-Aug-1991 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
#define CAPTURE_STRING_SIZE 130
// not in kernel, it is ok to do this much on the stack
BOOL META WINAPI ExtTextOutInternalA( HDC hdc, int x, int y, UINT fl, CONST RECT *prcl, LPCSTR psz, UINT c, CONST INT *pdx, BOOL bFromTextOut ) { BOOL bRet = FALSE; DWORD dwCodePage; BOOL bDBCSCodePage;
if ((fl & ETO_PDY) && !pdx) return FALSE;
// if we do not know what to do with the rectangle, ignore it.
if (prcl && !(fl & (ETO_OPAQUE | ETO_CLIPPED))) { prcl = NULL; } if (!prcl) { fl &= ~(ETO_CLIPPED | ETO_OPAQUE); // ignore flags if no rect, win95 compat
}
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) { if(bFromTextOut) { // yes this matters, some apps rely on TextOutA being metafiled at
// TextOut and not ExtTextOutA
return(MF16_TextOut(hdc,x,y,psz,c,FALSE)); } else { return (MF16_ExtTextOut(hdc,x,y,fl,prcl,psz,c,pdx,FALSE)); } }
DC_PLDC(hdc,pldc,bRet);
// if we are EMF spooling then metafile glyph index calls, otherwise don't
if((pldc->iType == LO_METADC) && (!((!(pldc->fl & LDC_META_PRINT) && (fl & ETO_GLYPH_INDEX)) || ((pldc->fl & LDC_META_PRINT) && !(fl & ETO_GLYPH_INDEX) && (gbLpk) && !(fl & ETO_IGNORELANGUAGE) && c)) || (!(pldc->fl & LDC_META_PRINT) && (!(fl & ETO_GLYPH_INDEX)) && (fl & ETO_IGNORELANGUAGE) && (gbLpk)) ) ) { DWORD mrType = (fl & ETO_GLYPH_INDEX) ? EMR_EXTTEXTOUTW : EMR_EXTTEXTOUTA ;
if (!MF_ExtTextOut(hdc,x,y,fl,prcl,psz,c, pdx, mrType)) return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
if (fl & ETO_GLYPH_INDEX) {
bRet = FALSE;
if ((c <= MAX_BATCH_WCHAR) && (GdiBatchLimit > 1)) {
bRet = bBatchTextOut(hdc, x, y, fl, (LPRECT)prcl, (LPWSTR)psz, pdx, c, 2*c, 0); }
if (!bRet) { bRet = NtGdiExtTextOutW(hdc, x,y, fl, (LPRECT)prcl, (LPWSTR)psz, (int)c, (LPINT)pdx, 0); }
return(bRet); }
// Get code page
dwCodePage = GetCodePage(hdc);
if(fFontAssocStatus) { dwCodePage = FontAssocHack(dwCodePage,(char*)psz,c); }
bDBCSCodePage = IS_ANY_DBCS_CODEPAGE(dwCodePage);
if (c) { // get the code page of the font selected in the dc
WCHAR awcCaptureBuffer[CAPTURE_STRING_SIZE]; PWSZ pwszCapt; INT aiDxCaptureBuffer[CAPTURE_STRING_SIZE*2]; // times 2 for pdy
INT *pDxCapture;
// Allocate the string buffer
if (c <= CAPTURE_STRING_SIZE) { pwszCapt = awcCaptureBuffer; } else { if(bDBCSCodePage) { pwszCapt = ((c+1) >= MAXIMUM_POOL_ALLOC/(sizeof(WCHAR)+2*sizeof(INT))) ? (PWSZ) 0 : LOCALALLOC((c+1) * (sizeof(WCHAR)+ 2 * sizeof(INT))); pDxCapture = (INT*) &pwszCapt[(c+1)&~1]; // ^
} // |
else // for pdy, just in case
{ pwszCapt = BALLOC_OVERFLOW1(c,WCHAR) ? ((PWSZ) 0) : LOCALALLOC(c * sizeof(WCHAR)); } }
if (pwszCapt) { UINT u;
if(bDBCSCodePage && pdx) { if(c <= CAPTURE_STRING_SIZE) { pDxCapture = aiDxCaptureBuffer; }
ConvertDxArray(dwCodePage,(char*) psz,(int*) pdx,c,pDxCapture, fl & ETO_PDY); } else { pDxCapture = (int*) pdx; }
u = MultiByteToWideChar( dwCodePage, 0, psz,c, pwszCapt, c*sizeof(WCHAR));
if (u) { bRet = FALSE;
#ifdef LANGPACK
if (gbLpk && !(fl & ETO_IGNORELANGUAGE)) { bRet = ((*fpLpkExtTextOut)(hdc, x, y, fl, prcl, pwszCapt, u, pDxCapture, 0));
if (pwszCapt != awcCaptureBuffer) LOCALFREE(pwszCapt);
return bRet; } #endif
if ((c <= MAX_BATCH_WCHAR) && (GdiBatchLimit > 1)) { bRet = bBatchTextOut(hdc, x, y, fl, (LPRECT)prcl, (LPWSTR)pwszCapt, pDxCapture, u, 2 * u, dwCodePage ); }
if (!bRet) { bRet = NtGdiExtTextOutW( hdc, x,y, fl, (LPRECT)prcl, (LPWSTR)pwszCapt,(int)u, pDxCapture, dwCodePage); }
}
if (pwszCapt != awcCaptureBuffer) LOCALFREE(pwszCapt); } else { GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY); } } else {
bRet = FALSE;
if ((prcl != NULL) && (fl & ETO_OPAQUE)) { //
// try to batch text out rect
//
PDC_ATTR pdca;
PSHARED_GET_VALIDATE(pdca,hdc,DC_TYPE);
if ((pdca != NULL) && !(pdca->lTextAlign & TA_UPDATECP)) { BEGIN_BATCH_HDC(hdc,pdca,BatchTypeTextOutRect,BATCHTEXTOUTRECT);
pBatch->BackColor = pdca->crBackgroundClr; pBatch->fl = fl; pBatch->rcl.left = prcl->left; pBatch->rcl.top = prcl->top; pBatch->rcl.right = prcl->right; pBatch->rcl.bottom = prcl->bottom; pBatch->ptlViewportOrg = pdca->ptlViewportOrg;
bRet = TRUE;
COMPLETE_BATCH_COMMAND(); } }
UNBATCHED_COMMAND:
if (!bRet) { bRet = NtGdiExtTextOutW(hdc, x,y, fl, (LPRECT)prcl, NULL,0,NULL,dwCodePage); } }
return(bRet); }
BOOL META WINAPI ExtTextOutA( HDC hdc, int x, int y, UINT fl, CONST RECT *prcl, LPCSTR psz, UINT c, CONST INT *pdx ) { return(ExtTextOutInternalA(hdc,x,y,fl,prcl,psz,c,pdx,FALSE)); }
/******************************Public*Routine******************************\
* * BOOL META WINAPI TextOut * * History: * 07-Aug-1991 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL META WINAPI TextOutA( HDC hdc, int x, int y, LPCSTR psz, int c ) { BOOL bRet = FALSE;
if ((c <= 0) || (psz == (LPCSTR) NULL)) { if (c == 0) return(TRUE);
GdiSetLastError(ERROR_INVALID_PARAMETER); return(FALSE); } return ExtTextOutInternalA(hdc, x, y, 0, NULL, psz, c, NULL, TRUE); }
/******************************Public*Routine******************************\
* FillRgn * * * * Client side stub. Copies all LDC attributes into the message. * * * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
BOOL META WINAPI FillRgn(HDC hdc,HRGN hrgn,HBRUSH hbrush) { BOOL bRet = FALSE;
FIXUP_HANDLE(hdc); FIXUP_HANDLE(hrgn); FIXUP_HANDLE(hbrush);
// validate the region and brush.
if (!hrgn || !hbrush) return(bRet);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return(MF16_DrawRgn(hdc,hrgn,hbrush,0,0,META_FILLREGION));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC) { if (!MF_FillRgn(hdc,hrgn,hbrush)) return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
return(NtGdiFillRgn(hdc,hrgn,hbrush)); }
/******************************Public*Routine******************************\
* FrameRgn * * * * Client side stub. Copies all LDC attributes into the message. * * * 23-11-94 -by- Lingyun Wang [lingyunw] * Now hrgn and hbrush are server side handles * * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
BOOL META WINAPI FrameRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush, int cx, int cy ) { BOOL bRet = FALSE;
FIXUP_HANDLE(hdc); FIXUP_HANDLE(hrgn); FIXUP_HANDLE(hbrush);
if (!hrgn || !hbrush) return(FALSE);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return(MF16_DrawRgn(hdc,hrgn,hbrush,cx,cy,META_FRAMEREGION));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC) { if (!MF_FrameRgn(hdc,hrgn,hbrush,cx,cy)) return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
return(NtGdiFrameRgn(hdc,hrgn,hbrush,cx,cy)); }
/******************************Public*Routine******************************\
* InvertRgn * * * * Client side stub. * * * 23-11-94 -by- Lingyun Wang [lingyunw] * Now hrgn is server side handle * * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
BOOL META WINAPI InvertRgn(HDC hdc,HRGN hrgn) { BOOL bRet = FALSE;
FIXUP_HANDLE(hdc); FIXUP_HANDLE(hrgn);
if (!hrgn) return(FALSE);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return(MF16_DrawRgn(hdc,hrgn,(HBRUSH)0,0,0,META_INVERTREGION));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC) { if (!MF_InvertPaintRgn(hdc,hrgn,EMR_INVERTRGN)) return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
return(NtGdiInvertRgn(hdc,hrgn)); }
/******************************Public*Routine******************************\
* SetPixelV * * * * Client side stub. This is a version of SetPixel that does not return a * * value. This one can be batched for better performance. * * * * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
BOOL META WINAPI SetPixelV(HDC hdc,int x,int y,COLORREF color) { BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return(MF16_RecordParmsWWD(hdc,(WORD)x,(WORD)y,(DWORD)color,META_SETPIXEL));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC) { if (!MF_SetPixelV(hdc,x,y,color)) return(bRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
//
// ICM conversion (only happen for non-palette index color)
//
if (!(color & 0x01000000)) { PDC_ATTR pdca;
PSHARED_GET_VALIDATE(pdca,hdc,DC_TYPE);
if (pdca && bNeedTranslateColor(pdca)) { COLORREF NewColor;
if (IcmTranslateCOLORREF(hdc,pdca,color,&NewColor,ICM_FORWARD)) { color = NewColor; } } }
return(NtGdiSetPixel(hdc,x,y,color) != CLR_INVALID); }
/******************************Public*Routine******************************\
* SetPixel * * * * Client side stub. * * * * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
COLORREF META WINAPI SetPixel(HDC hdc,int x,int y,COLORREF color) { ULONG iRet = CLR_INVALID; COLORREF ColorRet = CLR_INVALID; COLORREF NewColor; BOOL bStatus; PDC_ATTR pdca;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
if (IS_METADC16_TYPE(hdc)) return(MF16_RecordParmsWWD(hdc,(WORD)x,(WORD)y,(DWORD)color,META_SETPIXEL));
DC_PLDC(hdc,pldc,iRet);
if (pldc->iType == LO_METADC) { if (!MF_SetPixelV(hdc,x,y,color)) return(iRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(iRet);
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
RESETUSERPOLLCOUNT();
PSHARED_GET_VALIDATE(pdca,hdc,DC_TYPE);
if (pdca) { //
// if the color is not a PaletteIndex and ICM is on then translate
//
if (!(color & 0x01000000) && bNeedTranslateColor(pdca)) { bStatus = IcmTranslateCOLORREF(hdc, pdca, color, &NewColor, ICM_FORWARD); if (bStatus) { color = NewColor; } }
ColorRet = NtGdiSetPixel(hdc,x,y,color);
if ( bNeedTranslateColor(pdca) && ( IS_32BITS_COLOR(pdca->lIcmMode) || ((ColorRet != CLR_INVALID) && !(ColorRet & 0x01000000)) ) ) { //
// Translate back to original color
//
bStatus = IcmTranslateCOLORREF(hdc, pdca, ColorRet, &NewColor, ICM_BACKWARD); if (bStatus) { ColorRet = NewColor; } } } else { GdiSetLastError(ERROR_INVALID_PARAMETER); }
return(ColorRet); }
/******************************Public*Routine******************************\
* UpdateColors * * * * Client side stub. * * * * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
BOOL WINAPI UpdateColors(HDC hdc) { BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
RESETUSERPOLLCOUNT();
return(NtGdiUpdateColors(hdc)); }
/******************************Public*Routine******************************\
* GdiFlush * * * * Client side stub. * * * * Wed 26-Jun-1991 13:58:00 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
BOOL WINAPI GdiFlush(VOID) {
NtGdiFlush(); return(TRUE); }
/******************************Public*Routine******************************\
* GdiSetBatchLimit * * * History: * 31-Jul-1991 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/
DWORD WINAPI GdiSetBatchLimit( DWORD dwNewBatchLimit ) { DWORD OldLimit = 0;
//
// set batch limit (as long as it is (1 <= l <= 20))
// return old limit if successful. A new batch limit of 0
// means set to default (20)
//
if (dwNewBatchLimit == 0) { dwNewBatchLimit = 20; }
if ((dwNewBatchLimit > 0 ) && (dwNewBatchLimit <= 20)) { GdiFlush(); OldLimit = GdiBatchLimit; GdiBatchLimit = dwNewBatchLimit; }
return(OldLimit); }
/******************************Public*Routine******************************\
* GdiGetBatchLimit * * History: * 7-Apr-1992 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
DWORD WINAPI GdiGetBatchLimit() { return(GdiBatchLimit); }
/******************************Public*Routine******************************\
* EndPage * * Client side stub. * * History: * Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] * Wrote it. * 9/16/97 - Ramananthan N. Venkatpathy [RamanV] * Parameterized End Page to handle Form Pages. \**************************************************************************/
int InternalEndPage(HDC hdc, DWORD dwPageType) { int iRet = SP_ERROR;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc) && !IS_METADC16_TYPE(hdc)) { PLDC pldc;
DC_PLDC(hdc,pldc,iRet);
//
// If the EndPage() is already called from
// Escape(NEXTBAND), Just return TRUE here.
//
// This will fixed ...
//
// + The KB Q118873 "PRB: EndPage() Returns -1 When Banding"
// + NTRaid #90099 "T1R: Visio 4.1, 16-bit can't print".
//
if( pldc->fl & LDC_CALLED_ENDPAGE ) { pldc->fl &= ~LDC_CALLED_ENDPAGE; return((int)TRUE); }
if( pldc->fl & LDC_META_PRINT ) { if (dwPageType == NORMAL_PAGE) { return(MFP_EndPage( hdc )); } else if (dwPageType == FORM_PAGE) { return(MFP_EndFormPage( hdc ));; } }
if ((pldc->fl & LDC_DOC_CANCELLED) || ((pldc->fl & LDC_PAGE_STARTED) == 0)) { GdiSetLastError(ERROR_INVALID_PARAMETER); return(iRet); }
if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
pldc->fl &= ~LDC_PAGE_STARTED;
// now call the drivers UI portion
DocumentEventEx(pldc->pUMPD, pldc->hSpooler, hdc, DOCUMENTEVENT_ENDPAGE, 0, NULL, 0, NULL);
RESETUSERPOLLCOUNT();
iRet = NtGdiEndPage(hdc);
// if user mode printer, call EndPagePrinter from user mode
if (iRet && pldc->pUMPD) iRet = EndPagePrinterEx(pldc->pUMPD, pldc->hSpooler);
// For Win31 compatibility, return SP_ERROR for error.
if (!iRet) iRet = SP_ERROR; else pldc->fl |= LDC_CALL_STARTPAGE;
#if PRINT_TIMER
if( bPrintTimer ) { DWORD tc; tc = GetTickCount(); DbgPrint("Page took %d.%d seconds to print\n", (tc - pldc->msStartPage) / 1000, (tc - pldc->msStartPage) % 1000 );
} #endif
} else { GdiSetLastError(ERROR_INVALID_HANDLE); }
return(iRet); }
int WINAPI EndPage(HDC hdc) { return InternalEndPage(hdc, NORMAL_PAGE); }
int WINAPI EndFormPage(HDC hdc) { return InternalEndPage(hdc, FORM_PAGE); }
/******************************Public*Routine******************************\
* StartPage * * Client side stub. * * History: * 31-Jul-1991 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/
int WINAPI StartPage(HDC hdc) { int iRet = SP_ERROR;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc) && !IS_METADC16_TYPE(hdc)) { PLDC pldc;
DC_PLDC(hdc,pldc,iRet);
#if PRINT_TIMER
pldc->msStartPage = GetTickCount(); #endif
if( pldc->fl & LDC_META_PRINT ) return(MFP_StartPage( hdc ));
pldc->fl &= ~LDC_CALL_STARTPAGE; pldc->fl &= ~LDC_CALLED_ENDPAGE;
// Do nothing if page has already been started.
if (pldc->fl & LDC_PAGE_STARTED) return(1);
// now call the drivers UI portion
if (pldc->hSpooler) { if (DocumentEventEx(pldc->pUMPD, pldc->hSpooler, hdc, DOCUMENTEVENT_STARTPAGE, 0, NULL, 0, NULL) == -1) { return(iRet); } }
pldc->fl |= LDC_PAGE_STARTED;
RESETUSERPOLLCOUNT();
// If it is UMPD, call StartPagePrinter from user mode
if (pldc->pUMPD) iRet = StartPagePrinterEx(pldc->pUMPD, pldc->hSpooler);
if (iRet) { iRet = NtGdiStartPage(hdc); }
// For Win31 compatibility, return SP_ERROR for error.
if (!iRet) { pldc->fl &= ~LDC_PAGE_STARTED; EndDoc(hdc); iRet = SP_ERROR; SetLastError(ERROR_INVALID_HANDLE); } } else { GdiSetLastError(ERROR_INVALID_HANDLE); }
return(iRet); }
/******************************Public*Routine******************************\
* StartFormPage * * This interface has been added to support watermarks and forms. * * History: * 7/1/97 -- Ramanathan Venkatapathy [RamanV] * \**************************************************************************/
int WINAPI StartFormPage(HDC hdc) { // Call StartPage. Recording required for watermarks is done in EndFormPage
return StartPage(hdc); }
/******************************Public*Routine******************************\
* EndDoc * * If a thread is created at StartDoc(), terminate it here. * * History: * 31-Jul-1991 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/
int WINAPI EndDoc(HDC hdc) { int iRet = SP_ERROR;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc) && !IS_METADC16_TYPE(hdc)) { PLDC pldc;
DC_PLDC(hdc,pldc,iRet);
if( pldc->fl & LDC_META_PRINT ) return(MFP_EndDoc( hdc ));
#if PRINT_TIMER
if( bPrintTimer ) { DWORD tc; tc = GetTickCount(); DbgPrint("Document took %d.%d seconds to print\n", (tc - pldc->msStartDoc) / 1000, (tc - pldc->msStartDoc) % 1000 );
DbgPrint("Peak temporary spool buffer size: %d\n", PeakTempSpoolBuf); } #endif
if ((pldc->fl & LDC_DOC_STARTED) == 0) return(1);
// Call EndPage if the page has been started.
if (pldc->fl & LDC_PAGE_STARTED) EndPage(hdc);
// now call the drivers UI portion
DocumentEventEx(pldc->pUMPD, pldc->hSpooler, hdc, DOCUMENTEVENT_ENDDOCPRE, 0, NULL, 0, NULL);
RESETUSERPOLLCOUNT();
iRet = NtGdiEndDoc(hdc);
//
// call EndDocPrinter from user mode if it is a User Mode Printer
//
if (pldc->pUMPD) iRet = EndDocPrinterEx(pldc->pUMPD, pldc->hSpooler);
// For Win31 compatibility, return SP_ERROR for error.
if (!iRet) { iRet = SP_ERROR; } else { DocumentEventEx(pldc->pUMPD, pldc->hSpooler, hdc, DOCUMENTEVENT_ENDDOCPOST, 0, NULL, 0, NULL); }
pldc->fl &= ~(LDC_DOC_STARTED | LDC_CALL_STARTPAGE | LDC_SAP_CALLBACK | LDC_CALLED_ENDPAGE); } else { GdiSetLastError(ERROR_INVALID_HANDLE); }
return(iRet); }
/******************************Public*Routine******************************\
* AbortDoc * * Client side stub. * * History: * 02-Apr-1992 -by- Wendy Wu [wendywu] * Wrote it. \**************************************************************************/
int WINAPI AbortDoc(HDC hdc) { int iRet = SP_ERROR;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc) && !IS_METADC16_TYPE(hdc)) { PLDC pldc;
DC_PLDC(hdc,pldc,iRet);
if (!(pldc->fl & LDC_DOC_STARTED)) return(1);
// now call the drivers UI portion
DocumentEventEx(pldc->pUMPD, pldc->hSpooler, hdc, DOCUMENTEVENT_ABORTDOC, 0, NULL, 0, NULL);
RESETUSERPOLLCOUNT();
if( pldc->fl & LDC_META_PRINT ) { DeleteEnhMetaFile(UnassociateEnhMetaFile( hdc, FALSE )); DeleteEMFSpoolData(pldc);
//
// bug 150446: calling fpAbortPrinter before deleting the
// EMF file might cause EMF file leak.
//
iRet = (*fpAbortPrinter)( pldc->hSpooler ); } else {
iRet = NtGdiAbortDoc(hdc);
// call AbortPrinter from user mode if it is UMPD
if (iRet && pldc->pUMPD) iRet = AbortPrinterEx(pldc, FALSE); }
// For Win31 compatibility, return SP_ERROR for error.
if (!iRet) iRet = SP_ERROR;
// turn off the flags
pldc->fl &= ~(LDC_DOC_STARTED | LDC_PAGE_STARTED | LDC_CALL_STARTPAGE | LDC_SAP_CALLBACK | LDC_META_PRINT | LDC_CALLED_ENDPAGE); } else { GdiSetLastError(ERROR_INVALID_HANDLE); }
return(iRet); }
/******************************Public*Routine******************************\
* StartDocA * * Client side stub. * * History: * * 21-Mar-1995 -by- Mark Enstrom [marke] * Change to call StartDocW for kmode * * 31-Jul-1991 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/
ULONG ulToASCII_N(LPSTR psz, DWORD cbAnsi, LPWSTR pwsz, DWORD c);
int WINAPI StartDocA(HDC hdc, CONST DOCINFOA * pDocInfo) {
DOCINFOW DocInfoW; WCHAR wDocName[MAX_PATH]; WCHAR wOutput[MAX_PATH]; WCHAR wDataType[MAX_PATH]; int Length;
DocInfoW.cbSize = sizeof(DOCINFOW); DocInfoW.lpszDocName = NULL; DocInfoW.lpszOutput = NULL; DocInfoW.lpszDatatype = NULL; DocInfoW.fwType = 0;
if (pDocInfo) { if (pDocInfo->lpszDocName) { Length = strlen(pDocInfo->lpszDocName)+1;
if (Length > MAX_PATH) { ERROR_ASSERT(FALSE, "StartDocA lpszDocName Too long"); GdiSetLastError(ERROR_FILENAME_EXCED_RANGE); return(SP_ERROR); }
DocInfoW.lpszDocName = &wDocName[0]; vToUnicodeN(DocInfoW.lpszDocName,MAX_PATH,pDocInfo->lpszDocName,Length); }
if (pDocInfo->lpszOutput) { Length = strlen(pDocInfo->lpszOutput)+1;
if (Length > MAX_PATH) { ERROR_ASSERT(FALSE, "StartDocA lpszOutput Too long"); GdiSetLastError(ERROR_FILENAME_EXCED_RANGE); return(SP_ERROR); }
DocInfoW.lpszOutput = &wOutput[0]; vToUnicodeN(DocInfoW.lpszOutput,MAX_PATH,pDocInfo->lpszOutput,Length); }
// if the datatype is specified to be raw, and the size is the size of
// the new expanded DOCINFO, make it raw.
// we also verify that the fwType is valid. Otherwise, chances are
// the app left the two new fields unitialized.
try { if ((pDocInfo->cbSize == sizeof(DOCINFO)) && pDocInfo->lpszDatatype && (pDocInfo->fwType <= 1))
{
if (!_stricmp("emf",pDocInfo->lpszDatatype)) { DocInfoW.lpszDatatype = L"EMF"; } else { Length = strlen(pDocInfo->lpszDatatype)+1; vToUnicodeN(wDataType,MAX_PATH,pDocInfo->lpszDatatype,Length); DocInfoW.lpszDatatype = wDataType; } } } except(EXCEPTION_EXECUTE_HANDLER) { WARNING("StartDocA an app passed a new DOCINFO structure without initializing it\n"); } }
return(StartDocW(hdc,&DocInfoW)); }
/******************************Public*Routine******************************\
* StartDocW * * Client side stub. * * History: * 31-Jul-1991 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/
int WINAPI StartDocW(HDC hdc, CONST DOCINFOW * pDocInfo) { int iRet = SP_ERROR; PWSTR pwstr = NULL; DOCINFOW dio; BOOL bForceRaw = FALSE; BOOL bSendStartDocPost = FALSE; BOOL bCallAbortPrinter = TRUE; BOOL bEMF = FALSE; INT iJob;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc) && !IS_METADC16_TYPE(hdc)) { BOOL bBanding; PLDC pldc;
DC_PLDC(hdc,pldc,iRet);
// don't allow StartDoc's on info dc's
if (pldc->fl & LDC_INFO) { SetLastError(ERROR_INVALID_HANDLE); return iRet; }
pldc->fl &= ~LDC_DOC_CANCELLED;
#if PRINT_TIMER
{ DbgPrint("StartDocW: Print Timer is on\n"); pldc->msStartDoc = GetTickCount(); } #endif
if( pDocInfo ) { dio = *pDocInfo;
if (dio.cbSize != offsetof(DOCINFOW,lpszDatatype)) { dio.cbSize = sizeof(DOCINFOW); dio.lpszDatatype = NULL; dio.fwType = 0;
try { // if it is not NULL and not "emf", go raw
// we also verify that the fwType is valid. Otherwise, chances are
// the app left the two new fields unitialized.
if ((pDocInfo->cbSize == sizeof(DOCINFOW)) && pDocInfo->lpszDatatype && (pDocInfo->fwType <= 1) && _wcsicmp(L"emf",pDocInfo->lpszDatatype)) { // the app requested non emf
bForceRaw = TRUE; dio.lpszDatatype = pDocInfo->lpszDatatype; } } except(EXCEPTION_EXECUTE_HANDLER) { WARNING("StartDocW an app passed a new DOCINFO structure without initializing it\n"); } } } else { dio.cbSize = sizeof(DOCINFOW); dio.lpszDatatype = NULL; dio.lpszOutput = NULL; dio.lpszDocName = NULL; dio.fwType = 0; }
// if no output port is specified but a port was specified at createDC, use
// that port now
if ((dio.lpszOutput == NULL) && (pldc->pwszPort != NULL)) { dio.lpszOutput = pldc->pwszPort; }
// StartDocDlgW returns -1 for error
// -2 for user cancelled
// NULL if there is no string to copy (not file port)
// Non NULL if there is a valid string
if(pldc->hSpooler != (HANDLE)0) { ASSERTGDI(ghSpooler,"non null hSpooler with unloaded WINSPOOL W\n");
pwstr = (*fpStartDocDlgW)(pldc->hSpooler, &dio);
if((LONG_PTR)pwstr == -2) { pldc->fl |= LDC_DOC_CANCELLED; return(iRet); } if((LONG_PTR)pwstr == -1) return(iRet);
if(pwstr != NULL) { dio.lpszOutput = pwstr; } }
// now call the drivers UI portion
if (pldc->hSpooler) { PVOID pv = (PVOID)&dio;
iRet = DocumentEventEx(pldc->pUMPD, pldc->hSpooler, hdc, DOCUMENTEVENT_STARTDOCPRE, sizeof(pv), (PVOID)&pv, 0, NULL);
if (iRet == -1) { bCallAbortPrinter = FALSE; goto KMMSGERROR; } if(iRet == -2) { pldc->fl |= LDC_DOC_CANCELLED; goto MSGEXIT; }
}
//
// Check application compatibility
//
if (GetAppCompatFlags(NULL) & GACF_NOEMFSPOOLING) { ULONG InData = POSTSCRIPT_PASSTHROUGH;
//
// Disable EMF spooling for postscript printer driver.
//
// Several PS-centric application could not work with EMF spooling.
// This problem is introduced, because application developed for win95
// reley on that win95 does not do EMF spooling with postscript, but
// NT does.
//
if (ExtEscape(hdc,QUERYESCSUPPORT,sizeof(ULONG),(LPCSTR)&InData,0,NULL)) { bForceRaw = TRUE; } }
// Unless the driver has explicitly told us not to spool, we will first try
// to StartDoc with datatype EMF
// we also force to go to EMF if METAFILE_DRIVER is supported by the driver
if ((!bForceRaw && GetDCDWord(hdc, DDW_JOURNAL, 0) && RemoteRasterizerCompatible(pldc->hSpooler)) || ((pldc->pUMPD) && (pldc->pUMPD->dwFlags & UMPDFLAG_METAFILE_DRIVER))) { DOC_INFO_3W DocInfo;
DocInfo.pDocName = (LPWSTR) dio.lpszDocName; DocInfo.pOutputFile = (LPWSTR) dio.lpszOutput; DocInfo.pDatatype = (LPWSTR) L"NT EMF 1.008"; DocInfo.dwFlags = DI_MEMORYMAP_WRITE;
iJob = (*fpStartDocPrinterW)(pldc->hSpooler, 3, (LPBYTE) &DocInfo);
if( iJob <= 0 ) { if( GetLastError() != ERROR_INVALID_DATATYPE ) { WARNING("StartDocW: StartDocPrinter failed w/ error other \
than INVALID_DATA_TYPE\n"); bCallAbortPrinter = FALSE; goto KMMSGERROR; } else { // we are going raw so just fall through
} } else { // the spooler likes the EMF data type so let start metafiling
MFD1("StartDocW calling MFP_StartDocW to do EMF printing\n");
if(MFP_StartDocW( hdc, &dio, FALSE)) { iRet = iJob; bSendStartDocPost = TRUE;
goto MSGEXIT; } else { WARNING("StartDocW: error calling MFP_StartDocW\n"); bEMF = TRUE; goto KMMSGERROR; } } }
// if it is a UMPD driver, call StartDocPrinter at the client side
if (pldc->pUMPD) {
DOC_INFO_1W DocInfo;
#define MAX_DOCINFO_DATA_TYPE 80
WCHAR awchDatatype[MAX_DOCINFO_DATA_TYPE]; PFN pfn;
DocInfo.pDocName = (LPWSTR) dio.lpszDocName; DocInfo.pOutputFile = (LPWSTR) dio.lpszOutput; DocInfo.pDatatype = NULL;
if (pfn = pldc->pUMPD->apfn[INDEX_DrvQuerySpoolType]) { awchDatatype[0] = 0;
// did the app specify a data type and will it fit in our buffer
if (dio.lpszDatatype) { int cjStr = (wcslen(dio.lpszDatatype) + 1) * sizeof(WCHAR);
if (cjStr < (MAX_DOCINFO_DATA_TYPE * sizeof(WCHAR))) { RtlCopyMemory((PVOID)awchDatatype,(PVOID)dio.lpszDatatype,cjStr); } }
if (pfn(((PUMDHPDEV)pldc->pUMdhpdev)->dhpdev, awchDatatype)) { DocInfo.pDatatype = awchDatatype; }
}
iJob = StartDocPrinterWEx(pldc->pUMPD, pldc->hSpooler, 1, (LPBYTE) &DocInfo);
}
// If we got here it means we are going raw. Mark the DC as type direct
if (pldc->pUMPD && (pldc->pUMPD->dwFlags & UMPDFLAG_METAFILE_DRIVER)) { // we have to go EMF if METAFILE_DRIVER is on
WARNING("StartDocW failed because EMF failed and METAFILE_DRIVER is on\n"); goto KMMSGERROR; }
pldc->fl |= LDC_PRINT_DIRECT;
iRet = NtGdiStartDoc(hdc,&dio,&bBanding, iJob);
if (iRet) { if (pldc->pfnAbort != NULL) { vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) goto KMMSGERROR;
pldc->fl |= LDC_SAP_CALLBACK; pldc->ulLastCallBack = GetTickCount(); }
pldc->fl |= LDC_DOC_STARTED;
if (bBanding) { MFD1("StartDocW calling MFP_StartDocW to do banding\n"); iRet = MFP_StartDocW( hdc, NULL, TRUE ) ? iRet : SP_ERROR; } else { // Only set this when we are not banding since the system will
// get confused and try to call StartPage while playing the
// metafile back during banding.
pldc->fl |= LDC_CALL_STARTPAGE; }
bSendStartDocPost = TRUE; } else { KMMSGERROR: iRet = SP_ERROR;
if (bCallAbortPrinter && pldc->pUMPD) { AbortPrinterEx(pldc, bEMF); } }
MSGEXIT: if (bSendStartDocPost) { // now see if we need to call the drivers UI portion
{ if (DocumentEventEx(pldc->pUMPD, pldc->hSpooler, hdc, DOCUMENTEVENT_STARTDOCPOST, sizeof(iRet), (PVOID)&iRet, 0, NULL) == -1) { AbortDoc(hdc); iRet = SP_ERROR; } } } }
if (pwstr != NULL) { LocalFree(pwstr); }
return(iRet); }
/******************************Public*Routine******************************\
* StartDocEMF * * Special version of StartDoc used by the EMF playback code. * * History: * 31-Jul-1991 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/
int WINAPI StartDocEMF(HDC hdc, CONST DOCINFOW * pDocInfo, BOOL *pbBanding ) { int iRet = SP_ERROR; DOCINFOW dio; INT iJob = 0;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc) && !IS_METADC16_TYPE(hdc)) { BOOL bBanding; PLDC pldc;
DC_PLDC(hdc,pldc,iRet);
#if PRINT_TIMER
{ DbgPrint("StartDocW: Print Timer is on\n"); pldc->msStartDoc = GetTickCount(); } #endif
// if no output port is specified but a port was specified at createDC, use that port now
if (pDocInfo) { dio = *pDocInfo;
if (dio.lpszOutput == NULL && pldc->pwszPort != NULL) dio.lpszOutput = pldc->pwszPort; } else { ZeroMemory(&dio, sizeof(dio)); dio.cbSize = sizeof(dio); }
// if it is a UMPD driver, call StartDocPrinter at the client side
if (pldc->pUMPD) { DOC_INFO_3W DocInfo;
DocInfo.pDocName = (LPWSTR) dio.lpszDocName; DocInfo.pOutputFile = (LPWSTR) dio.lpszOutput; DocInfo.pDatatype = NULL; DocInfo.dwFlags = DI_MEMORYMAP_WRITE;
iJob = (*fpStartDocPrinterW)( pldc->hSpooler, 3, (LPBYTE) &DocInfo ); }
iRet = NtGdiStartDoc(hdc,(DOCINFOW *)&dio, pbBanding, iJob);
if (iRet) { pldc->fl |= LDC_DOC_STARTED; pldc->fl |= LDC_CALL_STARTPAGE; } else { // For Win31 compatibility, return SP_ERROR for error.
iRet = SP_ERROR;
if (pldc->pUMPD) { (*fpAbortPrinter)(pldc->hSpooler); } } }
return(iRet); }
/******************************Private*Function****************************\
* vSAPCallback * * Call back to applications abort proc. * * History: * 02-May-1992 -by- Wendy Wu [wendywu] * Wrote it. \**************************************************************************/
VOID vSAPCallback(PLDC pldc) { ULONG ulCurr = GetTickCount();
if (ulCurr - pldc->ulLastCallBack >= CALLBACK_INTERVAL) { pldc->ulLastCallBack = ulCurr; if (!(*pldc->pfnAbort)(pldc->hdc, 0)) { CancelDC(pldc->hdc); AbortDoc(pldc->hdc); } } }
/******************************Public*Routine******************************\
* SetAbortProc * * Save the application-supplied abort function in the LDC struct. * * History: * 02-Apr-1992 -by- Wendy Wu [wendywu] * Wrote it. \**************************************************************************/
int WINAPI SetAbortProc(HDC hdc, ABORTPROC pfnAbort) { int iRet = SP_ERROR;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc) && !IS_METADC16_TYPE(hdc)) { PLDC pldc;
DC_PLDC(hdc,pldc,iRet);
if (pfnAbort != (ABORTPROC)NULL) { // PageMaker calls SetAbortProc after StartDoc.
if (pldc->fl & LDC_DOC_STARTED) { pldc->fl |= LDC_SAP_CALLBACK; pldc->ulLastCallBack = GetTickCount(); } } else { pldc->fl &= ~LDC_SAP_CALLBACK; }
pldc->pfnAbort = pfnAbort;
iRet = 1; }
return(iRet); }
/******************************Public*Routine******************************\
* * GetPairKernTable * * support for GETPAIRKERNTABLE escape, basically reroute the call * the the regular API * * History: * 17-Jun-1996 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
DWORD GetPairKernTable ( HDC hdc, DWORD cjSize, // size of buffer in bytes
KERNPAIR * pkp ) { DWORD dwRet = GetKerningPairsA(hdc, 0, NULL); DWORD dwRet1, ikp;
if (pkp && dwRet) { // pointer to receiving buffer
KERNINGPAIR *pKernPair = LOCALALLOC(dwRet * sizeof(KERNINGPAIR)); if (pKernPair) { dwRet1 = GetKerningPairsA(hdc, dwRet, pKernPair); if (dwRet1 == dwRet) // paranoid check
{ // now we can copy the data out, get the number of pairs
// that the buffer can hold:
dwRet = cjSize / sizeof (KERNPAIR); if (dwRet > dwRet1) dwRet = dwRet1;
for (ikp = 0; ikp < dwRet; ikp++) { pkp[ikp].sAmount = (SHORT)pKernPair[ikp].iKernAmount; pkp[ikp].wBoth = (WORD) ((BYTE)pKernPair[ikp].wFirst | (BYTE)pKernPair[ikp].wSecond << 8); } } else { dwRet = 0; } LOCALFREE(pKernPair); } else { dwRet = 0; } }
return dwRet; }
/******************************Public*Routine******************************\
* Escape * * * * Compatibility support for the old 16 bit Escape call. * * * * Note that there are some rules to follow here: * * * * 1) WOW should map a selected set of old Escape calls to ExtEscape. * * These should be the calls that we want to support under NT (i.e. the * * ones we are forced to support), and that make sense (i.e. have well * * defined output structures, where NULL is well defined). In this * * mapping, WOW insures 32 bit alignment. It maps directly to ExtEscape * * just for efficiency. * * * * 2) GDI should map ALL the same calls that WOW does. Thus when a 16 bit * * app that works under WOW gets ported to 32 bits, it will keep * * working, even if it still calls Escape. (I'm basically assuming that * * Chicago will also allow this. On the other hand if Chicago forces * * apps to migrate to ExtEscape, then we can too. But we can't force * * them by ourselves!) * * * * 3) Any data structures passed to Escape must get passed unchanged to * * ExtEscape. This includes the 16 bit WORD in POSTSCRIPT_PASSTHROUGH. * * Remember, we *want* Chicago to be able to easily support our * * ExtEscapes. If we remove that WORD, it will be hard for then * * to put it back. It's pretty easy for our driver to ignore it. * * * * 4) Our Escape entry point should handle QUERYESCSUPPORT in the * * following way. a) It should require an nCount of 2, not the * * present 4. b) It should return TRUE for those functions that it * * handles by mapping onto APIs. c) For any function that it would pass * * on to ExtEscape, it should also pass the QUERYESCSUPPORT on. (For * * example, this function can't answer for the support of * * POSTSCRIPT_PASSTHROUGH.) However, the QUERYESCSUPPORT in ExtEscape * * *should* expect a DWORD. (It is after all a 32 bit function.) This * * should not inconvenience Chicago. They can simply reject function * * numbers >64K. * * [chuckwh - 5/8/93] * * * * History: * * Mon May 17 13:49:32 1993 -by- Hock San Lee [hockl] * * Made ENCAPSULATED_POSTSCRIPT call DrawEscape. * * * * Sat 08-May-1993 00:03:06 -by- Charles Whitmer [chuckwh] * * Added support for POSTSCRIPT_PASSTHROUGH, OPENCHANNEL, CLOSECHANNEL, * * DOWNLOADHEADER, DOWNLOADFACE, GETFACENAME, ENCAPSULATED_POSTSCRIPT. * * Cleaned up the code and conventions a bit. * * * * 02-Apr-1992 -by- Wendy Wu [wendywu] * * Modified to call the client side GDI functions. * * * * 01-Aug-1991 -by- Eric Kutter [erick] * * Wrote it. * \**************************************************************************/
int WINAPI Escape( HDC hdc, // Identifies the device context.
int iEscape, // Specifies the escape function to be performed.
int cjIn, // Number of bytes of data pointed to by pvIn.
LPCSTR pvIn, // Points to the input data.
LPVOID pvOut // Points to the structure to receive output.
) { int iRet = 0; DOCINFOA DocInfo; PLDC pldc; ULONG iQuery; BOOL bFixUp;
FIXUP_HANDLE(hdc);
// Metafile the call.
if(IS_METADC16_TYPE(hdc)) return((int) MF16_Escape(hdc,iEscape,cjIn,pvIn,pvOut));
// handle escapes that don't require a printer
switch (iEscape) { case QUERYESCSUPPORT: switch(*((UNALIGNED USHORT *) pvIn)) { // Respond OK to the calls we handle inline below.
case QUERYESCSUPPORT: case PASSTHROUGH: case STARTDOC: case ENDDOC: case NEWFRAME: case ABORTDOC: case SETABORTPROC: case GETPHYSPAGESIZE: case GETPRINTINGOFFSET: case GETSCALINGFACTOR: case NEXTBAND: case GETCOLORTABLE: case OPENCHANNEL: case CLOSECHANNEL: case DOWNLOADHEADER: iRet = (IS_ALTDC_TYPE(hdc) ? 1 : 0); break;
case GETEXTENDEDTEXTMETRICS: iRet = 1; break;
// Ask the driver about the few calls we allow to pass through.
case SETCOPYCOUNT: case GETDEVICEUNITS: case POSTSCRIPT_PASSTHROUGH: case POSTSCRIPT_DATA: case POSTSCRIPT_IGNORE: case POSTSCRIPT_IDENTIFY: case POSTSCRIPT_INJECTION: case DOWNLOADFACE: case BEGIN_PATH: case END_PATH: case CLIP_TO_PATH: case DRAWPATTERNRECT:
iQuery = (ULONG) (*((UNALIGNED USHORT *) pvIn));
iRet = ( ExtEscape ( hdc, (ULONG) ((USHORT) iEscape), 4, (LPCSTR) &iQuery, 0, (LPSTR) NULL ) ); break;
case ENCAPSULATED_POSTSCRIPT: iQuery = (ULONG) (*((UNALIGNED USHORT *) pvIn));
iRet = ( DrawEscape ( hdc, (int) (ULONG) ((USHORT) iEscape), 4, (LPCSTR) &iQuery ) ); break;
case QUERYDIBSUPPORT: iRet = 1; break;
// Otherwise it's no deal. Sorry. If we answer "yes" to some
// call we don't know *everything* about, we may find ourselves
// actually rejecting the call later when the app actually calls
// with some non-NULL pvOut. This would get the app all excited
// about our support for no reason. It would take a path that
// is doomed to failure. [chuckwh]
default: iRet = 0; break; } return(iRet);
case GETCOLORTABLE:
iRet = GetSystemPaletteEntries(hdc,*((UNALIGNED SHORT *)pvIn),1,pvOut);
if (iRet == 0) iRet = -1; return(iRet);
case QUERYDIBSUPPORT: if ((pvOut != NULL) && (cjIn >= sizeof(BITMAPINFOHEADER))) { *((UNALIGNED LONG *)pvOut) = 0;
switch (((UNALIGNED BITMAPINFOHEADER *)pvIn)->biCompression) { case BI_RGB: switch (((UNALIGNED BITMAPINFOHEADER *)pvIn)->biBitCount) { case 1: case 4: case 8: case 16: case 24: case 32: *((UNALIGNED LONG *)pvOut) = (QDI_SETDIBITS|QDI_GETDIBITS| QDI_DIBTOSCREEN|QDI_STRETCHDIB); break; default: break; }
case BI_RLE4: if (((UNALIGNED BITMAPINFOHEADER *)pvIn)->biBitCount == 4) { *((UNALIGNED LONG *)pvOut) = (QDI_SETDIBITS|QDI_GETDIBITS| QDI_DIBTOSCREEN|QDI_STRETCHDIB); } break;
case BI_RLE8: if (((UNALIGNED BITMAPINFOHEADER *)pvIn)->biBitCount == 8) { *((UNALIGNED LONG *)pvOut) = (QDI_SETDIBITS|QDI_GETDIBITS| QDI_DIBTOSCREEN|QDI_STRETCHDIB); } break;
case BI_BITFIELDS: switch (((UNALIGNED BITMAPINFOHEADER *)pvIn)->biBitCount) { case 16: case 32: *((UNALIGNED LONG *)pvOut) = (QDI_SETDIBITS|QDI_GETDIBITS| QDI_DIBTOSCREEN|QDI_STRETCHDIB); break; default: break; }
default: break; } return 1; }
case GETEXTENDEDTEXTMETRICS: return( GetETM( hdc, pvOut ) ? 1 : 0 );
}
// OK, ones that are related to printing and need the LDC
if (IS_ALTDC_TYPE(hdc)) { BOOL bFixUp = FALSE; PLDC pldc;
DC_PLDC(hdc,pldc,iRet);
// Call the appropriate client side APIs.
switch (iEscape) { case CLOSECHANNEL: case ENDDOC: iRet = EndDoc(hdc); break;
case ABORTDOC: iRet = AbortDoc(hdc); break;
case SETABORTPROC: iRet = SetAbortProc(hdc, (ABORTPROC)pvIn); break;
case GETSCALINGFACTOR: if (pvOut) { ((UNALIGNED POINT *)pvOut)->x = GetDeviceCaps(hdc, SCALINGFACTORX); ((UNALIGNED POINT *)pvOut)->y = GetDeviceCaps(hdc, SCALINGFACTORY); } iRet = 1;
break;
case SETCOPYCOUNT: iRet = ( ExtEscape ( hdc, (ULONG) ((USHORT) iEscape), cjIn, pvIn, pvOut ? sizeof(int) : 0, (LPSTR) pvOut ) ); break;
case GETDEVICEUNITS: iRet = ( ExtEscape ( hdc, GETDEVICEUNITS, cjIn, pvIn, 16, pvOut ) ); break;
case POSTSCRIPT_PASSTHROUGH: iRet = ( ExtEscape ( hdc, POSTSCRIPT_PASSTHROUGH, (int) (*((UNALIGNED USHORT *) pvIn))+2, pvIn, 0, (LPSTR) NULL ) ); break;
case OPENCHANNEL: DocInfo.lpszDocName = (LPSTR) NULL; DocInfo.lpszOutput = (LPSTR) NULL; DocInfo.lpszDatatype= (LPSTR) "RAW"; DocInfo.fwType = 0; iRet = StartDocA(hdc,&DocInfo); break;
case DOWNLOADHEADER: iRet = 1; break;
case POSTSCRIPT_DATA: case POSTSCRIPT_IGNORE: case POSTSCRIPT_IDENTIFY: case POSTSCRIPT_INJECTION: case DOWNLOADFACE: case BEGIN_PATH: case END_PATH: case CLIP_TO_PATH: case DRAWPATTERNRECT: iRet = ( ExtEscape ( hdc, (ULONG) ((USHORT) iEscape), cjIn, pvIn, 0, (LPSTR) NULL ) ); break;
case ENCAPSULATED_POSTSCRIPT: iRet = ( DrawEscape ( hdc, (int) (ULONG) ((USHORT) iEscape), cjIn, pvIn ) ); break;
case GETPHYSPAGESIZE: if (pvOut) { ((UNALIGNED POINT *)pvOut)->x = GetDeviceCaps(hdc, PHYSICALWIDTH); ((UNALIGNED POINT *)pvOut)->y = GetDeviceCaps(hdc, PHYSICALHEIGHT); } iRet = 1; break;
case GETPRINTINGOFFSET: if (pvOut) { ((UNALIGNED POINT *)pvOut)->x = GetDeviceCaps(hdc, PHYSICALOFFSETX); ((UNALIGNED POINT *)pvOut)->y = GetDeviceCaps(hdc, PHYSICALOFFSETY); } iRet = 1; break;
case STARTDOC: DocInfo.lpszDocName = (LPSTR)pvIn; DocInfo.lpszOutput = (LPSTR)NULL; DocInfo.lpszDatatype= (LPSTR) NULL; DocInfo.fwType = 0;
iRet = StartDocA(hdc, &DocInfo); bFixUp = TRUE; break;
case PASSTHROUGH:
#if (PASSTHROUGH != DEVICEDATA)
#error PASSTHROUGH != DEVICEDATA
#endif
iRet = ExtEscape ( hdc, PASSTHROUGH, (int) (*((UNALIGNED USHORT *) pvIn))+sizeof(WORD), pvIn, 0, (LPSTR) NULL ); bFixUp = TRUE; break;
case NEWFRAME: if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc);
// If no error occured in EndPage, call StartPage next time.
if ((iRet = EndPage(hdc)) > 0) pldc->fl |= LDC_CALL_STARTPAGE;
bFixUp = TRUE; break;
case NEXTBAND: // Win31 compatibility flags.
// GACF_MULTIPLEBANDS: Freelance thinks the first full-page band is
// a text-only band. So it ignores it and waits
// for the next band to print graphics. We'll
// return the full-page band twice for each page.
// The first band will be ignored while the second
// band really contains graphics to print.
// This flag only affects dotmatrix on win31.
// GACF_FORCETEXTBAND: World Perfect and Freelance both have assumptions
// on whether a band is text-only or not. They
// print text and graphics in different bands.
// We'll return two full-page bands for each page.
// One for text and the other for graphics.
// This flag only affects laser jet on win31.
if (pldc->fl & LDC_NEXTBAND) { if (GetAppCompatFlags(NULL) & (GACF_FORCETEXTBAND|GACF_MULTIPLEBANDS)) { if (pldc->fl & LDC_EMPTYBAND) { pldc->fl &= ~LDC_EMPTYBAND; } else { pldc->fl |= LDC_EMPTYBAND; goto FULLPAGEBAND; } }
((UNALIGNED RECT *)pvOut)->left = ((UNALIGNED RECT *)pvOut)->top = ((UNALIGNED RECT *)pvOut)->right = ((UNALIGNED RECT *)pvOut)->bottom = 0;
pldc->fl &= ~LDC_NEXTBAND; // Clear NextBand flag.
if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc);
if ((iRet = EndPage(hdc)) > 0) { pldc->fl |= LDC_CALL_STARTPAGE;
//
// Marks application is doing banding by themselves,
// then EndPage() is called when there is no more band.
//
pldc->fl |= LDC_CALLED_ENDPAGE; }
bFixUp = TRUE; } else { FULLPAGEBAND: ((UNALIGNED RECT *)pvOut)->left = ((UNALIGNED RECT *)pvOut)->top = 0; ((UNALIGNED RECT *)pvOut)->right = GetDeviceCaps(hdc, HORZRES); ((UNALIGNED RECT *)pvOut)->bottom = GetDeviceCaps(hdc, VERTRES);
pldc->fl |= LDC_NEXTBAND; // Set NextBand flag.
iRet = 1; } break;
default: iRet = 0; break; }
// Fix up the return values for STARTDOC and PASSTHROUGH so we're
// win31 compatible.
if (bFixUp && (iRet < 0)) { if (pldc->fl & LDC_DOC_CANCELLED) { iRet = SP_APPABORT; } else { switch(GetLastError()) { case ERROR_PRINT_CANCELLED: iRet = SP_USERABORT; break;
case ERROR_NOT_ENOUGH_MEMORY: iRet = SP_OUTOFMEMORY; break;
case ERROR_DISK_FULL: iRet = SP_OUTOFDISK; break;
default: iRet = SP_ERROR; break; } } } } else { // We don't support this escape on this DC, but CorelDRAW expects
// some non-random values back anyway. Zero the output buffer to
// keep it happy.
if ((iEscape == GETSCALINGFACTOR) && pvOut) { RtlZeroMemory(pvOut, sizeof(POINT)); } } return(iRet); }
/******************************Public*Routine******************************\
* ExtEscape * * * * History: * * 14-Feb-1992 -by- Dave Snipp [DaveSn] * * Wrote it. * \**************************************************************************/
#define BUFSIZE 520
int WINAPI ExtEscape( HDC hdc, // Identifies the device context.
int iEscape, // Specifies the escape function to be performed.
int cjInput, // Number of bytes of data pointed to by lpInData
LPCSTR lpInData, // Points to the input structure required
int cjOutput, // Number of bytes of data pointed to by lpOutData
LPSTR lpOutData // Points to the structure to receive output from
) // this escape.
{ int iRet = 0; int cjIn, cjOut, cjData; PLDC pldc; XFORM xf;
// We need some extra buffer space for at least one call. I'm going to
// hard code it here. The slickest thing would be to have a separate
// routine that knows how to alloc this space out of the memory window,
// but that would be more complex. I'm rushed. Sorry. [chuckwh]
BYTE jBuffer[BUFSIZE];
// We want to make this escape work just like it does in Windows which means
// that if there is a TrueType font in the DC GDI will compute it otherwise
// we'll pass the escape to the driver. So we call off to GetETM here because
// it does just that.
FIXUP_HANDLE(hdc);
if( iEscape == GETEXTENDEDTEXTMETRICS ) { if( GetETM( hdc, (EXTTEXTMETRIC*) jBuffer ) ) { RtlCopyMemory( lpOutData, jBuffer, MIN(cjOutput,sizeof(EXTTEXTMETRIC)) ); return(1); } else { return(0); } } else if (iEscape == DRAWPATTERNRECT) { if (GetAppCompatFlags2(VER40) & GACF2_NODRAWPATRECT) { // GACF_NODRAWPATRECT -
//
// Some of application does not work with DrawPatRect escape,
// so that we behave as we don't support it.
//
return (0); }
if (!cjInput) { //
// work around 32 bits Excel (with Ofiice 97) bug.
//
cjInput = sizeof(DRAWPATRECT); } } else if (iEscape == QUERYESCSUPPORT) { if (*(ULONG*)lpInData == GETPAIRKERNTABLE) { // intercept GETPAIRKERNTABLE escape on the client side where all the work is done
// It is interesting that this "api" works on win95 not only for device fonts but
// also for engine fonts. Therefore this needs to be outside of
// the IS_ALTDC_TYPE(hdc) clause below
return (1); } else if (*(ULONG*)lpInData == DRAWPATTERNRECT) { if (GetAppCompatFlags2(VER40) & GACF2_NODRAWPATRECT) { // GACF_NODRAWPATRECT -
//
// Some of application does not work with DrawPatRect escape,
// so that we behave as we don't support it.
//
return (0); } } } else if (iEscape == GETPAIRKERNTABLE) { return GetPairKernTable(hdc, (DWORD)cjOutput, (KERNPAIR *)lpOutData); }
// printer specific stuff
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
// don't allow them 16bit metafiles
if (IS_METADC16_TYPE(hdc)) return (0);
DC_PLDC(hdc,pldc,iRet);
MFD2("ExtEscapeCalled %d\n", iEscape );
if (pldc->fl & (LDC_DOC_CANCELLED|LDC_SAP_CALLBACK)) { if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(0); }
// if it is an output call that requires no return results, better make sure
// we do a start page.
if (( iEscape == DOWNLOADFACE ) || ( iEscape == GETFACENAME ) || ( iEscape == POSTSCRIPT_DATA ) || ( iEscape == BEGIN_PATH ) || ( iEscape == END_PATH ) || ( iEscape == CLIP_TO_PATH ) || ( iEscape == PASSTHROUGH ) || ( iEscape == DOWNLOADHEADER )) { if (pldc->fl & LDC_CALL_STARTPAGE) StartPage(hdc); }
if ((pldc->iType == LO_METADC) && (pldc->fl & LDC_META_PRINT)) { // These two escapes should be called *before* StartDoc, any these escape
// called *after* StartDoc will be failed when EMF is used (see SDK)
if ((iEscape == POSTSCRIPT_IDENTIFY) || (iEscape == POSTSCRIPT_INJECTION)) { WARNING("GDI32: ExtEscape() PSInjection after StartDoc with EMF, is ignored\n");
SetLastError(ERROR_INVALID_PARAMETER); return (0); }
// These escapes will not be recorded into metafile
//
// SETCOPYCOUNT - will be handled in kernel for EMF spooling case.
// and this will be recorded in DEVMODE.dmCopies.
//
// QUERYSUPPORT - will be handled in driver even EMF spooling case,
// since only driver knows which escape support it.
// and this is nothing for drawing, so not nessesary
// to record it.
//
// CHECKJPEGFORMAT & CHECKPNGFORMAT
// - query escapes that do not need to be reocorded
// into metafile.
//
if ((iEscape != SETCOPYCOUNT) && (iEscape != QUERYESCSUPPORT) && (iEscape != CHECKJPEGFORMAT) && (iEscape != CHECKPNGFORMAT)) { BOOL bSetXform = FALSE;
// Write this escape to metafile.
//
// If there's transform set in the hdc by the app
// at the time of DRAWPATRECT, select identity transform in
// once the escape is recorded, select back the original transform
//
if (GetWorldTransform(hdc, &xf)) { if ((xf.eM11 != 1.0f) || (xf.eM22 != 1.0f) || (xf.eM12 != 0.0f) || (xf.eM21 != 0.0f)) { bSetXform = TRUE; MF_ModifyWorldTransform(hdc,&xformIdentity,MWT_SET); } }
MF_WriteEscape( hdc, iEscape, cjInput, lpInData, EMR_EXTESCAPE );
if (bSetXform) { MF_ModifyWorldTransform(hdc,&xf,MWT_SET); }
if ((lpOutData == (LPSTR) NULL) || (cjOutput == 0)) { if ((iEscape == PASSTHROUGH) || (iEscape == POSTSCRIPT_PASSTHROUGH) || (iEscape == POSTSCRIPT_DATA)) { if ((cjInput < (int)sizeof(WORD)) || (cjInput < (int)sizeof(WORD) + *((LPWORD) lpInData))) { SetLastError(ERROR_INVALID_PARAMETER); return -1; }
cjInput = *((LPWORD) lpInData); }
return(MAX(cjInput,1)); } }
MFD2("ExtEscape goes to gre/driver Escape(%d) with EMF printing\n", iEscape); }
if ((iEscape == DOWNLOADFACE) || (iEscape == GETFACENAME)) { if (iEscape == DOWNLOADFACE) { // Adjust the buffer for the DOWNLOADFACE case. Note that lpOutData
// points at an input word for the mode.
if ((gpwcANSICharSet == (WCHAR *) NULL) && !bGetANSISetMap()) { return(0); }
RtlMoveMemory ( jBuffer + sizeof(WCHAR), (BYTE *) &gpwcANSICharSet[0], 256*sizeof(WCHAR) );
if (lpOutData) *(WCHAR *) jBuffer = *(UNALIGNED WORD *) lpOutData; else *(WCHAR *) jBuffer = 0;
cjInput = 257 * sizeof(WCHAR); lpInData = (LPCSTR) jBuffer;
ASSERTGDI(BUFSIZE >= cjInput,"Buffer too small.\n"); } }
if ((iEscape == POSTSCRIPT_INJECTION) || (iEscape == POSTSCRIPT_IDENTIFY)) { // Remember escape data for EMF spooling case. (only BEFORE StartDoc)
if (!(pldc->fl & LDC_DOC_STARTED)) { PPS_INJECTION_DATA pPSInjection; ULONG cjCellSize;
if( BROUNDUP_DWORDALIGN_OVERFLOW( (sizeof(PS_INJECTION_DATA)-1)+cjInput) ) return 0;
cjCellSize = ROUNDUP_DWORDALIGN((sizeof(PS_INJECTION_DATA)-1)+cjInput);
MFD2("ExtEscape records this Escape(%d) temporary then write EMF later\n",iEscape);
if ((pPSInjection = LOCALALLOC(cjCellSize)) != NULL) { cjCellSize -= offsetof(PS_INJECTION_DATA,EmfData);
// Fill up Injection Data.
pPSInjection->EmfData.cjSize = cjCellSize; pPSInjection->EmfData.nEscape = iEscape; pPSInjection->EmfData.cjInput = cjInput; RtlCopyMemory(pPSInjection->EmfData.EscapeData,lpInData,cjInput);
// Put this on list.
InsertTailList(&(pldc->PSDataList),&(pPSInjection->ListEntry));
// Update total data size.
pldc->dwSizeOfPSDataToRecord += cjCellSize; } else { WARNING("ExtEscape: Failed on LOCALALLOC for POSTSCRIPT_xxxxx\n"); GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY); return (0); } } }
// now call the drivers UI portion
if (pldc->hSpooler) { DOCEVENT_ESCAPE docEvent;
docEvent.iEscape = iEscape; docEvent.cjInput = cjInput; docEvent.pvInData = (PVOID)lpInData;
DocumentEventEx(pldc->pUMPD, pldc->hSpooler, hdc, DOCUMENTEVENT_ESCAPE, sizeof(docEvent), (PVOID)&docEvent, cjOutput, (PVOID)lpOutData); } }
cjIn = (lpInData == NULL) ? 0 : cjInput; cjOut = (lpOutData == NULL) ? 0 : cjOutput;
iRet = NtGdiExtEscape(hdc,NULL,0,iEscape,cjIn,(LPSTR)lpInData,cjOut,lpOutData);
return(iRet); }
/******************************Public*Routine******************************\
* NamedEscape * * History: * 5-Mar-1996 -by- Gerrit van Wingerden * Wrote it. \**************************************************************************/
#define BUFSIZE 520
int WINAPI NamedEscape( HDC hdc, // Identifies the device context for EMF spooling
LPWSTR pwszDriver, // Identfies the driver
int iEscape, // Specifies the escape function to be performed.
int cjInput, // Number of bytes of data pointed to by lpInData
LPCSTR lpInData, // Points to the input structure required
int cjOutput, // Number of bytes of data pointed to by lpOutData
LPSTR lpOutData // Points to the structure to receive output from
) // this escape.
{ int iRet = 0; int cjIn, cjOut, cjData; PLDC pldc;
if(hdc) { FIXUP_HANDLE(hdc);
// if we are EMF spooling then we need to record the call here
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
// don't allow them in 16bit metafiles
if (IS_METADC16_TYPE(hdc)) return(0);
DC_PLDC(hdc,pldc,iRet);
MFD2("NamedEscapeCalled %d\n", iEscape );
if (pldc->fl & (LDC_DOC_CANCELLED|LDC_SAP_CALLBACK)) { if (pldc->fl & LDC_SAP_CALLBACK) vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED) return(0); }
if (pldc->iType == LO_METADC) { if(!MF_WriteNamedEscape(hdc, pwszDriver, iEscape, cjInput, lpInData)) { WARNING("Error metafiling NameEscape\n"); return(0); } } } }
cjIn = (lpInData == NULL) ? 0 : cjInput; cjOut = (lpOutData == NULL) ? 0 : cjOutput;
iRet = NtGdiExtEscape((HDC) 0, pwszDriver, wcslen(pwszDriver), iEscape,cjIn, (LPSTR)lpInData, cjOut,lpOutData);
return(iRet); }
/******************************Public*Routine******************************\
* DrawEscape * * * * Client side stub. * * * * History: * * 02-Apr-1992 -by- Wendy Wu [wendywu] * * Wrote it. * \**************************************************************************/
int WINAPI DrawEscape( HDC hdc, // Identifies the device context.
int iEscape, // Specifies the escape function to be performed.
int cjIn, // Number of bytes of data pointed to by lpIn.
LPCSTR lpIn // Points to the input data.
) { int iRet = 0; int cjInput;
FIXUP_HANDLE(hdc);
// printer specific stuff
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
// don't allow them 16bit metafiles
if (IS_METADC16_TYPE(hdc)) return(0);
DC_PLDC(hdc,pldc,iRet);
MFD2("Calling DrawEscape %d\n", iEscape );
if( ( pldc->fl & LDC_META_PRINT ) && ( iEscape != QUERYESCSUPPORT ) ) { MF_WriteEscape( hdc, iEscape, cjIn, lpIn, EMR_DRAWESCAPE ); } }
// Compute the buffer size we need. Since the in and out buffers
// get rounded up to multiples of 4 bytes, we need to simulate that
// here.
cjInput = (lpIn == NULL) ? 0 : ((cjIn+3)&-4);
iRet = NtGdiDrawEscape(hdc,iEscape,cjIn,(LPSTR)lpIn);
return(iRet); }
/******************************Public*Routine******************************\
* DeviceCapabilitiesExA * * This never got implemented. The spooler suports DeviceCapabilities. * * History: * 01-Aug-1991 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/
int WINAPI DeviceCapabilitiesExA( LPCSTR pszDriver, LPCSTR pszDevice, LPCSTR pszPort, int iIndex, LPCSTR pb, CONST DEVMODEA *pdm) { return(GDI_ERROR);
pszDriver; pszDevice; pszPort; iIndex; pb; pdm; }
/**************************************************************************\
* * New to be implemented Api's for Windows95. * \**************************************************************************/
#if 0
WINGDIAPI int WINAPI GetTextCharsetInfo( HDC hdc, LPFONTSIGNATURE lpSig, DWORD dwFlags) { return NtGdiGetTextCharsetInfo(hdc, lpSig, dwFlags); } #endif
WINGDIAPI int WINAPI GetTextCharset( HDC hdc) { return NtGdiGetTextCharsetInfo(hdc, NULL, 0); }
/******************************Public*Routine******************************\
* * WINGDIAPI BOOL WINAPI TranslateCharsetInfo( * * client side stub * * History: * 06-Jan-1995 -by- Bodin Dresevic [BodinD] * Wrote it \**************************************************************************/
// the definition of this variable is in ntgdi\inc\hmgshare.h
CHARSET_ARRAYS
WINGDIAPI BOOL WINAPI TranslateCharsetInfo( DWORD *lpSrc, LPCHARSETINFO lpCs, DWORD dwFlags) { UINT i; int index; CHARSETINFO cs; BOOL bRet = 0;
if (!lpCs) return 0;
//
// zero these out, we dont support them here.
//
cs.fs.fsUsb[0] = cs.fs.fsUsb[1] = cs.fs.fsUsb[2] = cs.fs.fsUsb[3] = cs.fs.fsCsb[1] = 0;
switch (dwFlags ) { case TCI_SRCCHARSET : { WORD src ;
src = LOWORD(PtrToUlong(lpSrc)); for ( i=0; i<NCHARSETS; i++ ) { if ( charsets[i] == src ) { cs.ciACP = codepages[i]; cs.ciCharset = src; cs.fs.fsCsb[0] = fs[i]; bRet = 1; break; } } } break;
case TCI_SRCCODEPAGE : { WORD src ;
src = LOWORD(PtrToUlong(lpSrc));
for ( i=0; i<NCHARSETS; i++ ) { if ( codepages[i] == src ) { cs.ciACP = src ; cs.ciCharset = charsets[i] ; cs.fs.fsCsb[0] = fs[i]; bRet = 1; break; } } } break;
case TCI_SRCLOCALE : { // should only come from USER. It's used to find the charset of a
// keyboard layout, and the fonts that it can be used with (fontsigs).
// It is also used to obtain the fontsignature of the system font.
// Used in WM_INPUTLANGCHANGE message, and to determine wParam low-bit
// in WM_INPUTLANGCHANGEREQUEST message.
LOCALESIGNATURE ls; int iRet;
iRet = GetLocaleInfoW((DWORD)(LOWORD(PtrToUlong(lpSrc))), LOCALE_FONTSIGNATURE, (LPWSTR)&ls, 0);
if (GetLocaleInfoW((DWORD)(LOWORD(PtrToUlong(lpSrc))), LOCALE_FONTSIGNATURE, (LPWSTR)&ls, iRet) ) { for ( i=0; i<NCHARSETS; i++ ) { if (fs[i] == ls.lsCsbDefault[0]) { cs.ciACP = codepages[i]; cs.ciCharset = charsets[i] ; cs.fs.fsCsb[0] = fs[i]; // a single fontsig
cs.fs.fsCsb[1] = ls.lsCsbSupported[0]; // mask of fontsigs
bRet = 1; break; } } } } break;
case TCI_SRCFONTSIG : { DWORD src;
//if(IsBadReadPtr(lpSrc, 8))
// return 0;
try { if (!(*(lpSrc+1))) { // we dont recognise ANY of the OEM code pages here!
src = *lpSrc;
for ( i=0; i<NCHARSETS; i++ ) { if ( fs[i] == src ) { cs.ciACP = codepages[i]; cs.ciCharset = charsets[i] ; cs.fs.fsCsb[0] = src; bRet = 1; break; } } } } except(EXCEPTION_EXECUTE_HANDLER) { } } break;
default: GdiSetLastError(ERROR_INVALID_PARAMETER); break; }
if (bRet) { try { *lpCs = cs; // copy out
} except(EXCEPTION_EXECUTE_HANDLER) { } }
return bRet; }
|