947 lines
31 KiB
C++
947 lines
31 KiB
C++
/******************************************************************************
|
|
|
|
Source File: Driver Resources.CPP
|
|
|
|
This implements the driver resource class, which tracks the resources in the
|
|
driver.
|
|
|
|
Copyright (c) 1997 by Microsoft Corporation. All Rights Reserved.
|
|
|
|
A Pretty Penny Enterprises Production.
|
|
|
|
Change History:
|
|
02-08-1997 Bob_Kjelgaard@Prodigy.Net Created it
|
|
|
|
******************************************************************************/
|
|
|
|
#include "StdAfx.h"
|
|
#include "MiniDev.H"
|
|
#include "ModlData\Resource.H"
|
|
#include "ProjRec.H"
|
|
|
|
// First, we're going to implement the CStringTable class
|
|
|
|
IMPLEMENT_SERIAL(CStringTable, CObject, 0)
|
|
|
|
CString CStringTable::operator[](WORD wKey) const {
|
|
|
|
for (unsigned u = 0; u < Count(); u++)
|
|
if (wKey == m_cuaKeys[u])
|
|
break;
|
|
|
|
return u < Count() ? m_csaValues[u] : m_csEmpty;
|
|
}
|
|
|
|
void CStringTable::Map(WORD wKey, CString csValue) {
|
|
if (!wKey || csValue.IsEmpty()) return;
|
|
|
|
if (!Count() || wKey > m_cuaKeys[-1 + Count()]) {
|
|
m_cuaKeys.Add(wKey);
|
|
m_csaValues.Add(csValue);
|
|
return;
|
|
}
|
|
|
|
for (unsigned u = 0; u < Count(); u++)
|
|
if (m_cuaKeys[u] >= wKey)
|
|
break;
|
|
|
|
if (m_cuaKeys[u] != wKey){
|
|
m_cuaKeys.InsertAt(u, wKey);
|
|
m_csaValues.InsertAt(u, csValue);
|
|
}
|
|
else
|
|
m_csaValues.SetAt(u, csValue);
|
|
}
|
|
|
|
void CStringTable::Remove(WORD wKey) {
|
|
|
|
for (unsigned u = 0; u < Count(); u++)
|
|
if (wKey >= m_cuaKeys[u])
|
|
break;
|
|
|
|
if (u == Count() || wKey != m_cuaKeys[u])
|
|
return;
|
|
m_csaValues.RemoveAt(u);
|
|
m_cuaKeys.RemoveAt(u);
|
|
}
|
|
|
|
void CStringTable::Details(unsigned u, WORD &wKey, CString &csValue) {
|
|
if (u > Count()) u = 0;
|
|
wKey = m_cuaKeys[u];
|
|
|
|
csValue = operator[](wKey);
|
|
}
|
|
|
|
void CStringTable::Serialize(CArchive& car) {
|
|
CObject::Serialize(car);
|
|
m_cuaKeys.Serialize(car);
|
|
m_csaValues.Serialize(car);
|
|
}
|
|
|
|
IMPLEMENT_SERIAL(CDriverResources, CBasicNode, 0)
|
|
|
|
void CDriverResources::Serialize(CArchive& car) {
|
|
CBasicNode::Serialize(car);
|
|
|
|
m_csaIncludes.Serialize(car);
|
|
m_csoaFonts.Serialize(car);
|
|
m_csaTables.Serialize(car);
|
|
m_csoaAtlas.Serialize(car);
|
|
m_csaDefineNames.Serialize(car);
|
|
m_csaDefineValues.Serialize(car);
|
|
m_cst.Serialize(car);
|
|
m_csaRemnants.Serialize(car);
|
|
m_csoaModels.Serialize(car);
|
|
}
|
|
|
|
/******************************************************************************
|
|
|
|
CDriverResources::CheckTable(int iWhere, CString csLine,
|
|
CStringTable& cstTarget)
|
|
|
|
Internal work routine- this looks at a line, and some parameters, decides
|
|
whether to work on it or not, and if it does, validates the resource number
|
|
and adds the file name and resource number to its list.
|
|
|
|
This override is needed because the resource IDs for translation tables have
|
|
not heretofore been a compact set.
|
|
|
|
******************************************************************************/
|
|
|
|
UINT CDriverResources::CheckTable(int iWhere, CString csLine,
|
|
CStringTable& cstTarget) {
|
|
if (iWhere == -1)
|
|
return ItWasIrrelevant;
|
|
|
|
// See if the ID is valid or not. It must be an integer > 0
|
|
|
|
int iKey = atoi(csLine);
|
|
|
|
if (iKey < 0 || iKey > 0x7FFF) // Valid range for resource IDs in Win16
|
|
return ItFailed;
|
|
|
|
for (int i = -1 + csLine.GetLength(); i; i--) {
|
|
if (csLine[i] == _TEXT(' ') || csLine[i] == _TEXT('\t'))
|
|
break;
|
|
}
|
|
|
|
if (!i)
|
|
return ItFailed;
|
|
|
|
cstTarget.Map((WORD) iKey, csLine.Mid(++i));
|
|
|
|
return ItWorked;
|
|
}
|
|
|
|
/******************************************************************************
|
|
|
|
CDriverResources::CheckTable(int iWhere, CString csLine,
|
|
CStringArray& csaTarget)
|
|
|
|
Internal work routine- this looks at a line, and some parameters, decides
|
|
whether to work on it or not, and if it does, validates the resource number
|
|
and adds the file name to its list.
|
|
|
|
******************************************************************************/
|
|
|
|
UINT CDriverResources::CheckTable(int iWhere, CString csLine,
|
|
CStringArray& csaTarget,
|
|
BOOL bSansExtension) {
|
|
if (iWhere == -1)
|
|
return ItWasIrrelevant;
|
|
|
|
// See if the name is valid or not
|
|
|
|
if (atoi(csLine) != 1 +csaTarget.GetSize())
|
|
return ItFailed;
|
|
|
|
for (int i = -1 + csLine.GetLength(); i; i--) {
|
|
if (csLine[i] == _TEXT(' ') || csLine[i] == _TEXT('\t'))
|
|
break;
|
|
}
|
|
|
|
if (!i)
|
|
return ItFailed;
|
|
|
|
if (!bSansExtension) {
|
|
// Don't bother to strip the extension
|
|
csaTarget.Add(csLine.Mid(++i));
|
|
return ItWorked;
|
|
}
|
|
|
|
// Strip everything after the last period.
|
|
|
|
CString csName = csLine.Mid(++i);
|
|
|
|
if (csName.ReverseFind(_T('.')) > csName.ReverseFind(_T('\\')))
|
|
csName = csName.Left(csName.ReverseFind(_T('.')));
|
|
|
|
csaTarget.Add(csName);
|
|
|
|
return ItWorked;
|
|
}
|
|
|
|
// Private work member. This parses a line from a string table to extract
|
|
// the value and the string itself.
|
|
|
|
BOOL CDriverResources::AddStringEntry(CString csLine) {
|
|
|
|
WORD wKey = (WORD) atoi(csLine);
|
|
|
|
if (!wKey)
|
|
return FALSE; // 0 is not a valid resource number...
|
|
|
|
csLine = csLine.Mid(csLine.Find("\""));
|
|
csLine = csLine.Mid(1, -2 + csLine.GetLength());
|
|
|
|
m_cst.Map(wKey, csLine);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// Constructor- would be trivial, except we need to initialize some of the
|
|
// fancier UI objects
|
|
|
|
CDriverResources::CDriverResources() : m_cfnAtlas(IDS_Atlas, m_csoaAtlas),
|
|
m_cfnFonts(IDS_FontList, m_csoaFonts),
|
|
m_cfnModels(IDS_Models, m_csoaModels, GPDTemplate(),
|
|
RUNTIME_CLASS(CModelData)) {
|
|
m_cwaMenuID.Add(ID_ExpandBranch);
|
|
m_cwaMenuID.Add(ID_CollapseBranch);
|
|
m_cfnAtlas.SetMenu(m_cwaMenuID);
|
|
m_cfnFonts.SetMenu(m_cwaMenuID);
|
|
m_cfnModels.SetMenu(m_cwaMenuID);
|
|
m_cwaMenuID.InsertAt(0, 0, 1);
|
|
m_cwaMenuID.InsertAt(0, ID_RenameItem);
|
|
m_ucSynthesized = 0;
|
|
}
|
|
|
|
// Member function for returning a GPC file name. These come ready for
|
|
// concatenation, so they are preceded by '\'
|
|
|
|
CString CDriverResources::GPCName(unsigned u) {
|
|
CString csReturn('\\');
|
|
|
|
csReturn += m_csaTables[u] + _TEXT(".GPC");
|
|
|
|
return csReturn;
|
|
}
|
|
|
|
/******************************************************************************
|
|
|
|
ReportFileFailure
|
|
|
|
This is a private routine- it loads a string table resource with an error
|
|
message, formats it using the given file name, displays a message box,
|
|
then returns FALSE.
|
|
|
|
******************************************************************************/
|
|
|
|
static BOOL ReportFileFailure(int idMessage, LPCTSTR lpstrFile) {
|
|
CString csMessage;
|
|
|
|
csMessage.Format(idMessage, lpstrFile);
|
|
AfxMessageBox(csMessage.IsEmpty()? lpstrFile : csMessage, MB_ICONSTOP);
|
|
return FALSE;
|
|
}
|
|
|
|
/******************************************************************************
|
|
|
|
CDriverResources::Load
|
|
|
|
This function loads and reads the RC file for the driver, and determines all
|
|
of the needed resources. It initializes the structures used to fetermine the
|
|
glyph map file set, font file set, etc.
|
|
|
|
******************************************************************************/
|
|
|
|
BOOL CDriverResources::Load(class CProjectRecord& cprOwner) {
|
|
|
|
CWaitCursor cwc; // Just in case this takes a while...
|
|
NoteOwner(cprOwner);
|
|
|
|
CStringArray csaContents;
|
|
|
|
if (!LoadFile(cprOwner.SourceFile(), csaContents))
|
|
return FALSE;
|
|
|
|
// Clean everything up, in case we were previously loaded...
|
|
m_csaDefineNames.RemoveAll();
|
|
m_csaDefineValues.RemoveAll();
|
|
m_csoaFonts.RemoveAll();
|
|
m_csaIncludes.RemoveAll();
|
|
m_csoaAtlas.RemoveAll();
|
|
m_csoaModels.RemoveAll();
|
|
m_csaRemnants.RemoveAll();
|
|
m_csaTables.RemoveAll();
|
|
m_cst.Reset();
|
|
|
|
// Let the parsing begin
|
|
|
|
BOOL bLookingForBegin = FALSE, bLookingForEnd = FALSE;
|
|
|
|
CStringArray csaFonts; // Names First!
|
|
|
|
// 03-14-1997 We can't assume sequential numbering of the table resources
|
|
|
|
CStringTable cstMaps;
|
|
|
|
for (BOOL bInComment = FALSE;
|
|
csaContents.GetSize();
|
|
csaContents.RemoveAt(0)) {
|
|
|
|
// If stripping out a comment, keep doing it until done.
|
|
|
|
if (bInComment) {
|
|
|
|
if (csaContents[0].Find(_TEXT("*/")) == -1)
|
|
continue;
|
|
|
|
csaContents[0] =
|
|
csaContents[0].Mid(csaContents[0].Find(_TEXT("*/")) + 2);
|
|
|
|
bInComment = FALSE;
|
|
}
|
|
|
|
// Strike all empty lines and remove all comments and leading blanks
|
|
|
|
if (csaContents[0].Find(_TEXT("//")) != -1)
|
|
csaContents[0] =
|
|
csaContents[0].Left(csaContents[0].Find(_TEXT("//")));
|
|
|
|
// If this is the other style comment, zap it, as well
|
|
|
|
while (-1 != csaContents[0].Find(_TEXT("/*"))) {
|
|
|
|
if (csaContents[0].Find(_TEXT("*/")) >
|
|
csaContents[0].Find(_TEXT("/*"))) {
|
|
// strip out everything between them
|
|
|
|
csaContents[0] =
|
|
csaContents[0].Left(csaContents[0].Find(_TEXT("/*"))) +
|
|
csaContents[0].Mid(csaContents[0].Find(_TEXT("*/")) + 2);
|
|
}
|
|
else {
|
|
csaContents[0] =
|
|
csaContents[0].Left(csaContents[0].Find(_TEXT("/*")));
|
|
bInComment = TRUE;
|
|
}
|
|
}
|
|
|
|
// Now for the leading blanks and trailing blanks
|
|
|
|
csaContents[0].TrimLeft();
|
|
csaContents[0].TrimRight();
|
|
|
|
if (csaContents[0].IsEmpty())
|
|
continue;
|
|
|
|
// If we are processing a string table, press onward...
|
|
|
|
if (bLookingForBegin) {
|
|
if (csaContents[0].CompareNoCase(_TEXT("BEGIN")))
|
|
return FALSE; // Parsing failure
|
|
bLookingForBegin = FALSE;
|
|
bLookingForEnd = TRUE;
|
|
continue;
|
|
}
|
|
|
|
if (bLookingForEnd) {
|
|
if (!csaContents[0].CompareNoCase(_TEXT("END"))) {
|
|
bLookingForEnd = FALSE;
|
|
continue;
|
|
}
|
|
|
|
if (!AddStringEntry(csaContents[0]))
|
|
return FALSE; // Parsing error
|
|
|
|
continue;
|
|
}
|
|
|
|
// If it is an include, add it to the list
|
|
|
|
if (csaContents[0].Find(_TEXT("#include")) != -1) {
|
|
csaContents[0] =
|
|
csaContents[0].Mid(csaContents[0].Find(_TEXT("#include")) + 8);
|
|
csaContents[0].TrimLeft();
|
|
m_csaIncludes.Add(csaContents[0]);
|
|
continue;
|
|
}
|
|
|
|
// If it is a #define, do the same
|
|
|
|
if (csaContents[0].Find(_TEXT("#define")) != -1) {
|
|
csaContents[0] =
|
|
csaContents[0].Mid(csaContents[0].Find(_TEXT("#define")) + 7);
|
|
csaContents[0].TrimLeft();
|
|
// TODO: Handle macros with parameters
|
|
m_csaDefineNames.Add(csaContents[0].SpanExcluding(_TEXT(" \t")));
|
|
csaContents[0] =
|
|
csaContents[0].Mid(
|
|
m_csaDefineNames[-1 + m_csaDefineNames.GetSize()].
|
|
GetLength());
|
|
csaContents[0].TrimLeft();
|
|
m_csaDefineValues.Add(csaContents[0]);
|
|
continue;
|
|
}
|
|
|
|
// GPC Tables, fonts, Glyph Tables
|
|
switch (CheckTable(csaContents[0].Find(_TEXT("RC_TABLES")),
|
|
csaContents[0], m_csaTables)) {
|
|
case ItWorked:
|
|
continue;
|
|
case ItFailed:
|
|
return FALSE; // Parsing error
|
|
}
|
|
|
|
switch (CheckTable(csaContents[0].Find(_TEXT("RC_FONT")),
|
|
csaContents[0], csaFonts, FALSE)) {
|
|
case ItWorked:
|
|
continue;
|
|
case ItFailed:
|
|
return FALSE; // Parsing error
|
|
}
|
|
|
|
switch (CheckTable(csaContents[0].Find(_TEXT("RC_TRANSTAB")),
|
|
csaContents[0], cstMaps)) {
|
|
case ItWorked:
|
|
continue;
|
|
case ItFailed:
|
|
return FALSE; // Parsing error
|
|
}
|
|
|
|
// String table...
|
|
|
|
if (csaContents[0].CompareNoCase(_TEXT("STRINGTABLE")))
|
|
m_csaRemnants.Add(csaContents[0]);
|
|
else
|
|
bLookingForBegin = TRUE;
|
|
}
|
|
|
|
// RAID 103242- people can load totally bogus files. Die now if there is
|
|
// no GPC data as a result of this.
|
|
|
|
if (!m_csaTables.GetSize()) {
|
|
AfxMessageBox(IDS_NoGPCData);
|
|
return FALSE;
|
|
}
|
|
|
|
// End 103242
|
|
|
|
if (m_csaTables.GetSize() == 1)
|
|
m_csaTables.Add(_TEXT("NT")); // Usually necessary.
|
|
|
|
// Now, let's name the translation tables- we wil load them later...
|
|
|
|
for (unsigned u = 0; u < cstMaps.Count(); u++) {
|
|
WORD wKey;
|
|
CString csName;
|
|
m_csoaAtlas.Add(new CGlyphMap);
|
|
cstMaps.Details(u, wKey, csName);
|
|
GlyphTable(u).SetSourceName(cprOwner.TargetPath(Win95) + _T('\\') +
|
|
csName);
|
|
if (!GlyphTable(u).SetFileName(cprOwner.TargetPath(WinNT50) +
|
|
_T("\\GTT\\") + GlyphTable(u).Name()))
|
|
return FALSE;
|
|
GlyphTable(u).SetID(wKey);
|
|
}
|
|
|
|
// Ditto for the fonts
|
|
|
|
for (u = 0; u < (unsigned) csaFonts.GetSize(); u++) {
|
|
m_csoaFonts.Add(new CFontInfo);
|
|
Font(u).SetSourceName(cprOwner.TargetPath(Win95) + _T('\\') +
|
|
csaFonts[u]);
|
|
Font(u).SetUniqueName(m_csName);
|
|
if (!Font(u).SetFileName(cprOwner.TargetPath(WinNT50) +
|
|
_T("\\UFM\\") + Font(u).Name()))
|
|
return FALSE;
|
|
}
|
|
|
|
// Now, cycle it again, but this time, make sure all of the root file
|
|
// names are unique
|
|
|
|
for (u = 1; u < FontCount(); u++)
|
|
for (unsigned uCompare = 0; uCompare < u; uCompare++)
|
|
if (!Font(uCompare).FileTitle().CompareNoCase(
|
|
Font(u).FileTitle())) {
|
|
// Append an underscore to the name
|
|
Font(u).ReTitle(Font(u).FileTitle() + _T('_'));
|
|
uCompare = (unsigned) -1; // Check the names again
|
|
Font(u).Rename(Font(u).Name() + _T('_'));
|
|
}
|
|
|
|
// Attempt to load the GPC data if there is any.
|
|
|
|
CFile cfGPC;
|
|
|
|
if (!cfGPC.Open(cprOwner.TargetPath(Win95) + GPCName(0),
|
|
CFile::modeRead | CFile::shareDenyWrite) || !m_comdd.Load(cfGPC))
|
|
|
|
return ReportFileFailure(IDS_FileOpenError,
|
|
cprOwner.TargetPath(Win95) + GPCName(0));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/******************************************************************************
|
|
|
|
CDriverResource::LoadFontData
|
|
|
|
This member function loads the CTT files from the Win 3.1 mini-driver to
|
|
initialize the glyph table array. It is a separate function because the
|
|
Wizard must first verify the code page selection for each of the tables
|
|
with the user.
|
|
|
|
******************************************************************************/
|
|
|
|
BOOL CDriverResources::LoadFontData(CProjectRecord& cprOwner) {
|
|
|
|
CWaitCursor cwc;
|
|
|
|
// Now, let's load the translation tables.
|
|
|
|
for (unsigned u = 0; u < MapCount(); u++)
|
|
// Load the file..
|
|
if (!GlyphTable(u).ConvertCTT())
|
|
return ReportFileFailure(IDS_LoadFailure,
|
|
GlyphTable(u).SourceName());
|
|
|
|
// Now, let's load the Font Data.
|
|
|
|
for (u = 0; u < FontCount() - m_ucSynthesized; u++) {
|
|
|
|
// Load the file.. (side effect of GetTranslation)
|
|
if (!Font(u).GetTranslation())
|
|
return ReportFileFailure(IDS_LoadFailure, Font(u).SourceName());
|
|
|
|
// Generate the CTT/PFM mapping so we generate UFMs correctly
|
|
|
|
if (!Font(u).Translation()) {
|
|
/*
|
|
For each model, check and see if this font is in its map.
|
|
If it is, then add the CTT to the list used, and the model,
|
|
as well.
|
|
|
|
*/
|
|
|
|
CMapWordToDWord cmw2dCTT; // Used to count models per ID
|
|
CWordArray cwaModel; // Models which used this font
|
|
DWORD dwIgnore;
|
|
|
|
for (unsigned uModel = 0; uModel < m_comdd.ModelCount(); uModel++)
|
|
if (m_comdd.FontMap(uModel).Lookup(u + 1, dwIgnore)) {
|
|
// This model needs to be remembered, along with the CTT
|
|
cmw2dCTT[m_comdd.DefaultCTT(uModel)]++;
|
|
cwaModel.Add(uModel);
|
|
}
|
|
|
|
if (!cmw2dCTT.Count()) {
|
|
CString csDisplay;
|
|
csDisplay.Format(IDS_UnusedFont,
|
|
(LPCTSTR) Font(u).SourceName());
|
|
AfxMessageBox(csDisplay);
|
|
continue;
|
|
}
|
|
|
|
if (cmw2dCTT.Count() == 1) {
|
|
// Only one CTT ID was actually used.
|
|
Font(u).SetTranslation(m_comdd.DefaultCTT(cwaModel[0]));
|
|
continue; // We're done with this one
|
|
}
|
|
|
|
/*
|
|
|
|
OK, this font has multiple CTTs in different models. Each
|
|
will require a new UFM to be created. The IDs of the new UFMs
|
|
need to be added to the set, the new defaults established, and
|
|
a list of the font ID remapping needed for each model all need
|
|
maintenance.
|
|
|
|
*/
|
|
|
|
unsigned uGreatest = 0;
|
|
|
|
for (POSITION pos = cmw2dCTT.GetStartPosition(); pos; ) {
|
|
WORD widCTT;
|
|
DWORD dwcUses;
|
|
|
|
cmw2dCTT.GetNextAssoc(pos, widCTT, dwcUses);
|
|
if (dwcUses > uGreatest) {
|
|
uGreatest = dwcUses;
|
|
Font(u).SetTranslation(widCTT);
|
|
}
|
|
}
|
|
|
|
// The models that used the most common CTT will be dropped from
|
|
// the list
|
|
|
|
for (uModel = (unsigned) cwaModel.GetSize(); uModel--; )
|
|
if (m_comdd.DefaultCTT(cwaModel[uModel]) == Font(u).Translation())
|
|
cwaModel.RemoveAt(uModel);
|
|
|
|
// Now, we create a new UFM for each CTT ID, and add the new index to
|
|
// the mapping required for the each affected model.
|
|
|
|
m_ucSynthesized += cmw2dCTT.Count() - 1;
|
|
|
|
for (pos = cmw2dCTT.GetStartPosition(); pos; ) {
|
|
|
|
WORD widCTT;
|
|
DWORD dwcUses;
|
|
|
|
cmw2dCTT.GetNextAssoc(pos, widCTT, dwcUses);
|
|
|
|
if (widCTT == Font(u).Translation())
|
|
continue; // This one has already been done.
|
|
|
|
m_csoaFonts.Add(new CFontInfo(Font(u), widCTT));
|
|
|
|
for (uModel = (unsigned) cwaModel.GetSize(); uModel--; )
|
|
if (m_comdd.DefaultCTT(cwaModel[uModel]) == widCTT) {
|
|
m_comdd.NoteTranslation(cwaModel[uModel], u + 1,
|
|
FontCount());
|
|
cwaModel.RemoveAt(uModel);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// Point each font at its associated GTT file, if there is one
|
|
|
|
for (u = 0; u < FontCount(); u++)
|
|
for (unsigned uGTT = 0; uGTT < MapCount(); uGTT++)
|
|
if (Font(u).Translation() == GlyphTable(uGTT).GetID())
|
|
Font(u).SetTranslation(&GlyphTable(uGTT));
|
|
|
|
Changed();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/******************************************************************************
|
|
|
|
CDriverResources::ConvertGPCData
|
|
|
|
This will handle the conversion of the GPC data to GPD format. It has to be
|
|
done after the framework (especially the target directory) is created.
|
|
|
|
******************************************************************************/
|
|
|
|
BOOL CDriverResources::ConvertGPCData(CProjectRecord& cprOwner,
|
|
WORD wfGPDConvert) {
|
|
|
|
// We've already loaded the GPC data, so now we just generate the files.
|
|
|
|
for (unsigned u = 0; u < m_comdd.ModelCount(); u++) {
|
|
m_csoaModels.Add(new CModelData);
|
|
|
|
// Some model names have invalid characters unsuitable for file names
|
|
// Remove these characters and warn the user about it.
|
|
|
|
CString csModel = m_cst[m_comdd.ModelName(u)];
|
|
|
|
while (csModel.FindOneOf(_T(":<>/\\\"|")) >= 0)
|
|
csModel.SetAt(csModel.FindOneOf(_T(":<>/\\\"|")), _T('_'));
|
|
|
|
if (csModel != m_cst[m_comdd.ModelName(u)]) {
|
|
CString csDisplay;
|
|
|
|
csDisplay.Format(IDS_RemovedInvalid,
|
|
(LPCTSTR) m_cst[m_comdd.ModelName(u)], (LPCTSTR) csModel);
|
|
|
|
AfxMessageBox(csDisplay, MB_ICONINFORMATION);
|
|
}
|
|
|
|
if (!Model(u).SetFileName(cprOwner.TargetPath(WinNT50) + _T("\\") +
|
|
csModel))
|
|
return FALSE;
|
|
Model(u).Rename(m_cst[m_comdd.ModelName(u)]);
|
|
Model(u).NoteOwner(cprOwner);
|
|
Model(u).EditorInfo(GPDTemplate());
|
|
if (!Model(u).Load(m_comdd.Image(), Name(), u + 1,
|
|
m_comdd.FontMap(u), wfGPDConvert) || !Model(u).Store())
|
|
return ReportFileFailure(IDS_GPCConversionError, Model(u).Name());
|
|
}
|
|
|
|
Changed();
|
|
return TRUE;
|
|
}
|
|
|
|
/******************************************************************************
|
|
|
|
CDriverResources::Generate
|
|
|
|
This member function generates the RC file for one of the target environments
|
|
|
|
******************************************************************************/
|
|
|
|
BOOL CDriverResources::Generate(UINT ufTarget, LPCTSTR lpstrPath) {
|
|
|
|
CString csFontPrefix, csTransPrefix, csFontLabel, csTransLabel;
|
|
unsigned ucTables = 0, ucFonts =
|
|
(ufTarget == WinNT50) ? FontCount() : OriginalFontCount();
|
|
|
|
if (ufTarget == WinNT50) {
|
|
csFontLabel = _T("RC_UFM");
|
|
csTransLabel = _T("RC_GTT");
|
|
}
|
|
else {
|
|
csFontLabel = _T("RC_FONT");
|
|
csTransLabel = _T("RC_TRANSTAB");
|
|
}
|
|
|
|
switch (ufTarget) {
|
|
case WinNT50:
|
|
csFontPrefix = _TEXT("UFM");
|
|
csTransPrefix = _TEXT("GTT");
|
|
break;
|
|
|
|
case WinNT40:
|
|
case WinNT3x:
|
|
csFontPrefix = _TEXT("IFI");
|
|
csTransPrefix = _TEXT("RLE");
|
|
ucTables = 2;
|
|
break;
|
|
|
|
case Win95:
|
|
csFontPrefix = _TEXT("PFM");
|
|
csTransPrefix = _TEXT("CTT");
|
|
ucTables = 1;
|
|
break;
|
|
|
|
default:
|
|
_ASSERTE(FALSE); // This shouldn't happen
|
|
return FALSE;
|
|
}
|
|
|
|
// Create the RC file first.
|
|
|
|
CStdioFile csiof;
|
|
|
|
if (!csiof.Open(lpstrPath, CFile::modeCreate | CFile::modeWrite |
|
|
CFile::shareExclusive | CFile::typeText)) {
|
|
_ASSERTE(FALSE); // This shouldn't be possible
|
|
return FALSE;
|
|
}
|
|
|
|
// Write out our header- it identifies this tool as the source, and it
|
|
// will (eventually) include the Copyright and other strings used to
|
|
// customize the environment.
|
|
try {
|
|
csiof.WriteString(_TEXT("/********************************************")
|
|
_TEXT("**********************************\n\n"));
|
|
csiof.WriteString(_T(" RC file generated by the Minidriver ")
|
|
_T("Development Tool\n\n"));
|
|
csiof.WriteString(_TEXT("*********************************************")
|
|
_TEXT("*********************************/\n\n"));
|
|
|
|
// Write out all of the includes except those with a ".ver" in them
|
|
|
|
if (ufTarget == WinNT50) { // NT knows best. What do developers know?
|
|
csiof.WriteString(_T("#include <UniRC.H>\n"));
|
|
if (m_bUseCommonRC)
|
|
csiof.WriteString(_T("#include <Common.RC>\n"));
|
|
csiof.WriteString(_T("#include <Windows.H>\n"));
|
|
csiof.WriteString(_T("#include <NTVerP.H>\n"));
|
|
csiof.WriteString(_T("#define VER_FILETYPE VFT_DRV\n"));
|
|
csiof.WriteString(_T("#define VER_FILESUBTYPE VFT2_DRV_PRINTER\n"));
|
|
csiof.WriteString(_T("#define VER_FILEDESCRIPTION_STR \""));
|
|
csiof.WriteString(Name());
|
|
csiof.WriteString(_T(" Printer Driver\"\n"));
|
|
csiof.WriteString(_T("#define VER_INTERNALNAME_STR \""));
|
|
csiof.WriteString(Name().Left(5));
|
|
csiof.WriteString(_T("res.dll\"\n"));
|
|
csiof.WriteString(_T("#define VER_ORIGINALFILENAME_STR \""));
|
|
csiof.WriteString(Name().Left(5));
|
|
csiof.WriteString(_T("res.dll\"\n"));
|
|
csiof.WriteString(_T("#include \"common.ver\"\n"));
|
|
}
|
|
else
|
|
for (unsigned u = 0; u < (unsigned) m_csaIncludes.GetSize(); u++) {
|
|
CString csTest = m_csaIncludes[u];
|
|
csTest.MakeLower();
|
|
if (m_csaIncludes[u].Find(_TEXT(".ver")) != -1)
|
|
continue;
|
|
csTest = _TEXT("#include ");
|
|
csTest += m_csaIncludes[u] + _TEXT('\n');
|
|
csiof.WriteString(csTest);
|
|
}
|
|
|
|
csiof.WriteString(_TEXT("\n"));
|
|
|
|
// Now, write out all of the #defines
|
|
|
|
for (unsigned u = 0; u < (unsigned) m_csaDefineNames.GetSize(); u++) {
|
|
CString csDefine;
|
|
csDefine.Format(_TEXT("#define %-32s %s\n"),
|
|
(LPCTSTR) m_csaDefineNames[u], (LPCTSTR) m_csaDefineValues[u]);
|
|
csiof.WriteString(csDefine);
|
|
}
|
|
|
|
csiof.WriteString(_TEXT("\n"));
|
|
|
|
// GPC tables
|
|
|
|
if (ufTarget != WinNT50)
|
|
for (u = 0; u < ucTables; u++) {
|
|
CString csLine;
|
|
csLine.Format(_T("%-5u RC_TABLES PRELOAD MOVEABLE "), u + 1);
|
|
if (m_csaTables[u] != _T("NT"))
|
|
csLine += _T("\"");
|
|
csLine += m_csaTables[u] + _T(".GPC");
|
|
if (m_csaTables[u] != _T("NT"))
|
|
csLine += _T("\"");
|
|
csiof.WriteString(csLine + _T("\n"));
|
|
}
|
|
|
|
csiof.WriteString(_TEXT("\n"));
|
|
|
|
// Font tables
|
|
|
|
for (u = 0; u < ucFonts; u++) {
|
|
CString csLine;
|
|
#if defined(NOPOLLO)
|
|
csLine.Format(_TEXT("%-5u %s LOADONCALL DISCARDABLE \""),
|
|
u + 1, (LPCTSTR) csFontLabel);
|
|
csLine += csFontPrefix + _TEXT('\\') + Font(u).Name() +
|
|
_TEXT('.') + csFontPrefix + _TEXT("\"\n");
|
|
#else
|
|
csLine.Format(_TEXT("%-5u %s LOADONCALL DISCARDABLE "),
|
|
u + 1, (LPCTSTR) csFontLabel);
|
|
csLine += csFontPrefix + _TEXT('\\') + Font(u).Name() +
|
|
_TEXT('.') + csFontPrefix + _TEXT("\n");
|
|
#endif
|
|
csiof.WriteString(csLine);
|
|
}
|
|
|
|
csiof.WriteString(_TEXT("\n"));
|
|
|
|
// Mapping tables
|
|
|
|
for (u = 0; u < MapCount(); u++) {
|
|
CString csLine;
|
|
#if defined(NOPOLLO)
|
|
csLine.Format(_TEXT("%-5u %s LOADONCALL MOVEABLE \""),
|
|
u + 1, (LPCTSTR) csTransLabel);
|
|
csLine += csTransPrefix + _TEXT('\\') + GlyphTable(u).Name() +
|
|
_TEXT('.') + csTransPrefix + _TEXT("\"\n");
|
|
#else
|
|
csLine.Format(_TEXT("%-5u %s LOADONCALL MOVEABLE "),
|
|
u + 1, (LPCTSTR) csTransLabel);
|
|
csLine += csTransPrefix + _TEXT('\\') + GlyphTable(u).Name() +
|
|
_TEXT('.') + csTransPrefix + _TEXT("\n");
|
|
#endif
|
|
csiof.WriteString(csLine);
|
|
}
|
|
|
|
csiof.WriteString(_TEXT("\n"));
|
|
|
|
// Time to do the String Table
|
|
if (m_cst.Count()) {
|
|
csiof.WriteString(_TEXT("STRINGTABLE\n BEGIN\n"));
|
|
for (u = 0; u < m_cst.Count(); u++) {
|
|
WORD wKey;
|
|
CString csValue, csLine;
|
|
|
|
m_cst.Details(u, wKey, csValue);
|
|
|
|
csLine.Format(_TEXT(" %-5u \""), wKey);
|
|
csLine += csValue + _TEXT("\"\n");
|
|
csiof.WriteString(csLine);
|
|
}
|
|
csiof.WriteString(_TEXT(" END\n\n"));
|
|
}
|
|
|
|
// Now, write out any .ver includes
|
|
|
|
if (ufTarget != WinNT50) // Already hardcoded them here
|
|
for (u = 0; u < (unsigned) m_csaIncludes.GetSize(); u++) {
|
|
CString csTest = m_csaIncludes[u];
|
|
csTest.MakeLower();
|
|
if (m_csaIncludes[u].Find(_TEXT(".ver")) == -1)
|
|
continue;
|
|
csTest = _TEXT("#include ");
|
|
csTest += m_csaIncludes[u] + _TEXT('\n');
|
|
csiof.WriteString(csTest);
|
|
}
|
|
|
|
csiof.WriteString(_TEXT("\n"));
|
|
#if defined(NOPOLLO)
|
|
// Now, any of the remnants
|
|
|
|
for (u = 0; u < (unsigned) m_csaRemnants.GetSize(); u++)
|
|
csiof.WriteString(m_csaRemnants[u] + TEXT('\n'));
|
|
#endif
|
|
}
|
|
catch(CException* pce) {
|
|
pce -> ReportError();
|
|
pce -> Delete();
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/******************************************************************************
|
|
|
|
CDriverResources::Fill
|
|
|
|
This is a CProjectNode override- it fills in the material relevant to this
|
|
driver.
|
|
|
|
******************************************************************************/
|
|
|
|
void CDriverResources::Fill(CTreeCtrl *pctcWhere, CProjectRecord& cpr) {
|
|
CWaitCursor cwc;
|
|
|
|
NoteOwner(cpr);
|
|
SetWorkspace(this);
|
|
CBasicNode::Fill(pctcWhere);
|
|
|
|
// Fill in the font information
|
|
m_cfnFonts.Fill(pctcWhere, m_hti);
|
|
m_cfnFonts.NoteOwner(cpr);
|
|
|
|
for (unsigned u = 0; u < FontCount(); u++) {
|
|
Font(u).SetWorkspace(this);
|
|
Font(u).EditorInfo(FontTemplate());
|
|
}
|
|
|
|
// Fill in the glyph map information
|
|
m_cfnAtlas.Fill(pctcWhere, m_hti);
|
|
m_cfnAtlas.NoteOwner(cpr);
|
|
for (u = 0; u < MapCount(); u++) {
|
|
GlyphTable(u).SetWorkspace(this);
|
|
GlyphTable(u).EditorInfo(GlyphMapDocTemplate());
|
|
}
|
|
|
|
// Fill in the model data information.
|
|
|
|
m_cfnModels.Fill(pctcWhere, m_hti);
|
|
for (u = 0; u < Models(); u++) {
|
|
Model(u).SetWorkspace(this);
|
|
Model(u).EditorInfo(GPDTemplate());
|
|
}
|
|
m_cfnModels.NoteOwner(cpr);
|
|
pctcWhere -> Expand(m_hti, TVE_EXPAND);
|
|
|
|
// Load the font and GTT files, then map them together. Also load any
|
|
// predefined tables now.
|
|
|
|
for (u = 0; u < MapCount(); u++)
|
|
GlyphTable(u).Load();
|
|
|
|
for (u = 0; u < FontCount(); u++) {
|
|
Font(u).Load();
|
|
if (CGlyphMap::Public(Font(u).Translation()))
|
|
Font(u).SetTranslation(CGlyphMap::Public(Font(u).Translation()));
|
|
else
|
|
for (unsigned uGTT = 0; uGTT < MapCount(); uGTT++)
|
|
if (Font(u).Translation() == GlyphTable(uGTT).GetID())
|
|
Font(u).SetTranslation(&GlyphTable(uGTT));
|
|
Font(u).Load(); // Try it again, now that we know the linkage.
|
|
}
|
|
}
|