From cb17c3035bbd80bd8ea6718bae4c57cfb2555653 Mon Sep 17 00:00:00 2001 From: Joel Klinghed Date: Thu, 15 Jun 2017 23:20:00 +0200 Subject: Initial monitor GUI Basic monitor functionality, GTK-3.0 and QT5 backends --- src/gui_hexdump.cc | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 src/gui_hexdump.cc (limited to 'src/gui_hexdump.cc') diff --git a/src/gui_hexdump.cc b/src/gui_hexdump.cc new file mode 100644 index 0000000..fbda64d --- /dev/null +++ b/src/gui_hexdump.cc @@ -0,0 +1,136 @@ +// -*- mode: c++; c-basic-offset: 2; -*- + +#include "common.hh" + +#include + +#include "gui_attrtext.hh" +#include "gui_hexdump.hh" + +namespace { + +AttributedText::Attribute const addr(0x90, 0x90, 0x90); + +inline size_t append(char* out, size_t max, char const* in, size_t len) { + if (len <= max) { + memcpy(out, in, len); + return len; + } + return 0; +} + +inline size_t safe(char* out, size_t max, char const* in, size_t len) { + size_t ret = 0; + for (; len--; ++in) { + if (*in >= ' ' && *in < '\x7f') { + ret += append(out + ret, max - ret, in, 1); + continue; + } + switch (*in) { + case '\r': + ret += append(out + ret, max - ret, "\xe2\x86\xb5", 3); // U+21B5 + break; + case '\n': + ret += append(out + ret, max - ret, "\xc2\xb6", 2); // U+00B6 + break; + case '\x8': + ret += append(out + ret, max - ret, "\xe2\x8c\xab", 3); // U+232B + break; + case '\t': + ret += append(out + ret, max - ret, "\xe2\x86\xb9", 3); // U+21B9 + break; + default: + ret += append(out + ret, max - ret, "\xef\xbf\xbd", 3); // U+FFFD + break; + } + } + return ret; +} + +} // namespace + + +// static +void HexDump::write(AttributedText* text, uint8_t flags, std::string const& str, + size_t start, size_t length) { + if (start >= str.size()) return; + length = std::min(length, str.size() - start); + if (length == 0) return; + + AttributedText::Attribute box(0x90, 0x90, 0x90); + box.set_bold(true); + + size_t i = 0; + auto data = str.data() + start; + char tmp[80]; + char tmp2[64]; + int len; + while (i + 16 <= length) { + if (flags & ADDRESS) { + len = snprintf(tmp, sizeof(tmp), "%08lx ", static_cast(i)); + text->append(tmp, len, addr); + } + auto x = tmp2; + for (char c = 0; c < 2; ++c) { + len = snprintf(tmp, sizeof(tmp), "%02x %02x %02x %02x %02x %02x %02x %02x", + data[i], data[i + 1], data[i + 2], data[i + 3], data[i + 4], data[i + 5], data[i + 6], + data[i + 7]); + if (flags & CHARS) { + x += safe(x, sizeof(tmp2) - (x - tmp2), data + i, 8); + } + i += 8; + text->append(tmp, len); + if (c == 0) text->append(" ", 2); + } + if (flags & CHARS) { + text->append(" |", 3, box); + text->append(tmp2, x - tmp2); + text->append("|\n", 2, box); + } else { + text->append("\n", 1); + } + } + if (i < length) { + if (flags & ADDRESS) { + len = snprintf(tmp, sizeof(tmp), "%08lx ", static_cast(i)); + text->append(tmp, len, addr); + } + auto x = tmp2; + if (i + 8 <= length) { + len = snprintf(tmp, sizeof(tmp), "%02x %02x %02x %02x %02x %02x %02x %02x", + data[i], data[i + 1], data[i + 2], data[i + 3], data[i + 4], data[i + 5], data[i + 6], + data[i + 7]); + if (flags & CHARS) { + x += safe(x, sizeof(tmp2) - (x - tmp2), data + i, 8); + } + i += 8; + text->append(tmp, len); + text->append(" "); + } + for (; i < length; ++i) { + len = snprintf(tmp, sizeof(tmp), "%02x ", data[i]); + if (flags & CHARS) x += safe(x, sizeof(tmp2) - (x - tmp2), data + i, 1); + text->append(tmp, len); + } + if (flags & CHARS) { + auto extra = 16 - length % 16; + extra = extra * 3 + (extra > 8 ? 1 : 0); + memset(tmp, ' ', extra); + text->append(tmp, extra); + text->append(" |", 2, box); + text->append(tmp2, x - tmp2); + text->append("|\n", 2, box); + } else { + text->append("\n", 1); + } + if (flags & ADDRESS) { + len = snprintf(tmp, sizeof(tmp), "%08lx\n", static_cast(length)); + text->append(tmp, len, addr); + } + } +} + +// static +uint8_t const HexDump::ADDRESS = 1 << 0; +// static +uint8_t const HexDump::CHARS = 1 << 1; -- cgit v1.2.3-70-g09d2