diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | 2bda8f7717adf28da4af0d34fb82f63d2868c31d (patch) | |
tree | 8d927b7b47a90c4adb646482a52613f58acd6f8c /khexedit/lib | |
download | tdeutils-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/lib')
101 files changed, 13638 insertions, 0 deletions
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 |