Home | History | Annotate | Download | only in layout
      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