Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1341 lines
31 KiB

/*****************************************************************************
* *
* COMMANDS.C *
* *
* Copyright (C) Microsoft Corporation 1990-1995 *
* All Rights reserved. *
* *
*****************************************************************************/
#include "help.h"
#pragma hdrstop
/*****************************************************************************
* *
* Prototypes *
* *
*****************************************************************************/
static HLLN STDCALL HllnFindMark (LPSTR);
static HANDLE STDCALL HFill (PCSTR, WORD, DWORD);
static BOOL STDCALL LoadShellDll();
/*****************************************************************************
* *
* typedefs *
* *
*****************************************************************************/
typedef struct {
FM fm;
TLP tlp;
HASH hash;
CHAR rgchMember[cchWindowMemberMax];
} MARK, *QMARK;
/*****************************************************************************
* *
* static variables *
* *
*****************************************************************************/
static LL llMark = NULL;
/*******************
-
- Name: HFill
*
* Purpose: Builds a data block for communicating with help
*
* Arguments: lpszHelp - pointer to the name of the help file to use
* usCommand - command being set to help
* ulData - data for the command
*
* Returns: a handle to the data block or NULL if the the
* block could not be created.
*
******************/
// BUGBUG: this must follow USER code exactly!!!
static HANDLE STDCALL HFill(PCSTR lpszHelp, WORD usCommand, DWORD ulData)
{
int cb; // Size of the data block
HANDLE hHlp; // Handle to return
BYTE bHigh; // High byte of usCommand
QHLP qhlp; // Pointer to data block
// Calculate size
if (lpszHelp)
cb = sizeof(HLP) + strlen(lpszHelp) + 1;
else
cb = sizeof(HLP);
bHigh = (BYTE)HIBYTE(usCommand);
if (bHigh == 1)
cb += strlen((LPSTR)ulData) + 2;
else if (bHigh == 2)
cb += *((INT16 *)ulData);
// Get data block
if (!(hHlp = GhAlloc(GPTR, cb)))
return NULL;
qhlp = (QHLP) PtrFromGh(hHlp);
/*------------------------------------------------------------*\
| Since by this time we have no idea what app could be called
| "current", we'll ignore the whole issue.
\*------------------------------------------------------------*/
qhlp->hins = NULL;
qhlp->winhlp.cbData = (WORD) (cb - sizeof(HLP) + sizeof(WINHLP));
qhlp->winhlp.usCommand = usCommand;
qhlp->winhlp.ulReserved = 0;
qhlp->winhlp.offszHelpFile = sizeof(WINHLP);
if (lpszHelp)
strcpy((PSTR)(qhlp+1), lpszHelp);
switch(bHigh)
{
case 0:
qhlp->winhlp.offabData = 0;
qhlp->winhlp.ctx = ulData;
break;
case 1:
qhlp->winhlp.offabData = sizeof(WINHLP) + (lpszHelp ? lstrlen(lpszHelp) : 0) + 1;
lstrcpy((LPSTR)(&qhlp->winhlp) + qhlp->winhlp.offabData, (LPSTR)ulData);
break;
case 2:
qhlp->winhlp.offabData = sizeof(WINHLP) + (lpszHelp ? lstrlen(lpszHelp) : 0) + 1;
MoveMemory((LPSTR)(&qhlp->winhlp) + qhlp->winhlp.offabData, (LPSTR)ulData, (LONG)(*((INT16 *)ulData)));
break;
}
return hHlp;
}
/*******************
-
- Name: FWinHelp
*
* Purpose: Post an message for help requests
*
* Arguments:
* hwndMain handle to main window of application
* lpszHelp path (if not current directory) and file
* to use for help topic.
* usCommand Command to send to help
* ulData Data associated with command:
* HELP_QUIT - no data (undefined)
* HELP_LAST - no data (undefined)
* HELP_CONTEXT - context number to display
* HELP_KEY - string ('\0' terminated)
* use as keyword to topic
* to display
* HELP_FIND - no data (undefined)
*
*
* Returns: TRUE iff success
*
******************/
BOOL STDCALL FWinHelp(LPCSTR lpszHelp, UINT16 usCommand, DWORD ulData)
{
HANDLE hHlp;
if (!(hHlp = HFill(lpszHelp, usCommand, ulData)))
return(FALSE);
if (!GenerateMessage(MSG_KILLDLG, 0, 0))
return FALSE;
return (BOOL) GenerateMessage(MSG_EXECAPI, 0, (LPARAM) hHlp);
}
BOOL STDCALL FPopupCtx(LPCSTR lpszHelp, DWORD ulContext)
{
JD jd;
if (lpszHelp[0]) {
if (!IsCurrentFile(lpszHelp))
return FWinHelp(lpszHelp, HELP_CONTEXTPOPUP, ulContext);
}
/*
* Messages of the form MSG_JUMP* take data and a Jump Descriptor.
* The JD is a way to pass information about the origin and type of
* jump. For the macro routines, the default origin is always the
* Scrolling Region.
*/
jd.bf.fNote = TRUE;
jd.bf.fFromNSR = FALSE;
if (IsValidWindow(hwndSecondHelp))
PostMessage(hwndSecondHelp, MSG_JUMPCTX, jd.word, ulContext);
return (BOOL) GenerateMessage(MSG_JUMPCTX, jd.word, ulContext);
}
BOOL STDCALL FJumpContext(LPCSTR lpszHelp, DWORD ulContext)
{
JD jd;
if (lpszHelp[0]) {
if (!IsCurrentFile(lpszHelp))
return FWinHelp(lpszHelp, HELP_CONTEXT, ulContext);
}
jd.bf.fNote = FALSE;
jd.bf.fFromNSR = FALSE;
if (IsValidWindow(hwndSecondHelp))
PostMessage(hwndSecondHelp, MSG_JUMPCTX, jd.word, ulContext);
return (BOOL) GenerateMessage(MSG_JUMPCTX, jd.word, ulContext);
}
/***************************************************************************
*
- Name: FJumpIndex
-
* Purpose: Function to jump to the Contents of some file -- used for
* macro language.
*
* Arguments lpszHelp - far pointer to a null terminated string containging
* the help file name.
*
* Returns TRUE iff successful. Will only fail for lack of memory.
*
***************************************************************************/
BOOL STDCALL FJumpIndex(LPCSTR lpszHelp)
{
ASSERT(lpszHelp);
if (lpszHelp[0]) {
if (!IsCurrentFile(lpszHelp))
return FWinHelp(lpszHelp, HELP_CONTENTS, 0);
}
Contents();
return TRUE;
}
/***************************************************************************
*
- Name: FJumpHOH
-
* Purpose: Function to jump to help on help file used by the
* macro language.
*
* Arguments: none.
*
* Returns: TRUE iff successful. Will only fail for lack of memory.
*
***************************************************************************/
BOOL STDCALL FJumpHOH(VOID)
{
return FWinHelp(txtZeroLength, HELP_HELPONHELP, 0);
}
/***************************************************************************
*
- Name: FJumpId
-
* Purpose: Function to jump to a topic in the file based on the context
* ID string (i.e. by hash value of the string)
*
* Arguments lpszHelp - far pointer to a null terminated string containging
* the help file name.
* qchHash - ID string to jump to.
*
* Returns TRUE if successful. Will only fail for lack of memory or invalid
* context id
*
***************************************************************************/
BOOL STDCALL FJumpId(LPCSTR lpszHelp, LPCSTR qchHash)
{
lcHeapCheck();
if (!FValidContextSz(qchHash))
return FALSE;
return FJumpHash(lpszHelp, HashFromSz(qchHash));
}
/***************************************************************************
FUNCTION: JumpWindow
PURPOSE: Jump to a topic in a secondary window, returning the focus
to the caller window.
PARAMETERS:
lpszWindow
qchHash
RETURNS:
COMMENTS:
MODIFICATION DATES:
29-Nov-1993 [ralphw]
***************************************************************************/
BOOL STDCALL JumpWindow(LPSTR lpszWindow, LPSTR pszContextString)
{
char szHelp[MAX_PATH];
HANDLE hHlp;
int iSaveCurWindow, i;
PSTR psz;
if (!StrChrDBCS(lpszWindow, WINDOWSEPARATOR)) {
lstrcpy(szHelp, GetCurFilename());
lstrcat(szHelp, ">");
lstrcat(szHelp, lpszWindow);
}
else
lstrcpy(szHelp, lpszWindow);
psz = StrChrDBCS(szHelp, WINDOWSEPARATOR) + 1;
ASSERT(psz);
/*
* Find out if this window has been created. If not, don't execute
* the macro. Return FALSE in case this gets hooked up with IfThen.
*/
for (i = MAIN_HWND + 1; i < MAX_WINDOWS; i++) {
if (ahwnd[i].pszMemberName &&
_strcmpi(psz, ahwnd[i].pszMemberName) == 0)
break;
}
if (i == MAX_WINDOWS)
return FALSE;
if (!(hHlp = HFill(szHelp, cmdId, (DWORD) pszContextString)))
return(FALSE);
iSaveCurWindow = iCurWindow;
SendMessage(ahwnd[iCurWindow].hwndParent, MSG_EXECAPI, 0, (LPARAM) hHlp);
if (ahwnd[i].hwndTitle)
InvalidateRect(ahwnd[i].hwndTitle, NULL, TRUE);
SetActiveWindow(ahwnd[iSaveCurWindow].hwndParent);
return TRUE;
}
/***************************************************************************
*
*
- Name: FPopupId
-
* Purpose: Function to display a glossary based on context id string
*
* Arguments lpszHelp - far pointer to a null terminated string containging
* the help file name.
* qchHash - ID string to jump to.
*
* Returns TRUE iff successful. Will only fail for lack of memory.
*
***************************************************************************/
BOOL STDCALL FPopupId(LPCSTR lpszHelp, LPCSTR qchHash)
{
if (!FValidContextSz(qchHash))
return FALSE;
return FPopupHash(lpszHelp, HashFromSz(qchHash));
}
/***************************************************************************
*
- Name: FJumpHash
-
* Purpose: Function to jump to a topic in the file based on the hash
* value passed.
*
* Arguments lpszHelp - far pointer to a null terminated string containging
* the help file name.
* Hash - hash value
*
* Returns TRUE iff successful. Will only fail for lack of memory.
*
***************************************************************************/
BOOL STDCALL FJumpHash(LPCSTR lpszHelp, HASH hash)
{
JD jd;
char szBuf[MAX_PATH];
if (lpszHelp && lpszHelp[0]) {
if (lpszHelp[0] == WINDOWSEPARATOR) {
HDE hde = HdeGetEnv();
if (!hde)
return FALSE;
GetFmParts(QDE_FM(QdeFromGh(hde)), szBuf, PARTBASE | PARTEXT);
lstrcat(szBuf, lpszHelp);
return FWinHelp(szBuf, cmdHash, (DWORD) hash);
}
if (StrChrDBCS(lpszHelp, WINDOWSEPARATOR) || !IsCurrentFile(lpszHelp))
return FWinHelp(lpszHelp, cmdHash, (DWORD) hash);
}
jd.bf.fNote = FALSE;
jd.bf.fFromNSR = FALSE;
if (IsValidWindow(hwndSecondHelp))
PostMessage(hwndSecondHelp, MSG_JUMPHASH, jd.word, hash);
return (BOOL) GenerateMessage(MSG_JUMPHASH, jd.word, hash);
}
/***************************************************************************
*
*
- Name: FPopupHash
-
* Purpose: Function to display a glossary based on hash value
*
* Arguments lpszHelp - far pointer to a null terminated string containging
* the help file name.
* qchHash - ID string to jump to.
*
* Returns TRUE iff successful. Will only fail for lack of memory.
*
***************************************************************************/
BOOL STDCALL FPopupHash(LPCSTR lpszHelp, HASH hash)
{
JD jd;
if (lpszHelp[0]) {
// All member jumps must have a filename by this point.
ASSERT(lpszHelp[0] != '>');
if (!IsCurrentFile(lpszHelp))
return FWinHelp(lpszHelp, cmdHashPopup, (DWORD) hash);
}
jd.bf.fNote = TRUE;
jd.bf.fFromNSR = FALSE;
if (IsValidWindow(hwndSecondHelp))
PostMessage(hwndSecondHelp, MSG_JUMPHASH, jd.word, hash);
return (BOOL) GenerateMessage(MSG_JUMPHASH, jd.word, hash);
}
/***************************************************************************
*
- Name: FSetIndex
-
* Purpose: Function to set the current index -- used for
* macro language.
*
* Arguments lpszHelp - far pointer to a null terminated string
* containing the help file name.
* ulContext - context number of topic to be the index.
*
* Returns TRUE iff successful. Will only fail for lack of memory.
*
***************************************************************************/
BOOL STDCALL FSetIndex(PCSTR lpszHelp, DWORD ulContext)
{
return FWinHelp(lpszHelp, HELP_SETCONTENTS, ulContext);
}
/***************************************************************************
*
- Name: FShowKey
-
* Purpose: Function to set the current index -- used for
* macro language.
*
* Arguments lpszHelp - far pointer to a null terminated string
* containing the help file name.
* qchKey - far pointer to null terminated string containing
* key to lookup.
*
* Returns TRUE if successful. Will only fail for lack of memory.
*
***************************************************************************/
BOOL STDCALL FShowKey(LPSTR lpszHelp, LPSTR qchKey)
{
return FWinHelp(lpszHelp, HELP_KEY, (DWORD) qchKey);
}
/***************************************************************************
*
- Name: Index, Search, Back, History, Prev, Next
-
* Purpose: Causes the specified actions to occur as if the buttons
* had been pressed. They are packaged this way for the
* macro language
*
* Arguments None.
*
* Returns Nothing
*
***************************************************************************/
// This is really Contents, not Index.
void STDCALL Contents(VOID)
{
GenerateMessage(MSG_ACTION, IFW_CONTENTS, 1);
}
VOID STDCALL Search(VOID)
{
if (!fSequence)
GenerateMessage(MSG_ACTION, IFW_SEARCH, 1);
}
void STDCALL Finder(void)
{
if (!fSequence)
GenerateMessage(MSG_ACTION, IFW_TOPICS, 1);
}
void STDCALL Find(void)
{
if (!fSequence)
GenerateMessage(MSG_ACTION, IFW_FIND, 1);
}
void STDCALL ShowTab(UINT iTab)
{
if (!fSequence)
GenerateMessage(MSG_ACTION, IFW_FIND + iTab, 1);
idTabSetting = iTab + 2;
}
BOOL STDCALL Back(VOID)
{
dwSequence = 0;
if (IsValidWindow(hwndSecondHelp))
PostMessage(hwndSecondHelp, MSG_ACTION, IFW_BACK, 1);
GenerateMessage(MSG_ACTION, IFW_BACK, 1);
return FBackAvailable(iCurWindow);
}
VOID STDCALL History(VOID)
{
GenerateMessage(MSG_ACTION, IFW_HISTORY, 1);
}
VOID STDCALL Prev(VOID)
{
if (IsValidWindow(hwndSecondHelp))
PostMessage(hwndSecondHelp, MSG_ACTION, IFW_PREV, 1);
GenerateMessage(MSG_ACTION, IFW_PREV, 1);
}
VOID STDCALL Next(VOID)
{
if (IsValidWindow(hwndSecondHelp))
PostMessage(hwndSecondHelp, MSG_ACTION, IFW_NEXT, 1);
GenerateMessage(MSG_ACTION, IFW_NEXT, 1);
}
VOID STDCALL FileOpen(VOID)
{
if (FRaiseMacroFlag())
GenerateMessage(WM_COMMAND, HLPMENUFILEOPEN, 0);
else
PostErrorMessage(wERRS_MACROPROB);
}
VOID STDCALL Print(VOID)
{
if (FRaiseMacroFlag())
GenerateMessage(WM_COMMAND, HLPMENUFILEPRINT, 0);
else
PostErrorMessage(wERRS_MACROPROB);
}
VOID STDCALL PrinterSetup(VOID)
{
if (FRaiseMacroFlag())
GenerateMessage(WM_COMMAND, HLPMENUFILEPRINTSETUP, 0);
else
PostErrorMessage(wERRS_MACROPROB);
}
void STDCALL Exit(VOID)
{
if (IsValidWindow(hwndSecondHelp))
PostMessage(hwndSecondHelp, WM_COMMAND, HLPMENUFILEEXIT, 0);
GenerateMessage(WM_COMMAND, HLPMENUFILEEXIT, 0);
}
BOOL STDCALL ALink(PSTR pszLinkWords, UINT flags, PSTR pszContext,
PSTR pszWindow)
{
if (!(flags & 4)) // don't flush if we're just testing
FlushMessageQueue(0); // in case there are any macros before us
return doAlink(pszLinkWords, flags, pszContext, 'A', pszWindow);
}
BOOL STDCALL KLink(PSTR pszLinkWords, UINT flags, PSTR pszContext,
PSTR pszWindow)
{
if (!(flags & 4)) // don't flush if we're just testing
FlushMessageQueue(0); // in case there are any macros before us
return doAlink(pszLinkWords, flags, pszContext, 'K', pszWindow);
}
void STDCALL Annotate(VOID)
{
if (FRaiseMacroFlag())
// Flag must be lowered by routine.
GenerateMessage(WM_COMMAND, HLPMENUEDITANNOTATE, 0);
else
PostErrorMessage(wERRS_MACROPROB);
}
void STDCALL doCopy(VOID)
{
GenerateMessage(WM_COMMAND, HLPMENUEDITCOPY, 0);
}
void STDCALL CopySpecial(VOID)
{
GenerateMessage(WM_COMMAND, HLPMENUEDITCPYSPL, 0);
}
void STDCALL BookmarkDefine(VOID)
{
if (FRaiseMacroFlag())
// Flag must be lowered by routine.
GenerateMessage(WM_COMMAND, HLPMENUBOOKMARKDEFINE, 0);
else
PostErrorMessage(wERRS_MACROPROB);
}
void STDCALL BookmarkMore(VOID)
{
if (FRaiseMacroFlag())
GenerateMessage(WM_COMMAND, HLPMENUBOOKMARKMORE, 0);
else
PostErrorMessage(wERRS_MACROPROB);
}
void STDCALL HelpOn(VOID)
{
GenerateMessage(WM_COMMAND, HLPMENUHELPHELP, 0);
}
BOOL STDCALL HelpOnTop(VOID)
{
GenerateMessage(WM_COMMAND, HLPMENUHELPONTOP, 0);
return (ahwnd[iCurWindow].fsOnTop != ONTOP_AUTHOREDON);
}
void STDCALL About(VOID)
{
if (FRaiseMacroFlag())
GenerateMessage(WM_COMMAND, HLPMENUHELPABOUT, 0);
else
PostErrorMessage(wERRS_MACROPROB);
}
void STDCALL Command(UINT wCommand)
{
GenerateMessage(WM_COMMAND, wCommand, 0);
}
/***************************************************************************
*
- Name: BrowseButtons
-
* Purpose: Causes the Next and Prev buttons to be displayed.
*
* Arguments None.
*
* Returns Nothing
*
***************************************************************************/
VOID STDCALL BrowseButtons(VOID)
{
GenerateMessage(MSG_BROWSEBTNS, 0, 0);
}
/***************************************************************************
*
- Name: SetHelpOn
-
* Purpose: Sets the help on help file for the current window.
*
* Arguments: sz - file to set for help on.
*
* Returns: nothing.
*
***************************************************************************/
void STDCALL SetHelpOn(PCSTR sz)
{
/*
* This no longer makes sense -- given the changes to WinHelp 4, no
* previous help-on-help file will be accurate. So, we don't allow
* the author to change the help on help file.
*/
#if 0
HDE hde;
FM fm;
hde = HdeGetEnvHwnd(ahwnd[iCurWindow].hwndTopic);
if (hde == NULL)
return; // REVIEW
if ((fm = FmNew(sz)))
QDE_HHELPON(QdeFromGh(hde)) = fm;
#endif
}
/***************************************************************************\
*
- Function: ConfigMacrosHde
-
* Purpose: Executes the macros from the system file
*
*
* Arguments: hde - handle to current DE
*
* returns: Nothing
*
\***************************************************************************/
void STDCALL ConfigMacrosHde(HDE hde)
{
LL ll;
QDE qde;
ASSERT(hde);
qde = QdeFromGh(hde);
if (!QDE_TOPIC(qde))
return;
ll = QDE_LLMACROS(qde);
if (ll) {
HLLN hlln = NULL;
while (hlln = WalkLL(ll, hlln)) {
Execute((LPSTR) GetLLDataPtr(hlln));
}
}
}
/***************************************************************************
*
- Names IfThen(), IfThenElse(), Not()
-
* Purpose: Implements standard programming constructs for the macro
* language.
*
***************************************************************************/
void STDCALL IfThen(BOOL f, LPSTR qch)
{
if (f)
Execute(qch);
}
void STDCALL IfThenElse(BOOL f, LPSTR qch1, LPSTR qch2)
{
if (f)
Execute(qch1);
else
Execute(qch2); }
BOOL STDCALL FNot(BOOL f)
{
return !f;
}
/***************************************************************************
*
- Name: SaveMark
-
* Purpose: Saves the current position and file.
*
* Arguments: qchName - name to save the mark under.
*
* Returns: Nothing.
*
* Globals Used: llMark.
*
***************************************************************************/
void STDCALL SaveMark(PSTR qch)
{
HDE hde;
QDE qde;
MARK mark;
QMARK qmark;
HLLN hlln;
if (llMark == NULL) {
if ((llMark = LLCreate()) == NULL) {
PostErrorMessage(wERRS_OOM);
return;
}
}
if ((hde = HdeGetEnvHwnd(ahwnd[iCurWindow].hwndTopic)) == NULL) {
// It is theoretically impossible not to have an HDE, so we don't
// have an error message should the impossible happen.
ASSERT(hde);
PostErrorMessage(wERRS_INTERNAL_ERROR);
CloseHelp();
return;
}
ASSERT(hde);
qde = QdeFromGh(hde);
mark.hash = HashFromSz(qch);
mark.tlp = TLPGetCurrentQde(qde);
mark.fm = FmCopyFm(QDE_FM(qde));
strcpy(mark.rgchMember, ahwnd[iCurWindow].pszMemberName);
if ((hlln = HllnFindMark(qch)) != NULL) {
qmark = (QMARK)GetLLDataPtr(hlln);
DisposeFm(qmark->fm);
*qmark = mark;
}
else
if (!InsertLL(llMark, &mark, sizeof(mark)))
PostErrorMessage(wERRS_OOM);
}
/***************************************************************************
*
- Name: HllnFindMark
-
* Purpose: Saves the current position and file.
*
* Arguments: qch - name of the mark to find.
*
* Returns: A node containing the specified mark. If the mark is
* not found, NULL is returned.
*
* Globals Used: llMark.
*
***************************************************************************/
static HLLN STDCALL HllnFindMark(LPSTR qch)
{
HASH hash;
HLLN hlln = NULL;
QMARK qmarkT;
if (llMark == NULL)
return NULL;
hash = HashFromSz(qch);
while (hlln = WalkLL(llMark, hlln)) {
qmarkT = (QMARK) GetLLDataPtr(hlln);
if (qmarkT->hash == hash) {
break;
}
}
return hlln;
}
/***************************************************************************
*
- Name: FMark
-
* Purpose: Tests for the existance of a mark.
*
* Arguments: qch - name of the mark to find.
*
* Returns: TRUE if the mark is found.
*
***************************************************************************/
BOOL STDCALL FMark(LPSTR qch)
{
return (HllnFindMark(qch) != NULL);
}
BOOL STDCALL FNotMark(LPSTR qch)
{
return !(HllnFindMark(qch) != NULL);
}
/***************************************************************************
*
- Name: GotoMark
-
* Purpose: Causes the main window to return to a previously set mark.
*
* Arguments: qchName - name the mark was saved under.
*
* Returns: Nothing.
*
***************************************************************************/
void STDCALL GotoMark(LPSTR qch)
{
QMARK qmark;
HLLN hlln;
char rgch[MAX_PATH + cchWindowMemberMax + 1];
TLPHELP tlphelp;
if ((hlln = HllnFindMark(qch)) == NULL)
PostErrorMessage(wERRS_NOTOPIC);
else {
qmark = (QMARK) GetLLDataPtr(hlln);
lstrcpy(rgch, PszFromGh(qmark->fm));
strcat(rgch, ">");
lstrcat(rgch, qmark->rgchMember);
tlphelp.cb = sizeof(TLPHELP);
tlphelp.tlp = qmark->tlp;
FWinHelp(rgch, cmdTLP, (LONG) (LPVOID) &tlphelp);
}
}
/***************************************************************************
*
- Name: DeleteMark
-
* Purpose: Removes a mark from the mark list.
*
* Arguments: qchName - name the mark was saved under.
*
* Returns: Nothing.
*
* Globals Used: llMark.
*
***************************************************************************/
void STDCALL DeleteMark(LPSTR qch)
{
HLLN hlln;
if ((hlln = HllnFindMark(qch)) == NULL)
PostErrorMessage(wERRS_NOTOPIC);
else
DeleteHLLN(llMark, hlln);
}
/*******************
-
- Name: HelpExec
*
* Purpose: Attempts to execute the specified program
*
* Arguments: qch - far pointer to the program to execute
* w - how the app is to appear
* 0 - show normal
* 1 - show minimized
* 2 - show maximimized
*
* Returns: TRUE iff it succeeds
*
*******************/
BOOL STDCALL HelpExec(PCSTR pszFile, UINT w)
{
UINT wRet;
FM fm;
char szExe[MAX_PATH];
PSTR psz, pszCopy = NULL;
WaitCursor();
if ((psz = StrChrDBCS(pszFile, ' '))) {
pszCopy = LocalStrDup(psz);
*psz = '\0';
}
fm = FmNewExistSzDir(pszFile, DIR_INI | DIR_PATH |
DIR_CUR_HELP | DIR_CURRENT | DIR_SILENT_REG);
if (fm) {
lstrcpy(szExe, PszFromGh(fm));
if (pszCopy)
lstrcat(szExe, pszCopy);
pszFile = szExe;
}
if (pszCopy)
FreeLh(pszCopy);
if (psz)
*psz = ' ';
w++; // adjust to use SW_ constants
if (w > 3)
w = 1;
wRet = WinExec(pszFile, w);
RemoveWaitCursor();
if (wRet <= HINSTANCE_ERROR)
ErrorVarArgs(wERRS_APP_NOT_FOUND, wERRA_RETURN,
pszFile);
DisposeFm(fm);
return (wRet > 32);
}
#include <shellapi.h>
//#include <shell.h>
#ifndef NO_PRAGMAS
#pragma data_seg(".text", "CODE")
#endif
static const char txtOpen[] = "open";
static const char txtCplOpen[] = "cplopen";
static const char txtFolder[] = "folder";
static const char txtShellDll[] = "shell32.dll";
static const char txtShellExecute[] = "ShellExecuteA";
#ifndef NO_PRAGMAS
#pragma data_seg()
#endif
HINSTANCE (WINAPI* pShellExecute)(HWND hwnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, int iShowCmd);
typedef HINSTANCE (WINAPI* SHELLEXECUTEPROC)(HWND hwnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, int iShowCmd);
static BOOL STDCALL LoadShellDll()
{
HLIBMOD hmodule;
if ((hmodule = HFindDLL(txtShellDll, FALSE))) {
pShellExecute = (SHELLEXECUTEPROC)
GetProcAddress(hmodule, txtShellExecute);
return (BOOL) pShellExecute;
}
else
return FALSE;
}
BOOL STDCALL ExecFile(PCSTR pszFile, PCSTR pszArgs, UINT fsShowCmd,
PCSTR pszContext)
{
FM fm = FmNewExistSzDir(pszFile, DIR_INI | DIR_PATH |
DIR_CUR_HELP | DIR_CURRENT | DIR_SILENT_REG);
return FShellExecute(fm ? fm : pszFile, pszArgs, fsShowCmd,
((strstr(pszFile, ".cpl") || strstr(pszFile, ".CPL")) ? txtCplOpen : txtOpen),
txtZeroLength, pszContext);
}
#define WAIT_FOR_PROCESS_START (2 * 1000)
BOOL STDCALL FShellExecute(PCSTR pszFile,
PCSTR pszParams, int fsShowCmd, PCSTR pszOp, PCSTR pszDir,
PCSTR pszContext)
{
HINSTANCE hinstRet;
if (!pShellExecute) {
if (!LoadShellDll())
goto Problem;
}
WaitCursor();
hinstRet = pShellExecute(ahwnd[iCurWindow].hwndParent,
pszOp, pszFile, pszParams, pszDir, fsShowCmd);
RemoveWaitCursor();
if ((int) hinstRet == -1)
return TRUE; // means it's already running
if ((int) hinstRet <= HINSTANCE_ERROR) {
Problem:
if (*pszContext)
MacroErrorPopup(pszContext);
else
ErrorVarArgs(wERRS_APP_NOT_FOUND, wERRA_RETURN, pszFile);
}
return ((int) hinstRet > 32);
}
/***************************************************************************
FUNCTION: ShortCut
PURPOSE:
PARAMETERS:
pszApplication
msg
wParam
lParam
RETURNS:
COMMENTS:
MODIFICATION DATES:
02-Dec-1993 [ralphw]
***************************************************************************/
BOOL STDCALL ShortCut(PCSTR pszClass, PCSTR pszApplication,
UINT wParam, LPARAM lParam, PCSTR pszContext)
{
HWND hwndApp;
PSTR psz, pszParams;
FlushMessageQueue(0);
if (!(hwndApp = FindWindow(pszClass, NULL))) {
if (!LoadShellDll()) {
if (*pszContext)
MacroErrorPopup(pszContext);
else
ErrorVarArgs(wERRS_APP_NOT_FOUND, wERRA_RETURN,
pszApplication);
return FALSE;
}
// Separate out any parameters
if ((psz = StrChrDBCS(pszApplication, ' '))) {
pszParams = psz + 1;
*psz = '\0';
}
else
pszParams = (PSTR) txtZeroLength;
if (!FShellExecute(pszApplication, pszParams, SW_SHOW,
txtOpen, txtZeroLength, pszContext)) {
RemoveWaitCursor();
return FALSE;
}
}
else {
ShowWindow(hwndApp, SW_RESTORE); // RAID #27627 -- must restore minimized app
SetForegroundWindow(hwndApp);
}
// Clear out the queue in case this is the end of a series of macros.
if (wParam != (UINT) -1) {
int i;
if (!hwndApp) {
// Wait for up to 7 seconds for the process to initialize
WaitCursor();
for (i = 0; i < 70; i++) {
if ((hwndApp = FindWindow(pszClass, NULL)))
break;
Sleep(100);
}
RemoveWaitCursor();
}
if (!hwndApp) {
// Probably means the window class has changed.
if (fHelpAuthor)
ErrorVarArgs(wERRS_CLASS_NOT_FOUND, wERRA_RETURN, pszClass);
return FALSE;
}
SetForegroundWindow(hwndApp);
SendMessage(hwndApp, WM_COMMAND, wParam, lParam);
}
return TRUE;
}
/***************************************************************************
FUNCTION: OldGenerate
PURPOSE: This function is what gets exported. Previous versions
required a long for the second parameter even though it
was alwasy truncated to a word. The current GenerateMessage
expects a word, but we must export this old brain-dead
version.
PARAMETERS:
wWhich
wParam
lParam
RETURNS:
COMMENTS:
MODIFICATION DATES:
18-Mar-1993 [ralphw]
***************************************************************************/
LONG STDCALL OldGenerate(UINT wWhich, LONG wParam, LONG lParam)
{
return GenerateMessage(wWhich, (WPARAM) wParam, (LPARAM) lParam);
}
/***************************************************************************
FUNCTION: IsCurrentFile
PURPOSE: Determine if the specified help file is the same as our
current help file.
PARAMETERS:
lpszHelpFile -- help file to check against current help file
RETURNS:
COMMENTS:
Returns FALSE if specified help file contains a path specification
MODIFICATION DATES:
03-Jan-1994 [ralphw]
***************************************************************************/
BOOL STDCALL IsCurrentFile(LPCSTR lpszHelpFile)
{
HDE hde = HdeGetEnv();
PSTR pszWindowSep;
if (!hde)
return FALSE;
pszWindowSep = StrChrDBCS(lpszHelpFile, WINDOWSEPARATOR);
if (pszWindowSep) {
BOOL fReturn;
*pszWindowSep = '\0';
fReturn = IsSameFile(lpszHelpFile, PszFromGh(QDE_FM(QdeFromGh(hde))));
*pszWindowSep = WINDOWSEPARATOR;
return fReturn;
}
else
return (IsSameFile(lpszHelpFile, PszFromGh(QDE_FM(QdeFromGh(hde)))));
}
BOOL STDCALL IsSameFile(LPCSTR pszFile1, LPCSTR pszFile2)
{
char szFile1[MAX_PATH];
char szFile2[MAX_PATH];
if (_strcmpi(pszFile1, pszFile2) == 0)
return TRUE;
// No, then try partial pathname
GetFmParts((FM) pszFile1, szFile1, PARTBASE | PARTEXT);
GetFmParts((FM) pszFile2, szFile2, PARTBASE | PARTEXT);
return (_strcmpi(szFile1, szFile2) == 0);
}
/***************************************************************************
FUNCTION: MacroErrorPopup
PURPOSE: Display macro-defined error message via a popup topic
PARAMETERS:
pszContext
RETURNS:
COMMENTS:
MODIFICATION DATES:
26-Jan-1994 [ralphw]
***************************************************************************/
void STDCALL MacroErrorPopup(PCSTR pszContext)
{
PSTR psz;
if ((psz = StrChrDBCS(pszContext, FILESEPARATOR))) {
*psz = '\0';
FPopupId(psz + 1, pszContext);
*psz = FILESEPARATOR; // REVIEW: probably not necessary
}
else {
FPopupId((pszHelpBase ? pszHelpBase : txtZeroLength),
pszContext);
}
}
BOOL STDCALL TCard(WPARAM wParam, LPARAM lParam)
{
char szBuf[256];
wsprintf(szBuf, "W:%u %d %d\r\n", hwndTCApp,
wParam, lParam);
SendStringToParent(szBuf);
if (!hwndTCApp) {
Error(wERRS_CALLER_GONE, wERRA_RETURN);
return FALSE;
}
SendMessage(hwndTCApp, WM_TCARD, wParam, lParam);
return TRUE;
}
BOOL STDCALL IsBook(void)
{
return (fHelp == BOOK_HELP);
}
void STDCALL NoShow(void)
{
fNoShow = TRUE;
}
void STDCALL MenuButton(void)
{
RECT rc;
POINT pt;
if (ahwnd[iCurWindow].hwndButtonMenu) {
GetWindowRect(ahwnd[iCurWindow].hwndButtonMenu, &rc);
pt.x = rc.left + 5;
pt.y = rc.top + 5;
}
else
pt.x = -1;
DisplayFloatingMenu(pt);
}
/***************************************************************************
FUNCTION: FileExist
PURPOSE: Macro call, returns TRUE if the file exists.
PARAMETERS:
pszFile
RETURNS:
COMMENTS:
MODIFICATION DATES:
08-Nov-1994 [ralphw]
***************************************************************************/
BOOL STDCALL FileExist(PCSTR pszFile)
{
FM fm = FmNewExistSzDir(pszFile,
DIR_CURRENT | DIR_PATH | DIR_CUR_HELP | DIR_INI | DIR_SILENT_REG);
if (fm) {
FreeLh((HGLOBAL) fm);
return TRUE;
}
else
return FALSE;
}