#include "info.h"
#include "indices.h"
#include "dribble.h"
#include "getopt.h"
#if defined (HANDLE_MAN_PAGES)
# include "man.h"
#endif
int info_major_version = 2;
int info_minor_version = 18;
static char *program_name = NULL;
static int apropos_p = 0;
static char *apropos_search_string = (char *)NULL;
static int index_search_p = 0;
static char *index_search_string = (char *)NULL;
static int print_version_p = 0;
static int print_help_p = 0;
static char **user_nodenames = (char **)NULL;
static int user_nodenames_index = 0;
static int user_nodenames_slots = 0;
static char *user_filename = (char *)NULL;
static char *user_output_filename = (char *)NULL;
int dump_subnodes = 0;
#define APROPOS_OPTION 1
#define DRIBBLE_OPTION 2
#define RESTORE_OPTION 3
#define IDXSRCH_OPTION 4
static struct option long_options[] = {
{ "apropos", 1, 0, APROPOS_OPTION },
{ "directory", 1, 0, 'd' },
{ "node", 1, 0, 'n' },
{ "file", 1, 0, 'f' },
{ "subnodes", 0, &dump_subnodes, 1 },
{ "output", 1, 0, 'o' },
{ "help", 0, &print_help_p, 1 },
{ "version", 0, &print_version_p, 1 },
{ "dribble", 1, 0, DRIBBLE_OPTION },
{ "restore", 1, 0, RESTORE_OPTION },
{ "index-search", 1, 0, IDXSRCH_OPTION },
{NULL, 0, NULL, 0}
};
static char *short_options = "d:n:f:o:s";
int info_windows_initialized_p = 0;
static void info_short_help (), remember_info_program_name ();
int
main (argc, argv)
int argc;
char **argv;
{
int getopt_long_index;
NODE *initial_node;
remember_info_program_name (argv[0]);
#ifdef HAVE_SETLOCALE
setlocale (LC_ALL, "");
#endif
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
while (1)
{
int option_character;
option_character = getopt_long
(argc, argv, short_options, long_options, &getopt_long_index);
if (option_character == EOF)
break;
if (option_character == 0 && long_options[getopt_long_index].flag == 0)
option_character = long_options[getopt_long_index].val;
switch (option_character)
{
case 0:
break;
case 'd':
info_add_path (optarg, INFOPATH_PREPEND);
break;
case 'n':
add_pointer_to_array (optarg, user_nodenames_index, user_nodenames,
user_nodenames_slots, 10, char *);
break;
case 'f':
if (user_filename)
free (user_filename);
user_filename = xstrdup (optarg);
break;
case 'o':
if (user_output_filename)
free (user_output_filename);
user_output_filename = xstrdup (optarg);
break;
case 's':
dump_subnodes = 1;
break;
case APROPOS_OPTION:
apropos_p = 1;
maybe_free (apropos_search_string);
apropos_search_string = xstrdup (optarg);
break;
case DRIBBLE_OPTION:
close_dribble_file ();
open_dribble_file (optarg);
break;
case RESTORE_OPTION:
info_set_input_from_file (optarg);
break;
case IDXSRCH_OPTION:
index_search_p = 1;
maybe_free (index_search_string);
index_search_string = xstrdup (optarg);
break;
default:
fprintf (stderr, _("Try --help for more information."));
exit (1);
}
}
if ((!isatty (fileno (stdout))) && (user_output_filename == (char *)NULL))
{
user_output_filename = xstrdup ("-");
dump_subnodes = 1;
}
if (print_version_p)
{
printf ("%s (GNU %s %s) %s\n", program_name, PACKAGE, VERSION,
version_string ());
printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
There is NO warranty. You may redistribute this software\n\
under the terms of the GNU General Public License.\n\
For more information about these matters, see the files named COPYING.\n"),
"1998");
exit (0);
}
if (print_help_p)
{
info_short_help ();
exit (0);
}
if (!infopath)
{
char *path_from_env = getenv ("INFOPATH");
if (path_from_env)
{
unsigned len = strlen (path_from_env);
if (len && path_from_env[len - 1] == ':')
{
path_from_env[len - 1] = 0;
info_add_path (DEFAULT_INFOPATH, INFOPATH_PREPEND);
}
#ifdef INFODIR
info_add_path (INFODIR, INFOPATH_PREPEND);
#endif
info_add_path (path_from_env, INFOPATH_PREPEND);
}
else
{
info_add_path (DEFAULT_INFOPATH, INFOPATH_PREPEND);
#ifdef INFODIR
info_add_path (INFODIR, INFOPATH_PREPEND);
#endif
}
}
if (user_filename)
{
char *directory_name = xstrdup (user_filename);
char *temp = filename_non_directory (directory_name);
if (temp != directory_name)
{
*temp = 0;
info_add_path (directory_name, INFOPATH_PREPEND);
}
free (directory_name);
}
if (apropos_p)
{
info_apropos (apropos_search_string);
exit (0);
}
initial_node = info_get_node (user_filename,
user_nodenames ? user_nodenames[0] : NULL);
if (!initial_node)
{
if (info_recent_file_error)
info_error (info_recent_file_error);
else
info_error
(CANT_FIND_NODE, user_nodenames ? user_nodenames[0] : "Top");
exit (1);
}
if (user_nodenames_index > 1)
{
free (initial_node);
if (user_output_filename)
dump_nodes_to_file
(user_filename, user_nodenames, user_output_filename, dump_subnodes);
else
begin_multiple_window_info_session (user_filename, user_nodenames);
exit (0);
}
if (index_search_p)
{
int status = 0;
initialize_info_session (initial_node, 0);
if (index_entry_exists (windows, index_search_string))
{
terminal_clear_screen ();
terminal_prep_terminal ();
display_update_display (windows);
info_last_executed_command = (VFunction *)NULL;
do_info_index_search (windows, 0, index_search_string);
info_read_and_dispatch ();
terminal_unprep_terminal ();
terminal_goto_xy (0, screenheight - 1);
terminal_clear_to_eol ();
fflush (stdout);
}
else
{
fputs (_("no entries found\n"), stderr);
status = 2;
}
close_dribble_file ();
exit (status);
}
while (optind != argc)
{
REFERENCE **menu;
REFERENCE *entry;
NODE *node;
char *arg;
static char *first_arg = (char *)NULL;
arg = argv[optind++];
if (!first_arg)
first_arg = arg;
menu = info_menu_of_node (initial_node);
if (!menu)
{
#if defined (HANDLE_MAN_PAGES)
if (first_arg == arg)
{
node = make_manpage_node (first_arg);
if (node)
goto maybe_got_node;
}
#endif
begin_info_session_with_error
(initial_node, _("There is no menu in this node."));
exit (0);
}
entry = info_get_labeled_reference (arg, menu);
if (!entry)
{
register int i;
int best_guess = -1;
for (i = 0; (entry = menu[i]); i++)
{
if (strcasecmp (entry->label, arg) == 0)
break;
else
if (strncasecmp (entry->label, arg, strlen (arg)) == 0)
best_guess = i;
}
if (!entry && best_guess != -1)
entry = menu[best_guess];
}
if (!entry)
{
char *error_message = _("There is no menu item \"%s\" in this node.");
#if defined (HANDLE_MAN_PAGES)
if (first_arg == arg)
{
node = make_manpage_node (first_arg);
if (node)
goto maybe_got_node;
}
#endif
info_free_references (menu);
if (user_output_filename)
info_error (error_message, arg);
else
begin_info_session_with_error (initial_node, error_message, arg);
exit (0);
}
if (!entry->filename)
{
if (initial_node->parent)
entry->filename = xstrdup (initial_node->parent);
else
entry->filename = xstrdup (initial_node->filename);
}
node = info_get_node (entry->filename, entry->nodename);
#if defined (HANDLE_MAN_PAGES)
if ((first_arg == arg) && !node)
{
node = make_manpage_node (first_arg);
if (node)
goto maybe_got_node;
}
#endif
if (!node && entry->nodename &&
(strcmp (entry->label, entry->nodename) == 0))
node = info_get_node (entry->label, "Top");
maybe_got_node:
if (node)
{
free (initial_node);
initial_node = node;
info_free_references (menu);
}
else
{
char *temp = xstrdup (entry->label);
char *error_message;
error_message = _("Unable to find the node referenced by \"%s\".");
info_free_references (menu);
if (user_output_filename)
info_error (error_message, temp);
else
begin_info_session_with_error (initial_node, error_message, temp);
exit (0);
}
}
if (user_output_filename)
dump_node_to_file (initial_node, user_output_filename, dump_subnodes);
else
begin_info_session (initial_node);
exit (0);
}
char *
version_string ()
{
static char *vstring = (char *)NULL;
if (!vstring)
{
vstring = (char *)xmalloc (50);
sprintf (vstring, "%d.%d", info_major_version, info_minor_version);
}
return (vstring);
}
static void
remember_info_program_name (fullpath)
char *fullpath;
{
char *filename;
filename = filename_non_directory (fullpath);
program_name = xstrdup (filename);
}
int info_error_was_printed = 0;
int info_error_rings_bell_p = 1;
void
info_error (format, arg1, arg2)
char *format;
void *arg1, *arg2;
{
info_error_was_printed = 1;
if (!info_windows_initialized_p || display_inhibited)
{
fprintf (stderr, "%s: ", program_name);
fprintf (stderr, format, arg1, arg2);
fprintf (stderr, "\n");
fflush (stderr);
}
else
{
if (!echo_area_is_active)
{
if (info_error_rings_bell_p)
terminal_ring_bell ();
window_message_in_echo_area (format, arg1, arg2);
}
else
{
NODE *temp;
temp = build_message_node (format, arg1, arg2);
if (info_error_rings_bell_p)
terminal_ring_bell ();
inform_in_echo_area (temp->contents);
free (temp->contents);
free (temp);
}
}
}
static void
info_short_help ()
{
printf (_("\
Usage: %s [OPTION]... [INFO-FILE [MENU-ITEM...]]\n\
\n\
Read documentation in Info format.\n\
For more complete documentation on how to use Info, run `info info options'.\n\
\n\
Options:\n\
--directory DIR add DIR to INFOPATH.\n\
--dribble FILENAME remember user keystrokes in FILENAME.\n\
--file FILENAME specify Info file to visit.\n\
--node NODENAME specify nodes in first visited Info file.\n\
--output FILENAME output selected nodes to FILENAME.\n\
--restore FILENAME read initial keystrokes from FILENAME.\n\
--subnodes recursively output menu items.\n\
--help display this help and exit.\n\
--version display version information and exit.\n\
\n\
The first argument, if present, is the name of the Info file to read.\n\
Any remaining arguments are treated as the names of menu\n\
items in the initial node visited. For example, `info emacs buffers'\n\
moves to the node `buffers' in the info file `emacs'.\n\
\n\
Email bug reports to bug-texinfo@gnu.org."), program_name);
exit (0);
}