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