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