home *** CD-ROM | disk | FTP | other *** search
/ ftp.uv.es / 2014.11.ftp.uv.es.tar / ftp.uv.es / pub / unix / pine4.10.tar.gz / pine4.10.tar / pine4.10 / pico / file.c < prev    next >
C/C++ Source or Header  |  1999-01-29  |  22KB  |  944 lines

  1. #if    !defined(lint) && !defined(DOS)
  2. static char rcsid[] = "$Id: file.c,v 4.69 1999/01/29 19:59:05 hubert Exp $";
  3. #endif
  4. /*
  5.  * Program:    High level file input and output routines
  6.  *
  7.  *
  8.  * Michael Seibel
  9.  * Networks and Distributed Computing
  10.  * Computing and Communications
  11.  * University of Washington
  12.  * Administration Builiding, AG-44
  13.  * Seattle, Washington, 98195, USA
  14.  * Internet: mikes@cac.washington.edu
  15.  *
  16.  * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
  17.  *
  18.  *
  19.  * Pine and Pico are registered trademarks of the University of Washington.
  20.  * No commercial use of these trademarks may be made without prior written
  21.  * permission of the University of Washington.
  22.  * 
  23.  * Pine, Pico, and Pilot software and its included text are Copyright
  24.  * 1989-1998 by the University of Washington.
  25.  * 
  26.  * The full text of our legal notices is contained in the file called
  27.  * CPYRIGHT, included with this distribution.
  28.  *
  29.  */
  30. /*
  31.  * The routines in this file
  32.  * handle the reading and writing of
  33.  * disk files. All of details about the
  34.  * reading and writing of the disk are
  35.  * in "fileio.c".
  36.  */
  37. #include    "headers.h"
  38.  
  39.  
  40. #ifdef    ANSI
  41.     int ifile(char *);
  42.     int insmsgchar(int);
  43. #else
  44.     int ifile();
  45.     int insmsgchar();
  46. #endif
  47.  
  48.  
  49. /*
  50.  * Read a file into the current
  51.  * buffer. This is really easy; all you do it
  52.  * find the name of the file, and call the standard
  53.  * "read a file into the current buffer" code.
  54.  * Bound to "C-X C-R".
  55.  */
  56. fileread(f, n)
  57. int f, n;
  58. {
  59.         register int    s;
  60.         char fname[NFILEN];
  61.  
  62.         if ((s=mlreply("Read file: ", fname, NFILEN, QNORML, NULL)) != TRUE)
  63.                 return(s);
  64.  
  65.     if(gmode&MDSCUR){
  66.         emlwrite("File reading disabled in secure mode",NULL);
  67.         return(0);
  68.     }
  69.  
  70.     if (strlen(fname) == 0) {
  71.       emlwrite("No file name entered",NULL);
  72.       return(0);
  73.     }
  74.  
  75.     if((gmode & MDTREE) && !in_oper_tree(fname)){
  76.       emlwrite("Can't read file from outside of %s", opertree);
  77.       return(0);
  78.     }
  79.  
  80.         return(readin(fname, TRUE));
  81. }
  82.  
  83.  
  84.  
  85.  
  86. static char *inshelptext[] = {
  87.   "Insert File Help Text",
  88.   " ",
  89.   "\tType in a file name to have it inserted into your editing",
  90.   "\tbuffer between the line that the cursor is currently on",
  91.   "\tand the line directly below it.  You may abort this by ",
  92.   "~\ttyping the ~F~2 (~^~C) key after exiting help.",
  93.   " ",
  94.   "End of Insert File Help",
  95.   " ",
  96.   NULL
  97. };
  98.  
  99. static char *writehelp[] = {
  100.   "Write File Help Text",
  101.   " ",
  102.   "\tType in a file name to have it written out, thus saving",
  103.   "\tyour buffer, to a file.  You can abort this by typing ",
  104.   "~\tthe ~F~2 (~^~C) key after exiting help.",
  105.   " ",
  106.   "End of Write File Help",
  107.   " ",
  108.   " ",
  109.   NULL
  110. };
  111.  
  112.  
  113. /*
  114.  * Insert a file into the current
  115.  * buffer. This is really easy; all you do it
  116.  * find the name of the file, and call the standard
  117.  * "insert a file into the current buffer" code.
  118.  * Bound to "C-X C-I".
  119.  */
  120. insfile(f, n)
  121. int f, n;
  122. {
  123.     register int s;
  124.     char     fname[NLINE], dir[NLINE];
  125.     int         retval, bye = 0, msg = 0;
  126.     char     prompt[64], *infile;
  127.     EXTRAKEYS    menu_ins[5];
  128.     
  129.     if (curbp->b_mode&MDVIEW) /* don't allow this command if */
  130.       return(rdonly()); /* we are in read only mode */
  131.  
  132.     fname[0] = '\0';
  133.     while(!bye){
  134.     /* set up keymenu stuff */
  135.     if(!msg){
  136.         int last_menu = 0;
  137.  
  138.         menu_ins[last_menu].name  = "^T";
  139.         menu_ins[last_menu].key   = (CTRL|'T');
  140.         menu_ins[last_menu].label = "To Files";
  141.         KS_OSDATASET(&menu_ins[last_menu], KS_NONE);
  142.  
  143.         if(Pmaster && Pmaster->msgntext){
  144.         menu_ins[++last_menu].name  = "^W";
  145.         menu_ins[last_menu].key     = (CTRL|'W');
  146.         menu_ins[last_menu].label   = msg ? "InsertFile" : "InsertMsg";
  147.         KS_OSDATASET(&menu_ins[last_menu], KS_NONE);
  148.         }
  149.  
  150. #if    !defined(DOS) && !defined(MAC)
  151.         if(Pmaster && Pmaster->upload){
  152.         menu_ins[++last_menu].name = "^Y";
  153.         menu_ins[last_menu].key    = (CTRL|'Y');
  154.         menu_ins[last_menu].label  = "RcvUpload";
  155.         KS_OSDATASET(&menu_ins[last_menu], KS_NONE);
  156.         }
  157. #endif    /* !(DOS || MAC) */
  158.  
  159.         if(gmode & MDCMPLT){
  160.         menu_ins[++last_menu].name = msg ? "" : "TAB";
  161.         menu_ins[last_menu].key    = (CTRL|'I');
  162.         menu_ins[last_menu].label  = msg ? "" : "Complete";
  163.         KS_OSDATASET(&menu_ins[last_menu], KS_NONE);
  164.         }
  165.  
  166.         menu_ins[++last_menu].name = NULL;
  167.     }
  168.  
  169.     sprintf(prompt, "%s to insert from %s %s: ",
  170.         msg ? "Number of message" : "File",
  171.         (msg || (gmode&MDCURDIR))
  172.           ? "current"
  173.           : ((gmode & MDTREE) || opertree[0]) ? opertree : "home",
  174.         msg ? "folder" : "directory");
  175.     s = mlreplyd(prompt, fname, NLINE, QDEFLT, msg ? NULL : menu_ins);
  176.     /* something to read and it was edited or the default accepted */
  177.         if(fname[0] && (s == TRUE || s == FALSE)){
  178.         bye++;
  179.         if(msg){
  180.         if((*Pmaster->msgntext)(atol(fname), insmsgchar))
  181.           emlwrite("Message %s included", fname);
  182.         }
  183.         else{
  184.         bye++;
  185.         if(gmode&MDSCUR){
  186.             emlwrite("Can't insert file in restricted mode",NULL);
  187.         }
  188.         else{
  189.             if((gmode & MDTREE)
  190.                && !compresspath(opertree, fname, NLINE)){
  191.             emlwrite(
  192.             "Can't insert file from outside of %s: too many ..'s",
  193.             opertree);
  194.             }
  195.             else{
  196.             fixpath(fname, NLINE);
  197.  
  198.             if((gmode & MDTREE) && !in_oper_tree(fname))
  199.               emlwrite("Can't insert file from outside of %s",
  200.                     opertree);
  201.             else
  202.               retval = ifile(fname);
  203.             }
  204.         }
  205.         }
  206.     }
  207.     else{
  208.         switch(s){
  209.           case (CTRL|'I') :
  210.         {
  211.             char *fn, *p;
  212.             int   l = NLINE;
  213.  
  214.             dir[0] = '\0';
  215.             if(*fname && (p = strrchr(fname, C_FILESEP))){
  216.             fn = p + 1;
  217.             l -= fn - fname;
  218.             if(p == fname)
  219.               strcpy(dir, S_FILESEP);
  220. #ifdef    DOS
  221.             else if(fname[0] == C_FILESEP
  222.                  || (isalpha((unsigned char)fname[0])
  223.                      && fname[1] == ':')){
  224. #else
  225.             else if (fname[0] == C_FILESEP || fname[0] == '~') {
  226. #endif
  227.                 strncpy(dir, fname, p - fname);
  228.                 dir[p-fname] = '\0';
  229.             }
  230.             else
  231.               sprintf(dir, "%s%c%.*s", 
  232.                   (gmode & MDCURDIR) ? "."
  233.                       : ((gmode & MDTREE) || opertree[0])
  234.                            ? opertree : gethomedir(NULL),
  235.                   C_FILESEP, p - fname, fname);
  236.             }
  237.             else{
  238.             fn = fname;
  239.             strcpy(dir, (gmode & MDCURDIR)
  240.                        ? "."
  241.                        : ((gmode & MDTREE) || opertree[0])
  242.                         ? opertree : gethomedir(NULL));
  243.             }
  244.  
  245.             if(!pico_fncomplete(dir, fn, l - 1))
  246.               (*term.t_beep)();
  247.         }
  248.  
  249.         break;
  250.           case (CTRL|'W'):
  251.         msg = !msg;            /* toggle what to insert */
  252.         break;
  253.           case (CTRL|'T'):
  254.         if(msg){
  255.             emlwrite("Can't select messages yet!", NULL);
  256.         }
  257.         else{
  258.             if(*fname && isdir(fname, NULL, NULL))
  259.               strcpy(dir, fname);
  260.             else
  261.               strcpy(dir, (gmode&MDCURDIR)
  262.                      ? "."
  263.                      : ((gmode & MDTREE) || opertree[0])
  264.                       ? opertree : gethomedir(NULL));
  265.  
  266.             fname[0] = '\0';
  267.             if((s = FileBrowse(dir, NLINE, fname, NLINE, 
  268.                        NULL, FB_READ)) == 1){
  269.             if(gmode&MDSCUR){
  270.                 emlwrite("Can't insert in restricted mode",
  271.                      NULL);
  272.                 sleep(2);
  273.             }
  274.             else{
  275.                 if (infile = (char *)malloc((strlen(dir)+
  276.                                    strlen(S_FILESEP)+
  277.                            strlen(fname)+1)*sizeof(char))){
  278.                   strcpy(infile, dir);
  279.                   strcat(infile, S_FILESEP);
  280.                   strcat(infile, fname);
  281.                   retval = ifile(infile);
  282.                   free((char *) infile);
  283.                 }
  284.                 else {
  285.                   emlwrite("Trouble allocating space for insert!"
  286.                        ,NULL);
  287.                   sleep(3);
  288.                 }
  289.             }
  290.             bye++;
  291.             }
  292.             else
  293.               fname[0] = '\0';
  294.  
  295.             refresh(FALSE, 1);
  296.             if(s != 1){
  297.             update();         /* redraw on return */
  298.             continue;
  299.             }
  300.         }
  301.  
  302.         break;
  303.  
  304. #if    !defined(DOS) && !defined(MAC)
  305.           case (CTRL|'Y') :
  306.         if(Pmaster && Pmaster->upload){
  307.             char tfname[NLINE];
  308.  
  309.             if(gmode&MDSCUR){
  310.             emlwrite(
  311.                   "\007Restricted mode disallows uploaded command",
  312.                   NULL);
  313.             return(0);
  314.             }
  315.  
  316.             tfname[0] = '\0';
  317.             retval = (*Pmaster->upload)(tfname, NULL);
  318.  
  319.             refresh(FALSE, 1);
  320.             update();
  321.  
  322.             if(retval){
  323.             retval = ifile(tfname);
  324.             bye++;
  325.             }
  326.             else
  327.               sleep(3);            /* problem, show error! */
  328.  
  329.             if(tfname[0])        /* clean up temp file */
  330.               unlink(tfname);
  331.         }
  332.         else
  333.           (*term.t_beep)();        /* what? */
  334.  
  335.         break;
  336. #endif    /* !(DOS || MAC) */
  337.           case HELPCH:
  338.         if(Pmaster){
  339.             VARS_TO_SAVE *saved_state;
  340.  
  341.             saved_state = save_pico_state();
  342.             (*Pmaster->helper)(msg ? Pmaster->ins_m_help
  343.                        : Pmaster->ins_help,
  344.                        "Help for Insert File", 1);
  345.             if(saved_state){
  346.             restore_pico_state(saved_state);
  347.             free_pico_state(saved_state);
  348.             }
  349.         }
  350.         else
  351.           pico_help(inshelptext, "Help for Insert File", 1);
  352.           case (CTRL|'L'):
  353.         refresh(FALSE, 1);
  354.         update();
  355.         continue;
  356.           default:
  357.         ctrlg(FALSE, 0);
  358.                 retval = s;
  359.         bye++;
  360.         }
  361.         }
  362.     }
  363.     curwp->w_flag |= WFMODE|WFHARD;
  364.     
  365.     return(retval);
  366. }
  367.  
  368.  
  369. insmsgchar(c)
  370.     int c;
  371. {
  372.     if(c == '\n'){
  373.     char *p;
  374.  
  375.     lnewline();
  376.     for(p = Pmaster->quote_str; p && *p; p++)
  377.       if(!linsert(1, *p))
  378.         return(0);
  379.     }
  380.     else if(c != '\r')            /* ignore CR (likely CR of CRLF) */
  381.       return(linsert(1, c));
  382.  
  383.     return(1);
  384. }
  385.  
  386.  
  387.  
  388. /*
  389.  * Read file "fname" into the current
  390.  * buffer, blowing away any text found there. Called
  391.  * by both the read and find commands. Return the final
  392.  * status of the read. Also called by the mainline,
  393.  * to read in a file specified on the command line as
  394.  * an argument.
  395.  */
  396. readin(fname, lockfl)
  397. char    fname[];    /* name of file to read */
  398. int    lockfl;        /* check for file locks? */
  399. {
  400.         char line[NLINE], *linep;
  401.     long nline;
  402.     int  s, done, newline;
  403.  
  404.     curbp->b_linecnt = -1;            /* Must be recalculated */
  405.     if ((s = bclear(curbp)) != TRUE)    /* Might be old.        */
  406.       return (s);
  407.  
  408.     strcpy(curbp->b_fname, fname);
  409.     if ((s=ffropen(fname)) != FIOSUC){    /* Hard file open.      */
  410.         if(s == FIOFNF)                     /* File not found.      */
  411.           emlwrite("New file", NULL);
  412.         else
  413.           fioperr(s, fname);
  414.     }
  415.     else{
  416.         emlwrite("Reading file", NULL);
  417.         nline = 0L;
  418.         done  = newline = 0;
  419.         while(!done)
  420.           if((s = ffgetline(line, NLINE, 1)) == FIOEOF){
  421.           curbp->b_flag &= ~(BFTEMP|BFCHG);
  422.           gotobob(FALSE, 1);
  423.           sprintf(line,"Read %d line%s",
  424.               nline, (nline > 1) ? "s" : "");
  425.           emlwrite(line, NULL);
  426.           break;
  427.           }
  428.           else{
  429.           if(newline){
  430.               lnewline();
  431.               newline = 0;
  432.           }
  433.  
  434.           switch(s){
  435.             case FIOSUC :
  436.               nline++;
  437.               newline = 1;
  438.  
  439.             case FIOLNG :
  440.               for(linep = line; *linep; linep++)
  441.             linsert(1, (unsigned char) *linep);
  442.  
  443.               break;
  444.  
  445.             default :
  446.               done++;
  447.               break;
  448.           }
  449.           }
  450.  
  451.         ffclose();                              /* Ignore errors.       */
  452.     }
  453.  
  454.     return(s != FIOERR && s != FIOFNF);        /* true if success */
  455. }
  456.  
  457.  
  458. /*
  459.  * Ask for a file name, and write the
  460.  * contents of the current buffer to that file.
  461.  * Update the remembered file name and clear the
  462.  * buffer changed flag. This handling of file names
  463.  * is different from the earlier versions, and
  464.  * is more compatable with Gosling EMACS than
  465.  * with ITS EMACS. Bound to "C-X C-W".
  466.  */
  467. filewrite(f, n)
  468. int f, n;
  469. {
  470.         register WINDOW *wp;
  471.         register int    s;
  472.         char            fname[NFILEN];
  473.     char        shows[NLINE], *bufp;
  474.     EXTRAKEYS    menu_write[3];
  475.  
  476.     if(curbp->b_fname[0] != 0)
  477.       strcpy(fname, curbp->b_fname);
  478.     else
  479.       fname[0] = '\0';
  480.  
  481.     menu_write[0].name  = "^T";
  482.     menu_write[0].label = "To Files";
  483.     menu_write[0].key   = (CTRL|'T');
  484.     menu_write[1].name  = "TAB";
  485.     menu_write[1].label = "Complete";
  486.     menu_write[1].key   = (CTRL|'I');
  487.     menu_write[2].name  = NULL;
  488.     for(;!(gmode & MDTOOL);){
  489.         s = mlreplyd("File Name to write : ", fname, NFILEN,
  490.              QDEFLT|QFFILE, menu_write);
  491.  
  492.         switch(s){
  493.           case FALSE:
  494.         if(!fname[0]){            /* no file name to write to */
  495.             ctrlg(FALSE, 0);
  496.             return(s);
  497.         }
  498.           case TRUE:
  499.         if((gmode & MDTREE) && !compresspath(opertree, fname, NFILEN)){
  500.             emlwrite("Can't write outside of %s: too many ..'s",
  501.                  opertree);
  502.             sleep(2);
  503.             continue;
  504.         }
  505.         else{
  506.             fixpath(fname, NFILEN);    /*  fixup ~ in file name  */
  507.             if((gmode & MDTREE) && !in_oper_tree(fname)){
  508.             emlwrite("Can't write outside of %s", opertree);
  509.             sleep(2);
  510.             continue;
  511.             }
  512.         }
  513.  
  514.         break;
  515.  
  516.           case (CTRL|'I'):
  517.         {
  518.             char *fn, *p, dir[NFILEN];
  519.             int   l = NFILEN;
  520.  
  521.             dir[0] = '\0';
  522.             if(*fname && (p = strrchr(fname, C_FILESEP))){
  523.             fn = p + 1;
  524.             l -= fn - fname;
  525.             if(p == fname)
  526.               strcpy(dir, S_FILESEP);
  527. #ifdef    DOS
  528.             else if(fname[0] == C_FILESEP
  529.                  || (isalpha((unsigned char)fname[0])
  530.                      && fname[1] == ':')){
  531. #else
  532.             else if (fname[0] == C_FILESEP || fname[0] == '~') {
  533. #endif
  534.                 strncpy(dir, fname, p - fname);
  535.                 dir[p-fname] = '\0';
  536.             }
  537.             else
  538.               sprintf(dir, "%s%c%.*s", 
  539.                   (gmode & MDCURDIR)
  540.                      ? "."
  541.                      : ((gmode & MDTREE) || opertree[0])
  542.                       ? opertree : gethomedir(NULL),
  543.                   C_FILESEP, p - fname, fname);
  544.             }
  545.             else{
  546.             fn = fname;
  547.             strcpy(dir, (gmode & MDCURDIR)
  548.                        ? "."
  549.                        : ((gmode & MDTREE) || opertree[0])
  550.                         ? opertree : gethomedir(NULL));
  551.             }
  552.  
  553.             if(!pico_fncomplete(dir, fn, l - 1))
  554.               (*term.t_beep)();
  555.         }
  556.  
  557.         continue;
  558.           case (CTRL|'T'):
  559.         /* If we have a file name, break up into path and file name.*/
  560.         *shows = 0;
  561.         if(*fname) {
  562.             if (isdir (fname, NULL, NULL)) {
  563.             /* fname is a directory. */
  564.             strcpy (shows, fname);
  565.             *fname = '\0';
  566.             }
  567.             else {
  568.             /* Find right most seperator. */
  569.             bufp = strrchr (fname, C_FILESEP);
  570.             if (bufp != NULL) {
  571.                 /* Copy directory part to 'shows', and file
  572.                  * name part to front of 'fname'. */
  573.                 *bufp = '\0';
  574.                 strcpy (shows, fname);
  575.                 memcpy (fname, bufp+1, strlen (bufp+1) + 1);
  576.             }
  577.             }
  578.         }
  579.  
  580.         /* If we did not end up with a valid directory, use home. */
  581.         if (!*shows || !isdir (shows, NULL, NULL))
  582.           strcpy(shows, ((gmode & MDTREE) || opertree[0])
  583.                    ? opertree : gethomedir(NULL));
  584.  
  585.         if (s = FileBrowse(shows, NLINE, fname, NFILEN, NULL, FB_SAVE) == 1) {
  586.           if (strlen(shows)+strlen(S_FILESEP)+strlen(fname) < NLINE){
  587.             strcat(shows, S_FILESEP);
  588.             strcat(shows, fname);
  589.             strcpy(fname, shows);
  590.           }
  591.           else {
  592.             emlwrite("Cannot write. File name too long!!",NULL);
  593.             sleep(3);
  594.           }
  595.         }
  596.         else if (s == -1){
  597.           emlwrite("Cannot write. File name too long!!",NULL);
  598.           sleep(3);
  599.         }
  600.         refresh(FALSE, 1);
  601.         update();
  602.         if(s == 1)
  603.           break;
  604.         else
  605.           continue;
  606.           case HELPCH:
  607.         pico_help(writehelp, "", 1);
  608.           case (CTRL|'L'):
  609.         refresh(FALSE, 1);
  610.         update();
  611.         continue;
  612.           default:
  613.         return(s);
  614.         break;
  615.         }
  616.  
  617.         if(strcmp(fname, curbp->b_fname) == 0)
  618.         break;
  619.  
  620.         if((s=fexist(fname, "w", (off_t *)NULL)) == FIOSUC){
  621.                             /*exists overwrite? */
  622.  
  623.         sprintf(shows, "File \"%s\" exists, OVERWRITE", fname);
  624.         if((s=mlyesno(shows, FALSE)) == TRUE)
  625.           break;
  626.         }
  627.         else if(s == FIOFNF){
  628.         break;                /* go write it */
  629.         }
  630.         else{                /* some error, can't write */
  631.         fioperr(s, fname);
  632.         return(ABORT);
  633.         }
  634.     }
  635.     emlwrite("Writing...", NULL);
  636.  
  637.         if ((s=writeout(fname, 0)) != -1) {
  638.             if(!(gmode&MDTOOL)){
  639.             strcpy(curbp->b_fname, fname);
  640.             curbp->b_flag &= ~BFCHG;
  641.  
  642.             wp = wheadp;                    /* Update mode lines.   */
  643.             while (wp != NULL) {
  644.                         if (wp->w_bufp == curbp)
  645.                 if((Pmaster && s == TRUE) || Pmaster == NULL)
  646.                                 wp->w_flag |= WFMODE;
  647.                         wp = wp->w_wndp;
  648.             }
  649.         }
  650.  
  651.         if(s > 1)
  652.           emlwrite("Wrote %d lines", (void *)s);
  653.         else
  654.           emlwrite("Wrote 1 line", NULL);
  655.         }
  656.         return ((s == -1) ? FALSE : TRUE);
  657. }
  658.  
  659.  
  660.  
  661. /*
  662.  * Save the contents of the current
  663.  * buffer in its associatd file. No nothing
  664.  * if nothing has changed (this may be a bug, not a
  665.  * feature). Error if there is no remembered file
  666.  * name for the buffer. Bound to "C-X C-S". May
  667.  * get called by "C-Z".
  668.  */
  669. filesave(f, n)
  670. int f, n;
  671. {
  672.         register WINDOW *wp;
  673.         register int    s;
  674.  
  675.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  676.         return(rdonly());    /* we are in read only mode    */
  677.         if ((curbp->b_flag&BFCHG) == 0)         /* Return, no changes.  */
  678.                 return (TRUE);
  679.         if (curbp->b_fname[0] == 0) {           /* Must have a name.    */
  680.                 emlwrite("No file name", NULL);
  681.         sleep(2);
  682.                 return (FALSE);
  683.         }
  684.  
  685.     emlwrite("Writing...", NULL);
  686.         if ((s=writeout(curbp->b_fname, 0)) != -1) {
  687.                 curbp->b_flag &= ~BFCHG;
  688.                 wp = wheadp;                    /* Update mode lines.   */
  689.                 while (wp != NULL) {
  690.                         if (wp->w_bufp == curbp)
  691.               if(Pmaster == NULL)
  692.                                 wp->w_flag |= WFMODE;
  693.                         wp = wp->w_wndp;
  694.                 }
  695.         if(s > 1){
  696.             emlwrite("Wrote %d lines", (void *)s);
  697.         }
  698.         else
  699.           emlwrite("Wrote 1 line", NULL);
  700.         }
  701.         return (s);
  702. }
  703.  
  704. /*
  705.  * This function performs the details of file
  706.  * writing. Uses the file management routines in the
  707.  * "fileio.c" package. The number of lines written is
  708.  * displayed. Sadly, it looks inside a LINE; provide
  709.  * a macro for this. Most of the grief is error
  710.  * checking of some sort.
  711.  *
  712.  * If the argument readonly is set, the file is created with user read
  713.  * and write permission only if it doesn't already exist. Note that the
  714.  * word readonly is misleading. It is user r/w permission only.
  715.  *
  716.  * CHANGES: 1 Aug 91: returns number of lines written or -1 on error, MSS
  717.  */
  718. writeout(fn, readonly)
  719. char    *fn;
  720. int     readonly;
  721. {
  722.         register int    s;
  723.         register int    t;
  724.         register LINE   *lp;
  725.         register int    nline;
  726.     char     line[80];
  727.  
  728.         if (!((s = ffwopen(fn, readonly)) == FIOSUC && ffelbowroom()))
  729.       return (-1);                /* Open writes message. */
  730.  
  731.         lp = lforw(curbp->b_linep);             /* First line.          */
  732.         nline = 0;                              /* Number of lines.     */
  733.         while (lp != curbp->b_linep) {
  734.                 if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
  735.                         break;
  736.                 ++nline;
  737.                 lp = lforw(lp);
  738.         }
  739.  
  740.     t = ffclose();            /* ffclose complains if error */
  741.  
  742.     if(s == FIOSUC)
  743.       s = t;                /* report worst case */
  744.  
  745.     return ((s == FIOSUC) ? nline : -1);
  746. }
  747.  
  748.  
  749. /*
  750.  * writetmp - write a temporary file for message text, mindful of 
  751.  *          access restrictions and included text.  If n is true, include
  752.  *          lines that indicated included message text, otw forget them
  753.  *            If dir is non-null, put the temp file in that directory.
  754.  */
  755. char *writetmp(n, dir)
  756. int   n;
  757. char *dir;
  758. {
  759.         static   char    fn[NFILEN];
  760.         register int    s;
  761.         register int    t;
  762.         register LINE   *lp;
  763.         register int    nline;
  764.  
  765.         tmpname(dir, fn);
  766.  
  767.         if ((s=ffwopen(fn, TRUE)) != FIOSUC)    /* Open writes message. */
  768.           return(NULL);
  769.  
  770.         lp = lforw(curbp->b_linep);             /* First line.          */
  771.         nline = 0;                              /* Number of lines.     */
  772.         while (lp != curbp->b_linep) {
  773.         if(n || (!n && lp->l_text[0].c != '>'))
  774.           if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
  775.         break;
  776.  
  777.         ++nline;
  778.         lp = lforw(lp);
  779.         }
  780.  
  781.     t = ffclose();            /* ffclose complains if error */
  782.  
  783.     if(s == FIOSUC)
  784.       s = t;                /* remember worst case */
  785.  
  786.     if (s != FIOSUC){                       /* Some sort of error.  */
  787.         unlink(fn);
  788.         return(NULL);
  789.     }
  790.  
  791.     return(fn);
  792. }
  793.  
  794.  
  795. /*
  796.  * Insert file "fname" into the current
  797.  * buffer, Called by insert file command. Return the final
  798.  * status of the read.
  799.  */
  800. ifile(fname)
  801. char    fname[];
  802. {
  803.         char line[NLINE], *linep;
  804.     long nline;
  805.     int  s, done, newline;
  806.  
  807.         if ((s=ffropen(fname)) != FIOSUC){      /* Hard file open.      */
  808.         fioperr(s, fname);
  809.         return(FALSE);
  810.     }
  811.  
  812.     gotobol(FALSE, 1);
  813.  
  814.         curbp->b_flag |= BFCHG;            /* we have changed    */
  815.     curbp->b_flag &= ~BFTEMP;        /* and are not temporary*/
  816.     curbp->b_linecnt = -1;            /* must be recalculated */
  817.  
  818.         emlwrite("Inserting %s.", fname);
  819.     done = newline = 0;
  820.     nline = 0L;
  821.     while(!done)
  822.       if((s = ffgetline(line, NLINE, 1)) == FIOEOF){
  823.           if(llength(curwp->w_dotp) > curwp->w_doto)
  824.         lnewline();
  825.           else
  826.         forwchar(FALSE, 1);
  827.  
  828.           sprintf(line,"Inserted %d line%s", nline, (nline>1) ? "s" : "");
  829.           emlwrite(line, NULL);
  830.           break;
  831.       }
  832.       else{
  833.           if(newline){
  834.           lnewline();
  835.           newline = 0;
  836.           }
  837.  
  838.           switch(s){
  839.         case FIOSUC :            /* copy line into buf */
  840.           nline++;
  841.           newline = 1;
  842.  
  843.         case FIOLNG :
  844.           for(linep = line; *linep; linep++)
  845.             linsert(1, (unsigned char) *linep);
  846.  
  847.           break;
  848.  
  849.         default :
  850.           done++;
  851.           }
  852.       }
  853.  
  854.         ffclose();                              /* Ignore errors.       */
  855.  
  856.     return(s != FIOERR);
  857. }
  858.  
  859.  
  860.  
  861. /*
  862.  * pico_fncomplete - pico's function to complete the given file name
  863.  */
  864. int pico_fncomplete(dir, fn, len)
  865. char *dir, *fn;
  866. int   len;
  867. {
  868.     char *p, *dlist, tmp[NLINE], dtmp[NLINE];
  869.     int   n, i, match = -1;
  870. #ifdef    DOS
  871. #define    FILECMP(x, y)    (toupper((unsigned char)(x))\
  872.                 == toupper((unsigned char)(y)))
  873. #else
  874. #define    FILECMP(x, y)    ((x) == (y))
  875. #endif
  876.  
  877.     strcpy(dtmp, dir);
  878.     pfnexpand(dir = dtmp, NLINE);
  879.     if(*fn && (dlist = p = getfnames(dir, fn, &n, NULL))){
  880.     memset(tmp, 0, sizeof(tmp));
  881.     while(n--){            /* any names in it */
  882.         for(i = 0; fn[i] && FILECMP(p[i], fn[i]); i++)
  883.           ;
  884.  
  885.         if(!fn[i]){            /* match or more? */
  886.         if(tmp[0]){
  887.             for(; p[i] && FILECMP(p[i], tmp[i]); i++)
  888.               ;
  889.  
  890.             match = !p[i] && !tmp[i];
  891.             tmp[i] = '\0';    /* longest common string */
  892.         }
  893.         else{
  894.             match = 1;        /* may be it!?! */
  895.             strcpy(tmp,  p);
  896.         }
  897.         }
  898.  
  899.         p += strlen(p) + 1;
  900.     }
  901.  
  902.     free(dlist);
  903.     }
  904.  
  905.     if(match >= 0){
  906.     strncpy(fn, tmp, len);
  907.     fn[len] = '\0';
  908.     if(match == 1){
  909.       if ((strlen(dir)+strlen(S_FILESEP)+strlen(fn)) < len){
  910.         strcat(dir, S_FILESEP);
  911.         strcat(dir, fn);
  912.         if(isdir(dir, NULL, NULL))
  913.           strcat(fn, S_FILESEP);
  914.       }
  915.       else{
  916.         emlwrite("File name too BIG!!",0);
  917.         sleep(3);
  918.         *fn = '\0';
  919.       }
  920.  
  921.     }
  922.     }
  923.  
  924.     return(match == 1);
  925.  
  926. }
  927.  
  928.  
  929. /*
  930.  * in_oper_tree - returns true if file "f" does reside in opertree
  931.  */
  932. in_oper_tree(f)
  933. char *f;
  934. {
  935.     int end = strlen(opertree);
  936.  
  937.     return(!strncmp(opertree, f, end)
  938.         && (opertree[end-1] == '/'
  939.         || opertree[end-1] == '\\'
  940.         || f[end] == '\0'
  941.         || f[end] == '/'
  942.         || f[end] == '\\'));
  943. }
  944.