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

  1. #include "pt.h"
  2. #include "memory.h"
  3. #include "malloc.h"
  4. #include "string.h"
  5. #include "direct.h"
  6. #include "io.h"
  7. #include "process.h"
  8. #include "conio.h"
  9.  
  10. extern struct openFile *files;
  11. extern struct diskBuffer *buffers;
  12. extern struct diskBuffer *bufHash[];
  13. extern nextBuffer;
  14.  
  15. void pascal
  16. /* XTAG:initFileio */
  17. initFileio()
  18. {
  19.     extern unsigned char msgBuffer[];
  20.     extern struct piece *freePList;
  21.     extern struct piece pieceTable[];
  22.     extern unsigned char *bufferSpace;
  23.     extern int nBuffers;
  24.     extern unsigned int piecesLeft;
  25.     extern unsigned int bytesLeft;
  26.     extern unsigned int maxFiles;
  27.     extern unsigned int debug;
  28.     extern unsigned char *userMessages[];
  29.     
  30.     register int i;
  31.     unsigned short segIncrement, *segPointer;
  32.     long size;
  33.     unsigned char huge *bs;
  34.  
  35.     for(i = 0; i < maxFiles; i++) {
  36.         files[i].origHandle = -1;
  37.     }
  38.  
  39.     /* set up the buffer hash scheme */
  40.     for(i = 0; i < NBUFHASH; i++)
  41.         bufHash[i] = NULL;
  42.     nextBuffer = -1;
  43.  
  44.     /* allocate the space (out of this address space) for the buffers */
  45. retryAllocation:
  46.     size = (long)BUFFERSIZE * (long)nBuffers;
  47.     bs = halloc(size, 1);
  48.     if( bs == 0L ) {
  49.         /* if there is not enough space, try fewer buffers */
  50.         if( nBuffers >= 25 ) {
  51.             nBuffers -= 20;
  52.             goto retryAllocation;
  53.         }
  54.         size -= (unsigned)16*(unsigned)i;
  55.         cprintf(userMessages[NOBUFFERMEMORY], size);
  56.         exit(1);
  57.     }
  58.  
  59.     /* set up each buffer header to the segment address of the */
  60.     /* allocated buffer. Buffer i is at buffers[i].bufferAddress  */
  61.     segIncrement = (unsigned short)(BUFFERSIZE / 16);
  62.     for(i = 0; i < nBuffers; i++) {
  63.         buffers[i].handle = -1;
  64.         buffers[i].bufferAddress = (unsigned char far *)bs;
  65.         /***bs += BUFFERSIZE;***/
  66.         /* move the segment part of the address up */
  67.         segPointer = ((unsigned short *)(&bs)) + 1;
  68.         *segPointer += segIncrement;
  69.     }
  70.     
  71.     /* set up the free piece list */
  72.     freePList = NULL;
  73.     piecesLeft = 0;
  74.     bytesLeft = _memavl();
  75. }
  76.  
  77. int pascal
  78. /* XTAG:getFileId */
  79. getFileId(origName)
  80.     unsigned char *origName;
  81. {
  82.     extern unsigned char msgBuffer[];
  83.     extern unsigned char scratchFileName[];
  84.     extern int addHandle;
  85.     extern int readOnly;
  86.     extern int maxFiles;
  87.     extern int supressFileMsgs;
  88. #ifdef OVERLAYS
  89.     extern int filesToOpen;
  90.     extern struct openFile *ffsToOpen[];
  91. #endif
  92.     extern unsigned char *userMessages[];
  93.  
  94.     int fileNumber, origHandle;
  95.     int freeFileId;
  96.     long size;
  97.     register struct piece *pp;
  98.     register struct openFile *ff;
  99.     unsigned char *fullFilename;
  100.  
  101.     if( origName == NULL ) {
  102.         scratchFileName[0] = '\0';
  103.         fullFilename = &scratchFileName[0];
  104.     } else
  105.         fullFilename = makeFullPathname(origName);
  106.  
  107.     /* find a free file structure */
  108.     freeFileId = -1;
  109.     for(fileNumber = 0; fileNumber < maxFiles; fileNumber++) {
  110.         if( files[fileNumber].origHandle == -1 ) {
  111.             if( freeFileId == -1 )
  112.                 freeFileId = fileNumber;
  113.         } else if(
  114.             strcmpi(files[fileNumber].origName, fullFilename)
  115.                                 == 0 ) {
  116.             ++(files[fileNumber].useCount);
  117.             return fileNumber;
  118.         }
  119.     }
  120.     if( freeFileId == -1 ) {
  121.         msg(userMessages[OUTOFFILESTRUCT], 3);
  122.         return -1;
  123.     } else
  124.         fileNumber = freeFileId;
  125.  
  126.     /* open the original file */
  127.     ff = &files[fileNumber];
  128.     strncpy(ff->origName, fullFilename, FILENAMESIZE);
  129.     
  130.     if( fullFilename[0] == '\0' ) {
  131.         origHandle = addHandle;
  132.     } else {
  133.         origHandle = openls(fullFilename, 0);
  134.  
  135.         if( origHandle == -4 ) {
  136.             if( supressFileMsgs < 2 )
  137.                 msg(userMessages[HANDLEMSG], 3);
  138.             if( supressFileMsgs == 1 )
  139.                 supressFileMsgs = 2;
  140.             return -1;
  141.         } else if( origHandle < 0 ) {
  142.             sprintf(msgBuffer, userMessages[CANNOTOPEN],
  143.                 fullFilename);
  144.             msg(msgBuffer, 3);
  145.             return -1;
  146.         }
  147.  
  148. #ifdef OVERLAYS
  149.         /* see if we were called from an overlay any have to */
  150.         /* reopen the file after the overlay completes */
  151.         if( filesToOpen > 0 ) {
  152.             ffsToOpen[filesToOpen-1] = ff;
  153.             ++filesToOpen;
  154.         }
  155. #endif
  156.     }
  157.     ff->origHandle = origHandle;
  158.  
  159.     /* initialize the other fields */
  160.     if( origHandle != addHandle ) {
  161.         size = lseekls(origHandle, 0L, 2);
  162.         lseekls(origHandle, 0L, 0);
  163.     } else
  164.         size = 0;
  165.     ff->fileSize = size;
  166.     ff->origFileSize = size;
  167.     ff->useCount = 1;
  168.     ff->bakMade = 0;
  169.     ff->isChanged = 0;    /* has not been edited yet */
  170.     if( readOnly )
  171.         ff->readOnly = 1;
  172.     else if( origHandle == addHandle ) {
  173.         ff->readOnly = 0;
  174.     } else {
  175.         /* check for read and write permissions (6 => RW) */
  176.         /* edit in readOnly mode if the DOS file permissions */
  177.         /* do not allow writing the file */
  178.         ff->readOnly = (unsigned char)!(access(ff->origName, 6) == 0);
  179.     }
  180.  
  181.     /* initialize the piece table */
  182.     pp = getFreePiece();
  183.     pp->file = ORIGFILE;
  184.     pp->position = 0;
  185.     pp->length = size;
  186.     ff->pieceList = pp;
  187.  
  188.     /* initialize the optimization fields */
  189.     ff->loLogPiece = 0;
  190.     ff->hiLogPiece = size - 1;
  191.     ff->logPiece = pp;
  192.     ff->hiLogBuffer = -1L;
  193.     ff->logBufSegment = NULL;
  194.     ff->logBufOffset = NULL;
  195.  
  196.     /*return the fileId */
  197.     return fileNumber;
  198. }
  199.  
  200. void pascal
  201. /* XTAG:saveFile */
  202. saveFile(w)
  203.     struct window *w;
  204. {
  205.     extern unsigned char msgBuffer[];
  206.     extern struct openFile *files;
  207.     extern int addHandle;
  208. #ifdef OVERLAYS
  209.     extern int filesToOpen;
  210.     extern struct openFile *ffsToOpen[];
  211. #endif
  212.     extern unsigned char *userMessages[];
  213.  
  214.     register struct openFile *ff;
  215.     unsigned char *tempFile, *p;
  216.     int i;
  217.     long size;
  218.     struct piece *pp;
  219.  
  220.     ff = &files[w->fileId];
  221.     
  222.     if( ff->readOnly ) {
  223.         sprintf(msgBuffer, userMessages[READONLYFILE], ff->origName);
  224.         msg(msgBuffer, 3);
  225.         return;
  226.     }
  227.  
  228.     tempFile = makeTempFor(ff->origName);
  229.     sprintf(msgBuffer, userMessages[WRITINGFILE], ff->origName,
  230.         ff->fileSize);
  231.     msg(msgBuffer, 1);
  232.  
  233.     if( !doWrite(w->fileId, tempFile) )
  234.         return;
  235.  
  236.     sprintf(msgBuffer, userMessages[FILEWRITTEN], ff->origName,
  237.         ff->fileSize);
  238.     msg(msgBuffer, 1);
  239.  
  240.     /* invalidate any buffers allocated to this open file */
  241.     fidInvalid(ff->origHandle);
  242.     ff->hiLogBuffer = -1L;
  243.  
  244.     /* reset the change flag */
  245.     ff->isChanged = 0;
  246.  
  247.     /* close the original file for this open file */
  248.     if( ff->origHandle != addHandle ) {
  249.         i = closels(ff->origHandle);
  250.         if( i != 0 ) {
  251.             sprintf(msgBuffer, userMessages[CLOSEFAILED],
  252.                 ff->origName, i);
  253.             msg(msgBuffer, 3);
  254.         }
  255.     }
  256.  
  257.     if( !ff->bakMade ) {
  258.         /* generate the .bak name and rename the original file */
  259.         /* rename the temporary file we copied it into */
  260.         p = makeBak(ff->origName);
  261.         delete(p);    /* make sure any old .bak file is deleted */
  262.         if( renamels(ff->origName, p) ) {
  263.             sprintf(msgBuffer, userMessages[RENAMEFAILED],
  264.                 ff->origName, p, tempFile);
  265.             msg(msgBuffer, 3);
  266.         }
  267.         ff->bakMade = 1;
  268.     } else {
  269.         if( delete(ff->origName) ) {
  270.             sprintf(msgBuffer, userMessages[DELETEFAILED],
  271.                 ff->origName, tempFile);
  272.             msg(msgBuffer, 3);
  273.         }
  274.     }
  275.  
  276.     if( renamels(tempFile, ff->origName) ) {
  277.         sprintf(msgBuffer, userMessages[RENAMEFAILED2],
  278.             tempFile, ff->origName, ff->origName, tempFile);
  279.         msg(msgBuffer, 3);
  280.     }
  281.  
  282.     /* open it up again */
  283.     if( ff->origHandle != addHandle )
  284.         ff->origHandle = openls(ff->origName, 0);
  285.  
  286. #ifdef OVERLAYS
  287.     /* see if we were called from an overlay any have to reopen */
  288.     /* the file after the overlay completes */
  289.     if( filesToOpen > 0 ) {
  290.         ffsToOpen[filesToOpen-1] = ff;
  291.         ++filesToOpen;
  292.     }
  293. #endif
  294.  
  295.     /* re-initialize the other fields */
  296.     size = lseekls(ff->origHandle, 0L, 2);
  297.     ff->fileSize = size;
  298.     ff->origFileSize = size;
  299.     lseekls(ff->origHandle, 0L, 0);
  300.     
  301.     /* free all the pieces */
  302.     freePieces(ff->pieceList);
  303.  
  304.     /* re-initialize the piece table */
  305.     pp = getFreePiece();
  306.     ff->pieceList = pp;
  307.     pp->file = ORIGFILE;
  308.     pp->position = 0;
  309.     pp->length = size;
  310.  
  311.     /* re-initialize the optimization fields */
  312.     ff->loLogPiece = 0;
  313.     ff->hiLogPiece = size - 1;
  314.     ff->logPiece = pp;
  315.     ff->hiLogBuffer = -1L;
  316.     ff->logBufSegment = NULL;
  317.     ff->logBufOffset = NULL;
  318. }
  319.  
  320. unsigned char * pascal
  321. /* XTAG:makeBak */
  322. makeBak(s)
  323.     unsigned char *s;
  324. {
  325.     static unsigned char name[64];
  326.     register int i;
  327.     int len;
  328.  
  329.     /* find the extension (if there is one) */
  330.     len = strlen(s);
  331.     for(i = len - 1; i > 0 && s[i] != '.' && s[i] != '\\'; --i)
  332.         ;
  333.     if( s[i] != '.' )
  334.         /* if no extension then put the .bak at the end */
  335.         i = len;
  336.  
  337.     /* compose the name */
  338.     strcpy(name, s);
  339.     name[i] = '.';
  340.     name[++i] = 'b';
  341.     name[++i] = 'a';
  342.     name[++i] = 'k';
  343.     name[++i] = '\0';
  344.     return &name[0];
  345. }
  346.  
  347. void pascal
  348. /* XTAG:writeFile */
  349. writeFile(w)
  350.     struct window *w;
  351. {
  352.     extern struct openFile *files;
  353.     extern unsigned char msgBuffer[];
  354.     extern unsigned char textBuffer[];
  355.     extern unsigned char *userMessages[];
  356.  
  357.     unsigned char *tempFile;
  358.  
  359.     tempFile = getInput("File name to write to: ", "", 0);
  360.     if( tempFile == NULL ) {
  361.     cancel:
  362.         msg(userMessages[WRITECANCELLED], 1);
  363.         return;
  364.     }
  365.  
  366.     /* check if the file already exists */
  367.     if( access(tempFile, 0) == 0 ) {
  368.         strcpy(textBuffer, tempFile);
  369.         sprintf(msgBuffer, userMessages[FILEEXISTS], tempFile);
  370.         tempFile = getInput(msgBuffer, "n", 1);
  371.         if( tolower(*tempFile) != 'y' )
  372.             goto cancel;
  373.         tempFile = textBuffer;
  374.     }
  375.  
  376.     sprintf(msgBuffer, userMessages[WRITINGFILE],
  377.         tempFile, files[w->fileId].fileSize);
  378.     msg(msgBuffer, 1);
  379.  
  380.     if( !doWrite(w->fileId, tempFile) )
  381.         return;
  382.  
  383.     sprintf(msgBuffer, userMessages[FILEWRITTEN],
  384.         tempFile, files[w->fileId].fileSize);
  385.     msg(msgBuffer, 1);
  386. }
  387.  
  388. int pascal
  389. /* XTAG:doWrite */
  390. doWrite(fileId, tempFile)
  391.     int fileId;
  392.     unsigned char *tempFile;
  393. {
  394.     extern unsigned char msgBuffer[];
  395.     extern struct SREGS segRegs;
  396.     extern unsigned char *userMessages[];
  397.  
  398.     long cp, fSize;
  399.     int fid, iBuffer, lineSize, n;
  400.     unsigned char far *firstByte;
  401.     unsigned char far *lastByte;
  402.     unsigned char far *sBuffer;
  403.     unsigned int sizeOfBuffer;
  404.  
  405. fSize = fileSize(fileId);
  406.  
  407. /* open the output file */
  408. fid = creatls(tempFile, 0);
  409. if( fid == -4 ) {
  410.     msg(userMessages[HANDLEMSG], 3);
  411.     return 0;
  412. } else if( fid == -97 ) {
  413.     msg(userMessages[WRITEFAILED], 3);
  414.     return 0;
  415. } else if( fid < 0 ) {
  416.     sprintf(msgBuffer, userMessages[CREATEFAILED], tempFile, fid);
  417.     msg(msgBuffer, 3);
  418.     return 0;
  419. }
  420.  
  421. /* allocate the IO buffer */
  422. sizeOfBuffer = 4096;
  423. while( 1 ) {
  424.     sBuffer = _fmalloc(sizeOfBuffer);
  425.     if( sBuffer == 0L ) {
  426.         /* try again with a buffer half as large */
  427.         sizeOfBuffer >>= 1;
  428.         if( sizeOfBuffer < 64 ) {
  429.             msg(userMessages[NOSPACEMSG], 3);
  430.             return 0;
  431.         }
  432.         continue;
  433.     } else
  434.         break;
  435. }
  436.  
  437. cp = 0;
  438. iBuffer = 0;
  439. while( 1 ) {
  440.     /* special case for files of length 0 */
  441.     if( fSize == 0 )
  442.         fSize = 1;
  443.     sprintf(msgBuffer, userMessages[WRITEPROGRESS],
  444.         (int)( (100*cp) / fSize) );
  445.     msg(msgBuffer, 1);
  446.     if( getSpan(fileId, cp, &firstByte, &lastByte, 0) )
  447.         break;
  448.     lineSize = (int)(lastByte - firstByte + 1);
  449.     cp = cp + lineSize;
  450.  
  451.     if( (iBuffer+lineSize) >= sizeOfBuffer ) {/* will it fit? */
  452.         /* no, so write out the buffer to empty it */
  453.         if( (n = writeFar(fid, sBuffer, iBuffer)) < iBuffer ) {
  454. error:
  455.             _ffree(sBuffer);
  456.             /* avoid recursive calls if msg tries to write disk */
  457.             msg(userMessages[FULLMSG], 3);
  458.             closels(fid);
  459.             delete(tempFile);
  460.             return 0;
  461.         } else
  462.             iBuffer = 0;
  463.     }
  464.     movedata(FP_SEG(firstByte), FP_OFF(firstByte), FP_SEG(sBuffer),
  465.         FP_OFF(sBuffer)+iBuffer, (unsigned)lineSize);
  466.     iBuffer += lineSize;
  467. }
  468. if( (n = writeFar(fid, sBuffer, iBuffer)) < iBuffer )
  469.     goto error;
  470. closels(fid);
  471.  
  472. /* all is ok */
  473. _ffree(sBuffer);
  474. return 1;
  475. }
  476.  
  477. unsigned char * pascal
  478. /* XTAG:makeTempFor */
  479. makeTempFor(name)
  480.     unsigned char *name;
  481. {
  482.     static unsigned char tname[64];
  483.     register int len;
  484.     int pathEnd;
  485.     unsigned char ch;
  486.  
  487.     len = 0;
  488.     pathEnd = -1;
  489.     while( 1 ) {
  490.         if( (ch = name[len]) == '\0' )
  491.             break;
  492.         tname[len] = ch;
  493.         switch( ch ) {
  494.         case '/':
  495.         case '\\':
  496.         case ':':
  497.             pathEnd = len;
  498.         }
  499.         ++len;
  500.     }
  501.     tname[pathEnd+1] = '\0';
  502.     strcat(tname, "tempfile.pt");
  503.     return &tname[0];
  504. }
  505.  
  506. long pascal
  507. /* XTAG:fileSize */
  508. fileSize(fileNumber)
  509.     int fileNumber;
  510. {
  511.     return files[fileNumber].fileSize;
  512. }
  513.  
  514. int pascal
  515. /* XTAG:closeFile */
  516. closeFile(fileId, ask)
  517.     int fileId, ask;
  518. {
  519.     extern unsigned char msgBuffer[];
  520.     extern struct changeItem scrapBuffer;
  521.     extern int addHandle;
  522.     extern unsigned char *userMessages[];
  523.  
  524.     int i, writing;
  525.     unsigned char *s, *tempFile;
  526.     register struct openFile *ff;
  527.  
  528.     if( fileId == -1 )
  529.         return 0;
  530.  
  531.     ff = &files[fileId];
  532.  
  533.     /* is this the last close? */
  534.     if( --(ff->useCount) > 0 )
  535.         return 0;
  536.  
  537.     /* see if we need to write the file */
  538.     writing = 1;
  539.     /* has the file changed? */
  540.     if( ff->pieceList->nextPiece == NULL
  541.      && ff->pieceList->file == ORIGFILE ) {
  542.         if( ff->fileSize == ff->origFileSize ) 
  543.             writing = 0;
  544.     }
  545.     if( ask == 2 )    /* quit and discard mode */
  546.         writing = 0;
  547.     /* do not write the messages file into itself */
  548.     if( ff->origHandle == addHandle )
  549.         writing = 0;
  550.     /* see if we already saved these changes */
  551.     if( !(ff->isChanged) )
  552.         writing = 0;
  553.     if( writing && ff->readOnly ) {
  554.         sprintf(msgBuffer, userMessages[WASREADONLY], ff->origName);
  555.         s = getInput(msgBuffer, "", 1);
  556.         if( s == NULL )
  557.             return -1;
  558.         writing = 0;
  559.     }
  560.     if( writing ) {
  561.         while( 1 ) {
  562.             /* default place for s to point if no-ask mode */
  563.             s = (unsigned char *)&i;
  564.             if( ask ) {
  565.                 sprintf(msgBuffer, userMessages[YTOSAVE],
  566.                   ff->origName);
  567.                 s = getInput(msgBuffer, "y", 1);
  568.                 if( s == NULL ) {
  569.                     msg(userMessages[CLOSECANCELLED], 1);
  570.                     ++(ff->useCount);
  571.                     return -1;
  572.                 }
  573.             } else
  574.                 s[0] = 'y';
  575.             if( tolower(s[0]) == 'y' ) {
  576.                 tempFile = makeTempFor(ff->origName);
  577.                 sprintf(msgBuffer, userMessages[WRITINGFILE],
  578.                     ff->origName, ff->fileSize);
  579.                 msg(msgBuffer, 1);
  580.                 if( doWrite(fileId, tempFile) == 0 )
  581.                     return -1;
  582.                 sprintf(msgBuffer, userMessages[FILEWRITTEN],
  583.                     ff->origName, ff->fileSize);
  584.                 msg(msgBuffer, 1);
  585.                 writing = 1;
  586.                 break;
  587.             } else if( tolower(s[0]) == 'n' ) {
  588.                 writing = 0;
  589.                 break;
  590.             } /* else ask again */
  591.         }
  592.     }
  593.  
  594.     /* do the close */
  595.     if( ff->origHandle == -1 ) {
  596.         sprintf(msgBuffer, userMessages[NOTOPEN],
  597.             ff->origName);
  598.         msg(msgBuffer, 3);
  599.         return 0;
  600.     }
  601.     
  602.     /* see if the scrap points into this file */
  603.     if( ff->origHandle == scrapBuffer.fileId && scrapBuffer.type == 0 )
  604.         /* this call only copies the scrap text to the add file */
  605.         /* it does not really do any insert (just using the code) */
  606.         insScrap(0);
  607.  
  608.     /* invalidate any buffers allocated to this open file */
  609.     if( ff->origHandle != addHandle )
  610.         fidInvalid(ff->origHandle);
  611.     
  612.     /* close the original file for this open file */
  613.     if( ff->origHandle != addHandle ) {
  614.         i = closels(ff->origHandle);
  615.         if( i != 0 ) {
  616.             sprintf(msgBuffer, userMessages[CLOSEFAILED2],
  617.                 ff->origName, i);
  618.             msg(msgBuffer, 3);
  619.         }
  620.     }
  621.  
  622.     /* free all the pieces */
  623.     freePieces(ff->pieceList);
  624.  
  625.     /* indicate the file structure is free */
  626.     ff->origHandle = -1;
  627.  
  628.     /* rename the saved file */
  629.     if( writing == 1) {
  630.         /* generate the .bak name and rename the original file */
  631.         /* rename the temporary file we copied it into */
  632.         s = makeBak(ff->origName);
  633.         delete(s);
  634.         if( renamels(ff->origName, s) ) {
  635.             sprintf(msgBuffer, userMessages[REANMEFAILED2],
  636.                 ff->origName, s, tempFile);
  637.             msg(msgBuffer, 3);
  638.         }
  639.         ff->bakMade = 1;
  640.         if( renamels(tempFile, ff->origName) ) {
  641.             sprintf(msgBuffer, userMessages[RENAMEFAILED3],
  642.                 tempFile, ff->origName, ff->origName, tempFile);
  643.             msg(msgBuffer, 3);
  644.         }
  645.     }
  646.     return 0;    /* all ok */
  647. }
  648.