summaryrefslogtreecommitdiffstats
path: root/khexedit
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit2bda8f7717adf28da4af0d34fb82f63d2868c31d (patch)
tree8d927b7b47a90c4adb646482a52613f58acd6f8c /khexedit
downloadtdeutils-2bda8f7717adf28da4af0d34fb82f63d2868c31d.tar.gz
tdeutils-2bda8f7717adf28da4af0d34fb82f63d2868c31d.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdeutils@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'khexedit')
-rw-r--r--khexedit/Makefile.am35
-rw-r--r--khexedit/README34
-rw-r--r--khexedit/bitswapwidget.cc323
-rw-r--r--khexedit/bitswapwidget.h101
-rw-r--r--khexedit/chartabledialog.cc212
-rw-r--r--khexedit/chartabledialog.h72
-rw-r--r--khexedit/configure.in.in8
-rw-r--r--khexedit/conversion.cc395
-rw-r--r--khexedit/conversion.h71
-rw-r--r--khexedit/converterdialog.cc163
-rw-r--r--khexedit/converterdialog.h83
-rw-r--r--khexedit/dialog.cc1433
-rw-r--r--khexedit/dialog.h350
-rw-r--r--khexedit/draglabel.cc149
-rw-r--r--khexedit/draglabel.h60
-rw-r--r--khexedit/exportdialog.cc696
-rw-r--r--khexedit/exportdialog.h138
-rw-r--r--khexedit/fileinfodialog.cc330
-rw-r--r--khexedit/fileinfodialog.h74
-rw-r--r--khexedit/hexbuffer.cc5099
-rw-r--r--khexedit/hexbuffer.h2040
-rw-r--r--khexedit/hexclipboard.cc254
-rw-r--r--khexedit/hexclipboard.h40
-rw-r--r--khexedit/hexdrag.cc130
-rw-r--r--khexedit/hexdrag.h54
-rw-r--r--khexedit/hexeditorwidget.cc2443
-rw-r--r--khexedit/hexeditorwidget.h301
-rw-r--r--khexedit/hexeditstate.h596
-rw-r--r--khexedit/hexerror.cc69
-rw-r--r--khexedit/hexerror.h57
-rw-r--r--khexedit/hexmanagerwidget.cc370
-rw-r--r--khexedit/hexmanagerwidget.h202
-rw-r--r--khexedit/hexprinter.cc168
-rw-r--r--khexedit/hexprinter.h108
-rw-r--r--khexedit/hextoolwidget.cc416
-rw-r--r--khexedit/hextoolwidget.h81
-rw-r--r--khexedit/hexvalidator.cc329
-rw-r--r--khexedit/hexvalidator.h63
-rw-r--r--khexedit/hexviewwidget.cc2286
-rw-r--r--khexedit/hexviewwidget.h584
-rw-r--r--khexedit/hi16-app-khexedit.pngbin0 -> 411 bytes
-rw-r--r--khexedit/hi32-app-khexedit.pngbin0 -> 1146 bytes
-rw-r--r--khexedit/hi48-app-khexedit.pngbin0 -> 1878 bytes
-rw-r--r--khexedit/khexedit.desktop86
-rw-r--r--khexedit/khexeditui.rc137
-rw-r--r--khexedit/lib/Makefile.am39
-rw-r--r--khexedit/lib/README36
-rw-r--r--khexedit/lib/codecs/Makefile.am15
-rw-r--r--khexedit/lib/codecs/README1
-rw-r--r--khexedit/lib/codecs/kbinarybytecodec.cpp80
-rw-r--r--khexedit/lib/codecs/kbinarybytecodec.h59
-rw-r--r--khexedit/lib/codecs/kbytecodec.cpp63
-rw-r--r--khexedit/lib/codecs/kcharcodec.cpp74
-rw-r--r--khexedit/lib/codecs/kdecimalbytecodec.cpp92
-rw-r--r--khexedit/lib/codecs/kdecimalbytecodec.h59
-rw-r--r--khexedit/lib/codecs/kebcdic1047charcodec.cpp124
-rw-r--r--khexedit/lib/codecs/kebcdic1047charcodec.h50
-rw-r--r--khexedit/lib/codecs/khexadecimalbytecodec.cpp113
-rw-r--r--khexedit/lib/codecs/khexadecimalbytecodec.h69
-rw-r--r--khexedit/lib/codecs/koctalbytecodec.cpp80
-rw-r--r--khexedit/lib/codecs/koctalbytecodec.h59
-rw-r--r--khexedit/lib/codecs/ktextcharcodec.cpp236
-rw-r--r--khexedit/lib/codecs/ktextcharcodec.h66
-rw-r--r--khexedit/lib/controller/Makefile.am12
-rw-r--r--khexedit/lib/controller/kchareditor.cpp58
-rw-r--r--khexedit/lib/controller/kchareditor.h43
-rw-r--r--khexedit/lib/controller/kcontroller.cpp34
-rw-r--r--khexedit/lib/controller/kcontroller.h44
-rw-r--r--khexedit/lib/controller/keditor.cpp197
-rw-r--r--khexedit/lib/controller/keditor.h52
-rw-r--r--khexedit/lib/controller/knavigator.cpp142
-rw-r--r--khexedit/lib/controller/knavigator.h46
-rw-r--r--khexedit/lib/controller/ktabcontroller.cpp70
-rw-r--r--khexedit/lib/controller/ktabcontroller.h52
-rw-r--r--khexedit/lib/controller/kvalueeditor.cpp226
-rw-r--r--khexedit/lib/controller/kvalueeditor.h75
-rw-r--r--khexedit/lib/helper.h31
-rw-r--r--khexedit/lib/kadds.h36
-rw-r--r--khexedit/lib/kbigbuffer.cpp216
-rw-r--r--khexedit/lib/kbigbuffer.h119
-rw-r--r--khexedit/lib/kbordercoltextexport.cpp47
-rw-r--r--khexedit/lib/kbordercoltextexport.h40
-rw-r--r--khexedit/lib/kbordercolumn.cpp82
-rw-r--r--khexedit/lib/kbordercolumn.h52
-rw-r--r--khexedit/lib/kbuffercoltextexport.cpp108
-rw-r--r--khexedit/lib/kbuffercoltextexport.h73
-rw-r--r--khexedit/lib/kbuffercolumn.cpp700
-rw-r--r--khexedit/lib/kbuffercolumn.h253
-rw-r--r--khexedit/lib/kbuffercoord.h293
-rw-r--r--khexedit/lib/kbuffercursor.cpp365
-rw-r--r--khexedit/lib/kbuffercursor.h172
-rw-r--r--khexedit/lib/kbufferdrag.cpp237
-rw-r--r--khexedit/lib/kbufferdrag.h76
-rw-r--r--khexedit/lib/kbufferlayout.cpp240
-rw-r--r--khexedit/lib/kbufferlayout.h196
-rw-r--r--khexedit/lib/kbufferranges.cpp307
-rw-r--r--khexedit/lib/kbufferranges.h130
-rw-r--r--khexedit/lib/kbytecodec.h73
-rw-r--r--khexedit/lib/kbytesedit.cpp162
-rw-r--r--khexedit/lib/kbytesedit.h163
-rw-r--r--khexedit/lib/kcharcodec.h55
-rw-r--r--khexedit/lib/kcharcoltextexport.cpp71
-rw-r--r--khexedit/lib/kcharcoltextexport.h50
-rw-r--r--khexedit/lib/kcharcolumn.cpp61
-rw-r--r--khexedit/lib/kcharcolumn.h116
-rw-r--r--khexedit/lib/kcoltextexport.h40
-rw-r--r--khexedit/lib/kcolumn.cpp60
-rw-r--r--khexedit/lib/kcolumn.h126
-rw-r--r--khexedit/lib/kcolumnsview.cpp236
-rw-r--r--khexedit/lib/kcolumnsview.h168
-rw-r--r--khexedit/lib/kcoordrange.h95
-rw-r--r--khexedit/lib/kcoordrangelist.cpp78
-rw-r--r--khexedit/lib/kcoordrangelist.h44
-rw-r--r--khexedit/lib/kcursor.cpp49
-rw-r--r--khexedit/lib/kcursor.h68
-rw-r--r--khexedit/lib/kdatabuffer.cpp51
-rw-r--r--khexedit/lib/kdatabuffer.h246
-rw-r--r--khexedit/lib/kfixedsizebuffer.cpp272
-rw-r--r--khexedit/lib/kfixedsizebuffer.h116
-rw-r--r--khexedit/lib/khe.h95
-rw-r--r--khexedit/lib/khechar.h44
-rw-r--r--khexedit/lib/khexedit.cpp2032
-rw-r--r--khexedit/lib/khexedit.h562
-rw-r--r--khexedit/lib/khexedit_export.h25
-rw-r--r--khexedit/lib/koffsetcoltextexport.cpp61
-rw-r--r--khexedit/lib/koffsetcoltextexport.h57
-rw-r--r--khexedit/lib/koffsetcolumn.cpp110
-rw-r--r--khexedit/lib/koffsetcolumn.h109
-rw-r--r--khexedit/lib/koffsetformat.cpp48
-rw-r--r--khexedit/lib/koffsetformat.h70
-rw-r--r--khexedit/lib/kplainbuffer.cpp344
-rw-r--r--khexedit/lib/kplainbuffer.h131
-rw-r--r--khexedit/lib/krange.h123
-rw-r--r--khexedit/lib/kreadonlybuffer.h45
-rw-r--r--khexedit/lib/ksection.h108
-rw-r--r--khexedit/lib/ksectionlist.cpp79
-rw-r--r--khexedit/lib/ksectionlist.h44
-rw-r--r--khexedit/lib/kselection.h178
-rw-r--r--khexedit/lib/kvaluecoltextexport.cpp69
-rw-r--r--khexedit/lib/kvaluecoltextexport.h47
-rw-r--r--khexedit/lib/kvaluecolumn.cpp134
-rw-r--r--khexedit/lib/kvaluecolumn.h92
-rw-r--r--khexedit/lib/kwordbufferservice.cpp209
-rw-r--r--khexedit/lib/kwordbufferservice.h137
-rw-r--r--khexedit/lib/kwrappingrobuffer.cpp61
-rw-r--r--khexedit/lib/kwrappingrobuffer.h85
-rw-r--r--khexedit/listview.cc54
-rw-r--r--khexedit/listview.h49
-rw-r--r--khexedit/main.cc130
-rw-r--r--khexedit/optiondialog.cc1224
-rw-r--r--khexedit/optiondialog.h269
-rw-r--r--khexedit/parts/Makefile.am1
-rw-r--r--khexedit/parts/README3
-rw-r--r--khexedit/parts/kbytesedit/Makefile.am15
-rw-r--r--khexedit/parts/kbytesedit/README23
-rw-r--r--khexedit/parts/kbytesedit/kbyteseditwidget.cpp319
-rw-r--r--khexedit/parts/kbytesedit/kbyteseditwidget.desktop52
-rw-r--r--khexedit/parts/kbytesedit/kbyteseditwidget.h185
-rw-r--r--khexedit/parts/kpart/Makefile.am21
-rw-r--r--khexedit/parts/kpart/khebrowserextension.cpp95
-rw-r--r--khexedit/parts/kpart/khebrowserextension.h58
-rw-r--r--khexedit/parts/kpart/khepart.cpp213
-rw-r--r--khexedit/parts/kpart/khepart.h95
-rw-r--r--khexedit/parts/kpart/khepartfactory.cpp90
-rw-r--r--khexedit/parts/kpart/khepartfactory.h47
-rw-r--r--khexedit/parts/kpart/khexedit2part.desktop101
-rw-r--r--khexedit/parts/kpart/khexedit2partui.rc42
-rw-r--r--khexedit/pics/Makefile.am3
-rw-r--r--khexedit/pics/hexdrag.pngbin0 -> 459 bytes
-rw-r--r--khexedit/pics/hexmask.pngbin0 -> 188 bytes
-rw-r--r--khexedit/pics/hexwrite.pngbin0 -> 381 bytes
-rw-r--r--khexedit/printdialogpage.cc386
-rw-r--r--khexedit/printdialogpage.h73
-rw-r--r--khexedit/progress.h130
-rw-r--r--khexedit/searchbar.cc188
-rw-r--r--khexedit/searchbar.h73
-rw-r--r--khexedit/statusbarprogress.cc374
-rw-r--r--khexedit/statusbarprogress.h159
-rw-r--r--khexedit/stringdialog.cc412
-rw-r--r--khexedit/stringdialog.h110
-rw-r--r--khexedit/toplevel.cc1366
-rw-r--r--khexedit/toplevel.h279
-rw-r--r--khexedit/version.h32
183 files changed, 40949 insertions, 0 deletions
diff --git a/khexedit/Makefile.am b/khexedit/Makefile.am
new file mode 100644
index 0000000..bacaa75
--- /dev/null
+++ b/khexedit/Makefile.am
@@ -0,0 +1,35 @@
+INCLUDES = $(all_includes)
+
+SUBDIRS = pics lib parts
+
+bin_PROGRAMS = khexedit
+
+khexedit_SOURCES = main.cc toplevel.cc hexmanagerwidget.cc \
+hexeditorwidget.cc hextoolwidget.cc hexviewwidget.cc hexbuffer.cc \
+conversion.cc dialog.cc hexvalidator.cc hexclipboard.cc \
+optiondialog.cc printdialogpage.cc statusbarprogress.cc \
+hexprinter.cc hexerror.cc draglabel.cc stringdialog.cc \
+bitswapwidget.cc chartabledialog.cc hexdrag.cc exportdialog.cc \
+fileinfodialog.cc converterdialog.cc listview.cc searchbar.cc
+
+noinst_HEADERS = toplevel.h hexmanagerwidget.h hexeditorwidget.h \
+hextoolwidget.h hexviewwidget.h hexbuffer.h conversion.h dialog.h \
+hexvalidator.h hexclipboard.h optiondialog.h \
+printdialogpage.h statusbarprogress.h hexprinter.h hexerror.h \
+draglabel.h progress.h hexeditstate.h chartabledialog.h hexdrag.h \
+exportdialog.h fileinfodialog.h converterdialog.h listview.h searchbar.h
+
+khexedit_METASOURCES = AUTO
+khexedit_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+khexedit_LDADD = $(LIB_KIO) $(LIB_KDEPRINT)
+
+xdg_apps_DATA = khexedit.desktop
+
+KDE_ICON = khexedit
+
+rcdir = $(kde_datadir)/khexedit
+rc_DATA = khexeditui.rc
+
+messages: rc.cpp
+ $(EXTRACTRC) parts/kpart/*rc >> rc.cpp
+ $(XGETTEXT) rc.cpp `find . -name \*.cc -o -name \*.cpp` -o $(podir)/khexedit.pot
diff --git a/khexedit/README b/khexedit/README
new file mode 100644
index 0000000..ef686b7
--- /dev/null
+++ b/khexedit/README
@@ -0,0 +1,34 @@
+Overview
+--------
+To confuse you these directories mix two binary editor projects.
+The first project is the current khexedit app from Espen Sand,
+(here called KHE1). The second project is the coming khexedit app
+from Friedrich W. H. Kossebau (called KHE2) which has been already
+partly moved from kdenonbeta/khexedit2.
+
+
+What to find in which directory:
+--------------------------------
+khexedit:
+ sources of KHE1
+
+khexedit/pics:
+ pictures used by KHE1
+
+khexedit/lib:
+ sources of the basic library of KHE2
+
+khexedit/parts:
+ collection of all parts based on KHE2
+
+khexedit/parts/kbytesedit:
+ sources of the implementation for the service type KHexEdit/KBytesEdit
+
+
+Future plans:
+-------------
+* inclusion of the KReadWritePart based HexEdit2Part which can handle
+ GB sized files. (-> KDE 3.3)
+* a binary diff editor widget in the KHE2 lib
+* binary diff editor widget based parts
+* a standalone KHE2 app, replacing KHE1
diff --git a/khexedit/bitswapwidget.cc b/khexedit/bitswapwidget.cc
new file mode 100644
index 0000000..212d126
--- /dev/null
+++ b/khexedit/bitswapwidget.cc
@@ -0,0 +1,323 @@
+/*
+ * 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 <qpainter.h>
+
+#include <kglobalsettings.h>
+
+#include "bitswapwidget.h"
+
+CDigitLabel::CDigitLabel( QWidget *parent, uint digit, const char *name )
+ :QLabel(parent, name), mDigit( digit ), mDotPosition( 0 )
+{
+ setFocusPolicy( StrongFocus );
+ initialize();
+}
+
+CDigitLabel::~CDigitLabel( void )
+{
+
+}
+
+void CDigitLabel::initialize( void )
+{
+ QFont font( KGlobalSettings::generalFont() );
+ font.setBold( true );
+ setFont( font );
+}
+
+
+void CDigitLabel::paletteChange( const QPalette & )
+{
+ update();
+}
+
+
+void CDigitLabel::setValue( uint digit, bool notify )
+{
+ if( mDigit != digit )
+ {
+ if( notify == true )
+ {
+ emit valueChanged( this, digit, false );
+ }
+
+ mDigit = digit;
+ update();
+
+ if( notify == true )
+ {
+ emit valueChanged( this, mDigit, true );
+ }
+ }
+}
+
+
+void CDigitLabel::setDotPosition( uint dotPosition )
+{
+ if( mDotPosition != dotPosition )
+ {
+ mDotPosition = dotPosition;
+ update();
+ }
+}
+
+
+
+QSize CDigitLabel::sizeHint( void ) const
+{
+ int h = fontMetrics().height();
+ QSize s( h, h ); // Retangular
+ return( s );
+}
+
+
+#include <stdio.h>
+
+
+void CDigitLabel::drawContents( QPainter *p )
+{
+ QRect cr = contentsRect();
+
+ if( hasFocus() == true )
+ {
+ p->fillRect( cr, palette().active().highlight() );
+ p->setPen( palette().active().highlightedText() );
+ }
+ else
+ {
+ p->fillRect( cr, palette().active().base() );
+ p->setPen( palette().active().text() );
+ }
+
+ if( mDotPosition != 0 )
+ {
+ p->fillRect( cr.x()+2, cr.y()+2, 5, 5, Qt::red ); // UL
+ /*
+ if( mDotPosition == 1 )
+ {
+ p->fillRect( cr.x()+2, cr.y()+2, 5, 5, red ); // UL
+ }
+ else if( mDotPosition == 2 )
+ {
+ p->fillRect( cr.width()-7, cr.y()+2, 5, 5, red ); // UR
+ }
+ else if( mDotPosition == 3 )
+ {
+ p->fillRect( cr.x()+2, cr.height()-7, 5, 5, red ); // LL
+ }
+ else if( mDotPosition == 4 )
+ {
+ p->fillRect( cr.width()-7, cr.height()-7, 5, 5, red ); // LR
+ }
+ */
+ }
+
+ QString text;
+ text.setNum( mDigit );
+ p->drawText( 0, 0, cr.width(), cr.height(), alignment(), text );
+
+
+
+}
+
+
+void CDigitLabel::keyPressEvent( QKeyEvent *e )
+{
+ switch ( e->key() )
+ {
+ case Key_Left:
+ case Key_Up:
+ emit stepCell( this, false );
+ break;
+
+ case Key_Right:
+ case Key_Down:
+ emit stepCell( this, true );
+ break;
+
+ case Key_Escape:
+ e->ignore(); // Allow dialog or whatever use this one
+ return;
+ break;
+
+ default:
+ {
+ int val = e->text()[0].digitValue();
+ if( val >= 0 && val <= 7 )
+ {
+ setValue( val, true );
+ }
+ }
+ break;
+ }
+
+ e->accept();
+}
+
+
+
+CByteWidget::CByteWidget( QWidget *parent, const char *name )
+ :QWidget(parent, name)
+{
+ mHBox = new QHBoxLayout( this, 0 );
+
+ for( uint i=0; i<8; i++ )
+ {
+ mDigit[i] = new CDigitLabel( this, 7-i );
+ mDigit[i]->setLineWidth( 1 );
+ mDigit[i]->setFixedSize( mDigit[i]->sizeHint()*2 );
+ mDigit[i]->setFrameStyle( QFrame::Panel | QFrame::Sunken );
+ mDigit[i]->setAlignment( AlignCenter );
+ connect( mDigit[i], SIGNAL(stepCell(const QObject *, bool )),
+ this, SLOT(stepCell(const QObject *, bool )));
+ connect( mDigit[i], SIGNAL(valueChanged(const QObject *, uint, bool )),
+ this, SLOT(valueChanged(const QObject *, uint, bool )));
+ mHBox->addWidget( mDigit[i] );
+ }
+
+ mHBox->addStretch();
+}
+
+CByteWidget::~CByteWidget( void )
+{
+ for( uint i=0; i<8; i++ ) { delete mDigit[i]; }
+ delete mHBox;
+}
+
+void CByteWidget::stepCell( const QObject *obj, bool next )
+{
+ for( uint i=0; i<8; i++ )
+ {
+ if( obj == mDigit[i] )
+ {
+ if( next == true )
+ {
+ mDigit[(i+1)%8]->setFocus();
+ }
+ else
+ {
+ mDigit[(i+7)%8]->setFocus();
+ }
+ }
+ }
+}
+
+
+
+void CByteWidget::valueChanged( const QObject *obj, uint val, bool after )
+{
+ if( after == false )
+ {
+ for( uint i=0; i<8; i++ )
+ {
+ if( obj == mDigit[i] )
+ {
+ uint tmp = 7-mDigit[i]->value();
+ mDigit[tmp]->setValue( mDigit[i]->value(), false );
+ break;
+ }
+ }
+
+
+ if( mDigit[7-val]->value() != val )
+ {
+ uint tmp = mDigit[7-val]->value();
+ mDigit[7-tmp]->setValue( tmp, false );
+ mDigit[7-val]->setValue( val, false );
+ }
+
+ }
+ else
+ {
+ setBuddy( obj );
+
+ uint pos = 1;
+ for( uint i=0; i<8; i++ )
+ {
+ if( mDigit[i]->value() < (7-i) )
+ {
+ mDigit[i]->setDotPosition( pos );
+ mDigit[7-mDigit[i]->value()]->setDotPosition( pos );
+ pos++;
+ }
+ else if( mDigit[i]->value() == (7-i) )
+ {
+ mDigit[i]->setDotPosition( 0 );
+ }
+ }
+
+ }
+}
+
+
+void CByteWidget::reset( void )
+{
+ for( uint i=0; i<8; i++ )
+ {
+ mDigit[i]->setValue( 7-i, false );
+ mDigit[i]->setDotPosition( 0 );
+ }
+}
+
+
+void CByteWidget::setBuddy( const QObject *obj )
+{
+ for( uint i=0; i<8; i++ )
+ {
+ if( obj == mDigit[i] )
+ {
+ uint val = mDigit[i]->value();
+ if( val < 8 )
+ {
+ mDigit[7-val]->setValue( 7-i, false );
+ }
+ break;
+ }
+ }
+}
+
+
+
+
+
+bool CByteWidget::flag( QByteArray &buf )
+{
+ bool swapPresent = false;
+ uint i, j;
+
+ buf.resize( 8 );
+ for( i=0; i<8; buf[i++] = 0 );
+
+ for( i=j=0; i<8; i++ )
+ {
+ if( mDigit[i]->value() < (7-i) )
+ {
+ buf[j] = 7 - i; j++;
+ buf[j] = mDigit[i]->value(); j++;
+ swapPresent = true;
+ }
+ }
+
+ return( swapPresent );
+}
+
+
+#include "bitswapwidget.moc"
diff --git a/khexedit/bitswapwidget.h b/khexedit/bitswapwidget.h
new file mode 100644
index 0000000..f1d3582
--- /dev/null
+++ b/khexedit/bitswapwidget.h
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _BITSWAP_WIDGET_H_
+#define _BITSWAP_WIDGET_H_
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qstring.h>
+
+
+class CDigitLabel : public QLabel
+{
+ Q_OBJECT
+
+ public:
+ CDigitLabel( QWidget *parent, uint digit = 0, const char *name=0 );
+ ~CDigitLabel( void );
+
+ virtual QSize sizeHint() const;
+ inline uint value( void );
+
+ signals:
+ void stepCell( const QObject *obj, bool next );
+ void valueChanged( const QObject *obj, uint newVal, bool after );
+
+ public slots:
+ void setValue( uint digit, bool notify );
+ void setDotPosition( uint dotPosition );
+
+ protected:
+ void paletteChange( const QPalette & );
+ void drawContents( QPainter * );
+ virtual void keyPressEvent( QKeyEvent *e );
+
+ private:
+ void initialize( void );
+
+ private:
+ uint mDigit;
+ uint mDotPosition;
+};
+
+
+inline uint CDigitLabel::value( void )
+{
+ return( mDigit );
+}
+
+
+
+
+class CByteWidget : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ CByteWidget( QWidget *parent, const char *name=0 );
+ ~CByteWidget( void );
+
+ bool flag( QByteArray &buf );
+
+ public slots:
+ void reset( void );
+
+ private slots:
+ void stepCell( const QObject *obj, bool next );
+ void valueChanged( const QObject *obj, uint newVal, bool after );
+
+ private:
+ void setBuddy( const QObject *obj );
+
+ private:
+ QHBoxLayout *mHBox;
+ CDigitLabel *mDigit[8];
+};
+
+
+
+
+
+
+
+#endif
diff --git a/khexedit/chartabledialog.cc b/khexedit/chartabledialog.cc
new file mode 100644
index 0000000..1914750
--- /dev/null
+++ b/khexedit/chartabledialog.cc
@@ -0,0 +1,212 @@
+/*
+ * 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 <limits.h>
+
+#include <qlabel.h>
+#include <qheader.h>
+#include <qlayout.h>
+#include <qspinbox.h>
+
+#include <kglobalsettings.h>
+#include <klocale.h>
+#include <kstdguiitem.h>
+
+#include "chartabledialog.h"
+
+
+CCharTableDialog::CCharTableDialog( QWidget *parent, const char *name,
+ bool modal )
+ :KDialogBase( Plain, i18n("Character Table"), Help|User1|Cancel, User1,
+ parent, name, modal, true, KStdGuiItem::insert())
+{
+ updateGeometry();
+ setHelp( "khexedit/khexedit.html", QString::null );
+
+ QString text;
+ QVBoxLayout *topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() );
+ if( topLayout == 0 ) { return; }
+
+ mCharacterList = new CListView( plainPage(), "characterList" );
+ mCharacterList->setFont( KGlobalSettings::fixedFont() );
+ mCharacterList->addColumn( i18n("Decimal") );
+ mCharacterList->addColumn( i18n("Hexadecimal") );
+ mCharacterList->addColumn( i18n("Octal") );
+ mCharacterList->addColumn( i18n("Binary") );
+ mCharacterList->addColumn( i18n("Text") );
+ mCharacterList->setAllColumnsShowFocus( true );
+ mCharacterList->setFrameStyle( QFrame::WinPanel + QFrame::Sunken );
+ mCharacterList->setSorting( -1 );
+
+ //
+ // I am setting the min. size below
+ //
+ //connect( mCharacterList, SIGNAL(doubleClicked(QListViewItem *) ),
+ //SLOT(startAssign(QListViewItem *)));
+
+ topLayout->addWidget( mCharacterList, 10 );
+
+ QHBoxLayout *hbox = new QHBoxLayout();
+ if( hbox == 0 ) { return; }
+ topLayout->addLayout( hbox );
+
+ text = i18n("Insert this number of characters:");
+ QLabel *label = new QLabel( text, plainPage() );
+ label->setFixedWidth( label->sizeHint().width() );
+ hbox->addWidget( label );
+
+ mInputCountSpin = new QSpinBox( plainPage(), "spin" );
+ mInputCountSpin->setMinimumWidth( fontMetrics().maxWidth()*7 );
+ mInputCountSpin->setRange( 1, INT_MAX );
+ mInputCountSpin->setValue( 1 );
+ hbox->addWidget( mInputCountSpin );
+
+ hbox->addStretch ( 10 );
+
+ createListData();
+ setColumnWidth();
+ mCharacterList->setVisibleItem( 15 );
+}
+
+
+
+CCharTableDialog::~CCharTableDialog( void )
+{
+}
+
+
+const char *printBinary( uint val )
+{
+ static char buf[9];
+ for( int i = 0; i < 8; i++ )
+ {
+ buf[7-i] = (val&(1<<i)) ? '1' : '0';
+ }
+ buf[8] = 0;
+ return( buf );
+}
+
+
+void CCharTableDialog::createListData( void )
+{
+ QString d, h, o, b, c;
+ QListViewItem *item = 0;
+
+ char buf[10];
+ memset( buf, 0, sizeof( buf ) );
+
+ for( uint i=0; i<256; i++ )
+ {
+ d.sprintf("%03d", i );
+ h.sprintf("0x%02x", i );
+ o.sprintf("%03o", i );
+ b.sprintf("%s", printBinary(i) );
+
+ if( QChar((char)i).isPrint() == true )
+ {
+ c = QChar((char)i);
+ }
+ else
+ {
+ c = QChar('.');
+ }
+
+ item = new QListViewItem( mCharacterList, item, d, h, o, b, c );
+ if( i == 0 )
+ {
+ mCharacterList->setSelected( item, true );
+ }
+
+ }
+}
+
+
+void CCharTableDialog::slotUser1( void ) // Insert
+{
+ QListViewItem *item = mCharacterList->selectedItem();
+ if( item != 0 )
+ {
+ startAssign( item );
+ }
+
+}
+
+void CCharTableDialog::startAssign( QListViewItem *item )
+{
+ QByteArray buf;
+ if( buf.fill( item->text(0).toInt(), mInputCountSpin->value() ) == false )
+ {
+ return;
+ }
+ emit assign( buf );
+}
+
+
+void CCharTableDialog::setColumnWidth( void )
+{
+ const QFontMetrics &fm = mCharacterList->fontMetrics();
+ int w0, w1, w2, w3, w4;
+
+ w0 = -fm.minLeftBearing() - fm.minRightBearing() + 8 + fm.maxWidth();
+ w3 = 0;
+
+ w1 = fm.width( mCharacterList->header()->label(0) ) + w0;
+ w2 = fm.width('0')*5;
+ w3 += w1 > w2 ? w1 : w2;
+ mCharacterList->setColumnWidth( 0, w1 > w2 ? w1 : w2 );
+
+ w1 = fm.boundingRect( mCharacterList->header()->label(1) ).width() + w0;
+ w2 = fm.width('0')*6;
+ w3 += w1 > w2 ? w1 : w2;
+ mCharacterList->setColumnWidth( 1, w1 > w2 ? w1 : w2 );
+
+ w1 = fm.boundingRect( mCharacterList->header()->label(2) ).width() + w0;
+ w2 = fm.width('0')*5;
+ w3 += w1 > w2 ? w1 : w2;
+ mCharacterList->setColumnWidth( 2, w1 > w2 ? w1 : w2 );
+
+ w1 = fm.boundingRect( mCharacterList->header()->label(3) ).width() + w0;
+ w2 = fm.width('0')*10;
+ w3 += w1 > w2 ? w1 : w2;
+ mCharacterList->setColumnWidth( 3, w1 > w2 ? w1 : w2 );
+
+ w4 = mCharacterList->viewport()->width() - w3;
+ w1 = fm.boundingRect( mCharacterList->header()->label(4) ).width() + w0;
+ w2 = fm.width('0')*3;
+ w1 = w1 > w2 ? w1 : w2;
+ mCharacterList->setColumnWidth( 4, w1 > w4 ? w1 : w4 );
+}
+
+
+void CCharTableDialog::resizeEvent( QResizeEvent * )
+{
+ setColumnWidth();
+}
+
+
+void CCharTableDialog::showEvent( QShowEvent *e )
+{
+ KDialogBase::showEvent(e);
+ setColumnWidth();
+ mCharacterList->setFocus();
+}
+
+
+#include "chartabledialog.moc"
diff --git a/khexedit/chartabledialog.h b/khexedit/chartabledialog.h
new file mode 100644
index 0000000..a35246b
--- /dev/null
+++ b/khexedit/chartabledialog.h
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _CHAR_TABLE_DIALOG_H_
+#define _CHAR_TABLE_DIALOG_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+class QLabel;
+class QSpinBox;
+
+#include <kdialogbase.h>
+#include "listview.h"
+
+
+class CCharTableDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ CCharTableDialog( QWidget *parent=0, const char *name=0,bool modal=false );
+ ~CCharTableDialog( void );
+
+ signals:
+ void assign( const QByteArray &buf );
+
+ protected slots:
+ virtual void slotUser1( void );
+ virtual void startAssign( QListViewItem * );
+
+ protected:
+ virtual void resizeEvent( QResizeEvent *e );
+ virtual void showEvent( QShowEvent *e );
+
+ private:
+ void createListData( void );
+ void setColumnWidth( void );
+
+ private:
+ QSpinBox *mInputCountSpin;
+ CListView *mCharacterList;
+};
+
+#endif
+
+
+
+
+
+
+
+
+
diff --git a/khexedit/configure.in.in b/khexedit/configure.in.in
new file mode 100644
index 0000000..8f094fa
--- /dev/null
+++ b/khexedit/configure.in.in
@@ -0,0 +1,8 @@
+# kossebau: copied from kdelibs/configure.in.in for khexedit
+AC_LANG_SAVE
+AC_LANG_C
+dnl AC_C_BIGENDIAN has a bug (one of its tests uses "main()" instead of
+dnl "int main()") so C++ compilers would break. Thats why we switch languages
+AC_C_BIGENDIAN
+AC_LANG_RESTORE
+# kossebau end
diff --git a/khexedit/conversion.cc b/khexedit/conversion.cc
new file mode 100644
index 0000000..7a5c25c
--- /dev/null
+++ b/khexedit/conversion.cc
@@ -0,0 +1,395 @@
+/*
+ * 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 <string.h>
+
+#include <klocale.h>
+
+#include "conversion.h"
+
+
+CConversion::CConversion( void )
+{
+ setMode( cnvDefault );
+}
+
+
+CConversion::EMode CConversion::mode( void )
+{
+ return( (EMode)mState.mode );
+}
+
+const SEncodeState &CConversion::state( void )
+{
+ return( mState );
+}
+
+QString CConversion::names( unsigned int index )
+{
+ static const QString strings[4] =
+ {
+ i18n("Default encoding", "Default"),
+ i18n("EBCDIC"),
+ i18n("US-ASCII (7 bit)"),
+ i18n("Unknown"),
+ };
+
+ return( strings[ index > cnvUsAscii ? 3 : index ] );
+}
+
+
+const unsigned char *CConversion::tables( EMode cnvMode )
+{
+ /*
+ static unsigned char ebcdicToLatin1[256] =
+ {
+ 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F,
+ 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87,
+ 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B,
+ 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,
+ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
+ 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,
+ 0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5,
+ 0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
+ 0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF,
+ 0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
+ 0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5,
+ 0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
+ 0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF,
+ 0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
+ 0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1,
+ 0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+ 0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4,
+ 0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0x5B, 0xDE, 0xAE,
+ 0xAC, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC,
+ 0xBD, 0xBE, 0xDD, 0xA8, 0xAF, 0x5D, 0xB4, 0xD7,
+ 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5,
+ 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
+ 0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF,
+ 0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F
+ };
+ */
+
+ static unsigned char ebcdicToLatin1[256] =
+ {
+ 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F,
+ 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87,
+ 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B,
+ 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,
+ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
+ 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,
+ 0x20, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0x5B, 0x2E, 0x3C, 0x28, 0x2B, 0x21,
+ 0x26, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
+ 0xB0, 0xB1, 0x5D, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
+ 0x2D, 0x2F, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
+ 0xB8, 0xB9, 0x7C, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
+ 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1,
+ 0xC2, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
+ 0xC3, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
+ 0xCA, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+ 0x71, 0x72, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0,
+ 0xD1, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7A, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
+ 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+ 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED,
+ 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
+ 0x51, 0x52, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3,
+ 0x5C, 0x9F, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5A, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
+ };
+
+ static unsigned char buf[256];
+
+
+ if( cnvMode == cnvEbcdic )
+ {
+ return( ebcdicToLatin1 );
+ }
+ else if( cnvMode == cnvUsAscii )
+ {
+ memset( buf, 0, 256 );
+ for( unsigned int i=0; i<127; i++ ) { buf[i] = i; }
+ return( buf );
+ }
+ else if( cnvMode == cnvDefault )
+ {
+ for( unsigned int i=0; i<256; i++ ) { buf[i] = i; }
+ return( buf );
+ }
+ else
+ {
+ return( 0 );
+ }
+}
+
+
+void CConversion::setMode( EMode cnvMode )
+{
+ const unsigned char *table = tables( cnvMode );
+ if( table == 0 )
+ {
+ cnvMode = cnvDefault;
+ table = tables( cnvMode );
+ }
+
+ mState.mode = cnvMode;
+ mState.name = names( mState.mode );
+ memcpy( mData, table, 256 );
+}
+
+
+bool CConversion::lossless( EMode cnvMode )
+{
+ const unsigned char *table = tables( cnvMode );
+ if( table == 0 )
+ {
+ return( false );
+ }
+
+ unsigned char flag[256];
+ memset( flag, 0, sizeof( flag ) );
+
+ for( uint i=0; i<256; i++ )
+ {
+ int index = table[i];
+ if( flag[index] != 0 )
+ {
+ return( false );
+ }
+ flag[index] += 1;
+ }
+
+ return( true );
+}
+
+
+
+#if 0
+void CConversion::setMode( EMode cnvMode )
+{
+ /*
+ static unsigned char ebcdicToLatin1[256] =
+ {
+ 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F,
+ 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87,
+ 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B,
+ 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,
+ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
+ 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,
+ 0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5,
+ 0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
+ 0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF,
+ 0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
+ 0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5,
+ 0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
+ 0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF,
+ 0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
+ 0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1,
+ 0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+ 0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4,
+ 0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0x5B, 0xDE, 0xAE,
+ 0xAC, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC,
+ 0xBD, 0xBE, 0xDD, 0xA8, 0xAF, 0x5D, 0xB4, 0xD7,
+ 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5,
+ 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
+ 0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF,
+ 0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F
+ };
+ */
+
+ static unsigned char ebcdicToLatin1[256] =
+ {
+ 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F,
+ 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87,
+ 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B,
+ 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,
+ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
+ 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,
+ 0x20, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0x5B, 0x2E, 0x3C, 0x28, 0x2B, 0x21,
+ 0x26, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
+ 0xB0, 0xB1, 0x5D, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
+ 0x2D, 0x2F, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
+ 0xB8, 0xB9, 0x7C, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
+ 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1,
+ 0xC2, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
+ 0xC3, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
+ 0xCA, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+ 0x71, 0x72, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0,
+ 0xD1, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7A, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
+ 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+ 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED,
+ 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
+ 0x51, 0x52, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3,
+ 0x5C, 0x9F, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5A, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
+ };
+
+
+ if( cnvMode == cnvEbcdic )
+ {
+ memcpy( mData, ebcdicToLatin1, 256 );
+ }
+ else if( cnvMode == cnvUsAscii )
+ {
+ memset( mData, 0, 256 );
+ for( unsigned int i=0; i<127; i++ ) { mData[i] = i; }
+ }
+ else
+ {
+ for( unsigned int i=0; i<256; i++ ) { mData[i] = i; }
+ cnvMode = cnvDefault;
+ }
+
+ mState.mode = cnvMode;
+ mState.name = names( mState.mode );
+}
+#endif
+
+
+
+
+int CConversion::convert( QByteArray &buf, EMode newMode, CProgress &p )
+{
+ if( newMode == mode() )
+ {
+ p.finish();
+ return( Err_Success );
+ }
+
+ if( buf.isEmpty() )
+ {
+ p.finish();
+ setMode( newMode );
+ return( Err_Success );
+ }
+
+ //
+ // Make backup
+ //
+ const QByteArray tmp( buf.copy() );
+ if( tmp.isEmpty() )
+ {
+ p.finish();
+ return( Err_NoMemory );
+ }
+
+ unsigned char rev[256];
+ uint i, sum;
+
+ sum = 0;
+
+ const float total = buf.size() * 2.0;
+
+ //
+ // Prepare reverse buffer.
+ //
+ for( i=0; i < 256; i++ )
+ {
+ rev[(unsigned char)mData[i]] = i;
+ }
+
+ //
+ // Normalize
+ //
+ for( i=0; i<buf.size(); i++, sum++ )
+ {
+ buf[i] = rev[ (unsigned char)buf[i] ];
+
+ //
+ // The expired() function introduces too much overhead in this case
+ // so it is only executed every 100'th character
+ //
+ if( i % 100 == 0 && p.expired() == true )
+ {
+ const int errCode = p.step( (float)sum/ total );
+ if( errCode == Err_Stop )
+ {
+ buf = tmp;
+ p.finish();
+ return( Err_OperationAborted );
+ }
+ }
+ }
+
+ EMode origMode = mode();
+ setMode( newMode );
+
+ //
+ // Apply new encoding.
+ //
+ for( uint i=0; i<buf.size(); i++, sum++ )
+ {
+ buf[i] = mData[ (unsigned char)buf[i] ];
+
+ //
+ // The expired() function introduces too much overhead in this case
+ // so it is only executed every 100'th character
+ //
+ if( i % 100 == 0 && p.expired() == true )
+ {
+ const int errCode = p.step( (float)sum/ total );
+ if( errCode == Err_Stop )
+ {
+ buf = tmp;
+ setMode( origMode );
+ p.finish();
+ return( Err_OperationAborted );
+ }
+ }
+ }
+
+ p.finish();
+ return( Err_Success );
+}
+
+
diff --git a/khexedit/conversion.h b/khexedit/conversion.h
new file mode 100644
index 0000000..ef453ca
--- /dev/null
+++ b/khexedit/conversion.h
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _CONVERSION_H_
+#define _CONVERSION_H_
+
+#include <qstring.h>
+
+#include "progress.h"
+
+
+struct SEncodeState
+{
+ unsigned int mode;
+ QString name;
+};
+
+
+class CConversion
+{
+ public:
+ enum EMode
+ {
+ cnvDefault = 0,
+ cnvEbcdic,
+ cnvUsAscii
+ };
+
+ public:
+ CConversion( void );
+
+ int convert( QByteArray &buf, EMode mode, CProgress &p );
+ bool lossless( EMode cnvMode );
+
+ EMode mode( void );
+ const SEncodeState &state( void );
+
+ unsigned char operator[]( unsigned int i ) const
+ {
+ return( mData[i] );
+ }
+
+ private:
+ QString names( unsigned int index );
+ const unsigned char *tables( EMode cnvMode );
+ void setMode( EMode cnvMode );
+
+ private:
+ SEncodeState mState;
+ unsigned char mData[256];
+};
+
+
+#endif
diff --git a/khexedit/converterdialog.cc b/khexedit/converterdialog.cc
new file mode 100644
index 0000000..f8dd9be
--- /dev/null
+++ b/khexedit/converterdialog.cc
@@ -0,0 +1,163 @@
+/*
+ * khexedit - Versatile hex editor
+ * Copyright (C) 1999-2000 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 <qlabel.h>
+#include <qlayout.h>
+
+#include <klocale.h>
+
+#include "converterdialog.h"
+#include "hexvalidator.h"
+
+
+CValidateLineEdit::CValidateLineEdit( QWidget *parent, int validateType,
+ const char *name )
+ :QLineEdit( parent, name ), mBusy(false)
+{
+ mValidator = new CHexValidator( this, (CHexValidator::EState)validateType );
+ setValidator( mValidator );
+ connect( this, SIGNAL(textChanged(const QString &)),
+ this, SLOT(convertText(const QString &)) );
+}
+
+
+CValidateLineEdit::~CValidateLineEdit( void )
+{
+}
+
+
+void CValidateLineEdit::setData( const QByteArray &buf )
+{
+ if( mBusy == false )
+ {
+ QString text;
+ mValidator->format( text, buf );
+ setText( text );
+ }
+}
+
+
+void CValidateLineEdit::convertText( const QString &text )
+{
+ QByteArray buf;
+ mValidator->convert( buf, text );
+ mBusy = true; // Don't update while editing
+ emit dataChanged( buf );
+ mBusy = false;
+}
+
+
+
+CConverterDialog::CConverterDialog( QWidget *parent, const char *name,
+ bool modal )
+ :KDialogBase( parent, name, modal, i18n("Converter"), Cancel|User2|User1,
+ Cancel, true, KStdGuiItem::clear(), i18n("&On Cursor") )
+{
+ QWidget *page = new QWidget( this );
+ setMainWidget( page );
+
+ QGridLayout *topLayout = new QGridLayout( page, 6, 2, 0, spacingHint() );
+ topLayout->setRowStretch( 5, 10 );
+ topLayout->setColStretch( 1, 10 );
+
+ QLabel *label = new QLabel( i18n("Hexadecimal:"), page );
+ topLayout->addWidget( label, 0, 0 );
+ label = new QLabel( i18n("Decimal:"), page );
+ topLayout->addWidget( label, 1, 0 );
+ label = new QLabel( i18n("Octal:"), page );
+ topLayout->addWidget( label, 2, 0 );
+ label = new QLabel( i18n("Binary:"), page );
+ topLayout->addWidget( label, 3, 0 );
+ label = new QLabel( i18n("Text:"), page );
+ topLayout->addWidget( label, 4, 0 );
+
+ mHexInput = new CValidateLineEdit( page, CHexValidator::hexadecimal );
+ mHexInput->setMinimumWidth( fontMetrics().maxWidth()*17 );
+ topLayout->addWidget( mHexInput, 0, 1 );
+ mDecInput = new CValidateLineEdit( page, CHexValidator::decimal );
+ topLayout->addWidget( mDecInput, 1, 1 );
+ mOctInput = new CValidateLineEdit( page, CHexValidator::octal );
+ topLayout->addWidget( mOctInput, 2, 1 );
+ mBinInput = new CValidateLineEdit( page, CHexValidator::binary );
+ topLayout->addWidget( mBinInput, 3, 1 );
+ mTxtInput = new CValidateLineEdit( page, CHexValidator::regularText );
+ topLayout->addWidget( mTxtInput, 4, 1 );
+
+ connect( mHexInput, SIGNAL(dataChanged(const QByteArray &)),
+ this, SLOT(setData(const QByteArray &)) );
+ connect( mDecInput, SIGNAL(dataChanged(const QByteArray &)),
+ this, SLOT(setData(const QByteArray &)) );
+ connect( mOctInput, SIGNAL(dataChanged(const QByteArray &)),
+ this, SLOT(setData(const QByteArray &)) );
+ connect( mBinInput, SIGNAL(dataChanged(const QByteArray &)),
+ this, SLOT(setData(const QByteArray &)) );
+ connect( mTxtInput, SIGNAL(dataChanged(const QByteArray &)),
+ this, SLOT(setData(const QByteArray &)) );
+
+}
+
+
+CConverterDialog::~CConverterDialog( void )
+{
+}
+
+
+void CConverterDialog::showEvent( QShowEvent *e )
+{
+ KDialogBase::showEvent(e);
+ mHexInput->setFocus();
+}
+
+
+void CConverterDialog::setData( const QByteArray &data )
+{
+ mHexInput->blockSignals(true);
+ mDecInput->blockSignals(true);
+ mOctInput->blockSignals(true);
+ mBinInput->blockSignals(true);
+ mTxtInput->blockSignals(true);
+ mHexInput->setData(data);
+ mDecInput->setData(data);
+ mOctInput->setData(data);
+ mBinInput->setData(data);
+ mTxtInput->setData(data);
+ mHexInput->blockSignals(false);
+ mDecInput->blockSignals(false);
+ mOctInput->blockSignals(false);
+ mBinInput->blockSignals(false);
+ mTxtInput->blockSignals(false);
+}
+
+void CConverterDialog::slotUser1( void ) // Clear
+{
+ QByteArray buf;
+ setData( buf );
+}
+
+void CConverterDialog::slotUser2( void ) // On Cursor
+{
+ QByteArray buf;
+ emit probeCursorValue( buf, 1 );
+ setData( buf );
+}
+
+
+#include "converterdialog.moc"
diff --git a/khexedit/converterdialog.h b/khexedit/converterdialog.h
new file mode 100644
index 0000000..f84fe66
--- /dev/null
+++ b/khexedit/converterdialog.h
@@ -0,0 +1,83 @@
+/*
+ * khexedit - Versatile hex editor
+ * Copyright (C) 1999-2000 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.
+ *
+ */
+
+#ifndef _CONVERTER_DIALOG_H_
+#define _CONVERTER_DIALOG_H_
+
+#include <qlineedit.h>
+#include <kdialogbase.h>
+
+class CHexValidator;
+
+
+class CValidateLineEdit : public QLineEdit
+{
+ Q_OBJECT
+
+ public:
+ CValidateLineEdit( QWidget *parent, int validateType, const char *name=0 );
+ ~CValidateLineEdit( void );
+
+ public slots:
+ void setData( const QByteArray &buf );
+
+ private slots:
+ void convertText( const QString &text );
+
+ signals:
+ void dataChanged( const QByteArray &buf );
+
+ private:
+ bool mBusy;
+ CHexValidator *mValidator;
+};
+
+
+class CConverterDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ CConverterDialog( QWidget *parent, const char *name=0, bool modal=true );
+ ~CConverterDialog( void );
+
+ protected:
+ void showEvent( QShowEvent *e );
+
+ protected slots:
+ virtual void slotUser1( void );
+ virtual void slotUser2( void );
+
+ private slots:
+ void setData( const QByteArray &data );
+
+ signals:
+ void probeCursorValue( QByteArray &buf, uint size );
+
+ private:
+ CValidateLineEdit *mHexInput;
+ CValidateLineEdit *mDecInput;
+ CValidateLineEdit *mOctInput;
+ CValidateLineEdit *mBinInput;
+ CValidateLineEdit *mTxtInput;
+};
+
+#endif
+
diff --git a/khexedit/dialog.cc b/khexedit/dialog.cc
new file mode 100644
index 0000000..6ef1273
--- /dev/null
+++ b/khexedit/dialog.cc
@@ -0,0 +1,1433 @@
+/*
+ * 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 <ctype.h>
+#include <iostream>
+#include <limits.h>
+
+#include <qbuttongroup.h>
+#include <qfileinfo.h>
+#include <qlayout.h>
+#include <qvalidator.h>
+
+#include <kfiledialog.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kseparator.h>
+#include <kstdguiitem.h>
+
+#include "dialog.h"
+#include <qpushbutton.h>
+
+static const QStringList &formatStrings( void );
+static const QStringList &operationStrings( void );
+
+
+CGotoDialog::CGotoDialog( QWidget *parent, const char *name, bool modal )
+ :KDialogBase( Plain, i18n("Goto Offset"), Ok|Cancel, Ok, parent, name,
+ modal )
+{
+ QVBoxLayout *topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() );
+ if( topLayout == 0 ) { return; }
+
+ QVBoxLayout *vbox = new QVBoxLayout();
+ if( vbox == 0 ) { return; }
+ topLayout->addLayout( vbox );
+
+ mComboBox = new QComboBox( true, plainPage() );
+ if( mComboBox == 0 ) { return; }
+ mComboBox->setMaxCount( 10 );
+ mComboBox->setInsertionPolicy( QComboBox::AtTop );
+ mComboBox->setMinimumWidth( fontMetrics().maxWidth()*17 );
+
+ QLabel *label = new QLabel( mComboBox, i18n("O&ffset:"), plainPage() );
+ if( label == 0 ) { return; }
+
+ vbox->addWidget( label );
+ vbox->addWidget( mComboBox );
+
+ QButtonGroup *group = new QButtonGroup( i18n("Options"), plainPage() );
+ if( group == 0 ) { return; }
+ topLayout->addWidget( group, 10 );
+
+ QGridLayout *gbox = new QGridLayout( group, 4, 2, spacingHint() );
+ if( gbox == 0 ) { return; }
+ gbox->addRowSpacing( 0, fontMetrics().lineSpacing() );
+ mCheckFromCursor = new QCheckBox( i18n("&From cursor"), group );
+ gbox->addWidget( mCheckFromCursor, 1, 0 );
+ mCheckBackward = new QCheckBox( i18n("&Backwards"), group );
+ gbox->addWidget( mCheckBackward, 1, 1 );
+ mCheckVisible = new QCheckBox( i18n("&Stay visible"), group );
+ gbox->addWidget( mCheckVisible, 2, 0 );
+ gbox->setRowStretch( 3, 10 );
+
+ KConfig &config = *kapp->config();
+ config.setGroup("Goto Dialog");
+ mCheckFromCursor->setChecked( config.readBoolEntry( "FromCursor", false ) );
+ mCheckVisible->setChecked( config.readBoolEntry( "StayVisible", true ) );
+ mCheckBackward->setChecked( config.readBoolEntry( "Backwards", false ) );
+}
+
+
+
+CGotoDialog::~CGotoDialog( void )
+{
+ KConfig &config = *kapp->config();
+ config.setGroup("Goto Dialog");
+ config.writeEntry( "FromCursor", mCheckFromCursor->isChecked() );
+ config.writeEntry( "StayVisible", mCheckVisible->isChecked() );
+ config.writeEntry( "Backwards", mCheckBackward->isChecked() );
+ config.sync();
+}
+
+
+
+void CGotoDialog::showEvent( QShowEvent *e )
+{
+ KDialogBase::showEvent(e);
+ mComboBox->setFocus();
+}
+
+
+
+//
+// Format of input string:
+// 0x<HexNumber>|<DecimalNumber>s<Bit>
+// s = :,. or space
+//
+void CGotoDialog::slotOk( void )
+{
+ uint offset;
+ bool success = stringToOffset( mComboBox->currentText(), offset );
+ if( success == false )
+ {
+ showEntryFailure( this, QString("") );
+ return;
+ }
+
+ if( mCheckVisible->isChecked() == false )
+ {
+ hide();
+ }
+ emit gotoOffset( offset, 7, mCheckFromCursor->isChecked(),
+ mCheckBackward->isChecked() == true ? false : true );
+
+ #if 0
+ const char *p = mComboBox->currentText();
+ if( strlen( p ) == 0 )
+ {
+ return;
+ }
+
+ //
+ // Skip any whitespaces in front of string
+ //
+ for( ; *p != 0 && isspace( *p ) ; p++ );
+
+ uint offset, bit;
+ int match;
+ if( strncmp( p, "0x", 2 ) == 0 || strncmp( p, "0X", 2 ) == 0 )
+ {
+ match = sscanf( p+2, "%x", &offset );
+ }
+ else
+ {
+ match = sscanf( p, "%u", &offset );
+ }
+
+ if( match == 0 )
+ {
+ return;
+ }
+
+ bit = 7;
+
+ p = strpbrk( p, ":,. " );
+ if( p != 0 )
+ {
+ match = sscanf( p+1, "%u", &bit );
+ if( match == 0 )
+ {
+ return;
+ }
+ if( bit > 7 ) { bit = 7; }
+ }
+ #endif
+}
+
+
+
+CFindDialog::CFindDialog( QWidget *parent, const char *name, bool modal )
+ :KDialogBase( Plain, i18n("Find"), Ok|Cancel, Ok, parent, name, modal )
+{
+
+ QVBoxLayout *topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() );
+ if( topLayout == 0 ) { return; }
+
+ QVBoxLayout *vbox = new QVBoxLayout();
+ if( vbox == 0 ) { return; }
+ topLayout->addLayout( vbox );
+
+ mSelector = new QComboBox( false, plainPage() );
+ if( mSelector == 0 ) { return; }
+ mSelector->setMinimumWidth( fontMetrics().maxWidth()*17 );
+ mSelector->insertStringList( formatStrings() );
+ connect( mSelector, SIGNAL(activated(int)), SLOT(selectorChanged(int)) );
+
+ QLabel *label = new QLabel( mSelector, i18n("Fo&rmat:"), plainPage() );
+ if( label == 0 ) { return; }
+
+ vbox->addWidget( label );
+ vbox->addWidget( mSelector );
+
+ mInput = new QLineEdit( plainPage() );
+ if( mInput == 0 ) { return; }
+ mInput->setMinimumWidth( fontMetrics().maxWidth()*17 );
+ connect( mInput, SIGNAL(textChanged(const QString&)),
+ SLOT(inputChanged(const QString&)) );
+ mFindValidator = new CHexValidator( this, CHexValidator::regularText );
+ if( mFindValidator == 0 ) { return; }
+ mInput->setValidator( mFindValidator );
+
+ label = new QLabel( mInput, i18n("F&ind:"), plainPage() );
+ if( label == 0 ) { return; }
+
+ vbox->addWidget( label );
+ vbox->addWidget( mInput );
+
+ QButtonGroup *group = new QButtonGroup( i18n("Options"), plainPage() );
+ if( group == 0 ) { return; }
+ topLayout->addWidget( group, 10 );
+
+ QGridLayout *gbox = new QGridLayout( group, 5, 2, spacingHint() );
+ if( gbox == 0 ) { return; }
+ gbox->addRowSpacing( 0, fontMetrics().lineSpacing() );
+
+ mCheckFromCursor = new QCheckBox( i18n("&From cursor"), group );
+ gbox->addWidget( mCheckFromCursor, 1, 0 );
+ mCheckBackward = new QCheckBox( i18n("&Backwards"), group );
+ gbox->addWidget( mCheckBackward, 1, 1 );
+ mCheckInSelection = new QCheckBox( i18n("&In selection"), group );
+ gbox->addWidget( mCheckInSelection, 2, 0 );
+ mCheckUseNavigator = new QCheckBox( i18n("&Use navigator"),group);
+ gbox->addWidget( mCheckUseNavigator, 2, 1 );
+ mCheckIgnoreCase = new QCheckBox( i18n("Ignore c&ase"),group);
+ gbox->addWidget( mCheckIgnoreCase, 3, 0 );
+ gbox->setRowStretch( 4, 10 );
+
+ KConfig &config = *kapp->config();
+ config.setGroup("Find Dialog");
+ mCheckFromCursor->setChecked( config.readBoolEntry( "FromCursor", true ) );
+ mCheckInSelection->setChecked( config.readBoolEntry( "InSelection", false) );
+ mCheckIgnoreCase->setChecked( config.readBoolEntry( "IgnoreCase", false ) );
+ mCheckBackward->setChecked( config.readBoolEntry( "Backwards", false ) );
+ mCheckUseNavigator->setChecked( config.readBoolEntry( "UseNavigator", true));
+ uint val = config.readUnsignedNumEntry( "Format", 0 );
+ mSelector->setCurrentItem(QMIN(4,val) );
+ selectorChanged( mSelector->currentItem() );
+ enableButtonOK(!mInput->text().isEmpty());
+}
+
+
+CFindDialog::~CFindDialog( void )
+{
+ KConfig &config = *kapp->config();
+ config.setGroup("Find Dialog");
+ config.writeEntry( "FromCursor", mCheckFromCursor->isChecked() );
+ config.writeEntry( "InSelection", mCheckInSelection->isChecked() );
+ config.writeEntry( "IgnoreCase", mCheckIgnoreCase->isChecked() );
+ config.writeEntry( "Backwards", mCheckBackward->isChecked() );
+ config.writeEntry( "UseNavigator", mCheckUseNavigator->isChecked() );
+ config.writeEntry( "Format", mSelector->currentItem() );
+ config.sync();
+}
+
+
+void CFindDialog::selectorChanged( int index )
+{
+ mFindValidator->setState( (CHexValidator::EState)index );
+ mInput->setText( mFindString[ index ] );
+ mCheckIgnoreCase->setEnabled( index == 4 );
+}
+
+
+void CFindDialog::inputChanged( const QString &text )
+{
+ mFindString[ mSelector->currentItem() ] = text;
+ mFindValidator->convert( mFindData,
+ mFindString[ mSelector->currentItem() ] );
+ enableButtonOK(!text.isEmpty());
+}
+
+
+void CFindDialog::showEvent( QShowEvent *e )
+{
+ KDialogBase::showEvent(e);
+ mInput->setFocus();
+}
+
+
+bool CFindDialog::isEmpty( void )
+{
+ return( mFindData.isEmpty() );
+}
+
+
+void CFindDialog::slotOk( void )
+{
+ if( isEmpty() == true )
+ {
+ showEntryFailure( this, QString("") );
+ return;
+ }
+
+ SSearchControl sc;
+ sc.key = mFindData;
+ sc.keyType = mSelector->currentItem();
+ sc.fromCursor = mCheckFromCursor->isChecked();
+ sc.inSelection = mCheckInSelection->isChecked();
+ sc.forward = mCheckBackward->isChecked() == true ? false : true;
+ sc.ignoreCase = mCheckIgnoreCase->isEnabled() && mCheckIgnoreCase->isChecked();
+
+ hide();
+ emit findData( sc, Find_First, mCheckUseNavigator->isChecked() );
+}
+
+
+void CFindDialog::findAgain( EOperation operation )
+{
+ if( isEmpty() == true )
+ {
+ showEntryFailure( this, QString("") );
+ return;
+ }
+
+ SSearchControl sc;
+ sc.key = mFindData;
+ sc.fromCursor = true;
+ sc.inSelection = mCheckInSelection->isChecked();
+ sc.ignoreCase = mCheckIgnoreCase->isEnabled() && mCheckIgnoreCase->isChecked();
+ if( operation == find_Next )
+ {
+ sc.forward = true;
+ }
+ else if( operation == find_Previous )
+ {
+ sc.forward = false;
+ }
+ else
+ {
+ sc.forward = mCheckBackward->isChecked() == true ? false : true;
+ }
+
+ hide();
+ emit findData( sc, Find_Next, false );
+}
+
+
+
+CFindNavigatorDialog::CFindNavigatorDialog( QWidget *parent, const char *name,
+ bool modal )
+ :KDialogBase( Plain, i18n("Find (Navigator)"), User3|User2|User1|Close,
+ User2, parent, name, modal, true, i18n("New &Key"),
+ i18n("&Next"), i18n("&Previous") )
+{
+ QString text;
+ QBoxLayout *topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() );
+ if( topLayout == 0 ) { return; }
+
+ topLayout->addSpacing( spacingHint() ); // A little bit extra space
+
+ QHBoxLayout *hbox = new QHBoxLayout();
+ if( hbox == 0 ) { return; }
+ topLayout->addLayout( hbox );
+
+ text = i18n("Searching for:");
+ QLabel *label = new QLabel( text, plainPage() );
+ hbox->addWidget( label );
+
+ mKey = new QLineEdit( plainPage() );
+ mKey->setMinimumWidth( fontMetrics().width("M") * 20 );
+ mKey->setFocusPolicy( QWidget::NoFocus );
+ hbox->addWidget( mKey );
+
+ topLayout->addSpacing( spacingHint() ); // A little bit extra space
+ topLayout->addStretch(10);
+}
+
+
+CFindNavigatorDialog::~CFindNavigatorDialog( void )
+{
+}
+
+
+void CFindNavigatorDialog::defineData( SSearchControl &sc )
+{
+ mSearchControl = sc;
+ mSearchControl.key.duplicate( sc.key );
+
+ if( mSearchControl.key.isEmpty() == true )
+ {
+ mKey->setText("");
+ return;
+ }
+
+ if( mSearchControl.keyType == 0 )
+ {
+ QString str;
+ for( uint i=0; i<mSearchControl.key.size(); i++ )
+ {
+ str += mSearchControl.key[i];
+ }
+ mKey->setText( str );
+
+ }
+ else if( mSearchControl.keyType == 1 )
+ {
+ QString str("0x ");
+ for( uint i=0; i<mSearchControl.key.size(); i++ )
+ {
+ str += QString().sprintf("%02X ", (unsigned char)mSearchControl.key[i]);
+ }
+ mKey->setText( str );
+ }
+ else if( mSearchControl.keyType == 2 )
+ {
+ QString str;
+ for( uint i=0; i<mSearchControl.key.size(); i++ )
+ {
+ str += QString().sprintf("%03o ", (unsigned char)mSearchControl.key[i]);
+ }
+ mKey->setText( str );
+ }
+ else
+ {
+ char buf[10];
+ memset( buf, 0, sizeof( buf ) ); buf[8] = ' ';
+
+ QString str;
+ for( uint i=0; i<mSearchControl.key.size(); i++ )
+ {
+ unsigned char data = (unsigned char)mSearchControl.key[i];
+ for( int j = 0; j < 8; j++ )
+ {
+ buf[7-j] = (data&(1<<j)) ? '1' : '0';
+ }
+ str += buf;
+ }
+ mKey->setText( str );
+ }
+}
+
+
+void CFindNavigatorDialog::slotUser3( void ) // Previous
+{
+ done( repPrevious );
+}
+
+
+void CFindNavigatorDialog::slotUser2( void ) // Next
+{
+ done( repNext );
+}
+
+
+void CFindNavigatorDialog::slotUser1( void ) // New key
+{
+ done( repNewKey );
+}
+
+
+void CFindNavigatorDialog::slotClose( void )
+{
+ done( repClose );
+}
+
+
+void CFindNavigatorDialog::done( int resultCode )
+{
+ setResult( resultCode );
+ if( resultCode == repClose || resultCode == repNewKey )
+ {
+ if( resultCode == repNewKey )
+ {
+ emit makeKey();
+ }
+ hide();
+ return;
+ }
+
+ mSearchControl.forward = resultCode == repNext ? true : false;
+ emit findData( mSearchControl, Find_Next, true );
+}
+
+
+
+
+CReplaceDialog::CReplaceDialog( QWidget *parent, const char *name, bool modal )
+ :KDialogBase( Plain, i18n("Find & Replace"), Ok|Cancel, Ok,
+ parent, name, modal )
+{
+ QString text;
+ QVBoxLayout *topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() );
+ if( topLayout == 0 ) { return; }
+
+ QVBoxLayout *vbox = new QVBoxLayout();
+ if( vbox == 0 ) { return; }
+ topLayout->addLayout( vbox );
+
+
+ mFindSelector = new QComboBox( false, plainPage() );
+ if( mFindSelector == 0 ) { return; }
+ mFindSelector->setMinimumWidth( fontMetrics().maxWidth()*17 );
+ mFindSelector->insertStringList( formatStrings() );
+ connect( mFindSelector, SIGNAL(activated(int)),
+ SLOT(findSelectorChanged(int)) );
+
+ text = i18n("Fo&rmat (find):");
+ QLabel *label = new QLabel( mFindSelector, text, plainPage() );
+ if( label == 0 ) { return; }
+
+ vbox->addWidget( label );
+ vbox->addWidget( mFindSelector );
+
+ mFindInput = new QLineEdit( plainPage() );
+ if( mFindInput == 0 ) { return; }
+ mFindInput->setMinimumWidth( fontMetrics().maxWidth()*17 );
+ mFindValidator = new CHexValidator( this, CHexValidator::regularText );
+ if( mFindValidator == 0 ) { return; }
+ mFindInput->setValidator( mFindValidator );
+ connect( mFindInput, SIGNAL(textChanged(const QString&)),
+ SLOT(findInputChanged(const QString&)) );
+
+ label = new QLabel( mFindInput, i18n("F&ind:"), plainPage() );
+ if( label == 0 ) { return; }
+
+ vbox->addWidget( label );
+ vbox->addWidget( mFindInput );
+
+ mReplaceSelector = new QComboBox( false, plainPage() );
+ if( mReplaceSelector == 0 ) { return; }
+ mReplaceSelector->setMinimumWidth( fontMetrics().maxWidth()*17 );
+ mReplaceSelector->insertStringList( formatStrings() );
+ connect( mReplaceSelector, SIGNAL(activated(int)),
+ SLOT(replaceSelectorChanged(int)) );
+
+ text = i18n("For&mat (replace):");
+ label = new QLabel( mReplaceSelector, text, plainPage() );
+ if( label == 0 ) { return; }
+ label->setFixedHeight( label->sizeHint().height() );
+
+ vbox->addWidget( label );
+ vbox->addWidget( mReplaceSelector );
+
+ mReplaceInput = new QLineEdit( plainPage() );
+ if( mReplaceInput == 0 ) { return; }
+ mReplaceInput->setMinimumWidth( fontMetrics().maxWidth()*17 );
+ mReplaceValidator = new CHexValidator( this, CHexValidator::regularText );
+ if( mReplaceValidator == 0 ) { return; }
+ mReplaceInput->setValidator( mReplaceValidator );
+ connect( mReplaceInput, SIGNAL(textChanged(const QString&)),
+ SLOT(replaceInputChanged(const QString&)) );
+
+ label = new QLabel( mReplaceInput, i18n("Rep&lace:"), plainPage() );
+ if( label == 0 ) { return; }
+ label->setFixedHeight( label->sizeHint().height() );
+
+ vbox->addWidget( label );
+ vbox->addWidget( mReplaceInput );
+
+ QButtonGroup *group = new QButtonGroup( i18n("Options"), plainPage() );
+ if( group == 0 ) { return; }
+ topLayout->addWidget( group, 10 );
+
+ QGridLayout *gbox = new QGridLayout( group, 5, 2, spacingHint() );
+ if( gbox == 0 ) { return; }
+ gbox->addRowSpacing( 0, fontMetrics().lineSpacing() );
+ mCheckFromCursor = new QCheckBox( i18n("&From cursor"), group );
+ gbox->addWidget( mCheckFromCursor, 1, 0 );
+ mCheckBackward = new QCheckBox( i18n("&Backwards"), group );
+ gbox->addWidget( mCheckBackward, 1, 1 );
+ mCheckInSelection = new QCheckBox( i18n("&In selection"), group );
+ gbox->addWidget( mCheckInSelection, 2, 0 );
+ mCheckPrompt = new QCheckBox( i18n("&Prompt"), group );
+ gbox->addWidget( mCheckPrompt, 2, 1 );
+ mCheckIgnoreCase = new QCheckBox( i18n("Ignore c&ase"), group );
+ gbox->addWidget( mCheckIgnoreCase, 3, 0 );
+ gbox->setRowStretch( 4, 10 );
+
+ KConfig &config = *kapp->config();
+ config.setGroup("Replace Dialog");
+ mCheckFromCursor->setChecked( config.readBoolEntry( "FromCursor", true ) );
+ mCheckInSelection->setChecked( config.readBoolEntry( "InSelection", false) );
+ mCheckIgnoreCase->setChecked( config.readBoolEntry( "IgnoreCase", false ) );
+ mCheckBackward->setChecked( config.readBoolEntry( "Backwards", false ) );
+ mCheckPrompt->setChecked( config.readBoolEntry( "Prompt", true));
+ uint val = config.readUnsignedNumEntry( "FindFormat", 0 );
+ mFindSelector->setCurrentItem(QMIN(4,val) );
+ findSelectorChanged( mFindSelector->currentItem() );
+ val = config.readUnsignedNumEntry( "ReplaceFormat", 0 );
+ mReplaceSelector->setCurrentItem(QMIN(4,val) );
+ replaceSelectorChanged( mReplaceSelector->currentItem() );
+ enableButtonOK(!mFindInput->text().isEmpty());
+}
+
+
+CReplaceDialog::~CReplaceDialog( void )
+{
+ KConfig &config = *kapp->config();
+ config.setGroup("Replace Dialog");
+ config.writeEntry( "FromCursor", mCheckFromCursor->isChecked() );
+ config.writeEntry( "InSelection", mCheckInSelection->isChecked() );
+ config.writeEntry( "IgnoreCase", mCheckIgnoreCase->isChecked() );
+ config.writeEntry( "Backwards", mCheckBackward->isChecked() );
+ config.writeEntry( "Prompt", mCheckPrompt->isChecked() );
+ config.writeEntry( "FindFormat", mFindSelector->currentItem() );
+ config.writeEntry( "ReplaceFormat", mReplaceSelector->currentItem() );
+ config.sync();
+}
+
+
+void CReplaceDialog::findSelectorChanged( int index )
+{
+ mFindValidator->setState( (CHexValidator::EState)index );
+ mFindInput->setText( mFindString[ index ] );
+ mCheckIgnoreCase->setEnabled( index == 4 );
+}
+
+
+void CReplaceDialog::findInputChanged( const QString &text )
+{
+ mFindString[ mFindSelector->currentItem() ] = text;
+ mFindValidator->convert( mFindData,
+ mFindString[ mFindSelector->currentItem() ] );
+ enableButtonOK(!text.isEmpty());
+}
+
+
+void CReplaceDialog::replaceSelectorChanged( int index )
+{
+ mReplaceValidator->setState( (CHexValidator::EState)index );
+ mReplaceInput->setText( mReplaceString[ index ] );
+}
+
+
+void CReplaceDialog::replaceInputChanged( const QString &text )
+{
+ mReplaceString[ mReplaceSelector->currentItem() ] = text;
+ mReplaceValidator->convert( mReplaceData,
+ mReplaceString[ mReplaceSelector->currentItem() ] );
+}
+
+
+void CReplaceDialog::showEvent( QShowEvent *e )
+{
+ KDialogBase::showEvent(e);
+ mFindInput->setFocus();
+}
+
+
+void CReplaceDialog::slotOk( void )
+{
+ if( mFindData.isEmpty() == true )
+ {
+ showEntryFailure( this, QString("") );
+ return;
+ }
+
+ if( mFindData == mReplaceData )
+ {
+ showEntryFailure( this,i18n("Source and target values can not be equal."));
+ return;
+ }
+
+ hide();
+
+ SSearchControl sc;
+ sc.key = mFindData;
+ sc.val = mReplaceData;
+ sc.fromCursor = mCheckFromCursor->isChecked();
+ sc.inSelection = mCheckInSelection->isChecked();
+ sc.forward = mCheckBackward->isChecked() == true ? false : true;
+
+ sc.ignoreCase = mCheckIgnoreCase->isEnabled() && mCheckIgnoreCase->isChecked();
+
+ emit replaceData( sc, mCheckPrompt->isChecked() ? Replace_First: Replace_AllInit );
+}
+
+
+
+
+
+CReplacePromptDialog::CReplacePromptDialog( QWidget *parent, const char *name,
+ bool modal )
+ :KDialogBase( Plain, i18n("Find & Replace"), User3|User2|User1|Close,
+ User2, parent, name, modal, true, i18n("Replace &All"),
+ i18n("Do Not Replace"), i18n("Replace"))
+{
+ QString text;
+ QBoxLayout *topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() );
+ if( topLayout == 0 ) { return; }
+
+ topLayout->addSpacing( spacingHint() ); // A little bit extra space
+
+ text = i18n("Replace marked data at cursor position?");
+ QLabel* label = new QLabel( text, plainPage() );
+ topLayout->addWidget( label );
+
+ topLayout->addSpacing( spacingHint() ); // A little bit extra space
+ topLayout->addStretch(10);
+}
+
+
+CReplacePromptDialog::~CReplacePromptDialog( void )
+{
+}
+
+
+void CReplacePromptDialog::defineData( SSearchControl &sc )
+{
+ mSearchControl = sc;
+ mSearchControl.key.duplicate( sc.key );
+ mSearchControl.val.duplicate( sc.val );
+}
+
+
+void CReplacePromptDialog::slotUser3( void )
+{
+ done( repYes );
+}
+
+
+void CReplacePromptDialog::slotUser2( void )
+{
+ done( repNo );
+}
+
+
+void CReplacePromptDialog::slotUser1( void )
+{
+ done( repAll );
+}
+
+
+void CReplacePromptDialog::slotClose( void )
+{
+ done( repClose );
+}
+
+
+void CReplacePromptDialog::done( int returnCode )
+{
+ if( returnCode == repClose )
+ {
+ hide();
+ }
+ else if( returnCode == repYes )
+ {
+ emit replaceData( mSearchControl, Replace_Next );
+ }
+ else if( returnCode == repNo )
+ {
+ emit replaceData( mSearchControl, Replace_Ignore );
+ }
+ else
+ {
+ emit replaceData( mSearchControl, Replace_All );
+ }
+}
+
+
+
+
+CFilterDialog::CFilterDialog( QWidget *parent, const char *name, bool modal )
+ :KDialogBase( Plain, i18n("Binary Filter"), Ok|Cancel, Ok,
+ parent, name, modal )
+{
+ QString text;
+ QVBoxLayout *topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() );
+ if( topLayout == 0 ) { return; }
+
+ QVBoxLayout *vbox = new QVBoxLayout();
+ if( vbox == 0 ) { return; }
+ topLayout->addLayout( vbox );
+
+
+ mOperationSelector = new QComboBox( false, plainPage() );
+ if( mOperationSelector == 0 ) { return; }
+ mOperationSelector->setMinimumWidth( fontMetrics().maxWidth()*17 );
+ mOperationSelector->insertStringList( operationStrings() );
+ connect( mOperationSelector, SIGNAL(activated(int)),
+ SLOT(operationSelectorChanged(int)) );
+
+ text = i18n("O&peration:");
+ QLabel *label = new QLabel( mOperationSelector, text, plainPage() );
+ if( label == 0 ) { return; }
+
+ vbox->addWidget( label );
+ vbox->addWidget( mOperationSelector );
+
+ KSeparator *separator = new KSeparator( plainPage() );
+ separator->setOrientation( QFrame::HLine );
+ vbox->addWidget( separator );
+
+
+ mWidgetStack = new QWidgetStack( plainPage(), "pagestack" );
+ if( mWidgetStack == 0 ) { return; }
+ vbox->addWidget( mWidgetStack );
+
+ makeEmptyLayout();
+ makeOperandLayout();
+ makeBitSwapLayout();
+ makeRotateLayout();
+ mWidgetStack->raiseWidget( (int)OperandPage );
+
+
+ QButtonGroup *group = new QButtonGroup( i18n("Options"), plainPage() );
+ if( group == 0 ) { return; }
+ topLayout->addWidget( group, 10 );
+
+ QGridLayout *gbox = new QGridLayout( group, 4, 2, spacingHint() );
+ if( gbox == 0 ) { return; }
+ gbox->addRowSpacing( 0, fontMetrics().lineSpacing() );
+ mCheckFromCursor = new QCheckBox( i18n("&From cursor"), group );
+ gbox->addWidget( mCheckFromCursor, 1, 0 );
+ mCheckBackward = new QCheckBox( i18n("&Backwards"), group );
+ gbox->addWidget( mCheckBackward, 1, 1 );
+ mCheckInSelection = new QCheckBox( i18n("&In selection"), group );
+ gbox->addWidget( mCheckInSelection, 2, 0 );
+ mCheckVisible = new QCheckBox( i18n("&Stay visible"), group );
+ gbox->addWidget( mCheckVisible, 2, 1 );
+ gbox->setRowStretch( 3, 10 );
+}
+
+
+CFilterDialog::~CFilterDialog( void )
+{
+ delete mOperandValidator;
+}
+
+
+void CFilterDialog::makeEmptyLayout( void )
+{
+ QFrame *page = new QFrame( plainPage() );
+ if( page == 0 ) { return; }
+ mWidgetStack->addWidget( page, EmptyPage );
+}
+
+
+void CFilterDialog::makeOperandLayout( void )
+{
+ QString text;
+
+ QFrame *page = new QFrame( plainPage() );
+ if( page == 0 ) { return; }
+ mWidgetStack->addWidget( page, OperandPage );
+
+ QVBoxLayout *vbox = new QVBoxLayout( page, 0, spacingHint() );
+ if( vbox == 0 ) { return; }
+
+ mOperandSelector = new QComboBox( false, page );
+ if( mOperandSelector == 0 ) { return; }
+ mOperandSelector->setFixedHeight( mOperandSelector->sizeHint().height());
+ mOperandSelector->setMinimumWidth( fontMetrics().width("M")*20 );
+ mOperandSelector->insertStringList( formatStrings() );
+ connect( mOperandSelector, SIGNAL(activated(int)),
+ SLOT(operandSelectorChanged(int)) );
+
+ text = i18n("Fo&rmat (operand):");
+ mOperandFormatLabel = new QLabel( mOperandSelector, text, page );
+ if( mOperandFormatLabel == 0 ) { return; }
+
+ vbox->addWidget( mOperandFormatLabel );
+ vbox->addWidget( mOperandSelector );
+
+ mOperandInput = new QLineEdit( page );
+ if( mOperandInput == 0 ) { return; }
+ mOperandInput->setMinimumWidth( fontMetrics().width("M") * 20 );
+ mOperandValidator = new CHexValidator( this, CHexValidator::regularText );
+ if( mOperandValidator == 0 ) { return; }
+ mOperandInput->setValidator( mOperandValidator );
+ connect( mOperandInput, SIGNAL(textChanged(const QString&)),
+ SLOT(operandInputChanged(const QString&)) );
+
+ mOperandInputLabel = new QLabel( mOperandInput, i18n("O&perand:"), page );
+ if( mOperandInputLabel == 0 ) { return; }
+
+ vbox->addWidget( mOperandInputLabel );
+ vbox->addWidget( mOperandInput );
+ vbox->addSpacing( 1 );
+}
+
+
+void CFilterDialog::makeBitSwapLayout( void )
+{
+ QString text;
+
+ QFrame *page = new QFrame( plainPage() );
+ if( page == 0 ) { return; }
+ mWidgetStack->addWidget( page, BitSwapPage );
+
+ QVBoxLayout *vbox = new QVBoxLayout( page, 0, spacingHint() );
+ if( vbox == 0 ) { return; }
+
+ text = i18n("Swap rule");
+ QLabel *label = new QLabel( text, page );
+ if( label == 0 ) { return; }
+ label->setFixedHeight( label->sizeHint().height() );
+ vbox->addWidget( label );
+
+ mByteWidget = new CByteWidget( page );
+ vbox->addWidget( mByteWidget );
+
+ QHBoxLayout *hbox = new QHBoxLayout( 0 );
+ vbox->addLayout( hbox );
+
+ text = i18n("&Reset");
+ QPushButton *resetButton = new QPushButton( text, page );
+ resetButton->setFixedHeight( resetButton->sizeHint().height() );
+ connect( resetButton, SIGNAL(clicked()), mByteWidget, SLOT(reset()) );
+
+ hbox->addWidget( resetButton );
+ hbox->addStretch( 10 );
+}
+
+
+void CFilterDialog::makeRotateLayout( void )
+{
+ QString text;
+
+ QFrame *page = new QFrame( plainPage() );
+ if( page == 0 ) { return; }
+ mWidgetStack->addWidget( page, RotatePage );
+
+ QVBoxLayout *vbox = new QVBoxLayout( page, 0, spacingHint() );
+ if( vbox == 0 ) { return; }
+
+ mGroupSpin = new QSpinBox( page );
+ if( mGroupSpin == 0 ) { return; }
+ mGroupSpin->setMinimumWidth( fontMetrics().width("M")*20 );
+ mGroupSpin->setRange(1, INT_MAX );
+
+ text = i18n("&Group size [bytes]");
+ QLabel *label = new QLabel( mGroupSpin, text, page );
+ if( label == 0 ) { return; }
+
+ vbox->addWidget( label );
+ vbox->addWidget( mGroupSpin );
+
+ mBitSpin = new QSpinBox( page );
+ if( mBitSpin == 0 ) { return; }
+ mBitSpin->setMinimumWidth( fontMetrics().width("M")*20 );
+ mBitSpin->setRange(INT_MIN, INT_MAX);
+
+ text = i18n("S&hift size [bits]");
+ label = new QLabel( mBitSpin, text, page );
+ if( label == 0 ) { return; }
+
+ vbox->addWidget( label );
+ vbox->addWidget( mBitSpin );
+}
+
+
+
+void CFilterDialog::showEvent( QShowEvent *e )
+{
+ KDialogBase::showEvent(e);
+ mOperandInput->setFocus();
+}
+
+
+
+void CFilterDialog::slotOk( void )
+{
+ SFilterControl fc;
+ switch( mOperationSelector->currentItem() )
+ {
+ case SFilterControl::OperandAndData:
+ case SFilterControl::OperandOrData:
+ case SFilterControl::OperandXorData:
+ if( mOperandData.isEmpty() == true )
+ {
+ showEntryFailure( this, QString("") );
+ return;
+ }
+ fc.operand = mOperandData;
+ break;
+
+ case SFilterControl::InvertData:
+ case SFilterControl::ReverseData:
+ break;
+
+ case SFilterControl::RotateData:
+ case SFilterControl::ShiftData:
+ fc.rotate[0] = mGroupSpin->value();
+ fc.rotate[1] = mBitSpin->value();
+ if( fc.rotate[1] == 0 )
+ {
+ QString msg = i18n("Shift size is zero.");
+ showEntryFailure( this, msg );
+ return;
+ }
+ break;
+
+ case SFilterControl::SwapBits:
+ if( mByteWidget->flag( fc.operand ) == false )
+ {
+ QString msg = i18n("Swap rule does not define any swapping.");
+ showEntryFailure( this, msg );
+ return;
+ }
+ break;
+
+ default:
+ return;
+ break;
+
+ }
+
+ if( mCheckVisible->isChecked() == false )
+ {
+ hide();
+ }
+
+ fc.operation = (SFilterControl::Operation)mOperationSelector->currentItem();
+ fc.fromCursor = mCheckFromCursor->isChecked();
+ fc.inSelection = mCheckInSelection->isChecked();
+ if( mCheckBackward->isEnabled() == true )
+ {
+ fc.forward = mCheckBackward->isChecked() == true ? false : true;
+ }
+ else
+ {
+ fc.forward = true;
+ }
+
+ emit filterData( fc );
+}
+
+
+void CFilterDialog::operandSelectorChanged( int index )
+{
+ mOperandValidator->setState( (CHexValidator::EState)index );
+ mOperandInput->setText( mOperandString[ index ] );
+}
+
+
+void CFilterDialog::operandInputChanged( const QString &text )
+{
+ mOperandString[ mOperandSelector->currentItem() ] = text;
+ mOperandValidator->convert( mOperandData,
+ mOperandString[ mOperandSelector->currentItem() ] );
+}
+
+
+void CFilterDialog::operationSelectorChanged( int index )
+{
+ if( index <= 2 )
+ {
+ mWidgetStack->raiseWidget( OperandPage );
+ mCheckBackward->setEnabled( true );
+ }
+ else if( index <= 4 )
+ {
+ mWidgetStack->raiseWidget( EmptyPage );
+ mCheckBackward->setEnabled( true );
+ }
+ else if( index <= 6 )
+ {
+ mWidgetStack->raiseWidget( RotatePage );
+ mCheckBackward->setEnabled( false );
+ }
+ else
+ {
+ mWidgetStack->raiseWidget( BitSwapPage );
+ mCheckBackward->setEnabled( true );
+ }
+}
+
+
+
+
+CInsertDialog::CInsertDialog( QWidget *parent, const char *name, bool modal )
+ :KDialogBase( Plain, i18n("Insert Pattern"), Ok|Cancel, Ok,
+ parent, name, modal )
+{
+ setButtonOKText(i18n("&Insert"));
+
+ QString text;
+ QVBoxLayout *topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() );
+ if( topLayout == 0 ) { return; }
+
+ QVBoxLayout *vbox = new QVBoxLayout();
+ if( vbox == 0 ) { return; }
+ topLayout->addLayout( vbox );
+
+ mSizeBox = new QSpinBox( plainPage() );
+ if( mSizeBox == 0 ) { return; }
+ mSizeBox->setMinimumWidth( fontMetrics().maxWidth()*17 );
+ mSizeBox->setRange( 1, INT_MAX );
+ mSizeBox->setValue( 1 );
+
+ QLabel *label = new QLabel( mSizeBox, i18n("&Size:"), plainPage() );
+ if( label == 0 ) { return; }
+
+ vbox->addWidget( label );
+ vbox->addWidget( mSizeBox );
+
+ mPatternSelector = new QComboBox( false, plainPage() );
+ if( mPatternSelector == 0 ) { return; }
+ mPatternSelector->setMinimumWidth( fontMetrics().maxWidth()*17 );
+ mPatternSelector->insertStringList( formatStrings() );
+ connect( mPatternSelector, SIGNAL(activated(int)),
+ SLOT(patternSelectorChanged(int)) );
+
+ text = i18n("Fo&rmat (pattern):");
+ label = new QLabel( mPatternSelector, text, plainPage() );
+ if( label == 0 ) { return; }
+
+ vbox->addWidget( label );
+ vbox->addWidget( mPatternSelector );
+
+ mPatternInput = new QLineEdit( plainPage() );
+ if( mPatternInput == 0 ) { return; }
+ mPatternInput->setMinimumWidth( fontMetrics().maxWidth()*17 );
+ mPatternValidator = new CHexValidator( this, CHexValidator::regularText );
+ if( mPatternValidator == 0 ) { return; }
+ mPatternInput->setValidator( mPatternValidator );
+ connect( mPatternInput, SIGNAL(textChanged(const QString&)),
+ SLOT(patternInputChanged(const QString&)) );
+
+ label = new QLabel( mPatternInput, i18n("&Pattern:"), plainPage() );
+ if( label == 0 ) { return; }
+
+ vbox->addWidget( label );
+ vbox->addWidget( mPatternInput );
+
+ mOffsetInput = new QLineEdit( plainPage() );
+ mOffsetInput->setMinimumWidth( fontMetrics().maxWidth()*17 );
+
+ mOffsetLabel = new QLabel( mOffsetInput, i18n("&Offset:"), plainPage() );
+ if( mOffsetLabel == 0 ) { return; }
+
+ vbox->addWidget( mOffsetLabel );
+ vbox->addWidget( mOffsetInput );
+
+ QButtonGroup *group = new QButtonGroup( i18n("Options"), plainPage() );
+ if( group == 0 ) { return; }
+ topLayout->addWidget( group, 10 );
+
+
+ QGridLayout *gbox = new QGridLayout( group, 4, 2, spacingHint() );
+ if( gbox == 0 ) { return; }
+ gbox->addRowSpacing( 0, fontMetrics().lineSpacing() );
+
+ mCheckPattern = new QCheckBox( i18n("R&epeat pattern"), group );
+ gbox->addWidget( mCheckPattern, 1, 0 );
+ mCheckOnCursor = new QCheckBox( i18n("&Insert on cursor position"), group );
+ gbox->addWidget( mCheckOnCursor, 2, 0 );
+ connect( mCheckOnCursor, SIGNAL(clicked()), SLOT(cursorCheck()) );
+ gbox->setRowStretch( 3, 10 );
+
+ KConfig &config = *kapp->config();
+ config.setGroup("Insert Pattern Dialog");
+ mCheckPattern->setChecked( config.readBoolEntry( "RepeatPattern", false ) );
+ mCheckOnCursor->setChecked( config.readBoolEntry( "InsertOnCursor", false) );
+ cursorCheck();
+ uint val = config.readUnsignedNumEntry( "Format", 0 );
+ mPatternSelector->setCurrentItem( QMIN(4,val) );
+ patternSelectorChanged( mPatternSelector->currentItem() );
+}
+
+
+CInsertDialog::~CInsertDialog( void )
+{
+ KConfig &config = *kapp->config();
+ config.setGroup("Insert Pattern Dialog");
+ config.writeEntry( "RepeatPattern", mCheckPattern->isChecked() );
+ config.writeEntry( "InsertOnCursor", mCheckOnCursor->isChecked() );
+ config.writeEntry( "Format", mPatternSelector->currentItem() );
+ config.sync();
+}
+
+
+void CInsertDialog::showEvent( QShowEvent *e )
+{
+ KDialogBase::showEvent(e);
+ mPatternInput->setFocus();
+}
+
+
+void CInsertDialog::patternSelectorChanged( int index )
+{
+ mPatternValidator->setState( (CHexValidator::EState)index );
+ mPatternInput->setText( mPatternString[ index ] );
+}
+
+
+void CInsertDialog::patternInputChanged( const QString &text )
+{
+ mPatternString[ mPatternSelector->currentItem() ] = text;
+ mPatternValidator->convert( mPatternData,
+ mPatternString[ mPatternSelector->currentItem() ] );
+}
+
+
+void CInsertDialog::slotOk( void )
+{
+ if( mPatternData.isEmpty() == true )
+ {
+ showEntryFailure( this, QString("") );
+ return;
+ }
+
+ SInsertData id;
+ id.size = mSizeBox->value();
+ id.repeatPattern = mCheckPattern->isChecked();
+ id.onCursor = mCheckOnCursor->isChecked();
+ id.pattern = mPatternData;
+
+ if( id.onCursor == false )
+ {
+ bool success = stringToOffset( mOffsetInput->text(), id.offset );
+ if( success == false )
+ {
+ showEntryFailure( this, QString("") );
+ return;
+ }
+ }
+
+ hide();
+ execute( id );
+}
+
+
+void CInsertDialog::cursorCheck( void )
+{
+ bool state = mCheckOnCursor->isChecked() == true ? false : true;
+ mOffsetLabel->setEnabled( state );
+ mOffsetInput->setEnabled( state );
+}
+
+
+
+
+void centerDialog( QWidget *widget, QWidget *centerParent )
+{
+ if( centerParent == 0 || widget == 0 )
+ {
+ return;
+ }
+
+ QPoint point = centerParent->mapToGlobal( QPoint(0,0) );
+ QRect pos = centerParent->geometry();
+
+ widget->setGeometry( point.x() + pos.width()/2 - widget->width()/2,
+ point.y() + pos.height()/2 - widget->height()/2,
+ widget->width(), widget->height() );
+}
+
+
+void centerDialogBottom( QWidget *widget, QWidget *centerParent )
+{
+ if( centerParent == 0 || widget == 0 )
+ {
+ return;
+ }
+
+ QPoint point = centerParent->mapToGlobal( QPoint(0,0) );
+ QRect pos = centerParent->geometry();
+
+ widget->setGeometry( point.x() + pos.width()/2 - widget->width()/2,
+ point.y() + pos.height() - widget->height(),
+ widget->width(), widget->height() );
+}
+
+
+void comboMatchText( QComboBox *combo, const QString &text )
+{
+ for( int i=0; i < combo->count(); i++ )
+ {
+ if( combo->text(i) == text )
+ {
+ combo->setCurrentItem(i);
+ return;
+ }
+ }
+ combo->setCurrentItem(0);
+}
+
+
+
+
+
+void showEntryFailure( QWidget *parent, const QString &msg )
+{
+ QString message;
+ message += i18n("Your request can not be processed.");
+ message += "\n";
+ if( msg.isNull() == true || msg.isEmpty() == true )
+ {
+ message += i18n("Examine argument(s) and try again.");
+ }
+ else
+ {
+ message += msg;
+ }
+ KMessageBox::sorry( parent, message, i18n("Invalid argument(s)") );
+}
+
+
+bool verifyFileDestnation( QWidget *parent, const QString &title,
+ const QString &path )
+{
+ if( path.isEmpty() == true )
+ {
+ QString msg = i18n("You must specify a destination file.");
+ KMessageBox::sorry( parent, msg, title );
+ return( false );
+ }
+
+ QFileInfo info( path );
+ if( info.exists() == true )
+ {
+ if( info.isDir() == true )
+ {
+ QString msg = i18n("You have specified an existing folder.");
+ KMessageBox::sorry( parent, msg, title );
+ return( false );
+ }
+
+ if( info.isWritable() == false )
+ {
+ QString msg = i18n("You do not have write permission to this file.");
+ KMessageBox::sorry( parent, msg, title );
+ return( false );
+ }
+
+ QString msg = i18n( ""
+ "You have specified an existing file.\n"
+ "Overwrite current file?" );
+ int reply = KMessageBox::warningContinueCancel( parent, msg, title, i18n("Overwrite") );
+ if( reply != KMessageBox::Continue )
+ {
+ return( false );
+ }
+ }
+
+ return( true );
+}
+
+
+
+bool stringToOffset( const QString & text, uint &offset )
+{
+ if( text.isEmpty() )
+ {
+ return( false );
+ }
+
+ const char * p = text.ascii(); // ####: Is this correct?
+
+ //
+ // Skip any whitespaces in front of string
+ //
+ for( ; *p != 0 && isspace( *p ) ; p++ );
+
+ int match = 0;
+ bool space = false;
+ if( strncmp( p, "0x", 2 ) == 0 || strncmp( p, "0X", 2 ) == 0 )
+ {
+ for( const char *q = p+2; *q != 0; q++ )
+ {
+ if( isxdigit( *q ) == 0 || space == true )
+ {
+ if( isspace( *q ) == 0 )
+ {
+ return( false );
+ }
+ space = true;
+ }
+ }
+ match = sscanf( p+2, "%x", &offset );
+ }
+ else
+ {
+ for( const char *q = p; *q != 0; q++ )
+ {
+ if( isdigit( *q ) == 0 || space == true )
+ {
+ if( isspace( *q ) == 0 )
+ {
+ return( false );
+ }
+ space = true;
+ }
+ }
+ match = sscanf( p, "%u", &offset );
+ }
+
+ if( match == 0 )
+ {
+ return( false );
+ }
+
+ return( true );
+}
+
+
+static const QStringList &formatStrings( void )
+{
+ static QStringList list;
+ if( list.isEmpty() == true )
+ {
+ list.append( i18n( "Hexadecimal" ) );
+ list.append( i18n( "Decimal" ) );
+ list.append( i18n( "Octal" ) );
+ list.append( i18n( "Binary" ) );
+ list.append( i18n( "Regular Text" ) );
+ }
+ return( list );
+}
+
+
+static const QStringList &operationStrings( void )
+{
+ static QStringList list;
+ if( list.isEmpty() == true )
+ {
+ list.append( i18n( "operand AND data" ) );
+ list.append( i18n( "operand OR data" ) );
+ list.append( i18n( "operand XOR data" ) );
+ list.append( i18n( "INVERT data" ) );
+ list.append( i18n( "REVERSE data" ) );
+ list.append( i18n( "ROTATE data" ) );
+ list.append( i18n( "SHIFT data" ) );
+ list.append( i18n( "Swap Individual Bits" ) );
+ }
+
+ return( list );
+}
+
+
+
+
+
+#include "dialog.moc"
diff --git a/khexedit/dialog.h b/khexedit/dialog.h
new file mode 100644
index 0000000..6a6aae1
--- /dev/null
+++ b/khexedit/dialog.h
@@ -0,0 +1,350 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _DIALOG_H_
+#define _DIALOG_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qdialog.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qradiobutton.h>
+#include <qspinbox.h>
+#include <qstring.h>
+#include <qwidgetstack.h>
+
+#include <kdialogbase.h>
+
+#include "bitswapwidget.h"
+#include "hexbuffer.h"
+#include "hexvalidator.h"
+
+const int repYes = QDialog::Accepted;
+const int repNo = 11;
+const int repAll = 12;
+const int repClose = QDialog::Rejected;
+const int repNext = 13;
+const int repPrevious = 14;
+const int repNewKey = 15;
+
+const uint Replace_All = 1;
+const uint Replace_AllInit = 2;
+const uint Replace_First = 3;
+const uint Replace_Next = 4;
+const uint Replace_Ignore = 5;
+const uint Find_First = 6;
+const uint Find_Next = 7;
+
+
+
+
+class CGotoDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ CGotoDialog( QWidget *parent, const char *name = 0, bool modal = false );
+ ~CGotoDialog( void );
+
+ protected:
+ virtual void showEvent( QShowEvent *e );
+
+ private slots:
+ void slotOk( void );
+
+ signals:
+ void gotoOffset( uint offset, uint bit, bool fromCursor, bool forward );
+
+ private:
+ QComboBox *mComboBox;
+ QCheckBox *mCheckBackward;
+ QCheckBox *mCheckFromCursor;
+ QCheckBox *mCheckVisible;
+};
+
+
+
+class CFindDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ enum EOperation
+ {
+ find_Again = 0,
+ find_Next,
+ find_Previous
+ };
+
+ public:
+ CFindDialog( QWidget *parent=0, const char *name=0, bool modal=false );
+ ~CFindDialog( void );
+ bool isEmpty( void );
+
+ public slots:
+ void findAgain( EOperation operation );
+
+ protected:
+ virtual void showEvent( QShowEvent *e );
+
+ private slots:
+ void slotOk( void );
+ void selectorChanged( int index );
+ void inputChanged( const QString &text );
+
+ signals:
+ void findData( SSearchControl &sc, uint mode, bool navigator );
+
+ private:
+ QComboBox *mSelector;
+ QLineEdit *mInput;
+ QCheckBox *mCheckBackward;
+ QCheckBox *mCheckFromCursor;
+ QCheckBox *mCheckInSelection;
+ QCheckBox *mCheckUseNavigator;
+ QCheckBox *mCheckIgnoreCase;
+
+ QString mFindString[5];
+ QByteArray mFindData;
+ CHexValidator *mFindValidator;
+};
+
+
+
+class CFindNavigatorDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ CFindNavigatorDialog( QWidget *parent=0, const char *name=0,
+ bool modal=false );
+ ~CFindNavigatorDialog( void );
+ void defineData( SSearchControl &sc );
+
+ private slots:
+ void slotUser1( void );
+ void slotUser2( void );
+ void slotUser3( void );
+ void slotClose( void );
+
+ private:
+ void done( int returnCode );
+
+ signals:
+ void findData( SSearchControl &sc, uint mode, bool navigator );
+ void makeKey( void );
+
+ private:
+ QLineEdit *mKey;
+ SSearchControl mSearchControl;
+};
+
+
+class CReplaceDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ CReplaceDialog( QWidget *parent=0, const char *name=0, bool modal=false );
+ ~CReplaceDialog( void );
+
+ protected:
+ virtual void showEvent( QShowEvent *e );
+
+ private slots:
+ void slotOk( void );
+ void findSelectorChanged( int index );
+ void findInputChanged( const QString &text );
+ void replaceSelectorChanged( int index );
+ void replaceInputChanged( const QString &text );
+
+ signals:
+ void replaceData( SSearchControl &sc, uint mode );
+
+ private:
+ QComboBox *mFindSelector;
+ QComboBox *mReplaceSelector;
+ QLineEdit *mFindInput;
+ QLineEdit *mReplaceInput;
+
+ QCheckBox *mCheckBackward;
+ QCheckBox *mCheckFromCursor;
+ QCheckBox *mCheckInSelection;
+ QCheckBox *mCheckPrompt;
+ QCheckBox *mCheckIgnoreCase;
+
+ QString mFindString[5];
+ QString mReplaceString[5];
+ QByteArray mFindData;
+ QByteArray mReplaceData;
+ CHexValidator *mFindValidator;
+ CHexValidator *mReplaceValidator;
+};
+
+
+
+class CReplacePromptDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ CReplacePromptDialog( QWidget *parent=0, const char *name=0,
+ bool modal=false );
+ ~CReplacePromptDialog( void );
+ void defineData( SSearchControl &sc );
+
+ private slots:
+ void slotUser1( void );
+ void slotUser2( void );
+ void slotUser3( void );
+ void slotClose( void );
+
+ private:
+ void done( int returnCode );
+
+ signals:
+ void replaceData( SSearchControl &sc, uint mode );
+
+ private:
+ SSearchControl mSearchControl;
+};
+
+
+
+
+class CFilterDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ enum EStackMode
+ {
+ EmptyPage = 0,
+ OperandPage,
+ BitSwapPage,
+ RotatePage
+ };
+
+ public:
+ CFilterDialog( QWidget *parent=0, const char *name=0, bool modal=false );
+ ~CFilterDialog( void );
+
+ protected:
+ virtual void showEvent( QShowEvent *e );
+
+ private:
+ void makeEmptyLayout( void );
+ void makeOperandLayout( void );
+ void makeBitSwapLayout( void );
+ void makeRotateLayout( void );
+
+ private slots:
+ void slotOk( void );
+ void operandSelectorChanged( int index );
+ void operandInputChanged( const QString &text );
+ void operationSelectorChanged( int index );
+
+ signals:
+ void filterData( SFilterControl &fc );
+
+ private:
+ QWidgetStack *mWidgetStack;
+ QLabel *mOperandFormatLabel;
+ QLabel *mOperandInputLabel;
+ QComboBox *mOperandSelector;
+ QLineEdit *mOperandInput;
+ QComboBox *mOperationSelector;
+ QSpinBox *mGroupSpin;
+ QSpinBox *mBitSpin;
+ CByteWidget *mByteWidget;
+
+ QCheckBox *mCheckBackward;
+ QCheckBox *mCheckFromCursor;
+ QCheckBox *mCheckInSelection;
+ QCheckBox *mCheckVisible;
+
+ QString mOperandString[5];
+ QByteArray mOperandData;
+ CHexValidator *mOperandValidator;
+};
+
+
+
+
+class CInsertDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ CInsertDialog( QWidget *parent=0, const char *name=0, bool modal=false );
+ ~CInsertDialog( void );
+
+ protected:
+ virtual void showEvent( QShowEvent *e );
+
+ private slots:
+ void slotOk( void );
+ void cursorCheck( void );
+ void patternSelectorChanged( int index );
+ void patternInputChanged( const QString &text );
+
+ signals:
+ void execute( SInsertData &id );
+
+ private:
+ QSpinBox *mSizeBox;
+ QLabel *mOffsetLabel;
+ QComboBox *mPatternSelector;
+ QLineEdit *mPatternInput;
+ QLineEdit *mOffsetInput;
+ QCheckBox *mCheckPattern;
+ QCheckBox *mCheckOnCursor;
+
+ QString mPatternString[5];
+ QByteArray mPatternData;
+ CHexValidator *mPatternValidator;
+};
+
+
+
+
+void centerDialog( QWidget *widget, QWidget *centerParent );
+void centerDialogBottom( QWidget *widget, QWidget *centerParent );
+void comboMatchText( QComboBox *combo, const QString &text );
+bool stringToOffset( const QString & text, uint &offset );
+
+void showEntryFailure( QWidget *parent, const QString &msg );
+bool verifyFileDestnation( QWidget *parent, const QString &title,
+ const QString &path );
+
+
+
+#endif
+
+
+
+
+
diff --git a/khexedit/draglabel.cc b/khexedit/draglabel.cc
new file mode 100644
index 0000000..e20088c
--- /dev/null
+++ b/khexedit/draglabel.cc
@@ -0,0 +1,149 @@
+/*
+ * khexedit - Versatile hex editor
+ * Copyright (C) 1999-2000 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 <stdlib.h>
+
+#include <qbitmap.h>
+#include <qpainter.h>
+
+#include <kurldrag.h>
+
+#include "draglabel.h"
+
+
+CDragLabel::CDragLabel( QWidget *parent )
+ : QLabel( "draglabel", parent, "kde toolbar widget" )
+{
+ mValid = true;
+ mDragPending = false;
+ setBackgroundMode( Qt::PaletteButton );
+}
+
+
+CDragLabel::~CDragLabel( void )
+{
+}
+
+
+void CDragLabel::mousePressEvent( QMouseEvent *e )
+{
+ if( mValid == false || e->button() != LeftButton || mUrl.isEmpty() == true )
+ {
+ return;
+ }
+
+ mDragOrigin = e->pos();
+ mDragPending = true;
+}
+
+
+void CDragLabel::mouseMoveEvent( QMouseEvent *e )
+{
+ if( mDragPending == true )
+ {
+ if( abs(e->x() - mDragOrigin.x()) + abs(e->y() - mDragOrigin.y()) > 5 )
+ {
+ mDragPending = false;
+
+ //
+ // Make drag object, assign pixmap and grab keyboard. The grabbing
+ // will allow ESC to abort the drag
+ //
+ KURL::List uris;
+ uris.append(KURL(mUrl));
+ KURLDrag *uriDrag = new KURLDrag( uris, this );
+ if( uriDrag == 0 ) { return; }
+ prepPixmap( *uriDrag );
+ grabKeyboard();
+ uriDrag->drag();
+ releaseKeyboard();
+ }
+ }
+}
+
+void CDragLabel::mouseReleaseEvent( QMouseEvent * )
+{
+ mDragPending = false;
+}
+
+
+void CDragLabel::setUrl( const QString &url )
+{
+ mUrl = url;
+}
+
+
+void CDragLabel::setDragMask( const QPixmap pix )
+{
+ mDragMask = pix;
+}
+
+
+void CDragLabel::prepPixmap( KURLDrag &uriDrag )
+{
+ if( pixmap() == 0 )
+ {
+ return;
+ }
+
+ QString text;
+ int index = mUrl.findRev( '/', mUrl.length() );
+ if( index < 0 )
+ {
+ text = mUrl;
+ }
+ else
+ {
+ text = mUrl.right( mUrl.length() - index - 1 );
+ }
+
+ int sep = 2;
+ QRect rect = fontMetrics().boundingRect(text);
+ int w = pixmap()->width() + rect.width() + sep + 2;
+ int h = fontMetrics().lineSpacing();
+ if( pixmap()->height() > h ) { h = pixmap()->height(); }
+
+ QBitmap mask( w, h, TRUE );
+ QPixmap dragPixmap( w, h );
+ dragPixmap.fill( black );
+
+ QPainter p;
+ p.begin( &mask );
+ p.setPen( white );
+ p.drawPixmap( 0, 0, mDragMask );
+ p.drawText( pixmap()->width()+sep, 0, w-pixmap()->width()+sep,
+ h, AlignVCenter|AlignLeft, text );
+ p.end();
+
+ p.begin( &dragPixmap );
+ p.drawPixmap( 0, 0, *pixmap() );
+ p.end();
+
+ dragPixmap.setMask( mask );
+
+ QPoint hotspot( pixmap()->width(), pixmap()->height()/2 );
+ uriDrag.setPixmap( dragPixmap, hotspot );
+}
+
+
+
+
+
+#include "draglabel.moc"
diff --git a/khexedit/draglabel.h b/khexedit/draglabel.h
new file mode 100644
index 0000000..d90b5ed
--- /dev/null
+++ b/khexedit/draglabel.h
@@ -0,0 +1,60 @@
+/*
+ * khexedit - Versatile hex editor
+ * Copyright (C) 1999-2000 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.
+ *
+ */
+
+#ifndef _DRAG_SOURCE_H_
+#define _DRAG_SOURCE_H_
+
+#include <qdropsite.h>
+#include <qlabel.h>
+#include <qbitmap.h>
+#include <qstring.h>
+#include <qstrlist.h>
+
+class KURLDrag;
+
+class CDragLabel: public QLabel
+{
+ Q_OBJECT
+
+ public:
+ CDragLabel( QWidget *parent );
+ ~CDragLabel( void );
+
+ void setUrl( const QString &url );
+ void setDragMask( const QPixmap pix );
+
+ protected:
+ void mousePressEvent( QMouseEvent * );
+ void mouseMoveEvent( QMouseEvent * );
+ void mouseReleaseEvent( QMouseEvent * );
+
+ private:
+ void prepPixmap( KURLDrag &uriDrag );
+
+ private:
+ bool mValid;
+ QString mUrl;
+ QBitmap mDragMask;
+ bool mDragPending;
+ QPoint mDragOrigin;
+
+};
+
+#endif
diff --git a/khexedit/exportdialog.cc b/khexedit/exportdialog.cc
new file mode 100644
index 0000000..a178319
--- /dev/null
+++ b/khexedit/exportdialog.cc
@@ -0,0 +1,696 @@
+/*
+ * 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 <limits.h>
+#include <qbuttongroup.h>
+#include <qlineedit.h>
+
+#include <kfiledialog.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+#include "dialog.h"
+#include "exportdialog.h"
+#include <qpushbutton.h>
+
+
+CExportDialog::CExportDialog( QWidget *parent, char *name, bool modal )
+ :KDialogBase( Tabbed, i18n("Export Document"), Help|Ok|Cancel, Ok,
+ parent, name, modal )
+{
+ setHelp( "khexedit/khexedit.html", QString::null );
+
+ mFrame[ page_destination ] = addPage( i18n("Destination") );
+ mFrame[ page_option ] = addPage( i18n("Options") );
+
+ setupDestinationPage();
+ setupOptionPage();
+
+ mConfig = 0;
+ readConfiguration();
+
+ QString path = mDestination.fileInput->text();
+ int index = path.findRev( '/' );
+ if( index != -1 ) { mWorkDir = path.left( index+1 ); }
+}
+
+
+CExportDialog::~CExportDialog( void )
+{
+ writeConfiguration();
+ delete mConfig; mConfig = 0;
+}
+
+
+void CExportDialog::showEvent( QShowEvent *e )
+{
+ KDialogBase::showEvent(e);
+ showPage(0);
+ mDestination.fileInput->setFocus();
+}
+
+
+void CExportDialog::readConfiguration( void )
+{
+ if( mConfig != 0 ) { return; }
+
+ mConfig = new KSimpleConfig( QString("hexexport") );
+ if( mConfig == 0 ) { return; }
+
+ mConfig->setGroup( "Destination" );
+
+ int val = mConfig->readNumEntry( "Format", 0 );
+ mDestination.formatCombo->setCurrentItem( val );
+ formatChanged( val < 0 || val > option_html ? 0 : val );
+
+ mConfig->setGroup( "Option" );
+ val = mConfig->readNumEntry( "HtmlLine", 80 );
+ mHtml.lineSpin->setValue( val );
+ QString text = mConfig->readEntry( "HtmlPrefix", "table" );
+ mHtml.prefixInput->setText( text );
+ val = mConfig->readNumEntry( "HtmlHeader", 1 );
+ mHtml.topCombo->setCurrentItem( val < 0 || val >= 4 ? 0 : val );
+ val = mConfig->readNumEntry( "HtmlFooter", 3 );
+ mHtml.bottomCombo->setCurrentItem( val < 0 || val >= 4 ? 0 : val );
+
+ bool state = mConfig->readBoolEntry( "HtmlSymlink", true );
+ mHtml.symlinkCheck->setChecked( state );
+ state = mConfig->readBoolEntry( "HtmlNavigatorBar", true );
+ mHtml.navigatorCheck->setChecked( state );
+ state = mConfig->readBoolEntry( "HtmlBlackWhite", false );
+ mHtml.bwCheck->setChecked( state );
+
+ text = mConfig->readEntry( "ArrayName", "buffer" );
+ mArray.nameInput->setText( text );
+ text = mConfig->readEntry( "ArrayElementType", "char" );
+ for( int i=0; i < mArray.typeCombo->count(); i++ )
+ {
+ if( mArray.typeCombo->text(i) == text )
+ {
+ mArray.typeCombo->setCurrentItem(i);
+ break;
+ }
+ }
+ val = mConfig->readNumEntry( "ArrayElementPerLine", 20 );
+ val = QMAX( val, mArray.lineSizeSpin->minValue() );
+ val = QMIN( val, mArray.lineSizeSpin->maxValue() );
+ mArray.lineSizeSpin->setValue( val );
+ state = mConfig->readBoolEntry( "ArrayUnsignedAsHex", true );
+ mArray.hexadecimalCheck->setChecked( state );
+}
+
+
+void CExportDialog::writeConfiguration( void )
+{
+ if( mConfig == 0 )
+ {
+ return;
+ }
+
+ mConfig->setGroup( "Destination" );
+ mConfig->writeEntry( "Format", mDestination.formatCombo->currentItem() );
+
+ mConfig->setGroup( "Option" );
+ mConfig->writeEntry( "HtmlLine", mHtml.lineSpin->value() );
+ mConfig->writeEntry( "HtmlPrefix", mHtml.prefixInput->text() );
+ mConfig->writeEntry( "HtmlHeader", mHtml.topCombo->currentItem() );
+ mConfig->writeEntry( "HtmlFooter", mHtml.bottomCombo->currentItem() );
+ mConfig->writeEntry( "HtmlSymlink", mHtml.symlinkCheck->isChecked());
+ mConfig->writeEntry( "HtmlNavigatorBar",mHtml.navigatorCheck->isChecked());
+ mConfig->writeEntry( "HtmlBlackWhite", mHtml.bwCheck->isChecked() );
+
+
+ mConfig->writeEntry( "ArrayName", mArray.nameInput->text() );
+ mConfig->writeEntry( "ArrayElementType", mArray.typeCombo->currentText() );
+ mConfig->writeEntry( "ArrayElementPerLine", mArray.lineSizeSpin->value() );
+ mConfig->writeEntry( "ArrayUnsignedAsHex",
+ mArray.hexadecimalCheck->isChecked() );
+ mConfig->sync();
+}
+
+
+void CExportDialog::setupDestinationPage( void )
+{
+ QString text;
+ QFrame *page = mFrame[ page_destination ];
+
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
+ if( topLayout == 0 ) { return; }
+
+ QStringList formatList;
+ formatList.append( i18n("Plain Text") );
+ formatList.append( i18n("HTML Tables") );
+ formatList.append( i18n("Rich Text (RTF)") );
+ formatList.append( i18n("C Array") );
+
+ mDestination.formatCombo = new QComboBox( false, page );
+ mDestination.formatCombo->insertStringList( formatList );
+ mDestination.formatCombo->setMinimumWidth( fontMetrics().maxWidth()*10 );
+ connect( mDestination.formatCombo, SIGNAL(activated(int)),
+ SLOT(formatChanged(int)) );
+
+ text = i18n("&Format:");
+ QLabel *label = new QLabel( mDestination.formatCombo, text, page );
+ topLayout->addWidget( label );
+ topLayout->addWidget( mDestination.formatCombo );
+
+ QHBoxLayout *hbox = new QHBoxLayout();
+ topLayout->addLayout( hbox );
+
+ text = i18n("&Destination:");
+ label = new QLabel( text, page );
+ hbox->addWidget( label );
+
+ text = i18n("(Package folder)");
+ mDestination.fileExtraLabel = new QLabel( text, page );
+ hbox->addWidget( mDestination.fileExtraLabel, 10, AlignLeft|AlignVCenter );
+
+ hbox = new QHBoxLayout();
+ topLayout->addLayout( hbox );
+
+ mDestination.fileInput = new QLineEdit( page );
+ hbox->addWidget( mDestination.fileInput );
+ connect(mDestination.fileInput, SIGNAL(textChanged ( const QString & )),this,SLOT(destinationChanged(const QString &)));
+ text = i18n("Choose...");
+ QPushButton *browseButton = new QPushButton( text, page, "browse" );
+ hbox->addWidget( browseButton );
+ connect( browseButton, SIGNAL(clicked()), SLOT(browserClicked()) );
+ mDestination.fileInput->setMinimumWidth( fontMetrics().maxWidth()*15 );
+
+ label->setBuddy(mDestination.fileInput);
+
+ hbox = new QHBoxLayout();
+ topLayout->addLayout( hbox, 10 );
+
+ mDestination.rangeBox = new QButtonGroup( i18n("Export Range"), page );
+ hbox->addWidget( mDestination.rangeBox );
+
+ QButtonGroup *group = mDestination.rangeBox; // convenience
+
+ QVBoxLayout *vbox = new QVBoxLayout( group, spacingHint() );
+ vbox->addSpacing( fontMetrics().lineSpacing() );
+
+ QRadioButton *radio1 = new QRadioButton( i18n("&Everything"), group );
+ radio1->setFixedSize( radio1->sizeHint() );
+ mDestination.rangeBox->insert( radio1, 0 );
+ vbox->addWidget( radio1, 0, AlignLeft );
+
+ QRadioButton *radio2 = new QRadioButton( i18n("&Selection"), group );
+ radio2->setFixedSize( radio2->sizeHint() );
+ mDestination.rangeBox->insert( radio2, 1 );
+ vbox->addWidget( radio2, 0, AlignLeft );
+
+ QRadioButton *radio3 = new QRadioButton( i18n("&Range"), group );
+ radio3->setFixedSize( radio3->sizeHint() );
+ mDestination.rangeBox->insert( radio3, 2 );
+ vbox->addWidget( radio3, 0, AlignLeft );
+
+ QGridLayout *gbox = new QGridLayout( 2, 2, spacingHint() );
+ vbox->addLayout( gbox );
+
+ mDestination.fromInput = new QLineEdit( group );
+ text = i18n("&From offset:");
+ mDestination.fromLabel = new QLabel( mDestination.fromInput, text, group );
+ gbox->addWidget( mDestination.fromLabel, 0, 0 );
+ gbox->addWidget( mDestination.fromInput, 0, 1 );
+
+ mDestination.toInput = new QLineEdit( group );
+ text = i18n("&To offset:");
+ mDestination.toLabel = new QLabel( mDestination.toInput, text, group );
+ gbox->addWidget( mDestination.toLabel, 1, 0 );
+ gbox->addWidget( mDestination.toInput, 1, 1 );
+
+ connect( group, SIGNAL(clicked(int)), SLOT(rangeChanged(int)) );
+ group->setButton(0);
+ rangeChanged(0);
+ enableButtonOK( !mDestination.fileInput->text().isEmpty() );
+}
+
+void CExportDialog::destinationChanged(const QString &_text)
+{
+ enableButtonOK( !_text.isEmpty() );
+}
+
+void CExportDialog::setupOptionPage( void )
+{
+ QFrame *page = mFrame[ page_option ];
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
+ if( topLayout == 0 ) { return; }
+
+ mOptionStack = new QWidgetStack( page, "stack" );
+ if( mOptionStack == 0 ) { return; }
+ topLayout->addWidget( mOptionStack );
+
+ makeTextOption();
+ makeHtmlOption();
+ makeRtfOption();
+ makeCArrayOption();
+ mOptionStack->raiseWidget( (int)option_text );
+
+ QSize size = mOptionStack->sizeHint();
+ size += QSize(spacingHint()*2, spacingHint()*2);
+ page->setMinimumSize( size );
+}
+
+
+void CExportDialog::makeTextOption( void )
+{
+ QFrame *page = new QFrame( mFrame[ page_option ] );
+ if( page == 0 ) { return; }
+ mOptionStack->addWidget( page, option_text );
+
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
+ QString text = i18n("No options for this format.");
+ QLabel *label = new QLabel( text, page );
+ topLayout->addWidget( label, 0, AlignCenter );
+}
+
+
+void CExportDialog::makeHtmlOption( void )
+{
+ QFrame *page = new QFrame( mFrame[ page_option ] );
+ if( page == 0 ) { return; }
+ mOptionStack->addWidget( page, option_html );
+
+ QString text;
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
+ if( topLayout == 0 ) { return; }
+
+ text = i18n("HTML Options (one table per page)");
+ QLabel *label = new QLabel( text, page );
+ topLayout->addWidget( label );
+
+ QFrame *hline = new QFrame( page );
+ hline->setFrameStyle( QFrame::Sunken | QFrame::HLine );
+ topLayout->addWidget( hline );
+
+ QFrame *frame = new QFrame( page );
+ if( frame == 0 ) { return; }
+ topLayout->addWidget( frame );
+
+ QGridLayout *gbox = new QGridLayout( frame, 4, 2, 0, spacingHint() );
+ if( gbox == 0 ) { return; }
+ gbox->setColStretch( 1, 10 );
+
+ mHtml.lineSpin = new QSpinBox( frame );
+ mHtml.lineSpin->setMinimumWidth( fontMetrics().maxWidth()*10 );
+ mHtml.lineSpin->setRange( 5, INT_MAX );
+ gbox->addWidget( mHtml.lineSpin, 0, 1 );
+
+ text = i18n("&Lines per table:");
+ label = new QLabel( mHtml.lineSpin, text, frame );
+ gbox->addWidget( label, 0, 0 );
+
+ mHtml.prefixInput = new QLineEdit( frame, "prefix" );
+ mHtml.prefixInput->setMinimumWidth( fontMetrics().maxWidth()*10 );
+ gbox->addWidget( mHtml.prefixInput, 1, 1 );
+
+ text = i18n("Filename &prefix (in package):");
+ label = new QLabel( mHtml.prefixInput, text, frame );
+ gbox->addWidget( label, 1, 0 );
+
+ QStringList headerList;
+ headerList.append( i18n("None") );
+ headerList.append( i18n("Filename with Path") );
+ headerList.append( i18n("Filename") );
+ headerList.append( i18n("Page Number") );
+
+ mHtml.topCombo = new QComboBox( false, frame );
+ mHtml.topCombo->insertStringList( headerList );
+ gbox->addWidget( mHtml.topCombo, 2, 1 );
+
+ text = i18n("Header &above text:");
+ label = new QLabel( mHtml.topCombo, text, frame );
+ gbox->addWidget( label, 2, 0 );
+
+ mHtml.bottomCombo = new QComboBox( false, frame );
+ mHtml.bottomCombo->insertStringList( headerList );
+ gbox->addWidget( mHtml.bottomCombo, 3, 1 );
+
+ text = i18n("&Footer below text:");
+ label = new QLabel( mHtml.bottomCombo, text, frame );
+ gbox->addWidget( label, 3, 0 );
+
+ text = i18n("Link \"index.html\" to &table of contents file");
+ mHtml.symlinkCheck = new QCheckBox( text, page );
+ topLayout->addWidget( mHtml.symlinkCheck );
+
+ text = i18n("&Include navigator bar");
+ mHtml.navigatorCheck = new QCheckBox( text, page );
+ topLayout->addWidget( mHtml.navigatorCheck );
+
+ text = i18n("&Use black and white only");
+ mHtml.bwCheck = new QCheckBox( text, page );
+ topLayout->addWidget( mHtml.bwCheck );
+
+ topLayout->addStretch(10);
+}
+
+
+void CExportDialog::makeRtfOption( void )
+{
+ QFrame *page = new QFrame( mFrame[ page_option ] );
+ if( page == 0 ) { return; }
+ mOptionStack->addWidget( page, option_rtf );
+
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
+ QString text = i18n("No options for this format.");
+ QLabel *label = new QLabel( text, page );
+ topLayout->addWidget( label, 0, AlignCenter );
+}
+
+
+void CExportDialog::makeCArrayOption( void )
+{
+ QFrame *page = new QFrame( mFrame[ page_option ] );
+ mOptionStack->addWidget( page, option_carray );
+
+ QString text;
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
+
+ text = i18n("C Array Options");
+ QLabel *label = new QLabel( text, page );
+ topLayout->addWidget( label, 0, AlignLeft );
+
+ QFrame *hline = new QFrame( page );
+ hline->setFrameStyle( QFrame::Sunken | QFrame::HLine );
+ topLayout->addWidget( hline );
+
+ QGridLayout *gbox = new QGridLayout( 3, 2, spacingHint() );
+ topLayout->addLayout( gbox );
+ gbox->setColStretch( 1, 10 );
+
+ mArray.nameInput = new QLineEdit( page );
+ gbox->addWidget( mArray.nameInput, 0, 1 );
+ text = i18n("Array name:");
+ label = new QLabel( mArray.nameInput, text, page );
+ gbox->addWidget( label, 0, 0 );
+
+ QStringList typeList;
+ typeList.append( i18n("char") );
+ typeList.append( i18n("unsigned char") );
+ typeList.append( i18n("short") );
+ typeList.append( i18n("unsigned short") );
+ typeList.append( i18n("int") );
+ typeList.append( i18n("unsigned int") );
+ typeList.append( i18n("float") );
+ typeList.append( i18n("double") );
+ mArray.typeCombo = new QComboBox( false, page );
+ mArray.typeCombo->insertStringList( typeList );
+ mArray.typeCombo->setMinimumWidth( fontMetrics().maxWidth()*10 );
+ gbox->addWidget( mArray.typeCombo, 1, 1 );
+ text = i18n("Element type:");
+ label = new QLabel( mArray.typeCombo, text, page );
+ gbox->addWidget( label, 1, 0 );
+
+ mArray.lineSizeSpin = new QSpinBox( page );
+ mArray.lineSizeSpin->setMinimumWidth( fontMetrics().maxWidth()*10 );
+ mArray.lineSizeSpin->setRange( 1, INT_MAX );
+ gbox->addWidget( mArray.lineSizeSpin, 2, 1 );
+ text = i18n("Elements per line:");
+ label = new QLabel( mArray.lineSizeSpin, text, page );
+ gbox->addWidget( label, 2, 0 );
+
+ text = i18n("Print unsigned values as hexadecimal");
+ mArray.hexadecimalCheck = new QCheckBox( text, page );
+ topLayout->addWidget( mArray.hexadecimalCheck );
+
+ topLayout->addStretch(10);
+}
+
+
+
+
+
+void CExportDialog::formatChanged( int index )
+{
+ mDestination.formatCombo->setCurrentItem(index);
+ mDestination.fileExtraLabel->setEnabled( index == option_html );
+ mOptionStack->raiseWidget( index );
+}
+
+
+void CExportDialog::rangeChanged( int id )
+{
+ bool state = id == 2 ? true : false;
+ mDestination.toLabel->setEnabled( state );
+ mDestination.fromLabel->setEnabled( state );
+ mDestination.toInput->setEnabled( state );
+ mDestination.fromInput->setEnabled( state );
+}
+
+
+void CExportDialog::browserClicked( void )
+{
+ QString url;
+ if( mDestination.formatCombo->currentItem() == option_html )
+ {
+ url = KFileDialog::getExistingDirectory( mWorkDir, topLevelWidget() );
+ }
+ else
+ {
+ url = KFileDialog::getSaveFileName( mWorkDir, "*", topLevelWidget() );
+ }
+
+ if( url.isEmpty() )
+ {
+ return;
+ }
+
+ int index = url.findRev( '/' );
+ if( index != -1 )
+ {
+ mWorkDir = url.left( index+1 );
+ }
+ mDestination.fileInput->setText( url );
+}
+
+
+void CExportDialog::slotOk( void )
+{
+ QString path( mDestination.fileInput->text() );
+
+ int format = mDestination.formatCombo->currentItem();
+ if( format == option_text )
+ {
+ if( verifyFileDestnation( this, i18n("Export Document"), path ) == false )
+ {
+ return;
+ }
+
+ SExportText e;
+ uint mode;
+ if( collectRange( mode, e.range.start, e.range.stop ) == false )
+ {
+ showEntryFailure( this, QString("") );
+ return;
+ }
+ e.range.mode = (SExportRange::EMode)mode; // FIXME
+ e.destFile = path;
+
+ hide();
+ emit exportText(e);
+ }
+ else if( format == option_html )
+ {
+ SExportHtml e;
+ uint mode;
+ if( collectRange( mode, e.range.start, e.range.stop ) == false )
+ {
+ showEntryFailure( this, QString("") );
+ return;
+ }
+ e.range.mode = (SExportRange::EMode)mode; // FIXME
+
+ const QString str = mHtml.prefixInput->text().stripWhiteSpace();
+ mHtml.prefixInput->setText( str );
+ if( mHtml.prefixInput->text().isEmpty() == true )
+ {
+ mHtml.prefixInput->setText( "table" );
+ }
+
+ const QString prefix = mHtml.prefixInput->text();
+ for( uint i=0; i<prefix.length(); i++ )
+ {
+ QChar c = prefix[i];
+ if( c.isSpace() == true || c.isPunct() == true )
+ {
+ QString msg = i18n("The filename prefix can not contain empty letters "
+ "or punctuation marks.");
+ KMessageBox::sorry( this, msg, i18n("Export Document") );
+ return;
+ }
+ }
+
+ if( verifyPackage( path ) == false )
+ {
+ return;
+ }
+
+ e.package = path;
+ e.prefix = prefix;
+ e.linePerPage = mHtml.lineSpin->value();
+ e.topCaption = mHtml.topCombo->currentItem();
+ e.bottomCaption = mHtml.bottomCombo->currentItem();
+ e.symLink = mHtml.symlinkCheck->isChecked();
+ e.navigator = mHtml.navigatorCheck->isChecked();
+ e.blackWhite = mHtml.bwCheck->isChecked();
+
+ hide();
+ emit exportHtml(e);
+ }
+ else if( format == option_rtf )
+ {
+ QString msg = i18n("This format is not yet supported.");
+ KMessageBox::sorry( this, msg );
+ }
+ else if( format == option_carray )
+ {
+ if( verifyFileDestnation( this, i18n("Export Document"), path ) == false )
+ {
+ return;
+ }
+
+ SExportCArray e;
+ uint mode;
+ if( collectRange( mode, e.range.start, e.range.stop ) == false )
+ {
+ showEntryFailure( this, QString("") );
+ return;
+ }
+ e.range.mode = (SExportRange::EMode)mode; // FIXME
+ e.destFile = path;
+ e.arrayName = mArray.nameInput->text();
+ e.elementType = mArray.typeCombo->currentItem();
+ e.elementPerLine = mArray.lineSizeSpin->value();
+ e.unsignedAsHexadecimal = mArray.hexadecimalCheck->isChecked();
+
+ emit exportCArray( e );
+ }
+}
+
+
+
+
+bool CExportDialog::collectRange( uint &mode, uint &start, uint &stop )
+{
+ QButton *b = mDestination.rangeBox->selected();
+ if( b == 0 )
+ {
+ return( false );
+ }
+
+ int id = mDestination.rangeBox->id( b );
+ if( id == 0 )
+ {
+ mode = SExportRange::All;
+ }
+ else if( id == 1 )
+ {
+ mode = SExportRange::Selection;
+ }
+ else if( id == 2 )
+ {
+ mode = SExportRange::Range;
+ bool ok1 = stringToOffset( mDestination.fromInput->text(), start );
+ bool ok2 = stringToOffset( mDestination.toInput->text(), stop );
+ if( ok1 == false || ok2 == false || start >= stop )
+ {
+ return( false );
+ }
+ }
+ else
+ {
+ return( false );
+ }
+
+ return( true );
+}
+
+
+//
+// This one will attempt to create a directory if 'path'
+// specifies a nonexistent name.
+//
+bool CExportDialog::verifyPackage( const QString &path )
+{
+ const QString title = i18n("Export Document");
+
+ if( path.isEmpty() == true )
+ {
+ QString msg = i18n("You must specify a destination.");
+ KMessageBox::sorry( this, msg, title );
+ return( false );
+ }
+
+ QFileInfo info( path );
+ if( info.exists() == false )
+ {
+ QDir directory;
+ if( directory.mkdir( path ) == false )
+ {
+ QString msg;
+ msg += i18n("Unable to create a new folder");
+ msg += "\n";
+ msg += path;
+ KMessageBox::sorry( this, msg, title );
+ return( false );
+ }
+ }
+ else
+ {
+ if( info.isDir() == false )
+ {
+ QString msg = i18n("You have specified an existing file");
+ KMessageBox::sorry( this, msg, title );
+ return( false );
+ }
+ else
+ {
+ if( info.isWritable() == false )
+ {
+ QString msg = i18n( ""
+ "You do not have write permission to this folder.");
+ KMessageBox::sorry( this, msg, title );
+ return( false );
+ }
+
+ const QString prefix = mHtml.prefixInput->text();
+ QString f1 = QString("%1%2.html").arg(prefix).arg("00000000");
+ QString f2 = QString("%1%2.html").arg(prefix).arg("99999999");
+
+ QString msg = i18n( ""
+ "You have specified an existing folder.\n"
+ "If you continue, any existing file in the range "
+ "\"%1\" to \"%2\" can be lost.\n"
+ "Continue?").arg(f1).arg(f2);
+ int reply = KMessageBox::warningContinueCancel( this, msg, title );
+ if( reply != KMessageBox::Continue )
+ {
+ return( false );
+ }
+
+ }
+ }
+
+ return( true );
+}
+
+#include "exportdialog.moc"
diff --git a/khexedit/exportdialog.h b/khexedit/exportdialog.h
new file mode 100644
index 0000000..6d89ac3
--- /dev/null
+++ b/khexedit/exportdialog.h
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _EXPORT_DIALOG_H_
+#define _EXPORT_DIALOG_H_
+
+
+class QButtonGroup;
+class QComboBox;
+class QCheckBox;
+class QFrame;
+class QLabel;
+class QLineEdit;
+class QSpinBox;
+class QWidgetStack;
+class KSimpleConfig;
+
+#include <kdialogbase.h>
+#include "hexbuffer.h"
+
+
+class CExportDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ enum EPage
+ {
+ page_destination = 0,
+ page_option,
+ page_max
+ };
+
+ enum OptionPage
+ {
+ option_text = 0,
+ option_html,
+ option_rtf,
+ option_carray,
+ option_max
+ };
+
+ CExportDialog( QWidget *parent = 0, char *name = 0, bool modal = false );
+ ~CExportDialog( void );
+ void writeConfiguration( void );
+
+ protected:
+ void showEvent( QShowEvent *e );
+
+ protected slots:
+ virtual void slotOk( void );
+ void destinationChanged(const QString &);
+ private:
+ struct SDestinationWidgets
+ {
+ QComboBox *formatCombo;
+ QLabel *fileExtraLabel;
+ QLineEdit *fileInput;
+ QLabel *fromLabel;
+ QLabel *toLabel;
+ QButtonGroup *rangeBox;
+ QLineEdit *fromInput;
+ QLineEdit *toInput;
+ };
+
+ struct SHtmlWidgets
+ {
+ QSpinBox *lineSpin;
+ QLineEdit *prefixInput;
+ QComboBox *topCombo;
+ QComboBox *bottomCombo;
+ QCheckBox *navigatorCheck;
+ QCheckBox *symlinkCheck;
+ QCheckBox *bwCheck;
+ };
+
+ struct SArrayWidgets
+ {
+ QLineEdit *nameInput;
+ QComboBox *typeCombo;
+ QSpinBox *lineSizeSpin;
+ QCheckBox *hexadecimalCheck;
+ };
+
+ private slots:
+ void rangeChanged( int id );
+ void formatChanged( int index );
+ void browserClicked( void );
+
+ private:
+ void setupDestinationPage( void );
+ void setupOptionPage( void );
+ void makeTextOption( void );
+ void makeHtmlOption( void );
+ void makeRtfOption( void );
+ void makeCArrayOption( void );
+ void readConfiguration( void );
+ bool collectRange( uint &mode, uint &start, uint &stop );
+ bool verifyPackage( const QString &path );
+
+ signals:
+ void exportText( const SExportText &e );
+ void exportHtml( const SExportHtml &e );
+ void exportCArray( const SExportCArray &e );
+
+ private:
+ QFrame *mFrame[ page_max ];
+ QWidgetStack *mOptionStack;
+ SDestinationWidgets mDestination;
+ SHtmlWidgets mHtml;
+ SArrayWidgets mArray;
+ KSimpleConfig *mConfig;
+
+ QString mWorkDir;
+};
+
+
+
+
+
+#endif
diff --git a/khexedit/fileinfodialog.cc b/khexedit/fileinfodialog.cc
new file mode 100644
index 0000000..b9dff60
--- /dev/null
+++ b/khexedit/fileinfodialog.cc
@@ -0,0 +1,330 @@
+/*
+ * 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 <qheader.h>
+#include <qlabel.h>
+#include <qlayout.h>
+
+#include <kglobalsettings.h>
+#include <kglobal.h>
+#include <klocale.h>
+
+#include "fileinfodialog.h"
+#include "listview.h"
+
+// quick'n'dirty hack to have the occurrence column sorted correctly
+class CStatisticListViewItem : public QListViewItem
+{
+ public:
+ CStatisticListViewItem( QListView * parent, QListViewItem * after,
+ QString label1, QString label2, QString label3, QString label4,
+ QString label5, QString label6, QString label7, int i, int o)
+ : QListViewItem( parent, after, label1, label2, label3, label4, label5, label6, label7),
+ item( i ),
+ occurrence( o )
+ {}
+
+ virtual int compare( QListViewItem *i, int col, bool ascending/*Qt doc says: ignore this one*/ ) const
+ {
+ // occurrence column (or the percent one)?
+ if( col == 5 || col == 6 )
+ {
+ const int otherOccurrence = ((CStatisticListViewItem*)i)->occurrence;
+ return occurrence < otherOccurrence ? -1 : occurrence == otherOccurrence ? 0 : 1;
+ }
+ // char column?
+ else if( col == 4 )
+ {
+ const int otherItem = ((CStatisticListViewItem*)i)->item;
+ return item < otherItem ? -1 : item == otherItem ? 0 : 1;
+ }
+ // default
+ else
+ return QListViewItem::compare(i,col,ascending);
+ }
+
+ protected:
+ // no of byte
+ int item;
+ // number of the byte's occurrence
+ int occurrence;
+};
+
+
+
+CFileInfoDialog::CFileInfoDialog( QWidget *parent,const char *name,bool modal)
+ :KDialogBase( Plain, i18n("Statistics"), Help|User1|Cancel, User1,
+ parent, name, modal, true, i18n("&Update") ),
+ mBusy(false), mDirty(false)
+{
+ setHelp( "khexedit/khexedit.html", QString::null );
+
+ QString text;
+ QVBoxLayout *topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() );
+ if( topLayout == 0 ) { return; }
+
+
+ QGridLayout *gbox = new QGridLayout( 2, 2, spacingHint() );
+ if( gbox == 0 ) { return; }
+ topLayout->addLayout( gbox );
+ gbox->setColStretch( 1, 10 );
+
+ text = i18n("File name: ");
+ QLabel *label = new QLabel( text, plainPage() );
+ gbox->addWidget( label, 0, 0 );
+
+ text = i18n("Size [bytes]: ");
+ label = new QLabel( text, plainPage() );
+ gbox->addWidget( label, 1, 0 );
+
+ mFileNameLabel = new QLabel( plainPage() );
+ mFileSizeLabel = new QLabel( plainPage() );
+ gbox->addWidget( mFileNameLabel, 0, 1 );
+ gbox->addWidget( mFileSizeLabel, 1, 1 );
+
+ mFrequencyList = new CListView( plainPage(), "stringList" );
+ mFrequencyList->setFont( KGlobalSettings::fixedFont() );
+
+ mFrequencyList->addColumn( i18n("Hexadecimal") );
+ mFrequencyList->addColumn( i18n("Decimal") );
+ mFrequencyList->addColumn( i18n("Octal") );
+ mFrequencyList->addColumn( i18n("Binary") );
+ mFrequencyList->addColumn( i18n("Text") );
+ mFrequencyList->addColumn( i18n("Occurrence") );
+ mFrequencyList->addColumn( i18n("Percent") );
+ mFrequencyList->setAllColumnsShowFocus( true );
+ mFrequencyList->setFrameStyle( QFrame::WinPanel + QFrame::Sunken );
+ topLayout->addWidget( mFrequencyList, 10 );
+
+ mDirtyLabel = new QLabel( plainPage() );
+ mDirtyLabel->setFixedHeight( fontMetrics().height() );
+ topLayout->addWidget( mDirtyLabel );
+
+ setStatistics();
+ setColumnWidth();
+ mFrequencyList->setVisibleItem( 15 );
+
+ //
+ // Load the first set of data when this timer expires. I do it this
+ // way so that the dialog will be visible when the load operation starts.
+ //
+ startTimer( 0 );
+}
+
+
+CFileInfoDialog::~CFileInfoDialog( void )
+{
+}
+
+
+void CFileInfoDialog::slotUser1( void ) // Update
+{
+ if( mBusy )
+ return;
+
+ SStatisticControl *sc = new SStatisticControl;
+ if( sc == 0 ) { return; }
+
+ mBusy = true;
+ emit collectStatistic( *sc );
+ mBusy = false;
+
+ delete sc;
+
+}
+
+
+void CFileInfoDialog::setDirty( void )
+{
+ if( mDirty )
+ return;
+
+ mDirtyLabel->setText(
+ i18n("Warning: Document has been modified since last update"));
+ mDirty = true;
+}
+
+
+void CFileInfoDialog::setClean( void )
+{
+ if( !mDirty )
+ return;
+
+ mDirtyLabel->setText("");
+ mDirty = false;
+}
+
+
+const char *printBin( uint val )
+{
+ static char buf[9];
+ for( int i = 0; i < 8; i++ )
+ buf[7-i] = (val&(1<<i)) ? '1' : '0';
+ buf[8] = 0;
+ return( buf );
+}
+
+
+void CFileInfoDialog::setStatistics() // Default
+{
+ setClean();
+ mFrequencyList->clear();
+ mFileNameLabel->clear();
+ mFileSizeLabel->clear();
+
+ static const QString u("?");
+ QString d, h, o, b, c;
+ QListViewItem *item = 0;
+
+ char buf[10];
+ memset( buf, 0, sizeof( buf ) );
+
+ for( uint i=0; i<256; i++ )
+ {
+ h.sprintf("0x%02x", i );
+ d.sprintf("%03d", i );
+ o.sprintf("%03o", i );
+ b.sprintf("%s", printBin(i) );
+
+ const QChar _i((char)i);
+ c = _i.isPrint() ? _i : QChar('.');
+
+ item = new CStatisticListViewItem( mFrequencyList, item, h, d, o, b, c, u, u, i, -1 );
+ if( i == 0 )
+ mFrequencyList->setSelected( item, true );
+ }
+}
+
+
+
+void CFileInfoDialog::setStatistics( SStatisticControl &sc )
+{
+ setClean();
+ mFrequencyList->clear();
+ mFileNameLabel->setText( sc.documentName );
+ mFileSizeLabel->setText( KGlobal::locale()->formatNumber(sc.documentSize, 0) );
+
+ QString d, h, o, b, c, n, p;
+ QListViewItem *item = 0;
+
+ uint size, pre, i;
+ // find width of occurrence
+ for( i=size=0; i<256; i++ )
+ if( sc.occurrence[i] > size )
+ size = sc.occurrence[i];
+ for( pre = 1; size > 0 ; pre++ )
+ size /= 10;
+
+ for( i=0; i<256; i++ )
+ {
+ h.sprintf("0x%02x", i );
+ d.sprintf("%03d", i );
+ o.sprintf("%03o", i );
+ b.sprintf("%s", printBin(i) );
+
+ n = QString("%1").arg( sc.occurrence[i], pre );
+ if( sc.documentSize == 0 )
+ p = "0.00";
+ else
+ {
+ double val = 100.0*((double)sc.occurrence[i]/(double)sc.documentSize);
+ p = QString("%1").arg( val, 6, 'f', 2 );
+ }
+
+ const QChar _i((char)i);
+ c = _i.isPrint() ? _i : QChar('.');
+
+ item = new CStatisticListViewItem( mFrequencyList, item, h, d, o, b, c, n, p, i, sc.occurrence[i] );
+ if( i == 0 )
+ mFrequencyList->setSelected( item, true );
+ }
+}
+
+
+
+void CFileInfoDialog::setColumnWidth( void )
+{
+ const QFontMetrics &fm = mFrequencyList->fontMetrics();
+ int w0, w1, w2, w3, w4;
+
+ w0 = -fm.minLeftBearing() - fm.minRightBearing() + 8 + fm.maxWidth();
+ w3 = 0;
+
+ w1 = fm.width( mFrequencyList->header()->label(0) ) + w0;
+ w2 = fm.width('0')*6;
+ w3 += w1 > w2 ? w1 : w2;
+ mFrequencyList->setColumnWidth( 0, w1 > w2 ? w1 : w2 );
+
+ w1 = fm.boundingRect( mFrequencyList->header()->label(1) ).width() + w0;
+ w2 = fm.width('0')*5;
+ w3 += w1 > w2 ? w1 : w2;
+ mFrequencyList->setColumnWidth( 1, w1 > w2 ? w1 : w2 );
+
+ w1 = fm.boundingRect( mFrequencyList->header()->label(2) ).width() + w0;
+ w2 = fm.width('0')*5;
+ w3 += w1 > w2 ? w1 : w2;
+ mFrequencyList->setColumnWidth( 2, w1 > w2 ? w1 : w2 );
+
+ w1 = fm.boundingRect( mFrequencyList->header()->label(3) ).width() + w0;
+ w2 = fm.width('0')*10;
+ w3 += w1 > w2 ? w1 : w2;
+ mFrequencyList->setColumnWidth( 3, w1 > w2 ? w1 : w2 );
+
+ w1 = fm.boundingRect( mFrequencyList->header()->label(4) ).width() + w0;
+ w2 = fm.width('0')*3;
+ w3 += w1 > w2 ? w1 : w2;
+ mFrequencyList->setColumnWidth( 4, w1 > w2 ? w1 : w2 );
+
+ w1 = fm.boundingRect( mFrequencyList->header()->label(5) ).width() + w0;
+ w2 = fm.width('0')*10;
+ w3 += w1 > w2 ? w1 : w2;
+ mFrequencyList->setColumnWidth( 5, w1 > w2 ? w1 : w2 );
+
+ w4 = mFrequencyList->viewport()->width() - w3;
+ w1 = fm.boundingRect( mFrequencyList->header()->label(6) ).width() + w0;
+ w2 = fm.width('0')*3;
+ w1 = w1 > w2 ? w1 : w2;
+ mFrequencyList->setColumnWidth( 6, w1 > w4 ? w1 : w4 );
+}
+
+
+void CFileInfoDialog::resizeEvent( QResizeEvent * )
+{
+ setColumnWidth();
+}
+
+
+void CFileInfoDialog::showEvent( QShowEvent *e )
+{
+ KDialogBase::showEvent(e);
+ setColumnWidth();
+ mFrequencyList->setFocus();
+}
+
+
+void CFileInfoDialog::timerEvent( QTimerEvent * )
+{
+ killTimers();
+ slotUser1();
+}
+
+
+
+#include "fileinfodialog.moc"
diff --git a/khexedit/fileinfodialog.h b/khexedit/fileinfodialog.h
new file mode 100644
index 0000000..c994d48
--- /dev/null
+++ b/khexedit/fileinfodialog.h
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _FILE_INFO_DIALOG_H_
+#define _FILE_INFO_DIALOG_H_
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+class QLabel;
+
+#include <kdialogbase.h>
+
+class CListView;
+#include "hexbuffer.h"
+
+class CFileInfoDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ CFileInfoDialog( QWidget *parent=0, const char *name=0,bool modal=false );
+ ~CFileInfoDialog( void );
+
+ void setStatistics( void );
+ void setStatistics( SStatisticControl &sc );
+
+ public slots:
+ void setDirty( void );
+ void setClean( void );
+
+ protected slots:
+ virtual void slotUser1( void );
+
+ protected:
+ virtual void resizeEvent( QResizeEvent * );
+ virtual void showEvent( QShowEvent * );
+ virtual void timerEvent( QTimerEvent * );
+
+ private:
+ void setColumnWidth( void );
+
+ signals:
+ void collectStatistic( SStatisticControl &sc );
+
+ private:
+ bool mBusy;
+ bool mDirty;
+ CListView *mFrequencyList;
+ QLabel *mFileNameLabel;
+ QLabel *mFileSizeLabel;
+ QLabel *mDirtyLabel;
+};
+
+#endif
diff --git a/khexedit/hexbuffer.cc b/khexedit/hexbuffer.cc
new file mode 100644
index 0000000..0c1d598
--- /dev/null
+++ b/khexedit/hexbuffer.cc
@@ -0,0 +1,5099 @@
+/*
+ * khexedit - Versatile hex editor
+ * Copyright (C) 1999-2000 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 <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <qfileinfo.h>
+
+#include <klocale.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <knotifyclient.h>
+
+#include "hexbuffer.h"
+#include "hexerror.h"
+
+//
+// There are some comments marked with a "// ##" at various places.
+// These indicate a patch from Sergey A. Sukiyazov which I have applied
+// "as is" for now. The number of QString::fromLocal8Bit in this modification
+// indicates that I should perhaps modify code elsewhere as well
+// (espen 2000-11-26)
+//
+
+// #define DEBUG_FIXED_SIZE 1024
+// #define PRINTER_TEST
+
+
+CHexAction::CHexAction( HexAction action, uint offset )
+{
+ mAction = action;
+ mOffset = offset;
+ mSize = 0;
+ mData = 0;
+ mDataSize = 0;
+ mNext = 0;
+}
+
+CHexAction::~CHexAction( void )
+{
+ delete [] mData;
+}
+
+void CHexAction::setData( uint size, char *data, uint dataSize )
+{
+
+ if( data != 0 && dataSize > 0 )
+ {
+ mData = new char[ dataSize ];
+ if( mData == 0 )
+ {
+ return;
+ }
+ memcpy( mData, data, dataSize );
+ mDataSize = dataSize;
+ }
+ else
+ {
+ mDataSize = 0;
+ mData = 0;
+ }
+ mSize = size;
+}
+
+
+CHexActionGroup::CHexActionGroup( uint startOffset, uint startBit )
+{
+ mStartOffset = startOffset;
+ mStartBit = startBit;
+ mHexAction = 0;
+}
+
+CHexActionGroup::~CHexActionGroup( void )
+{
+ CHexAction *ptr = mHexAction;
+ while( ptr != 0 )
+ {
+ CHexAction *next = ptr->mNext;
+ delete ptr;
+ ptr = next;
+ }
+}
+
+void CHexActionGroup::insertAction( CHexAction *hexAction )
+{
+ hexAction->mNext = mHexAction;
+ mHexAction = hexAction;
+}
+
+
+
+int SFilterControl::execute( uchar *dest, uchar *src, uint size )
+{
+ if( size == 0 )
+ {
+ return( Err_IllegalArgument );
+ }
+
+ uint numElement = operand.size();
+ if( operation == OperandAndData )
+ {
+ if( numElement == 0 ) { return( Err_IllegalArgument ); }
+ if( forward == true )
+ {
+ for( uint i = 0; i < size; )
+ {
+ for( uint j = 0; i < size && j < numElement; j++, i++ )
+ {
+ dest[i] = src[i] & operand[j];
+ }
+ }
+ }
+ else
+ {
+ for( uint i = size; i > 0; )
+ {
+ for( uint j = numElement; i > 0 && j > 0; j--, i-- )
+ {
+ dest[i-1] = src[i-1] & operand[j-1];
+ }
+ }
+ }
+ }
+ else if( operation == OperandOrData )
+ {
+ if( numElement == 0 ) { return( Err_IllegalArgument ); }
+ if( forward == true )
+ {
+ for( uint i = 0; i < size; )
+ {
+ for( uint j = 0; i < size && j < numElement; j++, i++ )
+ {
+ dest[i] = src[i] | operand[j];
+ }
+ }
+ }
+ else
+ {
+ for( uint i = size; i > 0; )
+ {
+ for( uint j = numElement; i > 0 && j > 0; j--, i-- )
+ {
+ dest[i-1] = src[i-1] | operand[j-1];
+ }
+ }
+ }
+ }
+ else if( operation == OperandXorData )
+ {
+ if( numElement == 0 ) { return( Err_IllegalArgument ); }
+ if( forward == true )
+ {
+ for( uint i = 0; i < size; )
+ {
+ for( uint j = 0; i < size && j < numElement; j++, i++ )
+ {
+ dest[i] = src[i] ^ operand[j];
+ }
+ }
+ }
+ else
+ {
+ for( uint i = size; i > 0; )
+ {
+ for( uint j = numElement; i > 0 && j > 0; j--, i-- )
+ {
+ dest[i-1] = src[i-1] ^ operand[j-1];
+ }
+ }
+ }
+ }
+ else if( operation == InvertData )
+ {
+ for( uint i = 0; i < size; i++ )
+ {
+ dest[i] = ~src[i];
+ }
+ }
+ else if( operation == ReverseData )
+ {
+ for( uint i = 0; i < size; i++ )
+ {
+ uchar flag = src[i];
+ uchar rev = 0;
+ for( uint j = 0; j < 8; j++ )
+ {
+ rev |= (((flag & 0x80) >> (7-j)));
+ flag <<= 1;
+ }
+ dest[i] = rev;
+ }
+ }
+ else if( operation == RotateData || operation == ShiftData )
+ {
+ //
+ // Only forward here
+ //
+ bool up = rotate[1] > 0 ? true : false;
+ int range = rotate[0];
+ int shift = abs(rotate[1]);
+ if( range == 0 || shift == 0 ) { return( Err_IllegalArgument ); }
+ shift = shift % (range*8);
+
+ int b = shift / 8;
+ int s = shift - b * 8;
+
+ for( uint i = 0; i < size; )
+ {
+ if( up == true )
+ {
+ int j;
+ if( operation == RotateData )
+ {
+ for( j=0; j < b && i+range < size ; i++, j++ )
+ {
+ dest[i] = src[i+range-b];
+ }
+ }
+ else
+ {
+ for( j=0; j < b && i < size ; dest[i] = 0, i++, j++ );
+ }
+ for( ; j < range && i < size ; i++, j++ )
+ {
+ dest[i] = src[i-b];
+ }
+
+ uchar last = dest[i-1];
+ for( int k=1; k <= j; k++ )
+ {
+ dest[i-k] >>= s;
+ if( k < j )
+ {
+ dest[i-k] |= dest[i-k-1]<<(8-s);
+ }
+ else if( j == range && operation == RotateData )
+ {
+ dest[i-k] |= last<<(8-s);
+ }
+ }
+ }
+ else
+ {
+ int j;
+ for( j=0; j+b < range && i+b < size ; i++, j++ )
+ {
+ dest[i] = src[i+b];
+ }
+ for( ; j < range && i < size ; i++, j++ )
+ {
+ dest[i] = operation == RotateData ? src[i+b-range] : 0;
+ }
+
+ uchar first = dest[i-j];
+ for( int k=j; k>0; k-- )
+ {
+ dest[i-k] <<= s;
+ if( k>1 )
+ {
+ dest[i-k] |= dest[i-k+1]>>(8-s);
+ }
+ else if( j == range && operation == RotateData )
+ {
+ dest[i-k] |= first>>(8-s);
+ }
+ }
+ }
+ }
+ }
+ else if( operation == SwapBits )
+ {
+ //
+ // Swap bits. Based on Leon Lessing's work.
+ //
+
+ //
+ // Make non swapped version first.
+ //
+ for( uint i = 0; i < size; i++ )
+ {
+ dest[i] = src[i];
+ }
+
+ //
+ // Swap the pairs the have been defined
+ // Format of operand (example):
+ // 7 2 5 0 0 0 0 0
+ // Swap bit 7 with bit 2 and swap bit 5 with bit 0
+ //
+ for( uint j=0; j<4; j++ )
+ {
+ uchar b1 = 1 << (uchar)operand[j*2];
+ uchar b2 = 1 << (uchar)operand[j*2+1];
+ if( b1 == b2 ) { continue; } // Equal, no need to swap.
+
+ for( uint i = 0; i < size; i++ )
+ {
+ uchar b = 0;
+ if( dest[i] & b1 ) { b |= b2; }
+ if( dest[i] & b2 ) { b |= b1; }
+
+ //
+ // A short description so that I will understand what the
+ // h... is going on five minutes from now.
+ //
+ // Destination byte is masked (AND'ed) with the inverse bitmap
+ // (the noninversed bitmap contains position of the
+ // two swap bits, eg 7-2 gives 10000100). Then the destination
+ // is OR'ed with the swapped bitmap.
+ //
+ dest[i] = (dest[i] & ~(b1 | b2)) | b;
+ }
+ }
+ }
+ else
+ {
+ return( Err_IllegalArgument );
+ }
+
+ return( Err_Success );
+}
+
+
+const char *SExportCArray::printFormatted( const char *b, uint maxSize ) const
+{
+ static char buf[12];
+ if( elementType == Char )
+ {
+ char e = 0;
+ memcpy( &e, b, QMIN(sizeof(e),maxSize) );
+ sprintf( buf, "%d", e );
+ return( buf );
+ }
+ else if( elementType == Uchar )
+ {
+ unsigned char e = 0;
+ memcpy( &e, b, QMIN(sizeof(e),maxSize) );
+ if( unsignedAsHexadecimal == true )
+ {
+ sprintf( buf, "0x%02x", e );
+ }
+ else
+ {
+ sprintf( buf, "%u", e );
+ }
+ return( buf );
+ }
+ else if( elementType == Short )
+ {
+ short e = 0;
+ memcpy( &e, b, QMIN(sizeof(e),maxSize) );
+ sprintf( buf, "%d", e );
+ return( buf );
+
+ }
+ else if( elementType == Ushort )
+ {
+ unsigned short e = 0;
+ memcpy( &e, b, QMIN(sizeof(e),maxSize) );
+ if( unsignedAsHexadecimal == true )
+ {
+ sprintf( buf, "0x%04x", e );
+ }
+ else
+ {
+ sprintf( buf, "%u", e );
+ }
+ return( buf );
+ }
+ else if( elementType == Int )
+ {
+ int e = 0;
+ memcpy( &e, b, QMIN(sizeof(e),maxSize) );
+ sprintf( buf, "%u", e );
+ return( buf );
+ }
+ else if( elementType == Uint )
+ {
+ unsigned int e = 0;
+ memcpy( &e, b, QMIN(sizeof(e),maxSize) );
+ if( unsignedAsHexadecimal == true )
+ {
+ sprintf( buf, "0x%08x", e );
+ }
+ else
+ {
+ sprintf( buf, "%u", e );
+ }
+ return( buf );
+ }
+ else if( elementType == Float )
+ {
+ float e = 0;
+ memcpy( &e, b, QMIN(sizeof(e),maxSize) );
+ sprintf( buf, "%f", e );
+ return( buf );
+ }
+ else if( elementType == Double )
+ {
+ double e = 0;
+ memcpy( &e, b, QMIN(sizeof(e),maxSize) );
+ sprintf( buf, "%f", e );
+ return( buf );
+ }
+
+ else
+ {
+ return("");
+ }
+}
+
+
+QString SExportCArray::variableName( uint range ) const
+{
+ const char *typeString[] =
+ {
+ "char",
+ "unsigned char",
+ "short",
+ "unsigned short",
+ "int",
+ "unsigned int",
+ "float",
+ "double"
+ };
+
+ uint es = elementSize();
+ uint numElement = range / es + ((range % es) ? 1 : 0);
+
+ return( QString("%1 %2[%2]").arg(typeString[elementType]).
+ arg(arrayName).arg(numElement) );
+}
+
+
+
+int SExportCArray::elementSize( void ) const
+{
+ if( elementType == Char || elementType == Uchar )
+ {
+ return( sizeof(char) );
+ }
+ else if( elementType == Short || elementType == Ushort )
+ {
+ return( sizeof(short) );
+ }
+ else if( elementType == Int || elementType == Uint )
+ {
+ return( sizeof(int) );
+ }
+ else if( elementType == Float )
+ {
+ return( sizeof(float) );
+ }
+ else if( elementType == Double )
+ {
+ return( sizeof(double) );
+ }
+ else
+ {
+ return(1);
+ }
+}
+
+
+char CHexBuffer::mHexBigBuffer[16]=
+{
+ '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
+};
+
+char CHexBuffer::mHexSmallBuffer[16]=
+{
+ '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'
+};
+
+char CHexBuffer::mDecBuffer[10]=
+{
+ '0','1','2','3','4','5','6','7','8','9'
+};
+
+char CHexBuffer::mOctBuffer[8]=
+{
+ '0','1','2','3','4','5','6','7'
+};
+
+
+SCursorState CHexBuffer::mCursorState;
+SFileState CHexBuffer::mFileState;
+
+
+
+
+CHexBuffer::CHexBuffer( void )
+ :QByteArray()
+{
+ mColorIndex = 0;
+ mPrintBuf = 0;
+ mLoadingData = false;
+ mEditMode = EditReplace;
+ mActiveEditor = edit_primary;
+
+ mDocumentModified = false;
+
+ #ifdef DEBUG_FIXED_SIZE
+ setMaximumSize( DEBUG_FIXED_SIZE );
+ #else
+ setMaximumSize( ~0 );
+ #endif
+
+ setDocumentSize(0);
+
+ #ifdef PRINTER_TEST
+ puts("<CHexBuffer> Printer test is activated");
+ #endif
+
+
+ setInputMode( mInputMode );
+
+ int errCode = setLayout( mLayout );
+ if( errCode != 0 )
+ {
+ return;
+ }
+ setColor( mColor );
+ setFont( mFontInfo.init() );
+ setShowCursor( true );
+ setDisableCursor( false );
+ setEditMode( EditReplace, false, false );
+ setSoundState( false, false );
+
+ mUndoLimit = 10;
+ mUndoIndex = 0;
+ mUndoList.setAutoDelete( TRUE );
+ mBookmarkList.setAutoDelete( TRUE );
+}
+
+
+CHexBuffer::~CHexBuffer( void )
+{
+ //debug("CHexBuffer::~CHexBuffer");
+ delete [] mColorIndex;
+ delete [] mPrintBuf;
+}
+
+
+
+bool CHexBuffer::hasFileName( void )
+{
+ //
+ // FIXME: Files can be called "Untitled" so this must be corrected.
+ //
+ if( mUrl.isEmpty() || mUrl.contains( i18n( "Untitled" ), false ) )
+ {
+ return( false );
+ }
+ else
+ {
+ return( true );
+ }
+}
+
+
+
+int CHexBuffer::setLayout( SDisplayLayout &layout )
+{
+ mLayout = layout;
+ mLayout.verify();
+
+ if( mLayout.primaryMode == SDisplayLayout::textOnly )
+ {
+ mActiveEditor = edit_primary;
+ setEditMode( mEditMode );
+ }
+
+ mCursor.setLineSize( mLayout.lineSize );
+ mCursor.addOffset( 0 ); // This will only reset the cell position
+
+ computeLineWidth();
+ cursorCompute();
+
+ delete [] mColorIndex; mColorIndex = 0;
+ delete [] mPrintBuf; mPrintBuf = 0;
+
+ mColorIndex = new unsigned char[ mLayout.lineSize ];
+ if( mColorIndex == 0 )
+ {
+ return( Err_NoMemory );
+ }
+ setColor( mColor );
+
+ //
+ // The 'mPrintBuf' is used to store formatted text. It is used for all
+ // print operations and must have the size of the 'mDpyState.lineSize' which
+ // is the number of bytes in one single display line.
+ //
+ mPrintBuf = new char[ mLayout.lineSize < 12 ? 12 : mLayout.lineSize ];
+ if( mPrintBuf == 0 )
+ {
+ delete [] mColorIndex; mColorIndex = 0;
+ return( Err_NoMemory );
+ }
+
+ return( Err_Success );
+}
+
+
+void CHexBuffer::setColor( SDisplayColor &color )
+{
+ mColor = color;
+
+ //
+ // Test...
+ //
+ //mColor.secondTextBg = Qt::yellow;
+ //mColor.offsetBg = Qt::lightGray;
+ //mColor.gridFg = Qt::darkCyan;
+
+ /*
+ mColor.secondTextBg = mColor.textBg;
+ mColor.offsetBg = mColor.textBg;
+ mColor.gridFg = mColor.textBg;
+ */
+
+ if( mColorIndex != 0 )
+ {
+ uint columnSize = mLayout.columnSize == 0 ? 1 : mLayout.columnSize;
+ for( uint i = 0, entry = 0; i < mLayout.lineSize; i++ )
+ {
+ if( i > 0 && i % columnSize == 0 ) { entry = entry == 0 ? 1 : 0; }
+ mColorIndex[i] = entry;
+ }
+ }
+}
+
+void CHexBuffer::setInputMode( SDisplayInputMode &mode )
+{
+ mInputMode = mode;
+ if( mInputMode.allowResize == false && mEditMode != EditReplace )
+ {
+ setEditMode( EditReplace );
+ }
+}
+
+
+bool CHexBuffer::toggleEditor( void )
+{
+ bool changed;
+ if( mLayout.secondaryMode == SDisplayLayout::hide )
+ {
+ changed = mActiveEditor == edit_secondary ? true : false;
+ mActiveEditor = edit_primary;
+ }
+ else
+ {
+ changed = true;
+ mActiveEditor = mActiveEditor == edit_primary ?
+ edit_secondary : edit_primary;
+ }
+
+ setEditMode( mEditMode ); // Sets the cursor shapes as well
+
+ if( changed == true )
+ {
+ mCursor.resetCell();
+ cursorCompute();
+ }
+
+ return( changed );
+}
+
+
+
+
+
+
+
+bool CHexBuffer::matchWidth( uint width )
+{
+ if( documentPresent() == false || (uint)mFixedWidth >= width )
+ {
+ return( false );
+ }
+
+ width -= mFixedWidth;
+
+ uint g = mLayout.columnSpacing == 0 ? 1 : mLayout.columnSize;
+ uint n = g * mNumCell;
+ uint u = mUnitWidth;
+ uint s = mLayout.secondaryMode == SDisplayLayout::hide ? 0 : g;
+ uint o = mLayout.columnSpacing == 0 ? 0 : mSplitWidth;
+ float x = (float)(width+o)/(float)(u*(n+s)+o);
+
+ uint lineSize = (uint)x * g;
+
+ if( mLayout.lockColumn == false )
+ {
+ //
+ // Examine if we can add one or more entries from the next column. This
+ // will make the rightmost column smaller than the rest but we will
+ // utilize as much of the available space (ie., width) as possible.
+ // (Note that the entry itself (which represents one byte of filedata)
+ // can not be splitted, eg., in binary mode the entry is eight byte
+ // wide and will not be splitted).
+ //
+ int w = (int)((float)((int)x)* (float)(u*(n+s)+o) - (float)o);
+ if( w > 0 && (uint)w < width )
+ {
+ width -= w;
+ if( width > o )
+ {
+ x = (float)(width-o) / (float)(u*(mNumCell+1));
+ lineSize += (uint)x;
+ }
+ }
+ }
+
+ if( lineSize == 0 || lineSize == mLayout.lineSize )
+ {
+ //
+ // We have to redraw all text if a change occurs so we avoid it if
+ // possible.
+ //
+ return( false );
+ }
+
+ mLayout.lineSize = lineSize;
+ setLayout( mLayout );
+ return( true );
+}
+
+
+void CHexBuffer::setNonPrintChar( QChar nonPrintChar )
+{
+ mFontInfo.nonPrintChar = nonPrintChar;
+}
+
+
+void CHexBuffer::setShowCursor( bool showCursor )
+{
+ mShowCursor = showCursor;
+}
+
+
+void CHexBuffer::setDisableCursor( bool disableCursor )
+{
+ mDisableCursor = disableCursor;
+}
+
+
+void CHexBuffer::setCursorShapeModifier( bool alwaysBlock, bool thickInsert )
+{
+ mCursor.setShapeModifier( alwaysBlock, thickInsert );
+ setEditMode( mEditMode );
+}
+
+void CHexBuffer::setEditMode( EEditMode editMode, bool alwaysBlock,
+ bool thickInsert )
+{
+ mCursor.setShapeModifier( alwaysBlock, thickInsert );
+ setEditMode( editMode );
+}
+
+void CHexBuffer::setEditMode( EEditMode editMode )
+{
+ mEditMode = editMode;
+ if( mEditMode == EditInsert )
+ {
+ if( mActiveEditor == edit_primary )
+ {
+ mCursor.setShape( SCursorSpec::thin, SCursorSpec::frame, mUnitWidth,
+ mNumCell );
+ }
+ else
+ {
+ mCursor.setShape( SCursorSpec::frame, SCursorSpec::thin, mUnitWidth,
+ mNumCell );
+ }
+
+ }
+ else
+ {
+ if( mActiveEditor == edit_primary )
+ {
+ mCursor.setShape( SCursorSpec::solid, SCursorSpec::frame, mUnitWidth,
+ mNumCell );
+ }
+ else
+ {
+ mCursor.setShape( SCursorSpec::frame, SCursorSpec::solid, mUnitWidth,
+ mNumCell );
+ }
+ }
+}
+
+
+
+void CHexBuffer::setMaximumSize( uint maximumSize )
+{
+ if( maximumSize == 0 ) { maximumSize = ~0; }
+
+ mMaximumSize = maximumSize;
+ mFixedSizeMode = maximumSize == (uint)~0 ? false : true;
+ mCursor.setFixedSizeMode( mFixedSizeMode );
+
+ if( mLayout.offsetVisible == false )
+ {
+ mOffsetSize = 0;
+ mOffsetIndex = 0;
+ printOffset = &CHexBuffer::printDummyOffset;
+ }
+ else
+ {
+ if( mLayout.offsetMode == SDisplayLayout::decimal )
+ {
+ printOffset = &CHexBuffer::printDecimalOffset;
+ for( mOffsetSize=0; maximumSize > 0; mOffsetSize += 1 )
+ {
+ maximumSize = maximumSize / 10;
+ }
+ mOffsetIndex = 10 - mOffsetSize;
+ }
+ else if( mLayout.offsetMode == SDisplayLayout::hexadecimal )
+ {
+ if( mLayout.offsetUpperCase == true )
+ {
+ printOffset = &CHexBuffer::printHexadecimalBigOffset;
+ }
+ else
+ {
+ printOffset = &CHexBuffer::printHexadecimalSmallOffset;
+ }
+ for( mOffsetSize=0; maximumSize > 0; mOffsetSize += 1 )
+ {
+ maximumSize = maximumSize / 16;
+ }
+ if( mOffsetSize > 4 ) { mOffsetSize += 1; } // Space for the ':' sign
+ mOffsetIndex = 9 - mOffsetSize;
+ }
+ else
+ {
+ mLayout.offsetVisible = false;
+ mOffsetSize = 0;
+ mOffsetIndex = 0;
+ printOffset = &CHexBuffer::printDummyOffset;
+ }
+ }
+}
+
+
+void CHexBuffer::setDocumentSize( uint size )
+{
+ if( size > mMaximumSize ) { size = mMaximumSize; }
+ mDocumentSize = size;
+ mCursor.setDocumentSize( size );
+ updateBookmarkMap(true);
+}
+
+
+void CHexBuffer::setUndoLevel( uint level )
+{
+ if( level < 10 ) { level = 10; }
+
+ if( level >= mUndoLimit )
+ {
+ mUndoLimit = level;
+ return;
+ }
+ else
+ {
+ //
+ // The maximum size decreases. If the list is larger than the the new
+ // limit, then reduce the list size starting with the oldest elements.
+ //
+ mUndoLimit = level;
+ while( mUndoList.count() >= mUndoLimit )
+ {
+ mUndoList.removeFirst();
+ mUndoIndex -= (mUndoIndex > 0 ? 1 : 0);
+ }
+ }
+}
+
+
+void CHexBuffer::setSoundState( bool inputSound, bool fatalSound )
+{
+ mInputErrorSound = inputSound;
+ mFatalErrorSound = fatalSound;
+}
+
+
+void CHexBuffer::setBookmarkVisibility( bool showInColumn, bool showInEditor )
+{
+ mShowBookmarkInOffsetColumn = showInColumn;
+ mShowBookmarkInEditor = showInEditor;
+}
+
+int CHexBuffer::writeFile( QFile &file, CProgress &p )
+{
+ uint offset = 0;
+ uint remaining = documentSize();
+
+ do
+ {
+ const uint blockSize = QMIN( 131072 /* == 1024 * 128 */ , remaining );
+ const int writeSize = file.writeBlock( data() + offset, blockSize );
+ if( writeSize == -1 )
+ {
+ p.finish();
+ return( Err_ReadFailed );
+ }
+ offset += blockSize;
+ remaining -= blockSize;
+
+ if( p.expired() == true )
+ {
+ int errCode = p.step( (float)offset/(float)documentSize() );
+ if( errCode == Err_Stop && remaining > 0 )
+ {
+ p.finish();
+ return( Err_Success );
+ }
+ }
+ }
+ while( remaining > 0 );
+
+ p.finish();
+ mDocumentModified = false;
+ registerDiskModifyTime( file );
+
+ return( Err_Success );
+}
+
+
+int CHexBuffer::readFile( QFile &file, const QString &url, CProgress &p )
+{
+ if( resize( file.size() + 100 ) == false )
+ {
+ p.finish();
+ return( Err_NoMemory );
+ }
+
+ if( file.size() > 0 )
+ {
+ mLoadingData = true;
+ uint offset = 0;
+ uint remaining = file.size();
+ while( remaining > 0 )
+ {
+ const uint blockSize = QMIN( 131072 /* == 1024 * 128 */ , remaining );
+ const int readSize = file.readBlock( data() + offset, blockSize );
+ if( readSize == -1 )
+ {
+ p.finish();
+ mLoadingData = false;
+ return( Err_ReadFailed );
+ }
+ for( uint i=0; i<blockSize; i++)
+ {
+ data()[offset+i] = mEncode[ (unsigned char) data()[offset+i] ];
+ }
+
+ offset += blockSize;
+ remaining -= blockSize;
+
+ if( p.expired() == true )
+ {
+ int errCode = p.step( (float)offset/(float)file.size() );
+ if( errCode == Err_Stop && remaining > 0 )
+ {
+ p.finish();
+ return( Err_OperationAborted );
+ }
+ }
+ }
+ mLoadingData = false;
+ }
+
+ p.finish();
+
+ mDocumentModified = false;
+ setDocumentSize( file.size() );
+ registerDiskModifyTime( file );
+ setUrl( url );
+ computeNumLines();
+ mSelect.reset();
+ mMark.reset();
+ mUndoList.clear();
+ mUndoIndex = 0;
+
+ return( Err_Success );
+}
+
+
+int CHexBuffer::insertFile( QFile &file, CProgress &p )
+{
+ if( file.size() == 0 )
+ {
+ p.finish();
+ return( Err_Success );
+ }
+
+ QByteArray array( file.size() );
+ if( array.isNull() == true )
+ {
+ p.finish();
+ return( Err_NoMemory );
+ }
+
+ uint offset = 0;
+ uint remaining = file.size();
+ while( remaining > 0 )
+ {
+ const uint blockSize = QMIN( 131072 /* == 1024 * 128 */ , remaining );
+ const int readSize = file.readBlock( array.data() + offset, blockSize );
+ if( readSize == -1 )
+ {
+ p.finish();
+ return( Err_ReadFailed );
+ }
+ for( uint i=0; i<blockSize; i++)
+ {
+ array[offset+i] = mEncode[ (unsigned char) array[offset+i] ];
+ }
+
+ offset += blockSize;
+ remaining -= blockSize;
+
+ if( p.expired() == true )
+ {
+ int errCode = p.step( (float)offset/(float)file.size() );
+ if( errCode == Err_Stop && remaining > 0 )
+ {
+ p.finish();
+ return( Err_OperationAborted );
+ }
+ }
+ }
+
+ p.finish();
+
+ int errCode = inputAtCursor( array, 0 );
+ return( errCode );
+}
+
+
+int CHexBuffer::newFile( const QString &url )
+{
+ if( resize( 100 ) == 0 )
+ {
+ return( Err_NoMemory );
+ }
+
+ mDocumentModified = false;
+ setDocumentSize( 0 );
+ setUrl( url );
+ computeNumLines();
+ mSelect.reset();
+
+ return( Err_Success );
+}
+
+
+void CHexBuffer::closeFile( void )
+{
+ resize(0);
+ computeNumLines();
+
+ mUndoList.clear();
+ mUndoIndex = 0;
+
+ setDocumentSize(0);
+ mDocumentModified = false;
+
+ QString emptyUrl;
+ setUrl( emptyUrl );
+
+ mSelect.reset();
+ mMark.reset();
+
+ removeBookmark(-1); // Negative index - All bookmarks
+}
+
+
+void CHexBuffer::registerDiskModifyTime( const QFile &file )
+{
+ QFileInfo fileInfo( file );
+ mDiskModifyTime = fileInfo.lastModified();
+}
+
+
+
+void CHexBuffer::setFont( const SDisplayFontInfo &fontInfo )
+{
+ mFontInfo = fontInfo;
+ QFontMetrics fm( mFontInfo.font );
+ mFontHeight = fm.height();
+ mFontAscent = fm.ascent();
+ computeLineWidth();
+
+ for( int i=0; i < 256; i++ )
+ {
+ mCharValid[i] = QChar(i).isPrint();
+ }
+
+ /*
+ QFontInfo info( mFontInfo.font );
+ puts("CHexBuffer mCharValid broken");
+
+ KCharset charset( info.charSet() );
+ for( int i=0; i < 256; i++ )
+ {
+ mCharValid[i] = charset.printable(i);
+ }
+ */
+}
+
+
+int CHexBuffer::setEncoding( CConversion::EMode mode, CProgress &p )
+{
+ int errCode = mEncode.convert( *this, mode, p );
+ if( errCode == Err_Success )
+ {
+ //
+ // The cursor stores the byte it is "covering", so this information
+ // must be updated.
+ //
+ cursorCompute();
+ }
+
+ return( errCode );
+}
+
+
+
+
+void CHexBuffer::computeLineWidth( void )
+{
+ QFontMetrics fm( mFontInfo.font );
+ mUnitWidth = fm.width( "M" );
+
+ if( mLayout.primaryMode == SDisplayLayout::textOnly )
+ {
+ mSplitWidth = 0;
+ }
+ else if( mLayout.columnCharSpace == true )
+ {
+ mSplitWidth = mUnitWidth;
+ }
+ else
+ {
+ mSplitWidth = mLayout.columnSpacing;
+ }
+
+ setMaximumSize( mMaximumSize );
+
+ if( mLayout.primaryMode == SDisplayLayout::hexadecimal )
+ {
+ mNumCell = 2;
+ mCursor.setCellWeight( 4 );
+ if( mLayout.primaryUpperCase == true )
+ {
+ printCell = &CHexBuffer::printHexadecimalBigCell;
+ inputCell = &CHexBuffer::inputHexadecimal;
+ }
+ else
+ {
+ printCell = &CHexBuffer::printHexadecimalSmallCell;
+ inputCell = &CHexBuffer::inputHexadecimal;
+ }
+ }
+ else if( mLayout.primaryMode == SDisplayLayout::decimal )
+ {
+ mNumCell = 3;
+ printCell = &CHexBuffer::printDecimalCell;
+ inputCell = &CHexBuffer::inputDecimal;
+ mCursor.setCellWeight( 3 );
+ }
+ else if( mLayout.primaryMode == SDisplayLayout::octal )
+ {
+ mNumCell = 3;
+ printCell = &CHexBuffer::printOctalCell;
+ inputCell = &CHexBuffer::inputOctal;
+ mCursor.setCellWeight( 3 );
+ }
+ else if( mLayout.primaryMode == SDisplayLayout::binary )
+ {
+ mNumCell = 8;
+ printCell = &CHexBuffer::printBinaryCell;
+ inputCell = &CHexBuffer::inputBinary;
+ mCursor.setCellWeight( 1 );
+ }
+ else if( mLayout.primaryMode == SDisplayLayout::textOnly )
+ {
+ mNumCell = 1;
+ printCell = &CHexBuffer::printAsciiCell;
+ inputCell = &CHexBuffer::inputAscii;
+ mCursor.setCellWeight( 8 );
+ }
+ else
+ {
+ mNumCell = 2;
+ mLayout.primaryMode = SDisplayLayout::hexadecimal;
+ mLayout.primaryUpperCase = false;
+ printCell = &CHexBuffer::printHexadecimalSmallCell;
+ inputCell = &CHexBuffer::inputHexadecimal;
+ mCursor.setCellWeight( 4 );
+ }
+
+ //
+ // 'mPrimaryWidth' is the number of pixels that are needed to display a
+ // line in the primary field.
+ //
+ mPrimaryWidth = mLayout.lineSize * mNumCell * mUnitWidth;
+
+ if( mLayout.columnSpacing != 0 )
+ {
+ int numSplit = mLayout.lineSize / mLayout.columnSize;
+ numSplit -= mLayout.lineSize % mLayout.columnSize == 0 ? 1 : 0;
+ mPrimaryWidth += numSplit * mSplitWidth;
+ }
+
+ //
+ // 'mSecondaryWidth' is the number of pixels that are needed to display a
+ // line in the secondary field (there are no spaces).
+ //
+ if( mLayout.secondaryMode == SDisplayLayout::hide )
+ {
+ mSecondaryWidth = 0;
+ }
+ else
+ {
+ mSecondaryWidth = mLayout.lineSize * mUnitWidth;
+ }
+
+ //
+ // 'mLineWidth' is the total number of pixels required to display
+ // offset data, separators, primary and secondary data on a line.
+ //
+ mLineWidth = mPrimaryWidth + mSecondaryWidth + mOffsetSize * mUnitWidth;
+
+ //
+ // The 'mFixedWidth' is the number of pixels of the width that stays the
+ // same regardless of how many characters that are displayed.
+ // This entity consists of the edge margins, the inner margins and the
+ // separators.
+ //
+ mFixedWidth = mOffsetSize * mUnitWidth;
+
+ //
+ // The edge margin is always present in both ends.
+ //
+ mLineWidth += mLayout.edgeMarginWidth * 2;
+ mFixedWidth += mLayout.edgeMarginWidth * 2;
+
+ //
+ // 'mTextStart1' is the number of pixels from the left edge where the
+ // primary field starts.
+ //
+ mTextStart1 = mLayout.edgeMarginWidth;
+ if( mLayout.offsetVisible == true )
+ {
+ int width;
+ if( mLayout.leftSeparatorWidth > 0 )
+ {
+ width = mLayout.separatorMarginWidth * 2 + mLayout.leftSeparatorWidth;
+ }
+ else
+ {
+ width = (mLayout.separatorMarginWidth * 3) / 2;
+ }
+
+ mLineWidth += width;
+ mFixedWidth += width;
+ mTextStart1 += width + mOffsetSize * mUnitWidth;
+ }
+
+ //
+ // 'mTextStart2' is the number of pixels from the left edge where the
+ // secondary fields start.
+ //
+ mTextStart2 = mTextStart1;
+ if( mLayout.secondaryMode != SDisplayLayout::hide )
+ {
+ int width;
+ if( mLayout.rightSeparatorWidth > 0 )
+ {
+ width = mLayout.separatorMarginWidth * 2 + mLayout.rightSeparatorWidth;
+ }
+ else
+ {
+ width = (mLayout.separatorMarginWidth * 3) / 2;
+ }
+
+ mLineWidth += width;
+ mFixedWidth += width;
+ mTextStart2 += width + mPrimaryWidth;
+ }
+
+ setEditMode( mEditMode );
+ computeNumLines();
+}
+
+
+void CHexBuffer::computeNumLines( void )
+{
+ if( mLayout.lineSize == 0 )
+ {
+ mNumLines = 1;
+ }
+ else
+ {
+ uint s = mFixedSizeMode == true ? mMaximumSize : documentSize() + 1;
+ mNumLines = s / mLayout.lineSize + (s % mLayout.lineSize ? 1 : 0);
+ }
+}
+
+
+
+void CHexBuffer::drawSelection( QPainter &paint, QColor &color, uint start,
+ uint stop, int sx )
+{
+ if( start >= stop ) { return; }
+ uint width = stop - start;
+
+ uint addStart, addWidth;
+ addStart = (start / mLayout.columnSize) * mSplitWidth;
+ if( width == 0 )
+ {
+ addWidth = 0;
+ }
+ else
+ {
+ uint g = mLayout.columnSize;
+ addWidth = (((start % g) + width - 1) / g) * mSplitWidth;
+ }
+
+ int offset = mTextStart1 - sx;
+ paint.fillRect( offset + start * mNumCell * mUnitWidth + addStart,
+ 0, width * mNumCell * mUnitWidth + addWidth,
+ mFontHeight, color );
+
+ if( mLayout.secondaryMode != SDisplayLayout::hide )
+ {
+ offset = mTextStart2 - sx;
+ paint.fillRect( offset + start * mUnitWidth,
+ 0, width * mUnitWidth,
+ mFontHeight, color );
+ }
+}
+
+
+
+
+
+void CHexBuffer::drawText( QPainter &paint, uint line, int sx, int x1, int x2 )
+{
+ uint fileOffset = line * mLayout.lineSize;
+ if( documentPresent() == false || mLoadingData == true )
+ {
+ paint.fillRect( x1, 0, x2-x1, lineHeight(), mColor.inactiveBg );
+ return;
+ }
+
+ bool outsideText;
+ if( size() == 0 || fileOffset > documentSize() || fileOffset >= mMaximumSize)
+ {
+ outsideText = true;
+ }
+ else
+ {
+ outsideText = false;
+ }
+
+ if( (line+1) % 2 || outsideText == true )
+ {
+ paint.fillRect( x1, 0, x2-x1, lineHeight(), mColor.textBg );
+ }
+ else
+ {
+ paint.fillRect( x1, 0, x2-x1, lineHeight(), mColor.secondTextBg );
+ }
+ if( mLayout.horzGridWidth > 0 && outsideText == false )
+ {
+ paint.setPen( mColor.gridFg );
+ paint.drawLine( x1, mFontHeight, x2, mFontHeight );
+ }
+
+ if( mSelect.inside( fileOffset, mLayout.lineSize ) == true )
+ {
+ uint start = mSelect.start( fileOffset );
+ uint stop = mSelect.stop( fileOffset, mLayout.lineSize );
+ drawSelection( paint, mColor.selectBg, start, stop, sx );
+ }
+
+ //
+ // A marked area will be displayed "above" a selcted area (given
+ // the mark background color is different)
+ //
+ if( mMark.inside( fileOffset, mLayout.lineSize ) == true )
+ {
+ uint start = mMark.start( fileOffset );
+ uint stop = mMark.stop( fileOffset, mLayout.lineSize );
+ drawSelection( paint, mColor.markBg, start, stop, sx );
+ }
+
+ uint dataSize;
+ unsigned char *fileData;
+ if( outsideText == true )
+ {
+ if( size() == 0 )
+ {
+ return;
+ }
+ dataSize = 0;
+ fileData = 0;
+ }
+ else
+ {
+ dataSize = documentSize() - fileOffset;
+ if( dataSize > mLayout.lineSize ) { dataSize = mLayout.lineSize; }
+ fileData = (unsigned char*)&(data()[ fileOffset ]);
+ }
+
+ //
+ // Compute the offset area size. We postpose the actual drawing
+ // until we have drawn any bookmark indicators in the editor areas.
+ // because we may want to draw an indicator in the offset area as well.
+ //
+ int offset = mLayout.edgeMarginWidth - sx;
+ if( mLayout.offsetVisible == true )
+ {
+ offset += mOffsetSize * mUnitWidth;
+ if( mLayout.leftSeparatorWidth > 0 )
+ {
+ offset += mLayout.leftSeparatorWidth + mLayout.separatorMarginWidth*2;
+ }
+ else
+ {
+ offset += (mLayout.separatorMarginWidth * 3) / 2;
+ }
+ }
+
+
+ #if 0
+ int offset = mLayout.edgeMarginWidth - sx;
+ if( mLayout.offsetVisible == true )
+ {
+ int s0 = mOffsetSize * mUnitWidth;
+ int s1 = s0 + mLayout.separatorMarginWidth + mLayout.edgeMarginWidth - sx;
+ if( x1 < s1 && x2 > 0 )
+ {
+ if( outsideText == true )
+ {
+ paint.fillRect( 0, 0, s1, lineHeight(), mColor.offsetBg );
+ }
+ else
+ {
+ //
+ // I want to display the grid here so I cant use lineHeight()
+ //
+ paint.fillRect( 0, 0, s1, mFontHeight, mColor.offsetBg );
+ }
+ }
+
+ if( x1 < offset + s0 && x2 >= offset && fileData != 0 )
+ {
+ paint.setPen( mColor.offsetFg );
+ THIS_FPTR(printOffset)( mPrintBuf, fileOffset );
+ // ## paint.drawText(offset,mFontAscent,&mPrintBuf[mOffsetIndex],
+ // mOffsetSize);
+ paint.drawText( offset, mFontAscent,
+ QString::fromLocal8Bit(&mPrintBuf[mOffsetIndex]),
+ mOffsetSize );
+ }
+ offset += s0;
+
+ if( mLayout.leftSeparatorWidth > 0 )
+ {
+ offset += mLayout.separatorMarginWidth;
+
+ int s2 = mLayout.leftSeparatorWidth + mLayout.separatorMarginWidth;
+ if( x1 < offset + s2 && x2 >= offset )
+ {
+ QPen pen( mColor.leftSeparatorFg, mLayout.leftSeparatorWidth );
+ paint.setPen( pen );
+ int center = offset + mLayout.leftSeparatorWidth/2;
+ paint.drawLine( center, 0, center, lineHeight() );
+ }
+ offset += s2;
+ }
+ else
+ {
+ offset += (mLayout.separatorMarginWidth * 3) / 2;
+ }
+ }
+ #endif
+
+
+ //
+ // Draw the primary area
+ //
+ int localOffset = offset;
+ for( uint i = 0; i < dataSize; i++ )
+ {
+ int s = mNumCell * mUnitWidth +
+ ((i+1) % mLayout.columnSize == 0) * mSplitWidth;
+ if( x1 < localOffset + s && x2 >= localOffset )
+ {
+ int flag = THIS_FPTR(printCell)( mPrintBuf, fileData[i] );
+ if( mSelect.inside( fileOffset+i ) )
+ {
+ paint.setPen( mColor.selectFg );
+ }
+ else if( mMark.inside( fileOffset+i ) )
+ {
+ paint.setPen( mColor.markFg );
+ }
+ else
+ {
+ paint.setPen( flag == 0 ? foregroundColor( i ) : mColor.nonPrintFg );
+ }
+
+ // ## paint.drawText( localOffset, mFontAscent, mPrintBuf, mNumCell );
+ paint.drawText( localOffset, mFontAscent,
+ QString::fromLocal8Bit(mPrintBuf), mNumCell );
+ }
+ localOffset += s;
+
+ if( mLayout.vertGridWidth > 0 && i+1 < dataSize )
+ {
+ if( (i+1) % mLayout.columnSize == 0 )
+ {
+ paint.setPen( mColor.gridFg );
+ int x = localOffset - (mSplitWidth+1) / 2;
+ paint.drawLine( x, 0, x, mFontHeight );
+ }
+ }
+ }
+
+ //
+ // Draw the secondary area
+ //
+ offset += mPrimaryWidth;
+ if( mLayout.secondaryMode != SDisplayLayout::hide )
+ {
+ if( mLayout.rightSeparatorWidth > 0 )
+ {
+ offset += mLayout.separatorMarginWidth;
+ int s = mLayout.separatorMarginWidth + mLayout.rightSeparatorWidth;
+ if( x1 < offset + s && x2 >= offset )
+ {
+ QPen pen( mColor.rightSeparatorFg, mLayout.rightSeparatorWidth );
+ paint.setPen( pen );
+ int center = offset + mLayout.rightSeparatorWidth/2;
+ paint.drawLine( center, 0, center, lineHeight() );
+ }
+ offset += s;
+ }
+ else
+ {
+ offset += (mLayout.separatorMarginWidth * 3) / 2;
+ }
+
+ int s = mUnitWidth;
+ for( uint i = 0; i < dataSize; i++ )
+ {
+ if( x1 < offset + s && x2 >= offset )
+ {
+ int flag = printAsciiCell( mPrintBuf, fileData[i] );
+ if( mSelect.inside( fileOffset+i ) )
+ {
+ paint.setPen( mColor.selectFg );
+ }
+ else if( mMark.inside( fileOffset+i ) )
+ {
+ paint.setPen( mColor.markFg );
+ }
+ else
+ {
+ paint.setPen( flag == 0 ? mColor.secondaryFg : mColor.nonPrintFg );
+ }
+
+ // ## paint.drawText( offset, mFontAscent, mPrintBuf, 1 );
+ paint.drawText( offset, mFontAscent,
+ QString::fromLocal8Bit(mPrintBuf), 1 );
+ }
+ offset += s;
+ }
+ }
+
+ //
+ // Draw the bookmark identifiers on this line (if any). We use the
+ // bitmask to minimize the number of times we try to draw the bookmarks.
+ //
+ int bookmarkPosition = 0;
+ if( mBookmarkMap.testBit(fileOffset/200) ||
+ mBookmarkMap.testBit((fileOffset+mLayout.lineSize-1)/200 ) )
+ {
+ // Returns a bookmark postion state
+ bookmarkPosition = drawBookmarks( paint, line, sx );
+ }
+
+ //
+ // Draw the offset area. We have delayed the drawing until now because
+ // it is possible to draw a bookmark indicator in this area.
+ //
+ offset = mLayout.edgeMarginWidth - sx;
+ if( mLayout.offsetVisible == true )
+ {
+ int s0 = mOffsetSize * mUnitWidth;
+ int s1 = s0 + mLayout.separatorMarginWidth + mLayout.edgeMarginWidth - sx;
+ if( x1 < s1 && x2 > 0 )
+ {
+ QColor bg = mShowBookmarkInOffsetColumn &&
+ (bookmarkPosition & BookmarkOnLine) ?
+ mColor.bookmarkBg : mColor.offsetBg;
+ if( outsideText == true )
+ {
+ paint.fillRect( 0, 0, s1, lineHeight(), bg );
+ }
+ else
+ {
+ //
+ // I want to display the grid here so I cant use lineHeight()
+ //
+ paint.fillRect( 0, 0, s1, mFontHeight, bg );
+ }
+ }
+
+ if( x1 < offset + s0 && x2 >= offset && fileData != 0 )
+ {
+ paint.setPen( mShowBookmarkInOffsetColumn &&
+ bookmarkPosition & BookmarkOnLine ?
+ mColor.bookmarkFg : mColor.offsetFg );
+ THIS_FPTR(printOffset)( mPrintBuf, fileOffset );
+ // ## paint.drawText(offset,mFontAscent,&mPrintBuf[mOffsetIndex],
+ // mOffsetSize);
+ paint.drawText( offset, mFontAscent,
+ QString::fromLocal8Bit(&mPrintBuf[mOffsetIndex]),
+ mOffsetSize );
+ }
+
+ offset += s0;
+
+ if( mLayout.leftSeparatorWidth > 0 )
+ {
+ offset += mLayout.separatorMarginWidth;
+
+ int s2 = mLayout.leftSeparatorWidth + mLayout.separatorMarginWidth;
+ if( x1 < offset + s2 && x2 >= offset )
+ {
+ QPen pen( mColor.leftSeparatorFg, mLayout.leftSeparatorWidth );
+ paint.setPen( pen );
+ int center = offset + mLayout.leftSeparatorWidth/2;
+ paint.drawLine( center, 0, center, lineHeight() );
+ }
+ }
+ }
+
+
+ //
+ // If the cursors are located on the line we have drawn we redraw
+ // them unless they have been disabled.
+ //
+ if( mDisableCursor == false )
+ {
+ if( mCursor.curr.inside( fileOffset, fileOffset + mLayout.lineSize ) )
+ {
+ drawCursor( paint, line, sx, bookmarkPosition & BookmarkOnCursor );
+ }
+ }
+
+}
+
+
+
+
+void CHexBuffer::drawText( QPainter &paint, uint line, int x1, int x2, int y,
+ bool useBlackWhite )
+{
+ uint fileOffset = line * mLayout.lineSize;
+
+ bool outsideText;
+ if( size() == 0 || fileOffset > documentSize() || fileOffset >= mMaximumSize)
+ {
+ outsideText = true;
+ }
+ else
+ {
+ outsideText = false;
+ }
+
+ if( (line+1) % 2 || outsideText == true )
+ {
+ paint.fillRect( x1, y, x2, lineHeight(),
+ useBlackWhite == true ? Qt::white : mColor.textBg );
+ }
+ else
+ {
+ paint.fillRect( x1, y, x2, lineHeight(),
+ useBlackWhite == true ? Qt::white : mColor.secondTextBg );
+ }
+
+ if( mLayout.horzGridWidth > 0 && outsideText == false )
+ {
+ QPen pen( useBlackWhite == true ? Qt::black : mColor.gridFg,
+ mLayout.horzGridWidth );
+ paint.setPen( pen );
+ paint.drawLine( x1, y+mFontHeight, x2+x1, y+mFontHeight );
+ }
+
+ uint dataSize;
+ unsigned char *fileData;
+ if( outsideText == true )
+ {
+ if( size() == 0 )
+ {
+ return;
+ }
+ dataSize = 0;
+ fileData = 0;
+ }
+ else
+ {
+ dataSize = documentSize() - fileOffset;
+ if( dataSize > mLayout.lineSize ) { dataSize = mLayout.lineSize; }
+ fileData = (unsigned char*)&(data()[ fileOffset ]);
+ }
+
+ int offset = mLayout.edgeMarginWidth + x1;
+
+ if( mLayout.offsetVisible == true )
+ {
+ int s1 = mOffsetSize * mUnitWidth;
+ if( fileData != 0 )
+ {
+ paint.setPen( useBlackWhite == true ? Qt::black : mColor.offsetFg );
+ THIS_FPTR(printOffset)( mPrintBuf, fileOffset );
+ // ## paint.drawText( offset, mFontAscent+y, &mPrintBuf[mOffsetIndex],
+ // mOffsetSize );
+ paint.drawText( offset, mFontAscent+y,
+ QString::fromLocal8Bit(&mPrintBuf[mOffsetIndex]),
+ mOffsetSize );
+ }
+ offset += s1;
+
+ if( mLayout.leftSeparatorWidth > 0 )
+ {
+ offset += mLayout.separatorMarginWidth;
+
+ int s2 = mLayout.leftSeparatorWidth + mLayout.separatorMarginWidth;
+ QPen pen( useBlackWhite == true ? Qt::black : mColor.leftSeparatorFg,
+ mLayout.leftSeparatorWidth );
+ paint.setPen( pen );
+ int center = offset + mLayout.leftSeparatorWidth/2;
+ paint.drawLine( center, y, center, mFontHeight+y );
+ offset += s2;
+ }
+ else
+ {
+ offset += (mLayout.separatorMarginWidth * 3) / 2;
+ }
+ }
+
+ int localOffset = offset;
+ for( uint i = 0; i < dataSize; i++ )
+ {
+ int s = mNumCell * mUnitWidth +
+ ((i+1) % mLayout.columnSize == 0) * mSplitWidth;
+ int flag = THIS_FPTR(printCell)( mPrintBuf, fileData[i] );
+ if( useBlackWhite == true )
+ {
+ paint.setPen( Qt::black );
+ }
+ else
+ {
+ paint.setPen( flag == 0 ? foregroundColor( i ) : mColor.nonPrintFg );
+ }
+ // ## paint.drawText( localOffset, mFontAscent+y, mPrintBuf, mNumCell );
+ paint.drawText( localOffset, mFontAscent+y,
+ QString::fromLocal8Bit(mPrintBuf), mNumCell );
+ localOffset += s;
+
+ if( mLayout.vertGridWidth > 0 && i+1 < dataSize )
+ {
+ if( (i+1) % mLayout.columnSize == 0 )
+ {
+ QPen pen( useBlackWhite == true ? Qt::black : mColor.gridFg,
+ mLayout.vertGridWidth );
+ paint.setPen( pen );
+ int x = localOffset - (mSplitWidth+1) / 2;
+ paint.drawLine( x, y, x, y+mFontHeight );
+ }
+ }
+
+ }
+
+ offset += mPrimaryWidth;
+
+ if( mLayout.secondaryMode != SDisplayLayout::hide )
+ {
+ if( mLayout.rightSeparatorWidth > 0 )
+ {
+ offset += mLayout.separatorMarginWidth;
+ int s = mLayout.separatorMarginWidth + mLayout.rightSeparatorWidth;
+ QPen pen( useBlackWhite == true ? Qt::black : mColor.rightSeparatorFg,
+ mLayout.rightSeparatorWidth );
+ paint.setPen( pen );
+ int center = offset + mLayout.rightSeparatorWidth/2;
+ paint.drawLine( center, y, center, mFontHeight+y );
+ offset += s;
+ }
+ else
+ {
+ offset += (mLayout.separatorMarginWidth * 3) / 2;
+ }
+
+
+ int s = mUnitWidth;
+ for( uint i = 0; i < dataSize; i++ )
+ {
+ int flag = printAsciiCell( mPrintBuf, fileData[i] );
+ if( useBlackWhite == true )
+ {
+ paint.setPen( Qt::black );
+ }
+ else
+ {
+ paint.setPen( flag == 0 ? mColor.secondaryFg : mColor.nonPrintFg );
+ }
+ // ## paint.drawText( offset, mFontAscent+y, mPrintBuf, 1 );
+ paint.drawText( offset, mFontAscent+y,
+ QString::fromLocal8Bit(mPrintBuf), 1 );
+ offset += s;
+ }
+ }
+
+}
+
+
+int CHexBuffer::headerHeight( QPainter &paint )
+{
+ QFont font( paint.font() );
+ paint.setFont( KGlobalSettings::generalFont() );
+ const QFontMetrics &fm = paint.fontMetrics();
+
+ int height = fm.height();
+ paint.setFont( font );
+ return( height );
+}
+
+int CHexBuffer::headerMargin( QPainter &paint )
+{
+ QFont font( paint.font() );
+ paint.setFont( KGlobalSettings::generalFont() );
+ const QFontMetrics &fm = paint.fontMetrics();
+
+ int margin = fm.height() / 2;
+ paint.setFont( font );
+ return( margin );
+}
+
+
+void CHexBuffer::drawHeader( QPainter &paint, int sx, int width, int y,
+ bool isFooter, const SPageHeader &header,
+ const SPagePosition &position )
+{
+ QFont font( paint.font() );
+ paint.setFont( KGlobalSettings::generalFont() );
+ const QFontMetrics &fm = paint.fontMetrics();
+
+ paint.fillRect( sx, y, width, fm.height(), Qt::white );
+ paint.setPen( Qt::black );
+ if( header.line == SPageHeader::SingleLine )
+ {
+ if( isFooter == false )
+ {
+ paint.drawLine( sx, y+fm.height(), sx+width, y+fm.height() );
+ }
+ else
+ {
+ paint.drawLine( sx, y, sx+width, y );
+ }
+ }
+ else if( header.line == SPageHeader::Rectangle )
+ {
+ paint.drawRect( sx, y, width, fm.height() );
+ }
+
+ int pos[3] =
+ {
+ QPainter::AlignLeft, QPainter::AlignHCenter, QPainter::AlignRight
+ };
+
+ QString msg;
+ for( int i=0; i<3; i++ )
+ {
+ if( header.pos[i] == SPageHeader::DateTime )
+ {
+ QDateTime datetime;
+ datetime.setTime_t( position.now );
+ msg = KGlobal::locale()->formatDateTime(datetime);
+ }
+ else if( header.pos[i] == SPageHeader::PageNumber )
+ {
+ msg = i18n("Page %1 of %2")
+ .arg(KGlobal::locale()->formatNumber(position.curPage, 0))
+ .arg(KGlobal::locale()->formatNumber(position.maxPage, 0));
+ }
+ else if( header.pos[i] == SPageHeader::FileName )
+ {
+ msg = mUrl;
+ }
+ else
+ {
+ continue;
+ }
+
+ if( 0 && pos[i] == QPainter::AlignRight )
+ {
+ //const QFontMetrics &f = QFontMetrics( KGlobalSettings::generalFont() );
+ //QRect r = paint.boundingRect(sx, y, width, fm.height(), pos[i], msg );
+ //printf("R: %d, %d, %d, %d\n", r.x(), r.y(), r.width(), r.height() );
+
+ int x = sx + width - /*r.width();*/ fm.width(msg);
+ paint.drawText( x, y+fm.height(), msg );
+ //printf("paint at %d\n", x );
+ }
+ else
+ {
+ paint.drawText( sx, y, width, fm.height(), pos[i], msg );
+ }
+ }
+
+ //
+ // restore original font.
+ //
+ paint.setFont( font );
+}
+
+
+
+
+int CHexBuffer::drawBookmarks( QPainter &paint, uint line, int startx )
+{
+ if( documentPresent() == false || mLoadingData == true )
+ {
+ return( 0 );
+ }
+
+ uint start = line*mLayout.lineSize;
+ uint stop = start+mLayout.lineSize;
+ QColor bg = mColor.bookmarkBg;
+ QColor fg = mColor.bookmarkFg;
+
+ int bookmarkPosition = 0;
+
+ for( SCursorOffset *c=mBookmarkList.first(); c!=0; c=mBookmarkList.next() )
+ {
+ if( c->offset >= start && c->offset < stop )
+ {
+ int x = c->offset - start;
+ int x1 = mTextStart1 + x * mUnitWidth * mNumCell;
+ x1 += (x / mLayout.columnSize) * mSplitWidth;
+ int x2 = mTextStart2 + x * mUnitWidth;
+
+ bookmarkPosition |= BookmarkOnLine;
+
+ if( mShowBookmarkInEditor == false )
+ {
+ continue;
+ }
+
+ uint offset = line*mLayout.lineSize+x;
+ if( offset == mCursor.curr.offset )
+ {
+ bookmarkPosition |= BookmarkOnCursor;
+ }
+
+ if( mSelect.inside( offset ) || mMark.inside( offset ) )
+ {
+ paint.fillRect( x1-startx, 2, mUnitWidth*mNumCell, mFontHeight-4, bg );
+ if( mLayout.secondaryMode != SDisplayLayout::hide )
+ {
+ paint.fillRect( x2-startx, 2, mUnitWidth, mFontHeight-4, bg );
+ }
+ }
+ else
+ {
+ paint.fillRect( x1-startx, 1, mUnitWidth*mNumCell, mFontHeight-2, bg );
+ if( mLayout.secondaryMode != SDisplayLayout::hide )
+ {
+ paint.fillRect( x2-startx, 1, mUnitWidth, mFontHeight-2, bg );
+ }
+ }
+
+ unsigned char c = (data()[ line*mLayout.lineSize+x]);
+
+ int flag = THIS_FPTR(printCell)( mPrintBuf, c );
+ paint.setPen( flag == 0 ? fg : mColor.nonPrintFg );
+ // ## paint.drawText( x1-startx, mFontAscent, mPrintBuf, mNumCell );
+ paint.drawText( x1-startx, mFontAscent,
+ QString::fromLocal8Bit(mPrintBuf), mNumCell );
+ if( mLayout.secondaryMode != SDisplayLayout::hide )
+ {
+ flag = printAsciiCell( mPrintBuf, c );
+ paint.setPen( flag == 0 ? fg : mColor.nonPrintFg );
+ // ## paint.drawText( x2-startx, mFontAscent, mPrintBuf, 1 );
+ paint.drawText( x2-startx, mFontAscent,
+ QString::fromLocal8Bit(mPrintBuf), 1 );
+ }
+ }
+ }
+
+ return bookmarkPosition;
+}
+
+
+
+void CHexBuffer::drawCursor( QPainter &paint, uint line, int startx,
+ bool onBookmark )
+{
+ if( documentPresent() == false || mLoadingData == true )
+ {
+ return;
+ }
+
+ SCursorSpec &c = mCursor.curr;
+
+ //
+ // Draw the cursor in primary edit area.
+ //
+ QColor bg, fg;
+ bool useFg;
+ if( mMark.inside( c.offset ) == true )
+ {
+ bg = mColor.markBg;
+ fg = mSelect.inside( c.offset ) ? mColor.selectFg : mColor.markFg;
+ useFg = true;
+ }
+ else if( mSelect.inside( c.offset ) == true )
+ {
+ bg = mColor.selectBg;
+ fg = mColor.selectFg;
+ useFg = true;
+ }
+ else
+ {
+ bg = (line+1) % 2 ? mColor.textBg : mColor.secondTextBg;
+ fg = foregroundColor( c.offset % mLayout.lineSize );
+ useFg = false; // Can be true later.
+ }
+
+ QColor cbg = mColor.cursorBg;
+ QColor cfg = mColor.cursorFg;
+
+ //
+ // Fill in the general backround color
+ //
+ paint.fillRect( c.x1 - startx, 0, mUnitWidth, mFontHeight, bg );
+ if( onBookmark == true )
+ {
+ int w = mUnitWidth * (mNumCell-c.cell); // Rest of cell
+ if( useFg == true )
+ {
+ paint.fillRect( c.x1-startx, 2, w, mFontHeight-4, mColor.bookmarkBg );
+ }
+ else
+ {
+ paint.fillRect( c.x1-startx, 1, w, mFontHeight-2, mColor.bookmarkBg );
+ }
+ }
+
+ //
+ // Draw the cursor shape
+ //
+ bool transparent = false;
+ if( mActiveEditor == edit_primary )
+ {
+ if( mShowCursor == true ) // Cursor blink on
+ {
+ if( c.mPrimaryShape == SCursorSpec::thin )
+ {
+ paint.setPen( cbg );
+ int center = c.x1 - startx - 1;
+ transparent = true;
+
+ if( c.thickState == true )
+ {
+ paint.drawLine( center, 0, center, mFontHeight - 1 );
+ paint.drawLine( center+1, 0, center+1, mFontHeight - 1 );
+ }
+ else
+ {
+ paint.drawLine( center, 0, center, mFontHeight - 1 );
+ paint.drawLine( center-2, 0, center+2, 0 );
+ paint.drawLine( center-2, mFontHeight-1, center+2, mFontHeight-1 );
+ }
+ }
+ else // Solid block shape
+ {
+ paint.fillRect( c.x1 - startx, 0, mUnitWidth, mFontHeight, cbg );
+ useFg = true;
+ fg = cfg;
+ }
+ }
+ }
+ else
+ {
+ transparent = true;
+ paint.setPen( cbg );
+ paint.drawRect( c.x1 - startx, 0, mUnitWidth*mNumCell, mFontHeight );
+ }
+
+ //
+ // Draw the text on the cursor position and to the end of the cell.
+ //
+ if( c.offset < documentSize() )
+ {
+ int flag = THIS_FPTR(printCell)( mPrintBuf, (unsigned char)c.data );
+ if( onBookmark == true )
+ {
+ // Inside bookmark. Draw text with bookmark foreground.
+ paint.setPen( mColor.bookmarkFg );
+ // ## paint.drawText( c.x1-startx, mFontAscent, &mPrintBuf[c.cell],
+ // mNumCell-c.cell );
+ paint.drawText( c.x1-startx, mFontAscent,
+ QString::fromLocal8Bit(&mPrintBuf[c.cell]),
+ mNumCell-c.cell );
+ }
+
+ if( transparent == false || onBookmark == false )
+ {
+ paint.setPen( flag == 0 || useFg == true ? fg : mColor.nonPrintFg );
+ // ## paint.drawText( c.x1 - startx, mFontAscent, &mPrintBuf[c.cell], 1);
+ paint.drawText( c.x1 - startx, mFontAscent,
+ QString::fromLocal8Bit(&mPrintBuf[c.cell]), 1 );
+ }
+ }
+
+ //
+ // Draw the cursor in secodary edit area.
+ //
+ if( mLayout.secondaryMode == SDisplayLayout::hide )
+ {
+ return;
+ }
+
+
+ if( mMark.inside( c.offset ) == true )
+ {
+ bg = mColor.markBg;
+ fg = mSelect.inside( c.offset ) ? mColor.selectFg : mColor.markFg;
+ useFg = true;
+ }
+ else if( mSelect.inside( c.offset ) == true )
+ {
+ bg = mColor.selectBg;
+ fg = mColor.selectFg;
+ useFg = true;
+ }
+ else
+ {
+ bg = (line+1) % 2 ? mColor.textBg : mColor.secondTextBg;
+ fg = mColor.secondaryFg;
+ useFg = false; // Can be true later.
+ }
+
+
+
+ //
+ // Fill in the general backround color
+ //
+ if( onBookmark == true )
+ {
+ if( useFg == true )
+ {
+ paint.fillRect( c.x2-startx, 2, mUnitWidth, mFontHeight-4,
+ mColor.bookmarkBg );
+ }
+ else
+ {
+ paint.fillRect( c.x2-startx, 1, mUnitWidth, mFontHeight-2,
+ mColor.bookmarkBg );
+ }
+ }
+ else
+ {
+ paint.fillRect( c.x2 - startx, 0, mUnitWidth, mFontHeight, bg );
+ }
+
+ //
+ // Draw the cursor shape
+ //
+ transparent = false;
+ if( mActiveEditor == edit_secondary )
+ {
+ if( mShowCursor == true ) // Cursor blink on
+ {
+ if( c.mSecondaryShape == SCursorSpec::thin )
+ {
+ paint.setPen( cbg );
+ int center = c.x2 - startx - 1;
+ transparent = true;
+
+ if( c.thickState == true )
+ {
+ paint.drawLine( center, 0, center, mFontHeight - 1 );
+ paint.drawLine( center+1, 0, center+1, mFontHeight - 1 );
+ }
+ else
+ {
+ paint.drawLine( center, 0, center, mFontHeight - 1 );
+ paint.drawLine( center-2, 0, center+2, 0 );
+ paint.drawLine( center-2, mFontHeight-1, center+2, mFontHeight-1 );
+ }
+ }
+ else
+ {
+ paint.fillRect( c.x2 - startx, 0, mUnitWidth, mFontHeight, cbg );
+ useFg = true;
+ fg = cfg;
+ }
+ }
+ }
+ else
+ {
+ transparent = true;
+ paint.setPen( cbg );
+ paint.drawRect( c.x2 - startx, 0, mUnitWidth, mFontHeight );
+ }
+
+ //
+ // Draw the text on the cursor position and to the end of the cell.
+ //
+ if( c.offset < documentSize() )
+ {
+ int flag = printAsciiCell( mPrintBuf, (unsigned char)c.data );
+ if( onBookmark == true )
+ {
+ // Inside bookmark. Draw text with bookmark foreground.
+ paint.setPen( flag == 0 ? mColor.bookmarkFg : mColor.nonPrintFg );
+ // ## paint.drawText( c.x2-startx, mFontAscent, mPrintBuf, 1 );
+ paint.drawText( c.x2-startx, mFontAscent,
+ QString::fromLocal8Bit(mPrintBuf), 1 );
+ }
+ if( transparent == false || onBookmark == false )
+ {
+ paint.setPen( flag == 0 || useFg == true ? fg : mColor.nonPrintFg );
+ // ## paint.drawText( c.x2 - startx, mFontAscent, mPrintBuf, 1 );
+ paint.drawText( c.x2 - startx, mFontAscent,
+ QString::fromLocal8Bit(mPrintBuf), 1 );
+ }
+ }
+
+}
+
+
+
+
+void CHexBuffer::cursorReset( void )
+{
+ mCursor.reset();
+ cursorCompute();
+}
+
+void CHexBuffer::cursorCompute( void )
+{
+ mCursor.prev = mCursor.curr;
+
+ if( mCursor.next.offset >= documentSize() )
+ {
+ if( documentSize() == 0 )
+ {
+ mCursor.curr.offset = 0;
+ mCursor.curr.data = 0;
+ mCursor.curr.cell = 0;
+ mCursor.curr.maxCell = mNumCell;
+
+ int x = mCursor.curr.offset % mLayout.lineSize;
+ mCursor.curr.x1 = mTextStart1;
+ mCursor.curr.x1 += (x * mNumCell + mCursor.curr.cell) * mUnitWidth;
+ mCursor.curr.x1 += (x / mLayout.columnSize) * mSplitWidth;
+ mCursor.curr.x2 = mTextStart2 + x * mUnitWidth;
+ mCursor.curr.y = (mCursor.curr.offset/mLayout.lineSize) *
+ (mFontHeight+mLayout.horzGridWidth);
+ return;
+
+ }
+ if( mFixedSizeMode == true )
+ {
+ uint max = mMaximumSize - 1;
+ uint off = mCursor.curr.offset % mLayout.lineSize;
+ uint end = max % mLayout.lineSize;
+ if( off > end )
+ {
+ uint diff = off - end;
+ if( max + diff > mLayout.lineSize )
+ {
+ mCursor.next.offset = max + diff - mLayout.lineSize;
+ }
+ else
+ {
+ mCursor.next.offset = 0;
+ }
+ }
+ else
+ {
+ uint diff = end - off;
+ mCursor.next.offset = diff > max ? max : max - diff;
+ }
+ }
+ else
+ {
+ mCursor.next.offset = documentSize();
+ }
+ }
+
+ mCursor.curr.offset = mCursor.next.offset;
+ mCursor.curr.data = data()[ mCursor.curr.offset ];
+ mCursor.curr.cell = mCursor.next.cell;
+ mCursor.curr.maxCell = mNumCell;
+
+ int x = mCursor.curr.offset % mLayout.lineSize;
+
+ mCursor.curr.x1 = mTextStart1;
+ mCursor.curr.x1 += (x * mNumCell + mCursor.curr.cell) * mUnitWidth;
+ mCursor.curr.x1 += (x / mLayout.columnSize) * mSplitWidth;
+ mCursor.curr.x2 = mTextStart2 + x * mUnitWidth;
+ mCursor.curr.y = (mCursor.curr.offset/mLayout.lineSize) *
+ (mFontHeight + mLayout.horzGridWidth);
+}
+
+
+bool CHexBuffer::setCursorPosition( int x, int y, bool init, bool cellLevel )
+{
+ if( documentPresent() == false )
+ {
+ return( false );
+ }
+
+ uint line = y < 0 ? 0 : y / lineHeight();
+ uint entry = 0;
+ int bit = 7;
+
+ if( init == false )
+ {
+ if( mCursor.area() == edit_primary )
+ {
+ int start = mTextStart1;
+ if( x < start - (int)mLayout.separatorMarginWidth )
+ {
+ return( false );
+ }
+ else
+ {
+ int stop = mTextStart1 + mPrimaryWidth + mLayout.separatorMarginWidth;
+ int width = mNumCell * mUnitWidth;
+ int space = mSplitWidth;
+
+ for( int position = start, i=0; position < stop; i++ )
+ {
+ if( x <= position + width )
+ {
+ if( cellLevel == true )
+ {
+ while( bit > 0 )
+ {
+ if( x <= position + mUnitWidth )
+ {
+ break;
+ }
+ bit -= mCursor.cellWeight();
+ position += mUnitWidth;
+ }
+ }
+ break;
+ }
+ position += width + (((i+1) % mLayout.columnSize) ? 0 : space);
+ entry += 1;
+ }
+ }
+ }
+ else
+ {
+ int start = mTextStart2;
+ if( x < start - (int)mLayout.separatorMarginWidth ||
+ mLayout.secondaryMode == SDisplayLayout::hide )
+ {
+ return( false );
+ }
+ int stop = mTextStart2 + mLayout.lineSize * mUnitWidth;
+ int width = mUnitWidth * 1;
+ int space = 0;
+
+ for( int position = start; position < stop; )
+ {
+ if( x <= position + width )
+ {
+ break;
+ }
+ position += width + space;
+ entry += 1;
+ }
+ }
+ }
+ else
+ {
+ int start = mTextStart1;
+ int stop = start + mPrimaryWidth + mLayout.separatorMarginWidth;
+ if( x >= start - (int)mLayout.separatorMarginWidth && x <= stop )
+ {
+ int width = mUnitWidth * mNumCell;
+ int space = mSplitWidth;
+
+ for( int position = start, i=0; position < stop; i++ )
+ {
+ if( x <= position + width )
+ {
+ if( cellLevel == true )
+ {
+ while( bit > 0 )
+ {
+ if( x <= position + mUnitWidth )
+ {
+ break;
+ }
+ bit -= mCursor.cellWeight();
+ position += mUnitWidth;
+ }
+ }
+ break;
+ }
+ position += width + (((i+1) % mLayout.columnSize) ? 0 : space);
+ entry += 1;
+ }
+
+ mActiveEditor = edit_primary;
+ }
+ else if( mLayout.secondaryMode != SDisplayLayout::hide )
+ {
+ start = mTextStart2;
+ stop = mTextStart2 + mLayout.lineSize * mUnitWidth +
+ mLayout.edgeMarginWidth;
+ if( x >= start - (int)mLayout.separatorMarginWidth && x <= stop )
+ {
+ int width = mUnitWidth * 1;
+ int space = 0;
+
+ for( int position = start; position < stop; )
+ {
+ if( x <= position + width )
+ {
+ break;
+ }
+ position += width + space;
+ entry += 1;
+ }
+
+ mActiveEditor = edit_secondary;
+ }
+ }
+ else
+ {
+ return( false );
+ }
+ }
+
+ uint offset = line * mLayout.lineSize + entry;
+ if( offset > documentSize() )
+ {
+ offset = documentSize();
+ }
+
+ mCursor.setOffset( offset );
+ mCursor.setBit( bit < 0 ? 0 : bit );
+
+ cursorCompute();
+ if( mActiveEditor != mCursor.area() )
+ {
+ mCursor.setArea( mActiveEditor );
+ setEditMode( mEditMode );
+ }
+
+ return( true );
+}
+
+
+
+
+bool CHexBuffer::inputAtCursor( QChar c )
+{
+ if( documentPresent() == false || mInputMode.noInput() == true )
+ {
+ if( mInputMode.noInput() == true ) { inputSound(); }
+ return( false );
+ }
+
+ if( c.isPrint() == false )
+ {
+ inputSound();
+ return( false );
+ }
+
+ unsigned char dest;
+ bool insert;
+ if( mEditMode == EditReplace || mCursor.curr.cell > 0 )
+ {
+ if( mCursor.curr.offset >= documentSize() )
+ {
+ dest = 0;
+ insert = true;
+ }
+ else
+ {
+ dest = (unsigned char)data()[ mCursor.curr.offset ];
+ insert = false;
+ }
+ }
+ else
+ {
+ dest = 0;
+ insert = true;
+ }
+
+ if( insert == true && mInputMode.allowResize == false )
+ {
+ inputSound();
+ return( false );
+ }
+
+ if( mActiveEditor == edit_primary )
+ {
+ // ## if( THIS_FPTR(inputCell)( &dest, c.latin1(), mCursor.curr.cell )
+ //== false )
+ if( THIS_FPTR(inputCell)( &dest, QString(c).local8Bit()[0],
+ mCursor.curr.cell ) == false )
+ {
+ inputSound();
+ return( false );
+ }
+ }
+ else if( mActiveEditor == edit_secondary )
+ {
+ // ## if( inputAscii( &dest, c.latin1(), mCursor.curr.cell ) == false )
+ if( !inputAscii( &dest, QString(c).local8Bit()[0], mCursor.curr.cell ) )
+ {
+ inputSound();
+ return( false );
+ }
+ }
+ else
+ {
+ return( false );
+ }
+
+ recordStart( mCursor );
+ recordReplace( mCursor, insert == true ? 0 : 1, (char*)&dest, 1 );
+ cursorRight( cursorPrimaryEdit() );
+ recordEnd( mCursor );
+
+ computeNumLines();
+ return( true );
+}
+
+
+
+int CHexBuffer::inputAtCursor( const QByteArray &buf, uint oldSize )
+{
+ if( documentPresent() == false )
+ {
+ return( Err_NoActiveDocument );
+ }
+ if( buf.isNull() == true )
+ {
+ return( Err_EmptyArgument );
+ }
+
+ if( mInputMode.noInput() == true )
+ {
+ inputSound();
+ return( Err_WriteProtect );
+ }
+
+ if( mInputMode.allowResize == false )
+ {
+ inputSound();
+ return( Err_NoResize );
+ }
+
+ recordStart( mCursor );
+ recordReplace( mCursor, oldSize, (char*)&buf[0], buf.size() );
+ cursorStep( buf.size(), true, false );
+ recordEnd( mCursor );
+
+ computeNumLines();
+ return( Err_Success );
+}
+
+
+bool CHexBuffer::removeAtCursor( bool beforeCursor )
+{
+ if( documentPresent() == false )
+ {
+ return( false );
+ }
+
+ if( mInputMode.noInput() == true || mInputMode.allowResize == false )
+ {
+ inputSound();
+ return( false );
+ }
+
+
+ if( mSelect.valid() == true )
+ {
+ cutSelection();
+ return( true );
+ }
+
+
+ if( beforeCursor == true )
+ {
+ if( mCursor.curr.offset == 0 )
+ {
+ return( false );
+ }
+
+ recordStart( mCursor );
+ cursorLeft( false );
+ recordReplace( mCursor, 1, 0, 0 );
+ recordEnd( mCursor );
+
+ computeNumLines();
+ return( true );
+ }
+ else
+ {
+ if( mCursor.curr.offset + 1 > documentSize() )
+ {
+ return( false );
+ }
+
+ recordStart( mCursor );
+ recordReplace( mCursor, 1, 0, 0 );
+ recordEnd( mCursor );
+
+ computeNumLines();
+ return( true );
+ }
+}
+
+
+
+int CHexBuffer::locateRange(const SExportRange &range, uint &start, uint &stop)
+{
+ if( range.mode == SExportRange::All )
+ {
+ start = 0;
+ stop = documentSize();
+ }
+ else if( range.mode == SExportRange::Selection )
+ {
+ if( mSelect.valid() == false )
+ {
+ return( Err_NoSelection );
+ }
+ start = mSelect.curr.start;
+ stop = mSelect.curr.stop;
+ }
+ else if( range.mode == SExportRange::Range )
+ {
+ start = range.start;
+ stop = range.stop;
+ }
+ else
+ {
+ return( Err_IllegalMode );
+ }
+
+ if( start >= stop )
+ {
+ return( Err_IllegalRange );
+ }
+
+ return( Err_Success );
+}
+
+
+int CHexBuffer::exportText( const SExportText &ex, CProgress &p )
+{
+ uint start, stop;
+ int errCode = locateRange( ex.range, start, stop );
+ if( errCode != Err_Success )
+ {
+ p.finish();
+ return( errCode );
+ }
+
+ QFile file( ex.destFile );
+ if( file.open( IO_WriteOnly ) == false )
+ {
+ p.finish();
+ return( Err_OpenWriteFailed );
+ }
+
+ uint startLine = calculateLine( start );
+ if( startLine >= (uint)numLines() )
+ {
+ startLine = numLines() == 0 ? 0 : numLines() - 1;
+ }
+
+ uint stopLine = calculateLine( stop );
+ if( stopLine >= (uint)numLines() )
+ {
+ stopLine = numLines() == 0 ? 0 : numLines() - 1;
+ }
+
+ uint totalSize = stopLine - startLine + 1;
+ uint remaining = stopLine - startLine + 1;
+ uint bytePerLine = mOffsetSize + 1 + (mNumCell + 2)*mLayout.lineSize + 1;
+ uint linePerStep = 20;
+
+ QByteArray array( bytePerLine * linePerStep + 1 ); // Line is 0 terminated
+ if( array.isEmpty() == true )
+ {
+ p.finish();
+ return( Err_NoMemory );
+ }
+
+ while( remaining > 0 )
+ {
+ uint blockSize = remaining > linePerStep ? linePerStep : remaining;
+ uint printSize = 0;
+
+ for( uint i = 0; i < blockSize; i++, startLine++ )
+ {
+ printSize += printLine( &array[printSize], startLine );
+ }
+
+ int writeSize = file.writeBlock( &array[0], printSize );
+ if( writeSize == -1 )
+ {
+ p.finish();
+ return( Err_WriteFailed );
+ }
+
+ remaining -= blockSize;
+ if( p.expired() == true )
+ {
+ int errCode = p.step( (float)(totalSize-remaining)/(float)totalSize );
+ if( errCode == Err_Stop && remaining > 0 )
+ {
+ p.finish();
+ return( Err_OperationAborted );
+ }
+ }
+ }
+
+ p.finish();
+ return( Err_Success );
+}
+
+
+
+int CHexBuffer::exportHtml( const SExportHtml &ex, CProgress &p )
+{
+ uint start, stop;
+ int errCode = locateRange( ex.range, start, stop );
+ if( errCode != Err_Success )
+ {
+ p.finish();
+ return( errCode );
+ }
+
+ uint startLine = calculateLine( start );
+ if( startLine >= (uint)numLines() )
+ {
+ startLine = numLines() == 0 ? 0 : numLines() - 1;
+ }
+
+ uint stopLine = calculateLine( stop );
+ if( stopLine >= (uint)numLines() )
+ {
+ stopLine = numLines() == 0 ? 0 : numLines() - 1;
+ }
+
+ uint totalSize = stopLine - startLine + 1;
+ uint remaining = stopLine - startLine + 1;
+
+ if( ex.linePerPage == 0 )
+ {
+ p.finish();
+ return( Err_IllegalArgument );
+ }
+
+ uint linePerPage = ex.linePerPage;
+ uint numFiles = remaining/linePerPage + (remaining%linePerPage ? 1 : 0);
+ uint fileCount = 0;
+
+ QStringList fileNames, offsets;
+ QString name, offset;
+ for( uint i=0; i < numFiles; i++ )
+ {
+ name.sprintf( "%08d.html", i+1 );
+ fileNames.append( QString("%1/%2%3").arg(ex.package).arg(ex.prefix).
+ arg(name));
+ }
+ name.sprintf( "%08d.html", 0 );
+ QString tocName =QString("%1/%2%3").arg(ex.package).arg(ex.prefix).arg(name);
+
+ QString linkName;
+ if( ex.symLink == true )
+ {
+ linkName = QString("%1/%2").arg(ex.package).arg("index.html");
+ }
+
+ while( remaining > 0 )
+ {
+ THIS_FPTR(printOffset)( mPrintBuf, startLine*mLayout.lineSize );
+ mPrintBuf[mOffsetSize]=0;
+ offset.sprintf("[%s]", mPrintBuf );
+
+ uint pageSize = remaining > linePerPage ? linePerPage : remaining;
+ printHtmlDataPage( tocName, fileNames, fileCount, ex, startLine, pageSize);
+
+ remaining -= pageSize;
+ startLine += pageSize;
+ fileCount += 1;
+
+ THIS_FPTR(printOffset)( mPrintBuf, (startLine-1)*mLayout.lineSize );
+ mPrintBuf[mOffsetSize]=0;
+ offset += QString(" %1 [%2]").arg(i18n("to")).arg(mPrintBuf);
+ offsets.append(offset);
+
+ if( p.expired() == true )
+ {
+ int errCode = p.step( (float)(totalSize-remaining)/(float)totalSize );
+ if( errCode == Err_Stop && remaining > 0 )
+ {
+ printHtmlTocPage( tocName, linkName, fileNames, offsets, fileCount );
+ p.finish();
+ return( Err_OperationAborted );
+ }
+ }
+ }
+
+ printHtmlTocPage( tocName, linkName, fileNames, offsets, fileCount );
+
+ p.finish();
+ return( Err_Success );
+}
+
+
+int CHexBuffer::exportCArray( const SExportCArray &ex, CProgress &p )
+{
+ uint start, stop;
+ int errCode = locateRange( ex.range, start, stop );
+ if( errCode != Err_Success )
+ {
+ p.finish();
+ return( errCode );
+ }
+
+ QFile file( ex.destFile );
+ if( file.open( IO_WriteOnly ) == false )
+ {
+ p.finish();
+ return( Err_OpenWriteFailed );
+ }
+
+ uint startLine = calculateLine( start );
+ if( startLine >= (uint)numLines() )
+ {
+ startLine = numLines() == 0 ? 0 : numLines() - 1;
+ }
+
+ uint stopLine = calculateLine( stop );
+ if( stopLine >= (uint)numLines() )
+ {
+ stopLine = numLines() == 0 ? 0 : numLines() - 1;
+ }
+
+ uint elementSize = ex.elementSize();
+ uint elementOnThisLine = 0;
+
+ QTextStream dest( &file );
+
+ dest << ex.variableName(stop-start).latin1() << "={" << endl;
+ for( unsigned int i=start; i<stop; i+=elementSize )
+ {
+ dest << ex.printFormatted( (const char*)&data()[i], stop-i );
+ if( i + elementSize < stop )
+ {
+ dest << ",";
+ }
+
+ if( ++elementOnThisLine >= ex.elementPerLine )
+ {
+ dest << endl;
+ elementOnThisLine = 0;
+ }
+
+ if( p.expired() == true )
+ {
+ int errCode = p.step( (float)(i-start)/(float)(stop-start) );
+ if( errCode == Err_Stop && (i+elementSize) < stop)
+ {
+ p.finish();
+ return( Err_OperationAborted );
+ }
+ }
+ }
+ dest << "};" << endl;
+
+ p.finish();
+ return( Err_Success );
+}
+
+
+
+
+
+
+
+int CHexBuffer::copySelectedText( QByteArray &array, int columnSegment )
+{
+ SExportRange range;
+ range.mode = SExportRange::Selection;
+ return( copyText( array, range, columnSegment ) );
+}
+
+
+int CHexBuffer::copyAllText( QByteArray &array )
+{
+ SExportRange range;
+ range.mode = SExportRange::All;
+ return( copyText( array, range, VisibleColumn ) );
+}
+
+
+int CHexBuffer::copyText( QByteArray &array, const SExportRange &range,
+ int columnSegment )
+{
+ uint start, stop;
+ int errCode = locateRange( range, start, stop );
+ if( errCode != Err_Success )
+ {
+ return( errCode );
+ }
+
+ uint startLine = calculateLine( start );
+ uint stopLine = calculateLine( stop );
+ if( startLine >= (uint)numLines() )
+ {
+ startLine = numLines() == 0 ? 0 : numLines() - 1;
+ }
+ if( stopLine >= (uint)numLines() )
+ {
+ stopLine = numLines() == 0 ? 0 : numLines() - 1;
+ }
+
+ uint bytePerLine = mOffsetSize + 1 + (mNumCell + 2)*mLayout.lineSize + 1;
+ uint size = (stopLine - startLine + 1)*bytePerLine;
+ if( array.resize( size+1 ) == false )
+ {
+ return( Err_NoMemory );
+ }
+
+ if( columnSegment == VisibleColumn )
+ {
+ columnSegment = PrimaryColumn; // Always visible
+ if( mLayout.offsetVisible == true )
+ {
+ columnSegment |= OffsetColumn;
+ }
+ if( mLayout.secondaryMode != SDisplayLayout::hide )
+ {
+ columnSegment |= SecondaryColumn;
+ }
+ }
+
+ uint offset = 0;
+ for( uint i = startLine; i <= stopLine; i++ )
+ {
+ offset += printLine( &array[offset], i, columnSegment );
+ }
+ array[size] = 0;
+
+ return( Err_Success );
+}
+
+
+int CHexBuffer::copySelectedData( QByteArray &array )
+{
+ uint start = mSelect.start();
+ uint stop = mSelect.stop();
+
+ if( mSelect.valid() == false || start >= stop )
+ {
+ return( Err_IllegalRange );
+ }
+
+ uint size = stop - start;
+ if( array.resize( size ) == false )
+ {
+ return( Err_NoMemory );
+ }
+
+ //unsigned char *src = (unsigned char*)data();
+ //char *dst = (char*)array.data();
+
+ memcpy( &array[0], &data()[start], size );
+ return( Err_Success );
+}
+
+
+uint CHexBuffer::numPage( CHexPrinter &printer )
+{
+ QPainter paint( &printer );
+ paint.setFont( font() );
+
+ SPageMargin margin = printer.pageMargin();
+ SPageSize size = printer.pageUsableSize();
+ int headHeight, footHeight, headMargin, footMargin, freeHeight;
+
+ headHeight = footHeight = headMargin = footMargin = 0;
+ if( printer.pageHeader().enable == true )
+ {
+ headHeight = headerHeight( paint );
+ headMargin = headerMargin( paint );
+ }
+ if( printer.pageFooter().enable == true )
+ {
+ footHeight = headerHeight( paint );
+ footMargin = headerMargin( paint );
+ }
+ freeHeight = size.height - headHeight - footHeight - headMargin - footMargin;
+
+ float scale = 1.0;
+ if( (uint)mLineWidth > size.width )
+ {
+ scale = (float)size.width / (float)mLineWidth;
+ }
+ uint linePerPage = (uint) ((float)freeHeight/((float)lineHeight()*scale));
+
+ uint remaining = numLines();
+
+ return( remaining / linePerPage + (remaining % linePerPage ? 1 : 0) );
+}
+
+
+
+int CHexBuffer::print( CHexPrinter &printer, CProgress &p )
+{
+ printer.setDocName( mUrl );
+
+ QPainter paint( &printer );
+ paint.setFont( font() );
+
+ SPageMargin margin = printer.pageMargin();
+ SPageSize size = printer.pageUsableSize();
+ paint.setClipRect( margin.left, margin.top, size.width, size.height );
+
+ //printf("%d,%d,%d,%d\n", margin.left, margin.top, size.width, size.height );
+
+ int headHeight, footHeight, headMargin, footMargin, freeHeight;
+
+ headHeight = footHeight = headMargin = footMargin = 0;
+ if( printer.pageHeader().enable == true )
+ {
+ headHeight = headerHeight( paint );
+ headMargin = headerMargin( paint );
+ }
+ if( printer.pageFooter().enable == true )
+ {
+ footHeight = headerHeight( paint );
+ footMargin = headerMargin( paint );
+ }
+ freeHeight = size.height - headHeight - footHeight - headMargin - footMargin;
+
+ float scale = 1.0;
+ if( (uint)mLineWidth > size.width )
+ {
+ scale = (float)size.width / (float)mLineWidth;
+ paint.scale( scale, scale );
+ }
+
+ uint linePerPage = (uint) ((float)freeHeight/((float)lineHeight()*scale));
+ uint sx = (uint) ((float)margin.left/scale);
+ uint sy = (uint) ((float)(margin.top+headHeight+headMargin)/scale);
+
+ uint remaining = numLines();
+ uint line = 0;
+
+ #ifdef PRINTER_TEST
+ remaining = remaining > linePerPage * 10 ? linePerPage * 10 : remaining;
+ #endif
+
+
+ SPagePosition pageData( time(0), remaining, linePerPage );
+ while( remaining > 0 )
+ {
+ uint lineInPage = remaining > linePerPage ? linePerPage : remaining;
+ uint y = sy;
+
+ //
+ // Draw header and footer. Reset scaling during that operation.
+ //
+ paint.scale( 1.0/scale, 1.0/scale );
+ if( printer.pageHeader().enable == true )
+ {
+ drawHeader( paint, margin.left, size.width, margin.top, false,
+ printer.pageHeader(), pageData );
+ }
+ if( printer.pageFooter().enable == true )
+ {
+ drawHeader( paint, margin.left, size.width,
+ margin.top+size.height-footHeight, true,
+ printer.pageFooter(), pageData );
+ }
+ paint.scale( scale, scale );
+
+ //
+ // Draw actual data
+ //
+ for( uint i=0; i < lineInPage; i++, line++ )
+ {
+ drawText( paint, line, sx, mLineWidth, y, false/*printer.printBlackWhite()*/ );
+ y += lineHeight();// - mLayout.horzGridWidth; // FIXME not really nice :)
+
+ if( p.expired() == true )
+ {
+ int errCode = p.step( pageData.current(), pageData.max() );
+ if( errCode == Err_Stop )
+ {
+ p.finish();
+ return( Err_Success ); // Success here, even if we cancel
+ }
+ }
+ }
+
+ if( p.expired() == true )
+ {
+ int errCode = p.step( pageData.current(), pageData.max() );
+ if( errCode == Err_Stop )
+ {
+ p.finish();
+ return( Err_Success );// Success here, even if we cancel
+ }
+ }
+
+ remaining -= lineInPage;
+ if( remaining > 0 )
+ {
+ printer.newPage();
+ }
+
+ pageData.step();
+ }
+
+ p.finish();
+ return( Err_Success );
+}
+
+
+
+
+
+uint CHexBuffer::printLine( char *dst, uint line )
+{
+ uint offset = line * mLayout.lineSize;
+ unsigned char *src;
+ char *start = dst;
+
+ uint dataSize;
+ if( offset >= documentSize() )
+ {
+ src = 0;
+ dataSize = 0;
+ }
+ else
+ {
+ src = (unsigned char*)&data()[ offset ];
+ dataSize = documentSize() - offset;
+ }
+
+ if( mLayout.offsetVisible == true )
+ {
+ THIS_FPTR(printOffset)( dst, offset ); dst += mOffsetSize;
+ sprintf( dst, " " ); dst += 1;
+ }
+ for( uint i=0; i < mLayout.lineSize; i++ )
+ {
+ if( i<dataSize )
+ {
+ THIS_FPTR(printCell)( dst, src[i] ); dst += mNumCell;
+ }
+ else
+ {
+ memset( dst, ' ', mNumCell ); dst += mNumCell;
+ }
+ if( mSplitWidth != 0 )
+ {
+ sprintf( dst, " " ); dst += 1;
+ }
+ }
+ if( mLayout.secondaryMode != SDisplayLayout::hide )
+ {
+ for( uint i=0; i < mLayout.lineSize; i++ )
+ {
+ if( i < dataSize )
+ {
+ printAsciiCell( dst, src[i] ); dst += 1;
+ }
+ else
+ {
+ memset( dst, ' ', 1 ); dst += 1;
+ }
+ }
+ }
+ sprintf( dst, "\n" ); dst += 1;
+ return( (uint)(dst-start) );
+}
+
+
+uint CHexBuffer::printLine( char *dst, uint line, int columnSegment )
+{
+ uint offset = line * mLayout.lineSize;
+ unsigned char *src;
+ char *start = dst;
+
+ uint dataSize;
+ if( offset >= documentSize() )
+ {
+ src = 0;
+ dataSize = 0;
+ }
+ else
+ {
+ src = (unsigned char*)&data()[ offset ];
+ dataSize = documentSize() - offset;
+ }
+
+ if( columnSegment & OffsetColumn )
+ {
+ THIS_FPTR(printOffset)( dst, offset ); dst += mOffsetSize;
+ sprintf( dst, " " ); dst += 1;
+ }
+
+ if( columnSegment & PrimaryColumn )
+ {
+ for( uint i=0; i < mLayout.lineSize; i++ )
+ {
+ if( i<dataSize )
+ {
+ THIS_FPTR(printCell)( dst, src[i] ); dst += mNumCell;
+ }
+ else
+ {
+ memset( dst, ' ', mNumCell ); dst += mNumCell;
+ }
+ if( mSplitWidth != 0 )
+ {
+ sprintf( dst, " " ); dst += 1;
+ }
+ }
+ }
+
+ if( columnSegment & SecondaryColumn )
+ {
+ for( uint i=0; i < mLayout.lineSize; i++ )
+ {
+ if( i < dataSize )
+ {
+ printAsciiCell( dst, src[i] ); dst += 1;
+ }
+ else
+ {
+ memset( dst, ' ', 1 ); dst += 1;
+ }
+ }
+ }
+
+ sprintf( dst, "\n" ); dst += 1;
+ return( (uint)(dst-start) );
+}
+
+
+
+
+
+
+
+
+
+
+
+bool CHexBuffer::cutSelection( void )
+{
+ if( documentPresent() == false || mSelect.size() == 0 )
+ {
+ return( false );
+ }
+
+ if( mInputMode.noInput() == true || mInputMode.allowResize == false )
+ {
+ inputSound();
+ return( false );
+ }
+
+ recordStart( mCursor );
+ cursorGoto( mSelect.start(), 0 );
+ recordReplace( mCursor, mSelect.size(), 0, 0 );
+ recordEnd( mCursor );
+
+ mSelect.reset();
+
+ computeNumLines();
+ return( true );
+}
+
+
+
+bool CHexBuffer::undo( void )
+{
+ if( documentPresent() == false || mUndoIndex == 0 ||
+ mInputMode.noInput() == true )
+ {
+ if( mInputMode.noInput() == true ) { inputSound(); }
+ return( false );
+ }
+
+ CHexActionGroup *group = mUndoList.at( mUndoIndex-1 );
+ if( group == 0 )
+ {
+ return( false );
+ }
+
+ mUndoIndex -= 1;
+ doActionGroup( group );
+
+ cursorGoto( group->mStartOffset, group->mStartBit );
+
+ return( true );
+}
+
+
+bool CHexBuffer::redo( void )
+{
+ if( documentPresent() == false || mUndoIndex >= mUndoList.count() ||
+ mInputMode.noInput() == true )
+ {
+ if( mInputMode.noInput() == true ) { inputSound(); }
+ return( false );
+ }
+
+ CHexActionGroup *group = mUndoList.at( mUndoIndex );
+ if( group == 0 )
+ {
+ return( false );
+ }
+
+ mUndoIndex += 1;
+ doActionGroup( group );
+
+ cursorGoto( group->mStopOffset, group->mStopBit );
+
+ return( true );
+}
+
+
+int CHexBuffer::addBookmark( int position )
+{
+ if( documentPresent() == false )
+ {
+ return( Err_NoData );
+ }
+
+ if( mBookmarkList.count() >= 9 && position == -1 )
+ {
+ return( Err_ListFull );
+ }
+
+ SCursorOffset *co = new SCursorOffset;
+ if( co == 0 )
+ {
+ fatalSound();
+ return( Err_NoMemory );
+ }
+
+ co->offset = mCursor.curr.offset;
+ co->bit = mCursor.bit();
+
+ if( position == -1 || position > (int)mBookmarkList.count() )
+ {
+ mBookmarkList.append( co );
+ }
+ else
+ {
+ mBookmarkList.remove( (uint)position );
+ mBookmarkList.insert( (uint)position, co );
+ }
+
+ updateBookmarkMap(false);
+ return( Err_Success );
+}
+
+
+bool CHexBuffer::removeBookmark( int position )
+{
+ if( position < 0 )
+ {
+ if( mBookmarkList.count() == 0 )
+ {
+ return( false );
+ }
+ mBookmarkList.clear();
+ }
+ else
+ {
+ if( (uint)position >= mBookmarkList.count() )
+ {
+ return( false );
+ }
+ mBookmarkList.remove( position );
+ }
+
+ updateBookmarkMap(false);
+ return( true );
+}
+
+
+void CHexBuffer::updateBookmarkMap( bool resize )
+{
+ if( resize == true )
+ {
+ mBookmarkMap.resize( documentSize()/200 + 3 );
+ }
+ mBookmarkMap.fill(0);
+
+ int bookmarkMapSize = mBookmarkMap.size();
+ for( SCursorOffset *c=mBookmarkList.first(); c!=0; c=mBookmarkList.next() )
+ {
+ int bookmarkOffset = c->offset / 200;
+ if( bookmarkOffset < bookmarkMapSize )
+ {
+ //
+ // Espen 2000-05-16:
+ // I do this test to avoid some Qt warnings when I have closed
+ // or reduced the size of the documnet while the (now invalid)
+ // bookmarks still exist.
+ //
+ mBookmarkMap.setBit(bookmarkOffset);
+ }
+ }
+}
+
+
+int CHexBuffer::findFirst( SSearchControl &sc )
+{
+ mMark.reset();
+ int errCode = scanData( sc, true );
+ return( errCode );
+}
+
+int CHexBuffer::findNext( SSearchControl &sc )
+{
+ sc.fromCursor = true;
+ int errCode = scanData( sc, false );
+ return( errCode );
+}
+
+int CHexBuffer::findWrap( SSearchControl &sc )
+{
+ if( sc.wrapValid == false )
+ {
+ return( Err_NoMatch );
+ }
+ sc.wrapValid = false;
+
+ sc.fromCursor = false;
+ sc.wrapActive = true;
+ int errCode = scanData( sc, false );
+ sc.fromCursor = true;
+ return( errCode );
+}
+
+
+
+
+int CHexBuffer::replaceAll( SSearchControl &sc, bool init )
+{
+ if( init == true )
+ {
+ initScanData( sc );
+ }
+
+ if( sc.key.isEmpty() == true )
+ {
+ return( Err_EmptyArgument );
+ }
+
+ if( documentSize() == 0 )
+ {
+ return( Err_EmptyDocument );
+ }
+
+ uint head, tail;
+ if( sc.inSelection == true )
+ {
+ if( mSelect.valid() == false )
+ {
+ return( Err_NoSelection );
+ }
+
+ head = mSelect.start();
+ tail = mSelect.stop();
+ }
+ else
+ {
+ head = 0;
+ tail = documentSize();
+ }
+
+ uint start, stop;
+ if( sc.fromCursor == false )
+ {
+ if( sc.wrapActive == true )
+ {
+ start = sc.forward == true ? head : sc.wrapMark;
+ stop = sc.forward == true ? sc.wrapMark+sc.key.size() : tail;
+ }
+ else
+ {
+ start = head;
+ stop = tail;
+ }
+ }
+ else if( sc.forward == true )
+ {
+ start = cursorOffset() < head ? head : cursorOffset();
+ stop = sc.wrapActive == true ? sc.wrapMark+sc.key.size() : tail;
+ }
+ else
+ {
+ start = sc.wrapActive == true ? sc.wrapMark : head;
+ stop = cursorOffset() > tail ? tail : cursorOffset();
+ }
+
+ if( sc.forward == true && start + sc.key.size() > stop )
+ {
+ //
+ // When searching backwards "stop" is the last offset from where
+ // we do a memcmp() upward in memory. An overflow for that
+ // situation is taken care of below.
+ //
+ return( Err_NoMatch );
+ }
+
+ if( stop + sc.key.size() > tail )
+ {
+ uint diff = stop + sc.key.size() - tail;
+ stop = stop > diff ? stop - diff : 0;
+ }
+
+ if( mInputMode.noInput() == true )
+ {
+ inputSound();
+ return( Err_WriteProtect );
+ }
+
+ recordStart( mCursor );
+ uint numReplaced = 0;
+
+ if( sc.forward == true )
+ {
+ for( uint i = start; i <= stop ; )
+ {
+ if( memcmp( &data()[i], sc.key.data(), sc.key.size() ) != 0 )
+ {
+ i++;
+ }
+ else
+ {
+ cursorGoto( i, 7 );
+ recordReplace( mCursor, sc.key.size(), sc.val.data(), sc.val.size() );
+ numReplaced += 1;
+
+ if( sc.inSelection == true )
+ {
+ if( sc.key.size() > sc.val.size() )
+ {
+ mSelect.shrink( sc.key.size() - sc.val.size() );
+ }
+ else
+ {
+ mSelect.expand( sc.val.size() - sc.key.size() );
+ }
+ }
+
+ if( sc.key.size() > sc.val.size() )
+ {
+ uint diff = sc.key.size() - sc.val.size();
+ stop -= QMIN( stop, diff );
+ }
+ else if( sc.key.size() < sc.val.size() )
+ {
+ stop += sc.val.size() - sc.key.size();
+ }
+
+ i += sc.val.size();
+ cursorStep( sc.val.size(), true, false );
+ }
+ }
+ }
+ else
+ {
+ for( uint i = stop; i >= start; )
+ {
+ if( memcmp( &data()[i], sc.key.data(), sc.key.size() ) != 0 )
+ {
+ if( i == 0 ) { break; }
+ i--;
+ }
+ else
+ {
+ cursorGoto( i, 7 );
+ recordReplace( mCursor, sc.key.size(), sc.val.data(), sc.val.size() );
+ numReplaced += 1;
+
+ if( sc.inSelection == true )
+ {
+ if( sc.key.size() > sc.val.size() )
+ {
+ mSelect.shrink( sc.key.size() - sc.val.size() );
+ }
+ else
+ {
+ mSelect.expand( sc.val.size() - sc.key.size() );
+ }
+ }
+
+ i -= QMIN( i, sc.key.size() );
+ if( i == 0 ) { break; }
+ }
+ }
+ }
+
+ recordEnd( mCursor );
+ computeNumLines();
+
+ if( numReplaced == 0 )
+ {
+ return( Err_NoMatch );
+ }
+
+ sc.numReplace += numReplaced;
+ sc.match = true;
+ mMark.reset();
+
+ return( Err_Success );
+}
+
+
+int CHexBuffer::replaceMarked( SSearchControl &sc )
+{
+ if( documentSize() == 0 )
+ {
+ return( Err_EmptyDocument );
+ }
+
+ if( mMark.valid() == false )
+ {
+ return( Err_NoMark );
+ }
+
+ bool inSelection;
+ if( mSelect.valid() == true )
+ {
+ if( mMark.start() >= mSelect.start() && mMark.stop() <= mSelect.stop() )
+ {
+ inSelection = true;
+ }
+ else
+ {
+ inSelection = false;
+ }
+ }
+ else
+ {
+ inSelection = false;
+ }
+
+ if( mInputMode.noInput() == true )
+ {
+ inputSound();
+ return( Err_WriteProtect );
+ }
+
+ recordStart( mCursor );
+ cursorGoto( mMark.start(), 7 );
+ recordReplace( mCursor, mMark.size(), sc.val.data(), sc.val.size() );
+ sc.numReplace += 1;
+
+ if( inSelection == true )
+ {
+ if( mMark.size() > sc.val.size() )
+ {
+ mSelect.shrink( mMark.size() - sc.val.size() );
+ }
+ else
+ {
+ sc.wrapMark += sc.val.size() - mMark.size();
+ mSelect.expand( sc.val.size() - mMark.size() );
+ }
+ }
+
+
+ if( sc.wrapActive == false )
+ {
+ if( sc.forward == false )
+ {
+ sc.wrapMark += mMark.size() > sc.val.size() ?
+ mMark.size() - sc.val.size() : sc.val.size() - mMark.size();
+ }
+ }
+
+
+ recordEnd( mCursor );
+ computeNumLines();
+
+ if( sc.forward == true )
+ {
+ //
+ // We must step over the area we have just altered. This is
+ // vital if the search key contains a pattern that exists in
+ // the replace data buffer.
+ //
+ cursorStep( sc.val.size(), true, false );
+ }
+ mMark.reset();
+ return( Err_Success );
+}
+
+
+#if 0
+
+int CHexBuffer::replaceAll( SSearchControl &sc, bool init )
+{
+ if( init == true )
+ {
+ initScanData( sc );
+ }
+
+ if( sc.key.isEmpty() == true )
+ {
+ return( Err_EmptyArgument );
+ }
+
+ if( documentSize() == 0 )
+ {
+ return( Err_EmptyDocument );
+ }
+
+ uint head, tail;
+ if( sc.inSelection == true )
+ {
+ if( mSelect.valid() == false )
+ {
+ return( Err_NoSelection );
+ }
+
+ head = mSelect.start();
+ tail = mSelect.stop();
+ }
+ else
+ {
+ head = 0;
+ tail = documentSize();
+ }
+
+ uint start, stop;
+ if( sc.fromCursor == false )
+ {
+ if( sc.wrapActive == true )
+ {
+ start = sc.forward == true ? head : sc.wrapMark;
+ stop = sc.forward == true ? sc.wrapMark : tail;
+ }
+ else
+ {
+ start = head;
+ stop = tail;
+ }
+ }
+ else if( sc.forward == true )
+ {
+ start = cursorOffset() < head ? head : cursorOffset();
+ stop = sc.wrapActive == true ? sc.wrapMark : tail;
+ }
+ else
+ {
+ start = sc.wrapActive == true ? sc.wrapMark : head;
+ stop = cursorOffset() > tail ? tail : cursorOffset();
+ }
+
+
+ if( start + sc.key.size() > stop )
+ {
+ return( Err_NoMatch );
+ }
+
+ if( stop + sc.key.size() > tail )
+ {
+ uint diff = stop + sc.key.size() - tail;
+ stop = stop > diff ? stop - diff : 0;
+ }
+
+ if( mInputMode.noInput() == true )
+ {
+ inputSound();
+ return( Err_WriteProtect );
+ }
+
+ recordStart( mCursor );
+ uint numReplaced = 0;
+
+ if( sc.forward == true )
+ {
+ for( uint i = start; i <= stop; i++ )
+ {
+ if( memcmp( &data()[i], sc.key.data(), sc.key.size() ) == 0 )
+ {
+ cursorGoto( i, 7 );
+ recordReplace( mCursor, sc.key.size(), sc.val.data(), sc.val.size() );
+ numReplaced += 1;
+
+ if( sc.inSelection == true )
+ {
+ if( sc.key.size() > sc.val.size() )
+ {
+ mSelect.shrink( sc.key.size() - sc.val.size() );
+ }
+ else
+ {
+ mSelect.expand( sc.val.size() - sc.key.size() );
+ }
+ }
+
+ if( sc.key.size() > sc.key.size() )
+ {
+ uint diff = sc.key.size() - sc.val.size();
+ i += diff - 1;
+ }
+ else if( sc.key.size() < sc.val.size() )
+ {
+ uint diff = sc.val.size() - sc.key.size();
+ stop += diff;
+ }
+ else
+ {
+ i += sc.val.size() - 1;
+ }
+ cursorStep( sc.val.size(), true, false );
+ }
+ }
+ }
+ else
+ {
+ for( uint i = stop; i >= start; i-- )
+ {
+ if( memcmp( &data()[i], sc.key.data(), sc.key.size() ) == 0 )
+ {
+ cursorGoto( i, 7 );
+ recordReplace( mCursor, sc.key.size(), sc.val.data(), sc.val.size() );
+ numReplaced += 1;
+
+ if( sc.inSelection == true )
+ {
+ if( sc.key.size() > sc.val.size() )
+ {
+ mSelect.shrink( sc.key.size() - sc.val.size() );
+ }
+ else
+ {
+ mSelect.expand( sc.val.size() - sc.key.size() );
+ }
+ }
+
+ }
+ if( i == 0 ) { break; }
+ }
+ }
+
+ recordEnd( mCursor );
+ computeNumLines();
+
+ if( numReplaced == 0 )
+ {
+ return( Err_NoMatch );
+ }
+
+ sc.numReplace += numReplaced;
+ sc.match = true;
+ mMark.reset();
+
+ return( Err_Success );
+}
+
+
+int CHexBuffer::replaceMarked( SSearchControl &sc )
+{
+ if( documentSize() == 0 )
+ {
+ return( Err_EmptyDocument );
+ }
+
+ if( mMark.valid() == false )
+ {
+ return( Err_NoMark );
+ }
+
+ bool inSelection;
+ if( mSelect.valid() == false )
+ {
+ if( mMark.start() >= mSelect.start() && mMark.stop() <= mSelect.stop() )
+ {
+ inSelection = true;
+ }
+ else
+ {
+ inSelection = false;
+ }
+ }
+ else
+ {
+ inSelection = false;
+ }
+
+ if( mInputMode.noInput() == true )
+ {
+ inputSound();
+ return( Err_WriteProtect );
+ }
+
+ recordStart( mCursor );
+ cursorGoto( mMark.start(), 7 );
+ recordReplace( mCursor, mMark.size(), sc.val.data(), sc.val.size() );
+ sc.numReplace += 1;
+
+ if( inSelection == true )
+ {
+ if( mMark.size() > sc.val.size() )
+ {
+ mSelect.shrink( mMark.size() - sc.val.size() );
+ }
+ else
+ {
+ mSelect.expand( sc.val.size() - mMark.size() );
+ }
+ }
+
+ recordEnd( mCursor );
+ computeNumLines();
+ mMark.reset();
+
+ return( Err_Success );
+}
+
+#endif
+
+
+int CHexBuffer::initScanData( SSearchControl &sc )
+{
+ sc.wrapValid = false;
+ sc.wrapActive = false;
+ sc.wrapMark = 0;
+ sc.match = false;
+ sc.numReplace = 0;
+
+ uint head, tail;
+ if( sc.inSelection == true )
+ {
+ if( mSelect.valid() == false )
+ {
+ return( Err_NoSelection );
+ }
+
+ head = mSelect.start();
+ tail = mSelect.stop();
+ }
+ else
+ {
+ head = 0;
+ tail = documentSize();
+ }
+
+ if( sc.fromCursor == false )
+ {
+ sc.wrapValid = false;
+ sc.wrapActive = false;
+ sc.wrapMark = 0;
+ }
+ else if( sc.forward == true )
+ {
+ if( cursorOffset() > tail )
+ {
+ sc.wrapValid = true;
+ sc.wrapActive = false;
+ sc.wrapMark = tail;
+ }
+ else if( cursorOffset() <= head )
+ {
+ sc.wrapValid = false;
+ sc.wrapActive = false;
+ sc.wrapMark = 0;
+ }
+ else
+ {
+ sc.wrapValid = true;
+ sc.wrapActive = false;
+ sc.wrapMark = cursorOffset();
+ }
+ }
+ else
+ {
+ if( cursorOffset() >= tail )
+ {
+ sc.wrapValid = false;
+ sc.wrapActive = false;
+ sc.wrapMark = 0;
+ }
+ else if( cursorOffset() < head )
+ {
+ sc.wrapValid = true;
+ sc.wrapActive = false;
+ sc.wrapMark = head;
+ }
+ else
+ {
+ sc.wrapValid = true;
+ sc.wrapActive = false;
+ sc.wrapMark = cursorOffset();
+ }
+ }
+
+ return( Err_Success );
+}
+
+
+
+int CHexBuffer::scanData( SSearchControl &sc, bool init )
+{
+ if( init == true )
+ {
+ int errCode = initScanData( sc );
+ if( errCode != Err_Success )
+ {
+ return( errCode );
+ }
+ }
+
+ if( sc.key.isEmpty() == true )
+ {
+ return( Err_EmptyArgument );
+ }
+
+ if( documentSize() == 0 )
+ {
+ return( Err_EmptyDocument );
+ }
+
+ uint head, tail;
+ if( sc.inSelection == true )
+ {
+ if( mSelect.valid() == false )
+ {
+ return( Err_NoSelection );
+ }
+
+ head = mSelect.start();
+ tail = mSelect.stop();
+ }
+ else
+ {
+ head = 0;
+ tail = documentSize();
+ }
+
+ uint start, stop;
+ if( sc.fromCursor == false )
+ {
+ if( sc.wrapActive == true )
+ {
+ start = sc.forward == true ? head : sc.wrapMark;
+ stop = sc.forward == true ? sc.wrapMark+sc.key.size() : tail;
+ }
+ else
+ {
+ start = head;
+ stop = tail;
+ }
+ }
+ else if( sc.forward == true )
+ {
+ start = cursorOffset() < head ? head : cursorOffset();
+ stop = sc.wrapActive == true ? sc.wrapMark : tail;
+ }
+ else
+ {
+ start = sc.wrapActive == true ? sc.wrapMark : head;
+ stop = cursorOffset() > tail ? tail : cursorOffset();
+ }
+
+ if( sc.forward == true && start + sc.key.size() > stop )
+ {
+ //
+ // When searching backwards "stop" is the last offset from where
+ // we do a memcmp() upward in memory. An overflow for that
+ // situation is taken care of below.
+ //
+ return( stop + sc.key.size() < tail ? Err_WrapBuffer : Err_NoData );
+ }
+
+ if( stop + sc.key.size() > tail )
+ {
+ uint diff = stop + sc.key.size() - tail;
+ stop = stop > diff ? stop - diff : 0;
+ }
+
+ if( sc.forward == true )
+ {
+ for( uint i = start; i <= stop; i++ )
+ {
+ int result;
+ if( sc.ignoreCase == true )
+ {
+ result = strncasecmp( &data()[i], sc.key.data(), sc.key.size() );
+ }
+ else
+ {
+ result = memcmp( &data()[i], sc.key.data(), sc.key.size() );
+ }
+ if( result == 0 )
+ {
+ if( i != cursorOffset() || mMark.size() != sc.key.size() )
+ {
+ sc.match = true;
+ cursorGoto( i, 7 );
+ markSet( i, sc.key.size() );
+ return( Err_Success );
+ }
+ }
+ }
+ return( start > head ? Err_WrapBuffer : Err_NoData );
+ }
+ else
+ {
+ for( uint i = stop; i >= start; i-- )
+ {
+ int result;
+ if( sc.ignoreCase == true )
+ {
+ result = strncasecmp( &data()[i], sc.key.data(), sc.key.size() );
+ }
+ else
+ {
+ result = memcmp( &data()[i], sc.key.data(), sc.key.size() );
+ }
+ if( result == 0 )
+ {
+ if( i != cursorOffset() || mMark.size() != sc.key.size() )
+ {
+ sc.match = true;
+ cursorGoto( i, 7 );
+ markSet( i, sc.key.size() );
+ return( Err_Success );
+ }
+ }
+ if( i == 0 ) { break; }
+ }
+
+ return( stop + sc.key.size() <= tail ? Err_WrapBuffer : Err_NoData );
+ }
+}
+
+
+
+
+
+int CHexBuffer::filter( SFilterControl &fc )
+{
+ uint head, tail;
+ if( fc.inSelection == true )
+ {
+ if( mSelect.valid() == false )
+ {
+ return( Err_NoSelection );
+ }
+
+ head = mSelect.start();
+ tail = mSelect.stop();
+ }
+ else
+ {
+ head = 0;
+ tail = documentSize();
+ }
+
+ uint start, stop;
+ if( fc.fromCursor == false )
+ {
+ start = head;
+ stop = tail;
+ }
+ else if( fc.forward == true )
+ {
+ start = cursorOffset() < head ? head : cursorOffset();
+ stop = tail;
+ }
+ else
+ {
+ start = head;
+ stop = cursorOffset() > tail ? tail : cursorOffset();
+ }
+
+ if( mInputMode.noInput() == true )
+ {
+ inputSound();
+ return( Err_WriteProtect );
+ }
+
+ if( start >= stop ) { return( Err_IllegalRange ); }
+ QByteArray buf( stop - start );
+ if( buf.isEmpty() == true ) { return( Err_NoMemory ); }
+
+ int errCode = fc.execute((uchar*)&buf[0],(uchar*)&data()[start],buf.size());
+ if( errCode == Err_Success )
+ {
+ recordStart( mCursor );
+ cursorGoto( start, 7 );
+ recordReplace( mCursor, buf.size(), buf.data(), buf.size() );
+ recordEnd( mCursor );
+ }
+
+ return( errCode );
+}
+
+
+
+int CHexBuffer::collectStrings( CStringCollectControl &sc )
+{
+ uint startOffset = 0;
+ uint start, i;
+ bool on = false;
+
+ if( sc.minLength < 1 ) { sc.minLength = 1; }
+
+ start = startOffset;
+ for( i = startOffset; i<documentSize(); i++ )
+ {
+ unsigned char item = data()[i];
+ if( isprint( item ) == 0 || item >= 128 )
+ {
+ if( on == true && i-start >= sc.minLength )
+ {
+ QByteArray a( i-start );
+ for( uint j=0; j<(i-start); a[j]=data()[start+j], j++ );
+ sc.add( start, a );
+ }
+ on = false;
+ }
+ else
+ {
+ if( on == false ) { start = i; }
+ on = true;
+ }
+ }
+
+ if( on == true && i-start >= sc.minLength )
+ {
+ QByteArray a( i-start );
+ for( uint j=0; j<(i-start); a[j]=data()[start+j], j++ );
+ sc.add( start, a );
+ }
+
+ return( Err_Success );
+}
+
+
+int CHexBuffer::collectStatistic( SStatisticControl &sc, CProgress &p )
+{
+ sc.documentSize = documentSize();
+ sc.documentName = mUrl;
+
+ for( uint i = 0; i<documentSize(); i++ )
+ {
+ sc.occurrence[ (unsigned char)data()[i] ] += 1;
+
+ //
+ // The expired() function introduces too much overhead in this case
+ // so it is only executed every 100'th character
+ //
+ if( i % 100 == 0 && p.expired() == true )
+ {
+ int errCode = p.step( (float)i/(float)documentSize() );
+ if( errCode == Err_Stop && i+1 < documentSize() )
+ {
+ p.finish();
+ return( Err_OperationAborted );
+ }
+ }
+ }
+ p.finish();
+ return( Err_NoErr );
+}
+
+
+void CHexBuffer::doActionGroup( CHexActionGroup *group )
+{
+ if( group == 0 )
+ {
+ return;
+ }
+
+ CHexAction *action = group->mHexAction;
+ group->mHexAction = 0;
+
+ while( action != 0 )
+ {
+ doAction( action );
+ CHexAction *next = action->mNext;
+ group->insertAction( action );
+ action = next;
+ }
+
+ computeNumLines();
+}
+
+
+void CHexBuffer::doAction( CHexAction *action )
+{
+ if( action->mAction == CHexAction::replace )
+ {
+ doReplace( action, true );
+ }
+}
+
+
+
+
+
+void CHexBuffer::recordStart( SCursor &cursor )
+{
+ //
+ // Step 1: Remove any undo element that is more recent than the
+ // current undo index
+ //
+ while( mUndoList.count() > mUndoIndex )
+ {
+ mUndoList.removeLast();
+ }
+
+ //
+ // Step 2: Make sure the undo list is no larger than the undo limit.
+ // We remove the oldest elements in the list.
+ //
+ while( mUndoList.count() >= mUndoLimit )
+ {
+ mUndoList.removeFirst();
+ mUndoIndex -= 1;
+ }
+
+ CHexActionGroup *group = new CHexActionGroup( cursor.curr.offset,
+ cursor.bit() );
+ if( group == 0 )
+ {
+ return;
+ }
+
+ mUndoList.append( group );
+ mUndoIndex += 1;
+}
+
+
+void CHexBuffer::recordReplace( SCursor &cursor, uint size, char *data1,
+ uint data1Size )
+{
+ CHexAction *hexAction = new CHexAction( CHexAction::replace,
+ cursor.curr.offset );
+ if( hexAction == 0 )
+ {
+ return;
+ }
+
+ hexAction->mSize = size;
+ hexAction->mData = data1;
+ hexAction->mDataSize = data1Size;
+
+ doReplace( hexAction, false );
+ mUndoList.getLast()->insertAction( hexAction );
+
+ if( mCursor.curr.offset < documentSize() )
+ {
+ mCursor.curr.data = data()[ mCursor.curr.offset ];
+ }
+
+}
+
+void CHexBuffer::recordEnd( SCursor &cursor )
+{
+ mUndoList.getLast()->mStopOffset = cursor.curr.offset;
+ mUndoList.getLast()->mStopBit = cursor.bit();
+}
+
+
+//
+// This method is the only place where the doucument data can be changed.
+//
+void CHexBuffer::doReplace( CHexAction *hexAction, bool removeData )
+{
+ uint offset = hexAction->mOffset;
+ uint oldSize = hexAction->mSize;
+ char *newData = hexAction->mData;
+ uint newSize = hexAction->mDataSize;
+
+ hexAction->setData( newSize, &data()[offset], oldSize );
+
+ //
+ // Input new data. Resize buffer first if necessary. We always mark the
+ // data as changed (dirty) when the buffer is resized, otherwise only
+ // when the new data differ from the current. Nice feature :-)
+ //
+ int errCode;
+ if( newSize > oldSize )
+ {
+ errCode = moveBuffer( offset + newSize - oldSize, offset );
+ mDocumentModified = true;
+ }
+ else if( newSize < oldSize )
+ {
+ errCode = moveBuffer( offset, offset + oldSize - newSize );
+ mDocumentModified = true;
+ }
+ else
+ {
+ errCode = Err_Success;
+ if( memcmp( &data()[offset], newData, newSize ) != 0 )
+ {
+ mDocumentModified = true;
+ }
+ }
+
+ if( errCode == Err_Success )
+ {
+ memcpy( &data()[offset], newData, newSize );
+ }
+
+ //
+ // Data is removed regardless of success or not. Otherwise we will
+ // have a mmeory leak. The single reason why the operation above could
+ // fail is because there was that no more memory that could be
+ // allocated.
+ //
+ if( removeData == true )
+ {
+ delete [] newData;
+ }
+
+}
+
+
+bool CHexBuffer::inputDummy( unsigned char *dest, int value, uint cell )
+{
+ (void)dest;
+ (void)value;
+ (void)cell;
+ return( false );
+}
+
+
+bool CHexBuffer::inputHexadecimal( unsigned char *dest, int value, uint cell )
+{
+ if( value >= '0' && value <= '9' )
+ {
+ value = value - '0';
+ }
+ else if( value >= 'A' && value <= 'F' )
+ {
+ value = value - 'A' + 10;
+ }
+ else if( value >= 'a' && value <= 'f' )
+ {
+ value = value - 'a' + 10;
+ }
+ else
+ {
+ return( false );
+ }
+
+ if( cell > 1 )
+ {
+ return( false );
+ }
+
+ uint shift = 1 - cell;
+ *dest = (*dest & ~(0xF<<(shift*4)) ) | (value<<(shift*4));
+ return( true );
+}
+
+
+bool CHexBuffer::inputDecimal( unsigned char *dest, int value, uint cell )
+{
+ //
+ // 2000-01-22 Espen Sand
+ // I do the insertion a bit different here since decimal is special
+ // with respect to bitwidths.
+ //
+ if( value < '0' || value > '9' || cell > 2 )
+ {
+ return( false );
+ }
+
+ char buf[4];
+ printDecimalCell( buf, *dest );
+ buf[cell]=value;
+ buf[3]=0;
+
+ int tmp = atoi(buf);
+ if( tmp > 255 )
+ {
+ return( false );
+ }
+
+ *dest = tmp;
+ return( true );
+}
+
+
+bool CHexBuffer::inputOctal( unsigned char *dest, int value, uint cell )
+{
+ if( value >= '0' && value <= '7' )
+ {
+ value = value - '0';
+ if( cell == 0 && value > 3 )
+ {
+ return( false );
+ }
+ }
+ else
+ {
+ return( false );
+ }
+
+ if( cell >= 3 )
+ {
+ return( false );
+ }
+
+ uint shift = 2 - cell;
+ *dest = (*dest & ~(0x7<<(shift*3)) ) | (value<<(shift*3));
+ return( true );
+}
+
+
+bool CHexBuffer::inputBinary( unsigned char *dest, int value, uint cell )
+{
+ if( value >= '0' && value <= '1' )
+ {
+ value = value - '0';
+ }
+ else
+ {
+ return( false );
+ }
+
+ if( cell > 7 )
+ {
+ return( false );
+ }
+
+ uint shift = 7 - cell;
+ *dest = (*dest & ~(1<<shift)) | (value<<shift);
+ return( true );
+}
+
+
+
+bool CHexBuffer::inputAscii( unsigned char *dest, int value, uint )
+{
+ *dest = value;
+ return( true );
+}
+
+
+
+int CHexBuffer::moveBuffer( uint destOffset, uint srcOffset )
+{
+ if( srcOffset > documentSize() || destOffset == srcOffset )
+ {
+ return( Err_Success );
+ }
+
+ if( destOffset < srcOffset )
+ {
+ char *dest = &data()[ destOffset ];
+ char *src = &data()[ srcOffset ];
+
+ memmove( dest, src, documentSize() - srcOffset );
+ setDocumentSize( documentSize() - (srcOffset - destOffset) );
+ return( Err_Success );
+ }
+ else
+ {
+ uint s = documentSize() - srcOffset;
+ if( destOffset + s >= size() )
+ {
+ int errCode = resizeBuffer( destOffset + s );
+ if( errCode != Err_Success )
+ {
+ fatalSound();
+ return( errCode );
+ }
+ }
+ else
+ {
+ setDocumentSize( documentSize() + (destOffset - srcOffset) );
+ }
+
+ char *dest = &data()[ destOffset ];
+ char *src = &data()[ srcOffset ];
+
+ memmove( dest, src, s );
+ memset( src, 0, destOffset - srcOffset );
+ return( Err_Success );
+ }
+}
+
+
+
+
+int CHexBuffer::resizeBuffer( uint newSize )
+{
+ if( newSize < documentSize() )
+ {
+ return( Err_Success );
+ }
+
+ if( newSize >= size() )
+ {
+ QByteArray tmp;
+ tmp.duplicate( data(), size() );
+ if( tmp.isNull() == true )
+ {
+ return( Err_NoMemory );
+ }
+
+ if( fill( '\0', newSize + 100 ) == false )
+ {
+ return( Err_NoMemory );
+ }
+
+ memcpy( data(), &tmp[0], tmp.size() );
+ }
+
+ setDocumentSize( newSize );
+ return( Err_Success );
+}
+
+
+void CHexBuffer::inputSound( void )
+{
+ if( mInputErrorSound == true )
+ {
+ KNotifyClient::beep( QObject::tr("Edit operation failed") );
+ }
+}
+
+
+void CHexBuffer::fatalSound( void )
+{
+ if( mFatalErrorSound == true )
+ {
+ KNotifyClient::beep( QObject::tr("Could not allocate memory") );
+ }
+}
+
+
+int CHexBuffer::printHtmlDataPage( const QString &tocName,
+ const QStringList &fileNames, uint index,
+ const SExportHtml &ex,
+ uint line, uint numLine )
+{
+ if( fileNames.count() == 0 )
+ {
+ return( Err_NullArgument );
+ }
+
+ if( index >= fileNames.count() )
+ {
+ index = fileNames.count()-1;
+ }
+
+ QFile file( fileNames[index] );
+ if( file.open( IO_WriteOnly ) == false )
+ {
+ return( Err_OperationAborted );
+ }
+
+ QTextStream os( &file );
+ const QString *next = index+1 >= fileNames.count() ? 0 : &fileNames[index+1];
+ const QString *prev = index == 0 ? 0 : &fileNames[index-1];
+ const QString *toc = tocName.length() == 0 ? 0 : &tocName;
+
+ printHtmlHeader( os, true );
+ if( ex.navigator == true )
+ {
+ printHtmlNavigator( os, next, prev, toc );
+ }
+
+ printHtmlCaption( os, ex.topCaption, index+1, fileNames.count() );
+ printHtmlTable( os, line, numLine, ex.blackWhite );
+ printHtmlCaption( os, ex.bottomCaption, index+1, fileNames.count() );
+
+ if( ex.navigator == true )
+ {
+ printHtmlNavigator( os, next, prev, toc );
+ }
+ printHtmlHeader( os, false );
+
+ return( Err_Success );
+}
+
+
+void CHexBuffer::printHtmlTocPage( const QString &tocName,
+ const QString &linkName,
+ const QStringList &fileNames,
+ const QStringList &offsets,
+ uint numPage )
+{
+ if( numPage == 0 || fileNames.count() == 0 )
+ {
+ return;
+ }
+ if( numPage >= fileNames.count() )
+ {
+ numPage = fileNames.count() - 1;
+ }
+
+ QFile file( tocName );
+ if( file.open( IO_WriteOnly ) == false )
+ {
+ return;
+ }
+
+ QTextStream os( &file );
+ printHtmlHeader( os, true );
+
+ os << "<P ALIGN=\"CENTER\">" << endl;
+ os << "<B><FONT COLOR=BLACK>" << endl;
+ os << mUrl << endl;
+ os << "</FONT></B></CAPTION>" << endl;
+ os << "</P>" << endl;
+
+ os << "<P ALIGN=\"CENTER\"><TT>" << endl;
+ for( uint i=0; i<=numPage; i++ )
+ {
+ QString n( fileNames[i].right( fileNames[i].length() -
+ fileNames[i].findRev('/') - 1) );
+ os << "<A HREF=\"" << n << "\">" << i18n("Page") << i+1;
+ os << "</A>";
+ os << " " << offsets[i];
+ os << "<br>" << endl;
+ }
+ os << "</P>" << endl;
+
+ printHtmlHeader( os, false );
+
+ if( linkName.isEmpty() == false )
+ {
+ //
+ // Make a symlink. We ignore any error here. I don't consider
+ // it to be fatal.
+ //
+ QString n( tocName.right( tocName.length() - tocName.findRev('/') - 1) );
+ symlink( n.latin1(), linkName.latin1() );
+ }
+
+}
+
+
+
+void CHexBuffer::printHtmlCaption( QTextStream &os, uint captionType,
+ uint curPage, uint numPage )
+{
+ QString caption;
+ switch( captionType )
+ {
+ case 0:
+ return;
+ break;
+
+ case 1:
+ caption = mUrl;
+ break;
+
+ case 2:
+ caption = mUrl.right( mUrl.length() - mUrl.findRev('/') - 1);
+ break;
+
+ case 3:
+ caption = i18n("Page %1 of %2").arg(curPage).arg(numPage);
+ break;
+ }
+
+ os << "<P ALIGN=\"CENTER\">" << endl;
+ os << "<B><FONT COLOR=BLACK>" << endl;
+ os << caption << endl;
+ os << "</FONT></B></CAPTION>" << endl;
+ os << "</P>" << endl;
+}
+
+
+
+void CHexBuffer::printHtmlNavigator( QTextStream &os, const QString *next,
+ const QString *prev, const QString *toc )
+{
+ os << "<TABLE BORDER=\"0\" CELLSPACING=\"0\" WIDTH=\"100%\">" << endl;
+ os << "<TR>" << endl;
+ os << "<TD>" << endl;
+ if( next == 0 )
+ {
+ os << i18n("Next") << " ";
+ }
+ else
+ {
+ QString n( next->right( next->length() - next->findRev('/') - 1) );
+ os << "<A HREF=\"" << n << "\">" << i18n("Next") << "</A>" << " ";
+ }
+
+ if( prev == 0 )
+ {
+ os << i18n("Previous") << " ";
+ }
+ else
+ {
+ QString p( prev->right( prev->length() - prev->findRev('/') - 1) );
+ os << "<A HREF=\"" << p << "\">" << i18n("Previous") << "</A>" << " ";
+ }
+
+ if( toc == 0 )
+ {
+ os << i18n("Contents") << " ";
+ }
+ else
+ {
+ QString t( toc->right( toc->length() - toc->findRev('/') - 1) );
+ os << "<A HREF=\"" << t << "\">" << i18n("Contents");
+ os << "</A>" << " ";
+ }
+
+ os << "</TD>" << endl;
+
+ os << "<TD ALIGN=\"RIGHT\">" << endl;
+ os << "<A HREF=\"" << "http://home.sol.no/~espensa/khexedit" << "\">";
+ os << i18n("Generated by khexedit");
+ os << "</A>" << " ";
+
+ os << "</TD>" << endl;
+ os << "</TR>" << endl << "</TABLE>" << endl;
+}
+
+
+int CHexBuffer::printHtmlHeader( QTextStream &os, bool isFront )
+{
+ if( isFront == true )
+ {
+ os << "<HTML>" << endl << "<HEAD>" << endl;
+ os << "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; ";
+ os << "charset=iso-8859-1\">" << endl;
+ os << "<META NAME=\"hexdata\" CONTENT=\"khexedit dump\">" << endl;
+ os << "</HEAD>" << endl << "<BODY>" << endl;
+ }
+ else
+ {
+ os << "</BODY>" << endl << "</HTML>" << endl;
+ }
+
+ return( Err_Success );
+}
+
+
+int CHexBuffer::printHtmlTable( QTextStream &os, uint line, uint numLine,
+ bool bw )
+{
+ uint i;
+ QColor color;
+
+
+ int numCol = 1;
+ if( mLayout.offsetVisible == true ) { numCol += 1; }
+ if( mLayout.secondaryMode != SDisplayLayout::hide ) { numCol += 1; }
+
+ os << "<TABLE BORDER=1 COLS=" << numCol << " WIDTH=\"100%\" ";
+ os << "CELLSPACING=0 CELLPADDING=2>" << endl;
+ if( mLayout.offsetVisible == true )
+ {
+ color = bw == true ? Qt::white : mColor.offsetBg;
+ os << "<TD BGCOLOR=" << color.name().latin1() << ">" << endl;
+ os << "<TABLE BORDER=0 COLS=1 WIDTH=\"100%\" ";
+ os << "CELLSPACING=0 CELLPADDING=2>" << endl;
+
+ color = bw == true ? Qt::black : mColor.offsetFg;
+ for( i=0; i<numLine; i++ )
+ {
+ os << "<TR><TD><TT><b><FONT COLOR=" << color.name().latin1() << ">";
+ THIS_FPTR(printOffset)( mPrintBuf, (line+i)*mLayout.lineSize );
+ mPrintBuf[mOffsetSize]=0;
+ os << mPrintBuf << "</TD></TR>" << endl;
+ }
+ os << "</TABLE>" << endl << "</TD>" << endl;
+ }
+
+ color = bw == true ? Qt::white : mColor.textBg;
+ os << "<TD BGCOLOR=" << color.name().latin1() << ">" << endl;
+ os << "<TABLE BORDER=0 COLS=1 WIDTH=\"100%\" ";
+ os << "CELLSPACING=0 CELLPADDING=2>" << endl;
+ for( i=0; i<numLine; i++ )
+ {
+ printHtmlLine( os, line+i, true, bw );
+ }
+ os << "</TABLE>" << endl << "</TD>" << endl;
+
+ if( mLayout.secondaryMode != SDisplayLayout::hide )
+ {
+ color = bw == true ? Qt::white : mColor.textBg;
+ os << "<TD BGCOLOR=" << color.name().latin1() << ">" << endl;
+ os << "<TABLE BORDER=0 COLS=1 WIDTH=\"100%\" ";
+ os << "CELLSPACING=0 CELLPADDING=2>" << endl;
+ for( i=0; i<numLine; i++ )
+ {
+ printHtmlLine( os, line+i, false, bw );
+ }
+ os << "</TABLE>" << endl << "</TD>" << endl;
+ }
+
+ os << "</TR>" << endl << "</TABLE>" << endl;
+ return( Err_Success );
+}
+
+
+int CHexBuffer::printHtmlLine( QTextStream &os, uint line, bool isPrimary,
+ bool bw )
+{
+ uint offset = line * mLayout.lineSize;
+ QColor prevColor;
+
+ QColor color;
+ if( bw == true )
+ {
+ color = Qt::white;
+ }
+ else
+ {
+ color = (line+1) % 2 ? mColor.textBg : mColor.secondTextBg;
+ }
+
+ os << "<TR><TD NOWRAP BGCOLOR=" << color.name().latin1() << "><TT><B>"
+ << endl;
+ if( offset >= documentSize() )
+ {
+ os << "<BR></TD></TR>" << endl;
+ return( Err_Success );
+ }
+
+ for( uint i=0; i < mLayout.lineSize; i++ )
+ {
+ if( isPrimary == true )
+ {
+ if( offset+i >= documentSize() )
+ {
+ memset(mPrintBuf, ' ', mNumCell );
+ mPrintBuf[mNumCell] = 0;
+ if( i == 0 )
+ {
+ color = bw == true ? Qt::black : foregroundColor(i);
+ }
+ else
+ {
+ color = prevColor;
+ }
+ }
+ else
+ {
+ unsigned char val = (unsigned char)data()[offset+i];
+ if( THIS_FPTR(printCell)( mPrintBuf, val ) == 0 )
+ {
+ color = bw == true ? Qt::black : foregroundColor(i);
+ }
+ else
+ {
+ color = bw == true ? Qt::black : mColor.nonPrintFg;
+ }
+ }
+ mPrintBuf[mNumCell] = 0;
+ if( i == 0 )
+ {
+ os << "<FONT COLOR=" << color.name().latin1() << ">";
+ }
+ else if( color != prevColor )
+ {
+ os << "</FONT><FONT COLOR=" << color.name().latin1() << ">";
+ }
+ prevColor = color;
+
+ if( mPrintBuf[0] == '<' )
+ {
+ os << "&lt;";
+ }
+ else
+ {
+ os << mPrintBuf;
+ if( (i+1) % mLayout.columnSize == 0 && (i+1) != mLayout.lineSize )
+ {
+ os << " ";
+ }
+ }
+ }
+ else
+ {
+ if( offset+i >= documentSize() )
+ {
+ memset(mPrintBuf, ' ', 1 );
+ if( i == 0 )
+ {
+ color = bw == true ? Qt::black : mColor.secondaryFg;
+ }
+ else
+ {
+ color = prevColor;
+ }
+ }
+ else
+ {
+ unsigned char val = (unsigned char)data()[offset+i];
+ if( printAsciiCell( mPrintBuf, val ) == 0 )
+ {
+ color = bw == true ? Qt::black : mColor.secondaryFg;
+ }
+ else
+ {
+ color = bw == true ? Qt::black : mColor.nonPrintFg;
+ }
+ mPrintBuf[1] = 0;
+
+ if( i == 0 )
+ {
+ os << "<FONT COLOR=" << color.name().latin1() << ">";
+ }
+ else if( color != prevColor )
+ {
+ os << "</FONT><FONT COLOR=" << color.name().latin1() << ">";
+ }
+ prevColor = color;
+
+ mPrintBuf[1] = 0;
+ os << (mPrintBuf[0] == '<' ? "&lt;" : mPrintBuf);
+ }
+
+ }
+ }
+ os << "</TD></TR>" << endl;
+ return( Err_Success );
+}
+
+
+
+
+
diff --git a/khexedit/hexbuffer.h b/khexedit/hexbuffer.h
new file mode 100644
index 0000000..ea11d95
--- /dev/null
+++ b/khexedit/hexbuffer.h
@@ -0,0 +1,2040 @@
+/*
+ * khexedit - Versatile hex editor
+ * Copyright (C) 1999-2000 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.
+ *
+ */
+
+#ifndef _HEX_BUFFER_H_
+#define _HEX_BUFFER_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <iostream>
+#include <time.h>
+
+#include <qbitarray.h>
+#include <qdatetime.h>
+#include <qfile.h>
+#include <qfont.h>
+#include <qptrlist.h>
+#include <qpainter.h>
+#include <qstring.h>
+#include <qtextstream.h>
+
+#include <kapplication.h>
+
+#include "conversion.h"
+#include "hexeditstate.h"
+#include "hexprinter.h"
+#include "progress.h"
+
+//
+// Marco to simplify usage of function pointers
+//
+#define THIS_FPTR( func ) ((this->*func))
+
+struct SSearchControl
+{
+ QByteArray key;
+ QByteArray val;
+ uint keyType;
+ bool fromCursor;
+ bool inSelection;
+ bool forward;
+ bool ignoreCase;
+ bool match;
+ uint numReplace;
+
+ bool wrapValid;
+ bool wrapActive;
+ uint wrapMark;
+};
+
+
+struct SFilterControl
+{
+ enum Operation
+ {
+ OperandAndData = 0,
+ OperandOrData,
+ OperandXorData,
+ InvertData,
+ ReverseData,
+ RotateData,
+ ShiftData,
+ SwapBits
+ };
+
+ int execute( uchar *dest, uchar *src, uint size );
+
+
+ QByteArray operand;
+ int rotate[2];
+ Operation operation;
+ bool fromCursor;
+ bool inSelection;
+ bool forward;
+};
+
+
+struct SInsertData
+{
+ uint size;
+ QByteArray pattern;
+ uint offset;
+ bool repeatPattern;
+ bool onCursor;
+};
+
+
+struct SExportRange
+{
+ enum EMode
+ {
+ All = 0,
+ Selection,
+ Range
+ };
+
+ EMode mode;
+ uint start;
+ uint stop;
+};
+
+
+struct SExportText
+{
+ SExportRange range;
+ QString destFile;
+};
+
+
+struct SExportHtml
+{
+ SExportRange range;
+ QString package;
+ QString prefix;
+ uint linePerPage;
+ uint topCaption;
+ uint bottomCaption;
+ bool symLink;
+ bool navigator;
+ bool blackWhite;
+};
+
+
+struct SExportCArray
+{
+ enum ElementType
+ {
+ Char = 0,
+ Uchar,
+ Short,
+ Ushort,
+ Int,
+ Uint,
+ Float,
+ Double
+ };
+
+ const char *printFormatted( const char *b, uint maxSize ) const;
+ QString variableName( uint range ) const;
+ int elementSize( void ) const;
+
+ SExportRange range;
+ QString destFile;
+ QString arrayName;
+ int elementType;
+ uint elementPerLine;
+ bool unsignedAsHexadecimal;
+};
+
+
+struct SStatisticControl
+{
+ SStatisticControl( void )
+ {
+ memset( occurrence, 0, sizeof(occurrence) );
+ documentSize = 0;
+ }
+
+ uint documentSize;
+ uint occurrence[256];
+ QString documentName;
+};
+
+
+struct SPagePosition
+{
+ SPagePosition( time_t now, uint numLine, uint linePerPage )
+ {
+ init( now, numLine, linePerPage );
+ }
+
+ SPagePosition( void )
+ {
+ init( 0, 1, 1 );
+ }
+
+ void init( time_t at, uint numLine, uint linePerPage )
+ {
+ if( linePerPage == 0 ) { linePerPage = 1; }
+
+ now = at;
+ curPage = 1;
+ maxPage = numLine / linePerPage + (numLine % linePerPage ? 1 : 0);
+ if( maxPage < curPage ) { maxPage = curPage; }
+ }
+
+ void step( uint stepSize=1 )
+ {
+ curPage += stepSize;
+ if( curPage > maxPage ) { curPage = maxPage; }
+ }
+
+ uint current( void )
+ {
+ return( curPage );
+ }
+
+ uint max( void )
+ {
+ return( maxPage );
+ }
+
+ uint curPage;
+ uint maxPage;
+ time_t now;
+};
+
+
+
+class CStringCollectControl
+{
+ public:
+ CStringCollectControl( void )
+ {
+ mList.setAutoDelete( true );
+ }
+
+ int add( uint offset, const QByteArray &a )
+ {
+ QString *s = new QString();
+ if( s == 0 )
+ {
+ return( Err_NoMemory );
+ }
+
+ if( decimalOffset == true )
+ {
+ s->sprintf( "%010u", offset );
+ }
+ else
+ {
+ s->sprintf( "%04x:%04x", offset>>16, offset&0x0000FFFF );
+ }
+
+ *s += QString( a );
+
+ mList.append( s );
+ return( Err_Success );
+ }
+
+ uint offsetLen( void )
+ {
+ return( decimalOffset ? 10 : 9 );
+ }
+
+ void clear( void )
+ {
+ mList.clear();
+ }
+
+ const QString *get( uint index )
+ {
+ return( mList.at( index ) );
+ }
+
+ int count( void )
+ {
+ return( mList.count() );
+ }
+
+ QPtrList<QString> &list( void )
+ {
+ return( mList );
+ }
+
+ public:
+ uint minLength;
+ bool decimalOffset;
+ bool allow8bit;
+
+ private:
+ QPtrList<QString> mList;
+};
+
+
+
+
+
+
+struct SCursorConfig
+{
+ SCursorConfig( void )
+ {
+ state = 0;
+ }
+
+ bool selectOn( void )
+ {
+ return( state & Qt::ShiftButton );
+ }
+
+ bool removeSelection( void )
+ {
+ return( state & Qt::ShiftButton ? false : true );
+ }
+
+ void setKeepSelection( bool val )
+ {
+ state = val == true ? state|Qt::ShiftButton : state&~Qt::ShiftButton;
+ }
+
+ bool controlButton( void )
+ {
+ return( state & Qt::ControlButton ? true : false );
+ }
+
+ bool shiftButton( void )
+ {
+ return( state & Qt::ShiftButton ? true : false );
+ }
+
+ bool altButton( void )
+ {
+ return( state & Qt::AltButton ? true : false );
+ }
+
+
+ void emulateControlButton( bool val )
+ {
+ state = val == true ? state|Qt::ControlButton : state&~Qt::ControlButton;
+ }
+
+ int state;
+};
+
+
+
+struct SCursorSpec
+{
+ enum EShape
+ {
+ solid = 0,
+ frame,
+ thin
+ };
+
+ void reset( void )
+ {
+ offset = 0;
+ x1 = x2 = y = cell = maxCell = 0;
+ }
+
+ void setShape( EShape primaryShape, EShape secondaryShape, uint unitWidth,
+ uint numCell )
+ {
+
+ if( primaryShape == thin )
+ {
+ if( onlyBlock == true ) { primaryShape = solid; }
+ }
+ if( secondaryShape == thin )
+ {
+ if( onlyBlock == true ) { secondaryShape = solid; }
+ }
+
+ mPrimaryShape = primaryShape;
+ if( mPrimaryShape == solid )
+ {
+ drawWidth1 = unitWidth;
+ drawOffset1 = 0;
+ }
+ else if( mPrimaryShape == frame )
+ {
+ drawWidth1 = unitWidth * numCell;
+ drawOffset1 = 0;
+ }
+ else
+ {
+ mPrimaryShape = thin;
+ if( thickState == true )
+ {
+ drawWidth1 = 2;
+ drawOffset1 = -1;
+ }
+ else
+ {
+ drawWidth1 = 5;
+ drawOffset1 = -3;
+ }
+ }
+
+ mSecondaryShape = secondaryShape;
+ if( mSecondaryShape == solid )
+ {
+ drawWidth2 = unitWidth;
+ drawOffset2 = 0;
+ }
+ else if( mSecondaryShape == frame )
+ {
+ drawWidth2 = unitWidth * numCell;
+ drawOffset2 = 0;
+ }
+ else
+ {
+ mSecondaryShape = thin;
+ if( thickState == true )
+ {
+ drawWidth2 = 2;
+ drawOffset2 = -1;
+ }
+ else
+ {
+ drawWidth2 = 5;
+ drawOffset2 = -3;
+ }
+ }
+ }
+
+ void setShapeModifier( bool alwaysBlock, bool useThick )
+ {
+ onlyBlock = alwaysBlock;
+ thickState = useThick;
+ }
+
+ void dump( void )
+ {
+ std::cout << "offset: " << offset << " y: " << y << " x1: " << x1 << std::endl;
+ std::cout << "x2: " << x2 << " cell: " << cell << std::endl;
+ }
+
+ bool inside( uint min, uint max )
+ {
+ return( offset >= min && offset < max );
+ }
+
+ int drawX1( void )
+ {
+ return( x1 + drawOffset1 );
+ }
+
+ int drawX2( void )
+ {
+ return( x2 + drawOffset2 );
+ }
+
+ int width1( void )
+ {
+ return( drawWidth1 );
+ }
+
+ int width2( void )
+ {
+ return( drawWidth2 );
+ }
+
+ uint offset;
+ int y;
+ int x1;
+ int x2;
+ int cell;
+ int maxCell;
+ bool onlyBlock;
+ bool thickState;
+
+ char data;
+
+ int mPrimaryShape;
+ int mSecondaryShape;
+ int drawWidth1;
+ int drawWidth2;
+ int drawOffset1;
+ int drawOffset2;
+};
+
+
+struct SCursor
+{
+ SCursor( void )
+ {
+ mLineSize = 1;
+ mDocumentSize = 0;
+ mFixedSizeMode = false;
+ mArea = 0;
+ }
+
+ void reset( void )
+ {
+ prev.reset();
+ curr.reset();
+ next.reset();
+ }
+
+ void setDocumentSize( uint documentSize )
+ {
+ mDocumentSize = documentSize;
+ }
+
+ void setFixedSizeMode( bool fixedSizeMode )
+ {
+ mFixedSizeMode = fixedSizeMode;
+ }
+
+ bool incCell( void )
+ {
+ if( curr.cell + 1 >= curr.maxCell )
+ {
+ addOffset( 1 );
+ return( true );
+ }
+ else
+ {
+ next.cell = curr.cell + 1;
+ return( false );
+ }
+ }
+
+ bool decCell( void )
+ {
+ if( curr.cell == 0 )
+ {
+ if( curr.offset > 0 )
+ {
+ decOffset( 1, true );
+ next.cell = curr.maxCell > 0 ? curr.maxCell - 1 : 0;
+ }
+ return( true );
+ }
+ else
+ {
+ next.cell = curr.cell - 1;
+ return( false );
+ }
+ }
+
+ void resetCell( void )
+ {
+ next.cell = 0;
+ }
+
+
+ void addOffset( uint val )
+ {
+ setOffset( curr.offset + val );
+ }
+
+ void decOffset( uint val, bool ignoreCell )
+ {
+ if( ignoreCell == true || curr.cell == 0 )
+ {
+ setOffset( val > curr.offset ? curr.offset%mLineSize : curr.offset-val);
+ }
+ else
+ {
+ setOffset( curr.offset );
+ }
+ }
+
+ void setOffset( uint offset )
+ {
+ /*
+ if( offset >= mDocumentSize )
+ {
+ if( mFixedSizeMode == true )
+ {
+ offset = mDocumentSize > 0 ? mDocumentSize - 1 : 0;
+ }
+ else
+ {
+ offset = mDocumentSize;
+ }
+ }
+ */
+
+ next.offset = offset;
+ next.cell = 0;
+ }
+
+ uint getOffset( void )
+ {
+ return( curr.offset );
+ }
+
+ void setOffset( uint offset, uint bit, bool backward, bool fromCursor,
+ uint textSize )
+ {
+ if( fromCursor == true )
+ {
+ if( backward == true )
+ {
+ setOffset( offset > curr.offset ? 0 : curr.offset - offset );
+ }
+ else
+ {
+ setOffset( curr.offset + offset );
+ }
+ }
+ else
+ {
+ if( backward == true )
+ {
+ setOffset( offset > textSize ? 0 : textSize - offset );
+ }
+ else
+ {
+ setOffset( offset > textSize ? textSize : offset );
+ }
+ }
+ setBit( bit );
+ }
+
+
+ void setBit( uint bit )
+ {
+ bit = (bit > 7) ? 0 : 7 - bit;
+ next.cell = bit / mCellWeight;
+ }
+
+
+ void home( bool toExtreme )
+ {
+ if( toExtreme == true )
+ {
+ setOffset( 0 );
+ }
+ else
+ {
+ setOffset( next.offset - curr.offset % mLineSize );
+ }
+ }
+
+ void end( bool toExtreme )
+ {
+ uint maxOffset;
+ if( mFixedSizeMode == true )
+ {
+ maxOffset = mDocumentSize > 0 ? mDocumentSize-1 : mDocumentSize;
+ }
+ else
+ {
+ maxOffset = mDocumentSize;
+ }
+
+ if( toExtreme == true )
+ {
+ setOffset( maxOffset );
+ }
+ else
+ {
+ uint newOffset = next.offset + (mLineSize-1) - curr.offset % mLineSize;
+ setOffset( newOffset > maxOffset ? maxOffset : newOffset );
+ }
+
+ }
+
+ void up( uint numLines )
+ {
+ decOffset( numLines * mLineSize, true );
+ }
+
+ void down( uint numLines )
+ {
+ addOffset( numLines * mLineSize );
+ }
+
+ bool changed( void )
+ {
+ return( prev.offset != curr.offset || prev.cell != curr.cell ||
+ prev.data != curr.data ? true : false );
+ }
+
+ uint bit( void )
+ {
+ uint bitValue = mCellWeight*(curr.maxCell - curr.cell) - 1;
+ return( bitValue > 7 ? 7 : bitValue );
+ }
+
+ uint cellWeight( void )
+ {
+ return( mCellWeight );
+ }
+
+ void setLineSize( uint lineSize )
+ {
+ mLineSize = lineSize < 1 ? 1 : lineSize;
+ }
+
+ void setCellWeight( uint cellWeight )
+ {
+ mCellWeight = cellWeight;
+ }
+
+ int area( void )
+ {
+ return( mArea );
+ }
+
+ void setArea( int area )
+ {
+ mArea = area;
+ }
+
+ void setShape( SCursorSpec::EShape primary, SCursorSpec::EShape secondary,
+ uint unitWidth, uint numCell )
+ {
+ curr.setShape( primary, secondary, unitWidth, numCell );
+ }
+
+ void setShapeModifier( bool alwaysBlock, bool useThick )
+ {
+ curr.setShapeModifier( alwaysBlock, useThick );
+ }
+
+ uint mLineSize;
+ uint mDocumentSize;
+ uint mCellWeight;
+ int mArea;
+ bool mFixedSizeMode;
+ SCursorSpec prev;
+ SCursorSpec curr;
+ SCursorSpec next;
+};
+
+
+struct SCursorPosition
+{
+ int x;
+ int y;
+ int w;
+ int h;
+};
+
+struct SCursorOffset
+{
+ uint offset;
+ uint bit;
+};
+
+
+struct SSelectSpec
+{
+ void init( uint offset )
+ {
+ start = stop = anchor = offset;
+ }
+
+ void set( uint offset )
+ {
+ if( offset < anchor )
+ {
+ start = offset;
+ stop = anchor;
+ }
+ else
+ {
+ stop = offset;
+ start = anchor;
+ }
+ }
+
+ void expand( uint value )
+ {
+ if( anchor == stop ) { anchor +=value; }
+ stop += value;
+ //set( stop + value );
+ }
+
+ void shrink( uint value )
+ {
+ uint newVal = start + value > stop ? start : stop - value;
+ if( anchor == stop ) { anchor = newVal; }
+ stop = newVal;
+ /*
+ if( start + value > stop )
+ {
+ set( start );
+ }
+ else
+ {
+ set( stop - value );
+ }
+ */
+ }
+
+
+ uint start;
+ uint stop;
+ uint anchor;
+};
+
+
+struct SSelect
+{
+ SSelect( void )
+ {
+ reset();
+ }
+
+ bool init( uint offset )
+ {
+ curr.init( offset );
+ if( isValid == true )
+ {
+ isValid = false;
+ return( true );
+ }
+ else
+ {
+ return( false );
+ }
+ }
+
+ void reset( void )
+ {
+ curr.init( 0 );
+ isValid = false;
+ }
+
+ bool set( uint offset )
+ {
+ isValid = true;
+
+ curr.set( offset );
+ if( curr.start != prev.start || curr.stop != prev.stop )
+ {
+ return( true );
+ }
+ else
+ {
+ return( false );
+ }
+ }
+
+ void expand( uint value )
+ {
+ if( isValid == false )
+ {
+ return;
+ }
+ curr.expand( value );
+ }
+
+ void shrink( uint value )
+ {
+ if( isValid == false )
+ {
+ return;
+ }
+ curr.shrink( value );
+ }
+
+
+ void sync( void )
+ {
+ prev = curr;
+ }
+
+ bool inside( uint offset )
+ {
+ return( isValid == true && offset >= curr.start && offset < curr.stop );
+ }
+
+ bool inside( uint offset, uint range )
+ {
+ return( isValid == true && (offset + range) >= curr.start &&
+ offset < curr.stop );
+ }
+
+ bool verify( uint &start, uint &stop )
+ {
+ if( isValid == false )
+ {
+ return( false );
+ }
+
+ if( start < curr.start ) { start = curr.start; }
+ if( stop > curr.stop ) { stop = curr.stop; }
+ return( true );
+ }
+
+ uint start( uint offset )
+ {
+ //
+ // If 'curr.star' is smaller than 'offset' then the start is at
+ // the start of line.
+ //
+ return( curr.start < offset ? 0 : curr.start - offset );
+ }
+
+ uint start( void )
+ {
+ return( curr.start );
+ }
+
+ uint stop( uint offset, uint range )
+ {
+ return( curr.stop > offset + range ? range : curr.stop - offset );
+ }
+
+ uint stop( void )
+ {
+ return( curr.stop );
+ }
+
+ bool valid( void )
+ {
+ return( isValid );
+ }
+
+ uint size( void )
+ {
+ if( isValid == false )
+ {
+ return( 0 );
+ }
+ else
+ {
+ return( curr.start >= curr.stop ? 0 : curr.stop - curr.start );
+ }
+ }
+
+ void startChange( uint &first, uint &last )
+ {
+ if( curr.start <= prev.start )
+ {
+ first = curr.start;
+ last = prev.start;
+ }
+ else
+ {
+ first = prev.start;
+ last = curr.start;
+ }
+ }
+
+ void stopChange( uint &first, uint &last )
+ {
+ if( curr.stop <= prev.stop )
+ {
+ first = curr.stop;
+ last = prev.stop;
+ }
+ else
+ {
+ first = prev.stop;
+ last = curr.stop;
+ }
+ }
+
+
+ bool isValid;
+ SSelectSpec prev;
+ SSelectSpec curr;
+};
+
+
+
+class CHexAction
+{
+ public:
+ enum HexAction
+ {
+ replace
+ };
+
+ public:
+ CHexAction( HexAction action, uint offset );
+ ~CHexAction( void );
+ void setData( uint size, char *data, uint dataSize );
+
+ public:
+ HexAction mAction;
+ uint mOffset;
+ uint mSize;
+ char *mData;
+ uint mDataSize;
+ CHexAction *mNext;
+};
+
+class CHexActionGroup
+{
+ public:
+ CHexActionGroup( uint startOffset, uint startBit );
+ ~CHexActionGroup( void );
+ void insertAction( CHexAction *hexAction );
+
+ public:
+ uint mStartOffset;
+ uint mStopOffset;
+ uint mStartBit;
+ uint mStopBit;
+ CHexAction *mHexAction;
+};
+
+
+
+struct SCursorState
+{
+ bool valid;
+ uint selectionOffset;
+ uint selectionSize;
+ uint offset;
+ uint cell;
+ unsigned char data[8];
+ uint undoState;
+ bool charValid;
+};
+
+struct SFileState
+{
+ bool valid;
+ uint size;
+ bool modified;
+};
+
+
+
+
+
+class CHexBuffer;
+typedef int (CHexBuffer::*PrintCellFunc)( char *buf, unsigned char data );
+typedef bool (CHexBuffer::*InputCellFunc)( unsigned char *dest, int value,
+ uint cell );
+typedef void (CHexBuffer::*PrintOffsetFunc)( char *buf, uint offset );
+
+
+class CHexBuffer : public QByteArray
+{
+ public:
+ enum EColumn
+ {
+ VisibleColumn = 0x0,
+ OffsetColumn = 0x1,
+ PrimaryColumn = 0x2,
+ SecondaryColumn = 0x4,
+ EveryColumn = 0x7
+ };
+
+ enum EEditArea
+ {
+ edit_none = 0,
+ edit_primary,
+ edit_secondary
+ };
+
+ enum ECursorMode
+ {
+ cursor_curr = 0,
+ cursor_prev
+ };
+
+ enum EEditMode
+ {
+ EditInsert = 0,
+ EditReplace
+ };
+
+ enum EUndoState
+ {
+ UndoOk = 1,
+ RedoOk = 2
+ };
+
+ public:
+ CHexBuffer( void );
+ ~CHexBuffer( void );
+
+ int setLayout( SDisplayLayout &layout );
+ void setColor( SDisplayColor &color );
+ void setInputMode( SDisplayInputMode &mode );
+ bool toggleEditor( void );
+
+ bool matchWidth( uint width );
+
+ void setNonPrintChar( QChar nonPrintChar );
+ void setShowCursor( bool showCursor );
+ void setDisableCursor( bool disableCursor );
+ void setCursorShapeModifier( bool alwaysBlock, bool thickInsert );
+ void setEditMode( EEditMode editMode );
+ void setEditMode( EEditMode editMode, bool alwaysBlock, bool thickInsert );
+ void setMaximumSize( uint size );
+ void setDocumentSize( uint size );
+ void setUndoLevel( uint level );
+ void setSoundState( bool inputSound, bool fatalSound );
+ void setBookmarkVisibility( bool showInColumn, bool showInEditor );
+
+ void setFont( const SDisplayFontInfo &fontInfo );
+ int setEncoding( CConversion::EMode mode, CProgress &p );
+
+ bool setCursorPosition( int x, int y, bool init, bool cellLevel );
+
+ int readFile( QFile &file, const QString &url, CProgress &p );
+ int insertFile( QFile &file, CProgress &p );
+ int writeFile( QFile &file, CProgress &p );
+ int newFile( const QString &url );
+ void closeFile( void );
+ void registerDiskModifyTime( const QFile &file );
+
+ bool changedOnDisk( void );
+
+ void drawText( QPainter &paint, uint line, int sx, int x, int w );
+ void drawText( QPainter &paint, uint line, int x1, int x2, int y,
+ bool useBlackWhite );
+
+ void drawHeader( QPainter &paint, int sx, int width, int y, bool isFooter,
+ const SPageHeader &header,const SPagePosition &position );
+ int headerHeight( QPainter &paint );
+ int headerMargin( QPainter &paint );
+
+ bool inputAtCursor( QChar c );
+ int inputAtCursor( const QByteArray &buf, uint oldSize );
+ bool removeAtCursor( bool beforeCursor );
+
+ int locateRange( const SExportRange &range, uint &start, uint &stop );
+ int exportText( const SExportText &ex, CProgress &p );
+ int exportHtml( const SExportHtml &ex, CProgress &p );
+ int exportCArray( const SExportCArray &ex, CProgress &p );
+ int copySelectedText( QByteArray &array, int columnSegment=VisibleColumn);
+ int copyAllText( QByteArray &array );
+ int copyText( QByteArray &array, const SExportRange &range,
+ int columnSegment );
+ int copySelectedData( QByteArray &array );
+
+ uint numPage( CHexPrinter &printer );
+ int print( CHexPrinter &printer, CProgress &p );
+
+ uint printLine( char *dst, uint line );
+ uint printLine( char *dst, uint line, int columnSegment );
+
+ bool cutSelection( void );
+ bool undo( void );
+ bool redo( void );
+ int addBookmark( int position );
+ bool removeBookmark( int position );
+ void updateBookmarkMap( bool resize );
+
+ int findFirst( SSearchControl &sc );
+ int findNext( SSearchControl &sc );
+ int findWrap( SSearchControl &sc );
+ int replaceAll( SSearchControl &sc, bool init );
+ int replaceMarked( SSearchControl &sc );
+ int filter( SFilterControl &fc );
+ int collectStrings( CStringCollectControl &sc );
+ int collectStatistic( SStatisticControl &sc, CProgress &p );
+
+ void doActionGroup( CHexActionGroup *group );
+ void doAction( CHexAction *action );
+
+ inline SCursorState &cursorState( void );
+ inline void valueOnCursor( QByteArray &buf, uint size );
+ inline SFileState &fileState( void );
+ inline const SDisplayLayout &layout( void );
+
+ inline const SDisplayInputMode &inputMode( void );
+ inline QPtrList<SCursorOffset> &bookmarkList( void );
+
+ inline bool documentPresent( void );
+ inline bool modified( void );
+ inline uint undoState( void );
+ inline uint documentSize( void );
+ inline EEditMode editMode( void );
+ inline const SEncodeState &encoding( void );
+ inline bool losslessEncoding( CConversion::EMode mode );
+
+ inline QString &url( void );
+ bool hasFileName( void );
+ inline void setUrl( const QString &url );
+ inline void setModified( bool modified );
+ inline const QDateTime &diskModifyTime( void );
+
+
+
+ inline uint calculateLine( uint offset );
+ inline int lineSize( void );
+ inline int lineHeight( void );
+ inline int fontAscent( void );
+ inline int lineWidth( void );
+ inline int unitWidth( void );
+ inline int numLines( void );
+ inline int totalHeight( void );
+ inline const QFont &font( void );
+ inline SCursor *textCursor( void );
+ inline const QColor &backgroundColor( void );
+ inline int startX( void );
+ inline int startY( void );
+ inline void setStartX( int val );
+ inline void setStartY( int val );
+
+ inline bool selectionSet( uint offset, bool init );
+ inline void selectionSyncronize( void );
+ inline void selectionStartChange( uint &offset1, uint &offset2 );
+ inline void selectionStopChange( uint &offset1, uint &offset2 );
+ inline bool cursorInsideSelection( void );
+
+ inline void markSet( uint offset, uint size );
+ inline bool markSet( uint offset, bool init );
+ inline bool markRemove( void );
+ inline void markSyncronize( void );
+ inline void markStartChange( uint &offset1, uint &offset2 );
+ inline void markStopChange( uint &offset1, uint &offset2 );
+
+ inline uint cursorOffset( void );
+ inline uint cursorBit( void );
+ inline uint cursorLine( void );
+ inline uint prevCursorLine( void );
+ inline SCursor &cursor( void );
+
+ inline void currCursor( EEditArea editArea, SCursorPosition &p );
+ inline void prevCursor( EEditArea editArea, SCursorPosition &p );
+
+ inline void cursorUp( uint lines );
+ inline void cursorDown( uint lines );
+ inline void cursorRight( bool cellLevel );
+ inline void cursorLeft( bool cellLevel );
+ inline void cursorStep( uint size, bool forward, bool modulo );
+ inline void cursorHome( bool toExtreme );
+ inline void cursorEnd( bool toExtreme );
+ inline void cursorGoto( uint offset, uint bit );
+ inline void cursorGoto( uint offset, uint bit, bool backward,
+ bool fromCursor );
+ inline bool cursorChanged( void );
+ inline void cursorResetEditArea( void );
+ inline bool cursorPrimaryEdit( void );
+ inline int cursorFixedPosition( int position, int height );
+ inline int cursorChangePosition( int position, int height );
+ void cursorReset( void );
+
+ private:
+ enum { BookmarkOnLine = 0x01, BookmarkOnCursor = 0x02 };
+
+ void computeLineWidth( void );
+ void computeNumLines( void );
+ void cursorCompute( void );
+
+ void drawSelection( QPainter &paint, QColor &color, uint start, uint stop,
+ int sx );
+ int drawBookmarks(QPainter &paint, uint line, int startx);
+ void drawCursor( QPainter &paint, uint line, int startx, bool onBookmark );
+
+ void recordStart( SCursor &cursor );
+ void recordReplace( SCursor &cursor, uint size, char *data, uint dataSize);
+ void recordEnd( SCursor &cursor );
+ void doReplace( CHexAction *hexAction, bool removeData );
+ int scanData( SSearchControl &sc, bool init );
+ int initScanData( SSearchControl &sc );
+
+ inline const QColor &foregroundColor( uint column );
+ inline int printDummyCell( char *buf, unsigned char data );
+ inline int printHexadecimalBigCell( char *buf, unsigned char data );
+ inline int printHexadecimalSmallCell( char *buf, unsigned char data );
+ inline int printDecimalCell( char *buf, unsigned char data );
+ inline int printOctalCell( char *buf, unsigned char data );
+ inline int printBinaryCell( char *buf, unsigned char data );
+ inline int printAsciiCell( char *buf, unsigned char data );
+ inline void printDummyOffset( char *buf, uint offset );
+ inline void printHexadecimalBigOffset( char *buf, uint offset );
+ inline void printHexadecimalSmallOffset( char *buf, uint offset );
+ inline void printDecimalOffset( char *buf, uint offset );
+
+ bool inputDummy( unsigned char *dest, int value, uint cell );
+ bool inputHexadecimal( unsigned char *dest, int value, uint cell );
+ bool inputDecimal( unsigned char *dest, int value, uint cell );
+ bool inputOctal( unsigned char *dest, int value, uint cell );
+ bool inputBinary( unsigned char *dest, int value, uint cell );
+ bool inputAscii( unsigned char *dest, int value, uint cell );
+
+ int moveBuffer( uint destOffset, uint srcOffset );
+ int resizeBuffer( uint offset );
+
+ void inputSound( void );
+ void fatalSound( void );
+
+ int printHtmlDataPage( const QString &tocName,
+ const QStringList &fileNames, uint index,
+ const SExportHtml &ex, uint line, uint numLine );
+ void printHtmlCaption( QTextStream &os, uint captionType, uint curPage,
+ uint numPage );
+ void printHtmlNavigator( QTextStream &os, const QString *next,
+ const QString *prev, const QString *toc );
+ void printHtmlTocPage( const QString &tocName,
+ const QString &linkName,
+ const QStringList &fileNames,
+ const QStringList &offsets, uint numPage );
+ int printHtmlHeader( QTextStream &os, bool isFront );
+ int printHtmlTable( QTextStream &os, uint line, uint numLine, bool bw );
+ int printHtmlLine( QTextStream &os, uint offset, bool isPrimary, bool bw );
+
+ signals:
+ void fileSize( uint size );
+
+ private:
+ QString mUrl;
+ QDateTime mDiskModifyTime;
+ SDisplayLayout mLayout;
+ SDisplayColor mColor;
+ SDisplayFontInfo mFontInfo;
+ CConversion mEncode;
+ bool mCharValid[256];
+
+ unsigned char *mColorIndex;
+ char *mPrintBuf;
+ bool mLoadingData;
+ int mStartX;
+ int mStartY;
+
+ int mFontHeight;
+ int mFontAscent;
+ int mLineWidth;
+ int mFixedWidth;
+ int mUnitWidth;
+ int mSplitWidth;
+ int mNumLines;
+ int mTextStart1;
+ int mTextStart2;
+ int mNumCell;
+
+ uint mDocumentSize;
+ uint mMaximumSize;
+ bool mFixedSizeMode;
+ bool mDocumentModified;
+ EEditMode mEditMode;
+ SDisplayInputMode mInputMode;
+
+ int mOffsetSize;
+ int mOffsetIndex;
+ int mPrimaryWidth;
+ int mSecondaryWidth;
+ int mActiveEditor;
+
+ SSelect mSelect;
+ SSelect mMark;
+
+ SCursor mCursor;
+ bool mShowCursor;
+ bool mDisableCursor;
+
+ bool mInputErrorSound;
+ bool mFatalErrorSound;
+
+ bool mShowBookmarkInOffsetColumn;
+ bool mShowBookmarkInEditor;
+
+ uint mUndoLimit;
+ uint mUndoIndex;
+ QPtrList<CHexActionGroup> mUndoList;
+ QPtrList<SCursorOffset> mBookmarkList;
+ QBitArray mBookmarkMap;
+
+ PrintCellFunc printCell;
+ PrintOffsetFunc printOffset;
+ InputCellFunc inputCell;
+
+ static char mHexBigBuffer[16];
+ static char mHexSmallBuffer[16];
+ static char mDecBuffer[10];
+ static char mOctBuffer[8];
+ static SCursorState mCursorState;
+ static SFileState mFileState;
+};
+
+
+
+inline SCursorState &CHexBuffer::cursorState( void )
+{
+ if( size() == 0 )
+ {
+ mCursorState.valid = false;
+ mCursorState.selectionOffset = 0;
+ mCursorState.selectionSize = 0;
+ mCursorState.offset = 0;
+ mCursorState.cell = 0;
+ mCursorState.undoState = 0;
+ memset( mCursorState.data, 0, sizeof(mCursorState.data) );
+ mCursorState.charValid = false;
+ }
+ else
+ {
+ mCursorState.valid = true;
+ mCursorState.selectionOffset = mSelect.start();
+ mCursorState.selectionSize = mSelect.size();
+ mCursorState.offset = cursorOffset();
+ mCursorState.cell = cursorBit();
+ mCursorState.undoState = undoState();
+
+ for( uint i = 0; i < sizeof( mCursorState.data ); i++ )
+ {
+ mCursorState.data[i] = (mCursorState.offset+i >= mDocumentSize) ? 0 :
+ (unsigned char)data()[mCursorState.offset+i];
+ }
+
+ mCursorState.charValid = mCharValid[ mCursorState.data[0] ];
+ }
+ return( mCursorState );
+}
+
+
+inline void CHexBuffer::valueOnCursor( QByteArray &buf, uint size )
+{
+ int offset = cursorOffset();
+ if( offset + size >= mDocumentSize )
+ {
+ size = mDocumentSize - offset;
+ }
+
+ buf.resize(size);
+ for( uint i=0; i<buf.size(); i++)
+ {
+ buf[i] = (unsigned char)data()[offset+i];
+ }
+}
+
+
+inline const SDisplayLayout &CHexBuffer::layout( void )
+{
+ return( mLayout );
+}
+
+
+
+inline const SDisplayInputMode &CHexBuffer::inputMode( void )
+{
+ return( mInputMode );
+}
+
+inline QPtrList<SCursorOffset> &CHexBuffer::bookmarkList( void )
+{
+ return( mBookmarkList );
+}
+
+
+
+
+inline SFileState &CHexBuffer::fileState( void )
+{
+ if( size() == 0 )
+ {
+ mFileState.valid = false;
+ mFileState.size = 0;
+ mFileState.modified = false;
+
+ }
+ else
+ {
+ mFileState.valid = true;
+ mFileState.size = mDocumentSize;
+ mFileState.modified = mDocumentModified;
+ }
+
+ return( mFileState );
+}
+
+
+
+
+
+
+
+
+inline bool CHexBuffer::modified( void )
+{
+ return( mDocumentModified );
+}
+
+inline void CHexBuffer::setModified( bool modified )
+{
+ mDocumentModified = modified;
+}
+
+inline uint CHexBuffer::undoState( void )
+{
+ return( (mUndoIndex > 0 ? UndoOk : 0) |
+ (mUndoIndex < mUndoList.count() ? RedoOk : 0) );
+}
+
+
+inline uint CHexBuffer::documentSize( void )
+{
+ return( mDocumentSize );
+}
+
+
+inline CHexBuffer::EEditMode CHexBuffer::editMode( void )
+{
+ return( mEditMode );
+}
+
+
+inline const SEncodeState &CHexBuffer::encoding( void )
+{
+ return( mEncode.state() );
+}
+
+inline bool CHexBuffer::losslessEncoding( CConversion::EMode mode )
+{
+ return( mEncode.lossless(mode) );
+}
+
+inline QString &CHexBuffer::url( void )
+{
+ return( mUrl );
+}
+
+inline bool CHexBuffer::documentPresent( void )
+{
+ return( size() == 0 ? false : true );
+}
+
+inline void CHexBuffer::setUrl( const QString &url )
+{
+ mUrl = url;
+}
+
+inline const QDateTime &CHexBuffer::diskModifyTime( void )
+{
+ return( mDiskModifyTime );
+}
+
+inline uint CHexBuffer::calculateLine( uint offset )
+{
+ return( mLayout.lineSize == 0 ? 0 : offset / mLayout.lineSize );
+}
+
+inline const QColor &CHexBuffer::foregroundColor( uint column )
+{
+ if( column > mLayout.lineSize )
+ {
+ return( Qt::black );
+ }
+ else
+ {
+ return( mColor.primaryFg[ mColorIndex[ column ] ] );
+ }
+}
+
+inline bool CHexBuffer::selectionSet( uint offset, bool init )
+{
+ if( offset >= size() ) { offset = size() > 0 ? size() - 1 : 0; }
+
+ if( init == true )
+ {
+ return( mSelect.init( offset ) );
+ }
+ else
+ {
+ return( mSelect.set( offset ) );
+ }
+}
+
+inline void CHexBuffer::selectionSyncronize( void )
+{
+ mSelect.sync();
+}
+
+inline void CHexBuffer::selectionStartChange( uint &offset1, uint &offset2 )
+{
+ mSelect.startChange( offset1, offset2 );
+}
+
+inline void CHexBuffer::selectionStopChange( uint &offset1, uint &offset2 )
+{
+ mSelect.stopChange( offset1, offset2 );
+}
+
+inline bool CHexBuffer::cursorInsideSelection( void )
+{
+ return( mSelect.inside( cursorOffset() ) );
+}
+
+inline void CHexBuffer::markSet( uint offset, uint size )
+{
+ markSet( offset, true );
+ markSet( offset+size, false );
+ mMark.sync();
+}
+
+inline bool CHexBuffer::markSet( uint offset, bool init )
+{
+ if( offset >= size() ) { offset = size() > 0 ? size() - 1 : 0; }
+
+ if( init == true )
+ {
+ return( mMark.init( offset ) );
+ }
+ else
+ {
+ return( mMark.set( offset ) );
+ }
+}
+
+inline bool CHexBuffer::markRemove( void )
+{
+ return( mMark.init( mMark.start() ) );
+}
+
+
+inline void CHexBuffer::markSyncronize( void )
+{
+ mMark.sync();
+}
+
+inline void CHexBuffer::markStartChange( uint &offset1, uint &offset2 )
+{
+ mMark.startChange( offset1, offset2 );
+}
+
+inline void CHexBuffer::markStopChange( uint &offset1, uint &offset2 )
+{
+ mMark.stopChange( offset1, offset2 );
+}
+
+
+inline uint CHexBuffer::cursorOffset( void )
+{
+ return( mCursor.curr.offset );
+}
+
+inline uint CHexBuffer::cursorBit( void )
+{
+ return( mCursor.bit() );
+}
+
+
+inline uint CHexBuffer::cursorLine( void )
+{
+ return( mCursor.curr.y / lineHeight() );
+}
+
+inline uint CHexBuffer::prevCursorLine( void )
+{
+ return( mCursor.prev.y / lineHeight() );
+}
+
+inline SCursor &CHexBuffer::cursor( void )
+{
+ return( mCursor );
+}
+
+
+inline void CHexBuffer::currCursor( EEditArea editArea, SCursorPosition &p )
+{
+ if( editArea == edit_primary )
+ {
+ if( mActiveEditor == edit_primary )
+ {
+ p.x = mCursor.curr.drawX1();
+ p.w = mCursor.curr.width1();
+ }
+ else
+ {
+ p.x = mCursor.curr.drawX2();
+ p.w = mUnitWidth;
+ }
+ }
+ else
+ {
+ if( mActiveEditor == edit_primary )
+ {
+ p.x = mCursor.curr.drawX2();
+ p.w = mUnitWidth;
+ }
+ else
+ {
+ p.x = mCursor.curr.drawX1();
+ p.w = mUnitWidth * mNumCell;
+ }
+ }
+
+ p.x -= mStartX;
+ p.y = mCursor.curr.y - mStartY;
+ p.h = lineHeight();
+
+}
+
+inline void CHexBuffer::prevCursor( EEditArea editArea, SCursorPosition &p )
+{
+ if( editArea == edit_primary )
+ {
+ if( mActiveEditor == edit_primary )
+ {
+ p.x = mCursor.prev.drawX1();
+ p.w = mUnitWidth * mNumCell;
+ }
+ else
+ {
+ p.x = mCursor.prev.drawX2();
+ p.w = mUnitWidth;
+ }
+ }
+ else
+ {
+ if( mActiveEditor == edit_primary )
+ {
+ p.x = mCursor.prev.drawX2();
+ p.w = mUnitWidth;
+ }
+ else
+ {
+ p.x = mCursor.prev.drawX1();
+ p.w = mUnitWidth * mNumCell;
+ }
+ }
+
+ p.x -= mStartX;
+ p.y = mCursor.prev.y - mStartY;
+ p.h = lineHeight();
+}
+
+
+
+
+
+
+inline void CHexBuffer::cursorUp( uint lines )
+{
+ mCursor.up( lines );
+ cursorCompute();
+}
+
+inline void CHexBuffer::cursorDown( uint lines )
+{
+ mCursor.down( lines );
+ cursorCompute();
+}
+
+
+inline void CHexBuffer::cursorRight( bool cellLevel )
+{
+ if( cellLevel == true && mActiveEditor == edit_primary )
+ {
+ mCursor.incCell();
+ }
+ else
+ {
+ mCursor.addOffset( 1 );
+ }
+ cursorCompute();
+}
+
+
+inline void CHexBuffer::cursorStep( uint size, bool forward, bool modulo )
+{
+ if( forward == true )
+ {
+ if( modulo == true )
+ {
+ uint offset = mCursor.getOffset() + size;
+ mCursor.setOffset( offset - offset % size );
+ }
+ else
+ {
+ mCursor.addOffset( size );
+ }
+ }
+ else
+ {
+ if( modulo == true )
+ {
+ uint offset = mCursor.getOffset();
+ if( offset % size )
+ {
+ mCursor.decOffset( offset % size, false );
+ }
+ else
+ {
+ mCursor.setOffset( offset < size ? 0 : offset - size );
+ }
+ }
+ else
+ {
+ mCursor.decOffset( size, false );
+ }
+ }
+ cursorCompute();
+}
+
+
+inline void CHexBuffer::cursorLeft( bool cellLevel )
+{
+ if( cellLevel == true && mActiveEditor == edit_primary )
+ {
+ mCursor.decCell();
+ }
+ else
+ {
+ mCursor.decOffset( 1, false );
+ }
+ cursorCompute();
+}
+
+inline void CHexBuffer::cursorHome( bool toExtreme )
+{
+ mCursor.home( toExtreme );
+ cursorCompute();
+}
+
+inline void CHexBuffer::cursorEnd( bool toExtreme )
+{
+ mCursor.end( toExtreme );
+ cursorCompute();
+}
+
+
+inline void CHexBuffer::cursorGoto( uint offset, uint bit, bool backward,
+ bool fromCursor )
+{
+ uint maxOffset = mFixedSizeMode == true ? mMaximumSize-1 : documentSize();
+ mCursor.setOffset( offset, bit, backward, fromCursor, maxOffset );
+ cursorCompute();
+}
+
+inline void CHexBuffer::cursorGoto( uint offset, uint bit )
+{
+ mCursor.setOffset( offset );
+ mCursor.setBit( bit );
+ cursorCompute();
+}
+
+inline bool CHexBuffer::cursorChanged( void )
+{
+ return( mCursor.changed() );
+}
+
+inline void CHexBuffer::cursorResetEditArea( void )
+{
+ mCursor.setArea( edit_none );
+}
+
+inline bool CHexBuffer::cursorPrimaryEdit( void )
+{
+ return( mActiveEditor == edit_primary ? true : false );
+}
+
+inline int CHexBuffer::cursorFixedPosition( int position, int height )
+{
+ position += mCursor.curr.y - mCursor.prev.y;
+ if( position < 0 )
+ {
+ return( 0 );
+ }
+ else if( position + height > totalHeight() )
+ {
+ return( height > totalHeight() ? 0 : totalHeight() - height );
+ }
+ else
+ {
+ if( mCursor.curr.y < position )
+ {
+ return( mCursor.curr.y );
+ }
+ else if( mCursor.curr.y > position + height )
+ {
+ return( mCursor.curr.y - height + lineHeight() );
+ }
+ else
+ {
+ return( position );
+ }
+ }
+}
+
+inline int CHexBuffer::cursorChangePosition( int position, int height )
+{
+ if( mCursor.curr.y < position || mCursor.curr.y > position + height )
+ {
+ // When cursor is at top of window
+ position = mCursor.curr.y;
+ }
+ else if( mCursor.curr.y > position + height - lineHeight() )
+ {
+ // When cursor is at bottom of window
+ position = mCursor.curr.y - height + lineHeight();
+ }
+
+ return( position );
+}
+
+inline int CHexBuffer::printDummyCell( char *buf, unsigned char )
+{
+ buf[0] = 0;
+ return( 0 );
+}
+
+inline int CHexBuffer::printHexadecimalBigCell( char *buf, unsigned char data )
+{
+ buf[0] = mHexBigBuffer[ (data>>4)&0x0F ];
+ buf[1] = mHexBigBuffer[ data&0x0F ];
+ return( 0 );
+}
+
+inline int CHexBuffer::printHexadecimalSmallCell( char *buf,
+ unsigned char data )
+{
+ buf[0] = mHexSmallBuffer[ (data>>4)&0x0F ];
+ buf[1] = mHexSmallBuffer[ data&0x0F ];
+ return( 0 );
+}
+
+
+inline int CHexBuffer::printDecimalCell( char *buf, unsigned char data )
+{
+ buf[0] = mDecBuffer[ data/100 ];
+ data -= (data/100) * 100;
+ buf[1] = mDecBuffer[ data/10 ];
+ data -= (data/10) * 10;
+ buf[2] = mDecBuffer[ data ];
+ return( 0 );
+}
+
+inline int CHexBuffer::printOctalCell( char *buf, unsigned char data )
+{
+ buf[0] = mOctBuffer[ (data>>6)&0x07 ];
+ buf[1] = mOctBuffer[ (data>>3)&0x07 ];
+ buf[2] = mOctBuffer[ data&0x07 ];
+ return( 0 );
+}
+
+inline int CHexBuffer::printBinaryCell( char *buf, unsigned char data )
+{
+ for( int i = 0; i < 8; i++ )
+ {
+ buf[7-i] = (data&(1<<i)) ? '1' : '0';
+ }
+ return( 0 );
+}
+
+inline int CHexBuffer::printAsciiCell( char *buf, unsigned char data )
+{
+ if( mCharValid[data] == 0 )
+ {
+ buf[0] = mFontInfo.nonPrintChar;
+ return( 1 );
+ }
+ else
+ {
+ buf[0] = data;
+ return( 0 );
+ }
+}
+
+inline void CHexBuffer::printDummyOffset( char *buf, uint /*offset*/ )
+{
+ buf[0] = 0;
+}
+
+inline void CHexBuffer::printHexadecimalBigOffset( char *buf, uint offset )
+{
+ sprintf( buf, "%04X:%04X", offset>>16, offset&0x0000FFFF );
+}
+
+inline void CHexBuffer::printHexadecimalSmallOffset( char *buf, uint offset )
+{
+ sprintf( buf, "%04x:%04x", offset>>16, offset&0x0000FFFF );
+}
+
+inline void CHexBuffer::printDecimalOffset( char *buf, uint offset )
+{
+ sprintf( buf, "%010u", offset );
+}
+
+inline int CHexBuffer::lineSize( void )
+{
+ return( mLayout.lineSize );
+}
+
+inline int CHexBuffer::lineHeight( void )
+{
+ return( mFontHeight + mLayout.horzGridWidth );
+}
+
+inline int CHexBuffer::fontAscent( void )
+{
+ return( mFontAscent );
+}
+
+inline int CHexBuffer::lineWidth( void )
+{
+ return( mLineWidth );
+}
+
+inline int CHexBuffer::unitWidth( void )
+{
+ return( mUnitWidth );
+}
+
+inline int CHexBuffer::numLines( void )
+{
+ return( mNumLines );
+}
+
+inline int CHexBuffer::totalHeight( void )
+{
+ return( mNumLines * (mFontHeight+mLayout.horzGridWidth) );
+}
+
+inline const QFont &CHexBuffer::font( void )
+{
+ return( mFontInfo.font );
+}
+
+inline SCursor *CHexBuffer::textCursor( void )
+{
+ return( &mCursor );
+}
+
+inline const QColor &CHexBuffer::backgroundColor( void )
+{
+ return( documentPresent() == true ? mColor.textBg : mColor.inactiveBg );
+}
+
+inline int CHexBuffer::startX( void )
+{
+ return( mStartX );
+}
+
+inline int CHexBuffer::startY( void )
+{
+ return( mStartY );
+}
+
+inline void CHexBuffer::setStartX( int val )
+{
+ mStartX = val;
+}
+
+inline void CHexBuffer::setStartY( int val )
+{
+ mStartY = val;
+}
+
+
+
+#endif
+
diff --git a/khexedit/hexclipboard.cc b/khexedit/hexclipboard.cc
new file mode 100644
index 0000000..0de70d6
--- /dev/null
+++ b/khexedit/hexclipboard.cc
@@ -0,0 +1,254 @@
+/*
+ * 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.
+ *
+ */
+
+//
+// This is a VERY crude implementation, which serves my requirements and
+// nothing more.
+//
+
+
+#include <string.h>
+#include "hexclipboard.h"
+
+
+static const uchar *base64EncodeTable( void )
+{
+ static uchar table[64] =
+ {
+ 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
+ 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
+ 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
+ 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/',
+ };
+
+ return( table );
+}
+
+static const uchar *base64DecodeTable( void )
+{
+ static uchar table[255];
+ static bool init = false;
+ if( init == false )
+ {
+ uint i;
+ for( i = 0; i < 255; i++ ) { table[i] = 0x80; }
+ for( i = 'A'; i <= 'Z'; i++ ) { table[i] = 0 + (i - 'A'); }
+ for( i = 'a'; i <= 'z'; i++ ) { table[i] = 26 + (i - 'a'); }
+ for( i = '0'; i <= '9'; i++ ) { table[i] = 52 + (i - '0'); }
+ table[(uchar)'+'] = 62;
+ table[(uchar)'/'] = 63;
+ table[(uchar)'='] = 0;
+ init = true;
+ }
+ return( table );
+}
+
+
+static const char *mimeHeader( void )
+{
+ static const char *data =
+ "Content-Type: application/octet-stream; " \
+ "name=\"khexedit_copy\"\r\n" \
+ "Content-Transfer-Encoding: base64\r\n\r\n";
+ return( data );
+}
+
+
+
+
+
+
+
+
+CHexClipboard::CHexClipboard( void )
+{
+}
+
+
+CHexClipboard::~CHexClipboard( void )
+{
+}
+
+
+bool CHexClipboard::encode( QByteArray &dst, QByteArray &src )
+{
+ if( src.size() == 0 )
+ {
+ return( false );
+ }
+
+ uint srcSize = src.size();
+ uint mimeSize = strlen( mimeHeader() );
+ uint lineSize = 72;
+ uint dstSize = (srcSize / 3 + (srcSize % 3 ? 1 : 0)) * 4;
+ dstSize += ((dstSize/lineSize) + 1)*2 + 1;
+
+ dst.resize( dstSize + mimeSize + 1 );
+ if( dst.isNull() == true )
+ {
+ return( false );
+ }
+
+ unsigned char inBuf[3], outBuf[4];
+ uint lineLen = 0;
+
+ memcpy( dst.data(), mimeHeader(), mimeSize );
+ uint j = mimeSize;
+
+
+ const uchar *table = base64EncodeTable();
+ for( uint i=0; i < srcSize; i += 3 )
+ {
+ memset( inBuf, 0, sizeof(inBuf) );
+ uint n;
+ for( n=0; n < 3; n++ )
+ {
+ if( i+n >= srcSize )
+ {
+ break;
+ }
+ inBuf[n] = src[i+n];
+ }
+
+ if( n > 0 )
+ {
+ outBuf[0] = table[ inBuf[0] >> 2 ];
+ outBuf[1] = table[ ((inBuf[0] & 0x3) << 4) | (inBuf[1] >> 4) ];
+ outBuf[2] = table[ ((inBuf[1] & 0xF) << 2) | (inBuf[2] >> 6) ];
+ outBuf[3] = table[ inBuf[2] & 0x3F ];
+
+ if( n < 3 )
+ {
+ outBuf[3] = '=';
+ if( n < 2 )
+ {
+ outBuf[2] = '=';
+ }
+ }
+
+ for( uint m=0; m<4; m++ )
+ {
+ if( lineLen >= lineSize )
+ {
+ dst[j++] = '\r';
+ dst[j++] = '\n';
+ lineLen = 0;
+ }
+ dst[j++] = outBuf[m];
+ lineLen += 1;
+ }
+ }
+ }
+ dst[j++] = '\r';
+ dst[j++] = '\n';
+ dst[j++] = '\0';
+ return( true );
+}
+
+
+
+
+bool CHexClipboard::decode( QByteArray &dst, QString &src )
+{
+ uint mimeSize = strlen( mimeHeader() );
+ if( src.length() <= mimeSize )
+ {
+ return( plainDecode( dst, src ) );
+ }
+
+ if( memcmp( src.ascii(), mimeHeader(), mimeSize ) != 0 )
+ {
+ return( plainDecode( dst, src ) );
+ }
+
+ uint srcSize = src.length();
+ uint dstSize = (srcSize * 3) / 4;
+ uchar srcBuf[4], valBuf[4], dstBuf[3];
+ uint sumElement = 0;
+
+ dst.resize( dstSize );
+ if( dst.isNull() == true )
+ {
+ return( plainDecode( dst, src ) );
+ }
+
+ uint i,j;
+ uint n = 0;
+
+ const uchar *table = base64DecodeTable();
+ for( i=mimeSize; i<srcSize; )
+ {
+ for( j=0; j<4; )
+ {
+ if( i >= srcSize )
+ {
+ dst.truncate( sumElement );
+ return( j > 0 ? false : true );
+ }
+
+ int c = src[i++].latin1();
+ if( c <= ' ' )
+ {
+ continue;
+ }
+ if( table[c] & 0x80 )
+ {
+ return( plainDecode( dst, src ) );
+ }
+
+ srcBuf[j] = c;
+ valBuf[j] = table[c];
+ j++;
+ }
+
+ dstBuf[0] = (valBuf[0] << 2) | (valBuf[1] >> 4);
+ dstBuf[1] = (valBuf[1] << 4) | (valBuf[2] >> 2);
+ dstBuf[2] = (valBuf[2] << 6) | (valBuf[3]);
+
+ uint numElement = srcBuf[2] == '=' ? 1 : (srcBuf[3] == '=' ? 2 : 3);
+ for( uint m=0; m < numElement; m++ )
+ {
+ dst[n++] = dstBuf[m];
+ }
+ sumElement += numElement;
+
+ if( numElement < 3 )
+ {
+ break;
+ }
+ }
+
+ dst.truncate( sumElement );
+ return( true );
+}
+
+
+bool CHexClipboard::plainDecode( QByteArray &dst, QString &src )
+{
+ dst.resize( src.length() );
+ if( dst.isNull() == true )
+ {
+ return( false );
+ }
+
+ for( uint i=0; i < src.length(); dst[i] = src[i].latin1(), i++ );
+ return( true );
+}
+
diff --git a/khexedit/hexclipboard.h b/khexedit/hexclipboard.h
new file mode 100644
index 0000000..9a7710d
--- /dev/null
+++ b/khexedit/hexclipboard.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _HEX_CLIPBOARD_H_
+#define _HEX_CLIPBOARD_H_
+
+#include <qstring.h>
+
+class CHexClipboard
+{
+ public:
+ CHexClipboard( void );
+ ~CHexClipboard( void );
+
+ bool encode( QByteArray &dst, QByteArray &src );
+ bool decode( QByteArray &dst, QString &src );
+
+ private:
+ bool plainDecode( QByteArray &dst, QString &src );
+};
+
+
+#endif
diff --git a/khexedit/hexdrag.cc b/khexedit/hexdrag.cc
new file mode 100644
index 0000000..d09b28d
--- /dev/null
+++ b/khexedit/hexdrag.cc
@@ -0,0 +1,130 @@
+/*
+ * 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 "hexdrag.h"
+static const char *mediaString = "application/octet-stream";
+
+
+CHexDrag::CHexDrag( const QByteArray &data, QWidget *dragSource,
+ const char *name )
+ :QDragObject(dragSource,name)
+{
+ setData( data );
+ prepPixmap();
+}
+
+
+CHexDrag::CHexDrag( QWidget *dragSource, const char *name )
+ :QDragObject(dragSource,name)
+{
+ prepPixmap();
+}
+
+
+void CHexDrag::setData( const QByteArray &data )
+{
+ mData = data;
+}
+
+
+
+void CHexDrag::prepPixmap(void)
+{
+ //
+ // Wont use it yet,
+ //
+ /*
+ KIconLoader &loader = *KGlobal::iconLoader();
+ QPixmap pix = loader.loadIcon( "binary.xpm" );
+
+ QPoint hotspot( pix.width()-20,pix.height()/2 );
+ setPixmap( pix, hotspot );
+ */
+}
+
+
+const char *CHexDrag::format( int i ) const
+{
+ if( i == 0 )
+ {
+ return( mediaString );
+ }
+ else
+ {
+ return( 0 );
+ }
+ return( i == 0 ? mediaString : 0 );
+}
+
+
+QByteArray CHexDrag::encodedData( const char *fmt ) const
+{
+ if( fmt != 0 )
+ {
+ if( strcmp( fmt, mediaString) == 0 )
+ {
+ return( mData );
+ }
+ }
+
+ QByteArray buf;
+ return( buf );
+}
+
+
+bool CHexDrag::canDecode( const QMimeSource *e )
+{
+ return( e->provides(mediaString) );
+}
+
+
+bool CHexDrag::decode( const QMimeSource *e, QByteArray &dest )
+{
+ dest = e->encodedData(mediaString);
+ return( dest.size() == 0 ? false : true );
+
+ //
+ // I get an
+ // "X Error: BadAtom (invalid Atom parameter) 5
+ // Major opcode: 17"
+ //
+ // if I try to use the code below on a source that has been
+ // collected from QClipboard. It is the e->provides(mediaString)
+ // that fail (Qt-2.0). Sometimes it works :(
+ //
+ // printf("0: %s\n", e->format(0) ); No problem.
+ // printf("1: %s\n", e->format(1) ); Crash.
+ //
+ #if 0
+ if( e->provides(mediaString) == true )
+ {
+ dest = e->encodedData(mediaString);
+ return( true );
+ }
+ else
+ {
+ return( false );
+ }
+ #endif
+}
+
+
+#include "hexdrag.moc"
diff --git a/khexedit/hexdrag.h b/khexedit/hexdrag.h
new file mode 100644
index 0000000..b29b197
--- /dev/null
+++ b/khexedit/hexdrag.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _HEX_DRAG_H_
+#define _HEX_DRAG_H_
+
+
+#include <qdragobject.h>
+#include <qstring.h>
+
+class CHexDrag : public QDragObject
+{
+ Q_OBJECT
+
+ public:
+ CHexDrag( const QByteArray &data, QWidget *dragSource = 0,
+ const char *name = 0 );
+ CHexDrag( QWidget *dragSource = 0, const char *name = 0 );
+
+ void setData( const QByteArray &data );
+ const char* format ( int i ) const;
+ QByteArray encodedData( const char *fmt ) const;
+
+
+ static bool canDecode( const QMimeSource *e );
+ static bool decode( const QMimeSource *e, QByteArray &dest );
+
+ private:
+ void prepPixmap( void );
+
+ private:
+ QByteArray mData;
+
+};
+
+
+#endif
diff --git a/khexedit/hexeditorwidget.cc b/khexedit/hexeditorwidget.cc
new file mode 100644
index 0000000..16b62a4
--- /dev/null
+++ b/khexedit/hexeditorwidget.cc
@@ -0,0 +1,2443 @@
+/*
+ * 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 <kfiledialog.h>
+#include <kglobalsettings.h>
+#include <kio/netaccess.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <ktempfile.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( QWidget *parent, const char *name )
+ : QWidget( 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, SIGNAL(pleaseOpenNewFile()), SLOT( newFile()) );
+ connect( mHexView, SIGNAL(pleaseOpenFile( const QString&, bool, uint )),
+ SLOT( open(const QString&, bool, uint)) );
+ connect( mHexView, SIGNAL(pleaseStepFile(bool)), SLOT( stepFile(bool)) );
+ connect( kapp, SIGNAL( kdisplayFontChanged() ), SLOT( fontChanged() ) );
+ connect( kapp, SIGNAL( kdisplayPaletteChanged() ),SLOT( paletteChanged()) );
+ connect( mHexView, SIGNAL( layoutChanged( const SDisplayLayout & ) ),
+ SLOT( layoutChanged( const SDisplayLayout & ) ) );
+ connect( mHexView, SIGNAL( inputModeChanged( const SDisplayInputMode & ) ),
+ this, 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( KConfig &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( KConfig &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( QResizeEvent *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 = KGlobalSettings::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 QString &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;
+ }
+
+ QString 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 )
+ {
+ QString msg = i18n("Unable to create new document.");
+ KMessageBox::sorry( topLevelWidget(), msg, i18n("Operation Failed") );
+ return;
+ }
+
+ mUntitledCount += 1;
+}
+
+
+
+
+void CHexEditorWidget::newFile( const QByteArray &data )
+{
+ newFile();
+ mHexView->append( data );
+}
+
+
+
+
+void CHexEditorWidget::open()
+{
+ KURL file = KFileDialog::getOpenURL( mWorkDir, "*" ,topLevelWidget() );
+
+ if( file.isEmpty() )
+ return;
+
+ QString 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 QString &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 QString &url, uint &offset )
+{
+ CHexBuffer *hexBuffer = documentItem( url );
+ if( hexBuffer == 0 )
+ {
+ return( false );
+ }
+ offset = hexBuffer->cursorOffset();
+ return( true );
+}
+
+
+bool CHexEditorWidget::selectDocument( const QString &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, QString::null, 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;
+ }
+
+ QString 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 );
+ }
+
+ QString msg = i18n(""
+ "The current document has been modified.\n"
+ "Do you want to save it?" );
+ int reply = KMessageBox::warningYesNoCancel( topLevelWidget(), msg, QString::null, 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 QString currentName = kurl.path();
+ QString 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 )
+ {
+ QString 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() )
+ {
+ QString name( url.path() );
+ QFileInfo info( name );
+
+ if( info.exists() )
+ {
+ QString 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;
+ }
+ }
+
+ QString 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 )
+ {
+ QString msg = i18n( "The current document does not exist on the disk." );
+ KMessageBox::sorry( topLevelWidget(), msg, i18n("Reload") );
+ return;
+ }
+
+ if( mHexView->modified() == true )
+ {
+ QString 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;
+ }
+ }
+
+ QString 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
+ //
+ QString creator( PACKAGE );
+ creator += " ";
+ creator += VERSION;
+
+ printer.setCreator( creator );
+
+ int errCode = prepareProgressData( pg_print );
+ if( errCode == Err_Success )
+ {
+ errCode = mHexView->print( printer, mProgressData );
+ }
+
+ QString 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 )
+ {
+ QString 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, SIGNAL( exportText(const SExportText &)),
+ this, SLOT( exportText( const SExportText &)) );
+ connect( mExportDialog, SIGNAL( exportHtml(const SExportHtml &)),
+ this, SLOT( exportHtml( const SExportHtml &)) );
+ connect( mExportDialog, SIGNAL( exportCArray(const SExportCArray &)),
+ this, 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 )
+ {
+ QString 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 )
+ {
+ QString 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 )
+ {
+ QString 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 )
+ {
+ QString 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 )
+ {
+ QString 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 )
+ {
+ QString 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, SIGNAL(gotoOffset( uint, uint, bool, bool )),
+ mHexView, 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,
+ SIGNAL(findData(SSearchControl &, uint, bool)),
+ 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 )
+ {
+ QString 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 QString &header )
+{
+ if( mDisplayState.misc.confirmWrap == false )
+ {
+ return( true ); // Never ask the user
+ }
+
+ QString 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 )
+ {
+ QString 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,
+ SIGNAL(findData(SSearchControl &, uint, bool)),
+ SLOT(findData(SSearchControl &, uint, bool)) );
+ connect( mFindNavigatorDialog, SIGNAL(makeKey(void)),
+ 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,
+ SIGNAL( replaceData( SSearchControl &, uint)),
+ 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,
+ SIGNAL( replaceData( SSearchControl &, uint)),
+ 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 )
+ {
+ QString 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 QString 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, SIGNAL(execute( SInsertData & )),
+ mHexView, SLOT(insert( SInsertData & )) );
+ }
+ mInsertDialog->show();
+}
+
+
+void CHexEditorWidget::encoding( void )
+{
+ QString 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, SIGNAL(markText( uint, uint, bool )),
+ mHexView, SLOT(setMark( uint, uint, bool )) );
+ connect( mStringDialog, SIGNAL(collect()), SLOT(collectStrings()) );
+ connect( mHexView, SIGNAL(fileName( const QString &, bool ) ),
+ mStringDialog, SLOT( removeList() ) );
+ connect( mHexView, SIGNAL(dataChanged()),
+ mStringDialog, 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 )
+ {
+ QString msg = i18n("Could not collect strings.\n");
+ msg += hexError( errCode );
+ KMessageBox::sorry( topLevelWidget(), msg, i18n("Collect Strings") );
+ }
+
+}
+
+
+
+void CHexEditorWidget::recordView( void )
+{
+ QString 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, SIGNAL(filterData( SFilterControl & )),
+ mHexView, SLOT(filter( SFilterControl & )) );
+ }
+ mFilterDialog->show();
+}
+
+
+void CHexEditorWidget::chart( void )
+{
+ if( mCharTableDialog == 0 )
+ {
+ mCharTableDialog = new CCharTableDialog( topLevelWidget(), 0, false );
+ if( mCharTableDialog == 0 ) { return; }
+ connect( mCharTableDialog, SIGNAL(assign( const QByteArray & )),
+ mHexView, SLOT(insert( const QByteArray & )) );
+ }
+ mCharTableDialog->show();
+}
+
+
+void CHexEditorWidget::converter( void )
+{
+ if( mConverterDialog == 0 )
+ {
+ mConverterDialog = new CConverterDialog( this, "converter", false );
+ connect( mConverterDialog, SIGNAL(probeCursorValue(QByteArray &, uint)),
+ mHexView, SLOT(valueOnCursor(QByteArray &, uint)) );
+ }
+ mConverterDialog->show();
+}
+
+
+void CHexEditorWidget::statistics( void )
+{
+ if( mFileInfoDialog == 0 )
+ {
+ mFileInfoDialog = new CFileInfoDialog( topLevelWidget(), 0, false );
+ if( mFileInfoDialog == 0 ) { return; }
+ connect( mFileInfoDialog, SIGNAL(collectStatistic(SStatisticControl &)),
+ SLOT(collectStatistics(SStatisticControl &)));
+ connect( mHexView, SIGNAL(dataChanged()),
+ mFileInfoDialog, 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
+
+ QString 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, SIGNAL(lineSizeChoice(const SDisplayLine &)),
+ SLOT(setLineSize(const SDisplayLine &)) );
+ connect( mOptionDialog, SIGNAL(layoutChoice(const SDisplayLayout &)),
+ SLOT(setLayout(const SDisplayLayout &)) );
+ connect( mOptionDialog, SIGNAL(fontChoice(const SDisplayFont &)),
+ SLOT(setFont(const SDisplayFont &)) );
+ connect( mOptionDialog, SIGNAL(colorChoice(const SDisplayColor &)),
+ SLOT(setColor(const SDisplayColor &)) );
+ connect( mOptionDialog, SIGNAL(cursorChoice(const SDisplayCursor &)),
+ SLOT(setCursor(const SDisplayCursor &)) );
+ connect( mOptionDialog, SIGNAL(miscChoice(const SDisplayMisc &)),
+ SLOT(setMisc(const SDisplayMisc &)) );
+ connect( mOptionDialog, SIGNAL(removeRecentFiles()),
+ SIGNAL(removeRecentFiles()) );
+ }
+ if( mOptionDialog->isVisible() == false )
+ {
+ mOptionDialog->setState( mDisplayState );
+ }
+ mOptionDialog->show();
+}
+
+
+
+void CHexEditorWidget::favorites( void )
+{
+ QString 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() )
+ {
+ QString msg = i18n("Malformed URL\n%1").arg( url.url() );
+ KMessageBox::sorry( topLevelWidget(), msg, i18n("Read URL") );
+ return( Err_IllegalArgument );
+ }
+
+ //
+ // 3) Load the file.
+ //
+ QString tmpfile;
+ if ( !KIO::NetAccess::download( url, tmpfile, this ) )
+ return Err_ReadFailed;
+
+ bool success = readFile( tmpfile, url.url(), insert );
+
+ KIO::NetAccess::removeTempFile( tmpfile );
+
+ return( success == true ? Err_Success : Err_ReadFailed );
+}
+
+
+void CHexEditorWidget::writeURL( QString &url )
+{
+ KURL kurl( url );
+ if( kurl.isLocalFile() )
+ writeFile( kurl.path() );
+ else
+ {
+ bool modified = mHexView->modified();
+ KTempFile tf;
+ tf.setAutoDelete( true );
+ writeFile( tf.name() );
+ if( !KIO::NetAccess::upload(tf.name(),url,this) )
+ {
+ mHexView->setModified( modified );
+ QString msg = i18n("Could not save remote file.");
+ KMessageBox::sorry( topLevelWidget(), msg, i18n("Write Failure") );
+ }
+ }
+}
+
+bool CHexEditorWidget::modifiedByAlien( const QString &url )
+{
+ KURL kurl( url );
+ if( kurl.isLocalFile() == false )
+ {
+ return( false );
+ }
+
+ QFileInfo fileInfo( kurl.path() );
+ if( fileInfo.exists() == false )
+ {
+ return( false );
+ }
+
+ if( fileInfo.lastModified() == mHexView->diskModifyTime() )
+ {
+ return( false );
+ }
+
+ return( true );
+}
+
+
+
+bool CHexEditorWidget::readFile( const QString &diskPath, const QString &url,
+ bool insert )
+{
+
+ QFileInfo info( diskPath );
+ if( info.exists() == false )
+ {
+ const QString 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 QString msg = i18n("You have specified a folder.\n%1").arg( diskPath );
+ KMessageBox::sorry( topLevelWidget(), msg, i18n("Read") );
+ return( false );
+ }
+
+ if( info.isReadable() == false )
+ {
+ const QString msg = i18n("You do not have read permission to this file.\n%1").arg( diskPath );
+ KMessageBox::sorry( topLevelWidget(), msg, i18n("Read") );
+ return( false );
+ }
+
+ QFile file( diskPath );
+ if( file.open( IO_ReadOnly | IO_Raw ) == false )
+ {
+ const QString 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 )
+ {
+ QString header = insert == true ? i18n("Insert") : i18n("Read");
+ QString 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 QString &diskPath )
+{
+ QFileInfo info( diskPath );
+ if( info.exists() == true )
+ {
+ if( info.isDir() == true )
+ {
+ QString msg = i18n("You have specified a folder.");
+ KMessageBox::sorry( topLevelWidget(), msg, i18n("Write Failure") );
+ return( false );
+ }
+
+ if( info.isWritable() == false )
+ {
+ QString msg = i18n("You do not have write permission.");
+ KMessageBox::sorry( topLevelWidget(), msg, i18n("Write Failure") );
+ return( false );
+ }
+ }
+
+ QFile file( diskPath );
+ if( file.open( IO_WriteOnly | IO_Raw | IO_Truncate ) == false )
+ {
+ QString 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 )
+ {
+ QString 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 QString &url )
+{
+ QString 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 QString &url, bool next )
+{
+ if( mDocumentList.count() <= 1 )
+ {
+ return( 0 );
+ }
+
+ QString 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 )
+ {
+ QString 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 QString names[] =
+ {
+ i18n("Reading"),
+ i18n("Writing"),
+ i18n("Inserting"),
+ i18n("Printing"),
+ i18n("Encoding"),
+ i18n("Collect strings"),
+ i18n("Exporting"),
+ i18n("Scanning"),
+ };
+
+ mProgressData.define( progressReceiver, this );
+ emit setProgressText( QString(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 );
+ }
+
+ QString 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 )
+ {
+ QString msg = i18n("Could not finish operation.\n");
+ msg += hexError( Err_Busy );
+ KMessageBox::sorry( topLevelWidget(), msg );
+ }
+
+ return( mProgressBusy );
+}
+
+
+
+
+#include "hexeditorwidget.moc"
diff --git a/khexedit/hexeditorwidget.h b/khexedit/hexeditorwidget.h
new file mode 100644
index 0000000..5c4d86a
--- /dev/null
+++ b/khexedit/hexeditorwidget.h
@@ -0,0 +1,301 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _HEX_EDITOR_WIDGET_H_
+#define _HEX_EDITOR_WIDGET_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include <qvariant.h>
+#include <qptrdict.h>
+#include <kapplication.h>
+
+#include "hexbuffer.h"
+#include "hexviewwidget.h"
+#include "progress.h"
+
+class CGotoDialog;
+class CFindDialog;
+class CReplaceDialog;
+class CInsertDialog;
+class CFilterDialog;
+class COptionDialog;
+class CPrinterDialog;
+class CStringDialog;
+class CCharTableDialog;
+class CFileInfoDialog;
+class CExportDialog;
+class CConverterDialog;
+class CFindNavigatorDialog;
+class CReplacePromptDialog;
+namespace KIO { class Job; }
+
+
+class CHexEditorWidget : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ enum EProgressMode
+ {
+ pg_read = 0,
+ pg_write,
+ pg_insert,
+ pg_print,
+ pg_encode,
+ pg_strings,
+ pg_export,
+ pg_statistic,
+ pg_MAX
+ };
+
+ public:
+ CHexEditorWidget( QWidget *parent = 0, const char *name = 0 );
+ ~CHexEditorWidget( void );
+
+ void initialize( void );
+ void writeConfiguration( KConfig &config );
+ void readConfiguration( KConfig &config );
+
+ bool isOpen( const QString &url, uint &offset );
+ bool modified( void );
+
+ inline int defaultTextWidth( void );
+ inline CHexViewWidget *view( void );
+ inline SDisplayLayout &layout( void );
+ inline SDisplayLine &line( void );
+ inline SDisplayInputMode &inputMode( void );
+ inline SDisplayMisc::EOpenFile openFile( void );
+ inline bool discardRecentFiles( void );
+ inline bool gotoStartupOffset( void );
+ inline bool gotoReloadOffset( void );
+
+ signals:
+ void errorLoadFile( const QString &url );
+ void setProgress( int percent );
+ void setProgress( int curPage, int maxPage );
+ void enableProgressText( bool state );
+ void setProgressText( const QString &msg );
+ void operationChanged( bool state );
+ void removeRecentFiles( void );
+
+ public slots:
+ void setHexadecimalMode( void );
+ void setDecimalMode( void );
+ void setOctalMode( void );
+ void setTextMode( void );
+ void setBinaryMode( void );
+ void open( const QString &url, bool reloadWhenChanged, uint offset );
+ void newFile( void );
+ void newFile( const QByteArray &data );
+ void stepFile( bool next );
+ void open( void );
+ void insertFile( void );
+ void stop( void );
+ bool close( void );
+ bool closeAll( void );
+ bool backup( void );
+ bool save( void );
+ bool saveAs( void );
+ void reload( void );
+ void print( void );
+ void exportDialog( void );
+ void encode( CConversion::EMode mode );
+ void undo( void );
+ void redo( void );
+ void toggleWriteProtection( void );
+ void defaultWriteProtection( void );
+ void toggleResizeLock( void );
+ void setResizeLock( bool state );
+ void toggleOffsetColumnVisibility( void );
+ void toggleTextColumnVisibility( void );
+ void toggleOffsetAsDecimal( void );
+ void toggleDataUppercase( void );
+ void toggleOffsetUppercase( void );
+ void toggleInsertMode( void );
+ void benchmark( void );
+ void copy( void );
+ void copyText( void );
+ void paste( void );
+ void pasteNewFile( void );
+ void cut( void );
+ void selectAll( void );
+ void unselect( void );
+ void addBookmark( void );
+ void removeBookmark( void );
+ void removeAllBookmark( void );
+ void replaceBookmark( void );
+ void gotoBookmark( int position );
+ void gotoNextBookmark( void );
+ void gotoPrevBookmark( void );
+ void gotoOffset( void );
+ void find( void );
+ void findAgain( void );
+ void findNext( void );
+ void findPrevious( void );
+ void findData( SSearchControl &sc, uint mode, bool navigator );
+ void replace( void );
+ void insertPattern( void );
+ void encoding( void );
+ void strings( void );
+ void recordView( void );
+ void filter( void );
+ void chart( void );
+ void converter( void );
+ void statistics( void );
+ void options( void );
+ void favorites( void );
+
+ protected slots:
+ void fontChanged( void );
+ void paletteChanged( void );
+ void layoutChanged( const SDisplayLayout &layout );
+ void inputModeChanged( const SDisplayInputMode &input );
+ void setLineSize(const SDisplayLine &line );
+ void setLayout( const SDisplayLayout &layout );
+ void setCursor( const SDisplayCursor &cursor );
+ void setColor( const SDisplayColor &color );
+ void setFont( const SDisplayFont &font );
+ void setMisc( const SDisplayMisc &misc );
+
+ void printPostscript( CHexPrinter & );
+ void exportText( const SExportText & );
+ void exportHtml( const SExportHtml & );
+ void exportCArray( const SExportCArray &ex );
+
+ void findNavigator( SSearchControl &sc );
+ void replaceData( SSearchControl &sc, uint mode );
+ void replacePrompt( SSearchControl &sc );
+ void replaceResult( SSearchControl &sc );
+ void collectStrings( void );
+ void collectStatistics( SStatisticControl &sc );
+
+ protected:
+ void resizeEvent( QResizeEvent *e );
+
+ private:
+ bool selectDocument( const QString &url, bool reloadWhenChanged );
+ bool querySave( void );
+ int readURL( const KURL &url, bool insert );
+ void writeURL( QString &url );
+ bool readFile( const QString &diskPath, const QString &url, bool insert );
+ bool writeFile( const QString &diskPath );
+ void saveWorkingDirectory( const QString &url );
+
+ bool confirmPrintPageNumber( CHexPrinter &printer );
+
+ CHexBuffer *documentItem( const QString &url );
+ CHexBuffer *documentItem( const QString &url, bool next );
+ bool createBuffer( void );
+ void removeBuffer( void );
+
+ bool askWrap( bool fwd, const QString &header );
+ bool canFind( bool showError );
+ void hideReplacePrompt( void );
+ bool modifiedByAlien( const QString &url );
+ void enableInputLock( bool inputLock );
+
+ int prepareProgressData( EProgressMode mode );
+ static int progressReceiver( void *clientData, SProgressData &pd );
+ int progressParse( const SProgressData &pd );
+ bool busy( bool showWarning );
+
+ private:
+ QString mWorkDir; // Remembers last directroy used by file dialogs
+
+ uint mUntitledCount;
+ QPtrList<CHexBuffer> mDocumentList;
+ SDisplayState mDisplayState;
+
+ CProgress mProgressData;
+ EProgressMode mProgressMode;
+ bool mProgressBusy;
+ bool mProgressStop;
+
+ CHexViewWidget *mHexView;
+ CGotoDialog *mGotoDialog;
+ CFindDialog *mFindDialog;
+ CReplaceDialog *mReplaceDialog;
+ CInsertDialog *mInsertDialog;
+ CFilterDialog *mFilterDialog;
+ COptionDialog *mOptionDialog;
+ CStringDialog *mStringDialog;
+ CCharTableDialog *mCharTableDialog;
+ CFileInfoDialog *mFileInfoDialog;
+ CExportDialog *mExportDialog;
+ CConverterDialog *mConverterDialog;
+ CFindNavigatorDialog *mFindNavigatorDialog;
+ CReplacePromptDialog *mReplacePromptDialog;
+};
+
+inline int CHexEditorWidget::defaultTextWidth( void )
+{
+ return( mHexView->defaultWidth() );
+}
+
+inline CHexViewWidget *CHexEditorWidget::view( void )
+{
+ return( mHexView );
+}
+
+inline SDisplayLayout &CHexEditorWidget::layout( void )
+{
+ return( mDisplayState.layout );
+}
+
+inline SDisplayLine &CHexEditorWidget::line( void )
+{
+ return( mDisplayState.line );
+}
+
+inline SDisplayInputMode &CHexEditorWidget::inputMode( void )
+{
+ return( mDisplayState.input );
+}
+
+inline SDisplayMisc::EOpenFile CHexEditorWidget::openFile( void )
+{
+ return( mDisplayState.misc.openFile );
+}
+
+inline bool CHexEditorWidget::discardRecentFiles( void )
+{
+ return( mDisplayState.misc.discardRecent );
+}
+
+inline bool CHexEditorWidget::gotoStartupOffset( void )
+{
+ return( mDisplayState.misc.gotoOnStartup );
+}
+
+inline bool CHexEditorWidget::gotoReloadOffset( void )
+{
+ return( mDisplayState.misc.gotoOnReload );
+}
+
+
+
+#endif
+
+
+
diff --git a/khexedit/hexeditstate.h b/khexedit/hexeditstate.h
new file mode 100644
index 0000000..f3f8fff
--- /dev/null
+++ b/khexedit/hexeditstate.h
@@ -0,0 +1,596 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _HEX_EDIT_STATE_H_
+#define _HEX_EDIT_STATE_H_
+
+#include <kapplication.h>
+#include <qfont.h>
+#include <qpalette.h>
+#include <kglobalsettings.h>
+
+
+class SDisplayLine
+{
+ public:
+ enum EViewMode
+ {
+ hexadecimal = 0,
+ decimal,
+ octal,
+ binary,
+ textOnly
+ };
+
+ SDisplayLine( void )
+ {
+ lineSize[hexadecimal] = 16;
+ lineSize[decimal] = 16;
+ lineSize[octal] = 16;
+ lineSize[binary] = 8;
+ lineSize[textOnly] = 64;
+
+ columnSize[hexadecimal] = 1;
+ columnSize[decimal] = 1;
+ columnSize[octal] = 1;
+ columnSize[binary] = 1;
+ columnSize[textOnly] = 64;
+ }
+
+ uint getLineSize( int index )
+ {
+ return( lineSize[ index > textOnly ? 0 : index ] );
+ }
+
+ uint getColumnSize( int index )
+ {
+ return( columnSize[ index > textOnly ? 0 : index ] );
+ }
+
+ void setLineSize( int index, uint value )
+ {
+ if( index <= textOnly ) { lineSize[ index ] = value; }
+ }
+
+ void setColumnSize( int index, uint value )
+ {
+ if( index <= textOnly ) { columnSize[ index ] = value; }
+ }
+
+ uint lineSize[5];
+ uint columnSize[5];
+};
+
+
+class SDisplayLayout
+{
+ public:
+ enum EViewMode
+ {
+ hexadecimal = 0,
+ decimal,
+ octal,
+ binary,
+ textOnly,
+ hide
+ };
+
+ SDisplayLayout( void )
+ {
+ offsetMode = hexadecimal;
+ primaryMode = hexadecimal;
+ secondaryMode = textOnly;
+ offsetUpperCase = false;
+ primaryUpperCase = false;
+ offsetVisible = true;
+ lineSize = 16;
+ columnSize = 1;
+ lockLine = true;
+ lockColumn = true;
+ columnCharSpace = true;
+ columnSpacing = 5;
+ separatorMarginWidth = 5;
+ edgeMarginWidth = 5;
+ leftSeparatorWidth = 1;
+ rightSeparatorWidth = 1;
+ horzGridWidth = 0;
+ vertGridWidth = 0;
+ }
+
+ void verify( void )
+ {
+ if( lineSize < 1 ) { lineSize = 1; }
+ if( columnSize < 1 ) { columnSize = 1; }
+ if( columnSize > lineSize ) { columnSize = lineSize; }
+ if( primaryMode == textOnly ) { secondaryMode = hide; columnSpacing=0; }
+ if( columnSpacing == 0 ) { columnSize = lineSize; }
+ if( horzGridWidth > 1 ) { horzGridWidth = 1; }
+ if( vertGridWidth > 1 ) { vertGridWidth = 1; }
+ }
+
+ bool showSecondary( void )
+ {
+ if( primaryMode == textOnly || secondaryMode == hide )
+ {
+ return( false );
+ }
+ else
+ {
+ return( true );
+ }
+ }
+
+ QString modeStrings( uint index )
+ {
+ if( index == hexadecimal )
+ {
+ return( "hexadecimal" );
+ }
+ else if( index == decimal )
+ {
+ return( "decimal" );
+ }
+ else if( index == octal )
+ {
+ return( "octal" );
+ }
+ else if( index == binary )
+ {
+ return( "binary" );
+ }
+ else if( index == textOnly )
+ {
+ return( "textOnly" );
+ }
+ else
+ {
+ return( "hide" );
+ }
+ }
+
+
+ QString primaryModeString( void )
+ {
+ return( modeStrings( primaryMode > textOnly ?
+ hexadecimal : primaryMode ));
+ }
+
+ QString secondaryModeString( void )
+ {
+ return( modeStrings( secondaryMode == textOnly ? textOnly : hide ) );
+ }
+
+ QString offsetModeString( void )
+ {
+ return( modeStrings( offsetMode == hexadecimal ? hexadecimal : hide ) );
+ }
+
+ QString gridModeString( void )
+ {
+ if( horzGridWidth == 0 && vertGridWidth == 0 )
+ {
+ return( "none");
+ }
+ else if( horzGridWidth != 0 && vertGridWidth != 0 )
+ {
+ return( "both");
+ }
+ else if( horzGridWidth != 0 )
+ {
+ return( "horizontal");
+ }
+ else
+ {
+ return( "vertical");
+ }
+ }
+
+ void setPrimaryMode( const QString & str )
+ {
+ if( str.isNull() || str == "hexadecimal" )
+ {
+ primaryMode = hexadecimal;
+ }
+ else if( str == "decimal" )
+ {
+ primaryMode = decimal;
+ }
+ else if( str == "octal" )
+ {
+ primaryMode = octal;
+ }
+ else if( str == "binary" )
+ {
+ primaryMode = binary;
+ }
+ else if( str == "textOnly" )
+ {
+ primaryMode = textOnly;
+ }
+ else
+ {
+ primaryMode = hexadecimal;
+ }
+ }
+
+ void setSecondaryMode( const QString & str )
+ {
+ if( str.isNull() || str == "textOnly" )
+ {
+ secondaryMode = textOnly;
+ }
+ else
+ {
+ secondaryMode = hide;
+ }
+ }
+
+ void setOffsetMode( const QString & str )
+ {
+ if( str.isNull() || str == "hexadecimal" )
+ {
+ offsetMode = hexadecimal;
+ }
+ else
+ {
+ offsetMode = decimal;
+ }
+ }
+
+ void setGridMode( const QString & str )
+ {
+ if( str.isNull() || str == "none" )
+ {
+ horzGridWidth = vertGridWidth = 0;
+ }
+ else if( str == "vertical" )
+ {
+ horzGridWidth = 0;
+ vertGridWidth = 1;
+ }
+ else if( str == "horizontal" )
+ {
+ horzGridWidth = 1;
+ vertGridWidth = 0;
+ }
+ else if( str == "both" )
+ {
+ horzGridWidth = vertGridWidth = 1;
+ }
+ else
+ {
+ horzGridWidth = vertGridWidth = 0;
+ }
+ }
+
+ EViewMode offsetMode;
+ EViewMode primaryMode;
+ EViewMode secondaryMode;
+ bool offsetUpperCase;
+ bool primaryUpperCase;
+ bool offsetVisible;
+ bool lockLine;
+ bool lockColumn;
+ uint lineSize;
+ uint columnSize;
+ bool columnCharSpace;
+ uint columnSpacing;
+ uint separatorMarginWidth;
+ uint edgeMarginWidth;
+ uint leftSeparatorWidth;
+ uint rightSeparatorWidth;
+ uint horzGridWidth;
+ uint vertGridWidth;
+};
+
+
+
+
+class SDisplayCursor
+{
+ public:
+ enum EFocusMode
+ {
+ stopBlinking = 0,
+ hide,
+ ignore
+ };
+
+ SDisplayCursor( void )
+ {
+ focusMode = hide;
+ interval = 500;
+ alwaysVisible = false;
+ alwaysBlockShape = false;
+ thickInsertShape = true;
+ }
+
+ QString modeStrings( uint index )
+ {
+ if( index == hide )
+ {
+ return( "hide" );
+ }
+ else if( index == ignore )
+ {
+ return( "ignore" );
+ }
+ else
+ {
+ return( "stopBlinking" );
+ }
+ }
+
+ QString focusModeString( void )
+ {
+ return( modeStrings( focusMode > ignore ? stopBlinking : focusMode ));
+ }
+
+ void setFocusMode( const QString & str )
+ {
+ if( str.isNull() || str == "hide" )
+ {
+ focusMode = hide;
+ }
+ else if( str == "stopBlinking" )
+ {
+ focusMode = stopBlinking;
+ }
+ else
+ {
+ focusMode = ignore;
+ }
+ }
+
+ EFocusMode focusMode;
+ uint interval;
+ bool alwaysVisible;
+ bool alwaysBlockShape;
+ bool thickInsertShape;
+};
+
+
+class SDisplayColor
+{
+ public:
+
+ SDisplayColor( void )
+ {
+ //
+ // Default colors. The selection colors will always be the one
+ // choses in Control Center.
+ //
+ useSystemColor = false;
+ offsetBg = Qt::white;
+ textBg = Qt::white;
+ secondTextBg = Qt::white;
+ inactiveBg = Qt::gray;
+ selectBg = kapp->palette().active().highlight();
+ selectFg = kapp->palette().active().highlightedText();
+ markBg = Qt::blue;
+ markFg = Qt::white;
+ primaryFg[0] = Qt::black;
+ primaryFg[1] = Qt::blue;
+ offsetFg = Qt::red;
+ secondaryFg = Qt::black;
+ nonPrintFg = Qt::red;
+ gridFg = Qt::darkCyan;
+ leftSeparatorFg = Qt::darkGreen;
+ rightSeparatorFg = Qt::darkGreen;
+ cursorBg = Qt::red;
+ cursorFg = Qt::black;
+ bookmarkBg = Qt::green;
+ bookmarkFg = Qt::black;
+ }
+
+ bool useSystemColor;
+ QColor offsetBg;
+ QColor textBg;
+ QColor secondTextBg;
+ QColor inactiveBg;
+ QColor selectBg;
+ QColor selectFg;
+ QColor markBg;
+ QColor markFg;
+ QColor primaryFg[2];
+ QColor offsetFg;
+ QColor secondaryFg;
+ QColor nonPrintFg;
+ QColor gridFg;
+ QColor leftSeparatorFg;
+ QColor rightSeparatorFg;
+ QColor cursorBg;
+ QColor cursorFg;
+ QColor bookmarkBg;
+ QColor bookmarkFg;
+};
+
+
+class SDisplayFontInfo
+{
+ public:
+
+ SDisplayFontInfo &init( void )
+ {
+ font = KGlobalSettings::fixedFont();
+ nonPrintChar = '.';
+ return( *this );
+ }
+
+ QFont font;
+ QChar nonPrintChar;
+};
+
+class SDisplayFont
+{
+ public:
+ SDisplayFont( void )
+ {
+ useSystemFont = false;
+ localFont = KGlobalSettings::fixedFont();
+ nonPrintChar = '.';
+ }
+
+ bool useSystemFont;
+ QFont localFont;
+ QChar nonPrintChar;
+};
+
+
+class SDisplayMisc
+{
+ public:
+
+ enum EOpenFile
+ {
+ none = 0,
+ mostRecent,
+ allRecent
+ };
+
+ SDisplayMisc( void )
+ {
+ undoLevel = 100;
+ openFile = none;
+ inputSound = false;
+ fatalSound = false;
+ autoCopyToClipboard = true;
+ insertMode = false;
+ writeProtect = false;
+ confirmWrap = true;
+ cursorJump = true;
+ makeBackup = false;
+ confirmThreshold = true;
+ thresholdValue = 30;
+ discardRecent = false;
+ gotoOnStartup = false;
+ gotoOnReload = true;
+ bookmarkOffsetColumn = true;
+ bookmarkEditor = true;
+ }
+
+
+ QString fileStrings( uint index )
+ {
+ if( index == mostRecent )
+ {
+ return( "mostRecent" );
+ }
+ else if( index == allRecent )
+ {
+ return( "allRecent" );
+ }
+ else
+ {
+ return( "none" );
+ }
+ }
+
+
+ QString openFileString( void )
+ {
+ return( fileStrings( openFile > allRecent ? none : openFile ));
+ }
+
+ void setOpenFile( const QString &str )
+ {
+ if( str.isNull() == true || str == "none" )
+ {
+ openFile = none;
+ }
+ else if( str == "mostRecent" )
+ {
+ openFile = mostRecent;
+ }
+ else if( str == "allRecent" )
+ {
+ openFile = allRecent;
+ }
+ else
+ {
+ openFile = none;
+ }
+ }
+
+ uint undoLevel;
+ EOpenFile openFile;
+ bool inputSound;
+ bool fatalSound;
+ bool autoCopyToClipboard;
+ bool insertMode;
+ bool writeProtect;
+ bool confirmWrap;
+ bool cursorJump;
+ bool makeBackup;
+ bool confirmThreshold;
+ uint thresholdValue;
+ bool discardRecent;
+ bool gotoOnStartup;
+ bool gotoOnReload;
+ bool bookmarkOffsetColumn;
+ bool bookmarkEditor;
+};
+
+
+class SDisplayInputMode
+{
+ public:
+ SDisplayInputMode( void )
+ {
+ inputLock = false;
+ readOnly = false;
+ allowResize = true;
+ };
+
+ bool noInput( void )
+ {
+ return( inputLock || readOnly );
+ }
+
+ bool inputLock; // Set by application only
+ bool readOnly; // Set by user
+ bool allowResize;
+};
+
+
+class SDisplayState
+{
+ public:
+ SDisplayLine line;
+ SDisplayLayout layout;
+ SDisplayCursor cursor;
+ SDisplayColor color;
+ SDisplayFont font;
+ SDisplayMisc misc;
+ SDisplayInputMode input;
+};
+
+
+
+
+
+#endif
+
+
+
+
+
+
+
diff --git a/khexedit/hexerror.cc b/khexedit/hexerror.cc
new file mode 100644
index 0000000..ac179e6
--- /dev/null
+++ b/khexedit/hexerror.cc
@@ -0,0 +1,69 @@
+/*
+ * 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 <klocale.h>
+
+#include "hexerror.h"
+
+static QString message;
+
+
+const QString &hexError( int index )
+{
+ static QString messages[ Err_MAXERROR - Err_NoData ] =
+ {
+ i18n("No data"), // Err_NoData
+ i18n("Insufficient memory"), // Err_NoMemory
+ i18n("List is full"), // Err_ListFull
+ i18n("Read operation failed"), // Err_ReadFailed
+ i18n("Write operation failed"), // Err_WriteFailed
+ i18n("Empty argument"), // Err_EmptyArgument
+ i18n("Illegal argument"), // Err_IllegalArgument
+ i18n("Null pointer argument"), // Err_NullArgument
+ i18n("Wrap buffer"), // Err_WrapBuffer
+ i18n("No match"), // Err_NoMatch
+ i18n("No data is selected"), // Err_NoSelection
+ i18n("Empty document"), // Err_EmptyDocument
+ i18n("No active document"), // Err_NoActiveDocument
+ i18n("No data is marked"), // Err_NoMark
+ i18n("Document is write protected"), // Err_WriteProtect
+ i18n("Document is resize protected"), // Err_NoResize
+ i18n("Operation was stopped"), // Err_Stop
+ i18n("Illegal mode"), // Err_IllegalMode
+ i18n("Program is busy, try again later"), // Err_Busy
+ i18n("Value is not within valid range"), // Err_IllegalRange
+ i18n("Operation was aborted"), // Err_OperationAborted
+ i18n("File could not be opened for writing"), // Err_OpenWriteFailed
+ i18n("File could not be opened for reading"), // Err_OpenReadFailed
+ };
+
+
+ if( index < Err_NoData || index >= Err_MAXERROR )
+ {
+ message = i18n("Unknown error");
+ }
+ else
+ {
+ message = messages[ index - Err_NoData ];
+ }
+
+ return( message );
+}
+
diff --git a/khexedit/hexerror.h b/khexedit/hexerror.h
new file mode 100644
index 0000000..d17d302
--- /dev/null
+++ b/khexedit/hexerror.h
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _HEX_ERROR_H_
+#define _HEX_ERROR_H_
+
+enum EHexError
+{
+ Err_NoErr = 0,
+ Err_Success = 0,
+ Err_NoData = -10000, // Must be the first
+ Err_NoMemory,
+ Err_ListFull,
+ Err_ReadFailed,
+ Err_WriteFailed,
+ Err_EmptyArgument,
+ Err_IllegalArgument,
+ Err_NullArgument,
+ Err_WrapBuffer,
+ Err_NoMatch,
+ Err_NoSelection,
+ Err_EmptyDocument,
+ Err_NoActiveDocument,
+ Err_NoMark,
+ Err_WriteProtect,
+ Err_NoResize,
+ Err_Stop,
+ Err_IllegalMode,
+ Err_Busy,
+ Err_IllegalRange,
+ Err_OperationAborted,
+ Err_OpenWriteFailed,
+ Err_OpenReadFailed,
+ Err_MAXERROR // Must be the last
+};
+
+const QString &hexError( int index );
+
+
+#endif
diff --git a/khexedit/hexmanagerwidget.cc b/khexedit/hexmanagerwidget.cc
new file mode 100644
index 0000000..1073b95
--- /dev/null
+++ b/khexedit/hexmanagerwidget.cc
@@ -0,0 +1,370 @@
+/*
+ * khexedit - Versatile hex editor
+ * Copyright (C) 1999-2000 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 <klocale.h>
+#include <qlayout.h>
+#include "hexmanagerwidget.h"
+#include "searchbar.h"
+
+CHexManagerWidget::CHexManagerWidget( QWidget *parent, const char *name,
+ EConversionPosition conversionPosition,
+ EPosition tabBarPosition,
+ EPosition searchBarPosition )
+ : QWidget( parent, name )
+{
+ mValid = false;
+
+ mEditor = new CHexEditorWidget( this );
+ mTabBar = new CTabBar( this );
+ mTabBar->hide();
+ mSearchBar = 0;
+
+ mConverter = new CHexToolWidget( this );
+
+ connect( mEditor->view(), SIGNAL(fileName(const QString &, bool)),
+ this, SLOT( addName(const QString &)));
+ connect( mEditor->view(), SIGNAL( fileClosed(const QString &)),
+ this, SLOT( removeName(const QString &)));
+ connect( mEditor->view(),SIGNAL(fileRename(const QString &,const QString &)),
+ this, SLOT(changeName(const QString &,const QString &)));
+ connect( mEditor->view(), SIGNAL( cursorChanged( SCursorState & ) ),
+ mConverter, SLOT( cursorChanged( SCursorState & ) ) );
+ connect( mConverter, SIGNAL( closed(void) ),
+ this, SIGNAL( conversionClosed(void) ) );
+ connect( mTabBar, SIGNAL(selected(const QString &)),
+ this, SLOT(open(const QString &)));
+
+ mValid = true;
+ setConversionVisibility( conversionPosition );
+ setTabBarPosition( tabBarPosition );
+ setSearchBarPosition( searchBarPosition );
+}
+
+
+CHexManagerWidget::~CHexManagerWidget( void )
+{
+ delete mEditor;
+ delete mTabBar;
+ delete mConverter;
+}
+
+
+void CHexManagerWidget::updateLayout( void )
+{
+ if( mValid == false ) { return; }
+
+ delete layout();
+ QVBoxLayout *vlay = new QVBoxLayout( this, 0, 0 );
+
+ if( mSearchBar && mSearchBarPosition == AboveEditor )
+ {
+ vlay->addWidget( mSearchBar );
+ }
+
+ if( mTabPosition == AboveEditor )
+ {
+ vlay->addWidget( mTabBar );
+ vlay->addWidget( mEditor, 1 );
+ }
+ else
+ {
+ vlay->addWidget( mEditor, 1 );
+ vlay->addWidget( mTabBar );
+ }
+
+ if( mSearchBar && mSearchBarPosition == BelowEditor )
+ {
+ vlay->addWidget( mSearchBar );
+ }
+
+ if( mConversionPosition == Embed )
+ {
+ vlay->addWidget( mConverter );
+ }
+ vlay->activate(); // Required in this case
+}
+
+
+void CHexManagerWidget::setConversionVisibility( EConversionPosition position )
+{
+ if( mValid == false )
+ {
+ return;
+ }
+
+ if( mConversionPosition == position )
+ {
+ if( mConversionPosition == Float )
+ {
+ mConverter->raise();
+ }
+ return;
+ }
+
+ mConversionPosition = position;
+ if( mConversionPosition == Hide )
+ {
+ mConverter->hide();
+ }
+ else if( mConversionPosition == Float )
+ {
+ QPoint point = mapToGlobal( QPoint(0,0) );
+ QRect rect = geometry();
+ QPoint p;
+
+ p.setX(point.x() + rect.width()/2 - mConverter->minimumSize().width()/2);
+ p.setY(point.y() + rect.height()/2 - mConverter->minimumSize().height()/2);
+ mConverter->resize( mConverter->minimumSize() );
+ mConverter->reparent( 0, WStyle_Customize | WStyle_DialogBorder, p, true );
+ mConverter->setCaption(kapp->makeStdCaption(i18n("Conversion")));
+ }
+ else
+ {
+ mConversionPosition = Embed;
+ uint utilHeight = mConverter->minimumSize().height();
+ QPoint p( 0, height() - utilHeight );
+ mConverter->reparent( this, 0, p, true );
+ }
+
+ updateLayout();
+}
+
+
+void CHexManagerWidget::setTabBarPosition( EPosition position )
+{
+ mTabPosition = position;
+ if( mTabPosition != HideItem && mTabBar->count() > 0 )
+ {
+ if( mTabPosition == AboveEditor )
+ {
+ mTabBar->setShape( QTabBar::RoundedAbove );
+ }
+ else
+ {
+ mTabBar->setShape( QTabBar::RoundedBelow );
+ }
+ mTabBar->show();
+ }
+ else
+ {
+ mTabBar->hide();
+ }
+
+ updateLayout();
+}
+
+
+void CHexManagerWidget::setSearchBarPosition( EPosition position )
+{
+ mSearchBarPosition = position;
+ if( position != HideItem )
+ {
+ if( mSearchBar == 0 )
+ {
+ mSearchBar = new CSearchBar( this );
+ connect( mSearchBar, SIGNAL(hidden()), this, SLOT(searchBarHidden()) );
+ connect( mSearchBar, SIGNAL(findData(SSearchControl &, uint, bool)),
+ mEditor, SLOT(findData(SSearchControl &, uint, bool)) );
+ connect( editor()->view(), SIGNAL( cursorChanged( SCursorState & ) ),
+ mSearchBar, SLOT( cursorMoved() ) );
+ }
+ mSearchBar->show();
+ }
+ else
+ {
+ if( mSearchBar != 0 )
+ {
+ mSearchBar->hide();
+ }
+ }
+
+ updateLayout();
+}
+
+
+void CHexManagerWidget::searchBarHidden( void )
+{
+ updateLayout();
+ mSearchBarPosition = HideItem;
+ emit searchBarClosed();
+}
+
+
+void CHexManagerWidget::addName( const QString &name )
+{
+ if( name.isEmpty() == true )
+ {
+ return;
+ }
+
+ mTabBar->addName( name );
+ if( mTabBar->isVisible() == false && mTabPosition != HideItem )
+ {
+ setTabBarPosition( mTabPosition );
+ }
+}
+
+
+void CHexManagerWidget::removeName( const QString &name )
+{
+ mTabBar->removeName( name );
+ if( mTabBar->isVisible() == true && mTabBar->count() == 0 )
+ {
+ setTabBarPosition( mTabPosition );
+ }
+}
+
+
+void CHexManagerWidget::changeName( const QString &curName,
+ const QString &newName )
+{
+ mTabBar->changeName( curName, newName );
+}
+
+
+void CHexManagerWidget::open( const QString &name )
+{
+ mEditor->open( name, false, 0 );
+}
+
+
+int CHexManagerWidget::preferredWidth( void )
+{
+ int w = mEditor->defaultTextWidth();
+ if( mConversionPosition == Embed )
+ {
+ int converterWidth = mConverter->sizeHint().width();
+ w = QMAX( w, converterWidth );
+ }
+ return( w );
+}
+
+
+
+CTabBar::CTabBar( QWidget *parent, char *name )
+ :QTabBar( parent, name )
+{
+ connect( this, SIGNAL(selected(int)), this, SLOT(slotSelected(int)) );
+}
+
+
+void CTabBar::addName( const QString &name )
+{
+ QString n( name.right(name.length()-name.findRev('/')-1) );
+
+ QTab *t = find( n );
+ if( t == 0 )
+ {
+ t = new QTab();
+ t->setText( n);
+ int id = addTab( t );
+ mFileList.append( CFileKey(name,id) );
+ }
+ setCurrentTab(t);
+}
+
+
+void CTabBar::removeName( const QString &name )
+{
+ QString n( name.right(name.length()-name.findRev('/')-1) );
+ QTab *t = find(n);
+ if( t == 0 )
+ {
+ return;
+ }
+
+ QValueList<CFileKey>::Iterator it;
+ for( it = mFileList.begin(); it != mFileList.end(); ++it )
+ {
+ if( (*it).id() == t->identifier() )
+ {
+ mFileList.remove(it);
+ removeTab(t);
+ layoutTabs();
+ break;
+ }
+ }
+}
+
+
+void CTabBar::changeName( const QString &curName, const QString &newName )
+{
+ QString n( curName.right(curName.length()-curName.findRev('/')-1) );
+ QTab *t = find(n);
+ if( t == 0 )
+ {
+ return;
+ }
+
+ QValueList<CFileKey>::Iterator it;
+ for( it = mFileList.begin(); it != mFileList.end(); ++it )
+ {
+ if( (*it).id() == t->identifier() )
+ {
+ QString m( newName.right(newName.length()-newName.findRev('/')-1) );
+ t->setText(m);
+
+ mFileList.remove(it);
+ mFileList.append( CFileKey(newName,t->identifier()) );
+ layoutTabs();
+ update(); // Seems to be necessary
+ break;
+ }
+ }
+}
+
+
+QTab *CTabBar::find( const QString &name )
+{
+ QPtrList<QTab> &list = *tabList();
+ for( QTab *t = list.first(); t != 0; t = list.next() )
+ {
+ if( t->text() == name )
+ {
+ return( t );
+ }
+ }
+
+ return( 0 );
+}
+
+
+int CTabBar::count( void )
+{
+ return( tabList()->count() );
+}
+
+
+void CTabBar::slotSelected( int id )
+{
+ QValueList<CFileKey>::Iterator it;
+ for( it = mFileList.begin(); it != mFileList.end(); ++it )
+ {
+ if( (*it).id() == id )
+ {
+ emit selected( (*it).filename() );
+ }
+ }
+}
+
+
+
+
+#include "hexmanagerwidget.moc"
diff --git a/khexedit/hexmanagerwidget.h b/khexedit/hexmanagerwidget.h
new file mode 100644
index 0000000..08924da
--- /dev/null
+++ b/khexedit/hexmanagerwidget.h
@@ -0,0 +1,202 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _HEX_MANAGER_WIDGET_H_
+#define _HEX_MANAGER_WIDGET_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qtabbar.h>
+#include <qvaluelist.h>
+#include <qwidget.h>
+
+#include "hexeditorwidget.h"
+#include "hextoolwidget.h"
+
+class CSearchBar;
+
+
+class CFileKey
+{
+ public:
+ CFileKey( const QString &fname, int fid )
+ {
+ mFilename = fname;
+ mId = fid;
+ }
+
+ CFileKey( const CFileKey & k )
+ {
+ mFilename = k.mFilename;
+ mId = k.mId;
+ }
+
+ CFileKey( void )
+ {
+ }
+
+ QString filename( void ) const
+ {
+ return( mFilename );
+ }
+
+ int id() const
+ {
+ return( mId );
+ }
+
+ private:
+ QString mFilename;
+ int mId;
+};
+
+
+
+
+class CTabBar : public QTabBar
+{
+ Q_OBJECT
+
+ public:
+ CTabBar( QWidget *parent=0, char *name=0 );
+ void addName( const QString &name );
+ void removeName( const QString &name );
+ void changeName( const QString &curName, const QString &newName );
+ int count( void );
+
+ protected slots:
+ void slotSelected( int id );
+
+ private:
+ QTab *find( const QString &name );
+
+ private:
+ QValueList<CFileKey> mFileList;
+
+ signals:
+ void selected( const QString &filename );
+};
+
+
+class CHexManagerWidget : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ enum EConversionPosition
+ {
+ Hide,
+ Float,
+ Embed
+ };
+
+ enum EPosition
+ {
+ HideItem = 0,
+ AboveEditor,
+ BelowEditor
+ };
+
+ public:
+ CHexManagerWidget( QWidget *parent = 0, const char *name = 0,
+ EConversionPosition state = Embed,
+ EPosition tabBarPosition = HideItem,
+ EPosition searchBarPosition = HideItem );
+ ~CHexManagerWidget( void );
+
+ inline bool isValid( void );
+ inline CHexEditorWidget *editor( void );
+ inline CHexToolWidget *converter( void );
+ inline EConversionPosition conversionPosition( void );
+ inline EPosition tabBarPosition( void );
+ inline EPosition searchBarPosition( void );
+
+ int preferredWidth( void );
+
+ public slots:
+ void setConversionVisibility( EConversionPosition position );
+ void setTabBarPosition( EPosition position );
+ void setSearchBarPosition( EPosition position );
+ void addName( const QString &name );
+ void removeName( const QString &name );
+ void changeName( const QString &curName, const QString &newName );
+
+ protected slots:
+ void open( const QString &name );
+ void searchBarHidden( void );
+
+ private:
+ void updateLayout( void );
+
+ signals:
+ void conversionClosed( void );
+ void searchBarClosed( void );
+
+ private:
+ bool mValid;
+ bool mEnableTabBar;
+ EConversionPosition mConversionPosition;
+ EPosition mTabPosition;
+ EPosition mSearchBarPosition;
+ CHexEditorWidget *mEditor;
+ CTabBar *mTabBar;
+ CHexToolWidget *mConverter;
+ CSearchBar *mSearchBar;
+};
+
+
+inline bool CHexManagerWidget::isValid( void )
+{
+ return( mValid );
+}
+
+inline CHexEditorWidget *CHexManagerWidget::editor( void )
+{
+ return( mEditor );
+}
+
+inline CHexToolWidget *CHexManagerWidget::converter( void )
+{
+ return( mConverter );
+}
+
+inline CHexManagerWidget::EConversionPosition
+ CHexManagerWidget::conversionPosition( void )
+{
+ return( mConversionPosition );
+}
+
+inline CHexManagerWidget::EPosition CHexManagerWidget::tabBarPosition( void )
+{
+ return( mTabPosition );
+}
+
+inline CHexManagerWidget::EPosition CHexManagerWidget::searchBarPosition(void)
+{
+ return( mSearchBarPosition );
+}
+
+
+
+
+#endif
+
diff --git a/khexedit/hexprinter.cc b/khexedit/hexprinter.cc
new file mode 100644
index 0000000..0127751
--- /dev/null
+++ b/khexedit/hexprinter.cc
@@ -0,0 +1,168 @@
+/*
+ * 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 "hexprinter.h"
+
+
+CHexPrinter::CHexPrinter( void )
+ : KPrinter()
+{
+}
+
+
+void CHexPrinter::setPageMarginMM( uint top, uint bottom, int right, int left )
+{
+ mPageMargin.top = top;
+ mPageMargin.left = left;
+ mPageMargin.bottom = bottom;
+ mPageMargin.right = right;
+}
+
+void CHexPrinter::setTopMarginMM( uint value )
+{
+ mPageMargin.top = value;
+}
+
+void CHexPrinter::setLeftMarginMM( uint value )
+{
+ mPageMargin.left = value;
+}
+
+void CHexPrinter::setBottomMarginMM( uint value )
+{
+ mPageMargin.bottom = value;
+}
+
+void CHexPrinter::setRightMarginMM( uint value )
+{
+ mPageMargin.right = value;
+}
+
+
+
+void CHexPrinter::setPageHeader( bool enable, uint left, uint center,
+ uint right, uint line )
+{
+ if( left > SPageHeader::FileName ) { left = SPageHeader::NoString; }
+ if( center > SPageHeader::FileName ) { center = SPageHeader::NoString; }
+ if( right > SPageHeader::FileName ) { right = SPageHeader::NoString; }
+ if( line > SPageHeader::Rectangle ) { line = SPageHeader::NoLine; }
+
+ mHeader.enable = enable;
+ mHeader.pos[0] = (SPageHeader::EHeaderString)left;
+ mHeader.pos[1] = (SPageHeader::EHeaderString)center;
+ mHeader.pos[2] = (SPageHeader::EHeaderString)right;
+ mHeader.line = (SPageHeader::EHeaderLine)line;
+
+ if( mHeader.pos[0] == SPageHeader::NoString &&
+ mHeader.pos[1] == SPageHeader::NoString &&
+ mHeader.pos[2] == SPageHeader::NoString &&
+ mHeader.line == SPageHeader::NoLine )
+ {
+ mHeader.enable = false;
+ }
+}
+
+void CHexPrinter::setPageFooter( bool enable, uint left, uint center,
+ uint right, uint line )
+{
+ if( left > SPageHeader::FileName ) { left = SPageHeader::NoString; }
+ if( center > SPageHeader::FileName ) { center = SPageHeader::NoString; }
+ if( right > SPageHeader::FileName ) { right = SPageHeader::NoString; }
+ if( line > SPageHeader::Rectangle ) { line = SPageHeader::NoLine; }
+
+ mFooter.enable = enable;
+ mFooter.pos[0] = (SPageHeader::EHeaderString)left;
+ mFooter.pos[1] = (SPageHeader::EHeaderString)center;
+ mFooter.pos[2] = (SPageHeader::EHeaderString)right;
+ mFooter.line = (SPageHeader::EHeaderLine)line;
+
+ if( mFooter.pos[0] == SPageHeader::NoString &&
+ mFooter.pos[1] == SPageHeader::NoString &&
+ mFooter.pos[2] == SPageHeader::NoString &&
+ mFooter.line == SPageHeader::NoLine )
+ {
+ mFooter.enable = false;
+ }
+}
+
+
+SPageMargin CHexPrinter::pageMargin( void )
+{
+ QPaintDeviceMetrics metric( this );
+ float f = (float)metric.width()/(float)metric.widthMM();
+
+ SPageMargin margin;
+ margin.top = (uint) (f*(float)mPageMargin.top);
+ margin.right = (uint) (f*(float)mPageMargin.right);
+ margin.bottom = (uint) (f*(float)mPageMargin.bottom);
+ margin.left = (uint) (f*(float)mPageMargin.left);
+
+ return( margin );
+}
+
+
+SPageMargin CHexPrinter::pageMarginMM( void )
+{
+ return( mPageMargin );
+}
+
+
+SPageSize CHexPrinter::pageFullSize( void )
+{
+ QPaintDeviceMetrics metric( this );
+ SPageSize size;
+ size.width = metric.width();
+ size.height = metric.height();
+
+ return( size );
+}
+
+
+SPageSize CHexPrinter::pageUsableSize( void )
+{
+ QPaintDeviceMetrics metric( this );
+ SPageMargin margin = pageMargin();
+ SPageSize size;
+
+ uint mw = margin.left + margin.right;
+ if( metric.width() <= (int)mw )
+ {
+ size.width = 1;
+ }
+ else
+ {
+ size.width = metric.width() - mw;
+ }
+
+ uint mh = margin.top + margin.bottom;
+ if( metric.height() <= (int)mh )
+ {
+ size.height = 1;
+ }
+ else
+ {
+ size.height = metric.height() - mh;
+ }
+
+ return( size );
+}
+
diff --git a/khexedit/hexprinter.h b/khexedit/hexprinter.h
new file mode 100644
index 0000000..2d6eeba
--- /dev/null
+++ b/khexedit/hexprinter.h
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _HEX_PRINTER_H_
+#define _HEX_PRINTER_H_
+
+#include <kprinter.h>
+#include <qpaintdevicemetrics.h>
+
+struct SPageSize
+{
+ uint width;
+ uint height;
+};
+
+struct SPageMargin
+{
+ uint top;
+ uint right;
+ uint bottom;
+ uint left;
+};
+
+
+struct SPageHeader
+{
+ enum EHeaderString
+ {
+ NoString = 0,
+ DateTime,
+ PageNumber,
+ FileName
+ };
+
+ enum EHeaderLine
+ {
+ NoLine = 0,
+ SingleLine,
+ Rectangle
+ };
+
+ bool enable;
+ EHeaderString pos[3]; // left, center, right
+ EHeaderLine line;
+};
+
+
+
+
+class CHexPrinter : public KPrinter
+{
+ public:
+ CHexPrinter( void );
+
+ void setPageMarginMM( uint top, uint bottom, int right, int left );
+ void setTopMarginMM( uint value );
+ void setLeftMarginMM( uint value );
+ void setBottomMarginMM( uint value );
+ void setRightMarginMM( uint value );
+ void setPageHeader( bool enable, uint left, uint center, uint right,
+ uint line );
+ void setPageFooter( bool enable, uint left, uint center, uint right,
+ uint line );
+
+ inline SPageHeader pageHeader( void );
+ inline SPageHeader pageFooter( void );
+ SPageMargin pageMargin( void );
+ SPageMargin pageMarginMM( void );
+ SPageSize pageFullSize( void );
+ SPageSize pageUsableSize( void );
+
+ private:
+ SPageMargin mPageMargin;
+ SPageHeader mHeader;
+ SPageHeader mFooter;
+
+
+};
+
+
+inline SPageHeader CHexPrinter::pageHeader( void )
+{
+ return( mHeader );
+}
+
+inline SPageHeader CHexPrinter::pageFooter( void )
+{
+ return( mFooter );
+}
+
+#endif
diff --git a/khexedit/hextoolwidget.cc b/khexedit/hextoolwidget.cc
new file mode 100644
index 0000000..f0baf09
--- /dev/null
+++ b/khexedit/hextoolwidget.cc
@@ -0,0 +1,416 @@
+/*
+ * 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 <kdialog.h>
+#include <klocale.h>
+
+#include "hextoolwidget.h"
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+
+
+CHexToolWidget::CHexToolWidget( QWidget *parent, const char *name )
+ : QFrame( parent, name )
+{
+ setFrameStyle( QFrame::Panel | QFrame::Raised );
+ setLineWidth( 1 );
+
+ QString text;
+ mUtilBox = new QGridLayout( this, 5, 4, KDialog::marginHint(), KDialog::spacingHint() );
+ mUtilBox->setColStretch( 3, 10 );
+
+ QString msg1[4] =
+ {
+ i18n("Signed 8 bit:"), i18n("Unsigned 8 bit:"),
+ i18n("Signed 16 bit:"), i18n("Unsigned 16 bit:")
+ };
+
+ QString msg2[4] =
+ {
+ i18n("Signed 32 bit:"), i18n("Unsigned 32 bit:"),
+ i18n("32 bit float:"), i18n("64 bit float:")
+ };
+
+ QString msg3[4] =
+ {
+ i18n("Hexadecimal:"), i18n("Octal:"),
+ i18n("Binary:"), i18n("Text:")
+ };
+
+ QGridLayout *ValuesBox = new QGridLayout( this, 4, 6, 0, KDialog::spacingHint() );
+ ValuesBox->setColStretch( 2, 10 );
+ ValuesBox->setColStretch( 5, 10 );
+
+ for( int i=0; i<4; i++ )
+ {
+ QLabel *Label = new QLabel( msg1[i], this );
+ Label->setAlignment( AlignRight|AlignVCenter );
+ ValuesBox->addWidget( Label, i, 0 );
+
+ mText1[i] = new QLineEdit( this );
+ mText1[i]->setReadOnly( true );
+ mText1[i]->setAlignment( AlignRight );
+ ValuesBox->addWidget( mText1[i], i, 1 );
+
+ Label = new QLabel( msg2[i], this );
+ Label->setAlignment( AlignRight|AlignVCenter );
+ ValuesBox->addWidget( Label, i, 3 );
+
+ mText2[i] = new QLineEdit( this );
+ mText2[i]->setReadOnly( true );
+ mText2[i]->setAlignment( AlignRight );
+ ValuesBox->addWidget( mText2[i], i, 4 );
+
+ Label = new QLabel( msg3[i], this );
+ Label->setAlignment( AlignRight|AlignVCenter );
+ mUtilBox->addWidget( Label, i, 1 );
+
+ mText3[i] = new QLineEdit( this );
+ mText3[i]->setReadOnly( true );
+ mText3[i]->setAlignment( AlignRight );
+ mUtilBox->addWidget( mText3[i], i, 2 );
+ }
+
+ QBoxLayout * SettingsBox = new QHBoxLayout( this, 0, KDialog::spacingHint() );
+
+ text = i18n("Show little endian decoding");
+ mCheckIntelFormat = new QCheckBox( text, this );
+ mCheckIntelFormat->setMinimumSize( mCheckIntelFormat->sizeHint() );
+ connect( mCheckIntelFormat, SIGNAL(clicked()), this, SLOT(intelFormat()) );
+ SettingsBox->addWidget( mCheckIntelFormat, 0, AlignVCenter );
+ mCheckIntelFormat->setChecked( // default value to please endian system users
+#ifdef WORDS_BIGENDIAN
+ false // Big Endian: SUN, Motorola machines (amongst others)
+#else
+ true // Little Endian: Intel, Alpha
+#endif
+ );
+ // TODO: make this a pulldown box, adding PDP endianess
+
+ text = i18n("Show unsigned as hexadecimal");
+ mCheckHexadecimal = new QCheckBox( text, this );
+ mCheckHexadecimal->setMinimumSize( mCheckHexadecimal->sizeHint() );
+ connect( mCheckHexadecimal, SIGNAL(clicked()), this, SLOT(unsignedFormat()) );
+ SettingsBox->addWidget( mCheckHexadecimal, 0, AlignVCenter );
+
+ mUtilBox->addMultiCellLayout( ValuesBox, 0, 3, 0, 0, AlignLeft|AlignVCenter );
+ mUtilBox->addMultiCellLayout( SettingsBox, 4, 4, 0, 0, AlignLeft|AlignVCenter );
+
+ //
+ // Variable bitwidth. Based on Craig Graham's work.
+ //
+ QLabel *bitLabel = new QLabel( i18n("Stream length:"), this );
+ bitLabel->setAlignment( AlignRight|AlignVCenter );
+ mUtilBox->addWidget( bitLabel, 4, 1 );
+
+ mBitCombo = new QComboBox( false, this );
+ text = i18n("Fixed 8 Bit" );
+ mBitCombo->insertItem( text );
+ for( int i=0; i<16; i++ )
+ {
+ text.sprintf("%u ", i+1 );
+ text += i==0 ? i18n("Bit Window") : i18n("Bits Window");
+ mBitCombo->insertItem( text );
+ }
+ mBitCombo->setMinimumSize( mBitCombo->sizeHint() );
+ connect( mBitCombo, SIGNAL(activated(int)), SLOT(bitWidthChanged(int)));
+ mUtilBox->addWidget( mBitCombo, 4, 2 );
+
+ /* load font metrics */
+ fontChanged();
+
+ mUtilBox->activate();
+
+ connect( kapp, SIGNAL( kdisplayFontChanged() ),
+ SLOT( fontChanged() ) );
+
+ mCursorState.valid = false;
+ mViewHexCaps = true;
+
+ setMinimumSize( sizeHint() );
+ show();
+}
+
+
+CHexToolWidget::~CHexToolWidget( void )
+{
+}
+
+
+void CHexToolWidget::writeConfiguration( KConfig &config )
+{
+ config.setGroup("Conversion" );
+ config.writeEntry("LittleEndian", mCheckIntelFormat->isChecked() );
+ config.writeEntry("UnsignedAsHex", mCheckHexadecimal->isChecked() );
+ config.writeEntry("StreamWindow", mBitCombo->currentItem() );
+}
+
+void CHexToolWidget::readConfiguration( KConfig &config )
+{
+ config.setGroup("Conversion" );
+ bool s1 = config.readBoolEntry( "LittleEndian", true );
+ bool s2 = config.readBoolEntry( "UnsignedAsHex", false );
+ int val = config.readNumEntry( "StreamWindow", 0 );
+
+ mCheckIntelFormat->setChecked( s1 );
+ mCheckHexadecimal->setChecked( s2 );
+ mBitCombo->setCurrentItem( val );
+}
+
+//++cg[6/7/1999]: handler for change signal from bit width combo
+void CHexToolWidget::bitWidthChanged( int /*i*/ )
+{
+ cursorChanged( mCursorState );
+}
+
+
+//
+// Variable bitwidth. Based on Craig Graham's work.
+//
+// ++cg[6/7/1999]: Read n bit's from a bitstream (allows N length bit
+// values to cross byte boundarys).
+//
+unsigned long CHexToolWidget::bitValue( SCursorState &state, int n )
+{
+ static const unsigned char bitmask[9] =
+ {
+ 0, 1<<7, 3<<6, 7<<5, 15<<4, 31<<3, 63<<2, 127<<1, 255
+ };
+
+ unsigned long rtn = 0;
+ unsigned char *byte = state.data;
+ int bit = 7 - state.cell;
+
+ while( n )
+ {
+ //
+ // c hold's current byte, shifted to put remaining bits in
+ // high bits of byte
+ //
+ unsigned char c = *byte << bit;
+
+ //
+ // if there are n bits or more remaining in this byte, we
+ // swallow n bits, otherwise we swallow as many
+ // bits as we can (8-bit)
+ //
+ int this_time = ((8-bit)>=n)?n:(8-bit);
+
+ //
+ // mask to get only the bit's we're swallowing
+ //
+ c &= bitmask[this_time];
+
+ //
+ // shift down to get bit's in low part of byte
+ //
+ c >>= 8-this_time;
+
+ //
+ // shift up previous results to make room and OR in the extracted bits.
+ //
+ rtn = (rtn<<this_time)|c;
+
+ n -= this_time; // update the count of remaining bits
+ bit += this_time; // tell the stream we swallowed some swallowed bits
+
+ //
+ // if we've swallowed 8 bits, we zero the bit count and move on to
+ // the next byte
+ //
+ if( bit==8 )
+ {
+ bit=0;
+ byte++;
+ }
+ }
+
+ return( rtn );
+}
+
+
+void CHexToolWidget::cursorChanged( SCursorState &state )
+{
+ if( state.valid == true )
+ {
+ QString buf;
+ // change by Kossebau[03.11.2003]:
+ // checking for system endianess, using the compiler for the byte interpretation and cutting bloaded code
+ // TODO: add PDP endianess
+ void *P8Bit, *P16Bit, *P32Bit, *P64Bit;
+ // ensure strict alignment for double as needed on some architectures (e.g. PA-RISC)
+ typedef union { unsigned char b[8]; double d; } aligned_t;
+ aligned_t Data;
+ if(
+#ifdef WORDS_BIGENDIAN
+ ! // Assume Big Endian. This is the case for SUN machines (amongst others)
+#else
+ // Assume Little Endian. This is the case for the Intel architecture.
+#endif
+ mCheckIntelFormat->isChecked() )
+ {
+ // take it as it is
+ memcpy( Data.b, state.data, 8 );
+ P8Bit = P16Bit = P32Bit = P64Bit = Data.b;
+ }
+ else
+ {
+ // reverse order
+ for( int i=0,j=7; i<8; ++i,--j )
+ Data.b[i] = state.data[j];
+
+ P8Bit = &Data.b[7];
+ P16Bit = &Data.b[6];
+ P32Bit = &Data.b[4];
+ P64Bit = Data.b;
+ }
+
+ bool NoHex = !mCheckHexadecimal->isChecked();
+
+ // unsigned 8 bit
+ buf.sprintf( NoHex?"%u":mViewHexCaps?"0x%02X":"0x%02x", *(unsigned char*)P8Bit );
+ mText1[1]->setText( buf );
+ // signed int 8 bit
+ buf.sprintf( "%d", *(signed char*)P8Bit );
+ mText1[0]->setText( buf );
+
+ // unsigned int 16 bit
+ buf.sprintf( NoHex?"%u":mViewHexCaps?"0x%04X":"0x%04x", *(unsigned short*)P16Bit );
+ mText1[3]->setText( buf );
+ // signed int 16 bit
+ buf.sprintf( "%d", *(short*)P16Bit );
+ mText1[2]->setText( buf );
+
+ // unsigned int 32 bit
+ buf.sprintf( NoHex?"%u":mViewHexCaps?"0x%08X":"0x%08x", *(unsigned int*)P32Bit );
+ mText2[1]->setText( buf );
+ // signed int 32 bit
+ buf.sprintf( "%d", *(int*)P32Bit );
+ mText2[0]->setText( buf );
+
+ // float 32 bit
+ buf.sprintf( "%E", *(float*)P32Bit );
+ mText2[2]->setText( buf );
+ // float 64 bit
+ buf.sprintf( "%E", *(double*)P64Bit );
+ mText2[3]->setText( buf );
+
+ int numBits = mBitCombo->currentItem();
+ if( numBits == 0 )
+ {
+ //
+ // This is the original stuff
+ //
+ unsigned char data = (unsigned char)state.data[0];
+ buf.sprintf( mViewHexCaps?"%02X":"%02x", data );
+ mText3[0]->setText( buf );
+ buf.sprintf( "%03o", data );
+ mText3[1]->setText( buf );
+
+ char bitBuf[32];
+ for( int i = 0; i < 8; i++ )
+ bitBuf[7-i] = (data&(1<<i)) ? '1' : '0';
+
+ bitBuf[8] = 0;
+ mText3[2]->setText( QString(bitBuf) );
+ }
+ else
+ {
+ //
+ // Variable bitwidth. Based on Craig Graham's work.
+ //
+ unsigned long data = bitValue( state, numBits );
+ buf.sprintf( mViewHexCaps?"%02lX %02lX":"%02lx %02lx", (data>>8)&0xFF, data&0xFF );
+ mText3[0]->setText( buf );
+ buf.sprintf( "%03lo %03lo", (data>>8)&0xFF, data&0xFF );
+ mText3[1]->setText( buf );
+ char bitBuf[32];
+ for( int i = 0; i<numBits; i++ )
+ bitBuf[numBits-i-1] = (data&(1L<<i)) ? '1' : '0';
+ bitBuf[numBits] = 0;
+ mText3[2]->setText( QString(bitBuf) );
+ }
+
+ // Fix by Sergey A. Sukiyazov
+ unsigned char data[2] = { 0, 0 };
+ data[0] = state.charValid == false ? '.' :
+ (char)((unsigned char)state.data[0]&0xff );
+ buf = QString::fromLocal8Bit( (const char *)data );
+
+ mText3[3]->setText( buf );
+ }
+ else
+ {
+ QString str;
+ for( int i=0; i<4; i++)
+ {
+ mText1[i]->setText( str );
+ mText2[i]->setText( str );
+ mText3[i]->setText( str );
+ }
+ }
+
+ mCursorState = state;
+}
+
+
+void CHexToolWidget::fontChanged( void )
+{
+ QFontMetrics fm( mText1[0]->font() );
+ int W1 = fm.width( "XXXXXXXX" );
+ int W2 = fm.width( "XXXXXXXXXXXX" );
+ int W3 = fm.width( "888888888888888888" );
+ for( int i=0; i<4; i++ )
+ {
+ mText1[i]->setFixedWidth( W1 );
+ mText2[i]->setFixedWidth( W2 );
+ mText3[i]->setFixedWidth( W3 );
+ }
+}
+
+
+void CHexToolWidget::intelFormat( void )
+{
+ cursorChanged( mCursorState );
+}
+
+
+void CHexToolWidget::unsignedFormat( void )
+{
+ cursorChanged( mCursorState );
+}
+
+
+void CHexToolWidget::resizeEvent( QResizeEvent */*e*/ )
+{
+}
+
+
+
+void CHexToolWidget::closeEvent( QCloseEvent *e )
+{
+ e->accept();
+ emit closed();
+}
+
+#include "hextoolwidget.moc"
diff --git a/khexedit/hextoolwidget.h b/khexedit/hextoolwidget.h
new file mode 100644
index 0000000..d2ce892
--- /dev/null
+++ b/khexedit/hextoolwidget.h
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _HEX_TOOL_WIDGET_H_
+#define _HEX_TOOL_WIDGET_H_
+
+#include <kconfig.h>
+
+class QGridLayout;
+class QComboBox;
+class QLineEdit;
+class QCheckBox;
+
+#include "hexbuffer.h"
+#include <qframe.h>
+
+class CHexToolWidget : public QFrame
+{
+ Q_OBJECT
+
+ public:
+ CHexToolWidget( QWidget *parent = 0, const char *name = 0 );
+ ~CHexToolWidget( void );
+
+ void writeConfiguration( KConfig &config );
+ void readConfiguration( KConfig &config );
+ unsigned long bitValue( SCursorState &state, int n );
+
+ protected:
+ void resizeEvent( QResizeEvent *e );
+ void closeEvent( QCloseEvent *e );
+
+ public slots:
+ void cursorChanged( SCursorState &state );
+ void fontChanged( void );
+ void intelFormat( void );
+ void unsignedFormat( void );
+ void bitWidthChanged( int i );
+
+ signals:
+ void closed( void );
+
+
+ private:
+
+ private:
+ SCursorState mCursorState;
+ bool mViewHexCaps;
+
+ QGridLayout *mUtilBox;
+ QLineEdit *mText1[4];
+ QLineEdit *mText2[4];
+ QLineEdit *mText3[4];
+ QCheckBox *mCheckIntelFormat;
+ QCheckBox *mCheckHexadecimal;
+ QComboBox *mBitCombo;
+};
+
+
+
+
+
+
+#endif
diff --git a/khexedit/hexvalidator.cc b/khexedit/hexvalidator.cc
new file mode 100644
index 0000000..e8c1731
--- /dev/null
+++ b/khexedit/hexvalidator.cc
@@ -0,0 +1,329 @@
+/*
+ * 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 <ctype.h>
+#include <stdio.h>
+#include <qwidget.h>
+#include "hexvalidator.h"
+
+CHexValidator::CHexValidator( QWidget *parent, EState state,
+ const char *name )
+ :QValidator( parent, name )
+{
+ setState( state );
+}
+
+CHexValidator::~CHexValidator( void )
+{
+}
+
+QValidator::State CHexValidator::validate( QString &string, int &/*pos*/ ) const
+{
+ if( mState == hexadecimal )
+ {
+ for( uint i=0; i < string.length(); i++ )
+ {
+ int val = string[i].latin1();
+ if( isxdigit( val ) == 0 && isspace( val ) == 0 )
+ {
+ return( QValidator::Invalid );
+ }
+ }
+ return( QValidator::Valid );
+ }
+ if( mState == decimal )
+ {
+ for( uint i=0; i < string.length(); i++ )
+ {
+ int val = string[i].latin1();
+ if( isdigit( val ) == 0 && isspace( val ) == 0 )
+ {
+ return( QValidator::Invalid );
+ }
+ }
+ return( QValidator::Valid );
+ }
+ else if( mState == octal )
+ {
+ for( uint i=0; i < string.length(); i++ )
+ {
+ int val = string[i].latin1();
+ if( (isdigit( val ) == 0 || val == '8' || val == '9') &&
+ isspace( val ) == 0 )
+ {
+ return( QValidator::Invalid );
+ }
+ }
+ return( QValidator::Valid );
+ }
+ else if( mState == binary )
+ {
+ for( uint i=0; i < string.length(); i++ )
+ {
+ int val = string[i].latin1();
+ if( val != '0' && val != '1' && isspace( val ) == 0 )
+ {
+ return( QValidator::Invalid );
+ }
+ }
+ return( QValidator::Valid );
+ }
+ else if( mState == regularText )
+ {
+ return( QValidator::Valid );
+ }
+ else
+ {
+ return( QValidator::Invalid );
+ }
+
+}
+
+
+void CHexValidator::setState( EState state )
+{
+ mState = state;
+}
+
+
+void CHexValidator::convert( QByteArray &dest, const QString &src )
+{
+ uint value;
+ uint k=0;
+
+ if( mState == hexadecimal )
+ {
+ dest.resize(0);
+
+ char buf[3];
+ for( uint i=0; i < src.length(); i++ )
+ {
+ int val = src[i].latin1();
+ if( isxdigit(val) )
+ {
+ buf[k++] = val;
+ if( k == 2 )
+ {
+ buf[k] = 0;
+ sscanf( buf, "%X", &value );
+
+ dest.resize( dest.size()+1 );
+ dest[ dest.size()-1 ] = value;
+ k = 0;
+ }
+ }
+ }
+
+ if( k == 1 )
+ {
+ buf[1] = buf[0];
+ buf[0] = '0';
+ buf[2] = 0;
+ sscanf( buf, "%X", &value );
+
+ dest.resize( dest.size()+1 );
+ dest[ dest.size()-1 ] = value;
+ }
+
+ }
+ else if( mState == decimal )
+ {
+ dest.resize(0);
+
+ char buf[4];
+ for( uint i=0; i < src.length(); i++ )
+ {
+ int val = src[i].latin1();
+ if( isdigit(val) )
+ {
+ buf[k++] = val;
+ if( k == 3 )
+ {
+ buf[k] = 0;
+ sscanf( buf, "%u", &value );
+
+ dest.resize( dest.size()+1 );
+ dest[ dest.size()-1 ] = value;
+ k = 0;
+ }
+ }
+ }
+
+ if( k == 1 || k == 2 )
+ {
+ if( k == 1 )
+ {
+ buf[2] = buf[0];
+ buf[0] = buf[1] = '0';
+ }
+ else
+ {
+ buf[2] = buf[1];
+ buf[1] = buf[0];
+ buf[0] = '0';
+ }
+ buf[3] = 0;
+ sscanf( buf, "%u", &value );
+
+ dest.resize( dest.size()+1 );
+ dest[ dest.size()-1 ] = value;
+ }
+ }
+
+ else if( mState == octal )
+ {
+ dest.resize(0);
+
+ char buf[4];
+ for( uint i=0; i < src.length(); i++ )
+ {
+ int val = src[i].latin1();
+ if( isdigit(val) )
+ {
+ buf[k++] = val;
+ if( k == 3 )
+ {
+ if( buf[0] > '3' ) { buf[0] = '3'; }
+ buf[k] = 0;
+ sscanf( buf, "%o", &value );
+
+ dest.resize( dest.size()+1 );
+ dest[ dest.size()-1 ] = value;
+ k = 0;
+ }
+ }
+ }
+
+ if( k == 1 || k == 2 )
+ {
+ if( k == 1 )
+ {
+ buf[2] = buf[0];
+ buf[0] = buf[1] = '0';
+ }
+ else
+ {
+ buf[2] = buf[1];
+ buf[1] = buf[0];
+ buf[0] = '0';
+ }
+ buf[3] = 0;
+ sscanf( buf, "%o", &value );
+
+ dest.resize( dest.size()+1 );
+ dest[ dest.size()-1 ] = value;
+ }
+ }
+ else if( mState == binary )
+ {
+ dest.resize(0);
+
+ char buf[9];
+ for( uint i=0; i < src.length(); i++ )
+ {
+ int val = src[i].latin1();
+ if( isdigit(val) )
+ {
+ buf[k++] = val;
+ if( k == 8 )
+ {
+ value = 0;
+ for( uint j=0; j < 8; j++ )
+ {
+ value |= (buf[8-j-1] == '1') ? 1<<j : 0;
+ }
+
+ dest.resize( dest.size()+1 );
+ dest[ dest.size()-1 ] = value;
+ k = 0;
+ }
+ }
+ }
+
+ if( k > 0 )
+ {
+ value = 0;
+ for( uint j=0; j < k; j++ )
+ {
+ value |= (buf[k-j-1] == '1') ? 1<<j : 0;
+ }
+
+ dest.resize( dest.size()+1 );
+ dest[ dest.size()-1 ] = value;
+ }
+ }
+ else if( mState == regularText )
+ {
+ dest.resize(src.length());
+ for( uint i=0; i < src.length(); i++ )
+ {
+ dest[i] = src[i].latin1();
+ }
+
+ }
+ else
+ {
+ dest.resize(0);
+ }
+}
+
+
+
+void CHexValidator::format( QString &dest, const QByteArray &src )
+{
+ for( uint i=0; i<src.size(); ++i )
+ {
+ unsigned char srcCh = (unsigned char)src[i];
+ QString formattedCh;
+
+ switch( mState )
+ {
+ case hexadecimal:
+ formattedCh = zeroExtend( QString::number( srcCh, 16 ), 2 );
+ break;
+ case decimal:
+ formattedCh = zeroExtend( QString::number( srcCh, 10), 3 );
+ break;
+ case octal:
+ formattedCh = zeroExtend( QString::number( srcCh, 8), 3 );
+ break;
+ case binary:
+ formattedCh = zeroExtend( QString::number( srcCh, 2), 8 );
+ break;
+ case regularText:
+ formattedCh = QString( QChar( srcCh ) );
+ break;
+ }
+
+ dest += formattedCh + " ";
+ }
+}
+
+
+QString CHexValidator::zeroExtend( const QString &src, unsigned destLen) const
+{
+ if( src.length() >= destLen )
+ return src;
+
+ QString zeroes;
+ zeroes.fill( '0', destLen - src.length() );
+ return zeroes + src;
+}
+#include "hexvalidator.moc"
diff --git a/khexedit/hexvalidator.h b/khexedit/hexvalidator.h
new file mode 100644
index 0000000..cfe9f95
--- /dev/null
+++ b/khexedit/hexvalidator.h
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _HEX_VALIDATOR_H_
+#define _HEX_VALIDATOR_H_
+
+#include <qvalidator.h>
+
+class CHexValidator: public QValidator
+{
+ Q_OBJECT
+
+ public:
+ enum EState
+ {
+ hexadecimal = 0,
+ decimal,
+ octal,
+ binary,
+ regularText
+ };
+
+ public:
+ CHexValidator( QWidget *parent, EState state, const char *name = 0 );
+ ~CHexValidator( void );
+ QValidator::State validate( QString &string, int &pos ) const;
+ void setState( EState state );
+ void convert( QByteArray &dest, const QString &src );
+ void format( QString &dest, const QByteArray &src );
+
+ private:
+ /**
+ * Returns a string that is at least as long as @p destLen number of characters,
+ * by adding zeroes to the left as necessary.
+ *
+ * e.g. zeroExtend( "32", 3 ) => "032"
+ */
+ QString zeroExtend( const QString &src, unsigned destLen ) const;
+
+ EState mState;
+
+
+};
+
+
+#endif
diff --git a/khexedit/hexviewwidget.cc b/khexedit/hexviewwidget.cc
new file mode 100644
index 0000000..12226ed
--- /dev/null
+++ b/khexedit/hexviewwidget.cc
@@ -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 <iostream>
+
+#include <qclipboard.h>
+#include <qdrawutil.h>
+
+
+#include <kglobalsettings.h>
+#include <klocale.h>
+#include <kpopupmenu.h>
+#include <kdebug.h>
+#include <kurldrag.h>
+
+#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( QMouseEvent *e )
+{
+ if( mPending == false )
+ {
+ return( false );
+ }
+
+ if( mActivateMode == Movement )
+ {
+ if( (mOrigin - e->pos()).manhattanLength() > KGlobalSettings::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( QTimerEvent *e )
+{
+ if( e->timerId() == mTimerId )
+ {
+ removeTimer();
+ if( mPending == true )
+ {
+ mPending = false;
+ emit startDrag( ( kapp->keyboardModifiers() & KApplication::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( QWidget *parent, const char *name,
+ CHexBuffer *hexBuffer )
+ : QFrame( parent, name,
+ #ifdef USE_NORTHWEST_GRAVITY
+ Qt::WStaticContents
+ #else
+ 0
+ #endif
+ ), mScrollBarSize( 16 )
+{
+ if( parent == 0 || hexBuffer == 0 ) { return; }
+
+ //
+ // Qt 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 QHideEvent.
+ //
+
+ mVertScroll = new CScrollBar( QScrollBar::Vertical, this );
+ if( mVertScroll == 0 ) { return; }
+ mHorzScroll = new CScrollBar( QScrollBar::Horizontal, this );
+ if( mHorzScroll == 0 ) { return; }
+ mCorner = new QWidget( this );
+ if( mCorner == 0 ) { return; }
+ connect( mHorzScroll, SIGNAL(valueChanged(int)), SLOT(changeXPos(int)) );
+ connect( mVertScroll, SIGNAL(valueChanged(int)), SLOT(changeYPos(int)) );
+ connect( mHorzScroll, SIGNAL(hidden()), SLOT(update()) );
+ connect( mVertScroll, SIGNAL(hidden()), 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, SIGNAL(startDrag(bool)), SLOT(startDrag(bool)) );
+
+ setFrameStyle( QFrame::WinPanel|QFrame::Sunken );
+ setWFlags( WResizeNoErase );
+ setFocusPolicy( 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( QFile &file, const QString &url, CProgress &p )
+{
+ int errCode = mHexBuffer->readFile( file, url, p );
+ if( errCode != Err_Success )
+ {
+ return( errCode );
+ }
+
+ initFile();
+ return( Err_Success );
+}
+
+
+int CHexViewWidget::insertFile( QFile &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 QString &url )
+{
+ int errCode = mHexBuffer->newFile( url );
+ if( errCode != Err_Success )
+ {
+ return( errCode );
+ }
+
+ initFile();
+ return( Err_Success );
+}
+
+
+int CHexViewWidget::writeFile( QFile &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( QABS(dx) < width() )
+ {
+ scroll( dx, 0, contentsRect() );
+ }
+ else
+ {
+ QWidget::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( QABS( dy ) < height() )
+ {
+ scroll( 0, dy, contentsRect() );
+ }
+ else
+ {
+ QWidget::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(QApplication::clipboard(),SIGNAL(dataChanged()),
+ this,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;
+ }
+
+ QByteArray 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 QByteArray &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 QByteArray &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( QByteArray &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 )
+ {
+ QWidget::update();
+ }
+}
+
+
+void CHexViewWidget::setPalette( const QPalette &p )
+{
+ QWidget::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 )
+ {
+ QWidget::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 )
+{
+ QByteArray buf;
+ if( asText == true )
+ {
+ if( mHexBuffer->copySelectedText( buf ) != Err_Success )
+ {
+ return;
+ }
+ QDragObject *d = new QTextDrag( buf.data(), this );
+ d->dragCopy();
+ }
+ else
+ {
+ if( mHexBuffer->copySelectedData( buf ) != Err_Success )
+ {
+ return;
+ }
+ QDragObject *d = new CHexDrag( buf, this );
+ d->dragCopy();
+ }
+}
+
+
+
+void CHexViewWidget::copy( void )
+{
+ QByteArray buf;
+ if( mHexBuffer->copySelectedData( buf ) != Err_Success )
+ {
+ return;
+ }
+ disconnect(QApplication::clipboard(),SIGNAL(dataChanged()),
+ this,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).
+ //
+ QApplication::clipboard()->setData(new CHexDrag( buf ));
+ connect(QApplication::clipboard(),SIGNAL(dataChanged()),
+ this,SLOT(clipboardChanged()));
+}
+
+
+void CHexViewWidget::copyText( int columnSegment )
+{
+ QByteArray buf;
+ if( mHexBuffer->copySelectedText( buf, columnSegment ) != Err_Success )
+ {
+ return;
+ }
+
+ disconnect(QApplication::clipboard(),SIGNAL(dataChanged()),
+ this,SLOT(clipboardChanged()));
+ QApplication::clipboard()->setText( buf.data() );
+ connect(QApplication::clipboard(),SIGNAL(dataChanged()),
+ this,SLOT(clipboardChanged()));
+}
+
+
+
+void CHexViewWidget::paste( void )
+{
+ QMimeSource *data = QApplication::clipboard()->data();
+ if( data != 0 )
+ {
+ QByteArray buf;
+ if( CHexDrag::decode( data, buf ) == true )
+ {
+ insert( buf );
+ return;
+ }
+
+ QString text;
+ if( QTextDrag::decode( data, text ) == true )
+ {
+ QByteArray 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 QString &title )
+{
+ QPtrList<SCursorOffset> &list = mHexBuffer->bookmarkList();
+ if( list.count() == 0 )
+ {
+ return( -1 );
+ }
+
+ QString text;
+ KPopupMenu *popup = new KPopupMenu( 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( QString("[%1] %2: ").arg(i+1).arg(i18n("Offset")) );
+ popup->insertItem( text, i );
+ }
+
+ QSize s(popup->sizeHint());
+ QPoint 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;
+ }
+ QWidget::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 )
+{
+ QPtrList<SCursorOffset> &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 )
+{
+ QPtrList<SCursorOffset> &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 )
+{
+ QPtrList<SCursorOffset> &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 <sys/time.h>
+#include <unistd.h>
+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( QResizeEvent * )
+{
+ 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() )
+ {
+ QWidget::update();
+ }
+ else
+ {
+ paintFrame();
+ }
+ #endif
+ }
+}
+
+
+
+void CHexViewWidget::paintEvent( QPaintEvent *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( QRect(0,0,w,h) );
+}
+
+
+
+void CHexViewWidget::paintFrame( void )
+{
+ QPainter paint;
+ paint.begin( this );
+ drawFrame( &paint );
+ paint.end();
+}
+
+
+
+void CHexViewWidget::drawFrame( QPainter *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 "QFrame::WinPanel|QFrame::Plain"
+ //
+ if( mDropHighlight == true )
+ {
+ qDrawPlainRect( p, frameRect(), QColor("SteelBlue2"), lineWidth() );
+ }
+ else
+ {
+ QFrame::drawFrame(p); // Use standard drawFrame
+ }
+}
+
+
+
+void CHexViewWidget::keyPressEvent( QKeyEvent *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( e->text()[0] );
+ }
+ break;
+ }
+
+ e->accept();
+}
+
+
+void CHexViewWidget::keyReleaseEvent( QKeyEvent *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( QMouseEvent *e )
+{
+ //
+ // The RMB popup menu is managed by the KContextMenuManager
+ //
+
+ if( e->button() == 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() == MidButton )
+ {
+ paste();
+ }
+
+}
+
+void CHexViewWidget::mouseMoveEvent( QMouseEvent *e )
+{
+ if( e->state() & LeftButton )
+ {
+ if( mDragManager->start( e ) == false )
+ {
+ bool cellLevel = mMisc.cursorJump == false||e->state() & ControlButton;
+ setCursorPosition( e->x(), e->y(), false, cellLevel );
+ }
+ }
+}
+
+void CHexViewWidget::mouseReleaseEvent( QMouseEvent *e )
+{
+ //
+ // The RMB popup menu is managed by the KContextMenuManager
+ //
+
+ if( e->button() == 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( QWheelEvent *e )
+{
+ if( mVertScroll->isVisible() == true )
+ {
+ QApplication::sendEvent( mVertScroll, e );
+ }
+}
+
+
+void CHexViewWidget::dragEnterEvent( QDragEnterEvent *e )
+{
+ if( QTextDrag::canDecode(e) || CHexDrag::canDecode(e) ||
+ KURLDrag::canDecode(e))
+ {
+ e->accept();
+ setDropHighlight( true );
+ }
+}
+
+
+void CHexViewWidget::dragLeaveEvent( QDragLeaveEvent * )
+{
+ setDropHighlight( false );
+}
+
+
+void CHexViewWidget::dragMoveEvent( QDragMoveEvent *e )
+{
+ //
+ // Move the cursor if we are dragging (readable) text or binary
+ // data. Note: the QTextDrag::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( QTextDrag::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( QDropEvent *e )
+{
+ QMimeSource &m = *(QDropEvent*)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;
+ }
+
+ QByteArray buf;
+ if( CHexDrag::decode( &m, buf ) == true )
+ {
+ insert( buf );
+ return;
+ }
+
+ QString text;
+ if( QTextDrag::decode( &m, text ) == true )
+ {
+ bool success = mClipConvert.decode( buf, text );
+ if( success == true )
+ {
+ insert( buf );
+ }
+ return;
+ }
+
+}
+
+
+void CHexViewWidget::showEvent( QShowEvent * )
+{
+ // Currently we do nothing here.
+}
+
+
+
+
+void CHexViewWidget::timerEvent( QTimerEvent *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( QFocusEvent * )
+{
+ setupCursorTimer();
+ paintCursor( CHexBuffer::cursor_curr );
+}
+
+void CHexViewWidget::focusOutEvent( QFocusEvent * )
+{
+ 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 )
+ {
+ QRect r = contentsRect();
+ r.setTop( t );
+ paintText( contentsRect().intersect( r ), false );
+ }
+ else
+ {
+ int h = (numLine + (startY() % lineHeight ? 1 : 0)) * lineHeight;
+ QRect 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 )
+ {
+ QRect r = contentsRect();
+ r.setTop( t );
+ paintText( contentsRect().intersect( r ), false );
+ }
+ else
+ {
+ int h = t + lineHeight;
+ QRect r( contentsRect().left(), t, contentsRect().width(), h );
+ paintText( contentsRect().intersect( r ), false );
+ }
+}
+
+
+
+
+void CHexViewWidget::paintText( const QRect &rect, bool expand )
+{
+ QRect 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 ); }
+
+ QPainter 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 )
+{
+ QPainter 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( QChar 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 QFrame::drawFrame(QPainter *)
+ // to support a custom frame color. I assume the frame shape is
+ // "QFrame::WinPanel|QFrame::Plain" in that function.
+ //
+ setFrameStyle( QFrame::WinPanel|QFrame::Plain );
+ }
+ else
+ {
+ setFrameStyle( QFrame::WinPanel|QFrame::Sunken );
+ }
+}
+
+
+
+#include "hexviewwidget.moc"
diff --git a/khexedit/hexviewwidget.h b/khexedit/hexviewwidget.h
new file mode 100644
index 0000000..9dc55e4
--- /dev/null
+++ b/khexedit/hexviewwidget.h
@@ -0,0 +1,584 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _HEX_VIEW_WIDGET_H_
+#define _HEX_VIEW_WIDGET_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include <qframe.h>
+#include <qpixmap.h>
+#include <qpopupmenu.h>
+#include <qscrollbar.h>
+
+#include <kapplication.h>
+#include <kcmenumngr.h>
+
+#include "hexclipboard.h"
+#include "hexbuffer.h"
+
+class CScrollBar : public QScrollBar
+{
+ Q_OBJECT
+
+ public:
+ CScrollBar( Orientation o, QWidget *parent, const char *name = 0 )
+ : QScrollBar( o, parent, name )
+ {
+ }
+
+ signals:
+ void hidden( void );
+
+ protected:
+ virtual void hideEvent( QHideEvent * )
+ {
+ emit hidden();
+ }
+};
+
+
+class CDragManager : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ enum EDragActivateMode
+ {
+ Movement = 0,
+ Timer = 1
+ };
+
+ public:
+ CDragManager( void );
+ void setActivateMode( EDragActivateMode mode );
+ void setup( int x, int y );
+ bool start( QMouseEvent *e );
+ bool clear( void );
+
+ protected:
+ virtual void timerEvent( QTimerEvent *e );
+
+ private:
+ void removeTimer( void );
+ void setupTimer( void );
+
+ signals:
+ void startDrag( bool asText );
+
+ private:
+ EDragActivateMode mActivateMode;
+ bool mPending;
+ int mTimerId;
+ QPoint mOrigin;
+};
+
+
+
+class CHexViewWidget : public QFrame
+{
+ Q_OBJECT
+
+ public:
+ CHexViewWidget( QWidget *parent, const char *name, CHexBuffer *hexBuffer );
+ ~CHexViewWidget( void );
+ inline bool widgetValid( void );
+
+ int readFile( QFile &file, const QString &url, CProgress &p );
+ int insertFile( QFile &file, CProgress &p );
+ int writeFile( QFile &file, CProgress &p );
+ int newFile( const QString &url );
+ void closeFile( void );
+ void initFile( void );
+ void setBuffer( CHexBuffer *hexBuffer );
+ void updateView( bool redraw, bool fixCursor );
+
+ void selectAll( void );
+ void unselect( void );
+ void unmark( void );
+ uint numPage( CHexPrinter &printer );
+ int print( CHexPrinter &printer, CProgress &p );
+ int exportText( const SExportText &ex, CProgress &p );
+ int exportHtml( const SExportHtml &ex, CProgress &p );
+ int exportCArray( const SExportCArray &ex, CProgress &p );
+
+ void copy( void );
+ void copyText( int columnSegment=CHexBuffer::VisibleColumn );
+ void paste( void );
+ void cut( void );
+ void undo( void );
+ void redo( void );
+ void addBookmark( int position );
+ void removeBookmark( bool all );
+ void replaceBookmark( void );
+ void gotoBookmark( uint position );
+ void gotoNextBookmark( bool next );
+ void benchmark( void );
+
+ virtual void setPalette( const QPalette & );
+ void setInputMode( SDisplayInputMode &mode );
+ void setLayout( SDisplayLayout &layout );
+ void setCursor( const SDisplayCursor &cursor, bool updateDisplay );
+ void setColor( const SDisplayColor &color, bool updateDisplay );
+ void setFont( const SDisplayFontInfo &fontInfo, bool updateDisplay );
+ void setMisc( SDisplayMisc &misc );
+ void setInsertMode( bool insertMode );
+ int setEncoding( CConversion::EMode mode, CProgress &p );
+ void reportEncoding( void );
+
+ int findFirst( SSearchControl &sc );
+ int findNext( SSearchControl &sc );
+ int findWrap( SSearchControl &sc );
+ int replaceAll( SSearchControl &sc, bool init );
+ int replaceMarked( SSearchControl &sc );
+ int collectStrings( CStringCollectControl &sc );
+ int collectStatistic( SStatisticControl &sc, CProgress &p );
+
+
+ inline void setPopupMenu( QPopupMenu *popupMenu );
+ inline void setDocumentMenu( QPopupMenu *popupMenu );
+ inline bool insertMode( void );
+ inline int scrollBarWidth( void );
+ inline int dataWidth( void );
+ inline int defaultWidth( void );
+ inline uint offset( void );
+ inline uint bookmarkCount( void );
+ inline bool modified( void );
+ inline void setModified( bool modified );
+ inline const QDateTime &diskModifyTime( void );
+ inline bool losslessEncoding( CConversion::EMode mode );
+ inline const SEncodeState &encoding( void );
+ inline bool documentPresent( void );
+ inline bool urlValid( void );
+ inline QString &url( void );
+ inline void setUrl( QString &url );
+ inline const CHexBuffer *hexBuffer( void );
+
+ public slots:
+ void filter( SFilterControl &fc );
+ void insert( SInsertData &id );
+ void insert( const QByteArray &buf );
+ void append( const QByteArray &buf );
+ void valueOnCursor( QByteArray &buf, uint size );
+ void paletteChanged( void );
+ void fontChanged( void );
+ void gotoOffset( uint offset, uint bit, bool fromCursor, bool forward );
+ void gotoOffset( uint offset );
+ void setMark( uint offset, uint size, bool moveCursor );
+ void setDropHighlight( bool mode );
+
+ protected:
+ virtual void drawFrame( QPainter *p );
+ virtual void paintEvent( QPaintEvent *e );
+ virtual void resizeEvent( QResizeEvent *e );
+ virtual void keyPressEvent( QKeyEvent *e );
+ virtual void keyReleaseEvent( QKeyEvent *e );
+ virtual void mousePressEvent( QMouseEvent *e );
+ virtual void mouseMoveEvent( QMouseEvent *e );
+ virtual void wheelEvent( QWheelEvent * );
+ virtual void mouseReleaseEvent( QMouseEvent *e );
+ virtual void dragEnterEvent( QDragEnterEvent *e );
+ virtual void dragLeaveEvent( QDragLeaveEvent *e );
+ virtual void dragMoveEvent( QDragMoveEvent *e );
+ virtual void dropEvent( QDropEvent *e );
+ virtual void showEvent( QShowEvent * );
+ virtual void timerEvent( QTimerEvent *e );
+ virtual void focusInEvent( QFocusEvent *e );
+ virtual void focusOutEvent( QFocusEvent *e );
+
+ protected slots:
+ void changeXPos( int pos );
+ void changeYPos( int pos );
+ void clipboardChanged( void );
+
+ signals:
+ void cursorChanged( SCursorState &state );
+ void fileState( SFileState &state );
+ void dataChanged( void );
+ void layoutChanged( const SDisplayLayout &layout );
+ void inputModeChanged( const SDisplayInputMode &mode );
+ void bookmarkChanged( QPtrList<SCursorOffset> &list );
+ void editMode( CHexBuffer::EEditMode editMode );
+ void encodingChanged( const SEncodeState &state );
+ void textWidth( uint width );
+ void fileName( const QString &url, bool onDisk );
+ void fileRename( const QString &curName, const QString &newName );
+ void fileClosed( const QString &url );
+
+ void pleaseOpenNewFile( void );
+ void pleaseStepFile( bool next );
+ void pleaseOpenFile(const QString &url,bool reloadWhenChanged,uint offset);
+
+ private:
+ void setSelection( uint offset, bool init );
+ void setCursorPosition( int x, int y, bool init, bool cellLevel );
+ void updateCursor( SCursorConfig &cc, bool always = false,
+ bool touchSelection = true );
+ void setEditMode( CHexBuffer::EEditMode mode );
+
+ void paintFrame( void );
+ void updateFrameSize( void );
+
+ void redrawInterval( uint start, uint stop );
+ void redrawLines( uint docLine, int numLine );
+ void redrawFromOffset( uint offset, bool finishWindow );
+ void paintText( const QRect &r, bool expand );
+ void paintCursor( int cursorMode );
+
+
+ void toggleEditor( void );
+ void cursorStep( SCursorConfig &cc, uint stepSize );
+ void cursorLeft( SCursorConfig &cc );
+ void cursorRight( SCursorConfig &cc );
+ void cursorHome( SCursorConfig &cc );
+ void cursorEnd( SCursorConfig &cc );
+ void cursorUp( SCursorConfig &cc );
+ void cursorDown( SCursorConfig &cc );
+ void cursorPageUp( SCursorConfig &cc );
+ void cursorPageDown( SCursorConfig &cc );
+ void cursorInsert( SCursorConfig &cc );
+ void cursorDelete( SCursorConfig &cc );
+ void cursorBackspace( SCursorConfig &cc );
+ void cursorInput( QChar c );
+
+ int bookmarkMenu( const QString &title );
+
+ static inline bool shiftButtonState( void );
+
+ inline void setupCursorTimer( void );
+ inline int startX( void );
+ inline int startY( void );
+ inline void setStartX( int val );
+ inline void setStartY( int val );
+ inline void updateWindow( bool completeRedraw, bool touchSelection );
+ inline void updateWindow( uint line );
+ inline void updateWindow( uint fromOffset, bool finishWindow );
+ inline void updateWindow( void );
+ inline void setTextBufferSize( void );
+ inline void autoCopy( void );
+
+ private slots:
+ void startDrag( bool asText );
+
+ private:
+ CScrollBar *mVertScroll;
+ CScrollBar *mHorzScroll;
+ QWidget *mCorner;
+
+ CHexBuffer *mHexBuffer;
+ QPixmap mTextBuffer;
+ SDisplayLayout mLayout;
+ SDisplayCursor mCursor;
+ SDisplayColor mColor;
+ SDisplayFontInfo mFontInfo;
+ SDisplayMisc mMisc;
+
+ QPopupMenu *mDocumentMenu;
+
+ int mScrollBarSize;
+ CHexBuffer::EEditMode mEditMode;
+ bool mShowCursor;
+ bool mDropHighlight;
+
+ int mCursorTimerId;
+
+ CDragManager *mDragManager;
+ CHexClipboard mClipConvert;
+};
+
+
+inline bool CHexViewWidget::shiftButtonState( void )
+{
+ return kapp->keyboardModifiers() & KApplication::ShiftModifier;
+}
+
+
+
+inline bool CHexViewWidget::widgetValid( void )
+{
+ if( mVertScroll == 0 || mHorzScroll == 0 || mHexBuffer == 0 )
+ {
+ return( false );
+ }
+ else
+ {
+ return( true );
+
+ }
+}
+
+inline void CHexViewWidget::setupCursorTimer( void )
+{
+ if( mCursorTimerId != 0 )
+ {
+ killTimer( mCursorTimerId );
+ mCursorTimerId = 0;
+ }
+
+ if( hasFocus() == true )
+ {
+ if( mCursor.alwaysVisible == false )
+ {
+ mCursorTimerId = startTimer( mCursor.interval );
+ }
+ mShowCursor = true;
+ mHexBuffer->setDisableCursor( false );
+ }
+ else
+ {
+ if( mCursor.alwaysVisible == false )
+ {
+ if( mCursor.focusMode == SDisplayCursor::ignore )
+ {
+ mCursorTimerId = startTimer( mCursor.interval );
+ }
+ }
+ if( mCursor.focusMode != SDisplayCursor::hide )
+ {
+ mShowCursor = true;
+ }
+ else
+ {
+ mShowCursor = false;
+ mHexBuffer->setDisableCursor( true );
+ }
+ }
+
+ mHexBuffer->setShowCursor( mShowCursor );
+}
+
+inline void CHexViewWidget::setPopupMenu( QPopupMenu *popupMenu )
+{
+ KContextMenuManager::insert( this, popupMenu );
+}
+
+
+inline void CHexViewWidget::setDocumentMenu( QPopupMenu *popupMenu )
+{
+ mDocumentMenu = popupMenu;
+}
+
+
+inline int CHexViewWidget::startX( void )
+{
+ return( mHexBuffer->startX() );
+}
+
+inline int CHexViewWidget::startY( void )
+{
+ return( mHexBuffer->startY() );
+}
+
+inline void CHexViewWidget::setStartX( int val )
+{
+ mHexBuffer->setStartX( val );
+}
+
+inline void CHexViewWidget::setStartY( int val )
+{
+ mHexBuffer->setStartY( val );
+}
+
+
+inline void CHexViewWidget::updateWindow( bool completeRedraw,
+ bool touchSelection )
+{
+ if( completeRedraw == true )
+ {
+ SCursorConfig cc;
+ updateCursor( cc, true, touchSelection );
+ updateView( true, false );
+ }
+ else
+ {
+ SCursorConfig cc;
+ updateCursor( cc, false, touchSelection );
+ redrawFromOffset( mHexBuffer->cursorOffset(), true );
+ updateView( false, false );
+ }
+
+ emit fileState( mHexBuffer->fileState() );
+}
+
+
+
+inline void CHexViewWidget::updateWindow( uint line )
+{
+ SCursorConfig cc;
+ updateCursor( cc, false, true );
+ if( line == mHexBuffer->cursorLine() )
+ {
+ redrawLines( line, 1 );
+ }
+ else if( line < mHexBuffer->cursorLine() )
+ {
+ redrawLines( line, mHexBuffer->cursorLine() - line );
+ }
+ else
+ {
+ redrawLines( line, line - mHexBuffer->cursorLine() );
+ }
+ emit fileState( mHexBuffer->fileState() );
+}
+
+
+inline void CHexViewWidget::updateWindow( uint fromOffset, bool finishWindow )
+{
+ SCursorConfig cc;
+ updateCursor( cc, true, true );
+ updateView( false, false );
+ redrawFromOffset( fromOffset, finishWindow );
+
+ emit fileState( mHexBuffer->fileState() );
+}
+
+
+inline void CHexViewWidget::updateWindow( void )
+{
+ setTextBufferSize();
+ mHexBuffer->cursorUp(0); // Makes sure cursor is visible
+
+ SCursorConfig cc;
+ cc.emulateControlButton( true );
+ updateCursor( cc, true, false );
+ updateView( true, false );
+
+ emit fileState( mHexBuffer->fileState() );
+}
+
+
+inline void CHexViewWidget::setTextBufferSize( void )
+{
+ int w = width();
+ int h = mHexBuffer->lineHeight();
+
+ if( w != mTextBuffer.width() || h != mTextBuffer.height() )
+ {
+ mTextBuffer.resize( w, h );
+ }
+}
+
+
+inline void CHexViewWidget::autoCopy( void )
+{
+ if( mMisc.autoCopyToClipboard == true )
+ {
+ copy();
+ }
+}
+
+
+inline bool CHexViewWidget::insertMode( void )
+{
+ return mEditMode == CHexBuffer::EditInsert;
+}
+
+
+inline int CHexViewWidget::scrollBarWidth( void )
+{
+ return( mScrollBarSize );
+}
+
+inline int CHexViewWidget::dataWidth( void )
+{
+ return( mHexBuffer->lineWidth() );
+}
+
+inline int CHexViewWidget::defaultWidth( void )
+{
+ return( dataWidth() + scrollBarWidth() + frameWidth()*2 );
+}
+
+
+inline uint CHexViewWidget::offset( void )
+{
+ return( mHexBuffer->cursorOffset() );
+}
+
+inline uint CHexViewWidget::bookmarkCount( void )
+{
+ const QPtrList<SCursorOffset> &list = mHexBuffer->bookmarkList();
+ return( list.count() );
+}
+
+inline bool CHexViewWidget::modified( void )
+{
+ return( mHexBuffer->modified() );
+}
+
+inline void CHexViewWidget::setModified( bool modified )
+{
+ mHexBuffer->setModified( modified );
+ emit fileState( mHexBuffer->fileState() );
+}
+
+inline const QDateTime &CHexViewWidget::diskModifyTime( void )
+{
+ return( mHexBuffer->diskModifyTime() );
+}
+
+inline bool CHexViewWidget::losslessEncoding( CConversion::EMode mode )
+{
+ return( mHexBuffer->losslessEncoding(mode) );
+}
+
+inline const SEncodeState &CHexViewWidget::encoding( void )
+{
+ return( mHexBuffer->encoding() );
+}
+
+inline bool CHexViewWidget::documentPresent( void )
+{
+ return( mHexBuffer->documentPresent() );
+}
+
+inline bool CHexViewWidget::urlValid( void )
+{
+ return( mHexBuffer->hasFileName() );
+}
+
+inline QString &CHexViewWidget::url( void )
+{
+ return( mHexBuffer->url() );
+}
+
+inline void CHexViewWidget::setUrl( QString &url )
+{
+ if( mHexBuffer->url() != url )
+ {
+ emit fileRename( mHexBuffer->url(), url );
+ mHexBuffer->setUrl( url );
+ }
+}
+
+inline const CHexBuffer *CHexViewWidget::hexBuffer( void )
+{
+ return( mHexBuffer );
+}
+
+
+#endif
+
+
+
+
diff --git a/khexedit/hi16-app-khexedit.png b/khexedit/hi16-app-khexedit.png
new file mode 100644
index 0000000..9b23931
--- /dev/null
+++ b/khexedit/hi16-app-khexedit.png
Binary files differ
diff --git a/khexedit/hi32-app-khexedit.png b/khexedit/hi32-app-khexedit.png
new file mode 100644
index 0000000..cc64da0
--- /dev/null
+++ b/khexedit/hi32-app-khexedit.png
Binary files differ
diff --git a/khexedit/hi48-app-khexedit.png b/khexedit/hi48-app-khexedit.png
new file mode 100644
index 0000000..429c424
--- /dev/null
+++ b/khexedit/hi48-app-khexedit.png
Binary files differ
diff --git a/khexedit/khexedit.desktop b/khexedit/khexedit.desktop
new file mode 100644
index 0000000..befa3d7
--- /dev/null
+++ b/khexedit/khexedit.desktop
@@ -0,0 +1,86 @@
+[Desktop Entry]
+GenericName=Binary Editor
+GenericName[af]=Binêre Redigeerder
+GenericName[ar]=محرر ثنائى
+GenericName[bg]=Двоичен редактор
+GenericName[br]=Aozer binarel
+GenericName[bs]=Binarni editor
+GenericName[ca]=Editor binari
+GenericName[cs]=Binární editor
+GenericName[cy]=Golygydd Deuaidd
+GenericName[da]=Binær editor
+GenericName[de]=Binäreditor
+GenericName[el]=ΕπεξεÏγαστής δυαδικών αÏχείων
+GenericName[eo]=Deksesuma redaktilo
+GenericName[es]=Editor binario
+GenericName[et]=Binaarfailide redaktor
+GenericName[eu]=Editore Binarioa
+GenericName[fa]=ویرایشگر دوگانی
+GenericName[fi]=Binäärieditori
+GenericName[fr]=Éditeur hexadécimal
+GenericName[ga]=Eagarthóir Dénártha
+GenericName[he]=עורך בינרי
+GenericName[hi]=दà¥à¤µà¤¿à¤šà¤° संपादक
+GenericName[hr]=Binarni ureÄ‘ivaÄ
+GenericName[hu]=Hexaszerkesztő
+GenericName[is]=Tvíunda-ritill
+GenericName[it]=Editor binario
+GenericName[ja]=ãƒã‚¤ãƒŠãƒªã‚¨ãƒ‡ã‚£ã‚¿
+GenericName[ka]=ბინáƒáƒ áƒ£áƒšáƒ˜ რედáƒáƒ¥áƒ¢áƒáƒ áƒ˜
+GenericName[kk]=Бинарлық редактор
+GenericName[km]=កម្មវិធី​និពន្ធ​គោលពីរ
+GenericName[lt]=Dvejetainio kodo redaktorius
+GenericName[lv]=BinÄrais Redaktors
+GenericName[mk]=Бинарен уредувач
+GenericName[ms]=Penyunting Binari
+GenericName[mt]=Editur binarju
+GenericName[nb]=Binærredigerer
+GenericName[nds]=Hexeditor
+GenericName[ne]=बाइनरी समà¥à¤ªà¤¾à¤¦à¤•
+GenericName[nl]=Binaire bestanden bewerken
+GenericName[nn]=Program for binærredingerig
+GenericName[pa]=ਬਾਈਨਰੀ ਸੰਪਾਦਕ
+GenericName[pl]=Editor Binarny
+GenericName[pt]=Editor Binário
+GenericName[pt_BR]=Editor de Binários
+GenericName[ro]=Editor date binare
+GenericName[ru]=Двоичный редактор
+GenericName[sk]=Binárny editor
+GenericName[sl]=Binarni urejevalnik
+GenericName[sr]=Уређивач бинарних фајлова
+GenericName[sr@Latn]=UreÄ‘ivaÄ binarnih fajlova
+GenericName[sv]=Binäreditor
+GenericName[ta]=இரà¯à®¨à®¿à®²à¯ˆ தொகà¯à®ªà¯à®ªà®¾à®©à¯
+GenericName[tg]=Муҳаррири Дуӣ
+GenericName[th]=เครื่องมือà¹à¸à¹‰à¹„ขเลขà¸à¸²à¸™
+GenericName[tr]=İkili dosya düzenleyici
+GenericName[uk]=Двійковий редактор
+GenericName[ven]=Musengulusi kavhili
+GenericName[vi]=Trình biên tập nhị phân
+GenericName[wa]=Aspougneu binaire
+GenericName[xh]=Umphathi Webhetri
+GenericName[zh_CN]=二进制编辑器
+GenericName[zh_TW]=二進ä½ç·¨è¼¯å™¨
+GenericName[zu]=Umhleli Ohambisana ngambili
+Name=KHexEdit
+Name[af]=Khex-redigeerder
+Name[eo]=Deksesuma redaktilo
+Name[hi]=के-हेकà¥à¤¸-à¤à¤¡à¤¿à¤Ÿ
+Name[pl]=Edytor binarny
+Name[pt_BR]=Editor Hexadecimal
+Name[sv]=Khexedit
+Name[ta]=KHexதொகà¯à®ªà¯à®ªà¯
+Name[th]=à¹à¸à¹‰à¹„ขเลขà¸à¸²à¸™
+Name[tr]=Onaltılı Düzenleyici
+Name[ven]=U sengulusa ha KHex
+Name[zh_TW]=KHex 編輯器
+Exec=khexedit -caption "%c" %i %m %U
+Icon=khexedit
+Path=
+Type=Application
+DocPath=khexedit/index.html
+Terminal=false
+X-KDE-StartupNotify=true
+X-DCOP-ServiceType=Multi
+Categories=Qt;KDE;Utility;X-KDE-Utilities-File;
+
diff --git a/khexedit/khexeditui.rc b/khexedit/khexeditui.rc
new file mode 100644
index 0000000..5be593a
--- /dev/null
+++ b/khexedit/khexeditui.rc
@@ -0,0 +1,137 @@
+<!DOCTYPE kpartgui>
+<kpartgui name="khexedit" version="1">
+<MenuBar>
+ <Menu name="file">
+ <Action name="insert_file" append="open_merge"/>
+ <Action name="export" append="print_merge"/>
+ <Separator/>
+ <Action name="cancel"/>
+ <Menu name="permission">
+ <text>Permissions</text>
+ <Action name="read_only"/>
+ <Action name="resize_lock"/>
+ </Menu>
+ <Separator/>
+ <Action name="new_window"/>
+ <Action name="close_window"/>
+ </Menu>
+ <Menu name="edit">
+ <Menu name="special" append="edit_paste_merge"><text>Spec&amp;ial</text>
+ <Action name="copy_as_text"/>
+ <Action name="paste_into_new_file"/>
+ <Action name="paste_into_new_window"/>
+ </Menu>
+ <Action name="goto_offset"/>
+ <Action name="insert_pattern"/>
+ </Menu>
+ <Menu name="view">
+ <Action name="mode_hex"/>
+ <Action name="mode_dec"/>
+ <Action name="mode_oct"/>
+ <Action name="mode_bin"/>
+ <Action name="mode_text"/>
+ <Separator/>
+ <Action name="show_offset_column"/>
+ <Action name="show_text_field"/>
+ <Separator/>
+ <Action name="offset_as_decimal"/>
+ <Separator/>
+ <Action name="upper_case_data"/>
+ <Action name="upper_case_offset"/>
+ <Separator/>
+ <Menu name="encoding"><text>Document &amp;Encoding</text>
+ <Action name="enc_default"/>
+ <Action name="enc_ascii"/>
+ <Action name="enc_ebcdic"/>
+<!-- <Action name="enc_custom"/> //-->
+ </Menu>
+ </Menu>
+ <Menu name="bookmarks">
+ <Action name="replace_bookmark"/>
+ <Action name="remove_bookmark"/>
+ <Action name="remove_all_bookmarks"/>
+ <Separator/>
+ <Action name="next_bookmark"/>
+ <Action name="prev_bookmark"/>
+ <ActionList name="bookmark_list"/>
+ </Menu>
+ <Menu name="tools">
+ <Action name="extract_strings"/>
+<!-- <Action name="record_viewer"/> //-->
+ <Action name="binary_filter"/>
+ <Action name="char_table"/>
+ <Action name="converter"/>
+ <Separator/>
+ <Action name="statistics"/>
+ </Menu>
+ <Menu name="documents"><text>&amp;Documents</text>
+ </Menu>
+ <Menu name="settings">
+ <Separator append="show_merge"/>
+ <Action name="show_full_path" append="show_merge"/>
+ <Separator append="show_merge"/>
+ <Menu name="doctab" append="show_merge"><text>&amp;Document Tabs</text>
+ <Action name="doctab_hide"/>
+ <Action name="doctab_above"/>
+ <Action name="doctab_below"/>
+ </Menu>
+ <Menu name="conversion_field" append="show_merge"><text>Conversion &amp;Field</text>
+ <Action name="conversion_field_hide"/>
+ <Action name="conversion_field_float"/>
+ <Action name="conversion_field_embed"/>
+ </Menu>
+ <Menu name="searchbar" append="show_merge"><text>Searc&amp;hbar</text>
+ <Action name="searchbar_hide"/>
+ <Action name="searchbar_above"/>
+ <Action name="searchbar_below"/>
+ </Menu>
+<!-- <Action name="favorites"/> //-->
+ </Menu>
+</MenuBar>
+
+<!-- main toolbar //-->
+<ToolBar name="mainToolBar" noMerge="1"><text>Main Toolbar</text>
+ <Action name="drag_document"/>
+ <Separator lineSeparator="true"/>
+ <Action name="file_new"/>
+ <Action name="file_open"/>
+ <Action name="file_save"/>
+ <Action name="file_revert"/>
+ <Action name="file_print"/>
+ <Separator/>
+ <Action name="edit_undo"/>
+ <Action name="edit_redo"/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Separator/>
+ <Action name="edit_find"/>
+ <Action name="edit_find_last"/>
+ <Action name="edit_find_next"/>
+ <Separator/>
+ <Action name="cancel"/>
+ <Action name="help"/>
+</ToolBar>
+
+<!-- Editor popup menu //-->
+<Menu name="editor_popup">
+ <Action name="file_open"/>
+ <Action name="file_save"/>
+ <Action name="file_save_as"/>
+ <Separator/>
+ <Menu name="editor_bookmark_popup">
+ <text>&amp;Bookmarks</text>
+ <Action name="bookmark_add"/>
+ <ActionList name="bookmark_list"/>
+ </Menu>
+ <Separator/>
+ <Action name="mode_hex"/>
+ <Action name="mode_dec"/>
+ <Action name="mode_oct"/>
+ <Action name="mode_bin"/>
+ <Action name="mode_text"/>
+ <Separator/>
+ <Action name="read_only"/>
+ <Action name="resize_lock"/>
+</Menu>
+</kpartgui>
diff --git a/khexedit/lib/Makefile.am b/khexedit/lib/Makefile.am
new file mode 100644
index 0000000..c0c92cc
--- /dev/null
+++ b/khexedit/lib/Makefile.am
@@ -0,0 +1,39 @@
+SUBDIRS = controller codecs
+
+INCLUDES = $(all_includes)
+
+METASOURCES = AUTO
+
+# this library is used by the kbytesedit part and the khepart part
+lib_LTLIBRARIES = libkhexeditcommon.la
+libkhexeditcommon_la_LDFLAGS = $(all_libraries) -no-undefined
+libkhexeditcommon_la_LIBADD = controller/libkcontroller.la codecs/libkhecodecs.la $(LIB_KDECORE)
+libkhexeditcommon_la_SOURCES = kcolumn.cpp kbordercolumn.cpp koffsetcolumn.cpp \
+ kbuffercolumn.cpp kvaluecolumn.cpp kcharcolumn.cpp \
+ kcolumnsview.cpp khexedit.cpp kbytesedit.cpp \
+ koffsetformat.cpp \
+ kdatabuffer.cpp kwrappingrobuffer.cpp \
+ kplainbuffer.cpp kfixedsizebuffer.cpp kbigbuffer.cpp \
+ kbuffercursor.cpp kbufferlayout.cpp kbufferranges.cpp \
+ kcursor.cpp kbufferdrag.cpp \
+ kwordbufferservice.cpp \
+ ksectionlist.cpp kcoordrangelist.cpp \
+ kbordercoltextexport.cpp koffsetcoltextexport.cpp \
+ kbuffercoltextexport.cpp kvaluecoltextexport.cpp kcharcoltextexport.cpp
+
+# no public API for a direct use by now
+noinst_HEADERS = kcolumn.h kbordercolumn.h koffsetcolumn.h \
+ kbuffercolumn.h kvaluecolumn.h kcharcolumn.h \
+ kbytecodec.h koffsetformat.h khexedit_export.h \
+ kbuffercursor.h kbufferlayout.h kbufferranges.h \
+ kbuffercoord.h kselection.h \
+ kcursor.h kbufferdrag.h \
+ kcoordrange.h ksectionlist.h kcoordrangelist.h \
+ khechar.h kcharcodec.h \
+ kcoltextexport.h kbordercoltextexport.h koffsetcoltextexport.h \
+ kbuffercoltextexport.h kvaluecoltextexport.h kcharcoltextexport.h \
+ kadds.h khe.h krange.h ksection.h \
+ kwordbufferservice.h \
+ kcolumnsview.h khexedit.h kbytesedit.h \
+ kplainbuffer.h kfixedsizebuffer.h kbigbuffer.h \
+ kdatabuffer.h kreadonlybuffer.h kwrappingrobuffer.h
diff --git a/khexedit/lib/README b/khexedit/lib/README
new file mode 100644
index 0000000..ad5f346
--- /dev/null
+++ b/khexedit/lib/README
@@ -0,0 +1,36 @@
+hex editor library
+==================
+part of the KHexEdit 2 project (kdenonbeta/khexedit2)
+Author/Maintainer: Friedrich W. H. Kossebau <Friedrich.W.H@Kossebau.de>
+
+
+description:
+-----------
+The lib is the main work of KHexEdit2. It offers
+a general usable hex edit widget "KHexEdit"
+that interacts with an abstract data buffer
+interface called "KDataBuffer". This interface can
+be subclassed to offer access to different data buffers
+like paged gigabyte big files, video memory or whatever
+you can imagine (hopefully).
+
+For those simply needing a widget for a plain array of bytes
+there is the widget subclass "KBytesEdit", which hides the
+databuffer interface and publically simply interacts with
+arrays (like "char Array[25];").
+
+
+installing:
+-----------
+As these widgets and the databuffer interface have not got
+much testing the API might not be finished. Because of that
+it won't be made public available, i.e. there will be no headers
+installed.
+
+
+usage:
+------
+This lib is by now only used by the KBytesEdit part, to be found
+in "../parts/kbytesedit".
+It is _not_ used by the current KHexEdit 1 app. This will change once
+the successor app from KHexEdit2 is done. \ No newline at end of file
diff --git a/khexedit/lib/codecs/Makefile.am b/khexedit/lib/codecs/Makefile.am
new file mode 100644
index 0000000..0c208b7
--- /dev/null
+++ b/khexedit/lib/codecs/Makefile.am
@@ -0,0 +1,15 @@
+INCLUDES = -I$(srcdir)/.. $(all_includes)
+
+METASOURCES = AUTO
+
+#
+noinst_LTLIBRARIES = libkhecodecs.la
+libkhecodecs_la_SOURCES = kcharcodec.cpp kbytecodec.cpp \
+ ktextcharcodec.cpp kebcdic1047charcodec.cpp \
+ kbinarybytecodec.cpp koctalbytecodec.cpp \
+ kdecimalbytecodec.cpp khexadecimalbytecodec.cpp
+
+# no public API
+noinst_HEADERS = ktextcharcodec.h kebcdic1047charcodec.h \
+ kbinarybytecodec.h koctalbytecodec.h \
+ kdecimalbytecodec.h khexadecimalbytecodec.h \ No newline at end of file
diff --git a/khexedit/lib/codecs/README b/khexedit/lib/codecs/README
new file mode 100644
index 0000000..b4a0e52
--- /dev/null
+++ b/khexedit/lib/codecs/README
@@ -0,0 +1 @@
+This directory holds all the char codecs. All it exports is the call "createCodec()", the rest in hidden.
diff --git a/khexedit/lib/codecs/kbinarybytecodec.cpp b/khexedit/lib/codecs/kbinarybytecodec.cpp
new file mode 100644
index 0000000..d665a05
--- /dev/null
+++ b/khexedit/lib/codecs/kbinarybytecodec.cpp
@@ -0,0 +1,80 @@
+/***************************************************************************
+ kbinarybytecodec.cpp - description
+ -------------------
+ begin : Mo Nov 29 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// lib specific
+#include "kbinarybytecodec.h"
+
+using namespace KHE;
+
+
+void KBinaryByteCodec::encode( QString &Digits, unsigned int Pos, const unsigned char Char ) const
+{
+ for( unsigned char M=1<<7; M>0; M>>=1 )
+ Digits.at(Pos++) = (Char & M) ? '1' : '0';
+}
+
+void KBinaryByteCodec::encodeShort( QString &Digits, unsigned int Pos, unsigned char Char ) const
+{
+ unsigned char M = 1<<7;
+ // find first set bit
+ for( ; M>0; M>>=1 )
+ if( Char & M )
+ break;
+ // now set the
+ for( ; M>0; M>>=1 )
+ Digits.at(Pos++) = (Char & M) ? '1' : '0';
+}
+
+
+bool KBinaryByteCodec::isValidDigit( unsigned char Digit ) const
+{
+ return Digit == '0' || Digit == '1';
+}
+
+
+bool KBinaryByteCodec::turnToValue( unsigned char *Digit ) const
+{
+ if( isValidDigit(*Digit) )
+ {
+ *Digit -= '0';
+ return true;
+ }
+ return false;
+}
+
+
+bool KBinaryByteCodec::appendDigit( unsigned char *Byte, unsigned char Digit ) const
+{
+ if( turnToValue(&Digit) )
+ {
+ unsigned char B = *Byte;
+ if( B < 128 )
+ {
+ B <<= 1;
+ B += Digit;
+ *Byte = B;
+ return true;
+ }
+ }
+ return false;
+}
+
+
+void KBinaryByteCodec::removeLastDigit( unsigned char *Byte ) const
+{
+ *Byte >>= 1;
+}
diff --git a/khexedit/lib/codecs/kbinarybytecodec.h b/khexedit/lib/codecs/kbinarybytecodec.h
new file mode 100644
index 0000000..d0354fa
--- /dev/null
+++ b/khexedit/lib/codecs/kbinarybytecodec.h
@@ -0,0 +1,59 @@
+/***************************************************************************
+ kbinarybytecodec.h - description
+ -------------------
+ begin : Mo Nov 29 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KBINARYBYTECODEC_H
+#define KHE_KBINARYBYTECODEC_H
+
+// lib specific
+#include "kbytecodec.h"
+
+namespace KHE
+{
+
+/** class that is able to convert codings to and from binary
+ *
+ * the buffer will be always filled up to CodingWidth, if not using shortCodingFunction
+ * a closing '\0' will be always added
+ *
+ *@author Friedrich W. H. Kossebau
+ */
+
+class KBinaryByteCodec : public KByteCodec
+{
+ public: // API to be implemented
+ /** */
+ virtual unsigned int encodingWidth() const { return 8; }
+ /** */
+ virtual unsigned char digitsFilledLimit() const { return 128; }
+
+ /** encodes the Char and writes the result to */
+ virtual void encode( QString &Digits, unsigned int Pos, const unsigned char Char ) const;
+ /** */
+ virtual void encodeShort( QString &Digits, unsigned int Pos, const unsigned char Char ) const;
+ /** */
+ virtual bool appendDigit( unsigned char *Byte, const unsigned char Digit ) const;
+ /** */
+ virtual void removeLastDigit( unsigned char *Byte ) const;
+ /** */
+ virtual bool isValidDigit( const unsigned char Digit ) const;
+ /** */
+ virtual bool turnToValue( unsigned char *Digit ) const;
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/codecs/kbytecodec.cpp b/khexedit/lib/codecs/kbytecodec.cpp
new file mode 100644
index 0000000..dc5137f
--- /dev/null
+++ b/khexedit/lib/codecs/kbytecodec.cpp
@@ -0,0 +1,63 @@
+/***************************************************************************
+ kbytecodec.cpp - description
+ -------------------
+ begin : Mo Nov 29 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// lib specific
+#include "kbinarybytecodec.h"
+#include "koctalbytecodec.h"
+#include "kdecimalbytecodec.h"
+#include "khexadecimalbytecodec.h"
+
+using namespace KHE;
+
+
+KByteCodec *KByteCodec::createCodec( KCoding C )
+{
+ KByteCodec *Codec;
+ switch( C )
+ {
+ case DecimalCoding: Codec = new KDecimalByteCodec(); break;
+ case OctalCoding: Codec = new KOctalByteCodec(); break;
+ case BinaryCoding: Codec = new KBinaryByteCodec(); break;
+ case HexadecimalCoding:
+ default: Codec = new KHexadecimalByteCodec();
+ }
+ return Codec;
+}
+
+unsigned int KByteCodec::decode( unsigned char *Char, const QString &Digits, uint Pos ) const
+{
+ //kdDebug() << QString("KByteCodec::decode(%1,%2)").arg(Digits).arg(Pos) << endl;
+ const uint P = Pos;
+
+ // remove leading 0s
+ while( Digits.at(Pos) == '0' ) { ++Pos; }
+
+ unsigned char C = 0;
+ unsigned int d = encodingWidth();
+ do
+ {
+ if( !appendDigit(&C,Digits.at(Pos)) )
+ break;
+
+ ++Pos;
+ --d;
+ }
+ while( d > 0 );
+
+ *Char = C;
+ return Pos - P;
+}
diff --git a/khexedit/lib/codecs/kcharcodec.cpp b/khexedit/lib/codecs/kcharcodec.cpp
new file mode 100644
index 0000000..5a58320
--- /dev/null
+++ b/khexedit/lib/codecs/kcharcodec.cpp
@@ -0,0 +1,74 @@
+/***************************************************************************
+ kcharcodec.cpp - description
+ -------------------
+ begin : Do Nov 25 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// lib specific
+#include "kcharcodec.h"
+#include "ktextcharcodec.h"
+#include "kebcdic1047charcodec.h"
+
+using namespace KHE;
+
+
+QStringList KCharCodec::CodecNames;
+
+const QStringList &KCharCodec::codecNames()
+{
+ // first call?
+ if( CodecNames.isEmpty() )
+ {
+ CodecNames = KTextCharCodec::codecNames();
+ CodecNames.append( KEBCDIC1047CharCodec::codecName() );
+ }
+
+ return CodecNames;
+}
+
+
+KCharCodec *KCharCodec::createCodec( const QString &Name )
+{
+ KCharCodec *Codec = 0;
+
+ if( KTextCharCodec::codecNames().findIndex(Name) != -1 )
+ Codec = KTextCharCodec::createCodec( Name );
+ else if( KEBCDIC1047CharCodec::codecName() == Name )
+ Codec = KEBCDIC1047CharCodec::create();
+
+ // ensure at least a codec
+ if( Codec == 0 )
+ Codec = KTextCharCodec::createLocalCodec();
+
+ return Codec;
+}
+
+
+KCharCodec *KCharCodec::createCodec( KEncoding C )
+{
+ KCharCodec *Codec;
+ if( C == EBCDIC1047Encoding )
+ Codec = KEBCDIC1047CharCodec::create();
+ else if( C == ISO8859_1Encoding )
+ Codec = KTextCharCodec::createCodec( "ISO 8859-1" );
+ // LocalEncoding
+ else
+ Codec = 0;
+
+ // ensure at least a codec
+ if( Codec == 0 )
+ Codec = KTextCharCodec::createLocalCodec();
+
+ return Codec;
+}
diff --git a/khexedit/lib/codecs/kdecimalbytecodec.cpp b/khexedit/lib/codecs/kdecimalbytecodec.cpp
new file mode 100644
index 0000000..9470382
--- /dev/null
+++ b/khexedit/lib/codecs/kdecimalbytecodec.cpp
@@ -0,0 +1,92 @@
+/***************************************************************************
+ kdecimalbytecodec.cpp - description
+ -------------------
+ begin : Mo Nov 29 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// lib specific
+#include "kdecimalbytecodec.h"
+
+using namespace KHE;
+
+
+void KDecimalByteCodec::encode( QString &Digits, unsigned int Pos, unsigned char Char ) const
+{
+ unsigned char C = Char / 100;
+ Digits.at(Pos++) = '0'+C;
+ Char -= C * 100;
+ C = Char / 10;
+ Digits.at(Pos++) = '0'+C;
+ Char -= C * 10;
+ Digits.at(Pos) = '0'+Char;
+}
+
+
+void KDecimalByteCodec::encodeShort( QString &Digits, unsigned int Pos, unsigned char Char ) const
+{
+ unsigned char C;
+ if( (C = Char / 100) )
+ {
+ Digits.at(Pos++) = '0'+C;
+ Char -= C * 100;
+ }
+ if( (C = Char / 10) )
+ {
+ Digits.at(Pos++) = '0'+C;
+ Char -= C * 10;
+ }
+ Digits.at(Pos) = '0'+Char;
+}
+
+
+
+bool KDecimalByteCodec::isValidDigit( unsigned char Digit ) const
+{
+ return Digit >= '0' && Digit <= '9';
+}
+
+bool KDecimalByteCodec::turnToValue( unsigned char *Digit ) const
+{
+ if( isValidDigit(*Digit) )
+ {
+ *Digit -= '0';
+ return true;
+ }
+ return false;
+}
+
+
+bool KDecimalByteCodec::appendDigit( unsigned char *Byte, unsigned char Digit ) const
+{
+ if( turnToValue(&Digit) )
+ {
+ unsigned char B = *Byte;
+ if( B < 26 )
+ {
+ B *= 10;
+ if( Digit <= 255-B )
+ {
+ B += Digit;
+ *Byte = B;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void KDecimalByteCodec::removeLastDigit( unsigned char *Byte ) const
+{
+ *Byte /= 10;
+}
diff --git a/khexedit/lib/codecs/kdecimalbytecodec.h b/khexedit/lib/codecs/kdecimalbytecodec.h
new file mode 100644
index 0000000..31f61d0
--- /dev/null
+++ b/khexedit/lib/codecs/kdecimalbytecodec.h
@@ -0,0 +1,59 @@
+/***************************************************************************
+ kdecimalbytecodec.h - description
+ -------------------
+ begin : Mo Nov 29 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KDECIMALBYTECODEC_H
+#define KHE_KDECIMALBYTECODEC_H
+
+// lib specific
+#include "kbytecodec.h"
+
+namespace KHE
+{
+
+/** class that is able to convert codings to and from binary
+ *
+ * the buffer will be always filled up to CodingWidth, if not using shortCodingFunction
+ * a closing '\0' will be always added
+ *
+ *@author Friedrich W. H. Kossebau
+ */
+
+class KDecimalByteCodec : public KByteCodec
+{
+ public: // API to be implemented
+ /** */
+ virtual unsigned int encodingWidth() const { return 3; }
+ /** */
+ virtual unsigned char digitsFilledLimit() const { return 26; }
+
+ /** encodes the Char and writes the result to */
+ virtual void encode( QString &Digits, unsigned int Pos, const unsigned char Char ) const;
+ /** */
+ virtual void encodeShort( QString &Digits, unsigned int Pos, const unsigned char Char ) const;
+ /** */
+ virtual bool appendDigit( unsigned char *Byte, const unsigned char Digit ) const;
+ /** */
+ virtual void removeLastDigit( unsigned char *Byte ) const;
+ /** */
+ virtual bool isValidDigit( const unsigned char Digit ) const;
+ /** */
+ virtual bool turnToValue( unsigned char *Digit ) const;
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/codecs/kebcdic1047charcodec.cpp b/khexedit/lib/codecs/kebcdic1047charcodec.cpp
new file mode 100644
index 0000000..f26da37
--- /dev/null
+++ b/khexedit/lib/codecs/kebcdic1047charcodec.cpp
@@ -0,0 +1,124 @@
+/***************************************************************************
+ kebcdic1047charcodec.cpp - description
+ -------------------
+ begin : Sa Nov 27 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// lib specific
+#include "kebcdic1047charcodec.h"
+
+
+using namespace KHE;
+
+static Q_UINT16 UnicodeChars[256] =
+{
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x009C, 0x0009, 0x0086, 0x007F,
+ 0x0097, 0x008D, 0x008E, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x009D, 0x0085, 0x0008, 0x0087,
+ 0x0018, 0x0019, 0x0092, 0x008F, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x000A, 0x0017, 0x001B,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x0005, 0x0006, 0x0007,
+ 0x0090, 0x0091, 0x0016, 0x0093, 0x0094, 0x0095, 0x0096, 0x0004,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x0014, 0x0015, 0x009E, 0x001A,
+ 0x0020, 0x00A0, 0x00E2, 0x00E4, 0x00E0, 0x00E1, 0x00E3, 0x00E5,
+ 0x00E7, 0x00F1, 0x00A2, 0x002E, 0x003C, 0x0028, 0x002B, 0x007C,
+ 0x0026, 0x00E9, 0x00EA, 0x00EB, 0x00E8, 0x00ED, 0x00EE, 0x00EF,
+ 0x00EC, 0x00DF, 0x0021, 0x0024, 0x002A, 0x0029, 0x003B, 0x005E,
+ 0x002D, 0x002F, 0x00C2, 0x00C4, 0x00C0, 0x00C1, 0x00C3, 0x00C5,
+ 0x00C7, 0x00D1, 0x00A6, 0x002C, 0x0025, 0x005F, 0x003E, 0x003F,
+ 0x00F8, 0x00C9, 0x00CA, 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF,
+ 0x00CC, 0x0060, 0x003A, 0x0023, 0x0040, 0x0027, 0x003D, 0x0022,
+ 0x00D8, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x00AB, 0x00BB, 0x00F0, 0x00FD, 0x00FE, 0x00B1,
+ 0x00B0, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070,
+ 0x0071, 0x0072, 0x00AA, 0x00BA, 0x00E6, 0x00B8, 0x00C6, 0x00A4,
+ 0x00B5, 0x007E, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078,
+ 0x0079, 0x007A, 0x00A1, 0x00BF, 0x00D0, 0x005B, 0x00DE, 0x00AE,
+ 0x00AC, 0x00A3, 0x00A5, 0x00B7, 0x00A9, 0x00A7, 0x00B6, 0x00BC,
+ 0x00BD, 0x00BE, 0x00DD, 0x00A8, 0x00AF, 0x005D, 0x00B4, 0x00D7,
+ 0x007B, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x00AD, 0x00F4, 0x00F6, 0x00F2, 0x00F3, 0x00F5,
+ 0x007D, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050,
+ 0x0051, 0x0052, 0x00B9, 0x00FB, 0x00FC, 0x00F9, 0x00FA, 0x00FF,
+ 0x005C, 0x00F7, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005A, 0x00B2, 0x00D4, 0x00D6, 0x00D2, 0x00D3, 0x00D5,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x00B3, 0x00DB, 0x00DC, 0x00D9, 0x00DA, 0x009F
+};
+
+static unsigned char EBCDICChars[256] =
+{
+ 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
+ 0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,
+ 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
+ 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
+ 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+ 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
+ 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
+ 0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
+ 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17,
+ 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B,
+ 0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08,
+ 0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF,
+ 0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5,
+ 0xBB, 0xB4, 0x9A, 0x8A, 0xB0, 0xCA, 0xAF, 0xBC,
+ 0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3,
+ 0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB,
+ 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68,
+ 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77,
+ 0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF,
+ 0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xBA, 0xAE, 0x59,
+ 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48,
+ 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57,
+ 0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1,
+ 0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF
+};
+
+static const char KEBCDIC1047CharCodecName[] = "EBCDIC 1047";
+
+
+bool KEBCDIC1047CharCodec::encode( char *D, const QChar &C ) const
+{
+ int I = C.unicode();
+ // not in range?
+ if( 0x00FF < I )
+ return false;
+
+ *D = EBCDICChars[I];
+ return true;
+}
+
+KHEChar KEBCDIC1047CharCodec::decode( char Byte ) const
+{
+ return QChar(UnicodeChars[(unsigned char)Byte]);
+}
+
+const QString& KEBCDIC1047CharCodec::name() const
+{
+ return codecName();
+}
+
+const QString& KEBCDIC1047CharCodec::codecName()
+{
+ static const QString Name( QString::fromLatin1(KEBCDIC1047CharCodecName) );
+ return Name;
+}
diff --git a/khexedit/lib/codecs/kebcdic1047charcodec.h b/khexedit/lib/codecs/kebcdic1047charcodec.h
new file mode 100644
index 0000000..7c30956
--- /dev/null
+++ b/khexedit/lib/codecs/kebcdic1047charcodec.h
@@ -0,0 +1,50 @@
+/***************************************************************************
+ kebcdic1047charcodec.h - description
+ -------------------
+ begin : Sa Nov 27 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KEBCDIC1047CHARCODEC_H
+#define KHE_KEBCDIC1047CHARCODEC_H
+
+
+#include "kcharcodec.h"
+
+namespace KHE
+{
+
+//
+class KEBCDIC1047CharCodec : public KCharCodec
+{
+ protected:
+ KEBCDIC1047CharCodec();
+
+ public: // KCharCodec API
+ virtual KHEChar decode( char Byte ) const;
+ virtual bool encode( char *D, const QChar &C ) const;
+ virtual const QString& name() const;
+
+ public:
+ static KEBCDIC1047CharCodec *create();
+ static const QString& codecName();
+};
+
+
+inline KEBCDIC1047CharCodec::KEBCDIC1047CharCodec() {}
+
+inline KEBCDIC1047CharCodec *KEBCDIC1047CharCodec::create() { return new KEBCDIC1047CharCodec(); }
+
+}
+
+#endif
diff --git a/khexedit/lib/codecs/khexadecimalbytecodec.cpp b/khexedit/lib/codecs/khexadecimalbytecodec.cpp
new file mode 100644
index 0000000..7072464
--- /dev/null
+++ b/khexedit/lib/codecs/khexadecimalbytecodec.cpp
@@ -0,0 +1,113 @@
+/***************************************************************************
+ khexadecimalbytecodec.cpp - description
+ -------------------
+ begin : Mo Nov 29 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// lib specific
+#include "khexadecimalbytecodec.h"
+
+using namespace KHE;
+
+
+static const QChar BigDigit[16] =
+{ '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
+static const QChar SmallDigit[16] =
+{ '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
+
+
+KHexadecimalByteCodec::KHexadecimalByteCodec( bool S ) : Digit( S?SmallDigit:BigDigit ) {}
+
+bool KHexadecimalByteCodec::setSmallDigits( bool S )
+{
+ bool Change = ( S && Digit == BigDigit );
+ Digit = S?SmallDigit:BigDigit;
+ return Change;
+}
+
+bool KHexadecimalByteCodec::smallDigits() const { return Digit != BigDigit; }
+
+
+void KHexadecimalByteCodec::encode( QString &Digits, unsigned int Pos, unsigned char Char ) const
+{
+ Digits.at(Pos++) = Digit[Char>>4];
+ Digits.at(Pos) = Digit[Char&0x0F];
+}
+
+void KHexadecimalByteCodec::encodeShort( QString &Digits, unsigned int Pos, unsigned char Char ) const
+{
+ unsigned char C;
+ if( (C = (Char>>4)) )
+ Digits.at(Pos++) = Digit[C];
+ Digits.at(Pos) = Digit[Char&0x0F];
+}
+
+
+static inline bool isValidBigDigit( unsigned char Digit )
+{
+ return (Digit >= 'A' && Digit <= 'F');
+}
+
+static inline bool isValidSmallDigit( unsigned char Digit )
+{
+ return (Digit >= 'a' && Digit <= 'f');
+}
+
+static inline bool isValidDecimalDigit( unsigned char Digit )
+{
+ return Digit >= '0' && Digit <= '9';
+}
+
+
+bool KHexadecimalByteCodec::isValidDigit( unsigned char Digit ) const
+{
+ return isValidDecimalDigit(Digit) || isValidBigDigit(Digit) || isValidSmallDigit(Digit);
+}
+
+bool KHexadecimalByteCodec::turnToValue( unsigned char *Digit ) const
+{
+ if( isValidDecimalDigit(*Digit) )
+ *Digit -= '0';
+ else if( isValidBigDigit(*Digit) )
+ *Digit -= 'A' - 10;
+ else if( isValidSmallDigit(*Digit) )
+ *Digit -= 'a' - 10;
+ else
+ return false;
+
+ return true;
+}
+
+bool KHexadecimalByteCodec::appendDigit( unsigned char *Byte, unsigned char Digit ) const
+{
+ if( turnToValue(&Digit) )
+ {
+ unsigned char B = *Byte;
+ if( B < 16 )
+ {
+ B <<= 4;
+ B += Digit;
+ *Byte = B;
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+void KHexadecimalByteCodec::removeLastDigit( unsigned char *Byte ) const
+{
+ *Byte >>= 4;
+}
diff --git a/khexedit/lib/codecs/khexadecimalbytecodec.h b/khexedit/lib/codecs/khexadecimalbytecodec.h
new file mode 100644
index 0000000..9bb1969
--- /dev/null
+++ b/khexedit/lib/codecs/khexadecimalbytecodec.h
@@ -0,0 +1,69 @@
+/***************************************************************************
+ khexadecimalbytecodec.h - description
+ -------------------
+ begin : Mo Nov 29 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KHEXADECIMALBYTECODEC_H
+#define KHE_KHEXADECIMALBYTECODEC_H
+
+// lib specific
+#include "kbytecodec.h"
+
+namespace KHE
+{
+
+/** class that is able to convert codings to and from hexadecimal
+ *
+ * the buffer will be always filled up to CodingWidth, if not using shortCodingFunction
+ * a closing '\0' will be always added
+ *
+ *@author Friedrich W. H. Kossebau
+ */
+
+class KHexadecimalByteCodec : public KByteCodec
+{
+ public:
+ KHexadecimalByteCodec( bool S = false );
+
+ public:
+ bool setSmallDigits( bool S );
+ bool smallDigits() const;
+
+ public: // API to be implemented
+ /** */
+ virtual unsigned int encodingWidth() const { return 2; }
+ /** */
+ virtual unsigned char digitsFilledLimit() const { return 16; }
+
+ /** encodes the Char and writes the result to */
+ virtual void encode( QString &Digits, unsigned int Pos, const unsigned char Char ) const;
+ /** */
+ virtual void encodeShort( QString &Digits, unsigned int Pos, const unsigned char Char ) const;
+ /** */
+ virtual bool appendDigit( unsigned char *Byte, const unsigned char Digit ) const;
+ /** */
+ virtual void removeLastDigit( unsigned char *Byte ) const;
+ /** */
+ virtual bool isValidDigit( const unsigned char Digit ) const;
+ /** */
+ virtual bool turnToValue( unsigned char *Digit ) const;
+
+ protected:
+ const QChar* Digit;
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/codecs/koctalbytecodec.cpp b/khexedit/lib/codecs/koctalbytecodec.cpp
new file mode 100644
index 0000000..1167941
--- /dev/null
+++ b/khexedit/lib/codecs/koctalbytecodec.cpp
@@ -0,0 +1,80 @@
+/***************************************************************************
+ koctalbytecodec.cpp - description
+ -------------------
+ begin : Mo Nov 29 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// lib specific
+#include "koctalbytecodec.h"
+
+using namespace KHE;
+
+
+void KOctalByteCodec::encode( QString &Digits, unsigned int Pos, unsigned char Char ) const
+{
+ Digits.at(Pos++) = '0'+(Char>>6);
+ Digits.at(Pos++) = '0'+((Char>>3)&0x07);
+ Digits.at(Pos) = '0'+((Char) &0x07);
+}
+
+
+void KOctalByteCodec::encodeShort( QString &Digits, unsigned int Pos, unsigned char Char ) const
+{
+ unsigned char C;
+ if( (C = (Char>>6)&0x07) )
+ Digits.at(Pos++) = '0'+C;
+ if( (C = (Char>>3)&0x07) )
+ Digits.at(Pos++) = '0'+C;
+ Digits.at(Pos) = '0'+((Char)&0x07);
+}
+
+
+bool KOctalByteCodec::isValidDigit( unsigned char Digit ) const
+{
+ return Digit >= '0' && Digit <= '7';
+}
+
+
+bool KOctalByteCodec::turnToValue( unsigned char *Digit ) const
+{
+ if( isValidDigit(*Digit) )
+ {
+ *Digit -= '0';
+ return true;
+ }
+ return false;
+}
+
+
+bool KOctalByteCodec::appendDigit( unsigned char *Byte, unsigned char Digit ) const
+{
+ if( turnToValue(&Digit) )
+ {
+ unsigned char B = *Byte;
+ if( B < 64 )
+ {
+ B <<= 3;
+ B += Digit;
+ *Byte = B;
+ return true;
+ }
+ }
+ return false;
+}
+
+
+void KOctalByteCodec::removeLastDigit( unsigned char *Byte ) const
+{
+ *Byte >>= 3;
+}
diff --git a/khexedit/lib/codecs/koctalbytecodec.h b/khexedit/lib/codecs/koctalbytecodec.h
new file mode 100644
index 0000000..e05ca66
--- /dev/null
+++ b/khexedit/lib/codecs/koctalbytecodec.h
@@ -0,0 +1,59 @@
+/***************************************************************************
+ koctalbytecodec.h - description
+ -------------------
+ begin : Mo Nov 29 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KOCTALBYTECODEC_H
+#define KHE_KOCTALBYTECODEC_H
+
+// lib specific
+#include "kbytecodec.h"
+
+namespace KHE
+{
+
+/** class that is able to convert codings to and from binary
+ *
+ * the buffer will be always filled up to CodingWidth, if not using shortCodingFunction
+ * a closing '\0' will be always added
+ *
+ *@author Friedrich W. H. Kossebau
+ */
+
+class KOctalByteCodec : public KByteCodec
+{
+ public: // API to be implemented
+ /** */
+ virtual unsigned int encodingWidth() const { return 3; }
+ /** */
+ virtual unsigned char digitsFilledLimit() const { return 64; }
+
+ /** encodes the Char and writes the result to */
+ virtual void encode( QString &Digits, unsigned int Pos, const unsigned char Char ) const;
+ /** */
+ virtual void encodeShort( QString &Digits, unsigned int Pos, const unsigned char Char ) const;
+ /** */
+ virtual bool appendDigit( unsigned char *Byte, const unsigned char Digit ) const;
+ /** */
+ virtual void removeLastDigit( unsigned char *Byte ) const;
+ /** */
+ virtual bool isValidDigit( const unsigned char Digit ) const;
+ /** */
+ virtual bool turnToValue( unsigned char *Digit ) const;
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/codecs/ktextcharcodec.cpp b/khexedit/lib/codecs/ktextcharcodec.cpp
new file mode 100644
index 0000000..613dedd
--- /dev/null
+++ b/khexedit/lib/codecs/ktextcharcodec.cpp
@@ -0,0 +1,236 @@
+/***************************************************************************
+ ktextcharcodec.cpp - description
+ -------------------
+ begin : Sa Nov 27 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// qt specific
+#include "qtextcodec.h"
+// kde specific
+#include <kglobal.h>
+#include <klocale.h>
+#include <kcharsets.h>
+// lib specific
+#include "ktextcharcodec.h"
+
+
+using namespace KHE;
+
+static const char QTextCodecWhiteSpace = 63;
+
+static struct KEncodingNames {
+ KEncoding Encoding;
+ const char *Name;
+}
+const EncodingNames[] = {
+{ ISO8859_1Encoding, "ISO 8859-1" },
+{ ISO8859_2Encoding, "ISO 8859-2" },
+{ ISO8859_3Encoding, "ISO 8859-3" },
+{ ISO8859_4Encoding, "ISO 8859-4" },
+{ ISO8859_5Encoding, "ISO 8859-5" },
+{ ISO8859_6Encoding, "ISO 8859-6" },
+{ ISO8859_7Encoding, "ISO 8859-7" },
+{ ISO8859_8Encoding, "ISO 8859-8" },
+{ ISO8859_8_IEncoding, "ISO 8859-8-I" },
+{ ISO8859_9Encoding, "ISO 8859-9" },
+{ ISO8859_11Encoding, "ISO 8859-11" },
+{ ISO8859_13Encoding, "ISO 8859-13" },
+{ ISO8859_15Encoding, "ISO 8859-15" },
+{ CP1250Encoding, "CP 1250" },
+{ CP1251Encoding, "CP 1251" },
+{ CP1252Encoding, "CP 1252" },
+{ CP1253Encoding, "CP 1253" },
+{ CP1254Encoding, "CP 1254" },
+{ CP1255Encoding, "CP 1255" },
+{ CP1256Encoding, "CP 1256" },
+{ CP1257Encoding, "CP 1257" },
+{ CP1258Encoding, "CP 1258" },
+{ IBM850Encoding, "IBM 850" },
+{ IBM866Encoding, "IBM 866" },
+{ KOI8_REncoding, "KOI8-R" },
+{ KOI8_UEncoding, "KOI8-U" } };
+//TODO: WS2
+static const unsigned int NoOfEncodings = 26;
+
+static bool is8Bit( QTextCodec *Codec )
+{
+ bool Found = false;
+ for( unsigned int i=0; i<NoOfEncodings; ++i )
+ {
+ if( qstrcmp(Codec->name(),EncodingNames[i].Name) == 0 )
+ {
+ Found = true;
+ break;
+ }
+ }
+ return Found;
+}
+
+static QTextCodec *createLatin1()
+{
+ return KGlobal::charsets()->codecForName( EncodingNames[0].Name );
+}
+
+/** heuristic seems to be doomed :(
+static bool is8Bit( QTextCodec *Codec )
+{
+ bool Result = true;
+
+ // first test different for 0
+ unsigned char c[4];
+ c[0] = 0;
+ c[1] = c[2] = c[3] = 230;
+ QString S = Codec->toUnicode( (const char*)&c,4 );
+ int Length = 1;
+ QCString CS = Codec->fromUnicode( S, Length );
+ //kdDebug() << Codec->name() << " "<<Length << endl;
+ if( Length > 0 )
+ Result = false;
+ // test if all chars survive the recoding
+ else
+ do
+ {
+ ++c[0];
+ S = Codec->toUnicode( (const char*)&c,4 );
+ Length = 1;
+ CS = Codec->fromUnicode( S, Length );
+ //kdDebug() << Codec->name() << " "<<c[0]<<"->"<<CS[0]<<":"<<Length << endl;
+ if( Length != 1 || (CS[0] != (char)c[0] && CS[0] != QTextCodecWhiteSpace) )
+ {
+ Result = false;
+ break;
+ }
+ }
+ while( c[0] < 255 );
+ return Result;
+}
+const QStringList &KTextCharCodec::codecNames()
+{
+ // first call?
+ if( CodecNames.isEmpty() )
+{
+ const QStringList &CharSets = KGlobal::charsets()->availableEncodingNames();
+
+ for( QStringList::ConstIterator it = CharSets.begin(); it != CharSets.end(); ++it )
+{
+ bool Found = true;
+ QTextCodec* Codec = KGlobal::charsets()->codecForName( *it, Found );
+ if( Found && is8Bit(Codec) )
+ CodecNames.append( QString::fromLatin1(Codec->name()) );
+}
+}
+
+ return CodecNames;
+}
+
+QString KTextCharCodec::nameOfEncoding( KEncoding C )
+{
+ KTextCharCodec *Codec = 0;
+
+ const char* N = 0;
+ for( unsigned int i=0; i<NoOfEncodings; ++i )
+ {
+ if( EncodingNames[i].Encoding == C )
+ {
+ N = EncodingNames[i].Name;
+ break;
+ }
+ }
+
+ if( N != 0 )
+ {
+ QString CodeName = QString::fromLatin1( N );
+ }
+ return Codec;
+}
+ */
+
+
+QStringList KTextCharCodec::CodecNames;
+
+KTextCharCodec *KTextCharCodec::createLocalCodec()
+{
+ QTextCodec *Codec = KGlobal::locale()->codecForEncoding();
+ if( !is8Bit(Codec) )
+ Codec = createLatin1();
+ return new KTextCharCodec( Codec );
+}
+
+
+KTextCharCodec *KTextCharCodec::createCodec( const QString &CodeName )
+{
+ bool Ok;
+ QTextCodec *Codec = KGlobal::charsets()->codecForName( CodeName, Ok );
+ if( Ok )
+ Ok = is8Bit( Codec );
+ return Ok ? new KTextCharCodec( Codec ) : 0;
+}
+
+
+const QStringList &KTextCharCodec::codecNames()
+{
+ // first call?
+ if( CodecNames.isEmpty() )
+ {
+ for( unsigned int i=0; i<NoOfEncodings; ++i )
+ {
+ bool Found = true;
+ QString Name = QString::fromLatin1( EncodingNames[i].Name );
+ QTextCodec* Codec = KGlobal::charsets()->codecForName( Name, Found );
+ if( Found )
+ CodecNames.append( QString::fromLatin1(Codec->name()) );
+ }
+ }
+
+ return CodecNames;
+}
+
+
+KTextCharCodec::KTextCharCodec( QTextCodec *C )
+ : Codec( C ),
+ Decoder( C->makeDecoder() ),
+ Encoder( C->makeEncoder() )
+{}
+
+KTextCharCodec::~KTextCharCodec()
+{
+ delete Decoder;
+ delete Encoder;
+}
+
+bool KTextCharCodec::encode( char *D, const QChar &C ) const
+{
+ if( !Codec->canEncode(C) ) // TODO: do we really need the codec?
+ return false;
+ int dummy;
+ char T = Encoder->fromUnicode( C, dummy )[0];
+
+ *D = T;
+ return true;
+}
+
+
+KHEChar KTextCharCodec::decode( char Byte ) const
+{
+ QString S( Decoder->toUnicode(&Byte,1) );
+ return KHEChar(S.at(0));
+}
+
+
+const QString& KTextCharCodec::name() const
+{
+ if( Name.isNull() )
+ Name = QString::fromLatin1( Codec->name() );
+ return Name;
+}
diff --git a/khexedit/lib/codecs/ktextcharcodec.h b/khexedit/lib/codecs/ktextcharcodec.h
new file mode 100644
index 0000000..683919c
--- /dev/null
+++ b/khexedit/lib/codecs/ktextcharcodec.h
@@ -0,0 +1,66 @@
+/***************************************************************************
+ ktextcharcodec.h - description
+ -------------------
+ begin : Sa Nov 27 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KTEXTCHARCODEC_H
+#define KHE_KTEXTCHARCODEC_H
+
+
+#include "kcharcodec.h"
+
+class QTextCodec;
+class QTextDecoder;
+class QTextEncoder;
+
+namespace KHE
+{
+
+// used by all codecs with full char coping, i.e. there are no undefined chars
+class KTextCharCodec : public KCharCodec
+{
+ public:
+ static KTextCharCodec *createCodec( const QString &CodeName );
+ static KTextCharCodec *createCodec( KEncoding C );
+ static KTextCharCodec *createLocalCodec();
+
+ static const QStringList &codecNames();
+
+ protected:
+ KTextCharCodec( QTextCodec *C );
+ public:
+ virtual ~KTextCharCodec();
+
+ public: // KCharCodec API
+ virtual bool encode( char *D, const QChar &C ) const;
+ virtual KHEChar decode( char Byte ) const;
+ virtual const QString& name() const;
+
+
+ protected:
+ QTextCodec *Codec;
+ /** decodes the chars to unicode */
+ QTextDecoder *Decoder;
+ /** encodes the chars from unicode */
+ QTextEncoder *Encoder;
+ /** */
+ mutable QString Name;
+
+ static QStringList CodecNames;
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/controller/Makefile.am b/khexedit/lib/controller/Makefile.am
new file mode 100644
index 0000000..5fd894b
--- /dev/null
+++ b/khexedit/lib/controller/Makefile.am
@@ -0,0 +1,12 @@
+INCLUDES = -I$(srcdir)/.. $(all_includes)
+
+METASOURCES = AUTO
+
+#
+noinst_LTLIBRARIES = libkcontroller.la
+libkcontroller_la_SOURCES = kcontroller.cpp ktabcontroller.cpp knavigator.cpp \
+ keditor.cpp kvalueeditor.cpp kchareditor.cpp
+
+# no public API
+noinst_HEADERS = kcontroller.h ktabcontroller.h knavigator.h \
+ keditor.h kvalueeditor.h kchareditor.h
diff --git a/khexedit/lib/controller/kchareditor.cpp b/khexedit/lib/controller/kchareditor.cpp
new file mode 100644
index 0000000..5b48fc6
--- /dev/null
+++ b/khexedit/lib/controller/kchareditor.cpp
@@ -0,0 +1,58 @@
+/***************************************************************************
+ kchareditor.cpp - description
+ -------------------
+ begin : Sa Dez 4 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// qt specific
+#include <qevent.h>
+// lib specific
+#include "kcharcolumn.h"
+#include "kcharcodec.h"
+#include "khexedit.h"
+#include "kchareditor.h"
+
+
+using namespace KHE;
+
+
+KCharEditor::KCharEditor( KCharColumn *CC, KBufferCursor *BC, KHexEdit *HE, KController *P )
+ : KEditor( BC, HE, P ),
+ CharColumn( CC )
+{
+}
+
+
+bool KCharEditor::handleKeyPress( QKeyEvent *KeyEvent )
+{
+ bool KeyUsed = false;
+ // some input that should be inserted?
+ if( KeyEvent->text().length() > 0
+ && !(KeyEvent->state()&( Qt::ControlButton | Qt::AltButton | Qt::MetaButton )) )
+ {
+ QChar C = KeyEvent->text()[0];
+ if( C.isPrint() )
+ {
+ QByteArray D( 1 );
+ if( CharColumn->codec()->encode(&D[0],C) )
+ {
+ // clearUndoRedoInfo = false;
+ HexEdit->insert( D );
+ KeyUsed = true;
+ }
+ }
+ }
+
+ return KeyUsed ? true : KEditor::handleKeyPress(KeyEvent);
+}
diff --git a/khexedit/lib/controller/kchareditor.h b/khexedit/lib/controller/kchareditor.h
new file mode 100644
index 0000000..74c3d8d
--- /dev/null
+++ b/khexedit/lib/controller/kchareditor.h
@@ -0,0 +1,43 @@
+/***************************************************************************
+ kchareditor.h - description
+ -------------------
+ begin : Sa Dez 4 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KCHAREDITOR_H
+#define KHE_KCHAREDITOR_H
+
+// lib specific
+#include "keditor.h"
+
+namespace KHE
+{
+
+class KCharColumn;
+
+class KCharEditor : public KEditor
+{
+ public:
+ KCharEditor( KCharColumn *CC, KBufferCursor *BC, KHexEdit *HE, KController *P );
+
+ public: // KEditor API
+ virtual bool handleKeyPress( QKeyEvent *KeyEvent );
+
+ protected:
+ KCharColumn *CharColumn;
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/controller/kcontroller.cpp b/khexedit/lib/controller/kcontroller.cpp
new file mode 100644
index 0000000..490da93
--- /dev/null
+++ b/khexedit/lib/controller/kcontroller.cpp
@@ -0,0 +1,34 @@
+/***************************************************************************
+ kcontroller.cpp - description
+ -------------------
+ begin : Sa Dez 4 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+
+// lib specific
+#include "khexedit.h"
+#include "kcontroller.h"
+
+
+using namespace KHE;
+
+KController::KController( KHexEdit* HE, KController *P )
+ : Parent( P ), HexEdit( HE )
+{
+}
+
+bool KController::handleKeyPress( QKeyEvent *KeyEvent )
+{
+ return Parent ? Parent->handleKeyPress( KeyEvent ) : false;
+}
diff --git a/khexedit/lib/controller/kcontroller.h b/khexedit/lib/controller/kcontroller.h
new file mode 100644
index 0000000..daeb0d5
--- /dev/null
+++ b/khexedit/lib/controller/kcontroller.h
@@ -0,0 +1,44 @@
+/***************************************************************************
+ kcontroller.h - description
+ -------------------
+ begin : Sa Dez 4 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KCONTROLLER_H
+#define KHE_KCONTROLLER_H
+
+
+class QKeyEvent;
+
+namespace KHE
+{
+
+class KHexEdit;
+
+class KController
+{
+ protected:
+ KController( KHexEdit *HE, KController *P );
+
+ public: // KController API
+ virtual bool handleKeyPress( QKeyEvent *KeyEvent );
+
+ protected:
+ KController *Parent;
+ KHexEdit *HexEdit;
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/controller/keditor.cpp b/khexedit/lib/controller/keditor.cpp
new file mode 100644
index 0000000..7d4e92f
--- /dev/null
+++ b/khexedit/lib/controller/keditor.cpp
@@ -0,0 +1,197 @@
+/***************************************************************************
+ keditor.cpp - description
+ -------------------
+ begin : Sa Dez 4 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+
+// lib specific
+#include "kdatabuffer.h"
+#include "kbufferranges.h"
+#include "kbufferlayout.h"
+#include "kbuffercursor.h"
+#include "kwordbufferservice.h"
+#include "khexedit.h"
+#include "keditor.h"
+
+
+using namespace KHE;
+
+KEditor::KEditor( KBufferCursor *BC, KHexEdit* HE, KController *P )
+ : KController( HE, P ),
+ BufferCursor( BC )
+{
+}
+
+
+bool KEditor::handleKeyPress( QKeyEvent *KeyEvent )
+{
+ bool clearUndoRedoInfo = true;
+ bool ShiftPressed = KeyEvent->state() & Qt::ShiftButton;
+ bool ControlPressed = KeyEvent->state() & Qt::ControlButton;
+ bool AltPressed = KeyEvent->state() & Qt::AltButton;
+
+ bool KeyUsed = true;
+ // we only care for cursor keys and the like, won't hardcode any other keys
+ // we also don't check whether the commands are allowed
+ // as the commands are also available as API so the check has to be done
+ // in each command anyway
+ switch( KeyEvent->key() )
+ {
+ case Qt::Key_Delete:
+ if( ShiftPressed )
+ HexEdit->cut();
+ else if( HexEdit->BufferRanges->hasSelection() )
+ HexEdit->removeSelectedData();
+ else
+ {
+ doEditAction( ControlPressed ? WordDelete : CharDelete );
+ clearUndoRedoInfo = false;
+ }
+ break;
+
+ case Qt::Key_Insert:
+ if( ShiftPressed )
+ HexEdit->paste();
+ else if( ControlPressed )
+ HexEdit->copy();
+ else
+ HexEdit->setOverwriteMode( !HexEdit->OverWrite );
+ break;
+
+ case Qt::Key_Backspace:
+ if( AltPressed )
+ {
+ if( ControlPressed )
+ break;
+ else if( ShiftPressed )
+ {
+// HexEdit->redo();
+ break;
+ }
+ else
+ {
+// HexEdit->undo();
+ break;
+ }
+ }
+ else if( HexEdit->BufferRanges->hasSelection() )
+ {
+ HexEdit->removeSelectedData();
+ break;
+ }
+
+ doEditAction( ControlPressed ? WordBackspace : CharBackspace );
+ clearUndoRedoInfo = false;
+ break;
+ case Qt::Key_F16: // "Copy" key on Sun keyboards
+ HexEdit->copy();
+ break;
+ case Qt::Key_F18: // "Paste" key on Sun keyboards
+ HexEdit->paste();
+ break;
+ case Qt::Key_F20: // "Cut" key on Sun keyboards
+ HexEdit->cut();
+ break;
+
+ default:
+ KeyUsed = false;
+ }
+
+// if( clearUndoRedoInfo )
+// clearUndoRedo();
+// changeIntervalTimer->start( 100, true );
+
+ return KeyUsed ? true : KController::handleKeyPress(KeyEvent);
+}
+
+
+
+void KEditor::doEditAction( KEditAction Action )
+{
+ KSection ChangedRange;
+
+ HexEdit->pauseCursor( true );
+
+ switch( Action )
+ {
+ case CharDelete:
+ if( !HexEdit->OverWrite )
+ {
+ int Index = BufferCursor->realIndex();
+ if( Index < HexEdit->BufferLayout->length() )
+ {
+ ChangedRange = HexEdit->removeData( KSection(Index,1,false) );
+ if( Index == HexEdit->BufferLayout->length() )
+ BufferCursor->gotoEnd();
+ }
+ }
+ break;
+
+ case WordDelete: // kills data until the start of the next word
+ if( !HexEdit->OverWrite )
+ {
+ int Index = BufferCursor->realIndex();
+ if( Index < HexEdit->BufferLayout->length() )
+ {
+ KWordBufferService WBS( HexEdit->DataBuffer, HexEdit->Codec );
+ int End = WBS.indexOfBeforeNextWordStart( Index );
+ ChangedRange = HexEdit->removeData( KSection(Index,End) );
+ if( Index == HexEdit->BufferLayout->length() )
+ BufferCursor->gotoEnd();
+ }
+ }
+ break;
+
+ case CharBackspace:
+ if( HexEdit->OverWrite )
+ BufferCursor->gotoPreviousByte();
+ else
+ {
+ int DeleteIndex = BufferCursor->realIndex() - 1;
+ if( DeleteIndex >= 0 )
+ {
+ ChangedRange = HexEdit->removeData( KSection(DeleteIndex,1,false) );
+ if( DeleteIndex == HexEdit->BufferLayout->length() )
+ BufferCursor->gotoEnd();
+ else
+ BufferCursor->gotoPreviousByte();
+ }
+ }
+ break;
+ case WordBackspace:
+ {
+ int LeftIndex = BufferCursor->realIndex() - 1;
+ if( LeftIndex >= 0 )
+ {
+ KWordBufferService WBS( HexEdit->DataBuffer, HexEdit->Codec );
+ int WordStart = WBS.indexOfPreviousWordStart( LeftIndex );
+ if( !HexEdit->OverWrite )
+ ChangedRange = HexEdit->removeData( KSection(WordStart,LeftIndex) );
+ if( WordStart == HexEdit->BufferLayout->length() )
+ BufferCursor->gotoEnd();
+ else
+ BufferCursor->gotoIndex(WordStart);
+ }
+ }
+ }
+
+ HexEdit->repaintChanged();
+ HexEdit->ensureCursorVisible();
+
+ HexEdit->unpauseCursor();
+
+ emit HexEdit->cursorPositionChanged( BufferCursor->index() );
+ if( ChangedRange.isValid() ) emit HexEdit->bufferChanged( ChangedRange.start(), ChangedRange.end() );
+}
diff --git a/khexedit/lib/controller/keditor.h b/khexedit/lib/controller/keditor.h
new file mode 100644
index 0000000..dc2b0fd
--- /dev/null
+++ b/khexedit/lib/controller/keditor.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ keditor.h - description
+ -------------------
+ begin : Sa Dez 4 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KEDITOR_H
+#define KHE_KEDITOR_H
+
+
+// lib specific
+#include "kcontroller.h"
+
+
+namespace KHE
+{
+
+class KBufferCursor;
+
+class KEditor : public KController
+{
+ protected:
+ enum KEditAction { CharDelete, WordDelete, CharBackspace, WordBackspace };
+
+ protected:
+ KEditor( KBufferCursor *BC, KHexEdit *HE, KController *P );
+
+ public: // API
+ virtual bool handleKeyPress( QKeyEvent *KeyEvent );
+
+ protected:
+ /** executes keyboard Action \a Action. This is normally called by a key event handler. */
+ void doEditAction( KEditAction Action );
+
+ protected:
+ KBufferCursor *BufferCursor;
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/controller/knavigator.cpp b/khexedit/lib/controller/knavigator.cpp
new file mode 100644
index 0000000..51c8048
--- /dev/null
+++ b/khexedit/lib/controller/knavigator.cpp
@@ -0,0 +1,142 @@
+/***************************************************************************
+ knavigator.cpp - description
+ -------------------
+ begin : Sa Dez 4 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+
+// qt specific
+#include <qevent.h>
+// lib specific
+#include "kdatabuffer.h"
+#include "kbufferranges.h"
+#include "kbuffercursor.h"
+#include "kwordbufferservice.h"
+#include "khexedit.h"
+#include "knavigator.h"
+
+
+using namespace KHE;
+
+KNavigator::KNavigator( KHexEdit* HE, KController *P )
+ : KController( HE, P )
+{
+}
+
+bool KNavigator::handleKeyPress( QKeyEvent *KeyEvent )
+{
+ bool KeyUsed = true;
+
+ //bool clearUndoRedoInfo = true;
+ bool ShiftPressed = KeyEvent->state() & Qt::ShiftButton;
+ bool ControlPressed = KeyEvent->state() & Qt::ControlButton;
+ //bool AltPressed = KeyEvent->state() & AltButton;
+
+ // we only care for cursor keys and the like, won't hardcode any other keys
+ // we also don't check whether the commands are allowed
+ // as the commands are also available as API so the check has to be done
+ // in each command anyway
+ switch( KeyEvent->key() )
+ {
+ case Qt::Key_Left:
+ moveCursor( ControlPressed ? MoveWordBackward : MoveBackward, ShiftPressed );
+ break;
+ case Qt::Key_Right:
+ moveCursor( ControlPressed ? MoveWordForward : MoveForward, ShiftPressed );
+ break;
+ case Qt::Key_Up:
+ moveCursor( ControlPressed ? MovePgUp : MoveUp, ShiftPressed );
+ break;
+ case Qt::Key_Down:
+ moveCursor( ControlPressed ? MovePgDown : MoveDown, ShiftPressed );
+ break;
+ case Qt::Key_Home:
+ moveCursor( ControlPressed ? MoveHome : MoveLineStart, ShiftPressed );
+ break;
+ case Qt::Key_End:
+ moveCursor( ControlPressed ? MoveEnd : MoveLineEnd, ShiftPressed );
+ break;
+ case Qt::Key_Prior:
+ moveCursor( MovePgUp, ShiftPressed );
+ break;
+ case Qt::Key_Next:
+ moveCursor( MovePgDown, ShiftPressed );
+ break;
+
+ default:
+ KeyUsed = false;
+ }
+
+ return KeyUsed ? true : KController::handleKeyPress(KeyEvent);
+}
+
+
+void KNavigator::moveCursor( KMoveAction Action, bool Select )
+{
+ HexEdit->pauseCursor( true );
+
+ KBufferCursor *BufferCursor = HexEdit->BufferCursor;
+ KBufferRanges *BufferRanges = HexEdit->BufferRanges;
+
+ if( Select )
+ {
+ if( !BufferRanges->selectionStarted() )
+ BufferRanges->setSelectionStart( BufferCursor->realIndex() );
+ }
+ else
+ BufferRanges->removeSelection();
+
+ HexEdit->resetInputContext();
+ switch( Action )
+ {
+ case MoveBackward: BufferCursor->gotoPreviousByte(); break;
+ case MoveWordBackward: {
+ KWordBufferService WBS( HexEdit->DataBuffer, HexEdit->Codec );
+ int NewIndex = WBS.indexOfPreviousWordStart( BufferCursor->realIndex() );
+ BufferCursor->gotoIndex( NewIndex );
+ }
+ break;
+ case MoveForward: BufferCursor->gotoNextByte(); break;
+ case MoveWordForward: {
+ KWordBufferService WBS( HexEdit->DataBuffer, HexEdit->Codec );
+ int NewIndex = WBS.indexOfNextWordStart( BufferCursor->realIndex() );
+ BufferCursor->gotoCIndex( NewIndex );
+ }
+ break;
+ case MoveUp: BufferCursor->gotoUp(); break;
+ case MovePgUp: BufferCursor->gotoPageUp(); break;
+ case MoveDown: BufferCursor->gotoDown(); break;
+ case MovePgDown: BufferCursor->gotoPageDown(); break;
+ case MoveLineStart: BufferCursor->gotoLineStart(); break;
+ case MoveHome: BufferCursor->gotoStart(); break;
+ case MoveLineEnd: BufferCursor->gotoLineEnd(); break;
+ case MoveEnd: BufferCursor->gotoEnd(); break;
+ }
+
+ if( Select )
+ BufferRanges->setSelectionEnd( BufferCursor->realIndex() );
+
+ HexEdit->repaintChanged();
+ HexEdit->ensureCursorVisible();
+
+ HexEdit->unpauseCursor();
+
+ if( BufferRanges->isModified() )
+ {
+ if( !HexEdit->isOverwriteMode() ) emit HexEdit->cutAvailable( BufferRanges->hasSelection() );
+ emit HexEdit->copyAvailable( BufferRanges->hasSelection() );
+ KSection Selection = BufferRanges->selection();
+ emit HexEdit->selectionChanged( Selection.start(), Selection.end() );
+ }
+}
diff --git a/khexedit/lib/controller/knavigator.h b/khexedit/lib/controller/knavigator.h
new file mode 100644
index 0000000..4615419
--- /dev/null
+++ b/khexedit/lib/controller/knavigator.h
@@ -0,0 +1,46 @@
+/***************************************************************************
+ knavigator.h - description
+ -------------------
+ begin : Sa Dez 4 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KNAVIGATOR_H
+#define KHE_KNAVIGATOR_H
+
+// lib specific
+#include "kcontroller.h"
+
+namespace KHE
+{
+
+class KNavigator : public KController
+{
+ protected:
+ enum KMoveAction { MoveBackward, MoveWordBackward, MoveForward, MoveWordForward,
+ MoveUp, MovePgUp, MoveDown, MovePgDown,
+ MoveLineStart, MoveHome, MoveLineEnd, MoveEnd };
+ public:
+ KNavigator( KHexEdit *HE, KController *P );
+
+ public: // KEditor API
+ virtual bool handleKeyPress( QKeyEvent *KeyEvent );
+
+ protected:
+ /** moves the cursor according to the action, handles all drawing */
+ void moveCursor( KMoveAction Action, bool Select );
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/controller/ktabcontroller.cpp b/khexedit/lib/controller/ktabcontroller.cpp
new file mode 100644
index 0000000..76c3051
--- /dev/null
+++ b/khexedit/lib/controller/ktabcontroller.cpp
@@ -0,0 +1,70 @@
+/***************************************************************************
+ ktabcontroller.cpp - description
+ -------------------
+ begin : So Dez 5 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// qt specific
+#include <qevent.h>
+// lib specific
+#include "kvaluecolumn.h"
+#include "kcharcolumn.h"
+#include "khexedit.h"
+#include "ktabcontroller.h"
+
+
+using namespace KHE;
+
+KTabController::KTabController( KHexEdit* HE, KController *P )
+ : KController( HE, P ),
+ TabChangesFocus( false )
+{
+}
+
+
+bool KTabController::handleKeyPress( QKeyEvent *KeyEvent )
+{
+ bool KeyUsed = false;
+
+ bool ShiftPressed = KeyEvent->state() & Qt::ShiftButton;
+
+ if( KeyEvent->key() == Qt::Key_Tab )
+ {
+ // are we in the char column?
+ if( HexEdit->cursorColumn() == KHexEdit::CharColumnId )
+ {
+ // in last column we care about tab changes focus
+ if( HexEdit->ValueColumn->isVisible() && (!TabChangesFocus || ShiftPressed) )
+ {
+ HexEdit->setCursorColumn( KHexEdit::ValueColumnId );
+ KeyUsed = true;
+ }
+ }
+ // value column then
+ else
+ {
+ if( HexEdit->CharColumn->isVisible() )
+ {
+ // in last column we care about tab changes focus
+ if( HexEdit->CharColumn->isVisible() && (!TabChangesFocus || !ShiftPressed) )
+ {
+ HexEdit->setCursorColumn( KHexEdit::CharColumnId );
+ KeyUsed = true;
+ }
+ }
+ }
+ }
+
+ return KeyUsed ? true : KController::handleKeyPress(KeyEvent);
+}
diff --git a/khexedit/lib/controller/ktabcontroller.h b/khexedit/lib/controller/ktabcontroller.h
new file mode 100644
index 0000000..e1898b4
--- /dev/null
+++ b/khexedit/lib/controller/ktabcontroller.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ ktabcontroller.h - description
+ -------------------
+ begin : So Dez 5 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KTABCONTROLLER_H
+#define KHE_KTABCONTROLLER_H
+
+
+// lib specific
+#include "kcontroller.h"
+
+
+namespace KHE
+{
+
+class KTabController : public KController
+{
+ public:
+ KTabController( KHexEdit *HE, KController *P );
+
+ public: // API
+ virtual bool handleKeyPress( QKeyEvent *KeyEvent );
+
+ public:
+ bool tabChangesFocus() const;
+ void setTabChangesFocus( bool TCF );
+
+ protected:
+ /** flag if tab key should be ignored */
+ bool TabChangesFocus:1;
+};
+
+
+inline bool KTabController::tabChangesFocus() const { return TabChangesFocus; }
+inline void KTabController::setTabChangesFocus( bool TCF ) { TabChangesFocus = TCF; }
+
+}
+
+#endif
diff --git a/khexedit/lib/controller/kvalueeditor.cpp b/khexedit/lib/controller/kvalueeditor.cpp
new file mode 100644
index 0000000..ebfb589
--- /dev/null
+++ b/khexedit/lib/controller/kvalueeditor.cpp
@@ -0,0 +1,226 @@
+/***************************************************************************
+ kvalueeditor.cpp - description
+ -------------------
+ begin : Sa Dez 4 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// qt specific
+#include <qevent.h>
+// lib specific
+#include "kvaluecolumn.h"
+#include "kbufferranges.h"
+#include "kbuffercursor.h"
+#include "khexedit.h"
+#include "kvalueeditor.h"
+
+
+using namespace KHE;
+
+KValueEditor::KValueEditor( KValueColumn *VC, KBufferCursor *BC, KHexEdit* HE, KController *P )
+ : KEditor( BC, HE, P ),
+ ValueColumn( VC ),
+ InEditMode( false ),
+ EditModeByInsert( false )
+{
+}
+
+
+bool KValueEditor::handleKeyPress( QKeyEvent *KeyEvent )
+{
+ bool KeyUsed = true;
+
+ // TODO: for now we don't touch it if there are selections
+ if( !HexEdit->BufferRanges->hasSelection() )
+ {
+ //
+ switch( KeyEvent->key() )
+ {
+ case Qt::Key_Plus:
+ doValueEditAction( IncValue );
+ break;
+ case Qt::Key_Minus:
+ doValueEditAction( DecValue );
+ break;
+ case Qt::Key_Space:
+ if( !InEditMode )
+ {
+ KeyUsed = false;
+ break;
+ }
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ doValueEditAction( InEditMode?LeaveValue:EnterValue );
+ break;
+ case Qt::Key_Escape:
+ if( InEditMode )
+ doValueEditAction( CancelValue );
+ else
+ KeyUsed = false;
+ break;
+ case Qt::Key_Backspace:
+ if( InEditMode )
+ doValueEditAction( ValueBackspace );
+ else
+ KeyUsed = false;
+ break;
+ default:
+ // is plain char?
+ if( KeyEvent->text().length() > 0
+ && ( !(KeyEvent->state()&( Qt::ControlButton | Qt::AltButton | Qt::MetaButton )) ) )
+ {
+ QChar C = KeyEvent->text()[0];
+ // no usable char?
+ if( !C.isLetterOrNumber() )
+ {
+ KeyUsed = false;
+ break;
+ }
+ int Input = C.latin1();
+
+ if( InEditMode )
+ doValueEditAction( ValueAppend, Input );
+ else
+ {
+ unsigned char InputValue = 0;
+ const KByteCodec *ByteCodec = ValueColumn->byteCodec();
+ // valid digit?
+ if( ByteCodec->appendDigit(&InputValue,Input) )
+ {
+ if( HexEdit->OverWrite )
+ doValueEditAction( ValueEdit, InputValue );
+ else
+ {
+ int Index = BufferCursor->realIndex();
+ if( HexEdit->DataBuffer->insert(Index,(char*)&InputValue,1) > 0 )
+ {
+ HexEdit->pauseCursor();
+ HexEdit->updateLength();
+
+ InEditMode = true;
+ EditModeByInsert = true;
+ OldValue = EditValue = InputValue;
+ ByteCodec->encode( ByteBuffer, 0, EditValue );
+
+ BufferCursor->gotoRealIndex();
+ KSection ChangedRange( Index,HexEdit->DataBuffer->size()-1 );
+ HexEdit->BufferRanges->addChangedRange( ChangedRange );
+ HexEdit->repaintChanged();
+ HexEdit->ensureCursorVisible();
+ HexEdit->unpauseCursor();
+ HexEdit->updateCursor();
+ emit HexEdit->bufferChanged( ChangedRange.start(), ChangedRange.end() );
+ }
+ }
+ }
+ }
+ }
+ else
+ KeyUsed = false;
+ }
+ }
+ else
+ KeyUsed = false;
+
+ return KeyUsed ? true : KEditor::handleKeyPress(KeyEvent);
+}
+
+
+void KValueEditor::doValueEditAction( KValueEditAction Action, int Input )
+{
+ // we are not yet in edit mode?
+ if( !InEditMode )
+ {
+ int ValidIndex = BufferCursor->validIndex();
+ // no valid cursor position?
+ if( ValidIndex == -1 || (!HexEdit->OverWrite && Input == -1) || BufferCursor->isBehind() )
+ return;
+
+ InEditMode = true;
+ EditModeByInsert = false; // default, to be overwritten if so
+
+ // save old value
+ OldValue = EditValue = (unsigned char)HexEdit->DataBuffer->datum(ValidIndex);
+ }
+
+ const KByteCodec *ByteCodec = ValueColumn->byteCodec();
+ //
+ unsigned char NewValue = EditValue;
+ bool StayInEditMode = true;
+ bool MoveToNext = false;
+
+ switch( Action )
+ {
+ case ValueEdit:
+ NewValue = Input;
+ EditValue = NewValue^255; // force update
+ EditModeByInsert = true;
+ break;
+ case ValueBackspace:
+ if( NewValue > 0 )
+ ByteCodec->removeLastDigit( &NewValue );
+ break;
+ case EnterValue:
+ EditValue ^= 255; // force update
+ break;
+ case IncValue:
+ if( NewValue < 255 )
+ ++NewValue;
+ break;
+ case DecValue:
+ if( NewValue > 0 )
+ --NewValue;
+ break;
+ case ValueAppend:
+ if( ByteCodec->appendDigit(&NewValue,Input) )
+ if( EditModeByInsert && NewValue >= ByteCodec->digitsFilledLimit() )
+ {
+ StayInEditMode = false;
+ MoveToNext = true;
+ }
+ break;
+ case LeaveValue:
+ StayInEditMode = false;
+ MoveToNext = EditModeByInsert;
+ break;
+ case CancelValue:
+ NewValue = OldValue;
+ StayInEditMode = false;
+ break;
+ }
+
+ bool Changed = (NewValue != EditValue);
+ int Index = BufferCursor->index();
+ if( Changed )
+ {
+ // sync value
+ EditValue = NewValue;
+ ByteCodec->encode( ByteBuffer, 0, EditValue );
+
+ HexEdit->DataBuffer->replace( Index, 1, (char*)&EditValue, 1 );
+ }
+
+ HexEdit->updateCursor();
+
+ if( !StayInEditMode )
+ {
+ HexEdit->pauseCursor();
+ InEditMode = false;
+ if( MoveToNext )
+ BufferCursor->gotoNextByte();
+ HexEdit->unpauseCursor();
+ }
+
+ if( Changed )
+ if( Action != EnterValue ) emit HexEdit->bufferChanged( Index, Index );
+}
diff --git a/khexedit/lib/controller/kvalueeditor.h b/khexedit/lib/controller/kvalueeditor.h
new file mode 100644
index 0000000..496bcde
--- /dev/null
+++ b/khexedit/lib/controller/kvalueeditor.h
@@ -0,0 +1,75 @@
+/***************************************************************************
+ kvalueeditor.h - description
+ -------------------
+ begin : Sa Dez 4 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KVALUEEDITOR_H
+#define KHE_KVALUEEDITOR_H
+
+
+// lib specific
+#include "keditor.h"
+
+namespace KHE
+{
+
+class KValueColumn;
+
+
+class KValueEditor: public KEditor
+{
+ protected:
+ enum KValueEditAction
+ { EnterValue, IncValue, DecValue, ValueAppend, ValueEdit, LeaveValue, CancelValue, ValueBackspace };
+
+ public:
+ KValueEditor( KValueColumn *VC, KBufferCursor *BC, KHexEdit *HE, KController *P );
+ virtual ~KValueEditor();
+
+ public: // KEditor API
+ virtual bool handleKeyPress( QKeyEvent *KeyEvent );
+
+ public:
+ void reset();
+
+ public:
+ bool isInEditMode() const;
+
+ protected:
+ /** executes keyboard Action \a Action. This is normally called by a key event handler. */
+ void doValueEditAction( KValueEditAction Action, int Input = -1 );
+
+ public://protected:
+ KValueColumn *ValueColumn;
+ /** flag whether we are in editing mode */
+ bool InEditMode:1;
+ /** flag whether byte edit mode was reached by inserting */
+ bool EditModeByInsert:1;
+ /** */
+ unsigned char EditValue;
+ /** stores the old byte value */
+ unsigned char OldValue;
+ /** buffer with the */
+ QString ByteBuffer;
+};
+
+inline KValueEditor::~KValueEditor() {}
+
+inline bool KValueEditor::isInEditMode() const { return InEditMode; }
+inline void KValueEditor::reset() { InEditMode = false; }
+
+}
+
+#endif
diff --git a/khexedit/lib/helper.h b/khexedit/lib/helper.h
new file mode 100644
index 0000000..600ac5b
--- /dev/null
+++ b/khexedit/lib/helper.h
@@ -0,0 +1,31 @@
+/***************************************************************************
+ helper.h - description
+ -------------------
+ begin : Fri Oct 03 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+#ifndef KHEXEDIT_HELPER
+#define KHEXEDIT_HELPER
+
+// qt specific
+#include <qcolor.h>
+// lib specific
+#include <khechar.h>
+
+// temporary solution until syntax highlighting is implemented
+static inline QColor colorForChar( const KHE::KHEChar Byte )
+{
+ return Byte.isUndefined() ? Qt::yellow : Byte.isPunct() ? Qt::red : Byte.isPrint() ? Qt::black : Qt::blue;
+}
+
+#endif
diff --git a/khexedit/lib/kadds.h b/khexedit/lib/kadds.h
new file mode 100644
index 0000000..77c86f5
--- /dev/null
+++ b/khexedit/lib/kadds.h
@@ -0,0 +1,36 @@
+/***************************************************************************
+ kadds.h - description
+ -------------------
+ begin : Die Mai 20 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KADDS_H
+#define KHE_KADDS_H
+
+namespace KHE
+{
+// some possibly usefull aditions to KDE
+
+// these are to emphasize that measuring unit is pixel and which direction
+typedef int KPixelX;
+typedef int KPixelY;
+
+class KSection;
+
+typedef KSection KPixelXs;
+typedef KSection KPixelYs;
+
+}
+
+#endif
diff --git a/khexedit/lib/kbigbuffer.cpp b/khexedit/lib/kbigbuffer.cpp
new file mode 100644
index 0000000..8505ef7
--- /dev/null
+++ b/khexedit/lib/kbigbuffer.cpp
@@ -0,0 +1,216 @@
+/***************************************************************************
+ kbigbuffer.cpp - description
+ -------------------
+ begin : Mit Jun 02 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// c specific
+#include <stdlib.h>
+// lib specific
+#include "kbigbuffer.h"
+
+using namespace KHE;
+
+KBigBuffer::KBigBuffer( int NP, int PS )
+ : NoOfUsedPages( NP ),
+ NoOfFreePages( NP ),
+ PageSize( PS ),
+ FirstPage( -1 ),
+ LastPage( -1 ),
+ Size( 0 )
+{
+ IsOpen = false;
+
+// if( !filename.empty() )
+// open(filename);
+}
+
+
+KBigBuffer::~KBigBuffer()
+{
+ if( File.isOpen() )
+ close();
+}
+
+
+
+bool KBigBuffer::prepareRange( KSection /*Range*/ ) const
+{
+ return true;
+}
+
+const char *KBigBuffer::dataSet( KSection /*Section*/ ) const
+{
+ return 0;
+}
+
+
+char KBigBuffer::datum( unsigned int DatumOffset ) const
+{
+// std::cout << "reading datum " << DatumOffset << std::endl;
+ int OffsetInPage = DatumOffset - OffsetOfActualPage;
+ // there shouldn't be any need to check l
+ if( OffsetInPage >= 0 && OffsetInPage < (int)PageSize )
+ return ActualPage[OffsetInPage];
+
+ // load the page
+ unsigned int PageIndex = DatumOffset / PageSize;
+ ensurePageLoaded( PageIndex );
+ return ActualPage[DatumOffset-OffsetOfActualPage];
+}
+
+
+
+
+int KBigBuffer::insert( int /*Pos*/, const char*, int /*Length*/ )
+{
+ return 0;
+}
+
+int KBigBuffer::remove( KSection /*Section*/ )
+{
+ return 0;
+}
+
+unsigned int KBigBuffer::replace( KSection /*Section*/, const char*, unsigned int /*Length*/ )
+{
+ return 0;
+}
+
+int KBigBuffer::fill( char /*FillChar*/, int /*Length*/, unsigned int /*Pos*/ )
+{
+ return 0;
+}
+
+
+int KBigBuffer::move( int /*DestPos*/, KSection /*SourceSection*/ ) { return 0; }
+//int KBigBuffer::find( const char*, int /*Length*/, int /*Pos*/ ) const { return 0; }
+int KBigBuffer::find( const char*/*KeyData*/, int /*Length*/, KSection /*Section*/ ) const { return 0; }
+
+int KBigBuffer::rfind( const char*, int /*Length*/, int /*Pos*/ ) const { return 0; }
+
+
+
+bool KBigBuffer::open( const QString& FileName )
+{
+ // clear old data
+ if( isOpen() && !close() ) // only occurs if close somehow fails.
+ return false;
+
+ File.setName( FileName );
+ if( !File.open(IO_ReadOnly|IO_Raw) )
+ return false;
+
+// std::cout << "loading file " << FileName << std::endl;
+
+ int FileSize = File.size();
+ Size = FileSize;
+
+ // calculate necessary number of pages
+ int NoOfPages = FileSize/PageSize + 1;
+
+ // initialize Page pointers
+ Data.resize( NoOfPages );
+ for( KPageOfChar::iterator D=Data.begin(); D!=Data.end(); ++D )
+ *D = 0;
+
+ FirstPage = LastPage = 0;
+
+ return ensurePageLoaded( 0 );
+}
+
+
+bool KBigBuffer::close()
+{
+ if( !isOpen() )
+ return false;
+
+ File.close();
+
+ if( File.status() == IO_UnspecifiedError )
+ return false;
+
+// std::cout << "closing file " << std::endl;
+
+ // free pages
+ for( KPageOfChar::iterator D=Data.begin(); D!=Data.end(); ++D )
+ delete [] *D;
+
+ FirstPage = LastPage = -1;
+ NoOfFreePages = NoOfUsedPages;
+
+ return true;
+}
+
+
+bool KBigBuffer::ensurePageLoaded( unsigned int PageIndex ) const
+{
+ if( !isOpen() )
+ return false;
+ // page loaded?
+ if( Data[PageIndex] != 0 )
+ {
+ ActualPage = Data[PageIndex];
+ OffsetOfActualPage = PageIndex * PageSize;
+ return true;
+ }
+
+ // no page available?
+ if( NoOfFreePages < 1 )
+ {
+ // free the page which is the furthest away from the page we are loading
+ if( abs(FirstPage-PageIndex) > abs(LastPage-PageIndex) )
+ while( !freePage(FirstPage++) );
+ else
+ while( !freePage(LastPage--) );
+ }
+
+// std::cout << "loading page " << PageIndex << std::endl;
+ // create Page
+ Data[PageIndex] = new char[PageSize];
+ --NoOfFreePages;
+
+ // jump to position and read the page's data in
+ bool Success = File.at( (unsigned long)(PageIndex*PageSize) );
+ if( Success )
+ Success = File.readBlock( Data[PageIndex], PageSize ) > 0;
+
+ if( Success )
+ {
+ // correct bounds
+ if( (int)PageIndex < FirstPage )
+ FirstPage = PageIndex;
+
+ if( (int)PageIndex > LastPage )
+ LastPage = PageIndex;
+
+ ActualPage = Data[PageIndex];
+ OffsetOfActualPage = PageIndex * PageSize;
+ }
+
+ return Success;
+}
+
+
+bool KBigBuffer::freePage( unsigned int PageIndex ) const
+{
+ // check range and if is loaded at all
+ if( (unsigned int)PageIndex >= Data.size() || !Data[PageIndex] )
+ return false;
+// std::cout << "freeing page " << PageIndex << std::endl;
+ delete [] Data[PageIndex];
+ Data[PageIndex] = 0;
+ ++NoOfFreePages;
+ return true;
+}
diff --git a/khexedit/lib/kbigbuffer.h b/khexedit/lib/kbigbuffer.h
new file mode 100644
index 0000000..138e64b
--- /dev/null
+++ b/khexedit/lib/kbigbuffer.h
@@ -0,0 +1,119 @@
+/***************************************************************************
+ kbigbuffer.h - description
+ -------------------
+ begin : Mit Jun 02 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KBIGBUFFER_H
+#define KHE_KBIGBUFFER_H
+
+// qt specific
+#include <qvaluevector.h>
+#include <qfile.h>
+// lib specific
+#include "kdatabuffer.h"
+#include "khexedit_export.h"
+
+namespace KHE {
+
+/** base class for all Data buffers that are used to display
+ * TODO: think about a way to inform KHexEdit that there has been
+ * a change in the buffer outside. what kind of changes are possible?
+ *@author Friedrich W. H. Kossebau
+ */
+
+class KHEXEDIT_EXPORT KBigBuffer : public KDataBuffer
+{
+ typedef QValueVector<char *> KPageOfChar;
+
+ public:
+ /** default is only 50*4k = 200k memory image */
+ KBigBuffer( int NP = 50, int PS = 4096 );
+ virtual ~KBigBuffer();
+
+ public: // KDataBuffer API
+ virtual bool prepareRange( KSection Range ) const;
+ virtual const char *dataSet( KSection S ) const;
+ virtual char datum( unsigned int Offset ) const;
+ virtual int size() const;
+ virtual bool isReadOnly() const;
+ virtual bool isModified() const;
+
+ virtual int insert( int Pos, const char*, int Length );
+ virtual int remove( KSection S );
+ virtual unsigned int replace( KSection S, const char*, unsigned int InputLength );
+ virtual int move( int DestPos, KSection SourceSection );
+ virtual int fill( char FillChar, int Length = -1, unsigned int Pos = 0 );
+ virtual void setDatum( unsigned int Offset, const char Char );
+
+ virtual void setModified( bool M = true );
+
+ //virtual int find( const char*, int Length, int Pos = 0 ) const;
+ virtual int find( const char*KeyData, int Length, KSection Section ) const;
+ virtual int rfind( const char*, int Length, int Pos = -1 ) const;
+
+/* virtual int find( const QString &expr, bool cs, bool wo, bool forward = true, int *index = 0 ); */
+
+ public:
+ void setReadOnly( bool RO = true );
+ bool isOpen() const;
+ bool open (const QString& filename );
+ bool close();
+
+ protected:
+ bool ensurePageLoaded( unsigned int PageIndex ) const;
+ bool freePage( unsigned int PageIndex ) const;
+
+
+ protected:
+ /** */
+ mutable QFile File;
+ /** */
+ bool ReadOnly:1;
+ bool IsOpen:1;
+ bool AtEOF:1;
+ /** maximum number of pages which could be currently loaded */
+ unsigned int NoOfUsedPages;
+ /** number of actually not used pages (in terms of NoOfUsedPages) */
+ mutable int NoOfFreePages;
+ /** number of bytes in a page */
+ unsigned int PageSize;
+ /** first currently loaded page */
+ mutable int FirstPage;
+ /** last currently loaded page */
+ mutable int LastPage;
+ /** */
+ mutable KPageOfChar Data;
+ /** */
+ unsigned int Size;
+
+ /** current offset */
+ mutable unsigned int OffsetOfActualPage;
+ /** points to the actual page */
+ mutable char* ActualPage;
+};
+
+inline int KBigBuffer::size() const { return Size; }
+inline bool KBigBuffer::isReadOnly() const { return ReadOnly; }
+inline bool KBigBuffer::isModified() const { return false; }
+inline void KBigBuffer::setReadOnly( bool RO ) { ReadOnly = RO; }
+inline void KBigBuffer::setModified( bool ) {}
+
+inline void KBigBuffer::setDatum( unsigned int, const char ) {}
+
+inline bool KBigBuffer::isOpen() const { return File.isOpen(); }
+
+}
+
+#endif
diff --git a/khexedit/lib/kbordercoltextexport.cpp b/khexedit/lib/kbordercoltextexport.cpp
new file mode 100644
index 0000000..d46490f
--- /dev/null
+++ b/khexedit/lib/kbordercoltextexport.cpp
@@ -0,0 +1,47 @@
+/***************************************************************************
+ kbordercoltextexport.cpp - description
+ -------------------
+ begin : Sam Aug 30 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// qt specific
+#include <qstring.h>
+// lib specific
+#include "kbordercoltextexport.h"
+
+
+using namespace KHE;
+
+static const uint BorderColumnTEWidth = 3;
+
+
+int KBorderColTextExport::charsPerLine() const
+{
+ return BorderColumnTEWidth;
+}
+
+void KBorderColTextExport::printFirstLine( QString &T, int /*Line*/ ) const
+{
+ print( T );
+}
+
+void KBorderColTextExport::printNextLine( QString &T ) const
+{
+ print( T );
+}
+
+void KBorderColTextExport::print( QString &T ) const
+{
+ T.append( " | " );
+}
diff --git a/khexedit/lib/kbordercoltextexport.h b/khexedit/lib/kbordercoltextexport.h
new file mode 100644
index 0000000..4103f0b
--- /dev/null
+++ b/khexedit/lib/kbordercoltextexport.h
@@ -0,0 +1,40 @@
+/***************************************************************************
+ kbordercoltextexport.h - description
+ -------------------
+ begin : Sam Aug 30 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KBORDERCOLTEXTEXPORT_H
+#define KHE_KBORDERCOLTEXTEXPORT_H
+
+#include "kcoltextexport.h"
+
+namespace KHE
+{
+
+class KBorderColTextExport : public KColTextExport
+{
+ public: // API
+ void printFirstLine( QString &T, int Line ) const;
+ void printNextLine( QString &T) const;
+ /** tells how much chars per line are needed */
+ int charsPerLine() const ;
+
+ protected:
+ void print( QString &T ) const;
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/kbordercolumn.cpp b/khexedit/lib/kbordercolumn.cpp
new file mode 100644
index 0000000..c590246
--- /dev/null
+++ b/khexedit/lib/kbordercolumn.cpp
@@ -0,0 +1,82 @@
+/***************************************************************************
+ kbordercolumn.cpp - description
+ -------------------
+ begin : Mit Mai 21 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// qt specific
+#include <qpainter.h>
+#include <qstyle.h>
+// lib specific
+#include "kcolumnsview.h"
+#include "kbordercolumn.h"
+
+
+using namespace KHE;
+
+static const KPixelX DefaultWidth = 9;
+static const KPixelX LineX = DefaultWidth / 2;
+
+
+KBorderColumn::KBorderColumn( KColumnsView *V, bool M )
+ : KColumn( V ),
+ Middle( M )
+{
+ setWidth( M?DefaultWidth:LineX-1 );
+}
+
+KBorderColumn::~KBorderColumn()
+{
+}
+
+
+void KBorderColumn::paintLine( QPainter *P )
+{
+ if( LineHeight > 0 )
+ {
+ KColumn::paintBlankLine( P );
+
+ if( Middle )
+ {
+ int GridColor = View->style().styleHint( QStyle::SH_Table_GridLineColor, View );
+ P->setPen( GridColor != -1 ? (QRgb)GridColor : View->colorGroup().mid() );
+ P->drawLine( LineX, 0, LineX, LineHeight-1 ) ;
+ }
+ }
+}
+
+
+void KBorderColumn::paintFirstLine( QPainter *P, KPixelXs , int )
+{
+ paintLine( P );
+}
+
+
+void KBorderColumn::paintNextLine( QPainter *P )
+{
+ paintLine( P );
+}
+
+void KBorderColumn::paintEmptyColumn( QPainter *P, KPixelXs Xs, KPixelYs Ys )
+{
+ KColumn::paintEmptyColumn( P,Xs,Ys );
+
+ KPixelX LX = x() + LineX;
+ if( Middle && Xs.includes(LX) )
+ {
+ int GridColor = View->style().styleHint( QStyle::SH_Table_GridLineColor, View );
+ P->setPen( GridColor != -1 ? (QRgb)GridColor : View->colorGroup().mid() );
+ P->drawLine( LX, Ys.start(), LX, Ys.end() ) ;
+ }
+}
diff --git a/khexedit/lib/kbordercolumn.h b/khexedit/lib/kbordercolumn.h
new file mode 100644
index 0000000..0a72c05
--- /dev/null
+++ b/khexedit/lib/kbordercolumn.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ kbordercolumn.h - description
+ -------------------
+ begin : Mit Mai 21 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KBORDERCOLUMN_H
+#define KHE_KBORDERCOLUMN_H
+
+#include "kcolumn.h"
+
+namespace KHE
+{
+
+/** column that does nothing but draw a vertical line in the middle of the column
+ *
+ *@author Friedrich W. H. Kossebau
+ */
+
+class KBorderColumn : public KColumn
+{
+ public:
+ KBorderColumn( KColumnsView *V, bool M );
+ ~KBorderColumn();
+
+ public: // KColumn-API
+ virtual void paintFirstLine( QPainter *P, KPixelXs Xs, int FirstLine );
+ virtual void paintNextLine( QPainter *P );
+ virtual void paintEmptyColumn( QPainter *P, KPixelXs Xs, KPixelYs Ys );
+
+ protected:
+ virtual void paintLine( QPainter *P );
+
+ protected:
+ /** true if we are between two columns and should show a line */
+ bool Middle;
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/kbuffercoltextexport.cpp b/khexedit/lib/kbuffercoltextexport.cpp
new file mode 100644
index 0000000..a4ee91f
--- /dev/null
+++ b/khexedit/lib/kbuffercoltextexport.cpp
@@ -0,0 +1,108 @@
+/***************************************************************************
+ kbuffercoltextexport.cpp - description
+ -------------------
+ begin : Sam Aug 30 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// c specific
+#include <string.h>
+// lib specific
+#include "kbuffercolumn.h"
+#include "kbufferlayout.h"
+#include "kbuffercoltextexport.h"
+
+
+using namespace KHE;
+
+static const int DefaultTEByteSpacingWidth = 1;
+static const int TEGroupSpacingWidth = 3;
+
+QString KBufferColTextExport::whiteSpace( uint s )
+{
+ return QString().fill( ' ', s );
+}
+
+KBufferColTextExport::KBufferColTextExport( const KBufferColumn* BufferColumn, const char *D,
+ KCoordRange CR, int ByteWidth )
+ : Data( D ),
+ CoordRange( CR )
+{
+ NoOfBytesPerLine = BufferColumn->layout()->noOfBytesPerLine();
+ Pos = new int[NoOfBytesPerLine];
+
+ // TODO: remove this hack and make it more general
+ int ByteSpacingWidth = BufferColumn->byteSpacingWidth();
+ if( ByteSpacingWidth > 0 )
+ ByteSpacingWidth = DefaultTEByteSpacingWidth;
+
+ int SpacingTrigger = BufferColumn->noOfGroupedBytes()-1;
+ if( SpacingTrigger < 0 )
+ SpacingTrigger = NoOfBytesPerLine; // ensures to never trigger the group spacing
+
+ int N = 0;
+ int p = 0;
+ int gs = 0;
+ int *P = Pos;
+ for( ; P<&Pos[NoOfBytesPerLine]; ++P, ++p, ++gs )
+ {
+ *P = N;
+ N += ByteWidth;
+
+ // is there a space behind the actual byte (if it is not the last)?
+ if( gs == SpacingTrigger )
+ {
+ N += TEGroupSpacingWidth;
+ gs = -1;
+ }
+ else
+ N += ByteSpacingWidth;
+ }
+ N -= (gs==0)?TEGroupSpacingWidth:ByteSpacingWidth;
+
+ NoOfCharsPerLine = N;
+}
+
+
+KBufferColTextExport::~KBufferColTextExport()
+{
+ delete [] Pos;
+}
+
+
+int KBufferColTextExport::charsPerLine() const
+{
+ return NoOfCharsPerLine;
+}
+
+
+void KBufferColTextExport::printFirstLine( QString &T, int Line ) const
+{
+ PrintLine = Line;
+ PrintData = Data;
+ print( T );
+}
+
+
+void KBufferColTextExport::printNextLine( QString &T ) const
+{
+ print( T );
+}
+
+
+void KBufferColTextExport::print( QString &T ) const
+{
+ T.append( whiteSpace(NoOfCharsPerLine) );
+ ++PrintLine;
+}
+
diff --git a/khexedit/lib/kbuffercoltextexport.h b/khexedit/lib/kbuffercoltextexport.h
new file mode 100644
index 0000000..6cb161d
--- /dev/null
+++ b/khexedit/lib/kbuffercoltextexport.h
@@ -0,0 +1,73 @@
+/***************************************************************************
+ kbuffercoltextexport.h - description
+ -------------------
+ begin : Sam Aug 30 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KBUFFERCOLTEXTEXPORT_H
+#define KHE_KBUFFERCOLTEXTEXPORT_H
+
+// qt specific
+#include <qstring.h>
+// lib specific
+#include "kcoltextexport.h"
+#include "kcoordrange.h"
+
+
+namespace KHE
+{
+
+class KBufferColumn;
+
+
+class KBufferColTextExport : public KColTextExport
+{
+ public:
+ KBufferColTextExport( const KBufferColumn* BF, const char *D, KCoordRange CR, int BytesWidth );
+ virtual ~KBufferColTextExport();
+
+ public: // API
+ void printFirstLine( QString &T, int Line ) const;
+ void printNextLine( QString &T ) const;
+ /** tells how much chars per line are needed */
+ int charsPerLine() const;
+
+
+ protected: // API to be reimplemented by subclasses
+ virtual void print( QString &T ) const;
+
+
+ protected:
+ static QString whiteSpace( uint s );
+
+ protected:
+ const char *Data;
+ KCoordRange CoordRange;
+
+ int NoOfBytesPerLine;
+
+ /** Line to print */
+ mutable int PrintLine;
+ /** Data to print */
+ mutable const char *PrintData;
+
+ /** buffered value of how many chars a line needs */
+ int NoOfCharsPerLine;
+ // positions where to paint the
+ int *Pos;
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/kbuffercolumn.cpp b/khexedit/lib/kbuffercolumn.cpp
new file mode 100644
index 0000000..4291e00
--- /dev/null
+++ b/khexedit/lib/kbuffercolumn.cpp
@@ -0,0 +1,700 @@
+/***************************************************************************
+ kbuffercolumn.cpp - description
+ -------------------
+ begin : Mit Mai 14 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+//#include <kdebug.h>
+
+// qt specific
+#include <qpainter.h>
+// lib specific
+#include "kcolumnsview.h"
+#include "kbuffercursor.h"
+#include "kbuffercolumn.h"
+#include "kbufferlayout.h"
+#include "kbufferranges.h"
+#include "helper.h"
+#include "kcharcodec.h"
+
+using namespace KHE;
+
+static const unsigned int StartsBefore = 1;
+static const unsigned int EndsLater = 2;
+static const char EmptyByte = ' ';
+
+static const KPixelX DefaultCursorWidth = 2;
+static const KPixelX DefaultByteSpacingWidth = 3;
+static const KPixelX DefaultGroupSpacingWidth = 9;
+static const int DefaultNoOfGroupedBytes = 4;
+
+KBufferColumn::KBufferColumn( KColumnsView *CV, KDataBuffer *B, KBufferLayout *L, KBufferRanges *R )
+ : KColumn( CV ),
+ Buffer( B ),
+ Layout( L ),
+ Ranges( R ),
+ DigitWidth( 0 ),
+ DigitBaseLine( 0 ),
+ VerticalGrid( false ),
+ ByteWidth( 0 ),
+ ByteSpacingWidth( DefaultByteSpacingWidth ),
+ GroupSpacingWidth( DefaultGroupSpacingWidth ),
+ NoOfGroupedBytes( DefaultNoOfGroupedBytes ),
+ PosX( 0L ),
+ PosRightX( 0L ),
+ LastPos( 0 )
+{
+}
+
+
+KBufferColumn::~KBufferColumn()
+{
+ delete [] PosX;
+ delete [] PosRightX;
+}
+
+
+
+void KBufferColumn::set( KDataBuffer *B )
+{
+ Buffer= B;
+}
+
+
+void KBufferColumn::resetXBuffer()
+{
+ delete [] PosX;
+ delete [] PosRightX;
+
+ LastPos = Layout->noOfBytesPerLine()-1;
+ PosX = new KPixelX[LastPos+1];
+ PosRightX = new KPixelX[LastPos+1];
+
+ if( PosX )
+ recalcX();
+}
+
+
+void KBufferColumn::setMetrics( KPixelX DW, KPixelY DBL )
+{
+ DigitBaseLine = DBL;
+ setDigitWidth( DW );
+}
+
+
+bool KBufferColumn::setDigitWidth( KPixelX DW )
+{
+ // no changes?
+ if( DigitWidth == DW )
+ return false;
+
+ DigitWidth = DW;
+ // recalculate depend sizes
+ recalcByteWidth();
+
+ if( PosX )
+ recalcX();
+ return true;
+}
+
+
+bool KBufferColumn::setSpacing( KPixelX BSW, int NoGB, KPixelX GSW )
+{
+ // no changes?
+ if( ByteSpacingWidth == BSW && NoOfGroupedBytes == NoGB && GroupSpacingWidth == GSW )
+ return false;
+
+ ByteSpacingWidth = BSW;
+ NoOfGroupedBytes = NoGB;
+ GroupSpacingWidth = GSW;
+
+ // recalculate depend sizes
+ recalcVerticalGridX();
+
+ if( PosX )
+ recalcX();
+ return true;
+}
+
+
+bool KBufferColumn::setByteSpacingWidth( KPixelX BSW )
+{
+ // no changes?
+ if( ByteSpacingWidth == BSW )
+ return false;
+
+ ByteSpacingWidth = BSW;
+
+ // recalculate depend sizes
+ recalcVerticalGridX();
+
+ if( PosX )
+ recalcX();
+ return true;
+}
+
+
+bool KBufferColumn::setNoOfGroupedBytes( int NoGB )
+{
+ // no changes?
+ if( NoOfGroupedBytes == NoGB )
+ return false;
+
+ NoOfGroupedBytes = NoGB;
+
+ if( PosX )
+ recalcX();
+ return true;
+}
+
+
+bool KBufferColumn::setGroupSpacingWidth( KPixelX GSW )
+{
+ // no changes?
+ if( GroupSpacingWidth == GSW )
+ return false;
+
+ GroupSpacingWidth = GSW;
+
+ // recalculate depend sizes
+ recalcVerticalGridX();
+
+ if( PosX )
+ recalcX();
+ return true;
+}
+
+
+void KBufferColumn::recalcByteWidth()
+{
+ ByteWidth = DigitWidth;
+ recalcVerticalGridX();
+}
+
+
+void KBufferColumn::recalcVerticalGridX()
+{
+ VerticalGridX = ByteWidth-1 + GroupSpacingWidth/2;
+}
+
+
+void KBufferColumn::recalcX()
+{
+ SpacingTrigger = noOfGroupedBytes() > 0 ? noOfGroupedBytes()-1 : LastPos+1; // last ensures to never trigger the spacing
+
+ KPixelX NewWidth = 0;
+ int p = 0;
+ int gs = 0;
+ KPixelX *PX = PosX;
+ KPixelX *PRX = PosRightX;
+ for( ; PX<&PosX[LastPos+1]; ++PX, ++PRX, ++p, ++gs )
+ {
+ *PX = NewWidth;
+ NewWidth += ByteWidth;
+ *PRX = NewWidth-1;
+
+ // is there a space behind the actual byte (if it is not the last)?
+ if( gs == SpacingTrigger )
+ {
+ NewWidth += GroupSpacingWidth;
+ gs = -1;
+ }
+ else
+ NewWidth += ByteSpacingWidth;
+ }
+ setWidth( PosRightX[LastPos]+1 );
+}
+
+
+// TODO: why are inlined functions not available as symbols when defined before their use
+//TODO: works not precisly for the byte rects but includes spacing and left and right
+/*inline*/ int KBufferColumn::posOfX( KPixelX PX ) const
+{
+ if( !PosX )
+ return NoByteFound;
+
+ // translate
+ PX -= x();
+ // search backwards for the first byte that is equalleft to x
+ for( int p=LastPos; p>=0; --p )
+ if( PosX[p] <= PX )
+ return p;
+
+ return 0; //NoByteFound;
+}
+
+
+int KBufferColumn::magPosOfX( KPixelX PX ) const
+{
+ if( !PosX )
+ return NoByteFound;
+
+ // translate
+ PX -= x();
+ // search backwards for the first byte that is equalleft to x
+ for( int p=LastPos; p>=0; --p )
+ if( PosX[p] <= PX )
+ {
+ // are we close to the right?
+ if( PosRightX[p]-PX < DigitWidth/2 ) // TODO: perhaps cache also the middle xpos's
+ ++p;
+ return p;
+ }
+
+ return 0; //NoByteFound;
+}
+
+
+KSection KBufferColumn::posOfX( KPixelX PX, KPixelX PW ) const
+{
+ if( !PosX )
+ return KSection();
+
+ // translate
+ PX -= x();
+ int PRX = PX + PW - 1;
+
+ KSection P;
+ // search backwards for the first byte that is equalleft to x
+ for( int p=LastPos; p>=0; --p )
+ if( PosX[p] <= PRX )
+ {
+ P.setEnd( p );
+ for( ; p>=0; --p )
+ if( PosX[p] <= PX )
+ {
+ P.setStart( p );
+ break;
+ }
+ break;
+ }
+
+ return P;
+}
+
+
+KPixelX KBufferColumn::xOfPos( int Pos ) const { return x() + (PosX?PosX[Pos]:0); }
+KPixelX KBufferColumn::rightXOfPos( int Pos ) const { return x() + (PosRightX?PosRightX[Pos]:0); }
+
+
+int KBufferColumn::posOfRelX( KPixelX PX ) const
+{
+ if( !PosX )
+ return NoByteFound;
+
+ // search backwards for the first byte that is equalleft to x
+ for( int p=LastPos; p>=0; --p )
+ if( PosX[p] <= PX )
+ return p;
+
+ return 0; //NoByteFound;
+}
+
+
+KSection KBufferColumn::posOfRelX( KPixelX PX, KPixelX PW ) const
+{
+ if( !PosX )
+ return KSection();
+
+ int PRX = PX + PW - 1;
+
+ KSection P;
+ // search backwards for the first byte that is equalleft to x
+ for( int p=LastPos; p>=0; --p )
+ if( PosX[p] <= PRX )
+ {
+ P.setEnd( p );
+ for( ; p>=0; --p )
+ if( PosX[p] <= PX )
+ {
+ P.setStart( p );
+ break;
+ }
+ break;
+ }
+
+ return P;
+}
+
+
+KPixelX KBufferColumn::relXOfPos( int Pos ) const { return PosX ? PosX[Pos] : 0; }
+KPixelX KBufferColumn::relRightXOfPos( int Pos ) const { return PosRightX ? PosRightX[Pos] : 0; }
+
+
+KPixelXs KBufferColumn::wideXPixelsOfPos( KSection Positions ) const
+{
+ return KPixelXs( Positions.start()>0?rightXOfPos(Positions.start()-1)+1:xOfPos(Positions.start()),
+ Positions.end()<LastPos?xOfPos(Positions.end()+1)-1:rightXOfPos(Positions.end()) );
+}
+
+
+KPixelXs KBufferColumn::relWideXPixelsOfPos( KSection Positions ) const
+{
+ return KPixelXs( Positions.start()>0?relRightXOfPos(Positions.start()-1)+1:relXOfPos(Positions.start()),
+ Positions.end()<LastPos?relXOfPos(Positions.end()+1)-1:relRightXOfPos(Positions.end()) );
+}
+
+
+void KBufferColumn::preparePainting( KPixelXs Xs )
+{
+ Xs.restrictTo( XSpan );
+ // translate
+ Xs.moveBy( -x() );
+
+
+ // store the values
+ PaintX = Xs.start();
+ PaintW = Xs.width();
+
+ // get line positions to paint
+ PaintPositions = posOfRelX( PaintX, PaintW );
+}
+
+
+void KBufferColumn::paintFirstLine( QPainter *P, KPixelXs Xs, int FirstLine )
+{
+ preparePainting( Xs );
+
+ PaintLine = FirstLine;
+
+// kdDebug(1501) << "paintFirstLine:"<<cx<<","<<cw<<"|" <<PaintX<<","<<PaintW << ")\n";
+
+// paintPositions( P, PaintLine++, PaintPositions );
+ paintLine( P, PaintLine++ );
+}
+
+
+void KBufferColumn::paintNextLine( QPainter *P )
+{
+// paintPositions( P, PaintLine++, PaintPositions );
+ paintLine( P, PaintLine++ );
+}
+
+
+void KBufferColumn::paintLine( QPainter *P, int Line ) // TODO: could be removed???
+{
+// kdDebug(1501) << "paintLine line: "<<Line<<" Start: "<<PaintPositions.start()<<" End: "<<PaintPositions.end() << "\n";
+ // no bytes to paint?
+// if( !Layout->hasContent(Line) )
+// return;
+
+ paintPositions( P, Line, PaintPositions );
+}
+
+
+void KBufferColumn::paintPositions( QPainter *P, int Line, KSection Pos )
+{
+ const QColorGroup &CG = View->colorGroup();
+
+ // clear background
+ unsigned int BlankFlag = (Pos.start()!=0?StartsBefore:0) | (Pos.end()!=LastPos?EndsLater:0);
+ paintRange( P, CG.base(), Pos, BlankFlag );
+
+ // Go through the lines TODO: handle first and last line more effeciently
+ // check for leading and trailing spaces
+ KSection Positions( Layout->firstPos(KBufferCoord( Pos.start(), Line )),
+ Layout->lastPos( KBufferCoord( Pos.end(), Line )) );
+
+ // no bytes to paint?
+ if( !Layout->hasContent(Line) )
+ return;
+
+ // check for leading and trailing spaces
+ KSection Indizes( Layout->indexAtCoord(KBufferCoord( Positions.start(), Line )), Positions.width(), false );
+
+ unsigned int SelectionFlag;
+ unsigned int MarkingFlag;
+ KSection Selection;
+ KSection Marking;
+ bool HasMarking = Ranges->hasMarking();
+ bool HasSelection = Ranges->hasSelection();
+
+ while( Positions.isValid() )
+ {
+ KSection PositionsPart( Positions ); // set of positions to paint next
+ KSection IndizesPart( Indizes ); // set of indizes to paint next
+ // falls Marking nicht mehr gebuffert und noch zu erwarten
+ if( HasMarking && Marking.endsBefore(IndizesPart.start()) )
+ {
+ // erhebe nächste Markierung im Bereich
+ HasMarking = isMarked( IndizesPart, &Marking, &MarkingFlag );
+ }
+ // falls Selection nicht mehr gebuffert und noch zu erwarten
+ if( HasSelection && Selection.endsBefore(IndizesPart.start()) )
+ {
+ // erhebe nächste Selection im Bereich
+ HasSelection = isSelected( IndizesPart, &Selection, &SelectionFlag );
+ }
+
+ if( Marking.start() == IndizesPart.start() )
+ {
+ IndizesPart.setEnd( Marking.end() );
+ PositionsPart.setEndByWidth( Marking.width() );
+ if( PositionsPart.end() == Layout->lastPos(Line) ) MarkingFlag &= ~EndsLater;
+ if( PositionsPart.start() == Layout->firstPos(Line)) MarkingFlag &= ~StartsBefore;
+ paintMarking( P, PositionsPart, IndizesPart.start(), MarkingFlag );
+
+ }
+ else if( Selection.includes(IndizesPart.start()) )
+ {
+ if( Selection.startsBehind(IndizesPart.start()) )
+ SelectionFlag |= StartsBefore;
+ bool MarkingBeforeEnd = HasMarking && Marking.start() <= Selection.end();
+
+ IndizesPart.setEnd( MarkingBeforeEnd ? Marking.start()-1 : Selection.end() );
+ PositionsPart.setEndByWidth( IndizesPart.width() );
+
+ if( MarkingBeforeEnd )
+ SelectionFlag |= EndsLater;
+ if( PositionsPart.end() == Layout->lastPos(Line) ) SelectionFlag &= ~EndsLater;
+ if( PositionsPart.start() == Layout->firstPos(Line) ) SelectionFlag &= ~StartsBefore;
+
+ paintSelection( P, PositionsPart, IndizesPart.start(), SelectionFlag );
+ }
+ else
+ {
+ // calc end of plain text
+ if( HasMarking )
+ IndizesPart.setEnd( Marking.start()-1 );
+ if( HasSelection )
+ IndizesPart.restrictEndTo( Selection.start()-1 );
+
+ PositionsPart.setEndByWidth( IndizesPart.width() );
+ paintPlain( P, PositionsPart, IndizesPart.start() );
+ }
+ Indizes.setStartBehind( IndizesPart );
+ Positions.setStartBehind( PositionsPart );
+ }
+ // we don't paint grids as default, perhaps we never will though it works
+ // paintGrid( P, Positions ); // TODO: get some unmodified Positions (see three lines before)
+}
+
+
+void KBufferColumn::paintPlain( QPainter *P, KSection Positions, int Index )
+{
+ // paint all the bytes affected
+ for( int p=Positions.start(); p<=Positions.end(); ++p,++Index )
+ {
+ KPixelX x = relXOfPos( p );
+
+ // draw the byte
+ P->translate( x, 0 );
+ char Byte = Buffer->datum( Index );
+ KHEChar B = Codec->decode( Byte );
+ drawByte( P, Byte, B, colorForChar(B) );
+
+ P->translate( -x, 0 );
+ }
+}
+
+
+void KBufferColumn::paintSelection( QPainter *P, KSection Positions, int Index, int Flag )
+{
+ const QColorGroup &CG = View->colorGroup();
+
+ paintRange( P, CG.highlight(), Positions, Flag );
+
+ const QColor &HTC = CG.highlightedText();
+ // paint all the bytes affected
+ for( int p=Positions.start(); p<=Positions.end(); ++p,++Index )
+ {
+ KPixelX x = relXOfPos( p );
+
+ // draw the byte
+ P->translate( x, 0 );
+ char Byte = Buffer->datum( Index );
+ KHEChar B = Codec->decode( Byte );
+ drawByte( P, Byte, B, HTC );
+
+ P->translate( -x, 0 );
+ }
+}
+
+
+void KBufferColumn::paintMarking( QPainter *P, KSection Positions, int Index, int Flag )
+{
+ const QColorGroup &CG = View->colorGroup();
+
+ paintRange( P, CG.text(), Positions, Flag );
+
+ const QColor &BC = CG.base();
+ // paint all the bytes affected
+ for( int p=Positions.start(); p<=Positions.end(); ++p,++Index )
+ {
+ KPixelX x = relXOfPos( p );
+
+ // draw the byte
+ P->translate( x, 0 );
+ char Byte = Buffer->datum( Index );
+ KHEChar B = Codec->decode( Byte );
+ drawByte( P, Byte, B, BC );
+
+ P->translate( -x, 0 );
+ }
+}
+
+
+// TODO: smarter calculation
+void KBufferColumn::paintGrid( QPainter *P, KSection Range )
+{
+ int st = 0; // counter for spacing triggering
+ P->setPen( Qt::black );
+ // paint all the bytes affected
+ for( int p=Range.start(); p<=Range.end(); ++p,++st )
+ {
+ KPixelX x = relXOfPos( p );
+
+ // draw the byte
+ P->translate( x, 0 );
+
+ // spacing behind byte and vertical grid enabled?
+ if( st == SpacingTrigger && p != LastPos )
+ P->drawLine( VerticalGridX, 0, VerticalGridX, LineHeight-1 ) ;
+
+ P->translate( -x, 0 );
+ }
+}
+
+
+void KBufferColumn::paintRange( QPainter *P, const QColor &Color, KSection Positions, int Flag )
+{
+ KPixelX RangeX = Flag & StartsBefore ? relRightXOfPos( Positions.start()-1 ) + 1 : relXOfPos( Positions.start() );
+ KPixelX RangeW = (Flag & EndsLater ? relXOfPos( Positions.end()+1 ): relRightXOfPos( Positions.end() ) + 1) - RangeX;
+
+ P->fillRect( RangeX,0,RangeW,LineHeight, QBrush(Color,Qt::SolidPattern) );
+}
+
+
+void KBufferColumn::paintByte( QPainter *P, int Index )
+{
+ char Byte = ( Index > -1 ) ? Buffer->datum( Index ) : EmptyByte;
+ KHEChar B = Codec->decode( Byte );
+
+ const QColorGroup &CG = View->colorGroup();
+ QColor Color = CG.text();
+ QBrush Brush( CG.base(), Qt::SolidPattern );
+
+ if( Index > -1 )
+ {
+ if( Ranges->markingIncludes(Index) )
+ {
+ Brush.setColor( CG.text() );
+ Color = CG.base();
+ }
+ else if( Ranges->selectionIncludes(Index) )
+ {
+ Brush.setColor( CG.highlight() );
+ Color = CG.highlightedText();
+ }
+ else
+ {
+ Brush.setColor( CG.base() );
+ Color = colorForChar( B );
+ }
+ }
+
+ P->fillRect( 0,0,ByteWidth,LineHeight, Brush );
+
+ if( Index > -1 )
+ drawByte( P, Byte, B, Color );
+}
+
+
+void KBufferColumn::paintFramedByte( QPainter *P, int Index, KFrameStyle FrameStyle )
+{
+ paintByte( P, Index );
+ char Byte = ( Index > -1 ) ? Buffer->datum( Index ) : EmptyByte;
+ KHEChar B = Codec->decode( Byte );
+
+ P->setPen( colorForChar(B) );
+ if( FrameStyle == Frame )
+ P->drawRect( 0, 0, ByteWidth, LineHeight );
+ else if( FrameStyle == Left )
+ P->drawLine( 0, 0, 0, LineHeight-1 );
+ else
+ P->drawLine( ByteWidth-1,0,ByteWidth-1,LineHeight-1 );
+}
+
+
+void KBufferColumn::paintCursor( QPainter *P, int Index )
+{
+ char Byte = ( Index > -1 ) ? Buffer->datum( Index ) : EmptyByte;
+ KHEChar B = Codec->decode( Byte );
+ P->fillRect( 0, 0, ByteWidth, LineHeight, QBrush(colorForChar(B),Qt::SolidPattern) );
+}
+
+
+void KBufferColumn::drawByte( QPainter *P, char /*Byte*/, KHEChar B, const QColor &Color ) const
+{
+ P->setPen( Color );
+ P->drawText( 0, DigitBaseLine, B );
+}
+
+
+bool KBufferColumn::isSelected( KSection Range, KSection *Selection, unsigned int *Flag ) const
+{
+ KSection S;
+ unsigned int F = 0;
+ const KSection *OS = Ranges->firstOverlappingSelection( Range );
+ if( !OS )
+ return false;
+ S = *OS;
+
+ // does selection start before asked range?
+ if( Range.start() > S.start() )
+ {
+ S.setStart( Range.start() );
+ F |= StartsBefore;
+ }
+
+ // does selection go on behind asked range?
+ if( Range.end() < S.end() )
+ {
+ S.setEnd( Range.end() );
+ F |= EndsLater;
+ }
+
+ *Selection = S;
+ *Flag = F;
+ return true;
+}
+
+
+bool KBufferColumn::isMarked( KSection Range, KSection *Marking, unsigned int *Flag ) const
+{
+ KSection M;
+ unsigned int F = 0;
+ const KSection *OM = Ranges->overlappingMarking( Range );
+ if( !OM )
+ return false;
+ M = *OM;
+
+ // does selection start before asked range?
+ if( Range.start() > M.start() )
+ {
+ M.setStart( Range.start() );
+ F |= StartsBefore;
+ }
+
+ // does selection go on behind asked range?
+ if( Range.end() < M.end() )
+ {
+ M.setEnd( Range.end() );
+ F |= EndsLater;
+ }
+
+ *Marking = M;
+ *Flag = F;
+ return true;
+}
diff --git a/khexedit/lib/kbuffercolumn.h b/khexedit/lib/kbuffercolumn.h
new file mode 100644
index 0000000..76ed8bc
--- /dev/null
+++ b/khexedit/lib/kbuffercolumn.h
@@ -0,0 +1,253 @@
+/***************************************************************************
+ kbuffercolumn.h - description
+ -------------------
+ begin : Mit Mai 14 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KBUFFERCOLUMN_H
+#define KHE_KBUFFERCOLUMN_H
+
+// lib specific
+#include "khe.h"
+#include "kdatabuffer.h"
+#include "khechar.h"
+#include "kcolumn.h"
+#include "kbufferlayout.h"
+#include "ksection.h"
+
+class QPainter;
+class QColor;
+
+namespace KHE
+{
+
+// class KHexEdit;
+class KBufferRanges;
+class KCharCodec;
+
+const int NoByteFound = -1;
+
+/** base class of all buffer column displayers
+ * holds all information about the vertical layout of a buffer column
+ * knows how to paint the data and the editing things (focus, cursor, selection)
+ * but does not offer
+ *
+ *@author Friedrich W. H. Kossebauint KBufferColumn::posOfX( KPixelX PX, bool *ToTheRightFlag ) const
+ */
+class KBufferColumn : public KColumn
+{
+ public:
+ enum KFrameStyle { Frame, Left, Right };
+ public:
+ KBufferColumn( KColumnsView/*KHexEdit*/ *HE, KDataBuffer *B, KBufferLayout *L, KBufferRanges *R );
+ virtual ~KBufferColumn();
+
+
+ public: // KColumn-API
+ virtual void paintFirstLine( QPainter *P, KPixelXs Xs, int FirstLine );
+ virtual void paintNextLine( QPainter *P );
+
+ public:
+ void preparePainting( KPixelXs Xs );
+
+ public:
+ void paintLine( QPainter *P, int Line );
+ void paintPositions( QPainter *P, int Line, KSection Positions );
+ /** paints a cursor based on the type of the byte.
+ * @param Index Index of the byte to paint the cursor for. If -1 a space is used as char.
+ */
+ void paintCursor( QPainter *P, int Index );
+ /** paints the byte with background.
+ * @param Index Index of the byte to paint. If -1 only the background is painted.
+ */
+ void paintByte( QPainter *P, int Index );
+ /** paints the byte with background and a frame around.
+ * @param Index Index of the byte to paint the frame for. If -1 a space is used as char.
+ * @param Style the style of the framing
+ */
+ void paintFramedByte( QPainter *P, int Index, KFrameStyle Style );
+
+
+ public: // modification access
+ /** sets the spacing in the hex column
+ * @param ByteSpacingW spacing between the bytes in pixels
+ * @param NewNoOfGroupedBytes numbers of grouped bytes, 0 means no grouping
+ * @param GroupSpacingW spacing between the groups in pixels
+ * returns true if there was a change
+ */
+ bool setSpacing( KPixelX ByteSpacingW, int NewNoOfGroupedBytes = 0, KPixelX GroupSpacingW = 0 );
+ /** sets the spacing between the bytes in the hex column
+ * @param ByteSpacingW spacing between the bytes in pixels
+ * returns true if there was a change
+ */
+ bool setByteSpacingWidth( KPixelX ByteSpacingW );
+ /** sets the number of grouped bytes in the hex column
+ * @param NewNoOfGroupedBytes numbers of grouped bytes, 0 means no grouping
+ * returns true if there was a change
+ */
+ bool setNoOfGroupedBytes( int NewNoOfGroupedBytes );
+ /** sets the spacing between the groups of bytes in the hex column
+ * @param GroupSpacingW spacing between the groups in pixels
+ * returns true if there was a change
+ */
+ bool setGroupSpacingWidth( KPixelX GroupSpacingW );
+ /** sets width of digits and recalculates depend sizes
+ * returns true if there was a change
+ */
+ bool setDigitWidth( KPixelX DW );
+ /** sets the metrics of the used font
+ * @param NewDigitWidth the new width of a digit
+ * @param NewDigitBaseLine the new baseline of the digits
+ */
+ void setMetrics( KPixelX NewDigitWidth, KPixelY NewDigitBaseLine );
+ /** */
+ void set( KDataBuffer *B );
+ /** creates new buffer for x-values; to be called on any change of NoOfBytesPerLine or metrics */
+ void resetXBuffer();
+ /** sets the codec to be used by the char column. */
+ void setCodec( KCharCodec *C );
+
+ public: // functional logic
+ /** returns byte positions covered by pixels with absolute x-coord x */
+ KSection posOfX( KPixelX x, KPixelX w ) const;
+ /** returns byte pos at pixel with absolute x-coord x */
+ int posOfX( KPixelX x ) const;
+ /** returns byte pos at pixel with absolute x-coord x, and sets the flag to true if we are closer to the right */
+ int magPosOfX( KPixelX PX ) const;
+ /** returns absolute x-coord of byte at position Pos */
+ KPixelX xOfPos( int Pos ) const;
+ /** returns right absolute x-coord of byte at position Pos */
+ KPixelX rightXOfPos( int Pos ) const;
+ /** returns byte pos at pixel with relative x-coord x */
+ int posOfRelX( KPixelX x ) const;
+ /** returns byte positions covered by pixels with relative x-coord x */
+ KSection posOfRelX( KPixelX x, KPixelX w ) const;
+ /** returns relative x-coord of byte at position Pos */
+ KPixelX relXOfPos( int Pos ) const;
+ /** returns right relative x-coord of byte at position Pos */
+ KPixelX relRightXOfPos( int Pos ) const;
+ /** returns the positions that overlap with the absolute x-coords */
+ KSection visiblePositions( KPixelX x, KPixelX w ) const;
+ /** returns the */
+ KPixelXs wideXPixelsOfPos( KSection Positions ) const;
+ /** */
+ KPixelXs relWideXPixelsOfPos( KSection Positions ) const;
+
+ public: // value access
+ KPixelX byteWidth() const;
+ KPixelX digitWidth() const;
+ KPixelX groupSpacingWidth() const;
+ KPixelX byteSpacingWidth() const;
+ int noOfGroupedBytes() const;
+
+ int firstPos() const;
+ int lastPos() const;
+ KSection visiblePositions() const;
+ const KBufferLayout *layout() const;
+ KCharCodec* codec() const;
+
+ protected:
+ /** */
+ void recalcX();
+ void recalcVerticalGridX();
+
+
+ protected: // API to be refined
+ /** default implementation simply prints the byte as ASCII */
+ virtual void drawByte( QPainter *P, char Byte, KHEChar B, const QColor &Color ) const;
+ /** default implementation sets byte width to one digit width */
+ virtual void recalcByteWidth();
+
+
+ protected:
+ void paintGrid( QPainter *P, KSection Range );
+ void paintPlain( QPainter *P, KSection Positions, int Index );
+ void paintSelection( QPainter *P, KSection Positions, int Index, int Flag );
+ void paintMarking( QPainter *P, KSection Positions, int Index, int Flag );
+ void paintRange( QPainter *P, const QColor &Color, KSection Positions, int Flag );
+
+ bool isSelected( KSection Range, KSection *Selection, unsigned int *Flag ) const;
+ bool isMarked( KSection Range, KSection *Marking, unsigned int *Flag ) const;
+
+
+ protected:
+ /** pointer to the buffer */
+ KDataBuffer *Buffer;
+ /** pointer to the layout */
+ const KBufferLayout *Layout;
+ /** pointer to the ranges */
+ KBufferRanges *Ranges;
+ /** */
+ KCharCodec *Codec;
+
+ /** */
+ KPixelX DigitWidth;
+ /** */
+ KPixelY DigitBaseLine;
+ /** */
+ KPixelX VerticalGridX;
+ /** */
+ bool VerticalGrid;
+
+ protected: // individual data
+ /** total width of byte display in pixel */
+ KPixelX ByteWidth;
+ /** width of inserting cursor in pixel */
+ KPixelX CursorWidth;
+ /** size of the line margin */
+ KPixelX ByteSpacingWidth;
+ /** width of spacing in pixel */
+ KPixelX GroupSpacingWidth;
+
+ /** number of grouped bytes */
+ int NoOfGroupedBytes;
+
+ /** pointer to array with buffered positions (relative to column position)
+ * a spacing gets assigned to the left byte -> ...c|c|c |c|c...
+ */
+ KPixelX *PosX;
+ KPixelX *PosRightX;
+ /** index of right position */
+ int LastPos;
+
+
+ protected: // buffering drawing data
+ KSection PaintPositions;
+ int PaintLine;
+ KPixelX PaintX;
+ KPixelX PaintW;
+ int SpacingTrigger;
+};
+
+
+inline KPixelX KBufferColumn::byteWidth() const { return ByteWidth; }
+inline KPixelX KBufferColumn::digitWidth() const { return DigitWidth; }
+inline KPixelX KBufferColumn::byteSpacingWidth() const { return ByteSpacingWidth; }
+inline KPixelX KBufferColumn::groupSpacingWidth() const { return GroupSpacingWidth; }
+
+inline int KBufferColumn::noOfGroupedBytes() const { return NoOfGroupedBytes; }
+
+inline int KBufferColumn::firstPos() const { return PaintPositions.start(); }
+inline int KBufferColumn::lastPos() const { return PaintPositions.end(); }
+inline KSection KBufferColumn::visiblePositions() const { return PaintPositions; }
+
+inline const KBufferLayout *KBufferColumn::layout() const { return Layout; }
+
+
+inline void KBufferColumn::setCodec( KCharCodec *C ) { Codec = C; }
+inline KCharCodec* KBufferColumn::codec() const { return Codec; }
+
+}
+
+#endif
diff --git a/khexedit/lib/kbuffercoord.h b/khexedit/lib/kbuffercoord.h
new file mode 100644
index 0000000..997551a
--- /dev/null
+++ b/khexedit/lib/kbuffercoord.h
@@ -0,0 +1,293 @@
+/***************************************************************************
+ kbuffercoord.h - description
+ -------------------
+ begin : Don Mai 29 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KBUFFERCOORD_H
+#define KHE_KBUFFERCOORD_H
+
+
+namespace KHE
+{
+
+/**
+ * a class which represents a coord in a 2-dim. system
+ *
+ * It consists of a line number and a position in the line.
+ * The coord starts at (0,0). Line numbers increase downwards, positions to the right.
+ * With any of both at a negative number the coord is invalid.
+ * TODO: change as much as possible params to unsigned integer
+ *
+ * @author Friedrich W. H. Kossebau
+ */
+class KBufferCoord
+{
+ public:
+ /** creates a coord with 0,0 */
+ KBufferCoord();
+ KBufferCoord( int P, int L );
+ KBufferCoord( int Index, int LineWidth, bool /*dummy*/ );
+ KBufferCoord( const KBufferCoord &C );
+ KBufferCoord &operator=( const KBufferCoord &c );
+ ~KBufferCoord();
+
+
+ public: // logic
+ bool operator==( const KBufferCoord &c ) const;
+ bool operator!=( const KBufferCoord &c ) const;
+ bool operator<( const KBufferCoord &c ) const;
+ bool operator<=( const KBufferCoord &c ) const;
+ bool operator>( const KBufferCoord &c ) const;
+ bool operator>=( const KBufferCoord &c ) const;
+
+ /** tests if the coord is prior in the same line than the given coord.
+ * If at least one of both is invalid the result is undefined.
+ * @return true if the pos is left to the pos of C and both are in the same line, otherwise false.
+ */
+ bool isPriorInLineThan( const KBufferCoord &C ) const;
+ /** tests if the coord is later in the same line than the given coord.
+ * If at least one of both is invalid the result is undefined.
+ * @return true if the pos is right to the pos of C and both are in the same line, otherwise false
+ */
+ bool isLaterInLineThan( const KBufferCoord &C ) const;
+ /** @return true if the line is below L, otherwise false */
+ bool isBelow( int L ) const;
+ /** @return true if the line is above L, otherwise false */
+ bool isAbove( int L ) const;
+ /** @return true if the coord is at (0,0) */
+ bool isAtStart() const;
+ /** @return true if the pos is greater than 0, otherwise false */
+ bool isBehindLineStart() const;
+ /** @return true if the pos is smaller than MaxPos, otherwise false */
+ bool isBeforeLineEnd( int MaxPos ) const;
+
+ /** calculates the index the coord is at with a given line width
+ * If the coord is invalid the result is undefined.
+ * @param LineWidth given width of line
+ * @return index the coord is at
+ */
+ int indexByLineWidth( int LineWidth ) const;
+
+ public:
+ /** set the coord by calculating it for an index with a given line width
+ * @param Index index in the buffer
+ * @param LineWidth given line width
+ */
+ void setByIndexNWidth( int Index, int LineWidth );
+ /** sets both position and line */
+ void set( int P, int L );
+ /** sets the position */
+ void setPos( int P );
+ /** sets the line */
+ void setLine( int L );
+
+ /** moves the coord one position to the left. If the coord is invalid the result is undefined. */
+ void goLeft();
+ /** moves the coord a given number of positions to the left.
+ * If the coord is invalid the result is undefined or the position smaller then the given number
+ * the behaviour is undefined.
+ * @param P number of positions
+ */
+ void goLeft( unsigned int P );
+ /** moves the coord one position to the left, or if the position is already at the line start
+ * to the given position in the previous line. If the coord is invalid the result is undefined.
+ * @param MaxPos maximal allowed position
+ */
+ void goCLeft( int MaxPos );
+ /** moves the coord one position to the right. If the coord is invalid the result is undefined. */
+ void goRight();
+ /** moves the coord a given number of positions to the right. If the coord is invalid the result is undefined.
+ * @param P number of positions
+ */
+ void goRight( unsigned int P );
+ /** moves the coord one position to the right, or if the position has already reached or passed MaxPos
+ * to the first position in the next line. If the coord is invalid the result is undefined.
+ * @param MaxPos maximal allowed position
+ */
+ void goCRight( int MaxPos );
+ /** sets coord to (0,0) */
+ void gotoStart();
+ void gotoEndOfPreviousLine( int LastPos );
+ /** sets the coord to the start of the next line.
+ * If the coord is invalid the behaviour is undefined.
+ */
+ void gotoStartOfNextLine();
+ /** sets the position to the start of the line or
+ * if the line is the same as that of the given coord to the position of it.
+ * If one or more of the coords is invalid the behaviour is undefined.
+ * @param C a possible line start coord
+ */
+ void goLineStart( const KBufferCoord &C );
+ /** sets the position to the given pos or
+ * if the line is the same as that of the given coord to the position of that.
+ * If one or more of the coords is invalid the behaviour is undefined.
+ * @param L last position in normal line
+ * @param C a possible line end coord
+ */
+ void goLineEnd( int L, const KBufferCoord &C );
+ /** moves the coord 1 lines upwards. There is no check whether the first line is overstepped. */
+ void goUp();
+ /** moves the coord L lines downwards. */
+ void goDown();
+ /** moves the coord L lines upwards. There is no check whether the first line is overstepped.
+ * @param L number of lines
+ */
+ void goUp( unsigned int L );
+ /** moves the coord L lines downwards.
+ * @param L number of lines
+ */
+ void goDown( unsigned int L );
+
+ public: // state value access
+ /** @return the pos in the line */
+ int pos() const;
+ /** @return the line number */
+ int line() const;
+ /** @return true if the coord is valid */
+ bool isValid() const;
+
+ private: // member variables
+ /** Position in Line */
+ int Pos;
+ /** Line */
+ int Line;
+};
+
+
+inline KBufferCoord::KBufferCoord() : Pos( 0 ), Line( 0 ) {}
+inline KBufferCoord::KBufferCoord( int P, int L ) : Pos( P ), Line( L ) {}
+inline KBufferCoord::KBufferCoord( int Index, int LineWidth, bool )
+{
+ Line = Index / LineWidth;
+ Pos = Index - Line*LineWidth;
+}
+
+inline KBufferCoord::KBufferCoord( const KBufferCoord &C ) : Pos( C.Pos ), Line( C.Line ) {}
+inline KBufferCoord &KBufferCoord::operator=( const KBufferCoord &C ) { Pos = C.Pos; Line = C.Line; return *this; }
+inline KBufferCoord::~KBufferCoord() {}
+
+inline bool KBufferCoord::operator==( const KBufferCoord &C ) const { return Pos == C.Pos && Line == C.Line; }
+inline bool KBufferCoord::operator!=( const KBufferCoord &C ) const { return !(*this == C); }
+
+inline bool KBufferCoord::operator<( const KBufferCoord &C ) const
+{ return Line < C.Line || (Line == C.Line && Pos<C.Pos); }
+inline bool KBufferCoord::operator<=( const KBufferCoord &C ) const
+{ return Line < C.Line || (Line == C.Line && Pos<=C.Pos); }
+inline bool KBufferCoord::operator>( const KBufferCoord &C ) const
+{ return Line > C.Line || (Line == C.Line && Pos>C.Pos); }
+inline bool KBufferCoord::operator>=( const KBufferCoord &C ) const
+{ return Line > C.Line || (Line == C.Line && Pos>=C.Pos); }
+
+inline int KBufferCoord::pos() const { return Pos; }
+inline int KBufferCoord::line() const { return Line; }
+inline bool KBufferCoord::isValid() const { return Line >= 0 && Pos >= 0; }
+
+inline void KBufferCoord::setByIndexNWidth( int Index, int LineWidth )
+{
+ Line = Index / LineWidth;
+ Pos = Index - Line*LineWidth;
+}
+
+inline void KBufferCoord::set( int P, int L )
+{
+ Pos = P;
+ Line = L;
+}
+inline void KBufferCoord::setPos( int P ) { Pos = P; }
+inline void KBufferCoord::setLine( int L ) { Line = L; }
+
+inline void KBufferCoord::goCRight( int MaxPos )
+{
+ if( isBeforeLineEnd(MaxPos) )
+ goRight();
+ else
+ gotoStartOfNextLine();
+}
+inline void KBufferCoord::goCLeft( int MaxPos )
+{
+ if( isBehindLineStart() )
+ goLeft();
+ else
+ gotoEndOfPreviousLine( MaxPos );
+}
+
+inline void KBufferCoord::goRight() { ++Pos; }
+inline void KBufferCoord::goLeft() { --Pos; }
+inline void KBufferCoord::goRight( unsigned int P ) { Pos += P; }
+inline void KBufferCoord::goLeft( unsigned int P ) { Pos -= P; }
+
+inline void KBufferCoord::gotoStart() { Pos = Line = 0; }
+
+inline void KBufferCoord::gotoEndOfPreviousLine( int LastPos )
+{
+ --Line;
+ Pos = LastPos;
+}
+
+inline void KBufferCoord::gotoStartOfNextLine()
+{
+ ++Line;
+ Pos = 0;
+}
+
+
+inline void KBufferCoord::goLineStart( const KBufferCoord &C )
+{
+ Pos = ( Line == C.Line ) ? C.Pos : 0;
+}
+
+inline void KBufferCoord::goLineEnd( int L, const KBufferCoord &C )
+{
+ Pos = ( Line == C.Line ) ? C.Pos : L;
+}
+
+inline void KBufferCoord::goUp() { --Line; }
+inline void KBufferCoord::goDown() { ++Line; }
+inline void KBufferCoord::goUp( unsigned int L ) { Line -= L; }
+inline void KBufferCoord::goDown( unsigned int L ) { Line += L; }
+
+
+inline int KBufferCoord::indexByLineWidth( int LineWidth ) const
+{
+ return Line * LineWidth + Pos;
+}
+
+
+inline bool KBufferCoord::isPriorInLineThan( const KBufferCoord &C ) const
+{
+ return Line == C.Line && Pos < C.Pos;
+}
+
+inline bool KBufferCoord::isLaterInLineThan( const KBufferCoord &C ) const
+{
+ return Line == C.Line && Pos > C.Pos;
+}
+
+inline bool KBufferCoord::isBelow( int L ) const { return Line > L; }
+inline bool KBufferCoord::isAbove( int L ) const { return Line < L; }
+
+inline bool KBufferCoord::isBehindLineStart() const { return Pos > 0; }
+inline bool KBufferCoord::isBeforeLineEnd( int MaxPos ) const { return Pos < MaxPos; }
+
+inline bool KBufferCoord::isAtStart() const { return Pos == 0 && Line == 0; }
+
+inline KBufferCoord operator+( const KBufferCoord &C, int p )
+{
+ return KBufferCoord( C.pos()+p, C.line() );
+}
+
+}
+
+#endif
diff --git a/khexedit/lib/kbuffercursor.cpp b/khexedit/lib/kbuffercursor.cpp
new file mode 100644
index 0000000..0255d2d
--- /dev/null
+++ b/khexedit/lib/kbuffercursor.cpp
@@ -0,0 +1,365 @@
+/***************************************************************************
+ kbuffercursor.cpp - description
+ -------------------
+ begin : Don Mai 29 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+//#include <kdebug.h>
+
+// lib specific
+#include "kbufferlayout.h"
+#include "kbuffercursor.h"
+
+using namespace KHE;
+
+KBufferCursor::KBufferCursor( const KBufferLayout *L )
+ : Layout( L ),
+ Index( 0 ),
+ Coord( 0, 0 ),
+ Behind( false ),
+ AppendPosEnabled( false )
+{
+}
+
+KBufferCursor::~KBufferCursor()
+{
+}
+
+
+bool KBufferCursor::operator==( const KBufferCursor &C ) const
+{
+ return Index == C.Index && Behind == C.Behind ;
+}
+
+
+void KBufferCursor::setAppendPosEnabled( bool APE )
+{
+ if( AppendPosEnabled == APE )
+ return;
+
+ AppendPosEnabled = APE;
+ // reposition Cursor
+ int Length = Layout->length();
+ // behind buffer end, not end of line and not empty?
+ if( realIndex() >= Length && Coord.pos() < Layout->noOfBytesPerLine()-1 && Length > 0 )
+ {
+ if( AppendPosEnabled )
+ {
+ ++Index;
+ Coord.goRight();
+ Behind = false;
+ }
+ else
+ {
+ --Index;
+ Coord.goLeft();
+ Behind = true;
+ }
+ }
+}
+
+
+void KBufferCursor::gotoPreviousByte()
+{
+ if( Behind )
+ Behind = false;
+ else if( Index > 0 )
+ {
+ --Index;
+ Coord.goCLeft( Layout->noOfBytesPerLine()-1 );
+ }
+}
+
+
+void KBufferCursor::gotoPreviousByte( int D )
+{
+ if( Behind )
+ {
+ --D;
+ Behind = false;
+ }
+ if( D > Index )
+ {
+ if( Index == 0 )
+ return;
+ gotoStart();
+ }
+ gotoIndex( Index - D );
+}
+
+
+void KBufferCursor::gotoNextByte()
+{
+ int Length = Layout->length();
+
+ if( Index < Length )
+ {
+ if( Index == Length-1 )
+ stepToEnd();
+ else
+ {
+ ++Index;
+ Coord.goCRight( Layout->noOfBytesPerLine()-1 );
+ Behind = false;
+ }
+ }
+}
+
+
+void KBufferCursor::gotoNextByte( int D ) // TODO: think about consistency with gotoNextByte!!!
+{
+ if( Behind )
+ {
+ ++D;
+ Behind = false;
+ }
+ // would we end behind the end?
+ if( Index+D >= Layout->length() )
+ gotoEnd();
+ else
+ gotoIndex( Index + D );
+}
+
+
+void KBufferCursor::gotoNextByteInLine()
+{
+ int Length = Layout->length();
+
+ if( Index < Length )
+ {
+ if( Index == Length-1 )
+ stepToEnd();
+ else
+ {
+ ++Index;
+
+ if( Coord.pos() < Layout->noOfBytesPerLine()-1 )
+ Coord.goRight();
+ else
+ Behind = true;
+ }
+ }
+}
+
+
+void KBufferCursor::gotoUp()
+{
+ // can we even go up?
+ if( Coord.isBelow(Layout->startLine()) )
+ {
+ Coord.goUp();
+ if( Coord.isPriorInLineThan(Layout->start()) )
+ {
+ Index = 0;
+ Coord.setPos( Layout->startPos() );
+ Behind = false;
+ }
+ else
+ {
+ Index -= Layout->noOfBytesPerLine();
+ if( Behind && !atLineEnd() )
+ {
+ ++Index;
+ Coord.goRight();
+ Behind = false;
+ }
+ }
+ }
+}
+
+
+void KBufferCursor::gotoDown()
+{
+ if( Coord.isAbove(Layout->finalLine()) )
+ {
+ Coord.goDown();
+ // behind End?
+ if( Coord.isLaterInLineThan(Layout->final()) )
+ gotoEnd();
+ else
+ Index += Layout->noOfBytesPerLine();
+ }
+}
+
+
+void KBufferCursor::gotoLineStart()
+{
+ int OldIndex = Index;
+ Index = Layout->indexAtLineStart( Coord.line() );
+ Coord.goLeft( OldIndex-Index );
+ Behind = false;
+}
+
+
+void KBufferCursor::gotoLineEnd()
+{
+ if( Index < Layout->length() )
+ {
+ int OldIndex = Index;
+ Index = Layout->indexAtLineEnd( Coord.line() );
+ Coord.goRight( Index-OldIndex );
+
+ stepToEnd();
+ }
+}
+
+
+void KBufferCursor::gotoStart()
+{
+ Index = 0;
+ Coord = Layout->start();
+ Behind = false;
+}
+
+
+void KBufferCursor::gotoEnd()
+{
+ int Length = Layout->length();
+ if( Length > 0 )
+ {
+ Index = Length-1;
+ Coord = Layout->final();
+
+ stepToEnd();
+ }
+ else
+ gotoStart();
+}
+
+
+void KBufferCursor::gotoCIndex( int i )
+{
+ if( Layout->length() > 0 )
+ {
+ Index = Layout->correctIndex( i );
+ Coord = Layout->coordOfIndex( Index );
+ if( i > Index )
+ stepToEnd();
+ else
+ Behind = false;
+ }
+ else
+ gotoStart();
+}
+
+
+void KBufferCursor::gotoCCoord( const KBufferCoord &C )
+{
+ if( Layout->length() > 0 )
+ {
+ Coord = Layout->correctCoord( C );
+ Index = Layout->indexAtCoord( Coord );
+ if( C > Coord )
+ stepToEnd();
+ else
+ Behind = false;
+ }
+ else
+ gotoStart();
+}
+
+
+void KBufferCursor::stepToEnd()
+{
+ if( AppendPosEnabled && (Coord.pos() < Layout->noOfBytesPerLine()-1) )
+ {
+ ++Index;
+ Coord.goRight();
+ Behind = false;
+ }
+ else
+ Behind = true;
+}
+
+
+void KBufferCursor::gotoIndex( int i )
+{
+ Index = i;
+ Coord = Layout->coordOfIndex( Index );
+ Behind = false;
+}
+
+
+void KBufferCursor::gotoRealIndex()
+{
+ if( Behind )
+ {
+ ++Index;
+ Coord = Layout->coordOfIndex( Index );
+ Behind = false;
+ }
+}
+
+
+void KBufferCursor::gotoCoord( const KBufferCoord &C )
+{
+ Index = Layout->indexAtCoord( C );
+ Coord = C;
+ Behind = false;
+}
+
+
+void KBufferCursor::updateCoord()
+{
+ Coord = Layout->coordOfIndex( Index );
+}
+
+// page down should be: one page minus one line
+// -> if in the very first line page down will put the cursor on the same page into the last line
+void KBufferCursor::gotoPageUp()
+{
+ int NoOfLinesPerPage = Layout->noOfLinesPerPage();
+ int NewIndex = Index - NoOfLinesPerPage * Layout->noOfBytesPerLine();
+ if( NewIndex < 0 )
+ gotoStart();
+ else
+ {
+ Index = NewIndex;
+ Coord.goUp( NoOfLinesPerPage );
+ if( Behind && !atLineEnd() )
+ {
+ ++Index;
+ Coord.goRight();
+ Behind = false;
+ }
+ }
+}
+
+
+void KBufferCursor::gotoPageDown()
+{
+ int NoOfLinesPerPage = Layout->noOfLinesPerPage();
+ int NewIndex = Index + NoOfLinesPerPage * Layout->noOfBytesPerLine();
+ if( NewIndex >= Layout->length() )
+ gotoEnd();
+ else
+ {
+ Index = NewIndex;
+ Coord.goDown( NoOfLinesPerPage );
+ }
+}
+
+
+int KBufferCursor::validIndex() const { return Index < Layout->length() ? Index : -1; }
+int KBufferCursor::indexAtLineStart() const { return Layout->indexAtLineStart( Coord.line() ); }
+int KBufferCursor::indexAtLineEnd() const { return Layout->indexAtLineEnd( Coord.line() ); }
+
+
+bool KBufferCursor::atStart() const { return Index == 0; }
+bool KBufferCursor::atEnd() const { return Index == Layout->length() - 1; }
+bool KBufferCursor::atAppendPos() const { return realIndex() >= Layout->length(); }
+
+
+bool KBufferCursor::atLineStart() const { return Layout->atLineStart( Coord ); }
+bool KBufferCursor::atLineEnd() const { return Layout->atLineEnd( Coord ); }
diff --git a/khexedit/lib/kbuffercursor.h b/khexedit/lib/kbuffercursor.h
new file mode 100644
index 0000000..855b3e8
--- /dev/null
+++ b/khexedit/lib/kbuffercursor.h
@@ -0,0 +1,172 @@
+/***************************************************************************
+ kbuffercursor.h - description
+ -------------------
+ begin : Don Mai 29 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KBUFFERCURSOR_H
+#define KHE_KBUFFERCURSOR_H
+
+#include "kbuffercoord.h"
+
+
+namespace KHE
+{
+
+class KBufferLayout;
+
+
+/**@short navigates through the buffer in an abstract way, based on the layout
+ *
+ * The cursor is allowed to access every coord that has content as
+ * described in the layout. It holds the coord of the actual position
+ * and the according index in the data array.
+ *
+ * To enable the cursor to be placed behind the last position in a line
+ * (e.g, to mark all data in the line without placing the cursor to the
+ * beginning of the next line) there is a flag Behind that should be read
+ * as that the real index the cursor is at is the current one + 1
+ * (as returned by realIndex())
+ *
+ * For appending new data to the buffer there is also the need to be able
+ * to place the cursor at a position behind the last byte. This can be
+ * enabled by calling setAppendPosEnabled(true). If the cursor is placed to
+ * this position it gets the (real) index of the last byte + 1. As this
+ * index does not point to an existing byte validIndex() returns -1.
+ * Check for atAppendPos() to see whether cursor is at this position.
+ *
+ * If the buffer is empty there is no navigation possible, of course.
+ * The cursor will be placed to coord 0/0 with index 1, Behind=false.
+ *
+ *@author Friedrich W. H. Kossebau
+ */
+class KBufferCursor
+{
+ public:
+ KBufferCursor( const KBufferLayout *L );
+ ~KBufferCursor();
+
+
+ public:
+ bool operator==( const KBufferCursor &c ) const;
+ bool operator!=( const KBufferCursor &c ) const { return !(*this == c); }
+
+ public: // modificator
+ void setAppendPosEnabled( bool APE=true );
+
+ public: // state value access
+ /** the index that is drawn at the actual coord */
+ int index() const;
+ /** the pos of the actual coord */
+ int pos() const;
+ /** the line of the actual coord */
+ int line() const;
+ /** the actual coord */
+ KBufferCoord coord() const;
+ /** true if the cursor is located to the right of the actual coord but still shown at the coord */
+ bool isBehind() const;
+ /** returns the real index. That is if the cursor is tagged as "behind" the current index
+ * it's real index is the next one.
+ * Attention: this could be outside the data's range if the cursor is behind the last byte!
+ */
+ int realIndex() const;
+ /** returns the true index if it is valid index that is it is inside the data's range.
+ * Otherwise -1 is returned
+ */
+ int validIndex() const;
+
+ //bool isValid() const;
+ bool appendPosEnabled() const;
+
+ public: // index calculation service
+ /** returns the index at the start of the cursor's line */
+ int indexAtLineStart() const;
+ /** returns the index at the end of the cursor's line */
+ int indexAtLineEnd() const;
+
+ public: // navigation commands
+ void gotoIndex( int I );
+ void gotoCoord( const KBufferCoord &C );
+ void gotoCIndex( int I );
+ void gotoCCoord( const KBufferCoord &C );
+ void gotoRealIndex();
+
+ void gotoPreviousByte();
+ void gotoNextByte();
+ void gotoPreviousByte( int D );
+ void gotoNextByte( int D );
+ void gotoNextByteInLine();
+ void gotoUp();
+ void gotoDown();
+ void gotoLineStart();
+ void gotoLineEnd();
+ void gotoStart();
+ void gotoEnd();
+ void gotoPageUp();
+ void gotoPageDown();
+
+ /** puts the cursor behind the actual position if it isn't already*/
+ void stepBehind();
+ void updateCoord();
+
+
+ public: // logical state access
+ bool atStart() const;
+ bool atEnd() const;
+ /** could only be true in InsertMode: Cursor is behind the last byte */
+ bool atAppendPos() const;
+ bool atLineStart() const;
+ bool atLineEnd() const;
+
+
+ protected:
+ /** if newpos allowed steps at a coord behind the last existing
+ * or, if that is at a line end, behind the line
+ * does not check for empty content!
+ */
+ void stepToEnd();
+
+ private:
+ /** layout, tells how the column is organized */
+ const KBufferLayout *Layout;
+
+ /** Position in buffer */
+ int Index;
+ /** Position and Line */
+ KBufferCoord Coord;
+
+ /** tells whether the cursor is actually behind the actual position.
+ * This is used for selection to the end of a line or of the whole buffer.
+ */
+ bool Behind : 1;
+
+ /** tells whether there could be a position behind the end of the layout */
+ bool AppendPosEnabled : 1;
+};
+
+
+inline int KBufferCursor::index() const { return Index; }
+inline int KBufferCursor::pos() const { return Coord.pos(); }
+inline int KBufferCursor::line() const { return Coord.line(); }
+inline KBufferCoord KBufferCursor::coord() const { return Coord; }
+inline bool KBufferCursor::isBehind() const { return Behind; }
+inline int KBufferCursor::realIndex() const { return Behind ? Index + 1 : Index; }
+
+inline void KBufferCursor::stepBehind() { Behind = true; }
+
+//inline bool KBufferCursor::isValid() const { return Index != -1; }
+
+}
+
+#endif
diff --git a/khexedit/lib/kbufferdrag.cpp b/khexedit/lib/kbufferdrag.cpp
new file mode 100644
index 0000000..199982c
--- /dev/null
+++ b/khexedit/lib/kbufferdrag.cpp
@@ -0,0 +1,237 @@
+/***************************************************************************
+ kbufferdrag.cpp - description
+ -------------------
+ begin : Mon Jul 07 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// qt specific
+#include <qcstring.h>
+#include <qtextcodec.h>
+// kde specific
+#include <kglobal.h>
+#include <klocale.h>
+// lib specific
+#include "kbordercoltextexport.h"
+#include "koffsetcoltextexport.h"
+#include "kvaluecoltextexport.h"
+#include "kcharcoltextexport.h"
+#include "kcharcodec.h"
+#include "kbufferdrag.h"
+
+
+using namespace std;
+using namespace KHE;
+
+static const char OctetStream[] = "application/octet-stream";
+static const char TextPlainUTF8[] = "text/plain;charset=UTF-8";
+static const char TextPlain[] = "text/plain";
+static const char TextPlainLocalStub[] = "text/plain;charset=";
+
+//static const char *BaseTypes[3] = { OctetStream, TextPlainUTF8, TextPlain };
+
+// creates the name for the local text/plain
+static const char *localTextPlain()
+{
+ static QCString TextPlainLocal;
+
+ if( TextPlainLocal.isNull() )
+ {
+ TextPlainLocal = QCString(KGlobal::locale()->encoding()).lower();
+ // remove the whitespaces
+ int s;
+ while( (s=TextPlainLocal.find(' ')) >= 0 )
+ TextPlainLocal.remove( s, 1 );
+
+ TextPlainLocal.prepend( TextPlainLocalStub );
+ }
+
+ return TextPlainLocal;
+}
+
+// tries to create a codec by the given charset description
+static QTextCodec* codecForCharset( const QCString& Desc )
+{
+ int i = Desc.find( "charset=" );
+ if( i >= 0 )
+ {
+ QCString CharSetName = Desc.mid( i+8 );
+ // remove any further attributes
+ if( (i=CharSetName.find( ';' )) >= 0 )
+ CharSetName = CharSetName.left( i );
+
+ // try to find codec
+ return QTextCodec::codecForName( CharSetName );
+ }
+ // no charset=, use locale
+ return KGlobal::locale()->codecForEncoding();
+}
+
+
+
+KBufferDrag::KBufferDrag( const QByteArray &D, KCoordRange Range,
+ const KOffsetColumn *OC, const KValueColumn *HC, const KCharColumn *TC,
+ QChar SC, QChar UC, const QString &CN,
+ QWidget *Source, const char *Name )
+ :QDragObject( Source, Name ),
+ CoordRange( Range ),
+ NoOfCol( 0 ),
+ SubstituteChar( SC ),
+ UndefinedChar( UC ),
+ CodecName( CN )
+{
+ setData( D );
+
+ // print column wise?
+ if( HC || TC )
+ {
+ if( OC )
+ {
+ Columns[NoOfCol++] = new KOffsetColTextExport( OC );
+ Columns[NoOfCol++] = new KBorderColTextExport();
+ }
+ if( HC )
+ Columns[NoOfCol++] = new KValueColTextExport( HC, Data.data(), CoordRange );
+ if( TC )
+ {
+ if( HC ) Columns[NoOfCol++] = new KBorderColTextExport();
+ Columns[NoOfCol++] = new KCharColTextExport( TC, Data.data(), CoordRange, CodecName );
+ }
+ }
+}
+
+
+KBufferDrag::~KBufferDrag()
+{
+ for( uint i=0; i<NoOfCol; ++i )
+ delete Columns[i];
+}
+
+
+
+void KBufferDrag::setData( const QByteArray &D )
+{
+ Data = D;
+}
+
+
+const char *KBufferDrag::format( int i ) const
+{
+ return( i == 0 ? OctetStream :
+ i == 1 ? TextPlainUTF8 :
+ i == 2 ? TextPlain :
+ i == 3 ? localTextPlain() :
+ 0 );
+}
+
+
+QByteArray KBufferDrag::encodedData( const char *Format ) const
+{
+ if( Format != 0 )
+ {
+ // octet stream wanted?
+ if( qstrcmp(Format,OctetStream) == 0 )
+ return( Data );
+
+ // plain text wanted?
+ if( qstrncmp(Format,TextPlain,10) == 0 )
+ {
+ QCString Output;
+ QTextCodec *TextCodec = codecForCharset( QCString(Format).lower() );
+ if( TextCodec == 0 )
+ return Output;
+
+ QString Text;
+ // plain copy?
+ if( NoOfCol == 0 )
+ {
+ // duplicate the data and substitute all non-printable items with a space
+ KCharCodec *CharCodec = KCharCodec::createCodec( CodecName );
+ static const QChar Tab('\t');
+ static const QChar Return('\n');
+ uint Size = Data.size();
+ Text.setLength( Size );
+
+ for( uint i=0; i<Size; ++i )
+ {
+ KHEChar B = CharCodec->decode( Data[i] );
+
+ Text.at(i) = B.isUndefined() ? KHEChar(UndefinedChar) :
+ (!B.isPrint() && B != Tab && B != Return ) ? KHEChar(SubstituteChar) : B;
+ }
+ // clean up
+ delete CharCodec;
+ }
+ // formatted copy
+ else
+ {
+ // initialize: one for the line's newline \n
+ uint NeededChars = 1;
+ for( uint i=0; i<NoOfCol; ++i )
+ NeededChars += Columns[i]->charsPerLine();
+ // scale with the number of lines
+ NeededChars *= CoordRange.lines();
+ // find out needed size
+ Text.reserve( NeededChars );
+
+ // now fill
+ int l = CoordRange.start().line();
+ for( uint i=0; i<NoOfCol; ++i )
+ Columns[i]->printFirstLine( Text, l );
+ Text.append('\n');
+ for( ++l; l<=CoordRange.end().line(); ++l )
+ {
+ for( uint i=0; i<NoOfCol; ++i )
+ Columns[i]->printNextLine( Text );
+ Text.append('\n');
+ }
+ }
+ // generate the ouput
+ Output = TextCodec->fromUnicode( Text );
+ // fix end
+ //if( TextCodec->mibEnum() != 1000 )
+ //{
+ // Don't include NUL in size (QCString::resize() adds NUL)
+ // ((QByteArray&)Output).resize( Output.length() );
+ //}
+ return Output;
+ }
+ }
+
+ // return empty dummy
+ return QByteArray();
+}
+
+
+
+bool KBufferDrag::canDecode( const QMimeSource* Source )
+{
+ bool c =( Source->provides(OctetStream) /*|| Source->provides(TextPlain)*/ );
+ return c;
+// return( Source->provides(OctetStream) /*|| Source->provides(TextPlain)*/ );
+}
+
+
+bool KBufferDrag::decode( const QMimeSource* Source, QByteArray &Dest )
+{
+// Dest = Source->encodedData( MediaString );
+// return Dest.size() != 0;
+
+ bool CanDecode = Source->provides( OctetStream );
+ if( CanDecode )
+ Dest = Source->encodedData( OctetStream );
+
+ return CanDecode;
+}
+
+#include "kbufferdrag.moc"
diff --git a/khexedit/lib/kbufferdrag.h b/khexedit/lib/kbufferdrag.h
new file mode 100644
index 0000000..86c498f
--- /dev/null
+++ b/khexedit/lib/kbufferdrag.h
@@ -0,0 +1,76 @@
+/***************************************************************************
+ kbufferdrag.h - description
+ -------------------
+ begin : Mon Jul 07 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KBUFFERDRAG_H
+#define KHE_KBUFFERDRAG_H
+
+// qt specific
+#include <qdragobject.h>
+// lib specific
+#include "khe.h"
+#include "kcoordrange.h"
+#include "kcoltextexport.h"
+
+namespace KHE
+{
+
+// class KBorderColumn;
+class KOffsetColumn;
+class KValueColumn;
+class KCharColumn;
+
+typedef KColTextExport* KColTextExportPtr;
+/**
+ *@author Friedrich W. H. Kossebau
+ */
+class KBufferDrag : public QDragObject
+{
+ Q_OBJECT
+
+ public:
+ // TODO: make this call somewhat more generic
+ KBufferDrag( const QByteArray &, KCoordRange Range,
+ const KOffsetColumn *OC, const KValueColumn *HC, const KCharColumn *TC,
+ QChar SC, QChar UC, const QString &CN,
+ QWidget *Source = 0, const char *Name = 0 );
+ ~KBufferDrag();
+
+ public: // QDragObject API
+ virtual const char *format( int i ) const;
+ virtual QByteArray encodedData( const char* ) const;
+
+ public:
+ virtual void setData( const QByteArray &);
+
+ public:
+ static bool canDecode( const QMimeSource* Source );
+ static bool decode( const QMimeSource* Source, QByteArray &Dest );
+
+ protected:
+ QByteArray Data;
+ KCoordRange CoordRange;
+ /** collection of all the columns. All columns will be autodeleted. */
+ KColTextExportPtr Columns[5];
+ uint NoOfCol;
+ QChar SubstituteChar;
+ QChar UndefinedChar;
+ const QString &CodecName;
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/kbufferlayout.cpp b/khexedit/lib/kbufferlayout.cpp
new file mode 100644
index 0000000..a2ea9a0
--- /dev/null
+++ b/khexedit/lib/kbufferlayout.cpp
@@ -0,0 +1,240 @@
+/***************************************************************************
+ kbufferlayout.cpp - description
+ -------------------
+ begin : Thu Jun 12 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#include "kbufferlayout.h"
+
+using namespace KHE;
+
+
+
+KBufferLayout::KBufferLayout( int NoBpL, int SO, int L )
+ : NoOfBytesPerLine( NoBpL ),
+ StartOffset( SO ),
+ Length( L )
+{
+ calcStart();
+ calcEnd();
+}
+
+
+KBufferLayout::~KBufferLayout()
+{
+}
+
+
+bool KBufferLayout::setStartOffset( int SO )
+{
+ // rejecting <0
+ if( SO < 0 )
+ SO = 0;
+
+ if( StartOffset == SO )
+ return false;
+
+ StartOffset = SO;
+
+ calcStart();
+ calcEnd();
+ return true;
+}
+
+
+bool KBufferLayout::setNoOfBytesPerLine( int N )
+{
+ // rejecting <1
+ if( N < 1 )
+ N = 1;
+
+ // no changes?
+ if( NoOfBytesPerLine == N )
+ return false;
+
+ NoOfBytesPerLine = N;
+
+ calcStart();
+ calcEnd();
+ return true;
+}
+
+
+bool KBufferLayout::setLength( int L )
+{
+ // rejecting < 0
+ if( L < 0 )
+ L = 0;
+
+ // no changes?
+ if( Length == L )
+ return false;
+
+ Length = L;
+
+ calcEnd();
+ return true;
+}
+
+
+void KBufferLayout::setNoOfLinesPerPage( int N )
+{
+ NoOfLinesPerPage = N;
+}
+
+
+void KBufferLayout::calcStart()
+{
+ ContentCoords.setStart( KBufferCoord(StartOffset,NoOfBytesPerLine,false) );
+}
+
+
+void KBufferLayout::calcEnd()
+{
+ ContentCoords.setEnd( (Length>0)?KBufferCoord(Length-1+StartOffset,NoOfBytesPerLine,false):
+ KBufferCoord(-1,ContentCoords.start().line()) );
+}
+
+
+int KBufferLayout::indexAtCLineStart( int L ) const
+{
+ return ( L <= ContentCoords.start().line() ) ? 0:
+ ( L > ContentCoords.end().line() ) ? Length-1:
+ L * NoOfBytesPerLine - StartOffset;
+}
+
+
+int KBufferLayout::indexAtCLineEnd( int L ) const
+{
+ return ( L < ContentCoords.start().line() ) ? 0:
+ ( L >= ContentCoords.end().line() ) ? Length-1:
+ (L+1)*NoOfBytesPerLine-StartOffset-1;
+}
+
+
+int KBufferLayout::indexAtCCoord( const KBufferCoord &C ) const
+{
+ int Index = indexAtCoord( C );
+
+ return ( Index <= 0 ) ? 0:
+ ( Index >= Length ) ? Length-1:
+ Index;
+}
+
+
+int KBufferLayout::lineAtCIndex( int Index ) const
+{
+ return ( Index <= 0 ) ? ContentCoords.start().line():
+ ( Index >= Length ) ? ContentCoords.end().line():
+ lineAtIndex(Index);
+}
+
+
+KBufferCoord KBufferLayout::coordOfCIndex( int Index ) const
+{
+ return ( Index <= 0 ) ? ContentCoords.start():
+ ( Index >= Length ) ? ContentCoords.end():
+ coordOfIndex(Index);
+}
+
+
+int KBufferLayout::indexAtLineStart( int L ) const
+{
+ return ( L == ContentCoords.start().line() ) ? 0 : L*NoOfBytesPerLine-StartOffset;
+}
+
+
+int KBufferLayout::indexAtLineEnd( int L ) const
+{
+ return ( L == ContentCoords.end().line() ) ? Length-1 : (L+1)*NoOfBytesPerLine-StartOffset-1;
+}
+
+
+int KBufferLayout::indexAtCoord( const KBufferCoord &C ) const
+{
+ return C.indexByLineWidth( NoOfBytesPerLine ) - StartOffset;
+}
+
+int KBufferLayout::lineAtIndex( int Index ) const
+{
+ return (Index+StartOffset)/NoOfBytesPerLine;
+}
+
+KBufferCoord KBufferLayout::coordOfIndex( int Index ) const
+{
+ return KBufferCoord( Index+StartOffset, NoOfBytesPerLine, false );
+}
+
+
+
+int KBufferLayout::correctIndex( int I ) const
+{
+ return ( I <= 0 ) ? 0:
+ ( I >= Length ) ? Length-1:
+ I;
+}
+
+
+KBufferCoord KBufferLayout::correctCoord( const KBufferCoord &C ) const
+{
+ return ( C <= ContentCoords.start() ) ? ContentCoords.start():
+ ( C >= ContentCoords.end() ) ? ContentCoords.end():
+ ( C.pos() >= NoOfBytesPerLine ) ? KBufferCoord( NoOfBytesPerLine-1, C.line() ):
+ C;
+}
+
+
+bool KBufferLayout::atLineStart( const KBufferCoord &C ) const
+{
+ return ( C.line() == ContentCoords.start().line() ) ? C.pos() == ContentCoords.start().pos():
+ C.pos() == 0;
+}
+
+bool KBufferLayout::atLineEnd( const KBufferCoord &C ) const
+{
+ return ( C.line() == ContentCoords.end().line() ) ? C.pos() == ContentCoords.end().pos():
+ C.pos() == NoOfBytesPerLine-1;
+}
+
+
+KSection KBufferLayout::positions( int Line ) const
+{
+ return KSection( firstPos(Line), lastPos(Line) );
+}
+
+
+int KBufferLayout::firstPos( const KBufferCoord &C ) const
+{
+ return ( ContentCoords.start().isLaterInLineThan(C) ) ? ContentCoords.start().pos() : C.pos();
+}
+
+int KBufferLayout::lastPos( const KBufferCoord &C ) const
+{
+ return ( ContentCoords.end().isPriorInLineThan(C) ) ? ContentCoords.end().pos() : C.pos();
+}
+
+int KBufferLayout::firstPos( int Line ) const
+{
+ return Line == ContentCoords.start().line() ? ContentCoords.start().pos() : 0;
+}
+
+int KBufferLayout::lastPos( int Line ) const
+{
+ return ( Line == ContentCoords.end().line() ) ? ContentCoords.end().pos() : NoOfBytesPerLine-1;
+}
+
+bool KBufferLayout::hasContent( int Line ) const
+{
+ return ContentCoords.includesLine( Line );
+}
diff --git a/khexedit/lib/kbufferlayout.h b/khexedit/lib/kbufferlayout.h
new file mode 100644
index 0000000..c243225
--- /dev/null
+++ b/khexedit/lib/kbufferlayout.h
@@ -0,0 +1,196 @@
+/***************************************************************************
+ kbufferlayout.h - description
+ -------------------
+ begin : Thu Jun 12 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KBUFFERLAYOUT_H
+#define KHE_KBUFFERLAYOUT_H
+
+// lib specific
+#include "kcoordrange.h"
+#include "ksection.h"
+
+namespace KHE {
+
+/**@short the logical layout of a plain buffer view
+ *
+ * Given the values for
+ * * length of the buffer,
+ * * number of bytes per line,
+ * * a possible (relative) offset in the display, and
+ * * the number of lines per page jump
+ * the following values are calculated:
+ * * starting line of display,
+ * * starting position in this line,
+ * * final line of display,
+ * * final position in this line, and
+ * * the total number of lines (is final line +1 or 0)
+ *
+ * This layout sees the buffer as a continous stream of byte,
+ * thus uses each line after the start from the begin to the end.
+ *
+ * If the buffer is empty the end coord will be set one pos left to the start coord
+ * to easen the cursor handling.
+ *
+ *@author Friedrich W. H. Kossebau
+ */
+class KBufferLayout
+{
+ public:
+ KBufferLayout( int NoBpL, int SO, int L );
+ //KBufferLayout();
+ ~KBufferLayout();
+
+
+ public: // given values
+ /** */
+ int startOffset() const;
+ /** returns number of bytes per line */
+ int noOfBytesPerLine() const;
+ /** returns the length of the displayed data (equals Buffer->size()) */
+ int length() const;
+ /** returns number of lines per visual page */
+ int noOfLinesPerPage() const;
+
+ public: // calculated values
+ int startLine() const;
+ int startPos() const;
+ /** returns the coord of the start */
+ KBufferCoord start() const;
+
+ int finalLine() const;
+ int finalPos() const;
+ /** returns the coord of the end */
+ KBufferCoord final() const;
+
+ /** tells how much lines this layout needs (incl. blank leading lines due to StartOffset) */
+ int noOfLines() const;
+
+
+ public: // value calculation service
+ /** calculates the index of the coord
+ * If the coord is before the first coord the first index is returned,
+ * if the coord is behind the last coord the last index is returned
+ */
+ int indexAtCCoord( const KBufferCoord &C ) const;
+ /** calculates the index of the first pos in line.
+ * If the line is below the first line the first index is returned,
+ * if the line is above the last line the last index is returned
+ */
+ int indexAtCLineStart( int L ) const;
+ /** calculates the index of last pos in line
+ * If the line is below the first line the first index is returned,
+ * if the line is above the last line the last index is returned
+ */
+ int indexAtCLineEnd( int L ) const;
+ /** calculates the line in which index is found
+ * If the index is below the first index the first line is returned,
+ * if the index is above the last index the last line is returned
+ */
+ int lineAtCIndex( int Index ) const;
+ /** calculates the coord in which index is found
+ * If the index is below the first index the first coord is returned,
+ * if the index is above the last index the last coord is returned
+ */
+ KBufferCoord coordOfCIndex( int Index ) const;
+
+ /** calculates the index of coord. if coord is invalid the behaviour is undefinded */
+ int indexAtCoord( const KBufferCoord &C ) const;
+ /** calculates the index of the first pos in line. if line is invalid the behaviour is undefinded */
+ int indexAtLineStart( int L ) const;
+ /** calculates the index of last pos in line. if line is invalid the behaviour is undefinded */
+ int indexAtLineEnd( int L ) const;
+ /** calculates the line in which index is found. if index is invalid the behaviour is undefinded */
+ int lineAtIndex( int Index ) const;
+ /** calculates the coord in which index is found. if index is invalid the behaviour is undefinded */
+ KBufferCoord coordOfIndex( int Index ) const;
+
+ /** returns the used positions in line */
+ KSection positions( int Line ) const;
+ /** returns the first Pos in line. if line is invalid the behaviour is undefinded */
+ int firstPos( int Line ) const;
+ /** returns the last Pos in line. if line is invalid the behaviour is undefinded */
+ int lastPos( int Line ) const;
+ /** returns the valid Pos or the first Pos in line. if coord is invalid the behaviour is undefinded */
+ int firstPos( const KBufferCoord &C ) const;
+ /** returns the valid Pos or the last Pos in line. if coord is invalid the behaviour is undefinded */
+ int lastPos( const KBufferCoord &C ) const;
+ /** returns true if the line has content */
+ bool hasContent( int Line ) const;
+ /** returns true if the coord is the first in it's line. if coord is invalid the behaviour is undefinded */
+ bool atLineStart( const KBufferCoord &C ) const;
+ /** returns true if the coord is the last in it's line. if coord is invalid the behaviour is undefinded */
+ bool atLineEnd( const KBufferCoord &C ) const;
+
+ /** returns the index if valid or the nearest valid index */
+ int correctIndex( int I ) const;
+ /** returns the coord if valid or the nearest valid coord */
+ KBufferCoord correctCoord( const KBufferCoord &C ) const;
+
+
+ public: // modification access; return true if changes
+ /** sets StartOffset, returns true if changed */
+ bool setStartOffset( int SO );
+ /** sets number of bytes per line, returns true if changed */
+ bool setNoOfBytesPerLine( int N );
+ /** sets number of lines per page */
+ void setNoOfLinesPerPage( int N );
+ /** sets length of data to display, returns true if changed */
+ bool setLength( int L );
+
+
+ protected:
+ /** calculates the start coord by startoffset and number of bytes per line */
+ void calcStart();
+ /** calculates the final coord by startoffset, length, and number of bytes per line */
+ void calcEnd();
+
+
+ protected:
+ /** how many chars per line */
+ int NoOfBytesPerLine;
+ /** starting offset of the displayed data */
+ int StartOffset;
+ /** length of the displayed buffer */
+ int Length;
+ /** number of lines that are moved by page up/down */
+ int NoOfLinesPerPage;
+
+ protected: // calculated values, buffered
+ /** coord in which the start offset is (starting with 0) */
+// KBufferCoord Start;
+ /** coord in which the last byte is (starting with 0) */
+// KBufferCoord Final;
+ /** */
+ KCoordRange ContentCoords;
+};
+
+
+inline int KBufferLayout::startOffset() const { return StartOffset; }
+inline int KBufferLayout::noOfBytesPerLine() const { return NoOfBytesPerLine; }
+inline int KBufferLayout::length() const { return Length; }
+
+inline KBufferCoord KBufferLayout::final() const { return ContentCoords.end(); }
+inline KBufferCoord KBufferLayout::start() const { return ContentCoords.start(); }
+inline int KBufferLayout::startPos() const { return start().pos(); }
+inline int KBufferLayout::finalPos() const { return final().pos(); }
+inline int KBufferLayout::startLine() const { return start().line(); }
+inline int KBufferLayout::finalLine() const { return final().line(); }
+inline int KBufferLayout::noOfLinesPerPage() const { return NoOfLinesPerPage; }
+inline int KBufferLayout::noOfLines() const { return Length==0?0:final().line()+1; }
+
+}
+
+#endif
diff --git a/khexedit/lib/kbufferranges.cpp b/khexedit/lib/kbufferranges.cpp
new file mode 100644
index 0000000..57fb9c4
--- /dev/null
+++ b/khexedit/lib/kbufferranges.cpp
@@ -0,0 +1,307 @@
+/***************************************************************************
+ kbufferranges.cpp - description
+ -------------------
+ begin : Sun Jun 22 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+//#include <kdebug.h>
+
+// lib specific
+#include "kbufferranges.h"
+
+
+using namespace KHE;
+
+KBufferRanges::KBufferRanges( KBufferLayout *L )
+ : Modified( false ),
+ Layout( L )
+{
+}
+
+
+KBufferRanges::~KBufferRanges()
+{
+}
+
+
+void KBufferRanges::reset()
+{
+ Selection.cancel();
+ FirstWordSelection.unset();
+ Marking.unset();
+ ChangedRanges.clear();
+}
+
+
+void KBufferRanges::setMarking( KSection M )
+{
+ if( Marking == M )
+ return;
+
+ Marking = M;
+ addChangedRange( M );
+}
+
+
+void KBufferRanges::removeFurtherSelections()
+{
+ for( int i = 1; i < noOfSelections(); ++i )
+ removeSelection( i );
+}
+
+
+void KBufferRanges::setSelection( KSection S )
+{
+ bool Changed = Selection.isValid();
+ if( Changed )
+ addChangedRange( Selection );
+ Selection = S;
+ addChangedRange( Selection );
+}
+
+void KBufferRanges::setSelectionStart( int StartIndex )
+{
+ bool Changed = Selection.isValid();
+ if( Changed )
+ addChangedRange( Selection );
+
+ Selection.setStart( StartIndex );
+}
+
+
+void KBufferRanges::setSelectionEnd( int EndIndex )
+{
+ KSection OldSelection = Selection;
+ Selection.setEnd( EndIndex );
+
+ // TODO: think about rather building a diff of the sections
+ if( !OldSelection.isValid() )
+ {
+ addChangedRange( Selection );
+ return;
+ }
+ if( !Selection.isValid() )
+ {
+ addChangedRange( OldSelection );
+ return;
+ }
+
+ if( OldSelection == Selection )
+ return;
+ int CS_;
+ int CE_;
+ // changes at the end?
+ if( Selection.start() == OldSelection.start() )
+ {
+ CS_ = OldSelection.end()+1;
+ CE_ = Selection.end();
+ if( CE_ < CS_ )
+ {
+ CS_ = Selection.end()+1;
+ CE_ = OldSelection.end();
+ }
+ }
+ // changes at the start?
+ else if( Selection.end() == OldSelection.end() )
+ {
+ CS_ = OldSelection.start();
+ CE_ = Selection.start()-1;
+ if( CE_ < CS_ )
+ {
+ CS_ = Selection.start();
+ CE_ = OldSelection.start()-1;
+ }
+ }
+ // change over the anchor
+ else
+ {
+ CS_ = OldSelection.start();
+ CE_ = Selection.end();
+ if( CE_ < CS_ )
+ {
+ CS_ = Selection.start();
+ CE_ = OldSelection.end();
+ }
+ }
+ KSection C( CS_, CE_ );
+
+ bool Changed = C.isValid();
+ if( Changed )
+ addChangedRange( C );
+ return;
+}
+
+
+void KBufferRanges::removeSelection( int id )
+{
+ if( id > 0 )
+ return;
+
+ bool Changed = Selection.isValid();
+ if( Changed )
+ addChangedRange( Selection );
+
+ Selection.cancel();
+ FirstWordSelection.unset();
+}
+
+
+bool KBufferRanges::overlapsSelection( int FirstIndex, int LastIndex, int *SI, int *EI ) const
+{
+ if( Selection.overlaps(KSection(FirstIndex,LastIndex)) )
+ {
+ *SI = Selection.start();
+ *EI = Selection.end();
+ return true;
+ }
+ return false;
+}
+
+
+bool KBufferRanges::overlapsMarking( int FirstIndex, int LastIndex, int *SI, int *EI ) const
+{
+ if( Marking.overlaps(KSection(FirstIndex,LastIndex)) )
+ {
+ *SI = Marking.start();
+ *EI = Marking.end();
+ return true;
+ }
+ return false;
+}
+
+
+const KSection *KBufferRanges::firstOverlappingSelection( KSection Range ) const
+{
+ if( Selection.overlaps(Range) )
+ return &Selection;
+
+ return 0L;
+}
+
+
+const KSection *KBufferRanges::overlappingMarking( KSection Range ) const
+{
+ if( Marking.overlaps(Range) )
+ return &Marking;
+
+ return 0L;
+}
+
+/*
+bool KBufferRanges::overlapsChanges( int FirstIndex, int LastIndex, int *SI, int *EI ) const
+{
+ for( KCoordRangeList::const_iterator S=ChangedRanges.begin(); S!=ChangedRanges.end(); ++S )
+ {
+ if( (*S).overlaps(KBuff(FirstIndex,LastIndex)) )
+ {
+ *SI = (*S).start();
+ *EI = (*S).end();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool KBufferRanges::overlapsChanges( KSection Indizes, KSection *ChangedRange ) const
+{
+ for( KSectionList::const_iterator S=ChangedRanges.begin(); S!=ChangedRanges.end(); ++S )
+ {
+ if( (*S).overlaps(Indizes) )
+ {
+ *ChangedRange = *S;
+ return true;
+ }
+ }
+
+ return false;
+}
+*/
+bool KBufferRanges::overlapsChanges( const KCoordRange &Range, KCoordRange *ChangedRange ) const
+{
+ // TODO: add a lastusedrange pointer for quicker access
+ for( KCoordRangeList::const_iterator R=ChangedRanges.begin(); R!=ChangedRanges.end(); ++R )
+ {
+ if( (*R).overlaps(Range) )
+ {
+ *ChangedRange = *R;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+void KBufferRanges::addChangedRange( int SI, int EI )
+{
+ addChangedRange( KSection(SI,EI) );
+}
+
+
+void KBufferRanges::addChangedRange( KSection S )
+{
+ addChangedRange( KCoordRange(Layout->coordOfIndex(S.start()),Layout->coordOfIndex(S.end())) );
+}
+
+
+void KBufferRanges::addChangedRange( const KCoordRange &NewRange )
+{
+ ChangedRanges.addCoordRange( NewRange );
+
+ Modified = true;
+}
+
+
+void KBufferRanges::removeMarking()
+{
+ bool Changed = Marking.isValid();
+ if( Changed )
+ addChangedRange( Marking );
+
+ Marking.unset();
+}
+
+
+void KBufferRanges::resetChangedRanges()
+{
+ ChangedRanges.clear();
+ Modified = false;
+}
+
+
+void KBufferRanges::setFirstWordSelection( KSection Section )
+{
+ FirstWordSelection = Section;
+ setSelection( FirstWordSelection );
+}
+
+ void KBufferRanges::ensureWordSelectionForward( bool Forward )
+ {
+ // in the anchor not on the right side?
+ if( Selection.isForward() != Forward )
+ {
+ if( Forward )
+ {
+ setSelectionEnd( FirstWordSelection.start() );
+ Selection.setForward();
+ }
+ else
+ {
+ setSelectionEnd( FirstWordSelection.end()+1 );
+ Selection.setBackward();
+ }
+ }
+ }
+
diff --git a/khexedit/lib/kbufferranges.h b/khexedit/lib/kbufferranges.h
new file mode 100644
index 0000000..ed2cbce
--- /dev/null
+++ b/khexedit/lib/kbufferranges.h
@@ -0,0 +1,130 @@
+/***************************************************************************
+ kbufferranges.h - description
+ -------------------
+ begin : Sun Jun 22 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KBUFFERRANGES_H
+#define KHE_KBUFFERRANGES_H
+
+// lib specific
+#include "kbufferlayout.h"
+#include "kselection.h"
+#include "ksectionlist.h"
+#include "kcoordrangelist.h"
+
+namespace KHE
+{
+
+/** a class to control all the ranges like marking and selections
+ * holds also all modified ranges and merges them so a repaint can take its info from here
+ *
+ * @author Friedrich W. H. Kossebau
+ */
+class KBufferRanges
+{
+ public:
+ KBufferRanges( KBufferLayout *L );
+ ~KBufferRanges();
+
+ public: // modifcation access
+ void setMarking( KSection M );
+ void setSelectionStart( int StartIndex );
+ void setSelectionEnd( int StartIndex );
+ void setSelection( KSection S );
+ /** */
+ void setFirstWordSelection( KSection S );
+ /** */
+ void ensureWordSelectionForward( bool Forward );
+
+ /** removes marking and returns true if something changed */
+ void removeMarking();
+ /** removes selection with id and returns true if something changed */
+ void removeSelection( int id = 0 );
+ /** removes all but the standard selection and returns true if something changed */
+ void removeFurtherSelections();
+
+ void addChangedRange( KSection S );
+ void addChangedRange( int SI, int EI );
+ void addChangedRange( const KCoordRange &NewRange );
+ void resetChangedRanges();
+
+ void setModified( bool M = true );
+ /** removes all ranges */
+ void reset();
+
+ public: // value access
+ int noOfSelections() const;
+ int selectionStart() const;
+ int selectionEnd() const;
+ KSection selection() const;
+ KSection firstWordSelection() const;
+ int selectionLength() const;
+ bool isModified() const;
+
+ public: // calculated logic access
+ bool hasSelection() const;
+ bool hasMarking() const;
+ bool selectionStarted() const;
+ bool selectionJustStarted() const;
+ bool hasFirstWordSelection() const;
+ bool selectionIncludes( int Index ) const;
+ bool markingIncludes( int Index ) const;
+ // TODO: next three are deprecated
+ bool overlapsSelection( int FirstIndex, int LastIndex, int *SI, int *EI ) const;
+ bool overlapsMarking( int FirstIndex, int LastIndex, int *SI, int *EI ) const;
+// bool overlapsChanges( int FirstIndex, int LastIndex, int *SI, int *EI ) const;
+// bool overlapsChanges( KSection Indizes, KSection *ChangedRange ) const;
+ bool overlapsChanges( const KCoordRange &Range, KCoordRange *ChangedRange ) const;
+ const KSection *firstOverlappingSelection( KSection Range ) const;
+ const KSection *overlappingMarking( KSection Range ) const;
+
+
+ protected:
+ /** true if something changed */
+ bool Modified;
+
+ KSection Marking;
+ KSelection Selection;
+ /** memories first selected word on wordwise selection */
+ KSection FirstWordSelection;
+
+ KCoordRangeList ChangedRanges;
+
+ KBufferLayout *Layout;
+};
+
+
+inline int KBufferRanges::noOfSelections() const { return 1; }
+
+inline int KBufferRanges::selectionStart() const { return Selection.start(); }
+inline int KBufferRanges::selectionEnd() const { return Selection.end(); }
+inline KSection KBufferRanges::selection() const { return Selection; }
+inline KSection KBufferRanges::firstWordSelection() const { return FirstWordSelection; }
+inline int KBufferRanges::selectionLength() const { return Selection.width(); }
+inline bool KBufferRanges::isModified() const { return Modified; }
+
+inline bool KBufferRanges::hasSelection() const { return Selection.isValid(); }
+inline bool KBufferRanges::selectionStarted() const { return Selection.started(); }
+inline bool KBufferRanges::selectionJustStarted() const { return Selection.justStarted(); }
+inline bool KBufferRanges::hasFirstWordSelection() const { return FirstWordSelection.isValid(); }
+inline bool KBufferRanges::hasMarking() const { return Marking.isValid(); }
+inline bool KBufferRanges::selectionIncludes( int Index ) const { return Selection.includes( Index ); }
+inline bool KBufferRanges::markingIncludes( int Index ) const { return Marking.includes( Index ); }
+
+inline void KBufferRanges::setModified( bool M ) { Modified = M; }
+
+}
+
+#endif
diff --git a/khexedit/lib/kbytecodec.h b/khexedit/lib/kbytecodec.h
new file mode 100644
index 0000000..fc4e1b3
--- /dev/null
+++ b/khexedit/lib/kbytecodec.h
@@ -0,0 +1,73 @@
+/***************************************************************************
+ kbytecodec.h - description
+ -------------------
+ begin : Sam Mai 17 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KBYTECODEC_H
+#define KHE_KBYTECODEC_H
+
+#include "khe.h"
+#include <qstring.h>
+
+namespace KHE
+{
+
+/** class that is able to convert codings to and from
+ * hexadecimal, decimal, octal, and binary
+ *
+ * the buffer will be always filled up to CodingWidth, if not using shortCodingFunction
+ * a closing '\0' will be always added
+ *
+ *@author Friedrich W. H. Kossebau
+ */
+
+class KByteCodec
+{
+ public:
+ static KByteCodec *createCodec( KCoding C );
+
+
+ protected: // hiding, as this class should never be instanciated
+ KByteCodec() {}
+
+ public: // API to be implemented
+ /** */
+ virtual unsigned int encodingWidth() const = 0;
+ /** */
+ virtual unsigned char digitsFilledLimit() const = 0;
+
+ /** encodes the Char and writes the result to */
+ virtual void encode( QString &Digits, unsigned int Pos, const unsigned char Char ) const = 0;
+ /** */
+ virtual void encodeShort( QString &Digits, unsigned int Pos, const unsigned char Char ) const = 0;
+
+ /** */
+ virtual bool appendDigit( unsigned char *Byte, const unsigned char Digit ) const = 0;
+ /** */
+ virtual void removeLastDigit( unsigned char *Byte ) const = 0;
+ /** */
+ virtual bool isValidDigit( const unsigned char Digit ) const = 0;
+ /** */
+ virtual bool turnToValue( unsigned char *Digit ) const = 0;
+
+
+ public:
+ /** */
+ uint decode( unsigned char *Char, const QString &Digits, uint Pos ) const;
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/kbytesedit.cpp b/khexedit/lib/kbytesedit.cpp
new file mode 100644
index 0000000..40b57a1
--- /dev/null
+++ b/khexedit/lib/kbytesedit.cpp
@@ -0,0 +1,162 @@
+/***************************************************************************
+ kbytesedit.cpp - description
+ -------------------
+ begin : Die Jul 9 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// lib specific
+#include "kplainbuffer.h"
+#include "kbytesedit.h"
+#include "kbufferranges.h"
+#include "kbuffercursor.h"
+
+using namespace KHE;
+
+
+KBytesEdit::KBytesEdit( char *D, int DS_, int RS_, bool KM, QWidget *Parent, const char *Name, WFlags F )
+ : KHexEdit( 0L, Parent, Name, F ),
+ AutoDelete( false )
+{
+ setData( D, DS_, RS_, KM );
+}
+
+KBytesEdit::KBytesEdit( char *D, int DS_, QWidget *Parent, const char *Name, WFlags F )
+ : KHexEdit( 0L, Parent, Name, F ),
+ AutoDelete( false )
+{
+ setData( D, DS_ );
+}
+
+
+KBytesEdit::KBytesEdit( QWidget *Parent, const char *Name, WFlags F )
+ : KHexEdit( 0L, Parent, Name, F ),
+ AutoDelete( false )
+{
+ setDataBuffer( new KPlainBuffer() );
+}
+
+KBytesEdit::~KBytesEdit()
+{
+ clean();
+}
+
+void KBytesEdit::setReadOnly( bool RO )
+{
+ KPlainBuffer *Buffer = dynamic_cast<KPlainBuffer *>(DataBuffer);
+ if( Buffer )
+ Buffer->setReadOnly( RO );
+ KHexEdit::setReadOnly( RO );
+}
+
+
+void KBytesEdit::setAutoDelete( bool AD )
+{
+ AutoDelete = AD;
+}
+
+
+char *KBytesEdit::data() const
+{
+ KPlainBuffer *Buffer = dynamic_cast<KPlainBuffer *>(DataBuffer);
+ return Buffer ? Buffer->data() : 0L;
+}
+
+
+void KBytesEdit::setData( char *D, int S, int RS_, bool KM )
+{
+ KPlainBuffer *NewBuffer = new KPlainBuffer( D, S, RS_, KM );
+ if( DataBuffer )
+ {
+ // take the settings
+ NewBuffer->setReadOnly( DataBuffer->isReadOnly() );
+ clean();
+ }
+ else
+ NewBuffer->setReadOnly( isReadOnly() );
+
+ setDataBuffer( NewBuffer );
+}
+
+
+int KBytesEdit::dataSize() const
+{
+ KPlainBuffer *Buffer = dynamic_cast<KPlainBuffer *>(DataBuffer);
+ return Buffer ? Buffer->size() : -1;
+}
+
+
+int KBytesEdit::maxDataSize() const
+{
+ KPlainBuffer *Buffer = dynamic_cast<KPlainBuffer *>(DataBuffer);
+ return Buffer ? Buffer->maxSize() : -1;
+}
+
+
+void KBytesEdit::setMaxDataSize( int MS )
+{
+ KPlainBuffer *Buffer = dynamic_cast<KPlainBuffer *>(DataBuffer);
+ if( Buffer )
+ Buffer->setMaxSize( MS );
+}
+
+
+bool KBytesEdit::keepsMemory() const
+{
+ KPlainBuffer *Buffer = dynamic_cast<KPlainBuffer *>(DataBuffer);
+ return Buffer ? Buffer->keepsMemory() : false;
+}
+
+
+void KBytesEdit::setKeepsMemory( bool KM )
+{
+ KPlainBuffer *Buffer = dynamic_cast<KPlainBuffer *>(DataBuffer);
+ if( Buffer )
+ Buffer->setKeepsMemory( KM );
+}
+
+
+bool KBytesEdit::isAutoDelete() const { return AutoDelete; }
+
+
+void KBytesEdit::repaintRange( int i1, int i2 )
+{
+ bool ChangeCursor = !(CursorPaused) && KSection(i1,i2).includes( BufferCursor->index() );
+ if( ChangeCursor )
+ pauseCursor();
+
+ BufferRanges->addChangedRange( i1, i2 );
+
+ repaintChanged();
+
+ if( ChangeCursor )
+ unpauseCursor();
+}
+
+
+void KBytesEdit::clean()
+{
+ if( DataBuffer )
+ {
+ if( AutoDelete )
+ {
+ char *D = data();
+ if( D )
+ delete [] D;
+ }
+ delete DataBuffer;
+ }
+}
+
+
+#include "kbytesedit.moc"
diff --git a/khexedit/lib/kbytesedit.h b/khexedit/lib/kbytesedit.h
new file mode 100644
index 0000000..daf8b6e
--- /dev/null
+++ b/khexedit/lib/kbytesedit.h
@@ -0,0 +1,163 @@
+/***************************************************************************
+ kbytesedit.h - description
+ -------------------
+ begin : Die Jul 9 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KBYTESEDIT_H
+#define KHE_KBYTESEDIT_H
+
+
+#include "khexedit.h"
+
+#include <khexedit_export.h>
+
+namespace KHE
+{
+
+class KDataBuffer;
+class KBytesEditPrivate;
+
+/** the beginner's hex edit widget ;)
+ *
+ * It hides the concept of the KDataBuffer and accepts a pure pointer
+ * to a reasonable large array of bytes
+ *
+ * 1. used as viewer
+ * a) static data ranges -> no changes for data pointer and length
+ * possible changes are told to the widget by repaintRange
+ * b) changing data ranges -> data pointer and length might change
+ * changes told by
+ * * resetData( char *, int size, bool repaint );
+ * *
+ * 2. used as editor
+ * a) static data ranges
+ * data pointer stays the same
+ * b) changing data ranges
+ * pointer to the data changes in charge of the widget:
+ * given pointer and intermediate pointer are possibly invalid
+ * problem: who cares about the array if the data is deleted?
+ * -> solved by setAutoDelete()
+ *
+ *
+ *@author Friedrich W. H. Kossebau
+ */
+//TODO: give the bytes edit widget an empty buffer as default
+class KHEXEDIT_EXPORT KBytesEdit : public KHexEdit
+{
+ Q_OBJECT
+ //_PROPERTY( char * Data READ data )
+ Q_PROPERTY( int DataSize READ dataSize )
+ Q_PROPERTY( int MaxDataSize READ maxDataSize WRITE setMaxDataSize )
+ Q_PROPERTY( bool AutoDelete READ isAutoDelete WRITE setAutoDelete DESIGNABLE false )
+
+
+ public:
+ /** creates a new widget to view/edit data
+ * @param D pointer to memory
+ * @param S size of used memory
+ * @param RS_ real size of the memory
+ * @param KM keep the memory on resize (RS_ is then the maximum size)
+ * @param Parent parent widget
+ * @param Name name for this widget
+ * @param F flags
+ */
+ KBytesEdit( char *D, int DS_, int RS_, bool KM, QWidget *Parent = 0, const char *Name = 0, WFlags F = 0 );
+ /** hands over to the editor a new byte array.
+ * If there exists an old one and autodelete is set the old one gets deleted.
+ * @param D pointer to memory
+ * @param S size of used memory
+ * @param RS_ real size of the memory
+ * @param KM keep the memory on resize (RS_ is the maximum size)
+ */
+ KBytesEdit( char *D, int DS_, QWidget *Parent = 0, const char *Name = 0, WFlags F = 0 );
+ /** hands over to the editor a new byte array.
+ * If there exists an old one and autodelete is set the old one gets deleted.
+ * @param D pointer to memory
+ * @param S size of used memory
+ * @param RS_ real size of the memory
+ * @param KM keep the memory on resize (RS_ is the maximum size)
+ */
+ KBytesEdit( QWidget *Parent = 0, const char *Name = 0, WFlags F = 0 );
+ virtual ~KBytesEdit();
+
+
+ public: // value access
+ /** returns the pointer to the actual byte array. This can be but must not be the one
+ * that was given in the constructor.
+ */
+ char *data() const;
+ /** returns the size of the actual byte array */
+ int dataSize() const;
+ /** returns the maximal allowed size for the byte array */
+ int maxDataSize () const;
+ /** returns whether autodelete is set for the byte array */
+ bool isAutoDelete() const;
+ /** returns whether the memory of the byte array is kept */
+ bool keepsMemory() const;
+
+ public: // logic value service
+
+ public: // modification access
+
+ public slots:
+ /** hands over to the editor a new byte array.
+ * If there exists an old one and autodelete is set the old one gets deleted.
+ * @param D pointer to memory
+ * @param S size of used memory
+ * @param RS_ real size of the memory
+ * @param KM keep the memory on resize (RS_ is the maximum size)
+ */
+ void setData( char *D, int S, int RS_ = -1, bool KM = true );
+
+ /** sets whether the given array should be handled read only or not */
+ virtual void setReadOnly( bool RO = true );
+ /** sets the maximal size of the actual byte array. If the actual array is already larger
+ * it will not be modified but there can be only done non-inserting actions
+ * until the array's is below the limit
+ */
+ void setMaxDataSize( int MS );
+ /** sets whether the array should be deleted on the widget's end or if a new array is set.
+ * Default is false
+ */
+ void setAutoDelete( bool AD = true );
+ /** sets whether the memory given by setData or in the constructor should be kept on resize
+ */
+ void setKeepsMemory( bool KM = true );
+
+ /** repaint the indizes from i1 to i2 */
+ void repaintRange( int i1, int i2 );
+
+ protected:
+ /** deletes the databuffer */
+ void clean();
+
+
+ protected slots:
+
+
+ protected:
+ /** */
+ bool AutoDelete:1;
+ /** */
+ KBytesEditPrivate *d;
+
+ private: // Disabling copy constructor and operator= - not useful
+ KBytesEdit( const KBytesEdit & );
+ KBytesEdit &operator=( const KBytesEdit & );
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/kcharcodec.h b/khexedit/lib/kcharcodec.h
new file mode 100644
index 0000000..9d1b628
--- /dev/null
+++ b/khexedit/lib/kcharcodec.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+ kcharcodec.h - description
+ -------------------
+ begin : Do Nov 25 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KCHARCODEC_H
+#define KHE_KCHARCODEC_H
+
+// qt specific
+#include <qstringlist.h>
+// lib specific
+#include "khe.h"
+#include "khechar.h"
+#include "khexedit_export.h"
+
+
+namespace KHE
+{
+
+class KHEXEDIT_EXPORT KCharCodec
+{
+ public:
+ /** */
+ static KCharCodec* createCodec( KEncoding E );
+ /** */
+ static KCharCodec* createCodec( const QString &Name );
+
+ static const QStringList &codecNames();
+
+ public: // API to be implemented
+ virtual KHEChar decode( char Byte ) const = 0;
+ virtual bool encode( char *D, const QChar &C ) const = 0;
+ virtual const QString& name() const = 0;
+
+ protected:
+ /** */
+ static QStringList CodecNames;
+};
+
+}
+
+#endif
+
diff --git a/khexedit/lib/kcharcoltextexport.cpp b/khexedit/lib/kcharcoltextexport.cpp
new file mode 100644
index 0000000..bc4a60e
--- /dev/null
+++ b/khexedit/lib/kcharcoltextexport.cpp
@@ -0,0 +1,71 @@
+/***************************************************************************
+ kcharcoltextexport.cpp - description
+ -------------------
+ begin : Wed Sep 03 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// lib specific
+#include "kbufferlayout.h"
+#include "kcharcolumn.h"
+#include "kcharcodec.h"
+#include "kcharcoltextexport.h"
+
+using namespace KHE;
+
+
+KCharColTextExport::KCharColTextExport( const KCharColumn* TC, const char *D, KCoordRange CR, const QString &CodecName )
+ : KBufferColTextExport( TC, D, CR, 1 ),
+ CharCodec( KCharCodec::createCodec(CodecName) ),
+ SubstituteChar( TC->substituteChar() ),
+ UndefinedChar( TC->undefinedChar() )
+{
+}
+
+
+KCharColTextExport::~KCharColTextExport()
+{
+ delete CharCodec;
+}
+
+
+void KCharColTextExport::print( QString &T ) const
+{
+ int p = 0;
+ int pEnd = NoOfBytesPerLine;
+ // correct boundaries
+ if( PrintLine == CoordRange.start().line() )
+ p = CoordRange.start().pos();
+ if( PrintLine == CoordRange.end().line() )
+ pEnd = CoordRange.end().pos()+1;
+
+ // draw individual chars
+ uint e = 0;
+ for( ; p<pEnd; ++p, ++PrintData )
+ {
+ // get next position
+ uint t = Pos[p];
+ // clear spacing
+ T.append( whiteSpace(t-e) );
+
+ // print char
+ KHEChar B = CharCodec->decode( *PrintData );
+
+ T.append( B.isUndefined() ? KHEChar(UndefinedChar) : !B.isPrint() ? KHEChar(SubstituteChar) : B );
+ e = t + 1;
+ }
+
+ T.append( whiteSpace(NoOfCharsPerLine-e) );
+
+ ++PrintLine;
+}
diff --git a/khexedit/lib/kcharcoltextexport.h b/khexedit/lib/kcharcoltextexport.h
new file mode 100644
index 0000000..05a570c
--- /dev/null
+++ b/khexedit/lib/kcharcoltextexport.h
@@ -0,0 +1,50 @@
+/***************************************************************************
+ kcharcoltextexport.h - description
+ -------------------
+ begin : Wed Sep 3 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KCHARCOLTEXTEXPORT_H
+#define KHE_KCHARCOLTEXTEXPORT_H
+
+// lib specific
+#include "khe.h"
+#include "kbuffercoltextexport.h"
+
+
+namespace KHE
+{
+
+class KCharColumn;
+class KCharCodec;
+
+
+class KCharColTextExport : public KBufferColTextExport
+{
+ public:
+ KCharColTextExport( const KCharColumn* BF, const char *D, KCoordRange CR, const QString &CodecName );
+ virtual ~KCharColTextExport();
+
+ protected: //API
+ virtual void print( QString &T ) const;
+
+ protected:
+ KCharCodec *CharCodec;
+ QChar SubstituteChar;
+ QChar UndefinedChar;
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/kcharcolumn.cpp b/khexedit/lib/kcharcolumn.cpp
new file mode 100644
index 0000000..9ecbd5a
--- /dev/null
+++ b/khexedit/lib/kcharcolumn.cpp
@@ -0,0 +1,61 @@
+/***************************************************************************
+ kcharcolumn.cpp - description
+ -------------------
+ begin : Mit Sep 3 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// c specific
+#include <ctype.h>
+// qt specific
+#include <qpainter.h>
+// kde specific
+#include <kcharsets.h>
+#include <klocale.h>
+#include <kglobal.h>
+// lib specific
+#include "kcolumnsview.h"
+#include "kbuffercursor.h"
+#include "kbufferlayout.h"
+#include "kbufferranges.h"
+#include "kcharcolumn.h"
+
+using namespace KHE;
+
+static const bool DefaultShowUnprintable = false;
+static const QChar DefaultSubstituteChar = (char)'.';
+static const QChar DefaultUndefinedChar = (char)'?';
+
+
+KCharColumn::KCharColumn( KColumnsView *CV, KDataBuffer *B, KBufferLayout *L, KBufferRanges *R )
+ : KBufferColumn( CV, B, L, R ),
+ ShowUnprintable( DefaultShowUnprintable ),
+ SubstituteChar( DefaultSubstituteChar ),
+ UndefinedChar( DefaultUndefinedChar )
+{
+ setSpacing( 0, 0, 0 );
+}
+
+
+KCharColumn::~KCharColumn()
+{
+}
+
+void KCharColumn::drawByte( QPainter *P, char /*Byte*/, KHEChar B, const QColor &Color ) const
+{
+ // make a drawable String out of it
+ QString BS( B.isUndefined() ? KHEChar(UndefinedChar) : ( !(ShowUnprintable || B.isPrint()) ? KHEChar(SubstituteChar) : B ));
+
+ P->setPen( Color );
+ P->drawText( 0, DigitBaseLine, BS );
+}
diff --git a/khexedit/lib/kcharcolumn.h b/khexedit/lib/kcharcolumn.h
new file mode 100644
index 0000000..1e875b0
--- /dev/null
+++ b/khexedit/lib/kcharcolumn.h
@@ -0,0 +1,116 @@
+/***************************************************************************
+ kcharcolumn.h - description
+ -------------------
+ begin : Mit Sep 3 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KCHARCOLUMN_H
+#define KHE_KCHARCOLUMN_H
+
+// qt specific
+#include <qstring.h>
+// lib specific
+#include "kbuffercolumn.h"
+
+class QPainter;
+class QColor;
+
+
+namespace KHE
+{
+
+
+/** buffer column that interprets the bytes as chars
+ *
+ *@author Friedrich W. H. Kossebau
+ */
+class KCharColumn : public KBufferColumn
+{
+ public:
+ KCharColumn( KColumnsView *CV, KDataBuffer *B, KBufferLayout *L, KBufferRanges *R );
+ virtual ~KCharColumn();
+
+
+ public: // modification access
+ /** sets whether "unprintable" chars (>32) should be displayed in the char column
+ * with their corresponding character.
+ * @param SU
+ * returns true if there was a change
+ */
+ bool setShowUnprintable( bool SU = true );
+ /** sets the substitute character for "unprintable" chars
+ * returns true if there was a change
+ */
+ bool setSubstituteChar( QChar SC );
+ /** sets the undefined character for "undefined" chars
+ * returns true if there was a change
+ */
+ bool setUndefinedChar( QChar UC );
+
+
+ public: // value access
+ /** returns true if "unprintable" chars (>32) are displayed in the char column
+ * with their corresponding character, default is false
+ */
+ bool showUnprintable() const;
+ /** returns the actually used substitute character for "unprintable" chars, default is '.' */
+ QChar substituteChar() const;
+ /** returns the actually used undefined character for "undefined" chars, default is '?' */
+ QChar undefinedChar() const;
+
+
+ protected: // KBufferColumn API
+ virtual void drawByte( QPainter *P, char Byte, KHEChar B, const QColor &Color ) const;
+
+ protected:
+ /** */
+ bool ShowUnprintable;
+ /** */
+ QChar SubstituteChar;
+ /** */
+ QChar UndefinedChar;
+};
+
+
+inline bool KCharColumn::showUnprintable() const { return ShowUnprintable; }
+inline QChar KCharColumn::substituteChar() const { return SubstituteChar; }
+inline QChar KCharColumn::undefinedChar() const { return UndefinedChar; }
+
+inline bool KCharColumn::setSubstituteChar( QChar SC )
+{
+ if( SubstituteChar == SC )
+ return false;
+ SubstituteChar = SC;
+ return true;
+}
+
+inline bool KCharColumn::setUndefinedChar( QChar UC )
+{
+ if( UndefinedChar == UC )
+ return false;
+ UndefinedChar = UC;
+ return true;
+}
+
+inline bool KCharColumn::setShowUnprintable( bool SU )
+{
+ if( ShowUnprintable == SU )
+ return false;
+ ShowUnprintable = SU;
+ return true;
+}
+
+}
+
+#endif
diff --git a/khexedit/lib/kcoltextexport.h b/khexedit/lib/kcoltextexport.h
new file mode 100644
index 0000000..d0b3918
--- /dev/null
+++ b/khexedit/lib/kcoltextexport.h
@@ -0,0 +1,40 @@
+/***************************************************************************
+ kcoltextexport.h - description
+ -------------------
+ begin : Sam Aug 30 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KCOLTEXTEXPORT_H
+#define KHE_KCOLTEXTEXPORT_H
+
+class QString;
+
+namespace KHE
+{
+/**
+ * interface for the text export of columns
+ * @author Friedrich W. H. Kossebau <Friedrich.W.H@Kossebau.de>
+ */
+class KColTextExport
+{
+ public: // API
+ virtual void printFirstLine( QString &T, int Line ) const = 0;
+ virtual void printNextLine( QString &T ) const = 0;
+ /** tells how much chars per line are needed */
+ virtual int charsPerLine() const = 0;
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/kcolumn.cpp b/khexedit/lib/kcolumn.cpp
new file mode 100644
index 0000000..f9b0ce5
--- /dev/null
+++ b/khexedit/lib/kcolumn.cpp
@@ -0,0 +1,60 @@
+/***************************************************************************
+ kcolumn.cpp - description
+ -------------------
+ begin : Mit Mai 21 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// qt specific
+#include <qpainter.h>
+// lib specific
+#include "kcolumnsview.h"
+#include "kcolumn.h"
+
+using namespace KHE;
+
+
+KColumn::KColumn( KColumnsView *V )
+ : View( V ),
+ Visible( true ), //TODO: would false be better?
+ LineHeight( V->lineHeight() ),
+ XSpan( 0,0,true )
+{
+ V->addColumn( this );
+}
+
+
+void KColumn::paintFirstLine( QPainter *P, KPixelXs, int /*FirstLine*/ )
+{
+ paintBlankLine( P );
+}
+
+
+void KColumn::paintNextLine( QPainter *P )
+{
+ paintBlankLine( P );
+}
+
+
+void KColumn::paintBlankLine( QPainter *P ) const
+{
+ if( LineHeight > 0 )
+ P->fillRect( 0,0,width(),LineHeight, View->backgroundBrush() );
+}
+
+
+void KColumn::paintEmptyColumn( QPainter *P, KPixelXs Xs, KPixelYs Ys )
+{
+ Xs.restrictTo( XSpan );
+ P->fillRect( Xs.start(), Ys.start(), Xs.width(), Ys.width(), View->backgroundBrush() );
+}
diff --git a/khexedit/lib/kcolumn.h b/khexedit/lib/kcolumn.h
new file mode 100644
index 0000000..37c3118
--- /dev/null
+++ b/khexedit/lib/kcolumn.h
@@ -0,0 +1,126 @@
+/***************************************************************************
+ kcolumn.h - description
+ -------------------
+ begin : Mit Mai 21 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KCOLUMN_H
+#define KHE_KCOLUMN_H
+
+
+// lib specific
+#include "kadds.h"
+#include "ksection.h"
+
+class QPainter;
+
+namespace KHE
+{
+
+class KColumnsView;
+
+/** base class for columns of the KColumnsView
+ *
+ *
+ *@author Friedrich W. H. Kossebau
+ */
+
+class KColumn
+{
+// friend class KColumnsView;
+ public:
+ KColumn( KColumnsView *V );
+ virtual ~KColumn() {}
+
+
+ public: // API to be reimplemented in the subclasses
+ /** Before an update of the columns view each column that intersects with the area to be painted
+ * will be called with this function. As often multiple lines of a column are affected
+ * for each lines the same values (like first and last char positions) might be calculated.
+ * This function enables a one-time-calculation for such data that must be stored in some
+ * class members, though.
+ * @param P painter variable
+ * @param cx
+ * @param cw
+ * @param FirstLine no of the first of the range of lines to paint
+ */
+ virtual void paintFirstLine( QPainter *P, KPixelXs Xs, int FirstLine );
+ /** the actual painting call for a column's line.
+ * The default implementation simply paints the background
+ */
+ virtual void paintNextLine( QPainter *P );
+
+ /** */
+ virtual void paintEmptyColumn( QPainter *P, KPixelXs Xs, KPixelYs Ys );
+
+ public: // modification access
+ /** sets starting point of the column */
+ void setX( KPixelX NewX );
+ /** sets visibily */
+ void setVisible( bool V );
+ /** buffer actual line height in column */
+ void setLineHeight( KPixelY H );
+
+ public: // value access
+ /** left offset x in pixel */
+ KPixelX x() const;
+ /** total width in pixel */
+ KPixelX width() const;
+ /** right offset x in pixel */
+ KPixelX rightX() const;
+ /** should Column be displayed? */
+ bool isVisible() const;
+ /** convinience: returns width if visible else 0 */
+ KPixelX visibleWidth() const;
+
+ public: // functional logic
+ /** true if column overlaps with pixels between x-positions x1, x2 */
+ bool overlaps( KPixelXs Xs ) const;
+
+ protected:
+ /** sets width of the column */
+ void setWidth( KPixelX W );
+ /** */
+ void paintBlankLine( QPainter *P ) const;
+
+ protected: // general column data
+ /** pointer to the view */
+ KColumnsView *View;
+ /** should Column be displayed? */
+ bool Visible;
+
+ /** buffered value */
+ KPixelY LineHeight;
+
+ /** left offset x in pixel */
+ KPixelXs XSpan;
+};
+
+
+inline KPixelX KColumn::x() const { return XSpan.start(); }
+inline KPixelX KColumn::rightX() const { return XSpan.end(); }
+inline KPixelX KColumn::width() const { return XSpan.width(); }
+inline bool KColumn::isVisible() const { return Visible; }
+inline KPixelX KColumn::visibleWidth() const { return Visible ? XSpan.width(): 0; }
+
+inline void KColumn::setX( KPixelX NewX ) { XSpan.moveToStart( NewX ); }
+inline void KColumn::setWidth( KPixelX W ) { XSpan.setEndByWidth( W ); }
+inline void KColumn::setVisible( bool V ) { Visible = V; }
+inline void KColumn::setLineHeight( KPixelY H ) { LineHeight = H; }
+
+inline bool KColumn::overlaps( KPixelXs Xs ) const { return XSpan.overlaps(Xs); }
+
+}
+
+#endif
diff --git a/khexedit/lib/kcolumnsview.cpp b/khexedit/lib/kcolumnsview.cpp
new file mode 100644
index 0000000..1c93af8
--- /dev/null
+++ b/khexedit/lib/kcolumnsview.cpp
@@ -0,0 +1,236 @@
+/***************************************************************************
+ kcolumnsview.cpp - description
+ -------------------
+ begin : Mit Mai 21 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+//#include <kdebug.h>
+
+// qt specific
+#include <qpainter.h>
+// lib specific
+#include "kcolumn.h"
+#include "kcolumnsview.h"
+
+
+using namespace KHE;
+
+static bool DefaultHorizontalGrid = false;
+
+KColumnsView::KColumnsView( /*bool R,*/ QWidget *Parent, const char *Name, WFlags Flags )
+ : QScrollView( Parent, Name, Flags | WRepaintNoErase /*| WStaticContents*/ ),
+ NoOfLines( 0 ),
+ LineHeight( 0 ),
+ TotalWidth( 0 ),
+ HorizontalGrid( DefaultHorizontalGrid ),
+// Reversed( R ),
+ d( 0 )
+{
+ viewport()->setBackgroundMode( PaletteBase );
+ setBackgroundMode( PaletteBackground, PaletteBase );
+ viewport()->setFocusProxy( this );
+
+ Columns.setAutoDelete( true );
+}
+
+KColumnsView::~KColumnsView()
+{
+}
+
+
+void KColumnsView::setNoOfLines( int NewNoOfLines )
+{
+ NoOfLines = NewNoOfLines;
+}
+
+
+void KColumnsView::setLineHeight( KPixelY LH )
+{
+ LineHeight = LH;
+ for( KColumn *C=Columns.first(); C; C=Columns.next() )
+ C->setLineHeight( LineHeight );
+ verticalScrollBar()->setLineStep( LineHeight );
+
+ updateLineBufferSize();
+}
+
+
+void KColumnsView::updateWidths()
+{
+ TotalWidth = 0;
+ for( KColumn *C=Columns.first(); C; C=Columns.next() )
+ {
+ C->setX( TotalWidth );
+ TotalWidth += C->visibleWidth();
+ }
+
+ updateLineBufferSize();
+}
+
+
+void KColumnsView::updateLineBufferSize()
+{
+ int w = totalWidth();
+ int h = LineHeight;
+
+ if( w != LineBuffer.width() || h != LineBuffer.height() )
+ LineBuffer.resize( w, h );
+}
+
+
+int KColumnsView::noOfLinesPerPage() const
+{
+ if( !viewport() || LineHeight == 0 )
+ return 1;
+// int NoOfLinesPerPage = (visibleHeight()-1) / LineHeight; // -1 ensures to get always the last visible line
+ int NoOfLinesPerPage = (viewport()->height()-1) / LineHeight; // -1 ensures to get always the last visible line
+
+ if( NoOfLinesPerPage == 0 )
+ // ensure to move down at least one line
+ NoOfLinesPerPage = 1;
+ return NoOfLinesPerPage;
+}
+
+
+void KColumnsView::addColumn( KColumn *C )
+{
+// if( Reversed )
+// Columns.prepend( C );
+// else
+ Columns.append( C );
+
+ updateWidths();
+}
+
+
+void KColumnsView::removeColumn( KColumn *C )
+{
+ Columns.remove( C );
+
+ updateWidths();
+}
+
+
+void KColumnsView::updateView()
+{
+ resizeContents( totalWidth(), totalHeight() );
+ updateContents();
+}
+
+
+void KColumnsView::repaintView()
+{
+ resizeContents( totalWidth(), totalHeight() );
+ repaintContents( false );
+}
+
+
+void KColumnsView::paintEmptyArea( QPainter *P, int cx ,int cy, int cw, int ch)
+{
+ P->fillRect( cx, cy, cw, ch, backgroundBrush() );
+}
+
+
+void KColumnsView::drawContents( QPainter *P, int cx, int cy, int cw, int ch )
+{
+ //kdDebug(1501) << "drawContents(" << cx<<","<<cw<<"#"<<cy<<","<<ch<<")\n";
+ KPixelXs AffectedXs( cx, cw, true );
+ // content to be shown?
+ if( AffectedXs.startsBefore(TotalWidth) )
+ {
+ KPixelYs AffectedYs( cy, ch, true );
+
+ // collect affected columns
+ QPtrList<KColumn> RedrawColumns;
+ for( KColumn *C=Columns.first(); C; C=Columns.next() )
+ if( C->isVisible() && C->overlaps(AffectedXs) )
+ RedrawColumns.append( C );
+
+ // any lines to be drawn?
+ if( NoOfLines > 0 )
+ {
+ // calculate affected lines
+ KSection AffectedLines = visibleLines( AffectedYs );
+ AffectedLines.restrictEndTo( NoOfLines - 1 );
+
+ if( AffectedLines.isValid() )
+ {
+ QPainter Paint;
+ Paint.begin( &LineBuffer, this );
+
+ // starting painting with the first line
+ KColumn *C = RedrawColumns.first();
+ Paint.translate( C->x(), 0 );
+
+ for( ; C; C=RedrawColumns.next() )
+ {
+ C->paintFirstLine( &Paint, AffectedXs, AffectedLines.start() );
+ Paint.translate( C->width(), 0 );
+ }
+
+ // Go through the other lines
+ KPixelY y = AffectedLines.start() * LineHeight;
+ int l = AffectedLines.start();
+ while( true )
+ {
+ Paint.end();
+ P->drawPixmap( cx, y, LineBuffer, cx, 0, cw, LineHeight ); // bitBlt directly impossible: lack of real coord
+
+ // copy to screen
+// bitBlt( viewport(), cx - contentsX(), y - contentsY(),
+// &LineBuffer, cx, 0, cw, LineHeight );
+
+ ++l;
+ y += LineHeight;
+
+ if( l > AffectedLines.end() )
+ break;
+
+ // to avoid flickers we first paint to the linebuffer
+ Paint.begin( &LineBuffer, this );
+
+ KColumn *C = RedrawColumns.first();
+ Paint.translate( C->x(), 0 );
+
+ for( ; C; C=RedrawColumns.next() )
+ {
+ C->paintNextLine( &Paint );
+ Paint.translate( C->width(), 0 );
+ }
+
+ if( HorizontalGrid && cx < TotalWidth )
+ Paint.drawLine( cx, LineHeight-1, TotalWidth-1, LineHeight-1 ); // TODO: use a additional TotalHeight?
+ }
+ }
+ }
+
+ // draw empty columns?
+ AffectedYs.setStart( totalHeight() );
+ if( AffectedYs.isValid() )
+ {
+ for( KColumn *C = RedrawColumns.first(); C; C=RedrawColumns.next() )
+ C->paintEmptyColumn( P, AffectedXs, AffectedYs );
+ }
+ }
+
+ // Paint empty rects
+ AffectedXs.setStart( TotalWidth );
+ if( AffectedXs.isValid() )
+ paintEmptyArea( P, AffectedXs.start(), cy, AffectedXs.width(), ch );
+}
+
+// Implemented to get rid of a compiler warning
+void KColumnsView::drawContents( QPainter * ) {}
+
+#include "kcolumnsview.moc"
diff --git a/khexedit/lib/kcolumnsview.h b/khexedit/lib/kcolumnsview.h
new file mode 100644
index 0000000..aa3521d
--- /dev/null
+++ b/khexedit/lib/kcolumnsview.h
@@ -0,0 +1,168 @@
+/***************************************************************************
+ kcolumnsview.h - description
+ -------------------
+ begin : Mit Mai 21 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KCOLUMNSVIEW_H
+#define KHE_KCOLUMNSVIEW_H
+
+// qt specific
+#include <qptrlist.h>
+#include <qwidget.h>
+#include <qpixmap.h>
+#include <qscrollview.h>
+// lib specific
+#include "kadds.h"
+#include "ksection.h" // TODO: think about moving this out of the public API
+
+namespace KHE
+{
+
+class KColumn;
+class KColumnsViewPrivate;
+
+/** general class for widgets with columns that display different aspects of the same data
+ * with the same lineheight for all lines
+ *
+ *@author Friedrich W. H. Kossebau
+ */
+
+class KColumnsView : public QScrollView
+{
+ Q_OBJECT
+
+ friend class KColumn;
+
+ public:
+ KColumnsView( /*bool R = false,*/ QWidget *parent=0, const char *name=0, WFlags Flags=0 );
+ virtual ~KColumnsView();
+
+ public: // drawing
+ virtual void paintEmptyArea( QPainter *p, int cx, int cy, int cw, int ch );
+ virtual void drawContents( QPainter *p, int cx, int cy, int cw, int ch );
+
+ public: // data-wise sizes
+ /** returns the number of all lines */
+ int noOfLines() const;
+ /** returns number of fully visible lines, at least 1 (as needed by page down/up)
+ * doesn't care about the total height being smaller than the display height
+ */
+ int noOfLinesPerPage() const;
+
+ public: // pixel-wise sizes
+ /** returns the height of each line */
+ KPixelY lineHeight() const;
+ /** returns the size of all visible columns together */
+ QSize totalViewSize() const;
+ /** returns the width of all visible columns together */
+ KPixelX totalWidth() const;
+ /** returns the height of all lines together */
+ KPixelY totalHeight() const;
+
+ public: // services
+ /** gives the index of the line that would include y in pixel coord.
+ * y is not forced to be inside the total height.
+ */
+ uint lineAt( KPixelY y ) const;
+ /** gives the index of the first and the last line that would be visible
+ * these lines might not contain anything
+ */
+ KSection visibleLines() const;
+ /** gives the index of the first and the last line that would be visible in the given pixel range
+ * these lines might not contain anything
+ */
+ KSection visibleLines( KPixelYs YPixels ) const;
+
+
+ protected:
+ /** called by KColumn */
+ void addColumn( KColumn *C );
+ void removeColumn( KColumn *C );
+
+
+ protected: //
+ /** sets height of all lines and propagates this information to all columns
+ * doesn't update the content size
+ * @param NewLineHeight height in pixels
+ */
+ virtual void setLineHeight( KPixelY NewLineHeight );
+ /** sets the number of lines
+ * doesn't update the content size
+ * @param NewNoOfLines new number of lines to display
+ */
+ virtual void setNoOfLines( int NewNoOfLines );
+
+ protected: // recalculations
+ /** recalculates the positions of the columns and the total width */
+ void updateWidths();
+ /** ensures that the line buffer has the size of the whole line */
+ void updateLineBufferSize();
+
+ protected: // painting
+ void updateView();
+ void repaintView();
+
+ private:
+ /** hiding it*/
+ void drawContents( QPainter* );
+
+
+ protected: // calculated
+ /** collection of all the columns. All columns will be autodeleted. */
+ QPtrList<KColumn> Columns;
+ /** the number of lines which the column view has */
+ int NoOfLines;
+ /** the height of each line in pixels */
+ KPixelY LineHeight;
+ /** the width of all visible columns together */
+ KPixelX TotalWidth;
+// /** width that is used by columns that are not resizeable (if shown) */
+// KPixelX ReservedWidth;
+
+ protected:
+ // TODO: do we really want this?
+ bool HorizontalGrid;
+ /** Buffer where each line is drawn to before it is copied onto the screen */
+ QPixmap LineBuffer;
+// bool Reversed;
+
+ private:
+ KColumnsViewPrivate *d;
+};
+
+
+inline int KColumnsView::noOfLines() const { return NoOfLines; }
+inline KPixelY KColumnsView::lineHeight() const { return LineHeight; }
+inline uint KColumnsView::lineAt( KPixelY y ) const { return LineHeight!=0 ? y / LineHeight : 0; }
+inline KSection KColumnsView::visibleLines() const
+{
+ KPixelY cy = contentsY();
+ KPixelY ch = visibleHeight();
+ return KSection( lineAt(cy), lineAt(cy+ch-1) );
+}
+
+inline KSection KColumnsView::visibleLines( KPixelYs YPixels ) const
+{
+ return KSection( lineAt(YPixels.start()), lineAt(YPixels.end()) );
+}
+
+inline KPixelY KColumnsView::totalHeight() const { return NoOfLines*LineHeight; }
+inline KPixelX KColumnsView::totalWidth() const { return TotalWidth; }
+
+inline QSize KColumnsView::totalViewSize() const { return QSize( totalWidth(), totalHeight() ); }
+
+}
+
+#endif
diff --git a/khexedit/lib/kcoordrange.h b/khexedit/lib/kcoordrange.h
new file mode 100644
index 0000000..0d5b186
--- /dev/null
+++ b/khexedit/lib/kcoordrange.h
@@ -0,0 +1,95 @@
+/***************************************************************************
+ kcoordrange.h - description
+ -------------------
+ begin : Sun 03.08.2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+****************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KCOORDRANGE_H
+#define KHE_KCOORDRANGE_H
+
+// lib specific
+#include "krange.h"
+#include "kbuffercoord.h"
+#include "ksection.h"
+
+namespace KHE
+{
+
+template<>
+inline const KBufferCoord KRange<KBufferCoord>::null() const { return KBufferCoord(-1,-1);}
+
+typedef KRange<KBufferCoord> KBasicCoordRange;
+
+/** describes a range in the buffercoord
+ *@author Friedrich W. H. Kossebau
+ */
+class KCoordRange : public KRange<KBufferCoord>
+{
+ public:
+ /**
+ * @param SC start coord
+ * @param EC end coord
+ */
+ KCoordRange( KBufferCoord SC, KBufferCoord EC );
+ /**
+ * @param Pos start and end pos
+ * @param Lines start and end line
+ */
+ KCoordRange( KSection Pos, KSection Lines );
+ KCoordRange();
+ ~KCoordRange();
+
+ public:
+ KCoordRange &operator=( const KCoordRange &S );
+
+ public:
+ bool operator==( const KCoordRange &S ) const;
+
+ public:
+ /** calculates the number of coords that are covered if a line has the given length.
+ * If the range is invalid the behaviour is undefined.
+ * @param LineLength
+ * @return the number of points covered if a line has a length of LineLength.
+ */
+ int width( int LineLength ) const;
+ /** calculates the number of lines that are covered by the range.
+ * If the range is invalid the behaviour is undefined.
+ * @return number of lines covered
+ */
+ int lines() const;
+ /** tests if the given line is included by the range.
+ * If the range is invalid or the line < 0 the behaviour is undefined.
+ * @param Line index of line
+ * @return @c true if Line is included, otherwise @c false
+ */
+ bool includesLine( int Line ) const;
+};
+
+
+inline KCoordRange::KCoordRange( KBufferCoord SC, KBufferCoord EC ) : KBasicCoordRange(SC,EC) {}
+inline KCoordRange::KCoordRange( KSection Pos, KSection Lines )
+ : KBasicCoordRange( KBufferCoord(Pos.start(),Lines.start()), KBufferCoord(Pos.end(),Lines.end()) ) {}
+inline KCoordRange::KCoordRange() {}
+inline KCoordRange::~KCoordRange() {}
+
+inline bool KCoordRange::operator==( const KCoordRange &R ) const { return KBasicCoordRange::operator==(R); }
+
+inline KCoordRange &KCoordRange::operator=( const KCoordRange &R ) { KBasicCoordRange::operator=(R); return *this; }
+
+inline int KCoordRange::width( int LineLength ) const { return LineLength*(lines()-1) + End.pos() - Start.pos()+1; }
+inline int KCoordRange::lines() const { return End.line() - Start.line() + 1; }
+inline bool KCoordRange::includesLine( int Line ) const { return Line >= Start.line() && Line <= End.line(); }
+}
+
+#endif
diff --git a/khexedit/lib/kcoordrangelist.cpp b/khexedit/lib/kcoordrangelist.cpp
new file mode 100644
index 0000000..3028c7d
--- /dev/null
+++ b/khexedit/lib/kcoordrangelist.cpp
@@ -0,0 +1,78 @@
+/***************************************************************************
+ kcoordrangelist.cpp - description
+ -------------------
+ begin : Mon Jun 30 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// lib specific
+#include "kcoordrangelist.h"
+
+using namespace KHE;
+
+KCoordRangeList::KCoordRangeList()
+{
+}
+
+
+KCoordRangeList::~KCoordRangeList()
+{
+}
+
+
+void KCoordRangeList::addCoordRange( KCoordRange NewCoordRange )
+{
+ if( !NewCoordRange.isValid() )
+ return;
+ // we try to insert it by ascending indizes
+ // if sections are overlapping we combine them
+ iterator S = begin();
+ for( ; S!=end(); ++S )
+ {
+ // is next CoordRange behind the new CoordRange?
+ if( NewCoordRange.endsBefore(*S) )
+ {
+ // put the new before it
+ insert( S, NewCoordRange );
+ return;
+ }
+
+ // does the next CoordRange overlap?
+ if( (*S).overlaps(NewCoordRange) )
+ {
+ // Start of the combined sections is the smaller one
+ NewCoordRange.extendStartTo( (*S).start() );
+ // next we search all the overlapping sections and keep the highest end index
+ KBufferCoord End((*S).end());
+ iterator LS = S;
+ for( ++LS; LS!=end(); ++LS )
+ {
+ if( !(*LS).overlaps(NewCoordRange) )
+ break;
+ End = (*LS).end();
+ }
+ // the higher end is the end of the combined CoordRange
+ NewCoordRange.extendEndTo( End );
+ // remove all overlapping sections
+ S = erase( S, LS );
+ // and instead insert the combined one
+ insert( S, NewCoordRange );
+ return;
+ }
+ }
+
+ // all others are before the new?
+ if( S == end() )
+ // add it at the end
+ append( NewCoordRange );
+}
diff --git a/khexedit/lib/kcoordrangelist.h b/khexedit/lib/kcoordrangelist.h
new file mode 100644
index 0000000..187ec7f
--- /dev/null
+++ b/khexedit/lib/kcoordrangelist.h
@@ -0,0 +1,44 @@
+/***************************************************************************
+ kcoordrangelist.h - description
+ -------------------
+ begin : Wed Aug 13 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KCOORDRANGELIST_H
+#define KHE_KCOORDRANGELIST_H
+
+// qt specific
+#include <qvaluelist.h>
+// lib specific
+#include "kcoordrange.h"
+
+namespace KHE {
+
+typedef QValueList<KCoordRange> KCoordRangeBasicList;
+/**
+@author Friedrich W. H. Kossebau
+*/
+class KCoordRangeList : public KCoordRangeBasicList
+{
+ public:
+ KCoordRangeList();
+ ~KCoordRangeList();
+
+ public:
+ void addCoordRange( KCoordRange S );
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/kcursor.cpp b/khexedit/lib/kcursor.cpp
new file mode 100644
index 0000000..3150751
--- /dev/null
+++ b/khexedit/lib/kcursor.cpp
@@ -0,0 +1,49 @@
+/***************************************************************************
+ kcursor.cpp - description
+ -------------------
+ begin : Mit Jun 26 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#include "kcursor.h"
+
+using namespace KHE;
+
+KCursor::KCursor()
+: CursorX( 0 ),
+ CursorW( -1 )
+{
+}
+
+
+KCursor::~KCursor()
+{
+}
+
+
+
+void KCursor::setSize( KPixelX Width, KPixelY Height )
+{
+ if( Width != OnPixmap.width() || Height != OnPixmap.height() )
+ {
+ OnPixmap.resize( Width, Height );
+ OffPixmap.resize( Width, Height );
+ }
+}
+
+
+void KCursor::setShape( KPixelX X, KPixelX W )
+{
+ CursorX = X;
+ CursorW = W;
+}
diff --git a/khexedit/lib/kcursor.h b/khexedit/lib/kcursor.h
new file mode 100644
index 0000000..428c7ed
--- /dev/null
+++ b/khexedit/lib/kcursor.h
@@ -0,0 +1,68 @@
+/***************************************************************************
+ kbuffercolumn.h - description
+ -------------------
+ begin : Mit Jun 26 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KCURSOR_H
+#define KHE_KCURSOR_H
+
+
+#include <qpixmap.h>
+
+#include "kadds.h"
+
+namespace KHE
+{
+
+/**
+ *@author Friedrich W. H. Kossebau
+ */
+class KCursor
+{
+ public:
+ KCursor();
+ virtual ~KCursor();
+
+ public:
+ /** sets size of the full cursor */
+ void setSize( KPixelX Width, KPixelY Height );
+ /** sets the shape of the cursor to be drawn */
+ void setShape( KPixelX X, KPixelX W );
+
+ public: // access
+ const QPixmap &onPixmap() const;
+ const QPixmap &offPixmap() const;
+ KPixelX cursorX() const;
+ KPixelX cursorW() const;
+
+
+ protected:
+ QPixmap OnPixmap;
+ QPixmap OffPixmap;
+
+ KPixelX CursorX;
+ KPixelX CursorW;
+};
+
+
+inline const QPixmap &KCursor::onPixmap() const { return OnPixmap; }
+inline const QPixmap &KCursor::offPixmap() const { return OffPixmap; }
+
+inline KPixelX KCursor::cursorX() const { return CursorX; }
+inline KPixelX KCursor::cursorW() const { return CursorW; }
+
+}
+
+#endif
diff --git a/khexedit/lib/kdatabuffer.cpp b/khexedit/lib/kdatabuffer.cpp
new file mode 100644
index 0000000..054d792
--- /dev/null
+++ b/khexedit/lib/kdatabuffer.cpp
@@ -0,0 +1,51 @@
+/***************************************************************************
+ kdatabuffer.cpp - description
+ -------------------
+ begin : Fri Aug 01 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// c specific
+#include <ctype.h>
+// lib specific
+#include "kdatabuffer.h"
+
+using namespace KHE;
+
+
+int KDataBuffer::insert( int Pos, const char* D, int Length )
+{
+ return replace( Pos,0,D,Length );
+}
+
+
+int KDataBuffer::remove( KSection Remove )
+{
+ replace( Remove, 0, 0 );
+ return Remove.width(); // TODO: check if this is true
+}
+
+int KDataBuffer::copyTo( char* Dest, int Pos, int Length ) const
+{
+ return copyTo( Dest, KSection(Pos,Length,false) );
+}
+
+
+
+int KDataBuffer::copyTo( char* Dest, KSection Source ) const
+{
+ Source.restrictEndTo( size()-1 );
+ for( int i=Source.start(); i<=Source.end(); ++i )
+ *Dest++ = datum( i );
+ return Source.width();
+}
diff --git a/khexedit/lib/kdatabuffer.h b/khexedit/lib/kdatabuffer.h
new file mode 100644
index 0000000..e9733d8
--- /dev/null
+++ b/khexedit/lib/kdatabuffer.h
@@ -0,0 +1,246 @@
+/***************************************************************************
+ kdatabuffer.h - description
+ -------------------
+ begin : Mit Mai 14 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KDATABUFFER_H
+#define KHE_KDATABUFFER_H
+
+
+// lib specific
+#include "ksection.h"
+#include "khexedit_export.h"
+
+namespace KHE
+{
+
+/** could it be useful to hide the data access behind an iterator? *
+class KDataBufferIterator
+{
+ public:
+ bool hasNext();
+ char next();
+ protected:
+
+ protected:
+ char *
+ int Length;
+}
+
+bool KDataBufferIterator::hasNext()
+{
+}
+// this function should be simple as possible
+char KDataBufferIterator::next()
+{
+ // if next span is empty
+ if( )
+ return *NextChar++;
+}
+*/
+/** base class for all Data buffers that are used to display
+ * TODO: think about a way to inform KHexEdit that there has been
+ * a change in the buffer outside. what kind of changes are possible?
+ *
+ * Operations on the data:
+ *
+ * Finding: is implemented stateless. FindNext has to be done by perhaps a FindManager
+ * Replacing: not available. Implement within a ReplaceManager
+ *
+ *@author Friedrich W. H. Kossebau
+ */
+
+class KHEXEDIT_EXPORT KDataBuffer
+{
+ friend class KDataBufferIterator;
+
+
+ protected:
+ KDataBuffer();
+ public:
+ virtual ~KDataBuffer();
+
+
+ public: // data access API
+ /** locates working range
+ * The idea behind is to tell buffer which range will be requested in the following time,
+ * so that e.g. the corresponding pages will be loaded in advance
+ * TODO: do we really need this? Where will this lead to real enhancements?
+ * @param Range
+ * @return @c true if successfull, @c false otherwise
+ */
+ virtual bool prepareRange( KSection Range ) const = 0;
+ /** convenience function, same as above */
+ bool prepareRange( int Offset, int Length ) const;
+
+ /** creates an iterator to */
+ //virtual KDataBufferIterator *iterator() const = 0;
+ /** expects pointer to memory, should be in prepared range
+ * it is only expected to be a valid pointer until any further call
+ * to this or any modifying function
+ * @param Section
+ * @return pointer to
+ */
+ virtual const char *dataSet( KSection Section ) const = 0;
+ /** convenience function, same as above */
+ const char *dataSet( int Offset, int Length ) const;
+
+ /** requests a single byte
+ * if the offset is not valid the behaviout is undefined
+ * @param Offset offset of the datum requested
+ */
+ virtual char datum( unsigned int Offset ) const = 0;
+
+ /**
+ * @return the size of the data
+ */
+ virtual int size() const = 0;
+
+
+ public: // state read API
+ /**
+ * @return @c true if the buffer can only be read, @c false if writing is allowed
+ */
+ virtual bool isReadOnly() const;
+ /**
+ * @return @c true if the buffer has been modified, @c false otherwise
+ */
+ virtual bool isModified() const = 0;
+
+
+ public: // modification API
+ /** inserts bytes copied from the given source at Position.
+ * The original data beginnung at the position is moved
+ * with the buffer enlarged as needed
+ * If the buffer is readOnly this is a noop and returns 0.
+ * @param Pos
+ * @param Source data source
+ * @param SourceLength number of bytes to copy
+ * @return length of inserted data
+ */
+ virtual int insert( int Pos, const char* Source, int SourceLength );
+
+ /** removes beginning with position as much as possible
+ * @param Section
+ * @return length of removed data
+ */
+ virtual int remove( KSection Section );
+ /** convenience function, behaves as above */
+ int remove( int Pos, int Length );
+
+ /** replaces as much as possible
+ * @param DestSection
+ * @param Source
+ * @param SourceLength
+ * @return length of replacced data
+ */
+ virtual unsigned int replace( KSection DestSection, const char* Source, unsigned int SourceLength ) = 0;
+ /** convenience function, behaves as above */
+ unsigned int replace( unsigned int Pos, unsigned int RemoveLength,
+ const char* Source, unsigned int SourceLength );
+
+ /** moves a part of the data to a new position, while floating the other data around
+ * when moving to a higher place the length of the block must be taken into account
+ * if the new positions extend beyond the buffers end the section is moved to the end.
+ * @param DesPos position of the data where the section should be moved behind
+ * @param SourceSection data section to be moved
+ * @return new pos of moved data or old, if failed
+ */
+ virtual int move( int DestPos, KSection SourceSection ) = 0;
+
+ /**
+ * fills the buffer with the FillChar. If the buffer is to small it will be extended as much as possible.
+ * @param FillChar char to use
+ * @param Length number of chars to fill. If Length is -1, the current buffer length is used.
+ * @param Pos position where the filling starts
+ * @return number of filled characters
+ */
+ virtual int fill( const char FillChar, int Length = -1, unsigned int Pos = 0 ) = 0;
+
+ /** sets a single byte
+ * if the offset is not valid the behaviour is undefined
+ * @param Offset offset of the datum requested
+ * @param Char new byte value
+ */
+ virtual void setDatum( unsigned int Offset, const char Char ) = 0;
+
+ /** sets the modified flag for the buffer
+ * @param M
+ */
+ virtual void setModified( bool M ) = 0;
+
+
+ public: // service functions
+ /** copies the data of the section into a given array Dest. If the section extends the buffers range
+ * the section is limited to the buffer's end. If the section is invalid the behaviour is undefined.
+ * @param Dest pointer to a char array large enough to hold the copied section
+ * @param Source
+ * @return number of copied bytes
+ */
+ virtual int copyTo( char* Dest, KSection Source ) const;
+ /** convenience function, behaves as above */
+ int copyTo( char* Dest, int Pos, int n ) const;
+
+
+ public: // finding API
+ /** searches beginning with byte at Pos.
+ * @param
+ * @param Length length of search string
+ * @param Pos the position to start the search
+ * @return index of the first or -1
+ */
+ //virtual int find( const char*, int Length, int Pos = 0 ) const = 0;
+ /** searches for a given data string
+ * The section limits the data within which the key has to be found
+ * If the end of the section is lower then the start the search continues at the start???
+ * @param
+ * @param Length length of search string
+ * @param Section section within the keydata is to be found
+ * @return index of the first occurence or -1
+ */
+ virtual int find( const char*KeyData, int Length, KSection Section ) const = 0;
+ /** searches backward beginning with byte at Pos.
+ * @param
+ * @param Length length of search string
+ * @param Pos the position to start the search. If -1 the search starts at the end.
+ * @return index of the first or -1
+ */
+ virtual int rfind( const char*, int Length, int Pos = -1 ) const = 0;
+
+/* virtual int find( const QString &expr, bool cs, bool wo, bool forward = true, int *index = 0 ); */
+};
+
+
+inline KDataBuffer::KDataBuffer() {}
+inline KDataBuffer::~KDataBuffer() {}
+
+inline bool KDataBuffer::prepareRange( int Offset, int Length ) const
+{ return prepareRange( KSection(Offset,Offset+Length-1) ); }
+
+inline const char *KDataBuffer::dataSet( int Offset, int Length ) const
+{ return dataSet( KSection(Offset,Offset+Length-1) ); }
+
+inline int KDataBuffer::remove( int Pos, int Length )
+{ return remove( KSection(Pos,Pos+Length-1) ); }
+
+inline unsigned int KDataBuffer::replace( unsigned int Pos, unsigned int RemoveLength,
+ const char* D, unsigned int InputLength )
+{ return replace( KSection(Pos,Pos+RemoveLength-1), D, InputLength ); }
+
+inline bool KDataBuffer::isReadOnly() const { return false; }
+
+}
+
+#endif
diff --git a/khexedit/lib/kfixedsizebuffer.cpp b/khexedit/lib/kfixedsizebuffer.cpp
new file mode 100644
index 0000000..2945620
--- /dev/null
+++ b/khexedit/lib/kfixedsizebuffer.cpp
@@ -0,0 +1,272 @@
+/***************************************************************************
+ kfixedsizebuffer.cpp - description
+ -------------------
+ begin : Mit Jun 03 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+//#include <kdebug.h>
+// c specific
+#include <string.h>
+// lib specific
+#include "kfixedsizebuffer.h"
+
+using namespace KHE;
+
+KFixedSizeBuffer::KFixedSizeBuffer( char *D, unsigned int S, char FUC )
+ : Data( D ),
+ Size( S ),
+ FillUpChar( FUC ),
+ ReadOnly( true ),
+ Modified( false ),
+ AutoDelete( false )
+{
+}
+
+KFixedSizeBuffer::KFixedSizeBuffer( unsigned int S, char FUC )
+ : Data( new char[S] ),
+ Size( S ),
+ FillUpChar( FUC ),
+ ReadOnly( false ),
+ Modified( false ),
+ AutoDelete( true )
+{
+ reset( 0, S );
+}
+
+KFixedSizeBuffer::~KFixedSizeBuffer()
+{
+ if( AutoDelete )
+ delete [] Data;
+}
+
+
+
+int KFixedSizeBuffer::insert( int Pos, const char* D, int InputLength )
+{
+ // check all parameters
+ if( Pos >= (int)Size || InputLength == 0 )
+ return 0;
+ if( Pos + InputLength > (int)Size )
+ InputLength = Size - Pos;
+
+ unsigned int BehindInsertPos = Pos + InputLength;
+ // fmove right data behind the input range
+ memmove( &Data[BehindInsertPos], &Data[Pos], Size-BehindInsertPos );
+ // insert input
+ memcpy( &Data[Pos], D, InputLength );
+
+ Modified = true;
+ return InputLength;
+}
+
+
+int KFixedSizeBuffer::remove( KSection Remove )
+{
+ if( Remove.start() >= (int)Size || Remove.width() == 0 )
+ return 0;
+
+ Remove.restrictEndTo( Size-1 );
+
+ int RemoveLength = Remove.width();
+ int BehindRemovePos = Remove.end()+1;;
+ // fmove right data behind the input range
+ memmove( &Data[Remove.start()], &Data[BehindRemovePos], Size-BehindRemovePos );
+ // clear freed space
+ reset( Size-RemoveLength, RemoveLength );
+
+ Modified = true;
+ return RemoveLength;
+}
+
+
+unsigned int KFixedSizeBuffer::replace( KSection Remove, const char* D, unsigned int InputLength )
+{
+ // check all parameters
+ if( Remove.startsBehind( Size-1 ) || (Remove.width()==0 && InputLength==0) )
+ return 0;
+
+ Remove.restrictEndTo( Size-1 );
+ if( Remove.start() + InputLength > Size )
+ InputLength = Size - Remove.start();
+
+ int SizeDiff = InputLength - Remove.width();
+
+ // is input longer than removed?
+ if( SizeDiff > 0 )
+ {
+ unsigned int BehindInsertPos = Remove.start() + InputLength;
+ // fmove right data behind the input range
+ memmove( &Data[BehindInsertPos], &Data[Remove.end()+1], Size-BehindInsertPos );
+ }
+ // is input smaller than removed?
+ else if( SizeDiff < 0 )
+ {
+ unsigned int BehindRemovePos = Remove.end()+1;
+ // fmove right data behind the input range
+ memmove( &Data[Remove.start()+InputLength], &Data[BehindRemovePos], Size-BehindRemovePos );
+ // clear freed space
+ reset( Size+SizeDiff, -SizeDiff );
+ }
+ // insert input
+ memcpy( &Data[Remove.start()], D, InputLength );
+
+ Modified = true;
+ return InputLength;
+}
+
+
+int KFixedSizeBuffer::move( int DestPos, KSection SourceSection )
+{
+ // check all parameters
+ if( SourceSection.start() >= (int)Size || SourceSection.width() == 0
+ || DestPos > (int)Size || SourceSection.start() == DestPos )
+ return SourceSection.start();
+
+ SourceSection.restrictEndTo( Size-1 );
+ bool ToRight = DestPos > SourceSection.start();
+ int MovedLength = SourceSection.width();
+ int DisplacedLength = ToRight ? DestPos - SourceSection.end()-1 : SourceSection.start() - DestPos;
+
+ // find out section that is smaller
+ int SmallPartLength, LargePartLength, SmallPartStart, LargePartStart, SmallPartDest, LargePartDest;
+ // moving part is smaller?
+ if( MovedLength < DisplacedLength )
+ {
+ SmallPartStart = SourceSection.start();
+ SmallPartLength = MovedLength;
+ LargePartLength = DisplacedLength;
+ // moving part moves right?
+ if( ToRight )
+ {
+ SmallPartDest = DestPos - MovedLength;
+ LargePartStart = SourceSection.end()+1;
+ LargePartDest = SourceSection.start();
+ }
+ else
+ {
+ SmallPartDest = DestPos;
+ LargePartStart = DestPos;
+ LargePartDest = DestPos + MovedLength;
+ }
+ }
+ else
+ {
+ LargePartStart = SourceSection.start();
+ LargePartLength = MovedLength;
+ SmallPartLength = DisplacedLength;
+ // moving part moves right?
+ if( ToRight )
+ {
+ LargePartDest = DestPos - MovedLength;
+ SmallPartStart = SourceSection.end()+1;
+ SmallPartDest = SourceSection.start();
+ }
+ else
+ {
+ LargePartDest = DestPos;
+ SmallPartStart = DestPos;
+ SmallPartDest = DestPos + MovedLength;
+ }
+ }
+
+ // copy smaller part to tempbuffer
+ char *Temp = new char[SmallPartLength];
+ memcpy( Temp, &Data[SmallPartStart], SmallPartLength );
+
+ // move the larger part
+ memmove( &Data[LargePartDest], &Data[LargePartStart], LargePartLength );
+
+ // copy smaller part to its new dest
+ memcpy( &Data[SmallPartDest], Temp, SmallPartLength );
+ delete [] Temp;
+
+ Modified = true;
+ return MovedLength < DisplacedLength ? SmallPartDest : LargePartDest;
+}
+
+
+int KFixedSizeBuffer::fill( const char FChar, int FillLength, unsigned int Pos )
+{
+ // nothing to fill
+ if( Pos >= Size )
+ return 0;
+
+ unsigned int LengthToEnd = Size - Pos;
+
+ if( FillLength < 0 || FillLength > (int)LengthToEnd )
+ FillLength = LengthToEnd;
+
+ memset( &Data[Pos], FChar, FillLength );
+ Modified = true;
+ return FillLength;
+}
+
+
+int KFixedSizeBuffer::compare( const KDataBuffer &Other, KSection OtherRange, unsigned int Pos )
+{
+ //kdDebug() << QString("Pos: %1, OtherRange: (%3/%4)" ).arg(Pos).arg(OtherRange.start()).arg(OtherRange.end())
+ // << endl;
+ // test other values
+ if( OtherRange.startsBehind(Other.size()-1) )
+ return 1;
+
+ // check own values
+ if( Pos >= Size )
+ return -1;
+
+ int ValueByLength = 0; // default: equal
+
+ KSection Range( Pos, OtherRange.width(), true );
+ int Last = Other.size()-1;
+ //
+ if( OtherRange.endsBehind(Last) )
+ {
+ // make shorter
+ OtherRange.setEnd( Last );
+ if( OtherRange.width() < Range.width() )
+ ValueByLength = 1;
+ }
+ Last = Size-1;
+ if( Range.endsBehind(Last) )
+ {
+ // make shorter
+ Range.setEnd( Last );
+ if( OtherRange.width() > Range.width() )
+ ValueByLength = -1;
+ }
+ //kdDebug()
+ // << QString( "Range: (%1/%2), OtherRange: (%3/%4)" ).arg(Range.start()).arg(Range.end()).arg(OtherRange.start()).arg(OtherRange.end())
+ // << endl;
+ int oi = OtherRange.start();
+ for( int i=Range.start(); i<=Range.end(); ++i,++oi )
+ {
+ char OD = Other.datum(oi);
+ char D = Data[i];
+ //kdDebug() << QString("%1==%2").arg((int)D).arg((int)OD) << endl;
+ if( OD == D )
+ continue;
+ return OD < D ? 1 : -1;
+ }
+
+ return ValueByLength;
+}
+
+
+int KFixedSizeBuffer::find( const char*/*KeyData*/, int /*Length*/, KSection /*Section*/ ) const { return 0; }
+int KFixedSizeBuffer::rfind( const char*, int /*Length*/, int /*Pos*/ ) const { return 0; }
+
+
+void KFixedSizeBuffer::reset( unsigned int Pos, unsigned int Length )
+{
+ memset( &Data[Pos], FillUpChar, Length );
+}
diff --git a/khexedit/lib/kfixedsizebuffer.h b/khexedit/lib/kfixedsizebuffer.h
new file mode 100644
index 0000000..15c17da
--- /dev/null
+++ b/khexedit/lib/kfixedsizebuffer.h
@@ -0,0 +1,116 @@
+/***************************************************************************
+ kfixedsizebuffer.h - description
+ -------------------
+ begin : Mit Jun 03 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KFIXEDSIZEBUFFER_H
+#define KHE_KFIXEDSIZEBUFFER_H
+
+#include "kdatabuffer.h"
+
+namespace KHE
+{
+
+/** base class for all Data buffers that are used to display
+ * TODO: think about a way to inform KHexEdit that there has been
+ * a change in the buffer outside. what kind of changes are possible?
+ *@author Friedrich W. H. Kossebau
+ */
+
+class KFixedSizeBuffer : public KDataBuffer
+{
+ public:
+ /** creates a readonly buffer around the given data */
+ KFixedSizeBuffer( char *D, unsigned int S, char FUC = '\0' );
+ /** creates a writeable buffer which is deleted at the end */
+ KFixedSizeBuffer( unsigned int S, char FUC = '\0' );
+ virtual ~KFixedSizeBuffer();
+
+ public: // KDataBuffer API
+ virtual bool prepareRange( KSection Range ) const;
+ virtual const char *dataSet( KSection S ) const;
+ virtual char datum( unsigned int Offset ) const;
+ virtual int size() const;
+ virtual bool isReadOnly() const;
+ virtual bool isModified() const;
+
+ virtual int insert( int Pos, const char*, int Length );
+ virtual int remove( KSection Remove );
+ virtual unsigned int replace( KSection Remove, const char*, unsigned int InputLength );
+ virtual int move( int DestPos, KSection SourceSection );
+ virtual int fill( const char FillChar, int Length = -1, unsigned int Pos = 0 );
+ virtual void setDatum( unsigned int Offset, const char Char );
+
+ virtual void setModified( bool M = true );
+
+ virtual int find( const char*KeyData, int Length, KSection Section ) const;
+ virtual int rfind( const char*, int Length, int Pos = -1 ) const;
+
+/* virtual int find( const QString &expr, bool cs, bool wo, bool forward = true, int *index = 0 ); */
+
+ public:
+ void setReadOnly( bool RO = true );
+ int compare( const KDataBuffer &Other, KSection Range, unsigned int Pos = 0 );
+ int compare( const KDataBuffer &Other, int OtherPos, int Length, unsigned int Pos = 0 );
+ int compare( const KDataBuffer &Other );
+
+ public:
+ char *rawData() const;
+
+ protected:
+ void reset( unsigned int Pos, unsigned int Length );
+
+ protected:
+ /** */
+ char *Data;
+ /***/
+ unsigned int Size;
+ /** */
+ char FillUpChar;
+ /** */
+ bool ReadOnly:1;
+ /** */
+ bool Modified:1;
+ /** */
+ bool AutoDelete:1;
+};
+
+
+inline bool KFixedSizeBuffer::prepareRange( KSection ) const { return true; }
+inline const char *KFixedSizeBuffer::dataSet( KSection S ) const { return &Data[S.start()]; }
+
+inline char KFixedSizeBuffer::datum( unsigned int Offset ) const { return Data[Offset]; }
+inline int KFixedSizeBuffer::size() const { return Size; }
+
+inline void KFixedSizeBuffer::setDatum( unsigned int Offset, const char Char )
+{ Data[Offset] = Char; Modified = true; }
+
+inline bool KFixedSizeBuffer::isReadOnly() const { return ReadOnly; }
+inline bool KFixedSizeBuffer::isModified() const { return Modified; }
+
+inline void KFixedSizeBuffer::setReadOnly( bool RO ) { ReadOnly = RO; }
+inline void KFixedSizeBuffer::setModified( bool M ) { Modified = M; }
+
+inline int KFixedSizeBuffer::compare( const KDataBuffer &Other )
+{ return compare( Other, KSection(0,Other.size()-1),0 ); }
+
+inline int KFixedSizeBuffer::compare( const KDataBuffer &Other, int OtherPos, int Length, unsigned int Pos )
+{ return compare( Other, KSection(OtherPos,Length,true),Pos ); }
+
+inline char *KFixedSizeBuffer::rawData() const { return Data; }
+
+}
+
+#endif
diff --git a/khexedit/lib/khe.h b/khexedit/lib/khe.h
new file mode 100644
index 0000000..af029ea
--- /dev/null
+++ b/khexedit/lib/khe.h
@@ -0,0 +1,95 @@
+/***************************************************************************
+ khe.h - description
+ -------------------
+ begin : Mon Jul 14 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KHE_H
+#define KHE_KHE_H
+
+// here we collect all general data
+// let's see how much it gets ;)
+
+namespace KHE
+{
+ enum KCoding { HexadecimalCoding=0, DecimalCoding=1, OctalCoding=2, BinaryCoding=3, MaxCodingId=0xFFFF };
+ static const int NoOfCodings = 4;
+
+ /** */
+ enum KEncoding
+ {
+ /** the coding of your shell */
+ LocalEncoding=0,
+ /** ASCII encoding, also known as Latin1 */
+ ISO8859_1Encoding,
+ /** */
+ ISO8859_2Encoding,
+ /** */
+ ISO8859_3Encoding,
+ /** */
+ ISO8859_4Encoding,
+ /** */
+ ISO8859_5Encoding,
+ /** */
+ ISO8859_6Encoding,
+ /** */
+ ISO8859_7Encoding,
+ /** */
+ ISO8859_8Encoding,
+ /** */
+ ISO8859_8_IEncoding,
+ /** */
+ ISO8859_9Encoding,
+ /** */
+ ISO8859_11Encoding,
+ /** */
+ ISO8859_13Encoding,
+ /** */
+ ISO8859_15Encoding,
+ /** */
+ CP1250Encoding,
+ /** */
+ CP1251Encoding,
+ /** */
+ CP1252Encoding,
+ /** */
+ CP1253Encoding,
+ /** */
+ CP1254Encoding,
+ /** */
+ CP1255Encoding,
+ /** */
+ CP1256Encoding,
+ /** */
+ CP1257Encoding,
+ /** */
+ CP1258Encoding,
+ /** */
+ IBM850Encoding,
+ /** */
+ IBM866Encoding,
+ /** */
+ KOI8_REncoding,
+ /** */
+ KOI8_UEncoding,
+ /** the most common EBCDIC codepage */
+ EBCDIC1047Encoding,
+ /** Offset for own encodings which are bound in by plugins */
+ StartOfOwnEncoding=0x8000,
+ /** this should enable extension without breaking binary compatibility */
+ MaxEncodingId=0xFFFF
+ };
+}
+
+#endif
diff --git a/khexedit/lib/khechar.h b/khexedit/lib/khechar.h
new file mode 100644
index 0000000..4f51e9e
--- /dev/null
+++ b/khexedit/lib/khechar.h
@@ -0,0 +1,44 @@
+/***************************************************************************
+ helper.h - description
+ -------------------
+ begin : Do Nov 25 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+#ifndef KHE_KHECHAR_H
+#define KHE_KHECHAR_H
+
+// qt specific
+#include <qstring.h>
+
+namespace KHE
+{
+
+class KHEChar : public QChar
+{
+ public:
+ KHEChar( QChar C );
+ KHEChar( QChar C, bool U );
+ public:
+ bool isUndefined() const;
+ protected:
+ // the byte is not defined
+ bool IsUndefined:1;
+};
+
+inline KHEChar::KHEChar( QChar C ) : QChar( C ), IsUndefined( false ) {}
+inline KHEChar::KHEChar( QChar C, bool U ) : QChar( C ), IsUndefined( U ) {}
+inline bool KHEChar::isUndefined() const { return IsUndefined; }
+
+}
+
+#endif
diff --git a/khexedit/lib/khexedit.cpp b/khexedit/lib/khexedit.cpp
new file mode 100644
index 0000000..85478e5
--- /dev/null
+++ b/khexedit/lib/khexedit.cpp
@@ -0,0 +1,2032 @@
+/***************************************************************************
+ khexedit.cpp - description
+ -------------------
+ begin : Die Mai 13 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+//#include <kdebug.h>
+
+// c specific
+#include <stdlib.h>
+//#include <limits.h>
+// c++ specific
+//#include <limits>
+// qt specific
+#include <qstyle.h>
+#include <qpainter.h>
+#include <qtimer.h>
+#include <qcursor.h>
+#include <qapplication.h>
+// kde specific
+#ifndef QT_ONLY
+#include <kglobalsettings.h>
+#endif
+// lib specific
+#include "kdatabuffer.h"
+#include "koffsetcolumn.h"
+#include "kvaluecolumn.h"
+#include "kcharcolumn.h"
+#include "kbordercolumn.h"
+#include "kbuffercursor.h"
+#include "kbufferlayout.h"
+#include "kbufferranges.h"
+#include "controller/ktabcontroller.h"
+#include "controller/knavigator.h"
+#include "controller/kvalueeditor.h"
+#include "controller/kchareditor.h"
+#include "kbufferdrag.h"
+#include "kcursor.h"
+#include "kbytecodec.h"
+#include "kcharcodec.h"
+#include "kwordbufferservice.h"
+#include "khexedit.h"
+
+using namespace KHE;
+
+// zooming is done in steps of font size points
+static const int DefaultZoomStep = 1;
+static const int DefaultStartOffset = 0;//5;
+static const int DefaultFirstLineOffset = 0;
+static const int DefaultNoOfBytesPerLine = 16;
+static const KHexEdit::KResizeStyle DefaultResizeStyle = KHexEdit::FullSizeUsage;
+static const KHexEdit::KEncoding DefaultEncoding = KHexEdit::LocalEncoding;
+static const int DefaultScrollTimerPeriod = 100;
+static const int InsertCursorWidth = 2;
+
+
+
+KHexEdit::KHexEdit( KDataBuffer *Buffer, QWidget *Parent, const char *Name, WFlags Flags )
+ : KColumnsView( Parent, Name, Flags ),
+ DataBuffer( Buffer ),
+ BufferLayout( new KBufferLayout(DefaultNoOfBytesPerLine,DefaultStartOffset,0) ),
+ BufferCursor( new KBufferCursor(BufferLayout) ),
+ BufferRanges( new KBufferRanges(BufferLayout) ),
+ CursorBlinkTimer( new QTimer(this) ),
+ ScrollTimer( new QTimer(this) ),
+ DragStartTimer( new QTimer(this) ),
+ TrippleClickTimer( new QTimer(this) ),
+ CursorPixmaps( new KCursor() ),
+ Codec( 0 ),
+ ClipboardMode( QClipboard::Clipboard ),
+ ResizeStyle( DefaultResizeStyle ),
+ Encoding( MaxEncodingId ), // forces update
+ ReadOnly( false ),
+// Modified( false ),
+ OverWriteOnly( false ),
+ OverWrite( true ),
+ MousePressed( false ),
+ InDoubleClick( false ),
+ InDnD( false ),
+ DragStartPossible( false ),
+ CursorPaused( false ),
+ BlinkCursorVisible( false ),
+ InZooming( false ),
+ d( 0 )
+{
+ // initalize layout
+ if( DataBuffer )
+ BufferLayout->setLength( DataBuffer->size() );
+ BufferLayout->setNoOfLinesPerPage( noOfLinesPerPage() );
+
+ // creating the columns in the needed order
+ OffsetColumn = new KOffsetColumn( this, DefaultFirstLineOffset, DefaultNoOfBytesPerLine, KOffsetFormat::Hexadecimal );
+ FirstBorderColumn = new KBorderColumn( this, false );
+ ValueColumn = new KValueColumn( this, DataBuffer, BufferLayout, BufferRanges );
+ SecondBorderColumn = new KBorderColumn( this, true );
+ CharColumn = new KCharColumn( this, DataBuffer, BufferLayout, BufferRanges );
+
+ // select the active column
+ ActiveColumn = &charColumn();
+ InactiveColumn = &valueColumn();
+
+ // set encoding
+ Codec = KCharCodec::createCodec( (KHE::KEncoding)DefaultEncoding );
+ valueColumn().setCodec( Codec );
+ charColumn().setCodec( Codec );
+ Encoding = DefaultEncoding;
+
+ TabController = new KTabController( this, 0 );
+ Navigator = new KNavigator( this, TabController );
+ ValueEditor = new KValueEditor( ValueColumn, BufferCursor, this, Navigator );
+ CharEditor = new KCharEditor( CharColumn, BufferCursor, this, Navigator );
+
+ Controller = Navigator;
+
+#ifdef QT_ONLY
+ QFont FixedFont( "fixed", 10 );
+ FixedFont.setFixedPitch( true );
+ setFont( FixedFont );
+#else
+ setFont( KGlobalSettings::fixedFont() );
+#endif
+
+ // get the full control
+ viewport()->setFocusProxy( this );
+ viewport()->setFocusPolicy( WheelFocus );
+
+ viewport()->installEventFilter( this );
+ installEventFilter( this );
+
+ connect( CursorBlinkTimer, SIGNAL(timeout()), this, SLOT(blinkCursor()) );
+ connect( ScrollTimer, SIGNAL(timeout()), this, SLOT(autoScrollTimerDone()) );
+ connect( DragStartTimer, SIGNAL(timeout()), this, SLOT(startDrag()) );
+
+ viewport()->setAcceptDrops( true );
+}
+
+
+KHexEdit::~KHexEdit()
+{
+ delete TabController;
+ delete Navigator;
+ delete ValueEditor;
+ delete CharEditor;
+}
+
+
+int KHexEdit::noOfBytesPerLine() const { return BufferLayout->noOfBytesPerLine(); }
+int KHexEdit::firstLineOffset() const { return OffsetColumn->firstLineOffset(); }
+int KHexEdit::startOffset() const { return BufferLayout->startOffset(); }
+KHexEdit::KResizeStyle KHexEdit::resizeStyle() const { return ResizeStyle; }
+KHexEdit::KCoding KHexEdit::coding() const { return (KHexEdit::KCoding)valueColumn().coding(); }
+KPixelX KHexEdit::byteSpacingWidth() const { return valueColumn().byteSpacingWidth(); }
+int KHexEdit::noOfGroupedBytes() const { return valueColumn().noOfGroupedBytes(); }
+KPixelX KHexEdit::groupSpacingWidth() const { return valueColumn().groupSpacingWidth(); }
+KPixelX KHexEdit::binaryGapWidth() const { return valueColumn().binaryGapWidth(); }
+bool KHexEdit::isOverwriteMode() const { return OverWrite; }
+bool KHexEdit::isOverwriteOnly() const { return OverWriteOnly; }
+bool KHexEdit::isReadOnly() const { return ReadOnly; }
+bool KHexEdit::isModified() const { return DataBuffer->isModified(); }
+bool KHexEdit::tabChangesFocus() const { return TabController->tabChangesFocus(); }
+bool KHexEdit::showUnprintable() const { return charColumn().showUnprintable(); }
+QChar KHexEdit::substituteChar() const { return charColumn().substituteChar(); }
+QChar KHexEdit::undefinedChar() const { return charColumn().undefinedChar(); }
+KHexEdit::KEncoding KHexEdit::encoding() const { return (KHexEdit::KEncoding)Encoding; }
+const QString &KHexEdit::encodingName() const { return Codec->name(); }
+
+KSection KHexEdit::selection() const { return BufferRanges->selection(); }
+int KHexEdit::cursorPosition() const { return BufferCursor->index(); }
+bool KHexEdit::isCursorBehind() const { return BufferCursor->isBehind(); }
+KHexEdit::KBufferColumnId KHexEdit::cursorColumn() const
+{ return static_cast<KHE::KValueColumn *>( ActiveColumn ) == &valueColumn()? ValueColumnId : CharColumnId; }
+
+void KHexEdit::setOverwriteOnly( bool OO ) { OverWriteOnly = OO; if( OverWriteOnly ) setOverwriteMode( true ); }
+void KHexEdit::setModified( bool M ) { DataBuffer->setModified(M); }
+void KHexEdit::setTabChangesFocus( bool TCF ) { TabController->setTabChangesFocus(TCF); }
+void KHexEdit::setFirstLineOffset( int FLO ) { OffsetColumn->setFirstLineOffset( FLO ); }
+
+bool KHexEdit::offsetColumnVisible() const { return OffsetColumn->isVisible(); }
+int KHexEdit::visibleBufferColumns() const
+{ return (valueColumn().isVisible() ? ValueColumnId : 0) | (charColumn().isVisible() ? CharColumnId : 0); }
+
+
+void KHexEdit::setOverwriteMode( bool OM )
+{
+ if( (OverWriteOnly && !OM) || (OverWrite == OM) )
+ return;
+
+ OverWrite = OM;
+
+ // affected:
+ // cursor shape
+ bool ChangeCursor = !( CursorPaused || ValueEditor->isInEditMode() );
+ if( ChangeCursor )
+ pauseCursor();
+
+ BufferCursor->setAppendPosEnabled( !OverWrite );
+
+ if( ChangeCursor )
+ unpauseCursor();
+
+ emit cutAvailable( !OverWrite && BufferRanges->hasSelection() );
+}
+
+
+void KHexEdit::setDataBuffer( KDataBuffer *B )
+{
+ //pauseCursor();
+ ValueEditor->reset();
+ CursorPaused = true;
+
+ DataBuffer = B;
+ valueColumn().set( DataBuffer );
+ charColumn().set( DataBuffer);
+
+ // affected:
+ // length -> no of lines -> width
+ BufferLayout->setLength( DataBuffer->size() );
+ adjustLayoutToSize();
+
+ // ensure that the widget is readonly if the buffer is
+ if( DataBuffer->isReadOnly() )
+ setReadOnly( true );
+
+ updateView();
+ BufferCursor->gotoStart();
+ ensureCursorVisible();
+ unpauseCursor();
+}
+
+
+void KHexEdit::setStartOffset( int SO )
+{
+ if( !BufferLayout->setStartOffset(SO) )
+ return;
+
+ pauseCursor();
+ // affects:
+ // the no of lines -> width
+ adjustLayoutToSize();
+
+ updateView();
+
+ BufferCursor->updateCoord();
+ ensureCursorVisible();
+ unpauseCursor();
+}
+
+
+void KHexEdit::setReadOnly( bool RO )
+{
+ // don't set editor readwrite if databuffer is readonly
+ ReadOnly = (DataBuffer && DataBuffer->isReadOnly()) ? true : RO;
+
+ Controller = ReadOnly ? (KController*)Navigator :
+ cursorColumn() == CharColumnId ? (KController*)CharEditor : (KController*)ValueEditor;
+}
+
+
+void KHexEdit::setBufferSpacing( KPixelX ByteSpacing, int NoOfGroupedBytes, KPixelX GroupSpacing )
+{
+ if( !valueColumn().setSpacing(ByteSpacing,NoOfGroupedBytes,GroupSpacing) )
+ return;
+
+ updateViewByWidth();
+}
+
+
+void KHexEdit::setCoding( KCoding C )
+{
+ uint OldCodingWidth = valueColumn().byteCodec()->encodingWidth();
+
+ if( !valueColumn().setCoding((KHE::KCoding)C) )
+ return;
+
+ uint NewCodingWidth = valueColumn().byteCodec()->encodingWidth();
+ ValueEditor->ByteBuffer.setLength( NewCodingWidth ); //hack for now
+
+ // no change in the width?
+ if( NewCodingWidth == OldCodingWidth )
+ updateColumn( valueColumn() );
+ else
+ updateViewByWidth();
+}
+
+
+void KHexEdit::setResizeStyle( KResizeStyle NewStyle )
+{
+ if( ResizeStyle == NewStyle )
+ return;
+
+ ResizeStyle = NewStyle;
+
+ updateViewByWidth();
+}
+
+
+void KHexEdit::setNoOfBytesPerLine( int NoBpL )
+{
+ // if the number is explicitly set we expect a wish for no automatic resize
+ ResizeStyle = NoResize;
+
+ if( !BufferLayout->setNoOfBytesPerLine(NoBpL) )
+ return;
+ updateViewByWidth();
+}
+
+
+void KHexEdit::setByteSpacingWidth( int/*KPixelX*/ BSW )
+{
+ if( !valueColumn().setByteSpacingWidth(BSW) )
+ return;
+ updateViewByWidth();
+}
+
+void KHexEdit::setNoOfGroupedBytes( int NoGB )
+{
+ if( !valueColumn().setNoOfGroupedBytes(NoGB) )
+ return;
+ updateViewByWidth();
+}
+
+
+void KHexEdit::setGroupSpacingWidth( int/*KPixelX*/ GSW )
+{
+ if( !valueColumn().setGroupSpacingWidth(GSW) )
+ return;
+ updateViewByWidth();
+}
+
+
+void KHexEdit::setBinaryGapWidth( int/*KPixelX*/ BGW )
+{
+ if( !valueColumn().setBinaryGapWidth(BGW) )
+ return;
+ updateViewByWidth();
+}
+
+
+void KHexEdit::setSubstituteChar( QChar SC )
+{
+ if( !charColumn().setSubstituteChar(SC) )
+ return;
+ pauseCursor();
+ updateColumn( charColumn() );
+ unpauseCursor();
+}
+
+void KHexEdit::setUndefinedChar( QChar UC )
+{
+ if( !charColumn().setUndefinedChar(UC) )
+ return;
+ pauseCursor();
+ updateColumn( charColumn() );
+ unpauseCursor();
+}
+
+void KHexEdit::setShowUnprintable( bool SU )
+{
+ if( !charColumn().setShowUnprintable(SU) )
+ return;
+ pauseCursor();
+ updateColumn( charColumn() );
+ unpauseCursor();
+}
+
+
+void KHexEdit::setEncoding( KEncoding C )
+{
+ if( Encoding == C )
+ return;
+
+ KCharCodec *NC = KCharCodec::createCodec( (KHE::KEncoding)C );
+ if( NC == 0 )
+ return;
+
+ valueColumn().setCodec( NC );
+ charColumn().setCodec( NC );
+
+ delete Codec;
+ Codec = NC;
+ Encoding = C;
+
+ pauseCursor();
+ updateColumn( valueColumn() );
+ updateColumn( charColumn() );
+ unpauseCursor();
+}
+
+// TODO: join with function above!
+void KHexEdit::setEncoding( const QString& EncodingName )
+{
+ if( EncodingName == Codec->name() )
+ return;
+
+ KCharCodec *NC = KCharCodec::createCodec( EncodingName );
+ if( NC == 0 )
+ return;
+
+ valueColumn().setCodec( NC );
+ charColumn().setCodec( NC );
+
+ delete Codec;
+ Codec = NC;
+ Encoding = LocalEncoding; // TODO: add encoding no to every known codec
+
+ pauseCursor();
+ updateColumn( valueColumn() );
+ updateColumn( charColumn() );
+ unpauseCursor();
+}
+
+
+void KHexEdit::fontChange( const QFont &OldFont )
+{
+ QScrollView::fontChange( OldFont );
+
+ if( !InZooming )
+ DefaultFontSize = font().pointSize();
+
+ // get new values
+ QFontMetrics FM( fontMetrics() );
+ KPixelX DigitWidth = FM.maxWidth();
+ KPixelY DigitBaseLine = FM.ascent();
+
+ setLineHeight( FM.height() );
+
+ // update all dependant structures
+ BufferLayout->setNoOfLinesPerPage( noOfLinesPerPage() );
+
+ OffsetColumn->setMetrics( DigitWidth, DigitBaseLine );
+ valueColumn().setMetrics( DigitWidth, DigitBaseLine );
+ charColumn().setMetrics( DigitWidth, DigitBaseLine );
+
+ updateViewByWidth();
+}
+
+
+void KHexEdit::updateViewByWidth()
+{
+ pauseCursor();
+
+ adjustToLayoutNoOfBytesPerLine();
+ adjustLayoutToSize();
+
+ updateView();
+
+ BufferCursor->updateCoord();
+ ensureCursorVisible();
+
+ unpauseCursor();
+}
+
+
+void KHexEdit::zoomIn() { zoomIn( DefaultZoomStep ); }
+void KHexEdit::zoomOut() { zoomOut( DefaultZoomStep ); }
+
+void KHexEdit::zoomIn( int PointInc )
+{
+ InZooming = true;
+ QFont F( font() );
+ F.setPointSize( QFontInfo(F).pointSize() + PointInc );
+ setFont( F );
+ InZooming = false;
+}
+
+void KHexEdit::zoomOut( int PointDec )
+{
+ InZooming = true;
+ QFont F( font() );
+ F.setPointSize( QMAX( 1, QFontInfo(F).pointSize() - PointDec ) );
+ setFont( F );
+ InZooming = false;
+}
+
+
+void KHexEdit::zoomTo( int PointSize )
+{
+ InZooming = true;
+ QFont F( font() );
+ F.setPointSize( PointSize );
+ setFont( F );
+ InZooming = false;
+}
+
+
+void KHexEdit::unZoom()
+{
+ zoomTo( DefaultFontSize );
+}
+
+
+void KHexEdit::adjustLayoutToSize()
+{
+ // check whether there is a change with the numbers of fitting bytes per line
+ if( ResizeStyle != NoResize )
+ {
+ int FittingBytesPerLine = fittingBytesPerLine( size() );
+
+// std::cout<<"FitBpL"<<FittingBytesPerLine<<std::endl;
+
+ // changes?
+ if( BufferLayout->setNoOfBytesPerLine(FittingBytesPerLine) )
+ adjustToLayoutNoOfBytesPerLine();
+ }
+
+ setNoOfLines( BufferLayout->noOfLines() );
+}
+
+
+void KHexEdit::adjustToLayoutNoOfBytesPerLine()
+{
+ OffsetColumn->setDelta( BufferLayout->noOfBytesPerLine() );
+ valueColumn().resetXBuffer();
+ charColumn().resetXBuffer();
+
+ updateWidths();
+}
+
+
+void KHexEdit::setNoOfLines( int NewNoOfLines )
+{
+ KColumnsView::setNoOfLines( NewNoOfLines>1?NewNoOfLines:1 );
+}
+
+
+void KHexEdit::toggleOffsetColumn( bool Visible )
+{
+ bool OCVisible = OffsetColumn->isVisible();
+ // no change?
+ if( OCVisible == Visible )
+ return;
+
+ OffsetColumn->setVisible( Visible );
+ FirstBorderColumn->setVisible( Visible );
+
+ updateViewByWidth();
+}
+
+
+QSize KHexEdit::sizeHint() const
+{
+ return QSize( totalWidth(), totalHeight() );
+}
+
+
+QSize KHexEdit::minimumSizeHint() const
+{
+ // TODO: better minimal width (visibility!)
+ return QSize( OffsetColumn->visibleWidth()+FirstBorderColumn->visibleWidth()+SecondBorderColumn->visibleWidth()+valueColumn().byteWidth()+charColumn().byteWidth(),
+ lineHeight() + noOfLines()>1? style().pixelMetric(QStyle::PM_ScrollBarExtent):0 );
+}
+
+
+void KHexEdit::resizeEvent( QResizeEvent *ResizeEvent )
+{
+ if( ResizeStyle != NoResize )
+ {
+ int FittingBytesPerLine = fittingBytesPerLine( ResizeEvent->size() );
+
+ // changes?
+ if( BufferLayout->setNoOfBytesPerLine(FittingBytesPerLine) )
+ {
+ setNoOfLines( BufferLayout->noOfLines() );
+ updateViewByWidth();
+ }
+ }
+
+ QScrollView::resizeEvent( ResizeEvent );
+
+ BufferLayout->setNoOfLinesPerPage( noOfLinesPerPage() ); // TODO: doesn't work with the new size!!!
+}
+
+
+int KHexEdit::fittingBytesPerLine( const QSize &NewSize ) const
+{
+ KPixelX ReservedWidth = OffsetColumn->visibleWidth() + FirstBorderColumn->visibleWidth() + SecondBorderColumn->visibleWidth();
+
+ // abstract framewidth as well as offset and border columns width
+ int UsedbyFrameWidth = 2 * frameWidth();
+ KPixelX FullWidth = NewSize.width() - UsedbyFrameWidth - ReservedWidth;
+
+// // no width left for resizeable columns? TODO: put this in resizeEvent
+// if( FullWidth < 0 )
+// return;
+
+ KPixelY FullHeight = NewSize.height() - UsedbyFrameWidth;
+
+ // check influence of dis-/appearing of the vertical scrollbar
+ bool VerticalScrollbarIsVisible = verticalScrollBar()->isVisible();
+ KPixelX ScrollbarExtent = style().pixelMetric( QStyle::PM_ScrollBarExtent );//verticalScrollBar()->width();
+
+ KPixelX AvailableWidth = FullWidth;
+ if( VerticalScrollbarIsVisible )
+ AvailableWidth -= ScrollbarExtent;
+
+ enum KMatchTrial { FirstRun, RerunWithScrollbarOn, TestWithoutScrollbar };
+ KMatchTrial MatchRun = FirstRun;
+
+ // prepare needed values
+ KPixelX DigitWidth = valueColumn().digitWidth();
+ KPixelX TextByteWidth = charColumn().isVisible() ? DigitWidth : 0;
+ KPixelX HexByteWidth = valueColumn().isVisible() ? valueColumn().byteWidth() : 0;
+ KPixelX ByteSpacingWidth = valueColumn().isVisible() ? valueColumn().byteSpacingWidth() : 0;
+ KPixelX GroupSpacingWidth;
+ int NoOfGroupedBytes = valueColumn().noOfGroupedBytes();
+ // no grouping?
+ if( NoOfGroupedBytes == 0 )
+ {
+ // faking grouping by 1
+ NoOfGroupedBytes = 1;
+ GroupSpacingWidth = 0;
+ }
+ else
+ GroupSpacingWidth = valueColumn().isVisible() ? valueColumn().groupSpacingWidth() : 0;
+
+ KPixelX HexByteGroupWidth = NoOfGroupedBytes * HexByteWidth + (NoOfGroupedBytes-1)*ByteSpacingWidth;
+ KPixelX TextByteGroupWidth = NoOfGroupedBytes * TextByteWidth;
+ KPixelX TotalGroupWidth = HexByteGroupWidth + GroupSpacingWidth + TextByteGroupWidth;
+
+ int FittingBytesPerLine;
+ int WithScrollbarFittingBytesPerLine = 0;
+ for(;;)
+ {
+// std::cout << "matchWidth: " << FullWidth
+// << " (v:" << visibleWidth()
+// << ", f:" << frameWidth()
+// << ", A:" << AvailableWidth
+// << ", S:" << ScrollbarExtent
+// << ", R:" << ReservedWidth << ")" << std::endl;
+
+ // calculate fitting groups per line
+ int FittingGroupsPerLine = (AvailableWidth+GroupSpacingWidth) // fake spacing after last group
+ / TotalGroupWidth;
+
+ // calculate the fitting bytes per line by groups
+ FittingBytesPerLine = NoOfGroupedBytes * FittingGroupsPerLine;
+
+ // not only full groups?
+ if( ResizeStyle == FullSizeUsage && NoOfGroupedBytes > 1 )
+ {
+ if( FittingGroupsPerLine > 0 )
+ AvailableWidth -= FittingGroupsPerLine*TotalGroupWidth; // includes additional spacing after last group
+
+// std::cout << "Left: " << AvailableWidth << "("<<HexByteWidth<<", "<<TextByteWidth<<")" << std::endl;
+
+ if( AvailableWidth > 0 )
+ FittingBytesPerLine += (AvailableWidth+ByteSpacingWidth) / (HexByteWidth+ByteSpacingWidth+TextByteWidth);
+
+ // is there not even the space for a single byte?
+ if( FittingBytesPerLine == 0 )
+ {
+ // ensure at least one byte per line
+ FittingBytesPerLine = 1;
+ // and
+ break;
+ }
+ }
+ // is there not the space for a single group?
+ else if( FittingBytesPerLine == 0 )
+ {
+ // ensures at least one group
+ FittingBytesPerLine = NoOfGroupedBytes;
+ break;
+ }
+
+// std::cout << "meantime: " << FittingGroupsPerLine << " (T:" << TotalGroupWidth
+// << ", h:" << HexByteGroupWidth
+// << ", t:" << TextByteGroupWidth
+// << ", s:" << GroupSpacingWidth << ") " <<FittingBytesPerLine<< std::endl;
+
+ int NewNoOfLines = (BufferLayout->length()+BufferLayout->startOffset()+FittingBytesPerLine-1)
+ / FittingBytesPerLine;
+ KPixelY NewHeight = NewNoOfLines * LineHeight;
+
+ if( VerticalScrollbarIsVisible )
+ {
+ if( MatchRun == TestWithoutScrollbar )
+ {
+ // did the test without the scrollbar fail, don't the data fit into the view?
+ if( NewHeight>FullHeight )
+ // reset to old calculated value
+ FittingBytesPerLine = WithScrollbarFittingBytesPerLine;
+ break;
+ }
+
+ // a chance for to perhaps fit in height?
+ if( FittingBytesPerLine <= BufferLayout->noOfBytesPerLine() )
+ {
+ // remember this trial's result and calc number of bytes with vertical scrollbar on
+ WithScrollbarFittingBytesPerLine = FittingBytesPerLine;
+ AvailableWidth = FullWidth;
+ MatchRun = TestWithoutScrollbar;
+// std::cout << "tested without scrollbar..." << std::endl;
+ continue;
+ }
+ }
+ else
+ {
+ // doesn't it fit into the height anymore?
+ if( NewHeight>FullHeight && MatchRun==FirstRun )
+ {
+ // need for a scrollbar has risen... ->less width, new calculation
+ AvailableWidth = FullWidth - ScrollbarExtent;
+ MatchRun = RerunWithScrollbarOn;
+// std::cout << "rerun with scrollbar on..." << std::endl;
+ continue;
+ }
+ }
+
+ break;
+ }
+
+ return FittingBytesPerLine;
+}
+
+
+bool KHexEdit::selectWord( /*unsigned TODO:change all unneeded signed into unsigned!*/ int Index )
+{
+ if( Index >= 0 && Index < BufferLayout->length() )
+ {
+ KWordBufferService WBS( DataBuffer, Codec );
+ KSection WordSection = WBS.wordSection( Index );
+ if( WordSection.isValid() )
+ {
+ pauseCursor();
+
+ BufferRanges->setFirstWordSelection( WordSection );
+ BufferCursor->gotoIndex( WordSection.end()+1 );
+ repaintChanged();
+
+ unpauseCursor();
+ return true;
+ }
+ }
+ return false;
+}
+
+void KHexEdit::select( KSection Section )
+{
+ if( !Section.isValid() )
+ return;
+
+ Section.restrictTo( KSection(0,BufferLayout->length()-1) );
+
+ pauseCursor();
+
+ BufferRanges->setSelection( Section );
+ BufferCursor->gotoIndex( Section.end()+1 );
+ repaintChanged();
+
+ unpauseCursor();
+
+ if( !OverWrite ) emit cutAvailable( BufferRanges->hasSelection() );
+ emit copyAvailable( BufferRanges->hasSelection() );
+ emit selectionChanged( Section.start(), Section.end() );
+}
+
+void KHexEdit::selectAll( bool Select )
+{
+ KSection Selection;
+
+ pauseCursor( true );
+
+ if( !Select )
+ BufferRanges->removeSelection();
+ else
+ {
+ Selection.set( 0, BufferLayout->length()-1 );
+ BufferRanges->setSelection( Selection );
+ BufferCursor->gotoEnd();
+ }
+
+ repaintChanged();
+
+ unpauseCursor();
+
+ if( !OverWrite ) emit cutAvailable( BufferRanges->hasSelection() );
+ emit copyAvailable( BufferRanges->hasSelection() );
+ emit selectionChanged( Selection.start(), Selection.end() );
+ viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
+}
+
+
+bool KHexEdit::hasSelectedData() const
+{
+ return BufferRanges->hasSelection();
+}
+
+
+QByteArray KHexEdit::selectedData() const
+{
+ if( !BufferRanges->hasSelection() )
+ return QByteArray();
+
+ KSection Selection = BufferRanges->selection();
+ QByteArray SD( Selection.width() );
+ DataBuffer->copyTo( SD.data(), Selection.start(), Selection.width() );
+ return SD;
+}
+
+
+KBufferDrag *KHexEdit::dragObject( QWidget *Parent ) const
+{
+ if( !BufferRanges->hasSelection() )
+ return 0;
+
+ const KOffsetColumn *OC;
+ const KValueColumn *HC;
+ const KCharColumn *TC;
+ KCoordRange Range;
+
+ if( static_cast<KHE::KCharColumn *>( ActiveColumn ) == &charColumn() )
+ {
+ OC = 0;
+ HC = 0;
+ TC = 0;
+ }
+ else
+ {
+ OC = OffsetColumn->isVisible() ? OffsetColumn : 0;
+ HC = valueColumn().isVisible() ? &valueColumn() : 0;
+ TC = charColumn().isVisible() ? &charColumn() : 0;
+ KSection S = BufferRanges->selection();
+ Range.set( BufferLayout->coordOfIndex(S.start()),BufferLayout->coordOfIndex(S.end()) );
+ }
+
+ return new KBufferDrag( selectedData(), Range, OC, HC, TC,
+ charColumn().substituteChar(), charColumn().undefinedChar(),
+ Codec->name(), Parent );
+}
+
+
+void KHexEdit::cut()
+{
+ if( isReadOnly() || OverWrite )
+ return;
+
+ KBufferDrag *Drag = dragObject();
+ if( !Drag )
+ return;
+
+ QApplication::clipboard()->setData( Drag, ClipboardMode );
+
+ removeSelectedData();
+}
+
+
+void KHexEdit::copy()
+{
+ KBufferDrag *Drag = dragObject();
+ if( !Drag )
+ return;
+
+ QApplication::clipboard()->setData( Drag, ClipboardMode );
+}
+
+
+void KHexEdit::paste()
+{
+ if( isReadOnly() )
+ return;
+
+ QMimeSource *Source = QApplication::clipboard()->data( ClipboardMode );
+ pasteFromSource( Source );
+}
+
+
+void KHexEdit::pasteFromSource( QMimeSource *Source )
+{
+ if( !Source || !KBufferDrag::canDecode(Source) )
+ return;
+
+ QByteArray Data;
+ if( !KBufferDrag::decode(Source,Data) )
+ return;
+
+ if( !Data.isEmpty() )
+ insert( Data );
+}
+
+
+void KHexEdit::insert( const QByteArray &D )
+{
+ pauseCursor( true );
+
+ KSection ChangedRange;
+
+ if( OverWrite )
+ {
+ if( BufferRanges->hasSelection() )
+ {
+ // replacing the selection:
+ // we restrict the replacement to the minimum length of selection and input
+ ChangedRange = BufferRanges->selection();
+ ChangedRange.restrictEndTo( ChangedRange.start()+D.size()-1 );
+ int W = DataBuffer->replace( ChangedRange, D.data(), ChangedRange.width() );
+ BufferCursor->gotoCIndex( ChangedRange.start()+W );
+ BufferRanges->removeSelection();
+ }
+ else
+ {
+ if( !BufferCursor->isBehind() )
+ {
+ // replacing the normal data, at least until the end
+ ChangedRange.setByWidth( BufferCursor->realIndex(), D.size() );
+ ChangedRange.restrictEndTo( BufferLayout->length()-1 );
+ if( ChangedRange.isValid() )
+ {
+ int W = DataBuffer->replace( ChangedRange, D.data(), ChangedRange.width() );
+ BufferCursor->gotoNextByte( W );
+ }
+ }
+ }
+ }
+ else
+ {
+ if( BufferRanges->hasSelection() )
+ {
+ // replacing the selection
+ KSection Selection = BufferRanges->selection();
+ int OldLastIndex = BufferLayout->length() - 1;
+ int W = DataBuffer->replace( Selection, D.data(), D.size() );
+ updateLength();
+ BufferCursor->gotoIndex( Selection.start() + W );
+ if( W > 0 )
+ {
+ if( Selection.width() == (int)D.size() )
+ ChangedRange = Selection;
+ else
+ {
+ int NewLastIndex = DataBuffer->size() - 1;
+ ChangedRange.set( Selection.start(), NewLastIndex>OldLastIndex?NewLastIndex:OldLastIndex );
+ }
+ }
+ BufferRanges->removeSelection();
+ }
+ else
+ {
+ bool Appending = BufferCursor->atAppendPos();
+ int OldIndex = BufferCursor->realIndex();
+ int W = DataBuffer->insert( OldIndex, D.data(), D.size() );
+ updateLength();
+ // worked?
+ if( W > 0 )
+ {
+ if( Appending )
+ BufferCursor->gotoEnd();
+ else
+ BufferCursor->gotoNextByte( W );
+ ChangedRange.set( OldIndex, DataBuffer->size()-1 );
+ }
+ }
+ }
+
+ bool Changed = ChangedRange.isValid();
+ if( Changed )
+ {
+ BufferRanges->addChangedRange( ChangedRange );
+ repaintChanged();
+ }
+ ensureCursorVisible();
+
+ unpauseCursor();
+
+ if( Changed ) emit bufferChanged( ChangedRange.start(), ChangedRange.end() );
+ KSection Selection = BufferRanges->selection();
+ emit selectionChanged( Selection.start(), Selection.end() );
+}
+
+
+void KHexEdit::removeSelectedData()
+{
+ // Can't we do this?
+ if( isReadOnly() || OverWrite || ValueEditor->isInEditMode() )
+ return;
+
+ pauseCursor();
+
+ KSection Selection = BufferRanges->selection();
+
+ BufferRanges->removeFurtherSelections();
+
+ KSection ChangedRange = removeData( Selection );
+ BufferRanges->removeSelection();
+
+ repaintChanged();
+
+ BufferCursor->gotoCIndex( Selection.start() );
+
+ ensureCursorVisible();
+// clearUndoRedo();
+ viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
+
+ unpauseCursor();
+
+ if( ChangedRange.isValid() ) emit bufferChanged( ChangedRange.start(), ChangedRange.end() );
+ emit selectionChanged( -1, -1 );
+}
+
+
+KSection KHexEdit::removeData( KSection Indizes )
+{
+// if( undoEnabled )
+// {
+// checkUndoRedoInfo( UndoRedoInfo::RemoveSelected );
+// if( !undoRedoInfo.valid() )
+// {
+// doc->selectionStart( selNum, undoRedoInfo.id, undoRedoInfo.index );
+// undoRedoInfo.d->text = QString::null;
+// }
+// readFormats( c1, c2, undoRedoInfo.d->text, TRUE );
+// }
+
+ KSection ChangedRange( Indizes.start(), BufferLayout->length()-1 );
+ // do it!
+ DataBuffer->remove( Indizes );
+ updateLength();
+ BufferRanges->addChangedRange( ChangedRange );
+
+ return ChangedRange;
+}
+
+
+void KHexEdit::updateLength()
+{
+ BufferLayout->setLength( DataBuffer->size() );
+ setNoOfLines( BufferLayout->noOfLines() );
+}
+
+
+void KHexEdit::clipboardChanged()
+{
+ // don't listen to selection changes
+ disconnect( QApplication::clipboard(), SIGNAL(selectionChanged()), this, 0 );
+ selectAll( false );
+}
+
+
+void KHexEdit::setCursorPosition( int Index, bool Behind )
+{
+ pauseCursor( true );
+
+ BufferCursor->gotoCIndex( Index );
+ if( Behind )
+ BufferCursor->stepBehind();
+
+ BufferRanges->removeSelection();
+ bool RangesModifed = BufferRanges->isModified();
+ if( RangesModifed )
+ {
+ repaintChanged();
+
+ viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
+
+ }
+ ensureCursorVisible();
+ unpauseCursor();
+
+ if( RangesModifed )
+ {
+ if( !OverWrite ) emit cutAvailable( BufferRanges->hasSelection() );
+ emit copyAvailable( BufferRanges->hasSelection() );
+ emit selectionChanged( -1, -1 );
+ }
+}
+
+
+void KHexEdit::showBufferColumns( int CCs )
+{
+ int Columns = visibleBufferColumns();
+
+ // no changes or no column selected?
+ if( CCs == Columns || !(CCs&( ValueColumnId | CharColumnId )) )
+ return;
+
+ valueColumn().setVisible( ValueColumnId & CCs );
+ charColumn().setVisible( CharColumnId & CCs );
+ SecondBorderColumn->setVisible( CCs == (ValueColumnId|CharColumnId) );
+
+ // active column not visible anymore?
+ if( !activeColumn().isVisible() )
+ {
+ KBufferColumn *H = ActiveColumn;
+ ActiveColumn = InactiveColumn;
+ InactiveColumn = H;
+ Controller = ReadOnly ? (KController*)Navigator :
+ cursorColumn() == CharColumnId ? (KController*)CharEditor : (KController*)ValueEditor;
+ }
+
+ updateViewByWidth();
+}
+
+
+void KHexEdit::setCursorColumn( KBufferColumnId CC )
+{
+ // no changes or not visible?
+ if( CC == cursorColumn()
+ || (CC == ValueColumnId && !valueColumn().isVisible())
+ || (CC == CharColumnId && !charColumn().isVisible()) )
+ return;
+
+ pauseCursor( true );
+
+ if( CC == ValueColumnId )
+ {
+ ActiveColumn = &valueColumn();
+ InactiveColumn = &charColumn();
+ }
+ else
+ {
+ ActiveColumn = &charColumn();
+ InactiveColumn = &valueColumn();
+ }
+ Controller = ReadOnly ? (KController*)Navigator :
+ cursorColumn() == CharColumnId ? (KController*)CharEditor : (KController*)ValueEditor;
+
+ ensureCursorVisible();
+ unpauseCursor();
+}
+
+
+void KHexEdit::placeCursor( const QPoint &Point )
+{
+ resetInputContext();
+
+ // switch active column if needed
+ if( charColumn().isVisible() && Point.x() >= charColumn().x() )
+ {
+ ActiveColumn = &charColumn();
+ InactiveColumn = &valueColumn();
+ }
+ else
+ {
+ ActiveColumn = &valueColumn();
+ InactiveColumn = &charColumn();
+ }
+ Controller = ReadOnly ? (KController*)Navigator :
+ cursorColumn() == CharColumnId ? (KController*)CharEditor : (KController*)ValueEditor;
+
+ // get coord of click and whether this click was closer to the end of the pos
+ KBufferCoord C( activeColumn().magPosOfX(Point.x()), lineAt(Point.y()) );
+
+ BufferCursor->gotoCCoord( C );
+}
+
+
+int KHexEdit::indexByPoint( const QPoint &Point ) const
+{
+ const KBufferColumn *C;
+ if( charColumn().isVisible() && Point.x() >= charColumn().x() )
+ C = &charColumn();
+ else
+ C = &valueColumn();
+
+ KBufferCoord Coord( C->posOfX(Point.x()), lineAt(Point.y()) );
+
+ return BufferLayout->indexAtCCoord( Coord );
+}
+
+
+void KHexEdit::showEvent( QShowEvent *e )
+{
+ KColumnsView::showEvent( e );
+ BufferLayout->setNoOfLinesPerPage( noOfLinesPerPage() );
+}
+
+
+bool KHexEdit::eventFilter( QObject *O, QEvent *E )
+{
+ if( O == this || O == viewport() )
+ {
+ if( E->type() == QEvent::FocusIn )
+ {
+ startCursor();
+ }
+ else if( E->type() == QEvent::FocusOut )
+ {
+ stopCursor();
+ }
+ }
+
+// if( O == this && E->type() == QEvent::PaletteChange )
+// {
+// QColor old( viewport()->colorGroup().color(QColorGroup::Text) );
+//
+// if( old != colorGroup().color(QColorGroup::Text) )
+// {
+// QColor c( colorGroup().color(QColorGroup::Text) );
+// doc->setMinimumWidth( -1 );
+// doc->setDefaultFormat( doc->formatCollection()->defaultFormat()->font(), c );
+// lastFormatted = doc->firstParagraph();
+// formatMore();
+// repaintChanged();
+// }
+// }
+
+ return QScrollView::eventFilter( O, E );
+}
+
+
+void KHexEdit::blinkCursor()
+{
+ // skip the cursor drawing?
+ if( CursorPaused || ValueEditor->isInEditMode() )
+ return;
+
+ // switch the cursor state
+ paintActiveCursor( !BlinkCursorVisible );
+}
+
+
+void KHexEdit::startCursor()
+{
+ CursorPaused = false;
+
+ updateCursor();
+
+ CursorBlinkTimer->start( QApplication::cursorFlashTime()/2 );
+}
+
+
+void KHexEdit::unpauseCursor()
+{
+ CursorPaused = false;
+
+ if( CursorBlinkTimer->isActive() )
+ updateCursor();
+}
+
+
+void KHexEdit::updateCursor()
+{
+ createCursorPixmaps();
+
+ paintActiveCursor( true );
+ paintInactiveCursor( true );
+}
+
+
+void KHexEdit::stopCursor()
+{
+ CursorBlinkTimer->stop();
+
+ pauseCursor();
+}
+
+
+void KHexEdit::pauseCursor( bool LeaveEdit )
+{
+ paintActiveCursor( false );
+ paintInactiveCursor( false );
+
+ if( LeaveEdit )
+ ValueEditor->InEditMode = false;
+ CursorPaused = true;
+}
+
+
+void KHexEdit::createCursorPixmaps()
+{
+ // create CursorPixmaps
+ CursorPixmaps->setSize( activeColumn().byteWidth(), LineHeight );
+
+ int Index = BufferCursor->validIndex();
+
+ QPainter Paint;
+ Paint.begin( &CursorPixmaps->offPixmap(), this );
+ activeColumn().paintByte( &Paint, Index );
+ Paint.end();
+
+ Paint.begin( &CursorPixmaps->onPixmap(), this );
+ activeColumn().paintCursor( &Paint, Index );
+ Paint.end();
+
+ // calculat the shape
+ KPixelX CursorX;
+ KPixelX CursorW;
+ if( BufferCursor->isBehind() )
+ {
+ CursorX = QMAX( 0, CursorPixmaps->onPixmap().width()-InsertCursorWidth );
+ CursorW = InsertCursorWidth;
+ }
+ else
+ {
+ CursorX = 0;
+ CursorW = OverWrite ? -1 : InsertCursorWidth;
+ }
+ CursorPixmaps->setShape( CursorX, CursorW );
+}
+
+
+void KHexEdit::pointPainterToCursor( QPainter &Painter, const KBufferColumn &Column ) const
+{
+ int x = Column.xOfPos( BufferCursor->pos() ) - contentsX();
+ int y = LineHeight * BufferCursor->line() - contentsY();
+
+ Painter.begin( viewport() );
+ Painter.translate( x, y );
+}
+
+
+void KHexEdit::paintActiveCursor( bool CursorOn )
+{
+ // any reason to skip the cursor drawing?
+ if( !isUpdatesEnabled() || !viewport()->isUpdatesEnabled()
+ || (CursorOn && !hasFocus() && !viewport()->hasFocus() && !InDnD ) )
+ return;
+
+ QPainter Painter;
+ pointPainterToCursor( Painter, activeColumn() );
+
+ // paint edited byte?
+ if( ValueEditor->isInEditMode() )
+ {
+ int Index = BufferCursor->index();
+
+ if( CursorOn )
+ valueColumn().paintEditedByte( &Painter, ValueEditor->EditValue, ValueEditor->ByteBuffer );
+ else
+ valueColumn().paintByte( &Painter, Index );
+ }
+ else
+ {
+
+ Painter.drawPixmap( CursorPixmaps->cursorX(), 0,
+ CursorOn?CursorPixmaps->onPixmap():CursorPixmaps->offPixmap(),
+ CursorPixmaps->cursorX(),0,CursorPixmaps->cursorW(),-1 );
+ // store state
+ BlinkCursorVisible = CursorOn;
+ }
+}
+
+
+void KHexEdit::paintInactiveCursor( bool CursorOn )
+{
+ // any reason to skip the cursor drawing?
+ if( !isUpdatesEnabled()
+ || !viewport()->isUpdatesEnabled()
+ || !inactiveColumn().isVisible()
+ || (CursorOn && !hasFocus() && !viewport()->hasFocus() && !InDnD) )
+ return;
+
+ int Index = BufferCursor->validIndex();
+
+ QPainter Painter;
+ pointPainterToCursor( Painter, inactiveColumn() );
+ if( CursorOn )
+ {
+ KBufferColumn::KFrameStyle Style =
+ BufferCursor->isBehind() ? KBufferColumn::Right :
+ (OverWrite||ValueEditor->isInEditMode()) ? KBufferColumn::Frame :
+ KBufferColumn::Left;
+ inactiveColumn().paintFramedByte( &Painter, Index, Style );
+ }
+ else
+ inactiveColumn().paintByte( &Painter, Index );
+}
+
+
+void KHexEdit::drawContents( QPainter *P, int cx, int cy, int cw, int ch )
+{
+ KColumnsView::drawContents( P, cx, cy, cw, ch );
+ // TODO: update non blinking cursors. Should this perhaps be done in the buffercolumn?
+ // Then it needs to know about inactive, insideByte and the like... well...
+ // perhaps subclassing the buffer columns even more, to KCharColumn and KValueColumn?
+
+ if( !CursorPaused && visibleLines(KPixelYs(cy,ch,false)).includes(BufferCursor->line()) )
+ {
+ paintActiveCursor( true );
+ paintInactiveCursor( true );
+ }
+}
+
+void KHexEdit::updateColumn( KColumn &Column )
+{
+ //kdDebug(1501) << "updateColumn\n";
+ if( Column.isVisible() )
+ updateContents( Column.x(), 0, Column.width(), totalHeight() );
+}
+
+
+void KHexEdit::keyPressEvent( QKeyEvent *KeyEvent )
+{
+ if( !Controller->handleKeyPress( KeyEvent ) )
+ KeyEvent->ignore();
+}
+
+
+void KHexEdit::repaintChanged()
+{
+ if( !isUpdatesEnabled() || !viewport()->isUpdatesEnabled() || !BufferRanges->isModified() )
+ return;
+
+ // TODO: we do this only to let the scrollview handle new or removed lines. overlaps with repaintRange
+ resizeContents( totalWidth(), totalHeight() );
+
+ KPixelXs Xs( contentsX(), visibleWidth(), true );
+
+ // collect affected buffer columns
+ QPtrList<KBufferColumn> RepaintColumns;
+
+ KBufferColumn *C = ValueColumn;
+ while( true )
+ {
+ if( C->isVisible() && C->overlaps(Xs) )
+ {
+ RepaintColumns.append( C );
+ C->preparePainting( Xs );
+ }
+
+ if( C == CharColumn )
+ break;
+ C = CharColumn;
+ }
+
+ // any colums to paint?
+ if( RepaintColumns.count() > 0 )
+ {
+ KPixelYs Ys( contentsY(), visibleHeight(), true );
+
+ // calculate affected lines/indizes
+ KSection FullPositions( 0, BufferLayout->noOfBytesPerLine()-1 );
+ KCoordRange VisibleRange( FullPositions, visibleLines(Ys) );
+
+ KCoordRange ChangedRange;
+ // as there might be multiple selections on this line redo until no more is changed
+ while( hasChanged(VisibleRange,&ChangedRange) )
+ {
+// std::cout << " changed->"<<FirstChangedIndex<<","<<LastChangedIndex<<std::endl;
+
+ // only one line?
+ if( ChangedRange.start().line() == ChangedRange.end().line() )
+ for( KBufferColumn *C=RepaintColumns.first(); C; C=RepaintColumns.next() )
+ paintLine( C, ChangedRange.start().line(),
+ KSection(ChangedRange.start().pos(),ChangedRange.end().pos()) );
+ //
+ else
+ {
+ // first line
+ for( KBufferColumn *C=RepaintColumns.first(); C; C=RepaintColumns.next() )
+ paintLine( C, ChangedRange.start().line(),
+ KSection(ChangedRange.start().pos(),FullPositions.end()) );
+
+ // at least one full line?
+ for( int l = ChangedRange.start().line()+1; l < ChangedRange.end().line(); ++l )
+ for( KBufferColumn *C=RepaintColumns.first(); C; C=RepaintColumns.next() )
+ paintLine( C, l, FullPositions );
+
+ // last line
+ for( KBufferColumn *C=RepaintColumns.first(); C; C=RepaintColumns.next() )
+ paintLine( C, ChangedRange.end().line(),
+ KSection(FullPositions.start(),ChangedRange.end().pos()) );
+ }
+
+ // continue the search at the overnext index
+ VisibleRange.setStart( ChangedRange.end()+2 );
+ if( !VisibleRange.isValid() )
+ break;
+ }
+ }
+
+
+ // Paint possible removed bytes at the end of the last line
+ // Paint new/removed trailing lines
+// drawContents( P, cx, cy, cw, ch );
+ // Paint empty rects
+// paintEmptyArea( P, cx, cy, cw, ch );
+// BufferLayout->noOfLines()
+
+ BufferRanges->resetChangedRanges();
+}
+
+
+void KHexEdit::paintLine( KBufferColumn *C, int Line, KSection Positions )
+{
+ Positions.restrictTo( C->visiblePositions() );
+
+ // nothing to paint?
+ if( !Positions.isValid() )
+ return;
+// std::cout << " paintLine->"<<Line<< ":"<<FirstPos<<","<<LastPos<<std::endl;
+
+ // calculating pixel values
+ KPixelXs XPixels = C->wideXPixelsOfPos( Positions );
+
+ KPixelY cy = Line * LineHeight;
+
+ // to avoid flickers we first paint to the linebuffer
+ QPainter Paint;
+ Paint.begin( &LineBuffer, this );
+
+ Paint.translate( C->x(), 0 );
+ C->paintPositions( &Paint, Line, Positions );
+ Paint.translate( -C->x(), 0 );
+
+ if( HorizontalGrid && XPixels.start() < TotalWidth )
+ Paint.drawLine( XPixels.start(), LineHeight-1, XPixels.width(), LineHeight-1 ); // TODO: use a additional TotalHeight?
+
+ Paint.end();
+ // copy to screen
+ bitBlt( viewport(), XPixels.start() - contentsX(), cy - contentsY(),
+ &LineBuffer, XPixels.start(), 0, XPixels.width(), LineHeight );
+}
+
+
+bool KHexEdit::hasChanged( const KCoordRange &VisibleRange, KCoordRange *ChangedRange ) const
+{
+ if( !BufferRanges->overlapsChanges(VisibleRange,ChangedRange) )
+ return false;
+
+ ChangedRange->restrictTo( VisibleRange );
+ return true;
+}
+
+
+void KHexEdit::ensureCursorVisible()
+{
+// // Not visible or the user is draging the window, so don't position to caret yet
+// if ( !isVisible() || isHorizontalSliderPressed() || isVerticalSliderPressed() )
+// {
+// d->ensureCursorVisibleInShowEvent = true;
+// return;
+// }
+
+ KPixelX x = activeColumn().xOfPos( BufferCursor->pos() )+ activeColumn().byteWidth()/2;
+ KPixelY y = LineHeight * BufferCursor->line() + LineHeight/2;
+ int xMargin = activeColumn().byteWidth()/2 + 1;
+ int yMargin = LineHeight/2 + 1;
+ ensureVisible( x, y, xMargin, yMargin );
+}
+
+
+
+void KHexEdit::contentsMousePressEvent( QMouseEvent *e )
+{
+// clearUndoRedo();
+ pauseCursor( true );
+
+ // care about a left button press?
+ if( e->button() == LeftButton )
+ {
+ MousePressed = true;
+
+ // select whole line?
+ if( TrippleClickTimer->isActive()
+ && (e->globalPos()-DoubleClickPoint).manhattanLength() < QApplication::startDragDistance() )
+ {
+ BufferRanges->setSelectionStart( BufferLayout->indexAtLineStart(DoubleClickLine) );
+ BufferCursor->gotoLineEnd();
+ BufferRanges->setSelectionEnd( BufferCursor->realIndex() );
+ repaintChanged();
+
+ unpauseCursor();
+ return;
+ }
+
+ QPoint MousePoint = e->pos();
+ placeCursor( MousePoint );
+ ensureCursorVisible();
+
+ // start of a drag perhaps?
+ if( BufferRanges->selectionIncludes(BufferCursor->index()) )
+ {
+ DragStartPossible = true;
+ DragStartTimer->start( QApplication::startDragTime(), true );
+ DragStartPoint = MousePoint;
+
+ unpauseCursor();
+ return;
+ }
+
+ int RealIndex = BufferCursor->realIndex();
+ if( BufferRanges->selectionStarted() )
+ {
+ if( e->state() & ShiftButton )
+ BufferRanges->setSelectionEnd( RealIndex );
+ else
+ {
+ BufferRanges->removeSelection();
+ BufferRanges->setSelectionStart( RealIndex );
+ }
+ }
+ else // start of a new selection possible
+ {
+ BufferRanges->setSelectionStart( RealIndex );
+
+ if( !isReadOnly() && (e->state()&ShiftButton) ) // TODO: why only for readwrite?
+ BufferRanges->setSelectionEnd( RealIndex );
+ }
+
+ BufferRanges->removeFurtherSelections();
+ }
+ else if( e->button() == MidButton )
+ BufferRanges->removeSelection();
+
+ if( BufferRanges->isModified() )
+ {
+ repaintChanged();
+ viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
+ }
+
+ unpauseCursor();
+}
+
+
+void KHexEdit::contentsMouseMoveEvent( QMouseEvent *e )
+{
+ if( MousePressed )
+ {
+ if( DragStartPossible )
+ {
+ DragStartTimer->stop();
+ // moved enough for a drag?
+ if( (e->pos()-DragStartPoint).manhattanLength() > QApplication::startDragDistance() )
+ startDrag();
+ if( !isReadOnly() )
+ viewport()->setCursor( ibeamCursor );
+ return;
+ }
+ // selecting
+ QPoint MousePoint = e->pos();
+ handleMouseMove( MousePoint );
+ }
+ else if( !isReadOnly() )
+ {
+ // visual feedback for possible dragging
+ bool InSelection = BufferRanges->hasSelection() && BufferRanges->selectionIncludes( indexByPoint(e->pos()) );
+ viewport()->setCursor( InSelection?arrowCursor:ibeamCursor );
+ }
+}
+
+
+void KHexEdit::contentsMouseReleaseEvent( QMouseEvent *e )
+{
+ // this is not the release of a doubleclick so we need to process it?
+ if( !InDoubleClick )
+ {
+ int Line = lineAt( e->pos().y() );
+ int Pos = activeColumn().posOfX( e->pos().x() ); // TODO: can we be sure here about the active column?
+ int Index = BufferLayout->indexAtCCoord( KBufferCoord(Pos,Line) ); // TODO: can this be another index than the one of the cursor???
+ emit clicked( Index );
+ }
+
+ if( MousePressed )
+ {
+ MousePressed = false;
+
+ if( ScrollTimer->isActive() )
+ ScrollTimer->stop();
+
+ // was only click inside selection, nothing dragged?
+ if( DragStartPossible )
+ {
+ selectAll( false );
+ DragStartTimer->stop();
+ DragStartPossible = false;
+
+ unpauseCursor();
+ }
+ // was end of selection operation?
+ else if( BufferRanges->hasSelection() )
+ {
+ if( QApplication::clipboard()->supportsSelection() )
+ {
+ ClipboardMode = QClipboard::Selection;
+ disconnect( QApplication::clipboard(), SIGNAL(selectionChanged()), this, 0);
+
+ copy();
+
+ connect( QApplication::clipboard(), SIGNAL(selectionChanged()), this, SLOT(clipboardChanged()) );
+ ClipboardMode = QClipboard::Clipboard;
+ }
+ }
+ }
+ // middle mouse button paste?
+ else if( e->button() == MidButton && !isReadOnly() )
+ {
+ pauseCursor();
+
+ placeCursor( e->pos() );
+
+ // replace no selection?
+ if( BufferRanges->hasSelection() && !BufferRanges->selectionIncludes(BufferCursor->index()) )
+ BufferRanges->removeSelection();
+
+ ClipboardMode = QClipboard::Selection;
+ paste();
+ ClipboardMode = QClipboard::Clipboard;
+
+ // ensure selection changes to be drawn TODO: create a insert/pasteAtCursor that leaves out drawing
+ repaintChanged();
+
+ ensureCursorVisible();
+ unpauseCursor();
+ }
+
+ InDoubleClick = false;
+
+ if( BufferRanges->selectionJustStarted() )
+ BufferRanges->removeSelection();
+
+ emit cursorPositionChanged( BufferCursor->index() );
+
+ if( !OverWrite ) emit cutAvailable( BufferRanges->hasSelection() );
+ emit copyAvailable( BufferRanges->hasSelection() );
+ KSection Selection = BufferRanges->selection();
+ emit selectionChanged( Selection.start(), Selection.end() );
+}
+
+
+// gets called after press and release instead of a plain press event (?)
+void KHexEdit::contentsMouseDoubleClickEvent( QMouseEvent *e )
+{
+ // we are only interested in LMB doubleclicks
+ if( e->button() != Qt::LeftButton )
+ {
+ e->ignore();
+ return;
+ }
+
+ DoubleClickLine = BufferCursor->line();
+
+ int Index = BufferCursor->validIndex();
+
+ if( ActiveColumn == &charColumn() )
+ {
+ selectWord( Index );
+
+ // as we already have a doubleclick maybe it is a tripple click
+ TrippleClickTimer->start( qApp->doubleClickInterval(), true );
+ DoubleClickPoint = e->globalPos();
+ }
+// else
+// ValueEditor->goInsideByte(); TODO: make this possible again
+
+ InDoubleClick = true; //
+ MousePressed = true;
+
+ emit doubleClicked( Index );
+}
+
+
+void KHexEdit::autoScrollTimerDone()
+{
+ if( MousePressed )
+ handleMouseMove( viewportToContents(viewport()->mapFromGlobal( QCursor::pos() )) );
+}
+
+
+void KHexEdit::handleMouseMove( const QPoint& Point ) // handles the move of the mouse with pressed buttons
+{
+ // no scrolltimer and outside of viewport?
+ if( !ScrollTimer->isActive() && Point.y() < contentsY() || Point.y() > contentsY() + visibleHeight() )
+ ScrollTimer->start( DefaultScrollTimerPeriod, false );
+ // scrolltimer but inside of viewport?
+ else if( ScrollTimer->isActive() && Point.y() >= contentsY() && Point.y() <= contentsY() + visibleHeight() )
+ ScrollTimer->stop();
+
+ pauseCursor();
+
+ placeCursor( Point );
+ ensureCursorVisible();
+
+ // do wordwise selection?
+ if( InDoubleClick && BufferRanges->hasFirstWordSelection() )
+ {
+ int NewIndex = BufferCursor->realIndex();
+ KSection FirstWordSelection = BufferRanges->firstWordSelection();
+ KWordBufferService WBS( DataBuffer, Codec );
+ // are we before the selection?
+ if( NewIndex < FirstWordSelection.start() )
+ {
+ BufferRanges->ensureWordSelectionForward( false );
+ NewIndex = WBS.indexOfLeftWordSelect( NewIndex );
+ }
+ // or behind?
+ else if( NewIndex > FirstWordSelection.end() )
+ {
+ BufferRanges->ensureWordSelectionForward( true );
+ NewIndex = WBS.indexOfRightWordSelect( NewIndex );
+ }
+ // or inside?
+ else
+ {
+ BufferRanges->ensureWordSelectionForward( true );
+ NewIndex = FirstWordSelection.end()+1;
+ }
+
+ BufferCursor->gotoIndex( NewIndex );
+ }
+
+ if( BufferRanges->selectionStarted() )
+ BufferRanges->setSelectionEnd( BufferCursor->realIndex() );
+
+ repaintChanged();
+
+ unpauseCursor();
+}
+
+
+void KHexEdit::startDrag()
+{
+ // reset states
+ MousePressed = false;
+ InDoubleClick = false;
+ DragStartPossible = false;
+
+ // create data
+ QDragObject *Drag = dragObject( viewport() );
+ if( !Drag )
+ return;
+
+ // will we only copy the data?
+ if( isReadOnly() || OverWrite )
+ Drag->dragCopy();
+ // or is this left to the user and he choose to move?
+ else if( Drag->drag() )
+ // Not inside this widget itself?
+ if( QDragObject::target() != this && QDragObject::target() != viewport() )
+ removeSelectedData();
+}
+
+
+void KHexEdit::contentsDragEnterEvent( QDragEnterEvent *e )
+{
+ // interesting for this widget?
+ if( isReadOnly() || !KBufferDrag::canDecode(e) )
+ {
+ e->ignore();
+ return;
+ }
+
+ e->acceptAction();
+ InDnD = true;
+}
+
+
+void KHexEdit::contentsDragMoveEvent( QDragMoveEvent *e )
+{
+ // is this content still interesting for us?
+ if( isReadOnly() || !KBufferDrag::canDecode(e) )
+ {
+ e->ignore();
+ return;
+ }
+
+ // let text cursor follow mouse
+ pauseCursor( true );
+ placeCursor( e->pos() );
+ unpauseCursor();
+
+ e->acceptAction();
+}
+
+
+void KHexEdit::contentsDragLeaveEvent( QDragLeaveEvent * )
+{
+ // bye... and thanks for all the cursor movement...
+ InDnD = false;
+}
+
+
+
+void KHexEdit::contentsDropEvent( QDropEvent *e )
+{
+ // after drag enter and move check one more time
+ if( isReadOnly() )
+ return;
+
+ // leave state
+ InDnD = false;
+ e->acceptAction();
+
+ if( !KBufferDrag::canDecode(e) ) //TODO: why do we acept the action still?
+ return;
+
+ // is this an internal dnd?
+ if( e->source() == this || e->source() == viewport() )
+ handleInternalDrag( e );
+ else
+ {
+ //BufferRanges->removeSelection();
+ pasteFromSource( e );
+ }
+}
+
+
+void KHexEdit::handleInternalDrag( QDropEvent *e )
+{
+ KSection ChangedRange;
+
+ // stop ui
+ pauseCursor();
+
+ // get drag origin
+ KSection Selection = BufferRanges->selection();
+ int InsertIndex = BufferCursor->realIndex();
+
+ // is this a move?
+ if( e->action() == QDropEvent::Move )
+ {
+ // ignore the copy hold in the event but only move
+ int NewIndex = DataBuffer->move( InsertIndex, Selection );
+ if( NewIndex != Selection.start() )
+ {
+ BufferCursor->gotoCIndex( NewIndex+Selection.width() );
+ ChangedRange.set( QMIN(InsertIndex,Selection.start()), QMAX(InsertIndex,Selection.end()) );
+ }
+ }
+ // is a copy
+ else
+ {
+ // get data
+ QByteArray Data;
+ if( KBufferDrag::decode(e,Data) && !Data.isEmpty() )
+ {
+ if( OverWrite )
+ {
+ if( !BufferCursor->isBehind() )
+ {
+ ChangedRange.setByWidth( InsertIndex, Data.size() );
+ ChangedRange.restrictEndTo( BufferLayout->length()-1 );
+ if( ChangedRange.isValid() )
+ {
+ int NoOfReplaced = DataBuffer->replace( ChangedRange, Data.data(), ChangedRange.width() );
+ BufferCursor->gotoNextByte( NoOfReplaced );
+ }
+ }
+ }
+ else
+ {
+ int NoOfInserted = DataBuffer->insert( InsertIndex, Data.data(), Data.size() );
+ updateLength();
+ if( NoOfInserted > 0 )
+ {
+ BufferCursor->gotoCIndex( InsertIndex + NoOfInserted );
+ ChangedRange.set( InsertIndex, DataBuffer->size()-1 );
+ }
+ }
+ }
+ }
+ BufferRanges->addChangedRange( ChangedRange );
+ BufferRanges->removeSelection();
+
+ repaintChanged();
+ ensureCursorVisible();
+
+ // open ui
+ unpauseCursor();
+
+ // emit appropriate signals.
+ emit selectionChanged( -1, -1 );
+ if( ChangedRange.isValid() ) emit bufferChanged( ChangedRange.start(), ChangedRange.end() );
+ emit cursorPositionChanged( BufferCursor->index() );
+}
+
+
+void KHexEdit::contentsWheelEvent( QWheelEvent *e )
+{
+ if( isReadOnly() )
+ {
+ if( e->state() & ControlButton )
+ {
+ if( e->delta() > 0 )
+ zoomOut();
+ else if( e->delta() < 0 )
+ zoomIn();
+ return;
+ }
+ }
+ QScrollView::contentsWheelEvent( e );
+}
+
+
+#if 0
+void KHexEdit::contentsContextMenuEvent( QContextMenuEvent *e )
+{
+// clearUndoRedo();
+ MousePressed = false;
+
+ e->accept();
+
+ QPopupMenu *PopupMenu = createPopupMenu( e->pos() );
+ if( !PopupMenu )
+ PopupMenu = createPopupMenu();
+ if( !PopupMenu )
+ return;
+ int r = PopupMenu->exec( e->globalPos() );
+ delete PopupMenu;
+
+ if ( r == d->id[ IdClear ] )
+ clear();
+ else if ( r == d->id[ IdSelectAll ] )
+ {
+ selectAll();
+ // if the clipboard support selections, put the newly selected text into the clipboard
+ if( QApplication::clipboard()->supportsSelection() )
+ {
+ ClipboardMode = QClipboard::Selection;
+ disconnect( QApplication::clipboard(), SIGNAL(selectionChanged()), this, 0);
+
+ copy();
+
+ connect( QApplication::clipboard(), SIGNAL(selectionChanged()), this, SLOT(clipboardChanged()) );
+ ClipboardMode = QClipboard::Clipboard;
+ }
+ }
+ else if( r == d->id[IdUndo] )
+ undo();
+ else if( r == d->id[IdRedo] )
+ redo();
+ else if( r == d->id[IdCut] )
+ cut();
+ else if( r == d->id[IdCopy] )
+ copy();
+ else if( r == d->id[IdPaste] )
+ paste();
+}
+#endif
+
+#include "khexedit.moc"
diff --git a/khexedit/lib/khexedit.h b/khexedit/lib/khexedit.h
new file mode 100644
index 0000000..66059c8
--- /dev/null
+++ b/khexedit/lib/khexedit.h
@@ -0,0 +1,562 @@
+/***************************************************************************
+ khexedit.h - description
+ -------------------
+ begin : Die Mai 13 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KHEXEDIT_H
+#define KHE_KHEXEDIT_H
+
+// qt specific
+#include <qclipboard.h>
+// lib specific
+// #include "khe.h"
+#include "khexedit_export.h"
+#include "kcolumnsview.h"
+
+class QTimer;
+
+namespace KHE
+{
+
+class KCoordRange;
+
+class KDataBuffer;
+
+class KCharColumn;
+class KValueColumn;
+class KBufferColumn;
+class KOffsetColumn;
+class KBorderColumn;
+
+class KBufferCursor;
+class KBufferLayout;
+class KBufferRanges;
+
+class KController;
+class KTabController;
+class KNavigator;
+class KValueEditor;
+class KCharEditor;
+
+class KBufferDrag;
+
+class KCursor;
+class KCharCodec;
+
+class KHexEditPrivate;
+
+
+/** the main widget
+ *
+ * The functions split up in helper functions and those that are complete.
+ *
+ * Complete functions can be called from the outside and leave the widget in
+ * a consistent state. They care for exceptions so one can safely call them in all
+ * situations (like empty buffer, cursor behind end etc.)
+ *
+ * Helper functions do only partial tasks and need to be completed. They often do not
+ * check for exceptions so one has to care for this.
+ *
+ *@author Friedrich W. H. Kossebau
+ */
+
+class KHEXEDIT_EXPORT KHexEdit : public KColumnsView
+{
+ friend class KTabController;
+ friend class KNavigator;
+ friend class KEditor;
+ friend class KValueEditor;
+ friend class KCharEditor;
+
+ Q_OBJECT
+ Q_ENUMS( KResizeStyle KCoding )
+ Q_PROPERTY( bool OverwriteMode READ isOverwriteMode WRITE setOverwriteMode )
+ Q_PROPERTY( bool OverwriteOnly READ isOverwriteOnly WRITE setOverwriteOnly )
+ Q_PROPERTY( bool Modified READ isModified WRITE setModified DESIGNABLE false )
+ Q_PROPERTY( bool ReadOnly READ isReadOnly WRITE setReadOnly )
+
+ Q_PROPERTY( int NoOfBytesPerLine READ noOfBytesPerLine WRITE setNoOfBytesPerLine )
+ Q_PROPERTY( bool TabChangesFocus READ tabChangesFocus WRITE setTabChangesFocus )
+
+ //Q_PROPERTY( bool hasSelectedData READ hasSelectedData )
+ //Q_PROPERTY( QByteArray SelectedData READ selectedData )
+ Q_PROPERTY( KResizeStyle ResizeStyle READ resizeStyle WRITE setResizeStyle )
+ Q_PROPERTY( int StartOffset READ startOffset WRITE setStartOffset )
+ Q_PROPERTY( int FirstLineOffset READ firstLineOffset WRITE setFirstLineOffset )
+ //_PROPERTY( int undoDepth READ undoDepth WRITE setUndoDepth )
+ //_PROPERTY( bool undoRedoEnabled READ isUndoRedoEnabled WRITE setUndoRedoEnabled )
+ // value column
+ Q_PROPERTY( KCoding Coding READ coding WRITE setCoding )
+ Q_PROPERTY( int ByteSpacingWidth READ byteSpacingWidth WRITE setByteSpacingWidth )
+ Q_PROPERTY( int NoOfGroupedBytes READ noOfGroupedBytes WRITE setNoOfGroupedBytes )
+ Q_PROPERTY( int GroupSpacingWidth READ groupSpacingWidth WRITE setGroupSpacingWidth )
+ Q_PROPERTY( int BinaryGapWidth READ binaryGapWidth WRITE setBinaryGapWidth )
+ // char column
+ Q_PROPERTY( bool ShowUnprintable READ showUnprintable WRITE setShowUnprintable )
+ Q_PROPERTY( QChar SubstituteChar READ substituteChar WRITE setSubstituteChar )
+
+ public:
+ enum KResizeStyle { NoResize=0, LockGrouping=1, FullSizeUsage=2, MaxResizeStyleId=0xFF };
+ enum KCoding { HexadecimalCoding=0, DecimalCoding=1, OctalCoding=2, BinaryCoding=3, MaxCodingId=0xFFFF };
+ enum KEncoding { LocalEncoding=0, ISO8859_1Encoding=1, EBCDIC1047Encoding=2,
+ StartOfOwnEncoding=0x8000, MaxEncodingId=0xFFFF };
+
+ enum KBufferColumnId { ValueColumnId=1, CharColumnId=2 };
+
+
+ public:
+ KHexEdit( KDataBuffer *Buffer = 0, QWidget *Parent = 0, const char *Name = 0, WFlags F = 0 );
+ virtual ~KHexEdit();
+
+
+ public: // KColumnsView API
+ virtual void drawContents( QPainter *p, int cx, int cy, int cw, int ch );
+
+ public: // QWidget API
+// void focusInEvent( QFocusEvent *FocusEvent ); // TODO: why don't these work?
+// void focusOutEvent( QFocusEvent *FocusEvent );
+ virtual bool eventFilter( QObject *O, QEvent *E );
+
+ virtual QSize sizeHint() const;
+ virtual QSize minimumSizeHint() const;
+
+
+ public: // value access
+ /** returns the index of the cursor position */
+ int cursorPosition() const;
+ /***/
+ bool isCursorBehind() const;
+ KBufferColumnId cursorColumn() const;
+
+ bool isOverwriteMode() const;
+ bool isOverwriteOnly() const;
+ bool isReadOnly() const;
+ bool isModified() const;
+
+ bool tabChangesFocus() const;
+
+ KResizeStyle resizeStyle() const;
+ int noOfBytesPerLine() const;
+ int startOffset() const;
+ int firstLineOffset() const;
+
+ bool offsetColumnVisible() const;
+ int visibleBufferColumns() const;
+
+ // value column
+ KCoding coding() const;
+ int/*KPixelX*/ byteSpacingWidth() const;
+ int noOfGroupedBytes() const;
+ int/*KPixelX*/ groupSpacingWidth() const;
+ int/*KPixelX*/ binaryGapWidth() const;
+
+ // char column
+ /** reports if "unprintable" chars (value<32) are displayed in the char column
+ * with their original character. Default is false
+ * @return @c true if original chars are displayed, otherwise @c false
+ */
+ bool showUnprintable() const;
+ /** gives the used substitute character for "unprintable" chars, default is '.'
+ * @return substitute character
+ */
+ QChar substituteChar() const;
+ /** returns the actually used undefined character for "undefined" chars, default is '?' */
+ QChar undefinedChar() const;
+ /**
+ * @return encoding used in the char column
+ */
+ KEncoding encoding() const;
+ /**
+ * @return name of the encoding used in the char column
+ */
+ const QString &encodingName() const;
+
+ public: // logic value service
+ /** calculates the number of bytes per line that fit into a widget with the given size
+ * tests whether a vertical scroll bar is needed at all or not due to the given width
+ * takes the frame width into account
+ * @param TestSize Size the widget might have
+ * @return number of bytes per line that fit into a widget with the given size
+ */
+ int fittingBytesPerLine( const QSize &TestSize ) const;
+ /** detects the index of the byte at the given point
+ * @param Point in viewport coordinate system
+ * @return index of the byte that covers the point
+ */
+ int indexByPoint(const QPoint &Point ) const;
+
+ public:
+ /** returns true if there is a selected range in the array */
+ bool hasSelectedData() const;
+ /**
+ * @return deep copy of the selected data
+ */
+ QByteArray selectedData() const;
+ KSection selection() const;
+
+ public: // modification access
+ /** puts the cursor to the position of index, handles all drawing
+ * @param Index
+ */
+ void setCursorPosition( int Index, bool Behind=false );
+ /** puts the cursor in the column at the pos of Point (in absolute coord), does not handle the drawing */
+ void placeCursor( const QPoint &Point );
+ /***/
+ void setCursorColumn( KBufferColumnId );
+// void repaintByte( int row, int column, bool Erase = true );
+// void updateByte( int row, int column );
+// void ensureByteVisible( int row, int column );
+
+ public slots:
+ /** */
+ void setDataBuffer( KDataBuffer *B );
+
+ /** switches the Offset column on/off */
+ void toggleOffsetColumn( bool Visible );
+ /** */
+ void showBufferColumns( int Columns );
+ /** scrolls the view as much as needed to have the cursor fully visible */
+ void ensureCursorVisible();
+
+ // setting parameters
+ /** sets the resizestyle for the value column. Default is KHE::FullSizeUsage */
+ void setResizeStyle( KResizeStyle Style );
+ /** sets whether the widget is readonly or not, Default is true.
+ * If the databuffer which is worked on can't be written the widget stays readonly
+ */
+ virtual void setReadOnly( bool b );
+ /** sets whether the widget is overwriteonly or not. Default is false. */
+ virtual void setOverwriteOnly( bool b );
+ /** sets whether the widget is in overwrite mode or not. Default is true. */
+ virtual void setOverwriteMode( bool b );
+ /** sets whether the data should be treated modified or not */
+ virtual void setModified( bool b );
+ /** sets whether on a tab key there should be switched from the char column back to the value column
+ * or be switched to the next focusable widget. Default is false
+ */
+ virtual void setTabChangesFocus( bool b = true );
+ //
+ /** sets the number of bytes per line, switching the resize style to KHE::NoResize */
+ virtual void setNoOfBytesPerLine( int NoCpL );
+ /** sets absolut offset of the data */
+ void setStartOffset( int SO );
+ /** sets offset of the char in the upper left corner */
+ void setFirstLineOffset( int FLO );
+ // value column parameters
+ /** sets the spacing between the bytes in the value column
+ * @param BSW spacing between the bytes in pixels
+ * default is 3
+ */
+ void setByteSpacingWidth( int/*KPixelX*/ BSW ) ;
+ /** sets the number of grouped bytes in the value column
+ * @param NoGB numbers of grouped bytes, 0 means no grouping
+ * default is 4
+ */
+ void setNoOfGroupedBytes( int NoGB );
+ /** sets the spacing between the groups of bytes in the value column
+ * @param GSW spacing between the groups in pixels
+ * default is 9
+ */
+ void setGroupSpacingWidth( int/*KPixelX*/ GSW );
+ /** sets the spacing in the middle of a binary byte in the value column
+ * @param BinaryGapW spacing in the middle of a binary in pixels
+ * returns true if there was a change
+ */
+ void setBinaryGapWidth( int BGW );
+ /** sets the spacing in the value column
+ * @param ByteSpacingWidth spacing between the bytes in pixels
+ * @param NoOfGroupedBytes numbers of grouped bytes, 0 means no grouping
+ * @param GroupSpacingWidth spacing between the groups in pixels
+ * Default is 4 for NoOfGroupedBytes
+ */
+ void setBufferSpacing( KPixelX ByteSpacingWidth, int NoOfGroupedBytes = 0, KPixelX GroupSpacingWidth = 0 );
+ /** sets the format of the value column. Default is KHE::HexadecimalCoding */
+ void setCoding( KCoding C );
+ // char column parameters
+ /** sets whether "unprintable" chars (>32) should be displayed in the char column
+ * with their corresponding character.
+ * @param SU
+ * returns true if there was a change
+ */
+ void setShowUnprintable( bool SU = true );
+ /** sets the substitute character for "unprintable" chars
+ * returns true if there was a change
+ */
+ void setSubstituteChar( QChar SC );
+ /** sets the undefined character for "undefined" chars
+ * returns true if there was a change
+ */
+ void setUndefinedChar( QChar UC );
+ /** sets the encoding of the char column. Default is KHE::LocalEncoding.
+ * If the encoding is not available the format will not be changed. */
+ void setEncoding( KEncoding C );
+ /** sets the encoding of the char column. Default is KHE::LocalEncoding.
+ * If the encoding is not available the format will not be changed.
+ * @param Encoding name of the encoding
+ */
+ void setEncoding( const QString& Encoding );
+
+ // interaction
+ /** de-/selects all data */
+ void selectAll( bool select );
+ /** de-/selects all data */
+ void select( KSection S );
+ /** selects word at index, returns true if there is one */
+ bool selectWord( /*unsigned*/ int Index /*, Chartype*/ );
+ /** removes the selected data, takes care of the cursor */
+ virtual void removeSelectedData();
+ /** inserts */
+ virtual void insert( const QByteArray &D );
+
+ // clipboard interaction
+ virtual void copy();
+ virtual void cut();
+ virtual void paste();
+
+ // zooming
+ virtual void zoomIn( int PointInc );
+ virtual void zoomIn();
+ virtual void zoomOut( int PointInc );
+ virtual void zoomOut();
+ virtual void zoomTo( int PointSize );
+ virtual void unZoom();
+
+ // cursor control
+ /** we have focus again, start the timer */
+ virtual void startCursor();
+ /** we lost focus, stop the timer */
+ virtual void stopCursor();
+ /** simply pauses any blinking, i.e. ignores any calls to blinkCursor */
+ virtual void pauseCursor( bool LeaveEdit = false );
+ /** undoes pauseCursor */
+ virtual void unpauseCursor();
+
+
+ signals:
+ /** Index of the byte that was clicked */
+ void clicked( int Index );
+ /** Index of the byte that was double clicked */
+ void doubleClicked( int Index );
+
+ void cursorPositionChanged( int Index );
+ /** selection has changed */
+ void selectionChanged( int StartIndex, int EndIndex );
+ /** there is a cut available or not */
+ void cutAvailable( bool Really );
+ /** there is a copy available or not */
+ void copyAvailable( bool Really );
+ /** there has been a change to the buffer */
+ void bufferChanged( int StartIndex, int EndIndex );
+
+
+ protected: // QWidget API
+ virtual void keyPressEvent( QKeyEvent *KeyEvent );
+ virtual void resizeEvent( QResizeEvent *ResizeEvent );
+ virtual void showEvent( QShowEvent *e );
+
+ protected: // QScrollView API
+ virtual void contentsMousePressEvent( QMouseEvent *e );
+ virtual void contentsMouseReleaseEvent( QMouseEvent * e );
+ virtual void contentsMouseMoveEvent( QMouseEvent *e );
+ virtual void contentsMouseDoubleClickEvent( QMouseEvent * e );
+ virtual void contentsDragEnterEvent( QDragEnterEvent *e );
+ virtual void contentsDragMoveEvent( QDragMoveEvent *e );
+ virtual void contentsDragLeaveEvent( QDragLeaveEvent * );
+ virtual void contentsDropEvent( QDropEvent *e );
+ virtual void contentsWheelEvent( QWheelEvent *e );
+// virtual void contentsContextMenuEvent( QContextMenuEvent *e );
+
+ protected: // KColumnsView API
+ virtual void setNoOfLines( int NewNoOfLines );
+
+
+ protected: // element accessor functions
+ KValueColumn& valueColumn();
+ KCharColumn& charColumn();
+ KBufferColumn& activeColumn();
+ KBufferColumn& inactiveColumn();
+ const KValueColumn& valueColumn() const;
+ const KCharColumn& charColumn() const;
+ const KBufferColumn& activeColumn() const;
+ const KBufferColumn& inactiveColumn() const;
+
+ protected: // atomic ui operations
+ /** handles screen update in case of a change to any of the width sizes
+ */
+ void updateViewByWidth();
+ /** repaints all the parts that are signed as changed */
+ void repaintChanged();
+
+ protected: // drawing related operations
+ /** recreates the cursor pixmaps and paints active and inactive cursors if doable */
+ void updateCursor();
+ void createCursorPixmaps();
+ void pointPainterToCursor( QPainter &Painter, const KBufferColumn &Column ) const;
+ /** draws the blinking cursor or removes it */
+ void paintActiveCursor( bool CursorOn );
+ void paintInactiveCursor( bool CursorOn );
+ void paintLine( KBufferColumn *C, int Line, KSection Positions );
+
+ protected: // partial operations
+ void handleMouseMove( const QPoint& Point );
+ KBufferDrag *dragObject( QWidget *Parent = 0 ) const;
+ void pasteFromSource( QMimeSource *Source );
+ /** removes the section from the databuffer and updates all affected values */
+ KSection removeData( KSection Indizes );
+ /** sets ChangedRange to the range of VisibleRange that is actually changed
+ * @return true if there was a change within the visible range
+ */
+ bool hasChanged( const KCoordRange &VisibleRange, KCoordRange *ChangedRange ) const;
+ void handleInternalDrag( QDropEvent *e );
+
+ protected:
+ /** recalcs all dependant values with the actual NoOfBytesPerLine */
+ void adjustToLayoutNoOfBytesPerLine();
+ /** recalcs a layout due to the resize style that fits into the view size
+ * and updates the dependant values
+ */
+ void adjustLayoutToSize();
+ /** */
+ void updateLength();
+ /** calls updateContent for the Column */
+ void updateColumn( KColumn &Column );
+
+ protected slots:
+ /** gets called by the cursor blink timer */
+ void blinkCursor();
+ /** gets called by the scroll timer (for mouse selection) */
+ void autoScrollTimerDone();
+ /** */
+ void clipboardChanged();
+ /** */
+ void startDrag();
+
+ protected slots: // QWidget API
+ virtual void fontChange( const QFont &OldFont );
+
+
+ protected:
+ /** Buffer with the data */
+ KDataBuffer *DataBuffer;
+
+ /** holds the logical layout */
+ KBufferLayout *BufferLayout;
+ /** */
+ KBufferCursor *BufferCursor;
+ /** */
+ KBufferRanges *BufferRanges;
+
+
+ protected:
+ KOffsetColumn *OffsetColumn;
+ KBorderColumn *FirstBorderColumn;
+ KValueColumn *ValueColumn;
+ KBorderColumn *SecondBorderColumn;
+ KCharColumn *CharColumn;
+
+ /** points to the column with keyboard focus */
+ KBufferColumn *ActiveColumn;
+ /** points to the column without keyboard focus (if there is) */
+ KBufferColumn *InactiveColumn;
+
+ /** the actual input controller */
+ KController *Controller;
+ /** */
+ KTabController *TabController;
+ /** */
+ KNavigator *Navigator;
+ /** */
+ KValueEditor *ValueEditor;
+ /** */
+ KCharEditor *CharEditor;
+
+ protected:
+ /** Timer that controls the blinking of the cursor */
+ QTimer *CursorBlinkTimer;
+ /** Timer that triggers ensureCursorVisible function calls */
+ QTimer *ScrollTimer;
+/* QTimer *ChangeIntervalTimer, */
+ /** Timer to start a drag */
+ QTimer *DragStartTimer;
+ /** timer to measure whether the time between a double click and the following counts for a tripleclick */
+ QTimer *TrippleClickTimer;
+
+ /** object to store the blinking cursor pixmaps */
+ KCursor *CursorPixmaps;
+ /** */
+ KCharCodec *Codec;
+
+ protected:
+ /** point at which the current double click happended (used by TrippleClick) */
+ QPoint DoubleClickPoint;
+ /** line in which the current double click happended (used by TrippleClick) */
+ int DoubleClickLine;
+ /** point at which the current dragging started */
+ QPoint DragStartPoint;
+ /** */
+ QClipboard::Mode ClipboardMode;
+ /** font size as set by user (used for zooming) */
+ int DefaultFontSize;
+
+ protected: // parameters
+ /** style of resizing */
+ KResizeStyle ResizeStyle;
+ /** */
+ KEncoding Encoding;
+
+ /** flag whether the widget is set to readonly. Cannot override the databuffer's setting, of course. */
+ bool ReadOnly:1;
+ /** flag if only overwrite is allowed */
+ bool OverWriteOnly:1;
+ /** flag if overwrite mode is active */
+ bool OverWrite:1;
+ /** flag if a mouse button is pressed */
+ bool MousePressed:1;
+ /** flag if a double click is happening */
+ bool InDoubleClick:1;
+ /** flag if a Drag'n'Drop is happening */
+ bool InDnD:1;
+ /** flag if a drag might have started */
+ bool DragStartPossible:1;
+ /** flag if the cursor should be invisible */
+ bool CursorPaused:1;
+ /** flag if the cursor is visible */
+ bool BlinkCursorVisible:1;
+ /** flag whether the font is changed due to a zooming */
+ bool InZooming:1;
+
+ private:
+ /** the binary compatibility saving helper */
+ KHexEditPrivate* d;
+
+ private: // Disabling copy constructor and operator= - not useful
+ KHexEdit( const KHexEdit & );
+ KHexEdit &operator=( const KHexEdit & );
+};
+
+
+inline const KValueColumn& KHexEdit::valueColumn() const { return *ValueColumn; }
+inline const KCharColumn& KHexEdit::charColumn() const { return *CharColumn; }
+inline const KBufferColumn& KHexEdit::activeColumn() const { return *ActiveColumn; }
+inline const KBufferColumn& KHexEdit::inactiveColumn() const { return *InactiveColumn; }
+
+inline KValueColumn& KHexEdit::valueColumn() { return *ValueColumn; }
+inline KCharColumn& KHexEdit::charColumn() { return *CharColumn; }
+inline KBufferColumn& KHexEdit::activeColumn() { return *ActiveColumn; }
+inline KBufferColumn& KHexEdit::inactiveColumn() { return *InactiveColumn; }
+
+}
+
+#endif
diff --git a/khexedit/lib/khexedit_export.h b/khexedit/lib/khexedit_export.h
new file mode 100644
index 0000000..f922516
--- /dev/null
+++ b/khexedit/lib/khexedit_export.h
@@ -0,0 +1,25 @@
+/***************************************************************************
+ khexedit_export.h - description
+ -------------------
+ begin : 22 Nov 2004
+ copyright : (C) 2004 Dirk Mueller
+ email : mueller@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHEXEDIT_EXPORT_H
+#define KHEXEDIT_EXPORT_H
+
+#include <kdemacros.h>
+
+#define KHEXEDIT_EXPORT KDE_EXPORT
+
+#endif
diff --git a/khexedit/lib/koffsetcoltextexport.cpp b/khexedit/lib/koffsetcoltextexport.cpp
new file mode 100644
index 0000000..c5644df
--- /dev/null
+++ b/khexedit/lib/koffsetcoltextexport.cpp
@@ -0,0 +1,61 @@
+/***************************************************************************
+ koffsetcoltextexport.cpp - description
+ -------------------
+ begin : Sam Aug 30 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// qt specific
+#include <qstring.h>
+// lib specific
+#include "koffsetcolumn.h"
+#include "koffsetcoltextexport.h"
+
+using namespace KHE;
+
+
+KOffsetColTextExport::KOffsetColTextExport( const KOffsetColumn *OffsetColumn )
+ : CodingWidth( OffsetColumn->codingWidth() ),
+ FirstLineOffset( OffsetColumn->firstLineOffset() ),
+ Delta( OffsetColumn->delta() ),
+ printFunction( OffsetColumn->printFunction() )
+{
+}
+
+int KOffsetColTextExport::charsPerLine() const
+{
+ return CodingWidth;
+}
+
+
+void KOffsetColTextExport::printFirstLine( QString &T, int Line ) const
+{
+ PrintLine = Line;
+ print( T );
+}
+
+void KOffsetColTextExport::printNextLine( QString &T ) const
+{
+ print( T );
+}
+
+void KOffsetColTextExport::print( QString &T ) const
+{
+ // TODO: fix me (no more printFunction)
+ char *B = new char[CodingWidth+1];
+ printFunction( B, FirstLineOffset + Delta*PrintLine );
+ T.append( B );
+ delete [] B;
+
+ ++PrintLine;
+}
diff --git a/khexedit/lib/koffsetcoltextexport.h b/khexedit/lib/koffsetcoltextexport.h
new file mode 100644
index 0000000..e07e659
--- /dev/null
+++ b/khexedit/lib/koffsetcoltextexport.h
@@ -0,0 +1,57 @@
+/***************************************************************************
+ koffsetcoltextexport.h - description
+ -------------------
+ begin : Sam Aug 30 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KOFFSETCOLTEXTEXPORT_H
+#define KHE_KOFFSETCOLTEXTEXPORT_H
+
+// lib specific
+#include "kcoltextexport.h"
+#include "koffsetformat.h"
+
+
+namespace KHE
+{
+
+class KOffsetColumn;
+
+class KOffsetColTextExport : public KColTextExport
+{
+ public:
+ KOffsetColTextExport( const KOffsetColumn *OC );
+
+ public: // KColTextExport API
+ void printFirstLine( QString &T, int Line ) const;
+ void printNextLine( QString &T ) const;
+ /** tells how much chars per line are needed */
+ int charsPerLine() const;
+
+ protected:
+ void print( QString &T ) const;
+
+ protected:
+ const int CodingWidth;
+ const int FirstLineOffset;
+ const int Delta;
+ const KOffsetFormat::print printFunction;
+
+ /** the line we are in */
+ mutable int PrintLine;
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/koffsetcolumn.cpp b/khexedit/lib/koffsetcolumn.cpp
new file mode 100644
index 0000000..6bd6d09
--- /dev/null
+++ b/khexedit/lib/koffsetcolumn.cpp
@@ -0,0 +1,110 @@
+/***************************************************************************
+ koffsetcolumn.cpp - description
+ -------------------
+ begin : Mit Mai 14 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+// qt specific
+#include "qpainter.h"
+// lib specific
+#include "kcolumnsview.h"
+#include "koffsetcolumn.h"
+
+using namespace KHE;
+
+KOffsetColumn::KOffsetColumn( KColumnsView *V, int FLO, int D, KOffsetFormat::KFormat F )
+ : KColumn( V ),
+ FirstLineOffset( FLO ),
+ Delta( D ),
+ Margin( 0 ),
+ DigitWidth( 0 ),
+ DigitBaseLine( 0 ),
+ Format( KOffsetFormat::None )
+{
+ setFormat( F );
+}
+
+
+KOffsetColumn::~KOffsetColumn()
+{
+}
+
+
+void KOffsetColumn::paintLine( QPainter *P, int Line )
+{
+ const QColor &ButtonColor = View->colorGroup().button();
+ P->fillRect( 0,0,width(),LineHeight, QBrush(ButtonColor,Qt::SolidPattern) );
+
+ printFunction()( CodedOffset,FirstLineOffset+Delta*Line );
+ P->drawText( 0, DigitBaseLine, QString().append(CodedOffset) );
+}
+
+
+void KOffsetColumn::paintFirstLine( QPainter *P, KPixelXs, int FirstLine )
+{
+ PaintLine = FirstLine;
+ paintLine( P, PaintLine++ );
+}
+
+
+void KOffsetColumn::paintNextLine( QPainter *P )
+{
+ paintLine( P, PaintLine++ );
+}
+
+
+
+void KOffsetColumn::paintEmptyColumn( QPainter *P, KPixelXs Xs, KPixelYs Ys )
+{
+ Xs.restrictTo( XSpan );
+
+ const QColor &ButtonColor = View->colorGroup().button();
+ P->fillRect( Xs.start(), Ys.start(), Xs.width(), Ys.width(), QBrush(ButtonColor,Qt::SolidPattern) );
+}
+
+void KOffsetColumn::setFormat( KOffsetFormat::KFormat F )
+{
+ // no changes?
+ if( Format == F )
+ return;
+
+ Format = F;
+
+ CodingWidth = KOffsetFormat::codingWidth( Format );
+ PrintFunction = KOffsetFormat::printFunction( Format );
+
+ recalcX();
+}
+
+void KOffsetColumn::setMetrics( KPixelX DW, KPixelY DBL )
+{
+ DigitBaseLine = DBL;
+ setDigitWidth( DW );
+}
+
+void KOffsetColumn::setDigitWidth( KPixelX DW )
+{
+ // no changes?
+ if( DigitWidth == DW )
+ return;
+
+ DigitWidth = DW;
+
+ recalcX();
+}
+
+void KOffsetColumn::recalcX()
+{
+ // recalculate depend sizes
+ setWidth( CodingWidth * DigitWidth );
+}
diff --git a/khexedit/lib/koffsetcolumn.h b/khexedit/lib/koffsetcolumn.h
new file mode 100644
index 0000000..ae182f9
--- /dev/null
+++ b/khexedit/lib/koffsetcolumn.h
@@ -0,0 +1,109 @@
+/***************************************************************************
+ koffsetcolumn.h - description
+ -------------------
+ begin : Mit Mai 14 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KOFFSETCOLUMN_H
+#define KHE_KOFFSETCOLUMN_H
+
+// lib specific
+#include "koffsetformat.h"
+#include "kcolumn.h"
+
+namespace KHE
+{
+
+/**
+ *@author Friedrich W. H. Kossebau
+ */
+
+class KOffsetColumn : public KColumn
+{
+ public:
+ KOffsetColumn( KColumnsView *V, int FLO, int D, KOffsetFormat::KFormat F );
+ virtual ~KOffsetColumn();
+
+ public: // KColumn API
+ virtual void paintFirstLine( QPainter *P, KPixelXs Xs, int FirstLine );
+ virtual void paintNextLine( QPainter *P );
+ virtual void paintEmptyColumn( QPainter *P, KPixelXs Xs, KPixelYs Ys );
+
+
+ public:
+ void setFirstLineOffset( int FLO );
+ void setDelta( int D );
+
+ void setFormat( KOffsetFormat::KFormat F );
+ /** sets width of digits and recalculates depend sizes */
+ void setDigitWidth( KPixelX DW );
+ /** */
+ void setMetrics( KPixelX DW, KPixelY DBL );
+
+ public: // read access
+ int delta() const;
+ int firstLineOffset() const;
+ int codingWidth() const;
+ KOffsetFormat::print printFunction() const;
+
+
+ protected:
+ /** recalculates all x values */
+ void recalcX();
+ /** paints full line */
+ void paintLine( QPainter *P, int Line );
+
+
+ protected: // user settings
+ /** starting offset of the first line
+ * if different from StartOffset results in leading space
+ */
+ int FirstLineOffset;
+ /** offset delta per line */
+ int Delta;
+
+ protected: // pixel related
+ /** size of the line margin */
+ int Margin;
+ /** */
+ KPixelX DigitWidth;
+ /** */
+ KPixelY DigitBaseLine;
+
+ protected: // general layout
+ KOffsetFormat::KFormat Format;
+
+ int CodingWidth;
+ KOffsetFormat::print PrintFunction;
+
+ /** buffer to hold the formatted coding */
+ mutable char CodedOffset[KOffsetFormat::MaxFormatWidth+1];
+
+ protected: // firstnext trips related
+ /** */
+ int PaintLine;
+};
+
+
+inline int KOffsetColumn::firstLineOffset() const { return FirstLineOffset; }
+inline void KOffsetColumn::setFirstLineOffset( int FLO ) { FirstLineOffset = FLO; }
+inline int KOffsetColumn::delta() const { return Delta; }
+inline void KOffsetColumn::setDelta( int D ) { Delta = D; }
+
+inline int KOffsetColumn::codingWidth() const { return CodingWidth; }
+inline KOffsetFormat::print KOffsetColumn::printFunction() const { return PrintFunction; }
+
+}
+
+#endif
diff --git a/khexedit/lib/koffsetformat.cpp b/khexedit/lib/koffsetformat.cpp
new file mode 100644
index 0000000..e82fa9d
--- /dev/null
+++ b/khexedit/lib/koffsetformat.cpp
@@ -0,0 +1,48 @@
+/***************************************************************************
+ koffsetformat.cpp - description
+ -------------------
+ begin : Mit Mai 21 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// c specific
+#include <stdio.h>
+// lib specific
+#include "koffsetformat.h"
+
+using namespace KHE;
+
+
+const unsigned int KOffsetFormat::CodingWidth[2] = { 9, 10 };
+
+const KOffsetFormat::print KOffsetFormat::PrintFunction[2] =
+{ KOffsetFormat::printHexadecimalOffset, KOffsetFormat::printDecimalOffset };
+
+
+
+void KOffsetFormat::printHexadecimalOffset( char *Buffer, unsigned int Offset )
+{
+ sprintf( Buffer, "%04X:%04X", Offset>>16, Offset&0x0000FFFF );
+}
+
+
+void KOffsetFormat::printHexadecimalSmallOffset( char *Buffer, unsigned int Offset )
+{
+ sprintf( Buffer, "%04x:%04x", Offset>>16, Offset&0x0000FFFF );
+}
+
+
+void KOffsetFormat::printDecimalOffset( char *Buffer, unsigned int Offset )
+{
+ sprintf( Buffer, "%010u", Offset );
+}
diff --git a/khexedit/lib/koffsetformat.h b/khexedit/lib/koffsetformat.h
new file mode 100644
index 0000000..8bd90e2
--- /dev/null
+++ b/khexedit/lib/koffsetformat.h
@@ -0,0 +1,70 @@
+/***************************************************************************
+ koffsetformat.h - description
+ -------------------
+ begin : Mit Mai 21 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KOFFSETFORMAT_H
+#define KHE_KOFFSETFORMAT_H
+
+namespace KHE
+{
+
+/**
+ *@author Friedrich W. H. Kossebau
+ */
+
+class KOffsetFormat
+{
+ public:
+ /** */
+ typedef void (*print)( char *Buffer, unsigned int Offset );
+ /** */
+ enum KFormat { Hexadecimal=0, Decimal, None };
+ /** */
+ static const int MaxFormatWidth = 9;
+
+ private:
+ KOffsetFormat();
+ ~KOffsetFormat();
+
+ public:
+ /** */
+ static unsigned int codingWidth( int i );
+ /** */
+ static print printFunction( int i );
+
+ public:
+ static void printHexadecimalOffset( char *Buffer, unsigned int Offset );
+ static void printHexadecimalSmallOffset( char *Buffer, unsigned int Offset );
+ static void printDecimalOffset( char *Buffer, unsigned int Offset );
+
+ protected:
+ /** */
+ static const unsigned int CodingWidth[2]; //TODO: would sizeof(Coding} work?
+ /** */
+ static const print PrintFunction[2];
+};
+
+
+inline unsigned int KOffsetFormat::codingWidth( int i )
+{ return CodingWidth[i]; }
+
+inline KOffsetFormat::print KOffsetFormat::printFunction( int i )
+{ return PrintFunction[i]; }
+
+
+}
+
+#endif
diff --git a/khexedit/lib/kplainbuffer.cpp b/khexedit/lib/kplainbuffer.cpp
new file mode 100644
index 0000000..63c1db7
--- /dev/null
+++ b/khexedit/lib/kplainbuffer.cpp
@@ -0,0 +1,344 @@
+/***************************************************************************
+ kplainbuffer.cpp - description
+ -------------------
+ begin : Mit Jun 03 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+//#include <kdebug.h>
+// c specific
+#include <string.h>
+#include <stdlib.h>
+// lib specific
+#include "kplainbuffer.h"
+
+
+static const unsigned int MinChunkSize = 512;
+static const unsigned int MaxChunkSize = 1024*10; // TODO: get max. memory page size
+
+// TODO: think about realloc & Co.
+using namespace KHE;
+
+KPlainBuffer::KPlainBuffer( char *D, unsigned int S, int RS, bool KM )
+ : Data( D ),
+ Size( S ),
+ RawSize( RS<(int)S?S:RS ),
+ MaxSize( -1 ),
+ KeepsMemory( KM ),
+ ReadOnly( true ),
+ Modified( false )
+{
+}
+
+KPlainBuffer::KPlainBuffer( const char *D, unsigned int S )
+ : Data( (char *)D ),
+ Size( S ),
+ RawSize( S ),
+ MaxSize( -1 ),
+ KeepsMemory( true ),
+ ReadOnly( true ),
+ Modified( false )
+{
+}
+
+KPlainBuffer::KPlainBuffer( int S, int MS )
+ : Data( S?new char[S]:0 ),
+ Size( S ),
+ RawSize( S ),
+ MaxSize( MS ),
+ KeepsMemory( false ),
+ ReadOnly( true ),
+ Modified( false )
+{
+}
+
+KPlainBuffer::~KPlainBuffer()
+{
+}
+
+
+
+int KPlainBuffer::insert( int Pos, const char* D, int Length )
+{
+ // check all parameters
+ if( Length == 0 )
+ return 0;
+ //kdDebug() << QString("before: Size: %1, RawSize: %2").arg(Size).arg(RawSize) << endl;
+ // correct for appending
+ if( Pos > (int)Size )
+ Pos = Size;
+
+ Length = addSize( Length, Pos, true );
+
+ // copy new data to its place
+ memcpy( &Data[Pos], D, Length );
+
+ //kdDebug() << QString("after: Size: %1, RawSize: %2").arg(Size).arg(RawSize) << endl;
+
+ Modified = true;
+ return Length;
+}
+
+
+int KPlainBuffer::remove( KSection Remove )
+{
+ if( Remove.startsBehind(Size-1) || Remove.width() == 0 )
+ return 0;
+
+ Remove.restrictEndTo( Size-1 );
+
+ unsigned int BehindRemovePos = Remove.end()+1;
+ // move right data behind the input range
+ memmove( &Data[Remove.start()], &Data[BehindRemovePos], Size-BehindRemovePos );
+
+ // set new values
+ Size -= Remove.width();
+
+ Modified = true;
+ return Remove.width();
+}
+
+
+unsigned int KPlainBuffer::replace( KSection Remove, const char* D, unsigned int InputLength )
+{
+ // check all parameters
+ if( Remove.start() >= (int)Size || (Remove.width()==0 && InputLength==0) )
+ return 0;
+
+ Remove.restrictEndTo( Size-1 );
+
+ int SizeDiff = InputLength - Remove.width();
+ unsigned int NewSize = Size + SizeDiff;
+ // check if buffer does not get to big TODO: make algo simplier and less if else
+ if( MaxSize != -1 && (int)NewSize > MaxSize)
+ {
+ if( (int)Size == MaxSize )
+ return 0;
+ InputLength -= NewSize - MaxSize;
+ NewSize = MaxSize;
+ }
+ else if( KeepsMemory && NewSize > RawSize )
+ {
+ if( Size == RawSize )
+ return 0;
+ InputLength -= NewSize - RawSize;
+ NewSize = RawSize;
+ }
+
+ int BehindInsertPos = Remove.start() + InputLength;
+ int BehindRemovePos = Remove.end()+1;
+
+ // raw array not big enough?
+ if( RawSize < NewSize )
+ {
+ // create new buffer
+ char *NewData = new char[NewSize];
+ if( NewData == 0 )
+ return 0;
+
+ // move old data to its (new) places
+ memcpy( NewData, Data, Remove.start() );
+ memcpy( &NewData[BehindInsertPos], &Data[BehindRemovePos], Size-BehindRemovePos );
+
+ // remove old
+ delete [] Data;
+ // set new values
+ Data = NewData;
+ RawSize = NewSize;
+ }
+ else
+ // move old data to its (new) places
+ memmove( &Data[BehindInsertPos], &Data[BehindRemovePos], Size-BehindRemovePos );
+
+ // copy new data to its place
+ memcpy( &Data[Remove.start()], D, InputLength );
+
+ // set new values
+ Size = NewSize;
+
+ Modified = true;
+ return InputLength;
+}
+
+
+int KPlainBuffer::move( int DestPos, KSection SourceSection )
+{
+ // check all parameters
+ if( SourceSection.start() >= (int)Size || SourceSection.width() == 0
+ || DestPos > (int)Size || SourceSection.start() == DestPos )
+ return SourceSection.start();
+
+ SourceSection.restrictEndTo( Size-1 );
+ bool ToRight = DestPos > SourceSection.start();
+ int MovedLength = SourceSection.width();
+ int DisplacedLength = ToRight ? DestPos - SourceSection.end()-1 : SourceSection.start() - DestPos;
+
+ // find out section that is smaller
+ int SmallPartLength, LargePartLength, SmallPartStart, LargePartStart, SmallPartDest, LargePartDest;
+ // moving part is smaller?
+ if( MovedLength < DisplacedLength )
+ {
+ SmallPartStart = SourceSection.start();
+ SmallPartLength = MovedLength;
+ LargePartLength = DisplacedLength;
+ // moving part moves right?
+ if( ToRight )
+ {
+ SmallPartDest = DestPos - MovedLength;
+ LargePartStart = SourceSection.end()+1;
+ LargePartDest = SourceSection.start();
+ }
+ else
+ {
+ SmallPartDest = DestPos;
+ LargePartStart = DestPos;
+ LargePartDest = DestPos + MovedLength;
+ }
+ }
+ else
+ {
+ LargePartStart = SourceSection.start();
+ LargePartLength = MovedLength;
+ SmallPartLength = DisplacedLength;
+ // moving part moves right?
+ if( ToRight )
+ {
+ LargePartDest = DestPos - MovedLength;
+ SmallPartStart = SourceSection.end()+1;
+ SmallPartDest = SourceSection.start();
+ }
+ else
+ {
+ LargePartDest = DestPos;
+ SmallPartStart = DestPos;
+ SmallPartDest = DestPos + MovedLength;
+ }
+ }
+
+ // copy smaller part to tempbuffer
+ char *Temp = new char[SmallPartLength];
+ memcpy( Temp, &Data[SmallPartStart], SmallPartLength );
+
+ // move the larger part
+ memmove( &Data[LargePartDest], &Data[LargePartStart], LargePartLength );
+
+ // copy smaller part to its new dest
+ memcpy( &Data[SmallPartDest], Temp, SmallPartLength );
+ delete [] Temp;
+
+ Modified = true;
+ return MovedLength < DisplacedLength ? SmallPartDest : LargePartDest;
+}
+
+
+int KPlainBuffer::fill( const char FChar, int FillLength, unsigned int Pos )
+{
+ // nothing to fill
+ if( Pos >= Size )
+ return 0;
+
+ int LengthToEnd = Size - Pos;
+
+ if( FillLength < 0 )
+ FillLength = LengthToEnd;
+ else if( FillLength > LengthToEnd )
+ FillLength = addSize( FillLength, Pos, false );
+
+ memset( &Data[Pos], FChar, FillLength );
+ Modified = true;
+ return FillLength;
+}
+
+
+int KPlainBuffer::find( const char* SearchString, int Length, KSection Section ) const
+{
+ Section.restrictEndTo( Size-1 );
+
+ for( int i = Section.start(); i <= Section.end(); ++i )
+ {
+ int Result;
+// if( IgnoreCase )
+// result = strncasecmp( &data()[i], sc.key.data(), sc.key.size() );
+// else
+ Result = memcmp( &Data[i], SearchString, Length );
+ // found?
+ if( Result == 0 )
+ return i;
+ }
+ return -1;
+}
+
+int KPlainBuffer::rfind( const char*, int /*Length*/, int /*Pos*/ ) const { return 0; }
+
+
+int KPlainBuffer::addSize( int AddSize, int SplitPos, bool SaveUpperPart )
+{
+ unsigned int NewSize = Size + AddSize;
+ // check if buffer does not get too big
+ if( MaxSize != -1 && (int)NewSize > MaxSize )
+ {
+ if( (int)Size == MaxSize )
+ return 0;
+ NewSize = MaxSize;
+ AddSize = NewSize - Size;
+ }
+ else if( KeepsMemory && NewSize > RawSize )
+ {
+ if( Size == RawSize )
+ return 0;
+ NewSize = RawSize;
+ AddSize = NewSize - Size;
+ }
+
+ int BehindSplitPos = SplitPos + AddSize;
+ // raw array not big enough?
+ if( RawSize < NewSize )
+ {
+ // get new raw size
+ unsigned int ChunkSize = MinChunkSize;
+ // find chunk size where newsize fits into
+ while( ChunkSize < NewSize )
+ ChunkSize <<= 1;
+ // limit to max size
+ if( ChunkSize > MaxChunkSize )
+ ChunkSize = MaxChunkSize;
+ // find add size
+ unsigned int NewRawSize = ChunkSize;
+ while( NewRawSize<NewSize )
+ NewRawSize += ChunkSize;
+ // create new buffer
+ char *NewData = new char[NewRawSize];
+
+ // move old data to its (new) places
+ memcpy( NewData, Data, SplitPos );
+ if( SaveUpperPart )
+ memcpy( &NewData[BehindSplitPos], &Data[SplitPos], Size-SplitPos );
+
+ // remove old
+ delete [] Data;
+ // set new values
+ Data = NewData;
+ RawSize = NewRawSize;
+ }
+ // old buffer kept
+ else
+ {
+ if( SaveUpperPart )
+ // move old data to its (new) places
+ memmove( &Data[BehindSplitPos], &Data[SplitPos], Size-SplitPos );
+ }
+
+ // set new values
+ Size = NewSize;
+
+ return AddSize;
+}
diff --git a/khexedit/lib/kplainbuffer.h b/khexedit/lib/kplainbuffer.h
new file mode 100644
index 0000000..27bbbad
--- /dev/null
+++ b/khexedit/lib/kplainbuffer.h
@@ -0,0 +1,131 @@
+/***************************************************************************
+ kplainbuffer.h - description
+ -------------------
+ begin : Mit Jun 03 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KPLAINBUFFER_H
+#define KHE_KPLAINBUFFER_H
+
+#include "kdatabuffer.h"
+
+namespace KHE
+{
+/*
+class KPlainBufferIterator : public KDataBufferIterator
+{
+}
+*/
+/** base class for all Data buffers that are used to display
+ * TODO: think about a way to inform KHexEdit that there has been
+ * a change in the buffer outside. what kind of changes are possible?
+ *@author Friedrich W. H. Kossebau
+ */
+
+class KPlainBuffer : public KDataBuffer
+{
+ friend class KPlainBufferIterator;
+
+ public:
+ KPlainBuffer( char *D, unsigned int S, int RS = -1, bool KM = true );
+ KPlainBuffer( const char *D, unsigned int S );
+ KPlainBuffer( int S=0, int MS = -1 );
+ virtual ~KPlainBuffer();
+
+ public: // KDataBuffer API
+ virtual bool prepareRange( KSection Range ) const;
+ //virtual KDataBufferIterator *iterator() const;
+ virtual const char *dataSet( KSection S ) const;
+ virtual char datum( unsigned int Offset ) const;
+ virtual int size() const;
+ virtual bool isReadOnly() const;
+ virtual bool isModified() const;
+
+ virtual int insert( int Pos, const char*, int Length );
+ virtual int remove( KSection Remove );
+ virtual unsigned int replace( KSection Remove, const char*, unsigned int InputLength );
+ virtual int move( int DestPos, KSection SourceSection );
+ virtual int fill( const char FillChar, int Length = -1, unsigned int Pos = 0 );
+ virtual void setDatum( unsigned int Offset, const char Char );
+
+ virtual void setModified( bool M = true );
+
+ //virtual int find( const char*, int Length, int Pos = 0 ) const;
+ virtual int find( const char*KeyData, int Length, KSection Section ) const;
+ virtual int rfind( const char*, int Length, int Pos = -1 ) const;
+
+/* virtual int find( const QString &expr, bool cs, bool wo, bool forward = true, int *index = 0 ); */
+
+ public:
+ void setReadOnly( bool RO = true );
+ void setMaxSize( int MS );
+ /** sets whether the memory given by setData or in the constructor should be kept on resize
+ */
+ void setKeepsMemory( bool KM = true );
+
+ public:
+ char *data() const;
+ int maxSize() const;
+ /** returns whether the memory of the byte array is kept */
+ bool keepsMemory() const;
+
+ protected:
+ /** resizes the buffer, if possible, saving the data and splitting the data, if demanded
+ * @param AddSize additional size the buffer should grow
+ * @param SplitPos if -1 does not split
+ * @param SaveUpperPart true if upper part should be copied into new buffer
+ * @return additional size the buffer has grown
+ */
+ int addSize( int AddSize, int SplitPos = -1, bool SaveUpperPart = true );
+
+ protected:
+ /** */
+ char *Data;
+ /** size of the data */
+ unsigned int Size;
+ /** Size of data array */
+ unsigned int RawSize;
+ /** maximal size of array, unlimited if -1 */
+ int MaxSize;
+ /** flag whether the initially given memory should be kept */
+ bool KeepsMemory:1;
+ /** */
+ bool ReadOnly:1;
+ /** */
+ bool Modified:1;
+};
+
+
+inline bool KPlainBuffer::prepareRange( KSection ) const { return true; }
+inline const char *KPlainBuffer::dataSet( KSection S ) const { return &Data[S.start()]; }
+inline char KPlainBuffer::datum( unsigned int Offset ) const { return Data[Offset]; }
+inline int KPlainBuffer::size() const { return Size; }
+
+inline bool KPlainBuffer::isReadOnly() const { return ReadOnly; }
+inline bool KPlainBuffer::isModified() const { return Modified; }
+
+inline void KPlainBuffer::setDatum( unsigned int Offset, const char Char )
+{ Data[Offset] = Char; Modified = true; }
+
+inline void KPlainBuffer::setReadOnly( bool RO ) { ReadOnly = RO; }
+inline void KPlainBuffer::setModified( bool M ) { Modified = M; }
+inline void KPlainBuffer::setMaxSize( int MS ) { MaxSize = MS; }
+inline void KPlainBuffer::setKeepsMemory( bool KM ) { KeepsMemory = KM; }
+
+inline char *KPlainBuffer::data() const { return Data; }
+inline int KPlainBuffer::maxSize() const { return MaxSize; }
+inline bool KPlainBuffer::keepsMemory() const { return KeepsMemory; }
+}
+
+#endif
diff --git a/khexedit/lib/krange.h b/khexedit/lib/krange.h
new file mode 100644
index 0000000..a0df3f1
--- /dev/null
+++ b/khexedit/lib/krange.h
@@ -0,0 +1,123 @@
+/***************************************************************************
+ krange.h - description
+ -------------------
+ begin : Sun 03.08.2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+****************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KRANGE_H
+#define KHE_KRANGE_H
+
+
+namespace KHE
+{
+
+/** This template describes a range.
+ * A range is something with a start and an end.
+ * The start is a value relative before the end.
+ * The distance cannot be estimated.
+ *
+ *@author Friedrich W. H. Kossebau
+ */
+template<class T>
+class KRange
+{
+ public:
+ KRange( T S, T E ) : Start( S ), End( E ) {}
+ KRange() : Start( null() ), End( null() ) {}
+ ~KRange() {}
+
+ public:
+ KRange &operator=( const KRange &R ) { Start = R.Start; End = R.End; return *this; }
+
+ public:
+ bool operator==( const KRange &R ) const { return Start == R.Start && End == R.End; }
+
+ public: // modification access
+ /** sets the first and the last index of the range */
+ void set( T S, T E ) { Start = S; End = E; }
+ /** sets the first index of the range */
+ void setStart( T S ) { Start = S; }
+ /** sets the last index of the range */
+ void setEnd( T E ) { End = E; }
+ /** sets the range to null */
+ void unset() { Start = End = null(); }
+ /** restricts the range to Limit. If one of both ranges is invalid the behaviour is undefined */
+ void restrictTo( const KRange &Limit )
+ { if( Start < Limit.start() ) Start = Limit.start(); if( End > Limit.end() ) End = Limit.end(); }
+ /** restricts the start to Limit. If the range is invalid the behaviour is undefined */
+ void restrictStartTo( T Limit ) { if( Start < Limit ) Start = Limit; }
+ /** restricts the end to Limit. If the range is invalid the behaviour is undefined */
+ void restrictEndTo( T Limit ) { if( End > Limit ) End = Limit; }
+ /** extends the range to Limit. If one of both is invalid the behaviour is undefined */
+ void extendTo( const KRange &Limit )
+ { if( Start > Limit.start() ) Start = Limit.start(); if( End < Limit.end() ) End = Limit.end(); }
+ /** extends the start to Limit. If the range is invalid the behaviour is undefined */
+ void extendStartTo( T Limit ) { if( Start > Limit ) Start = Limit; }
+ /** extends the end to Limit. If the range is invalid the behaviour is undefined */
+ void extendEndTo( T Limit ) { if( End < Limit ) End = Limit; }
+ /** moves the range by D. If the range is invalid the behaviour is undefined */
+ void moveBy( T D ) { Start += D; End += D; }
+
+ public: // value access
+ /** @return start */
+ T start() const { return Start; }
+ /** @return end */
+ T end() const { return End; }
+
+
+ public: // logic access
+ /** returns true if Value is covered */
+ bool includes( T Value ) const { return Value <= End && Value >= Start; }
+ /** returns true if range is before index. if range is invalid the behaviour is undefined */
+ bool endsBefore( T Value ) const { return End < Value; }
+ /** returns true if range is behind index. if range is invalid the behaviour is undefined */
+ bool startsBehind( T Value ) const { return Start > Value; }
+ /** returns true is the range starts before index. If the range is invalid the behaviour is undefined */
+ bool startsBefore( T Value ) const { return Start < Value; }
+ /** returns true is the range end later then index. If the range is invalid the behaviour is undefined */
+ bool endsBehind( T Value ) const { return End > Value; }
+
+ /** returns true is the range covers R. If one of both is invalid the behaviour is undefined */
+ bool includes( const KRange &R ) const { return End >= R.End && Start <= R.Start; }
+ /** returns true is the range ends before R starts. If one of both is invalid the behaviour is undefined */
+ bool endsBefore( const KRange &R ) const { return End < R.Start; }
+ /** returns true is the range starts later than R ends. If one of both is invalid the behaviour is undefined */
+ bool startsBehind( const KRange &R ) const { return Start > R.End; }
+ /** returns true is the range starts prior than R. If one of both is invalid the behaviour is undefined */
+ bool startsBefore( const KRange &R ) const { return Start < R.Start; }
+ /** returns true is the range ends later than R. If one of both is invalid the behaviour is undefined */
+ bool endsBehind( const KRange &R ) const { return End > R.End; }
+ /** returns true is the range shares at least one index with R. If one of both is invalid the behaviour is undefined */
+ bool overlaps( const KRange &R ) const { return Start <= R.End && End >= R.Start; }
+
+ /** returns true if the range covers at least one index */
+ bool isValid() const { return Start != null() && Start <= End; }
+ /** returns true if the range has not been set */
+ bool isEmpty() const { return Start == null() && End == null(); }
+
+
+ protected:
+ /** delivers a null element. Should be specialiced for complexer types. */
+ const T null () const { return T(-1);}
+
+ protected:
+ /** first value of the range */
+ T Start;
+ /** last value of the range */
+ T End;
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/kreadonlybuffer.h b/khexedit/lib/kreadonlybuffer.h
new file mode 100644
index 0000000..63264b2
--- /dev/null
+++ b/khexedit/lib/kreadonlybuffer.h
@@ -0,0 +1,45 @@
+/***************************************************************************
+ kreadonlybuffer.h - description
+ -------------------
+ begin : Mit Mai 14 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KREADONLYBUFFER_H
+#define KHE_KREADONLYBUFFER_H
+
+#include "kdatabuffer.h"
+
+namespace KHE
+{
+
+/**
+ *@author Friedrich W. H. Kossebau
+ */
+
+class KReadOnlyBuffer : public KDataBuffer
+{
+ public:
+ KReadOnlyBuffer() {}
+ ~KReadOnlyBuffer() {}
+
+ public: // KDataBuffer API
+ /** is the buffer changeable ?*/
+ virtual bool isReadOnly() const { return true; }
+ /** has the buffer been modified? */
+ virtual bool isModified() const { return false; }
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/ksection.h b/khexedit/lib/ksection.h
new file mode 100644
index 0000000..7693219
--- /dev/null
+++ b/khexedit/lib/ksection.h
@@ -0,0 +1,108 @@
+/***************************************************************************
+ ksection.h - description
+ -------------------
+ begin : Sun 22.06.2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+****************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KSECTION_H
+#define KHE_KSECTION_H
+
+
+#include "krange.h"
+
+namespace KHE
+{
+
+/** describes a section of indizes
+ *@author Friedrich W. H. Kossebau
+ */
+class KSection : public KRange<int>
+{
+ public:
+ /** constructs a section
+ * @param SI starting index
+ * @param EI end index
+ */
+ KSection( int SI, int EI );
+ /** constructs a section
+ * @param SI starting index
+ * @param W width of the section
+ */
+ KSection( int SI, int W, bool );
+ KSection();
+ ~KSection();
+
+ public:
+ KSection &operator=( const KSection &S );
+
+ public:
+ bool operator==( const KSection &S ) const;
+
+ public:
+ void setByWidth( int S, int Width );
+ /** sets the first index of the section's range one behind the other's end
+ * If one of both is invalid the behaviour is undefined
+ */
+ void setStartBehind( KSection S );
+ /** sets the first index of the section's range one behind the other's end
+ * If one of both is invalid or the other' start is 0 the behaviour is undefined
+ */
+ void setEndBefore( KSection S );
+ /** sets the first index of the section's range to be width-1 before the end
+ * If the section is invalid the behaviour is undefined
+ */
+ void setStartByWidth( int Width );
+ /** sets the last index of the section's range to be width-1 behind the start
+ * If the section is invalid the behaviour is undefined
+ */
+ void setEndByWidth( int Width );
+ /** moves the range defined by a new start.
+ * If the range is invalid the behaviour is undefined
+ */
+ void moveToStart( int S );
+ /** moves the range defined by a new start.
+ * If the range is invalid the behaviour is undefined
+ */
+ void moveToEnd( int E );
+
+ public:
+ /**
+ * @return the numbered of included indizes or 0, if the section is invalid
+ */
+ int width() const;
+};
+
+
+inline KSection::KSection( int SI, int EI ) : KRange<int>(SI,EI) {}
+inline KSection::KSection( int SI, int W, bool ) : KRange<int>(SI,SI+W-1) {}
+inline KSection::KSection() {}
+inline KSection::~KSection() {}
+
+inline bool KSection::operator==( const KSection &S ) const { return KRange<int>::operator==(S); }
+
+inline KSection &KSection::operator=( const KSection &S ) { KRange<int>::operator=(S); return *this; }
+
+inline int KSection::width() const { return isValid() ? end()-start()+1 : 0; }
+
+inline void KSection::setByWidth( int S, int Width ) { setStart( S ); setEnd( S+Width-1 ); }
+inline void KSection::setStartByWidth( int Width ) { setStart( end()-Width+1 ); }
+inline void KSection::setEndByWidth( int Width ) { setEnd( start()+Width-1 ); }
+inline void KSection::setStartBehind( KSection S ) { setStart( S.end()+1 ); }
+inline void KSection::setEndBefore( KSection S ) { setEnd( S.start()-1 ); }
+
+inline void KSection::moveToStart( int S ) { setEnd( S+width()-1 ); setStart( S ); }
+inline void KSection::moveToEnd( int E ) { setStart( E-width()+1 ); setEnd( E ); }
+}
+
+#endif
diff --git a/khexedit/lib/ksectionlist.cpp b/khexedit/lib/ksectionlist.cpp
new file mode 100644
index 0000000..eec54e4
--- /dev/null
+++ b/khexedit/lib/ksectionlist.cpp
@@ -0,0 +1,79 @@
+/***************************************************************************
+ ksectionlist.cpp - description
+ -------------------
+ begin : Mon Jun 30 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// lib specific
+#include "ksectionlist.h"
+
+using namespace KHE;
+
+KSectionList::KSectionList()
+{
+}
+
+
+KSectionList::~KSectionList()
+{
+}
+
+
+void KSectionList::addSection( KSection NewSection )
+{
+ if( !NewSection.isValid() )
+ return;
+
+ // we try to insert it by ascending indizes
+ // if sections are overlapping we combine them
+ iterator S = begin();
+ for( ; S!=end(); ++S )
+ {
+ // is new section before the next section?
+ if( NewSection.endsBefore(*S) )
+ {
+ // put the new before it
+ insert( S, NewSection );
+ return;
+ }
+
+ // does the next section overlap?
+ if( (*S).overlaps(NewSection) )
+ {
+ // Start of the combined sections is the smaller one
+ NewSection.extendStartTo( (*S).start() );
+ // next we search all the overlapping sections and keep the highest end index
+ int End = (*S).end();
+ iterator LS = S;
+ for( ++LS; LS!=end(); ++LS )
+ {
+ if( !(*LS).overlaps(NewSection) )
+ break;
+ End = (*LS).end();
+ }
+ // the higher end is the end of the combined section
+ NewSection.extendEndTo( End );
+ // remove all overlapping sections
+ S = erase( S, LS );
+ // and instead insert the combined one
+ insert( S, NewSection );
+ return;
+ }
+ }
+
+ // all others are before the new?
+ if( S == end() )
+ // add it at the end
+ append( NewSection );
+}
diff --git a/khexedit/lib/ksectionlist.h b/khexedit/lib/ksectionlist.h
new file mode 100644
index 0000000..7328e42
--- /dev/null
+++ b/khexedit/lib/ksectionlist.h
@@ -0,0 +1,44 @@
+/***************************************************************************
+ ksectionlist.h - description
+ -------------------
+ begin : Mon Jun 30 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KSECTIONLIST_H
+#define KHE_KSECTIONLIST_H
+
+// qt specific
+#include <qvaluelist.h>
+// lib specific
+#include "ksection.h"
+
+namespace KHE {
+
+typedef QValueList<KSection> KSectionBasicList;
+/**
+@author Friedrich W. H. Kossebau
+*/
+class KSectionList : public KSectionBasicList
+{
+ public:
+ KSectionList();
+ ~KSectionList();
+
+ public:
+ void addSection( KSection S );
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/kselection.h b/khexedit/lib/kselection.h
new file mode 100644
index 0000000..19b8a99
--- /dev/null
+++ b/khexedit/lib/kselection.h
@@ -0,0 +1,178 @@
+/***************************************************************************
+ kbuffersection.h - description
+ -------------------
+ begin : 22.06.2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+****************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KSELECTION_H
+#define KHE_KSELECTION_H
+
+#include "ksection.h"
+
+namespace KHE
+{
+
+/** This class describes a selected section of the buffer.
+ * As it is used as selection controlled by
+ * mouse and keyboard commands it offers two ways to set its range:
+ * - by giving the startposition (of the cursor) of an interactive selection
+ * and the subsequent end positions (until selection is finished)
+ * - direct setting (as provided by KSection)
+ *
+ * the interactive selection takes care that
+ *
+ *@author Friedrich W. H. Kossebau
+ */
+class KSelection : public KSection
+{
+ public:
+ /** creates a selection with a given start.
+ * @param Index index in front of which the selection begins
+ */
+ KSelection( int Index );
+ /** creates an invalid selection */
+ KSelection();
+ ~KSelection();
+
+ public:
+ KSelection &operator=( const KSelection &S );
+ KSelection &operator=( const KSection &S );
+
+ public: // modification access
+ /** starts the selection.
+ * For this the anchor, start and end are set to the given index,
+ * so the initial selection is empty.
+ * @param Index index in front of which the selection begins
+ */
+ void setStart( int Index );
+ /** sets the end of the current selection
+ * If the end is before the start the selection will reach from the given index
+ * @param Index index in front of which the selection ends
+ */
+ void setEnd( int Index );
+ /** sets the selection to be invalid
+ */
+ void cancel();
+ /** sets the anchor to the start
+ * If the selection has not started the behaviour is undefined.
+ */
+ void setForward();
+ /** sets the anchor to the end
+ * If the selection has not started the behaviour is undefined.
+ */
+ void setBackward();
+ /** swaps anchor from start to end or vice versa
+ * If the selection has not started the behaviour is undefined.
+ */
+ void reverse();
+
+ public: // value access
+ /**
+ * @return anchor value
+ */
+ int anchor() const;
+
+ public: // logic access
+ /**
+ * @return @c true if the anchor has been set, otherwise @c false.
+ */
+ bool started() const;
+ /**
+ * @return @c true if the anchor has been set and the selection is empty, otherwise @c false.
+ */
+ bool justStarted() const;
+ /**
+ * @return @c true if the anchor is at the begin of the selection
+ */
+ bool isForward() const;
+
+ protected:
+ /** cursor index where the selection starts */
+ int Anchor;
+};
+
+
+inline KSelection::KSelection() : Anchor( -1 ) {}
+inline KSelection::KSelection( int Index ) : Anchor( Index ) {}
+inline KSelection::~KSelection() {}
+
+inline KSelection &KSelection::operator=( const KSelection &S )
+{
+ KSection::operator=(S);
+ Anchor = S.Anchor;
+ return *this;
+}
+
+inline KSelection &KSelection::operator=( const KSection &S )
+{
+ KSection::operator=(S);
+ Anchor = start();
+ return *this;
+}
+
+
+inline void KSelection::setStart( int Index )
+{
+ Anchor = Index;
+ unset();
+}
+
+
+inline void KSelection::setEnd( int Index )
+{
+ // nothing selected?
+ if( Index == Anchor )
+ unset();
+ // selecting forwards?
+ else if( Index > Anchor )
+ {
+ KSection::setStart( Anchor );
+ KSection::setEnd( Index-1 );
+ }
+ // selecting backwards
+ else
+ {
+ KSection::setStart( Index );
+ KSection::setEnd( Anchor-1 );
+ }
+}
+
+inline void KSelection::reverse()
+{
+ Anchor = isForward() ? end()+1 : start();
+}
+
+inline void KSelection::setForward()
+{
+ Anchor = start();
+}
+
+inline void KSelection::setBackward()
+{
+ Anchor = end()+1;
+}
+
+inline int KSelection::anchor() const { return Anchor; }
+
+inline void KSelection::cancel() { Anchor = -1; unset(); }
+
+inline bool KSelection::started() const { return Anchor != -1; }
+
+inline bool KSelection::justStarted() const { return Anchor != -1 && start() == -1; }
+
+inline bool KSelection::isForward() const { return Anchor == start(); }
+
+}
+
+#endif
diff --git a/khexedit/lib/kvaluecoltextexport.cpp b/khexedit/lib/kvaluecoltextexport.cpp
new file mode 100644
index 0000000..009ad54
--- /dev/null
+++ b/khexedit/lib/kvaluecoltextexport.cpp
@@ -0,0 +1,69 @@
+/***************************************************************************
+ kvaluecoltextexport.cpp - description
+ -------------------
+ begin : Wed Sep 3 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// lib specific
+#include "kbufferlayout.h"
+#include "kvaluecolumn.h"
+#include "kvaluecoltextexport.h"
+#include "helper.h"
+
+
+using namespace KHE;
+
+KValueColTextExport::KValueColTextExport( const KValueColumn* HC, const char *D, KCoordRange CR )
+ : KBufferColTextExport( HC, D, CR, HC->byteCodec()->encodingWidth() ),
+ ByteCodec( KByteCodec::createCodec(HC->coding()) )
+{
+}
+
+
+KValueColTextExport::~KValueColTextExport()
+{
+ delete ByteCodec;
+}
+
+
+
+void KValueColTextExport::print( QString &T ) const
+{
+ int p = 0;
+ int pEnd = NoOfBytesPerLine;
+ // correct boundaries
+ if( PrintLine == CoordRange.start().line() )
+ p = CoordRange.start().pos();
+ if( PrintLine == CoordRange.end().line() )
+ pEnd = CoordRange.end().pos()+1;
+
+ QString E;
+ E.setLength( ByteCodec->encodingWidth() );
+ // draw individual chars
+ uint e = 0;
+ for( ; p<pEnd; ++p, ++PrintData )
+ {
+ // get next position
+ uint t = Pos[p];
+ // clear spacing
+ T.append( whiteSpace(t-e) );
+ ByteCodec->encode( E, 0, *PrintData );
+ T.append( E );
+ e = t + ByteCodec->encodingWidth();
+ }
+
+ T.append( whiteSpace(NoOfCharsPerLine-e) );
+ ++PrintLine;
+}
+
diff --git a/khexedit/lib/kvaluecoltextexport.h b/khexedit/lib/kvaluecoltextexport.h
new file mode 100644
index 0000000..be6bab4
--- /dev/null
+++ b/khexedit/lib/kvaluecoltextexport.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ kvaluecoltextexport.h - description
+ -------------------
+ begin : Sam Aug 30 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KVALUECOLTEXTEXPORT_H
+#define KHE_KVALUECOLTEXTEXPORT_H
+
+#include "kbytecodec.h"
+#include "kbuffercoltextexport.h"
+
+
+namespace KHE
+{
+
+class KValueColumn;
+
+
+class KValueColTextExport : public KBufferColTextExport
+{
+ public:
+ KValueColTextExport( const KValueColumn* BF, const char *D, KCoordRange CR );
+ virtual ~KValueColTextExport();
+
+ protected:
+ virtual void print( QString &T ) const;
+
+
+ protected:
+ KByteCodec *ByteCodec;
+};
+
+}
+
+#endif
diff --git a/khexedit/lib/kvaluecolumn.cpp b/khexedit/lib/kvaluecolumn.cpp
new file mode 100644
index 0000000..82da795
--- /dev/null
+++ b/khexedit/lib/kvaluecolumn.cpp
@@ -0,0 +1,134 @@
+/***************************************************************************
+ kvaluecolumn.cpp - description
+ -------------------
+ begin : Mit Sep 3 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// qt specific
+#include <qpainter.h>
+// lib specific
+#include "kcolumnsview.h"
+#include "kbuffercursor.h"
+#include "kbufferlayout.h"
+#include "kbufferranges.h"
+#include "kvaluecolumn.h"
+#include "helper.h"
+#include "kcharcodec.h"
+
+using namespace KHE;
+
+static const KCoding DefaultCoding = HexadecimalCoding;
+static const KCoding NotDefaultCoding = DecimalCoding;
+static const int DefaultBinaryGapWidth = 1;
+
+
+KValueColumn::KValueColumn( KColumnsView *CV, KDataBuffer *B, KBufferLayout *L, KBufferRanges *R )
+ : KBufferColumn( CV, B, L, R ),
+ Coding( NotDefaultCoding ),
+ ByteCodec( 0 ),
+ BinaryGapWidth( DefaultBinaryGapWidth )
+{
+ setCoding( DefaultCoding );
+}
+
+
+KValueColumn::~KValueColumn()
+{
+}
+
+
+
+bool KValueColumn::setCoding( KCoding C )
+{
+ // no changes?
+ if( Coding == C )
+ return false;
+
+ delete ByteCodec;
+
+ Coding = C;
+ ByteCodec = KByteCodec::createCodec( Coding );
+ CodedByte.setLength( ByteCodec->encodingWidth() );
+
+ // recalculate depend sizes
+ recalcByteWidth();
+
+ if( PosX )
+ recalcX();
+ return true;
+}
+
+
+bool KValueColumn::setBinaryGapWidth( KPixelX BGW )
+{
+ // no changes?
+ if( BinaryGapWidth == BGW )
+ return false;
+
+ BinaryGapWidth = BGW;
+
+ // recalculate depend sizes
+ recalcByteWidth();
+
+ if( PosX )
+ recalcX();
+ return true;
+}
+
+
+void KValueColumn::recalcByteWidth()
+{
+ ByteWidth = ByteCodec->encodingWidth() * DigitWidth;
+
+ if( Coding == BinaryCoding )
+ {
+ BinaryHalfOffset = 4 * DigitWidth + BinaryGapWidth;
+ ByteWidth += BinaryGapWidth;
+ }
+ recalcVerticalGridX();
+}
+
+
+// perhaps sometimes there will be a grammar
+void KValueColumn::paintEditedByte( QPainter *P, char Byte, const QString &EditBuffer )
+{
+ KHEChar B = Codec->decode( Byte );
+
+ const QColorGroup &CG = View->colorGroup();
+
+ P->fillRect( 0,0,ByteWidth,LineHeight, QBrush(colorForChar(B),Qt::SolidPattern) );
+
+ drawCode( P, EditBuffer, CG.base() );
+}
+
+
+void KValueColumn::drawByte( QPainter *P, char Byte, KHEChar /*B*/, const QColor &Color ) const
+{
+ ByteCodec->encode( CodedByte, 0, Byte );
+ drawCode( P, CodedByte, Color );
+}
+
+
+void KValueColumn::drawCode( QPainter *P, const QString &Code, const QColor &Color ) const
+{
+ P->setPen( Color );
+ if( Coding == BinaryCoding )
+ {
+ // leave a gap in the middle
+ P->drawText( 0, DigitBaseLine, Code.left(4) );
+ P->drawText( BinaryHalfOffset, DigitBaseLine, Code.right(4) );
+ }
+ else
+ P->drawText( 0, DigitBaseLine, Code );
+}
diff --git a/khexedit/lib/kvaluecolumn.h b/khexedit/lib/kvaluecolumn.h
new file mode 100644
index 0000000..cc25929
--- /dev/null
+++ b/khexedit/lib/kvaluecolumn.h
@@ -0,0 +1,92 @@
+/***************************************************************************
+ kvaluecolumn.h - description
+ -------------------
+ begin : Mit Sep 3 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KVALUECOLUMN_H
+#define KHE_KVALUECOLUMN_H
+
+// lib specific
+#include "kbytecodec.h"
+#include "kbuffercolumn.h"
+
+
+namespace KHE
+{
+
+class KBufferRanges;
+
+
+/** buffer column which displays the numerical values of the bytes
+ *
+ *@author Friedrich W. H. Kossebau
+ */
+class KValueColumn : public KBufferColumn
+{
+ public:
+ KValueColumn( KColumnsView *CV, KDataBuffer *B, KBufferLayout *L, KBufferRanges *R );
+ virtual ~KValueColumn();
+
+ public:
+ void paintEditedByte( QPainter *P, char Byte, const QString &EditBuffer );
+
+ public: // modification access
+ /**
+ * returns true if there was a change
+ */
+ bool setCoding( KCoding C );
+ /** sets the spacing in the middle of a binary byte in the value column
+ * @param BinaryGapW spacing in the middle of a binary in pixels
+ * returns true if there was a change
+ */
+ bool setBinaryGapWidth( KPixelX BGW );
+
+
+ public: // value access
+ KPixelX binaryGapWidth() const;
+ KCoding coding() const;
+ const KByteCodec *byteCodec() const;
+
+
+ protected: // KBufferColumn API
+ virtual void drawByte( QPainter *P, char Byte, KHEChar B, const QColor &Color ) const;
+ virtual void recalcByteWidth();
+
+ protected:
+ void drawCode( QPainter *P, const QString &Code, const QColor &Color ) const;
+
+ protected: // set data
+ /** */
+ KCoding Coding;
+ /** */
+ KByteCodec *ByteCodec;
+ /** */
+ KPixelX BinaryGapWidth;
+
+ protected: // buffered data
+ /** buffer to hold the formatted coding */
+ mutable QString CodedByte;
+ /** calculated: Offset in pixels of the second half of the binary */
+ KPixelX BinaryHalfOffset;
+};
+
+
+inline KPixelX KValueColumn::binaryGapWidth() const { return BinaryGapWidth; }
+inline KCoding KValueColumn::coding() const { return Coding; }
+inline const KByteCodec *KValueColumn::byteCodec() const { return ByteCodec; }
+
+}
+
+#endif
diff --git a/khexedit/lib/kwordbufferservice.cpp b/khexedit/lib/kwordbufferservice.cpp
new file mode 100644
index 0000000..0489139
--- /dev/null
+++ b/khexedit/lib/kwordbufferservice.cpp
@@ -0,0 +1,209 @@
+/***************************************************************************
+ kwordbufferservice.cpp - description
+ -------------------
+ begin : Di Jan 18 2005
+ copyright : (C) 2005 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// lib specific
+#include "kdatabuffer.h"
+#include "kcharcodec.h"
+#include "kwordbufferservice.h"
+
+using namespace KHE;
+
+
+bool KWordBufferService::isWordChar( unsigned int Index ) const
+{
+ KHEChar C = CharCodec->decode( Buffer->datum(Index) );
+ return !C.isUndefined() && C.isLetterOrNumber();
+}
+
+
+int KWordBufferService::indexOfPreviousWordStart( unsigned int Index ) const
+{
+ unsigned int Size = Buffer->size();
+ // already at the start or can the result only be 0?
+ if( Index == 0 || Size < 3 )
+ return 0;
+
+ // search in two rounds: first for the next char, than for the next nonchar
+ // after that return the index of the one before
+ bool LookingForFirstWordChar = false;
+ for( ; Index>0; --Index )
+ {
+ if( !isWordChar(Index-1) )
+ {
+ if( !LookingForFirstWordChar )
+ continue;
+ return( Index );
+ }
+ else if( !LookingForFirstWordChar )
+ LookingForFirstWordChar = true;
+ }
+ return 0;
+}
+
+
+int KWordBufferService::indexOfNextWordStart( unsigned int Index ) const
+{
+ unsigned int Size = Buffer->size();
+ bool LookingForFirstWordChar = false;
+ for( ; Index<Size; ++Index )
+ {
+ if( isWordChar(Index) )
+ {
+ if( !LookingForFirstWordChar )
+ continue;
+ return Index;
+ }
+ else if( !LookingForFirstWordChar )
+ LookingForFirstWordChar = true;
+ }
+ // if no more word found, go to the end
+ return Size;
+}
+
+
+int KWordBufferService::indexOfBeforeNextWordStart( unsigned int Index ) const
+{
+ unsigned int Size = Buffer->size();
+ bool LookingForFirstWordChar = false;
+ for( ; Index<Size; ++Index )
+ {
+ if( isWordChar(Index) )
+ {
+ if( !LookingForFirstWordChar )
+ continue;
+ return Index-1;
+ }
+ else if( !LookingForFirstWordChar )
+ LookingForFirstWordChar = true;
+ }
+ // if no more word found, go to the end
+ return Size-1;
+}
+
+
+int KWordBufferService::indexOfWordStart( unsigned int Index ) const
+{
+ for( ; Index > 0; --Index )
+ {
+ if( !isWordChar(Index-1) )
+ return( Index );
+ }
+ return 0;
+}
+
+
+int KWordBufferService::indexOfWordEnd( unsigned int Index ) const
+{
+ unsigned int Size = Buffer->size();
+ for( ++Index; Index<Size; ++Index )
+ {
+ if( !isWordChar(Index) )
+ return Index-1;
+ }
+ // word reaches the end
+ return Size-1;
+}
+
+
+int KWordBufferService::indexOfLeftWordSelect( unsigned int Index ) const
+{
+ // word at Index?
+ if( isWordChar(Index) )
+ {
+ // search for word start to the left
+ for( ; Index>0; --Index )
+ {
+ if( !isWordChar(Index-1) )
+ return Index;
+ }
+ // reached start, so return it
+ return 0;
+ }
+ else
+ {
+ unsigned int Size = Buffer->size();
+ // search for word start to the right
+ for( ++Index; Index<Size; ++Index )
+ {
+ if( isWordChar(Index) )
+ return Index;
+ }
+ // word reaches the end, so step behind
+ return Size;
+ }
+}
+
+
+int KWordBufferService::indexOfRightWordSelect( unsigned int Index ) const
+{
+ // no word at Index?
+ if( !isWordChar(Index) )
+ {
+ // search for word end to the left
+ for( ; Index>0; --Index )
+ {
+ if( isWordChar(Index-1) )
+ return Index;
+ }
+ // reached start, so return it
+ return 0;
+ }
+ else
+ {
+ unsigned int Size = Buffer->size();
+ for( ++Index; Index<Size; ++Index )
+ {
+ // search for word end to the right
+ if( !isWordChar(Index) )
+ return Index;
+ }
+ // word reaches the end, so step behind
+ return Size;
+ }
+}
+
+/*
+int KWordBufferService::indexOfBehindWordEnd( unsigned int Index ) const
+{
+ // no word at Index?
+ return !::isWordChar(datum(Index)) ? indexOfBehindLeftWordEnd(Index) : indexOfBehindRightWordEnd(Index+1)
+}
+
+
+int KWordBufferService::indexOfBehindRightWordEnd( unsigned int Index ) const
+{
+ for( ; Index<size(); ++Index )
+{
+ if( !::isWordChar(datum(Index)) )
+ return Index;
+}
+ // word reaches the end, so step behind
+ return size();
+}
+
+
+int KWordBufferService::indexOfBehindLeftWordEnd( unsigned int Index ) const
+{
+ for( --Index; Index>=0; --Index )
+{
+ if( ::isWordChar(datum(Index)) )
+ return Index+1;
+}
+ // word reaches the end, so step behind
+ return 0;
+}
+*/
diff --git a/khexedit/lib/kwordbufferservice.h b/khexedit/lib/kwordbufferservice.h
new file mode 100644
index 0000000..805f064
--- /dev/null
+++ b/khexedit/lib/kwordbufferservice.h
@@ -0,0 +1,137 @@
+/***************************************************************************
+ kwordbufferservice.h - description
+ -------------------
+ begin : Di Jan 18 2005
+ copyright : (C) 2005 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KWORDBUFFERSERVICE_H
+#define KHE_KWORDBUFFERSERVICE_H
+
+// lib specific
+#include "ksection.h"
+
+namespace KHE
+{
+
+class KDataBuffer;
+class KCharCodec;
+
+/**
+ *
+ *@author Friedrich W. H. Kossebau
+ */
+
+class KWordBufferService
+{
+ public:
+ KWordBufferService( KDataBuffer *B, KCharCodec *C );
+ ~KWordBufferService();
+
+
+ public:
+ /** searches for the start of the word including the given index.
+ * if no other nonwordchar preceds this is 0;
+ * If the byte at the given Index is already a nonword char the given index is returned.
+ * @param Index index to start with
+ * @param CharType
+ * @return index of the first char of the current word or the given index if there is none
+ */
+ int indexOfWordStart( unsigned int Index ) const;
+ int indexOfLeftWordSelect( unsigned int Index ) const;
+ /** searches for the end of the word including the given index.
+ * If the byte at the given Index is already a nonword char the given index is returned.
+ * if no other nonwordchar follows, that of the last byte;
+ * @param Index index to start with
+ * @param CharType
+ * @return index of the last char of the current word or the given index if there is none
+ */
+ int indexOfWordEnd( unsigned int Index ) const;
+ /** searches for the first char after the end of the word including the given index.
+ * If the byte at the given Index is already a nonword char the given index is returned.
+ * if no other nonwordchar follows that of behind the last byte;
+ * @param Index index to start with
+ * @param CharType
+ * @return index of the first char after the current word or the given index if there is none
+ */
+ int indexOfRightWordSelect( unsigned int Index ) const;
+ /** searches for the first char after the end of the word including the given index.
+ * If the byte at the given Index is already a nonword char the given index is returned.
+ * if no other nonwordchar follows that of behind the last byte;
+ * @param Index index to start with
+ * @param CharType
+ * @return index of the first char after the current word or the given index if there is none
+ */
+// int indexOfBehindLeftWordEnd( unsigned int Index ) const;
+ /** searches for the first char after the end of the word including the given index.
+ * If the byte at the given Index is already a nonword char the given index is returned.
+ * if no other nonwordchar follows that of behind the last byte;
+ * @param Index index to start with
+ * @param CharType
+ * @return index of the first char after the current word or the given index if there is none
+ */
+// int indexOfBehindRightWordEnd( unsigned int Index ) const;
+ /** searches the start of the next previous word that does not include the given index,
+ * if no further word is found 0 is returned.
+ * if the index is out of range the behaviour is undefined.
+ * @param Index
+ * @param CharType
+ * @return index of the next previous word start or 0
+ */
+ int indexOfPreviousWordStart( unsigned int Index ) const;
+ /** searches for the start of the next word not including the given index.
+ * if there isn't a next word the index behind end is returned
+ * @param Index
+ * @param CharType
+ * @return index of the start of the next word or behind end
+ */
+ int indexOfNextWordStart( unsigned int Index ) const;
+ /** searches for the start of the next word not including the given index.
+ * if there isn't a next word the index of the end is returned
+ * @param Index index to start with
+ * @param CharType
+ * @return index of the last nonword char before the next word or the last index
+ */
+ int indexOfBeforeNextWordStart( unsigned int Index ) const;
+
+ /** if Index is out of range the behaviour is undefined
+ * @param Index
+ * @param CharType
+ * @return @c true if the byte at position i is a char of type CharType
+ */
+ bool isWordChar( unsigned int Index ) const;
+
+ /** returns the section with a word around index.
+ * if there is no word the section is empty
+ * @param Index
+ * @param CharType
+ * @return the section with a word around index.
+ */
+ KSection wordSection( unsigned int Index ) const;
+
+ protected:
+ KDataBuffer *Buffer;
+ KCharCodec *CharCodec;
+};
+
+
+inline KWordBufferService::KWordBufferService( KDataBuffer *B, KCharCodec *C )
+ : Buffer( B ), CharCodec( C ) {}
+inline KWordBufferService::~KWordBufferService() {}
+
+inline KSection KWordBufferService::wordSection( unsigned int Index ) const
+{ return isWordChar(Index) ? KSection( indexOfWordStart(Index), indexOfWordEnd(Index) ) : KSection(); }
+
+}
+
+#endif
diff --git a/khexedit/lib/kwrappingrobuffer.cpp b/khexedit/lib/kwrappingrobuffer.cpp
new file mode 100644
index 0000000..b913c1a
--- /dev/null
+++ b/khexedit/lib/kwrappingrobuffer.cpp
@@ -0,0 +1,61 @@
+/***************************************************************************
+ kwrappingrobuffer.cpp - description
+ -------------------
+ begin : Mit Mai 14 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#include "kwrappingrobuffer.h"
+
+using namespace KHE;
+
+KWrappingROBuffer::KWrappingROBuffer( const char* D, int L )
+{
+ Data = D;
+ Size = L;
+}
+
+KWrappingROBuffer::KWrappingROBuffer()
+{
+ Data = 0L;
+ Size = 0;
+}
+
+
+KWrappingROBuffer::~KWrappingROBuffer()
+{
+}
+
+
+const char *KWrappingROBuffer::dataSet( KSection S ) const
+{
+ return &Data[S.start()];
+}
+
+
+void KWrappingROBuffer::set( const char* D, int L )
+{
+ Data = D;
+ Size = L;
+}
+
+
+int KWrappingROBuffer::find( const char*/*KeyData*/, int /*Length*/, KSection /*Section*/ ) const
+{
+ return 0;
+}
+
+int KWrappingROBuffer::rfind( const char*, int /*Length*/, int /*Pos*/ ) const
+{
+ return 0;
+}
diff --git a/khexedit/lib/kwrappingrobuffer.h b/khexedit/lib/kwrappingrobuffer.h
new file mode 100644
index 0000000..51ee7b8
--- /dev/null
+++ b/khexedit/lib/kwrappingrobuffer.h
@@ -0,0 +1,85 @@
+/***************************************************************************
+ kwrappingrobuffer.h - description
+ -------------------
+ begin : Mit Mai 14 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHE_KWRAPPINGROBUFFER_H
+#define KHE_KWRAPPINGROBUFFER_H
+
+#include "kreadonlybuffer.h"
+
+namespace KHE
+{
+
+/**
+ *@author Friedrich W. H. Kossebau
+ */
+
+class KWrappingROBuffer : public KReadOnlyBuffer
+{
+ public:
+ static const int NothingFound = -1;
+
+ public:
+ KWrappingROBuffer();
+ KWrappingROBuffer( const char* D, int L );
+ virtual ~KWrappingROBuffer();
+
+
+ public: // KDataBuffer API
+ virtual bool prepareRange( KSection Range ) const;
+ virtual const char *dataSet( KSection S ) const;
+ virtual char datum( unsigned int Offset ) const;
+ virtual int size() const;
+ virtual bool isModified() const;
+
+ virtual int insert( int Pos, const char*, int Length );
+ virtual int remove( KSection S );
+ virtual unsigned int replace( KSection S, const char*, unsigned int Length );
+ virtual int fill( const char FillChar, int, int );
+ virtual void setDatum( unsigned int Offset, const char Char );
+
+ virtual void setModified( bool M );
+
+ virtual int find( const char*KeyData, int Length, KSection Section ) const;
+ virtual int rfind( const char*, int Length, int Pos = -1 ) const;
+
+
+ public: //
+ void set( const char* D, int L );
+
+ protected:
+ const char* Data;
+ int Size;
+ bool Modified;
+};
+
+inline int KWrappingROBuffer::size() const { return Size; }
+
+inline bool KWrappingROBuffer::isModified() const { return Modified; }
+
+inline bool KWrappingROBuffer::prepareRange( KSection ) const { return true; }
+inline char KWrappingROBuffer::datum( unsigned int Offset ) const { return Data[Offset]; }
+
+inline int KWrappingROBuffer::insert( int, const char*, int ) { return 0; }
+inline int KWrappingROBuffer::remove( KSection ) { return 0; }
+inline unsigned int KWrappingROBuffer::replace( KSection, const char*, unsigned int ) { return 0; }
+inline int KWrappingROBuffer::fill( const char , int, int ) { return 0; }
+inline void KWrappingROBuffer::setDatum( unsigned int, const char ) {}
+
+inline void KWrappingROBuffer::setModified( bool M ) { Modified = M; }
+}
+
+#endif
diff --git a/khexedit/listview.cc b/khexedit/listview.cc
new file mode 100644
index 0000000..50de78a
--- /dev/null
+++ b/khexedit/listview.cc
@@ -0,0 +1,54 @@
+/*
+ * 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 <qheader.h>
+
+
+#include "listview.h"
+
+
+CListView::CListView( QWidget *parent, const char *name, int visibleItem )
+ :KListView( parent, name ), mVisibleItem(QMAX( 1, visibleItem ))
+{
+ setVisibleItem(visibleItem);
+}
+
+void CListView::setVisibleItem( int visibleItem, bool updateSize )
+{
+ mVisibleItem = QMAX( 1, visibleItem );
+ if( updateSize == true )
+ {
+ QSize s = sizeHint();
+ setMinimumSize( s.width() + verticalScrollBar()->sizeHint().width() +
+ lineWidth() * 2, s.height() );
+ }
+}
+
+QSize CListView::sizeHint( void ) const
+{
+ QSize s = QListView::sizeHint();
+
+ int h = fontMetrics().height() + 2*itemMargin();
+ if( h % 2 > 0 ) { h++; }
+
+ s.setHeight( h*mVisibleItem + lineWidth()*2 + header()->sizeHint().height());
+ return( s );
+}
+#include "listview.moc"
diff --git a/khexedit/listview.h b/khexedit/listview.h
new file mode 100644
index 0000000..253fce9
--- /dev/null
+++ b/khexedit/listview.h
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _LISTVIEW_H_
+#define _LISTVIEW_H_
+
+#include <klistview.h>
+
+class CListView : public KListView
+{
+ Q_OBJECT
+
+ public:
+ CListView( QWidget *parent=0, const char *name=0, int visibleItem=10 );
+
+ void setVisibleItem( int visibleItem, bool updateSize=true );
+ virtual QSize sizeHint( void ) const;
+
+ private:
+ int mVisibleItem;
+};
+
+
+
+
+#endif
+
+
+
+
+
+
diff --git a/khexedit/main.cc b/khexedit/main.cc
new file mode 100644
index 0000000..525868f
--- /dev/null
+++ b/khexedit/main.cc
@@ -0,0 +1,130 @@
+/*
+ * khexedit - Versatile hex editor
+ * Copyright (C) 1999-2000 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 <stdlib.h>
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+
+#include "toplevel.h"
+#include "version.h" // Contains khexedit name string and version string
+
+
+static const char description[] =
+ I18N_NOOP("KDE hex editor");
+
+static const char version[] = APP_VERSION_STRING;
+
+static KCmdLineOptions option[] =
+{
+ { "offset <offset>", I18N_NOOP("Jump to 'offset'"), 0 },
+ { "+[file(s)]", I18N_NOOP("File(s) to open"), 0 },
+ KCmdLineLastOption
+};
+
+static uint parseDecimalOrHexadecimal( char *buf );
+
+int main( int argc, char **argv )
+{
+ KAboutData aboutData("khexedit", I18N_NOOP("KHexEdit"),
+ version, description, KAboutData::License_GPL_V2,
+ "(c) 1999-2000, Espen Sand");
+ aboutData.addAuthor("Espen Sand",0, "espensa@online.no",
+ "http://home.online.no/~espensa/khexedit/" );
+ aboutData.addCredit("",I18N_NOOP("\n"
+ "This program uses modified code and techniques from other KDE programs,\n"
+ "specifically kwrite, kiconedit and ksysv. Credit goes to authors\n"
+ "and maintainers.\n"
+ "\n"
+ "Leon Lessing, leon@lrlabs.com, has made parts of the bit swapping\n"
+ "functionality.\n"
+ "\n"
+ "Craig Graham, c_graham@hinge.mistral.co.uk, has made parts of\n"
+ "the bit stream functionality of the conversion field.\n"
+ "\n"
+ "Dima Rogozin, dima@mercury.co.il, has extended the string dialog\n"
+ "list capabilities.\n"
+ "\n"
+ "Edward Livingston-Blade, sbcs@bigfoot.com, has given me very good\n"
+ "reports which removed some nasty bugs.\n"));
+ KCmdLineArgs::init( argc, argv, &aboutData );
+ KCmdLineArgs::addCmdLineOptions( option );
+
+ KApplication app;
+
+ if( app.isRestored() != 0 )
+ {
+ RESTORE( KHexEdit );
+ }
+ else
+ {
+ KHexEdit *hexEdit = new KHexEdit;
+ if( hexEdit == 0 )
+ {
+ std::cerr << "Unable to start - Memory exhausted" << std::endl;
+ return( 1 );
+ }
+
+ hexEdit->show();
+
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ if (args->isSet("offset"))
+ {
+ QCString offsetStr = args->getOption("offset");
+ uint _offset = parseDecimalOrHexadecimal(offsetStr.data() );
+ hexEdit->setStartupOffset( _offset );
+ }
+
+ for(int i = 0; i < args->count(); i++)
+ hexEdit->addStartupFile( args->url(i).url() );
+
+ args->clear();
+ }
+
+ int result = app.exec();
+ return( result );
+}
+
+
+
+static uint parseDecimalOrHexadecimal( char *buf )
+{
+ if( buf == 0 ) { return( 0 ); }
+
+ long int value;
+ char *end = 0;
+
+ value = strtol( buf, &end, 10 );
+ if( *end != 0 )
+ {
+ value = strtol( buf, &end, 16 );
+ if( *end != 0 )
+ {
+ value = 0;
+ }
+ }
+ if( value < 0 ) { value = 0; }
+ return( value );
+}
+
diff --git a/khexedit/optiondialog.cc b/khexedit/optiondialog.cc
new file mode 100644
index 0000000..2038b2d
--- /dev/null
+++ b/khexedit/optiondialog.cc
@@ -0,0 +1,1224 @@
+/*
+ * 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 <limits.h>
+
+#include <qvbox.h>
+#include <qvbuttongroup.h>
+#include <qpainter.h>
+
+#include <qcheckbox.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qradiobutton.h>
+#include <qspinbox.h>
+#include <qwhatsthis.h>
+
+#include <kcolordialog.h>
+#include <kcolordrag.h>
+#include <kfontdialog.h> // For KFontChooser
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kglobalsettings.h>
+
+#include "optiondialog.h"
+#include <qpushbutton.h>
+#include <qcombobox.h>
+
+#if 0
+#include <qobjectlist.h>
+static void enableWidget( QWidget *w, bool state )
+{
+ if( w->children() )
+ {
+ QObjectList *l = (QObjectList*)w->children(); // silence please
+ for( uint i=0; i < l->count(); i++ )
+ {
+ QObject *o = l->at(i);
+ if( o->isWidgetType() )
+ {
+ enableWidget( (QWidget*)o, state );
+ }
+ }
+ }
+ w->setEnabled( state );
+}
+#endif
+
+
+
+COptionDialog::COptionDialog( QWidget *parent, char *name, bool modal )
+ :KDialogBase( IconList, i18n("Configure"), Help|Default|Apply|Ok|Cancel,
+ Ok, parent, name, modal, true )
+{
+ setHelp( "khexedit/khexedit.html", QString::null );
+
+ setupLayoutPage();
+ setupCursorPage();
+ setupFontPage();
+ setupColorPage();
+ setupFilePage();
+ setupMiscPage();
+ enableButton( Apply, false );
+ configChanged = false;
+}
+
+
+COptionDialog::~COptionDialog( void )
+{
+}
+
+void COptionDialog::slotChanged()
+{
+ enableButton( Apply, true );
+ configChanged = true;
+}
+
+void COptionDialog::showEvent( QShowEvent *e )
+{
+ KDialogBase::showEvent(e);
+ showPage(0);
+ mLayout.lineSizeSpin->setFocus();
+}
+
+
+void COptionDialog::setupLayoutPage( void )
+{
+ QString text;
+ QFrame *page = addPage( i18n("Layout"), i18n("Data Layout in Editor"),
+ BarIcon("khexedit", KIcon::SizeMedium ) );
+
+ QGridLayout *gbox = new QGridLayout( page, 15, 2, 0, spacingHint() );
+ gbox->setColStretch( 1, 10 );
+
+ mLayout.formatCombo = new QComboBox( false, page );
+ QStringList modeList;
+ modeList.append( i18n("Hexadecimal Mode") );
+ modeList.append( i18n("Decimal Mode") );
+ modeList.append( i18n("Octal Mode") );
+ modeList.append( i18n("Binary Mode") );
+ modeList.append( i18n("Text Only Mode") );
+ mLayout.formatCombo->insertStringList( modeList );
+ connect( mLayout.formatCombo, SIGNAL(activated(int)),
+ SLOT(slotModeSelectorChanged(int)) );
+ connect( mLayout.formatCombo, SIGNAL(activated(int)),
+ SLOT(slotChanged()) );
+ gbox->addWidget( mLayout.formatCombo, 0, 1 );
+
+ //
+ // I am setting the min. width for one widget in the second column
+ // This widtk will be used by every widget in this column.
+ //
+ mLayout.lineSizeSpin = new QSpinBox( page );
+ mLayout.lineSizeSpin->setMinimumWidth( fontMetrics().width("M") * 10 );
+ mLayout.lineSizeSpin->setRange( 1, 10000 );
+ connect( mLayout.lineSizeSpin, SIGNAL(valueChanged(int)),
+ SLOT(slotLineSizeChanged(int) ) );
+ connect( mLayout.lineSizeSpin, SIGNAL(valueChanged(int)),
+ SLOT(slotChanged()) );
+ gbox->addWidget( mLayout.lineSizeSpin, 1, 1 );
+
+ mLayout.columnSizeSpin = new QSpinBox( page );
+ mLayout.columnSizeSpin->setRange( 1, 10000 );
+ connect( mLayout.columnSizeSpin, SIGNAL(valueChanged(int)),
+ SLOT(slotColumnSizeChanged(int) ) );
+ connect( mLayout.columnSizeSpin, SIGNAL(valueChanged(int)),
+ SLOT(slotChanged() ) );
+ gbox->addWidget( mLayout.columnSizeSpin, 2, 1 );
+
+ text = i18n("Default l&ine size [bytes]:");
+ QLabel *label = new QLabel( mLayout.lineSizeSpin, text, page );
+ gbox->addWidget( label, 1, 0 );
+
+ text = i18n("Colu&mn size [bytes]:");
+ label = new QLabel( mLayout.columnSizeSpin, text, page );
+ gbox->addWidget( label, 2, 0 );
+
+ QFrame *hline = new QFrame( page );
+ hline->setFrameStyle( QFrame::Sunken | QFrame::HLine );
+ gbox->addMultiCellWidget( hline, 3, 3, 0, 1 );
+
+ text = i18n("Line size is &fixed (use scrollbar when required)");
+ mLayout.lockLineCheck = new QCheckBox( text, page );
+ gbox->addMultiCellWidget( mLayout.lockLineCheck, 4, 4, 0, 1, AlignLeft );
+ connect( mLayout.lockLineCheck, SIGNAL(toggled(bool)),
+ SLOT(slotChanged()) );
+
+ text = i18n("Loc&k column at end of line (when column size>1)");
+ mLayout.lockColumnCheck = new QCheckBox( text, page );
+ gbox->addMultiCellWidget( mLayout.lockColumnCheck, 5, 5, 0, 1 );
+ connect( mLayout.lockColumnCheck, SIGNAL(toggled(bool)),
+ SLOT(slotChanged()) );
+
+ hline = new QFrame( page );
+ hline->setFrameStyle( QFrame::Sunken | QFrame::HLine );
+ gbox->addMultiCellWidget( hline, 6, 6, 0, 1 );
+
+ QStringList gridList;
+ gridList.append( i18n("None") );
+ gridList.append( i18n("Vertical Only") );
+ gridList.append( i18n("Horizontal Only") );
+ gridList.append( i18n("Both Directions") );
+
+ mLayout.gridCombo = new QComboBox( false, page );
+ mLayout.gridCombo->insertStringList( gridList );
+ connect( mLayout.gridCombo, SIGNAL(activated(int)),
+ SLOT(slotChanged()) );
+
+ text = i18n("&Gridlines between text:");
+ label = new QLabel( mLayout.gridCombo, text, page );
+
+ gbox->addWidget( label, 7, 0 );
+ gbox->addWidget( mLayout.gridCombo, 7, 1 );
+
+ mLayout.leftSepWidthSpin = new QSpinBox( page );
+ mLayout.leftSepWidthSpin->setRange( 0, 20 );
+ gbox->addWidget( mLayout.leftSepWidthSpin, 8, 1 );
+ connect( mLayout.leftSepWidthSpin, SIGNAL(valueChanged(int)),
+ SLOT(slotChanged()) );
+
+ mLayout.rightSepWidthSpin = new QSpinBox( page );
+ mLayout.rightSepWidthSpin->setRange( 0, 20 );
+ gbox->addWidget( mLayout.rightSepWidthSpin, 9, 1 );
+ connect( mLayout.rightSepWidthSpin, SIGNAL(valueChanged(int)),
+ SLOT(slotChanged()) );
+
+ text = i18n("&Left separator width [pixels]:");
+ mLayout.leftSepLabel = new QLabel( mLayout.leftSepWidthSpin, text, page );
+ gbox->addWidget( mLayout.leftSepLabel, 8, 0 );
+
+ text = i18n("&Right separator width [pixels]:");
+ mLayout.rightSepLabel = new QLabel( mLayout.rightSepWidthSpin, text, page );
+ gbox->addWidget( mLayout.rightSepLabel, 9, 0 );
+
+ mLayout.separatorSpin = new QSpinBox( page );
+ mLayout.separatorSpin->setRange( 0, 20 );
+ gbox->addWidget( mLayout.separatorSpin, 10, 1 );
+ connect( mLayout.separatorSpin, SIGNAL(valueChanged(int)),
+ SLOT(slotChanged()) );
+
+ mLayout.edgeSpin = new QSpinBox( page );
+ mLayout.edgeSpin->setRange( 0, 20 );
+ gbox->addWidget( mLayout.edgeSpin, 11, 1 );
+ connect( mLayout.edgeSpin, SIGNAL(valueChanged(int)),
+ SLOT(slotChanged()) );
+
+ text = i18n("&Separator margin width [pixels]:");
+ label = new QLabel( mLayout.separatorSpin, text, page );
+ gbox->addWidget( label, 10, 0 );
+
+ text = i18n("&Edge margin width [pixels]:");
+ label = new QLabel( mLayout.edgeSpin, text, page );
+ gbox->addWidget( label, 11, 0 );
+
+ text = i18n("Column separation is e&qual to one character");
+ mLayout.columnCheck = new QCheckBox( text, page );
+ gbox->addMultiCellWidget( mLayout.columnCheck, 12, 12, 0, 1, AlignLeft );
+ connect( mLayout.columnCheck, SIGNAL(toggled(bool)),
+ SLOT( slotColumnSepCheck(bool)));
+ connect( mLayout.columnCheck, SIGNAL(toggled(bool)),
+ SLOT( slotChanged()));
+
+ mLayout.columnSepSpin = new QSpinBox( page );
+ mLayout.columnSepSpin->setRange( 1, 100 );
+ connect( mLayout.columnSepSpin, SIGNAL(valueChanged(int)),
+ SLOT(slotChanged()) );
+
+ text = i18n("Column separa&tion [pixels]:");
+ mLayout.columnSepLabel = new QLabel( mLayout.columnSepSpin, text, page );
+
+ gbox->addWidget( mLayout.columnSepLabel, 13, 0 );
+ gbox->addWidget( mLayout.columnSepSpin, 13, 1 );
+
+ gbox->setRowStretch( 14, 10 );
+}
+
+
+void COptionDialog::setupCursorPage( void )
+{
+ QString text;
+ QFrame *page = addPage( i18n("Cursor"),
+ i18n("Cursor Behavior (only valid for editor)"),
+ BarIcon("mouse", KIcon::SizeMedium ) );
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
+
+ QVButtonGroup *group = new QVButtonGroup( i18n("Blinking"), page );
+ group->layout()->setMargin( spacingHint() );
+ topLayout->addWidget( group );
+
+ text = i18n("Do not b&link");
+ mCursor.blinkCheck = new QCheckBox( i18n("Do not b&link"), group );
+ connect( mCursor.blinkCheck, SIGNAL(toggled(bool)),
+ SLOT( slotBlinkIntervalCheck(bool)));
+ connect( mCursor.blinkCheck, SIGNAL(toggled(bool)),
+ SLOT( slotChanged()));
+
+ QHBox *hbox = new QHBox( group );
+ mCursor.blinkLabel = new QLabel( i18n("&Blink interval [ms]:" ), hbox );
+ mCursor.blinkSpin = new QSpinBox( hbox );
+ mCursor.blinkSpin->setMinimumWidth( fontMetrics().width("M") * 10 );
+ mCursor.blinkSpin->setRange( 100, 1000 );
+ mCursor.blinkSpin->setSteps( 100, 100 );
+ mCursor.blinkSpin->setValue( 500 );
+ mCursor.blinkLabel->setBuddy(mCursor.blinkSpin);
+ connect( mCursor.blinkSpin, SIGNAL(valueChanged(int)),
+ SLOT( slotChanged()));
+
+ group = new QVButtonGroup( i18n("Shape"), page );
+ group->layout()->setMargin( spacingHint() );
+ topLayout->addWidget( group );
+
+ text = i18n("Always &use block (rectangular) cursor");
+ mCursor.blockCheck = new QCheckBox( text, group );
+ connect( mCursor.blockCheck, SIGNAL(toggled(bool)),
+ SLOT( slotBlockCursorCheck(bool)));
+ connect( mCursor.blockCheck, SIGNAL(toggled(bool)),
+ SLOT( slotChanged()));
+ text = i18n("Use &thick cursor in insert mode");
+ mCursor.thickCheck = new QCheckBox( text, group );
+ connect( mCursor.thickCheck, SIGNAL(toggled(bool)),
+ SLOT( slotChanged()));
+
+ text = i18n("Cursor Behavior When Editor Loses Focus");
+ group = new QVButtonGroup( text, page );
+ group->layout()->setMargin( spacingHint() );
+ topLayout->addWidget( group );
+
+ text = i18n("&Stop blinking (if blinking is enabled)");
+ mCursor.stopRadio = new QRadioButton( text, group, "radio1" );
+ mCursor.hideRadio = new QRadioButton( i18n("H&ide"), group, "radio2" );
+ text = i18n("Do &nothing");
+ mCursor.nothingRadio = new QRadioButton( text, group, "radio3" );
+ connect( mCursor.stopRadio, SIGNAL(toggled(bool)),
+ SLOT( slotChanged()));
+ connect( mCursor.hideRadio, SIGNAL(toggled(bool)),
+ SLOT( slotChanged()));
+ connect( mCursor.nothingRadio, SIGNAL(toggled(bool)),
+ SLOT( slotChanged()));
+
+ topLayout->addStretch(10);
+}
+
+
+void COptionDialog::setupColorPage( void )
+{
+ QString text;
+ QFrame *page = addPage( i18n("Colors"),
+ i18n("Editor Colors (system selection color is always used)"),
+ BarIcon("colorize", KIcon::SizeMedium ) );
+
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
+
+ text = i18n("&Use system colors (as chosen in Control Center)");
+ mColor.checkSystem = new QCheckBox( text, page );
+ connect( mColor.checkSystem, SIGNAL(toggled(bool)),
+ SLOT( slotColorSystem(bool)));
+ connect( mColor.checkSystem, SIGNAL(toggled(bool)),
+ SLOT( slotChanged()));
+ topLayout->addWidget( mColor.checkSystem );
+
+ QFrame *hline = new QFrame( page );
+ hline->setFrameStyle( QFrame::Sunken | QFrame::HLine );
+ topLayout->addWidget( hline );
+
+ QStringList modeList;
+ modeList.append( i18n("First, Third ... Line Background") );
+ modeList.append( i18n("Second, Fourth ... Line Background") );
+ modeList.append( i18n("Offset Background") );
+ modeList.append( i18n("Inactive Background") );
+ modeList.append( i18n("Even Column Text") );
+ modeList.append( i18n("Odd Column Text") );
+ modeList.append( i18n("Non Printable Text") );
+ modeList.append( i18n("Offset Text") );
+ modeList.append( i18n("Secondary Text") );
+ modeList.append( i18n("Marked Background") );
+ modeList.append( i18n("Marked Text") );
+ modeList.append( i18n("Cursor Background") );
+ modeList.append( i18n("Cursor Text (block shape)") );
+ modeList.append( i18n("Bookmark Background") );
+ modeList.append( i18n("Bookmark Text") );
+ modeList.append( i18n("Separator") );
+ modeList.append( i18n("Grid Lines") );
+
+ mColor.colorList = new CColorListBox( page );
+ topLayout->addWidget( mColor.colorList, 10 );
+ for( uint i=0; i<17; i++ )
+ {
+ CColorListItem *listItem = new CColorListItem( modeList[i] );
+ mColor.colorList->insertItem( listItem );
+ }
+ mColor.colorList->setCurrentItem(0);
+ connect( mColor.colorList, SIGNAL( dataChanged() ), this, SLOT( slotChanged() ) );
+}
+
+
+void COptionDialog::setupFontPage( void )
+{
+ QString text;
+ QFrame *page = addPage( i18n("Font"),
+ i18n("Font Selection (editor can only use a fixed font)"),
+ BarIcon("fonts", KIcon::SizeMedium ) );
+
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
+
+ text = i18n("&Use system font (as chosen in Control Center)");
+ mFont.checkSystem = new QCheckBox( text, page );
+ connect( mFont.checkSystem, SIGNAL(toggled(bool)),
+ this, SLOT( slotFontSystem(bool)));
+ connect( mFont.checkSystem, SIGNAL(toggled(bool)),
+ this, SLOT( slotChanged()));
+ topLayout->addWidget( mFont.checkSystem );
+
+ QFrame *hline = new QFrame( page );
+ hline->setFrameStyle( QFrame::Sunken | QFrame::HLine );
+ topLayout->addWidget( hline );
+
+ mFont.chooser = new KFontChooser( page, "font", true, QStringList(), false, 4 );
+ topLayout->addWidget( mFont.chooser );
+ QFont fixFont( KGlobalSettings::fixedFont() );
+ fixFont.setBold(true);
+ mFont.chooser->setFont( fixFont, true );
+ mFont.chooser->setSampleText( i18n("KHexEdit editor font") );
+ connect( mFont.chooser, SIGNAL(fontSelected(const QFont &)),
+ this, SLOT( slotChanged()));
+
+ hline = new QFrame( page );
+ hline->setFrameStyle( QFrame::Sunken | QFrame::HLine );
+ topLayout->addWidget( hline );
+
+ QHBoxLayout *hbox = new QHBoxLayout();
+ topLayout->addLayout( hbox );
+
+ mFont.nonPrintInput = new QLineEdit( page );
+ mFont.nonPrintInput->setMaxLength( 1 );
+ connect( mFont.nonPrintInput, SIGNAL(textChanged(const QString &)),
+ this, SLOT( slotChanged()));
+
+ text = i18n("&Map non printable characters to:");
+ QLabel *nonPrintLabel = new QLabel( mFont.nonPrintInput, text, page );
+
+ hbox->addWidget( nonPrintLabel, 0, AlignLeft );
+ hbox->addSpacing( spacingHint() );
+ hbox->addWidget( mFont.nonPrintInput, 10 );
+
+ topLayout->addStretch(10);
+}
+
+
+void COptionDialog::setupFilePage( void )
+{
+ QString text;
+ QFrame *page = addPage( i18n("Files"), i18n("File Management"),
+ BarIcon("kmultiple", KIcon::SizeMedium ) );
+
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
+
+ QGridLayout *gbox = new QGridLayout( 2, 2, spacingHint() );
+ topLayout->addLayout( gbox );
+
+ mFile.openCombo = new QComboBox( false, page );
+ QStringList modeList;
+ modeList.append( i18n("None") );
+ modeList.append( i18n("Most Recent Document") );
+ modeList.append( i18n("All Recent Documents") );
+ mFile.openCombo->insertStringList( modeList );
+ mFile.openCombo->setMinimumWidth( mFile.openCombo->sizeHint().width() );
+ connect( mFile.openCombo, SIGNAL(activated(int)),
+ this, SLOT( slotChanged()));
+
+ text = i18n("Open doc&uments on startup:");
+ QLabel *label = new QLabel( mFile.openCombo, text, page );
+
+ gbox->addWidget( label, 0, 0 );
+ gbox->addWidget( mFile.openCombo, 0, 1 );
+
+ text = i18n("&Jump to previous cursor position on startup");
+ mFile.gotoOffsetCheck = new QCheckBox( text, page );
+ // ### TODO: this is currently not available.
+ mFile.gotoOffsetCheck->setChecked( false );
+ mFile.gotoOffsetCheck->setEnabled( false );
+ // ### END
+ topLayout->addWidget( mFile.gotoOffsetCheck, 0, AlignLeft );
+ connect( mFile.gotoOffsetCheck, SIGNAL(toggled(bool)),
+ this, SLOT( slotChanged()));
+
+ QFrame *hline = new QFrame( page );
+ hline->setFrameStyle( QFrame::Sunken | QFrame::HLine );
+ topLayout->addWidget( hline );
+
+ text = i18n("Open document with &write protection enabled");
+ mFile.writeProtectCheck = new QCheckBox( text, page );
+ topLayout->addWidget( mFile.writeProtectCheck, 0, AlignLeft );
+ connect( mFile.writeProtectCheck, SIGNAL(toggled(bool)),
+ this, SLOT( slotChanged()));
+
+ text = i18n("&Keep cursor position after reloading document");
+ mFile.reloadOffsetCheck = new QCheckBox( text, page );
+ topLayout->addWidget( mFile.reloadOffsetCheck, 0, AlignLeft );
+ connect( mFile.reloadOffsetCheck, SIGNAL(toggled(bool)),
+ this, SLOT( slotChanged()));
+
+ text = i18n("&Make a backup when saving document");
+ mFile.backupCheck = new QCheckBox( text, page );
+ topLayout->addWidget( mFile.backupCheck, 0, AlignLeft );
+ connect( mFile.backupCheck, SIGNAL(toggled(bool)),
+ this, SLOT( slotChanged()));
+
+ hline = new QFrame( page );
+ hline->setFrameStyle( QFrame::Sunken | QFrame::HLine );
+ topLayout->addWidget( hline );
+
+ text = i18n("Don't &save \"Recent\" document list on exit");
+ mFile.discardRecentCheck = new QCheckBox( text, page );
+ topLayout->addWidget( mFile.discardRecentCheck, 0, AlignLeft );
+ QWhatsThis::add( mFile.discardRecentCheck,
+ i18n( "Clicking this check box makes KHexEdit forget his recent document list "
+ "when the program is closed.\n"
+ "Note: it will not erase any document of the recent document list "
+ "created by KDE." ) );
+ connect( mFile.discardRecentCheck, SIGNAL(toggled(bool)),
+ this, SLOT( slotChanged()));
+
+ text = i18n("Cl&ear \"Recent\" Document List");
+ QPushButton *discardRecentButton = new QPushButton( page );
+ discardRecentButton->setText( text );
+ QWhatsThis::add( discardRecentButton,
+ i18n( "Clicking this button makes KHexEdit forget his recent document list.\n"
+ "Note: it will not erase any document of the recent document list "
+ "created by KDE." ) );
+ topLayout->addWidget( discardRecentButton, 0, AlignCenter );
+ connect( discardRecentButton, SIGNAL(clicked()),
+ SIGNAL(removeRecentFiles()) );
+
+ topLayout->addStretch(10);
+}
+
+
+
+void COptionDialog::setupMiscPage( void )
+{
+ QString text;
+ QLabel *label;
+
+ QFrame *page = addPage( i18n("Miscellaneous"), i18n("Various Properties"),
+ BarIcon("gear", KIcon::SizeMedium ) );
+
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
+
+
+ text = i18n("Auto&matic copy to clipboard when selection is ready");
+ mMisc.autoCheck = new QCheckBox( text, page );
+ topLayout->addWidget( mMisc.autoCheck, 0, AlignLeft );
+ connect( mMisc.autoCheck, SIGNAL(toggled(bool)),
+ this, SLOT( slotChanged()));
+
+ text = i18n("&Editor starts in \"insert\" mode" );
+ mMisc.insertCheck = new QCheckBox( text, page );
+ topLayout->addWidget( mMisc.insertCheck, 0, AlignLeft );
+ connect( mMisc.insertCheck, SIGNAL(toggled(bool)),
+ this, SLOT( slotChanged()));
+
+ text = i18n("Confirm &wrapping (to beginning or end) during search");
+ mMisc.confirmWrapCheck = new QCheckBox( text, page );
+ topLayout->addWidget( mMisc.confirmWrapCheck, 0, AlignLeft );
+ connect( mMisc.confirmWrapCheck, SIGNAL(toggled(bool)),
+ this, SLOT( slotChanged()));
+
+ text = i18n("Cursor jumps to &nearest byte when moved");
+ mMisc.cursorJumpCheck = new QCheckBox( text, page );
+ topLayout->addWidget( mMisc.cursorJumpCheck, 0, AlignLeft );
+ connect( mMisc.cursorJumpCheck, SIGNAL(toggled(bool)),
+ this, SLOT( slotChanged()));
+
+ QVButtonGroup *group = new QVButtonGroup( i18n("Sounds"), page );
+ group->layout()->setMargin( spacingHint() );
+ topLayout->addWidget( group );
+ text = i18n("Make sound on data &input (eg. typing) failure");
+ mMisc.inputCheck = new QCheckBox( text, group );
+ connect( mMisc.inputCheck, SIGNAL(toggled(bool)),
+ this, SLOT( slotChanged()));
+ text = i18n("Make sound on &fatal failure");
+ mMisc.fatalCheck = new QCheckBox( text, group );
+ connect( mMisc.fatalCheck, SIGNAL(toggled(bool)),
+ this, SLOT( slotChanged()));
+
+ group = new QVButtonGroup( i18n("Bookmark Visibility"), page );
+ group->layout()->setMargin( spacingHint() );
+ topLayout->addWidget( group );
+ text = i18n("Use visible bookmarks in the offset column");
+ mMisc.bookmarkColumnCheck = new QCheckBox( text, group );
+ connect( mMisc.bookmarkColumnCheck, SIGNAL(toggled(bool)),
+ this, SLOT( slotChanged()));
+ text = i18n("Use visible bookmarks in the editor fields");
+ mMisc.bookmarkEditorCheck = new QCheckBox( text, group );
+ connect( mMisc.bookmarkEditorCheck, SIGNAL(toggled(bool)),
+ this, SLOT( slotChanged()));
+
+ text = i18n("Confirm when number of printed pages will e&xceed limit");
+ mMisc.thresholdCheck = new QCheckBox( text, page );
+ connect( mMisc.thresholdCheck, SIGNAL(clicked()),
+ SLOT( slotThresholdConfirm()));
+ connect( mMisc.thresholdCheck, SIGNAL(toggled(bool)),
+ this, SLOT( slotChanged()));
+ topLayout->addWidget( mMisc.thresholdCheck, 0, AlignLeft );
+
+ QGridLayout *glay = new QGridLayout( 3, 3 );
+ glay->setColStretch(2,10);
+ topLayout->addLayout( glay );
+
+ mMisc.thresholdSpin = new QSpinBox( page );
+ mMisc.thresholdSpin->setMinimumWidth( fontMetrics().width("M") * 10 );
+ mMisc.thresholdSpin->setRange( 5, INT_MAX );
+ mMisc.thresholdSpin->setSteps( 5, 5 );
+ mMisc.thresholdSpin->setValue( 5 );
+ connect( mMisc.thresholdSpin, SIGNAL(valueChanged(int)),
+ this, SLOT( slotChanged()));
+
+ text = i18n("&Threshold [pages]:" );
+ mMisc.thresholdLabel = new QLabel( mMisc.thresholdSpin, text, page );
+
+ glay->addWidget( mMisc.thresholdLabel, 0, 0 );
+ glay->addWidget( mMisc.thresholdSpin, 0, 1 );
+
+ QFrame *hline = new QFrame( page );
+ hline->setFrameStyle( QFrame::Sunken | QFrame::HLine );
+ glay->addMultiCellWidget( hline, 1, 1, 0, 2 );
+
+ mMisc.undoSpin = new QSpinBox( page );
+ mMisc.undoSpin->setRange( 10, 10000 );
+ mMisc.undoSpin->setSteps( 5, 5 );
+ mMisc.undoSpin->setValue( 50 );
+ connect( mMisc.undoSpin, SIGNAL(valueChanged(int)),
+ this, SLOT( slotChanged()));
+
+ label = new QLabel( mMisc.undoSpin, i18n("&Undo limit:"), page );
+ glay->addWidget( label, 2, 0 );
+ glay->addWidget( mMisc.undoSpin, 2, 1 );
+
+ topLayout->addStretch(10);
+}
+
+
+
+void COptionDialog::slotModeSelectorChanged( int index )
+{
+ int lineSize = mDisplayState.line.getLineSize( index );
+ int colSize = mDisplayState.line.getColumnSize( index );
+ mLayout.lineSizeSpin->setValue( lineSize );
+ mLayout.columnSizeSpin->setValue( colSize );
+}
+
+void COptionDialog::slotLineSizeChanged( int value )
+{
+ int index = mLayout.formatCombo->currentItem();
+ mDisplayState.line.setLineSize( index, value );
+ if( index == SDisplayLine::textOnly )
+ {
+ mLayout.columnSizeSpin->setValue( value );
+ }
+}
+
+void COptionDialog::slotColumnSizeChanged( int value )
+{
+ int index = mLayout.formatCombo->currentItem();
+ mDisplayState.line.setColumnSize( index, value );
+ if( index == SDisplayLine::textOnly )
+ {
+ mLayout.lineSizeSpin->setValue( value );
+ }
+}
+
+void COptionDialog::slotColumnSepCheck( bool state )
+{
+ state = state == true ? false: true;
+ mLayout.columnSepLabel->setEnabled( state );
+ mLayout.columnSepSpin->setEnabled( state );
+}
+
+
+void COptionDialog::slotBlinkIntervalCheck( bool state )
+{
+ state = state == true ? false : true;
+ mCursor.blinkSpin->setEnabled( state );
+ mCursor.blinkLabel->setEnabled( state );
+}
+
+void COptionDialog::slotBlockCursorCheck( bool state )
+{
+ state = state == true ? false : true;
+ mCursor.thickCheck->setEnabled( state );
+}
+
+void COptionDialog::slotFontSystem( bool state )
+{
+ mFont.chooser->setEnabled( state == true ? false : true );
+}
+
+void COptionDialog::slotColorSystem( bool state )
+{
+ state = state == true ? false : true;
+ mColor.colorList->setEnabled( state );
+}
+
+
+
+void COptionDialog::slotThresholdConfirm( void )
+{
+ bool state = mMisc.thresholdCheck->isChecked();
+ mMisc.thresholdLabel->setEnabled( state );
+ mMisc.thresholdSpin->setEnabled( state );
+}
+
+
+void COptionDialog::slotDefault( void )
+{
+ //
+ // We use the constructor settings as default values
+ //
+ switch( activePageIndex() )
+ {
+ case page_layout:
+ {
+ SDisplayLayout layout;
+ SDisplayLine line;
+ setLayout( layout, line );
+ }
+ break;
+
+ case page_cursor:
+ {
+ SDisplayCursor cursor;
+ setCursor( cursor );
+ }
+ break;
+
+ case page_color:
+ {
+ SDisplayColor color;
+ setColor( color );
+ }
+ break;
+
+ case page_font:
+ {
+ SDisplayFont font;
+ setFont( font );
+ }
+ break;
+
+ case page_file:
+ {
+ SDisplayMisc misc;
+ setFile( misc );
+ }
+ break;
+
+ case page_misc:
+ {
+ SDisplayMisc misc;
+ setMisc( misc );
+ }
+ break;
+ }
+}
+
+
+void COptionDialog::slotOk( void )
+{
+ if( configChanged )
+ slotApply();
+ accept();
+}
+
+void COptionDialog::slotApply( void )
+{
+ switch( activePageIndex() )
+ {
+ case page_layout:
+ {
+ int index = mLayout.formatCombo->currentItem();
+ mDisplayState.line.setLineSize(index, mLayout.lineSizeSpin->value());
+ mDisplayState.line.setColumnSize(index, mLayout.columnSizeSpin->value());
+ emit lineSizeChoice( mDisplayState.line );
+
+ SDisplayLayout &l = mDisplayState.layout;
+ l.lockLine = mLayout.lockLineCheck->isChecked();
+ l.lockColumn = mLayout.lockColumnCheck->isChecked();
+ l.leftSeparatorWidth = mLayout.leftSepWidthSpin->value();
+ l.rightSeparatorWidth = mLayout.rightSepWidthSpin->value();
+ l.separatorMarginWidth = mLayout.separatorSpin->value();
+ l.edgeMarginWidth = mLayout.edgeSpin->value();
+ l.leftSeparatorWidth = mLayout.leftSepWidthSpin->value();
+ l.rightSeparatorWidth = mLayout.rightSepWidthSpin->value();
+ l.columnCharSpace = mLayout.columnCheck->isChecked();
+ l.columnSpacing = mLayout.columnSepSpin->value();
+
+ if( mLayout.gridCombo->currentItem() == 0 )
+ {
+ l.horzGridWidth = l.vertGridWidth = 0;
+ }
+ else if( mLayout.gridCombo->currentItem() == 1 )
+ {
+ l.horzGridWidth = 0;
+ l.vertGridWidth = 1;
+ }
+ else if( mLayout.gridCombo->currentItem() == 2 )
+ {
+ l.horzGridWidth = 1;
+ l.vertGridWidth = 0;
+ }
+ else
+ {
+ l.horzGridWidth = l.vertGridWidth = 1;
+ }
+
+ emit layoutChoice( mDisplayState.layout );
+ }
+ break;
+
+
+ case page_cursor:
+ {
+ SDisplayCursor &c = mDisplayState.cursor;
+ c.alwaysVisible = mCursor.blinkCheck->isChecked();
+ c.interval = mCursor.blinkSpin->value();
+ c.alwaysBlockShape = mCursor.blockCheck->isChecked();
+ c.thickInsertShape = mCursor.thickCheck->isChecked();
+ c.focusMode = cursorFocusMode();
+ emit cursorChoice( mDisplayState.cursor );
+ }
+ break;
+
+ case page_color:
+ {
+ SDisplayColor &c = mDisplayState.color;
+ c.useSystemColor = mColor.checkSystem->isChecked();
+ c.textBg = mColor.colorList->color( SColorWidgets::FirstTextBg );
+ c.secondTextBg = mColor.colorList->color( SColorWidgets::SecondTextBg );
+ c.offsetBg = mColor.colorList->color( SColorWidgets::OffsetBg );
+ c.inactiveBg = mColor.colorList->color( SColorWidgets::InactiveBg );
+ c.markBg = mColor.colorList->color( SColorWidgets::MarkedBg );
+ c.markFg = mColor.colorList->color( SColorWidgets::MarkedFg );
+ c.primaryFg[0] = mColor.colorList->color( SColorWidgets::EvenColumnFg );
+ c.primaryFg[1] = mColor.colorList->color( SColorWidgets::OddColumnFg );
+ c.offsetFg = mColor.colorList->color( SColorWidgets::OffsetFg );
+ c.secondaryFg = mColor.colorList->color( SColorWidgets::SecondaryFg );
+ c.cursorBg = mColor.colorList->color( SColorWidgets::CursorBg );
+ c.cursorFg = mColor.colorList->color( SColorWidgets::CursorFg );
+ c.leftSeparatorFg = mColor.colorList->color(SColorWidgets::SeparatorFg);
+ c.rightSeparatorFg = mColor.colorList->color(SColorWidgets::SeparatorFg);
+ c.bookmarkBg = mColor.colorList->color( SColorWidgets::BookmarkBg );
+ c.bookmarkFg = mColor.colorList->color( SColorWidgets::BookmarkFg );
+ c.nonPrintFg = mColor.colorList->color( SColorWidgets::NonPrintFg );
+ c.gridFg = mColor.colorList->color( SColorWidgets::GridFg );
+ emit colorChoice( mDisplayState.color );
+ }
+ break;
+
+ case page_font:
+ {
+ SDisplayFont &f = mDisplayState.font;
+ f.useSystemFont = mFont.checkSystem->isChecked();
+ f.localFont = mFont.chooser->font();
+
+ QString nonPrintText = mFont.nonPrintInput->text();
+ if( nonPrintText.isEmpty() )
+ {
+ f.nonPrintChar = ' ';
+ }
+ else
+ {
+ f.nonPrintChar = nonPrintText[0];
+ }
+
+ emit fontChoice( mDisplayState.font );
+ }
+ break;
+
+ case page_file:
+ case page_misc:
+ {
+ SDisplayMisc &m = mDisplayState.misc;
+ m.undoLevel = mMisc.undoSpin->value();
+ m.autoCopyToClipboard = mMisc.autoCheck->isChecked();
+ m.insertMode = mMisc.insertCheck->isChecked();
+ m.inputSound = mMisc.inputCheck->isChecked();
+ m.confirmWrap = mMisc.confirmWrapCheck->isChecked();
+ m.cursorJump = mMisc.cursorJumpCheck->isChecked();
+ m.fatalSound = mMisc.fatalCheck->isChecked();
+ m.confirmThreshold = mMisc.thresholdCheck->isChecked();
+ m.thresholdValue = mMisc.thresholdSpin->value();
+ m.bookmarkOffsetColumn = mMisc.bookmarkColumnCheck->isChecked();
+ m.bookmarkEditor = mMisc.bookmarkEditorCheck->isChecked();
+
+ m.openFile = (SDisplayMisc::EOpenFile)mFile.openCombo->currentItem();
+ m.gotoOnStartup = mFile.gotoOffsetCheck->isChecked();
+ m.writeProtect = mFile.writeProtectCheck->isChecked();
+ m.gotoOnReload = mFile.reloadOffsetCheck->isChecked();
+ m.makeBackup = mFile.backupCheck->isChecked();
+ m.discardRecent = mFile.discardRecentCheck->isChecked();
+
+ emit miscChoice( mDisplayState.misc );
+ }
+ break;
+ }
+ enableButton( Apply, false );
+ configChanged = false;
+}
+
+void COptionDialog::setLayout( SDisplayLayout &layout, SDisplayLine &line )
+{
+ mDisplayState.line = line;
+ mDisplayState.layout = layout;
+
+ slotModeSelectorChanged( mLayout.formatCombo->currentItem() );
+ mLayout.lockLineCheck->setChecked( layout.lockLine );
+ mLayout.lockColumnCheck->setChecked( layout.lockColumn );
+ mLayout.leftSepWidthSpin->setValue( layout.leftSeparatorWidth );
+ mLayout.rightSepWidthSpin->setValue( layout.rightSeparatorWidth );
+ mLayout.separatorSpin->setValue( layout.separatorMarginWidth );
+ mLayout.edgeSpin->setValue( layout.edgeMarginWidth );
+ mLayout.leftSepWidthSpin->setValue( layout.leftSeparatorWidth );
+ mLayout.rightSepWidthSpin->setValue( layout.rightSeparatorWidth );
+ mLayout.columnCheck->setChecked( layout.columnCharSpace );
+ slotColumnSepCheck( layout.columnCharSpace );
+ mLayout.columnSepSpin->setValue( layout.columnSpacing );
+
+ if( layout.horzGridWidth == 0 && layout.vertGridWidth == 0 )
+ {
+ mLayout.gridCombo->setCurrentItem(0);
+ }
+ else if( layout.horzGridWidth != 0 && layout.vertGridWidth != 0 )
+ {
+ mLayout.gridCombo->setCurrentItem(3);
+ }
+ else
+ {
+ mLayout.gridCombo->setCurrentItem( layout.vertGridWidth != 0 ? 1 : 2 );
+ }
+
+}
+
+
+void COptionDialog::setCursor( SDisplayCursor &cursor )
+{
+ mDisplayState.cursor = cursor;
+
+ mCursor.blinkCheck->setChecked( cursor.alwaysVisible );
+ mCursor.blinkSpin->setValue( cursor.interval );
+ mCursor.blockCheck->setChecked( cursor.alwaysBlockShape );
+ mCursor.thickCheck->setChecked( cursor.thickInsertShape );
+ bool state = cursor.focusMode == SDisplayCursor::stopBlinking ? true : false;
+ mCursor.stopRadio->setChecked( state );
+ state = cursor.focusMode == SDisplayCursor::hide ? true : false;
+ mCursor.hideRadio->setChecked( state );
+ state = cursor.focusMode == SDisplayCursor::ignore ? true : false;
+ mCursor.nothingRadio->setChecked( state );
+}
+
+
+void COptionDialog::setColor( SDisplayColor &color )
+{
+ mDisplayState.color = color;
+
+ mColor.checkSystem->setChecked( color.useSystemColor );
+ mColor.colorList->setColor( SColorWidgets::FirstTextBg, color.textBg );
+ mColor.colorList->setColor( SColorWidgets::SecondTextBg, color.secondTextBg);
+ mColor.colorList->setColor( SColorWidgets::OffsetBg, color.offsetBg );
+ mColor.colorList->setColor( SColorWidgets::InactiveBg, color.inactiveBg );
+ mColor.colorList->setColor( SColorWidgets::MarkedBg, color.markBg );
+ mColor.colorList->setColor( SColorWidgets::MarkedFg, color.markFg );
+ mColor.colorList->setColor( SColorWidgets::EvenColumnFg, color.primaryFg[0]);
+ mColor.colorList->setColor( SColorWidgets::OddColumnFg, color.primaryFg[1] );
+ mColor.colorList->setColor( SColorWidgets::OffsetFg, color.offsetFg );
+ mColor.colorList->setColor( SColorWidgets::SecondaryFg, color.secondaryFg );
+ mColor.colorList->setColor( SColorWidgets::CursorBg, color.cursorBg );
+ mColor.colorList->setColor( SColorWidgets::CursorFg, color.cursorFg );
+ mColor.colorList->setColor(SColorWidgets::SeparatorFg,color.leftSeparatorFg);
+ mColor.colorList->setColor( SColorWidgets::BookmarkBg, color.bookmarkBg );
+ mColor.colorList->setColor( SColorWidgets::BookmarkFg, color.bookmarkFg );
+ mColor.colorList->setColor( SColorWidgets::NonPrintFg, color.nonPrintFg );
+ mColor.colorList->setColor( SColorWidgets::GridFg, color.gridFg );
+}
+
+
+void COptionDialog::setFont( SDisplayFont &font )
+{
+ mDisplayState.font = font;
+
+ mFont.checkSystem->setChecked( font.useSystemFont );
+ mFont.chooser->setFont( font.localFont, true );
+ QString buf = font.nonPrintChar;
+ mFont.nonPrintInput->setText( buf );
+}
+
+
+void COptionDialog::setMisc( SDisplayMisc &misc )
+{
+ mDisplayState.misc.undoLevel = misc.undoLevel;
+ mDisplayState.misc.inputSound = misc.inputSound;
+ mDisplayState.misc.fatalSound = misc.fatalSound;
+ mDisplayState.misc.autoCopyToClipboard = misc.autoCopyToClipboard;
+ mDisplayState.misc.insertMode = misc.insertMode;
+ mDisplayState.misc.confirmWrap = misc.confirmWrap;
+ mDisplayState.misc.cursorJump = misc.cursorJump;
+ mDisplayState.misc.confirmThreshold = misc.confirmThreshold;
+ mDisplayState.misc.thresholdValue = misc.thresholdValue;
+ mDisplayState.misc.bookmarkOffsetColumn = misc.bookmarkOffsetColumn;
+ mDisplayState.misc.bookmarkEditor = misc.bookmarkEditor;
+
+ mMisc.autoCheck->setChecked( misc.autoCopyToClipboard );
+ mMisc.insertCheck->setChecked( misc.insertMode );
+ mMisc.confirmWrapCheck->setChecked( misc.confirmWrap );
+ mMisc.cursorJumpCheck->setChecked( misc.cursorJump );
+
+ mMisc.inputCheck->setChecked( misc.inputSound );
+ mMisc.fatalCheck->setChecked( misc.fatalSound );
+ mMisc.bookmarkColumnCheck->setChecked( misc.bookmarkOffsetColumn );
+ mMisc.bookmarkEditorCheck->setChecked( misc.bookmarkEditor );
+
+ mMisc.thresholdCheck->setChecked( misc.confirmThreshold );
+ mMisc.thresholdSpin->setValue( misc.thresholdValue );
+ slotThresholdConfirm();
+
+ mMisc.undoSpin->setValue( misc.undoLevel );
+}
+
+void COptionDialog::setFile( SDisplayMisc &misc )
+{
+ mDisplayState.misc.openFile = misc.openFile;
+ mDisplayState.misc.gotoOnStartup = misc.gotoOnStartup;
+ mDisplayState.misc.writeProtect = misc.writeProtect;
+ mDisplayState.misc.gotoOnReload = misc.gotoOnReload;
+ mDisplayState.misc.discardRecent = misc.discardRecent;
+ mDisplayState.misc.makeBackup = misc.makeBackup;
+
+ mFile.openCombo->setCurrentItem( (uint)misc.openFile );
+ mFile.gotoOffsetCheck->setChecked( misc.gotoOnStartup );
+ mFile.writeProtectCheck->setChecked( misc.writeProtect );
+ mFile.reloadOffsetCheck->setChecked( misc.gotoOnReload );
+ mFile.discardRecentCheck->setChecked( misc.discardRecent );
+ mFile.backupCheck->setChecked( misc.makeBackup );
+}
+
+
+void COptionDialog::setState( SDisplayState &state )
+{
+ setLayout( state.layout, state.line );
+ setCursor( state.cursor );
+ setColor( state.color );
+ setFont( state.font );
+ setFile( state.misc );
+ setMisc( state.misc );
+ enableButton( Apply, false );
+ configChanged = false;
+}
+
+
+SDisplayCursor::EFocusMode COptionDialog::cursorFocusMode( void )
+{
+ if( mCursor.stopRadio->isChecked() == true )
+ {
+ return( SDisplayCursor::stopBlinking );
+ }
+ else if( mCursor.hideRadio->isChecked() == true )
+ {
+ return( SDisplayCursor::hide );
+ }
+ else
+ {
+ return( SDisplayCursor::ignore );
+ }
+}
+
+
+
+CColorListBox::CColorListBox( QWidget *parent, const char *name, WFlags f )
+ :KListBox( parent, name, f ), mCurrentOnDragEnter(-1)
+{
+ connect( this, SIGNAL(selected(int)), this, SLOT(newColor(int)) );
+ setAcceptDrops( true);
+}
+
+
+void CColorListBox::setEnabled( bool state )
+{
+ if( state == isEnabled() )
+ {
+ return;
+ }
+
+ QListBox::setEnabled( state );
+ for( uint i=0; i<count(); i++ )
+ {
+ updateItem( i );
+ }
+}
+
+
+void CColorListBox::setColor( uint index, const QColor &color )
+{
+ if( index < count() )
+ {
+ CColorListItem *colorItem = (CColorListItem*)item(index);
+ colorItem->setColor(color);
+ updateItem( colorItem );
+ }
+}
+
+
+const QColor CColorListBox::color( uint index )
+{
+ if( index < count() )
+ {
+ CColorListItem *colorItem = (CColorListItem*)item(index);
+ return( colorItem->color() );
+ }
+ else
+ {
+ return( black );
+ }
+}
+
+
+void CColorListBox::newColor( int index )
+{
+ if( isEnabled() == false )
+ {
+ return;
+ }
+
+ if( (uint)index < count() )
+ {
+ QColor c = color( index );
+ if( KColorDialog::getColor( c, this ) != QDialog::Rejected )
+ {
+ setColor( index, c );
+ emit dataChanged();
+ }
+ }
+}
+
+
+void CColorListBox::dragEnterEvent( QDragEnterEvent *e )
+{
+ if( KColorDrag::canDecode(e) && isEnabled() )
+ {
+ mCurrentOnDragEnter = currentItem();
+ e->accept( true );
+ }
+ else
+ {
+ mCurrentOnDragEnter = -1;
+ e->accept( false );
+ }
+}
+
+
+void CColorListBox::dragLeaveEvent( QDragLeaveEvent * )
+{
+ if( mCurrentOnDragEnter != -1 )
+ {
+ setCurrentItem( mCurrentOnDragEnter );
+ mCurrentOnDragEnter = -1;
+ }
+}
+
+
+void CColorListBox::dragMoveEvent( QDragMoveEvent *e )
+{
+ if( KColorDrag::canDecode(e) && isEnabled() )
+ {
+ CColorListItem *item = (CColorListItem*)itemAt( e->pos() );
+ if( item != 0 )
+ {
+ setCurrentItem ( item );
+ }
+ }
+}
+
+
+void CColorListBox::dropEvent( QDropEvent *e )
+{
+ QColor color;
+ if( KColorDrag::decode( e, color ) )
+ {
+ int index = currentItem();
+ if( index != -1 )
+ {
+ CColorListItem *colorItem = (CColorListItem*)item(index);
+ colorItem->setColor(color);
+ triggerUpdate( false ); // Redraw item
+ }
+ mCurrentOnDragEnter = -1;
+ }
+}
+
+
+
+CColorListItem::CColorListItem( const QString &text, const QColor &color )
+ : QListBoxItem(), mColor( color ), mBoxWidth( 30 )
+{
+ setText( text );
+}
+
+
+const QColor &CColorListItem::color( void )
+{
+ return( mColor );
+}
+
+
+void CColorListItem::setColor( const QColor &color )
+{
+ mColor = color;
+}
+
+
+void CColorListItem::paint( QPainter *p )
+{
+ QFontMetrics fm = p->fontMetrics();
+ int h = fm.height();
+
+ p->drawText( mBoxWidth+3*2, fm.ascent() + fm.leading()/2, text() );
+
+ p->setPen( Qt::black );
+ p->drawRect( 3, 1, mBoxWidth, h-1 );
+ p->fillRect( 4, 2, mBoxWidth-2, h-3, mColor );
+}
+
+
+int CColorListItem::height(const QListBox *lb ) const
+{
+ return( lb->fontMetrics().lineSpacing()+1 );
+}
+
+
+int CColorListItem::width(const QListBox *lb ) const
+{
+ return( mBoxWidth + lb->fontMetrics().width( text() ) + 6 );
+}
+
+
+
+
+
+
+#include "optiondialog.moc"
diff --git a/khexedit/optiondialog.h b/khexedit/optiondialog.h
new file mode 100644
index 0000000..ba62f62
--- /dev/null
+++ b/khexedit/optiondialog.h
@@ -0,0 +1,269 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _OPTION_DIALOG_H_
+#define _OPTION_DIALOG_H_
+
+
+class QComboBox;
+class QFrame;
+class QCheckBox;
+class QLabel;
+class QLineEdit;
+class QPushbutton;
+class QRadioButton;
+class QSpinBox;
+class QComboBox;
+class KFontChooser;
+
+
+#include <kdialogbase.h>
+#include <klistbox.h>
+#include "hexeditstate.h"
+
+
+
+class CColorListBox : public KListBox
+{
+ Q_OBJECT
+
+ public:
+ CColorListBox( QWidget *parent=0, const char * name=0, WFlags f=0 );
+ void setColor( uint index, const QColor &color );
+ const QColor color( uint index );
+
+ public slots:
+ virtual void setEnabled( bool state );
+
+ protected:
+ void dragEnterEvent( QDragEnterEvent *e );
+ void dragLeaveEvent( QDragLeaveEvent *e );
+ void dragMoveEvent( QDragMoveEvent *e );
+ void dropEvent( QDropEvent *e );
+
+ private slots:
+ void newColor( int index );
+
+ private:
+ int mCurrentOnDragEnter;
+
+ signals:
+ void dataChanged();
+};
+
+
+class CColorListItem : public QListBoxItem
+{
+ public:
+ CColorListItem( const QString &text, const QColor &color=Qt::black );
+ const QColor &color( void );
+ void setColor( const QColor &color );
+
+ protected:
+ virtual void paint( QPainter * );
+ virtual int height( const QListBox * ) const;
+ virtual int width( const QListBox * ) const;
+
+ private:
+ QColor mColor;
+ int mBoxWidth;
+};
+
+
+
+
+class COptionDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ enum EPage
+ {
+ page_layout = 0,
+ page_cursor,
+ page_font,
+ page_color,
+ page_file,
+ page_misc,
+ page_max
+ };
+
+ COptionDialog( QWidget *parent = 0, char *name = 0, bool modal = false );
+ ~COptionDialog( void );
+
+ void setLayout( SDisplayLayout &layout, SDisplayLine &line );
+ void setCursor( SDisplayCursor &cursor );
+ void setColor( SDisplayColor &color );
+ void setFont( SDisplayFont &font );
+ void setFile( SDisplayMisc &misc );
+ void setMisc( SDisplayMisc &misc );
+ void setState( SDisplayState &state );
+
+ protected:
+ virtual void showEvent( QShowEvent *e );
+
+ protected slots:
+ void slotModeSelectorChanged( int index );
+ void slotLineSizeChanged( int value );
+ void slotColumnSizeChanged( int value );
+ void slotColumnSepCheck( bool state );
+ void slotBlinkIntervalCheck( bool state );
+ void slotBlockCursorCheck( bool state );
+ void slotFontSystem( bool state );
+ void slotColorSystem( bool state );
+ void slotThresholdConfirm( void );
+
+ virtual void slotDefault( void );
+ virtual void slotOk( void );
+ virtual void slotApply( void );
+ void slotChanged();
+
+ private:
+ struct SLayoutWidgets
+ {
+ QComboBox *formatCombo;
+ QSpinBox *lineSizeSpin;
+ QSpinBox *columnSizeSpin;
+ QCheckBox *lockLineCheck;
+ QCheckBox *lockColumnCheck;
+ QCheckBox *columnCheck;
+ QComboBox *gridCombo;
+ QLabel *leftSepLabel;
+ QLabel *rightSepLabel;
+ QSpinBox *leftSepWidthSpin;
+ QSpinBox *rightSepWidthSpin;
+ QSpinBox *separatorSpin;
+ QSpinBox *edgeSpin;
+ QLabel *columnSepLabel;
+ QSpinBox *columnSepSpin;
+
+ };
+ struct SCursorWidgets
+ {
+ QCheckBox *blinkCheck;
+ QSpinBox *blinkSpin;
+ QLabel *blinkLabel;
+ QCheckBox *blockCheck;
+ QCheckBox *thickCheck;
+ QRadioButton *stopRadio;
+ QRadioButton *hideRadio;
+ QRadioButton *nothingRadio;
+ };
+ struct SColorWidgets
+ {
+ enum colorType
+ {
+ FirstTextBg = 0,
+ SecondTextBg,
+ OffsetBg,
+ InactiveBg,
+ EvenColumnFg,
+ OddColumnFg,
+ NonPrintFg,
+ OffsetFg,
+ SecondaryFg,
+ MarkedBg,
+ MarkedFg,
+ CursorBg,
+ CursorFg,
+ BookmarkBg,
+ BookmarkFg,
+ SeparatorFg,
+ GridFg,
+ MAX_COLOR
+ };
+
+ QCheckBox *checkSystem;
+ CColorListBox *colorList;
+ };
+ struct SFontWidgets
+ {
+ QCheckBox *checkSystem;
+ KFontChooser *chooser;
+ QLineEdit *nonPrintInput;
+ };
+ struct SFileWidgets
+ {
+ QComboBox *openCombo;
+ QCheckBox *gotoOffsetCheck;
+ QCheckBox *reloadOffsetCheck;
+ QCheckBox *writeProtectCheck;
+ QCheckBox *backupCheck;
+ QCheckBox *discardRecentCheck;
+ };
+ struct SMiscWidgets
+ {
+ QSpinBox *undoSpin;
+ QCheckBox *inputCheck;
+ QCheckBox *fatalCheck;
+ QCheckBox *autoCheck;
+ QCheckBox *insertCheck;
+ QCheckBox *confirmWrapCheck;
+ QCheckBox *cursorJumpCheck;
+ QCheckBox *thresholdCheck;
+ QCheckBox *bookmarkColumnCheck;
+ QCheckBox *bookmarkEditorCheck;
+ QLabel *thresholdLabel;
+ QSpinBox *thresholdSpin;
+ };
+
+ private:
+ void setupLayoutPage( void );
+ void setupCursorPage( void );
+ void setupColorPage( void );
+ void setupFontPage( void );
+ void setupFilePage( void );
+ void setupMiscPage( void );
+ SDisplayCursor::EFocusMode cursorFocusMode( void );
+
+
+ signals:
+ void lineSizeChoice( const SDisplayLine &lineSize );
+ void layoutChoice( const SDisplayLayout &layout );
+ void cursorChoice( const SDisplayCursor &cursor );
+ void colorChoice( const SDisplayColor &color );
+ void fontChoice( const SDisplayFont &font );
+ void miscChoice( const SDisplayMisc &misc );
+ void removeRecentFiles( void );
+
+ private:
+ SDisplayState mDisplayState;
+ SLayoutWidgets mLayout;
+ SCursorWidgets mCursor;
+ SColorWidgets mColor;
+ SFontWidgets mFont;
+ SFileWidgets mFile;
+ SMiscWidgets mMisc;
+ bool configChanged;
+
+};
+
+
+
+
+
+#endif
+
+
+
+
+
+
+
diff --git a/khexedit/parts/Makefile.am b/khexedit/parts/Makefile.am
new file mode 100644
index 0000000..7e2726b
--- /dev/null
+++ b/khexedit/parts/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = kbytesedit kpart
diff --git a/khexedit/parts/README b/khexedit/parts/README
new file mode 100644
index 0000000..a484f1e
--- /dev/null
+++ b/khexedit/parts/README
@@ -0,0 +1,3 @@
+hex editor parts
+==================
+in each subdirectory one part based on the KHexEdit2 library
diff --git a/khexedit/parts/kbytesedit/Makefile.am b/khexedit/parts/kbytesedit/Makefile.am
new file mode 100644
index 0000000..b8be127
--- /dev/null
+++ b/khexedit/parts/kbytesedit/Makefile.am
@@ -0,0 +1,15 @@
+kde_module_LTLIBRARIES = libkbyteseditwidget.la
+
+INCLUDES = -I$(srcdir)/../../lib $(all_includes)
+
+noinst_HEADERS = kbyteseditwidget.h
+
+METASOURCES = AUTO
+
+libkbyteseditwidget_la_SOURCES = kbyteseditwidget.cpp
+
+libkbyteseditwidget_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module -avoid-version -no-undefined
+libkbyteseditwidget_la_LIBADD = ../../lib/libkhexeditcommon.la $(LIB_KPARTS)
+
+service_DATA = kbyteseditwidget.desktop
+servicedir = $(kde_servicesdir)
diff --git a/khexedit/parts/kbytesedit/README b/khexedit/parts/kbytesedit/README
new file mode 100644
index 0000000..e3aa164
--- /dev/null
+++ b/khexedit/parts/kbytesedit/README
@@ -0,0 +1,23 @@
+KBytesEdit widget modul
+=======================
+part of the KHexEdit 2 project (kdenonbeta/khexedit2)
+Author/Maintainer: Friedrich W. H. Kossebau <Friedrich.W.H@Kossebau.de>
+
+
+description:
+------------
+This module delivers a service for the service type "KHexEdit/KBytesEdit".
+It is a hex edit widget that operates on an array of chars given by
+the programmer.
+It serves right now the interfaces
+HexColumnInterface, TextColumnInterface, ZoomInterface, ClipBoardInterface.
+
+
+installing:
+-----------
+Installs the .desktop file describing the service and the module library.
+
+
+usage:
+------
+Only official known usage is by KPilot (kdepim/kpilot) for now. \ No newline at end of file
diff --git a/khexedit/parts/kbytesedit/kbyteseditwidget.cpp b/khexedit/parts/kbytesedit/kbyteseditwidget.cpp
new file mode 100644
index 0000000..4cc91ab
--- /dev/null
+++ b/khexedit/parts/kbytesedit/kbyteseditwidget.cpp
@@ -0,0 +1,319 @@
+/***************************************************************************
+ kbyteseditwidget.cpp - description
+ -------------------
+ begin : Fri Aug 29 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// qt specific
+#include <qlayout.h>
+// kde specific
+#include <klocale.h>
+#include <kgenericfactory.h>
+#include <kapplication.h>
+// lib specific
+#include "kbytesedit.h"
+#include "kbyteseditwidget.h"
+
+
+KBytesEditWidget::KBytesEditWidget( QWidget *parent, const char *name, const QStringList & )
+ : QWidget( parent, name)
+{
+ QHBoxLayout* Layout = new QHBoxLayout( this );
+ BytesEdit = new KHE::KBytesEdit( this, "BytesEdit" );
+ Layout->addWidget( BytesEdit );
+// connect( _editor, SIGNAL( canUndo(bool) ), this, SIGNAL( canUndo(bool) ) );
+ connect( BytesEdit, SIGNAL(copyAvailable( bool )), this, SIGNAL(copyAvailable( bool )) );
+}
+
+
+
+void KBytesEditWidget::setData( char *D, int S, int RS, bool KM )
+{
+ BytesEdit->setData( D, S, RS, KM );
+}
+
+
+void KBytesEditWidget::setReadOnly( bool RO )
+{
+ BytesEdit->setReadOnly( RO );
+}
+
+void KBytesEditWidget::setMaxDataSize( int MS )
+{
+ BytesEdit->setMaxDataSize( MS );
+}
+
+void KBytesEditWidget::setAutoDelete( bool AD )
+{
+ BytesEdit->setAutoDelete( AD );
+}
+
+
+void KBytesEditWidget::setKeepsMemory( bool KM )
+{
+ BytesEdit->setKeepsMemory( KM );
+}
+
+
+void KBytesEditWidget::setCursorPosition( int Index )
+{
+ BytesEdit->setCursorPosition( Index );
+}
+
+void KBytesEditWidget::setCoding( KCoding C )
+{
+ BytesEdit->setCoding( (KHE::KHexEdit::KCoding) C );
+}
+
+void KBytesEditWidget::setResizeStyle( KResizeStyle Style )
+{
+ BytesEdit->setResizeStyle( (KHE::KHexEdit::KResizeStyle) Style );
+}
+int KBytesEditWidget::noOfBytesPerLine() const
+{
+ return BytesEdit->noOfBytesPerLine();
+}
+
+KBytesEditWidget::KResizeStyle KBytesEditWidget::resizeStyle() const
+{
+ return (KResizeStyle)BytesEdit->resizeStyle();
+}
+void KBytesEditWidget::setNoOfBytesPerLine( int NoCpL )
+{
+ BytesEdit->setNoOfBytesPerLine( NoCpL );
+}
+
+
+
+void KBytesEditWidget::setOverwriteOnly( bool b )
+{
+ BytesEdit->setOverwriteOnly( b );
+}
+
+
+void KBytesEditWidget::setOverwriteMode( bool b )
+{
+ BytesEdit->setOverwriteMode( b );
+}
+
+
+void KBytesEditWidget::setModified( bool b )
+{
+ BytesEdit->setModified( b );
+}
+
+
+void KBytesEditWidget::setByteSpacingWidth( int BSW )
+{
+ BytesEdit->setByteSpacingWidth( BSW );
+}
+
+void KBytesEditWidget::setNoOfGroupedBytes( int NoGB )
+{
+ BytesEdit->setNoOfGroupedBytes( NoGB );
+}
+
+void KBytesEditWidget::setGroupSpacingWidth( int GSW )
+{
+ BytesEdit->setGroupSpacingWidth( GSW );
+}
+
+void KBytesEditWidget::setBinaryGapWidth( int BGW )
+{
+ BytesEdit->setBinaryGapWidth( BGW );
+}
+
+void KBytesEditWidget::setEncoding( KEncoding C )
+{
+ BytesEdit->setEncoding( (KHE::KHexEdit::KEncoding)C );
+}
+
+void KBytesEditWidget::setShowUnprintable( bool SU )
+{
+ BytesEdit->setShowUnprintable( SU );
+}
+
+void KBytesEditWidget::setSubstituteChar( QChar SC )
+{
+ BytesEdit->setSubstituteChar( SC );
+}
+
+
+char *KBytesEditWidget::data() const
+{
+ return BytesEdit->data();
+}
+
+int KBytesEditWidget::dataSize() const
+{
+ return BytesEdit->dataSize();
+}
+int KBytesEditWidget::maxDataSize () const
+{
+ return BytesEdit->maxDataSize();
+}
+bool KBytesEditWidget::isAutoDelete() const
+{
+ return BytesEdit->isAutoDelete();
+}
+
+bool KBytesEditWidget::keepsMemory() const
+{
+ return BytesEdit->keepsMemory();
+}
+
+bool KBytesEditWidget::isOverwriteMode() const
+{
+ return BytesEdit->isOverwriteMode();
+}
+
+bool KBytesEditWidget::isOverwriteOnly() const
+{
+ return BytesEdit->isOverwriteOnly();
+}
+
+bool KBytesEditWidget::isModified() const
+{
+ return BytesEdit->isModified();
+}
+
+bool KBytesEditWidget::isReadOnly() const
+{
+ return BytesEdit->isReadOnly();
+}
+
+
+// bool KBytesEditWidget::tabChangesFocus() const
+// {
+// }
+
+
+
+KBytesEditWidget::KCoding KBytesEditWidget::coding() const
+{
+ return (KCoding)BytesEdit->coding();
+}
+
+int KBytesEditWidget::byteSpacingWidth() const
+{
+ return BytesEdit->byteSpacingWidth();
+}
+
+int KBytesEditWidget::noOfGroupedBytes() const
+{
+ return BytesEdit->noOfGroupedBytes();
+}
+
+int KBytesEditWidget::groupSpacingWidth() const
+{
+ return BytesEdit->groupSpacingWidth();
+}
+
+int KBytesEditWidget::binaryGapWidth() const
+{
+ return BytesEdit->binaryGapWidth();
+}
+
+bool KBytesEditWidget::showUnprintable() const
+{
+ return BytesEdit->showUnprintable();
+}
+
+QChar KBytesEditWidget::substituteChar() const
+{
+ return BytesEdit->substituteChar();
+}
+
+KBytesEditWidget::KEncoding KBytesEditWidget::encoding() const
+{
+ return (KEncoding)BytesEdit->encoding();
+}
+
+
+bool KBytesEditWidget::hasSelectedData() const
+{
+ return BytesEdit->hasSelectedData();
+}
+
+
+void KBytesEditWidget::repaintRange( int i1, int i2 )
+{
+ BytesEdit->repaintRange( i1, i2 );
+}
+
+
+void KBytesEditWidget::insert( const QByteArray &D )
+{
+ BytesEdit->insert( D );
+}
+
+
+void KBytesEditWidget::selectAll( bool Select )
+{
+ BytesEdit->selectAll( Select );
+}
+
+ // clipboard interface
+void KBytesEditWidget::copy()
+{
+ BytesEdit->copy();
+}
+
+void KBytesEditWidget::cut()
+{
+ BytesEdit->cut();
+}
+
+void KBytesEditWidget::paste()
+{
+ BytesEdit->paste();
+}
+
+// zooming interface
+void KBytesEditWidget::zoomIn( int PointInc )
+{
+ BytesEdit->zoomIn( PointInc );
+}
+
+void KBytesEditWidget::zoomIn()
+{
+ BytesEdit->zoomIn();
+}
+
+void KBytesEditWidget::zoomOut( int PointDec )
+{
+ BytesEdit->zoomOut( PointDec );
+}
+
+void KBytesEditWidget::zoomOut()
+{
+ BytesEdit->zoomOut();
+}
+
+void KBytesEditWidget::zoomTo( int PointSize )
+{
+ BytesEdit->zoomTo( PointSize );
+}
+
+void KBytesEditWidget::unZoom()
+{
+ BytesEdit->unZoom();
+}
+
+
+typedef K_TYPELIST_1( KBytesEditWidget ) Product;
+K_EXPORT_COMPONENT_FACTORY( libkbyteseditwidget, KGenericFactory<Product>( "kbytesedit" ) )
+//K_EXPORT_COMPONENT_FACTORY( libkbyteseditwidget, KGenericFactory<MyPlugin> )
+
+#include "kbyteseditwidget.moc"
diff --git a/khexedit/parts/kbytesedit/kbyteseditwidget.desktop b/khexedit/parts/kbytesedit/kbyteseditwidget.desktop
new file mode 100644
index 0000000..4a050a6
--- /dev/null
+++ b/khexedit/parts/kbytesedit/kbyteseditwidget.desktop
@@ -0,0 +1,52 @@
+[Desktop Entry]
+Type=Service
+Name=BytesEdit Widget
+Name[ar]=كائن BytesEdit
+Name[bg]=Модул за двоично редактиране на файлове
+Name[bs]=BytesEdit grafiÄki element
+Name[ca]=Estri BytesEdit
+Name[cy]=Celfigyn GolyguBeit
+Name[de]=BytesEdit-Bedienelement
+Name[el]=ΓÏαφικό συστατικό BytesEdit
+Name[eo]=BytesEdit-fenestraĵo
+Name[es]=Ventana de edición de bytes
+Name[et]=Baitide redigeerimise komponent
+Name[eu]=Byteak Editatzeko Widget-a
+Name[fa]=عنصر ویرایش بایت
+Name[fi]=BytesEdit käyttöliittymäkomponentti
+Name[fr]=Composant éditeur binaire
+Name[ga]=Giuirléid BytesEdit
+Name[he]=פריט עורך ×”×‘×™×˜×•×™×™× ×”×¡×“×™×¨×™×
+Name[hi]=बाइटà¥à¤¸-à¤à¤¡à¤¿à¤Ÿ विजेट
+Name[hu]=BytesEdit grafikus elem
+Name[is]=Græja til að sýsla með bætaskrár
+Name[it]=Elemento grafico editor di byte
+Name[ja]=ãƒã‚¤ãƒˆã‚¨ãƒ‡ã‚£ãƒƒãƒˆã‚¦ã‚£ã‚¸ã‚§ãƒƒãƒˆ
+Name[kk]=Бинарлы деректерді өңдеу бөлшегі
+Name[km]=ážœážáŸ’ážáž»áž˜áž¾áž›ážƒáž¾áž‰ BytesEdit
+Name[lt]=BytesEdit valdiklis
+Name[mk]=BytesEdit - графичка контрола
+Name[nb]=BytesEdit skjermelement
+Name[nds]=BytesEdit-Bedeenelement
+Name[ne]=बाइट समà¥à¤ªà¤¾à¤¦à¤¨ विजेट
+Name[nn]=BytesEdit-skjermelement
+Name[pa]=ਬਾਈਟ ਸੋਧ ਸਹਾਇਕ
+Name[pl]=Okienko BytesEdit
+Name[pt]=Editor de Bytes
+Name[pt_BR]=Widget do Editor de Bytes
+Name[ro]=Componentă de editare octeţi
+Name[ru]=Виджет Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð´Ð²Ð¾Ð¸Ñ‡Ð½Ñ‹Ñ… данных
+Name[sk]=Prvok BytesEdit
+Name[sl]=Gradnik BytesEdit
+Name[sr]=Контрола за бинарно уређивање
+Name[sr@Latn]=Kontrola za binarno uređivanje
+Name[sv]=Grafisk komponent för att redigera binärdata
+Name[ta]= பைடà¯à®¸à¯à®¤à¯Šà®•à¯à®ªà¯à®ªà¯ சாளரமà¯
+Name[tg]=Элементи Таҳрири Додаҳои Дуӣ
+Name[uk]=Віджет побайтового редагуваннÑ
+Name[zh_CN]=字节编辑部件
+Name[zh_TW]=ä½å…ƒç·¨è¼¯å™¨å…ƒä»¶
+X-KDE-Library=libkbyteseditwidget
+InitialPreference=2
+ServiceTypes=KHexEdit/KBytesEdit
+
diff --git a/khexedit/parts/kbytesedit/kbyteseditwidget.h b/khexedit/parts/kbytesedit/kbyteseditwidget.h
new file mode 100644
index 0000000..78e4dba
--- /dev/null
+++ b/khexedit/parts/kbytesedit/kbyteseditwidget.h
@@ -0,0 +1,185 @@
+/***************************************************************************
+ kbyteseditwidget.h - description
+ -------------------
+ begin : Fri Aug 29 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KBYTESEDITWIDGET_H
+#define KBYTESEDITWIDGET_H
+
+// qt specific
+#include <qwidget.h>
+// kde specific
+#include <khexedit/byteseditinterface.h>
+#include <khexedit/valuecolumninterface.h>
+#include <khexedit/charcolumninterface.h>
+#include <khexedit/zoominterface.h>
+#include <khexedit/clipboardinterface.h>
+
+
+namespace KHE {
+class KBytesEdit;
+}
+
+/**
+ hex editor/viewer.
+
+ @author Friedrich W. H. Kossebau <Friedrich.W.H@Kossebau.de>
+ @version 0.1
+ **/
+class KBytesEditWidget : public QWidget, public KHE::BytesEditInterface,
+ public KHE::ValueColumnInterface, public KHE::CharColumnInterface,
+ public KHE::ZoomInterface, public KHE::ClipboardInterface
+{
+ Q_OBJECT
+
+ public:
+ /** constructor API as demanded by KGenericFactory */
+ KBytesEditWidget( QWidget *parent, const char *name, const QStringList & = QStringList() );
+
+ public: // bytesedit interface
+ /** hands over to the editor a new byte array.
+ * If there exists an old one and autodelete is set the old one gets deleted.
+ * @param D pointer to memory
+ * @param DS_ size of used memory
+ * @param RS_ real size of the memory
+ * @param KM keep the memory on resize (RS_ is the maximum size)
+ */
+ virtual void setData( char *D, int DS_, int RS_ = -1, bool KM = true );
+
+ /** sets the maximal size of the actual byte array. If the actual array is already larger
+ * it will not be modified but there can be only done non-inserting actions
+ * until the array's is below the limit
+ */
+ virtual void setMaxDataSize( int MS );
+ /** sets whether the array should be deleted on the widget's end or if a new array is set.
+ * Default is false
+ */
+ virtual void setAutoDelete( bool AD = true );
+ /** sets whether the memory given by setData or in the constructor should be kept on resize
+ */
+ virtual void setKeepsMemory( bool KM = true );
+ /** */
+ virtual char *data() const;
+ /** returns the size of the actual byte array */
+ virtual int dataSize() const;
+ /** returns the maximal allowed size for the byte array */
+ virtual int maxDataSize () const;
+ /** returns whether autodelete is set for the byte array */
+ virtual bool isAutoDelete() const;
+ /** returns whether the memory of the byte array is kept */
+ virtual bool keepsMemory() const;
+ /** */
+ virtual bool isOverwriteMode() const;
+ virtual bool isOverwriteOnly() const;
+ virtual bool isReadOnly() const;
+ virtual bool isModified() const;
+ /** repaint the indizes from i1 to i2 */
+ virtual void repaintRange( int i1, int i2 );
+
+ public: // cursor interface
+ /** */
+ virtual void setCursorPosition( int Index );
+// virtual bool tabChangesFocus() const;
+
+ public: // layout interface ??
+ /** sets the resizestyle for the value column. Default is KHE::FullSizeUsage */
+ virtual void setResizeStyle( KResizeStyle Style );
+ /** sets the number of bytes per line, switching the resize style to KHE::NoResize */
+ virtual void setNoOfBytesPerLine( int NoCpL );
+
+ virtual int noOfBytesPerLine() const;
+ virtual KResizeStyle resizeStyle() const;
+
+ public: // value column
+ /** sets the format of the value column. Default is KHE::HexadecimalCoding */
+ virtual void setCoding( KCoding C );
+ /** sets the spacing between the bytes in pixels */
+ virtual void setByteSpacingWidth( int BSW );
+ /** sets the numbers of grouped bytes, 0 means no grouping, Default is 4 */
+ virtual void setNoOfGroupedBytes( int NoGB );
+ /** sets the spacing between the groups in pixels */
+ virtual void setGroupSpacingWidth( int GSW );
+ /** sets the spacing in the middle of a binary byte in the value column
+ * @param BGW spacing in the middle of a binary in pixels
+ */
+ virtual void setBinaryGapWidth( int BGW );
+
+ virtual KCoding coding() const;
+ virtual int byteSpacingWidth() const;
+
+ virtual int noOfGroupedBytes() const;
+ virtual int groupSpacingWidth() const;
+ virtual int binaryGapWidth() const;
+
+ public: // char column
+ /** sets whether "unprintable" chars (>32) should be displayed in the char column
+ * with their corresponding character.
+ * @param SU
+ * returns true if there was a change
+ */
+ virtual void setShowUnprintable( bool SU = true );
+ /** sets the substitute character for "unprintable" chars
+ * returns true if there was a change
+ */
+ virtual void setSubstituteChar( QChar SC );
+ /** sets the encoding of the char column. Default is KHE::LocalEncoding.
+ * If the encoding is not available the format will not be changed. */
+ virtual void setEncoding( KEncoding C );
+ /** returns true if "unprintable" chars (>32) are displayed in the char column
+ * with their corresponding character, default is false
+ */
+ virtual bool showUnprintable() const;
+ /** returns the actually used substitute character for "unprintable" chars, default is '.' */
+ virtual QChar substituteChar() const;
+ /** */
+ virtual KEncoding encoding() const;
+
+ public: // edit interface
+ /** */
+ virtual void insert( const QByteArray &D );
+ /** de-/selects all data */
+ virtual void selectAll( bool select );
+ /** returns true if there is a selected range in the array */
+ virtual bool hasSelectedData() const;
+
+ public slots:
+ // bytesedit interface
+ virtual void setReadOnly( bool RO = true );
+ virtual void setOverwriteOnly( bool b );
+ virtual void setOverwriteMode( bool b );
+ virtual void setModified( bool b );
+
+ // clipboard interface
+ virtual void copy();
+ virtual void cut();
+ virtual void paste();
+
+ // zooming interface
+ virtual void zoomIn( int PointInc );
+ virtual void zoomIn();
+ virtual void zoomOut( int PointDec );
+ virtual void zoomOut();
+ virtual void zoomTo( int PointSize );
+ virtual void unZoom();
+
+ signals:
+ // clipboard interface
+ virtual void copyAvailable( bool Really );
+
+ protected:
+ KHE::KBytesEdit* BytesEdit;
+};
+
+#endif
diff --git a/khexedit/parts/kpart/Makefile.am b/khexedit/parts/kpart/Makefile.am
new file mode 100644
index 0000000..42d9c77
--- /dev/null
+++ b/khexedit/parts/kpart/Makefile.am
@@ -0,0 +1,21 @@
+kde_module_LTLIBRARIES = libkhexedit2part.la
+
+INCLUDES = -I$(srcdir)/../../lib $(all_includes)
+
+noinst_HEADERS = khepart.h khebrowserextension.h khepartfactory.h
+
+METASOURCES = AUTO
+
+libkhexedit2part_la_SOURCES = khepart.cpp khebrowserextension.cpp khepartfactory.cpp
+
+libkhexedit2part_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module -no-undefined
+libkhexedit2part_la_LIBADD = ../../lib/libkhexeditcommon.la $(LIB_KPARTS) $(LIB_KIO)
+
+partdesktop_DATA = khexedit2part.desktop
+partdesktopdir = $(kde_servicesdir)
+
+partrc_DATA = khexedit2partui.rc
+partrcdir = $(kde_datadir)/khexedit2part
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/khexedit2part.pot
diff --git a/khexedit/parts/kpart/khebrowserextension.cpp b/khexedit/parts/kpart/khebrowserextension.cpp
new file mode 100644
index 0000000..d4fc3f3
--- /dev/null
+++ b/khexedit/parts/kpart/khebrowserextension.cpp
@@ -0,0 +1,95 @@
+/***************************************************************************
+ khebrowserextension.cpp - description
+ -------------------
+ begin : Di Nov 16 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// qt specific
+#include <kaction.h>
+// app specific
+#include "khexedit.h"
+#include "khepart.h"
+#include "khebrowserextension.h"
+
+using namespace KHE;
+
+
+KHexEditBrowserExtension::KHexEditBrowserExtension( KHexEditPart *P )
+ : KParts::BrowserExtension( P, "khexeditpartbrowserextension" ),
+ HexEditPart( P )
+{
+ connect( HexEditPart->HexEdit, SIGNAL( selectionChanged() ), this, SLOT( slotSelectionChanged() ) );
+}
+
+void KHexEditBrowserExtension::copy()
+{
+ HexEditPart->HexEdit->copy();
+}
+
+
+void KHexEditBrowserExtension::slotSelectionChanged()
+{
+ emit enableAction( "copy", HexEditPart->HexEdit->hasSelectedData() );
+}
+
+
+void KHexEditBrowserExtension::saveState( QDataStream &stream )
+{
+ KParts::BrowserExtension::saveState( stream );
+
+ KHexEdit *HexEdit = HexEditPart->HexEdit;
+
+ stream << (int)HexEdit->offsetColumnVisible() << HexEdit->visibleBufferColumns()
+ << (int)HexEdit->resizeStyle() << (int)HexEdit->coding()
+ << HexEdit->encodingName() << (int)HexEdit->showUnprintable()
+ << HexEdit->contentsX() << HexEdit->contentsY()
+ << HexEdit->cursorPosition() << (int)HexEdit->isCursorBehind()
+ << HexEdit->cursorColumn();
+}
+
+
+void KHexEditBrowserExtension::restoreState( QDataStream &stream )
+{
+ KParts::BrowserExtension::restoreState( stream );
+
+ int OffsetColumnVisible;
+ int VisibleBufferColumns;
+ int ResizeStyle;
+ int Coding;
+ QString EncodingName;
+ int ShowUnprintable;
+ int x, y;
+ int Position;
+ int CursorBehind;
+ int CursorColumn;
+
+ stream >> OffsetColumnVisible >> VisibleBufferColumns >> ResizeStyle >> Coding >> EncodingName >> ShowUnprintable
+ >> x >> y >> Position >> CursorBehind >> CursorColumn;
+
+ KHexEdit *HexEdit = HexEditPart->HexEdit;
+
+ HexEdit->toggleOffsetColumn( OffsetColumnVisible );
+ HexEdit->showBufferColumns( VisibleBufferColumns );
+ HexEdit->setResizeStyle( (KHexEdit::KResizeStyle)ResizeStyle );
+ HexEdit->setCoding( (KHexEdit::KCoding)Coding );
+ HexEdit->setEncoding( EncodingName );
+ HexEdit->setShowUnprintable( ShowUnprintable );
+ HexEdit->setContentsPos( x, y );
+ HexEdit->setCursorPosition( Position, CursorBehind );
+ HexEdit->setCursorColumn( (KHexEdit::KBufferColumnId)CursorColumn );
+
+ HexEditPart->fitActionSettings();
+}
+
+#include "khebrowserextension.moc"
diff --git a/khexedit/parts/kpart/khebrowserextension.h b/khexedit/parts/kpart/khebrowserextension.h
new file mode 100644
index 0000000..4638944
--- /dev/null
+++ b/khexedit/parts/kpart/khebrowserextension.h
@@ -0,0 +1,58 @@
+/***************************************************************************
+ khebrowserextension.h - description
+ -------------------
+ begin : Di Nov 16 2004
+ copyright : (C) 2004 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHEBROWSEREXTENSION_H
+#define KHEBROWSEREXTENSION_H
+
+// kde specific
+#include <kparts/browserextension.h>
+
+namespace KHE
+{
+
+// forward declaration
+class KHexEditPart;
+
+/**
+ * @short Extension for better support for embedding in browsers
+ * @author Friedrich W. H. Kossebau <Friedrich.W.H@Kossebau.de>
+ */
+class KHexEditBrowserExtension : public KParts::BrowserExtension
+{
+ Q_OBJECT
+
+ public:
+ KHexEditBrowserExtension( KHexEditPart *P );
+
+ public: // KParts::BrowserExtension API
+ virtual void saveState( QDataStream &stream );
+ virtual void restoreState( QDataStream &stream );
+
+ public slots:
+ /** copy text to clipboard */
+ void copy();
+
+ /** selection has changed */
+ void slotSelectionChanged();
+
+ protected:
+ KHexEditPart *HexEditPart;
+};
+
+}
+
+#endif
diff --git a/khexedit/parts/kpart/khepart.cpp b/khexedit/parts/kpart/khepart.cpp
new file mode 100644
index 0000000..e9b9ed5
--- /dev/null
+++ b/khexedit/parts/kpart/khepart.cpp
@@ -0,0 +1,213 @@
+/***************************************************************************
+ khepart.cpp - description
+ -------------------
+ begin : Don Jun 19 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// kde specific
+#include <klocale.h>
+//#include <kinstance.h>
+#include <kaction.h>
+#include <kstdaction.h>
+//#include <kglobalsettings.h>
+// app specific
+#include "khexedit.h"
+#include "kcharcodec.h"
+#include "khepartfactory.h"
+#include "khebrowserextension.h"
+#include "khepart.h"
+
+using namespace KHE;
+
+static const char RCFileName[] = "khexedit2partui.rc";
+
+KHexEditPart::KHexEditPart( QWidget *ParentWidget, const char *WidgetName,
+ QObject *Parent, const char *Name,
+ bool BrowserViewWanted )
+ : KParts::ReadOnlyPart( Parent, Name )
+{
+ setInstance( KHexEditPartFactory::instance() );
+
+ HexEdit = new KHexEdit( &Wrapping, ParentWidget, WidgetName );
+ HexEdit->setNoOfBytesPerLine( 16 );
+ HexEdit->setBufferSpacing( 3, 4, 10 );
+ HexEdit->setShowUnprintable( false );
+
+ // notify the part that this is our internal widget
+ setWidget( HexEdit );
+
+ setupActions( BrowserViewWanted );
+
+ if( CopyAction )
+ {
+ connect( HexEdit, SIGNAL(copyAvailable(bool)), CopyAction,SLOT(setEnabled(bool)) );
+ connect( HexEdit, SIGNAL(selectionChanged()), this, SLOT(slotSelectionChanged()) );
+ CopyAction->setEnabled( false );
+ }
+
+ // plugin to browsers
+ if( BrowserViewWanted )
+ new KHexEditBrowserExtension( this );
+}
+
+
+KHexEditPart::~KHexEditPart()
+{
+}
+
+/*
+void KHexEditPart::setupTools( bool BrowserViewWanted )
+{
+ if( !BrowserViewWanted ) new KClipboardTool( this );
+
+ new KZoomToolet( this );
+ new KSelectToolet( this );
+ new KHEValueCodingToolet( this );
+ new KHECharEncodingToolet( this );
+ new KHEResizeStyleToolet( this );
+ new KHEColumnToggleToolet( this );
+}
+*/
+void KHexEditPart::setupActions( bool BrowserViewWanted )
+{
+ KActionCollection *AC = actionCollection();
+ // create our actions
+ CopyAction = BrowserViewWanted ? 0 : KStdAction::copy( HexEdit, SLOT(copy()), AC );
+
+ KStdAction::selectAll( this, SLOT(slotSelectAll()), AC );
+ KStdAction::deselect( this, SLOT(slotUnselect()), AC );
+
+ // value encoding
+ CodingAction = new KSelectAction( i18n("&Value Coding"), 0, AC, "view_valuecoding" );
+ QStringList List;
+ List.append( i18n("&Hexadecimal") );
+ List.append( i18n("&Decimal") );
+ List.append( i18n("&Octal") );
+ List.append( i18n("&Binary") );
+ CodingAction->setItems( List );
+ connect( CodingAction, SIGNAL(activated(int)), this, SLOT(slotSetCoding(int)) );
+
+ // document encoding
+ EncodingAction = new KSelectAction( i18n("&Char Encoding"), 0, AC, "view_charencoding" );
+ EncodingAction->setItems( KCharCodec::codecNames() );
+ connect( EncodingAction, SIGNAL(activated(int)), this, SLOT(slotSetEncoding(int)) );
+
+ ShowUnprintableAction = new KToggleAction( i18n("Show &Unprintable Chars (<32)"), 0, this, SLOT(slotSetShowUnprintable()), actionCollection(), "view_showunprintable" );
+
+ KStdAction::zoomIn( HexEdit, SLOT(zoomIn()), actionCollection() );
+ KStdAction::zoomOut( HexEdit, SLOT(zoomOut()), actionCollection() );
+
+ // resize style
+ ResizeStyleAction = new KSelectAction( i18n("&Resize Style"), 0, AC, "resizestyle" );
+ List.clear();
+ List.append( i18n("&No Resize") );
+ List.append( i18n("&Lock Groups") );
+ List.append( i18n("&Full Size Usage") );
+ ResizeStyleAction->setItems( List );
+ connect( ResizeStyleAction, SIGNAL(activated(int)), this, SLOT(slotSetResizeStyle(int)) );
+
+ ShowOffsetColumnAction = new KToggleAction( i18n("&Line Offset"), Key_F11, this, SLOT(slotToggleOffsetColumn()), AC, "view_lineoffset" );
+
+ // show buffer columns
+ ToggleColumnsAction = new KSelectAction( i18n("&Columns"), 0, AC, "togglecolumns" );
+ List.clear();
+ List.append( i18n("&Values Column") );
+ List.append( i18n("&Chars Column") );
+ List.append( i18n("&Both Columns") );
+ ToggleColumnsAction->setItems( List );
+ connect( ToggleColumnsAction, SIGNAL(activated(int)), this, SLOT(slotToggleValueCharColumns(int)) );
+
+ fitActionSettings();
+
+ // set our XML-UI resource file
+ setXMLFile( RCFileName );
+}
+
+
+void KHexEditPart::fitActionSettings()
+{
+ ShowOffsetColumnAction->setChecked( HexEdit->offsetColumnVisible() );
+ ShowUnprintableAction->setChecked( HexEdit->showUnprintable() );
+
+ CodingAction->setCurrentItem( (int)HexEdit->coding() );
+ EncodingAction->setCurrentItem( KCharCodec::codecNames().findIndex(HexEdit->encodingName()) );
+
+ ResizeStyleAction->setCurrentItem( (int)HexEdit->resizeStyle() );
+
+ ToggleColumnsAction->setCurrentItem( (int)HexEdit->visibleBufferColumns()-1 );
+}
+
+
+bool KHexEditPart::openFile()
+{
+ Wrapping.open( m_file );
+ HexEdit->setDataBuffer( &Wrapping );
+ HexEdit->setCursorPosition( 0 );
+ HexEdit->selectAll( false );
+
+ return true;
+}
+
+
+
+void KHexEditPart::slotSelectionChanged()
+{
+ bool State = HexEdit->hasSelectedData();
+ CopyAction->setEnabled( State );
+}
+
+
+void KHexEditPart::slotSelectAll()
+{
+ HexEdit->selectAll( true );
+}
+
+
+void KHexEditPart::slotUnselect()
+{
+ HexEdit->selectAll( false );
+}
+
+
+void KHexEditPart::slotSetCoding( int Coding )
+{
+ HexEdit->setCoding( (KHexEdit::KCoding)Coding );
+}
+
+void KHexEditPart::slotSetShowUnprintable()
+{
+ HexEdit->setShowUnprintable( ShowUnprintableAction->isChecked() );
+}
+
+void KHexEditPart::slotToggleOffsetColumn()
+{
+ HexEdit->toggleOffsetColumn( ShowOffsetColumnAction->isChecked() );
+}
+
+void KHexEditPart::slotSetResizeStyle( int ResizeStyle )
+{
+ HexEdit->setResizeStyle( (KHexEdit::KResizeStyle)ResizeStyle );
+}
+
+void KHexEditPart::slotSetEncoding( int Encoding )
+{
+ HexEdit->setEncoding( KCharCodec::codecNames()[Encoding] );
+}
+
+void KHexEditPart::slotToggleValueCharColumns( int VisibleColumns)
+{
+ HexEdit->showBufferColumns( VisibleColumns+1 );
+}
+
+#include "khepart.moc"
diff --git a/khexedit/parts/kpart/khepart.h b/khexedit/parts/kpart/khepart.h
new file mode 100644
index 0000000..54befa0
--- /dev/null
+++ b/khexedit/parts/kpart/khepart.h
@@ -0,0 +1,95 @@
+/***************************************************************************
+ khepart.h - description
+ -------------------
+ begin : Don Jun 19 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHEPART_H
+#define KHEPART_H
+
+// kde specific
+#include <kparts/part.h>
+// app specific
+#include "kbigbuffer.h"
+
+// forward declarations
+class KRadioAction;
+class KToggleAction;
+class KSelectAction;
+
+namespace KHE
+{
+
+// forward declarations
+class KHexEdit;
+
+/**
+ * This is a "Part". It that does all the real work in a KPart
+ * application.
+ *
+ * @short Main Part
+ * @author Friedrich W. H. Kossebau <Friedrich.W.H@Kossebau.de>
+ * @version 0.1.0
+ */
+class KHexEditPart : public KParts::ReadOnlyPart
+{
+ Q_OBJECT
+
+ friend class KHexEditBrowserExtension;
+
+ public:
+ KHexEditPart( QWidget *ParentWidget, const char *WidgetName, QObject *Parent, const char *Name,
+ bool BrowserViewWanted );
+ virtual ~KHexEditPart();
+
+
+ protected: // KParts::ReadOnlyPart API
+ virtual bool openFile();
+
+ protected:
+ void setupActions( bool BrowserViewWanted );
+ void fitActionSettings();
+
+ protected slots:
+ // used to catch changes in the HexEdit widget
+ void slotSelectionChanged();
+ protected slots: // action slots
+ void slotSelectAll();
+ void slotUnselect();
+ void slotSetCoding( int Coding );
+ void slotSetEncoding( int Encoding );
+ void slotSetShowUnprintable();
+ void slotSetResizeStyle( int Style );
+ void slotToggleOffsetColumn();
+ void slotToggleValueCharColumns( int VisibleColunms );
+
+ private:
+ KHexEdit *HexEdit;
+ KBigBuffer Wrapping;
+
+ // edit menu
+ KAction *CopyAction;
+ // view menu
+ KSelectAction *CodingAction;
+ KSelectAction *EncodingAction;
+ KToggleAction *ShowUnprintableAction;
+ // settings menu
+ KSelectAction *ResizeStyleAction;
+ KToggleAction *ShowOffsetColumnAction;
+ KSelectAction *ToggleColumnsAction;
+};
+
+}
+
+#endif
diff --git a/khexedit/parts/kpart/khepartfactory.cpp b/khexedit/parts/kpart/khepartfactory.cpp
new file mode 100644
index 0000000..f85d8a9
--- /dev/null
+++ b/khexedit/parts/kpart/khepartfactory.cpp
@@ -0,0 +1,90 @@
+/***************************************************************************
+ khepartfactory.h - description
+ -------------------
+ begin : Don Jun 19 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+// kde specific
+#include <kinstance.h>
+#include <kaboutdata.h>
+#include <klocale.h>
+// app specific
+#include "khepart.h"
+#include "khepartfactory.h"
+
+using namespace KHE;
+
+// Part
+static const char PartId[] = "khexedit2part";
+static const char PartName[] = I18N_NOOP("KHexEdit2Part");
+static const char PartDescription[] = I18N_NOOP("Embedded hex editor");
+static const char PartVersion[] = "0.2.0";
+static const char PartCopyright[] = "(C) 2003-2004 Friedrich W. H. Kossebau";
+// Author
+static const char FWHKName[] = "Friedrich W. H. Kossebau";
+static const char FWHKTask[] = I18N_NOOP("Author");
+static const char FWHKEmailAddress[] = "Friedrich.W.H@Kossebau.de";
+// static const char FWHKWebAddress[] = "http://www.kossebau.de";
+
+
+KInstance* KHexEditPartFactory::s_instance = 0L;
+KAboutData* KHexEditPartFactory::s_about = 0L;
+
+
+KHexEditPartFactory::KHexEditPartFactory()
+ : KParts::Factory()
+{
+}
+
+
+KHexEditPartFactory::~KHexEditPartFactory()
+{
+ delete s_instance;
+ delete s_about;
+
+ s_instance = 0;
+}
+
+
+KParts::Part* KHexEditPartFactory::createPartObject( QWidget *ParentWidget, const char *WidgetName,
+ QObject *Parent, const char *Name,
+ const char *CN, const QStringList &/*args*/ )
+{
+ QCString Classname( CN );
+ bool BrowserViewWanted = ( Classname == "Browser/View" );
+ //bool ReadOnlyWanted = (BrowserViewWanted || ( Classname == "KParts::ReadOnlyPart" ));
+
+ // Create an instance of our Part
+ KHexEditPart* HexEditPart = new KHexEditPart( ParentWidget, WidgetName, Parent, Name, BrowserViewWanted );
+
+ return HexEditPart;
+}
+
+
+KInstance* KHexEditPartFactory::instance()
+{
+ if( !s_instance )
+ {
+ s_about = new KAboutData( PartId, PartName, PartVersion, PartDescription,
+ KAboutData::License_GPL_V2, PartCopyright, 0, 0, FWHKEmailAddress );
+ s_about->addAuthor( FWHKName, FWHKTask, FWHKEmailAddress );
+ s_instance = new KInstance( s_about );
+ }
+ return s_instance;
+}
+
+
+K_EXPORT_COMPONENT_FACTORY( libkhexedit2part, KHexEditPartFactory )
+
+#include "khepartfactory.moc"
diff --git a/khexedit/parts/kpart/khepartfactory.h b/khexedit/parts/kpart/khepartfactory.h
new file mode 100644
index 0000000..7cd6c7e
--- /dev/null
+++ b/khexedit/parts/kpart/khepartfactory.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ khepartfactory.h - description
+ -------------------
+ begin : Don Jun 19 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KHEPARTFACTORY_H
+#define KHEPARTFACTORY_H
+
+#include <kparts/factory.h>
+
+class KInstance;
+class KAboutData;
+
+
+class KHexEditPartFactory : public KParts::Factory
+{
+ Q_OBJECT
+
+ public:
+ KHexEditPartFactory();
+ virtual ~KHexEditPartFactory();
+
+ public:
+ virtual KParts::Part* createPartObject( QWidget *parentWidget, const char *widgetName,
+ QObject *parent, const char *name,
+ const char *classname, const QStringList &args );
+ static KInstance* instance();
+
+
+ private:
+ static KInstance* s_instance;
+ static KAboutData* s_about;
+};
+
+#endif
diff --git a/khexedit/parts/kpart/khexedit2part.desktop b/khexedit/parts/kpart/khexedit2part.desktop
new file mode 100644
index 0000000..60f4132
--- /dev/null
+++ b/khexedit/parts/kpart/khexedit2part.desktop
@@ -0,0 +1,101 @@
+[Desktop Entry]
+Type=Service
+Icon=khexedit
+Name=Embedded Binary Viewer
+Name[ar]=عارض ثنائى مدمج
+Name[bg]=Вграден двоичен преглед
+Name[br]=Gweler HTML enframmus
+Name[bs]=Ugrađeni preglednik binarnih datoteka
+Name[ca]=Visor binari encastat
+Name[cs]=Zabudovaný binární prohlížeÄ
+Name[da]=Indlejret binær fremviser
+Name[de]=Eingebettetes Anzeigeprogramm für Binärdateien
+Name[el]=Ενσωματωμένος Ï€Ïοβολέας δυαδικών αÏχείων
+Name[eo]=Enkonstruita duum-rigardilo
+Name[es]=Visor binario empotrado
+Name[et]=Põimitud binaarfailide näitaja
+Name[eu]=Ikusgailu binario txertagarria
+Name[fa]=مشاهده‌گر دوگانی نهÙته
+Name[fi]=Sulautettu binääritiedostojen näytin
+Name[fr]=Afficheur de binaires intégré
+Name[ga]=Amharcán Leabaithe Dénártha
+Name[he]=עורך הקס×דצימלי משובץ
+Name[hu]=Beágyazott nézegető bináris fájlokhoz
+Name[is]=Innbyggður tvíundakerfisskoðari
+Name[it]=Visore binario integrabile
+Name[ja]=埋ã‚è¾¼ã¿ãƒã‚¤ãƒŠãƒªãƒ“ューア
+Name[kk]=Ендірілетін бинарлық қарау құралы
+Name[km]=កម្មវិធី​មើល​គោលពីរ​ដែល​បាន​បង្កប់
+Name[lt]=Įdedama dvejetainių duomenų žiūryklė
+Name[nb]=Innebygget Binærfremviser
+Name[nds]=Inbett Bineerdaten-Kieker
+Name[ne]=समà¥à¤®à¤¿à¤²à¤¿à¤¤ बाइनरी दरà¥à¤¶à¤•
+Name[nl]=Ingebedde binaire viewer
+Name[nn]=Innebygd binærframvisar
+Name[pa]=ਸ਼ਾਮਲ ਬਾਈਨਰੀ ਦਰਸ਼ਕ
+Name[pl]=Wbudowana przeglÄ…darka binarna
+Name[pt]=Visualizador Binário Incorporado
+Name[pt_BR]=Visualizador Binário Embutido
+Name[ru]=Компонент проÑмотра двоичных данных
+Name[sk]=Vložený binárny prezeraÄ
+Name[sl]=Vgrajen binarni pregledovalnik
+Name[sr]=Уградиви приказивач бинарног
+Name[sr@Latn]=Ugradivi prikazivaÄ binarnog
+Name[sv]=Inbäddad binärvisning
+Name[ta]=உடà¯à®ªà¯Šà®¤à®¿à®¨à¯à®¤ இரà¯à®¨à®¿à®²à¯ˆ காடà¯à®šà®¿à®¯à®¾à®³à®©à¯
+Name[tr]=Gömülü İkili dosya Görüntüleyici
+Name[uk]=Вбудований переглÑдач Ð´Ð»Ñ Ð´Ð²Ñ–Ð¹ÐºÐ¾Ð²Ð¸Ñ… даних
+Name[zh_CN]=嵌入å¼äºŒè¿›åˆ¶æŸ¥çœ‹å™¨
+Name[zh_TW]=嵌入å¼äºŒé€²ä½é¡¯ç¤ºå™¨
+Comment=Embedded Binary Viewer
+Comment[ar]=عارض ثنائى مدمج
+Comment[bg]=Вградена програма за преглед на двоични файлове
+Comment[br]=Gweler HTML enframmus
+Comment[bs]=Ugrađeni preglednik binarnih datoteka
+Comment[ca]=Visor binari encastat
+Comment[cs]=Zabudovaný binární prohlížeÄ
+Comment[da]=Indlejret binær fremviser
+Comment[de]=Eingebettetes Anzeigeprogramm für Binärdateien
+Comment[el]=Ενσωματωμένος Ï€Ïοβολέας δυαδικών αÏχείων
+Comment[eo]=Enkonstruita duum-rigardilo
+Comment[es]=Visor binario empotrado
+Comment[et]=Põimitud binaarfailide näitaja
+Comment[eu]=Ikusgailu binario txertagarria
+Comment[fa]=مشاهده‌گر دوگانی نهÙته
+Comment[fi]=Sulautettu binääritiedostojen näytin
+Comment[fr]=Afficheur de binaires intégré
+Comment[ga]=Amharcán Leabaithe Dénártha
+Comment[he]=עורך הקס×דצימלי משובץ
+Comment[hu]=Beágyazott fájlmegjelenítő bináris fájlokhoz
+Comment[is]=Innbyggður tvíundakerfisskoðari
+Comment[it]=Visore binario integrabile
+Comment[ja]=埋ã‚è¾¼ã¿ãƒã‚¤ãƒŠãƒªãƒ“ューア
+Comment[ka]=ჩáƒáƒ¨áƒ”ნებული ბინáƒáƒ áƒ£áƒšáƒ˜ დáƒáƒ›áƒ—ვáƒáƒšáƒ˜áƒ”რებელი
+Comment[kk]=Ендірілетін бинарлық қарау құралы
+Comment[km]=កម្មវិធី​មើល​គោលពីរ​ដែល​បាន​បង្កប់
+Comment[lt]=Įdedama dvejetainių duomenų žiūryklė
+Comment[nb]=Innebygget Binærfremviser
+Comment[nds]=Inbett Bineerdaten-Kieker
+Comment[ne]=समà¥à¤®à¤¿à¤²à¤¿à¤¤ बाइनरी दरà¥à¤¶à¤•
+Comment[nl]=Ingebedde binaire viewer
+Comment[nn]=Innebygd binærframvisar
+Comment[pa]=ਸ਼ਾਮਲ ਬਾਈਨਰੀ ਦਰਸ਼ਕ
+Comment[pl]=Wbudowana przeglÄ…darka binarna
+Comment[pt]=Visualizador Binário Incorporado
+Comment[pt_BR]=Visualizador Binário Embutido
+Comment[ru]=Компонент проÑмотра двоичных данных
+Comment[sk]=Vložený binárny prezeraÄ
+Comment[sl]=Vgrajen binarni pregledovalnik
+Comment[sr]=Уградиви приказивач бинарног
+Comment[sr@Latn]=Ugradivi prikazivaÄ binarnog
+Comment[sv]=Inbäddad binärvisning
+Comment[ta]=உடà¯à®ªà¯Šà®¤à®¿à®¨à¯à®¤ இரà¯à®¨à®¿à®²à¯ˆ காடà¯à®šà®¿à®¯à®¾à®³à®©à¯
+Comment[tr]=Gömülü İkili dosya Görüntüleyici
+Comment[uk]=Вбудований переглÑдач Ð´Ð»Ñ Ð´Ð²Ñ–Ð¹ÐºÐ¾Ð²Ð¸Ñ… даних
+Comment[zh_CN]=嵌入å¼äºŒè¿›åˆ¶æŸ¥çœ‹å™¨
+Comment[zh_TW]=嵌入å¼äºŒé€²ä½é¡¯ç¤ºå™¨
+#MimeType=all/allfiles
+MimeType=application/octet-stream
+ServiceTypes=KParts/ReadOnlyPart,Browser/View
+#,KParts/ReadWritePart
+X-KDE-Library=libkhexedit2part
diff --git a/khexedit/parts/kpart/khexedit2partui.rc b/khexedit/parts/kpart/khexedit2partui.rc
new file mode 100644
index 0000000..82b40eb
--- /dev/null
+++ b/khexedit/parts/kpart/khexedit2partui.rc
@@ -0,0 +1,42 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="khexedit2part" version="1">
+<MenuBar>
+ <Menu name="edit"><text>&amp;Edit</text>
+ <Action name="edit_copy" group="edit_paste_merge" />
+ <Action name="edit_select_all" group="edit_select_merge" />
+ <Action name="edit_deselect" group="edit_select_merge" />
+ </Menu>
+ <Menu name="view"><text>&amp;View</text>
+ <Separator/>
+ <Action name="view_zoom_in" />
+ <Action name="view_zoom_out" />
+ <Separator/>
+ <Action name="view_showunprintable" />
+ <Action name="view_lineoffset" />
+ <Separator/>
+ <Action name="view_valuecoding" />
+ <Action name="view_charencoding" />
+ </Menu>
+ <Menu name="settings"><text>&amp;Settings</text>
+ <Separator/>
+ <Action name="resizestyle" group="show_merge" />
+ <Action name="togglecolumns" group="show_merge" />
+ </Menu>
+</MenuBar>
+
+<ToolBar name="mainToolBar"><text>Main Toolbar</text>
+ <Action name="edit_copy" />
+ <Action name="view_zoom_in" />
+ <Action name="view_zoom_out" />
+</ToolBar>
+
+<!-- Editor popup menu //-->
+<Menu name="editor_popup">
+ <Action name="view_hexcoding" />
+ <Action name="view_deccoding" />
+ <Action name="view_octcoding" />
+ <Action name="view_bincoding" />
+ <Separator/>
+ <Action name="resize_lock" />
+</Menu>
+</kpartgui>
diff --git a/khexedit/pics/Makefile.am b/khexedit/pics/Makefile.am
new file mode 100644
index 0000000..0dd7a3f
--- /dev/null
+++ b/khexedit/pics/Makefile.am
@@ -0,0 +1,3 @@
+toolbar_DATA = hexwrite.png hexdrag.png hexmask.png
+toolbardir = $(kde_datadir)/khexedit/pics
+
diff --git a/khexedit/pics/hexdrag.png b/khexedit/pics/hexdrag.png
new file mode 100644
index 0000000..1459f4f
--- /dev/null
+++ b/khexedit/pics/hexdrag.png
Binary files differ
diff --git a/khexedit/pics/hexmask.png b/khexedit/pics/hexmask.png
new file mode 100644
index 0000000..69e71e5
--- /dev/null
+++ b/khexedit/pics/hexmask.png
Binary files differ
diff --git a/khexedit/pics/hexwrite.png b/khexedit/pics/hexwrite.png
new file mode 100644
index 0000000..a408a03
--- /dev/null
+++ b/khexedit/pics/hexwrite.png
Binary files differ
diff --git a/khexedit/printdialogpage.cc b/khexedit/printdialogpage.cc
new file mode 100644
index 0000000..ecc0a90
--- /dev/null
+++ b/khexedit/printdialogpage.cc
@@ -0,0 +1,386 @@
+/*
+ * 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 <qlayout.h>
+#include <qbuttongroup.h>
+#include <qspinbox.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <qstringlist.h>
+#include <qcombobox.h>
+
+#include <klocale.h>
+
+
+#include "printdialogpage.h"
+
+LayoutDialogPage::LayoutDialogPage( QWidget *parent, const char *name )
+ : KPrintDialogPage( parent, name )
+{
+ mConfig = 0;
+ setTitle( i18n( "Page Layout" ) );
+ setupLayoutPage();
+
+ readConfiguration();
+}
+
+
+LayoutDialogPage::~LayoutDialogPage( void )
+{
+ writeConfiguration();
+
+ delete mConfig; mConfig = 0;
+}
+
+
+void LayoutDialogPage::setupLayoutPage( void )
+{
+ QString text;
+ QVBoxLayout *topLayout = new QVBoxLayout( this, 0, 6 /*KDialog::mSpacingSize*/ );
+ if( topLayout == 0 ) { return; }
+
+ text = i18n("Margins [millimeter]");
+ QButtonGroup *group = new QButtonGroup( text, this );
+ if( group == 0 ) { return; }
+ topLayout->addWidget( group );
+
+ QGridLayout *gbox = new QGridLayout( group, 3, 6, 6 /*KDialog::mSpacingSize*/ );
+ if( gbox == 0 ) { return; }
+ gbox->addRowSpacing( 0, group->fontMetrics().height() );
+ gbox->setColStretch( 5, 10 );
+
+ QString name[4];
+ int i;
+
+ name[0] = i18n("&Top:");
+ name[1] = i18n("&Bottom:");
+ name[2] = i18n("&Left:");
+ name[3] = i18n("&Right:");
+
+ for( i=0; i<4; i++ )
+ {
+ mLayout.marginSpin[i] = new QSpinBox( group );
+ mLayout.marginSpin[i]->setFixedHeight(
+ mLayout.marginSpin[i]->sizeHint().height() );
+ mLayout.marginSpin[i]->setMinimumWidth(
+ mLayout.marginSpin[i]->fontMetrics().width("M")*10 );
+ mLayout.marginSpin[i]->setRange( 0, INT_MAX );
+
+ QLabel *label = new QLabel( mLayout.marginSpin[i], name[i], group );
+ label->setFixedHeight( mLayout.marginSpin[i]->sizeHint().height() );
+ label->setFixedWidth( label->sizeHint().width() );
+
+ if( i < 2 )
+ {
+ gbox->addWidget( label, i+1, 0, AlignLeft );
+ gbox->addWidget( mLayout.marginSpin[i], i+1, 1, AlignLeft );
+ }
+ else
+ {
+ gbox->addWidget( label, i-1, 3, AlignLeft );
+ gbox->addWidget( mLayout.marginSpin[i], i-1, 4, AlignLeft );
+ }
+ }
+
+ text = i18n("Draw h&eader above text");
+ mLayout.headerCheck = new QCheckBox( text, this );
+ mLayout.headerCheck->setFixedSize( mLayout.headerCheck->sizeHint() );
+ connect( mLayout.headerCheck, SIGNAL( toggled(bool)),
+ SLOT( slotDrawHeader(bool)));
+ topLayout->addWidget( mLayout.headerCheck, 0, AlignLeft );
+
+ gbox = new QGridLayout( 5, 6, 0 );
+ if( gbox == 0 ) { return; }
+ topLayout->addLayout( gbox );
+
+ gbox->setColStretch ( 5, 10 );
+ gbox->addColSpacing( 1, 6 /*KDialog::mSpacingSize*/ );
+ gbox->addColSpacing( 3, 6 /*KDialog::mSpacingSize*/ );
+ gbox->addRowSpacing( 2, 6 /*KDialog::mSpacingSize*/ );
+
+ name[0] = i18n("Left:");
+ name[1] = i18n("Center:");
+ name[2] = i18n("Right:");
+ name[3] = i18n("Border:");
+
+ QStringList textList;
+ textList.append(i18n("None"));
+ textList.append(i18n("Date & Time"));
+ textList.append(i18n("Page Number"));
+ textList.append(i18n("Filename"));
+
+ QStringList lineList;
+ lineList.append(i18n("None"));
+ lineList.append(i18n("Single Line"));
+ lineList.append(i18n("Rectangle"));
+
+ for( i=0; i<4; i++ )
+ {
+ mLayout.headerCombo[i] = new QComboBox( false, this );
+ mLayout.headerCombo[i]->setFixedHeight(
+ mLayout.headerCombo[i]->sizeHint().height() );
+ mLayout.headerCombo[i]->setMinimumWidth(
+ mLayout.headerCombo[i]->fontMetrics().width("M")*10 );
+
+ mLayout.headerLabel[i] = new QLabel( mLayout.headerCombo[i], name[i],
+ this );
+ mLayout.headerLabel[i]->setFixedHeight(
+ mLayout.headerLabel[i]->sizeHint().height() );
+ mLayout.headerLabel[i]->setFixedWidth(
+ mLayout.headerLabel[i]->sizeHint().width() );
+
+ if( i<3 )
+ {
+ mLayout.headerCombo[i]->insertStringList( textList );
+ gbox->addWidget( mLayout.headerLabel[i], 0, i*2, AlignLeft );
+ gbox->addWidget( mLayout.headerCombo[i], 1, i*2, AlignLeft );
+ }
+ else
+ {
+ mLayout.headerCombo[i]->insertStringList( lineList );
+ gbox->addWidget( mLayout.headerLabel[i], 3, 0, AlignLeft );
+ gbox->addWidget( mLayout.headerCombo[i], 4, 0, AlignLeft );
+ }
+ }
+
+
+ text = i18n("Draw &footer below text");
+ mLayout.footerCheck = new QCheckBox( text, this );
+ mLayout.footerCheck->setFixedSize( mLayout.footerCheck->sizeHint() );
+ connect( mLayout.footerCheck, SIGNAL( toggled(bool)),
+ SLOT( slotDrawFooter(bool)));
+ topLayout->addWidget( mLayout.footerCheck, 0, AlignLeft );
+
+ gbox = new QGridLayout( 5, 6, 0 );
+ if( gbox == 0 ) { return; }
+ topLayout->addLayout( gbox );
+
+ gbox->setColStretch ( 5, 10 );
+ gbox->addColSpacing( 1, 6 /*KDialog::mSpacingSize*/ );
+ gbox->addColSpacing( 3, 6 /*KDialog::mSpacingSize*/ );
+ gbox->addRowSpacing( 2, 6 /*KDialog::mSpacingSize*/ );
+
+ for( i=0; i<4; i++ )
+ {
+ mLayout.footerCombo[i] = new QComboBox( false, this );
+ mLayout.footerCombo[i]->setFixedHeight(
+ mLayout.footerCombo[i]->sizeHint().height() );
+ mLayout.footerCombo[i]->setMinimumWidth(
+ mLayout.footerCombo[i]->fontMetrics().width("M")*10 );
+
+ mLayout.footerLabel[i] = new QLabel( mLayout.footerCombo[i], name[i],
+ this );
+ mLayout.footerLabel[i]->setFixedHeight(
+ mLayout.footerLabel[i]->sizeHint().height() );
+ mLayout.footerLabel[i]->setFixedWidth(
+ mLayout.footerLabel[i]->sizeHint().width() );
+
+ if( i<3 )
+ {
+ mLayout.footerCombo[i]->insertStringList( textList );
+ gbox->addWidget( mLayout.footerLabel[i], 0, i*2, AlignLeft );
+ gbox->addWidget( mLayout.footerCombo[i], 1, i*2, AlignLeft );
+ }
+ else
+ {
+ mLayout.footerCombo[i]->insertStringList( lineList );
+ gbox->addWidget( mLayout.footerLabel[i], 3, 0, AlignLeft );
+ gbox->addWidget( mLayout.footerCombo[i], 4, 0, AlignLeft );
+ }
+ }
+
+ for( i=0; i<4; i++ )
+ {
+ mLayout.marginSpin[i]->setValue( 15 );
+ }
+ mLayout.headerCheck->setChecked( true );
+ slotDrawHeader( true );
+ mLayout.footerCheck->setChecked( true );
+ slotDrawFooter( true );
+
+ topLayout->addStretch(10);
+}
+
+
+void LayoutDialogPage::readConfiguration( void )
+{
+ if( mConfig != 0 ) { return; }
+
+ mConfig = new KSimpleConfig( QString("hexprinter") );
+ if( mConfig == 0 ) { return; }
+
+ mConfig->setGroup( "PageLayout" );
+ int val = mConfig->readNumEntry( "MarginTop", 15 );
+ mLayout.marginSpin[0]->setValue( val );
+ val = mConfig->readNumEntry( "MarginBottom", 15 );
+ mLayout.marginSpin[1]->setValue( val );
+ val = mConfig->readNumEntry( "MarginLeft", 15 );
+ mLayout.marginSpin[2]->setValue( val );
+ val = mConfig->readNumEntry( "MarginRight", 15 );
+ mLayout.marginSpin[3]->setValue( val );
+ bool state = mConfig->readBoolEntry( "DrawHeader", true );
+ mLayout.headerCheck->setChecked( state );
+ slotDrawHeader( state );
+ state = mConfig->readBoolEntry( "DrawFooter", true );
+ mLayout.footerCheck->setChecked( state );
+ slotDrawFooter( state );
+
+ mLayout.headerCombo[0]->setCurrentItem(
+ headerTextIndex( mConfig->readEntry("HeaderLeft","DateTime")));
+ mLayout.headerCombo[1]->setCurrentItem(
+ headerTextIndex( mConfig->readEntry("HeaderCenter")));
+ mLayout.headerCombo[2]->setCurrentItem(
+ headerTextIndex( mConfig->readEntry("HeaderRight","FileName")));
+ mLayout.headerCombo[3]->setCurrentItem(
+ headerLineIndex( mConfig->readEntry("HeaderLine","SingleLine")));
+
+ mLayout.footerCombo[0]->setCurrentItem(
+ headerTextIndex( mConfig->readEntry("FooterLeft")));
+ mLayout.footerCombo[1]->setCurrentItem(
+ headerTextIndex( mConfig->readEntry("FooterCenter","PageNumber")));
+ mLayout.footerCombo[2]->setCurrentItem(
+ headerTextIndex( mConfig->readEntry("FooterRight")));
+ mLayout.footerCombo[3]->setCurrentItem(
+ headerLineIndex( mConfig->readEntry("FooterLine","SingleLine")));
+
+}
+
+
+void LayoutDialogPage::writeConfiguration( void )
+{
+ if( mConfig == 0 )
+ {
+ return;
+ }
+
+ mConfig->setGroup( "PageLayout" );
+ mConfig->writeEntry( "MarginTop", mLayout.marginSpin[0]->value() );
+ mConfig->writeEntry( "MarginBottom", mLayout.marginSpin[1]->value() );
+ mConfig->writeEntry( "MarginLeft", mLayout.marginSpin[2]->value() );
+ mConfig->writeEntry( "MarginRight", mLayout.marginSpin[3]->value() );
+ mConfig->writeEntry( "DrawHeader", mLayout.headerCheck->isChecked() );
+ mConfig->writeEntry( "DrawFooter", mLayout.footerCheck->isChecked() );
+
+ mConfig->writeEntry( "HeaderLeft",
+ headerText( mLayout.headerCombo[0]->currentItem() ) );
+ mConfig->writeEntry( "HeaderCenter",
+ headerText( mLayout.headerCombo[1]->currentItem() ) );
+ mConfig->writeEntry( "HeaderRight",
+ headerText( mLayout.headerCombo[2]->currentItem() ) );
+ mConfig->writeEntry( "HeaderLine",
+ headerLine( mLayout.headerCombo[3]->currentItem() ) );
+
+ mConfig->writeEntry( "FooterLeft",
+ headerText( mLayout.footerCombo[0]->currentItem() ) );
+ mConfig->writeEntry( "FooterCenter",
+ headerText( mLayout.footerCombo[1]->currentItem() ) );
+ mConfig->writeEntry( "FooterRight",
+ headerText( mLayout.footerCombo[2]->currentItem() ) );
+ mConfig->writeEntry( "FooterLine",
+ headerLine( mLayout.footerCombo[3]->currentItem() ) );
+
+ mConfig->sync();
+}
+
+
+QString LayoutDialogPage::headerText( uint index )
+{
+ static const QString text[4] = {"None","DateTime","PageNumber","FileName"};
+ return( text[ index > 3 ? 0 : index ] );
+}
+
+
+int LayoutDialogPage::headerTextIndex( const QString & headerText )
+{
+ static const QString text[4] = {"None","DateTime","PageNumber","FileName"};
+ if( headerText != 0 )
+ {
+ for( int i=0; i<4; i++ )
+ {
+ if( headerText == text[i] ) { return( i ); }
+ }
+ }
+ return( 0 );
+}
+
+
+QString LayoutDialogPage::headerLine( uint index )
+{
+ static const QString text[3] = {"None","SingleLine","Rectangle"};
+ return( text[ index > 2 ? 0 : index ] );
+}
+
+
+int LayoutDialogPage::headerLineIndex( const QString & headerLine )
+{
+ static const QString text[3] = {"None","SingleLine","Rectangle"};
+ if( headerLine != 0 )
+ {
+ for( int i=0; i<3; i++ )
+ {
+ if( headerLine == text[i] ) { return( i ); }
+ }
+ }
+ return( 0 );
+}
+
+
+void LayoutDialogPage::slotDrawHeader( bool state )
+{
+ for( int i=0; i<4; i++ )
+ {
+ mLayout.headerLabel[i]->setEnabled( state );
+ mLayout.headerCombo[i]->setEnabled( state );
+ }
+}
+
+
+void LayoutDialogPage::slotDrawFooter( bool state )
+{
+ for( int i=0; i<4; i++ )
+ {
+ mLayout.footerLabel[i]->setEnabled( state );
+ mLayout.footerCombo[i]->setEnabled( state );
+ }
+}
+
+
+void LayoutDialogPage::getOptions( QMap<QString,QString>& opts, bool /*incldef*/ )
+{
+ opts[ "kde-khexedit-topmarginmm" ] = QString::number( mLayout.marginSpin[0]->value() );
+ opts[ "kde-khexedit-bottommarginmm" ] = QString::number( mLayout.marginSpin[1]->value() );
+ opts[ "kde-khexedit-leftmarginmm" ] = QString::number( mLayout.marginSpin[2]->value() );
+ opts[ "kde-khexedit-rightmarginmm" ] = QString::number( mLayout.marginSpin[3]->value() );
+
+ opts[ "kde-khexedit-headercheck" ] = (mLayout.headerCheck->isChecked() ? "true" : "false");
+ opts[ "kde-khexedit-headercombo0" ] = QString::number( mLayout.headerCombo[0]->currentItem() );
+ opts[ "kde-khexedit-headercombo1" ] = QString::number( mLayout.headerCombo[1]->currentItem() );
+ opts[ "kde-khexedit-headercombo2" ] = QString::number( mLayout.headerCombo[2]->currentItem() );
+ opts[ "kde-khexedit-headercombo3" ] = QString::number( mLayout.headerCombo[3]->currentItem() );
+
+ opts[ "kde-khexedit-footercheck" ] = (mLayout.footerCheck->isChecked() ? "true" : "false");
+ opts[ "kde-khexedit-footercombo0" ] = QString::number( mLayout.footerCombo[0]->currentItem() );
+ opts[ "kde-khexedit-footercombo1" ] = QString::number( mLayout.footerCombo[1]->currentItem() );
+ opts[ "kde-khexedit-footercombo2" ] = QString::number( mLayout.footerCombo[2]->currentItem() );
+ opts[ "kde-khexedit-footercombo3" ] = QString::number( mLayout.footerCombo[3]->currentItem() );
+}
+
+
+#include "printdialogpage.moc"
diff --git a/khexedit/printdialogpage.h b/khexedit/printdialogpage.h
new file mode 100644
index 0000000..bdc58f6
--- /dev/null
+++ b/khexedit/printdialogpage.h
@@ -0,0 +1,73 @@
+/*
+ * khexedit - Versatile hex editor
+ * Copyright (C) 1999 Espen Sand, espensa@online.no
+ * This file is based on the work by F. Zigterman, fzr@dds.nl
+ *
+ * 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.
+ *
+ */
+
+#ifndef _PRINT_DIALOG_PAGE_H_
+#define _PRINT_DIALOG_PAGE_H_
+
+class QCheckBox;
+class QComboBox;
+class QLabel;
+class QSpinBox;
+
+#include <kdeprint/kprintdialogpage.h>
+#include <ksimpleconfig.h>
+
+class LayoutDialogPage : public KPrintDialogPage
+{
+ Q_OBJECT
+
+ public:
+ LayoutDialogPage( QWidget *parent = 0, const char *name = 0 );
+ ~LayoutDialogPage( void );
+
+ void getOptions( QMap<QString,QString>& opts, bool incldef = false );
+
+ private slots:
+ void slotDrawHeader( bool state );
+ void slotDrawFooter( bool state );
+
+ private:
+ void setupLayoutPage( void );
+
+ void readConfiguration( void );
+ void writeConfiguration( void );
+
+ QString headerText( uint index );
+ QString headerLine( uint index );
+ int headerTextIndex( const QString & headerText );
+ int headerLineIndex( const QString & headerLine );
+
+ struct SLayoutWidgets
+ {
+ QSpinBox *marginSpin[4];
+ QCheckBox *headerCheck;
+ QCheckBox *footerCheck;
+ QLabel *headerLabel[4];
+ QComboBox *headerCombo[4];
+ QLabel *footerLabel[4];
+ QComboBox *footerCombo[4];
+ };
+
+ KSimpleConfig *mConfig;
+ SLayoutWidgets mLayout;
+};
+
+#endif
diff --git a/khexedit/progress.h b/khexedit/progress.h
new file mode 100644
index 0000000..fa6e8a3
--- /dev/null
+++ b/khexedit/progress.h
@@ -0,0 +1,130 @@
+/*
+ * khexedit - Versatile hex editor
+ * Copyright (C) 1999 Espen Sand, espensa@online.no
+ * This file is based on the work by F. Zigterman, fzr@dds.nl
+ *
+ * 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.
+ *
+ */
+
+#ifndef _PROGRESS_H_
+#define _PROGRESS_H_
+
+#include <qdatetime.h>
+#include "hexerror.h"
+
+
+struct SProgressData
+{
+ SProgressData( float f )
+ {
+ useFraction = 1;
+ fraction = f;
+ }
+
+ SProgressData( int cPage, int mPage )
+ {
+ useFraction = 0;
+ curPage = cPage;
+ maxPage = mPage;
+ }
+
+ int valid( void ) const
+ {
+ return( (useFraction == 1 && fraction >= 0) ||
+ (useFraction == 0 && curPage >= 0) ? 1 : 0 );
+ }
+
+ int useFraction;
+ float fraction;
+ int curPage;
+ int maxPage;
+};
+
+
+
+typedef int (*ProgressFunc)( void *clientData, SProgressData &pd );
+
+class CProgress
+{
+ public:
+ CProgress( void )
+ {
+ define( 0, 0 );
+ mInterruptTimer.start();
+ }
+
+ CProgress( ProgressFunc progressFunc, void *clientData )
+ {
+ define( progressFunc, clientData );
+ mInterruptTimer.start();
+ }
+
+ void define( ProgressFunc progressFunc, void *clientData )
+ {
+ mProgressFunc = progressFunc;
+ mClientData = clientData;
+ }
+
+ void finish( void ) const
+ {
+ if( mProgressFunc == 0 )
+ {
+ return;
+ }
+ SProgressData pd( -1.0 );
+ mProgressFunc( mClientData, pd );
+ }
+
+ bool expired( void )
+ {
+ return( mInterruptTimer.elapsed() > 200 );
+ }
+
+ int step( float fraction )
+ {
+ mInterruptTimer.start();
+
+ if( mProgressFunc == 0 )
+ {
+ return( Err_Success );
+ }
+ SProgressData pd( fraction );
+ int errCode = mProgressFunc( mClientData, pd );
+ return( errCode );
+ }
+
+ int step( int curPage, int maxPage )
+ {
+ mInterruptTimer.start();
+
+ if( mProgressFunc == 0 )
+ {
+ return( Err_Success );
+ }
+ SProgressData pd( curPage, maxPage );
+ int errCode = mProgressFunc( mClientData, pd );
+ return( errCode );
+ }
+
+ private:
+ ProgressFunc mProgressFunc;
+ void *mClientData;
+ QTime mInterruptTimer;
+};
+
+#endif
+
+
diff --git a/khexedit/searchbar.cc b/khexedit/searchbar.cc
new file mode 100644
index 0000000..44d4944
--- /dev/null
+++ b/khexedit/searchbar.cc
@@ -0,0 +1,188 @@
+/*
+ * khexedit - Versatile hex editor
+ * Copyright (C) 2000 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 <klocale.h>
+
+#include "dialog.h"
+#include "hexvalidator.h"
+#include "searchbar.h"
+#include <qpushbutton.h>
+
+// crappy X11 headers
+#undef KeyPress
+
+static const char * close_xpm[] = {
+"16 16 3 1",
+" s None c None",
+". c #ffffff",
+"X c #707070",
+" ",
+" ",
+" .X .X ",
+" .XX .XX ",
+" .XX .XX ",
+" .XX .XX ",
+" .XX.XX ",
+" .XXX ",
+" .XXX ",
+" .XX.XX ",
+" .XX .XX ",
+" .XX .XX ",
+" .XX .XX ",
+" .X .X ",
+" ",
+" "};
+
+CSearchBar::CSearchBar( QWidget *parent, const char *name, WFlags f )
+ :QFrame( parent, name, f )
+{
+ setFrameStyle( QFrame::Panel | QFrame::Raised );
+ setLineWidth( 1 );
+
+ mTypeCombo = new QComboBox( this );
+ connect( mTypeCombo, SIGNAL(activated(int)), SLOT(selectorChanged(int)) );
+ QStringList list;
+ list << i18n("Hex") << i18n("Dec") << i18n("Oct") << i18n("Bin")
+ << i18n("Txt");
+ mTypeCombo->insertStringList( list );
+
+ mInputEdit = new QLineEdit( this );
+ connect( mInputEdit, SIGNAL(textChanged(const QString&)),
+ SLOT(textChanged(const QString&)) );
+ mValidator = new CHexValidator( this, CHexValidator::regularText );
+ mInputEdit->setValidator( mValidator );
+
+ mFindButton = new QPushButton( i18n("Find"), this );
+ mFindButton->setAutoDefault(false);
+ connect( mFindButton, SIGNAL(clicked()), this, SLOT(start()) );
+ connect(mInputEdit,SIGNAL(returnPressed()),mFindButton,SLOT(animateClick()));
+ mFindButton->setFixedHeight( mTypeCombo->sizeHint().height() );
+
+ mBackwards = new QCheckBox( i18n("Backwards"), this );
+ mIgnoreCase = new QCheckBox( i18n("Ignore case"), this );
+
+ mCloseButton = new QPushButton( this );
+ mCloseButton->setAutoDefault(false);
+ mCloseButton->setPixmap( QPixmap( close_xpm ) );
+ connect( mCloseButton, SIGNAL(clicked()), this, SLOT(hideWidget()) );
+
+ //
+ // Make layout
+ //
+ QHBoxLayout *hlay = new QHBoxLayout( this, 4, 6 );
+ hlay->addWidget( mTypeCombo );
+ hlay->addWidget( mInputEdit );
+ hlay->addWidget( mFindButton );
+ hlay->addWidget( mBackwards );
+ hlay->addWidget( mIgnoreCase );
+ hlay->addWidget( mCloseButton );
+
+ //
+ // Read below why I do this.
+ //
+ mInputEdit->installEventFilter( this );
+ selectorChanged(0);
+}
+
+
+//
+// Espen 2000-04-21
+// Qt 2.1: Seems like the QLineEdit::returnPressed() does not work when
+// I install a validator. So I catch the event manually
+//
+bool CSearchBar::eventFilter( QObject *o, QEvent *e )
+{
+ if( o == mInputEdit && e->type() == QEvent::KeyPress )
+ {
+ QKeyEvent *ke = (QKeyEvent*)e;
+ if( ke->key() == Key_Return )
+ {
+ mFindButton->animateClick();
+ return true;
+ }
+ }
+ return QFrame::eventFilter( o, e );
+}
+
+//
+// Seach for te first item each time the curso has moved. Note: The cursor
+// will move when we search and get a match, but (in start() below) the
+// mSearchMode is set to Find_Next after this slot has been called so it
+// will work.
+//
+void CSearchBar::cursorMoved()
+{
+ mSearchMode = Find_First;
+}
+
+
+void CSearchBar::selectorChanged( int index )
+{
+ mValidator->setState( (CHexValidator::EState)index );
+ mInputEdit->setText( mFindString[ index ] );
+ mIgnoreCase->setEnabled( index == 4 ? true : false );
+ mSearchMode = Find_First;
+}
+
+
+void CSearchBar::textChanged( const QString &text )
+{
+ mFindString[ mTypeCombo->currentItem() ] = text;
+ mValidator->convert( mFindData, mFindString[ mTypeCombo->currentItem() ] );
+ mSearchMode = Find_First;
+}
+
+
+void CSearchBar::hideWidget()
+{
+ hide();
+ emit hidden();
+}
+
+
+void CSearchBar::start( void )
+{
+ if( mFindData.isEmpty() == true )
+ {
+ showEntryFailure( this, QString("") );
+ return;
+ }
+
+ SSearchControl sc;
+ sc.key = mFindData;
+ sc.keyType = mTypeCombo->currentItem();
+ sc.fromCursor = true;
+ sc.inSelection = false;
+ sc.forward = !mBackwards->isChecked();
+ sc.ignoreCase = mIgnoreCase->isEnabled() && mIgnoreCase->isChecked();
+ emit findData( sc, mSearchMode, false );
+ mSearchMode = Find_Next;
+}
+
+
+void CSearchBar::showEvent( QShowEvent *e )
+{
+ QFrame::showEvent(e);
+ mInputEdit->setFocus();
+}
+
+
+#include "searchbar.moc"
diff --git a/khexedit/searchbar.h b/khexedit/searchbar.h
new file mode 100644
index 0000000..c11f652
--- /dev/null
+++ b/khexedit/searchbar.h
@@ -0,0 +1,73 @@
+/*
+ * khexedit - Versatile hex editor
+ * Copyright (C) 2000 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.
+ *
+ */
+#ifndef _SEARCHBAR_H_
+#define _SEARCHBAR_H_
+
+#include <qframe.h>
+
+#include "hexbuffer.h"
+
+class QComboBox;
+class QLineEdit;
+class QPushButton;
+class QCheckBox;
+class CHexValidator;
+
+class CSearchBar : public QFrame
+{
+ Q_OBJECT
+
+ public:
+ CSearchBar( QWidget *parent=0, const char *name=0, WFlags f=0 );
+ virtual bool eventFilter( QObject *o, QEvent *e );
+
+ public slots:
+ void cursorMoved();
+
+ protected:
+ virtual void showEvent( QShowEvent * );
+
+ private slots:
+ void hideWidget();
+ void selectorChanged( int index );
+ void textChanged( const QString &text );
+ void start();
+
+ signals:
+ void hidden();
+ void findData( SSearchControl &sc, uint mode, bool navigator );
+
+ private:
+ QPushButton *mCloseButton;
+ QPushButton *mFindButton;
+ QComboBox *mTypeCombo;
+ QLineEdit *mInputEdit;
+ QCheckBox *mBackwards;
+ QCheckBox *mIgnoreCase;
+
+ QString mFindString[5];
+ QByteArray mFindData;
+ CHexValidator *mValidator;
+ uint mSearchMode;
+};
+
+#endif
+
+
diff --git a/khexedit/statusbarprogress.cc b/khexedit/statusbarprogress.cc
new file mode 100644
index 0000000..6e45cf2
--- /dev/null
+++ b/khexedit/statusbarprogress.cc
@@ -0,0 +1,374 @@
+/*
+ * khexedit - Versatile hex editor
+ * Copyright (C) 1999 Espen Sand, espensa@online.no
+ * This file is based on the work by Martynas Kunigelis (KProgress)
+ *
+ * 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 "statusbarprogress.h"
+
+#include <qpainter.h>
+
+#include <kapplication.h>
+#include <kglobalsettings.h>
+#include <klocale.h>
+#include <qstyle.h>
+
+CStatusBarProgress::CStatusBarProgress( QWidget *parent, const char *name )
+ : QFrame(parent, name), QRangeControl(0, 100, 1, 10, 0),
+ mOrientation( Horizontal )
+{
+ initialize();
+}
+
+CStatusBarProgress::CStatusBarProgress( Orientation orientation,
+ QWidget *parent, const char *name )
+ : QFrame(parent, name), QRangeControl(0, 100, 1, 10, 0),
+ mOrientation( orientation )
+{
+ initialize();
+}
+
+CStatusBarProgress::CStatusBarProgress( int minValue, int maxValue, int value,
+ Orientation orientation,
+ QWidget *parent, const char *name )
+ : QFrame(parent, name), QRangeControl(minValue, maxValue, 1, 10, value),
+ mOrientation(orientation)
+{
+ initialize();
+}
+
+CStatusBarProgress::~CStatusBarProgress()
+{
+ delete mBarPixmap;
+}
+
+void CStatusBarProgress::advance( int offset )
+{
+ setValue(value() + offset);
+}
+
+void CStatusBarProgress::initialize( void )
+{
+ mBarPixmap = 0;
+ mBarStyle = Solid;
+
+ mBarColor = palette().active().highlight();
+ mBarTextColor = palette().active().highlightedText();
+ mTextColor = palette().active().text();
+ setBackgroundColor( palette().active().background() );
+
+ QFont font( KGlobalSettings::generalFont() );
+ font.setBold( true );
+ setFont( font );
+
+ mTextEnabled = false;
+ adjustStyle();
+}
+
+
+void CStatusBarProgress::setBarPixmap( const QPixmap &pixmap )
+{
+ if( pixmap.isNull() == true )
+ {
+ return;
+ }
+
+ delete mBarPixmap;
+ mBarPixmap = new QPixmap( pixmap );
+}
+
+void CStatusBarProgress::setBarColor( const QColor &color )
+{
+ mBarColor = color;
+ delete mBarPixmap;
+ mBarPixmap = 0;
+}
+
+void CStatusBarProgress::setBarStyle( BarStyle style )
+{
+ if( mBarStyle != style )
+ {
+ mBarStyle = style;
+ update();
+ }
+}
+
+void CStatusBarProgress::setOrientation( Orientation orientation )
+{
+ if( mOrientation != orientation )
+ {
+ mOrientation = orientation;
+ update();
+ }
+}
+
+void CStatusBarProgress::setValue(int value)
+{
+ mCurPage = mMaxPage = -1;
+ QRangeControl::setValue(value);
+}
+
+void CStatusBarProgress::setValue( int curPage, int maxPage )
+{
+ if( curPage <= 0 || maxPage <= 0 || curPage > maxPage )
+ {
+ mCurPage = mMaxPage = -1;
+ QRangeControl::setValue(0);
+ }
+ else
+ {
+ mCurPage = curPage;
+ mMaxPage = maxPage;
+ float fraction = (float)curPage/(float)maxPage;
+ QRangeControl::setValue( (int)(fraction*100.0) );
+ }
+}
+
+
+void CStatusBarProgress::setTextEnabled( bool state )
+{
+ if( mTextEnabled != state )
+ {
+ mTextEnabled = state;
+ update();
+ }
+}
+
+void CStatusBarProgress::setText( const QString &msg )
+{
+ mMsg = msg;
+ if( mTextEnabled == true )
+ {
+ update();
+ }
+}
+
+
+
+
+const QColor & CStatusBarProgress::barColor( void ) const
+{
+ return( mBarColor );
+}
+
+const QPixmap * CStatusBarProgress::barPixmap( void ) const
+{
+ return( mBarPixmap );
+}
+
+bool CStatusBarProgress::textEnabled( void ) const
+{
+ return( mTextEnabled );
+}
+
+QSize CStatusBarProgress::sizeHint( void ) const
+{
+ QSize s( size() );
+
+ if( orientation() == CStatusBarProgress::Vertical )
+ {
+ s.setWidth( fontMetrics().lineSpacing() );
+ }
+ else
+ {
+ s.setHeight( fontMetrics().lineSpacing() );
+ }
+
+ return( s );
+}
+
+
+CStatusBarProgress::Orientation CStatusBarProgress::orientation( void ) const
+{
+ return( mOrientation );
+}
+
+CStatusBarProgress::BarStyle CStatusBarProgress::barStyle() const
+{
+ return( mBarStyle );
+}
+
+int CStatusBarProgress::recalcValue(int range)
+{
+ int abs_value = value() - minValue();
+ int abs_range = maxValue() - minValue();
+ return range * abs_value / abs_range;
+}
+
+void CStatusBarProgress::valueChange()
+{
+ repaint(contentsRect(), FALSE);
+ emit percentageChanged(recalcValue(100));
+}
+
+void CStatusBarProgress::rangeChange()
+{
+ repaint(contentsRect(), FALSE);
+ emit percentageChanged(recalcValue(100));
+}
+
+void CStatusBarProgress::styleChange( GUIStyle )
+{
+ adjustStyle();
+}
+
+void CStatusBarProgress::adjustStyle( void )
+{
+ switch( style().SH_GUIStyle)
+ {
+ case WindowsStyle:
+ setFrameStyle( QFrame::NoFrame );
+ break;
+
+ case MotifStyle:
+ default:
+ setFrameStyle( QFrame::Panel|QFrame::Sunken );
+ setLineWidth( 1 );
+ break;
+ }
+ update();
+}
+
+void CStatusBarProgress::paletteChange( const QPalette & )
+{
+ mBarColor = palette().active().highlight();
+ mBarTextColor = palette().active().highlightedText();
+ mTextColor = palette().active().text();
+ setBackgroundColor( palette().active().background() );
+}
+
+void CStatusBarProgress::drawText( QPainter *p )
+{
+ QRect r(contentsRect());
+ QString s;
+
+ if( mMsg.isEmpty() == true )
+ {
+ s = QString("%1%").arg(recalcValue(100));
+ }
+ else
+ {
+ if( mCurPage > 0 )
+ {
+ s = i18n("%1... %2 of %3").arg(mMsg).arg(mCurPage).arg(mMaxPage);
+ }
+ else
+ {
+ s = i18n("%1... %2%").arg(mMsg).arg(recalcValue(100));
+ }
+ }
+
+ p->setPen( mTextColor );
+ p->drawText( r, AlignCenter, s );
+ p->setClipRegion( fr );
+ p->setPen( mBarTextColor );
+ p->drawText( r, AlignCenter, s );
+}
+
+void CStatusBarProgress::drawContents(QPainter *p)
+{
+ QRect cr = contentsRect(), er = cr;
+ fr = cr;
+ QBrush fb(mBarColor), eb(backgroundColor() );
+
+ if( mBarPixmap != 0 )
+ {
+ fb.setPixmap( *mBarPixmap );
+ }
+
+ if (backgroundPixmap())
+ eb.setPixmap(*backgroundPixmap());
+
+ switch( mBarStyle )
+ {
+ case Solid:
+ if( mOrientation == Horizontal )
+ {
+ fr.setWidth(recalcValue(cr.width()));
+ er.setLeft(fr.right() + 1);
+ }
+ else
+ {
+ fr.setTop(cr.bottom() - recalcValue(cr.height()));
+ er.setBottom(fr.top() - 1);
+ }
+
+ p->setBrushOrigin(cr.topLeft());
+ p->fillRect(fr, fb);
+ p->fillRect(er, eb);
+
+ if( mTextEnabled == true )
+ drawText(p);
+ break;
+
+ case Blocked:
+ const int margin = 2;
+ int max, num, dx, dy;
+ if( mOrientation == Horizontal )
+ {
+ fr.setHeight(cr.height() - 2 * margin);
+ fr.setWidth((int)(0.67 * fr.height()));
+ fr.moveTopLeft(QPoint(cr.left() + margin, cr.top() + margin));
+ dx = fr.width() + margin;
+ dy = 0;
+ max = (cr.width() - margin) / (fr.width() + margin) + 1;
+ num = recalcValue(max);
+ }
+ else
+ {
+ fr.setWidth(cr.width() - 2 * margin);
+ fr.setHeight((int)(0.67 * fr.width()));
+ fr.moveBottomLeft(QPoint(cr.left() + margin, cr.bottom() - margin));
+ dx = 0;
+ dy = - (fr.height() + margin);
+ max = (cr.height() - margin) / (fr.height() + margin) + 1;
+ num = recalcValue(max);
+ }
+ p->setClipRect(cr.x() + margin, cr.y() + margin,
+ cr.width() - margin, cr.height() - margin);
+ for (int i = 0; i < num; i++)
+ {
+ p->setBrushOrigin(fr.topLeft());
+ p->fillRect(fr, fb);
+ fr.moveBy(dx, dy);
+ }
+
+ if (num != max)
+ {
+ if( mOrientation == Horizontal )
+ er.setLeft(fr.right() + 1);
+ else
+ er.setBottom(fr.bottom() + 1);
+ if (!er.isNull())
+ {
+ p->setBrushOrigin(cr.topLeft());
+ p->fillRect(er, eb);
+ }
+ }
+ break;
+ }
+
+}
+
+
+void CStatusBarProgress::mousePressEvent( QMouseEvent */*e*/ )
+{
+ emit pressed();
+}
+
+#include "statusbarprogress.moc"
diff --git a/khexedit/statusbarprogress.h b/khexedit/statusbarprogress.h
new file mode 100644
index 0000000..ca605f3
--- /dev/null
+++ b/khexedit/statusbarprogress.h
@@ -0,0 +1,159 @@
+/*
+ * khexedit - Versatile hex editor
+ * Copyright (C) 1999 Espen Sand, espensa@online.no
+ * This file is based on the work by Martynas Kunigelis (KProgress)
+ *
+ * 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.
+ *
+ */
+
+#ifndef _STATUSBAR_PROGRESS_H_
+#define _STATUSBAR_PROGRESS_H_
+
+#include <qframe.h>
+#include <qrangecontrol.h>
+
+class CStatusBarProgress : public QFrame, public QRangeControl
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Possible values for orientation
+ */
+ enum Orientation { Horizontal, Vertical };
+
+ /**
+ * Possible values for bar style.
+ *
+ * Solid means one continuous progress bar, Blocked means a
+ * progress bar made up of several blocks.
+ */
+ enum BarStyle { Solid, Blocked };
+
+ /**
+ * Construct a default progress bar. Orientation is horizontal.
+ */
+ CStatusBarProgress(QWidget *parent=0, const char *name=0);
+
+ /**
+ * Construct a KProgress bar with an orientation.
+ */
+ CStatusBarProgress(Orientation, QWidget *parent=0, const char *name=0);
+
+ /**
+ * Construct a KProgress bar with minimum, maximum and initial value.
+ */
+ CStatusBarProgress(int minValue, int maxValue, int value, Orientation,
+ QWidget *parent=0, const char *name=0);
+
+ /**
+ * Destructor
+ */
+ ~CStatusBarProgress( void );
+
+ /**
+ * Set the progress bar style. Allowed values are Solid and Blocked.
+ */
+ void setBarStyle(BarStyle style);
+
+ /**
+ * Set the color of the progress bar.
+ */
+ void setBarColor(const QColor &);
+
+ /**
+ * Set a pixmap to be shown in the progress bar.
+ */
+ void setBarPixmap(const QPixmap &);
+
+ /**
+ * Set the orientation of the progress bar.
+ * Allowed values are Horizonzal and Vertical.
+ */
+ void setOrientation(Orientation);
+
+ /**
+ * Retrieve the bar style.
+ */
+ BarStyle barStyle() const;
+
+ /**
+ * Retrieve the bar color.
+ */
+ const QColor &barColor() const;
+
+ /**
+ * Retrieve the bar pixmap.
+ */
+ const QPixmap *barPixmap() const;
+
+ /**
+ * Retrieve the orientation.
+ */
+ Orientation orientation() const;
+
+ /**
+ * Returns TRUE if progress text will be displayed, FALSE otherwise.
+ */
+ bool textEnabled() const;
+
+ /**
+ * Returns the recommended width for vertical progress bars or
+ * the recommended height for vertical progress bars
+ */
+ virtual QSize sizeHint() const;
+
+
+ public slots:
+ void setValue( int );
+ void setValue( int, int);
+ void advance( int );
+ void setTextEnabled( bool state );
+ void setText( const QString &msg );
+
+ signals:
+ void percentageChanged(int);
+ void pressed( void );
+
+ protected:
+ void valueChange();
+ void rangeChange();
+ void styleChange( GUIStyle );
+ void paletteChange( const QPalette & );
+ void drawContents( QPainter * );
+ void mousePressEvent( QMouseEvent *e );
+
+ private:
+ QPixmap *mBarPixmap;
+ QColor mBarColor;
+ QColor mBarTextColor;
+ QColor mTextColor;
+ QRect fr;
+ BarStyle mBarStyle;
+ Orientation mOrientation;
+ bool mTextEnabled;
+ QString mMsg;
+ int mCurPage;
+ int mMaxPage;
+
+ void initialize( void );
+ int recalcValue( int );
+ void drawText( QPainter * );
+ void adjustStyle( void );
+};
+
+
+#endif
diff --git a/khexedit/stringdialog.cc b/khexedit/stringdialog.cc
new file mode 100644
index 0000000..dff774c
--- /dev/null
+++ b/khexedit/stringdialog.cc
@@ -0,0 +1,412 @@
+/*
+ * khexedit - Versatile hex editor
+ * Copyright (C) 1999-2000 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 <qcheckbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qspinbox.h>
+
+#include <kconfig.h>
+#include <kglobalsettings.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+#include "listview.h"
+#include "stringdialog.h"
+#include <qpushbutton.h>
+
+
+CStringDialog::CStringDialog( QWidget *parent, const char *name, bool modal )
+ : KDialogBase( Plain, i18n("Extract Strings"), Help|User1|Cancel, User1,
+ parent, name, modal, true, i18n("&Update") ),
+ mMaxLength(0), mBusy(false), mDirty(false)
+{
+ setHelp( "khexedit/khexedit.html", QString::null );
+
+ QString text;
+ QVBoxLayout *topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() );
+
+ QGridLayout *glay = new QGridLayout( 3, 3, spacingHint() );
+ topLayout->addLayout( glay );
+ glay->setColStretch( 1, 10 );
+
+ mLengthSpin = new QSpinBox( plainPage() );
+ mLengthSpin->setMinimumWidth( fontMetrics().maxWidth()*17 );
+ mLengthSpin->setRange( 1, 1000000 );
+ mLengthSpin->setValue( 4 );
+ glay->addMultiCellWidget( mLengthSpin, 0, 0, 1, 2 );
+
+ text = i18n("&Minimum length:");
+ QLabel *label = new QLabel( mLengthSpin, text, plainPage() );
+ glay->addWidget( label, 0, 0, AlignRight );
+
+ mFilter = new QLineEdit( plainPage() );
+ mFilter->setMinimumWidth( fontMetrics().maxWidth()*17 );
+ mFilter->setText("*");
+ glay->addWidget( mFilter, 1, 1 );
+
+ text = i18n("&Filter:");
+ label = new QLabel( mFilter, text, plainPage() );
+ glay->addWidget( label, 1, 0, AlignRight );
+
+ QPushButton *useButton = new QPushButton( plainPage(), "use" );
+ useButton->setText( i18n("&Use") );
+ useButton->setAutoDefault( false );
+ connect( useButton, SIGNAL(clicked()),this,SLOT(slotUser1()) );
+ glay->addWidget( useButton, 1, 2 );
+
+ QWidget *helper = new QWidget( plainPage() );
+ glay->addMultiCellWidget( helper, 2, 2, 1, 2 );
+ QHBoxLayout *hlay = new QHBoxLayout( helper, 0, spacingHint() );
+
+ text = i18n("&Ignore case");
+ mIgnoreCaseCheck = new QCheckBox( text, helper );
+ hlay->addWidget( mIgnoreCaseCheck );
+
+ text = i18n("Show offset as &decimal");
+ mOffsetDecimalCheck = new QCheckBox( text, helper );
+ hlay->addWidget( mOffsetDecimalCheck );
+
+ hlay->addStretch(10);
+
+ //
+ // Using listview as suggested by Dima Rogozin <dima@mercury.co.il>
+ //
+ mStringList = new CListView( plainPage(), "stringList" );
+ mStringList->setFont( KGlobalSettings::fixedFont() );
+ mStringList->addColumn( i18n("Offset") );
+ mStringList->addColumn( i18n("String") );
+ mStringList->setAllColumnsShowFocus( true );
+ mStringList->setFrameStyle( QFrame::WinPanel + QFrame::Sunken );
+
+ connect( mStringList, SIGNAL(selectionChanged()),
+ SLOT(selectionChanged()));
+ topLayout->addWidget( mStringList, 10 );
+
+ hlay = new QHBoxLayout( topLayout );
+
+ text = i18n("Number of strings:");
+ label = new QLabel( text, plainPage() );
+ hlay->addWidget( label, AlignLeft );
+
+ mListSizeLabel = new QLabel( QString(), plainPage() );
+ mListSizeLabel->setFixedWidth( fontMetrics().maxWidth()*10 );
+ hlay->addWidget( mListSizeLabel, AlignLeft|AlignHCenter );
+
+ text = i18n("Displayed:");
+ label = new QLabel( text, plainPage() );
+ hlay->addWidget( label, AlignLeft );
+
+ mDisplaySizeLabel = new QLabel( QString(""), plainPage() );
+ mDisplaySizeLabel->setFixedWidth( fontMetrics().maxWidth()*10 );
+ hlay->addWidget( mDisplaySizeLabel, AlignLeft|AlignHCenter);
+
+ hlay->addStretch( 10 );
+
+ mDirtyLabel = new QLabel( plainPage() );
+ topLayout->addWidget( mDirtyLabel );
+
+ readConfiguration();
+
+ //
+ // The initial width of the columns are set in updateListInfo()
+ //
+ updateListInfo();
+ mStringList->setVisibleItem( 15 );
+ startTimer(100);
+}
+
+
+CStringDialog::~CStringDialog( void )
+{
+ writeConfiguration();
+}
+
+
+void CStringDialog::showEvent( QShowEvent *e )
+{
+ KDialogBase::showEvent(e);
+ mLengthSpin->setFocus();
+}
+
+
+void CStringDialog::readConfiguration( void )
+{
+ KConfig &config = *kapp->config();
+ config.setGroup( "String Dialog" );
+
+ mLengthSpin->setValue( config.readNumEntry("MinimumLength", 4) );
+ mFilter->setText( config.readEntry("FilterText", "*") );
+ mIgnoreCaseCheck->setChecked( config.readBoolEntry("IgnoreCase", false) );
+ mOffsetDecimalCheck->setChecked(
+ config.readBoolEntry("OffsetAsDecimal", false ) );
+}
+
+
+void CStringDialog::writeConfiguration( void )
+{
+ KConfig &config = *kapp->config();
+ config.setGroup( "String Dialog" );
+
+ config.writeEntry( "MinimumLength", mLengthSpin->value() );
+ config.writeEntry( "FilterText", mFilter->text() );
+ config.writeEntry( "IgnoreCase", mIgnoreCaseCheck->isChecked() );
+ config.writeEntry( "OffsetAsDecimal", mOffsetDecimalCheck->isChecked() );
+ config.sync();
+}
+
+
+void CStringDialog::slotUser1( void ) // Start
+{
+ if( mBusy == true )
+ {
+ return;
+ }
+
+ mRegExp.setCaseSensitive( mIgnoreCaseCheck->isChecked() == false );
+ mRegExp.setWildcard( true );
+ if( mFilter->text().isEmpty() == true )
+ {
+ mRegExp.setPattern("*");
+ }
+ else
+ {
+ mRegExp.setPattern(mFilter->text());
+ }
+
+ if( mRegExp.isValid() == false )
+ {
+ QString msg = i18n(""
+ "The filter expression you have specified is illegal. "
+ "You must specify a valid regular expression.\n"
+ "Continue without filter?");
+ int reply = KMessageBox::warningContinueCancel( this, msg, i18n("Extract Strings"));
+ if( reply != KMessageBox::Continue )
+ {
+ return;
+ }
+ mRegExp.setPattern( "*");
+ }
+
+
+ mStringData.minLength = mLengthSpin->value();
+ mStringData.decimalOffset = mOffsetDecimalCheck->isChecked();
+
+ removeList();
+
+ mBusy = true;
+ emit collect();
+ mBusy = false;
+}
+
+
+void CStringDialog::startGoto( QListViewItem *item )
+{
+ QString str_offset = item->text(0);
+ QString string = item->text(1);
+
+ uint offset;
+ if( stringData().decimalOffset == true )
+ {
+ // sscanf( str_offset.ascii(), "%u", &offset );
+ offset = str_offset.toInt();
+ }
+ else
+ {
+ uint val1,val2;
+ // #### Rewrite it do it doesn't need the .ascii() call
+ sscanf( str_offset.ascii(), "%X:%X", &val1, &val2 );
+ offset = (val1<<16) + val2;
+ }
+
+ uint size = string.length();
+
+ emit markText( offset, size, true );
+}
+
+
+void CStringDialog::setDirty( void )
+{
+ if( mDirty == true )
+ {
+ return;
+ }
+
+ mDirtyLabel->setText(
+ i18n("Warning: Document has been modified since last update"));
+ mDirty = true;
+}
+
+
+void CStringDialog::setClean( void )
+{
+ if( mDirty == false )
+ {
+ return;
+ }
+
+ mDirtyLabel->setText("");
+ mDirty = false;
+}
+
+
+void CStringDialog::selectionChanged()
+{
+ killTimers();
+ startTimer( 200 );
+}
+
+
+void CStringDialog::timerEvent( QTimerEvent * )
+{
+ killTimers();
+
+ QListViewItem *item = mStringList->currentItem();
+ if( item == 0 )
+ {
+ slotUser1();
+ return;
+ }
+ startGoto( item );
+}
+
+
+void CStringDialog::resizeEvent( QResizeEvent * )
+{
+ setColumnWidth();
+}
+
+
+
+int CStringDialog::updateList( CProgress &p )
+{
+ clearList();
+ enableList( false );
+
+ int offsetLen = stringData().offsetLen();
+
+ QPtrList<QString> &list = stringData().list();
+ for( const QString *str = list.first(); str != 0; str = list.next() )
+ {
+ appendListItem( *str, offsetLen );
+ mMaxLength = QMAX( mMaxLength, str->length() );
+
+ if( p.expired() == true )
+ {
+ int errCode = p.step( (float)list.at()/(float)list.count() );
+ if( errCode == Err_Stop )
+ {
+ p.finish();
+ return( Err_Success );
+ }
+ }
+ }
+
+ p.finish();
+ updateListInfo();
+ enableList( true );
+
+ return( Err_Success );
+}
+
+
+
+
+void CStringDialog::clearList( void )
+{
+ if( mStringList->childCount() > 0 )
+ {
+ mStringList->clear();
+ mStringList->update();
+ }
+ mMaxLength = 0;
+
+ updateListInfo();
+ setClean();
+}
+
+
+void CStringDialog::removeList( void )
+{
+ mStringData.clear();
+ clearList();
+}
+
+
+void CStringDialog::enableList( bool state )
+{
+ mStringList->setEnabled( state );
+ if( state == true )
+ {
+ mStringList->update();
+ }
+}
+
+
+void CStringDialog::appendListItem( const QString &str, uint offsetLen )
+{
+ if( mRegExp.search ( str, offsetLen ) != -1 )
+ {
+ new QListViewItem( mStringList, str.left(offsetLen), str.mid(offsetLen) );
+ }
+}
+
+
+void CStringDialog::updateListInfo( void )
+{
+ mListSizeLabel->setText( QString("%1").arg(mStringData.count()) );
+ mDisplaySizeLabel->setText( QString("%1").arg(mStringList->childCount()) );
+ setColumnWidth();
+}
+
+
+
+void CStringDialog::setColumnWidth( void )
+{
+ const QFontMetrics &fm = mStringList->fontMetrics();
+
+ if( mStringData.count() == 0 )
+ {
+ int w1 = fm.maxWidth() * (stringData().offsetLen() + 2);
+ int w2 = mStringList->viewport()->width() - w1;
+ mStringList->setColumnWidth( 0, w1 );
+ mStringList->setColumnWidth( 1, w2 );
+ }
+ else
+ {
+ int w1 = fm.maxWidth() * (stringData().offsetLen() + 2);
+ int w2 = fm.maxWidth() * mMaxLength - w1;
+ if( w2 < 0 )
+ {
+ w2 = mStringList->viewport()->width() - w1;
+ }
+
+ mStringList->setColumnWidth( 0, w1 );
+ mStringList->setColumnWidth( 1, w2 );
+ }
+}
+
+
+
+
+
+
+#include "stringdialog.moc"
diff --git a/khexedit/stringdialog.h b/khexedit/stringdialog.h
new file mode 100644
index 0000000..ec731e4
--- /dev/null
+++ b/khexedit/stringdialog.h
@@ -0,0 +1,110 @@
+/*
+ * khexedit - Versatile hex editor
+ * Copyright (C) 1999-2000 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.
+ *
+ */
+
+#ifndef _STRING_DIALOG_H_
+#define _STRING_DIALOG_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+class QCheckBox;
+class QLabel;
+class QLineEdit;
+class QListView;
+class QSpinBox;
+
+#include <qregexp.h>
+#include <kdialogbase.h>
+
+class CListView;
+#include "hexbuffer.h"
+#include "progress.h"
+
+class CStringDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ CStringDialog( QWidget *parent=0, const char *name = 0, bool modal=false );
+ ~CStringDialog( void );
+
+ int updateList( CProgress &p );
+ inline CStringCollectControl &stringData( void );
+
+ signals:
+ void markText( uint offset, uint size, bool moveCursor );
+ void collect( void );
+
+ public slots:
+ void clearList( void ); // Removes list entries
+ void removeList( void ); // Removes list entries and the string list.
+ void setDirty( void );
+ void setClean( void );
+
+ protected slots:
+ virtual void slotUser1( void );
+ virtual void startGoto( QListViewItem * );
+ virtual void selectionChanged( );
+
+ protected:
+ virtual void timerEvent( QTimerEvent *e );
+ virtual void resizeEvent( QResizeEvent *e );
+ virtual void showEvent( QShowEvent *e );
+
+ private:
+ void enableList( bool state );
+ void appendListItem( const QString &str, uint offsetSize );
+ void updateListInfo( void );
+ void setColumnWidth( void );
+ void readConfiguration( void );
+ void writeConfiguration( void );
+
+ private:
+ CStringCollectControl mStringData;
+ QRegExp mRegExp;
+ uint mMaxLength;
+ bool mBusy;
+ bool mDirty;
+
+ QSpinBox *mLengthSpin;
+ QLineEdit *mFilter;
+ QCheckBox *mIgnoreCaseCheck;
+ QCheckBox *mOffsetDecimalCheck;
+ CListView *mStringList;
+ QLabel *mListSizeLabel;
+ QLabel *mDisplaySizeLabel;
+ QLabel *mDirtyLabel;
+};
+
+
+CStringCollectControl &CStringDialog::stringData( void )
+{
+ return( mStringData );
+}
+
+#endif
+
+
+
+
+
+
+
diff --git a/khexedit/toplevel.cc b/khexedit/toplevel.cc
new file mode 100644
index 0000000..733173e
--- /dev/null
+++ b/khexedit/toplevel.cc
@@ -0,0 +1,1366 @@
+/*
+ * khexedit - Versatile hex editor
+ * Copyright (C) 1999-2000 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.
+ *
+ */
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
+
+#include <qptrlist.h>
+#include <qsignalmapper.h>
+#include <qtimer.h>
+#include <qtooltip.h>
+
+#include <kaction.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kstatusbar.h>
+#include <kpopupmenu.h>
+#include <kstdaction.h>
+#include <ktoolbarbutton.h>
+#include <kdebug.h>
+#include <kurl.h>
+#include <kurldrag.h>
+
+#include "dialog.h"
+#include "draglabel.h"
+#include "hexerror.h"
+#include "toplevel.h"
+
+
+QPtrList<KHexEdit> KHexEdit::mWindowList;
+
+KHexEdit::KHexEdit( void )
+ : KMainWindow(0, "toplevel"), mStartupOffset(0),
+ mIsModified(0)
+{
+ mWindowList.append( this );
+
+ //
+ // Create main widget and register it.
+ //
+ mManager = new CHexManagerWidget( this, "manager" );
+ setCentralWidget( mManager );
+
+ //
+ // I use an eventfilter to catch all drag/drop events for the
+ // area outside the editor window. It will only accept KURLDrag.
+ // (The editor window will catch KURLDrag, QTextDrag and CHexDrag)
+ //
+ installEventFilter( this );
+ setAcceptDrops(true);
+
+ //
+ // Prepare menus and status bar
+ //
+ mAction.bookmarkMapper = new QSignalMapper(this);
+ connect(mAction.bookmarkMapper, SIGNAL(mapped(int)), editor(), SLOT(gotoBookmark(int)));
+ setupActions();
+ setupStatusBar();
+
+ connect( hexView(), SIGNAL( cursorChanged( SCursorState & ) ),
+ this, SLOT( cursorChanged( SCursorState & ) ) );
+ connect( hexView(), SIGNAL( editMode( CHexBuffer::EEditMode ) ),
+ this, SLOT( editMode( CHexBuffer::EEditMode ) ) );
+ connect( hexView(), SIGNAL( encodingChanged( const SEncodeState &)),
+ this, SLOT( encodingChanged( const SEncodeState & )) );
+ connect( hexView(), SIGNAL( textWidth( uint ) ),
+ this, SLOT( textWidth( uint ) ) );
+ connect( hexView(), SIGNAL( fileState( SFileState & ) ),
+ this, SLOT( fileState( SFileState & ) ) );
+ connect( hexView(), SIGNAL( layoutChanged( const SDisplayLayout & ) ),
+ this, SLOT( layoutChanged( const SDisplayLayout & ) ) );
+ connect( hexView(), SIGNAL( inputModeChanged( const SDisplayInputMode & ) ),
+ this, SLOT( inputModeChanged( const SDisplayInputMode & ) ) );
+ connect( hexView(), SIGNAL( bookmarkChanged( QPtrList<SCursorOffset> &)),
+ this, SLOT( bookmarkChanged( QPtrList<SCursorOffset> & ) ) );
+ connect( hexView(), SIGNAL( fileName( const QString &, bool ) ),
+ this, SLOT( fileActive( const QString &, bool ) ) );
+ connect( hexView(), SIGNAL( fileRename( const QString &, const QString & )),
+ this, SLOT( fileRename( const QString &, const QString & ) ) );
+ connect( hexView(), SIGNAL( fileClosed( const QString & ) ),
+ this, SLOT( fileClosed( const QString & ) ) );
+ connect( editor(), SIGNAL( errorLoadFile( const QString & ) ),
+ this, SLOT( removeRecentFile( const QString & ) ) );
+ connect( editor(), SIGNAL( operationChanged( bool ) ),
+ this, SLOT( operationChanged( bool ) ) );
+ connect( editor(), SIGNAL( removeRecentFiles() ),
+ this, SLOT( removeRecentFiles() ) );
+ connect( mManager, SIGNAL( conversionClosed() ),
+ this, SLOT(conversionClosed()) );
+ connect( mManager, SIGNAL( searchBarClosed() ),
+ this, SLOT(searchBarClosed()) );
+
+ //
+ // Read configuration from file and set the default editor size.
+ // Open files if this is the first toplevel window.
+ //
+ readConfiguration();
+ initialize( mWindowList.count() == 1 ? true : false );
+ setAutoSaveSettings();
+}
+
+
+KHexEdit::~KHexEdit( void )
+{
+ delete mAction.bookmarkMapper;
+ delete mManager;
+}
+
+
+void KHexEdit::setupActions( void )
+{
+ KStdAction::openNew( editor(), SLOT(newFile()), actionCollection() );
+ KStdAction::open( editor(), SLOT(open()), actionCollection() );
+ KStdAction::keyBindings(guiFactory(), SLOT(configureShortcuts()),
+actionCollection());
+
+ mAction.insert = new KAction( i18n("&Insert..."), CTRL+Key_I,
+ editor(), SLOT(insertFile()), actionCollection(), "insert_file" );
+ mAction.openRecent = KStdAction::openRecent( this, SLOT( slotFileOpenRecent( const KURL& ) ), actionCollection() );
+ mAction.save = KStdAction::save( editor(), SLOT(save()), actionCollection() );
+ mAction.saveAs = KStdAction::saveAs( editor(), SLOT(saveAs()), actionCollection() );
+ mAction.revert = KStdAction::revert( editor(), SLOT(reload()), actionCollection() );
+ //mAction.revert = KStdAction::revert( this, SLOT(resizeTest()), actionCollection() );
+
+ mAction.close = KStdAction::close( editor(), SLOT(close()), actionCollection() );
+ mAction.print = KStdAction::print( editor(), SLOT(print()), actionCollection() );
+ mAction.exportData = new KAction( i18n("E&xport..."), 0,
+ editor(), SLOT(exportDialog()), actionCollection(), "export" );
+ mAction.cancel = new KAction( i18n("&Cancel Operation"),
+ "stop", 0, editor(), SLOT(stop()), actionCollection(), "cancel" );
+ mAction.readOnly = new KToggleAction( i18n("&Read Only"),
+ 0, editor(), SLOT(toggleWriteProtection()),actionCollection(), "read_only" );
+ mAction.resizeLock = new KToggleAction( i18n("&Allow Resize"),
+ 0, editor(), SLOT(toggleResizeLock()),actionCollection(), "resize_lock" );
+ mAction.newWindow = new KAction( i18n("N&ew Window"),
+ 0, this, SLOT(newWindow()),actionCollection(), "new_window" );
+ mAction.closeWindow= new KAction( i18n("Close &Window"),
+ 0, this, SLOT(closeWindow()),actionCollection(), "close_window" );
+ mAction.quit = KStdAction::quit( this, SLOT(closeProgram()), actionCollection() );
+
+ mAction.undo = KStdAction::undo( editor(), SLOT(undo()), actionCollection() );
+ mAction.redo = KStdAction::redo( editor(), SLOT(redo()), actionCollection() );
+ mAction.cut = KStdAction::cut( editor(), SLOT(cut()), actionCollection() );
+ mAction.copy = KStdAction::copy( editor(), SLOT(copy()), actionCollection() );
+ mAction.paste = KStdAction::paste( editor(), SLOT(paste()), actionCollection() );
+ mAction.selectAll = KStdAction::selectAll(editor(), SLOT(selectAll()),actionCollection() );
+ mAction.unselect = KStdAction::deselect(editor(), SLOT(unselect()), actionCollection());
+ mAction.find = KStdAction::find( editor(), SLOT(find()), actionCollection() );
+ mAction.findNext = KStdAction::findNext(editor(), SLOT(findNext()), actionCollection() );
+ mAction.findPrev = KStdAction::findPrev(editor(),SLOT(findPrevious()),actionCollection() );
+ mAction.replace = KStdAction::replace( editor(), SLOT(replace()), actionCollection() );
+ mAction.gotoOffset = new KAction( i18n("&Goto Offset..."), CTRL+Key_G,
+ editor(), SLOT(gotoOffset()),actionCollection(), "goto_offset" );
+ mAction.insertPattern = new KAction( i18n("&Insert Pattern..."), CTRL+Key_Insert,
+ editor(), SLOT(insertPattern()), actionCollection(), "insert_pattern" );
+
+ mAction.copyAsText = new KAction( i18n("Copy as &Text"), 0,
+ editor(), SLOT(copyText()), actionCollection(), "copy_as_text" );
+ mAction.pasteToNewFile = new KAction( i18n("Paste into New &File"), 0,
+ editor(), SLOT(pasteNewFile()), actionCollection(), "paste_into_new_file" );
+ mAction.pasteToNewWindow = new KAction( i18n("Paste into New &Window"), 0,
+ this, SLOT(pasteNewWindow()), actionCollection(), "paste_into_new_window" );
+
+ mAction.hexadecimal = new KRadioAction( i18n("&Hexadecimal"),
+ 0, this, SLOT(setDisplayMode()), actionCollection(), "mode_hex" );
+ mAction.decimal = new KRadioAction( i18n("&Decimal"),
+ 0, this, SLOT(setDisplayMode()), actionCollection(), "mode_dec" );
+ mAction.octal = new KRadioAction( i18n("&Octal"),
+ 0, this, SLOT(setDisplayMode()), actionCollection(), "mode_oct" );
+ mAction.binary = new KRadioAction( i18n("&Binary"),
+ 0, this, SLOT(setDisplayMode()), actionCollection(), "mode_bin" );
+ mAction.textOnly = new KRadioAction( i18n("&Text"),
+ 0, this, SLOT(setDisplayMode()), actionCollection(), "mode_text" );
+ mAction.hexadecimal->setExclusiveGroup( "displayMode" );
+ mAction.decimal->setExclusiveGroup( "displayMode" );
+ mAction.octal->setExclusiveGroup( "displayMode" );
+ mAction.binary->setExclusiveGroup( "displayMode" );
+ mAction.textOnly->setExclusiveGroup( "displayMode" );
+
+ mAction.showOffsetColumn = new KToggleAction( i18n("Show O&ffset Column"),
+ 0, editor(), SLOT(toggleOffsetColumnVisibility()),actionCollection(), "show_offset_column" );
+ mAction.showTextColumn = new KToggleAction( i18n("Show Te&xt Field"),
+ 0, editor(), SLOT(toggleTextColumnVisibility()),actionCollection(), "show_text_field" );
+ mAction.offsetAsDecimal = new KToggleAction( i18n("Off&set as Decimal"),
+ 0, editor(), SLOT(toggleOffsetAsDecimal()),actionCollection(), "offset_as_decimal" );
+ mAction.dataUppercase = new KToggleAction( i18n("&Upper Case (Data)"),
+ 0, editor(), SLOT(toggleDataUppercase()),actionCollection(), "upper_case_data" );
+ mAction.offsetUppercase = new KToggleAction( i18n("Upper &Case (Offset)"),
+ 0, editor(), SLOT(toggleOffsetUppercase()),actionCollection(), "upper_case_offset" );
+
+ mAction.defaultEncoding = new KRadioAction( i18n("&Default encoding", "&Default"),
+ 0, this, SLOT( setEncoding()), actionCollection(), "enc_default" );
+ mAction.usAsciiEncoding = new KRadioAction( i18n("US-&ASCII (7 bit)"),
+ 0, this, SLOT( setEncoding()), actionCollection(), "enc_ascii");
+ mAction.ebcdicEncoding = new KRadioAction( i18n("&EBCDIC"),
+ 0, this, SLOT( setEncoding()), actionCollection(), "enc_ebcdic" );
+// mAction.customEncoding = new KAction( i18n("&Custom..."),
+// 0, editor(), SLOT( encoding()), actionCollection(), "enc_custom" );
+ mAction.defaultEncoding->setExclusiveGroup( "encodingMode" );
+ mAction.usAsciiEncoding->setExclusiveGroup( "encodingMode" );
+ mAction.ebcdicEncoding->setExclusiveGroup( "encodingMode" );
+
+ mAction.strings = new KAction( i18n("&Extract Strings..."), 0,
+ editor(), SLOT(strings()), actionCollection(), "extract_strings" );
+// mAction.recordViewer = new KAction( i18n("&Record Viewer"), 0,
+// editor(), SLOT(recordView()), actionCollection(), "record_viewer" );
+ mAction.filter = new KAction( i18n("&Binary Filter..."), 0,
+ editor(), SLOT(filter()), actionCollection(), "binary_filter" );
+ mAction.characterTable = new KAction( i18n("&Character Table"), 0,
+ editor(), SLOT(chart()), actionCollection(), "char_table" );
+ mAction.converter = new KAction( i18n("C&onverter"), 0,
+ editor(), SLOT(converter()), actionCollection(), "converter" );
+ mAction.statistics = new KAction( i18n("&Statistics"), 0,
+ editor(), SLOT(statistics()), actionCollection(), "statistics" );
+
+ mAction.addBookmark = KStdAction::addBookmark( editor(),
+ SLOT(addBookmark()), actionCollection() );
+ mAction.replaceBookmark = new KAction( i18n("&Replace Bookmark"), CTRL+Key_E,
+ editor(), SLOT(replaceBookmark()), actionCollection(), "replace_bookmark");
+ mAction.removeBookmark = new KAction( i18n("R&emove Bookmark"), CTRL+Key_U,
+ editor(), SLOT(removeBookmark()), actionCollection(), "remove_bookmark" );
+ mAction.removeAllBookmark = new KAction( i18n("Re&move All"), 0,
+ editor(), SLOT(removeAllBookmark()), actionCollection(), "remove_all_bookmarks" );
+ mAction.nextBookmark = new KAction( i18n("Goto &Next Bookmark"),
+ ALT+Key_Down, editor(),
+ SLOT(gotoNextBookmark()), actionCollection(), "next_bookmark" );
+ mAction.prevBookmark = new KAction( i18n("Goto &Previous Bookmark"),
+ ALT+Key_Up, editor(),
+ SLOT(gotoPrevBookmark()), actionCollection(), "prev_bookmark" );
+
+ createStandardStatusBarAction();
+ setStandardToolBarMenuEnabled(true);
+ mAction.showFullPath = new KToggleAction( i18n("Show F&ull Path"),
+ 0, this, SLOT(showFullPath()), actionCollection(), "show_full_path" );
+
+ mAction.tabHide = new KRadioAction( i18n("&Hide"),
+ 0, this, SLOT(showDocumentTabs()), actionCollection(), "doctab_hide" );
+ mAction.tabShowAboveEditor = new KRadioAction( i18n("&Above Editor"),
+ 0, this, SLOT(showDocumentTabs()), actionCollection(), "doctab_above" );
+ mAction.tabShowBelowEditor = new KRadioAction( i18n("&Below Editor"),
+ 0, this, SLOT(showDocumentTabs()), actionCollection(), "doctab_below" );
+ mAction.tabHide->setExclusiveGroup( "editorTab" );
+ mAction.tabShowAboveEditor->setExclusiveGroup( "editorTab" );
+ mAction.tabShowBelowEditor->setExclusiveGroup( "editorTab" );
+
+ mAction.conversionHide = new KRadioAction( i18n("&Hide"),
+ 0, this, SLOT(showConversionField()), actionCollection(), "conversion_field_hide");
+ mAction.conversionFloat = new KRadioAction( i18n("&Floating"),
+ 0, this, SLOT(showConversionField()), actionCollection(), "conversion_field_float");
+ mAction.conversionEmbed = new KRadioAction( i18n("&Embed in Main Window"),
+ 0, this, SLOT(showConversionField()), actionCollection(), "conversion_field_embed");
+ mAction.conversionHide->setExclusiveGroup( "conversionField" );
+ mAction.conversionFloat->setExclusiveGroup( "conversionField" );
+ mAction.conversionEmbed->setExclusiveGroup( "conversionField" );
+
+ mAction.searchHide = new KRadioAction( i18n("&Hide"),
+ 0, this, SLOT(showSearchBar()), actionCollection(), "searchbar_hide" );
+ mAction.searchShowAboveEditor = new KRadioAction( i18n("&Above Editor"),
+ Key_F5, this, SLOT(showSearchBar()), actionCollection(), "searchbar_above" );
+ mAction.searchShowBelowEditor = new KRadioAction( i18n("&Below Editor"),
+ Key_F6, this, SLOT(showSearchBar()), actionCollection(), "searchbar_below" );
+ mAction.searchHide->setExclusiveGroup( "searchBar" );
+ mAction.searchShowAboveEditor->setExclusiveGroup( "searchBar" );
+ mAction.searchShowBelowEditor->setExclusiveGroup( "searchBar" );
+
+ KStdAction::saveOptions(this, SLOT(writeConfiguration()), actionCollection());
+ KStdAction::preferences(editor(),SLOT(options()),actionCollection() );
+// mAction.favorites = new KAction( i18n("P&rofiles..."), 0,
+// editor(), SLOT(favorites()), actionCollection(), "favorites" );
+
+ KStdAction::help( this, SLOT(appHelpActivated()), actionCollection() );
+
+ mDragLabel = new CDragLabel(this);
+ mDragLabel->setPixmap( UserIcon( "hexdrag" ) );
+ mDragLabel->setDragMask( UserIcon( "hexmask" ) );
+ mDragLabel->setEnabled( false ); // Enabled once we open a document
+ QToolTip::add( mDragLabel, i18n("Drag document") );
+ (void) new KWidgetAction(mDragLabel, i18n("Drag Document"), 0, editor(), SLOT(options()), actionCollection(), "drag_document");
+
+ createGUI("khexeditui.rc", false);
+
+ QPopupMenu *popup = (QPopupMenu *)factory()->container("editor_popup", this);
+ hexView()->setPopupMenu( popup );
+
+ int id = 100;
+ toolBar(0)->insertButton( MainBarIcon("lock"), id, SIGNAL(clicked()),
+ editor(), SLOT(toggleWriteProtection()), true,
+ i18n("Toggle write protection") );
+ toolBar(0)->alignItemRight( id );
+ mWriteProtectButton = toolBar(0)->getButton(id);
+
+ QPopupMenu *documentMenu = (QPopupMenu *)factory()->container("documents", this);
+ hexView()->setDocumentMenu(documentMenu);
+ connect(documentMenu, SIGNAL(activated(int)), SLOT(documentMenuCB(int)));
+
+}
+
+
+void KHexEdit::setupStatusBar( void )
+{
+ CStatusBarProgress *progess = new CStatusBarProgress( statusBar() );
+ statusBar()->addWidget( progess, 10 );
+ connect( progess, SIGNAL(pressed()), editor(), SLOT(stop()) );
+ connect( editor(), SIGNAL( setProgress( int ) ),
+ progess, SLOT( setValue( int ) ) );
+ connect( editor(), SIGNAL( setProgress( int, int ) ),
+ progess, SLOT( setValue( int, int ) ) );
+ connect( editor(), SIGNAL( enableProgressText( bool ) ),
+ progess, SLOT( setTextEnabled( bool ) ) );
+ connect( editor(), SIGNAL( setProgressText( const QString & ) ),
+ progess, SLOT( setText( const QString & ) ) );
+
+ statusBar()->insertFixedItem( i18n("Selection: 0000:0000 0000:0000"),
+ status_Selection );
+ statusBar()->insertFixedItem( i18n("M"), status_Modified );
+ statusBar()->insertFixedItem( i18n("OVR"), status_Ovr );
+ statusBar()->insertFixedItem( i18n("Size: FFFFFFFFFF"), status_Size );
+ statusBar()->insertFixedItem( i18n("Offset: FFFFFFFFFF-F"), status_Offset );
+ statusBar()->insertFixedItem( i18n("FFF"), status_Layout );
+ statusBar()->insertFixedItem( i18n("RW"), status_WriteProtect );
+
+ statusBar()->setItemAlignment( status_Selection, AlignLeft|AlignVCenter );
+ statusBar()->setItemAlignment( status_Size, AlignLeft|AlignVCenter );
+ statusBar()->setItemAlignment( status_Offset, AlignLeft|AlignVCenter );
+
+ //
+ // Some good default strings we can use after the fields have got
+ // their fixed width.
+ //
+ statusBar()->changeItem( i18n("Offset:"), status_Offset );
+ statusBar()->changeItem( i18n("Size:"), status_Size );
+ statusBar()->changeItem( "", status_Modified );
+ statusBar()->changeItem( "", status_Selection );
+ connect( statusBar(),SIGNAL(pressed(int)),this,SLOT(statusBarPressed(int)) );
+}
+
+
+void KHexEdit::removeRecentFiles( void )
+{
+ mAction.openRecent->clearURLList();
+}
+
+
+void KHexEdit::initialize( bool openFiles )
+{
+ mUndoState = CHexBuffer::UndoOk; // Reset in function below
+ setUndoState( 0 );
+
+ mSelectionOffset = 0;
+ mSelectionSize = 1;
+ mSelectionAsHexadecimal = true;
+ setSelectionState( 0, 0 );
+
+ operationChanged( false );
+
+ editor()->initialize();
+
+ mAction.showFullPath->setChecked( mShowFullPath );
+ showFullPath();
+
+ if ( openFiles && editor()->openFile() != SDisplayMisc::none )
+ {
+ // Code modified from kdelibs/kdeui/kactionclasses.cpp KRecentFilesAction::loadEntries
+
+ KConfig* config = kapp->config();
+
+ const QString oldGroup = config->group();
+
+ const QString groupname = "RecentFiles";
+ config->setGroup( groupname );
+
+ // read file list
+ unsigned int maxItems = mAction.openRecent->maxItems();
+ if ( editor()->openFile() == SDisplayMisc::mostRecent )
+ maxItems = 1;
+ for( unsigned int i = 1 ; i <= maxItems ; i++ )
+ {
+ const QString key = QString( "File%1" ).arg( i );
+ const QString value = config->readPathEntry( key );
+
+ if (!value.isEmpty())
+ {
+ mStartupFileList.append( value );
+ mStartupOffsetList.append( "0" ); // ### TODO find a way to still have kept offsets
+ }
+ }
+
+ config->setGroup( oldGroup );
+
+ }
+
+ //
+ // Open file(s) after editor has been displayed.
+ // Main reason: If anything goes wrong and an error dialog box
+ // is displayed, then the editor will not be visible until the error
+ // is confirmed and the (modal) dialog is closed.
+ //
+ QTimer::singleShot( 100, this, SLOT(delayedStartupOpen()) );
+}
+
+
+void KHexEdit::delayedStartupOpen( void )
+{
+ open( mStartupFileList, mStartupOffsetList );
+ mStartupFileList.clear();
+ mStartupOffsetList.clear();
+}
+
+
+void KHexEdit::statusBarPressed( int id )
+{
+ if( id == status_WriteProtect )
+ {
+ editor()->toggleWriteProtection();
+ }
+ else if( id == status_Ovr )
+ {
+ editor()->toggleInsertMode();
+ }
+ else if( id == status_Offset )
+ {
+ editor()->toggleOffsetAsDecimal();
+ }
+ else if( id == status_Selection )
+ {
+ if( mSelectionSize > 0 )
+ {
+ mSelectionAsHexadecimal = mSelectionAsHexadecimal == true ? false : true;
+ setSelectionText( mSelectionOffset, mSelectionSize );
+ }
+ }
+
+}
+
+
+
+void KHexEdit::open( QStringList &fileList, QStringList &offsetList )
+{
+ //
+ // We load in reverse to allow the first document in
+ // the list to become the active one.
+ //
+
+ uint offset;
+ for( uint i = fileList.count(); i>0; i-- )
+ {
+ if( i <= offsetList.count() )
+ {
+ offset = (*offsetList.at(i-1)).toUInt(0,16);
+ }
+ else
+ {
+ offset = 0;
+ }
+ editor()->open( *fileList.at(i-1), true, offset );
+ }
+}
+
+void KHexEdit::addRecentFile( const QString &fileName )
+{
+ if( fileName.isEmpty() == true )
+ {
+ return;
+ }
+
+ if( fileName.contains( i18n( "Untitled" ), false ) )
+ {
+ return;
+ }
+
+ const KURL url( KURL::fromPathOrURL( fileName ) );
+ kdDebug(1501) << k_funcinfo << " adding recent " << fileName << " => " << url.prettyURL() << endl;
+ mAction.openRecent->addURL( url );
+
+}
+
+
+void KHexEdit::removeRecentFile( const QString &fileName )
+{
+ if( fileName.isEmpty() == true )
+ {
+ return;
+ }
+
+ if( fileName.contains( i18n( "Untitled" ), false ) )
+ {
+ return;
+ }
+
+ const KURL url( KURL::fromPathOrURL( fileName ) );
+ mAction.openRecent->removeURL( url );
+
+}
+
+
+void KHexEdit::renameRecentFile(const QString &curName, const QString &newName)
+{
+ if( curName.contains( i18n( "Untitled" ), false ) )
+ {
+ addRecentFile( newName );
+ }
+ else
+ {
+ mAction.openRecent->removeURL( KURL::fromPathOrURL( curName ) );
+ mAction.openRecent->addURL( KURL::fromPathOrURL( newName ) );
+ }
+}
+
+
+
+void KHexEdit::slotFileOpenRecent( const KURL& url )
+{
+ if ( url.isLocalFile() )
+ {
+ editor()->open( url.path(), false, 0 );
+ }
+ else
+ {
+ // ### TODO: support network transparency
+ KMessageBox::error( this, i18n("Non local recent file: %1").arg( url.prettyURL() ) );
+ }
+}
+
+
+KHexEdit *KHexEdit::newWindow( void )
+{
+ KHexEdit *hexEdit = new KHexEdit;
+ if( hexEdit == 0 )
+ {
+ QString msg = i18n( "Can not create new window.\n" );
+ msg += hexError( Err_NoMemory );
+ KMessageBox::error( topLevelWidget(), msg );
+ return(0);
+ }
+ hexEdit->show();
+ return(hexEdit);
+}
+
+
+
+void KHexEdit::pasteNewWindow( void )
+{
+ KHexEdit *app = newWindow();
+ if( app != 0 )
+ {
+ app->editor()->pasteNewFile();
+ }
+}
+
+
+
+void KHexEdit::closeWindow( void )
+{
+ close();
+}
+
+
+void KHexEdit::closeProgram( void )
+{
+ if( mWindowList.count() > 1 )
+ {
+ for( KHexEdit *w = mWindowList.first(); w != 0; w = mWindowList.next() )
+ {
+ if( w->editor()->modified() == true )
+ {
+ QString msg = i18n(""
+ "There are windows with unsaved modified documents. "
+ "If you quit now, these modifications will be lost.");
+ int reply = KMessageBox::warningContinueCancel( topLevelWidget(), msg, QString::null, KStdGuiItem::quit() );
+ if( reply == KMessageBox::Continue )
+ {
+ break;
+ }
+ else
+ {
+ return;
+ }
+ }
+ }
+
+
+ //
+ // Ths will write current configuration to disk.
+ //
+ queryExit();
+
+ //
+ // Make sure every widget is destroyed. The reason why I do this
+ // (besides it is the clean way to do it) is to make sure any
+ // configuration updates in the various destructors are triggered.
+ //
+ mWindowList.setAutoDelete(true);
+ while( mWindowList.first() )
+ {
+ mWindowList.removeRef( mWindowList.first() );
+ }
+
+ kapp->quit();
+ }
+ else
+ {
+ closeWindow();
+ }
+
+}
+
+
+bool KHexEdit::queryClose( void )
+{
+ bool success = editor()->closeAll();
+ if( success == true )
+ {
+ mWindowList.removeRef( this );
+ }
+
+ return( success );
+}
+
+
+//
+// We will always return true here.
+//
+bool KHexEdit::queryExit( void )
+{
+ writeConfiguration();
+ return( true );
+}
+
+void KHexEdit::readConfiguration( void )
+{
+ KConfig &config = *kapp->config();
+ readConfiguration( config );
+}
+
+
+void KHexEdit::writeConfiguration( void )
+{
+ KConfig &config = *kapp->config();
+ writeConfiguration( config );
+}
+
+
+void KHexEdit::writeConfiguration( KConfig &config )
+{
+ saveMainWindowSettings(& config, "General Options");
+ config.setGroup("General Options" );
+ config.writeEntry("ShowFullPath", mShowFullPath );
+ config.writeEntry("ConversionPosition", (int)mManager->conversionPosition());
+ config.writeEntry("TabBarPosition", (int)mManager->tabBarPosition());
+ config.writeEntry("SearchBarPosition", (int)mManager->searchBarPosition());
+
+ if ( editor()->discardRecentFiles() )
+ mAction.openRecent->clearURLList();
+ mAction.openRecent->saveEntries( &config );
+
+ converter()->writeConfiguration( config );
+ editor()->writeConfiguration( config );
+
+ config.sync();
+}
+
+
+void KHexEdit::readConfiguration( KConfig &config )
+{
+ applyMainWindowSettings(& config, "General Options");
+
+ config.setGroup("General Options");
+ mShowFullPath = config.readBoolEntry( "ShowFullPath", true );
+ int position = config.readNumEntry( "ConversionPosition",
+ CHexManagerWidget::Embed );
+
+ mAction.conversionHide->blockSignals(true);
+ mAction.conversionFloat->blockSignals(true);
+ mAction.conversionEmbed->blockSignals(true);
+ mAction.conversionHide->setChecked(
+ position == CHexManagerWidget::Hide );
+ mAction.conversionFloat->setChecked(
+ position == CHexManagerWidget::Float );
+ mAction.conversionEmbed->setChecked(
+ position == CHexManagerWidget::Embed );
+ mAction.conversionHide->blockSignals(false);
+ mAction.conversionFloat->blockSignals(false);
+ mAction.conversionEmbed->blockSignals(false);
+ showConversionField();
+
+ position = config.readNumEntry( "TabBarPosition", CHexManagerWidget::Hide );
+ mAction.tabHide->blockSignals(true);
+ mAction.tabShowAboveEditor->blockSignals(true);
+ mAction.tabShowBelowEditor->blockSignals(true);
+ mAction.tabHide->setChecked(
+ position==CHexManagerWidget::Hide );
+ mAction.tabShowAboveEditor->setChecked(
+ position==CHexManagerWidget::AboveEditor );
+ mAction.tabShowBelowEditor->setChecked(
+ position==CHexManagerWidget::BelowEditor );
+ mAction.tabHide->blockSignals(false);
+ mAction.tabShowAboveEditor->blockSignals(false);
+ mAction.tabShowBelowEditor->blockSignals(false);
+ showDocumentTabs();
+
+ position = config.readNumEntry( "SearchBarPosition",
+ CHexManagerWidget::BelowEditor );
+ mAction.searchHide->blockSignals(true);
+ mAction.searchShowAboveEditor->blockSignals(true);
+ mAction.searchShowBelowEditor->blockSignals(true);
+ mAction.searchHide->setChecked(
+ position==CHexManagerWidget::Hide );
+ mAction.searchShowAboveEditor->setChecked(
+ position==CHexManagerWidget::AboveEditor );
+ mAction.searchShowBelowEditor->setChecked(
+ position==CHexManagerWidget::BelowEditor );
+ mAction.searchHide->blockSignals(false);
+ mAction.searchShowAboveEditor->blockSignals(false);
+ mAction.searchShowBelowEditor->blockSignals(false);
+ showSearchBar();
+
+ mAction.openRecent->loadEntries( &config );
+
+ converter()->readConfiguration( config );
+ editor()->readConfiguration( config );
+}
+
+
+
+void KHexEdit::operationChanged( bool state )
+{
+ mAction.cancel->setEnabled( state );
+}
+
+
+
+void KHexEdit::cursorChanged( SCursorState &state )
+{
+ QString offset( i18n("Offset:") );
+
+ if( state.valid == false )
+ {
+ statusBar()->changeItem( offset, status_Offset );
+ }
+ else
+ {
+ SDisplayLayout &layout = editor()->layout();
+
+ if( layout.offsetMode == SDisplayLayout::hexadecimal )
+ {
+ if( layout.offsetUpperCase == false )
+ {
+ offset += QString().sprintf( " %04x:%04x-%u", state.offset>>16,
+ state.offset&0x0000FFFF, state.cell );
+ }
+ else
+ {
+ offset += QString().sprintf( " %04X:%04X-%u", state.offset>>16,
+ state.offset&0x0000FFFF, state.cell );
+ }
+ }
+ else
+ {
+ offset += QString().sprintf( " %010u-%u", state.offset, state.cell );
+ }
+ statusBar()->changeItem( offset, status_Offset );
+ }
+
+ setUndoState( state.undoState );
+ setSelectionState( state.selectionOffset, state.selectionSize );
+}
+
+
+
+
+void KHexEdit::fileState( SFileState &state )
+{
+ if( state.valid == true )
+ {
+ statusBar()->changeItem( i18n("Size: %1").arg( state.size ), status_Size);
+ statusBar()->changeItem( state.modified ? "!" : "", status_Modified);
+
+ if( mIsModified != state.modified )
+ {
+ mIsModified = state.modified;
+ setupCaption( hexView()->url() );
+ }
+
+ }
+ else
+ {
+ statusBar()->changeItem( "", status_Size );
+ statusBar()->changeItem( "", status_Modified );
+ }
+}
+
+
+
+void KHexEdit::layoutChanged( const SDisplayLayout &layout )
+{
+ KRadioAction *radioAction;
+
+ if( layout.primaryMode == SDisplayLayout::hexadecimal )
+ {
+ radioAction = mAction.hexadecimal;
+ }
+ else if( layout.primaryMode == SDisplayLayout::decimal )
+ {
+ radioAction = mAction.decimal;
+ }
+ else if( layout.primaryMode == SDisplayLayout::octal )
+ {
+ radioAction = mAction.octal;
+ }
+ else if( layout.primaryMode == SDisplayLayout::binary )
+ {
+ radioAction = mAction.binary;
+ }
+ else
+ {
+ radioAction = mAction.textOnly;
+ }
+ radioAction->blockSignals(true);
+ radioAction->setChecked( true );
+ radioAction->blockSignals(false);
+
+ mAction.showOffsetColumn->blockSignals(true);
+ mAction.showTextColumn->blockSignals(true);
+ mAction.offsetAsDecimal->blockSignals(true);
+ mAction.dataUppercase->blockSignals(true);
+ mAction.offsetUppercase->blockSignals(true);
+
+ mAction.showOffsetColumn->setChecked( layout.offsetVisible );
+ mAction.showTextColumn->setEnabled(
+ layout.primaryMode != SDisplayLayout::textOnly );
+ mAction.showTextColumn->setChecked(
+ layout.secondaryMode != SDisplayLayout::hide );
+ mAction.offsetAsDecimal->setChecked(
+ layout.offsetMode != SDisplayLayout::hexadecimal);
+ mAction.dataUppercase->setChecked( layout.primaryUpperCase );
+ mAction.offsetUppercase->setChecked( layout.offsetUpperCase );
+
+ mAction.showOffsetColumn->blockSignals(false);
+ mAction.showTextColumn->blockSignals(false);
+ mAction.offsetAsDecimal->blockSignals(false);
+ mAction.dataUppercase->blockSignals(false);
+ mAction.offsetUppercase->blockSignals(false);
+
+ if( layout.primaryMode == SDisplayLayout::hexadecimal )
+ {
+ statusBar()->changeItem( i18n("Hex"), status_Layout );
+ }
+ else if( layout.primaryMode == SDisplayLayout::decimal )
+ {
+ statusBar()->changeItem( i18n("Dec"), status_Layout );
+ }
+ else if( layout.primaryMode == SDisplayLayout::octal )
+ {
+ statusBar()->changeItem( i18n("Oct"), status_Layout );
+ }
+ else if( layout.primaryMode == SDisplayLayout::binary )
+ {
+ statusBar()->changeItem( i18n("Bin"), status_Layout );
+ }
+ else if( layout.primaryMode == SDisplayLayout::textOnly )
+ {
+ statusBar()->changeItem( i18n("Txt"), status_Layout );
+ }
+}
+
+
+void KHexEdit::inputModeChanged( const SDisplayInputMode &mode )
+{
+ mAction.readOnly->blockSignals(true);
+ mAction.resizeLock->blockSignals(true);
+ mAction.readOnly->setChecked( mode.readOnly );
+ mAction.resizeLock->setChecked( mode.allowResize );
+ mAction.readOnly->blockSignals(false);
+ mAction.resizeLock->blockSignals(false);
+
+ statusBar()->changeItem( mode.readOnly == true ?
+ i18n("R") : i18n("RW"), status_WriteProtect );
+
+ if( mode.readOnly == false )
+ {
+ mWriteProtectButton->setIcon("edit");
+ }
+ else
+ {
+ mWriteProtectButton->setIcon("lock");
+ }
+}
+
+
+void KHexEdit::bookmarkChanged( QPtrList<SCursorOffset> &list )
+{
+ unplugActionList("bookmark_list");
+ mAction.bookmarkList.setAutoDelete(true);
+ mAction.bookmarkList.clear();
+
+ if( list.count() == 0 )
+ {
+ return;
+ }
+
+ mAction.bookmarkList.append(new KActionSeparator());
+
+ QString text, offset;
+ int i=0;
+
+ for( SCursorOffset *p=list.first(); p!=0; p=list.next(), i++ )
+ {
+ offset.sprintf("%04X:%04X", p->offset>>16, p->offset&0x0000FFFF );
+ text = i18n("Offset: %1").arg(offset);
+ KAction *action = new KAction(text, 0, mAction.bookmarkMapper, SLOT(map()), this, text.latin1());
+ int key = acceleratorNumKey( i );
+ if( key > 0 )
+ {
+ action->setShortcut(KShortcut(ALT+key));
+ }
+ mAction.bookmarkMapper->setMapping(action, i);
+ mAction.bookmarkList.append(action);
+ }
+ plugActionList("bookmark_list", mAction.bookmarkList);
+}
+
+
+void KHexEdit::setupCaption( const QString &url )
+{
+ KURL u(url);
+ if( mShowFullPath == true )
+ {
+ setCaption( u.prettyURL(), hexView()->modified() );
+ }
+ else
+ {
+ setCaption( u.fileName(), hexView()->modified() );
+ }
+}
+
+
+void KHexEdit::fileActive( const QString &url, bool onDisk )
+{
+ setupCaption( url );
+ mDragLabel->setUrl( url );
+ mDragLabel->setEnabled( onDisk );
+
+ mAction.revert->setEnabled( onDisk );
+
+ if( url.isNull() == false )
+ {
+ addDocument( url );
+ addRecentFile( url );
+ setTickedDocument( url );
+ }
+}
+
+
+void KHexEdit::fileRename( const QString &curName, const QString &newName )
+{
+ if( newName.isNull() == true )
+ {
+ return;
+ }
+
+ renameDocument( curName, newName );
+ renameRecentFile( curName, newName );
+ setupCaption( newName );
+ //setCaption( newName );
+}
+
+
+void KHexEdit::fileClosed( const QString &url )
+{
+ removeDocument( url );
+}
+
+
+void KHexEdit::editMode( CHexBuffer::EEditMode editMode )
+{
+ statusBar()->changeItem( editMode == CHexBuffer::EditReplace ?
+ i18n("OVR") : i18n("INS"), status_Ovr );
+}
+
+
+void KHexEdit::encodingChanged( const SEncodeState &encodeState )
+{
+ KRadioAction *radioAction;
+
+ if( encodeState.mode == CConversion::cnvDefault )
+ {
+ radioAction = mAction.defaultEncoding;
+ }
+ else if( encodeState.mode == CConversion::cnvUsAscii )
+ {
+ radioAction = mAction.usAsciiEncoding;
+ }
+ else if( encodeState.mode == CConversion::cnvEbcdic )
+ {
+ radioAction = mAction.ebcdicEncoding;
+ }
+ else
+ {
+ return;
+ }
+
+ radioAction->blockSignals(true);
+ radioAction->setChecked( true );
+ radioAction->blockSignals(false);
+
+ if( mSelectionSize == 0 )
+ {
+ statusBar()->changeItem( i18n("Encoding: %1").arg(encodeState.name),
+ status_Selection );
+ }
+}
+
+
+void KHexEdit::textWidth( uint )
+{
+ resize( mManager->preferredWidth(), height() );
+}
+
+
+void KHexEdit::setDisplayMode( void )
+{
+ if( mAction.hexadecimal->isChecked() == true )
+ {
+ editor()->setHexadecimalMode();
+ }
+ else if( mAction.decimal->isChecked() == true )
+ {
+ editor()->setDecimalMode();
+ }
+ else if( mAction.octal->isChecked() == true )
+ {
+ editor()->setOctalMode();
+ }
+ else if( mAction.binary->isChecked() == true )
+ {
+ editor()->setBinaryMode();
+ }
+ else if( mAction.textOnly->isChecked() == true )
+ {
+ editor()->setTextMode();
+ }
+}
+
+
+void KHexEdit::showFullPath( void )
+{
+ mShowFullPath = mAction.showFullPath->isChecked();
+ setupCaption( hexView()->url() );
+}
+
+
+void KHexEdit::showDocumentTabs( void )
+{
+ if( mAction.tabHide->isChecked() == true )
+ {
+ mManager->setTabBarPosition( CHexManagerWidget::HideItem );
+ }
+ else if( mAction.tabShowAboveEditor->isChecked() == true )
+ {
+ mManager->setTabBarPosition( CHexManagerWidget::AboveEditor );
+ }
+ else if( mAction.tabShowBelowEditor->isChecked() == true )
+ {
+ mManager->setTabBarPosition( CHexManagerWidget::BelowEditor );
+ }
+}
+
+
+void KHexEdit::showConversionField( void )
+{
+ if( mAction.conversionHide->isChecked() == true )
+ {
+ mManager->setConversionVisibility( CHexManagerWidget::Hide );
+ }
+ else if( mAction.conversionFloat->isChecked() == true )
+ {
+ mManager->setConversionVisibility( CHexManagerWidget::Float );
+ }
+ else if( mAction.conversionEmbed->isChecked() == true )
+ {
+ mManager->setConversionVisibility( CHexManagerWidget::Embed );
+ if( width() < mManager->preferredWidth() )
+ {
+ resize( mManager->preferredWidth(), height() );
+ }
+ }
+}
+
+
+void KHexEdit::showSearchBar( void )
+{
+ if( mAction.searchHide->isChecked() == true )
+ {
+ mManager->setSearchBarPosition( CHexManagerWidget::HideItem );
+ }
+ else if( mAction.searchShowAboveEditor->isChecked() == true )
+ {
+ mManager->setSearchBarPosition( CHexManagerWidget::AboveEditor );
+ }
+ else if( mAction.searchShowBelowEditor->isChecked() == true )
+ {
+ mManager->setSearchBarPosition( CHexManagerWidget::BelowEditor );
+ }
+}
+
+
+void KHexEdit::setEncoding( void )
+{
+ if( mAction.defaultEncoding->isChecked() == true )
+ {
+ editor()->encode( CConversion::cnvDefault );
+ }
+ else if( mAction.usAsciiEncoding->isChecked() == true )
+ {
+ editor()->encode( CConversion::cnvUsAscii );
+ }
+ else if( mAction.ebcdicEncoding->isChecked() == true )
+ {
+ editor()->encode( CConversion::cnvEbcdic );
+ }
+}
+
+
+void KHexEdit::setUndoState( uint undoState )
+{
+ if( mUndoState != undoState )
+ {
+ mUndoState = undoState;
+ mAction.undo->setEnabled( mUndoState & CHexBuffer::UndoOk );
+ mAction.redo->setEnabled( mUndoState & CHexBuffer::RedoOk );
+ }
+}
+
+
+void KHexEdit::setSelectionState( uint selectionOffset, uint selectionSize )
+{
+ if( mSelectionSize != selectionSize )
+ {
+ mSelectionOffset = selectionOffset;
+ mSelectionSize = selectionSize;
+
+ bool valid = mSelectionSize > 0 ? true : false;
+ mAction.copy->setEnabled( valid );
+ mAction.cut->setEnabled( valid );
+ mAction.copyAsText->setEnabled( valid );
+
+ setSelectionText( selectionOffset, selectionSize );
+ }
+}
+
+
+void KHexEdit::setSelectionText( uint selectionOffset, uint selectionSize )
+{
+ if( selectionSize > 0 )
+ {
+ QString selection = i18n("Selection:");
+ if( mSelectionAsHexadecimal == true )
+ {
+ selection += QString().sprintf( " %04x:%04x %04x:%04x",
+ selectionOffset>>16, selectionOffset&0x0000FFFF,
+ selectionSize>>16, selectionSize&0x0000FFFF );
+ }
+ else
+ {
+ selection += QString().sprintf( " %08u %08u",
+ selectionOffset, selectionSize);
+ }
+ statusBar()->changeItem( selection, status_Selection );
+ }
+ else
+ {
+ statusBar()->changeItem(
+ i18n("Encoding: %1").arg(hexView()->encoding().name), status_Selection);
+ }
+}
+
+
+void KHexEdit::documentMenuCB( int index )
+{
+ if( (uint)index < mDocumentList.count() )
+ {
+ editor()->open( mDocumentList[index], false, 0 );
+ }
+}
+
+
+void KHexEdit::addDocument( const QString &fileName )
+{
+ uint documentCount = mDocumentList.count();
+ for( uint i=0; i < documentCount; i++ )
+ {
+ if( fileName == mDocumentList[i] )
+ {
+ return;
+ }
+ }
+
+ mDocumentList.append( fileName );
+
+ QPopupMenu *documentMenu = (QPopupMenu *)factory()->container("documents", this);
+ documentMenu->insertItem( fileName, documentCount, documentCount );
+ int key = acceleratorNumKey( documentCount );
+ if( key > 0 )
+ {
+ documentMenu->setAccel( CTRL+key, documentCount );
+ }
+}
+
+
+void KHexEdit::removeDocument( const QString &fileName )
+{
+ QStringList::Iterator it;
+ for( it = mDocumentList.begin(); it != mDocumentList.end(); it++ )
+ {
+ if( *it == fileName )
+ {
+ QPopupMenu *documentMenu = (QPopupMenu *)factory()->container("documents", this);
+
+ documentMenu->removeItemAt( mDocumentList.findIndex(*it) );
+ mDocumentList.remove( it );
+
+ for( uint i=0; i < mDocumentList.count(); i++ )
+ {
+ documentMenu->setId( i, i );
+ int key = acceleratorNumKey( i );
+ if( key > 0 )
+ {
+ documentMenu->setAccel( CTRL+key, i );
+ }
+ }
+ return;
+
+ }
+ }
+}
+
+
+void KHexEdit::renameDocument( const QString &curName, const QString &newName )
+{
+ QStringList::Iterator it;
+ for( it = mDocumentList.begin(); it != mDocumentList.end(); it++ )
+ {
+ if( *it == curName )
+ {
+ QPopupMenu *documentMenu = (QPopupMenu *)factory()->container("documents", this);
+ documentMenu->changeItem( newName, mDocumentList.findIndex(*it) );
+ mDocumentList.insert( it, newName );
+ mDocumentList.remove( it );
+ return;
+ }
+ }
+}
+
+
+void KHexEdit::setTickedDocument( const QString &fileName )
+{
+ uint documentCount = mDocumentList.count();
+ QPopupMenu *documentMenu = (QPopupMenu *)factory()->container("documents", this);
+ for( uint i=0; i < documentCount; i++ )
+ {
+ documentMenu->setItemChecked( i, fileName == mDocumentList[i] );
+ }
+}
+
+
+void KHexEdit::conversionClosed( void )
+{
+ mAction.conversionHide->setChecked(true);
+}
+
+
+void KHexEdit::searchBarClosed( void )
+{
+ mAction.searchHide->setChecked(true);
+}
+
+
+bool KHexEdit::eventFilter( QObject *o, QEvent *event )
+{
+ if( event->type() == QEvent::DragEnter )
+ {
+ QDragEnterEvent *e = (QDragEnterEvent*)event;
+ if( KURLDrag::canDecode(e) )
+ {
+ e->accept();
+ hexView()->setDropHighlight( true );
+ }
+ return( true );
+ }
+ else if( event->type() == QEvent::Drop )
+ {
+ QMimeSource &m = *(QDropEvent*)event;
+ hexView()->setDropHighlight( false );
+
+ KURL::List list;
+ if( KURLDrag::decode( &m, list ) == true )
+ {
+ QStringList offset;
+ QStringList urlList = list.toStringList();
+ open( urlList, offset );
+ return( true );
+ }
+ return( true );
+ }
+ else if( event->type() == QEvent::DragLeave )
+ {
+ hexView()->setDropHighlight( false );
+ return( true );
+ }
+
+ return KMainWindow::eventFilter( o, event );
+}
+
+
+int KHexEdit::acceleratorNumKey( uint index )
+{
+ static int keys[9] =
+ {
+ Key_1, Key_2, Key_3, Key_4, Key_5, Key_6, Key_7, Key_8, Key_9
+ };
+ return( index >= 9 ? -1 : keys[index] );
+}
+
+
+#include <sys/time.h>
+#include <unistd.h>
+
+//
+// This function is used to test kwin performance
+//
+void KHexEdit::resizeTest()
+{
+ struct timeval t1, t2;
+ gettimeofday( &t1, 0 );
+
+ int loop=400;
+
+ for( int i=0; i<loop; i+=4 )
+ {
+ resize( i+400, i+400 );
+ //kapp->processOneEvent();
+ }
+
+ gettimeofday( &t2, 0 );
+ 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;
+}
+#include "toplevel.moc"
diff --git a/khexedit/toplevel.h b/khexedit/toplevel.h
new file mode 100644
index 0000000..fbacca1
--- /dev/null
+++ b/khexedit/toplevel.h
@@ -0,0 +1,279 @@
+/*
+ * khexedit - Versatile hex editor
+ * Copyright (C) 1999-2000 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.
+ *
+ */
+
+#ifndef _TOPLEVEL_H_
+#define _TOPLEVEL_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qptrlist.h>
+#include <kapplication.h>
+#include <kstdaccel.h>
+#include <kmainwindow.h>
+
+#include "hexbuffer.h"
+#include "hexmanagerwidget.h"
+#include "statusbarprogress.h"
+
+class QSignalMapper;
+class KAction;
+class KRecentFilesAction;
+class KRadioAction;
+class KSelectAction;
+class KToggleAction;
+class KToolBarButton;
+class KURL;
+class CDragLabel;
+
+
+class KHexEdit : public KMainWindow
+{
+ Q_OBJECT
+
+ enum StatusBarId
+ {
+ status_WriteProtect = 0,
+ status_Layout = 1,
+ status_Offset = 2,
+ status_Size = 3,
+ status_Ovr = 4,
+ status_Modified = 5,
+ status_Selection = 6,
+ status_Progress = 7
+ };
+
+ struct SActionList
+ {
+ KAction *insert;
+ KRecentFilesAction *openRecent;
+ KAction *save;
+ KAction *saveAs;
+ KAction *revert;
+ KAction *close;
+ KAction *print;
+ KAction *exportData;
+ KAction *cancel;
+ KToggleAction *readOnly;
+ KToggleAction *resizeLock;
+ KAction *newWindow;
+ KAction *closeWindow;
+ KAction *quit;
+ KAction *undo;
+ KAction *redo;
+ KAction *cut;
+ KAction *copy;
+ KAction *paste;
+ KAction *selectAll;
+ KAction *unselect;
+ KAction *find;
+ KAction *findNext;
+ KAction *findPrev;
+ KAction *replace;
+ KAction *gotoOffset;
+ KAction *insertPattern;
+ KAction *copyAsText;
+ KAction *pasteToNewFile;
+ KAction *pasteToNewWindow;
+ KRadioAction *hexadecimal;
+ KRadioAction *decimal;
+ KRadioAction *octal;
+ KRadioAction *binary;
+ KRadioAction *textOnly;
+ KToggleAction *showOffsetColumn;
+ KToggleAction *showTextColumn;
+ KToggleAction *offsetAsDecimal;
+ KToggleAction *dataUppercase;
+ KToggleAction *offsetUppercase;
+ KRadioAction *defaultEncoding;
+ KRadioAction *usAsciiEncoding;
+ KRadioAction *ebcdicEncoding;
+// KAction *customEncoding;
+
+ KAction *strings;
+// KAction *recordViewer;
+ KAction *filter;
+ KAction *characterTable;
+ KAction *converter;
+ KAction *statistics;
+
+ KAction *addBookmark;
+ KAction *replaceBookmark;
+ KAction *removeBookmark;
+ KAction *removeAllBookmark;
+ KAction *nextBookmark;
+ KAction *prevBookmark;
+
+ KToggleAction *showFullPath;
+ KRadioAction *tabHide;
+ KRadioAction *tabShowBelowEditor;
+ KRadioAction *tabShowAboveEditor;
+ KRadioAction *conversionHide;
+ KRadioAction *conversionFloat;
+ KRadioAction *conversionEmbed;
+ KRadioAction *searchHide;
+ KRadioAction *searchShowAboveEditor;
+ KRadioAction *searchShowBelowEditor;
+
+// KAction *favorites;
+
+ QPtrList< KAction > bookmarkList;
+ QSignalMapper *bookmarkMapper;
+ };
+
+ public:
+ KHexEdit( void );
+ ~KHexEdit( void );
+
+ inline void addStartupFile( const QString &fileName );
+ inline void setStartupOffset( uint offset );
+
+ public slots:
+ KHexEdit *newWindow( void );
+ void pasteNewWindow( void );
+ void closeWindow( void );
+ void closeProgram( void );
+ void statusBarPressed( int id );
+
+ void operationChanged( bool state );
+ void cursorChanged( SCursorState &state );
+ void fileState( SFileState &state );
+ void layoutChanged( const SDisplayLayout &layout );
+ void inputModeChanged( const SDisplayInputMode &mode );
+ void bookmarkChanged( QPtrList<SCursorOffset> &list );
+ void removeRecentFile( const QString &fileName );
+ void renameRecentFile( const QString &curName, const QString &newName );
+
+ void setupCaption( const QString &url );
+ void fileActive( const QString &url, bool onDisk );
+ void fileRename( const QString &curName, const QString &newName );
+ void fileClosed( const QString &url );
+ void readConfiguration( void );
+ void writeConfiguration( void );
+ void editMode( CHexBuffer::EEditMode editMode );
+ void encodingChanged( const SEncodeState &state );
+ void textWidth( uint width );
+
+ void setDisplayMode( void );
+ void showFullPath( void );
+ void showDocumentTabs( void );
+ void showConversionField( void );
+ void showSearchBar( void );
+
+ void setEncoding( void );
+ void documentMenuCB( int id );
+
+ /**
+ * Slot for opening a file among the recently opened files.
+ */
+ void slotFileOpenRecent( const KURL & );
+
+protected:
+ virtual bool queryExit( void );
+ virtual bool queryClose( void );
+
+ private slots:
+ void delayedStartupOpen( void );
+ void removeRecentFiles( void );
+ void conversionClosed( void );
+ void searchBarClosed( void );
+ void resizeTest();
+
+ private:
+ void setupActions( void );
+ void setupStatusBar( void );
+ void open( QStringList &fileList, QStringList &offsetList );
+ void initialize( bool openFiles );
+ void addRecentFile( const QString &fileName );
+ bool closeAllWindow( void );
+ void setUndoState( uint undoState );
+ void setSelectionState( uint selectionOffset, uint selectionSize );
+ void setSelectionText( uint selectionOffset, uint selectionSize );
+ void addDocument( const QString &fileName );
+ void removeDocument( const QString &fileName );
+ void renameDocument( const QString &curName, const QString &newName );
+ void setTickedDocument( const QString &fileName );
+
+ void writeConfiguration( KConfig &config );
+ void readConfiguration( KConfig &config );
+ bool eventFilter( QObject *obj, QEvent *event );
+
+ int acceleratorNumKey( uint index );
+ inline CHexEditorWidget *editor( void );
+ inline CHexToolWidget *converter( void );
+ inline CHexViewWidget *hexView( void );
+
+ private:
+ static QPtrList<KHexEdit> mWindowList;
+ CHexManagerWidget *mManager;
+ QStringList mDocumentList;
+
+ QStringList mStartupFileList; ///< Files to automatically open on startup
+ QStringList mStartupOffsetList; ///< Start offset for those files.
+ uint mStartupOffset; ///< Value read from the command line
+
+ SActionList mAction;
+
+ CDragLabel *mDragLabel;
+ KToolBarButton *mWriteProtectButton;
+
+ bool mIsModified;
+ bool mShowFullPath;
+ bool mSelectionAsHexadecimal;
+ uint mSelectionOffset;
+ uint mSelectionSize;
+ uint mUndoState;
+ int mRecentFileId;
+};
+
+
+inline void KHexEdit::addStartupFile( const QString &fileName )
+{
+ mStartupFileList.prepend( fileName );
+ mStartupOffsetList.prepend( QString("%1").arg(mStartupOffset,0,16) );
+ mStartupOffset = 0;
+}
+
+inline void KHexEdit::setStartupOffset( uint offset )
+{
+ mStartupOffset = offset;
+}
+
+inline CHexEditorWidget *KHexEdit::editor( void )
+{
+ return( mManager->editor() );
+}
+
+inline CHexViewWidget *KHexEdit::hexView( void )
+{
+ return( mManager->editor()->view() );
+}
+
+inline CHexToolWidget *KHexEdit::converter( void )
+{
+ return( mManager->converter() );
+}
+
+
+
+#endif
+
+
diff --git a/khexedit/version.h b/khexedit/version.h
new file mode 100644
index 0000000..536fa35
--- /dev/null
+++ b/khexedit/version.h
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _VERSION_H_
+#define _VERSION_H_
+
+//
+// Just a few replacements for defines in config.h I used when this
+// program lived outside CVS
+//
+#define APP_PACKAGE_STRING "khexedit"
+#define APP_VERSION_STRING "0.8.6"
+
+
+#endif