📄 winhelp.c
字号:
/* * Help Viewer * * Copyright 1996 Ulrich Schmid <uschmid@mail.hh.provi.de> * 2002 Sylvain Petreolle <spetreolle@yahoo.fr> * 2002 Eric Pouech <eric.pouech@wanadoo.fr> * 2004 Ken Belleau <jamez@ivic.qc.ca> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */#include <assert.h>#include <stdio.h>#include <string.h>#include <stdarg.h>#include <stdlib.h>#include "windef.h"#include "winbase.h"#include "wingdi.h"#include "winuser.h"#include "commdlg.h"#include "winhelp.h"#include "winhelp_res.h"#include "shellapi.h"#include "wine/debug.h"WINE_DEFAULT_DEBUG_CHANNEL(winhelp);static BOOL WINHELP_RegisterWinClasses(void);static LRESULT CALLBACK WINHELP_MainWndProc(HWND, UINT, WPARAM, LPARAM);static LRESULT CALLBACK WINHELP_TextWndProc(HWND, UINT, WPARAM, LPARAM);static LRESULT CALLBACK WINHELP_ButtonBoxWndProc(HWND, UINT, WPARAM, LPARAM);static LRESULT CALLBACK WINHELP_ButtonWndProc(HWND, UINT, WPARAM, LPARAM);static LRESULT CALLBACK WINHELP_HistoryWndProc(HWND, UINT, WPARAM, LPARAM);static LRESULT CALLBACK WINHELP_ShadowWndProc(HWND, UINT, WPARAM, LPARAM);static void WINHELP_CheckPopup(UINT);static BOOL WINHELP_SplitLines(HWND hWnd, LPSIZE);static void WINHELP_InitFonts(HWND hWnd);static void WINHELP_DeleteLines(WINHELP_WINDOW*);static void WINHELP_DeleteWindow(WINHELP_WINDOW*);static void WINHELP_SetupText(HWND hWnd);static WINHELP_LINE_PART* WINHELP_IsOverLink(WINHELP_WINDOW*, WPARAM, LPARAM);WINHELP_GLOBALS Globals = {3, NULL, NULL, 0, TRUE, NULL, NULL, NULL, NULL};/*********************************************************************** * * WINHELP_GetOpenFileName */BOOL WINHELP_GetOpenFileName(LPSTR lpszFile, int len){ OPENFILENAME openfilename; CHAR szDir[MAX_PATH]; CHAR szzFilter[2 * MAX_STRING_LEN + 100]; LPSTR p = szzFilter; WINE_TRACE("()\n"); LoadString(Globals.hInstance, STID_HELP_FILES_HLP, p, MAX_STRING_LEN); p += strlen(p) + 1; lstrcpy(p, "*.hlp"); p += strlen(p) + 1; LoadString(Globals.hInstance, STID_ALL_FILES, p, MAX_STRING_LEN); p += strlen(p) + 1; lstrcpy(p, "*.*"); p += strlen(p) + 1; *p = '\0'; GetCurrentDirectory(sizeof(szDir), szDir); lpszFile[0]='\0'; openfilename.lStructSize = sizeof(OPENFILENAME); openfilename.hwndOwner = NULL; openfilename.hInstance = Globals.hInstance; openfilename.lpstrFilter = szzFilter; openfilename.lpstrCustomFilter = 0; openfilename.nMaxCustFilter = 0; openfilename.nFilterIndex = 1; openfilename.lpstrFile = lpszFile; openfilename.nMaxFile = len; openfilename.lpstrFileTitle = 0; openfilename.nMaxFileTitle = 0; openfilename.lpstrInitialDir = szDir; openfilename.lpstrTitle = 0; openfilename.Flags = 0; openfilename.nFileOffset = 0; openfilename.nFileExtension = 0; openfilename.lpstrDefExt = 0; openfilename.lCustData = 0; openfilename.lpfnHook = 0; openfilename.lpTemplateName = 0; return GetOpenFileName(&openfilename);}/*********************************************************************** * * WINHELP_LookupHelpFile */HLPFILE* WINHELP_LookupHelpFile(LPCSTR lpszFile){ HLPFILE* hlpfile; char szFullName[MAX_PATH]; char szAddPath[MAX_PATH]; char *p; /* * NOTE: This is needed by popup windows only. * In other cases it's not needed but does not hurt though. */ if (Globals.active_win && Globals.active_win->page && Globals.active_win->page->file) { strcpy(szAddPath, Globals.active_win->page->file->lpszPath); p = strrchr(szAddPath, '\\'); if (p) *p = 0; } /* * FIXME: Should we swap conditions? */ if (!SearchPath(NULL, lpszFile, ".hlp", MAX_PATH, szFullName, NULL) && !SearchPath(szAddPath, lpszFile, ".hlp", MAX_PATH, szFullName, NULL)) { if (WINHELP_MessageBoxIDS_s(STID_FILE_NOT_FOUND_s, lpszFile, STID_WHERROR, MB_YESNO|MB_ICONQUESTION) != IDYES) return NULL; if (!WINHELP_GetOpenFileName(szFullName, MAX_PATH)) return NULL; } hlpfile = HLPFILE_ReadHlpFile(szFullName); if (!hlpfile) WINHELP_MessageBoxIDS_s(STID_HLPFILE_ERROR_s, lpszFile, STID_WHERROR, MB_OK|MB_ICONSTOP); return hlpfile;}/****************************************************************** * WINHELP_GetWindowInfo * * */HLPFILE_WINDOWINFO* WINHELP_GetWindowInfo(HLPFILE* hlpfile, LPCSTR name){ static HLPFILE_WINDOWINFO mwi; unsigned int i; if (!name || !name[0]) name = Globals.active_win->lpszName; if (hlpfile) for (i = 0; i < hlpfile->numWindows; i++) if (!strcmp(hlpfile->windows[i].name, name)) return &hlpfile->windows[i]; if (strcmp(name, "main") != 0) { WINE_FIXME("Couldn't find window info for %s\n", name); assert(0); return NULL; } if (!mwi.name[0]) { strcpy(mwi.type, "primary"); strcpy(mwi.name, "main"); if (!LoadString(Globals.hInstance, STID_WINE_HELP, mwi.caption, sizeof(mwi.caption))) strcpy(mwi.caption, hlpfile->lpszTitle); mwi.origin.x = mwi.origin.y = mwi.size.cx = mwi.size.cy = CW_USEDEFAULT; mwi.style = SW_SHOW; mwi.win_style = WS_OVERLAPPEDWINDOW; mwi.sr_color = mwi.sr_color = 0xFFFFFF; } return &mwi;}/****************************************************************** * HLPFILE_GetPopupWindowInfo * * */static HLPFILE_WINDOWINFO* WINHELP_GetPopupWindowInfo(HLPFILE* hlpfile, HWND hParentWnd, POINT* mouse){ static HLPFILE_WINDOWINFO wi; RECT parent_rect; wi.type[0] = wi.name[0] = wi.caption[0] = '\0'; /* Calculate horizontal size and position of a popup window */ GetWindowRect(hParentWnd, &parent_rect); wi.size.cx = (parent_rect.right - parent_rect.left) / 2; wi.size.cy = 10; /* need a non null value, so that border are taken into account while computing */ wi.origin = *mouse; ClientToScreen(hParentWnd, &wi.origin); wi.origin.x -= wi.size.cx / 2; wi.origin.x = min(wi.origin.x, GetSystemMetrics(SM_CXSCREEN) - wi.size.cx); wi.origin.x = max(wi.origin.x, 0); wi.style = SW_SHOW; wi.win_style = WS_POPUPWINDOW; wi.sr_color = wi.sr_color = 0xFFFFFF; return &wi;}/*********************************************************************** * * WinMain */int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show){ MSG msg; LONG lHash = 0; HLPFILE* hlpfile; static CHAR default_wndname[] = "main"; LPSTR wndname = default_wndname; WINHELP_DLL* dll; Globals.hInstance = hInstance; /* Get options */ while (*cmdline && (*cmdline == ' ' || *cmdline == '-')) { CHAR option; LPCSTR topic_id; if (*cmdline++ == ' ') continue; option = *cmdline; if (option) cmdline++; while (*cmdline && *cmdline == ' ') cmdline++; switch (option) { case 'i': case 'I': topic_id = cmdline; while (*cmdline && *cmdline != ' ') cmdline++; if (*cmdline) *cmdline++ = '\0'; lHash = HLPFILE_Hash(topic_id); break; case '3': case '4': Globals.wVersion = option - '0'; break; case 'x': show = SW_HIDE; Globals.isBook = FALSE; break; default: WINE_FIXME("Unsupported cmd line: %s\n", cmdline); break; } } /* Create primary window */ if (!WINHELP_RegisterWinClasses()) { WINE_FIXME("Couldn't register classes\n"); return 0; } if (*cmdline) { char* ptr; if ((*cmdline == '"') && (ptr = strchr(cmdline+1, '"'))) { cmdline++; *ptr = '\0'; } if ((ptr = strchr(cmdline, '>'))) { *ptr = '\0'; wndname = ptr + 1; } hlpfile = WINHELP_LookupHelpFile(cmdline); if (!hlpfile) return 0; } else hlpfile = NULL; WINHELP_CreateHelpWindowByHash(hlpfile, lHash, WINHELP_GetWindowInfo(hlpfile, wndname), show); /* Message loop */ while (GetMessage(&msg, 0, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } for (dll = Globals.dlls; dll; dll = dll->next) { if (dll->class & DC_INITTERM) dll->handler(DW_TERM, 0, 0); } return 0;}/*********************************************************************** * * RegisterWinClasses */static BOOL WINHELP_RegisterWinClasses(void){ WNDCLASS class_main, class_button_box, class_text, class_shadow, class_history; class_main.style = CS_HREDRAW | CS_VREDRAW; class_main.lpfnWndProc = WINHELP_MainWndProc; class_main.cbClsExtra = 0; class_main.cbWndExtra = sizeof(LONG); class_main.hInstance = Globals.hInstance; class_main.hIcon = LoadIcon(0, IDI_APPLICATION); class_main.hCursor = LoadCursor(0, IDC_ARROW); class_main.hbrBackground = GetStockObject(WHITE_BRUSH); class_main.lpszMenuName = 0; class_main.lpszClassName = MAIN_WIN_CLASS_NAME; class_button_box = class_main; class_button_box.lpfnWndProc = WINHELP_ButtonBoxWndProc; class_button_box.hbrBackground = GetStockObject(GRAY_BRUSH); class_button_box.lpszClassName = BUTTON_BOX_WIN_CLASS_NAME; class_text = class_main; class_text.lpfnWndProc = WINHELP_TextWndProc; class_text.hbrBackground = 0; class_text.lpszClassName = TEXT_WIN_CLASS_NAME; class_shadow = class_main; class_shadow.lpfnWndProc = WINHELP_ShadowWndProc; class_shadow.hbrBackground = GetStockObject(GRAY_BRUSH); class_shadow.lpszClassName = SHADOW_WIN_CLASS_NAME; class_history = class_main; class_history.lpfnWndProc = WINHELP_HistoryWndProc; class_history.lpszClassName = HISTORY_WIN_CLASS_NAME; return (RegisterClass(&class_main) && RegisterClass(&class_button_box) && RegisterClass(&class_text) && RegisterClass(&class_shadow) && RegisterClass(&class_history));}typedef struct{ WORD size; WORD command; LONG data; LONG reserved; WORD ofsFilename; WORD ofsData;} WINHELP,*LPWINHELP;/****************************************************************** * WINHELP_HandleCommand * * */static LRESULT WINHELP_HandleCommand(HWND hSrcWnd, LPARAM lParam){ COPYDATASTRUCT* cds = (COPYDATASTRUCT*)lParam; WINHELP* wh; if (cds->dwData != 0xA1DE505) { WINE_FIXME("Wrong magic number (%08lx)\n", cds->dwData); return 0; } wh = (WINHELP*)cds->lpData; if (wh)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -