/*************************************************************************** kbuffercursor.cpp - description ------------------- begin : Don Mai 29 2003 copyright : (C) 2003 by Friedrich W. H. Kossebau email : Friedrich.W.H@Kossebau.de ***************************************************************************/ /*************************************************************************** * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License version 2 as published by the Free Software Foundation. * * * ***************************************************************************/ //#include // lib specific #include "kbufferlayout.h" #include "kbuffercursor.h" using namespace KHE; TDEBufferCursor::TDEBufferCursor( const TDEBufferLayout *L ) : Layout( L ), Index( 0 ), Coord( 0, 0 ), Behind( false ), AppendPosEnabled( false ) { } TDEBufferCursor::~TDEBufferCursor() { } bool TDEBufferCursor::operator==( const TDEBufferCursor &C ) const { return Index == C.Index && Behind == C.Behind ; } void TDEBufferCursor::setAppendPosEnabled( bool APE ) { if( AppendPosEnabled == APE ) return; AppendPosEnabled = APE; // reposition Cursor int Length = Layout->length(); // behind buffer end, not end of line and not empty? if( realIndex() >= Length && Coord.pos() < Layout->noOfBytesPerLine()-1 && Length > 0 ) { if( AppendPosEnabled ) { ++Index; Coord.goRight(); Behind = false; } else { --Index; Coord.goLeft(); Behind = true; } } } void TDEBufferCursor::gotoPreviousByte() { if( Behind ) Behind = false; else if( Index > 0 ) { --Index; Coord.goCLeft( Layout->noOfBytesPerLine()-1 ); } } void TDEBufferCursor::gotoPreviousByte( int D ) { if( Behind ) { --D; Behind = false; } if( D > Index ) { if( Index == 0 ) return; gotoStart(); } gotoIndex( Index - D ); } void TDEBufferCursor::gotoNextByte() { int Length = Layout->length(); if( Index < Length ) { if( Index == Length-1 ) stepToEnd(); else { ++Index; Coord.goCRight( Layout->noOfBytesPerLine()-1 ); Behind = false; } } } void TDEBufferCursor::gotoNextByte( int D ) // TODO: think about consistency with gotoNextByte!!! { if( Behind ) { ++D; Behind = false; } // would we end behind the end? if( Index+D >= Layout->length() ) gotoEnd(); else gotoIndex( Index + D ); } void TDEBufferCursor::gotoNextByteInLine() { int Length = Layout->length(); if( Index < Length ) { if( Index == Length-1 ) stepToEnd(); else { ++Index; if( Coord.pos() < Layout->noOfBytesPerLine()-1 ) Coord.goRight(); else Behind = true; } } } void TDEBufferCursor::gotoUp() { // can we even go up? if( Coord.isBelow(Layout->startLine()) ) { Coord.goUp(); if( Coord.isPriorInLineThan(Layout->start()) ) { Index = 0; Coord.setPos( Layout->startPos() ); Behind = false; } else { Index -= Layout->noOfBytesPerLine(); if( Behind && !atLineEnd() ) { ++Index; Coord.goRight(); Behind = false; } } } } void TDEBufferCursor::gotoDown() { if( Coord.isAbove(Layout->finalLine()) ) { Coord.goDown(); // behind End? if( Coord.isLaterInLineThan(Layout->final()) ) gotoEnd(); else Index += Layout->noOfBytesPerLine(); } } void TDEBufferCursor::gotoLineStart() { int OldIndex = Index; Index = Layout->indexAtLineStart( Coord.line() ); Coord.goLeft( OldIndex-Index ); Behind = false; } void TDEBufferCursor::gotoLineEnd() { if( Index < Layout->length() ) { int OldIndex = Index; Index = Layout->indexAtLineEnd( Coord.line() ); Coord.goRight( Index-OldIndex ); stepToEnd(); } } void TDEBufferCursor::gotoStart() { Index = 0; Coord = Layout->start(); Behind = false; } void TDEBufferCursor::gotoEnd() { int Length = Layout->length(); if( Length > 0 ) { Index = Length-1; Coord = Layout->final(); stepToEnd(); } else gotoStart(); } void TDEBufferCursor::gotoCIndex( int i ) { if( Layout->length() > 0 ) { Index = Layout->correctIndex( i ); Coord = Layout->coordOfIndex( Index ); if( i > Index ) stepToEnd(); else Behind = false; } else gotoStart(); } void TDEBufferCursor::gotoCCoord( const TDEBufferCoord &C ) { if( Layout->length() > 0 ) { Coord = Layout->correctCoord( C ); Index = Layout->indexAtCoord( Coord ); if( C > Coord ) stepToEnd(); else Behind = false; } else gotoStart(); } void TDEBufferCursor::stepToEnd() { if( AppendPosEnabled && (Coord.pos() < Layout->noOfBytesPerLine()-1) ) { ++Index; Coord.goRight(); Behind = false; } else Behind = true; } void TDEBufferCursor::gotoIndex( int i ) { Index = i; Coord = Layout->coordOfIndex( Index ); Behind = false; } void TDEBufferCursor::gotoRealIndex() { if( Behind ) { ++Index; Coord = Layout->coordOfIndex( Index ); Behind = false; } } void TDEBufferCursor::gotoCoord( const TDEBufferCoord &C ) { Index = Layout->indexAtCoord( C ); Coord = C; Behind = false; } void TDEBufferCursor::updateCoord() { Coord = Layout->coordOfIndex( Index ); } // page down should be: one page minus one line // -> if in the very first line page down will put the cursor on the same page into the last line void TDEBufferCursor::gotoPageUp() { int NoOfLinesPerPage = Layout->noOfLinesPerPage(); int NewIndex = Index - NoOfLinesPerPage * Layout->noOfBytesPerLine(); if( NewIndex < 0 ) gotoStart(); else { Index = NewIndex; Coord.goUp( NoOfLinesPerPage ); if( Behind && !atLineEnd() ) { ++Index; Coord.goRight(); Behind = false; } } } void TDEBufferCursor::gotoPageDown() { int NoOfLinesPerPage = Layout->noOfLinesPerPage(); int NewIndex = Index + NoOfLinesPerPage * Layout->noOfBytesPerLine(); if( NewIndex >= Layout->length() ) gotoEnd(); else { Index = NewIndex; Coord.goDown( NoOfLinesPerPage ); } } int TDEBufferCursor::validIndex() const { return Index < Layout->length() ? Index : -1; } int TDEBufferCursor::indexAtLineStart() const { return Layout->indexAtLineStart( Coord.line() ); } int TDEBufferCursor::indexAtLineEnd() const { return Layout->indexAtLineEnd( Coord.line() ); } bool TDEBufferCursor::atStart() const { return Index == 0; } bool TDEBufferCursor::atEnd() const { return Index == Layout->length() - 1; } bool TDEBufferCursor::atAppendPos() const { return realIndex() >= Layout->length(); } bool TDEBufferCursor::atLineStart() const { return Layout->atLineStart( Coord ); } bool TDEBufferCursor::atLineEnd() const { return Layout->atLineEnd( Coord ); }