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.
 
 
 
 
 
 

646 lines
16 KiB

//// TEXTWND.CPP
//
// Maintains the text display panel
#include "precomp.hxx"
#include "global.h"
#include "winspool.h"
#include <Tchar.h>
//// InvalidateText - Force redisplay
//
//
void InvalidateText() {
RECT rc;
rc.left = g_fPresentation ? 0 : g_iSettingsWidth;
rc.top = 0;
rc.right = 10000;
rc.bottom = 10000;
InvalidateRect(g_hTextWnd, &rc, TRUE);
}
//// Header - draw a simple header for each text section
//
// Used to distinguish logical, plaintext and formatted text sections of
// text window.
//
// Advances SEPARATORHEIGHT drawing a horizontal line 2/5ths of the way
// down, and displays a title below the line.
//
// At the top of the page displays only the title.
void Header(HDC hdc, char* str, RECT *prc, int *piY) {
HFONT hf;
HFONT hfold;
RECT rcClear;
int iLinePos;
int iTextPos;
int iFontEmHeight;
int iHeight;
int separatorHeight = (prc->bottom - prc->top) / 20;
iFontEmHeight = separatorHeight*40/100;
if (*piY <= prc->top)
{
// Prepare settings for title only, at top of window
iLinePos = -1;
iTextPos = 0;
iHeight = separatorHeight*60/100;
}
else
{
// Prepare settings for 40% white space, a line, 10% whitespace, text and 3% whitespace
iLinePos = separatorHeight*30/100;
iTextPos = separatorHeight*40/100;
iHeight = separatorHeight;
}
rcClear = *prc;
rcClear.top = *piY;
rcClear.bottom = *piY + iHeight;
FillRect(hdc, &rcClear, (HBRUSH) GetStockObject(WHITE_BRUSH));
if (*piY > prc->top) {
// Separate from previous output with double pixel line
MoveToEx(hdc, prc->left, *piY+iLinePos, NULL);
LineTo (hdc, prc->right, *piY+iLinePos);
MoveToEx(hdc, prc->left, *piY+iLinePos+1, NULL);
LineTo (hdc, prc->right, *piY+iLinePos+1);
}
hf = CreateFontA(-iFontEmHeight, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "Tahoma");
hfold = (HFONT) SelectObject(hdc, hf);
ExtTextOutA(hdc, prc->left, *piY + iTextPos, 0, prc, str, strlen(str), NULL);
*piY += iHeight;
SelectObject(hdc, hfold);
DeleteObject(hf);
}
//// ResetCaret - used during paint by each DSP*.CPP
//
//
void ResetCaret(int iX, int iY, int iHeight) {
g_iCaretX = iX;
g_iCaretY = iY;
if (g_iCaretHeight != iHeight) {
g_iCaretHeight = iHeight;
HideCaret(g_hTextWnd);
DestroyCaret();
CreateCaret(g_hTextWnd, NULL, 0, g_iCaretHeight);
SetCaretPos(g_iCaretX, g_iCaretY);
ShowCaret(g_hTextWnd);
} else {
SetCaretPos(g_iCaretX, g_iCaretY);
}
}
///// PaintDC - display all selected tests, either on screen
// or on printer.
void PaintDC(HDC hdc, BOOL presentation, RECT &rcText, INT &iY)
{
int iPos;
int iLineHeight;
iY = rcText.top;
if (presentation) {
iLineHeight = rcText.bottom*9/20;
} else {
iLineHeight = 40;
}
if (g_ShowGDI) {
if (!presentation) {
Header(hdc, "GDI", &rcText, &iY);
}
PaintGDI(hdc, &iY, &rcText, iLineHeight);
}
if (g_ShowFamilies) {
if (!presentation) {
Header(hdc, "Font families", &rcText, &iY);
}
PaintFamilies(hdc, &iY, &rcText, iLineHeight);
}
if (g_ShowLogical) {
if (!presentation) {
Header(hdc, "Logical characters (ScriptGetCmap, ExtTextOut(ETO_GLYPHINDEX))", &rcText, &iY);
}
PaintLogical(hdc, &iY, &rcText, iLineHeight);
}
if (g_ShowGlyphs) {
if (!presentation) {
Header(hdc, "DrawGlyphs", &rcText, &iY);
}
PaintGlyphs(hdc, &iY, &rcText, iLineHeight);
}
if (g_ShowDrawString) {
if (!presentation) {
Header(hdc, "DrawString", &rcText, &iY);
}
PaintDrawString(hdc, &iY, &rcText, iLineHeight);
}
if (g_ShowDriver) {
if (!presentation) {
Header(hdc, "DrawDriverString", &rcText, &iY);
}
PaintDrawDriverString(hdc, &iY, &rcText, iLineHeight);
}
if (g_ShowPath) {
if (!presentation) {
Header(hdc, "Path", &rcText, &iY);
}
PaintPath(hdc, &iY, &rcText, iLineHeight);
}
if (g_ShowMetric) {
if (!presentation) {
Header(hdc, "Metrics", &rcText, &iY);
}
PaintMetrics(hdc, &iY, &rcText, iLineHeight);
}
if (g_ShowPerformance) {
if (!presentation) {
Header(hdc, "Performance", &rcText, &iY);
}
PaintPerformance(hdc, &iY, &rcText, iLineHeight);
}
if (g_ShowScaling) {
if (!presentation) {
Header(hdc, "Scaling", &rcText, &iY);
}
PaintScaling(hdc, &iY, &rcText, iLineHeight);
}
/*
if (g_fShowFancyText && !presentation) {
Header(hdc, "Formatted text (ScriptItemize, ScriptLayout, ScriptShape, ScriptPlace, ScriptTextOut)", &rcText, &iY);
PaintFormattedText(hdc, &iY, &rcText, iLineHeight);
}
*/
}
//// Paint - redraw part or all of client area
//
//
void PaintWindow(HWND hWnd) {
PAINTSTRUCT ps;
HDC hdc;
RECT rcText;
RECT rcClear;
int iY;
hdc = BeginPaint(hWnd, &ps);
// Remove the settings dialog from the repaint rectangle
if (ps.fErase) {
// Clear below the settings dialog
if (!g_fPresentation) {
rcClear = ps.rcPaint;
if (rcClear.right > g_iSettingsWidth) {
rcClear.right = g_iSettingsWidth;
}
if (rcClear.top < g_iSettingsHeight) {
rcClear.top = g_iSettingsHeight;
}
FillRect(ps.hdc, &rcClear, (HBRUSH) GetStockObject(WHITE_BRUSH));
}
}
// Clear top and left margin
GetClientRect(hWnd, &rcText);
// Left margin
rcClear = rcText;
rcClear.left = g_fPresentation ? 0 : g_iSettingsWidth;
rcClear.right = rcClear.left + 10;
FillRect(ps.hdc, &rcClear, (HBRUSH) GetStockObject(WHITE_BRUSH));
// Top margin
rcClear = rcText;
rcClear.left = g_fPresentation ? 0 : g_iSettingsWidth;
rcClear.top = 0;
rcClear.bottom = 8;
FillRect(ps.hdc, &rcClear, (HBRUSH) GetStockObject(WHITE_BRUSH));
rcText.left = g_fPresentation ? 10 : g_iSettingsWidth + 10;
rcText.top = 8;
if (!g_Offscreen)
{
PaintDC(hdc, g_fPresentation, rcText, iY);
}
else
{
// Render everything to an offscreen buffer instead of
// directly to the display surface...
HBITMAP hbmpOffscreen = NULL;
HDC hdcOffscreen = NULL;
RECT rectOffscreen;
rectOffscreen.left = 0;
rectOffscreen.top = 0;
rectOffscreen.right = rcText.right - rcText.left;
rectOffscreen.bottom = rcText.bottom - rcText.top;
hbmpOffscreen = CreateCompatibleBitmap(hdc, rectOffscreen.right, rectOffscreen.bottom);
if (hbmpOffscreen)
{
hdcOffscreen = CreateCompatibleDC(hdc);
if (hdcOffscreen)
{
HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcOffscreen, hbmpOffscreen);
PaintDC(hdcOffscreen, g_fPresentation, rectOffscreen, iY);
StretchBlt(
hdc,
rcText.left,
rcText.top,
rectOffscreen.right,
rectOffscreen.bottom,
hdcOffscreen,
0,
0,
rectOffscreen.right,
rectOffscreen.bottom,
SRCCOPY);
SelectObject(hdcOffscreen, (HGDIOBJ)hbmpOld);
DeleteDC(hdcOffscreen);
}
DeleteObject(hbmpOffscreen);
}
}
// Clear any remaining space below the text
if ( ps.fErase
&& iY < rcText.bottom) {
rcClear = rcText;
rcClear.top = iY;
FillRect(ps.hdc, &rcClear, (HBRUSH) GetStockObject(WHITE_BRUSH));
}
EndPaint(hWnd, &ps);
}
void PrintPage()
{
PRINTDLG printDialog;
memset(&printDialog, 0, sizeof(printDialog));
printDialog.lStructSize = sizeof(printDialog);
printDialog.Flags = PD_RETURNDC | PD_NOPAGENUMS | PD_NOSELECTION ;
if (PrintDlg(&printDialog))
{
HDC dc = printDialog.hDC;
if (dc != NULL)
{
DOCINFO documentInfo;
documentInfo.cbSize = sizeof(documentInfo);
documentInfo.lpszDocName = _T("TextTest");
documentInfo.lpszOutput = NULL;
documentInfo.lpszDatatype = NULL;
documentInfo.fwType = 0;
if (StartDoc(dc, &documentInfo))
{
if (StartPage(dc) > 0)
{
RECT rcText;
INT iY;
rcText.left = 0;
rcText.top = 0;
rcText.right = GetDeviceCaps(dc, HORZRES);
rcText.bottom = GetDeviceCaps(dc, VERTRES);
PaintDC(dc, FALSE, rcText, iY);
EndPage(dc);
}
EndDoc(dc);
}
DeleteDC(dc);
}
}
}
//// TextWndProc - Main window message handler and dispatcher
//
//
LRESULT CALLBACK TextWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
HDC hdc;
switch (message) {
case WM_CREATE:
hdc = GetDC(hWnd);
g_iLogPixelsY = GetDeviceCaps(hdc, LOGPIXELSY);
ReleaseDC(hWnd, hdc);
break;
case WM_ERASEBKGND:
return 0; // Leave Paint to erase the background
case WM_CHAR:
if (!g_bUnicodeWnd) {
// Convert ANSI keyboard data to Unicode
int iCP;
switch (PRIMARYLANGID(LOWORD(GetKeyboardLayout(NULL)))) {
case LANG_ARABIC: iCP = 1256; break;
case LANG_HEBREW: iCP = 1255; break;
case LANG_THAI: iCP = 874; break;
default: iCP = 1252; break;
}
MultiByteToWideChar(iCP, 0, (char*)&wParam, 1, (WCHAR*)&wParam, 1);
}
if (LOWORD(wParam) == 0x1B) {
// Exit presentation mode
g_fPresentation = FALSE;
ShowWindow(g_hSettingsDlg, SW_SHOW);
UpdateWindow(g_hSettingsDlg);
InvalidateText();
} else {
EditChar(LOWORD(wParam));
}
break;
case WM_KEYDOWN:
EditKeyDown(LOWORD(wParam));
break;
case WM_KEYUP:
if (wParam != VK_ESCAPE) {
goto DefaultWindowProcedure;
}
// Eat all escape key processing
break;
case WM_LBUTTONDOWN:
g_iMouseDownX = LOWORD(lParam); // horizontal position of cursor
g_iMouseDownY = HIWORD(lParam); // vertical position of cursor
g_fMouseDown = TRUE;
SetFocus(hWnd);
break;
case WM_MOUSEMOVE:
// Treat movement like lbuttonup while lbutton is down,
// so the selection tracks the cursor movement.
if (wParam & MK_LBUTTON) {
g_iMouseUpX = LOWORD(lParam); // horizontal position of cursor
g_iMouseUpY = HIWORD(lParam); // vertical position of cursor
g_fMouseUp = TRUE;
InvalidateText();
SetActiveWindow(hWnd);
}
break;
case WM_LBUTTONUP:
g_iMouseUpX = LOWORD(lParam); // horizontal position of cursor
g_iMouseUpY = HIWORD(lParam); // vertical position of cursor
g_fMouseUp = TRUE;
InvalidateText();
SetActiveWindow(hWnd);
break;
case WM_SETFOCUS:
CreateCaret(hWnd, NULL, 0, g_iCaretHeight);
SetCaretPos(g_iCaretX, g_iCaretY);
ShowCaret(hWnd);
break;
case WM_KILLFOCUS:
DestroyCaret();
break;
case WM_GETMINMAXINFO:
// Don't let text window size drop too low
((LPMINMAXINFO)lParam)->ptMinTrackSize.x = g_fPresentation ? 10 : g_iMinWidth;
((LPMINMAXINFO)lParam)->ptMinTrackSize.y = g_fPresentation ? 10 : g_iMinHeight;
return 0;
case WM_PAINT:
PaintWindow(hWnd);
break;
case WM_DESTROY:
if (g_textBrush)
delete g_textBrush;
if (g_textBackBrush)
delete g_textBackBrush;
DestroyWindow(g_hSettingsDlg);
PostQuitMessage(0);
return 0;
default:
DefaultWindowProcedure:
if (g_bUnicodeWnd) {
return DefWindowProcW(hWnd, message, wParam, lParam);
} else {
return DefWindowProcA(hWnd, message, wParam, lParam);
}
}
return 0;
}
//// CreateTextWindow - create window class and window
//
// Attempts to use a Unicode window, if this fails uses an ANSI
// window.
//
// For example the Unicode window will succeed on Windows NT and
// Windows CE, but fail on Windows 9x.
HWND CreateTextWindow() {
WNDCLASSA wcA;
WNDCLASSW wcW;
HWND hWnd;
// Try registering as a Unicode window
wcW.style = CS_HREDRAW | CS_VREDRAW;
wcW.lpfnWndProc = TextWndProc;
wcW.cbClsExtra = 0;
wcW.cbWndExtra = 0;
wcW.hInstance = g_hInstance;
wcW.hIcon = LoadIconW(g_hInstance, APPNAMEW);
wcW.hCursor = LoadCursorW(NULL, (WCHAR*)IDC_ARROW);
wcW.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcW.lpszMenuName = APPNAMEW;
wcW.lpszClassName = APPNAMEW;
if (RegisterClassW(&wcW)) {
// Use a Unicode window
g_bUnicodeWnd = TRUE;
hWnd = CreateWindowW(
APPNAMEW, APPTITLEW,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0,
CW_USEDEFAULT, 0,
NULL, NULL,
g_hInstance,
NULL);
return hWnd;
} else {
// Must use an ANSI window.
wcA.style = CS_HREDRAW | CS_VREDRAW;
wcA.lpfnWndProc = TextWndProc;
wcA.cbClsExtra = 0;
wcA.cbWndExtra = 0;
wcA.hInstance = g_hInstance;
wcA.hIcon = LoadIconA(g_hInstance, APPNAMEA);
wcA.hCursor = LoadCursor(NULL, IDC_ARROW);
wcA.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcA.lpszMenuName = APPNAMEA;
wcA.lpszClassName = APPNAMEA;
if (!RegisterClassA(&wcA)) {
return NULL;
}
g_bUnicodeWnd = FALSE;
hWnd = CreateWindowA(
APPNAMEA, APPTITLEA,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0,
CW_USEDEFAULT, 0,
NULL, NULL,
g_hInstance,
NULL);
};
return hWnd;
}