mirror of
https://github.com/microsoft/Microsoft-3D-Movie-Maker.git
synced 2024-11-22 02:12:33 +01:00
4018 lines
91 KiB
C++
4018 lines
91 KiB
C++
/* Copyright (c) Microsoft Corporation.
|
|
Licensed under the MIT License. */
|
|
|
|
/***************************************************************************
|
|
|
|
Chunky help topic editor documents and their DDGs.
|
|
|
|
***************************************************************************/
|
|
#include "chelp.h"
|
|
ASSERTNAME
|
|
|
|
|
|
RTCLASS(HEDO)
|
|
RTCLASS(TSEL)
|
|
RTCLASS(HEDG)
|
|
RTCLASS(HETD)
|
|
RTCLASS(HETG)
|
|
RTCLASS(HTRU)
|
|
|
|
#ifndef UNICODE
|
|
#define SPELL
|
|
#else //UNICODE
|
|
#undef SPELL
|
|
#endif //UNICODE
|
|
|
|
|
|
BEGIN_CMD_MAP(HEDG, DDG)
|
|
ON_CID_GEN(cidDeleteTopic, &HEDG::FCmdDeleteTopic, &HEDG::FEnableHedgCmd)
|
|
ON_CID_GEN(cidEditTopic, &HEDG::FCmdEditTopic, &HEDG::FEnableHedgCmd)
|
|
ON_CID_GEN(cidNewTopic, &HEDG::FCmdNewTopic, pvNil)
|
|
ON_CID_GEN(cidExportText, &HEDG::FCmdExport, pvNil)
|
|
ON_CID_GEN(cidFind, &HEDG::FCmdFind, &HEDG::FEnableHedgCmd)
|
|
ON_CID_GEN(cidFindAgain, &HEDG::FCmdFind, &HEDG::FEnableHedgCmd)
|
|
ON_CID_GEN(cidPrint, &HEDG::FCmdPrint, &HEDG::FEnableHedgCmd)
|
|
ON_CID_GEN(cidSpellCheck, &HEDG::FCmdCheckSpelling, &HEDG::FEnableHedgCmd)
|
|
ON_CID_GEN(cidDumpText, &HEDG::FCmdDump, &HEDG::FEnableHedgCmd)
|
|
END_CMD_MAP_NIL()
|
|
|
|
|
|
BEGIN_CMD_MAP(HETG, TXRG)
|
|
ON_CID_GEN(cidGroupText, &HETG::FCmdGroupText, &HETG::FEnableHetgCmd)
|
|
ON_CID_GEN(cidLineSpacing, &HETG::FCmdLineSpacing, pvNil)
|
|
ON_CID_GEN(cidFormatPicture, &HETG::FCmdFormatPicture, &HETG::FEnableHetgCmd)
|
|
ON_CID_GEN(cidFormatButton, &HETG::FCmdFormatButton, &HETG::FEnableHetgCmd)
|
|
ON_CID_GEN(cidFormatEdit, &HETG::FCmdFormatEdit, &HETG::FEnableHetgCmd)
|
|
ON_CID_GEN(cidInsertEdit, &HETG::FCmdInsertEdit, pvNil)
|
|
ON_CID_GEN(cidEditHtop, &HETG::FCmdEditHtop, pvNil)
|
|
ON_CID_GEN(cidNextTopic, &HETG::FCmdNextTopic, pvNil)
|
|
ON_CID_GEN(cidPrevTopic, &HETG::FCmdNextTopic, pvNil)
|
|
ON_CID_GEN(cidFind, &HETG::FCmdFind, pvNil)
|
|
ON_CID_GEN(cidFindAgain, &HETG::FCmdFind, &HETG::FEnableHetgCmd)
|
|
ON_CID_GEN(cidReplace, &HETG::FCmdFind, &HETG::FEnableHetgCmd)
|
|
ON_CID_GEN(cidReplaceFind, &HETG::FCmdFind, &HETG::FEnableHetgCmd)
|
|
ON_CID_GEN(cidFindNextTopic, &HETG::FCmdFind, pvNil)
|
|
ON_CID_GEN(cidPrint, &HETG::FCmdPrint, pvNil)
|
|
ON_CID_GEN(cidSpellCheck, &HETG::FCmdCheckSpelling, pvNil)
|
|
ON_CID_GEN(cidSaveAs, pvNil, pvNil)
|
|
ON_CID_GEN(cidSaveCopy, pvNil, pvNil)
|
|
ON_CID_GEN(cidFontDialog, &HETG::FCmdFontDialog, pvNil)
|
|
END_CMD_MAP_NIL()
|
|
|
|
|
|
bool _fCaseSensitive;
|
|
|
|
void _TokenizeStn(PSTN pstn);
|
|
bool _FDoFindDlg(void);
|
|
|
|
|
|
/***************************************************************************
|
|
Constructor for HEDO class.
|
|
***************************************************************************/
|
|
HEDO::HEDO(void)
|
|
{
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Destructor for HEDO class.
|
|
***************************************************************************/
|
|
HEDO::~HEDO(void)
|
|
{
|
|
ReleasePpo(&_pcfl);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Static method to create a new document based on the given fni.
|
|
Use pfni == pvNil to create a new file, non-nil to open an
|
|
existing file.
|
|
***************************************************************************/
|
|
PHEDO HEDO::PhedoNew(FNI *pfni, PRCA prca)
|
|
{
|
|
AssertNilOrPo(pfni, ffniFile);
|
|
AssertPo(prca, 0);
|
|
PCFL pcfl;
|
|
PHEDO phedo;
|
|
|
|
if (pvNil == pfni)
|
|
pcfl = CFL::PcflCreateTemp();
|
|
else
|
|
{
|
|
AssertPo(pfni, ffniFile);
|
|
|
|
//make sure no other docs are based on this pcfl.
|
|
if (pvNil != DOCB::PdocbFromFni(pfni))
|
|
return pvNil;
|
|
pcfl = CFL::PcflOpen(pfni, fcflNil);
|
|
}
|
|
|
|
if (pvNil == pcfl)
|
|
return pvNil;
|
|
|
|
if (pvNil == (phedo = NewObj HEDO()))
|
|
{
|
|
ReleasePpo(&pcfl);
|
|
return pvNil;
|
|
}
|
|
|
|
phedo->_pcfl = pcfl;
|
|
phedo->_prca = prca;
|
|
AssertPo(phedo, 0);
|
|
return phedo;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Create a new DDG for the HEDO.
|
|
***************************************************************************/
|
|
PDDG HEDO::PddgNew(PGCB pgcb)
|
|
{
|
|
AssertThis(0);
|
|
return HEDG::PhedgNew(this, _pcfl, pgcb);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Get the current FNI for the doc. Return false if the doc is not
|
|
currently based on an FNI (it's a new doc or an internal one).
|
|
***************************************************************************/
|
|
bool HEDO::FGetFni(FNI *pfni)
|
|
{
|
|
AssertThis(0);
|
|
AssertBasePo(pfni, 0);
|
|
if (_pcfl->FTemp())
|
|
return fFalse;
|
|
|
|
_pcfl->GetFni(pfni);
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Save the document and optionally set this fni as the current one.
|
|
If the doc is currently based on an FNI, pfni may be nil, indicating
|
|
that this is a normal save (not save as). If pfni is not nil and
|
|
fSetFni is false, this just writes a copy of the doc but doesn't change
|
|
the doc one bit.
|
|
***************************************************************************/
|
|
bool HEDO::FSaveToFni(FNI *pfni, bool fSetFni)
|
|
{
|
|
AssertThis(0);
|
|
if (!fSetFni && pvNil != pfni)
|
|
return _pcfl->FSaveACopy(kctgChelp, pfni);
|
|
|
|
if (!_pcfl->FSave(kctgChelp, pfni))
|
|
return fFalse;
|
|
|
|
_fDirty = fFalse;
|
|
_pcfl->SetTemp(fFalse);
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Ask the user what file they want to save to.
|
|
***************************************************************************/
|
|
bool HEDO::FGetFniSave(FNI *pfni)
|
|
{
|
|
AssertThis(0);
|
|
AssertPo(pfni, 0);
|
|
|
|
return FGetFniSaveMacro(pfni, 'CHN2', "\x9" "Save As: ", "",
|
|
PszLit("All files\0*.*\0"), vwig.hwndApp);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Invalidate all DDGs on this HEDO. Also dirties the document. Should be
|
|
called by any code that edits the document.
|
|
***************************************************************************/
|
|
void HEDO::InvalAllDdg(CNO cno)
|
|
{
|
|
AssertThis(0);
|
|
long ipddg;
|
|
PDDG pddg;
|
|
|
|
//mark the document dirty
|
|
SetDirty();
|
|
|
|
//inform the DDGs
|
|
for (ipddg = 0; pvNil != (pddg = PddgGet(ipddg)); ipddg++)
|
|
{
|
|
if (pddg->FIs(kclsHEDG))
|
|
((PHEDG)pddg)->InvalCno(cno);
|
|
else
|
|
pddg->InvalRc(pvNil);
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Export the help topics in their textual representation for compilation
|
|
by chomp.
|
|
REVIEW shonk: this code is a major hack and very fragile.
|
|
***************************************************************************/
|
|
bool HEDO::FExportText(void)
|
|
{
|
|
AssertThis(0);
|
|
FNI fni;
|
|
PFIL pfil;
|
|
MSFIL msfil;
|
|
|
|
if (!FGetFniSaveMacro(&fni, 'TEXT', "\x9" "Save As: ", "",
|
|
PszLit("Chomp files\0*.cht\0"), vwig.hwndApp))
|
|
{
|
|
return fFalse;
|
|
}
|
|
|
|
if (pvNil == (pfil = FIL::PfilCreate(&fni)))
|
|
{
|
|
vpappb->TGiveAlertSz(PszLit("Can't create destination file!"),
|
|
bkOk, cokExclamation);
|
|
return fFalse;
|
|
}
|
|
|
|
msfil.SetFile(pfil);
|
|
|
|
if (!FExportHelpText(_pcfl, &msfil))
|
|
{
|
|
vpappb->TGiveAlertSz(PszLit("Exporting file failed"),
|
|
bkOk, cokExclamation);
|
|
pfil->SetTemp();
|
|
ReleasePpo(&pfil);
|
|
return fFalse;
|
|
}
|
|
|
|
ReleasePpo(&pfil);
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Resume searching in the topic at or after the given one, according to
|
|
fAdvance.
|
|
***************************************************************************/
|
|
void HEDO::DoFindNext(PHETD phetd, CNO cno, bool fAdvance)
|
|
{
|
|
AssertThis(0);
|
|
AssertNilOrPo(phetd, 0);
|
|
Assert(pvNil == phetd || phetd->PdocbPar() == this, "bad topic doc");
|
|
long cpMin, cpLim;
|
|
STN stn;
|
|
PHETG phetg;
|
|
PHETD phetdT;
|
|
|
|
if (!vpstrg->FGet(kstidFind, &stn) || stn.Cch() <= 0)
|
|
{
|
|
vpappb->TGiveAlertSz(PszLit("Empty search string"), bkOk, cokExclamation);
|
|
return;
|
|
}
|
|
|
|
if (cnoNil != cno)
|
|
{
|
|
if (pvNil != (phetd = HETD::PhetdFromChunk(this, cno)))
|
|
phetd->AddRef();
|
|
else if (pvNil == (phetd = HETD::PhetdNew(this, _prca, _pcfl, cno)))
|
|
{
|
|
// couldn't load the thing
|
|
return;
|
|
}
|
|
}
|
|
else if (pvNil != phetd)
|
|
phetd->AddRef();
|
|
|
|
if (fAdvance || pvNil == phetd)
|
|
{
|
|
phetdT = PhetdOpenNext(phetd);
|
|
ReleasePpo(&phetd);
|
|
phetd = phetdT;
|
|
}
|
|
|
|
while (pvNil != phetd)
|
|
{
|
|
// search phetd
|
|
AssertPo(phetd, 0);
|
|
|
|
if (phetd->FFind(stn.Prgch(), stn.Cch(), 0, &cpMin, &cpLim,
|
|
_fCaseSensitive))
|
|
{
|
|
// found it!
|
|
if (phetd->Cddg() == 0)
|
|
{
|
|
// need to open a window onto the doc.
|
|
phetd->PdmdNew();
|
|
}
|
|
else
|
|
phetd->ActivateDmd();
|
|
phetg = (PHETG)phetd->PddgActive();
|
|
if (pvNil != phetg)
|
|
{
|
|
AssertPo(phetg, 0);
|
|
phetg->SetSel(cpMin, cpLim);
|
|
phetg->ShowSel();
|
|
ReleasePpo(&phetd);
|
|
return;
|
|
}
|
|
}
|
|
|
|
phetdT = PhetdOpenNext(phetd);
|
|
ReleasePpo(&phetd);
|
|
phetd = phetdT;
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Open the next topic subdocument. If phetd is nil, open the first one.
|
|
***************************************************************************/
|
|
PHETD HEDO::PhetdOpenNext(PHETD phetd)
|
|
{
|
|
AssertThis(0);
|
|
AssertNilOrPo(phetd, 0);
|
|
Assert(pvNil == phetd || phetd->PdocbPar() == this, "bad topic doc");
|
|
long icki;
|
|
CKI cki;
|
|
PDOCB pdocb;
|
|
|
|
if (pvNil == phetd)
|
|
{
|
|
// start the search
|
|
_pcfl->FGetIcki(kctgHelpTopic, 0, &icki);
|
|
}
|
|
else if (cnoNil != (cki.cno = phetd->Cno()))
|
|
{
|
|
_pcfl->FGetIcki(kctgHelpTopic, cki.cno + 1, &icki);
|
|
phetd = pvNil;
|
|
}
|
|
|
|
if (pvNil == (pdocb = phetd))
|
|
{
|
|
// icki is valid
|
|
if (_pcfl->FGetCki(icki, &cki) && cki.ctg == kctgHelpTopic)
|
|
{
|
|
if (pvNil != (phetd = HETD::PhetdFromChunk(this, cki.cno)))
|
|
{
|
|
phetd->AddRef();
|
|
return phetd;
|
|
}
|
|
return HETD::PhetdNew(this, _prca, _pcfl, cki.cno);
|
|
}
|
|
|
|
// we're done with the saved topics - get the first
|
|
// new unsaved one
|
|
if (pvNil == (pdocb = PdocbChd()))
|
|
return pvNil;
|
|
if (pdocb->FIs(kclsHETD) && ((PHETD)pdocb)->Cno() == cnoNil)
|
|
{
|
|
pdocb->AddRef();
|
|
return (PHETD)pdocb;
|
|
}
|
|
}
|
|
|
|
for (;;)
|
|
{
|
|
AssertPo(pdocb, 0);
|
|
pdocb = pdocb->PdocbSib();
|
|
if (pvNil == pdocb)
|
|
break;
|
|
if (pdocb->FIs(kclsHETD) && ((PHETD)pdocb)->Cno() == cnoNil)
|
|
{
|
|
pdocb->AddRef();
|
|
return (PHETD)pdocb;
|
|
}
|
|
}
|
|
|
|
return pvNil;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Open the previous topic subdocument. If phetd is nil, open the last one.
|
|
***************************************************************************/
|
|
PHETD HEDO::PhetdOpenPrev(PHETD phetd)
|
|
{
|
|
AssertThis(0);
|
|
AssertNilOrPo(phetd, 0);
|
|
Assert(pvNil == phetd || phetd->PdocbPar() == this, "bad topic doc");
|
|
long icki;
|
|
CKI cki;
|
|
PDOCB pdocb;
|
|
PHETD phetdNew;
|
|
|
|
if (pvNil == phetd || (cki.cno = phetd->Cno()) == cnoNil)
|
|
{
|
|
// look for the last unsaved topic before phetd
|
|
phetdNew = pvNil;
|
|
for (pdocb = PdocbChd(); phetd != pdocb && pvNil != pdocb;
|
|
pdocb = pdocb->PdocbSib())
|
|
{
|
|
if (pdocb->FIs(kclsHETD) && ((PHETD)pdocb)->Cno() == cnoNil)
|
|
phetdNew = (PHETD)pdocb;
|
|
}
|
|
|
|
if (pvNil != phetdNew)
|
|
{
|
|
AssertPo(phetdNew, 0);
|
|
phetdNew->AddRef();
|
|
return phetdNew;
|
|
}
|
|
|
|
_pcfl->FGetIcki(kctgHelpTopic + 1, 0, &icki);
|
|
}
|
|
else
|
|
_pcfl->FGetIcki(kctgHelpTopic, cki.cno, &icki);
|
|
|
|
if (icki > 0 && _pcfl->FGetCki(icki - 1, &cki) && cki.ctg == kctgHelpTopic)
|
|
{
|
|
if (pvNil != (phetdNew = HETD::PhetdFromChunk(this, cki.cno)))
|
|
{
|
|
phetdNew->AddRef();
|
|
return phetdNew;
|
|
}
|
|
return HETD::PhetdNew(this, _prca, _pcfl, cki.cno);
|
|
}
|
|
|
|
return pvNil;
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
/***************************************************************************
|
|
Assert the validity of the HEDO.
|
|
***************************************************************************/
|
|
void HEDO::AssertValid(ulong grf)
|
|
{
|
|
HEDO_PAR::AssertValid(grf);
|
|
AssertPo(_pcfl, 0);
|
|
}
|
|
#endif //DEBUG
|
|
|
|
|
|
/***************************************************************************
|
|
Constructor for TSEL class.
|
|
***************************************************************************/
|
|
TSEL::TSEL(PCFL pcfl)
|
|
{
|
|
AssertPo(pcfl, 0);
|
|
_pcfl = pcfl;
|
|
_SetNil();
|
|
AssertThis(0);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Set the selection to a nil selection.
|
|
***************************************************************************/
|
|
void TSEL::_SetNil(void)
|
|
{
|
|
_icki = ivNil;
|
|
_cno = cnoNil;
|
|
AssertThis(0);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Set the selection to the given line. Return true iff the resulting
|
|
selection is not nil.
|
|
***************************************************************************/
|
|
bool TSEL::FSetIcki(long icki)
|
|
{
|
|
AssertThis(0);
|
|
CKI cki;
|
|
|
|
if (icki == ivNil || !_pcfl->FGetCkiCtg(kctgHelpTopic, icki, &cki))
|
|
{
|
|
_SetNil();
|
|
return fFalse;
|
|
}
|
|
|
|
_cno = cki.cno;
|
|
_icki = icki;
|
|
AssertThis(0);
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Set the selection to the given cno.
|
|
***************************************************************************/
|
|
bool TSEL::FSetCno(CNO cno)
|
|
{
|
|
AssertThis(0);
|
|
|
|
_cno = cno;
|
|
_icki = 0;
|
|
|
|
Adjust();
|
|
AssertThis(0);
|
|
return ivNil != _icki;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Adjust the sel after an edit to the doc. Assume icki is wrong
|
|
(except as indicators of invalid cno).
|
|
***************************************************************************/
|
|
void TSEL::Adjust(void)
|
|
{
|
|
AssertPo(_pcfl, 0);
|
|
long dicki;
|
|
|
|
if (ivNil == _icki || !_pcfl->FGetIcki(kctgHelpTopic, _cno, &_icki))
|
|
_SetNil();
|
|
_pcfl->FGetIcki(kctgHelpTopic, 0, &dicki);
|
|
_icki -= dicki;
|
|
AssertThis(0);
|
|
}
|
|
|
|
|
|
#ifdef DEBUG
|
|
/***************************************************************************
|
|
Assert the validity of the sel.
|
|
***************************************************************************/
|
|
void TSEL::AssertValid(ulong grf)
|
|
{
|
|
TSEL_PAR::AssertValid(0);
|
|
AssertPo(_pcfl, 0);
|
|
Assert((_cno == cnoNil) == (_icki == ivNil), "nil values not in sync");
|
|
}
|
|
#endif //DEBUG
|
|
|
|
|
|
/***************************************************************************
|
|
Constructor for the HEDG.
|
|
***************************************************************************/
|
|
HEDG::HEDG(PHEDO phedo, PCFL pcfl, PGCB pgcb) : DDG(phedo, pgcb), _tsel(pcfl)
|
|
{
|
|
AssertPo(pcfl, 0);
|
|
RC rc;
|
|
achar ch = kchSpace;
|
|
GNV gnv(this);
|
|
|
|
_pcfl = pcfl;
|
|
|
|
_onn = vpappb->OnnDefFixed();
|
|
gnv.SetOnn(_onn);
|
|
gnv.GetRcFromRgch(&rc, &ch, 1, 0, 0);
|
|
_dypLine = rc.Dyp();
|
|
_dxpChar = rc.Dxp();
|
|
_dypHeader = _dypLine;
|
|
AssertThis(0);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Static method to create a new HEDG.
|
|
***************************************************************************/
|
|
PHEDG HEDG::PhedgNew(PHEDO phedo, PCFL pcfl, PGCB pgcb)
|
|
{
|
|
PHEDG phedg;
|
|
|
|
if (pvNil == (phedg = NewObj HEDG(phedo, pcfl, pgcb)))
|
|
return pvNil;
|
|
|
|
if (!phedg->_FInit())
|
|
{
|
|
ReleasePpo(&phedg);
|
|
return pvNil;
|
|
}
|
|
phedg->Activate(fTrue);
|
|
|
|
AssertPo(phedg, 0);
|
|
return phedg;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
We're being activated or deactivated, invert the sel.
|
|
***************************************************************************/
|
|
void HEDG::_Activate(bool fActive)
|
|
{
|
|
AssertThis(0);
|
|
DDG::_Activate(fActive);
|
|
|
|
GNV gnv(this);
|
|
_DrawSel(&gnv);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Invalidate the display from cno to the end of the display. If we're
|
|
the active HEDG, also redraw.
|
|
***************************************************************************/
|
|
void HEDG::InvalCno(CNO cno)
|
|
{
|
|
AssertThis(0);
|
|
long icki, ickiT;
|
|
RC rc;
|
|
|
|
//we need to recalculate the lnLim
|
|
_pcfl->FGetIcki(kctgHelpTopic, cno, &icki);
|
|
_pcfl->FGetIcki(kctgHelpTopic, 0, &ickiT);
|
|
icki -= ickiT;
|
|
|
|
//correct the sel
|
|
ickiT = _tsel.Icki();
|
|
if (ivNil != ickiT && ickiT >= icki)
|
|
_tsel.Adjust();
|
|
|
|
GetRc(&rc, cooLocal);
|
|
rc.ypTop = LwMax(0, _YpFromIcki(icki));
|
|
if (rc.FEmpty())
|
|
return;
|
|
|
|
if (_fActive)
|
|
{
|
|
ValidRc(&rc, kginDraw);
|
|
InvalRc(&rc, kginDraw);
|
|
}
|
|
else
|
|
InvalRc(&rc);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Draw the topic list.
|
|
***************************************************************************/
|
|
void HEDG::Draw(PGNV pgnv, RC *prcClip)
|
|
{
|
|
AssertThis(0);
|
|
AssertPo(pgnv, 0);
|
|
AssertVarMem(prcClip);
|
|
STN stn, stnT;
|
|
RC rc;
|
|
long yp, xp;
|
|
long icki;
|
|
CKI cki;
|
|
|
|
pgnv->ClipRc(prcClip);
|
|
pgnv->FillRc(prcClip, kacrWhite);
|
|
pgnv->SetOnn(_onn);
|
|
xp = _XpFromIch(0);
|
|
|
|
//draw the header
|
|
stn = PszLit(" Hex CNO Name");
|
|
pgnv->DrawStn(&stn, xp, 0);
|
|
pgnv->GetRcSrc(&rc);
|
|
rc.ypTop = _dypHeader - 1;
|
|
rc.ypBottom = _dypHeader;
|
|
pgnv->FillRc(&rc, kacrBlack);
|
|
|
|
//use the sel to find the first icki to draw
|
|
icki = _IckiFromYp(LwMax(prcClip->ypTop, _dypHeader));
|
|
for (yp = _YpFromIcki(icki);
|
|
yp < prcClip->ypBottom && _pcfl->FGetCkiCtg(kctgHelpTopic, icki, &cki);
|
|
icki++)
|
|
{
|
|
//draw the cki description
|
|
_pcfl->FGetName(cki.ctg, cki.cno, &stnT);
|
|
stn.FFormatSz(PszLit("%08x %10d \"%s\""), cki.cno, cki.cno, &stnT);
|
|
pgnv->DrawStn(&stn, xp, yp);
|
|
yp += _dypLine;
|
|
}
|
|
|
|
//draw the selection
|
|
if (_fActive)
|
|
_DrawSel(pgnv);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Hilite the selection (if there is one)
|
|
***************************************************************************/
|
|
void HEDG::_DrawSel(PGNV pgnv)
|
|
{
|
|
AssertThis(0);
|
|
AssertPo(pgnv, 0);
|
|
RC rc;
|
|
long icki;
|
|
|
|
if (ivNil == (icki = _tsel.Icki()))
|
|
return;
|
|
|
|
pgnv->GetRcSrc(&rc);
|
|
rc.ypTop = _YpFromIcki(icki);
|
|
rc.ypBottom = rc.ypTop + _dypLine;
|
|
rc.ypTop = LwMax(rc.ypTop, _dypHeader);
|
|
pgnv->HiliteRc(&rc, kacrWhite);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Set the selection to the given icki or cno. If cno is not cnoNil,
|
|
this uses the cno, otherwise it uses the icki. If both are nil, it
|
|
clears the selection.
|
|
***************************************************************************/
|
|
void HEDG::_SetSel(long icki, CNO cno)
|
|
{
|
|
AssertThis(0);
|
|
|
|
if (cnoNil != cno)
|
|
{
|
|
TSEL tsel(_pcfl);
|
|
|
|
tsel.FSetCno(cno);
|
|
icki = tsel.Icki();
|
|
}
|
|
|
|
if (_tsel.Icki() == icki)
|
|
return;
|
|
|
|
GNV gnv(this);
|
|
|
|
//erase the old sel
|
|
if (_fActive)
|
|
_DrawSel(&gnv);
|
|
|
|
//set the new sel and draw it
|
|
_tsel.FSetIcki(icki);
|
|
if (_fActive)
|
|
_DrawSel(&gnv);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Scroll the sel into view.
|
|
***************************************************************************/
|
|
void HEDG::_ShowSel(void)
|
|
{
|
|
AssertThis(0);
|
|
RC rc;
|
|
long icki, ccki;
|
|
|
|
if (ivNil == (icki = _tsel.Icki()))
|
|
return;
|
|
|
|
if (icki < _scvVert)
|
|
_Scroll(scaNil, scaToVal, 0, icki);
|
|
else
|
|
{
|
|
_GetContent(&rc);
|
|
ccki = LwMax(_scvVert + 1, _IckiFromYp(rc.ypBottom));
|
|
if (icki >= ccki)
|
|
_Scroll(scaNil, scaToVal, 0, _scvVert + icki + 1 - ccki);
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Handle a mouse down in our content.
|
|
***************************************************************************/
|
|
void HEDG::MouseDown(long xp, long yp, long cact, ulong grfcust)
|
|
{
|
|
AssertThis(0);
|
|
long icki, ickiNew;
|
|
|
|
if (ivNil != (ickiNew = _IckiFromYp(yp)))
|
|
{
|
|
if ((icki = _tsel.Icki()) != ickiNew)
|
|
_SetSel(ickiNew);
|
|
ickiNew = _tsel.Icki();
|
|
}
|
|
|
|
if (!_fActive)
|
|
Activate(fTrue);
|
|
|
|
if (ivNil == ickiNew)
|
|
return;
|
|
|
|
if (cact > 1 && icki == ickiNew)
|
|
_EditTopic(_tsel.Cno());
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Handle key input.
|
|
***************************************************************************/
|
|
bool HEDG::FCmdKey(PCMD_KEY pcmd)
|
|
{
|
|
AssertThis(0);
|
|
long icki, ccki, ickiNew, cckiPage;
|
|
RC rc;
|
|
|
|
icki = _tsel.Icki();
|
|
ccki = _pcfl->CckiCtg(kctgHelpTopic);
|
|
switch (pcmd->vk)
|
|
{
|
|
case kvkDown:
|
|
ickiNew = (0 > icki) ? 0 : (icki + 1) % ccki;
|
|
goto LChangeSel;
|
|
|
|
case kvkUp:
|
|
ickiNew = (0 > icki) ? ccki - 1 : (icki + ccki - 1) % ccki;
|
|
goto LChangeSel;
|
|
|
|
case kvkPageUp:
|
|
case kvkPageDown:
|
|
_GetContent(&rc);
|
|
cckiPage = LwMax(1, rc.Dyp() / _dypLine - 1);
|
|
if (pcmd->vk == kvkPageDown)
|
|
ickiNew = LwMin(ccki - 1, ivNil == icki ? cckiPage : icki + cckiPage);
|
|
else
|
|
ickiNew = LwMax(0, ivNil == icki ? 0 : icki - cckiPage);
|
|
goto LChangeSel;
|
|
|
|
case kvkHome:
|
|
ickiNew = 0;
|
|
goto LChangeSel;
|
|
|
|
case kvkEnd:
|
|
ickiNew = ccki - 1;
|
|
LChangeSel:
|
|
if (ccki == 0)
|
|
{
|
|
Assert(ivNil == icki, "no lines, but non-nil sel");
|
|
break;
|
|
}
|
|
|
|
AssertIn(ickiNew, 0, ccki);
|
|
_SetSel(ickiNew);
|
|
_ShowSel();
|
|
break;
|
|
|
|
case kvkDelete:
|
|
case kvkBack:
|
|
if (ivNil != icki && tYes == vpappb->TGiveAlertSz(
|
|
PszLit("Are you sure you want to delete this topic?"),
|
|
bkYesNo, cokQuestion))
|
|
{
|
|
_ClearSel();
|
|
}
|
|
break;
|
|
|
|
case kvkReturn:
|
|
//edit the topic
|
|
if (ivNil != icki)
|
|
_EditTopic(_tsel.Cno());
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Return the maximum for the indicated scroll bar.
|
|
***************************************************************************/
|
|
long HEDG::_ScvMax(bool fVert)
|
|
{
|
|
AssertThis(0);
|
|
if (fVert)
|
|
{
|
|
RC rc;
|
|
|
|
_GetContent(&rc);
|
|
return LwMax(0, _pcfl->CckiCtg(kctgHelpTopic) - rc.Dyp() / _dypLine + 1);
|
|
}
|
|
return 320;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Handle enabling/disabling HEDG commands.
|
|
***************************************************************************/
|
|
bool HEDG::FEnableHedgCmd(PCMD pcmd, ulong *pgrfeds)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcmd);
|
|
AssertVarMem(pgrfeds);
|
|
CKI cki;
|
|
STN stn;
|
|
|
|
*pgrfeds = fedsEnable;
|
|
switch (pcmd->cid)
|
|
{
|
|
default:
|
|
if (ivNil == _tsel.Icki())
|
|
*pgrfeds = fedsDisable;
|
|
break;
|
|
|
|
case cidFindAgain:
|
|
if (!vpstrg->FGet(kstidFind, &stn) || stn.Cch() <= 0)
|
|
*pgrfeds = fedsDisable;
|
|
// fall thru
|
|
case cidFind:
|
|
case cidPrint:
|
|
case cidSpellCheck:
|
|
case cidDumpText:
|
|
if (!_pcfl->FGetCkiCtg(kctgHelpTopic, 0, &cki) &&
|
|
pvNil == Phedo()->PdocbChd())
|
|
{
|
|
*pgrfeds = fedsDisable;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Handle command to delete a chunk.
|
|
***************************************************************************/
|
|
bool HEDG::FCmdDeleteTopic(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcmd);
|
|
|
|
_ClearSel();
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Handles commands to edit a topic.
|
|
***************************************************************************/
|
|
bool HEDG::FCmdEditTopic(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcmd);
|
|
|
|
if (ivNil == _tsel.Icki())
|
|
return fTrue;
|
|
|
|
_EditTopic(_tsel.Cno());
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Create and edit a new topic in the help file.
|
|
***************************************************************************/
|
|
bool HEDG::FCmdNewTopic(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcmd);
|
|
|
|
_EditTopic(cnoNil);
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Create and edit a new topic in the help file.
|
|
***************************************************************************/
|
|
bool HEDG::FCmdExport(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcmd);
|
|
|
|
Phedo()->FExportText();
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Opens a window onto the given topic.
|
|
***************************************************************************/
|
|
void HEDG::_EditTopic(CNO cno)
|
|
{
|
|
AssertThis(0);
|
|
PHETD phetd;
|
|
|
|
//check for a hetd already open on the chunk.
|
|
if (cnoNil != cno && pvNil != (phetd = HETD::PhetdFromChunk(_pdocb, cno)))
|
|
{
|
|
phetd->ActivateDmd();
|
|
return;
|
|
}
|
|
|
|
phetd = HETD::PhetdNew(_pdocb, Phedo()->Prca(), _pcfl, cno);
|
|
if (pvNil != phetd)
|
|
phetd->PdmdNew();
|
|
|
|
ReleasePpo(&phetd);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Copy the selection to a new document.
|
|
***************************************************************************/
|
|
bool HEDG::_FCopySel(PDOCB *ppdocb)
|
|
{
|
|
AssertThis(0);
|
|
AssertNilOrVarMem(ppdocb);
|
|
CNO cno;
|
|
PHEDO phedo;
|
|
|
|
if (ivNil == _tsel.Icki())
|
|
return fFalse;
|
|
|
|
if (pvNil == ppdocb)
|
|
return fTrue;
|
|
|
|
if (pvNil != (phedo = HEDO::PhedoNew(pvNil, Phedo()->Prca())) &&
|
|
!_pcfl->FCopy(kctgHelpTopic, _tsel.Cno(), phedo->Pcfl(), &cno))
|
|
{
|
|
ReleasePpo(&phedo);
|
|
}
|
|
|
|
*ppdocb = phedo;
|
|
return pvNil != *ppdocb;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Delete the current selection.
|
|
***************************************************************************/
|
|
void HEDG::_ClearSel(void)
|
|
{
|
|
AssertThis(0);
|
|
CNO cno;
|
|
|
|
if (ivNil == _tsel.Icki())
|
|
return;
|
|
|
|
cno = _tsel.Cno();
|
|
_pcfl->Delete(kctgHelpTopic, cno);
|
|
Phedo()->InvalAllDdg(cno);
|
|
HETD::CloseDeletedHetd(_pdocb);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Paste all the topics of the given document into the current document.
|
|
***************************************************************************/
|
|
bool HEDG::_FPaste(PCLIP pclip, bool fDoIt, long cid)
|
|
{
|
|
AssertThis(0);
|
|
AssertPo(pclip, 0);
|
|
PHEDO phedo;
|
|
PCFL pcfl;
|
|
long icki;
|
|
CKI cki;
|
|
CNO cnoSel;
|
|
bool fFailed = fFalse;
|
|
|
|
if (cidPaste != cid || !pclip->FGetFormat(kclsHEDO))
|
|
return fFalse;
|
|
|
|
if (!fDoIt)
|
|
return fTrue;
|
|
|
|
if (!pclip->FGetFormat(kclsHEDO, (PDOCB *)&phedo))
|
|
return fFalse;
|
|
|
|
if (pvNil == (pcfl = phedo->Pcfl()) || pcfl->CckiCtg(kctgHelpTopic) <= 0)
|
|
{
|
|
ReleasePpo(&phedo);
|
|
return fTrue;
|
|
}
|
|
|
|
_SetSel(ivNil);
|
|
for (icki = 0; pcfl->FGetCkiCtg(kctgHelpTopic, icki, &cki); icki++)
|
|
fFailed |= !pcfl->FClone(cki.ctg, cki.cno, _pcfl, &cnoSel);
|
|
|
|
Phedo()->InvalAllDdg(0);
|
|
if (fFailed)
|
|
vpappb->TGiveAlertSz(PszLit("Couldn't paste everything"), bkOk, cokExclamation);
|
|
else
|
|
{
|
|
_SetSel(ivNil, cnoSel);
|
|
_ShowSel();
|
|
}
|
|
|
|
ReleasePpo(&phedo);
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Get the content part of the HEDG minus header (and any future footer).
|
|
***************************************************************************/
|
|
void HEDG::_GetContent(RC *prc)
|
|
{
|
|
GetRc(prc, cooLocal);
|
|
prc->ypTop += _dypHeader;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Return the icki that corresponds with the given yp value. If yp is in
|
|
the header, returns ivNil.
|
|
***************************************************************************/
|
|
long HEDG::_IckiFromYp(long yp)
|
|
{
|
|
AssertThis(0);
|
|
if (yp < _dypHeader)
|
|
return ivNil;
|
|
return _scvVert + (yp - _dypHeader) / _dypLine;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Perform a scroll according to scaHorz and scaVert.
|
|
***************************************************************************/
|
|
void HEDG::_Scroll(long scaHorz, long scaVert, long scvHorz, long scvVert)
|
|
{
|
|
AssertThis(0);
|
|
RC rc;
|
|
long dscvHorz, dscvVert;
|
|
long dxp, dyp;
|
|
|
|
_GetContent(&rc);
|
|
dscvHorz = dscvVert = 0;
|
|
dxp = 0;
|
|
switch (scaHorz)
|
|
{
|
|
case scaPageUp:
|
|
dscvHorz = -LwMax(1, LwMulDiv(rc.Dxp(), 9, 10) / _dxpChar);
|
|
goto LHorz;
|
|
case scaPageDown:
|
|
dscvHorz = LwMax(1, LwMulDiv(rc.Dxp(), 9, 10) / _dxpChar);
|
|
goto LHorz;
|
|
case scaLineUp:
|
|
dscvHorz = -LwMax(1, rc.Dxp() / 10 / _dxpChar);
|
|
goto LHorz;
|
|
case scaLineDown:
|
|
dscvHorz = LwMax(1, rc.Dxp() / 10 / _dxpChar);
|
|
goto LHorz;
|
|
case scaToVal:
|
|
dscvHorz = scvHorz - _scvHorz;
|
|
LHorz:
|
|
dscvHorz = LwBound(_scvHorz + dscvHorz, 0, _ScvMax(fFalse) + 1) - _scvHorz;
|
|
_scvHorz += dscvHorz;
|
|
dxp = LwMul(dscvHorz, _dxpChar);
|
|
break;
|
|
}
|
|
|
|
dyp = 0;
|
|
switch (scaVert)
|
|
{
|
|
case scaPageUp:
|
|
dscvVert = -LwMax(1, rc.Dyp() / _dypLine - 1);
|
|
goto LVert;
|
|
case scaPageDown:
|
|
dscvVert = LwMax(1, rc.Dyp() / _dypLine - 1);
|
|
goto LVert;
|
|
case scaLineUp:
|
|
dscvVert = -1;
|
|
goto LVert;
|
|
case scaLineDown:
|
|
dscvVert = 1;
|
|
goto LVert;
|
|
case scaToVal:
|
|
dscvVert = scvVert - _scvVert;
|
|
LVert:
|
|
dscvVert = LwBound(_scvVert + dscvVert, 0, _ScvMax(fTrue) + 1) - _scvVert;
|
|
_scvVert += dscvVert;
|
|
dyp = LwMul(dscvVert, _dypLine);
|
|
break;
|
|
}
|
|
|
|
_SetScrollValues();
|
|
if (dxp != 0 || dyp != 0)
|
|
_ScrollDxpDyp(dxp, dyp);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Move the bits in the window.
|
|
***************************************************************************/
|
|
void HEDG::_ScrollDxpDyp(long dxp, long dyp)
|
|
{
|
|
AssertThis(0);
|
|
RC rc;
|
|
|
|
_GetContent(&rc);
|
|
Scroll(&rc, -dxp, -dyp, kginDraw);
|
|
if (0 != dxp)
|
|
{
|
|
//scroll the header
|
|
rc.ypTop = 0;
|
|
rc.ypBottom = _dypHeader - 1;
|
|
Scroll(&rc, -dxp, 0, kginDraw);
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Do a find in some topics.
|
|
***************************************************************************/
|
|
bool HEDG::FCmdFind(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcmd);
|
|
|
|
switch (pcmd->cid)
|
|
{
|
|
case cidFind:
|
|
if (!_FDoFindDlg())
|
|
break;
|
|
// fall thru
|
|
case cidFindAgain:
|
|
Phedo()->DoFindNext(pvNil, _tsel.Cno(), fFalse);
|
|
break;
|
|
}
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Print some topics.
|
|
***************************************************************************/
|
|
bool HEDG::FCmdPrint(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcmd);
|
|
|
|
#ifdef WIN
|
|
const long kdypFontTitle = 9;
|
|
const long kdzpBox = 2;
|
|
long icki;
|
|
CKI cki;
|
|
PDOCB pdocb;
|
|
PRINTDLG pd;
|
|
DOCINFO di;
|
|
STN stn, stnT;
|
|
STN stnDoc;
|
|
RC rcPage, rcSrc, rcDst, rcT;
|
|
long onnDef;
|
|
long yp, ypTopic;
|
|
long dxpTopic;
|
|
long dypLine, dyp;
|
|
long ilin;
|
|
HTOP htop;
|
|
|
|
PHETD phetd = pvNil;
|
|
PHETG phetg = pvNil;
|
|
PGPT pgpt = pvNil;
|
|
PGNV pgnv = pvNil;
|
|
long lwPage = 1;
|
|
bool fInPage = fFalse;
|
|
PHEDO phedo = Phedo();
|
|
|
|
// set up the print dialog structure
|
|
ClearPb(&pd, size(pd));
|
|
pd.lStructSize = size(pd);
|
|
pd.Flags = PD_RETURNDC | PD_HIDEPRINTTOFILE | PD_NOPAGENUMS |
|
|
PD_NOSELECTION | PD_USEDEVMODECOPIES;
|
|
pd.hwndOwner = vwig.hwndApp;
|
|
|
|
if (!PrintDlg(&pd))
|
|
goto LFail;
|
|
|
|
// see if the device supports BitBlt
|
|
if (!(GetDeviceCaps(pd.hDC, RASTERCAPS) & RC_BITBLT))
|
|
goto LFail;
|
|
|
|
if (pvNil == (pgpt = GPT::PgptNew(pd.hDC)))
|
|
goto LFail;
|
|
if (pvNil == (pgnv = NewObj GNV(pgpt)))
|
|
goto LFail;
|
|
|
|
rcDst.Zero();
|
|
rcDst.xpRight = GetDeviceCaps(pd.hDC, LOGPIXELSX);
|
|
rcDst.ypBottom = GetDeviceCaps(pd.hDC, LOGPIXELSY);
|
|
pgnv->SetRcDst(&rcDst);
|
|
rcSrc.Zero();
|
|
rcSrc.xpRight = kdzpInch;
|
|
rcSrc.ypBottom = kdzpInch;
|
|
pgnv->SetRcSrc(&rcSrc);
|
|
|
|
phedo->GetName(&stnDoc);
|
|
di.cbSize = size(di);
|
|
di.lpszDocName = stnDoc.Psz();
|
|
di.lpszOutput = pvNil;
|
|
|
|
if (SP_ERROR == StartDoc(pd.hDC, &di))
|
|
goto LFail;
|
|
|
|
rcPage.Set(0, 0, GetDeviceCaps(pd.hDC, HORZRES), GetDeviceCaps(pd.hDC, VERTRES));
|
|
rcPage.Map(&rcDst, &rcSrc);
|
|
rcPage.Inset(kdzpInch, kdzpInch);
|
|
onnDef = vpappb->OnnDefVariable();
|
|
|
|
if (0 >= StartPage(pd.hDC))
|
|
goto LFail;
|
|
yp = rcPage.ypTop;
|
|
|
|
_StartPage(pgnv, &stnDoc, lwPage++, &rcPage, onnDef);
|
|
|
|
// set the topic info font and get its height
|
|
pgnv->SetFont(onnDef, fontNil, kdypFontTitle, tahLeft, tavTop);
|
|
pgnv->GetRcFromRgch(&rcT, pvNil, 0, 0, 0);
|
|
dypLine = rcT.Dyp();
|
|
|
|
// print the topics
|
|
for (icki = 0, pdocb = pvNil; ; )
|
|
{
|
|
if (ivNil != icki && _pcfl->FGetCkiCtg(kctgHelpTopic, icki++, &cki))
|
|
{
|
|
// get a saved topic
|
|
if (pvNil != (phetd = HETD::PhetdFromChunk(phedo, cki.cno)))
|
|
phetd->AddRef();
|
|
else if (pvNil == (phetd = HETD::PhetdNew(phedo, phedo->Prca(),
|
|
_pcfl, cki.cno)))
|
|
{
|
|
// couldn't load the thing
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// get an unsaved topic
|
|
icki = ivNil;
|
|
if (pvNil == pdocb)
|
|
pdocb = Phedo()->PdocbChd();
|
|
else
|
|
pdocb = pdocb->PdocbSib();
|
|
|
|
if (pvNil == pdocb)
|
|
break;
|
|
AssertPo(pdocb, 0);
|
|
if (!pdocb->FIs(kclsHETD) || ((PHETD)pdocb)->Cno() != cnoNil)
|
|
continue;
|
|
phetd = (PHETD)pdocb;
|
|
}
|
|
AssertPo(phetd, 0);
|
|
|
|
if (pvNil == (phetg = (PHETG)phetd->PddgGet(0)))
|
|
{
|
|
// need to open a window onto the doc.
|
|
GCB gcb(khidDdg, this);
|
|
if (pvNil == (phetg = (PHETG)phetd->PddgNew(&gcb)))
|
|
goto LFail;
|
|
}
|
|
else
|
|
phetg->AddRef();
|
|
AssertPo(phetg, 0);
|
|
phetd->GetHtop(&htop);
|
|
dxpTopic = phetd->DxpDef();
|
|
|
|
if (yp > rcPage.ypTop)
|
|
{
|
|
// see if we should start a new page before the topic
|
|
yp += 3 * dypLine;
|
|
|
|
if (yp + phetg->DypLine(0) + dypLine * 3 > rcPage.ypBottom)
|
|
{
|
|
// start a new page
|
|
if (0 >= EndPage(pd.hDC))
|
|
goto LFail;
|
|
if (0 >= StartPage(pd.hDC))
|
|
goto LFail;
|
|
yp = rcPage.ypTop;
|
|
_StartPage(pgnv, &stnDoc, lwPage++, &rcPage, onnDef);
|
|
}
|
|
}
|
|
|
|
// draw the topic header stuff
|
|
rcT = rcPage;
|
|
rcT.ypTop = yp;
|
|
rcT.ypBottom = yp + 3 * dypLine;
|
|
rcT.Inset(-3, -3);
|
|
|
|
pgnv->SetFont(onnDef, fontNil, kdypFontTitle, tahLeft, tavTop);
|
|
phetd->GetHtopStn(1, &stnT);
|
|
stn.FFormatSz(PszLit("Topic 0x%08x (%s): "), phetd->Cno(), &stnT);
|
|
phetd->GetHtopStn(-1, &stnT);
|
|
stn.FAppendStn(&stnT);
|
|
pgnv->DrawStn(&stn, rcPage.xpLeft, yp);
|
|
yp += dypLine;
|
|
|
|
phetd->GetHtopStn(4, &stnT);
|
|
stn.FFormatSz(PszLit("Script: 0x%08x (%s); Sound: '%f', 0x%08x ("),
|
|
htop.cnoScript, &stnT, htop.ckiSnd.ctg, htop.ckiSnd.cno);
|
|
phetd->GetHtopStn(5, &stnT);
|
|
stn.FAppendStn(&stnT);
|
|
stn.FAppendCh(ChLit(')'));
|
|
pgnv->DrawStn(&stn, rcPage.xpLeft, yp);
|
|
yp += dypLine;
|
|
|
|
stn.FFormatSz(PszLit("Topic Width: %d"), dxpTopic);
|
|
pgnv->DrawStn(&stn, rcPage.xpLeft, yp);
|
|
yp += 2 * dypLine;
|
|
|
|
ypTopic = yp;
|
|
pgnv->SetPenSize(1, 1);
|
|
pgnv->FrameRc(&rcT, kacrBlack);
|
|
|
|
// draw the start box
|
|
rcT.Set(rcPage.xpLeft, yp - kdzpBox, rcPage.xpLeft + dxpTopic, yp);
|
|
pgnv->FillRc(&rcT, kacrBlack);
|
|
|
|
// draw the lines
|
|
for (ilin = 0; ; ilin++)
|
|
{
|
|
dyp = phetg->DypLine(ilin);
|
|
if (0 >= dyp)
|
|
break;
|
|
|
|
if (ilin > 0 && yp + dyp > rcPage.ypBottom)
|
|
{
|
|
// end the page and start a new one
|
|
ypTopic = -1;
|
|
|
|
// draw the topic end box
|
|
rcT.Set(rcPage.xpLeft, yp,
|
|
rcPage.xpLeft + dxpTopic, yp + kdzpBox / 2);
|
|
pgnv->FillRcApt(&rcT, &vaptGray, kacrGray, kacrWhite);
|
|
|
|
if (0 >= EndPage(pd.hDC))
|
|
goto LFail;
|
|
if (0 >= StartPage(pd.hDC))
|
|
goto LFail;
|
|
yp = rcPage.ypTop;
|
|
|
|
// draw the start box
|
|
rcT.Set(rcPage.xpLeft, yp - kdzpBox / 2,
|
|
rcPage.xpLeft + dxpTopic, yp);
|
|
pgnv->FillRcApt(&rcT, &vaptGray, kacrGray, kacrWhite);
|
|
|
|
_StartPage(pgnv, &stnDoc, lwPage++, &rcPage, onnDef);
|
|
}
|
|
|
|
phetg->DrawLines(pgnv, &rcPage, rcPage.xpLeft, yp,
|
|
ilin, ilin + 1, ftxtgNoColor);
|
|
yp += dyp;
|
|
}
|
|
|
|
// draw the topic end box
|
|
rcT.Set(rcPage.xpLeft, yp, rcPage.xpLeft + dxpTopic, yp + kdzpBox);
|
|
pgnv->FillRc(&rcT, kacrBlack);
|
|
|
|
ReleasePpo(&phetg);
|
|
ReleasePpo(&phetd);
|
|
}
|
|
|
|
if (0 >= EndPage(pd.hDC))
|
|
goto LFail;
|
|
|
|
// end the print job
|
|
if (0 >= EndDoc(pd.hDC))
|
|
{
|
|
LFail:
|
|
vpappb->TGiveAlertSz(PszLit("Printing failed"), bkOk, cokExclamation);
|
|
ReleasePpo(&phetd);
|
|
ReleasePpo(&phetg);
|
|
}
|
|
|
|
if (pd.hDC != hNil)
|
|
DeleteDC(pd.hDC);
|
|
if (pd.hDevMode != hNil)
|
|
GlobalFree(pd.hDevMode);
|
|
if (pd.hDevNames != hNil)
|
|
GlobalFree(pd.hDevNames);
|
|
ReleasePpo(&pgnv);
|
|
ReleasePpo(&pgpt);
|
|
#endif //WIN
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
#ifdef WIN
|
|
/***************************************************************************
|
|
Print the page number and document name.
|
|
***************************************************************************/
|
|
void HEDG::_StartPage(PGNV pgnv, PSTN pstnDoc, long lwPage, RC *prcPage, long onn)
|
|
{
|
|
STN stn;
|
|
|
|
// draw the document name and page number
|
|
pgnv->SetFont(onn, fontNil, 10, tahLeft, tavTop);
|
|
pgnv->DrawStn(pstnDoc, prcPage->xpLeft, prcPage->ypBottom + 12);
|
|
stn.FFormatSz(PszLit("- %d -"), lwPage);
|
|
pgnv->SetFont(onn, fontNil, 10, tahCenter, tavTop);
|
|
pgnv->DrawStn(&stn, prcPage->XpCenter(), prcPage->ypBottom + 12);
|
|
}
|
|
#endif //WIN
|
|
|
|
|
|
/***************************************************************************
|
|
Check spelling in topics from the selected one on.
|
|
***************************************************************************/
|
|
bool HEDG::FCmdCheckSpelling(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcmd);
|
|
|
|
#ifdef SPELL
|
|
CNO cno;
|
|
PDMD pdmd;
|
|
long cactT;
|
|
PHETD phetd, phetdT;
|
|
PHETG phetg;
|
|
long cactTotal = 0;
|
|
bool fContinue = fTrue;
|
|
PHEDO phedo = Phedo();
|
|
|
|
cno = _tsel.Cno();
|
|
if (cnoNil == cno)
|
|
phetd = phedo->PhetdOpenNext(pvNil);
|
|
else
|
|
{
|
|
if (pvNil != (phetd = HETD::PhetdFromChunk(phedo, cno)))
|
|
phetd->AddRef();
|
|
else
|
|
phetd = HETD::PhetdNew(phedo, phedo->Prca(), _pcfl, cno);
|
|
}
|
|
|
|
if (pvNil != vpsplc)
|
|
{
|
|
vpsplc->FlushIgnoreList();
|
|
vpsplc->FlushChangeList(fTrue);
|
|
}
|
|
|
|
while (pvNil != phetd)
|
|
{
|
|
// check phetd
|
|
AssertPo(phetd, 0);
|
|
|
|
if (phetd->Cddg() == 0)
|
|
{
|
|
// need to open a window onto the doc.
|
|
pdmd = phetd->PdmdNew();
|
|
}
|
|
else
|
|
{
|
|
phetd->ActivateDmd();
|
|
pdmd = pvNil;
|
|
}
|
|
|
|
phetg = (PHETG)phetd->PddgActive();
|
|
if (pvNil != phetg)
|
|
{
|
|
AssertPo(phetg, 0);
|
|
fContinue = phetg->FCheckSpelling(&cactT);
|
|
cactTotal += cactT;
|
|
}
|
|
|
|
if (pdmd != pvNil)
|
|
{
|
|
if (phetd->FQueryCloseDmd(pdmd))
|
|
ReleasePpo(&pdmd);
|
|
}
|
|
|
|
phetdT = fContinue ? phedo->PhetdOpenNext(phetd) : pvNil;
|
|
ReleasePpo(&phetd);
|
|
phetd = phetdT;
|
|
}
|
|
|
|
if (fContinue)
|
|
{
|
|
STN stn;
|
|
|
|
if (cactTotal == 0)
|
|
stn = PszLit("No corrections made.");
|
|
else
|
|
stn.FFormatSz(PszLit("Corrected %d words."), cactTotal);
|
|
vpappb->TGiveAlertSz(stn.Psz(), bkOk, cokExclamation);
|
|
}
|
|
#else //!SPELL
|
|
vpappb->TGiveAlertSz(PszLit("Spell checking not available"),
|
|
bkOk, cokExclamation);
|
|
#endif //!SPELL
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Dump the text of all topics.
|
|
***************************************************************************/
|
|
bool HEDG::FCmdDump(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcmd);
|
|
|
|
const long kcchMax = 1024;
|
|
achar rgch[kcchMax];
|
|
const long kcchEop = MacWin(1, 2);
|
|
achar rgchEop[] = { kchReturn, kchLineFeed };
|
|
long icki;
|
|
CKI cki;
|
|
PDOCB pdocb;
|
|
FNI fni;
|
|
PFIL pfil;
|
|
long cpMac;
|
|
long cp;
|
|
long cch;
|
|
bool fFirst;
|
|
FP fpCur;
|
|
|
|
PHETD phetd = pvNil;
|
|
PHEDO phedo = Phedo();
|
|
|
|
if (!FGetFniSaveMacro(&fni, kftgText, "\pFile to dump text to:", "\pDump",
|
|
PszLit("Text Files\0*.txt\0"), vwig.hwndApp))
|
|
{
|
|
return fTrue;
|
|
}
|
|
|
|
if (pvNil == (pfil = FIL::PfilCreate(&fni)))
|
|
return fTrue;
|
|
fpCur = 0;
|
|
|
|
#ifdef UNICODE
|
|
rgch[0] = kchwUnicode;
|
|
pfil->FWriteRgbSeq(rgch, size(achar), &fpCur);
|
|
#endif //UNICODE
|
|
|
|
// dump the topics
|
|
for (icki = 0, pdocb = pvNil, fFirst = fTrue; ; )
|
|
{
|
|
if (ivNil != icki && _pcfl->FGetCkiCtg(kctgHelpTopic, icki++, &cki))
|
|
{
|
|
// get a saved topic
|
|
if (pvNil != (phetd = HETD::PhetdFromChunk(phedo, cki.cno)))
|
|
phetd->AddRef();
|
|
else if (pvNil == (phetd = HETD::PhetdNew(phedo, phedo->Prca(),
|
|
_pcfl, cki.cno)))
|
|
{
|
|
// couldn't load the thing
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// get an unsaved topic
|
|
icki = ivNil;
|
|
if (pvNil == pdocb)
|
|
pdocb = Phedo()->PdocbChd();
|
|
else
|
|
pdocb = pdocb->PdocbSib();
|
|
|
|
if (pvNil == pdocb)
|
|
break;
|
|
AssertPo(pdocb, 0);
|
|
if (!pdocb->FIs(kclsHETD) || ((PHETD)pdocb)->Cno() != cnoNil)
|
|
continue;
|
|
phetd = (PHETD)pdocb;
|
|
}
|
|
AssertPo(phetd, 0);
|
|
|
|
if (!fFirst)
|
|
{
|
|
pfil->FWriteRgbSeq(rgchEop, kcchEop, &fpCur);
|
|
pfil->FWriteRgbSeq(PszLit("------------------------------"),
|
|
30 * size(achar), &fpCur);
|
|
pfil->FWriteRgbSeq(rgchEop, kcchEop, &fpCur);
|
|
pfil->FWriteRgbSeq(rgchEop, kcchEop, &fpCur);
|
|
}
|
|
else
|
|
fFirst = fFalse;
|
|
|
|
cpMac = phetd->CpMac() - 1;
|
|
for (cp = 0; cp < cpMac; cp += cch)
|
|
{
|
|
cch = LwMin(cpMac - cp, kcchMax);
|
|
phetd->FetchRgch(cp, cch, rgch);
|
|
pfil->FWriteRgbSeq(rgch, cch * size(achar), &fpCur);
|
|
}
|
|
|
|
pfil->FWriteRgbSeq(rgchEop, kcchEop, &fpCur);
|
|
ReleasePpo(&phetd);
|
|
}
|
|
|
|
ReleasePpo(&pfil);
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
#ifdef DEBUG
|
|
/***************************************************************************
|
|
Assert the validity of an object.
|
|
***************************************************************************/
|
|
void HEDG::AssertValid(ulong grf)
|
|
{
|
|
HEDG_PAR::AssertValid(0);
|
|
AssertPo(&_tsel, 0);
|
|
AssertPo(_pcfl, 0);
|
|
}
|
|
#endif //DEBUG
|
|
|
|
|
|
/***************************************************************************
|
|
Static method: For all HETD children of the DOCB, checks if the chunk
|
|
still exists and nukes the HETD if not.
|
|
***************************************************************************/
|
|
void HETD::CloseDeletedHetd(PDOCB pdocb)
|
|
{
|
|
PDOCB pdocbNext;
|
|
PHETD phetd;
|
|
|
|
for (pdocb = pdocb->PdocbChd(); pvNil != pdocb; pdocb = pdocbNext)
|
|
{
|
|
pdocbNext = pdocb->PdocbSib();
|
|
if (!pdocb->FIs(kclsHETD))
|
|
continue;
|
|
phetd = (PHETD)pdocb;
|
|
//NOTE: can't assert the phetd here because the chunk may be gone
|
|
//AssertPo(phetd, 0);
|
|
AssertBasePo(phetd, 0);
|
|
AssertNilOrPo(phetd->_pcfl, 0);
|
|
if (phetd->_cno != cnoNil && pvNil != phetd->_pcfl &&
|
|
!phetd->_pcfl->FFind(kctgHelpTopic, phetd->_cno))
|
|
{
|
|
phetd->CloseAllDdg();
|
|
}
|
|
else
|
|
AssertPo(phetd, 0);
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Static method to look for a HETD for the given chunk.
|
|
***************************************************************************/
|
|
PHETD HETD::PhetdFromChunk(PDOCB pdocb, CNO cno)
|
|
{
|
|
AssertPo(pdocb, 0);
|
|
Assert(cnoNil != cno, 0);
|
|
PHETD phetd;
|
|
|
|
for (pdocb = pdocb->PdocbChd(); pvNil != pdocb; pdocb = pdocb->PdocbSib())
|
|
{
|
|
if (!pdocb->FIs(kclsHETD))
|
|
continue;
|
|
phetd = (PHETD)pdocb;
|
|
AssertPo(phetd, 0);
|
|
if (phetd->_cno == cno)
|
|
return phetd;
|
|
}
|
|
return pvNil;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Constructor for a help topic document.
|
|
***************************************************************************/
|
|
HETD::HETD(PDOCB pdocb, PRCA prca, PCFL pcfl, CNO cno) : TXHD(prca, pdocb)
|
|
{
|
|
AssertNilOrPo(pcfl, 0);
|
|
_pcfl = pcfl;
|
|
_cno = cno;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Destructor for a help topic editing document.
|
|
***************************************************************************/
|
|
HETD::~HETD(void)
|
|
{
|
|
ReleasePpo(&_pgst);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Static method to read a help topic document from the given
|
|
(pcfl, cno) and using the given prca as the source for pictures
|
|
and buttons.
|
|
***************************************************************************/
|
|
PHETD HETD::PhetdNew(PDOCB pdocb, PRCA prca, PCFL pcfl, CNO cno)
|
|
{
|
|
AssertNilOrPo(pdocb, 0);
|
|
AssertPo(prca, 0);
|
|
AssertNilOrPo(pcfl, 0);
|
|
Assert(pcfl != pvNil || cnoNil == cno, "non-nil cno with nil CFL");
|
|
PHETD phetd;
|
|
|
|
if (pvNil == (phetd = NewObj HETD(pdocb, prca, pcfl, cno)))
|
|
return pvNil;
|
|
|
|
if ((cnoNil == cno) ? !phetd->_FInit() :
|
|
!phetd->_FReadChunk(pcfl, kctgHelpTopic, cno, fTrue))
|
|
{
|
|
PushErc(ercHelpReadFailed);
|
|
ReleasePpo(&phetd);
|
|
return pvNil;
|
|
}
|
|
|
|
if (cnoNil == cno)
|
|
phetd->_dxpDef = 200;
|
|
|
|
// force the default font to be Comic Sans MS
|
|
phetd->_stnFontDef = PszLit("Comic Sans MS");
|
|
if (!vntl.FGetOnn(&phetd->_stnFontDef, &phetd->_onnDef))
|
|
phetd->_onnDef = vpappb->OnnDefVariable();
|
|
phetd->_oskFont = koskCur;
|
|
|
|
// force the background color to clear
|
|
phetd->SetAcrBack(kacrClear);
|
|
|
|
return phetd;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Read the given chunk into this TXRD.
|
|
***************************************************************************/
|
|
bool HETD::_FReadChunk(PCFL pcfl, CTG ctg, CNO cno, bool fCopyText)
|
|
{
|
|
AssertPo(pcfl, 0);
|
|
BLCK blck;
|
|
KID kid;
|
|
|
|
if (!HETD_PAR::_FReadChunk(pcfl, ctg, cno, pvNil,
|
|
fCopyText ? ftxhdCopyText : ftxhdNil))
|
|
{
|
|
return fFalse;
|
|
}
|
|
|
|
if (pcfl->FGetKidChidCtg(ctg, cno, 0, kctgGst, &kid))
|
|
{
|
|
// read the string table
|
|
if (!pcfl->FFind(kid.cki.ctg, kid.cki.cno, &blck) ||
|
|
pvNil == (_pgst = GST::PgstRead(&blck)) ||
|
|
_pgst->IvMac() != 6 && (_pgst->IvMac() != 5 ||
|
|
!_pgst->FAddRgch(PszLit(""), 0)))
|
|
{
|
|
return fFalse;
|
|
}
|
|
}
|
|
|
|
pcfl->FGetName(ctg, cno, &_stnDesc);
|
|
|
|
AssertThis(0);
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Get the name of the document.
|
|
***************************************************************************/
|
|
void HETD::GetName(PSTN pstn)
|
|
{
|
|
AssertThis(0);
|
|
AssertPo(pstn, 0);
|
|
|
|
if (pvNil == _pdocbPar)
|
|
HETD_PAR::GetName(pstn);
|
|
else
|
|
{
|
|
STN stn;
|
|
|
|
if (cnoNil == _cno)
|
|
{
|
|
if (_cactUntitled == 0)
|
|
_cactUntitled = ++_cactLast;
|
|
stn.FFormatSz(PszLit(": Untitled Topic %d"), _cactUntitled);
|
|
}
|
|
else if (pvNil != _pdocbPar)
|
|
stn.FFormatSz(PszLit(": Topic %08x"), _cno);
|
|
|
|
_pdocbPar->GetName(pstn);
|
|
pstn->FAppendStn(&stn);
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Save the document. Handles only cidSave. Asserts on cidSaveAs and
|
|
cidSaveCopy.
|
|
***************************************************************************/
|
|
bool HETD::FSave(long cid)
|
|
{
|
|
AssertThis(0);
|
|
CKI cki;
|
|
|
|
if (cidSave != cid)
|
|
{
|
|
Bug("Bad cid");
|
|
return fFalse;
|
|
}
|
|
|
|
if (pvNil == _pcfl)
|
|
{
|
|
vpappb->TGiveAlertSz(
|
|
PszLit("Can't save this topic - it doesn't belong to a topic file"),
|
|
bkOk, cokExclamation);
|
|
return fFalse;
|
|
}
|
|
|
|
if (!FSaveToChunk(_pcfl, &cki, fFalse))
|
|
{
|
|
vpappb->TGiveAlertSz(PszLit("Saving topic failed"), bkOk, cokExclamation);
|
|
return fFalse;
|
|
}
|
|
|
|
Assert(cki.ctg == kctgHelpTopic, "wrong ctg");
|
|
if (cnoNil != _cno)
|
|
{
|
|
_pcfl->Delete(kctgHelpTopic, _cno);
|
|
_pcfl->Move(cki.ctg, cki.cno, kctgHelpTopic, _cno);
|
|
}
|
|
else
|
|
_cno = cki.cno;
|
|
|
|
_pcfl->FSetName(cki.ctg, _cno, &_stnDesc);
|
|
|
|
_fDirty = fFalse;
|
|
if (Phedo() != pvNil)
|
|
Phedo()->InvalAllDdg(0);
|
|
UpdateName();
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Save a help topic to the given chunky file. Fill in *pcki with where
|
|
we put the root chunk.
|
|
***************************************************************************/
|
|
bool HETD::FSaveToChunk(PCFL pcfl, CKI *pcki, bool fRedirectText)
|
|
{
|
|
AssertThis(0);
|
|
AssertPo(pcfl, 0);
|
|
AssertVarMem(pcki);
|
|
BLCK blck;
|
|
CNO cno;
|
|
|
|
if (!HETD_PAR::FSaveToChunk(pcfl, pcki, fRedirectText))
|
|
return fFalse;
|
|
|
|
if (pvNil != _pgst)
|
|
{
|
|
//add the string table chunk and write it
|
|
if (!pcfl->FAddChild(pcki->ctg, pcki->cno, 0, _pgst->CbOnFile(),
|
|
kctgGst, &cno, &blck) || !_pgst->FWrite(&blck))
|
|
{
|
|
pcfl->Delete(pcki->ctg, pcki->cno);
|
|
PushErc(ercHelpSaveFailed);
|
|
return fFalse;
|
|
}
|
|
}
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Create a new Document MDI window for this help topic.
|
|
***************************************************************************/
|
|
PDMD HETD::PdmdNew(void)
|
|
{
|
|
AssertThis(0);
|
|
PDMD pdmd;
|
|
PGOB pgob;
|
|
RC rcRel, rcAbs;
|
|
long dxpLig, ypT;
|
|
GCB gcb;
|
|
|
|
if (pvNil == (pdmd = HETD_PAR::PdmdNew()))
|
|
return pvNil;
|
|
|
|
dxpLig = kdxpCellLig + SCB::DxpNormal();
|
|
if (pvNil == (pgob = pdmd->PgobFromHid(khidDmw)))
|
|
goto LFail;
|
|
pgob->GetPos(&rcAbs, &rcRel);
|
|
rcAbs.xpLeft += dxpLig + kdxpCcg;
|
|
pgob->SetPos(&rcAbs, &rcRel);
|
|
|
|
rcRel.xpRight = rcRel.xpLeft;
|
|
ypT = rcRel.ypBottom;
|
|
rcRel.ypBottom = rcRel.YpCenter();
|
|
|
|
rcAbs.xpRight = rcAbs.xpLeft;
|
|
rcAbs.xpLeft = rcAbs.xpRight - kdxpCcg;
|
|
rcAbs.ypTop = 0;
|
|
rcAbs.ypBottom = kdxpFrameCcg / 2;
|
|
gcb.Set(CMH::HidUnique(), pgob, fgobSibling, kginDefault, &rcAbs, &rcRel);
|
|
if (pvNil == NewObj CCG(&gcb, this, fTrue))
|
|
goto LFail;
|
|
|
|
rcAbs.xpRight = rcAbs.xpLeft;
|
|
rcAbs.xpLeft = rcAbs.xpRight - dxpLig;
|
|
gcb.Set(khidLigButton, pgob, fgobSibling, kginDefault, &rcAbs, &rcRel);
|
|
if (pvNil == vapp.PligNew(fTrue, &gcb, this))
|
|
goto LFail;
|
|
|
|
rcAbs.ypTop = rcAbs.ypBottom;
|
|
rcAbs.ypBottom = kdxpFrameCcg;
|
|
rcRel.ypTop = rcRel.ypBottom;
|
|
rcRel.ypBottom = ypT;
|
|
gcb.Set(khidLigPicture, pgob, fgobSibling, kginDefault, &rcAbs, &rcRel);
|
|
if (pvNil == vapp.PligNew(fFalse, &gcb, this))
|
|
goto LFail;
|
|
|
|
rcAbs.xpLeft = rcAbs.xpRight;
|
|
rcAbs.xpRight = rcAbs.xpLeft + kdxpCcg;
|
|
gcb.Set(CMH::HidUnique(), pgob, fgobSibling, kginDefault, &rcAbs, &rcRel);
|
|
if (pvNil == NewObj CCG(&gcb, this, fFalse))
|
|
{
|
|
LFail:
|
|
ReleasePpo(&pdmd);
|
|
return pvNil;
|
|
}
|
|
|
|
AssertPo(pdmd, 0);
|
|
return pdmd;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Create a new DDG for the HETD.
|
|
***************************************************************************/
|
|
PDDG HETD::PddgNew(PGCB pgcb)
|
|
{
|
|
AssertThis(0);
|
|
return HETG::PhetgNew(this, pgcb);
|
|
}
|
|
|
|
|
|
enum
|
|
{
|
|
kiditOkTopic,
|
|
kiditCancelTopic,
|
|
kiditBalnTopic,
|
|
kiditBalnStnTopic,
|
|
kiditHtopStnTopic,
|
|
kiditHidTopic,
|
|
kiditHidStnTopic,
|
|
kiditHidTargetTopic,
|
|
kiditHidTargetStnTopic,
|
|
kiditScriptTopic,
|
|
kiditScriptStnTopic,
|
|
kiditDxpTopic,
|
|
kiditDypTopic,
|
|
kiditDescriptionTopic,
|
|
kiditCtgSoundTopic,
|
|
kiditCnoSoundTopic,
|
|
kiditCnoSoundStnTopic,
|
|
kiditWidthTopic,
|
|
kiditLimTopic
|
|
};
|
|
|
|
|
|
/***************************************************************************
|
|
Put up a dialog for the user to edit the help topic properties.
|
|
***************************************************************************/
|
|
void HETD::EditHtop(void)
|
|
{
|
|
AssertThis(0);
|
|
PDLG pdlg;
|
|
long dxp;
|
|
STN stn;
|
|
|
|
if (pvNil == (pdlg = DLG::PdlgNew(dlidTopicInfo)))
|
|
return;
|
|
|
|
if (pvNil != _pgst)
|
|
{
|
|
// initialize the string fields
|
|
_pgst->GetStn(0, &stn);
|
|
pdlg->FPutStn(kiditBalnStnTopic, &stn);
|
|
_pgst->GetStn(1, &stn);
|
|
pdlg->FPutStn(kiditHtopStnTopic, &stn);
|
|
_pgst->GetStn(2, &stn);
|
|
pdlg->FPutStn(kiditHidStnTopic, &stn);
|
|
_pgst->GetStn(3, &stn);
|
|
pdlg->FPutStn(kiditHidTargetStnTopic, &stn);
|
|
_pgst->GetStn(4, &stn);
|
|
pdlg->FPutStn(kiditScriptStnTopic, &stn);
|
|
_pgst->GetStn(5, &stn);
|
|
pdlg->FPutStn(kiditCnoSoundStnTopic, &stn);
|
|
}
|
|
else if (pvNil == (_pgst = GST::PgstNew(0, 6, 0)))
|
|
return;
|
|
else
|
|
{
|
|
stn.SetNil();
|
|
if (!_pgst->FAddStn(&stn) || !_pgst->FAddStn(&stn) ||
|
|
!_pgst->FAddStn(&stn) || !_pgst->FAddStn(&stn) ||
|
|
!_pgst->FAddStn(&stn) || !_pgst->FAddStn(&stn))
|
|
{
|
|
ReleasePpo(&_pgst);
|
|
return;
|
|
}
|
|
}
|
|
|
|
pdlg->FPutStn(kiditDescriptionTopic, &_stnDesc);
|
|
|
|
// initialize the numeric fields
|
|
pdlg->FPutLwInEdit(kiditBalnTopic, _htop.cnoBalloon);
|
|
pdlg->FPutLwInEdit(kiditHidTopic, _htop.hidThis);
|
|
pdlg->FPutLwInEdit(kiditHidTargetTopic, _htop.hidTarget);
|
|
pdlg->FPutLwInEdit(kiditScriptTopic, _htop.cnoScript);
|
|
pdlg->FPutLwInEdit(kiditDxpTopic, _htop.dxp);
|
|
pdlg->FPutLwInEdit(kiditDypTopic, _htop.dyp);
|
|
if (_htop.ckiSnd.ctg == ctgNil)
|
|
stn = PszLit("WAVE");
|
|
else
|
|
stn.FFormatSz(PszLit("%f"), _htop.ckiSnd.ctg);
|
|
pdlg->FPutStn(kiditCtgSoundTopic, &stn);
|
|
pdlg->FPutLwInEdit(kiditCnoSoundTopic, _htop.ckiSnd.cno);
|
|
pdlg->FPutLwInEdit(kiditWidthTopic, DxpDef());
|
|
|
|
if (kiditOkTopic != pdlg->IditDo(kiditBalnTopic))
|
|
{
|
|
ReleasePpo(&pdlg);
|
|
return;
|
|
}
|
|
|
|
if (!pdlg->FGetLwFromEdit(kiditBalnTopic, (long *)&_htop.cnoBalloon))
|
|
_htop.cnoBalloon = cnoNil;
|
|
if (!pdlg->FGetLwFromEdit(kiditHidTopic, &_htop.hidThis))
|
|
_htop.hidThis = hidNil;
|
|
if (!pdlg->FGetLwFromEdit(kiditHidTargetTopic, &_htop.hidTarget))
|
|
_htop.hidTarget = hidNil;
|
|
if (!pdlg->FGetLwFromEdit(kiditScriptTopic, (long *)&_htop.cnoScript))
|
|
_htop.cnoScript = cnoNil;
|
|
if (!pdlg->FGetLwFromEdit(kiditDxpTopic, &_htop.dxp))
|
|
_htop.dxp = 0;
|
|
if (!pdlg->FGetLwFromEdit(kiditDypTopic, &_htop.dyp))
|
|
_htop.dyp = 0;
|
|
if (pdlg->FGetLwFromEdit(kiditWidthTopic, &dxp) && FIn(dxp, 1, kcbMax))
|
|
SetDxpDef(dxp);
|
|
|
|
if (!pdlg->FGetLwFromEdit(kiditCnoSoundTopic, (long *)&_htop.ckiSnd.cno))
|
|
{
|
|
_htop.ckiSnd.cno = cnoNil;
|
|
_htop.ckiSnd.ctg = kctgWave;
|
|
}
|
|
else
|
|
{
|
|
pdlg->GetStn(kiditCtgSoundTopic, &stn);
|
|
if (!FIn(stn.Cch(), 1, 5))
|
|
{
|
|
_htop.ckiSnd.cno = cnoNil;
|
|
_htop.ckiSnd.ctg = kctgWave;
|
|
}
|
|
else
|
|
{
|
|
achar rgch[4];
|
|
|
|
rgch[0] = rgch[1] = rgch[2] = rgch[3] = kchSpace;
|
|
stn.GetRgch(rgch);
|
|
|
|
//first character becomes the high byte
|
|
_htop.ckiSnd.ctg = LwFromBytes((byte)rgch[0], (byte)rgch[1],
|
|
(byte)rgch[2], (byte)rgch[3]);
|
|
}
|
|
}
|
|
|
|
pdlg->GetStn(kiditBalnStnTopic, &stn);
|
|
_TokenizeStn(&stn);
|
|
_pgst->FPutStn(0, &stn);
|
|
pdlg->GetStn(kiditHtopStnTopic, &stn);
|
|
_TokenizeStn(&stn);
|
|
_pgst->FPutStn(1, &stn);
|
|
pdlg->GetStn(kiditHidStnTopic, &stn);
|
|
_TokenizeStn(&stn);
|
|
_pgst->FPutStn(2, &stn);
|
|
pdlg->GetStn(kiditHidTargetStnTopic, &stn);
|
|
_TokenizeStn(&stn);
|
|
_pgst->FPutStn(3, &stn);
|
|
pdlg->GetStn(kiditScriptStnTopic, &stn);
|
|
_TokenizeStn(&stn);
|
|
_pgst->FPutStn(4, &stn);
|
|
pdlg->GetStn(kiditCnoSoundStnTopic, &stn);
|
|
_TokenizeStn(&stn);
|
|
_pgst->FPutStn(5, &stn);
|
|
pdlg->GetStn(kiditDescriptionTopic, &_stnDesc);
|
|
ReleasePpo(&pdlg);
|
|
|
|
SetDirty();
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Do a search on this topic document.
|
|
***************************************************************************/
|
|
bool HETD::FDoFind(long cpMin, long *pcpMin, long *pcpLim)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcpMin);
|
|
AssertVarMem(pcpLim);
|
|
STN stn;
|
|
|
|
if (!vpstrg->FGet(kstidFind, &stn) || stn.Cch() == 0 ||
|
|
!FFind(stn.Psz(), stn.Cch(), cpMin, pcpMin, pcpLim, _fCaseSensitive))
|
|
{
|
|
TrashVar(pcpMin);
|
|
TrashVar(pcpLim);
|
|
return fFalse;
|
|
}
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Do a replace on this topic document.
|
|
***************************************************************************/
|
|
bool HETD::FDoReplace(long cp1, long cp2, long *pcpMin, long *pcpLim)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcpMin);
|
|
AssertVarMem(pcpLim);
|
|
STN stn;
|
|
|
|
SortLw(&cp1, &cp2);
|
|
vpstrg->FGet(kstidReplace, &stn);
|
|
*pcpMin = cp1;
|
|
*pcpLim = cp1 + stn.Cch();
|
|
HideSel();
|
|
return FReplaceRgch(stn.Psz(), stn.Cch(), cp1, cp2 - cp1);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Get a string corresponding to an entry in the HTOP. -1 means get the
|
|
topic description.
|
|
***************************************************************************/
|
|
void HETD::GetHtopStn(long istn, PSTN pstn)
|
|
{
|
|
AssertThis(0);
|
|
AssertPo(pstn, 0);
|
|
|
|
if (istn == -1)
|
|
*pstn = _stnDesc;
|
|
else if (pvNil != _pgst && istn < _pgst->IvMac())
|
|
_pgst->GetStn(istn, pstn);
|
|
else
|
|
pstn->SetNil;
|
|
}
|
|
|
|
|
|
#ifdef DEBUG
|
|
/***************************************************************************
|
|
Assert the validity of a HETD.
|
|
***************************************************************************/
|
|
void HETD::AssertValid(ulong grf)
|
|
{
|
|
HETD_PAR::AssertValid(0);
|
|
AssertNilOrPo(_pcfl, 0);
|
|
Assert(cnoNil == _cno ||
|
|
pvNil != _pcfl && _pcfl->FFind(kctgHelpTopic, _cno), "bad _cno");
|
|
AssertNilOrPo(_pgst, 0);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Mark memory for the HETD.
|
|
***************************************************************************/
|
|
void HETD::MarkMem(void)
|
|
{
|
|
AssertValid(0);
|
|
HETD_PAR::MarkMem();
|
|
MarkMemObj(_pgst);
|
|
}
|
|
#endif //DEBUG
|
|
|
|
|
|
/***************************************************************************
|
|
Constructor for a help text editing gob.
|
|
***************************************************************************/
|
|
HETG::HETG(PHETD phetd, PGCB pgcb) : HETG_PAR(phetd, pgcb)
|
|
{
|
|
_fMark = fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Create a new help text editing gob.
|
|
***************************************************************************/
|
|
PHETG HETG::PhetgNew(PHETD phetd, PGCB pgcb)
|
|
{
|
|
AssertPo(phetd, 0);
|
|
AssertVarMem(pgcb);
|
|
PHETG phetg;
|
|
|
|
if (pvNil == (phetg = NewObj HETG(phetd, pgcb)))
|
|
return pvNil;
|
|
if (!phetg->_FInit())
|
|
{
|
|
ReleasePpo(&phetg);
|
|
return pvNil;
|
|
}
|
|
phetg->ShowRuler();
|
|
phetg->Activate(fTrue);
|
|
return phetg;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Return the height of the ruler.
|
|
***************************************************************************/
|
|
long HETG::_DypTrul(void)
|
|
{
|
|
AssertThis(0);
|
|
return kdzpInch / 2 + 1;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Create the ruler.
|
|
***************************************************************************/
|
|
PTRUL HETG::_PtrulNew(PGCB pgcb)
|
|
{
|
|
AssertThis(0);
|
|
PAP pap;
|
|
long dyp;
|
|
|
|
_FetchPap(LwMin(_cpAnchor, _cpOther), &pap);
|
|
GetNaturalSize(pvNil, &dyp);
|
|
return HTRU::PhtruNew(pgcb, this, pap.dxpTab, _DxpDoc(), dyp,
|
|
kdxpIndentTxtg - _scvHorz, vpappb->OnnDefVariable(), 12, fontNil);
|
|
}
|
|
|
|
|
|
enum
|
|
{
|
|
kiditOkPicture,
|
|
kiditCancelPicture,
|
|
kiditNamePicture,
|
|
kiditLimPicture
|
|
};
|
|
|
|
|
|
/***************************************************************************
|
|
Insert a picture into the help text document.
|
|
***************************************************************************/
|
|
bool HETG::FInsertPicture(PCRF pcrf, CTG ctg, CNO cno)
|
|
{
|
|
AssertThis(0);
|
|
AssertPo(pcrf, 0);
|
|
Assert(ctg == kctgMbmp, "bad mbmp chunk");
|
|
long cpMin, cpLim;
|
|
PDLG pdlg;
|
|
STN stn;
|
|
long cb;
|
|
byte rgb[kcbMaxDataStn];
|
|
|
|
pdlg = DLG::PdlgNew(dlidFormatPicture);
|
|
if (pvNil == pdlg)
|
|
return fFalse;
|
|
|
|
pcrf->Pcfl()->FGetName(ctg, cno, &stn);
|
|
_TokenizeStn(&stn);
|
|
pdlg->FPutStn(kiditNamePicture, &stn);
|
|
|
|
_SwitchSel(fFalse, ginNil);
|
|
cpMin = LwMin(_cpAnchor, _cpOther);
|
|
cpLim = LwMax(_cpAnchor, _cpOther);
|
|
|
|
if (kiditOkPicture != pdlg->IditDo(kiditNamePicture))
|
|
{
|
|
ReleasePpo(&pdlg);
|
|
goto LFail;
|
|
}
|
|
|
|
pdlg->GetStn(kiditNamePicture, &stn);
|
|
_TokenizeStn(&stn);
|
|
cb = stn.CbData();
|
|
stn.GetData(rgb);
|
|
ReleasePpo(&pdlg);
|
|
|
|
if (Phetd()->FInsertPicture(cno, rgb, cb,
|
|
cpMin, cpLim - cpMin, _fValidChp ? &_chpIns : pvNil))
|
|
{
|
|
cpMin++;
|
|
SetSel(cpMin, cpMin);
|
|
}
|
|
else
|
|
{
|
|
LFail:
|
|
_SwitchSel(fTrue, kginMark);
|
|
}
|
|
|
|
ShowSel();
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
enum
|
|
{
|
|
kiditOkButton,
|
|
kiditCancelButton,
|
|
kiditNameButton,
|
|
kiditTopicButton,
|
|
kiditTopicNameButton,
|
|
kiditLimButton
|
|
};
|
|
|
|
bool _FDlgFormatButton(PDLG pdlg, long *pidit, void *pv);
|
|
|
|
|
|
/***************************************************************************
|
|
Dialog proc for formatting a button.
|
|
***************************************************************************/
|
|
bool _FDlgFormatButton(PDLG pdlg, long *pidit, void *pv)
|
|
{
|
|
AssertPo(pdlg, 0);
|
|
AssertVarMem(pidit);
|
|
long lw;
|
|
|
|
switch (*pidit)
|
|
{
|
|
case kiditCancelButton:
|
|
return fTrue; //dismiss the dialog
|
|
|
|
case kiditOkButton:
|
|
if (!pdlg->FGetValues(0, kiditLimButton))
|
|
{
|
|
*pidit = ivNil;
|
|
return fTrue;
|
|
}
|
|
if (!pdlg->FGetLwFromEdit(kiditTopicButton, &lw))
|
|
{
|
|
vpappb->TGiveAlertSz(PszLit("Topic number is bad"), bkOk, cokStop);
|
|
pdlg->SelectDit(kiditTopicButton);
|
|
return fFalse;
|
|
}
|
|
return fTrue;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return fFalse;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Insert a button into the help text document.
|
|
***************************************************************************/
|
|
bool HETG::FInsertButton(PCRF pcrf, CTG ctg, CNO cno)
|
|
{
|
|
AssertThis(0);
|
|
AssertPo(pcrf, 0);
|
|
Assert(ctg == kctgGokd, "bad button chunk");
|
|
long cpMin, cpLim;
|
|
long lw;
|
|
PDLG pdlg;
|
|
STN stn;
|
|
byte rgb[2 * kcbMaxDataStn];
|
|
long cb;
|
|
|
|
pdlg = DLG::PdlgNew(dlidFormatButton, _FDlgFormatButton);
|
|
if (pvNil == pdlg)
|
|
return fFalse;
|
|
|
|
pcrf->Pcfl()->FGetName(ctg, cno, &stn);
|
|
_TokenizeStn(&stn);
|
|
pdlg->FPutStn(kiditNameButton, &stn);
|
|
pdlg->FPutLwInEdit(kiditTopicButton, cnoNil);
|
|
|
|
_SwitchSel(fFalse, ginNil);
|
|
cpMin = LwMin(_cpAnchor, _cpOther);
|
|
cpLim = LwMax(_cpAnchor, _cpOther);
|
|
|
|
if (kiditOkButton != pdlg->IditDo(kiditNameButton) ||
|
|
!pdlg->FGetLwFromEdit(kiditTopicButton, &lw))
|
|
{
|
|
ReleasePpo(&pdlg);
|
|
goto LFail;
|
|
}
|
|
|
|
pdlg->GetStn(kiditNameButton, &stn);
|
|
_TokenizeStn(&stn);
|
|
cb = stn.CbData();
|
|
stn.GetData(rgb);
|
|
pdlg->GetStn(kiditTopicNameButton, &stn);
|
|
_TokenizeStn(&stn);
|
|
stn.GetData(rgb + cb);
|
|
cb += stn.CbData();
|
|
ReleasePpo(&pdlg);
|
|
|
|
if (Phetd()->FInsertButton(cno, (CNO)lw, rgb, cb,
|
|
cpMin, cpLim - cpMin, _fValidChp ? &_chpIns : pvNil))
|
|
{
|
|
cpMin++;
|
|
SetSel(cpMin, cpMin);
|
|
}
|
|
else
|
|
{
|
|
LFail:
|
|
_SwitchSel(fTrue, kginMark);
|
|
}
|
|
|
|
ShowSel();
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
enum
|
|
{
|
|
kiditOkEdit,
|
|
kiditCancelEdit,
|
|
kiditWidthEdit,
|
|
kiditLimEdit
|
|
};
|
|
|
|
|
|
bool _FDlgFormatEdit(PDLG pdlg, long *pidit, void *pv);
|
|
|
|
|
|
/***************************************************************************
|
|
Dialog proc for formatting an edit control.
|
|
***************************************************************************/
|
|
bool _FDlgFormatEdit(PDLG pdlg, long *pidit, void *pv)
|
|
{
|
|
AssertPo(pdlg, 0);
|
|
AssertVarMem(pidit);
|
|
long lw;
|
|
|
|
switch (*pidit)
|
|
{
|
|
case kiditCancelEdit:
|
|
return fTrue; //dismiss the dialog
|
|
|
|
case kiditOkEdit:
|
|
if (!pdlg->FGetValues(0, kiditLimEdit))
|
|
{
|
|
*pidit = ivNil;
|
|
return fTrue;
|
|
}
|
|
if (!pdlg->FGetLwFromEdit(kiditWidthEdit, &lw) || !FIn(lw, 10, 20000))
|
|
{
|
|
vpappb->TGiveAlertSz(PszLit("Width is bad"), bkOk, cokStop);
|
|
pdlg->SelectDit(kiditWidthEdit);
|
|
return fFalse;
|
|
}
|
|
return fTrue;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return fFalse;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Insert a text edit control into the help text document.
|
|
***************************************************************************/
|
|
bool HETG::FCmdInsertEdit(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcmd);
|
|
long cpMin, cpLim;
|
|
PDLG pdlg;
|
|
ECOS ecos;
|
|
|
|
ecos.ctg = 'EDIT';
|
|
pdlg = DLG::PdlgNew(dlidFormatEdit, _FDlgFormatEdit);
|
|
if (pvNil == pdlg)
|
|
return fFalse;
|
|
|
|
_SwitchSel(fFalse, ginNil);
|
|
cpMin = LwMin(_cpAnchor, _cpOther);
|
|
cpLim = LwMax(_cpAnchor, _cpOther);
|
|
|
|
if (kiditOkEdit != pdlg->IditDo(kiditWidthEdit))
|
|
goto LFail;
|
|
|
|
if (!pdlg->FGetLwFromEdit(kiditWidthEdit, &ecos.dxp))
|
|
goto LFail;
|
|
ReleasePpo(&pdlg);
|
|
|
|
if (Phetd()->FInsertObject(&ecos, size(ecos), cpMin, cpLim - cpMin,
|
|
_fValidChp ? &_chpIns : pvNil))
|
|
{
|
|
cpMin++;
|
|
SetSel(cpMin, cpMin);
|
|
}
|
|
else
|
|
{
|
|
LFail:
|
|
ReleasePpo(&pdlg);
|
|
_SwitchSel(fTrue, kginMark);
|
|
}
|
|
|
|
ShowSel();
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Copy the selection.
|
|
***************************************************************************/
|
|
bool HETG::_FCopySel(PDOCB *ppdocb)
|
|
{
|
|
AssertNilOrVarMem(ppdocb);
|
|
PHETD phetd;
|
|
|
|
if (_cpAnchor == _cpOther)
|
|
return fFalse;
|
|
|
|
if (pvNil == ppdocb)
|
|
return fTrue;
|
|
|
|
if (pvNil != (phetd = HETD::PhetdNew(pvNil, Phetd()->Prca(), pvNil, cnoNil)))
|
|
{
|
|
long cpMin = LwMin(_cpAnchor, _cpOther);
|
|
long cpLim = LwMax(_cpAnchor, _cpOther);
|
|
|
|
phetd->SetInternal();
|
|
phetd->SuspendUndo();
|
|
if (!phetd->FReplaceTxrd((PTXRD)_ptxtb, cpMin, cpLim - cpMin,
|
|
0, 0, fdocNil))
|
|
{
|
|
ReleasePpo(&phetd);
|
|
}
|
|
else
|
|
phetd->ResumeUndo();
|
|
}
|
|
|
|
*ppdocb = phetd;
|
|
return pvNil != *ppdocb;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Draw extra stuff for the line. In our case we put a box around grouped
|
|
text.
|
|
***************************************************************************/
|
|
void HETG::_DrawLinExtra(PGNV pgnv, PRC prcClip, LIN *plin,
|
|
long dxp, long yp, ulong grftxtg)
|
|
{
|
|
AssertThis(0);
|
|
AssertPo(pgnv, 0);
|
|
AssertVarMem(prcClip);
|
|
AssertVarMem(plin);
|
|
long cp, cpLimBox;
|
|
long cpLim = plin->cpMin + plin->ccp;
|
|
PHETD phetd = Phetd();
|
|
RC rc;
|
|
|
|
for (cp = plin->cpMin; cp < cpLim; )
|
|
{
|
|
if (phetd->FGrouped(cp, pvNil, &cpLimBox))
|
|
{
|
|
rc.ypTop = yp;
|
|
rc.ypBottom = yp + plin->dyp;
|
|
rc.xpLeft = plin->xpLeft + dxp + _DxpFromCp(plin->cpMin, cp)
|
|
- kdxpIndentTxtg;
|
|
if (cpLimBox >= cpLim)
|
|
rc.xpRight = dxp + _DxpDoc();
|
|
else
|
|
{
|
|
rc.xpRight = plin->xpLeft + dxp +
|
|
_DxpFromCp(plin->cpMin, cpLimBox) - kdxpIndentTxtg;
|
|
}
|
|
pgnv->SetPenSize(1, 1);
|
|
pgnv->FrameRcApt(&rc, &vaptGray, kacrInvert, kacrClear);
|
|
}
|
|
cp = cpLimBox;
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Draw the view on the help topic.
|
|
***************************************************************************/
|
|
void HETG::Draw(PGNV pgnv, RC *prcClip)
|
|
{
|
|
AssertThis(0);
|
|
RC rc;
|
|
APT apt = { 0x88, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00 };
|
|
|
|
GetRc(&rc, cooLocal);
|
|
pgnv->FillRcApt(prcClip, &apt, kacrLtGray, kacrWhite);
|
|
HETG_PAR::Draw(pgnv, prcClip);
|
|
}
|
|
|
|
|
|
enum
|
|
{
|
|
kiditOkGroupText,
|
|
kiditCancelGroupText,
|
|
kiditLwGroupText,
|
|
kiditTopicGroupText,
|
|
kiditTopicStnGroupText,
|
|
kiditLimGroupText,
|
|
};
|
|
|
|
|
|
/***************************************************************************
|
|
Handle grouping text.
|
|
***************************************************************************/
|
|
bool HETG::FCmdGroupText(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcmd);
|
|
long cpAnchor, cpOther;
|
|
PDLG pdlg;
|
|
CNO cnoTopic;
|
|
STN stnTopic;
|
|
byte bGroup;
|
|
long lw;
|
|
|
|
if (_cpAnchor == _cpOther)
|
|
return fTrue;
|
|
|
|
_SwitchSel(fFalse, ginNil);
|
|
pdlg = DLG::PdlgNew(dlidGroupText);
|
|
if (pvNil == pdlg)
|
|
goto LCancel;
|
|
Phetd()->FGrouped(LwMin(_cpAnchor, _cpOther), pvNil, pvNil, &bGroup,
|
|
&cnoTopic, &stnTopic);
|
|
pdlg->FPutLwInEdit(kiditLwGroupText, (long)bGroup);
|
|
pdlg->FPutLwInEdit(kiditTopicGroupText, cnoTopic);
|
|
_TokenizeStn(&stnTopic);
|
|
pdlg->FPutStn(kiditTopicStnGroupText, &stnTopic);
|
|
if (kiditOkGroupText != pdlg->IditDo(kiditLwGroupText))
|
|
{
|
|
ReleasePpo(&pdlg);
|
|
goto LCancel;
|
|
}
|
|
if (!pdlg->FGetLwFromEdit(kiditLwGroupText, &lw) || !FIn(lw, 0, 256))
|
|
{
|
|
vpappb->TGiveAlertSz(PszLit("Group number must be between 0 and 255!"),
|
|
bkOk, cokExclamation);
|
|
lw = 0;
|
|
}
|
|
bGroup = (byte)lw;
|
|
if (bGroup != 0)
|
|
{
|
|
pdlg->GetStn(kiditTopicStnGroupText, &stnTopic);
|
|
_TokenizeStn(&stnTopic);
|
|
if (!pdlg->FGetLwFromEdit(kiditTopicGroupText, &lw))
|
|
{
|
|
vpappb->TGiveAlertSz(PszLit("Topic number was bad!"),
|
|
bkOk, cokExclamation);
|
|
cnoTopic = cnoNil;
|
|
}
|
|
else
|
|
cnoTopic = lw;
|
|
}
|
|
ReleasePpo(&pdlg);
|
|
|
|
if (Phetd()->FGroupText(cpAnchor = _cpAnchor, cpOther = _cpOther, bGroup,
|
|
cnoTopic, &stnTopic))
|
|
{
|
|
SetSel(cpAnchor, cpOther);
|
|
ShowSel();
|
|
}
|
|
else
|
|
{
|
|
LCancel:
|
|
_SwitchSel(fTrue, kginMark);
|
|
}
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
enum
|
|
{
|
|
kiditOkSpace,
|
|
kiditCancelSpace,
|
|
kiditExtraLineSpace,
|
|
kiditNumLineSpace,
|
|
kiditExtraAfterSpace,
|
|
kiditNumAfterSpace,
|
|
kiditLimSpace,
|
|
};
|
|
|
|
|
|
/***************************************************************************
|
|
Put up the line & paragraph spacing dialog and handle any changes.
|
|
***************************************************************************/
|
|
bool HETG::FCmdLineSpacing(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcmd);
|
|
PDLG pdlg;
|
|
PAP pap, papOld;
|
|
long lw;
|
|
|
|
pdlg = DLG::PdlgNew(dlidSpacing);
|
|
if (pvNil == pdlg)
|
|
return fTrue;
|
|
_FetchPap(LwMin(_cpAnchor, _cpOther), &pap);
|
|
pdlg->FPutLwInEdit(kiditExtraLineSpace, pap.dypExtraLine);
|
|
pdlg->FPutLwInEdit(kiditNumLineSpace, pap.numLine);
|
|
pdlg->FPutLwInEdit(kiditExtraAfterSpace, pap.dypExtraAfter);
|
|
pdlg->FPutLwInEdit(kiditNumAfterSpace, pap.numAfter);
|
|
|
|
if (kiditOkSpace != pdlg->IditDo(kiditExtraLineSpace))
|
|
{
|
|
ReleasePpo(&pdlg);
|
|
return fTrue;
|
|
}
|
|
|
|
papOld = pap;
|
|
if (pdlg->FGetLwFromEdit(kiditExtraLineSpace, &lw))
|
|
{
|
|
pap.dypExtraLine = (short)lw;
|
|
papOld.dypExtraLine = (short)~lw;
|
|
}
|
|
if (pdlg->FGetLwFromEdit(kiditNumLineSpace, &lw))
|
|
{
|
|
pap.numLine = (short)lw;
|
|
papOld.numLine = (short)~lw;
|
|
}
|
|
if (pdlg->FGetLwFromEdit(kiditExtraAfterSpace, &lw))
|
|
{
|
|
pap.dypExtraAfter = (short)lw;
|
|
papOld.dypExtraAfter = (short)~lw;
|
|
}
|
|
if (pdlg->FGetLwFromEdit(kiditNumAfterSpace, &lw))
|
|
{
|
|
pap.numAfter = (short)lw;
|
|
papOld.numAfter = (short)~lw;
|
|
}
|
|
ReleasePpo(&pdlg);
|
|
|
|
FApplyPap(&pap, &papOld);
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Handle enabling/disabling HETG commands.
|
|
***************************************************************************/
|
|
bool HETG::FEnableHetgCmd(PCMD pcmd, ulong *pgrfeds)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcmd);
|
|
AssertVarMem(pgrfeds);
|
|
void *pv;
|
|
long cp, cpT, cb;
|
|
STN stn;
|
|
|
|
*pgrfeds = fedsDisable;
|
|
switch (pcmd->cid)
|
|
{
|
|
default:
|
|
if (_cpAnchor != _cpOther)
|
|
*pgrfeds = fedsEnable;
|
|
break;
|
|
|
|
case cidFormatPicture:
|
|
case cidFormatButton:
|
|
case cidFormatEdit:
|
|
if (LwAbs(_cpAnchor - _cpOther) > 1)
|
|
break;
|
|
cp = LwMin(_cpAnchor, _cpOther);
|
|
if (!Phetd()->FFetchObject(cp, &cpT, &pv, &cb))
|
|
break;
|
|
if (cp == cpT && cb >= size(CKI))
|
|
{
|
|
switch (*(CTG *)pv)
|
|
{
|
|
case kctgMbmp:
|
|
if (pcmd->cid == cidFormatPicture)
|
|
*pgrfeds = fedsEnable;
|
|
break;
|
|
case kctgGokd:
|
|
if (pcmd->cid == cidFormatButton)
|
|
*pgrfeds = fedsEnable;
|
|
break;
|
|
case kctgEditControl:
|
|
if (pcmd->cid == cidFormatEdit)
|
|
*pgrfeds = fedsEnable;
|
|
break;
|
|
}
|
|
}
|
|
FreePpv(&pv);
|
|
break;
|
|
|
|
case cidFindAgain:
|
|
case cidReplace:
|
|
case cidReplaceFind:
|
|
if (vpstrg->FGet(kstidFind, &stn) && stn.Cch() > 0)
|
|
*pgrfeds = fedsEnable;
|
|
break;
|
|
}
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Allow the user to edit the properties of an embedded picture.
|
|
***************************************************************************/
|
|
bool HETG::FCmdFormatPicture(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcmd);
|
|
void *pv;
|
|
PDLG pdlg;
|
|
long cp, cpT, cb;
|
|
byte rgb[size(CKI) + kcbMaxDataStn];
|
|
STN stn;
|
|
CKI *pcki = (CKI *)rgb;
|
|
|
|
if (LwAbs(_cpAnchor - _cpOther) > 1)
|
|
return fTrue;
|
|
|
|
cp = LwMin(_cpAnchor, _cpOther);
|
|
if (!Phetd()->FFetchObject(cp, &cpT, &pv, &cb))
|
|
return fTrue;
|
|
|
|
if (cp != cpT || !FIn(cb, size(CKI), size(rgb) + 1) ||
|
|
((CKI *)pv)->ctg != kctgMbmp)
|
|
{
|
|
FreePpv(&pv);
|
|
return fFalse;
|
|
}
|
|
|
|
CopyPb(pv, rgb, cb);
|
|
FreePpv(&pv);
|
|
|
|
pdlg = DLG::PdlgNew(dlidFormatPicture);
|
|
if (pvNil == pdlg)
|
|
return fFalse;
|
|
|
|
if (cb > size(CKI) && stn.FSetData(rgb + size(CKI), cb - size(CKI)))
|
|
{
|
|
_TokenizeStn(&stn);
|
|
pdlg->FPutStn(kiditNamePicture, &stn);
|
|
}
|
|
|
|
_SwitchSel(fFalse, ginNil);
|
|
if (kiditOkPicture != pdlg->IditDo(kiditNamePicture))
|
|
{
|
|
ReleasePpo(&pdlg);
|
|
goto LFail;
|
|
}
|
|
|
|
pdlg->GetStn(kiditNamePicture, &stn);
|
|
_TokenizeStn(&stn);
|
|
cb = stn.CbData() + size(CKI);
|
|
stn.GetData(rgb + size(CKI));
|
|
ReleasePpo(&pdlg);
|
|
|
|
if (Phetd()->FApplyObjectProps(rgb, cb, cp))
|
|
SetSel(cp, cp + 1);
|
|
else
|
|
{
|
|
LFail:
|
|
_SwitchSel(fTrue, kginMark);
|
|
}
|
|
|
|
ShowSel();
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Allow the user to edit the properties of an embedded button.
|
|
***************************************************************************/
|
|
bool HETG::FCmdFormatButton(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcmd);
|
|
void *pv;
|
|
PDLG pdlg;
|
|
long cp, cpT, cb, ib, cbRead;
|
|
STN stn;
|
|
byte rgb[size(CKI) + size(long) + 2 * kcbMaxDataStn];
|
|
CKI *pcki = (CKI *)rgb;
|
|
long *plw = (long *)(pcki + 1);
|
|
|
|
if (LwAbs(_cpAnchor - _cpOther) > 1)
|
|
return fTrue;
|
|
|
|
cp = LwMin(_cpAnchor, _cpOther);
|
|
if (!Phetd()->FFetchObject(cp, &cpT, &pv, &cb))
|
|
return fTrue;
|
|
|
|
if (cp != cpT || !FIn(cb, size(CKI) + size(long), size(rgb) + 1) ||
|
|
((CKI *)pv)->ctg != kctgGokd)
|
|
{
|
|
FreePpv(&pv);
|
|
return fFalse;
|
|
}
|
|
|
|
CopyPb(pv, rgb, cb);
|
|
FreePpv(&pv);
|
|
|
|
pdlg = DLG::PdlgNew(dlidFormatButton, _FDlgFormatButton);
|
|
if (pvNil == pdlg)
|
|
return fFalse;
|
|
|
|
ib = size(CKI) + size(long);
|
|
if (cb > ib && stn.FSetData(rgb + ib, cb - ib, &cbRead))
|
|
{
|
|
_TokenizeStn(&stn);
|
|
pdlg->FPutStn(kiditNameButton, &stn);
|
|
if ((ib += cbRead) < cb &&
|
|
stn.FSetData(rgb + ib, cb - ib))
|
|
{
|
|
_TokenizeStn(&stn);
|
|
pdlg->FPutStn(kiditTopicNameButton, &stn);
|
|
}
|
|
}
|
|
pdlg->FPutLwInEdit(kiditTopicButton, *plw);
|
|
|
|
_SwitchSel(fFalse, ginNil);
|
|
if (kiditOkButton != pdlg->IditDo(kiditNameButton) ||
|
|
!pdlg->FGetLwFromEdit(kiditTopicButton, plw))
|
|
{
|
|
ReleasePpo(&pdlg);
|
|
goto LFail;
|
|
}
|
|
|
|
pdlg->GetStn(kiditNameButton, &stn);
|
|
_TokenizeStn(&stn);
|
|
ib = size(CKI) + size(long);
|
|
stn.GetData(rgb + ib);
|
|
ib += stn.CbData();
|
|
pdlg->GetStn(kiditTopicNameButton, &stn);
|
|
_TokenizeStn(&stn);
|
|
stn.GetData(rgb + ib);
|
|
ib += stn.CbData();
|
|
ReleasePpo(&pdlg);
|
|
|
|
if (Phetd()->FApplyObjectProps(rgb, ib, cp))
|
|
SetSel(cp, cp + 1);
|
|
else
|
|
{
|
|
LFail:
|
|
_SwitchSel(fTrue, kginMark);
|
|
}
|
|
|
|
ShowSel();
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Allow the user to edit the properties of an embedded edit control.
|
|
***************************************************************************/
|
|
bool HETG::FCmdFormatEdit(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcmd);
|
|
void *pv;
|
|
PDLG pdlg;
|
|
long cp, cpT, cb;
|
|
ECOS ecos;
|
|
|
|
if (LwAbs(_cpAnchor - _cpOther) > 1)
|
|
return fTrue;
|
|
|
|
cp = LwMin(_cpAnchor, _cpOther);
|
|
if (!Phetd()->FFetchObject(cp, &cpT, &pv, &cb))
|
|
return fTrue;
|
|
|
|
if (cp != cpT || cb != size(ecos) || *(CTG *)pv != kctgEditControl)
|
|
{
|
|
FreePpv(&pv);
|
|
return fFalse;
|
|
}
|
|
|
|
CopyPb(pv, &ecos, size(ecos));
|
|
FreePpv(&pv);
|
|
|
|
pdlg = DLG::PdlgNew(dlidFormatEdit, _FDlgFormatEdit);
|
|
if (pvNil == pdlg)
|
|
return fFalse;
|
|
|
|
pdlg->FPutLwInEdit(kiditWidthEdit, ecos.dxp);
|
|
|
|
_SwitchSel(fFalse, ginNil);
|
|
if (kiditOkEdit != pdlg->IditDo(kiditWidthEdit) ||
|
|
!pdlg->FGetLwFromEdit(kiditWidthEdit, &ecos.dxp))
|
|
{
|
|
ReleasePpo(&pdlg);
|
|
goto LFail;
|
|
}
|
|
ReleasePpo(&pdlg);
|
|
|
|
if (Phetd()->FApplyObjectProps(&ecos, size(ecos), cp))
|
|
SetSel(cp, cp + 1);
|
|
else
|
|
{
|
|
LFail:
|
|
_SwitchSel(fTrue, kginMark);
|
|
}
|
|
|
|
ShowSel();
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Edit the topic info.
|
|
***************************************************************************/
|
|
bool HETG::FCmdEditHtop(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcmd);
|
|
|
|
Phetd()->EditHtop();
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Open the next or previous topic.
|
|
***************************************************************************/
|
|
bool HETG::FCmdNextTopic(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcmd);
|
|
|
|
PHETD phetd;
|
|
PHETD phetdThis = Phetd();
|
|
PHEDO phedo = phetdThis->Phedo();
|
|
|
|
if (pvNil == phedo)
|
|
return fTrue;
|
|
|
|
phetd = pcmd->cid == cidNextTopic ? phedo->PhetdOpenNext(phetdThis) :
|
|
phedo->PhetdOpenPrev(phetdThis);
|
|
if (pvNil == phetd)
|
|
{
|
|
phetd = pcmd->cid == cidNextTopic ? phedo->PhetdOpenNext(pvNil) :
|
|
phedo->PhetdOpenPrev(pvNil);
|
|
}
|
|
|
|
if (pvNil == phetd || phetd == phetdThis)
|
|
{
|
|
ReleasePpo(&phetd);
|
|
return fTrue;
|
|
}
|
|
|
|
if (phetdThis->Cno() == cnoNil || phetdThis->FDirty())
|
|
phetdThis = pvNil;
|
|
|
|
// open a DMD onto the topic
|
|
if (phetd->Cddg() == 0)
|
|
{
|
|
// need to open a window onto the doc.
|
|
if (phetd->PdmdNew() != pvNil && pvNil != phetdThis)
|
|
phetdThis->CloseAllDdg();
|
|
}
|
|
else
|
|
{
|
|
phetd->ActivateDmd();
|
|
if (pvNil != phetd->PddgActive() && pvNil != phetdThis)
|
|
phetdThis->CloseAllDdg();
|
|
}
|
|
|
|
ReleasePpo(&phetd);
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Handle cidFind and cidFindAgain. Search for some text.
|
|
***************************************************************************/
|
|
bool HETG::FCmdFind(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcmd);
|
|
long cpMin, cpLim;
|
|
PHETD phetd;
|
|
|
|
switch (pcmd->cid)
|
|
{
|
|
case cidReplace:
|
|
case cidReplaceFind:
|
|
if (!Phetd()->FDoReplace(_cpAnchor, _cpOther, &cpMin, &cpLim))
|
|
{
|
|
vpappb->TGiveAlertSz(PszLit("Replace failed."), bkOk, cokStop);
|
|
break;
|
|
}
|
|
SetSel(cpMin, cpLim);
|
|
ShowSel();
|
|
if (pcmd->cid == cidReplace)
|
|
break;
|
|
vpappb->UpdateMarked();
|
|
cpMin = LwMin(cpMin + 1, cpLim);
|
|
goto LFind;
|
|
|
|
case cidFind:
|
|
if (!_FDoFindDlg())
|
|
break;
|
|
cpMin = LwMin(_cpAnchor, _cpOther);
|
|
goto LFind;
|
|
|
|
case cidFindAgain:
|
|
cpMin = LwMin(_cpAnchor, _cpOther);
|
|
cpMin = LwMin(cpMin + 1, LwMax(_cpAnchor, _cpOther));
|
|
LFind:
|
|
if (!Phetd()->FDoFind(cpMin, &cpMin, &cpLim))
|
|
{
|
|
vpappb->TGiveAlertSz(PszLit("Search string not found."),
|
|
bkOk, cokStop);
|
|
break;
|
|
}
|
|
SetSel(cpMin, cpLim);
|
|
ShowSel();
|
|
break;
|
|
|
|
case cidFindNextTopic:
|
|
phetd = Phetd();
|
|
if (phetd->Phedo() != pvNil)
|
|
phetd->Phedo()->DoFindNext(phetd, phetd->Cno());
|
|
break;
|
|
}
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Handle printing of a topic.
|
|
***************************************************************************/
|
|
bool HETG::FCmdPrint(PCMD pcmd)
|
|
{
|
|
#ifdef WIN
|
|
PRINTDLG pd;
|
|
DOCINFO di;
|
|
PGPT pgpt = pvNil;
|
|
PGNV pgnv = pvNil;
|
|
STN stn;
|
|
RC rc;
|
|
|
|
// set up the print dialog structure
|
|
ClearPb(&pd, size(pd));
|
|
pd.lStructSize = size(pd);
|
|
pd.Flags = PD_RETURNDC | PD_HIDEPRINTTOFILE | PD_NOPAGENUMS |
|
|
PD_NOSELECTION | PD_USEDEVMODECOPIES;
|
|
pd.hwndOwner = vwig.hwndApp;
|
|
|
|
if (!PrintDlg(&pd))
|
|
goto LFail;
|
|
|
|
// see if the device supports BitBlt
|
|
if (!(GetDeviceCaps(pd.hDC, RASTERCAPS) & RC_BITBLT))
|
|
goto LFail;
|
|
|
|
if (pvNil == (pgpt = GPT::PgptNew(pd.hDC)))
|
|
goto LFail;
|
|
if (pvNil == (pgnv = NewObj GNV(pgpt)))
|
|
goto LFail;
|
|
|
|
rc.Zero();
|
|
rc.xpRight = GetDeviceCaps(pd.hDC, LOGPIXELSX);
|
|
rc.ypBottom = GetDeviceCaps(pd.hDC, LOGPIXELSY);
|
|
pgnv->SetRcDst(&rc);
|
|
rc.xpRight = kdzpInch;
|
|
rc.ypBottom = kdzpInch;
|
|
pgnv->SetRcSrc(&rc);
|
|
|
|
Phetd()->GetName(&stn);
|
|
di.cbSize = size(di);
|
|
di.lpszDocName = stn.Psz();
|
|
di.lpszOutput = pvNil;
|
|
|
|
if (SP_ERROR == StartDoc(pd.hDC, &di))
|
|
goto LFail;
|
|
|
|
if (0 >= StartPage(pd.hDC))
|
|
goto LFail;
|
|
|
|
rc.Set(0, 0, GetDeviceCaps(pd.hDC, HORZRES), GetDeviceCaps(pd.hDC, VERTRES));
|
|
rc.Inset(kdzpInch, kdzpInch);
|
|
|
|
DrawLines(pgnv, &rc, rc.xpLeft, rc.ypTop, 0, klwMax, ftxtgNoColor);
|
|
|
|
if (0 >= EndPage(pd.hDC))
|
|
goto LFail;
|
|
|
|
if (0 >= EndDoc(pd.hDC))
|
|
{
|
|
LFail:
|
|
vpappb->TGiveAlertSz(PszLit("Printing failed"), bkOk, cokExclamation);
|
|
}
|
|
|
|
if (pd.hDC != hNil)
|
|
DeleteDC(pd.hDC);
|
|
if (pd.hDevMode != hNil)
|
|
GlobalFree(pd.hDevMode);
|
|
if (pd.hDevNames != hNil)
|
|
GlobalFree(pd.hDevNames);
|
|
ReleasePpo(&pgnv);
|
|
ReleasePpo(&pgpt);
|
|
#endif //WIN
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
enum
|
|
{
|
|
kiditIgnoreSpell,
|
|
kiditCancelSpell,
|
|
kiditChangeSpell,
|
|
kiditChangeAllSpell,
|
|
kiditIgnoreAllSpell,
|
|
kiditAddSpell,
|
|
kiditComboSpell,
|
|
kiditBadSpell,
|
|
kiditLimSpell
|
|
};
|
|
|
|
|
|
/***************************************************************************
|
|
Spell check the topic.
|
|
***************************************************************************/
|
|
bool HETG::FCmdCheckSpelling(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcmd);
|
|
|
|
#ifdef SPELL
|
|
STN stn;
|
|
long cactChanges;
|
|
|
|
if (pvNil != vpsplc)
|
|
{
|
|
vpsplc->FlushIgnoreList();
|
|
vpsplc->FlushChangeList(fTrue);
|
|
}
|
|
|
|
if (FCheckSpelling(&cactChanges))
|
|
{
|
|
if (cactChanges == 0)
|
|
stn = PszLit("No corrections made.");
|
|
else
|
|
stn.FFormatSz(PszLit("Corrected %d words."), cactChanges);
|
|
vpappb->TGiveAlertSz(stn.Psz(), bkOk, cokExclamation);
|
|
}
|
|
#else //!SPELL
|
|
vpappb->TGiveAlertSz(PszLit("Spell checking not available"),
|
|
bkOk, cokExclamation);
|
|
#endif //!SPELL
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Spell check the topic.
|
|
***************************************************************************/
|
|
bool HETG::FCheckSpelling(long *pcactChanges)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcactChanges);
|
|
|
|
#ifdef SPELL
|
|
achar rgch[1024];
|
|
long cpMin, cpMac;
|
|
long cchBuf;
|
|
long ichMin, ichLim;
|
|
long idit;
|
|
long cstn;
|
|
STN stnSrc, stnDst;
|
|
long scrs;
|
|
PDLG pdlg = pvNil;
|
|
|
|
*pcactChanges = 0;
|
|
if (pvNil == vpsplc)
|
|
{
|
|
if (ksclidAmerican == vsclid)
|
|
stnSrc = PszLit("Chelp");
|
|
else
|
|
stnSrc.FFormatSz(PszLit("Chp%d"), vsclid);
|
|
|
|
if (pvNil == (vpsplc = SPLC::PsplcNew(vsclid, &stnSrc)))
|
|
{
|
|
vpappb->TGiveAlertSz(PszLit("Couldn't load the main dictionary"), bkOk,
|
|
cokExclamation);
|
|
return fFalse;
|
|
}
|
|
}
|
|
|
|
cpMin = 0;
|
|
cpMac = _ptxtb->CpMac() - 1;
|
|
|
|
for (cchBuf = 0; cpMin < cpMac; )
|
|
{
|
|
if (cchBuf <= 0)
|
|
{
|
|
// fetch more text
|
|
if ((cchBuf = CvFromRgv(rgch)) + cpMin < cpMac)
|
|
{
|
|
// make sure we end on a word boundary
|
|
long cpT = _ptxtb->CpPrev(cpMin + cchBuf, fTrue);
|
|
if (cpT > cpMin)
|
|
cchBuf = cpT - cpMin;
|
|
}
|
|
else
|
|
cchBuf = cpMac - cpMin;
|
|
|
|
AssertIn(cchBuf, 1, CvFromRgv(rgch) + 1);
|
|
_ptxtb->FetchRgch(cpMin, cchBuf, rgch);
|
|
}
|
|
AssertIn(cchBuf, 1, CvFromRgv(rgch) + 1);
|
|
|
|
if (!vpsplc->FCheck(rgch, cchBuf, &ichMin, &ichLim, &stnDst, &scrs))
|
|
{
|
|
vpappb->TGiveAlertSz(PszLit("Spell checking failed!"),
|
|
bkOk, cokExclamation);
|
|
return fFalse;
|
|
}
|
|
|
|
if (ichMin >= cchBuf || ichMin >= ichLim)
|
|
{
|
|
cpMin += cchBuf;
|
|
cchBuf = 0;
|
|
continue;
|
|
}
|
|
|
|
// misspelled word
|
|
SetSel(cpMin + ichMin, cpMin + ichLim);
|
|
|
|
if (scrs == scrsReturningChangeAlways)
|
|
{
|
|
// change all word - change it and continue on
|
|
goto LChange;
|
|
}
|
|
|
|
// put up the dialog
|
|
if (pvNil == pdlg &&
|
|
pvNil == (pdlg = DLG::PdlgNew(dlidCheckSpelling)))
|
|
{
|
|
vpappb->TGiveAlertSz(PszLit("Couldn't create spelling dialog!"),
|
|
bkOk, cokExclamation);
|
|
return fFalse;
|
|
}
|
|
|
|
stnSrc.SetRgch(rgch + ichMin, ichLim - ichMin);
|
|
pdlg->FPutStn(kiditBadSpell, &stnSrc);
|
|
if (scrs == scrsReturningChangeOnce)
|
|
pdlg->FPutStn(kiditComboSpell, &stnDst);
|
|
else
|
|
pdlg->FPutStn(kiditComboSpell, &stnSrc);
|
|
|
|
// fill in the suggestions
|
|
pdlg->ClearList(kiditComboSpell);
|
|
for (cstn = 0;
|
|
cstn < 20 && vpsplc->FSuggest(rgch + ichMin, ichLim - ichMin,
|
|
cstn == 0, &stnDst);
|
|
cstn++)
|
|
{
|
|
pdlg->FAddToList(kiditComboSpell, &stnDst);
|
|
}
|
|
|
|
Clean();
|
|
idit = pdlg->IditDo(kiditComboSpell);
|
|
|
|
switch (idit)
|
|
{
|
|
default:
|
|
Bug("unknown button");
|
|
ReleasePpo(&pdlg);
|
|
return fFalse;
|
|
|
|
case kiditAddSpell:
|
|
vpsplc->FAddToUser(&stnSrc);
|
|
goto LIgnore;
|
|
|
|
case kiditIgnoreAllSpell:
|
|
vpsplc->FIgnoreAll(&stnSrc);
|
|
// fall thru
|
|
case kiditIgnoreSpell:
|
|
LIgnore:
|
|
if (cchBuf > ichLim)
|
|
BltPb(rgch + ichLim, rgch, (cchBuf - ichLim) * size(achar));
|
|
cchBuf -= ichLim;
|
|
cpMin += ichLim;
|
|
break;
|
|
|
|
case kiditChangeSpell:
|
|
case kiditChangeAllSpell:
|
|
pdlg->GetStn(kiditComboSpell, &stnDst);
|
|
if (!stnDst.FEqualRgch(rgch + ichMin, ichLim - ichMin))
|
|
{
|
|
// tell the spell checker that we're doing a change
|
|
vpsplc->FChange(&stnSrc, &stnDst, idit == kiditChangeAllSpell);
|
|
|
|
LChange:
|
|
(*pcactChanges)++;
|
|
HideSel();
|
|
if (!_ptxtb->FReplaceRgch(stnDst.Prgch(), stnDst.Cch(),
|
|
cpMin + ichMin, ichLim - ichMin))
|
|
{
|
|
vpappb->TGiveAlertSz(PszLit("Couldn't replace wrong word!"),
|
|
bkOk, cokExclamation);
|
|
ReleasePpo(&pdlg);
|
|
return fFalse;
|
|
}
|
|
}
|
|
|
|
if (cchBuf > ichLim)
|
|
BltPb(rgch + ichLim, rgch, (cchBuf - ichLim) * size(achar));
|
|
cchBuf -= ichLim;
|
|
cpMac += stnDst.Cch() + ichMin - ichLim;
|
|
cpMin += stnDst.Cch() + ichMin;
|
|
break;
|
|
|
|
case kiditCancelSpell:
|
|
ReleasePpo(&pdlg);
|
|
return fFalse;
|
|
}
|
|
}
|
|
|
|
ReleasePpo(&pdlg);
|
|
#else //!SPELL
|
|
vpappb->TGiveAlertSz(PszLit("Spell checking not available"),
|
|
bkOk, cokExclamation);
|
|
*pcactChanges = 0;
|
|
#endif //!SPELL
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Handle idle stuff - update the ruler with our new height.
|
|
***************************************************************************/
|
|
void HETG::InvalCp(long cp, long ccpIns, long ccpDel)
|
|
{
|
|
AssertThis(0);
|
|
long dyp;
|
|
|
|
HETG_PAR::InvalCp(cp, ccpIns, ccpDel);
|
|
if (pvNil == _ptrul || !_ptrul->FIs(kclsHTRU))
|
|
return;
|
|
|
|
GetNaturalSize(pvNil, &dyp);
|
|
((PHTRU)_ptrul)->SetDypHeight(dyp);
|
|
}
|
|
|
|
|
|
enum
|
|
{
|
|
kiditOkSize,
|
|
kiditCancelSize,
|
|
kiditSizeSize,
|
|
kiditLimSize
|
|
};
|
|
|
|
|
|
/***************************************************************************
|
|
Get a font size from the user.
|
|
***************************************************************************/
|
|
bool HETG::_FGetOtherSize(long *pdypFont)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pdypFont);
|
|
PDLG pdlg;
|
|
bool fRet;
|
|
|
|
if (pvNil == (pdlg = DLG::PdlgNew(dlidFontSize)))
|
|
return fFalse;
|
|
|
|
pdlg->FPutLwInEdit(kiditSizeSize, *pdypFont);
|
|
|
|
if (kiditOkSize != pdlg->IditDo(kiditSizeSize))
|
|
{
|
|
ReleasePpo(&pdlg);
|
|
return fFalse;
|
|
}
|
|
|
|
fRet = pdlg->FGetLwFromEdit(kiditSizeSize, pdypFont);
|
|
ReleasePpo(&pdlg);
|
|
return fRet;
|
|
}
|
|
|
|
|
|
enum
|
|
{
|
|
kiditOkOffset,
|
|
kiditCancelOffset,
|
|
kiditSizeOffset,
|
|
kiditSuperOffset,
|
|
kiditLimOffset
|
|
};
|
|
|
|
|
|
/***************************************************************************
|
|
Get the amount to sub/superscript from the user.
|
|
***************************************************************************/
|
|
bool HETG::_FGetOtherSubSuper(long *pdypOffset)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pdypOffset);
|
|
PDLG pdlg;
|
|
bool fRet;
|
|
|
|
if (pvNil == (pdlg = DLG::PdlgNew(dlidSubSuper)))
|
|
return fFalse;
|
|
|
|
pdlg->FPutLwInEdit(kiditSizeSize, LwAbs(*pdypOffset));
|
|
pdlg->PutCheck(kiditSuperOffset, *pdypOffset < 0);
|
|
|
|
if (kiditOkOffset != pdlg->IditDo(kiditSizeOffset))
|
|
{
|
|
ReleasePpo(&pdlg);
|
|
return fFalse;
|
|
}
|
|
|
|
fRet = pdlg->FGetLwFromEdit(kiditSizeOffset, pdypOffset);
|
|
if (pdlg->FGetCheck(kiditSuperOffset))
|
|
*pdypOffset = -*pdypOffset;
|
|
ReleasePpo(&pdlg);
|
|
return fRet;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Get the height of a particular line. Returns 0 if the line is past
|
|
the end of the document.
|
|
***************************************************************************/
|
|
long HETG::DypLine(long ilin)
|
|
{
|
|
AssertThis(0);
|
|
AssertIn(ilin, 0, kcbMax);
|
|
LIN lin;
|
|
long ilinT;
|
|
|
|
_FetchLin(ilin, &lin, &ilinT);
|
|
if (ilin > ilinT)
|
|
return 0;
|
|
|
|
return LwMax(1, lin.dyp);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Constructor for a text ruler.
|
|
***************************************************************************/
|
|
HTRU::HTRU(GCB *pgcb, PTXTG ptxtg) : HTRU_PAR(pgcb)
|
|
{
|
|
AssertPo(ptxtg, 0);
|
|
_ptxtg = ptxtg;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Create a new text ruler.
|
|
***************************************************************************/
|
|
PHTRU HTRU::PhtruNew(GCB *pgcb, PTXTG ptxtg, long dxpTab, long dxpDoc,
|
|
long dypDoc, long xpLeft, long onn, long dypFont, ulong grfont)
|
|
{
|
|
AssertVarMem(pgcb);
|
|
AssertPo(ptxtg, 0);
|
|
AssertIn(dxpTab, 1, kcbMax);
|
|
AssertIn(dxpDoc, 1, kcbMax);
|
|
PHTRU phtru;
|
|
|
|
if (pvNil == (phtru = NewObj HTRU(pgcb, ptxtg)))
|
|
return pvNil;
|
|
|
|
phtru->_dxpTab = dxpTab;
|
|
phtru->_dxpDoc = dxpDoc;
|
|
phtru->_dyp = dypDoc;
|
|
phtru->_xpLeft = xpLeft;
|
|
phtru->_onn = onn;
|
|
phtru->_dypFont = dypFont;
|
|
phtru->_grfont = grfont;
|
|
AssertPo(phtru, 0);
|
|
return phtru;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Draw the ruler.
|
|
***************************************************************************/
|
|
void HTRU::Draw(PGNV pgnv, RC *prcClip)
|
|
{
|
|
AssertThis(0);
|
|
AssertPo(pgnv, 0);
|
|
AssertVarMem(prcClip);
|
|
RC rc, rcT;
|
|
STN stn;
|
|
|
|
GetRc(&rc, cooLocal);
|
|
pgnv->SetPenSize(0, 1);
|
|
pgnv->FrameRc(&rc, kacrBlack);
|
|
rc.Inset(0, 1);
|
|
pgnv->FillRc(&rc, kacrWhite);
|
|
|
|
rcT = rc;
|
|
rcT.ypTop = rc.YpCenter();
|
|
rcT.ypBottom = rcT.ypTop + 1;
|
|
pgnv->FillRc(&rcT, kacrBlack);
|
|
|
|
stn.FFormatSz(PszLit("Width = %d; Tab = %d; Height = %d"),
|
|
_dxpDoc, _dxpTab, _dyp);
|
|
pgnv->SetFont(_onn, _grfont, _dypFont);
|
|
pgnv->DrawStn(&stn, rc.xpLeft + 8, rc.ypTop);
|
|
|
|
rc.ypTop = rcT.ypBottom;
|
|
rcT = rc;
|
|
rcT.xpLeft = _xpLeft - 1;
|
|
rcT.xpRight = _xpLeft + 1;
|
|
pgnv->FillRcApt(&rcT, &vaptGray, kacrBlack, kacrWhite);
|
|
|
|
rcT.Offset(_dxpDoc, 0);
|
|
pgnv->FillRc(&rcT, kacrBlack);
|
|
|
|
rcT.Inset(0, 2);
|
|
rcT.Offset(_dxpTab - _dxpDoc, 0);
|
|
pgnv->FillRc(&rcT, kacrBlack);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Track the mouse.
|
|
***************************************************************************/
|
|
bool HTRU::FCmdTrackMouse(PCMD_MOUSE pcmd)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcmd);
|
|
|
|
if (pcmd->cid == cidMouseDown)
|
|
{
|
|
Assert(vpcex->PgobTracking() == pvNil, "mouse already being tracked!");
|
|
RC rc;
|
|
|
|
GetRc(&rc, cooLocal);
|
|
if (pcmd->yp < rc.YpCenter())
|
|
{
|
|
_rtt = rttNil;
|
|
return fTrue;
|
|
}
|
|
|
|
if (LwAbs(pcmd->xp - _xpLeft - _dxpTab) < 3)
|
|
{
|
|
_rtt = krttTab;
|
|
_dxpTrack = _dxpTab - pcmd->xp;
|
|
}
|
|
else if (LwAbs(pcmd->xp - _xpLeft - _dxpDoc) < 3)
|
|
{
|
|
_rtt = krttDoc;
|
|
_dxpTrack = _dxpDoc - pcmd->xp;
|
|
}
|
|
else
|
|
{
|
|
_rtt = rttNil;
|
|
return fTrue;
|
|
}
|
|
vpcex->TrackMouse(this);
|
|
}
|
|
else
|
|
{
|
|
Assert(vpcex->PgobTracking() == this, "not tracking mouse!");
|
|
Assert(pcmd->cid == cidTrackMouse, 0);
|
|
Assert(_rtt != rttNil, "no track type");
|
|
}
|
|
|
|
switch (_rtt)
|
|
{
|
|
case krttTab:
|
|
_ptxtg->SetDxpTab(pcmd->xp + _dxpTrack);
|
|
break;
|
|
case krttDoc:
|
|
_ptxtg->SetDxpDoc(pcmd->xp + _dxpTrack);
|
|
break;
|
|
}
|
|
|
|
if (pcmd->cid == cidMouseDown)
|
|
_ptxtg->Ptxtb()->SuspendUndo();
|
|
|
|
if (!(pcmd->grfcust & fcustMouse))
|
|
{
|
|
_ptxtg->Ptxtb()->ResumeUndo();
|
|
vpcex->EndMouseTracking();
|
|
_rtt = rttNil;
|
|
}
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
enum
|
|
{
|
|
kiditOkFont,
|
|
kiditCancelFont,
|
|
kiditComboFont,
|
|
kiditLimFont
|
|
};
|
|
|
|
|
|
/***************************************************************************
|
|
Give the fonts in a dialog.
|
|
***************************************************************************/
|
|
bool HETG::FCmdFontDialog(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pcmd);
|
|
PDLG pdlg;
|
|
CHP chpNew, chpOld;
|
|
STN stn;
|
|
long onn;
|
|
|
|
if (pvNil == (pdlg = DLG::PdlgNew(dlidChooseFont)))
|
|
return fTrue;
|
|
|
|
// fill in the font list
|
|
pdlg->ClearList(kiditComboFont);
|
|
for (onn = 0; onn < vntl.OnnMac(); onn++)
|
|
{
|
|
vntl.GetStn(onn, &stn);
|
|
pdlg->FAddToList(kiditComboFont, &stn);
|
|
}
|
|
|
|
_EnsureChpIns();
|
|
vntl.GetStn(_chpIns.onn, &stn);
|
|
pdlg->FPutStn(kiditComboFont, &stn);
|
|
|
|
if (kiditOkFont == pdlg->IditDo(kiditComboFont))
|
|
{
|
|
pdlg->GetStn(kiditComboFont, &stn);
|
|
if (vntl.FGetOnn(&stn, &onn))
|
|
{
|
|
chpNew.Clear();
|
|
chpOld.Clear();
|
|
chpNew.onn = onn;
|
|
chpOld.onn = ~onn;
|
|
FApplyChp(&chpNew, &chpOld);
|
|
}
|
|
}
|
|
ReleasePpo(&pdlg);
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Set the tab width.
|
|
***************************************************************************/
|
|
void HTRU::SetDxpTab(long dxpTab)
|
|
{
|
|
AssertThis(0);
|
|
if (dxpTab == _dxpTab)
|
|
return;
|
|
|
|
_dxpTab = dxpTab;
|
|
AssertThis(0);
|
|
InvalRc(pvNil, kginMark);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Set the document width.
|
|
***************************************************************************/
|
|
void HTRU::SetDxpDoc(long dxpDoc)
|
|
{
|
|
AssertThis(0);
|
|
if (dxpDoc == _dxpDoc)
|
|
return;
|
|
|
|
_dxpDoc = dxpDoc;
|
|
AssertThis(0);
|
|
InvalRc(pvNil, kginMark);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Change the location of the left edge of the document.
|
|
***************************************************************************/
|
|
void HTRU::SetXpLeft(long xpLeft)
|
|
{
|
|
AssertThis(0);
|
|
if (xpLeft == _xpLeft)
|
|
return;
|
|
|
|
_xpLeft = xpLeft;
|
|
AssertThis(0);
|
|
InvalRc(pvNil, kginMark);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Set the text height.
|
|
***************************************************************************/
|
|
void HTRU::SetDypHeight(long dyp)
|
|
{
|
|
AssertThis(0);
|
|
if (dyp == _dyp)
|
|
return;
|
|
|
|
_dyp = dyp;
|
|
AssertThis(0);
|
|
InvalRc(pvNil, kginMark);
|
|
}
|
|
|
|
|
|
#ifdef DEBUG
|
|
/***************************************************************************
|
|
Assert the validity of a HTRU.
|
|
***************************************************************************/
|
|
void HTRU::AssertValid(ulong grf)
|
|
{
|
|
HTRU_PAR::AssertValid(0);
|
|
AssertPo(_ptxtg, 0);
|
|
AssertIn(_dxpTab, 1, kcbMax);
|
|
AssertIn(_dxpDoc, 1, kcbMax);
|
|
}
|
|
#endif //DEBUG
|
|
|
|
|
|
/***************************************************************************
|
|
Munge the string so it is a valid token or empty.
|
|
***************************************************************************/
|
|
void _TokenizeStn(PSTN pstn)
|
|
{
|
|
AssertPo(pstn, 0);
|
|
bool fDigitOk;
|
|
SZ sz;
|
|
achar ch;
|
|
achar *pch;
|
|
|
|
fDigitOk = fFalse;
|
|
pstn->GetSz(sz);
|
|
for (pch = sz; *pch; pch++, fDigitOk = fTrue)
|
|
{
|
|
ch = *pch;
|
|
if (!FIn(ch, ChLit('A'), ChLit('Z') + 1) &&
|
|
!FIn(ch, ChLit('a'), ChLit('z') + 1))
|
|
{
|
|
if (!fDigitOk || !FIn(ch, ChLit('0'), ChLit('9') + 1))
|
|
{
|
|
*pch = ChLit('_');
|
|
}
|
|
}
|
|
}
|
|
*pch = 0;
|
|
*pstn = sz;
|
|
}
|
|
|
|
|
|
enum
|
|
{
|
|
kiditOkFind,
|
|
kiditCancelFind,
|
|
kiditFindFind,
|
|
kiditReplaceFind,
|
|
kiditCaseSensitiveFind,
|
|
kiditLimFind
|
|
};
|
|
|
|
|
|
bool _FDlgFind(PDLG pdlg, long *pidit, void *pv);
|
|
|
|
|
|
/***************************************************************************
|
|
Dialog proc for searching.
|
|
***************************************************************************/
|
|
bool _FDlgFind(PDLG pdlg, long *pidit, void *pv)
|
|
{
|
|
AssertPo(pdlg, 0);
|
|
AssertVarMem(pidit);
|
|
STN stn;
|
|
|
|
switch (*pidit)
|
|
{
|
|
case kiditCancelFind:
|
|
return fTrue; //dismiss the dialog
|
|
|
|
case kiditOkFind:
|
|
if (!pdlg->FGetValues(0, kiditLimFind))
|
|
{
|
|
*pidit = ivNil;
|
|
return fTrue;
|
|
}
|
|
pdlg->GetStn(kiditFindFind, &stn);
|
|
if (stn.Cch() <= 0)
|
|
{
|
|
vpappb->TGiveAlertSz(PszLit("Empty search string"), bkOk, cokStop);
|
|
pdlg->SelectDit(kiditFindFind);
|
|
return fFalse;
|
|
}
|
|
return fTrue;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return fFalse;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Do the find dialog. Return true if the user OK'ed the dialog.
|
|
***************************************************************************/
|
|
bool _FDoFindDlg(void)
|
|
{
|
|
PDLG pdlg;
|
|
STN stn;
|
|
bool fRet = fFalse;
|
|
|
|
if (pvNil == (pdlg = DLG::PdlgNew(dlidFind, _FDlgFind)))
|
|
return fFalse;
|
|
vpstrg->FGet(kstidFind, &stn);
|
|
pdlg->FPutStn(kiditFindFind, &stn);
|
|
vpstrg->FGet(kstidReplace, &stn);
|
|
pdlg->FPutStn(kiditReplaceFind, &stn);
|
|
pdlg->PutCheck(kiditCaseSensitiveFind, _fCaseSensitive);
|
|
|
|
if (kiditOkFind != pdlg->IditDo(kiditFindFind))
|
|
goto LFail;
|
|
pdlg->GetStn(kiditFindFind, &stn);
|
|
if (stn.Cch() <= 0)
|
|
goto LFail;
|
|
vpstrg->FPut(kstidFind, &stn);
|
|
pdlg->GetStn(kiditReplaceFind, &stn);
|
|
vpstrg->FPut(kstidReplace, &stn);
|
|
_fCaseSensitive = FPure(pdlg->FGetCheck(kiditCaseSensitiveFind));
|
|
fRet = fTrue;
|
|
|
|
LFail:
|
|
ReleasePpo(&pdlg);
|
|
|
|
return fRet;
|
|
}
|