| /* | |
| ******************************************************************************* | |
| * | |
| * © 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; | |
| } |