wdtview.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. // WDTView.cpp : implementation file
  19. //
  20. #include "stdafx.h"
  21. #include "wdump.h"
  22. #include "WDTView.h"
  23. #include "wdumpdoc.h"
  24. #include "chunk_d.h"
  25. #include "finddialog.h"
  26. #ifdef _DEBUG
  27. #define new DEBUG_NEW
  28. #undef THIS_FILE
  29. static char THIS_FILE[] = __FILE__;
  30. #endif
  31. /////////////////////////////////////////////////////////////////////////////
  32. // CWDumpTreeView
  33. IMPLEMENT_DYNCREATE(CWDumpTreeView, CTreeView)
  34. CWDumpTreeView::CWDumpTreeView()
  35. {
  36. }
  37. CWDumpTreeView::~CWDumpTreeView()
  38. {
  39. }
  40. BEGIN_MESSAGE_MAP(CWDumpTreeView, CTreeView)
  41. //{{AFX_MSG_MAP(CWDumpTreeView)
  42. ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelchanged)
  43. ON_COMMAND(IDM_TOOLS_FIND, OnToolsFind)
  44. ON_COMMAND(IDM_TOOLS_FIND_NEXT, OnToolsFindNext)
  45. //}}AFX_MSG_MAP
  46. END_MESSAGE_MAP()
  47. /////////////////////////////////////////////////////////////////////////////
  48. // CWDumpTreeView drawing
  49. void CWDumpTreeView::OnDraw(CDC* pDC)
  50. {
  51. CDocument* pDoc = GetDocument();
  52. // TODO: add draw code here
  53. }
  54. /////////////////////////////////////////////////////////////////////////////
  55. // CWDumpTreeView diagnostics
  56. #ifdef _DEBUG
  57. void CWDumpTreeView::AssertValid() const
  58. {
  59. CTreeView::AssertValid();
  60. }
  61. void CWDumpTreeView::Dump(CDumpContext& dc) const
  62. {
  63. CTreeView::Dump(dc);
  64. }
  65. #endif //_DEBUG
  66. /////////////////////////////////////////////////////////////////////////////
  67. // CWDumpTreeView message handlers
  68. void CWDumpTreeView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
  69. {
  70. // add all the chunk items to the view
  71. CTreeCtrl &tree = GetTreeCtrl();
  72. tree.DeleteAllItems();
  73. long flags = tree.GetStyle();
  74. flags |= TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_SHOWSELALWAYS | TVS_DISABLEDRAGDROP;
  75. SetWindowLong(tree.GetSafeHwnd(), GWL_STYLE, flags);
  76. CWdumpDoc *doc= (CWdumpDoc *) GetDocument();
  77. ChunkData *data = &doc->m_ChunkData;
  78. POSITION p = data->Chunks.GetHeadPosition();
  79. while(p) {
  80. ChunkItem *item = data->Chunks.GetNext(p);
  81. InsertItem(item);
  82. }
  83. }
  84. void CWDumpTreeView::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult)
  85. {
  86. NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
  87. CWdumpDoc *doc= (CWdumpDoc *) GetDocument();
  88. doc->m_ChunkItem = (ChunkItem *) pNMTreeView->itemNew.lParam;
  89. doc->UpdateAllViews(this);
  90. *pResult = 0;
  91. }
  92. void CWDumpTreeView::InsertItem(ChunkItem * item, HTREEITEM Parent)
  93. {
  94. const char *name;
  95. if(item->Type)
  96. name = item->Type->Name;
  97. else {
  98. static char _buf[256];
  99. sprintf(_buf,"Unknown: id=0x%X",item->ID);
  100. name = _buf;
  101. }
  102. CTreeCtrl &tree = GetTreeCtrl();
  103. HTREEITEM tree_item = tree.InsertItem(name, Parent);
  104. tree.SetItem(tree_item, TVIF_PARAM,0,0,0,0,0, (long) item);
  105. POSITION p = item->Chunks.GetHeadPosition();
  106. while(p != 0) {
  107. ChunkItem *subitem = item->Chunks.GetNext(p);
  108. InsertItem(subitem, tree_item);
  109. }
  110. }
  111. void CWDumpTreeView::OnToolsFind()
  112. {
  113. FindDialog finder;
  114. if (finder.DoModal() == IDOK) {
  115. // If there is a string go find it.
  116. if (strlen (FindDialog::String()) > 0) {
  117. OnToolsFindNext();
  118. }
  119. }
  120. }
  121. void CWDumpTreeView::OnToolsFindNext()
  122. {
  123. ChunkItem *matchedchunkitem;
  124. // If no string go request one.
  125. if (strlen (FindDialog::String()) == 0) {
  126. OnToolsFind();
  127. } else {
  128. FindDialog::Found (false);
  129. // Iterate over all chunks in the hierarchy. If a match is found select the tree
  130. // item that corresponds to the matched chunk item.
  131. {
  132. CWaitCursor waitcursor;
  133. HTREEITEM selectedtreeitem;
  134. ChunkItem *selectedchunkitem;
  135. SearchStateEnum searchstate;
  136. CWdumpDoc *doc = (CWdumpDoc *) GetDocument();
  137. ChunkData *data = &doc->m_ChunkData;
  138. POSITION p;
  139. // Get the currently selected chunk item.
  140. selectedtreeitem = GetTreeCtrl().GetSelectedItem();
  141. if (selectedtreeitem != NULL) {
  142. selectedchunkitem = (ChunkItem*) GetTreeCtrl().GetItemData (selectedtreeitem);
  143. searchstate = FIND_SELECTED_ITEM;
  144. } else {
  145. selectedchunkitem = NULL;
  146. searchstate = FIND_STRING;
  147. }
  148. p = 0;
  149. matchedchunkitem = NULL;
  150. while (true) {
  151. ChunkItem *chunkitem;
  152. // Get the root chunk item.
  153. if (p == 0) {
  154. p = data->Chunks.GetHeadPosition();
  155. if (p == 0) break;
  156. }
  157. chunkitem = data->Chunks.GetNext (p);
  158. matchedchunkitem = FindChunkItem (selectedchunkitem, chunkitem, searchstate);
  159. if ((matchedchunkitem != NULL) || (searchstate == SEARCH_WRAPPED)) break;
  160. }
  161. }
  162. // Was a match found?
  163. if (matchedchunkitem != NULL) {
  164. SelectTreeItem (GetTreeCtrl().GetRootItem(), matchedchunkitem);
  165. } else {
  166. const char *controlstring = "Cannot find \"%s\".";
  167. char *message;
  168. message = new char [strlen (controlstring) + strlen (FindDialog::String())];
  169. ASSERT (message != NULL);
  170. sprintf (message, controlstring, FindDialog::String());
  171. MessageBox (message, "Find String", MB_OK | MB_ICONEXCLAMATION);
  172. delete [] message;
  173. }
  174. }
  175. }
  176. ChunkItem *CWDumpTreeView::FindChunkItem (ChunkItem *selectedchunkitem, ChunkItem *chunkitem, SearchStateEnum &searchstate)
  177. {
  178. // Searching for the currently selected item or looking for a match?
  179. switch (searchstate) {
  180. case FIND_SELECTED_ITEM:
  181. // Searching for the currently selected chunk item.
  182. if (chunkitem == selectedchunkitem) {
  183. searchstate = FIND_STRING;
  184. }
  185. break;
  186. case FIND_STRING:
  187. // Searching for a string associated with the chunk item.
  188. if (chunkitem == selectedchunkitem) {
  189. searchstate = SEARCH_WRAPPED;
  190. return (NULL);
  191. } else {
  192. if ((chunkitem != 0) && (chunkitem->Type != 0) && (chunkitem->Type->Callback != 0)) {
  193. (*chunkitem->Type->Callback)(chunkitem, NULL);
  194. }
  195. if (FindDialog::Found()) return (chunkitem);
  196. }
  197. break;
  198. case SEARCH_WRAPPED:
  199. // This case should never occur at this point. As soon as it has been detected
  200. // that the search has wrapped the stack should unwind immediately.
  201. ASSERT (FALSE);
  202. return (NULL);
  203. break;
  204. }
  205. // Iterate over all chunks in the hierarchy. Return immediately if a match is found or if the search has wrapped.
  206. POSITION p = chunkitem->Chunks.GetHeadPosition();
  207. while (p != 0) {
  208. ChunkItem *subchunkitem, *matchedchunkitem;
  209. subchunkitem = chunkitem->Chunks.GetNext (p);
  210. matchedchunkitem = FindChunkItem (selectedchunkitem, subchunkitem, searchstate);
  211. if ((matchedchunkitem != NULL) || (searchstate == SEARCH_WRAPPED)) return (matchedchunkitem);
  212. }
  213. // No match found.
  214. return (NULL);
  215. }
  216. void CWDumpTreeView::SelectTreeItem (HTREEITEM treeitem, ChunkItem *chunkitem)
  217. {
  218. CTreeCtrl &tree = GetTreeCtrl();
  219. // Select a tree item that matches the given chunk item. Recurse if necessary.
  220. while (treeitem != NULL) {
  221. HTREEITEM subtreeitem;
  222. if (tree.GetItemData (treeitem) == (DWORD) chunkitem) {
  223. tree.SelectItem (treeitem);
  224. }
  225. subtreeitem = tree.GetChildItem (treeitem);
  226. if (subtreeitem != NULL) {
  227. SelectTreeItem (subtreeitem, chunkitem);
  228. }
  229. treeitem = tree.GetNextSiblingItem (treeitem);
  230. }
  231. }