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.

1389 lines
42 KiB

  1. /******************************************************************************
  2. Source File: Model Data.CPP
  3. Implementation of the code for handling GPC format data
  4. Copyright (c) 1997 by Microsoft Corporation. All Rights Resreved.
  5. A Pretty Penny Enterprises Production
  6. Change History:
  7. 02-19-97 Bob_Kjelgaard@Prodgy.Net Created it
  8. ******************************************************************************/
  9. #include "StdAfx.h"
  10. #include "ProjNode.H"
  11. #include "CodePage.H"
  12. #include "Resource.H"
  13. #include "GPDFile.H"
  14. #include "utility.H"
  15. #include "minidev.h"
  16. /******************************************************************************
  17. COldMiniDriverData class
  18. This class is tasked with representing the GPC data. It will begin life as
  19. a stub, although it could become more functional, later.
  20. ******************************************************************************/
  21. /******************************************************************************
  22. ExtractList
  23. This is a private worker function. It takes a pointer to a null-terminated
  24. list of WORD font IDs, with the nasty complication that the first two
  25. elements of the list represent the endpoints of a range. It mashes these
  26. into a passed word map (of which we only use the indices).
  27. ******************************************************************************/
  28. static void ExtractList(PWORD pw, CMapWordToDWord& cmw2d) {
  29. for (WORD w = *pw++; w && w < *pw; w++)
  30. cmw2d[w] = 0;
  31. if (!w)
  32. return; // The whole list was empty
  33. while (*pw) // We start at the endpoint (which we haven't mapped yet)
  34. cmw2d[*pw++] = 0;
  35. }
  36. COldMiniDriverData::~COldMiniDriverData()
  37. {
  38. // The m_csoaFonts array has some duplicate entries in it because of GPC
  39. // entries that reference multiple printer models. We must zap those
  40. // duplicate entries so the data won't be deleted twice in the CSafeObArray
  41. // destructor. That would cause an AV.
  42. for (unsigned u = 0 ; u < m_csoaFonts.GetSize() ; u++) {
  43. if (GetSplitCode(u) != NoSplit)
  44. m_csoaFonts.SetAt(u, NULL) ;
  45. } ;
  46. }
  47. /******************************************************************************
  48. ColdMiniDriverData::Load
  49. This member function loads the mini-driver's GPC file, and extracts the
  50. number of models, the CTT IDs, and the model name IDs.
  51. ******************************************************************************/
  52. BOOL COldMiniDriverData::Load(CFile& cfImage) {
  53. struct sGPCHeaderEntry {
  54. WORD m_wOffset, m_wcbItem, m_wcItems;
  55. };
  56. struct sMaster {
  57. WORD m_wX, m_wY;
  58. };
  59. struct sPrinterModelData {
  60. WORD m_wcbSize;
  61. WORD m_widName; // Stringtable id for model name.
  62. WORD m_wfGeneral; // TODO: Define enums
  63. WORD m_wfCurves; // TODO: Define enums
  64. WORD m_wfLines; // TODO: Define enums
  65. WORD m_wfPolygons; // TODO: Define enums
  66. WORD m_wfText; // TODO: Define enums
  67. WORD m_wfClipping; // TODO: Define enums
  68. WORD m_wfRaster;; // TODO: Define enums
  69. WORD m_wfLandscapeText; // TODO: Define enums
  70. WORD m_wLeftMargin; // Left-hand unprintable area
  71. WORD m_wMaximumWidth; // Of physica page
  72. sMaster m_smMaximum, m_smMinimum; // Max min page sizes
  73. WORD m_widDefaultFont;
  74. WORD m_wLookAhead;
  75. WORD m_wMaxFontsPerPage;
  76. WORD m_wcCartridges;
  77. WORD m_widDefaultCTT;
  78. enum {PortraitFonts, LandscapeFonts, Resolution, PaperSize,
  79. PaperQuality, PaperSource, PaperDestination, TextQuality,
  80. Compression, FontCartridge, Color, MemoryConfiguration};
  81. WORD m_awofIndexLists[12]; // Uses the preceding enum
  82. WORD m_awIndices[16]; // Ditto
  83. WORD m_awVer3IndexLists[5]; // Ditto
  84. WORD m_wofDefaults; // List of defaults for index lists
  85. WORD m_wReserved;
  86. DWORD m_dwidICMManufactirer, m_dwidICMModel;
  87. DWORD m_adwReserved[8];
  88. };
  89. struct sGPCFileHeader {
  90. WORD m_widGPC; // 0x7F00 or it isn't valid.
  91. WORD m_wVersion; // Final version is 3, there was a V2
  92. sMaster m_smMasterdpi;
  93. DWORD m_dwoHeap; // The GPC data is maintained in one
  94. DWORD m_dwcbFile; // Total GPC Image size, heap and all
  95. enum {Default, PCL4, CAPSL, PPDS, TTY, DBCS};
  96. WORD m_wTechnology; // Use the preceding enum
  97. enum {PrivateHelp = 1, OneDraftFont};
  98. WORD m_wfGeneral; // Again, use the preceding enum
  99. char m_acReserved[10];
  100. WORD m_wcHeaderItems; // Number of valid header entries
  101. enum {ModelData, Resolution, PaperSize, PaperQuality, PaperSource,
  102. PaperDestination, TextQuality, Compression, FontCartridge,
  103. PageControl, CursorMovement, FontSimulation, DeviceColor,
  104. RectangleFill, DownloadInfo, VectorPage, Carousel, PenInfo,
  105. LineInfo, BrushInfo, VectorOutput, PolyVectorOutput,
  106. VectorSupport, ImageControl, PrintDensity, ColorTracking,
  107. MaximumDefined = 30};
  108. sGPCHeaderEntry m_asgpche[MaximumDefined];
  109. };
  110. struct sFontCartridge {
  111. WORD m_wSize; // = 12
  112. WORD m_widCartridge; // In the string table
  113. WORD m_wofPortraitList;
  114. WORD m_wofLandscapeList;
  115. WORD m_wfGeneral;
  116. WORD m_wReserved;
  117. };
  118. // In case we get called more than once, dump any old info...
  119. m_cbaImage.RemoveAll();
  120. m_csoaFonts.RemoveAll();
  121. m_cwaidCTT.RemoveAll();
  122. m_cwaidModel.RemoveAll();
  123. m_cbaImage.SetSize(cfImage.GetLength());
  124. cfImage.Read(m_cbaImage.GetData(), cfImage.GetLength());
  125. sGPCFileHeader *psgfh = (sGPCFileHeader *) Image();
  126. if (psgfh -> m_widGPC != 0x7F00 || psgfh -> m_wVersion > 0x3ff)
  127. return FALSE;
  128. // Suck out the printer model data we care about- eventually, this may
  129. // be all of it
  130. for (unsigned u = 0;
  131. u < psgfh -> m_asgpche[sGPCFileHeader::ModelData].m_wcItems;
  132. u++) {
  133. sPrinterModelData& spmd = *(sPrinterModelData *) (Image() +
  134. psgfh -> m_asgpche[sGPCFileHeader::ModelData].m_wOffset +
  135. psgfh -> m_asgpche[sGPCFileHeader::ModelData].m_wcbItem * u);
  136. m_cwaidModel.Add(spmd.m_widName);
  137. m_cwaidCTT.Add(spmd.m_widDefaultCTT);
  138. // Build the font list- I use a CMapWordToOb to handle the duplicate
  139. // screening
  140. CMapWordToDWord& cmw2dThis = * (new CMapWordToDWord);
  141. // Extract the portrait resident fonts
  142. if (spmd.m_awofIndexLists[sPrinterModelData::PortraitFonts])
  143. ExtractList((PWORD) (Image() + psgfh -> m_dwoHeap +
  144. spmd.m_awofIndexLists[sPrinterModelData::PortraitFonts]),
  145. cmw2dThis);
  146. // Extract the landscape resident fonts
  147. if (spmd.m_awofIndexLists[sPrinterModelData::LandscapeFonts])
  148. ExtractList((PWORD) (Image() + psgfh -> m_dwoHeap +
  149. spmd.m_awofIndexLists[sPrinterModelData::LandscapeFonts]),
  150. cmw2dThis);
  151. // Extract the cartridge fonts
  152. if (spmd.m_awofIndexLists[sPrinterModelData::FontCartridge]) {
  153. PWORD pw = (PWORD) (Image() + psgfh -> m_dwoHeap +
  154. spmd.m_awofIndexLists[sPrinterModelData::FontCartridge]);
  155. // RAID 102890- Cartridge font index is 1-based, not 0-based
  156. while (*pw) {
  157. sFontCartridge* psfc = (sFontCartridge *) (Image() + psgfh ->
  158. m_asgpche[sGPCFileHeader::FontCartridge].m_wOffset +
  159. psgfh ->
  160. m_asgpche[sGPCFileHeader::FontCartridge].m_wcbItem *
  161. (-1 + *pw++));
  162. // END RAID 102890
  163. // Portrait
  164. if (psfc -> m_wofPortraitList)
  165. ExtractList((PWORD) (Image() + psgfh -> m_dwoHeap +
  166. psfc -> m_wofPortraitList), cmw2dThis);
  167. // Landscape
  168. if (psfc -> m_wofLandscapeList)
  169. ExtractList((PWORD) (Image() + psgfh -> m_dwoHeap +
  170. psfc -> m_wofLandscapeList), cmw2dThis);
  171. }
  172. }
  173. // Save the map in the font structure
  174. m_csoaFonts.Add(&cmw2dThis);
  175. }
  176. return TRUE;
  177. }
  178. /******************************************************************************
  179. COldMiniDriverData::SplitMultiGPCs
  180. The Load() function has loaded information about each GPC entry into this
  181. class' member variables. The problem is that there are some GPC entries
  182. that are used to manage multiple models. This routine is used to "split"
  183. the data for these entries into single model "sections". Actually, what
  184. happens is that new member variables entries are allocated for each model
  185. and the GPC entry's data is copied into them. Next, a flag is set to
  186. mark this copy.
  187. ******************************************************************************/
  188. bool COldMiniDriverData::SplitMultiGPCs(CStringTable& cstdriversstrings)
  189. {
  190. // Make sure the data arrays are the same size.
  191. ASSERT(m_cwaidModel.GetSize() == m_cwaidCTT.GetSize()) ;
  192. ASSERT(m_cwaidModel.GetSize() == (int) m_csoaFonts.GetSize()) ;
  193. // Size the split codes array and split models names array to the current
  194. // number of GPC entries.
  195. m_cuaSplitCodes.SetSize(m_cwaidModel.GetSize()) ;
  196. m_csaSplitNames.SetSize(m_cwaidModel.GetSize()) ;
  197. // Declare the variables needed for the processing in the following loops.
  198. unsigned u, u2 ; // Looping/indexing variables
  199. int nloc ; // Location of "%" in model name
  200. CString csentryname ;
  201. int nlen ; // Length of csentryname/csmodelname
  202. // Loop through each GPC entry...
  203. for (u = 0 ; u < ModelCount(); u++) {
  204. // If the GPC entry's model name contains no percent signs, the entry
  205. // only references one model. Note this and continue.
  206. csentryname = cstdriversstrings[ModelName(u)] ;
  207. if ((nloc = csentryname.Find(_T('%'))) == -1) {
  208. SetSplitCode(u, NoSplit) ;
  209. continue ;
  210. } ;
  211. // The entry references multiple models. Mark the entry as the first
  212. // one and save its correct single model name.
  213. SetSplitCode(u, FirstSplit) ;
  214. m_csaSplitNames[u] = csentryname.Left(nloc) ;
  215. // Copy the entry's data into new elements of the data arrays. One
  216. // new set of data elements are allocated for each additional model
  217. // referenced by the entry.
  218. nlen = csentryname.GetLength() ;
  219. for (u2 = u + 1 ; nloc != -1 ; u2++, u++) {
  220. m_cwaidModel.InsertAt(u2, m_cwaidModel[u]) ;
  221. m_cwaidCTT.InsertAt(u2, m_cwaidCTT[u]) ;
  222. m_csoaFonts.InsertAt(u2, m_csoaFonts[u]) ;
  223. InsertSplitCode(u2, OtherSplit) ;
  224. // Look for the next percent sign in the entry's name. (Make sure
  225. // we don't reference passed the end of the string while doing
  226. // this.)
  227. if (nloc + 2 < nlen) {
  228. csentryname = csentryname.Mid(nloc + 1) ;
  229. nlen = csentryname.GetLength() ;
  230. nloc = csentryname.Find(_T('%')) ;
  231. } else
  232. break ;
  233. // Save the model name for the new entry.
  234. if (nloc == -1)
  235. m_csaSplitNames.InsertAt(u2, csentryname) ;
  236. else
  237. m_csaSplitNames[u] = csentryname.Left(nloc) ;
  238. } ;
  239. } ;
  240. // All went well so...
  241. return true ;
  242. }
  243. /******************************************************************************
  244. COldMiniDriverData::FontMap(unsigned u)
  245. This member returns the map which shows which fonts are used by the given
  246. model.
  247. ******************************************************************************/
  248. CMapWordToDWord& COldMiniDriverData::FontMap(unsigned u) const {
  249. return *(CMapWordToDWord *) m_csoaFonts[u];
  250. }
  251. /******************************************************************************
  252. COldMiniDriverData::NoteTranslation
  253. This records the fact that model nn must translate instances of font ID xxx
  254. to font ID y.
  255. ******************************************************************************/
  256. void COldMiniDriverData::NoteTranslation(unsigned uModel, unsigned uidOld,
  257. unsigned uidNew) {
  258. FontMap(uModel)[(WORD)uidOld] = uidNew;
  259. }
  260. /******************************************************************************
  261. CModelData class
  262. This class encapsulates the GPD file. It will start life as a big
  263. CStringArray, but as the editor gets more sophisticated, it may gain
  264. additional members to speed processing and/or manipulation of the data.
  265. ******************************************************************************/
  266. IMPLEMENT_SERIAL(CModelData, CProjectNode, 0)
  267. /******************************************************************************
  268. CModelData::FillViewer
  269. This static member function is a callback for the rich edit control. It
  270. receives a pointer to the CModelData in question, and calls its Fill from
  271. buffer member function.
  272. Args:
  273. DWORD dwthis Pointer to the CModelData in question
  274. LPBYTE lpb Pointer to the buffer to fill
  275. LONG lcb Number of bytes to read
  276. LONG *plcb Number of bytes actually read is saved here
  277. Returns:
  278. TRUE (failure) if class instance pointer is NULL. Otherwise, whatever
  279. Fill() returns.
  280. ******************************************************************************/
  281. DWORD CALLBACK CModelData::FillViewer(DWORD_PTR dwthis, LPBYTE lpb, LONG lcb,
  282. LONG *plcb) {
  283. if (!dwthis)
  284. return TRUE;
  285. CModelData* pcmd = (CModelData *) dwthis;
  286. return pcmd -> Fill(lpb, lcb, plcb);
  287. }
  288. /******************************************************************************
  289. CModelData::FromViewer
  290. This is a stream callback for moving data from the edit control to the GPD
  291. class. It receives a pointer to the CModelData being updated, and calls its
  292. UpdateFrom buffer member function to do the rest of the work
  293. ******************************************************************************/
  294. DWORD CALLBACK CModelData::FromViewer(DWORD_PTR dwthis, LPBYTE lpb, LONG lcb,
  295. LONG *plcb) {
  296. if (!dwthis)
  297. return TRUE; // Stop the madness
  298. CModelData* pcmd = (CModelData *) dwthis;
  299. return pcmd -> UpdateFrom(lpb, lcb, plcb);
  300. }
  301. /******************************************************************************
  302. CModelData::Fill(LPBYTE lpb, LONG lcb, LONG *plcb)
  303. This private method fills a buffer from the GPD contents in CString form.
  304. An internal buffer is used to handle partially moved strings.
  305. ******************************************************************************/
  306. DWORD CModelData::Fill(LPBYTE lpb, LONG lcb, LONG *plcb) {
  307. int iTotalLines = (int)m_csaGPD.GetSize(); // Get the # of lines in the GPD
  308. // If the temp buffer is empty and the next line to read is greater than
  309. // the number of lines in the GPD, the REC has been loaded. We're done.
  310. if (!m_cbaBuffer.GetSize() && m_iLine >= iTotalLines) {
  311. *plcb = 0;
  312. return 0;
  313. }
  314. unsigned ucb = (unsigned) lcb; // Number of bytes still wanted
  315. union {
  316. LPTSTR lpstr;
  317. LPBYTE lpbThis;
  318. };
  319. // First, empty anything buffered previously
  320. lpbThis = lpb;
  321. // If there is data left over from a line partially loaded into the REC
  322. // before..
  323. if (m_cbaBuffer.GetSize())
  324. // ...If the partial line will fit into the REC buffer, copy it
  325. // into the buffer, update variables to indicate this, and continue.
  326. if ((unsigned) m_cbaBuffer.GetSize() <= ucb) {
  327. memcpy(lpbThis, m_cbaBuffer.GetData(), (size_t)m_cbaBuffer.GetSize());
  328. ucb -= (unsigned)m_cbaBuffer.GetSize();
  329. lpbThis += m_cbaBuffer.GetSize();
  330. m_cbaBuffer.RemoveAll();
  331. // ...If the partial line won't fit in the REC buffer, copy the
  332. // portion of it that will fit into the REC buffer, remove those bytes
  333. // from the line buffer, and return because nothing more can be loaded.
  334. } else {
  335. memcpy(lpbThis, m_cbaBuffer.GetData(), ucb);
  336. m_cbaBuffer.RemoveAt(0, ucb);
  337. *plcb = lcb;
  338. return 0;
  339. }
  340. // Line by line, copy as much data as possible into the REC's buffer.
  341. for (; ucb && m_iLine < iTotalLines; m_iLine++) {
  342. // Get the next GPD line and add CR LF to it.
  343. CString csLine = m_csaGPD[m_iLine];
  344. csLine += _TEXT("\r\n");
  345. // If the entire line will fit into the REC's buffer, copy it in. Then
  346. // update all pointers, counters, etc and then check the next line.
  347. if ((csLine.GetLength()) * sizeof(TCHAR) <= ucb) {
  348. memcpy(lpbThis, (LPCTSTR) csLine,
  349. sizeof(TCHAR) * csLine.GetLength());
  350. ucb -= sizeof(TCHAR) * csLine.GetLength();
  351. lpstr += csLine.GetLength();
  352. continue;
  353. }
  354. // If this point is reached, the current line will not fit in the REC's
  355. // buffer so first copy the line into the temp buffer. Then copy the
  356. // portion of the line that will fit into the REC's buffer. Last,
  357. // update the buffers, pointers, and counters.
  358. m_cbaBuffer.SetSize(sizeof(TCHAR) * csLine.GetLength());
  359. memcpy(m_cbaBuffer.GetData(), (LPCTSTR) csLine,
  360. sizeof(TCHAR) * csLine.GetLength());
  361. memcpy(lpbThis, m_cbaBuffer.GetData(), ucb);
  362. m_cbaBuffer.RemoveAt(0, ucb);
  363. ucb = 0;
  364. }
  365. // Save the number of bytes load and return 0 to indicate success.
  366. *plcb = lcb - ucb;
  367. return 0;
  368. }
  369. /******************************************************************************
  370. CModelData::UpdateFrom(LPBYTE lpb, LONG lcb, LONG* plcb)
  371. This is a private member- an overload which adds the contents of the given
  372. buffer to the GPD CStringArray, by parsing it into strings. A private buffer
  373. member is used to hold partial strings between calls.
  374. ******************************************************************************/
  375. DWORD CModelData::UpdateFrom(LPBYTE lpb, LONG lcb, LONG* plcb) {
  376. // Copy the buffer to a byte buffer and null-terminate
  377. m_cbaBuffer.SetSize(1 + lcb);
  378. memcpy(m_cbaBuffer.GetData(), lpb, lcb);
  379. m_cbaBuffer.SetAt(-1 + m_cbaBuffer.GetSize(), 0);
  380. // Convert to string and append to any buffered data.
  381. CString csWork(m_cbaBuffer.GetData());
  382. CString csEnd(_T("\r\x1A")); // These get dumped
  383. m_cbaBuffer.RemoveAll();
  384. m_csBuffer += csWork;
  385. // Add any complete strings to the GPD contents.
  386. csWork = m_csBuffer.SpanExcluding(_T("\n"));
  387. while (csWork.GetLength() != m_csBuffer.GetLength()) {
  388. m_csBuffer = m_csBuffer.Mid(csWork.GetLength() + 1);
  389. // Remove any trailing whitespace.
  390. csWork.TrimRight();
  391. // Add the string sans any leading control characters
  392. m_csaGPD.Add(csWork.Mid(csWork.SpanIncluding(csEnd).GetLength()));
  393. // While we're here, remove any leading control characters from buffer
  394. m_csBuffer =
  395. m_csBuffer.Mid(m_csBuffer.SpanIncluding(csEnd).GetLength());
  396. csWork = m_csBuffer.SpanExcluding(_T("\n"));
  397. }
  398. // The leftover data (if any) may be used later...
  399. *plcb = lcb;
  400. return 0;
  401. }
  402. /******************************************************************************
  403. CModelData::Classify
  404. This method identifies the line numbers for each warning comment, error
  405. comment, and any other sort of comment, so they can later be syntax colored.
  406. ******************************************************************************/
  407. /******************************************************************************
  408. CModelData::CModelData
  409. Constructs an empty CModelData object- includes building the Menu table
  410. ******************************************************************************/
  411. CModelData::CModelData() {
  412. m_pcmdt = NULL;
  413. m_cfn.SetExtension(_T(".GPD"));
  414. m_cfn.AllowPathEdit();
  415. // Build the context menu control
  416. m_cwaMenuID.Add(ID_OpenItem);
  417. m_cwaMenuID.Add(ID_CopyItem);
  418. m_cwaMenuID.Add(ID_RenameItem);
  419. m_cwaMenuID.Add(ID_DeleteItem);
  420. m_cwaMenuID.Add(0);
  421. m_cwaMenuID.Add(ID_ExpandBranch);
  422. m_cwaMenuID.Add(ID_CollapseBranch);
  423. // Initialize the variables needed for workspace completeness and tidiness
  424. // checking.
  425. m_bTCUpdateNeeded = false ;
  426. m_pnUFMRCIDs = m_pnStringRCIDs = NULL ;
  427. m_nNumUFMsInGPD = m_nNumStringsInGPD = 0 ;
  428. m_pvRawData = NULL ;
  429. }
  430. /******************************************************************************
  431. CModelData::~CModelData()
  432. Free, unload, and delete the data used for completeness and tidiness checks.
  433. ******************************************************************************/
  434. extern "C" void UnloadRawBinaryData(PVOID pRawData) ;
  435. CModelData::~CModelData()
  436. {
  437. // If the GPD has been parsed...
  438. if (m_pvRawData) {
  439. // Free the parsed data
  440. UnloadRawBinaryData(m_pvRawData) ;
  441. // Delete the parsed data file
  442. try {
  443. CString cs ;
  444. cs = FilePath() + FileTitle() + _T(".BUD") ;
  445. DeleteFile(cs) ;
  446. }
  447. catch (CException *pce) {
  448. pce->ReportError();
  449. pce->Delete();
  450. }
  451. // Delete each of the resource lists that exist
  452. if (m_pnUFMRCIDs)
  453. delete m_pnUFMRCIDs ;
  454. if (m_pnStringRCIDs)
  455. delete m_pnStringRCIDs ;
  456. } ;
  457. }
  458. /******************************************************************************
  459. CModelData::Load(CStdioFile csiofGPD)
  460. This overload loads the GPD from a text file directly.
  461. ******************************************************************************/
  462. BOOL CModelData::Load(CStdioFile& csiofGPD)
  463. {
  464. CString csWork; // Used to read the GPD file's contents
  465. // Initialize the string array used to hold the GPD file's contents
  466. m_csaGPD.RemoveAll();
  467. // Load the GPD into the string array one line at a time.
  468. while (csiofGPD.ReadString(csWork)) {
  469. csWork.TrimRight(); // Cut off the trailing line stuff
  470. m_csaGPD.Add(csWork);
  471. }
  472. // Set the correct name and path when necessary. The rename checks may
  473. // fail since the file is opened elsewhere (possibly with sharing
  474. // conflicts), so disable them while the name is set.
  475. if (FileTitle().IsEmpty()) {
  476. m_cfn.EnableCreationCheck(FALSE);
  477. SetFileName(csiofGPD.GetFilePath());
  478. m_cfn.EnableCreationCheck();
  479. }
  480. // All went well so...
  481. return TRUE;
  482. }
  483. /******************************************************************************
  484. CModelData::Load()
  485. This overload loads the GPD file from the disk using the stored name and path
  486. information.
  487. ******************************************************************************/
  488. BOOL CModelData::Load()
  489. {
  490. // There is nothing to load if no file has been associated with this
  491. // instance of CModelData.
  492. if (FileTitle().IsEmpty())
  493. return FALSE;
  494. // Open the GPD file and call another load routine to finish the work.
  495. try {
  496. CStdioFile csiofGPD(FileName(),
  497. CFile::modeRead | CFile::shareDenyWrite);
  498. return Load(csiofGPD);
  499. }
  500. catch (CException *pce) {
  501. pce -> ReportError();
  502. pce -> Delete();
  503. }
  504. return FALSE;
  505. }
  506. /******************************************************************************
  507. CModelData::Store
  508. This method sends the GPD file to the disk. Since GPD infromation can be
  509. easily edited with an external editor, this avoids replication and
  510. consistency issues.
  511. ******************************************************************************/
  512. BOOL CModelData::Store(LPCTSTR lpstrPath) {
  513. int n = (int)m_csaGPD.GetSize() ;
  514. CString cs = m_csaGPD[0] ;
  515. // Write the GPD file to the target location, with the traditional CR/LF
  516. // separators. If the given name is NULL, use the stored one.
  517. try {
  518. CStdioFile csiofGPD(lpstrPath ? lpstrPath :
  519. FileName(), CFile::modeCreate | CFile::modeWrite |
  520. CFile::shareExclusive | CFile::typeBinary);
  521. for (int i = 0; i < m_csaGPD.GetSize(); i++)
  522. csiofGPD.WriteString(m_csaGPD[i] + _T("\r\n"));
  523. }
  524. catch (CException *pce) {
  525. pce -> ReportError();
  526. pce -> Delete();
  527. return FALSE;
  528. }
  529. Changed(FALSE);
  530. return TRUE;
  531. }
  532. /******************************************************************************
  533. CModelData::BkupStore
  534. Backup the original contents of the GPD to file called "BKUP_GPD" before
  535. calling Store() to save the file.
  536. Return TRUE if the backup and storing succeed. Otherwise, return FALSE.
  537. ******************************************************************************/
  538. BOOL CModelData::BkupStore()
  539. {
  540. // Build the backup file's filespec
  541. CString csbkfspec = m_cfn.Path() ;
  542. if (csbkfspec[csbkfspec.GetLength() - 1] != _T('\\'))
  543. csbkfspec += _T("\\") ;
  544. csbkfspec += _T("BKUP_GPD") ;
  545. // raid 9730 : bug caused by "Read-Only"
  546. CFileStatus rStatus;
  547. CFile::GetStatus(FileName(), rStatus);
  548. // Back up the file.
  549. try {
  550. if (rStatus.m_attribute & 0x01 || !CopyFile(FileName(), csbkfspec, FALSE)) {//end raid
  551. csbkfspec.Format(IDS_GPDBackupFailed, FileTitleExt()) ;
  552. if (AfxMessageBox(csbkfspec, MB_YESNO + MB_ICONQUESTION) == IDNO)
  553. return FALSE ;
  554. } ;
  555. }
  556. catch (CException *pce) {
  557. pce->ReportError() ;
  558. pce->Delete() ;
  559. return FALSE ;
  560. } ;
  561. // Now do a normal store operation.
  562. return (Store()) ;
  563. }
  564. /******************************************************************************
  565. CModelData::Restore
  566. Copy the file "BKUP_GPD" to the GPD file to restore the GPD's original
  567. contents. If the restore operation is successful, delete the backup file.
  568. Return nonzero if this succeeds. Otherwise, return FALSE.
  569. ******************************************************************************/
  570. BOOL CModelData::Restore()
  571. {
  572. // Build the backup file's filespec
  573. CString csbkfspec = m_cfn.Path() ;
  574. if (csbkfspec[csbkfspec.GetLength() - 1] != _T('\\'))
  575. csbkfspec += _T("\\") ;
  576. csbkfspec += _T("BKUP_GPD") ;
  577. // Restore the file.
  578. try {
  579. if (CopyFile(csbkfspec, FileName(), FALSE)) {
  580. DeleteFile(csbkfspec) ;
  581. return TRUE ;
  582. } else
  583. return FALSE ;
  584. }
  585. catch (CException *pce) {
  586. pce->ReportError() ;
  587. pce->Delete() ;
  588. return FALSE ;
  589. } ;
  590. }
  591. /******************************************************************************
  592. CModelData::Parse
  593. This method is responsible for parsing the GPD file and collecting the
  594. resulting errors.
  595. The initial implementation will be a bit bizarre, because the GPD parser
  596. isn't stable, and converting it so it would work well for ma and then staying
  597. on top of the changes just doesn't make sense.
  598. ******************************************************************************/
  599. extern "C" BOOL BcreateGPDbinary(LPCWSTR lpstrFile, DWORD dwVerbosity);
  600. // The parser hook
  601. extern "C" PVOID LoadRawBinaryData(LPCWSTR lpstrFile) ;
  602. extern "C" PVOID InitBinaryData(PVOID pv, PVOID pv2, PVOID pv3) ;
  603. extern "C" void FreeBinaryData(PVOID pInfoHdr);
  604. extern "C" void UseLog(FILE *pfLog);
  605. //extern "C" DWORD gdwVerbosity ;
  606. BOOL CModelData::Parse(int nerrorlevel)
  607. {
  608. // Step 0: Set the error level. This is 0 by default.
  609. // Step 1: Establish the correct directory for the parser, and
  610. // bang together a couple of file names
  611. CString csCurrent ;
  612. GetCurrentDirectory(MAX_PATH + 1, csCurrent.GetBuffer(MAX_PATH + 1));
  613. csCurrent.ReleaseBuffer();
  614. SetCurrentDirectory(m_cfn.Path().Left(m_cfn.Path().ReverseFind(_T('\\'))));
  615. // Step 2: Fake out the error logging interface so it actually tosses
  616. // them all into a CString Array for us, the invoke the parser.
  617. SetLog();
  618. // Step 3: Convert the file name to Unicode so we don't have to tweak the
  619. // parser code.
  620. CString csFile = FileTitle() + _T(".GPD");
  621. CByteArray cbaIn;
  622. CWordArray cwaOut;
  623. cbaIn.SetSize(csFile.GetLength() + 1);
  624. lstrcpy((LPSTR) cbaIn.GetData(), csFile);
  625. CCodePageInformation ccpi;
  626. ccpi.Convert(cbaIn, cwaOut, GetACP());
  627. if (BcreateGPDbinary((PWSTR)cwaOut.GetData(), nerrorlevel)) {
  628. PVOID pRawData ;
  629. PVOID pInfoHdr ;
  630. pRawData = LoadRawBinaryData((PWSTR)cwaOut.GetData());
  631. if(pRawData)
  632. pInfoHdr = InitBinaryData(pRawData, NULL, NULL);
  633. if (pRawData && pInfoHdr)
  634. FreeBinaryData(pInfoHdr);
  635. if (pRawData)
  636. UnloadRawBinaryData(pRawData) ;
  637. DeleteFile(FileTitle() + _T(".Bud"));
  638. }
  639. // Finally, clean up the mess by restoring the original working
  640. // directory and turn off logging.
  641. SetCurrentDirectory(csCurrent);
  642. EndLog() ;
  643. return TRUE;
  644. }
  645. /******************************************************************************
  646. CModelData::RemoveError
  647. This removes the given error from the log.
  648. ******************************************************************************/
  649. void CModelData::RemoveError(unsigned u) {
  650. if (u >= Errors())
  651. return;
  652. m_csaConvertLog.RemoveAt(u);
  653. Changed();
  654. }
  655. /******************************************************************************
  656. CModelData::Fill(CRichEditCtrl& crec)
  657. This overload fills the gven rich edit control with the GPD contents, either
  658. as currently cached in memory, or stored on the disk.
  659. ******************************************************************************/
  660. void CModelData::Fill(CRichEditCtrl& crec)
  661. {
  662. // Prepare to load the rich edit control (REC) with the GPD data
  663. EDITSTREAM es = {(DWORD_PTR) this, 0, FillViewer};
  664. m_iLine = 0;
  665. // If the GPD is not in memory yet, read it in before loading the REC.
  666. if (!m_csaGPD.GetSize())
  667. Load();
  668. // Load the GPD into the REC.
  669. crec.StreamIn(SF_TEXT, es);
  670. }
  671. /******************************************************************************
  672. CModelData::UpdateFrom(CRichEditCtrl& crec)
  673. This overloaded member function discards the current GPD cache and refills
  674. it from the given edit control.
  675. ******************************************************************************/
  676. void CModelData::UpdateFrom(CRichEditCtrl& crec) {
  677. EDITSTREAM es = {(DWORD_PTR) this, 0, FromViewer};
  678. m_csaGPD.RemoveAll();
  679. m_csBuffer.Empty(); // Just in case...
  680. crec.StreamOut(SF_TEXT, es);
  681. Changed();
  682. }
  683. /******************************************************************************
  684. CModelData::CreateEditor
  685. This member function launches an editing view for the GPD Data.
  686. ******************************************************************************/
  687. CMDIChildWnd* CModelData::CreateEditor()
  688. {
  689. // Create a new document class instance for the new editor
  690. CGPDContainer* pcgpdcMe=
  691. new CGPDContainer(this, FileName());
  692. // Read in the GPD
  693. Load();
  694. // Make up a cool title
  695. pcgpdcMe -> SetTitle(m_pcbnWorkspace -> Name() + _T(": ") + Name());
  696. // Build a frame for the editor and attach the doc class to it
  697. CMDIChildWnd *pcmcwNew = (CMDIChildWnd *) m_pcmdt ->
  698. CreateNewFrame(pcgpdcMe, NULL);
  699. // Update the new frame/view
  700. if (pcmcwNew) {
  701. m_pcmdt -> InitialUpdateFrame(pcmcwNew, pcgpdcMe, TRUE);
  702. m_pcmdt -> AddDocument(pcgpdcMe);
  703. }
  704. // Return the new frame pointer
  705. return pcmcwNew;
  706. }
  707. /******************************************************************************
  708. CModelData::Import
  709. This method walks one step up the tree and passes the call to the import
  710. method for the fixed node which owns us.
  711. ******************************************************************************/
  712. void CModelData::Import() {
  713. ((CBasicNode *) m_pctcOwner ->
  714. GetItemData(m_pctcOwner -> GetParentItem(m_hti))) -> Import();
  715. }
  716. /******************************************************************************
  717. CModelData::Serialize
  718. Stores the image, as we need it stored.
  719. ******************************************************************************/
  720. void CModelData::Serialize(CArchive& car) {
  721. CProjectNode::Serialize(car);
  722. //TRACE("\n%s has %d strings:\n", Name(), m_csaConvertLog.GetSize()) ;
  723. //for (int n = 0 ; n < m_csaConvertLog.GetSize() ; n++)
  724. // TRACE(" %d: %s\n", n, m_csaConvertLog[n]) ;
  725. m_csaConvertLog.Serialize(car);
  726. }
  727. /******************************************************************************
  728. CModelData::UpdateResIDs
  729. This routine will make sure that the specified resource ID list is up to
  730. date. There are several steps that must be taken to accomplish this goal:
  731. 1. Free/invalidate old resource lists and related information if the GPD
  732. has changed.
  733. 2. Parse the GPD and load its data if this is needed.
  734. 3. If step 2 is taken or the requested resource list is unitialized, get
  735. that data.
  736. ******************************************************************************/
  737. //#define RESLISTSIZE 16 // Initial resource list size
  738. // Declarations for the GPD Parser routine that will get resource ID lists.
  739. extern "C" BOOL GetGPDResourceIDs(LPINT lpiresarray, int numelts, LPINT lpicount,
  740. BOOL brestype, PVOID prawdata) ;
  741. bool CModelData::UpdateResIDs(bool bufmids)
  742. {
  743. //TRACE("gdwVerbosity = %d\n", gdwVerbosity) ;
  744. // If the GPD has changed so the resource data needs to be updated...
  745. if (m_bTCUpdateNeeded) {
  746. if (m_pvRawData) { // Free the old preparsed data if there is any
  747. UnloadRawBinaryData(m_pvRawData) ;
  748. m_pvRawData = NULL ;
  749. } ;
  750. if (m_pnUFMRCIDs) { // Free the old UFM RC ID list if there is one
  751. delete m_pnUFMRCIDs ;
  752. m_pnUFMRCIDs = NULL ;
  753. m_nNumUFMsInGPD = 0 ;
  754. } ;
  755. if (m_pnStringRCIDs) { // Free the old string RC ID list if there is one
  756. delete m_pnStringRCIDs ;
  757. m_pnStringRCIDs = NULL ;
  758. m_nNumStringsInGPD = 0 ;
  759. } ;
  760. m_bTCUpdateNeeded = false ;
  761. } ;
  762. // Parse and load the GPD data if this is needed. If either of these steps
  763. // fail, return false because the resource list cannot be updated.
  764. if (!m_pvRawData) {
  765. try {
  766. WCHAR wstrfilename[MAX_PATH] ;
  767. CString cs ;
  768. cs = FileName() ;
  769. MultiByteToWideChar(CP_ACP, 0, FileName(), -1, wstrfilename, MAX_PATH) ;
  770. //gdwVerbosity = 4 ;
  771. if (!BcreateGPDbinary(wstrfilename, 0))
  772. return false ;
  773. if ((m_pvRawData = LoadRawBinaryData(wstrfilename)) == NULL)
  774. return false ;
  775. }
  776. catch (CException *pce) {
  777. pce->ReportError() ;
  778. pce->Delete() ;
  779. return false ;
  780. }
  781. } ;
  782. // If the requested resource list is already up to date, just return true.
  783. if ((bufmids && m_pnUFMRCIDs) || (!bufmids && m_pnStringRCIDs))
  784. return true ;
  785. // Allocate space for the resource list
  786. int* pn = NULL ;
  787. int ncnt = -1 ;
  788. //pn = new int[RESLISTSIZE + 2] ;
  789. // Try to get the requested resource ID list. If this fails because the
  790. // array used to hold the IDs isn't big enough, reallocate the array and
  791. // try to get the IDs again. If this fails again, generate a hard error.
  792. GetGPDResourceIDs(pn, 0, &ncnt, bufmids, m_pvRawData) ;
  793. pn = new int[ncnt + 2] ;
  794. VERIFY(GetGPDResourceIDs(pn, ncnt, &ncnt, bufmids, m_pvRawData)) ;
  795. //if (GetGPDResourceIDs(pn, RESLISTSIZE, &ncnt, bufmids, m_pvRawData)) {
  796. // delete pn ;
  797. // pn = new int[ncnt + 2] ;
  798. // VERIFY(!GetGPDResourceIDs(pn, ncnt, &ncnt, bufmids, m_pvRawData)) ;
  799. //} ;
  800. // Update the specific resource ID variables based with the info collected
  801. // above.
  802. if (bufmids) {
  803. m_pnUFMRCIDs = pn ;
  804. m_nNumUFMsInGPD = ncnt ;
  805. } else {
  806. m_pnStringRCIDs = pn ;
  807. m_nNumStringsInGPD = ncnt ;
  808. } ;
  809. // All went well so...
  810. return true ;
  811. }
  812. /******************************************************************************
  813. //RAID 17897
  814. CModelData::GetKeywordValue
  815. Get the value of keyword in Gpd file,
  816. Arguments :
  817. csFileName ; file path of gpd file
  818. csKeyword : section name such as *GpdFileVersion: , *ModleName:
  819. Return :
  820. Success : return section value (string)
  821. Failue : return csFileName : file path as it come
  822. *****************************************************************************8*/
  823. CString CModelData::GetKeywordValue(CString csfile, CString csKeyword)
  824. {
  825. CFile cf;
  826. CString csModel,csline;
  827. int offset;
  828. CStringArray csaData;
  829. if(!LoadFile(csfile,csaData)){ // call global function in minidev.h(which is include for this fucntion)
  830. CString csErr;
  831. csErr.Format(IDS_InvalidFilename, csfile);
  832. AfxMessageBox(csErr,MB_OK);
  833. return csfile;
  834. }
  835. for(int i=0; i<csaData.GetSize();i++){
  836. csline = csaData[i];
  837. if(-1 ==(offset=csline.Find(csKeyword)))
  838. continue;
  839. else
  840. {
  841. csModel = csline.Mid(offset+csKeyword.GetLength());
  842. return csModel.Mid(csModel.Find(_T('"'))+1,csModel.ReverseFind(_T('"'))
  843. + - csModel.Find(_T('"')) - 1 ); // cancel : "
  844. }
  845. }
  846. return csfile;
  847. }
  848. /***************************************************************************************
  849. CModelData::SetKeywordValue
  850. Set the keyword value
  851. Arguments:
  852. csfile ; target file gpd file name
  853. csKeyword : target keyword ex) *GPDFilename
  854. csValue : value of keyworkd ex)*GPDFilename= g;\nt\dirver\mm.gpd
  855. *****************************************************************************************/
  856. void CModelData::SetKeywordValue(CString csfile, CString csKeyword, CString csValue,bool bSource)
  857. {
  858. CFile cf;
  859. int offset;
  860. CString csline;
  861. CStringArray csaData;
  862. if(!LoadFile(csfile,csaData)){
  863. CString csErr;
  864. csErr.Format(IDS_InvalidFilename, csfile);
  865. AfxMessageBox(csErr,MB_OK);
  866. }
  867. for(int i=0; i<csaData.GetSize();i++){
  868. csline = csaData[i];
  869. if(-1 ==(offset=csline.Find(csKeyword)))
  870. continue;
  871. else
  872. {
  873. csline.Empty();
  874. if(bSource )
  875. csline = csKeyword + _T("=") + csValue ;
  876. else
  877. csline = csKeyword +_T(": ")+ _T('"') + csValue + _T('"');
  878. csaData[i]= csline;
  879. m_csaGPD.Copy(csaData);
  880. Store(csfile);
  881. return ;
  882. }
  883. }
  884. }
  885. /******************************************************************************
  886. CGPDContainer class implementation
  887. This class is a document class which contains one GPD file and its assorted
  888. control mechanisms
  889. ******************************************************************************/
  890. IMPLEMENT_DYNCREATE(CGPDContainer, CDocument)
  891. // This version of the constructor is called when the GPD Editor is started
  892. // from the Workspace View.
  893. CGPDContainer::CGPDContainer(CModelData *pcmd, CString csPath)
  894. {
  895. m_bEmbedded = TRUE ; // Called from Workspace View
  896. m_pcmd = pcmd;
  897. SetPathName(csPath, FALSE);
  898. m_pcmd -> NoteOwner(*this);
  899. }
  900. // This version of the constructor is called when the GPD Editor is started
  901. // from the File Open command.
  902. CGPDContainer::CGPDContainer()
  903. {
  904. m_bEmbedded = FALSE; // Called from File Open menu
  905. m_pcmd = new CModelData;
  906. m_pcmd -> NoteOwner(*this);
  907. }
  908. /******************************************************************************
  909. CGPDContainer::OnNewDocument
  910. We just pass it back to the default handler. Could mean this one can be
  911. toasted
  912. ******************************************************************************/
  913. BOOL CGPDContainer::OnNewDocument() {
  914. return CDocument::OnNewDocument();
  915. }
  916. /******************************************************************************
  917. CGPDContainer::~CGPDContainer
  918. If this wasn't created from the workspace, then zap the data!
  919. ******************************************************************************/
  920. CGPDContainer::~CGPDContainer() {
  921. if (!m_bEmbedded && m_pcmd)
  922. delete m_pcmd;
  923. }
  924. BEGIN_MESSAGE_MAP(CGPDContainer, CDocument)
  925. //{{AFX_MSG_MAP(CGPDContainer)
  926. // NOTE - the ClassWizard will add and remove mapping macros here.
  927. //}}AFX_MSG_MAP
  928. END_MESSAGE_MAP()
  929. /////////////////////////////////////////////////////////////////////////////
  930. // CGPDContainer diagnostics
  931. #ifdef _DEBUG
  932. void CGPDContainer::AssertValid() const {
  933. CDocument::AssertValid();
  934. }
  935. void CGPDContainer::Dump(CDumpContext& dc) const {
  936. CDocument::Dump(dc);
  937. }
  938. #endif //_DEBUG
  939. /////////////////////////////////////////////////////////////////////////////
  940. // CGPDContainer serialization
  941. void CGPDContainer::Serialize(CArchive& ar) {
  942. if (ar.IsStoring()) {
  943. // TODO: add storing code here
  944. }
  945. else {
  946. // TODO: add loading code here
  947. }
  948. }
  949. /////////////////////////////////////////////////////////////////////////////
  950. // CGPDContainer commands
  951. /******************************************************************************
  952. CGPDContainer::OnSaveDocument
  953. First, make sure that the document is up to date. See CGPDViewer::OnUpdate()
  954. for more information. Then, we bypass the normal serialization process, and
  955. simple blast it to the drive.
  956. ******************************************************************************/
  957. BOOL CGPDContainer::OnSaveDocument(LPCTSTR lpszPathName)
  958. {
  959. UpdateAllViews(NULL, 0x4545, (CObject*) 0x4545) ;
  960. return ModelData()->Store(lpszPathName) ;
  961. }
  962. /******************************************************************************
  963. CDPSContainer::OnOpenDocument
  964. Again, blow off serialization- if I haven't figured out how to read a text
  965. file by now, I'm definitely in the wrong place.
  966. ******************************************************************************/
  967. BOOL CGPDContainer::OnOpenDocument(LPCTSTR lpszPathName) {
  968. try {
  969. CStdioFile csiofGPD(lpszPathName, CFile::modeRead |
  970. CFile::shareDenyWrite | CFile::typeText);
  971. return ModelData() -> Load(csiofGPD);
  972. }
  973. catch (CException *pce) {
  974. pce -> ReportError();
  975. pce -> Delete();
  976. }
  977. return FALSE;
  978. }
  979.