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