X-Git-Url: http://git.cinelerra-gg.org/git/?a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fundostack.C;h=23f33bc193148fadc237dc9ed85d8e8133429778;hb=a94468d6de897136e77c70662177f4b8b4454b6b;hp=0c49981b22ff63f025deab29a4f2561de1633bad;hpb=7ead44762b23da404eee89b63e0474153fdf58a1;p=goodguy%2Fhistory.git diff --git a/cinelerra-5.1/cinelerra/undostack.C b/cinelerra-5.1/cinelerra/undostack.C index 0c49981b..23f33bc1 100644 --- a/cinelerra-5.1/cinelerra/undostack.C +++ b/cinelerra-5.1/cinelerra/undostack.C @@ -27,6 +27,9 @@ #include "undostack.h" #include +// undo can be incremental or direct, from key to current +//#define UNDO_INCREMENTAL + UndoStack::UndoStack() : List() { current = 0; @@ -55,37 +58,30 @@ UndoStackItem *UndoStack::get_current_redo() UndoStackItem* UndoStack::push() { -// current is only 0 if before first undo - if( current ) - current = insert_after(current); - else - current = insert_before(first); - -// delete future undos if necessary - if( current && current->next ) { - while( current->next ) remove(last); - } - // delete oldest 2 undos if necessary if( total() > UNDOLEVELS ) { - for( int i=0; i<2; ++i ) { - UndoStackItem *second = first->next; - char *temp_data = 0; - - - if( !second->is_key() ) { - temp_data = second->get_data(); - } - remove(first); - -// Convert new first to key buffer. - if( !second->is_key() ) { - second->set_data(temp_data); - } - delete [] temp_data; + UndoStackItem *item = first, *key = item; +#ifdef UNDO_INCREMENTAL + for( int i=2; --i>=0; item=item->next ); +#else + for( int i=2; --i>=0; item=item->next ) + if( item->is_key() ) key = item; +#endif + char *data = !item->is_key() ? key->get_data() : 0; + while( first != item ) { + if( current == first ) current = first->next; + delete first; + } + if( data ) { + item->set_data(data); + delete [] data; } } +// current is only 0 if before first undo + current = current ? insert_after(current) : insert_before(first); +// delete future undos if necessary + while( current->next ) remove(last); return current; } @@ -120,9 +116,6 @@ void UndoStack::dump(FILE *fp) } } -// undo can be incremental or direct, from key to current -//#define UNDO_INCREMENTAL - class undo_record { public: int32_t new_ofs; @@ -257,9 +250,9 @@ UndoHash *UndoHashTable::add(char *txt, int len) return hp; } -UndoLine::UndoLine(UndoHash *hash) +UndoLine::UndoLine(UndoHash *hash, char *tp) { - this->txt = 0; this->len = 0; + this->txt = tp; this->len = 0; this->hash = hash; hash->occurs[va] = hash->occurs[vb] = 1; } @@ -280,7 +273,6 @@ int UndoLine::eq(UndoLine *ln) void UndoVersion::scan_lines(UndoHashTable *hash, char *sp, char *ep) { - append(new UndoLine(hash->bof)); for( int line=1; sphash->occurs[ver]; append(ln); } - append(new UndoLine(hash->eof)); } @@ -334,13 +325,21 @@ void UndoStackItem::set_data(char *data) UndoVersion alines(va), blines(vb); char *asp = data, *aep = asp + data_size-1; char *bsp = prev, *bep = bsp + prev_size-1; + alines.append(new UndoLine(hash.bof, asp)); + blines.append(new UndoLine(hash.bof, bsp)); alines.scan_lines(&hash, asp, aep); blines.scan_lines(&hash, bsp, bep); -// trim suffix int asz = alines.size(), bsz = blines.size(); +// trim matching suffix while( asz > 0 && bsz > 0 && alines[asz-1]->eq(blines[bsz-1]) ) { - --asz; --bsz; + aep = alines[--asz]->txt; alines.remove_object(); + bep = blines[--bsz]->txt; blines.remove_object(); } +// include for matching last item + alines.append(new UndoLine(hash.eof, aep)); + blines.append(new UndoLine(hash.eof, bep)); + hash.eof->line[va] = asz++; + hash.eof->line[vb] = bsz++; int ai = 0, bi = 0; while( ai < asz || bi < bsz ) { @@ -482,3 +481,58 @@ void* UndoStackItem::get_creator() return creator; } +void UndoStackItem::save(FILE *fp) +{ + fwrite(&key,1,sizeof(key),fp); + fwrite(&load_flags,1,sizeof(load_flags),fp); + fwrite(&data_size,1,sizeof(data_size),fp); + fwrite(data,1,data_size,fp); + for( char *bp=session_filename; *bp; ++bp ) fputc(*bp, fp); + fputc(0, fp); + for( char *bp=description; *bp; ++bp ) fputc(*bp, fp); + fputc(0, fp); +} + +void UndoStackItem::load(FILE *fp) +{ + fread(&key,1,sizeof(key),fp); + fread(&load_flags,1,sizeof(load_flags),fp); + fread(&data_size,1,sizeof(data_size),fp); + fread(data=new char[data_size],1,data_size,fp); + char filename[BCTEXTLEN], descr[BCTEXTLEN]; + char *bp = filename, *ep = bp+sizeof(filename)-1; + for( int ch; bp0; ++bp ) *bp = ch; + *bp = 0; + session_filename = cstrdup(filename); + bp = descr; ep = bp+sizeof(descr)-1; + for( int ch; bp0; ++bp ) *bp = ch; + *bp = 0; + description = cstrdup(descr); +//printf("read undo key=%d,flags=%jx,data_size=%d,data=%p,file=%s,descr=%s\n", +// key, load_flags, data_size, data, session_filename, description); +} + +void UndoStack::save(FILE *fp) +{ + for( UndoStackItem *item=first; item; item=item->next ) { + int is_current = item == current ? 1 : 0; + fwrite(&is_current,1,sizeof(is_current),fp); + item->save(fp); +// if( item == current ) break; // stop at current + } +} + +void UndoStack::load(FILE *fp) +{ + while( last ) delete last; + current = 0; + UndoStackItem *current_item = 0; + int is_current = 0; + while( fread(&is_current,1,sizeof(is_current),fp) == sizeof(is_current) ) { + UndoStackItem *item = push(); + item->load(fp); + if( is_current ) current_item = item; + } + if( current_item ) current = current_item; +} +