home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / appwiz / customwz / zap.cpp < prev    next >
C/C++ Source or Header  |  1998-03-05  |  19KB  |  475 lines

  1. // zap.cpp : implementation of the CZap class
  2. //
  3. // Copyright (c) 1985-1998, Microsoft Corporation. All rights reserved.
  4. //
  5.  
  6. #include "stdafx.h"
  7. #include "customwz.h"
  8. #include "sampleaw.h"
  9. #include "zap.h"
  10.  
  11. #ifdef _PSEUDO_DEBUG
  12. #undef THIS_FILE
  13. static char THIS_FILE[] = __FILE__;
  14. #endif
  15.  
  16. // This helper (used in CZap::LoadFile) determines whether we should zap
  17. //  a file into a "binary" template-- that is, a template to be copied using
  18. //  CopyTemplate, rather than parsed via ProcessTemplate.
  19. inline BOOL ShouldCopyVerbatim(LPCTSTR szFullName, LPCTSTR szExt)
  20. {
  21.     return (szExt != NULL &&
  22.         // Icons and bitmaps should be copied not parsed
  23.         (!_tcsicmp(szExt, _T(".ico")) || !_tcsicmp(szExt, _T(".bmp"))
  24.             // miscellaneous binary files not to be parsed
  25.             || !_tcsicmp(szExt, _T(".dat"))
  26.             // .rtf files other than afxdlg.rtf should be copied not parsed
  27.             || (!_tcsicmp(szExt, _T(".rtf")) && _tcsicmp(szFullName, _T("afxdlg.rtf")))));
  28. }
  29.  
  30. // Given a filename, map it to memory, store its size in dwSize, and return
  31. //  the mapped view.
  32. LPCTSTR CZap::LoadFile(LPCTSTR lpszResource, DWORD& dwSize)
  33. {
  34.     ASSERT(m_hFile == NULL);
  35.     ASSERT(m_hMapping == NULL);
  36.     ASSERT(m_strFile.IsEmpty());
  37.  
  38.     // First open the file
  39.     m_hFile = CreateFile(
  40.         lpszResource,           // File name
  41.         GENERIC_READ,           // Read-only
  42.         FILE_SHARE_READ
  43.             | FILE_SHARE_WRITE, // Allow sharing-- we're only doing a quick scan
  44.         NULL,                   // No security attributes
  45.         OPEN_EXISTING,          // Only open an existing file
  46.         0,                      // Ignore file attributes
  47.         NULL);                  // Ignore hTemplateFile
  48.  
  49.     if (m_hFile == INVALID_HANDLE_VALUE)
  50.     {
  51.         m_hFile = NULL;
  52.         ReportAndThrow(IDP_ZAP_CANT_OPEN_FILE, lpszResource);
  53.     }
  54.  
  55.     // Get the file's size
  56.     dwSize = GetFileSize(m_hFile, NULL);
  57.     if (dwSize == 0xffffffff)
  58.     {
  59.         m_hFile = NULL;
  60.         ReportAndThrow(IDP_ZAP_CANT_GET_SIZE, lpszResource);
  61.     }
  62.  
  63.     // Create a mapping object from the file
  64.     m_hMapping = CreateFileMapping(
  65.         m_hFile,                // Handle we got from CreateFile
  66.         NULL,                   // No security attributes
  67.         PAGE_READONLY,          // read-only
  68.         0, 0,                   // Max size = current size of file
  69.         NULL);                  // Don't name the mapping object
  70.  
  71.     // Map the file to memory
  72.     m_lpszFile = (LPCTSTR) MapViewOfFile(
  73.         m_hMapping,             // Handle we got from CreateFileMapping
  74.         FILE_MAP_READ,          // read-only (didn't I mention that before?)
  75.         0, 0,                   // Offset into file = beginning of file
  76.         0);                     // Map entire file
  77.  
  78.     _tsplitpath(lpszResource, NULL, m_strSubdir.GetBuffer(_MAX_DIR), m_strBaseFileName.GetBuffer(_MAX_FNAME),
  79.         m_strFileExt.GetBuffer(_MAX_EXT));
  80.     m_strSubdir.ReleaseBuffer();
  81.     m_strSubdir.MakeLower();
  82.     m_strBaseFileName.ReleaseBuffer();
  83.     m_strFileExt.ReleaseBuffer();
  84.     m_strBaseFileName += m_strFileExt;
  85.     LPCTSTR szBeginRootDir = _tcsstr(m_strSubdir, m_strRootDir);
  86.     ASSERT(szBeginRootDir != NULL);
  87.     m_strSubdir = szBeginRootDir + m_strRootDir.GetLength();
  88.  
  89.     m_bBinary = ShouldCopyVerbatim(m_strBaseFileName, m_strFileExt);
  90.  
  91.     // Remember name of file for potential future error messages
  92.     m_strFile = lpszResource;
  93.  
  94.     return m_lpszFile;
  95. }
  96.  
  97. // Called after a file has been zapped to deallocate resources used for zapping.
  98. void CZap::UnloadFile()
  99. {
  100.     ASSERT(m_hFile != NULL);
  101.     ASSERT(m_hMapping != NULL);
  102.     ASSERT(m_lpszFile != NULL);
  103.     ASSERT(!m_strFile.IsEmpty());
  104.  
  105.     VERIFY(UnmapViewOfFile((LPVOID) m_lpszFile));
  106.     VERIFY(CloseHandle(m_hMapping));
  107.     VERIFY(CloseHandle(m_hFile));
  108.     m_hFile = NULL;
  109.     m_hMapping = NULL;
  110.     m_strFile.Empty();
  111. }
  112.  
  113. // This helper (used in CZap::AddToNewProjInf) determines whether to set the
  114. //  "resource file" flag for this file in the generated newproj.inf
  115.  
  116. inline BOOL ShouldAddFileToResource (LPCTSTR szFullName, LPCTSTR szExt)
  117. {
  118.     return (szExt != NULL &&
  119.         (!_tcsicmp (szExt, _T(".rc2")) || !_tcscmp (szExt, _T(".ico"))
  120.         || !_tcsicmp (szExt, _T(".bmp"))));
  121. }
  122.  
  123. // This is defined in zapdlg.cpp.  We've stored the non-colliding names of the templates
  124. //  we're generating in here.  This information is used in CZap::AddToNewProjInf() below.
  125. extern CStringList g_TemplateNames;
  126.  
  127. // This is called after a file is zapped.  At that point, it has been determined
  128. //  whether the resulting template should be considered a "binary" template, and
  129. //  so we're prepared to add the entry to the generated custom AppWizard's
  130. //  newproj.inf (which is what this does).
  131. void CZap::AddToNewProjInf()
  132. {
  133.     ASSERT(m_posTplName != NULL);
  134.  
  135.     // Determine whether we should set the ':' flag.
  136.     CString strFlag;
  137.     if (ShouldAddFileToResource (m_strBaseFileName,  m_strFileExt))
  138.         strFlag = _T(":");
  139.  
  140.     // Determine whether we should set the '=' flag
  141.     CString strEquals;
  142.     strEquals = m_bBinary ? _T("=") : _T("");
  143.  
  144.     CString strMacroizedFile;
  145.     ZapFileName(m_strBaseFileName, strMacroizedFile);
  146.     CString strTemplateName = g_TemplateNames.GetNext(m_posTplName);
  147.  
  148.     // Finally, the string used in this custom AppWizard's newnwprj.inf
  149.     //  (i.e., the generated custom AppWizard's newproj.inf).
  150.     m_strGeneratedNewProjInfo += strEquals + strFlag + strTemplateName // Template we just zapped
  151.         + _T('\t')
  152.         + m_strSubdir + strMacroizedFile + _T('\n');        // What that template generates
  153. }
  154.  
  155.  
  156. // This is the meat of our override of ProcessTemplate.  It zaps a file line
  157. //  by line using ZapLine.
  158. void CZap::ZapFile(LPCTSTR lpszInput, DWORD dwSize, OutputStream* pOutput)
  159. {
  160.     ASSERT(m_hFile != NULL);
  161.     ASSERT(m_hMapping != NULL);
  162.     if (m_posTplName == NULL)
  163.         m_posTplName = g_TemplateNames.GetHeadPosition();
  164.  
  165.     if (m_bBinary)
  166.     {
  167.         sampleaw.CopyTemplate(lpszInput, dwSize, pOutput);
  168.         AddToNewProjInf();
  169.         return;
  170.     }
  171.  
  172.     if (dwSize == 0)
  173.     {
  174.         pOutput->WriteLine(_T(" "));
  175.         AddToNewProjInf();
  176.         return;
  177.     }
  178.  
  179.     LPCTSTR lpszBeginLine = lpszInput;
  180.     LPCTSTR lpszEndLine;
  181.  
  182.     // Loop line by line, until we go past the end
  183.     while ((DWORD) (lpszBeginLine-lpszInput) < dwSize)
  184.     {
  185.         // Start from the beginning of a line, and find a carriage return
  186.         lpszEndLine = _tcschr(lpszBeginLine, _T('\r'));
  187.  
  188.         // If there was no carriage return...
  189.         if (lpszEndLine == NULL
  190.             // ...or no newline after the carriage return
  191.             || *(lpszEndLine = _tcsinc(lpszEndLine)) != _T('\n'))
  192.         {
  193.             // Then this must be a binary file (or there was no trailing
  194.             //  "\r\n" at the end of the file).  In either case, bail and
  195.             //  write the rest of the file verbatim to the output; mark the
  196.             //  file as binary.
  197.             m_bBinary = TRUE;
  198.             pOutput->WriteBlock(lpszBeginLine, dwSize - (DWORD)(lpszBeginLine-lpszInput));
  199.             break;
  200.         }
  201.  
  202.         // Here, we successfully found a "\r\n", and lpszEndLine is
  203.         //  sitting at the '\n'.  So zap the line.
  204.         CString strLine(lpszBeginLine, lpszEndLine-lpszBeginLine-1);
  205.         ZapLine(strLine);
  206.         pOutput->WriteLine(strLine);
  207.         lpszBeginLine = _tcsinc(lpszEndLine);
  208.     }
  209.     AddToNewProjInf();
  210. }
  211.  
  212. // Here are the brains of the operation.  zrdGeneral contains the strings we
  213. //  search for, and what we replace them with.  ZapRawData is defined in
  214. //  zap.h.
  215. // The reason we have such a structure is that we can not simply "macroize"
  216. //  every occurrence of the project name in its files.  For example, if the
  217. //  project were named "View" or "while", and we blindly replaced all
  218. //  occurrences of the project name with macros, the generated custom AppWizard
  219. //  would be incapable of creating compilable projects.  Thus, we have to
  220. //  search for the project name occurring in special contexts.
  221. // In general, the format is:
  222. //      { Pre, RootType, Post, {Replacement #0, Replacement #1}},
  223. //  where Pre + RootType + Post is the string we search for, and Replacement #0
  224. //  is what we usually replace it with-- the exception is when we're naming
  225. //  one of the generated custom AppWizard's template files, in which case we use
  226. //  Replacement #1.  (Replacement #1 can be NULL if we know that the particular
  227. //  search string will never be replaced by the name of a template file in
  228. //  the generated custom AppWizard.)
  229. // See CZap::ZapLine and its references in CZap::ZapFile & CZap::ZapFileName,
  230. //  to see how zrdGeneral is used.
  231. static ZapRawData zrdGeneral[] =
  232. {
  233.     {_T(""), ZRD_ROOT, _T(".h"), {_T("$$root$$.h"), _T("root.h")}},
  234.     {_T(""), ZRD_ROOT, _T(".cpp"), {_T("$$root$$.cpp"), _T("root.cpp")}},
  235.     {_T(""), ZRD_ROOT, _T(".rc"), {_T("$$root$$.rc"), _T("root.rc")}},
  236.     {_T(""), ZRD_ROOT_UPR, _T(".RC"), {_T("$$ROOT$$.RC"), NULL}},
  237.     {_T(""), ZRD_ROOT, _T(".rc2"), {_T("$$root$$.rc2"), _T("root.rc2")}},
  238.     {_T(""), ZRD_ROOT_UPR, _T(".RC2"), {_T("$$ROOT$$.RC2"), NULL}},
  239.     {_T(""), ZRD_ROOT, _T(".ico"), {_T("$$root$$.ico"), _T("root.ico")}},
  240.     {_T(""), ZRD_ROOT, _T(".dll"), {_T("$$root$$.dll"), NULL}},
  241.     {_T(""), ZRD_ROOT_UPR, _T(".DLL"), {_T("$$ROOT$$.DLL"), NULL}},
  242.     {_T(""), ZRD_ROOT, _T(".exe"), {_T("$$root$$.exe"), NULL}},
  243.     {_T(""), ZRD_ROOT_UPR, _T(".EXE"), {_T("$$ROOT$$.EXE"), NULL}},
  244.     {_T(""), ZRD_ROOT, _T(".mak"), {_T("$$root$$.mak"), _T("root.mak")}},
  245.     {_T(""), ZRD_ROOT, _T(".hm"), {_T("$$root$$.hm"), _T("root.hm")}},
  246.     {_T(""), ZRD_ROOT_UPR, _T(".HM"), {_T("$$ROOT$$.HM"), NULL}},
  247.     {_T(""), ZRD_ROOT, _T(".hpj"), {_T("$$root$$.hpj"), _T("root.hpj")}},
  248.     {_T(""), ZRD_ROOT_UPR, _T(".HPJ"), {_T("$$ROOT$$.HPJ"), NULL}},
  249.     {_T(""), ZRD_ROOT, _T(".cnt"), {_T("$$root$$.cnt"), _T("root.cnt")}},
  250.     {_T(""), ZRD_ROOT, _T(".clw"), {_T("$$root$$.clw"), _T("root.clw")}},
  251.     {_T(""), ZRD_ROOT, _T(".reg"), {_T("$$root$$.reg"), _T("root.reg")}},
  252.     {_T(""), ZRD_ROOT, _T(".def"), {_T("$$root$$.def"), _T("root.def")}},
  253.     {_T(""), ZRD_ROOT, _T(".odl"), {_T("$$root$$.odl"), _T("root.odl")}},
  254.     {_T(""), ZRD_ROOT, _T(".tlb"), {_T("$$root$$.tlb"), _T("root.tlb")}},
  255.     {_T(""), ZRD_ROOT, _T(".HLP"), {_T("$$root$$.hlp"), _T("root.hlp")}},
  256.     {_T(""), ZRD_ROOT, _T(".LOG"), {_T("$$root$$.log"), _T("root.log")}},
  257.     {_T(""), ZRD_R_FILE, _T(".reg"), {_T("$$root$$Mac.reg"), _T("MacRoot.reg")}},
  258.     {_T(""), ZRD_R_FILE, _T(".r"), {_T("$$root$$Mac.r"), _T("root.r")}},
  259.     {_T(""), ZRD_ROOT, _T(".r"), {_T("$$root$$.r"), _T("root.r")}},
  260.     {_T(""), ZRD_ROOT, _T(".pch"), {_T("$$root$$.pch"), NULL}},
  261.     {_T(""), ZRD_ROOT, _T("DLL"), {_T("$$safe_root$$DLL"), NULL}},
  262.     {_T("library "), ZRD_CLASS, _T(""), {_T("library $$root$$"), NULL}},// (root.odl)
  263.     {_T("IID_I"), ZRD_DOC, _T(""), {_T("IID_I$$Doc$$"), NULL}},
  264.     {_T("IDD_"), ZRD_SAFE_ROOT, _T("_"), {_T("IDD_$$SAFE_ROOT$$_"), NULL}},
  265.     {_T("C"), ZRD_CLASS, _T("App"), {_T("C$$Safe_root$$App"), NULL}},
  266.     {_T("C"), ZRD_CLASS, _T("Doc"), {_T("C$$Safe_root$$Doc"), NULL}},
  267.     {_T("C"), ZRD_CLASS, _T("View"), {_T("C$$Safe_root$$View"), NULL}},
  268.     {_T("C"), ZRD_CLASS, _T("Set"), {_T("C$$Safe_root$$Set"), NULL}},
  269.     {_T("C"), ZRD_CLASS, _T("CntrItem"), {_T("C$$Safe_root$$CntrItem"), NULL}},
  270.     {_T("C"), ZRD_CLASS, _T("SrvrItem"), {_T("C$$Safe_root$$SrvrItem"), NULL}},
  271.     {_T("C"), ZRD_CLASS, _T("Dlg"), {_T("C$$Safe_root$$Dlg"), NULL}},
  272.     {_T(""), ZRD_FILEBASE, _T("Doc."), {_T("$$root$$Doc."), _T("Doc.")}},
  273.     {_T(""), ZRD_FILEBASE, _T("View."), {_T("$$root$$View."), _T("View.")}},
  274.     {_T(""), ZRD_FILEBASE, _T("Set."), {_T("$$root$$Set."), _T("RecSet.")}},
  275.     {_T(""), ZRD_FILEBASE, _T("Dlg."), {_T("$$root$$Dlg."), _T("Dialog.")}},
  276.     {_T("m_"), ZRD_ROOT, _T("Set"), {_T("m_$$safe_root$$Set"), NULL}},
  277.     {_T("IDR_"), ZRD_DOC_UPR, _T("TYPE"), {_T("IDR_$$DOC$$TYPE"), NULL}},
  278.     {_T("dispinterface I"), ZRD_DOC, _T(""), {_T("dispinterface I$$Doc$$"), NULL}},
  279.     {_T("\\n"), ZRD_DOC, _T("\\n"), {_T("\\n$$Doc$$\\n"), NULL}},
  280.     {_T("\""), ZRD_ROOT, _T("\""), {_T("\"$$root$$\""), NULL}},
  281.     {_T("\""), ZRD_CLASS, _T("\""), {_T("\"$$Root$$\""), NULL}},
  282.     {_T("= "), ZRD_ROOT, _T(""), {_T("= $$Root$$"), NULL}},
  283.     {_T("= "), ZRD_DOC, _T(""), {_T("= $$Doc$$"), NULL}},
  284.     {_T("\""), ZRD_ROOT_UPR, _T(" MFC Extension DLL"), {_T("\"$$ROOT$$ MFC Extension DLL"), NULL}},
  285.     {_T("\""), ZRD_ROOT_UPR, _T(" MFC Application"), {_T("\"$$ROOT$$ MFC Application"), NULL}},
  286.     {_T("\""), ZRD_ROOT_UPR, _T("\\0\""), {_T("\"$$ROOT$$\\0\""), NULL}},
  287.     {_T("\""), ZRD_ROOT_UPR, _T(" Dynamic Link Library"), {_T("\"$$ROOT$$ Dynamic Link Library"), NULL}},
  288.     {_T(""), ZRD_ROOT, _T(" application"), {_T("$$root$$ application"), NULL}},
  289.     {_T(""), ZRD_ROOT, _T(" Application"), {_T("$$root$$ Application"), NULL}},
  290.     {_T(""), ZRD_CLASS, _T(".Application"), {_T("$$Safe_root$$.Application"), NULL}},
  291.     {_T("coclass "), ZRD_CLASS, _T(""), {_T("coclass $$Safe_root$$"), NULL}},
  292.     {_T(""), ZRD_ROOT_UPR, _T(" application"), {_T("$$ROOT$$ application"), NULL}},
  293.     {_T(""), ZRD_ROOT_UPR, _T(" Application"), {_T("$$ROOT$$ Application"), NULL}},
  294.     {_T(""), ZRD_ROOT_UPR, _T(" DLL"), {_T("$$ROOT$$ DLL"), NULL}},
  295.     {_T("\""), ZRD_ROOT, _T(" Version 1.0"), {_T("\"$$Root$$ Version 1.0"), NULL}},
  296.     {_T("\"&About "), ZRD_ROOT, _T("..."), {_T("\"&About $$Root$$..."), NULL}},
  297.     {_T("\"About "), ZRD_ROOT, _T("\""), {_T("\"About $$Root$$\""), NULL}},
  298.     {_T("Make help for Project "), ZRD_ROOT_UPR, _T(""), {_T("Make help for Project $$ROOT$$"), NULL}},
  299.     {_T("// "), ZRD_ROOT, _T(" bundle resource ID"), {_T("// $$root$$ bundle resource ID"), NULL}},
  300.     {_T("// "), ZRD_ROOT, _T(" document"), {_T("// $$root$$ document"), NULL}},
  301.     {_T("// "), ZRD_ROOT, _T(" signature"), {_T("// $$root$$ signature"), NULL}},
  302.     {_T(""), ZRD_DOC, _T(" Document"), {_T("$$Doc$$ Document"), NULL}},
  303.     {_T("MICROSOFT FOUNDATION CLASS LIBRARY : "), ZRD_ROOT, _T(""),
  304.         {_T("MICROSOFT FOUNDATION CLASS LIBRARY : $$root$$"), NULL}},
  305.     {_T(""), ZRD_CLASS, _T(".Document"), {_T("$$Doc$$.Document"), NULL}},
  306.     {_T("\\n"), ZRD_MAC_TYPE, _T(" Files\""), {_T("\\n $$MAC_TYPE$$ Files\""), NULL}},
  307.     {_T("'"), ZRD_MAC_TYPE, _T("'"), {_T("'$$MAC_TYPE$$'"), NULL}},
  308.     {_T("\\n"), ZRD_MAC_TYPE, _T("\\n"), {_T("\\n$$MAC_TYPE$$\\n"), NULL}},
  309. };
  310.  
  311. // Called when the zap dialog is dismissed.  It initializes the matches
  312. //  array (m_pStrMatches) for the particular project's root name.
  313. void CZap::SetRoot(LPCTSTR lpszDir, LPCTSTR lpszRoot)
  314. {
  315.     m_strRoot = lpszRoot;
  316.  
  317.     m_strRootDir = lpszDir;
  318.     m_strRootDir.MakeLower();
  319.  
  320.     m_strGeneratedNewProjInfo.Empty();
  321.     m_posTplName = NULL;
  322.  
  323.     InitMatches();
  324. }
  325.  
  326. // Changes each space in str to an underscore
  327. void SpaceToUnderscore(CString& str)
  328. {
  329.     LPCTSTR pch = str;
  330.     for (int i=0; *pch != _T('\0'); i += _tclen(pch), pch = _tcsinc(pch))
  331.     {
  332.         if (str[i] == _T(' '))
  333.             str.SetAt(i, _T('_'));
  334.     }
  335. }
  336.  
  337. void MakeSafeRoot(CString& tag, LPCTSTR szRoot)
  338. {
  339.     tag.Empty();
  340.  
  341.     const TCHAR* pch = szRoot;
  342.     for( ; *pch != '\0'; pch = _tcsinc(pch))
  343.     {
  344.         if(_istalnum(*pch)  // Strip characters that cannot be in class names
  345.            || *pch == '_')  // valid chars are 'A'-'Z', 'a'-'z', '0'-'9', '_'
  346.         {
  347.             tag += *pch;
  348.         }
  349.     }
  350.     if(tag.IsEmpty())       // An empty tag would produce: CApp, CDoc, and CView
  351.         tag = "My";         // CView would become CMyView, so just make tag="My"
  352.  
  353.     if (_istdigit(tag[0]))  // Can't begin with number
  354.         tag = "My" + tag;
  355.  
  356.     tag.SetAt(0, (TCHAR)_totupper(tag[0]));     // make 1st character upper
  357.  
  358.     if (!tag.Compare(_T("Custom")))         // rare, probably tester only, case
  359.         tag = "My" + tag;
  360.  
  361.     // Limit length of tag so generated class names don't exceed _MAX_SYMBOL
  362.     #define MAX_ADDED_TO_TAG 10
  363.     #define _MAX_SYMBOL 64
  364.     if (tag.GetLength() + MAX_ADDED_TO_TAG > _MAX_SYMBOL)
  365.         tag = tag.Left(_MAX_SYMBOL - MAX_ADDED_TO_TAG);
  366. }
  367.  
  368. // This fills the array m_pStrMatches with an entry for each search string
  369. //  from zrdGeneral.  Each entry is the concatenation of the three components
  370. //  of the search string (i.e., Pre, RootType, and Post).
  371. // Example (loosely expressed):
  372. //  m_pStrMatches[0] = "" + ZRD_ROOT + ".h"
  373. //  m_pStrMatches[1] = "" + ZRD_ROOT_UPR ".H"
  374. //  etc.
  375. void CZap::InitMatches()
  376. {
  377.     // First, translate ZRD_ROOT, ZRD_ROOT_UPR, etc. into strings based
  378.     //  on the name of the "zappee" (i.e., project off of which we're
  379.     //  basing the custom AppWizard).
  380.  
  381.     CString strRootTypes[NUM_ROOT_TYPES];
  382.     strRootTypes[ZRD_ROOT] = m_strRoot;
  383.  
  384.     strRootTypes[ZRD_ROOT_UPR] = strRootTypes[ZRD_ROOT];
  385.     strRootTypes[ZRD_ROOT_UPR].MakeUpper();
  386.  
  387.     CString strSafeRoot;
  388.     MakeSafeRoot(strSafeRoot, m_strRoot);
  389.     strRootTypes[ZRD_SAFE_ROOT] = strSafeRoot;
  390.     strRootTypes[ZRD_SAFE_ROOT].MakeUpper();
  391.  
  392.     strRootTypes[ZRD_CLASS] = m_strRoot;
  393.     strRootTypes[ZRD_CLASS].SetAt(0, (TCHAR)_totupper(strRootTypes[ZRD_CLASS][0]));
  394.  
  395.     strRootTypes[ZRD_FILEBASE] = m_strRoot;
  396.  
  397.     strRootTypes[ZRD_DOC] = m_strRoot.Left(6);
  398.     strRootTypes[ZRD_DOC].SetAt(0, (TCHAR)_totupper(strRootTypes[ZRD_DOC][0]));
  399.  
  400.     strRootTypes[ZRD_DOC_UPR] = strRootTypes[ZRD_DOC];
  401.     strRootTypes[ZRD_DOC_UPR].MakeUpper();
  402.  
  403.     strRootTypes[ZRD_MAC_TYPE] = m_strRoot.Left(4);
  404.     int nLen = strRootTypes[ZRD_MAC_TYPE].GetLength();
  405.     if (nLen < 4)
  406.     {
  407.         CString strPad(_T(' '), 4 - nLen);
  408.         strRootTypes[ZRD_MAC_TYPE] += strPad;
  409.     }
  410.     strRootTypes[ZRD_MAC_TYPE].MakeUpper();
  411.  
  412.     strRootTypes[ZRD_R_FILE] = m_strRoot + _T("Mac");
  413.  
  414.     strRootTypes[ZRD_R_FILE_UPR] = strRootTypes[ZRD_R_FILE];
  415.     strRootTypes[ZRD_R_FILE_UPR].MakeUpper();
  416.  
  417.     // Now, using these values, traverse zrdGeneral and concatenate the three
  418.     //  components of each search string.  Store the value in the
  419.     //  corresponding entry of the array m_pStrMatches.
  420.  
  421.     FreeMatches();
  422.     int nSize = sizeof(zrdGeneral)/sizeof(ZapRawData);
  423.     m_pStrMatches = new CString[nSize];
  424.  
  425.     for (int i=0; i < nSize; i++)
  426.     {
  427.         m_pStrMatches[i] =
  428.             zrdGeneral[i].lpszPre +
  429.             strRootTypes[zrdGeneral[i].nRootType] +
  430.             zrdGeneral[i].lpszPost;
  431.     }
  432. }
  433.  
  434. void CZap::FreeMatches()
  435. {
  436.     if (m_pStrMatches != NULL)
  437.         delete [sizeof(zrdGeneral)/sizeof(ZapRawData)] m_pStrMatches;
  438.     m_pStrMatches = NULL;
  439. }
  440.  
  441. CZap::~CZap()
  442. {
  443.     ASSERT(m_posTplName == NULL);
  444.     FreeMatches();
  445. }
  446.  
  447.  
  448. void CZap::ZapLine(CString& strLine, int iReplace /* = 0 */)
  449. {
  450.     ASSERT(m_pStrMatches != NULL);
  451.     ASSERT(0 <= iReplace && iReplace <= 1);
  452.  
  453.     for (int i=0; i < sizeof(zrdGeneral)/sizeof(ZapRawData); i++)
  454.     {
  455.         int nStart = strLine.Find(m_pStrMatches[i]);
  456.         if (nStart != -1)
  457.         {
  458.             if (zrdGeneral[i].lpszReplace[iReplace] != NULL)
  459.             {
  460.                 strLine = strLine.Left(nStart)              // Region to left of match
  461.                     + zrdGeneral[i].lpszReplace[iReplace]   // String to replace match with
  462.                     + (((LPCTSTR) strLine) + nStart + m_pStrMatches[i].GetLength());
  463.                         // String to right of match
  464.                 i--;                // In case there are more occurrences of this match
  465.             }
  466.         }
  467.     }
  468. }
  469.  
  470. void CZap::ZapFileName(LPCTSTR lpszFileName, CString& rStrZappedFile, int iReplace /* = 0 */)
  471. {
  472.     rStrZappedFile = lpszFileName;
  473.     ZapLine(rStrZappedFile, iReplace);
  474. }
  475.