ultimatepp/uppsrc/HexView/HexView.cpp
cxl 872d41c54d .cosmetics
git-svn-id: svn://ultimatepp.org/upp/trunk@13705 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2019-11-21 09:56:47 +00:00

510 lines
9.6 KiB
C++

#include "HexView.h"
namespace Upp {
inline int FormatHexDigit(int c) {
return c < 10 ? c + '0' : c - 10 + 'a';
}
void FormatHex(char *buffer, int64 number, int n) {
buffer[n] = '\0';
while(n) {
buffer[--n] = FormatHexDigit((byte)number & 0x0f);
number >>= 4;
}
}
void HexViewInfo::PrintValue(Draw& w, int x, int y, int bytes, bool be)
{
dword d = 0;
Size fsz = GetTextSize("X", font);
for(int i = 0; i < bytes; i++) {
int b = data[be ? i : bytes - i - 1];
if(b < 0) {
w.DrawText(x, y, String('?', 2 * bytes), font, SColorHighlight);
x += 2 * bytes * fsz.cx;
w.DrawText(x, y, "=", font);
x += fsz.cx;
w.DrawText(x, y, "?", font, Red);
return;
}
d = (d << 8) | (byte) b;
}
w.DrawText(x, y, FormatIntHex(d, 2 * bytes), font, SColorHighlight);
x += 2 * bytes * fsz.cx;
w.DrawText(x, y, "=", font);
x += fsz.cx;
String txt = FormatUnsigned(d);
w.DrawText(x, y, txt, font, Red);
x += GetTextSize(txt, font).cx;
w.DrawText(x, y, "=", font);
x += fsz.cx;
int q = d;
if(bytes == 1)
q = (int8) d;
else
if(bytes == 2)
q = (int16) d;
w.DrawText(x, y, FormatInt(q), font, Magenta);
}
void HexViewInfo::Paint(Draw& w)
{
Size sz = GetSize();
w.DrawRect(sz, SColorLtFace);
if(mode < 1 || empty)
return;
Size fsz = GetTextSize("X", font);
char h[17];
FormatHex(h, pos, longmode ? 16 : 8);
int xx = 0;
w.DrawText(xx, 0, h, font, SColorHighlight);
xx += (longmode ? 16 : 8) * fsz.cx;
w.DrawText(xx, 0, "=", font);
xx += fsz.cx;
w.DrawText(xx, 0, Format64(pos), font, Red);
xx += (longmode ? 22 : 12) * fsz.cx;
int y = 0;
int x;
for(int q = 0; q < mode; q++) {
x = xx;
if(q < 1)
PrintValue(w, x, y, 1, q);
x += 12 * fsz.cx;
PrintValue(w, x, y, 2, q);
x += 18 * fsz.cx;
PrintValue(w, x, y, 4, q);
x += 32 * fsz.cx;
y += fsz.cy;
}
char sh[80];
memset(sh, 0, sizeof(sh));
int i;
for(i = 0; i < 80; i++) {
if(data[i] < 0)
break;
sh[i] = data[i];
}
WString ws = FromUtf8(sh, i);
w.DrawText(x, 0, ws, font, Cyan, i);
if(mode < 2)
return;
wchar wh[40];
memset(wh, 0, sizeof(wh));
for(i = 0; i < 40; i++) {
if(data[2 * i] < 0 || data[2 * i + 1] < 0)
break;
wh[i] = MAKEWORD(data[2 * i], data[2 * i + 1]);
}
w.DrawText(x, fsz.cy, wh, font, Cyan, i);
String txt;
String ftxt;
i = 0;
for(;;) {
if(data[i] < 0) {
if((unsigned)i < sizeof(float))
ftxt = "?";
txt = "?";
break;
}
if((unsigned)i >= sizeof(double)) {
double h;
memcpy(&h, sh, sizeof(double));
txt = Sprintf("%.8g", h);
break;
}
if(i == sizeof(float)) {
float h;
memcpy(&h, sh, sizeof(float));
ftxt = Sprintf("%.6g", h);
}
sh[i] = data[i];
i++;
}
w.DrawText(0, fsz.cy, txt, font, Red);
w.DrawText(18 * fsz.cx, fsz.cy, ftxt, font, Red);
}
void HexViewInfo::SetMode(int _mode)
{
mode = _mode;
Height(mode * GetTextSize("X", CourierZ(12)).cy + 3);
Show(mode);
}
HexViewInfo::HexViewInfo()
{
SetMode(0);
AddFrame(TopSeparatorFrame());
AddFrame(RightSeparatorFrame());
font = CourierZ(12);
}
int HexView::Byte(int64 adr)
{
return 0;
}
void HexView::Paint(Draw& w)
{
Size sz = GetSize();
w.DrawRect(sz, SColorPaper);
if(!total) {
w.DrawText(Zx(10), Zx(10), "No data", ArialZ(20).Italic(), SRed());
return;
}
int y = 0;
uint64 adr = sc;
while(y < sz.cy) {
char h[17];
FormatHex(h, adr + start, IsLongMode() ? 16 : 8);
w.DrawText(0, y, h, font);
int x = (IsLongMode() ? 17 : 9) * fsz.cx;
int tx = x + columns * fcx3;
for(int q = columns; q--;) {
if(adr >= total)
return;
if(adr == cursor) {
w.DrawRect(x, y, fsz.cx * 2, fsz.cy, LtCyan);
w.DrawRect(tx, y, fsz.cx, fsz.cy, LtCyan);
}
int b = Byte(adr++);
if(b < 0) {
w.DrawText(x, y, "??", font, Brown);
w.DrawText(tx, y, "?", font, Brown);
}
else {
h[0] = FormatHexDigit((b & 0xf0) >> 4);
h[1] = FormatHexDigit(b & 0x0f);
h[2] = '\0';
w.DrawText(x, y, h, font, SColorText);
Color color = SColorMark;
switch(b) {
case '\a': *h = 'a'; break;
case '\b': *h = 'b'; break;
case '\t': *h = 't'; break;
case '\f': *h = 'f'; break;
case '\r': *h = 'r'; break;
case '\n': *h = 'n'; break;
case '\v': *h = 'v'; break;
case '\0': *h = '0'; break;
default:
if(b >= 32) {
*h = b;
color = SColorText;
}
else {
*h = '.';
color = SColorDisabled;
}
}
h[1] = '\0';
w.DrawText(tx, y, h, charset, font, color);
}
tx += fsz.cx;
x += fcx3;
}
y += fsz.cy;
}
}
void HexView::MouseWheel(Point, int zdelta, dword)
{
sb.Wheel(zdelta);
}
void HexView::SetSb()
{
sbm = 0;
uint64 sz = total;
while((sz >> sbm) > (1 << 30))
sbm++;
sb.SetTotal(int(sz >> sbm) / columns + 2);
sb.SetPage(int(rows >> sbm));
sb.Set(int(sc >> sbm) / columns + 1);
}
void HexView::Layout()
{
Size sz = GetSize();
columns = fixed ? fixed : max(4, (sz.cx - (IsLongMode() ? 18 : 10) * fsz.cx) / (4 * fsz.cx));
rows = max(1, sz.cy / fsz.cy);
bytes = columns * rows;
SetSb();
}
void HexView::SetStart(uint64 start_)
{
start = start_;
Layout();
SetSb();
Refresh();
RefreshInfo();
}
void HexView::SetTotal(uint64 _total)
{
total = _total;
Layout();
SetSb();
Refresh();
RefreshInfo();
}
void HexView::SetSc(uint64 address)
{
sc = minmax(address, start, total);
SetSb();
Refresh();
}
void HexView::Scroll()
{
int64 q = (int64)(int)sb << sbm;
if(q == 0)
sc = 0;
else
sc = (q - 1) * columns + sc % columns;
Refresh();
}
void HexView::RefreshInfo()
{
if(total) {
info.SetPos(cursor + start, IsLongMode());
for(int i = 0; i < 80; i++)
info.Set(i, Byte(cursor + i));
}
else
info.SetEmpty();
}
void HexView::SetCursor(uint64 _cursor)
{
cursor = _cursor;
if(cursor > total)
cursor = total - 1;
int q = int(sc % columns);
if(cursor >= sc + bytes)
sc = cursor - bytes + columns;
if(cursor < sc) {
sc = cursor;
}
if(sc > (uint64)q)
sc = (sc - q) / columns * columns + q;
if(sc >= total)
sc = total - 1;
SetSb();
Refresh();
RefreshInfo();
}
void HexView::LeftDown(Point p, dword)
{
int rowi = p.y / fsz.cy;
int x = (IsLongMode() ? 17 : 9) * fsz.cx;
int tx = x + columns * fcx3;
if(p.x >= x && p.x < tx) {
x = p.x - x;
int q = x / fcx3;
if(x - q * fcx3 < 2 * fsz.cx && q < columns) {
uint64 c = sc + rowi * columns + q;
if(c < total)
SetCursor(c);
}
}
else
if(p.x >= tx) {
int q = (p.x - tx) / fsz.cx;
if(q >= 0 && q < columns) {
uint64 c = sc + rowi * columns + q;
if(c < total)
SetCursor(c);
}
}
SetFocus();
}
bool HexView::Key(dword key, int)
{
int pg = max(columns, bytes - columns);
int q = int(sc % columns);
switch(key) {
case K_LEFT:
SetCursor(cursor - 1);
return true;
case K_RIGHT:
SetCursor(cursor + 1);
return true;
case K_UP:
SetCursor(cursor - columns);
return true;
case K_DOWN:
SetCursor(cursor + columns);
return true;
case K_PAGEUP:
SetSc(sc - pg);
SetCursor(cursor - pg);
return true;
case K_PAGEDOWN:
SetSc(sc + pg);
SetCursor(cursor + pg);
return true;
case K_CTRL_LEFT:
SetSc(sc - 1);
break;
case K_CTRL_RIGHT:
SetSc(sc + 1);
break;
case K_CTRL_UP:
SetSc(sc - columns);
break;
case K_CTRL_DOWN:
SetSc(sc + columns);
break;
case K_HOME:
SetCursor((cursor - q) / columns * columns + q);
break;
case K_END:
SetCursor((cursor - q) / columns * columns + q + columns - 1);
break;
case K_CTRL_HOME:
case K_CTRL_PAGEUP:
SetCursor(0);
break;
case K_CTRL_END:
case K_CTRL_PAGEDOWN:
SetCursor(total - 1);
break;
}
return MenuBar::Scan(WhenBar, key);
}
void HexView::SetColumns(int x)
{
FixedColumns(x);
}
void HexView::SetCharset(int chr)
{
Charset(chr);
}
void HexView::StdGoto(const String& s)
{
CParser p(s);
int n = 10;
if(p.Char2('0', 'x') || p.Char('$') || p.Char('#'))
n = 16;
if(p.IsNumber(n)) {
uint64 a = p.ReadNumber(n);
if(a < total) {
SetCursor(a);
SetSc(a);
return;
}
}
Exclamation("Invalid position!");
}
void HexView::Goto()
{
if(go.Execute() == IDOK)
WhenGoto((String)~go.text);
}
void HexView::ColumnsMenu(Bar& bar)
{
bar.Add("Auto", THISBACK1(SetColumns, 0))
.Radio(fixed == 0);
bar.Add("8", THISBACK1(SetColumns, 8))
.Radio(fixed == 8);
bar.Add("16", THISBACK1(SetColumns, 16))
.Radio(fixed == 16);
bar.Add("32", THISBACK1(SetColumns, 32))
.Radio(fixed == 32);
}
void HexView::SetInfo(int m)
{
info.SetMode(m);
}
void HexView::InfoMenu(Bar& bar)
{
bar.Add("None", THISBACK1(SetInfo, 0))
.Check(info.GetMode() == 0);
bar.Add("Standard", THISBACK1(SetInfo, 1))
.Check(info.GetMode() == 1);
bar.Add("Extended", THISBACK1(SetInfo, 2))
.Check(info.GetMode() == 2);
}
void HexView::CharsetMenu(Bar& bar)
{
for(int i = 1; i < CharsetCount(); i++)
bar.Add(CharsetName(i), THISBACK1(SetCharset, i))
.Radio(charset == i);
}
void HexView::StdMenu(Bar& bar)
{
bar.Add("Go to..", [=] { WhenGotoDlg(); })
.Key(K_CTRL_G);
bar.Add("Columns", THISBACK(ColumnsMenu));
bar.Add("Charset", THISBACK(CharsetMenu));
bar.Add("Position info", THISBACK(InfoMenu));
}
void HexView::RightDown(Point p, dword w)
{
LeftDown(p, w);
MenuBar::Execute(WhenBar);
}
HexView& HexView::SetFont(Font fnt)
{
font = fnt;
fsz = GetTextSize("X", font);
fcx3 = 3 * fsz.cx;
Layout();
Refresh();
SetSb();
return *this;
}
void HexView::SerializeSettings(Stream& s)
{
int version = 0;
s / version;
s / fixed;
s % charset;
int mode = info.GetMode();
s / mode;
info.SetMode(mode);
go.text.SerializeList(s);
}
HexView::HexView()
{
SetFont(CourierZ(12));
BackPaint();
charset = CHARSET_WIN1252;
sb <<= THISBACK(Scroll);
SetFrame(InsetFrame());
AddFrame(sb);
cursor = sc = 0;
total = 0;
fixed = 0;
SetSc(0);
SetCursor(0);
AddFrame(info);
info.SetMode(1);
WhenBar = THISBACK(StdMenu);
CtrlLayoutOKCancel(go, "Go to");
WhenGoto = THISBACK(StdGoto);
WhenGotoDlg = THISBACK(Goto);
}
}