summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatthias Melcher <fltk@matthiasm.com>2002-11-05 19:53:50 +0000
committerMatthias Melcher <fltk@matthiasm.com>2002-11-05 19:53:50 +0000
commit3473297741ac6224b9c461aba98b73b3217b808f (patch)
tree27eb7285c2d1b4b6fe321d68813a4e1b060887f1 /src
parent66dabdb8f53231eff304cbb944cd900ddbce00af (diff)
Added 'Undo' to Fl_Text_Editor by reusing some of the Fl_Input_ code. I tried many cases and it seems to work fine.
Matthias git-svn-id: file:///fltk/svn/fltk/branches/branch-1.1@2825 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src')
-rw-r--r--src/Fl_Text_Buffer.cxx107
-rw-r--r--src/Fl_Text_Editor.cxx19
2 files changed, 117 insertions, 9 deletions
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 );
@@ -312,6 +333,45 @@ void Fl_Text_Buffer::copy( Fl_Text_Buffer *fromBuf, int fromStart,
}
/*
+** 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
** space the width and height of "text", by moving all text to the right of
@@ -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 $".
//