/* * @doc INTERNAL * * @module RTFLOG.CPP - RichEdit RTF log * * Contains the code for the RTFLog class which can be used * to log the number of times RTF tags are read by the RTF reader * for use in coverage testing * * Authors: * Created for RichEdit 2.0: Brad Olenick * * Copyright (c) 1995-1996, Microsoft Corporation. All rights reserved. */ #include "_common.h" #include "_rtflog.h" #include "tokens.h" extern INT cKeywords; extern const KEYWORD rgKeyword[]; /* * CRTFLog::CRTFLog() * * @mfunc * Constructor - * 1. Opens a file mapping to log hit counts, creating * the backing file if neccessary * 2. Map a view of the file mapping into memory * 3. Register a windows message for change notifications * */ CRTFLog::CRTFLog() : _rgdwHits(NULL), _hfm(NULL), _hfile(NULL) { #ifndef PEGASUS const char cstrMappingName[] = "RTFLOG"; const char cstrWM[] = "RTFLOGWM"; const int cbMappingSize = sizeof(ELEMENT) * ISize(); BOOL fNewFile = FALSE; // check for existing file mapping if(!(_hfm = OpenFileMappingA(FILE_MAP_ALL_ACCESS, TRUE, cstrMappingName))) { // no existing file mapping // get the file with which to create the file mapping // first, attempt to open an existing file if(!(_hfile = CreateFileA(LpcstrLogFilename(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL))) { // no existing file, attempt to create new if(!(_hfile = CreateFileA(LpcstrLogFilename(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL))) { return; } fNewFile = TRUE; } if(!(_hfm = CreateFileMappingA(_hfile, NULL, PAGE_READWRITE, 0, cbMappingSize, cstrMappingName))) { return; } } LPVOID lpv; if(!(lpv = MapViewOfFile(_hfm, FILE_MAP_ALL_ACCESS, 0, 0, cbMappingSize))) { return; } // register windows message for change notifications SideAssert(_uMsg = RegisterWindowMessageA(cstrWM)); // memory-mapped file is now mapped to _rgdwHits _rgdwHits = (PELEMENT)lpv; // zero the memory-mapped file if we created it new // (Win95 gives us a new file w/ garbage in it for some reason) if(fNewFile) { Reset(); } #endif } /* * CRTFLog::Reset() * * @mfunc * Resets the hitcount of each element in the log to 0 * */ void CRTFLog::Reset() { if(!FInit()) { return; } for(INDEX i = 0; i < ISize(); i++) { (*this)[i] = 0; } // notify clients of change ChangeNotifyAll(); } /* * CRTFLog::UGetWindowMsg * * @mdesc * Returns the window message id used for change notifications * * @rdesc * UINT window message id * * @devnote * This should be inline, but the AssertSz macro doesn't compile * properly on the Mac if its placed in a header file * */ UINT CRTFLog::UGetWindowMsg() const { AssertSz(FInit(), "CRTFLog::UGetWindowMsg(): CRTFLog not initialized properly"); return _uMsg; } /* * CRTFLog::operator[] * * @mdesc * Returns reference to element i of RTF log (l-value) * * @rdesc * ELEMENT & reference to element i of log * * @devnote * This should be inline, but the AssertSz macro doesn't compile * properly on the Mac if its placed in a header file * */ CRTFLog::ELEMENT &CRTFLog::operator[](INDEX i) { AssertSz(i < ISize(), "CRTFLog::operator[]: index out of range"); AssertSz(FInit(), "CRTFLog::operator[]: CRTFLog not initialized properly"); return _rgdwHits[i]; } /* * CRTFLog::operator[] * * @mdesc * Returns reference to element i of RTF log (r-value) * * @rdesc * const ELEMENT & reference to element i of log * * @devnote * This should be inline, but the AssertSz macro doesn't compile * properly on the Mac if its placed in a header file * */ const CRTFLog::ELEMENT &CRTFLog::operator[](INDEX i) const { AssertSz(i < ISize(), "CRTFLog::operator[]: index out of range"); AssertSz(FInit(), "CRTFLog::operator[]: CRTFLog not initialized properly"); return _rgdwHits[i]; } /* * CRTFLog::LpcstrLogFilename() * * @mfunc * Returns name of file to be used for log * * @rdesc * LPCSTR pointer to static buffer containing file name */ LPCSTR CRTFLog::LpcstrLogFilename() const { const char cstrLogFilename[] = "RTFLOG"; static char szBuf[MAX_PATH] = ""; #ifndef PEGASUS if(!szBuf[0]) { DWORD cchLength; char szBuf2[MAX_PATH]; SideAssert(cchLength = GetTempPathA(MAX_PATH, szBuf2)); // append trailing backslash if neccessary if(szBuf2[cchLength - 1] != '\\') { szBuf2[cchLength] = '\\'; szBuf2[cchLength + 1] = 0; } wsprintfA(szBuf, "%s%s", szBuf2, cstrLogFilename); } #endif return szBuf; } /* * CRTFLog::IIndexOfKeyword(LPCSTR lpcstrKeyword, PINDEX piIndex) * * @mfunc * Returns the index of the log element which corresponds to * the RTF keyword, lpcstrKeyword * * @rdesc * BOOL flag indicating whether index was found */ BOOL CRTFLog::IIndexOfKeyword(LPCSTR lpcstrKeyword, PINDEX piIndex) const { INDEX i; for(i = 0; i < ISize(); i++) { if(strcmp(lpcstrKeyword, rgKeyword[i].szKeyword) == 0) { break; } } if(i == ISize()) { return FALSE; } if(piIndex) { *piIndex = i; } return TRUE; } /* * CRTFLog::IIndexOfToken(TOKEN token, PINDEX piIndex) * * @mfunc * Returns the index of the log element which corresponds to * the RTF token, token * * @rdesc * BOOL flag indicating whether index was found */ BOOL CRTFLog::IIndexOfToken(TOKEN token, PINDEX piIndex) const { INDEX i; for(i = 0; i < ISize(); i++) { if(token == rgKeyword[i].token) { break; } } if(i == ISize()) { return FALSE; } if(piIndex) { *piIndex = i; } return TRUE; }