home *** CD-ROM | disk | FTP | other *** search
- #include "pt.h"
-
- void pascal
- /* XTAG:insertChar */
- insertChar(ch)
- unsigned char ch;
- {
- extern struct window *selWindow;
- extern long selBegin, selEnd;
- extern unsigned char msgBuffer[];
- extern struct openFile *files;
- extern struct changeItem *change;
- extern int nextChange;
- extern long addPosition;
- extern unsigned char *userMessages[];
-
- register struct changeItem *thisChange;
- register struct openFile *ff;
- struct piece *pp, *pp2, *thispp, *nextpp, *thirdpp;
- long nn, offset;
-
- /* find out what piece 'selBegin' is in */
- ff = &files[selWindow->fileId];
- pp = findPiece(selBegin, ff, &nn);
-
- /* check if this is a readOnly file */
- if( ff->readOnly ) {
- sprintf(msgBuffer, userMessages[READONLYFILE], ff->origName);
- msg(msgBuffer, 1);
- return;
- }
-
- offset = selBegin - nn;
- if( offset > 0 ) { /* we must split the piece */
- /* we insert two new pieces */
- /* nextpp is for the character we are inserting */
- /* thirdpp is the split of portion of pp */
-
- /* update the fields of the new piece */
- nextpp = getFreePiece();
- nextpp->file = ADDFILE;
- nextpp->position = addPosition;
- nextpp->length = 1;
-
- /* update the fields of the split off piece */
- thirdpp = getFreePiece();
- thirdpp->file = pp->file;
- thirdpp->position = pp->position + offset;
- thirdpp->length = pp->length - offset;
-
- /* update the fields of the original piece */
- /* pp->file remains the same */
- /* pp->position remains the same */
- pp->length = offset;
-
- /* link everything together again */
- nextpp->nextPiece = thirdpp;
- thirdpp->prevPiece = nextpp;
- pp2 = pp->nextPiece;
- thirdpp->nextPiece = pp2;
- if( pp2 != NULL )
- pp2->prevPiece = thirdpp;
- nextpp->prevPiece = pp;
- pp->nextPiece = nextpp;
-
- /* make the third piece the cached one */
- ff->logPiece = thirdpp;
- ff->loLogPiece = selBegin + 1;
- ff->hiLogPiece = selBegin + thirdpp->length;
- } else { /* put in front of this piece */
- /* can we put it at the end of the previous piece? */
- thispp = pp->prevPiece;
- /* if (1) there IS a previous piece and */
- /* (2) it is a piece in the add file and */
- /* (3) it is just before the piece we are adding */
- /* then we coalsce the two pieces */
- if( (thispp != NULL) /* pp is not the first piece */
- && (thispp->file == ADDFILE) /* in the add file */
- && (thispp->position+thispp->length == addPosition)
- ) {
- ++(thispp->length); /* simply adjust the length */
- ff->logPiece = pp;
- ff->loLogPiece = nn + 1;
- ff->hiLogPiece = nn + pp->length;
- } else {
- /* create a new piece for this character */
- thispp = getFreePiece();
- thispp->file = ADDFILE;
- thispp->position = addPosition;
- thispp->length = 1;
- thispp->nextPiece = pp;
- pp2 = pp->prevPiece;
- pp->prevPiece = thispp;
- thispp->prevPiece = pp2;
- if( pp2 != NULL )
- pp2->nextPiece = thispp;
- else
- ff->pieceList = thispp;
- ff->logPiece = thispp;
- ff->loLogPiece = selBegin;
- ff->hiLogPiece = selBegin;
- }
- }
-
- /* record in the change history */
- /* see if we can add this to the last insert */
- thisChange = &change[nextChange];
- if( thisChange->type == CINSERT
- && thisChange->fileId == selWindow->fileId
- && selBegin == thisChange->position+thisChange->length ) {
- ++(thisChange->length);
- ++(thisChange->firstPiece->length);
- } else {
- /* record in the change history */
- IncrementNextChange();
- thisChange = &change[nextChange];
- thisChange->type = CINSERT;
- thisChange->position = selBegin;
- thisChange->length = 1;
- thisChange->fileId = selWindow->fileId;
- pp = getFreePiece();
- thisChange->firstPiece = pp;
- pp->file = ADDFILE;
- pp->position = addPosition;
- pp->length = 1;
- }
-
-
- /* add one character to the file */
- ff->fileSize += 1;
- writeChar(ch, addPosition++);
-
- /* invalidate the buffer cache */
- ff->hiLogBuffer = -1L;
-
- /* record the fact that the file has changed */
- ff->isChanged = 1;
-
- /* adjust window data even though we do not redraw */
- updateTops(selWindow->fileId, selBegin, 1L);
-
- /* invalidate the last-row-found cache */
- if( selWindow->posCurLast > selBegin )
- selWindow->lastPosTop = -1;
-
- /* move the selection to char past new char */
- selEnd = ++selBegin;
- if( readChar(selWindow->fileId, selBegin) == '\r' ) {
- if( readChar(selWindow->fileId, selBegin+1) == '\n' )
- ++selEnd;
- }
- }
-
- int pascal
- /* XTAG:delChar */
- delChar()
- {
- extern struct window *selWindow;
- extern long selBegin, selEnd;
- extern unsigned char msgBuffer[];
- extern struct openFile *files;
- extern struct changeItem *change;
- extern int nextChange;
- extern long addPosition;
- extern unsigned char *userMessages[];
-
- long nn, offset;
- register struct openFile *ff;
- struct piece *pp, *thispp;
- register struct changeItem *thisChange;
-
- /* find out what piece 'selBegin' is in */
- ff = &files[selWindow->fileId];
- pp = findPiece(selBegin, ff, &nn);
-
- /* check if this is a readOnly file */
- if( ff->readOnly ) {
- sprintf(msgBuffer, userMessages[READONLYFILE], ff->origName);
- msg(msgBuffer, 1);
- return 0;
- }
-
- offset = selBegin - nn;
- if( offset > 0 )
- return 0;
-
- /* is the char to delete at the end of the previous piece? */
- thispp = pp->prevPiece;
- /* if (1) there IS a previous piece and */
- /* (2) it is a piece in the add file and */
- /* (3) it is just before the piece we are adding and */
- /* (4) we are not deleting the last char in the piece */
- /* (5) the preceding change was an insert */
- /* then we coalsce the two pieces */
- if( (thispp != NULL) /* pp is not the first piece */
- && (thispp->file == ADDFILE) /* in the add file */
- && (thispp->position+thispp->length == addPosition)
- && (thispp->length >= 1)
- && (change[nextChange].type == CINSERT)
- ) {
- --(thispp->length); /* simply adjust the length */
- ff->logPiece = pp;
- ff->loLogPiece = nn - 1;
- ff->hiLogPiece = nn + pp->length - 1;
- } else
- return 0;
-
- /* record in the change history */
- /* see if we can add this to the last insert */
- thisChange = &change[nextChange];
- if( thisChange->type == CINSERT
- && thisChange->fileId == selWindow->fileId
- && selBegin == thisChange->position+thisChange->length ) {
- --(thisChange->length);
- --(thisChange->firstPiece->length);
- } else {
- ++(thispp->length); /* re-adjust the length */
- return 0;
- }
-
- /* subtract one character to the file */
- ff->fileSize -= 1;
- --addPosition;
-
- /* invalidate the buffer cache */
- ff->hiLogBuffer = -1L;
-
- /* record the fact that the file has changed */
- ff->isChanged = 1;
-
- /* adjust window data even though we do not redraw */
- updateTops(selWindow->fileId, selBegin, 1L);
-
- /* invalidate the last-row-found cache */
- if( selWindow->posCurLast > selBegin )
- selWindow->lastPosTop = -1;
-
- /* move the selection to char past new char */
- selEnd = --selBegin;
- if( readChar(selWindow->fileId, selBegin) == '\r' ) {
- if( readChar(selWindow->fileId, selBegin+1) == '\n' )
- ++selEnd;
- }
- return 1;
- }
-
- int pascal
- /* XTAG:deleteChars */
- deleteChars(fileId, update, toScrap)
- /* toScrap=0 --> do not put in the scrap */
- /* toScrap=1 --> do put in the scrap */
- /* toScrap=2 --> do not put in the scrap or the history */
- int fileId, update, toScrap;
- {
- extern unsigned char msgBuffer[];
- extern int debug;
- extern long selBegin, selEnd;
- extern struct window *selWindow;
- extern struct changeItem *change;
- extern struct changeItem scrapBuffer;
- extern int nextChange;
- extern int selMode;
- extern int scrapMode;
- extern long addPosition;
- extern struct openFile *files;
- extern unsigned char *userMessages[];
-
- register struct openFile *ff;
- long sb, nn, curPos, nextPos, offset, delLength;
- int wasLF;
- register struct piece *pp;
- struct piece *pp2, *firstPP, *nextPP, *lastPP;
- struct changeItem *thisChange;
-
- ff = &files[fileId];
- nn = ff->fileSize;
-
- /* check if this is a readOnly file */
- if( ff->readOnly ) {
- sprintf(msgBuffer, userMessages[READONLYFILE], ff->origName);
- msg(msgBuffer, 1);
- return 0;
- }
-
- /* eliminate the EOF marker from the selection */
- if( selEnd >= nn ) {
- if( selBegin < nn )
- selEnd = nn-1;
- else /* only the EOF symbol is selected */
- return 0;
- }
-
- delLength = selEnd - selBegin + 1;
-
- /* see if we are deleting a newline */
- if( delLength < 20 ) { /* worth it to look? */
- wasLF = 0;
- sb = selBegin;
- while( sb <= selEnd )
- if( readChar(fileId, sb++) == '\n' ) {
- wasLF = 1;
- break;
- }
- } else /* assume there is one -- too many to search */
- wasLF = 1;
-
- /* find out what piece 'selBegin' is in */
- firstPP = findPiece(selBegin, ff, &curPos);
-
- /* first see if we have to split pp */
- offset = selBegin - curPos;
- if( offset > 0 ) { /* delete starts inside this piece */
- /* split firstPP at selBegin */
- /* that is, get a new piece and adjust all the fields */
- nextPP = getFreePiece();
- nextPP->file = firstPP->file;
- nextPP->position = firstPP->position + offset;
- nextPP->length = firstPP->length - offset;
- firstPP->length = offset;
- nextPP->nextPiece = firstPP->nextPiece;
- nextPP->prevPiece = firstPP;
- if( (pp = firstPP->nextPiece) != NULL )
- pp->prevPiece = nextPP;
- firstPP->nextPiece = nextPP;
- firstPP = nextPP;
- curPos += offset;
- }
-
- /* Now the delete begins at the first byte of firstPP */
- /* See where the last piece is */
- lastPP = firstPP;
- while( 1 ) {
- /* does the selection end in this piece? */
- nextPos = curPos + lastPP->length;
- if( nextPos > selEnd )
- break;
- curPos = nextPos;
- lastPP = lastPP->nextPiece;
- }
-
- /* now we see if we have to split this piece */
- if( selEnd < nextPos-1 ) { /* delete ends inside this piece */
- /* split lastPP at selEnd */
- /* that is, get a new piece and adjust all the fields */
- nextPP = getFreePiece();
- nextPP->file = lastPP->file;
- offset = selEnd - curPos + 1;
- nextPP->position = lastPP->position + offset;
- nextPP->length = lastPP->length - offset;
- lastPP->length = offset;
- pp = lastPP->nextPiece;
- nextPP->nextPiece = pp;
- nextPP->prevPiece = lastPP;
- if( pp != NULL )
- pp->prevPiece = nextPP;
- lastPP->nextPiece = nextPP;
- }
-
- /* Now the selection has been isolated in pieces firstPP (which begins */
- /* with selBegin) and lastPP (which ends with selEnd) */
- /* Now just link them out of this piece table */
- if( (pp = firstPP->prevPiece) != NULL ) {
- nextPP = lastPP->nextPiece;
- pp->nextPiece = nextPP;
- ff->logPiece = pp;
- ff->loLogPiece = selBegin - pp->length;
- if( nextPP != NULL )
- nextPP->prevPiece = firstPP->prevPiece;
- /* see if we can combine the two pieces now together */
- if( (nextPP != NULL) && (pp->file == nextPP->file)
- && ((pp->position+pp->length) == nextPP->position) ) {
- pp->length += nextPP->length; /* add to first piece */
- /* link the second piece out of the list */
- pp2 = nextPP->nextPiece;
- pp->nextPiece = pp2;
- if( pp2 != NULL )
- pp2->prevPiece = pp;
- /* isolate the one piece and free is (as a chain) */
- nextPP->nextPiece = nextPP->prevPiece = NULL;
- freePieces(nextPP);
- }
- } else { /* this delete is at the beginning of the file and there */
- /* are no pieces in front of firstPiece */
- pp = lastPP->nextPiece;
- ff->pieceList = pp;
- if( pp != NULL ) {
- pp->prevPiece = NULL;
- ff->logPiece = pp;
- } else {
- /* the piece table is empty so put a 0 length piece in it */
- /* it is convenient to be able to assume (in other parts */
- /* of the editor) that a piece table always contains at */
- /* least one piece */
- pp = getFreePiece();
- pp->file = ADDFILE;
- pp->position = addPosition;
- pp->length = 0;
- ff->pieceList = pp;
- ff->logPiece = pp;
- }
- ff->loLogPiece = 0;
- }
-
- /* make this an independent chain */
- firstPP->prevPiece = NULL;
- lastPP->nextPiece = NULL;
-
- /* put it into the history */
- if( toScrap != 2 ) {
- /* record in the change history */
- IncrementNextChange();
- thisChange = &change[nextChange];
- thisChange->type = CDELETE;
- thisChange->position = selBegin;
- thisChange->length = delLength;
- thisChange->fileId = fileId;
- thisChange->firstPiece = firstPP;
- }
-
- if( toScrap == 1 ) {
- freePieces(scrapBuffer.firstPiece);
- scrapBuffer.length = delLength;
- scrapBuffer.type = 0;
- scrapBuffer.fileId = ff->origHandle;
- scrapBuffer.firstPiece = dupPieces(firstPP);
- scrapMode = selMode;
- } else if( toScrap == 2 )
- freePieces(firstPP);
-
- /* update the cached piece */
- ff->hiLogPiece = ff->loLogPiece + (ff->logPiece)->length - 1;
- if( ff->hiLogPiece > ff->fileSize )
- /* this could happen if we just deleted the last piece */
- /* in the piece table */
- ff->hiLogPiece = ff->fileSize;
-
- /* invalidate the buffer cache */
- ff->hiLogBuffer = -1L;
-
- /* record the fact that the file has changed */
- ff->isChanged = 1;
-
- /* invalidate the last-row-found cache */
- if( selWindow->posCurLast > selBegin )
- selWindow->lastPosTop = -1;
-
- /* update the file length */
- ff->fileSize -= delLength;
-
- /* the character after the deleted characters is the new selection */
- selEnd = selBegin;
- if( readChar(fileId, selBegin) == '\r' ) {
- if( readChar(fileId, selBegin+1) == '\n' )
- ++selEnd;
- }
- /* entend the selection according to the selection mode */
- modeExtend(selWindow, selBegin, &selBegin, &selEnd);
-
- if( update == UPDATEWINDOWS ) {
- /* redraw all the affected windows */
- updateFile(fileId, selBegin, -delLength, !wasLF);
- } else {
- /* adjust window data even though we do not redraw */
- updateTops(fileId, selBegin, -delLength);
- }
-
- return wasLF;
- }
-