mirror of https://github.com/fltk/fltk
parent
72f8604381
commit
7f87c847ba
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// Input header file for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2021 by Bill Spitzak and others.
|
||||
// Copyright 1998-2023 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#define FL_MULTILINE_OUTPUT_WRAP (FL_MULTILINE_INPUT | FL_INPUT_READONLY | FL_INPUT_WRAP)
|
||||
|
||||
class Fl_Input_Undo_Action;
|
||||
class Fl_Input_Undo_Action_List;
|
||||
|
||||
/**
|
||||
This class provides a low-overhead text input field.
|
||||
|
@ -148,6 +149,8 @@ class FL_EXPORT Fl_Input_ : public Fl_Widget {
|
|||
|
||||
/** \internal local undo event */
|
||||
Fl_Input_Undo_Action* undo_;
|
||||
Fl_Input_Undo_Action_List* undo_list_;
|
||||
Fl_Input_Undo_Action_List* redo_list_;
|
||||
|
||||
/** \internal Horizontal cursor position in pixels while moving up or down. */
|
||||
static double up_down_pos;
|
||||
|
@ -212,6 +215,9 @@ protected:
|
|||
/* Return the number of lines displayed on a single page. */
|
||||
int linesPerPage();
|
||||
|
||||
/* Apply the current undo/redo operation, called from undo() or redo() */
|
||||
int apply_undo();
|
||||
|
||||
public:
|
||||
|
||||
/* Change the size of the widget. */
|
||||
|
@ -378,6 +384,9 @@ public:
|
|||
/* Undo previous changes to the text buffer. */
|
||||
int undo();
|
||||
|
||||
/* Redo previous undo operations. */
|
||||
int redo();
|
||||
|
||||
/* Copy the yank buffer to the clipboard. */
|
||||
int copy_cuts();
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// Header file for Fl_Text_Buffer class.
|
||||
//
|
||||
// Copyright 2001-2021 by Bill Spitzak and others.
|
||||
// Copyright 2001-2023 by Bill Spitzak and others.
|
||||
// Original code Copyright Mark Edel. Permission to distribute under
|
||||
// the LGPL for the FLTK library granted by Mark Edel.
|
||||
//
|
||||
|
@ -61,6 +61,7 @@
|
|||
|
||||
#include "Fl_Export.H"
|
||||
|
||||
class Fl_Text_Undo_Action_List;
|
||||
class Fl_Text_Undo_Action;
|
||||
|
||||
/**
|
||||
|
@ -326,6 +327,11 @@ public:
|
|||
*/
|
||||
int undo(int *cp=0);
|
||||
|
||||
/**
|
||||
Redo previous undo action.
|
||||
*/
|
||||
int redo(int *cp=0);
|
||||
|
||||
/**
|
||||
Lets the undo system know if we can undo changes
|
||||
*/
|
||||
|
@ -813,6 +819,11 @@ protected:
|
|||
*/
|
||||
void update_selections(int pos, int nDeleted, int nInserted);
|
||||
|
||||
/**
|
||||
Apply the current undo/redo operation, called from undo() or redo().
|
||||
*/
|
||||
int apply_undo(Fl_Text_Undo_Action* action, int* cursorPos);
|
||||
|
||||
Fl_Text_Selection mPrimary; /**< highlighted areas */
|
||||
Fl_Text_Selection mSecondary; /**< highlighted areas */
|
||||
Fl_Text_Selection mHighlight; /**< highlighted areas */
|
||||
|
@ -841,6 +852,8 @@ protected:
|
|||
bytes and should only be increased if frequent
|
||||
and large changes in buffer size are expected */
|
||||
Fl_Text_Undo_Action* mUndo; /**< local undo event */
|
||||
Fl_Text_Undo_Action_List* mUndoList; /**< List of undo event */
|
||||
Fl_Text_Undo_Action_List* mRedoList; /**< List of redo event */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// Header file for Fl_Text_Editor class.
|
||||
//
|
||||
// Copyright 2001-2010 by Bill Spitzak and others.
|
||||
// Copyright 2001-2023 by Bill Spitzak and others.
|
||||
// Original code Copyright Mark Edel. Permission to distribute under
|
||||
// the LGPL for the FLTK library granted by Mark Edel.
|
||||
//
|
||||
|
@ -110,6 +110,7 @@ class FL_EXPORT Fl_Text_Editor : public Fl_Text_Display {
|
|||
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);
|
||||
static int kf_redo(int c, Fl_Text_Editor* e);
|
||||
|
||||
protected:
|
||||
int handle_key();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// Input widget for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2021 by Bill Spitzak and others.
|
||||
// Copyright 1998-2023 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
|
@ -275,10 +275,10 @@ int Fl_Input::kf_undo() {
|
|||
return undo();
|
||||
}
|
||||
|
||||
// Redo. (currently unimplemented.. toggles undo() instead)
|
||||
// Redo.
|
||||
int Fl_Input::kf_redo() {
|
||||
if (readonly()) { fl_beep(); return 1; }
|
||||
return kf_undo(); // currently we don't support multilevel undo
|
||||
return redo();
|
||||
}
|
||||
|
||||
// Do a copy operation
|
||||
|
|
|
@ -33,6 +33,7 @@ extern void fl_draw(const char*, int, float, float);
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// see: Fl_Text_Undo_Action
|
||||
class Fl_Input_Undo_Action {
|
||||
public:
|
||||
Fl_Input_Undo_Action() :
|
||||
|
@ -71,6 +72,50 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
// see: Fl_Text_Undo_Action_List
|
||||
class Fl_Input_Undo_Action_List {
|
||||
Fl_Input_Undo_Action** list_;
|
||||
int list_size_;
|
||||
int list_capacity_;
|
||||
public:
|
||||
Fl_Input_Undo_Action_List() :
|
||||
list_(NULL),
|
||||
list_size_(0),
|
||||
list_capacity_(0)
|
||||
{ }
|
||||
|
||||
~Fl_Input_Undo_Action_List() {
|
||||
clear();
|
||||
}
|
||||
|
||||
void push(Fl_Input_Undo_Action* action) {
|
||||
if (list_size_ == list_capacity_) {
|
||||
list_capacity_ += 25;
|
||||
list_ = (Fl_Input_Undo_Action**)realloc(list_, list_capacity_ * sizeof(Fl_Input_Undo_Action*));
|
||||
}
|
||||
list_[list_size_++] = action;
|
||||
}
|
||||
|
||||
Fl_Input_Undo_Action* pop() {
|
||||
if (list_size_ > 0)
|
||||
return list_[--list_size_];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
if (list_) {
|
||||
for (int i=0; i<list_size_; i++) {
|
||||
delete list_[i];
|
||||
}
|
||||
delete list_;
|
||||
}
|
||||
list_ = NULL;
|
||||
list_size_ = 0;
|
||||
list_capacity_ = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** \internal
|
||||
Converts a given text segment into the text that will be rendered on screen.
|
||||
|
@ -186,7 +231,7 @@ double Fl_Input_::expandpos(
|
|||
/** \internal
|
||||
Marks a range of characters for update.
|
||||
|
||||
This call marks all characters from \p to the end of the
|
||||
This call marks all characters from \p p to the end of the
|
||||
text buffer for update. At least these characters
|
||||
will be redrawn in the next update cycle.
|
||||
|
||||
|
@ -891,6 +936,9 @@ int Fl_Input_::replace(int b, int e, const char* text, int ilen) {
|
|||
} else if (e == undo_->undoat && (e-b)<undo_->undoinsert) {
|
||||
undo_->undoinsert -= e-b;
|
||||
} else {
|
||||
redo_list_->clear();
|
||||
undo_list_->push(undo_);
|
||||
undo_ = new Fl_Input_Undo_Action();
|
||||
undo_->undobuffersize(e-b);
|
||||
memcpy(undo_->undobuffer, value_+b, e-b);
|
||||
undo_->undocut = e-b;
|
||||
|
@ -903,9 +951,12 @@ int Fl_Input_::replace(int b, int e, const char* text, int ilen) {
|
|||
}
|
||||
|
||||
if (ilen) {
|
||||
if (b == undo_->undoat)
|
||||
if (b == undo_->undoat) {
|
||||
undo_->undoinsert += ilen;
|
||||
else {
|
||||
} else {
|
||||
redo_list_->clear();
|
||||
undo_list_->push(undo_);
|
||||
undo_ = new Fl_Input_Undo_Action();
|
||||
undo_->undocut = 0;
|
||||
undo_->undoinsert = ilen;
|
||||
}
|
||||
|
@ -947,13 +998,13 @@ int Fl_Input_::replace(int b, int e, const char* text, int ilen) {
|
|||
}
|
||||
|
||||
/**
|
||||
Undoes previous changes to the text buffer.
|
||||
Apply the current undo/redo operation
|
||||
|
||||
This call undoes a number of previous calls to replace().
|
||||
It's up to undo() and redo() to push and pop actions to and from the lists.
|
||||
|
||||
\return non-zero if any change was made.
|
||||
*/
|
||||
int Fl_Input_::undo() {
|
||||
\return 1 if the current action changed any text.
|
||||
\see undo(), redo() */
|
||||
int Fl_Input_::apply_undo() {
|
||||
was_up_down = 0;
|
||||
if (!undo_->undocut && !undo_->undoinsert) return 0;
|
||||
|
||||
|
@ -962,6 +1013,8 @@ int Fl_Input_::undo() {
|
|||
int b = undo_->undoat-xlen;
|
||||
int b1 = b;
|
||||
|
||||
minimal_update(position_);
|
||||
|
||||
put_in_buffer(size_+ilen);
|
||||
|
||||
if (ilen) {
|
||||
|
@ -989,10 +1042,52 @@ int Fl_Input_::undo() {
|
|||
while (b1 > 0 && index(b1)!='\n') b1--;
|
||||
minimal_update(b1);
|
||||
set_changed();
|
||||
if (when()&FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
Undoes previous changes to the text buffer.
|
||||
|
||||
This call undoes a number of previous calls to replace().
|
||||
|
||||
\return non-zero if any change was made.
|
||||
*/
|
||||
int Fl_Input_::undo() {
|
||||
if (apply_undo() == 0)
|
||||
return 0;
|
||||
|
||||
redo_list_->push(undo_);
|
||||
undo_ = undo_list_->pop();
|
||||
if (!undo_) undo_ = new Fl_Input_Undo_Action();
|
||||
|
||||
if (when()&FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
Redo previous undo operation.
|
||||
|
||||
This call reapplies previously executed undo operations.
|
||||
|
||||
\return non-zero if any change was made.
|
||||
*/
|
||||
int Fl_Input_::redo() {
|
||||
Fl_Input_Undo_Action *redo_action = redo_list_->pop();
|
||||
if (!redo_action)
|
||||
return 0;
|
||||
|
||||
if (undo_->undocut || undo_->undoinsert)
|
||||
undo_list_->push(undo_);
|
||||
undo_ = redo_action;
|
||||
|
||||
int ret = apply_undo();
|
||||
if (ret && (when()&FL_WHEN_CHANGED)) do_callback(FL_REASON_CHANGED);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
Copies the \e yank buffer to the clipboard.
|
||||
|
||||
|
@ -1168,6 +1263,8 @@ Fl_Input_::Fl_Input_(int X, int Y, int W, int H, const char* l)
|
|||
xscroll_ = yscroll_ = 0;
|
||||
maximum_size_ = 32767;
|
||||
shortcut_ = 0;
|
||||
undo_list_ = new Fl_Input_Undo_Action_List();
|
||||
redo_list_ = new Fl_Input_Undo_Action_List();
|
||||
undo_ = new Fl_Input_Undo_Action();
|
||||
set_flag(SHORTCUT_LABEL);
|
||||
set_flag(MAC_USE_ACCENTS_MENU);
|
||||
|
@ -1236,6 +1333,8 @@ void Fl_Input_::put_in_buffer(int len) {
|
|||
int Fl_Input_::static_value(const char* str, int len) {
|
||||
clear_changed();
|
||||
undo_->clear();
|
||||
undo_list_->clear();
|
||||
redo_list_->clear();
|
||||
if (str == value_ && len == size_) return 0;
|
||||
if (len) { // non-empty new value:
|
||||
if (xscroll_ || yscroll_) {
|
||||
|
@ -1336,6 +1435,8 @@ void Fl_Input_::resize(int X, int Y, int W, int H) {
|
|||
from the parent Fl_Group.
|
||||
*/
|
||||
Fl_Input_::~Fl_Input_() {
|
||||
delete undo_list_;
|
||||
delete redo_list_;
|
||||
delete undo_;
|
||||
if (bufsize) free((void*)buffer);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// Copyright 2001-2017 by Bill Spitzak and others.
|
||||
// Copyright 2001-2023 by Bill Spitzak and others.
|
||||
// Original code Copyright Mark Edel. Permission to distribute under
|
||||
// the LGPL for the FLTK library granted by Mark Edel.
|
||||
//
|
||||
|
@ -66,6 +66,23 @@ static int min(int i1, int i2)
|
|||
|
||||
#endif
|
||||
|
||||
/*
|
||||
Undo/Redo is handled with Fl_Text_Undo_Action. The names of the class members
|
||||
relate to the original action.
|
||||
|
||||
Deleting text will store the number of bytes deleted in `undocut`, and store
|
||||
the deleted text in `undobuffer`. `undoat` is the insertion position.
|
||||
|
||||
Inserting text will store the number of bytes inserted in `undoinsert` and
|
||||
`undoat` will point after the inserted text.
|
||||
|
||||
If text is deleted first and then text is inserted at the same position, it's
|
||||
called a yankcut, and the number of bytes that were deleted is stored in
|
||||
`undoyankcut`, again storing the deleted text in `undobuffer`.
|
||||
|
||||
If an undo action is run, text is deleted and inserted via the normal
|
||||
Fl_Text_Editor methods, generating the inverse undo action (redo) in mUndo.
|
||||
*/
|
||||
class Fl_Text_Undo_Action {
|
||||
public:
|
||||
Fl_Text_Undo_Action() :
|
||||
|
@ -102,6 +119,76 @@ public:
|
|||
void clear() {
|
||||
undocut = undoinsert = 0;
|
||||
}
|
||||
|
||||
bool empty() {
|
||||
return (!undocut && !undoinsert);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Undo events are stored in a Last In - First Out stack.
|
||||
|
||||
Any insertion or deletion of text will either add to the current undo event
|
||||
in mUndo, or generate a new undo event if cursor positions are not consecutive.
|
||||
The previously current undo event will then be pushed to the undo list and
|
||||
the redo event list is purged.
|
||||
|
||||
If the user calls undo(), the current undo event in mUndo will be run,
|
||||
generating a matching redo event in mUndo. The redo event is then pushed into
|
||||
the redo list, and the next undo event is popped from the undo list and made
|
||||
current.
|
||||
|
||||
A list can be locked to be protected from purging while running an undo event.
|
||||
*/
|
||||
class Fl_Text_Undo_Action_List {
|
||||
Fl_Text_Undo_Action** list_;
|
||||
int list_size_;
|
||||
int list_capacity_;
|
||||
bool locked_;
|
||||
public:
|
||||
Fl_Text_Undo_Action_List() :
|
||||
list_(NULL),
|
||||
list_size_(0),
|
||||
list_capacity_(0),
|
||||
locked_(false)
|
||||
{ }
|
||||
|
||||
~Fl_Text_Undo_Action_List() {
|
||||
unlock();
|
||||
clear();
|
||||
}
|
||||
|
||||
void push(Fl_Text_Undo_Action* action) {
|
||||
if (list_size_ == list_capacity_) {
|
||||
list_capacity_ += 25;
|
||||
list_ = (Fl_Text_Undo_Action**)realloc(list_, list_capacity_ * sizeof(Fl_Text_Undo_Action*));
|
||||
}
|
||||
list_[list_size_++] = action;
|
||||
}
|
||||
|
||||
Fl_Text_Undo_Action* pop() {
|
||||
if (list_size_ > 0) {
|
||||
Fl_Text_Undo_Action *action = list_[list_size_-1];
|
||||
return list_[--list_size_];
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
if (locked_) return;
|
||||
if (list_) {
|
||||
for (int i=0; i<list_size_; i++) {
|
||||
delete list_[i];
|
||||
}
|
||||
delete list_;
|
||||
}
|
||||
list_ = NULL;
|
||||
list_size_ = 0;
|
||||
list_capacity_ = 0;
|
||||
}
|
||||
|
||||
void lock() { locked_ = true; }
|
||||
void unlock() { locked_ = false; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -136,6 +223,8 @@ Fl_Text_Buffer::Fl_Text_Buffer(int requestedSize, int preferredGapSize)
|
|||
mCursorPosHint = 0;
|
||||
mCanUndo = 1;
|
||||
mUndo = new Fl_Text_Undo_Action();
|
||||
mUndoList = new Fl_Text_Undo_Action_List();
|
||||
mRedoList = new Fl_Text_Undo_Action_List();
|
||||
input_file_was_transcoded = 0;
|
||||
transcoding_warning_action = def_transcoding_warning_action;
|
||||
}
|
||||
|
@ -156,6 +245,8 @@ Fl_Text_Buffer::~Fl_Text_Buffer()
|
|||
delete[] mPredeleteCbArgs;
|
||||
}
|
||||
delete mUndo;
|
||||
delete mUndoList;
|
||||
delete mRedoList;
|
||||
}
|
||||
|
||||
|
||||
|
@ -205,8 +296,11 @@ void Fl_Text_Buffer::text(const char *t)
|
|||
call_modify_callbacks(0, deletedLength, insertedLength, 0, deletedText);
|
||||
free((void *) deletedText);
|
||||
|
||||
if (mCanUndo)
|
||||
if (mCanUndo) {
|
||||
mUndo->clear();
|
||||
mUndoList->clear();
|
||||
mRedoList->clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -459,51 +553,97 @@ void Fl_Text_Buffer::copy(Fl_Text_Buffer * fromBuf, int fromStart,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Take the previous changes and undo them. Return the previous
|
||||
cursor position in cursorPos. Returns 1 if the undo was applied.
|
||||
CursorPos will be at a character boundary.
|
||||
/**
|
||||
Apply the current undo/redo operation, called from undo() or redo().
|
||||
*/
|
||||
int Fl_Text_Buffer::undo(int *cursorPos)
|
||||
int Fl_Text_Buffer::apply_undo(Fl_Text_Undo_Action* action, int* cursorPos)
|
||||
{
|
||||
if (!mCanUndo)
|
||||
if (action->empty())
|
||||
return 0;
|
||||
|
||||
if (!mUndo->undocut && !mUndo->undoinsert)
|
||||
return 0;
|
||||
mRedoList->lock();
|
||||
|
||||
int ilen = mUndo->undocut;
|
||||
int xlen = mUndo->undoinsert;
|
||||
int b = mUndo->undoat - xlen;
|
||||
int ilen = action->undocut;
|
||||
int xlen = action->undoinsert;
|
||||
int b = action->undoat - xlen;
|
||||
|
||||
if (xlen && mUndo->undoyankcut && !ilen) {
|
||||
ilen = mUndo->undoyankcut;
|
||||
if (xlen && action->undoyankcut && !ilen) {
|
||||
ilen = action->undoyankcut;
|
||||
}
|
||||
|
||||
if (xlen && ilen) {
|
||||
mUndo->undobuffersize(ilen + 1);
|
||||
mUndo->undobuffer[ilen] = 0;
|
||||
char *tmp = fl_strdup(mUndo->undobuffer);
|
||||
replace(b, mUndo->undoat, tmp);
|
||||
action->undobuffersize(ilen + 1);
|
||||
action->undobuffer[ilen] = 0;
|
||||
char *tmp = fl_strdup(action->undobuffer);
|
||||
replace(b, action->undoat, tmp);
|
||||
if (cursorPos)
|
||||
*cursorPos = mCursorPosHint;
|
||||
free(tmp);
|
||||
} else if (xlen) {
|
||||
remove(b, mUndo->undoat);
|
||||
remove(b, action->undoat);
|
||||
if (cursorPos)
|
||||
*cursorPos = mCursorPosHint;
|
||||
} else if (ilen) {
|
||||
mUndo->undobuffersize(ilen + 1);
|
||||
mUndo->undobuffer[ilen] = 0;
|
||||
insert(mUndo->undoat, mUndo->undobuffer);
|
||||
action->undobuffersize(ilen + 1);
|
||||
action->undobuffer[ilen] = 0;
|
||||
insert(action->undoat, action->undobuffer);
|
||||
if (cursorPos)
|
||||
*cursorPos = mCursorPosHint;
|
||||
mUndo->undoyankcut = 0;
|
||||
action->undoyankcut = 0;
|
||||
}
|
||||
|
||||
mRedoList->unlock();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
Take the previous changes and undo them. Return the previous
|
||||
cursor position in cursorPos. Returns 1 if the undo was applied.
|
||||
CursorPos will be at a character boundary.
|
||||
*/
|
||||
int Fl_Text_Buffer::undo(int *cursorPos) {
|
||||
if (!mCanUndo || mUndo->empty())
|
||||
return 0;
|
||||
|
||||
// save the current undo action and add an empty action to avoid generating yankcuts
|
||||
Fl_Text_Undo_Action* action = mUndo;
|
||||
mUndo = new Fl_Text_Undo_Action();
|
||||
|
||||
int ret = apply_undo(action, cursorPos);
|
||||
delete action;
|
||||
|
||||
if (ret) {
|
||||
// push the generated undo action to the redo list
|
||||
mRedoList->push(mUndo);
|
||||
// drop the empty action we previously created
|
||||
mUndo = mUndoList->pop();
|
||||
if (mUndo) {
|
||||
delete mUndo;
|
||||
// pop the undo action before that and make it the current undo action
|
||||
mUndo = mUndoList->pop();
|
||||
if (!mUndo) mUndo = new Fl_Text_Undo_Action();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
Redo previous undo action.
|
||||
*/
|
||||
int Fl_Text_Buffer::redo(int *cursorPos) {
|
||||
if (!mCanUndo)
|
||||
return 0;
|
||||
|
||||
Fl_Text_Undo_Action *redo_action = mRedoList->pop();
|
||||
if (!redo_action)
|
||||
return 0;
|
||||
|
||||
// running the redo action will also generate a new undo action
|
||||
// Note: there is a slight chance that the current undo action and the
|
||||
// generated action merge into one.
|
||||
return apply_undo(redo_action, cursorPos);
|
||||
}
|
||||
|
||||
/*
|
||||
Set a flag if undo function will work.
|
||||
|
@ -1218,10 +1358,20 @@ int Fl_Text_Buffer::insert_(int pos, const char *text)
|
|||
|
||||
if (mCanUndo) {
|
||||
if (mUndo->undoat == pos && mUndo->undoinsert) {
|
||||
// continue inserting text at the given cursor position
|
||||
mUndo->undoinsert += insertedLength;
|
||||
} else {
|
||||
int yankcut = (mUndo->undoat == pos) ? mUndo->undocut : 0;
|
||||
if (!yankcut) {
|
||||
// insert text at a new position, so generate a new undo action
|
||||
mRedoList->clear();
|
||||
mUndoList->push(mUndo);
|
||||
mUndo = new Fl_Text_Undo_Action();
|
||||
} else {
|
||||
// we deleted and inserted at the same position, making this a yankcut
|
||||
}
|
||||
mUndo->undoinsert = insertedLength;
|
||||
mUndo->undoyankcut = (mUndo->undoat == pos) ? mUndo->undocut : 0;
|
||||
mUndo->undoyankcut = yankcut;
|
||||
}
|
||||
mUndo->undoat = pos + insertedLength;
|
||||
mUndo->undocut = 0;
|
||||
|
@ -1241,10 +1391,15 @@ void Fl_Text_Buffer::remove_(int start, int end)
|
|||
|
||||
if (mCanUndo) {
|
||||
if (mUndo->undoat == end && mUndo->undocut) {
|
||||
// continue to remove text at the same cursor position
|
||||
mUndo->undobuffersize(mUndo->undocut + end - start + 1);
|
||||
memmove(mUndo->undobuffer + end - start, mUndo->undobuffer, mUndo->undocut);
|
||||
mUndo->undocut += end - start;
|
||||
} else {
|
||||
// remove text at a new position, so generate a new undo action
|
||||
mRedoList->clear();
|
||||
mUndoList->push(mUndo);
|
||||
mUndo = new Fl_Text_Undo_Action();
|
||||
mUndo->undocut = end - start;
|
||||
mUndo->undobuffersize(mUndo->undocut);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// Copyright 2001-2018 by Bill Spitzak and others.
|
||||
// Copyright 2001-2023 by Bill Spitzak and others.
|
||||
//
|
||||
// Original code Copyright Mark Edel. Permission to distribute under
|
||||
// the LGPL for the FLTK library granted by Mark Edel.
|
||||
|
@ -132,7 +132,9 @@ static struct {
|
|||
{ 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::kf_undo },
|
||||
{ '/', FL_CTRL, Fl_Text_Editor::kf_undo },
|
||||
{ 'z', FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_redo }, // MSWindows screen driver also defines Ctrl-Y
|
||||
{ '/', FL_CTRL, Fl_Text_Editor::kf_undo }, // Emacs
|
||||
{ '?', FL_CTRL, Fl_Text_Editor::kf_redo }, // Emacs
|
||||
{ '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 },
|
||||
|
@ -602,7 +604,7 @@ int Fl_Text_Editor::kf_select_all(int, Fl_Text_Editor* e) {
|
|||
int Fl_Text_Editor::kf_undo(int , Fl_Text_Editor* e) {
|
||||
e->buffer()->unselect();
|
||||
Fl::copy("", 0, 0);
|
||||
int crsr;
|
||||
int crsr = e->insert_position();
|
||||
int ret = e->buffer()->undo(&crsr);
|
||||
e->insert_position(crsr);
|
||||
e->show_insert_position();
|
||||
|
@ -611,6 +613,22 @@ int Fl_Text_Editor::kf_undo(int , Fl_Text_Editor* e) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
/** Redo last undo action.
|
||||
Also deselects previous selection.
|
||||
The key value \p 'c' is currently unused.
|
||||
*/
|
||||
int Fl_Text_Editor::kf_redo(int , Fl_Text_Editor* e) {
|
||||
e->buffer()->unselect();
|
||||
Fl::copy("", 0, 0);
|
||||
int crsr = e->insert_position();
|
||||
int ret = e->buffer()->redo(&crsr);
|
||||
e->insert_position(crsr);
|
||||
e->show_insert_position();
|
||||
e->set_changed();
|
||||
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Handles a key press in the editor */
|
||||
int Fl_Text_Editor::handle_key() {
|
||||
// Call FLTK's rules to try to turn this into a printing character.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// Definition of Apple Cocoa Screen interface.
|
||||
//
|
||||
// Copyright 1998-2022 by Bill Spitzak and others.
|
||||
// Copyright 1998-2023 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
|
@ -79,6 +79,7 @@ Fl_Screen_Driver::Keyname darwin_key_table[] = {
|
|||
static Fl_Text_Editor::Key_Binding extra_bindings[] = {
|
||||
// Define CMD+key accelerators...
|
||||
{ 'z', FL_COMMAND, Fl_Text_Editor::kf_undo ,0},
|
||||
{ 'z', FL_COMMAND|FL_SHIFT, Fl_Text_Editor::kf_redo ,0},
|
||||
{ 'x', FL_COMMAND, Fl_Text_Editor::kf_cut ,0},
|
||||
{ 'c', FL_COMMAND, Fl_Text_Editor::kf_copy ,0},
|
||||
{ 'v', FL_COMMAND, Fl_Text_Editor::kf_paste ,0},
|
||||
|
|
|
@ -41,9 +41,7 @@ protected:
|
|||
|
||||
public:
|
||||
float dpi[MAX_SCREENS][2];
|
||||
Fl_WinAPI_Screen_Driver() : Fl_Screen_Driver() {
|
||||
for (int i = 0; i < MAX_SCREENS; i++) scale_of_screen[i] = 1;
|
||||
}
|
||||
Fl_WinAPI_Screen_Driver();
|
||||
// --- display management
|
||||
int visual(int flags) FL_OVERRIDE;
|
||||
// --- screen configuration
|
||||
|
|
|
@ -38,6 +38,17 @@ extern const char *fl_bg2;
|
|||
# include <multimon.h>
|
||||
#endif // !HMONITOR_DECLARED && _WIN32_WINNT < 0x0500
|
||||
|
||||
static Fl_Text_Editor::Key_Binding extra_bindings[] = {
|
||||
// Define MS Windows specific accelerators...
|
||||
{ 'y', FL_CTRL, Fl_Text_Editor::kf_redo ,0},
|
||||
{ 0, 0, 0 ,0}
|
||||
};
|
||||
|
||||
|
||||
Fl_WinAPI_Screen_Driver::Fl_WinAPI_Screen_Driver() : Fl_Screen_Driver() {
|
||||
text_editor_extra_key_bindings = extra_bindings;
|
||||
for (int i = 0; i < MAX_SCREENS; i++) scale_of_screen[i] = 1;
|
||||
}
|
||||
|
||||
int Fl_WinAPI_Screen_Driver::visual(int flags)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue