Added new dynamic loading classes. (which handle proper
[wxWidgets.git] / src / msw / helpchm.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: helpchm.cpp
3 // Purpose: Help system: MS HTML Help implementation
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 16/04/2000
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "helpchm.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/defs.h"
25 #endif
26
27 #include "wx/filefn.h"
28
29 #if wxUSE_HELP && wxUSE_MS_HTML_HELP && defined(__WIN95__)
30 #include "wx/msw/helpchm.h"
31
32 #if wxUSE_DYNAMIC_LOADER || wxUSE_DYNLIB_CLASS
33 #include "wx/dynlib.h"
34 #endif
35
36 #ifndef WX_PRECOMP
37 #include <windows.h>
38 #endif
39
40 // This is found in the HTML Help Workshop installation,
41 // along with htmlhelp.lib.
42 #include <htmlhelp.h>
43
44 #include <time.h>
45
46 #ifdef __WXMSW__
47 #include "wx/msw/private.h"
48 #endif
49
50 #include <string.h>
51
52 // utility functions to manage the loading/unloading
53 // of hhctrl.ocx
54 #ifndef UNICODE
55 typedef HWND ( WINAPI * HTMLHELP )( HWND, LPCSTR, UINT, DWORD );
56 #define HTMLHELP_NAME "HtmlHelpA"
57 #else
58 typedef HWND ( WINAPI * HTMLHELP )( HWND, LPCWSTR, UINT, DWORD );
59 #define HTMLHELP_NAME "HtmlHelpW"
60 #endif
61 // dll handle/reference count
62 static HTMLHELP gs_htmlHelp = 0;
63 static wxDllType gs_dllHandle = 0;
64 static int gs_dllCount = 0;
65
66 static bool LoadHtmlHelpLibrary()
67 {
68 if( !gs_dllCount )
69 {
70 gs_dllHandle = wxDllLoader::LoadLibrary( "hhctrl.ocx" );
71 if( !gs_dllHandle )
72 {
73 wxLogError(_("MS HTML Help functions are unavailable because the MS HTML Help library is not installed on this machine. Please install it."));
74 return FALSE;
75 }
76 else
77 {
78 gs_dllCount = 1;
79 gs_htmlHelp = (HTMLHELP)wxDllLoader::GetSymbol( gs_dllHandle, HTMLHELP_NAME );
80
81 if( !gs_htmlHelp )
82 {
83 wxLogError(_("Failed to initialize MS HTML Help."));
84
85 wxDllLoader::UnloadLibrary(gs_dllHandle);
86 gs_dllHandle = 0;
87 gs_dllCount = 0;
88
89 return FALSE ;
90 }
91 }
92 }
93 else
94 {
95 ++gs_dllCount;
96 }
97
98 return TRUE;
99 }
100
101 static void UnloadHtmlHelpLibrary()
102 {
103 if( gs_dllCount != 0 && !--gs_dllCount )
104 {
105 wxDllLoader::UnloadLibrary( gs_dllHandle );
106 gs_dllHandle = 0;
107 gs_htmlHelp = 0;
108 }
109 }
110
111 static HWND GetSuitableHWND()
112 {
113 if (wxTheApp->GetTopWindow())
114 return (HWND) wxTheApp->GetTopWindow()->GetHWND();
115 else
116 return GetDesktopWindow();
117 }
118
119 IMPLEMENT_DYNAMIC_CLASS(wxCHMHelpController, wxHelpControllerBase)
120
121 bool wxCHMHelpController::Initialize(const wxString& filename)
122 {
123 // warn on failure
124 if( !LoadHtmlHelpLibrary() )
125 return FALSE;
126
127 m_helpFile = filename;
128 return TRUE;
129 }
130
131 bool wxCHMHelpController::LoadFile(const wxString& file)
132 {
133 if (!file.IsEmpty())
134 m_helpFile = file;
135 return TRUE;
136 }
137
138 bool wxCHMHelpController::DisplayContents()
139 {
140 if (m_helpFile.IsEmpty()) return FALSE;
141
142 wxString str = GetValidFilename(m_helpFile);
143
144 gs_htmlHelp(GetSuitableHWND(), (const wxChar*) str, HH_HELP_FINDER, 0L);
145 return TRUE;
146 }
147
148 // Use topic or HTML filename
149 bool wxCHMHelpController::DisplaySection(const wxString& section)
150 {
151 if (m_helpFile.IsEmpty()) return FALSE;
152
153 wxString str = GetValidFilename(m_helpFile);
154
155 // Is this an HTML file or a keyword?
156 bool isFilename = (section.Find(wxT(".htm")) != -1);
157
158 if (isFilename)
159 gs_htmlHelp(GetSuitableHWND(), (const wxChar*) str, HH_DISPLAY_TOPIC, (DWORD) (const wxChar*) section);
160 else
161 KeywordSearch(section);
162 return TRUE;
163 }
164
165 // Use context number
166 bool wxCHMHelpController::DisplaySection(int section)
167 {
168 if (m_helpFile.IsEmpty()) return FALSE;
169
170 wxString str = GetValidFilename(m_helpFile);
171
172 gs_htmlHelp(GetSuitableHWND(), (const wxChar*) str, HH_HELP_CONTEXT, (DWORD)section);
173 return TRUE;
174 }
175
176 bool wxCHMHelpController::DisplayContextPopup(int contextId)
177 {
178 if (m_helpFile.IsEmpty()) return FALSE;
179
180 wxString str = GetValidFilename(m_helpFile);
181
182 // We also have to specify the popups file (default is cshelp.txt).
183 // str += wxT("::/cshelp.txt");
184
185 HH_POPUP popup;
186 popup.cbStruct = sizeof(popup);
187 popup.hinst = (HINSTANCE) wxGetInstance();
188 popup.idString = contextId ;
189
190 GetCursorPos(& popup.pt);
191 popup.clrForeground = (COLORREF)-1;
192 popup.clrBackground = (COLORREF)-1;
193 popup.rcMargins.top = popup.rcMargins.left = popup.rcMargins.right = popup.rcMargins.bottom = -1;
194 popup.pszFont = NULL;
195 popup.pszText = NULL;
196
197 gs_htmlHelp(GetSuitableHWND(), (const wxChar*) str, HH_DISPLAY_TEXT_POPUP, (DWORD) & popup);
198 return TRUE;
199 }
200
201 bool wxCHMHelpController::DisplayTextPopup(const wxString& text, const wxPoint& pos)
202 {
203 HH_POPUP popup;
204 popup.cbStruct = sizeof(popup);
205 popup.hinst = (HINSTANCE) wxGetInstance();
206 popup.idString = 0 ;
207 popup.pt.x = pos.x; popup.pt.y = pos.y;
208 popup.clrForeground = (COLORREF)-1;
209 popup.clrBackground = (COLORREF)-1;
210 popup.rcMargins.top = popup.rcMargins.left = popup.rcMargins.right = popup.rcMargins.bottom = -1;
211 popup.pszFont = NULL;
212 popup.pszText = (const wxChar*) text;
213
214 gs_htmlHelp(GetSuitableHWND(), NULL, HH_DISPLAY_TEXT_POPUP, (DWORD) & popup);
215 return TRUE;
216 }
217
218 bool wxCHMHelpController::DisplayBlock(long block)
219 {
220 return DisplaySection(block);
221 }
222
223 bool wxCHMHelpController::KeywordSearch(const wxString& k)
224 {
225 if (m_helpFile.IsEmpty()) return FALSE;
226
227 wxString str = GetValidFilename(m_helpFile);
228
229 HH_AKLINK link;
230 link.cbStruct = sizeof(HH_AKLINK) ;
231 link.fReserved = FALSE ;
232 link.pszKeywords = k.c_str() ;
233 link.pszUrl = NULL ;
234 link.pszMsgText = NULL ;
235 link.pszMsgTitle = NULL ;
236 link.pszWindow = NULL ;
237 link.fIndexOnFail = TRUE ;
238
239 gs_htmlHelp(GetSuitableHWND(), (const wxChar*) str, HH_KEYWORD_LOOKUP, (DWORD)& link);
240 return TRUE;
241 }
242
243 bool wxCHMHelpController::Quit()
244 {
245 gs_htmlHelp(GetSuitableHWND(), 0, HH_CLOSE_ALL, 0L);
246 UnloadHtmlHelpLibrary();
247
248 return TRUE;
249 }
250
251 // Append extension if necessary.
252 wxString wxCHMHelpController::GetValidFilename(const wxString& file) const
253 {
254 wxString path, name, ext;
255 wxSplitPath(file, & path, & name, & ext);
256
257 wxString fullName;
258 if (path.IsEmpty())
259 fullName = name + wxT(".chm");
260 else if (path.Last() == wxT('\\'))
261 fullName = path + name + wxT(".chm");
262 else
263 fullName = path + wxT("\\") + name + wxT(".chm");
264 return fullName;
265 }
266
267 #endif // wxUSE_HELP