home *** CD-ROM | disk | FTP | other *** search
- #include "pt.h"
- #include "string.h"
-
- void pascal
- /* XTAG:updateFile */
- updateFile(fileId, cp, len, tryShortcut)
- int fileId, tryShortcut;
- long cp, len;
- {
- extern unsigned char msgBuffer[];
- extern struct window *windowList;
- extern struct window *selWindow;
- extern long selBegin, selEnd;
- extern unsigned char *screenMap;
- extern int debug;
- extern int scrRows, scrCols;
-
- register struct window *w;
- struct window *lastW;
- int i, n, minRow, maxRow, row2, col1, col2;
- long cp1;
-
- lastW = NULL;
- w = windowList;
- while( w != NULL ) {
- if( w->fileId == fileId )
- lastW = w;
- w = w->nextWindow;
- }
-
- /* If the top window is the only window showing this file */
- /* and no line feed was deleted and the line is in the window */
- /* then try to do it faster */
- if( tryShortcut && lastW == windowList
- && cp < windowList->posBotline ) {
- posToxy(windowList, selBegin, &row2, &col2);
- col1 = windowList->col1 + 1;
- col2 = windowList->col2 - 1;
- setMap(row2, col1, row2, col2, 1, 0x07);
- n = -1;
- cp1 = prevLine(windowList->fileId, selBegin, &n);
- fillLine(windowList, cp1, row2, col1, col2);
- updateScreen(row2, row2);
- return;
- }
- /* redraw the affected windows */
- setMap(0, 0, scrRows-1, scrCols-1, 1, 0x07);
- w = windowList;
- minRow = scrRows;
- maxRow = -1;
- while( 1 ) {
- if( w->fileId != fileId ) {
- /* just mask off the window area so later */
- /* windows (underneath it) will not repaint it */
- col1 = w->col1;
- row2 = w->row2;
- n = w->col2 - col1 + 1;
- for(i = w->row1; i <= row2; i++)
- memset(screenMap+scrCols*i+col1, 0, n);
- } else {
- /* repaint the window as necessary */
- if( cp <= w->posBotline )
- w->posBotline += len;
- if( cp < w->posTopline ) {
- cp1 = w->posTopline + len;
- /* remember: len < 0 for a delete */
- /* a delete overlapping this window? */
- if( cp1 < cp ) {
- n = -1;
- cp1 = prevLine(w->fileId, cp, &n);
- }
- /* recalculate the line number by letting */
- /* prevLine count as far back as it can */
- n = 30000;
- prevLine(w->fileId, cp1, &n);
- w->numTopline = n + 1;
- w->posTopline = cp1;
- }
- drawWindow(w);
- if( w->row1 < minRow )
- minRow = w->row1;
- if( w->row2 > maxRow )
- maxRow = w->row2;
- }
- if( w == lastW )
- break;
- w = w->nextWindow;
- }
- if( maxRow != -1 )
- updateScreen(minRow, maxRow);
- }
-
- void pascal
- /* XTAG:updateTops */
- updateTops(fileId, cp, len)
- int fileId;
- long cp, len;
- {
- extern unsigned char msgBuffer[];
- extern struct window *windowList;
- extern int debug;
-
- register struct window *w;
- struct window *lastW;
- int n;
- long cp1;
-
- lastW = NULL;
- w = windowList;
- while( w != NULL ) {
- if( w->fileId == fileId )
- lastW = w;
- w = w->nextWindow;
- }
- /* adjust the data of the affected windows */
- w = windowList;
- while( 1 ) {
- if( w->fileId == fileId ) {
- if( cp >= w->posBotline )
- goto nextWindow;
- else
- w->posBotline += len;
- if( cp < w->posTopline ) {
- cp1 = w->posTopline + len;
- /* a delete overlapping this window? */
- if( cp1 < cp ) {
- n = -1;
- cp1 = prevLine(w->fileId, cp, &n);
- }
- /* recalculate the line number by letting */
- /* prevLine count as far back as it can */
- n = 30000;
- prevLine(w->fileId, cp1, &n);
- w->numTopline = n + 1;
- w->posTopline = cp1;
- }
- }
- nextWindow:
- if( w == lastW )
- break;
- w = w->nextWindow;
- }
- }
-
- void pascal
- /* XTAG:exchWithScrap */
- exchWithScrap()
- {
- extern unsigned char msgBuffer[];
- extern struct changeItem scrapBuffer;
- extern struct changeItem *change;
- extern int nextChange;
- extern long selBegin, selEnd;
- extern struct window *selWindow;
- extern struct openFile *files;
- extern unsigned char *userMessages[];
-
- long length;
- register struct changeItem *thisChange;
- struct piece *firstPiece;
-
- /* check if this is a readOnly file */
- if( files[selWindow->fileId].readOnly ) {
- sprintf(msgBuffer, userMessages[READONLYFILE],
- files[selWindow->fileId].origName);
- msg(msgBuffer, 1);
- return;
- }
-
- /* remember what was in the scrap */
- firstPiece = scrapBuffer.firstPiece;
- length = scrapBuffer.length;
- /* prevent this from getting freed when the scrap buffer is reused */
- scrapBuffer.firstPiece = NULL;
-
- /* move the selection into the scrap */
- deleteChars(selWindow->fileId, NOUPDATE, 1);
-
- /* record in the change history */
- IncrementNextChange();
- thisChange = &change[nextChange];
- thisChange->type = CINSERT;
- thisChange->position = selBegin;
- thisChange->length = length;
- thisChange->fileId = selWindow->fileId;
- thisChange->firstPiece = firstPiece;
-
- /* copy the old scrap into the file */
- copyPieces(firstPiece, selWindow, selBegin, length, 1);
-
- /* free the scrap pieces */
- freePieces(firstPiece);
- }
-
- void pascal
- /* XTAG:copyToScrap */
- copyToScrap(fromWindow, fromBegin, fromEnd)
- struct window *fromWindow;
- long fromBegin, fromEnd;
- {
- extern unsigned char msgBuffer[];
- extern struct changeItem scrapBuffer;
- extern long addPosition;
- extern int selMode;
- extern int scrapMode;
-
- int fromId;
- long fb, copyLength;
- register struct piece *tempPP;
-
- fromId = fromWindow->fileId;
-
- /* eliminate the EOF marker from the selection */
- fb = fileSize(fromId);
- if( fromEnd >= fb ) {
- if( fromBegin < fb )
- fromEnd = fb-1;
- else /* only the EOF symbol is selected */
- return;
- }
- copyLength = fromEnd - fromBegin + 1;
-
- /* free the old scrap buffer pieces */
- freePieces(scrapBuffer.firstPiece);
-
- /* record in the scrap buffer */
- scrapBuffer.type = 1;
- scrapBuffer.length = copyLength;
- tempPP = getFreePiece();
- scrapBuffer.firstPiece = tempPP;
- scrapMode = selMode;
-
- tempPP->file = ADDFILE;
- tempPP->position = addPosition;
- fb = fromBegin;
- while( fb <= fromEnd ) {
- writeChar( readChar(fromId, fb++), addPosition++);
- }
- tempPP->length = copyLength;
- }
-
- void pascal
- /* XTAG:insScrap */
- insScrap(doInsert)
- int doInsert;
- {
- extern unsigned char msgBuffer[];
- extern struct window *selWindow;
- extern long selBegin, selEnd;
- extern struct changeItem scrapBuffer;
- extern long addPosition;
- extern struct openFile *files;
- extern struct changeItem *change;
- extern int nextChange;
- extern int selMode;
- extern int scrapMode;
- extern int maxFiles;
- extern unsigned char *userMessages[];
-
- long limit, logByte;
- struct piece *tempPP, *oldScrap;
- register struct openFile *ff;
- register struct changeItem *thisChange;
-
- /* check if this is a readOnly file */
- if( files[selWindow->fileId].readOnly ) {
- sprintf(msgBuffer, userMessages[READONLYFILE],
- files[selWindow->fileId].origName);
- msg(msgBuffer, 1);
- return;
- }
-
- /* See if the text in the scrap buffer is in an edit file rather */
- /* then in the add file. If it is we need to copy it to the add */
- /* file. */
- if( !scrapBuffer.type ) {
- /* keep a pointer to the old piece list */
- oldScrap = scrapBuffer.firstPiece;
- /* scrapBuffer.length will not change */
-
- /* get a new piece and initialize the fields */
- tempPP = getFreePiece();
- tempPP->file = ADDFILE;
- tempPP->position = addPosition;
- tempPP->length = scrapBuffer.length;
-
- /* this will be the new scrapBuffer piece list */
- scrapBuffer.type = 1; /* now it is addFile only type */
- scrapBuffer.firstPiece = tempPP;
-
- /* Now copy the characters into the add file */
- logByte = 0;
- limit = scrapBuffer.length;
- /* simulate a file this was deleted from */
- ff = &files[maxFiles];
- ff->hiLogBuffer = -1;
- ff->origHandle = scrapBuffer.fileId;
- ff->fileSize = limit;
- ff->logPiece = oldScrap;
- ff->loLogPiece = 0;
- ff->hiLogPiece = oldScrap->length - 1;
- while( logByte < limit ) {
- /* copy the characters in pp to the add file */
- writeChar( readChar(maxFiles, logByte++),
- addPosition++);
- }
-
- freePieces(oldScrap); /* free the old piece chain */
- }
- if( doInsert ) {
- /* record in the change history */
- IncrementNextChange();
- thisChange = &change[nextChange];
- thisChange->type = CCOPY;
- selMode = scrapMode;
- selBegin = adjustSelMode(selWindow->fileId, selBegin);
- thisChange->position = selBegin;
- thisChange->length = scrapBuffer.length;
- thisChange->fileId = selWindow->fileId;
- thisChange->firstPiece = dupPieces(scrapBuffer.firstPiece);
-
- copyPieces(scrapBuffer.firstPiece, selWindow, selBegin,
- scrapBuffer.length, 1);
- }
- }
-
- void pascal
- /* XTAG:copyMove */
- copyMove(fromWindow, fromBegin, fromEnd, toWindow, toPosition, mode)
- struct window *fromWindow, *toWindow;
- long fromBegin, fromEnd, toPosition;
- int mode;
- {
- extern unsigned char msgBuffer[];
- extern struct openFile *files;
- extern long selBegin, selEnd;
- extern struct window *selWindow;
- extern struct changeItem *change;
- extern int nextChange;
- extern int addHandle;
- extern long addPosition;
- extern unsigned char *userMessages[];
-
- int n, fromId, toId;
- long fb, copyLength;
- register struct piece *tempPP;
- register struct changeItem *thisChange;
-
- /* check if this is a readOnly file */
- if( files[toWindow->fileId].readOnly ) {
- sprintf(msgBuffer, userMessages[READONLYFILE],
- files[toWindow->fileId].origName);
- msg(msgBuffer, 1);
- return;
- }
-
- /* Is this a move with source and destination ovelapping? */
- if( mode==MOVE && fromBegin<=toPosition && toPosition<=fromEnd
- && fromWindow==toWindow ) {
- msg("Cannot move text into itself", 2);
- return;
- }
-
- fromId = fromWindow->fileId;
- toId = toWindow->fileId;
-
- /* eliminate the EOF marker from the selection */
- fb = fileSize(fromId);
- if( fromEnd >= fb ) {
- if( fromBegin < fb )
- fromEnd = fb-1;
- else /* only the EOF symbol is selected */
- return;
- }
- copyLength = fromEnd - fromBegin + 1;
-
- /* record in the change history */
- IncrementNextChange();
- thisChange = &change[nextChange];
- if( mode == COPY )
- thisChange->type = CCOPY;
- else
- thisChange->type = CMOVE;
- thisChange->position = toPosition;
- thisChange->length = copyLength;
- thisChange->fileId = toId;
- tempPP = getFreePiece();
- thisChange->firstPiece = tempPP;
-
- tempPP->file = ADDFILE;
- tempPP->position = addPosition;
- fb = fromBegin;
- while( fb <= fromEnd ) {
- writeChar( readChar(fromId, fb++), addPosition++);
- }
- tempPP->length = copyLength;
-
- /* if it is a move, then delete the from text */
- if( mode == MOVE ) {
- selWindow = fromWindow;
- selBegin = fromBegin;
- selEnd = fromEnd;
- if( fromWindow == toWindow )
- n = NOUPDATE;
- else
- n = UPDATEWINDOWS;
- deleteChars(fromWindow->fileId, n, 1);
- /* if we deleted text before the toPosition we have */
- /* to adjust it since the logical text positions change */
- /* after a delete. We also fix up the position on the */
- /* delete following so it will look like it really did */
- /* take place AFTER the copying in of the moved text */
- if( fromWindow->fileId == toWindow->fileId ) {
- if( toPosition > fromBegin )
- toPosition -= copyLength;
- else
- change[nextChange].position += copyLength;
- }
- }
-
- copyPieces(thisChange->firstPiece, toWindow, toPosition, copyLength,
- 1);
- }
-
- void pascal
- /* XTAG:copyPieces */
- copyPieces(fromPP, toWindow, toPosition, copyLength, update)
- struct piece *fromPP;
- struct window *toWindow;
- long toPosition, copyLength;
- int update;
- {
- extern unsigned char msgBuffer[];
- extern struct openFile *files;
- extern long selBegin, selEnd;
- extern int selMode;
- extern struct window *selWindow;
- extern struct changeItem *change;
- extern int nextChange;
- extern int addHandle;
- extern long addPosition;
-
- int toId;
- long offset, toNN;
- register struct piece *nextPP, *toPP, *lastPP;
- register struct openFile *toFF;
- struct piece *pp2;
- struct window *w;
-
- if( update ) {
- /* just using these variables to save the selection */
- offset = selBegin;
- toNN = selEnd;
- w = selWindow;
- selBegin = selEnd = toPosition;
- selWindow = toWindow;
- selBegin = offset;
- selEnd = toNN;
- selWindow = w;
- }
-
- /* This is a special case to handle a backspace problem. To wit, */
- /* if we delete text and type in new text, then select other text */
- /* and REDO, then the piece from the first change is copied in. */
- /* If we then backspace and type a new character, the piece itself */
- /* is changed and so the orignal edit is changed also. We have to */
- /* prevent this so we bump addPosition in this case so the */
- /* backspace does not change the piece */
- /* A BETTER SOLUTION would be to make an actual copy of the text */
- /* in the piece. This would allow further editing that would then */
- /* be able to be repeated again. */
- toPP = fromPP; /* just using toPP as a convenient variable */
- while( toPP->nextPiece != NULL )
- toPP = toPP->nextPiece;
- if( (toPP->file == ADDFILE)
- && (toPP->position+toPP->length == addPosition) )
- ++addPosition;
-
- /* compute some values for later efficiency */
- toId = toWindow->fileId;
- toFF = &files[toId];
-
- /* find out what piece 'toBegin' is in */
- toPP = findPiece(toPosition, toFF, &toNN);
- /* special case for the end of the file */
- if( toPosition > toFF->fileSize ) {
- /* leave toPP as the last piece in the file */
- nextPP = NULL;
- } else if( toPosition > toNN ) {
- /* copied text starts inside piece "toPP" */
- /* We split toPP into two pieces (toPP and nextPP) */
- /* at toPosition */
- /* get a new piece */
- nextPP = getFreePiece();
- /* link the new piece in before the piece after toPP */
- pp2 = toPP->nextPiece;
- nextPP->nextPiece = pp2;
- if( pp2 != NULL )
- pp2->prevPiece = nextPP;
- /* adjust the fields of the two pieces */
- offset = toPosition - toNN;
- nextPP->file = toPP->file;
- nextPP->position = toPP->position + offset;
- nextPP->length = toPP->length - offset;
- toPP->length = offset;
- } else {
- nextPP = toPP;
- toPP = toPP->prevPiece;
- }
-
- /* now copy the pieces into the piece list between toPP and nextPP */
- lastPP = toPP;
- while( fromPP != NULL ) {
- pp2 = getFreePiece();
- /* copy the information into the new piece */
- pp2->file = fromPP->file;
- pp2->position = fromPP->position;
- pp2->length = fromPP->length;
- /* link in the new piece */
- pp2->prevPiece = lastPP;
- /* link it into the list */
- if( lastPP != NULL )
- lastPP->nextPiece = pp2;
- else /* new first item on the list */
- toFF->pieceList = pp2;
- /* move to the next piece to copy */
- lastPP = pp2;
- fromPP = fromPP->nextPiece;
- }
- lastPP->nextPiece = nextPP;
- if( nextPP != NULL )
- nextPP->prevPiece = lastPP;
-
- /* make the cached piece the one after the copied pieces */
- /* unless it is NULL */
- if( nextPP != NULL ) {
- toFF->logPiece = nextPP;
- toFF->loLogPiece = toPosition + copyLength;
- toFF->hiLogPiece = toFF->loLogPiece + nextPP->length - 1;
- } else { /* make it the first piece in the file */
- toFF->logPiece = toFF->pieceList;
- toFF->loLogPiece = 0;
- toFF->hiLogPiece = toFF->loLogPiece
- + (toFF->logPiece)->length - 1;
- }
-
- /* update the length of the "to" file */
- toFF->fileSize += copyLength;
-
- /* invalidate the buffer cache of the "to" file */
- toFF->hiLogBuffer = -1L;
-
- /* record the fact that the file has changed */
- toFF->isChanged = 1;
-
- /* invalidate the last-row-found cache */
- if( toWindow->posCurLast > toPosition )
- toWindow->lastPosTop = -1;
-
- /* make the selection the character past the copied text */
- if( selWindow != toWindow ) {
- eraseSelection();
- selWindow = toWindow;
- }
- selEnd = selBegin = toPosition + copyLength;
- if( readChar(toId, selBegin) == '\r' ) {
- if( readChar(toId, selBegin + 1) == '\n' )
- ++selEnd;
- }
- /* change selection mode to character mode */
- selMode = SELCHAR;
- if( update )
- updateFile(toId, toPosition, copyLength, 0);
- }
-