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