home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / EDITOR / PT20PC.ZIP / COPYMOVE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-04  |  15.6 KB  |  575 lines

  1. #include "pt.h"
  2. #include "string.h"
  3.  
  4. void pascal
  5. /* XTAG:updateFile */
  6. updateFile(fileId, cp, len, tryShortcut)
  7.     int fileId, tryShortcut;
  8.     long cp, len;
  9. {
  10.     extern unsigned char msgBuffer[];
  11.     extern struct window *windowList;
  12.     extern struct window *selWindow;
  13.     extern long selBegin, selEnd;
  14.     extern unsigned char *screenMap;
  15.     extern int debug;
  16.     extern int scrRows, scrCols;
  17.  
  18.     register struct window *w;
  19.     struct window *lastW;
  20.     int i, n, minRow, maxRow, row2, col1, col2;
  21.     long cp1;
  22.  
  23.     lastW = NULL;
  24.     w = windowList;
  25.     while( w != NULL ) {
  26.         if( w->fileId == fileId )
  27.             lastW = w;
  28.         w = w->nextWindow;
  29.     }
  30.  
  31.     /* If the top window is the only window showing this file */
  32.     /* and no line feed was deleted and the line is in the window */
  33.     /* then try to do it faster */
  34.     if( tryShortcut && lastW == windowList
  35.                 && cp < windowList->posBotline ) {
  36.         posToxy(windowList, selBegin, &row2, &col2);
  37.         col1 = windowList->col1 + 1;
  38.         col2 = windowList->col2 - 1;
  39.         setMap(row2, col1, row2, col2, 1, 0x07);
  40.         n = -1;
  41.         cp1 = prevLine(windowList->fileId, selBegin, &n);
  42.         fillLine(windowList, cp1, row2, col1, col2);
  43.         updateScreen(row2, row2);
  44.         return;
  45.     }
  46.     /* redraw the affected windows */
  47.     setMap(0, 0, scrRows-1, scrCols-1, 1, 0x07);
  48.     w = windowList;
  49.     minRow = scrRows;
  50.     maxRow = -1;
  51.     while( 1 ) {
  52.         if( w->fileId != fileId ) {
  53.             /* just mask off the window area so later */
  54.             /* windows (underneath it) will not repaint it */
  55.             col1 = w->col1;
  56.             row2 = w->row2;
  57.             n = w->col2 - col1 + 1;
  58.             for(i = w->row1; i <= row2; i++)
  59.                 memset(screenMap+scrCols*i+col1, 0, n);
  60.         } else {
  61.             /* repaint the window as necessary */
  62.             if( cp <= w->posBotline )
  63.                 w->posBotline += len;
  64.             if( cp < w->posTopline ) {
  65.                 cp1 = w->posTopline + len;
  66.                 /* remember: len < 0 for a delete */
  67.                 /* a delete overlapping this window? */
  68.                 if( cp1 < cp ) {
  69.                     n = -1;
  70.                     cp1 = prevLine(w->fileId, cp, &n);
  71.                 }
  72.                 /* recalculate the line number by letting */
  73.                 /* prevLine count as far back as it can */
  74.                 n = 30000;
  75.                 prevLine(w->fileId, cp1, &n);
  76.                 w->numTopline = n + 1;
  77.                 w->posTopline = cp1;
  78.             }
  79.             drawWindow(w);
  80.             if( w->row1 < minRow )
  81.                 minRow = w->row1;
  82.             if( w->row2 > maxRow )
  83.                 maxRow = w->row2;
  84.         }
  85.         if( w == lastW )
  86.             break;
  87.         w = w->nextWindow;
  88.     }
  89.     if( maxRow != -1 )
  90.         updateScreen(minRow, maxRow);
  91. }
  92.  
  93. void pascal
  94. /* XTAG:updateTops */
  95. updateTops(fileId, cp, len)
  96.     int fileId;
  97.     long cp, len;
  98. {
  99.     extern unsigned char msgBuffer[];
  100.     extern struct window *windowList;
  101.     extern int debug;
  102.  
  103.     register struct window *w;
  104.     struct window *lastW;
  105.     int n;
  106.     long cp1;
  107.  
  108.     lastW = NULL;
  109.     w = windowList;
  110.     while( w != NULL ) {
  111.         if( w->fileId == fileId )
  112.             lastW = w;
  113.         w = w->nextWindow;
  114.     }
  115.     /* adjust the data of the affected windows */
  116.     w = windowList;
  117.     while( 1 ) {
  118.         if( w->fileId == fileId ) {
  119.             if( cp >= w->posBotline )
  120.                 goto nextWindow;
  121.             else
  122.                 w->posBotline += len;
  123.             if( cp < w->posTopline ) {
  124.                 cp1 = w->posTopline + len;
  125.                 /* a delete overlapping this window? */
  126.                 if( cp1 < cp ) {
  127.                     n = -1;
  128.                     cp1 = prevLine(w->fileId, cp, &n);
  129.                 }
  130.                 /* recalculate the line number by letting */
  131.                 /* prevLine count as far back as it can */
  132.                 n = 30000;
  133.                 prevLine(w->fileId, cp1, &n);
  134.                 w->numTopline = n + 1;
  135.                 w->posTopline = cp1;
  136.             }
  137.         }
  138.     nextWindow:
  139.         if( w == lastW )
  140.             break;
  141.         w = w->nextWindow;
  142.     }
  143. }
  144.  
  145. void pascal
  146. /* XTAG:exchWithScrap */
  147. exchWithScrap()
  148. {
  149.     extern unsigned char msgBuffer[];
  150.     extern struct changeItem scrapBuffer;
  151.     extern struct changeItem *change;
  152.     extern int nextChange;
  153.     extern long selBegin, selEnd;
  154.     extern struct window *selWindow;
  155.     extern struct openFile *files;
  156.     extern unsigned char *userMessages[];
  157.  
  158.     long length;
  159.     register struct changeItem *thisChange;
  160.     struct piece *firstPiece;
  161.  
  162.     /* check if this is a readOnly file */
  163.     if( files[selWindow->fileId].readOnly ) {
  164.         sprintf(msgBuffer, userMessages[READONLYFILE],
  165.             files[selWindow->fileId].origName);
  166.         msg(msgBuffer, 1);
  167.         return;
  168.     }
  169.  
  170.     /* remember what was in the scrap */
  171.     firstPiece = scrapBuffer.firstPiece;
  172.     length = scrapBuffer.length;
  173.     /* prevent this from getting freed when the scrap buffer is reused */
  174.     scrapBuffer.firstPiece = NULL;
  175.     
  176.     /* move the selection into the scrap */
  177.     deleteChars(selWindow->fileId, NOUPDATE, 1);
  178.  
  179.     /* record in the change history */
  180.     IncrementNextChange();
  181.     thisChange = &change[nextChange];
  182.     thisChange->type = CINSERT;
  183.     thisChange->position = selBegin;
  184.     thisChange->length = length;
  185.     thisChange->fileId = selWindow->fileId;
  186.     thisChange->firstPiece = firstPiece;
  187.  
  188.     /* copy the old scrap into the file */
  189.     copyPieces(firstPiece, selWindow, selBegin, length, 1);
  190.     
  191.     /* free the scrap pieces */
  192.     freePieces(firstPiece);
  193. }
  194.  
  195. void pascal
  196. /* XTAG:copyToScrap */
  197. copyToScrap(fromWindow, fromBegin, fromEnd)
  198.     struct window *fromWindow;
  199.     long fromBegin, fromEnd;
  200. {
  201.     extern unsigned char msgBuffer[];
  202.     extern struct changeItem scrapBuffer;
  203.     extern long addPosition;
  204.     extern int selMode;
  205.     extern int scrapMode;
  206.  
  207.     int fromId;
  208.     long fb, copyLength;
  209.     register struct piece *tempPP;
  210.  
  211.     fromId = fromWindow->fileId;
  212.     
  213.     /* eliminate the EOF marker from the selection */
  214.     fb = fileSize(fromId);
  215.     if( fromEnd >= fb ) {
  216.         if( fromBegin < fb )
  217.             fromEnd = fb-1;
  218.         else    /* only the EOF symbol is selected */
  219.             return;
  220.     }
  221.     copyLength = fromEnd - fromBegin + 1;
  222.  
  223.     /* free the old scrap buffer pieces */
  224.     freePieces(scrapBuffer.firstPiece);
  225.  
  226.     /* record in the scrap buffer */
  227.     scrapBuffer.type = 1;
  228.     scrapBuffer.length = copyLength;
  229.     tempPP = getFreePiece();
  230.     scrapBuffer.firstPiece = tempPP;
  231.     scrapMode = selMode;
  232.  
  233.     tempPP->file = ADDFILE;
  234.     tempPP->position = addPosition;
  235.     fb = fromBegin;
  236.     while( fb <= fromEnd ) {
  237.         writeChar( readChar(fromId, fb++), addPosition++);
  238.     }
  239.     tempPP->length = copyLength;
  240. }
  241.  
  242. void pascal
  243. /* XTAG:insScrap */
  244. insScrap(doInsert)
  245.     int doInsert;
  246. {
  247.     extern unsigned char msgBuffer[];
  248.     extern struct window *selWindow;
  249.     extern long selBegin, selEnd;
  250.     extern struct changeItem scrapBuffer;
  251.     extern long addPosition;
  252.     extern struct openFile *files;
  253.     extern struct changeItem *change;
  254.     extern int nextChange;
  255.      extern int selMode;
  256.     extern int scrapMode;
  257.     extern int maxFiles;
  258.     extern unsigned char *userMessages[];
  259.  
  260.     long limit, logByte;
  261.     struct piece *tempPP, *oldScrap;
  262.     register struct openFile *ff;
  263.     register struct changeItem *thisChange;
  264.  
  265.     /* check if this is a readOnly file */
  266.     if( files[selWindow->fileId].readOnly ) {
  267.         sprintf(msgBuffer, userMessages[READONLYFILE],
  268.             files[selWindow->fileId].origName);
  269.         msg(msgBuffer, 1);
  270.         return;
  271.     }
  272.  
  273.     /* See if the text in the scrap buffer is in an edit file rather */
  274.     /* then in the add file.  If it is we need to copy it to the add */
  275.     /* file. */
  276.     if( !scrapBuffer.type ) {
  277.         /* keep a pointer to the old piece list */
  278.         oldScrap = scrapBuffer.firstPiece;
  279.         /* scrapBuffer.length will not change */
  280.         
  281.         /* get a new piece and initialize the fields */
  282.         tempPP = getFreePiece();
  283.         tempPP->file = ADDFILE;
  284.         tempPP->position = addPosition;
  285.         tempPP->length = scrapBuffer.length;
  286.         
  287.         /* this will be the new scrapBuffer piece list */
  288.         scrapBuffer.type = 1;  /* now it is addFile only type */
  289.         scrapBuffer.firstPiece = tempPP;
  290.         
  291.         /* Now copy the characters into the add file */
  292.         logByte = 0;
  293.         limit = scrapBuffer.length;
  294.         /* simulate a file this was deleted from */
  295.         ff = &files[maxFiles];
  296.         ff->hiLogBuffer = -1;
  297.         ff->origHandle = scrapBuffer.fileId;
  298.         ff->fileSize = limit;
  299.         ff->logPiece = oldScrap;
  300.         ff->loLogPiece = 0;
  301.         ff->hiLogPiece = oldScrap->length - 1;
  302.         while( logByte < limit ) {
  303.             /* copy the characters in pp to the add file */
  304.             writeChar( readChar(maxFiles, logByte++),
  305.                 addPosition++);
  306.         }
  307.         
  308.         freePieces(oldScrap);  /* free the old piece chain */
  309.     }
  310.     if( doInsert ) {
  311.         /* record in the change history */
  312.         IncrementNextChange();
  313.         thisChange = &change[nextChange];
  314.         thisChange->type = CCOPY;
  315.         selMode = scrapMode;
  316.         selBegin = adjustSelMode(selWindow->fileId, selBegin);
  317.         thisChange->position = selBegin;
  318.         thisChange->length = scrapBuffer.length;
  319.         thisChange->fileId = selWindow->fileId;
  320.         thisChange->firstPiece = dupPieces(scrapBuffer.firstPiece);
  321.  
  322.         copyPieces(scrapBuffer.firstPiece, selWindow, selBegin,
  323.             scrapBuffer.length, 1);
  324.     }
  325. }
  326.  
  327. void pascal
  328. /* XTAG:copyMove */
  329. copyMove(fromWindow, fromBegin, fromEnd, toWindow, toPosition, mode)
  330.     struct window *fromWindow, *toWindow;
  331.     long fromBegin, fromEnd, toPosition;
  332.     int mode;
  333. {
  334.     extern unsigned char msgBuffer[];
  335.     extern struct openFile *files;
  336.     extern long selBegin, selEnd;
  337.     extern struct window *selWindow;
  338.     extern struct changeItem *change;
  339.     extern int nextChange;
  340.     extern int addHandle;
  341.     extern long addPosition;
  342.     extern unsigned char *userMessages[];
  343.  
  344.     int n, fromId, toId;
  345.     long  fb, copyLength;
  346.     register struct piece *tempPP;
  347.     register struct changeItem *thisChange;
  348.  
  349.     /* check if this is a readOnly file */
  350.     if( files[toWindow->fileId].readOnly ) {
  351.         sprintf(msgBuffer, userMessages[READONLYFILE],
  352.             files[toWindow->fileId].origName);
  353.         msg(msgBuffer, 1);
  354.         return;
  355.     }
  356.  
  357.     /* Is this a move with source and destination ovelapping? */
  358.     if( mode==MOVE && fromBegin<=toPosition && toPosition<=fromEnd
  359.       && fromWindow==toWindow ) {
  360.         msg("Cannot move text into itself", 2);
  361.         return;
  362.     }
  363.  
  364.     fromId = fromWindow->fileId;
  365.     toId = toWindow->fileId;
  366.  
  367.     /* eliminate the EOF marker from the selection */
  368.     fb = fileSize(fromId);
  369.     if( fromEnd >= fb ) {
  370.         if( fromBegin < fb )
  371.             fromEnd = fb-1;
  372.         else    /* only the EOF symbol is selected */
  373.             return;
  374.     }
  375.     copyLength = fromEnd - fromBegin + 1;
  376.  
  377.     /* record in the change history */
  378.     IncrementNextChange();
  379.     thisChange = &change[nextChange];
  380.     if( mode == COPY )
  381.         thisChange->type = CCOPY;
  382.     else
  383.         thisChange->type = CMOVE;
  384.     thisChange->position = toPosition;
  385.     thisChange->length = copyLength;
  386.     thisChange->fileId = toId;
  387.     tempPP = getFreePiece();
  388.     thisChange->firstPiece = tempPP;
  389.  
  390.     tempPP->file = ADDFILE;
  391.     tempPP->position = addPosition;
  392.     fb = fromBegin;
  393.     while( fb <= fromEnd ) {
  394.         writeChar( readChar(fromId, fb++), addPosition++);
  395.     }
  396.     tempPP->length = copyLength;
  397.  
  398.     /* if it is a move, then delete the from text */
  399.     if( mode == MOVE ) {
  400.         selWindow = fromWindow;
  401.         selBegin = fromBegin;
  402.         selEnd = fromEnd;
  403.         if( fromWindow == toWindow )
  404.             n = NOUPDATE;
  405.         else
  406.             n = UPDATEWINDOWS;
  407.         deleteChars(fromWindow->fileId, n, 1);
  408.         /* if we deleted text before the toPosition we have */
  409.         /* to adjust it since the logical text positions change */
  410.         /* after a delete.  We also fix up the position on the */
  411.         /* delete following so it will look like it really did */
  412.         /* take place AFTER the copying in of the moved text */
  413.         if( fromWindow->fileId == toWindow->fileId ) {
  414.             if( toPosition > fromBegin )
  415.                 toPosition -= copyLength;
  416.             else
  417.                 change[nextChange].position += copyLength;
  418.         }
  419.     }
  420.  
  421.     copyPieces(thisChange->firstPiece, toWindow, toPosition, copyLength,
  422.         1);
  423. }
  424.  
  425. void pascal
  426. /* XTAG:copyPieces */
  427. copyPieces(fromPP, toWindow, toPosition, copyLength, update)
  428.     struct piece *fromPP;
  429.     struct window *toWindow;
  430.     long toPosition, copyLength;
  431.     int update;
  432. {
  433.     extern unsigned char msgBuffer[];
  434.     extern struct openFile *files;
  435.     extern long selBegin, selEnd;
  436.     extern int selMode;
  437.     extern struct window *selWindow;
  438.     extern struct changeItem *change;
  439.     extern int nextChange;
  440.     extern int addHandle;
  441.     extern long addPosition;
  442.  
  443.     int toId;
  444.     long offset, toNN;
  445.     register struct piece *nextPP, *toPP, *lastPP;
  446.     register struct openFile *toFF;
  447.     struct piece *pp2;
  448.     struct window *w;
  449.  
  450.     if( update ) {
  451.         /* just using these variables to save the selection */
  452.         offset = selBegin;
  453.         toNN = selEnd;
  454.         w = selWindow;
  455.         selBegin = selEnd = toPosition;
  456.         selWindow = toWindow;
  457.         selBegin = offset;
  458.         selEnd = toNN;
  459.         selWindow = w;
  460.     }
  461.     
  462.     /* This is a special case to handle a backspace problem.  To wit, */
  463.     /* if we delete text and type in new text, then select other text */
  464.     /* and REDO, then the piece from the first change is copied in. */
  465.     /* If we then backspace and type a new character, the piece itself */
  466.     /* is changed and so the orignal edit is changed also.  We have to */
  467.     /* prevent this so we bump addPosition in this case so the */
  468.     /* backspace does not change the piece */
  469.     /* A BETTER SOLUTION would be to make an actual copy of the text */
  470.     /* in the piece.  This would allow further editing that would then */
  471.     /* be able to be repeated again. */
  472.     toPP = fromPP;        /* just using toPP as a convenient variable */
  473.     while( toPP->nextPiece != NULL )
  474.         toPP = toPP->nextPiece;
  475.     if( (toPP->file == ADDFILE)
  476.      && (toPP->position+toPP->length == addPosition) )
  477.          ++addPosition;
  478.         
  479.     /* compute some values for later efficiency */
  480.     toId = toWindow->fileId;
  481.     toFF = &files[toId];
  482.  
  483.     /* find out what piece 'toBegin' is in */
  484.     toPP = findPiece(toPosition, toFF, &toNN);
  485.     /* special case for the end of the file */
  486.     if( toPosition > toFF->fileSize ) {
  487.         /* leave toPP as the last piece in the file */
  488.         nextPP = NULL;
  489.     } else if( toPosition > toNN ) {
  490.         /* copied text starts inside piece "toPP" */
  491.         /* We split toPP into two pieces (toPP and nextPP) */
  492.         /* at toPosition */
  493.         /* get a new piece */
  494.         nextPP = getFreePiece();
  495.         /* link the new piece in before the piece after toPP */
  496.         pp2 = toPP->nextPiece;
  497.         nextPP->nextPiece = pp2;
  498.         if( pp2 != NULL )
  499.             pp2->prevPiece = nextPP;
  500.         /* adjust the fields of the two pieces */
  501.         offset = toPosition - toNN;
  502.         nextPP->file = toPP->file;
  503.         nextPP->position = toPP->position + offset;
  504.         nextPP->length = toPP->length - offset;
  505.         toPP->length = offset;
  506.     } else {
  507.         nextPP = toPP;
  508.         toPP = toPP->prevPiece;
  509.     }
  510.     
  511.     /* now copy the pieces into the piece list between toPP and nextPP */
  512.     lastPP = toPP;
  513.     while( fromPP != NULL ) {
  514.         pp2 = getFreePiece();
  515.         /* copy the information into the new piece */
  516.         pp2->file = fromPP->file;
  517.         pp2->position = fromPP->position;
  518.         pp2->length = fromPP->length;
  519.         /* link in the new piece */
  520.         pp2->prevPiece = lastPP;
  521.         /* link it into the list */
  522.         if( lastPP != NULL )
  523.             lastPP->nextPiece = pp2;
  524.         else /* new first item on the list */
  525.             toFF->pieceList = pp2;
  526.         /* move to the next piece to copy */
  527.         lastPP = pp2;
  528.         fromPP = fromPP->nextPiece;
  529.     }
  530.     lastPP->nextPiece = nextPP;
  531.     if( nextPP != NULL )
  532.         nextPP->prevPiece = lastPP;
  533.  
  534.     /* make the cached piece the one after the copied pieces */
  535.     /* unless it is NULL */
  536.     if( nextPP != NULL ) {
  537.         toFF->logPiece = nextPP;
  538.         toFF->loLogPiece = toPosition + copyLength;
  539.         toFF->hiLogPiece = toFF->loLogPiece + nextPP->length - 1;
  540.     } else {    /* make it the first piece in the file */
  541.         toFF->logPiece = toFF->pieceList;
  542.         toFF->loLogPiece = 0;
  543.         toFF->hiLogPiece = toFF->loLogPiece
  544.                     + (toFF->logPiece)->length - 1;
  545.     }
  546.  
  547.     /* update the length of the "to" file */
  548.     toFF->fileSize += copyLength;
  549.  
  550.     /* invalidate the buffer cache of the "to" file */
  551.     toFF->hiLogBuffer = -1L;
  552.  
  553.     /* record the fact that the file has changed */
  554.     toFF->isChanged = 1;
  555.  
  556.     /* invalidate the last-row-found cache */
  557.     if( toWindow->posCurLast > toPosition )
  558.         toWindow->lastPosTop = -1;
  559.     
  560.     /* make the selection the character past the copied text */
  561.     if( selWindow != toWindow ) {
  562.         eraseSelection();
  563.         selWindow = toWindow;
  564.     }
  565.     selEnd = selBegin = toPosition + copyLength;
  566.     if( readChar(toId, selBegin) == '\r' ) {
  567.         if( readChar(toId, selBegin + 1) == '\n' )
  568.             ++selEnd;
  569.     }
  570.     /* change selection mode to character mode */
  571.     selMode = SELCHAR;
  572.     if( update )
  573.         updateFile(toId, toPosition, copyLength, 0);
  574. }
  575.