home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / editor / stevie / fileio.c < prev    next >
C/C++ Source or Header  |  1994-01-31  |  7KB  |  309 lines

  1. /* $Header: /nw/tony/src/stevie/src/RCS/fileio.c,v 1.12 89/08/06 09:50:01 tony Exp $
  2.  *
  3.  * Basic file I/O routines.
  4.  */
  5.  
  6. #include <sys/types.h>        /* For stat() and chmod() */
  7. #include <sys/stat.h>        /* Ditto */
  8. #include "stevie.h"
  9.  
  10. void
  11. filemess(s)
  12. char    *s;
  13. {
  14.     smsg("\"%s\" %s", (Filename == NULL) ? "" : Filename, s);
  15.     flushbuf();
  16. }
  17.  
  18. void
  19. renum()
  20. {
  21.     LPTR    *p;
  22.     unsigned long l = 0;
  23.  
  24.     for (p = Filemem; p != NULL ;p = nextline(p), l += LINEINC)
  25.         p->linep->num = l;
  26.  
  27.     Fileend->linep->num = 0xffffffff;
  28. }
  29.  
  30. #define    MAXLINE    256    /* maximum size of a line */
  31.  
  32. bool_t
  33. readfile(fname,fromp,nochangename)
  34. /*-------------------------------------------------
  35.  * Note that this will try to expand the file name using environment
  36.  * variables.  For this reason, we copy it into an 80-byte buffer,
  37.  * so that there's room to expand it.
  38.  *
  39.  * It uses the environment-variable convention of UNIX, even
  40.  * under systems with other conventions.  That is, your home directory
  41.  * would be called $HOME (even in DOS, where you might want to say %HOME%)
  42.  *-----------------------------------------------------*/
  43. char    *fname;
  44. LPTR    *fromp;
  45. bool_t    nochangename;    /* if TRUE, don't change the Filename */
  46. {
  47.     FILE    *f, *fopen();
  48.     register LINE    *curr;
  49.     char    buff[MAXLINE], buf2[80];
  50.     char    namebuf[80];
  51.     register int    i, c;
  52.     register long    nchars = 0;
  53.     int    linecnt = 0;
  54.     bool_t    wasempty = bufempty();
  55.     int    nonascii = 0;        /* count garbage characters */
  56.     int    nulls = 0;        /* count nulls */
  57.     bool_t    incomplete = FALSE;    /* was the last line incomplete? */
  58.     bool_t    toolong = FALSE;    /* a line was too long */
  59.  
  60.     curr = fromp->linep;
  61.  
  62.     strncpy (namebuf, fname, 80);
  63.     EnvEval (namebuf, 80);
  64.  
  65.     if ( ! nochangename )
  66.         Filename = strsave(namebuf);
  67.  
  68.     if ( (f=fopen(fixname(namebuf),"r")) == NULL )
  69.         return TRUE;
  70.  
  71.     filemess("");
  72.  
  73.     i = 0;
  74.     do {
  75.         c = getc(f);
  76.  
  77.         if (c == EOF) {
  78.             if (i == 0)    /* normal loop termination */
  79.                 break;
  80.  
  81.             /*
  82.              * If we get EOF in the middle of a line, note the
  83.              * fact and complete the line ourselves.
  84.              */
  85.             incomplete = TRUE;
  86.             c = NL;
  87.         }
  88.  
  89.         /*
  90.          * Abort if we get an interrupt, but finished reading the
  91.          * current line first.
  92.          */
  93.         if (got_int && i == 0)
  94.             break;
  95.  
  96.         if (c >= 0x80) {
  97.             c -= 0x80;
  98.             nonascii++;
  99.         }
  100.  
  101.         /*
  102.          * If we reached the end of the line, OR we ran out of
  103.          * space for it, then process the complete line.
  104.          */
  105.         if (c == NL || i == (MAXLINE-1)) {
  106.             LINE    *lp;
  107.  
  108.             if (c != NL)
  109.                 toolong = TRUE;
  110.  
  111.             buff[i] = '\0';
  112.             if ((lp = newline(strlen(buff))) == NULL)
  113.                 exit(1);
  114.  
  115.             strcpy(lp->s, buff);
  116.  
  117.             curr->next->prev = lp;    /* new line to next one */
  118.             lp->next = curr->next;
  119.  
  120.             curr->next = lp;    /* new line to prior one */
  121.             lp->prev = curr;
  122.  
  123.             curr = lp;        /* new line becomes current */
  124.             i = 0;
  125.             linecnt++;
  126.  
  127.         } else if (c == NUL)
  128.             nulls++;        /* count and ignore nulls */
  129.         else {
  130.             buff[i++] = c;        /* normal character */
  131.         }
  132.  
  133.         nchars++;
  134.  
  135.     } while (!incomplete && !toolong);
  136.  
  137.     fclose(f);
  138.  
  139.     /*
  140.      * If the buffer was empty when we started, we have to go back
  141.      * and remove the "dummy" line at Filemem and patch up the ptrs.
  142.      */
  143.     if (wasempty && nchars != 0) {
  144.         LINE    *dummy = Filemem->linep;    /* dummy line ptr */
  145.  
  146.         free(dummy->s);                /* free string space */
  147.         Filemem->linep = Filemem->linep->next;
  148.         free((char *)dummy);            /* free LINE struct */
  149.         Filemem->linep->prev = Filetop->linep;
  150.         Filetop->linep->next = Filemem->linep;
  151.  
  152.         Curschar->linep = Filemem->linep;
  153.         Topchar->linep  = Filemem->linep;
  154.     }
  155.  
  156.     renum();
  157.  
  158.     if (got_int) {
  159.         smsg("\"%s\" Interrupt", namebuf);
  160.         got_int = FALSE;
  161.         return FALSE;        /* an interrupt isn't really an error */
  162.     }
  163.  
  164.     if (toolong) {
  165.         smsg("\"%s\" Line too long", namebuf);
  166.         return FALSE;
  167.     }
  168.  
  169.     sprintf(buff, "\"%s\" %s%d line%s, %ld character%s",
  170.         namebuf,
  171.         incomplete ? "[Incomplete last line] " : "",
  172.         linecnt, (linecnt != 1) ? "s" : "",
  173.         nchars, (nchars != 1) ? "s" : "");
  174.  
  175.     buf2[0] = NUL;
  176.  
  177.     if (nonascii || nulls) {
  178.         if (nonascii) {
  179.             if (nulls)
  180.                 sprintf(buf2, " (%d null, %d non-ASCII)",
  181.                     nulls, nonascii);
  182.             else
  183.                 sprintf(buf2, " (%d non-ASCII)", nonascii);
  184.         } else
  185.             sprintf(buf2, " (%d null)", nulls);
  186.     }
  187.     strcat(buff, buf2);
  188.     msg(buff);
  189.  
  190.     return FALSE;
  191. }
  192.  
  193.  
  194. /*
  195.  * writeit - write to file 'fname' lines 'start' through 'end'
  196.  *
  197.  * If either 'start' or 'end' contain null line pointers, the default
  198.  * is to use the start or end of the file respectively.
  199.  */
  200. bool_t
  201. writeit(fname, start, end)
  202. char    *fname;
  203. LPTR    *start, *end;
  204. {
  205.     FILE    *f, *fopen();
  206.     FILE    *fopenb();        /* open in binary mode, where needed */
  207.     char    *backup;
  208.     register char    *s;
  209.     register long    nchars;
  210.     register int    lines;
  211.     register LPTR    *p;
  212.     struct stat statbuf;
  213.     int        statres;
  214.  
  215.     smsg("\"%s\"", fname);
  216.  
  217.     /* Expand any environment variables left in the name.
  218.      * fname better be in a variable big enough to handle the
  219.      * expansion (80 bytes).
  220.      */
  221.     EnvEval (fname, 80);
  222.  
  223.     /* If the file already exists, get what we need to know
  224.      * (like current mode).
  225.      */
  226.     statres = stat (fname, &statbuf);
  227.  
  228.     /*
  229.      * Form the backup file name - change foo.* to foo.bak
  230.      */
  231.     backup = alloc((unsigned) (strlen(fname) + 5));
  232.     if (backup == NULL) {
  233.         emsg("Can't open file for writing!");
  234.         return FALSE;
  235.     }
  236.  
  237.     strcpy(backup, fname);
  238.     for (s = backup; *s && *s != '.' ;s++)
  239.         ;
  240.     *s = NUL;
  241.     strcat(backup, ".bak");
  242.  
  243.     /*
  244.      * Delete any existing backup and move the current version
  245.      * to the backup. For safety, we don't remove the backup
  246.      * until the write has finished successfully. And if the
  247.      * 'backup' option is set, leave it around.
  248.      */
  249.     rename(fname, backup);
  250.  
  251.  
  252.     f = P(P_CR) ? fopen(fixname(fname), "w") : fopenb(fixname(fname), "w");
  253.  
  254.     if (f == NULL) {
  255.         emsg("Can't open file for writing!");
  256.         free(backup);
  257.         return FALSE;
  258.     }
  259.  
  260.     /*
  261.      * If we were given a bound, start there. Otherwise just
  262.      * start at the beginning of the file.
  263.      */
  264.     if (start == NULL || start->linep == NULL)
  265.         p = Filemem;
  266.     else
  267.         p = start;
  268.  
  269.     lines = nchars = 0;
  270.     do {
  271.         fprintf(f, "%s\n", p->linep->s);
  272.         nchars += strlen(p->linep->s) + 1;
  273.         lines++;
  274.  
  275.         /*
  276.          * If we were given an upper bound, and we just did that
  277.          * line, then bag it now.
  278.          */
  279.         if (end != NULL && end->linep != NULL) {
  280.             if (end->linep == p->linep)
  281.                 break;
  282.         }
  283.  
  284.     } while ((p = nextline(p)) != NULL);
  285.  
  286.     fclose(f);
  287.     smsg("\"%s\" %d line%s, %ld character%s", fname,
  288.         lines, (lines > 1) ? "s" : "",
  289.         nchars, (nchars > 1) ? "s" : "");
  290.  
  291.     UNCHANGED;
  292.  
  293.     /*
  294.      * Remove the backup unless they want it left around
  295.      */
  296.     if (!P(P_BK))
  297.         remove(backup);
  298.  
  299.     free(backup);
  300.  
  301.     /*
  302.      * Set the mode of the new file to agree with the old.
  303.      */
  304.     if (statres==0)
  305.         chmod (fname, statbuf.st_mode);
  306.  
  307.     return TRUE;
  308. }
  309.