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.
365 lines
9.8 KiB
365 lines
9.8 KiB
/*
|
|
*******************************************************************************
|
|
*
|
|
* © 2016 and later: Unicode, Inc. and others.
|
|
* License & terms of use: http://www.unicode.org/copyright.html
|
|
*
|
|
*******************************************************************************
|
|
*******************************************************************************
|
|
*
|
|
* Copyright (C) 1999-2007, International Business Machines
|
|
* Corporation and others. All Rights Reserved.
|
|
*
|
|
*******************************************************************************
|
|
* file name: Layout.cpp
|
|
*
|
|
* created on: 08/03/2000
|
|
* created by: Eric R. Mader
|
|
*/
|
|
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
|
|
#include "paragraph.h"
|
|
|
|
#include "GDIGUISupport.h"
|
|
#include "GDIFontMap.h"
|
|
#include "UnicodeReader.h"
|
|
#include "ScriptCompositeFontInstance.h"
|
|
|
|
#include "resource.h"
|
|
|
|
#define ARRAY_LENGTH(array) (sizeof array / sizeof array[0])
|
|
|
|
struct Context
|
|
{
|
|
le_int32 width;
|
|
le_int32 height;
|
|
Paragraph *paragraph;
|
|
};
|
|
|
|
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
|
|
|
|
#define APP_NAME "LayoutSample"
|
|
|
|
TCHAR szAppName[] = TEXT(APP_NAME);
|
|
|
|
void PrettyTitle(HWND hwnd, char *fileName)
|
|
{
|
|
char title[MAX_PATH + 64];
|
|
|
|
sprintf(title, "%s - %s", APP_NAME, fileName);
|
|
|
|
SetWindowTextA(hwnd, title);
|
|
}
|
|
|
|
void InitParagraph(HWND hwnd, Context *context)
|
|
{
|
|
SCROLLINFO si;
|
|
|
|
if (context->paragraph != NULL) {
|
|
// FIXME: does it matter what we put in the ScrollInfo
|
|
// if the window's been minimized?
|
|
if (context->width > 0 && context->height > 0) {
|
|
context->paragraph->breakLines(context->width, context->height);
|
|
}
|
|
|
|
si.cbSize = sizeof si;
|
|
si.fMask = SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL;
|
|
si.nMin = 0;
|
|
si.nMax = context->paragraph->getLineCount() - 1;
|
|
si.nPage = context->height / context->paragraph->getLineHeight();
|
|
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
|
|
}
|
|
}
|
|
|
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
|
|
{
|
|
HWND hwnd;
|
|
HACCEL hAccel;
|
|
MSG msg;
|
|
WNDCLASS wndclass;
|
|
LEErrorCode status = LE_NO_ERROR;
|
|
|
|
wndclass.style = CS_HREDRAW | CS_VREDRAW;
|
|
wndclass.lpfnWndProc = WndProc;
|
|
wndclass.cbClsExtra = 0;
|
|
wndclass.cbWndExtra = sizeof(LONG);
|
|
wndclass.hInstance = hInstance;
|
|
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
|
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
|
|
wndclass.lpszMenuName = szAppName;
|
|
wndclass.lpszClassName = szAppName;
|
|
|
|
if (!RegisterClass(&wndclass)) {
|
|
MessageBox(NULL, TEXT("This demo only runs on Windows 2000!"), szAppName, MB_ICONERROR);
|
|
|
|
return 0;
|
|
}
|
|
|
|
hAccel = LoadAccelerators(hInstance, szAppName);
|
|
|
|
hwnd = CreateWindow(szAppName, NULL,
|
|
WS_OVERLAPPEDWINDOW | WS_VSCROLL,
|
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
|
600, 400,
|
|
NULL, NULL, hInstance, NULL);
|
|
|
|
ShowWindow(hwnd, iCmdShow);
|
|
UpdateWindow(hwnd);
|
|
|
|
while (GetMessage(&msg, NULL, 0, 0)) {
|
|
if (!TranslateAccelerator(hwnd, hAccel, &msg)) {
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
|
|
UnregisterClass(szAppName, hInstance);
|
|
return msg.wParam;
|
|
}
|
|
|
|
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HDC hdc;
|
|
Context *context;
|
|
static le_int32 windowCount = 0;
|
|
static GDIFontMap *fontMap = NULL;
|
|
static GDISurface *surface = NULL;
|
|
static GDIGUISupport *guiSupport = new GDIGUISupport();
|
|
static ScriptCompositeFontInstance *font = NULL;
|
|
|
|
switch (message) {
|
|
case WM_CREATE:
|
|
{
|
|
LEErrorCode fontStatus = LE_NO_ERROR;
|
|
|
|
hdc = GetDC(hwnd);
|
|
surface = new GDISurface(hdc);
|
|
|
|
fontMap = new GDIFontMap(surface, "FontMap.GDI", 24, guiSupport, fontStatus);
|
|
font = new ScriptCompositeFontInstance(fontMap);
|
|
|
|
if (LE_FAILURE(fontStatus)) {
|
|
ReleaseDC(hwnd, hdc);
|
|
return -1;
|
|
}
|
|
|
|
context = new Context();
|
|
|
|
context->width = 600;
|
|
context->height = 400;
|
|
|
|
context->paragraph = Paragraph::paragraphFactory("Sample.txt", font, guiSupport);
|
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) context);
|
|
|
|
windowCount += 1;
|
|
ReleaseDC(hwnd, hdc);
|
|
|
|
PrettyTitle(hwnd, "Sample.txt");
|
|
return 0;
|
|
}
|
|
|
|
case WM_SIZE:
|
|
{
|
|
context = (Context *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
context->width = LOWORD(lParam);
|
|
context->height = HIWORD(lParam);
|
|
|
|
InitParagraph(hwnd, context);
|
|
return 0;
|
|
}
|
|
|
|
case WM_VSCROLL:
|
|
{
|
|
SCROLLINFO si;
|
|
le_int32 vertPos;
|
|
|
|
si.cbSize = sizeof si;
|
|
si.fMask = SIF_ALL;
|
|
GetScrollInfo(hwnd, SB_VERT, &si);
|
|
|
|
vertPos = si.nPos;
|
|
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case SB_TOP:
|
|
si.nPos = si.nMin;
|
|
break;
|
|
|
|
case SB_BOTTOM:
|
|
si.nPos = si.nMax;
|
|
break;
|
|
|
|
case SB_LINEUP:
|
|
si.nPos -= 1;
|
|
break;
|
|
|
|
case SB_LINEDOWN:
|
|
si.nPos += 1;
|
|
break;
|
|
|
|
case SB_PAGEUP:
|
|
si.nPos -= si.nPage;
|
|
break;
|
|
|
|
case SB_PAGEDOWN:
|
|
si.nPos += si.nPage;
|
|
break;
|
|
|
|
case SB_THUMBTRACK:
|
|
si.nPos = si.nTrackPos;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
si.fMask = SIF_POS;
|
|
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
|
|
GetScrollInfo(hwnd, SB_VERT, &si);
|
|
|
|
context = (Context *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
|
|
if (context->paragraph != NULL && si.nPos != vertPos) {
|
|
ScrollWindow(hwnd, 0, context->paragraph->getLineHeight() * (vertPos - si.nPos), NULL, NULL);
|
|
UpdateWindow(hwnd);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
case WM_PAINT:
|
|
{
|
|
PAINTSTRUCT ps;
|
|
SCROLLINFO si;
|
|
le_int32 firstLine, lastLine;
|
|
|
|
hdc = BeginPaint(hwnd, &ps);
|
|
SetBkMode(hdc, TRANSPARENT);
|
|
|
|
si.cbSize = sizeof si;
|
|
si.fMask = SIF_ALL;
|
|
GetScrollInfo(hwnd, SB_VERT, &si);
|
|
|
|
firstLine = si.nPos;
|
|
|
|
context = (Context *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
|
|
if (context->paragraph != NULL) {
|
|
surface->setHDC(hdc);
|
|
|
|
// NOTE: si.nPos + si.nPage may include a partial line at the bottom
|
|
// of the window. We need this because scrolling assumes that the
|
|
// partial line has been painted.
|
|
lastLine = min (si.nPos + (le_int32) si.nPage, context->paragraph->getLineCount() - 1);
|
|
|
|
context->paragraph->draw(surface, firstLine, lastLine);
|
|
}
|
|
|
|
EndPaint(hwnd, &ps);
|
|
return 0;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam)) {
|
|
case IDM_FILE_OPEN:
|
|
{
|
|
OPENFILENAMEA ofn;
|
|
char szFileName[MAX_PATH], szTitleName[MAX_PATH];
|
|
static char szFilter[] = "Text Files (.txt)\0*.txt\0"
|
|
"All Files (*.*)\0*.*\0\0";
|
|
|
|
ofn.lStructSize = sizeof (OPENFILENAMEA);
|
|
ofn.hwndOwner = hwnd;
|
|
ofn.hInstance = NULL;
|
|
ofn.lpstrFilter = szFilter;
|
|
ofn.lpstrCustomFilter = NULL;
|
|
ofn.nMaxCustFilter = 0;
|
|
ofn.nFilterIndex = 0;
|
|
ofn.lpstrFile = szFileName;
|
|
ofn.nMaxFile = MAX_PATH;
|
|
ofn.lpstrFileTitle = szTitleName;
|
|
ofn.nMaxFileTitle = MAX_PATH;
|
|
ofn.lpstrInitialDir = NULL;
|
|
ofn.lpstrTitle = NULL;
|
|
ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
|
|
ofn.nFileOffset = 0;
|
|
ofn.nFileExtension = 0;
|
|
ofn.lpstrDefExt = "txt";
|
|
ofn.lCustData = 0L;
|
|
ofn.lpfnHook = NULL;
|
|
ofn.lpTemplateName = NULL;
|
|
|
|
szFileName[0] = '\0';
|
|
|
|
if (GetOpenFileNameA(&ofn)) {
|
|
hdc = GetDC(hwnd);
|
|
surface->setHDC(hdc);
|
|
|
|
Paragraph *newParagraph = Paragraph::paragraphFactory(szFileName, font, guiSupport);
|
|
|
|
if (newParagraph != NULL) {
|
|
context = (Context *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
|
|
if (context->paragraph != NULL) {
|
|
delete context->paragraph;
|
|
}
|
|
|
|
context->paragraph = newParagraph;
|
|
InitParagraph(hwnd, context);
|
|
PrettyTitle(hwnd, szTitleName);
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
|
|
}
|
|
}
|
|
|
|
//ReleaseDC(hwnd, hdc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
case IDM_FILE_EXIT:
|
|
case IDM_FILE_CLOSE:
|
|
SendMessage(hwnd, WM_CLOSE, 0, 0);
|
|
return 0;
|
|
|
|
case IDM_HELP_ABOUTLAYOUTSAMPLE:
|
|
MessageBox(hwnd, TEXT("Windows Layout Sample 0.1\n")
|
|
TEXT("Copyright (C) 1998-2005 By International Business Machines Corporation and others.\n")
|
|
TEXT("Author: Eric Mader"),
|
|
szAppName, MB_ICONINFORMATION | MB_OK);
|
|
return 0;
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
case WM_DESTROY:
|
|
{
|
|
context = (Context *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
|
|
if (context != NULL && context->paragraph != NULL) {
|
|
delete context->paragraph;
|
|
}
|
|
|
|
delete context;
|
|
|
|
if (--windowCount <= 0) {
|
|
delete font;
|
|
delete surface;
|
|
|
|
PostQuitMessage(0);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
default:
|
|
return DefWindowProc(hwnd, message, wParam, lParam);
|
|
}
|
|
|
|
return 0;
|
|
}
|