diff options
author | Gerald Combs <gerald@wireshark.org> | 2012-10-30 19:21:24 +0000 |
---|---|---|
committer | Gerald Combs <gerald@wireshark.org> | 2012-10-30 19:21:24 +0000 |
commit | 0a28fb8f6a354aa9a446b6bf70733c305534e074 (patch) | |
tree | a075f90a96240ec13bbb5b15135e4f81cb9c75f3 /ui/qt/byte_view_text.cpp | |
parent | 27b5d556cb53bee24e20a9bb5862189ee2e55a61 (diff) | |
download | wireshark-0a28fb8f6a354aa9a446b6bf70733c305534e074.tar.gz |
Update the Qt byte view widget to reflect the recent changes in the GTK+
byte view.
Move the packet_char_enc enum from packet.h to frame_data.h. Make the
encoding flag a packet_char_enc and make it one bit.
Get rid of the "cfile" global in a few places. C++-ize some of the font
code. Clean up some variable names.
svn path=/trunk/; revision=45838
Diffstat (limited to 'ui/qt/byte_view_text.cpp')
-rw-r--r-- | ui/qt/byte_view_text.cpp | 838 |
1 files changed, 297 insertions, 541 deletions
diff --git a/ui/qt/byte_view_text.cpp b/ui/qt/byte_view_text.cpp index ba814e0966..fca655ed47 100644 --- a/ui/qt/byte_view_text.cpp +++ b/ui/qt/byte_view_text.cpp @@ -21,11 +21,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "monospace_font.h" #include "byte_view_text.h" #include <epan/charsets.h> +#include "wireshark_application.h" #include <QTextCursor> #include <QApplication> #include <QMouseEvent> @@ -33,579 +33,334 @@ // XXX - Use KHexEdit instead? // http://api.kde.org/4.x-api/kdelibs-apidocs/interfaces/khexedit/html/index.html -ByteViewText::ByteViewText(QWidget *parent, tvbuff_t *tvb, proto_tree *tree, QTreeWidget *protoTree, unsigned int encoding) : - QTextEdit(parent) +ByteViewText::ByteViewText(QWidget *parent, tvbuff_t *tvb, proto_tree *tree, QTreeWidget *tree_widget, packet_char_enc encoding) : + QTextEdit(parent), + tvb_(tvb), + proto_tree_(tree), + tree_widget_(tree_widget), + max_width_(0), + bold_highlight_(false), + encoding_(encoding), + format_(BYTES_HEX), + per_line_(16), + offset_width_(4) { setReadOnly(true); setLineWrapMode(QTextEdit::NoWrap); - setCurrentFont(get_monospace_font()); + setState(StateNormal); +} - m_tvb = tvb; - m_tree = tree; - m_protoTree = protoTree; - m_encoding = encoding; - m_start = m_len = 0; +void ByteViewText::setEncoding(packet_char_enc encoding) +{ + encoding_ = encoding; +} -// m_background = textBackgroundColor(); -// m_foreground = textColor(); +bool ByteViewText::hasDataSource(tvbuff_t *ds_tvb) { + if (ds_tvb != NULL && ds_tvb == tvb_) + return true; + return false; +} -// g_log(NULL, G_LOG_LEVEL_DEBUG, "fg %d %d %d bg %d %d %d", -// m_foreground.red(), m_foreground.green(), m_foreground.blue(), -// m_background.red(), m_background.green(), m_background.blue() -// ); +void ByteViewText::setProtocolHighlight(int start, int end) +{ + p_start_ = start; + p_end_ = end; +} - hexPrintCommon(); +void ByteViewText::setFieldHighlight(int start, int end, guint32 mask, int mask_le) +{ + Q_UNUSED(mask); + Q_UNUSED(mask_le); + f_start_ = start; + f_end_ = end; } -#define MAX_OFFSET_LEN 8 /* max length of hex offset of bytes */ -#define BYTES_PER_LINE 16 /* max byte values in a line */ -#define BITS_PER_LINE 8 /* max bit values in a line */ +void ByteViewText::setFieldAppendixHighlight(int start, int end) +{ + fa_start_ = start; + fa_end_ = end; +} + +void ByteViewText::render() +{ + int length; + + if (!tvb_) { + clear(); + return; + } + + setUpdatesEnabled(false); + clear(); + + length = tvb_length(tvb_); + for (int off = 0; off < length; off += per_line_) { + lineCommon(off); + } + + if (f_start_ != -1 && f_end_ != -1) { + scrollToByte(f_start_); + } else if (p_start_ != -1 && p_end_ != -1) { + scrollToByte(p_start_); + } + + setUpdatesEnabled(true); +} + +// Private + #define BYTE_VIEW_SEP 8 /* insert a space every BYTE_VIEW_SEP bytes */ -#define HEX_DUMP_LEN (BYTES_PER_LINE*3 + 1) -/* max number of characters hex dump takes - - 2 digits plus trailing blank - plus separator between first and - second 8 digits */ -#define DATA_DUMP_LEN (HEX_DUMP_LEN + 2 + BYTES_PER_LINE) -/* number of characters those bytes take; - 3 characters per byte of hex dump, - 2 blanks separating hex from ASCII, - 1 character per byte of ASCII dump */ -#define MAX_LINE_LEN (MAX_OFFSET_LEN + 2 + DATA_DUMP_LEN) -/* number of characters per line; - offset, 2 blanks separating offset - from data dump, data dump */ -#define MAX_LINES 100 -#define MAX_LINES_LEN (MAX_LINES*MAX_LINE_LEN) - -// Copied from packet_hex_print_common -void -ByteViewText::hexPrintCommon() + +void ByteViewText::lineCommon(const int org_off) { - int i = 0, j, k = 0, len; - const guint8 *pd; - QString line; - static guchar hexchars[16] = { + static const guchar hexchars[16] = { '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; -// static const guint8 bitmask[8] = { -// 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; - guchar c = '\0'; - -// progdlg_t *progbar = NULL; -// float progbar_val; -// gboolean progbar_stop_flag; -// GTimeVal progbar_start_time; -// gchar progbar_status_str[100]; -// int progbar_nextstep; -// int progbar_quantum; - - setPlainText(""); - // Replaces get_byte_view_data_and_length(). - if (!m_tvb) + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + + const guint8 *pd; + int len; + + highlight_state state; + + QString str; + + int off; + guchar c; + int byten; + int j; + + g_assert(org_off >= 0); + + if (!tvb_) return; - len = tvb_length(m_tvb); - pd = tvb_get_ptr(m_tvb, 0, -1); - - /* - * How many of the leading digits of the offset will we supply? - * We always supply at least 4 digits, but if the maximum offset - * won't fit in 4 digits, we use as many digits as will be needed. - */ - if (((len - 1) & 0xF0000000) != 0) - m_useDigits = 8; /* need all 8 digits */ - else if (((len - 1) & 0x0F000000) != 0) - m_useDigits = 7; /* need 7 digits */ - else if (((len - 1) & 0x00F00000) != 0) - m_useDigits = 6; /* need 6 digits */ - else if (((len - 1) & 0x000F0000) != 0) - m_useDigits = 5; /* need 5 digits */ - else - m_useDigits = 4; /* we'll supply 4 digits */ - - /* Update the progress bar when it gets to this value. */ -// if (len > MIN_PACKET_LENGTH){ -// progbar_nextstep = 0; -// }else{ -// /* If length =< MIN_PACKET_LENGTH -// * there is no need to calculate the progress -// */ -// progbar_nextstep = len+1; -// } - -// /* When we reach the value that triggers a progress bar update, -// bump that value by this amount. */ -// progbar_quantum = len/N_PROGBAR_UPDATES; -// /* Progress so far. */ -// progbar_val = 0.0f; - -// progbar_stop_flag = FALSE; -// g_get_current_time(&progbar_start_time); - - while (i < len) { - /* Create the progress bar if necessary. - We check on every iteration of the loop, so that it takes no - longer than the standard time to create it (otherwise, for a - large packet, we might take considerably longer than that standard - time in order to get to the next progress bar step). */ -// if ((progbar == NULL) && (len > MIN_PACKET_LENGTH)) -// progbar = delayed_create_progress_dlg("Processing", "Packet Details", -// TRUE, -// &progbar_stop_flag, -// &progbar_start_time, -// progbar_val); - - /* Update the progress bar, but do it only N_PROGBAR_UPDATES times; - when we update it, we have to run the GTK+ main loop to get it - to repaint what's pending, and doing so may involve an "ioctl()" - to see if there's any pending input from an X server, and doing - that for every packet can be costly, especially on a big file. */ -// if (i >= progbar_nextstep) { - -// if (progbar != NULL) { -// /* let's not divide by zero. I should never be started -// * with count == 0, so let's assert that -// */ -// g_assert(len > 0); -// progbar_val = (gfloat) i / len; -// g_snprintf(progbar_status_str, sizeof(progbar_status_str), -// "%4u of %u bytes", i, len); -// update_progress_dlg(progbar, progbar_val, progbar_status_str); -// } - -// progbar_nextstep += progbar_quantum; -// } - -// if (progbar_stop_flag) { -// /* Well, the user decided to abort the operation. Just stop, -// and arrange to return TRUE to our caller, so they know it -// was stopped explicitly. */ -// break; -// } - - /* Print the line number */ - j = m_useDigits; - do { - j--; - c = (i >> (j*4)) & 0xF; - line += hexchars[c]; - } while (j != 0); - line += " "; - - j = i; -// switch (recent.gui_bytes_view) { -// case BYTES_HEX: - k = i + BYTES_PER_LINE; -// break; -// case BYTES_BITS: -// k = i + BITS_PER_LINE; -// break; -// default: -// g_assert_not_reached(); -// } - /* Print the hex bit */ - while (i < k) { - if (i < len) { -// switch (recent.gui_bytes_view) { -// case BYTES_HEX: - line += hexchars[(pd[i] & 0xf0) >> 4]; - line += hexchars[pd[i] & 0x0f]; -// break; -// case BYTES_BITS: -// for (b = 0; b < 8; b++) { -// line += (pd[i] & bitmask[b]) ? '1' : '0'; -// } -// break; -// default: -// g_assert_not_reached(); -// } - } else { -// switch (recent.gui_bytes_view) { -// case BYTES_HEX: - line += " "; -// break; -// case BYTES_BITS: -// for (b = 0; b < 8; b++) { -// line += ' '; -// } -// break; -// default: -// g_assert_not_reached(); -// } - } - i++; - /* Inter byte space if not at end of line */ - if (i < k) { - line += ' '; + len = tvb_length(tvb_); + pd = tvb_get_ptr(tvb_, 0, -1); + + state = StateNormal; + setState(state); + + /* Print the line number */ + str += QString("%1 ").arg(org_off, offset_width_, 16, QChar('0')); + + /* Print the hex bit */ + for (byten = 0, off = org_off; byten < per_line_; byten++) { + highlight_state state_cur = StateNormal; + bool add_space = byten > 0; + + if ((off >= f_start_ && off < f_end_) || (off >= fa_start_ && off < fa_end_)) { + state_cur = StateField; + } else if (off >= p_start_ && off < p_end_) { + state_cur = StateProtocol; + } + + if (state_cur != state) { + if (state != StateField && add_space) { + add_space = false; + str += ' '; /* insert a space every BYTE_VIEW_SEP bytes */ - if( ( i % BYTE_VIEW_SEP ) == 0 ) { - line += ' '; - } + if ((off % BYTE_VIEW_SEP) == 0) + str += ' '; } - } - /* Print some space at the end of the line */ - line += " "; + if (flushBytes(str) < 0) + return; + setState(state_cur); + state = state_cur; + } - /* Print the ASCII bit */ - i = j; + if (add_space) { + str += ' '; + /* insert a space every BYTE_VIEW_SEP bytes */ + if ((off % BYTE_VIEW_SEP) == 0) + str += ' '; + } - while (i < k) { - if (i < len) { - if (m_encoding == PACKET_CHAR_ENC_CHAR_ASCII) { - c = pd[i]; - } - else if (m_encoding == PACKET_CHAR_ENC_CHAR_EBCDIC) { - c = EBCDIC_to_ASCII1(pd[i]); - } - else { - g_assert_not_reached(); - } - line += isascii(c) && isprint(c) ? c : '.'; - } else { - line += ' '; + if (off < len) { + switch (format_) { + case BYTES_HEX: + str += hexchars[(pd[off] & 0xf0) >> 4]; + str += hexchars[pd[off] & 0x0f]; + break; + case BYTES_BITS: + /* XXX, bitmask */ + for (j = 7; j >= 0; j--) + str += (pd[off] & (1 << j)) ? '1' : '0'; + break; } - i++; - if (i < k) { - /* insert a space every BYTE_VIEW_SEP bytes */ - if( ( i % BYTE_VIEW_SEP ) == 0 ) { - line += ' '; - } + } else { + switch (format_) { + case BYTES_HEX: + str += " "; + break; + case BYTES_BITS: + str += " "; + break; } } - line += '\n'; - if (line.length() >= (MAX_LINES_LEN - MAX_LINE_LEN)) { - append(line); - line.clear(); - } + off++; } -// /* We're done printing the packets; destroy the progress bar if -// it was created. */ -// if (progbar != NULL) -// destroy_progress_dlg(progbar); - - if (line.length()) { - append(line); + if (state != StateNormal) { + if (flushBytes(str) < 0) + return; + setState(StateNormal); + state = StateNormal; } -} -bool ByteViewText::hasDataSource(tvbuff_t *ds_tvb) { - if (ds_tvb != NULL && ds_tvb == m_tvb) - return true; - return false; -} + /* Print some space at the end of the line */ + str += " "; -// Copied from packet_hex_apply_reverse_tag -void ByteViewText::highlight(int bstart, int blen, bool is_root) { - m_start = bstart; -// m_len = blen; + /* Print the ASCII bit */ + for (byten = 0, off = org_off; byten < per_line_; byten++) { + highlight_state state_cur = StateNormal; + bool add_space = byten > 0; -// g_log(NULL, G_LOG_LEVEL_DEBUG, "hl %d %d %d %d", start, len, m_foreground.color().red(), m_background.color().red()); - QTextCursor cursor(textCursor()); - QTextCharFormat format = cursor.charFormat(); + if ((off >= f_start_ && off < f_end_) || (off >= fa_start_ && off < fa_end_)) { + state_cur = StateField; + } else if (off >= p_start_ && off < p_end_) { + state_cur = StateProtocol; + } - QPalette pal = QApplication::palette(); + if (state_cur != state) { + if (state != StateField && add_space) { + add_space = false; + /* insert a space every BYTE_VIEW_SEP bytes */ + if ((off % BYTE_VIEW_SEP) == 0) + str += ' '; + } - if (is_root) { - cursor.movePosition(QTextCursor::Start); - cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor); - format.setForeground(pal.text()); - format.setBackground(pal.base()); - cursor.setCharFormat(format); - } + if (flushBytes(str) < 0) + return; + setState(state_cur); + state = state_cur; + } - // XXX - We should probably use the same colors as the packet list and proto tree selections. - // It isn't obvious how to fetch these. - format.setForeground(is_root ? pal.text() : pal.base()); - format.setBackground(is_root ? pal.alternateBase() : pal.text()); + if (add_space) { + /* insert a space every BYTE_VIEW_SEP bytes */ + if ((off % BYTE_VIEW_SEP) == 0) + str += ' '; + } - int bend = bstart + blen; - int per_line = 0; - int per_one = 0; -// int bits_per_one = 0; - int hex_offset, ascii_offset; + if (off < len) { + c = (encoding_ == PACKET_CHAR_ENC_CHAR_EBCDIC) ? + EBCDIC_to_ASCII1(pd[off]) : + pd[off]; - int start_line, start_line_pos; - int stop_line, stop_line_pos; + str += isprint(c) ? c : '.'; + } else + str += ' '; - if (bstart == -1 || blen == -1) - return; + off++; + } -// /* Display with inverse video ? */ -// if (prefs.gui_hex_dump_highlight_style) -// revstyle = "reverse"; -// else -// revstyle = "bold"; - -// switch (recent.gui_bytes_view) { -// case BYTES_HEX: - per_line = BYTES_PER_LINE; - per_one = 2+1; /* "ff " */ -// bits_per_one = 4; -// break; -// case BYTES_BITS: -// per_line = BITS_PER_LINE; -// per_one = 8+1; /* "10101010 " */ -// bits_per_one = 1; -// break; -// default: -// g_assert_not_reached(); -// } - - start_line = bstart / per_line; - start_line_pos = bstart % per_line; - - stop_line = bend / per_line; - stop_line_pos = bend % per_line; - -#define hex_fix(pos) hex_offset + (pos * per_one) + (pos / BYTE_VIEW_SEP) - (pos == per_line) -#define ascii_fix(pos) pos + (pos / BYTE_VIEW_SEP) - (pos == per_line) - - hex_offset = m_useDigits + 2; - ascii_offset = hex_fix(per_line) + 2; - - cursor.setPosition(0); - cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, start_line); - -// if (mask == 0x00) { - while (start_line <= stop_line) { - int line_pos_end = (start_line == stop_line) ? stop_line_pos : per_line; -// int first_block_adjust = (recent.gui_bytes_view == BYTES_HEX) ? (line_pos_end == per_line/2) : 0; - int first_block_adjust = line_pos_end == per_line/2; - - if (start_line_pos == line_pos_end) break; - - // Should we just jump to absolute offsets instead? - /* bits/hex */ - int cursor_start = hex_fix(start_line_pos); - int cursor_len = hex_fix(line_pos_end) - cursor_start - 1 - first_block_adjust; - cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, cursor_start); - cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, cursor_len); - cursor.setCharFormat(format); - cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, ascii_offset - cursor_start - cursor_len); - - /* ascii */ - cursor_start = ascii_fix(start_line_pos); - cursor_len = ascii_fix(line_pos_end) - cursor_start - first_block_adjust; - cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, cursor_start); - cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, cursor_len); - cursor.setCharFormat(format); - - start_line_pos = 0; - start_line++; - // You are encouraged to make carriage return and line feed sound - // effects as you read the next two lines. - cursor.movePosition(QTextCursor::StartOfLine); - cursor.movePosition(QTextCursor::Down); - } + if (str.length() > 0) { + if (flushBytes(str) < 0) + return; + } -// } else if (mask_le) { /* LSB of mask first (little-endian) */ -// while (start_line <= stop_line) { -// int line_pos_end = (start_line == stop_line) ? stop_line_pos : per_line; -// int line_pos = start_line_pos; - -// while (line_pos < line_pos_end) { -// int lop = 8 / bits_per_one; -// int mask_per_one = (1 << bits_per_one) - 1; -// int ascii_on = 0; - -// while (lop--) { -// if ((mask & mask_per_one)) { -// /* bits/hex */ -// gtk_text_buffer_get_iter_at_line_index(buf, &i_start, start_line, hex_fix(line_pos)+lop); -// gtk_text_buffer_get_iter_at_line_index(buf, &i_stop, start_line, hex_fix(line_pos)+lop+1); -// gtk_text_buffer_apply_tag(buf, revstyle_tag, &i_start, &i_stop); - -// ascii_on = 1; -// } -// mask >>= bits_per_one; -// } - -// /* at least one bit of ascii was one -> turn ascii on */ -// if (ascii_on) { -// /* ascii */ -// gtk_text_buffer_get_iter_at_line_index(buf, &i_start, start_line, ascii_fix(line_pos)); -// gtk_text_buffer_get_iter_at_line_index(buf, &i_stop, start_line, ascii_fix(line_pos)+1); -// gtk_text_buffer_apply_tag(buf, revstyle_tag, &i_start, &i_stop); -// } - -// if (!mask) -// goto xend; - -// line_pos++; -// } - -// start_line_pos = 0; -// start_line++; -// } -// } else { /* mask starting from end (big-endian) */ -// while (start_line <= stop_line) { -// int line_pos_start = (start_line == stop_line) ? start_line_pos : 0; -// int line_pos = stop_line_pos-1; - -// while (line_pos >= line_pos_start) { -// int lop = 8 / bits_per_one; -// int mask_per_one = (1 << bits_per_one) - 1; -// int ascii_on = 0; - -// while (lop--) { -// if ((mask & mask_per_one)) { -// /* bits/hex */ -// gtk_text_buffer_get_iter_at_line_index(buf, &i_start, stop_line, hex_fix(line_pos)+lop); -// gtk_text_buffer_get_iter_at_line_index(buf, &i_stop, stop_line, hex_fix(line_pos)+lop+1); -// gtk_text_buffer_apply_tag(buf, revstyle_tag, &i_start, &i_stop); - -// ascii_on = 1; -// } -// mask >>= bits_per_one; -// } - -// /* at least one bit of ascii was one -> turn ascii on */ -// if (ascii_on) { -// /* ascii */ -// gtk_text_buffer_get_iter_at_line_index(buf, &i_start, stop_line, ascii_fix(line_pos)); -// gtk_text_buffer_get_iter_at_line_index(buf, &i_stop, stop_line, ascii_fix(line_pos)+1); -// gtk_text_buffer_apply_tag(buf, revstyle_tag, &i_start, &i_stop); -// } - -// if (!mask) -// goto xend; - -// line_pos--; -// } - -// stop_line_pos = per_line; -// stop_line--; -// } -// } -//xend: - -#undef hex_fix -#undef ascii_fix + if (state != StateNormal) { + setState(StateNormal); + /* state = StateNormal; */ + } + append(""); } -// XXX - Copied from main_proto_draw.c -/* Which byte the offset is referring to. Associates - * whitespace with the preceding digits. */ -static int -byte_num(int offset, int start_point) +void ByteViewText::setState(ByteViewText::highlight_state state) { - return (offset - start_point) / 3; + QPalette pal = wsApp->palette(); + + moveCursor(QTextCursor::End); + setCurrentFont(wsApp->monospaceFont()); + setTextColor(pal.text().color()); + setTextBackgroundColor(pal.base().color()); + + switch (state) { + case StateProtocol: + setTextBackgroundColor(pal.alternateBase().color()); + break; + case StateField: + if (bold_highlight_) { + setCurrentFont(wsApp->monospaceFont(true)); + } else { + setTextColor(pal.base().color()); + setTextBackgroundColor(pal.text().color()); + } + break; + default: + break; + } } -// XXX - Copied from main_proto_draw.c -//static int -//bit_num(int offset, int start_point) -//{ -// return (offset - start_point) / 9; -//} +int ByteViewText::flushBytes(QString &str) +{ + if (str.length() < 1) return 0; + + insertPlainText(str); + str.clear(); + return str.length(); +} -// XXX - Copied from main_proto_draw.c -static int -hex_view_get_byte(guint ndigits, int row, int column) +void ByteViewText::scrollToByte(int byte) { - int byte; - int digits_start_1; - int digits_end_1; - int digits_start_2; - int digits_end_2; - int text_start_1; - int text_end_1; - int text_start_2; - int text_end_2; - - /* - * The column of the first hex digit in the first half. - * That starts after "ndigits" digits of offset and two - * separating blanks. - */ - digits_start_1 = ndigits + 2; - - /* - * The column of the last hex digit in the first half. - * There are BYTES_PER_LINE/2 bytes displayed in the first - * half; there are 2 characters per byte, plus a separating - * blank after all but the last byte's characters. - */ - digits_end_1 = digits_start_1 + (BYTES_PER_LINE/2)*2 + - (BYTES_PER_LINE/2 - 1); - - /* - * The column of the first hex digit in the second half. - * Add 2 for the 2 separating blanks between the halves. - */ - digits_start_2 = digits_end_1 + 2; - - /* - * The column of the last hex digit in the second half. - * Add the same value we used to get "digits_end_1" from - * "digits_start_1". - */ - digits_end_2 = digits_start_2 + (BYTES_PER_LINE/2)*2 + - (BYTES_PER_LINE/2 - 1); - - /* - * The column of the first "text dump" character in the first half. - * Add 3 for the 3 separating blanks between the hex and text dump. - */ - text_start_1 = digits_end_2 + 3; - - /* - * The column of the last "text dump" character in the first half. - * There are BYTES_PER_LINE/2 bytes displayed in the first - * half; there is 1 character per byte. - * - * Then subtract 1 to get the last column of the first half - * rather than the first column after the first half. - */ - text_end_1 = text_start_1 + BYTES_PER_LINE/2 - 1; - - /* - * The column of the first "text dump" character in the second half. - * Add back the 1 to get the first column after the first half, - * and then add 1 for the separating blank between the halves. - */ - text_start_2 = text_end_1 + 2; - - /* - * The column of the last "text dump" character in second half. - * Add the same value we used to get "text_end_1" from - * "text_start_1". - */ - text_end_2 = text_start_2 + BYTES_PER_LINE/2 - 1; - - /* Given the column and row, determine which byte offset - * the user clicked on. */ - if (column >= digits_start_1 && column <= digits_end_1) { - byte = byte_num(column, digits_start_1); - if (byte == -1) { - return byte; - } - } - else if (column >= digits_start_2 && column <= digits_end_2) { - byte = byte_num(column, digits_start_2); - if (byte == -1) { - return byte; - } - byte += 8; - } - else if (column >= text_start_1 && column <= text_end_1) { - byte = column - text_start_1; - } - else if (column >= text_start_2 && column <= text_end_2) { - byte = 8 + column - text_start_2; - } - else { - /* The user didn't select a hex digit or - * text-dump character. */ + QTextCursor cursor(textCursor()); + + cursor.movePosition(QTextCursor::Start); + cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, byte / per_line_); + setTextCursor(cursor); +} + +int ByteViewText::byteFromRowCol(int row, int col) +{ + /* hex_pos_byte array generated with hex_view_get_byte(0, 0, 0...70) */ + static const int hex_pos_byte[70] = { + -1, -1, + 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, + 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, + -1, + 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, + 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, + -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + -1, + 8, 9, 10, 11, 12, 13, 14, 15 + }; + + /* bits_pos_byte array generated with bit_view_get_byte(0, 0, 0...84) */ + static const int bits_pos_byte[84] = { + -1, -1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, + -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7 + }; + + int off_col = 1; + int off_row; + + off_row = row * per_line_; + + if (/* char_x < 0 || */ col < offset_width_) return -1; + col -= offset_width_; + + switch (format_) { + case BYTES_BITS: + g_return_val_if_fail(col >= 0 && col < (int) G_N_ELEMENTS(bits_pos_byte), -1); + off_col = bits_pos_byte[col]; + break; + + case BYTES_HEX: + g_return_val_if_fail(col >= 0 && col < (int) G_N_ELEMENTS(hex_pos_byte), -1); + off_col = hex_pos_byte[col]; + break; } - /* Add the number of bytes from the previous rows. */ - byte += row * BYTES_PER_LINE; + if (col == -1) + return -1; - return byte; + return off_row + off_col; } void ByteViewText::mousePressEvent (QMouseEvent * event) { @@ -614,26 +369,27 @@ void ByteViewText::mousePressEvent (QMouseEvent * event) { QTextCursor cursor(cursorForPosition(event->pos())); field_info *fi; - byte = hex_view_get_byte(m_useDigits, cursor.blockNumber(), cursor.columnNumber()); - fi = proto_find_field_from_offset(m_tree, byte, m_tvb); - g_log(NULL, G_LOG_LEVEL_DEBUG, "byte %d fi %p", byte, fi); - - if (fi && m_protoTree) { - // XXX - This should probably be a ProtoTree method. - QTreeWidgetItemIterator iter(m_protoTree); - while (*iter) { - if (fi == (*iter)->data(0, Qt::UserRole).value<field_info *>()) { - g_log(NULL, G_LOG_LEVEL_DEBUG, "found %p", fi); - m_protoTree->setCurrentItem((*iter)); - } + byte = byteFromRowCol(cursor.blockNumber(), cursor.columnNumber()); + if (byte >= 0) { + fi = proto_find_field_from_offset(proto_tree_, byte, tvb_); + + if (fi && tree_widget_) { + // XXX - This should probably be a ProtoTree method. + QTreeWidgetItemIterator iter(tree_widget_); + while (*iter) { + if (fi == (*iter)->data(0, Qt::UserRole).value<field_info *>()) { + tree_widget_->setCurrentItem((*iter)); + } - iter++; + iter++; + } } } } QWidget::mousePressEvent (event); } + /* * Editor modelines * |