home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2994 / edit.c next >
C/C++ Source or Header  |  1991-03-05  |  8KB  |  452 lines

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