mirror of
https://github.com/microsoft/Microsoft-3D-Movie-Maker.git
synced 2024-11-22 02:12:33 +01:00
1302 lines
29 KiB
C++
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);
|
|
}
|
|
}
|
|
|