Wxwidgets: Improve memory search and refactor text panel code
This commit is contained in:
parent
d1c8435fa2
commit
9dc12ae746
6 changed files with 366 additions and 188 deletions
|
@ -1,6 +1,7 @@
|
||||||
#ifndef _textrender__hpp__included__
|
#ifndef _textrender__hpp__included__
|
||||||
#define _textrender__hpp__included__
|
#define _textrender__hpp__included__
|
||||||
|
|
||||||
|
#include <wx/panel.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
@ -37,4 +38,25 @@ private:
|
||||||
size_t height;
|
size_t height;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct text_framebuffer_panel : public wxPanel, public text_framebuffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
text_framebuffer_panel(wxWindow* parent, size_t w, size_t h, wxWindowID id, wxWindow* redirect);
|
||||||
|
~text_framebuffer_panel();
|
||||||
|
void set_size(size_t _width, size_t _height);
|
||||||
|
void request_paint();
|
||||||
|
bool AcceptsFocus() { return (redirect != NULL); }
|
||||||
|
protected:
|
||||||
|
virtual void prepare_paint() = 0;
|
||||||
|
private:
|
||||||
|
void on_erase(wxEraseEvent& e);
|
||||||
|
void on_paint(wxPaintEvent& e);
|
||||||
|
void on_focus(wxFocusEvent& e);
|
||||||
|
bool paint_requested;
|
||||||
|
bool locked;
|
||||||
|
bool size_changed;
|
||||||
|
std::vector<char> buffer;
|
||||||
|
wxWindow* redirect;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9,22 +9,16 @@
|
||||||
class wxwin_status : public wxFrame
|
class wxwin_status : public wxFrame
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
class panel : public wxPanel
|
class panel : public text_framebuffer_panel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
panel(wxWindow* _parent, wxWindow* tfocus, unsigned lines);
|
panel(wxWindow* _parent, wxWindow* tfocus, unsigned lines);
|
||||||
bool AcceptsFocus () const;
|
|
||||||
void on_focus(wxFocusEvent& e);
|
|
||||||
void on_paint(wxPaintEvent& e);
|
|
||||||
void on_erase(wxEraseEvent& e);
|
|
||||||
bool dirty;
|
|
||||||
wxWindow* parent;
|
|
||||||
wxWindow* tfocuswin;
|
|
||||||
//-1: memory watch only, 0: Both, 1: Status only.
|
//-1: memory watch only, 0: Both, 1: Status only.
|
||||||
void set_watch_flag(int f) { watch_flag = f; }
|
void set_watch_flag(int f) { watch_flag = f; }
|
||||||
|
protected:
|
||||||
|
void prepare_paint();
|
||||||
private:
|
private:
|
||||||
text_framebuffer statusvars;
|
text_framebuffer fb;
|
||||||
text_framebuffer memorywatches;
|
|
||||||
int watch_flag;
|
int watch_flag;
|
||||||
size_t previous_size;
|
size_t previous_size;
|
||||||
};
|
};
|
||||||
|
|
|
@ -984,10 +984,7 @@ void wxwin_mainwindow::notify_resized() throw()
|
||||||
|
|
||||||
void wxwin_mainwindow::notify_update_status() throw()
|
void wxwin_mainwindow::notify_update_status() throw()
|
||||||
{
|
{
|
||||||
if(!spanel->dirty) {
|
spanel->request_paint();
|
||||||
spanel->dirty = true;
|
|
||||||
spanel->Refresh();
|
|
||||||
}
|
|
||||||
if(mwindow)
|
if(mwindow)
|
||||||
mwindow->notify_update();
|
mwindow->notify_update();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "library/string.hpp"
|
#include "library/string.hpp"
|
||||||
|
|
||||||
#include "platform/wxwidgets/platform.hpp"
|
#include "platform/wxwidgets/platform.hpp"
|
||||||
|
#include "platform/wxwidgets/textrender.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
@ -33,6 +34,17 @@ class wxwindow_memorysearch;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
void connect_events(wxScrollBar* s, wxObjectEventFunction fun, wxEvtHandler* obj)
|
||||||
|
{
|
||||||
|
s->Connect(wxEVT_SCROLL_THUMBTRACK, fun, NULL, obj);
|
||||||
|
s->Connect(wxEVT_SCROLL_PAGEDOWN, fun, NULL, obj);
|
||||||
|
s->Connect(wxEVT_SCROLL_PAGEUP, fun, NULL, obj);
|
||||||
|
s->Connect(wxEVT_SCROLL_LINEDOWN, fun, NULL, obj);
|
||||||
|
s->Connect(wxEVT_SCROLL_LINEUP, fun, NULL, obj);
|
||||||
|
s->Connect(wxEVT_SCROLL_TOP, fun, NULL, obj);
|
||||||
|
s->Connect(wxEVT_SCROLL_BOTTOM, fun, NULL, obj);
|
||||||
|
}
|
||||||
|
|
||||||
const char* watchchars = "bBwWdDqQ";
|
const char* watchchars = "bBwWdDqQ";
|
||||||
|
|
||||||
wxwindow_memorysearch* mwatch;
|
wxwindow_memorysearch* mwatch;
|
||||||
|
@ -251,29 +263,54 @@ void wxwindow_memorysearch_vmasel::on_cancel(wxCommandEvent& e)
|
||||||
class wxwindow_memorysearch : public wxFrame
|
class wxwindow_memorysearch : public wxFrame
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
class panel : public text_framebuffer_panel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
panel(wxwindow_memorysearch* parent);
|
||||||
|
void set_selection(uint64_t first, uint64_t last);
|
||||||
|
void get_selection(uint64_t& first, uint64_t& last);
|
||||||
|
protected:
|
||||||
|
void prepare_paint();
|
||||||
|
private:
|
||||||
|
wxwindow_memorysearch* parent;
|
||||||
|
uint64_t first_sel;
|
||||||
|
uint64_t last_sel;
|
||||||
|
};
|
||||||
wxwindow_memorysearch();
|
wxwindow_memorysearch();
|
||||||
~wxwindow_memorysearch();
|
~wxwindow_memorysearch();
|
||||||
bool ShouldPreventAppExit() const;
|
bool ShouldPreventAppExit() const;
|
||||||
void on_close(wxCloseEvent& e);
|
void on_close(wxCloseEvent& e);
|
||||||
void on_button_click(wxCommandEvent& e);
|
void on_button_click(wxCommandEvent& e);
|
||||||
void auto_update();
|
void auto_update();
|
||||||
|
void on_mousedrag(wxMouseEvent& e);
|
||||||
void on_mouse(wxMouseEvent& e);
|
void on_mouse(wxMouseEvent& e);
|
||||||
|
void on_scroll(wxScrollEvent& e);
|
||||||
bool update_queued;
|
bool update_queued;
|
||||||
private:
|
private:
|
||||||
|
friend class panel;
|
||||||
template<typename T> void valuesearch(bool diff);
|
template<typename T> void valuesearch(bool diff);
|
||||||
template<typename T> void valuesearch2(T value);
|
template<typename T> void valuesearch2(T value);
|
||||||
template<typename T> void valuesearch3(T value);
|
template<typename T> void valuesearch3(T value);
|
||||||
void update();
|
void update();
|
||||||
void on_mouse2();
|
void on_mouse0(wxMouseEvent& e, bool polarity);
|
||||||
|
void on_mousedrag();
|
||||||
|
void on_mouse2(wxMouseEvent& e);
|
||||||
memorysearch* msearch;
|
memorysearch* msearch;
|
||||||
wxStaticText* count;
|
wxStaticText* count;
|
||||||
wxTextCtrl* matches;
|
wxScrollBar* scroll;
|
||||||
|
panel* matches;
|
||||||
wxComboBox* type;
|
wxComboBox* type;
|
||||||
wxCheckBox* hexmode2;
|
wxCheckBox* hexmode2;
|
||||||
wxCheckBox* autoupdate;
|
wxCheckBox* autoupdate;
|
||||||
std::map<long, uint64_t> addresses;
|
std::map<uint64_t, uint64_t> addresses;
|
||||||
|
uint64_t act_line;
|
||||||
|
uint64_t drag_startline;
|
||||||
|
bool dragging;
|
||||||
|
int mpx, mpy;
|
||||||
unsigned typecode;
|
unsigned typecode;
|
||||||
bool hexmode;
|
bool hexmode;
|
||||||
|
bool toomany;
|
||||||
|
int scroll_delta;
|
||||||
std::set<std::string> vmas_enabled;
|
std::set<std::string> vmas_enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -318,21 +355,30 @@ wxwindow_memorysearch::wxwindow_memorysearch()
|
||||||
}
|
}
|
||||||
toplevel->Add(searches);
|
toplevel->Add(searches);
|
||||||
|
|
||||||
toplevel->Add(count = new wxStaticText(this, wxID_ANY, wxT("XXX candidates")), 0, wxGROW);
|
toplevel->Add(count = new wxStaticText(this, wxID_ANY, wxT("XXXXXX candidates")), 0, wxGROW);
|
||||||
toplevel->Add(matches = new wxTextCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(500, 300),
|
wxBoxSizer* matchesb = new wxBoxSizer(wxHORIZONTAL);
|
||||||
wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP | wxTE_NOHIDESEL), 1, wxGROW);
|
matchesb->Add(matches = new panel(this), 1, wxGROW);
|
||||||
|
matchesb->Add(scroll = new wxScrollBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSB_VERTICAL), 0,
|
||||||
|
wxGROW);
|
||||||
|
toplevel->Add(matchesb, 1, wxGROW);
|
||||||
|
|
||||||
|
scroll->SetScrollbar(0, 0, 0, 0);
|
||||||
|
|
||||||
for(auto i : get_regions())
|
for(auto i : get_regions())
|
||||||
if(!i.readonly && !i.iospace)
|
if(!i.readonly && !i.iospace)
|
||||||
vmas_enabled.insert(i.region_name);
|
vmas_enabled.insert(i.region_name);
|
||||||
|
|
||||||
//matches->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this);
|
dragging = false;
|
||||||
//matches->Connect(wxEVT_LEFT_UP, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this);
|
toomany = true;
|
||||||
//matches->Connect(wxEVT_MIDDLE_DOWN, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this);
|
matches->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this);
|
||||||
//matches->Connect(wxEVT_MIDDLE_UP, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this);
|
matches->Connect(wxEVT_LEFT_UP, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this);
|
||||||
|
matches->Connect(wxEVT_MIDDLE_DOWN, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this);
|
||||||
|
matches->Connect(wxEVT_MIDDLE_UP, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this);
|
||||||
matches->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this);
|
matches->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this);
|
||||||
matches->Connect(wxEVT_RIGHT_UP, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this);
|
matches->Connect(wxEVT_RIGHT_UP, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this);
|
||||||
//matches->Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this);
|
matches->Connect(wxEVT_MOTION, wxMouseEventHandler(wxwindow_memorysearch::on_mousedrag), NULL, this);
|
||||||
|
matches->Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this);
|
||||||
|
connect_events(scroll, wxScrollEventHandler(wxwindow_memorysearch::on_scroll), this);
|
||||||
|
|
||||||
toplevel->SetSizeHints(this);
|
toplevel->SetSizeHints(this);
|
||||||
Fit();
|
Fit();
|
||||||
|
@ -341,6 +387,115 @@ wxwindow_memorysearch::wxwindow_memorysearch()
|
||||||
hexmode = false;
|
hexmode = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxwindow_memorysearch::panel::panel(wxwindow_memorysearch* _parent)
|
||||||
|
: text_framebuffer_panel(_parent, 40, 25, wxID_ANY, NULL)
|
||||||
|
{
|
||||||
|
parent = _parent;
|
||||||
|
first_sel = 0;
|
||||||
|
last_sel = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxwindow_memorysearch::panel::prepare_paint()
|
||||||
|
{
|
||||||
|
uint64_t first = parent->scroll->GetThumbPosition();
|
||||||
|
auto ssize = get_characters();
|
||||||
|
uint64_t last = first + ssize.second;
|
||||||
|
std::vector<std::string> lines;
|
||||||
|
lines.reserve(ssize.second);
|
||||||
|
std::map<uint64_t, uint64_t> addrs;
|
||||||
|
auto* ms = parent->msearch;
|
||||||
|
uint64_t addr_count;
|
||||||
|
bool toomany = false;
|
||||||
|
auto _parent = parent;
|
||||||
|
runemufn([&toomany, &first, &last, ms, &lines, &addrs, &addr_count, _parent]() {
|
||||||
|
addr_count = ms->get_candidate_count();
|
||||||
|
if(last > addr_count) {
|
||||||
|
uint64_t delta = last - addr_count;
|
||||||
|
if(first > delta) {
|
||||||
|
first -= delta;
|
||||||
|
last -= delta;
|
||||||
|
} else {
|
||||||
|
last -= first;
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(addr_count <= CANDIDATE_LIMIT) {
|
||||||
|
std::list<uint64_t> addrs2 = ms->get_candidates();
|
||||||
|
long j = 0;
|
||||||
|
for(auto i : addrs2) {
|
||||||
|
std::string row = hexformat_address(i) + " ";
|
||||||
|
switch(_parent->typecode) {
|
||||||
|
case 0:
|
||||||
|
row += format_number_signed(memory_read_byte(i), _parent->hexmode);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
row += format_number_unsigned(memory_read_byte(i), _parent->hexmode);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
row += format_number_signed(memory_read_word(i), _parent->hexmode);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
row += format_number_unsigned(memory_read_word(i), _parent->hexmode);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
row += format_number_signed(memory_read_dword(i), _parent->hexmode);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
row += format_number_unsigned(memory_read_dword(i), _parent->hexmode);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
row += format_number_signed(memory_read_qword(i), _parent->hexmode);
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
row += format_number_unsigned(memory_read_qword(i), _parent->hexmode);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
if(j >= first && j < last)
|
||||||
|
lines.push_back(row);
|
||||||
|
addrs[j++] = i;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lines.push_back("Too many candidates to display");
|
||||||
|
toomany = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
std::swap(parent->addresses, addrs);
|
||||||
|
|
||||||
|
std::ostringstream x;
|
||||||
|
x << addr_count << " " << ((addr_count != 1) ? "candidates" : "candidate");
|
||||||
|
parent->count->SetLabel(towxstring(x.str()));
|
||||||
|
|
||||||
|
clear();
|
||||||
|
for(unsigned i = 0; i < lines.size(); i++) {
|
||||||
|
bool sel = (first + i) >= first_sel && (first + i) < last_sel;
|
||||||
|
write(lines[i], 0, 0, i, sel ? 0xFFFFFF : 0, sel ? 0 : 0xFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(last_sel > last)
|
||||||
|
last_sel = last;
|
||||||
|
if(first_sel > last)
|
||||||
|
first_sel = last;
|
||||||
|
|
||||||
|
parent->toomany = toomany;
|
||||||
|
if(!toomany && addr_count > ssize.second)
|
||||||
|
parent->scroll->SetScrollbar(first, ssize.second, addr_count, ssize.second);
|
||||||
|
else
|
||||||
|
parent->scroll->SetScrollbar(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxwindow_memorysearch::panel::set_selection(uint64_t first, uint64_t last)
|
||||||
|
{
|
||||||
|
first_sel = first;
|
||||||
|
last_sel = last;
|
||||||
|
request_paint();
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxwindow_memorysearch::panel::get_selection(uint64_t& first, uint64_t& last)
|
||||||
|
{
|
||||||
|
first = first_sel;
|
||||||
|
last = last_sel;
|
||||||
|
}
|
||||||
|
|
||||||
wxwindow_memorysearch::~wxwindow_memorysearch()
|
wxwindow_memorysearch::~wxwindow_memorysearch()
|
||||||
{
|
{
|
||||||
delete msearch;
|
delete msearch;
|
||||||
|
@ -352,19 +507,79 @@ bool wxwindow_memorysearch::ShouldPreventAppExit() const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxwindow_memorysearch::on_scroll(wxScrollEvent& e)
|
||||||
|
{
|
||||||
|
matches->request_paint();
|
||||||
|
}
|
||||||
|
|
||||||
void wxwindow_memorysearch::on_mouse(wxMouseEvent& e)
|
void wxwindow_memorysearch::on_mouse(wxMouseEvent& e)
|
||||||
{
|
{
|
||||||
if(e.RightUp() || (e.LeftUp() && e.ControlDown()))
|
if(e.RightUp() || (e.LeftUp() && e.ControlDown()))
|
||||||
on_mouse2();
|
on_mouse2(e);
|
||||||
|
else if(e.LeftDown())
|
||||||
|
on_mouse0(e, true);
|
||||||
|
else if(e.LeftUp())
|
||||||
|
on_mouse0(e, false);
|
||||||
|
|
||||||
|
int wrotate = e.GetWheelRotation();
|
||||||
|
int threshold = e.GetWheelDelta();
|
||||||
|
if(threshold)
|
||||||
|
scroll_delta += wrotate;
|
||||||
|
while(wrotate && threshold && scroll_delta <= -threshold) {
|
||||||
|
//Scroll down by line.
|
||||||
|
uint64_t first = scroll->GetThumbPosition();
|
||||||
|
if(addresses.count(first + matches->get_characters().second))
|
||||||
|
scroll->SetThumbPosition(first + 1);
|
||||||
|
scroll_delta += threshold;
|
||||||
|
}
|
||||||
|
while(wrotate && threshold && scroll_delta >= threshold) {
|
||||||
|
//Scroll up by line.
|
||||||
|
//Scroll down by line.
|
||||||
|
uint64_t first = scroll->GetThumbPosition();
|
||||||
|
if(first > 0 && addresses.count(first - 1))
|
||||||
|
scroll->SetThumbPosition(first - 1);
|
||||||
|
scroll_delta -= threshold;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxwindow_memorysearch::on_mouse2()
|
void wxwindow_memorysearch::on_mouse0(wxMouseEvent& e, bool polarity)
|
||||||
|
{
|
||||||
|
dragging = polarity && !toomany;
|
||||||
|
if(dragging) {
|
||||||
|
mpx = e.GetX();
|
||||||
|
mpy = e.GetY();
|
||||||
|
uint64_t first = scroll->GetThumbPosition();
|
||||||
|
drag_startline = first + e.GetY() / matches->get_cell().second;
|
||||||
|
} else if(mpx == e.GetX() && mpy == e.GetY()) {
|
||||||
|
matches->set_selection(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxwindow_memorysearch::on_mousedrag(wxMouseEvent& e)
|
||||||
|
{
|
||||||
|
if(!dragging)
|
||||||
|
return;
|
||||||
|
uint64_t first = scroll->GetThumbPosition();
|
||||||
|
uint64_t linenow = first + e.GetY() / matches->get_cell().second;
|
||||||
|
if(drag_startline < linenow)
|
||||||
|
matches->set_selection(drag_startline, linenow + 1);
|
||||||
|
else
|
||||||
|
matches->set_selection(linenow, drag_startline + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxwindow_memorysearch::on_mouse2(wxMouseEvent& e)
|
||||||
{
|
{
|
||||||
wxMenu menu;
|
wxMenu menu;
|
||||||
bool some_selected;
|
bool some_selected;
|
||||||
long start, end;
|
uint64_t start, end;
|
||||||
matches->GetSelection(&start, &end);
|
matches->get_selection(start, end);
|
||||||
some_selected = (start < end);
|
some_selected = (start < end);
|
||||||
|
if(!some_selected) {
|
||||||
|
uint64_t first = scroll->GetThumbPosition();
|
||||||
|
act_line = first + e.GetY() / matches->get_cell().second;
|
||||||
|
if(addresses.count(act_line))
|
||||||
|
some_selected = true;
|
||||||
|
}
|
||||||
menu.Append(wxID_ADD, wxT("Add watch..."))->Enable(some_selected);
|
menu.Append(wxID_ADD, wxT("Add watch..."))->Enable(some_selected);
|
||||||
menu.AppendSeparator();
|
menu.AppendSeparator();
|
||||||
menu.Append(wxID_DISQUALIFY, wxT("Disqualify"))->Enable(some_selected);
|
menu.Append(wxID_DISQUALIFY, wxT("Disqualify"))->Enable(some_selected);
|
||||||
|
@ -390,58 +605,7 @@ void wxwindow_memorysearch::auto_update()
|
||||||
|
|
||||||
void wxwindow_memorysearch::update()
|
void wxwindow_memorysearch::update()
|
||||||
{
|
{
|
||||||
std::string ret;
|
matches->request_paint();
|
||||||
uint64_t addr_count;
|
|
||||||
runemufn([this, &ret, &addr_count]() {
|
|
||||||
addr_count = this->msearch->get_candidate_count();
|
|
||||||
if(addr_count <= CANDIDATE_LIMIT) {
|
|
||||||
this->addresses.clear();
|
|
||||||
std::list<uint64_t> addrs = this->msearch->get_candidates();
|
|
||||||
long j = 0;
|
|
||||||
for(auto i : addrs) {
|
|
||||||
std::ostringstream row;
|
|
||||||
row << hexformat_address(i) << " ";
|
|
||||||
switch(this->typecode) {
|
|
||||||
case 0:
|
|
||||||
row << format_number_signed(memory_read_byte(i), this->hexmode);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
row << format_number_unsigned(memory_read_byte(i), this->hexmode);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
row << format_number_signed(memory_read_word(i), this->hexmode);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
row << format_number_unsigned(memory_read_word(i), this->hexmode);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
row << format_number_signed(memory_read_dword(i), this->hexmode);
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
row << format_number_unsigned(memory_read_dword(i), this->hexmode);
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
row << format_number_signed(memory_read_qword(i), this->hexmode);
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
row << format_number_unsigned(memory_read_qword(i), this->hexmode);
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
row << std::endl;
|
|
||||||
ret = ret + row.str();
|
|
||||||
this->addresses[j++] = i;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ret = "Too many candidates to display";
|
|
||||||
this->addresses.clear();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
std::ostringstream x;
|
|
||||||
x << addr_count << " " << ((addr_count != 1) ? "candidates" : "candidate");
|
|
||||||
count->SetLabel(towxstring(x.str()));
|
|
||||||
matches->SetValue(towxstring(ret));
|
|
||||||
Fit();
|
|
||||||
update_queued = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxwindow_memorysearch::on_button_click(wxCommandEvent& e)
|
void wxwindow_memorysearch::on_button_click(wxCommandEvent& e)
|
||||||
|
@ -463,19 +627,14 @@ void wxwindow_memorysearch::on_button_click(wxCommandEvent& e)
|
||||||
} else if(id == wxID_HEX_SELECT) {
|
} else if(id == wxID_HEX_SELECT) {
|
||||||
hexmode = hexmode2->GetValue();
|
hexmode = hexmode2->GetValue();
|
||||||
} else if(id == wxID_ADD) {
|
} else if(id == wxID_ADD) {
|
||||||
long start, end;
|
uint64_t start, end;
|
||||||
long startx, starty, endx, endy;
|
matches->get_selection(start, end);
|
||||||
matches->GetSelection(&start, &end);
|
if(start == end) {
|
||||||
if(start == end)
|
start = act_line;
|
||||||
return;
|
end = act_line + 1;
|
||||||
if(!matches->PositionToXY(start, &startx, &starty))
|
}
|
||||||
return;
|
|
||||||
if(!matches->PositionToXY(end, &endx, &endy))
|
|
||||||
return;
|
|
||||||
if(endx == 0 && endy != 0)
|
|
||||||
endy--;
|
|
||||||
char wch = watchchars[typecode];
|
char wch = watchchars[typecode];
|
||||||
for(long r = starty; r <= endy; r++) {
|
for(long r = start; r < end; r++) {
|
||||||
if(!addresses.count(r))
|
if(!addresses.count(r))
|
||||||
return;
|
return;
|
||||||
uint64_t addr = addresses[r];
|
uint64_t addr = addresses[r];
|
||||||
|
@ -489,25 +648,22 @@ void wxwindow_memorysearch::on_button_click(wxCommandEvent& e)
|
||||||
} catch(canceled_exception& e) {
|
} catch(canceled_exception& e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
matches->set_selection(0, 0);
|
||||||
} else if(id == wxID_DISQUALIFY) {
|
} else if(id == wxID_DISQUALIFY) {
|
||||||
long start, end;
|
uint64_t start, end;
|
||||||
long startx, starty, endx, endy;
|
matches->get_selection(start, end);
|
||||||
matches->GetSelection(&start, &end);
|
if(start == end) {
|
||||||
if(start == end)
|
start = act_line;
|
||||||
return;
|
end = act_line + 1;
|
||||||
if(!matches->PositionToXY(start, &startx, &starty))
|
}
|
||||||
return;
|
for(long r = start; r < end; r++) {
|
||||||
if(!matches->PositionToXY(end, &endx, &endy))
|
|
||||||
return;
|
|
||||||
if(endx == 0 && endy != 0)
|
|
||||||
endy--;
|
|
||||||
for(long r = starty; r <= endy; r++) {
|
|
||||||
if(!addresses.count(r))
|
if(!addresses.count(r))
|
||||||
return;
|
return;
|
||||||
uint64_t addr = addresses[r];
|
uint64_t addr = addresses[r];
|
||||||
auto ms = msearch;
|
auto ms = msearch;
|
||||||
runemufn([addr, ms]() { ms->dq_range(addr, addr); });
|
runemufn([addr, ms]() { ms->dq_range(addr, addr); });
|
||||||
}
|
}
|
||||||
|
matches->set_selection(0, 0);
|
||||||
} else if(id == wxID_SET_REGIONS) {
|
} else if(id == wxID_SET_REGIONS) {
|
||||||
wxwindow_memorysearch_vmasel* d = new wxwindow_memorysearch_vmasel(this, vmas_enabled);
|
wxwindow_memorysearch_vmasel* d = new wxwindow_memorysearch_vmasel(this, vmas_enabled);
|
||||||
if(d->ShowModal() == wxID_OK)
|
if(d->ShowModal() == wxID_OK)
|
||||||
|
|
|
@ -21,35 +21,9 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
wxwin_status::panel::panel(wxWindow* _parent, wxWindow* focuswin, unsigned lines)
|
wxwin_status::panel::panel(wxWindow* _parent, wxWindow* focuswin, unsigned lines)
|
||||||
: wxPanel(_parent)
|
: text_framebuffer_panel(_parent, STATWIDTH, lines ? lines : MAXSTATUS, wxID_ANY, focuswin)
|
||||||
{
|
{
|
||||||
tfocuswin = focuswin;
|
|
||||||
parent = _parent;
|
|
||||||
dirty = false;
|
|
||||||
statusvars.set_size(STATWIDTH, lines ? lines : MAXSTATUS);
|
|
||||||
auto s = statusvars.get_pixels();
|
|
||||||
SetMinSize(wxSize(s.first, s.second));
|
|
||||||
this->Connect(wxEVT_PAINT, wxPaintEventHandler(wxwin_status::panel::on_paint), NULL, this);
|
|
||||||
this->Connect(wxEVT_ERASE_BACKGROUND, wxEraseEventHandler(panel::on_erase), NULL, this);
|
|
||||||
this->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(wxwin_status::panel::on_focus), NULL, this);
|
|
||||||
watch_flag = 0;
|
watch_flag = 0;
|
||||||
previous_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void wxwin_status::panel::on_erase(wxEraseEvent& e)
|
|
||||||
{
|
|
||||||
//Blank.
|
|
||||||
}
|
|
||||||
|
|
||||||
bool wxwin_status::panel::AcceptsFocus () const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void wxwin_status::panel::on_focus(wxFocusEvent& e)
|
|
||||||
{
|
|
||||||
if(tfocuswin)
|
|
||||||
tfocuswin->SetFocus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wxwin_status::wxwin_status(int flag, const std::string& title)
|
wxwin_status::wxwin_status(int flag, const std::string& title)
|
||||||
|
@ -68,7 +42,7 @@ wxwin_status::~wxwin_status()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxwin_status::panel::on_paint(wxPaintEvent& e)
|
void wxwin_status::panel::prepare_paint()
|
||||||
{
|
{
|
||||||
//Quickly copy the status area.
|
//Quickly copy the status area.
|
||||||
auto& s = platform::get_emustatus();
|
auto& s = platform::get_emustatus();
|
||||||
|
@ -77,10 +51,8 @@ void wxwin_status::panel::on_paint(wxPaintEvent& e)
|
||||||
while(s.next(i))
|
while(s.next(i))
|
||||||
newstatus[i.key] = i.value;
|
newstatus[i.key] = i.value;
|
||||||
|
|
||||||
memorywatches.clear();
|
clear();
|
||||||
statusvars.clear();
|
|
||||||
|
|
||||||
int y = 0;
|
|
||||||
size_t mem_width = 0;
|
size_t mem_width = 0;
|
||||||
size_t oth_width = 0;
|
size_t oth_width = 0;
|
||||||
size_t mem_count = 0;
|
size_t mem_count = 0;
|
||||||
|
@ -104,75 +76,39 @@ void wxwin_status::panel::on_paint(wxPaintEvent& e)
|
||||||
single = true;
|
single = true;
|
||||||
|
|
||||||
regex_results r;
|
regex_results r;
|
||||||
|
size_t p = 0;
|
||||||
if(mem_count) {
|
if(mem_count) {
|
||||||
size_t p = single ? 0 : 1;
|
|
||||||
memorywatches.set_size(STATWIDTH, mem_count + p);
|
|
||||||
if(!single)
|
if(!single)
|
||||||
memorywatches.write("Memory watches:", 0, 0, 0, 0, 0xFFFFFF);
|
write("Memory watches:", 0, 0, p++, 0, 0xFFFFFF);
|
||||||
for(auto i : newstatus) {
|
for(auto i : newstatus) {
|
||||||
if(r = regex("M\\[(.*)\\]", i.first)) {
|
if(r = regex("M\\[(.*)\\]", i.first)) {
|
||||||
size_t n = memorywatches.write(r[1], mem_width + 1, 0, p, 0, 0xFFFFFF);
|
size_t n = write(r[1], mem_width + 1, 0, p, 0, 0xFFFFFF);
|
||||||
memorywatches.write(i.second, 0, n, p, 0, 0xFFFFFF);
|
write(i.second, 0, n, p++, 0, 0xFFFFFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(mem_count && oth_count) {
|
||||||
|
auto s = get_characters();
|
||||||
|
for(unsigned i = 0; i < s.first; i++)
|
||||||
|
write(U"\u2500", 0, i, p, 0, 0xFFFFFF);
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(oth_count) {
|
if(oth_count) {
|
||||||
size_t p = single ? 0 : 1;
|
|
||||||
statusvars.set_size(STATWIDTH, oth_count + p);
|
|
||||||
if(!single)
|
if(!single)
|
||||||
statusvars.write("Status:", 0, 0, 0, 0, 0xFFFFFF);
|
write("Status:", 0, 0, p++, 0, 0xFFFFFF);
|
||||||
for(auto i : newstatus) {
|
for(auto i : newstatus) {
|
||||||
if(regex_match("M\\[.*\\]", i.first))
|
if(regex_match("M\\[.*\\]", i.first))
|
||||||
continue;
|
continue;
|
||||||
size_t n = statusvars.write(i.first, oth_width + 1, 0, p, 0, 0xFFFFFF);
|
size_t n = write(i.first, oth_width + 1, 0, p, 0, 0xFFFFFF);
|
||||||
statusvars.write(i.second, 0, n, p, 0, 0xFFFFFF);
|
write(i.second, 0, n, p++, 0, 0xFFFFFF);
|
||||||
p++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ssize = statusvars.get_pixels();
|
|
||||||
auto msize = memorywatches.get_pixels();
|
|
||||||
size_t y2 = ssize.second + (!single ? 3 : 0);
|
|
||||||
size_t yl = ssize.second + 1;
|
|
||||||
std::vector<char> buffer1, buffer2;
|
|
||||||
buffer1.resize(msize.first * msize.second * 3);
|
|
||||||
buffer2.resize(ssize.first * ssize.second * 3);
|
|
||||||
|
|
||||||
wxPaintDC dc(this);
|
|
||||||
if(oth_count) {
|
|
||||||
statusvars.render(&buffer2[0]);
|
|
||||||
wxBitmap bmp2(wxImage(ssize.first, ssize.second, reinterpret_cast<unsigned char*>(&buffer2[0]),
|
|
||||||
true));
|
|
||||||
dc.DrawBitmap(bmp2, 0, 0, false);
|
|
||||||
}
|
|
||||||
if(!single) {
|
|
||||||
dc.SetPen(*wxBLACK_PEN);
|
|
||||||
dc.DrawLine(0, yl, msize.first, yl);
|
|
||||||
}
|
|
||||||
if(mem_count) {
|
|
||||||
memorywatches.render(&buffer1[0]);
|
|
||||||
wxBitmap bmp1(wxImage(msize.first, msize.second, reinterpret_cast<unsigned char*>(&buffer1[0]),
|
|
||||||
true));
|
|
||||||
dc.DrawBitmap(bmp1, 0, y2, false);
|
|
||||||
}
|
|
||||||
auto psize = GetSize();
|
|
||||||
dc.SetPen(*wxWHITE_PEN);
|
|
||||||
dc.SetBrush(*wxWHITE_BRUSH);
|
|
||||||
size_t minsize = max(static_cast<size_t>(psize.y), previous_size);
|
|
||||||
size_t maxuse = y2 + 16 * (mem_count + (!single ? 1 : 0));
|
|
||||||
dc.DrawRectangle(0, maxuse, psize.x, minsize);
|
|
||||||
previous_size = maxuse;
|
|
||||||
dirty = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxwin_status::notify_update() throw()
|
void wxwin_status::notify_update() throw()
|
||||||
{
|
{
|
||||||
if(spanel->dirty)
|
spanel->request_paint();
|
||||||
return;
|
|
||||||
spanel->dirty = true;
|
|
||||||
spanel->Refresh();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxwin_status::ShouldPreventAppExit() const
|
bool wxwin_status::ShouldPreventAppExit() const
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "platform/wxwidgets/textrender.hpp"
|
#include "platform/wxwidgets/textrender.hpp"
|
||||||
#include "fonts/wrapper.hpp"
|
#include "fonts/wrapper.hpp"
|
||||||
#include "library/utf8.hpp"
|
#include "library/utf8.hpp"
|
||||||
|
#include <wx/dc.h>
|
||||||
|
#include <wx/dcclient.h>
|
||||||
|
|
||||||
extern const uint32_t text_framebuffer::element::white = 0xFFFFFF;
|
extern const uint32_t text_framebuffer::element::white = 0xFFFFFF;
|
||||||
extern const uint32_t text_framebuffer::element::black = 0x000000;
|
extern const uint32_t text_framebuffer::element::black = 0x000000;
|
||||||
|
@ -141,6 +143,8 @@ size_t text_framebuffer::write(const std::string& str, size_t w, size_t x, size_
|
||||||
|
|
||||||
size_t text_framebuffer::write(const std::u32string& str, size_t w, size_t x, size_t y, uint32_t fg, uint32_t bg)
|
size_t text_framebuffer::write(const std::u32string& str, size_t w, size_t x, size_t y, uint32_t fg, uint32_t bg)
|
||||||
{
|
{
|
||||||
|
if(y >= height)
|
||||||
|
return 0;
|
||||||
size_t spos = 0;
|
size_t spos = 0;
|
||||||
size_t slen = str.length();
|
size_t slen = str.length();
|
||||||
size_t pused = 0;
|
size_t pused = 0;
|
||||||
|
@ -170,3 +174,72 @@ size_t text_framebuffer::write(const std::u32string& str, size_t w, size_t x, si
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
text_framebuffer_panel::text_framebuffer_panel(wxWindow* parent, size_t w, size_t h, wxWindowID id,
|
||||||
|
wxWindow* _redirect)
|
||||||
|
: wxPanel(parent, id), text_framebuffer(w, h)
|
||||||
|
{
|
||||||
|
redirect = _redirect;
|
||||||
|
auto psize = get_pixels();
|
||||||
|
SetMinSize(wxSize(psize.first, psize.second));
|
||||||
|
this->Connect(wxEVT_PAINT, wxPaintEventHandler(text_framebuffer_panel::on_paint), NULL, this);
|
||||||
|
this->Connect(wxEVT_ERASE_BACKGROUND, wxEraseEventHandler(text_framebuffer_panel::on_erase), NULL, this);
|
||||||
|
this->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(text_framebuffer_panel::on_focus), NULL, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
text_framebuffer_panel::~text_framebuffer_panel()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void text_framebuffer_panel::set_size(size_t _width, size_t _height)
|
||||||
|
{
|
||||||
|
text_framebuffer::set_size(_width, _height);
|
||||||
|
auto psize = get_pixels();
|
||||||
|
buffer.resize(psize.first * psize.second * 3);
|
||||||
|
if(!locked) {
|
||||||
|
SetMinSize(wxSize(psize.first, psize.second));
|
||||||
|
} else
|
||||||
|
size_changed = true;
|
||||||
|
request_paint();
|
||||||
|
}
|
||||||
|
|
||||||
|
void text_framebuffer_panel::request_paint()
|
||||||
|
{
|
||||||
|
if(size_changed) {
|
||||||
|
auto psize = get_pixels();
|
||||||
|
SetMinSize(wxSize(psize.first, psize.second));
|
||||||
|
size_changed = false;
|
||||||
|
paint_requested = true;
|
||||||
|
Refresh();
|
||||||
|
} else if(!paint_requested) {
|
||||||
|
paint_requested = true;
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void text_framebuffer_panel::on_erase(wxEraseEvent& e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void text_framebuffer_panel::on_paint(wxPaintEvent& e)
|
||||||
|
{
|
||||||
|
locked = true;
|
||||||
|
auto size = GetSize();
|
||||||
|
text_framebuffer::set_size((size.x + 7) / 8, (size.y + 15) / 16);
|
||||||
|
auto psize = get_pixels();
|
||||||
|
buffer.resize(psize.first * psize.second * 3);
|
||||||
|
prepare_paint();
|
||||||
|
locked = false;
|
||||||
|
psize = get_pixels();
|
||||||
|
wxPaintDC dc(this);
|
||||||
|
render(&buffer[0]);
|
||||||
|
wxBitmap bmp1(wxImage(psize.first, psize.second, reinterpret_cast<unsigned char*>(&buffer[0]),
|
||||||
|
true));
|
||||||
|
dc.DrawBitmap(bmp1, 0, 0, false);
|
||||||
|
paint_requested = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void text_framebuffer_panel::on_focus(wxFocusEvent& e)
|
||||||
|
{
|
||||||
|
if(redirect)
|
||||||
|
redirect->SetFocus();
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue