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