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