home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / edit / point20 / insdel.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-04  |  13.4 KB  |  469 lines

  1. #include "pt.h"
  2.  
  3. void pascal
  4. /* XTAG:insertChar */
  5. insertChar(ch)
  6.     unsigned char ch;
  7. {
  8.     extern struct window *selWindow;
  9.     extern long selBegin, selEnd;
  10.     extern unsigned char msgBuffer[];
  11.     extern struct openFile *files;
  12.     extern struct changeItem *change;
  13.     extern int nextChange;
  14.     extern long addPosition;
  15.     extern unsigned char *userMessages[];
  16.  
  17.     register struct changeItem *thisChange;
  18.     register struct openFile *ff;
  19.     struct piece *pp, *pp2, *thispp, *nextpp, *thirdpp;
  20.     long nn, offset;
  21.  
  22.     /* find out what piece 'selBegin' is in */
  23.     ff = &files[selWindow->fileId];
  24.     pp = findPiece(selBegin, ff, &nn);
  25.  
  26.     /* check if this is a readOnly file */
  27.     if( ff->readOnly ) {
  28.         sprintf(msgBuffer, userMessages[READONLYFILE], ff->origName);
  29.         msg(msgBuffer, 1);
  30.         return;
  31.     }
  32.  
  33.     offset = selBegin - nn;
  34.     if( offset > 0 ) {    /* we must split the piece */
  35.         /* we insert two new pieces */
  36.         /* nextpp is for the character we are inserting */
  37.         /* thirdpp is the split of portion of pp */
  38.         
  39.         /* update the fields of the new piece */
  40.         nextpp = getFreePiece();
  41.         nextpp->file = ADDFILE;
  42.         nextpp->position = addPosition;
  43.         nextpp->length = 1;
  44.  
  45.         /* update the fields of the split off piece */
  46.         thirdpp = getFreePiece();
  47.         thirdpp->file = pp->file;
  48.         thirdpp->position = pp->position + offset;
  49.         thirdpp->length = pp->length - offset;
  50.  
  51.         /* update the fields of the original piece */
  52.         /* pp->file remains the same */
  53.         /* pp->position remains the same */
  54.         pp->length = offset;
  55.         
  56.         /* link everything together again */
  57.         nextpp->nextPiece = thirdpp;
  58.         thirdpp->prevPiece = nextpp;
  59.         pp2 = pp->nextPiece;
  60.         thirdpp->nextPiece = pp2;
  61.         if( pp2 != NULL )
  62.             pp2->prevPiece = thirdpp;
  63.         nextpp->prevPiece = pp;
  64.         pp->nextPiece = nextpp;
  65.  
  66.         /* make the third piece the cached one */
  67.         ff->logPiece = thirdpp;
  68.         ff->loLogPiece = selBegin + 1;
  69.         ff->hiLogPiece = selBegin + thirdpp->length;
  70.     } else {    /* put in front of this piece */
  71.         /* can we put it at the end of the previous piece? */
  72.         thispp = pp->prevPiece;
  73.         /* if (1) there IS a previous piece and */
  74.         /*    (2) it is a piece in the add file and */
  75.         /*    (3) it is just before the piece we are adding */
  76.         /* then we coalsce the two pieces */
  77.         if( (thispp != NULL)    /* pp is not the first piece */
  78.          && (thispp->file == ADDFILE)    /* in the add file */
  79.          && (thispp->position+thispp->length == addPosition)
  80.         ) {
  81.             ++(thispp->length);    /* simply adjust the length */
  82.             ff->logPiece = pp;
  83.             ff->loLogPiece = nn + 1;
  84.             ff->hiLogPiece = nn + pp->length;
  85.         } else {
  86.             /* create a new piece for this character */
  87.             thispp = getFreePiece();
  88.             thispp->file = ADDFILE;
  89.             thispp->position = addPosition;
  90.             thispp->length = 1;
  91.             thispp->nextPiece = pp;
  92.             pp2 = pp->prevPiece;
  93.             pp->prevPiece = thispp;
  94.             thispp->prevPiece = pp2;
  95.             if( pp2 != NULL )
  96.                 pp2->nextPiece = thispp;
  97.             else
  98.                 ff->pieceList = thispp;
  99.             ff->logPiece = thispp;
  100.             ff->loLogPiece = selBegin;
  101.             ff->hiLogPiece = selBegin;
  102.         }
  103.     }
  104.  
  105.     /* record in the change history */
  106.     /* see if we can add this to the last insert */
  107.     thisChange = &change[nextChange];
  108.     if( thisChange->type == CINSERT
  109.      && thisChange->fileId == selWindow->fileId
  110.      && selBegin == thisChange->position+thisChange->length ) {
  111.         ++(thisChange->length);
  112.         ++(thisChange->firstPiece->length);
  113.     } else {
  114.         /* record in the change history */
  115.         IncrementNextChange();
  116.         thisChange = &change[nextChange];
  117.         thisChange->type = CINSERT;
  118.         thisChange->position = selBegin;
  119.         thisChange->length = 1;
  120.         thisChange->fileId = selWindow->fileId;
  121.         pp = getFreePiece();
  122.         thisChange->firstPiece = pp;
  123.         pp->file = ADDFILE;
  124.         pp->position = addPosition;
  125.         pp->length = 1;
  126.     }
  127.  
  128.  
  129.     /* add one character to the file */
  130.     ff->fileSize += 1;
  131.     writeChar(ch, addPosition++);
  132.  
  133.     /* invalidate the buffer cache */
  134.     ff->hiLogBuffer = -1L;
  135.  
  136.     /* record the fact that the file has changed */
  137.     ff->isChanged = 1;
  138.  
  139.     /* adjust window data even though we do not redraw */
  140.     updateTops(selWindow->fileId, selBegin, 1L);
  141.  
  142.     /* invalidate the last-row-found cache */
  143.     if( selWindow->posCurLast > selBegin )
  144.         selWindow->lastPosTop = -1;
  145.     
  146.     /* move the selection to char past new char */
  147.     selEnd = ++selBegin;
  148.     if( readChar(selWindow->fileId, selBegin) == '\r' ) {
  149.         if( readChar(selWindow->fileId, selBegin+1) == '\n' )
  150.             ++selEnd;
  151.     }
  152. }
  153.  
  154. int pascal
  155. /* XTAG:delChar */
  156. delChar()
  157. {
  158.     extern struct window *selWindow;
  159.     extern long selBegin, selEnd;
  160.     extern unsigned char msgBuffer[];
  161.     extern struct openFile *files;
  162.     extern struct changeItem *change;
  163.     extern int nextChange;
  164.     extern long addPosition;
  165.     extern unsigned char *userMessages[];
  166.  
  167.     long nn, offset;
  168.     register struct openFile *ff;
  169.     struct piece *pp, *thispp;
  170.     register struct changeItem *thisChange;
  171.  
  172.     /* find out what piece 'selBegin' is in */
  173.     ff = &files[selWindow->fileId];
  174.     pp = findPiece(selBegin, ff, &nn);
  175.  
  176.     /* check if this is a readOnly file */
  177.     if( ff->readOnly ) {
  178.         sprintf(msgBuffer, userMessages[READONLYFILE], ff->origName);
  179.         msg(msgBuffer, 1);
  180.         return 0;
  181.     }
  182.  
  183.     offset = selBegin - nn;
  184.     if( offset > 0 )
  185.         return 0;
  186.  
  187.     /* is the char to delete at the end of the previous piece? */
  188.     thispp = pp->prevPiece;
  189.     /* if (1) there IS a previous piece and */
  190.     /*    (2) it is a piece in the add file and */
  191.     /*    (3) it is just before the piece we are adding and */
  192.     /*    (4) we are not deleting the last char in the piece */
  193.     /*    (5) the preceding change was an insert */
  194.     /* then we coalsce the two pieces */
  195.     if( (thispp != NULL)    /* pp is not the first piece */
  196.      && (thispp->file == ADDFILE)    /* in the add file */
  197.      && (thispp->position+thispp->length == addPosition)
  198.      && (thispp->length >= 1)
  199.      && (change[nextChange].type == CINSERT)
  200.     ) {
  201.         --(thispp->length);    /* simply adjust the length */
  202.         ff->logPiece = pp;
  203.         ff->loLogPiece = nn - 1;
  204.         ff->hiLogPiece = nn + pp->length - 1;
  205.     } else
  206.         return 0;
  207.  
  208.     /* record in the change history */
  209.     /* see if we can add this to the last insert */
  210.     thisChange = &change[nextChange];
  211.     if( thisChange->type == CINSERT
  212.      && thisChange->fileId == selWindow->fileId
  213.      && selBegin == thisChange->position+thisChange->length ) {
  214.         --(thisChange->length);
  215.         --(thisChange->firstPiece->length);
  216.     } else {
  217.         ++(thispp->length);    /* re-adjust the length */
  218.         return 0;
  219.     }
  220.  
  221.     /* subtract one character to the file */
  222.     ff->fileSize -= 1;
  223.     --addPosition;
  224.  
  225.     /* invalidate the buffer cache */
  226.     ff->hiLogBuffer = -1L;
  227.  
  228.     /* record the fact that the file has changed */
  229.     ff->isChanged = 1;
  230.  
  231.     /* adjust window data even though we do not redraw */
  232.     updateTops(selWindow->fileId, selBegin, 1L);
  233.  
  234.     /* invalidate the last-row-found cache */
  235.     if( selWindow->posCurLast > selBegin )
  236.         selWindow->lastPosTop = -1;
  237.     
  238.     /* move the selection to char past new char */
  239.     selEnd = --selBegin;
  240.     if( readChar(selWindow->fileId, selBegin) == '\r' ) {
  241.         if( readChar(selWindow->fileId, selBegin+1) == '\n' )
  242.             ++selEnd;
  243.     }
  244.     return 1;
  245. }
  246.  
  247. int pascal
  248. /* XTAG:deleteChars */
  249. deleteChars(fileId, update, toScrap)
  250.     /* toScrap=0 --> do not put in the scrap */
  251.     /* toScrap=1 --> do put in the scrap */
  252.     /* toScrap=2 --> do not put in the scrap or the history */
  253.     int fileId, update, toScrap;
  254. {
  255.     extern unsigned char msgBuffer[];
  256.     extern int debug;
  257.     extern long selBegin, selEnd;
  258.     extern struct window *selWindow;
  259.     extern struct changeItem *change;
  260.     extern struct changeItem scrapBuffer;
  261.     extern int nextChange;
  262.     extern int selMode;
  263.     extern int scrapMode;
  264.     extern long addPosition;
  265.     extern struct openFile *files;
  266.     extern unsigned char *userMessages[];
  267.  
  268.     register struct openFile *ff;
  269.     long sb, nn, curPos, nextPos, offset, delLength;
  270.     int wasLF;
  271.     register struct piece *pp;
  272.     struct piece *pp2, *firstPP, *nextPP, *lastPP;
  273.     struct changeItem *thisChange;
  274.  
  275.     ff = &files[fileId];
  276.     nn = ff->fileSize;
  277.  
  278.     /* check if this is a readOnly file */
  279.     if( ff->readOnly ) {
  280.         sprintf(msgBuffer, userMessages[READONLYFILE], ff->origName);
  281.         msg(msgBuffer, 1);
  282.         return 0;
  283.     }
  284.  
  285.     /* eliminate the EOF marker from the selection */
  286.     if( selEnd >= nn ) {
  287.         if( selBegin < nn )
  288.             selEnd = nn-1;
  289.         else    /* only the EOF symbol is selected */
  290.             return 0;
  291.     }
  292.  
  293.     delLength = selEnd - selBegin + 1;
  294.  
  295.     /* see if we are deleting a newline */
  296.     if( delLength < 20 ) {    /* worth it to look? */
  297.         wasLF = 0;
  298.         sb = selBegin;
  299.         while( sb <= selEnd )
  300.             if( readChar(fileId, sb++) == '\n' ) {
  301.                 wasLF = 1;
  302.                 break;
  303.             }
  304.     } else    /* assume there is one -- too many to search */
  305.         wasLF = 1;
  306.  
  307.     /* find out what piece 'selBegin' is in */
  308.     firstPP = findPiece(selBegin, ff, &curPos);
  309.  
  310. /* first see if we have to split pp */
  311. offset = selBegin - curPos;
  312. if( offset > 0 ) {    /* delete starts inside this piece */
  313.     /* split firstPP at selBegin */
  314.     /* that is, get a new piece and adjust all the fields */
  315.     nextPP = getFreePiece();
  316.     nextPP->file = firstPP->file;
  317.     nextPP->position = firstPP->position + offset;
  318.     nextPP->length = firstPP->length - offset;
  319.     firstPP->length = offset;
  320.     nextPP->nextPiece = firstPP->nextPiece;
  321.     nextPP->prevPiece = firstPP;
  322.     if( (pp = firstPP->nextPiece) != NULL )
  323.         pp->prevPiece = nextPP;
  324.     firstPP->nextPiece = nextPP;
  325.     firstPP = nextPP;
  326.     curPos += offset;
  327. }
  328.  
  329. /* Now the delete begins at the first byte of firstPP */
  330. /* See where the last piece is */
  331. lastPP = firstPP;
  332. while( 1 ) {
  333.     /* does the selection end in this piece? */
  334.     nextPos = curPos + lastPP->length;
  335.     if( nextPos > selEnd )
  336.         break;
  337.     curPos = nextPos;
  338.     lastPP = lastPP->nextPiece;
  339. }
  340.  
  341. /* now we see if we have to split this piece */
  342. if( selEnd < nextPos-1 ) {    /* delete ends inside this piece */
  343.     /* split lastPP at selEnd */
  344.     /* that is, get a new piece and adjust all the fields */
  345.     nextPP = getFreePiece();
  346.     nextPP->file = lastPP->file;
  347.     offset = selEnd - curPos + 1;
  348.     nextPP->position = lastPP->position + offset;
  349.     nextPP->length = lastPP->length - offset;
  350.     lastPP->length = offset;
  351.     pp = lastPP->nextPiece;
  352.     nextPP->nextPiece = pp;
  353.     nextPP->prevPiece = lastPP;
  354.     if( pp != NULL )
  355.         pp->prevPiece = nextPP;
  356.     lastPP->nextPiece = nextPP;
  357. }
  358.  
  359. /* Now the selection has been isolated in pieces firstPP (which begins */
  360. /* with selBegin) and lastPP (which ends with selEnd) */
  361. /* Now just link them out of this piece table */
  362. if( (pp = firstPP->prevPiece) != NULL ) {
  363.     nextPP = lastPP->nextPiece;
  364.     pp->nextPiece = nextPP;
  365.     ff->logPiece = pp;
  366.     ff->loLogPiece = selBegin - pp->length;
  367.     if( nextPP != NULL )
  368.         nextPP->prevPiece = firstPP->prevPiece;
  369.     /* see if we can combine the two pieces now together */
  370.     if( (nextPP != NULL) && (pp->file == nextPP->file)
  371.      && ((pp->position+pp->length) == nextPP->position) ) {
  372.         pp->length += nextPP->length;    /* add to first piece */
  373.         /* link the second piece out of the list */
  374.         pp2 = nextPP->nextPiece;
  375.         pp->nextPiece = pp2;
  376.         if( pp2 != NULL )
  377.             pp2->prevPiece = pp;
  378.         /* isolate the one piece and free is (as a chain) */
  379.         nextPP->nextPiece = nextPP->prevPiece = NULL;
  380.         freePieces(nextPP);
  381.     }
  382. } else {    /* this delete is at the beginning of the file and there */
  383.         /* are no pieces in front of firstPiece */
  384.     pp = lastPP->nextPiece;
  385.     ff->pieceList = pp;
  386.     if( pp != NULL ) {
  387.         pp->prevPiece = NULL;
  388.         ff->logPiece = pp;
  389.     } else {
  390.         /* the piece table is empty so put a 0 length piece in it */
  391.         /* it is convenient to be able to assume (in other parts */
  392.         /* of the editor) that a piece table always contains at */
  393.         /* least one piece */
  394.         pp = getFreePiece();
  395.         pp->file = ADDFILE;
  396.         pp->position = addPosition;
  397.         pp->length = 0;
  398.         ff->pieceList = pp;
  399.         ff->logPiece = pp;
  400.     }
  401.     ff->loLogPiece = 0;
  402. }
  403.  
  404.     /* make this an independent chain */
  405.     firstPP->prevPiece = NULL;
  406.     lastPP->nextPiece = NULL;
  407.     
  408.     /* put it into the history */
  409.     if( toScrap != 2 ) {
  410.         /* record in the change history */
  411.         IncrementNextChange();
  412.         thisChange = &change[nextChange];
  413.         thisChange->type = CDELETE;
  414.         thisChange->position = selBegin;
  415.         thisChange->length = delLength;
  416.         thisChange->fileId = fileId;
  417.         thisChange->firstPiece = firstPP;
  418.     }
  419.  
  420.     if( toScrap == 1 ) {
  421.         freePieces(scrapBuffer.firstPiece);
  422.         scrapBuffer.length = delLength;
  423.         scrapBuffer.type = 0;
  424.         scrapBuffer.fileId = ff->origHandle;
  425.         scrapBuffer.firstPiece = dupPieces(firstPP);
  426.         scrapMode = selMode;
  427.     } else if( toScrap == 2 )
  428.         freePieces(firstPP);
  429.  
  430.     /* update the cached piece */
  431.     ff->hiLogPiece = ff->loLogPiece + (ff->logPiece)->length - 1;
  432.     if( ff->hiLogPiece > ff->fileSize )
  433.         /* this could happen if we just deleted the last piece */
  434.         /* in the piece table */
  435.         ff->hiLogPiece = ff->fileSize;
  436.  
  437.     /* invalidate the buffer cache */
  438.     ff->hiLogBuffer = -1L;
  439.  
  440.     /* record the fact that the file has changed */
  441.     ff->isChanged = 1;
  442.  
  443.     /* invalidate the last-row-found cache */
  444.     if( selWindow->posCurLast > selBegin )
  445.         selWindow->lastPosTop = -1;
  446.         
  447.     /* update the file length */
  448.     ff->fileSize -= delLength;
  449.     
  450.     /* the character after the deleted characters is the new selection */
  451.     selEnd = selBegin;
  452.     if( readChar(fileId, selBegin) == '\r' ) {
  453.         if( readChar(fileId, selBegin+1) == '\n' )
  454.             ++selEnd;
  455.     }
  456.     /* entend the selection according to the selection mode */
  457.     modeExtend(selWindow, selBegin, &selBegin, &selEnd);
  458.  
  459.     if( update == UPDATEWINDOWS ) {
  460.         /* redraw all the affected windows */
  461.         updateFile(fileId, selBegin, -delLength, !wasLF);
  462.     } else {
  463.         /* adjust window data even though we do not redraw */
  464.         updateTops(fileId, selBegin, -delLength);
  465.     }
  466.  
  467.     return wasLF;
  468. }
  469.