home *** CD-ROM | disk | FTP | other *** search
- /*
- ** 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);
- }
-
-
-