You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeutils/khexedit/hexeditorwidget.cpp

2444 lines
62 KiB

/*
* 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 <iostream>
#include <unistd.h>
#undef Unsorted
#include <tdefiledialog.h>
#include <tdeglobalsettings.h>
#include <tdeio/netaccess.h>
#include <tdelocale.h>
#include <tdemessagebox.h>
#include <tdetempfile.h>
#include <kpushbutton.h>
#include <kstdguiitem.h>
#include "chartabledialog.h"
#include "converterdialog.h"
#include "dialog.h"
#include "exportdialog.h"
#include "fileinfodialog.h"
#include "hexeditorwidget.h"
#include "hexerror.h"
#include "optiondialog.h"
#include "printdialogpage.h"
#include "stringdialog.h"
CHexEditorWidget::CHexEditorWidget( TQWidget *parent, const char *name )
: TQWidget( parent, name )
{
CHexBuffer *hexBuffer = new CHexBuffer;
if( hexBuffer == 0 ) { return; }
mDocumentList.setAutoDelete( true );
mDocumentList.append( hexBuffer );
mUntitledCount = 1;
mHexView = new CHexViewWidget( this, "hexview", hexBuffer );
if( mHexView == 0 || mHexView->widgetValid() == false ) { return; }
connect( mHexView, TQT_SIGNAL(pleaseOpenNewFile()), TQT_SLOT( newFile()) );
connect( mHexView, TQT_SIGNAL(pleaseOpenFile( const TQString&, bool, uint )),
TQT_SLOT( open(const TQString&, bool, uint)) );
connect( mHexView, TQT_SIGNAL(pleaseStepFile(bool)), TQT_SLOT( stepFile(bool)) );
connect( kapp, TQT_SIGNAL( tdedisplayFontChanged() ), TQT_SLOT( fontChanged() ) );
connect( kapp, TQT_SIGNAL( tdedisplayPaletteChanged() ),TQT_SLOT( paletteChanged()) );
connect( mHexView, TQT_SIGNAL( layoutChanged( const SDisplayLayout & ) ),
TQT_SLOT( layoutChanged( const SDisplayLayout & ) ) );
connect( mHexView, TQT_SIGNAL( inputModeChanged( const SDisplayInputMode & ) ),
this, TQT_SLOT( inputModeChanged( const SDisplayInputMode & ) ) );
mHexView->setFocus();
setBackgroundColor( palette().active().base() );
mProgressBusy = false;
mGotoDialog = 0;
mFindDialog = 0;
mReplaceDialog = 0;
mInsertDialog = 0;
mFilterDialog = 0;
mOptionDialog = 0;
mStringDialog = 0;
mCharTableDialog = 0;
mFileInfoDialog = 0;
mExportDialog = 0;
mConverterDialog = 0;
mFindNavigatorDialog = 0;
mReplacePromptDialog = 0;
}
CHexEditorWidget::~CHexEditorWidget( void )
{
delete mHexView;
delete mGotoDialog;
delete mFindDialog;
delete mReplaceDialog;
delete mInsertDialog;
delete mFilterDialog;
delete mOptionDialog;
delete mStringDialog;
delete mCharTableDialog;
delete mFileInfoDialog;
delete mExportDialog;
delete mConverterDialog;
delete mFindNavigatorDialog;
delete mReplacePromptDialog;
}
void CHexEditorWidget::initialize( void )
{
setColor( mDisplayState.color );
setFont( mDisplayState.font );
mHexView->setMisc( mDisplayState.misc );
mHexView->setCursor( mDisplayState.cursor, false );
mHexView->setLayout( mDisplayState.layout );
mHexView->setInputMode( mDisplayState.input );
mHexView->setInsertMode( mDisplayState.misc.insertMode );
}
void CHexEditorWidget::writeConfiguration( TDEConfig &config )
{
SDisplayLayout &layout = mDisplayState.layout;
config.setGroup( "Display Options" );
config.writeEntry( "PrimaryMode", layout.primaryModeString() );
config.writeEntry( "SecondaryMode", layout.secondaryModeString() );
config.writeEntry( "OffsetMode", layout.offsetModeString() );
config.writeEntry( "OffsetVisible", layout.offsetVisible );
config.writeEntry( "PrimaryUpperCase", layout.primaryUpperCase );
config.writeEntry( "OffsetUpperCase", layout.offsetUpperCase );
config.writeEntry( "LineSize", layout.lineSize );
config.writeEntry( "ColumnSize", layout.columnSize );
config.writeEntry( "LockLine", layout.lockLine );
config.writeEntry( "LockColumn", layout.lockColumn );
config.writeEntry( "ColumnCharSpace", layout.columnCharSpace );
config.writeEntry( "ColumnSpacing", layout.columnSpacing );
config.writeEntry( "SeparatorMarginWidth", layout.separatorMarginWidth );
config.writeEntry( "EdgeMarginWidth", layout.edgeMarginWidth );
config.writeEntry( "LeftSeparatorWidth", layout.leftSeparatorWidth );
config.writeEntry( "RightSeparatorWidth", layout.rightSeparatorWidth );
config.writeEntry( "GridMode", layout.gridModeString() );
SDisplayLine &line = mDisplayState.line;
config.setGroup( "Line Size" );
config.writeEntry( "Hexadecimal",line.lineSize[SDisplayLine::hexadecimal] );
config.writeEntry( "Decimal", line.lineSize[SDisplayLine::decimal] );
config.writeEntry( "Octal", line.lineSize[SDisplayLine::octal] );
config.writeEntry( "Binary", line.lineSize[SDisplayLine::binary] );
config.writeEntry( "TextOnly", line.lineSize[SDisplayLine::textOnly] );
config.setGroup( "Column Size" );
config.writeEntry( "Hexadecimal",line.columnSize[SDisplayLine::hexadecimal]);
config.writeEntry( "Decimal", line.columnSize[SDisplayLine::decimal] );
config.writeEntry( "Octal", line.columnSize[SDisplayLine::octal] );
config.writeEntry( "Binary", line.columnSize[SDisplayLine::binary] );
config.writeEntry( "TextOnly", line.columnSize[SDisplayLine::textOnly] );
SDisplayColor &color = mDisplayState.color;
config.setGroup( "Display Colors" );
config.writeEntry( "UseSystemColor", color.useSystemColor );
config.writeEntry( "TextBg", color.textBg );
config.writeEntry( "SecondTextBg", color.secondTextBg );
config.writeEntry( "OffsetBg", color.offsetBg );
config.writeEntry( "InactiveBg", color.inactiveBg );
config.writeEntry( "PrimaryFg1", color.primaryFg[0] );
config.writeEntry( "PrimaryFg2", color.primaryFg[1] );
config.writeEntry( "OffsetFg", color.offsetFg );
config.writeEntry( "SecondaryFg", color.secondaryFg );
config.writeEntry( "MarkBg", color.markBg );
config.writeEntry( "MarkFg", color.markFg );
config.writeEntry( "LeftSeparatorFg", color.leftSeparatorFg );
config.writeEntry( "RightSeparatorFg", color.leftSeparatorFg );
config.writeEntry( "NonPrintFg", color.nonPrintFg );
config.writeEntry( "CursorBg", color.cursorBg );
config.writeEntry( "CursorFg", color.cursorFg );
config.writeEntry( "GridFg", color.gridFg );
config.writeEntry( "BookmarkBg", color.bookmarkBg );
config.writeEntry( "BookmarkFg", color.bookmarkFg );
SDisplayFont &font = mDisplayState.font;
config.setGroup( "Display Font" );
config.writeEntry( "UseSystemFont", font.useSystemFont );
config.writeEntry( "LocalFont", font.localFont );
config.writeEntry( "NonPrintChar", font.nonPrintChar.unicode() );
SDisplayCursor &cursor = mDisplayState.cursor;
config.setGroup( "Display Cursor" );
config.writeEntry( "NeverBlink", cursor.alwaysVisible );
config.writeEntry( "AlwaysBlockShape", cursor.alwaysBlockShape );
config.writeEntry( "ThickInsertShape", cursor.thickInsertShape );
config.writeEntry( "FocusMode", cursor.focusModeString() );
config.writeEntry( "Interval", cursor.interval );
SDisplayMisc &misc = mDisplayState.misc;
config.setGroup( "Display Misc" );
config.writeEntry( "UndoLevel", misc.undoLevel );
config.writeEntry( "OpenFile", misc.openFileString() );
config.writeEntry( "InputSound", misc.inputSound );
config.writeEntry( "FatalSound", misc.fatalSound );
config.writeEntry( "AutoCopyToClipboard", misc.autoCopyToClipboard );
config.writeEntry( "InsertMode", misc.insertMode );
config.writeEntry( "WriteProtect", misc.writeProtect );
config.writeEntry( "ConfirmWrap", misc.confirmWrap );
config.writeEntry( "CursorJump", misc.cursorJump );
config.writeEntry( "MakeBackup", misc.makeBackup );
config.writeEntry( "ConfirmThreshold", misc.confirmThreshold );
config.writeEntry( "ThresholdValue", misc.thresholdValue );
config.writeEntry( "DiscardRecent", misc.discardRecent );
config.writeEntry( "GotoOnStartup", misc.gotoOnStartup );
config.writeEntry( "GotoOnReload", misc.gotoOnReload );
config.writeEntry( "ShowBookmarkInOffsetColumn", misc.bookmarkOffsetColumn );
config.writeEntry( "ShowBookmarkInEditor", misc.bookmarkEditor );
if( mExportDialog != 0 )
{
mExportDialog->writeConfiguration();
}
}
void CHexEditorWidget::readConfiguration( TDEConfig &config )
{
SDisplayLayout &layout = mDisplayState.layout;
config.setGroup( "Display Options" );
layout.setPrimaryMode( config.readEntry("PrimaryMode") );
layout.setSecondaryMode( config.readEntry("SecondaryMode") );
layout.setOffsetMode( config.readEntry("OffsetMode") );
layout.offsetVisible = config.readBoolEntry(
"OffsetVisible", layout.offsetVisible );
layout.primaryUpperCase = config.readBoolEntry(
"PrimaryUpperCase", layout.primaryUpperCase );
layout.offsetUpperCase = config.readBoolEntry(
"OffsetUpperCase", layout.offsetUpperCase );
layout.lineSize = config.readNumEntry(
"LineSize", layout.lineSize );
layout.columnSize = config.readNumEntry(
"ColumnSize", layout.columnSize );
layout.lockLine = config.readBoolEntry(
"LockLine", layout.lockLine );
layout.lockColumn = config.readBoolEntry(
"LockColumn", layout.lockColumn );
layout.columnCharSpace = config.readBoolEntry(
"ColumnCharSpace", layout.columnCharSpace );
layout.columnSpacing = config.readNumEntry(
"ColumnSpacing", layout.columnSpacing );
layout.separatorMarginWidth = config.readNumEntry(
"SeparatorMarginWidth", layout.separatorMarginWidth );
layout.edgeMarginWidth = config.readNumEntry(
"EdgeMarginWidth", layout.edgeMarginWidth );
layout.leftSeparatorWidth = config.readNumEntry(
"LeftSeparatorWidth", layout.leftSeparatorWidth );
layout.rightSeparatorWidth = config.readNumEntry(
"RightSeparatorWidth", layout.rightSeparatorWidth );
layout.setGridMode( config.readEntry("GridMode") );
SDisplayLine &line = mDisplayState.line;
config.setGroup( "Line Size" );
line.lineSize[SDisplayLine::hexadecimal] = config.readUnsignedNumEntry(
"Hexadecimal", line.lineSize[SDisplayLine::hexadecimal] );
line.lineSize[SDisplayLine::decimal] = config.readUnsignedNumEntry(
"Decimal", line.lineSize[SDisplayLine::decimal] );
line.lineSize[SDisplayLine::octal] = config.readUnsignedNumEntry(
"Octal", line.lineSize[SDisplayLine::octal] );
line.lineSize[SDisplayLine::binary] = config.readUnsignedNumEntry(
"Binary", line.lineSize[SDisplayLine::binary] );
line.lineSize[SDisplayLine::textOnly] = config.readUnsignedNumEntry(
"TextOnly", line.lineSize[SDisplayLine::textOnly] );
config.setGroup( "Column Size" );
line.columnSize[SDisplayLine::hexadecimal] = config.readUnsignedNumEntry(
"Hexadecimal", line.columnSize[SDisplayLine::hexadecimal] );
line.columnSize[SDisplayLine::decimal] = config.readUnsignedNumEntry(
"Decimal", line.columnSize[SDisplayLine::decimal] );
line.columnSize[SDisplayLine::octal] = config.readUnsignedNumEntry(
"Octal", line.columnSize[SDisplayLine::octal] );
line.columnSize[SDisplayLine::binary] = config.readUnsignedNumEntry(
"Binary", line.columnSize[SDisplayLine::binary] );
line.columnSize[SDisplayLine::textOnly] = config.readUnsignedNumEntry(
"TextOnly", line.columnSize[SDisplayLine::textOnly] );
SDisplayFont &font = mDisplayState.font;
config.setGroup( "Display Font" );
font.useSystemFont = config.readBoolEntry(
"UseSystemFont", true );
font.localFont = config.readFontEntry(
"LocalFont", &font.localFont );
font.nonPrintChar = config.readNumEntry(
"NonPrintChar", font.nonPrintChar );
SDisplayColor &color = mDisplayState.color;
config.setGroup( "Display Colors" );
color.useSystemColor = config.readBoolEntry(
"UseSystemColor", color.useSystemColor );
color.textBg = config.readColorEntry(
"TextBg", &color.textBg );
color.secondTextBg = config.readColorEntry(
"SecondTextBg", &color.secondTextBg );
color.offsetBg = config.readColorEntry(
"OffsetBg", &color.offsetBg );
color.inactiveBg = config.readColorEntry(
"InactiveBg", &color.inactiveBg );
color.primaryFg[0] = config.readColorEntry(
"PrimaryFg1", &color.primaryFg[0] );
color.primaryFg[1] = config.readColorEntry(
"PrimaryFg2", &color.primaryFg[1] );
color.offsetFg = config.readColorEntry(
"OffsetFg", &color.offsetFg );
color.secondaryFg = config.readColorEntry(
"SecondaryFg", &color.secondaryFg );
color.markBg = config.readColorEntry(
"MarkBg", &color.markBg );
color.markFg = config.readColorEntry(
"MarkFg", &color.markFg );
color.cursorBg = config.readColorEntry(
"CursorBg", &color.cursorBg );
color.cursorFg = config.readColorEntry(
"CursorFg", &color.cursorFg );
color.leftSeparatorFg = config.readColorEntry(
"LeftSeparatorFg", &color.leftSeparatorFg );
color.rightSeparatorFg = config.readColorEntry(
"RightSeparatorFg", &color.rightSeparatorFg );
color.nonPrintFg = config.readColorEntry(
"NonPrintFg", &color.nonPrintFg );
color.gridFg = config.readColorEntry(
"GridFg", &color.gridFg );
color.bookmarkBg = config.readColorEntry(
"BookmarkBg", &color.bookmarkBg );
color.bookmarkFg = config.readColorEntry(
"BookmarkFg", &color.bookmarkFg );
SDisplayCursor &cursor = mDisplayState.cursor;
config.setGroup( "Display Cursor" );
cursor.alwaysVisible = config.readBoolEntry(
"NeverBlink", cursor.alwaysVisible );
cursor.alwaysBlockShape = config.readBoolEntry(
"AlwaysBlockShape", cursor.alwaysBlockShape );
cursor.thickInsertShape = config.readBoolEntry(
"ThickInsertShape", cursor.thickInsertShape );
cursor.setFocusMode( config.readEntry("FocusMode") );
cursor.interval = config.readNumEntry(
"Interval", cursor.interval );
SDisplayMisc &misc = mDisplayState.misc;
config.setGroup( "Display Misc" );
misc.undoLevel = config.readNumEntry(
"UndoLevel", misc.undoLevel );
misc.setOpenFile( config.readEntry("OpenFile") );
misc.inputSound = config.readBoolEntry(
"InputSound", misc.inputSound );
misc.fatalSound = config.readBoolEntry(
"FatalSound", misc.fatalSound );
misc.autoCopyToClipboard = config.readBoolEntry(
"AutoCopyToClipboard", misc.autoCopyToClipboard );
misc.insertMode = config.readBoolEntry(
"InsertMode", misc.insertMode );
misc.writeProtect = config.readBoolEntry(
"WriteProtect", misc.writeProtect );
misc.confirmWrap = config.readBoolEntry(
"ConfirmWrap", misc.confirmWrap );
misc.cursorJump = config.readBoolEntry(
"CursorJump", misc.cursorJump );
misc.makeBackup = config.readBoolEntry(
"MakeBackup", misc.makeBackup );
misc.confirmThreshold = config.readBoolEntry(
"ConfirmThreshold", misc.confirmThreshold );
misc.thresholdValue = config.readNumEntry(
"ThresholdValue", misc.thresholdValue );
misc.discardRecent = config.readBoolEntry(
"DiscardRecent", misc.discardRecent );
misc.gotoOnStartup = config.readBoolEntry(
"GotoOnStartup", misc.gotoOnStartup );
misc.gotoOnReload = config.readBoolEntry(
"GotoOnReload", misc.gotoOnReload );
misc.bookmarkOffsetColumn = config.readBoolEntry(
"ShowBookmarkInOffsetColumn", misc.bookmarkOffsetColumn );
misc.bookmarkEditor = config.readBoolEntry(
"ShowBookmarkInEditor", misc.bookmarkEditor );
}
void CHexEditorWidget::resizeEvent( TQResizeEvent *e )
{
mHexView->resize( e->size().width(), e->size().height() );
}
void CHexEditorWidget::fontChanged( void )
{
if( mDisplayState.font.useSystemFont == true )
{
setFont( mDisplayState.font );
}
}
void CHexEditorWidget::paletteChanged( void )
{
setColor( mDisplayState.color );
}
void CHexEditorWidget::layoutChanged( const SDisplayLayout &/*layout*/ )
{
//mDisplayState.layout = layout;
}
void CHexEditorWidget::inputModeChanged( const SDisplayInputMode &input )
{
mDisplayState.input = input;
}
void CHexEditorWidget::setLineSize(const SDisplayLine &line )
{
mDisplayState.line = line;
}
void CHexEditorWidget::setLayout( const SDisplayLayout &layout )
{
//
// We only set the values that can be modified by the dialog
//
mDisplayState.layout.lockLine = layout.lockLine;
mDisplayState.layout.lockColumn = layout.lockColumn;
mDisplayState.layout.leftSeparatorWidth = layout.leftSeparatorWidth;
mDisplayState.layout.rightSeparatorWidth = layout.rightSeparatorWidth;
mDisplayState.layout.separatorMarginWidth = layout.separatorMarginWidth;
mDisplayState.layout.edgeMarginWidth = layout.edgeMarginWidth;
mDisplayState.layout.columnCharSpace = layout.columnCharSpace;
mDisplayState.layout.columnSpacing = layout.columnSpacing;
mDisplayState.layout.horzGridWidth = layout.horzGridWidth;
mDisplayState.layout.vertGridWidth = layout.vertGridWidth;
//
// Select the line and column sizes we shall use now.
//
SDisplayLayout &l = mDisplayState.layout;
l.lineSize = mDisplayState.line.lineSize[ l.primaryMode ];
l.columnSize = mDisplayState.line.columnSize[ l.primaryMode ];
mHexView->setLayout( mDisplayState.layout );
}
void CHexEditorWidget::setCursor( const SDisplayCursor &cursor )
{
mDisplayState.cursor = cursor;
mHexView->setCursor( mDisplayState.cursor, true );
}
void CHexEditorWidget::setColor( const SDisplayColor &color )
{
mDisplayState.color = color;
//
// The selection colors can not be chosen.
//
mDisplayState.color.selectBg = kapp->palette().active().highlight();
mDisplayState.color.selectFg = kapp->palette().active().highlightedText();
if( mDisplayState.color.useSystemColor == true )
{
SDisplayColor c = mDisplayState.color;
c.textBg = kapp->palette().active().base();
c.secondTextBg = kapp->palette().active().base();
c.offsetBg = kapp->palette().active().base();
c.inactiveBg = kapp->palette().active().base();
c.primaryFg[0] = kapp->palette().active().text();
c.primaryFg[1] = kapp->palette().active().text();
c.nonPrintFg = kapp->palette().active().text();
c.offsetFg = kapp->palette().active().text();
c.secondaryFg = kapp->palette().active().text();
c.leftSeparatorFg = kapp->palette().active().text();
c.rightSeparatorFg = kapp->palette().active().text();
c.cursorBg = kapp->palette().active().text();
c.cursorFg = kapp->palette().active().base();
c.gridFg = kapp->palette().active().text();
SDisplayColor defaultColor;
c.bookmarkBg = defaultColor.bookmarkBg;
c.bookmarkFg = defaultColor.bookmarkFg;
mHexView->setColor( c, true );
}
else
{
mHexView->setColor( mDisplayState.color, true );
}
}
void CHexEditorWidget::setFont( const SDisplayFont &font )
{
mDisplayState.font = font;
SDisplayFontInfo fontInfo;
if( mDisplayState.font.useSystemFont == true )
{
fontInfo.font = TDEGlobalSettings::fixedFont();
}
else
{
fontInfo.font = mDisplayState.font.localFont;
}
fontInfo.nonPrintChar = mDisplayState.font.nonPrintChar;
mHexView->setFont( fontInfo, true );
}
void CHexEditorWidget::setMisc( const SDisplayMisc &misc )
{
mDisplayState.misc = misc;
mHexView->setMisc( mDisplayState.misc );
}
void CHexEditorWidget::setHexadecimalMode( void )
{
layout().primaryMode = SDisplayLayout::hexadecimal;
layout().lineSize = line().lineSize[ SDisplayLine::hexadecimal ];
layout().columnSize = line().columnSize[ SDisplayLine::hexadecimal ];
mHexView->setLayout( layout() );
}
void CHexEditorWidget::setDecimalMode( void )
{
layout().primaryMode = SDisplayLayout::decimal;
layout().lineSize = line().lineSize[ SDisplayLine::decimal ];
layout().columnSize = line().columnSize[ SDisplayLine::decimal ];
mHexView->setLayout( layout() );
}
void CHexEditorWidget::setOctalMode( void )
{
layout().primaryMode = SDisplayLayout::octal;
layout().lineSize = line().lineSize[ SDisplayLine::octal ];
layout().columnSize = line().columnSize[ SDisplayLine::octal ];
mHexView->setLayout( layout() );
}
void CHexEditorWidget::setBinaryMode( void )
{
layout().primaryMode = SDisplayLayout::binary;
layout().lineSize = line().lineSize[ SDisplayLine::binary ];
layout().columnSize = line().columnSize[ SDisplayLine::binary ];
mHexView->setLayout( layout() );
}
void CHexEditorWidget::setTextMode( void )
{
layout().primaryMode = SDisplayLayout::textOnly;
layout().lineSize = line().lineSize[ SDisplayLine::textOnly ];
layout().columnSize = line().columnSize[ SDisplayLine::textOnly ];
mHexView->setLayout( layout() );
}
void CHexEditorWidget::saveWorkingDirectory( const TQString &url )
{
if( url.isEmpty() == true )
{
return;
}
int index = url.findRev( '/' );
if( index != -1 )
{
mWorkDir = url.left( index+1 );
}
}
void CHexEditorWidget::newFile( void )
{
if( busy( true ) == true )
{
return;
}
TQString url = i18n("Untitled %1").arg( mUntitledCount );
//
// If the url is already present in the document list (should not happen),
// then this document is "raised".
//
bool success = selectDocument( url, false );
if( success == true )
{
return;
}
//
// Prepare a new buffer we can load the document into
//
success = createBuffer();
if( success == false )
{
return;
}
int errCode = mHexView->newFile( url );
if( errCode != Err_Success )
{
TQString msg = i18n("Unable to create new document.");
KMessageBox::sorry( topLevelWidget(), msg, i18n("Operation Failed") );
return;
}
mUntitledCount += 1;
}
void CHexEditorWidget::newFile( const TQByteArray &data )
{
newFile();
mHexView->append( data );
}
void CHexEditorWidget::open()
{
KURL file = KFileDialog::getOpenURL( mWorkDir, "*" ,topLevelWidget() );
if( file.isEmpty() )
return;
TQString url = file.url();
saveWorkingDirectory( url );
if( busy( true ) )
return;
//
// If the url is already present in the document list, then this
// document is "raised".
//
if( selectDocument( url, true ) )
return;
//
// Prepare a new buffer we can load the document into
//
if( !createBuffer() )
return;
int errCode = readURL( file, false );
if( errCode != Err_Success )
{
emit errorLoadFile( url );
removeBuffer();
}
else if( errCode == Err_Success )
{
defaultWriteProtection();
}
}
void CHexEditorWidget::open( const TQString &url, bool reloadWhenChanged,
uint offset )
{
if( busy( true ) == true )
{
return;
}
//
// If the url is already present in the document list, then this
// document is "raised".
//
bool success = selectDocument( url, reloadWhenChanged );
if( success == true )
{
return;
}
//
// Prepare a new buffer we can load the document into
//
success = createBuffer();
if( success == false )
{
return;
}
int errCode = readURL( url, false );
if( errCode != Err_Success )
{
emit errorLoadFile( url );
removeBuffer();
}
else if( errCode == Err_Success )
{
mHexView->gotoOffset( offset );
defaultWriteProtection();
}
}
void CHexEditorWidget::stepFile( bool next )
{
//
// The buffer list is is reverse when compared with the visible
// document list in the menu so I toggle the flag.
//
next = next == true ? false : true;
CHexBuffer *hexBuffer = documentItem( mHexView->url(), next );
if( hexBuffer == 0 )
{
return;
}
mHexView->setBuffer( hexBuffer );
}
bool CHexEditorWidget::isOpen( const TQString &url, uint &offset )
{
CHexBuffer *hexBuffer = documentItem( url );
if( hexBuffer == 0 )
{
return( false );
}
offset = hexBuffer->cursorOffset();
return( true );
}
bool CHexEditorWidget::selectDocument( const TQString &url,
bool reloadWhenChanged )
{
CHexBuffer *hexBuffer = documentItem( url );
if( hexBuffer == 0 )
{
return( false );
}
mHexView->setBuffer( hexBuffer );
if( reloadWhenChanged == true && mHexView->urlValid() == true )
{
if( modifiedByAlien( mHexView->url() ) == true )
{
reload();
}
}
return( true );
}
void CHexEditorWidget::insertFile( void )
{
KFileDialog fdlg(mWorkDir, TQString(), topLevelWidget(), 0, TRUE);
fdlg.setOperationMode( KFileDialog::Opening );
fdlg.okButton()->setGuiItem( KStdGuiItem::insert() );
fdlg.setCaption(i18n("Insert File"));
if (!fdlg.exec()) return;
KURL file = fdlg.selectedURL();
if( file.isEmpty() )
return;
if( !file.isLocalFile() )
{
KMessageBox::sorry( this, i18n( "Only local files are currently supported." ) );
return;
}
TQString url = file.path();
saveWorkingDirectory( url );
if( busy( true ) )
return;
readURL( url, true );
}
void CHexEditorWidget::stop( void )
{
mProgressStop = mProgressBusy;
}
bool CHexEditorWidget::close( void )
{
if( busy( true ) == true )
{
return( false );
}
if( querySave() == false )
{
return( false );
}
removeBuffer();
return( true );
}
bool CHexEditorWidget::closeAll( void )
{
if( busy( true ) == true )
{
return( false );
}
while( mDocumentList.count() > 0 )
{
CHexBuffer *buf;
for( buf = mDocumentList.first(); buf != 0; buf = mDocumentList.next() )
{
//
// We select the buffer we are about to close because it will
// the become visible, and because 'close()' works on the current
// buffer.
//
mHexView->setBuffer( buf );
if( close() == false )
{
return( false );
}
}
//
// The document list will always contain at least one element because
// the hexview widget needs a hexbuffer to work. If this hexbuffer is
// not valid, then all files have been closed.
//
if( mDocumentList.count() == 1 && mHexView->documentPresent() == false )
{
break;
}
}
return( true );
}
bool CHexEditorWidget::querySave( void )
{
if( mHexView->modified() == false )
{
return( true );
}
TQString msg = i18n(""
"The current document has been modified.\n"
"Do you want to save it?" );
int reply = KMessageBox::warningYesNoCancel( topLevelWidget(), msg, TQString(), KStdGuiItem::save(), KStdGuiItem::discard() );
if( reply == KMessageBox::Yes )
{
return( save() );
}
else if( reply == KMessageBox::No )
{
return( true );
}
else
{
return( false );
}
}
bool CHexEditorWidget::backup( void )
{
if( mHexView->documentPresent() == false || mHexView->urlValid() == false )
{
return( false );
}
KURL kurl( mHexView->url() );
if( kurl.isLocalFile() == false )
{
return( false );
}
const TQString currentName = kurl.path();
TQString backupName = currentName + '~';
int errCode = rename( currentName.latin1(), backupName.latin1() );
if( errCode != 0 )
{
return( false );
}
return( true );
}
//
// Returns false if operation was canceled
//
bool CHexEditorWidget::save( void )
{
if( mHexView->documentPresent() == false )
{
return( true );
}
if( mHexView->urlValid() == false )
{
return( saveAs() );
}
else
{
if( modifiedByAlien( mHexView->url() ) == true )
{
TQString msg = i18n(""
"Current document has been changed on disk.\n"
"If you save now, those changes will be lost.\n"
"Proceed?" );
int reply = KMessageBox::warningYesNoCancel( topLevelWidget(), msg,
i18n("Save"), KStdGuiItem::save(), KStdGuiItem::discard() );
if( reply == KMessageBox::No || reply == KMessageBox::Cancel )
{
return( reply == KMessageBox::No ? true : false );
}
}
if( mDisplayState.misc.makeBackup == true )
{
backup();
}
writeURL( mHexView->url() );
}
return( true );
}
//
// Returns false if operation was canceled
//
bool CHexEditorWidget::saveAs( void )
{
if( mHexView->documentPresent() == false )
{
return( true );
}
KURL url;
while( 1 )
{
url = KFileDialog::getSaveURL( mHexView->url(), "*", this );
if( url.isEmpty() == true )
{
return( false );
}
else
{
saveWorkingDirectory( url.url() );
}
if( url.isLocalFile() )
{
TQString name( url.path() );
TQFileInfo info( name );
if( info.exists() )
{
TQString msg = i18n(""
"A document with this name already exists.\n"
"Do you want to overwrite it?" );
int reply = KMessageBox::warningContinueCancel( topLevelWidget(), msg,
i18n("Save As"), i18n("Overwrite") );
if( reply == KMessageBox::Continue )
break;
}
else
break;
}
}
TQString symbolicName( url.url() );
// KURL::decode( symbolicName );
mHexView->setUrl( symbolicName );
writeURL( mHexView->url() );
return( true );
}
void CHexEditorWidget::reload( void )
{
if( mHexView->documentPresent() == false )
{
return;
}
if( busy( true ) == true )
{
return;
}
if( mHexView->urlValid() == false )
{
TQString msg = i18n( "The current document does not exist on the disk." );
KMessageBox::sorry( topLevelWidget(), msg, i18n("Reload") );
return;
}
if( mHexView->modified() == true )
{
TQString msg;
if( modifiedByAlien( mHexView->url() ) == true )
{
msg = i18n( "The current document has changed on the disk and "
"also contains unsaved modifications.\n"
"If you reload now, the modifications will be lost." );
}
else
{
msg = i18n( "The current document contains unsaved modifications.\n"
"If you reload now, the modifications will be lost." );
}
int reply = KMessageBox::warningContinueCancel(topLevelWidget(),msg,i18n("Reload"), i18n("&Reload"));
if( reply != KMessageBox::Continue )
{
return;
}
}
TQString url( mHexView->url() );
uint offset = mHexView->offset();
//mHexView->closeFile();
int errCode = readURL( url, false );
if( errCode == Err_Success && gotoReloadOffset() == true )
{
mHexView->gotoOffset( offset );
}
}
void CHexEditorWidget::print( void )
{
CHexPrinter prt;
prt.addDialogPage( new LayoutDialogPage() );
prt.setPageSelection( KPrinter::SystemSide );
prt.setFullPage( true ); // I use my own marings
// FIXME: Make a better header for the printingdialog
if (prt.setup(topLevelWidget(), i18n("Print Hex-Document")))
{
prt.setTopMarginMM( prt.option("kde-khexedit-topmarginmm").toInt() );
prt.setBottomMarginMM( prt.option("kde-khexedit-bottommarginmm").toInt() );
prt.setLeftMarginMM( prt.option("kde-khexedit-leftmarginmm").toInt() );
prt.setRightMarginMM( prt.option("kde-khexedit-rightmarginmm").toInt() );
prt.setPageHeader( (prt.option("kde-khexedit-headercheck") == "true"),
prt.option("kde-khexedit-headercombo0").toInt(),
prt.option("kde-khexedit-headercombo1").toInt(),
prt.option("kde-khexedit-headercombo2").toInt(),
prt.option("kde-khexedit-headercombo3").toInt() );
prt.setPageFooter( (prt.option("kde-khexedit-footercheck") == "true"),
prt.option("kde-khexedit-footercombo0").toInt(),
prt.option("kde-khexedit-footercombo1").toInt(),
prt.option("kde-khexedit-footercombo2").toInt(),
prt.option("kde-khexedit-footercombo3").toInt() );
printPostscript(prt);
}
}
void CHexEditorWidget::printPostscript( CHexPrinter &printer )
{
if( confirmPrintPageNumber( printer ) == false )
{
return;
}
//
// No i18n() on this one!
// Constants come from config.h
//
TQString creator( PACKAGE );
creator += " ";
creator += VERSION;
printer.setCreator( creator );
int errCode = prepareProgressData( pg_print );
if( errCode == Err_Success )
{
errCode = mHexView->print( printer, mProgressData );
}
TQString msg = i18n("Could not print data.\n");
msg += hexError( errCode );
if( errCode != Err_Success )
{
KMessageBox::sorry( topLevelWidget(), msg, i18n("Print") );
}
}
bool CHexEditorWidget::confirmPrintPageNumber( CHexPrinter &printer )
{
if( mDisplayState.misc.confirmThreshold == true )
{
uint numPage = mHexView->numPage( printer );
printer.setMinMax( 1, numPage );
uint numPageSelected = printer.pageList().count();
if( numPageSelected > mDisplayState.misc.thresholdValue )
{
TQString msg = i18n(
"<qt>Print threshold exceeded.<br>"
"You are about to print one page.<br>"
"Proceed?</qt>",
"<qt>Print threshold exceeded.<br>"
"You are about to print %n pages.<br>"
"Proceed?</qt>",
numPageSelected );
int reply = KMessageBox::warningYesNo( topLevelWidget(), msg,
i18n("Print"), KStdGuiItem::print(), KStdGuiItem::cancel() );
if( reply != KMessageBox::Continue )
{
return( false );
}
}
}
return( true );
}
void CHexEditorWidget::exportDialog( void )
{
if( mExportDialog == 0 )
{
mExportDialog = new CExportDialog( topLevelWidget(), 0, false );
if( mExportDialog == 0 ) { return; }
connect( mExportDialog, TQT_SIGNAL( exportText(const SExportText &)),
this, TQT_SLOT( exportText( const SExportText &)) );
connect( mExportDialog, TQT_SIGNAL( exportHtml(const SExportHtml &)),
this, TQT_SLOT( exportHtml( const SExportHtml &)) );
connect( mExportDialog, TQT_SIGNAL( exportCArray(const SExportCArray &)),
this, TQT_SLOT( exportCArray( const SExportCArray &)) );
}
mExportDialog->show();
}
void CHexEditorWidget::exportText( const SExportText &ex )
{
int errCode = prepareProgressData( pg_export );
if( errCode == Err_Success )
{
errCode = mHexView->exportText( ex, mProgressData );
}
if( errCode != Err_Success )
{
TQString msg = i18n("Unable to export data.\n");
msg += hexError( errCode );
KMessageBox::sorry( topLevelWidget(), msg, i18n("Export") );
}
}
void CHexEditorWidget::exportHtml( const SExportHtml &ex )
{
int errCode = prepareProgressData( pg_export );
if( errCode == Err_Success )
{
errCode = mHexView->exportHtml( ex, mProgressData );
}
if( errCode != Err_Success )
{
TQString msg = i18n("Unable to export data.\n");
msg += hexError( errCode );
KMessageBox::sorry( topLevelWidget(), msg, i18n("Export") );
}
}
void CHexEditorWidget::exportCArray( const SExportCArray &ex )
{
int errCode = prepareProgressData( pg_export );
if( errCode == Err_Success )
{
errCode = mHexView->exportCArray( ex, mProgressData );
}
if( errCode != Err_Success )
{
TQString msg = i18n("Unable to export data.\n");
msg += hexError( errCode );
KMessageBox::sorry( topLevelWidget(), msg, i18n("Export") );
}
}
void CHexEditorWidget::encode( CConversion::EMode mode )
{
if( mHexView->losslessEncoding( mode ) == false )
{
TQString msg = i18n(""
"The encoding you have selected is not reversible.\n"
"If you revert to the original encoding later, there is no "
"guarantee that the data can be restored to the original state.");
int reply = KMessageBox::warningContinueCancel( topLevelWidget(), msg,
i18n("Encode"), i18n("&Encode"));
if( reply != KMessageBox::Continue )
{
// Restore correct menu setting
mHexView->reportEncoding();
return;
}
}
int errCode = prepareProgressData( pg_encode );
if( errCode == Err_Success )
{
errCode = mHexView->setEncoding( mode, mProgressData );
}
if( errCode != Err_Success )
{
TQString msg = i18n("Could not encode data.\n");
msg += hexError( errCode );
KMessageBox::sorry( topLevelWidget(), msg, i18n("Encode") );
}
}
void CHexEditorWidget::undo( void )
{
mHexView->undo();
}
void CHexEditorWidget::redo( void )
{
mHexView->redo();
}
void CHexEditorWidget::toggleWriteProtection( void )
{
mDisplayState.input.readOnly = mDisplayState.input.readOnly == true ?
false : true;
mHexView->setInputMode( mDisplayState.input );
}
void CHexEditorWidget::defaultWriteProtection( void )
{
mDisplayState.input.readOnly = mDisplayState.misc.writeProtect;
mHexView->setInputMode( mDisplayState.input );
}
void CHexEditorWidget::toggleResizeLock( void )
{
mDisplayState.input.allowResize = mDisplayState.input.allowResize == true ?
false : true;
mHexView->setInputMode( mDisplayState.input );
}
void CHexEditorWidget::setResizeLock( bool state )
{
mDisplayState.input.allowResize = state;
mHexView->setInputMode( mDisplayState.input );
}
void CHexEditorWidget::enableInputLock( bool inputLock )
{
mDisplayState.input.inputLock = inputLock;
mHexView->setInputMode( mDisplayState.input );
}
void CHexEditorWidget::toggleOffsetColumnVisibility( void )
{
layout().offsetVisible = layout().offsetVisible == true ? false : true;
mHexView->setLayout( layout() );
}
void CHexEditorWidget::toggleTextColumnVisibility( void )
{
layout().secondaryMode = layout().secondaryMode == SDisplayLayout::hide ?
SDisplayLayout::textOnly : SDisplayLayout::hide;
mHexView->setLayout( layout() );
}
void CHexEditorWidget::toggleOffsetAsDecimal( void )
{
layout().offsetMode = layout().offsetMode == SDisplayLayout::hexadecimal ?
SDisplayLayout::decimal : SDisplayLayout::hexadecimal;
mHexView->setLayout( layout() );
}
void CHexEditorWidget::toggleDataUppercase( void )
{
layout().primaryUpperCase = layout().primaryUpperCase == true ? false : true;
mHexView->setLayout( layout() );
}
void CHexEditorWidget::toggleOffsetUppercase( void )
{
layout().offsetUpperCase = layout().offsetUpperCase == true ? false : true;
mHexView->setLayout( layout() );
}
void CHexEditorWidget::toggleInsertMode( void )
{
mHexView->setInsertMode( !mHexView->insertMode() );
}
void CHexEditorWidget::benchmark( void )
{
mHexView->benchmark();
}
void CHexEditorWidget::copy( void )
{
mHexView->copy();
}
void CHexEditorWidget::copyText( void )
{
mHexView->copyText();
}
void CHexEditorWidget::paste( void )
{
if( mHexView->documentPresent() == false )
{
pasteNewFile();
}
else
{
mHexView->paste();
}
}
void CHexEditorWidget::pasteNewFile( void )
{
newFile();
mHexView->paste();
}
void CHexEditorWidget::cut( void )
{
mHexView->cut();
}
void CHexEditorWidget::selectAll( void )
{
mHexView->selectAll();
}
void CHexEditorWidget::unselect( void )
{
mHexView->unselect();
}
void CHexEditorWidget::addBookmark( void )
{
mHexView->addBookmark( -1 );
}
void CHexEditorWidget::removeBookmark( void )
{
if( mHexView->bookmarkCount() > 0 )
{
mHexView->removeBookmark( false );
}
}
void CHexEditorWidget::removeAllBookmark( void )
{
if( mHexView->bookmarkCount() > 0 )
{
TQString msg = i18n(""
"Deleted bookmarks can not be restored.\n"
"Proceed?" );
int reply = KMessageBox::warningContinueCancel( topLevelWidget(), msg );
if( reply != KMessageBox::Continue )
{
return;
}
mHexView->removeBookmark( true );
}
}
void CHexEditorWidget::replaceBookmark( void )
{
mHexView->replaceBookmark();
}
void CHexEditorWidget::gotoBookmark( int position )
{
mHexView->gotoBookmark( (uint)position );
}
void CHexEditorWidget::gotoNextBookmark( void )
{
mHexView->gotoNextBookmark(true);
}
void CHexEditorWidget::gotoPrevBookmark( void )
{
mHexView->gotoNextBookmark(false);
}
void CHexEditorWidget::gotoOffset( void )
{
if( mGotoDialog == 0 )
{
mGotoDialog = new CGotoDialog( topLevelWidget(), 0, false );
if( mGotoDialog == 0 ) { return; }
connect( mGotoDialog, TQT_SIGNAL(gotoOffset( uint, uint, bool, bool )),
mHexView, TQT_SLOT(gotoOffset( uint, uint, bool, bool )) );
}
mGotoDialog->show();
}
void CHexEditorWidget::find( void )
{
if( mFindNavigatorDialog != 0 )
{
mFindNavigatorDialog->hide();
}
if( mFindDialog == 0 )
{
mFindDialog = new CFindDialog( topLevelWidget(), 0, false );
if( mFindDialog == 0 ) { return; }
connect( mFindDialog,
TQT_SIGNAL(findData(SSearchControl &, uint, bool)),
TQT_SLOT(findData(SSearchControl &, uint, bool)) );
}
mFindDialog->show();
}
void CHexEditorWidget::findData( SSearchControl &sc, uint mode, bool navigator)
{
for( uint i=0; i < 2; i++ )
{
int errCode;
if( mode == Find_First )
{
errCode = mHexView->findFirst( sc );
if( errCode == Err_Success )
{
if( navigator == true )
{
findNavigator( sc );
}
return;
}
}
else if( mode == Find_Next )
{
errCode = mHexView->findNext( sc );
if( errCode == Err_Success )
{
if( navigator == true )
{
findNavigator( sc );
}
return;
}
}
else
{
return;
}
if( errCode == Err_WrapBuffer && i == 0 )
{
bool reply = askWrap( sc.forward, i18n("Find") );
if( reply == false )
{
return;
}
sc.fromCursor = false;
mode = Find_First;
}
}
if( mode == Find_First )
{
TQString msg = i18n( "Search key not found in document." );
KMessageBox::sorry( topLevelWidget(), msg, i18n("Find") );
}
}
void CHexEditorWidget::findAgain( void )
{
if( canFind( true ) == true )
{
mFindDialog->findAgain( CFindDialog::find_Again );
}
}
void CHexEditorWidget::findNext( void )
{
if( canFind( true ) == true )
{
mFindDialog->findAgain( CFindDialog::find_Next );
}
}
void CHexEditorWidget::findPrevious( void )
{
if( canFind( true ) == true )
{
mFindDialog->findAgain( CFindDialog::find_Previous );
}
}
bool CHexEditorWidget::askWrap( bool fwd, const TQString &header )
{
if( mDisplayState.misc.confirmWrap == false )
{
return( true ); // Never ask the user
}
TQString msg;
if( fwd == true )
{
msg += i18n(""
"End of document reached.\n"
"Continue from the beginning?" );
}
else
{
msg += i18n(""
"Beginning of document reached.\n"
"Continue from the end?" );
}
int reply = KMessageBox::questionYesNo( topLevelWidget(), msg, header, KStdGuiItem::cont(), KStdGuiItem::cancel() );
return( reply == KMessageBox::Yes ? true : false );
}
bool CHexEditorWidget::canFind( bool showError )
{
if( mFindDialog == 0 || mFindDialog->isEmpty() == true )
{
if( showError == true )
{
TQString msg = i18n(""
"Your request can not be processed.\n"
"No search pattern defined." );
KMessageBox::sorry( topLevelWidget(), msg, i18n("Find") );
}
return( false );
}
return( true );
}
void CHexEditorWidget::findNavigator( SSearchControl &sc )
{
if( canFind( false ) == false )
{
return;
}
if( mFindNavigatorDialog == 0 )
{
mFindNavigatorDialog = new CFindNavigatorDialog(topLevelWidget(),0,false);
if( mFindNavigatorDialog == 0 ) { return; }
connect( mFindNavigatorDialog,
TQT_SIGNAL(findData(SSearchControl &, uint, bool)),
TQT_SLOT(findData(SSearchControl &, uint, bool)) );
connect( mFindNavigatorDialog, TQT_SIGNAL(makeKey(void)),
TQT_SLOT(find()) );
}
if( mFindNavigatorDialog->isVisible() == false )
{
mFindNavigatorDialog->defineData( sc );
}
mFindNavigatorDialog->show();
}
void CHexEditorWidget::replace( void )
{
hideReplacePrompt();
if( mReplaceDialog == 0 )
{
mReplaceDialog = new CReplaceDialog( topLevelWidget(), 0, false );
if( mReplaceDialog == 0 ) { return; }
connect( mReplaceDialog,
TQT_SIGNAL( replaceData( SSearchControl &, uint)),
TQT_SLOT( replaceData( SSearchControl &, uint)));
}
mReplaceDialog->show();
}
void CHexEditorWidget::replaceData( SSearchControl &sc, uint mode )
{
while( 1 )
{
if( mode == Replace_All || mode == Replace_AllInit )
{
mHexView->replaceAll( sc, mode == Replace_AllInit ? true : false );
}
else if( mode == Replace_First )
{
int errCode = mHexView->findFirst( sc );
if( errCode == Err_Success )
{
replacePrompt( sc );
return;
}
}
else if( mode == Replace_Next )
{
int errCode = mHexView->replaceMarked( sc );
if( errCode != Err_Success )
{
// Perhaps a notification here ?
}
errCode = mHexView->findNext( sc );
if( errCode == Err_Success )
{
replacePrompt( sc );
return;
}
}
else if( mode == Replace_Ignore )
{
int errCode = mHexView->findNext( sc );
if( errCode == Err_Success )
{
replacePrompt( sc );
return;
}
}
else
{
break;
}
if( sc.wrapValid == false )
{
break;
}
bool reply = askWrap( sc.forward, i18n("Find and Replace") );
if( reply == false )
{
break;
}
int errCode = mHexView->findWrap( sc );
if( errCode != Err_Success )
{
break;
}
if( mode == Replace_All || mode == Replace_AllInit )
{
mode = Replace_All;
continue;
}
replacePrompt( sc );
return;
}
replaceResult( sc );
}
void CHexEditorWidget::replacePrompt( SSearchControl &sc )
{
if( mReplacePromptDialog == 0 )
{
mReplacePromptDialog = new CReplacePromptDialog(topLevelWidget(), 0,false);
if( mReplacePromptDialog == 0 ) { return; }
connect( mReplacePromptDialog,
TQT_SIGNAL( replaceData( SSearchControl &, uint)),
TQT_SLOT( replaceData( SSearchControl &, uint)));
}
if( mReplacePromptDialog->isVisible() == false )
{
mReplacePromptDialog->defineData( sc );
}
mReplacePromptDialog->show();
}
void CHexEditorWidget::hideReplacePrompt( void )
{
if( mReplacePromptDialog != 0 )
{
mReplacePromptDialog->hide();
}
}
void CHexEditorWidget::replaceResult( SSearchControl &sc )
{
hideReplacePrompt();
if( sc.match == false )
{
TQString msg;
if( sc.inSelection == true )
{
msg += i18n( "Search key not found in selected area." );
}
else
{
msg += i18n( "Search key not found in document." );
}
KMessageBox::information( topLevelWidget(), msg, i18n("Find & Replace"));
}
else
{
const TQString msg = i18n(
"<qt>Operation complete.<br><br>One replacement was made.</qt>",
"<qt>Operation complete.<br><br>%n replacements were made.</qt>", sc.numReplace );
KMessageBox::information( topLevelWidget(), msg, i18n("Find & Replace"));
}
}
void CHexEditorWidget::insertPattern( void )
{
if( mInsertDialog == 0 )
{
mInsertDialog = new CInsertDialog( topLevelWidget(), 0, false );
if( mInsertDialog == 0 ) { return; }
connect( mInsertDialog, TQT_SIGNAL(execute( SInsertData & )),
mHexView, TQT_SLOT(insert( SInsertData & )) );
}
mInsertDialog->show();
}
void CHexEditorWidget::encoding( void )
{
TQString msg = i18n(""
"Not available yet!\n"
"Define your own encoding" );
KMessageBox::sorry( topLevelWidget(), msg, i18n("Encoding") );
}
void CHexEditorWidget::strings( void )
{
if( mStringDialog == 0 )
{
mStringDialog = new CStringDialog( topLevelWidget(), 0, false );
if( mStringDialog == 0 ) { return; }
connect( mStringDialog, TQT_SIGNAL(markText( uint, uint, bool )),
mHexView, TQT_SLOT(setMark( uint, uint, bool )) );
connect( mStringDialog, TQT_SIGNAL(collect()), TQT_SLOT(collectStrings()) );
connect( mHexView, TQT_SIGNAL(fileName( const TQString &, bool ) ),
mStringDialog, TQT_SLOT( removeList() ) );
connect( mHexView, TQT_SIGNAL(dataChanged()),
mStringDialog, TQT_SLOT(setDirty()) );
}
mStringDialog->show();
}
void CHexEditorWidget::collectStrings( void )
{
int errCode = prepareProgressData( pg_strings );
if( errCode == Err_Success )
{
mHexView->collectStrings( mStringDialog->stringData() );
errCode = mStringDialog->updateList( mProgressData );
}
if( errCode != Err_Success && errCode != Err_Stop )
{
TQString msg = i18n("Could not collect strings.\n");
msg += hexError( errCode );
KMessageBox::sorry( topLevelWidget(), msg, i18n("Collect Strings") );
}
}
void CHexEditorWidget::recordView( void )
{
TQString msg = i18n(""
"Not available yet!\n"
"Define a record (structure) and fill it with data from the document." );
KMessageBox::sorry( topLevelWidget(), msg, i18n("Record Viewer") );
}
void CHexEditorWidget::filter( void )
{
if( mFilterDialog == 0 )
{
mFilterDialog = new CFilterDialog( topLevelWidget(), 0, false );
if( mFilterDialog == 0 ) { return; }
connect( mFilterDialog, TQT_SIGNAL(filterData( SFilterControl & )),
mHexView, TQT_SLOT(filter( SFilterControl & )) );
}
mFilterDialog->show();
}
void CHexEditorWidget::chart( void )
{
if( mCharTableDialog == 0 )
{
mCharTableDialog = new CCharTableDialog( topLevelWidget(), 0, false );
if( mCharTableDialog == 0 ) { return; }
connect( mCharTableDialog, TQT_SIGNAL(assign( const TQByteArray & )),
mHexView, TQT_SLOT(insert( const TQByteArray & )) );
}
mCharTableDialog->show();
}
void CHexEditorWidget::converter( void )
{
if( mConverterDialog == 0 )
{
mConverterDialog = new CConverterDialog( this, "converter", false );
connect( mConverterDialog, TQT_SIGNAL(probeCursorValue(TQByteArray &, uint)),
mHexView, TQT_SLOT(valueOnCursor(TQByteArray &, uint)) );
}
mConverterDialog->show();
}
void CHexEditorWidget::statistics( void )
{
if( mFileInfoDialog == 0 )
{
mFileInfoDialog = new CFileInfoDialog( topLevelWidget(), 0, false );
if( mFileInfoDialog == 0 ) { return; }
connect( mFileInfoDialog, TQT_SIGNAL(collectStatistic(SStatisticControl &)),
TQT_SLOT(collectStatistics(SStatisticControl &)));
connect( mHexView, TQT_SIGNAL(dataChanged()),
mFileInfoDialog, TQT_SLOT(setDirty()) );
}
mFileInfoDialog->show();
}
void CHexEditorWidget::collectStatistics( SStatisticControl &sc )
{
int errCode = prepareProgressData( pg_statistic );
if( errCode == Err_Success )
{
errCode = mHexView->collectStatistic( sc, mProgressData );
if( errCode == Err_Success )
{
mFileInfoDialog->setStatistics( sc );
}
}
if( errCode != Err_Success && errCode != Err_Stop )
{
mFileInfoDialog->setStatistics(); // Default values
TQString msg = i18n("Could not collect document statistics.\n");
msg += hexError( errCode );
KMessageBox::sorry( topLevelWidget(), msg,
i18n("Collect Document Statistics") );
}
}
void CHexEditorWidget::options( void )
{
if( mOptionDialog == 0 )
{
mOptionDialog = new COptionDialog( topLevelWidget(), 0, false );
if( mOptionDialog == 0 ) { return; }
connect( mOptionDialog, TQT_SIGNAL(lineSizeChoice(const SDisplayLine &)),
TQT_SLOT(setLineSize(const SDisplayLine &)) );
connect( mOptionDialog, TQT_SIGNAL(layoutChoice(const SDisplayLayout &)),
TQT_SLOT(setLayout(const SDisplayLayout &)) );
connect( mOptionDialog, TQT_SIGNAL(fontChoice(const SDisplayFont &)),
TQT_SLOT(setFont(const SDisplayFont &)) );
connect( mOptionDialog, TQT_SIGNAL(colorChoice(const SDisplayColor &)),
TQT_SLOT(setColor(const SDisplayColor &)) );
connect( mOptionDialog, TQT_SIGNAL(cursorChoice(const SDisplayCursor &)),
TQT_SLOT(setCursor(const SDisplayCursor &)) );
connect( mOptionDialog, TQT_SIGNAL(miscChoice(const SDisplayMisc &)),
TQT_SLOT(setMisc(const SDisplayMisc &)) );
connect( mOptionDialog, TQT_SIGNAL(removeRecentFiles()),
TQT_SIGNAL(removeRecentFiles()) );
}
if( mOptionDialog->isVisible() == false )
{
mOptionDialog->setState( mDisplayState );
}
mOptionDialog->show();
}
void CHexEditorWidget::favorites( void )
{
TQString msg = i18n(""
"Not available yet!\n"
"Save or retrive your favorite layout" );
KMessageBox::sorry( topLevelWidget(), msg, i18n("Profiles") );
}
int CHexEditorWidget::readURL( const KURL &url, bool insert )
{
//
// 1) Make sure there is data in the url
//
if( url.isEmpty() )
return( Err_EmptyArgument );
//
// 2) Verify that the url is valid URL string. If not, try to repair it.
// This will work if the url contains a name of a file in the
// current directory.
//
if( !url.isValid() )
{
TQString msg = i18n("Malformed URL\n%1").arg( url.url() );
KMessageBox::sorry( topLevelWidget(), msg, i18n("Read URL") );
return( Err_IllegalArgument );
}
//
// 3) Load the file.
//
TQString tmpfile;
if ( !TDEIO::NetAccess::download( url, tmpfile, this ) )
return Err_ReadFailed;
bool success = readFile( tmpfile, url.url(), insert );
TDEIO::NetAccess::removeTempFile( tmpfile );
return( success == true ? Err_Success : Err_ReadFailed );
}
void CHexEditorWidget::writeURL( TQString &url )
{
KURL kurl( url );
if( kurl.isLocalFile() )
writeFile( kurl.path() );
else
{
bool modified = mHexView->modified();
KTempFile tf;
tf.setAutoDelete( true );
writeFile( tf.name() );
if( !TDEIO::NetAccess::upload(tf.name(),url,this) )
{
mHexView->setModified( modified );
TQString msg = i18n("Could not save remote file.");
KMessageBox::sorry( topLevelWidget(), msg, i18n("Write Failure") );
}
}
}
bool CHexEditorWidget::modifiedByAlien( const TQString &url )
{
KURL kurl( url );
if( kurl.isLocalFile() == false )
{
return( false );
}
TQFileInfo fileInfo( kurl.path() );
if( fileInfo.exists() == false )
{
return( false );
}
if( fileInfo.lastModified() == mHexView->diskModifyTime() )
{
return( false );
}
return( true );
}
bool CHexEditorWidget::readFile( const TQString &diskPath, const TQString &url,
bool insert )
{
TQFileInfo info( diskPath );
if( info.exists() == false )
{
const TQString msg = i18n("The specified file does not exist.\n%1").arg( diskPath );
KMessageBox::sorry( topLevelWidget(), msg, i18n("Read") );
return( false );
}
if( info.isDir() == true )
{
const TQString msg = i18n("You have specified a folder.\n%1").arg( diskPath );
KMessageBox::sorry( topLevelWidget(), msg, i18n("Read") );
return( false );
}
if( info.isReadable() == false )
{
const TQString msg = i18n("You do not have read permission to this file.\n%1").arg( diskPath );
KMessageBox::sorry( topLevelWidget(), msg, i18n("Read") );
return( false );
}
TQFile file( diskPath );
if( file.open( IO_ReadOnly | IO_Raw ) == false )
{
const TQString msg = i18n("An error occurred while trying to open the file.\n%1").arg( diskPath );
KMessageBox::sorry( topLevelWidget(), msg, i18n("Read") );
return( false );
}
if( mHexView->documentPresent() == false )
{
//
// Can not insert if there is no document present.
//
insert = false;
}
int errCode = prepareProgressData( insert == true ? pg_insert: pg_read );
if( errCode == Err_Success )
{
if( insert == true )
{
errCode = mHexView->insertFile( file, mProgressData );
}
else
{
errCode = mHexView->readFile( file, url, mProgressData );
}
}
if( errCode != Err_Success )
{
TQString header = insert == true ? i18n("Insert") : i18n("Read");
TQString msg = i18n("Could not read file.\n");
msg += hexError( errCode );
KMessageBox::sorry( topLevelWidget(), msg, header );
}
file.close();
return( errCode == Err_Success || errCode == Err_Busy ? true : false );
}
bool CHexEditorWidget::writeFile( const TQString &diskPath )
{
TQFileInfo info( diskPath );
if( info.exists() == true )
{
if( info.isDir() == true )
{
TQString msg = i18n("You have specified a folder.");
KMessageBox::sorry( topLevelWidget(), msg, i18n("Write Failure") );
return( false );
}
if( info.isWritable() == false )
{
TQString msg = i18n("You do not have write permission.");
KMessageBox::sorry( topLevelWidget(), msg, i18n("Write Failure") );
return( false );
}
}
TQFile file( diskPath );
if( file.open( IO_WriteOnly | IO_Raw | IO_Truncate ) == false )
{
TQString msg = i18n("An error occurred while trying to open the file.");
KMessageBox::sorry( topLevelWidget(), msg, i18n("Write Failure") );
return( false );
}
int errCode = prepareProgressData( pg_write );
if( errCode == Err_Success )
{
errCode = mHexView->writeFile( file, mProgressData );
}
if( errCode != Err_Success )
{
TQString msg = i18n("Could not write data to disk.\n");
msg += hexError( errCode );
KMessageBox::sorry( topLevelWidget(), msg, i18n("Write Failure") );
}
file.close();
return( true );
}
CHexBuffer *CHexEditorWidget::documentItem( const TQString &url )
{
TQString symbolicName( url );
// KURL::decode( symbolicName );
for( CHexBuffer *hexBuffer = mDocumentList.first(); hexBuffer != 0;
hexBuffer = mDocumentList.next() )
{
if( hexBuffer->url() == symbolicName )
{
return( hexBuffer );
}
}
return( 0 );
}
CHexBuffer *CHexEditorWidget::documentItem( const TQString &url, bool next )
{
if( mDocumentList.count() <= 1 )
{
return( 0 );
}
TQString symbolicName( url );
// KURL::decode( symbolicName );
if( next == true )
{
CHexBuffer *hexBuffer = mDocumentList.first();
for( ; hexBuffer != 0; hexBuffer = mDocumentList.next() )
{
if( hexBuffer->url() == symbolicName )
{
hexBuffer = mDocumentList.next();
return( hexBuffer == 0 ? mDocumentList.first() : hexBuffer );
}
}
}
else
{
CHexBuffer *hexBuffer = mDocumentList.last();
for( ; hexBuffer != 0; hexBuffer = mDocumentList.prev() )
{
if( hexBuffer->url() == symbolicName )
{
hexBuffer = mDocumentList.prev();
return( hexBuffer == 0 ? mDocumentList.last() : hexBuffer );
}
}
}
return( 0 );
}
bool CHexEditorWidget::createBuffer( void )
{
if( mHexView->documentPresent() == false )
{
//
// The document is not valid, i.e. the buffer contains no data
// so we can use this one without destroying anything.
//
return( true );
}
CHexBuffer *hexBuffer = new CHexBuffer;
if( hexBuffer == 0 )
{
TQString msg = i18n( "Can not create text buffer.\n" );
msg += hexError( Err_NoMemory );
KMessageBox::error( topLevelWidget(), msg, i18n("Loading Failed" ) );
return( false );
}
mDocumentList.append( hexBuffer );
mHexView->setBuffer( hexBuffer );
return( true );
}
void CHexEditorWidget::removeBuffer( void )
{
mHexView->closeFile();
if( mDocumentList.count() > 1 )
{
CHexBuffer *prev = 0;
CHexBuffer *curr = mDocumentList.first();
for( ; curr != 0; curr = mDocumentList.next() )
{
if( curr == mHexView->hexBuffer() )
{
CHexBuffer *ptr = prev != 0 ? prev : mDocumentList.next();
if( ptr != 0 )
{
mHexView->setBuffer( ptr );
mDocumentList.remove( curr );
break;
}
}
prev = curr;
}
}
}
bool CHexEditorWidget::modified( void )
{
for( CHexBuffer *hexBuffer = mDocumentList.first(); hexBuffer != 0;
hexBuffer = mDocumentList.next() )
{
if( hexBuffer->modified() == true )
{
return( true );
}
}
return( false );
}
int CHexEditorWidget::prepareProgressData( EProgressMode mode )
{
if( mode >= pg_MAX )
{
return( Err_IllegalMode );
}
if( mProgressBusy == true )
{
return( Err_Busy );
}
mProgressMode = mode;
mProgressBusy = true;
mProgressStop = false;
enableInputLock( true );
static TQString names[] =
{
i18n("Reading"),
i18n("Writing"),
i18n("Inserting"),
i18n("Printing"),
i18n("Encoding"),
i18n("Collect strings"),
i18n("Exporting"),
i18n("Scanning"),
};
mProgressData.define( progressReceiver, this );
emit setProgressText( TQString(names[mode]) );
emit operationChanged( true );
return( Err_Success );
}
int CHexEditorWidget::progressReceiver( void *clientData, SProgressData &pd )
{
if( clientData != 0 )
{
int errCode = ((CHexEditorWidget*)clientData)->progressParse( pd );
return( errCode );
}
else
{
return( Err_Success );
}
}
int CHexEditorWidget::progressParse( const SProgressData &pd )
{
if( pd.valid() == 0 )
{
emit enableProgressText( false );
emit setProgress( 0 );
emit operationChanged( false );
mProgressBusy = false;
enableInputLock( false );
kapp->processEvents();
return( Err_Success );
}
else if( pd.useFraction == 1 )
{
emit enableProgressText( true );
emit setProgress( (int)(100.0 * pd.fraction ) );
kapp->processEvents();
}
else
{
emit enableProgressText( true );
emit setProgress( pd.curPage, pd.maxPage );
kapp->processEvents();
}
if( mProgressStop == false )
{
return( Err_Success );
}
TQString msg, header;
switch( mProgressMode )
{
case pg_read:
header = i18n("Read");
msg = i18n("Do you really want to cancel reading?");
break;
case pg_write:
header = i18n("Write");
msg = i18n("Do you really want to cancel writing?\n"
"WARNING: Canceling can corrupt your data on disk");
break;
case pg_insert:
header = i18n("Insert");
msg = i18n("Do you really want to cancel inserting?");
break;
case pg_print:
header = i18n("Print");
msg = i18n("Do you really want to cancel printing?");
break;
case pg_encode:
header = i18n("Encode");
msg = i18n("Do you really want to cancel encoding?");
break;
case pg_strings:
header = i18n("Collect strings");
msg = i18n("Do you really want to cancel string scanning?");
break;
case pg_export:
header = i18n("Export");
msg = i18n("Do you really want to cancel exporting?");
break;
case pg_statistic:
header = i18n("Collect document statistics");
msg = i18n("Do you really want to cancel document scanning?");
break;
default:
return( Err_Success );
break;
}
int reply = KMessageBox::warningYesNo( topLevelWidget(), msg, header, KStdGuiItem::cancel(), KStdGuiItem::cont() );
mProgressStop = false;
return( reply == KMessageBox::Yes ? Err_Stop : Err_Success );
}
bool CHexEditorWidget::busy( bool showWarning )
{
if( mProgressBusy == true && showWarning == true )
{
TQString msg = i18n("Could not finish operation.\n");
msg += hexError( Err_Busy );
KMessageBox::sorry( topLevelWidget(), msg );
}
return( mProgressBusy );
}
#include "hexeditorwidget.moc"