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 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 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 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 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