Microsoft-3D-Movie-Maker/kauai/TOOLS/CHELP.CPP

1302 lines
29 KiB
C++

/* Copyright (c) Microsoft Corporation.
Licensed under the MIT License. */
/***************************************************************************
Help authoring tool.
***************************************************************************/
#include "chelp.h"
ASSERTNAME
BEGIN_CMD_MAP(APP, APPB)
ON_CID_GEN(cidNew, &APP::FCmdOpen, pvNil)
ON_CID_GEN(cidOpen, &APP::FCmdOpen, pvNil)
ON_CID_GEN(cidOpenText, &APP::FCmdOpen, pvNil)
ON_CID_GEN(cidOpenRichText, &APP::FCmdOpen, pvNil)
ON_CID_GEN(cidLoadResFile, &APP::FCmdLoadResFile, pvNil)
ON_CID_GEN(cidChooseLanguage, &APP::FCmdChooseLanguage,
&APP::FEnableChooseLanguage)
END_CMD_MAP_NIL()
BEGIN_CMD_MAP(LIG, GOB)
ON_CID_ME(cidDoScroll, FCmdScroll, pvNil)
ON_CID_ME(cidEndScroll, FCmdScroll, pvNil)
END_CMD_MAP_NIL()
APP vapp;
RTCLASS(APP)
RTCLASS(LIG)
RTCLASS(LID)
RTCLASS(CCG)
RTCLASS(CCGT)
STRG _strg;
PSTRG vpstrg;
SC_LID vsclid = ksclidAmerican;
PSPLC vpsplc;
/***************************************************************************
Main for a frame app.
***************************************************************************/
void FrameMain(void)
{
vpstrg = &_strg;
vapp.Run(fappNil, fgobNil, kginDefault);
ReleasePpo(&vpsplc);
}
#ifdef DEBUG
/***************************************************************************
Assert the validity of a APP.
***************************************************************************/
void APP::AssertValid(ulong grf)
{
APP_PAR::AssertValid(0);
AssertNilOrPo(_pcrm, 0);
AssertNilOrPo(_plidPicture, 0);
AssertNilOrPo(_plidButton, 0);
}
/***************************************************************************
Mark memory for the APP.
***************************************************************************/
void APP::MarkMem(void)
{
AssertValid(0);
APP_PAR::MarkMem();
MarkMemObj(_pcrm);
MarkMemObj(_plidPicture);
MarkMemObj(_plidButton);
MarkMemObj(&_strg);
MarkMemObj(vpsplc);
}
#endif //DEBUG
/***************************************************************************
Initialize the app. Add some stuff to the menus and do the command
line parsing thing.
***************************************************************************/
bool APP::_FInit(ulong grfapp, ulong grfgob, long ginDef)
{
static long _rgdypFont[] =
{ 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 24, 28, 32, 36, 0 };
struct LANG
{
PSZ psz;
long sclid;
};
static LANG _rglang[] =
{
{ PszLit("American"), ksclidAmerican },
{ PszLit("Australian"), ksclidAustralian },
{ PszLit("British"), ksclidBritish },
{ PszLit("German"), ksclidGerman },
{ PszLit("Swiss German"), ksclidSwissGerman },
{ PszLit("French"), ksclidFrench },
{ PszLit("French Canadian"), ksclidFrenchCanadian },
{ PszLit("Spanish"), ksclidSpanish },
{ PszLit("Catalan"), ksclidCatalan },
{ PszLit("Italian"), ksclidItalian },
{ PszLit("Other..."), 0 },
};
long iv, dyp;
STN stn;
if (!APP_PAR::_FInit(grfapp, grfgob, ginDef))
return fFalse;
vpmubCur->FRemoveAllListCid(cidChooseFontSize);
stn = PszLit("Other...");
vpmubCur->FAddListCid(cidChooseFontSize, 0, &stn);
for (iv = 0; (dyp = _rgdypFont[iv]) != 0; iv++)
{
stn.FFormatSz(PszLit("%d"), dyp);
vpmubCur->FAddListCid(cidChooseFontSize, dyp, &stn);
}
for (iv = 0; iv < CvFromRgv(_rglang); iv++)
{
stn = _rglang[iv].psz;
vpmubCur->FAddListCid(cidChooseLanguage, _rglang[iv].sclid, &stn);
}
#ifdef WIN
//parse the command line and load any resource files and help files
FNI fni;
bool fQuote, fRes, fSkip;
PSZ psz = vwig.pszCmdLine;
// skip the first token since it is the path
fSkip = fTrue;
fRes = fFalse;
for (;;)
{
while (*psz == kchSpace)
psz++;
if (!*psz)
break;
stn.SetNil();
fQuote = fFalse;
while (*psz && (fQuote || *psz != kchSpace))
{
if (*psz == ChLit('"'))
fQuote = !fQuote;
else
stn.FAppendCh(*psz);
psz++;
}
if (stn.Cch() == 0)
continue;
if (fSkip)
{
fSkip = fFalse;
continue;
}
if (stn.Cch() == 2 && (stn.Psz()[0] == ChLit('/') ||
stn.Psz()[0] == ChLit('-')))
{
// command line switch
switch (stn.Psz()[1])
{
case ChLit('r'):
case ChLit('R'):
fRes = fTrue;
break;
}
continue;
}
if (!fni.FBuildFromPath(&stn) || fni.Ftg() == kftgDir)
{
fRes = fFalse;
continue;
}
if (fRes)
FLoadResFile(&fni);
else
FOpenDocFile(&fni);
fRes = fFalse;
}
#endif //WIN
return fTrue;
}
/***************************************************************************
Get the name for the help editor app.
***************************************************************************/
void APP::GetStnAppName(PSTN pstn)
{
AssertThis(0);
AssertPo(pstn, 0);
#ifdef UNICODE
STN stnDate;
STN stnTime;
stnDate.SetSzs(__DATE__);
stnTime.SetSzs(__TIME__);
pstn->FFormatSz(Debug(PszLit("Debug ")) PszLit("Chelp (Unicode; %s; %s)"),
&stnDate, &stnTime);
#else //!UNICODE
*pstn = Debug("Debug ") "Chelp (Ansi; " __DATE__ "; " __TIME__ ")";
#endif //!UNICODE
}
/***************************************************************************
Update the given window. *prc is the bounding rectangle of the update
region.
***************************************************************************/
void APP::UpdateHwnd(HWND hwnd, RC *prc, ulong grfapp)
{
AssertThis(0);
PGOB pgob;
if (pvNil == (pgob = GOB::PgobFromHwnd(hwnd)))
return;
//for text windows, do offscreen updating
if (pgob->FIs(kclsDMD) && ((PDMD)pgob)->Pdocb()->FIs(kclsTXRD))
grfapp |= fappOffscreen;
APP_PAR::UpdateHwnd(hwnd, prc, grfapp);
}
/***************************************************************************
Do a fast update of the gob and its descendents into the given gpt.
***************************************************************************/
void APP::_FastUpdate(PGOB pgob, PREGN pregnClip, ulong grfapp, PGPT pgpt)
{
AssertThis(0);
//for text windows, do offscreen updating
if (pgob->FIs(kclsDMD) && ((PDMD)pgob)->Pdocb()->FIs(kclsTXRD))
grfapp |= fappOffscreen;
APP_PAR::_FastUpdate(pgob, pregnClip, grfapp, pgpt);
}
/***************************************************************************
Open an existing or new chunky file for editing.
Handles cidNew and cidOpen.
***************************************************************************/
bool APP::FCmdOpen(PCMD pcmd)
{
AssertThis(0);
AssertVarMem(pcmd);
FNI fni;
FNI *pfni;
pfni = pvNil;
switch (pcmd->cid)
{
default:
Bug("why are we here?");
return fTrue;
case cidOpen:
//do the standard dialog
if (!FGetFniOpenMacro(&fni, pvNil, 0,
PszLit("Kid Help Files\0*.khp;*.chk\0All Files\0*.*\0"),
vwig.hwndApp))
{
return fTrue;
}
pfni = &fni;
break;
case cidOpenText:
//do the standard dialog
if (!FGetFniOpenMacro(&fni, pvNil, 0,
PszLit("Text files\0*.txt\0All Files\0*.*\0"), vwig.hwndApp))
{
return fTrue;
}
pfni = &fni;
break;
case cidOpenRichText:
//do the standard dialog
if (!FGetFniOpenMacro(&fni, pvNil, 0,
PszLit("Rich Text files\0*.rtx\0All Files\0*.*\0"), vwig.hwndApp))
{
return fTrue;
}
pfni = &fni;
break;
case cidNew:
break;
}
FOpenDocFile(pfni, pcmd->cid);
return fTrue;
}
/***************************************************************************
Load a document file.
***************************************************************************/
bool APP::FOpenDocFile(PFNI pfni, long cid)
{
AssertThis(0);
AssertNilOrPo(pfni, 0);
bool fRet;
PDOCB pdocb;
PHEDO phedo;
PTXRD ptxrd;
if (pvNil != pfni && pvNil != (pdocb = DOCB::PdocbFromFni(pfni)))
{
pdocb->ActivateDmd();
return fTrue;
}
pdocb = pvNil;
switch (cid)
{
case cidOpenText:
if (pvNil == (ptxrd = TXRD::PtxrdNew(pvNil)))
return fFalse;
fRet = fFalse;
if (pvNil != pfni)
{
FLO flo;
if (pvNil == (flo.pfil = FIL::PfilOpen(pfni)))
goto LFail;
flo.fp = 0;
flo.cb = flo.pfil->FpMac();
fRet = ptxrd->FReplaceFlo(&flo, fTrue, 0, 0);
ReleasePpo(&flo.pfil);
if (!fRet)
{
LFail:
ReleasePpo(&ptxrd);
return fFalse;
}
}
pdocb = ptxrd;
break;
case cidOpenRichText:
if (pvNil == (pdocb = TXRD::PtxrdNew(pfni)))
return fFalse;
break;
default:
if (pvNil == _pcrm && pvNil == (_pcrm = CRM::PcrmNew(1)))
return fFalse;
if (pvNil == _plidPicture &&
pvNil == (_plidPicture = LID::PlidNew(_pcrm, kctgMbmp)))
{
return fFalse;
}
if (pvNil == _plidButton &&
pvNil == (_plidButton = LID::PlidNew(_pcrm, kctgGokd,
ChidFromSnoDchid(ksnoInit, 0))))
{
return fFalse;
}
phedo = HEDO::PhedoNew(pfni, _pcrm);
if (pvNil == phedo)
return fFalse;
pdocb = phedo;
break;
}
fRet = (pdocb->PdmdNew() != pvNil);
ReleasePpo(&pdocb);
return fRet;
}
/***************************************************************************
Open an existing or new chunky file for editing.
Handles cidNew and cidOpen.
***************************************************************************/
bool APP::FCmdLoadResFile(PCMD pcmd)
{
AssertThis(0);
AssertVarMem(pcmd);
FNI fni;
if (!FGetFniOpenMacro(&fni, pvNil, 0,
PszLit("Chunky Resource Files\0*.chk\0All Files\0*.*\0"),
vwig.hwndApp))
{
return fTrue;
}
FLoadResFile(&fni);
return fTrue;
}
/***************************************************************************
Load a resource file.
***************************************************************************/
bool APP::FLoadResFile(PFNI pfni)
{
AssertThis(0);
AssertPo(pfni, ffniFile);
PCFL pcfl;
long ipcrf;
PCRF pcrf;
BLCK blck;
if (pvNil == _pcrm && pvNil == (_pcrm = CRM::PcrmNew(1)))
return fFalse;
if (pvNil == (pcfl = CFL::PcflOpen(pfni, fcflNil)))
{
vpappb->TGiveAlertSz(PszLit("Can't open that file"), bkOk, cokStop);
return fFalse;
}
//see if it's already in the crm.
for (ipcrf = _pcrm->Ccrf(); ipcrf-- > 0; )
{
pcrf = _pcrm->PcrfGet(ipcrf);
if (pcfl == pcrf->Pcfl())
return fTrue;
}
if (!_pcrm->FAddCfl(pcfl, 0x100000L))
{
ReleasePpo(&pcfl);
return fFalse;
}
if (pcfl->FGetCkiCtg(kctgColorTable, 0, pvNil, pvNil, &blck))
{
PGL pglclr;
if (pvNil != (pglclr = GL::PglRead(&blck)) &&
pglclr->CbEntry() == size(CLR))
{
GPT::SetActiveColors(pglclr, fpalIdentity);
}
ReleasePpo(&pglclr);
}
ReleasePpo(&pcfl);
if (pvNil != _plidPicture)
_plidPicture->FRefresh();
if (pvNil != _plidButton)
_plidButton->FRefresh();
return fTrue;
}
/***************************************************************************
Check or uncheck the language as appropriate.
***************************************************************************/
bool APP::FEnableChooseLanguage(PCMD pcmd, ulong *pgrfeds)
{
AssertThis(0);
AssertPo(pcmd, 0);
AssertVarMem(pgrfeds);
*pgrfeds = fedsEnable | fedsUncheck;
if (vsclid == pcmd->rglw[0])
*pgrfeds = fedsEnable | fedsCheck;
return fTrue;
}
enum
{
kiditOkLang,
kiditCancelLang,
kiditCodeLang,
kiditLimLang
};
/***************************************************************************
Command to choose the language (for spelling).
***************************************************************************/
bool APP::FCmdChooseLanguage(PCMD pcmd)
{
AssertThis(0);
AssertPo(pcmd, 0);
if (pcmd->rglw[0] == 0)
{
// ask the user
PDLG pdlg;
bool fRet;
if (pvNil == (pdlg = DLG::PdlgNew(dlidFontSize)))
return fTrue;
pdlg->FPutLwInEdit(kiditCodeLang, vsclid);
if (kiditOkLang != pdlg->IditDo(kiditCodeLang))
{
ReleasePpo(&pdlg);
return fFalse;
}
fRet = pdlg->FGetLwFromEdit(kiditCodeLang, &pcmd->rglw[0]);
ReleasePpo(&pdlg);
if (!fRet)
return fTrue;
}
if ((SC_LID)pcmd->rglw[0] == vsclid)
return fTrue;
ReleasePpo(&vpsplc);
vsclid = (SC_LID)pcmd->rglw[0];
return fTrue;
}
/***************************************************************************
Create a new LIG for the given help text document.
***************************************************************************/
PLIG APP::PligNew(bool fButton, PGCB pgcb, PTXHD ptxhd)
{
PLID plid = fButton ? _plidButton : _plidPicture;
if (pvNil == plid)
return pvNil;
return LIG::PligNew(plid, pgcb, ptxhd);
}
/***************************************************************************
Constructor for the list display gob.
***************************************************************************/
LID::LID(void) : LID_PAR()
{
}
/***************************************************************************
Desctructor for the list display gob.
***************************************************************************/
LID::~LID(void)
{
ReleasePpo(&_pcrm);
ReleasePpo(&_pglcach);
}
#ifdef DEBUG
/***************************************************************************
Assert the validity of a LID.
***************************************************************************/
void LID::AssertValid(ulong grf)
{
LID_PAR::AssertValid(0);
AssertPo(_pcrm, 0);
AssertPo(_pglcach, 0);
}
/***************************************************************************
Mark memory for the LIG.
***************************************************************************/
void LID::MarkMem(void)
{
AssertValid(0);
LID_PAR::MarkMem();
MarkMemObj(_pcrm);
MarkMemObj(_pglcach);
}
#endif //DEBUG
/***************************************************************************
Static method to create a new list document.
***************************************************************************/
PLID LID::PlidNew(PCRM pcrm, CTG ctg, CHID chid)
{
AssertPo(pcrm, 0);
PLID plid;
if (pvNil == (plid = NewObj LID))
return pvNil;
if (!plid->_FInit(pcrm, ctg, chid))
ReleasePpo(&plid);
return plid;
}
/***************************************************************************
Initialization for the list document.
***************************************************************************/
bool LID::_FInit(PCRM pcrm, CTG ctg, CHID chid)
{
AssertPo(pcrm, 0);
GCB gcb;
if (pvNil == (_pglcach = GL::PglNew(size(CACH))))
return fFalse;
_pglcach->SetMinGrow(100);
_pcrm = pcrm;
_pcrm->AddRef();
_ctg = ctg;
_chid = chid;
return FRefresh();
}
/***************************************************************************
Rebuild the list and update the DDGs. The pcrm has changed.
***************************************************************************/
bool LID::FRefresh(void)
{
AssertThis(0);
long ipcrf, icki;
CACH cach, cachT;
PCRF pcrf;
PCFL pcfl;
CKI cki;
long ivMin, ivLim, iv;
KID kid;
long ipddg;
PDDG pddg;
bool fRet = fFalse;
_pglcach->FSetIvMac(0);
for (ipcrf = 0; ipcrf < _pcrm->Ccrf(); ipcrf++)
{
pcrf = _pcrm->PcrfGet(ipcrf);
pcfl = pcrf->Pcfl();
for (icki = 0; pcfl->FGetCkiCtg(_ctg, icki, &cki); icki++)
{
cach.pcrf = pcrf;
cach.cno = cach.cnoMbmp = cki.cno;
if (kctgMbmp != _ctg)
{
if (!pcfl->FGetKidChidCtg(_ctg, cki.cno, _chid, kctgMbmp, &kid))
continue;
cach.cnoMbmp = kid.cki.cno;
}
// determine where this cno goes.
for (ivMin = 0, ivLim = _pglcach->IvMac(); ivMin < ivLim; )
{
iv = (ivMin + ivLim) / 2;
_pglcach->Get(iv, &cachT);
if (cachT.cno < cach.cno)
ivMin = iv + 1;
else
ivLim = iv;
}
if (ivMin < _pglcach->IvMac())
{
_pglcach->Get(ivMin, &cachT);
if (cachT.cno == cach.cno)
continue;
}
if (!_pglcach->FInsert(ivMin, &cach))
goto LFail;
}
}
fRet = fTrue;
LFail:
//invalidate the LIGs
for (ipddg = 0; pvNil != (pddg = PddgGet(ipddg)); ipddg++)
{
Assert(pddg->FIs(kclsLIG), 0);
((PLIG)pddg)->Refresh();
}
return fTrue;
}
/***************************************************************************
Return the number of items in the list.
***************************************************************************/
long LID::Ccki(void)
{
AssertThis(0);
return _pglcach->IvMac();
}
/***************************************************************************
Get the CKI for the indicated item.
***************************************************************************/
void LID::GetCki(long icki, CKI *pcki, PCRF *ppcrf)
{
AssertThis(0);
AssertIn(icki, 0, _pglcach->IvMac());
AssertVarMem(pcki);
AssertNilOrVarMem(ppcrf);
CACH cach;
_pglcach->Get(icki, &cach);
pcki->ctg = _ctg;
pcki->cno = cach.cno;
if (pvNil != ppcrf)
*ppcrf = cach.pcrf;
}
/***************************************************************************
Get an MBMP for the indicated item.
***************************************************************************/
PMBMP LID::PmbmpGet(long icki)
{
AssertThis(0);
AssertIn(icki, 0, _pglcach->IvMac());
CACH cach;
_pglcach->Get(icki, &cach);
return (PMBMP)cach.pcrf->PbacoFetch(kctgMbmp, cach.cnoMbmp, MBMP::FReadMbmp);
}
/***************************************************************************
Constructor for the list display gob.
***************************************************************************/
LIG::LIG(PLID plid, GCB *pgcb) : LIG_PAR(plid, pgcb)
{
}
#ifdef DEBUG
/***************************************************************************
Assert the validity of a LIG.
***************************************************************************/
void LIG::AssertValid(ulong grf)
{
LIG_PAR::AssertValid(0);
AssertPo(_pscb, 0);
AssertPo(_ptxhd, 0);
AssertIn(_dypCell, 1, kswMax);
}
/***************************************************************************
Mark memory for the LIG.
***************************************************************************/
void LIG::MarkMem(void)
{
AssertValid(0);
LIG_PAR::MarkMem();
MarkMemObj(_ptxhd);
}
#endif //DEBUG
/***************************************************************************
Static method to create a new list display gob.
***************************************************************************/
PLIG LIG::PligNew(PLID plid, GCB *pgcb, PTXHD ptxhd, long dypCell)
{
AssertPo(plid, 0);
AssertVarMem(pgcb);
AssertPo(ptxhd, 0);
AssertIn(dypCell, 1, kswMax);
PLIG plig;
if (pvNil == (plig = NewObj LIG(plid, pgcb)))
return pvNil;
if (!plig->_FInit(ptxhd, dypCell))
ReleasePpo(&plig);
return plig;
}
/***************************************************************************
Return the LID for this LIG.
***************************************************************************/
PLID LIG::Plid(void)
{
AssertPo(_pdocb, 0);
Assert(_pdocb->FIs(kclsLID), 0);
return (PLID)_pdocb;
}
/***************************************************************************
Initialization for the list display gob.
***************************************************************************/
bool LIG::_FInit(PTXHD ptxhd, long dypCell)
{
AssertPo(ptxhd, 0);
AssertIn(dypCell, 1, kswMax);
GCB gcb;
if (!LIG_PAR::_FInit())
return fFalse;
_ptxhd = ptxhd;
_dypCell = dypCell;
gcb.Set(khidVScroll, this);
gcb._rcRel.Set(krelOne, 0, krelOne, krelOne);
gcb._rcAbs.Set(-SCB::DxpNormal(), -1, 0, 1 - kdxpFrameCcg);
if (pvNil == (_pscb = SCB::PscbNew(&gcb, fscbVert,
0, 0, Plid()->Ccki() - 1)))
{
return fFalse;
}
AssertThis(0);
return fTrue;
}
/***************************************************************************
The LID has changed, reset the scroll bounds and invalidate the display
area.
***************************************************************************/
void LIG::Refresh(void)
{
AssertThis(0);
long val;
InvalRc(pvNil);
val = LwMax(0, LwMin(_pscb->Val(), Plid()->Ccki() - 1));
_pscb->SetValMinMax(val, 0, Plid()->Ccki() - 1);
}
/***************************************************************************
Draw the list.
***************************************************************************/
void LIG::Draw(PGNV pgnv, RC *prcClip)
{
AssertThis(0);
AssertPo(pgnv, 0);
AssertVarMem(prcClip);
RC rc, rcT, rcCell, rcClip;
long icki;
PMBMP pmbmp;
PLID plid;
long ccki;
plid = Plid();
ccki = plid->Ccki();
GetRc(&rc, cooLocal);
rcT = rc;
rc.ypBottom = rcT.ypTop = rcT.ypBottom - kdxpFrameCcg;
pgnv->FillRc(&rcT, kacrBlack);
_pscb->GetRc(&rcT, cooParent);
rc.xpRight = rcT.xpLeft;
rcCell = rc;
if (!rc.FIntersect(prcClip))
return;
pgnv->FillRc(&rc, kacrWhite);
rcCell.ypTop = LwRoundToward(rc.ypTop, _dypCell);
icki = _pscb->Val() + rcCell.ypTop / _dypCell;
for ( ; rcCell.ypTop < rc.ypBottom && icki < ccki;
rcCell.ypTop += _dypCell, icki++)
{
rcCell.ypBottom = rcCell.ypTop + _dypCell;
pmbmp = plid->PmbmpGet(icki);
if (pvNil == pmbmp)
continue;
pmbmp->GetRc(&rcT);
rcT.CenterOnRc(&rcCell);
if (rcClip.FIntersect(&rc, &rcCell))
{
pgnv->ClipRc(&rcClip);
pgnv->DrawMbmp(pmbmp, &rcT);
}
ReleasePpo(&pmbmp);
}
}
/***************************************************************************
Handles a scroll command.
***************************************************************************/
bool LIG::FCmdScroll(PCMD pcmd)
{
long dval, val;
RC rc, rcT;
GetRc(&rc, cooLocal);
rc.ypBottom -= kdxpFrameCcg;
_pscb->GetRc(&rcT, cooParent);
rc.xpRight = rcT.xpLeft;
val = _pscb->Val();
switch (pcmd->cid)
{
case cidDoScroll:
switch (pcmd->rglw[1])
{
default:
Bug("unknown sca");
return fTrue;
case scaLineUp:
dval = -1;
break;
case scaPageUp:
dval = -LwMax(1, rc.Dyp() / _dypCell - 1);
break;
case scaLineDown:
dval = 1;
break;
case scaPageDown:
dval = LwMax(1, rc.Dyp() / _dypCell - 1);
break;
case scaToVal:
dval = pcmd->rglw[2] - val;
break;
}
break;
case cidEndScroll:
dval = pcmd->rglw[1] - val;
break;
}
dval = LwMax(0, LwMin(dval + val, _pscb->ValMax())) - val;
if (dval == 0)
return fTrue;
_pscb->SetVal(val + dval);
Scroll(&rc, 0, -dval * _dypCell, kginDraw);
return fTrue;
}
/***************************************************************************
The mouse was clicked in the LIG. Insert the object in the active
DDG.
***************************************************************************/
void LIG::MouseDown(long xp, long yp, long cact, ulong grfcust)
{
AssertThis(0);
long icki;
CKI cki;
RC rc, rcT;
PHETG phetg;
PCRF pcrf;
PLID plid;
plid = (PLID)_pdocb;
Assert(plid->FIs(kclsLID), 0);
AssertPo(plid, 0);
GetRc(&rc, cooLocal);
_pscb->GetRc(&rcT, cooParent);
rc.xpRight = rcT.xpLeft;
if (!rc.FPtIn(xp, yp))
return;
icki = _pscb->Val() + yp / _dypCell;
if (!FIn(icki, 0, plid->Ccki()))
return;
phetg = (PHETG)_ptxhd->PddgActive();
if (pvNil == phetg || !phetg->FIs(kclsHETG))
return;
plid->GetCki(icki, &cki, &pcrf);
switch (cki.ctg)
{
case kctgMbmp:
phetg->FInsertPicture(pcrf, cki.ctg, cki.cno);
break;
case kctgGokd:
phetg->FInsertButton(pcrf, cki.ctg, cki.cno);
break;
}
}
/***************************************************************************
Constructor for the CCG.
***************************************************************************/
CCG::CCG(GCB *pgcb, PTXHD ptxhd, bool fForeColor, long cacrRow) : CCG_PAR(pgcb)
{
AssertPo(ptxhd, 0);
AssertIn(cacrRow, 1, 257);
_ptxhd = ptxhd;
_cacrRow = cacrRow;
_fForeColor = FPure(fForeColor);
}
/***************************************************************************
Handle mousedown in a CCG. Set the foreground or background color of
the text in the active of DDG of the ptxhd.
***************************************************************************/
void CCG::MouseDown(long xp, long yp, long cact, ulong grfcust)
{
AssertThis(0);
PHETG phetg;
ACR acr;
if (!_FGetAcrFromPt(xp, yp, &acr))
return;
phetg = (PHETG)_ptxhd->PddgActive();
if (pvNil != phetg && phetg->FIs(kclsHETG))
phetg->FSetColor(_fForeColor ? &acr : pvNil, _fForeColor ? pvNil : &acr);
}
/***************************************************************************
Draw the Color chooser gob.
***************************************************************************/
void CCG::Draw(PGNV pgnv, RC *prcClip)
{
AssertThis(0);
AssertPo(pgnv, 0);
AssertVarMem(prcClip);
long crcHeight, ircHeight, ircWidth;
long iscr;
RC rc, rcT;
ACR acr;
GetRc(&rc, cooLocal);
rc.ypTop -= kdxpFrameCcg;
rc.xpLeft -= kdxpFrameCcg;
pgnv->SetPenSize(kdxpFrameCcg, kdxpFrameCcg);
pgnv->FrameRc(&rc, kacrBlack);
rc.Inset(kdxpFrameCcg, kdxpFrameCcg);
pgnv->FillRc(&rc, kacrWhite);
rc.Inset(kdxpFrameCcg, kdxpFrameCcg);
crcHeight = LwDivAway(257, _cacrRow);
for (iscr = 0, ircHeight = 0; ircHeight < crcHeight; ircHeight++)
{
for (ircWidth = 0; ircWidth < _cacrRow; ircWidth++, iscr++)
{
rcT.SetToCell(&rc, _cacrRow, crcHeight, ircWidth, ircHeight);
switch (iscr)
{
default:
acr.SetToIndex((byte)iscr);
pgnv->FillRc(&rcT, acr);
break;
case 0:
pgnv->FillRc(&rcT, kacrBlack);
break;
case 256:
if (!_fForeColor)
pgnv->FillRcApt(&rcT, &vaptGray, kacrBlack, kacrWhite);
return;
}
}
}
}
/***************************************************************************
Map the given point to a color.
***************************************************************************/
bool CCG::_FGetAcrFromPt(long xp, long yp, ACR *pacr, RC *prc, long *piscr)
{
AssertThis(0);
AssertVarMem(pacr);
AssertNilOrVarMem(prc);
AssertNilOrVarMem(piscr);
RC rc;
long iscr;
long ircWidth, ircHeight;
GetRc(&rc, cooLocal);
rc.ypTop += kdxpFrameCcg;
rc.xpLeft += kdxpFrameCcg;
rc.ypBottom -= 2 * kdxpFrameCcg;
rc.xpRight -= 2 * kdxpFrameCcg;
if (!rc.FMapToCell(xp, yp, _cacrRow, LwDivAway(257, _cacrRow),
&ircWidth, &ircHeight))
{
TrashVar(prc);
TrashVar(piscr);
return fFalse;
}
iscr = LwMul(ircHeight, _cacrRow) + ircWidth;
switch (iscr)
{
default:
if (!FIn(iscr, 1, 256))
return fFalse;
pacr->SetToIndex((byte)iscr);
break;
case 0:
*pacr = kacrBlack;
break;
case 256:
if (_fForeColor)
return fFalse;
pacr->SetToClear();
break;
}
if (pvNil != prc)
{
prc->SetToCell(&rc, _cacrRow, LwDivAway(257, _cacrRow),
ircWidth, ircHeight);
}
if (pvNil != piscr)
*piscr = iscr;
return fTrue;
}
/***************************************************************************
Put up the CCG's tool tip.
***************************************************************************/
bool CCG::FEnsureToolTip(PGOB *ppgobCurTip, long xpMouse, long ypMouse)
{
AssertThis(0);
AssertVarMem(ppgobCurTip);
AssertNilOrPo(*ppgobCurTip, 0);
RC rc;
ACR acr;
ReleasePpo(ppgobCurTip);
GCB gcb(khidToolTip, this, fgobNil, kginMark);
*ppgobCurTip = NewObj CCGT(&gcb, kacrBlack);
return fTrue;
}
/***************************************************************************
When the mouse moves over the CCG, update the tool tip.
***************************************************************************/
bool CCG::FCmdMouseMove(PCMD_MOUSE pcmd)
{
AssertThis(0);
AssertVarMem(pcmd);
PCCGT pccgt;
RC rc, rcOld;
ACR acr;
STN stn;
long iscr;
if (pvNil == (pccgt = (PCCGT)PgobFromHid(khidToolTip)) ||
!pccgt->FIs(kclsCCGT))
{
return fTrue;
}
if (!_FGetAcrFromPt(pcmd->xp, pcmd->yp, &acr, &rc, &iscr))
{
rc.Zero();
acr = kacrBlack;
}
else
{
rc.ypBottom = rc.ypTop;
rc.ypTop -= 30;
rc.Inset(-20, 0);
if (acr == kacrClear)
stn = PszLit(" Clear ");
else
stn.FFormatSz(PszLit(" %d "), iscr);
}
if (rc.ypTop < 0 && pcmd->yp < rc.Dyp())
rc.Offset(0, 60);
GetRc(&rcOld, cooLocal);
rcOld.ypBottom -= kdxpFrameCcg;
rcOld.xpRight -= kdxpFrameCcg;
rc.PinToRc(&rcOld);
pccgt->GetPos(&rcOld, pvNil);
if (rcOld != rc)
pccgt->SetPos(&rc);
pccgt->SetAcr(acr, &stn);
return fTrue;
}
#ifdef DEBUG
/***************************************************************************
Assert the validity of a CCG.
***************************************************************************/
void CCG::AssertValid(ulong grf)
{
CCG_PAR::AssertValid(0);
AssertPo(_ptxhd, 0);
AssertIn(_cacrRow, 1, 257);
}
#endif //DEBUG
/***************************************************************************
Constructor for color chooser tool tip.
***************************************************************************/
CCGT::CCGT(PGCB pgcb, ACR acr, PSTN pstn) : CCGT_PAR(pgcb)
{
AssertBaseThis(0);
_acr = acr;
if (pvNil != pstn)
_stn = *pstn;
}
/***************************************************************************
Set the color for the tool tip.
***************************************************************************/
void CCGT::SetAcr(ACR acr, PSTN pstn)
{
AssertThis(0);
AssertPo(&acr, 0);
AssertNilOrPo(pstn, 0);
if (_acr != acr || pvNil == pstn && _stn.Cch() > 0 || !_stn.FEqual(pstn))
{
_acr = acr;
if (pvNil == pstn)
_stn.SetNil();
else
_stn = *pstn;
InvalRc(pvNil, kginMark);
}
}
/***************************************************************************
Draw the color tool tip.
***************************************************************************/
void CCGT::Draw(PGNV pgnv, RC *prcClip)
{
AssertThis(0);
AssertPo(pgnv, 0);
AssertVarMem(prcClip);
RC rc;
ACR acr;
GetRc(&rc, cooLocal);
pgnv->SetPenSize(1, 1);
pgnv->FrameRc(&rc, kacrBlack);
rc.Inset(1, 1);
pgnv->FrameRc(&rc, kacrWhite);
rc.Inset(1, 1);
if (_acr == kacrClear)
pgnv->FillRcApt(&rc, &vaptGray, kacrBlack, kacrWhite);
else
pgnv->FillRc(&rc, _acr);
if (_stn.Cch() > 0)
{
pgnv->ClipRc(&rc);
pgnv->SetFont(vpappb->OnnDefVariable(), fontBold, 12, tahCenter, tavCenter);
if (_acr == kacrClear)
{
pgnv->DrawStn(&_stn, rc.XpCenter(), rc.YpCenter(),
kacrBlack, kacrWhite);
}
else
pgnv->DrawStn(&_stn, rc.XpCenter(), rc.YpCenter(), _acr, kacrInvert);
}
}