From 081b62360e937fd44bd4d2518dee2543dc51fd2a Mon Sep 17 00:00:00 2001 From: blasty Date: Thu, 23 Jul 2026 22:52:54 +0200 Subject: fix: Tab decomp->listing reuses the nav entry so edits stay put The previous fix reopened the listing via _goto_ea(push=False), which made _cur a DETACHED entry (not _nav[-1]). Cursor moves update _nav[-1], so _cur.cursor went stale: after moving to a label and renaming it, _reload_active_code -> _open_entry(cur) restored the stale cursor and scrolled the just-renamed label off-screen. The rename actually applied (model showed the new name) but the view jumped away, so it looked like it "didn't propagate". Now Tab from a jumped-to pseudocode view converts the CURRENT entry (which is _nav[-1]) to a listing view in place (_toggle_to_listing): set view="listing", position at the current line's address, and reopen. Cursor moves keep updating the same entry, so a subsequent rename reloads at the cursor and the renamed label stays on screen. Verified: decomp jump -> Tab -> move to loc_ label -> rename: cursor stays on the label, which now shows the new name (00002040 ZZLABEL:) in the viewport. view_toggle/decomp_nav/decomp_follow_self/follow_xrefs/xref_labels/rename/ rename_history/disasm_nav/search/mouse/listing_view/continuous_view/func_banners/ scroll_restore 70/0. --- idatui/app.py | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'idatui') diff --git a/idatui/app.py b/idatui/app.py index e06d2c8..c4cae93 100644 --- a/idatui/app.py +++ b/idatui/app.py @@ -2611,17 +2611,37 @@ class IdaTui(App): self._active = "listing" self._open_entry(ret, push=False) elif self._cur is not None: - # No F5 snapshot (we arrived via a decomp navigation): open the - # listing at the current pseudocode line's address, as a real listing - # view — otherwise we'd show a stale widget with _cur.view still - # "decomp", and the next edit would bounce back to the decompiler. + # No F5 snapshot (we arrived via a decomp navigation): show THIS entry + # in the listing at the current pseudocode line's address. Reuse the + # entry (it is _nav[-1]) rather than spawning a detached one, so cursor + # moves keep updating it and a later edit reloads at the right spot. dec = self.query_one(DecompView) ea = dec._line_ea(dec.cursor) - self._goto_ea(ea if ea is not None else self._cur.ea, push=False) + self._toggle_to_listing(ea if ea is not None else self._cur.ea) else: self._active = "listing" self._show_active() + @work(thread=True, group="nav") + def _toggle_to_listing(self, ea: int) -> None: + assert self.program is not None + lm = self.program.listing(ea) + idx = max(lm.ensure_ea(ea), 0) if lm is not None else 0 + self.app.call_from_thread(self._apply_toggle_listing, idx) + + def _apply_toggle_listing(self, idx: int) -> None: + cur = self._cur + if cur is None: + self._active = "listing" + self._show_active() + return + cur.view = "listing" + cur.cursor = idx + cur.cursor_x = 0 + cur.scroll_y = -1 # derive a viewport (keeps the target in context) + self._active = "listing" + self._open_entry(cur, push=False) + @work(thread=True, group="nav") def _decomp_from_listing(self, ea: int) -> None: assert self.program is not None -- cgit v1.3.1-sl0p