diff options
Diffstat (limited to 'hexEditor.cpp')
-rwxr-xr-x | hexEditor.cpp | 1112 |
1 files changed, 0 insertions, 1112 deletions
diff --git a/hexEditor.cpp b/hexEditor.cpp deleted file mode 100755 index 0cae378..0000000 --- a/hexEditor.cpp +++ /dev/null @@ -1,1112 +0,0 @@ -/* $Id: hexEditor.cpp,v 1.14 2006/11/05 04:42:43 ganzhorn Exp $ - * This file is part of lfhex. - * Copyright (C) 2006 Salem Ganzhorn <eyekode@yahoo.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include <math.h> -#include <assert.h> -#include <stdio.h> -#include <errno.h> -#include <string.h> -#include <ctype.h> -#include <algorithm> -#include <iostream> - -#include <QApplication> -#include <QMessageBox> -#include <QFileDialog> -#include <QProgressDialog> -#include <QPainter> -#include <QPixmap> -#include <QFocusEvent> -#include <QPaintEvent> -#include <QKeyEvent> -#include <QResizeEvent> -#include <QMouseEvent> - -#include "hexEditor.hpp" -#include "translate.hpp" -#include "local.h" - -extern int errno; - -HexEditor::HexEditor( QWidget * parent ) - : QWidget(parent) -{ - _cols = 5; - _rows = 10; - _charsPerByte = 2; - _base = 16; - _topLeft = 0; - _topMargin = _wordSpacing = 6; - _bytesPerWord = 1; - _lastValidWord = -1; - _selection[SelectionStart] = _selection[SelectionEnd] = -1; - - setFocusPolicy(Qt::StrongFocus); - // the first setBytesPerWord should not come before the first setFont() - QFont font("fixed"); - font.setFixedPitch(1); - setFont( font ); - setBackgroundRole( QPalette::Base ); -} - -HexEditor::~HexEditor() -{ - _reader.close(); -} - -bool HexEditor::isModified() const -{ - return ( _reader.is_open() && _delta.numEdits() ); -} - -bool HexEditor::save( QString filename ) -{ - if( !isModified() ) { - QString errMsg = "Error, file is not open or has not been modified. " - "Aborting save."; - QMessageBox::warning(this,PROGRAM_STRING,errMsg); - return false; - } - - if( filename != "" ) { - // copy open reader file to filename - QString oldFilename = _reader.filename(); - - if( oldFilename == "" ) - return false; - - _reader.close(); - FILE* fin = fopen(C_STR(oldFilename),"r"); - if( !fin ) { - QString errMsg = "Error opening \"" + oldFilename + "\" for reading: " + - strerror(errno); - QMessageBox::warning(this,PROGRAM_STRING,errMsg); - return false; - } - FILE* fout = fopen(C_STR(filename),"w"); - if( !fout ) { - QString errMsg = "Error opening \"" + filename+ "\" for writing: " + - strerror(errno); - QMessageBox::warning(this,PROGRAM_STRING,errMsg); - fclose(fin); - return false; - } - int length; - uchar bytes[4096]; - while( (length = fread(bytes,1,4096,fin)) ) { - fwrite( bytes, 1, length, fout ); - } - fclose(fin); - fclose(fout); - } else { - filename = _reader.filename(); - _reader.close(); - } - - if( filename == "" ) - return false; - - if( !_delta.numEdits() ) - return false; - - if( !writeDeltas(C_STR(filename),_delta) ) { - _reader.open(C_STR(filename)); - return false; - } - _delta.clear(); - _reader.open(C_STR(filename)); - setTopLeft(_topLeft); - return true; -} - -QString HexEditor::filename() const -{ - return _reader.filename(); -} - -bool HexEditor::open( const QString & filename ) -{ - if( closeFile() == QMessageBox::Cancel ) - return false; - - if(!_reader.open(C_STR(filename))) { - QMessageBox::critical( this, "HexEdit", - "Error loading \"" + filename + "\"\n" + - _reader.lastError(), - QMessageBox::Ok,0); - return false; - } - _delta.clear(); // reset modification tree - - // set the new range for the scrollbar - _cursor.setRange(0,_reader.size()); - _cursor.setCharsPerByte(_charsPerByte); - setSelection(SelectionStart,-1); - setSelection(SelectionEnd,-1); - emit rangeChanged(0,_reader.size()/bytesPerLine()); - calculateFontMetrics(); // update labels - setTopLeft(0); // reset the GUI - return true; -} - -int HexEditor::closeFile(bool force) -{ - int retval = QMessageBox::No; - if( _delta.numEdits() ) { - QString message = - "Save changes to \"" + QString(_reader.filename()) + "\"?"; - if( force ) { - retval = QMessageBox::warning( this, - PROGRAM_STRING, - message, - QMessageBox::Yes, - QMessageBox::No ); - } else { - retval = QMessageBox::warning( this, - PROGRAM_STRING, - message, - QMessageBox::Yes, - QMessageBox::No, - QMessageBox::Cancel); - } - } - if( retval == QMessageBox::Yes ) - save(); - return retval; -} - -void HexEditor::setBytesPerWord( int nbytes ) -{ - _bytesPerWord = nbytes; - calculateFontMetrics(); - QResizeEvent *re = new QResizeEvent(QSize(size()),QSize(size())); - resizeEvent(re); - delete re; -} -int HexEditor::fontHeight() const -{ - return _fontHeight; -} -int HexEditor::lineSpacing() const -{ - return _lineSpacing; -} -int HexEditor::fontMaxWidth() const -{ - return _fontMaxWidth; -} -void HexEditor::calculateFontMetrics() -{ - _lineSpacing = fontMetrics().lineSpacing(); - _fontMaxWidth = fontMetrics().maxWidth(); - _wordWidth = _fontMaxWidth*charsPerWord(); - _fontHeight = fontMetrics().height(); - // see how many bytes are needed to show the size of this file - // log base 16 -> log16(x) = log(x)/log(16) - if( _reader.size() ) { - double width = log(static_cast<float>(_reader.size()))/log(16.0)+2; - _offsetLabelBytes = static_cast<int>( width ); - } else { - _offsetLabelBytes = 0; - } - _leftMargin = _topMargin + _fontMaxWidth*(_offsetLabelBytes + 2); - // make sure bboxes are updated with new offset subdivision - QResizeEvent *re = new QResizeEvent(QSize(size()),QSize(size())); - resizeEvent(re); - delete re; -} -void HexEditor::setFont(const QFont& font ) -{ - if( !font.fixedPitch() ) { - cerr << "setFont() failed, font was not fixedPitch()." << endl; - return; - } - QWidget::setFont(font); - calculateFontMetrics(); -} -// set the top left editor to offset in reader -void HexEditor::setTopLeft( off_t offset ) -{ - static bool inTopLeft; - if( inTopLeft ) { - // don't nest - return; - } - inTopLeft = true; - try { - if( offset < 0 ) { - _topLeft = 0; - } else if( offset > _reader.size() ) { - _topLeft = _reader.size(); - } else { - _topLeft = offset; - } - // only let _topLeft be an integer multiple of the line length (round down) - _topLeft = (_topLeft/bytesPerLine()) * bytesPerLine(); - // update the labels - // setOffsetLabels(_topLeft); - - const Delta * delta; - - _reader.seek(_topLeft); - _reader.read(_data,bytesPerPage()); - - // update data from delta map - for( offset = _delta.lower_bound(_topLeft); - (offset != -1) && (offset < _topLeft + bytesPerPage()); - offset = _delta.lower_bound(offset) ) { - delta = _delta.search(offset); - _data[offset++-_topLeft] = delta->newData()[0]; - } - - repaint(); - emit topLeftChanged(_topLeft); - } catch( const exception &e ) { - inTopLeft = false; - throw e; - } - inTopLeft = false; -} - -//void HexEditor::setOffsetLabels( off_t topLeft ) -//{ - // need to impliment manually printing labels -//} - -int HexEditor::topMargin() const -{ - return _topMargin; -} -int HexEditor::leftMargin() const -{ - return _leftMargin; -} -// -// access fn's for offset manip -// -int HexEditor::bytesPerPage() const -{ - return _rows*_cols*bytesPerWord(); -} -int HexEditor::bytesPerWord() const -{ - return _bytesPerWord; -} -int HexEditor::bytesPerLine() const -{ - return bytesPerWord()*wordsPerLine(); -} -int HexEditor::wordsPerLine() const -{ - return _cols; -} -int HexEditor::linesPerPage() const -{ - return _rows; -} -int HexEditor::wordsPerPage() const -{ - return _rows*_cols; -} -int HexEditor::charsPerByte() const -{ - return _charsPerByte; -} -int HexEditor::charsPerWord() const -{ - return _charsPerByte*bytesPerWord(); -} -int HexEditor::charsPerLine() const -{ - return _charsPerByte*(bytesPerLine()); -} -// translate local byte offsets to global byte offsets -off_t HexEditor::globalOffset( off_t local ) const -{ - return local+_topLeft; -} -// translate global byte offsets to viewport byte offsets -off_t HexEditor::localOffset( off_t global ) const -{ - return global-_topLeft; -} - -int HexEditor::offsetToPercent( - off_t offset - ) -{ - // round up - return _reader.size() ? (int)ceil(100.0*offset/_reader.size()) : 0; -} - -// public slots: -bool HexEditor::browseLoadFile() -{ - QString filename = QFileDialog::getOpenFileName(); - if( filename.isNull() ) - return false; - return open(filename); -} - -QRect HexEditor::charBBox( off_t charIdx ) const { - // byteIdx = charIdx/charsPerByte - // wordIdx = byteIdx/bytesPerWord - int wordIdx = (charIdx/charsPerByte())/bytesPerWord(); - int localCharIdx = charIdx % charsPerWord(); - return QRect( _wordBBox[wordIdx].left() + localCharIdx*fontMaxWidth() + - wordSpacing()/2, - _wordBBox[wordIdx].top(), - fontMaxWidth(), - fontHeight() ); -} - -QRect HexEditor::byteBBox( off_t byteIdx ) const { - // wordIdx = byteIdx/bytesPerWord - int wordIdx = byteIdx/bytesPerWord(); - int localByteIdx = byteIdx % bytesPerWord(); - return QRect( _wordBBox[wordIdx].left() + localByteIdx*2*fontMaxWidth() + - wordSpacing()/2, - _wordBBox[wordIdx].top(), - fontMaxWidth()*2, - lineSpacing() ); -} - -void HexEditor::setTopLeftToPercent( int percent ) -{ - setTopLeft( (_reader.size()/100)*percent ); -} - -// -// slot for setting cursor offset. -// -void HexEditor::setOffset( off_t offset ) -{ - off_t oldWordOffset = localWordOffset(); - _cursor.setOffset( offset, 0 ); - // updateWord clamps the wordIdx to [0,_rows*_cols) - updateWord( oldWordOffset ); - emit offsetChanged( _cursor.byteOffset() ); -} - -void HexEditor::nextLine() -{ - setTopLeft(_topLeft+bytesPerLine()); -} -void HexEditor::prevLine() -{ - setTopLeft(_topLeft-bytesPerLine()); -} -void HexEditor::nextPage() -{ - setTopLeft(_topLeft+bytesPerPage()); -} -void HexEditor::prevPage() -{ - setTopLeft(_topLeft-bytesPerPage()); -} - -off_t HexEditor::localByteOffsetAtXY(off_t x, off_t y) -{ - off_t wordIdx; - off_t wordLength = wordSpacing()+wordWidth(); - off_t line = min(y/lineSpacing(),(off_t)linesPerPage()); - - // constrain x to be less than the right side of the last char on a line - x = max( (off_t)0, x - leftMargin()); - x = min(wordsPerLine()*wordLength - 1 ,x); - // constrain y to be > topMargin() and less than bottom of last line - y = max( (off_t)0, y - topMargin()); - line = min(y/lineSpacing(), (off_t)linesPerPage()-1); - wordIdx = line*wordsPerLine() + x/wordLength; - - off_t byteOffsetInWord = (x%wordLength)*bytesPerWord()/wordLength; - // = wordIdx*bytesPerWord + byteOffsetInWord - return min( (off_t) bytesPerPage()-1, - wordIdx*bytesPerWord() + byteOffsetInWord); - -} -// -// event handler implimentation: -// -void HexEditor::setCursorFromXY(int x,int y) -{ - off_t oldWordIdx = localWordOffset(); - - _cursor.setOffset( _topLeft+localByteOffsetAtXY(x,y) ,0 ); - - // update where the cursor used to be, and where it is now - if( oldWordIdx != localWordOffset() ) { - updateWord( oldWordIdx ); - } - updateWord( localWordOffset() ); - emit offsetChanged(_cursor.byteOffset()); -} - -void HexEditor::mousePressEvent( QMouseEvent* e ) -{ - setCursorFromXY(e->x(),e->y()); - - off_t byte_offset = localByteOffset(); - QRect bbox = byteBBox(byte_offset); - if( e->x() > bbox.right() ) { - byte_offset++; - } - setSelection( SelectionStart, globalOffset( byte_offset )); -} - -void HexEditor::mouseMoveEvent( QMouseEvent* e ) -{ - setCursorFromXY(e->x(),e->y()); - - off_t byte_offset = localByteOffset(); - QRect bbox = byteBBox(byte_offset); - if(e->x() > bbox.right() ) { - byte_offset++; - } - - setSelection( SelectionEnd, globalOffset( byte_offset )); -} - -void HexEditor::mouseReleaseEvent( QMouseEvent* e ) -{ - setCursorFromXY(e->x(),e->y()); - - off_t byte_offset = localByteOffset(); - QRect bbox = byteBBox(byte_offset); - if(e->x() > bbox.right() ) { - byte_offset++; - } - - setSelection( SelectionEnd, globalOffset( byte_offset )); -} - -off_t HexEditor::selectionStart() const -{ - if( _selection[SelectionStart] == -1 || _selection[SelectionEnd] == -1 ) - return -1; - return min(_selection[SelectionStart],_selection[SelectionEnd]); -} -// note: end is open. range is: [start,end) - -off_t HexEditor::selectionEnd() const -{ - if( _selection[SelectionStart] == -1 || _selection[SelectionEnd] == -1 ) - return -1; - return max(_selection[SelectionStart],_selection[SelectionEnd]); -} - -void HexEditor::setSelection(SelectionPos_e pos, off_t offset) -{ - if( !_reader.is_open() ) { - return; - } - if( pos == SelectionStart ) { - _selection[SelectionEnd] = -1; - } - _selection[pos] = offset; - - if( _selection[SelectionStart] < 0 ) { - emit selectionChanged(""); - } else { - if( selectionEnd() > -1 && selectionEnd() <= _reader.size() ) { - QString data; - const Delta* delta; - for(off_t i = selectionStart(); - i < selectionEnd(); - ++i) { - if( (delta = _delta.search(i)) ) - data += Translate::ByteToHex(delta->newData()[0]); - else - data += Translate::ByteToHex(_reader[i]); - } - emit selectionChanged( data ); - } else { - emit selectionChanged( "" ); - } - } - - repaint(); -} - -// -// Editor implimentation -// -void HexEditor::keyPressEvent( QKeyEvent *e ) -{ - int key = e->key(); - - switch(_base) { - case -1: - // ascii - // range is taken from qnamespace.h - if( key >= Qt::Key_Space && key <= Qt::Key_AsciiTilde ) { - seeCursor(); - vector<uchar> oldData; - vector<uchar> newData; - vector<uchar> chars; - - oldData.push_back( *(_data.begin()+localByteOffset()) ); - Translate::ByteToChar(chars,oldData); - chars[0] = key; - Translate::CharToByte(newData,chars); - _delta.insert( _cursor.byteOffset(), - oldData, - newData); - _data[_cursor.byteOffset()-_topLeft] = newData[0]; - cursorRight(); - setSelection(SelectionStart,-1); - return; - } - break; - case 16: - if ( key >= 'A' && key <= 'F' ) { - key = tolower(key); - } - if ( (key >= 'a' && key <= 'f') || - (key >= '0' && key <= '9') ) { - // - // make sure we can see where the cursor is - // - seeCursor(); - vector<uchar> oldData; - vector<uchar> newData; - vector<uchar> hex; - - oldData.push_back( *(_data.begin()+localByteOffset()) ); - Translate::ByteToHex(hex,oldData); - hex[_cursor.charOffset()] = key; - Translate::HexToByte(newData,hex); - - _delta.insert( _cursor.byteOffset(), - oldData, - newData ); - _data[_cursor.byteOffset()-_topLeft] = newData[0]; - // move to the next char - cursorRight(); - setSelection(SelectionStart,-1); - return; - } - break; - case 8: - if( key >= '0' && key < '8' ) { - // valid octal key - seeCursor(); - vector<uchar> oldData; - vector<uchar> newData; - vector<uchar> octal; - - oldData.push_back( *(_data.begin()+localByteOffset()) ); - Translate::ByteToOctal(octal,oldData); - octal[_cursor.charOffset()] = key; - Translate::OctalToByte(newData,octal); - - _delta.insert( _cursor.byteOffset(), - oldData, - newData ); - _data[_cursor.byteOffset()-_topLeft] = newData[0]; - cursorRight(); - setSelection(SelectionStart,-1); - return; - } - break; - case 2: - if( key >= '0' && key < '2' ) { - // valid binary key - seeCursor(); - vector<uchar> oldData; - vector<uchar> newData; - vector<uchar> binary; - - oldData.push_back( *(_data.begin()+localByteOffset()) ); - Translate::ByteToBinary(binary,oldData); - binary[_cursor.charOffset()] = key; - Translate::BinaryToByte(newData,binary); - - _delta.insert( _cursor.byteOffset(), - oldData, - newData ); - _data[_cursor.byteOffset()-_topLeft] = newData[0]; - cursorRight(); - setSelection(SelectionStart,-1); - return; - } - break; - } - switch ( e->key() ) { - case Qt::Key_Left: - cursorLeft(); - break; - case Qt::Key_Right: - cursorRight(); - break; - case Qt::Key_Up: - cursorUp(); - break; - case Qt::Key_Down: - cursorDown(); - break; - case Qt::Key_PageUp: - prevPage(); - break; - case Qt::Key_PageDown: - nextPage(); - break; - case Qt::Key_End: - setTopLeft( _reader.size() - bytesPerPage()/2 ); - break; - case Qt::Key_Home: - setTopLeft(0); - break; - default: - e->ignore(); - break; - } -} - -void HexEditor::resizeEvent( QResizeEvent * e ) -{ - int height= lineSpacing(); - int totalWordWidth = wordWidth() + wordSpacing(); - int linewidth = e->size().width(); - - // don't let _rows or _cols drop below 1 - _rows = max(1,(e->size().height() - _topMargin)/height); - _cols = max(1,(e->size().width() - _leftMargin)/totalWordWidth); - - // now update the line && word bbox vectors - _lineBBox.reserve(_rows); - _wordBBox.reserve(_rows*_cols); - int top,left; - for(int r = 0; r < _rows; r++) { - top = r*height + _topMargin; - for(int c = 0; c < _cols; c++) { - left = totalWordWidth*c + _leftMargin; - _wordBBox[r*_cols+c] = QRect(left, //left - top, //top - totalWordWidth, //width - height); //height - } - _lineBBox[r] = QRect(_leftMargin,top,linewidth,height); - } - // calculate offset label bounding box - _labelBBox.setRect(0, // x - 0, // y - _leftMargin, // width - e->size().height()); // height - - // do this to recalculate the amount of displayed data. - setTopLeft(_topLeft); - emit rangeChanged(0,_reader.size()/bytesPerLine()); -} -// -// Reimplimented to be more efficient then repainting the whole screen on -// focus events. -// -void HexEditor::focusInEvent( QFocusEvent* ) -{ - updateWord( localWordOffset() ); -} -void HexEditor::focusOutEvent( QFocusEvent* ) -{ - updateWord( localWordOffset() ); -} -// generate's paint events for wordIdx (global wordIdx) -// is safe to call with any wordIdx -void HexEditor::updateWord( off_t wordIdx ) -{ - if( wordIdx > -1 && wordIdx < _rows*_cols ) - repaint(_wordBBox[wordIdx]); -} - -void HexEditor::paintLabels( QPainter* paintPtr) -{ - // ignore redraw range for first aproximation: - int y = _wordBBox[0].bottom(); - unsigned int i; - off_t offset = _topLeft; - uchar *ucptr; - QString label; - - for(int row = 0; row < _rows;++row) { - label = ""; -#ifdef WORDS_BIGENDIAN - for(i=0, ucptr = (uchar*)&offset; i<sizeof(off_t);++i) { - label += Translate::ByteToHex(*ucptr++); - } -#else - // make sure we write offset labels in big-endian (easier to read) - ucptr = (uchar*)(&offset) + sizeof(off_t)-1; - for(i=0;i<sizeof(off_t);++i) { - label += Translate::ByteToHex(*ucptr--); - } -#endif - label = label.mid(sizeof(off_t)*2-_offsetLabelBytes); - paintPtr->drawText( 5, y, label ); - offset+=bytesPerLine(); - y+=lineSpacing(); - } - // draw dividing line between offset labels and data - int x = leftMargin()-fontMaxWidth(); - paintPtr->drawLine(x,topMargin(), - x,height()-topMargin()); -} -// -// painting optimizations, each time resize is called, it calculates -// the bounding boxes for each word and each line. -// This data can then be retrieved with wordBBox() -// We can then test intersections to see which words need to be redrawn -// -void HexEditor::paintEvent( QPaintEvent* e) -{ -/* QPixmap pixmap(this->width(),this->height()); - pixmap.fill(backgroundRole());*/ - QPainter paint( this );//&pixmap); - - // set up painter;/ - paint.setFont(font()); - const QPalette& p = qApp->palette(); - paint.setBrush(p.background()); - - if( _labelBBox.intersects(e->rect()) ) { - paintLabels(&paint); - } - - QString text; - if( !getDisplayText(text) ) { - cerr << "[error] - internal inconsitency. Please file bug report." - << endl; - return; - } - - // both cursor and selection is drawn underneath the text - drawCursor( paint ); - drawSelection( paint ); - - // Find the stop/start row/col idx's for the repaint - int totalWordWidth = wordWidth()+wordSpacing(); - int row_start = max(0,(e->rect().top()-topMargin())/lineSpacing() ); - int col_start = max(0,(e->rect().left()-leftMargin())/totalWordWidth); - int row_stop = min(_rows-1,e->rect().bottom() / lineSpacing()); - int col_stop = min(_cols-1,e->rect().right() / totalWordWidth); - - // draw text in repaint event - drawTextRegion( paint, text, row_start, row_stop, col_start, col_stop ); -} - -bool HexEditor::getDisplayText( QString& text ) -{ - // get data to draw - switch (_base) { - case 16: - Translate::ByteToHex(text,_data); - break; - case 8: - Translate::ByteToOctal(text,_data); - break; - case 2: - Translate::ByteToBinary(text,_data); - break; - case -1: - Translate::ByteToChar(text,_data); - break; - default: - // error state - return false; - } - return true; -} - -bool HexEditor::wordModified ( off_t wordIdx ) const -{ - off_t lboffset = wordIdx*bytesPerWord()+_topLeft; - off_t nearest_offset = _delta.lower_bound(lboffset); - return ( nearest_offset != -1 && nearest_offset < lboffset+bytesPerWord() ); -} - -// -// accessors for local offsets -// -off_t HexEditor::localByteOffset() const -{ - return _cursor.byteOffset() - _topLeft; -} -off_t HexEditor::localWordOffset() const -{ - return localByteOffset()/bytesPerWord(); -} -// in offset relative to _data[0] -off_t HexEditor::localCharOffset() const -{ - return localByteOffset()*charsPerByte() + _cursor.charOffset(); -} -off_t HexEditor::localLineOffset() const -{ - return localWordOffset()/wordsPerLine(); -} -int HexEditor::wordWidth() const -{ - return _fontMaxWidth*charsPerWord(); -} -int HexEditor::wordSpacing() const -{ - return _wordSpacing; -} -// -// cursor movement members -// -void HexEditor::seeCursor() -{ - // see if it is already visible - if ( _cursor.byteOffset() >= _topLeft && - _cursor.byteOffset() <= _topLeft+bytesPerPage()-1 ) { - updateWord( localWordOffset() ); - return; - } else { - // setTopLeft so cursor is in middle line of screen - setTopLeft( max(_cursor.byteOffset() - bytesPerPage()/2, (off_t)0) ); - } -} - -void HexEditor::cursorLeft() -{ - off_t oldWordIdx = localWordOffset(); - // move the cursor - _cursor.decrByChar(1); - // make sure the user can see the cursor - seeCursor(); - // redraw where the cursor used to be - if( localWordOffset() != oldWordIdx ) - updateWord( oldWordIdx ); - emit offsetChanged( _cursor.byteOffset() ); -} -void HexEditor::cursorRight() -{ - off_t oldWordIdx = localWordOffset(); - _cursor.incrByChar(1); - seeCursor(); - if( localWordOffset() != oldWordIdx ) - updateWord( oldWordIdx ); - emit offsetChanged( _cursor.byteOffset() ); -} -void HexEditor::cursorUp() -{ - off_t oldWordIdx = localWordOffset(); - _cursor.decrByByte( bytesPerLine() ); - seeCursor(); - if( localWordOffset() != oldWordIdx ) - updateWord( oldWordIdx ); - emit offsetChanged( _cursor.byteOffset() ); -} -void HexEditor::cursorDown() -{ - off_t oldWordIdx = localWordOffset(); - _cursor.incrByByte( bytesPerLine() ); - seeCursor(); - if( localWordOffset() != oldWordIdx ) - updateWord( oldWordIdx ); - emit offsetChanged( _cursor.byteOffset() ); -} - -// slots for undo/redo. -// note: it is necessary to reset topLeft to force a reread of the data. -// -void HexEditor::redo() -{ - _delta.redo(); - setTopLeft(_topLeft); - off_t start = selectionStart(); - off_t end = selectionEnd(); - setSelection(SelectionStart,start); - setSelection(SelectionEnd,end); -} - -void HexEditor::undo() -{ - _delta.undo(); - setTopLeft(_topLeft); - off_t start = selectionStart(); - off_t end = selectionEnd(); - setSelection(SelectionStart,start); - setSelection(SelectionEnd,end); -} - -void HexEditor::search( const QString& hexText, bool forwards ) -{ - QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) ); - if( !hexText.length() || _reader.filename() == "" ) - return; - - if( -1 != _delta.lower_bound(0) ) { - QMessageBox::information(this,PROGRAM_STRING, - "Cannot search file with unsaved modifications."); - return; - } - - vector<uchar> data; - Translate::HexToByte(data,hexText); -// QProgressDialog progress( "Searching...","Cancel", 0, -// _reader.size(),this ); -// progress.setWindowModality( Qt::WindowModal ); -// progress.setWindowTitle(PROGRAM_STRING); -// progress.setValue(0); - off_t pos; - if( forwards ) { - pos = _reader.findIndex(_cursor.byteOffset(),data,_reader.size()-1); - } else { - pos = _reader.rFindIndex(_cursor.byteOffset(),data,0); - } - if( pos < _reader.size() ) { - showMatch(pos,data.size()); - setOffset( forwards?selectionEnd():selectionStart()-1 ); - seeCursor(); - } else { - QMessageBox::information(this,PROGRAM_STRING, - "Could not find search data 0x" + hexText); - } - QApplication::restoreOverrideCursor(); -} -void HexEditor::setBaseASCII() { - setBase(-1); -} -void HexEditor::setBaseHex() -{ - setBase(16); -} -void HexEditor::setBaseOctal() -{ - setBase(8); -} -void HexEditor::setBaseBinary() -{ - setBase(2); -} -void HexEditor::setBase(int base) -{ - switch(base) { - case -1: - // setup ascii editing mode - _charsPerByte = 1; - break; - case 2: - // setup binary editing mode - _charsPerByte = 8; - break; - case 8: - // setup octal editing mode - _charsPerByte = 3; - break; - case 16: - // setup hex editing mode - _charsPerByte = 2; - break; - default: - // just ignore unsupported bases for now - return; - } - _base = base; - _cursor.setCharsPerByte(_charsPerByte); - // refresh the display - // note: cannot call resize() because it will ignore resize events - // if the size has not changed. - QResizeEvent *re = new QResizeEvent(QSize(size()),QSize(size())); - resizeEvent(re); - delete re; - // make sure we can still see the cursor - // switching from a larger base to a smaller base has the - // possibility of pushing the cursor off the screen - seeCursor(); -} - -off_t HexEditor::offset() const -{ - return _cursor.byteOffset(); -} - -Reader * HexEditor::reader() -{ - return &_reader; -} - -void HexEditor::showMatch( off_t pos, int len ) -{ - setSelection( SelectionStart, pos ); - setSelection( SelectionEnd, pos + len ); -} - -void HexEditor::drawTextRegion( QPainter& paint, const QString& text, - int row_start, int row_stop, - int col_start, int col_stop ) -{ - paint.setPen(qApp->palette().foreground().color()); - for(int r = row_start; r <= row_stop; r++) { - for(int c = col_start; c <= col_stop; c++) { - int widx = r*_cols+c; - if ( wordModified( widx ) ) { - paint.setPen(qApp->palette().link().color()); - paint.drawText( _wordBBox[widx].left() + wordSpacing()/2, - _wordBBox[widx].bottom(), - text.mid(widx*charsPerWord(),charsPerWord()) ); - paint.setPen(qApp->palette().foreground().color()); - } else { - paint.drawText( _wordBBox[widx].left() + wordSpacing()/2, - _wordBBox[widx].bottom(), - text.mid(widx*charsPerWord(),charsPerWord()) ); - } - } - } -} - -void HexEditor::drawSelection( QPainter& paint ) -{ - // draw selection - off_t start = max( (off_t)0, selectionStart() - _topLeft); - if( start < bytesPerPage() ) { - off_t stop = min(selectionEnd() - _topLeft, (off_t)bytesPerPage()); - paint.setPen(Qt::NoPen); - paint.setBrush( qApp->palette().highlight() ); - // foreach line with selection - stop--; - while( start <= stop ) { - // linestop = min(stop,endofline) - off_t linestop = - min(stop, start+bytesPerLine()-1 -(start % bytesPerLine())); - QRect bbox = byteBBox(start); - bbox.setRight( byteBBox(linestop).right() ); - paint.drawRect( bbox ); - start = linestop+1; - } - } -} - -void HexEditor::drawCursor( QPainter& paint ) -{ - QBrush b = qApp->palette().mid(); - if( localWordOffset() > -1 && localWordOffset() < wordsPerPage() ) { - if( hasFocus() ) { - // draw a solid cursor - paint.setPen(Qt::NoPen); - paint.setBrush(b); - } else { - // just draw the outline - paint.setPen(b.color()); - paint.setBrush(Qt::NoBrush); - } - QRect box = charBBox( localCharOffset() ); - paint.drawRect( box ); - } -} |