📄 font.c
字号:
/*
* ReactOS kernel
* Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: font.c 22634 2006-06-26 13:16:43Z fireball $
*
* PROJECT: ReactOS user32.dll
* FILE: lib/user32/windows/input.c
* PURPOSE: Input
* PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* UPDATE HISTORY:
* 09-05-2001 CSH Created
*/
/* INCLUDES ******************************************************************/
#include <user32.h>
#include <wine/debug.h>
/* FUNCTIONS *****************************************************************/
/*
* @implemented
*/
LONG
STDCALL
TabbedTextOutA(
HDC hDC,
int X,
int Y,
LPCSTR lpString,
int nCount,
int nTabPositions,
CONST LPINT lpnTabStopPositions,
int nTabOrigin)
{
LONG ret;
DWORD len;
LPWSTR strW;
len = MultiByteToWideChar(CP_ACP, 0, lpString, nCount, NULL, 0);
strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
if (!strW)
{
return 0;
}
MultiByteToWideChar(CP_ACP, 0, lpString, nCount, strW, len);
ret = TabbedTextOutW(hDC, X, Y, strW, len, nTabPositions, lpnTabStopPositions, nTabOrigin);
HeapFree(GetProcessHeap(), 0, strW);
return ret;
}
/***********************************************************************
* TEXT_TabbedTextOut
*
* Helper function for TabbedTextOut() and GetTabbedTextExtent().
* Note: this doesn't work too well for text-alignment modes other
* than TA_LEFT|TA_TOP. But we want bug-for-bug compatibility :-)
*/
/* WINE synced 22-May-2006 */
static LONG TEXT_TabbedTextOut( HDC hdc, INT x, INT y, LPCWSTR lpstr,
INT count, INT cTabStops, const INT *lpTabPos, INT nTabOrg,
BOOL fDisplayText )
{
INT defWidth;
SIZE extent;
int i, j;
int start = x;
if (!lpTabPos)
cTabStops=0;
if (cTabStops == 1)
{
defWidth = *lpTabPos;
cTabStops = 0;
}
else
{
TEXTMETRICA tm;
GetTextMetricsA( hdc, &tm );
defWidth = 8 * tm.tmAveCharWidth;
}
while (count > 0)
{
RECT r;
INT x0;
x0 = x;
r.left = x0;
/* chop the string into substrings of 0 or more <tabs>
* possibly followed by 1 or more normal characters */
for (i = 0; i < count; i++)
if (lpstr[i] != '\t') break;
for (j = i; j < count; j++)
if (lpstr[j] == '\t') break;
/* get the extent of the normal character part */
GetTextExtentPointW( hdc, lpstr + i, j - i , &extent );
/* and if there is a <tab>, calculate its position */
if( i) {
/* get x coordinate for the drawing of this string */
for (; cTabStops > i; lpTabPos++, cTabStops--)
{
if( nTabOrg + abs( *lpTabPos) > x) {
if( lpTabPos[ i - 1] >= 0) {
/* a left aligned tab */
x = nTabOrg + lpTabPos[ i-1] + extent.cx;
break;
}
else
{
/* if tab pos is negative then text is right-aligned
* to tab stop meaning that the string extends to the
* left, so we must subtract the width of the string */
if (nTabOrg - lpTabPos[ i - 1] - extent.cx > x)
{
x = nTabOrg - lpTabPos[ i - 1];
x0 = x - extent.cx;
break;
}
}
}
}
/* if we have run out of tab stops and we have a valid default tab
* stop width then round x up to that width */
if ((cTabStops <= i) && (defWidth > 0)) {
x0 = nTabOrg + ((x - nTabOrg) / defWidth + i) * defWidth;
x = x0 + extent.cx;
} else if ((cTabStops <= i) && (defWidth < 0)) {
x = nTabOrg + ((x - nTabOrg + extent.cx) / -defWidth + i)
* -defWidth;
x0 = x - extent.cx;
}
} else
x += extent.cx;
if (fDisplayText)
{
r.top = y;
r.right = x;
r.bottom = y + extent.cy;
ExtTextOutW( hdc, x0, y, GetBkMode(hdc) == OPAQUE ? ETO_OPAQUE : 0,
&r, lpstr + i, j - i, NULL );
}
count -= j;
lpstr += j;
}
return MAKELONG(x - start, extent.cy);
}
/*
* @implemented
*/
LONG
STDCALL
TabbedTextOutW(
HDC hDC,
int X,
int Y,
LPCWSTR lpString,
int nCount,
int nTabPositions,
CONST LPINT lpnTabStopPositions,
int nTabOrigin)
{
return TEXT_TabbedTextOut(hDC, X, Y, lpString, nCount, nTabPositions, lpnTabStopPositions, nTabOrigin, TRUE);
}
/* WINE synced 22-May-2006 */
/*
* @implemented
*/
DWORD
STDCALL
GetTabbedTextExtentA(
HDC hDC,
LPCSTR lpString,
int nCount,
int nTabPositions,
CONST LPINT lpnTabStopPositions)
{
LONG ret;
DWORD len = MultiByteToWideChar(CP_ACP, 0, lpString, nCount, NULL, 0);
LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
if (!strW)
return 0;
MultiByteToWideChar(CP_ACP, 0, lpString, nCount, strW, len);
ret = GetTabbedTextExtentW(hDC, strW, len, nTabPositions,
lpnTabStopPositions);
HeapFree(GetProcessHeap(), 0, strW);
return ret;
}
/*
* @implemented
*/
DWORD
STDCALL
GetTabbedTextExtentW(
HDC hDC,
LPCWSTR lpString,
int nCount,
int nTabPositions,
CONST LPINT lpnTabStopPositions)
{
return TEXT_TabbedTextOut(hDC, 0, 0, lpString, nCount, nTabPositions, lpnTabStopPositions, 0, FALSE);
}
/*********************************************************************
*
* DrawText functions
*
* Copied from Wine.
* Copyright 1993, 1994 Alexandre Julliard
* Copyright 2002 Bill Medland
*
* Design issues
* How many buffers to use
* While processing in DrawText there are potentially three different forms
* of the text that need to be held. How are they best held?
* 1. The original text is needed, of course, to see what to display.
* 2. The text that will be returned to the user if the DT_MODIFYSTRING is
* in effect.
* 3. The buffered text that is about to be displayed e.g. the current line.
* Typically this will exclude the ampersands used for prefixing etc.
*
* Complications.
* a. If the buffered text to be displayed includes the ampersands then
* we will need special measurement and draw functions that will ignore
* the ampersands (e.g. by copying to a buffer without the prefix and
* then using the normal forms). This may involve less space but may
* require more processing. e.g. since a line containing tabs may
* contain several underlined characters either we need to carry around
* a list of prefix locations or we may need to locate them several
* times.
* b. If we actually directly modify the "original text" as we go then we
* will need some special "caching" to handle the fact that when we
* ellipsify the text the ellipsis may modify the next line of text,
* which we have not yet processed. (e.g. ellipsification of a W at the
* end of a line will overwrite the W, the \n and the first character of
* the next line, and a \0 will overwrite the second. Try it!!)
*
* Option 1. Three separate storages. (To be implemented)
* If DT_MODIFYSTRING is in effect then allocate an extra buffer to hold
* the edited string in some form, either as the string itself or as some
* sort of "edit list" to be applied just before returning.
* Use a buffer that holds the ellipsified current line sans ampersands
* and accept the need occasionally to recalculate the prefixes (if
* DT_EXPANDTABS and not DT_NOPREFIX and not DT_HIDEPREFIX)
*/
#define TAB 9
#define LF 10
#define CR 13
#define SPACE 32
#define PREFIX 38
#define FORWARD_SLASH '/'
#define BACK_SLASH '\\'
static const WCHAR ELLIPSISW[] = {'.','.','.', 0};
typedef struct tag_ellipsis_data
{
int before;
int len;
int under;
int after;
} ellipsis_data;
/*********************************************************************
* TEXT_Ellipsify (static)
*
* Add an ellipsis to the end of the given string whilst ensuring it fits.
*
* If the ellipsis alone doesn't fit then it will be returned anyway.
*
* See Also TEXT_PathEllipsify
*
* Arguments
* hdc [in] The handle to the DC that defines the font.
* str [in/out] The string that needs to be modified.
* max_str [in] The dimension of str (number of WCHAR).
* len_str [in/out] The number of characters in str
* width [in] The maximum width permitted (in logical coordinates)
* size [out] The dimensions of the text
* modstr [out] The modified form of the string, to be returned to the
* calling program. It is assumed that the caller has
* made sufficient space available so we don't need to
* know the size of the space. This pointer may be NULL if
* the modified string is not required.
* len_before [out] The number of characters before the ellipsis.
* len_ellip [out] The number of characters in the ellipsis.
*
* See for example Microsoft article Q249678.
*
* For now we will simply use three dots rather than worrying about whether
* the font contains an explicit ellipsis character.
*/
static void TEXT_Ellipsify (HDC hdc, WCHAR *str, unsigned int max_len,
unsigned int *len_str, int width, SIZE *size,
WCHAR *modstr,
int *len_before, int *len_ellip)
{
unsigned int len_ellipsis;
unsigned int lo, mid, hi;
len_ellipsis = wcslen (ELLIPSISW);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -