/****************************************************************************** Source File: Model Data.CPP Implementation of the code for handling GPC format data Copyright (c) 1997 by Microsoft Corporation. All Rights Resreved. A Pretty Penny Enterprises Production Change History: 02-19-97 Bob_Kjelgaard@Prodgy.Net Created it ******************************************************************************/ #include "StdAfx.h" #include "ProjNode.H" #include "CodePage.H" #include "Resource.H" #include "GPDFile.H" #include "utility.H" #include "minidev.h" /****************************************************************************** COldMiniDriverData class This class is tasked with representing the GPC data. It will begin life as a stub, although it could become more functional, later. ******************************************************************************/ /****************************************************************************** ExtractList This is a private worker function. It takes a pointer to a null-terminated list of WORD font IDs, with the nasty complication that the first two elements of the list represent the endpoints of a range. It mashes these into a passed word map (of which we only use the indices). ******************************************************************************/ static void ExtractList(PWORD pw, CMapWordToDWord& cmw2d) { for (WORD w = *pw++; w && w < *pw; w++) cmw2d[w] = 0; if (!w) return; // The whole list was empty while (*pw) // We start at the endpoint (which we haven't mapped yet) cmw2d[*pw++] = 0; } COldMiniDriverData::~COldMiniDriverData() { // The m_csoaFonts array has some duplicate entries in it because of GPC // entries that reference multiple printer models. We must zap those // duplicate entries so the data won't be deleted twice in the CSafeObArray // destructor. That would cause an AV. for (unsigned u = 0 ; u < m_csoaFonts.GetSize() ; u++) { if (GetSplitCode(u) != NoSplit) m_csoaFonts.SetAt(u, NULL) ; } ; } /****************************************************************************** ColdMiniDriverData::Load This member function loads the mini-driver's GPC file, and extracts the number of models, the CTT IDs, and the model name IDs. ******************************************************************************/ BOOL COldMiniDriverData::Load(CFile& cfImage) { struct sGPCHeaderEntry { WORD m_wOffset, m_wcbItem, m_wcItems; }; struct sMaster { WORD m_wX, m_wY; }; struct sPrinterModelData { WORD m_wcbSize; WORD m_widName; // Stringtable id for model name. WORD m_wfGeneral; // TODO: Define enums WORD m_wfCurves; // TODO: Define enums WORD m_wfLines; // TODO: Define enums WORD m_wfPolygons; // TODO: Define enums WORD m_wfText; // TODO: Define enums WORD m_wfClipping; // TODO: Define enums WORD m_wfRaster;; // TODO: Define enums WORD m_wfLandscapeText; // TODO: Define enums WORD m_wLeftMargin; // Left-hand unprintable area WORD m_wMaximumWidth; // Of physica page sMaster m_smMaximum, m_smMinimum; // Max min page sizes WORD m_widDefaultFont; WORD m_wLookAhead; WORD m_wMaxFontsPerPage; WORD m_wcCartridges; WORD m_widDefaultCTT; enum {PortraitFonts, LandscapeFonts, Resolution, PaperSize, PaperQuality, PaperSource, PaperDestination, TextQuality, Compression, FontCartridge, Color, MemoryConfiguration}; WORD m_awofIndexLists[12]; // Uses the preceding enum WORD m_awIndices[16]; // Ditto WORD m_awVer3IndexLists[5]; // Ditto WORD m_wofDefaults; // List of defaults for index lists WORD m_wReserved; DWORD m_dwidICMManufactirer, m_dwidICMModel; DWORD m_adwReserved[8]; }; struct sGPCFileHeader { WORD m_widGPC; // 0x7F00 or it isn't valid. WORD m_wVersion; // Final version is 3, there was a V2 sMaster m_smMasterdpi; DWORD m_dwoHeap; // The GPC data is maintained in one DWORD m_dwcbFile; // Total GPC Image size, heap and all enum {Default, PCL4, CAPSL, PPDS, TTY, DBCS}; WORD m_wTechnology; // Use the preceding enum enum {PrivateHelp = 1, OneDraftFont}; WORD m_wfGeneral; // Again, use the preceding enum char m_acReserved[10]; WORD m_wcHeaderItems; // Number of valid header entries enum {ModelData, Resolution, PaperSize, PaperQuality, PaperSource, PaperDestination, TextQuality, Compression, FontCartridge, PageControl, CursorMovement, FontSimulation, DeviceColor, RectangleFill, DownloadInfo, VectorPage, Carousel, PenInfo, LineInfo, BrushInfo, VectorOutput, PolyVectorOutput, VectorSupport, ImageControl, PrintDensity, ColorTracking, MaximumDefined = 30}; sGPCHeaderEntry m_asgpche[MaximumDefined]; }; struct sFontCartridge { WORD m_wSize; // = 12 WORD m_widCartridge; // In the string table WORD m_wofPortraitList; WORD m_wofLandscapeList; WORD m_wfGeneral; WORD m_wReserved; }; // In case we get called more than once, dump any old info... m_cbaImage.RemoveAll(); m_csoaFonts.RemoveAll(); m_cwaidCTT.RemoveAll(); m_cwaidModel.RemoveAll(); m_cbaImage.SetSize(cfImage.GetLength()); cfImage.Read(m_cbaImage.GetData(), cfImage.GetLength()); sGPCFileHeader *psgfh = (sGPCFileHeader *) Image(); if (psgfh -> m_widGPC != 0x7F00 || psgfh -> m_wVersion > 0x3ff) return FALSE; // Suck out the printer model data we care about- eventually, this may // be all of it for (unsigned u = 0; u < psgfh -> m_asgpche[sGPCFileHeader::ModelData].m_wcItems; u++) { sPrinterModelData& spmd = *(sPrinterModelData *) (Image() + psgfh -> m_asgpche[sGPCFileHeader::ModelData].m_wOffset + psgfh -> m_asgpche[sGPCFileHeader::ModelData].m_wcbItem * u); m_cwaidModel.Add(spmd.m_widName); m_cwaidCTT.Add(spmd.m_widDefaultCTT); // Build the font list- I use a CMapWordToOb to handle the duplicate // screening CMapWordToDWord& cmw2dThis = * (new CMapWordToDWord); // Extract the portrait resident fonts if (spmd.m_awofIndexLists[sPrinterModelData::PortraitFonts]) ExtractList((PWORD) (Image() + psgfh -> m_dwoHeap + spmd.m_awofIndexLists[sPrinterModelData::PortraitFonts]), cmw2dThis); // Extract the landscape resident fonts if (spmd.m_awofIndexLists[sPrinterModelData::LandscapeFonts]) ExtractList((PWORD) (Image() + psgfh -> m_dwoHeap + spmd.m_awofIndexLists[sPrinterModelData::LandscapeFonts]), cmw2dThis); // Extract the cartridge fonts if (spmd.m_awofIndexLists[sPrinterModelData::FontCartridge]) { PWORD pw = (PWORD) (Image() + psgfh -> m_dwoHeap + spmd.m_awofIndexLists[sPrinterModelData::FontCartridge]); // RAID 102890- Cartridge font index is 1-based, not 0-based while (*pw) { sFontCartridge* psfc = (sFontCartridge *) (Image() + psgfh -> m_asgpche[sGPCFileHeader::FontCartridge].m_wOffset + psgfh -> m_asgpche[sGPCFileHeader::FontCartridge].m_wcbItem * (-1 + *pw++)); // END RAID 102890 // Portrait if (psfc -> m_wofPortraitList) ExtractList((PWORD) (Image() + psgfh -> m_dwoHeap + psfc -> m_wofPortraitList), cmw2dThis); // Landscape if (psfc -> m_wofLandscapeList) ExtractList((PWORD) (Image() + psgfh -> m_dwoHeap + psfc -> m_wofLandscapeList), cmw2dThis); } } // Save the map in the font structure m_csoaFonts.Add(&cmw2dThis); } return TRUE; } /****************************************************************************** COldMiniDriverData::SplitMultiGPCs The Load() function has loaded information about each GPC entry into this class' member variables. The problem is that there are some GPC entries that are used to manage multiple models. This routine is used to "split" the data for these entries into single model "sections". Actually, what happens is that new member variables entries are allocated for each model and the GPC entry's data is copied into them. Next, a flag is set to mark this copy. ******************************************************************************/ bool COldMiniDriverData::SplitMultiGPCs(CStringTable& cstdriversstrings) { // Make sure the data arrays are the same size. ASSERT(m_cwaidModel.GetSize() == m_cwaidCTT.GetSize()) ; ASSERT(m_cwaidModel.GetSize() == (int) m_csoaFonts.GetSize()) ; // Size the split codes array and split models names array to the current // number of GPC entries. m_cuaSplitCodes.SetSize(m_cwaidModel.GetSize()) ; m_csaSplitNames.SetSize(m_cwaidModel.GetSize()) ; // Declare the variables needed for the processing in the following loops. unsigned u, u2 ; // Looping/indexing variables int nloc ; // Location of "%" in model name CString csentryname ; int nlen ; // Length of csentryname/csmodelname // Loop through each GPC entry... for (u = 0 ; u < ModelCount(); u++) { // If the GPC entry's model name contains no percent signs, the entry // only references one model. Note this and continue. csentryname = cstdriversstrings[ModelName(u)] ; if ((nloc = csentryname.Find(_T('%'))) == -1) { SetSplitCode(u, NoSplit) ; continue ; } ; // The entry references multiple models. Mark the entry as the first // one and save its correct single model name. SetSplitCode(u, FirstSplit) ; m_csaSplitNames[u] = csentryname.Left(nloc) ; // Copy the entry's data into new elements of the data arrays. One // new set of data elements are allocated for each additional model // referenced by the entry. nlen = csentryname.GetLength() ; for (u2 = u + 1 ; nloc != -1 ; u2++, u++) { m_cwaidModel.InsertAt(u2, m_cwaidModel[u]) ; m_cwaidCTT.InsertAt(u2, m_cwaidCTT[u]) ; m_csoaFonts.InsertAt(u2, m_csoaFonts[u]) ; InsertSplitCode(u2, OtherSplit) ; // Look for the next percent sign in the entry's name. (Make sure // we don't reference passed the end of the string while doing // this.) if (nloc + 2 < nlen) { csentryname = csentryname.Mid(nloc + 1) ; nlen = csentryname.GetLength() ; nloc = csentryname.Find(_T('%')) ; } else break ; // Save the model name for the new entry. if (nloc == -1) m_csaSplitNames.InsertAt(u2, csentryname) ; else m_csaSplitNames[u] = csentryname.Left(nloc) ; } ; } ; // All went well so... return true ; } /****************************************************************************** COldMiniDriverData::FontMap(unsigned u) This member returns the map which shows which fonts are used by the given model. ******************************************************************************/ CMapWordToDWord& COldMiniDriverData::FontMap(unsigned u) const { return *(CMapWordToDWord *) m_csoaFonts[u]; } /****************************************************************************** COldMiniDriverData::NoteTranslation This records the fact that model nn must translate instances of font ID xxx to font ID y. ******************************************************************************/ void COldMiniDriverData::NoteTranslation(unsigned uModel, unsigned uidOld, unsigned uidNew) { FontMap(uModel)[(WORD)uidOld] = uidNew; } /****************************************************************************** CModelData class This class encapsulates the GPD file. It will start life as a big CStringArray, but as the editor gets more sophisticated, it may gain additional members to speed processing and/or manipulation of the data. ******************************************************************************/ IMPLEMENT_SERIAL(CModelData, CProjectNode, 0) /****************************************************************************** CModelData::FillViewer This static member function is a callback for the rich edit control. It receives a pointer to the CModelData in question, and calls its Fill from buffer member function. Args: DWORD dwthis Pointer to the CModelData in question LPBYTE lpb Pointer to the buffer to fill LONG lcb Number of bytes to read LONG *plcb Number of bytes actually read is saved here Returns: TRUE (failure) if class instance pointer is NULL. Otherwise, whatever Fill() returns. ******************************************************************************/ DWORD CALLBACK CModelData::FillViewer(DWORD_PTR dwthis, LPBYTE lpb, LONG lcb, LONG *plcb) { if (!dwthis) return TRUE; CModelData* pcmd = (CModelData *) dwthis; return pcmd -> Fill(lpb, lcb, plcb); } /****************************************************************************** CModelData::FromViewer This is a stream callback for moving data from the edit control to the GPD class. It receives a pointer to the CModelData being updated, and calls its UpdateFrom buffer member function to do the rest of the work ******************************************************************************/ DWORD CALLBACK CModelData::FromViewer(DWORD_PTR dwthis, LPBYTE lpb, LONG lcb, LONG *plcb) { if (!dwthis) return TRUE; // Stop the madness CModelData* pcmd = (CModelData *) dwthis; return pcmd -> UpdateFrom(lpb, lcb, plcb); } /****************************************************************************** CModelData::Fill(LPBYTE lpb, LONG lcb, LONG *plcb) This private method fills a buffer from the GPD contents in CString form. An internal buffer is used to handle partially moved strings. ******************************************************************************/ DWORD CModelData::Fill(LPBYTE lpb, LONG lcb, LONG *plcb) { int iTotalLines = (int)m_csaGPD.GetSize(); // Get the # of lines in the GPD // If the temp buffer is empty and the next line to read is greater than // the number of lines in the GPD, the REC has been loaded. We're done. if (!m_cbaBuffer.GetSize() && m_iLine >= iTotalLines) { *plcb = 0; return 0; } unsigned ucb = (unsigned) lcb; // Number of bytes still wanted union { LPTSTR lpstr; LPBYTE lpbThis; }; // First, empty anything buffered previously lpbThis = lpb; // If there is data left over from a line partially loaded into the REC // before.. if (m_cbaBuffer.GetSize()) // ...If the partial line will fit into the REC buffer, copy it // into the buffer, update variables to indicate this, and continue. if ((unsigned) m_cbaBuffer.GetSize() <= ucb) { memcpy(lpbThis, m_cbaBuffer.GetData(), (size_t)m_cbaBuffer.GetSize()); ucb -= (unsigned)m_cbaBuffer.GetSize(); lpbThis += m_cbaBuffer.GetSize(); m_cbaBuffer.RemoveAll(); // ...If the partial line won't fit in the REC buffer, copy the // portion of it that will fit into the REC buffer, remove those bytes // from the line buffer, and return because nothing more can be loaded. } else { memcpy(lpbThis, m_cbaBuffer.GetData(), ucb); m_cbaBuffer.RemoveAt(0, ucb); *plcb = lcb; return 0; } // Line by line, copy as much data as possible into the REC's buffer. for (; ucb && m_iLine < iTotalLines; m_iLine++) { // Get the next GPD line and add CR LF to it. CString csLine = m_csaGPD[m_iLine]; csLine += _TEXT("\r\n"); // If the entire line will fit into the REC's buffer, copy it in. Then // update all pointers, counters, etc and then check the next line. if ((csLine.GetLength()) * sizeof(TCHAR) <= ucb) { memcpy(lpbThis, (LPCTSTR) csLine, sizeof(TCHAR) * csLine.GetLength()); ucb -= sizeof(TCHAR) * csLine.GetLength(); lpstr += csLine.GetLength(); continue; } // If this point is reached, the current line will not fit in the REC's // buffer so first copy the line into the temp buffer. Then copy the // portion of the line that will fit into the REC's buffer. Last, // update the buffers, pointers, and counters. m_cbaBuffer.SetSize(sizeof(TCHAR) * csLine.GetLength()); memcpy(m_cbaBuffer.GetData(), (LPCTSTR) csLine, sizeof(TCHAR) * csLine.GetLength()); memcpy(lpbThis, m_cbaBuffer.GetData(), ucb); m_cbaBuffer.RemoveAt(0, ucb); ucb = 0; } // Save the number of bytes load and return 0 to indicate success. *plcb = lcb - ucb; return 0; } /****************************************************************************** CModelData::UpdateFrom(LPBYTE lpb, LONG lcb, LONG* plcb) This is a private member- an overload which adds the contents of the given buffer to the GPD CStringArray, by parsing it into strings. A private buffer member is used to hold partial strings between calls. ******************************************************************************/ DWORD CModelData::UpdateFrom(LPBYTE lpb, LONG lcb, LONG* plcb) { // Copy the buffer to a byte buffer and null-terminate m_cbaBuffer.SetSize(1 + lcb); memcpy(m_cbaBuffer.GetData(), lpb, lcb); m_cbaBuffer.SetAt(-1 + m_cbaBuffer.GetSize(), 0); // Convert to string and append to any buffered data. CString csWork(m_cbaBuffer.GetData()); CString csEnd(_T("\r\x1A")); // These get dumped m_cbaBuffer.RemoveAll(); m_csBuffer += csWork; // Add any complete strings to the GPD contents. csWork = m_csBuffer.SpanExcluding(_T("\n")); while (csWork.GetLength() != m_csBuffer.GetLength()) { m_csBuffer = m_csBuffer.Mid(csWork.GetLength() + 1); // Remove any trailing whitespace. csWork.TrimRight(); // Add the string sans any leading control characters m_csaGPD.Add(csWork.Mid(csWork.SpanIncluding(csEnd).GetLength())); // While we're here, remove any leading control characters from buffer m_csBuffer = m_csBuffer.Mid(m_csBuffer.SpanIncluding(csEnd).GetLength()); csWork = m_csBuffer.SpanExcluding(_T("\n")); } // The leftover data (if any) may be used later... *plcb = lcb; return 0; } /****************************************************************************** CModelData::Classify This method identifies the line numbers for each warning comment, error comment, and any other sort of comment, so they can later be syntax colored. ******************************************************************************/ /****************************************************************************** CModelData::CModelData Constructs an empty CModelData object- includes building the Menu table ******************************************************************************/ CModelData::CModelData() { m_pcmdt = NULL; m_cfn.SetExtension(_T(".GPD")); m_cfn.AllowPathEdit(); // Build the context menu control m_cwaMenuID.Add(ID_OpenItem); m_cwaMenuID.Add(ID_CopyItem); m_cwaMenuID.Add(ID_RenameItem); m_cwaMenuID.Add(ID_DeleteItem); m_cwaMenuID.Add(0); m_cwaMenuID.Add(ID_ExpandBranch); m_cwaMenuID.Add(ID_CollapseBranch); // Initialize the variables needed for workspace completeness and tidiness // checking. m_bTCUpdateNeeded = false ; m_pnUFMRCIDs = m_pnStringRCIDs = NULL ; m_nNumUFMsInGPD = m_nNumStringsInGPD = 0 ; m_pvRawData = NULL ; } /****************************************************************************** CModelData::~CModelData() Free, unload, and delete the data used for completeness and tidiness checks. ******************************************************************************/ extern "C" void UnloadRawBinaryData(PVOID pRawData) ; CModelData::~CModelData() { // If the GPD has been parsed... if (m_pvRawData) { // Free the parsed data UnloadRawBinaryData(m_pvRawData) ; // Delete the parsed data file try { CString cs ; cs = FilePath() + FileTitle() + _T(".BUD") ; DeleteFile(cs) ; } catch (CException *pce) { pce->ReportError(); pce->Delete(); } // Delete each of the resource lists that exist if (m_pnUFMRCIDs) delete m_pnUFMRCIDs ; if (m_pnStringRCIDs) delete m_pnStringRCIDs ; } ; } /****************************************************************************** CModelData::Load(CStdioFile csiofGPD) This overload loads the GPD from a text file directly. ******************************************************************************/ BOOL CModelData::Load(CStdioFile& csiofGPD) { CString csWork; // Used to read the GPD file's contents // Initialize the string array used to hold the GPD file's contents m_csaGPD.RemoveAll(); // Load the GPD into the string array one line at a time. while (csiofGPD.ReadString(csWork)) { csWork.TrimRight(); // Cut off the trailing line stuff m_csaGPD.Add(csWork); } // Set the correct name and path when necessary. The rename checks may // fail since the file is opened elsewhere (possibly with sharing // conflicts), so disable them while the name is set. if (FileTitle().IsEmpty()) { m_cfn.EnableCreationCheck(FALSE); SetFileName(csiofGPD.GetFilePath()); m_cfn.EnableCreationCheck(); } // All went well so... return TRUE; } /****************************************************************************** CModelData::Load() This overload loads the GPD file from the disk using the stored name and path information. ******************************************************************************/ BOOL CModelData::Load() { // There is nothing to load if no file has been associated with this // instance of CModelData. if (FileTitle().IsEmpty()) return FALSE; // Open the GPD file and call another load routine to finish the work. try { CStdioFile csiofGPD(FileName(), CFile::modeRead | CFile::shareDenyWrite); return Load(csiofGPD); } catch (CException *pce) { pce -> ReportError(); pce -> Delete(); } return FALSE; } /****************************************************************************** CModelData::Store This method sends the GPD file to the disk. Since GPD infromation can be easily edited with an external editor, this avoids replication and consistency issues. ******************************************************************************/ BOOL CModelData::Store(LPCTSTR lpstrPath) { int n = (int)m_csaGPD.GetSize() ; CString cs = m_csaGPD[0] ; // Write the GPD file to the target location, with the traditional CR/LF // separators. If the given name is NULL, use the stored one. try { CStdioFile csiofGPD(lpstrPath ? lpstrPath : FileName(), CFile::modeCreate | CFile::modeWrite | CFile::shareExclusive | CFile::typeBinary); for (int i = 0; i < m_csaGPD.GetSize(); i++) csiofGPD.WriteString(m_csaGPD[i] + _T("\r\n")); } catch (CException *pce) { pce -> ReportError(); pce -> Delete(); return FALSE; } Changed(FALSE); return TRUE; } /****************************************************************************** CModelData::BkupStore Backup the original contents of the GPD to file called "BKUP_GPD" before calling Store() to save the file. Return TRUE if the backup and storing succeed. Otherwise, return FALSE. ******************************************************************************/ BOOL CModelData::BkupStore() { // Build the backup file's filespec CString csbkfspec = m_cfn.Path() ; if (csbkfspec[csbkfspec.GetLength() - 1] != _T('\\')) csbkfspec += _T("\\") ; csbkfspec += _T("BKUP_GPD") ; // raid 9730 : bug caused by "Read-Only" CFileStatus rStatus; CFile::GetStatus(FileName(), rStatus); // Back up the file. try { if (rStatus.m_attribute & 0x01 || !CopyFile(FileName(), csbkfspec, FALSE)) {//end raid csbkfspec.Format(IDS_GPDBackupFailed, FileTitleExt()) ; if (AfxMessageBox(csbkfspec, MB_YESNO + MB_ICONQUESTION) == IDNO) return FALSE ; } ; } catch (CException *pce) { pce->ReportError() ; pce->Delete() ; return FALSE ; } ; // Now do a normal store operation. return (Store()) ; } /****************************************************************************** CModelData::Restore Copy the file "BKUP_GPD" to the GPD file to restore the GPD's original contents. If the restore operation is successful, delete the backup file. Return nonzero if this succeeds. Otherwise, return FALSE. ******************************************************************************/ BOOL CModelData::Restore() { // Build the backup file's filespec CString csbkfspec = m_cfn.Path() ; if (csbkfspec[csbkfspec.GetLength() - 1] != _T('\\')) csbkfspec += _T("\\") ; csbkfspec += _T("BKUP_GPD") ; // Restore the file. try { if (CopyFile(csbkfspec, FileName(), FALSE)) { DeleteFile(csbkfspec) ; return TRUE ; } else return FALSE ; } catch (CException *pce) { pce->ReportError() ; pce->Delete() ; return FALSE ; } ; } /****************************************************************************** CModelData::Parse This method is responsible for parsing the GPD file and collecting the resulting errors. The initial implementation will be a bit bizarre, because the GPD parser isn't stable, and converting it so it would work well for ma and then staying on top of the changes just doesn't make sense. ******************************************************************************/ extern "C" BOOL BcreateGPDbinary(LPCWSTR lpstrFile, DWORD dwVerbosity); // The parser hook extern "C" PVOID LoadRawBinaryData(LPCWSTR lpstrFile) ; extern "C" PVOID InitBinaryData(PVOID pv, PVOID pv2, PVOID pv3) ; extern "C" void FreeBinaryData(PVOID pInfoHdr); extern "C" void UseLog(FILE *pfLog); //extern "C" DWORD gdwVerbosity ; BOOL CModelData::Parse(int nerrorlevel) { // Step 0: Set the error level. This is 0 by default. // Step 1: Establish the correct directory for the parser, and // bang together a couple of file names CString csCurrent ; GetCurrentDirectory(MAX_PATH + 1, csCurrent.GetBuffer(MAX_PATH + 1)); csCurrent.ReleaseBuffer(); SetCurrentDirectory(m_cfn.Path().Left(m_cfn.Path().ReverseFind(_T('\\')))); // Step 2: Fake out the error logging interface so it actually tosses // them all into a CString Array for us, the invoke the parser. SetLog(); // Step 3: Convert the file name to Unicode so we don't have to tweak the // parser code. CString csFile = FileTitle() + _T(".GPD"); CByteArray cbaIn; CWordArray cwaOut; cbaIn.SetSize(csFile.GetLength() + 1); lstrcpy((LPSTR) cbaIn.GetData(), csFile); CCodePageInformation ccpi; ccpi.Convert(cbaIn, cwaOut, GetACP()); if (BcreateGPDbinary((PWSTR)cwaOut.GetData(), nerrorlevel)) { PVOID pRawData ; PVOID pInfoHdr ; pRawData = LoadRawBinaryData((PWSTR)cwaOut.GetData()); if(pRawData) pInfoHdr = InitBinaryData(pRawData, NULL, NULL); if (pRawData && pInfoHdr) FreeBinaryData(pInfoHdr); if (pRawData) UnloadRawBinaryData(pRawData) ; DeleteFile(FileTitle() + _T(".Bud")); } // Finally, clean up the mess by restoring the original working // directory and turn off logging. SetCurrentDirectory(csCurrent); EndLog() ; return TRUE; } /****************************************************************************** CModelData::RemoveError This removes the given error from the log. ******************************************************************************/ void CModelData::RemoveError(unsigned u) { if (u >= Errors()) return; m_csaConvertLog.RemoveAt(u); Changed(); } /****************************************************************************** CModelData::Fill(CRichEditCtrl& crec) This overload fills the gven rich edit control with the GPD contents, either as currently cached in memory, or stored on the disk. ******************************************************************************/ void CModelData::Fill(CRichEditCtrl& crec) { // Prepare to load the rich edit control (REC) with the GPD data EDITSTREAM es = {(DWORD_PTR) this, 0, FillViewer}; m_iLine = 0; // If the GPD is not in memory yet, read it in before loading the REC. if (!m_csaGPD.GetSize()) Load(); // Load the GPD into the REC. crec.StreamIn(SF_TEXT, es); } /****************************************************************************** CModelData::UpdateFrom(CRichEditCtrl& crec) This overloaded member function discards the current GPD cache and refills it from the given edit control. ******************************************************************************/ void CModelData::UpdateFrom(CRichEditCtrl& crec) { EDITSTREAM es = {(DWORD_PTR) this, 0, FromViewer}; m_csaGPD.RemoveAll(); m_csBuffer.Empty(); // Just in case... crec.StreamOut(SF_TEXT, es); Changed(); } /****************************************************************************** CModelData::CreateEditor This member function launches an editing view for the GPD Data. ******************************************************************************/ CMDIChildWnd* CModelData::CreateEditor() { // Create a new document class instance for the new editor CGPDContainer* pcgpdcMe= new CGPDContainer(this, FileName()); // Read in the GPD Load(); // Make up a cool title pcgpdcMe -> SetTitle(m_pcbnWorkspace -> Name() + _T(": ") + Name()); // Build a frame for the editor and attach the doc class to it CMDIChildWnd *pcmcwNew = (CMDIChildWnd *) m_pcmdt -> CreateNewFrame(pcgpdcMe, NULL); // Update the new frame/view if (pcmcwNew) { m_pcmdt -> InitialUpdateFrame(pcmcwNew, pcgpdcMe, TRUE); m_pcmdt -> AddDocument(pcgpdcMe); } // Return the new frame pointer return pcmcwNew; } /****************************************************************************** CModelData::Import This method walks one step up the tree and passes the call to the import method for the fixed node which owns us. ******************************************************************************/ void CModelData::Import() { ((CBasicNode *) m_pctcOwner -> GetItemData(m_pctcOwner -> GetParentItem(m_hti))) -> Import(); } /****************************************************************************** CModelData::Serialize Stores the image, as we need it stored. ******************************************************************************/ void CModelData::Serialize(CArchive& car) { CProjectNode::Serialize(car); //TRACE("\n%s has %d strings:\n", Name(), m_csaConvertLog.GetSize()) ; //for (int n = 0 ; n < m_csaConvertLog.GetSize() ; n++) // TRACE(" %d: %s\n", n, m_csaConvertLog[n]) ; m_csaConvertLog.Serialize(car); } /****************************************************************************** CModelData::UpdateResIDs This routine will make sure that the specified resource ID list is up to date. There are several steps that must be taken to accomplish this goal: 1. Free/invalidate old resource lists and related information if the GPD has changed. 2. Parse the GPD and load its data if this is needed. 3. If step 2 is taken or the requested resource list is unitialized, get that data. ******************************************************************************/ //#define RESLISTSIZE 16 // Initial resource list size // Declarations for the GPD Parser routine that will get resource ID lists. extern "C" BOOL GetGPDResourceIDs(LPINT lpiresarray, int numelts, LPINT lpicount, BOOL brestype, PVOID prawdata) ; bool CModelData::UpdateResIDs(bool bufmids) { //TRACE("gdwVerbosity = %d\n", gdwVerbosity) ; // If the GPD has changed so the resource data needs to be updated... if (m_bTCUpdateNeeded) { if (m_pvRawData) { // Free the old preparsed data if there is any UnloadRawBinaryData(m_pvRawData) ; m_pvRawData = NULL ; } ; if (m_pnUFMRCIDs) { // Free the old UFM RC ID list if there is one delete m_pnUFMRCIDs ; m_pnUFMRCIDs = NULL ; m_nNumUFMsInGPD = 0 ; } ; if (m_pnStringRCIDs) { // Free the old string RC ID list if there is one delete m_pnStringRCIDs ; m_pnStringRCIDs = NULL ; m_nNumStringsInGPD = 0 ; } ; m_bTCUpdateNeeded = false ; } ; // Parse and load the GPD data if this is needed. If either of these steps // fail, return false because the resource list cannot be updated. if (!m_pvRawData) { try { WCHAR wstrfilename[MAX_PATH] ; CString cs ; cs = FileName() ; MultiByteToWideChar(CP_ACP, 0, FileName(), -1, wstrfilename, MAX_PATH) ; //gdwVerbosity = 4 ; if (!BcreateGPDbinary(wstrfilename, 0)) return false ; if ((m_pvRawData = LoadRawBinaryData(wstrfilename)) == NULL) return false ; } catch (CException *pce) { pce->ReportError() ; pce->Delete() ; return false ; } } ; // If the requested resource list is already up to date, just return true. if ((bufmids && m_pnUFMRCIDs) || (!bufmids && m_pnStringRCIDs)) return true ; // Allocate space for the resource list int* pn = NULL ; int ncnt = -1 ; //pn = new int[RESLISTSIZE + 2] ; // Try to get the requested resource ID list. If this fails because the // array used to hold the IDs isn't big enough, reallocate the array and // try to get the IDs again. If this fails again, generate a hard error. GetGPDResourceIDs(pn, 0, &ncnt, bufmids, m_pvRawData) ; pn = new int[ncnt + 2] ; VERIFY(GetGPDResourceIDs(pn, ncnt, &ncnt, bufmids, m_pvRawData)) ; //if (GetGPDResourceIDs(pn, RESLISTSIZE, &ncnt, bufmids, m_pvRawData)) { // delete pn ; // pn = new int[ncnt + 2] ; // VERIFY(!GetGPDResourceIDs(pn, ncnt, &ncnt, bufmids, m_pvRawData)) ; //} ; // Update the specific resource ID variables based with the info collected // above. if (bufmids) { m_pnUFMRCIDs = pn ; m_nNumUFMsInGPD = ncnt ; } else { m_pnStringRCIDs = pn ; m_nNumStringsInGPD = ncnt ; } ; // All went well so... return true ; } /****************************************************************************** //RAID 17897 CModelData::GetKeywordValue Get the value of keyword in Gpd file, Arguments : csFileName ; file path of gpd file csKeyword : section name such as *GpdFileVersion: , *ModleName: Return : Success : return section value (string) Failue : return csFileName : file path as it come *****************************************************************************8*/ CString CModelData::GetKeywordValue(CString csfile, CString csKeyword) { CFile cf; CString csModel,csline; int offset; CStringArray csaData; if(!LoadFile(csfile,csaData)){ // call global function in minidev.h(which is include for this fucntion) CString csErr; csErr.Format(IDS_InvalidFilename, csfile); AfxMessageBox(csErr,MB_OK); return csfile; } for(int i=0; i NoteOwner(*this); } // This version of the constructor is called when the GPD Editor is started // from the File Open command. CGPDContainer::CGPDContainer() { m_bEmbedded = FALSE; // Called from File Open menu m_pcmd = new CModelData; m_pcmd -> NoteOwner(*this); } /****************************************************************************** CGPDContainer::OnNewDocument We just pass it back to the default handler. Could mean this one can be toasted ******************************************************************************/ BOOL CGPDContainer::OnNewDocument() { return CDocument::OnNewDocument(); } /****************************************************************************** CGPDContainer::~CGPDContainer If this wasn't created from the workspace, then zap the data! ******************************************************************************/ CGPDContainer::~CGPDContainer() { if (!m_bEmbedded && m_pcmd) delete m_pcmd; } BEGIN_MESSAGE_MAP(CGPDContainer, CDocument) //{{AFX_MSG_MAP(CGPDContainer) // NOTE - the ClassWizard will add and remove mapping macros here. //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CGPDContainer diagnostics #ifdef _DEBUG void CGPDContainer::AssertValid() const { CDocument::AssertValid(); } void CGPDContainer::Dump(CDumpContext& dc) const { CDocument::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CGPDContainer serialization void CGPDContainer::Serialize(CArchive& ar) { if (ar.IsStoring()) { // TODO: add storing code here } else { // TODO: add loading code here } } ///////////////////////////////////////////////////////////////////////////// // CGPDContainer commands /****************************************************************************** CGPDContainer::OnSaveDocument First, make sure that the document is up to date. See CGPDViewer::OnUpdate() for more information. Then, we bypass the normal serialization process, and simple blast it to the drive. ******************************************************************************/ BOOL CGPDContainer::OnSaveDocument(LPCTSTR lpszPathName) { UpdateAllViews(NULL, 0x4545, (CObject*) 0x4545) ; return ModelData()->Store(lpszPathName) ; } /****************************************************************************** CDPSContainer::OnOpenDocument Again, blow off serialization- if I haven't figured out how to read a text file by now, I'm definitely in the wrong place. ******************************************************************************/ BOOL CGPDContainer::OnOpenDocument(LPCTSTR lpszPathName) { try { CStdioFile csiofGPD(lpszPathName, CFile::modeRead | CFile::shareDenyWrite | CFile::typeText); return ModelData() -> Load(csiofGPD); } catch (CException *pce) { pce -> ReportError(); pce -> Delete(); } return FALSE; }