home *** CD-ROM | disk | FTP | other *** search
/ vsiftp.vmssoftware.com / VSIPUBLIC@vsiftp.vmssoftware.com.tar / FREEWARE / FREEWARE40.ZIP / pine / pico / file.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-06  |  21.7 KB  |  833 lines

  1. #if    !defined(lint) && !defined(DOS)
  2. static char rcsid[] = "$Id: file.c,v 4.3 1993/08/20 02:01:43 mikes 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.  * Copyright 1991-1993  University of Washington
  19.  *
  20.  *  Permission to use, copy, modify, and distribute this software and its
  21.  * documentation for any purpose and without fee to the University of
  22.  * Washington is hereby granted, provided that the above copyright notice
  23.  * appears in all copies and that both the above copyright notice and this
  24.  * permission notice appear in supporting documentation, and that the name
  25.  * of the University of Washington not be used in advertising or publicity
  26.  * pertaining to distribution of the software without specific, written
  27.  * prior permission.  This software is made available "as is", and
  28.  * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
  29.  * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
  30.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
  31.  * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
  32.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  33.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
  34.  * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
  35.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  36.  *
  37.  * Pine and Pico are trademarks of the University of Washington.
  38.  * No commercial use of these trademarks may be made without prior
  39.  * written permission of the University of Washington.
  40.  *
  41.  */
  42. /*
  43.  * The routines in this file
  44.  * handle the reading and writing of
  45.  * disk files. All of details about the
  46.  * reading and writing of the disk are
  47.  * in "fileio.c".
  48.  */
  49. #include        <stdio.h>
  50. #include    "osdep.h"
  51. #include        "pico.h"
  52. #include    "estruct.h"
  53. #include        "edef.h"
  54. #include        "efunc.h"
  55. #ifdef HEBREW
  56. #include <sys/types.h>
  57. #ifdef VMS
  58. #include <stdlib.h>
  59. #else /* VMS */
  60. #include <malloc.h>   /* ? */
  61. #endif    /* VMS */
  62. #include "hebrew.h"
  63. #define  HEB_LEN  80
  64. #endif
  65.  
  66.  
  67. #ifdef    ANSI
  68.     int ifile(char *);
  69. #else
  70.     int ifile();
  71. #endif
  72.  
  73.  
  74. /*
  75.  * Read a file into the current
  76.  * buffer. This is really easy; all you do it
  77.  * find the name of the file, and call the standard
  78.  * "read a file into the current buffer" code.
  79.  * Bound to "C-X C-R".
  80.  */
  81. fileread(f, n)
  82. int f, n;
  83. {
  84.         register int    s;
  85.         char fname[NFILEN];
  86.  
  87.         if ((s=mlreply("Read file: ", fname, NFILEN, QFFILE)) != TRUE)
  88.                 return(s);
  89.  
  90.     if(gmode&MDSCUR){
  91.         emlwrite("File reading disabled in secure mode",NULL);
  92.         return(0);
  93.     }
  94.  
  95.         return(readin(fname, TRUE));
  96. }
  97.  
  98.  
  99.  
  100.  
  101. static char *inshelptext[] = {
  102.   "Insert File Help Text",
  103.   " ",
  104.   "\tType in a file name to have it inserted into your editing",
  105.   "\tbuffer between the line that the cursor is currently on",
  106.   "\tand the line directly below it.  You may abort this by ",
  107.   "~\ttyping the ~F~3 (~^~C) key after exiting help.",
  108.   " ",
  109.   "End of Insert File Help",
  110.   " ",
  111.   NULL
  112. };
  113.  
  114. static char *writehelp[] = {
  115.   "Write File Help Text",
  116.   " ",
  117.   "\tType in a file name to have it written out, thus saving",
  118.   "\tyour buffer, to a file.  You can abort this by typing ",
  119.   "~\tthe ~F~3 (~^~C) key after exiting help.",
  120.   " ",
  121.   "End of Write File Help",
  122.   " ",
  123.   " ",
  124.   NULL
  125. };
  126.  
  127.  
  128. /*
  129.  * Insert a file into the current
  130.  * buffer. This is really easy; all you do it
  131.  * find the name of the file, and call the standard
  132.  * "insert a file into the current buffer" code.
  133.  * Bound to "C-X C-I".
  134.  */
  135. insfile(f, n)
  136. int f, n;
  137. {
  138.         register int    s;
  139.         char fname[NFILEN], dir[NFILEN];
  140.         int    retval, bye = 0;
  141.         char    *prompt = "Insert file: ";
  142.         register int    availen;
  143.  
  144.         availen = term.t_ncol - strlen(prompt);
  145.  
  146.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  147.         return(rdonly());    /* we are in read only mode    */
  148.  
  149.         fname[0] = '\0';
  150.         while(!bye){
  151.             wkeyhelp("GC00000T0000","Get Help,Cancel,To Files");
  152.  
  153.         if(Pmaster == NULL)
  154.           sgarbk = TRUE;
  155.  
  156.             if ((s=mlreplyd(prompt,fname,NFILEN,QDEFLT|QFFILE)) != TRUE){
  157.         switch(s){
  158.           case (CTRL|'T'):
  159. #ifdef VMS
  160.                     if(*fname)
  161.             strcpy(dir, fname);
  162.             else
  163.             strcpy(dir, "*.*");    /* Current directory */
  164. #else /* VMS */
  165.             if(*fname && isdir(fname, NULL))
  166.               strcpy(dir, fname);
  167.             else
  168.               strcpy(dir, gethomedir(NULL));
  169. #endif    /* VMS */
  170.  
  171.             if((s = FileBrowse(dir, fname, NULL)) == 1){
  172.             if(gmode&MDSCUR){
  173.                 emlwrite("Can't insert file in restricted mode",
  174.                      NULL);
  175.                 sleep(2);
  176.             }
  177.             else{
  178.                 strcat(dir, S_FILESEP);
  179.                 strcat(dir, fname);
  180.                 retval = ifile(dir);
  181.             }
  182.             bye++;
  183.             }
  184.             else
  185.               fname[0] = '\0';
  186.  
  187.             refresh(FALSE, 1);
  188.             if(s != 1){
  189.             update();         /* redraw on return */
  190.             continue;
  191.             }
  192.             break;
  193.           case HELPCH:
  194.             if(Pmaster){
  195.             (*Pmaster->helper)(Pmaster->ins_help,
  196.                        "Help for Insert File", 1);
  197.             }
  198.             else
  199.               pico_help(inshelptext, "Help for Insert File", 1);
  200.           case (CTRL|'L'):
  201.             refresh(FALSE, 1);
  202.             update();
  203.             continue;
  204.           default:
  205.                     retval = s;
  206.             bye++;
  207.         }
  208.             }
  209.             else{
  210.         bye++;
  211.         if(gmode&MDSCUR){
  212.             emlwrite("Can't insert file in restricted mode",NULL);
  213.         }
  214.         else{
  215.             fixpath(fname, NFILEN);
  216.             retval = ifile(fname);
  217.         }
  218.             }
  219.         }
  220.         curwp->w_flag |= WFMODE|WFHARD;
  221.  
  222.         return(retval);
  223. }
  224.  
  225.  
  226. /*
  227.  * Read file "fname" into the current
  228.  * buffer, blowing away any text found there. Called
  229.  * by both the read and find commands. Return the final
  230.  * status of the read. Also called by the mainline,
  231.  * to read in a file specified on the command line as
  232.  * an argument. If the filename ends in a ".c", CMODE is
  233.  * set for the current buffer.
  234.  */
  235. readin(fname, lockfl)
  236. char    fname[];    /* name of file to read */
  237. int    lockfl;        /* check for file locks? */
  238. {
  239.         register LINE   *lp1;
  240.         register LINE   *lp2;
  241.         register int    i;
  242.         register WINDOW *wp;
  243.         register BUFFER *bp;
  244.         register int    s;
  245.         register int    nbytes;
  246.         register int    nline;
  247.     register char    *sptr;        /* pointer into filename string */
  248.     int        lflag;        /* any lines longer than allowed? */
  249.         char            line[NLINE];
  250.     CELL            ac;
  251.  
  252.         bp = curbp;                             /* Cheap.               */
  253.     ac.a = 0;
  254.         if ((s=bclear(bp)) != TRUE)             /* Might be old.        */
  255.                 return (s);
  256.         bp->b_flag &= ~(BFTEMP|BFCHG);
  257.     /* removed 'C' mode detection */
  258.         strcpy(bp->b_fname, fname);
  259.         if ((s=ffropen(fname)) == FIOERR)       /* Hard file open.      */
  260.                 goto out;
  261.         if (s == FIOFNF) {                      /* File not found.      */
  262.                 emlwrite("New file", NULL);
  263.                 goto out;
  264.         }
  265.         emlwrite("Reading file", NULL);
  266.         nline = 0;
  267.     lflag = FALSE;
  268.         while ((s=ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG) {
  269.         if (s == FIOLNG)
  270.             lflag = TRUE;
  271.                 nbytes = strlen(line);
  272.                 if ((lp1=lalloc(nbytes)) == NULL) {
  273.                         s = FIOERR;             /* Keep message on the  */
  274.                         break;                  /* display.             */
  275.                 }
  276.                 lp2 = lback(curbp->b_linep);
  277.                 lp2->l_fp = lp1;
  278.                 lp1->l_fp = curbp->b_linep;
  279.                 lp1->l_bp = lp2;
  280.                 curbp->b_linep->l_bp = lp1;
  281.                 for (i=0; i<nbytes; ++i){
  282.             ac.c = line[i];
  283.             lputc(lp1, i, ac);
  284.         }
  285.                 ++nline;
  286.         }
  287.         ffclose();                              /* Ignore errors.       */
  288.         if (s == FIOEOF) {                      /* Don't zap message!   */
  289.                 sprintf(line,"Read %d line%s", nline, (nline > 1) ? "s" : "");
  290.                 emlwrite(line, NULL);
  291.         }
  292.     if (lflag){
  293.         sprintf(line,"Read %d line%s, Long lines wrapped",
  294.             nline, (nline > 1) ? "s" : "");
  295.                 emlwrite(line, NULL);
  296.         }
  297. out:
  298.         for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
  299.                 if (wp->w_bufp == curbp) {
  300.                         wp->w_linep = lforw(curbp->b_linep);
  301.                         wp->w_dotp  = lforw(curbp->b_linep);
  302.                         wp->w_doto  = 0;
  303.                         wp->w_imarkp = NULL;
  304.                         wp->w_imarko = 0;
  305.  
  306.             if(Pmaster)
  307.               wp->w_flag |= WFHARD;
  308.             else
  309.               wp->w_flag |= WFMODE|WFHARD;
  310.                 }
  311.         }
  312.         if (s == FIOERR || s == FIOFNF)        /* False if error.      */
  313.                 return(FALSE);
  314.         return (TRUE);
  315. }
  316.  
  317.  
  318. /*
  319.  * Ask for a file name, and write the
  320.  * contents of the current buffer to that file.
  321.  * Update the remembered file name and clear the
  322.  * buffer changed flag. This handling of file names
  323.  * is different from the earlier versions, and
  324.  * is more compatable with Gosling EMACS than
  325.  * with ITS EMACS. Bound to "C-X C-W".
  326.  */
  327. filewrite(f, n)
  328. int f, n;
  329. {
  330.         register WINDOW *wp;
  331.         register int    s;
  332.         char            fname[NFILEN];
  333.     char    shows[128], *bufp;
  334.     long    l;        /* length returned from fexist() */
  335.  
  336.     if(curbp->b_fname[0] != 0)
  337.       strcpy(fname, curbp->b_fname);
  338.     else
  339.       fname[0] = '\0';
  340.  
  341.     for(;;){
  342.  
  343.         wkeyhelp("GC00000T0000","Get Help,Cancel,To Files");
  344.         sgarbk = TRUE;
  345.  
  346.         s=mlreplyd("File Name to write : ", fname, NFILEN, QDEFLT|QFFILE);
  347.  
  348.         fixpath(fname, NFILEN);        /*  fixup ~ in file name  */
  349.  
  350.         switch(s){
  351.           case FALSE:
  352.         if(strlen(fname) == 0)        /* no file name to write to */
  353.           return(s);
  354.           case TRUE:
  355.         break;
  356.           case (CTRL|'T'):
  357.         if(*fname && isdir(fname, NULL)){
  358.             strcpy(shows, fname);
  359.             fname[0] = '\0';
  360.         }
  361.         else
  362.           strcpy(shows, gethomedir(NULL));
  363.  
  364.         s = FileBrowse(shows, fname, NULL);
  365.         strcat(shows, S_FILESEP);
  366.         strcat(shows, fname);
  367.         strcpy(fname, shows);
  368.  
  369.         refresh(FALSE, 1);
  370.         update();
  371.         if(s == 1)
  372.           break;
  373.         else
  374.           continue;
  375.           case HELPCH:
  376.         pico_help(writehelp, "", 1);
  377.           case (CTRL|'L'):
  378.         refresh(FALSE, 1);
  379.         update();
  380.         continue;
  381.           default:
  382.         return(s);
  383.         break;
  384.         }
  385.  
  386.         if(strcmp(fname, curbp->b_fname) == 0)
  387.         break;
  388.  
  389.         if((s=fexist(fname, "w", &l)) == FIOSUC){ /* exists.  overwrite? */
  390.  
  391.         sprintf(shows, "File \"%s\" exists, OVERWRITE", fname);
  392.         if((s=mlyesno(shows, FALSE)) != TRUE){
  393.             if((bufp = strrchr(fname,'/')) == NULL)
  394.               fname[0] = '\0';
  395.             else
  396.               *++bufp = '\0';
  397.         }
  398.         else
  399.           break;
  400.         }
  401.         else if(s == FIOFNF){
  402.         break;                /* go write it */
  403.         }
  404.         else{                /* some error, can't write */
  405.         fioperr(s, fname);
  406.         return(ABORT);
  407.         }
  408.     }
  409.     emlwrite("Writing...", NULL);
  410.  
  411.         if ((s=writeout(fname)) != -1) {
  412.             if(!(gmode&MDTOOL)){
  413.             strcpy(curbp->b_fname, fname);
  414.             curbp->b_flag &= ~BFCHG;
  415.  
  416.             wp = wheadp;                    /* Update mode lines.   */
  417.             while (wp != NULL) {
  418.                         if (wp->w_bufp == curbp)
  419.                 if((Pmaster && s == TRUE) || Pmaster == NULL)
  420.                                 wp->w_flag |= WFMODE;
  421.                         wp = wp->w_wndp;
  422.             }
  423.         }
  424.  
  425.         if(s > 1)
  426.           emlwrite("Wrote %d lines", (void *)s);
  427.         else
  428.           emlwrite("Wrote 1 line", NULL);
  429.         }
  430.         return ((s == -1) ? FALSE : TRUE);
  431. }
  432.  
  433.  
  434.  
  435. /*
  436.  * Save the contents of the current
  437.  * buffer in its associatd file. No nothing
  438.  * if nothing has changed (this may be a bug, not a
  439.  * feature). Error if there is no remembered file
  440.  * name for the buffer. Bound to "C-X C-S". May
  441.  * get called by "C-Z".
  442.  */
  443. filesave(f, n)
  444. int f, n;
  445. {
  446.         register WINDOW *wp;
  447.         register int    s;
  448.  
  449.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  450.         return(rdonly());    /* we are in read only mode    */
  451.         if ((curbp->b_flag&BFCHG) == 0)         /* Return, no changes.  */
  452.                 return (TRUE);
  453.         if (curbp->b_fname[0] == 0) {           /* Must have a name.    */
  454.                 emlwrite("No file name", NULL);
  455.         sleep(2);
  456.                 return (FALSE);
  457.         }
  458.  
  459.     emlwrite("Writing...", NULL);
  460.         if ((s=writeout(curbp->b_fname)) != -1) {
  461.                 curbp->b_flag &= ~BFCHG;
  462.                 wp = wheadp;                    /* Update mode lines.   */
  463.                 while (wp != NULL) {
  464.                         if (wp->w_bufp == curbp)
  465.               if(Pmaster == NULL)
  466.                                 wp->w_flag |= WFMODE;
  467.                         wp = wp->w_wndp;
  468.                 }
  469.         if(s > 1){
  470.             emlwrite("Wrote %d lines", (void *)s);
  471.         }
  472.         else
  473.           emlwrite("Wrote 1 line", NULL);
  474.         }
  475.         return (s);
  476. }
  477.  
  478. /*
  479.  * This function performs the details of file
  480.  * writing. Uses the file management routines in the
  481.  * "fileio.c" package. The number of lines written is
  482.  * displayed. Sadly, it looks inside a LINE; provide
  483.  * a macro for this. Most of the grief is error
  484.  * checking of some sort.
  485.  *
  486.  * CHANGES: 1 Aug 91: returns number of lines written or -1 on error, MSS
  487.  */
  488. writeout(fn)
  489. char    *fn;
  490. {
  491.         register int    s;
  492.         register LINE   *lp;
  493.         register int    nline;
  494.     char     line[80];
  495. #ifdef HEBREW
  496.         register CELL  *lin;
  497.     int len;
  498. #define max(x,y)  ((x>=y)?x:y) 
  499. #endif
  500.  
  501.         if ((s=ffwopen(fn)) != FIOSUC)          /* Open writes message. */
  502.                 return (-1);
  503.  
  504.         lp = lforw(curbp->b_linep);             /* First line.          */
  505.         nline = 0;                              /* Number of lines.     */
  506.         while (lp != curbp->b_linep) {
  507. #ifdef HEBREW
  508.         if(compose_heb){
  509.           len=llength(lp);
  510.           if((lin=malloc(max(len,HEB_LEN)*sizeof(CELL)))==NULL)break;
  511.           memcpy(lin,&lp->l_text[0],len*sizeof(CELL));
  512.           if(lp->l_type==L_HEB){
  513.             if(!pad_line(lin,len,HEB_LEN))len=HEB_LEN;
  514.             reverse_line(lin,len);
  515.           }          
  516.           if ((s=ffputline(lin,len)) != FIOSUC)break;      
  517.           free(lin);
  518.         }
  519.         else
  520.           if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)break;
  521. #else
  522.                 if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)break;
  523. #endif
  524.                 ++nline;
  525.                 lp = lforw(lp);
  526.         }
  527.         if (s == FIOSUC) {                      /* No write error.      */
  528.                 s = ffclose();
  529.         } else                                  /* Ignore close error   */
  530.                 ffclose();                      /* if a write error.    */
  531.         if (s != FIOSUC)                        /* Some sort of error.  */
  532.                 return (-1);
  533.         return (nline);
  534. }
  535.  
  536.  
  537. /*
  538.  * writetmp - write a temporary file for message text, mindful of 
  539.  *          access restrictions and included text.  If n is true, include
  540.  *          lines that indicated included message text, otw forget them
  541.  */
  542. char *writetmp(f, n)
  543. int f, n;
  544. {
  545.         static   char    fn[NFILEN];
  546.         register int    s;
  547.         register LINE   *lp;
  548.         register int    nline;
  549.  
  550.     tmpname(fn);
  551.     
  552.         if ((s=ffwopen(fn)) != FIOSUC)          /* Open writes message. */
  553.                 return(NULL);
  554.  
  555.     chmod(fn, 0600);            /* fix access rights */
  556.  
  557.         lp = lforw(curbp->b_linep);             /* First line.          */
  558.         nline = 0;                              /* Number of lines.     */
  559.         while (lp != curbp->b_linep) {
  560.         if(n || (!n && lp->l_text[0].c != '>'))
  561.                 if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
  562.                         break;
  563.                 ++nline;
  564.                 lp = lforw(lp);
  565.         }
  566.         if (s == FIOSUC) {                      /* No write error.      */
  567.                 s = ffclose();
  568.         } else                                  /* Ignore close error   */
  569.                 ffclose();                      /* if a write error.    */
  570.         if (s != FIOSUC){                       /* Some sort of error.  */
  571.             unlink(fn);
  572.                 return(NULL);
  573.     }
  574.         return(fn);
  575. }
  576.  
  577.  
  578. /*
  579.  * The command allows the user
  580.  * to modify the file name associated with
  581.  * the current buffer. It is like the "f" command
  582.  * in UNIX "ed". The operation is simple; just zap
  583.  * the name in the BUFFER structure, and mark the windows
  584.  * as needing an update. You can type a blank line at the
  585.  * prompt if you wish.
  586.  */
  587. filename(f, n)
  588. int f, n;
  589. {
  590.         register WINDOW *wp;
  591.         register int    s;
  592.         char            fname[NFILEN];
  593.  
  594.         if ((s=mlreply("Name: ", fname, NFILEN, QFFILE)) == ABORT)
  595.                 return (s);
  596.         if (s == FALSE)
  597.                 strcpy(curbp->b_fname, "");
  598.         else
  599.                 strcpy(curbp->b_fname, fname);
  600.         wp = wheadp;                            /* Update mode lines.   */
  601.         while (wp != NULL) {
  602.                 if (wp->w_bufp == curbp)
  603.           if(Pmaster == NULL)
  604.                         wp->w_flag |= WFMODE;
  605.                 wp = wp->w_wndp;
  606.         }
  607.     curbp->b_mode &= ~MDVIEW;    /* no longer read only mode */
  608.         return (TRUE);
  609. }
  610.  
  611. /*
  612.  * Insert file "fname" into the current
  613.  * buffer, Called by insert file command. Return the final
  614.  * status of the read.
  615.  */
  616. ifile(fname)
  617. char    fname[];
  618. {
  619.         register LINE   *lp0;
  620.         register LINE   *lp1;
  621.         register LINE   *lp2;
  622.         register int    i;
  623.         register BUFFER *bp;
  624.         register int    s;
  625.         register int    nbytes;
  626.         register int    nline;
  627.     int        lflag;        /* any lines longer than allowed? */
  628.         char            line[NLINE];
  629.         char     dbuf[128];
  630.         register char    *dbufp;
  631.     CELL            ac;
  632.  
  633.         bp = curbp;                             /* Cheap.               */
  634.         bp->b_flag |= BFCHG;            /* we have changed    */
  635.     bp->b_flag &= ~BFTEMP;            /* and are not temporary*/
  636.     ac.a = 0;
  637.         if ((s=ffropen(fname)) == FIOERR)       /* Hard file open.      */
  638.                 goto out;
  639.         if (s == FIOFNF) {                      /* File not found.      */
  640.         emlwrite("No such file: %s",fname);
  641.         return(FALSE);
  642.         }
  643.         emlwrite("Inserting %s.", fname);
  644.  
  645.     /* back up a line and save the mark here */
  646.     curwp->w_dotp = lback(curwp->w_dotp);
  647.     curwp->w_doto = 0;
  648.     curwp->w_imarkp = curwp->w_dotp;
  649.     curwp->w_imarko = 0;
  650.  
  651.         nline = 0;
  652.     lflag = FALSE;
  653.         while ((s=ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG) {
  654.         if (s == FIOLNG)
  655.             lflag = TRUE;
  656.                 nbytes = strlen(line);
  657.                 if ((lp1=lalloc(nbytes)) == NULL) {
  658.                         s = FIOERR;             /* Keep message on the  */
  659.                         break;                  /* display.             */
  660.                 }
  661.         lp0 = curwp->w_dotp;    /* line previous to insert */
  662.         lp2 = lp0->l_fp;    /* line after insert */
  663.  
  664.         /* re-link new line between lp0 and lp2 */
  665.         lp2->l_bp = lp1;
  666.         lp0->l_fp = lp1;
  667.         lp1->l_bp = lp0;
  668.         lp1->l_fp = lp2;
  669. #ifdef HEBREW
  670.         lp1->l_type=L_ENG;
  671. #endif
  672.         /* and advance and write out the current line */
  673.         curwp->w_dotp = lp1;
  674.                 for (i=0; i<nbytes; ++i){
  675.             ac.c = line[i];
  676.             lputc(lp1, i, ac);
  677.         }
  678.                 ++nline;
  679.         }
  680.         ffclose();                              /* Ignore errors.       */
  681.     curwp->w_imarkp = lforw(curwp->w_imarkp);
  682.         if (s == FIOEOF) {                      /* Don't zap message!   */
  683.             sprintf(dbuf,"Inserted %d line%s",nline,(nline>1) ? "s" : "");
  684.         emlwrite(dbuf, NULL);
  685.         }
  686.     if (lflag) {
  687.         sprintf(dbuf,"Inserted %d line%s, Long lines wrapped.",
  688.             nline, (nline>1) ? "s" : "");
  689.         emlwrite(dbuf, NULL);
  690.         }
  691. out:
  692.     /* advance to the next line and mark the window for changes */
  693.     curwp->w_flag |= WFHARD;
  694.  
  695.     /* copy window parameters back to the buffer structure */
  696.     curbp->b_dotp = curwp->w_dotp;
  697.     curbp->b_doto = curwp->w_doto;
  698.     curbp->b_markp = curwp->w_imarkp;
  699.     curbp->b_marko = curwp->w_imarko;
  700.  
  701.         if (s == FIOERR)                        /* False if error.      */
  702.                 return (FALSE);
  703.         return (TRUE);
  704. }
  705.  
  706. #ifdef HEBREW
  707. reverse_line(buf,nbuf)
  708. CELL buf[];
  709. int nbuf;
  710. {
  711. int i;
  712. char t;
  713.  
  714. for(i=0;i<nbuf/2;i++){
  715.    t=buf[i].c;
  716.    buf[i].c=buf[nbuf-i-1].c;
  717.    buf[nbuf-i-1].c=t;
  718.    t=buf[i].a;
  719.    buf[i].a=buf[nbuf-i-1].a;
  720.    buf[nbuf-i-1].a=t;
  721. }
  722.  
  723. }
  724.  
  725.  
  726. pad_line(line,nbytes,padlen)
  727. CELL line[];
  728. int nbytes;
  729. int padlen;
  730. {
  731. register int i,j,k;
  732. register int tab;
  733. CELL temp[HEB_LEN];
  734. register CELL   *cp1,*cp2;
  735.  
  736. if(nbytes > padlen)return 1;
  737. cp1=line;
  738. cp2=temp;
  739. tab=8;
  740. k=0;
  741.  
  742. for(i=0;i<nbytes && cp2 < temp+padlen;i++){
  743.   if(cp1->c==0x09){
  744.     for(j=0;j<tab && cp2 < temp+padlen;j++,cp2++,k++){
  745.       cp2->c=' ';
  746.       cp2->a=0;
  747.     }
  748.     tab=1;
  749.     cp1++;
  750.   }
  751.   else if(cp1->c=='\0'){
  752.     cp2->c=' ';
  753.     cp2->a=0;
  754.     cp2++;
  755.     cp1++;
  756.     k++;
  757.   }
  758.   else{
  759.     cp2->c=cp1->c;
  760.     cp2->a=cp1->a;
  761.     cp2++;
  762.     cp1++;
  763.     k++;
  764.   }
  765.   if(--tab==0)tab=8;
  766. }  
  767.  
  768. bcopy(&temp[0],&line[0],k*sizeof(CELL));
  769. for(i=k;i<padlen;i++){
  770.   line[i].c=' ';
  771.   line[i].a=0;
  772. }
  773.  
  774. return 0;
  775.  
  776.  
  777. }
  778.  
  779. reverse_pad_buf()
  780. {
  781.         register int    s,j;
  782.         register LINE   *lp1,*lp2;
  783.     register CELL   *cp1,*cp2;
  784.         register int    nline;
  785.     int tab;
  786.     int len;
  787.     int new_len;
  788.  
  789.         lp1 = lforw(curbp->b_linep);             /* First line.          */
  790.         while (lp1 != curbp->b_linep) {
  791.       if(lp1->l_type==L_HEB){
  792.         tab=8;
  793.         len=0;
  794.         new_len = (HEB_LEN>lp1->l_used)?HEB_LEN:lp1->l_used;
  795.         if ((lp2=lalloc(new_len)) == NULL)return (FALSE);
  796.         cp1 = &lp1->l_text[0];
  797.         cp2 = &lp2->l_text[0];             
  798.         while (cp1 < &lp1->l_text[lp1->l_used]){
  799.           if(cp1->c==0x09){
  800.         for(j=0;j<tab;j++,cp2++){
  801.           cp2->c=' ';
  802.           cp2->a=0;
  803.         }
  804.         cp1++;
  805.           }
  806.           else{
  807.         cp2->c=cp1->c;
  808.         cp2->a=cp1->a;
  809.         cp2++;
  810.         cp1++;
  811.           }
  812.           if(--tab==0)tab=8;
  813.         }
  814.         while (cp2 < &lp2->l_text[new_len]){
  815.           cp2->c = ' ';
  816.           cp2->a=0;
  817.           cp2++;
  818.         }
  819.         lp1->l_bp->l_fp = lp2;
  820.         lp2->l_fp = lp1->l_fp;
  821.         lp1->l_fp->l_bp = lp2;
  822.         lp2->l_bp = lp1->l_bp;
  823.         free(lp1);
  824.         lp1=lp2;
  825.         if(lp1->l_used < HEB_LEN)lp1->l_used=HEB_LEN;        
  826.         reverse_line(&lp1->l_text[0], llength(lp1));
  827.       }
  828.           lp1 = lforw(lp1);
  829.         }
  830.     return TRUE;  
  831. }
  832. #endif
  833.