summaryrefslogtreecommitdiffstats
path: root/khexedit/hextoolwidget.cc
diff options
context:
space:
mode:
Diffstat (limited to 'khexedit/hextoolwidget.cc')
-rw-r--r--khexedit/hextoolwidget.cc416
1 files changed, 416 insertions, 0 deletions
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"