Files
2025-04-27 07:49:33 -04:00

931 lines
30 KiB
C++

/******************************************************************************
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"
#undef AFX_EXT_CLASS
#define AFX_EXT_CLASS __declspec(dllimport)
#include "..\FontEdit\ProjNode.H"
#include "..\CodePage\CodePage.H"
#undef AFX_EXT_CLASS
#define AFX_EXT_CLASS __declspec(dllexport)
#include "..\Resource.H"
#include "Resource.H"
#include "GPDFile.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::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;
// pull 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::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)[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.
******************************************************************************/
DWORD CALLBACK CModelData::FillViewer(DWORD 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 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 = m_csaGPD.GetSize();
if (!m_cbaBuffer.GetSize() && m_iLine >= iTotalLines) {
*plcb = 0;
return 0; // We be done!
}
unsigned ucb = (unsigned) lcb;
union {
LPTSTR lpstr;
LPBYTE lpbThis;
};
// First, empty anything buffered previously
lpbThis = lpb;
if (m_cbaBuffer.GetSize())
if ((unsigned) m_cbaBuffer.GetSize() <= ucb) {
// Cool- the entire line will fit in the buffer.
memcpy(lpbThis, m_cbaBuffer.GetData(), m_cbaBuffer.GetSize());
ucb -= m_cbaBuffer.GetSize();
lpbThis += m_cbaBuffer.GetSize();
m_cbaBuffer.RemoveAll();
}
else {
memcpy(lpbThis, m_cbaBuffer.GetData(), ucb);
m_cbaBuffer.RemoveAt(0, ucb);
*plcb = lcb;
return 0;
}
for (; ucb && m_iLine < iTotalLines; m_iLine++) {
CString csLine = m_csaGPD[m_iLine];
csLine += _TEXT("\r\n");
if ((csLine.GetLength()) * sizeof(TCHAR) <= ucb) {
// Cool- the entire line will fit in the buffer.
memcpy(lpbThis, (LPCTSTR) csLine,
sizeof(TCHAR) * csLine.GetLength());
ucb -= sizeof(TCHAR) * csLine.GetLength();
lpstr += csLine.GetLength();
continue;
}
// This is a partial buffer- copy it to the internal buffer, and
// finish filling the original.
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;
}
*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_RenameItem);
m_cwaMenuID.Add(0);
m_cwaMenuID.Add(ID_Import);
m_cwaMenuID.Add(ID_DeleteItem);
m_cwaMenuID.Add(0);
m_cwaMenuID.Add(ID_ExpandBranch);
m_cwaMenuID.Add(ID_CollapseBranch);
}
/******************************************************************************
CModelData::Load(CStdioFile csiofGPD)
This overload loads the GPD from a text file directly.
******************************************************************************/
BOOL CModelData::Load(CStdioFile& csiofGPD) {
CString csWork;
m_csaGPD.RemoveAll();
while (csiofGPD.ReadString(csWork)) {
csWork.TrimRight(); // Cut off the trailing line stuff
m_csaGPD.Add(csWork);
}
// Note the correct name and path- the rename checks may fail, since the
// file is opened elsewhere (possibly with sharing conflicts), so disable
// them, for now.
if (FileTitle().IsEmpty()) {
m_cfn.EnableCreationCheck(FALSE);
SetFileName(csiofGPD.GetFilePath());
m_cfn.EnableCreationCheck();
}
return TRUE;
}
/******************************************************************************
CModelData::Load()
This overload loads the GPD file from the disk using the stored name and path
information.
******************************************************************************/
BOOL CModelData::Load() {
if (FileTitle().IsEmpty())
return FALSE;
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) {
// 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::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); // 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 UnloadRawBinaryData(PVOID pRawData) ;
extern "C" void UseLog(FILE *pfLog);
BOOL CModelData::Parse() {
// 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 tosees
// 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(cwaOut.GetData())) {
PVOID pRawData ;
PVOID pInfoHdr ;
pRawData = LoadRawBinaryData(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.
SetCurrentDirectory(csCurrent);
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) {
EDITSTREAM es = {(DWORD) this, 0, FillViewer};
m_iLine = 0;
if (!m_csaGPD.GetSize())
Load();
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) 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() {
CGPDContainer* pcgpdcMe=
new CGPDContainer(this, FileName());
Load();
// Make up a cool title
pcgpdcMe -> SetTitle(m_pcbnWorkspace -> Name() + _T(": ") + Name());
CMDIChildWnd *pcmcwNew = (CMDIChildWnd *) m_pcmdt ->
CreateNewFrame(pcgpdcMe, NULL);
if (pcmcwNew) {
m_pcmdt -> InitialUpdateFrame(pcmcwNew, pcgpdcMe, TRUE);
m_pcmdt -> AddDocument(pcgpdcMe);
}
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::Delete
This is called when the user presses the Delete key or selects the Delete
menu item from an appropriate context menu.
We use a modal dialog to ask whether the user intends to really remove the
file from the workspace, and whether or not they wish to delete the
underlying file.
******************************************************************************/
void CModelData::Delete() {
CGPDDeleteQuery cgdq;
cgdq.FileName(Name());
if (cgdq.DoModal() != IDYES)
return;
if (cgdq.KillFile())
DeleteFile(m_cfn.FullName());
// Walk back up the hierarchy to find the owning Fixed node, and
// remove us from the array for that node- since that member is a
// reference to the array, all will work as it should.
CFixedNode& cfnGPD = * (CFixedNode *) m_pctcOwner -> GetItemData(
m_pctcOwner -> GetParentItem(m_hti));
ASSERT(cfnGPD.IsKindOf(RUNTIME_CLASS(CFixedNode)));
cfnGPD.Zap(this);
// WARNING: the object pointed to by this has been deleted do NOTHING
// from this point on that could cause the pointer to be dereferenced!
}
/******************************************************************************
CModelData::Serialize
Stores the image, as we need it stored.
******************************************************************************/
void CModelData::Serialize(CArchive& car) {
CProjectNode::Serialize(car);
m_csaConvertLog.Serialize(car);
}
/******************************************************************************
CGPDContainer class implementation
This class is a document class which contains one GPD file and its assorted
control mechanisms
******************************************************************************/
IMPLEMENT_DYNCREATE(CGPDContainer, CDocument)
CGPDContainer::CGPDContainer(CModelData *pcmd, CString csPath) {
m_bEmbedded = TRUE;
m_pcmd = pcmd;
SetPathName(csPath, FALSE);
m_pcmd -> NoteOwner(*this);
}
CGPDContainer::CGPDContainer() {
m_bEmbedded = FALSE;
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
We bypass the normal serialization process, and simple blast it to the drive.
******************************************************************************/
BOOL CGPDContainer::OnSaveDocument(LPCTSTR lpszPathName) {
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;
}
/******************************************************************************
CGPDDeleteQuery dialog
This implements the dialog that validates and verifies the removal of a GPD
file from the workspace.
******************************************************************************/
CGPDDeleteQuery::CGPDDeleteQuery(CWnd* pParent /*=NULL*/)
: CDialog(CGPDDeleteQuery::IDD, pParent) {
//{{AFX_DATA_INIT(CGPDDeleteQuery)
m_csTarget = _T("");
m_bRemoveFile = FALSE;
//}}AFX_DATA_INIT
}
void CGPDDeleteQuery::DoDataExchange(CDataExchange* pDX) {
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CGPDDeleteQuery)
DDX_Text(pDX, IDC_FileName, m_csTarget);
DDX_Check(pDX, IDC_Remove, m_bRemoveFile);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CGPDDeleteQuery, CDialog)
//{{AFX_MSG_MAP(CGPDDeleteQuery)
ON_BN_CLICKED(IDNO, OnNo)
ON_BN_CLICKED(IDYES, OnYes)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CGPDDeleteQuery message handlers
void CGPDDeleteQuery::OnYes() {
if (UpdateData())
EndDialog(IDYES);
}
void CGPDDeleteQuery::OnNo() {
EndDialog(IDNO);
}