/* * khexedit - Versatile hex editor * Copyright (C) 1999-2000 Espen Sand, espensa@online.no * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include #include #include #include #include #include #include #include #include #include #include "hexbuffer.h" #include "hexerror.h" // // There are some comments marked with a "// ##" at various places. // These indicate a patch from Sergey A. Sukiyazov which I have applied // "as is" for now. The number of TQString::fromLocal8Bit in this modification // indicates that I should perhaps modify code elsewhere as well // (espen 2000-11-26) // // #define DEBUG_FIXED_SIZE 1024 // #define PRINTER_TEST CHexAction::CHexAction( HexAction action, uint offset ) { mAction = action; mOffset = offset; mSize = 0; mData = 0; mDataSize = 0; mNext = 0; } CHexAction::~CHexAction( void ) { delete [] mData; } void CHexAction::setData( uint size, char *data, uint dataSize ) { if( data != 0 && dataSize > 0 ) { mData = new char[ dataSize ]; if( mData == 0 ) { return; } memcpy( mData, data, dataSize ); mDataSize = dataSize; } else { mDataSize = 0; mData = 0; } mSize = size; } CHexActionGroup::CHexActionGroup( uint startOffset, uint startBit ) { mStartOffset = startOffset; mStartBit = startBit; mHexAction = 0; } CHexActionGroup::~CHexActionGroup( void ) { CHexAction *ptr = mHexAction; while( ptr != 0 ) { CHexAction *next = ptr->mNext; delete ptr; ptr = next; } } void CHexActionGroup::insertAction( CHexAction *hexAction ) { hexAction->mNext = mHexAction; mHexAction = hexAction; } int SFilterControl::execute( uchar *dest, uchar *src, uint size ) { if( size == 0 ) { return( Err_IllegalArgument ); } uint numElement = operand.size(); if( operation == OperandAndData ) { if( numElement == 0 ) { return( Err_IllegalArgument ); } if( forward == true ) { for( uint i = 0; i < size; ) { for( uint j = 0; i < size && j < numElement; j++, i++ ) { dest[i] = src[i] & operand[j]; } } } else { for( uint i = size; i > 0; ) { for( uint j = numElement; i > 0 && j > 0; j--, i-- ) { dest[i-1] = src[i-1] & operand[j-1]; } } } } else if( operation == OperandOrData ) { if( numElement == 0 ) { return( Err_IllegalArgument ); } if( forward == true ) { for( uint i = 0; i < size; ) { for( uint j = 0; i < size && j < numElement; j++, i++ ) { dest[i] = src[i] | operand[j]; } } } else { for( uint i = size; i > 0; ) { for( uint j = numElement; i > 0 && j > 0; j--, i-- ) { dest[i-1] = src[i-1] | operand[j-1]; } } } } else if( operation == OperandXorData ) { if( numElement == 0 ) { return( Err_IllegalArgument ); } if( forward == true ) { for( uint i = 0; i < size; ) { for( uint j = 0; i < size && j < numElement; j++, i++ ) { dest[i] = src[i] ^ operand[j]; } } } else { for( uint i = size; i > 0; ) { for( uint j = numElement; i > 0 && j > 0; j--, i-- ) { dest[i-1] = src[i-1] ^ operand[j-1]; } } } } else if( operation == InvertData ) { for( uint i = 0; i < size; i++ ) { dest[i] = ~src[i]; } } else if( operation == ReverseData ) { for( uint i = 0; i < size; i++ ) { uchar flag = src[i]; uchar rev = 0; for( uint j = 0; j < 8; j++ ) { rev |= (((flag & 0x80) >> (7-j))); flag <<= 1; } dest[i] = rev; } } else if( operation == RotateData || operation == ShiftData ) { // // Only forward here // bool up = rotate[1] > 0 ? true : false; int range = rotate[0]; int shift = abs(rotate[1]); if( range == 0 || shift == 0 ) { return( Err_IllegalArgument ); } shift = shift % (range*8); int b = shift / 8; int s = shift - b * 8; for( uint i = 0; i < size; ) { if( up == true ) { int j; if( operation == RotateData ) { for( j=0; j < b && i+range < size ; i++, j++ ) { dest[i] = src[i+range-b]; } } else { for( j=0; j < b && i < size ; dest[i] = 0, i++, j++ ); } for( ; j < range && i < size ; i++, j++ ) { dest[i] = src[i-b]; } uchar last = dest[i-1]; for( int k=1; k <= j; k++ ) { dest[i-k] >>= s; if( k < j ) { dest[i-k] |= dest[i-k-1]<<(8-s); } else if( j == range && operation == RotateData ) { dest[i-k] |= last<<(8-s); } } } else { int j; for( j=0; j+b < range && i+b < size ; i++, j++ ) { dest[i] = src[i+b]; } for( ; j < range && i < size ; i++, j++ ) { dest[i] = operation == RotateData ? src[i+b-range] : 0; } uchar first = dest[i-j]; for( int k=j; k>0; k-- ) { dest[i-k] <<= s; if( k>1 ) { dest[i-k] |= dest[i-k+1]>>(8-s); } else if( j == range && operation == RotateData ) { dest[i-k] |= first>>(8-s); } } } } } else if( operation == SwapBits ) { // // Swap bits. Based on Leon Lessing's work. // // // Make non swapped version first. // for( uint i = 0; i < size; i++ ) { dest[i] = src[i]; } // // Swap the pairs the have been defined // Format of operand (example): // 7 2 5 0 0 0 0 0 // Swap bit 7 with bit 2 and swap bit 5 with bit 0 // for( uint j=0; j<4; j++ ) { uchar b1 = 1 << (uchar)operand[j*2]; uchar b2 = 1 << (uchar)operand[j*2+1]; if( b1 == b2 ) { continue; } // Equal, no need to swap. for( uint i = 0; i < size; i++ ) { uchar b = 0; if( dest[i] & b1 ) { b |= b2; } if( dest[i] & b2 ) { b |= b1; } // // A short description so that I will understand what the // h... is going on five minutes from now. // // Destination byte is masked (AND'ed) with the inverse bitmap // (the noninversed bitmap contains position of the // two swap bits, eg 7-2 gives 10000100). Then the destination // is OR'ed with the swapped bitmap. // dest[i] = (dest[i] & ~(b1 | b2)) | b; } } } else { return( Err_IllegalArgument ); } return( Err_Success ); } const char *SExportCArray::printFormatted( const char *b, uint maxSize ) const { static char buf[12]; if( elementType == Char ) { char e = 0; memcpy( &e, b, TQMIN(sizeof(e),maxSize) ); sprintf( buf, "%d", e ); return( buf ); } else if( elementType == Uchar ) { unsigned char e = 0; memcpy( &e, b, TQMIN(sizeof(e),maxSize) ); if( unsignedAsHexadecimal == true ) { sprintf( buf, "0x%02x", e ); } else { sprintf( buf, "%u", e ); } return( buf ); } else if( elementType == Short ) { short e = 0; memcpy( &e, b, TQMIN(sizeof(e),maxSize) ); sprintf( buf, "%d", e ); return( buf ); } else if( elementType == Ushort ) { unsigned short e = 0; memcpy( &e, b, TQMIN(sizeof(e),maxSize) ); if( unsignedAsHexadecimal == true ) { sprintf( buf, "0x%04x", e ); } else { sprintf( buf, "%u", e ); } return( buf ); } else if( elementType == Int ) { int e = 0; memcpy( &e, b, TQMIN(sizeof(e),maxSize) ); sprintf( buf, "%u", e ); return( buf ); } else if( elementType == Uint ) { unsigned int e = 0; memcpy( &e, b, TQMIN(sizeof(e),maxSize) ); if( unsignedAsHexadecimal == true ) { sprintf( buf, "0x%08x", e ); } else { sprintf( buf, "%u", e ); } return( buf ); } else if( elementType == Float ) { float e = 0; memcpy( &e, b, TQMIN(sizeof(e),maxSize) ); sprintf( buf, "%f", e ); return( buf ); } else if( elementType == Double ) { double e = 0; memcpy( &e, b, TQMIN(sizeof(e),maxSize) ); sprintf( buf, "%f", e ); return( buf ); } else { return(""); } } TQString SExportCArray::variableName( uint range ) const { const char *typeString[] = { "char", "unsigned char", "short", "unsigned short", "int", "unsigned int", "float", "double" }; uint es = elementSize(); uint numElement = range / es + ((range % es) ? 1 : 0); return( TQString("%1 %2[%2]").tqarg(typeString[elementType]). tqarg(arrayName).tqarg(numElement) ); } int SExportCArray::elementSize( void ) const { if( elementType == Char || elementType == Uchar ) { return( sizeof(char) ); } else if( elementType == Short || elementType == Ushort ) { return( sizeof(short) ); } else if( elementType == Int || elementType == Uint ) { return( sizeof(int) ); } else if( elementType == Float ) { return( sizeof(float) ); } else if( elementType == Double ) { return( sizeof(double) ); } else { return(1); } } char CHexBuffer::mHexBigBuffer[16]= { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' }; char CHexBuffer::mHexSmallBuffer[16]= { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' }; char CHexBuffer::mDecBuffer[10]= { '0','1','2','3','4','5','6','7','8','9' }; char CHexBuffer::mOctBuffer[8]= { '0','1','2','3','4','5','6','7' }; SCursorState CHexBuffer::mCursorState; SFileState CHexBuffer::mFileState; CHexBuffer::CHexBuffer( void ) :TQByteArray() { mColorIndex = 0; mPrintBuf = 0; mLoadingData = false; mEditMode = EditReplace; mActiveEditor = edit_primary; mDocumentModified = false; #ifdef DEBUG_FIXED_SIZE setMaximumSize( DEBUG_FIXED_SIZE ); #else setMaximumSize( ~0 ); #endif setDocumentSize(0); #ifdef PRINTER_TEST puts(" Printer test is activated"); #endif setInputMode( mInputMode ); int errCode = setLayout( mLayout ); if( errCode != 0 ) { return; } setColor( mColor ); setFont( mFontInfo.init() ); setShowCursor( true ); setDisableCursor( false ); setEditMode( EditReplace, false, false ); setSoundState( false, false ); mUndoLimit = 10; mUndoIndex = 0; mUndoList.setAutoDelete( TRUE ); mBookmarkList.setAutoDelete( TRUE ); } CHexBuffer::~CHexBuffer( void ) { //debug("CHexBuffer::~CHexBuffer"); delete [] mColorIndex; delete [] mPrintBuf; } bool CHexBuffer::hasFileName( void ) { // // FIXME: Files can be called "Untitled" so this must be corrected. // if( mUrl.isEmpty() || mUrl.contains( i18n( "Untitled" ), false ) ) { return( false ); } else { return( true ); } } int CHexBuffer::setLayout( SDisplayLayout &tqlayout ) { mLayout = tqlayout; mLayout.verify(); if( mLayout.primaryMode == SDisplayLayout::textOnly ) { mActiveEditor = edit_primary; setEditMode( mEditMode ); } mCursor.setLineSize( mLayout.lineSize ); mCursor.addOffset( 0 ); // This will only reset the cell position computeLineWidth(); cursorCompute(); delete [] mColorIndex; mColorIndex = 0; delete [] mPrintBuf; mPrintBuf = 0; mColorIndex = new unsigned char[ mLayout.lineSize ]; if( mColorIndex == 0 ) { return( Err_NoMemory ); } setColor( mColor ); // // The 'mPrintBuf' is used to store formatted text. It is used for all // print operations and must have the size of the 'mDpyState.lineSize' which // is the number of bytes in one single display line. // mPrintBuf = new char[ mLayout.lineSize < 12 ? 12 : mLayout.lineSize ]; if( mPrintBuf == 0 ) { delete [] mColorIndex; mColorIndex = 0; return( Err_NoMemory ); } return( Err_Success ); } void CHexBuffer::setColor( SDisplayColor &color ) { mColor = color; // // Test... // //mColor.secondTextBg = TQt::yellow; //mColor.offsetBg = TQt::lightGray; //mColor.gridFg = TQt::darkCyan; /* mColor.secondTextBg = mColor.textBg; mColor.offsetBg = mColor.textBg; mColor.gridFg = mColor.textBg; */ if( mColorIndex != 0 ) { uint columnSize = mLayout.columnSize == 0 ? 1 : mLayout.columnSize; for( uint i = 0, entry = 0; i < mLayout.lineSize; i++ ) { if( i > 0 && i % columnSize == 0 ) { entry = entry == 0 ? 1 : 0; } mColorIndex[i] = entry; } } } void CHexBuffer::setInputMode( SDisplayInputMode &mode ) { mInputMode = mode; if( mInputMode.allowResize == false && mEditMode != EditReplace ) { setEditMode( EditReplace ); } } bool CHexBuffer::toggleEditor( void ) { bool changed; if( mLayout.secondaryMode == SDisplayLayout::hide ) { changed = mActiveEditor == edit_secondary ? true : false; mActiveEditor = edit_primary; } else { changed = true; mActiveEditor = mActiveEditor == edit_primary ? edit_secondary : edit_primary; } setEditMode( mEditMode ); // Sets the cursor tqshapes as well if( changed == true ) { mCursor.resetCell(); cursorCompute(); } return( changed ); } bool CHexBuffer::matchWidth( uint width ) { if( documentPresent() == false || (uint)mFixedWidth >= width ) { return( false ); } width -= mFixedWidth; uint g = mLayout.columnSpacing == 0 ? 1 : mLayout.columnSize; uint n = g * mNumCell; uint u = mUnitWidth; uint s = mLayout.secondaryMode == SDisplayLayout::hide ? 0 : g; uint o = mLayout.columnSpacing == 0 ? 0 : mSplitWidth; float x = (float)(width+o)/(float)(u*(n+s)+o); uint lineSize = (uint)x * g; if( mLayout.lockColumn == false ) { // // Examine if we can add one or more entries from the next column. This // will make the rightmost column smaller than the rest but we will // utilize as much of the available space (ie., width) as possible. // (Note that the entry itself (which represents one byte of filedata) // can not be splitted, eg., in binary mode the entry is eight byte // wide and will not be splitted). // int w = (int)((float)((int)x)* (float)(u*(n+s)+o) - (float)o); if( w > 0 && (uint)w < width ) { width -= w; if( width > o ) { x = (float)(width-o) / (float)(u*(mNumCell+1)); lineSize += (uint)x; } } } if( lineSize == 0 || lineSize == mLayout.lineSize ) { // // We have to redraw all text if a change occurs so we avoid it if // possible. // return( false ); } mLayout.lineSize = lineSize; setLayout( mLayout ); return( true ); } void CHexBuffer::setNonPrintChar( TQChar nonPrintChar ) { mFontInfo.nonPrintChar = nonPrintChar; } void CHexBuffer::setShowCursor( bool showCursor ) { mShowCursor = showCursor; } void CHexBuffer::setDisableCursor( bool disableCursor ) { mDisableCursor = disableCursor; } void CHexBuffer::settqCursorShapeModifier( bool alwaysBlock, bool thickInsert ) { mCursor.setShapeModifier( alwaysBlock, thickInsert ); setEditMode( mEditMode ); } void CHexBuffer::setEditMode( EEditMode editMode, bool alwaysBlock, bool thickInsert ) { mCursor.setShapeModifier( alwaysBlock, thickInsert ); setEditMode( editMode ); } void CHexBuffer::setEditMode( EEditMode editMode ) { mEditMode = editMode; if( mEditMode == EditInsert ) { if( mActiveEditor == edit_primary ) { mCursor.setShape( SCursorSpec::thin, SCursorSpec::frame, mUnitWidth, mNumCell ); } else { mCursor.setShape( SCursorSpec::frame, SCursorSpec::thin, mUnitWidth, mNumCell ); } } else { if( mActiveEditor == edit_primary ) { mCursor.setShape( SCursorSpec::solid, SCursorSpec::frame, mUnitWidth, mNumCell ); } else { mCursor.setShape( SCursorSpec::frame, SCursorSpec::solid, mUnitWidth, mNumCell ); } } } void CHexBuffer::setMaximumSize( uint tqmaximumSize ) { if( tqmaximumSize == 0 ) { tqmaximumSize = ~0; } mMaximumSize = tqmaximumSize; mFixedSizeMode = tqmaximumSize == (uint)~0 ? false : true; mCursor.setFixedSizeMode( mFixedSizeMode ); if( mLayout.offsetVisible == false ) { mOffsetSize = 0; mOffsetIndex = 0; printOffset = &CHexBuffer::printDummyOffset; } else { if( mLayout.offsetMode == SDisplayLayout::decimal ) { printOffset = &CHexBuffer::printDecimalOffset; for( mOffsetSize=0; tqmaximumSize > 0; mOffsetSize += 1 ) { tqmaximumSize = tqmaximumSize / 10; } mOffsetIndex = 10 - mOffsetSize; } else if( mLayout.offsetMode == SDisplayLayout::hexadecimal ) { if( mLayout.offsetUpperCase == true ) { printOffset = &CHexBuffer::printHexadecimalBigOffset; } else { printOffset = &CHexBuffer::printHexadecimalSmallOffset; } for( mOffsetSize=0; tqmaximumSize > 0; mOffsetSize += 1 ) { tqmaximumSize = tqmaximumSize / 16; } if( mOffsetSize > 4 ) { mOffsetSize += 1; } // Space for the ':' sign mOffsetIndex = 9 - mOffsetSize; } else { mLayout.offsetVisible = false; mOffsetSize = 0; mOffsetIndex = 0; printOffset = &CHexBuffer::printDummyOffset; } } } void CHexBuffer::setDocumentSize( uint size ) { if( size > mMaximumSize ) { size = mMaximumSize; } mDocumentSize = size; mCursor.setDocumentSize( size ); updateBookmarkMap(true); } void CHexBuffer::setUndoLevel( uint level ) { if( level < 10 ) { level = 10; } if( level >= mUndoLimit ) { mUndoLimit = level; return; } else { // // The maximum size decreases. If the list is larger than the the new // limit, then reduce the list size starting with the oldest elements. // mUndoLimit = level; while( mUndoList.count() >= mUndoLimit ) { mUndoList.removeFirst(); mUndoIndex -= (mUndoIndex > 0 ? 1 : 0); } } } void CHexBuffer::setSoundState( bool inputSound, bool fatalSound ) { mInputErrorSound = inputSound; mFatalErrorSound = fatalSound; } void CHexBuffer::setBookmarkVisibility( bool showInColumn, bool showInEditor ) { mShowBookmarkInOffsetColumn = showInColumn; mShowBookmarkInEditor = showInEditor; } int CHexBuffer::writeFile( TQFile &file, CProgress &p ) { uint offset = 0; uint remaining = documentSize(); do { const uint blockSize = TQMIN( 131072 /* == 1024 * 128 */ , remaining ); const int writeSize = file.writeBlock( data() + offset, blockSize ); if( writeSize == -1 ) { p.finish(); return( Err_ReadFailed ); } offset += blockSize; remaining -= blockSize; if( p.expired() == true ) { int errCode = p.step( (float)offset/(float)documentSize() ); if( errCode == Err_Stop && remaining > 0 ) { p.finish(); return( Err_Success ); } } } while( remaining > 0 ); p.finish(); mDocumentModified = false; registerDiskModifyTime( file ); return( Err_Success ); } int CHexBuffer::readFile( TQFile &file, const TQString &url, CProgress &p ) { if( tqresize( file.size() + 100 ) == false ) { p.finish(); return( Err_NoMemory ); } if( file.size() > 0 ) { mLoadingData = true; uint offset = 0; uint remaining = file.size(); while( remaining > 0 ) { const uint blockSize = TQMIN( 131072 /* == 1024 * 128 */ , remaining ); const int readSize = file.readBlock( data() + offset, blockSize ); if( readSize == -1 ) { p.finish(); mLoadingData = false; return( Err_ReadFailed ); } for( uint i=0; i 0 ) { p.finish(); return( Err_OperationAborted ); } } } mLoadingData = false; } p.finish(); mDocumentModified = false; setDocumentSize( file.size() ); registerDiskModifyTime( file ); setUrl( url ); computeNumLines(); mSelect.reset(); mMark.reset(); mUndoList.clear(); mUndoIndex = 0; return( Err_Success ); } int CHexBuffer::insertFile( TQFile &file, CProgress &p ) { if( file.size() == 0 ) { p.finish(); return( Err_Success ); } TQByteArray array( file.size() ); if( array.isNull() == true ) { p.finish(); return( Err_NoMemory ); } uint offset = 0; uint remaining = file.size(); while( remaining > 0 ) { const uint blockSize = TQMIN( 131072 /* == 1024 * 128 */ , remaining ); const int readSize = file.readBlock( array.data() + offset, blockSize ); if( readSize == -1 ) { p.finish(); return( Err_ReadFailed ); } for( uint i=0; i 0 ) { p.finish(); return( Err_OperationAborted ); } } } p.finish(); int errCode = inputAtCursor( array, 0 ); return( errCode ); } int CHexBuffer::newFile( const TQString &url ) { if( tqresize( 100 ) == 0 ) { return( Err_NoMemory ); } mDocumentModified = false; setDocumentSize( 0 ); setUrl( url ); computeNumLines(); mSelect.reset(); return( Err_Success ); } void CHexBuffer::closeFile( void ) { resize(0); computeNumLines(); mUndoList.clear(); mUndoIndex = 0; setDocumentSize(0); mDocumentModified = false; TQString emptyUrl; setUrl( emptyUrl ); mSelect.reset(); mMark.reset(); removeBookmark(-1); // Negative index - All bookmarks } void CHexBuffer::registerDiskModifyTime( const TQFile &file ) { TQFileInfo fileInfo( file ); mDiskModifyTime = fileInfo.lastModified(); } void CHexBuffer::setFont( const SDisplayFontInfo &fontInfo ) { mFontInfo = fontInfo; TQFontMetrics fm( mFontInfo.font ); mFontHeight = fm.height(); mFontAscent = fm.ascent(); computeLineWidth(); for( int i=0; i < 256; i++ ) { mCharValid[i] = TQChar(i).isPrint(); } /* TQFontInfo info( mFontInfo.font ); puts("CHexBuffer mCharValid broken"); KCharset charset( info.charSet() ); for( int i=0; i < 256; i++ ) { mCharValid[i] = charset.printable(i); } */ } int CHexBuffer::setEncoding( CConversion::EMode mode, CProgress &p ) { int errCode = mEncode.convert( *this, mode, p ); if( errCode == Err_Success ) { // // The cursor stores the byte it is "covering", so this information // must be updated. // cursorCompute(); } return( errCode ); } void CHexBuffer::computeLineWidth( void ) { TQFontMetrics fm( mFontInfo.font ); mUnitWidth = fm.width( "M" ); if( mLayout.primaryMode == SDisplayLayout::textOnly ) { mSplitWidth = 0; } else if( mLayout.columnCharSpace == true ) { mSplitWidth = mUnitWidth; } else { mSplitWidth = mLayout.columnSpacing; } setMaximumSize( mMaximumSize ); if( mLayout.primaryMode == SDisplayLayout::hexadecimal ) { mNumCell = 2; mCursor.setCellWeight( 4 ); if( mLayout.primaryUpperCase == true ) { printCell = &CHexBuffer::printHexadecimalBigCell; inputCell = &CHexBuffer::inputHexadecimal; } else { printCell = &CHexBuffer::printHexadecimalSmallCell; inputCell = &CHexBuffer::inputHexadecimal; } } else if( mLayout.primaryMode == SDisplayLayout::decimal ) { mNumCell = 3; printCell = &CHexBuffer::printDecimalCell; inputCell = &CHexBuffer::inputDecimal; mCursor.setCellWeight( 3 ); } else if( mLayout.primaryMode == SDisplayLayout::octal ) { mNumCell = 3; printCell = &CHexBuffer::printOctalCell; inputCell = &CHexBuffer::inputOctal; mCursor.setCellWeight( 3 ); } else if( mLayout.primaryMode == SDisplayLayout::binary ) { mNumCell = 8; printCell = &CHexBuffer::printBinaryCell; inputCell = &CHexBuffer::inputBinary; mCursor.setCellWeight( 1 ); } else if( mLayout.primaryMode == SDisplayLayout::textOnly ) { mNumCell = 1; printCell = &CHexBuffer::printAsciiCell; inputCell = &CHexBuffer::inputAscii; mCursor.setCellWeight( 8 ); } else { mNumCell = 2; mLayout.primaryMode = SDisplayLayout::hexadecimal; mLayout.primaryUpperCase = false; printCell = &CHexBuffer::printHexadecimalSmallCell; inputCell = &CHexBuffer::inputHexadecimal; mCursor.setCellWeight( 4 ); } // // 'mPrimaryWidth' is the number of pixels that are needed to display a // line in the primary field. // mPrimaryWidth = mLayout.lineSize * mNumCell * mUnitWidth; if( mLayout.columnSpacing != 0 ) { int numSplit = mLayout.lineSize / mLayout.columnSize; numSplit -= mLayout.lineSize % mLayout.columnSize == 0 ? 1 : 0; mPrimaryWidth += numSplit * mSplitWidth; } // // 'mSecondaryWidth' is the number of pixels that are needed to display a // line in the secondary field (there are no spaces). // if( mLayout.secondaryMode == SDisplayLayout::hide ) { mSecondaryWidth = 0; } else { mSecondaryWidth = mLayout.lineSize * mUnitWidth; } // // 'mLineWidth' is the total number of pixels required to display // offset data, separators, primary and secondary data on a line. // mLineWidth = mPrimaryWidth + mSecondaryWidth + mOffsetSize * mUnitWidth; // // The 'mFixedWidth' is the number of pixels of the width that stays the // same regardless of how many characters that are displayed. // This entity consists of the edge margins, the inner margins and the // separators. // mFixedWidth = mOffsetSize * mUnitWidth; // // The edge margin is always present in both ends. // mLineWidth += mLayout.edgeMarginWidth * 2; mFixedWidth += mLayout.edgeMarginWidth * 2; // // 'mTextStart1' is the number of pixels from the left edge where the // primary field starts. // mTextStart1 = mLayout.edgeMarginWidth; if( mLayout.offsetVisible == true ) { int width; if( mLayout.leftSeparatorWidth > 0 ) { width = mLayout.separatorMarginWidth * 2 + mLayout.leftSeparatorWidth; } else { width = (mLayout.separatorMarginWidth * 3) / 2; } mLineWidth += width; mFixedWidth += width; mTextStart1 += width + mOffsetSize * mUnitWidth; } // // 'mTextStart2' is the number of pixels from the left edge where the // secondary fields start. // mTextStart2 = mTextStart1; if( mLayout.secondaryMode != SDisplayLayout::hide ) { int width; if( mLayout.rightSeparatorWidth > 0 ) { width = mLayout.separatorMarginWidth * 2 + mLayout.rightSeparatorWidth; } else { width = (mLayout.separatorMarginWidth * 3) / 2; } mLineWidth += width; mFixedWidth += width; mTextStart2 += width + mPrimaryWidth; } setEditMode( mEditMode ); computeNumLines(); } void CHexBuffer::computeNumLines( void ) { if( mLayout.lineSize == 0 ) { mNumLines = 1; } else { uint s = mFixedSizeMode == true ? mMaximumSize : documentSize() + 1; mNumLines = s / mLayout.lineSize + (s % mLayout.lineSize ? 1 : 0); } } void CHexBuffer::drawSelection( TQPainter &paint, TQColor &color, uint start, uint stop, int sx ) { if( start >= stop ) { return; } uint width = stop - start; uint addStart, addWidth; addStart = (start / mLayout.columnSize) * mSplitWidth; if( width == 0 ) { addWidth = 0; } else { uint g = mLayout.columnSize; addWidth = (((start % g) + width - 1) / g) * mSplitWidth; } int offset = mTextStart1 - sx; paint.fillRect( offset + start * mNumCell * mUnitWidth + addStart, 0, width * mNumCell * mUnitWidth + addWidth, mFontHeight, color ); if( mLayout.secondaryMode != SDisplayLayout::hide ) { offset = mTextStart2 - sx; paint.fillRect( offset + start * mUnitWidth, 0, width * mUnitWidth, mFontHeight, color ); } } void CHexBuffer::drawText( TQPainter &paint, uint line, int sx, int x1, int x2 ) { uint fileOffset = line * mLayout.lineSize; if( documentPresent() == false || mLoadingData == true ) { paint.fillRect( x1, 0, x2-x1, lineHeight(), mColor.inactiveBg ); return; } bool outsideText; if( size() == 0 || fileOffset > documentSize() || fileOffset >= mMaximumSize) { outsideText = true; } else { outsideText = false; } if( (line+1) % 2 || outsideText == true ) { paint.fillRect( x1, 0, x2-x1, lineHeight(), mColor.textBg ); } else { paint.fillRect( x1, 0, x2-x1, lineHeight(), mColor.secondTextBg ); } if( mLayout.horzGridWidth > 0 && outsideText == false ) { paint.setPen( mColor.gridFg ); paint.drawLine( x1, mFontHeight, x2, mFontHeight ); } if( mSelect.inside( fileOffset, mLayout.lineSize ) == true ) { uint start = mSelect.start( fileOffset ); uint stop = mSelect.stop( fileOffset, mLayout.lineSize ); drawSelection( paint, mColor.selectBg, start, stop, sx ); } // // A marked area will be displayed "above" a selcted area (given // the mark background color is different) // if( mMark.inside( fileOffset, mLayout.lineSize ) == true ) { uint start = mMark.start( fileOffset ); uint stop = mMark.stop( fileOffset, mLayout.lineSize ); drawSelection( paint, mColor.markBg, start, stop, sx ); } uint dataSize; unsigned char *fileData; if( outsideText == true ) { if( size() == 0 ) { return; } dataSize = 0; fileData = 0; } else { dataSize = documentSize() - fileOffset; if( dataSize > mLayout.lineSize ) { dataSize = mLayout.lineSize; } fileData = (unsigned char*)&(data()[ fileOffset ]); } // // Compute the offset area size. We postpose the actual drawing // until we have drawn any bookmark indicators in the editor areas. // because we may want to draw an indicator in the offset area as well. // int offset = mLayout.edgeMarginWidth - sx; if( mLayout.offsetVisible == true ) { offset += mOffsetSize * mUnitWidth; if( mLayout.leftSeparatorWidth > 0 ) { offset += mLayout.leftSeparatorWidth + mLayout.separatorMarginWidth*2; } else { offset += (mLayout.separatorMarginWidth * 3) / 2; } } #if 0 int offset = mLayout.edgeMarginWidth - sx; if( mLayout.offsetVisible == true ) { int s0 = mOffsetSize * mUnitWidth; int s1 = s0 + mLayout.separatorMarginWidth + mLayout.edgeMarginWidth - sx; if( x1 < s1 && x2 > 0 ) { if( outsideText == true ) { paint.fillRect( 0, 0, s1, lineHeight(), mColor.offsetBg ); } else { // // I want to display the grid here so I cant use lineHeight() // paint.fillRect( 0, 0, s1, mFontHeight, mColor.offsetBg ); } } if( x1 < offset + s0 && x2 >= offset && fileData != 0 ) { paint.setPen( mColor.offsetFg ); THIS_FPTR(printOffset)( mPrintBuf, fileOffset ); // ## paint.drawText(offset,mFontAscent,&mPrintBuf[mOffsetIndex], // mOffsetSize); paint.drawText( offset, mFontAscent, TQString::fromLocal8Bit(&mPrintBuf[mOffsetIndex]), mOffsetSize ); } offset += s0; if( mLayout.leftSeparatorWidth > 0 ) { offset += mLayout.separatorMarginWidth; int s2 = mLayout.leftSeparatorWidth + mLayout.separatorMarginWidth; if( x1 < offset + s2 && x2 >= offset ) { TQPen pen( mColor.leftSeparatorFg, mLayout.leftSeparatorWidth ); paint.setPen( pen ); int center = offset + mLayout.leftSeparatorWidth/2; paint.drawLine( center, 0, center, lineHeight() ); } offset += s2; } else { offset += (mLayout.separatorMarginWidth * 3) / 2; } } #endif // // Draw the primary area // int localOffset = offset; for( uint i = 0; i < dataSize; i++ ) { int s = mNumCell * mUnitWidth + ((i+1) % mLayout.columnSize == 0) * mSplitWidth; if( x1 < localOffset + s && x2 >= localOffset ) { int flag = THIS_FPTR(printCell)( mPrintBuf, fileData[i] ); if( mSelect.inside( fileOffset+i ) ) { paint.setPen( mColor.selectFg ); } else if( mMark.inside( fileOffset+i ) ) { paint.setPen( mColor.markFg ); } else { paint.setPen( flag == 0 ? foregroundColor( i ) : mColor.nonPrintFg ); } // ## paint.drawText( localOffset, mFontAscent, mPrintBuf, mNumCell ); paint.drawText( localOffset, mFontAscent, TQString::fromLocal8Bit(mPrintBuf), mNumCell ); } localOffset += s; if( mLayout.vertGridWidth > 0 && i+1 < dataSize ) { if( (i+1) % mLayout.columnSize == 0 ) { paint.setPen( mColor.gridFg ); int x = localOffset - (mSplitWidth+1) / 2; paint.drawLine( x, 0, x, mFontHeight ); } } } // // Draw the secondary area // offset += mPrimaryWidth; if( mLayout.secondaryMode != SDisplayLayout::hide ) { if( mLayout.rightSeparatorWidth > 0 ) { offset += mLayout.separatorMarginWidth; int s = mLayout.separatorMarginWidth + mLayout.rightSeparatorWidth; if( x1 < offset + s && x2 >= offset ) { TQPen pen( mColor.rightSeparatorFg, mLayout.rightSeparatorWidth ); paint.setPen( pen ); int center = offset + mLayout.rightSeparatorWidth/2; paint.drawLine( center, 0, center, lineHeight() ); } offset += s; } else { offset += (mLayout.separatorMarginWidth * 3) / 2; } int s = mUnitWidth; for( uint i = 0; i < dataSize; i++ ) { if( x1 < offset + s && x2 >= offset ) { int flag = printAsciiCell( mPrintBuf, fileData[i] ); if( mSelect.inside( fileOffset+i ) ) { paint.setPen( mColor.selectFg ); } else if( mMark.inside( fileOffset+i ) ) { paint.setPen( mColor.markFg ); } else { paint.setPen( flag == 0 ? mColor.secondaryFg : mColor.nonPrintFg ); } // ## paint.drawText( offset, mFontAscent, mPrintBuf, 1 ); paint.drawText( offset, mFontAscent, TQString::fromLocal8Bit(mPrintBuf), 1 ); } offset += s; } } // // Draw the bookmark identifiers on this line (if any). We use the // bitmask to minimize the number of times we try to draw the bookmarks. // int bookmarkPosition = 0; if( mBookmarkMap.testBit(fileOffset/200) || mBookmarkMap.testBit((fileOffset+mLayout.lineSize-1)/200 ) ) { // Returns a bookmark postion state bookmarkPosition = drawBookmarks( paint, line, sx ); } // // Draw the offset area. We have delayed the drawing until now because // it is possible to draw a bookmark indicator in this area. // offset = mLayout.edgeMarginWidth - sx; if( mLayout.offsetVisible == true ) { int s0 = mOffsetSize * mUnitWidth; int s1 = s0 + mLayout.separatorMarginWidth + mLayout.edgeMarginWidth - sx; if( x1 < s1 && x2 > 0 ) { TQColor bg = mShowBookmarkInOffsetColumn && (bookmarkPosition & BookmarkOnLine) ? mColor.bookmarkBg : mColor.offsetBg; if( outsideText == true ) { paint.fillRect( 0, 0, s1, lineHeight(), bg ); } else { // // I want to display the grid here so I cant use lineHeight() // paint.fillRect( 0, 0, s1, mFontHeight, bg ); } } if( x1 < offset + s0 && x2 >= offset && fileData != 0 ) { paint.setPen( mShowBookmarkInOffsetColumn && bookmarkPosition & BookmarkOnLine ? mColor.bookmarkFg : mColor.offsetFg ); THIS_FPTR(printOffset)( mPrintBuf, fileOffset ); // ## paint.drawText(offset,mFontAscent,&mPrintBuf[mOffsetIndex], // mOffsetSize); paint.drawText( offset, mFontAscent, TQString::fromLocal8Bit(&mPrintBuf[mOffsetIndex]), mOffsetSize ); } offset += s0; if( mLayout.leftSeparatorWidth > 0 ) { offset += mLayout.separatorMarginWidth; int s2 = mLayout.leftSeparatorWidth + mLayout.separatorMarginWidth; if( x1 < offset + s2 && x2 >= offset ) { TQPen pen( mColor.leftSeparatorFg, mLayout.leftSeparatorWidth ); paint.setPen( pen ); int center = offset + mLayout.leftSeparatorWidth/2; paint.drawLine( center, 0, center, lineHeight() ); } } } // // If the cursors are located on the line we have drawn we redraw // them unless they have been disabled. // if( mDisableCursor == false ) { if( mCursor.curr.inside( fileOffset, fileOffset + mLayout.lineSize ) ) { drawCursor( paint, line, sx, bookmarkPosition & BookmarkOnCursor ); } } } void CHexBuffer::drawText( TQPainter &paint, uint line, int x1, int x2, int y, bool useBlackWhite ) { uint fileOffset = line * mLayout.lineSize; bool outsideText; if( size() == 0 || fileOffset > documentSize() || fileOffset >= mMaximumSize) { outsideText = true; } else { outsideText = false; } if( (line+1) % 2 || outsideText == true ) { paint.fillRect( x1, y, x2, lineHeight(), useBlackWhite == true ? TQt::white : mColor.textBg ); } else { paint.fillRect( x1, y, x2, lineHeight(), useBlackWhite == true ? TQt::white : mColor.secondTextBg ); } if( mLayout.horzGridWidth > 0 && outsideText == false ) { TQPen pen( useBlackWhite == true ? TQt::black : mColor.gridFg, mLayout.horzGridWidth ); paint.setPen( pen ); paint.drawLine( x1, y+mFontHeight, x2+x1, y+mFontHeight ); } uint dataSize; unsigned char *fileData; if( outsideText == true ) { if( size() == 0 ) { return; } dataSize = 0; fileData = 0; } else { dataSize = documentSize() - fileOffset; if( dataSize > mLayout.lineSize ) { dataSize = mLayout.lineSize; } fileData = (unsigned char*)&(data()[ fileOffset ]); } int offset = mLayout.edgeMarginWidth + x1; if( mLayout.offsetVisible == true ) { int s1 = mOffsetSize * mUnitWidth; if( fileData != 0 ) { paint.setPen( useBlackWhite == true ? TQt::black : mColor.offsetFg ); THIS_FPTR(printOffset)( mPrintBuf, fileOffset ); // ## paint.drawText( offset, mFontAscent+y, &mPrintBuf[mOffsetIndex], // mOffsetSize ); paint.drawText( offset, mFontAscent+y, TQString::fromLocal8Bit(&mPrintBuf[mOffsetIndex]), mOffsetSize ); } offset += s1; if( mLayout.leftSeparatorWidth > 0 ) { offset += mLayout.separatorMarginWidth; int s2 = mLayout.leftSeparatorWidth + mLayout.separatorMarginWidth; TQPen pen( useBlackWhite == true ? TQt::black : mColor.leftSeparatorFg, mLayout.leftSeparatorWidth ); paint.setPen( pen ); int center = offset + mLayout.leftSeparatorWidth/2; paint.drawLine( center, y, center, mFontHeight+y ); offset += s2; } else { offset += (mLayout.separatorMarginWidth * 3) / 2; } } int localOffset = offset; for( uint i = 0; i < dataSize; i++ ) { int s = mNumCell * mUnitWidth + ((i+1) % mLayout.columnSize == 0) * mSplitWidth; int flag = THIS_FPTR(printCell)( mPrintBuf, fileData[i] ); if( useBlackWhite == true ) { paint.setPen( TQt::black ); } else { paint.setPen( flag == 0 ? foregroundColor( i ) : mColor.nonPrintFg ); } // ## paint.drawText( localOffset, mFontAscent+y, mPrintBuf, mNumCell ); paint.drawText( localOffset, mFontAscent+y, TQString::fromLocal8Bit(mPrintBuf), mNumCell ); localOffset += s; if( mLayout.vertGridWidth > 0 && i+1 < dataSize ) { if( (i+1) % mLayout.columnSize == 0 ) { TQPen pen( useBlackWhite == true ? TQt::black : mColor.gridFg, mLayout.vertGridWidth ); paint.setPen( pen ); int x = localOffset - (mSplitWidth+1) / 2; paint.drawLine( x, y, x, y+mFontHeight ); } } } offset += mPrimaryWidth; if( mLayout.secondaryMode != SDisplayLayout::hide ) { if( mLayout.rightSeparatorWidth > 0 ) { offset += mLayout.separatorMarginWidth; int s = mLayout.separatorMarginWidth + mLayout.rightSeparatorWidth; TQPen pen( useBlackWhite == true ? TQt::black : mColor.rightSeparatorFg, mLayout.rightSeparatorWidth ); paint.setPen( pen ); int center = offset + mLayout.rightSeparatorWidth/2; paint.drawLine( center, y, center, mFontHeight+y ); offset += s; } else { offset += (mLayout.separatorMarginWidth * 3) / 2; } int s = mUnitWidth; for( uint i = 0; i < dataSize; i++ ) { int flag = printAsciiCell( mPrintBuf, fileData[i] ); if( useBlackWhite == true ) { paint.setPen( TQt::black ); } else { paint.setPen( flag == 0 ? mColor.secondaryFg : mColor.nonPrintFg ); } // ## paint.drawText( offset, mFontAscent+y, mPrintBuf, 1 ); paint.drawText( offset, mFontAscent+y, TQString::fromLocal8Bit(mPrintBuf), 1 ); offset += s; } } } int CHexBuffer::headerHeight( TQPainter &paint ) { TQFont font( paint.font() ); paint.setFont( KGlobalSettings::generalFont() ); const TQFontMetrics &fm = paint.fontMetrics(); int height = fm.height(); paint.setFont( font ); return( height ); } int CHexBuffer::headerMargin( TQPainter &paint ) { TQFont font( paint.font() ); paint.setFont( KGlobalSettings::generalFont() ); const TQFontMetrics &fm = paint.fontMetrics(); int margin = fm.height() / 2; paint.setFont( font ); return( margin ); } void CHexBuffer::drawHeader( TQPainter &paint, int sx, int width, int y, bool isFooter, const SPageHeader &header, const SPagePosition &position ) { TQFont font( paint.font() ); paint.setFont( KGlobalSettings::generalFont() ); const TQFontMetrics &fm = paint.fontMetrics(); paint.fillRect( sx, y, width, fm.height(), TQt::white ); paint.setPen( TQt::black ); if( header.line == SPageHeader::SingleLine ) { if( isFooter == false ) { paint.drawLine( sx, y+fm.height(), sx+width, y+fm.height() ); } else { paint.drawLine( sx, y, sx+width, y ); } } else if( header.line == SPageHeader::Rectangle ) { paint.drawRect( sx, y, width, fm.height() ); } int pos[3] = { TQPainter::AlignLeft, TQPainter::AlignHCenter, TQPainter::AlignRight }; TQString msg; for( int i=0; i<3; i++ ) { if( header.pos[i] == SPageHeader::DateTime ) { TQDateTime datetime; datetime.setTime_t( position.now ); msg = KGlobal::locale()->formatDateTime(datetime); } else if( header.pos[i] == SPageHeader::PageNumber ) { msg = i18n("Page %1 of %2") .tqarg(KGlobal::locale()->formatNumber(position.curPage, 0)) .tqarg(KGlobal::locale()->formatNumber(position.maxPage, 0)); } else if( header.pos[i] == SPageHeader::FileName ) { msg = mUrl; } else { continue; } if( 0 && pos[i] == TQPainter::AlignRight ) { //const TQFontMetrics &f = TQFontMetrics( KGlobalSettings::generalFont() ); //TQRect r = paint.boundingRect(sx, y, width, fm.height(), pos[i], msg ); //printf("R: %d, %d, %d, %d\n", r.x(), r.y(), r.width(), r.height() ); int x = sx + width - /*r.width();*/ fm.width(msg); paint.drawText( x, y+fm.height(), msg ); //printf("paint at %d\n", x ); } else { paint.drawText( sx, y, width, fm.height(), pos[i], msg ); } } // // restore original font. // paint.setFont( font ); } int CHexBuffer::drawBookmarks( TQPainter &paint, uint line, int startx ) { if( documentPresent() == false || mLoadingData == true ) { return( 0 ); } uint start = line*mLayout.lineSize; uint stop = start+mLayout.lineSize; TQColor bg = mColor.bookmarkBg; TQColor fg = mColor.bookmarkFg; int bookmarkPosition = 0; for( SCursorOffset *c=mBookmarkList.first(); c!=0; c=mBookmarkList.next() ) { if( c->offset >= start && c->offset < stop ) { int x = c->offset - start; int x1 = mTextStart1 + x * mUnitWidth * mNumCell; x1 += (x / mLayout.columnSize) * mSplitWidth; int x2 = mTextStart2 + x * mUnitWidth; bookmarkPosition |= BookmarkOnLine; if( mShowBookmarkInEditor == false ) { continue; } uint offset = line*mLayout.lineSize+x; if( offset == mCursor.curr.offset ) { bookmarkPosition |= BookmarkOnCursor; } if( mSelect.inside( offset ) || mMark.inside( offset ) ) { paint.fillRect( x1-startx, 2, mUnitWidth*mNumCell, mFontHeight-4, bg ); if( mLayout.secondaryMode != SDisplayLayout::hide ) { paint.fillRect( x2-startx, 2, mUnitWidth, mFontHeight-4, bg ); } } else { paint.fillRect( x1-startx, 1, mUnitWidth*mNumCell, mFontHeight-2, bg ); if( mLayout.secondaryMode != SDisplayLayout::hide ) { paint.fillRect( x2-startx, 1, mUnitWidth, mFontHeight-2, bg ); } } unsigned char c = (data()[ line*mLayout.lineSize+x]); int flag = THIS_FPTR(printCell)( mPrintBuf, c ); paint.setPen( flag == 0 ? fg : mColor.nonPrintFg ); // ## paint.drawText( x1-startx, mFontAscent, mPrintBuf, mNumCell ); paint.drawText( x1-startx, mFontAscent, TQString::fromLocal8Bit(mPrintBuf), mNumCell ); if( mLayout.secondaryMode != SDisplayLayout::hide ) { flag = printAsciiCell( mPrintBuf, c ); paint.setPen( flag == 0 ? fg : mColor.nonPrintFg ); // ## paint.drawText( x2-startx, mFontAscent, mPrintBuf, 1 ); paint.drawText( x2-startx, mFontAscent, TQString::fromLocal8Bit(mPrintBuf), 1 ); } } } return bookmarkPosition; } void CHexBuffer::drawCursor( TQPainter &paint, uint line, int startx, bool onBookmark ) { if( documentPresent() == false || mLoadingData == true ) { return; } SCursorSpec &c = mCursor.curr; // // Draw the cursor in primary edit area. // TQColor bg, fg; bool useFg; if( mMark.inside( c.offset ) == true ) { bg = mColor.markBg; fg = mSelect.inside( c.offset ) ? mColor.selectFg : mColor.markFg; useFg = true; } else if( mSelect.inside( c.offset ) == true ) { bg = mColor.selectBg; fg = mColor.selectFg; useFg = true; } else { bg = (line+1) % 2 ? mColor.textBg : mColor.secondTextBg; fg = foregroundColor( c.offset % mLayout.lineSize ); useFg = false; // Can be true later. } TQColor cbg = mColor.cursorBg; TQColor cfg = mColor.cursorFg; // // Fill in the general backround color // paint.fillRect( c.x1 - startx, 0, mUnitWidth, mFontHeight, bg ); if( onBookmark == true ) { int w = mUnitWidth * (mNumCell-c.cell); // Rest of cell if( useFg == true ) { paint.fillRect( c.x1-startx, 2, w, mFontHeight-4, mColor.bookmarkBg ); } else { paint.fillRect( c.x1-startx, 1, w, mFontHeight-2, mColor.bookmarkBg ); } } // // Draw the cursor tqshape // bool transparent = false; if( mActiveEditor == edit_primary ) { if( mShowCursor == true ) // Cursor blink on { if( c.mPrimaryShape == SCursorSpec::thin ) { paint.setPen( cbg ); int center = c.x1 - startx - 1; transparent = true; if( c.thickState == true ) { paint.drawLine( center, 0, center, mFontHeight - 1 ); paint.drawLine( center+1, 0, center+1, mFontHeight - 1 ); } else { paint.drawLine( center, 0, center, mFontHeight - 1 ); paint.drawLine( center-2, 0, center+2, 0 ); paint.drawLine( center-2, mFontHeight-1, center+2, mFontHeight-1 ); } } else // Solid block tqshape { paint.fillRect( c.x1 - startx, 0, mUnitWidth, mFontHeight, cbg ); useFg = true; fg = cfg; } } } else { transparent = true; paint.setPen( cbg ); paint.drawRect( c.x1 - startx, 0, mUnitWidth*mNumCell, mFontHeight ); } // // Draw the text on the cursor position and to the end of the cell. // if( c.offset < documentSize() ) { int flag = THIS_FPTR(printCell)( mPrintBuf, (unsigned char)c.data ); if( onBookmark == true ) { // Inside bookmark. Draw text with bookmark foreground. paint.setPen( mColor.bookmarkFg ); // ## paint.drawText( c.x1-startx, mFontAscent, &mPrintBuf[c.cell], // mNumCell-c.cell ); paint.drawText( c.x1-startx, mFontAscent, TQString::fromLocal8Bit(&mPrintBuf[c.cell]), mNumCell-c.cell ); } if( transparent == false || onBookmark == false ) { paint.setPen( flag == 0 || useFg == true ? fg : mColor.nonPrintFg ); // ## paint.drawText( c.x1 - startx, mFontAscent, &mPrintBuf[c.cell], 1); paint.drawText( c.x1 - startx, mFontAscent, TQString::fromLocal8Bit(&mPrintBuf[c.cell]), 1 ); } } // // Draw the cursor in secodary edit area. // if( mLayout.secondaryMode == SDisplayLayout::hide ) { return; } if( mMark.inside( c.offset ) == true ) { bg = mColor.markBg; fg = mSelect.inside( c.offset ) ? mColor.selectFg : mColor.markFg; useFg = true; } else if( mSelect.inside( c.offset ) == true ) { bg = mColor.selectBg; fg = mColor.selectFg; useFg = true; } else { bg = (line+1) % 2 ? mColor.textBg : mColor.secondTextBg; fg = mColor.secondaryFg; useFg = false; // Can be true later. } // // Fill in the general backround color // if( onBookmark == true ) { if( useFg == true ) { paint.fillRect( c.x2-startx, 2, mUnitWidth, mFontHeight-4, mColor.bookmarkBg ); } else { paint.fillRect( c.x2-startx, 1, mUnitWidth, mFontHeight-2, mColor.bookmarkBg ); } } else { paint.fillRect( c.x2 - startx, 0, mUnitWidth, mFontHeight, bg ); } // // Draw the cursor tqshape // transparent = false; if( mActiveEditor == edit_secondary ) { if( mShowCursor == true ) // Cursor blink on { if( c.mSecondaryShape == SCursorSpec::thin ) { paint.setPen( cbg ); int center = c.x2 - startx - 1; transparent = true; if( c.thickState == true ) { paint.drawLine( center, 0, center, mFontHeight - 1 ); paint.drawLine( center+1, 0, center+1, mFontHeight - 1 ); } else { paint.drawLine( center, 0, center, mFontHeight - 1 ); paint.drawLine( center-2, 0, center+2, 0 ); paint.drawLine( center-2, mFontHeight-1, center+2, mFontHeight-1 ); } } else { paint.fillRect( c.x2 - startx, 0, mUnitWidth, mFontHeight, cbg ); useFg = true; fg = cfg; } } } else { transparent = true; paint.setPen( cbg ); paint.drawRect( c.x2 - startx, 0, mUnitWidth, mFontHeight ); } // // Draw the text on the cursor position and to the end of the cell. // if( c.offset < documentSize() ) { int flag = printAsciiCell( mPrintBuf, (unsigned char)c.data ); if( onBookmark == true ) { // Inside bookmark. Draw text with bookmark foreground. paint.setPen( flag == 0 ? mColor.bookmarkFg : mColor.nonPrintFg ); // ## paint.drawText( c.x2-startx, mFontAscent, mPrintBuf, 1 ); paint.drawText( c.x2-startx, mFontAscent, TQString::fromLocal8Bit(mPrintBuf), 1 ); } if( transparent == false || onBookmark == false ) { paint.setPen( flag == 0 || useFg == true ? fg : mColor.nonPrintFg ); // ## paint.drawText( c.x2 - startx, mFontAscent, mPrintBuf, 1 ); paint.drawText( c.x2 - startx, mFontAscent, TQString::fromLocal8Bit(mPrintBuf), 1 ); } } } void CHexBuffer::cursorReset( void ) { mCursor.reset(); cursorCompute(); } void CHexBuffer::cursorCompute( void ) { mCursor.prev = mCursor.curr; if( mCursor.next.offset >= documentSize() ) { if( documentSize() == 0 ) { mCursor.curr.offset = 0; mCursor.curr.data = 0; mCursor.curr.cell = 0; mCursor.curr.maxCell = mNumCell; int x = mCursor.curr.offset % mLayout.lineSize; mCursor.curr.x1 = mTextStart1; mCursor.curr.x1 += (x * mNumCell + mCursor.curr.cell) * mUnitWidth; mCursor.curr.x1 += (x / mLayout.columnSize) * mSplitWidth; mCursor.curr.x2 = mTextStart2 + x * mUnitWidth; mCursor.curr.y = (mCursor.curr.offset/mLayout.lineSize) * (mFontHeight+mLayout.horzGridWidth); return; } if( mFixedSizeMode == true ) { uint max = mMaximumSize - 1; uint off = mCursor.curr.offset % mLayout.lineSize; uint end = max % mLayout.lineSize; if( off > end ) { uint diff = off - end; if( max + diff > mLayout.lineSize ) { mCursor.next.offset = max + diff - mLayout.lineSize; } else { mCursor.next.offset = 0; } } else { uint diff = end - off; mCursor.next.offset = diff > max ? max : max - diff; } } else { mCursor.next.offset = documentSize(); } } mCursor.curr.offset = mCursor.next.offset; mCursor.curr.data = data()[ mCursor.curr.offset ]; mCursor.curr.cell = mCursor.next.cell; mCursor.curr.maxCell = mNumCell; int x = mCursor.curr.offset % mLayout.lineSize; mCursor.curr.x1 = mTextStart1; mCursor.curr.x1 += (x * mNumCell + mCursor.curr.cell) * mUnitWidth; mCursor.curr.x1 += (x / mLayout.columnSize) * mSplitWidth; mCursor.curr.x2 = mTextStart2 + x * mUnitWidth; mCursor.curr.y = (mCursor.curr.offset/mLayout.lineSize) * (mFontHeight + mLayout.horzGridWidth); } bool CHexBuffer::setCursorPosition( int x, int y, bool init, bool cellLevel ) { if( documentPresent() == false ) { return( false ); } uint line = y < 0 ? 0 : y / lineHeight(); uint entry = 0; int bit = 7; if( init == false ) { if( mCursor.area() == edit_primary ) { int start = mTextStart1; if( x < start - (int)mLayout.separatorMarginWidth ) { return( false ); } else { int stop = mTextStart1 + mPrimaryWidth + mLayout.separatorMarginWidth; int width = mNumCell * mUnitWidth; int space = mSplitWidth; for( int position = start, i=0; position < stop; i++ ) { if( x <= position + width ) { if( cellLevel == true ) { while( bit > 0 ) { if( x <= position + mUnitWidth ) { break; } bit -= mCursor.cellWeight(); position += mUnitWidth; } } break; } position += width + (((i+1) % mLayout.columnSize) ? 0 : space); entry += 1; } } } else { int start = mTextStart2; if( x < start - (int)mLayout.separatorMarginWidth || mLayout.secondaryMode == SDisplayLayout::hide ) { return( false ); } int stop = mTextStart2 + mLayout.lineSize * mUnitWidth; int width = mUnitWidth * 1; int space = 0; for( int position = start; position < stop; ) { if( x <= position + width ) { break; } position += width + space; entry += 1; } } } else { int start = mTextStart1; int stop = start + mPrimaryWidth + mLayout.separatorMarginWidth; if( x >= start - (int)mLayout.separatorMarginWidth && x <= stop ) { int width = mUnitWidth * mNumCell; int space = mSplitWidth; for( int position = start, i=0; position < stop; i++ ) { if( x <= position + width ) { if( cellLevel == true ) { while( bit > 0 ) { if( x <= position + mUnitWidth ) { break; } bit -= mCursor.cellWeight(); position += mUnitWidth; } } break; } position += width + (((i+1) % mLayout.columnSize) ? 0 : space); entry += 1; } mActiveEditor = edit_primary; } else if( mLayout.secondaryMode != SDisplayLayout::hide ) { start = mTextStart2; stop = mTextStart2 + mLayout.lineSize * mUnitWidth + mLayout.edgeMarginWidth; if( x >= start - (int)mLayout.separatorMarginWidth && x <= stop ) { int width = mUnitWidth * 1; int space = 0; for( int position = start; position < stop; ) { if( x <= position + width ) { break; } position += width + space; entry += 1; } mActiveEditor = edit_secondary; } } else { return( false ); } } uint offset = line * mLayout.lineSize + entry; if( offset > documentSize() ) { offset = documentSize(); } mCursor.setOffset( offset ); mCursor.setBit( bit < 0 ? 0 : bit ); cursorCompute(); if( mActiveEditor != mCursor.area() ) { mCursor.setArea( mActiveEditor ); setEditMode( mEditMode ); } return( true ); } bool CHexBuffer::inputAtCursor( TQChar c ) { if( documentPresent() == false || mInputMode.noInput() == true ) { if( mInputMode.noInput() == true ) { inputSound(); } return( false ); } if( c.isPrint() == false ) { inputSound(); return( false ); } unsigned char dest; bool insert; if( mEditMode == EditReplace || mCursor.curr.cell > 0 ) { if( mCursor.curr.offset >= documentSize() ) { dest = 0; insert = true; } else { dest = (unsigned char)data()[ mCursor.curr.offset ]; insert = false; } } else { dest = 0; insert = true; } if( insert == true && mInputMode.allowResize == false ) { inputSound(); return( false ); } if( mActiveEditor == edit_primary ) { // ## if( THIS_FPTR(inputCell)( &dest, c.latin1(), mCursor.curr.cell ) //== false ) if( THIS_FPTR(inputCell)( &dest, TQString(c).local8Bit()[0], mCursor.curr.cell ) == false ) { inputSound(); return( false ); } } else if( mActiveEditor == edit_secondary ) { // ## if( inputAscii( &dest, c.latin1(), mCursor.curr.cell ) == false ) if( !inputAscii( &dest, TQString(c).local8Bit()[0], mCursor.curr.cell ) ) { inputSound(); return( false ); } } else { return( false ); } recordStart( mCursor ); recordReplace( mCursor, insert == true ? 0 : 1, (char*)&dest, 1 ); cursorRight( cursorPrimaryEdit() ); recordEnd( mCursor ); computeNumLines(); return( true ); } int CHexBuffer::inputAtCursor( const TQByteArray &buf, uint oldSize ) { if( documentPresent() == false ) { return( Err_NoActiveDocument ); } if( buf.isNull() == true ) { return( Err_EmptyArgument ); } if( mInputMode.noInput() == true ) { inputSound(); return( Err_WriteProtect ); } if( mInputMode.allowResize == false ) { inputSound(); return( Err_NoResize ); } recordStart( mCursor ); recordReplace( mCursor, oldSize, (char*)&buf[0], buf.size() ); cursorStep( buf.size(), true, false ); recordEnd( mCursor ); computeNumLines(); return( Err_Success ); } bool CHexBuffer::removeAtCursor( bool beforeCursor ) { if( documentPresent() == false ) { return( false ); } if( mInputMode.noInput() == true || mInputMode.allowResize == false ) { inputSound(); return( false ); } if( mSelect.valid() == true ) { cutSelection(); return( true ); } if( beforeCursor == true ) { if( mCursor.curr.offset == 0 ) { return( false ); } recordStart( mCursor ); cursorLeft( false ); recordReplace( mCursor, 1, 0, 0 ); recordEnd( mCursor ); computeNumLines(); return( true ); } else { if( mCursor.curr.offset + 1 > documentSize() ) { return( false ); } recordStart( mCursor ); recordReplace( mCursor, 1, 0, 0 ); recordEnd( mCursor ); computeNumLines(); return( true ); } } int CHexBuffer::locateRange(const SExportRange &range, uint &start, uint &stop) { if( range.mode == SExportRange::All ) { start = 0; stop = documentSize(); } else if( range.mode == SExportRange::Selection ) { if( mSelect.valid() == false ) { return( Err_NoSelection ); } start = mSelect.curr.start; stop = mSelect.curr.stop; } else if( range.mode == SExportRange::Range ) { start = range.start; stop = range.stop; } else { return( Err_IllegalMode ); } if( start >= stop ) { return( Err_IllegalRange ); } return( Err_Success ); } int CHexBuffer::exportText( const SExportText &ex, CProgress &p ) { uint start, stop; int errCode = locateRange( ex.range, start, stop ); if( errCode != Err_Success ) { p.finish(); return( errCode ); } TQFile file( ex.destFile ); if( file.open( IO_WriteOnly ) == false ) { p.finish(); return( Err_OpenWriteFailed ); } uint startLine = calculateLine( start ); if( startLine >= (uint)numLines() ) { startLine = numLines() == 0 ? 0 : numLines() - 1; } uint stopLine = calculateLine( stop ); if( stopLine >= (uint)numLines() ) { stopLine = numLines() == 0 ? 0 : numLines() - 1; } uint totalSize = stopLine - startLine + 1; uint remaining = stopLine - startLine + 1; uint bytePerLine = mOffsetSize + 1 + (mNumCell + 2)*mLayout.lineSize + 1; uint linePerStep = 20; TQByteArray array( bytePerLine * linePerStep + 1 ); // Line is 0 terminated if( array.isEmpty() == true ) { p.finish(); return( Err_NoMemory ); } while( remaining > 0 ) { uint blockSize = remaining > linePerStep ? linePerStep : remaining; uint printSize = 0; for( uint i = 0; i < blockSize; i++, startLine++ ) { printSize += printLine( &array[printSize], startLine ); } int writeSize = file.writeBlock( &array[0], printSize ); if( writeSize == -1 ) { p.finish(); return( Err_WriteFailed ); } remaining -= blockSize; if( p.expired() == true ) { int errCode = p.step( (float)(totalSize-remaining)/(float)totalSize ); if( errCode == Err_Stop && remaining > 0 ) { p.finish(); return( Err_OperationAborted ); } } } p.finish(); return( Err_Success ); } int CHexBuffer::exportHtml( const SExportHtml &ex, CProgress &p ) { uint start, stop; int errCode = locateRange( ex.range, start, stop ); if( errCode != Err_Success ) { p.finish(); return( errCode ); } uint startLine = calculateLine( start ); if( startLine >= (uint)numLines() ) { startLine = numLines() == 0 ? 0 : numLines() - 1; } uint stopLine = calculateLine( stop ); if( stopLine >= (uint)numLines() ) { stopLine = numLines() == 0 ? 0 : numLines() - 1; } uint totalSize = stopLine - startLine + 1; uint remaining = stopLine - startLine + 1; if( ex.linePerPage == 0 ) { p.finish(); return( Err_IllegalArgument ); } uint linePerPage = ex.linePerPage; uint numFiles = remaining/linePerPage + (remaining%linePerPage ? 1 : 0); uint fileCount = 0; TQStringList fileNames, offsets; TQString name, offset; for( uint i=0; i < numFiles; i++ ) { name.sprintf( "%08d.html", i+1 ); fileNames.append( TQString("%1/%2%3").tqarg(ex.package).tqarg(ex.prefix). arg(name)); } name.sprintf( "%08d.html", 0 ); TQString tocName =TQString("%1/%2%3").tqarg(ex.package).tqarg(ex.prefix).tqarg(name); TQString linkName; if( ex.symLink == true ) { linkName = TQString("%1/%2").tqarg(ex.package).tqarg("index.html"); } while( remaining > 0 ) { THIS_FPTR(printOffset)( mPrintBuf, startLine*mLayout.lineSize ); mPrintBuf[mOffsetSize]=0; offset.sprintf("[%s]", mPrintBuf ); uint pageSize = remaining > linePerPage ? linePerPage : remaining; printHtmlDataPage( tocName, fileNames, fileCount, ex, startLine, pageSize); remaining -= pageSize; startLine += pageSize; fileCount += 1; THIS_FPTR(printOffset)( mPrintBuf, (startLine-1)*mLayout.lineSize ); mPrintBuf[mOffsetSize]=0; offset += TQString(" %1 [%2]").tqarg(i18n("to")).tqarg(mPrintBuf); offsets.append(offset); if( p.expired() == true ) { int errCode = p.step( (float)(totalSize-remaining)/(float)totalSize ); if( errCode == Err_Stop && remaining > 0 ) { printHtmlTocPage( tocName, linkName, fileNames, offsets, fileCount ); p.finish(); return( Err_OperationAborted ); } } } printHtmlTocPage( tocName, linkName, fileNames, offsets, fileCount ); p.finish(); return( Err_Success ); } int CHexBuffer::exportCArray( const SExportCArray &ex, CProgress &p ) { uint start, stop; int errCode = locateRange( ex.range, start, stop ); if( errCode != Err_Success ) { p.finish(); return( errCode ); } TQFile file( ex.destFile ); if( file.open( IO_WriteOnly ) == false ) { p.finish(); return( Err_OpenWriteFailed ); } uint startLine = calculateLine( start ); if( startLine >= (uint)numLines() ) { startLine = numLines() == 0 ? 0 : numLines() - 1; } uint stopLine = calculateLine( stop ); if( stopLine >= (uint)numLines() ) { stopLine = numLines() == 0 ? 0 : numLines() - 1; } uint elementSize = ex.elementSize(); uint elementOnThisLine = 0; TQTextStream dest( &file ); dest << ex.variableName(stop-start).latin1() << "={" << endl; for( unsigned int i=start; i= ex.elementPerLine ) { dest << endl; elementOnThisLine = 0; } if( p.expired() == true ) { int errCode = p.step( (float)(i-start)/(float)(stop-start) ); if( errCode == Err_Stop && (i+elementSize) < stop) { p.finish(); return( Err_OperationAborted ); } } } dest << "};" << endl; p.finish(); return( Err_Success ); } int CHexBuffer::copySelectedText( TQByteArray &array, int columnSegment ) { SExportRange range; range.mode = SExportRange::Selection; return( copyText( array, range, columnSegment ) ); } int CHexBuffer::copyAllText( TQByteArray &array ) { SExportRange range; range.mode = SExportRange::All; return( copyText( array, range, VisibleColumn ) ); } int CHexBuffer::copyText( TQByteArray &array, const SExportRange &range, int columnSegment ) { uint start, stop; int errCode = locateRange( range, start, stop ); if( errCode != Err_Success ) { return( errCode ); } uint startLine = calculateLine( start ); uint stopLine = calculateLine( stop ); if( startLine >= (uint)numLines() ) { startLine = numLines() == 0 ? 0 : numLines() - 1; } if( stopLine >= (uint)numLines() ) { stopLine = numLines() == 0 ? 0 : numLines() - 1; } uint bytePerLine = mOffsetSize + 1 + (mNumCell + 2)*mLayout.lineSize + 1; uint size = (stopLine - startLine + 1)*bytePerLine; if( array.tqresize( size+1 ) == false ) { return( Err_NoMemory ); } if( columnSegment == VisibleColumn ) { columnSegment = PrimaryColumn; // Always visible if( mLayout.offsetVisible == true ) { columnSegment |= OffsetColumn; } if( mLayout.secondaryMode != SDisplayLayout::hide ) { columnSegment |= SecondaryColumn; } } uint offset = 0; for( uint i = startLine; i <= stopLine; i++ ) { offset += printLine( &array[offset], i, columnSegment ); } array[size] = 0; return( Err_Success ); } int CHexBuffer::copySelectedData( TQByteArray &array ) { uint start = mSelect.start(); uint stop = mSelect.stop(); if( mSelect.valid() == false || start >= stop ) { return( Err_IllegalRange ); } uint size = stop - start; if( array.tqresize( size ) == false ) { return( Err_NoMemory ); } //unsigned char *src = (unsigned char*)data(); //char *dst = (char*)array.data(); memcpy( &array[0], &data()[start], size ); return( Err_Success ); } uint CHexBuffer::numPage( CHexPrinter &printer ) { TQPainter paint( &printer ); paint.setFont( font() ); SPageMargin margin = printer.pageMargin(); SPageSize size = printer.pageUsableSize(); int headHeight, footHeight, headMargin, footMargin, freeHeight; headHeight = footHeight = headMargin = footMargin = 0; if( printer.pageHeader().enable == true ) { headHeight = headerHeight( paint ); headMargin = headerMargin( paint ); } if( printer.pageFooter().enable == true ) { footHeight = headerHeight( paint ); footMargin = headerMargin( paint ); } freeHeight = size.height - headHeight - footHeight - headMargin - footMargin; float scale = 1.0; if( (uint)mLineWidth > size.width ) { scale = (float)size.width / (float)mLineWidth; } uint linePerPage = (uint) ((float)freeHeight/((float)lineHeight()*scale)); uint remaining = numLines(); return( remaining / linePerPage + (remaining % linePerPage ? 1 : 0) ); } int CHexBuffer::print( CHexPrinter &printer, CProgress &p ) { printer.setDocName( mUrl ); TQPainter paint( &printer ); paint.setFont( font() ); SPageMargin margin = printer.pageMargin(); SPageSize size = printer.pageUsableSize(); paint.setClipRect( margin.left, margin.top, size.width, size.height ); //printf("%d,%d,%d,%d\n", margin.left, margin.top, size.width, size.height ); int headHeight, footHeight, headMargin, footMargin, freeHeight; headHeight = footHeight = headMargin = footMargin = 0; if( printer.pageHeader().enable == true ) { headHeight = headerHeight( paint ); headMargin = headerMargin( paint ); } if( printer.pageFooter().enable == true ) { footHeight = headerHeight( paint ); footMargin = headerMargin( paint ); } freeHeight = size.height - headHeight - footHeight - headMargin - footMargin; float scale = 1.0; if( (uint)mLineWidth > size.width ) { scale = (float)size.width / (float)mLineWidth; paint.scale( scale, scale ); } uint linePerPage = (uint) ((float)freeHeight/((float)lineHeight()*scale)); uint sx = (uint) ((float)margin.left/scale); uint sy = (uint) ((float)(margin.top+headHeight+headMargin)/scale); uint remaining = numLines(); uint line = 0; #ifdef PRINTER_TEST remaining = remaining > linePerPage * 10 ? linePerPage * 10 : remaining; #endif SPagePosition pageData( time(0), remaining, linePerPage ); while( remaining > 0 ) { uint lineInPage = remaining > linePerPage ? linePerPage : remaining; uint y = sy; // // Draw header and footer. Reset scaling during that operation. // paint.scale( 1.0/scale, 1.0/scale ); if( printer.pageHeader().enable == true ) { drawHeader( paint, margin.left, size.width, margin.top, false, printer.pageHeader(), pageData ); } if( printer.pageFooter().enable == true ) { drawHeader( paint, margin.left, size.width, margin.top+size.height-footHeight, true, printer.pageFooter(), pageData ); } paint.scale( scale, scale ); // // Draw actual data // for( uint i=0; i < lineInPage; i++, line++ ) { drawText( paint, line, sx, mLineWidth, y, false/*printer.printBlackWhite()*/ ); y += lineHeight();// - mLayout.horzGridWidth; // FIXME not really nice :) if( p.expired() == true ) { int errCode = p.step( pageData.current(), pageData.max() ); if( errCode == Err_Stop ) { p.finish(); return( Err_Success ); // Success here, even if we cancel } } } if( p.expired() == true ) { int errCode = p.step( pageData.current(), pageData.max() ); if( errCode == Err_Stop ) { p.finish(); return( Err_Success );// Success here, even if we cancel } } remaining -= lineInPage; if( remaining > 0 ) { printer.newPage(); } pageData.step(); } p.finish(); return( Err_Success ); } uint CHexBuffer::printLine( char *dst, uint line ) { uint offset = line * mLayout.lineSize; unsigned char *src; char *start = dst; uint dataSize; if( offset >= documentSize() ) { src = 0; dataSize = 0; } else { src = (unsigned char*)&data()[ offset ]; dataSize = documentSize() - offset; } if( mLayout.offsetVisible == true ) { THIS_FPTR(printOffset)( dst, offset ); dst += mOffsetSize; sprintf( dst, " " ); dst += 1; } for( uint i=0; i < mLayout.lineSize; i++ ) { if( i= documentSize() ) { src = 0; dataSize = 0; } else { src = (unsigned char*)&data()[ offset ]; dataSize = documentSize() - offset; } if( columnSegment & OffsetColumn ) { THIS_FPTR(printOffset)( dst, offset ); dst += mOffsetSize; sprintf( dst, " " ); dst += 1; } if( columnSegment & PrimaryColumn ) { for( uint i=0; i < mLayout.lineSize; i++ ) { if( imStartOffset, group->mStartBit ); return( true ); } bool CHexBuffer::redo( void ) { if( documentPresent() == false || mUndoIndex >= mUndoList.count() || mInputMode.noInput() == true ) { if( mInputMode.noInput() == true ) { inputSound(); } return( false ); } CHexActionGroup *group = mUndoList.at( mUndoIndex ); if( group == 0 ) { return( false ); } mUndoIndex += 1; doActionGroup( group ); cursorGoto( group->mStopOffset, group->mStopBit ); return( true ); } int CHexBuffer::addBookmark( int position ) { if( documentPresent() == false ) { return( Err_NoData ); } if( mBookmarkList.count() >= 9 && position == -1 ) { return( Err_ListFull ); } SCursorOffset *co = new SCursorOffset; if( co == 0 ) { fatalSound(); return( Err_NoMemory ); } co->offset = mCursor.curr.offset; co->bit = mCursor.bit(); if( position == -1 || position > (int)mBookmarkList.count() ) { mBookmarkList.append( co ); } else { mBookmarkList.remove( (uint)position ); mBookmarkList.insert( (uint)position, co ); } updateBookmarkMap(false); return( Err_Success ); } bool CHexBuffer::removeBookmark( int position ) { if( position < 0 ) { if( mBookmarkList.count() == 0 ) { return( false ); } mBookmarkList.clear(); } else { if( (uint)position >= mBookmarkList.count() ) { return( false ); } mBookmarkList.remove( position ); } updateBookmarkMap(false); return( true ); } void CHexBuffer::updateBookmarkMap( bool resize ) { if( resize == true ) { mBookmarkMap.resize( documentSize()/200 + 3 ); } mBookmarkMap.fill(0); int bookmarkMapSize = mBookmarkMap.size(); for( SCursorOffset *c=mBookmarkList.first(); c!=0; c=mBookmarkList.next() ) { int bookmarkOffset = c->offset / 200; if( bookmarkOffset < bookmarkMapSize ) { // // Espen 2000-05-16: // I do this test to avoid some TQt warnings when I have closed // or reduced the size of the documnet while the (now invalid) // bookmarks still exist. // mBookmarkMap.setBit(bookmarkOffset); } } } int CHexBuffer::findFirst( SSearchControl &sc ) { mMark.reset(); int errCode = scanData( sc, true ); return( errCode ); } int CHexBuffer::findNext( SSearchControl &sc ) { sc.fromCursor = true; int errCode = scanData( sc, false ); return( errCode ); } int CHexBuffer::findWrap( SSearchControl &sc ) { if( sc.wrapValid == false ) { return( Err_NoMatch ); } sc.wrapValid = false; sc.fromCursor = false; sc.wrapActive = true; int errCode = scanData( sc, false ); sc.fromCursor = true; return( errCode ); } int CHexBuffer::replaceAll( SSearchControl &sc, bool init ) { if( init == true ) { initScanData( sc ); } if( sc.key.isEmpty() == true ) { return( Err_EmptyArgument ); } if( documentSize() == 0 ) { return( Err_EmptyDocument ); } uint head, tail; if( sc.inSelection == true ) { if( mSelect.valid() == false ) { return( Err_NoSelection ); } head = mSelect.start(); tail = mSelect.stop(); } else { head = 0; tail = documentSize(); } uint start, stop; if( sc.fromCursor == false ) { if( sc.wrapActive == true ) { start = sc.forward == true ? head : sc.wrapMark; stop = sc.forward == true ? sc.wrapMark+sc.key.size() : tail; } else { start = head; stop = tail; } } else if( sc.forward == true ) { start = cursorOffset() < head ? head : cursorOffset(); stop = sc.wrapActive == true ? sc.wrapMark+sc.key.size() : tail; } else { start = sc.wrapActive == true ? sc.wrapMark : head; stop = cursorOffset() > tail ? tail : cursorOffset(); } if( sc.forward == true && start + sc.key.size() > stop ) { // // When searching backwards "stop" is the last offset from where // we do a memcmp() upward in memory. An overflow for that // situation is taken care of below. // return( Err_NoMatch ); } if( stop + sc.key.size() > tail ) { uint diff = stop + sc.key.size() - tail; stop = stop > diff ? stop - diff : 0; } if( mInputMode.noInput() == true ) { inputSound(); return( Err_WriteProtect ); } recordStart( mCursor ); uint numReplaced = 0; if( sc.forward == true ) { for( uint i = start; i <= stop ; ) { if( memcmp( &data()[i], sc.key.data(), sc.key.size() ) != 0 ) { i++; } else { cursorGoto( i, 7 ); recordReplace( mCursor, sc.key.size(), sc.val.data(), sc.val.size() ); numReplaced += 1; if( sc.inSelection == true ) { if( sc.key.size() > sc.val.size() ) { mSelect.shrink( sc.key.size() - sc.val.size() ); } else { mSelect.expand( sc.val.size() - sc.key.size() ); } } if( sc.key.size() > sc.val.size() ) { uint diff = sc.key.size() - sc.val.size(); stop -= TQMIN( stop, diff ); } else if( sc.key.size() < sc.val.size() ) { stop += sc.val.size() - sc.key.size(); } i += sc.val.size(); cursorStep( sc.val.size(), true, false ); } } } else { for( uint i = stop; i >= start; ) { if( memcmp( &data()[i], sc.key.data(), sc.key.size() ) != 0 ) { if( i == 0 ) { break; } i--; } else { cursorGoto( i, 7 ); recordReplace( mCursor, sc.key.size(), sc.val.data(), sc.val.size() ); numReplaced += 1; if( sc.inSelection == true ) { if( sc.key.size() > sc.val.size() ) { mSelect.shrink( sc.key.size() - sc.val.size() ); } else { mSelect.expand( sc.val.size() - sc.key.size() ); } } i -= TQMIN( i, sc.key.size() ); if( i == 0 ) { break; } } } } recordEnd( mCursor ); computeNumLines(); if( numReplaced == 0 ) { return( Err_NoMatch ); } sc.numReplace += numReplaced; sc.match = true; mMark.reset(); return( Err_Success ); } int CHexBuffer::replaceMarked( SSearchControl &sc ) { if( documentSize() == 0 ) { return( Err_EmptyDocument ); } if( mMark.valid() == false ) { return( Err_NoMark ); } bool inSelection; if( mSelect.valid() == true ) { if( mMark.start() >= mSelect.start() && mMark.stop() <= mSelect.stop() ) { inSelection = true; } else { inSelection = false; } } else { inSelection = false; } if( mInputMode.noInput() == true ) { inputSound(); return( Err_WriteProtect ); } recordStart( mCursor ); cursorGoto( mMark.start(), 7 ); recordReplace( mCursor, mMark.size(), sc.val.data(), sc.val.size() ); sc.numReplace += 1; if( inSelection == true ) { if( mMark.size() > sc.val.size() ) { mSelect.shrink( mMark.size() - sc.val.size() ); } else { sc.wrapMark += sc.val.size() - mMark.size(); mSelect.expand( sc.val.size() - mMark.size() ); } } if( sc.wrapActive == false ) { if( sc.forward == false ) { sc.wrapMark += mMark.size() > sc.val.size() ? mMark.size() - sc.val.size() : sc.val.size() - mMark.size(); } } recordEnd( mCursor ); computeNumLines(); if( sc.forward == true ) { // // We must step over the area we have just altered. This is // vital if the search key contains a pattern that exists in // the replace data buffer. // cursorStep( sc.val.size(), true, false ); } mMark.reset(); return( Err_Success ); } #if 0 int CHexBuffer::replaceAll( SSearchControl &sc, bool init ) { if( init == true ) { initScanData( sc ); } if( sc.key.isEmpty() == true ) { return( Err_EmptyArgument ); } if( documentSize() == 0 ) { return( Err_EmptyDocument ); } uint head, tail; if( sc.inSelection == true ) { if( mSelect.valid() == false ) { return( Err_NoSelection ); } head = mSelect.start(); tail = mSelect.stop(); } else { head = 0; tail = documentSize(); } uint start, stop; if( sc.fromCursor == false ) { if( sc.wrapActive == true ) { start = sc.forward == true ? head : sc.wrapMark; stop = sc.forward == true ? sc.wrapMark : tail; } else { start = head; stop = tail; } } else if( sc.forward == true ) { start = cursorOffset() < head ? head : cursorOffset(); stop = sc.wrapActive == true ? sc.wrapMark : tail; } else { start = sc.wrapActive == true ? sc.wrapMark : head; stop = cursorOffset() > tail ? tail : cursorOffset(); } if( start + sc.key.size() > stop ) { return( Err_NoMatch ); } if( stop + sc.key.size() > tail ) { uint diff = stop + sc.key.size() - tail; stop = stop > diff ? stop - diff : 0; } if( mInputMode.noInput() == true ) { inputSound(); return( Err_WriteProtect ); } recordStart( mCursor ); uint numReplaced = 0; if( sc.forward == true ) { for( uint i = start; i <= stop; i++ ) { if( memcmp( &data()[i], sc.key.data(), sc.key.size() ) == 0 ) { cursorGoto( i, 7 ); recordReplace( mCursor, sc.key.size(), sc.val.data(), sc.val.size() ); numReplaced += 1; if( sc.inSelection == true ) { if( sc.key.size() > sc.val.size() ) { mSelect.shrink( sc.key.size() - sc.val.size() ); } else { mSelect.expand( sc.val.size() - sc.key.size() ); } } if( sc.key.size() > sc.key.size() ) { uint diff = sc.key.size() - sc.val.size(); i += diff - 1; } else if( sc.key.size() < sc.val.size() ) { uint diff = sc.val.size() - sc.key.size(); stop += diff; } else { i += sc.val.size() - 1; } cursorStep( sc.val.size(), true, false ); } } } else { for( uint i = stop; i >= start; i-- ) { if( memcmp( &data()[i], sc.key.data(), sc.key.size() ) == 0 ) { cursorGoto( i, 7 ); recordReplace( mCursor, sc.key.size(), sc.val.data(), sc.val.size() ); numReplaced += 1; if( sc.inSelection == true ) { if( sc.key.size() > sc.val.size() ) { mSelect.shrink( sc.key.size() - sc.val.size() ); } else { mSelect.expand( sc.val.size() - sc.key.size() ); } } } if( i == 0 ) { break; } } } recordEnd( mCursor ); computeNumLines(); if( numReplaced == 0 ) { return( Err_NoMatch ); } sc.numReplace += numReplaced; sc.match = true; mMark.reset(); return( Err_Success ); } int CHexBuffer::replaceMarked( SSearchControl &sc ) { if( documentSize() == 0 ) { return( Err_EmptyDocument ); } if( mMark.valid() == false ) { return( Err_NoMark ); } bool inSelection; if( mSelect.valid() == false ) { if( mMark.start() >= mSelect.start() && mMark.stop() <= mSelect.stop() ) { inSelection = true; } else { inSelection = false; } } else { inSelection = false; } if( mInputMode.noInput() == true ) { inputSound(); return( Err_WriteProtect ); } recordStart( mCursor ); cursorGoto( mMark.start(), 7 ); recordReplace( mCursor, mMark.size(), sc.val.data(), sc.val.size() ); sc.numReplace += 1; if( inSelection == true ) { if( mMark.size() > sc.val.size() ) { mSelect.shrink( mMark.size() - sc.val.size() ); } else { mSelect.expand( sc.val.size() - mMark.size() ); } } recordEnd( mCursor ); computeNumLines(); mMark.reset(); return( Err_Success ); } #endif int CHexBuffer::initScanData( SSearchControl &sc ) { sc.wrapValid = false; sc.wrapActive = false; sc.wrapMark = 0; sc.match = false; sc.numReplace = 0; uint head, tail; if( sc.inSelection == true ) { if( mSelect.valid() == false ) { return( Err_NoSelection ); } head = mSelect.start(); tail = mSelect.stop(); } else { head = 0; tail = documentSize(); } if( sc.fromCursor == false ) { sc.wrapValid = false; sc.wrapActive = false; sc.wrapMark = 0; } else if( sc.forward == true ) { if( cursorOffset() > tail ) { sc.wrapValid = true; sc.wrapActive = false; sc.wrapMark = tail; } else if( cursorOffset() <= head ) { sc.wrapValid = false; sc.wrapActive = false; sc.wrapMark = 0; } else { sc.wrapValid = true; sc.wrapActive = false; sc.wrapMark = cursorOffset(); } } else { if( cursorOffset() >= tail ) { sc.wrapValid = false; sc.wrapActive = false; sc.wrapMark = 0; } else if( cursorOffset() < head ) { sc.wrapValid = true; sc.wrapActive = false; sc.wrapMark = head; } else { sc.wrapValid = true; sc.wrapActive = false; sc.wrapMark = cursorOffset(); } } return( Err_Success ); } int CHexBuffer::scanData( SSearchControl &sc, bool init ) { if( init == true ) { int errCode = initScanData( sc ); if( errCode != Err_Success ) { return( errCode ); } } if( sc.key.isEmpty() == true ) { return( Err_EmptyArgument ); } if( documentSize() == 0 ) { return( Err_EmptyDocument ); } uint head, tail; if( sc.inSelection == true ) { if( mSelect.valid() == false ) { return( Err_NoSelection ); } head = mSelect.start(); tail = mSelect.stop(); } else { head = 0; tail = documentSize(); } uint start, stop; if( sc.fromCursor == false ) { if( sc.wrapActive == true ) { start = sc.forward == true ? head : sc.wrapMark; stop = sc.forward == true ? sc.wrapMark+sc.key.size() : tail; } else { start = head; stop = tail; } } else if( sc.forward == true ) { start = cursorOffset() < head ? head : cursorOffset(); stop = sc.wrapActive == true ? sc.wrapMark : tail; } else { start = sc.wrapActive == true ? sc.wrapMark : head; stop = cursorOffset() > tail ? tail : cursorOffset(); } if( sc.forward == true && start + sc.key.size() > stop ) { // // When searching backwards "stop" is the last offset from where // we do a memcmp() upward in memory. An overflow for that // situation is taken care of below. // return( stop + sc.key.size() < tail ? Err_WrapBuffer : Err_NoData ); } if( stop + sc.key.size() > tail ) { uint diff = stop + sc.key.size() - tail; stop = stop > diff ? stop - diff : 0; } if( sc.forward == true ) { for( uint i = start; i <= stop; i++ ) { int result; if( sc.ignoreCase == true ) { result = strncasecmp( &data()[i], sc.key.data(), sc.key.size() ); } else { result = memcmp( &data()[i], sc.key.data(), sc.key.size() ); } if( result == 0 ) { if( i != cursorOffset() || mMark.size() != sc.key.size() ) { sc.match = true; cursorGoto( i, 7 ); markSet( i, (uint)sc.key.size() ); return( Err_Success ); } } } return( start > head ? Err_WrapBuffer : Err_NoData ); } else { for( uint i = stop; i >= start; i-- ) { int result; if( sc.ignoreCase == true ) { result = strncasecmp( &data()[i], sc.key.data(), sc.key.size() ); } else { result = memcmp( &data()[i], sc.key.data(), sc.key.size() ); } if( result == 0 ) { if( i != cursorOffset() || mMark.size() != sc.key.size() ) { sc.match = true; cursorGoto( i, 7 ); markSet( i, (uint)sc.key.size() ); return( Err_Success ); } } if( i == 0 ) { break; } } return( stop + sc.key.size() <= tail ? Err_WrapBuffer : Err_NoData ); } } int CHexBuffer::filter( SFilterControl &fc ) { uint head, tail; if( fc.inSelection == true ) { if( mSelect.valid() == false ) { return( Err_NoSelection ); } head = mSelect.start(); tail = mSelect.stop(); } else { head = 0; tail = documentSize(); } uint start, stop; if( fc.fromCursor == false ) { start = head; stop = tail; } else if( fc.forward == true ) { start = cursorOffset() < head ? head : cursorOffset(); stop = tail; } else { start = head; stop = cursorOffset() > tail ? tail : cursorOffset(); } if( mInputMode.noInput() == true ) { inputSound(); return( Err_WriteProtect ); } if( start >= stop ) { return( Err_IllegalRange ); } TQByteArray buf( stop - start ); if( buf.isEmpty() == true ) { return( Err_NoMemory ); } int errCode = fc.execute((uchar*)&buf[0],(uchar*)&data()[start],buf.size()); if( errCode == Err_Success ) { recordStart( mCursor ); cursorGoto( start, 7 ); recordReplace( mCursor, buf.size(), buf.data(), buf.size() ); recordEnd( mCursor ); } return( errCode ); } int CHexBuffer::collectStrings( CStringCollectControl &sc ) { uint startOffset = 0; uint start, i; bool on = false; if( sc.minLength < 1 ) { sc.minLength = 1; } start = startOffset; for( i = startOffset; i= 128 ) { if( on == true && i-start >= sc.minLength ) { TQByteArray a( i-start ); for( uint j=0; j<(i-start); a[j]=data()[start+j], j++ ); sc.add( start, a ); } on = false; } else { if( on == false ) { start = i; } on = true; } } if( on == true && i-start >= sc.minLength ) { TQByteArray a( i-start ); for( uint j=0; j<(i-start); a[j]=data()[start+j], j++ ); sc.add( start, a ); } return( Err_Success ); } int CHexBuffer::collectStatistic( SStatisticControl &sc, CProgress &p ) { sc.documentSize = documentSize(); sc.documentName = mUrl; for( uint i = 0; imHexAction; group->mHexAction = 0; while( action != 0 ) { doAction( action ); CHexAction *next = action->mNext; group->insertAction( action ); action = next; } computeNumLines(); } void CHexBuffer::doAction( CHexAction *action ) { if( action->mAction == CHexAction::replace ) { doReplace( action, true ); } } void CHexBuffer::recordStart( SCursor &cursor ) { // // Step 1: Remove any undo element that is more recent than the // current undo index // while( mUndoList.count() > mUndoIndex ) { mUndoList.removeLast(); } // // Step 2: Make sure the undo list is no larger than the undo limit. // We remove the oldest elements in the list. // while( mUndoList.count() >= mUndoLimit ) { mUndoList.removeFirst(); mUndoIndex -= 1; } CHexActionGroup *group = new CHexActionGroup( cursor.curr.offset, cursor.bit() ); if( group == 0 ) { return; } mUndoList.append( group ); mUndoIndex += 1; } void CHexBuffer::recordReplace( SCursor &cursor, uint size, char *data1, uint data1Size ) { CHexAction *hexAction = new CHexAction( CHexAction::replace, cursor.curr.offset ); if( hexAction == 0 ) { return; } hexAction->mSize = size; hexAction->mData = data1; hexAction->mDataSize = data1Size; doReplace( hexAction, false ); mUndoList.getLast()->insertAction( hexAction ); if( mCursor.curr.offset < documentSize() ) { mCursor.curr.data = data()[ mCursor.curr.offset ]; } } void CHexBuffer::recordEnd( SCursor &cursor ) { mUndoList.getLast()->mStopOffset = cursor.curr.offset; mUndoList.getLast()->mStopBit = cursor.bit(); } // // This method is the only place where the doucument data can be changed. // void CHexBuffer::doReplace( CHexAction *hexAction, bool removeData ) { uint offset = hexAction->mOffset; uint oldSize = hexAction->mSize; char *newData = hexAction->mData; uint newSize = hexAction->mDataSize; hexAction->setData( newSize, &data()[offset], oldSize ); // // Input new data. Resize buffer first if necessary. We always mark the // data as changed (dirty) when the buffer is resized, otherwise only // when the new data differ from the current. Nice feature :-) // int errCode; if( newSize > oldSize ) { errCode = moveBuffer( offset + newSize - oldSize, offset ); mDocumentModified = true; } else if( newSize < oldSize ) { errCode = moveBuffer( offset, offset + oldSize - newSize ); mDocumentModified = true; } else { errCode = Err_Success; if( memcmp( &data()[offset], newData, newSize ) != 0 ) { mDocumentModified = true; } } if( errCode == Err_Success ) { memcpy( &data()[offset], newData, newSize ); } // // Data is removed regardless of success or not. Otherwise we will // have a mmeory leak. The single reason why the operation above could // fail is because there was that no more memory that could be // allocated. // if( removeData == true ) { delete [] newData; } } bool CHexBuffer::inputDummy( unsigned char *dest, int value, uint cell ) { (void)dest; (void)value; (void)cell; return( false ); } bool CHexBuffer::inputHexadecimal( unsigned char *dest, int value, uint cell ) { if( value >= '0' && value <= '9' ) { value = value - '0'; } else if( value >= 'A' && value <= 'F' ) { value = value - 'A' + 10; } else if( value >= 'a' && value <= 'f' ) { value = value - 'a' + 10; } else { return( false ); } if( cell > 1 ) { return( false ); } uint shift = 1 - cell; *dest = (*dest & ~(0xF<<(shift*4)) ) | (value<<(shift*4)); return( true ); } bool CHexBuffer::inputDecimal( unsigned char *dest, int value, uint cell ) { // // 2000-01-22 Espen Sand // I do the insertion a bit different here since decimal is special // with respect to bitwidths. // if( value < '0' || value > '9' || cell > 2 ) { return( false ); } char buf[4]; printDecimalCell( buf, *dest ); buf[cell]=value; buf[3]=0; int tmp = atoi(buf); if( tmp > 255 ) { return( false ); } *dest = tmp; return( true ); } bool CHexBuffer::inputOctal( unsigned char *dest, int value, uint cell ) { if( value >= '0' && value <= '7' ) { value = value - '0'; if( cell == 0 && value > 3 ) { return( false ); } } else { return( false ); } if( cell >= 3 ) { return( false ); } uint shift = 2 - cell; *dest = (*dest & ~(0x7<<(shift*3)) ) | (value<<(shift*3)); return( true ); } bool CHexBuffer::inputBinary( unsigned char *dest, int value, uint cell ) { if( value >= '0' && value <= '1' ) { value = value - '0'; } else { return( false ); } if( cell > 7 ) { return( false ); } uint shift = 7 - cell; *dest = (*dest & ~(1< documentSize() || destOffset == srcOffset ) { return( Err_Success ); } if( destOffset < srcOffset ) { char *dest = &data()[ destOffset ]; char *src = &data()[ srcOffset ]; memmove( dest, src, documentSize() - srcOffset ); setDocumentSize( documentSize() - (srcOffset - destOffset) ); return( Err_Success ); } else { uint s = documentSize() - srcOffset; if( destOffset + s >= size() ) { int errCode = resizeBuffer( destOffset + s ); if( errCode != Err_Success ) { fatalSound(); return( errCode ); } } else { setDocumentSize( documentSize() + (destOffset - srcOffset) ); } char *dest = &data()[ destOffset ]; char *src = &data()[ srcOffset ]; memmove( dest, src, s ); memset( src, 0, destOffset - srcOffset ); return( Err_Success ); } } int CHexBuffer::resizeBuffer( uint newSize ) { if( newSize < documentSize() ) { return( Err_Success ); } if( newSize >= size() ) { TQByteArray tmp; tmp.duplicate( data(), size() ); if( tmp.isNull() == true ) { return( Err_NoMemory ); } if( fill( '\0', newSize + 100 ) == false ) { return( Err_NoMemory ); } memcpy( data(), &tmp[0], tmp.size() ); } setDocumentSize( newSize ); return( Err_Success ); } void CHexBuffer::inputSound( void ) { if( mInputErrorSound == true ) { KNotifyClient::beep( TQObject::tr("Edit operation failed") ); } } void CHexBuffer::fatalSound( void ) { if( mFatalErrorSound == true ) { KNotifyClient::beep( TQObject::tr("Could not allocate memory") ); } } int CHexBuffer::printHtmlDataPage( const TQString &tocName, const TQStringList &fileNames, uint index, const SExportHtml &ex, uint line, uint numLine ) { if( fileNames.count() == 0 ) { return( Err_NullArgument ); } if( index >= fileNames.count() ) { index = fileNames.count()-1; } TQFile file( fileNames[index] ); if( file.open( IO_WriteOnly ) == false ) { return( Err_OperationAborted ); } TQTextStream os( &file ); const TQString *next = index+1 >= fileNames.count() ? 0 : &fileNames[index+1]; const TQString *prev = index == 0 ? 0 : &fileNames[index-1]; const TQString *toc = tocName.length() == 0 ? 0 : &tocName; printHtmlHeader( os, true ); if( ex.navigator == true ) { printHtmlNavigator( os, next, prev, toc ); } printHtmlCaption( os, ex.topCaption, index+1, fileNames.count() ); printHtmlTable( os, line, numLine, ex.blackWhite ); printHtmlCaption( os, ex.bottomCaption, index+1, fileNames.count() ); if( ex.navigator == true ) { printHtmlNavigator( os, next, prev, toc ); } printHtmlHeader( os, false ); return( Err_Success ); } void CHexBuffer::printHtmlTocPage( const TQString &tocName, const TQString &linkName, const TQStringList &fileNames, const TQStringList &offsets, uint numPage ) { if( numPage == 0 || fileNames.count() == 0 ) { return; } if( numPage >= fileNames.count() ) { numPage = fileNames.count() - 1; } TQFile file( tocName ); if( file.open( IO_WriteOnly ) == false ) { return; } TQTextStream os( &file ); printHtmlHeader( os, true ); os << "

" << endl; os << "" << endl; os << mUrl << endl; os << "" << endl; os << "

" << endl; os << "

" << endl; for( uint i=0; i<=numPage; i++ ) { TQString n( fileNames[i].right( fileNames[i].length() - fileNames[i].findRev('/') - 1) ); os << "" << i18n("Page") << i+1; os << ""; os << " " << offsets[i]; os << "
" << endl; } os << "

" << endl; printHtmlHeader( os, false ); if( linkName.isEmpty() == false ) { // // Make a symlink. We ignore any error here. I don't consider // it to be fatal. // TQString n( tocName.right( tocName.length() - tocName.findRev('/') - 1) ); symlink( n.latin1(), linkName.latin1() ); } } void CHexBuffer::printHtmlCaption( TQTextStream &os, uint captionType, uint curPage, uint numPage ) { TQString caption; switch( captionType ) { case 0: return; break; case 1: caption = mUrl; break; case 2: caption = mUrl.right( mUrl.length() - mUrl.findRev('/') - 1); break; case 3: caption = i18n("Page %1 of %2").tqarg(curPage).tqarg(numPage); break; } os << "

" << endl; os << "" << endl; os << caption << endl; os << "" << endl; os << "

" << endl; } void CHexBuffer::printHtmlNavigator( TQTextStream &os, const TQString *next, const TQString *prev, const TQString *toc ) { os << "" << endl; os << "" << endl; os << "" << endl; os << "" << endl; os << "" << endl << "
" << endl; if( next == 0 ) { os << i18n("Next") << " "; } else { TQString n( next->right( next->length() - next->findRev('/') - 1) ); os << "" << i18n("Next") << "" << " "; } if( prev == 0 ) { os << i18n("Previous") << " "; } else { TQString p( prev->right( prev->length() - prev->findRev('/') - 1) ); os << "" << i18n("Previous") << "" << " "; } if( toc == 0 ) { os << i18n("Contents") << " "; } else { TQString t( toc->right( toc->length() - toc->findRev('/') - 1) ); os << "" << i18n("Contents"); os << "" << " "; } os << "" << endl; os << ""; os << i18n("Generated by khexedit"); os << "" << " "; os << "
" << endl; } int CHexBuffer::printHtmlHeader( TQTextStream &os, bool isFront ) { if( isFront == true ) { os << "" << endl << "" << endl; os << "" << endl; os << "" << endl; os << "" << endl << "" << endl; } else { os << "" << endl << "" << endl; } return( Err_Success ); } int CHexBuffer::printHtmlTable( TQTextStream &os, uint line, uint numLine, bool bw ) { uint i; TQColor color; int numCol = 1; if( mLayout.offsetVisible == true ) { numCol += 1; } if( mLayout.secondaryMode != SDisplayLayout::hide ) { numCol += 1; } os << "" << endl; if( mLayout.offsetVisible == true ) { color = bw == true ? TQt::white : mColor.offsetBg; os << "" << endl; } color = bw == true ? TQt::white : mColor.textBg; os << "
" << endl; os << "" << endl; color = bw == true ? TQt::black : mColor.offsetFg; for( i=0; i" << endl; } os << "
"; THIS_FPTR(printOffset)( mPrintBuf, (line+i)*mLayout.lineSize ); mPrintBuf[mOffsetSize]=0; os << mPrintBuf << "
" << endl << "
" << endl; os << "" << endl; for( i=0; i" << endl << "" << endl; if( mLayout.secondaryMode != SDisplayLayout::hide ) { color = bw == true ? TQt::white : mColor.textBg; os << "" << endl; return( Err_Success ); } for( uint i=0; i < mLayout.lineSize; i++ ) { if( isPrimary == true ) { if( offset+i >= documentSize() ) { memset(mPrintBuf, ' ', mNumCell ); mPrintBuf[mNumCell] = 0; if( i == 0 ) { color = bw == true ? TQt::black : foregroundColor(i); } else { color = prevColor; } } else { unsigned char val = (unsigned char)data()[offset+i]; if( THIS_FPTR(printCell)( mPrintBuf, val ) == 0 ) { color = bw == true ? TQt::black : foregroundColor(i); } else { color = bw == true ? TQt::black : mColor.nonPrintFg; } } mPrintBuf[mNumCell] = 0; if( i == 0 ) { os << ""; } else if( color != prevColor ) { os << ""; } prevColor = color; if( mPrintBuf[0] == '<' ) { os << "<"; } else { os << mPrintBuf; if( (i+1) % mLayout.columnSize == 0 && (i+1) != mLayout.lineSize ) { os << " "; } } } else { if( offset+i >= documentSize() ) { memset(mPrintBuf, ' ', 1 ); if( i == 0 ) { color = bw == true ? TQt::black : mColor.secondaryFg; } else { color = prevColor; } } else { unsigned char val = (unsigned char)data()[offset+i]; if( printAsciiCell( mPrintBuf, val ) == 0 ) { color = bw == true ? TQt::black : mColor.secondaryFg; } else { color = bw == true ? TQt::black : mColor.nonPrintFg; } mPrintBuf[1] = 0; if( i == 0 ) { os << ""; } else if( color != prevColor ) { os << ""; } prevColor = color; mPrintBuf[1] = 0; os << (mPrintBuf[0] == '<' ? "<" : mPrintBuf); } } } os << "" << endl; return( Err_Success ); }
" << endl; os << "" << endl; for( i=0; i" << endl << "" << endl; } os << "" << endl << "
" << endl; return( Err_Success ); } int CHexBuffer::printHtmlLine( TQTextStream &os, uint line, bool isPrimary, bool bw ) { uint offset = line * mLayout.lineSize; TQColor prevColor; TQColor color; if( bw == true ) { color = TQt::white; } else { color = (line+1) % 2 ? mColor.textBg : mColor.secondTextBg; } os << "
" << endl; if( offset >= documentSize() ) { os << "