mirror of https://github.com/fltk/fltk
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
This commit is contained in:
parent
66dabdb8f5
commit
3473297741
|
@ -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.
|
// Header file for Fl_Text_Buffer class.
|
||||||
//
|
//
|
||||||
|
@ -83,6 +83,7 @@ class FL_EXPORT Fl_Text_Buffer {
|
||||||
void remove(int start, int end);
|
void remove(int start, int end);
|
||||||
void replace(int start, int end, const char *text);
|
void replace(int start, int end, const char *text);
|
||||||
void copy(Fl_Text_Buffer* fromBuf, int fromStart, int fromEnd, int toPos);
|
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 insertfile(const char *file, int pos, int buflen = 128*1024);
|
||||||
int appendfile(const char *file, int buflen = 128*1024)
|
int appendfile(const char *file, int buflen = 128*1024)
|
||||||
{ return insertfile(file, length(), buflen); }
|
{ return insertfile(file, length(), buflen); }
|
||||||
|
@ -249,5 +250,5 @@ class FL_EXPORT Fl_Text_Buffer {
|
||||||
#endif
|
#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 $".
|
||||||
//
|
//
|
||||||
|
|
|
@ -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.
|
// 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_cut(int c, Fl_Text_Editor* e);
|
||||||
static int kf_paste(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_select_all(int c, Fl_Text_Editor* e);
|
||||||
|
static int kf_undo(int c, Fl_Text_Editor* e);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int handle_key();
|
int handle_key();
|
||||||
|
@ -102,6 +103,6 @@ class FL_EXPORT Fl_Text_Editor : public Fl_Text_Display {
|
||||||
#endif
|
#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 $".
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
|
@ -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.
|
// Copyright 2001-2002 by Bill Spitzak and others.
|
||||||
// Original code Copyright Mark Edel. Permission to distribute under
|
// 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",
|
"dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
|
||||||
"can", "em", "sub", "esc", "fs", "gs", "rs", "us"};
|
"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
|
** 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
|
** 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 );
|
call_predelete_callbacks( start, end-start );
|
||||||
deletedText = text_range( start, end );
|
deletedText = text_range( start, end );
|
||||||
remove_( start, end );
|
remove_( start, end );
|
||||||
|
//undoyankcut = undocut;
|
||||||
nInserted = insert_( start, s );
|
nInserted = insert_( start, s );
|
||||||
mCursorPosHint = start + nInserted;
|
mCursorPosHint = start + nInserted;
|
||||||
call_modify_callbacks( start, end - start, nInserted, 0, deletedText );
|
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 );
|
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
|
** Insert "text" columnwise into buffer starting at displayed character
|
||||||
** position "column" on the line beginning at "startPos". Opens a rectangular
|
** 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;
|
mLength += insertedLength;
|
||||||
update_selections( pos, 0, 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;
|
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 ) {
|
void Fl_Text_Buffer::remove_( int start, int end ) {
|
||||||
/* if the gap is not contiguous to the area to remove, move it there */
|
/* 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 );
|
move_gap( start );
|
||||||
else if ( end < mGapStart )
|
}
|
||||||
|
else if ( end < mGapStart ) {
|
||||||
|
memcpy( undobuffer, mBuf+start, end-start );
|
||||||
move_gap( end );
|
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 */
|
/* expand the gap to encompass the deleted characters */
|
||||||
mGapEnd += end - mGapStart;
|
mGapEnd += end - mGapStart;
|
||||||
|
@ -1843,8 +1938,10 @@ void Fl_Text_Buffer::remove_selection_( Fl_Text_Selection *sel ) {
|
||||||
return;
|
return;
|
||||||
if ( isRect )
|
if ( isRect )
|
||||||
remove_rectangular( start, end, rectStart, rectEnd );
|
remove_rectangular( start, end, rectStart, rectEnd );
|
||||||
else
|
else {
|
||||||
remove( start, end );
|
remove( start, end );
|
||||||
|
//undoyankcut = undocut;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fl_Text_Buffer::replace_selection_( Fl_Text_Selection *sel, const char *s ) {
|
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 $".
|
||||||
//
|
//
|
||||||
|
|
|
@ -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.
|
// Copyright 2001-2002 by Bill Spitzak and others.
|
||||||
// Original code Copyright Mark Edel. Permission to distribute under
|
// 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_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_Page_Down, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move },
|
||||||
//{ FL_Clear, 0, Fl_Text_Editor::delete_to_eol },
|
//{ FL_Clear, 0, Fl_Text_Editor::delete_to_eol },
|
||||||
//{ 'z', FL_CTRL, Fl_Text_Editor::undo },
|
{ 'z', FL_CTRL, Fl_Text_Editor::kf_undo },
|
||||||
//{ '/', FL_CTRL, Fl_Text_Editor::undo },
|
{ '/', FL_CTRL, Fl_Text_Editor::kf_undo },
|
||||||
{ 'x', FL_CTRL, Fl_Text_Editor::kf_cut },
|
{ 'x', FL_CTRL, Fl_Text_Editor::kf_cut },
|
||||||
{ FL_Delete, FL_SHIFT, Fl_Text_Editor::kf_cut },
|
{ FL_Delete, FL_SHIFT, Fl_Text_Editor::kf_cut },
|
||||||
{ 'c', FL_CTRL, Fl_Text_Editor::kf_copy },
|
{ 'c', FL_CTRL, Fl_Text_Editor::kf_copy },
|
||||||
|
@ -105,6 +105,7 @@ static struct {
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
// Define CMD+key accelerators...
|
// Define CMD+key accelerators...
|
||||||
|
{ 'z', FL_COMMAND, Fl_Text_Editor::kf_undo },
|
||||||
{ 'x', FL_COMMAND, Fl_Text_Editor::kf_cut },
|
{ 'x', FL_COMMAND, Fl_Text_Editor::kf_cut },
|
||||||
{ 'c', FL_COMMAND, Fl_Text_Editor::kf_copy },
|
{ 'c', FL_COMMAND, Fl_Text_Editor::kf_copy },
|
||||||
{ 'v', FL_COMMAND, Fl_Text_Editor::kf_paste },
|
{ '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;
|
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() {
|
int Fl_Text_Editor::handle_key() {
|
||||||
|
|
||||||
// Call fltk's rules to try to turn this into a printing character.
|
// 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 $".
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in New Issue