s/wxSplitPath/wxFileName::SplitPath
[wxWidgets.git] / src / msw / helpchm.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/helpchm.cpp
3 // Purpose: Help system: MS HTML Help implementation
4 // Author: Julian Smart
5 // Modified by: Vadim Zeitlin at 2008-03-01: refactoring, simplification
6 // Created: 16/04/2000
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #if wxUSE_HELP && wxUSE_MS_HTML_HELP
20
21 #include "wx/filefn.h"
22 #include "wx/msw/helpchm.h"
23
24 #include "wx/dynload.h"
25
26 #ifndef WX_PRECOMP
27 #include "wx/intl.h"
28 #include "wx/app.h"
29 #endif
30
31 #include "wx/msw/private.h"
32 #include "wx/msw/htmlhelp.h"
33
34 // ----------------------------------------------------------------------------
35 // utility functions to manage the loading/unloading
36 // of hhctrl.ocx
37 // ----------------------------------------------------------------------------
38
39 #ifndef UNICODE
40 typedef HWND ( WINAPI * HTMLHELP )( HWND, LPCSTR, UINT, DWORD );
41 #define HTMLHELP_NAME wxT("HtmlHelpA")
42 #else // ANSI
43 typedef HWND ( WINAPI * HTMLHELP )( HWND, LPCWSTR, UINT, DWORD );
44 #define HTMLHELP_NAME wxT("HtmlHelpW")
45 #endif
46
47 HTMLHELP GetHtmlHelpFunction()
48 {
49 static HTMLHELP s_htmlHelp = NULL;
50
51 if ( !s_htmlHelp )
52 {
53 static wxDynamicLibrary s_dllHtmlHelp(_T("HHCTRL.OCX"), wxDL_VERBATIM);
54
55 if ( !s_dllHtmlHelp.IsLoaded() )
56 {
57 wxLogError(_("MS HTML Help functions are unavailable because the MS HTML Help library is not installed on this machine. Please install it."));
58 }
59 else
60 {
61 s_htmlHelp = (HTMLHELP)s_dllHtmlHelp.GetSymbol(HTMLHELP_NAME);
62 if ( !s_htmlHelp )
63 {
64 wxLogError(_("Failed to initialize MS HTML Help."));
65 }
66 }
67 }
68
69 return s_htmlHelp;
70 }
71
72 // find the window to use in HtmlHelp() call: use the given one by default but
73 // fall back to the top level app window and then the desktop if it's NULL
74 static HWND GetSuitableHWND(wxWindow *win)
75 {
76 if ( !win && wxTheApp )
77 win = wxTheApp->GetTopWindow();
78
79 return win ? GetHwndOf(win) : ::GetDesktopWindow();
80 }
81
82
83 IMPLEMENT_DYNAMIC_CLASS(wxCHMHelpController, wxHelpControllerBase)
84
85 bool wxCHMHelpController::Initialize(const wxString& filename)
86 {
87 if ( !GetHtmlHelpFunction() )
88 return false;
89
90 m_helpFile = filename;
91 return true;
92 }
93
94 bool wxCHMHelpController::LoadFile(const wxString& file)
95 {
96 if (!file.IsEmpty())
97 m_helpFile = file;
98 return true;
99 }
100
101 /* static */ bool
102 wxCHMHelpController::CallHtmlHelp(wxWindow *win,
103 const wxChar *str,
104 unsigned cmd,
105 WXWPARAM param)
106 {
107 HTMLHELP htmlHelp = GetHtmlHelpFunction();
108
109 return htmlHelp && htmlHelp(GetSuitableHWND(win), str, cmd, param);
110 }
111
112 bool wxCHMHelpController::DisplayContents()
113 {
114 if (m_helpFile.IsEmpty())
115 return false;
116
117 return CallHtmlHelp(HH_DISPLAY_TOPIC);
118 }
119
120 // Use topic or HTML filename
121 bool wxCHMHelpController::DisplaySection(const wxString& section)
122 {
123 if (m_helpFile.IsEmpty())
124 return false;
125
126 // Is this an HTML file or a keyword?
127 if ( section.Find(wxT(".htm")) != wxNOT_FOUND )
128 {
129 // interpret as a file name
130 return CallHtmlHelp(HH_DISPLAY_TOPIC, section.wx_str());
131 }
132
133 return KeywordSearch(section);
134 }
135
136 // Use context number
137 bool wxCHMHelpController::DisplaySection(int section)
138 {
139 if (m_helpFile.IsEmpty())
140 return false;
141
142 return CallHtmlHelp(HH_HELP_CONTEXT, section);
143 }
144
145 /* static */
146 bool
147 wxCHMHelpController::DoDisplayTextPopup(const wxChar *text,
148 const wxPoint& pos,
149 int contextId,
150 wxWindow *window)
151 {
152 HH_POPUP popup;
153 popup.cbStruct = sizeof(popup);
154 popup.hinst = (HINSTANCE) wxGetInstance();
155 popup.idString = contextId;
156 popup.pszText = text;
157 popup.pt.x = pos.x;
158 popup.pt.y = pos.y;
159 popup.clrForeground =
160 popup.clrBackground = (COLORREF)-1;
161 popup.rcMargins.top =
162 popup.rcMargins.left =
163 popup.rcMargins.right =
164 popup.rcMargins.bottom = -1;
165 popup.pszFont = NULL;
166
167 return CallHtmlHelp(window, NULL, HH_DISPLAY_TEXT_POPUP, &popup);
168 }
169
170 bool wxCHMHelpController::DisplayContextPopup(int contextId)
171 {
172 return DoDisplayTextPopup(NULL, wxGetMousePosition(), contextId,
173 GetParentWindow());
174 }
175
176 bool
177 wxCHMHelpController::DisplayTextPopup(const wxString& text, const wxPoint& pos)
178 {
179 return ShowContextHelpPopup(text, pos, GetParentWindow());
180 }
181
182 /* static */
183 bool wxCHMHelpController::ShowContextHelpPopup(const wxString& text,
184 const wxPoint& pos,
185 wxWindow *window)
186 {
187 return DoDisplayTextPopup(text.wx_str(), pos, 0, window);
188 }
189
190 bool wxCHMHelpController::DisplayBlock(long block)
191 {
192 return DisplaySection(block);
193 }
194
195 bool wxCHMHelpController::KeywordSearch(const wxString& k,
196 wxHelpSearchMode WXUNUSED(mode))
197 {
198 if (m_helpFile.IsEmpty())
199 return false;
200
201 HH_AKLINK link;
202 link.cbStruct = sizeof(HH_AKLINK);
203 link.fReserved = FALSE;
204 link.pszKeywords = k.wx_str();
205 link.pszUrl = NULL;
206 link.pszMsgText = NULL;
207 link.pszMsgTitle = NULL;
208 link.pszWindow = NULL;
209 link.fIndexOnFail = TRUE;
210
211 return CallHtmlHelp(HH_KEYWORD_LOOKUP, &link);
212 }
213
214 bool wxCHMHelpController::Quit()
215 {
216 return CallHtmlHelp(NULL, NULL, HH_CLOSE_ALL);
217 }
218
219 wxString wxCHMHelpController::GetValidFilename() const
220 {
221 wxString path, name, ext;
222 wxFileName::SplitPath(m_helpFile, &path, &name, &ext);
223
224 wxString fullName;
225 if (path.IsEmpty())
226 fullName = name + wxT(".chm");
227 else if (path.Last() == wxT('\\'))
228 fullName = path + name + wxT(".chm");
229 else
230 fullName = path + wxT("\\") + name + wxT(".chm");
231 return fullName;
232 }
233
234 #endif // wxUSE_HELP