SVN commit 670288 by zwabel: Check in my last work on the document-transformation. I forgot checking it in. It probably makes the document-transformation makes it work a bit better, but is not ready yet. I don't quite remember whether this creates any problems in the file-collaboration, but I check it in now to make sure these changes are not lost M +0 -1 collaborationmanager.cpp M +0 -5 documentwrapper.cpp M +19 -183 lib/dynamictext/dynamictext.cpp M +4 -2 lib/dynamictext/dynamictext.h M +6 -2 lib/dynamictext/dynamictexthelpers.h M +36 -1 lib/dynamictext/main.cpp M +1 -1 vectortimestampeditor.cpp --- trunk/KDE/kdevelop/plugins/teamwork/collaborationmanager.cpp #670287:670288 @@ -29,7 +29,6 @@ #include Q_DECLARE_METATYPE( MessagePointer ) - using namespace std; typedef QPointer QFileCollaborationSessionPointer; Q_DECLARE_METATYPE( QPersistentModelIndex ) --- trunk/KDE/kdevelop/plugins/teamwork/documentwrapper.cpp #670287:670288 @@ -57,11 +57,6 @@ #define IFDEBUG( x ) /**/ //#define IFDEBUG( x ) x -std::ostream& operator << ( std::ostream& o, const SimpleReplacement& rhs ) { - o << "( at " << rhs.m_position << ": '" << rhs.m_oldText << "' -> '" << rhs.m_newText << "' )"; - return o; -} - struct DocumentWrapperTreeAction : public StandardCollaborationTreeAction { DocumentWrapperTreeAction( DocumentWrapper* w ) : StandardCollaborationTreeAction( w ) {} virtual void doubleClicked() { --- trunk/KDE/kdevelop/plugins/teamwork/lib/dynamictext/dynamictext.cpp #670287:670288 @@ -15,6 +15,7 @@ #define NOCATCH #include "network/serialization.h" +#include #include "dynamictext.h" #include "verify.h" @@ -24,6 +25,10 @@ typedef DynamicTextErrorDummy CatchedDynamicTextError; #endif +std::ostream& operator << ( std::ostream& o, const SimpleReplacement& rhs ) { + o << "( at " << rhs.m_position << ": '" << rhs.m_oldText << "' -> '" << rhs.m_newText << "' )"; + return o; +} CROSSMAP_KEY_EXTRACTOR( WeakReplacementPointer, WeakReplacementPointer, 0, value ) CROSSMAP_KEY_EXTRACTOR( WeakReplacementPointer, VectorTimestamp, 0, value->vectorStamp() ) @@ -61,32 +66,33 @@ template -bool Replacement::apply( TextType& text, const OffsetMap& outerOffset, OffsetMap& contextOffset ) { +bool Replacement::apply( TextType& text, const OffsetMap& outerOffset, OffsetMap& staticOffset ) { if ( m_enabled ) { - int pos = outerOffset( contextOffset( m_replacement.m_position ) ); + std::cout << "applying replacement " << replacement() << "\noffset: " << outerOffset.print() << "\nstaticOffset: " << staticOffset.print() << endl; + int pos = outerOffset( staticOffset( m_replacement.m_position ) ); DYN_VERIFY_SMALLERSAME( 0, pos ); DYN_VERIFY_SMALLERSAME( (int)pos, (int)text.length() ); DYN_VERIFY_SAME( text.substr( pos, m_replacement.m_oldText.length() ), m_replacement.m_oldText ); text.replace( pos, m_replacement.m_oldText.length(), m_replacement.m_newText ); } else { - contextOffset %= ~offset( outerOffset ); + staticOffset %= ~offset( outerOffset ); } return true; } template -bool Replacement::unApply( TextType& text, const OffsetMap& outerOffset, OffsetMap& contextOffset ) { +bool Replacement::unApply( TextType& text, const OffsetMap& outerOffset, OffsetMap& staticOffset ) { if ( m_enabled ) { - int pos = outerOffset( contextOffset( m_replacement.m_position ) ); + int pos = outerOffset( staticOffset( m_replacement.m_position ) ); DYN_VERIFY_SMALLERSAME( 0, pos ); DYN_VERIFY_SMALLERSAME( (int)pos, (int)text.length() ); DYN_VERIFY_SAME( text.substr( pos, m_replacement.m_newText.length() ), m_replacement.m_newText ); text.replace( pos, m_replacement.m_newText.length(), m_replacement.m_oldText ); } else { - contextOffset %= offset( outerOffset ); + staticOffset %= offset( outerOffset ); } return true; @@ -378,164 +384,6 @@ return true; } -#ifdef OLDOFFSET -OffsetMap DynamicText::offset( VectorTimestamp from, VectorTimestamp to ) { - if ( from == to ) - return OffsetMap(); - - OffsetRequest request( from, to ); - - OffsetCache::iterator it = m_offsetCache.find( request ); - - if ( it != m_offsetCache.end() ) { - return ( *it ).second; - } - - bool backwards = true; - if ( from.smallerOrSame( to ) ) { - backwards = false; - VectorTimestamp t = from; - from = to; - to = t; - } - DYN_VERIFY( to.smallerOrSame( from ) ); - - static int depth = 0; - depth++; - - DYN_VERIFY_SMALLER( depth, 5000 ); - - if ( from == to ) - return OffsetMap(); - - bool applied = true; - - uint sz = m_applied.size(); - - DYN_VERIFY_SMALLERSAME( to.size(), sz ); - DYN_VERIFY_SMALLERSAME( from.size(), sz ); - - std::vector chains( sz ); - for ( uint a = 0; a < sz; a++ ) { - chains[ a ] = m_applied[ a ].last; - if ( !chains[ a ] ) - chains[ a ] = m_unApplied[ a ].first; - if ( chains[ a ] ) - DYN_VERIFY_SAME( chains[ a ] ->primaryIndex(), a ); - //if( backwards ) { - while ( chains[ a ] && chains[ a ] ->primaryStamp() > from[ a ] ) - chains[ a ] = chains[ a ] ->prev(); - //} else { - while ( chains[ a ] && chains[ a ] ->primaryStamp() < from[ a ] ) - chains[ a ] = chains[ a ] ->next(); - //} - if ( chains[ a ] ) - DYN_VERIFY_SAME( chains[ a ] ->primaryStamp(), from[ a ] ); - } - - OffsetMap offset; - VectorTimestamp currentState = from; - - SafetyCounter s( 10000 ); - - bool waited = false; - - while ( applied || waited ) { - DYN_VERIFY( s ); - - bool force = false; - if ( waited && !applied ) { ///If there is an inheritance-chain, break it by just applying the first one. - force = true; - waited = false; - } - applied = false; - waited = false; - - //Apply all replacements that can be applied to the current state, and need to be applied. - for ( uint a = 0; a < chains.size(); a++ ) { - ReplacementPointer& r( chains[ a ] ); - if ( !r ) - continue; - DYN_VERIFY( r ); - const VectorTimestamp& s( r->vectorStamp() ); - - if ( s.primaryStamp() > to[ s.primaryIndex() ] ) { - - if ( !force ) { - ///Find out if there's another one that can be unapplied, and that should be unapplied before this one. If there is one, wait. - bool wait = false; - for ( uint b = 0; b < chains.size(); b++ ) { - if ( b == a ) - continue; - - ReplacementPointer& r2( chains[ b ] ); - if ( !r2 ) - continue; - const VectorTimestamp& s2( r2->vectorStamp() ); - - if ( s2.primaryStamp() > to[ s2.primaryIndex() ] && currentState[ s2.primaryIndex() ] >= s2.primaryStamp() ) { - ///The other replacement has to be unapplied - if ( s[ b ] < s2.primaryStamp() || s2[ a ] >= s.primaryStamp() ) { - ///The other replacement should be unapplied before this one - wait = true; - break; - } - } - } - - if ( wait ) { - waited = true; - continue; - } - } else { - force = false; - } - - OffsetMap selfOffset; - - /*VectorTimestamp prev = currentState; - prev.setPrimaryIndex( a ); - if ( prev.primaryStamp() != 0 ) { - prev.decrease(); - VectorTimestamp selfPrev = s; - DYN_VERIFY( selfPrev.primaryStamp() != 0 ); - selfPrev.decrease(); - DYN_VERIFY( selfPrev.primaryStamp() >= 0 ); - - selfOffset = this->offset( prev, selfPrev ); - }*/ - - if ( backwards ) { - offset = offset % ( chains[ a ] ->offset( selfOffset ) ); - } else { - offset = offset % ( ~chains[ a ] ->offset( selfOffset ) ); - } - /*if ( backwards ) { - offset = ( chains[ a ] ->offset( selfOffset ) ) % offset; - } else { - offset = ( ~chains[ a ] ->offset( selfOffset ) ) % offset; - }*/ - - r = r->prev(); - - currentState.setPrimaryIndex( s.primaryIndex() ); - currentState.decrease(); - DYN_VERIFY_SMALLERSAME( to[ s.primaryIndex() ], currentState.primaryStamp() ); - - applied = true; - } - } - } - - depth--; - - DYN_VERIFY_SAME( currentState, to ); - m_offsetCache.insert( OffsetCache::value_type( request, offset ) ); - - return offset; -} -#else - OffsetMap DynamicText::offset( VectorTimestamp from, VectorTimestamp to, int position ) { if ( from == to ) return OffsetMap(); @@ -656,15 +504,15 @@ if ( to[ a ] < from[ a ] ) { VectorTimestamp n = from; n.setPrimaryIndex( a ); - n.decrease(); + n.decrease(); ///n = the intermediate state we are stepping to VectorTimestamp prev = chains[a]->vectorStamp(); - prev.decrease(); + prev.decrease(); ///prev = the state the replacement in chains[a] was applied to - ///The position-checking has to be done to avoid endless recursion + ///The position-checking needs to be done to avoid endless recursion OffsetMap innerOffset = ~offset( prev, n, chains[a]->replacement().m_position ); ret = offset( n, to ); - if( position != -1 && position < innerOffset( chains[a]->replacement().m_position ) ) + if( position != INVALID_POSITION && position < innerOffset( chains[a]->replacement().m_position ) ) return ret; ret = chains[a]->offset( innerOffset ) % ret; } else { @@ -675,7 +523,7 @@ prev.decrease(); OffsetMap innerOffset = ~offset( prev, from, next[a]->replacement().m_position ); ret = offset( n, to ); - if( position != -1 && position < innerOffset( next[a]->replacement().m_position ) ) + if( position != INVALID_POSITION && position < innerOffset( next[a]->replacement().m_position ) ) return ret; ret = ~next[a]->offset( innerOffset ) % ret; } @@ -700,9 +548,7 @@ DYN_VERIFY( 0 ); } -#endif - bool DynamicText::rewindInternal( const VectorTimestamp& state ) { SafetyCounter s( 10000 ); @@ -775,16 +621,11 @@ VectorTimestamp prev( s ); //prev.decrease(); - OffsetMap prevOffset; OffsetMap offset; - //if ( !prev.isZero() ) - offset = prevOffset = this->offset( prevCurrent, prev ); + offset = ~this->offset( prev, prevCurrent, r.first->replacement().m_position - 1 ); ///@todo -1 or not? DYN_VERIFY( r.last->unApply( m_text, offset, m_currentOffset ) ); - /*OffsetMap relOffset = ~( prevOffset % (~offset) ); - m_currentOffset %= relOffset;*/ - m_state.setPrimaryIndex( s.primaryIndex() ); m_state.decrease(); @@ -939,16 +780,11 @@ //It can be applied now VectorTimestamp prev( s ); prev.decrease(); - OffsetMap prevOffset; OffsetMap offset; - if ( !prev.isZero() ) - offset = prevOffset = this->offset( m_state, prev ); + offset = ~this->offset( prev, m_state, r.first->replacement().m_position-1 ); DYN_VERIFY( r.first->apply( m_text, offset, m_currentOffset ) ); - /*OffsetMap relOffset = ~( prevOffset % (~offset) ); - m_currentOffset %= relOffset;*/ - m_state.setPrimaryIndex( s.primaryIndex() ); m_state.increase(); --- trunk/KDE/kdevelop/plugins/teamwork/lib/dynamictext/dynamictext.h #670287:670288 @@ -30,6 +30,8 @@ #include "flexibletext.h" using namespace Tree; +#define INVALID_POSITION -1000000 + struct OffsetRequest { VectorTimestamp from; VectorTimestamp to; @@ -206,8 +208,8 @@ void hashReplacement( const ReplacementPointer& rep ); void unHashReplacement( const ReplacementPointer& rep ); - ///Returns the backwards-offset from the current position to the searched one(the searched must be legal, and smaller than current state). If position is set, offsets that do not affect the given position in the from-space are not included. - OffsetMap offset( VectorTimestamp from, VectorTimestamp to, int position = -1 ); + ///Returns the offset from the 'from' position to the 'to' one. If position is set, all replacements that are behind that position(given in from-space) will be excluded while computation. + OffsetMap offset( VectorTimestamp from, VectorTimestamp to, int position = INVALID_POSITION ); ReplacementPointer m_dummy; --- trunk/KDE/kdevelop/plugins/teamwork/lib/dynamictext/dynamictexthelpers.h #670287:670288 @@ -17,6 +17,8 @@ #ifndef DYNAMICTEXT_HELPERS #define DYNAMICTEXT_HELPERS +#include + #include "offsetutils.h" #include "verify.h" #include "network/sharedptr.h" @@ -49,6 +51,8 @@ } }; +std::ostream& operator << ( std::ostream& o, const SimpleReplacement& rhs ); + class Replacement : public WeakShared { public: @@ -89,9 +93,9 @@ void setPrev( ReplacementPointer prev ); template - bool apply( TextType& text, const OffsetMap& outerOffset, OffsetMap& contextOffset ); + bool apply( TextType& text, const OffsetMap& offset, OffsetMap& staticOffset ); template - bool unApply( TextType& text, const OffsetMap& outerOffset, OffsetMap& contextOffset ); + bool unApply( TextType& text, const OffsetMap& offset, OffsetMap& staticOffset ); #ifdef USE_LINKS ///Checks whether "link" should be put into the "links"-map. If it should --- trunk/KDE/kdevelop/plugins/teamwork/lib/dynamictext/main.cpp #670287:670288 @@ -432,6 +432,41 @@ try { DynamicText t; + cout << "test 0.1: \n"; + VectorTimestamp a5 = t.insert( 0, SimpleReplacement( 0, "a", "" ) ); + VectorTimestamp a1 = t.insert( 0, SimpleReplacement( 1, "a", "" ) ); + VectorTimestamp b1 = t.insert( 1, SimpleReplacement( 2, "b", "" ) ); + VectorTimestamp a2 = t.insert( 0, SimpleReplacement( 3, "a", "" ) ); + + cout << t.state().print() << "text: " << t.text() << endl; + + VectorTimestamp v( t.state() ); + v.setStamp( 0, 0 ); + t.changeState( v ); + cout << t.state().print() << v << " text: " << t.text() << endl; + DYN_VERIFY_SAME( t.text().text(), "b" ); + + v.setStamp( 0, 1 ); + t.changeState( v ); + cout << t.state().print() << v << " text: " << t.text() << endl; + DYN_VERIFY_SAME( t.text().text(), "ab" ); + + v.setStamp( 0, 2 ); + t.changeState( v ); + cout << t.state().print() << v << " text: " << t.text() << endl; + DYN_VERIFY_SAME( t.text().text(), "aab" ); + + v.setStamp( 0, 3 ); + t.changeState( v ); + DYN_VERIFY_SAME( t.text().text(), "aaba" ); + + } catch ( DynamicTextError err ) { + cout << "error: " << err.what(); + terminate(); + } + + try { + DynamicText t; cout << "test 4: \n"; VectorTimestamp a1 = t.insert( 0, SimpleReplacement( 0, "i", "" ) ); VectorTimestamp b1 = t.insert( 1, SimpleReplacement( 0, "d", "" ) ); @@ -797,10 +832,10 @@ int main( int /* argc */, char /**argv[]*/ ) { + verifyDynamicText(); verifySumTree(); verifyFlexibleText(); verifyOffsets(); - verifyDynamicText(); //printf("testing\n"); // for( int q = 0; q < CYCLES; q++ ) { --- trunk/KDE/kdevelop/plugins/teamwork/vectortimestampeditor.cpp #670287:670288 @@ -53,7 +53,7 @@ bool TimestampEditor::trySeekTo( Timestamp s ) { VectorTimestamp state = m_parent->text()->state(); - state.setStamp( m_index, s ); + state.setStamp( m_index, s ); state.setPrimaryIndex( m_index ); try { return m_parent->text()->changeState( state ); } catch( const DynamicTextError& err ) {