home *** CD-ROM | disk | FTP | other *** search
- #include "pt.h"
-
- void pascal
- /* XTAG:initChanges */
- initChanges()
- {
- extern struct changeItem *change;
- extern struct changeItem scrapBuffer;
- extern int tailChange, nextChange;
-
- register int i;
-
- for(i = 0; i < NHISTORY; i++) {
- change[i].type = CNULL;
- change[i].firstPiece = NULL;
- }
- tailChange = nextChange = 0;
- scrapBuffer.firstPiece = getFreePiece();
- scrapBuffer.firstPiece->file = ADDFILE;
- scrapBuffer.firstPiece->position = 0L;
- scrapBuffer.firstPiece->length = 0L;
- }
-
- void pascal
- /* XTAG:IncrementNextChange */
- IncrementNextChange()
- {
- extern int tailChange, nextChange;
- extern struct changeItem *change;
-
- /* change history is a circular buffer */
- if( ++nextChange >= NHISTORY )
- nextChange = 0;
- /* is the change buffer full? */
- if( nextChange == tailChange ) {
- /* if so, free the 'tailChange' change */
- if( change[tailChange].type != CNULL )
- freePieces( change[tailChange].firstPiece );
- change[tailChange].firstPiece = NULL;
- /* and move the 'tail' up one */
- if( ++tailChange >= NHISTORY )
- tailChange = 0;
- }
- }
-
- void pascal
- /* XTAG:redo */
- redo()
- {
- extern unsigned char msgBuffer[];
- extern struct window *selWindow;
- extern long selBegin, selEnd;
- extern struct changeItem *change;
- extern int tailChange, nextChange;
- extern struct openFile *files;
- extern unsigned char *userMessages[];
-
- register struct changeItem *newChange;
- struct changeItem *thisChange, *prevChange;
- int n, type, count;
-
- /* check if this is a readOnly file */
- if( files[selWindow->fileId].readOnly ) {
- sprintf(msgBuffer, userMessages[READONLYFILE],
- files[selWindow->fileId].origName);
- msg(msgBuffer, 1);
- return;
- }
-
- if( nextChange == tailChange ) {
- noChanges:
- msg("No previous change to redo", 2);
- return;
- }
-
- n = nextChange; /* remember where the next change is */
-
- /* find the change to redo (not a delete ) */
- count = 0;
- while( 1 ) {
- thisChange = &change[n];
- if((thisChange->type)!=CDELETE && (thisChange->type)!=CNULL)
- break;
- if( --n < 0 )
- n = NHISTORY - 1;
- if( count++ > NHISTORY )
- goto noChanges;
- }
-
- switch( thisChange->type ) {
-
- case CINSERT:
- type = CINSERT;
- goto doCopy;
-
- case CCOPY:
- case CMOVE:
- type = CCOPY;
- doCopy:
- /* see if the previous change was a delete */
- if( --n < 0 )
- n = NHISTORY - 1;
- prevChange = &change[n];
- if( thisChange->position == prevChange->position
- && prevChange->type == CDELETE )
- /* the delete must go into the history first */
- deleteChars(selWindow->fileId, NOUPDATE, 0);
- /* find the slot to record this change */
- IncrementNextChange();
- /* record the change before copyPieces changes things */
- newChange = &change[nextChange];
- newChange->type = type;
- newChange->position = selBegin;
- newChange->length = thisChange->length;
- newChange->fileId = selWindow->fileId;
- newChange->firstPiece = dupPieces(thisChange->firstPiece);
- copyPieces(thisChange->firstPiece, selWindow, selBegin,
- thisChange->length, 1);
- break;
-
- case CDELETE:
- deleteChars(selWindow->fileId, UPDATEWINDOWS, 0);
- break;
- }
- }
-
- void pascal
- /* XTAG:undo */
- undo(doHistory)
- int doHistory;
- {
- extern unsigned char msgBuffer[];
- extern struct window *selWindow;
- extern long selBegin, selEnd;
- extern struct window *windowList;
- extern struct changeItem *change;
- extern int tailChange, nextChange;
- extern int debug;
-
- int n, delAlso, count;
- register struct changeItem *newChange;
- struct changeItem *thisChange, *prevChange;
- struct window *w1;
-
- if( nextChange == tailChange ) {
- noChanges:
- msg("No previous change to undo", 2);
- return;
- }
-
- /* find the change to undo */
- n = nextChange;
- count = 0;
- while( 1 ) {
- thisChange = &change[n];
- if( (thisChange->type) != CNULL )
- break;
- if( --n < 0 )
- n = NHISTORY - 1;
- if( count++ > NHISTORY )
- goto noChanges;
- }
- nextChange = n;
- if( --n < 0 )
- n = NHISTORY - 1;
- prevChange = &change[n];
-
- /* find a window displaying the file the change was made in */
- if( thisChange->fileId != selWindow->fileId ) {
- w1 = windowList;
- while( w1 != NULL && w1->fileId != thisChange->fileId )
- w1 = w1->nextWindow;
- if( w1 == NULL ) {
- msg("Cannot undo. No windows have that file open.",3);
- return;
- } else
- selWindow = w1;
- }
-
- switch( thisChange->type ) {
-
- case CDELETE:
- if( doHistory ) {
- /* find the slot to record this change */
- IncrementNextChange();
- newChange = &change[nextChange];
- newChange->type = CCOPY;
- newChange->position = thisChange->position;
- newChange->length = thisChange->length;
- newChange->fileId = selWindow->fileId;
- newChange->firstPiece =
- dupPieces(thisChange->firstPiece);
- }
- showChange();
- copyPieces(thisChange->firstPiece, selWindow,
- thisChange->position, thisChange->length, 1);
- if( !doHistory ) {
- change[nextChange--].type = CNULL;
- if( nextChange < 0 )
- nextChange = NHISTORY - 1;
- }
- /* see if this is really the DELETE of a CMOVE */
- if( prevChange->type != CMOVE )
- break;
- if( doHistory ) /* if we are recording in history */
- newChange->type = CMOVE; /* change it to a move */
- /* else finish undoing the move by dropping through */
- /* to the CCOPY case to delete the MOVEd text */
- thisChange = prevChange;
- /* erase this change from the history list */
-
- case CCOPY:
- selBegin = thisChange->position;
- selEnd = selBegin + thisChange->length - 1;
- showChange();
- deleteChars(thisChange->fileId, UPDATEWINDOWS,
- doHistory ? 0 : 2);
- /* erase this change from the history list */
- if( !doHistory ) {
- change[nextChange--].type = CNULL;
- if( nextChange < 0 )
- nextChange = NHISTORY - 1;
- }
- break;
-
- case CINSERT:
- /* delete the characters inserted */
- selBegin = thisChange->position;
- selEnd = selBegin + thisChange->length - 1;
- /* test this first so we can avoid updating the */
- /* screen twice once for the delete and again for */
- /* the copy to follow */
- if( thisChange->position == prevChange->position
- && prevChange->type == CDELETE )
- delAlso = NOUPDATE;
- else
- delAlso = UPDATEWINDOWS;
- showChange();
- deleteChars(thisChange->fileId, delAlso,
- doHistory ? 0 : 2);
- /* erase this change from the history list */
- if( !doHistory ) {
- /* erase the last 1 or 2 changes */
- change[nextChange--].type = CNULL;
- if( delAlso == NOUPDATE ) {
- change[nextChange--].type = CNULL;
- }
- if( nextChange < 0 )
- nextChange = NHISTORY - 1;
- }
- /* see if there is a previous, related delete to undo */
- if( delAlso == NOUPDATE ) {
- if( doHistory ) {
- /* find the slot to record this change */
- IncrementNextChange();
- newChange = &change[nextChange];
- newChange->type = CINSERT;
- newChange->position = selBegin;
- newChange->length = prevChange->length;
- newChange->fileId = prevChange->fileId;
- newChange->firstPiece =
- dupPieces(prevChange->firstPiece);
- }
- copyPieces(prevChange->firstPiece, selWindow,
- selBegin, prevChange->length, 1);
- }
- break;
- }
- }
-
- /* make sure the change is visible */
- void pascal
- /* XTAG:showChange */
- showChange()
- {
- extern long selBegin, selEnd;
- extern struct window *selWindow;
- extern struct window *windowList;
-
- /* if the selection window is not on top */
- /* or if the selection is not in the window */
- /* then move the window to show the selection */
- if( windowList != selWindow || selBegin < selWindow->posTopline
- || selEnd > selWindow->posBotline )
- doGoSel(selWindow);
- }
-