home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / LESS177.ZIP / src / edit.c < prev    next >
C/C++ Source or Header  |  1992-07-18  |  9KB  |  456 lines

  1. #include "less.h"
  2.  
  3. #if __MSDOS__ || OS2
  4. #include <fcntl.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <io.h>
  8. #endif
  9.  
  10. #define    ISPIPE(fd)    ((fd)==0)
  11. extern int ispipe;
  12. extern int new_file;
  13. extern int errmsgs;
  14. extern int quit_at_eof;
  15. extern int file;
  16. extern int cbufs;
  17. extern char *every_first_cmd;
  18. extern int any_display;
  19. extern int force_open;
  20. extern int is_tty;
  21. extern IFILE curr_ifile;
  22. extern IFILE old_ifile;
  23. extern struct scrpos initial_scrpos;
  24.  
  25. #if LOGFILE
  26. extern int logfile;
  27. extern int force_logfile;
  28. extern char *namelogfile;
  29. #endif
  30.  
  31.  
  32. /*
  33.  * Edit a new file.
  34.  * Filename == "-" means standard input.
  35.  * Filename == NULL means just close the current file.
  36.  */
  37.     public int
  38. edit(filename, just_looking)
  39.     register char *filename;
  40.     int just_looking;
  41. {
  42.     register int f;
  43.     char *s;
  44.     int answer;
  45.     int no_display;
  46.     struct scrpos scrpos;
  47.     PARG parg;
  48.  
  49.     if (filename == NULL)
  50.     {
  51.         /*
  52.          * Close the current file, but don't open a new one.
  53.          */
  54.         f = -1;
  55.     } else if (strcmp(filename, "-") == 0)
  56.     {
  57.         /* 
  58.          * Use standard input.
  59.          */
  60.         f = 0;
  61.     } else if ((parg.p_string = bad_file(filename)) != NULL)
  62.     {
  63.         error("%s", &parg);
  64.         free(parg.p_string);
  65.         return (1);
  66. #if __MSDOS__ || OS2
  67.     } else if ((f = open(filename, O_RDONLY|O_BINARY)) < 0)
  68. #else
  69.     } else if ((f = open(filename, 0)) < 0)
  70. #endif
  71.     {
  72.         parg.p_string = errno_message(filename);
  73.         error("%s", &parg);
  74.         free(parg.p_string);
  75.         return (1);
  76.     } else if (!force_open && !just_looking && bin_file(f))
  77.     {
  78.         parg.p_string = filename;
  79.         answer = query("\"%s\" may be a binary file.  Continue? ",
  80.             &parg);
  81.         if (answer != 'y' && answer != 'Y')
  82.         {
  83.             close(f);
  84.             return (1);
  85.         }
  86.     }
  87.  
  88.     if (f >= 0 && isatty(f))
  89.     {
  90.         /*
  91.          * Not really necessary to call this an error,
  92.          * but if the control terminal (for commands)
  93.          * and the input file (for data) are the same,
  94.          * we get weird results at best.
  95.          */
  96. #if __MSDOS__ || OS2
  97.         parg.p_string = "less -?";
  98. #else
  99.         parg.p_string = "less -\\?";
  100. #endif
  101.         error("Cannot take input from a terminal (\"%s\" for help)", 
  102.             &parg);
  103.         if (!ISPIPE(f))
  104.             close(f);
  105.         return (1);
  106.     }
  107.  
  108. #if LOGFILE
  109.     s = namelogfile;
  110.     end_logfile();
  111.     if (f >= 0 && ISPIPE(f) && s != NULL && is_tty)
  112.         use_logfile(s);
  113. #endif
  114.  
  115.     /*
  116.      * We are now committed to using the new file.
  117.      * Close the current input file and set up to use the new one.
  118.      */
  119.     if (curr_ifile != NULL_IFILE)
  120.     {
  121.         /*
  122.          * Save the current position so that we can return to
  123.          * the same position if we edit this file again.
  124.          */
  125.         get_scrpos(&scrpos);
  126.         if (scrpos.pos != NULL_POSITION)
  127.         {
  128.             store_pos(curr_ifile, &scrpos);
  129.             lastmark();
  130.         }
  131.     }
  132.  
  133.     /*
  134.      * Close the current file, unless it is a pipe.
  135.      */
  136.     if (!ISPIPE(file))
  137.         close(file);
  138.     file = f;
  139.  
  140.     if (f < 0)
  141.         return (1);
  142.  
  143.     /*
  144.      * Get the new ifile.
  145.      * Get the saved position for that file.
  146.      */
  147.     old_ifile = curr_ifile;
  148.     curr_ifile = get_ifile(filename, curr_ifile);
  149.     get_pos(curr_ifile, &initial_scrpos);
  150.  
  151.     ispipe = ISPIPE(f);
  152.     if (ispipe)
  153.         ch_pipe();
  154.     else
  155.         ch_nonpipe();
  156.     (void) ch_nbuf(cbufs);
  157.     ch_flush();
  158.  
  159.     new_file = 1;
  160.  
  161. #if  __MSDOS__
  162.     top_filename();
  163. #endif
  164.  
  165.     if (every_first_cmd != NULL)
  166.         ungetsc(every_first_cmd);
  167.  
  168.     no_display = !any_display;
  169.     flush();
  170.     any_display = 1;
  171.  
  172.     if (is_tty)
  173.     {
  174.         /*
  175.          * Output is to a real tty.
  176.          */
  177.  
  178.         /*
  179.          * Indicate there is nothing displayed yet.
  180.          */
  181.         pos_clear();
  182.         clr_linenum();
  183.         if (no_display && errmsgs > 0)
  184.         {
  185.             /*
  186.              * We displayed some messages on error output
  187.              * (file descriptor 2; see error() function).
  188.              * Before erasing the screen contents,
  189.              * display the file name and wait for a keystroke.
  190.              */
  191.             parg.p_string = filename;
  192.             error("%s", &parg);
  193.         }
  194.     }
  195.     return (0);
  196. }
  197.  
  198. /*
  199.  * Edit a space-separated list of files.
  200.  * For each filename in the list, enter it into the ifile list.
  201.  * Then edit the first one.
  202.  */
  203.     public void
  204. edit_list(list)
  205.     char *list;
  206. {
  207.     register char *s;
  208.     register char *es;
  209.     register char *filename;
  210.     char *good_filename;
  211.     IFILE save_curr_ifile;
  212.  
  213.     /*
  214.      * good_filename keeps track of the first valid filename.
  215.      */
  216.     good_filename = NULL;
  217.     s = list;
  218.     es = s + strlen(s);
  219.     save_curr_ifile = curr_ifile;
  220.     while ((s = skipsp(s)) < es)
  221.     {
  222.         /*
  223.          * Get the next filename and null terminate it.
  224.          */
  225.         filename = s;
  226. #if OS2
  227.         while (*s != '\t' && *s != '\0' && *s != '\r')
  228. #else
  229.         while (*s != ' ' && *s != '\0')
  230. #endif
  231.             s++;
  232.         if (*s != '\0')
  233.             *s++ = '\0';
  234.         /*
  235.          * Try to edit the file.
  236.          * This enters it into the command line list (if it is good).
  237.          * If it is the first good file we've seen, remember it.
  238.          * {{ A little weirdness here: if any of the filenames
  239.          *    are already in the list, subsequent ones get
  240.          *    entered after the position where that one already
  241.          *    was, instead of at the end. }}
  242.          */
  243.         if (edit(filename, 1) == 0 && good_filename == NULL)
  244.             good_filename = filename;
  245.     }
  246.  
  247.     /*
  248.      * Edit the first valid filename in the list.
  249.      */
  250.     if (good_filename != NULL)
  251.     {
  252.         curr_ifile = save_curr_ifile;
  253.         (void) edit(good_filename, 0);
  254.     }
  255. }
  256.  
  257. /*
  258.  * Edit the first file in the command line (ifile) list.
  259.  */
  260.     public int
  261. edit_first()
  262. {
  263.     curr_ifile = NULL_IFILE;
  264.     return (edit_next(1));
  265. }
  266.  
  267. /*
  268.  * Edit the last file in the command line (ifile) list.
  269.  */
  270.     public int
  271. edit_last()
  272. {
  273.     curr_ifile = NULL_IFILE;
  274.     return (edit_prev(1));
  275. }
  276.  
  277.  
  278. /*
  279.  * Edit the next file in the command line (ifile) list.
  280.  */
  281.     public int
  282. edit_next(n)
  283.     int n;
  284. {
  285.     IFILE h;
  286.  
  287.     h = curr_ifile;
  288.     while (--n >= 0 || edit(get_filename(h), 0))
  289.     {
  290.         if ((h = next_ifile(h)) == NULL_IFILE)
  291.             /*
  292.              * Reached end of the ifile list.
  293.              */
  294.             return (1);
  295.     } 
  296.     /*
  297.      * Found a file that we can edit.
  298.      */
  299.     return (0);
  300. }
  301.  
  302. /*
  303.  * Edit the previous file in the command line list.
  304.  */
  305.     public int
  306. edit_prev(n)
  307.     int n;
  308. {
  309.     IFILE h;
  310.  
  311.     h = curr_ifile;
  312.     while (--n >= 0 || edit(get_filename(h), 0))
  313.     {
  314.         if ((h = prev_ifile(h)) == NULL_IFILE)
  315.             /*
  316.              * Reached beginning of the ifile list.
  317.              */
  318.             return (1);
  319.     } 
  320.     /*
  321.      * Found a file that we can edit.
  322.      */
  323.     return (0);
  324. }
  325.  
  326. /*
  327.  * Edit a specific file in the command line (ifile) list.
  328.  */
  329.     public int
  330. edit_index(n)
  331.     int n;
  332. {
  333.     IFILE h;
  334.  
  335.     h = NULL_IFILE;
  336.     do
  337.     {
  338.         if ((h = next_ifile(h)) == NULL_IFILE)
  339.         {
  340.             /*
  341.              * Reached end of the list without finding it.
  342.              */
  343.             return (1);
  344.         }
  345.     } while (get_index(h) != n);
  346.  
  347.     return (edit(get_filename(h), 0));
  348. }
  349.  
  350. /*
  351.  * Copy a file directly to standard output.
  352.  * Used if standard output is not a tty.
  353.  */
  354.     public void
  355. cat_file()
  356. {
  357.     register int c;
  358.  
  359.     while ((c = ch_forw_get()) != EOI)
  360.         putchr(c);
  361.     flush();
  362. }
  363.  
  364. #if LOGFILE
  365.  
  366. /*
  367.  * If the user asked for a log file and our input file
  368.  * is standard input, create the log file.  
  369.  * We take care not to blindly overwrite an existing file.
  370.  */
  371.     public void
  372. use_logfile(filename)
  373.     char *filename;
  374. {
  375.     register int exists;
  376.     register int answer;
  377.     PARG parg;
  378.  
  379.     /*
  380.      * {{ We could use access() here. }}
  381.      */
  382.     exists = open(filename, 0);
  383.     close(exists);
  384.     exists = (exists >= 0);
  385.  
  386.     /*
  387.      * Decide whether to overwrite the log file or append to it.
  388.      * (If it doesn't exist we "overwrite" it.
  389.      */
  390.     if (!exists || force_logfile)
  391.     {
  392.         /*
  393.          * Overwrite (or create) the log file.
  394.          */
  395.         answer = 'O';
  396.     } else
  397.     {
  398.         /*
  399.          * Ask user what to do.
  400.          */
  401.         parg.p_string = filename;
  402.         answer = query("Warning: \"%s\" exists; Overwrite, Append or Don't log? ", &parg);
  403.     }
  404.  
  405. loop:
  406.     switch (answer)
  407.     {
  408.     case 'O': case 'o':
  409.         /*
  410.          * Overwrite: create the file.
  411.          */
  412.         logfile = creat(filename, 0644);
  413.         break;
  414.     case 'A': case 'a':
  415.         /*
  416.          * Append: open the file and seek to the end.
  417.          */
  418. #if __MSDOS__ || OS2
  419.         logfile = open(filename, O_APPEND|O_WRONLY);
  420. #else
  421.         logfile = open(filename, 1);
  422. #endif
  423.         if (lseek(logfile, (offset_t)0, 2) == BAD_LSEEK)
  424.         {
  425.             close(logfile);
  426.             logfile = -1;
  427.         }
  428.         break;
  429.     case 'D': case 'd':
  430.         /*
  431.          * Don't do anything.
  432.          */
  433.         return;
  434.     case 'q':
  435.         quit(0);
  436.         /*NOTREACHED*/
  437.     default:
  438.         /*
  439.          * Eh?
  440.          */
  441.         answer = query("Overwrite, Append, or Don't log? ", NULL_PARG);
  442.         goto loop;
  443.     }
  444.  
  445.     if (logfile < 0)
  446.     {
  447.         /*
  448.          * Error in opening logfile.
  449.          */
  450.         parg.p_string = filename;
  451.         error("Cannot write to \"%s\"", &parg);
  452.     }
  453. }
  454.  
  455. #endif
  456.