Bugfix : Zooming works correct, no more errors on screen.
[xara-cairo.git] / wxOil / helpuser.cpp
blob60f496c8bcc8c965a5d20dc37c230eee383cdce1
1 // $Id: helpuser.cpp 1729 2006-08-30 12:48:48Z luke $
2 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
3 ================================XARAHEADERSTART===========================
5 Xara LX, a vector drawing and manipulation program.
6 Copyright (C) 1993-2006 Xara Group Ltd.
7 Copyright on certain contributions may be held in joint with their
8 respective authors. See AUTHORS file for details.
10 LICENSE TO USE AND MODIFY SOFTWARE
11 ----------------------------------
13 This file is part of Xara LX.
15 Xara LX is free software; you can redistribute it and/or modify it
16 under the terms of the GNU General Public License version 2 as published
17 by the Free Software Foundation.
19 Xara LX and its component source files are distributed in the hope
20 that it will be useful, but WITHOUT ANY WARRANTY; without even the
21 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
22 See the GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License along
25 with Xara LX (see the file GPL in the root directory of the
26 distribution); if not, write to the Free Software Foundation, Inc., 51
27 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 ADDITIONAL RIGHTS
31 -----------------
33 Conditional upon your continuing compliance with the GNU General Public
34 License described above, Xara Group Ltd grants to you certain additional
35 rights.
37 The additional rights are to use, modify, and distribute the software
38 together with the wxWidgets library, the wxXtra library, and the "CDraw"
39 library and any other such library that any version of Xara LX relased
40 by Xara Group Ltd requires in order to compile and execute, including
41 the static linking of that library to XaraLX. In the case of the
42 "CDraw" library, you may satisfy obligation under the GNU General Public
43 License to provide source code by providing a binary copy of the library
44 concerned and a copy of the license accompanying it.
46 Nothing in this section restricts any of the rights you have under
47 the GNU General Public License.
50 SCOPE OF LICENSE
51 ----------------
53 This license applies to this program (XaraLX) and its constituent source
54 files only, and does not necessarily apply to other Xara products which may
55 in part share the same code base, and are subject to their own licensing
56 terms.
58 This license does not apply to files in the wxXtra directory, which
59 are built into a separate library, and are subject to the wxWindows
60 license contained within that directory in the file "WXXTRA-LICENSE".
62 This license does not apply to the binary libraries (if any) within
63 the "libs" directory, which are subject to a separate license contained
64 within that directory in the file "LIBS-LICENSE".
67 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
68 ----------------------------------------------
70 Subject to the terms of the GNU Public License (see above), you are
71 free to do whatever you like with your modifications. However, you may
72 (at your option) wish contribute them to Xara's source tree. You can
73 find details of how to do this at:
74 http://www.xaraxtreme.org/developers/
76 Prior to contributing your modifications, you will need to complete our
77 contributor agreement. This can be found at:
78 http://www.xaraxtreme.org/developers/contribute/
80 Please note that Xara will not accept modifications which modify any of
81 the text between the start and end of this header (marked
82 XARAHEADERSTART and XARAHEADEREND).
85 MARKS
86 -----
88 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
89 designs are registered or unregistered trademarks, design-marks, and/or
90 service marks of Xara Group Ltd. All rights in these marks are reserved.
93 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
94 http://www.xara.com/
96 =================================XARAHEADEREND============================
100 helpuser.cpp
102 Routines to invoke the platform's help system for a given Camelot object or
103 topic reference.
107 #include "camtypes.h"
109 //#include <io.h> // for FileExists
110 #include <stdlib.h>
111 #include "camelot.h"
112 //#include "mainfrm.h"
113 //#include "dialogop.h" - in camtypes.h [AUTOMATICALLY REMOVED]
114 //#include "errorbox.h"
116 #include "helpuser.h"
117 #include "helptabs.h"
118 //#include "xshelpid.h" // for the _R(IDH_TEST_PAGE)
119 #include "product.h" // for the PRODUCT_BASENAME
120 //#include "resdll.h"
121 //#include "helpdownload.h"
123 //#include "simon.h" // for the _R(IDS_HELP) button label string
125 //#include <htmlhelp.h> // for html help
126 #include "keypress.h"
129 // Code version.
130 DECLARE_SOURCE("$Revision: 1729 $");
133 // We need to use the correct filename parsing functions, depending on whether we are
134 // a C/ASCII/ANSI or a Unicode build. Note that under Win32 all exported functions
135 // are specified in the ANSI character set, even in Unicode builds.
136 #undef SPLITPATH
137 #undef MAKEPATH
138 #undef GETSHORTPATHNAME
140 #ifdef UNICODE
141 // Wide-character versions.
142 #define SPLITPATH (_wsplitpath)
143 #define MAKEPATH (_wmakepath)
144 #define GETSHORTPATHNAME ("GetShortPathNameW")
145 #else
146 // C/ASCII/ANSI versions.
147 #define SPLITPATH (_tsplitpath)
148 #define MAKEPATH (_tmakepath)
149 #define GETSHORTPATHNAME ("GetShortPathNameA")
150 #endif
153 // DialogOps derived from this class are "tabbed", and require special processing.
154 #undef TABBED_DIALOG_CLASS
155 #define TABBED_DIALOG_CLASS (CC_RUNTIME_CLASS(DialogTabOp))
158 // This is the window class name for push buttons.
159 #undef BUTTON_CLASS
160 #define BUTTON_CLASS (TEXT("BUTTON"))
163 // This determines the maximum time, in seconds, the app will wait on shutdown for the
164 // NT launcher to pass a quit message to the 16-bit help engine on Windows NT.
165 #define NTLAUNCHER_TIMEOUT (3)
169 ///////////////////////////////////////////////////////////////////////////////////////////
170 // Implementation.
172 // These store the full paths to the help-file
173 static String_256 achzHelpPath;
175 PORTNOTE("help", "Help function unimplemented!")
176 #if !defined(EXCLUDE_FROM_XARALX)
177 static TCHAR achzMoviesHelpPath[_MAX_PATH];
178 // static TCHAR achzStubPath[_MAX_PATH];
180 #ifdef STANDALONE
181 static TCHAR achzSpecPath[_MAX_PATH];
182 #endif
184 // This holds a handle to our message filter hook that traps F1 being pressed in dialogs.
185 static HHOOK hF1Hook = NULL;
186 #endif
188 // This is set to TRUE if we use the help at all. It reminds us to shut the help engine
189 // down when we quit.
190 static BOOL fHaveUsedHelp = FALSE;
192 #ifdef STANDALONE
193 static BOOL fHaveUsedSpecHelp = FALSE;
194 #endif
196 // This remembers that last format message resource ID passed to MakeMsg. If we have to
197 // provide help on an error box with a "error ID" of zero, we use this value instead,
198 // hoping that it contains the ID of the string that was used to format the message.
199 static UINT32 nNextMessageHelpContext = 0;
201 // This flag prevents a bad-install error message being shown repeatedly.
202 // static BOOL fNoNTLauncherMsgShown = FALSE;
206 /********************************************************************************************
207 > static DWORD LookupDialogTopic(LPCTSTR lpcszLookupClass, UINT32 nPageResID)
209 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
210 Created: 11/5/95
211 Inputs: lpcszLookupClass the run-time class name of the dialog to find
212 on-line help about. Can be null - in which case
213 we just check the PageID
214 nPageResID the resource ID of the current page, if we
215 want help on a 'tabbed' dialog
216 Returns: The index ID of the appropriate help topic, or zero if there isn't one.
217 Purpose: Private helper function that finds the help topic associated with "named"
218 dialogs, ie. those dialogs that are managed by a specialised C++ class, not
219 error or warning dialogs.
220 SeeAlso: HelpUser
221 ********************************************************************************************/
223 static DWORD LookupDialogTopic(LPCTSTR lpcszLookupClass, UINT32 nPageResID)
225 // Check we're not being passed junk.
226 // ERROR3IF(lpcszLookupClass == NULL, "No dialog class in LookupDialogTopic");
228 // Scan through the whole table.
229 for (DialogHelpTuple* ptpl = atplDialogTopics;
230 ptpl->lpcszDialogClass != NULL;
231 ptpl++)
233 // If the class-names & page ID's match then return the associated topic index.
234 if ((lpcszLookupClass == NULL || ::camStricmp(ptpl->lpcszDialogClass, lpcszLookupClass) == 0) &&
235 ptpl->nPageResID == nPageResID)
237 return ptpl->dwTopicIndex;
241 // Couldn't find such a dialog class.
242 return 0;
247 /********************************************************************************************
248 > static DWORD LookupOperationTopic(LPCTSTR lpcszOpName)
250 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
251 Created: 23/5/95
252 Inputs: lpcszOpName the OPTOKEN value of the Operation to look up help
254 Returns: The index ID of the appropriate help topic, or zero if there isn't one.
255 Purpose: Private helper function that finds the help topic associated with
256 Camelot operations, eg. those things exposed in menus!
257 SeeAlso: HelpUser
258 ********************************************************************************************/
260 static DWORD LookupOperationTopic(LPCTSTR lpcszOpName)
262 // Check for junk.
263 ERROR3IF(lpcszOpName == NULL, "No valid OpToken in LookupOperationTopic");
265 // Scan through the whole table.
266 for (OpHelpTuple* ptpl = atplOpTopics;
267 ptpl->lpcszToken != NULL;
268 ptpl++)
270 // If the token values match then we've found our help topic.
271 if (::camStricmp(ptpl->lpcszToken, lpcszOpName) == 0)
273 return ptpl->dwTopicIndex;
277 // No help topic, so sorry.
278 return 0;
283 /********************************************************************************************
284 > static DWORD LookupMessageTopic(UINT32 nMessageID)
286 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
287 Created: 11/5/95
288 Inputs: nMessageID the resource identifier of the message displayed in an
289 error or warning dialog
290 Returns: The index ID of the appropriate help topic, or zero if there isn't one.
291 Purpose: Private helper function that finds the help topic associated with the given
292 message, generally diaplayed in an error or warning dialog.
293 SeeAlso: HelpUser
294 ********************************************************************************************/
296 static DWORD LookupMessageTopic(UINT32 nMessageID)
298 #ifndef STANDALONE
299 // If we have no message ID then use the last one passed to MakeMsg.
300 if (nMessageID == 0) nMessageID = nNextMessageHelpContext;
302 // Start at the beginning of the table, naturally . . .
303 MsgHelpTuple* ptpl = atplMsgTopics;
304 DWORD dwHelpTopic;
306 // The table is terminated by a zero topic index.
307 while ((dwHelpTopic = *ptpl++) != 0)
309 // Each sub-table is terminated by a zero message ID.
310 while (*ptpl != 0)
312 // If one of the following matches the message then return the help topic.
313 if (*ptpl++ == nMessageID) return dwHelpTopic;
316 // Skip over the terminating message ID.
317 ptpl++;
319 #endif
320 // No help topic for this message, so sorry.
321 return 0;
325 /********************************************************************************************
326 > static BOOL FakeHelpButtonClick(HWND hwndDialog)
328 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
329 Created: 31/5/95
330 Inputs: hwndDialog the dialog box to fake a help button click within
331 Returns: TRUE if the fake click was possible, FALSE otherwise (maybe the dialog
332 doesn't have a help button?)
333 Purpose: Searches through the child windows of the given dialog, looking for a push
334 button with the label "Help". If it finds one then the routine posts a
335 "faked" click message for the button, so help is invoked.
336 SeeAlso: F1HookProc
337 ********************************************************************************************/
339 PORTNOTE("help", "Help function unimplemented!")
340 #if !defined(EXCLUDE_FROM_XARALX)
341 static BOOL FakeHelpButtonClick(HWND hwndDialog)
343 // Make sure we've been passed a genuine window handle.
344 if (!::IsWindow(hwndDialog)) return FALSE;
346 // Get the text of a "help" button.
347 String_256 strHelpLabel(_R(IDS_HELP));
349 // Search through all child windows of the given dialog, looking for a push-button
350 // with the label "Help".
351 for (HWND hwndChild = ::GetWindow(hwndDialog, GW_CHILD);
352 hwndChild != NULL;
353 hwndChild = ::GetWindow(hwndChild, GW_HWNDNEXT))
355 // Find out the window class of the child window.
356 TCHAR achzClassName[256];
357 ::GetClassName(hwndChild, achzClassName, 256);
359 // If it is a button then examine the label.
360 if (camStricmp(achzClassName, BUTTON_CLASS) == 0)
362 // It is a button. Get its label.
363 TCHAR achzButtonLabel[256];
364 ::GetWindowText(hwndChild, achzButtonLabel, 256);
366 // Does its label match the "help" label?
367 if (camStricmp(achzButtonLabel, strHelpLabel) == 0)
369 // It does! Fake a click on it and return.
370 return ::PostMessage(hwndDialog,
371 WM_COMMAND,
372 (WPARAM) MAKEWPARAM(::GetDlgCtrlID(hwndChild), BN_CLICKED),
373 (LPARAM) hwndChild);
378 // No help button found, can't do it.
379 return FALSE;
384 /********************************************************************************************
385 > static LRESULT CALLBACK EXPORT F1HookProc(INT32 nCode, WPARAM wParam, LPARAM lParam)
386 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
387 Created: 25/5/95
388 Inputs: nCode where the message was generated, eg. a menu, or a dialog
389 wParam (ignored)
390 lParam contains a pointer to a MSG structure describing the event
391 Returns: Whatever the next hook in the chain returns.
392 Purpose: Called when a message is generated within the app. Checks if the message
393 was from a dialog box, and if so checks if it is the F1 key being pressed.
394 If it is then we work out which dialog has the "focus" and simulate its
395 help button being clicked.
396 SeeAlso: InitUserHelp; DeInitUserHelp
397 ********************************************************************************************/
399 static LRESULT CALLBACK EXPORT F1HookProc(INT32 nCode, WPARAM wParam, LPARAM lParam)
401 // Check if it's the F1 key going down within a dialog box . . .
402 LPMSG lpmsg = (LPMSG) lParam;
403 BOOL fHandleOK = ::IsWindow(lpmsg->hwnd);
404 if (nCode == MSGF_DIALOGBOX && lpmsg->message == WM_KEYDOWN && lpmsg->wParam == CAMKEY(F1))
406 // Simulate the help button within the dialog being clicked, if there is one.
407 // Empirically I have discovered that the window handle contained within the
408 // message is that of the first child window in the dialog.
409 if (fHandleOK) FakeHelpButtonClick(::GetParent(lpmsg->hwnd));
412 // Pass this event on to the next hook proc if it's valid.
413 return (fHandleOK) ? ::CallNextHookEx(hF1Hook, nCode, wParam, lParam) : 0;
415 #endif
418 /********************************************************************************************
419 > static BOOL RunOilHelp(LPCTSTR lpcszHelpPath, UINT32 nCommand, DWORD dwData)
421 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
422 Created: 11/5/95
423 Inputs: lpcszHelpPath string containing the path to the helpfile to display.
424 nCommand the command identifier to pass to the help engine, eg
425 HELP_CONTEXT or HELP_CONTENTS.
426 dwData extra data to pass to the help engine, eg. the topic
427 index, or zero.
428 Returns: TRUE if the help engine was run successfully, FALSE otherwise.
429 Purpose: Private helper function that runs the system's help engine, whatever that
430 might be, passing the given command. On Windows this is WINHELP.EXE or
431 WINHLP32.EXE, on RISCOS it's get-the-manual-out time . . .
432 SeeAlso: HelpUser
433 ********************************************************************************************/
435 static BOOL RunOilHelp(LPCTSTR lpcszHelpPath, UINT32 nCommand, DWORD dwData)
437 #if !defined(EXCLUDE_FROM_XARALX)
438 // Firing up the help engine can take a while, so show an hour-glass cursor.
439 HCURSOR hOldCursor;
440 HCURSOR hBusyCursor = ::LoadCursor(NULL, _R(IDC_WAIT));
441 if (hBusyCursor != NULL) hOldCursor = ::SetCursor(hBusyCursor);
443 // We always pass the handle of the main-frame window as the "owning" window.
444 HWND hwndInvoker = GetMainFrame()->GetSafeHwnd();
445 #endif
447 // If we are running on a pure 32-bit platform such as Windows NT then we must fake
448 // the WinHelp() function, as we want the 16-bit engine to be run, not WINHLP32.EXE.
449 // The current help-file build includes references to 16-bit DLLs that seem to be
450 // almost too much for the 32-bit engine. We don't have to do this if we aren't
451 // running the engine to browse a file, but simply issuing a command, such as
452 // HELP_HELPONHELP.
453 BOOL fOk;
455 // Running under Chicago or Win32s, or the helpfile parameter is NULL, so run the
456 // "normal" engine. Here we should really "thunk" (translate) the 32-bit HWND
457 // to a 16-bit HWND, I think?
458 // TRACEUSER( "JustinF", _T("Help being invoked normally\n"));
461 fOk = TRUE;
462 if(nCommand != HELP_QUIT)
464 wxString strHelpFileName(lpcszHelpPath);
465 wxString Context = _T("");
466 if (dwData)
468 Context = PCTSTR(String_256( dwData ));
469 if (_T("") != Context)
470 // so that the string table contains a bit less, the ::/xarax/ and .htm
471 // are here, because they are common to every HTML help path.
472 strHelpFileName += _T("xarax/") + Context + _T(".htm");
475 CCamApp::LaunchWebBrowser( strHelpFileName );
478 #if !defined(EXCLUDE_FROM_XARALX)
479 // Get some slightly useful information if it all goes horribly wrong.
480 #ifdef _DEBUG
481 if (!fOk) TRACEUSER( "Ollie", _T("RunOilHelp failed - last error: %lu\n"),
482 (UINT32) ::GetLastError());
483 #endif
485 // Undo the hour-glass cursor and return a success code.
486 if (hBusyCursor != NULL) ::SetCursor(hOldCursor);
487 #endif
489 return fOk;
494 /********************************************************************************************
495 > BOOL MakeShortPath(LPTSTR lpszPath, size_t cchMaxLen)
497 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
498 Created: 2/6/95
499 Inputs: lpszPath the full path to shorten. The shortened version will be
500 "outputed" into this same buffer.
501 cchMaxLen the size of the above buffer
502 Outputs: lpszPath contains the shortened path
503 Returns: TRUE if successful, FALSE otherwise.
504 Purpose: Special function to work around an ommission in Win32s, which does not
505 include the GetShortPathName function, even though Win32s is supposed to
506 export ALL Win32 functions. This version does nothing under Win32s, which
507 shortens pathnames automatically (?), under other versions of Windows it
508 dynamically links to the function in the kernel32 library, thus avoiding
509 an explicit link to the function which would prevent the app loading.
510 Errors: -
511 SeeAlso: -
512 ********************************************************************************************/
514 BOOL MakeShortPath(LPTSTR lpszPath, size_t cchMaxLen)
516 PORTNOTETRACE("help", "Help function unimplemented!");
517 #if !defined(EXCLUDE_FROM_XARALX)
518 // Under Win32s we don't want to do this, because (i) Win32s does it anyway;
519 // and (ii) the bloody GetShortPathName function isn't supported because they
520 // forgot it (a serious bug, Mr Gates!)
521 if (IsWin32s() && !IsWin32c()) return TRUE;
523 // Now we have some aggro. Because GetShortPathName isn't recognised as a Win32
524 // function by Win32s, we must NOT have any explicit references to it in the program,
525 // or the app won't load under Win32s. Instead, we will try to dynamically link to it.
526 HMODULE hlib = ::GetModuleHandle(TEXT("KERNEL32"));
527 if (hlib == NULL)
529 TRACEUSER( "Ollie", _T("MakeShortPath: GetModuleHandle failed (error: %lu)\n"),
530 (UINT32) ::GetLastError());
531 return FALSE;
534 // OK, we've loaded the relevant library. Now try to link to the function it contains.
535 typedef DWORD (WINAPI *GSPNFUNC)(LPCTSTR, LPTSTR, DWORD);
536 GSPNFUNC lpfn = (GSPNFUNC) ::GetProcAddress(hlib, GETSHORTPATHNAME);
537 if (lpfn == NULL)
539 TRACEUSER( "Ollie", _T("MakeShortPath: GetProcAddress failed (error: %lu)\n"),
540 (UINT32) ::GetLastError());
541 return FALSE;
544 // Now call the GetShortPathName function and return a success code.
545 DWORD dwResult = (*lpfn)(lpszPath, lpszPath, cchMaxLen);
546 return dwResult != 0 && dwResult < cchMaxLen;
547 #else
548 return FALSE;
549 #endif
554 /********************************************************************************************
555 > static BOOL ShowHelp(UINT32 nCommand, DWORD dwData)
557 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
558 Created: 11/6/95
559 Inputs: nCommand the command to pass to the help engine, eg. HELP_CONTENTS
560 Returns: TRUE if successful.
561 Purpose: Called to display the given topic in the Xara Studio general help file.
562 Makes a note if help is run successfully that we have to shut it down when
563 we quit.
564 ********************************************************************************************/
566 static BOOL ShowHelp(UINT32 nCommand, DWORD dwData)
568 BOOL fResult = RunOilHelp(achzHelpPath, nCommand, dwData);
569 if (!fHaveUsedHelp && fResult) fHaveUsedHelp = TRUE;
570 return fResult;
576 ///////////////////////////////////////////////////////////////////////////////////////////
577 // Interface.
579 /********************************************************************************************
580 > BOOL HelpUser(const DialogOp& DlgOp)
582 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
583 Created: 11/5/95
584 Inputs: DlgOp reference to a (constant) dialog operation to display
585 help about
586 Returns: TRUE if help was successfully provided, FALSE if not.
587 Purpose: Public function that finds the help topic associated with the given dialog
588 operation and runs the system help engine to display the topic.
589 SeeAlso: RunOilHelp; LookupDialogTopic
590 ********************************************************************************************/
592 BOOL HelpUser(const DialogOp& DlgOp)
594 // Work out which page within the dialog is visible, if appropriate. We begin by
595 // assuming this isn't relevant.
596 UINT32 nPageResID = 0;
597 if (DlgOp.IsKindOf(TABBED_DIALOG_CLASS))
599 // Work out which is the active (top-most) page within the tabbed dialog.
600 wxWindow* pWnd = (wxWindow*) DlgOp.WindowID;
601 if (pWnd != NULL)
603 // We got the window handle, get its MFC CWnd analogue.
604 wxBookCtrlBase* pSheet = DialogManager::GetBookControl( pWnd );
605 if (pSheet != NULL)
607 // Ask it for the resource ID of its currently active page.
608 nPageResID = (UINT32) pSheet->GetCurrentPage()->GetId();
610 #ifdef _DEBUG
611 else
613 TRACEUSER( "Ollie", _T("Null OurPropSheet pointer in HelpUser\n"));
615 #endif
617 #ifdef _DEBUG
618 else
620 TRACEUSER( "Ollie", _T("Null DialogOp window handle in HelpUser\n"));
622 #endif
625 // Get the run-time class name etc of the dialog.
626 LPCTSTR lpcszDialogClass = DlgOp.GetRuntimeClass()->m_lpszClassName;
628 // Look-up the class name/page ID in our list of help topics. If we can't find it
629 // then we return a failure code.
630 DWORD dwHelpIndex = LookupDialogTopic(lpcszDialogClass, nPageResID);
631 if (dwHelpIndex == 0)
633 TRACEUSER( "Ollie", _T("Can't find help topic for %s dialog (page ID %lu)\n"),
634 (LPTSTR) lpcszDialogClass, (UINT32) nPageResID);
635 return FALSE;
638 // Show this topic in the help system and return a success code.
639 return ShowHelp(HELP_CONTEXT, dwHelpIndex);
644 /********************************************************************************************
645 > BOOL HelpUser(const CDialog& dlg)
647 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
648 Created: 11/5/95
649 Inputs: dlg the MFC dialog that requires help
650 Returns: TRUE if help was successfully provided, FALSE if not.
651 Purpose: Public function that finds the help topic associated with the given MFC
652 dialog and runs the system help engine to display the topic.
653 SeeAlso: RunOilHelp; LookupDialogTopic
654 ********************************************************************************************/
656 BOOL HelpUser(const wxDialog& dlg)
658 // Look-up the class name/page ID in our list of help topics. If we can't find it
659 // then we return a failure code.
660 DWORD dwHelpIndex = LookupDialogTopic(dlg.GetClassInfo()->GetClassName(), 0);
661 if (dwHelpIndex == 0)
663 TRACEUSER( "Ollie", _T("Can't find help topic for the %s MFC dialog\n"),
664 (LPCTSTR) dlg.GetClassInfo()->GetClassName());
665 return FALSE;
668 // Show this topic in the help system and return a success code.
669 return ShowHelp(HELP_CONTEXT, dwHelpIndex);
674 /********************************************************************************************
675 > BOOL HelpUser(const OpDescriptor& opdesc)
677 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
678 Created: 11/5/95
679 Inputs: opdesc the OpDescriptor of the Operation to provide help for
680 Returns: TRUE if help was successfully provided, FALSE if not.
681 Purpose: Public function that finds the help topic associated with the given
682 OpDescriptor and runs the system help engine to display the topic.
683 SeeAlso: RunOilHelp; LookupOperationTopic
684 ********************************************************************************************/
686 BOOL HelpUser(const OpDescriptor& opdesc)
688 // Check if a help topic is already recorded within the OpDescriptor. If it isn't
689 // then we will have to look it up instead.
691 // NB. all the help topic ID's within the OpDescriptors are wrong, so ignore them!
692 DWORD dwHelpIndex = ((OpDescriptor&) opdesc).GetHelpId();
693 if (dwHelpIndex == 0) dwHelpIndex = LookupOperationTopic(opdesc.Token);
695 DWORD dwHelpIndex = LookupOperationTopic(opdesc.Token);
696 if (dwHelpIndex == 0)
698 TRACEUSER( "Ollie", _T("Can't find help topic for the %s OpDescriptor\n"),
699 (LPCTSTR) opdesc.Token);
700 return FALSE;
703 // Show the topic we have found.
704 return ShowHelp(HELP_CONTEXT, dwHelpIndex);
709 /********************************************************************************************
710 > BOOL HelpUser(UINT32 nMessageID)
712 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
713 Created: 11/5/95
714 Inputs: nMessageID the resource identifier of the message to display
715 help about
716 Returns: TRUE if help was successfully provided, FALSE otherwise
717 Purpose: Public function that finds the help topic associated with the given
718 message and runs the system help engine to display the topic.
719 SeeAlso: RunOilHelp; LookupMessageTopic
720 ********************************************************************************************/
722 BOOL HelpUser(UINT32 nMessageID)
724 // Look-up the message ID in our list of help topics. If we can't find it
725 // then return a failure code.
726 DWORD dwHelpIndex = LookupMessageTopic(nMessageID);
727 if (dwHelpIndex == 0)
729 TRACEUSER( "Ollie", _T("Can't find help topic for message 0x%lX\n"),
730 (UINT32) nMessageID);
731 return FALSE;
734 // Show this topic in the help system and return a success code.
735 return ShowHelp(HELP_CONTEXT, dwHelpIndex);
738 /********************************************************************************************
740 > BOOL HelpUserPropertyPage(UINT32 PageID);
742 Author: Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
743 Created: 7/5/97
744 Inputs: PageID ResourceID of the currently active page
745 Returns: TRUE if help was successfully provided, FALSE otherwise
746 Purpose: Public function that finds the help topic associated with the given
747 property page. This is required due to the new way the tabbed dialogs work
748 (via MFC).
750 ********************************************************************************************/
752 BOOL HelpUserPropertyPage(UINT32 PageID)
754 DWORD dwHelpIndex = LookupDialogTopic(NULL, PageID);
755 return (HelpUserTopic(dwHelpIndex));
758 /********************************************************************************************
760 > BOOL HelpUserTopic(DWORD dwHelpIndex)
762 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
763 Created: 11/7/96
764 Inputs: nMessageID the resource identifier of the message to display
765 help about
766 Returns: TRUE if help was successfully provided, FALSE otherwise
767 Purpose: Public function that finds the help topic associated with the given
768 message and runs the system help engine to display the topic.
770 ********************************************************************************************/
772 BOOL HelpUserTopic(DWORD dwHelpIndex)
774 if (dwHelpIndex == 0)
775 return FALSE;
777 // Show this topic in the help system and return a success code.
778 return ShowHelp(HELP_CONTEXT, dwHelpIndex);
782 /********************************************************************************************
783 > BOOL _HelpUser(LPCTSTR lpcszClassName, UINT32 nSubTopic = 0)
785 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
786 Created: 23/5/95
787 Inputs: lpcszClassName the class name of the object to run help for
788 nSubTopic which sub-topic for the object to display
789 (by default, no sub-topic)
790 Returns: TRUE if the help system is started successfully.
791 Purpose: Public function that finds the help topic associated with the given
792 object and runs the system help engine to display it. This is a
793 "bodgey" direct-access function for invoking help in those tricky cases,
794 such as the print-setup dialog, that do not have any Camelot object
795 directly associated with them.
796 SeeAlso: HelpUser; LookupDialogTopic; RunOilHelp
797 ********************************************************************************************/
799 BOOL _HelpUser(LPCTSTR lpcszClassName, UINT32 nSubTopic /* = 0 */)
801 DWORD dwHelpIndex = LookupDialogTopic(lpcszClassName, nSubTopic);
802 if (dwHelpIndex == 0)
804 TRACEUSER( "Ollie", _T("Can't find raw help topic for %s (sub %lu)\n"),
805 lpcszClassName, nSubTopic);
806 return FALSE;
809 return ShowHelp(HELP_CONTEXT, dwHelpIndex);
814 /********************************************************************************************
815 > BOOL HelpContents()
817 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
818 Created: 12/5/95
819 Returns: TRUE if successful.
820 Purpose: Runs the system help engine, displaying the "Contents" page.
821 Errors: -
822 SeeAlso: HelpUser; HelpSearch; HelpUsingHelp
823 ********************************************************************************************/
825 BOOL HelpContents()
827 #ifndef STANDALONE
829 // If F1 was pressed, popup help in the context of the current tool. Use the tool's OpToken (of
830 // the form "TOOL<ToolId>") to look-up its help page. Fixes #10489
831 if (KeyPress::IsKeyPressed(CAMKEY(F1)))
833 String OpToken;
834 OpToken._MakeMsg( _T("TOOL%u"), Tool::GetCurrentID() );
835 DWORD dwHelpIndex = LookupOperationTopic(OpToken);
836 return ShowHelp(HELP_CONTEXT, dwHelpIndex);
839 return ShowHelp(HELP_FINDER, 0);
841 #else // STANDALONE
842 // On the viewer go directly to the contents page on all OS's
843 #ifdef WEBSTER
844 return ShowHelp(HELP_CONTEXT, _R(IDH_Contents));
845 #else //WEBSTER
846 return ShowHelp(HELP_CONTEXT, _R(IDH_Misc_Contents));
847 #endif // WEBSTER
848 #endif // STANDALONE
853 /********************************************************************************************
854 > BOOL HelpUsingHelp()
856 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
857 Created: 12/5/95
858 Returns: TRUE if successful.
859 Purpose: Runs the system help engine, displaying the system's instructions for
860 using it.
861 SeeAlso: HelpUser; HelpContents; HelpSearch
862 ********************************************************************************************/
864 BOOL HelpUsingHelp()
866 return RunOilHelp(NULL, HELP_HELPONHELP, 0);
871 /********************************************************************************************
872 > BOOL HelpUsingTools()
874 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
875 Created: 12/5/95
876 Returns: TRUE if successful.
877 Purpose: Runs the system help engine, displaying the help on tools.
878 SeeAlso: HelpUser; HelpContents; HelpSearch
879 ********************************************************************************************/
881 BOOL HelpUsingTools()
883 return ShowHelp(HELP_CONTEXT, _R(IDH_Misc_Tools));
888 /********************************************************************************************
889 > BOOL HelpUsingGalleries()
891 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
892 Created: 12/5/95
893 Returns: TRUE if successful.
894 Purpose: Runs the system help engine, displaying the help on galleries.
895 SeeAlso: HelpUser; HelpContents; HelpSearch
896 ********************************************************************************************/
898 BOOL HelpUsingGalleries()
900 return ShowHelp(HELP_CONTEXT, _R(IDH_Overview_Galleries));
905 /********************************************************************************************
906 > BOOL HelpOnlineDemos()
908 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
909 Created: 12/5/95
910 Returns: TRUE if successful.
911 Purpose: Runs the system help engine, displaying the on-line demos help page.
912 SeeAlso: HelpUser; HelpContents; HelpSearch
913 ********************************************************************************************/
915 BOOL HelpOnlineDemos()
917 PORTNOTETRACE("help", "Help function unimplemented!");
918 #if !defined(EXCLUDE_FROM_XARALX)
919 return RunOilHelp(achzMoviesHelpPath, 0, 0);
920 #else
921 return FALSE;
922 #endif
927 /********************************************************************************************
928 > BOOL HelpTechnicalSupport()
930 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
931 Created: 1/11/95
932 Returns: TRUE if successful.
933 Purpose: Runs the system help engine, displaying the tech support help page.
934 SeeAlso: HelpUser; HelpContents; HelpSearch
935 *******************************************************************************************/
937 BOOL HelpTechnicalSupport()
939 #ifdef WEBSTER
940 return FALSE;
941 #else
942 return ShowHelp(HELP_CONTEXT, _R(IDH_Misc_Tech_Support));
943 #endif
948 /********************************************************************************************
949 > BOOL CanHelpUser(UINT32 nMessageID)
951 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
952 Created: 11/5/95
953 Inputs: nMessageID the resource identifier of the message that is being
954 enquired about
955 Returns: TRUE if a help topic descrbing this message exists, FALSE otherwise.
956 Purpose: Public function to query whether a help topic exists for a given message.
957 Depending on this the caller may display a help button in a message box,
958 or may not etc.
959 SeeAlso: LookupMessageTopic; InformGeneral
960 ********************************************************************************************/
962 BOOL CanHelpUser(UINT32 nMessageID)
964 // Just return TRUE if a help topic for the message exists.
965 return LookupMessageTopic(nMessageID) != 0;
970 /********************************************************************************************
971 > void SetNextMsgHelpContext(UINT32 nMessageID)
973 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
974 Created: 15/5/95
975 Inputs: nMessageID the last message format string passed to MakeMsg
976 Purpose: Remembers the last format string passed to MakeMsg. If a call is made to
977 InformWarning, InformError etc and no string resource ID is passed then we
978 have a problem using the string resource as an index into the help file.
979 This remembers that last one, which we use if the "error ID" is zero.
980 SeeAlso: StringBase::MakeMsg
981 ********************************************************************************************/
983 void SetNextMsgHelpContext(UINT32 nMessageID)
985 nNextMessageHelpContext = nMessageID;
986 //TRACEUSER( "Andy", _T("\tSetNextMsgHelpContext(%d)\n"), nMessageID);
991 /********************************************************************************************
992 > UINT32 GetNextMsgHelpContext()
994 Author: Andy_Hills (Xara Group Ltd) <camelotdev@xara.com>
995 Created: 22/11/00
996 Inputs: none
997 Returns: help context
998 Purpose: Gets the last help context set by SetNextMsgHelpContext
999 SeeAlso: used by ScreenView::OnActivateView
1000 ********************************************************************************************/
1002 UINT32 GetNextMsgHelpContext()
1004 return nNextMessageHelpContext;
1009 /********************************************************************************************
1010 > BOOL InitUserHelp()
1012 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
1013 Created: 11/5/95
1014 Returns: TRUE if successful.
1015 Purpose: Initialises the help system. This should generally be called before just
1016 about everything else, so help is available for startup problems.
1017 SeeAlso: DeInitUserHelp
1018 ********************************************************************************************/
1020 // Forward references to helper functions
1021 BOOL InitHelpPath(BOOL bMainHelp);
1022 BOOL HelpFileExists(LPTSTR FileName);
1024 BOOL InitUserHelp()
1026 #if !defined(EXCLUDE_FROM_XARALX)
1027 // If we have any deferred file copies, deal with them now...
1028 HelpDownloadOp::DoDeferredFileCopy();
1029 #endif
1031 // init main help file:
1032 BOOL bOK = InitHelpPath(TRUE);
1034 // init movies help file
1035 bOK = bOK && InitHelpPath(FALSE);
1037 #if !defined(EXCLUDE_FROM_XARALX)
1038 // Install a message filter hook to trap F1 being pressed in dialogs etc. We don't need
1039 // one for menus as our "custom menu code" (ha ha ha) does this already.
1040 hF1Hook = ::SetWindowsHookEx(WH_MSGFILTER, F1HookProc, NULL, ::GetCurrentThreadId());
1041 ERROR3IF(hF1Hook == NULL, "Couldn't set F1 key hook in InitUserHelp");
1043 // Success!?!
1044 return hF1Hook != NULL;
1045 #else
1046 return bOK;
1047 #endif
1051 // --------------------------------------------------------------------------------
1052 BOOL InitHelpPath(BOOL bMainHelp)
1054 if( !bMainHelp )
1056 PORTNOTETRACE("help", "InitHelpPath does not support Movie path yet");
1059 // Get the locale id
1060 wxString strLocale( setlocale( LC_MESSAGES, NULL ), wxConvUTF8 );
1061 INT32 ordSep = strLocale.Find( _T('_' ) );
1062 if ( -1 != ordSep )
1063 strLocale = strLocale.Left( ordSep );
1064 TRACEUSER( "jlh92", _T("Locale = %s\n"), PCTSTR(strLocale) );
1066 // Locale C is considered a synonym for en
1067 if( strLocale == _T("C") )
1068 strLocale = _T("en");
1070 // Check the help dir exists, if not bomb out
1071 wxString strHelpPath( (PCTSTR)CCamApp::GetResourceDirectory() );
1072 strHelpPath += _T("/doc/");
1073 TRACEUSER( "jlh92", _T("Using filter discovery directory \"%s\"\n"), PCTSTR(strHelpPath + strLocale) );
1074 if( wxDir::Exists( strHelpPath + strLocale ) )
1075 strHelpPath += strLocale + _T("/");
1076 else
1078 if( wxDir::Exists( strHelpPath + _T("en") ) )
1079 strHelpPath += _T("en/");
1080 #if defined(_DEBUG)
1081 else
1083 // We'll try default location under debug to make life easier
1084 strHelpPath = _T("/usr/share/xaralx/doc/en/");
1085 TRACEUSER( "jlh92", _T("Try = \"%s\"\n"), PCTSTR(strHelpPath) );
1087 #endif
1090 achzHelpPath = strHelpPath;
1091 PORTNOTE( "help", "We should check and report non-existant help directory at some point" )
1092 return TRUE; // wxDir::Exists( strHelpPath );
1096 /********************************************************************************************
1097 > BOOL DeInitUserHelp()
1099 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
1100 Created: 11/5/95
1101 Returns: TRUE if successful.
1102 Purpose: Shuts down the help system. This should be called as late as possible, so
1103 help is available for app shut-down problems. Note that MFC will call
1104 WinHelp(HELP_QUIT) for us when the main frame window is destroyed.
1105 SeeAlso: InitUserHelp
1106 ********************************************************************************************/
1108 BOOL DeInitUserHelp()
1110 PORTNOTETRACE("help", "Help function unimplemented!");
1111 #if !defined(EXCLUDE_FROM_XARALX)
1112 // Tell the help engine we've finished using the help file(s).
1113 // NB. KNWON BUG: this doesn't do the job on Windows NT, leaving the helpfiles open.
1114 // As yet I have no idea why - it is as per the docs and works on Win32s & Chicago.
1115 if (fHaveUsedHelp)
1117 TRACEUSER( "Ollie", _T("Closing general helpfile\n"));
1118 ShowHelp(HELP_QUIT, 0);
1121 #ifdef STANDALONE
1122 // Same if we ran the special helpfile.
1123 if (fHaveUsedSpecHelp)
1125 TRACEUSER( "Ollie", _T("Closing special helpfile\n"));
1126 RunOilHelp(achzSpecPath, HELP_QUIT, 0);
1128 #endif
1130 // Remove our F1 message hook.
1131 return hF1Hook == NULL || ::UnhookWindowsHookEx(hF1Hook);
1132 #else
1133 return TRUE;
1134 #endif
1139 /********************************************************************************************
1140 > BOOL ShowHelpSpec()
1142 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
1143 Created: 11/6/95
1144 Returns: TRUE if successful.
1145 Purpose: Used by the viewer to display the Xara Studio special help file. Makes a
1146 note if help is run successfully that we have to shut it down when we
1147 quit.
1148 ********************************************************************************************/
1150 #ifdef STANDALONE
1152 BOOL ShowHelpSpec()
1154 PORTNOTETRACE("help", "Help function unimplemented!");
1155 #if !defined(EXCLUDE_FROM_XARALX)
1156 BOOL fResult = RunOilHelp(achzSpecPath, HELP_CONTENTS, 0);
1157 if (!fHaveUsedSpecHelp && fResult) fHaveUsedSpecHelp = TRUE;
1158 return fResult;
1159 #else
1160 return FALSE;
1161 #endif
1164 #endif // STANDALONE