Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

636 lines
21 KiB

//////////////////////////////////////////////////////////////////////////////
// //
// Module Name : LPK_USER.c //
// //
// Entry points (formal interfaces) for GDI32 to call //
// and route their APIs, so that we can implement our language-specific //
// features. //
// //
// Created : Nov 6, 1996 //
// Author : Mohamed AbdEl Hamid [mhamid] //
// //
// Copyright (c) 1996, Microsoft Corporation. All rights reserved. //
//////////////////////////////////////////////////////////////////////////////
#include "precomp.hxx"
///// Shared definitions for USER code
#define IS_ALTDC_TYPE(h) (LO_TYPE(h) != LO_DC_TYPE)
///
#undef TRACE
#define TRACE(a,b)
//////////////////////////////////////////////////////////////////////////////
// USER32 TabbedTextOut will call this function for supporting Multilingual //
// Tabbed Text handling. //
// LpkTabbedTextOut( HDC hdc , int x, int y, LPCWSTR lpstring, UINT nCount, //
// int nTabPositions, LPINT lpTabPositions, int iTabOrigin,//
// BOOL fDrawTheText, int cxCharWidth, int cyCharHeight, //
// int charSet) //
// hDC : Handle of device context //
// x : x-coordinate of text to render //
// y : y-coordinate of text to render //
// lpstring : Input string //
// nCount : Count of characters in input string //
// nTabPositions : Specifies the number of values in the array of //
// tab-stop positions. //
// lpTabPositions : The tab-stop positions array (increasing order)(+/-)//
// iTabOrigin : The X-coordinate position to start expand tabs //
// fDrawTheText : Draw the Text or expand tha tabs only //
// cxCharWidth : Character width to be use to expand the tabs //
// cxCharHeight : Character Height to be use to expand the tabs //
// charSet : Indicates character set of codes. to optimizing the work. ??//
// //
// Return : //
// If the function succeeds, return the string dimensions //
// Else, the return value is 0. //
// And we seted the error by call SetLastError. //
// //
// History : //
// Nov 6, 1996 -by- Mohamed AbdEl Hamid [mhamid] //
//////////////////////////////////////////////////////////////////////////////
LONG LpkTabbedTextOut(
HDC hdc,
int x,
int y,
WCHAR *pwcInChars,
int nCount,
int nTabPositions,
int *pTabPositions,
int iTabOrigin,
BOOL fDrawTheText,
int cxCharWidth,
int cyCharHeight,
int iCharset) {
SIZE textextent;
SIZE viewextent;
SIZE windowextent;
int initialx = x;
int cch;
WCHAR *pwc;
int iOneTab = 0;
RECT rc;
UINT uOpaque;
BOOL fStrStart = TRUE;
BOOL fRTLreading;
int ySign = 1; //Assume y increases in down direction.
UINT OldTextAlign;
HRESULT hr;
DWORD dwObjType;
RECT rcRTL;
STRING_ANALYSIS *psa;
uOpaque = (GetBkMode(hdc) == OPAQUE) ? ETO_OPAQUE : 0;
/*
* If no tabstop positions are specified, then use a default of 8 system
* font ave char widths or use the single fixed tab stop.
*/
if (!pTabPositions) {
// no tab stops specified -- default to a tab stop every 8 characters
iOneTab = 8 * cxCharWidth;
} else if (nTabPositions == 1) {
// one tab stop specified -- treat value as the tab increment, one
// tab stop every increment
iOneTab = pTabPositions[0];
if (!iOneTab) {
iOneTab = 1;
}
}
// Calculate if the y increases or decreases in the down direction using
// the ViewPortExtent and WindowExtents.
// If this call fails, hdc must be invalid
if (!GetViewportExtEx(hdc, &viewextent)) {
TRACEMSG(("LpkTabbedTextOut: GetViewportExtEx failed"));
return 0;
}
GetWindowExtEx(hdc, &windowextent);
if ((viewextent.cy ^ windowextent.cy) & 0x80000000) {
ySign = -1;
}
OldTextAlign = GetTextAlign(hdc);
fRTLreading = OldTextAlign & TA_RTLREADING;
SetTextAlign(hdc, (OldTextAlign & ~(TA_CENTER|TA_RIGHT)) | TA_LEFT);
rc.left = initialx;
rc.right= initialx;
rc.top = y;
if (OldTextAlign & TA_BOTTOM) {
rc.bottom = rc.top;
} else {
rc.bottom = rc.top + (ySign * cyCharHeight);
}
while (TRUE) {
// count the number of characters until the next tab character
// this set of characters (substring) will be the working set for
// each iteration of this loop
for (cch = nCount, pwc = pwcInChars; cch && (*pwc != TEXT('\t')); pwc++, cch--) {
}
// Compute the number of characters to be drawn with textout.
cch = nCount - cch;
// Compute the number of characters remaining.
nCount -= cch; // + 1;
// get height and width of substring
if (cch == 0) {
textextent.cx = 0;
textextent.cy = cyCharHeight;
psa = NULL;
} else {
dwObjType = GetObjectType(hdc);
hr = LpkStringAnalyse(
hdc, pwcInChars, cch, 0, -1,
SSA_GLYPHS
| (dwObjType == OBJ_METADC || dwObjType == OBJ_ENHMETADC ? SSA_METAFILE : 0)
| (iCharset==-1 || GdiIsPlayMetafileDC(hdc) ? SSA_FALLBACK : SSA_LPKANSIFALLBACK)
| (fRTLreading ? SSA_RTL : 0),
-1, 0,
NULL, NULL, NULL, NULL, NULL,
&psa);
if (FAILED(hr)) {
ASSERTHR(hr, ("LpkTabbedTextOut - LpkStringAnalyse"));
return FALSE;
}
textextent = psa->size;
}
if (fStrStart) {
// first iteration should just spit out the first substring
// no tabbing occurs until the first tab character is encountered
fStrStart = FALSE;
} else {
// not the first iteration -- tab accordingly
int xTab;
int i;
if (!iOneTab) {
// look thru tab stop array for next tab stop after existing
// text to put this substring
for (i = 0; i != nTabPositions; i++) {
xTab = pTabPositions[i];
if (xTab < 0) {
// calc length needed to use this right justified tab
xTab = iTabOrigin - xTab - textextent.cx;
} else {
// calc length needed to use this left justified tab
xTab = iTabOrigin + xTab;
}
if ((xTab - x) > 0) {
// we found a tab with enough room -- let's use it
x = xTab;
break;
}
}
if (i == nTabPositions) {
// we've exhausted all of the given tab positions
// go back to default of a tab stop every 8 characters
iOneTab = 8 * cxCharWidth;
}
}
// we have to recheck iOneTab here (instead of just saying "else")
// because iOneTab will be set if we've run out of tab stops
if (iOneTab) {
if (iOneTab < 0) {
// calc next available right justified tab stop
xTab = x + textextent.cx - iTabOrigin;
xTab = ((xTab / iOneTab) * iOneTab) - iOneTab - textextent.cx + iTabOrigin;
} else {
// calc next available left justified tab stop
xTab = x - iTabOrigin;
xTab = ((xTab / iOneTab) * iOneTab) + iOneTab + iTabOrigin;
}
x = xTab;
}
}
if (fDrawTheText && (cch!=0)) {
/*
* Output all text up to the tab (or end of string) and get its
* extent.
*/
rc.right = x + textextent.cx;
// All the calculations are made as if it is LTR and we flip the coordinates
// if we have RTL.
if (fRTLreading) {
rcRTL = rc;
rcRTL.left = (2 * initialx) - rc.right;
rcRTL.right= rcRTL.left + (rc.right - rc.left) ;
ScriptStringOut(psa, rcRTL.left , y, uOpaque, &rcRTL, 0, 0, FALSE);
} else {
ScriptStringOut(psa, x, y, uOpaque, &rc, 0, 0, FALSE);
}
rc.left = rc.right;
}
if (cch) {
ScriptStringFree((void**)&psa);
}
// Skip over the tab and the characters we just drew.
x = x + textextent.cx;
// Skip over the characters we just drew.
pwcInChars += cch;
// See if we have more to draw OR see if this string ends in
// a tab character that needs to be drawn.
if ((nCount > 0) && (*pwcInChars == TEXT('\t'))) {
pwcInChars++; // Skip over the tab
nCount--;
continue;
} else {
break; // Break from the loop.
}
}
// if we have at the end of the text some Tabs then wen need to drae the background
// for it.
if (fDrawTheText && x>rc.right && uOpaque)
{
rc.right = x;
if (fRTLreading) {
rcRTL = rc;
rcRTL.left = (2 * initialx) - rc.right;
rcRTL.right= rcRTL.left + (rc.right - rc.left) ;
ExtTextOutW(hdc, rcRTL.left, y, uOpaque|ETO_IGNORELANGUAGE, &rcRTL, L"", 0, NULL);
} else {
ExtTextOutW(hdc, rc.left, y, uOpaque|ETO_IGNORELANGUAGE, &rc, L"", 0, NULL);
}
}
SetTextAlign(hdc, OldTextAlign);
return MAKELONG((x - initialx), (short)textextent.cy);
}
//////////////////////////////////////////////////////////////////////////////
// USER32 PSMTextOut will call this function for supporting Multilingual //
// Menu handling. //
// LpkPSMTextOut( HDC hdc, int xLeft, int yTop, LPCWSTR lpString, //
// int nCount) //
// hDC : Handle of device context //
// xLeft : x-coordinate of text to render //
// yTop : y-coordinate of text to render //
// lpString : Input string //
// nCount : Count of characters in input string //
// //
// Return : Nothing //
// //
// History : //
// Nov 6, 1996 -by- Mohamed AbdEl Hamid [mhamid] //
//////////////////////////////////////////////////////////////////////////////
///// LpkInternalPSMtextOut
//
// Called from LPK_USRC.C
int LpkInternalPSMTextOut(
HDC hdc,
int xLeft,
int yTop,
const WCHAR *pwcInChars,
int nCount,
DWORD dwFlags) {
HRESULT hr;
int iTextAlign;
STRING_ANALYSIS *psa;
int iWidth;
DWORD dwObjType;
if (!nCount || !pwcInChars) {
// No action required
TRACE(GDI, ("LpkPSMTextOut: No string: nCount %d, pwcInChars %x",
nCount, pwcInChars));
return 0; // That was easy!
}
dwObjType = GetObjectType(hdc);
hr = LpkStringAnalyse(
hdc, pwcInChars, nCount, 0, -1,
SSA_GLYPHS
| (dwFlags & DT_NOPREFIX ? 0
: (dwFlags & DT_HIDEPREFIX ? SSA_HIDEHOTKEY
: (dwFlags & DT_PREFIXONLY ? SSA_HOTKEYONLY : SSA_HOTKEY)))
| (dwObjType == OBJ_METADC || dwObjType == OBJ_ENHMETADC ? SSA_METAFILE : 0)
| SSA_FALLBACK
| ((((iTextAlign = GetTextAlign(hdc)) & TA_RTLREADING) && (iTextAlign != -1)) ? SSA_RTL : 0),
-1, 0,
NULL, NULL, NULL, NULL, NULL,
&psa);
if (SUCCEEDED(hr)) {
iWidth = psa->size.cx;
ScriptStringOut(psa, xLeft, yTop, 0, NULL, 0, 0, FALSE);
ScriptStringFree((void**)&psa);
} else {
iWidth = 0;
ASSERTHR(hr, ("LpkInternalPSMTextOut - LpkStringAnalyse"));
psa = NULL;
}
return iWidth;
}
#ifdef LPKBREAKAWORD
//////////////////////////////////////////////////////////////////////////////
// //
// LpkBreakAWord : DrawText calls this routine when the length of a word //
// is longer than the line width. //
// //
// return - character position to break a non-breakable word //
// //
//////////////////////////////////////////////////////////////////////////////
///// LpkBreakAWord
//
// Called from LPK_USRC.C
int LpkBreakAWord(
HDC hdc,
LPCWSTR lpchStr,
int cchStr,
int iMaxWidth) {
if (!lpchStr || cchStr <= 0 || iMaxWidth <= 0)
return 0;
STRING_ANALYSIS* psa;
int cOutChars;
HRESULT hr;
hr = LpkStringAnalyse(
hdc, lpchStr, cchStr, 0, -1,
SSA_GLYPHS | SSA_CLIP,
-1, iMaxWidth,
NULL, NULL, NULL, NULL, NULL,
&psa);
if (FAILED(hr)) {
ASSERTHR(hr, ("LpkBreakAWord - qLpkStringAnalyse"));
return 0;
}
cOutChars = psa->cOutChars;
ScriptStringFree((void**)&psa);
return max(0, cOutChars);
}
#endif
//////////////////////////////////////////////////////////////////////////////
// //
// LpkGetNextWord //
// return - offset to the next word //
// //
//////////////////////////////////////////////////////////////////////////////
#define CR 0x000D
#define LF 0x000A
///// LpkgetNextWord
//
// Called from LPK_USRC.C
int LpkGetNextWord(
HDC hdc,
LPCWSTR lpchStr,
int cchCount,
int iCharset) {
WCHAR *pRun;
WCHAR *pRunEnd;
int cchRun;
int i=0;
WCHAR wchRun;
HRESULT hr;
STRING_ANALYSIS *psa;
// instantly advance 1 if current char located at whitespaces.
if (*lpchStr == '\t' || *lpchStr == ' ') {
return 1;
}
// try to find the shortest text run that are going to be analysed
cchRun = 0;
pRun = (PWSTR)lpchStr;
pRunEnd = (PWSTR)(lpchStr + cchCount);
while (pRun < pRunEnd) {
wchRun = *pRun;
if (wchRun == CR || wchRun == LF ||
wchRun == '\t' || wchRun == ' ') {
break;
}
pRun++;
cchRun++;
}
if (cchRun == 0) {
return 0;
}
hr = LpkStringAnalyse(
hdc, lpchStr, cchRun, 0, -1,
SSA_BREAK,
-1, 0,
NULL, NULL, NULL, NULL, NULL,
&psa);
if (FAILED(hr)) {
ASSERTHR(hr, ("LpkGetNextWord - qLpkStringAnalyse"));
return 0;
}
// We only return next wordbreak if the first item is a breakable one.
if (g_ppScriptProperties[psa->pItems->a.eScript]->fComplex) {
for (i=1; i < cchRun; i++) {
if (psa->pLogAttr[i].fSoftBreak )
break;
}
}
ScriptStringFree((void**)&psa);
return i;
}
//////////////////////////////////////////////////////////////////////////////
// USER32 DrawTextEx will call this function for supporting Multilingual //
// DrawTextEx handling. //
// LpkDrawTextEx(HDC hdc, int xLeft, int yTop,LPCWSTR pwcInChars, int cchCount//
// , BOOL fDraw, WORD wFormat, LPDRAWTEXTDATA lpDrawInfo, //
// UNIT bAction) //
// hDC : Handle of device context //
// xLeft : x-coordinate of text to render //
// yTop : y-coordinate of text to render //
// lpchStr : Input string //
// cchCount : Count of characters in input string //
// fDraw : Draw the Text or expand tha tabs only //
// wFormat : Same as dwDTFormat options for DrawTextEx //
// lpDrawInfo : Internal Structure //
// bAction : DT_CHARSETDRAW OR DT_GETNEXTWORD //
// //
// Return : Nothing //
// //
// History : //
// Nov 15, 1996 -by- Mohamed AbdEl Hamid [mhamid] //
// Mar 26, 1997 Adding DT_GETNEXTWORD -[wchao] //
//////////////////////////////////////////////////////////////////////////////
///// LpkCharsetDraw
//
// Called from LPK_USRC.C
//
// Note: Doesn't implement user defined tabstops
int LpkCharsetDraw(
HDC hdc,
int xLeft,
int cxOverhang,
int iTabOrigin,
int iTabLength,
int yTop,
PCWSTR pcwString,
int cchCount,
BOOL fDraw,
DWORD dwFormat,
int iCharset) {
HRESULT hr;
int iTextAlign;
int iWidth;
STRING_ANALYSIS *psa;
SCRIPT_TABDEF std;
DWORD dwObjType;
if (cchCount <= 0) {
return 0; // That was easy!
}
if (dwFormat & DT_EXPANDTABS) {
std.cTabStops = 1;
std.pTabStops = &iTabLength;
std.iTabOrigin = 0;
std.iScale = 4; // Tab stops in pixels (avg ch width already applied in USER)
}
dwObjType = GetObjectType(hdc);
hr = LpkStringAnalyse(
hdc, pcwString, cchCount, 0, -1,
SSA_GLYPHS
| (dwFormat & DT_NOPREFIX ? 0
: (dwFormat & DT_HIDEPREFIX ? SSA_HIDEHOTKEY
: (dwFormat & DT_PREFIXONLY ? SSA_HOTKEYONLY : SSA_HOTKEY)))
| (dwFormat & DT_EXPANDTABS ? SSA_TAB : 0)
| (dwObjType == OBJ_METADC || dwObjType == OBJ_ENHMETADC ? SSA_METAFILE : 0)
| (iCharset==-1 || GdiIsPlayMetafileDC(hdc) ? SSA_FALLBACK : SSA_LPKANSIFALLBACK)
| ( dwFormat & DT_RTLREADING
|| (((iTextAlign = GetTextAlign(hdc)) & TA_RTLREADING) && (iTextAlign != -1))
? SSA_RTL : 0),
-1, 0,
NULL, NULL, NULL,
dwFormat & DT_EXPANDTABS ? &std : NULL,
NULL,
&psa);
if (SUCCEEDED(hr)) {
iWidth = psa->size.cx;
if (fDraw && (!(dwFormat & DT_CALCRECT))) {
ScriptStringOut(psa, xLeft, yTop, 0, NULL, 0, 0, FALSE);
}
ScriptStringFree((void**)&psa);
} else {
iWidth = 0;
ASSERTHR(hr, ("LpkCharsetDraw - LpkStringAnalyse"));
psa = NULL;
}
return iWidth;
}