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

2041 lines
40 KiB

/*
* khexedit - Versatile hex editor
* Copyright (C) 1999-2000 Espen Sand, espensa@online.no
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef _HEX_BUFFER_H_
#define _HEX_BUFFER_H_
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <iostream>
#include <time.h>
#include <tqbitarray.h>
#include <tqdatetime.h>
#include <tqfile.h>
#include <tqfont.h>
#include <tqptrlist.h>
#include <tqpainter.h>
#include <tqstring.h>
#include <tqtextstream.h>
#include <kapplication.h>
#include "conversion.h"
#include "hexeditstate.h"
#include "hexprinter.h"
#include "progress.h"
//
// Marco to simplify usage of function pointers
//
#define THIS_FPTR( func ) ((this->*func))
struct SSearchControl
{
TQByteArray key;
TQByteArray val;
uint keyType;
bool fromCursor;
bool inSelection;
bool forward;
bool ignoreCase;
bool match;
uint numReplace;
bool wrapValid;
bool wrapActive;
uint wrapMark;
};
struct SFilterControl
{
enum Operation
{
OperandAndData = 0,
OperandOrData,
OperandXorData,
InvertData,
ReverseData,
RotateData,
ShiftData,
SwapBits
};
int execute( uchar *dest, uchar *src, uint size );
TQByteArray operand;
int rotate[2];
Operation operation;
bool fromCursor;
bool inSelection;
bool forward;
};
struct SInsertData
{
uint size;
TQByteArray pattern;
uint offset;
bool repeatPattern;
bool onCursor;
};
struct SExportRange
{
enum EMode
{
All = 0,
Selection,
Range
};
EMode mode;
uint start;
uint stop;
};
struct SExportText
{
SExportRange range;
TQString destFile;
};
struct SExportHtml
{
SExportRange range;
TQString package;
TQString prefix;
uint linePerPage;
uint topCaption;
uint bottomCaption;
bool symLink;
bool navigator;
bool blackWhite;
};
struct SExportCArray
{
enum ElementType
{
Char = 0,
Uchar,
Short,
Ushort,
Int,
Uint,
Float,
Double
};
const char *printFormatted( const char *b, uint maxSize ) const;
TQString variableName( uint range ) const;
int elementSize( void ) const;
SExportRange range;
TQString destFile;
TQString arrayName;
int elementType;
uint elementPerLine;
bool unsignedAsHexadecimal;
};
struct SStatisticControl
{
SStatisticControl( void )
{
memset( occurrence, 0, sizeof(occurrence) );
documentSize = 0;
}
uint documentSize;
uint occurrence[256];
TQString documentName;
};
struct SPagePosition
{
SPagePosition( time_t now, uint numLine, uint linePerPage )
{
init( now, numLine, linePerPage );
}
SPagePosition( void )
{
init( 0, 1, 1 );
}
void init( time_t at, uint numLine, uint linePerPage )
{
if( linePerPage == 0 ) { linePerPage = 1; }
now = at;
curPage = 1;
maxPage = numLine / linePerPage + (numLine % linePerPage ? 1 : 0);
if( maxPage < curPage ) { maxPage = curPage; }
}
void step( uint stepSize=1 )
{
curPage += stepSize;
if( curPage > maxPage ) { curPage = maxPage; }
}
uint current( void )
{
return( curPage );
}
uint max( void )
{
return( maxPage );
}
uint curPage;
uint maxPage;
time_t now;
};
class CStringCollectControl
{
public:
CStringCollectControl( void )
{
mList.setAutoDelete( true );
}
int add( uint offset, const TQByteArray &a )
{
TQString *s = new TQString();
if( s == 0 )
{
return( Err_NoMemory );
}
if( decimalOffset == true )
{
s->sprintf( "%010u", offset );
}
else
{
s->sprintf( "%04x:%04x", offset>>16, offset&0x0000FFFF );
}
*s += TQString( a );
mList.append( s );
return( Err_Success );
}
uint offsetLen( void )
{
return( decimalOffset ? 10 : 9 );
}
void clear( void )
{
mList.clear();
}
const TQString *get( uint index )
{
return( mList.at( index ) );
}
int count( void )
{
return( mList.count() );
}
TQPtrList<TQString> &list( void )
{
return( mList );
}
public:
uint minLength;
bool decimalOffset;
bool allow8bit;
private:
TQPtrList<TQString> mList;
};
struct SCursorConfig
{
SCursorConfig( void )
{
state = 0;
}
bool selectOn( void )
{
return( state & TQt::ShiftButton );
}
bool removeSelection( void )
{
return( state & TQt::ShiftButton ? false : true );
}
void setKeepSelection( bool val )
{
state = val == true ? state|TQt::ShiftButton : state&~TQt::ShiftButton;
}
bool controlButton( void )
{
return( state & TQt::ControlButton ? true : false );
}
bool shiftButton( void )
{
return( state & TQt::ShiftButton ? true : false );
}
bool altButton( void )
{
return( state & TQt::AltButton ? true : false );
}
void emulateControlButton( bool val )
{
state = val == true ? state|TQt::ControlButton : state&~TQt::ControlButton;
}
int state;
};
struct SCursorSpec
{
enum EShape
{
solid = 0,
frame,
thin
};
void reset( void )
{
offset = 0;
x1 = x2 = y = cell = maxCell = 0;
}
void setShape( EShape primaryShape, EShape secondaryShape, uint unitWidth,
uint numCell )
{
if( primaryShape == thin )
{
if( onlyBlock == true ) { primaryShape = solid; }
}
if( secondaryShape == thin )
{
if( onlyBlock == true ) { secondaryShape = solid; }
}
mPrimaryShape = primaryShape;
if( mPrimaryShape == solid )
{
drawWidth1 = unitWidth;
drawOffset1 = 0;
}
else if( mPrimaryShape == frame )
{
drawWidth1 = unitWidth * numCell;
drawOffset1 = 0;
}
else
{
mPrimaryShape = thin;
if( thickState == true )
{
drawWidth1 = 2;
drawOffset1 = -1;
}
else
{
drawWidth1 = 5;
drawOffset1 = -3;
}
}
mSecondaryShape = secondaryShape;
if( mSecondaryShape == solid )
{
drawWidth2 = unitWidth;
drawOffset2 = 0;
}
else if( mSecondaryShape == frame )
{
drawWidth2 = unitWidth * numCell;
drawOffset2 = 0;
}
else
{
mSecondaryShape = thin;
if( thickState == true )
{
drawWidth2 = 2;
drawOffset2 = -1;
}
else
{
drawWidth2 = 5;
drawOffset2 = -3;
}
}
}
void setShapeModifier( bool alwaysBlock, bool useThick )
{
onlyBlock = alwaysBlock;
thickState = useThick;
}
void dump( void )
{
std::cout << "offset: " << offset << " y: " << y << " x1: " << x1 << std::endl;
std::cout << "x2: " << x2 << " cell: " << cell << std::endl;
}
bool inside( uint min, uint max )
{
return( offset >= min && offset < max );
}
int drawX1( void )
{
return( x1 + drawOffset1 );
}
int drawX2( void )
{
return( x2 + drawOffset2 );
}
int width1( void )
{
return( drawWidth1 );
}
int width2( void )
{
return( drawWidth2 );
}
uint offset;
int y;
int x1;
int x2;
int cell;
int maxCell;
bool onlyBlock;
bool thickState;
char data;
int mPrimaryShape;
int mSecondaryShape;
int drawWidth1;
int drawWidth2;
int drawOffset1;
int drawOffset2;
};
struct SCursor
{
SCursor( void )
{
mLineSize = 1;
mDocumentSize = 0;
mFixedSizeMode = false;
mArea = 0;
}
void reset( void )
{
prev.reset();
curr.reset();
next.reset();
}
void setDocumentSize( uint documentSize )
{
mDocumentSize = documentSize;
}
void setFixedSizeMode( bool fixedSizeMode )
{
mFixedSizeMode = fixedSizeMode;
}
bool incCell( void )
{
if( curr.cell + 1 >= curr.maxCell )
{
addOffset( 1 );
return( true );
}
else
{
next.cell = curr.cell + 1;
return( false );
}
}
bool decCell( void )
{
if( curr.cell == 0 )
{
if( curr.offset > 0 )
{
decOffset( 1, true );
next.cell = curr.maxCell > 0 ? curr.maxCell - 1 : 0;
}
return( true );
}
else
{
next.cell = curr.cell - 1;
return( false );
}
}
void resetCell( void )
{
next.cell = 0;
}
void addOffset( uint val )
{
setOffset( curr.offset + val );
}
void decOffset( uint val, bool ignoreCell )
{
if( ignoreCell == true || curr.cell == 0 )
{
setOffset( val > curr.offset ? curr.offset%mLineSize : curr.offset-val);
}
else
{
setOffset( curr.offset );
}
}
void setOffset( uint offset )
{
/*
if( offset >= mDocumentSize )
{
if( mFixedSizeMode == true )
{
offset = mDocumentSize > 0 ? mDocumentSize - 1 : 0;
}
else
{
offset = mDocumentSize;
}
}
*/
next.offset = offset;
next.cell = 0;
}
uint getOffset( void )
{
return( curr.offset );
}
void setOffset( uint offset, uint bit, bool backward, bool fromCursor,
uint textSize )
{
if( fromCursor == true )
{
if( backward == true )
{
setOffset( offset > curr.offset ? 0 : curr.offset - offset );
}
else
{
setOffset( curr.offset + offset );
}
}
else
{
if( backward == true )
{
setOffset( offset > textSize ? 0 : textSize - offset );
}
else
{
setOffset( offset > textSize ? textSize : offset );
}
}
setBit( bit );
}
void setBit( uint bit )
{
bit = (bit > 7) ? 0 : 7 - bit;
next.cell = bit / mCellWeight;
}
void home( bool toExtreme )
{
if( toExtreme == true )
{
setOffset( 0 );
}
else
{
setOffset( next.offset - curr.offset % mLineSize );
}
}
void end( bool toExtreme )
{
uint maxOffset;
if( mFixedSizeMode == true )
{
maxOffset = mDocumentSize > 0 ? mDocumentSize-1 : mDocumentSize;
}
else
{
maxOffset = mDocumentSize;
}
if( toExtreme == true )
{
setOffset( maxOffset );
}
else
{
uint newOffset = next.offset + (mLineSize-1) - curr.offset % mLineSize;
setOffset( newOffset > maxOffset ? maxOffset : newOffset );
}
}
void up( uint numLines )
{
decOffset( numLines * mLineSize, true );
}
void down( uint numLines )
{
addOffset( numLines * mLineSize );
}
bool changed( void )
{
return( prev.offset != curr.offset || prev.cell != curr.cell ||
prev.data != curr.data ? true : false );
}
uint bit( void )
{
uint bitValue = mCellWeight*(curr.maxCell - curr.cell) - 1;
return( bitValue > 7 ? 7 : bitValue );
}
uint cellWeight( void )
{
return( mCellWeight );
}
void setLineSize( uint lineSize )
{
mLineSize = lineSize < 1 ? 1 : lineSize;
}
void setCellWeight( uint cellWeight )
{
mCellWeight = cellWeight;
}
int area( void )
{
return( mArea );
}
void setArea( int area )
{
mArea = area;
}
void setShape( SCursorSpec::EShape primary, SCursorSpec::EShape secondary,
uint unitWidth, uint numCell )
{
curr.setShape( primary, secondary, unitWidth, numCell );
}
void setShapeModifier( bool alwaysBlock, bool useThick )
{
curr.setShapeModifier( alwaysBlock, useThick );
}
uint mLineSize;
uint mDocumentSize;
uint mCellWeight;
int mArea;
bool mFixedSizeMode;
SCursorSpec prev;
SCursorSpec curr;
SCursorSpec next;
};
struct SCursorPosition
{
int x;
int y;
int w;
int h;
};
struct SCursorOffset
{
uint offset;
uint bit;
};
struct SSelectSpec
{
void init( uint offset )
{
start = stop = anchor = offset;
}
void set( uint offset )
{
if( offset < anchor )
{
start = offset;
stop = anchor;
}
else
{
stop = offset;
start = anchor;
}
}
void expand( uint value )
{
if( anchor == stop ) { anchor +=value; }
stop += value;
//set( stop + value );
}
void shrink( uint value )
{
uint newVal = start + value > stop ? start : stop - value;
if( anchor == stop ) { anchor = newVal; }
stop = newVal;
/*
if( start + value > stop )
{
set( start );
}
else
{
set( stop - value );
}
*/
}
uint start;
uint stop;
uint anchor;
};
struct SSelect
{
SSelect( void )
{
reset();
}
bool init( uint offset )
{
curr.init( offset );
if( isValid == true )
{
isValid = false;
return( true );
}
else
{
return( false );
}
}
void reset( void )
{
curr.init( 0 );
isValid = false;
}
bool set( uint offset )
{
isValid = true;
curr.set( offset );
if( curr.start != prev.start || curr.stop != prev.stop )
{
return( true );
}
else
{
return( false );
}
}
void expand( uint value )
{
if( isValid == false )
{
return;
}
curr.expand( value );
}
void shrink( uint value )
{
if( isValid == false )
{
return;
}
curr.shrink( value );
}
void sync( void )
{
prev = curr;
}
bool inside( uint offset )
{
return( isValid == true && offset >= curr.start && offset < curr.stop );
}
bool inside( uint offset, uint range )
{
return( isValid == true && (offset + range) >= curr.start &&
offset < curr.stop );
}
bool verify( uint &start, uint &stop )
{
if( isValid == false )
{
return( false );
}
if( start < curr.start ) { start = curr.start; }
if( stop > curr.stop ) { stop = curr.stop; }
return( true );
}
uint start( uint offset )
{
//
// If 'curr.star' is smaller than 'offset' then the start is at
// the start of line.
//
return( curr.start < offset ? 0 : curr.start - offset );
}
uint start( void )
{
return( curr.start );
}
uint stop( uint offset, uint range )
{
return( curr.stop > offset + range ? range : curr.stop - offset );
}
uint stop( void )
{
return( curr.stop );
}
bool valid( void )
{
return( isValid );
}
uint size( void )
{
if( isValid == false )
{
return( 0 );
}
else
{
return( curr.start >= curr.stop ? 0 : curr.stop - curr.start );
}
}
void startChange( uint &first, uint &last )
{
if( curr.start <= prev.start )
{
first = curr.start;
last = prev.start;
}
else
{
first = prev.start;
last = curr.start;
}
}
void stopChange( uint &first, uint &last )
{
if( curr.stop <= prev.stop )
{
first = curr.stop;
last = prev.stop;
}
else
{
first = prev.stop;
last = curr.stop;
}
}
bool isValid;
SSelectSpec prev;
SSelectSpec curr;
};
class CHexAction
{
public:
enum HexAction
{
replace
};
public:
CHexAction( HexAction action, uint offset );
~CHexAction( void );
void setData( uint size, char *data, uint dataSize );
public:
HexAction mAction;
uint mOffset;
uint mSize;
char *mData;
uint mDataSize;
CHexAction *mNext;
};
class CHexActionGroup
{
public:
CHexActionGroup( uint startOffset, uint startBit );
~CHexActionGroup( void );
void insertAction( CHexAction *hexAction );
public:
uint mStartOffset;
uint mStopOffset;
uint mStartBit;
uint mStopBit;
CHexAction *mHexAction;
};
struct SCursorState
{
bool valid;
uint selectionOffset;
uint selectionSize;
uint offset;
uint cell;
unsigned char data[8];
uint undoState;
bool charValid;
};
struct SFileState
{
bool valid;
uint size;
bool modified;
};
class CHexBuffer;
typedef int (CHexBuffer::*PrintCellFunc)( char *buf, unsigned char data );
typedef bool (CHexBuffer::*InputCellFunc)( unsigned char *dest, int value,
uint cell );
typedef void (CHexBuffer::*PrintOffsetFunc)( char *buf, uint offset );
class CHexBuffer : public TQByteArray
{
public:
enum EColumn
{
VisibleColumn = 0x0,
OffsetColumn = 0x1,
PrimaryColumn = 0x2,
SecondaryColumn = 0x4,
EveryColumn = 0x7
};
enum EEditArea
{
edit_none = 0,
edit_primary,
edit_secondary
};
enum ECursorMode
{
cursor_curr = 0,
cursor_prev
};
enum EEditMode
{
EditInsert = 0,
EditReplace
};
enum EUndoState
{
UndoOk = 1,
RedoOk = 2
};
public:
CHexBuffer( void );
~CHexBuffer( void );
int setLayout( SDisplayLayout &layout );
void setColor( SDisplayColor &color );
void setInputMode( SDisplayInputMode &mode );
bool toggleEditor( void );
bool matchWidth( uint width );
void setNonPrintChar( TQChar nonPrintChar );
void setShowCursor( bool showCursor );
void setDisableCursor( bool disableCursor );
void setCursorShapeModifier( bool alwaysBlock, bool thickInsert );
void setEditMode( EEditMode editMode );
void setEditMode( EEditMode editMode, bool alwaysBlock, bool thickInsert );
void setMaximumSize( uint size );
void setDocumentSize( uint size );
void setUndoLevel( uint level );
void setSoundState( bool inputSound, bool fatalSound );
void setBookmarkVisibility( bool showInColumn, bool showInEditor );
void setFont( const SDisplayFontInfo &fontInfo );
int setEncoding( CConversion::EMode mode, CProgress &p );
bool setCursorPosition( int x, int y, bool init, bool cellLevel );
int readFile( TQFile &file, const TQString &url, CProgress &p );
int insertFile( TQFile &file, CProgress &p );
int writeFile( TQFile &file, CProgress &p );
int newFile( const TQString &url );
void closeFile( void );
void registerDiskModifyTime( const TQFile &file );
bool changedOnDisk( void );
void drawText( TQPainter &paint, uint line, int sx, int x, int w );
void drawText( TQPainter &paint, uint line, int x1, int x2, int y,
bool useBlackWhite );
void drawHeader( TQPainter &paint, int sx, int width, int y, bool isFooter,
const SPageHeader &header,const SPagePosition &position );
int headerHeight( TQPainter &paint );
int headerMargin( TQPainter &paint );
bool inputAtCursor( TQChar c );
int inputAtCursor( const TQByteArray &buf, uint oldSize );
bool removeAtCursor( bool beforeCursor );
int locateRange( const SExportRange &range, uint &start, uint &stop );
int exportText( const SExportText &ex, CProgress &p );
int exportHtml( const SExportHtml &ex, CProgress &p );
int exportCArray( const SExportCArray &ex, CProgress &p );
int copySelectedText( TQByteArray &array, int columnSegment=VisibleColumn);
int copyAllText( TQByteArray &array );
int copyText( TQByteArray &array, const SExportRange &range,
int columnSegment );
int copySelectedData( TQByteArray &array );
uint numPage( CHexPrinter &printer );
int print( CHexPrinter &printer, CProgress &p );
uint printLine( char *dst, uint line );
uint printLine( char *dst, uint line, int columnSegment );
bool cutSelection( void );
bool undo( void );
bool redo( void );
int addBookmark( int position );
bool removeBookmark( int position );
void updateBookmarkMap( bool resize );
int findFirst( SSearchControl &sc );
int findNext( SSearchControl &sc );
int findWrap( SSearchControl &sc );
int replaceAll( SSearchControl &sc, bool init );
int replaceMarked( SSearchControl &sc );
int filter( SFilterControl &fc );
int collectStrings( CStringCollectControl &sc );
int collectStatistic( SStatisticControl &sc, CProgress &p );
void doActionGroup( CHexActionGroup *group );
void doAction( CHexAction *action );
inline SCursorState &cursorState( void );
inline void valueOnCursor( TQByteArray &buf, uint size );
inline SFileState &fileState( void );
inline const SDisplayLayout &layout( void );
inline const SDisplayInputMode &inputMode( void );
inline TQPtrList<SCursorOffset> &bookmarkList( void );
inline bool documentPresent( void );
inline bool modified( void );
inline uint undoState( void );
inline uint documentSize( void );
inline EEditMode editMode( void );
inline const SEncodeState &encoding( void );
inline bool losslessEncoding( CConversion::EMode mode );
inline TQString &url( void );
bool hasFileName( void );
inline void setUrl( const TQString &url );
inline void setModified( bool modified );
inline const TQDateTime &diskModifyTime( void );
inline uint calculateLine( uint offset );
inline int lineSize( void );
inline int lineHeight( void );
inline int fontAscent( void );
inline int lineWidth( void );
inline int unitWidth( void );
inline int numLines( void );
inline int totalHeight( void );
inline const TQFont &font( void );
inline SCursor *textCursor( void );
inline const TQColor &backgroundColor( void );
inline int startX( void );
inline int startY( void );
inline void setStartX( int val );
inline void setStartY( int val );
inline bool selectionSet( uint offset, bool init );
inline void selectionSyncronize( void );
inline void selectionStartChange( uint &offset1, uint &offset2 );
inline void selectionStopChange( uint &offset1, uint &offset2 );
inline bool cursorInsideSelection( void );
inline void markSet( uint offset, uint size );
inline bool markSet( uint offset, bool init );
inline bool markRemove( void );
inline void markSyncronize( void );
inline void markStartChange( uint &offset1, uint &offset2 );
inline void markStopChange( uint &offset1, uint &offset2 );
inline uint cursorOffset( void );
inline uint cursorBit( void );
inline uint cursorLine( void );
inline uint prevCursorLine( void );
inline SCursor &cursor( void );
inline void currCursor( EEditArea editArea, SCursorPosition &p );
inline void prevCursor( EEditArea editArea, SCursorPosition &p );
inline void cursorUp( uint lines );
inline void cursorDown( uint lines );
inline void cursorRight( bool cellLevel );
inline void cursorLeft( bool cellLevel );
inline void cursorStep( uint size, bool forward, bool modulo );
inline void cursorHome( bool toExtreme );
inline void cursorEnd( bool toExtreme );
inline void cursorGoto( uint offset, uint bit );
inline void cursorGoto( uint offset, uint bit, bool backward,
bool fromCursor );
inline bool cursorChanged( void );
inline void cursorResetEditArea( void );
inline bool cursorPrimaryEdit( void );
inline int cursorFixedPosition( int position, int height );
inline int cursorChangePosition( int position, int height );
void cursorReset( void );
private:
enum { BookmarkOnLine = 0x01, BookmarkOnCursor = 0x02 };
void computeLineWidth( void );
void computeNumLines( void );
void cursorCompute( void );
void drawSelection( TQPainter &paint, TQColor &color, uint start, uint stop,
int sx );
int drawBookmarks(TQPainter &paint, uint line, int startx);
void drawCursor( TQPainter &paint, uint line, int startx, bool onBookmark );
void recordStart( SCursor &cursor );
void recordReplace( SCursor &cursor, uint size, char *data, uint dataSize);
void recordEnd( SCursor &cursor );
void doReplace( CHexAction *hexAction, bool removeData );
int scanData( SSearchControl &sc, bool init );
int initScanData( SSearchControl &sc );
inline const TQColor &foregroundColor( uint column );
inline int printDummyCell( char *buf, unsigned char data );
inline int printHexadecimalBigCell( char *buf, unsigned char data );
inline int printHexadecimalSmallCell( char *buf, unsigned char data );
inline int printDecimalCell( char *buf, unsigned char data );
inline int printOctalCell( char *buf, unsigned char data );
inline int printBinaryCell( char *buf, unsigned char data );
inline int printAsciiCell( char *buf, unsigned char data );
inline void printDummyOffset( char *buf, uint offset );
inline void printHexadecimalBigOffset( char *buf, uint offset );
inline void printHexadecimalSmallOffset( char *buf, uint offset );
inline void printDecimalOffset( char *buf, uint offset );
bool inputDummy( unsigned char *dest, int value, uint cell );
bool inputHexadecimal( unsigned char *dest, int value, uint cell );
bool inputDecimal( unsigned char *dest, int value, uint cell );
bool inputOctal( unsigned char *dest, int value, uint cell );
bool inputBinary( unsigned char *dest, int value, uint cell );
bool inputAscii( unsigned char *dest, int value, uint cell );
int moveBuffer( uint destOffset, uint srcOffset );
int resizeBuffer( uint offset );
void inputSound( void );
void fatalSound( void );
int printHtmlDataPage( const TQString &tocName,
const TQStringList &fileNames, uint index,
const SExportHtml &ex, uint line, uint numLine );
void printHtmlCaption( TQTextStream &os, uint captionType, uint curPage,
uint numPage );
void printHtmlNavigator( TQTextStream &os, const TQString *next,
const TQString *prev, const TQString *toc );
void printHtmlTocPage( const TQString &tocName,
const TQString &linkName,
const TQStringList &fileNames,
const TQStringList &offsets, uint numPage );
int printHtmlHeader( TQTextStream &os, bool isFront );
int printHtmlTable( TQTextStream &os, uint line, uint numLine, bool bw );
int printHtmlLine( TQTextStream &os, uint offset, bool isPrimary, bool bw );
signals:
void fileSize( uint size );
private:
TQString mUrl;
TQDateTime mDiskModifyTime;
SDisplayLayout mLayout;
SDisplayColor mColor;
SDisplayFontInfo mFontInfo;
CConversion mEncode;
bool mCharValid[256];
unsigned char *mColorIndex;
char *mPrintBuf;
bool mLoadingData;
int mStartX;
int mStartY;
int mFontHeight;
int mFontAscent;
int mLineWidth;
int mFixedWidth;
int mUnitWidth;
int mSplitWidth;
int mNumLines;
int mTextStart1;
int mTextStart2;
int mNumCell;
uint mDocumentSize;
uint mMaximumSize;
bool mFixedSizeMode;
bool mDocumentModified;
EEditMode mEditMode;
SDisplayInputMode mInputMode;
int mOffsetSize;
int mOffsetIndex;
int mPrimaryWidth;
int mSecondaryWidth;
int mActiveEditor;
SSelect mSelect;
SSelect mMark;
SCursor mCursor;
bool mShowCursor;
bool mDisableCursor;
bool mInputErrorSound;
bool mFatalErrorSound;
bool mShowBookmarkInOffsetColumn;
bool mShowBookmarkInEditor;
uint mUndoLimit;
uint mUndoIndex;
TQPtrList<CHexActionGroup> mUndoList;
TQPtrList<SCursorOffset> mBookmarkList;
TQBitArray mBookmarkMap;
PrintCellFunc printCell;
PrintOffsetFunc printOffset;
InputCellFunc inputCell;
static char mHexBigBuffer[16];
static char mHexSmallBuffer[16];
static char mDecBuffer[10];
static char mOctBuffer[8];
static SCursorState mCursorState;
static SFileState mFileState;
};
inline SCursorState &CHexBuffer::cursorState( void )
{
if( size() == 0 )
{
mCursorState.valid = false;
mCursorState.selectionOffset = 0;
mCursorState.selectionSize = 0;
mCursorState.offset = 0;
mCursorState.cell = 0;
mCursorState.undoState = 0;
memset( mCursorState.data, 0, sizeof(mCursorState.data) );
mCursorState.charValid = false;
}
else
{
mCursorState.valid = true;
mCursorState.selectionOffset = mSelect.start();
mCursorState.selectionSize = mSelect.size();
mCursorState.offset = cursorOffset();
mCursorState.cell = cursorBit();
mCursorState.undoState = undoState();
for( uint i = 0; i < sizeof( mCursorState.data ); i++ )
{
mCursorState.data[i] = (mCursorState.offset+i >= mDocumentSize) ? 0 :
(unsigned char)data()[mCursorState.offset+i];
}
mCursorState.charValid = mCharValid[ mCursorState.data[0] ];
}
return( mCursorState );
}
inline void CHexBuffer::valueOnCursor( TQByteArray &buf, uint size )
{
int offset = cursorOffset();
if( offset + size >= mDocumentSize )
{
size = mDocumentSize - offset;
}
buf.resize(size);
for( uint i=0; i<buf.size(); i++)
{
buf[i] = (unsigned char)data()[offset+i];
}
}
inline const SDisplayLayout &CHexBuffer::layout( void )
{
return( mLayout );
}
inline const SDisplayInputMode &CHexBuffer::inputMode( void )
{
return( mInputMode );
}
inline TQPtrList<SCursorOffset> &CHexBuffer::bookmarkList( void )
{
return( mBookmarkList );
}
inline SFileState &CHexBuffer::fileState( void )
{
if( size() == 0 )
{
mFileState.valid = false;
mFileState.size = 0;
mFileState.modified = false;
}
else
{
mFileState.valid = true;
mFileState.size = mDocumentSize;
mFileState.modified = mDocumentModified;
}
return( mFileState );
}
inline bool CHexBuffer::modified( void )
{
return( mDocumentModified );
}
inline void CHexBuffer::setModified( bool modified )
{
mDocumentModified = modified;
}
inline uint CHexBuffer::undoState( void )
{
return( (mUndoIndex > 0 ? UndoOk : 0) |
(mUndoIndex < mUndoList.count() ? RedoOk : 0) );
}
inline uint CHexBuffer::documentSize( void )
{
return( mDocumentSize );
}
inline CHexBuffer::EEditMode CHexBuffer::editMode( void )
{
return( mEditMode );
}
inline const SEncodeState &CHexBuffer::encoding( void )
{
return( mEncode.state() );
}
inline bool CHexBuffer::losslessEncoding( CConversion::EMode mode )
{
return( mEncode.lossless(mode) );
}
inline TQString &CHexBuffer::url( void )
{
return( mUrl );
}
inline bool CHexBuffer::documentPresent( void )
{
return( size() == 0 ? false : true );
}
inline void CHexBuffer::setUrl( const TQString &url )
{
mUrl = url;
}
inline const TQDateTime &CHexBuffer::diskModifyTime( void )
{
return( mDiskModifyTime );
}
inline uint CHexBuffer::calculateLine( uint offset )
{
return( mLayout.lineSize == 0 ? 0 : offset / mLayout.lineSize );
}
inline const TQColor &CHexBuffer::foregroundColor( uint column )
{
if( column > mLayout.lineSize )
{
return( TQt::black );
}
else
{
return( mColor.primaryFg[ mColorIndex[ column ] ] );
}
}
inline bool CHexBuffer::selectionSet( uint offset, bool init )
{
if( offset >= size() ) { offset = size() > 0 ? size() - 1 : 0; }
if( init == true )
{
return( mSelect.init( offset ) );
}
else
{
return( mSelect.set( offset ) );
}
}
inline void CHexBuffer::selectionSyncronize( void )
{
mSelect.sync();
}
inline void CHexBuffer::selectionStartChange( uint &offset1, uint &offset2 )
{
mSelect.startChange( offset1, offset2 );
}
inline void CHexBuffer::selectionStopChange( uint &offset1, uint &offset2 )
{
mSelect.stopChange( offset1, offset2 );
}
inline bool CHexBuffer::cursorInsideSelection( void )
{
return( mSelect.inside( cursorOffset() ) );
}
inline void CHexBuffer::markSet( uint offset, uint size )
{
markSet( offset, true );
markSet( offset+size, false );
mMark.sync();
}
inline bool CHexBuffer::markSet( uint offset, bool init )
{
if( offset >= size() ) { offset = size() > 0 ? size() - 1 : 0; }
if( init == true )
{
return( mMark.init( offset ) );
}
else
{
return( mMark.set( offset ) );
}
}
inline bool CHexBuffer::markRemove( void )
{
return( mMark.init( mMark.start() ) );
}
inline void CHexBuffer::markSyncronize( void )
{
mMark.sync();
}
inline void CHexBuffer::markStartChange( uint &offset1, uint &offset2 )
{
mMark.startChange( offset1, offset2 );
}
inline void CHexBuffer::markStopChange( uint &offset1, uint &offset2 )
{
mMark.stopChange( offset1, offset2 );
}
inline uint CHexBuffer::cursorOffset( void )
{
return( mCursor.curr.offset );
}
inline uint CHexBuffer::cursorBit( void )
{
return( mCursor.bit() );
}
inline uint CHexBuffer::cursorLine( void )
{
return( mCursor.curr.y / lineHeight() );
}
inline uint CHexBuffer::prevCursorLine( void )
{
return( mCursor.prev.y / lineHeight() );
}
inline SCursor &CHexBuffer::cursor( void )
{
return( mCursor );
}
inline void CHexBuffer::currCursor( EEditArea editArea, SCursorPosition &p )
{
if( editArea == edit_primary )
{
if( mActiveEditor == edit_primary )
{
p.x = mCursor.curr.drawX1();
p.w = mCursor.curr.width1();
}
else
{
p.x = mCursor.curr.drawX2();
p.w = mUnitWidth;
}
}
else
{
if( mActiveEditor == edit_primary )
{
p.x = mCursor.curr.drawX2();
p.w = mUnitWidth;
}
else
{
p.x = mCursor.curr.drawX1();
p.w = mUnitWidth * mNumCell;
}
}
p.x -= mStartX;
p.y = mCursor.curr.y - mStartY;
p.h = lineHeight();
}
inline void CHexBuffer::prevCursor( EEditArea editArea, SCursorPosition &p )
{
if( editArea == edit_primary )
{
if( mActiveEditor == edit_primary )
{
p.x = mCursor.prev.drawX1();
p.w = mUnitWidth * mNumCell;
}
else
{
p.x = mCursor.prev.drawX2();
p.w = mUnitWidth;
}
}
else
{
if( mActiveEditor == edit_primary )
{
p.x = mCursor.prev.drawX2();
p.w = mUnitWidth;
}
else
{
p.x = mCursor.prev.drawX1();
p.w = mUnitWidth * mNumCell;
}
}
p.x -= mStartX;
p.y = mCursor.prev.y - mStartY;
p.h = lineHeight();
}
inline void CHexBuffer::cursorUp( uint lines )
{
mCursor.up( lines );
cursorCompute();
}
inline void CHexBuffer::cursorDown( uint lines )
{
mCursor.down( lines );
cursorCompute();
}
inline void CHexBuffer::cursorRight( bool cellLevel )
{
if( cellLevel == true && mActiveEditor == edit_primary )
{
mCursor.incCell();
}
else
{
mCursor.addOffset( 1 );
}
cursorCompute();
}
inline void CHexBuffer::cursorStep( uint size, bool forward, bool modulo )
{
if( forward == true )
{
if( modulo == true )
{
uint offset = mCursor.getOffset() + size;
mCursor.setOffset( offset - offset % size );
}
else
{
mCursor.addOffset( size );
}
}
else
{
if( modulo == true )
{
uint offset = mCursor.getOffset();
if( offset % size )
{
mCursor.decOffset( offset % size, false );
}
else
{
mCursor.setOffset( offset < size ? 0 : offset - size );
}
}
else
{
mCursor.decOffset( size, false );
}
}
cursorCompute();
}
inline void CHexBuffer::cursorLeft( bool cellLevel )
{
if( cellLevel == true && mActiveEditor == edit_primary )
{
mCursor.decCell();
}
else
{
mCursor.decOffset( 1, false );
}
cursorCompute();
}
inline void CHexBuffer::cursorHome( bool toExtreme )
{
mCursor.home( toExtreme );
cursorCompute();
}
inline void CHexBuffer::cursorEnd( bool toExtreme )
{
mCursor.end( toExtreme );
cursorCompute();
}
inline void CHexBuffer::cursorGoto( uint offset, uint bit, bool backward,
bool fromCursor )
{
uint maxOffset = mFixedSizeMode == true ? mMaximumSize-1 : documentSize();
mCursor.setOffset( offset, bit, backward, fromCursor, maxOffset );
cursorCompute();
}
inline void CHexBuffer::cursorGoto( uint offset, uint bit )
{
mCursor.setOffset( offset );
mCursor.setBit( bit );
cursorCompute();
}
inline bool CHexBuffer::cursorChanged( void )
{
return( mCursor.changed() );
}
inline void CHexBuffer::cursorResetEditArea( void )
{
mCursor.setArea( edit_none );
}
inline bool CHexBuffer::cursorPrimaryEdit( void )
{
return( mActiveEditor == edit_primary ? true : false );
}
inline int CHexBuffer::cursorFixedPosition( int position, int height )
{
position += mCursor.curr.y - mCursor.prev.y;
if( position < 0 )
{
return( 0 );
}
else if( position + height > totalHeight() )
{
return( height > totalHeight() ? 0 : totalHeight() - height );
}
else
{
if( mCursor.curr.y < position )
{
return( mCursor.curr.y );
}
else if( mCursor.curr.y > position + height )
{
return( mCursor.curr.y - height + lineHeight() );
}
else
{
return( position );
}
}
}
inline int CHexBuffer::cursorChangePosition( int position, int height )
{
if( mCursor.curr.y < position || mCursor.curr.y > position + height )
{
// When cursor is at top of window
position = mCursor.curr.y;
}
else if( mCursor.curr.y > position + height - lineHeight() )
{
// When cursor is at bottom of window
position = mCursor.curr.y - height + lineHeight();
}
return( position );
}
inline int CHexBuffer::printDummyCell( char *buf, unsigned char )
{
buf[0] = 0;
return( 0 );
}
inline int CHexBuffer::printHexadecimalBigCell( char *buf, unsigned char data )
{
buf[0] = mHexBigBuffer[ (data>>4)&0x0F ];
buf[1] = mHexBigBuffer[ data&0x0F ];
return( 0 );
}
inline int CHexBuffer::printHexadecimalSmallCell( char *buf,
unsigned char data )
{
buf[0] = mHexSmallBuffer[ (data>>4)&0x0F ];
buf[1] = mHexSmallBuffer[ data&0x0F ];
return( 0 );
}
inline int CHexBuffer::printDecimalCell( char *buf, unsigned char data )
{
buf[0] = mDecBuffer[ data/100 ];
data -= (data/100) * 100;
buf[1] = mDecBuffer[ data/10 ];
data -= (data/10) * 10;
buf[2] = mDecBuffer[ data ];
return( 0 );
}
inline int CHexBuffer::printOctalCell( char *buf, unsigned char data )
{
buf[0] = mOctBuffer[ (data>>6)&0x07 ];
buf[1] = mOctBuffer[ (data>>3)&0x07 ];
buf[2] = mOctBuffer[ data&0x07 ];
return( 0 );
}
inline int CHexBuffer::printBinaryCell( char *buf, unsigned char data )
{
for( int i = 0; i < 8; i++ )
{
buf[7-i] = (data&(1<<i)) ? '1' : '0';
}
return( 0 );
}
inline int CHexBuffer::printAsciiCell( char *buf, unsigned char data )
{
if( mCharValid[data] == 0 )
{
buf[0] = mFontInfo.nonPrintChar;
return( 1 );
}
else
{
buf[0] = data;
return( 0 );
}
}
inline void CHexBuffer::printDummyOffset( char *buf, uint /*offset*/ )
{
buf[0] = 0;
}
inline void CHexBuffer::printHexadecimalBigOffset( char *buf, uint offset )
{
sprintf( buf, "%04X:%04X", offset>>16, offset&0x0000FFFF );
}
inline void CHexBuffer::printHexadecimalSmallOffset( char *buf, uint offset )
{
sprintf( buf, "%04x:%04x", offset>>16, offset&0x0000FFFF );
}
inline void CHexBuffer::printDecimalOffset( char *buf, uint offset )
{
sprintf( buf, "%010u", offset );
}
inline int CHexBuffer::lineSize( void )
{
return( mLayout.lineSize );
}
inline int CHexBuffer::lineHeight( void )
{
return( mFontHeight + mLayout.horzGridWidth );
}
inline int CHexBuffer::fontAscent( void )
{
return( mFontAscent );
}
inline int CHexBuffer::lineWidth( void )
{
return( mLineWidth );
}
inline int CHexBuffer::unitWidth( void )
{
return( mUnitWidth );
}
inline int CHexBuffer::numLines( void )
{
return( mNumLines );
}
inline int CHexBuffer::totalHeight( void )
{
return( mNumLines * (mFontHeight+mLayout.horzGridWidth) );
}
inline const TQFont &CHexBuffer::font( void )
{
return( mFontInfo.font );
}
inline SCursor *CHexBuffer::textCursor( void )
{
return( &mCursor );
}
inline const TQColor &CHexBuffer::backgroundColor( void )
{
return( documentPresent() == true ? mColor.textBg : mColor.inactiveBg );
}
inline int CHexBuffer::startX( void )
{
return( mStartX );
}
inline int CHexBuffer::startY( void )
{
return( mStartY );
}
inline void CHexBuffer::setStartX( int val )
{
mStartX = val;
}
inline void CHexBuffer::setStartY( int val )
{
mStartY = val;
}
#endif