ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

winhelp.c
Go to the documentation of this file.
00001 /*
00002  * Help Viewer
00003  *
00004  * Copyright    1996 Ulrich Schmid <uschmid@mail.hh.provi.de>
00005  *              2002 Sylvain Petreolle <spetreolle@yahoo.fr>
00006  *              2002, 2008 Eric Pouech <eric.pouech@wanadoo.fr>
00007  *              2004 Ken Belleau <jamez@ivic.qc.ca>
00008  *              2008 Kirill K. Smirnov <lich@math.spbu.ru>
00009  *
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or (at your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00023  */
00024 
00025 #include <assert.h>
00026 #include <stdio.h>
00027 #include <string.h>
00028 #include <stdarg.h>
00029 #include <stdlib.h>
00030 
00031 #define NONAMELESSUNION
00032 #define NONAMELESSSTRUCT
00033 
00034 #include "windef.h"
00035 #include "winbase.h"
00036 #include "wingdi.h"
00037 #include "winuser.h"
00038 #include "commdlg.h"
00039 #include "winhelp.h"
00040 #include "winhelp_res.h"
00041 #include "shellapi.h"
00042 #include "richedit.h"
00043 #include "commctrl.h"
00044 
00045 #include "wine/debug.h"
00046 
00047 WINE_DEFAULT_DEBUG_CHANNEL(winhelp);
00048 
00049 WINHELP_GLOBALS Globals = {3, NULL, TRUE, NULL, NULL, NULL, NULL, NULL, {{{NULL,NULL}},0}, NULL};
00050 
00051 #define CTL_ID_BUTTON   0x700
00052 #define CTL_ID_TEXT     0x701
00053 
00054 
00055 /***********************************************************************
00056  *
00057  *           WINHELP_InitFonts
00058  */
00059 static void WINHELP_InitFonts(HWND hWnd)
00060 {
00061     WINHELP_WINDOW *win = (WINHELP_WINDOW*) GetWindowLongPtr(hWnd, 0);
00062     LOGFONT logfontlist[] = {
00063         {-10, 0, 0, 0, 400, 0, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 32, "Helv"},
00064         {-12, 0, 0, 0, 700, 0, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 32, "Helv"},
00065         {-12, 0, 0, 0, 700, 0, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 32, "Helv"},
00066         {-12, 0, 0, 0, 400, 0, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 32, "Helv"},
00067         {-12, 0, 0, 0, 700, 0, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 32, "Helv"},
00068         {-10, 0, 0, 0, 700, 0, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 32, "Helv"},
00069         { -8, 0, 0, 0, 400, 0, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 32, "Helv"}};
00070 #define FONTS_LEN (sizeof(logfontlist)/sizeof(*logfontlist))
00071 
00072     static HFONT fonts[FONTS_LEN];
00073     static BOOL init = 0;
00074 
00075     win->fonts_len = FONTS_LEN;
00076     win->fonts = fonts;
00077 
00078     if (!init)
00079     {
00080         UINT i;
00081 
00082         for (i = 0; i < FONTS_LEN; i++)
00083     {
00084             fonts[i] = CreateFontIndirect(&logfontlist[i]);
00085     }
00086 
00087         init = 1;
00088     }
00089 }
00090 
00091 static DWORD CALLBACK WINHELP_RtfStreamIn(DWORD_PTR cookie, BYTE* buff,
00092                                           LONG cb, LONG* pcb)
00093 {
00094     struct RtfData*     rd = (struct RtfData*)cookie;
00095 
00096     if (rd->where >= rd->ptr) return 1;
00097     if (rd->where + cb > rd->ptr)
00098         cb = rd->ptr - rd->where;
00099     memcpy(buff, rd->where, cb);
00100     rd->where += cb;
00101     *pcb = cb;
00102     return 0;
00103 }
00104 
00105 static void WINHELP_SetupText(HWND hTextWnd, WINHELP_WINDOW* win, ULONG relative)
00106 {
00107     /* At first clear area - needed by EM_POSFROMCHAR/EM_SETSCROLLPOS */
00108     SendMessage(hTextWnd, WM_SETTEXT, 0, (LPARAM)"");
00109     SendMessage(hTextWnd, WM_SETREDRAW, FALSE, 0);
00110     SendMessage(hTextWnd, EM_SETBKGNDCOLOR, 0, (LPARAM)win->info->sr_color);
00111     /* set word-wrap to window size (undocumented) */
00112     SendMessage(hTextWnd, EM_SETTARGETDEVICE, 0, 0);
00113     if (win->page)
00114     {
00115         struct RtfData  rd;
00116         EDITSTREAM      es;
00117         unsigned        cp = 0;
00118         POINTL          ptl;
00119         POINT           pt;
00120 
00121 
00122         if (HLPFILE_BrowsePage(win->page, &rd, win->font_scale, relative))
00123         {
00124             rd.where = rd.data;
00125             es.dwCookie = (DWORD_PTR)&rd;
00126             es.dwError = 0;
00127             es.pfnCallback = WINHELP_RtfStreamIn;
00128 
00129             SendMessageW(hTextWnd, EM_STREAMIN, SF_RTF, (LPARAM)&es);
00130             cp = rd.char_pos_rel;
00131         }
00132         /* FIXME: else leaking potentially the rd.first_link chain */
00133         HeapFree(GetProcessHeap(), 0, rd.data);
00134         SendMessage(hTextWnd, EM_POSFROMCHAR, (WPARAM)&ptl, cp ? cp - 1 : 0);
00135         pt.x = 0; pt.y = ptl.y;
00136         SendMessage(hTextWnd, EM_SETSCROLLPOS, 0, (LPARAM)&pt);
00137     }
00138     SendMessage(hTextWnd, WM_SETREDRAW, TRUE, 0);
00139     RedrawWindow(hTextWnd, NULL, NULL, RDW_FRAME|RDW_INVALIDATE);
00140 }
00141 
00142 /***********************************************************************
00143  *
00144  *           WINHELP_GetOpenFileName
00145  */
00146 BOOL WINHELP_GetOpenFileName(LPSTR lpszFile, int len)
00147 {
00148     OPENFILENAME openfilename;
00149     CHAR szDir[MAX_PATH];
00150     CHAR szzFilter[2 * MAX_STRING_LEN + 100];
00151     LPSTR p = szzFilter;
00152 
00153     WINE_TRACE("()\n");
00154 
00155     LoadString(Globals.hInstance, STID_HELP_FILES_HLP, p, MAX_STRING_LEN);
00156     p += strlen(p) + 1;
00157     lstrcpy(p, "*.hlp");
00158     p += strlen(p) + 1;
00159     LoadString(Globals.hInstance, STID_ALL_FILES, p, MAX_STRING_LEN);
00160     p += strlen(p) + 1;
00161     lstrcpy(p, "*.*");
00162     p += strlen(p) + 1;
00163     *p = '\0';
00164 
00165     GetCurrentDirectory(sizeof(szDir), szDir);
00166 
00167     lpszFile[0]='\0';
00168 
00169     openfilename.lStructSize       = sizeof(OPENFILENAME);
00170     openfilename.hwndOwner         = (Globals.active_win ? Globals.active_win->hMainWnd : 0);
00171     openfilename.hInstance         = Globals.hInstance;
00172     openfilename.lpstrFilter       = szzFilter;
00173     openfilename.lpstrCustomFilter = 0;
00174     openfilename.nMaxCustFilter    = 0;
00175     openfilename.nFilterIndex      = 1;
00176     openfilename.lpstrFile         = lpszFile;
00177     openfilename.nMaxFile          = len;
00178     openfilename.lpstrFileTitle    = 0;
00179     openfilename.nMaxFileTitle     = 0;
00180     openfilename.lpstrInitialDir   = szDir;
00181     openfilename.lpstrTitle        = 0;
00182     openfilename.Flags             = OFN_ENABLESIZING;
00183     openfilename.nFileOffset       = 0;
00184     openfilename.nFileExtension    = 0;
00185     openfilename.lpstrDefExt       = 0;
00186     openfilename.lCustData         = 0;
00187     openfilename.lpfnHook          = 0;
00188     openfilename.lpTemplateName    = 0;
00189 
00190     return GetOpenFileName(&openfilename);
00191 }
00192 
00193 /***********************************************************************
00194  *
00195  *           WINHELP_MessageBoxIDS_s
00196  */
00197 static INT WINHELP_MessageBoxIDS_s(UINT ids_text, LPCSTR str, UINT ids_title, WORD type)
00198 {
00199     CHAR text[MAX_STRING_LEN];
00200     CHAR newtext[MAX_STRING_LEN + MAX_PATH];
00201 
00202     LoadString(Globals.hInstance, ids_text, text, sizeof(text));
00203     wsprintf(newtext, text, str);
00204 
00205     return MessageBox(0, newtext, MAKEINTRESOURCE(ids_title), type);
00206 }
00207 
00208 /***********************************************************************
00209  *
00210  *           WINHELP_LookupHelpFile
00211  */
00212 HLPFILE* WINHELP_LookupHelpFile(LPCSTR lpszFile)
00213 {
00214     HLPFILE*        hlpfile;
00215     char szFullName[MAX_PATH];
00216     char szAddPath[MAX_PATH];
00217     char *p;
00218 
00219     /*
00220      * NOTE: This is needed by popup windows only.
00221      * In other cases it's not needed but does not hurt though.
00222      */
00223     if (Globals.active_win && Globals.active_win->page && Globals.active_win->page->file)
00224     {
00225         strcpy(szAddPath, Globals.active_win->page->file->lpszPath);
00226         p = strrchr(szAddPath, '\\');
00227         if (p) *p = 0;
00228     }
00229 
00230     /*
00231      * FIXME: Should we swap conditions?
00232      */
00233     if (!SearchPath(NULL, lpszFile, ".hlp", MAX_PATH, szFullName, NULL) &&
00234         !SearchPath(szAddPath, lpszFile, ".hlp", MAX_PATH, szFullName, NULL))
00235     {
00236         if (WINHELP_MessageBoxIDS_s(STID_FILE_NOT_FOUND_s, lpszFile, STID_WHERROR,
00237                                     MB_YESNO|MB_ICONQUESTION) != IDYES)
00238             return NULL;
00239         if (!WINHELP_GetOpenFileName(szFullName, MAX_PATH))
00240             return NULL;
00241     }
00242     hlpfile = HLPFILE_ReadHlpFile(szFullName);
00243     if (!hlpfile)
00244         WINHELP_MessageBoxIDS_s(STID_HLPFILE_ERROR_s, lpszFile,
00245                                 STID_WHERROR, MB_OK|MB_ICONSTOP);
00246     return hlpfile;
00247 }
00248 
00249 /******************************************************************
00250  *      WINHELP_GetWindowInfo
00251  *
00252  *
00253  */
00254 HLPFILE_WINDOWINFO*     WINHELP_GetWindowInfo(HLPFILE* hlpfile, LPCSTR name)
00255 {
00256     static      HLPFILE_WINDOWINFO      mwi;
00257     unsigned int     i;
00258 
00259     if (!name || !name[0])
00260         name = Globals.active_win->info->name;
00261 
00262     if (hlpfile)
00263         for (i = 0; i < hlpfile->numWindows; i++)
00264             if (!lstrcmpi(hlpfile->windows[i].name, name))
00265                 return &hlpfile->windows[i];
00266 
00267     if (strcmp(name, "main") != 0)
00268     {
00269         WINE_FIXME("Couldn't find window info for %s\n", name);
00270         assert(0);
00271         return NULL;
00272     }
00273     if (!mwi.name[0])
00274     {
00275         strcpy(mwi.type, "primary");
00276         strcpy(mwi.name, "main");
00277         if (hlpfile && hlpfile->lpszTitle[0])
00278         {
00279             char        tmp[128];
00280             LoadString(Globals.hInstance, STID_WINE_HELP, tmp, sizeof(tmp));
00281             snprintf(mwi.caption, sizeof(mwi.caption), "%s %s - %s",
00282                      hlpfile->lpszTitle, tmp, hlpfile->lpszPath);
00283         }
00284         else
00285             LoadString(Globals.hInstance, STID_WINE_HELP, mwi.caption, sizeof(mwi.caption));
00286         mwi.origin.x = mwi.origin.y = mwi.size.cx = mwi.size.cy = CW_USEDEFAULT;
00287         mwi.style = SW_SHOW;
00288         mwi.win_style = WS_OVERLAPPEDWINDOW;
00289         mwi.sr_color = mwi.nsr_color = 0xFFFFFF;
00290     }
00291     return &mwi;
00292 }
00293 
00294 /******************************************************************
00295  *      HLPFILE_GetPopupWindowInfo
00296  *
00297  *
00298  */
00299 static HLPFILE_WINDOWINFO*     WINHELP_GetPopupWindowInfo(HLPFILE* hlpfile,
00300                                                           WINHELP_WINDOW* parent, LPARAM mouse)
00301 {
00302     static      HLPFILE_WINDOWINFO      wi;
00303 
00304     RECT parent_rect;
00305     
00306     wi.type[0] = wi.name[0] = wi.caption[0] = '\0';
00307 
00308     /* Calculate horizontal size and position of a popup window */
00309     GetWindowRect(parent->hMainWnd, &parent_rect);
00310     wi.size.cx = (parent_rect.right  - parent_rect.left) / 2;
00311     wi.size.cy = 10; /* need a non null value, so that border are taken into account while computing */
00312 
00313     wi.origin.x = (short)LOWORD(mouse);
00314     wi.origin.y = (short)HIWORD(mouse);
00315     ClientToScreen(parent->hMainWnd, &wi.origin);
00316     wi.origin.x -= wi.size.cx / 2;
00317     wi.origin.x  = min(wi.origin.x, GetSystemMetrics(SM_CXSCREEN) - wi.size.cx);
00318     wi.origin.x  = max(wi.origin.x, 0);
00319 
00320     wi.style = SW_SHOW;
00321     wi.win_style = WS_POPUP | WS_BORDER;
00322     if (parent->page->file->has_popup_color)
00323         wi.sr_color = parent->page->file->popup_color;
00324     else
00325         wi.sr_color = parent->info->sr_color;
00326     wi.nsr_color = 0xFFFFFF;
00327 
00328     return &wi;
00329 }
00330 
00331 typedef struct
00332 {
00333     WORD size;
00334     WORD command;
00335     LONG data;
00336     LONG reserved;
00337     WORD ofsFilename;
00338     WORD ofsData;
00339 } WINHELP,*LPWINHELP;
00340 
00341 static BOOL WINHELP_HasWorkingWindow(void)
00342 {
00343     if (!Globals.active_win) return FALSE;
00344     if (Globals.active_win->next || Globals.win_list != Globals.active_win) return TRUE;
00345     return Globals.active_win->page != NULL && Globals.active_win->page->file != NULL;
00346 }
00347 
00348 /******************************************************************
00349  *      WINHELP_HandleCommand
00350  *
00351  *
00352  */
00353 static LRESULT  WINHELP_HandleCommand(HWND hSrcWnd, LPARAM lParam)
00354 {
00355     COPYDATASTRUCT*     cds = (COPYDATASTRUCT*)lParam;
00356     WINHELP*            wh;
00357 
00358     if (cds->dwData != 0xA1DE505)
00359     {
00360         WINE_FIXME("Wrong magic number (%08lx)\n", cds->dwData);
00361         return 0;
00362     }
00363 
00364     wh = cds->lpData;
00365 
00366     if (wh)
00367     {
00368         char*   ptr = (wh->ofsFilename) ? (LPSTR)wh + wh->ofsFilename : NULL;
00369 
00370         WINE_TRACE("Got[%u]: cmd=%u data=%08x fn=%s\n",
00371                    wh->size, wh->command, wh->data, ptr);
00372         switch (wh->command)
00373         {
00374         case HELP_CONTEXT:
00375             if (ptr)
00376             {
00377                 MACRO_JumpContext(ptr, "main", wh->data);
00378             }
00379             if (!WINHELP_HasWorkingWindow()) MACRO_Exit();
00380             break;
00381         case HELP_QUIT:
00382             MACRO_Exit();
00383             break;
00384         case HELP_CONTENTS:
00385             if (ptr)
00386             {
00387                 MACRO_JumpContents(ptr, "main");
00388             }
00389             if (!WINHELP_HasWorkingWindow()) MACRO_Exit();
00390             break;
00391         case HELP_HELPONHELP:
00392             MACRO_HelpOn();
00393             if (!WINHELP_HasWorkingWindow()) MACRO_Exit();
00394             break;
00395         /* case HELP_SETINDEX: */
00396         case HELP_SETCONTENTS:
00397             if (ptr)
00398             {
00399                 MACRO_SetContents(ptr, wh->data);
00400             }
00401             break;
00402         case HELP_CONTEXTPOPUP:
00403             if (ptr)
00404             {
00405                 MACRO_PopupContext(ptr, wh->data);
00406             }
00407             break;
00408         /* case HELP_FORCEFILE:*/
00409         /* case HELP_CONTEXTMENU: */
00410         case HELP_FINDER:
00411             /* in fact, should be the topic dialog box */
00412             WINE_FIXME("HELP_FINDER: stub\n");
00413             if (ptr)
00414             {
00415                 MACRO_JumpHash(ptr, "main", 0);
00416             }
00417             break;
00418         /* case HELP_WM_HELP: */
00419         /* case HELP_SETPOPUP_POS: */
00420         /* case HELP_KEY: */
00421         /* case HELP_COMMAND: */
00422         /* case HELP_PARTIALKEY: */
00423         /* case HELP_MULTIKEY: */
00424         /* case HELP_SETWINPOS: */
00425         default:
00426             WINE_FIXME("Unhandled command (%x) for remote winhelp control\n", wh->command);
00427             break;
00428         }
00429     }
00430     /* Always return success for now */
00431     return 1;
00432 }
00433 
00434 void            WINHELP_LayoutMainWindow(WINHELP_WINDOW* win)
00435 {
00436     RECT        rect, button_box_rect;
00437     INT         text_top = 0;
00438     HWND        hButtonBoxWnd = GetDlgItem(win->hMainWnd, CTL_ID_BUTTON);
00439     HWND        hTextWnd = GetDlgItem(win->hMainWnd, CTL_ID_TEXT);
00440 
00441     GetClientRect(win->hMainWnd, &rect);
00442 
00443     /* Update button box and text Window */
00444     SetWindowPos(hButtonBoxWnd, HWND_TOP,
00445                  rect.left, rect.top,
00446                  rect.right - rect.left,
00447                  rect.bottom - rect.top, 0);
00448 
00449     if (GetWindowRect(hButtonBoxWnd, &button_box_rect))
00450         text_top = rect.top + button_box_rect.bottom - button_box_rect.top;
00451 
00452     SetWindowPos(hTextWnd, HWND_TOP,
00453                  rect.left, text_top,
00454                  rect.right - rect.left,
00455                  rect.bottom - text_top, 0);
00456 
00457 }
00458 
00459 /******************************************************************
00460  *      WINHELP_DeleteButtons
00461  *
00462  */
00463 static void WINHELP_DeleteButtons(WINHELP_WINDOW* win)
00464 {
00465     WINHELP_BUTTON*     b;
00466     WINHELP_BUTTON*     bp;
00467 
00468     for (b = win->first_button; b; b = bp)
00469     {
00470         DestroyWindow(b->hWnd);
00471         bp = b->next;
00472         HeapFree(GetProcessHeap(), 0, b);
00473     }
00474     win->first_button = NULL;
00475 }
00476 
00477 /******************************************************************
00478  *      WINHELP_DeleteBackSet
00479  *
00480  */
00481 void WINHELP_DeleteBackSet(WINHELP_WINDOW* win)
00482 {
00483     unsigned int i;
00484 
00485     for (i = 0; i < win->back.index; i++)
00486     {
00487         HLPFILE_FreeHlpFile(win->back.set[i].page->file);
00488         win->back.set[i].page = NULL;
00489     }
00490     win->back.index = 0;
00491 }
00492 
00493 /******************************************************************
00494  *             WINHELP_DeletePageLinks
00495  *
00496  */
00497 static void WINHELP_DeletePageLinks(HLPFILE_PAGE* page)
00498 {
00499     HLPFILE_LINK*       curr;
00500     HLPFILE_LINK*       next;
00501 
00502     for (curr = page->first_link; curr; curr = next)
00503     {
00504         next = curr->next;
00505         HeapFree(GetProcessHeap(), 0, curr);
00506     }
00507 }
00508 
00509 /***********************************************************************
00510  *
00511  *           WINHELP_GrabWindow
00512  */
00513 WINHELP_WINDOW* WINHELP_GrabWindow(WINHELP_WINDOW* win)
00514 {
00515     WINE_TRACE("Grab %p#%d++\n", win, win->ref_count);
00516     win->ref_count++;
00517     return win;
00518 }
00519 
00520 /***********************************************************************
00521  *
00522  *           WINHELP_RelaseWindow
00523  */
00524 BOOL WINHELP_ReleaseWindow(WINHELP_WINDOW* win)
00525 {
00526     WINE_TRACE("Release %p#%d--\n", win, win->ref_count);
00527 
00528     if (!--win->ref_count)
00529     {
00530         DestroyWindow(win->hMainWnd);
00531         return FALSE;
00532     }
00533     return TRUE;
00534 }
00535 
00536 /***********************************************************************
00537  *
00538  *           WINHELP_DeleteWindow
00539  */
00540 static void WINHELP_DeleteWindow(WINHELP_WINDOW* win)
00541 {
00542     WINHELP_WINDOW**    w;
00543     BOOL bExit;
00544     HWND hTextWnd;
00545 
00546     for (w = &Globals.win_list; *w; w = &(*w)->next)
00547     {
00548         if (*w == win)
00549         {
00550             *w = win->next;
00551             break;
00552         }
00553     }
00554     bExit = (Globals.wVersion >= 4 && !lstrcmpi(win->info->name, "main"));
00555 
00556     if (Globals.active_win == win)
00557     {
00558         Globals.active_win = Globals.win_list;
00559         if (Globals.win_list)
00560             SetActiveWindow(Globals.win_list->hMainWnd);
00561     }
00562 
00563     if (win == Globals.active_popup)
00564         Globals.active_popup = NULL;
00565 
00566     hTextWnd = GetDlgItem(win->hMainWnd, CTL_ID_TEXT);
00567     SetWindowLongPtr(hTextWnd, GWLP_WNDPROC,
00568                      (LONG_PTR)win->origRicheditWndProc);
00569 
00570     WINHELP_DeleteButtons(win);
00571 
00572     if (win->page) WINHELP_DeletePageLinks(win->page);
00573     if (win->hHistoryWnd) DestroyWindow(win->hHistoryWnd);
00574 
00575     DeleteObject(win->hBrush);
00576 
00577     WINHELP_DeleteBackSet(win);
00578 
00579     if (win->page) HLPFILE_FreeHlpFile(win->page->file);
00580     HeapFree(GetProcessHeap(), 0, win);
00581 
00582     if (bExit) MACRO_Exit();
00583     if (!Globals.win_list)
00584         PostQuitMessage(0);
00585 }
00586 
00587 static char* WINHELP_GetCaption(WINHELP_WNDPAGE* wpage)
00588 {
00589     if (wpage->wininfo->caption[0]) return wpage->wininfo->caption;
00590     return wpage->page->file->lpszTitle;
00591 }
00592 
00593 static void WINHELP_RememberPage(WINHELP_WINDOW* win, WINHELP_WNDPAGE* wpage)
00594 {
00595     unsigned        num;
00596 
00597     if (!Globals.history.index || Globals.history.set[0].page != wpage->page)
00598     {
00599         num = sizeof(Globals.history.set) / sizeof(Globals.history.set[0]);
00600         /* we're full, remove latest entry */
00601         if (Globals.history.index == num)
00602         {
00603             HLPFILE_FreeHlpFile(Globals.history.set[num - 1].page->file);
00604             Globals.history.index--;
00605         }
00606         memmove(&Globals.history.set[1], &Globals.history.set[0],
00607                 Globals.history.index * sizeof(Globals.history.set[0]));
00608         Globals.history.set[0] = *wpage;
00609         Globals.history.index++;
00610         wpage->page->file->wRefCount++;
00611     }
00612     if (win->hHistoryWnd) InvalidateRect(win->hHistoryWnd, NULL, TRUE);
00613 
00614     num = sizeof(win->back.set) / sizeof(win->back.set[0]);
00615     if (win->back.index == num)
00616     {
00617         /* we're full, remove latest entry */
00618         HLPFILE_FreeHlpFile(win->back.set[0].page->file);
00619         memmove(&win->back.set[0], &win->back.set[1],
00620                 (num - 1) * sizeof(win->back.set[0]));
00621         win->back.index--;
00622     }
00623     win->back.set[win->back.index++] = *wpage;
00624     wpage->page->file->wRefCount++;
00625 }
00626 
00627 /***********************************************************************
00628  *
00629  *           WINHELP_FindLink
00630  */
00631 static HLPFILE_LINK* WINHELP_FindLink(WINHELP_WINDOW* win, LPARAM pos)
00632 {
00633     HLPFILE_LINK*           link;
00634     POINTL                  mouse_ptl, char_ptl, char_next_ptl;
00635     DWORD                   cp;
00636 
00637     if (!win->page) return NULL;
00638 
00639     mouse_ptl.x = (short)LOWORD(pos);
00640     mouse_ptl.y = (short)HIWORD(pos);
00641     cp = SendMessageW(GetDlgItem(win->hMainWnd, CTL_ID_TEXT), EM_CHARFROMPOS,
00642                       0, (LPARAM)&mouse_ptl);
00643 
00644     for (link = win->page->first_link; link; link = link->next)
00645     {
00646         if (link->cpMin <= cp && cp <= link->cpMax)
00647         {
00648             /* check whether we're at end of line */
00649             SendMessageW(GetDlgItem(win->hMainWnd, CTL_ID_TEXT), EM_POSFROMCHAR,
00650                          (LPARAM)&char_ptl, cp);
00651             SendMessageW(GetDlgItem(win->hMainWnd, CTL_ID_TEXT), EM_POSFROMCHAR,
00652                          (LPARAM)&char_next_ptl, cp + 1);
00653             if (link->bHotSpot)
00654             {
00655                 HLPFILE_HOTSPOTLINK*    hslink = (HLPFILE_HOTSPOTLINK*)link;
00656                 if ((mouse_ptl.x < char_ptl.x + hslink->x) ||
00657                     (mouse_ptl.x >= char_ptl.x + hslink->x + hslink->width) ||
00658                     (mouse_ptl.y < char_ptl.y + hslink->y) ||
00659                     (mouse_ptl.y >= char_ptl.y + hslink->y + hslink->height))
00660                     continue;
00661                 break;
00662             }
00663             if (char_next_ptl.y != char_ptl.y || mouse_ptl.x >= char_next_ptl.x)
00664                 link = NULL;
00665             break;
00666         }
00667     }
00668     return link;
00669 }
00670 
00671 static LRESULT CALLBACK WINHELP_RicheditWndProc(HWND hWnd, UINT msg,
00672                                                 WPARAM wParam, LPARAM lParam)
00673 {
00674     WINHELP_WINDOW *win = (WINHELP_WINDOW*) GetWindowLongPtr(GetParent(hWnd), 0);
00675     DWORD messagePos;
00676     POINT pt;
00677     switch(msg)
00678     {
00679         case WM_SETCURSOR:
00680             messagePos = GetMessagePos();
00681             pt.x = (short)LOWORD(messagePos);
00682             pt.y = (short)HIWORD(messagePos);
00683             ScreenToClient(hWnd, &pt);
00684             if (win->page && WINHELP_FindLink(win, MAKELPARAM(pt.x, pt.y)))
00685             {
00686                 SetCursor(win->hHandCur);
00687                 return 0;
00688             }
00689             /* fall through */
00690         default:
00691             return CallWindowProcA(win->origRicheditWndProc, hWnd, msg, wParam, lParam);
00692     }
00693 }
00694 
00695 /***********************************************************************
00696  *
00697  *           WINHELP_CreateHelpWindow
00698  */
00699 BOOL WINHELP_CreateHelpWindow(WINHELP_WNDPAGE* wpage, int nCmdShow, BOOL remember)
00700 {
00701     WINHELP_WINDOW*     win = NULL;
00702     BOOL                bPrimary, bPopup, bReUsed = FALSE;
00703     HICON               hIcon;
00704     HWND                hTextWnd = NULL;
00705 
00706     bPrimary = !lstrcmpi(wpage->wininfo->name, "main");
00707     bPopup = !bPrimary && (wpage->wininfo->win_style & WS_POPUP);
00708 
00709     if (!bPopup)
00710     {
00711         for (win = Globals.win_list; win; win = win->next)
00712         {
00713             if (!lstrcmpi(win->info->name, wpage->wininfo->name))
00714             {
00715                 if (win->page == wpage->page && win->info == wpage->wininfo)
00716                 {
00717                     /* see #22979, some hlp files have a macro (run at page opening), which
00718                      * jumps to the very same page
00719                      * Exit gracefully in that case
00720                      */
00721                     return TRUE;
00722                 }
00723                 WINHELP_DeleteButtons(win);
00724                 bReUsed = TRUE;
00725                 SetWindowText(win->hMainWnd, WINHELP_GetCaption(wpage));
00726                 if (win->info != wpage->wininfo)
00727                 {
00728                     POINT   pt = {0, 0};
00729                     SIZE    sz = {0, 0};
00730                     DWORD   flags = SWP_NOSIZE | SWP_NOMOVE;
00731 
00732                     if (wpage->wininfo->origin.x != CW_USEDEFAULT &&
00733                         wpage->wininfo->origin.y != CW_USEDEFAULT)
00734                     {
00735                         pt = wpage->wininfo->origin;
00736                         flags &= ~SWP_NOSIZE;
00737                     }
00738                     if (wpage->wininfo->size.cx != CW_USEDEFAULT &&
00739                         wpage->wininfo->size.cy != CW_USEDEFAULT)
00740                     {
00741                         sz = wpage->wininfo->size;
00742                         flags &= ~SWP_NOMOVE;
00743                     }
00744                     SetWindowPos(win->hMainWnd, HWND_TOP, pt.x, pt.y, sz.cx, sz.cy, flags);
00745                 }
00746 
00747                 if (wpage->page && win->page && wpage->page->file != win->page->file)
00748                     WINHELP_DeleteBackSet(win);
00749                 WINHELP_InitFonts(win->hMainWnd);
00750 
00751                 win->page = wpage->page;
00752                 win->info = wpage->wininfo;
00753                 hTextWnd = GetDlgItem(win->hMainWnd, CTL_ID_TEXT);
00754                 WINHELP_SetupText(hTextWnd, win, wpage->relative);
00755 
00756                 InvalidateRect(win->hMainWnd, NULL, TRUE);
00757                 if (win->hHistoryWnd) InvalidateRect(win->hHistoryWnd, NULL, TRUE);
00758 
00759                 break;
00760             }
00761         }
00762     }
00763 
00764     if (!win)
00765     {
00766         /* Initialize WINHELP_WINDOW struct */
00767         win = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINHELP_WINDOW));
00768         if (!win) return FALSE;
00769         win->next = Globals.win_list;
00770         Globals.win_list = win;
00771 
00772         win->hHandCur = LoadCursorW(0, (LPWSTR)IDC_HAND);
00773         win->back.index = 0;
00774         win->font_scale = 1;
00775         WINHELP_GrabWindow(win);
00776     }
00777     win->page = wpage->page;
00778     win->info = wpage->wininfo;
00779     WINHELP_GrabWindow(win);
00780 
00781     if (!bPopup && wpage->page && remember)
00782     {
00783         WINHELP_RememberPage(win, wpage);
00784     }
00785 
00786     if (bPopup)
00787         Globals.active_popup = win;
00788     else
00789         Globals.active_win = win;
00790 
00791     /* Initialize default pushbuttons */
00792     if (bPrimary && wpage->page)
00793     {
00794         CHAR    buffer[MAX_STRING_LEN];
00795 
00796         LoadString(Globals.hInstance, STID_CONTENTS, buffer, sizeof(buffer));
00797         MACRO_CreateButton("BTN_CONTENTS", buffer, "Contents()");
00798         LoadString(Globals.hInstance, STID_INDEX, buffer, sizeof(buffer));
00799         MACRO_CreateButton("BTN_INDEX", buffer, "Finder()");
00800         LoadString(Globals.hInstance, STID_BACK, buffer, sizeof(buffer));
00801         MACRO_CreateButton("BTN_BACK", buffer, "Back()");
00802         if (win->back.index <= 1) MACRO_DisableButton("BTN_BACK");
00803     }
00804 
00805     if (!bReUsed)
00806     {
00807         win->hMainWnd = CreateWindowEx((bPopup) ? WS_EX_TOOLWINDOW : 0, MAIN_WIN_CLASS_NAME,
00808                                        WINHELP_GetCaption(wpage),
00809                                        bPrimary ? WS_OVERLAPPEDWINDOW : wpage->wininfo->win_style,
00810                                        wpage->wininfo->origin.x, wpage->wininfo->origin.y,
00811                                        wpage->wininfo->size.cx, wpage->wininfo->size.cy,
00812                                        bPopup ? Globals.active_win->hMainWnd : NULL,
00813                                        bPrimary ? LoadMenu(Globals.hInstance, MAKEINTRESOURCE(MAIN_MENU)) : 0,
00814                                        Globals.hInstance, win);
00815         if (!bPopup)
00816             /* Create button box and text Window */
00817             CreateWindow(BUTTON_BOX_WIN_CLASS_NAME, "", WS_CHILD | WS_VISIBLE,
00818                          0, 0, 0, 0, win->hMainWnd, (HMENU)CTL_ID_BUTTON, Globals.hInstance, NULL);
00819 
00820         hTextWnd = CreateWindow(RICHEDIT_CLASS, NULL,
00821                                 ES_MULTILINE | ES_READONLY | WS_CHILD | WS_HSCROLL | WS_VSCROLL | WS_VISIBLE,
00822                                 0, 0, 0, 0, win->hMainWnd, (HMENU)CTL_ID_TEXT, Globals.hInstance, NULL);
00823         SendMessage(hTextWnd, EM_SETEVENTMASK, 0,
00824                     SendMessage(hTextWnd, EM_GETEVENTMASK, 0, 0) | ENM_MOUSEEVENTS);
00825         win->origRicheditWndProc = (WNDPROC)SetWindowLongPtr(hTextWnd, GWLP_WNDPROC,
00826                                                              (LONG_PTR)WINHELP_RicheditWndProc);
00827     }
00828 
00829     hIcon = (wpage->page) ? wpage->page->file->hIcon : NULL;
00830     if (!hIcon) hIcon = LoadImage(Globals.hInstance, MAKEINTRESOURCE(IDI_WINHELP), IMAGE_ICON,
00831                                   GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
00832     SendMessage(win->hMainWnd, WM_SETICON, ICON_SMALL, (DWORD_PTR)hIcon);
00833 
00834     /* Initialize file specific pushbuttons */
00835     if (!(wpage->wininfo->win_style & WS_POPUP) && wpage->page)
00836     {
00837         HLPFILE_MACRO  *macro;
00838         for (macro = wpage->page->file->first_macro; macro; macro = macro->next)
00839             MACRO_ExecuteMacro(win, macro->lpszMacro);
00840 
00841         for (macro = wpage->page->first_macro; macro; macro = macro->next)
00842             MACRO_ExecuteMacro(win, macro->lpszMacro);
00843     }
00844     /* See #17681, in some cases, the newly created window is closed by the macros it contains
00845      * (braindead), so deal with this case
00846      */
00847     for (win = Globals.win_list; win; win = win->next)
00848     {
00849         if (!lstrcmpi(win->info->name, wpage->wininfo->name)) break;
00850     }
00851     if (!win || !WINHELP_ReleaseWindow(win)) return TRUE;
00852 
00853     if (bPopup)
00854     {
00855         DWORD   mask = SendMessage(hTextWnd, EM_GETEVENTMASK, 0, 0);
00856 
00857         win->font_scale = Globals.active_win->font_scale;
00858         WINHELP_SetupText(hTextWnd, win, wpage->relative);
00859 
00860         /* we need the window to be shown for richedit to compute the size */
00861         ShowWindow(win->hMainWnd, nCmdShow);
00862         SendMessage(hTextWnd, EM_SETEVENTMASK, 0, mask | ENM_REQUESTRESIZE);
00863         SendMessage(hTextWnd, EM_REQUESTRESIZE, 0, 0);
00864         SendMessage(hTextWnd, EM_SETEVENTMASK, 0, mask);
00865     }
00866     else
00867     {
00868         WINHELP_SetupText(hTextWnd, win, wpage->relative);
00869         WINHELP_LayoutMainWindow(win);
00870         ShowWindow(win->hMainWnd, nCmdShow);
00871     }
00872 
00873     return TRUE;
00874 }
00875 
00876 /******************************************************************
00877  *             WINHELP_OpenHelpWindow
00878  * Main function to search for a page and display it in a window
00879  */
00880 BOOL WINHELP_OpenHelpWindow(HLPFILE_PAGE* (*lookup)(HLPFILE*, LONG, ULONG*),
00881                             HLPFILE* hlpfile, LONG val, HLPFILE_WINDOWINFO* wi,
00882                             int nCmdShow)
00883 {
00884     WINHELP_WNDPAGE     wpage;
00885 
00886     wpage.page = lookup(hlpfile, val, &wpage.relative);
00887     if (wpage.page) wpage.page->file->wRefCount++;
00888     wpage.wininfo = wi;
00889     return WINHELP_CreateHelpWindow(&wpage, nCmdShow, TRUE);
00890 }
00891 
00892 /******************************************************************
00893  *             WINHELP_HandleTextMouse
00894  *
00895  */
00896 static BOOL WINHELP_HandleTextMouse(WINHELP_WINDOW* win, UINT msg, LPARAM lParam)
00897 {
00898     HLPFILE*                hlpfile;
00899     HLPFILE_LINK*           link;
00900     BOOL                    ret = FALSE;
00901 
00902     switch (msg)
00903     {
00904     case WM_LBUTTONDOWN:
00905         if ((link = WINHELP_FindLink(win, lParam)))
00906         {
00907             HLPFILE_WINDOWINFO*     wi;
00908 
00909             switch (link->cookie)
00910             {
00911             case hlp_link_link:
00912                 if ((hlpfile = WINHELP_LookupHelpFile(link->string)))
00913                 {
00914                     if (link->window == -1)
00915                     {
00916                         wi = win->info;
00917                         if (wi->win_style & WS_POPUP) wi = Globals.active_win->info;
00918                     }
00919                     else if (link->window < hlpfile->numWindows)
00920                         wi = &hlpfile->windows[link->window];
00921                     else
00922                     {
00923                         WINE_WARN("link to window %d/%d\n", link->window, hlpfile->numWindows);
00924                         break;
00925                     }
00926                     WINHELP_OpenHelpWindow(HLPFILE_PageByHash, hlpfile, link->hash, wi, SW_NORMAL);
00927                 }
00928                 break;
00929             case hlp_link_popup:
00930                 if ((hlpfile = WINHELP_LookupHelpFile(link->string)))
00931                     WINHELP_OpenHelpWindow(HLPFILE_PageByHash, hlpfile, link->hash,
00932                                            WINHELP_GetPopupWindowInfo(hlpfile, win, lParam),
00933                                            SW_NORMAL);
00934                 break;
00935             case hlp_link_macro:
00936                 MACRO_ExecuteMacro(win, link->string);
00937                 break;
00938             default:
00939                 WINE_FIXME("Unknown link cookie %d\n", link->cookie);
00940             }
00941             ret = TRUE;
00942         }
00943         break;
00944     }
00945     return ret;
00946 }
00947 
00948 /***********************************************************************
00949  *
00950  *           WINHELP_CheckPopup
00951  */
00952 static BOOL WINHELP_CheckPopup(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* lret)
00953 {
00954     WINHELP_WINDOW*     popup;
00955 
00956     if (!Globals.active_popup) return FALSE;
00957 
00958     switch (msg)
00959     {
00960     case WM_NOTIFY:
00961         {
00962             MSGFILTER*  msgf = (MSGFILTER*)lParam;
00963             if (msgf->nmhdr.code == EN_MSGFILTER)
00964             {
00965                 if (!WINHELP_CheckPopup(hWnd, msgf->msg, msgf->wParam, msgf->lParam, NULL))
00966                     return FALSE;
00967                 if (lret) *lret = 1;
00968                 return TRUE;
00969             }
00970         }
00971         break;
00972     case WM_ACTIVATE:
00973         if (LOWORD(wParam) != WA_INACTIVE || (HWND)lParam == Globals.active_win->hMainWnd ||
00974             (HWND)lParam == Globals.active_popup->hMainWnd ||
00975             GetWindow((HWND)lParam, GW_OWNER) == Globals.active_win->hMainWnd)
00976             break;
00977         /* fall through */
00978     case WM_LBUTTONDOWN:
00979         if (msg == WM_LBUTTONDOWN)
00980             WINHELP_HandleTextMouse(Globals.active_popup, msg, lParam);
00981         /* fall through */
00982     case WM_MBUTTONDOWN:
00983     case WM_RBUTTONDOWN:
00984     case WM_NCLBUTTONDOWN:
00985     case WM_NCMBUTTONDOWN:
00986     case WM_NCRBUTTONDOWN:
00987         popup = Globals.active_popup;
00988         Globals.active_popup = NULL;
00989         WINHELP_ReleaseWindow(popup);
00990         return TRUE;
00991     }
00992     return FALSE;
00993 }
00994 
00995 /***********************************************************************
00996  *
00997  *           WINHELP_ButtonWndProc
00998  */
00999 static LRESULT CALLBACK WINHELP_ButtonWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
01000 {
01001     if (WINHELP_CheckPopup(hWnd, msg, wParam, lParam, NULL)) return 0;
01002 
01003     if (msg == WM_KEYDOWN)
01004     {
01005         switch (wParam)
01006         {
01007         case VK_UP:
01008         case VK_DOWN:
01009         case VK_PRIOR:
01010         case VK_NEXT:
01011         case VK_ESCAPE:
01012             return SendMessage(GetParent(hWnd), msg, wParam, lParam);
01013         }
01014     }
01015 
01016     return CallWindowProc(Globals.button_proc, hWnd, msg, wParam, lParam);
01017 }
01018 
01019 /***********************************************************************
01020  *
01021  *           WINHELP_ButtonBoxWndProc
01022  */
01023 static LRESULT CALLBACK WINHELP_ButtonBoxWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
01024 {
01025     WINDOWPOS      *winpos;
01026     WINHELP_WINDOW *win;
01027     WINHELP_BUTTON *button;
01028     SIZE button_size;
01029     INT  x, y;
01030 
01031     if (WINHELP_CheckPopup(hWnd, msg, wParam, lParam, NULL)) return 0L;
01032 
01033     switch (msg)
01034     {
01035     case WM_WINDOWPOSCHANGING:
01036         winpos = (WINDOWPOS*) lParam;
01037         win = (WINHELP_WINDOW*) GetWindowLongPtr(GetParent(hWnd), 0);
01038 
01039         /* Update buttons */
01040         button_size.cx = 0;
01041         button_size.cy = 0;
01042         for (button = win->first_button; button; button = button->next)
01043     {
01044             HDC  hDc;
01045             SIZE textsize;
01046             if (!button->hWnd)
01047             {
01048                 button->hWnd = CreateWindow(STRING_BUTTON, button->lpszName,
01049                                             WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
01050                                             0, 0, 0, 0,
01051                                             hWnd, (HMENU) button->wParam,
01052                                             Globals.hInstance, 0);
01053                 if (button->hWnd)
01054                 {
01055                     if (Globals.button_proc == NULL)
01056                     {
01057                         NONCLIENTMETRICSW ncm;
01058                         Globals.button_proc = (WNDPROC) GetWindowLongPtr(button->hWnd, GWLP_WNDPROC);
01059 
01060                         ncm.cbSize = sizeof(NONCLIENTMETRICSW);
01061                         SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
01062                                               sizeof(NONCLIENTMETRICSW), &ncm, 0);
01063                         Globals.hButtonFont = CreateFontIndirectW(&ncm.lfMenuFont);
01064                     }
01065                     SetWindowLongPtr(button->hWnd, GWLP_WNDPROC, (LONG_PTR) WINHELP_ButtonWndProc);
01066                     if (Globals.hButtonFont)
01067                         SendMessage(button->hWnd, WM_SETFONT, (WPARAM)Globals.hButtonFont, TRUE);
01068                 }
01069             }
01070             hDc = GetDC(button->hWnd);
01071             GetTextExtentPoint(hDc, button->lpszName,
01072                                lstrlen(button->lpszName), &textsize);
01073             ReleaseDC(button->hWnd, hDc);
01074 
01075             button_size.cx = max(button_size.cx, textsize.cx + BUTTON_CX);
01076             button_size.cy = max(button_size.cy, textsize.cy + BUTTON_CY);
01077     }
01078 
01079         x = 0;
01080         y = 0;
01081         for (button = win->first_button; button; button = button->next)
01082     {
01083             SetWindowPos(button->hWnd, HWND_TOP, x, y, button_size.cx, button_size.cy, 0);
01084 
01085             if (x + 2 * button_size.cx <= winpos->cx)
01086                 x += button_size.cx;
01087             else
01088                 x = 0, y += button_size.cy;
01089     }
01090         winpos->cy = y + (x ? button_size.cy : 0);
01091         break;
01092 
01093     case WM_COMMAND:
01094         SendMessage(GetParent(hWnd), msg, wParam, lParam);
01095         break;
01096 
01097     case WM_KEYDOWN:
01098         switch (wParam)
01099         {
01100         case VK_UP:
01101         case VK_DOWN:
01102         case VK_PRIOR:
01103         case VK_NEXT:
01104         case VK_ESCAPE:
01105             return SendMessage(GetParent(hWnd), msg, wParam, lParam);
01106         }
01107         break;
01108     }
01109 
01110     return DefWindowProc(hWnd, msg, wParam, lParam);
01111 }
01112 
01113 /******************************************************************
01114  *      WINHELP_HistoryWndProc
01115  *
01116  *
01117  */
01118 static LRESULT CALLBACK WINHELP_HistoryWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
01119 {
01120     WINHELP_WINDOW*     win;
01121     PAINTSTRUCT         ps;
01122     HDC                 hDc;
01123     TEXTMETRIC          tm;
01124     unsigned int        i;
01125     RECT                r;
01126 
01127     switch (msg)
01128     {
01129     case WM_NCCREATE:
01130         win = (WINHELP_WINDOW*)((LPCREATESTRUCT)lParam)->lpCreateParams;
01131         SetWindowLongPtr(hWnd, 0, (ULONG_PTR)win);
01132         win->hHistoryWnd = hWnd;
01133         break;
01134     case WM_CREATE:
01135         win = (WINHELP_WINDOW*) GetWindowLongPtr(hWnd, 0);
01136         hDc = GetDC(hWnd);
01137         GetTextMetrics(hDc, &tm);
01138         GetWindowRect(hWnd, &r);
01139 
01140         r.right = r.left + 30 * tm.tmAveCharWidth;
01141         r.bottom = r.top + (sizeof(Globals.history.set) / sizeof(Globals.history.set[0])) * tm.tmHeight;
01142         AdjustWindowRect(&r, GetWindowLong(hWnd, GWL_STYLE), FALSE);
01143         if (r.left < 0) {r.right -= r.left; r.left = 0;}
01144         if (r.top < 0) {r.bottom -= r.top; r.top = 0;}
01145 
01146         MoveWindow(hWnd, r.left, r.top, r.right, r.bottom, TRUE);
01147         ReleaseDC(hWnd, hDc);
01148         break;
01149     case WM_LBUTTONDOWN:
01150         win = (WINHELP_WINDOW*) GetWindowLongPtr(hWnd, 0);
01151         hDc = GetDC(hWnd);
01152         GetTextMetrics(hDc, &tm);
01153         i = HIWORD(lParam) / tm.tmHeight;
01154         if (i < Globals.history.index)
01155             WINHELP_CreateHelpWindow(&Globals.history.set[i], SW_SHOW, TRUE);
01156         ReleaseDC(hWnd, hDc);
01157         break;
01158     case WM_PAINT:
01159         hDc = BeginPaint(hWnd, &ps);
01160         win = (WINHELP_WINDOW*) GetWindowLongPtr(hWnd, 0);
01161         GetTextMetrics(hDc, &tm);
01162 
01163         for (i = 0; i < Globals.history.index; i++)
01164         {
01165             if (Globals.history.set[i].page->file == Globals.active_win->page->file)
01166             {
01167                 TextOut(hDc, 0, i * tm.tmHeight,
01168                         Globals.history.set[i].page->lpszTitle,
01169                         strlen(Globals.history.set[i].page->lpszTitle));
01170             }
01171             else
01172             {
01173                 char        buffer[1024];
01174                 const char* ptr1;
01175                 const char* ptr2;
01176                 unsigned    len;
01177 
01178                 ptr1 = strrchr(Globals.history.set[i].page->file->lpszPath, '\\');
01179                 if (!ptr1) ptr1 = Globals.history.set[i].page->file->lpszPath;
01180                 else ptr1++;
01181                 ptr2 = strrchr(ptr1, '.');
01182                 len = ptr2 ? ptr2 - ptr1 : strlen(ptr1);
01183                 if (len > sizeof(buffer)) len = sizeof(buffer);
01184                 memcpy(buffer, ptr1, len);
01185                 if (len < sizeof(buffer)) buffer[len++] = ':';
01186                 strncpy(&buffer[len], Globals.history.set[i].page->lpszTitle, sizeof(buffer) - len);
01187                 buffer[sizeof(buffer) - 1] = '\0';
01188                 TextOut(hDc, 0, i * tm.tmHeight, buffer, strlen(buffer));
01189             }
01190         }
01191         EndPaint(hWnd, &ps);
01192         break;
01193     case WM_DESTROY:
01194         win = (WINHELP_WINDOW*) GetWindowLongPtr(hWnd, 0);
01195         if (hWnd == win->hHistoryWnd)
01196             win->hHistoryWnd = 0;
01197         break;
01198     }
01199     return DefWindowProc(hWnd, msg, wParam, lParam);
01200 }
01201 
01202 /**************************************************************************
01203  * cb_KWBTree
01204  *
01205  * HLPFILE_BPTreeCallback enumeration function for '|KWBTREE' internal file.
01206  *
01207  */
01208 static void cb_KWBTree(void *p, void **next, void *cookie)
01209 {
01210     HWND hListWnd = cookie;
01211     int count;
01212 
01213     WINE_TRACE("Adding '%s' to search list\n", (char *)p);
01214     SendMessage(hListWnd, LB_INSERTSTRING, -1, (LPARAM)p);
01215     count = SendMessage(hListWnd, LB_GETCOUNT, 0, 0);
01216     SendMessage(hListWnd, LB_SETITEMDATA, count-1, (LPARAM)p);
01217     *next = (char*)p + strlen((char*)p) + 7;
01218 }
01219 
01220 struct index_data
01221 {
01222     HLPFILE*    hlpfile;
01223     BOOL        jump;
01224     ULONG       offset;
01225 };
01226 
01227 /**************************************************************************
01228  * WINHELP_IndexDlgProc
01229  *
01230  */
01231 static INT_PTR CALLBACK WINHELP_IndexDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
01232 {
01233     static struct index_data* id;
01234     int sel;
01235 
01236     switch (msg)
01237     {
01238     case WM_INITDIALOG:
01239         id = (struct index_data*)((PROPSHEETPAGE*)lParam)->lParam;
01240         HLPFILE_BPTreeEnum(id->hlpfile->kwbtree, cb_KWBTree,
01241                            GetDlgItem(hWnd, IDC_INDEXLIST));
01242         id->jump = FALSE;
01243         id->offset = 1;
01244         return TRUE;
01245     case WM_COMMAND:
01246         switch (HIWORD(wParam))
01247         {
01248         case LBN_DBLCLK:
01249             if (LOWORD(wParam) == IDC_INDEXLIST)
01250                 SendMessage(GetParent(hWnd), PSM_PRESSBUTTON, PSBTN_OK, 0);
01251             break;
01252         }
01253         break;
01254     case WM_NOTIFY:
01255     switch (((NMHDR*)lParam)->code)
01256     {
01257     case PSN_APPLY:
01258             sel = SendDlgItemMessage(hWnd, IDC_INDEXLIST, LB_GETCURSEL, 0, 0);
01259             if (sel != LB_ERR)
01260             {
01261                 BYTE *p;
01262                 int count;
01263 
01264                 p = (BYTE*)SendDlgItemMessage(hWnd, IDC_INDEXLIST,
01265                                               LB_GETITEMDATA, sel, 0);
01266                 count = *(short*)((char *)p + strlen((char *)p) + 1);
01267                 if (count > 1)
01268                 {
01269                     MessageBox(hWnd, "count > 1 not supported yet", "Error", MB_OK | MB_ICONSTOP);
01270                     SetWindowLongPtr(hWnd, DWLP_MSGRESULT, PSNRET_INVALID);
01271                     return TRUE;
01272                 }
01273                 id->offset = *(ULONG*)((char *)p + strlen((char *)p) + 3);
01274                 id->offset = *(long*)(id->hlpfile->kwdata + id->offset + 9);
01275                 if (id->offset == 0xFFFFFFFF)
01276                 {
01277                     MessageBox(hWnd, "macro keywords not supported yet", "Error", MB_OK | MB_ICONSTOP);
01278                     SetWindowLongPtr(hWnd, DWLP_MSGRESULT, PSNRET_INVALID);
01279                     return TRUE;
01280                 }
01281                 id->jump = TRUE;
01282                 SetWindowLongPtr(hWnd, DWLP_MSGRESULT, PSNRET_NOERROR);
01283             }
01284             return TRUE;
01285         default:
01286             return FALSE;
01287         }
01288         break;
01289     default:
01290         break;
01291     }
01292     return FALSE;
01293 }
01294 
01295 /**************************************************************************
01296  * WINHELP_SearchDlgProc
01297  *
01298  */
01299 static INT_PTR CALLBACK WINHELP_SearchDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
01300 {
01301     switch (msg)
01302     {
01303     case WM_INITDIALOG:
01304         return TRUE;
01305     case WM_NOTIFY:
01306     switch (((NMHDR*)lParam)->code)
01307     {
01308     case PSN_APPLY:
01309             SetWindowLongPtr(hWnd, DWLP_MSGRESULT, PSNRET_NOERROR);
01310             return TRUE;
01311         default:
01312             return FALSE;
01313         }
01314         break;
01315     default:
01316         break;
01317     }
01318     return FALSE;
01319 }
01320 
01321 /***********************************************************************
01322  *
01323  *           WINHELP_MainWndProc
01324  */
01325 static LRESULT CALLBACK WINHELP_MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
01326 {
01327     WINHELP_WINDOW *win;
01328     WINHELP_BUTTON *button;
01329     HWND hTextWnd;
01330     LRESULT ret;
01331 
01332     if (WINHELP_CheckPopup(hWnd, msg, wParam, lParam, &ret)) return ret;
01333 
01334     switch (msg)
01335     {
01336     case WM_NCCREATE:
01337         win = (WINHELP_WINDOW*) ((LPCREATESTRUCT) lParam)->lpCreateParams;
01338         SetWindowLongPtr(hWnd, 0, (ULONG_PTR) win);
01339         if (!win->page && Globals.isBook)
01340             PostMessage(hWnd, WM_COMMAND, MNID_FILE_OPEN, 0);
01341         win->hMainWnd = hWnd;
01342         break;
01343 
01344     case WM_WINDOWPOSCHANGED:
01345         WINHELP_LayoutMainWindow((WINHELP_WINDOW*) GetWindowLongPtr(hWnd, 0));
01346         break;
01347 
01348     case WM_COMMAND:
01349         win = (WINHELP_WINDOW*) GetWindowLongPtr(hWnd, 0);
01350         switch (wParam)
01351     {
01352             /* Menu FILE */
01353     case MNID_FILE_OPEN:    MACRO_FileOpen();       break;
01354     case MNID_FILE_PRINT:   MACRO_Print();          break;
01355     case MNID_FILE_SETUP:   MACRO_PrinterSetup();   break;
01356     case MNID_FILE_EXIT:    MACRO_Exit();           break;
01357 
01358             /* Menu EDIT */
01359     case MNID_EDIT_COPYDLG:
01360             SendMessage(GetDlgItem(hWnd, CTL_ID_TEXT), WM_COPY, 0, 0);
01361             break;
01362     case MNID_EDIT_ANNOTATE:MACRO_Annotate();       break;
01363 
01364             /* Menu Bookmark */
01365     case MNID_BKMK_DEFINE:  MACRO_BookmarkDefine(); break;
01366 
01367             /* Menu Help */
01368     case MNID_HELP_HELPON:  MACRO_HelpOn();         break;
01369     case MNID_HELP_HELPTOP: MACRO_HelpOnTop();      break;
01370     case MNID_HELP_ABOUT:   MACRO_About();          break;
01371 
01372             /* Context help */
01373         case MNID_CTXT_ANNOTATE:MACRO_Annotate();       break;
01374         case MNID_CTXT_COPY:    MACRO_CopyDialog();     break;
01375         case MNID_CTXT_PRINT:   MACRO_Print();          break;
01376         case MNID_OPTS_HISTORY: MACRO_History();        break;
01377         case MNID_OPTS_FONTS_SMALL:
01378         case MNID_CTXT_FONTS_SMALL:
01379             win = (WINHELP_WINDOW*) GetWindowLongPtr(hWnd, 0);
01380             if (win->font_scale != 0)
01381             {
01382                 win->font_scale = 0;
01383                 WINHELP_SetupText(GetDlgItem(hWnd, CTL_ID_TEXT), win, 0 /* FIXME */);
01384             }
01385             break;
01386         case MNID_OPTS_FONTS_NORMAL:
01387         case MNID_CTXT_FONTS_NORMAL:
01388             win = (WINHELP_WINDOW*) GetWindowLongPtr(hWnd, 0);
01389             if (win->font_scale != 1)
01390             {
01391                 win->font_scale = 1;
01392                 WINHELP_SetupText(GetDlgItem(hWnd, CTL_ID_TEXT), win, 0 /* FIXME */);
01393             }
01394             break;
01395         case MNID_OPTS_FONTS_LARGE:
01396         case MNID_CTXT_FONTS_LARGE:
01397             win = (WINHELP_WINDOW*) GetWindowLongPtr(hWnd, 0);
01398             if (win->font_scale != 2)
01399             {
01400                 win->font_scale = 2;
01401                 WINHELP_SetupText(GetDlgItem(hWnd, CTL_ID_TEXT), win, 0 /* FIXME */);
01402             }
01403             break;
01404         case MNID_OPTS_HELP_DEFAULT:
01405         case MNID_OPTS_HELP_VISIBLE:
01406         case MNID_OPTS_HELP_NONVISIBLE:
01407         case MNID_OPTS_SYSTEM_COLORS:
01408         case MNID_CTXT_HELP_DEFAULT:
01409         case MNID_CTXT_HELP_VISIBLE:
01410         case MNID_CTXT_HELP_NONVISIBLE:
01411         case MNID_CTXT_SYSTEM_COLORS:
01412             /* FIXME: NIY */
01413 
01414     default:
01415             /* Buttons */
01416             for (button = win->first_button; button; button = button->next)
01417                 if (wParam == button->wParam) break;
01418             if (button)
01419                 MACRO_ExecuteMacro(win, button->lpszMacro);
01420             else if (!HIWORD(wParam))
01421                 MessageBox(0, MAKEINTRESOURCE(STID_NOT_IMPLEMENTED),
01422                            MAKEINTRESOURCE(STID_WHERROR), MB_OK);
01423             break;
01424     }
01425         break;
01426 /* EPP     case WM_DESTROY: */
01427 /* EPP         if (Globals.hPopupWnd) DestroyWindow(Globals.hPopupWnd); */
01428 /* EPP         break; */
01429     case WM_COPYDATA:
01430         return WINHELP_HandleCommand((HWND)wParam, lParam);
01431 
01432     case WM_CHAR:
01433         if (wParam == 3)
01434         {
01435             SendMessage(GetDlgItem(hWnd, CTL_ID_TEXT), WM_COPY, 0, 0);
01436             return 0;
01437         }
01438         break;
01439 
01440     case WM_KEYDOWN:
01441         win = (WINHELP_WINDOW*) GetWindowLongPtr(hWnd, 0);
01442         hTextWnd = GetDlgItem(win->hMainWnd, CTL_ID_TEXT);
01443 
01444         switch (wParam)
01445         {
01446         case VK_UP:
01447             SendMessage(hTextWnd, EM_SCROLL, SB_LINEUP, 0);
01448             return 0;
01449         case VK_DOWN:
01450             SendMessage(hTextWnd, EM_SCROLL, SB_LINEDOWN, 0);
01451             return 0;
01452         case VK_PRIOR:
01453             SendMessage(hTextWnd, EM_SCROLL, SB_PAGEUP, 0);
01454             return 0;
01455         case VK_NEXT:
01456             SendMessage(hTextWnd, EM_SCROLL, SB_PAGEDOWN, 0);
01457             return 0;
01458         case VK_ESCAPE:
01459             MACRO_Exit();
01460             return 0;
01461         }
01462         break;
01463 
01464     case WM_NOTIFY:
01465         if (wParam == CTL_ID_TEXT)
01466         {
01467             RECT        rc;
01468 
01469             switch (((NMHDR*)lParam)->code)
01470             {
01471             case EN_MSGFILTER:
01472                 {
01473                     const MSGFILTER*    msgf = (const MSGFILTER*)lParam;
01474                     switch (msgf->msg)
01475                     {
01476                     case WM_KEYUP:
01477                         if (msgf->wParam == VK_ESCAPE)
01478                             WINHELP_ReleaseWindow((WINHELP_WINDOW*)GetWindowLongPtr(hWnd, 0));
01479                         break;
01480                     case WM_RBUTTONDOWN:
01481                     {
01482                         HMENU       hMenu;
01483                         POINT       pt;
01484 
01485                         win = (WINHELP_WINDOW*) GetWindowLongPtr(hWnd, 0);
01486                         hMenu = LoadMenu(Globals.hInstance, (LPSTR)CONTEXT_MENU);
01487                         switch (win->font_scale)
01488                         {
01489                         case 0:
01490                             CheckMenuItem(hMenu, MNID_CTXT_FONTS_SMALL,
01491                                           MF_BYCOMMAND|MF_CHECKED);
01492                             break;
01493                         default:
01494                             WINE_FIXME("Unsupported %d\n", win->font_scale);
01495                         case 1:
01496                             CheckMenuItem(hMenu, MNID_CTXT_FONTS_NORMAL,
01497                                           MF_BYCOMMAND|MF_CHECKED);
01498                             break;
01499                         case 2:
01500                             CheckMenuItem(hMenu, MNID_CTXT_FONTS_LARGE,
01501                                           MF_BYCOMMAND|MF_CHECKED);
01502                             break;
01503                         }
01504                         pt.x = (int)(short)LOWORD(msgf->lParam);
01505                         pt.y = (int)(short)HIWORD(msgf->lParam);
01506                         ClientToScreen(msgf->nmhdr.hwndFrom, &pt);
01507                         TrackPopupMenu(GetSubMenu(hMenu, 0), TPM_LEFTALIGN|TPM_TOPALIGN,
01508                                        pt.x, pt.y, 0, hWnd, NULL);
01509                         DestroyMenu(hMenu);
01510                     }
01511                     break;
01512                     default:
01513                         return WINHELP_HandleTextMouse((WINHELP_WINDOW*)GetWindowLongPtr(hWnd, 0),
01514                                                        msgf->msg, msgf->lParam);
01515                     }
01516                 }
01517                 break;
01518 
01519             case EN_REQUESTRESIZE:
01520                 rc = ((REQRESIZE*)lParam)->rc;
01521                 win = (WINHELP_WINDOW*) GetWindowLongPtr(hWnd, 0);
01522                 AdjustWindowRect(&rc, GetWindowLong(win->hMainWnd, GWL_STYLE),
01523                                  FALSE);
01524                 SetWindowPos(win->hMainWnd, HWND_TOP, 0, 0,
01525                              rc.right - rc.left, rc.bottom - rc.top,
01526                              SWP_NOMOVE | SWP_NOZORDER);
01527                 WINHELP_LayoutMainWindow(win);
01528                 break;
01529             }
01530         }
01531         break;
01532 
01533     case WM_INITMENUPOPUP:
01534         win = (WINHELP_WINDOW*) GetWindowLongPtr(hWnd, 0);
01535         CheckMenuItem((HMENU)wParam, MNID_OPTS_FONTS_SMALL,
01536                       MF_BYCOMMAND | (win->font_scale == 0) ? MF_CHECKED : 0);
01537         CheckMenuItem((HMENU)wParam, MNID_OPTS_FONTS_NORMAL,
01538                       MF_BYCOMMAND | (win->font_scale == 1) ? MF_CHECKED : 0);
01539         CheckMenuItem((HMENU)wParam, MNID_OPTS_FONTS_LARGE,
01540                       MF_BYCOMMAND | (win->font_scale == 2) ? MF_CHECKED : 0);
01541         break;
01542     case WM_DESTROY:
01543         win = (WINHELP_WINDOW*) GetWindowLongPtr(hWnd, 0);
01544         WINHELP_DeleteWindow(win);
01545         break;
01546     }
01547     return DefWindowProc(hWnd, msg, wParam, lParam);
01548 }
01549 
01550 /**************************************************************************
01551  * WINHELP_CreateIndexWindow
01552  *
01553  * Displays a dialog with keywords of current help file.
01554  *
01555  */
01556 BOOL WINHELP_CreateIndexWindow(BOOL is_search)
01557 {
01558     HPROPSHEETPAGE      psPage[3];
01559     PROPSHEETPAGE       psp;
01560     PROPSHEETHEADER     psHead;
01561     struct index_data   id;
01562     char                buf[256];
01563 
01564     if (Globals.active_win && Globals.active_win->page && Globals.active_win->page->file)
01565         id.hlpfile = Globals.active_win->page->file;
01566     else
01567         return FALSE;
01568 
01569     if (id.hlpfile->kwbtree == NULL)
01570     {
01571         WINE_TRACE("No index provided\n");
01572         return FALSE;
01573     }
01574 
01575     InitCommonControls();
01576 
01577     id.jump = FALSE;
01578     memset(&psp, 0, sizeof(psp));
01579     psp.dwSize = sizeof(psp);
01580     psp.dwFlags = 0;
01581     psp.hInstance = Globals.hInstance;
01582 
01583     psp.u.pszTemplate = MAKEINTRESOURCE(IDD_INDEX);
01584     psp.lParam = (LPARAM)&id;
01585     psp.pfnDlgProc = WINHELP_IndexDlgProc;
01586     psPage[0] = CreatePropertySheetPage(&psp);
01587 
01588     psp.u.pszTemplate = MAKEINTRESOURCE(IDD_SEARCH);
01589     psp.lParam = (LPARAM)&id;
01590     psp.pfnDlgProc = WINHELP_SearchDlgProc;
01591     psPage[1] = CreatePropertySheetPage(&psp);
01592 
01593     memset(&psHead, 0, sizeof(psHead));
01594     psHead.dwSize = sizeof(psHead);
01595 
01596     LoadString(Globals.hInstance, STID_PSH_INDEX, buf, sizeof(buf));
01597     strcat(buf, Globals.active_win->info->caption);
01598 
01599     psHead.pszCaption = buf;
01600     psHead.nPages = 2;
01601     psHead.u2.nStartPage = is_search ? 1 : 0;
01602     psHead.hwndParent = Globals.active_win->hMainWnd;
01603     psHead.u3.phpage = psPage;
01604     psHead.dwFlags = PSH_NOAPPLYNOW;
01605 
01606     PropertySheet(&psHead);
01607     if (id.jump)
01608     {
01609         WINE_TRACE("got %d as an offset\n", id.offset);
01610         WINHELP_OpenHelpWindow(HLPFILE_PageByOffset, id.hlpfile, id.offset,
01611                                Globals.active_win->info, SW_NORMAL);
01612     }
01613     return TRUE;
01614 }
01615 
01616 /***********************************************************************
01617  *
01618  *           RegisterWinClasses
01619  */
01620 static BOOL WINHELP_RegisterWinClasses(void)
01621 {
01622     WNDCLASSEX class_main, class_button_box, class_history;
01623 
01624     class_main.cbSize              = sizeof(class_main);
01625     class_main.style               = CS_HREDRAW | CS_VREDRAW;
01626     class_main.lpfnWndProc         = WINHELP_MainWndProc;
01627     class_main.cbClsExtra          = 0;
01628     class_main.cbWndExtra          = sizeof(WINHELP_WINDOW *);
01629     class_main.hInstance           = Globals.hInstance;
01630     class_main.hIcon               = LoadIcon(Globals.hInstance, MAKEINTRESOURCE(IDI_WINHELP));
01631     class_main.hCursor             = LoadCursor(0, IDC_ARROW);
01632     class_main.hbrBackground       = (HBRUSH)(COLOR_WINDOW+1);
01633     class_main.lpszMenuName        = 0;
01634     class_main.lpszClassName       = MAIN_WIN_CLASS_NAME;
01635     class_main.hIconSm             = LoadImage(Globals.hInstance, MAKEINTRESOURCE(IDI_WINHELP), IMAGE_ICON,
01636                                                GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
01637                                                LR_SHARED);
01638 
01639     class_button_box               = class_main;
01640     class_button_box.lpfnWndProc   = WINHELP_ButtonBoxWndProc;
01641     class_button_box.cbWndExtra    = 0;
01642     class_button_box.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
01643     class_button_box.lpszClassName = BUTTON_BOX_WIN_CLASS_NAME;
01644 
01645     class_history                  = class_main;
01646     class_history.lpfnWndProc      = WINHELP_HistoryWndProc;
01647     class_history.lpszClassName    = HISTORY_WIN_CLASS_NAME;
01648 
01649     return (RegisterClassEx(&class_main) &&
01650             RegisterClassEx(&class_button_box) &&
01651             RegisterClassEx(&class_history));
01652 }
01653 
01654 /***********************************************************************
01655  *
01656  *           WinMain
01657  */
01658 int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show)
01659 {
01660     MSG                 msg;
01661     LONG                lHash = 0;
01662     HLPFILE*            hlpfile;
01663     static CHAR         default_wndname[] = "main";
01664     LPSTR               wndname = default_wndname;
01665     WINHELP_DLL*        dll;
01666 
01667     Globals.hInstance = hInstance;
01668 
01669     if (LoadLibrary("riched20.dll") == NULL)
01670         return MessageBox(0, MAKEINTRESOURCE(STID_NO_RICHEDIT),
01671                           MAKEINTRESOURCE(STID_WHERROR), MB_OK);
01672 
01673     /* Get options */
01674     while (*cmdline && (*cmdline == ' ' || *cmdline == '-'))
01675     {
01676         CHAR   option;
01677         LPCSTR topic_id;
01678         if (*cmdline++ == ' ') continue;
01679 
01680         option = *cmdline;
01681         if (option) cmdline++;
01682         while (*cmdline && *cmdline == ' ') cmdline++;
01683         switch (option)
01684     {
01685     case 'i':
01686     case 'I':
01687             topic_id = cmdline;
01688             while (*cmdline && *cmdline != ' ') cmdline++;
01689             if (*cmdline) *cmdline++ = '\0';
01690             lHash = HLPFILE_Hash(topic_id);
01691             break;
01692 
01693     case '3':
01694     case '4':
01695             Globals.wVersion = option - '0';
01696             break;
01697 
01698         case 'x':
01699             show = SW_HIDE;
01700             Globals.isBook = FALSE;
01701             break;
01702 
01703         default:
01704             WINE_FIXME("Unsupported cmd line: %s\n", cmdline);
01705             break;
01706     }
01707     }
01708 
01709     /* Create primary window */
01710     if (!WINHELP_RegisterWinClasses())
01711     {
01712         WINE_FIXME("Couldn't register classes\n");
01713         return 0;
01714     }
01715 
01716     if (*cmdline)
01717     {
01718         char*   ptr;
01719         if ((*cmdline == '"') && (ptr = strchr(cmdline+1, '"')))
01720         {
01721             cmdline++;
01722             *ptr = '\0';
01723         }
01724         if ((ptr = strchr(cmdline, '>')))
01725         {
01726             *ptr = '\0';
01727             wndname = ptr + 1;
01728         }
01729         hlpfile = WINHELP_LookupHelpFile(cmdline);
01730         if (!hlpfile) return 0;
01731     }
01732     else hlpfile = NULL;
01733     WINHELP_OpenHelpWindow(HLPFILE_PageByHash, hlpfile, lHash,
01734                            WINHELP_GetWindowInfo(hlpfile, wndname), show);
01735 
01736     /* Message loop */
01737     while ((Globals.win_list || Globals.active_popup) && GetMessage(&msg, 0, 0, 0))
01738     {
01739         TranslateMessage(&msg);
01740         DispatchMessage(&msg);
01741     }
01742     for (dll = Globals.dlls; dll; dll = dll->next)
01743     {
01744         if (dll->class & DC_INITTERM) dll->handler(DW_TERM, 0, 0);
01745     }
01746     return 0;
01747 }

Generated on Sun May 27 2012 04:17:50 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.