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