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.

2359 lines
54 KiB

  1. /*++
  2. Copyright (c) 1999-2001 Microsoft Corporation
  3. Module Name:
  4. cmnwin.cpp
  5. Abstract:
  6. This module contains the code for the common window architecture.
  7. --*/
  8. #include "precomp.hxx"
  9. #pragma hdrstop
  10. ULONG g_WinOptions = WOPT_AUTO_ARRANGE | WOPT_AUTO_DISASM;
  11. LIST_ENTRY g_ActiveWin;
  12. PCOMMONWIN_DATA g_IndexedWin[MAXVAL_WINDOW];
  13. HWND g_IndexedHwnd[MAXVAL_WINDOW];
  14. INDEXED_FONT g_Fonts[FONT_COUNT];
  15. BOOL g_LineMarkers = FALSE;
  16. #define CW_WSP_SIG3 '3WCW'
  17. //
  18. //
  19. //
  20. COMMONWIN_DATA::COMMONWIN_DATA(ULONG ChangeBy)
  21. : StateBuffer(ChangeBy)
  22. {
  23. m_Size.cx = 0;
  24. m_Size.cy = 0;
  25. m_CausedArrange = FALSE;
  26. // Creation is an automatic operation so
  27. // InAutoOp is initialized to a non-zero value.
  28. // After CreateWindow returns it is decremented.
  29. m_InAutoOp = 1;
  30. m_enumType = MINVAL_WINDOW;
  31. m_Font = &g_Fonts[FONT_FIXED];
  32. m_FontHeight = 0;
  33. m_LineHeight = 0;
  34. m_Toolbar = NULL;
  35. m_ShowToolbar = FALSE;
  36. m_ToolbarHeight = 0;
  37. m_MinToolbarWidth = 0;
  38. m_ToolbarEdit = NULL;
  39. }
  40. void
  41. COMMONWIN_DATA::Validate()
  42. {
  43. Assert(MINVAL_WINDOW < m_enumType);
  44. Assert(m_enumType < MAXVAL_WINDOW);
  45. }
  46. void
  47. COMMONWIN_DATA::SetFont(ULONG FontIndex)
  48. {
  49. m_Font = &g_Fonts[FontIndex];
  50. m_FontHeight = m_Font->Metrics.tmHeight;
  51. m_LineHeight = m_Size.cy / m_FontHeight;
  52. }
  53. BOOL
  54. COMMONWIN_DATA::CanCopy()
  55. {
  56. if (GetFocus() == m_ToolbarEdit)
  57. {
  58. DWORD Start, End;
  59. SendMessage(m_ToolbarEdit, EM_GETSEL,
  60. (WPARAM)&Start, (WPARAM)&End);
  61. return Start != End;
  62. }
  63. else
  64. {
  65. return FALSE;
  66. }
  67. }
  68. BOOL
  69. COMMONWIN_DATA::CanCut()
  70. {
  71. if (GetFocus() == m_ToolbarEdit)
  72. {
  73. DWORD Start, End;
  74. SendMessage(m_ToolbarEdit, EM_GETSEL,
  75. (WPARAM)&Start, (WPARAM)&End);
  76. return Start != End;
  77. }
  78. else
  79. {
  80. return FALSE;
  81. }
  82. }
  83. BOOL
  84. COMMONWIN_DATA::CanPaste()
  85. {
  86. if (GetFocus() == m_ToolbarEdit)
  87. {
  88. return TRUE;
  89. }
  90. else
  91. {
  92. return FALSE;
  93. }
  94. }
  95. void
  96. COMMONWIN_DATA::Copy()
  97. {
  98. if (GetFocus() == m_ToolbarEdit)
  99. {
  100. SendMessage(m_ToolbarEdit, WM_COPY, 0, 0);
  101. }
  102. }
  103. void
  104. COMMONWIN_DATA::Cut()
  105. {
  106. if (GetFocus() == m_ToolbarEdit)
  107. {
  108. SendMessage(m_ToolbarEdit, WM_CUT, 0, 0);
  109. }
  110. }
  111. void
  112. COMMONWIN_DATA::Paste()
  113. {
  114. if (GetFocus() == m_ToolbarEdit)
  115. {
  116. SendMessage(m_ToolbarEdit, WM_PASTE, 0, 0);
  117. }
  118. }
  119. BOOL
  120. COMMONWIN_DATA::CanSelectAll()
  121. {
  122. return FALSE;
  123. }
  124. void
  125. COMMONWIN_DATA::SelectAll()
  126. {
  127. }
  128. BOOL
  129. COMMONWIN_DATA::HasEditableProperties()
  130. {
  131. return FALSE;
  132. }
  133. BOOL
  134. COMMONWIN_DATA::EditProperties()
  135. /*++
  136. Returns
  137. TRUE - If properties were edited
  138. FALSE - If nothing was changed
  139. --*/
  140. {
  141. return FALSE;
  142. }
  143. HMENU
  144. COMMONWIN_DATA::GetContextMenu(void)
  145. {
  146. return NULL;
  147. }
  148. void
  149. COMMONWIN_DATA::OnContextMenuSelection(UINT Item)
  150. {
  151. // Nothing to do.
  152. }
  153. BOOL
  154. COMMONWIN_DATA::CanGotoLine(void)
  155. {
  156. return FALSE;
  157. }
  158. void
  159. COMMONWIN_DATA::GotoLine(ULONG Line)
  160. {
  161. // Do nothing.
  162. }
  163. void
  164. COMMONWIN_DATA::Find(PTSTR Text, ULONG Flags)
  165. {
  166. // Do nothing.
  167. }
  168. BOOL
  169. COMMONWIN_DATA::CodeExprAtCaret(PSTR Expr, PULONG64 Offset)
  170. {
  171. return FALSE;
  172. }
  173. void
  174. COMMONWIN_DATA::ToggleBpAtCaret(void)
  175. {
  176. char CodeExpr[MAX_OFFSET_EXPR];
  177. ULONG64 Offset;
  178. if (!CodeExprAtCaret(CodeExpr, &Offset) &&
  179. Offset != DEBUG_INVALID_OFFSET)
  180. {
  181. MessageBeep(0);
  182. ErrorBox(NULL, 0, ERR_No_Code_For_File_Line);
  183. return;
  184. }
  185. ULONG CurBpId = DEBUG_ANY_ID;
  186. // This doesn't work too well with duplicate
  187. // breakpoints, but that should be a minor problem.
  188. if (IsBpAtOffset(NULL, Offset, &CurBpId) != BP_NONE)
  189. {
  190. PrintStringCommand(UIC_SILENT_EXECUTE, "bc %d", CurBpId);
  191. }
  192. else
  193. {
  194. PrintStringCommand(UIC_SILENT_EXECUTE, "bp %s", CodeExpr);
  195. }
  196. }
  197. BOOL
  198. COMMONWIN_DATA::OnCreate(void)
  199. {
  200. return TRUE;
  201. }
  202. LRESULT
  203. COMMONWIN_DATA::OnCommand(WPARAM wParam, LPARAM lParam)
  204. {
  205. return 1;
  206. }
  207. void
  208. COMMONWIN_DATA::OnSetFocus(void)
  209. {
  210. }
  211. void
  212. COMMONWIN_DATA::OnSize(void)
  213. {
  214. RECT Rect;
  215. // Resize the toolbar.
  216. if (m_Toolbar != NULL && m_ShowToolbar)
  217. {
  218. // If the toolbar gets too small sometimes it's better
  219. // to just let it get clipped rather than have it
  220. // try to fit into a narrow column.
  221. if (m_Size.cx >= m_MinToolbarWidth)
  222. {
  223. MoveWindow(m_Toolbar, 0, 0, m_Size.cx, m_ToolbarHeight, TRUE);
  224. }
  225. // Record what size it ended up.
  226. GetClientRect(m_Toolbar, &Rect);
  227. m_ToolbarHeight = Rect.bottom - Rect.top;
  228. if (m_FontHeight != 0)
  229. {
  230. if (m_ToolbarHeight >= m_Size.cy)
  231. {
  232. m_LineHeight = 0;
  233. }
  234. else
  235. {
  236. m_LineHeight = (m_Size.cy - m_ToolbarHeight) / m_FontHeight;
  237. }
  238. }
  239. }
  240. else
  241. {
  242. Assert(m_ToolbarHeight == 0);
  243. }
  244. }
  245. void
  246. COMMONWIN_DATA::OnButtonDown(ULONG Button)
  247. {
  248. }
  249. void
  250. COMMONWIN_DATA::OnButtonUp(ULONG Button)
  251. {
  252. }
  253. void
  254. COMMONWIN_DATA::OnMouseMove(ULONG Modifiers, ULONG X, ULONG Y)
  255. {
  256. }
  257. void
  258. COMMONWIN_DATA::OnTimer(WPARAM TimerId)
  259. {
  260. }
  261. LRESULT
  262. COMMONWIN_DATA::OnGetMinMaxInfo(LPMINMAXINFO Info)
  263. {
  264. return 1;
  265. }
  266. LRESULT
  267. COMMONWIN_DATA::OnVKeyToItem(WPARAM wParam, LPARAM lParam)
  268. {
  269. return -1;
  270. }
  271. LRESULT
  272. COMMONWIN_DATA::OnNotify(WPARAM wParam, LPARAM lParam)
  273. {
  274. return 0;
  275. }
  276. void
  277. COMMONWIN_DATA::OnUpdate(UpdateType Type)
  278. {
  279. }
  280. void
  281. COMMONWIN_DATA::OnDestroy(void)
  282. {
  283. }
  284. LRESULT
  285. COMMONWIN_DATA::OnOwnerDraw(UINT uMsg, WPARAM wParam, LPARAM lParam)
  286. {
  287. return 0;
  288. }
  289. ULONG
  290. COMMONWIN_DATA::GetWorkspaceSize(void)
  291. {
  292. return 3 * sizeof(ULONG) + sizeof(WINDOWPLACEMENT);
  293. }
  294. PUCHAR
  295. COMMONWIN_DATA::SetWorkspace(PUCHAR Data)
  296. {
  297. // First store the special signature that marks
  298. // this version of the workspace data.
  299. *(PULONG)Data = CW_WSP_SIG3;
  300. Data += sizeof(ULONG);
  301. // Store the size saved by this layer.
  302. *(PULONG)Data = COMMONWIN_DATA::GetWorkspaceSize();
  303. Data += sizeof(ULONG);
  304. //
  305. // Store the actual data.
  306. //
  307. *(PULONG)Data = m_ShowToolbar;
  308. Data += sizeof(ULONG);
  309. LPWINDOWPLACEMENT Place = (LPWINDOWPLACEMENT)Data;
  310. Place->length = sizeof(WINDOWPLACEMENT);
  311. GetWindowPlacement(m_Win, Place);
  312. Data += sizeof(WINDOWPLACEMENT);
  313. return Data;
  314. }
  315. PUCHAR
  316. COMMONWIN_DATA::ApplyWorkspace1(PUCHAR Data, PUCHAR End)
  317. {
  318. ULONG_PTR Size = End - Data;
  319. // There are three versions of the base COMMONWIN data.
  320. // 1. RECT.
  321. // 2. WINDOWPLACEMENT.
  322. // 3. CW_WSP_SIG3 sized block.
  323. // All three cases can be easily distinguished.
  324. if (Size > 2 * sizeof(ULONG) &&
  325. *(PULONG)Data == CW_WSP_SIG3 &&
  326. Size >= *(PULONG)(Data + sizeof(ULONG)))
  327. {
  328. Size = *(PULONG)(Data + sizeof(ULONG)) - 2 * sizeof(ULONG);
  329. Data += 2 * sizeof(ULONG);
  330. if (Size >= sizeof(ULONG))
  331. {
  332. SetShowToolbar(*(PULONG)Data);
  333. Size -= sizeof(ULONG);
  334. Data += sizeof(ULONG);
  335. }
  336. }
  337. if (Size >= sizeof(WINDOWPLACEMENT) &&
  338. ((LPWINDOWPLACEMENT)Data)->length == sizeof(WINDOWPLACEMENT))
  339. {
  340. LPWINDOWPLACEMENT Place = (LPWINDOWPLACEMENT)Data;
  341. if (!IsAutoArranged(m_enumType))
  342. {
  343. SetWindowPlacement(m_Win, Place);
  344. }
  345. return (PUCHAR)(Place + 1);
  346. }
  347. else
  348. {
  349. LPRECT Rect = (LPRECT)Data;
  350. Assert((PUCHAR)(Rect + 1) <= End);
  351. if (!IsAutoArranged(m_enumType))
  352. {
  353. MoveWindow(m_Win, Rect->left, Rect->top,
  354. (Rect->right - Rect->left), (Rect->bottom - Rect->top),
  355. TRUE);
  356. }
  357. return (PUCHAR)(Rect + 1);
  358. }
  359. }
  360. void
  361. COMMONWIN_DATA::UpdateColors(void)
  362. {
  363. // Nothing to do.
  364. }
  365. void
  366. COMMONWIN_DATA::UpdateSize(ULONG Width, ULONG Height)
  367. {
  368. m_Size.cx = Width;
  369. m_Size.cy = Height;
  370. if (m_FontHeight != 0)
  371. {
  372. m_LineHeight = m_Size.cy / m_FontHeight;
  373. }
  374. }
  375. void
  376. COMMONWIN_DATA::SetShowToolbar(BOOL Show)
  377. {
  378. if (!m_Toolbar)
  379. {
  380. return;
  381. }
  382. m_ShowToolbar = Show;
  383. if (m_ShowToolbar)
  384. {
  385. ShowWindow(m_Toolbar, SW_SHOW);
  386. }
  387. else
  388. {
  389. ShowWindow(m_Toolbar, SW_HIDE);
  390. m_ToolbarHeight = 0;
  391. }
  392. OnSize();
  393. if (g_Workspace != NULL)
  394. {
  395. g_Workspace->AddDirty(WSPF_DIRTY_WINDOWS);
  396. }
  397. }
  398. PCOMMONWIN_DATA
  399. NewWinData(WIN_TYPES Type)
  400. {
  401. switch(Type)
  402. {
  403. case DOC_WINDOW:
  404. return new DOCWIN_DATA;
  405. case WATCH_WINDOW:
  406. return new WATCHWIN_DATA;
  407. case LOCALS_WINDOW:
  408. return new LOCALSWIN_DATA;
  409. case CPU_WINDOW:
  410. return new CPUWIN_DATA;
  411. case DISASM_WINDOW:
  412. return new DISASMWIN_DATA;
  413. case CMD_WINDOW:
  414. return new CMDWIN_DATA;
  415. case SCRATCH_PAD_WINDOW:
  416. return new SCRATCH_PAD_DATA;
  417. case MEM_WINDOW:
  418. return new MEMWIN_DATA;
  419. #if 0
  420. case QUICKW_WINDOW:
  421. // XXX drewb - Unimplemented.
  422. return new QUICKWWIN_DATA;
  423. #endif
  424. case CALLS_WINDOW:
  425. return new CALLSWIN_DATA;
  426. case PROCESS_THREAD_WINDOW:
  427. return new PROCESS_THREAD_DATA;
  428. default:
  429. Assert(FALSE);
  430. return NULL;
  431. }
  432. }
  433. LRESULT
  434. CALLBACK
  435. COMMONWIN_DATA::WindowProc(
  436. HWND hwnd,
  437. UINT uMsg,
  438. WPARAM wParam,
  439. LPARAM lParam
  440. )
  441. {
  442. PCOMMONWIN_DATA pWinData = GetCommonWinData(hwnd);
  443. #if 0
  444. {
  445. DebugPrint("CommonWin msg %X for %p, args %X %X\n",
  446. uMsg, pWinData, wParam, lParam);
  447. }
  448. #endif
  449. if (uMsg != WM_CREATE && pWinData == NULL)
  450. {
  451. return DefMDIChildProc(hwnd, uMsg, wParam, lParam);
  452. }
  453. switch (uMsg)
  454. {
  455. case WM_CREATE:
  456. RECT rc;
  457. COMMONWIN_CREATE_DATA* Data;
  458. Assert(NULL == pWinData);
  459. Data = (COMMONWIN_CREATE_DATA*)
  460. ((LPMDICREATESTRUCT)
  461. (((CREATESTRUCT *)lParam)->lpCreateParams))->lParam;
  462. pWinData = NewWinData(Data->Type);
  463. if (!pWinData)
  464. {
  465. return -1; // Fail window creation
  466. }
  467. Assert(pWinData->m_enumType == Data->Type);
  468. pWinData->m_Win = hwnd;
  469. GetClientRect(hwnd, &rc);
  470. pWinData->m_Size.cx = rc.right;
  471. pWinData->m_Size.cy = rc.bottom;
  472. if ( !pWinData->OnCreate() )
  473. {
  474. delete pWinData;
  475. return -1; // Fail window creation
  476. }
  477. // store this in the window
  478. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pWinData);
  479. #if DBG
  480. pWinData->Validate();
  481. #endif
  482. g_IndexedWin[Data->Type] = pWinData;
  483. g_IndexedHwnd[Data->Type] = hwnd;
  484. InsertHeadList(&g_ActiveWin, &pWinData->m_ActiveWin);
  485. if (g_Workspace != NULL)
  486. {
  487. g_Workspace->AddDirty(WSPF_DIRTY_WINDOWS);
  488. }
  489. SendMessage(hwnd, WM_SETICON, 0, (LPARAM)
  490. LoadIcon(g_hInst,
  491. MAKEINTRESOURCE(pWinData->m_enumType +
  492. MINVAL_WINDOW_ICON)));
  493. // A new buffer has been created so put it in the list
  494. // then wake up the engine to fill it.
  495. Dbg_EnterCriticalSection(&g_QuickLock);
  496. InsertHeadList(&g_StateList, pWinData);
  497. Dbg_LeaveCriticalSection(&g_QuickLock);
  498. UpdateEngine();
  499. // Force initial updates so that the window starts
  500. // out with a state which matches the current debug
  501. // session's state.
  502. PostMessage(hwnd, WU_UPDATE, UPDATE_BUFFER, 0);
  503. PostMessage(hwnd, WU_UPDATE, UPDATE_EXEC, 0);
  504. if (g_WinOptions & WOPT_AUTO_ARRANGE)
  505. {
  506. Arrange();
  507. }
  508. return 0;
  509. case WM_COMMAND:
  510. if (pWinData->OnCommand(wParam, lParam) == 0)
  511. {
  512. return 0;
  513. }
  514. break;
  515. case WM_SETFOCUS:
  516. pWinData->OnSetFocus();
  517. break;
  518. case WM_MOVE:
  519. // When the frame window is minimized or restored
  520. // a move to 0,0 comes through. Ignore this so
  521. // as to not trigger the warning.
  522. if (!IsIconic(g_hwndFrame) && lParam != 0)
  523. {
  524. DisplayAutoArrangeWarning(pWinData);
  525. }
  526. if (g_Workspace != NULL)
  527. {
  528. g_Workspace->AddDirty(WSPF_DIRTY_WINDOWS);
  529. }
  530. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  531. case WM_SIZE:
  532. if (wParam == SIZE_MAXHIDE || wParam == SIZE_MAXSHOW)
  533. {
  534. // We don't care about cover/uncover events.
  535. break;
  536. }
  537. DisplayAutoArrangeWarning(pWinData);
  538. if (g_Workspace != NULL)
  539. {
  540. g_Workspace->AddDirty(WSPF_DIRTY_WINDOWS);
  541. }
  542. pWinData->UpdateSize(LOWORD(lParam), HIWORD(lParam));
  543. // No need to run sizing code for minimize.
  544. if (wParam == SIZE_MINIMIZED)
  545. {
  546. // The minimized window will leave a hole so
  547. // arrange to fill it and leave space for the
  548. // minimized window.
  549. if (g_WinOptions & WOPT_AUTO_ARRANGE)
  550. {
  551. pWinData->m_CausedArrange = TRUE;
  552. Arrange();
  553. }
  554. break;
  555. }
  556. if (wParam == SIZE_RESTORED && pWinData->m_CausedArrange)
  557. {
  558. // If we're restoring a window that caused
  559. // a rearrange when it was minimized we
  560. // need to update things to account for it.
  561. pWinData->m_CausedArrange = FALSE;
  562. if (g_WinOptions & WOPT_AUTO_ARRANGE)
  563. {
  564. Arrange();
  565. }
  566. }
  567. else if (wParam == SIZE_MAXIMIZED)
  568. {
  569. // Ask for a rearrange on restore just
  570. // for consistency with minimize.
  571. pWinData->m_CausedArrange = TRUE;
  572. }
  573. pWinData->OnSize();
  574. break;
  575. case WM_LBUTTONDOWN:
  576. pWinData->OnButtonDown(MK_LBUTTON);
  577. return 0;
  578. case WM_LBUTTONUP:
  579. pWinData->OnButtonUp(MK_LBUTTON);
  580. return 0;
  581. case WM_MBUTTONDOWN:
  582. pWinData->OnButtonDown(MK_MBUTTON);
  583. return 0;
  584. case WM_MBUTTONUP:
  585. pWinData->OnButtonUp(MK_MBUTTON);
  586. return 0;
  587. case WM_RBUTTONDOWN:
  588. pWinData->OnButtonDown(MK_RBUTTON);
  589. return 0;
  590. case WM_RBUTTONUP:
  591. pWinData->OnButtonUp(MK_RBUTTON);
  592. return 0;
  593. case WM_MOUSEMOVE:
  594. pWinData->OnMouseMove((ULONG)wParam, LOWORD(lParam), HIWORD(lParam));
  595. return 0;
  596. case WM_TIMER:
  597. pWinData->OnTimer(wParam);
  598. return 0;
  599. case WM_GETMINMAXINFO:
  600. if (pWinData->OnGetMinMaxInfo((LPMINMAXINFO)lParam) == 0)
  601. {
  602. return 0;
  603. }
  604. break;
  605. case WM_VKEYTOITEM:
  606. return pWinData->OnVKeyToItem(wParam, lParam);
  607. case WM_NOTIFY:
  608. return pWinData->OnNotify(wParam, lParam);
  609. case WU_UPDATE:
  610. pWinData->OnUpdate((UpdateType)wParam);
  611. return 0;
  612. case WU_RECONFIGURE:
  613. pWinData->OnSize();
  614. break;
  615. case WM_DESTROY:
  616. pWinData->OnDestroy();
  617. SetWindowLongPtr(hwnd, GWLP_USERDATA, NULL);
  618. g_IndexedWin[pWinData->m_enumType] = NULL;
  619. g_IndexedHwnd[pWinData->m_enumType] = NULL;
  620. RemoveEntryList(&pWinData->m_ActiveWin);
  621. if (g_Workspace != NULL)
  622. {
  623. g_Workspace->AddDirty(WSPF_DIRTY_WINDOWS);
  624. }
  625. // Mark this buffer as ready for cleanup by the
  626. // engine when it gets around to it.
  627. pWinData->m_Win = NULL;
  628. if (pWinData == g_FindLast)
  629. {
  630. g_FindLast = NULL;
  631. }
  632. UpdateEngine();
  633. if (g_WinOptions & WOPT_AUTO_ARRANGE)
  634. {
  635. Arrange();
  636. }
  637. break;
  638. case WM_MEASUREITEM:
  639. case WM_DRAWITEM:
  640. //
  641. // Both these messages must be handled by owner drawn windows
  642. //
  643. return pWinData->OnOwnerDraw(uMsg, wParam, lParam);
  644. }
  645. return DefMDIChildProc(hwnd, uMsg, wParam, lParam);
  646. }
  647. //
  648. //
  649. //
  650. SINGLE_CHILDWIN_DATA::SINGLE_CHILDWIN_DATA(ULONG ChangeBy)
  651. : COMMONWIN_DATA(ChangeBy)
  652. {
  653. m_hwndChild = NULL;
  654. }
  655. void
  656. SINGLE_CHILDWIN_DATA::Validate()
  657. {
  658. COMMONWIN_DATA::Validate();
  659. Assert(m_hwndChild);
  660. }
  661. void
  662. SINGLE_CHILDWIN_DATA::SetFont(ULONG FontIndex)
  663. {
  664. COMMONWIN_DATA::SetFont(FontIndex);
  665. SendMessage(m_hwndChild,
  666. WM_SETFONT,
  667. (WPARAM) m_Font->Font,
  668. (LPARAM) TRUE
  669. );
  670. }
  671. BOOL
  672. SINGLE_CHILDWIN_DATA::CanCopy()
  673. {
  674. if (GetFocus() != m_hwndChild)
  675. {
  676. return COMMONWIN_DATA::CanCopy();
  677. }
  678. switch (m_enumType)
  679. {
  680. default:
  681. Assert(!"Unknown type");
  682. return FALSE;
  683. case CMD_WINDOW:
  684. Assert(!"Should not be handled here since this is only for windows"
  685. " with only one child window.");
  686. return FALSE;
  687. case WATCH_WINDOW:
  688. case LOCALS_WINDOW:
  689. case CPU_WINDOW:
  690. case QUICKW_WINDOW:
  691. return -1 != ListView_GetNextItem(m_hwndChild,
  692. -1, // Find the first match
  693. LVNI_FOCUSED
  694. );
  695. case CALLS_WINDOW:
  696. return LB_ERR != SendMessage(m_hwndChild, LB_GETCURSEL, 0, 0);
  697. case DOC_WINDOW:
  698. case DISASM_WINDOW:
  699. case MEM_WINDOW:
  700. case SCRATCH_PAD_WINDOW:
  701. CHARRANGE chrg;
  702. SendMessage(m_hwndChild, EM_EXGETSEL, 0, (LPARAM)&chrg);
  703. return chrg.cpMin != chrg.cpMax;
  704. case PROCESS_THREAD_WINDOW:
  705. return NULL != TreeView_GetSelection(m_hwndChild);
  706. }
  707. }
  708. BOOL
  709. SINGLE_CHILDWIN_DATA::CanCut()
  710. {
  711. if (GetFocus() != m_hwndChild)
  712. {
  713. return COMMONWIN_DATA::CanCut();
  714. }
  715. switch (m_enumType)
  716. {
  717. default:
  718. Assert(!"Unknown type");
  719. return FALSE;
  720. case CMD_WINDOW:
  721. Assert(!"Should not be handled here since this is only for windows"
  722. " with only one child window.");
  723. return FALSE;
  724. case WATCH_WINDOW:
  725. case LOCALS_WINDOW:
  726. case CPU_WINDOW:
  727. case QUICKW_WINDOW:
  728. case CALLS_WINDOW:
  729. case DOC_WINDOW:
  730. case DISASM_WINDOW:
  731. case MEM_WINDOW:
  732. case PROCESS_THREAD_WINDOW:
  733. return FALSE;
  734. case SCRATCH_PAD_WINDOW:
  735. CHARRANGE chrg;
  736. SendMessage(m_hwndChild, EM_EXGETSEL, 0, (LPARAM)&chrg);
  737. return chrg.cpMin != chrg.cpMax;
  738. }
  739. }
  740. BOOL
  741. SINGLE_CHILDWIN_DATA::CanPaste()
  742. {
  743. if (GetFocus() != m_hwndChild)
  744. {
  745. return COMMONWIN_DATA::CanPaste();
  746. }
  747. switch (m_enumType)
  748. {
  749. default:
  750. Assert(!"Unknown type");
  751. return FALSE;
  752. case CMD_WINDOW:
  753. Assert(!"Should not be handled here since this is only for windows"
  754. " with only one child window.");
  755. return FALSE;
  756. case WATCH_WINDOW:
  757. case LOCALS_WINDOW:
  758. case CPU_WINDOW:
  759. case QUICKW_WINDOW:
  760. case CALLS_WINDOW:
  761. case DOC_WINDOW:
  762. case DISASM_WINDOW:
  763. case MEM_WINDOW:
  764. case PROCESS_THREAD_WINDOW:
  765. return FALSE;
  766. case SCRATCH_PAD_WINDOW:
  767. return TRUE;
  768. }
  769. }
  770. void
  771. SINGLE_CHILDWIN_DATA::Copy()
  772. {
  773. if (GetFocus() != m_hwndChild)
  774. {
  775. COMMONWIN_DATA::Copy();
  776. }
  777. else
  778. {
  779. SendMessage(m_hwndChild, WM_COPY, 0, 0);
  780. }
  781. }
  782. void
  783. SINGLE_CHILDWIN_DATA::Cut()
  784. {
  785. if (GetFocus() != m_hwndChild)
  786. {
  787. COMMONWIN_DATA::Paste();
  788. }
  789. }
  790. void
  791. SINGLE_CHILDWIN_DATA::Paste()
  792. {
  793. if (GetFocus() != m_hwndChild)
  794. {
  795. COMMONWIN_DATA::Paste();
  796. }
  797. }
  798. void
  799. SINGLE_CHILDWIN_DATA::OnSetFocus()
  800. {
  801. ::SetFocus(m_hwndChild);
  802. }
  803. void
  804. SINGLE_CHILDWIN_DATA::OnSize(void)
  805. {
  806. COMMONWIN_DATA::OnSize();
  807. MoveWindow(m_hwndChild, 0, m_ToolbarHeight,
  808. m_Size.cx, m_Size.cy - m_ToolbarHeight, TRUE);
  809. }
  810. //
  811. //
  812. //
  813. PROCESS_THREAD_DATA::PROCESS_THREAD_DATA()
  814. : SINGLE_CHILDWIN_DATA(512)
  815. {
  816. m_enumType = PROCESS_THREAD_WINDOW;
  817. m_NumProcesses = 0;
  818. }
  819. void
  820. PROCESS_THREAD_DATA::Validate()
  821. {
  822. SINGLE_CHILDWIN_DATA::Validate();
  823. Assert(PROCESS_THREAD_WINDOW == m_enumType);
  824. }
  825. HRESULT
  826. PROCESS_THREAD_DATA::ReadState(void)
  827. {
  828. HRESULT Status;
  829. ULONG CurProc, CurThread;
  830. ULONG NumProc, NumThread;
  831. ULONG TotalThread, MaxThread;
  832. ULONG Proc, Thread;
  833. PULONG ProcIds, ProcSysIds, ProcThreads, ProcNames;
  834. PULONG ThreadIds, ThreadSysIds;
  835. ULONG ThreadsDone;
  836. char ExeName[MAX_PATH];
  837. if ((Status = g_pDbgSystem->GetCurrentProcessId(&CurProc)) != S_OK ||
  838. (Status = g_pDbgSystem->GetCurrentThreadId(&CurThread)) != S_OK ||
  839. (Status = g_pDbgSystem->GetNumberProcesses(&NumProc)) != S_OK ||
  840. (Status = g_pDbgSystem->
  841. GetTotalNumberThreads(&TotalThread, &MaxThread)) != S_OK)
  842. {
  843. return Status;
  844. }
  845. Empty();
  846. ProcIds = (PULONG)AddData((NumProc * 4 + TotalThread * 2) * sizeof(ULONG));
  847. if (ProcIds == NULL)
  848. {
  849. return E_OUTOFMEMORY;
  850. }
  851. ProcSysIds = ProcIds + NumProc;
  852. if ((Status = g_pDbgSystem->
  853. GetProcessIdsByIndex(0, NumProc, ProcIds, ProcSysIds)) != S_OK)
  854. {
  855. return Status;
  856. }
  857. ThreadsDone = 0;
  858. for (Proc = 0; Proc < NumProc; Proc++)
  859. {
  860. PSTR ExeStore;
  861. // Refresh pointers on every loop in case a resize
  862. // caused buffer movement.
  863. ProcIds = (PULONG)GetDataBuffer();
  864. ProcSysIds = ProcIds + NumProc;
  865. ProcThreads = ProcSysIds + NumProc;
  866. ProcNames = ProcThreads + NumProc;
  867. ThreadIds = ProcNames + NumProc + ThreadsDone;
  868. ThreadSysIds = ThreadIds + TotalThread;
  869. if ((Status = g_pDbgSystem->
  870. SetCurrentProcessId(ProcIds[Proc])) != S_OK ||
  871. FAILED(Status = g_pDbgSystem->
  872. GetCurrentProcessExecutableName(ExeName,
  873. sizeof(ExeName),
  874. NULL)) ||
  875. (Status = g_pDbgSystem->GetNumberThreads(&NumThread)) != S_OK ||
  876. (Status = g_pDbgSystem->
  877. GetThreadIdsByIndex(0, NumThread,
  878. ThreadIds, ThreadSysIds)) != S_OK)
  879. {
  880. goto CurProc;
  881. }
  882. ProcThreads[Proc] = NumThread;
  883. ThreadsDone += NumThread;
  884. ProcNames[Proc] = strlen(ExeName) + 1;
  885. if (ProcNames[Proc] > 1)
  886. {
  887. ExeStore = (PSTR)AddData(ProcNames[Proc]);
  888. if (ExeStore == NULL)
  889. {
  890. Status = E_OUTOFMEMORY;
  891. goto CurProc;
  892. }
  893. strcpy(ExeStore, ExeName);
  894. }
  895. }
  896. m_NumProcesses = NumProc;
  897. m_TotalThreads = TotalThread;
  898. Status = S_OK;
  899. CurProc:
  900. g_pDbgSystem->SetCurrentProcessId(CurProc);
  901. return Status;
  902. }
  903. BOOL
  904. PROCESS_THREAD_DATA::OnCreate(void)
  905. {
  906. if (!SINGLE_CHILDWIN_DATA::OnCreate())
  907. {
  908. return FALSE;
  909. }
  910. m_hwndChild = CreateWindow(
  911. WC_TREEVIEW, // class name
  912. NULL, // title
  913. WS_CLIPSIBLINGS |
  914. WS_CHILD | WS_VISIBLE |
  915. WS_HSCROLL | WS_VSCROLL |
  916. TVS_HASBUTTONS | TVS_LINESATROOT |
  917. TVS_HASLINES, // style
  918. 0, // x
  919. 0, // y
  920. m_Size.cx, // width
  921. m_Size.cy, // height
  922. m_Win, // parent
  923. (HMENU) IDC_PROCESS_TREE, // control id
  924. g_hInst, // hInstance
  925. NULL); // user defined data
  926. if (!m_hwndChild)
  927. {
  928. return FALSE;
  929. }
  930. SetFont(FONT_FIXED);
  931. return TRUE;
  932. }
  933. LRESULT
  934. PROCESS_THREAD_DATA::OnNotify(WPARAM Wpm, LPARAM Lpm)
  935. {
  936. LPNMTREEVIEW Tvn;
  937. HTREEITEM Sel;
  938. Tvn = (LPNMTREEVIEW)Lpm;
  939. if (Tvn->hdr.idFrom != IDC_PROCESS_TREE)
  940. {
  941. return FALSE;
  942. }
  943. switch(Tvn->hdr.code)
  944. {
  945. case NM_DBLCLK:
  946. TVHITTESTINFO HitTest;
  947. if (!GetCursorPos(&HitTest.pt))
  948. {
  949. break;
  950. }
  951. ScreenToClient(m_hwndChild, &HitTest.pt);
  952. Sel = TreeView_HitTest(m_hwndChild, &HitTest);
  953. if (Sel != NULL &&
  954. (HitTest.flags & TVHT_ONITEMLABEL))
  955. {
  956. SetCurThreadFromProcessTreeItem(m_hwndChild, Sel);
  957. }
  958. break;
  959. }
  960. return FALSE;
  961. }
  962. void
  963. PROCESS_THREAD_DATA::OnUpdate(UpdateType Type)
  964. {
  965. if (Type != UPDATE_BUFFER &&
  966. Type != UPDATE_EXEC)
  967. {
  968. return;
  969. }
  970. HRESULT Status;
  971. Status = UiLockForRead();
  972. if (Status != S_OK)
  973. {
  974. return;
  975. }
  976. ULONG NumThread;
  977. ULONG Proc, Thread;
  978. PULONG ProcIds, ProcSysIds, ProcThreads, ProcNames;
  979. PULONG ThreadIds, ThreadSysIds;
  980. char Text[MAX_PATH + 64];
  981. PSTR Names;
  982. HTREEITEM CurThreadItem = NULL;
  983. ProcIds = (PULONG)GetDataBuffer();
  984. ProcSysIds = ProcIds + m_NumProcesses;
  985. ProcThreads = ProcSysIds + m_NumProcesses;
  986. ProcNames = ProcThreads + m_NumProcesses;
  987. ThreadIds = ProcNames + m_NumProcesses;
  988. ThreadSysIds = ThreadIds + m_TotalThreads;
  989. Names = (PSTR)(ThreadSysIds + m_TotalThreads);
  990. TreeView_DeleteAllItems(m_hwndChild);
  991. for (Proc = 0; Proc < m_NumProcesses; Proc++)
  992. {
  993. HTREEITEM ProcItem;
  994. TVINSERTSTRUCT Insert;
  995. sprintf(Text, "%03d:%x ", ProcIds[Proc], ProcSysIds[Proc]);
  996. if (ProcNames[Proc] > 1)
  997. {
  998. strcpy(Text + strlen(Text), Names);
  999. Names += strlen(Names) + 1;
  1000. }
  1001. Insert.hParent = TVI_ROOT;
  1002. Insert.hInsertAfter = TVI_LAST;
  1003. Insert.item.mask = TVIF_TEXT | TVIF_STATE | TVIF_PARAM;
  1004. Insert.item.pszText = Text;
  1005. Insert.item.state =
  1006. ProcIds[Proc] == g_CurProcessId ? TVIS_EXPANDED | TVIS_BOLD: 0;
  1007. Insert.item.stateMask = TVIS_EXPANDED | TVIS_BOLD;
  1008. // Parameter is the thread ID to set to select the given thread.
  1009. Insert.item.lParam = (LPARAM)ThreadIds[0];
  1010. ProcItem = TreeView_InsertItem(m_hwndChild, &Insert);
  1011. for (Thread = 0; Thread < ProcThreads[Proc]; Thread++)
  1012. {
  1013. HTREEITEM ThreadItem;
  1014. sprintf(Text, "%03d:%x", ThreadIds[Thread], ThreadSysIds[Thread]);
  1015. Insert.hParent = ProcItem;
  1016. Insert.hInsertAfter = TVI_LAST;
  1017. Insert.item.mask = TVIF_TEXT | TVIF_STATE | TVIF_PARAM;
  1018. Insert.item.pszText = Text;
  1019. Insert.item.state =
  1020. ProcIds[Proc] == g_CurProcessId &&
  1021. ThreadIds[Thread] == g_CurThreadId ?
  1022. TVIS_BOLD : 0;
  1023. Insert.item.stateMask = TVIS_BOLD;
  1024. Insert.item.lParam = (LPARAM)ThreadIds[Thread];
  1025. ThreadItem = TreeView_InsertItem(m_hwndChild, &Insert);
  1026. if (Insert.item.state & TVIS_BOLD)
  1027. {
  1028. CurThreadItem = ThreadItem;
  1029. }
  1030. }
  1031. ThreadIds += ProcThreads[Proc];
  1032. ThreadSysIds += ProcThreads[Proc];
  1033. }
  1034. if (CurThreadItem)
  1035. {
  1036. TreeView_Select(m_hwndChild, CurThreadItem, TVGN_CARET);
  1037. }
  1038. UnlockStateBuffer(this);
  1039. }
  1040. void
  1041. PROCESS_THREAD_DATA::SetCurThreadFromProcessTreeItem(HWND Tree, HTREEITEM Sel)
  1042. {
  1043. TVITEM Item;
  1044. Item.hItem = Sel;
  1045. Item.mask = TVIF_CHILDREN | TVIF_PARAM;
  1046. TreeView_GetItem(Tree, &Item);
  1047. g_pUiSystem->SetCurrentThreadId((ULONG)Item.lParam);
  1048. }
  1049. //
  1050. //
  1051. //
  1052. EDITWIN_DATA::EDITWIN_DATA(ULONG ChangeBy)
  1053. : SINGLE_CHILDWIN_DATA(ChangeBy)
  1054. {
  1055. m_TextLines = 0;
  1056. m_Highlights = NULL;
  1057. }
  1058. void
  1059. EDITWIN_DATA::Validate()
  1060. {
  1061. SINGLE_CHILDWIN_DATA::Validate();
  1062. }
  1063. void
  1064. EDITWIN_DATA::SetFont(ULONG FontIndex)
  1065. {
  1066. SINGLE_CHILDWIN_DATA::SetFont(FontIndex);
  1067. // Force the tabstop size to be recomputed
  1068. // with the new font.
  1069. SendMessage(m_hwndChild, EM_SETTABSTOPS, 1, (LPARAM)&g_TabWidth);
  1070. }
  1071. BOOL
  1072. EDITWIN_DATA::CanSelectAll()
  1073. {
  1074. return TRUE;
  1075. }
  1076. void
  1077. EDITWIN_DATA::SelectAll()
  1078. {
  1079. CHARRANGE Sel;
  1080. Sel.cpMin = 0;
  1081. Sel.cpMax = INT_MAX;
  1082. SendMessage(m_hwndChild, EM_EXSETSEL, 0, (LPARAM)&Sel);
  1083. }
  1084. BOOL
  1085. EDITWIN_DATA::OnCreate(void)
  1086. {
  1087. m_hwndChild = CreateWindowEx(
  1088. WS_EX_CLIENTEDGE, // Extended style
  1089. RICHEDIT_CLASS, // class name
  1090. NULL, // title
  1091. WS_CLIPSIBLINGS
  1092. | WS_CHILD | WS_VISIBLE
  1093. | WS_VSCROLL | ES_AUTOVSCROLL
  1094. | WS_HSCROLL | ES_AUTOHSCROLL
  1095. | ES_READONLY
  1096. | ES_MULTILINE, // style
  1097. 0, // x
  1098. m_ToolbarHeight, // y
  1099. m_Size.cx, // width
  1100. m_Size.cy - m_ToolbarHeight, // height
  1101. m_Win, // parent
  1102. (HMENU) 0, // control id
  1103. g_hInst, // hInstance
  1104. NULL); // user defined data
  1105. if (m_hwndChild)
  1106. {
  1107. SetFont( FONT_FIXED );
  1108. SendMessage(m_hwndChild, EM_SETBKGNDCOLOR, FALSE,
  1109. g_Colors[COL_PLAIN].Color);
  1110. }
  1111. return m_hwndChild != NULL;
  1112. }
  1113. LRESULT
  1114. EDITWIN_DATA::OnNotify(WPARAM Wpm, LPARAM Lpm)
  1115. {
  1116. NMHDR* Hdr = (NMHDR*)Lpm;
  1117. if (Hdr->code == EN_SAVECLIPBOARD)
  1118. {
  1119. // Indicate that the clipboard contents should
  1120. // be kept alive.
  1121. return 0;
  1122. }
  1123. else if (Hdr->code == EN_MSGFILTER)
  1124. {
  1125. MSGFILTER* Filter = (MSGFILTER*)Lpm;
  1126. if (WM_SYSKEYDOWN == Filter->msg ||
  1127. WM_SYSKEYUP == Filter->msg ||
  1128. WM_SYSCHAR == Filter->msg)
  1129. {
  1130. // Force default processing for menu operations
  1131. // so that the Alt-minus menu comes up.
  1132. return 1;
  1133. }
  1134. }
  1135. return 0;
  1136. }
  1137. void
  1138. EDITWIN_DATA::OnDestroy(void)
  1139. {
  1140. EDIT_HIGHLIGHT* Next;
  1141. while (m_Highlights != NULL)
  1142. {
  1143. Next = m_Highlights->Next;
  1144. delete m_Highlights;
  1145. m_Highlights = Next;
  1146. }
  1147. SINGLE_CHILDWIN_DATA::OnDestroy();
  1148. }
  1149. void
  1150. EDITWIN_DATA::UpdateColors(void)
  1151. {
  1152. SendMessage(m_hwndChild, EM_SETBKGNDCOLOR, FALSE,
  1153. g_Colors[COL_PLAIN].Color);
  1154. UpdateBpMarks();
  1155. }
  1156. void
  1157. EDITWIN_DATA::SetCurrentLineHighlight(ULONG Line)
  1158. {
  1159. //
  1160. // Clear any other current line highlight in this window.
  1161. // Also, oOnly one doc window can have a current IP highlight so if
  1162. // this is a doc window getting a current IP highlight make
  1163. // sure no other doc windows have a current IP highlight.
  1164. //
  1165. if (m_enumType == DOC_WINDOW && ULONG_MAX != Line)
  1166. {
  1167. RemoveActiveWinHighlights(1 << DOC_WINDOW, EHL_CURRENT_LINE);
  1168. }
  1169. else
  1170. {
  1171. RemoveAllHighlights(EHL_CURRENT_LINE);
  1172. }
  1173. if (ULONG_MAX != Line)
  1174. {
  1175. AddHighlight(Line, EHL_CURRENT_LINE);
  1176. CHARRANGE crSet;
  1177. // Set the caret on the current line. This automatically
  1178. // scrolls the line into view if necessary and prevents
  1179. // the view from snapping back to whatever old selection
  1180. // there was.
  1181. HWND OldFocus = ::SetFocus(m_hwndChild);
  1182. crSet.cpMax = crSet.cpMin = (LONG)
  1183. SendMessage(m_hwndChild, EM_LINEINDEX, Line, 0);
  1184. SendMessage(m_hwndChild, EM_EXSETSEL, 0, (LPARAM)&crSet);
  1185. ::SetFocus(OldFocus);
  1186. }
  1187. }
  1188. EDIT_HIGHLIGHT*
  1189. EDITWIN_DATA::GetLineHighlighting(ULONG Line)
  1190. {
  1191. EDIT_HIGHLIGHT* Hl;
  1192. for (Hl = m_Highlights; Hl != NULL; Hl = Hl->Next)
  1193. {
  1194. if (Hl->Line == Line)
  1195. {
  1196. return Hl;
  1197. }
  1198. }
  1199. return NULL;
  1200. }
  1201. void
  1202. EDITWIN_DATA::ApplyHighlight(EDIT_HIGHLIGHT* Hl)
  1203. {
  1204. CHARRANGE crOld;
  1205. // Get the old selection
  1206. SendMessage(m_hwndChild, EM_EXGETSEL, 0, (LPARAM) &crOld);
  1207. //
  1208. // Compute the highlight information.
  1209. //
  1210. char Markers[LINE_MARKERS + 1];
  1211. CHARFORMAT2 cf;
  1212. ULONG TextCol, BgCol;
  1213. Markers[2] = 0;
  1214. ZeroMemory(&cf, sizeof(cf));
  1215. cf.cbSize = sizeof(cf);
  1216. cf.dwMask = CFM_COLOR | CFM_BACKCOLOR;
  1217. if (Hl->Flags & EHL_CURRENT_LINE)
  1218. {
  1219. Markers[1] = '>';
  1220. switch(Hl->Flags & EHL_ANY_BP)
  1221. {
  1222. case EHL_ENABLED_BP:
  1223. Markers[0] = 'B';
  1224. TextCol = COL_BP_CURRENT_LINE_TEXT;
  1225. BgCol = COL_BP_CURRENT_LINE;
  1226. break;
  1227. case EHL_DISABLED_BP:
  1228. Markers[0] = 'D';
  1229. TextCol = COL_BP_CURRENT_LINE_TEXT;
  1230. BgCol = COL_BP_CURRENT_LINE;
  1231. break;
  1232. default:
  1233. Markers[0] = ' ';
  1234. TextCol = COL_CURRENT_LINE_TEXT;
  1235. BgCol = COL_CURRENT_LINE;
  1236. break;
  1237. }
  1238. }
  1239. else
  1240. {
  1241. Markers[1] = ' ';
  1242. switch(Hl->Flags & EHL_ANY_BP)
  1243. {
  1244. case EHL_ENABLED_BP:
  1245. Markers[0] = 'B';
  1246. TextCol = COL_ENABLED_BP_TEXT;
  1247. BgCol = COL_ENABLED_BP;
  1248. break;
  1249. case EHL_DISABLED_BP:
  1250. Markers[0] = 'D';
  1251. TextCol = COL_DISABLED_BP_TEXT;
  1252. BgCol = COL_DISABLED_BP;
  1253. break;
  1254. default:
  1255. Markers[0] = ' ';
  1256. TextCol = COL_PLAIN_TEXT;
  1257. BgCol = COL_PLAIN;
  1258. break;
  1259. }
  1260. }
  1261. cf.crTextColor = g_Colors[TextCol].Color;
  1262. cf.crBackColor = g_Colors[BgCol].Color;
  1263. //
  1264. // Select the line to be highlighted
  1265. //
  1266. CHARRANGE crNew;
  1267. crNew.cpMin = (LONG)SendMessage(m_hwndChild, EM_LINEINDEX, Hl->Line, 0);
  1268. if (g_LineMarkers)
  1269. {
  1270. // Replace the markers at the beginning of the line.
  1271. crNew.cpMax = crNew.cpMin + 2;
  1272. SendMessage(m_hwndChild, EM_EXSETSEL, 0, (LPARAM)&crNew);
  1273. SendMessage(m_hwndChild, EM_REPLACESEL, FALSE, (LPARAM)Markers);
  1274. }
  1275. // Color the line.
  1276. crNew.cpMax = crNew.cpMin + (LONG)
  1277. SendMessage(m_hwndChild, EM_LINELENGTH, crNew.cpMin, 0) + 1;
  1278. if (g_LineMarkers)
  1279. {
  1280. crNew.cpMin += 2;
  1281. }
  1282. SendMessage(m_hwndChild, EM_EXSETSEL, 0, (LPARAM) &crNew);
  1283. SendMessage(m_hwndChild, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
  1284. // Restore the old selection
  1285. SendMessage(m_hwndChild, EM_EXSETSEL, 0, (LPARAM) &crOld);
  1286. }
  1287. EDIT_HIGHLIGHT*
  1288. EDITWIN_DATA::AddHighlight(ULONG Line, ULONG Flags)
  1289. {
  1290. EDIT_HIGHLIGHT* Hl;
  1291. // Search for an existing highlight record for the line.
  1292. Hl = GetLineHighlighting(Line);
  1293. if (Hl == NULL)
  1294. {
  1295. Hl = new EDIT_HIGHLIGHT;
  1296. if (Hl == NULL)
  1297. {
  1298. return NULL;
  1299. }
  1300. Hl->Data = 0;
  1301. Hl->Line = Line;
  1302. Hl->Flags = 0;
  1303. Hl->Next = m_Highlights;
  1304. m_Highlights = Hl;
  1305. }
  1306. Hl->Flags |= Flags;
  1307. ApplyHighlight(Hl);
  1308. return Hl;
  1309. }
  1310. void
  1311. EDITWIN_DATA::RemoveHighlight(ULONG Line, ULONG Flags)
  1312. {
  1313. EDIT_HIGHLIGHT* Hl;
  1314. EDIT_HIGHLIGHT* Prev;
  1315. // Search for an existing highlight record for the line.
  1316. Prev = NULL;
  1317. for (Hl = m_Highlights; Hl != NULL; Hl = Hl->Next)
  1318. {
  1319. if (Hl->Line == Line)
  1320. {
  1321. break;
  1322. }
  1323. Prev = Hl;
  1324. }
  1325. if (Hl == NULL)
  1326. {
  1327. return;
  1328. }
  1329. Hl->Flags &= ~Flags;
  1330. ApplyHighlight(Hl);
  1331. if (Hl->Flags == 0)
  1332. {
  1333. if (Prev == NULL)
  1334. {
  1335. m_Highlights = Hl->Next;
  1336. }
  1337. else
  1338. {
  1339. Prev->Next = Hl->Next;
  1340. }
  1341. delete Hl;
  1342. }
  1343. }
  1344. void
  1345. EDITWIN_DATA::RemoveAllHighlights(ULONG Flags)
  1346. {
  1347. EDIT_HIGHLIGHT* Hl;
  1348. EDIT_HIGHLIGHT* Next;
  1349. EDIT_HIGHLIGHT* Prev;
  1350. Prev = NULL;
  1351. for (Hl = m_Highlights; Hl != NULL; Hl = Next)
  1352. {
  1353. Next = Hl->Next;
  1354. if (Hl->Flags & Flags)
  1355. {
  1356. Hl->Flags &= ~Flags;
  1357. ApplyHighlight(Hl);
  1358. if (Hl->Flags == 0)
  1359. {
  1360. if (Prev == NULL)
  1361. {
  1362. m_Highlights = Hl->Next;
  1363. }
  1364. else
  1365. {
  1366. Prev->Next = Hl->Next;
  1367. }
  1368. delete Hl;
  1369. }
  1370. else
  1371. {
  1372. Prev = Hl;
  1373. }
  1374. }
  1375. else
  1376. {
  1377. Prev = Hl;
  1378. }
  1379. }
  1380. }
  1381. void
  1382. EDITWIN_DATA::RemoveActiveWinHighlights(ULONG Types, ULONG Flags)
  1383. {
  1384. PLIST_ENTRY Entry = g_ActiveWin.Flink;
  1385. while (Entry != &g_ActiveWin)
  1386. {
  1387. PEDITWIN_DATA WinData = (PEDITWIN_DATA)
  1388. ACTIVE_WIN_ENTRY(Entry);
  1389. if (Types & (1 << WinData->m_enumType))
  1390. {
  1391. WinData->RemoveAllHighlights(Flags);
  1392. }
  1393. Entry = Entry->Flink;
  1394. }
  1395. }
  1396. void
  1397. EDITWIN_DATA::UpdateBpMarks(void)
  1398. {
  1399. // Empty implementation for derived classes
  1400. // that do not show BP marks.
  1401. }
  1402. int
  1403. EDITWIN_DATA::CheckForFileChanges(PCSTR File, FILETIME* LastWrite)
  1404. {
  1405. HANDLE Handle;
  1406. Handle = CreateFile(File, GENERIC_READ, FILE_SHARE_READ,
  1407. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
  1408. NULL);
  1409. if (Handle == INVALID_HANDLE_VALUE)
  1410. {
  1411. goto Changed;
  1412. }
  1413. FILETIME NewWrite;
  1414. if (!GetFileTime(Handle, NULL, NULL, &NewWrite))
  1415. {
  1416. if (!GetFileTime(Handle, &NewWrite, NULL, NULL))
  1417. {
  1418. ZeroMemory(&NewWrite, sizeof(NewWrite));
  1419. }
  1420. }
  1421. CloseHandle(Handle);
  1422. if (CompareFileTime(LastWrite, &NewWrite) == 0)
  1423. {
  1424. // No change.
  1425. return IDCANCEL;
  1426. }
  1427. Changed:
  1428. return QuestionBox(ERR_File_Has_Changed, MB_YESNO, File);
  1429. }
  1430. //
  1431. //
  1432. //
  1433. SCRATCH_PAD_DATA::SCRATCH_PAD_DATA()
  1434. : EDITWIN_DATA(16)
  1435. {
  1436. m_enumType = SCRATCH_PAD_WINDOW;
  1437. }
  1438. void
  1439. SCRATCH_PAD_DATA::Validate()
  1440. {
  1441. EDITWIN_DATA::Validate();
  1442. Assert(SCRATCH_PAD_WINDOW == m_enumType);
  1443. }
  1444. void
  1445. SCRATCH_PAD_DATA::Cut()
  1446. {
  1447. SendMessage(m_hwndChild, WM_CUT, 0, 0);
  1448. }
  1449. void
  1450. SCRATCH_PAD_DATA::Paste()
  1451. {
  1452. SendMessage(m_hwndChild, WM_PASTE, 0, 0);
  1453. }
  1454. BOOL
  1455. SCRATCH_PAD_DATA::OnCreate(void)
  1456. {
  1457. if (!EDITWIN_DATA::OnCreate())
  1458. {
  1459. return FALSE;
  1460. }
  1461. SendMessage(m_hwndChild, EM_SETOPTIONS, ECOOP_AND, ~ECO_READONLY);
  1462. return TRUE;
  1463. }
  1464. //
  1465. //
  1466. //
  1467. DISASMWIN_DATA::DISASMWIN_DATA()
  1468. : EDITWIN_DATA(2048)
  1469. {
  1470. m_enumType = DISASM_WINDOW;
  1471. sprintf(m_OffsetExpr, "0x%I64x", g_EventIp);
  1472. m_UpdateExpr = FALSE;
  1473. m_FirstInstr = 0;
  1474. m_LastInstr = 0;
  1475. }
  1476. void
  1477. DISASMWIN_DATA::Validate()
  1478. {
  1479. EDITWIN_DATA::Validate();
  1480. Assert(DISASM_WINDOW == m_enumType);
  1481. }
  1482. HRESULT
  1483. DISASMWIN_DATA::ReadState(void)
  1484. {
  1485. HRESULT Status;
  1486. // Sample these values right away in case the UI changes them.
  1487. ULONG LinesTotal = m_LineHeight;
  1488. ULONG LinesBefore = LinesTotal / 2;
  1489. ULONG Line;
  1490. DEBUG_VALUE Value;
  1491. if ((Status = g_pDbgControl->Evaluate(m_OffsetExpr, DEBUG_VALUE_INT64,
  1492. &Value, NULL)) != S_OK)
  1493. {
  1494. return Status;
  1495. }
  1496. m_PrimaryInstr = Value.I64;
  1497. // Reserve space at the beginning of the buffer to
  1498. // store the line to offset mapping table.
  1499. PULONG64 LineMap;
  1500. Empty();
  1501. LineMap = (PULONG64)AddData(sizeof(ULONG64) * LinesTotal);
  1502. if (LineMap == NULL)
  1503. {
  1504. return E_OUTOFMEMORY;
  1505. }
  1506. // We also need to allocate a temporary line map to
  1507. // pass to the engine for filling. This can't be
  1508. // the state buffer data since that may move as
  1509. // output is generated.
  1510. LineMap = new ULONG64[LinesTotal];
  1511. if (LineMap == NULL)
  1512. {
  1513. return E_OUTOFMEMORY;
  1514. }
  1515. g_OutStateBuf.SetBuffer(this);
  1516. if ((Status = g_OutStateBuf.Start(FALSE)) != S_OK)
  1517. {
  1518. delete LineMap;
  1519. return Status;
  1520. }
  1521. Status = g_pOutCapControl->
  1522. OutputDisassemblyLines(DEBUG_OUTCTL_THIS_CLIENT |
  1523. DEBUG_OUTCTL_OVERRIDE_MASK |
  1524. DEBUG_OUTCTL_NOT_LOGGED,
  1525. LinesBefore, LinesTotal, m_PrimaryInstr,
  1526. DEBUG_DISASM_EFFECTIVE_ADDRESS |
  1527. DEBUG_DISASM_MATCHING_SYMBOLS,
  1528. &m_PrimaryLine, &m_FirstInstr, &m_LastInstr,
  1529. LineMap);
  1530. memcpy(m_Data, LineMap, sizeof(ULONG64) * LinesTotal);
  1531. delete LineMap;
  1532. if (Status != S_OK)
  1533. {
  1534. g_OutStateBuf.End(FALSE);
  1535. return Status;
  1536. }
  1537. m_TextLines = LinesTotal;
  1538. m_TextOffset = LinesTotal * sizeof(ULONG64);
  1539. // The line map is generated with offsets followed by
  1540. // invalid offsets for continuation lines. We want
  1541. // the offsets to be on the last line of the disassembly
  1542. // for a continuation set so move them down.
  1543. // We don't want to move the offsets down to blank lines,
  1544. // though, such as the blank lines that separate bundles
  1545. // in IA64 disassembly.
  1546. LineMap = (PULONG64)m_Data;
  1547. PULONG64 LineMapEnd = LineMap + m_TextLines;
  1548. PULONG64 SetStart;
  1549. PSTR Text = (PSTR)m_Data + m_TextOffset;
  1550. PSTR PrevText;
  1551. while (LineMap < LineMapEnd)
  1552. {
  1553. if (*LineMap != DEBUG_INVALID_OFFSET)
  1554. {
  1555. SetStart = LineMap;
  1556. for (;;)
  1557. {
  1558. PrevText = Text;
  1559. Text = strchr(Text, '\n') + 1;
  1560. LineMap++;
  1561. if (LineMap >= LineMapEnd ||
  1562. *LineMap != DEBUG_INVALID_OFFSET ||
  1563. *Text == '\n')
  1564. {
  1565. break;
  1566. }
  1567. }
  1568. LineMap--;
  1569. Text = PrevText;
  1570. if (LineMap > SetStart)
  1571. {
  1572. *LineMap = *SetStart;
  1573. *SetStart = DEBUG_INVALID_OFFSET;
  1574. }
  1575. }
  1576. LineMap++;
  1577. Text = strchr(Text, '\n') + 1;
  1578. }
  1579. #ifdef DEBUG_DISASM
  1580. LineMap = (PULONG64)m_Data;
  1581. for (Line = 0; Line < m_TextLines; Line++)
  1582. {
  1583. DebugPrint("%d: %I64x\n", Line, LineMap[Line]);
  1584. }
  1585. #endif
  1586. return g_OutStateBuf.End(TRUE);
  1587. }
  1588. BOOL
  1589. DISASMWIN_DATA::CodeExprAtCaret(PSTR Expr, PULONG64 Offset)
  1590. {
  1591. BOOL Succ = FALSE;
  1592. LRESULT LineChar;
  1593. LONG Line;
  1594. PULONG64 LineMap;
  1595. if (UiLockForRead() != S_OK)
  1596. {
  1597. goto NoCode;
  1598. }
  1599. LineChar = SendMessage(m_hwndChild, EM_LINEINDEX, -1, 0);
  1600. Line = (LONG)SendMessage(m_hwndChild, EM_EXLINEFROMCHAR, 0, LineChar);
  1601. if (Line < 0 || (ULONG)Line >= m_TextLines)
  1602. {
  1603. goto UnlockNoCode;
  1604. }
  1605. ULONG64 LineOff;
  1606. // Look up the offset in the line map. If it's part of
  1607. // a multiline group move forward to the offset.
  1608. LineMap = (PULONG64)m_Data;
  1609. LineOff = LineMap[Line];
  1610. while ((ULONG)(Line + 1) < m_TextLines && LineOff == DEBUG_INVALID_OFFSET)
  1611. {
  1612. Line++;
  1613. LineOff = LineMap[Line];
  1614. }
  1615. if (Expr != NULL)
  1616. {
  1617. sprintf(Expr, "0x%I64x", LineOff);
  1618. }
  1619. if (Offset != NULL)
  1620. {
  1621. *Offset = LineOff;
  1622. }
  1623. Succ = TRUE;
  1624. UnlockNoCode:
  1625. UnlockStateBuffer(this);
  1626. NoCode:
  1627. return Succ;
  1628. }
  1629. BOOL
  1630. DISASMWIN_DATA::OnCreate(void)
  1631. {
  1632. RECT Rect;
  1633. int i;
  1634. ULONG Height;
  1635. Height = GetSystemMetrics(SM_CYVSCROLL) + 4 * GetSystemMetrics(SM_CYEDGE);
  1636. m_Toolbar = CreateWindowEx(0, REBARCLASSNAME, NULL,
  1637. WS_VISIBLE | WS_CHILD |
  1638. WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
  1639. CCS_NODIVIDER | CCS_NOPARENTALIGN |
  1640. RBS_VARHEIGHT | RBS_BANDBORDERS,
  1641. 0, 0, m_Size.cx, Height, m_Win,
  1642. (HMENU)ID_TOOLBAR,
  1643. g_hInst, NULL);
  1644. if (m_Toolbar == NULL)
  1645. {
  1646. return FALSE;
  1647. }
  1648. REBARINFO BarInfo;
  1649. BarInfo.cbSize = sizeof(BarInfo);
  1650. BarInfo.fMask = 0;
  1651. BarInfo.himl = NULL;
  1652. SendMessage(m_Toolbar, RB_SETBARINFO, 0, (LPARAM)&BarInfo);
  1653. m_ToolbarEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", NULL,
  1654. WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL,
  1655. 0, 0, 18 * m_Font->Metrics.tmAveCharWidth,
  1656. Height, m_Toolbar, (HMENU)IDC_EDIT_OFFSET,
  1657. g_hInst, NULL);
  1658. if (m_ToolbarEdit == NULL)
  1659. {
  1660. return FALSE;
  1661. }
  1662. SendMessage(m_ToolbarEdit, WM_SETFONT, (WPARAM)m_Font->Font, 0);
  1663. SendMessage(m_ToolbarEdit, EM_LIMITTEXT, sizeof(m_OffsetExpr) - 1, 0);
  1664. GetClientRect(m_ToolbarEdit, &Rect);
  1665. REBARBANDINFO BandInfo;
  1666. BandInfo.cbSize = sizeof(BandInfo);
  1667. BandInfo.fMask = RBBIM_STYLE | RBBIM_TEXT | RBBIM_CHILD | RBBIM_CHILDSIZE;
  1668. BandInfo.fStyle = RBBS_FIXEDSIZE;
  1669. BandInfo.lpText = "Offset:";
  1670. BandInfo.hwndChild = m_ToolbarEdit;
  1671. BandInfo.cxMinChild = Rect.right - Rect.left;
  1672. BandInfo.cyMinChild = Rect.bottom - Rect.top;
  1673. SendMessage(m_Toolbar, RB_INSERTBAND, -1, (LPARAM)&BandInfo);
  1674. // If the toolbar is allowed to shrink too small it hangs
  1675. // while resizing. Just let it clip off below a certain width.
  1676. m_MinToolbarWidth = BandInfo.cxMinChild * 2;
  1677. PSTR PrevText = "Previous";
  1678. m_PreviousButton =
  1679. AddButtonBand(m_Toolbar, PrevText, PrevText, IDC_DISASM_PREVIOUS);
  1680. m_NextButton =
  1681. AddButtonBand(m_Toolbar, "Next", PrevText, IDC_DISASM_NEXT);
  1682. if (m_PreviousButton == NULL || m_NextButton == NULL)
  1683. {
  1684. return FALSE;
  1685. }
  1686. // Maximize the space for the offset expression.
  1687. SendMessage(m_Toolbar, RB_MAXIMIZEBAND, 0, FALSE);
  1688. GetClientRect(m_Toolbar, &Rect);
  1689. m_ToolbarHeight = Rect.bottom - Rect.top;
  1690. m_ShowToolbar = TRUE;
  1691. if (!EDITWIN_DATA::OnCreate())
  1692. {
  1693. return FALSE;
  1694. }
  1695. // Suppress the scroll bar as the text is always
  1696. // fitted to the window size.
  1697. SendMessage(m_hwndChild, EM_SHOWSCROLLBAR, SB_VERT, FALSE);
  1698. SendMessage(m_hwndChild, EM_SETEVENTMASK, 0, ENM_KEYEVENTS);
  1699. return TRUE;
  1700. }
  1701. LRESULT
  1702. DISASMWIN_DATA::OnCommand(WPARAM Wpm, LPARAM Lpm)
  1703. {
  1704. switch(LOWORD(Wpm))
  1705. {
  1706. case IDC_EDIT_OFFSET:
  1707. if (HIWORD(Wpm) == EN_CHANGE)
  1708. {
  1709. // This message is sent on every keystroke
  1710. // which causes a bit too much updating.
  1711. // Set up a timer to trigger the actual
  1712. // update in half a second.
  1713. SetTimer(m_Win, IDC_EDIT_OFFSET, EDIT_DELAY, NULL);
  1714. m_UpdateExpr = TRUE;
  1715. }
  1716. break;
  1717. case IDC_DISASM_PREVIOUS:
  1718. ScrollLower();
  1719. break;
  1720. case IDC_DISASM_NEXT:
  1721. ScrollHigher();
  1722. break;
  1723. }
  1724. return 0;
  1725. }
  1726. void
  1727. DISASMWIN_DATA::OnSize(void)
  1728. {
  1729. EDITWIN_DATA::OnSize();
  1730. // Force buffer to refill for new line count.
  1731. UiRequestRead();
  1732. }
  1733. void
  1734. DISASMWIN_DATA::OnTimer(WPARAM TimerId)
  1735. {
  1736. if (TimerId == IDC_EDIT_OFFSET && m_UpdateExpr)
  1737. {
  1738. m_UpdateExpr = FALSE;
  1739. GetWindowText(m_ToolbarEdit, m_OffsetExpr, sizeof(m_OffsetExpr));
  1740. UiRequestRead();
  1741. }
  1742. }
  1743. LRESULT
  1744. DISASMWIN_DATA::OnNotify(WPARAM Wpm, LPARAM Lpm)
  1745. {
  1746. MSGFILTER* Filter = (MSGFILTER*)Lpm;
  1747. if (Filter->nmhdr.code != EN_MSGFILTER)
  1748. {
  1749. return EDITWIN_DATA::OnNotify(Wpm, Lpm);
  1750. }
  1751. if (Filter->msg == WM_KEYDOWN)
  1752. {
  1753. switch(Filter->wParam)
  1754. {
  1755. case VK_UP:
  1756. {
  1757. CHARRANGE range;
  1758. SendMessage(m_hwndChild, EM_EXGETSEL, 0, (LPARAM) &range);
  1759. if (!SendMessage(m_hwndChild, EM_LINEFROMCHAR, range.cpMin, 0))
  1760. {
  1761. // up arrow on top line, scroll
  1762. ScrollLower();
  1763. return 1;
  1764. }
  1765. break;
  1766. }
  1767. case VK_DOWN:
  1768. {
  1769. CHARRANGE range;
  1770. int MaxLine;
  1771. SendMessage(m_hwndChild, EM_EXGETSEL, 0, (LPARAM) &range);
  1772. MaxLine = (int) SendMessage(m_hwndChild, EM_GETLINECOUNT, 0, 0);
  1773. if (MaxLine == (1+SendMessage(m_hwndChild, EM_LINEFROMCHAR, range.cpMin, 0)))
  1774. {
  1775. // down arrow on bottom line, scroll
  1776. ScrollHigher();
  1777. return 1;
  1778. }
  1779. break;
  1780. }
  1781. case VK_PRIOR:
  1782. ScrollLower();
  1783. return 1;
  1784. case VK_NEXT:
  1785. ScrollHigher();
  1786. return 1;
  1787. }
  1788. }
  1789. else if (WM_SYSKEYDOWN == Filter->msg ||
  1790. WM_SYSKEYUP == Filter->msg ||
  1791. WM_SYSCHAR == Filter->msg)
  1792. {
  1793. // Force default processing for menu operations
  1794. // so that the Alt-minus menu comes up.
  1795. return 1;
  1796. }
  1797. return 0;
  1798. }
  1799. void
  1800. DISASMWIN_DATA::OnUpdate(UpdateType Type)
  1801. {
  1802. if (Type == UPDATE_BP ||
  1803. Type == UPDATE_END_SESSION)
  1804. {
  1805. UpdateBpMarks();
  1806. return;
  1807. }
  1808. else if (Type != UPDATE_BUFFER)
  1809. {
  1810. return;
  1811. }
  1812. HRESULT Status;
  1813. Status = UiLockForRead();
  1814. if (Status == S_OK)
  1815. {
  1816. PULONG64 LineMap;
  1817. ULONG Line;
  1818. if (!g_LineMarkers)
  1819. {
  1820. SendMessage(m_hwndChild, WM_SETTEXT,
  1821. 0, (LPARAM)m_Data + m_TextOffset);
  1822. }
  1823. else
  1824. {
  1825. SendMessage(m_hwndChild, WM_SETTEXT, 0, (LPARAM)"");
  1826. PSTR Text = (PSTR)m_Data + m_TextOffset;
  1827. for (;;)
  1828. {
  1829. SendMessage(m_hwndChild, EM_REPLACESEL, FALSE, (LPARAM)" ");
  1830. PSTR NewLine = strchr(Text, '\n');
  1831. if (NewLine != NULL)
  1832. {
  1833. *NewLine = 0;
  1834. }
  1835. SendMessage(m_hwndChild, EM_REPLACESEL, FALSE, (LPARAM)Text);
  1836. if (NewLine == NULL)
  1837. {
  1838. break;
  1839. }
  1840. SendMessage(m_hwndChild, EM_REPLACESEL, FALSE, (LPARAM)"\n");
  1841. *NewLine = '\n';
  1842. Text = NewLine + 1;
  1843. }
  1844. }
  1845. // Highlight the last line of multiline disassembly.
  1846. LineMap = (PULONG64)m_Data;
  1847. Line = m_PrimaryLine;
  1848. while (Line + 1 < m_TextLines &&
  1849. LineMap[Line] == DEBUG_INVALID_OFFSET)
  1850. {
  1851. Line++;
  1852. }
  1853. SetCurrentLineHighlight(Line);
  1854. UnlockStateBuffer(this);
  1855. UpdateBpMarks();
  1856. EnableWindow(m_PreviousButton, m_FirstInstr != m_PrimaryInstr);
  1857. EnableWindow(m_NextButton, m_LastInstr != m_PrimaryInstr);
  1858. }
  1859. else
  1860. {
  1861. SendLockStatusMessage(m_hwndChild, WM_SETTEXT, Status);
  1862. RemoveCurrentLineHighlight();
  1863. }
  1864. }
  1865. void
  1866. DISASMWIN_DATA::UpdateBpMarks(void)
  1867. {
  1868. if (m_TextLines == 0 ||
  1869. UiLockForRead() != S_OK)
  1870. {
  1871. return;
  1872. }
  1873. if (g_BpBuffer->UiLockForRead() != S_OK)
  1874. {
  1875. UnlockStateBuffer(this);
  1876. return;
  1877. }
  1878. SendMessage(m_hwndChild, WM_SETREDRAW, FALSE, 0);
  1879. // Remove existing BP highlights.
  1880. RemoveAllHighlights(EHL_ANY_BP);
  1881. //
  1882. // Highlight every line that matches a breakpoint.
  1883. //
  1884. PULONG64 LineMap = (PULONG64)m_Data;
  1885. BpBufferData* BpData = (BpBufferData*)g_BpBuffer->GetDataBuffer();
  1886. ULONG Line;
  1887. BpStateType State;
  1888. for (Line = 0; Line < m_TextLines; Line++)
  1889. {
  1890. if (*LineMap != DEBUG_INVALID_OFFSET)
  1891. {
  1892. State = IsBpAtOffset(BpData, *LineMap, NULL);
  1893. if (State != BP_NONE)
  1894. {
  1895. AddHighlight(Line, State == BP_ENABLED ?
  1896. EHL_ENABLED_BP : EHL_DISABLED_BP);
  1897. }
  1898. }
  1899. LineMap++;
  1900. }
  1901. SendMessage(m_hwndChild, WM_SETREDRAW, TRUE, 0);
  1902. InvalidateRect(m_hwndChild, NULL, TRUE);
  1903. UnlockStateBuffer(g_BpBuffer);
  1904. UnlockStateBuffer(this);
  1905. }
  1906. void
  1907. DISASMWIN_DATA::SetCurInstr(ULONG64 Offset)
  1908. {
  1909. // Any pending user update is now irrelevant.
  1910. m_UpdateExpr = FALSE;
  1911. sprintf(m_OffsetExpr, "0x%I64x", Offset);
  1912. // Force engine to update buffer.
  1913. UiRequestRead();
  1914. }
  1915. void
  1916. RicheditFind(HWND Edit,
  1917. PTSTR Text, ULONG Flags,
  1918. CHARRANGE* SaveSel, PULONG SaveFlags,
  1919. BOOL HideSel)
  1920. {
  1921. if (Text == NULL)
  1922. {
  1923. // Clear last find.
  1924. if (SaveSel->cpMax >= SaveSel->cpMin)
  1925. {
  1926. if (*SaveFlags & FR_DOWN)
  1927. {
  1928. SaveSel->cpMin = SaveSel->cpMax;
  1929. }
  1930. else
  1931. {
  1932. SaveSel->cpMax = SaveSel->cpMin;
  1933. }
  1934. if (HideSel)
  1935. {
  1936. SendMessage(Edit, EM_SETOPTIONS, ECOOP_AND, ~ECO_NOHIDESEL);
  1937. }
  1938. SendMessage(Edit, EM_EXSETSEL, 0, (LPARAM)SaveSel);
  1939. SendMessage(Edit, EM_SCROLLCARET, 0, 0);
  1940. SaveSel->cpMin = 1;
  1941. SaveSel->cpMax = 0;
  1942. }
  1943. }
  1944. else
  1945. {
  1946. LRESULT Match;
  1947. FINDTEXTEX Find;
  1948. SendMessage(Edit, EM_EXGETSEL, 0, (LPARAM)&Find.chrg);
  1949. if (Flags & FR_DOWN)
  1950. {
  1951. Find.chrg.cpMax = LONG_MAX;
  1952. }
  1953. else
  1954. {
  1955. Find.chrg.cpMax = 0;
  1956. }
  1957. Find.lpstrText = Text;
  1958. Match = SendMessage(Edit, EM_FINDTEXTEX, Flags, (LPARAM)&Find);
  1959. if (Match != -1)
  1960. {
  1961. *SaveSel = Find.chrgText;
  1962. *SaveFlags = Flags;
  1963. if (HideSel)
  1964. {
  1965. SendMessage(Edit, EM_SETOPTIONS, ECOOP_OR, ECO_NOHIDESEL);
  1966. }
  1967. SendMessage(Edit, EM_EXSETSEL, 0, (LPARAM)SaveSel);
  1968. SendMessage(Edit, EM_SCROLLCARET, 0, 0);
  1969. }
  1970. else
  1971. {
  1972. InformationBox(ERR_No_More_Matches, Text);
  1973. SetFocus(g_FindDialog);
  1974. }
  1975. }
  1976. }
  1977. #undef DEFINE_GET_WINDATA
  1978. #undef ASSERT_CLASS_TYPE
  1979. #ifndef DBG
  1980. #define ASSERT_CLASS_TYPE(p, ct) ((VOID)0)
  1981. #else
  1982. #define ASSERT_CLASS_TYPE(p, ct) if (p) { AssertType(*p, ct); }
  1983. #endif
  1984. #define DEFINE_GET_WINDATA(ClassType, FuncName) \
  1985. ClassType * \
  1986. Get##FuncName##WinData( \
  1987. HWND hwnd \
  1988. ) \
  1989. { \
  1990. ClassType *p = (ClassType *) \
  1991. GetWindowLongPtr(hwnd, GWLP_USERDATA); \
  1992. \
  1993. ASSERT_CLASS_TYPE(p, ClassType); \
  1994. \
  1995. return p; \
  1996. }
  1997. #include "fncdefs.h"
  1998. #undef DEFINE_GET_WINDATA
  1999. #undef ASSERT_CLASS_TYPE