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.

1099 lines
32 KiB

  1. /******************************************************************************
  2. Source File: Project Node.CPP
  3. This implements the CProjectNode class which alows individual nodes in the
  4. tree view to control their behavior without the control itself having to know
  5. what all that behavior is.
  6. The original header file (from the prototype) said this class didn't need an
  7. implementation file, but this no longer makes sense, so it's bite the bullet
  8. time here at Pretty Penny Enterprises...
  9. Copyright (c) 1997 by Microsoft Corporation. All Rights Resreved.
  10. A Pretty Penny Enterprises Production
  11. Change History:
  12. 02-20-1997 Bob_Kjelgaard#Prodigy.Net Created it
  13. ******************************************************************************/
  14. #include "StdAfx.H"
  15. #include <gpdparse.h>
  16. #include "Resource.H"
  17. #include "ProjNode.H"
  18. #include "gtt.h"
  19. #include "fontinfo.h"
  20. #include "rcfile.h"
  21. #include "projrec.h"
  22. #include "comctrls.h"
  23. #include "StrEdit.h"
  24. IMPLEMENT_SERIAL(CBasicNode, CObject, 0)
  25. CBasicNode::CBasicNode() {
  26. m_pcmcwEdit = NULL;
  27. m_pcdOwner = NULL;
  28. m_pctcOwner = NULL;
  29. m_hti = NULL;
  30. m_pcbnWorkspace = NULL;
  31. m_bUniqueNameChange = false ;
  32. }
  33. CBasicNode::~CBasicNode() {
  34. if (m_pcmcwEdit)
  35. if (IsWindow(m_pcmcwEdit->m_hWnd))
  36. m_pcmcwEdit -> DestroyWindow();
  37. }
  38. // Changed() - If the node contains a document pointer, use it to indicate
  39. // that the document does or does not need to be saved. If the RC file
  40. // needs to be rewritten, call the routine in the document class to save
  41. // this info.
  42. void CBasicNode::Changed(BOOL bModified, BOOL bWriteRC)
  43. {
  44. if (m_pcdOwner) {
  45. m_pcdOwner->SetModifiedFlag(bModified) ;
  46. if (bWriteRC)
  47. ((CProjectRecord *) m_pcdOwner)->SetRCModifiedFlag(TRUE) ;
  48. } ;
  49. }
  50. // Name ourselves and children- default to just our name, no children
  51. void CBasicNode::Fill(CTreeCtrl *pctcWhere, HTREEITEM htiParent) {
  52. m_pctcOwner = pctcWhere;
  53. m_hti = pctcWhere -> InsertItem(m_csName, htiParent);
  54. pctcWhere -> SetItemData(m_hti, PtrToUlong(this));
  55. }
  56. // Display a context menu using the ID array, if it has any members
  57. void CBasicNode::ContextMenu(CWnd *pcw, CPoint cp) {
  58. if (!m_cwaMenuID.GetSize())
  59. return;
  60. CMenu cmThis;
  61. if (!cmThis.CreatePopupMenu())
  62. return;
  63. for (int i = 0; i < m_cwaMenuID.GetSize(); i++) {
  64. if (m_cwaMenuID[i]) {
  65. CString csWork;
  66. csWork.LoadString(m_cwaMenuID[i]);
  67. cmThis.AppendMenu(MF_STRING | MF_ENABLED, m_cwaMenuID[i], csWork);
  68. }
  69. else
  70. cmThis.AppendMenu(MF_SEPARATOR);
  71. }
  72. cmThis.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, cp.x, cp.y, pcw);
  73. }
  74. // This override is called if our label is edited, or we are otherwise
  75. // renamed...
  76. BOOL CBasicNode::Rename(LPCTSTR lpstrNewName) {
  77. if (!lpstrNewName)
  78. return FALSE;
  79. if (lpstrNewName == m_csName)
  80. return TRUE;
  81. // We'll return TRUE, unless the rename produces an exception
  82. try {
  83. m_csName = lpstrNewName;
  84. }
  85. catch (CException *pce) {
  86. pce -> ReportError();
  87. pce -> Delete();
  88. return FALSE;
  89. }
  90. WorkspaceChange();
  91. return TRUE;
  92. }
  93. void CBasicNode::Edit() {
  94. if (!m_pcmcwEdit)
  95. m_pcmcwEdit = CreateEditor();
  96. else {
  97. if (IsWindow(m_pcmcwEdit -> m_hWnd))
  98. m_pcmcwEdit -> ActivateFrame();
  99. else
  100. m_pcmcwEdit = CreateEditor();
  101. } ;
  102. }
  103. /******************************************************************************\
  104. CBasicNode::GetEditor
  105. Get the node's editor frame pointer and check to see if it is valid. Return
  106. it if it is valid. If it isn't valid, clear the pointer and return NULL.
  107. ******************************************************************************/
  108. CMDIChildWnd* CBasicNode::GetEditor()
  109. {
  110. if (m_pcmcwEdit != NULL && !IsWindow(m_pcmcwEdit->m_hWnd))
  111. m_pcmcwEdit = NULL ;
  112. return m_pcmcwEdit ;
  113. }
  114. /******************************************************************************\
  115. CBasicNode::UniqueName
  116. Add a character or replace a character in the node's name to try to make it
  117. unique. The new character will be in one of the following ranges a-z or
  118. 0-9.
  119. ******************************************************************************/
  120. void CBasicNode::UniqueName(bool bsizematters, bool bfile, LPCTSTR lpstrpath)
  121. {
  122. CString csnew(m_csName) ;
  123. TCHAR tch ; // Unique character
  124. int nposlen ; // Name's change position/length
  125. // Determine the 0-based length of the name
  126. nposlen = csnew.GetLength() - 1 ;
  127. // If the name has been changed before, use the last "unique" character to
  128. // determine the new unique character. Then replace the old unique
  129. // character with the new unique character.
  130. if (m_bUniqueNameChange) {
  131. tch = csnew.GetAt(nposlen) + 1 ;
  132. if (tch == _T('{'))
  133. tch = _T('0') ;
  134. else if (tch == _T(':'))
  135. tch = _T('a') ;
  136. csnew.SetAt(nposlen, tch) ;
  137. // If the name has not been changed before, add a unique character to the
  138. // end of the name if this won't make the name longer than 8 characters
  139. // or we don't care how long the name is. Otherwise, replace the last
  140. // character with the new unique character.
  141. } else {
  142. if (nposlen < 7 || !bsizematters)
  143. csnew += _T("a") ;
  144. else
  145. csnew.SetAt(nposlen, _T('a')) ;
  146. } ;
  147. // Rename the node/file by calling the appropriate Rename() routine. If
  148. // CFileNode::Rename() m_csName must be zapped to force it to take the
  149. // correct code path. In addition, the file's path must be prepended to
  150. // its name.
  151. if (bfile) {
  152. m_csName.Empty() ;
  153. csnew = lpstrpath + csnew ;
  154. Rename(csnew) ;
  155. } else
  156. CBasicNode::Rename(csnew) ;
  157. // Indicate that the name has been changed.
  158. m_bUniqueNameChange = true ;
  159. }
  160. /******************************************************************************\
  161. CBasicNode::Serialize
  162. Pretty simple- the names the only field we will be keeping...
  163. ******************************************************************************/
  164. void CBasicNode::Serialize(CArchive& car) {
  165. CObject::Serialize(car);
  166. if (car.IsLoading())
  167. car >> m_csName;
  168. else
  169. car << m_csName;
  170. }
  171. /******************************************************************************
  172. CFixedNode implementation
  173. ******************************************************************************/
  174. IMPLEMENT_DYNAMIC(CFixedNode, CBasicNode)
  175. CFixedNode::CFixedNode(unsigned uidName, CSafeObArray& csoa, FIXEDNODETYPE fnt,
  176. CMultiDocTemplate *pcmdt, CRuntimeClass *pcrc) :
  177. m_csoaDescendants(csoa) {
  178. m_uidName = uidName;
  179. m_fntType = fnt;
  180. m_pcmdt = pcmdt;
  181. m_pcrc = pcrc;
  182. }
  183. /******************************************************************************
  184. CFixedNode::Zap
  185. This method is called when an underlying object is to be destroyed. It finds
  186. a matching pointer in the array, and then deletes that entry.
  187. ******************************************************************************/
  188. void CFixedNode::Zap(CProjectNode *pcpn, BOOL bdelfile)
  189. {
  190. // Try to find the node we want to delete in the array of descendants for
  191. // this node. Just return if it can't be found.
  192. for (unsigned u = 0; u < m_csoaDescendants.GetSize(); u++) {
  193. if (pcpn == m_csoaDescendants[u])
  194. break ;
  195. } ;
  196. if (u >= m_csoaDescendants.GetSize())
  197. return ;
  198. // If the user wants to remove the file too, do it.
  199. if (bdelfile)
  200. DeleteFile(pcpn->FileName()) ;
  201. // Save a copy of the node's tree handle
  202. HTREEITEM htiGone = pcpn->Handle() ;
  203. // Remove the project node from the array of descendants and delete it from
  204. // the tree.
  205. m_csoaDescendants.RemoveAt(u);
  206. m_pctcOwner -> DeleteItem(htiGone);
  207. // Update this (fixed) node's entry in the tree so that it will accurately
  208. // reflect the new number of descendants.
  209. CString csWork;
  210. csWork.Format(_TEXT(" (%d)"), m_csoaDescendants.GetSize());
  211. m_csName.LoadString(m_uidName);
  212. m_csName += csWork;
  213. m_pctcOwner -> SetItemText(m_hti, m_csName);
  214. // Mark the workspace and RC file as needing to be saved.
  215. WorkspaceChange(TRUE, TRUE);
  216. }
  217. /******************************************************************************
  218. CFixedNode::Import
  219. This member function will import one or more files of the given type if there
  220. is a document template and dynamic constructor available. It uses the
  221. template to customize the File Open dialog, and the constructor to build the
  222. elements.
  223. NOTE: There is a fair amount of common code between this routine and
  224. Copy(). If a bug/change is made in this routine, check to see if the
  225. same change needs to be made to Copy().
  226. ******************************************************************************/
  227. void CFixedNode::Import() {
  228. if (!m_pcmdt || !m_pcrc || !m_pcrc -> m_pfnCreateObject)
  229. return;
  230. CString csExtension, csFilter;
  231. m_pcmdt -> GetDocString(csExtension, CDocTemplate::filterExt);
  232. m_pcmdt -> GetDocString(csFilter, CDocTemplate::filterName);
  233. csFilter += _T("|*") + csExtension + _T("||");
  234. CFileDialog cfd(TRUE, csExtension, NULL,
  235. OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT, csFilter,
  236. m_pctcOwner);
  237. // raid 104822
  238. cfd.m_ofn.lpstrFile = new char[4096];
  239. memset(cfd.m_ofn.lpstrFile,0,4096);
  240. cfd.m_ofn.nMaxFile = 4096;
  241. if (cfd.DoModal() != IDOK) {
  242. delete cfd.m_ofn.lpstrFile ;
  243. return;
  244. }
  245. // Get the first, new RC ID to use if this is a resource node.
  246. int nnewrcid = GetNextRCID() ;
  247. // Build a path to the directory for the added files. The path is node
  248. // type specific.
  249. CString csnodepath = ((CDriverResources *) m_pcbnWorkspace)->GetW2000Path() ;
  250. if (csnodepath.Right(1) != _T("\\"))
  251. csnodepath += _T("\\") ;
  252. CString cstmp ;
  253. if (m_fntType == FNT_UFMS)
  254. cstmp.LoadString(IDS_FontDir) ;
  255. else if (m_fntType == FNT_GTTS)
  256. cstmp.LoadString(IDS_GTTDir) ;
  257. csnodepath += cstmp ;
  258. // Import all of the named files...
  259. CString cssrc ; // Source fspec
  260. for (POSITION pos = cfd.GetStartPosition(); pos; ) {
  261. // Create the underlying object using dynamic creation. Only a
  262. // CProjectNode has the required function, here.
  263. CProjectNode* pcpn = (CProjectNode *) m_pcrc -> CreateObject();
  264. if (!pcpn || !pcpn -> IsKindOf(RUNTIME_CLASS(CProjectNode))) {
  265. TRACE("Imported object not derived from CProjectNode");
  266. delete pcpn;
  267. continue;
  268. }
  269. // If the file is already in the right directory, make sure that it is
  270. // not already a part of the workspace.
  271. cssrc = cfd.GetNextPathName(pos) ;
  272. if (csnodepath.CompareNoCase(cssrc.Left(csnodepath.GetLength())) == 0) {
  273. if (IsFileInWorkspace(cssrc)) {
  274. // Build and display error message. Then skip this file.
  275. CString csmsg ;
  276. csmsg.Format(IDS_AddDupError, cssrc) ;
  277. AfxMessageBox(csmsg) ;
  278. delete pcpn ;
  279. continue ;
  280. } ;
  281. cstmp = cssrc ;
  282. // If the file is not in the right directory, try to copy it there.
  283. } else {
  284. cstmp = cssrc.Mid(cssrc.ReverseFind(_T('\\')) + 1) ;
  285. cstmp = csnodepath + cstmp ;
  286. if (!CopyFile(cssrc, cstmp, TRUE)) {
  287. // Build and display error message. Then skip this file.
  288. CString csmsg ;
  289. csmsg.Format(IDS_AddCopyFailed, cssrc,
  290. csnodepath.Left(csnodepath.GetLength() - 1)) ;
  291. csmsg += cstmp ;
  292. AfxMessageBox(csmsg) ;
  293. delete pcpn ;
  294. continue ;
  295. } ;
  296. } ;
  297. // Initialize the new node
  298. // RAID: 17897 :
  299. // Add CModelData::GetKeywordValue
  300. // CBN::Rename(ModelName) after SetFileName() by pcpn->Rename(ModelName)
  301. CModelData cmd;
  302. pcpn -> SetFileName(cstmp); //goes to CBN::Rename(FileName)
  303. if (m_fntType == FNT_GPDS) //add 1/3
  304. pcpn ->Rename(cmd.GetKeywordValue(cstmp,_T("ModelName"))); //add 2/3
  305. else //add 3/3
  306. pcpn -> Rename(pcpn -> FileTitle());
  307. pcpn -> NoteOwner(*m_pcdOwner);
  308. pcpn -> SetWorkspace(m_pcbnWorkspace);
  309. m_csoaDescendants.Add(pcpn);
  310. WorkspaceChange(TRUE, TRUE);
  311. pcpn -> EditorInfo(m_pcmdt);
  312. // load actual UFM, GTT data. // raid 128653
  313. if (m_fntType == FNT_UFMS ) {
  314. CFontInfo *pfi = (CFontInfo* )pcpn;
  315. CDriverResources* pcdr = (CDriverResources*) pfi->GetWorkspace() ;
  316. pcdr -> LinkAndLoadFont(*pfi,TRUE);
  317. }
  318. else if (m_fntType == FNT_GTTS) {
  319. CGlyphMap *pcgm = (CGlyphMap* ) pcpn;
  320. pcgm ->Load();
  321. } ;
  322. // Add the new node to the workspace view
  323. pcpn -> Fill(m_pctcOwner, m_hti, nnewrcid++, m_fntType);
  324. } ;
  325. delete cfd.m_ofn.lpstrFile;
  326. // Now, update our own appearance (get the count right)
  327. CString csWork;
  328. csWork.Format(_TEXT(" (%d)"), m_csoaDescendants.GetSize());
  329. m_csName.LoadString(m_uidName);
  330. m_csName += csWork;
  331. m_pctcOwner -> SetItemText(m_hti, m_csName);
  332. }
  333. /******************************************************************************
  334. CFixedNode::Copy
  335. This member function will make a copy of one the this node's children. The
  336. UI needed to determine the source child and the destination file name was
  337. done in CProjectView and the information is passed into this routine.
  338. NOTE: There is a fair amount of common code between this routine and
  339. Import(). If a bug/change is made in this routine, check to see if the
  340. same change needs to be made to Import().
  341. ******************************************************************************/
  342. void CFixedNode::Copy(CProjectNode *pcpnsrc, CString csorgdest)
  343. {
  344. // Can't do anything if the following pointers are set.
  345. if (!m_pcmdt || !m_pcrc || !m_pcrc -> m_pfnCreateObject)
  346. return;
  347. // Build the destination filespec by isolating the name in the destination
  348. // string and adding on this source's path and extension.
  349. CString csdest(csorgdest) ;
  350. int npos ;
  351. if ((npos = csdest.ReverseFind(_T('\\'))) != -1)
  352. csdest = csdest.Mid(npos + 1) ;
  353. if ((npos = csdest.ReverseFind(_T('.'))) != -1)
  354. csdest = csdest.Left(npos) ;
  355. if (csdest.GetLength() <= 0) {
  356. csdest.Format(IDS_CopyNameError, csorgdest) ;
  357. AfxMessageBox(csdest) ;
  358. return ;
  359. } ;
  360. csdest = csdest + pcpnsrc->FileExt() ;
  361. CString csdesttitleext(csdest) ;
  362. csdest = pcpnsrc->FilePath() + csdest ;
  363. // Copy the source file to the destination
  364. if (!CopyFile(pcpnsrc->FileName(), csdest, TRUE)) {
  365. // Build and display error message. Then return.
  366. CString csmsg, cspath(pcpnsrc->FilePath()) ;
  367. cspath.Left(cspath.GetLength() - 1) ;
  368. csmsg.Format(IDS_CopyCopyFailed, pcpnsrc->FileTitleExt(),
  369. csdesttitleext, cspath) ;
  370. AfxMessageBox(csmsg) ;
  371. return ;
  372. } ;
  373. // Create the underlying object using dynamic creation. Only a
  374. // CProjectNode has the required function, here.
  375. int nnewrcid = GetNextRCID() ;
  376. CProjectNode* pcpn = (CProjectNode *) m_pcrc -> CreateObject();
  377. if (!pcpn || !pcpn -> IsKindOf(RUNTIME_CLASS(CProjectNode))) {
  378. TRACE("Imported object not derived from CProjectNode");
  379. delete pcpn;
  380. return;
  381. } ;
  382. // Initialize the new node
  383. pcpn->SetFileName(csdest);
  384. pcpn->Rename(pcpn->FileTitle());
  385. pcpn->NoteOwner(*m_pcdOwner);
  386. pcpn->SetWorkspace(m_pcbnWorkspace);
  387. m_csoaDescendants.Add(pcpn);
  388. WorkspaceChange(TRUE, TRUE);
  389. pcpn->EditorInfo(m_pcmdt);
  390. // Add the new node to the workspace view
  391. pcpn->Fill(m_pctcOwner, m_hti, nnewrcid, m_fntType);
  392. // Now, update our own appearance (get the count right)
  393. CString csWork;
  394. csWork.Format(_TEXT(" (%d)"), m_csoaDescendants.GetSize());
  395. m_csName.LoadString(m_uidName);
  396. m_csName += csWork;
  397. m_pctcOwner -> SetItemText(m_hti, m_csName);
  398. // Last but not least... If a new GPD was just added, tell the user to
  399. // change the name in the GPD to make sure it is unique.
  400. if (m_fntType == FNT_GPDS) {
  401. csdest.Format(IDS_GPDReminder, pcpn->Name()) ;
  402. AfxMessageBox(csdest) ;
  403. } ;
  404. }
  405. /******************************************************************************
  406. CFixedNode::GetNextRCID
  407. If this is a resource (UFM or GTT) node, all of its descendants have RC IDs.
  408. Find the largest one and return one greater than that for use in a new
  409. descendant. If this is not a resource node, just return -1.
  410. ******************************************************************************/
  411. int CFixedNode::GetNextRCID()
  412. {
  413. // Return -1 if this is not a resource node that requires RC IDs
  414. if (m_fntType != FNT_UFMS && m_fntType != FNT_GTTS)
  415. return -1 ;
  416. // Find the largest used RC ID. Use the descendant's index if it does not
  417. // have an RC ID.
  418. int nlargestusedid = 0 ;
  419. int nrcid ;
  420. for (unsigned u = 0; u < m_csoaDescendants.GetSize(); u++) {
  421. nrcid = ((CProjectNode *) m_csoaDescendants[u])->nGetRCID() ;
  422. if (nrcid == -1)
  423. nrcid = (int) u + 1 ;
  424. if (nrcid > nlargestusedid)
  425. nlargestusedid = nrcid ;
  426. } ;
  427. // Return the next RC ID to use
  428. return (nlargestusedid + 1) ;
  429. }
  430. /******************************************************************************
  431. CFixedNode::IsFileInWorkspace
  432. Check the node's descendants to see if one of them matches the given filespec.
  433. Return true if a match is found. Otherwise, return false.
  434. ******************************************************************************/
  435. bool CFixedNode::IsFileInWorkspace(LPCTSTR strfspec)
  436. {
  437. CString csdescfspec ; // Filespec for current descendant
  438. for (unsigned u = 0; u < m_csoaDescendants.GetSize(); u++) {
  439. csdescfspec = ((CProjectNode *) m_csoaDescendants[u])->FileName() ;
  440. if (csdescfspec.CompareNoCase(strfspec) == 0)
  441. return true ;
  442. } ;
  443. return false ;
  444. }
  445. /******************************************************************************
  446. CFixedNode::IsRCIDUnique
  447. Check the node's descendants to see if one of them has the same RC ID as the
  448. one passed in. Return true if a no match is found. Otherwise, return false.
  449. ******************************************************************************/
  450. bool CFixedNode::IsRCIDUnique(int nid)
  451. {
  452. for (unsigned u = 0; u < m_csoaDescendants.GetSize(); u++) {
  453. if (((CProjectNode *) m_csoaDescendants[u])->nGetRCID() == nid)
  454. return false ;
  455. }
  456. return true ;
  457. }
  458. /******************************************************************************
  459. CFixedNode::Fill
  460. This is a generic fill- the node names itself, then fills its node using the
  461. array of nodes given to it at init time.
  462. ******************************************************************************/
  463. void CFixedNode::Fill(CTreeCtrl *pctc, HTREEITEM hti) {
  464. CString csWork;
  465. // Add the number of descendants to the node's name IFF this is the UFMs,
  466. // GTTs, or GPDs nodes. Then add the node to the tree.
  467. m_csName.LoadString(m_uidName);
  468. if (m_fntType == FNT_UFMS || m_fntType == FNT_GTTS || m_fntType == FNT_GPDS) {
  469. csWork.Format(_TEXT(" (%d)"), m_csoaDescendants.GetSize());
  470. m_csName += csWork;
  471. } ;
  472. CBasicNode::Fill(pctc, hti);
  473. // Add this node's descendants to the tree.
  474. for (unsigned u = 0; u < m_csoaDescendants.GetSize(); u++)
  475. ((CProjectNode *) m_csoaDescendants[u]) -> Fill(pctc, m_hti, u + 1, m_fntType) ;
  476. }
  477. /******************************************************************************
  478. CStringsNode implementation
  479. ******************************************************************************/
  480. IMPLEMENT_DYNAMIC(CStringsNode, CBasicNode)
  481. CStringsNode::CStringsNode(unsigned uidName, CSafeObArray& csoa,
  482. FIXEDNODETYPE fnt, CMultiDocTemplate *pcmdt,
  483. CRuntimeClass *pcrc) : m_csoaDescendants(csoa) {
  484. m_uidName = uidName;
  485. m_fntType = fnt;
  486. m_pcmdt = pcmdt;
  487. m_pcrc = pcrc;
  488. m_nFirstSelRCID = -1 ;
  489. }
  490. /******************************************************************************
  491. CStringsNode::Fill
  492. This is a generic fill- the node names itself, then fills its node using the
  493. array of nodes given to it at init time.
  494. ******************************************************************************/
  495. void CStringsNode::Fill(CTreeCtrl *pctc, HTREEITEM hti) {
  496. CString csWork;
  497. // Add this node to the tree
  498. m_csName.LoadString(m_uidName);
  499. CBasicNode::Fill(pctc, hti);
  500. }
  501. /*****************************************************************************
  502. CStringsNode::CreateEditor
  503. This member function launches an editing view for the strings.
  504. ******************************************************************************/
  505. CMDIChildWnd* CStringsNode::CreateEditor()
  506. {
  507. // Allocate and initialize the document.
  508. CProjectRecord* cpr = (CProjectRecord*) m_pcdOwner ;
  509. CStringEditorDoc* pcsed = new CStringEditorDoc(this, cpr, cpr->GetStrTable()) ;
  510. // Set the editor's title
  511. CString cstitle ;
  512. cstitle.Format(IDS_StringEditorTitle, cpr->DriverName()) ;
  513. pcsed->SetTitle(cstitle) ;
  514. // Create the window.
  515. CMDIChildWnd* pcmcwnew ;
  516. pcmcwnew = (CMDIChildWnd *) m_pcmdt->CreateNewFrame(pcsed, NULL) ;
  517. // If the window was created, finish the initialization and return the
  518. // frame pointer. Otherwise, clean up and return NULL.
  519. if (pcmcwnew) {
  520. m_pcmdt->InitialUpdateFrame(pcmcwnew, pcsed, TRUE) ;
  521. m_pcmdt->AddDocument(pcsed) ;
  522. return pcmcwnew ;
  523. } else {
  524. delete pcsed ;
  525. return NULL ;
  526. } ;
  527. }
  528. /******************************************************************************
  529. CFileNode implementation
  530. ******************************************************************************/
  531. IMPLEMENT_SERIAL(CFileNode, CBasicNode, 0);
  532. CFileNode::CFileNode() {
  533. m_cwaMenuID.Add(ID_RenameItem);
  534. m_bEditPath = FALSE;
  535. m_bCheckForValidity = TRUE;
  536. }
  537. /******************************************************************************
  538. CFileNode::Rename
  539. If there is no name currently, then see if the named file can be created.
  540. The other case, means the file should already be on the disk, so it is a bit
  541. trickier.
  542. First, check to see if the name violates the current naming conventions. If
  543. so, reject it. Then attempt to move the file. IF the name is OK and the
  544. file is moved, set the new name in the item label. Always returns FALSE.
  545. ******************************************************************************/
  546. BOOL CFileNode::Rename(LPCTSTR lpstrNew) {
  547. CString csNew = lpstrNew;
  548. if (!lpstrNew) { // This only happens if the label edit was canceled.
  549. csNew.LoadString(IDS_FileName);
  550. if (m_pctcOwner)
  551. m_pctcOwner -> SetItemText(m_hti, csNew + ViewName());
  552. WorkspaceChange(TRUE, TRUE); // ** Parameters might be wrong
  553. return FALSE;
  554. }
  555. // Add an extension to the file name if it is needed.
  556. if (m_csExtension.CompareNoCase(csNew.Right(m_csExtension.GetLength())))
  557. csNew += m_csExtension;
  558. // This path is taken when a driver is being converted.
  559. if (m_csName.IsEmpty()) {
  560. CFile cfTemp;
  561. // This check needs to be optional since in some instances, we know
  562. // the name is valid because the file is open, and we're just trying
  563. // to collect the name.
  564. if (!cfTemp.Open(csNew, CFile::modeCreate | CFile::modeNoTruncate |
  565. CFile::modeWrite | CFile::shareDenyNone) && m_bCheckForValidity) {
  566. CString csWork, csDisplay;
  567. csWork.LoadString(IDS_InvalidFilename);
  568. csDisplay.Format(csWork, (LPCTSTR) csNew);
  569. AfxMessageBox(csDisplay);
  570. return FALSE;
  571. }
  572. try {
  573. m_csPath = cfTemp.GetFilePath();
  574. m_csPath = m_csPath.Left(1 + m_csPath.ReverseFind(_T('\\')));
  575. }
  576. catch (CException *pce) {
  577. pce -> ReportError();
  578. pce -> Delete();
  579. return FALSE;
  580. }
  581. // If the file type isn't registered, then GetFileTitle returns the
  582. // extension, so strip it!
  583. csNew = cfTemp.GetFileTitle();
  584. if (!m_csExtension.CompareNoCase(csNew.Right(
  585. m_csExtension.GetLength())))
  586. csNew = csNew.Left(csNew.GetLength() - m_csExtension.GetLength());
  587. return CBasicNode::Rename(csNew); // OK from this path
  588. }
  589. // Strip any path if it cannot be changed, and substitute the real one
  590. if (!m_bEditPath)
  591. csNew = m_csPath + csNew.Mid(1 + csNew.ReverseFind(_T('\\')));
  592. try {
  593. LPSTR lpstr;
  594. CFile::Rename(FullName(), csNew);
  595. GetFullPathName(csNew, MAX_PATH, csNew.GetBuffer(MAX_PATH), &lpstr);
  596. csNew.ReleaseBuffer();
  597. m_csPath = csNew.Left(1 + csNew.ReverseFind(_T('\\')));
  598. csNew = csNew.Mid(m_csPath.GetLength());
  599. m_csName = csNew.Left(csNew.GetLength() -
  600. m_csExtension.GetLength());
  601. csNew.LoadString(IDS_FileName);
  602. if (m_pctcOwner)
  603. m_pctcOwner -> SetItemText(m_hti, csNew + m_csName);
  604. WorkspaceChange(TRUE, TRUE);
  605. return FALSE; // Force the change (above) to be kept.
  606. }
  607. catch (CFileException *pcfe) { // Don't get a file name with statics
  608. if (pcfe -> m_cause == ERROR_FILE_NOT_FOUND)
  609. csNew = FullName();
  610. pcfe -> m_strFileName = csNew;
  611. pcfe -> ReportError();
  612. pcfe -> Delete();
  613. return FALSE;
  614. }
  615. catch (CException *pce) {
  616. pce -> ReportError();
  617. pce -> Delete();
  618. return FALSE;
  619. }
  620. }
  621. /******************************************************************************
  622. CFileNode::SetPathAndName
  623. Set the node's path and file name in a way that works when someone has
  624. directly editted the UFM table in the RC file. This is the only time that
  625. this routine should be called. It doesn't perform any checks. We rely on the
  626. person who editted the RC file to have done it correctly.
  627. ******************************************************************************/
  628. void CFileNode::SetPathAndName(LPCTSTR lpstrpath, LPCTSTR lpstrname)
  629. {
  630. m_csPath = lpstrpath ;
  631. m_csName = lpstrname ;
  632. }
  633. /******************************************************************************
  634. CFileNode::CanEdit
  635. This will return TRUE, but it will first have to remove the File Name: stuff
  636. from the label, so we can get a cleaner edit.
  637. ******************************************************************************/
  638. BOOL CFileNode::CanEdit() const {
  639. CEdit* pce = m_pctcOwner -> GetEditControl();
  640. if (pce)
  641. pce -> SetWindowText(m_bEditPath ? m_csPath + m_csName : m_csName);
  642. return !!pce;
  643. }
  644. /******************************************************************************
  645. CFileNode::Fill
  646. We play a bit of a game here, changing our name temporarily to use the base
  647. class implementation.
  648. ******************************************************************************/
  649. void CFileNode::Fill(CTreeCtrl* pctc, HTREEITEM htiParent) {
  650. CString csTemp = Name();
  651. m_csName.LoadString(IDS_FileName);
  652. m_csName += csTemp;
  653. CBasicNode::Fill(pctc, htiParent);
  654. m_csName = csTemp;
  655. }
  656. /******************************************************************************
  657. CFileNode::Serialize
  658. Since the name is covered by the base class, we only need to serialize the
  659. boolean controlling long/short file names. The file paths are only handled
  660. in down level versions of the MDW.
  661. ******************************************************************************/
  662. void CFileNode::Serialize(CArchive& car)
  663. {
  664. CBasicNode::Serialize(car) ;
  665. // The file path is only kept in the MDW file when the MDW version is less
  666. // than MDW_VER_NO_FILE_PATHS. Process it in this case.
  667. unsigned uver = ((CProjectRecord*) car.m_pDocument)->GetMDWVersion() ;
  668. if (uver >= MDW_VER_YES_FILE_PATHS) { // raid 123448
  669. if (car.IsLoading())
  670. car >> m_csPath ;
  671. else
  672. car << m_csPath ;
  673. } ;
  674. }
  675. /******************************************************************************
  676. CProjectNode implementation
  677. ******************************************************************************/
  678. IMPLEMENT_SERIAL(CProjectNode, CBasicNode, 1)
  679. CProjectNode::CProjectNode()
  680. {
  681. m_pcmdt = NULL ;
  682. m_bRefFlag = false ; // Clear the referenced flag
  683. }
  684. void CProjectNode::Fill(CTreeCtrl *pctc, HTREEITEM hti, unsigned urcid,
  685. FIXEDNODETYPE fnt)
  686. {
  687. // Add this node to the tree
  688. CBasicNode::Fill(pctc, hti);
  689. // Add this node's file node to the tree
  690. m_cfn.SetWorkspace(m_pcbnWorkspace);
  691. m_cfn.Fill(pctc, m_hti);
  692. // Add this node's RC ID node to the tree IFF it needs to use it
  693. if (fnt == FNT_UFMS || fnt == FNT_GTTS) {
  694. m_crinRCID.SetWorkspace(m_pcbnWorkspace) ;
  695. m_crinRCID.Fill(pctc, m_hti, urcid, fnt) ;
  696. } ;
  697. }
  698. void CProjectNode::Serialize(CArchive& car)
  699. {
  700. CBasicNode::Serialize(car);
  701. m_cfn.Serialize(car);
  702. m_crinRCID.Serialize(car);
  703. }
  704. void CProjectNode::ChangeID(CRCIDNode* prcidn, int nnewid, CString csrestype)
  705. {
  706. // Walk back up the hierarchy to find this project node's owning Fixed node.
  707. CFixedNode& cfn = * (CFixedNode *) m_pctcOwner->GetItemData(
  708. m_pctcOwner->GetParentItem(m_hti)) ;
  709. ASSERT(cfn.IsKindOf(RUNTIME_CLASS(CFixedNode))) ;
  710. // Make sure that the new ID is unique for this resource type
  711. if (!cfn.IsRCIDUnique(nnewid)) {
  712. CString csmsg ;
  713. csmsg.Format(IDS_IDNotUnique, nnewid, csrestype) ;
  714. AfxMessageBox(csmsg) ;
  715. return ;
  716. } ;
  717. // Change this node's ID, update the display, and mark the workspace and
  718. // RC file as needing to be saved.
  719. nSetRCID(nnewid) ;
  720. m_crinRCID.BuildDisplayName() ;
  721. m_pctcOwner->SetItemText(m_crinRCID.Handle(), m_crinRCID.Name()) ;
  722. WorkspaceChange(TRUE, TRUE);
  723. }
  724. ///////////////////////////////////////////////////////////////////////////////
  725. //
  726. // CRCIDNode Implementation
  727. //
  728. // Note: This class must be enhanced to support extra functionality.
  729. //
  730. IMPLEMENT_SERIAL(CRCIDNode, CBasicNode, 0) ;
  731. CRCIDNode::CRCIDNode()
  732. {
  733. // Initialze as unset or unknown.
  734. m_nRCID = -9999 ;
  735. m_fntType = FNT_UNKNOWN ;
  736. // Build the context sensitive menu for this node type
  737. m_cwaMenuID.Add(ID_ChangeID);
  738. }
  739. /******************************************************************************
  740. CRCIDNode::Fill
  741. Add the RC ID node for the current resource to the workspace view.
  742. ******************************************************************************/
  743. void CRCIDNode::Fill(CTreeCtrl *pctc, HTREEITEM hti, int nid, FIXEDNODETYPE fnt)
  744. {
  745. // Set the RC ID and the node type. The info passed in should only be used
  746. // if these member variables are "unset". (This class has other functions
  747. // that can be used to change these variables once they've been set.)
  748. if (m_nRCID == -9999) // raid 167257
  749. m_nRCID = nid ;
  750. if (m_fntType == FNT_UNKNOWN)
  751. m_fntType = fnt ;
  752. // Build the string to display for this node based on the RC ID & node type
  753. BuildDisplayName() ;
  754. // Add the node to the view
  755. CBasicNode::Fill(pctc, hti);
  756. }
  757. void CRCIDNode::BuildDisplayName()
  758. {
  759. CString csid ; // Holds ID string
  760. // Build the string to display for this node based on the RC ID & node type
  761. if (m_nRCID != -9999)
  762. csid.Format(_T("%d"), m_nRCID) ;
  763. else
  764. csid.LoadString(IDS_Unknown) ;
  765. switch (m_fntType) {
  766. case FNT_UFMS:
  767. m_csName.Format(IDS_RCUFM, csid) ;
  768. break ;
  769. case FNT_GTTS:
  770. m_csName.Format(IDS_RCGTT, csid) ;
  771. break ;
  772. default :
  773. m_csName.Format(IDS_RCUNK, csid) ;
  774. break ;
  775. } ;
  776. }
  777. void CRCIDNode::Serialize(CArchive& car)
  778. {
  779. int nfnt = (int) m_fntType ; // CArchive doesn't handle enumerations
  780. CBasicNode::Serialize(car);
  781. if (car.IsLoading())
  782. car >> m_nRCID >> nfnt ;
  783. else
  784. car << m_nRCID << nfnt ;
  785. }