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.
 
 
 
 
 
 

1332 lines
34 KiB

/*****************************************************************************
*
* frawhide.c
*
* Copyright (C) Microsoft Corporation 1990.
* All Rights reserved.
*
******************************************************************************
*
* The only reason this is in frame is because we use a qfcm
* This could be changed.
*
******************************************************************************
*
* Current Owner: kevynct
*
******************************************************************************
*
* Revision History:
* 03-Dec-1990 LeoN PDB changes
*
*****************************************************************************/
#include "help.h"
#pragma hdrstop
#include "inc\frstuff.h"
#ifdef RAWHIDE
static RC RcFromSearchWerr(int werr);
static DWORD PaFromQde(QDE);
static BOOL fOkToCallFtui = TRUE;
/*----------------------------------------------------------------------------+
| FSearchMatchesExist(qde) |
| |
+----------------------------------------------------------------------------*/
BOOL STDCALL FSearchMatchesExist(QDE qde)
{
int werr;
DWORD dwRU;
DWORD dwaddr;
WORD wext;
if (QDE_HRHFT(qde) == NULL || !fOkToCallFtui)
return FALSE;
werr = ((FT_WerrHoldCrsrHs) SearchModule(FN_WerrHoldCrsrHs))(QDE_HRHFT(qde));
if (werr != ER_NOERROR)
return FALSE;
werr = ((FT_WerrRestoreCrsrHs) SearchModule(FN_WerrRestoreCrsrHs))
(QDE_HRHFT(qde), (QUL)&dwRU, (QUL)&dwaddr, (QW)&wext);
if (fFATALERROR(werr))
{
fOkToCallFtui = FALSE;
return FALSE;
}
return TRUE;
}
/*----------------------------------------------------------------------------+
| RcInitMatchInFCM(qde, qfcm, qsmp) |
| |
| Return codes: |
| |
| rcSuccess: *qsmp contains first match in FC. |
| rcNoExists: *qsmp contains first match after FC in the current help file.|
| rcFileChange: *qsmp contains first match after FC in different help file.|
| rcFailure: *qsmp is invalid: no more matches. |
| |
| NOTE: Caller is currently ignoring any errors. |
+----------------------------------------------------------------------------*/
RC STDCALL RcInitMatchInFCM(qde, qfcm, qsmp)
QDE qde;
QFCM qfcm;
QSMP qsmp;
{
WERR werr;
DWORD dwRU;
DWORD dwaddr;
WORD wext;
PA paFirst;
RC rc;
#ifdef UNIMPLEMENTED
if (fcidCache == qfcm->fcid)
{
*qsmp = smpCache;
return rcCache;
}
#endif
werr = ((FT_WerrHoldCrsrHs) SearchModule(FN_WerrHoldCrsrHs))(QDE_HRHFT(qde));
if (werr != ER_NOERROR)
return rcFailure;
/* Set PA to first region in FC */
paFirst.blknum = qfcm->va.bf.blknum;
paFirst.objoff = qfcm->cobjrgP;
/* REVIEW: what about nil lTopicNo? */
dwRU = (DWORD)qde->top.mtop.lTopicNo;
dwaddr = *(QDW)&paFirst;
werr = ((FT_WerrNearestMatchHs) SearchModule(FN_WerrNearestMatchHs))
(QDE_HRHFT(qde), dwRU, (QDW)&dwaddr, (QW)&wext);
qsmp->pa = *(QPA)&dwaddr;
qsmp->cobjrg = wext;
/* Is the next match beyond the end of this FC ? */
if (paFirst.blknum != qsmp->pa.blknum
|| qsmp->pa.objoff >= paFirst.objoff + qfcm->cobjrg)
{
rc = rcNoExists;
}
else
rc = RcFromSearchWerr(werr);
return rc;
}
/*----------------------------------------------------------------------------+
| RcNextMatchInFCM(qde, qfcm, qsmp) |
| |
| Given a SMP, finds the next SMP occurring in the same FC. |
| |
| Return codes: |
| |
| rcSuccess: *qsmp contains next match in FC. |
| rcNoExists: *qsmp contains next match after FC in the current help file. |
| rcFileChange: *qsmp contains next match after FC in different help file. |
| rcFailure: *qsmp is invalid: no more matches. |
| |
| |
| NOTE: Caller is currently ignoring any errors. |
+----------------------------------------------------------------------------*/
RC STDCALL RcNextMatchInFCM(qde, qfcm, qsmp)
QDE qde;
QFCM qfcm;
QSMP qsmp;
{
WORD werr;
DWORD dwaddr;
DWORD dwRU;
DWORD dwRUNew;
WORD wext;
RC rc;
PA paFirst;
#ifdef _DEBUG
DWORD dwaddrT;
#endif
/* Set PA to first region in FC */
paFirst.blknum = qfcm->va.bf.blknum;
paFirst.objoff = qfcm->cobjrgP;
dwRU = dwRUNew = (DWORD)qde->top.mtop.lTopicNo;
dwaddr = *(QDW)&qsmp->pa;
#ifdef _DEBUG
dwaddrT = dwaddr;
#endif
werr = ((FT_WerrNextMatchHs) SearchModule(FN_WerrNextMatchHs))(QDE_HRHFT(qde), \
(QDW)&dwRUNew, (QDW)&dwaddr, (QW)&wext);
qsmp->pa = *(QPA)&dwaddr;
qsmp->cobjrg = wext;
/* REVIEW: Make this into a macro */
if (paFirst.blknum != qsmp->pa.blknum
|| qsmp->pa.objoff >= paFirst.objoff + qfcm->cobjrg)
{
rc = rcNoExists;
}
else
rc = RcFromSearchWerr(werr);
#ifdef _DEBUG
if (rc == rcSuccess)
ASSERT(dwaddr != dwaddrT);
#endif
return rc;
}
/*----------------------------------------------------------------------------+
| FiniMatchInFCM(qde, qfcm) |
| |
+----------------------------------------------------------------------------*/
void STDCALL FiniMatchInFCM(qde, qfcm)
QDE qde;
QFCM qfcm;
{
DWORD dwRU;
DWORD dwaddr;
WORD wext;
Unreferenced(qfcm);
((FT_WerrRestoreCrsrHs) SearchModule(FN_WerrRestoreCrsrHs))
(QDE_HRHFT(qde), (QUL)&dwRU, (QUL)&dwaddr, (QW)&wext);
}
/*----------------------------------------------------------------------------+
| RcSetMatchList(qde, hwnd) |
| |
| Replaces the current hit list and sets the topic cursor. This takes an |
| HWND, which is bogus, but necessary. It gets the new list by doing a |
| new search (bringing up a dialog). |
+----------------------------------------------------------------------------*/
RC STDCALL RcSetMatchList(qde, hwnd)
QDE qde;
HWND hwnd;
{
WERR werr;
fOkToCallFtui = TRUE;
werr = ((FT_WerrBeginSearchHs) SearchModule(FN_WerrBeginSearchHs)) \
(hwnd, QDE_HRHFT(qde));
return RcFromSearchWerr(werr);
}
/*----------------------------------------------------------------------------+
| RcMoveTopicCursor(qde, wMode, wCmdWhere) |
| |
+----------------------------------------------------------------------------*/
RC STDCALL RcMoveTopicCursor(qde, wMode, wCmdWhere)
QDE qde;
WORD wMode;
WORD wCmdWhere;
{
DWORD dwRU;
DWORD dwaddr;
WORD wext;
WERR werr;
if (wMode == wMMMoveRelative)
{
switch (wCmdWhere)
{
case wMMMoveFirst:
werr = ((FT_WerrFirstHitHs) SearchModule(FN_WerrFirstHitHs))(QDE_HRHFT(qde),\
(QDW)&dwRU, (QDW)&dwaddr, (QW)&wext);
break;
case wMMMoveLast:
werr = ((FT_WerrLastHitHs) SearchModule(FN_WerrLastHitHs))(QDE_HRHFT(qde),\
(QDW)&dwRU, (QDW)&dwaddr, (QW)&wext);
break;
case wMMMovePrev:
werr = ((FT_WerrPrevHitHs) SearchModule(FN_WerrPrevHitHs))(QDE_HRHFT(qde),\
(QDW)&dwRU, (QDW)&dwaddr, (QW)&wext);
break;
case wMMMoveNext:
werr = ((FT_WerrNextHitHs) SearchModule(FN_WerrNextHitHs))(QDE_HRHFT(qde),\
(QDW)&dwRU, (QDW)&dwaddr, (QW)&wext);
break;
}
}
else
{
#ifndef UNIMPLEMENTED
werr = ER_NOMOREHITS;
#endif
}
return RcFromSearchWerr(werr);
}
/*----------------------------------------------------------------------------+
| RcGetCurrentMatch(qde, qla) |
| |
+----------------------------------------------------------------------------*/
RC STDCALL RcGetCurrentMatch(QDE qde, QLA qla)
{
WERR werr;
DWORD dwRU;
DWORD dwaddr;
WORD wext;
werr = ((FT_WerrCurrentMatchHs) SearchModule(FN_WerrCurrentMatchHs))(QDE_HRHFT(qde),\
(QDW)&dwRU, (QDW)&dwaddr, (QW)&wext);
CbReadMemQLA(qla, (LPBYTE)&dwaddr, QDE_HHDR(qde).wVersionNo);
MakeSearchMatchQLA(qla);
return RcFromSearchWerr(werr);
}
/***************************************************************************\
*
- Function:
- PaFromQde()
*
* Purpose:
* Calculate a PA from layout recorded in a qde. There are times when
* no search hits are visible/registered in the layout of the SR yet
* we need to figure out where we are so we know what to do when we
* receive a message from the search engine to move to the next match.
* What we do here is calculate what the PA is for the first visible
* frame is of the layout. We start with the first FC in the layout and
* walk the frames that compose it. We can't take the location of the
* start or end of the FC because they may not be exposed and using
* them might cause us to skip over matches between visible frames in
* the FC and these end-points. Once we've located the visible frame,
* we can construct a PA which we can then use to talk with to the
* search engine.
*
* Side Effects:
*
\***************************************************************************/
static DWORD PaFromQde(QDE qde)
{
POINT pt;
IFCM ifcm;
QFCM qfcm;
QFR qfr;
INT16 ifr;
PA pa;
/* Get a grip on the first FC in the layout. */
AccessMRD(((QMRD)&qde->mrdFCM));
ifcm = IFooFirstMRD((QMRD)&qde->mrdFCM);
qfcm = (QFCM)QFooInMRD(((QMRD)&qde->mrdFCM), sizeof(FCM), ifcm);
/* Figure out where the frame is relative to the display window
* so we can tell if frames are visible.
*/
pt.y = qde->rct.top + qfcm->yPos;
/* Walk the frames of the FC. As long as frames are invisible, keep
* looking. We stop looking as soon as we reach a visible point or
* we run out of frames.
*/
qfr = (QFR)PtrFromGh(qfcm->hfr);
for (ifr = 0; ifr < qfcm->cfr; ifr++, qfr++)
{
/* See if this frame is visible, loop until we reach it. */
if (qfr->yPos + pt.y > qde->rct.bottom ||
qfr->yPos + qfr->dySize + pt.y <= qde->rct.top)
continue;
/* We are now at the first visible frame in the FC */
break;
}
/* We are either at the first visible frame or we have fallen off the
* end of the FC for some reason. This should not happen. FC's exist at
* this time because they are supposed to be at least partially visible.
* Sometimes though, some SR qde's just have frames in them with no position
* information, such as mark new paragraph frames.
*/
ASSERT(qfcm->cfr != 0);
if (ifr >= qfcm->cfr)
qfr--;
/* Now that we've located our visible frame, construct a PA from
* the block number this FC is in, the starting objrg offset of the
* FC, and the frame objrg within the FC.
*/
pa.blknum = qfcm->va.bf.blknum;
pa.objoff = qfcm->cobjrgP + qfr->objrgFirst;
DeAccessMRD(((QMRD)&qde->mrdFCM));
return(*(QDW)&pa);
}
#define yFocusRect(qde) (((qde)->rct.bottom - (qde)->rct.top)/6)
/*----------------------------------------------------------------------------+
| RcGetNextHiddenMatch(qde, qla) |
| |
+----------------------------------------------------------------------------*/
RC STDCALL RcGetPrevNextHiddenMatch(QDE qde, QLA qla, BOOL fPrev)
{
WERR werr;
DWORD dwRU;
DWORD dwaddr;
DWORD dwaddrSav;
WORD wext;
INT16 ilsm;
QLSM qlsm;
QLSM qlsmFirst;
char szMatchFile[MAX_PATH];
char szCurrFile[MAX_PATH];
ASSERT(qde != NULL);
ASSERT(qla != NULL);
werr = ((FT_WerrFileNameForCur) SearchModule(FN_WerrFileNameForCur))
(QDE_HRHFT(qde), (LPSTR)szMatchFile);
// Hack for ftui32 -- force the .HLP file extension so we can compare names
ChangeExtension(szMatchFile, txtHlpExtension);
if (werr != ER_NOERROR)
goto error_return;
/*
* This may not be in the same file any longer: The user may have
* done other operations to switch the file from beneath us.
*/
werr = ((FT_WerrFileNameForCur) SearchModule(FN_WerrFileNameForCur))
(QDE_HRHFT(qde), (LPSTR)szMatchFile);
if (werr != ER_NOERROR)
goto error_return;
// Is the match file the same as this file?
GetFmParts(QDE_FM(qde), szCurrFile, PARTBASE | PARTEXT);
if (WCmpiSz(szCurrFile, szMatchFile) != 0) {
werr = ER_SWITCHFILE;
goto error_return;
}
// Match Cursor is pointing at focus match
werr = ((FT_WerrCurrentMatchHs) SearchModule(FN_WerrCurrentMatchHs))(QDE_HRHFT(qde),
(QDW)&dwRU, (QDW)&dwaddr, (QW)&wext);
if (werr != ER_NOERROR)
goto error_return;
dwaddrSav = dwaddr;
/*
* If the focus match is not in this topic, just return the focus match.
* Note that the rest of this function knows that dwRU == qde->top.mtop.lTopicNo;
*/
if (dwRU != (DWORD)qde->top.mtop.lTopicNo)
goto done_looking;
/*
* If the focus match is in this topic, we ignore its location and
* determine the next/prev match solely by what the topic window sees.
*
* If we are not visible, skip to the next hit instead of the next match.
* The rectangle test duplicates that in LayoutDEATQLA.
*/
if (qde->rct.top >= qde->rct.bottom) {
if (fPrev) {
werr = ((FT_WerrPrevHitHs) SearchModule(FN_WerrPrevHitHs))(QDE_HRHFT(qde),
(QDW)&dwRU, (QDW)&dwaddr, (QW)&wext);
}
else {
werr = ((FT_WerrNextHitHs)
SearchModule(FN_WerrNextHitHs))(QDE_HRHFT(qde),
(QDW)&dwRU, (QDW)&dwaddr, (QW)&wext);
}
if (werr != ER_NOERROR)
goto error_return;
goto done_looking;
}
ilsm = IFooFirstMRD((QMRD)(&qde->mrdLSM));
if (ilsm == FOO_NIL) {
DWORD dwaddrT;
/*
* No layout search matches are visible. Get the next nearest
* match (if it exists) to the address of the first layout FC. If we
* want the previous match, we need to go back one. Note that dwRU
* is equal to qde->top.mtop.lTopicNo by this point.
*/
dwaddrT = dwaddr = PaFromQde(qde);
werr = ((FT_WerrNearestMatchHs) SearchModule(FN_WerrNearestMatchHs))
(QDE_HRHFT(qde), dwRU, (QDW)&dwaddr, (QW)&wext);
if (fPrev) {
werr = ((FT_WerrPrevMatchHs) SearchModule(FN_WerrPrevMatchHs))(QDE_HRHFT(qde),
(QDW)&dwRU, (QDW)&dwaddr, (QW)&wext);
}
else {
if (werr == ER_NOMOREHITS) {
dwaddr = dwaddrT;
werr = ((FT_WerrNextHitHs) SearchModule(FN_WerrNextHitHs))
(QDE_HRHFT(qde), &dwRU, (QDW)&dwaddr, (QW)&wext);
}
}
if (werr != ER_NOERROR)
goto error_return;
goto done_looking;
}
else
{
INT16 ilsmSav;
LSM lsmSav;
LSM lsmVisible;
INT16 x;
INT16 y;
BOOL fVisible;
BOOL fSawVisible = FALSE;
INT16 xSav = 0;
INT16 ySav = 0;
QFCM qfcm;
RECT rct;
ilsmSav = FOO_NIL;
lsmVisible.smp.pa.blknum = 0;
lsmVisible.smp.pa.objoff = 0;
qlsmFirst = ((QLSM)QFooInMRD(((QMRD)&qde->mrdLSM), sizeof(LSM), ilsm));
do
{
qlsm = ((QLSM)QFooInMRD(((QMRD)&qde->mrdLSM), sizeof(LSM), ilsm));
qfcm = (QFCM)QFooInMRD(((QMRD)&qde->mrdFCM), sizeof(FCM), qlsm->ifcm);
x = qde->rct.left - qde->xScrolled + qfcm->xPos;
y = qde->rct.top + qfcm->yPos;
rct = qlsm->rctFirst;
fVisible = y + rct.top >= 0 && x + rct.left >= 0;
fVisible = fVisible && y + rct.bottom < qde->rct.bottom;
fVisible = fVisible && x + rct.right < qde->rct.right;
if (fVisible)
{
if (*(QDW)&qlsm->smp.pa > *(QDW)&lsmVisible.smp.pa)
lsmVisible = *qlsm;
fSawVisible = TRUE;
continue;
}
if (fPrev)
{
/* Rules for determining PREV match */
/* LSM yPos less than focus yPos */
if (y + rct.bottom > yFocusRect(qde))
continue;
/* LSM yPos greater than focus yPos */
if (y + rct.bottom < yFocusRect(qde))
{
/* LSM yPos less than saved LSM yPos */
if (ilsmSav == FOO_NIL
|| (y + rct.bottom > ySav + lsmSav.rctFirst.bottom)
|| (y + rct.bottom == ySav + lsmSav.rctFirst.bottom
&& x + rct.right > xSav + lsmSav.rctFirst.right))
{
ilsmSav = ilsm;
lsmSav = *qlsm;
xSav = x;
ySav = y;
continue;
}
}
}
else
{
/* Rules for determining NEXT match */
/* LSM yPos less than focus yPos */
if (y + rct.top < yFocusRect(qde))
continue;
/* LSM yPos greater than focus yPos */
if (y + rct.top > yFocusRect(qde))
{
/* LSM yPos less than saved LSM yPos */
if (ilsmSav == FOO_NIL
|| (y + rct.top < ySav + lsmSav.rctFirst.top)
|| (y + rct.top == ySav + lsmSav.rctFirst.top
&& x + rct.left < xSav + lsmSav.rctFirst.left))
{
ilsmSav = ilsm;
lsmSav = *qlsm;
xSav = x;
ySav = y;
continue;
}
}
}
} while ((ilsm = IFooNextMRD(((QMRD)&qde->mrdLSM), sizeof(LSM), ilsm)) !=
FOO_NIL);
/* Either use the winning match if we found one (ilsmSav != FOO_NIL), or
* get the PREV/NEXT match of the first/last match in the list.
*/
if (ilsmSav == FOO_NIL)
{
if (fPrev)
dwaddr = *(QDW)&qlsmFirst->smp.pa;
else
{
dwaddr = *(QDW)&qlsm->smp.pa;
if (fSawVisible)
dwaddr = max(dwaddr, *(QDW)&lsmVisible.smp.pa);
}
werr = ((FT_WerrNearestMatchHs) SearchModule(FN_WerrNearestMatchHs))
(QDE_HRHFT(qde), dwRU, (QDW)&dwaddr, (QW)&wext);
if (werr != ER_NOERROR)
goto error_return;
if (fPrev)
{
werr = ((FT_WerrPrevMatchHs) SearchModule(FN_WerrPrevMatchHs))(QDE_HRHFT(qde),\
(QDW)&dwRU, (QDW)&dwaddr, (QW)&wext);
}
else
{
werr = ((FT_WerrNextMatchHs) SearchModule(FN_WerrNextMatchHs))(QDE_HRHFT(qde),\
(QDW)&dwRU, (QDW)&dwaddr, (QW)&wext);
}
if (werr != ER_NOERROR)
goto error_return;
goto done_looking;
}
else
{
dwaddr = *(QDW)&lsmSav.smp.pa;
/*
* Set the new focus match location. I don't know a better
* way to do this.
*/
werr = ((FT_WerrNearestMatchHs) SearchModule(FN_WerrNearestMatchHs))
(QDE_HRHFT(qde), dwRU, (QDW)&dwaddr, (QW)&wext);
if (werr != ER_NOERROR)
goto error_return;
goto done_looking;
}
}
done_looking:
/*
* Did we go anywhere? If not, for any reason, we must force PREV/NEXT.
*/
if (dwaddr == dwaddrSav)
{
if (fPrev)
{
werr = ((FT_WerrPrevMatchHs) SearchModule(FN_WerrPrevMatchHs))(QDE_HRHFT(qde),
(QDW)&dwRU, (QDW)&dwaddr, (QW)&wext);
}
else
{
werr = ((FT_WerrNextMatchHs) SearchModule(FN_WerrNextMatchHs))(QDE_HRHFT(qde),
(QDW)&dwRU, (QDW)&dwaddr, (QW)&wext);
}
if (werr != ER_NOERROR)
goto error_return;
}
/* Previous match may take us into the NSR. If we have done a previous
* match and we're still in the same topic and the match is in the NSR or
* we cannot resolve the PA into a VA, then we assume the reason (this
* is kind of bogus but it may do for now) we couldn't was the PA was
* in the NSR. In any event, we just jump to the previous topic.
*/
if (fPrev && dwRU == (DWORD)qde->top.mtop.lTopicNo)
{
CbReadMemQLA(qla, (LPBYTE)&dwaddr, QDE_HHDR(qde).wVersionNo);
MakeSearchMatchQLA(qla);
VAFromQLA(qla, qde);
if (qla->mla.va.dword < qde->top.mtop.vaSR.dword || qla->mla.va.dword == vaNil)
{
ASSERT(qla->mla.va.dword >= qde->top.mtop.vaNSR.dword);
werr = ((FT_WerrPrevHitHs) SearchModule(FN_WerrPrevHitHs))(QDE_HRHFT(qde),
(QDW)&dwRU, (QDW)&dwaddr, (QW)&wext);
if (werr != ER_NOERROR)
goto error_return;
}
}
CbReadMemQLA(qla, (LPBYTE) &dwaddr, QDE_HHDR(qde).wVersionNo);
MakeSearchMatchQLA(qla);
error_return:
return RcFromSearchWerr(werr);
}
/*----------------------------------------------------------------------------+
| RcGetCurrMatchFile(qde, qch) |
| |
+----------------------------------------------------------------------------*/
RC STDCALL RcGetCurrMatchFile(QDE qde, LPSTR qch)
{
WERR werr;
werr = ((FT_WerrFileNameForCur) SearchModule(FN_WerrFileNameForCur))\
(QDE_HRHFT(qde), (LPSTR)qch);
return RcFromSearchWerr(werr);
}
static RC RcFromSearchWerr(int werr)
{
switch (werr) {
case ER_NOERROR:
return rcSuccess;
case ER_SWITCHFILE:
return rcFileChange;
case ER_NOHITS:
case ER_NOMOREHITS:
default:
return rcFailure;
}
}
RC STDCALL RcProcessNavSrchCmd(HDE hde, WORD wNavSrchCmd, QLA qla)
{
QDE qde;
RC rc;
WORD wPos;
LA la;
if (hde == NULL)
return rcBadHandle;
qde = QdeFromGh(hde);
switch (wNavSrchCmd) {
case wNavSrchInit:
rc = rcSuccess;
break;
case wNavSrchFini:
rc = rcSuccess;
break;
case wNavSrchHiliteOn:
case wNavSrchHiliteOff:
if (FGetMatchState() != (wNavSrchCmd == wNavSrchHiliteOn))
{
/*
* We no longer call DrawSearchMatches here. As it turns
* out, the window will be completely redrawn anyway, since the
* caller will do an InvalidateRect on the topic window.
*
* The original intent was that DrawSearchMatches would
* redraw ONLY the highlights, and make the InvalidateRect
* uneccessary. However there's some kind of bug that causes
* this call to draw the highlights off position. The solution
* for now is to avoid that, and just repaint the topic.
*
* 06-Aug-1991 LeoN
*/
// DrawSearchMatches(qde, TRUE);
SetMatchState (wNavSrchCmd == wNavSrchHiliteOn);
return rcSuccess;
}
return rcFailure;
break;
case wNavSrchQuerySearchable:
rc = (FSearchModuleExists(qde) && QDE_HRHFT(qde) != NULL)
? rcSuccess : rcFailure;
break;
case wNavSrchQueryHasMatches:
rc = (FSearchMatchesExist(qde)) ? rcSuccess : rcFailure;
break;
case wNavSrchCurrTopic:
rc = RcGetCurrentMatch(qde, (QLA) &la);
break;
case wNavSrchFirstTopic:
case wNavSrchLastTopic:
wPos = (wNavSrchCmd == wNavSrchFirstTopic) ?
wMMMoveFirst : wMMMoveLast;
rc = RcMoveTopicCursor(qde, wMMMoveRelative, wPos);
if (rc != rcFailure)
RcGetCurrentMatch(qde, (QLA)&la);
break;
case wNavSrchPrevTopic:
case wNavSrchNextTopic:
wPos = (wNavSrchCmd == wNavSrchPrevTopic) ?
wMMMovePrev : wMMMoveNext;
rc = RcMoveTopicCursor(qde, wMMMoveRelative, wPos);
if (rc != rcFailure)
RcGetCurrentMatch(qde, (QLA)&la);
break;
case wNavSrchPrevMatch:
case wNavSrchNextMatch:
rc = RcGetPrevNextHiddenMatch(qde, (QLA)&la,
wNavSrchCmd == wNavSrchPrevMatch);
break;
default:
NotReached();
}
if (qla != NULL)
*qla = la;
return rc;
}
/***************************************************************************
*
- Name: CallSearch
-
* Purpose
*
* Arguments
*
* Returns
*
* +++
*
* Notes
*
***************************************************************************/
RC STDCALL RcCallSearch(HDE hde, HWND hwnd)
{
QDE qde = QdeFromGh(hde);
RC rc;
if (FSearchModuleExists(qde) && QDE_HRHFT(qde) != NULL)
rc = RcSetMatchList(qde, hwnd);
else
rc = rcFailure;
return rc;
}
RC STDCALL RcResetCurrMatchFile(HDE hde)
{
RC rc = rcFailure;
QDE qde;
char rgch[MAX_PATH];
qde = QdeFromGh(hde);
if ((rc = RcGetCurrMatchFile(qde, rgch)) == rcSuccess) {
rc = (FWinHelp(rgch, cmdSrchSet, (LONG)QDE_HRHFT(qde))) ?
rcSuccess : rcFailure;
}
return rc;
}
#endif // RAWHIDE
/*----------------------------------------------------------------------------+
| RegisterSearchHits(qde, ifcm, qch) |
| |
| Each frame type, given a search hit address, knows how to figure out where |
| or if the hit occurs in that frame. |
| |
| We make some assumptions which simplify and speed up things greatly. |
| Assumptions: |
| |
| 1) Hits do not overlap. |
| 2) Frames in an FC are sorted by ascending objrgFirst. |
| 3) Hits in the same FCM are sorted by start address by the search engine. |
| |
| Notes: |
| The current hit is kept in smp. |
| |
+----------------------------------------------------------------------------*/
#ifdef RAWHIDE
void STDCALL RegisterSearchHits(qde, ifcm, qch)
QDE qde;
IFCM ifcm;
LPSTR qch;
{
QFR qfr;
SMP smp;
QFCM qfcm;
RECT rctFirst;
RECT rctLast;
OBJRG objrgS;
OBJRG cobjrg;
int ifrFirst;
int ifrLast;
int ifr;
DWORD wHitStatus;
if (!FSearchMatchesExist(qde))
return;
#if 0
/* we always record the hits, even if not highlighted, incase we need to
* turn on the highlighting without a relayout later.
*/
if (!FGetMatchState())
return;
#endif
qfcm = (QFCM)QFooInMRD(((QMRD)&qde->mrdFCM), sizeof(FCM), ifcm);
qfr = (QFR)PtrFromGh(qfcm->hfr);
ifr = 0;
if (RcInitMatchInFCM(qde, qfcm, &smp) != rcSuccess)
goto done_hits;
objrgS = OBJRGFromSMP(&smp, qfcm);
cobjrg = COBJRGFromSMP(&smp);
ifrFirst = ifrLast = FOO_NIL;
wHitStatus = wHitFindStart;
while (1)
{
if (ifr >= qfcm->cfr)
break;
if (qfr->objrgFirst == objrgNil)
goto next_frame;
switch (wHitStatus)
{
case wHitFindStart:
if (qfr->objrgFirst > objrgS)
objrgS = qfr->objrgFirst;
if (objrgS <= qfr->objrgLast && objrgS >= qfr->objrgFirst)
{
ASSERT(ifrFirst == FOO_NIL);
ASSERT(ifrLast == FOO_NIL);
ifrFirst = ifr;
rctFirst = RctFrameHit(qde, qfr, qch, objrgS, qfr->objrgLast);
/* Hack to get matches in SHED bitmaps to work: */
if (qfr->bType == bFrTypeColdspot)
{
cobjrg = 1;
}
wHitStatus = wHitFindEnd;
continue;
}
break;
case wHitFindEnd:
if (objrgS + cobjrg - 1 <= qfr->objrgLast &&
objrgS + cobjrg - 1 >= qfr->objrgFirst)
{
LSM lsm;
int ilsm;
ASSERT(ifrFirst != FOO_NIL);
ifrLast = ifr;
rctLast = RctFrameHit(qde, qfr, qch, qfr->objrgFirst, objrgS + cobjrg - 1);
/*
* In the case that a hit is contained within a single frame, the
* first and last frame rects get combined into the first rect.
*/
if (ifrLast == ifrFirst)
rctFirst.right = rctLast.right;
lsm.ifcm = ifcm;
lsm.ifrFirst = ifrFirst;
lsm.ifrLast = ifrLast;
lsm.rctFirst = rctFirst;
lsm.rctLast = rctLast;
lsm.smp = smp;
ilsm = IFooLastMRD(((QMRD)&qde->mrdLSM));
ilsm = IFooInsertFooMRD(((QMRD)&qde->mrdLSM), sizeof(LSM), ilsm);
*((QLSM)QFooInMRD(((QMRD)&qde->mrdLSM), sizeof(LSM), ilsm)) = lsm;
ifrFirst = ifrLast = FOO_NIL;
wHitStatus = wHitFindStart;
if (RcNextMatchInFCM(qde, qfcm, &smp) != rcSuccess)
goto done_hits;
objrgS = OBJRGFromSMP(&smp, qfcm);
cobjrg = COBJRGFromSMP(&smp);
continue;
}
break;
default:
NotReached();
}
next_frame:
++qfr;
++ifr;
}
done_hits:
FiniMatchInFCM(qde, qfcm);
}
static RECT RctFrameHit(QDE qde, QFR qfr, PSTR qch, OBJRG objrgS, OBJRG objrgE)
{
RECT rct;
switch (qfr->bType)
{
case bFrTypeText:
CalcTextMatchRect(qde, qch, qfr, objrgS, objrgE, &rct);
break;
case bFrTypeColdspot:
rct.left = qfr->xPos;
rct.right = rct.left + qfr->dxSize;
rct.top = qfr->yPos;
rct.bottom = rct.top + qfr->dySize;
break;
default:
NotReached();
break;
}
return rct;
}
/*----------------------------------------------------------------------------+
| ReleaseSearchHits(qde, ifcm) |
| |
| Frees any memory associated with search hits in the given FCM. |
+----------------------------------------------------------------------------*/
void STDCALL ReleaseSearchHits(QDE qde, int ifcm)
{
int ilsm;
int ilsmNext;
QLSM qlsm;
QFCM qfcm;
qfcm = (QFCM)QFooInMRD(((QMRD)&qde->mrdFCM), sizeof(FCM), ifcm);
ilsm = IFooFirstMRD((QMRD)(&qde->mrdLSM));
while (ilsm != FOO_NIL)
{
qlsm = ((QLSM)QFooInMRD(((QMRD)&qde->mrdLSM), sizeof(LSM), ilsm));
ilsmNext = IFooNextMRD(((QMRD)&qde->mrdLSM), sizeof(LSM), ilsm);
if (qlsm->ifcm == ifcm)
DeleteFooMRD(((QMRD)&qde->mrdLSM), sizeof(LSM), ilsm);
ilsm = ilsmNext;
}
}
void STDCALL DrawMatchesIfcm(QDE qde, IFCM ifcm, POINT pt, const RECT* qrct,
int ifrFirst, int ifrMax, BOOL fShow)
{
int ilsm;
QFCM qfcm;
QLSM qlsm;
INT16 ifrFirstT;
INT16 ifrMaxT;
/* Horrible, ugly hack: we do not draw highlights for secondary windows.
* 05-Aug-1991 LeoN
*/
// REVIEW: why not??? [ralphw]
if (FIsSecondaryQde(qde))
return;
qfcm = (QFCM)QFooInMRD(((QMRD)&qde->mrdFCM), sizeof(FCM), ifcm);
ilsm = IFooFirstMRD((QMRD)(&qde->mrdLSM));
ifrFirstT = ifrFirst;
ifrMaxT = ifrMax;
while (ilsm != FOO_NIL)
{
qlsm = ((QLSM)QFooInMRD(((QMRD)&qde->mrdLSM), sizeof(LSM), ilsm));
if (qlsm->ifcm == ifcm)
{
ifrFirstT = max(qlsm->ifrFirst, ifrFirst);
ifrMaxT = min(qlsm->ifrLast + 1, ifrMax);
if (ifrFirstT < ifrMaxT)
DrawMatchFrames(qde, qfcm, qlsm, pt, qrct, ifrFirstT, ifrMaxT, fShow);
}
ilsm = IFooNextMRD(((QMRD)&qde->mrdLSM), sizeof(LSM), ilsm);
}
}
INLINE static VOID DrawMatchFrames(qde, qfcm, qlsm, pt, qrct, ifrFirst, ifrMax, fShow)
QDE qde;
QFCM qfcm;
QLSM qlsm;
POINT pt;
const LPRECT qrct;
int ifrFirst;
int ifrMax;
BOOL fShow;
{
QFR qfr;
int ifr;
RECT rct;
BOOL fSelected;
BOOL fHotSpt;
MHI mhi;
qfr = (QFR)PtrFromGh(qfcm->hfr);
if (qde->imhiSelected != FOO_NIL) {
AccessMRD(((QMRD)&qde->mrdHot));
mhi = *(QMHI)QFooInMRD(((QMRD)&qde->mrdHot), sizeof(MHI), qde->imhiSelected);
DeAccessMRD(((QMRD)&qde->mrdHot));
}
for (ifr = ifrFirst, qfr += ifr; ifr < ifrMax; ifr++, qfr++) {
if (qrct != (LPRECT) NULL && (qfr->yPos + pt.y > qrct->bottom
|| qfr->yPos + qfr->dySize + pt.y <= qrct->top))
continue;
if (ifr == qlsm->ifrFirst)
rct = qlsm->rctFirst;
else
if (ifr == qlsm->ifrLast)
rct = qlsm->rctLast;
else
{
rct.top = qfr->yPos;
rct.bottom = qfr->yPos + qfr->dySize;
rct.left = qfr->xPos;
rct.right = qfr->xPos + qfr->dxSize;
}
if (qde->imhiSelected != FOO_NIL)
fSelected = qfr->lHotID == mhi.lHotID;
else
fSelected = FALSE;
fHotSpt = qfr->rgf.fHot;
DrawMatchRect(qde, pt, &rct, fShow, fSelected, fHotSpt);
/* Start ugly bug #1173 hack
* We know here we are drawing a search hit. If the search hit is
* the first one of the search set, we disable the Prev results button
* and if the last one, disable the Next button.
* Check that the topics, address, and extent agree between the match
* we are drawing and the first and last matches in the search set.
* Disable if we have determined they are enabled and can be disabled.
*/
if (dwRUFirst == (DWORD)qde->top.mtop.lTopicNo &&
dwaddrFirst == *((DWORD *)&qlsm->smp.pa) &&
(DWORD)wextFirst == qlsm->smp.cobjrg)
fMorePrevMatches &= ~RESULTSENABLED;
if (dwRULast == (DWORD)qde->top.mtop.lTopicNo &&
dwaddrLast == *((DWORD *)&qlsm->smp.pa) &&
(DWORD)wextLast == qlsm->smp.cobjrg)
fMoreNextMatches &= ~RESULTSENABLED;
/* End ugly bug #1173 hack */
}
}
INLINE static VOID DrawMatchRect(qde, pt, qrct, fShow, fSelected, fHotSpt)
QDE qde;
POINT pt;
LPRECT qrct;
BOOL fShow;
BOOL fSelected;
BOOL fHotSpt;
{
HSGC hsgc;
hsgc = HsgcFromQde(qde);
Unreferenced(fHotSpt);
Unreferenced(fSelected);
// if (fShow)
{
RECT rctT;
rctT.left = pt.x + qrct->left;
rctT.top = pt.y + qrct->top;
rctT.right = pt.x + qrct->right;
rctT.bottom = pt.y + qrct->bottom;
InvertRect(hsgc, &rctT);
}
FreeHsgc(hsgc);
}
BOOL STDCALL FSearchMatchVisible(qde, qsmp)
QDE qde;
QSMP qsmp;
{
INT16 x;
INT16 y;
RECT rct;
int ilsm;
BOOL fVisible = FALSE;
QLSM qlsm;
QFCM qfcm;
ilsm = IFooFirstMRD(((QMRD)&qde->mrdLSM));
while (ilsm != FOO_NIL)
{
qlsm = ((QLSM)QFooInMRD(((QMRD)&qde->mrdLSM), sizeof(LSM), ilsm));
if (*(QDW)&qlsm->smp.pa == *(QDW)&qsmp->pa)
{
/* look at screen */
qfcm = (QFCM)QFooInMRD(((QMRD)&qde->mrdFCM), sizeof(FCM), qlsm->ifcm);
x = qde->rct.left - qde->xScrolled + qfcm->xPos;
y = qde->rct.top + qfcm->yPos;
rct = qlsm->rctFirst;
fVisible = (y + rct.top >= 0 && y + rct.bottom < qde->rct.bottom
&& x + rct.left >= 0 && x + rct.right < qde->rct.right);
if (fVisible)
break;
}
ilsm = IFooNextMRD(((QMRD)&qde->mrdLSM), sizeof(LSM), ilsm);
}
return fVisible;
}
/* Start ugly bug #1173 hack */
/***************************************************************************\
*
- Function:
- ResultsButtonsStart()
*
* Purpose:
* The purpose of this function is to initialize two flags for the state of
* the Next/Prev buttons in the Search Results dialog and store the location
* of the first and last matches. We do this when we change topics before
* drawing any layout. As we draw search matches, we note if any of them are
* the same as the first and last and disable the Next/Prev results buttons
* appropriately.
*
* Side Effects:
* Sets the state of fMorePrevMatches and fMoreNextMatches. See
* definition of RESULT* for explanation of states.
*
\***************************************************************************/
void STDCALL ResultsButtonsStart(HDE hde)
{
QDE qde;
qde = QdeFromGh(hde);
/* If we get a werr other than ER_NOERROR for WerrFirst/LastHitHs
* then we leave the buttons on no matter what. This is from a first
* or last hit in a different file. Otherwise, we set them as enabled
* so that we can disable them later as we draw the topic and see the
* first or last hit.
*/
if (FSearchMatchesExist(qde) && FGetMatchState()) {
WORD werr;
werr = ((FT_WerrFirstHitHs)
SearchModule(FN_WerrFirstHitHs)) (QDE_HRHFT(qde),
(QUL) &dwRUFirst, (QUL) &dwaddrFirst, (QW) &wextFirst);
fMorePrevMatches = (werr == ER_NOERROR ? RESULTSENABLED : RESULTSON);
werr = ((FT_WerrLastHitHs)
SearchModule(FN_WerrLastHitHs))(QDE_HRHFT(qde), (QUL)&dwRULast,
(QUL) &dwaddrLast, (QW) &wextLast);
fMoreNextMatches = (werr == ER_NOERROR ? RESULTSENABLED : RESULTSON);
}
else
// No search active, don't do anything
fMorePrevMatches = fMoreNextMatches = RESULTSNIL;
}
/***************************************************************************\
*
- Function:
- ResultsButtonsEnd()
*
* Purpose:
* If we drew a layout and there are search results active, tell the results
* dialog what the state of the next/prev buttons should be after we've
* completed drawing the layout based on whether we've seen the first or
* last search hit.
*
* Side Effects:
* Sets internal state in the search results ftui.dll
*
\***************************************************************************/
void STDCALL ResultsButtonsEnd(QDE qde)
{
if (fMorePrevMatches != RESULTSNIL || fMoreNextMatches != RESULTSNIL) {
if (FSearchMatchesExist(qde) && FGetMatchState())
((FT_VSetPrevNextEnable) SearchModule(FN_VSetPrevNextEnable))(QDE_HRHFT(qde), qde->top.mtop.lTopicNo, fMorePrevMatches, fMoreNextMatches);
}
}
/* End ugly bug #1173 hack */
INLINE static void STDCALL CalcTextMatchRect(QDE qde, LPSTR qch,
QFR qfr, OBJRG objrgFirst, OBJRG objrgLast, RECT *qrct)
{
RECT rct;
ASSERT(objrgLast >= objrgFirst);
ASSERT(qfr->u.frt.wStyle != wStyleNil);
if (qde->wStyleTM != qfr->u.frt.wStyle)
{
SelFont(qde, qfr->u.frt.wStyle);
GetFontInfo(qde, (QTM)&qde->tm);
qde->wStyleTM = qde->wStyleDraw = qfr->u.frt.wStyle;
}
rct.top = qfr->yPos;
rct.bottom = qfr->yPos + qfr->dySize;
rct.left = qfr->xPos;
if (qfr->objrgFirst != objrgFirst)
{
rct.left += DxFrameTextWidth(qde, qfr, qch,
(objrgFirst - qfr->objrgFirst));
rct.left -= qde->tm.tmOverhang;
}
if (qfr->objrgLast == objrgLast)
rct.right = qfr->xPos + qfr->dxSize;
else
rct.right = qfr->xPos + DxFrameTextWidth(qde, qfr, qch,
(objrgLast - qfr->objrgFirst + 1));
*qrct = rct;
}
static int STDCALL DxFrameTextWidth(QDE qde, QFR qfr, PSTR qch, int cch)
{
if (cch == 0)
return 0;
if (qfr->libHotBinding != libHotNil)
return FindSplTextWidth(qde, qch, qfr->u.frt.lichFirst, cch,
*((PBYTE)qch - qfr->libHotBinding));
else
return FindTextWidth(qde->hdc, qch, qfr->u.frt.lichFirst, cch);
}
#endif