Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

450 lines
12 KiB

/****************************** Module Header ******************************\
* Module Name: drawtext.c
*
* Copyright (c) 1985-91, Microsoft Corporation
*
* This module contains common text drawing functions.
*
* History:
* 02-12-92 mikeke Moved Drawtext to the client side
\***************************************************************************/
#include "precomp.h"
#pragma hdrstop
#define CR 13
#define LF 10
#define DT_HFMTMASK 0x03
/***************************************************************************\
* IsMetaFile
*
* History:
* 30-Nov-1992 mikeke Created
\***************************************************************************/
BOOL IsMetaFile(
HDC hdc)
{
DWORD dwType = GetObjectType(hdc);
return (dwType == OBJ_METAFILE ||
dwType == OBJ_METADC ||
dwType == OBJ_ENHMETAFILE ||
dwType == OBJ_ENHMETADC);
}
/***************************************************************************\
* DrawTextA (API)
*
* History:
* 30-11-92 mikeke Created
\***************************************************************************/
int DrawTextExA(
HDC hdc,
LPSTR lpchText,
int cchText,
LPRECT lprc,
UINT format,
LPDRAWTEXTPARAMS lpdtp)
{
LPWSTR lpwstr;
int iRet;
int iUniString;
WORD wCodePage = (WORD)GdiGetCodePage(hdc);
if ((iUniString = MBToWCSEx(wCodePage, lpchText, cchText, &lpwstr, -1, TRUE)) == 0)
return FALSE;
iRet = DrawTextExW(hdc, lpwstr, cchText, lprc, format, lpdtp);
if (format & DT_MODIFYSTRING)
WCSToMBEx(wCodePage, lpwstr, iUniString, &lpchText, iUniString, FALSE);
UserLocalFree((HANDLE)lpwstr);
return iRet;
}
/***************************************************************************\
* DrawTextW (API)
*
* History:
* 30-11-92 mikeke Created
\***************************************************************************/
int DrawTextW(
HDC hdc,
LPCWSTR lpchText,
int cchText,
LPRECT lprc,
UINT format)
{
DRAWTEXTPARAMS DTparams;
LPDRAWTEXTPARAMS lpDTparams = NULL;
/* v-ronaar: fix bug #24985
* Disallow negative string lengths, except -1 (which has special meaning).
*/
if (cchText < -1)
return(0);
if (format & DT_TABSTOP)
{
DTparams.cbSize = sizeof(DRAWTEXTPARAMS);
DTparams.iLeftMargin = DTparams.iRightMargin = 0;
DTparams.iTabLength = (format & 0xff00) >> 8;
lpDTparams = &DTparams;
format &= 0xffff00ff;
}
return DrawTextExW(hdc, (LPWSTR)lpchText, cchText, lprc, format, lpDTparams);
}
/***************************************************************************\
* DrawTextA (API)
*
* History:
* 30-11-92 mikeke Created
\***************************************************************************/
int DrawTextA(
HDC hdc,
LPCSTR lpchText,
int cchText,
LPRECT lprc,
UINT format)
{
LPWSTR lpwstr;
int nHeight;
int iUniString;
DRAWTEXTPARAMS DTparams;
LPDRAWTEXTPARAMS lpDTparams = NULL;
WORD wCodePage = (WORD)GdiGetCodePage(hdc);
/* v-ronaar: fix bug #24985
* Disallow negative string lengths, except -1 (which has special meaning).
*/
if (cchText < -1)
return 0;
if ((iUniString = MBToWCSEx(wCodePage, lpchText, cchText, &lpwstr, -1, TRUE)) == 0)
return 0;
if (format & DT_TABSTOP)
{
DTparams.cbSize = sizeof(DRAWTEXTPARAMS);
DTparams.iLeftMargin = DTparams.iRightMargin = 0;
DTparams.iTabLength = (format & 0xff00) >> 8;
lpDTparams = &DTparams;
format &= 0xffff00ff;
}
nHeight = DrawTextExW(hdc, lpwstr, cchText, lprc, format, lpDTparams);
if (format & DT_MODIFYSTRING)
WCSToMBEx(wCodePage, lpwstr, iUniString, &((LPSTR)lpchText), iUniString, FALSE);
UserLocalFree((HANDLE)lpwstr);
return nHeight;
}
/***************************************************************************\
* ClientTabTheTextOutForWimps
*
* effects: Outputs the tabbed text if fDrawTheText is TRUE and returns the
* textextent of the tabbed text.
*
* nCount Count of bytes in string
* nTabPositions Count of tabstops in tabstop array
* lpintTabStopPositions Tab stop positions in pixels
* iTabOrigin Tab stops are with respect to this
*
* History:
* 19-Jan-1993 mikeke Client side
\***************************************************************************/
LONG TabTextOut(
HDC hdc,
int x,
int y,
LPCWSTR lpstring,
int nCount,
int nTabPositions,
LPINT lpTabPositions,
int iTabOrigin,
BOOL fDrawTheText)
{
SIZE textextent, viewextent, windowextent;
int initialx = x;
int cch;
LPCWSTR lp;
int cxCharWidth;
int cyCharHeight = 0;
int iOneTab = 0;
RECT rc;
UINT uOpaque = (GetBkMode(hdc) == OPAQUE) ? ETO_OPAQUE : 0;
BOOL fStrStart = TRUE;
int ySign = 1; //Assume y increases in down direction.
if (!lpstring || !nCount || nTabPositions < 0)
return 0;
// Check if it is SysFont AND the mapping mode is MM_TEXT;
// Fix made in connection with Bug #8717 --02-01-90 --SANKAR--
if (IsSysFontAndDefaultMode(hdc))
{
cxCharWidth = gpsi->cxSysFontChar;
cyCharHeight = gpsi->cySysFontChar;
} else {
cxCharWidth = GdiGetCharDimensions(hdc, NULL, &cyCharHeight);
if (cxCharWidth == 0) {
RIPMSG0(RIP_WARNING, "TabTextOut: GdiGetCharDimensions failed");
return 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 (!lpTabPositions) {
// 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 = lpTabPositions[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))
return 0;
GetWindowExtEx(hdc, &windowextent);
if ((viewextent.cy ^ windowextent.cy) & 0x80000000)
ySign = -1;
rc.left = initialx;
rc.top = y;
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, lp = lpstring; cch && (*lp != TEXT('\t')); lp++, 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;
} else
GetTextExtentPointW(hdc, lpstring, cch, &textextent);
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 = lpTabPositions[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 (x < xTab)
{
// 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) {
/*
* Output all text up to the tab (or end of string) and get its
* extent.
*/
rc.right = x + textextent.cx;
ExtTextOutW(
hdc, x, y, uOpaque, &rc, (LPWSTR)lpstring,
cch, NULL);
rc.left = rc.right;
}
// Skip over the tab and the characters we just drew.
x += textextent.cx;
// Skip over the characters we just drew.
lpstring += 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) || ((nCount == 0) && (*lpstring == TEXT('\t'))))
{
lpstring++; // Skip over the tab
continue;
}
else
break; // Break from the loop.
}
return MAKELONG((x - initialx), (short)textextent.cy);
}
/***************************************************************************\
* TabbedTextOutW
*
* effects: Outputs the tabbed text and returns the
* textextent of the tabbed text.
*
* nCount Count of bytes in string
* nTabPositions Count of tabstops in tabstop array
* lpintTabStopPositions Tab stop positions in pixels
* iTabOrigin Tab stops are with respect to this
*
* History:
* 19-Jan-1993 mikeke Client side
\***************************************************************************/
LONG TabbedTextOutW(
HDC hdc,
int x,
int y,
LPCWSTR lpstring,
int cchChars,
int nTabPositions,
LPINT lpintTabStopPositions,
int iTabOrigin)
{
return TabTextOut(hdc, x, y, lpstring, cchChars,
nTabPositions, lpintTabStopPositions, iTabOrigin, TRUE);
}
/***************************************************************************\
* TabbedTextOutA (API)
*
* History:
* 30-11-92 mikeke Created
\***************************************************************************/
LONG TabbedTextOutA(
HDC hdc,
int x,
int y,
LPCSTR pString,
int chCount,
int nTabPositions,
LPINT pnTabStopPositions,
int nTabOrigin)
{
LPWSTR lpwstr;
BOOL bRet;
WORD wCodePage = (WORD)GdiGetCodePage(hdc);
if (!MBToWCSEx(wCodePage, pString, chCount, &lpwstr, -1, TRUE))
return FALSE;
bRet = TabTextOut(
hdc, x, y, lpwstr, chCount, nTabPositions,
pnTabStopPositions, nTabOrigin, TRUE);
UserLocalFree((HANDLE)lpwstr);
return bRet;
}
DWORD GetTabbedTextExtentW(
HDC hdc,
LPCWSTR pString,
int chCount,
int nTabPositions,
LPINT pnTabStopPositions)
{
return TabTextOut(hdc, 0, 0, pString, chCount,
nTabPositions, pnTabStopPositions, 0, FALSE);
}
DWORD GetTabbedTextExtentA(
HDC hdc,
LPCSTR pString,
int chCount,
int nTabPositions,
LPINT pnTabStopPositions)
{
LPWSTR lpwstr;
BOOL bRet;
WORD wCodePage = (WORD)GdiGetCodePage(hdc);
if (!MBToWCSEx(wCodePage, pString, chCount, &lpwstr, -1, TRUE))
return FALSE;
bRet = TabTextOut(hdc, 0, 0, lpwstr, chCount,
nTabPositions, pnTabStopPositions, 0, FALSE);
UserLocalFree((HANDLE)lpwstr);
return bRet;
}