version 1.6, 2002/02/21 17:36:12 |
version 1.7, 2002/02/26 00:45:45 |
|
|
|
|
#include <sys/queue.h> |
#include <sys/queue.h> |
|
|
#define MAX_LIST_RECORDS 32 |
|
#define MAX_FREE_RECORDS 32 |
#define MAX_FREE_RECORDS 32 |
|
|
/* |
/* |
* Local variables |
* Local variables |
*/ |
*/ |
static struct undo_list undo_list; |
static LIST_HEAD(, undo_rec) undo_free; |
static int undo_list_num; |
static int undo_free_num; |
static struct undo_list undo_free; |
|
static int undo_free_num; |
|
|
|
/* |
/* |
* Global variables |
* Global variables |
|
|
static int find_offset(LINE *, int); |
static int find_offset(LINE *, int); |
static int find_linep(int, LINE **, int *); |
static int find_linep(int, LINE **, int *); |
static struct undo_rec *new_undo_record(void); |
static struct undo_rec *new_undo_record(void); |
static void free_undo_record(struct undo_rec *); |
|
static int drop_oldest_undo_record(void); |
static int drop_oldest_undo_record(void); |
|
|
static int |
static int |
|
|
{ |
{ |
struct undo_rec *rec; |
struct undo_rec *rec; |
|
|
while (undo_list_num >= MAX_LIST_RECORDS) { |
|
drop_oldest_undo_record(); |
|
undo_list_num--; |
|
} |
|
undo_list_num++; |
|
rec = LIST_FIRST(&undo_free); |
rec = LIST_FIRST(&undo_free); |
if (rec != NULL) |
if (rec != NULL) |
LIST_REMOVE(rec, next); /* Remove it from the free-list */ |
LIST_REMOVE(rec, next); /* Remove it from the free-list */ |
|
|
return rec; |
return rec; |
} |
} |
|
|
static void |
void |
free_undo_record(struct undo_rec *rec) |
free_undo_record(struct undo_rec *rec) |
{ |
{ |
if (rec->content != NULL) { |
if (rec->content != NULL) { |
|
|
undo_init(void) |
undo_init(void) |
{ |
{ |
LIST_INIT(&undo_free); |
LIST_INIT(&undo_free); |
LIST_INIT(&undo_list); |
|
|
|
return TRUE; |
return TRUE; |
} |
} |
|
|
return TRUE; |
return TRUE; |
rec = new_undo_record(); |
rec = new_undo_record(); |
rec->pos = find_offset(lp, offset); |
rec->pos = find_offset(lp, offset); |
rec->buf = curbp; |
|
rec->type = type; |
rec->type = type; |
rec->content = content; |
rec->content = content; |
rec->region.r_linep = lp; |
rec->region.r_linep = lp; |
rec->region.r_offset = offset; |
rec->region.r_offset = offset; |
rec->region.r_size = size; |
rec->region.r_size = size; |
|
|
LIST_INSERT_HEAD(&undo_list, rec, next); |
LIST_INSERT_HEAD(&curbp->b_undo, rec, next); |
|
|
return TRUE; |
return TRUE; |
} |
} |
|
|
return TRUE; |
return TRUE; |
|
|
rec = new_undo_record(); |
rec = new_undo_record(); |
rec->buf = curbp; |
|
rec->type = BOUNDARY; |
rec->type = BOUNDARY; |
|
|
LIST_INSERT_HEAD(&undo_list, rec, next); |
LIST_INSERT_HEAD(&curbp->b_undo, rec, next); |
|
|
return TRUE; |
return TRUE; |
} |
} |
|
|
/* |
/* |
* We try to reuse the last undo record to `compress' things. |
* We try to reuse the last undo record to `compress' things. |
*/ |
*/ |
rec = LIST_FIRST(&undo_list); |
rec = LIST_FIRST(&curbp->b_undo); |
if ((rec != NULL) && |
if ((rec != NULL) && |
(rec->type == INSERT) && |
(rec->type == INSERT) && |
(rec->buf == curbp) && |
|
(rec->region.r_linep == lp)) { |
(rec->region.r_linep == lp)) { |
int dist; |
int dist; |
|
|
|
|
*/ |
*/ |
rec = new_undo_record(); |
rec = new_undo_record(); |
rec->pos = find_offset(lp, offset); |
rec->pos = find_offset(lp, offset); |
rec->buf = curbp; |
|
rec->type = INSERT; |
rec->type = INSERT; |
memmove(&rec->region, ®, sizeof(REGION)); |
memmove(&rec->region, ®, sizeof(REGION)); |
rec->content = NULL; |
rec->content = NULL; |
LIST_INSERT_HEAD(&undo_list, rec, next); |
LIST_INSERT_HEAD(&curbp->b_undo, rec, next); |
|
|
return TRUE; |
return TRUE; |
} |
} |
|
|
/* |
/* |
* Again, try to reuse last undo record, if we can |
* Again, try to reuse last undo record, if we can |
*/ |
*/ |
rec = LIST_FIRST(&undo_list); |
rec = LIST_FIRST(&curbp->b_undo); |
if (!skip && |
if (!skip && |
(rec != NULL) && |
(rec != NULL) && |
(rec->type == DELETE) && |
(rec->type == DELETE) && |
(rec->buf == curbp) && |
|
(rec->region.r_linep == reg.r_linep)) { |
(rec->region.r_linep == reg.r_linep)) { |
char *newbuf; |
char *newbuf; |
int newlen; |
int newlen; |
|
|
rec = new_undo_record(); |
rec = new_undo_record(); |
rec->pos = pos; |
rec->pos = pos; |
|
|
rec->buf = curbp; |
|
rec->type = DELETE; |
rec->type = DELETE; |
memmove(&rec->region, ®, sizeof(REGION)); |
memmove(&rec->region, ®, sizeof(REGION)); |
do { |
do { |
|
|
|
|
region_get_data(®, rec->content, reg.r_size); |
region_get_data(®, rec->content, reg.r_size); |
|
|
LIST_INSERT_HEAD(&undo_list, rec, next); |
LIST_INSERT_HEAD(&curbp->b_undo, rec, next); |
|
|
return TRUE; |
return TRUE; |
} |
} |
|
|
|
|
rec = new_undo_record(); |
rec = new_undo_record(); |
rec->pos = find_offset(lp, offset); |
rec->pos = find_offset(lp, offset); |
rec->buf = curbp; |
|
rec->type = CHANGE; |
rec->type = CHANGE; |
memmove(&rec->region, ®, sizeof reg); |
memmove(&rec->region, ®, sizeof reg); |
|
|
|
|
|
|
region_get_data(®, rec->content, size); |
region_get_data(®, rec->content, size); |
|
|
LIST_INSERT_HEAD(&undo_list, rec, next); |
LIST_INSERT_HEAD(&curbp->b_undo, rec, next); |
|
|
return TRUE; |
return TRUE; |
} |
} |
|
|
undoaction++; |
undoaction++; |
|
|
while (n > 0) { |
while (n > 0) { |
rec = LIST_FIRST(&undo_list); |
rec = LIST_FIRST(&curbp->b_undo); |
if (rec == NULL) { |
if (rec == NULL) { |
ewprintf("Nothing to undo!"); |
ewprintf("Nothing to undo!"); |
return FALSE; |
return FALSE; |
} |
} |
if (rec->buf != curbp) |
|
popbuf(rec->buf); |
|
|
|
LIST_REMOVE(rec, next); |
LIST_REMOVE(rec, next); |
if (rec->type == BOUNDARY) { |
if (rec->type == BOUNDARY) { |
continue; |
continue; |