• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *******************************************************************************
3  *
4  *   © 2016 and later: Unicode, Inc. and others.
5  *   License & terms of use: http://www.unicode.org/copyright.html
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 <stdbool.h>
22 #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 
34 struct Context
35 {
36     le_int32 width;
37     le_int32 height;
38     pf_flow *paragraph;
39 };
40 
41 typedef struct Context Context;
42 
43 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
44 
45 #define APP_NAME "LayoutSample"
46 
47 TCHAR szAppName[] = TEXT(APP_NAME);
48 
PrettyTitle(HWND hwnd,char * fileName)49 void 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 
InitParagraph(HWND hwnd,Context * context)58 void 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);
74         SetScrollInfo(hwnd, SB_VERT, &si, true);
75     }
76 }
77 
WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)78 int 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 
WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)125 LRESULT 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;
223         SetScrollInfo(hwnd, SB_VERT, &si, true);
224         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);
318                     InvalidateRect(hwnd, NULL, true);
319 
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 }
371