blob: b1077102170b2526f2106832c31383e140e35e1e [file] [log] [blame]
jshin@chromium.org6f31ac32014-03-26 22:15:14 +00001/*
2 *******************************************************************************
3 *
Jungshik Shin87232d82017-05-13 21:10:13 -07004 * © 2016 and later: Unicode, Inc. and others.
Frank Tangf90543d2020-10-30 19:02:04 -07005 * License & terms of use: http://www.unicode.org/copyright.html
Jungshik Shin5feb9ad2016-10-21 12:52:48 -07006 *
7 *******************************************************************************
8 *******************************************************************************
9 *
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000010 * Copyright (C) 1999-2007, International Business Machines
11 * Corporation and others. All Rights Reserved.
12 *
13 *******************************************************************************
14 * file name: Layout.cpp
15 *
16 * created on: 08/03/2000
17 * created by: Eric R. Mader
18 */
19
20#include <windows.h>
Frank Tang1f164ee2022-11-08 12:31:27 -080021#include <stdbool.h>
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000022#include <stdio.h>
23
24#include "playout.h"
25#include "pflow.h"
26
27#include "gdiglue.h"
28#include "ucreader.h"
29
30#include "arraymem.h"
31
32#include "resource.h"
33
34struct Context
35{
36 le_int32 width;
37 le_int32 height;
38 pf_flow *paragraph;
39};
40
41typedef struct Context Context;
42
43LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
44
45#define APP_NAME "LayoutSample"
46
47TCHAR szAppName[] = TEXT(APP_NAME);
48
49void PrettyTitle(HWND hwnd, char *fileName)
50{
51 char title[MAX_PATH + 64];
52
53 sprintf(title, "%s - %s", APP_NAME, fileName);
54
55 SetWindowTextA(hwnd, title);
56}
57
58void InitParagraph(HWND hwnd, Context *context)
59{
60 SCROLLINFO si;
61
62 if (context->paragraph != NULL) {
63 // FIXME: does it matter what we put in the ScrollInfo
64 // if the window's been minimized?
65 if (context->width > 0 && context->height > 0) {
66 pf_breakLines(context->paragraph, context->width, context->height);
67 }
68
69 si.cbSize = sizeof si;
70 si.fMask = SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL;
71 si.nMin = 0;
72 si.nMax = pf_getLineCount(context->paragraph) - 1;
73 si.nPage = context->height / pf_getLineHeight(context->paragraph);
Frank Tang1f164ee2022-11-08 12:31:27 -080074 SetScrollInfo(hwnd, SB_VERT, &si, true);
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000075 }
76}
77
78int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
79{
80 HWND hwnd;
81 HACCEL hAccel;
82 MSG msg;
83 WNDCLASS wndclass;
84 LEErrorCode status = LE_NO_ERROR;
85
86 wndclass.style = CS_HREDRAW | CS_VREDRAW;
87 wndclass.lpfnWndProc = WndProc;
88 wndclass.cbClsExtra = 0;
89 wndclass.cbWndExtra = sizeof(LONG);
90 wndclass.hInstance = hInstance;
91 wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
92 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
93 wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
94 wndclass.lpszMenuName = szAppName;
95 wndclass.lpszClassName = szAppName;
96
97 if (!RegisterClass(&wndclass)) {
98 MessageBox(NULL, TEXT("This demo only runs on Windows 2000!"), szAppName, MB_ICONERROR);
99
100 return 0;
101 }
102
103 hAccel = LoadAccelerators(hInstance, szAppName);
104
105 hwnd = CreateWindow(szAppName, NULL,
106 WS_OVERLAPPEDWINDOW | WS_VSCROLL,
107 CW_USEDEFAULT, CW_USEDEFAULT,
108 600, 400,
109 NULL, NULL, hInstance, NULL);
110
111 ShowWindow(hwnd, iCmdShow);
112 UpdateWindow(hwnd);
113
114 while (GetMessage(&msg, NULL, 0, 0)) {
115 if (!TranslateAccelerator(hwnd, hAccel, &msg)) {
116 TranslateMessage(&msg);
117 DispatchMessage(&msg);
118 }
119 }
120
121 UnregisterClass(szAppName, hInstance);
122 return msg.wParam;
123}
124
125LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
126{
127 HDC hdc;
128 Context *context;
129 static le_int32 windowCount = 0;
130 static fm_fontMap *fontMap = NULL;
131 static rs_surface *surface = NULL;
132 static gs_guiSupport *guiSupport = NULL;
133 static le_font *font = NULL;
134
135 switch (message) {
136 case WM_CREATE:
137 {
138 LEErrorCode fontStatus = LE_NO_ERROR;
139
140 hdc = GetDC(hwnd);
141 guiSupport = gs_gdiGuiSupportOpen();
142 surface = rs_gdiRenderingSurfaceOpen(hdc);
143
144 fontMap = fm_gdiFontMapOpen(surface, "FontMap.GDI", 24, guiSupport, &fontStatus);
145 font = le_scriptCompositeFontOpen(fontMap);
146
147 if (LE_FAILURE(fontStatus)) {
148 ReleaseDC(hwnd, hdc);
149 return -1;
150 }
151
152 context = NEW_ARRAY(Context, 1);
153
154 context->width = 600;
155 context->height = 400;
156
157 context->paragraph = pf_factory("Sample.txt", font, guiSupport);
158 SetWindowLongPtr(hwnd, 0, (LONG_PTR) context);
159
160 windowCount += 1;
161 ReleaseDC(hwnd, hdc);
162
163 PrettyTitle(hwnd, "Sample.txt");
164 return 0;
165 }
166
167 case WM_SIZE:
168 {
169 context = (Context *) GetWindowLongPtr(hwnd, 0);
170 context->width = LOWORD(lParam);
171 context->height = HIWORD(lParam);
172
173 InitParagraph(hwnd, context);
174 return 0;
175 }
176
177 case WM_VSCROLL:
178 {
179 SCROLLINFO si;
180 le_int32 vertPos;
181
182 si.cbSize = sizeof si;
183 si.fMask = SIF_ALL;
184 GetScrollInfo(hwnd, SB_VERT, &si);
185
186 vertPos = si.nPos;
187
188 switch (LOWORD(wParam))
189 {
190 case SB_TOP:
191 si.nPos = si.nMin;
192 break;
193
194 case SB_BOTTOM:
195 si.nPos = si.nMax;
196 break;
197
198 case SB_LINEUP:
199 si.nPos -= 1;
200 break;
201
202 case SB_LINEDOWN:
203 si.nPos += 1;
204 break;
205
206 case SB_PAGEUP:
207 si.nPos -= si.nPage;
208 break;
209
210 case SB_PAGEDOWN:
211 si.nPos += si.nPage;
212 break;
213
214 case SB_THUMBTRACK:
215 si.nPos = si.nTrackPos;
216 break;
217
218 default:
219 break;
220 }
221
222 si.fMask = SIF_POS;
Frank Tang1f164ee2022-11-08 12:31:27 -0800223 SetScrollInfo(hwnd, SB_VERT, &si, true);
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000224 GetScrollInfo(hwnd, SB_VERT, &si);
225
226 context = (Context *) GetWindowLongPtr(hwnd, 0);
227
228 if (context->paragraph != NULL && si.nPos != vertPos) {
229 ScrollWindow(hwnd, 0, pf_getLineHeight(context->paragraph) * (vertPos - si.nPos), NULL, NULL);
230 UpdateWindow(hwnd);
231 }
232
233 return 0;
234 }
235
236 case WM_PAINT:
237 {
238 PAINTSTRUCT ps;
239 SCROLLINFO si;
240 le_int32 firstLine, lastLine;
241
242 hdc = BeginPaint(hwnd, &ps);
243 SetBkMode(hdc, TRANSPARENT);
244
245 si.cbSize = sizeof si;
246 si.fMask = SIF_ALL;
247 GetScrollInfo(hwnd, SB_VERT, &si);
248
249 firstLine = si.nPos;
250
251 context = (Context *) GetWindowLongPtr(hwnd, 0);
252
253 if (context->paragraph != NULL) {
254 rs_gdiRenderingSurfaceSetHDC(surface, hdc);
255
256 // NOTE: si.nPos + si.nPage may include a partial line at the bottom
257 // of the window. We need this because scrolling assumes that the
258 // partial line has been painted.
259 lastLine = min (si.nPos + (le_int32) si.nPage, pf_getLineCount(context->paragraph) - 1);
260
261 pf_draw(context->paragraph, surface, firstLine, lastLine);
262 }
263
264 EndPaint(hwnd, &ps);
265 return 0;
266 }
267
268 case WM_COMMAND:
269 switch (LOWORD(wParam)) {
270 case IDM_FILE_OPEN:
271 {
272 OPENFILENAMEA ofn;
273 char szFileName[MAX_PATH], szTitleName[MAX_PATH];
274 static char szFilter[] = "Text Files (.txt)\0*.txt\0"
275 "All Files (*.*)\0*.*\0\0";
276
277 ofn.lStructSize = sizeof (OPENFILENAMEA);
278 ofn.hwndOwner = hwnd;
279 ofn.hInstance = NULL;
280 ofn.lpstrFilter = szFilter;
281 ofn.lpstrCustomFilter = NULL;
282 ofn.nMaxCustFilter = 0;
283 ofn.nFilterIndex = 0;
284 ofn.lpstrFile = szFileName;
285 ofn.nMaxFile = MAX_PATH;
286 ofn.lpstrFileTitle = szTitleName;
287 ofn.nMaxFileTitle = MAX_PATH;
288 ofn.lpstrInitialDir = NULL;
289 ofn.lpstrTitle = NULL;
290 ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
291 ofn.nFileOffset = 0;
292 ofn.nFileExtension = 0;
293 ofn.lpstrDefExt = "txt";
294 ofn.lCustData = 0L;
295 ofn.lpfnHook = NULL;
296 ofn.lpTemplateName = NULL;
297
298 szFileName[0] = '\0';
299
300 if (GetOpenFileNameA(&ofn)) {
301 pf_flow *newParagraph;
302
303 hdc = GetDC(hwnd);
304 rs_gdiRenderingSurfaceSetHDC(surface, hdc);
305
306 newParagraph = pf_factory(szFileName, font, guiSupport);
307
308 if (newParagraph != NULL) {
309 context = (Context *) GetWindowLongPtr(hwnd, 0);
310
311 if (context->paragraph != NULL) {
312 pf_close(context->paragraph);
313 }
314
315 context->paragraph = newParagraph;
316 InitParagraph(hwnd, context);
317 PrettyTitle(hwnd, szTitleName);
Frank Tang1f164ee2022-11-08 12:31:27 -0800318 InvalidateRect(hwnd, NULL, true);
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000319
320 }
321 }
322
323 //ReleaseDC(hwnd, hdc);
324
325 return 0;
326 }
327
328 case IDM_FILE_EXIT:
329 case IDM_FILE_CLOSE:
330 SendMessage(hwnd, WM_CLOSE, 0, 0);
331 return 0;
332
333 case IDM_HELP_ABOUTLAYOUTSAMPLE:
334 MessageBox(hwnd, TEXT("Windows Layout Sample 0.1\n")
335 TEXT("Copyright (C) 1998-2005 By International Business Machines Corporation and others.\n")
336 TEXT("Author: Eric Mader"),
337 szAppName, MB_ICONINFORMATION | MB_OK);
338 return 0;
339
340 }
341 break;
342
343
344 case WM_DESTROY:
345 {
346 context = (Context *) GetWindowLongPtr(hwnd, 0);
347
348 if (context != NULL && context->paragraph != NULL) {
349 pf_close(context->paragraph);
350 }
351
352 DELETE_ARRAY(context);
353
354 if (--windowCount <= 0) {
355 le_fontClose(font);
356 rs_gdiRenderingSurfaceClose(surface);
357 gs_gdiGuiSupportClose(guiSupport);
358
359 PostQuitMessage(0);
360 }
361
362 return 0;
363 }
364
365 default:
366 return DefWindowProc(hwnd, message, wParam, lParam);
367 }
368
369 return 0;
370}