version 1.24, 2003/12/15 00:00:12 |
version 1.25, 2005/04/03 02:09:28 |
|
|
/* $OpenBSD$ */ |
/* $OpenBSD$ */ |
/* |
/* |
* Copyright (c) 2002 Vincent Labrecque |
* Copyright (c) 2002 Vincent Labrecque <vincent@openbsd.org> |
* All rights reserved. |
* All rights reserved. |
* |
* |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
|
|
* Since lines can be deleted while they are referenced by undo record, we |
* Since lines can be deleted while they are referenced by undo record, we |
* need to have an absolute dot to have something reliable. |
* need to have an absolute dot to have something reliable. |
*/ |
*/ |
|
|
static int |
static int |
find_dot(LINE *lp, int off) |
find_dot(LINE *lp, int off) |
{ |
{ |
int count = 0; |
int count = 0; |
LINE *p; |
LINE *p; |
|
|
for (p = curbp->b_linep; p != lp; p = lforw(p)) { |
for (p = curbp->b_linep; p != lp; p = lforw(p)) { |
if (count != 0) { |
if (count != 0) { |
|
|
LIST_REMOVE(rec, next); /* Remove it from the free-list */ |
LIST_REMOVE(rec, next); /* Remove it from the free-list */ |
undo_free_num--; |
undo_free_num--; |
} else { |
} else { |
if ((rec = malloc(sizeof *rec)) == NULL) |
if ((rec = malloc(sizeof(*rec))) == NULL) |
panic("Out of memory in undo code (record)"); |
panic("Out of memory in undo code (record)"); |
} |
} |
memset(rec, 0, sizeof(struct undo_rec)); |
memset(rec, 0, sizeof(struct undo_rec)); |
|
|
|
|
/* |
/* |
* Drop the oldest undo record in our list. Return 1 if we could remove it, |
* Drop the oldest undo record in our list. Return 1 if we could remove it, |
* 0 if the undo list was empty |
* 0 if the undo list was empty. |
*/ |
*/ |
static int |
static int |
drop_oldest_undo_record(void) |
drop_oldest_undo_record(void) |
|
|
int |
int |
undo_add_insert(LINE *lp, int offset, int size) |
undo_add_insert(LINE *lp, int offset, int size) |
{ |
{ |
REGION reg; |
REGION reg; |
struct undo_rec *rec; |
struct undo_rec *rec; |
int pos; |
int pos; |
|
|
if (undo_disable_flag) |
if (undo_disable_flag) |
return (TRUE); |
return (TRUE); |
|
|
} |
} |
|
|
/* |
/* |
* We couldn't reuse the last undo record, so prepare a new one |
* We couldn't reuse the last undo record, so prepare a new one. |
*/ |
*/ |
rec = new_undo_record(); |
rec = new_undo_record(); |
rec->pos = pos; |
rec->pos = pos; |
|
|
} |
} |
|
|
/* |
/* |
* This of course must be done _before_ the actual deletion is done |
* This of course must be done _before_ the actual deletion is done. |
*/ |
*/ |
int |
int |
undo_add_delete(LINE *lp, int offset, int size) |
undo_add_delete(LINE *lp, int offset, int size) |
{ |
{ |
REGION reg; |
REGION reg; |
struct undo_rec *rec; |
struct undo_rec *rec; |
int pos; |
int pos; |
|
|
if (undo_disable_flag) |
if (undo_disable_flag) |
return (TRUE); |
return (TRUE); |
|
|
} |
} |
|
|
/* |
/* |
* This of course must be called before the change takes place |
* This of course must be called before the change takes place. |
*/ |
*/ |
int |
int |
undo_add_change(LINE *lp, int offset, int size) |
undo_add_change(LINE *lp, int offset, int size) |
|
|
int |
int |
undo_dump(int f, int n) |
undo_dump(int f, int n) |
{ |
{ |
struct undo_rec *rec; |
struct undo_rec *rec; |
BUFFER *bp; |
BUFFER *bp; |
MGWIN *wp; |
MGWIN *wp; |
char buf[4096], tmp[1024]; |
char buf[4096], tmp[1024]; |
int num; |
int num; |
|
|
/* |
/* |
* Prepare the buffer for insertion. |
* Prepare the buffer for insertion. |
|
|
for (rec = LIST_FIRST(&curwp->w_undo); rec != NULL; |
for (rec = LIST_FIRST(&curwp->w_undo); rec != NULL; |
rec = LIST_NEXT(rec, next)) { |
rec = LIST_NEXT(rec, next)) { |
num++; |
num++; |
snprintf(buf, sizeof buf, |
snprintf(buf, sizeof(buf), |
"Record %d =>\t %s at %d ", num, |
"Record %d =>\t %s at %d ", num, |
(rec->type == DELETE) ? "DELETE": |
(rec->type == DELETE) ? "DELETE": |
(rec->type == INSERT) ? "INSERT": |
(rec->type == INSERT) ? "INSERT": |
|
|
rec->pos); |
rec->pos); |
|
|
if (rec->content) { |
if (rec->content) { |
strlcat(buf, "\"", sizeof buf); |
strlcat(buf, "\"", sizeof(buf)); |
snprintf(tmp, sizeof tmp, "%.*s", rec->region.r_size, |
snprintf(tmp, sizeof(tmp), "%.*s", rec->region.r_size, |
rec->content); |
rec->content); |
strlcat(buf, tmp, sizeof buf); |
strlcat(buf, tmp, sizeof(buf)); |
strlcat(buf, "\"", sizeof buf); |
strlcat(buf, "\"", sizeof(buf)); |
} |
} |
snprintf(tmp, sizeof tmp, " [%d]", rec->region.r_size); |
snprintf(tmp, sizeof(tmp), " [%d]", rec->region.r_size); |
strlcat(buf, tmp, sizeof buf); |
strlcat(buf, tmp, sizeof(buf)); |
addlinef(bp, "%s", buf); |
addlinef(bp, "%s", buf); |
} |
} |
return (TRUE); |
return (TRUE); |
} |
} |
|
|
/* |
/* |
* After the user did action1, then action2, then action3 : |
* After the user did action1, then action2, then action3: |
* |
* |
* [action3] <--- Undoptr |
* [action3] <--- Undoptr |
* [action2] |
* [action2] |
|
|
* ------ |
* ------ |
* [undo] |
* [undo] |
* |
* |
* Note that the "undo of actionX" have no special meaning. Only when, |
* Note that the "undo of actionX" have no special meaning. Only when |
* say, we undo a deletion, the insertion will be recorded just as if it |
* we undo a deletion, the insertion will be recorded just as if it |
* was typed on the keyboard. Resulting in the inverse operation being |
* was typed on the keyboard. Resulting in the inverse operation being |
* saved in the list. |
* saved in the list. |
* |
* |
|
|
int |
int |
undo(int f, int n) |
undo(int f, int n) |
{ |
{ |
struct undo_rec *ptr, *nptr; |
struct undo_rec *ptr, *nptr; |
int done, rval; |
int done, rval; |
LINE *lp; |
LINE *lp; |
int offset, save, dot; |
int offset, save, dot; |
|
|
dot = find_dot(curwp->w_dotp, curwp->w_doto); |
dot = find_dot(curwp->w_dotp, curwp->w_doto); |
|
|