home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
fed0217s.zip
/
source
/
undo.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2001-02-20
|
11KB
|
434 lines
/*
** Module :UNDO.CPP
** Abstract :UNDO processor
**
** Copyright (C) Sergey I. Yevtushenko
**
** Log: Mon 15/03/1998 Created
*/
#include <string.h>
#include <buffer.h>
#include <version.h>
#define UNDO 1
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
//----------------------------------------------------------------------
// Undo processing routines
//
//----------------------------------------------------------------------
void Buffer::track_beg()
{
tracking = UNDO;
}
void Buffer::track_end()
{
if(!tracking)
return;
if(!track_head)
{
tracking = 0;
return;
}
trackinfo *head = track_head; //Save track
track_head = undobuff; //spoof 'track'
track(opAction, head);
undobuff = track_head;
track_head = 0;
tracking = 0;
undo_count++;
}
void Buffer::track_cancel()
{
if(track_head) //cleanup here
{
while(track_head)
{
switch(track_head->op)
{
case opInsBlock:
delete (Buffer *)track_head->arg1;
break;
case opRestoreLine:
case opInsLine:
Free(track_head->arg1);
break;
// case opRestoreOrder:
// delete (char*)(track_head->arg1);
}
trackinfo *tmp = track_head;
track_head = track_head->next;
delete tmp;
}
}
tracking = 0;
}
void Buffer::track(int op, void *arg1, void *arg2)
{
if(!tracking)
{
if(op == opInsBlock)
delete (Buffer *)arg1;
return;
}
trackinfo *item = new trackinfo;
item->next = track_head;
item->op = op;
item->arg1 = arg1;
item->arg2 = arg2;
track_head = item;
switch(op)
{
case opRestoreLine:
case opInsLine:
// In this cases arg1 contains pointer to line,
// we need a copy of them
item->arg1 = new Line(PLine(arg1));
break;
}
}
void Buffer::undo(Rect&)
{
trackinfo *item = undobuff;
int need_recalc = 0;
if(item) //Undo buffer always contains opAction items
{
undobuff = item->next;
trackinfo *action = (trackinfo *)item->arg1;
while(action)
{
// Do action
switch(action->op)
{
case opCurRow:
cur_row = (int)action->arg1;
break;
case opCurCol:
cur_col = (int)action->arg1;
break;
case opStartRow:
start_row = (int)action->arg1;
break;
case opStartCol:
start_col = (int)action->arg1;
break;
case opColBlock:
col_block = (int)action->arg1;
break;
case opInsMode:
ins_mode = (int)action->arg1;
break;
case opHiliting:
hiliting = (int)action->arg1;
need_recalc = 1;
break;
case opMarking:
mark_state = (int)action->arg1;
break;
case opDelLine:
//Free(del_line(rect, (int)action->arg1));
Free(Remove((unsigned)action->arg1));
need_recalc = 1;
break;
case opInsBlock:
{
Buffer* tmp_buf = (Buffer *)action->arg1;
int start_pos = (int)action->arg2;
move_items(tmp_buf, start_pos);
delete tmp_buf;
need_recalc = 1;
}
break;
case opInsLine:
//ins_line(PLine(action->arg1), (int)action->arg2);
At(action->arg1, (unsigned) action->arg2);
need_recalc = 1;
break;
case opRestoreLine:
//Free(del_line(rect, (int)action->arg2));
//ins_line(PLine(action->arg1), (int)action->arg2);
//Semi-brute force:
Free(Remove((unsigned)action->arg2));
At(action->arg1,(unsigned)action->arg2);
need_recalc = 1;
break;
case opMarkPos:
old_abs_col = (int)action->arg1;
old_abs_row = (int)action->arg2;
break;
case opInsChar:
abs_line()->ins_char(chr_in((int)action->arg1), abs_col());
need_recalc = 1;
break;
case opDelChar:
abs_line()->del_char(abs_col());
need_recalc = 1;
break;
}
trackinfo *temp = action->next;
delete action;
action = temp;
}
delete item;
undo_count--;
if(undo_count < 0)
undo_count = 0;
}
if(hiliting && need_recalc)
fill_hiliting(0, ST_INITIAL);
}
int Buffer::get_undo_count()
{
return undo_count;
}
void Buffer::clear_undobuff()
{
while(undobuff)
{
trackinfo *item = undobuff;
if(item) //Undo buffer always contains opAction items
{
undobuff = item->next;
trackinfo *action = (trackinfo *)item->arg1;
while(action)
{
// Cleanup action item
switch(action->op)
{
case opRestoreLine:
case opInsLine:
Free(action->arg1);
break;
}
trackinfo *temp = action->next;
delete action;
action = temp;
}
delete item;
}
}
undo_count = 0;
}
//----------------------------------------------------------------------
// Massive block processing routines
//
//----------------------------------------------------------------------
void Buffer::process_block(Rect& rect, PerCharFunc func)
{
changed = 1;
if(!mark_state)
{
int chr = chr_out(get_cur_char());
if(chr)
{
replace_char(rect, func((char)chr));
cursor_left(rect);
}
return;
}
int mark_beg_row = min(old_abs_row, abs_row());
int mark_end_row = max(old_abs_row, abs_row());
int i,j;
for(i = mark_beg_row; i <= mark_end_row; i++)
track(opRestoreLine,(void *)line(i),(void *)i);
if(col_block || mark_beg_row == mark_end_row)
{
int mark_col_start = min(old_abs_col, abs_col());
int mark_col_end = max(old_abs_col, abs_col());
for(i = mark_beg_row; i <= mark_end_row; i++)
for(j = mark_col_start; j < mark_col_end; j++)
{
int chr = chr_out(line(i)->del_char(j));
line(i)->ins_char(chr_in(func((char)chr)),j);
}
}
else
{
for(i = mark_beg_row; i <= mark_end_row; i++)
{
int chr;
int col_start = 0;
int col_end = line(i)->len();
if(i == mark_beg_row)
col_start = (mark_beg_row == old_abs_row) ? old_abs_col : abs_col();
if(i == mark_end_row)
col_end = (mark_end_row == old_abs_row) ? old_abs_col : abs_col();
for(int j = col_start; j < col_end; j++)
{
chr = chr_out(line(i)->del_char(j));
line(i)->ins_char(chr_in(func((char)chr)), j);
}
}
}
fill_hiliting(mark_beg_row, line(mark_beg_row)->state());
}
void Buffer::indent()
{
changed = 1;
if(!mark_state)
{
track(opRestoreLine,(void *)abs_line(),(void *)abs_row());
abs_line()->ins_char(' ',0);
return;
}
int mark_beg_row = min(old_abs_row, abs_row());
int mark_end_row = max(old_abs_row, abs_row());
int i;
for(i = mark_beg_row; i <= mark_end_row; i++)
track(opRestoreLine,(void *)line(i),(void *)i);
if(col_block || mark_beg_row == mark_end_row)
{
int mark_col_start = min(old_abs_col, abs_col());
for(i = mark_beg_row; i <= mark_end_row; i++)
line(i)->ins_char(' ', mark_col_start);
}
else
{
for(i = mark_beg_row; i <= mark_end_row; i++)
{
int col_start = 0;
if(i == mark_beg_row)
col_start = (mark_beg_row == old_abs_row) ?
old_abs_col :
abs_col();
if(i == mark_end_row)
{
int col_end = (mark_end_row == old_abs_row) ?
old_abs_col :
abs_col();
if(col_end == 0)
break;
}
line(i)->ins_char(' ', col_start);
}
}
fill_hiliting(mark_beg_row, line(mark_beg_row)->state());
}
void Buffer::unindent()
{
changed = 1;
if(!mark_state)
{
track(opRestoreLine,(void *)abs_line(),(void *)abs_row());
abs_line()->del_char(0);
return;
}
int mark_beg_row = min(old_abs_row, abs_row());
int mark_end_row = max(old_abs_row, abs_row());
int i;
for(i = mark_beg_row; i <= mark_end_row; i++)
track(opRestoreLine,(void *)line(i),(void *)i);
if(col_block || mark_beg_row == mark_end_row)
{
int mark_col_start = min(old_abs_col, abs_col());
for(i = mark_beg_row; i <= mark_end_row; i++)
line(i)->del_char(mark_col_start);
}
else
{
for(i = mark_beg_row; i <= mark_end_row; i++)
{
int col_start = 0;
if(i == mark_beg_row)
col_start = (mark_beg_row == old_abs_row) ? old_abs_col : abs_col();
if(i == mark_end_row)
{
int col_end = (mark_end_row == old_abs_row) ?
old_abs_col :
abs_col();
if(col_end == 0)
break;
}
line(i)->del_char(col_start);
}
}
fill_hiliting(mark_beg_row, line(mark_beg_row)->state());
}
void Buffer::toupper(Rect& rect)
{
process_block(rect, __to_upper);
}
void Buffer::tolower(Rect& rect)
{
process_block(rect, __to_lower);
}