summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Fl_Input_.cxx138
-rw-r--r--src/Fl_Text_Buffer.cxx149
2 files changed, 165 insertions, 122 deletions
diff --git a/src/Fl_Input_.cxx b/src/Fl_Input_.cxx
index 55190b258..a8ad63ce0 100644
--- a/src/Fl_Input_.cxx
+++ b/src/Fl_Input_.cxx
@@ -33,6 +33,45 @@ extern void fl_draw(const char*, int, float, float);
////////////////////////////////////////////////////////////////
+class Fl_Input_Undo_Action {
+public:
+ Fl_Input_Undo_Action() :
+ undobuffer(NULL),
+ undobufferlength(0),
+ undoat(0),
+ undocut(0),
+ undoinsert(0),
+ undoyankcut(0)
+ { }
+ ~Fl_Input_Undo_Action() {
+ if (undobuffer)
+ ::free(undobuffer);
+ }
+
+ char *undobuffer;
+ int undobufferlength;
+ int undoat; // points after insertion
+ int undocut; // number of characters deleted there
+ int undoinsert; // number of characters inserted
+ int undoyankcut; // length of valid contents of buffer, even if undocut=0
+
+ /*
+ Resize the undo buffer to match at least the requested size.
+ */
+ void undobuffersize(int n)
+ {
+ if (n > undobufferlength) {
+ undobufferlength = n + 128;
+ undobuffer = (char *)realloc(undobuffer, undobufferlength);
+ }
+ }
+
+ void clear() {
+ undocut = undoinsert = 0;
+ }
+};
+
+
/** \internal
Converts a given text segment into the text that will be rendered on screen.
@@ -723,26 +762,6 @@ int Fl_Input_::copy(int clipboard) {
#define MAXFLOATSIZE 40
-static char* undobuffer;
-static int undobufferlength;
-static Fl_Input_* undowidget;
-static int undoat; // points after insertion
-static int undocut; // number of characters deleted there
-static int undoinsert; // number of characters inserted
-static int yankcut; // 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);
- }
- }
-}
-
/**
Append text at the end.
@@ -860,45 +879,43 @@ int Fl_Input_::replace(int b, int e, const char* text, int ilen) {
put_in_buffer(size_+ilen);
if (e>b) {
- if (undowidget == this && b == undoat) {
- undobuffersize(undocut+(e-b));
- memcpy(undobuffer+undocut, value_+b, e-b);
- undocut += e-b;
- } else if (undowidget == this && e == undoat && !undoinsert) {
- undobuffersize(undocut+(e-b));
- memmove(undobuffer+(e-b), undobuffer, undocut);
- memcpy(undobuffer, value_+b, e-b);
- undocut += e-b;
- } else if (undowidget == this && e == undoat && (e-b)<undoinsert) {
- undoinsert -= e-b;
+ if (b == undo_->undoat) {
+ undo_->undobuffersize(undo_->undocut+(e-b));
+ memcpy(undo_->undobuffer+undo_->undocut, value_+b, e-b);
+ undo_->undocut += e-b;
+ } else if (e == undo_->undoat && !undo_->undoinsert) {
+ undo_->undobuffersize(undo_->undocut+(e-b));
+ memmove(undo_->undobuffer+(e-b), undo_->undobuffer, undo_->undocut);
+ memcpy(undo_->undobuffer, value_+b, e-b);
+ undo_->undocut += e-b;
+ } else if (e == undo_->undoat && (e-b)<undo_->undoinsert) {
+ undo_->undoinsert -= e-b;
} else {
- undobuffersize(e-b);
- memcpy(undobuffer, value_+b, e-b);
- undocut = e-b;
- undoinsert = 0;
+ undo_->undobuffersize(e-b);
+ memcpy(undo_->undobuffer, value_+b, e-b);
+ undo_->undocut = e-b;
+ undo_->undoinsert = 0;
}
memmove(buffer+b, buffer+e, size_-e+1);
size_ -= e-b;
- undowidget = this;
- undoat = b;
- if (input_type() == FL_SECRET_INPUT) yankcut = 0; else yankcut = undocut;
+ undo_->undoat = b;
+ if (input_type() == FL_SECRET_INPUT) undo_->undoyankcut = 0; else undo_->undoyankcut = undo_->undocut;
}
if (ilen) {
- if (undowidget == this && b == undoat)
- undoinsert += ilen;
+ if (b == undo_->undoat)
+ undo_->undoinsert += ilen;
else {
- undocut = 0;
- undoinsert = ilen;
+ undo_->undocut = 0;
+ undo_->undoinsert = ilen;
}
memmove(buffer+b+ilen, buffer+b, size_-b+1);
memcpy(buffer+b, text, ilen);
size_ += ilen;
}
- undowidget = this;
om = mark_;
op = position_;
- mark_ = position_ = undoat = b+ilen;
+ mark_ = position_ = undo_->undoat = b+ilen;
// Insertions into the word at the end of the line will cause it to
// wrap to the next line, so we must indicate that the changes may start
@@ -922,7 +939,7 @@ int Fl_Input_::replace(int b, int e, const char* text, int ilen) {
minimal_update(b);
- mark_ = position_ = undoat;
+ mark_ = position_ = undo_->undoat;
set_changed();
if (when()&FL_WHEN_CHANGED) do_callback();
@@ -938,33 +955,33 @@ int Fl_Input_::replace(int b, int e, const char* text, int ilen) {
*/
int Fl_Input_::undo() {
was_up_down = 0;
- if ( undowidget != this || (!undocut && !undoinsert) ) return 0;
+ if (!undo_->undocut && !undo_->undoinsert) return 0;
- int ilen = undocut;
- int xlen = undoinsert;
- int b = undoat-xlen;
+ int ilen = undo_->undocut;
+ int xlen = undo_->undoinsert;
+ int b = undo_->undoat-xlen;
int b1 = b;
put_in_buffer(size_+ilen);
if (ilen) {
memmove(buffer+b+ilen, buffer+b, size_-b+1);
- memcpy(buffer+b, undobuffer, ilen);
+ memcpy(buffer+b, undo_->undobuffer, ilen);
size_ += ilen;
b += ilen;
}
if (xlen) {
- undobuffersize(xlen);
- memcpy(undobuffer, buffer+b, xlen);
+ undo_->undobuffersize(xlen);
+ memcpy(undo_->undobuffer, buffer+b, xlen);
memmove(buffer+b, buffer+b+xlen, size_-xlen-b+1);
size_ -= xlen;
}
- undocut = xlen;
- if (xlen) yankcut = xlen;
- undoinsert = ilen;
- undoat = b;
+ undo_->undocut = xlen;
+ if (xlen) undo_->undoyankcut = xlen;
+ undo_->undoinsert = ilen;
+ undo_->undoat = b;
mark_ = b /* -ilen */;
position_ = b;
@@ -988,8 +1005,8 @@ int Fl_Input_::undo() {
*/
int Fl_Input_::copy_cuts() {
// put the yank buffer into the X clipboard
- if (!yankcut || input_type()==FL_SECRET_INPUT) return 0;
- Fl::copy(undobuffer, yankcut, 1);
+ if (!undo_->undoyankcut || input_type()==FL_SECRET_INPUT) return 0;
+ Fl::copy(undo_->undobuffer, undo_->undoyankcut, 1);
return 1;
}
@@ -1151,6 +1168,7 @@ Fl_Input_::Fl_Input_(int X, int Y, int W, int H, const char* l)
xscroll_ = yscroll_ = 0;
maximum_size_ = 32767;
shortcut_ = 0;
+ undo_ = new Fl_Input_Undo_Action();
set_flag(SHORTCUT_LABEL);
set_flag(MAC_USE_ACCENTS_MENU);
set_flag(NEEDS_KEYBOARD);
@@ -1217,7 +1235,7 @@ void Fl_Input_::put_in_buffer(int len) {
*/
int Fl_Input_::static_value(const char* str, int len) {
clear_changed();
- if (undowidget == this) undowidget = 0;
+ undo_->clear();
if (str == value_ && len == size_) return 0;
if (len) { // non-empty new value:
if (xscroll_ || yscroll_) {
@@ -1318,7 +1336,7 @@ void Fl_Input_::resize(int X, int Y, int W, int H) {
from the parent Fl_Group.
*/
Fl_Input_::~Fl_Input_() {
- if (undowidget == this) undowidget = 0;
+ delete undo_;
if (bufsize) free((void*)buffer);
}
diff --git a/src/Fl_Text_Buffer.cxx b/src/Fl_Text_Buffer.cxx
index 410492957..4733fc177 100644
--- a/src/Fl_Text_Buffer.cxx
+++ b/src/Fl_Text_Buffer.cxx
@@ -66,32 +66,44 @@ static int min(int i1, int i2)
#endif
+class Fl_Text_Undo_Action {
+public:
+ Fl_Text_Undo_Action() :
+ undobuffer(NULL),
+ undobufferlength(0),
+ undoat(0),
+ undocut(0),
+ undoinsert(0),
+ undoyankcut(0)
+ { }
+ ~Fl_Text_Undo_Action() {
+ if (undobuffer)
+ ::free(undobuffer);
+ }
-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
-
-/*
- Resize the undo buffer to match at least the requested size.
- */
-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);
+ char *undobuffer;
+ int undobufferlength;
+ int undoat; // points after insertion
+ int undocut; // number of characters deleted there
+ int undoinsert; // number of characters inserted
+ int undoyankcut; // length of valid contents of buffer, even if undocut=0
+
+ /*
+ Resize the undo buffer to match at least the requested size.
+ */
+ void undobuffersize(int n)
+ {
+ if (n > undobufferlength) {
+ undobufferlength = n + 128;
+ undobuffer = (char *)realloc(undobuffer, undobufferlength);
}
}
-}
+
+ void clear() {
+ undocut = undoinsert = 0;
+ }
+};
+
static void def_transcoding_warning_action(Fl_Text_Buffer *text)
{
@@ -123,6 +135,7 @@ Fl_Text_Buffer::Fl_Text_Buffer(int requestedSize, int preferredGapSize)
mPredeleteCbArgs = NULL;
mCursorPosHint = 0;
mCanUndo = 1;
+ mUndo = new Fl_Text_Undo_Action();
input_file_was_transcoded = 0;
transcoding_warning_action = def_transcoding_warning_action;
}
@@ -142,6 +155,7 @@ Fl_Text_Buffer::~Fl_Text_Buffer()
delete[] mPredeleteProcs;
delete[] mPredeleteCbArgs;
}
+ delete mUndo;
}
@@ -190,6 +204,9 @@ void Fl_Text_Buffer::text(const char *t)
/* Call the saved display routine(s) to update the screen */
call_modify_callbacks(0, deletedLength, insertedLength, 0, deletedText);
free((void *) deletedText);
+
+ if (mCanUndo)
+ mUndo->clear();
}
@@ -449,36 +466,39 @@ void Fl_Text_Buffer::copy(Fl_Text_Buffer * fromBuf, int fromStart,
*/
int Fl_Text_Buffer::undo(int *cursorPos)
{
- if (undowidget != this || (!undocut && !undoinsert && !mCanUndo))
+ if (!mCanUndo)
return 0;
- int ilen = undocut;
- int xlen = undoinsert;
- int b = undoat - xlen;
+ if (!mUndo->undocut && !mUndo->undoinsert)
+ return 0;
- if (xlen && undoyankcut && !ilen) {
- ilen = undoyankcut;
+ int ilen = mUndo->undocut;
+ int xlen = mUndo->undoinsert;
+ int b = mUndo->undoat - xlen;
+
+ if (xlen && mUndo->undoyankcut && !ilen) {
+ ilen = mUndo->undoyankcut;
}
if (xlen && ilen) {
- undobuffersize(ilen + 1);
- undobuffer[ilen] = 0;
- char *tmp = fl_strdup(undobuffer);
- replace(b, undoat, tmp);
+ mUndo->undobuffersize(ilen + 1);
+ mUndo->undobuffer[ilen] = 0;
+ char *tmp = fl_strdup(mUndo->undobuffer);
+ replace(b, mUndo->undoat, tmp);
if (cursorPos)
*cursorPos = mCursorPosHint;
free(tmp);
} else if (xlen) {
- remove(b, undoat);
+ remove(b, mUndo->undoat);
if (cursorPos)
*cursorPos = mCursorPosHint;
} else if (ilen) {
- undobuffersize(ilen + 1);
- undobuffer[ilen] = 0;
- insert(undoat, undobuffer);
+ mUndo->undobuffersize(ilen + 1);
+ mUndo->undobuffer[ilen] = 0;
+ insert(mUndo->undoat, mUndo->undobuffer);
if (cursorPos)
*cursorPos = mCursorPosHint;
- undoyankcut = 0;
+ mUndo->undoyankcut = 0;
}
return 1;
@@ -490,10 +510,17 @@ int Fl_Text_Buffer::undo(int *cursorPos)
*/
void Fl_Text_Buffer::canUndo(char flag)
{
+ if (flag) {
+ if (!mCanUndo) {
+ mUndo = new Fl_Text_Undo_Action();
+ }
+ } else {
+ if (mCanUndo) {
+ delete mUndo;
+ mUndo = NULL;
+ }
+ }
mCanUndo = flag;
- // disabling undo also clears the last undo operation!
- if (!mCanUndo && undowidget==this)
- undowidget = 0;
}
@@ -1190,15 +1217,14 @@ int Fl_Text_Buffer::insert_(int pos, const char *text)
update_selections(pos, 0, insertedLength);
if (mCanUndo) {
- if (undowidget == this && undoat == pos && undoinsert) {
- undoinsert += insertedLength;
+ if (mUndo->undoat == pos && mUndo->undoinsert) {
+ mUndo->undoinsert += insertedLength;
} else {
- undoinsert = insertedLength;
- undoyankcut = (undoat == pos) ? undocut : 0;
+ mUndo->undoinsert = insertedLength;
+ mUndo->undoyankcut = (mUndo->undoat == pos) ? mUndo->undocut : 0;
}
- undoat = pos + insertedLength;
- undocut = 0;
- undowidget = this;
+ mUndo->undoat = pos + insertedLength;
+ mUndo->undocut = 0;
}
return insertedLength;
@@ -1214,34 +1240,33 @@ void Fl_Text_Buffer::remove_(int start, int end)
/* if the gap is not contiguous to the area to remove, move it there */
if (mCanUndo) {
- if (undowidget == this && undoat == end && undocut) {
- undobuffersize(undocut + end - start + 1);
- memmove(undobuffer + end - start, undobuffer, undocut);
- undocut += end - start;
+ if (mUndo->undoat == end && mUndo->undocut) {
+ mUndo->undobuffersize(mUndo->undocut + end - start + 1);
+ memmove(mUndo->undobuffer + end - start, mUndo->undobuffer, mUndo->undocut);
+ mUndo->undocut += end - start;
} else {
- undocut = end - start;
- undobuffersize(undocut);
+ mUndo->undocut = end - start;
+ mUndo->undobuffersize(mUndo->undocut);
}
- undoat = start;
- undoinsert = 0;
- undoyankcut = 0;
- undowidget = this;
+ mUndo->undoat = start;
+ mUndo->undoinsert = 0;
+ mUndo->undoyankcut = 0;
}
if (start > mGapStart) {
if (mCanUndo)
- memcpy(undobuffer, mBuf + (mGapEnd - mGapStart) + start,
+ memcpy(mUndo->undobuffer, mBuf + (mGapEnd - mGapStart) + start,
end - start);
move_gap(start);
} else if (end < mGapStart) {
if (mCanUndo)
- memcpy(undobuffer, mBuf + start, end - start);
+ memcpy(mUndo->undobuffer, mBuf + start, end - start);
move_gap(end);
} else {
int prelen = mGapStart - start;
if (mCanUndo) {
- memcpy(undobuffer, mBuf + start, prelen);
- memcpy(undobuffer + prelen, mBuf + mGapEnd, end - start - prelen);
+ memcpy(mUndo->undobuffer, mBuf + start, prelen);
+ memcpy(mUndo->undobuffer + prelen, mBuf + mGapEnd, end - start - prelen);
}
}