• 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#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