00001 // $Id: helpuser.cpp 1729 2006-08-30 12:48:48Z luke $ 00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00003 ================================XARAHEADERSTART=========================== 00004 00005 Xara LX, a vector drawing and manipulation program. 00006 Copyright (C) 1993-2006 Xara Group Ltd. 00007 Copyright on certain contributions may be held in joint with their 00008 respective authors. See AUTHORS file for details. 00009 00010 LICENSE TO USE AND MODIFY SOFTWARE 00011 ---------------------------------- 00012 00013 This file is part of Xara LX. 00014 00015 Xara LX is free software; you can redistribute it and/or modify it 00016 under the terms of the GNU General Public License version 2 as published 00017 by the Free Software Foundation. 00018 00019 Xara LX and its component source files are distributed in the hope 00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00022 See the GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with Xara LX (see the file GPL in the root directory of the 00026 distribution); if not, write to the Free Software Foundation, Inc., 51 00027 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00028 00029 00030 ADDITIONAL RIGHTS 00031 ----------------- 00032 00033 Conditional upon your continuing compliance with the GNU General Public 00034 License described above, Xara Group Ltd grants to you certain additional 00035 rights. 00036 00037 The additional rights are to use, modify, and distribute the software 00038 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00039 library and any other such library that any version of Xara LX relased 00040 by Xara Group Ltd requires in order to compile and execute, including 00041 the static linking of that library to XaraLX. In the case of the 00042 "CDraw" library, you may satisfy obligation under the GNU General Public 00043 License to provide source code by providing a binary copy of the library 00044 concerned and a copy of the license accompanying it. 00045 00046 Nothing in this section restricts any of the rights you have under 00047 the GNU General Public License. 00048 00049 00050 SCOPE OF LICENSE 00051 ---------------- 00052 00053 This license applies to this program (XaraLX) and its constituent source 00054 files only, and does not necessarily apply to other Xara products which may 00055 in part share the same code base, and are subject to their own licensing 00056 terms. 00057 00058 This license does not apply to files in the wxXtra directory, which 00059 are built into a separate library, and are subject to the wxWindows 00060 license contained within that directory in the file "WXXTRA-LICENSE". 00061 00062 This license does not apply to the binary libraries (if any) within 00063 the "libs" directory, which are subject to a separate license contained 00064 within that directory in the file "LIBS-LICENSE". 00065 00066 00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00068 ---------------------------------------------- 00069 00070 Subject to the terms of the GNU Public License (see above), you are 00071 free to do whatever you like with your modifications. However, you may 00072 (at your option) wish contribute them to Xara's source tree. You can 00073 find details of how to do this at: 00074 http://www.xaraxtreme.org/developers/ 00075 00076 Prior to contributing your modifications, you will need to complete our 00077 contributor agreement. This can be found at: 00078 http://www.xaraxtreme.org/developers/contribute/ 00079 00080 Please note that Xara will not accept modifications which modify any of 00081 the text between the start and end of this header (marked 00082 XARAHEADERSTART and XARAHEADEREND). 00083 00084 00085 MARKS 00086 ----- 00087 00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00089 designs are registered or unregistered trademarks, design-marks, and/or 00090 service marks of Xara Group Ltd. All rights in these marks are reserved. 00091 00092 00093 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00094 http://www.xara.com/ 00095 00096 =================================XARAHEADEREND============================ 00097 */ 00098 /* 00099 00100 helpuser.cpp 00101 00102 Routines to invoke the platform's help system for a given Camelot object or 00103 topic reference. 00104 00105 */ 00106 00107 #include "camtypes.h" 00108 00109 //#include <io.h> // for FileExists 00110 #include <stdlib.h> 00111 #include "camelot.h" 00112 //#include "mainfrm.h" 00113 //#include "dialogop.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00114 //#include "errorbox.h" 00115 00116 #include "helpuser.h" 00117 #include "helptabs.h" 00118 //#include "xshelpid.h" // for the _R(IDH_TEST_PAGE) 00119 #include "product.h" // for the PRODUCT_BASENAME 00120 //#include "resdll.h" 00121 //#include "helpdownload.h" 00122 00123 //#include "simon.h" // for the _R(IDS_HELP) button label string 00124 00125 //#include <htmlhelp.h> // for html help 00126 #include "keypress.h" 00127 00128 00129 // Code version. 00130 DECLARE_SOURCE("$Revision: 1729 $"); 00131 00132 00133 // We need to use the correct filename parsing functions, depending on whether we are 00134 // a C/ASCII/ANSI or a Unicode build. Note that under Win32 all exported functions 00135 // are specified in the ANSI character set, even in Unicode builds. 00136 #undef SPLITPATH 00137 #undef MAKEPATH 00138 #undef GETSHORTPATHNAME 00139 00140 #ifdef UNICODE 00141 // Wide-character versions. 00142 #define SPLITPATH (_wsplitpath) 00143 #define MAKEPATH (_wmakepath) 00144 #define GETSHORTPATHNAME ("GetShortPathNameW") 00145 #else 00146 // C/ASCII/ANSI versions. 00147 #define SPLITPATH (_tsplitpath) 00148 #define MAKEPATH (_tmakepath) 00149 #define GETSHORTPATHNAME ("GetShortPathNameA") 00150 #endif 00151 00152 00153 // DialogOps derived from this class are "tabbed", and require special processing. 00154 #undef TABBED_DIALOG_CLASS 00155 #define TABBED_DIALOG_CLASS (CC_RUNTIME_CLASS(DialogTabOp)) 00156 00157 00158 // This is the window class name for push buttons. 00159 #undef BUTTON_CLASS 00160 #define BUTTON_CLASS (TEXT("BUTTON")) 00161 00162 00163 // This determines the maximum time, in seconds, the app will wait on shutdown for the 00164 // NT launcher to pass a quit message to the 16-bit help engine on Windows NT. 00165 #define NTLAUNCHER_TIMEOUT (3) 00166 00167 00168 00170 // Implementation. 00171 00172 // These store the full paths to the help-file 00173 static String_256 achzHelpPath; 00174 00175 PORTNOTE("help", "Help function unimplemented!") 00176 #if !defined(EXCLUDE_FROM_XARALX) 00177 static TCHAR achzMoviesHelpPath[_MAX_PATH]; 00178 // static TCHAR achzStubPath[_MAX_PATH]; 00179 00180 #ifdef STANDALONE 00181 static TCHAR achzSpecPath[_MAX_PATH]; 00182 #endif 00183 00184 // This holds a handle to our message filter hook that traps F1 being pressed in dialogs. 00185 static HHOOK hF1Hook = NULL; 00186 #endif 00187 00188 // This is set to TRUE if we use the help at all. It reminds us to shut the help engine 00189 // down when we quit. 00190 static BOOL fHaveUsedHelp = FALSE; 00191 00192 #ifdef STANDALONE 00193 static BOOL fHaveUsedSpecHelp = FALSE; 00194 #endif 00195 00196 // This remembers that last format message resource ID passed to MakeMsg. If we have to 00197 // provide help on an error box with a "error ID" of zero, we use this value instead, 00198 // hoping that it contains the ID of the string that was used to format the message. 00199 static UINT32 nNextMessageHelpContext = 0; 00200 00201 // This flag prevents a bad-install error message being shown repeatedly. 00202 // static BOOL fNoNTLauncherMsgShown = FALSE; 00203 00204 00205 00206 /******************************************************************************************** 00207 > static DWORD LookupDialogTopic(LPCTSTR lpcszLookupClass, UINT32 nPageResID) 00208 00209 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00210 Created: 11/5/95 00211 Inputs: lpcszLookupClass the run-time class name of the dialog to find 00212 on-line help about. Can be null - in which case 00213 we just check the PageID 00214 nPageResID the resource ID of the current page, if we 00215 want help on a 'tabbed' dialog 00216 Returns: The index ID of the appropriate help topic, or zero if there isn't one. 00217 Purpose: Private helper function that finds the help topic associated with "named" 00218 dialogs, ie. those dialogs that are managed by a specialised C++ class, not 00219 error or warning dialogs. 00220 SeeAlso: HelpUser 00221 ********************************************************************************************/ 00222 00223 static DWORD LookupDialogTopic(LPCTSTR lpcszLookupClass, UINT32 nPageResID) 00224 { 00225 // Check we're not being passed junk. 00226 // ERROR3IF(lpcszLookupClass == NULL, "No dialog class in LookupDialogTopic"); 00227 00228 // Scan through the whole table. 00229 for (DialogHelpTuple* ptpl = atplDialogTopics; 00230 ptpl->lpcszDialogClass != NULL; 00231 ptpl++) 00232 { 00233 // If the class-names & page ID's match then return the associated topic index. 00234 if ((lpcszLookupClass == NULL || ::camStricmp(ptpl->lpcszDialogClass, lpcszLookupClass) == 0) && 00235 ptpl->nPageResID == nPageResID) 00236 { 00237 return ptpl->dwTopicIndex; 00238 } 00239 } 00240 00241 // Couldn't find such a dialog class. 00242 return 0; 00243 } 00244 00245 00246 00247 /******************************************************************************************** 00248 > static DWORD LookupOperationTopic(LPCTSTR lpcszOpName) 00249 00250 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00251 Created: 23/5/95 00252 Inputs: lpcszOpName the OPTOKEN value of the Operation to look up help 00253 for 00254 Returns: The index ID of the appropriate help topic, or zero if there isn't one. 00255 Purpose: Private helper function that finds the help topic associated with 00256 Camelot operations, eg. those things exposed in menus! 00257 SeeAlso: HelpUser 00258 ********************************************************************************************/ 00259 00260 static DWORD LookupOperationTopic(LPCTSTR lpcszOpName) 00261 { 00262 // Check for junk. 00263 ERROR3IF(lpcszOpName == NULL, "No valid OpToken in LookupOperationTopic"); 00264 00265 // Scan through the whole table. 00266 for (OpHelpTuple* ptpl = atplOpTopics; 00267 ptpl->lpcszToken != NULL; 00268 ptpl++) 00269 { 00270 // If the token values match then we've found our help topic. 00271 if (::camStricmp(ptpl->lpcszToken, lpcszOpName) == 0) 00272 { 00273 return ptpl->dwTopicIndex; 00274 } 00275 } 00276 00277 // No help topic, so sorry. 00278 return 0; 00279 } 00280 00281 00282 00283 /******************************************************************************************** 00284 > static DWORD LookupMessageTopic(UINT32 nMessageID) 00285 00286 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00287 Created: 11/5/95 00288 Inputs: nMessageID the resource identifier of the message displayed in an 00289 error or warning dialog 00290 Returns: The index ID of the appropriate help topic, or zero if there isn't one. 00291 Purpose: Private helper function that finds the help topic associated with the given 00292 message, generally diaplayed in an error or warning dialog. 00293 SeeAlso: HelpUser 00294 ********************************************************************************************/ 00295 00296 static DWORD LookupMessageTopic(UINT32 nMessageID) 00297 { 00298 #ifndef STANDALONE 00299 // If we have no message ID then use the last one passed to MakeMsg. 00300 if (nMessageID == 0) nMessageID = nNextMessageHelpContext; 00301 00302 // Start at the beginning of the table, naturally . . . 00303 MsgHelpTuple* ptpl = atplMsgTopics; 00304 DWORD dwHelpTopic; 00305 00306 // The table is terminated by a zero topic index. 00307 while ((dwHelpTopic = *ptpl++) != 0) 00308 { 00309 // Each sub-table is terminated by a zero message ID. 00310 while (*ptpl != 0) 00311 { 00312 // If one of the following matches the message then return the help topic. 00313 if (*ptpl++ == nMessageID) return dwHelpTopic; 00314 } 00315 00316 // Skip over the terminating message ID. 00317 ptpl++; 00318 } 00319 #endif 00320 // No help topic for this message, so sorry. 00321 return 0; 00322 } 00323 00324 00325 /******************************************************************************************** 00326 > static BOOL FakeHelpButtonClick(HWND hwndDialog) 00327 00328 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00329 Created: 31/5/95 00330 Inputs: hwndDialog the dialog box to fake a help button click within 00331 Returns: TRUE if the fake click was possible, FALSE otherwise (maybe the dialog 00332 doesn't have a help button?) 00333 Purpose: Searches through the child windows of the given dialog, looking for a push 00334 button with the label "Help". If it finds one then the routine posts a 00335 "faked" click message for the button, so help is invoked. 00336 SeeAlso: F1HookProc 00337 ********************************************************************************************/ 00338 00339 PORTNOTE("help", "Help function unimplemented!") 00340 #if !defined(EXCLUDE_FROM_XARALX) 00341 static BOOL FakeHelpButtonClick(HWND hwndDialog) 00342 { 00343 // Make sure we've been passed a genuine window handle. 00344 if (!::IsWindow(hwndDialog)) return FALSE; 00345 00346 // Get the text of a "help" button. 00347 String_256 strHelpLabel(_R(IDS_HELP)); 00348 00349 // Search through all child windows of the given dialog, looking for a push-button 00350 // with the label "Help". 00351 for (HWND hwndChild = ::GetWindow(hwndDialog, GW_CHILD); 00352 hwndChild != NULL; 00353 hwndChild = ::GetWindow(hwndChild, GW_HWNDNEXT)) 00354 { 00355 // Find out the window class of the child window. 00356 TCHAR achzClassName[256]; 00357 ::GetClassName(hwndChild, achzClassName, 256); 00358 00359 // If it is a button then examine the label. 00360 if (camStricmp(achzClassName, BUTTON_CLASS) == 0) 00361 { 00362 // It is a button. Get its label. 00363 TCHAR achzButtonLabel[256]; 00364 ::GetWindowText(hwndChild, achzButtonLabel, 256); 00365 00366 // Does its label match the "help" label? 00367 if (camStricmp(achzButtonLabel, strHelpLabel) == 0) 00368 { 00369 // It does! Fake a click on it and return. 00370 return ::PostMessage(hwndDialog, 00371 WM_COMMAND, 00372 (WPARAM) MAKEWPARAM(::GetDlgCtrlID(hwndChild), BN_CLICKED), 00373 (LPARAM) hwndChild); 00374 } 00375 } 00376 } 00377 00378 // No help button found, can't do it. 00379 return FALSE; 00380 } 00381 00382 00383 00384 /******************************************************************************************** 00385 > static LRESULT CALLBACK EXPORT F1HookProc(INT32 nCode, WPARAM wParam, LPARAM lParam) 00386 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00387 Created: 25/5/95 00388 Inputs: nCode where the message was generated, eg. a menu, or a dialog 00389 wParam (ignored) 00390 lParam contains a pointer to a MSG structure describing the event 00391 Returns: Whatever the next hook in the chain returns. 00392 Purpose: Called when a message is generated within the app. Checks if the message 00393 was from a dialog box, and if so checks if it is the F1 key being pressed. 00394 If it is then we work out which dialog has the "focus" and simulate its 00395 help button being clicked. 00396 SeeAlso: InitUserHelp; DeInitUserHelp 00397 ********************************************************************************************/ 00398 00399 static LRESULT CALLBACK EXPORT F1HookProc(INT32 nCode, WPARAM wParam, LPARAM lParam) 00400 { 00401 // Check if it's the F1 key going down within a dialog box . . . 00402 LPMSG lpmsg = (LPMSG) lParam; 00403 BOOL fHandleOK = ::IsWindow(lpmsg->hwnd); 00404 if (nCode == MSGF_DIALOGBOX && lpmsg->message == WM_KEYDOWN && lpmsg->wParam == CAMKEY(F1)) 00405 { 00406 // Simulate the help button within the dialog being clicked, if there is one. 00407 // Empirically I have discovered that the window handle contained within the 00408 // message is that of the first child window in the dialog. 00409 if (fHandleOK) FakeHelpButtonClick(::GetParent(lpmsg->hwnd)); 00410 } 00411 00412 // Pass this event on to the next hook proc if it's valid. 00413 return (fHandleOK) ? ::CallNextHookEx(hF1Hook, nCode, wParam, lParam) : 0; 00414 } 00415 #endif 00416 00417 00418 /******************************************************************************************** 00419 > static BOOL RunOilHelp(LPCTSTR lpcszHelpPath, UINT32 nCommand, DWORD dwData) 00420 00421 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00422 Created: 11/5/95 00423 Inputs: lpcszHelpPath string containing the path to the helpfile to display. 00424 nCommand the command identifier to pass to the help engine, eg 00425 HELP_CONTEXT or HELP_CONTENTS. 00426 dwData extra data to pass to the help engine, eg. the topic 00427 index, or zero. 00428 Returns: TRUE if the help engine was run successfully, FALSE otherwise. 00429 Purpose: Private helper function that runs the system's help engine, whatever that 00430 might be, passing the given command. On Windows this is WINHELP.EXE or 00431 WINHLP32.EXE, on RISCOS it's get-the-manual-out time . . . 00432 SeeAlso: HelpUser 00433 ********************************************************************************************/ 00434 00435 static BOOL RunOilHelp(LPCTSTR lpcszHelpPath, UINT32 nCommand, DWORD dwData) 00436 { 00437 #if !defined(EXCLUDE_FROM_XARALX) 00438 // Firing up the help engine can take a while, so show an hour-glass cursor. 00439 HCURSOR hOldCursor; 00440 HCURSOR hBusyCursor = ::LoadCursor(NULL, _R(IDC_WAIT)); 00441 if (hBusyCursor != NULL) hOldCursor = ::SetCursor(hBusyCursor); 00442 00443 // We always pass the handle of the main-frame window as the "owning" window. 00444 HWND hwndInvoker = GetMainFrame()->GetSafeHwnd(); 00445 #endif 00446 00447 // If we are running on a pure 32-bit platform such as Windows NT then we must fake 00448 // the WinHelp() function, as we want the 16-bit engine to be run, not WINHLP32.EXE. 00449 // The current help-file build includes references to 16-bit DLLs that seem to be 00450 // almost too much for the 32-bit engine. We don't have to do this if we aren't 00451 // running the engine to browse a file, but simply issuing a command, such as 00452 // HELP_HELPONHELP. 00453 BOOL fOk; 00454 00455 // Running under Chicago or Win32s, or the helpfile parameter is NULL, so run the 00456 // "normal" engine. Here we should really "thunk" (translate) the 32-bit HWND 00457 // to a 16-bit HWND, I think? 00458 // TRACEUSER( "JustinF", _T("Help being invoked normally\n")); 00459 00460 00461 fOk = TRUE; 00462 if(nCommand != HELP_QUIT) 00463 { 00464 wxString strHelpFileName(lpcszHelpPath); 00465 wxString Context = _T(""); 00466 if (dwData) 00467 { 00468 Context = PCTSTR(String_256( dwData )); 00469 if (_T("") != Context) 00470 // so that the string table contains a bit less, the ::/xarax/ and .htm 00471 // are here, because they are common to every HTML help path. 00472 strHelpFileName += _T("xarax/") + Context + _T(".htm"); 00473 } 00474 00475 CCamApp::LaunchWebBrowser( strHelpFileName ); 00476 } 00477 00478 #if !defined(EXCLUDE_FROM_XARALX) 00479 // Get some slightly useful information if it all goes horribly wrong. 00480 #ifdef _DEBUG 00481 if (!fOk) TRACEUSER( "Ollie", _T("RunOilHelp failed - last error: %lu\n"), 00482 (UINT32) ::GetLastError()); 00483 #endif 00484 00485 // Undo the hour-glass cursor and return a success code. 00486 if (hBusyCursor != NULL) ::SetCursor(hOldCursor); 00487 #endif 00488 00489 return fOk; 00490 } 00491 00492 00493 00494 /******************************************************************************************** 00495 > BOOL MakeShortPath(LPTSTR lpszPath, size_t cchMaxLen) 00496 00497 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00498 Created: 2/6/95 00499 Inputs: lpszPath the full path to shorten. The shortened version will be 00500 "outputed" into this same buffer. 00501 cchMaxLen the size of the above buffer 00502 Outputs: lpszPath contains the shortened path 00503 Returns: TRUE if successful, FALSE otherwise. 00504 Purpose: Special function to work around an ommission in Win32s, which does not 00505 include the GetShortPathName function, even though Win32s is supposed to 00506 export ALL Win32 functions. This version does nothing under Win32s, which 00507 shortens pathnames automatically (?), under other versions of Windows it 00508 dynamically links to the function in the kernel32 library, thus avoiding 00509 an explicit link to the function which would prevent the app loading. 00510 Errors: - 00511 SeeAlso: - 00512 ********************************************************************************************/ 00513 00514 BOOL MakeShortPath(LPTSTR lpszPath, size_t cchMaxLen) 00515 { 00516 PORTNOTETRACE("help", "Help function unimplemented!"); 00517 #if !defined(EXCLUDE_FROM_XARALX) 00518 // Under Win32s we don't want to do this, because (i) Win32s does it anyway; 00519 // and (ii) the bloody GetShortPathName function isn't supported because they 00520 // forgot it (a serious bug, Mr Gates!) 00521 if (IsWin32s() && !IsWin32c()) return TRUE; 00522 00523 // Now we have some aggro. Because GetShortPathName isn't recognised as a Win32 00524 // function by Win32s, we must NOT have any explicit references to it in the program, 00525 // or the app won't load under Win32s. Instead, we will try to dynamically link to it. 00526 HMODULE hlib = ::GetModuleHandle(TEXT("KERNEL32")); 00527 if (hlib == NULL) 00528 { 00529 TRACEUSER( "Ollie", _T("MakeShortPath: GetModuleHandle failed (error: %lu)\n"), 00530 (UINT32) ::GetLastError()); 00531 return FALSE; 00532 } 00533 00534 // OK, we've loaded the relevant library. Now try to link to the function it contains. 00535 typedef DWORD (WINAPI *GSPNFUNC)(LPCTSTR, LPTSTR, DWORD); 00536 GSPNFUNC lpfn = (GSPNFUNC) ::GetProcAddress(hlib, GETSHORTPATHNAME); 00537 if (lpfn == NULL) 00538 { 00539 TRACEUSER( "Ollie", _T("MakeShortPath: GetProcAddress failed (error: %lu)\n"), 00540 (UINT32) ::GetLastError()); 00541 return FALSE; 00542 } 00543 00544 // Now call the GetShortPathName function and return a success code. 00545 DWORD dwResult = (*lpfn)(lpszPath, lpszPath, cchMaxLen); 00546 return dwResult != 0 && dwResult < cchMaxLen; 00547 #else 00548 return FALSE; 00549 #endif 00550 } 00551 00552 00553 00554 /******************************************************************************************** 00555 > static BOOL ShowHelp(UINT32 nCommand, DWORD dwData) 00556 00557 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00558 Created: 11/6/95 00559 Inputs: nCommand the command to pass to the help engine, eg. HELP_CONTENTS 00560 Returns: TRUE if successful. 00561 Purpose: Called to display the given topic in the Xara Studio general help file. 00562 Makes a note if help is run successfully that we have to shut it down when 00563 we quit. 00564 ********************************************************************************************/ 00565 00566 static BOOL ShowHelp(UINT32 nCommand, DWORD dwData) 00567 { 00568 BOOL fResult = RunOilHelp(achzHelpPath, nCommand, dwData); 00569 if (!fHaveUsedHelp && fResult) fHaveUsedHelp = TRUE; 00570 return fResult; 00571 } 00572 00573 00574 00575 00577 // Interface. 00578 00579 /******************************************************************************************** 00580 > BOOL HelpUser(const DialogOp& DlgOp) 00581 00582 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00583 Created: 11/5/95 00584 Inputs: DlgOp reference to a (constant) dialog operation to display 00585 help about 00586 Returns: TRUE if help was successfully provided, FALSE if not. 00587 Purpose: Public function that finds the help topic associated with the given dialog 00588 operation and runs the system help engine to display the topic. 00589 SeeAlso: RunOilHelp; LookupDialogTopic 00590 ********************************************************************************************/ 00591 00592 BOOL HelpUser(const DialogOp& DlgOp) 00593 { 00594 // Work out which page within the dialog is visible, if appropriate. We begin by 00595 // assuming this isn't relevant. 00596 UINT32 nPageResID = 0; 00597 if (DlgOp.IsKindOf(TABBED_DIALOG_CLASS)) 00598 { 00599 // Work out which is the active (top-most) page within the tabbed dialog. 00600 wxWindow* pWnd = (wxWindow*) DlgOp.WindowID; 00601 if (pWnd != NULL) 00602 { 00603 // We got the window handle, get its MFC CWnd analogue. 00604 wxBookCtrlBase* pSheet = DialogManager::GetBookControl( pWnd ); 00605 if (pSheet != NULL) 00606 { 00607 // Ask it for the resource ID of its currently active page. 00608 nPageResID = (UINT32) pSheet->GetCurrentPage()->GetId(); 00609 } 00610 #ifdef _DEBUG 00611 else 00612 { 00613 TRACEUSER( "Ollie", _T("Null OurPropSheet pointer in HelpUser\n")); 00614 } 00615 #endif 00616 } 00617 #ifdef _DEBUG 00618 else 00619 { 00620 TRACEUSER( "Ollie", _T("Null DialogOp window handle in HelpUser\n")); 00621 } 00622 #endif 00623 } 00624 00625 // Get the run-time class name etc of the dialog. 00626 LPCTSTR lpcszDialogClass = DlgOp.GetRuntimeClass()->m_lpszClassName; 00627 00628 // Look-up the class name/page ID in our list of help topics. If we can't find it 00629 // then we return a failure code. 00630 DWORD dwHelpIndex = LookupDialogTopic(lpcszDialogClass, nPageResID); 00631 if (dwHelpIndex == 0) 00632 { 00633 TRACEUSER( "Ollie", _T("Can't find help topic for %s dialog (page ID %lu)\n"), 00634 (LPTSTR) lpcszDialogClass, (UINT32) nPageResID); 00635 return FALSE; 00636 } 00637 00638 // Show this topic in the help system and return a success code. 00639 return ShowHelp(HELP_CONTEXT, dwHelpIndex); 00640 } 00641 00642 00643 00644 /******************************************************************************************** 00645 > BOOL HelpUser(const CDialog& dlg) 00646 00647 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00648 Created: 11/5/95 00649 Inputs: dlg the MFC dialog that requires help 00650 Returns: TRUE if help was successfully provided, FALSE if not. 00651 Purpose: Public function that finds the help topic associated with the given MFC 00652 dialog and runs the system help engine to display the topic. 00653 SeeAlso: RunOilHelp; LookupDialogTopic 00654 ********************************************************************************************/ 00655 00656 BOOL HelpUser(const wxDialog& dlg) 00657 { 00658 // Look-up the class name/page ID in our list of help topics. If we can't find it 00659 // then we return a failure code. 00660 DWORD dwHelpIndex = LookupDialogTopic(dlg.GetClassInfo()->GetClassName(), 0); 00661 if (dwHelpIndex == 0) 00662 { 00663 TRACEUSER( "Ollie", _T("Can't find help topic for the %s MFC dialog\n"), 00664 (LPCTSTR) dlg.GetClassInfo()->GetClassName()); 00665 return FALSE; 00666 } 00667 00668 // Show this topic in the help system and return a success code. 00669 return ShowHelp(HELP_CONTEXT, dwHelpIndex); 00670 } 00671 00672 00673 00674 /******************************************************************************************** 00675 > BOOL HelpUser(const OpDescriptor& opdesc) 00676 00677 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00678 Created: 11/5/95 00679 Inputs: opdesc the OpDescriptor of the Operation to provide help for 00680 Returns: TRUE if help was successfully provided, FALSE if not. 00681 Purpose: Public function that finds the help topic associated with the given 00682 OpDescriptor and runs the system help engine to display the topic. 00683 SeeAlso: RunOilHelp; LookupOperationTopic 00684 ********************************************************************************************/ 00685 00686 BOOL HelpUser(const OpDescriptor& opdesc) 00687 { 00688 // Check if a help topic is already recorded within the OpDescriptor. If it isn't 00689 // then we will have to look it up instead. 00690 /* 00691 // NB. all the help topic ID's within the OpDescriptors are wrong, so ignore them! 00692 DWORD dwHelpIndex = ((OpDescriptor&) opdesc).GetHelpId(); 00693 if (dwHelpIndex == 0) dwHelpIndex = LookupOperationTopic(opdesc.Token); 00694 */ 00695 DWORD dwHelpIndex = LookupOperationTopic(opdesc.Token); 00696 if (dwHelpIndex == 0) 00697 { 00698 TRACEUSER( "Ollie", _T("Can't find help topic for the %s OpDescriptor\n"), 00699 (LPCTSTR) opdesc.Token); 00700 return FALSE; 00701 } 00702 00703 // Show the topic we have found. 00704 return ShowHelp(HELP_CONTEXT, dwHelpIndex); 00705 } 00706 00707 00708 00709 /******************************************************************************************** 00710 > BOOL HelpUser(UINT32 nMessageID) 00711 00712 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00713 Created: 11/5/95 00714 Inputs: nMessageID the resource identifier of the message to display 00715 help about 00716 Returns: TRUE if help was successfully provided, FALSE otherwise 00717 Purpose: Public function that finds the help topic associated with the given 00718 message and runs the system help engine to display the topic. 00719 SeeAlso: RunOilHelp; LookupMessageTopic 00720 ********************************************************************************************/ 00721 00722 BOOL HelpUser(UINT32 nMessageID) 00723 { 00724 // Look-up the message ID in our list of help topics. If we can't find it 00725 // then return a failure code. 00726 DWORD dwHelpIndex = LookupMessageTopic(nMessageID); 00727 if (dwHelpIndex == 0) 00728 { 00729 TRACEUSER( "Ollie", _T("Can't find help topic for message 0x%lX\n"), 00730 (UINT32) nMessageID); 00731 return FALSE; 00732 } 00733 00734 // Show this topic in the help system and return a success code. 00735 return ShowHelp(HELP_CONTEXT, dwHelpIndex); 00736 } 00737 00738 /******************************************************************************************** 00739 00740 > BOOL HelpUserPropertyPage(UINT32 PageID); 00741 00742 Author: Richard_Millican (Xara Group Ltd) <camelotdev@xara.com> 00743 Created: 7/5/97 00744 Inputs: PageID ResourceID of the currently active page 00745 Returns: TRUE if help was successfully provided, FALSE otherwise 00746 Purpose: Public function that finds the help topic associated with the given 00747 property page. This is required due to the new way the tabbed dialogs work 00748 (via MFC). 00749 00750 ********************************************************************************************/ 00751 00752 BOOL HelpUserPropertyPage(UINT32 PageID) 00753 { 00754 DWORD dwHelpIndex = LookupDialogTopic(NULL, PageID); 00755 return (HelpUserTopic(dwHelpIndex)); 00756 } 00757 00758 /******************************************************************************************** 00759 00760 > BOOL HelpUserTopic(DWORD dwHelpIndex) 00761 00762 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00763 Created: 11/7/96 00764 Inputs: nMessageID the resource identifier of the message to display 00765 help about 00766 Returns: TRUE if help was successfully provided, FALSE otherwise 00767 Purpose: Public function that finds the help topic associated with the given 00768 message and runs the system help engine to display the topic. 00769 00770 ********************************************************************************************/ 00771 00772 BOOL HelpUserTopic(DWORD dwHelpIndex) 00773 { 00774 if (dwHelpIndex == 0) 00775 return FALSE; 00776 00777 // Show this topic in the help system and return a success code. 00778 return ShowHelp(HELP_CONTEXT, dwHelpIndex); 00779 } 00780 00781 00782 /******************************************************************************************** 00783 > BOOL _HelpUser(LPCTSTR lpcszClassName, UINT32 nSubTopic = 0) 00784 00785 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00786 Created: 23/5/95 00787 Inputs: lpcszClassName the class name of the object to run help for 00788 nSubTopic which sub-topic for the object to display 00789 (by default, no sub-topic) 00790 Returns: TRUE if the help system is started successfully. 00791 Purpose: Public function that finds the help topic associated with the given 00792 object and runs the system help engine to display it. This is a 00793 "bodgey" direct-access function for invoking help in those tricky cases, 00794 such as the print-setup dialog, that do not have any Camelot object 00795 directly associated with them. 00796 SeeAlso: HelpUser; LookupDialogTopic; RunOilHelp 00797 ********************************************************************************************/ 00798 00799 BOOL _HelpUser(LPCTSTR lpcszClassName, UINT32 nSubTopic /* = 0 */) 00800 { 00801 DWORD dwHelpIndex = LookupDialogTopic(lpcszClassName, nSubTopic); 00802 if (dwHelpIndex == 0) 00803 { 00804 TRACEUSER( "Ollie", _T("Can't find raw help topic for %s (sub %lu)\n"), 00805 lpcszClassName, nSubTopic); 00806 return FALSE; 00807 } 00808 00809 return ShowHelp(HELP_CONTEXT, dwHelpIndex); 00810 } 00811 00812 00813 00814 /******************************************************************************************** 00815 > BOOL HelpContents() 00816 00817 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00818 Created: 12/5/95 00819 Returns: TRUE if successful. 00820 Purpose: Runs the system help engine, displaying the "Contents" page. 00821 Errors: - 00822 SeeAlso: HelpUser; HelpSearch; HelpUsingHelp 00823 ********************************************************************************************/ 00824 00825 BOOL HelpContents() 00826 { 00827 #ifndef STANDALONE 00828 00829 // If F1 was pressed, popup help in the context of the current tool. Use the tool's OpToken (of 00830 // the form "TOOL<ToolId>") to look-up its help page. Fixes #10489 00831 if (KeyPress::IsKeyPressed(CAMKEY(F1))) 00832 { 00833 String OpToken; 00834 OpToken._MakeMsg( _T("TOOL%u"), Tool::GetCurrentID() ); 00835 DWORD dwHelpIndex = LookupOperationTopic(OpToken); 00836 return ShowHelp(HELP_CONTEXT, dwHelpIndex); 00837 } 00838 00839 return ShowHelp(HELP_FINDER, 0); 00840 00841 #else // STANDALONE 00842 // On the viewer go directly to the contents page on all OS's 00843 #ifdef WEBSTER 00844 return ShowHelp(HELP_CONTEXT, _R(IDH_Contents)); 00845 #else //WEBSTER 00846 return ShowHelp(HELP_CONTEXT, _R(IDH_Misc_Contents)); 00847 #endif // WEBSTER 00848 #endif // STANDALONE 00849 } 00850 00851 00852 00853 /******************************************************************************************** 00854 > BOOL HelpUsingHelp() 00855 00856 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00857 Created: 12/5/95 00858 Returns: TRUE if successful. 00859 Purpose: Runs the system help engine, displaying the system's instructions for 00860 using it. 00861 SeeAlso: HelpUser; HelpContents; HelpSearch 00862 ********************************************************************************************/ 00863 00864 BOOL HelpUsingHelp() 00865 { 00866 return RunOilHelp(NULL, HELP_HELPONHELP, 0); 00867 } 00868 00869 00870 00871 /******************************************************************************************** 00872 > BOOL HelpUsingTools() 00873 00874 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00875 Created: 12/5/95 00876 Returns: TRUE if successful. 00877 Purpose: Runs the system help engine, displaying the help on tools. 00878 SeeAlso: HelpUser; HelpContents; HelpSearch 00879 ********************************************************************************************/ 00880 00881 BOOL HelpUsingTools() 00882 { 00883 return ShowHelp(HELP_CONTEXT, _R(IDH_Misc_Tools)); 00884 } 00885 00886 00887 00888 /******************************************************************************************** 00889 > BOOL HelpUsingGalleries() 00890 00891 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00892 Created: 12/5/95 00893 Returns: TRUE if successful. 00894 Purpose: Runs the system help engine, displaying the help on galleries. 00895 SeeAlso: HelpUser; HelpContents; HelpSearch 00896 ********************************************************************************************/ 00897 00898 BOOL HelpUsingGalleries() 00899 { 00900 return ShowHelp(HELP_CONTEXT, _R(IDH_Overview_Galleries)); 00901 } 00902 00903 00904 00905 /******************************************************************************************** 00906 > BOOL HelpOnlineDemos() 00907 00908 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00909 Created: 12/5/95 00910 Returns: TRUE if successful. 00911 Purpose: Runs the system help engine, displaying the on-line demos help page. 00912 SeeAlso: HelpUser; HelpContents; HelpSearch 00913 ********************************************************************************************/ 00914 00915 BOOL HelpOnlineDemos() 00916 { 00917 PORTNOTETRACE("help", "Help function unimplemented!"); 00918 #if !defined(EXCLUDE_FROM_XARALX) 00919 return RunOilHelp(achzMoviesHelpPath, 0, 0); 00920 #else 00921 return FALSE; 00922 #endif 00923 } 00924 00925 00926 00927 /******************************************************************************************** 00928 > BOOL HelpTechnicalSupport() 00929 00930 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00931 Created: 1/11/95 00932 Returns: TRUE if successful. 00933 Purpose: Runs the system help engine, displaying the tech support help page. 00934 SeeAlso: HelpUser; HelpContents; HelpSearch 00935 *******************************************************************************************/ 00936 00937 BOOL HelpTechnicalSupport() 00938 { 00939 #ifdef WEBSTER 00940 return FALSE; 00941 #else 00942 return ShowHelp(HELP_CONTEXT, _R(IDH_Misc_Tech_Support)); 00943 #endif 00944 } 00945 00946 00947 00948 /******************************************************************************************** 00949 > BOOL CanHelpUser(UINT32 nMessageID) 00950 00951 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00952 Created: 11/5/95 00953 Inputs: nMessageID the resource identifier of the message that is being 00954 enquired about 00955 Returns: TRUE if a help topic descrbing this message exists, FALSE otherwise. 00956 Purpose: Public function to query whether a help topic exists for a given message. 00957 Depending on this the caller may display a help button in a message box, 00958 or may not etc. 00959 SeeAlso: LookupMessageTopic; InformGeneral 00960 ********************************************************************************************/ 00961 00962 BOOL CanHelpUser(UINT32 nMessageID) 00963 { 00964 // Just return TRUE if a help topic for the message exists. 00965 return LookupMessageTopic(nMessageID) != 0; 00966 } 00967 00968 00969 00970 /******************************************************************************************** 00971 > void SetNextMsgHelpContext(UINT32 nMessageID) 00972 00973 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00974 Created: 15/5/95 00975 Inputs: nMessageID the last message format string passed to MakeMsg 00976 Purpose: Remembers the last format string passed to MakeMsg. If a call is made to 00977 InformWarning, InformError etc and no string resource ID is passed then we 00978 have a problem using the string resource as an index into the help file. 00979 This remembers that last one, which we use if the "error ID" is zero. 00980 SeeAlso: StringBase::MakeMsg 00981 ********************************************************************************************/ 00982 00983 void SetNextMsgHelpContext(UINT32 nMessageID) 00984 { 00985 nNextMessageHelpContext = nMessageID; 00986 //TRACEUSER( "Andy", _T("\tSetNextMsgHelpContext(%d)\n"), nMessageID); 00987 } 00988 00989 00990 00991 /******************************************************************************************** 00992 > UINT32 GetNextMsgHelpContext() 00993 00994 Author: Andy_Hills (Xara Group Ltd) <camelotdev@xara.com> 00995 Created: 22/11/00 00996 Inputs: none 00997 Returns: help context 00998 Purpose: Gets the last help context set by SetNextMsgHelpContext 00999 SeeAlso: used by ScreenView::OnActivateView 01000 ********************************************************************************************/ 01001 01002 UINT32 GetNextMsgHelpContext() 01003 { 01004 return nNextMessageHelpContext; 01005 } 01006 01007 01008 01009 /******************************************************************************************** 01010 > BOOL InitUserHelp() 01011 01012 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01013 Created: 11/5/95 01014 Returns: TRUE if successful. 01015 Purpose: Initialises the help system. This should generally be called before just 01016 about everything else, so help is available for startup problems. 01017 SeeAlso: DeInitUserHelp 01018 ********************************************************************************************/ 01019 01020 // Forward references to helper functions 01021 BOOL InitHelpPath(BOOL bMainHelp); 01022 BOOL HelpFileExists(LPTSTR FileName); 01023 01024 BOOL InitUserHelp() 01025 { 01026 #if !defined(EXCLUDE_FROM_XARALX) 01027 // If we have any deferred file copies, deal with them now... 01028 HelpDownloadOp::DoDeferredFileCopy(); 01029 #endif 01030 01031 // init main help file: 01032 BOOL bOK = InitHelpPath(TRUE); 01033 01034 // init movies help file 01035 bOK = bOK && InitHelpPath(FALSE); 01036 01037 #if !defined(EXCLUDE_FROM_XARALX) 01038 // Install a message filter hook to trap F1 being pressed in dialogs etc. We don't need 01039 // one for menus as our "custom menu code" (ha ha ha) does this already. 01040 hF1Hook = ::SetWindowsHookEx(WH_MSGFILTER, F1HookProc, NULL, ::GetCurrentThreadId()); 01041 ERROR3IF(hF1Hook == NULL, "Couldn't set F1 key hook in InitUserHelp"); 01042 01043 // Success!?! 01044 return hF1Hook != NULL; 01045 #else 01046 return bOK; 01047 #endif 01048 } 01049 01050 01051 // -------------------------------------------------------------------------------- 01052 BOOL InitHelpPath(BOOL bMainHelp) 01053 { 01054 if( !bMainHelp ) 01055 { 01056 PORTNOTETRACE("help", "InitHelpPath does not support Movie path yet"); 01057 } 01058 01059 // Get the locale id 01060 wxString strLocale( setlocale( LC_MESSAGES, NULL ), wxConvUTF8 ); 01061 INT32 ordSep = strLocale.Find( _T('_' ) ); 01062 if ( -1 != ordSep ) 01063 strLocale = strLocale.Left( ordSep ); 01064 TRACEUSER( "jlh92", _T("Locale = %s\n"), PCTSTR(strLocale) ); 01065 01066 // Locale C is considered a synonym for en 01067 if( strLocale == _T("C") ) 01068 strLocale = _T("en"); 01069 01070 // Check the help dir exists, if not bomb out 01071 wxString strHelpPath( (PCTSTR)CCamApp::GetResourceDirectory() ); 01072 strHelpPath += _T("/doc/"); 01073 TRACEUSER( "jlh92", _T("Using filter discovery directory \"%s\"\n"), PCTSTR(strHelpPath + strLocale) ); 01074 if( wxDir::Exists( strHelpPath + strLocale ) ) 01075 strHelpPath += strLocale + _T("/"); 01076 else 01077 { 01078 if( wxDir::Exists( strHelpPath + _T("en") ) ) 01079 strHelpPath += _T("en/"); 01080 #if defined(_DEBUG) 01081 else 01082 { 01083 // We'll try default location under debug to make life easier 01084 strHelpPath = _T("/usr/share/xaralx/doc/en/"); 01085 TRACEUSER( "jlh92", _T("Try = \"%s\"\n"), PCTSTR(strHelpPath) ); 01086 } 01087 #endif 01088 } 01089 01090 achzHelpPath = strHelpPath; 01091 PORTNOTE( "help", "We should check and report non-existant help directory at some point" ) 01092 return TRUE; // wxDir::Exists( strHelpPath ); 01093 } 01094 01095 01096 /******************************************************************************************** 01097 > BOOL DeInitUserHelp() 01098 01099 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01100 Created: 11/5/95 01101 Returns: TRUE if successful. 01102 Purpose: Shuts down the help system. This should be called as late as possible, so 01103 help is available for app shut-down problems. Note that MFC will call 01104 WinHelp(HELP_QUIT) for us when the main frame window is destroyed. 01105 SeeAlso: InitUserHelp 01106 ********************************************************************************************/ 01107 01108 BOOL DeInitUserHelp() 01109 { 01110 PORTNOTETRACE("help", "Help function unimplemented!"); 01111 #if !defined(EXCLUDE_FROM_XARALX) 01112 // Tell the help engine we've finished using the help file(s). 01113 // NB. KNWON BUG: this doesn't do the job on Windows NT, leaving the helpfiles open. 01114 // As yet I have no idea why - it is as per the docs and works on Win32s & Chicago. 01115 if (fHaveUsedHelp) 01116 { 01117 TRACEUSER( "Ollie", _T("Closing general helpfile\n")); 01118 ShowHelp(HELP_QUIT, 0); 01119 } 01120 01121 #ifdef STANDALONE 01122 // Same if we ran the special helpfile. 01123 if (fHaveUsedSpecHelp) 01124 { 01125 TRACEUSER( "Ollie", _T("Closing special helpfile\n")); 01126 RunOilHelp(achzSpecPath, HELP_QUIT, 0); 01127 } 01128 #endif 01129 01130 // Remove our F1 message hook. 01131 return hF1Hook == NULL || ::UnhookWindowsHookEx(hF1Hook); 01132 #else 01133 return TRUE; 01134 #endif 01135 } 01136 01137 01138 01139 /******************************************************************************************** 01140 > BOOL ShowHelpSpec() 01141 01142 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01143 Created: 11/6/95 01144 Returns: TRUE if successful. 01145 Purpose: Used by the viewer to display the Xara Studio special help file. Makes a 01146 note if help is run successfully that we have to shut it down when we 01147 quit. 01148 ********************************************************************************************/ 01149 01150 #ifdef STANDALONE 01151 01152 BOOL ShowHelpSpec() 01153 { 01154 PORTNOTETRACE("help", "Help function unimplemented!"); 01155 #if !defined(EXCLUDE_FROM_XARALX) 01156 BOOL fResult = RunOilHelp(achzSpecPath, HELP_CONTENTS, 0); 01157 if (!fHaveUsedSpecHelp && fResult) fHaveUsedSpecHelp = TRUE; 01158 return fResult; 01159 #else 01160 return FALSE; 01161 #endif 01162 } 01163 01164 #endif // STANDALONE