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