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.

3026 lines
81 KiB

  1. /*++
  2. Copyright (c) 1992-2002 Microsoft Corporation
  3. Module Name:
  4. dualwin.cpp
  5. Abstract:
  6. Header for new window architecture functions.
  7. --*/
  8. #include "precomp.hxx"
  9. #pragma hdrstop
  10. #define NAME_BUFFER 1024
  11. BOOL g_UseTextMode = FALSE;
  12. //
  13. // DUALLISTWIN_DATA methods
  14. //
  15. DUALLISTWIN_DATA::DUALLISTWIN_DATA(ULONG ChangeBy)
  16. : SINGLE_CHILDWIN_DATA(ChangeBy)
  17. {
  18. m_wFlags = DL_EDIT_SECONDPANE;
  19. m_hwndEditControl = NULL;
  20. m_nItem_LastSelected = -1;
  21. m_nSubItem_LastSelected = 0;
  22. m_nItem_CurrentlyEditing = -1;
  23. m_nSubItem_CurrentlyEditing = -1;
  24. }
  25. void
  26. DUALLISTWIN_DATA::Validate()
  27. {
  28. SINGLE_CHILDWIN_DATA::Validate();
  29. }
  30. void
  31. DUALLISTWIN_DATA::SetFont(ULONG FontIndex)
  32. {
  33. SINGLE_CHILDWIN_DATA::SetFont(FontIndex);
  34. SendMessage(m_hwndEditControl, WM_SETFONT,
  35. (WPARAM)m_Font->Font, TRUE);
  36. }
  37. BOOL
  38. DUALLISTWIN_DATA::OnCreate(void)
  39. {
  40. m_hwndChild = CreateWindowEx(
  41. WS_EX_CLIENTEDGE, // Extended style
  42. WC_LISTVIEW, // class name
  43. NULL, // title
  44. WS_CHILD | WS_VISIBLE
  45. | WS_MAXIMIZE
  46. | WS_HSCROLL | WS_VSCROLL
  47. | LVS_SHOWSELALWAYS
  48. | LVS_REPORT | LVS_SINGLESEL
  49. | ((m_enumType != CPU_WINDOW)
  50. ? LVS_OWNERDRAWFIXED : 0), // style
  51. 0, // x
  52. 0, // y
  53. CW_USEDEFAULT, // width
  54. CW_USEDEFAULT, // height
  55. m_Win, // parent
  56. 0, // control id
  57. g_hInst, // hInstance
  58. NULL // user defined data
  59. );
  60. if (m_hwndChild == NULL)
  61. {
  62. return FALSE;
  63. }
  64. m_hwndEditControl = CreateWindowEx(
  65. 0, // Extended style
  66. RICHEDIT_CLASS, // class name
  67. NULL, // title
  68. WS_CHILD,
  69. 0, // x
  70. 0, // y
  71. CW_USEDEFAULT, // width
  72. CW_USEDEFAULT, // height
  73. m_Win, // parent
  74. 0, // control id
  75. g_hInst, // hInstance
  76. NULL // user defined data
  77. );
  78. if (m_hwndEditControl == NULL)
  79. {
  80. DestroyWindow(m_hwndChild);
  81. return FALSE;
  82. }
  83. SetFont(FONT_FIXED);
  84. SendMessage(m_hwndEditControl,
  85. EM_SETEVENTMASK,
  86. 0,
  87. (LPARAM) ENM_KEYEVENTS | ENM_MOUSEEVENTS
  88. );
  89. ListView_SetBkColor(m_hwndChild, g_Colors[COL_PLAIN].Color);
  90. ListView_SetTextBkColor(m_hwndChild, g_Colors[COL_PLAIN].Color);
  91. ListView_SetTextColor(m_hwndChild, g_Colors[COL_PLAIN_TEXT].Color);
  92. return TRUE;
  93. }
  94. LRESULT
  95. DUALLISTWIN_DATA::OnCommand(
  96. WPARAM wParam,
  97. LPARAM lParam
  98. )
  99. {
  100. WORD wCode = HIWORD(wParam);
  101. WORD wId = LOWORD(wParam);
  102. HWND hwnd = (HWND) lParam;
  103. if (hwnd != m_hwndEditControl)
  104. {
  105. return 1; // Not handled
  106. }
  107. switch (wCode)
  108. {
  109. default:
  110. return 1; // not handled
  111. case EN_KILLFOCUS:
  112. //
  113. // Duplicate code in OnNotify : EN_MSGFILTER
  114. //
  115. if (-1 != m_nItem_CurrentlyEditing)
  116. {
  117. if (!SetItemFromEdit(m_nItem_CurrentlyEditing,
  118. m_nSubItem_CurrentlyEditing))
  119. {
  120. break;
  121. }
  122. ShowWindow(hwnd, SW_HIDE);
  123. SetFocus(m_hwndChild);
  124. InvalidateItem(m_nItem_CurrentlyEditing);
  125. m_nItem_CurrentlyEditing = -1;
  126. m_nSubItem_CurrentlyEditing = -1;
  127. }
  128. break;
  129. }
  130. return 0;
  131. }
  132. LRESULT
  133. DUALLISTWIN_DATA::OnNotify(
  134. WPARAM wParam,
  135. LPARAM lParam
  136. )
  137. {
  138. // Branch depending on the specific notification message.
  139. switch (((LPNMHDR) lParam)->code)
  140. {
  141. case LVN_ITEMCHANGED:
  142. InvalidateItem( ((LPNMLISTVIEW) lParam)->iItem);
  143. break;
  144. case NM_CLICK:
  145. case NM_DBLCLK:
  146. // Figure out whether an item or a sub-item was clicked
  147. OnClick((LPNMLISTVIEW) lParam);
  148. break;
  149. case NM_CUSTOMDRAW:
  150. return OnCustomDraw((LPNMLVCUSTOMDRAW)lParam);
  151. case EN_MSGFILTER:
  152. //
  153. // Duplicate code in OnCommand : EN_KILLFOCUS
  154. //
  155. if (WM_KEYDOWN == ((MSGFILTER *)lParam)->msg)
  156. {
  157. MSGFILTER * pMsgFilter = (MSGFILTER *) lParam;
  158. switch (pMsgFilter->wParam)
  159. {
  160. case VK_RETURN:
  161. // Ignore this message so the richedit
  162. // doesn't beep.
  163. return 1;
  164. }
  165. }
  166. else if (WM_CHAR == ((MSGFILTER *)lParam)->msg)
  167. {
  168. MSGFILTER * pMsgFilter = (MSGFILTER *) lParam;
  169. switch (pMsgFilter->wParam)
  170. {
  171. case VK_RETURN:
  172. if (!SetItemFromEdit(m_nItem_CurrentlyEditing,
  173. m_nSubItem_CurrentlyEditing))
  174. {
  175. break;
  176. }
  177. // fall through...
  178. case VK_ESCAPE:
  179. InvalidateItem(m_nItem_CurrentlyEditing);
  180. //
  181. // Invalidate these before changing focus, so that Itemchanged
  182. // doesn't get called again on same item
  183. //
  184. m_nItem_CurrentlyEditing = -1;
  185. m_nSubItem_CurrentlyEditing = -1;
  186. //
  187. // Hide the edit box and set focus to the list view
  188. //
  189. ShowWindow(m_hwndEditControl, SW_HIDE);
  190. SetFocus(m_hwndChild);
  191. break;
  192. }
  193. }
  194. else if (WM_RBUTTONDOWN == ((MSGFILTER *)lParam)->msg ||
  195. WM_RBUTTONDBLCLK == ((MSGFILTER *)lParam)->msg)
  196. {
  197. // process cpoy/passte selection
  198. if (CanCopy())
  199. {
  200. Copy();
  201. CHARRANGE Sel;
  202. SendMessage(m_hwndEditControl, EM_EXGETSEL, 0, (LPARAM)&Sel);
  203. Sel.cpMax = Sel.cpMin;
  204. SendMessage(m_hwndEditControl, EM_EXSETSEL, 0, (LPARAM)&Sel);
  205. }
  206. else if (SendMessage(m_hwndEditControl, EM_CANPASTE, CF_TEXT, 0))
  207. {
  208. SetFocus(m_hwndEditControl);
  209. Paste();
  210. }
  211. // Ignore right-button events.
  212. return 1;
  213. }
  214. return 0; // process this message
  215. case LVN_COLUMNCLICK:
  216. // LVN_COLUMNCLICK pnmv = (LPNMLISTVIEW) lParam;
  217. break;
  218. }
  219. return DefMDIChildProc(m_Win, WM_NOTIFY, wParam, lParam);
  220. }
  221. BOOL
  222. DUALLISTWIN_DATA::ClearList(ULONG ClearFrom)
  223. {
  224. if (!ClearFrom)
  225. {
  226. return ListView_DeleteAllItems(m_hwndChild);
  227. }
  228. else
  229. {
  230. ULONG nItems = ListView_GetItemCount(m_hwndChild);
  231. BOOL res = TRUE;
  232. while (res && (ClearFrom < nItems))
  233. {
  234. res = ListView_DeleteItem(m_hwndChild, --nItems);
  235. }
  236. return res;
  237. }
  238. }
  239. void
  240. DUALLISTWIN_DATA::InvalidateItem(
  241. int nItem
  242. )
  243. {
  244. RECT rc = {0};
  245. if (-1 == nItem)
  246. {
  247. // Invalidate the entire window
  248. GetClientRect(m_hwndChild, &rc);
  249. }
  250. else
  251. {
  252. // Invalidate the item row
  253. if (!ListView_GetItemRect(m_hwndChild,nItem,&rc,LVIR_BOUNDS))
  254. {
  255. // Invalidate the entire window
  256. GetClientRect(m_hwndChild, &rc);
  257. }
  258. }
  259. InvalidateRect(m_hwndChild, &rc, TRUE);
  260. }
  261. void
  262. DUALLISTWIN_DATA::ItemChanged(
  263. int Item,
  264. PCSTR Text
  265. )
  266. {
  267. // Do-nothing placeholder.
  268. }
  269. LRESULT
  270. DUALLISTWIN_DATA::OnCustomDraw(LPNMLVCUSTOMDRAW Custom)
  271. {
  272. static int s_SelectedItem = -1;
  273. static ULONG s_SubItem;
  274. if (Custom->nmcd.hdr.hwndFrom != m_hwndChild)
  275. {
  276. return CDRF_DODEFAULT;
  277. }
  278. switch (Custom->nmcd.dwDrawStage)
  279. {
  280. case CDDS_PREPAINT:
  281. s_SelectedItem = ListView_GetNextItem(m_hwndChild, -1, LVNI_SELECTED);
  282. if (m_wFlags & DL_CUSTOM_ITEMS)
  283. {
  284. return CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTPAINT;
  285. }
  286. else
  287. {
  288. return CDRF_NOTIFYPOSTPAINT;
  289. }
  290. case CDDS_ITEMPREPAINT:
  291. s_SubItem = 0;
  292. return CDRF_NOTIFYSUBITEMDRAW;
  293. case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
  294. return OnCustomItem(s_SubItem++, Custom);
  295. case CDDS_POSTPAINT:
  296. if (-1 != s_SelectedItem)
  297. {
  298. RECT rc;
  299. // If we ask for subitem 0, then we get the rectangle for the
  300. // entire item, so we ask for item 1, and do the math
  301. Dbg( ListView_GetSubItemRect(m_hwndChild,
  302. s_SelectedItem,
  303. 1,
  304. LVIR_BOUNDS,
  305. &rc));
  306. if (0 == m_nSubItem_LastSelected)
  307. {
  308. rc.right = rc.left - 1;
  309. rc.left = 0;
  310. }
  311. InvertRect(Custom->nmcd.hdc, &rc);
  312. }
  313. return CDRF_NOTIFYPOSTPAINT;
  314. default:
  315. return 0;
  316. }
  317. }
  318. LRESULT
  319. DUALLISTWIN_DATA::OnCustomItem(ULONG SubItem, LPNMLVCUSTOMDRAW Custom)
  320. {
  321. return CDRF_DODEFAULT;
  322. }
  323. void
  324. DUALLISTWIN_DATA::OnClick(
  325. LPNMLISTVIEW Notify
  326. )
  327. {
  328. LVHITTESTINFO lvHTInfo = {0};
  329. lvHTInfo.pt = Notify->ptAction;
  330. if (-1 != ListView_SubItemHitTest(m_hwndChild, &lvHTInfo) )
  331. {
  332. // success
  333. //
  334. // If the user click on a different item than the one currently selected
  335. // then the LVN_ITEMCHANGED message will take care of updating the screen.
  336. //
  337. // If the user clicked on the currently slected item then we need to
  338. // check whether he wants to edit the contents or select a different subitem.
  339. //
  340. if (m_nItem_CurrentlyEditing == lvHTInfo.iItem
  341. && m_nSubItem_CurrentlyEditing == lvHTInfo.iSubItem)
  342. {
  343. ShowWindow(m_hwndEditControl, SW_SHOW);
  344. SetFocus(m_hwndEditControl);
  345. } else if (m_nItem_LastSelected == lvHTInfo.iItem
  346. && m_nSubItem_LastSelected == lvHTInfo.iSubItem)
  347. {
  348. // If we clicked on the currently selected item & subitem
  349. // then the user wants to edit the text.
  350. //
  351. // Is editing allowed
  352. if ( ( (0 == m_nSubItem_LastSelected) &&
  353. (m_wFlags & DL_EDIT_LEFTPANE) ) ||
  354. ( (1 == m_nSubItem_LastSelected) &&
  355. (m_wFlags & DL_EDIT_SECONDPANE) ) ||
  356. ( (2 == m_nSubItem_LastSelected) &&
  357. (m_wFlags & DL_EDIT_THIRDPANE) ) )
  358. {
  359. m_nItem_CurrentlyEditing = m_nItem_LastSelected;
  360. m_nSubItem_CurrentlyEditing = m_nSubItem_LastSelected;
  361. EditText();
  362. }
  363. }
  364. else
  365. {
  366. // User wants to select a different subitem
  367. m_nItem_LastSelected = lvHTInfo.iItem;
  368. m_nSubItem_LastSelected = lvHTInfo.iSubItem;
  369. InvalidateItem(lvHTInfo.iItem);
  370. }
  371. }
  372. }
  373. void
  374. DUALLISTWIN_DATA::EditText()
  375. {
  376. RECT rc;
  377. TCHAR sz[NAME_BUFFER * 10], *psz;
  378. // Get the item's text
  379. ListView_GetItemText(m_hwndChild,
  380. m_nItem_CurrentlyEditing,
  381. m_nSubItem_CurrentlyEditing,
  382. sz,
  383. _tsizeof(sz)
  384. );
  385. // If we ask for subitem 0, then we get the rectangle for the
  386. // entire item, so we ask for item m_nItem_CurrentlyEditing, and do the math
  387. // if we need subitem 0
  388. Dbg( ListView_GetSubItemRect(m_hwndChild,
  389. m_nItem_CurrentlyEditing,
  390. (m_nSubItem_CurrentlyEditing ? m_nSubItem_CurrentlyEditing : 1),
  391. LVIR_BOUNDS,
  392. &rc));
  393. psz = &sz[0];
  394. if (0 == m_nSubItem_CurrentlyEditing)
  395. {
  396. rc.right = rc.left - 1;
  397. rc.left = 0;
  398. while (*psz && (*psz == ' ')) {
  399. ++psz;
  400. }
  401. }
  402. SetWindowText(m_hwndEditControl, psz);
  403. CHARRANGE charRange={0};
  404. charRange.cpMax = strlen(psz);
  405. charRange.cpMin = 0;
  406. SendMessage(m_hwndEditControl, EM_EXSETSEL, (WPARAM) 0, (LPARAM) &charRange);
  407. SendMessage(m_hwndEditControl, EM_SETSEL, (WPARAM) 0, (LPARAM) -1);
  408. POINT ChildBase = {0, 0};
  409. MapWindowPoints(m_hwndChild, m_Win, &ChildBase, 1);
  410. MoveWindow(m_hwndEditControl,
  411. rc.left + ChildBase.x,
  412. rc.top + ChildBase.y,
  413. rc.right - rc.left,
  414. rc.bottom - rc.top,
  415. FALSE);
  416. ShowWindow(m_hwndEditControl, SW_SHOW);
  417. SetFocus(m_hwndEditControl);
  418. }
  419. BOOL
  420. DUALLISTWIN_DATA::CanCopy()
  421. {
  422. HWND hwnd = (m_nItem_CurrentlyEditing == -1) ? m_hwndChild : m_hwndEditControl;
  423. CHARRANGE chrg;
  424. SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM) (CHARRANGE *) &chrg);
  425. return chrg.cpMin != chrg.cpMax;
  426. }
  427. BOOL
  428. DUALLISTWIN_DATA::CanCut()
  429. {
  430. return(m_nItem_CurrentlyEditing != -1) && CanCopy();
  431. }
  432. BOOL
  433. DUALLISTWIN_DATA::CanPaste()
  434. {
  435. return(m_nItem_CurrentlyEditing != -1)
  436. && SendMessage(m_hwndEditControl,
  437. EM_CANPASTE,
  438. CF_TEXT,
  439. 0
  440. );
  441. }
  442. CHAR ListCopy[500];
  443. void
  444. DUALLISTWIN_DATA::Copy()
  445. {
  446. if ((m_nItem_CurrentlyEditing == -1) &&
  447. (m_nItem_LastSelected != -1))
  448. {
  449. PCHAR sz = &ListCopy[0];
  450. ZeroMemory(sz, sizeof(ListCopy));
  451. if (!GlobalLock( (HGLOBAL) sz))
  452. {
  453. return;
  454. }
  455. ListView_GetItemText(m_hwndChild, m_nItem_LastSelected, m_nSubItem_LastSelected,
  456. sz, sizeof(ListCopy));
  457. CopyToClipboard(sz, FALSE);
  458. }
  459. else
  460. {
  461. SendMessage(m_hwndEditControl, WM_COPY, 0, 0);
  462. }
  463. }
  464. void
  465. DUALLISTWIN_DATA::Cut()
  466. {
  467. SendMessage(m_hwndEditControl, WM_CUT, 0, 0);
  468. }
  469. void
  470. DUALLISTWIN_DATA::Paste()
  471. {
  472. SendMessage(m_hwndEditControl, WM_PASTE, 0, 0);
  473. }
  474. void
  475. DUALLISTWIN_DATA::UpdateColors(void)
  476. {
  477. // Update the general colors and force a repaint to
  478. // get the text updated. Specific colors will be
  479. // applied by custom drawing.
  480. ListView_SetBkColor(m_hwndChild, g_Colors[COL_PLAIN].Color);
  481. ListView_SetTextBkColor(m_hwndChild, g_Colors[COL_PLAIN].Color);
  482. ListView_SetTextColor(m_hwndChild, g_Colors[COL_PLAIN_TEXT].Color);
  483. InvalidateRect(m_hwndChild, NULL, FALSE);
  484. }
  485. ULONG
  486. DUALLISTWIN_DATA::GetItemFlags(ULONG Item)
  487. {
  488. LVITEM LvItem;
  489. LvItem.mask = LVIF_PARAM;
  490. LvItem.iItem = Item;
  491. LvItem.iSubItem = 0;
  492. if (ListView_GetItem(m_hwndChild, &LvItem))
  493. {
  494. return (ULONG)LvItem.lParam;
  495. }
  496. else
  497. {
  498. return 0;
  499. }
  500. }
  501. void
  502. DUALLISTWIN_DATA::SetItemFlags(ULONG Item, ULONG Flags)
  503. {
  504. LVITEM LvItem;
  505. LvItem.mask = LVIF_PARAM;
  506. LvItem.iItem = Item;
  507. LvItem.iSubItem = 0;
  508. LvItem.lParam = (LPARAM)Flags;
  509. ListView_SetItem(m_hwndChild, &LvItem);
  510. }
  511. BOOL
  512. DUALLISTWIN_DATA::SetItemFromEdit(ULONG Item, ULONG SubItem)
  513. {
  514. //
  515. // Save the text from the edit box to list item.
  516. //
  517. int nLen = GetWindowTextLength(m_hwndEditControl) + 1;
  518. PTSTR psz = (PTSTR)calloc( nLen, sizeof(TCHAR) );
  519. if (psz == NULL)
  520. {
  521. return FALSE;
  522. }
  523. GetWindowText(m_hwndEditControl, psz, nLen);
  524. ListView_SetItemText(m_hwndChild, Item, SubItem, psz);
  525. SetItemFlags(Item, GetItemFlags(Item) | ITEM_CHANGED);
  526. ItemChanged(Item, psz);
  527. free(psz);
  528. return TRUE;
  529. }
  530. //
  531. // SYMWIN_DATA methods
  532. //
  533. HMENU SYMWIN_DATA::s_ContextMenu;
  534. SYMWIN_DATA::SYMWIN_DATA(IDebugSymbolGroup **pDbgSymbolGroup)
  535. : DUALLISTWIN_DATA(2048)
  536. {
  537. m_pWinSyms = NULL;
  538. m_nWinSyms = 0;
  539. m_pDbgSymbolGroup = pDbgSymbolGroup;
  540. m_NumSymsDisplayed = 0;
  541. m_DisplayTypes = FALSE;
  542. m_DisplayOffsets = FALSE;
  543. m_RefreshItem = 0;
  544. m_UpdateItem = -1;
  545. m_SplitWindowAtItem = 0;
  546. m_MaxNameWidth = 0;
  547. m_NumCols = 0;
  548. m_RefreshValues = TRUE;
  549. SetMaxSyms(1);
  550. // Use text for Accessibility readers
  551. SystemParametersInfo(SPI_GETSCREENREADER, 0, &g_UseTextMode, 0);
  552. }
  553. #define VALUE_COLM 1
  554. #define TYPE_COLM 2
  555. #define OFFSET_COLM (m_DisplayTypes ? 3 : 2)
  556. SYMWIN_DATA::~SYMWIN_DATA()
  557. {
  558. if (m_pWinSyms)
  559. {
  560. free (m_pWinSyms);
  561. }
  562. return;
  563. }
  564. void
  565. SYMWIN_DATA::Validate()
  566. {
  567. DUALLISTWIN_DATA::Validate();
  568. }
  569. #define SYMWIN_CONTEXT_ID_BASE 0x100
  570. #define SYMWIN_TBB_TYPECAST 0
  571. #define SYMWIN_TBB_OFFSETS 1
  572. TBBUTTON g_SymWinTbButtons[] =
  573. {
  574. TEXT_TB_BTN(SYMWIN_TBB_TYPECAST, "Typecast", BTNS_CHECK),
  575. TEXT_TB_BTN(SYMWIN_TBB_OFFSETS, "Offsets", BTNS_CHECK),
  576. SEP_TB_BTN(),
  577. TEXT_TB_BTN(ID_SHOW_TOOLBAR, "Toolbar", 0),
  578. };
  579. #define NUM_SYMWIN_MENU_BUTTONS \
  580. (sizeof(g_SymWinTbButtons) / sizeof(g_SymWinTbButtons[0]))
  581. #define NUM_SYMWIN_TB_BUTTONS \
  582. (NUM_SYMWIN_MENU_BUTTONS - 2)
  583. #define IsAParent(Sym) ((Sym)->SubElements)
  584. #define SYM_LEVEL(sym) ((sym)->Flags & DEBUG_SYMBOL_EXPANSION_LEVEL_MASK)
  585. #define IsRootSym(Sym) !SYM_LEVEL(Sym)
  586. HMENU
  587. SYMWIN_DATA::GetContextMenu(void)
  588. {
  589. //
  590. // We only keep one menu around for all call windows
  591. // so apply the menu check state for this particular
  592. // window.
  593. //
  594. CheckMenuItem(s_ContextMenu, SYMWIN_TBB_TYPECAST + SYMWIN_CONTEXT_ID_BASE,
  595. MF_BYCOMMAND | (m_DisplayTypes ? MF_CHECKED : 0));
  596. CheckMenuItem(s_ContextMenu, SYMWIN_TBB_OFFSETS + SYMWIN_CONTEXT_ID_BASE,
  597. MF_BYCOMMAND | (m_DisplayOffsets ? MF_CHECKED : 0));
  598. CheckMenuItem(s_ContextMenu, ID_SHOW_TOOLBAR + SYMWIN_CONTEXT_ID_BASE,
  599. MF_BYCOMMAND | (m_ShowToolbar ? MF_CHECKED : 0));
  600. return s_ContextMenu;
  601. }
  602. void
  603. SYMWIN_DATA::OnContextMenuSelection(UINT Item)
  604. {
  605. ULONG Changed = 0;
  606. Item -= SYMWIN_CONTEXT_ID_BASE;
  607. switch(Item)
  608. {
  609. case SYMWIN_TBB_TYPECAST:
  610. SetDisplayTypes(Item, !m_DisplayTypes);
  611. Changed = 1 << SYMWIN_TBB_TYPECAST;
  612. break;
  613. case SYMWIN_TBB_OFFSETS:
  614. SetDisplayTypes(Item, !m_DisplayOffsets);
  615. Changed = 1 << SYMWIN_TBB_OFFSETS;
  616. break;
  617. case ID_SHOW_TOOLBAR:
  618. SetShowToolbar(!m_ShowToolbar);
  619. break;
  620. }
  621. SyncUiWithFlags(Changed);
  622. }
  623. BOOL
  624. SYMWIN_DATA::OnCreate(void)
  625. {
  626. if (s_ContextMenu == NULL)
  627. {
  628. s_ContextMenu = CreateContextMenuFromToolbarButtons
  629. (NUM_SYMWIN_MENU_BUTTONS, g_SymWinTbButtons,
  630. SYMWIN_CONTEXT_ID_BASE);
  631. if (s_ContextMenu == NULL)
  632. {
  633. return FALSE;
  634. }
  635. }
  636. if (!DUALLISTWIN_DATA::OnCreate())
  637. {
  638. return FALSE;
  639. }
  640. m_Toolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
  641. WS_CHILD | WS_VISIBLE |
  642. TBSTYLE_WRAPABLE | TBSTYLE_LIST | CCS_TOP,
  643. 0, 0, m_Size.cx, 0, m_Win, (HMENU)ID_TOOLBAR,
  644. g_hInst, NULL);
  645. if (m_Toolbar == NULL)
  646. {
  647. return FALSE;
  648. }
  649. SendMessage(m_Toolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
  650. SendMessage(m_Toolbar, TB_ADDBUTTONS, NUM_SYMWIN_TB_BUTTONS,
  651. (LPARAM)&g_SymWinTbButtons);
  652. SendMessage(m_Toolbar, TB_AUTOSIZE, 0, 0);
  653. RECT Rect;
  654. GetClientRect(m_Toolbar, &Rect);
  655. m_ToolbarHeight = Rect.bottom - Rect.top + GetSystemMetrics(SM_CYEDGE);
  656. m_ShowToolbar = TRUE;
  657. SendMessage(m_hwndChild, WM_SETREDRAW, FALSE, 0);
  658. RECT rc;
  659. LV_COLUMN lvc = {0};
  660. GetClientRect(m_hwndChild, &rc);
  661. rc.right -= rc.left + GetSystemMetrics(SM_CXVSCROLL);
  662. //initialize the columns
  663. lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_TEXT;
  664. lvc.fmt = LVCFMT_LEFT;
  665. lvc.iSubItem = 0;
  666. lvc.cx = m_Font->Metrics.tmAveCharWidth * 20;
  667. if (lvc.cx > rc.right / 2)
  668. {
  669. lvc.cx = rc.right / 2;
  670. }
  671. lvc.pszText = _T("Name");
  672. Dbg( (0 == ListView_InsertColumn(m_hwndChild, 0, &lvc)) );
  673. // Give the rest of the space to the value.
  674. lvc.cx = rc.right - lvc.cx;
  675. lvc.pszText = _T("Value");
  676. Dbg( (1 == ListView_InsertColumn(m_hwndChild, 1, &lvc)) );
  677. m_NumCols = 2;
  678. ListView_SetExtendedListViewStyle(m_hwndChild,
  679. LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT
  680. );
  681. SendMessage(m_hwndChild, WM_SETREDRAW, TRUE, 0);
  682. InvalidateRect(m_hwndChild, NULL, TRUE);
  683. return TRUE;
  684. }
  685. void
  686. SYMWIN_DATA::OnSize(void)
  687. {
  688. DUALLISTWIN_DATA::OnSize();
  689. // ListView_SetColumnWidth(m_hwndChild, 0 , m_MaxNameWidth);
  690. }
  691. LRESULT
  692. SYMWIN_DATA::OnNotify(
  693. WPARAM wParam,
  694. LPARAM lParam
  695. )
  696. {
  697. if (((LPNMHDR) lParam)->code == LVN_KEYDOWN)
  698. {
  699. if (m_nItem_LastSelected != -1 &&
  700. m_nItem_CurrentlyEditing == -1 &&
  701. g_ExecStatus == DEBUG_STATUS_BREAK)
  702. {
  703. NMLVKEYDOWN * pNmKeyDown = (NMLVKEYDOWN *) lParam;
  704. switch (pNmKeyDown->wVKey)
  705. {
  706. case VK_LEFT:
  707. if (m_nSubItem_LastSelected == 0)
  708. {
  709. ExpandSymbol(m_nItem_LastSelected, FALSE);
  710. return TRUE;
  711. }
  712. break;
  713. case VK_RIGHT:
  714. if (m_nSubItem_LastSelected == 0)
  715. {
  716. ExpandSymbol(m_nItem_LastSelected, TRUE);
  717. return TRUE;
  718. }
  719. break;
  720. case VK_RETURN:
  721. switch (m_nSubItem_LastSelected) {
  722. case 0:
  723. if (IsRootSym(&m_pWinSyms[m_nItem_LastSelected]) && (m_enumType == WATCH_WINDOW))
  724. {
  725. m_nItem_CurrentlyEditing = m_nItem_LastSelected;
  726. m_nSubItem_CurrentlyEditing=0;
  727. EditText();
  728. }
  729. break;
  730. case 1:
  731. if (!(m_pWinSyms[m_nItem_LastSelected].Flags & DEBUG_SYMBOL_READ_ONLY))
  732. {
  733. m_nItem_CurrentlyEditing = m_nItem_LastSelected;
  734. m_nSubItem_CurrentlyEditing=1;
  735. EditText();
  736. }
  737. break;
  738. case 2:
  739. m_nItem_CurrentlyEditing = m_nItem_LastSelected;
  740. m_nSubItem_CurrentlyEditing=2;
  741. EditText();
  742. break;
  743. default:
  744. break;
  745. }
  746. break;
  747. default:
  748. break;
  749. }
  750. }
  751. }
  752. else if (((LPNMHDR) lParam)->code == LVN_ITEMCHANGED)
  753. {
  754. LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
  755. if (pnmv->uNewState & LVIS_SELECTED)
  756. {
  757. m_nItem_LastSelected = pnmv->iItem;
  758. m_nSubItem_LastSelected = pnmv->iSubItem;
  759. }
  760. }
  761. return DUALLISTWIN_DATA::OnNotify(wParam, lParam);
  762. }
  763. void
  764. SYMWIN_DATA::OnUpdate(
  765. UpdateType Type
  766. )
  767. {
  768. if (Type == UPDATE_EXEC)
  769. {
  770. // Disallow editing when the debuggee is running.
  771. if (g_ExecStatus == DEBUG_STATUS_BREAK)
  772. {
  773. if (m_enumType != LOCALS_WINDOW)
  774. {
  775. m_wFlags |= DL_EDIT_LEFTPANE;
  776. }
  777. else
  778. {
  779. m_wFlags &= ~DL_EDIT_LEFTPANE;
  780. }
  781. ListView_SetTextBkColor(m_hwndChild, g_Colors[COL_PLAIN].Color);
  782. }
  783. else
  784. {
  785. m_wFlags = 0;
  786. ListView_SetTextBkColor(m_hwndChild,
  787. g_Colors[COL_DISABLED_WINDOW].Color);
  788. }
  789. InvalidateRect(m_hwndChild, NULL, FALSE);
  790. return;
  791. }
  792. else if (Type != UPDATE_BUFFER)
  793. {
  794. return;
  795. }
  796. SendMessage(m_hwndChild, WM_SETREDRAW, FALSE, 0);
  797. UpdateNames();
  798. SendMessage(m_hwndChild, WM_SETREDRAW, TRUE, 0);
  799. InvalidateRect(m_hwndChild, NULL, TRUE);
  800. }
  801. void
  802. SYMWIN_DATA::ExpandSymbol(
  803. ULONG Index,
  804. BOOL Expand
  805. )
  806. {
  807. //
  808. // Expand the Item
  809. //
  810. UIC_SYMBOL_WIN_DATA* WatchItem;
  811. WatchItem = StartStructCommand(UIC_SYMBOL_WIN);
  812. if (WatchItem != NULL)
  813. {
  814. WatchItem->Type = EXPAND_SYMBOL;
  815. WatchItem->pSymbolGroup = m_pDbgSymbolGroup;
  816. WatchItem->u.ExpandSymbol.Index = Index;
  817. WatchItem->u.ExpandSymbol.Expand = Expand;
  818. FinishCommand();
  819. UiRequestRead();
  820. }
  821. }
  822. ULONG
  823. SYMWIN_DATA::GetWorkspaceSize(void)
  824. {
  825. return DUALLISTWIN_DATA::GetWorkspaceSize() + 2*sizeof(BOOL);
  826. }
  827. PUCHAR
  828. SYMWIN_DATA::SetWorkspace(PUCHAR Data)
  829. {
  830. Data = DUALLISTWIN_DATA::SetWorkspace(Data);
  831. *(PBOOL)Data = m_DisplayTypes;
  832. Data += sizeof(BOOL);
  833. *(PBOOL)Data = m_DisplayOffsets;
  834. Data += sizeof(BOOL);
  835. return Data;
  836. }
  837. PUCHAR
  838. SYMWIN_DATA::ApplyWorkspace1(PUCHAR Data, PUCHAR End)
  839. {
  840. UIC_SYMBOL_WIN_DATA* WatchItem;
  841. Data = DUALLISTWIN_DATA::ApplyWorkspace1(Data, End);
  842. // Clear the window
  843. WatchItem = StartStructCommand(UIC_SYMBOL_WIN);
  844. if (WatchItem != NULL)
  845. {
  846. WatchItem->Type = DEL_SYMBOL_WIN_ALL;
  847. WatchItem->pSymbolGroup = m_pDbgSymbolGroup;
  848. FinishCommand();
  849. }
  850. ULONG Changed = 0;
  851. if (End - Data >= sizeof(BOOL))
  852. {
  853. SetDisplayTypes(SYMWIN_TBB_TYPECAST, *(PBOOL)Data);
  854. Changed |= 1 << SYMWIN_TBB_TYPECAST;
  855. Data += sizeof(BOOL);
  856. }
  857. if (End - Data >= sizeof(BOOL))
  858. {
  859. SetDisplayTypes(SYMWIN_TBB_OFFSETS, *(PBOOL)Data);
  860. Changed |= 1 << SYMWIN_TBB_OFFSETS;
  861. Data += sizeof(BOOL);
  862. }
  863. SyncUiWithFlags(Changed);
  864. return Data;
  865. }
  866. BOOL
  867. SYMWIN_DATA::AddListItem(
  868. ULONG iItem,
  869. PSTR ItemText,
  870. ULONG Level,
  871. BOOL HasChildren,
  872. BOOL Expanded)
  873. {
  874. LVITEM LvItem = {0};
  875. CHAR Name[NAME_BUFFER], OldName[NAME_BUFFER];
  876. ULONG i;
  877. LvItem.mask = LVIF_TEXT | LVIF_INDENT;
  878. Name[0] = 0;
  879. ULONG NameUsed = strlen(Name);
  880. // HACK - Column autosize doesn't take indent into account
  881. // while autosizing the column, so padd with spaces in front to make it work
  882. i = 0;
  883. while (i <= (Level + 2) && i < sizeof(Name) - 1)
  884. {
  885. Name[i++] = ' ';
  886. }
  887. Name[i] = 0;
  888. CatString(Name, ItemText, DIMA(Name));
  889. LvItem.pszText = Name;
  890. LvItem.iItem = iItem;
  891. LvItem.iIndent = Level + 1;
  892. if ((ULONG)ListView_GetItemCount(m_hwndChild) <= iItem)
  893. {
  894. ListView_InsertItem(m_hwndChild, &LvItem);
  895. return TRUE;
  896. }
  897. else
  898. {
  899. ListView_GetItemText(m_hwndChild, iItem, 0, OldName, sizeof(OldName));
  900. ListView_SetItem(m_hwndChild, &LvItem);
  901. return (strcmp(Name, OldName) != 0);
  902. }
  903. }
  904. void
  905. SYMWIN_DATA::UpdateNames()
  906. {
  907. ULONG Sym, Items;
  908. PSTR Buf;
  909. PDEBUG_SYMBOL_PARAMETERS SymParams = GetSymParam();
  910. BOOL NameChanged;
  911. HDC hDC = GetDC(m_hwndChild);
  912. TEXTMETRIC tm = {0};
  913. Items = ListView_GetItemCount(m_hwndChild);
  914. GetTextMetrics(hDC, &tm);
  915. ReleaseDC(m_hwndChild, hDC);
  916. if (UiLockForRead() == S_OK)
  917. {
  918. Buf = (PSTR)GetDataBuffer();
  919. ULONG Len;
  920. CHAR Name[NAME_BUFFER], Value[NAME_BUFFER], Type[NAME_BUFFER], Offset[20];
  921. ULONG LastArgSym=-1, LastParent=0;
  922. Items = 0;
  923. if (m_UpdateItem < m_SplitWindowAtItem)
  924. {
  925. LastArgSym = m_UpdateItem;
  926. m_SplitWindowAtItem = 0;
  927. }
  928. for (Sym = m_UpdateItem; Sym < m_NumSymsDisplayed; Sym++)
  929. {
  930. PSTR EndTag;
  931. PSTR NameSt, NameEn;
  932. if (Buf == NULL)
  933. {
  934. strcpy(Name, _T("Unknown"));
  935. strcpy(Value, _T(""));
  936. }
  937. else
  938. {
  939. #if DBG_SYM_WIN
  940. DebugPrint("SYM_WIN: Buffer left %s\n", Buf);
  941. #endif
  942. Name[0] = 0;
  943. EndTag = strstr(Buf, DEBUG_OUTPUT_NAME_END);
  944. if (!EndTag)
  945. {
  946. break;
  947. }
  948. NameSt = Buf;
  949. NameEn = EndTag;
  950. Buf = EndTag + strlen(DEBUG_OUTPUT_NAME_END);
  951. EndTag = strstr(Buf, DEBUG_OUTPUT_VALUE_END);
  952. if (!EndTag)
  953. {
  954. break;
  955. }
  956. Len = (ULONG) (EndTag - Buf);
  957. if (Len >= sizeof(Value))
  958. {
  959. Len = sizeof(Value) - 1;
  960. }
  961. memcpy(Value, Buf, Len);
  962. Value[Len] = 0;
  963. Buf = EndTag + strlen(DEBUG_OUTPUT_VALUE_END);
  964. if (m_DisplayOffsets)
  965. {
  966. EndTag = strstr(Buf, DEBUG_OUTPUT_OFFSET_END);
  967. if (!EndTag)
  968. {
  969. EndTag = Buf;
  970. }
  971. Len = (ULONG) (EndTag - Buf);
  972. if (Len >= sizeof(Offset))
  973. {
  974. Len = sizeof(Offset) - 1;
  975. }
  976. memcpy(Offset, Buf, Len);
  977. Offset[Len] = 0;
  978. Buf = EndTag + strlen(DEBUG_OUTPUT_OFFSET_END);
  979. }
  980. Len = (ULONG) (NameEn - NameSt);
  981. if (Len >= sizeof(Name) - 10)
  982. {
  983. Len = sizeof(Name) - 11;
  984. }
  985. strncat(Name, NameSt, Len);
  986. Name[DIMA(Name) - 1] = 0;
  987. if (m_DisplayTypes)
  988. {
  989. EndTag = strstr(Buf, DEBUG_OUTPUT_TYPE_END);
  990. if (!EndTag)
  991. {
  992. EndTag = Buf;
  993. }
  994. Len = (ULONG) (EndTag - Buf);
  995. if (Len >= sizeof(Type))
  996. {
  997. Len = sizeof(Type) - 1;
  998. }
  999. memcpy(Type, Buf, Len);
  1000. Type[Len] = 0;
  1001. Buf = EndTag + strlen(DEBUG_OUTPUT_TYPE_END);
  1002. }
  1003. }
  1004. if (GetMaxSyms() > Sym)
  1005. {
  1006. NameChanged =
  1007. AddListItem(Sym, Name, SYM_LEVEL((SymParams + Sym)),
  1008. SymParams[Sym].SubElements,
  1009. SymParams[Sym].Flags & DEBUG_SYMBOL_EXPANDED);
  1010. }
  1011. else
  1012. {
  1013. break;
  1014. }
  1015. if (!(SymParams[Sym].Flags & DEBUG_SYMBOL_EXPANSION_LEVEL_MASK))
  1016. {
  1017. LastParent = Sym;
  1018. if ((SymParams[Sym].Flags & DEBUG_SYMBOL_IS_ARGUMENT) &&
  1019. (m_enumType == LOCALS_WINDOW))
  1020. {
  1021. LastArgSym = Sym;
  1022. }
  1023. if ((LastParent > LastArgSym) && !m_SplitWindowAtItem)
  1024. {
  1025. m_SplitWindowAtItem = Sym;
  1026. }
  1027. }
  1028. if (!NameChanged)
  1029. {
  1030. // Check if the value changed
  1031. PCHAR OldValue = &Name[0];
  1032. ListView_GetItemText(m_hwndChild, Sym, VALUE_COLM,
  1033. OldValue, sizeof(Name));
  1034. if (strcmp(OldValue, Value))
  1035. {
  1036. // Value changed
  1037. SymParams[Sym].Flags |= ITEM_VALUE_CHANGED;
  1038. }
  1039. else
  1040. {
  1041. SymParams[Sym].Flags &= ~ITEM_VALUE_CHANGED;
  1042. }
  1043. }
  1044. ListView_SetItemText(m_hwndChild, Sym, VALUE_COLM, Value);
  1045. if (m_DisplayOffsets)
  1046. {
  1047. ListView_SetItemText(m_hwndChild, Sym, OFFSET_COLM, Offset);
  1048. }
  1049. if (m_DisplayTypes)
  1050. {
  1051. ListView_SetItemText(m_hwndChild, Sym, TYPE_COLM, Type);
  1052. }
  1053. if (Sym < sizeof(m_ListItemLines))
  1054. {
  1055. m_ListItemLines[Sym] = 2;
  1056. }
  1057. }
  1058. UnlockStateBuffer(this);
  1059. }
  1060. ClearList(m_NumSymsDisplayed);
  1061. if (Items == 0 && (m_enumType == WATCH_WINDOW))
  1062. {
  1063. //
  1064. // add a dummy to enable adding new items
  1065. //
  1066. LVITEM LvItem = {0};
  1067. LvItem.mask = LVIF_TEXT | LVIF_INDENT;
  1068. LvItem.pszText = "";
  1069. LvItem.iItem = m_NumSymsDisplayed;
  1070. ListView_InsertItem(m_hwndChild, &LvItem);
  1071. // ListView_SetItemText(m_hwndChild, m_NumSymsDisplayed, 1, "Dummy");
  1072. }
  1073. m_MaxNameWidth = 0;
  1074. m_UpdateItem = -1;
  1075. }
  1076. #define ALLOCATE_CHUNK 0x100
  1077. HRESULT
  1078. SYMWIN_DATA::SetMaxSyms(
  1079. ULONG nSyms
  1080. )
  1081. {
  1082. if (m_nWinSyms < nSyms)
  1083. {
  1084. DEBUG_SYMBOL_PARAMETERS *TempSyms = m_pWinSyms;
  1085. m_nWinSyms = ALLOCATE_CHUNK * ((nSyms + ALLOCATE_CHUNK - 1 )/ ALLOCATE_CHUNK);
  1086. TempSyms = (DEBUG_SYMBOL_PARAMETERS *) realloc(m_pWinSyms, m_nWinSyms*sizeof(DEBUG_SYMBOL_PARAMETERS));
  1087. if (!TempSyms)
  1088. {
  1089. // malloc failed, free old allocations and bail with error below
  1090. if (m_pWinSyms)
  1091. {
  1092. free ( m_pWinSyms );
  1093. m_pWinSyms = NULL;
  1094. }
  1095. m_nWinSyms = 0;
  1096. return E_OUTOFMEMORY;
  1097. }
  1098. // move ptr to new memory address
  1099. m_pWinSyms = TempSyms;
  1100. }
  1101. return S_OK;
  1102. }
  1103. LRESULT
  1104. SYMWIN_DATA::OnCommand(
  1105. WPARAM wParam,
  1106. LPARAM lParam
  1107. )
  1108. {
  1109. if ((HWND) lParam == m_Toolbar)
  1110. {
  1111. OnContextMenuSelection(LOWORD(wParam) + SYMWIN_CONTEXT_ID_BASE);
  1112. return 0;
  1113. }
  1114. return DUALLISTWIN_DATA::OnCommand(wParam, lParam);
  1115. }
  1116. void
  1117. SYMWIN_DATA::OnClick(
  1118. LPNMLISTVIEW Notify
  1119. )
  1120. {
  1121. LVHITTESTINFO lvHTInfo = {0};
  1122. RECT itemRect;
  1123. ULONG item;
  1124. lvHTInfo.pt = Notify->ptAction;
  1125. if (-1 != ListView_SubItemHitTest(m_hwndChild, &lvHTInfo) &&
  1126. (m_NumSymsDisplayed > (ULONG) lvHTInfo.iItem) &&
  1127. (g_ExecStatus == DEBUG_STATUS_BREAK))
  1128. {
  1129. PDEBUG_SYMBOL_PARAMETERS SymParams = GetSymParam();
  1130. item = lvHTInfo.iItem;
  1131. if (ListView_GetItemRect(m_hwndChild, lvHTInfo.iItem, &itemRect, LVIR_BOUNDS))
  1132. {
  1133. if (((int) SYM_LEVEL(&SymParams[item]) * m_IndentWidth < Notify->ptAction.x) &&
  1134. (Notify->ptAction.x < (int) (itemRect.left + m_IndentWidth * (2+SYM_LEVEL(&SymParams[item])))) &&
  1135. (lvHTInfo.iSubItem == 0) &&
  1136. (SymParams[item].SubElements))
  1137. {
  1138. BOOL Expand = TRUE;
  1139. if (SymParams[item].SubElements)
  1140. {
  1141. if ((m_NumSymsDisplayed > item + 1) &&
  1142. (SymParams[item+1].ParentSymbol == item) &&
  1143. ((SymParams[item+1].Flags & DEBUG_SYMBOL_EXPANSION_LEVEL_MASK) ==
  1144. (SymParams[item].Flags & DEBUG_SYMBOL_EXPANSION_LEVEL_MASK) + 1))
  1145. {
  1146. //
  1147. // Already expanded
  1148. //
  1149. Expand = FALSE;
  1150. }
  1151. ExpandSymbol(item, Expand);
  1152. }
  1153. m_RefreshItem = item;
  1154. m_nItem_LastSelected = lvHTInfo.iItem;
  1155. m_nSubItem_LastSelected = lvHTInfo.iSubItem;
  1156. return;
  1157. }
  1158. }
  1159. //
  1160. // Check if ok to edit right pane
  1161. //
  1162. if (SymParams[lvHTInfo.iItem].Flags & DEBUG_SYMBOL_READ_ONLY)
  1163. {
  1164. m_wFlags &= ~DL_EDIT_SECONDPANE;
  1165. }
  1166. else
  1167. {
  1168. m_wFlags |= DL_EDIT_SECONDPANE;
  1169. }
  1170. //
  1171. // Check if ok to edit left pane
  1172. //
  1173. if ((SymParams[lvHTInfo.iItem].Flags & DEBUG_SYMBOL_EXPANSION_LEVEL_MASK) ||
  1174. (m_enumType != WATCH_WINDOW))
  1175. {
  1176. m_wFlags &= ~DL_EDIT_LEFTPANE;
  1177. }
  1178. else
  1179. {
  1180. m_wFlags |= DL_EDIT_LEFTPANE;
  1181. }
  1182. if (m_DisplayTypes)
  1183. {
  1184. m_wFlags |= DL_EDIT_THIRDPANE;
  1185. }
  1186. else
  1187. {
  1188. m_wFlags &= ~DL_EDIT_THIRDPANE;
  1189. }
  1190. }
  1191. else if ((m_enumType == WATCH_WINDOW) &&
  1192. (g_ExecStatus == DEBUG_STATUS_BREAK) &&
  1193. (m_NumSymsDisplayed == (ULONG) lvHTInfo.iItem))
  1194. {
  1195. m_wFlags |= DL_EDIT_LEFTPANE;
  1196. }
  1197. //
  1198. // Default processing
  1199. //
  1200. DUALLISTWIN_DATA::OnClick(Notify);
  1201. }
  1202. HRESULT
  1203. SYMWIN_DATA::ReadState(void)
  1204. {
  1205. HRESULT Status;
  1206. ULONG getSyms;
  1207. if (m_pDbgSymbolGroup == NULL ||
  1208. *m_pDbgSymbolGroup == NULL)
  1209. {
  1210. return E_UNEXPECTED;
  1211. }
  1212. (*m_pDbgSymbolGroup)->GetNumberSymbols(&m_NumSymsDisplayed);
  1213. if (m_NumSymsDisplayed < m_RefreshItem)
  1214. {
  1215. // numsyms changed since last click - might happen for locals
  1216. m_RefreshItem = 0;
  1217. }
  1218. getSyms = m_NumSymsDisplayed - m_RefreshItem;
  1219. if (m_NumSymsDisplayed > GetMaxSyms())
  1220. {
  1221. if ((Status = SetMaxSyms(m_NumSymsDisplayed)) != S_OK)
  1222. {
  1223. m_NumSymsDisplayed = 0;
  1224. return Status;
  1225. }
  1226. }
  1227. (*m_pDbgSymbolGroup)->GetSymbolParameters(m_RefreshItem, getSyms, GetSymParam() + m_RefreshItem);
  1228. Empty();
  1229. g_OutStateBuf.SetBuffer(this);
  1230. if ((Status = g_OutStateBuf.Start(TRUE)) != S_OK)
  1231. {
  1232. return Status;
  1233. }
  1234. (*m_pDbgSymbolGroup)->OutputSymbols(DEBUG_OUTCTL_THIS_CLIENT |
  1235. DEBUG_OUTCTL_OVERRIDE_MASK |
  1236. DEBUG_OUTCTL_NOT_LOGGED,
  1237. (m_DisplayOffsets ? 0 : DEBUG_OUTPUT_SYMBOLS_NO_OFFSETS) |
  1238. (m_DisplayTypes ? 0 : DEBUG_OUTPUT_SYMBOLS_NO_TYPES),
  1239. m_RefreshItem,
  1240. m_NumSymsDisplayed - m_RefreshItem);
  1241. Status = g_OutStateBuf.End(FALSE);
  1242. m_UpdateItem = m_RefreshItem;
  1243. m_RefreshItem = 0;
  1244. return Status;
  1245. }
  1246. void
  1247. SYMWIN_DATA::ItemChanged(int Item, PCSTR Text)
  1248. {
  1249. UIC_SYMBOL_WIN_DATA* WatchItem;
  1250. if (m_nItem_CurrentlyEditing == -1)
  1251. {
  1252. return;
  1253. }
  1254. if (m_nSubItem_CurrentlyEditing == 0)
  1255. {
  1256. //
  1257. // First delete, then add the item
  1258. //
  1259. if (Item < (int) GetMaxSyms() && Item < (int) m_NumSymsDisplayed)
  1260. {
  1261. //
  1262. // See if this item can be changed or not - only root and dummy can be chnged
  1263. //
  1264. if ((GetSymParam())[Item].Flags & DEBUG_SYMBOL_EXPANSION_LEVEL_MASK)
  1265. {
  1266. UiRequestRead();
  1267. return;
  1268. }
  1269. }
  1270. WatchItem = StartStructCommand(UIC_SYMBOL_WIN);
  1271. if (WatchItem != NULL)
  1272. {
  1273. WatchItem->Type = DEL_SYMBOL_WIN_INDEX;
  1274. WatchItem->pSymbolGroup = m_pDbgSymbolGroup;
  1275. WatchItem->u.DelIndex = Item;
  1276. FinishCommand();
  1277. }
  1278. else
  1279. {
  1280. // XXX drewb - Failure?
  1281. }
  1282. WatchItem = StartStructCommand(UIC_SYMBOL_WIN);
  1283. if (WatchItem != NULL)
  1284. {
  1285. WatchItem->Type = ADD_SYMBOL_WIN;
  1286. WatchItem->pSymbolGroup = m_pDbgSymbolGroup;
  1287. CopyString(m_ChangedName, Text, DIMA(m_ChangedName));
  1288. WatchItem->u.Add.Name = m_ChangedName;
  1289. WatchItem->u.Add.Index = Item;
  1290. FinishCommand();
  1291. }
  1292. if (g_Workspace != NULL)
  1293. {
  1294. g_Workspace->AddDirty(WSPF_DIRTY_WINDOWS);
  1295. }
  1296. }
  1297. else if (m_nSubItem_CurrentlyEditing == 1)
  1298. {
  1299. WatchItem = StartStructCommand(UIC_SYMBOL_WIN);
  1300. if (WatchItem != NULL)
  1301. {
  1302. CopyString(m_ChangedName, Text, DIMA(m_ChangedName));
  1303. WatchItem->Type = EDIT_SYMBOL;
  1304. WatchItem->pSymbolGroup = m_pDbgSymbolGroup;
  1305. WatchItem->u.WriteSymbol.Index = m_nItem_CurrentlyEditing;
  1306. WatchItem->u.WriteSymbol.Value = m_ChangedName;
  1307. FinishCommand();
  1308. }
  1309. }
  1310. else if (m_nSubItem_CurrentlyEditing == 2)
  1311. {
  1312. WatchItem = StartStructCommand(UIC_SYMBOL_WIN);
  1313. if (WatchItem != NULL)
  1314. {
  1315. CopyString(m_ChangedName, Text, DIMA(m_ChangedName));
  1316. WatchItem->Type = EDIT_TYPE;
  1317. WatchItem->pSymbolGroup = m_pDbgSymbolGroup;
  1318. WatchItem->u.OutputAsType.Index = m_nItem_CurrentlyEditing;
  1319. WatchItem->u.OutputAsType.Type = m_ChangedName;
  1320. FinishCommand();
  1321. }
  1322. }
  1323. UiRequestRead();
  1324. }
  1325. void
  1326. SYMWIN_DATA::SetDisplayTypes(LONG Id, BOOL Set)
  1327. {
  1328. if (Id == g_SymWinTbButtons[0].idCommand ||
  1329. Id == g_SymWinTbButtons[1].idCommand)
  1330. {
  1331. //
  1332. // Add / remove a column
  1333. //
  1334. if (Id == g_SymWinTbButtons[0].idCommand)
  1335. {
  1336. m_wFlags |= DL_EDIT_THIRDPANE;
  1337. if (Set == m_DisplayTypes)
  1338. {
  1339. return;
  1340. }
  1341. m_DisplayTypes = Set;
  1342. }
  1343. else
  1344. {
  1345. if (Set == m_DisplayOffsets)
  1346. {
  1347. return;
  1348. }
  1349. m_DisplayOffsets = Set;
  1350. }
  1351. if (g_Workspace != NULL)
  1352. {
  1353. g_Workspace->AddDirty(WSPF_DIRTY_WINDOWS);
  1354. }
  1355. if (Id == g_SymWinTbButtons[1].idCommand)
  1356. {
  1357. //UiRequestRead();
  1358. //return;
  1359. }
  1360. if (Set)
  1361. {
  1362. LV_COLUMN lvc = {0};
  1363. int Col1Width;
  1364. Col1Width = ListView_GetColumnWidth(m_hwndChild, VALUE_COLM);
  1365. lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_TEXT;
  1366. lvc.fmt = LVCFMT_LEFT;
  1367. lvc.iSubItem = 0;
  1368. if (Col1Width >= (m_Font->Metrics.tmAveCharWidth * 20))
  1369. {
  1370. lvc.cx = max(Col1Width / 4,
  1371. m_Font->Metrics.tmAveCharWidth * 10);
  1372. Col1Width -= lvc.cx;
  1373. } else
  1374. {
  1375. lvc.cx = Col1Width >> 1;
  1376. Col1Width -= lvc.cx;
  1377. }
  1378. ListView_SetColumnWidth(m_hwndChild, VALUE_COLM, Col1Width);
  1379. lvc.pszText = _T((Id == g_SymWinTbButtons[0].idCommand) ? "Type" : "Offset");
  1380. ListView_InsertColumn(
  1381. m_hwndChild,
  1382. ((Id == g_SymWinTbButtons[0].idCommand) ? TYPE_COLM : OFFSET_COLM),
  1383. &lvc);
  1384. m_NumCols++;
  1385. }
  1386. else
  1387. {
  1388. if (Id == g_SymWinTbButtons[0].idCommand)
  1389. {
  1390. m_wFlags &= ~DL_EDIT_THIRDPANE;
  1391. }
  1392. int Col2Width;
  1393. int Col1Width;
  1394. int ColToDel = ((Id == g_SymWinTbButtons[0].idCommand) ? TYPE_COLM : OFFSET_COLM);
  1395. Col1Width = ListView_GetColumnWidth(m_hwndChild, VALUE_COLM);
  1396. Col2Width = ListView_GetColumnWidth(m_hwndChild, ColToDel);
  1397. ListView_DeleteColumn(m_hwndChild, ColToDel);
  1398. ListView_SetColumnWidth(m_hwndChild, VALUE_COLM, Col1Width + Col2Width);
  1399. m_NumCols--;
  1400. }
  1401. UiRequestRead();
  1402. }
  1403. }
  1404. //the basic rutine making the ... thing
  1405. LPTSTR MakeShortString(HDC hDC, LPTSTR lpszLong, LONG nColumnLen,
  1406. LONG nOffset, PULONG pActualLen )
  1407. {
  1408. static const _TCHAR szThreeDots[]=_T("...");
  1409. SIZE strSz;
  1410. int nStringLen = lstrlen(lpszLong);
  1411. if (nStringLen==0 ||
  1412. (GetTextExtentPoint(hDC, lpszLong,nStringLen,
  1413. &strSz), strSz.cx + nOffset < nColumnLen))
  1414. {
  1415. *pActualLen = nStringLen ? strSz.cx : 0;
  1416. return(lpszLong);
  1417. }
  1418. *pActualLen = strSz.cx;
  1419. static _TCHAR szShort[1024];
  1420. if (nStringLen < sizeof(szShort) - 4)
  1421. {
  1422. lstrcpy(szShort, lpszLong);
  1423. }
  1424. else
  1425. {
  1426. nStringLen = sizeof(szShort) - 4;
  1427. strncpy(szShort, lpszLong, nStringLen);
  1428. szShort[nStringLen] = 0;
  1429. }
  1430. GetTextExtentPoint(hDC, szThreeDots, sizeof(szThreeDots), &strSz);
  1431. int nAddLen = strSz.cx;
  1432. for (int i = nStringLen - 1; i > 0; i--)
  1433. {
  1434. szShort[i] = 0;
  1435. GetTextExtentPoint(hDC, szShort, i, &strSz);
  1436. if(strSz.cx + nOffset + nAddLen < nColumnLen)
  1437. {
  1438. break;
  1439. }
  1440. }
  1441. lstrcat(szShort, szThreeDots);
  1442. return szShort;
  1443. }
  1444. void DrawRectangle(HDC hDc, POINT pt, ULONG width)
  1445. {
  1446. POINT corners[5];
  1447. corners[0] = pt;
  1448. corners[1].x = pt.x; corners[1].y = pt.y + width;
  1449. corners[2].x = pt.x + width; corners[2].y = pt.y + width;
  1450. corners[3].x = pt.x + width; corners[3].y = pt.y;
  1451. corners[4] = pt;
  1452. Polyline(hDc, &corners[0], 5);
  1453. }
  1454. void DrawHorizLine(HDC hDc, POINT start, ULONG length, ULONG thick)
  1455. {
  1456. POINT curr, pt = start;
  1457. while (thick)
  1458. {
  1459. MoveToEx(hDc, pt.x, pt.y, &curr);
  1460. LineTo(hDc, pt.x + length, pt.y);
  1461. --thick;
  1462. ++pt.y;
  1463. }
  1464. }
  1465. void DrawPlus(HDC hDc, POINT topLeft, ULONG width)
  1466. {
  1467. if (g_UseTextMode)
  1468. {
  1469. TextOut(hDc, topLeft.x, topLeft.y - width/2, "+", 1);
  1470. return;
  1471. }
  1472. POINT curr, pt = topLeft;
  1473. DrawRectangle(hDc, pt, width);
  1474. MoveToEx(hDc, pt.x, pt.y + width/2, &curr);
  1475. LineTo(hDc, pt.x + width, pt.y + width/2);
  1476. MoveToEx(hDc, pt.x + width/2, pt.y, &curr);
  1477. LineTo(hDc, pt.x + width/2, pt.y + width);
  1478. }
  1479. void DrawMinus(HDC hDc, POINT topLeft, ULONG width)
  1480. {
  1481. if (g_UseTextMode)
  1482. {
  1483. TextOut(hDc, topLeft.x, topLeft.y - width/2, "-", 1);
  1484. return;
  1485. }
  1486. POINT curr, pt = topLeft;
  1487. DrawRectangle(hDc, pt, width);
  1488. MoveToEx(hDc, pt.x, pt.y + width/2, &curr);
  1489. LineTo(hDc, pt.x + width, pt.y + width/2);
  1490. }
  1491. void DrawIndentLevel(HDC hDc, ULONG Indent, RECT leftRect)
  1492. {
  1493. POINT curr, pt;
  1494. ULONG i;
  1495. INT width, height;
  1496. pt.x = leftRect.left;
  1497. pt.y = leftRect.top;
  1498. width = leftRect.right - leftRect.left;
  1499. height = leftRect.bottom - leftRect.top;
  1500. for (i=0;i<Indent; i++,pt.x+=width)
  1501. {
  1502. if (g_UseTextMode)
  1503. {
  1504. TextOut(hDc, pt.x, pt.y, "|",1);
  1505. continue;
  1506. }
  1507. MoveToEx(hDc, pt.x + width/2, pt.y, &curr);
  1508. LineTo(hDc, pt.x + width/2, pt.y + height);
  1509. if (i+1==Indent)
  1510. {
  1511. MoveToEx(hDc, pt.x + width/2, pt.y + height/2, &curr);
  1512. LineTo(hDc, pt.x + width - 1, pt.y + height/2);
  1513. }
  1514. }
  1515. }
  1516. #define NAME_LEFT_PAD 6
  1517. void
  1518. SYMWIN_DATA::DrawTreeItem(HDC hDC, ULONG itemID, RECT ItemRect, PULONG pIndentOffset)
  1519. {
  1520. ULONG RectWidth;
  1521. ULONG level;
  1522. TEXTMETRIC tm;
  1523. if (itemID >= m_NumSymsDisplayed)
  1524. {
  1525. return;
  1526. }
  1527. // derive the Width of +/- from tm
  1528. GetTextMetrics(hDC, &tm);
  1529. RectWidth = (tm.tmHeight * 2) / 3;
  1530. level = m_pWinSyms[itemID].Flags & DEBUG_SYMBOL_EXPANSION_LEVEL_MASK;
  1531. // Rectangle for One indent level
  1532. RECT IndentRc;
  1533. IndentRc = ItemRect;
  1534. IndentRc.left = ItemRect.left + 2;
  1535. IndentRc.right = IndentRc.left + RectWidth + 1;
  1536. DrawIndentLevel(hDC, level, IndentRc);
  1537. *pIndentOffset = level * (RectWidth+1) + NAME_LEFT_PAD;
  1538. POINT pt;
  1539. pt.x = ItemRect.left + *pIndentOffset - 4;
  1540. pt.y = (ItemRect.top + ItemRect.bottom - RectWidth) / 2;
  1541. if (m_pWinSyms[itemID].Flags & DEBUG_SYMBOL_EXPANDED)
  1542. {
  1543. DrawMinus(hDC, pt, RectWidth);
  1544. } else if (m_pWinSyms[itemID].SubElements)
  1545. {
  1546. DrawPlus(hDC, pt, RectWidth);
  1547. }
  1548. m_IndentWidth = RectWidth+1;
  1549. *pIndentOffset += RectWidth+1;
  1550. }
  1551. LRESULT
  1552. SYMWIN_DATA::OnOwnerDraw(UINT uMsg, WPARAM wParam, LPARAM lParam)
  1553. {
  1554. LPDRAWITEMSTRUCT lpdis;
  1555. TEXTMETRIC tm;
  1556. ULONG IndentOffset = 0, ActualWidth;
  1557. if (uMsg == WM_MEASUREITEM)
  1558. {
  1559. MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT * ) lParam;
  1560. HDC hDC = GetDC(m_hwndChild);
  1561. GetTextMetrics(hDC, &tm);
  1562. lpmis->CtlType = ODT_LISTVIEW;
  1563. lpmis->itemHeight = tm.tmHeight;
  1564. lpmis->itemWidth = m_MaxNameWidth;
  1565. ReleaseDC(m_hwndChild, hDC);
  1566. return TRUE;
  1567. }
  1568. else
  1569. {
  1570. // Assert (uMsg == WM_DRAWITEM);
  1571. }
  1572. lpdis = (LPDRAWITEMSTRUCT) lParam;
  1573. int y;
  1574. TCHAR Buffer[NAME_BUFFER];
  1575. int Col;
  1576. LPTSTR pszText=&Buffer[0];
  1577. // If there are no list box items, skip this message.
  1578. if (lpdis->itemID == -1)
  1579. {
  1580. return FALSE;
  1581. }
  1582. switch (lpdis->itemAction)
  1583. {
  1584. case ODA_SELECT:
  1585. case ODA_DRAWENTIRE:
  1586. {
  1587. HBRUSH hBrush;
  1588. DWORD dwOldTextColor, dwOldBkColor, TextColor;
  1589. if (g_ExecStatus != DEBUG_STATUS_BREAK)
  1590. {
  1591. dwOldTextColor = ListView_GetTextColor(m_hwndChild);
  1592. dwOldBkColor = ListView_GetBkColor(m_hwndChild);
  1593. hBrush = g_Colors[COL_DISABLED_WINDOW].Brush;
  1594. TextColor = dwOldTextColor =
  1595. SetTextColor(lpdis->hDC, dwOldTextColor);
  1596. dwOldBkColor = SetBkColor(lpdis->hDC,
  1597. g_Colors[COL_DISABLED_WINDOW].Color);
  1598. }
  1599. else if (lpdis->itemState & ODS_SELECTED)
  1600. {
  1601. hBrush = g_Colors[COL_CURRENT_LINE].Brush;
  1602. TextColor = g_Colors[COL_CURRENT_LINE_TEXT].Color;
  1603. dwOldTextColor = SetTextColor(lpdis->hDC, TextColor);
  1604. dwOldBkColor = SetBkColor(lpdis->hDC,
  1605. g_Colors[COL_CURRENT_LINE].Color);
  1606. }
  1607. else // item not selected
  1608. {
  1609. hBrush = g_Colors[COL_PLAIN].Brush;
  1610. TextColor = g_Colors[COL_PLAIN_TEXT].Color;
  1611. dwOldTextColor = SetTextColor(lpdis->hDC, TextColor);
  1612. dwOldBkColor = SetBkColor(lpdis->hDC,
  1613. g_Colors[COL_PLAIN].Color);
  1614. }
  1615. if (hBrush != NULL)
  1616. {
  1617. FillRect(lpdis->hDC, (LPRECT)&lpdis->rcItem, hBrush);
  1618. }
  1619. // Display the text associated with the item.
  1620. ListView_GetItemText(m_hwndChild, lpdis->itemID,
  1621. 0, Buffer, sizeof(Buffer));
  1622. GetTextMetrics(lpdis->hDC, &tm);
  1623. y = (lpdis->rcItem.bottom + lpdis->rcItem.top -
  1624. tm.tmHeight) / 2;
  1625. RECT rc = lpdis->rcItem;
  1626. if (m_SplitWindowAtItem && (lpdis->itemID == m_SplitWindowAtItem))
  1627. {
  1628. POINT pt = {rc.left, rc.top-1};
  1629. DrawHorizLine(lpdis->hDC, pt, rc.right - rc.left, 2);
  1630. rc.top++;
  1631. }
  1632. LV_COLUMN lvc;
  1633. lvc.mask = LVCF_FMT | LVCF_WIDTH;
  1634. RECT rc2;
  1635. ListView_GetSubItemRect(m_hwndChild, lpdis->itemID,
  1636. 1, LVIR_BOUNDS,
  1637. &rc2);
  1638. rc.right = rc2.left;
  1639. DrawTreeItem(lpdis->hDC, lpdis->itemID, rc, &IndentOffset);
  1640. while (*pszText && *pszText == ' ')
  1641. {
  1642. ++pszText;
  1643. }
  1644. pszText = MakeShortString(lpdis->hDC, pszText, rc.right-rc.left,
  1645. 2 + IndentOffset, &ActualWidth);
  1646. TextOut(lpdis->hDC, rc.left + IndentOffset, y,
  1647. pszText, strlen(pszText));
  1648. if (m_MaxNameWidth < (2 + IndentOffset*3/2 + ActualWidth))
  1649. {
  1650. m_MaxNameWidth = 2 + IndentOffset*3/2 + ActualWidth;
  1651. }
  1652. for (Col = 1;
  1653. //ListView_GetColumn(m_hwndChild, Col, &lvc);
  1654. Col < (int) m_NumCols;
  1655. Col++)
  1656. {
  1657. if (!ListView_GetSubItemRect(m_hwndChild,
  1658. lpdis->itemID,
  1659. Col,
  1660. LVIR_BOUNDS,
  1661. &rc))
  1662. {
  1663. // invalid coulmn
  1664. break;
  1665. }
  1666. ListView_GetItemText(m_hwndChild, lpdis->itemID,
  1667. Col, Buffer, sizeof(Buffer));
  1668. int nRetLen = strlen(Buffer);
  1669. if (nRetLen == 0)
  1670. {
  1671. pszText = "";
  1672. }
  1673. else
  1674. {
  1675. pszText = MakeShortString(lpdis->hDC, Buffer,
  1676. rc.right - rc.left, 2, &ActualWidth);
  1677. }
  1678. if ((Col == 1) &&
  1679. (m_NumSymsDisplayed > lpdis->itemID))
  1680. {
  1681. if (m_pWinSyms[lpdis->itemID].Flags & ITEM_VALUE_CHANGED)
  1682. {
  1683. SetTextColor(lpdis->hDC,
  1684. g_Colors[COL_CHANGED_DATA_TEXT].Color);
  1685. }
  1686. }
  1687. TextOut(lpdis->hDC, rc.left + 2, y, pszText, strlen(pszText));
  1688. if (m_pWinSyms[lpdis->itemID].Flags & ITEM_VALUE_CHANGED)
  1689. {
  1690. SetTextColor(lpdis->hDC, TextColor);
  1691. }
  1692. }
  1693. // restore text and back ground color of list box's selection
  1694. SetTextColor(lpdis->hDC, dwOldTextColor);
  1695. SetBkColor(lpdis->hDC, dwOldBkColor);
  1696. return TRUE;
  1697. }
  1698. case ODA_FOCUS:
  1699. // Do not process focus changes. The focus caret
  1700. // (outline rectangle) indicates the selection.
  1701. break;
  1702. }
  1703. return DefMDIChildProc(m_Win, WM_DRAWITEM, wParam, lParam);
  1704. }
  1705. void
  1706. SYMWIN_DATA::SyncUiWithFlags(ULONG Changed)
  1707. {
  1708. if (Changed & (1 << SYMWIN_TBB_TYPECAST))
  1709. {
  1710. SendMessage(m_Toolbar, TB_SETSTATE, SYMWIN_TBB_TYPECAST,
  1711. TBSTATE_ENABLED |
  1712. (m_DisplayTypes ? TBSTATE_CHECKED : 0));
  1713. }
  1714. if (Changed & (1 << SYMWIN_TBB_OFFSETS))
  1715. {
  1716. SendMessage(m_Toolbar, TB_SETSTATE, SYMWIN_TBB_OFFSETS,
  1717. TBSTATE_ENABLED |
  1718. (m_DisplayOffsets ? TBSTATE_CHECKED : 0));
  1719. }
  1720. }
  1721. //
  1722. // WATCHWIN_DATA methods
  1723. //
  1724. extern IDebugSymbolGroup * g_pDbgWatchSymbolGroup;
  1725. WATCHWIN_DATA::WATCHWIN_DATA()
  1726. : SYMWIN_DATA(&g_pDbgWatchSymbolGroup)
  1727. {
  1728. m_wFlags = DL_EDIT_LEFTPANE;
  1729. m_enumType = WATCH_WINDOW;
  1730. }
  1731. void
  1732. WATCHWIN_DATA::Validate()
  1733. {
  1734. SYMWIN_DATA::Validate();
  1735. Assert(WATCH_WINDOW == m_enumType);
  1736. }
  1737. HRESULT
  1738. WATCHWIN_DATA::ReadState(void)
  1739. {
  1740. m_pDbgSymbolGroup = &g_pDbgWatchSymbolGroup;
  1741. return SYMWIN_DATA::ReadState();
  1742. }
  1743. #define WATCH_WRKSPC_TAG 0x40404040
  1744. //
  1745. // Workspace
  1746. // 0 4 8
  1747. // WATCH_WRKSPC_TAG NUM syms [Null terminated names]
  1748. //
  1749. ULONG
  1750. WATCHWIN_DATA::GetWorkspaceSize(void)
  1751. {
  1752. ULONG i;
  1753. ULONG Size = 2*sizeof(ULONG);
  1754. PDEBUG_SYMBOL_PARAMETERS SymParam;
  1755. for (SymParam = GetSymParam(), i = 0;
  1756. i < m_NumSymsDisplayed;
  1757. SymParam++, i++)
  1758. {
  1759. if (IsRootSym(SymParam))
  1760. {
  1761. CHAR Text[500] = {0};
  1762. ListView_GetItemText(m_hwndChild, i, 0, Text, sizeof(Text));
  1763. Size += strlen(Text) + 1;
  1764. }
  1765. }
  1766. return SYMWIN_DATA::GetWorkspaceSize() + Size;
  1767. }
  1768. PUCHAR
  1769. WATCHWIN_DATA::SetWorkspace(PUCHAR Data)
  1770. {
  1771. Data = SYMWIN_DATA::SetWorkspace(Data);
  1772. PULONG pNumSyms, watchWrkspc = (PULONG) Data;
  1773. *watchWrkspc = WATCH_WRKSPC_TAG;
  1774. pNumSyms = (PULONG) (Data + sizeof(ULONG));
  1775. *pNumSyms = 0;
  1776. Data += 2 * sizeof(ULONG);
  1777. ULONG i;
  1778. PDEBUG_SYMBOL_PARAMETERS SymParam;
  1779. for (SymParam = GetSymParam(), i = 0;
  1780. i < m_NumSymsDisplayed;
  1781. SymParam++, i++)
  1782. {
  1783. if (IsRootSym(SymParam))
  1784. {
  1785. CHAR Text[500] = {0}, *pName = &Text[0];
  1786. ListView_GetItemText(m_hwndChild, i, 0, Text, sizeof(Text));
  1787. strcpy((PCHAR) Data, pName);
  1788. Data += strlen(pName) + 1;
  1789. *pNumSyms = *pNumSyms + 1;
  1790. }
  1791. }
  1792. return Data;
  1793. }
  1794. PUCHAR
  1795. WATCHWIN_DATA::ApplyWorkspace1(PUCHAR Data, PUCHAR End)
  1796. {
  1797. Data = SYMWIN_DATA::ApplyWorkspace1(Data, End);
  1798. if (*((PULONG) Data) == WATCH_WRKSPC_TAG &&
  1799. End >= Data + 2 * sizeof(ULONG))
  1800. {
  1801. Data += sizeof(ULONG);
  1802. ULONG NumSyms = *((PULONG) Data);
  1803. ULONG i = 0;
  1804. Data += sizeof(ULONG);
  1805. PCHAR Name = (PCHAR) Data, pCopyName = &m_ChangedName[0];
  1806. while ((Data < End) && (i<NumSyms))
  1807. {
  1808. UIC_SYMBOL_WIN_DATA* WatchItem;
  1809. while (*Name == ' ')
  1810. {
  1811. // eat out space in begining
  1812. ++Name;
  1813. }
  1814. if (pCopyName + strlen(Name) >=
  1815. &m_ChangedName[sizeof(m_ChangedName) - 1])
  1816. {
  1817. Data = End;
  1818. break;
  1819. }
  1820. strcpy(pCopyName, Name);
  1821. WatchItem = StartStructCommand(UIC_SYMBOL_WIN);
  1822. if (WatchItem != NULL)
  1823. {
  1824. WatchItem->Type = ADD_SYMBOL_WIN;
  1825. WatchItem->pSymbolGroup = m_pDbgSymbolGroup;
  1826. WatchItem->u.Add.Name = pCopyName;
  1827. WatchItem->u.Add.Index = i;
  1828. FinishCommand();
  1829. }
  1830. ++i;
  1831. pCopyName += strlen(pCopyName) + 1;
  1832. while (*Data != 0)
  1833. {
  1834. ++Data;
  1835. }
  1836. ++Data;
  1837. Name = (PCHAR) Data;
  1838. }
  1839. }
  1840. return Data;
  1841. }
  1842. //
  1843. // LOCALSWIN_DATA methods
  1844. //
  1845. extern IDebugSymbolGroup * g_pDbgLocalSymbolGroup;
  1846. LOCALSWIN_DATA::LOCALSWIN_DATA()
  1847. : SYMWIN_DATA(&g_pDbgLocalSymbolGroup)
  1848. {
  1849. m_enumType = LOCALS_WINDOW;
  1850. }
  1851. void
  1852. LOCALSWIN_DATA::Validate()
  1853. {
  1854. DUALLISTWIN_DATA::Validate();
  1855. Assert(LOCALS_WINDOW == m_enumType);
  1856. }
  1857. LOCALSWIN_DATA::~LOCALSWIN_DATA()
  1858. {
  1859. }
  1860. BOOL
  1861. LOCALSWIN_DATA::OnCreate(void)
  1862. {
  1863. if (!SYMWIN_DATA::OnCreate())
  1864. {
  1865. return FALSE;
  1866. }
  1867. return TRUE;
  1868. }
  1869. HRESULT
  1870. LOCALSWIN_DATA::ReadState(void)
  1871. {
  1872. HRESULT Hr;
  1873. IDebugSymbolGroup *pLocalSymbolGroup;
  1874. if (g_ScopeChanged)
  1875. {
  1876. //
  1877. // Get the new locals
  1878. //
  1879. if ((Hr = g_pDbgSymbols->GetScopeSymbolGroup(DEBUG_SCOPE_GROUP_LOCALS,
  1880. g_pDbgLocalSymbolGroup,
  1881. &pLocalSymbolGroup)) == E_NOTIMPL)
  1882. {
  1883. // Older engine version
  1884. Hr = g_pDbgSymbols->GetScopeSymbolGroup(DEBUG_SCOPE_GROUP_ALL,
  1885. g_pDbgLocalSymbolGroup,
  1886. &pLocalSymbolGroup);
  1887. }
  1888. if (Hr == S_OK)
  1889. {
  1890. g_pDbgLocalSymbolGroup = pLocalSymbolGroup;
  1891. m_pDbgSymbolGroup = &g_pDbgLocalSymbolGroup;
  1892. g_ScopeChanged = FALSE;
  1893. }
  1894. else
  1895. {
  1896. //
  1897. // Keep the old values
  1898. //
  1899. return E_PENDING;
  1900. }
  1901. }
  1902. return SYMWIN_DATA::ReadState();
  1903. }
  1904. //
  1905. // CPUWIN_DATA methods
  1906. //
  1907. HMENU CPUWIN_DATA::s_ContextMenu;
  1908. CPUWIN_DATA::CPUWIN_DATA()
  1909. : DUALLISTWIN_DATA(1024)
  1910. {
  1911. m_wFlags |= DL_CUSTOM_ITEMS;
  1912. m_enumType = CPU_WINDOW;
  1913. m_ProcType = IMAGE_FILE_MACHINE_UNKNOWN;
  1914. m_NamesProcType = IMAGE_FILE_MACHINE_UNKNOWN;
  1915. m_NumRegisters = 0;
  1916. m_CheckChanged = FALSE;
  1917. }
  1918. void
  1919. CPUWIN_DATA::Validate()
  1920. {
  1921. DUALLISTWIN_DATA::Validate();
  1922. Assert(CPU_WINDOW == m_enumType);
  1923. }
  1924. HRESULT
  1925. CPUWIN_DATA::ReadState(void)
  1926. {
  1927. HRESULT Status;
  1928. PDEBUG_VALUE OldVals;
  1929. ULONG NumOld, NumReg;
  1930. PDEBUG_VALUE Vals;
  1931. PDEBUG_VALUE Coerced;
  1932. PULONG Types;
  1933. PBOOL Changed;
  1934. ULONG ProcType;
  1935. BOOL ProcChanged;
  1936. NumOld = m_NumRegisters;
  1937. if ((Status = g_pDbgRegisters->
  1938. GetNumberRegisters(&NumReg)) != S_OK ||
  1939. (Status = g_pDbgControl->
  1940. GetEffectiveProcessorType(&ProcType)) != S_OK)
  1941. {
  1942. return Status;
  1943. }
  1944. ProcChanged = ProcType != m_ProcType;
  1945. Empty();
  1946. //
  1947. // Retrieve all register values and diff them.
  1948. // Also keep space for a coercion type map and
  1949. // temporary coerced values.
  1950. //
  1951. OldVals = (PDEBUG_VALUE)
  1952. AddData(NumReg * (3 * sizeof(DEBUG_VALUE) + sizeof(ULONG) +
  1953. sizeof(BOOL)));
  1954. if (OldVals == NULL)
  1955. {
  1956. return E_OUTOFMEMORY;
  1957. }
  1958. Changed = (PBOOL)(OldVals + NumReg);
  1959. Coerced = (PDEBUG_VALUE)(Changed + NumReg);
  1960. Vals = Coerced + NumReg;
  1961. Types = (PULONG)(Vals + NumReg);
  1962. Status = g_pDbgRegisters->GetValues(NumReg, NULL, 0, Vals);
  1963. if (Status != S_OK)
  1964. {
  1965. return Status;
  1966. }
  1967. ULONG i;
  1968. // Coerce values into known types.
  1969. // If it's an integer value coerce it to 64-bit.
  1970. // If it's a float value coerce to 64-bit also,
  1971. // which loses precision but has CRT support for
  1972. // formatting.
  1973. for (i = 0; i < NumReg; i++)
  1974. {
  1975. if (Vals[i].Type >= DEBUG_VALUE_INT8 &&
  1976. Vals[i].Type <= DEBUG_VALUE_INT64)
  1977. {
  1978. Types[i] = DEBUG_VALUE_INT64;
  1979. }
  1980. else if (Vals[i].Type >= DEBUG_VALUE_FLOAT32 &&
  1981. Vals[i].Type <= DEBUG_VALUE_FLOAT128)
  1982. {
  1983. Types[i] = DEBUG_VALUE_FLOAT64;
  1984. }
  1985. else if (Vals[i].Type == DEBUG_VALUE_VECTOR64 ||
  1986. Vals[i].Type == DEBUG_VALUE_VECTOR128)
  1987. {
  1988. Types[i] = Vals[i].Type;
  1989. }
  1990. else
  1991. {
  1992. // Unknown type.
  1993. return E_INVALIDARG;
  1994. }
  1995. }
  1996. if ((Status = g_pDbgControl->
  1997. CoerceValues(NumReg, Vals, Types, Coerced)) != S_OK)
  1998. {
  1999. return Status;
  2000. }
  2001. // Diff new values against the old.
  2002. for (i = 0; i < NumReg; i++)
  2003. {
  2004. // Ignore differences if the processor has changed.
  2005. if (!ProcChanged && i < NumOld)
  2006. {
  2007. switch(Types[i])
  2008. {
  2009. case DEBUG_VALUE_INT64:
  2010. Changed[i] = Coerced[i].I64 != OldVals[i].I64;
  2011. break;
  2012. case DEBUG_VALUE_FLOAT64:
  2013. Changed[i] = Coerced[i].F64 != OldVals[i].F64;
  2014. break;
  2015. case DEBUG_VALUE_VECTOR64:
  2016. Changed[i] = memcmp(Coerced[i].RawBytes, OldVals[i].RawBytes,
  2017. 8);
  2018. break;
  2019. case DEBUG_VALUE_VECTOR128:
  2020. Changed[i] = memcmp(Coerced[i].RawBytes, OldVals[i].RawBytes,
  2021. 16);
  2022. break;
  2023. }
  2024. }
  2025. else
  2026. {
  2027. Changed[i] = FALSE;
  2028. }
  2029. }
  2030. // Copy new values into permanent storage area.
  2031. memmove(OldVals, Coerced, NumReg * sizeof(*Vals));
  2032. // Trim off temporary information.
  2033. RemoveTail(NumReg * (2 * sizeof(DEBUG_VALUE) + sizeof(ULONG)));
  2034. m_NumRegisters = NumReg;
  2035. m_ProcType = ProcType;
  2036. if (ProcChanged)
  2037. {
  2038. UpdateBufferWindows(1 << CPU_WINDOW, UPDATE_REG_NAMES);
  2039. }
  2040. return Status;
  2041. }
  2042. #define CPU_CONTEXT_ID_BASE 0x100
  2043. TBBUTTON g_CpuTbButtons[] =
  2044. {
  2045. TEXT_TB_BTN(ID_CUSTOMIZE, "Customize...", 0),
  2046. SEP_TB_BTN(),
  2047. TEXT_TB_BTN(ID_SHOW_TOOLBAR, "Toolbar", 0),
  2048. };
  2049. #define NUM_CPU_MENU_BUTTONS \
  2050. (sizeof(g_CpuTbButtons) / sizeof(g_CpuTbButtons[0]))
  2051. #define NUM_CPU_TB_BUTTONS \
  2052. (NUM_CPU_MENU_BUTTONS - 2)
  2053. HMENU
  2054. CPUWIN_DATA::GetContextMenu(void)
  2055. {
  2056. //
  2057. // We only keep one menu around for all CPU windows
  2058. // so apply the menu check state for this particular
  2059. // window.
  2060. // In reality there's only one CPU window anyway,
  2061. // but this is a good example of how to handle
  2062. // multi-instance windows.
  2063. //
  2064. CheckMenuItem(s_ContextMenu, ID_SHOW_TOOLBAR + CPU_CONTEXT_ID_BASE,
  2065. MF_BYCOMMAND | (m_ShowToolbar ? MF_CHECKED : 0));
  2066. return s_ContextMenu;
  2067. }
  2068. void
  2069. CPUWIN_DATA::OnContextMenuSelection(UINT Item)
  2070. {
  2071. StateBuffer* NameBuf;
  2072. Item -= CPU_CONTEXT_ID_BASE;
  2073. switch(Item)
  2074. {
  2075. case ID_CUSTOMIZE:
  2076. NameBuf = GetRegisterNames(m_ProcType);
  2077. if (!NameBuf ||
  2078. (NameBuf->UiLockForRead() != S_OK))
  2079. {
  2080. ErrorBox(NULL, 0, ERR_No_Register_Names);
  2081. }
  2082. else
  2083. {
  2084. int Res =
  2085. StartDialog(IDD_DLG_REG_CUSTOMIZE, DlgProc_RegCustomize,
  2086. (LPARAM)NameBuf);
  2087. UnlockStateBuffer(NameBuf);
  2088. if (Res == IDOK)
  2089. {
  2090. UpdateNames(TRUE);
  2091. OnUpdate(UPDATE_BUFFER);
  2092. }
  2093. }
  2094. break;
  2095. case ID_SHOW_TOOLBAR:
  2096. SetShowToolbar(!m_ShowToolbar);
  2097. break;
  2098. }
  2099. }
  2100. BOOL
  2101. CPUWIN_DATA::OnCreate(void)
  2102. {
  2103. if (s_ContextMenu == NULL)
  2104. {
  2105. s_ContextMenu = CreateContextMenuFromToolbarButtons
  2106. (NUM_CPU_MENU_BUTTONS, g_CpuTbButtons, CPU_CONTEXT_ID_BASE);
  2107. if (s_ContextMenu == NULL)
  2108. {
  2109. return FALSE;
  2110. }
  2111. }
  2112. if (!DUALLISTWIN_DATA::OnCreate())
  2113. {
  2114. return FALSE;
  2115. }
  2116. m_Toolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
  2117. WS_CHILD | WS_VISIBLE |
  2118. TBSTYLE_WRAPABLE | TBSTYLE_LIST | CCS_TOP,
  2119. 0, 0, m_Size.cx, 0, m_Win, (HMENU)ID_TOOLBAR,
  2120. g_hInst, NULL);
  2121. if (m_Toolbar == NULL)
  2122. {
  2123. return FALSE;
  2124. }
  2125. SendMessage(m_Toolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
  2126. SendMessage(m_Toolbar, TB_ADDBUTTONS, NUM_CPU_TB_BUTTONS,
  2127. (LPARAM)&g_CpuTbButtons);
  2128. SendMessage(m_Toolbar, TB_AUTOSIZE, 0, 0);
  2129. RECT Rect;
  2130. GetClientRect(m_Toolbar, &Rect);
  2131. m_ToolbarHeight = Rect.bottom - Rect.top + GetSystemMetrics(SM_CYEDGE);
  2132. m_ShowToolbar = TRUE;
  2133. SendMessage(m_hwndChild, WM_SETREDRAW, FALSE, 0);
  2134. RECT rc;
  2135. LV_COLUMN lvc = {0};
  2136. GetClientRect(m_hwndChild, &rc);
  2137. rc.right -= rc.left + GetSystemMetrics(SM_CXVSCROLL);
  2138. //initialize the columns
  2139. lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_TEXT;
  2140. lvc.fmt = LVCFMT_LEFT;
  2141. lvc.iSubItem = 0;
  2142. // Keep the register name column narrow since most names are short.
  2143. lvc.cx = m_Font->Metrics.tmAveCharWidth * 7;
  2144. if (lvc.cx > rc.right / 2)
  2145. {
  2146. lvc.cx = rc.right / 2;
  2147. }
  2148. lvc.pszText = _T("Reg");
  2149. Dbg( (0 == ListView_InsertColumn(m_hwndChild, 0, &lvc)) );
  2150. // Give the rest of the space to the value.
  2151. lvc.cx = rc.right - lvc.cx;
  2152. lvc.pszText = _T("Value");
  2153. Dbg( (1 == ListView_InsertColumn(m_hwndChild, 1, &lvc)) );
  2154. ListView_SetExtendedListViewStyle(m_hwndChild,
  2155. LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT
  2156. );
  2157. UpdateNames(FALSE);
  2158. SendMessage(m_hwndChild, WM_SETREDRAW, TRUE, 0);
  2159. InvalidateRect(m_hwndChild, NULL, TRUE);
  2160. return TRUE;
  2161. }
  2162. LRESULT
  2163. CPUWIN_DATA::OnCommand(
  2164. WPARAM wParam,
  2165. LPARAM lParam
  2166. )
  2167. {
  2168. if ((HWND)lParam == m_Toolbar)
  2169. {
  2170. OnContextMenuSelection(LOWORD(wParam) + CPU_CONTEXT_ID_BASE);
  2171. return 0;
  2172. }
  2173. return DUALLISTWIN_DATA::OnCommand(wParam, lParam);
  2174. }
  2175. void
  2176. CPUWIN_DATA::OnSize(void)
  2177. {
  2178. DUALLISTWIN_DATA::OnSize();
  2179. // The register label column stays fixed in size so
  2180. // resize the value column to fit the remaining space.
  2181. ListView_SetColumnWidth(m_hwndChild, 1, LVSCW_AUTOSIZE_USEHEADER);
  2182. }
  2183. void
  2184. CPUWIN_DATA::OnUpdate(UpdateType Type)
  2185. {
  2186. if (Type == UPDATE_EXEC)
  2187. {
  2188. // Disallow editing when the debuggee is running.
  2189. if (g_ExecStatus == DEBUG_STATUS_BREAK)
  2190. {
  2191. m_wFlags |= DL_EDIT_SECONDPANE;
  2192. ListView_SetTextBkColor(m_hwndChild, g_Colors[COL_PLAIN].Color);
  2193. }
  2194. else
  2195. {
  2196. m_wFlags &= ~DL_EDIT_SECONDPANE;
  2197. ListView_SetTextBkColor(m_hwndChild,
  2198. g_Colors[COL_DISABLED_WINDOW].Color);
  2199. }
  2200. InvalidateRect(m_hwndChild, NULL, FALSE);
  2201. return;
  2202. }
  2203. else if (Type == UPDATE_START_SESSION ||
  2204. Type == UPDATE_END_SESSION)
  2205. {
  2206. m_ProcType = IMAGE_FILE_MACHINE_UNKNOWN;
  2207. m_NumRegisters = 0;
  2208. m_CheckChanged = Type != UPDATE_START_SESSION;
  2209. return;
  2210. }
  2211. else if (Type == UPDATE_REG_NAMES)
  2212. {
  2213. UpdateNames(FALSE);
  2214. return;
  2215. }
  2216. else if (Type != UPDATE_BUFFER)
  2217. {
  2218. return;
  2219. }
  2220. PDEBUG_VALUE Vals = NULL;
  2221. PBOOL Changed = NULL;
  2222. HRESULT Status;
  2223. RegisterNamesStateBuffer* NameBuf = GetRegisterNames(m_ProcType);
  2224. PTSTR RegNames = NULL;
  2225. PULONG RegTypes = NULL;
  2226. SendMessage(m_hwndChild, WM_SETREDRAW, FALSE, 0);
  2227. Status = UiLockForRead();
  2228. if (Status == S_OK)
  2229. {
  2230. Vals = (PDEBUG_VALUE)m_Data;
  2231. Changed = (PBOOL)(Vals + m_NumRegisters);
  2232. }
  2233. if (NameBuf &&
  2234. NameBuf->UiLockForRead() == S_OK)
  2235. {
  2236. RegTypes = (PULONG)NameBuf->GetDataBuffer();
  2237. RegNames = (PTSTR)NameBuf->GetDataBuffer() +
  2238. NameBuf->m_NamesOffset;
  2239. }
  2240. if (NameBuf &&
  2241. (NameBuf->m_Flags & REGCUST_CHANGED_FIRST))
  2242. {
  2243. ULONG Idx = 0;
  2244. // Set the changed values first.
  2245. Idx = SetRegVals(Status, Vals, Changed, NameBuf, RegTypes,
  2246. RegNames, Idx, TRUE, TRUE);
  2247. // Set the remainder.
  2248. Idx = SetRegVals(Status, Vals, Changed, NameBuf, RegTypes,
  2249. RegNames, Idx, TRUE, FALSE);
  2250. }
  2251. else
  2252. {
  2253. SetRegVals(Status, Vals, Changed, NameBuf, RegTypes,
  2254. NULL, 0, FALSE, FALSE);
  2255. }
  2256. if (RegTypes)
  2257. {
  2258. UnlockStateBuffer(NameBuf);
  2259. }
  2260. if (Status == S_OK)
  2261. {
  2262. UnlockStateBuffer(this);
  2263. }
  2264. SendMessage(m_hwndChild, WM_SETREDRAW, TRUE, 0);
  2265. InvalidateRect(m_hwndChild, NULL, TRUE);
  2266. m_CheckChanged = TRUE;
  2267. }
  2268. ULONG
  2269. CPUWIN_DATA::SetRegVals(HRESULT LockStatus,
  2270. PDEBUG_VALUE Vals,
  2271. PBOOL Changed,
  2272. RegisterNamesStateBuffer* NameBuf,
  2273. PULONG RegTypes,
  2274. PTSTR RegNames,
  2275. ULONG EntryIdx,
  2276. BOOL MatchChanged,
  2277. BOOL MatchChangedVal)
  2278. {
  2279. ULONG i;
  2280. PDEBUG_VALUE Val;
  2281. TCHAR TextBuf[256];
  2282. PTSTR Str;
  2283. BOOL ChangeFlag;
  2284. USHORT EngReg;
  2285. ULONG RegType;
  2286. for (i = 0; i < m_NumRegisters; i++)
  2287. {
  2288. ChangeFlag = FALSE;
  2289. EngReg = 0xffff;
  2290. RegType = DEBUG_VALUE_INT64;
  2291. if (LockStatus == S_FALSE)
  2292. {
  2293. _tcscpy(TextBuf, _T("Retrieving"));
  2294. }
  2295. else if (FAILED(LockStatus) || !Vals || !NameBuf)
  2296. {
  2297. _tcscpy(TextBuf, _T("Error"));
  2298. }
  2299. else
  2300. {
  2301. EngReg = NameBuf->MapUserToEngine(i);
  2302. RegType = RegTypes[EngReg * 2];
  2303. if ((NameBuf->m_Flags & REGCUST_NO_SUBREG) &&
  2304. (RegTypes[EngReg * 2 + 1] & DEBUG_REGISTER_SUB_REGISTER))
  2305. {
  2306. continue;
  2307. }
  2308. Val = Vals + EngReg;
  2309. // If this is a new session consider everything
  2310. // unchanged since comparisons may be against
  2311. // values from the previous session.
  2312. if (m_CheckChanged)
  2313. {
  2314. ChangeFlag = Changed[EngReg];
  2315. }
  2316. if (MatchChanged && ChangeFlag != MatchChangedVal)
  2317. {
  2318. continue;
  2319. }
  2320. // Buffer values are coerced into known types.
  2321. switch(Val->Type)
  2322. {
  2323. case DEBUG_VALUE_INT64:
  2324. CPFormatMemory(TextBuf, _tsizeof(TextBuf),
  2325. (LPBYTE)&Val->I64, 64, fmtUInt, g_NumberRadix);
  2326. break;
  2327. case DEBUG_VALUE_FLOAT64:
  2328. CPFormatMemory(TextBuf, _tsizeof(TextBuf),
  2329. (LPBYTE)&Val->F64, 64, fmtFloat, 10);
  2330. break;
  2331. case DEBUG_VALUE_VECTOR64:
  2332. // Assume they want it as v4i16.
  2333. Str = TextBuf;
  2334. CPFormatMemory(Str, _tsizeof(TextBuf) - (ULONG)(Str - TextBuf),
  2335. (LPBYTE)&Val->VI16[3], 16, fmtUInt,
  2336. g_NumberRadix);
  2337. Str += strlen(Str);
  2338. *Str++ = ':';
  2339. CPFormatMemory(Str, _tsizeof(TextBuf) - (ULONG)(Str - TextBuf),
  2340. (LPBYTE)&Val->VI16[2], 16, fmtUInt,
  2341. g_NumberRadix);
  2342. Str += strlen(Str);
  2343. *Str++ = ':';
  2344. CPFormatMemory(Str, _tsizeof(TextBuf) - (ULONG)(Str - TextBuf),
  2345. (LPBYTE)&Val->VI16[1], 16, fmtUInt,
  2346. g_NumberRadix);
  2347. Str += strlen(Str);
  2348. *Str++ = ':';
  2349. CPFormatMemory(Str, _tsizeof(TextBuf) - (ULONG)(Str - TextBuf),
  2350. (LPBYTE)&Val->VI16[0], 16, fmtUInt,
  2351. g_NumberRadix);
  2352. break;
  2353. case DEBUG_VALUE_VECTOR128:
  2354. // Assume they want it as v4f32.
  2355. Str = TextBuf;
  2356. CPFormatMemory(Str, _tsizeof(TextBuf) - (ULONG)(Str - TextBuf),
  2357. (LPBYTE)&Val->VF32[3], 32, fmtFloat, 10);
  2358. Str += strlen(Str);
  2359. *Str++ = ':';
  2360. CPFormatMemory(Str, _tsizeof(TextBuf) - (ULONG)(Str - TextBuf),
  2361. (LPBYTE)&Val->VF32[2], 32, fmtFloat, 10);
  2362. Str += strlen(Str);
  2363. *Str++ = ':';
  2364. CPFormatMemory(Str, _tsizeof(TextBuf) - (ULONG)(Str - TextBuf),
  2365. (LPBYTE)&Val->VF32[1], 32, fmtFloat, 10);
  2366. Str += strlen(Str);
  2367. *Str++ = ':';
  2368. CPFormatMemory(Str, _tsizeof(TextBuf) - (ULONG)(Str - TextBuf),
  2369. (LPBYTE)&Val->VF32[0], 32, fmtFloat, 10);
  2370. break;
  2371. default:
  2372. Assert(FALSE);
  2373. break;
  2374. }
  2375. }
  2376. ULONG ItemFlags = GetItemFlags(EntryIdx);
  2377. ItemFlags &= ~ITEM_USER_FLAGS;
  2378. ItemFlags |= RegToFlags(EngReg);
  2379. if (RegType >= DEBUG_VALUE_FLOAT32 &&
  2380. RegType <= DEBUG_VALUE_FLOAT128)
  2381. {
  2382. ItemFlags |= ITEM_FLOATING_POINT;
  2383. }
  2384. else
  2385. {
  2386. ItemFlags &= ~ITEM_FLOATING_POINT;
  2387. }
  2388. if (ChangeFlag)
  2389. {
  2390. ItemFlags |= ITEM_CHANGED;
  2391. }
  2392. else
  2393. {
  2394. ItemFlags &= ~ITEM_CHANGED;
  2395. }
  2396. SetItemFlags(EntryIdx, ItemFlags);
  2397. if (RegNames)
  2398. {
  2399. PTSTR Name = RegNames;
  2400. while (EngReg-- > 0)
  2401. {
  2402. Name += strlen(Name) + 1;
  2403. }
  2404. ListView_SetItemText(m_hwndChild, EntryIdx, 0, Name);
  2405. }
  2406. ListView_SetItemText(m_hwndChild, EntryIdx, 1, TextBuf);
  2407. EntryIdx++;
  2408. }
  2409. return EntryIdx;
  2410. }
  2411. void
  2412. CPUWIN_DATA::ItemChanged(int Item, PCSTR Text)
  2413. {
  2414. UIC_SET_REG_DATA* SetRegData;
  2415. ULONG ItemFlags = GetItemFlags(Item);
  2416. USHORT Reg = FlagsToReg(ItemFlags);
  2417. if (Reg == 0xffff)
  2418. {
  2419. // Invalid register.
  2420. return;
  2421. }
  2422. SetRegData = StartStructCommand(UIC_SET_REG);
  2423. if (SetRegData != NULL)
  2424. {
  2425. SetRegData->Reg = Reg;
  2426. // Default the guess about the value type based
  2427. // on whether the value includes a decimal point
  2428. // or not. If we can access the stored register
  2429. // description information we'll use that to
  2430. // override.
  2431. BOOL IsFloat = strchr(Text, '.') != NULL;
  2432. if (ItemFlags & ITEM_FLOATING_POINT)
  2433. {
  2434. IsFloat = TRUE;
  2435. }
  2436. if (IsFloat)
  2437. {
  2438. SetRegData->Val.Type = DEBUG_VALUE_FLOAT64;
  2439. if (sscanf(Text, "%lf", &SetRegData->Val.F64) != 1)
  2440. {
  2441. SetRegData->Val.F64 = 0.0;
  2442. }
  2443. }
  2444. else
  2445. {
  2446. SetRegData->Val.Type = DEBUG_VALUE_INT64;
  2447. switch(g_NumberRadix)
  2448. {
  2449. case 10:
  2450. if (sscanf(Text, "%I64d", &SetRegData->Val.I64) != 1)
  2451. {
  2452. SetRegData->Val.I64 = 0;
  2453. }
  2454. break;
  2455. default:
  2456. if (sscanf(Text, "%I64x", &SetRegData->Val.I64) != 1)
  2457. {
  2458. SetRegData->Val.I64 = 0;
  2459. }
  2460. break;
  2461. }
  2462. // XXX drewb - What about IA64 NAT bits?
  2463. SetRegData->Val.Nat = FALSE;
  2464. }
  2465. FinishCommand();
  2466. }
  2467. }
  2468. LRESULT
  2469. CPUWIN_DATA::OnCustomItem(ULONG SubItem, LPNMLVCUSTOMDRAW Custom)
  2470. {
  2471. if (SubItem == 1)
  2472. {
  2473. // Check changed flag stored in lParam.
  2474. if (Custom->nmcd.lItemlParam & ITEM_CHANGED)
  2475. {
  2476. Custom->clrText = g_Colors[COL_CHANGED_DATA_TEXT].Color;
  2477. }
  2478. }
  2479. return CDRF_NOTIFYSUBITEMDRAW;
  2480. }
  2481. void
  2482. CPUWIN_DATA::UpdateNames(BOOL FullUpdate)
  2483. {
  2484. ULONG i;
  2485. ULONG EntryIdx = 0;
  2486. PSTR Name;
  2487. LVITEM LvItem = {0};
  2488. RegisterNamesStateBuffer* NameBuf;
  2489. PULONG RegTypes = NULL;
  2490. PSTR RegNames = NULL;
  2491. ULONG ProcType = m_ProcType;
  2492. BOOL NameChange = FullUpdate || ProcType != m_NamesProcType;
  2493. //
  2494. // This routine has two primary functions: to set
  2495. // up the register window properly for a register set
  2496. // and also to set the register names properly.
  2497. // In the first case the register window must be cleared
  2498. // and all items recreated for the given processor type.
  2499. // During this operation the register names for the given
  2500. // processor type may not have been retrieved yet, so
  2501. // all of the register names will be set as unknown. The
  2502. // important part of the operation is then just creating
  2503. // the proper number of items. A later update will come
  2504. // through when the names are retrieved and at that point
  2505. // a simple name-label-only update will occur.
  2506. //
  2507. NameBuf = GetRegisterNames(ProcType);
  2508. if (NameBuf)
  2509. {
  2510. // If the entries are being sorted by change the
  2511. // names will get updated there and we do not
  2512. // want to do it here.
  2513. if (!NameChange && (NameBuf->m_Flags & REGCUST_CHANGED_FIRST))
  2514. {
  2515. return;
  2516. }
  2517. if (NameBuf->UiLockForRead() == S_OK)
  2518. {
  2519. RegTypes = (PULONG)NameBuf->GetDataBuffer();
  2520. RegNames = (PSTR)NameBuf->GetDataBuffer() +
  2521. NameBuf->m_NamesOffset;
  2522. }
  2523. }
  2524. SendMessage(m_hwndChild, WM_SETREDRAW, FALSE, 0);
  2525. if (NameChange)
  2526. {
  2527. ListView_DeleteAllItems(m_hwndChild);
  2528. }
  2529. LvItem.mask = LVIF_TEXT;
  2530. for (i = 0; i < m_NumRegisters; i++)
  2531. {
  2532. if (RegNames == NULL)
  2533. {
  2534. Name = _T("Unknown");
  2535. }
  2536. else
  2537. {
  2538. ULONG NameIdx = NameBuf->MapUserToEngine(i);
  2539. if ((NameBuf->m_Flags & REGCUST_NO_SUBREG) &&
  2540. (RegTypes[NameIdx * 2 + 1] & DEBUG_REGISTER_SUB_REGISTER))
  2541. {
  2542. continue;
  2543. }
  2544. Name = RegNames;
  2545. while (NameIdx-- > 0)
  2546. {
  2547. Name += strlen(Name) + 1;
  2548. }
  2549. }
  2550. LvItem.pszText = Name;
  2551. LvItem.iItem = EntryIdx;
  2552. if (NameChange)
  2553. {
  2554. ListView_InsertItem(m_hwndChild, &LvItem);
  2555. SetItemFlags(EntryIdx, RegToFlags(0xffff));
  2556. }
  2557. else
  2558. {
  2559. ListView_SetItemText(m_hwndChild, EntryIdx, 0, Name);
  2560. }
  2561. EntryIdx++;
  2562. }
  2563. if (NameBuf && RegNames)
  2564. {
  2565. UnlockStateBuffer(NameBuf);
  2566. }
  2567. SendMessage(m_hwndChild, WM_SETREDRAW, TRUE, 0);
  2568. m_NamesProcType = ProcType;
  2569. }