home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD1.bin / gnu / src / baseline / jove-4.14.6.lha / jove-4.14.6 / io.c < prev    next >
C/C++ Source or Header  |  1992-01-10  |  29KB  |  1,462 lines

  1. /***************************************************************************
  2.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  3.  * is provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is    *
  5.  * included in all the files.                                              *
  6.  ***************************************************************************/
  7.  
  8. #include "jove.h"
  9. #include "list.h"
  10. #include "fp.h"
  11. #include "termcap.h"
  12. #include "ctype.h"
  13. #include "disp.h"
  14. #include "scandir.h"
  15.  
  16.  
  17. #ifdef    IPROCS
  18. # include <signal.h>
  19. #endif
  20.  
  21. #ifdef    MAC
  22. # include "mac.h"
  23. #else
  24. # include <sys/stat.h>
  25. #endif
  26.  
  27. #ifdef    UNIX
  28. # include <sys/file.h>
  29. #endif
  30.  
  31. #ifdef    MSDOS
  32. # include <fcntl.h>
  33. # include <io.h>
  34. # include <direct.h>
  35. # include <dos.h>
  36. #endif    /* MSDOS */
  37.  
  38. #include <errno.h>
  39.  
  40. private struct block
  41.     *lookup proto((int /* promoted short */));
  42.  
  43. private char
  44. #ifdef    MSDOS
  45.     *fixpath proto((char *)),
  46. #endif
  47.     *getblock proto((daddr, bool));
  48.  
  49. private bool
  50.     f_getputl proto((struct line *line,struct FileStruct *fp));
  51.  
  52. private void
  53. #ifdef    MSDOS
  54.     abspath proto((char *, char *)),
  55. #endif
  56.     file_backup proto((char *fname));
  57.  
  58. #ifdef    MSDOS
  59. private int
  60.     Dchdir proto((char *));
  61. #endif
  62.  
  63. long    io_chars;        /* number of chars in this open_file */
  64. int    io_lines;        /* number of lines in this open_file */
  65.  
  66. #ifdef    pdp11
  67. char    *iobuff,
  68.     *genbuf,
  69.     *linebuf;
  70. #else
  71. char    iobuff[LBSIZE],
  72.     genbuf[LBSIZE],
  73.     linebuf[LBSIZE];
  74. #endif
  75.  
  76. #ifdef    BACKUPFILES
  77. bool    BkupOnWrite = OFF;
  78. #endif
  79.  
  80. #ifndef    MSDOS
  81.  
  82. #define    Dchdir(to)  chdir(to)
  83.  
  84. #else    /* MSDOS */
  85.  
  86. private int            /* chdir + drive */
  87. Dchdir(to)
  88. char *to;
  89. {
  90.     unsigned d, dd, n;
  91.  
  92.     if (to[1] == ':') {
  93.         d = CharUpcase(to[0]) - 'A';
  94.         /* ??? only 16 drives? */
  95.         if (d >= 16)
  96.             complain("invalid drive");
  97.         _dos_getdrive(&dd);
  98.         if (dd != d)
  99.             _dos_setdrive(d, &n);
  100.         if (to[2] == '\0') {
  101.             /* ??? Is this correct? DHR
  102.              * Current path on this drive might not be the root.
  103.              */
  104.             return 0;
  105.         }
  106.     }
  107.     return chdir(to);
  108. }
  109.  
  110. private char *
  111. fixpath(p)
  112. char *p;
  113. {
  114.     char *pp = p;
  115.  
  116.     while (*p) {
  117.         if (*p == '\\')
  118.             *p = '/';
  119.         p++;
  120.     }
  121.     return strlwr(pp);
  122. }
  123.  
  124.  
  125. private void
  126. abspath(so, dest)
  127. char *so, *dest;
  128. {
  129.     char cwd[FILESIZE], cwdD[3], cwdDIR[FILESIZE], cwdF[9], cwdEXT[5],
  130.          soD[3], soDIR[FILESIZE], soF[9], soEXT[5];
  131.     char *drive, *path;
  132.  
  133.     _splitpath(fixpath(so), soD, soDIR, soF, soEXT);
  134.     getcwd(cwd, FILESIZE);
  135.     if (*soD != '\0') {
  136.         Dchdir(soD);                /* this is kinda messy    */
  137.         getcwd(cwdDIR, FILESIZE);    /* should probably just    */
  138.         Dchdir(cwd);                /* call DOS to do it    */
  139.         strcpy(cwd, cwdDIR);
  140.     }
  141.     (void) fixpath(cwd);
  142.     if (cwd[strlen(cwd)-1] != '/')
  143.         strcat(cwd, "/x.x");    /* need dummy filename */
  144.  
  145.     _splitpath(fixpath(cwd), cwdD, cwdDIR, cwdF, cwdEXT);
  146.  
  147.     drive = (*soD == '\0') ? cwdD : soD;
  148.  
  149.     if (*soDIR != '/')
  150.         path = strcat(cwdDIR, soDIR);
  151.     else
  152.         path = soDIR;
  153.     _makepath(dest, drive, path, soF, soEXT);
  154.     fixpath(dest);    /* can't do it often enough */
  155. }
  156.  
  157. #endif    /* MSDOS */
  158.  
  159.  
  160. void
  161. close_file(fp)
  162. File    *fp;
  163. {
  164.     if (fp) {
  165.         if (fp->f_flags & F_TELLALL)
  166.             add_mess(" %d lines, %D characters.",
  167.                  io_lines,
  168.                  io_chars);
  169.         f_close(fp);
  170.     }
  171. }
  172.  
  173. /* Write the region from line1/char1 to line2/char2 to FP.  This
  174.    never CLOSES the file since we don't know if we want to. */
  175.  
  176. bool    EndWNewline = 1;
  177.  
  178. void
  179. putreg(fp, line1, char1, line2, char2, makesure)
  180. register File    *fp;
  181. Line    *line1,
  182.     *line2;
  183. int    char1,
  184.     char2;
  185. bool    makesure;
  186. {
  187.     register int    c;
  188.     register char    *lp;
  189.  
  190.     if (makesure)
  191.         (void) fixorder(&line1, &char1, &line2, &char2);
  192.     while (line1 != line2->l_next) {
  193.         lp = lcontents(line1) + char1;
  194.         if (line1 == line2) {
  195.             fputnchar(lp, (char2 - char1), fp);
  196.             io_chars += (char2 - char1);
  197.         } else {
  198.             while ((c = *lp++) != '\0') {
  199.                 jputc(c, fp);
  200.                 io_chars += 1;
  201.             }
  202.         }
  203.         if (line1 != line2) {
  204.             io_lines += 1;
  205.             io_chars += 1;
  206. #ifdef    MSDOS
  207.             jputc('\r', fp);
  208. #endif    /* MSDOS */
  209.             jputc('\n', fp);
  210.         }
  211.         line1 = line1->l_next;
  212.         char1 = 0;
  213.     }
  214.     flushout(fp);
  215. }
  216.  
  217. private void
  218. dofread(fp)
  219. register File    *fp;
  220. {
  221.     char    end[LBSIZE];
  222.     bool    xeof;
  223.     Line    *savel = curline;
  224.     int    savec = curchar;
  225.  
  226.     strcpy(end, linebuf + curchar);
  227.     xeof = f_gets(fp, linebuf + curchar, (size_t) (LBSIZE - curchar));
  228.     SavLine(curline, linebuf);
  229.     while(!xeof) {
  230.         curline = listput(curbuf, curline);
  231.         xeof = f_getputl(curline, fp);
  232.     }
  233.     getDOT();
  234.     linecopy(linebuf, (curchar = strlen(linebuf)), end);
  235.     SavLine(curline, linebuf);
  236.     IFixMarks(savel, savec, curline, curchar);
  237. }
  238.  
  239. void
  240. read_file(file, is_insert)
  241. char    *file;
  242. bool    is_insert;
  243. {
  244.     Bufpos    save;
  245.     File    *fp;
  246.     int    rdonly;
  247.  
  248.     if (!is_insert)
  249.         curbuf->b_ntbf = NO;
  250.     fp = open_file(file, iobuff, F_READ, NO, NO);
  251.     if (fp == NULL) {
  252.         if (!is_insert && errno == ENOENT)
  253.             s_mess("(new file)");
  254.         else
  255.             s_mess(IOerr("open", file));
  256.         return;
  257.     }
  258.     rdonly = (fp->f_flags & F_READONLY)? 1 : 0;
  259.     DOTsave(&save);
  260.     dofread(fp);
  261.     if (is_insert && io_chars > 0) {
  262.         modify();
  263.         set_mark();
  264.     }
  265.     SetDot(&save);
  266.     getDOT();
  267.     close_file(fp);
  268.     /* just guessing that if this is moved here */
  269.     /* then the bug on SunOS that seems to alter */
  270.     /* mtime under our feet will disappear */
  271.     if (!is_insert) {
  272.         set_ino(curbuf);
  273.         set_arg_value(rdonly);
  274.         TogMinor(ReadOnly);
  275.     }
  276. }
  277.  
  278. void
  279. SaveFile()
  280. {
  281.     if (IsModified(curbuf)) {
  282.         if (curbuf->b_fname == NULL)
  283.             WriteFile();
  284.         else {
  285.             filemunge(curbuf->b_fname);
  286.             chk_mtime(curbuf, curbuf->b_fname, "save");
  287.             file_write(curbuf->b_fname, NO);
  288.         }
  289.     } else
  290.         message("No changes need to be written.");
  291. }
  292.  
  293. char    *HomeDir;    /* home directory */
  294. size_t    HomeLen;    /* length of home directory string */
  295.  
  296. private List        *DirStack = NULL;
  297. #define dir_name(dp)    ((char *) list_data((dp)))
  298. #define PWD_PTR        (list_data(DirStack))
  299. #define PWD        ((char *) PWD_PTR)
  300.  
  301. char *
  302. pwd()
  303. {
  304.     return (char *) PWD_PTR;
  305. }
  306.  
  307. char *
  308. pr_name(fname, okay_home)
  309. char    *fname;
  310. int    okay_home;
  311. {
  312.     int    n;
  313.  
  314.     if (fname != NULL) {
  315.         n = numcomp(fname, PWD);
  316.  
  317.         if ((PWD[n] == '\0') &&    /* Matched to end of PWD */
  318.             (fname[n] == '/'))
  319.             return fname + n + 1;
  320.  
  321.         if (okay_home && strcmp(HomeDir, "/") != 0
  322.         && strncmp(fname, HomeDir, HomeLen) == 0
  323.         && fname[HomeLen] == '/')
  324.         {
  325.             static char    name_buf[100];
  326.  
  327.             swritef(name_buf, sizeof(name_buf),
  328.                 "~%s", fname + HomeLen);
  329.             return name_buf;
  330.         }
  331.     }
  332.     return fname;
  333. }
  334.  
  335. void
  336. Chdir()
  337. {
  338.     char    dirbuf[FILESIZE];
  339.  
  340. #ifdef    MSDOS
  341.     fmask = 0x10;
  342. #endif
  343.     (void) ask_file((char *)NULL, PWD, dirbuf);
  344. #ifdef    MSDOS
  345.     fmask = 0x13;
  346. #endif
  347.     if (Dchdir(dirbuf) == -1)
  348.     {
  349.         s_mess("cd: cannot change into %s.", dirbuf);
  350.         return;
  351.     }
  352.     UpdModLine = YES;
  353.     setCWD(dirbuf);
  354.     prCWD();
  355. #ifdef    MAC
  356.     Bufchange = YES;
  357. #endif
  358. }
  359.  
  360. #ifdef    UNIX
  361.  
  362. #  ifndef    BSD4_2
  363. char *
  364. getwd(buffer)
  365. char    *buffer;
  366. {
  367.     Buffer    *old = curbuf;
  368.     char    *ret_val;
  369.  
  370.     SetBuf(do_select((Window *)NULL, "pwd-output"));
  371.     curbuf->b_type = B_PROCESS;
  372.     (void) UnixToBuf("pwd-output", (char *)NULL, NO, 0, YES,
  373.         "/bin/pwd", (char *) NULL);
  374.     ToFirst();
  375.     strcpy(buffer, linebuf);
  376.     SetBuf(old);
  377.     return buffer;
  378. }
  379. #  endif    /* not BSD4_2 */
  380.  
  381. /* Check if dn is the name of the current working directory
  382.    and that it is in cannonical form */
  383.  
  384. bool
  385. chkCWD(dn)
  386. char    *dn;
  387. {
  388.     char    filebuf[FILESIZE];
  389.     struct stat    dnstat,
  390.             dotstat;
  391.  
  392.     if (dn[0] != '/')
  393.         return FALSE;        /* need absolute pathname */
  394.     PathParse(dn, filebuf);
  395.     return stat(filebuf, &dnstat) == 0 &&
  396.            stat(".", &dotstat) == 0 &&
  397.            dnstat.st_dev == dotstat.st_dev &&
  398.            dnstat.st_ino == dotstat.st_ino;
  399. }
  400.  
  401. #endif    /* UNIX */
  402.  
  403. void
  404. setCWD(d)
  405. char    *d;
  406. {
  407.     if (DirStack == NULL)
  408.         list_push(&DirStack, (UnivPtr)NULL);
  409.     PWD_PTR = (PWD == NULL)
  410.         ? (UnivPtr) emalloc((size_t) (strlen(d) + 1))
  411.         : (UnivPtr) freealloc((UnivPtr) PWD, strlen(d) + 1);
  412.     strcpy(PWD, d);
  413. }
  414.  
  415. void
  416. getCWD()
  417. {
  418.     char    *cwd;
  419.     char    pathname[FILESIZE];
  420.  
  421. #ifndef    MSDOS
  422.     cwd = getenv("CWD");
  423.     if (cwd == NULL || !chkCWD(cwd)) {
  424.         cwd = getenv("PWD");
  425.         if (cwd == NULL || !chkCWD(cwd)) {
  426. #ifdef    HAVE_GETWD
  427.             cwd = getwd(pathname);
  428. #else
  429.             /* System Vr4, and who else? */
  430.             extern char    *getcwd proto((char *, int/*!!!*/));
  431.  
  432.             cwd = getcwd(pathname, (int) sizeof(pathname));
  433. #endif    /* HAVE_GETWD */
  434.         }
  435.     }
  436. #else    /* MSDOS */
  437.     {
  438.         extern char    *getcwd();
  439.  
  440.         cwd = fixpath(getcwd(pathname, FILESIZE));
  441.     }
  442. #