mirror of https://github.com/lianthony/NT4.0
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.
401 lines
11 KiB
401 lines
11 KiB
/*****************************************************************************
|
|
*
|
|
* frfc.c
|
|
* Copyright (C) Microsoft Corporation 1990.
|
|
* All Rights reserved.
|
|
*
|
|
******************************************************************************
|
|
*
|
|
* This file contains code for handling FCs in the layout manager.
|
|
*
|
|
* FCs (Full Context Points) are one of the key concepts of the layout
|
|
* manager. An FC is a piece of layout material which contains all of the
|
|
* information needed to display it. A display topic is nothing more than a
|
|
* series of FCs. FCs are never side by side- they are always stacked.
|
|
*
|
|
* FCs are laid out in a logical coordinate space where 0,0 corresponds to
|
|
* the upper-left-hand corner of the layout area. 0,0 in FC coordinates,
|
|
* therefore, corresponds to de.rct.left,de.rct.top in display device
|
|
* coordinates. All coordinates passed into frfc.c are in FC coordinates.
|
|
*
|
|
* FCs are stored in an MRD.
|
|
* The data structures in the FCM are as follows:
|
|
* HANDLE hfr; handle to array of FRs. Always exists, even when
|
|
* there are no frames (the size is padded by 1).
|
|
* INT fExport; used for text export?
|
|
* HFC hfc; HFC containing raw layout data for this FC
|
|
* FCID fcid; FCID of this FC
|
|
* INT xPos; position of the FC in FC space
|
|
* INT yPos;
|
|
* INT dxSize; size of the FC
|
|
* INT dySize;
|
|
* INT cfr; total number of frames in the FC. This may be 0.
|
|
* INT wStyle; current text style for this FC. Only for layout.
|
|
* INT imhiFirst; hotspot manager info
|
|
* INT imhiLast;
|
|
*
|
|
******************************************************************************
|
|
*
|
|
* Testing Notes
|
|
*
|
|
******************************************************************************
|
|
*
|
|
* Current Owner:
|
|
*
|
|
******************************************************************************
|
|
*
|
|
* Released by Development:
|
|
*
|
|
******************************************************************************
|
|
*
|
|
* Revision History:
|
|
* 15-Aug-1989 MattB Created
|
|
* 24-Oct-1990 LeoN JumpButton takes a pointer to its arg. Minor clenaup
|
|
* 04-Nov-1990 Tomsn Use new VA address type (enabling zeck compression).
|
|
* 30-Jul-1991 LeoN HELP31 #1244: remove fHiliteMatches from DE. Add
|
|
* FSet/GetMatchState
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "help.h"
|
|
|
|
#include "inc\frstuff.h"
|
|
|
|
/*-------------------------------------------------------------------------
|
|
| IfcmLayout(qde, hfc, yPos, fFirst, fExport) |
|
|
| |
|
|
| Purpose: This lays out a new FC corresponding to the passed HFC, and |
|
|
| returns its IFCM. |
|
|
| Params: qde qde to use |
|
|
| hfc hfc containing raw layout data |
|
|
| yPos vertical position of this FCM |
|
|
| fFirst TRUE if FCM is first in layout chain |
|
|
| fExport TRUE if FCM is being used for text export. |
|
|
| Method: Each FC contains a single layout object, so all we do is call |
|
|
| LayoutObject() to lay it out. During layout, all frames are |
|
|
| placed in temporary storage provided by de.mrfr. After |
|
|
| layout, we increase the size of hfcm, and append the frames |
|
|
| after the fcm structure. |
|
|
-------------------------------------------------------------------------*/
|
|
|
|
IFCM STDCALL IfcmLayout(QDE qde, HFC hfc, int yPos, BOOL fFirst, BOOL fExport)
|
|
{
|
|
IFCM ifcm;
|
|
QFCM qfcm;
|
|
QB qbObj, qb;
|
|
MOBJ mobj;
|
|
LPSTR qchText;
|
|
int cfr;
|
|
OLR olr;
|
|
|
|
if (fFirst)
|
|
ifcm = IFooInsertFooMRD(((QMRD)&qde->mrdFCM), sizeof(FCM), FOO_NIL);
|
|
else
|
|
ifcm = IFooInsertFooMRD(((QMRD)&qde->mrdFCM), sizeof(FCM), IFooLastMRD(((QMRD)&qde->mrdFCM)));
|
|
qfcm = (QFCM)QFooInMRD(((QMRD)&qde->mrdFCM), sizeof(FCM), ifcm);
|
|
qfcm->fExport = fExport;
|
|
qfcm->hfc = hfc;
|
|
qfcm->va = VaFromHfc(hfc);
|
|
qfcm->xPos = xLeftFCMargin;
|
|
qfcm->yPos = yPos;
|
|
qfcm->cfr = 0;
|
|
qfcm->wStyle = wStyleNil;
|
|
ClearMR((QMR)&qde->mrFr);
|
|
|
|
qbObj = (QB) QobjLockHfc(hfc);
|
|
#ifdef _X86_
|
|
qchText = qbObj + CbUnpackMOBJ((QMOBJ)&mobj, qbObj);
|
|
#else
|
|
qchText = qbObj + CbUnpackMOBJ((QMOBJ)&mobj, qbObj, QDE_ISDFFTOPIC(qde));
|
|
#endif
|
|
qchText += mobj.lcbSize;
|
|
|
|
qfcm->cobjrg = (COBJRG)mobj.wObjInfo;
|
|
#ifdef RAWHIDE
|
|
qfcm->cobjrgP = CobjrgFromHfc(hfc);
|
|
#endif
|
|
|
|
olr.xPos = olr.yPos = 0;
|
|
olr.ifrFirst = 0;
|
|
olr.objrgFirst = 0;
|
|
olr.objrgFront = objrgNil;
|
|
|
|
AccessMR((QMR)&qde->mrFr);
|
|
LayoutObject(qde, qfcm, qbObj, qchText, qde->rct.right - qde->rct.left
|
|
- xLeftFCMargin, &olr);
|
|
|
|
cfr = qfcm->cfr = olr.ifrMax;
|
|
|
|
/*
|
|
* REVIEW: This is pretty gross. cfr can be 0, but we always want to
|
|
* allocate an hfr, so that we don't have to check for it everywhere.
|
|
*/
|
|
|
|
qfcm->hfr = GhForceAlloc(0, cfr * sizeof(FR) + 1);
|
|
qb = PtrFromGh(qfcm->hfr);
|
|
MoveMemory((QB)qb, (QB)QFooInMR((QMR)&qde->mrFr, sizeof(FR), 0),
|
|
cfr * sizeof(FR));
|
|
DeAccessMR((QMR)&qde->mrFr);
|
|
|
|
qfcm->dxSize = olr.dxSize;
|
|
qfcm->dySize = olr.dySize;
|
|
if (!fExport) {
|
|
RegisterHotspots(qde, ifcm, fFirst);
|
|
#ifdef RAWHIDE
|
|
RegisterSearchHits(qde, ifcm, qchText);
|
|
#endif
|
|
}
|
|
|
|
return ifcm;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
| DrawIfcm(qde, ifcm, pt, qrct, ifrFirst, ifrMax) |
|
|
| |
|
|
| Purpose: Draws a specified set of frames in an FCM. |
|
|
| Params: qde qde to use |
|
|
| pt offset between FC space and display space |
|
|
| qrct rectangle containing the area we want to draw. |
|
|
| This is for efficiency only- we don't handle |
|
|
| clipping. If qrct == NULL, it's ignored. |
|
|
| ifrFirst First frame to draw |
|
|
| ifrMax Max of frames to draw (ie, ifrMax isn't drawn) |
|
|
-------------------------------------------------------------------------*/
|
|
|
|
void STDCALL DrawIfcm(QDE qde, IFCM ifcm, POINT pt, LPRECT qrct, int ifrFirst,
|
|
int ifrMax, BOOL fErase)
|
|
{
|
|
QFCM qfcm;
|
|
QB qbObj;
|
|
MOBJ mobj;
|
|
LPSTR qchText;
|
|
QFR qfr;
|
|
QFR qfrStart;
|
|
int ifr;
|
|
|
|
qfcm = (QFCM)QFooInMRD(((QMRD)&qde->mrdFCM), sizeof(FCM), ifcm);
|
|
ASSERT(!qfcm->fExport);
|
|
pt.x += qfcm->xPos;
|
|
pt.y += qfcm->yPos;
|
|
if (qrct != NULL && (pt.y > qrct->bottom || pt.y + qfcm->dySize <= qrct->top))
|
|
return;
|
|
|
|
qbObj = (QB) QobjLockHfc(qfcm->hfc);
|
|
#ifdef _X86_
|
|
qchText = qbObj + CbUnpackMOBJ((QMOBJ)&mobj, qbObj);
|
|
#else
|
|
qchText = qbObj + CbUnpackMOBJ((QMOBJ)&mobj, qbObj, QDE_ISDFFTOPIC(qde));
|
|
#endif
|
|
qchText += mobj.lcbSize;
|
|
|
|
qfrStart = qfr = (QFR)PtrFromGh(qfcm->hfr);
|
|
|
|
for (ifr = ifrFirst, qfr += ifr; ifr < ifrMax; ifr++, qfr++)
|
|
{
|
|
if (qrct != NULL && (qfr->yPos + pt.y > qrct->bottom
|
|
|| qfr->yPos + qfr->dySize + pt.y <= qrct->top))
|
|
continue;
|
|
switch(qfr->bType) {
|
|
case bFrTypeText:
|
|
DrawTextFrame(qde, qchText, qfr, pt, fErase);
|
|
break;
|
|
|
|
case bFrTypeAnno:
|
|
DrawAnnoFrame(qde, qfr, pt);
|
|
break;
|
|
|
|
case bFrTypeBitmap:
|
|
DrawBitmapFrame(qde, qfr, pt, fErase);
|
|
break;
|
|
|
|
case bFrTypeHotspot:
|
|
DrawHotspotFrame(qde, qfr, pt, fErase);
|
|
break;
|
|
|
|
case bFrTypeBox:
|
|
DrawBoxFrame(qde, qfr, pt);
|
|
break;
|
|
|
|
case bFrTypeWindow:
|
|
DrawWindowFrame(qde, qfr, pt);
|
|
break;
|
|
|
|
case bFrTypeColdspot:
|
|
/* Currently never drawn */
|
|
/* DrawColdspot(qde, qfr, pt); */
|
|
break;
|
|
}
|
|
#ifdef _DEBUG
|
|
#define coYELLOW RGB(255, 255, 0)
|
|
if (fDebugState & fDEBUGFRAME)
|
|
{
|
|
HSGC hsgc;
|
|
|
|
hsgc = (HSGC) HsgcFromQde(qde);
|
|
FSetPen(hsgc, 1, coDEFAULT, coYELLOW, wTRANSPARENT, roXOR, wPenSolid);
|
|
Rectangle(hsgc, pt.x + qfr->xPos, pt.y + qfr->yPos,
|
|
pt.x + qfr->xPos + qfr->dxSize, pt.y + qfr->yPos + qfr->dySize);
|
|
FreeHsgc(hsgc);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
#define coMAGENTA RGB(255, 0, 255)
|
|
if (fDebugState & fDEBUGFRAME)
|
|
{
|
|
HSGC hsgc;
|
|
|
|
hsgc = (HSGC) HsgcFromQde(qde);
|
|
FSetPen(hsgc, 1, coDEFAULT, coMAGENTA, wTRANSPARENT, roCOPY, wPenSolid);
|
|
Rectangle(hsgc, pt.x, pt.y, pt.x + qfcm->dxSize, pt.y + qfcm->dySize);
|
|
FreeHsgc(hsgc);
|
|
}
|
|
#endif /* DEBUG */
|
|
|
|
#ifdef RAWHIDE
|
|
if (FGetMatchState()) {
|
|
/*
|
|
* If printing, don't show search hilites. On HP printers, prints
|
|
* out black squares instead of text where the search matches are.
|
|
*/
|
|
|
|
if (qde->deType != dePrint)
|
|
DrawMatchesIfcm(qde, ifcm, pt, qrct, ifrFirst, ifrMax, fErase);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: ClickFC
|
|
|
|
PURPOSE: Handles a mouse click in an FC
|
|
|
|
PARAMETERS:
|
|
qde
|
|
ifcm
|
|
pt Offset between FC space and display space
|
|
|
|
RETURNS: TRUE if point is in a hotspot
|
|
|
|
COMMENTS:
|
|
|
|
MODIFICATION DATES:
|
|
13-Mar-1995 [ralphw]
|
|
|
|
***************************************************************************/
|
|
|
|
BOOL STDCALL ClickFC(QDE qde, IFCM ifcm, POINT pt)
|
|
{
|
|
QFCM qfcm;
|
|
QFR qfr;
|
|
int xNew, yNew, ifr;
|
|
|
|
qfcm = (QFCM)QFooInMRD(((QMRD)&qde->mrdFCM), sizeof(FCM), ifcm);
|
|
ASSERT(!qfcm->fExport);
|
|
qfr = (QFR) PtrFromGh(qfcm->hfr);
|
|
xNew = pt.x - qfcm->xPos;
|
|
yNew = pt.y - qfcm->yPos;
|
|
for (ifr = 0; ifr < qfcm->cfr; ifr++, qfr++) {
|
|
if (qfr->rgf.fHot
|
|
&& xNew >= qfr->xPos && xNew <= qfr->xPos + qfr->dxSize
|
|
&& yNew >= qfr->yPos && yNew <= qfr->yPos + qfr->dySize) {
|
|
FSelectHotspot(qde, FOO_NIL);
|
|
ClickFrame(qde, ifcm, ifr);
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
| DiscardIfcm(qde, ifcm) |
|
|
| |
|
|
| Purpose: Discards all memory associated with an FC |
|
|
-------------------------------------------------------------------------*/
|
|
|
|
static int count;
|
|
|
|
void STDCALL DiscardIfcm(QDE qde, int ifcm)
|
|
{
|
|
QFCM qfcm;
|
|
QFR qfr;
|
|
|
|
qfcm = (QFCM)QFooInMRD(((QMRD)&qde->mrdFCM), sizeof(FCM), ifcm);
|
|
qfr = (QFR)PtrFromGh(qfcm->hfr);
|
|
if (!qfcm->fExport) {
|
|
ReleaseHotspots(qde, ifcm);
|
|
#ifdef RAWHIDE
|
|
ReleaseSearchHits(qde, ifcm);
|
|
#endif
|
|
}
|
|
count++;
|
|
DiscardFrames(qde, qfr, qfr + qfcm->cfr);
|
|
|
|
if (qfcm->hfc != NULL)
|
|
lcClearFree(&qfcm->hfc);
|
|
|
|
if (qfcm->hfr)
|
|
lcClearFree(&qfcm->hfr);
|
|
DeleteFooMRD(((QMRD)&qde->mrdFCM), sizeof(FCM), ifcm);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
| DiscardFrames(qde, qfrFirst, qfrMax) |
|
|
| |
|
|
| Purpose: Discards all memory associated with a given set of frames. |
|
|
| Currently, only bitmap, window and possibly hotspot frames |
|
|
| allocate memory. |
|
|
-------------------------------------------------------------------------*/
|
|
void STDCALL DiscardFrames(QDE qde, QFR qfrFirst, QFR qfrMax)
|
|
{
|
|
QFR qfr;
|
|
|
|
for (qfr = qfrFirst; qfr < qfrMax; qfr++) {
|
|
switch (qfr->bType) {
|
|
case bFrTypeText:
|
|
case bFrTypeAnno:
|
|
break;
|
|
|
|
case bFrTypeBitmap:
|
|
DiscardBitmapFrame(qfr);
|
|
break;
|
|
|
|
case bFrTypeHotspot:
|
|
DiscardHotspotFrame(qfr);
|
|
break;
|
|
|
|
case bFrTypeWindow:
|
|
DiscardWindowFrame(qde, qfr);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/***************
|
|
**
|
|
** GH GhForceAlloc(WORD wFlags, DWORD lcb)
|
|
**
|
|
** purpose
|
|
** Create a handle to relocatable block
|
|
** Identical to GhAlloc, but dies in the event of an error
|
|
**
|
|
** arguments
|
|
** wFlags Memory allocation flags |'ed together
|
|
** lcb Number of bytes to allocate
|
|
**
|
|
** return value
|
|
** Handle to allocated block of memory, or NULL otherwise
|
|
**
|
|
***************/
|
|
|
|
GH STDCALL GhForceAlloc(UINT wFlags, DWORD lcb)
|
|
{
|
|
GH gh;
|
|
|
|
if ((gh = GhAlloc(wFlags, lcb)) == NULL)
|
|
OOM();
|
|
|
|
return gh;
|
|
}
|