diff --git a/FL/Fl_Text_Buffer.H b/FL/Fl_Text_Buffer.H index 92f4792ff..45771c99e 100644 --- a/FL/Fl_Text_Buffer.H +++ b/FL/Fl_Text_Buffer.H @@ -1,5 +1,5 @@ // -// "$Id: Fl_Text_Buffer.H,v 1.3.2.5 2002/09/20 19:59:45 easysw Exp $" +// "$Id: Fl_Text_Buffer.H,v 1.3.2.6 2002/11/05 19:53:50 matthiaswm Exp $" // // Header file for Fl_Text_Buffer class. // @@ -83,6 +83,7 @@ class FL_EXPORT Fl_Text_Buffer { void remove(int start, int end); void replace(int start, int end, const char *text); void copy(Fl_Text_Buffer* fromBuf, int fromStart, int fromEnd, int toPos); + int undo(int *cp=0); int insertfile(const char *file, int pos, int buflen = 128*1024); int appendfile(const char *file, int buflen = 128*1024) { return insertfile(file, length(), buflen); } @@ -249,5 +250,5 @@ class FL_EXPORT Fl_Text_Buffer { #endif // -// End of "$Id: Fl_Text_Buffer.H,v 1.3.2.5 2002/09/20 19:59:45 easysw Exp $". +// End of "$Id: Fl_Text_Buffer.H,v 1.3.2.6 2002/11/05 19:53:50 matthiaswm Exp $". // diff --git a/FL/Fl_Text_Editor.H b/FL/Fl_Text_Editor.H index d436e73c8..f146d61f5 100644 --- a/FL/Fl_Text_Editor.H +++ b/FL/Fl_Text_Editor.H @@ -1,5 +1,5 @@ // -// "$Id: Fl_Text_Editor.H,v 1.1.2.5 2002/11/05 06:45:40 matthiaswm Exp $" +// "$Id: Fl_Text_Editor.H,v 1.1.2.6 2002/11/05 19:53:50 matthiaswm Exp $" // // Header file for Fl_Text_Editor class. // @@ -88,6 +88,7 @@ class FL_EXPORT Fl_Text_Editor : public Fl_Text_Display { static int kf_cut(int c, Fl_Text_Editor* e); static int kf_paste(int c, Fl_Text_Editor* e); static int kf_select_all(int c, Fl_Text_Editor* e); + static int kf_undo(int c, Fl_Text_Editor* e); protected: int handle_key(); @@ -102,6 +103,6 @@ class FL_EXPORT Fl_Text_Editor : public Fl_Text_Display { #endif // -// End of "$Id: Fl_Text_Editor.H,v 1.1.2.5 2002/11/05 06:45:40 matthiaswm Exp $". +// End of "$Id: Fl_Text_Editor.H,v 1.1.2.6 2002/11/05 19:53:50 matthiaswm Exp $". // diff --git a/src/Fl_Text_Buffer.cxx b/src/Fl_Text_Buffer.cxx index 50cf59723..eb8c3b235 100644 --- a/src/Fl_Text_Buffer.cxx +++ b/src/Fl_Text_Buffer.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Text_Buffer.cxx,v 1.9.2.12 2002/09/20 19:59:45 easysw Exp $" +// "$Id: Fl_Text_Buffer.cxx,v 1.9.2.13 2002/11/05 19:53:50 matthiaswm Exp $" // // Copyright 2001-2002 by Bill Spitzak and others. // Original code Copyright Mark Edel. Permission to distribute under @@ -69,6 +69,26 @@ static const char *ControlCodeTable[ 32 ] = { "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb", "can", "em", "sub", "esc", "fs", "gs", "rs", "us"}; +static char* undobuffer; +static int undobufferlength; +static Fl_Text_Buffer* undowidget; +static int undoat; // points after insertion +static int undocut; // number of characters deleted there +static int undoinsert; // number of characters inserted +static int undoyankcut; // length of valid contents of buffer, even if undocut=0 + +static void undobuffersize(int n) { + if (n > undobufferlength) { + if (undobuffer) { + do {undobufferlength *= 2;} while (undobufferlength < n); + undobuffer = (char*)realloc(undobuffer, undobufferlength); + } else { + undobufferlength = n+9; + undobuffer = (char*)malloc(undobufferlength); + } + } +} + /* ** Create an empty text buffer of a pre-determined size (use this to ** avoid unnecessary re-allocation if you know exactly how much the buffer @@ -249,6 +269,7 @@ void Fl_Text_Buffer::replace( int start, int end, const char *s ) { call_predelete_callbacks( start, end-start ); deletedText = text_range( start, end ); remove_( start, end ); + //undoyankcut = undocut; nInserted = insert_( start, s ); mCursorPosHint = start + nInserted; call_modify_callbacks( start, end - start, nInserted, 0, deletedText ); @@ -311,6 +332,45 @@ void Fl_Text_Buffer::copy( Fl_Text_Buffer *fromBuf, int fromStart, update_selections( toPos, 0, copiedLength ); } +/* +** remove text according to the undo variables or insert text +** from the undo buffer +*/ +int Fl_Text_Buffer::undo(int *cursorPos) { + if (undowidget != this || !undocut && !undoinsert) return 0; + + int ilen = undocut; + int xlen = undoinsert; + int b = undoat-xlen; + + if (xlen && undoyankcut && !ilen) { + ilen = undoyankcut; + } + + if (xlen && ilen) { + undobuffersize(ilen+1); + undobuffer[ilen] = 0; + char *tmp = strdup(undobuffer); + int at = undoat; + replace(b, undoat, tmp); + if (cursorPos) *cursorPos = mCursorPosHint; + free(tmp); + } + else if (xlen) { + remove(b, undoat); + if (cursorPos) *cursorPos = mCursorPosHint; + } + else if (ilen) { + undobuffersize(ilen+1); + undobuffer[ilen] = 0; + insert(undoat, undobuffer); + if (cursorPos) *cursorPos = mCursorPosHint; + undoyankcut = 0; + } + + return 1; +} + /* ** Insert "text" columnwise into buffer starting at displayed character ** position "column" on the line beginning at "startPos". Opens a rectangular @@ -1279,6 +1339,17 @@ int Fl_Text_Buffer::insert_( int pos, const char *s ) { mLength += insertedLength; update_selections( pos, 0, insertedLength ); + if ( undowidget==this && undoat==pos && undoinsert ) { + undoinsert += insertedLength; + } + else { + undoinsert = insertedLength; + undoyankcut = (undoat==pos) ? undocut : 0 ; + } + undoat = pos+insertedLength; + undocut = 0; + undowidget = this; + return insertedLength; } @@ -1289,10 +1360,34 @@ int Fl_Text_Buffer::insert_( int pos, const char *s ) { */ void Fl_Text_Buffer::remove_( int start, int end ) { /* if the gap is not contiguous to the area to remove, move it there */ - if ( start > mGapStart ) + + if ( undowidget==this && undoat==end && undocut ) { + undobuffersize( undocut+end-start+1 ); + memmove( undobuffer+end-start, undobuffer, undocut ); + undocut += end-start; + } + else { + undocut = end-start; + undobuffersize(undocut); + } + undoat = start; + undoinsert = 0; + undoyankcut = 0; + undowidget = this; + + if ( start > mGapStart ) { + memcpy( undobuffer, mBuf+(mGapEnd-mGapStart)+start, end-start ); move_gap( start ); - else if ( end < mGapStart ) + } + else if ( end < mGapStart ) { + memcpy( undobuffer, mBuf+start, end-start ); move_gap( end ); + } + else { + int prelen = mGapStart - start; + memcpy( undobuffer, mBuf+start, prelen ); + memcpy( undobuffer+prelen, mBuf+mGapEnd, end-start-prelen); + } /* expand the gap to encompass the deleted characters */ mGapEnd += end - mGapStart; @@ -1843,8 +1938,10 @@ void Fl_Text_Buffer::remove_selection_( Fl_Text_Selection *sel ) { return; if ( isRect ) remove_rectangular( start, end, rectStart, rectEnd ); - else + else { remove( start, end ); + //undoyankcut = undocut; + } } void Fl_Text_Buffer::replace_selection_( Fl_Text_Selection *sel, const char *s ) { @@ -2397,5 +2494,5 @@ Fl_Text_Buffer::outputfile(const char *file, int start, int end, int buflen) { // -// End of "$Id: Fl_Text_Buffer.cxx,v 1.9.2.12 2002/09/20 19:59:45 easysw Exp $". +// End of "$Id: Fl_Text_Buffer.cxx,v 1.9.2.13 2002/11/05 19:53:50 matthiaswm Exp $". // diff --git a/src/Fl_Text_Editor.cxx b/src/Fl_Text_Editor.cxx index 4d44e8529..eda8a0adb 100644 --- a/src/Fl_Text_Editor.cxx +++ b/src/Fl_Text_Editor.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Text_Editor.cxx,v 1.9.2.11 2002/11/05 06:45:40 matthiaswm Exp $" +// "$Id: Fl_Text_Editor.cxx,v 1.9.2.12 2002/11/05 19:53:50 matthiaswm Exp $" // // Copyright 2001-2002 by Bill Spitzak and others. // Original code Copyright Mark Edel. Permission to distribute under @@ -93,8 +93,8 @@ static struct { { FL_Page_Up, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move }, { FL_Page_Down, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move }, //{ FL_Clear, 0, Fl_Text_Editor::delete_to_eol }, -//{ 'z', FL_CTRL, Fl_Text_Editor::undo }, -//{ '/', FL_CTRL, Fl_Text_Editor::undo }, + { 'z', FL_CTRL, Fl_Text_Editor::kf_undo }, + { '/', FL_CTRL, Fl_Text_Editor::kf_undo }, { 'x', FL_CTRL, Fl_Text_Editor::kf_cut }, { FL_Delete, FL_SHIFT, Fl_Text_Editor::kf_cut }, { 'c', FL_CTRL, Fl_Text_Editor::kf_copy }, @@ -105,6 +105,7 @@ static struct { #ifdef __APPLE__ // Define CMD+key accelerators... + { 'z', FL_COMMAND, Fl_Text_Editor::kf_undo }, { 'x', FL_COMMAND, Fl_Text_Editor::kf_cut }, { 'c', FL_COMMAND, Fl_Text_Editor::kf_copy }, { 'v', FL_COMMAND, Fl_Text_Editor::kf_paste }, @@ -386,6 +387,16 @@ int Fl_Text_Editor::kf_select_all(int, Fl_Text_Editor* e) { return 1; } +int Fl_Text_Editor::kf_undo(int , Fl_Text_Editor* e) { + e->buffer()->unselect(); + int crsr; + int ret = e->buffer()->undo(&crsr); + e->insert_position(crsr); + e->show_insert_position(); + if (e->when()&FL_WHEN_CHANGED) e->do_callback(); else e->set_changed(); + return ret; +} + int Fl_Text_Editor::handle_key() { // Call fltk's rules to try to turn this into a printing character. @@ -466,5 +477,5 @@ int Fl_Text_Editor::handle(int event) { } // -// End of "$Id: Fl_Text_Editor.cxx,v 1.9.2.11 2002/11/05 06:45:40 matthiaswm Exp $". +// End of "$Id: Fl_Text_Editor.cxx,v 1.9.2.12 2002/11/05 19:53:50 matthiaswm Exp $". //