/***************************************************************************** * * * 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; }