home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 6 File / 06-File.zip / less373.zip / main.c < prev    next >
C/C++ Source or Header  |  2002-01-14  |  8KB  |  387 lines

  1. /*
  2.  * Copyright (C) 1984-2000  Mark Nudelman
  3.  *
  4.  * You may distribute under the terms of either the GNU General Public
  5.  * License or the Less License, as specified in the README file.
  6.  *
  7.  * For more information about less, or for information on how to 
  8.  * contact the author, see the README file.
  9.  */
  10.  
  11.  
  12. /*
  13.  * Entry point, initialization, miscellaneous routines.
  14.  */
  15.  
  16. #include "less.h"
  17. #if MSDOS_COMPILER==WIN32C
  18. #include <windows.h>
  19. #endif
  20.  
  21. public char *    every_first_cmd = NULL;
  22. public int    new_file;
  23. public int    is_tty;
  24. public IFILE    curr_ifile = NULL_IFILE;
  25. public IFILE    old_ifile = NULL_IFILE;
  26. public struct scrpos initial_scrpos;
  27. public int    any_display = FALSE;
  28. public POSITION    start_attnpos = NULL_POSITION;
  29. public POSITION    end_attnpos = NULL_POSITION;
  30. public int    wscroll;
  31. public char *    progname;
  32. public int    quitting;
  33. public int    secure;
  34. public int    dohelp;
  35.  
  36. #if LOGFILE
  37. public int    logfile = -1;
  38. public int    force_logfile = FALSE;
  39. public char *    namelogfile = NULL;
  40. #endif
  41.  
  42. #if EDITOR
  43. public char *    editor;
  44. public char *    editproto;
  45. #endif
  46.  
  47. #if TAGS
  48. extern char *    tags;
  49. extern char *    tagoption;
  50. extern int    jump_sline;
  51. #endif
  52.  
  53. #ifdef WIN32
  54. static char consoleTitle[256];
  55. #endif
  56.  
  57. extern int    missing_cap;
  58. extern int    know_dumb;
  59.  
  60.  
  61. /*
  62.  * Entry point.
  63.  */
  64. int
  65. main(argc, argv)
  66.     int argc;
  67.     char *argv[];
  68. {
  69.     IFILE ifile;
  70.     char *s;
  71.  
  72. #ifdef __EMX__
  73.     _response(&argc, &argv);
  74.     _wildcard(&argc, &argv);
  75. #endif
  76.  
  77.     progname = *argv++;
  78.     argc--;
  79.  
  80.     secure = 0;
  81.     s = lgetenv("LESSSECURE");
  82.     if (s != NULL && *s != '\0')
  83.         secure = 1;
  84.  
  85. #ifdef WIN32
  86.     if (getenv("HOME") == NULL)
  87.     {
  88.         /*
  89.          * If there is no HOME environment variable,
  90.          * try the concatenation of HOMEDRIVE + HOMEPATH.
  91.          */
  92.         char *drive = getenv("HOMEDRIVE");
  93.         char *path  = getenv("HOMEPATH");
  94.         if (drive != NULL && path != NULL)
  95.         {
  96.             char *env = (char *) ecalloc(strlen(drive) + 
  97.                     strlen(path) + 6, sizeof(char));
  98.             strcpy(env, "HOME=");
  99.             strcat(env, drive);
  100.             strcat(env, path);
  101.             putenv(env);
  102.         }
  103.     }
  104.     GetConsoleTitle(consoleTitle, sizeof(consoleTitle)/sizeof(char));
  105. #endif /* WIN32 */
  106.  
  107.     /*
  108.      * Process command line arguments and LESS environment arguments.
  109.      * Command line arguments override environment arguments.
  110.      */
  111.     is_tty = isatty(1);
  112.     get_term();
  113.     init_cmds();
  114.     init_prompt();
  115.     init_charset();
  116.     init_line();
  117.     init_option();
  118.     s = lgetenv("LESS");
  119.     if (s != NULL)
  120.         scan_option(save(s));
  121.  
  122. #define    isoptstring(s)    (((s)[0] == '-' || (s)[0] == '+') && (s)[1] != '\0')
  123.     while (argc > 0 && (isoptstring(*argv) || isoptpending()))
  124.     {
  125.         s = *argv++;
  126.         argc--;
  127.         if (strcmp(s, "--") == 0)
  128.             break;
  129.         scan_option(s);
  130.     }
  131. #undef isoptstring
  132.  
  133.     if (isoptpending())
  134.     {
  135.         /*
  136.          * Last command line option was a flag requiring a
  137.          * following string, but there was no following string.
  138.          */
  139.         nopendopt();
  140.         quit(QUIT_OK);
  141.     }
  142.  
  143. #if EDITOR
  144.     editor = lgetenv("VISUAL");
  145.     if (editor == NULL || *editor == '\0')
  146.     {
  147.         editor = lgetenv("EDITOR");
  148.         if (editor == NULL || *editor == '\0')
  149.             editor = EDIT_PGM;
  150.     }
  151.     editproto = lgetenv("LESSEDIT");
  152.     if (editproto == NULL || *editproto == '\0')
  153.         editproto = "%E ?lm+%lm. %f";
  154. #endif
  155.  
  156.     /*
  157.      * Call get_ifile with all the command line filenames
  158.      * to "register" them with the ifile system.
  159.      */
  160.     ifile = NULL_IFILE;
  161.     if (dohelp)
  162.         ifile = get_ifile(FAKE_HELPFILE, ifile);
  163.     while (argc-- > 0)
  164.     {
  165.         char *filename;
  166. #if (MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC)
  167.         /*
  168.          * Because the "shell" doesn't expand filename patterns,
  169.          * treat each argument as a filename pattern rather than
  170.          * a single filename.  
  171.          * Expand the pattern and iterate over the expanded list.
  172.          */
  173.         struct textlist tlist;
  174.         char *gfilename;
  175.         
  176.         gfilename = lglob(*argv++);
  177.         init_textlist(&tlist, gfilename);
  178.         filename = NULL;
  179.         while ((filename = forw_textlist(&tlist, filename)) != NULL)
  180.             ifile = get_ifile(filename, ifile);
  181.         free(gfilename);
  182. #else
  183.         filename = shell_quote(*argv);
  184.         if (filename == NULL)
  185.             filename = *argv;
  186.         argv++;
  187.         ifile = get_ifile(filename, ifile);
  188. #endif
  189.     }
  190.     /*
  191.      * Set up terminal, etc.
  192.      */
  193.     if (!is_tty)
  194.     {
  195.         /*
  196.          * Output is not a tty.
  197.          * Just copy the input file(s) to output.
  198.          */
  199.         SET_BINARY(1);
  200.         if (nifile() == 0)
  201.         {
  202.             if (edit_stdin() == 0)
  203.                 cat_file();
  204.         } else if (edit_first() == 0)
  205.         {
  206.             do {
  207.                 cat_file();
  208.             } while (edit_next(1) == 0);
  209.         }
  210.         quit(QUIT_OK);
  211.     }
  212.  
  213.     if (missing_cap && !know_dumb)
  214.         error("WARNING: terminal is not fully functional", NULL_PARG);
  215.     init_mark();
  216.     raw_mode(1);
  217.     open_getchr();
  218.     init_signals(1);
  219.  
  220.  
  221.     /*
  222.      * Select the first file to examine.
  223.      */
  224. #if TAGS
  225.     if (tagoption != NULL || strcmp(tags, "-") == 0)
  226.     {
  227.         /*
  228.          * A -t option was given.
  229.          * Verify that no filenames were also given.
  230.          * Edit the file selected by the "tags" search,
  231.          * and search for the proper line in the file.
  232.          */
  233.         if (nifile() > 0)
  234.         {
  235.             error("No filenames allowed with -t option", NULL_PARG);
  236.             quit(QUIT_ERROR);
  237.         }
  238.         findtag(tagoption);
  239.         if (edit_tagfile())  /* Edit file which contains the tag */
  240.             quit(QUIT_ERROR);
  241.         /*
  242.          * Search for the line which contains the tag.
  243.          * Set up initial_scrpos so we display that line.
  244.          */
  245.         initial_scrpos.pos = tagsearch();
  246.         if (initial_scrpos.pos == NULL_POSITION)
  247.             quit(QUIT_ERROR);
  248.         initial_scrpos.ln = jump_sline;
  249.     } else
  250. #endif
  251.     if (nifile() == 0)
  252.     {
  253.         if (edit_stdin())  /* Edit standard input */
  254.             quit(QUIT_ERROR);
  255.     } else 
  256.     {
  257.         if (edit_first())  /* Edit first valid file in cmd line */
  258.             quit(QUIT_ERROR);
  259.     }
  260.  
  261.     init();
  262.     commands();
  263.     quit(QUIT_OK);
  264.     /*NOTREACHED*/
  265. }
  266.  
  267. /*
  268.  * Copy a string to a "safe" place
  269.  * (that is, to a buffer allocated by calloc).
  270.  */
  271.     public char *
  272. save(s)
  273.     char *s;
  274. {
  275.     register char *p;
  276.  
  277.     p = (char *) ecalloc(strlen(s)+1, sizeof(char));
  278.     strcpy(p, s);
  279.     return (p);
  280. }
  281.  
  282. /*
  283.  * Allocate memory.
  284.  * Like calloc(), but never returns an error (NULL).
  285.  */
  286.     public VOID_POINTER
  287. ecalloc(count, size)
  288.     int count;
  289.     unsigned int size;
  290. {
  291.     register VOID_POINTER p;
  292.  
  293.     p = (VOID_POINTER) calloc(count, size);
  294.     if (p != NULL)
  295.         return (p);
  296.     error("Cannot allocate memory", NULL_PARG);
  297.     quit(QUIT_ERROR);
  298.     /*NOTREACHED*/
  299. }
  300.  
  301. /*
  302.  * Skip leading spaces in a string.
  303.  */
  304.     public char *
  305. skipsp(s)
  306.     register char *s;
  307. {
  308.     while (*s == ' ' || *s == '\t')    
  309.         s++;
  310.     return (s);
  311. }
  312.  
  313. /*
  314.  * See how many characters of two strings are identical.
  315.  * If uppercase is true, the first string must begin with an uppercase
  316.  * character; the remainder of the first string may be either case.
  317.  */
  318.     public int
  319. sprefix(ps, s, uppercase)
  320.     char *ps;
  321.     char *s;
  322.     int uppercase;
  323. {
  324.     register int c;
  325.     register int sc;
  326.     register int len = 0;
  327.  
  328.     for ( ;  *s != '\0';  s++, ps++)
  329.     {
  330.         c = *ps;
  331.         if (uppercase)
  332.         {
  333.             if (len == 0 && SIMPLE_IS_LOWER(c))
  334.                 return (-1);
  335.             if (SIMPLE_IS_UPPER(c))
  336.                 c = SIMPLE_TO_LOWER(c);
  337.         }
  338.         sc = *s;
  339.         if (len > 0 && SIMPLE_IS_UPPER(sc))
  340.             sc = SIMPLE_TO_LOWER(sc);
  341.         if (c != sc)
  342.             break;
  343.         len++;
  344.     }
  345.     return (len);
  346. }
  347.  
  348. /*
  349.  * Exit the program.
  350.  */
  351.     public void
  352. quit(status)
  353.     int status;
  354. {
  355.     static int save_status;
  356.  
  357.     /*
  358.      * Put cursor at bottom left corner, clear the line,
  359.      * reset the terminal modes, and exit.
  360.      */
  361.     if (status < 0)
  362.         status = save_status;
  363.     else
  364.         save_status = status;
  365.     quitting = 1;
  366.     edit((char*)NULL);
  367.     if (any_display && is_tty)
  368.         clear_bot();
  369.     deinit();
  370.     flush();
  371.     raw_mode(0);
  372. #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
  373.     /* 
  374.      * If we don't close 2, we get some garbage from
  375.      * 2's buffer when it flushes automatically.
  376.      * I cannot track this one down  RB
  377.      * The same bug shows up if we use ^C^C to abort.
  378.      */
  379.     close(2);
  380. #endif
  381. #if WIN32
  382.     SetConsoleTitle(consoleTitle);
  383. #endif
  384.     close_getchr();
  385.     exit(status);
  386. }
  387.