323 lines
8.5 KiB
C++
323 lines
8.5 KiB
C++
/*****************************************************************************
|
|
* *
|
|
* NEXTLIST.C *
|
|
* *
|
|
* Copyright (C) Microsoft Corporation 1990. *
|
|
* All Rights reserved. *
|
|
* *
|
|
******************************************************************************
|
|
* *
|
|
* Module Intent *
|
|
* This module processes nextlist footnotes, putting the information into *
|
|
* a temporary file. After parsing all the RTF files, it then processes *
|
|
* this file. Eventually it will backpatch the |TOPIC file with the correct *
|
|
* browse topic addresses; for now, it just creates the |TOMAP with the *
|
|
* correct addresses. *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Revision History: Created 00/00/00 by LarryPo
|
|
*
|
|
* 11/21/90 JohnSc RcSortFm() replaces RcMegasortFm()
|
|
* 12/02/90 JohnSc do case insensitive sort of browse tags
|
|
* 12/14/90 JohnSc FErrorRc(rc) -> FErrorHce(HceFromRc(rc))
|
|
* 25-Feb-1991 JohnSc bug 948: unsafe calls to HceFromRc()
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "stdafx.h"
|
|
|
|
#pragma hdrstop
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Defines *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
#define chMinorDelimiter ((char) ':')
|
|
#define szMajorDefault "R"
|
|
|
|
/* This is the offset from the start of a topic FC to the previous
|
|
* and next fields in the packed MTOP structure.
|
|
* Note that the MOBJ structure contains a WORD parameter at the end
|
|
* that we currently don't write out in topic objects.
|
|
*/
|
|
#define cbOffsetToPrevInMTOP &(((QMTOP)0)->prev)
|
|
#define cbOffsetToNextInMTOP &(((QMTOP)0)->next)
|
|
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Typedefs *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
// Next List Info.
|
|
|
|
typedef struct {
|
|
FCL fclTopic; // backpatch location of MTOP struct.
|
|
WORD iBitdex; // magic zeck-compression code-bits bitdex for that fcl.
|
|
ADDR addr; // addr to backpatch.
|
|
BOOL fNewSeq; // TRUE if this NLI starts a new sequence.
|
|
} NLI;
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Static Variables *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
/*
|
|
* This variable contains the number of entries that have been written
|
|
* out to ptfBrowse.
|
|
*/
|
|
|
|
static long cnliMac;
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: FProcNextlistSz
|
|
|
|
PURPOSE: Processes a nextlist footnote string.
|
|
|
|
PARAMETERS:
|
|
szNextlist -- The nextlist footnote string
|
|
idfcp
|
|
perr
|
|
|
|
RETURNS:
|
|
|
|
COMMENTS:
|
|
|
|
MODIFICATION DATES:
|
|
30-Jul-1993 [ralphw]
|
|
|
|
***************************************************************************/
|
|
|
|
static int autoBrowse = 1;
|
|
static const char txtAuto[] = "auto";
|
|
|
|
BOOL STDCALL FProcNextlistSz(PSTR szNextlist, IDFCP idfcp, PERR perr)
|
|
{
|
|
PSTR pszMinor, pszMajor;
|
|
static BOOL fCreateFailed = FALSE;
|
|
char szBuf[10];
|
|
|
|
// Check if no browse sequences to be made
|
|
|
|
if (!ptblBrowse)
|
|
ptblBrowse = new CTable;
|
|
|
|
if (fBrowseDefined) {
|
|
VReportError(HCERR_BROWSE_DEFINED, &errHpj);
|
|
return FALSE;
|
|
}
|
|
|
|
pszMinor = StrChr(szNextlist, chMinorDelimiter, fDBCSSystem);
|
|
if (pszMinor == NULL) {
|
|
pszMajor = szMajorDefault;
|
|
pszMinor = SzTrimSz(szNextlist);
|
|
if (*pszMinor == '\0') {
|
|
pszMinor = szBuf;
|
|
_ltoa(autoBrowse++, szBuf, 10);
|
|
}
|
|
}
|
|
else {
|
|
*pszMinor = '\0';
|
|
pszMinor = SzTrimSz(pszMinor + 1);
|
|
if (*pszMinor == '\0' || _stricmp(pszMinor, txtAuto) == 0) {
|
|
pszMinor = szBuf;
|
|
_ltoa(autoBrowse++, szBuf, 10);
|
|
}
|
|
|
|
pszMajor = SzTrimSz(szNextlist);
|
|
if (*pszMajor == '\0')
|
|
pszMajor = szMajorDefault; // REVIEW: Warning needed ?
|
|
}
|
|
|
|
// Check for browse sequence defined too late
|
|
|
|
if (fHasTopicFCP) {
|
|
VReportError(HCERR_LATE_BROWSE, &errHpj);
|
|
return FALSE;
|
|
}
|
|
|
|
fBrowseDefined = TRUE;
|
|
FDelayExecutionBrowse(pszMajor, pszMinor, idfcp);
|
|
cnliMac++;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
- Name FResolveNextlist
|
|
-
|
|
* Purpose
|
|
* This function processes the file of browse sequences to do
|
|
* what needs to be done to make browsing happen. Right now, that
|
|
* is to write FCL's to the |TOMAP file. In the future, this
|
|
* will consist of backpatching PA's into the |TOPIC file.
|
|
*
|
|
* Arguments
|
|
*
|
|
* Returns
|
|
*
|
|
* Globals
|
|
* This function uses the static variable cnliMac, which contains
|
|
* the number of entries in ptfBrowse.
|
|
*
|
|
* +++
|
|
*
|
|
* Notes
|
|
*
|
|
***************************************************************************/
|
|
|
|
static const int GRIND_INCREMENT = 100;
|
|
|
|
BOOL STDCALL FResolveNextlist(HF hfTopic)
|
|
{
|
|
#ifdef _DEBUG
|
|
int inli = 0;
|
|
#endif
|
|
PSTR szMajor, szMinor, pchFcl, pchAddr, pchBitdex;
|
|
int cGrind = 0;
|
|
|
|
//ADDR addr;
|
|
|
|
NLI nliPrev, nliCur, nliNext;
|
|
|
|
if (!ptblBrowse)
|
|
return TRUE; // Nothing to be done
|
|
|
|
// Check for no browse sequences:
|
|
|
|
if (cnliMac == 0) {
|
|
delete ptblBrowse;
|
|
ptblBrowse = NULL;
|
|
return TRUE;
|
|
}
|
|
|
|
SendStringToParent(IDS_RESOLVING_BROWSE);
|
|
if (!hwndParent && hwndGrind)
|
|
SetWindowText(hwndGrind, GetStringResource(IDS_RESOLVING_BROWSE));
|
|
|
|
ptblBrowse->SetSorting(lcid, kwlcid.fsCompareI, kwlcid.fsCompare);
|
|
ptblBrowse->SortTable();
|
|
doGrind();
|
|
|
|
/*
|
|
* When reading in new strings, we need to check if the major string
|
|
* matches the previous major string. To do this, the previous major
|
|
* string is stored at szScratchBuf, and the current major string is read
|
|
* in following that. The first previous major string is nil to always
|
|
* make it different.
|
|
*/
|
|
|
|
szScratchBuf[0] = '\0';
|
|
szMajor = szScratchBuf + 1;
|
|
nliCur.fclTopic = fclNil;
|
|
|
|
ptblBrowse->SetPosition(1);
|
|
|
|
while (ptblBrowse->GetString(szMajor)) {
|
|
|
|
if (++cGrind >= GRIND_INCREMENT) {
|
|
cGrind = 0;
|
|
doGrind();
|
|
}
|
|
|
|
// Split input into different strings
|
|
|
|
szMinor = StrChr(szMajor, chMinorDelimiter, fDBCSSystem);
|
|
ASSERT(szMinor != NULL);
|
|
*szMinor++ = '\0';
|
|
|
|
/* NOTE: While we are guaranteed that the major sequence string will
|
|
* not contain a delimiter character, we have no such guarantee for
|
|
* the minor sequence string. To calculate pointers to the fcl
|
|
* and addr fields, then, we need to backtrack from the end of
|
|
* the string.
|
|
*
|
|
* Each field is eight characters wide, and they are separated
|
|
* by ':' characters. The string will be terminated by a newline,
|
|
* unless buffer overflow has occured.
|
|
*/
|
|
|
|
pchAddr = StrChr(szMinor, '\n', fDBCSSystem);
|
|
ASSERT(pchAddr != NULL);
|
|
pchAddr -= 9;
|
|
pchBitdex = pchAddr - 9;
|
|
pchFcl = pchBitdex - 9;
|
|
ASSERT(*pchAddr == ':' && *pchFcl == ':' && *pchBitdex == ':');
|
|
|
|
*pchFcl++ = '\0';
|
|
*pchBitdex++ = '\0';
|
|
*pchAddr++ = '\0';
|
|
|
|
nliNext.fclTopic = strtoul(pchFcl, NULL, 16);
|
|
nliNext.iBitdex = (WORD) strtoul(pchBitdex, NULL, 16);
|
|
nliNext.addr = strtoul(pchAddr, NULL, 16);
|
|
nliNext.fNewSeq = (strcmp(szScratchBuf, szMajor) != 0);
|
|
|
|
// Copy new szMajor to rgch, and move next szMajor to just beyond it
|
|
|
|
strcpy(szScratchBuf, szMajor);
|
|
szMajor = StrChr(szScratchBuf, '\0', FALSE) + 1;
|
|
|
|
// Write out next and previous addresses
|
|
|
|
if (nliCur.fclTopic != fclNil) {
|
|
|
|
// use magic zeck-backpatch code:
|
|
// Write out address of previous topic, if any
|
|
|
|
FDiskBackpatchZeck(hfTopic, nliCur.fclTopic,
|
|
(int) cbOffsetToPrevInMTOP,
|
|
nliCur.iBitdex, (nliCur.fNewSeq ? addrNil : nliPrev.addr));
|
|
|
|
// Write out address of next topic, if any
|
|
|
|
FDiskBackpatchZeck(hfTopic, nliCur.fclTopic,
|
|
(int) cbOffsetToNextInMTOP,
|
|
nliCur.iBitdex, (nliNext.fNewSeq ? addrNil : nliNext.addr));
|
|
}
|
|
nliPrev = nliCur;
|
|
nliCur = nliNext;
|
|
#ifdef _DEBUG
|
|
++inli;
|
|
#endif
|
|
}
|
|
|
|
delete ptblBrowse;
|
|
ptblBrowse = NULL;
|
|
|
|
ASSERT(inli == cnliMac);
|
|
|
|
// Process last browse sequence:
|
|
|
|
ASSERT(nliCur.fclTopic != fclNil);
|
|
|
|
// use magic zeck-backpatch code:
|
|
// Write out address of previous topic, if any
|
|
|
|
FDiskBackpatchZeck(hfTopic, nliCur.fclTopic,
|
|
(int) cbOffsetToPrevInMTOP,
|
|
nliCur.iBitdex, (nliCur.fNewSeq ? addrNil : nliPrev.addr));
|
|
|
|
// Write out address next address (always nil)
|
|
|
|
FDiskBackpatchZeck(hfTopic, nliCur.fclTopic,
|
|
(DWORD) cbOffsetToNextInMTOP, nliCur.iBitdex, (DWORD) addrNil);
|
|
|
|
return TRUE;
|
|
}
|