From 7ec5a57fc3f04526f36477e22066199372beb0ee Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Tue, 8 Dec 2020 12:30:30 +0900 Subject: Renaming of files in preparation for code style tools. Signed-off-by: Michele Calgaro --- khexedit/hexviewwidget.cpp | 2286 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2286 insertions(+) create mode 100644 khexedit/hexviewwidget.cpp (limited to 'khexedit/hexviewwidget.cpp') diff --git a/khexedit/hexviewwidget.cpp b/khexedit/hexviewwidget.cpp new file mode 100644 index 0000000..6c15ae3 --- /dev/null +++ b/khexedit/hexviewwidget.cpp @@ -0,0 +1,2286 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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 + +#include +#include + + +#include +#include +#include +#include +#include + +#include "hexdrag.h" +#include "hexerror.h" +#include "hexviewwidget.h" + +// +// The usage of the WNorthWestGravity flag should make screen update +// faster (less paintEvents). I have had to add update() some places +// to ensure proper redrawing. Undefine if something goes wrong +// (i.e. not updated ) +// +#define USE_NORTHWEST_GRAVITY 1 + +// +// I don't want to decide what is best: Drag starts when mouse is moved or +// after a timeout. +// +#define USE_DRAG_MOVEMENT 1 + + + + + + +CDragManager::CDragManager( void ) +{ + mActivateMode = Movement; + mPending = false; + mTimerId = 0; +} + +void CDragManager::setActivateMode( EDragActivateMode mode ) +{ + clear(); + mActivateMode = mode; // Movement or Timer +} + +void CDragManager::setup( int x, int y ) +{ + if( mActivateMode == Movement ) + { + mOrigin.setX(x); + mOrigin.setY(y); + } + else + { + setupTimer(); + } + mPending = true; +} + +bool CDragManager::start( TQMouseEvent *e ) +{ + if( mPending == false ) + { + return( false ); + } + + if( mActivateMode == Movement ) + { + if( (mOrigin - e->pos()).manhattanLength() > TDEGlobalSettings::dndEventDelay() ) + { + mPending = false; + emit startDrag( e->state() & ShiftButton ? true : false ); + } + return( true ); + } + else // Timer + { + if( mTimerId != 0 ) + { + removeTimer(); + mPending = false; + emit startDrag( e->state() & ShiftButton ? true : false ); + return( true ); + } + else + { + // Should never happen! + mPending = false; + return( false ); + } + } + +} + +bool CDragManager::clear( void ) +{ + if( mPending == false ) + { + return( false ); + } + + if( mActivateMode == Timer ) + { + removeTimer(); + } + + mPending = false; + return( true ); +} + +void CDragManager::timerEvent( TQTimerEvent *e ) +{ + if( e->timerId() == mTimerId ) + { + removeTimer(); + if( mPending == true ) + { + mPending = false; + emit startDrag( ( kapp->keyboardModifiers() & TDEApplication::ShiftModifier ) ); + } + } +} + +void CDragManager::removeTimer( void ) +{ + if( mTimerId != 0 ) + { + killTimer( mTimerId ); + mTimerId = 0; + } +} + +void CDragManager::setupTimer( void ) +{ + if( mTimerId != 0 ) + { + killTimer( mTimerId ); + mTimerId = 0; + } + mTimerId = startTimer( 500 ); +} + + +// +// This widget will use the entire space of the parent widget +// +CHexViewWidget::CHexViewWidget( TQWidget *parent, const char *name, + CHexBuffer *hexBuffer ) + : TQFrame( parent, name, + #ifdef USE_NORTHWEST_GRAVITY + TQt::WStaticContents + #else + 0 + #endif + ), mScrollBarSize( 16 ) +{ + if( parent == 0 || hexBuffer == 0 ) { return; } + + // + // TQt 2.0: + // ------- + // I use the "CScrollBar" because sometimes (very seldom) when I + // do a mHorzScroll->hide() the mHorzScroll->isVisible() remains true + // in updateView() for a short while. I need the correct visibility + // because I have to redraw the area - due to the "WNorthWestGravity" usage. + // + // I tried to do a + // "while( mHorzScroll->isVisible() ) { mHorzScroll->hide(); }" + // but then the loop never ended. The "CScrollBar" emits a "hidden()" + // signal whenever is receives a TQHideEvent. + // + + mVertScroll = new CScrollBar( Qt::Vertical, this ); + if( mVertScroll == 0 ) { return; } + mHorzScroll = new CScrollBar( Qt::Horizontal, this ); + if( mHorzScroll == 0 ) { return; } + mCorner = new TQWidget( this ); + if( mCorner == 0 ) { return; } + connect( mHorzScroll, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(changeXPos(int)) ); + connect( mVertScroll, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(changeYPos(int)) ); + connect( mHorzScroll, TQT_SIGNAL(hidden()), TQT_SLOT(update()) ); + connect( mVertScroll, TQT_SIGNAL(hidden()), TQT_SLOT(update()) ); + mHorzScroll->hide(); + mVertScroll->hide(); + + mDragManager = new CDragManager(); + if( mDragManager == 0 ) { return; } + #ifdef USE_DRAG_MOVEMENT + mDragManager->setActivateMode( CDragManager::Movement ); + #else + mDragManager->setActivateMode( CDragManager::Timer ); + #endif + connect( mDragManager, TQT_SIGNAL(startDrag(bool)), TQT_SLOT(startDrag(bool)) ); + + setFrameStyle( TQFrame::WinPanel|TQFrame::Sunken ); + setWFlags( WResizeNoErase ); + setFocusPolicy( TQ_StrongFocus ); + + mHexBuffer = hexBuffer; + mHexBuffer->cursorReset(); + + mEditMode = mHexBuffer->editMode(); + mShowCursor = false; + mCursorTimerId = 0; + + mDocumentMenu = 0; + + setTextBufferSize(); // Make sure there is a pixmap buffer + setStartX(0); + setStartY(0); + + setAcceptDrops(true); + setDropHighlight(false); // Init state + frame shape + setBackgroundColor( mHexBuffer->backgroundColor() ); +} + + +CHexViewWidget::~CHexViewWidget( void ) +{ + delete mVertScroll; + delete mHorzScroll; + delete mCorner; + delete mDragManager; +} + + +int CHexViewWidget::readFile( TQFile &file, const TQString &url, CProgress &p ) +{ + int errCode = mHexBuffer->readFile( file, url, p ); + if( errCode != Err_Success ) + { + return( errCode ); + } + + initFile(); + return( Err_Success ); +} + + +int CHexViewWidget::insertFile( TQFile &file, CProgress &p ) +{ + int errCode = mHexBuffer->insertFile( file, p ); + if( errCode != Err_Success ) + { + return( errCode ); + } + + updateWindow( true, true ); + + emit dataChanged(); + emit cursorChanged( mHexBuffer->cursorState() ); + emit layoutChanged( mLayout ); + return( Err_Success ); +} + + +int CHexViewWidget::newFile( const TQString &url ) +{ + int errCode = mHexBuffer->newFile( url ); + if( errCode != Err_Success ) + { + return( errCode ); + } + + initFile(); + return( Err_Success ); +} + + +int CHexViewWidget::writeFile( TQFile &file, CProgress &p ) +{ + int errCode = mHexBuffer->writeFile( file, p ); + if( errCode == Err_Success ) + { + emit fileState( mHexBuffer->fileState() ); + } + return( errCode ); +} + + +void CHexViewWidget::closeFile( void ) +{ + emit fileClosed( mHexBuffer->url() ); + mHexBuffer->closeFile(); + initFile(); +} + + + +void CHexViewWidget::initFile( void ) +{ + setStartX(0); + setStartY(0); + + mHexBuffer->cursorReset(); + mHexBuffer->setLayout( mLayout ); + mHexBuffer->setFont( mFontInfo ); + setEditMode( mEditMode ); + setColor( mColor, false ); + setCursor( mCursor, false ); + setMisc( mMisc ); + + setBackgroundColor( mHexBuffer->backgroundColor() ); + setBackgroundMode( NoBackground ); + + updateView( true, false ); + resizeEvent( 0 ); + + emit dataChanged(); + emit cursorChanged( mHexBuffer->cursorState() ); + emit fileState( mHexBuffer->fileState() ); + emit encodingChanged( mHexBuffer->encoding() ); + emit fileName( mHexBuffer->url(), mHexBuffer->hasFileName() ); + emit bookmarkChanged( mHexBuffer->bookmarkList() ); +} + + +void CHexViewWidget::setBuffer( CHexBuffer *hexBuffer ) +{ + if( hexBuffer == 0 || mHexBuffer == hexBuffer ) + { + return; + } + + unselect(); + unmark(); + + mHexBuffer = hexBuffer; + mHexBuffer->setLayout( mLayout ); + mHexBuffer->setFont( mFontInfo ); + setEditMode( mEditMode ); + setColor( mColor, false ); + setCursor( mCursor, false ); + setMisc( mMisc ); + + if( mLayout.lockLine == false ) + { + mHexBuffer->matchWidth( width() ); + } + + setBackgroundColor( hexBuffer->backgroundColor() ); + setBackgroundMode( NoBackground ); + + setEditMode( mEditMode ); + updateWindow(); + + emit dataChanged(); + emit cursorChanged( mHexBuffer->cursorState() ); + emit fileState( mHexBuffer->fileState() ); + emit encodingChanged( mHexBuffer->encoding() ); + emit layoutChanged( mLayout ); + emit inputModeChanged( mHexBuffer->inputMode() ); + emit fileName( mHexBuffer->url(), mHexBuffer->hasFileName() ); + emit bookmarkChanged( mHexBuffer->bookmarkList() ); +} + + + + +void CHexViewWidget::changeXPos( int p ) +{ + int dx = startX() - p; + setStartX(p); + + + if( TQABS(dx) < width() ) + { + scroll( dx, 0, contentsRect() ); + } + else + { + TQWidget::update(); + } + + // + // If the start position has become 0, then update the view. This + // will remove the scrollbar (if it is visible) if the textarea width + // is wider than the text. The scrollbar will then disappear under the + // mouse pointer. + // + if( startX() == 0 ) + { + updateView( false, false ); + } + +} + + +void CHexViewWidget::changeYPos( int p ) +{ + int dy = startY() - p; + setStartY(p); + + if( TQABS( dy ) < height() ) + { + scroll( 0, dy, contentsRect() ); + } + else + { + TQWidget::update(); + } + + // + // If the start position has become 0, then update the view. This + // will remove the scrollbar (if it is visible) if the textarea height + // is taller than the text. The scrollbar will then disappear under the + // mouse pointer. + // + if( startY() == 0 ) + { + updateView( false, false ); + } +} + + +void CHexViewWidget::clipboardChanged( void ) +{ + disconnect(TQApplication::clipboard(),TQT_SIGNAL(dataChanged()), + this,TQT_SLOT(clipboardChanged())); + unselect(); +} + +void CHexViewWidget::paletteChanged( void ) +{ + setColor( mColor, true ); +} + + +void CHexViewWidget::fontChanged( void ) +{ + //setFont( kapp->fixedFont, true ); +} + +void CHexViewWidget::filter( SFilterControl &fc ) +{ + int errCode = mHexBuffer->filter( fc ); + if( errCode == Err_Success ) + { + repaint(); + emit dataChanged(); + emit cursorChanged( mHexBuffer->cursorState() ); + } +} + + + +void CHexViewWidget::insert( SInsertData &id ) +{ + if( id.onCursor == false ) + { + mHexBuffer->cursorGoto( id.offset, 7 ); + } + SCursorConfig cc; + updateCursor( cc, true ); + + if( id.size == 0 ) + { + return; + } + + TQByteArray buf( id.size ); + if( buf.isNull() == true ) + { + return; + } + buf.fill( 0 ); + + if( id.pattern.size() > 0 ) + { + uint size = id.pattern.size()>buf.size() ? buf.size() : id.pattern.size(); + if( id.repeatPattern == false ) + { + memcpy( &buf[0], &id.pattern[0], size ); + if( size < buf.size() ) + { + memset( &buf[size], id.pattern[id.pattern.size()-1], buf.size()-size ); + } + } + else + { + for( uint i=0; i < buf.size(); i+= size ) + { + uint s = i+size > buf.size() ? buf.size()-i : size; + memcpy( &buf[i], &id.pattern[0], s ); + } + } + } + + insert( buf ); +} + + +void CHexViewWidget::insert( const TQByteArray &buf ) +{ + if( mHexBuffer->documentPresent() == false ) + { + emit pleaseOpenNewFile(); + if( mHexBuffer->documentPresent() == false ) + { + return; + } + } + + uint offset = mHexBuffer->cursorOffset(); + int errCode = mHexBuffer->inputAtCursor( buf, 0 ); + if( errCode == Err_Success ) + { + updateWindow( offset, true ); + emit dataChanged(); + } +} + + +void CHexViewWidget::append( const TQByteArray &buf ) +{ + if( mHexBuffer->documentPresent() == false ) + { + insert( buf ); + } + else + { + SCursorConfig cc; + cc.emulateControlButton( true ); + cursorEnd( cc ); + + int errCode = mHexBuffer->inputAtCursor( buf, 0 ); + if( errCode == Err_Success ) + { + updateWindow( true, true ); + emit dataChanged(); + } + } +} + + +void CHexViewWidget::valueOnCursor( TQByteArray &buf, uint size ) +{ + mHexBuffer->valueOnCursor( buf, size ); +} + + + +void CHexViewWidget::updateView( bool redraw, bool fixCursor ) +{ + int f2 = frameWidth() * 2; + int scrollBarCount = 0; // Number of visible scrollbars + int editWidth = 0; + int editHeight = 0; + + for( uint i=0; i < 2; i++ ) + { + editWidth = width() - f2; // Total available width + editHeight = height() - f2; // Total available height + int textWidth = dataWidth(); + int textHeight = mHexBuffer->totalHeight(); + + // + // This will move the start position of the horizontal scrollbar + // to the left (if possible) if the text width is smaller than the + // edit width. + // + if( startX() > 0 ) + { + int size = mVertScroll->isVisible() == true ? mScrollBarSize : 0; + if( startX() + editWidth - size > textWidth ) + { + int position = textWidth - editWidth + size; + setStartX( position > 0 ? position : 0 ); + #ifdef USE_NORTHWEST_GRAVITY + redraw = true; + #endif + } + } + + int tooMuchX = textWidth - editWidth; + bool horzScrollbarVisible = startX() > 0 || tooMuchX > 0 ? true : false; + if( horzScrollbarVisible == true ) + { + editHeight -= mScrollBarSize; + } + + + // + // This will move the start position of the vertical scrollbar + // to the top (if possible) if the text height is smaller than the + // edit height. + // + if( startY() > 0 ) + { + if( startY() + editHeight > textHeight ) + { + int position = textHeight - editHeight; + setStartY( position > 0 ? position : 0 ); + #ifdef USE_NORTHWEST_GRAVITY + redraw = true; + #endif + } + } + + int tooMuchY = textHeight - editHeight; + int startLine = startY() / textHeight; + + if( startLine > 0 || tooMuchY > 0 ) + { + editWidth -= mScrollBarSize; + tooMuchX += mScrollBarSize; + if( horzScrollbarVisible == false && tooMuchX > 0 ) + { + // Horizontal scrollbar will be visible after all. + editHeight -= mScrollBarSize; + tooMuchY += mScrollBarSize; + } + } + + if( tooMuchX < startX() ) { tooMuchX = startX(); } + if( tooMuchY < startY() ) { tooMuchY = startY(); } + + scrollBarCount = 0; + if( tooMuchX > 0 && documentPresent() == true ) + { + mHorzScroll->blockSignals( true ); + mHorzScroll->setGeometry( 0, editHeight+f2, editWidth+f2,mScrollBarSize); + mHorzScroll->setRange( 0, tooMuchX ); + mHorzScroll->setValue( startX() ); + mHorzScroll->setSteps(mHexBuffer->lineHeight(),editWidth-mScrollBarSize); + mHorzScroll->blockSignals( false ); + if( mHorzScroll->isVisible() == false ) { mHorzScroll->show(); } + scrollBarCount ++; + } + else + { + if( mHorzScroll->isVisible() == true ) { mHorzScroll->hide(); } + } + + if( tooMuchY > 0 && documentPresent() == true ) + { + mVertScroll->blockSignals( true ); + mVertScroll->setGeometry( editWidth+f2, 0, mScrollBarSize,editHeight+f2); + mVertScroll->setRange( 0, tooMuchY ); + mVertScroll->setValue( startY() ); + mVertScroll->setSteps(mHexBuffer->lineHeight(), + editHeight-mScrollBarSize ); + mVertScroll->blockSignals( false ); + if( mVertScroll->isVisible() == false ) { mVertScroll->show(); } + scrollBarCount ++; + } + else + { + if( mVertScroll->isVisible() == true ) { mVertScroll->hide(); } + } + + if( fixCursor == true ) + { + int position = mHexBuffer->cursorFixedPosition( startY(), height() ); + if( position != startY() ) + { + setStartY( position ); + fixCursor = false; + continue; + } + } + break; + } + + + if( scrollBarCount == 2 ) + { + mCorner->setGeometry( editWidth+f2, editHeight+f2, mScrollBarSize, + mScrollBarSize ); + mCorner->show(); + } + else + { + mCorner->hide(); + } + + + updateFrameSize(); + + if( redraw == true ) + { + TQWidget::update(); + } +} + + +void CHexViewWidget::setPalette( const TQPalette &p ) +{ + TQWidget::setPalette( p ); + mCorner->setPalette( p ); + mVertScroll->setPalette( p ); + mHorzScroll->setPalette( p ); +} + + +void CHexViewWidget::setLayout( SDisplayLayout &layout ) +{ + mLayout = layout; + mHexBuffer->setLayout( mLayout ); + updateWindow(); + + emit layoutChanged( mLayout ); + emit cursorChanged( mHexBuffer->cursorState() ); + emit textWidth( defaultWidth() ); +} + + +void CHexViewWidget::setInputMode( SDisplayInputMode &input ) +{ + mHexBuffer->setInputMode( input ); + emit inputModeChanged( mHexBuffer->inputMode() ); +} + + +void CHexViewWidget::setCursor( const SDisplayCursor &cursor, + bool /*updateDisplay*/ ) +{ + mCursor = cursor; + mHexBuffer->setCursorShapeModifier( cursor.alwaysBlockShape, + cursor.thickInsertShape ); + setupCursorTimer(); + redrawFromOffset( mHexBuffer->cursorOffset(), false ); +} + +void CHexViewWidget::setColor( const SDisplayColor &color, + bool updateDisplay ) +{ + mColor = color; + mHexBuffer->setColor( mColor ); + if( updateDisplay == true ) + { + repaint(); + } +} + +void CHexViewWidget::setFont( const SDisplayFontInfo &fontInfo, + bool updateDisplay ) +{ + mFontInfo = fontInfo; + mHexBuffer->setFont( mFontInfo ); + emit textWidth( defaultWidth() ); + if( updateDisplay == true ) + { + updateWindow(); + } +} + + + +void CHexViewWidget::setMisc( SDisplayMisc &misc ) +{ + mMisc = misc; + mHexBuffer->setUndoLevel( misc.undoLevel ); + mHexBuffer->setSoundState( misc.inputSound, misc.fatalSound ); + mHexBuffer->setBookmarkVisibility( misc.bookmarkOffsetColumn, + misc.bookmarkEditor ); + if( mHexBuffer->documentPresent() == true ) + { + TQWidget::update(); + } +} + + +void CHexViewWidget::setInsertMode( bool insertMode ) +{ + setEditMode( insertMode == true ? CHexBuffer::EditInsert : + CHexBuffer::EditReplace ); +} + + +int CHexViewWidget::setEncoding( CConversion::EMode mode, CProgress &p ) +{ + int errCode = mHexBuffer->setEncoding( mode, p ); + if( errCode == Err_Success ) + { + repaint(); + emit cursorChanged( mHexBuffer->cursorState() ); + emit encodingChanged( mHexBuffer->encoding() ); + } + return( errCode ); +} + + +void CHexViewWidget::reportEncoding( void ) +{ + emit encodingChanged( mHexBuffer->encoding() ); +} + + +void CHexViewWidget::selectAll( void ) +{ + setSelection( 0, true ); + setSelection( mHexBuffer->documentSize(), false ); + autoCopy(); + emit cursorChanged( mHexBuffer->cursorState() ); +} + +void CHexViewWidget::unselect( void ) +{ + setSelection( 0, true ); + emit cursorChanged( mHexBuffer->cursorState() ); +} + +void CHexViewWidget::unmark( void ) +{ + setMark( 0, 0, false ); +} + + +int CHexViewWidget::findFirst( SSearchControl &sc ) +{ + int errCode = mHexBuffer->findFirst( sc ); + if( errCode == Err_Success ) { updateWindow( true, false ); } + return( errCode ); +} + +int CHexViewWidget::findNext( SSearchControl &sc ) +{ + int errCode = mHexBuffer->findNext( sc ); + if( errCode == Err_Success ) { updateWindow( true, false ); } + return( errCode ); +} + +int CHexViewWidget::findWrap( SSearchControl &sc ) +{ + int errCode = mHexBuffer->findWrap( sc ); + if( errCode == Err_Success ) { updateWindow( true, false ); } + return( errCode ); +} + +int CHexViewWidget::replaceAll( SSearchControl &sc, bool init ) +{ + int errCode = mHexBuffer->replaceAll( sc, init ); + if( errCode == Err_Success ) + { + updateWindow( true, false ); + emit dataChanged(); + } + return( errCode ); +} + +int CHexViewWidget::replaceMarked( SSearchControl &sc ) +{ + int errCode = mHexBuffer->replaceMarked( sc ); + if( errCode == Err_Success ) + { + updateWindow( true, false ); + emit dataChanged(); + } + return( errCode ); +} + +int CHexViewWidget::collectStrings( CStringCollectControl &sc ) +{ + int errCode = mHexBuffer->collectStrings( sc ); + return( errCode ); +} + + +int CHexViewWidget::collectStatistic( SStatisticControl &sc, CProgress &p ) +{ + int errCode = mHexBuffer->collectStatistic( sc, p ); + return( errCode ); +} + + +void CHexViewWidget::gotoOffset( uint offset, uint bit, bool fromCursor, + bool forward ) +{ + bool reverse = forward == true ? false : true; + mHexBuffer->cursorGoto( offset, bit, reverse, fromCursor ); + updateWindow( true, false ); +} + + +void CHexViewWidget::gotoOffset( uint offset ) +{ + gotoOffset( offset, 7, true, true ); +} + + +int CHexViewWidget::print( CHexPrinter &printer, CProgress &p ) +{ + return( mHexBuffer->print( printer, p ) ); +} + + +uint CHexViewWidget::numPage( CHexPrinter &printer ) +{ + return( mHexBuffer->numPage( printer ) ); +} + + +int CHexViewWidget::exportText( const SExportText &ex, CProgress &p ) +{ + return( mHexBuffer->exportText( ex, p ) ); +} + + +int CHexViewWidget::exportHtml( const SExportHtml &ex, CProgress &p ) +{ + return( mHexBuffer->exportHtml( ex, p ) ); +} + + +int CHexViewWidget::exportCArray( const SExportCArray &ex, CProgress &p ) +{ + return( mHexBuffer->exportCArray( ex, p ) ); +} + + +void CHexViewWidget::startDrag( bool asText ) +{ + TQByteArray buf; + if( asText == true ) + { + if( mHexBuffer->copySelectedText( buf ) != Err_Success ) + { + return; + } + TQDragObject *d = new TQTextDrag( buf.data(), this ); + d->dragCopy(); + } + else + { + if( mHexBuffer->copySelectedData( buf ) != Err_Success ) + { + return; + } + TQDragObject *d = new CHexDrag( buf, this ); + d->dragCopy(); + } +} + + + +void CHexViewWidget::copy( void ) +{ + TQByteArray buf; + if( mHexBuffer->copySelectedData( buf ) != Err_Success ) + { + return; + } + disconnect(TQApplication::clipboard(),TQT_SIGNAL(dataChanged()), + this,TQT_SLOT(clipboardChanged())); + // + // Note: Do no give the CHexDrag a parent != 0. The clipboard + // owns the current dragdata and will destroy it on exit or + // when it receives a new object. If the CHexDrag has a parent + // != 0, the CHexDrag object will be destroyed when the parent + // is destroyed. We will then have a double destroy situation + // when the app. is closed (=> segfault). + // + TQApplication::clipboard()->setData(new CHexDrag( buf )); + connect(TQApplication::clipboard(),TQT_SIGNAL(dataChanged()), + this,TQT_SLOT(clipboardChanged())); +} + + +void CHexViewWidget::copyText( int columnSegment ) +{ + TQByteArray buf; + if( mHexBuffer->copySelectedText( buf, columnSegment ) != Err_Success ) + { + return; + } + + disconnect(TQApplication::clipboard(),TQT_SIGNAL(dataChanged()), + this,TQT_SLOT(clipboardChanged())); + TQApplication::clipboard()->setText( buf.data() ); + connect(TQApplication::clipboard(),TQT_SIGNAL(dataChanged()), + this,TQT_SLOT(clipboardChanged())); +} + + + +void CHexViewWidget::paste( void ) +{ + TQMimeSource *data = TQApplication::clipboard()->data(); + if( data != 0 ) + { + TQByteArray buf; + if( CHexDrag::decode( data, buf ) == true ) + { + insert( buf ); + return; + } + + TQString text; + if( TQTextDrag::decode( data, text ) == true ) + { + TQByteArray buf; + if( mClipConvert.decode( buf, text ) == true ) + { + insert( buf ); + } + return; + } + } + +} + + +void CHexViewWidget::cut( void ) +{ + copy(); // Always make a copy to the clipboard of what we remove. + bool success = mHexBuffer->cutSelection(); + if( success == false ) + { + return; + } + + updateWindow( false, true ); + emit dataChanged(); +} + + +void CHexViewWidget::undo( void ) +{ + bool success = mHexBuffer->undo(); + if( success == false ) + { + return; + } + + updateWindow( true, true ); + emit dataChanged(); +} + + +void CHexViewWidget::redo( void ) +{ + bool success = mHexBuffer->redo(); + if( success == false ) + { + return; + } + + updateWindow( true, true ); + emit dataChanged(); +} + + +void CHexViewWidget::addBookmark( int position ) +{ + int errCode = mHexBuffer->addBookmark( position ); + if( errCode != Err_Success ) + { + if( errCode == Err_ListFull ) + { + replaceBookmark(); + } + return; + } + redrawFromOffset( mHexBuffer->cursorOffset(), false ); + + emit bookmarkChanged( mHexBuffer->bookmarkList() ); +} + + + +int CHexViewWidget::bookmarkMenu( const TQString &title ) +{ + TQPtrList &list = mHexBuffer->bookmarkList(); + if( list.count() == 0 ) + { + return( -1 ); + } + + TQString text; + TDEPopupMenu *popup = new TDEPopupMenu( 0 ); + popup->insertTitle( title ); + for( uint i=0; i < list.count(); i++ ) + { + const SCursorOffset *p = list.at( i ); + if( p == 0 ) { continue; } + + text.sprintf("%04X:%04X", p->offset>>16, p->offset&0x0000FFFF ); + text.prepend( TQString("[%1] %2: ").arg(i+1).arg(i18n("Offset")) ); + popup->insertItem( text, i ); + } + + TQSize s(popup->sizeHint()); + TQPoint center( (width()-s.width())/2, (height()-s.height())/2 ); + int position = popup->exec( mapToGlobal(center) ); + delete popup; + + return( position ); +} + + +void CHexViewWidget::removeBookmark( bool all ) +{ + if( all == true ) + { + bool success = mHexBuffer->removeBookmark( -1 ); + if( success == false ) + { + return; + } + TQWidget::update(); // Redraw visisble area. + } + else + { + int position = bookmarkMenu( i18n("Remove Bookmark") ); + if( position < 0 ) + { + return; + } + + const SCursorOffset *p = mHexBuffer->bookmarkList().at(position); + uint offset = p ? p->offset : 0; + + bool success = mHexBuffer->removeBookmark( position ); + if( success == false ) + { + return; + } + + redrawFromOffset( offset, false ); + } + + emit bookmarkChanged( mHexBuffer->bookmarkList() ); +} + + +void CHexViewWidget::replaceBookmark( void ) +{ + TQPtrList &list = mHexBuffer->bookmarkList(); + if( list.count() == 0 ) + { + return; + } + + int position = bookmarkMenu( i18n("Replace Bookmark") ); + if( position < 0 ) + { + return; + } + addBookmark( position ); +} + + +void CHexViewWidget::gotoBookmark( uint position ) +{ + TQPtrList &list = mHexBuffer->bookmarkList(); + if( position >= list.count() ) + { + return; + } + + SCursorOffset *p = list.at( position ); + if( p == 0 ) + { + return; + } + + mHexBuffer->cursorGoto( p->offset, p->bit ); + updateWindow(); +} + + + +void CHexViewWidget::gotoNextBookmark( bool next ) +{ + TQPtrList &list = mHexBuffer->bookmarkList(); + uint offset = mHexBuffer->cursorOffset(); + uint diff = ~0; + + SCursorOffset *match = 0; + + // + // Note: the list is unsorted. + // + if( next == true ) + { + for( SCursorOffset *co = list.first(); co != 0; co = list.next() ) + { + if( co->offset > offset ) + { + if( co->offset-offset < diff ) + { + diff = co->offset-offset; + match = co; + } + } + } + } + else + { + for( SCursorOffset *co = list.first(); co != 0; co = list.next() ) + { + if( co->offset < offset ) + { + if( offset-co->offset < diff ) + { + diff = offset-co->offset; + match = co; + } + } + } + } + + + if( match == 0 ) + { + if( next == true ) + { + // Wrap: Locate entry with smallest offset. + offset = ~0; + for( SCursorOffset *co = list.first(); co != 0; co = list.next() ) + { + if( co->offset < offset ) + { + offset = co->offset; + match = co; + } + } + } + else + { + // Wrap: Locate entry with largest offset. + offset=0; + for( SCursorOffset *co = list.first(); co != 0; co = list.next() ) + { + if( co->offset > offset ) + { + offset = co->offset; + match = co; + } + } + } + } + + if( match != 0 ) + { + mHexBuffer->cursorGoto( match->offset, match->bit ); + updateWindow(); + } +} + + + + + + +// +// Used to test the speed of drawing +// +#include +#include +void CHexViewWidget::benchmark( void ) +{ + struct timeval t1, t2; + uint loop = 10; + + gettimeofday( &t1, 0 ); + for( uint i=0; i< loop; i++ ) + { + paintText( contentsRect(), false ); + } + gettimeofday( &t2, 0 ); + + + uint area = width() * height(); + uint last = (t2.tv_sec-t1.tv_sec) * 1000000 + (t2.tv_usec - t1.tv_usec); + + kdDebug(1501) << "Duration: " << (float)last/ 1000000.0 << endl; + kdDebug(1501) << "Duration/loop: " << (float)last/ (1000000.0*(float)loop) << endl; + kdDebug(1501) << "Area: " << area << endl; + kdDebug(1501) << "Loop: " << loop << endl; +} + + + + + +void CHexViewWidget::resizeEvent( TQResizeEvent * ) +{ + setTextBufferSize(); + + if( mLayout.lockLine == true ) + { + updateView( false, false ); + #ifdef USE_NORTHWEST_GRAVITY + paintFrame(); + #endif + } + else + { + bool state = mVertScroll->isVisible(); + int size = (state == true ? mScrollBarSize : 0) + frameWidth()*2; + #ifdef USE_NORTHWEST_GRAVITY + int w = dataWidth(); + #endif + + bool bufferChanged = mHexBuffer->matchWidth( width() - size ); + updateView( false, bufferChanged ); + + if( mVertScroll->isVisible() != state ) + { + size = (mVertScroll->isVisible() ? mScrollBarSize : 0) + frameWidth()*2; + bufferChanged = mHexBuffer->matchWidth( width() - size ); + updateView( false, bufferChanged ); + } + + #ifdef USE_NORTHWEST_GRAVITY + if( w != dataWidth() ) + { + TQWidget::update(); + } + else + { + paintFrame(); + } + #endif + } +} + + + +void CHexViewWidget::paintEvent( TQPaintEvent *e ) +{ + paintText( e->rect(), true ); +} + + + +void CHexViewWidget::updateFrameSize( void ) +{ + int w = width() - (mVertScroll->isVisible() ? mScrollBarSize : 0); + if( w < 0 ) { w = 0; } + int h = height() - (mHorzScroll->isVisible() ? mScrollBarSize : 0); + if( h < 0 ) { h = 0; } + + setFrameRect( TQRect(0,0,w,h) ); +} + + + +void CHexViewWidget::paintFrame( void ) +{ + TQPainter paint; + paint.begin( this ); + drawFrame( &paint ); + paint.end(); +} + + + +void CHexViewWidget::drawFrame( TQPainter *p ) +{ + // + // 2000-01-10 Espen Sand + // I want to display the frame with a custom color whenever the widget + // accepts a drop. The setPalette() function causes quite a bit of flicker + // in the scrollbars (even when PropagationMode is NoChildren), so I + // draw the frame manually when it can accept a drop. Note that the + // code below is for the frame shape "TQFrame::WinPanel|TQFrame::Plain" + // + if( mDropHighlight == true ) + { + qDrawPlainRect( p, frameRect(), TQColor("SteelBlue2"), lineWidth() ); + } + else + { + TQFrame::drawFrame(p); // Use standard drawFrame + } +} + + + +void CHexViewWidget::keyPressEvent( TQKeyEvent *e ) +{ + SCursorConfig cc; + cc.state = e->state(); + + // + // Some special actions that we have to trap here + // + if( e->state() & ControlButton ) + { + switch( e->key() ) + { + case Key_Space: + e->accept(); + toggleEditor(); + return; + break; + + case Key_1: + e->accept(); + cursorStep( cc, 1 ); + return; + break; + + case Key_2: + e->accept(); + cursorStep( cc, 2 ); + return; + break; + + case Key_4: + e->accept(); + cursorStep( cc, 4 ); + return; + break; + + case Key_8: + e->accept(); + cursorStep( cc, 8 ); + return; + break; + } + } + + if( e->state() & AltButton ) + { + if( e->key() == Key_Left || e->key() == Key_Right ) + { + emit pleaseStepFile( e->key() == Key_Left ? true : false ); + e->accept(); + } + else if( e->key() == Key_Up || e->key() == Key_Down ) + { + gotoNextBookmark( e->key() == Key_Down ? true : false ); + e->accept(); + } + else + { + e->ignore(); + } + return; + } + + switch ( e->key() ) + { + case Key_Left: + cursorLeft( cc ); + break; + + case Key_Right: + cursorRight( cc ); + break; + + case Key_Up: + cursorUp( cc ); + break; + + case Key_Down: + cursorDown( cc ); + break; + + case Key_Home: + cursorHome( cc ); + break; + + case Key_End: + cursorEnd( cc ); + break; + + case Key_Next: + cursorPageDown( cc ); + break; + + case Key_Prior: + cursorPageUp( cc ); + break; + + case Key_Insert: + cursorInsert( cc ); + break; + + case Key_Delete: + cursorDelete( cc ); + break; + + case Key_Backspace: + cursorBackspace( cc ); + break; + + default: + if( (e->text()[0]).isPrint() == true ) + { + cursorInput( TQString(e->text())[0] ); + } + break; + } + + e->accept(); +} + + +void CHexViewWidget::keyReleaseEvent( TQKeyEvent *e ) +{ + if( ( e->state() & ShiftButton ) && shiftButtonState() == false ) + { + // + // The shift button was pressed when event was triggered, but is + // now released. I use this as a sign to copy selected data to the + // clipboard. + // + autoCopy(); + } +} + + +void CHexViewWidget::mousePressEvent( TQMouseEvent *e ) +{ + // + // The RMB popup menu is managed by the KContextMenuManager + // + + if( e->button() == Qt::LeftButton ) + { + if( e->state() & ControlButton ) + { + if( KContextMenuManager::showOnButtonPress() == true + && mDocumentMenu != 0 ) + { + mDocumentMenu->popup( e->globalPos() ); + } + } + else + { + bool cellLevel = mMisc.cursorJump == false; + setCursorPosition( e->x(), e->y(), true, cellLevel ); + } + } + else if( e->button() == Qt::MidButton ) + { + paste(); + } + +} + +void CHexViewWidget::mouseMoveEvent( TQMouseEvent *e ) +{ + if( e->state() & Qt::LeftButton ) + { + if( mDragManager->start( e ) == false ) + { + bool cellLevel = mMisc.cursorJump == false||e->state() & ControlButton; + setCursorPosition( e->x(), e->y(), false, cellLevel ); + } + } +} + +void CHexViewWidget::mouseReleaseEvent( TQMouseEvent *e ) +{ + // + // The RMB popup menu is managed by the KContextMenuManager + // + + if( e->button() == Qt::LeftButton ) + { + if( e->state() & ControlButton ) + { + if( KContextMenuManager::showOnButtonPress() == false + && mDocumentMenu != 0 ) + { + mDocumentMenu->popup( e->globalPos() ); + } + } + else + { + if( mDragManager->clear() == true ) + { + // Remove any selection + SCursorConfig cc; + cc.setKeepSelection( false ); + updateCursor( cc, true ); + } + else + { + mHexBuffer->cursorResetEditArea(); + autoCopy(); + } + } + } + +} + + + +void CHexViewWidget::wheelEvent( TQWheelEvent *e ) +{ + if( mVertScroll->isVisible() == true ) + { + TQApplication::sendEvent( mVertScroll, e ); + } +} + + +void CHexViewWidget::dragEnterEvent( TQDragEnterEvent *e ) +{ + if( TQTextDrag::canDecode(e) || CHexDrag::canDecode(e) || + KURLDrag::canDecode(e)) + { + e->accept(); + setDropHighlight( true ); + } +} + + +void CHexViewWidget::dragLeaveEvent( TQDragLeaveEvent * ) +{ + setDropHighlight( false ); +} + + +void CHexViewWidget::dragMoveEvent( TQDragMoveEvent *e ) +{ + // + // Move the cursor if we are dragging (readable) text or binary + // data. Note: the TQTextDrag::canDecode() will return true if we + // are dragging a file so we have to test for KURLDrag::canDecode() + // first. + // + + if( KURLDrag::canDecode(e) == true ) + { + return; + } + + if( TQTextDrag::canDecode(e) == true || CHexDrag::canDecode(e) == true ) + { + int x = startX() + e->pos().x(); + int y = startY() + e->pos().y(); + if( mHexBuffer->setCursorPosition( x, y, false, false ) == true ) + { + SCursorConfig cc; + cc.setKeepSelection( true ); + updateCursor( cc, false, false ); + } + } +} + + +void CHexViewWidget::dropEvent( TQDropEvent *e ) +{ + TQMimeSource &m = *(TQDropEvent*)e; + setDropHighlight( false ); + + KURL::List list; + if( KURLDrag::decode( &m, list ) == true ) + { + // + // This widget can not itself open a file so it will simply pass + // the request to a parent that can (hopefully) do this + // + for( KURL::List::ConstIterator it = list.begin(); it != list.end(); it++ ) + { + emit pleaseOpenFile( (*it).url(), true, 0 ); + } + return; + } + + TQByteArray buf; + if( CHexDrag::decode( &m, buf ) == true ) + { + insert( buf ); + return; + } + + TQString text; + if( TQTextDrag::decode( &m, text ) == true ) + { + bool success = mClipConvert.decode( buf, text ); + if( success == true ) + { + insert( buf ); + } + return; + } + +} + + +void CHexViewWidget::showEvent( TQShowEvent * ) +{ + // Currently we do nothing here. +} + + + + +void CHexViewWidget::timerEvent( TQTimerEvent *e ) +{ + if( e->timerId() == mCursorTimerId ) + { + if( hasFocus() == true ) + { + if( mCursor.alwaysVisible == true ) + { + mShowCursor = true; + } + else + { + mShowCursor = mShowCursor == true ? false : true; + } + } + else if( mCursor.focusMode == SDisplayCursor::hide ) + { + mShowCursor = false; + } + else if( mCursor.focusMode == SDisplayCursor::stopBlinking ) + { + mShowCursor = true; + } + else + { + mShowCursor = mShowCursor == true ? false : true; + } + mHexBuffer->setShowCursor( mShowCursor ); + paintCursor( CHexBuffer::cursor_curr ); + } +} + +void CHexViewWidget::focusInEvent( TQFocusEvent * ) +{ + setupCursorTimer(); + paintCursor( CHexBuffer::cursor_curr ); +} + +void CHexViewWidget::focusOutEvent( TQFocusEvent * ) +{ + if( mCursor.focusMode != SDisplayCursor::ignore ) + { + setupCursorTimer(); + paintCursor( CHexBuffer::cursor_curr ); + } +} + + +void CHexViewWidget::setSelection( uint offset, bool init ) +{ + bool selectionChanged = mHexBuffer->selectionSet( offset, init ); + if( selectionChanged == true ) + { + uint off1, off2; + mHexBuffer->selectionStartChange( off1, off2 ); + if( off1 != off2 ) + { + redrawInterval( off1, off2 ); + } + mHexBuffer->selectionStopChange( off1, off2 ); + if( off1 != off2 ) + { + redrawInterval( off1, off2 ); + } + } + mHexBuffer->selectionSyncronize(); +} + + + +void CHexViewWidget::setMark( uint offset, uint size, bool moveCursor ) +{ + bool changed; + if( size == 0 ) + { + changed = mHexBuffer->markRemove(); + } + else + { + mHexBuffer->markSet( offset, size ); + if( moveCursor == true ) + { + changed = false; + gotoOffset( offset, 7, false, true ); + } + else + { + changed = true; + } + } + + if( changed == true ) + { + uint off1, off2; + mHexBuffer->markStartChange( off1, off2 ); + if( off1 != off2 ) + { + redrawInterval( off1, off2 ); + } + + mHexBuffer->markStopChange( off1, off2 ); + if( off1 != off2 ) + { + redrawInterval( off1, off2 ); + } + } + mHexBuffer->markSyncronize(); +} + + + +void CHexViewWidget::setCursorPosition(int x, int y, bool init, bool cellLevel) +{ + x += startX(); + y += startY(); + + if( mHexBuffer->setCursorPosition( x, y, init, cellLevel ) == false ) + { + if( init == true ) + { + unselect(); + unmark(); + } + } + else if( init == false ) + { + SCursorConfig cc; + cc.setKeepSelection( true ); + updateCursor( cc, false ); + } + else + { + SCursorConfig cc; + if( mHexBuffer->cursorInsideSelection() == true ) + { + mDragManager->setup( x - startX(), y - startY() ); + cc.setKeepSelection( true ); + updateCursor( cc, true, false ); + } + else + { + cc.setKeepSelection( false ); + updateCursor( cc, true ); + } + } +} + + + +void CHexViewWidget::redrawInterval( uint startOffset, uint stopOffset ) +{ + // + // Can be improved, I repaint the entire line even if the offsets + // only specify one byte. + // + uint lineStart = mHexBuffer->calculateLine( startOffset ); + uint lineStop = mHexBuffer->calculateLine( stopOffset ); + if( lineStart <= lineStop ) + { + redrawLines( lineStart, lineStop - lineStart + 1 ); + } + else + { + redrawLines( lineStop, lineStart - lineStop + 1 ); + } +} + + + +void CHexViewWidget::redrawLines( uint docLine, int numLine ) +{ + int lineHeight = mHexBuffer->lineHeight(); + int lineOffset = startY() / lineHeight; + + // FIXME: startY() should return uint + if( (uint)lineOffset > docLine ) + { + numLine -= (lineOffset-docLine); + if( numLine <= 0 ) { return; } + docLine = lineOffset; + } + + int t = docLine * lineHeight - startY() + frameWidth(); + if( mEditMode == CHexBuffer::EditInsert ) + { + TQRect r = contentsRect(); + r.setTop( t ); + paintText( contentsRect().intersect( r ), false ); + } + else + { + int h = (numLine + (startY() % lineHeight ? 1 : 0)) * lineHeight; + TQRect r( contentsRect().left(), t, contentsRect().width(), h ); + paintText( contentsRect().intersect( r ), false ); + } +} + + + +void CHexViewWidget::redrawFromOffset( uint offset, bool finishWindow ) +{ + int lineHeight = mHexBuffer->lineHeight(); + uint docLine = mHexBuffer->calculateLine( offset ); + + int t = docLine * lineHeight - startY() + frameWidth(); + if( finishWindow == true ) + { + TQRect r = contentsRect(); + r.setTop( t ); + paintText( contentsRect().intersect( r ), false ); + } + else + { + int h = t + lineHeight; + TQRect r( contentsRect().left(), t, contentsRect().width(), h ); + paintText( contentsRect().intersect( r ), false ); + } +} + + + + +void CHexViewWidget::paintText( const TQRect &rect, bool expand ) +{ + TQRect r = rect; + + if( expand == true ) + { + #ifdef USE_NORTHWEST_GRAVITY + r.setLeft( r.left() - frameWidth() ); + r.setTop( r.top() - frameWidth() ); + #endif + } + + if( contentsRect().contains( r ) == false ) + { + paintFrame(); + if( r.left() < frameWidth() ) { r.setLeft( frameWidth() ); } + if( r.top() < frameWidth() ) { r.setTop( frameWidth() ); } + } + + int maxX = width() - frameWidth() - 1 - + (mVertScroll->isVisible() ? mScrollBarSize : 0); + int maxY = height() - frameWidth() - 1 - + (mHorzScroll->isVisible() ? mScrollBarSize : 0); + + if( r.right() > maxX ) { r.setRight( maxX ); } + if( r.bottom() > maxY ) { r.setBottom( maxY ); } + + TQPainter paint( &mTextBuffer ); + paint.setFont( mHexBuffer->font() ); + + int lineHeight = mHexBuffer->lineHeight(); + int docLine = (startY() + r.y() - frameWidth()) / lineHeight; + if( docLine < 0 ) { docLine = 0; } + int y = docLine * lineHeight - startY(); + int yMax = r.height(); + int xMax = r.x() + r.width(); + + y += frameWidth(); + + int s = 0; + int d = r.y()-y; + int h; + while( yMax > 0 ) + { + mHexBuffer->drawText( paint, docLine, startX()-frameWidth(), r.x(), xMax ); + + if( d != 0 ) + { + h = lineHeight - d; + if( h > yMax ) { h = yMax; } + } + else + { + h = yMax > lineHeight ? lineHeight : yMax; + } + bitBlt( this, r.x(), r.y()+s, &mTextBuffer, r.x(), d, r.width(), h ); + + s += h; + yMax -= h; + docLine += 1; + d = 0; + } + paint.end(); +} + + + +void CHexViewWidget::paintCursor( int cursorMode ) +{ + TQPainter paint; + paint.begin( &mTextBuffer ); + paint.setFont( mHexBuffer->font() ); + + int f = frameWidth(); + + if( cursorMode == CHexBuffer::cursor_prev ) + { + int line = mHexBuffer->prevCursorLine(); + SCursorPosition p; + + mHexBuffer->prevCursor( CHexBuffer::edit_primary, p ); + mHexBuffer->drawText( paint, line, startX(), p.x, p.x + p.w ); + if( p.y + p.h + f > contentsRect().bottom() ) + p.h = contentsRect().bottom() - p.y - f + 1; + bitBlt( this, p.x+f, p.y+f, &mTextBuffer, p.x, 0, p.w, p.h ); + + mHexBuffer->prevCursor( CHexBuffer::edit_secondary, p ); + mHexBuffer->drawText( paint, line, startX(), p.x, p.x + p.w ); + if( p.y + p.h + f > contentsRect().bottom() ) + p.h = contentsRect().bottom() - p.y - f + 1; + bitBlt( this, p.x+f, p.y+f, &mTextBuffer, p.x, 0, p.w, p.h ); + } + else + { + int line = mHexBuffer->cursorLine(); + SCursorPosition p; + + mHexBuffer->currCursor( CHexBuffer::edit_primary, p ); + mHexBuffer->drawText( paint, line, startX(), p.x, p.x + p.w ); + if( p.y + p.h + f > contentsRect().bottom() ) + p.h = contentsRect().bottom() - p.y - f + 1; + bitBlt( this, p.x+f, p.y+f, &mTextBuffer, p.x, 0, p.w, p.h ); + + mHexBuffer->currCursor( CHexBuffer::edit_secondary, p ); + mHexBuffer->drawText( paint, line, startX(), p.x, p.x + p.w ); + if( p.y + p.h + f > contentsRect().bottom() ) + p.h = contentsRect().bottom() - p.y - f + 1; + bitBlt( this, p.x+f, p.y+f, &mTextBuffer, p.x, 0, p.w, p.h ); + } + + paint.end(); +} + + + + + +void CHexViewWidget::updateCursor( SCursorConfig &cc, bool always, + bool touchSelection ) +{ + if( mHexBuffer->cursorChanged() == false && always == false ) + { + return; + } + + // + // Make blinking (and perhaps invisible) cursor visible + // + setupCursorTimer(); + + // + // Clear cursor at old location + // + paintCursor( CHexBuffer::cursor_prev ); + + // + // Compute the new position of the vertical scroll bar. + // + int position, h; + if( cc.controlButton() == true ) + { + // + // The cursor should stay fixed (if possible) in the window while + // the text is scrolled (e.g., PageUp/Down behavior). The position + // of the vertical scrollbar must change just as much as the cursor + // has changed in the vertical direction. + // + h = frameWidth()*2; + h += mHorzScroll->isVisible() == false ? 0 : mScrollBarSize; + position = mHexBuffer->cursorFixedPosition( startY(), height()-h ); + changeYPos( position ); + } + else + { + h = frameWidth()*2; + h += mHorzScroll->isVisible() == false ? 0 : mScrollBarSize; + position = mHexBuffer->cursorChangePosition( startY(), height()-h ); + changeYPos( position ); + } + + // + // Paint cursor at new location and update the vertical scroll bar. + // + paintCursor( CHexBuffer::cursor_curr ); + mVertScroll->blockSignals( true ); + mVertScroll->setValue( position ); + mVertScroll->blockSignals( false ); + + if( touchSelection == true ) + { + setSelection( mHexBuffer->cursorOffset(), cc.removeSelection() ); + unmark(); + } + emit cursorChanged( mHexBuffer->cursorState() ); +} + + + +void CHexViewWidget::toggleEditor( void ) +{ + bool success = mHexBuffer->toggleEditor(); + if( success == false ) + { + return; + } + + SCursorConfig cc; + updateCursor( cc, true ); + redrawFromOffset( mHexBuffer->cursorOffset(), false ); +} + + +void CHexViewWidget::cursorStep( SCursorConfig &cc, uint stepSize ) +{ + mHexBuffer->cursorStep( stepSize, cc.altButton() ? false : true, true ); + cc.emulateControlButton( false ); + updateCursor( cc ); +} + + + +void CHexViewWidget::cursorLeft( SCursorConfig &cc ) +{ + bool cellLevel = mMisc.cursorJump == false || cc.controlButton(); + cc.emulateControlButton( false ); + mHexBuffer->cursorLeft( cellLevel ); + updateCursor( cc, cellLevel ); +} + + +void CHexViewWidget::cursorRight( SCursorConfig &cc ) +{ + bool cellLevel = mMisc.cursorJump == false || cc.controlButton(); + cc.emulateControlButton( false ); + mHexBuffer->cursorRight( cellLevel ); + updateCursor( cc, cellLevel ); +} + + + +void CHexViewWidget::cursorUp( SCursorConfig &cc ) +{ + mHexBuffer->cursorUp( 1 ); + updateCursor( cc ); +} + + +void CHexViewWidget::cursorDown( SCursorConfig &cc ) +{ + mHexBuffer->cursorDown( 1 ); + updateCursor( cc ); +} + + +void CHexViewWidget::cursorHome( SCursorConfig &cc ) +{ + mHexBuffer->cursorHome( cc.controlButton() ); + updateCursor( cc ); +} + + +void CHexViewWidget::cursorEnd( SCursorConfig &cc ) +{ + mHexBuffer->cursorEnd( cc.controlButton() ); + updateCursor( cc ); +} + + +void CHexViewWidget::cursorPageDown( SCursorConfig &cc ) +{ + mHexBuffer->cursorDown( height() / mHexBuffer->lineHeight() ); + cc.emulateControlButton( true ); + updateCursor( cc ); +} + + +void CHexViewWidget::cursorPageUp( SCursorConfig &cc ) +{ + mHexBuffer->cursorUp( height() / mHexBuffer->lineHeight() ); + cc.emulateControlButton( true ); + updateCursor( cc ); +} + + +void CHexViewWidget::cursorInsert( SCursorConfig &/*cc*/ ) +{ + // Toggle mode + setEditMode( mEditMode == CHexBuffer::EditInsert ? + CHexBuffer::EditReplace : CHexBuffer::EditInsert ); +} + + + +void CHexViewWidget::cursorDelete( SCursorConfig &/*cc*/ ) +{ + int numLine = mHexBuffer->numLines(); + + bool success = mHexBuffer->removeAtCursor( false ); + if( success == false ) + { + return; + } + + updateWindow( numLine == mHexBuffer->numLines() ? false : true, true ); + emit dataChanged(); +} + + +void CHexViewWidget::cursorBackspace( SCursorConfig &/*cc*/ ) +{ + int numLine = mHexBuffer->numLines(); + + bool success = mHexBuffer->removeAtCursor( true ); + if( success == false ) + { + return; + } + + updateWindow( numLine == mHexBuffer->numLines() ? false : true, true ); + emit dataChanged(); +} + + +void CHexViewWidget::cursorInput( TQChar c ) +{ + uint cursorLine = mHexBuffer->cursorLine(); + bool success = mHexBuffer->inputAtCursor( c ); + if( success == false ) + { + return; + } + + updateWindow( cursorLine ); + emit dataChanged(); +} + + +void CHexViewWidget::setEditMode( CHexBuffer::EEditMode mode ) +{ + mEditMode = mode; + mHexBuffer->setEditMode( mEditMode, mCursor.alwaysBlockShape, + mCursor.thickInsertShape ); + setupCursorTimer(); + + // + // This will redraw the current line (which contains the cursor) + // + redrawFromOffset( mHexBuffer->cursorOffset(), false ); + emit editMode( mEditMode ); +} + + +void CHexViewWidget::setDropHighlight( bool dropHighlight ) +{ + mDropHighlight = dropHighlight; + if( mDropHighlight == true ) + { + // + // 2000-01-10 Espen Sand + // Highlight. I have reimplemented TQFrame::drawFrame(TQPainter *) + // to support a custom frame color. I assume the frame shape is + // "TQFrame::WinPanel|TQFrame::Plain" in that function. + // + setFrameStyle( TQFrame::WinPanel|TQFrame::Plain ); + } + else + { + setFrameStyle( TQFrame::WinPanel|TQFrame::Sunken ); + } +} + + + +#include "hexviewwidget.moc" -- cgit v1.2.1