You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1390 lines
42 KiB
1390 lines
42 KiB
/******************************************************************************
|
|
|
|
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 [email protected] 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<csaData.GetSize();i++){
|
|
csline = csaData[i];
|
|
if(-1 ==(offset=csline.Find(csKeyword)))
|
|
continue;
|
|
else
|
|
{
|
|
csModel = csline.Mid(offset+csKeyword.GetLength());
|
|
|
|
return csModel.Mid(csModel.Find(_T('"'))+1,csModel.ReverseFind(_T('"'))
|
|
+ - csModel.Find(_T('"')) - 1 ); // cancel : "
|
|
|
|
|
|
}
|
|
}
|
|
return csfile;
|
|
}
|
|
/***************************************************************************************
|
|
CModelData::SetKeywordValue
|
|
Set the keyword value
|
|
|
|
Arguments:
|
|
csfile ; target file gpd file name
|
|
csKeyword : target keyword ex) *GPDFilename
|
|
csValue : value of keyworkd ex)*GPDFilename= g;\nt\dirver\mm.gpd
|
|
|
|
|
|
*****************************************************************************************/
|
|
|
|
void CModelData::SetKeywordValue(CString csfile, CString csKeyword, CString csValue,bool bSource)
|
|
{
|
|
CFile cf;
|
|
int offset;
|
|
CString csline;
|
|
CStringArray csaData;
|
|
|
|
if(!LoadFile(csfile,csaData)){
|
|
CString csErr;
|
|
csErr.Format(IDS_InvalidFilename, csfile);
|
|
AfxMessageBox(csErr,MB_OK);
|
|
}
|
|
|
|
|
|
for(int i=0; i<csaData.GetSize();i++){
|
|
csline = csaData[i];
|
|
if(-1 ==(offset=csline.Find(csKeyword)))
|
|
continue;
|
|
else
|
|
{
|
|
csline.Empty();
|
|
if(bSource )
|
|
csline = csKeyword + _T("=") + csValue ;
|
|
else
|
|
csline = csKeyword +_T(": ")+ _T('"') + csValue + _T('"');
|
|
|
|
csaData[i]= csline;
|
|
m_csaGPD.Copy(csaData);
|
|
Store(csfile);
|
|
return ;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
CGPDContainer class implementation
|
|
|
|
This class is a document class which contains one GPD file and its assorted
|
|
control mechanisms
|
|
|
|
******************************************************************************/
|
|
|
|
IMPLEMENT_DYNCREATE(CGPDContainer, CDocument)
|
|
|
|
// This version of the constructor is called when the GPD Editor is started
|
|
// from the Workspace View.
|
|
|
|
CGPDContainer::CGPDContainer(CModelData *pcmd, CString csPath)
|
|
{
|
|
m_bEmbedded = TRUE ; // Called from Workspace View
|
|
m_pcmd = pcmd;
|
|
SetPathName(csPath, FALSE);
|
|
m_pcmd -> 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;
|
|
}
|
|
|
|
|