Source code of Windows XP (NT5)
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.

2819 lines
72 KiB

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