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