undo off by default, Emacs-style undo added

svn: r1719
This commit is contained in:
Matthew Flatt 2005-12-30 21:41:58 +00:00
parent f695e16a52
commit e422152bc4
13 changed files with 560 additions and 83 deletions

View File

@ -79,7 +79,8 @@
(inherit get-max-width set-max-width get-admin (inherit get-max-width set-max-width get-admin
get-keymap get-style-list get-keymap get-style-list
set-modified set-filename set-modified set-filename
get-file put-file) get-file put-file
get-max-undo-history)
(define canvases null) (define canvases null)
(define active-canvas #f) (define active-canvas #f)
(define auto-set-wrap? #f) (define auto-set-wrap? #f)
@ -360,6 +361,7 @@
[else text%]))]) [else text%]))])
(send e set-keymap (get-keymap)) (send e set-keymap (get-keymap))
(send e set-style-list (get-style-list)) (send e set-style-list (get-style-list))
(send e set-max-undo-history (get-max-undo-history))
e))))]) e))))])
(apply super-make-object args))) (apply super-make-object args)))

View File

@ -15,7 +15,7 @@
;; The REPL buffer class ;; The REPL buffer class
(define esq:text% (define esq:text%
(class100 text% () (class100 text% ()
(inherit insert last-position get-text erase change-style clear-undos) (inherit insert last-position get-text erase change-style clear-undos set-max-undo-history)
(rename [super-on-char on-char]) (rename [super-on-char on-char])
(private-field [prompt-pos 0] [locked? #f]) (private-field [prompt-pos 0] [locked? #f])
(augment (augment
@ -62,7 +62,8 @@
(send (make-object wx:style-delta% 'change-italic) set-delta-foreground "RED") (send (make-object wx:style-delta% 'change-italic) set-delta-foreground "RED")
s e))) s e)))
(insert "The current input port always returns eof.") (insert #\newline) (insert "The current input port always returns eof.") (insert #\newline)
(new-prompt)))) (new-prompt)
(set-max-undo-history 'forever))))
;; GUI creation ;; GUI creation
(define frame (make-object (class100 frame% args (define frame (make-object (class100 frame% args

View File

@ -20,7 +20,7 @@
(define text-field-text% (define text-field-text%
(class100 text% (cb ret-cb control set-cb-mgrs!) (class100 text% (cb ret-cb control set-cb-mgrs!)
(rename [super-on-char on-char]) (rename [super-on-char on-char])
(inherit get-text last-position) (inherit get-text last-position set-max-undo-history)
(private-field (private-field
[return-cb ret-cb]) [return-cb ret-cb])
(private-field (private-field
@ -60,7 +60,8 @@
(lambda () (set! block-callback (sub1 block-callback))))) (lambda () (set! block-callback (sub1 block-callback)))))
(lambda () (lambda ()
(set! block-callback 0))) (set! block-callback 0)))
(super-init)))) (super-init)
(set-max-undo-history 'forever))))
(define wx-text-editor-canvas% (define wx-text-editor-canvas%
(class100* wx-editor-canvas% (wx-text-editor-canvas<%>) (mred proxy control parent style) (class100* wx-editor-canvas% (wx-text-editor-canvas<%>) (mred proxy control parent style)

View File

@ -605,7 +605,7 @@
(make-fixed-width c message-editor #t return-bitmap) (make-fixed-width c message-editor #t return-bitmap)
(send message-editor set-paste-text-only #t) (send message-editor set-paste-text-only #t)
(send message-editor set-max-undo-history 5000) ;; Many undos! (send message-editor set-max-undo-history 'forever)
(send c set-editor message-editor) (send c set-editor message-editor)
(activate-spelling message-editor) (activate-spelling message-editor)

View File

@ -155,6 +155,7 @@
;;;;;; Undo tests ;;;;;; Undo tests
(define e (make-object text%)) (define e (make-object text%))
(send e set-max-undo-history 1024)
(stv e insert "Hello") (stv e insert "Hello")
(st #t e is-modified?) (st #t e is-modified?)
@ -173,9 +174,10 @@
(stv e redo) (stv e redo)
(st #f e is-modified?) (st #f e is-modified?)
(stv e undo) (stv e undo)
(st "" e get-text)
(stv e set-modified #f) (stv e set-modified #f)
(st #f e is-modified?) (st #f e is-modified?)
(stv e redo) (stv e redo) ; somehow cancel's redo action to set modified to #f...
(st #t e is-modified?) (st #t e is-modified?)
(st "Hello" e get-text) (st "Hello" e get-text)
(define undone? #f) (define undone? #f)
@ -435,5 +437,43 @@
;; ---------------------------------------- ;; ----------------------------------------
;; More undo tests, checking mainly that internal undo array grows
;; correctly
(define (test-undos local-undo?)
(define e (new text%))
(send e insert (make-string 1024 #\x))
(send e set-max-undo-history 10240)
(send e set-position 0)
(let loop ([n 1024])
(unless (zero? n)
(send e set-position (add1 (send e get-start-position)))
(send e delete)
(send e insert #\y)
(when local-undo?
(send e undo)
(send e redo))
(loop (sub1 n))))
(st (make-string 1024 #\y) e get-text 0 'eof)
(let loop ([n 1023])
(unless (zero? n)
(send e undo)
(send e undo)
(loop (sub1 n))))
(st (string-append "y" (make-string 1023 #\x) )
e get-text 0 'eof))
(test-undos #f)
(test-undos #t)
;; ----------------------------------------
(report-errs) (report-errs)

View File

@ -1,4 +1,9 @@
Version 300.3
Default max undo history for an editor<%> is 0; use
set-max-undo-history to enable undo
Added |MrEd:emacsUndo| low-level preference
Version 300.1 Version 300.1
Disabled menu-item shortcuts stay effective (to just beep) Disabled menu-item shortcuts stay effective (to just beep)

View File

@ -87,6 +87,34 @@ void wxChangeRecord::DropSetUnmodified(void)
{ {
} }
Bool wxChangeRecord::IsComposite()
{
return FALSE;
}
wxChangeRecordId *wxChangeRecord::GetId()
{
return NULL;
}
int wxChangeRecord::GetParity()
{
return 0;
}
wxChangeRecord *wxChangeRecord::Inverse()
{
return NULL;
}
#if CGREC_DEBUG
char *wxChangeRecord::GetName()
{
return "???";
}
#endif
wxSchemeModifyRecord::wxSchemeModifyRecord(void *proc) wxSchemeModifyRecord::wxSchemeModifyRecord(void *proc)
{ {
p = proc; p = proc;
@ -99,6 +127,14 @@ Bool wxSchemeModifyRecord::Undo(wxMediaBuffer *)
return wxsSchemeUndo(p); return wxsSchemeUndo(p);
} }
#if CGREC_DEBUG
char *wxSchemeModifyRecord::GetName()
{
return "scheme-modify";
}
#endif
wxUnmodifyRecord::wxUnmodifyRecord(void) wxUnmodifyRecord::wxUnmodifyRecord(void)
{ {
ok = 1; ok = 1;
@ -116,6 +152,14 @@ void wxUnmodifyRecord::DropSetUnmodified(void)
ok = 0; ok = 0;
} }
#if CGREC_DEBUG
char *wxUnmodifyRecord::GetName()
{
return "unmodify";
}
#endif
wxInsertRecord::wxInsertRecord(long position, long length, Bool cont, long ss, long es) wxInsertRecord::wxInsertRecord(long position, long length, Bool cont, long ss, long es)
{ {
start = position; start = position;
@ -137,6 +181,13 @@ Bool wxInsertRecord::Undo(wxMediaBuffer *buffer)
return continued; return continued;
} }
#if CGREC_DEBUG
char *wxInsertRecord::GetName()
{
return "insert";
}
#endif
wxInsertSnipRecord::wxInsertSnipRecord(wxSnip *thesnip, Bool cont) wxInsertSnipRecord::wxInsertSnipRecord(wxSnip *thesnip, Bool cont)
{ {
snip = thesnip; snip = thesnip;
@ -155,6 +206,13 @@ Bool wxInsertSnipRecord::Undo(wxMediaBuffer *buffer)
return continued; return continued;
} }
#if CGREC_DEBUG
char *wxInsertSnipRecord::GetName()
{
return "insert-snip";
}
#endif
class DeleteSnipItem /* : public wxObject --- uncomment to GC */ class DeleteSnipItem /* : public wxObject --- uncomment to GC */
{ {
public: public:
@ -237,6 +295,13 @@ Bool wxDeleteSnipRecord::Undo(wxMediaBuffer *buffer)
return continued; return continued;
} }
#if CGREC_DEBUG
char *wxDeleteSnipRecord::GetName()
{
return "delete-snip";
}
#endif
wxDeleteRecord::wxDeleteRecord(long startpos, long endpos, Bool cont, long ss, long es) wxDeleteRecord::wxDeleteRecord(long startpos, long endpos, Bool cont, long ss, long es)
{ {
continued = cont; continued = cont;
@ -322,6 +387,13 @@ Bool wxDeleteRecord::Undo(wxMediaBuffer *buffer)
return continued; return continued;
} }
#if CGREC_DEBUG
char *wxDeleteRecord::GetName()
{
return "delete";
}
#endif
class StyleChange /* : public wxObject */ class StyleChange /* : public wxObject */
{ {
public: public:
@ -390,6 +462,13 @@ Bool wxStyleChangeRecord::Undo(wxMediaBuffer *buffer)
return continued; return continued;
} }
#if CGREC_DEBUG
char *wxStyleChangeRecord::GetName()
{
return "style-change";
}
#endif
class StyleChangeSnip /* : public wxObject */ class StyleChangeSnip /* : public wxObject */
{ {
public: public:
@ -451,6 +530,13 @@ Bool wxStyleChangeSnipRecord::Undo(wxMediaBuffer *buffer)
return continued; return continued;
} }
#if CGREC_DEBUG
char *wxStyleChangeSnipRecord::GetName()
{
return "style-change-snip";
}
#endif
wxMoveSnipRecord::wxMoveSnipRecord(wxSnip *s, double fx, double fy, wxMoveSnipRecord::wxMoveSnipRecord(wxSnip *s, double fx, double fy,
Bool d, Bool cont) Bool d, Bool cont)
{ {
@ -475,6 +561,13 @@ Bool wxMoveSnipRecord::Undo(wxMediaBuffer *buffer)
return continued; return continued;
} }
#if CGREC_DEBUG
char *wxMoveSnipRecord::GetName()
{
return "move-snip";
}
#endif
wxResizeSnipRecord::wxResizeSnipRecord(wxSnip *s, double fx, double fy, wxResizeSnipRecord::wxResizeSnipRecord(wxSnip *s, double fx, double fy,
Bool cont) Bool cont)
{ {
@ -495,3 +588,166 @@ Bool wxResizeSnipRecord::Undo(wxMediaBuffer *buffer)
return continued; return continued;
} }
#if CGREC_DEBUG
char *wxResizeSnipRecord::GetName()
{
return "resize-snip";
}
#endif
wxCompositeRecord::wxCompositeRecord(int _cnt, wxChangeRecordId *_id, int _parity)
{
cnt = _cnt;
seq = new wxChangeRecord*[cnt];
id = _id;
parity = _parity;
if (!id) {
id = new wxChangeRecordId;
}
if (parity)
id->positive = this;
else
id->negative = this;
}
wxCompositeRecord::~wxCompositeRecord()
{
int i = cnt;
wxChangeRecord *cr;
while (i--) {
cr = seq[i];
DELETE_OBJ cr;
}
cnt = 0;
seq = NULL;
if (id) {
if (parity)
id->positive = NULL;
else
id->negative = NULL;
id = NULL;
}
}
Bool wxCompositeRecord::Undo(wxMediaBuffer *media)
{
int i = cnt;
wxChangeRecord *cr;
while (i--) {
cr = seq[i];
cr->Undo(media);
}
return FALSE;
}
void wxCompositeRecord::DropSetUnmodified()
{
int i = cnt;
wxChangeRecord *cr;
while (i--) {
cr = seq[i];
cr->DropSetUnmodified();
}
}
void wxCompositeRecord::AddUndo(int pos, wxChangeRecord *c)
{
seq[pos] = c;
}
Bool wxCompositeRecord::IsComposite()
{
return TRUE;
}
wxChangeRecordId *wxCompositeRecord::GetId()
{
return id;
}
int wxCompositeRecord::GetParity()
{
return parity;
}
wxChangeRecord *wxCompositeRecord::Inverse()
{
return new wxInverseRecord(id, !parity);
}
#if CGREC_DEBUG
char *wxCompositeRecord::GetName()
{
if (cnt == 1) {
wxChangeRecord *cr;
cr = seq[0];
return cr->GetName();
} else
return "composite";
}
#endif
wxInverseRecord::wxInverseRecord(wxChangeRecordId *_id, int _parity)
{
id = _id;
parity = _parity;
}
wxInverseRecord::~wxInverseRecord()
{
/* Avoid double-frees by not doing anything */
}
wxChangeRecord *wxInverseRecord::Get()
{
if (parity)
return id->positive;
else
return id->negative;
}
Bool wxInverseRecord::Undo(wxMediaBuffer *media)
{
wxChangeRecord *c;
c = Get();
return c->Undo(media);
}
void wxInverseRecord::DropSetUnmodified()
{
wxChangeRecord *c;
c = Get();
if (c)
c->DropSetUnmodified();
}
wxChangeRecordId *wxInverseRecord::GetId()
{
return id;
}
int wxInverseRecord::GetParity()
{
return parity;
}
wxChangeRecord *wxInverseRecord::Inverse()
{
wxChangeRecord *c;
c = Get();
return c->Inverse();
}
#if CGREC_DEBUG
char *wxInverseRecord::GetName()
{
wxChangeRecord *c;
c = Get();
if (c)
return c->GetName();
else
return "inverse";
}
#endif

View File

@ -1,6 +1,10 @@
class wxcgList; class wxcgList;
#define CGREC_DEBUG 0
class wxChangeRecordId;
class wxChangeRecord class wxChangeRecord
{ {
public: public:
@ -8,6 +12,13 @@ class wxChangeRecord
virtual ~wxChangeRecord(); virtual ~wxChangeRecord();
virtual Bool Undo(wxMediaBuffer *media); virtual Bool Undo(wxMediaBuffer *media);
virtual void DropSetUnmodified(void); virtual void DropSetUnmodified(void);
virtual Bool IsComposite();
virtual wxChangeRecordId *GetId();
virtual int GetParity();
virtual wxChangeRecord *Inverse();
#if CGREC_DEBUG
virtual char *GetName();
#endif
}; };
class wxSchemeModifyRecord : public wxChangeRecord class wxSchemeModifyRecord : public wxChangeRecord
@ -16,6 +27,9 @@ class wxSchemeModifyRecord : public wxChangeRecord
public: public:
wxSchemeModifyRecord(void *p); wxSchemeModifyRecord(void *p);
Bool Undo(wxMediaBuffer *media); Bool Undo(wxMediaBuffer *media);
#if CGREC_DEBUG
char *GetName();
#endif
}; };
class wxUnmodifyRecord : public wxChangeRecord class wxUnmodifyRecord : public wxChangeRecord
@ -25,6 +39,9 @@ class wxUnmodifyRecord : public wxChangeRecord
wxUnmodifyRecord(void); wxUnmodifyRecord(void);
Bool Undo(wxMediaBuffer *media); Bool Undo(wxMediaBuffer *media);
void DropSetUnmodified(void); void DropSetUnmodified(void);
#if CGREC_DEBUG
char *GetName();
#endif
}; };
class wxInsertRecord : public wxChangeRecord class wxInsertRecord : public wxChangeRecord
@ -33,11 +50,12 @@ class wxInsertRecord : public wxChangeRecord
long start, end; long start, end;
long startsel, endsel; long startsel, endsel;
Bool continued; Bool continued;
public: public:
wxInsertRecord(long position, long length, Bool cont, long startsel, long endsel); wxInsertRecord(long position, long length, Bool cont, long startsel, long endsel);
Bool Undo(wxMediaBuffer *media); Bool Undo(wxMediaBuffer *media);
#if CGREC_DEBUG
char *GetName();
#endif
}; };
class wxInsertSnipRecord : public wxChangeRecord class wxInsertSnipRecord : public wxChangeRecord
@ -45,11 +63,12 @@ class wxInsertSnipRecord : public wxChangeRecord
private: private:
wxSnip *snip; wxSnip *snip;
Bool continued; Bool continued;
public: public:
wxInsertSnipRecord(wxSnip *s, Bool cont); wxInsertSnipRecord(wxSnip *s, Bool cont);
Bool Undo(wxMediaBuffer *media); Bool Undo(wxMediaBuffer *media);
#if CGREC_DEBUG
char *GetName();
#endif
}; };
class wxDeleteRecord : public wxChangeRecord class wxDeleteRecord : public wxChangeRecord
@ -70,6 +89,10 @@ class wxDeleteRecord : public wxChangeRecord
void AddClickback(wxClickback *); void AddClickback(wxClickback *);
Bool Undo(wxMediaBuffer *media); Bool Undo(wxMediaBuffer *media);
#if CGREC_DEBUG
char *GetName();
#endif
}; };
class wxDeleteSnipRecord : public wxChangeRecord class wxDeleteSnipRecord : public wxChangeRecord
@ -87,6 +110,10 @@ class wxDeleteSnipRecord : public wxChangeRecord
void InsertSnip(wxSnip *, wxSnip *, double, double); void InsertSnip(wxSnip *, wxSnip *, double, double);
Bool Undo(wxMediaBuffer *media); Bool Undo(wxMediaBuffer *media);
#if CGREC_DEBUG
char *GetName();
#endif
}; };
class wxStyleChangeRecord : public wxChangeRecord class wxStyleChangeRecord : public wxChangeRecord
@ -103,6 +130,10 @@ class wxStyleChangeRecord : public wxChangeRecord
void AddStyleChange(long start, long end, wxStyle *style); void AddStyleChange(long start, long end, wxStyle *style);
Bool Undo(wxMediaBuffer *media); Bool Undo(wxMediaBuffer *media);
#if CGREC_DEBUG
char *GetName();
#endif
}; };
class wxStyleChangeSnipRecord : public wxChangeRecord class wxStyleChangeSnipRecord : public wxChangeRecord
@ -117,6 +148,10 @@ class wxStyleChangeSnipRecord : public wxChangeRecord
void AddStyleChange(wxSnip *, wxStyle *style); void AddStyleChange(wxSnip *, wxStyle *style);
Bool Undo(wxMediaBuffer *media); Bool Undo(wxMediaBuffer *media);
#if CGREC_DEBUG
char *GetName();
#endif
}; };
class wxMoveSnipRecord : public wxChangeRecord class wxMoveSnipRecord : public wxChangeRecord
@ -129,6 +164,9 @@ class wxMoveSnipRecord : public wxChangeRecord
public: public:
wxMoveSnipRecord(wxSnip *snip, double x, double y, Bool delta, Bool cont); wxMoveSnipRecord(wxSnip *snip, double x, double y, Bool delta, Bool cont);
Bool Undo(wxMediaBuffer *media); Bool Undo(wxMediaBuffer *media);
#if CGREC_DEBUG
char *GetName();
#endif
}; };
class wxResizeSnipRecord : public wxChangeRecord class wxResizeSnipRecord : public wxChangeRecord
@ -140,5 +178,51 @@ class wxResizeSnipRecord : public wxChangeRecord
public: public:
wxResizeSnipRecord(wxSnip *snip, double x, double y, Bool cont); wxResizeSnipRecord(wxSnip *snip, double x, double y, Bool cont);
Bool Undo(wxMediaBuffer *media); Bool Undo(wxMediaBuffer *media);
#if CGREC_DEBUG
char *GetName();
#endif
}; };
class wxChangeRecordId {
public:
wxChangeRecord *positive, *negative;
};
class wxCompositeRecord : public wxChangeRecord
{
int cnt;
int parity;
wxChangeRecordId *id;
wxChangeRecord **seq;
public:
wxCompositeRecord(int cnt, wxChangeRecordId *, int parity);
~wxCompositeRecord();
Bool Undo(wxMediaBuffer *media);
void DropSetUnmodified(void);
void AddUndo(int pos, wxChangeRecord *c);
Bool IsComposite();
wxChangeRecordId *GetId();
int GetParity();
wxChangeRecord *Inverse();
#if CGREC_DEBUG
char *GetName();
#endif
};
class wxInverseRecord : public wxChangeRecord
{
int parity;
wxChangeRecordId *id;
wxChangeRecord *Get();
public:
wxInverseRecord(wxChangeRecordId *, int parity);
~wxInverseRecord();
Bool Undo(wxMediaBuffer *media);
void DropSetUnmodified(void);
wxChangeRecordId *GetId();
int GetParity();
wxChangeRecord *Inverse();
#if CGREC_DEBUG
char *GetName();
#endif
};

View File

@ -49,8 +49,6 @@
#include <string.h> #include <string.h>
#include "scheme.h" #include "scheme.h"
#define NUM_MAX_UNDOS 256
#define DELETE_CLIP_LIST_CONTENT 0 #define DELETE_CLIP_LIST_CONTENT 0
#if ALLOW_X_STYLE_SELECTION #if ALLOW_X_STYLE_SELECTION
@ -107,6 +105,9 @@ extern Scheme_Object *objscheme_bundle_wxMediaBuffer(wxMediaBuffer*);
/******************************************************************/ /******************************************************************/
static int emacs_style_undo = -1;
extern int wxGetBoolPreference(const char *name, int *res);
#ifndef EACH_BUFFER_OWN_OFFSCREEN #ifndef EACH_BUFFER_OWN_OFFSCREEN
static int bcounter = 0; static int bcounter = 0;
#endif #endif
@ -114,8 +115,6 @@ static int bcounter = 0;
wxMediaBuffer::wxMediaBuffer() wxMediaBuffer::wxMediaBuffer()
: wxObject(WXGC_NO_CLEANUP) : wxObject(WXGC_NO_CLEANUP)
{ {
wxChangeRecord **crpa;
map = new wxKeymap(); map = new wxKeymap();
// AddBufferFunctions(map); // AddBufferFunctions(map);
@ -127,13 +126,13 @@ wxMediaBuffer::wxMediaBuffer()
filename = NULL; filename = NULL;
undomode = redomode = interceptmode = FALSE; undomode = redomode = interceptmode = FALSE;
maxUndos = NUM_MAX_UNDOS; maxUndos = 0;
crpa = MALLOC_CRP(maxUndos);
changes = crpa; if (emacs_style_undo == -1) {
changes_start = changes_end = 0; if (!wxGetBoolPreference("emacsUndo", &emacs_style_undo)) {
crpa = MALLOC_CRP(maxUndos); emacs_style_undo = 0;
redochanges = crpa; }
redochanges_start = redochanges_end = 0; }
customCursor = NULL; customCursor = NULL;
@ -1467,7 +1466,7 @@ void wxMediaBuffer::Undo(void)
if (!undomode && !redomode) { if (!undomode && !redomode) {
undomode = TRUE; undomode = TRUE;
PerformUndos(changes, FALSE); PerformUndos(FALSE);
undomode = FALSE; undomode = FALSE;
} }
@ -1478,7 +1477,7 @@ void wxMediaBuffer::Redo(void)
if (!undomode && !redomode) { if (!undomode && !redomode) {
redomode = TRUE; redomode = TRUE;
PerformUndos(redochanges, TRUE); PerformUndos(TRUE);
redomode = FALSE; redomode = FALSE;
} }
@ -1486,12 +1485,11 @@ void wxMediaBuffer::Redo(void)
#define delete_cgrec(x) DELETE_OBJ (x) #define delete_cgrec(x) DELETE_OBJ (x)
static void wxmeClearUndos(wxChangeRecord **changes, int start, int end, static void wxmeClearUndos(wxChangeRecord **changes, int start, int end, int size)
int maxUndos)
{ {
int i; int i;
for (i = start; i != end; i = (i + 1) % maxUndos) { for (i = start; i != end; i = (i + 1) % size) {
delete_cgrec(changes[i]); delete_cgrec(changes[i]);
changes[i] = NULL; changes[i] = NULL;
} }
@ -1502,14 +1500,32 @@ void wxMediaBuffer::AddUndo(wxChangeRecord *rec)
if (interceptmode) if (interceptmode)
intercepted->Append((wxObject *)rec); intercepted->Append((wxObject *)rec);
else if (undomode) else if (undomode)
AppendUndo(rec, redochanges, TRUE); AppendUndo(rec, TRUE);
else if (!noundomode) { else if (!noundomode) {
if (!redomode) { if (!redomode) {
wxmeClearUndos(redochanges, redochanges_start, if (emacs_style_undo) {
redochanges_end, maxUndos); if (redochanges_start != redochanges_end) {
redochanges_start = redochanges_end = 0; int e = redochanges_end;
wxChangeRecord *cr;
while (redochanges_start != e) {
e = (e - 1 + redochanges_size) % redochanges_size;
cr = redochanges[e];
AppendUndo(cr->Inverse(), FALSE);
}
while (redochanges_start != redochanges_end) {
AppendUndo(redochanges[redochanges_start], FALSE);
redochanges[redochanges_start] = NULL;
redochanges_start = (redochanges_start + 1) % redochanges_size;
}
redochanges_start = 0;
redochanges_end = 0;
}
} else {
wxmeClearUndos(redochanges, redochanges_start, redochanges_end, redochanges_size);
redochanges_start = redochanges_end = 0;
}
} }
AppendUndo(rec, changes, FALSE); AppendUndo(rec, FALSE);
} else } else
delete_cgrec(rec); delete_cgrec(rec);
} }
@ -1521,59 +1537,102 @@ void wxMediaBuffer::AddSchemeUndo(void *proc)
AddUndo(modrec); AddUndo(modrec);
} }
void wxMediaBuffer::AppendUndo(wxChangeRecord *rec, wxChangeRecord **changes, void wxMediaBuffer::AppendUndo(wxChangeRecord *rec, Bool redos)
Bool redos)
{ {
if (maxUndos) { if (maxUndos) {
int start, end; wxChangeRecord **c;
int start, end, size;
if (redos) { if (redos) {
start = redochanges_start; start = redochanges_start;
end = redochanges_end; end = redochanges_end;
size = redochanges_size;
c = redochanges;
} else { } else {
start = changes_start; start = changes_start;
end = changes_end; end = changes_end;
size = changes_size;
c = changes;
} }
changes[end] = rec; if (!size) {
end = (end + 1) % maxUndos; size = 128; /* Initial undo size */
if (size > maxUndos)
size = maxUndos;
c = MALLOC_CRP(size);
}
c[end] = rec;
end = (end + 1) % size;
if (end == start) { if (end == start) {
delete_cgrec(changes[start]); if ((size < maxUndos) || emacs_style_undo) {
changes[start] = NULL; /* Make more room */
start = (start + 1) % maxUndos; int s, i, j;
wxChangeRecord **naya;
s = (size * 2);
if (s > maxUndos)
s = maxUndos;
naya = MALLOC_CRP(s);
for (j = 0, i = start;
(j < size);
j++, i = (i + 1) % size) {
naya[j] = c[i];
}
size = s;
c = naya;
start = 0;
end = j;
} else {
/* No room to grow, so drop an undo record */
delete_cgrec(c[start]);
c[start] = NULL;
start = (start + 1) % size;
}
} }
if (redos) { if (redos) {
redochanges_start = start; redochanges_start = start;
redochanges_end = end; redochanges_end = end;
redochanges_size = size;
redochanges = c;
} else { } else {
changes_start = start; changes_start = start;
changes_end = end; changes_end = end;
changes_size = size;
changes = c;
} }
} else } else
delete_cgrec(rec); delete_cgrec(rec);
} }
void wxMediaBuffer::PerformUndos(wxChangeRecord **changes, Bool redos) void wxMediaBuffer::PerformUndos(Bool redos)
{ {
wxChangeRecord **c;
wxChangeRecord *rec; wxChangeRecord *rec;
wxChangeRecordId *id = NULL;
int parity = 0;
Bool cont; Bool cont;
int start, end; int start, end, size;
BeginEditSequence(); BeginEditSequence();
if (redos) { if (redos) {
start = redochanges_start; start = redochanges_start;
end = redochanges_end; end = redochanges_end;
size = redochanges_size;
c = redochanges;
} else { } else {
start = changes_start; start = changes_start;
end = changes_end; end = changes_end;
size = changes_size;
c = changes;
} }
while (start != end) { while (start != end) {
end = (end - 1 + maxUndos) % maxUndos; end = (end - 1 + size) % size;
rec = changes[end]; rec = c[end];
changes[end] = NULL; c[end] = NULL;
if (redos) { if (redos) {
redochanges_start = start; redochanges_start = start;
@ -1583,13 +1642,55 @@ void wxMediaBuffer::PerformUndos(wxChangeRecord **changes, Bool redos)
changes_end = end; changes_end = end;
} }
if (emacs_style_undo) {
id = rec->GetId();
parity = rec->GetParity();
}
cont = rec->Undo(this); cont = rec->Undo(this);
delete_cgrec(rec);
if (!cont) if (!cont)
break; break;
} }
EndEditSequence(); EndEditSequence();
if (emacs_style_undo && !redos) {
/* Combine all new steps into one undo record, and
set/generate id */
start = redochanges_start;
end = redochanges_end;
size = redochanges_size;
c = redochanges;
if (start != end) {
wxChangeRecord *cr;
int e, cnt = 0;
for (e = end; start != e; ) {
e = (e - 1 + size) % size;
cr = c[e];
if (cr->IsComposite())
break;
else
cnt++;
}
if (cnt > 0) {
wxCompositeRecord *cu;
int i;
cu = new wxCompositeRecord(cnt, id, !parity);
for (i = 0; i < cnt; i++) {
e = (end - cnt + i + size) % size;
cu->AddUndo(i, c[e]);
c[e] = NULL;
}
e = (end - cnt + size) % size;
c[e] = cu;
end = (e + 1) % size;
redochanges_end = end;
}
}
}
} }
void wxMediaBuffer::PerformUndoList(wxList *changes) void wxMediaBuffer::PerformUndoList(wxList *changes)
@ -1613,45 +1714,30 @@ void wxMediaBuffer::PerformUndoList(wxList *changes)
void wxMediaBuffer::ClearUndos() void wxMediaBuffer::ClearUndos()
{ {
wxmeClearUndos(changes, changes_start, changes_end, maxUndos); wxmeClearUndos(changes, changes_start, changes_end, changes_size);
changes_start = changes_end = 0; changes_start = changes_end = 0;
wxmeClearUndos(redochanges, redochanges_start, redochanges_end, maxUndos); wxmeClearUndos(redochanges, redochanges_start, redochanges_end, redochanges_size);
redochanges_start = redochanges_end = 0; redochanges_start = redochanges_end = 0;
} }
void wxMediaBuffer::SetMaxUndoHistory(int v) void wxMediaBuffer::SetMaxUndoHistory(int v)
{ {
wxChangeRecord **naya; if (v < 0)
int i, j; v = 0xfffFFFF;
if (undomode || redomode || (v == maxUndos)) if (undomode || redomode || (v == maxUndos))
return; return;
naya = MALLOC_CRP(v); if (!v) {
for (j = 0, i = changes_start; ClearUndos();
(i != changes_end) && (j < v); changes = NULL;
j++, i = (i + 1) % maxUndos) { redochanges = NULL;
naya[j] = changes[i]; changes_size = 0;
redochanges_size = 0;
} }
for (; i != changes_end; i = (i + 1) % maxUndos) {
delete_cgrec(changes[i]);
}
changes = naya;
changes_start = 0;
changes_end = v ? (j % v) : 0;
naya = MALLOC_CRP(v); /* Should we bother downsizing if maxUndos gets smaller but stays
for (j = 0, i = redochanges_start; non-0? */
(i != redochanges_end) && (j < v);
j++, i = (i + 1) % maxUndos) {
naya[j] = redochanges[i];
}
for (; i != redochanges_end; i = (i + 1) % maxUndos) {
delete_cgrec(redochanges[i]);
}
redochanges = naya;
redochanges_start = 0;
redochanges_end = v ? (j % v) : v;
maxUndos = v; maxUndos = v;
} }
@ -2369,13 +2455,13 @@ void wxMediaBuffer::SetModified(Bool mod)
num_parts_modified = 0; num_parts_modified = 0;
for (i = changes_end; i != changes_start; ) { for (i = changes_end; i != changes_start; ) {
wxChangeRecord *cr; wxChangeRecord *cr;
i = (i - 1 + maxUndos) % maxUndos; i = (i - 1 + changes_size) % changes_size;
cr = changes[i]; cr = changes[i];
cr->DropSetUnmodified(); cr->DropSetUnmodified();
} }
for (i = redochanges_end; i != redochanges_start; ) { for (i = redochanges_end; i != redochanges_start; ) {
wxChangeRecord *cr; wxChangeRecord *cr;
i = (i - 1 + maxUndos) % maxUndos; i = (i - 1 + redochanges_size) % redochanges_size;
cr = redochanges[i]; cr = redochanges[i];
cr->DropSetUnmodified(); cr->DropSetUnmodified();
} }

View File

@ -97,9 +97,10 @@ class wxMediaBuffer : public wxObject
int maxUndos; int maxUndos;
wxChangeRecord **changes; wxChangeRecord **changes;
int changes_start, changes_end; int changes_start, changes_end, changes_size;
wxChangeRecord **redochanges; wxChangeRecord **redochanges;
int redochanges_start, redochanges_end; int redochanges_start, redochanges_end, redochanges_size;
wxChangeRecord **savedchanges; /* for Emacs-style undo */
wxList *intercepted; wxList *intercepted;
wxCursor *customCursor; wxCursor *customCursor;
@ -124,9 +125,9 @@ class wxMediaBuffer : public wxObject
virtual void InsertPasteSnip(wxSnip *snip, wxBufferData *) = 0; virtual void InsertPasteSnip(wxSnip *snip, wxBufferData *) = 0;
virtual void InsertPasteString(wxchar *str) = 0; virtual void InsertPasteString(wxchar *str) = 0;
void PerformUndos(wxChangeRecord **, Bool redos); void PerformUndos(Bool redos);
void PerformUndoList(wxList *); void PerformUndoList(wxList *);
void AppendUndo(wxChangeRecord *, wxChangeRecord **, Bool redo); void AppendUndo(wxChangeRecord *, Bool redo);
Bool DoOwnCaret(Bool ownit); Bool DoOwnCaret(Bool ownit);
Bool DoSetCaretOwner(wxSnip *, int); Bool DoSetCaretOwner(wxSnip *, int);

View File

@ -1258,13 +1258,13 @@ static Scheme_Object *os_wxMediaBufferSetMaxUndoHistory(int n, Scheme_Object *p
WXS_USE_ARGUMENT(n) WXS_USE_ARGUMENT(p) WXS_USE_ARGUMENT(n) WXS_USE_ARGUMENT(p)
REMEMBER_VAR_STACK(); REMEMBER_VAR_STACK();
objscheme_check_valid(os_wxMediaBuffer_class, "set-max-undo-history in editor<%>", n, p); objscheme_check_valid(os_wxMediaBuffer_class, "set-max-undo-history in editor<%>", n, p);
int x0; long x0;
SETUP_VAR_STACK_REMEMBERED(1); SETUP_VAR_STACK_REMEMBERED(1);
VAR_STACK_PUSH(0, p); VAR_STACK_PUSH(0, p);
x0 = WITH_VAR_STACK(objscheme_unbundle_integer_in(p[POFFSET+0], 0, 100000, "set-max-undo-history in editor<%>")); x0 = WITH_VAR_STACK(objscheme_unbundle_nonnegative_symbol_integer(p[POFFSET+0], "forever", "set-max-undo-history in editor<%>"));
WITH_VAR_STACK(((wxMediaBuffer *)((Scheme_Class_Object *)p[0])->primdata)->SetMaxUndoHistory(x0)); WITH_VAR_STACK(((wxMediaBuffer *)((Scheme_Class_Object *)p[0])->primdata)->SetMaxUndoHistory(x0));

View File

@ -144,7 +144,7 @@ static void NoInsertFile(wxMediaBuffer *)
@ "add-undo" : void AddSchemeUndo(UNKNOWN_OBJ//ubUndoer////push); : : /CHECKUNDOER @ "add-undo" : void AddSchemeUndo(UNKNOWN_OBJ//ubUndoer////push); : : /CHECKUNDOER
@ "set-max-undo-history" : void SetMaxUndoHistory(rint[0|100000]); @ "set-max-undo-history" : void SetMaxUndoHistory(nnls[forever]);
@ "get-max-undo-history" : int GetMaxUndoHistory(); @ "get-max-undo-history" : int GetMaxUndoHistory();
@ "do-edit-operation" : void DoEdit(SYM[editOp],bool=TRUE,ExactLong=0); @ "do-edit-operation" : void DoEdit(SYM[editOp],bool=TRUE,ExactLong=0);

View File

@ -724,6 +724,7 @@ scheme_init_port_fun(Scheme_Env *env)
void scheme_init_port_fun_config(void) void scheme_init_port_fun_config(void)
{ {
scheme_set_root_param(MZCONFIG_LOAD_DIRECTORY, scheme_false); scheme_set_root_param(MZCONFIG_LOAD_DIRECTORY, scheme_false);
scheme_set_root_param(MZCONFIG_WRITE_DIRECTORY, scheme_false);
scheme_set_root_param(MZCONFIG_USE_COMPILED_KIND, scheme_set_root_param(MZCONFIG_USE_COMPILED_KIND,
scheme_make_immutable_pair(scheme_make_path("compiled"), scheme_make_immutable_pair(scheme_make_path("compiled"),
scheme_null)); scheme_null));