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