Leaked source code of windows server 2003
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.

2767 lines
86 KiB

  1. /******************************************************************************
  2. Source File: Driver Resources.CPP
  3. This implements the driver resource class, which tracks the resources in the
  4. driver.
  5. Copyright (c) 1997 by Microsoft Corporation. All Rights Reserved.
  6. A Pretty Penny Enterprises Production.
  7. Change History:
  8. 02-08-1997 Bob_Kjelgaard@Prodigy.Net Created it
  9. ******************************************************************************/
  10. #include "StdAfx.h"
  11. #include <gpdparse.h>
  12. #include "MiniDev.H"
  13. #include "Resource.H"
  14. #include "WSCheck.h"
  15. #include "ProjRec.H"
  16. // First, we're going to implement the CStringTable class
  17. IMPLEMENT_SERIAL(CStringTable, CObject, 0)
  18. CString CStringTable::operator[](WORD wKey) const {
  19. for (unsigned u = 0; u < Count(); u++)
  20. if (wKey == m_cuaKeys[u])
  21. break;
  22. return u < Count() ? m_csaValues[u] : m_csEmpty;
  23. }
  24. void CStringTable::Map(WORD wKey, CString csValue) {
  25. if (!wKey || csValue.IsEmpty()) return;
  26. if (!Count() || wKey > m_cuaKeys[-1 + Count()]) {
  27. m_cuaKeys.Add(wKey);
  28. m_csaValues.Add(csValue);
  29. return;
  30. }
  31. for (unsigned u = 0; u < Count(); u++)
  32. if (m_cuaKeys[u] >= wKey)
  33. break;
  34. if (m_cuaKeys[u] != wKey){
  35. m_cuaKeys.InsertAt(u, wKey);
  36. m_csaValues.InsertAt(u, csValue);
  37. }
  38. else
  39. m_csaValues.SetAt(u, csValue);
  40. }
  41. void CStringTable::Remove(WORD wKey) {
  42. for (unsigned u = 0; u < Count(); u++)
  43. if (wKey >= m_cuaKeys[u])
  44. break;
  45. if (u == Count() || wKey != m_cuaKeys[u])
  46. return;
  47. m_csaValues.RemoveAt(u);
  48. m_cuaKeys.RemoveAt(u);
  49. }
  50. void CStringTable::Details(unsigned u, WORD &wKey, CString &csValue) {
  51. if (u > Count()) u = 0;
  52. wKey = (WORD)m_cuaKeys[u];
  53. csValue = operator[](wKey);
  54. }
  55. void CStringTable::Serialize(CArchive& car)
  56. {
  57. // First, call the base class' serialization routine.
  58. CObject::Serialize(car);
  59. // CUIntArray is not serializable so the keys array's size and values have
  60. // to be saved/restored manually. This is only done when the MDW should
  61. // contain (save) or does contain (restore) this information.
  62. int n = 0 ;
  63. int ncnt = (int)m_cuaKeys.GetSize() ;
  64. CProjectRecord* cpr = (CProjectRecord *) car.m_pDocument ;
  65. if (cpr->GetMDWVersion() > MDW_DEFAULT_VERSION) {
  66. if (car.IsStoring()) {
  67. car << ncnt ;
  68. for (n ; n < ncnt ; n++)
  69. car << m_cuaKeys[n] ;
  70. } else {
  71. car >> ncnt ;
  72. m_cuaKeys.SetSize(ncnt) ;
  73. int nvalue ;
  74. for (n ; n < ncnt ; n++) {
  75. car >> nvalue ;
  76. m_cuaKeys[n] = nvalue ;
  77. } ;
  78. } ;
  79. } ;
  80. // Now save/restore the values array.
  81. m_csaValues.Serialize(car);
  82. }
  83. void CStringTable::InitRefFlags()
  84. {
  85. // Initialize the number of elements in the array to the number of strings
  86. // in the table.
  87. unsigned ucount = Count() ;
  88. m_cuaRefFlags.SetSize(ucount) ;
  89. // Clear all of the flags
  90. for (unsigned u = 0 ; u < ucount ; u++)
  91. ClearRefFlag(u) ;
  92. }
  93. IMPLEMENT_SERIAL(CDriverResources, CBasicNode, 0)
  94. void CDriverResources::Serialize(CArchive& car)
  95. {
  96. CBasicNode::Serialize(car);
  97. m_csaIncludes.Serialize(car);
  98. m_csoaFonts.Serialize(car);
  99. m_csaTables.Serialize(car);
  100. m_csoaAtlas.Serialize(car);
  101. m_csaDefineNames.Serialize(car);
  102. m_csaDefineValues.Serialize(car);
  103. m_cst.Serialize(car);
  104. m_csaRemnants.Serialize(car);
  105. m_csoaModels.Serialize(car);
  106. // There are no paths for driver files in the MDW file when the MDW version
  107. // is at least MDW_VER_NO_FILE_PATHS. Build and set the paths in this case.
  108. unsigned uver = ((CProjectRecord*) car.m_pDocument)->GetMDWVersion() ;
  109. if (uver < MDW_VER_YES_FILE_PATHS) { // raid 123448
  110. CString csw2kpath = ((CProjectRecord*) car.m_pDocument)->GetW2000Path() ;
  111. unsigned unumobjs, u ;
  112. CString cspath ;
  113. // Set the GPD file paths.
  114. cspath = csw2kpath + _T('\\') ;
  115. for (unumobjs = Models(), u = 0 ; u < unumobjs ; u++)
  116. Model(u).SetPath(cspath) ;
  117. // Set the UFM file paths.
  118. cspath.LoadString(IDS_FontDir) ;
  119. cspath = csw2kpath + _T('\\') + cspath ;
  120. for (unumobjs = FontCount(), u = 0 ; u < unumobjs ; u++)
  121. Font(u).SetPath(cspath) ;
  122. // Set the GTT file paths.
  123. cspath.LoadString(IDS_GTTDir) ;
  124. cspath = csw2kpath + _T('\\') + cspath ;
  125. for (unumobjs = MapCount(), u = 0 ; u < unumobjs ; u++)
  126. GlyphTable(u).SetPath(cspath) ;
  127. } ;
  128. }
  129. /******************************************************************************
  130. CDriverResources::CheckTable(int iWhere, CString csLine,
  131. CStringTable& cstTarget)
  132. Internal work routine- this looks at a line, and some parameters, decides
  133. whether to work on it or not, and if it does, validates the resource number
  134. and adds the file name and resource number to its list.
  135. This override is needed because the resource IDs for translation tables have
  136. not heretofore been a compact set.
  137. ******************************************************************************/
  138. UINT CDriverResources::CheckTable(int iWhere, CString csLine,
  139. CStringTable& cstTarget) {
  140. if (iWhere == -1)
  141. return ItWasIrrelevant;
  142. // See if the ID is valid or not. It must be an integer > 0
  143. int iKey = atoi(csLine);
  144. if (iKey < 0 || iKey > 0x7FFF) // Valid range for resource IDs in Win16
  145. LogConvInfo(IDS_ORangeRCID, 1, &csLine) ;
  146. //return ItFailed;
  147. // Find the filespec at the end of the line. Fail if there is no filespec.
  148. for (int i = -1 + csLine.GetLength(); i; i--) {
  149. if (csLine[i] == _TEXT(' ') || csLine[i] == _TEXT('\t'))
  150. break;
  151. }
  152. if (!i) {
  153. LogConvInfo(IDS_NoFSpecInRCLine, 1, &csLine) ;
  154. return ItWorked; // Cause the line to be skipped.
  155. //return ItFailed;
  156. } ;
  157. cstTarget.Map((WORD) iKey, csLine.Mid(++i));
  158. return ItWorked;
  159. }
  160. /******************************************************************************
  161. CDriverResources::CheckTable(int iWhere, CString csLine,
  162. CStringArray& csaTarget)
  163. Internal work routine- this looks at a line, and some parameters, decides
  164. whether to work on it or not, and if it does, validates the resource number
  165. and adds the file name to its list.
  166. ******************************************************************************/
  167. UINT CDriverResources::CheckTable(int iWhere, CString csLine,
  168. CStringArray& csaTarget,
  169. BOOL bSansExtension) {
  170. if (iWhere == -1)
  171. return ItWasIrrelevant;
  172. // See if the name is valid or not
  173. if (atoi(csLine) != 1 +csaTarget.GetSize())
  174. LogConvInfo(IDS_DupInvRCID, 1, &csLine) ;
  175. //return ItFailed;
  176. // Find the filespec at the end of the line. Fail if there is no filespec.
  177. for (int i = -1 + csLine.GetLength(); i; i--) {
  178. if (csLine[i] == _TEXT(' ') || csLine[i] == _TEXT('\t'))
  179. break;
  180. }
  181. if (!i) {
  182. LogConvInfo(IDS_NoFSpecInRCLine, 1, &csLine) ;
  183. return ItWorked; // Cause the line to be skipped.
  184. //return ItFailed;
  185. } ;
  186. if (!bSansExtension) {
  187. // Don't bother to strip the extension
  188. csaTarget.Add(csLine.Mid(++i));
  189. return ItWorked;
  190. }
  191. // Strip everything after the last period.
  192. CString csName = csLine.Mid(++i);
  193. if (csName.ReverseFind(_T('.')) > csName.ReverseFind(_T('\\')))
  194. csName = csName.Left(csName.ReverseFind(_T('.')));
  195. csaTarget.Add(csName);
  196. return ItWorked;
  197. }
  198. // Private work member. This parses a line from a string table to extract
  199. // the value and the string itself.
  200. BOOL CDriverResources::AddStringEntry(CString csLine,
  201. CStringTable& cstrcstrings)
  202. {
  203. WORD wKey = (WORD) atoi(csLine);
  204. if (!wKey)
  205. return FALSE; // 0 is not a valid resource number...
  206. csLine = csLine.Mid(csLine.Find("\""));
  207. csLine = csLine.Mid(1, -2 + csLine.GetLength());
  208. cstrcstrings.Map(wKey, csLine);
  209. return TRUE;
  210. }
  211. // Constructor- would be trivial, except we need to initialize some of the
  212. // fancier UI objects
  213. CDriverResources::CDriverResources() :
  214. m_cfnAtlas(IDS_Atlas, m_csoaAtlas, FNT_GTTS, GlyphMapDocTemplate(),
  215. RUNTIME_CLASS(CGlyphMap)),
  216. m_cfnFonts(IDS_FontList, m_csoaFonts, FNT_UFMS, FontTemplate(),
  217. RUNTIME_CLASS(CFontInfo)),
  218. m_cfnModels(IDS_Models, m_csoaModels, FNT_GPDS, GPDTemplate(),
  219. RUNTIME_CLASS(CModelData)),
  220. m_cfnResources(IDS_Resources, m_csoaResources, FNT_RESOURCES),
  221. m_csnStrings(IDS_Strings, m_csoaStrings, FNT_STRINGS, StringEditorTemplate(),
  222. RUNTIME_CLASS(CStringsNode))
  223. {
  224. // Set the context sensitive menus for the workspace, resources, UFMs, GTTs,
  225. // GPDs, and Strings nodes.
  226. m_cwaMenuID.Add(ID_OpenItem);
  227. m_csnStrings.SetMenu(m_cwaMenuID);
  228. m_cwaMenuID.SetAt(0, ID_ExpandBranch);
  229. m_cwaMenuID.Add(ID_CollapseBranch);
  230. m_cfnResources.SetMenu(m_cwaMenuID);
  231. m_cwaMenuID.InsertAt(0, 0, 1);
  232. m_cwaMenuID.InsertAt(0, ID_Import);
  233. m_cfnAtlas.SetMenu(m_cwaMenuID);
  234. m_cfnFonts.SetMenu(m_cwaMenuID);
  235. m_cfnModels.SetMenu(m_cwaMenuID);
  236. m_cwaMenuID.SetAt(0, ID_RenameItem);
  237. m_cwaMenuID.InsertAt(0, ID_CheckWS);
  238. m_ucSynthesized = 0;
  239. m_pcsfLogFile = NULL;
  240. m_bErrorsLogged = false;
  241. m_pwscdCheckDoc = NULL ;
  242. m_pcmcwCheckFrame = NULL ;
  243. m_bFirstCheckMsg = true ;
  244. }
  245. CDriverResources::~CDriverResources()
  246. {
  247. // Make sure that if there is a log file, it gets closed.
  248. CloseConvLogFile() ;
  249. }
  250. // Member function for returning a GPC file name. These come ready for
  251. // concatenation, so they are preceded by '\'
  252. CString CDriverResources::GPCName(unsigned u) {
  253. CString csReturn('\\');
  254. csReturn += m_csaTables[u] + _TEXT(".GPC");
  255. return csReturn;
  256. }
  257. /******************************************************************************
  258. CDriverResources::ReportFileFailure
  259. This is a private routine- it loads a string table resource with an error
  260. message, formats it using the given file name, displays a message box,
  261. then returns FALSE.
  262. ******************************************************************************/
  263. BOOL CDriverResources::ReportFileFailure(int idMessage,
  264. LPCTSTR lpstrFile)
  265. {
  266. CString csfile(lpstrFile) ;
  267. LogConvInfo(idMessage, 1, &csfile) ;
  268. return FALSE ;
  269. }
  270. /******************************************************************************
  271. CDriverResources::OpenConvLogFile
  272. This function allocates an instance of CFile to manage the conversion log
  273. file and opens the log file.
  274. ******************************************************************************/
  275. bool CDriverResources::OpenConvLogFile(CString cssourcefile)
  276. {
  277. // Return "failure" if CFile instance cannot be allocated.
  278. if ((m_pcsfLogFile = new CStdioFile) == NULL)
  279. return false ;
  280. // Build the log file name from the input source file name.
  281. m_csConvLogFile = cssourcefile ;
  282. int npos ;
  283. if ((npos = m_csConvLogFile.Find(_T('.'))) >= 0)
  284. m_csConvLogFile = m_csConvLogFile.Left(npos) ;
  285. m_csConvLogFile += _T(".LOG") ;
  286. // Open the log file
  287. if (!m_pcsfLogFile->Open(m_csConvLogFile, CFile::modeCreate | CFile::modeWrite |
  288. CFile::shareExclusive)) {
  289. CloseConvLogFile() ;
  290. return false ;
  291. } ;
  292. // All went well so...
  293. return true ;
  294. }
  295. /******************************************************************************
  296. CDriverResources::CloseConvLogFile
  297. This function closes the conversion log file and deletes the instance of
  298. CFile used to manage the log file.
  299. ******************************************************************************/
  300. void CDriverResources::CloseConvLogFile(void)
  301. {
  302. // Do nothing if the pointer is null.
  303. if (m_pcsfLogFile == NULL)
  304. return ;
  305. // Close the file if it is open
  306. if (m_pcsfLogFile->m_pStream != NULL)
  307. m_pcsfLogFile->Close() ;
  308. delete m_pcsfLogFile ;
  309. m_pcsfLogFile = NULL ;
  310. }
  311. /******************************************************************************
  312. CDriverResources::LogConvInfo
  313. Assuming the log file is ready to use, build and write a message to the
  314. conversion log file.
  315. ******************************************************************************/
  316. void CDriverResources::LogConvInfo(int nmsgid, int numargs, CString* pcsarg1,
  317. int narg2)
  318. {
  319. CString csmsg ; // Log message is loaded/built here
  320. // Do nothing if the log file pointer is null or the file handle is
  321. // uninitialized.
  322. if (m_pcsfLogFile == NULL || m_pcsfLogFile->m_pStream == NULL)
  323. return ;
  324. // Load and/or build the message based on the number of arguments
  325. switch (numargs) {
  326. case 0:
  327. csmsg.LoadString(nmsgid) ;
  328. break ;
  329. case 1:
  330. csmsg.Format(nmsgid, *pcsarg1) ;
  331. break ;
  332. case 2:
  333. csmsg.Format(nmsgid, *pcsarg1, narg2) ;
  334. break ;
  335. default:
  336. return ;
  337. } ;
  338. // Write the message and indicate that a message has been written
  339. try {
  340. m_pcsfLogFile->WriteString(csmsg) ;
  341. }
  342. catch (CException *pce) {
  343. pce->ReportError() ;
  344. pce->Delete() ;
  345. return ;
  346. }
  347. m_bErrorsLogged = true ;
  348. }
  349. /******************************************************************************
  350. CDriverResources::Load
  351. This function loads and reads the RC file for the driver, and determines all
  352. of the needed resources. It initializes the structures used to fetermine the
  353. glyph map file set, font file set, etc.
  354. ******************************************************************************/
  355. BOOL CDriverResources::Load(class CProjectRecord& cprOwner)
  356. {
  357. CWaitCursor cwc; // Just in case this takes a while...
  358. NoteOwner(cprOwner);
  359. // Load the RC file and save its data into data specific arrays.
  360. CStringTable cstFonts; // Names First!
  361. CStringTable cstMaps;
  362. if (!LoadRCFile(cprOwner.SourceFile(), m_csaDefineNames, m_csaDefineValues,
  363. m_csaIncludes, m_csaRemnants, m_csaTables, m_cst, cstFonts,
  364. cstMaps, NotW2000))
  365. return FALSE ;
  366. // The string table with font info in it needs to be copied into a string
  367. // array for further processing.
  368. CStringArray csaFonts ;
  369. int numelts = cstFonts.Count() ;
  370. WORD wKey ;
  371. csaFonts.SetSize(numelts) ;
  372. for (int n = 0 ; n < numelts ; n++)
  373. cstFonts.Details(n, wKey, csaFonts[n]) ;
  374. // RAID 103242- people can load totally bogus files. Die now if there is
  375. // no GPC data as a result of this.
  376. if (!m_csaTables.GetSize()) {
  377. AfxMessageBox(IDS_NoGPCData);
  378. return FALSE;
  379. }
  380. // End 103242
  381. if (m_csaTables.GetSize() == 1)
  382. m_csaTables.Add(_TEXT("NT")); // Usually necessary.
  383. // Now, let's name the translation tables- we wil load them later...
  384. // Note: Different rules are used for naming the node and the file.
  385. CString cstmp ;
  386. int npos ;
  387. for (unsigned u = 0; u < cstMaps.Count(); u++) {
  388. CString csName;
  389. m_csoaAtlas.Add(new CGlyphMap);
  390. cstMaps.Details(u, wKey, csName);
  391. if (csName[0] == _T('\\'))
  392. GlyphTable(u).SetSourceName(cprOwner.TargetPath(Win95) + csName) ;
  393. else
  394. GlyphTable(u).SetSourceName(cprOwner.TargetPath(Win95) + _T('\\') +
  395. csName) ;
  396. //if (!GlyphTable(u).SetFileName(cprOwner.TargetPath(Win2000) +
  397. // _T("\\GTT\\") + GlyphTable(u).Name()))
  398. if ((npos = csName.ReverseFind(_T('\\'))) >= 0)
  399. cstmp = csName.Mid(npos + 1) ;
  400. else
  401. cstmp = csName ;
  402. cstmp = cprOwner.TargetPath(Win2000) + _T("\\GTT\\") + cstmp ;
  403. if (!GlyphTable(u).SetFileName(cstmp)) {
  404. LogConvInfo(IDS_GTTSetName, 1, &cstmp) ;
  405. return FALSE;
  406. };
  407. GlyphTable(u).nSetRCID((int) wKey);
  408. }
  409. // Now, cycle it again, but this time, make sure all of the root file
  410. // names and display names are unique.
  411. for (u = 1; u < MapCount(); u++) {
  412. for (unsigned uCompare = 0; uCompare < u; uCompare++) {
  413. // If a matching file title is found, make it unique.
  414. if (!GlyphTable(uCompare).FileTitle().CompareNoCase(
  415. GlyphTable(u).FileTitle())) {
  416. GlyphTable(u).m_cfn.UniqueName(true, false) ;
  417. uCompare = (unsigned) -1; // Check the names again
  418. continue ;
  419. } ;
  420. // If a matching display name is found, make it unique.
  421. if (!GlyphTable(uCompare).Name().CompareNoCase(
  422. GlyphTable(u).Name())) {
  423. GlyphTable(u).UniqueName(false, false) ;
  424. uCompare = (unsigned) -1; // Check the names again
  425. } ;
  426. } ;
  427. } ;
  428. // Now, let's name the fonts - we wil load them later...
  429. // Note: Different rules are used for naming the node and the file.
  430. for (u = 0; u < (unsigned) csaFonts.GetSize(); u++) {
  431. m_csoaFonts.Add(new CFontInfo);
  432. cstmp = csaFonts[u] ;
  433. if (cstmp.GetAt(0) == _T('\\'))
  434. Font(u).SetSourceName(cprOwner.TargetPath(Win95) + cstmp) ;
  435. else
  436. Font(u).SetSourceName(cprOwner.TargetPath(Win95) + _T('\\') +
  437. cstmp) ;
  438. Font(u).SetUniqueName(m_csName);
  439. if ((npos = cstmp.ReverseFind(_T('\\'))) >= 0)
  440. cstmp = cstmp.Mid(npos + 1) ;
  441. cstmp = cprOwner.TargetPath(Win2000) + _T("\\UFM\\") + cstmp ;
  442. if (!Font(u).SetFileName(cstmp)) {
  443. LogConvInfo(IDS_UFMSetName, 1, &cstmp) ;
  444. return FALSE;
  445. };
  446. }
  447. // Now, cycle it again, but this time, make sure all of the root file
  448. // names and display names are unique.
  449. for (u = 1; u < FontCount(); u++) {
  450. for (unsigned uCompare = 0; uCompare < u; uCompare++) {
  451. // If a matching file title is found, make it unique.
  452. if (!Font(uCompare).FileTitle().CompareNoCase(
  453. Font(u).FileTitle())) {
  454. Font(u).m_cfn.UniqueName(true, false) ;
  455. uCompare = (unsigned) -1; // Check the names again
  456. continue ;
  457. } ;
  458. // If a matching display name is found, make it unique.
  459. if (!Font(uCompare).Name().CompareNoCase(
  460. Font(u).Name())) {
  461. Font(u).UniqueName(false, false) ;
  462. uCompare = (unsigned) -1; // Check the names again
  463. } ;
  464. } ;
  465. } ;
  466. // Attempt to load the GPC data if there is any. Then begin the
  467. // process of splitting GPCs that manage multiple models into multiple
  468. // GPDs.
  469. CFile cfGPC;
  470. if (!cfGPC.Open(cprOwner.TargetPath(Win95) + GPCName(0),
  471. CFile::modeRead | CFile::shareDenyWrite) || !m_comdd.Load(cfGPC))
  472. return ReportFileFailure(IDS_FileOpenError,
  473. cprOwner.TargetPath(Win95) + GPCName(0));
  474. if (!m_comdd.SplitMultiGPCs(m_cst))
  475. return ReportFileFailure(IDS_FileOpenError,
  476. cprOwner.TargetPath(Win95) + GPCName(0));
  477. n = m_cst.Count() ;
  478. return TRUE;
  479. }
  480. /******************************************************************************
  481. CDriverResources::LoadRCFile
  482. This function loads and reads the RC file for the driver, and determines all
  483. of the needed resources. The data is loaded into the arguments.
  484. Args:
  485. csrcfpec The RC filespec for the file to load
  486. csadefinenames Definition names
  487. csadefinevalues Definition values
  488. csaincludes Include statement filespecs
  489. csaremnants RC statements that don't fall into other categories
  490. csatables GPC info
  491. cstrcstrings String table strings
  492. cstfonts Font (UFM/PFM) info
  493. cstmaps Map (CTT/GTT) info
  494. ufrctype Win2000 iff parsing Win2K RC file. Otherwise, NotW2000.
  495. Returns true if the file is successfully loaded. Otherwise, false.
  496. ******************************************************************************/
  497. bool CDriverResources::LoadRCFile(CString& csrcfpec,
  498. CStringArray& csadefinenames,
  499. CStringArray& csadefinevalues,
  500. CStringArray& csaincludes,
  501. CStringArray& csaremnants,
  502. CStringArray& csatables,
  503. CStringTable& cstrcstrings,
  504. CStringTable& cstfonts,
  505. CStringTable& cstmaps,
  506. UINT ufrctype)
  507. {
  508. // Read the RC file
  509. CStringArray csacontents ;
  510. while (!LoadFile(csrcfpec, csacontents)){ // Raid 3176
  511. CString cstmp;int iRet;
  512. cstmp.LoadString(IDS_NotFoundRC);
  513. if ( (iRet = AfxMessageBox(cstmp,MB_YESNO) ) == IDYES) {
  514. CFileDialog cfd(TRUE);
  515. if(IDCANCEL == cfd.DoModal())
  516. return false;
  517. csrcfpec = cfd.GetPathName();
  518. continue;
  519. }
  520. else
  521. return false ;
  522. }
  523. // Clean everything up, in case we were previously loaded...
  524. csadefinenames.RemoveAll();
  525. csadefinevalues.RemoveAll();
  526. csaincludes.RemoveAll();
  527. csaremnants.RemoveAll();
  528. csatables.RemoveAll();
  529. cstrcstrings.Reset();
  530. cstfonts.Reset();
  531. cstmaps.Reset();
  532. // Declare and load the Map and Font table keyword variables
  533. CString csfontlabel, cstranslabel ;
  534. if (ufrctype == Win2000) {
  535. csfontlabel = _T("RC_UFM");
  536. cstranslabel = _T("RC_GTT");
  537. } else {
  538. csfontlabel = _T("RC_FONT");
  539. cstranslabel = _T("RC_TRANSTAB");
  540. } ;
  541. // Let the parsing begin
  542. // 03-14-1997 We can't assume sequential numbering of the table resources
  543. BOOL bLookingForBegin=false, bLookingForEnd=false, bInComment=false ;
  544. CString cscurline, cshold ;
  545. int nloc, nloc2 ;
  546. bool blastlinewasremnant = false ;
  547. while (csacontents.GetSize()) {
  548. // Get the next line to process. Usually this is the next line in the
  549. // contents array. Occassionally, a line held for later processing
  550. // should be used.
  551. if (cshold.IsEmpty()) {
  552. cscurline = csacontents[0] ;
  553. csacontents.RemoveAt(0) ; // *** csacontents updated here
  554. } else {
  555. cscurline = cshold ;
  556. cshold.Empty() ;
  557. } ;
  558. // Add multiline comments to the remnants array. If the comment is
  559. // continuing, just add the line and continue. If this is the last line
  560. // of the comment, check to see if there is anything after the ending
  561. // comment characters. If there is, save everything up to and including
  562. // the comment chars and then set up to process the rest of the line.
  563. if (bInComment) {
  564. blastlinewasremnant = true ;
  565. if ((nloc = cscurline.Find(_TEXT("*/"))) >= 0) {
  566. bInComment = false ;
  567. cscurline.TrimRight();
  568. if (nloc + 2 < cscurline.GetLength()) {
  569. csaremnants.Add(cscurline.Left(nloc + 2)) ;
  570. cscurline = cscurline.Mid(nloc + 2) ;
  571. } else {
  572. csaremnants.Add(cscurline) ;
  573. continue ;
  574. } ;
  575. // Add the comment line to the remnants array.
  576. } else {
  577. csaremnants.Add(cscurline) ;
  578. continue ;
  579. } ;
  580. } ;
  581. // Remove partial line comments
  582. if ((nloc = cscurline.Find(_TEXT("//"))) != -1)
  583. cscurline = cscurline.Left(nloc) ;
  584. // Handle the other style of comments.
  585. while (-1 != (nloc = cscurline.Find(_TEXT("/*")))) {
  586. // Remove all partial line comments.
  587. if ((nloc2 = cscurline.Find(_TEXT("*/"))) > nloc)
  588. cscurline = cscurline.Left(nloc) + cscurline.Mid(nloc2 + 2) ;
  589. // If this is the beginning of a multiline comment that starts at
  590. // the beginning of the line, set the comments flag and continue
  591. // processing. It will be saved later.
  592. else if (nloc == 0) {
  593. bInComment = true ;
  594. break ;
  595. // If this is the beginning of a multiline comment that does NOT
  596. // start at the beginning of the line, save the comment for latter
  597. // processing and set up to continue processing the beginning of
  598. // the line.
  599. } else {
  600. cshold = cscurline.Mid(nloc + 1) ;
  601. cscurline = cscurline.Left(nloc) ;
  602. } ;
  603. } ;
  604. // Now for the leading blanks and trailing blanks
  605. cscurline.TrimLeft();
  606. cscurline.TrimRight();
  607. // Handle blank lines. If the previous line was a nonblank, remnant
  608. // line, add the blank line to the remnants array. Always contine;
  609. // ie go get the next line.
  610. if (cscurline.IsEmpty()) {
  611. if (blastlinewasremnant) {
  612. csaremnants.Add(cscurline) ;
  613. blastlinewasremnant = false ;
  614. } ;
  615. continue ;
  616. } ;
  617. blastlinewasremnant = false ;
  618. // If we are processing a string table, press onward...
  619. if (bLookingForBegin) {
  620. if (cscurline.CompareNoCase(_TEXT("BEGIN")))
  621. return false; // Parsing failure
  622. bLookingForBegin = false;
  623. bLookingForEnd = true;
  624. continue;
  625. }
  626. if (bLookingForEnd) {
  627. if (!cscurline.CompareNoCase(_TEXT("END"))) {
  628. bLookingForEnd = false;
  629. continue;
  630. }
  631. if (!AddStringEntry(cscurline, cstrcstrings))
  632. return false; // Parsing error
  633. continue;
  634. }
  635. // If it is an include, add it to the list
  636. if (cscurline.Find(_TEXT("#include")) != -1) {
  637. cscurline =
  638. cscurline.Mid(cscurline.Find(_TEXT("#include")) + 8);
  639. cscurline.TrimLeft();
  640. csaincludes.Add(cscurline);
  641. continue;
  642. }
  643. // If it is a #define, do the same
  644. if (cscurline.Find(_TEXT("#define")) != -1) {
  645. cscurline =
  646. cscurline.Mid(cscurline.Find(_TEXT("#define")) + 7);
  647. cscurline.TrimLeft();
  648. // TODO: Handle macros with parameters
  649. csadefinenames.Add(cscurline.SpanExcluding(_TEXT(" \t")));
  650. cscurline =
  651. cscurline.Mid(
  652. csadefinenames[-1 + csadefinenames.GetSize()].
  653. GetLength());
  654. cscurline.TrimLeft();
  655. csadefinevalues.Add(cscurline);
  656. continue;
  657. }
  658. // GPC Tables, fonts, Glyph Tables
  659. switch (CheckTable(cscurline.Find(_TEXT("RC_TABLES")),
  660. cscurline, csatables)) {
  661. case ItWorked:
  662. continue;
  663. case ItFailed:
  664. return false; // Parsing error
  665. }
  666. switch (CheckTable(cscurline.Find(csfontlabel),
  667. cscurline, cstfonts)) {
  668. case ItWorked:
  669. continue;
  670. case ItFailed:
  671. return false; // Parsing error
  672. }
  673. switch (CheckTable(cscurline.Find(cstranslabel),
  674. cscurline, cstmaps)) {
  675. case ItWorked:
  676. continue;
  677. case ItFailed:
  678. return false; // Parsing error
  679. }
  680. // String table...
  681. if (cscurline.CompareNoCase(_TEXT("STRINGTABLE"))) {
  682. csaremnants.Add(cscurline) ;
  683. blastlinewasremnant = true ;
  684. } else
  685. bLookingForBegin = true ;
  686. }
  687. //unsigned u, unuments ;
  688. //for (u = 0, unuments = csaremnants.GetSize() ; u < unuments ; u++)
  689. // TRACE("Remnants[%d] = '%s' (%d)\n", u, csaremnants[u], unuments) ;
  690. // All went well so...
  691. return true ;
  692. }
  693. /******************************************************************************
  694. CDriverResource::LoadFontData
  695. This member function loads the CTT files from the Win 3.1 mini-driver to
  696. initialize the glyph table array. It is a separate function because the
  697. Wizard must first verify the code page selection for each of the tables
  698. with the user.
  699. ******************************************************************************/
  700. BOOL CDriverResources::LoadFontData(CProjectRecord& cprOwner) {
  701. CWaitCursor cwc;
  702. int nerrorid ;
  703. // Conversion of drivers that have CTTs **>AND<** are using a Far East
  704. // default code page are not support. Complain and stop the conversion
  705. // when this situation is detected.
  706. if (MapCount() > 0 && ((int) cprOwner.GetDefaultCodePage()) < 0) {
  707. LogConvInfo(IDS_CTTFarEastCPError, 0) ;
  708. return FALSE ;
  709. } ;
  710. // Now, let's load the translation tables.
  711. for (unsigned u = 0; u < MapCount(); u++) {
  712. GlyphTable(u).NoteOwner(cprOwner) ;
  713. // Load the file..
  714. if ((nerrorid = GlyphTable(u).ConvertCTT()) != 0) {
  715. CString cstmp ;
  716. cstmp = GlyphTable(u).SourceName() ;
  717. return ReportFileFailure(IDS_LoadFailure, cstmp) ;
  718. } ;
  719. } ;
  720. // Now, let's load the Font Data.
  721. for (u = 0; u < FontCount() - m_ucSynthesized; u++) {
  722. // Load the file.. (side effect of GetTranslation)
  723. //if ((nerrorid = Font(u).GetTranslation(this)) != 0) {
  724. if ((nerrorid = Font(u).GetTranslation(m_csoaAtlas)) != 0) {
  725. CString cstmp ;
  726. cstmp = Font(u).SourceName() ;
  727. LogConvInfo(abs(nerrorid), 1, &cstmp) ;
  728. if (nerrorid < 0)
  729. return ReportFileFailure(IDS_LoadFailure, cstmp);
  730. } ;
  731. // Generate the CTT/PFM mapping so we generate UFMs correctly
  732. if (!Font(u).Translation()) {
  733. /*
  734. For each model, check and see if this font is in its map.
  735. If it is, then add the CTT to the list used, and the model,
  736. as well.
  737. */
  738. CMapWordToDWord cmw2dCTT; // Used to count models per ID
  739. CWordArray cwaModel; // Models which used this font
  740. DWORD dwIgnore;
  741. for (unsigned uModel = 0; uModel < m_comdd.ModelCount(); uModel++)
  742. if (m_comdd.FontMap(uModel).Lookup(u + 1, dwIgnore)) {
  743. // This model needs to be remembered, along with the CTT
  744. cmw2dCTT[m_comdd.DefaultCTT(uModel)]++;
  745. cwaModel.Add((WORD)uModel);
  746. }
  747. if (!cmw2dCTT.Count()) {
  748. CString cstmp ;
  749. cstmp = Font(u).SourceName() ;
  750. LogConvInfo(IDS_UnusedFont, 1, &cstmp) ;
  751. continue;
  752. }
  753. if (cmw2dCTT.Count() == 1) {
  754. // Only one CTT ID was actually used.
  755. Font(u).SetTranslation(m_comdd.DefaultCTT(cwaModel[0]));
  756. continue; // We're done with this one
  757. }
  758. /*
  759. OK, this font has multiple CTTs in different models. Each
  760. will require a new UFM to be created. The IDs of the new UFMs
  761. need to be added to the set, the new defaults established, and
  762. a list of the font ID remapping needed for each model all need
  763. maintenance.
  764. */
  765. unsigned uGreatest = 0;
  766. for (POSITION pos = cmw2dCTT.GetStartPosition(); pos; ) {
  767. WORD widCTT;
  768. DWORD dwcUses;
  769. cmw2dCTT.GetNextAssoc(pos, widCTT, dwcUses);
  770. if (dwcUses > uGreatest) {
  771. uGreatest = dwcUses;
  772. Font(u).SetTranslation(widCTT);
  773. }
  774. }
  775. // The models that used the most common CTT will be dropped from
  776. // the list
  777. for (uModel = (unsigned) cwaModel.GetSize(); uModel--; )
  778. if (m_comdd.DefaultCTT(cwaModel[uModel]) == Font(u).Translation())
  779. cwaModel.RemoveAt(uModel);
  780. // Now, we create a new UFM for each CTT ID, and add the new index to
  781. // the mapping required for the each affected model.
  782. m_ucSynthesized += cmw2dCTT.Count() - 1;
  783. for (pos = cmw2dCTT.GetStartPosition(); pos; ) {
  784. WORD widCTT;
  785. DWORD dwcUses;
  786. cmw2dCTT.GetNextAssoc(pos, widCTT, dwcUses);
  787. if (widCTT == Font(u).Translation())
  788. continue; // This one has already been done.
  789. // Add a new font and make sure its file name is unique
  790. int nnewpos = m_csoaFonts.Add(new CFontInfo(Font(u), widCTT));
  791. for (unsigned ucomp = 0 ; ucomp < FontCount() ; ucomp++) {
  792. if ((unsigned) nnewpos == ucomp)
  793. continue ;
  794. // If a matching file title is found, try to make it unique
  795. // and restart the checking.
  796. if (!Font(nnewpos).FileTitle().CompareNoCase(Font(ucomp).FileTitle())) {
  797. Font(nnewpos).m_cfn.UniqueName(true, true, Font(nnewpos).m_cfn.Path()) ;
  798. ucomp = (unsigned) -1 ;
  799. } ;
  800. } ;
  801. for (uModel = (unsigned) cwaModel.GetSize(); uModel--; )
  802. if (m_comdd.DefaultCTT(cwaModel[uModel]) == widCTT) {
  803. m_comdd.NoteTranslation(cwaModel[uModel], u + 1,
  804. FontCount());
  805. cwaModel.RemoveAt(uModel);
  806. }
  807. }
  808. }
  809. }
  810. // Change the GTT ID in each CGlyphMap instance. Currently, these IDs are
  811. // set to whatever was used in the old RC file. The new RC file may
  812. // renumber the GTTs so the IDs in CGlyphMap instances should match what
  813. // will be in the RC file. When the RC file is written, the GTTs are
  814. // number consecutively starting at 1. (Don't change IDs that are <= 0.)
  815. for (u = 0 ; u < MapCount(); u++)
  816. if (GlyphTable(u).nGetRCID() > 0)
  817. GlyphTable(u).nSetRCID((int) (u + 1)) ;
  818. // Point each font at its associated GTT file, if there is one.
  819. for (u = 0 ; u < FontCount(); u++)
  820. for (unsigned uGTT = 0; uGTT < MapCount(); uGTT++)
  821. if (Font(u).Translation() == ((WORD) GlyphTable(uGTT).nGetRCID()))
  822. Font(u).SetTranslation(&GlyphTable(uGTT));
  823. Changed();
  824. return TRUE;
  825. }
  826. /******************************************************************************
  827. CDriverResources::ConvertGPCData
  828. This will handle the conversion of the GPC data to GPD format. It has to be
  829. done after the framework (especially the target directory) is created.
  830. ******************************************************************************/
  831. BOOL CDriverResources::ConvertGPCData(CProjectRecord& cprOwner,
  832. WORD wfGPDConvert)
  833. {
  834. // We've already loaded the GPC data, so now we just generate the files.
  835. unsigned umidx = -1 ; // Used to index Model
  836. unsigned ugpcidx = 0 ; // Used to indext GPC info
  837. int nsc ; // Each entries split code
  838. for (unsigned u = 0 ; u < m_comdd.ModelCount(); u++) {
  839. CString csModel = m_csaModelFileNames[u] ;
  840. // Skip this GPD if it was not selected by the user; ie, it does not
  841. // have a file name.
  842. //
  843. // Before the GPD can be skipped, the GPC info index may need to be
  844. // incremented. See below for a description of when this is done.
  845. if (csModel.IsEmpty()) {
  846. nsc = m_comdd.GetSplitCode(u) ;
  847. if (nsc == COldMiniDriverData::NoSplit)
  848. ugpcidx++ ;
  849. else if ((u + 1) < m_comdd.ModelCount()
  850. && m_comdd.GetSplitCode(u + 1) == COldMiniDriverData::NoSplit)
  851. ugpcidx++ ;
  852. else if ((u + 1) < m_comdd.ModelCount()
  853. && nsc == COldMiniDriverData::OtherSplit
  854. && m_comdd.GetSplitCode(u + 1) == COldMiniDriverData::FirstSplit)
  855. ugpcidx++ ;
  856. continue ;
  857. } ;
  858. // Add a new model node and increment the index used to reference them.
  859. m_csoaModels.Add(new CModelData) ;
  860. umidx++ ;
  861. // Set the node's file name and display name. Then load the other
  862. // pointers, etc needed for this node to perform correctly.
  863. if (!Model(umidx).SetFileName(cprOwner.TargetPath(Win2000) + _T("\\") +
  864. csModel))
  865. return FALSE;
  866. Model(umidx).NoteOwner(cprOwner);
  867. Model(umidx).EditorInfo(GPDTemplate());
  868. // Set the node's display name. Normally, a node's display name is
  869. // pulled from the string table. A separate array of names is used
  870. // to get the names of nodes that are based on GPC entries that
  871. // reference multiple models.
  872. if ((nsc = m_comdd.GetSplitCode(u)) == COldMiniDriverData::NoSplit)
  873. Model(umidx).Rename(m_cst[m_comdd.ModelName(u)]) ;
  874. else
  875. Model(umidx).Rename(m_comdd.SplitModelName(u)) ;
  876. // Convert and save the GPD.
  877. //if (!Model(umidx).Load(m_comdd.Image(), Name(), u + 1,
  878. if (!Model(umidx).Load(m_comdd.Image(), Name(), ugpcidx + 1,
  879. m_comdd.FontMap(u), wfGPDConvert) || !Model(umidx).Store())
  880. return ReportFileFailure(IDS_GPCConversionError, Model(umidx).Name());
  881. // Only increment the GPC index when
  882. // 1. The current entry does not reference multiple models
  883. // 2. The next entry does not reference multiple models
  884. // 3. The last model in the current entry is being processed
  885. // This is done to make sure that every model in an entry use the same
  886. // GPC index and that the index is kept in sync with each entry that
  887. // is processed.
  888. if (nsc == COldMiniDriverData::NoSplit)
  889. ugpcidx++ ;
  890. else if ((u + 1) < m_comdd.ModelCount()
  891. && m_comdd.GetSplitCode(u + 1) == COldMiniDriverData::NoSplit)
  892. ugpcidx++ ;
  893. else if ((u + 1) < m_comdd.ModelCount()
  894. && nsc == COldMiniDriverData::OtherSplit
  895. && m_comdd.GetSplitCode(u + 1) == COldMiniDriverData::FirstSplit)
  896. ugpcidx++ ;
  897. }
  898. Changed();
  899. return TRUE;
  900. }
  901. /******************************************************************************
  902. CDriverResources::GetGPDModelInfo
  903. Load the string arrays with with the GPD model names and file names.
  904. ******************************************************************************/
  905. BOOL CDriverResources::GetGPDModelInfo(CStringArray* pcsamodels,
  906. CStringArray* pcsafiles)
  907. {
  908. // If this is the first time this routine is called, initialize
  909. // m_csaModelFileNames.
  910. unsigned unummodels = m_comdd.ModelCount() ;
  911. if (unummodels != (unsigned) m_csaModelFileNames.GetSize()) {
  912. try {
  913. m_csaModelFileNames.SetSize(unummodels) ;
  914. }
  915. catch(CException* pce) { // Caller processes error
  916. pce -> Delete() ;
  917. return FALSE ;
  918. } ;
  919. } ;
  920. // Size the destination arrays
  921. try {
  922. pcsamodels->SetSize(unummodels) ;
  923. pcsafiles->SetSize(unummodels) ;
  924. }
  925. catch(CException* pce) { // Caller processes error
  926. pce -> Delete() ;
  927. return FALSE ;
  928. } ;
  929. // Loop through all of the GPDs and copy the information
  930. for (unsigned u = 0 ; u < m_comdd.ModelCount() ; u++) {
  931. if (m_comdd.GetSplitCode(u) == COldMiniDriverData::NoSplit)
  932. pcsamodels->SetAt(u, m_cst[m_comdd.ModelName(u)]) ;
  933. else
  934. pcsamodels->SetAt(u, m_comdd.SplitModelName(u)) ;
  935. pcsafiles->SetAt(u, m_csaModelFileNames[u]) ;
  936. } ;
  937. // All went well so...
  938. return TRUE ;
  939. }
  940. /******************************************************************************
  941. CDriverResources::SaveVerGPDFNames
  942. Save the GPD file names that entered into the GPD Selection page of the
  943. Conversion Wizard. If requested, the names will be verified, too. Two tests
  944. are made. First, the file names are checked to make sure they only contain
  945. valid file name characters. Second, the file names are checked to make sure
  946. they are all unique.
  947. Return -1 if all is ok. If an error was found, return the index of the first
  948. offending entry so that that entry can be highlighted on the GPD Selection
  949. page.
  950. ******************************************************************************/
  951. int CDriverResources::SaveVerGPDFNames(CStringArray& csafiles, bool bverifydata)
  952. {
  953. int numelts = (int)csafiles.GetSize() ;
  954. // Save the GPD file names
  955. for (int n = 0 ; n < numelts ; n++)
  956. m_csaModelFileNames[n] = csafiles[n] ;
  957. // Return "all is ok" if no verification is needed.
  958. if (!bverifydata)
  959. return -1 ;
  960. // Complain if any of the file names contains an illegal character and
  961. // return the index for that file.
  962. for (n = 0 ; n < numelts ; n++) {
  963. if (m_csaModelFileNames[n].FindOneOf(_T(":<>/\\\"|")) < 0)
  964. continue ;
  965. CString csmsg ;
  966. csmsg.Format(IDS_BadFileChars, m_csaModelFileNames[n]) ;
  967. AfxMessageBox(csmsg, MB_ICONEXCLAMATION) ;
  968. return n ;
  969. } ;
  970. // Complain if any of the file names are dups and return the index for that
  971. // file.
  972. for (n = 1 ; n < numelts ; n++) {
  973. // Skip this entry if it is empty.
  974. if (m_csaModelFileNames[n].IsEmpty())
  975. continue ;
  976. for (int m = 0 ; m < n ; m++) {
  977. // If these files don't match, continue checking.
  978. if (m_csaModelFileNames[n] != m_csaModelFileNames[m])
  979. continue ;
  980. // A duplicate was found so display an error message and return
  981. // its index.
  982. CString csmsg ;
  983. csmsg.Format(IDS_DupGPDFName, m, n, m_csaModelFileNames[n]) ;
  984. AfxMessageBox(csmsg, MB_ICONEXCLAMATION) ;
  985. return n ;
  986. } ;
  987. } ;
  988. // The file names passed the tests so...
  989. return -1 ;
  990. }
  991. /******************************************************************************
  992. CDriverResources::GenerateGPDFileNames
  993. Generate a file name (sans extension) for each GPD that doesn't already have
  994. a file name. This is done by taking the first two characters of the model
  995. name + the last 6 characters of the model name. Then make sure that each
  996. name is unique. (Note: This last phase might change one of the user's
  997. names.)
  998. ******************************************************************************/
  999. void CDriverResources::GenerateGPDFileNames(CStringArray& csamodels,
  1000. CStringArray& csafiles)
  1001. {
  1002. CString csfname ; // New file name
  1003. CString csmodel ; // Used to build file names
  1004. int npos ; // Positions of specific chars in a string
  1005. TCHAR tch ; // Unique character
  1006. // Loop through all of the file names looking for onces that are empty
  1007. int numelts = (int)csafiles.GetSize() ;
  1008. for (int n = 0 ; n < numelts ; n++) {
  1009. // Continue if the current file name is already set
  1010. if (!csafiles[n].IsEmpty())
  1011. continue ;
  1012. // The current model has no file name so generate one from the model
  1013. // name. Start by making a copy of the model name and remove all bad
  1014. // characters from it.
  1015. csmodel = csamodels[n] ;
  1016. while ((npos = csmodel.FindOneOf(_T(":<>/\\\"|"))) >= 0)
  1017. csmodel = csmodel.Left(npos) + csmodel.Mid(npos + 1) ;
  1018. // Add the first 2 characters of the model name (usually the first 2
  1019. // letters of the manufacturer's name) to the file name.
  1020. csfname = csmodel.Left(2) ;
  1021. // Remove the first space delimited word (usually manufacturer's name)
  1022. // from the model name.
  1023. if ((npos = csmodel.Find(_T(' '))) >= 0)
  1024. csmodel = csmodel.Mid(npos + 1) ;
  1025. // Use up to 6 characters from the right of the remaining model name
  1026. // characters to finish the file name. Then save the file name.
  1027. csfname += csmodel.Right(6) ;
  1028. csafiles[n] = csfname ;
  1029. } ;
  1030. // Now we need to make sure that the file names are unique. The algorithm
  1031. // used is much like the one in CBasicNode::UniqueName(). That function
  1032. // is not used because we aren't dealing with Workspace View nodes here.
  1033. bool bchanged = false ;
  1034. for (n = 1 ; n < numelts ; n++, bchanged = false) {
  1035. for (int m = 0 ; m < n ; m++) {
  1036. if (csafiles[n] != csafiles[m])
  1037. continue ;
  1038. // The current file name is not unique so it has to be changed.
  1039. // Begin by determine the 0-based length of the name.
  1040. npos = csafiles[n].GetLength() - 1 ;
  1041. // If the name has been changed before, use the last "unique"
  1042. // character to determine the new unique character. Then replace
  1043. // the old unique character with the new unique character.
  1044. if (bchanged) {
  1045. tch = csafiles[n].GetAt(npos) + 1 ;
  1046. if (tch == _T('{'))
  1047. tch = _T('0') ;
  1048. else if (tch == _T(':'))
  1049. tch = _T('a') ;
  1050. csafiles[n].SetAt(npos, tch) ;
  1051. // If the name has not been changed before, add a unique character
  1052. // to the end of the name if this won't make the name longer than
  1053. // 8 characters. Otherwise, replace the last character with the
  1054. // new unique character.
  1055. } else {
  1056. if (npos < 7)
  1057. csafiles[n] += _T("a") ;
  1058. else
  1059. csafiles[n].SetAt(npos, _T('a')) ;
  1060. } ;
  1061. // Note that this name has been changed and reset the inner loop
  1062. // counter so that the changed name will be rechecked against all
  1063. // of the file names it needs to be checked against.
  1064. bchanged = true ;
  1065. m = -1 ;
  1066. } ;
  1067. } ;
  1068. }
  1069. /******************************************************************************
  1070. CDriverResources::Generate
  1071. This member function generates the RC file for one of the target environments
  1072. ******************************************************************************/
  1073. BOOL CDriverResources::Generate(UINT ufTarget, LPCTSTR lpstrPath)
  1074. {
  1075. int nrcid ; // Holds a resource's ID
  1076. CString csFontPrefix, csTransPrefix, csFontLabel, csTransLabel;
  1077. unsigned ucTables = 0, ucFonts =
  1078. (ufTarget == Win2000) ? FontCount() : OriginalFontCount();
  1079. if (ufTarget == Win2000) {
  1080. csFontLabel = _T("RC_UFM");
  1081. csTransLabel = _T("RC_GTT");
  1082. }
  1083. else {
  1084. csFontLabel = _T("RC_FONT");
  1085. csTransLabel = _T("RC_TRANSTAB");
  1086. }
  1087. switch (ufTarget) {
  1088. case Win2000:
  1089. csFontPrefix = _TEXT("UFM");
  1090. csTransPrefix = _TEXT("GTT");
  1091. break;
  1092. case WinNT40:
  1093. case WinNT3x:
  1094. csFontPrefix = _TEXT("IFI");
  1095. csTransPrefix = _TEXT("RLE");
  1096. ucTables = 2;
  1097. break;
  1098. case Win95:
  1099. csFontPrefix = _TEXT("PFM");
  1100. csTransPrefix = _TEXT("CTT");
  1101. ucTables = 1;
  1102. break;
  1103. default:
  1104. _ASSERTE(FALSE); // This shouldn't happen
  1105. return FALSE;
  1106. }
  1107. // Create the RC file first.
  1108. CStdioFile csiof;
  1109. if (!csiof.Open(lpstrPath, CFile::modeCreate | CFile::modeWrite |
  1110. CFile::shareExclusive | CFile::typeText)) {
  1111. _ASSERTE(FALSE); // This shouldn't be possible
  1112. return FALSE;
  1113. }
  1114. // Write out our header- it identifies this tool as the source, and it
  1115. // will (eventually) include the Copyright and other strings used to
  1116. // customize the environment.
  1117. try {
  1118. CString cs, cs2 ;
  1119. cs.LoadString(IDS_RCCommentHdr1) ;
  1120. csiof.WriteString(cs) ;
  1121. cs.LoadString(IDS_RCCommentHdr2) ;
  1122. csiof.WriteString(cs) ;
  1123. cs.LoadString(IDS_RCCommentHdr3) ;
  1124. csiof.WriteString(cs) ;
  1125. //csiof.WriteString(_TEXT("/********************************************")
  1126. // _TEXT("**********************************\n\n"));
  1127. //csiof.WriteString(_T(" RC file generated by the Minidriver ")
  1128. // _T("Development Tool\n\n"));
  1129. //csiof.WriteString(_TEXT("*********************************************")
  1130. // _TEXT("*********************************/\n\n"));
  1131. // Write out the standard definition and include statements for Win2K
  1132. // style RC files.
  1133. ForceCommonRC(FALSE); // Don't use common.rc at all // raid 141064
  1134. if (ufTarget == Win2000) { // NT knows best. What do developers know?
  1135. cs.LoadString(IDS_StdIncludeFile1) ;
  1136. cs2.Format(IDS_IncStmt, cs) ;
  1137. csiof.WriteString(cs2) ;
  1138. if (m_bUseCommonRC) {
  1139. cs.LoadString(IDS_StdIncludeFile2) ;
  1140. cs2.Format(IDS_IncStmt, cs) ;
  1141. csiof.WriteString(cs2) ;
  1142. } ;
  1143. cs.LoadString(IDS_StdIncludeFile3) ;
  1144. cs2.Format(IDS_IncStmt, cs) ;
  1145. csiof.WriteString(cs2) ;
  1146. cs.LoadString(IDS_StdIncludeFile4) ;
  1147. cs2.Format(IDS_IncStmt, cs) ;
  1148. csiof.WriteString(cs2) ;
  1149. //csiof.WriteString(_T("#include <Minidrv.H>\n"));
  1150. //if (m_bUseCommonRC)
  1151. // csiof.WriteString(_T("#include <Common.RC>\n"));
  1152. //csiof.WriteString(_T("#include <Windows.H>\n"));
  1153. //csiof.WriteString(_T("#include <NTVerP.H>\n"));
  1154. // Add the version definitions to the RC file.
  1155. csiof.WriteString(_T("#define VER_FILETYPE VFT_DRV\n"));
  1156. csiof.WriteString(_T("#define VER_FILESUBTYPE VFT2_DRV_PRINTER\n"));
  1157. csiof.WriteString(_T("#define VER_FILEDESCRIPTION_STR \""));
  1158. csiof.WriteString(Name());
  1159. csiof.WriteString(_T(" Printer Driver\"\n"));
  1160. csiof.WriteString(_T("#define VER_INTERNALNAME_STR \""));
  1161. csiof.WriteString(Name().Left(8));
  1162. csiof.WriteString(_T(".dll\"\n"));
  1163. csiof.WriteString(_T("#define VER_ORIGINALFILENAME_STR \""));
  1164. csiof.WriteString(Name().Left(8));
  1165. csiof.WriteString(_T(".dll\"\n"));
  1166. // Source RC files often contain the same version definitions as
  1167. // those added above. Make sure they aren't added to the Win2K RC
  1168. // file twice by removing them from the definitions from the source
  1169. // file.
  1170. //
  1171. // If any new definitions are added in the section above, add a
  1172. // statement for that definition below.
  1173. RemUnneededRCDefine(_T("VER_FILETYPE")) ;
  1174. RemUnneededRCDefine(_T("VER_FILESUBTYPE")) ;
  1175. RemUnneededRCDefine(_T("VER_FILEDESCRIPTION_STR")) ;
  1176. RemUnneededRCDefine(_T("VER_INTERNALNAME_STR")) ;
  1177. RemUnneededRCDefine(_T("VER_ORIGINALFILENAME_STR")) ;
  1178. // Add include statement for common version info.
  1179. cs.LoadString(IDS_StdIncludeFile5) ;
  1180. cs2.Format(IDS_IncStmt, cs) ;
  1181. csiof.WriteString(cs2) ;
  1182. //csiof.WriteString(_T("#include \"common.ver\"\n"));
  1183. } ;
  1184. // Write out the rest (all if < NT 4) of the include statements.
  1185. /* raid 141064
  1186. for (unsigned u = 0; u < (unsigned) m_csaIncludes.GetSize(); u++) {
  1187. CString csTest = m_csaIncludes[u];
  1188. csTest.MakeLower();
  1189. if (m_csaIncludes[u].Find(_TEXT(".ver")) != -1)
  1190. continue;
  1191. csTest = _TEXT("#include ");
  1192. csTest += m_csaIncludes[u] + _TEXT('\n');
  1193. csiof.WriteString(csTest);
  1194. }
  1195. */
  1196. csiof.WriteString(_TEXT("\n"));
  1197. // Now, write out all of the #defines
  1198. for (unsigned u = 0; u < (unsigned) m_csaDefineNames.GetSize(); u++) {
  1199. CString csDefine;
  1200. csDefine.Format(_TEXT("#define %-32s %s\n"),
  1201. (LPCTSTR) m_csaDefineNames[u], (LPCTSTR) m_csaDefineValues[u]);
  1202. csiof.WriteString(csDefine);
  1203. }
  1204. csiof.WriteString(_TEXT("\n"));
  1205. // GPC tables
  1206. if (ufTarget != Win2000)
  1207. for (u = 0; u < ucTables; u++) {
  1208. CString csLine;
  1209. csLine.Format(_T("%-5u RC_TABLES PRELOAD MOVEABLE "), u + 1);
  1210. if (m_csaTables[u] != _T("NT"))
  1211. csLine += _T("\"");
  1212. csLine += m_csaTables[u] + _T(".GPC");
  1213. if (m_csaTables[u] != _T("NT"))
  1214. csLine += _T("\"");
  1215. csiof.WriteString(csLine + _T("\n"));
  1216. }
  1217. csiof.WriteString(_TEXT("\n"));
  1218. // Font tables
  1219. for (u = 0; u < ucFonts; u++) {
  1220. CString csLine;
  1221. // Get the RC ID from the font node. If the ID == -1, use the
  1222. // font's index as its ID.
  1223. if ((nrcid = Font(u).nGetRCID()) == -9999)
  1224. nrcid = u + 1 ;
  1225. #if defined(NOPOLLO)
  1226. csLine.Format(_TEXT("%-5u %s LOADONCALL DISCARDABLE \""),
  1227. nrcid, (LPCTSTR) csFontLabel);
  1228. csLine += csFontPrefix + _TEXT('\\') + Font(u).FileTitle() +
  1229. _TEXT('.') + csFontPrefix + _TEXT("\"\n");
  1230. #else
  1231. csLine.Format(_TEXT("%-5u %s LOADONCALL DISCARDABLE "),
  1232. nrcid, (LPCTSTR) csFontLabel);
  1233. csLine += csFontPrefix + _TEXT('\\') + Font(u).FileTitle() +
  1234. _TEXT('.') + csFontPrefix + _TEXT("\n");
  1235. #endif
  1236. csiof.WriteString(csLine);
  1237. }
  1238. csiof.WriteString(_TEXT("\n"));
  1239. // Mapping tables
  1240. for (u = 0; u < MapCount(); u++) {
  1241. CString csLine;
  1242. // Get the RC ID from the GTT node. If the ID == -1, use the
  1243. // GTT's index as its ID.
  1244. if ((nrcid = GlyphTable(u).nGetRCID()) == -1)
  1245. nrcid = u + 1 ;
  1246. #if defined(NOPOLLO)
  1247. csLine.Format(_TEXT("%-5u %s LOADONCALL MOVEABLE \""),
  1248. nrcid, (LPCTSTR) csTransLabel);
  1249. csLine += csTransPrefix + _TEXT('\\') + GlyphTable(u).FileTitle() +
  1250. _TEXT('.') + csTransPrefix + _TEXT("\"\n");
  1251. #else
  1252. csLine.Format(_TEXT("%-5u %s LOADONCALL MOVEABLE "),
  1253. nrcid, (LPCTSTR) csTransLabel);
  1254. csLine += csTransPrefix + _TEXT('\\') + GlyphTable(u).FileTitle() +
  1255. _TEXT('.') + csTransPrefix + _TEXT("\n");
  1256. #endif
  1257. csiof.WriteString(csLine);
  1258. }
  1259. csiof.WriteString(_TEXT("\n"));
  1260. int n ;
  1261. n = m_cst.Count() ;
  1262. // Time to do the String Table
  1263. if (m_cst.Count()) {
  1264. csiof.WriteString(_TEXT("STRINGTABLE\n BEGIN\n"));
  1265. for (u = 0; u < m_cst.Count(); u++) {
  1266. WORD wKey;
  1267. CString csValue, csLine;
  1268. m_cst.Details(u, wKey, csValue);
  1269. csLine.Format(_TEXT(" %-5u \""), wKey);
  1270. csLine += csValue + _TEXT("\"\n");
  1271. csiof.WriteString(csLine);
  1272. }
  1273. csiof.WriteString(_TEXT(" END\n\n"));
  1274. }
  1275. // Now, write out any .ver includes
  1276. if (ufTarget != Win2000) // Already hardcoded them here
  1277. for (u = 0; u < (unsigned) m_csaIncludes.GetSize(); u++) {
  1278. CString csTest = m_csaIncludes[u];
  1279. csTest.MakeLower();
  1280. if (m_csaIncludes[u].Find(_TEXT(".ver")) == -1)
  1281. continue;
  1282. csTest = _TEXT("#include ");
  1283. csTest += m_csaIncludes[u] + _TEXT('\n');
  1284. csiof.WriteString(csTest);
  1285. }
  1286. csiof.WriteString(_TEXT("\n"));
  1287. // Now, any of the remnants
  1288. // RAID 3449 kill below 2 line
  1289. // for (u = 0; u < (unsigned) m_csaRemnants.GetSize(); u++)
  1290. // csiof.WriteString(m_csaRemnants[u] + TEXT('\n'));
  1291. }
  1292. catch (CException* pce) {
  1293. pce -> ReportError();
  1294. pce -> Delete();
  1295. return FALSE;
  1296. }
  1297. return TRUE;
  1298. }
  1299. /******************************************************************************
  1300. CDriverResources::RemUnneededRCDefine
  1301. Remove the specified definition from the array of definitions that will be
  1302. added to the definitions in the output RC file.
  1303. ******************************************************************************/
  1304. void CDriverResources::RemUnneededRCDefine(LPCTSTR strdefname)
  1305. {
  1306. for (unsigned u = 0 ; u < (unsigned) m_csaDefineNames.GetSize() ; u++) {
  1307. if (m_csaDefineNames[u].CompareNoCase(strdefname) != 0)
  1308. continue ;
  1309. m_csaDefineNames.RemoveAt(u) ;
  1310. m_csaDefineValues.RemoveAt(u) ;
  1311. return ;
  1312. } ;
  1313. }
  1314. /******************************************************************************
  1315. CDriverResources::RemUnneededRCInclude
  1316. Remove the specified include file from the array of include files that will
  1317. be added to the include statements in the output RC file.
  1318. ******************************************************************************/
  1319. void CDriverResources::RemUnneededRCInclude(LPCTSTR strincname)
  1320. {
  1321. for (unsigned u = 0 ; u < (unsigned) m_csaIncludes.GetSize() ; u++) {
  1322. //TRACE("Inc[%d] = '%s' incname = '%s'\n", u, m_csaIncludes[u], strincname) ;
  1323. if (m_csaIncludes[u].CompareNoCase(strincname) != 0)
  1324. continue ;
  1325. m_csaIncludes.RemoveAt(u) ;
  1326. return ;
  1327. } ;
  1328. }
  1329. /******************************************************************************
  1330. CDriverResources::ReparseRCFile
  1331. Read in the new RC file, parse its statements, and update all of the internal
  1332. data structures with the information from the new RC file.
  1333. ******************************************************************************/
  1334. bool CDriverResources::ReparseRCFile(CString& csrcfspec)
  1335. {
  1336. CWaitCursor cwc ; // Just in case this takes a while...
  1337. CString cs, cs2 ;
  1338. // Load the RC file and save its data into data specific arrays.
  1339. CStringTable cstfonts, cstmaps ;
  1340. CStringArray csa ; // Use this instead of m_csaTables
  1341. if (!LoadRCFile(csrcfspec, m_csaDefineNames, m_csaDefineValues,
  1342. m_csaIncludes, m_csaRemnants, csa, m_cst, cstfonts,
  1343. cstmaps, Win2000)) {
  1344. cs.LoadString(IDS_RCRepFailed1) ;
  1345. AfxMessageBox(cs, MB_ICONEXCLAMATION) ;
  1346. return false ;
  1347. } ;
  1348. // LoadRCFile() will have correctly reloaded m_csaDefineNames,
  1349. // m_csaDefineValues, and m_csaIncludes. Nothing needs to be done with csa.
  1350. // Now, the rest of the data needs to be processed. Start by finding and
  1351. // removing the standard comment header from the remnants array.
  1352. cs.LoadString(IDS_RCCommentHdr2) ;
  1353. cs.TrimLeft() ;
  1354. cs.TrimRight() ;
  1355. CString csrem ;
  1356. for (int n = 0 ; n < m_csaRemnants.GetSize() ; n++) {
  1357. //TRACE("Rem[%d] = '%s' hdr2 = '%s'\n", n, m_csaRemnants[n], cs) ;
  1358. csrem = m_csaRemnants[n] ;
  1359. csrem.TrimLeft() ;
  1360. csrem.TrimRight() ;
  1361. if (csrem == cs)
  1362. break ;
  1363. } ;
  1364. if (n < m_csaRemnants.GetSize()) {
  1365. n -= 2 ;
  1366. int nc = n + 6 ;
  1367. m_csaRemnants.RemoveAt(n, nc) ;
  1368. } ;
  1369. // Find and remove the standard include files from m_csaIncludes.
  1370. cs.LoadString(IDS_StdIncludeFile1) ;
  1371. RemUnneededRCInclude(cs) ;
  1372. cs.LoadString(IDS_StdIncludeFile2) ;
  1373. RemUnneededRCInclude(cs) ;
  1374. cs.LoadString(IDS_StdIncludeFile3) ;
  1375. RemUnneededRCInclude(cs) ;
  1376. cs.LoadString(IDS_StdIncludeFile4) ;
  1377. RemUnneededRCInclude(cs) ;
  1378. cs.LoadString(IDS_StdIncludeFile5) ;
  1379. RemUnneededRCInclude(cs) ;
  1380. cs.LoadString(IDS_OldIncludeFile1) ;
  1381. RemUnneededRCInclude(cs) ;
  1382. // Get the path to the RC file.
  1383. CString csrcpath ;
  1384. csrcpath = csrcfspec.Left(csrcfspec.ReverseFind(_T('\\')) + 1) ;
  1385. // Update the old/current GTT list with data from the new GTT list.
  1386. CUIntArray cuaboldfound, cuabnewfound ;
  1387. int nc ; // Count of elements in new list.
  1388. UpdateResourceList(cstmaps, m_csoaAtlas, cuaboldfound, cuabnewfound,
  1389. csrcpath, nc) ;
  1390. // GTT List Update Step 3: Update the old list with data for items from
  1391. // the new list whenever a new list item was not found in the old list.
  1392. CGlyphMap* pcgm ;
  1393. WORD wkey ;
  1394. for (n = 0 ; n < nc ; n++) {
  1395. if (cuabnewfound[n])
  1396. continue ;
  1397. pcgm = new CGlyphMap ;
  1398. cstmaps.Details(n, wkey, cs) ;
  1399. pcgm->nSetRCID((int) wkey) ; // Set resource handle
  1400. UpdateResourceItem(pcgm, csrcpath, wkey, cs, FNT_GTTS) ;
  1401. m_csoaAtlas.InsertAt(n, pcgm) ;
  1402. } ;
  1403. // Update the old/current UFM list with data from the new UFM list.
  1404. UpdateResourceList(cstfonts, m_csoaFonts, cuaboldfound, cuabnewfound,
  1405. csrcpath, nc) ;
  1406. // UFM List Update Step 3: Update the old list with data for items from
  1407. // the new list whenever a new list item was not found in the old list.
  1408. CFontInfo* pcfi ;
  1409. for (n = 0 ; n < nc ; n++) {
  1410. if (cuabnewfound[n])
  1411. continue ;
  1412. pcfi = new CFontInfo ;
  1413. cstfonts.Details(n, wkey, cs) ;
  1414. UpdateResourceItem(pcfi, csrcpath, wkey, cs, FNT_UFMS) ;
  1415. m_csoaFonts.InsertAt(n, pcfi) ;
  1416. } ;
  1417. // All went well so...
  1418. return true ;
  1419. }
  1420. /******************************************************************************
  1421. CDriverResources::UpdateResourceList
  1422. Three steps are needed to update a resource list. Two of those steps are
  1423. performed in this version of UpdateResourceList().
  1424. Step 1: Compare the old and new lists. Whenever a new resource file matches
  1425. an old one, update the RC ID when necessary and mark them both as being found.
  1426. Step 2: Remove any of the old resource class instances that were not found in
  1427. Step 1.
  1428. ******************************************************************************/
  1429. void CDriverResources::UpdateResourceList(CStringTable& cst, CSafeObArray& csoa,
  1430. CUIntArray& cuaboldfound,
  1431. CUIntArray& cuabnewfound,
  1432. CString& csrcpath, int& nc)
  1433. {
  1434. // Declare and initialize the variables that will control the loops, etc.
  1435. nc = cst.Count() ;
  1436. cuabnewfound.RemoveAll() ;
  1437. cuabnewfound.SetSize(nc) ;
  1438. int ncold = csoa.GetSize() ;
  1439. cuaboldfound.RemoveAll() ;
  1440. cuaboldfound.SetSize(ncold) ;
  1441. WORD wkey ;
  1442. CString cs ;
  1443. // Try to find each new resource in the list of old resources.
  1444. for (int n = 0 ; n < nc ; n++) {
  1445. cst.Details(n, wkey, cs) ;
  1446. cs = csrcpath + cs ;
  1447. for (int n2 = 0 ; n2 < ncold ; n2++) {
  1448. //TRACE("+++ Resource path = %s\n", ((CProjectNode *) csoa[n2])->FileName()) ;
  1449. if (cs == ((CProjectNode *) csoa[n2])->FileName()) {
  1450. // Update the matching old resource's ID if it isn't the same
  1451. // as the new one.
  1452. if (wkey != ((CProjectNode *) csoa[n2])->nGetRCID())
  1453. ((CProjectNode *) csoa[n2])->nSetRCID(wkey) ;
  1454. // Note that a match for the old and new resources was found.
  1455. cuabnewfound[n] = (unsigned) true ;
  1456. cuaboldfound[n2] = (unsigned) true ;
  1457. break ;
  1458. } ;
  1459. } ;
  1460. } ;
  1461. // Remove the old resource class instances that are no longer in the new
  1462. // list.
  1463. for (n = ncold - 1 ; n >= 0 ; n--) {
  1464. if (cuaboldfound[n])
  1465. continue ;
  1466. csoa.RemoveAt(n) ;
  1467. } ;
  1468. }
  1469. /******************************************************************************
  1470. CDriverResources::UpdateResourceItem
  1471. This function does most of the work for the third resource update step. It
  1472. initializes new resources that are going to be added to the resource list.
  1473. Essentially, it does what the serialize routines do.
  1474. ******************************************************************************/
  1475. void CDriverResources::UpdateResourceItem(CProjectNode* pcpn, CString& csrcpath,
  1476. WORD wkey, CString& cs,
  1477. FIXEDNODETYPE fnt)
  1478. {
  1479. // Build the full filespec for the resource, its name, and its path.
  1480. CString csfspec, csname, cspath ;
  1481. csfspec = csrcpath + cs ;
  1482. int n = csfspec.ReverseFind(_T('\\')) ;
  1483. cspath = csfspec.Left(n + 1) ;
  1484. csname = csfspec.Mid(n + 1) ;
  1485. n = csname.ReverseFind(_T('.')) ;
  1486. if (n >= 0)
  1487. csname = csname.Left(n) ;
  1488. // Use the file name (no extension) as the default resource name.
  1489. CString csfs ;
  1490. pcpn->Rename(csname) ;
  1491. csfs = pcpn->Name() ;
  1492. // Set the file node's path and file name.
  1493. pcpn->m_cfn.SetPathAndName(cspath, csname) ;
  1494. csfs = pcpn->FileName() ;
  1495. // Set the rc id and resource type.
  1496. pcpn->nSetRCID(wkey) ;
  1497. pcpn->m_crinRCID.fntSetType(FNT_GTTS) ;
  1498. }
  1499. /******************************************************************************
  1500. CDriverResources::Fill
  1501. This is a CProjectNode override- it fills in the material relevant to this
  1502. driver.
  1503. ******************************************************************************/
  1504. void CDriverResources::Fill(CTreeCtrl *pctcWhere, CProjectRecord& cpr)
  1505. {
  1506. CWaitCursor cwc;
  1507. NoteOwner(cpr);
  1508. SetWorkspace(this);
  1509. CBasicNode::Fill(pctcWhere);
  1510. // Add the resources node
  1511. m_cfnResources.Fill(pctcWhere, m_hti) ;
  1512. m_cfnResources.NoteOwner(cpr) ;
  1513. // Fill in the font information
  1514. m_cfnFonts.NoteOwner(cpr);
  1515. for (unsigned u = 0; u < FontCount(); u++) {
  1516. Font(u).SetWorkspace(this);
  1517. Font(u).EditorInfo(FontTemplate());
  1518. }
  1519. m_cfnFonts.Fill(pctcWhere, m_cfnResources.Handle());
  1520. m_cfnFonts.SetWorkspace(this);
  1521. // Fill in the glyph map information
  1522. m_cfnAtlas.NoteOwner(cpr);
  1523. for (u = 0; u < MapCount(); u++) {
  1524. GlyphTable(u).SetWorkspace(this);
  1525. GlyphTable(u).EditorInfo(GlyphMapDocTemplate());
  1526. }
  1527. m_cfnAtlas.Fill(pctcWhere, m_cfnResources.Handle());
  1528. m_cfnAtlas.SetWorkspace(this);
  1529. // Add the strings node
  1530. m_csnStrings.Fill(pctcWhere, m_cfnResources.Handle());
  1531. m_csnStrings.NoteOwner(cpr);
  1532. m_csnStrings.SetWorkspace(this);
  1533. // Fill in the model data information.
  1534. for (u = 0; u < Models(); u++) {
  1535. Model(u).SetWorkspace(this);
  1536. Model(u).EditorInfo(GPDTemplate());
  1537. }
  1538. m_cfnModels.NoteOwner(cpr);
  1539. m_cfnModels.Fill(pctcWhere, m_hti);
  1540. m_cfnModels.SetWorkspace(this);
  1541. // Expand the first couple of levels of the tree
  1542. pctcWhere -> Expand(m_hti, TVE_EXPAND);
  1543. pctcWhere -> Expand(m_cfnResources.Handle(), TVE_EXPAND);
  1544. // Load the font and GTT files, then map them together. Also load any
  1545. // predefined tables now.
  1546. for (u = 0; u < MapCount(); u++)
  1547. GlyphTable(u).Load();
  1548. for (u = 0; u < FontCount(); u++)
  1549. LinkAndLoadFont(Font(u), true) ;
  1550. // Save a copy of the Win2K path in this class because the path is easier to
  1551. // get and use when it is in this class.
  1552. m_csW2000Path = cpr.GetW2000Path() ;
  1553. }
  1554. /******************************************************************************
  1555. CDriverResources::LinkAndLoadFont
  1556. ******************************************************************************/
  1557. // raid 0003
  1558. void CDriverResources::LinkAndLoadFont(CFontInfo& cfi, bool bworkspaceload, bool bonlyglyph)
  1559. {
  1560. CGlyphMap* pcgm ;
  1561. // If this is part of a workspace load (ie, called from Fill()), load the
  1562. // font the first time to get the GTT ID and code page number in the font.
  1563. if (bworkspaceload)
  1564. cfi.Load(true) ;
  1565. // Now that the font has been loaded, use the data in it to see if it
  1566. // references a predefined GTT.
  1567. pcgm = CGlyphMap::Public(cfi.Translation(), (WORD) cfi.m_ulDefaultCodepage,
  1568. ((CProjectRecord*) GetOwner())->GetDefaultCodePage(),
  1569. cfi.GetFirst(), cfi.GetLast()) ;
  1570. // If a GTT was found, save a pointer to it in the font's class. Otherwise,
  1571. // look for the font's GTT amongst the GTTs in the font's workspace. Again,
  1572. // save a pointer to the GTT if a match is found.
  1573. if (pcgm)
  1574. cfi.SetTranslation(pcgm) ;
  1575. else {
  1576. //TRACE( "UFM = %s GTT ID = %d\n", cfi.Name(), cfi.Translation()) ;
  1577. for (unsigned uGTT = 0; uGTT < MapCount(); uGTT++) {
  1578. //TRACE("Checking %dth ID = %d Name = %s\n", uGTT+1,
  1579. // GlyphTable(uGTT).nGetRCID(), GlyphTable(uGTT).Name()) ;
  1580. if (cfi.Translation() == ((WORD) GlyphTable(uGTT).nGetRCID())) {
  1581. cfi.SetTranslation(&GlyphTable(uGTT)) ;
  1582. break ;
  1583. } ;
  1584. } ;
  1585. } ;
  1586. if (bonlyglyph && cfi.m_pcgmTranslation != NULL)
  1587. return ;
  1588. // Load the font again if we now know the linkage; ie the GTT/CP.
  1589. // Otherwise, warn the user. (The font is loaded again because parts of
  1590. // the UFM cannot be correctly loaded until the GTT is available.)
  1591. if (cfi.m_pcgmTranslation != NULL)
  1592. cfi.Load(true) ;
  1593. else {
  1594. cfi.SetNoGTTCP(true) ;
  1595. CString csmsg ;
  1596. csmsg.Format(IDS_NoGTTForUFMError, cfi.Name()) ;
  1597. AfxMessageBox(csmsg, MB_ICONEXCLAMATION) ;
  1598. } ;
  1599. }
  1600. /******************************************************************************
  1601. CDriverResources::WorkspaceChecker
  1602. Check the workspace for completeness and tidiness. The following checks are
  1603. made:
  1604. 1. All GTTs referenced in the UFMs exist.
  1605. 2. All GTTs are referenced by at least one UFM.
  1606. 3. All UFMs referenced in the GPDs exist.
  1607. 4. All UFMs are referenced by at least one GPD.
  1608. 5. All strings referenced in the GPDs exist.
  1609. 6. All strings are referenced by at least one GPD.
  1610. 7. All GPD model names are unique.
  1611. 8. All GPD file names are unique.
  1612. Workspaces that pass tests 1, 3, 5, 7, and 8 are considered to be complete.
  1613. These test must be passed before the driver is built and used. Workspaces
  1614. that pass tests 2, 4, and 6 are considered to be tidy. Failure to pass these
  1615. tests generate warnings.
  1616. ******************************************************************************/
  1617. bool CDriverResources::WorkspaceChecker(bool bclosing)
  1618. {
  1619. bool bwsproblem ; // True iff an error or warning was found
  1620. // This might take a while, so...
  1621. CWaitCursor cwc ;
  1622. // First reset any existing error window for this workspace to make sure
  1623. // that the window won't contain duplicate error/warning messages. Then
  1624. // initialize the error found flag.
  1625. ResetWorkspaceErrorWindow(bclosing) ;
  1626. bwsproblem = false ;
  1627. // Perform the GTT related checks (1 & 2)
  1628. DoGTTWorkspaceChecks(bclosing, bwsproblem) ;
  1629. if (m_bIgnoreChecks) // Just return if further checking should be
  1630. return false ; // skipped.
  1631. // Perform the GPD related checks (7 & 8)
  1632. DoGPDWorkspaceChecks(bclosing, bwsproblem) ;
  1633. if (m_bIgnoreChecks) // Just return if further checking should be
  1634. return false ; // skipped.
  1635. // Perform the UFM related checks (3 & 4)
  1636. DoUFMWorkspaceChecks(bclosing, bwsproblem) ;
  1637. if (m_bIgnoreChecks) // Just return if further checking should be
  1638. return false ; // skipped.
  1639. // Perform the string related checks (5 & 6). This check should only be
  1640. // done if the workspace contains RC IDs for the strings that we want to
  1641. // check.
  1642. CProjectRecord* pcpr = (CProjectRecord *) m_pcdOwner ;
  1643. if (pcpr != NULL && pcpr->GetMDWVersion() > MDW_DEFAULT_VERSION)
  1644. DoStringWorkspaceChecks(bclosing, bwsproblem) ;
  1645. if (m_bIgnoreChecks) // Just return if further checking should be
  1646. return false ; // skipped.
  1647. // Tell the user if no problems were found. Only do this when the
  1648. // workspace is not closing.
  1649. if (!bwsproblem && !bclosing) {
  1650. CString csmsg ;
  1651. csmsg.Format(IDS_NoWSProblems, Name()) ;
  1652. AfxMessageBox(csmsg) ;
  1653. } ;
  1654. // Let the caller know if any problems were found.
  1655. return bwsproblem ;
  1656. }
  1657. /******************************************************************************
  1658. CDriverResources::DoGTTWorkspaceChecks
  1659. The following checks are made:
  1660. 1. All GTTs referenced in the UFMs exist.
  1661. 2. All GTTs are referenced by at least one UFM.
  1662. ******************************************************************************/
  1663. void CDriverResources::DoGTTWorkspaceChecks(bool bclosing, bool& bwsproblem)
  1664. {
  1665. short srcid ; // Current RC ID being checked
  1666. unsigned ucount ; // Count of nodes, etc processed in a loop
  1667. unsigned ucount2 ; // Count of nodes, etc processed in a loop
  1668. unsigned u, u2 ; // Loop counters
  1669. CString csmsg ; // Error or warning message
  1670. CGlyphMap* pcgm ; // Used to streamline code
  1671. CFontInfo* pcfi ; // Used to streamline code
  1672. // Clear the referenced flag in each GTT node
  1673. for (ucount = MapCount(), u = 0 ; u < ucount ; u++)
  1674. GlyphTable(u).ClearRefFlag() ;
  1675. // Completeness Check #1
  1676. // Check each UFM to make sure that the GTT it references, exists. This is
  1677. // done by checking the GTT RC ID in each UFM against all of the GTT RC IDs
  1678. // to see if a match is found.
  1679. for (ucount = FontCount(), u = 0 ; u < ucount ; u++) {
  1680. pcfi = &Font(u) ;
  1681. // Get the GTT RC ID referenced in the current UFM. Continue if the ID
  1682. // is one of the special GTT IDs (-1 to -18).
  1683. srcid = pcfi->Translation() ;
  1684. if (srcid >= CGlyphMap::Wansung && srcid <= CGlyphMap::CodePage437)
  1685. continue ;
  1686. // Try to find a matching GTT ID. If one is found, mark that GTT as
  1687. // being referenced.
  1688. for (ucount2 = MapCount(), u2 = 0 ; u2 < ucount2 ; u2++) {
  1689. if (srcid == GlyphTable(u2).nGetRCID()) {
  1690. GlyphTable(u2).SetRefFlag() ;
  1691. break ;
  1692. } ;
  1693. } ;
  1694. // If the GTT was not found, format and post an error message. Also,
  1695. // set the flag indicating that an error has occurred.
  1696. if (u2 >= ucount2) {
  1697. if (IgnoreChecksWhenClosing(bclosing))
  1698. return ;
  1699. if(srcid == 0) //RAID 18518
  1700. csmsg.Format(IDS_UFMCompWarning, pcfi->Name(), srcid) ;
  1701. else //END RAID
  1702. csmsg.Format(IDS_UFMCompError, pcfi->Name(), srcid) ;
  1703. PostWSCheckingMessage(csmsg, (CProjectNode *) pcfi) ;
  1704. bwsproblem = true ;
  1705. } ;
  1706. } ;
  1707. // Tidiness Check #2
  1708. // Each GTT that is referenced by a UFM was marked above. Now we need to
  1709. // find out if any GTT is unreferenced. Post a warning message for each
  1710. // unreferenced GTT.
  1711. for (ucount = MapCount(), u = 0 ; u < ucount ; u++) {
  1712. pcgm = &GlyphTable(u) ;
  1713. if (!pcgm->GetRefFlag()) {
  1714. if (IgnoreChecksWhenClosing(bclosing))
  1715. return ;
  1716. csmsg.Format(IDS_GTTTidyWarning, pcgm->Name(), pcgm->nGetRCID()) ;
  1717. PostWSCheckingMessage(csmsg, (CProjectNode *) pcgm) ;
  1718. } ;
  1719. } ;
  1720. }
  1721. void CDriverResources::DoUFMWorkspaceChecks(bool bclosing, bool& bwsproblem)
  1722. {
  1723. int nrcid ; // Current RC ID being checked
  1724. unsigned ucount ; // Count of nodes, etc processed in a loop
  1725. unsigned ucount2 ; // Count of nodes, etc processed in a loop
  1726. unsigned ucount3 ; // Count of nodes, etc processed in a loop
  1727. unsigned u, u2, u3 ; // Loop counters
  1728. CString csmsg ; // Error or warning message
  1729. CFontInfo* pcfi ; // Used to streamline code
  1730. CModelData* pcmd ; // Used to streamline code
  1731. // Clear the referenced flag in each UFM
  1732. for (ucount = FontCount(), u = 0 ; u < ucount ; u++)
  1733. Font(u).ClearRefFlag() ;
  1734. // Completeness Check #3
  1735. // Check to see if all of the UFMs referenced by each GPD exist in the
  1736. // workspace.
  1737. for (ucount = Models(), u = 0; u < ucount ; u++) {
  1738. pcmd = &Model(u) ;
  1739. // Update the list of UFMs in the GPD. This may fail. If it does,
  1740. // post an error message explaining the problem and how to fix it.
  1741. // Then skip further processing of this GPD.
  1742. if (!pcmd->UpdateResIDs(true)) {
  1743. if (IgnoreChecksWhenClosing(bclosing))
  1744. return ;
  1745. csmsg.Format(IDS_BadGPDError, pcmd->Name()) ;
  1746. PostWSCheckingMessage(csmsg, (CProjectNode *) pcmd) ;
  1747. bwsproblem = true ;
  1748. continue ;
  1749. } ;
  1750. // Check to see if each UFM referenced by the GPD is in the workspace.
  1751. for (ucount2 = pcmd->NumUFMsInGPD(), u2 = 0 ; u2 < ucount2 ; u2++) {
  1752. // Skip this UFM if it is 0x7fffffff. That ID has a special
  1753. // meaning.
  1754. if ((nrcid = pcmd->GetUFMRCID(u2)) == 0x7fffffff || nrcid < 0
  1755. || nrcid >= 32768)
  1756. continue ;
  1757. // Try to find a UFM in the workspace that matches the current ID
  1758. // from the GPD. If one is found, mark that UFM as being
  1759. // referenced.
  1760. for (ucount3 = FontCount(), u3 = 0 ; u3 < ucount3 ; u3++) {
  1761. if (nrcid == Font(u3).nGetRCID()) {
  1762. Font(u3).SetRefFlag() ;
  1763. break ;
  1764. } ;
  1765. } ;
  1766. // If the UFM was not found, format and post an error message.
  1767. // Also, set the flag indicating that an error has occurred.
  1768. if (u3 >= ucount3) {
  1769. if (IgnoreChecksWhenClosing(bclosing))
  1770. return ;
  1771. csmsg.Format(IDS_GPDUFMCompError, pcmd->Name(), nrcid) ;
  1772. PostWSCheckingMessage(csmsg, (CProjectNode *) pcmd) ;
  1773. bwsproblem = true ;
  1774. } ;
  1775. } ;
  1776. } ;
  1777. // Tidiness Check #4
  1778. // Each UFM that is referenced by a GPD was marked above. Now we need to
  1779. // find out if any UFM is unreferenced. Post a warning message for each
  1780. // unreferenced UFM.
  1781. for (ucount = FontCount(), u = 0 ; u < ucount ; u++) {
  1782. pcfi = &Font(u) ;
  1783. if (!pcfi->GetRefFlag()) {
  1784. if (IgnoreChecksWhenClosing(bclosing))
  1785. return ;
  1786. csmsg.Format(IDS_UFMTidyWarning, pcfi->Name(), pcfi->nGetRCID()) ;
  1787. PostWSCheckingMessage(csmsg, (CProjectNode *) pcfi) ;
  1788. } ;
  1789. } ;
  1790. }
  1791. /******************************************************************************
  1792. CDriverResources::DoStringWorkspaceChecks
  1793. The following checks are made:
  1794. 5. All strings referenced in the GPDs exist.
  1795. 6. All strings are referenced by at least one GPD.
  1796. ******************************************************************************/
  1797. void CDriverResources::DoStringWorkspaceChecks(bool bclosing, bool& bwsproblem)
  1798. {
  1799. int nrcid ; // Current RC ID being checked
  1800. unsigned ucount ; // Count of nodes, etc processed in a loop
  1801. unsigned ucount2 ; // Count of nodes, etc processed in a loop
  1802. unsigned ucount3 ; // Count of nodes, etc processed in a loop
  1803. unsigned u, u2, u3 ; // Loop counters
  1804. CString csmsg ; // Error or warning message
  1805. CModelData* pcmd ; // Used to streamline code
  1806. WORD wkey ; // String RC ID
  1807. CString csstr ; // String associated with wkey & other strings
  1808. // Clear the referenced flags for each of the strings in the table
  1809. m_cst.InitRefFlags() ;
  1810. // Completeness Check #5
  1811. // Check to see if all of the strings referenced by each GPD exist in the
  1812. // workspace.
  1813. for (ucount = Models(), u = 0; u < ucount ; u++) {
  1814. pcmd = &Model(u) ;
  1815. // Update the list of strings in the GPD. This may fail. If it does,
  1816. // post an error message explaining the problem and how to fix it.
  1817. // Then skip further processing of this GPD.
  1818. if (!pcmd->UpdateResIDs(false)) {
  1819. if (IgnoreChecksWhenClosing(bclosing))
  1820. return ;
  1821. csmsg.Format(IDS_BadGPDError, pcmd->Name()) ;
  1822. PostWSCheckingMessage(csmsg, (CProjectNode *) pcmd) ;
  1823. bwsproblem = true ;
  1824. continue ;
  1825. } ;
  1826. // Check to see if each string referenced by the GPD is in the
  1827. // workspace.
  1828. for (ucount2 = pcmd->NumStringsInGPD(), u2 = 0 ; u2 < ucount2 ; u2++) {
  1829. // Get the current string ID from the GPD.
  1830. nrcid = pcmd->GetStringRCID(u2) ;
  1831. // Skip this ID if it is 0x7fffffff or in the range of IDs in
  1832. // common.rc or the ID comes from a resource DLL or the ID is 0
  1833. // because 0 IDs are just placeholders for constant strings in the
  1834. // GPD.
  1835. if (nrcid == 0x7fffffff
  1836. || (nrcid >= FIRSTCOMMONRCSTRID && nrcid <= LASTCOMMONRCSTRID)
  1837. || nrcid >= 65536 || nrcid == 0)
  1838. continue ;
  1839. // Try to find a string in the workspace that matches the current
  1840. // ID from the GPD. If one is found, mark that string as being
  1841. // referenced.
  1842. for (ucount3 = m_cst.Count(), u3 = 0 ; u3 < ucount3 ; u3++) {
  1843. m_cst.Details(u3, wkey, csstr) ;
  1844. if (nrcid == wkey) {
  1845. m_cst.SetRefFlag(u3) ;
  1846. break ;
  1847. } ;
  1848. } ;
  1849. // If the string was not found, format and post an error message.
  1850. // Also, set the flag indicating that an error has occurred.
  1851. if (u3 >= ucount3) {
  1852. if (IgnoreChecksWhenClosing(bclosing))
  1853. return ;
  1854. csmsg.Format(IDS_GPDStrCompError, pcmd->Name(), nrcid) ;
  1855. PostWSCheckingMessage(csmsg, (CProjectNode *) pcmd) ;
  1856. bwsproblem = true ;
  1857. } ;
  1858. } ;
  1859. } ;
  1860. // Tidiness Check #6
  1861. // Each string that is referenced by a GPD was marked above. Now we need to
  1862. // find out if any string is unreferenced. Post a warning message for each
  1863. // unreferenced string.
  1864. for (ucount = m_cst.Count(), u = 0 ; u < ucount ; u++) {
  1865. if (m_cst.GetRefFlag(u)) // Skip this string if it was referenced
  1866. continue ;
  1867. m_cst.Details(u, wkey, csstr) ; // Skip this string if ID in low range
  1868. if (wkey >= 1 && wkey <= 256)
  1869. continue ;
  1870. if (IgnoreChecksWhenClosing(bclosing))
  1871. return ;
  1872. csmsg.Format(IDS_StrTidyWarning, csstr, wkey) ;
  1873. // NULL should be replaced with something that will allow the
  1874. // string editor to be invoked once the string editor is
  1875. // implemented.
  1876. PostWSCheckingMessage(csmsg, NULL) ;
  1877. bwsproblem = true ;
  1878. } ;
  1879. }
  1880. /******************************************************************************
  1881. CDriverResources::DoGPDWorkspaceChecks
  1882. The following checks are made:
  1883. 7. All GPD model names are unique.
  1884. 8. All GPD file names are unique.
  1885. ******************************************************************************/
  1886. void CDriverResources::DoGPDWorkspaceChecks(bool bclosing, bool& bwsproblem)
  1887. {
  1888. unsigned ucount ; // Count of nodes, etc processed in a loop
  1889. unsigned u, u2 ; // Loop counters
  1890. CString csmsg ; // Error or warning message
  1891. CString csstr ; // Temp string
  1892. // Completeness Check #7
  1893. // Check to see if all of the GPD model names are unique.
  1894. for (ucount = Models(), u = 0; u < ucount ; u++) {
  1895. csstr = Model(u).Name() ;
  1896. for (u2 = 0 ; u2 < u ; u2++) {
  1897. // If these model names don't match, continue checking.
  1898. if (csstr != Model(u2).Name())
  1899. continue ;
  1900. // A duplicate was found so post an error message and indicate
  1901. // that there is a problem.
  1902. if (IgnoreChecksWhenClosing(bclosing))
  1903. return ;
  1904. csmsg.Format(IDS_GPDModNameCompError, u, csstr) ;
  1905. PostWSCheckingMessage(csmsg, (CProjectNode *) &Model(u)) ;
  1906. bwsproblem = true ;
  1907. } ;
  1908. } ;
  1909. // Completeness Check #8
  1910. // Check to see if all of the GPD file names are unique.
  1911. for (ucount = Models(), u = 0; u < ucount ; u++) {
  1912. csstr = Model(u).FileTitleExt() ;
  1913. for (u2 = 0 ; u2 < u ; u2++) {
  1914. // If these model names don't match, continue checking.
  1915. if (csstr != Model(u2).FileTitleExt())
  1916. continue ;
  1917. // A duplicate was found so post an error message and indicate
  1918. // that there is a problem.
  1919. if (IgnoreChecksWhenClosing(bclosing))
  1920. return ;
  1921. csmsg.Format(IDS_GPDFileNameCompError, u, csstr) ;
  1922. PostWSCheckingMessage(csmsg, (CProjectNode *) &Model(u)) ;
  1923. bwsproblem = true ;
  1924. } ;
  1925. } ;
  1926. }
  1927. /******************************************************************************
  1928. CDriverResources::IgnoreChecksWhenClosing
  1929. This function is used to end workspace checking and return to the caller
  1930. when the workspace is closing iff the user says to do so. This routine is
  1931. only called - and therefore the user is only prompted - when an error or
  1932. warning has been detected. The up side of this is that no user intervention
  1933. is needed unless a problem is detected. The downside is that more checking
  1934. (and sometimes all of the checking) has to be performed before we can find
  1935. out if we should stop. This is why the GPD checking is the last thing done
  1936. by WorkspaceChecker(). Hopefully, if there is a problem, it will be found
  1937. in the faster checks before the GPD checks have to be done.
  1938. ******************************************************************************/
  1939. bool CDriverResources::IgnoreChecksWhenClosing(bool bclosing)
  1940. {
  1941. // If this is the first message to be posted and the WS is closing, ask
  1942. // the user what he wants to do.
  1943. if (m_bFirstCheckMsg) {
  1944. m_bIgnoreChecks = false ; // Assume checks are NOT ignored
  1945. if (bclosing) {
  1946. CString csmsg ;
  1947. csmsg.Format(IDS_WSCloseCheckPrmt, Name()) ;
  1948. int nrc = AfxMessageBox(csmsg, MB_YESNO) ;
  1949. m_bIgnoreChecks = (nrc == IDNO) ;
  1950. } ;
  1951. // Reset flag now that first check processing is done
  1952. m_bFirstCheckMsg = false ;
  1953. } ;
  1954. // By the time this point is reached, the value of m_bIgnoreChecks will
  1955. // contain whatever should be returned by this function.
  1956. return m_bIgnoreChecks ;
  1957. }
  1958. /******************************************************************************
  1959. CDriverResources::PostWSCheckingMessage
  1960. Create the checking results window if needed and then post a message to it.
  1961. ******************************************************************************/
  1962. bool CDriverResources::PostWSCheckingMessage(CString csmsg, CProjectNode* ppn)
  1963. {
  1964. // Create the workspace checking, error and warning display window if one
  1965. // does not exist.
  1966. if (m_pwscdCheckDoc == NULL) {
  1967. m_pwscdCheckDoc = new CWSCheckDoc(this) ;
  1968. if (m_pwscdCheckDoc == NULL)
  1969. return false ;
  1970. CString cstitle ;
  1971. cstitle.Format(IDS_WSCheckTitle, Name()) ;
  1972. m_pwscdCheckDoc->SetTitle(cstitle) ;
  1973. CMultiDocTemplate* pcmdt = WSCheckTemplate() ;
  1974. m_pcmcwCheckFrame = (CMDIChildWnd *) pcmdt->CreateNewFrame(m_pwscdCheckDoc, NULL) ;
  1975. if (m_pcmcwCheckFrame) {
  1976. pcmdt->InitialUpdateFrame(m_pcmcwCheckFrame, m_pwscdCheckDoc, TRUE) ;
  1977. pcmdt->AddDocument(m_pwscdCheckDoc) ;
  1978. } else {
  1979. delete m_pwscdCheckDoc ;
  1980. m_pwscdCheckDoc = NULL ;
  1981. m_bIgnoreChecks = true ;
  1982. return false ;
  1983. } ;
  1984. m_bFirstCheckMsg = false ;
  1985. } ;
  1986. // Post the message and return
  1987. m_pwscdCheckDoc->PostWSCMsg(csmsg, ppn) ;
  1988. return true ;
  1989. }
  1990. /******************************************************************************
  1991. CDriverResources::ResetWorkspaceErrorWindow
  1992. If there is an existing checking results window for this workspace, clear
  1993. out its contents. Next, initialize a couple of flags that have to be set
  1994. before the ws checking begins.
  1995. ******************************************************************************/
  1996. void CDriverResources::ResetWorkspaceErrorWindow(bool bclosing)
  1997. {
  1998. // Clear the checking window if there is one.
  1999. if (m_pwscdCheckDoc && m_pcmcwCheckFrame && IsWindow(m_pcmcwCheckFrame->m_hWnd))
  2000. m_pwscdCheckDoc->DeleteAllMessages() ;
  2001. else {
  2002. m_pwscdCheckDoc = NULL ;
  2003. m_pcmcwCheckFrame = NULL ;
  2004. // BUG_BUG - Do I need to delete these classes first???
  2005. } ;
  2006. // Initialize checking flags
  2007. m_bFirstCheckMsg = true ;
  2008. m_bIgnoreChecks = false ;
  2009. }
  2010. /******************************************************************************
  2011. CDriverResources::RunEditor
  2012. Run the String Editor if requested and the string RC ID is not a common ID.
  2013. Otherwise, run the UFM Editor with the requested UFM loaded if the UFM ID
  2014. is valid.
  2015. Return true if it is possible to run an editor. Otherwise, return false.
  2016. ******************************************************************************/
  2017. bool CDriverResources::RunEditor(bool bstring, int nrcid)
  2018. {
  2019. // If the String Editor is requested...
  2020. if (bstring) {
  2021. // Can't do anything if this is a special or common string ID.
  2022. if (nrcid == 0x7fffffff
  2023. || (nrcid >= FIRSTCOMMONRCSTRID && nrcid <= LASTCOMMONRCSTRID))
  2024. return false ;
  2025. // Run the editor and return true because this was possible.
  2026. m_csnStrings.SetFirstSelRCID(nrcid) ;
  2027. m_csnStrings.Edit() ;
  2028. return true ;
  2029. } ;
  2030. // UFM Editor requested so...
  2031. // Fail if the UFM ID is invalid.
  2032. if (nrcid < 1 || nrcid > (int) FontCount())
  2033. return false ;
  2034. // Since the UFMs might not be in RC ID order, I have to search for the UFM
  2035. // with the matching ID.
  2036. for (unsigned u = 0 ; u < FontCount() ; u++)
  2037. if (Font(u).nGetRCID() == nrcid) {
  2038. Font(u).Edit() ;
  2039. return true ;
  2040. } ;
  2041. // Could not find UFM with matching RC ID so...
  2042. return false ;
  2043. }
  2044. void CDriverResources::CopyResources(CStringArray& csaUFMFiles, CStringArray& csaGTTFiles, CString& csModel,CStringArray& csaRcid)
  2045. {
  2046. // copy files to CDriverResources member data
  2047. // UFM
  2048. for (int i = 0 ; i < csaUFMFiles.GetSize(); i++ ) {
  2049. CFontInfo* pcfi = new CFontInfo ;
  2050. pcfi->SetFileName(csaUFMFiles.GetAt(i)) ;
  2051. pcfi->Rename(pcfi->FileTitle() ) ;
  2052. m_csoaFonts.Add(pcfi) ;
  2053. }
  2054. // GTT
  2055. for (i = 0 ; i < csaGTTFiles.GetSize() ; i ++ ) {
  2056. CGlyphMap* pcgm = new CGlyphMap ;
  2057. pcgm->SetFileName(csaGTTFiles.GetAt(i)) ;
  2058. pcgm->Rename(pcgm->FileTitle() ) ;
  2059. m_csoaAtlas.Add(pcgm) ;
  2060. }
  2061. // GPD
  2062. for (i = 0 ; i < 1 ; i ++ ) {
  2063. CModelData* pcmd = new CModelData ;
  2064. pcmd->SetFileName(csModel);
  2065. pcmd->Rename(pcmd->FileTitle() );
  2066. m_csoaModels.Add(pcmd) ;
  2067. }
  2068. for (i = 0 ; i < csaRcid.GetSize() ; i ++ ) {
  2069. AddStringEntry(csaRcid[i], m_cst) ;
  2070. }
  2071. }
  2072. /******************************************************************************
  2073. CDriverResources::SyncUFMWidth
  2074. To Do : call all UFM and reload the width table regard to change of the GTT
  2075. return; true at end of the process
  2076. ******************************************************************************/
  2077. BOOL CDriverResources::SyncUFMWidth()
  2078. {
  2079. unsigned uufms, u ;
  2080. for (uufms = FontCount(), u = 0 ; u < uufms ; u++) {
  2081. CFontInfo& cfi = Font(u) ;
  2082. CString cspath = cfi.FileName() ;
  2083. cfi.CheckReloadWidths() ;
  2084. cfi.Store(cspath,true ) ;
  2085. }
  2086. return true ;
  2087. }