142660Smarkm/* info.c -- Display nodes of Info files in multiple windows.
2146515Sru   $Id: info.c,v 1.11 2004/04/11 17:56:45 karl Exp $
321495Sjmacd
4146515Sru   Copyright (C) 1993, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
5146515Sru   2004 Free Software Foundation, Inc.
621495Sjmacd
721495Sjmacd   This program is free software; you can redistribute it and/or modify
821495Sjmacd   it under the terms of the GNU General Public License as published by
921495Sjmacd   the Free Software Foundation; either version 2, or (at your option)
1021495Sjmacd   any later version.
1121495Sjmacd
1221495Sjmacd   This program is distributed in the hope that it will be useful,
1321495Sjmacd   but WITHOUT ANY WARRANTY; without even the implied warranty of
1421495Sjmacd   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1521495Sjmacd   GNU General Public License for more details.
1621495Sjmacd
1721495Sjmacd   You should have received a copy of the GNU General Public License
1821495Sjmacd   along with this program; if not, write to the Free Software
1921495Sjmacd   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
2021495Sjmacd
2121495Sjmacd   Written by Brian Fox (bfox@ai.mit.edu). */
2221495Sjmacd
2321495Sjmacd#include "info.h"
2442660Smarkm#include "indices.h"
2521495Sjmacd#include "dribble.h"
2621495Sjmacd#include "getopt.h"
2721495Sjmacd#if defined (HANDLE_MAN_PAGES)
2821495Sjmacd#  include "man.h"
2921495Sjmacd#endif /* HANDLE_MAN_PAGES */
3021495Sjmacd
3156160Srustatic char *program_name = "info";
3221495Sjmacd
3321495Sjmacd/* Non-zero means search all indices for APROPOS_SEARCH_STRING. */
3421495Sjmacdstatic int apropos_p = 0;
3521495Sjmacd
3621495Sjmacd/* Variable containing the string to search for when apropos_p is non-zero. */
3721495Sjmacdstatic char *apropos_search_string = (char *)NULL;
3821495Sjmacd
3942660Smarkm/* Non-zero means search all indices for INDEX_SEARCH_STRING.  Unlike
4042660Smarkm   apropos, this puts the user at the node, running info. */
4142660Smarkmstatic int index_search_p = 0;
4242660Smarkm
4356160Sru/* Non-zero means look for the node which describes the invocation
4456160Sru   and command-line options of the program, and start the info
4556160Sru   session at that node.  */
4656160Srustatic int goto_invocation_p = 0;
4756160Sru
4842660Smarkm/* Variable containing the string to search for when index_search_p is
4956160Sru   non-zero. */
5042660Smarkmstatic char *index_search_string = (char *)NULL;
5142660Smarkm
5221495Sjmacd/* Non-zero means print version info only. */
5321495Sjmacdstatic int print_version_p = 0;
5421495Sjmacd
5521495Sjmacd/* Non-zero means print a short description of the options. */
5621495Sjmacdstatic int print_help_p = 0;
5721495Sjmacd
5821495Sjmacd/* Array of the names of nodes that the user specified with "--node" on the
5921495Sjmacd   command line. */
6021495Sjmacdstatic char **user_nodenames = (char **)NULL;
6121495Sjmacdstatic int user_nodenames_index = 0;
6221495Sjmacdstatic int user_nodenames_slots = 0;
6321495Sjmacd
6421495Sjmacd/* String specifying the first file to load.  This string can only be set
6521495Sjmacd   by the user specifying "--file" on the command line. */
6621495Sjmacdstatic char *user_filename = (char *)NULL;
6721495Sjmacd
6821495Sjmacd/* String specifying the name of the file to dump nodes to.  This value is
6921495Sjmacd   filled if the user speficies "--output" on the command line. */
7021495Sjmacdstatic char *user_output_filename = (char *)NULL;
7121495Sjmacd
7221495Sjmacd/* Non-zero indicates that when "--output" is specified, all of the menu
7321495Sjmacd   items of the specified nodes (and their subnodes as well) should be
7421495Sjmacd   dumped in the order encountered.  This basically can print a book. */
7521495Sjmacdint dump_subnodes = 0;
7621495Sjmacd
7756160Sru/* Non-zero means make default keybindings be loosely modeled on vi(1).  */
7856160Sruint vi_keys_p = 0;
7956160Sru
80146515Sru/* Non-zero means don't remove ANSI escape sequences.  */
81146515Sruint raw_escapes_p = 1;
8293139Sru
83146515Sru/* Non-zero means print the absolute location of the file to be loaded.  */
84146515Srustatic int print_where_p = 0;
85146515Sru
8656160Sru#ifdef __MSDOS__
8756160Sru/* Non-zero indicates that screen output should be made 'speech-friendly'.
8856160Sru   Since on MSDOS the usual behavior is to write directly to the video
8956160Sru   memory, speech synthesizer software cannot grab the output.  Therefore,
9056160Sru   we provide a user option which tells us to avoid direct screen output
9156160Sru   and use stdout instead (which loses the color output).  */
9256160Sruint speech_friendly = 0;
9356160Sru#endif
9456160Sru
9521495Sjmacd/* Structure describing the options that Info accepts.  We pass this structure
9621495Sjmacd   to getopt_long ().  If you add or otherwise change this structure, you must
9721495Sjmacd   also change the string which follows it. */
9821495Sjmacd#define APROPOS_OPTION 1
9921495Sjmacd#define DRIBBLE_OPTION 2
10021495Sjmacd#define RESTORE_OPTION 3
10142660Smarkm#define IDXSRCH_OPTION 4
10221495Sjmacdstatic struct option long_options[] = {
10321495Sjmacd  { "apropos", 1, 0, APROPOS_OPTION },
10421495Sjmacd  { "directory", 1, 0, 'd' },
105100513Sru  { "dribble", 1, 0, DRIBBLE_OPTION },
106100513Sru  { "file", 1, 0, 'f' },
107100513Sru  { "help", 0, &print_help_p, 1 },
108100513Sru  { "index-search", 1, 0, IDXSRCH_OPTION },
109146515Sru  { "location", 0, &print_where_p, 1 },
11021495Sjmacd  { "node", 1, 0, 'n' },
11121495Sjmacd  { "output", 1, 0, 'o' },
11293139Sru  { "raw-escapes", 0, &raw_escapes_p, 1 },
113146515Sru  { "no-raw-escapes", 0, &raw_escapes_p, 0 },
114100513Sru  { "restore", 1, 0, RESTORE_OPTION },
11556160Sru  { "show-options", 0, 0, 'O' },
116100513Sru  { "subnodes", 0, &dump_subnodes, 1 },
11756160Sru  { "usage", 0, 0, 'O' },
118100513Sru  { "version", 0, &print_version_p, 1 },
11956160Sru  { "vi-keys", 0, &vi_keys_p, 1 },
120146515Sru  { "where", 0, &print_where_p, 1 },
12156160Sru#ifdef __MSDOS__
12256160Sru  { "speech-friendly", 0, &speech_friendly, 1 },
12356160Sru#endif
12421495Sjmacd  {NULL, 0, NULL, 0}
12521495Sjmacd};
12621495Sjmacd
12721495Sjmacd/* String describing the shorthand versions of the long options found above. */
12856160Sru#ifdef __MSDOS__
129146515Srustatic char *short_options = "d:n:f:ho:ORswb";
13056160Sru#else
131146515Srustatic char *short_options = "d:n:f:ho:ORws";
13256160Sru#endif
13321495Sjmacd
13421495Sjmacd/* When non-zero, the Info window system has been initialized. */
13521495Sjmacdint info_windows_initialized_p = 0;
13621495Sjmacd
13721495Sjmacd/* Some "forward" declarations. */
138146515Srustatic void info_short_help (void);
139146515Srustatic void init_messages (void);
14021495Sjmacd
14121495Sjmacd
14221495Sjmacd/* **************************************************************** */
14342660Smarkm/*                                                                  */
14442660Smarkm/*                Main Entry Point to the Info Program              */
14542660Smarkm/*                                                                  */
14621495Sjmacd/* **************************************************************** */
14721495Sjmacd
14821495Sjmacdint
149146515Srumain (int argc, char **argv)
15021495Sjmacd{
15142660Smarkm  int getopt_long_index;        /* Index returned by getopt_long (). */
15242660Smarkm  NODE *initial_node;           /* First node loaded by Info. */
15321495Sjmacd
15442660Smarkm#ifdef HAVE_SETLOCALE
15542660Smarkm  /* Set locale via LC_ALL.  */
15642660Smarkm  setlocale (LC_ALL, "");
15742660Smarkm#endif
15842660Smarkm
159146515Sru#ifdef ENABLE_NLS
16042660Smarkm  /* Set the text message domain.  */
16142660Smarkm  bindtextdomain (PACKAGE, LOCALEDIR);
16242660Smarkm  textdomain (PACKAGE);
163146515Sru#endif
16442660Smarkm
16556160Sru  init_messages ();
166116525Sru
16721495Sjmacd  while (1)
16821495Sjmacd    {
16921495Sjmacd      int option_character;
17021495Sjmacd
17121495Sjmacd      option_character = getopt_long
17242660Smarkm        (argc, argv, short_options, long_options, &getopt_long_index);
17321495Sjmacd
174116525Sru      /* getopt_long returns EOF when there are no more long options. */
17521495Sjmacd      if (option_character == EOF)
17642660Smarkm        break;
17721495Sjmacd
17821495Sjmacd      /* If this is a long option, then get the short version of it. */
17921495Sjmacd      if (option_character == 0 && long_options[getopt_long_index].flag == 0)
18042660Smarkm        option_character = long_options[getopt_long_index].val;
18121495Sjmacd
18221495Sjmacd      /* Case on the option that we have received. */
18321495Sjmacd      switch (option_character)
18442660Smarkm        {
18542660Smarkm        case 0:
18642660Smarkm          break;
18721495Sjmacd
18842660Smarkm          /* User wants to add a directory. */
18942660Smarkm        case 'd':
19042660Smarkm          info_add_path (optarg, INFOPATH_PREPEND);
19142660Smarkm          break;
19221495Sjmacd
19342660Smarkm          /* User is specifying a particular node. */
19442660Smarkm        case 'n':
19542660Smarkm          add_pointer_to_array (optarg, user_nodenames_index, user_nodenames,
19642660Smarkm                                user_nodenames_slots, 10, char *);
19742660Smarkm          break;
19821495Sjmacd
19942660Smarkm          /* User is specifying a particular Info file. */
20042660Smarkm        case 'f':
20142660Smarkm          if (user_filename)
20242660Smarkm            free (user_filename);
20321495Sjmacd
20442660Smarkm          user_filename = xstrdup (optarg);
20542660Smarkm          break;
20621495Sjmacd
207116525Sru          /* Treat -h like --help. */
208116525Sru        case 'h':
209116525Sru          print_help_p = 1;
210116525Sru          break;
211116525Sru
21242660Smarkm          /* User is specifying the name of a file to output to. */
21342660Smarkm        case 'o':
21442660Smarkm          if (user_output_filename)
21542660Smarkm            free (user_output_filename);
21642660Smarkm          user_output_filename = xstrdup (optarg);
21742660Smarkm          break;
21821495Sjmacd
21956160Sru         /* User has specified that she wants to find the "Options"
22056160Sru             or "Invocation" node for the program.  */
22156160Sru        case 'O':
22256160Sru          goto_invocation_p = 1;
22356160Sru          break;
22456160Sru
22593139Sru	  /* User has specified that she wants the escape sequences
22693139Sru	     in man pages to be passed thru unaltered.  */
22793139Sru        case 'R':
22893139Sru          raw_escapes_p = 1;
22993139Sru          break;
23093139Sru
23142660Smarkm          /* User is specifying that she wishes to dump the subnodes of
23242660Smarkm             the node that she is dumping. */
23342660Smarkm        case 's':
23442660Smarkm          dump_subnodes = 1;
23542660Smarkm          break;
23621495Sjmacd
237146515Sru          /* For compatibility with man, -w is --where.  */
238146515Sru        case 'w':
239146515Sru          print_where_p = 1;
240146515Sru          break;
241146515Sru
24256160Sru#ifdef __MSDOS__
24393139Sru	  /* User wants speech-friendly output.  */
24456160Sru	case 'b':
24556160Sru	  speech_friendly = 1;
24656160Sru	  break;
24756160Sru#endif /* __MSDOS__ */
24856160Sru
24942660Smarkm          /* User has specified a string to search all indices for. */
25042660Smarkm        case APROPOS_OPTION:
25142660Smarkm          apropos_p = 1;
25242660Smarkm          maybe_free (apropos_search_string);
25342660Smarkm          apropos_search_string = xstrdup (optarg);
25442660Smarkm          break;
25521495Sjmacd
25642660Smarkm          /* User has specified a dribble file to receive keystrokes. */
25742660Smarkm        case DRIBBLE_OPTION:
25842660Smarkm          close_dribble_file ();
25942660Smarkm          open_dribble_file (optarg);
26042660Smarkm          break;
26121495Sjmacd
26242660Smarkm          /* User has specified an alternate input stream. */
26342660Smarkm        case RESTORE_OPTION:
26442660Smarkm          info_set_input_from_file (optarg);
26542660Smarkm          break;
26621495Sjmacd
26742660Smarkm          /* User has specified a string to search all indices for. */
26842660Smarkm        case IDXSRCH_OPTION:
26942660Smarkm          index_search_p = 1;
27042660Smarkm          maybe_free (index_search_string);
27142660Smarkm          index_search_string = xstrdup (optarg);
27242660Smarkm          break;
27342660Smarkm
27442660Smarkm        default:
27556160Sru          fprintf (stderr, _("Try --help for more information.\n"));
27656160Sru          xexit (1);
27742660Smarkm        }
27821495Sjmacd    }
27921495Sjmacd
28021495Sjmacd  /* If the output device is not a terminal, and no output filename has been
28121495Sjmacd     specified, make user_output_filename be "-", so that the info is written
28221495Sjmacd     to stdout, and turn on the dumping of subnodes. */
28321495Sjmacd  if ((!isatty (fileno (stdout))) && (user_output_filename == (char *)NULL))
28421495Sjmacd    {
28542660Smarkm      user_output_filename = xstrdup ("-");
28621495Sjmacd      dump_subnodes = 1;
28721495Sjmacd    }
28821495Sjmacd
28921495Sjmacd  /* If the user specified --version, then show the version and exit. */
29021495Sjmacd  if (print_version_p)
29121495Sjmacd    {
29256160Sru      printf ("%s (GNU %s) %s\n", program_name, PACKAGE, VERSION);
29356160Sru      puts ("");
294146515Sru      puts ("Copyright (C) 2004 Free Software Foundation, Inc.");
295146515Sru      printf (_("There is NO warranty.  You may redistribute this software\n\
29621495Sjmacdunder the terms of the GNU General Public License.\n\
297146515SruFor more information about these matters, see the files named COPYING.\n"));
29856160Sru      xexit (0);
29921495Sjmacd    }
30021495Sjmacd
30121495Sjmacd  /* If the `--help' option was present, show the help and exit. */
30221495Sjmacd  if (print_help_p)
30321495Sjmacd    {
30421495Sjmacd      info_short_help ();
30556160Sru      xexit (0);
30621495Sjmacd    }
30756160Sru
30842660Smarkm  /* If the user hasn't specified a path for Info files, default it.
30942660Smarkm     Lowest priority is our messy hardwired list in filesys.h.
31042660Smarkm     Then comes the user's INFODIR from the Makefile.
31142660Smarkm     Highest priority is the environment variable, if set.  */
31221495Sjmacd  if (!infopath)
31321495Sjmacd    {
31442660Smarkm      char *path_from_env = getenv ("INFOPATH");
31521495Sjmacd
31621495Sjmacd      if (path_from_env)
31742660Smarkm        {
31842660Smarkm          unsigned len = strlen (path_from_env);
31942660Smarkm          /* Trailing : on INFOPATH means insert the default path.  */
32056160Sru          if (len && path_from_env[len - 1] == PATH_SEP[0])
32142660Smarkm            {
32242660Smarkm              path_from_env[len - 1] = 0;
32342660Smarkm              info_add_path (DEFAULT_INFOPATH, INFOPATH_PREPEND);
32442660Smarkm            }
32542660Smarkm#ifdef INFODIR /* from the Makefile */
32642660Smarkm          info_add_path (INFODIR, INFOPATH_PREPEND);
32742660Smarkm#endif
32842660Smarkm          info_add_path (path_from_env, INFOPATH_PREPEND);
32942660Smarkm        }
33021495Sjmacd      else
33142660Smarkm        {
33242660Smarkm          info_add_path (DEFAULT_INFOPATH, INFOPATH_PREPEND);
33342660Smarkm#ifdef INFODIR /* from the Makefile */
334146515Sru          info_add_path (INFODIR, INFOPATH_PREPEND);
33542660Smarkm#endif
336146515Sru#ifdef INFODIR2 /* from the Makefile, too */
337146515Sru#  ifdef INFODIR
338146515Sru          if (!STREQ (INFODIR, INFODIR2))
339146515Sru#  endif
340146515Sru            info_add_path (INFODIR2, INFOPATH_PREPEND);
341146515Sru#endif
34242660Smarkm        }
34321495Sjmacd    }
34421495Sjmacd
34521495Sjmacd  /* If the user specified a particular filename, add the path of that
34621495Sjmacd     file to the contents of INFOPATH. */
34721495Sjmacd  if (user_filename)
34893139Sru    add_file_directory_to_path (user_filename);
34921495Sjmacd
35021495Sjmacd  /* If the user wants to search every known index for a given string,
35121495Sjmacd     do that now, and report the results. */
35221495Sjmacd  if (apropos_p)
35321495Sjmacd    {
35421495Sjmacd      info_apropos (apropos_search_string);
35556160Sru      xexit (0);
35621495Sjmacd    }
35721495Sjmacd
35821495Sjmacd  /* Get the initial Info node.  It is either "(dir)Top", or what the user
35921495Sjmacd     specifed with values in user_filename and user_nodenames. */
36042660Smarkm  initial_node = info_get_node (user_filename,
36156160Sru                                user_nodenames ? user_nodenames[0] : 0);
36221495Sjmacd
36321495Sjmacd  /* If we couldn't get the initial node, this user is in trouble. */
36421495Sjmacd  if (!initial_node)
36521495Sjmacd    {
36621495Sjmacd      if (info_recent_file_error)
367146515Sru        info_error (info_recent_file_error, NULL, NULL);
36821495Sjmacd      else
369146515Sru        info_error ((char *) msg_cant_find_node,
370146515Sru                    user_nodenames ? user_nodenames[0] : "Top", NULL);
37156160Sru      xexit (1);
37221495Sjmacd    }
37321495Sjmacd
37442660Smarkm  /* Special cases for when the user specifies multiple nodes.  If we
37542660Smarkm     are dumping to an output file, dump all of the nodes specified.
37642660Smarkm     Otherwise, attempt to create enough windows to handle the nodes
37742660Smarkm     that this user wants displayed. */
37821495Sjmacd  if (user_nodenames_index > 1)
37921495Sjmacd    {
38021495Sjmacd      free (initial_node);
38121495Sjmacd
382146515Sru      if (print_where_p)
383146515Sru        printf ("%s\n", user_filename ? user_filename : "unknown?!");
384146515Sru      else if (user_output_filename)
38542660Smarkm        dump_nodes_to_file
38642660Smarkm          (user_filename, user_nodenames, user_output_filename, dump_subnodes);
38721495Sjmacd      else
38842660Smarkm        begin_multiple_window_info_session (user_filename, user_nodenames);
38921495Sjmacd
39056160Sru      xexit (0);
39121495Sjmacd    }
39221495Sjmacd
39321495Sjmacd  /* If there are arguments remaining, they are the names of menu items
39421495Sjmacd     in sequential info files starting from the first one loaded.  That
39521495Sjmacd     file name is either "dir", or the contents of user_filename if one
39621495Sjmacd     was specified. */
39756160Sru  {
398146515Sru    const char *errstr;
399146515Sru    char *errarg1, *errarg2;
400146515Sru
40156160Sru    NODE *new_initial_node = info_follow_menus (initial_node, argv + optind,
402146515Sru        &errstr, &errarg1, &errarg2);
40393139Sru
40456160Sru    if (new_initial_node && new_initial_node != initial_node)
40556160Sru      initial_node = new_initial_node;
40621495Sjmacd
407146515Sru    if (print_where_p)
408146515Sru      {
409146515Sru        if (initial_node->parent)
410146515Sru          printf ("%s\n", initial_node->parent);
411146515Sru        else if (initial_node->filename
412146515Sru            && !is_dir_name (filename_non_directory (initial_node->filename)))
413146515Sru          printf ("%s\n", initial_node->filename);
414146515Sru        else
415146515Sru          xexit (1);
416146515Sru        xexit (0);
417146515Sru      }
418146515Sru
41956160Sru    /* If the user specified that this node should be output, then do that
42056160Sru       now.  Otherwise, start the Info session with this node.  Or act
42156160Sru       accordingly if the initial node was not found.  */
42293139Sru    if (user_output_filename && !goto_invocation_p)
42356160Sru      {
42456160Sru        if (!errstr)
42556160Sru          dump_node_to_file (initial_node, user_output_filename,
42656160Sru                             dump_subnodes);
42756160Sru        else
428146515Sru          info_error ((char *) errstr, errarg1, errarg2);
42956160Sru      }
43056160Sru    else
43156160Sru      {
43221495Sjmacd
43356160Sru        if (errstr)
434146515Sru          begin_info_session_with_error (initial_node, (char *) errstr,
435146515Sru              errarg1, errarg2);
43656160Sru        /* If the user specified `--index-search=STRING' or
43756160Sru           --show-options, start the info session in the node
43856160Sru           corresponding to what they want. */
43956160Sru        else if (index_search_p || goto_invocation_p)
44056160Sru          {
44156160Sru            int status = 0;
44221495Sjmacd
44356160Sru            initialize_info_session (initial_node, 0);
44421495Sjmacd
44556160Sru            if (goto_invocation_p
44656160Sru                || index_entry_exists (windows, index_search_string))
44756160Sru              {
44856160Sru                terminal_prep_terminal ();
44956160Sru                terminal_clear_screen ();
45056160Sru                info_last_executed_command = (VFunction *)NULL;
45121495Sjmacd
45256160Sru                if (index_search_p)
45356160Sru                  do_info_index_search (windows, 0, index_search_string);
45456160Sru                else
45556160Sru                  {
45656160Sru                    /* If they said "info --show-options foo bar baz",
45756160Sru                       the last of the arguments is the program whose
45856160Sru                       options they want to see.  */
45956160Sru                    char **p = argv + optind;
46056160Sru                    char *program;
46121495Sjmacd
46256160Sru                    if (*p)
46356160Sru                      {
46456160Sru                        while (p[1])
46556160Sru                          p++;
46656160Sru                        program = xstrdup (*p);
46756160Sru                      }
46856160Sru                    else if (user_filename)
46956160Sru		      /* If there's no command-line arguments to
47056160Sru			 supply the program name, use the Info file
47156160Sru			 name (sans extension and leading directories)
47256160Sru			 instead.  */
47356160Sru		      program = program_name_from_file_name (user_filename);
47456160Sru		    else
47556160Sru		      program = xstrdup ("");
47621495Sjmacd
47756160Sru                    info_intuit_options_node (windows, initial_node, program);
47856160Sru                    free (program);
47956160Sru                  }
48021495Sjmacd
48193139Sru		if (user_output_filename)
48293139Sru		  {
48393139Sru		    dump_node_to_file (windows->node, user_output_filename,
48493139Sru				       dump_subnodes);
48593139Sru		  }
48693139Sru		else
48793139Sru		  info_read_and_dispatch ();
48821495Sjmacd
48956160Sru                /* On program exit, leave the cursor at the bottom of the
49056160Sru                   window, and restore the terminal IO. */
49156160Sru                terminal_goto_xy (0, screenheight - 1);
49256160Sru                terminal_clear_to_eol ();
49356160Sru                fflush (stdout);
49456160Sru                terminal_unprep_terminal ();
49556160Sru              }
49656160Sru            else
49756160Sru              {
49856160Sru                fprintf (stderr, _("no index entries found for `%s'\n"),
49956160Sru                         index_search_string);
50056160Sru                status = 2;
50156160Sru              }
50221495Sjmacd
50356160Sru            close_dribble_file ();
50456160Sru            xexit (status);
50556160Sru          }
50656160Sru        else
50756160Sru          begin_info_session (initial_node);
50856160Sru      }
50921495Sjmacd
51056160Sru    xexit (0);
51156160Sru  }
512116525Sru
513116525Sru  return 0; /* Avoid bogus warnings.  */
51421495Sjmacd}
51521495Sjmacd
51693139Sruvoid
517146515Sruadd_file_directory_to_path (char *filename)
51893139Sru{
51993139Sru  char *directory_name = xstrdup (filename);
52093139Sru  char *temp = filename_non_directory (directory_name);
52193139Sru
52293139Sru  if (temp != directory_name)
52393139Sru    {
52493139Sru      if (HAVE_DRIVE (directory_name) && temp == directory_name + 2)
52593139Sru	{
52693139Sru	  /* The directory of "d:foo" is stored as "d:.", to avoid
52793139Sru	     mixing it with "d:/" when a slash is appended.  */
52893139Sru	  *temp = '.';
52993139Sru	  temp += 2;
53093139Sru	}
53193139Sru      temp[-1] = 0;
53293139Sru      info_add_path (directory_name, INFOPATH_PREPEND);
53393139Sru    }
53493139Sru
53593139Sru  free (directory_name);
53693139Sru}
53793139Sru
53821495Sjmacd
53942660Smarkm/* Error handling.  */
54021495Sjmacd
54121495Sjmacd/* Non-zero if an error has been signalled. */
54221495Sjmacdint info_error_was_printed = 0;
54321495Sjmacd
54421495Sjmacd/* Non-zero means ring terminal bell on errors. */
54521495Sjmacdint info_error_rings_bell_p = 1;
54621495Sjmacd
54721495Sjmacd/* Print FORMAT with ARG1 and ARG2.  If the window system was initialized,
54821495Sjmacd   then the message is printed in the echo area.  Otherwise, a message is
54921495Sjmacd   output to stderr. */
55021495Sjmacdvoid
551146515Sruinfo_error (char *format, void *arg1, void *arg2)
55221495Sjmacd{
55321495Sjmacd  info_error_was_printed = 1;
55421495Sjmacd
55521495Sjmacd  if (!info_windows_initialized_p || display_inhibited)
55621495Sjmacd    {
55721495Sjmacd      fprintf (stderr, "%s: ", program_name);
55821495Sjmacd      fprintf (stderr, format, arg1, arg2);
55921495Sjmacd      fprintf (stderr, "\n");
56021495Sjmacd      fflush (stderr);
56121495Sjmacd    }
56221495Sjmacd  else
56321495Sjmacd    {
56421495Sjmacd      if (!echo_area_is_active)
56542660Smarkm        {
56642660Smarkm          if (info_error_rings_bell_p)
56742660Smarkm            terminal_ring_bell ();
56842660Smarkm          window_message_in_echo_area (format, arg1, arg2);
56942660Smarkm        }
57021495Sjmacd      else
57142660Smarkm        {
57242660Smarkm          NODE *temp;
57321495Sjmacd
57442660Smarkm          temp = build_message_node (format, arg1, arg2);
57542660Smarkm          if (info_error_rings_bell_p)
57642660Smarkm            terminal_ring_bell ();
57742660Smarkm          inform_in_echo_area (temp->contents);
57842660Smarkm          free (temp->contents);
57942660Smarkm          free (temp);
58042660Smarkm        }
58121495Sjmacd    }
58221495Sjmacd}
58321495Sjmacd
58456160Sru
58521495Sjmacd/* Produce a scaled down description of the available options to Info. */
58621495Sjmacdstatic void
587146515Sruinfo_short_help (void)
58821495Sjmacd{
58993139Sru#ifdef __MSDOS__
59093139Sru  static const char speech_friendly_string[] = N_("\
591100513Sru  -b, --speech-friendly        be friendly to speech synthesizers.\n");
59293139Sru#else
59393139Sru  static const char speech_friendly_string[] = "";
59493139Sru#endif
59593139Sru
596116525Sru
59742660Smarkm  printf (_("\
59856160SruUsage: %s [OPTION]... [MENU-ITEM...]\n\
59921495Sjmacd\n\
60042660SmarkmRead documentation in Info format.\n\
60121495Sjmacd\n\
60242660SmarkmOptions:\n\
603100513Sru      --apropos=STRING         look up STRING in all indices of all manuals.\n\
604100513Sru  -d, --directory=DIR          add DIR to INFOPATH.\n\
605100513Sru      --dribble=FILENAME       remember user keystrokes in FILENAME.\n\
606100513Sru  -f, --file=FILENAME          specify Info file to visit.\n\
607100513Sru  -h, --help                   display this help and exit.\n\
608100513Sru      --index-search=STRING    go to node pointed by index entry STRING.\n\
609100513Sru  -n, --node=NODENAME          specify nodes in first visited Info file.\n\
610100513Sru  -o, --output=FILENAME        output selected nodes to FILENAME.\n\
611146515Sru  -R, --raw-escapes            output \"raw\" ANSI escapes (default).\n\
612146515Sru      --no-raw-escapes         output escapes as literal text.\n\
613100513Sru      --restore=FILENAME       read initial keystrokes from FILENAME.\n\
614100513Sru  -O, --show-options, --usage  go to command-line options node.\n%s\
615100513Sru      --subnodes               recursively output menu items.\n\
616146515Sru  -w, --where, --location      print physical location of Info file.\n\
617100513Sru      --vi-keys                use vi-like and less-like key bindings.\n\
618100513Sru      --version                display version information and exit.\n\
61921495Sjmacd\n\
62056160SruThe first non-option argument, if present, is the menu entry to start from;\n\
62156160Sruit is searched for in all `dir' files along INFOPATH.\n\
62256160SruIf it is not present, info merges all `dir' files and shows the result.\n\
62342660SmarkmAny remaining arguments are treated as the names of menu\n\
62456160Sruitems relative to the initial node visited.\n\
62542660Smarkm\n\
62656160SruExamples:\n\
62756160Sru  info                       show top-level dir menu\n\
62856160Sru  info emacs                 start at emacs node from top-level dir\n\
62956160Sru  info emacs buffers         start at buffers node within emacs manual\n\
63056160Sru  info --show-options emacs  start at node with emacs' command line options\n\
63156160Sru  info -f ./foo.info         show file ./foo.info, not searching dir\n\
63256160Sru"),
63393139Sru  program_name, speech_friendly_string);
63421495Sjmacd
635100513Sru  puts (_("\n\
636100513SruEmail bug reports to bug-texinfo@gnu.org,\n\
637100513Srugeneral questions and discussion to help-texinfo@gnu.org.\n\
638100513SruTexinfo home page: http://www.gnu.org/software/texinfo/"));
639100513Sru
64056160Sru  xexit (0);
64121495Sjmacd}
64256160Sru
64356160Sru
64456160Sru/* Initialize strings for gettext.  Because gettext doesn't handle N_ or
64556160Sru   _ within macro definitions, we put shared messages into variables and
64656160Sru   use them that way.  This also has the advantage that there's only one
64756160Sru   copy of the strings.  */
64856160Sru
649116525Sruconst char *msg_cant_find_node;
650116525Sruconst char *msg_cant_file_node;
651116525Sruconst char *msg_cant_find_window;
652116525Sruconst char *msg_cant_find_point;
653116525Sruconst char *msg_cant_kill_last;
654116525Sruconst char *msg_no_menu_node;
655116525Sruconst char *msg_no_foot_node;
656116525Sruconst char *msg_no_xref_node;
657116525Sruconst char *msg_no_pointer;
658116525Sruconst char *msg_unknown_command;
659116525Sruconst char *msg_term_too_dumb;
660116525Sruconst char *msg_at_node_bottom;
661116525Sruconst char *msg_at_node_top;
662116525Sruconst char *msg_one_window;
663116525Sruconst char *msg_win_too_small;
664116525Sruconst char *msg_cant_make_help;
66556160Sru
66656160Srustatic void
667146515Sruinit_messages (void)
66856160Sru{
66956160Sru  msg_cant_find_node   = _("Cannot find node `%s'.");
67056160Sru  msg_cant_file_node   = _("Cannot find node `(%s)%s'.");
67156160Sru  msg_cant_find_window = _("Cannot find a window!");
67256160Sru  msg_cant_find_point  = _("Point doesn't appear within this window's node!");
67356160Sru  msg_cant_kill_last   = _("Cannot delete the last window.");
67456160Sru  msg_no_menu_node     = _("No menu in this node.");
67556160Sru  msg_no_foot_node     = _("No footnotes in this node.");
67656160Sru  msg_no_xref_node     = _("No cross references in this node.");
67756160Sru  msg_no_pointer       = _("No `%s' pointer for this node.");
67856160Sru  msg_unknown_command  = _("Unknown Info command `%c'; try `?' for help.");
67956160Sru  msg_term_too_dumb    = _("Terminal type `%s' is not smart enough to run Info.");
68056160Sru  msg_at_node_bottom   = _("You are already at the last page of this node.");
68156160Sru  msg_at_node_top      = _("You are already at the first page of this node.");
68256160Sru  msg_one_window       = _("Only one window.");
68356160Sru  msg_win_too_small    = _("Resulting window would be too small.");
68456160Sru  msg_cant_make_help   = _("Not enough room for a help window, please delete a window.");
68556160Sru}
686