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