home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 June
/
SIMTEL_0692.cdr
/
msdos
/
gnuish
/
mkinf10.arc
/
info.d
< prev
next >
Wrap
Text File
|
1990-11-01
|
43KB
|
1,887 lines
/* info -- a stand-alone Info program
Copyright (C) 1987 Free Software Foundation, Inc.
This file is part of GNU Info.
GNU Info is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY. No author or distributor accepts
responsibility to anyone for the consequences of using it or for
whether it serves any particular purpose or works at all, unless he
says so in writing. Refer to the GNU Emacs General Public License
for full details.
Everyone is granted permission to copy, modify and redistribute
GNU Info, but only under the conditions described in the GNU Emacs
General Public License. A copy of this license is supposed to
have been given to you along with GNU Emacs so you can know your
rights and responsibilities. It should be in a file named COPYING.
Among other things, the copyright notice and this notice must be
preserved on all copies. */
/* MS-DOS port (c) 1990 by Thorsten Ohl, td12@ddagsi3.bitnet
This port is also distributed under the terms of the
GNU General Public License as published by the
Free Software Foundation.
Please note that this file is not identical to the
original GNU release, you should have received this
code as patch to the official release.
$Header: e:/gnu/info/RCS/info.d 0.1.1.1 90/10/05 11:25:17 tho Exp $
*/
/* cont'd from info.c */
/*===(cut here)===*/
/* **************************************************************** */
/* */
/* Page Display */
/* */
/* **************************************************************** */
/* The display functions for GNU Info. */
int display_ch, display_cv;
#if 0
int point_ch, point_cv; /* the located values of Point */
#endif
LONG display_point;
VOID
display_page ()
{
/* Display the current page from pagetop down to the bottom of the
page or the bottom of the node, whichever comes first. */
display_point = pagetop;
display_ch = the_window.left;
display_cv = the_window.top;
generic_page_display ();
}
VOID
generic_page_display ()
{
/* Print the page from display_point to bottom of node, or window,
whichever comes first. Start printing at display_ch, display_cv. */
int done_with_display = 0;
int character;
goto_xy (display_ch, display_cv);
while (!done_with_display)
{
if (display_point == nodebot)
{
clear_eop ();
goto display_finish;
}
character = info_file[display_point];
if ((display_width (character, the_window.ch) +the_window.ch)
>=the_window.right)
display_carefully (character);
else
charout (character);
if ((the_window.cv >= the_window.bottom)
|| (the_window.cv == the_window.top
&& the_window.ch == the_window.left))
{
display_finish:
make_modeline ();
done_with_display++;
continue;
}
else
display_point++;
}
}
VOID
display_carefully (character)
int character;
{
/* Display character carefully, insuring that no scrolling takes place, even
in the case of funky control characters. */
if (CTRL_P (character))
{
switch (character)
{
case RETURN:
case NEWLINE:
case TAB:
clear_eol ();
advance (the_window.right - the_window.ch);
break;
default:
charout ('^');
if (the_window.cv == the_window.bottom)
break;
else
charout (UNCTRL (character));
}
}
else
charout (character);
}
boolean
next_page ()
{
/* Move to the next page in this node. Return FALSE if
we can't get to the next page. */
LONG pointer =
forward_lines ((the_window.bottom - the_window.top) - 2, pagetop);
if (pointer >= nodebot)
return (false);
pagetop = pointer;
return (true);
}
boolean
prev_page ()
{
/* Move to the previous page in this node. Return FALSE if
there is no previous page. */
LONG pointer =
back_lines ((the_window.bottom - the_window.top) - 2, pagetop);
if (pagetop == nodetop)
return (false);
if (pointer < nodetop)
pointer = nodetop;
pagetop = pointer;
return (true);
}
/* **************************************************************** */
/* */
/* Utility Functions */
/* */
/* **************************************************************** */
char *search_buffer; /* area in ram to scan through. */
LONG buffer_bottom; /* Length of this area. */
void
set_search_constraints (buffer, extent)
char *buffer;
LONG extent;
{
/* Set the global variables that all of these routines use. */
search_buffer = buffer;
buffer_bottom = extent;
}
LONG
to_beg_line (from)
LONG from;
{
/* Move back to the start of this line. */
while (from && search_buffer[from - 1] != '\n')
from--;
return (from);
}
LONG
to_end_line (from)
LONG from;
{
/* Move forward to the end of this line. */
while (from < buffer_bottom && search_buffer[from] != '\n')
from++;
return (from);
}
LONG
back_lines (count, starting_pos)
int count;
LONG starting_pos;
{
/* Move back count lines in search_buffer starting at starting_pos.
Returns the start of that line. */
starting_pos = to_beg_line (starting_pos);
while (starting_pos && count)
{
starting_pos = to_beg_line (starting_pos - 1);
count--;
}
return (starting_pos);
}
LONG
forward_lines (count, starting_pos)
int count;
LONG starting_pos;
{
/* Move forward count lines starting at starting_pos.
Returns the start of that line. */
starting_pos = to_end_line (starting_pos);
while (starting_pos < buffer_bottom && count)
{
starting_pos = to_end_line (starting_pos + 1);
count--;
}
return (to_beg_line (starting_pos));
}
LONG
search_forward (string, starting_pos)
char *string;
LONG starting_pos;
{
/* Search for STRING in SEARCH_BUFFER starting at STARTING_POS.
Return the location of the string, or -1 if not found. */
int len = strlen (string);
while ((starting_pos + len) < buffer_bottom)
{
if (strnicmp (search_buffer + starting_pos, string, len) == 0)
return (starting_pos);
else
starting_pos++;
}
return (-1);
}
LONG
search_backward (string, starting_pos)
char *string;
LONG starting_pos;
{
/* Search for STRING in SEARCH_BUFFER starting at STARTING_POS.
Return the location of the string, or -1 if not found. */
int len = strlen (string);
while (starting_pos - len > -1)
{
if (strnicmp (search_buffer + (starting_pos - len), string, len) == 0)
return (starting_pos - len);
else
starting_pos--;
}
return (-1);
}
LONG
string_in_line (string, pointer)
char *string;
LONG pointer;
{
/* Only search for STRING from POINTER to end of line. Return offset
of string, or -1 if not found. */
LONG old_buffer_bottom = buffer_bottom;
set_search_constraints (search_buffer, to_end_line (pointer));
pointer = search_forward (string, pointer);
buffer_bottom = old_buffer_bottom;
return (pointer);
}
/* Skip whitespace characters at OFFSET in SEARCH_BUFFER.
Return the next non-whitespace character or -1 if BUFFER_BOTTOM
is reached. */
LONG
skip_whitespace (offset)
LONG offset;
{
int character;
while (offset < buffer_bottom)
{
character = search_buffer[offset];
if (character == ' ' || character == '\t')
offset++;
else
return (offset);
}
return (-1);
}
/* Skip whitespace characters including <CR> at OFFSET in
SEARCH_BUFFER. Return the position of the next non-whitespace
character, or -1 if BUFFER_BOTTOM is reached. */
LONG
skip_whitespace_and_cr (offset)
LONG offset;
{
while (true)
{
offset = skip_whitespace (offset);
if (offset > 0 && search_buffer[offset] != '\n')
return (offset);
else
offset++;
}
}
/* Extract the node name part of the of the text after the FIELD.
Place the node name into NODENAME. Assume the line starts at
OFFSET in SEARCH_BUFFER. */
boolean
extract_field (field_name, nodename, offset)
char *field_name, *nodename;
LONG offset;
{
LONG temp;
int character;
temp = string_in_line (field_name, offset);
if (temp < 0)
return (false);
temp += strlen (field_name);
temp = skip_whitespace (temp);
/* Okay, place the following text into NODENAME. */
while ((character = search_buffer[temp]) != ','
&& character != '\n'
&& character != '\t')
{
*nodename = character;
nodename++;
temp++;
}
*nodename = '\0';
return (true);
}
boolean
looking_at (string, pointer)
char *string;
LONG pointer;
{
/* Return true if pointer is exactly at string, else false. */
if (strnicmp (search_buffer + pointer, string, strlen (string)) == 0)
return (true);
else
return (false);
}
extern NODEINFO *Info_History;
/* Save the current filename, nodename, and position on the history list.
We prepend. */
boolean
push_node (filename, nodename, page_position, node_position)
char *filename, *nodename;
LONG page_position, node_position;
{
NODEINFO *newnode = (NODEINFO *) xmalloc (sizeof (NODEINFO));
newnode->next = Info_History;
newnode->filename = (char *) xmalloc (strlen (filename) + 1);
strcpy (newnode->filename, filename);
newnode->nodename = (char *) xmalloc (strlen (nodename) + 1);
strcpy (newnode->nodename, nodename);
newnode->pagetop = page_position;
newnode->nodetop = node_position;
Info_History = newnode;
return (true);
}
boolean
pop_node (filename, nodename, nodetop, pagetop)
char *filename, *nodename;
LONG *nodetop, *pagetop;
{
/* Pop one node from the node list, leaving the values in
passed variables. */
if (Info_History->next == (NODEINFO *) NULL)
{
display_error ("At beginning of history now!");
return (false);
}
else
{
NODEINFO *releaser = Info_History;
if (strcmp (Info_History->filename, last_loaded_info_file) != 0)
last_loaded_info_file[0] = '\0'; /* Force the reloading of the file. */
strcpy (filename, Info_History->filename);
strcpy (nodename, Info_History->nodename);
*pagetop = Info_History->pagetop;
*nodetop = Info_History->nodetop;
free (Info_History->nodename);
free (Info_History->filename);
Info_History = Info_History->next;
free (releaser);
return (true);
}
}
#ifndef MSDOS
/* Whoops, Unix doesn't have strnicmp. */
strnicmp (string1, string2, count)
char *string1, *string2;
{
/* Compare at most COUNT characters from string1 to string2. Case
doesn't matter. */
char ch1, ch2;
while (count)
{
ch1 = *string1++;
ch2 = *string2++;
if (to_upper (ch1) == to_upper (ch2))
count--;
else
break;
}
return (count);
}
#endif /* not MSDOS */
boolean
get_y_or_n_p ()
{
/* Make the user type "Y" or "N". */
int character;
print_string (" (Y or N)?");
clear_eol ();
until_we_like_it:
character = blink_cursor ();
if (character == EOF)
return (false);
if (to_upper (character) == 'Y')
{
charout (character);
return (true);
}
if (to_upper (character) == 'N')
{
charout (character);
return (false);
}
if (character == ABORT_CHAR)
{
ding ();
return (false);
}
goto until_we_like_it;
}
VOID
indent_to (screen_column)
int screen_column;
{
/* Move the cursor to the desired column in the window. */
int counter = screen_column - the_window.ch;
if (counter > 0)
{
while (counter--)
charout (' ');
}
else if (screen_column != 0)
charout (' ');
}
/* **************************************************************** */
/* */
/* Error output/handling. */
/* */
/* **************************************************************** */
file_error (file)
char *file;
{
/* Display specific error from known file error table. */
#ifndef MSDOS
extern int errno;
extern int sys_nerr;
extern char *sys_errlist[];
#endif /* not MSDOS */
if (errno < sys_nerr)
return (display_error ("%s: %s", file, sys_errlist[errno]));
else
return (display_error ("%s: Unknown error %d", file, errno));
}
#ifdef MSDOS
int CDECL
display_error (char *format_string, ...)
{
/* Display the error in the echo-area using format_string and args.
This is a specialized interface to printf. */
extern boolean terminal_inited_p;
char output_buffer[1024];
va_list arg_ptr;
va_start (arg_ptr, format_string);
if (totally_inhibit_errors)
return (1);
vsprintf (output_buffer, format_string, arg_ptr);
if (terminal_inited_p)
{
new_echo_area ();
ding ();
print_string (output_buffer);
close_echo_area ();
}
else
fprintf (stderr, "%s\n", output_buffer);
return (1);
}
#else /* not MSDOS */
display_error (format_string, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
char *format_string;
{
/* Display the error in the echo-area using format_string and args.
This is a specialized interface to printf. */
extern boolean terminal_inited_p;
char output_buffer[1024];
if (totally_inhibit_errors)
return (1);
sprintf (output_buffer, format_string, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
if (terminal_inited_p)
{
new_echo_area ();
ding ();
print_string (output_buffer);
close_echo_area ();
}
else
fprintf (stderr, "%s\n", output_buffer);
return (1);
}
#endif /* not MSDOS */
brians_error ()
{
/* Tell everybody what a loser I am. If you see this error,
send me a bug report. */
display_error ("You are never supposed to see this error. Tell Brian to fix this.");
return (-1);
}
#ifndef MSDOS
/* **************************************************************** */
/* */
/* Terminal IO, and Driver */
/* */
/* **************************************************************** */
/* The Unix termcap interface code. */
#define NO_ERROR 0
#define GENERIC_ERROR 1
#define NO_TERMINAL_DESCRIPTOR 2
#define OUT_OF_MEMORY 3
#define BAD_TERMINAL 4
#define FERROR(msg) fprintf (stderr, msg); exit (GENERIC_ERROR)
extern int tgetnum (), tgetflag ();
extern char *tgetstr ();
extern char *tgoto ();
#define certainly_enough_space 2048 /* page 3, Section 1.1, para 4 */
#ifdef UNIX
char termcap_buffer[certainly_enough_space];
#else
#define termcap_buffer NULL
#endif
/* You CANNOT remove these next four vars. TERMCAP needs them to operate. */
char PC;
char *BC;
char *UP;
short ospeed;
/* A huge array of stuff to get from termcap initialization. */
#define tc_int 0
#define tc_char tc_int+1
#define tc_flag tc_char+1
#define tc_last tc_flag+1
typedef int flag;
/* First, the variables which this array refers to */
/* Capabilities */
int terminal_rows; /* {tc_int, "co" */
int terminal_lines; /* {tc_int, "li" */
flag terminal_is_generic; /* {tc_flag,"gn" */
/* Cursor Motion */
char *terminal_goto; /* {tc_char,"cm" */
char *terminal_home; /* {tc_char,"ho" */
char *terminal_cursor_left; /* {tc_char,"le" */
char *terminal_cursor_right; /* {tc_char,"nd" */
char *terminal_cursor_up; /* {tc_char,"up" */
char *terminal_cursor_down; /* {tc_char,"do" */
/* Screen Clearing */
char *terminal_clearpage; /* {tc_char,"cl" */
char *terminal_clearEOP; /* {tc_char,"cd" */
char *terminal_clearEOL; /* {tc_char,"ce" */
/* "Standout" */
char *terminal_standout_begin; /* {tc_char,"so" */
char *terminal_standout_end; /* {tc_char,"se" */
/* Reverse Video */
char *terminal_inverse_begin; /* {tc_char,"mr" */
char *terminal_end_attributes; /* {tc_char,"me" */
/* Ding! */
char *terminal_ear_bell; /* {tc_char,"bl" */
/* Terminal Initialization */
char *terminal_use_begin; /* {tc_char,"ti" */
char *terminal_use_end; /* {tc_char,"te" */
/* Padding Stuff */
char *terminal_padding; /* {tc_char,"pc" */
/* Now the whopping big array */
typedef struct
{
char type;
char *name;
char *value;
} termcap_capability_struct;
termcap_capability_struct capabilities[] = {
/* Capabilities */
{tc_int, "co", (char *) &terminal_rows},
{tc_int, "li", (char *) &terminal_lines},
{tc_flag, "gn", (char *) &terminal_is_generic},
/* Cursor Motion */
{tc_char, "cm", (char *) &terminal_goto},
{tc_char, "ho", (char *) &terminal_home},
{tc_char, "le", (char *) &terminal_cursor_left},
{tc_char, "nd", (char *) &terminal_cursor_right},
{tc_char, "up", (char *) &terminal_cursor_up},
{tc_char, "do", (char *) &terminal_cursor_down},
/* Screen Clearing */
{tc_char, "cl", (char *) &terminal_clearpage},
{tc_char, "cd", (char *) &terminal_clearEOP},
{tc_char, "ce", (char *) &terminal_clearEOL},
/* "Standout" */
{tc_char, "so", (char *) &terminal_standout_begin},
{tc_char, "se", (char *) &terminal_standout_end},
/* Reverse Video */
{tc_char, "mr", (char *) &terminal_inverse_begin},
{tc_char, "me", (char *) &terminal_end_attributes},
/* Ding! */
{tc_char, "bl", (char *) &terminal_ear_bell},
/* Terminal Initialization */
{tc_char, "ti", (char *) &terminal_use_begin},
{tc_char, "te", (char *) &terminal_use_end},
/* Padding Stuff */
{tc_char, "pc", (char *) &terminal_padding},
/* Terminate this array with a var of type tc_last */
{tc_last, NULL, NULL}
};
int terminal_opened_p = 0;
open_terminal_io ()
{
int error;
if (terminal_opened_p)
return (NO_ERROR);
if ((error = get_terminal_info ()) != NO_ERROR)
return (error);
if ((error = get_terminal_vars (capabilities)) != NO_ERROR)
return (error);
/* Now, make sure we have the capabilites that we need. */
if (terminal_is_generic)
return (BAD_TERMINAL);
terminal_opened_p++;
return (NO_ERROR);
}
get_terminal_info ()
{
char temp_string_buffer[256];
int result;
char *terminal_name = getenv ("TERM");
if (terminal_name == NULL || *terminal_name == 0
|| (strcmp (terminal_name, "dialup") == 0))
{
terminal_name = temp_string_buffer;
printf ("\nTerminal Type:");
fflush (stdout);
fgets (terminal_name, 256, stdin);
if (!(*terminal_name))
return (NO_TERMINAL_DESCRIPTOR);
}
/* #define VERBOSE_GET_TERMINAL 1 */
#ifdef VERBOSE_GET_TERMINAL
#define buffer_limit 256
#define opsys_termcap_filename "/etc/termcap"
/* We hack question mark if that is what the user typed. All this means
is we read /etc/termcap, and prettily print out the names of terminals
that we find. */
if (terminal_name[0] == '?' && !terminal_name[1])
{
FILE *termcap_file;
if ((termcap_file = fopen (opsys_termcap_filename, "r")) != NULL)
{
int result;
char line_buffer[buffer_limit];
int terminal_count = 0;
while ((readline_termcap (termcap_file, line_buffer)) != EOF)
{
char first_char = *line_buffer;
if (first_char == '#' || first_char == ' '
|| first_char == '\t' || first_char == '\n')
;
else
{
/* print the names the pretty way. */
printf ("\n%s", line_buffer); /* liar */
terminal_count++;
}
}
fclose (termcap_file);
if (terminal_count)
{
printf ("\n%d terminals listed.\n", terminal_count);
}
else
printf ("\nNo terminals were listed. Brian's mistake.\n");
}
else
{
fprintf (stderr,
"\nNo such system file as %s!\nWe lose badly.\n",
opsys_termcap_filename);
return (NO_TERMINAL_DESCRIPTOR);
}
return (get_terminal_info ());
}
#endif /* VERBOSE_GET_TERMINAL */
result = tgetent (termcap_buffer, terminal_name);
if (!result)
return (NO_TERMINAL_DESCRIPTOR);
else
return (NO_ERROR);
}
#ifdef VERBOSE_GET_TERMINAL
readline_termcap (stream, buffer)
FILE *stream;
char *buffer;
{
int c;
int buffer_index = 0;
while ((c = getc (stream)) != EOF && c != '\n')
{
if (buffer_index != buffer_limit - 1)
{
buffer[buffer_index++] = c;
}
}
buffer[buffer_index] = 0;
if (c == EOF)
{
return ((buffer_index) ? 0 : EOF);
}
else
return (0);
}
#endif /* VERBOSE_GET_TERMINAL */
get_terminal_vars (from_array)
termcap_capability_struct from_array[];
{
/* For each element of "from_array", read the corresponding variable's
value into the right place. You should comment out the parts of the
array that you don't need, and their corresponding variable
declarations. */
int i;
register termcap_capability_struct *item;
#ifdef UNIX /* this shit makes my code ugly. */
char *buffer = (char *) xmalloc (strlen (termcap_buffer) + 1);
#define buffer_space &buffer
#else
#define buffer_space 0
#endif
for (i = 0; (item = &from_array[i]) && (item->type != tc_last); i++)
{
switch (item->type)
{
case tc_int:
*((int *) (item->value)) = tgetnum (item->name);
break;
case tc_flag:
*((int *) item->value) = tgetflag (item->name);
break;
case tc_char:
*((char **) item->value) = tgetstr (item->name, buffer_space);
break;
default:
FERROR ("Bad entry scanned in tc_struct[].\n \
Ask Brian to fix this someday.\n");
}
}
PC = terminal_padding ? terminal_padding[0] : 0;
BC = terminal_cursor_left;
UP = terminal_cursor_up;
return (NO_ERROR);
}
get_term_width ()
{
return (tgetnum ("co"));
}
get_term_height ()
{
return (tgetnum ("li"));
}
/* #define TERMINAL_INFO_PRINTING */
#ifdef TERMINAL_INFO_PRINTING
show_terminal_info (from_array)
termcap_capability_struct from_array[];
{
/* Scan this (already "get_terminal_vars"ed) array, printing out the
capability name, and value for each entry. Pretty print the value
so that the terminal doesn't actually do anything, shitbrain. */
int i;
register termcap_capability_struct *item;
for (i = 0; ((item = &from_array[i]) && ((item->type) != tc_last)); i++)
{
char *type_name;
switch (item->type)
{
case tc_int:
type_name = "int ";
break;
case tc_flag:
type_name = "flag";
break;
case tc_char:
type_name = "char";
break;
default:
type_name = "Broken";
}
printf ("\t%s\t%s = ", type_name, item->name);
switch (item->type)
{
case tc_int:
case tc_flag:
printf ("%d", *((int *) item->value));
break;
case tc_char:
tc_pretty_print (*((char **) item->value));
break;
}
printf ("\n");
}
}
tc_pretty_print (string)
char *string;
{
/* Print the contents of string without sending anything that isn't
a normal printing ASCII character. */
char c;
while (c = *string++)
{
if (c < ' ')
{
putchar ('^');
c += 64;
}
putchar (c);
}
}
#endif /* TERMINAL_INFO_PRINTING */
#endif /* not MSDOS */
/* **************************************************************** */
/* */
/* Character IO, and driver */
/* */
/* **************************************************************** */
WINDOW the_window = {0, 0, 80, 24, 0, 0};
WINDOW_LIST *window_stack = NULL;
WINDOW terminal_window = {0, 0, 80, 24, 0, 0};
char *widest_line;
boolean terminal_inited_p = false;
VOID
init_terminal_io ()
{
/* Start up the character io stuff. */
if (!terminal_inited_p)
{
opsys_init_terminal ();
widest_line = (char *) xmalloc (terminal_rows);
if (terminal_lines <= 0)
terminal_lines = 24;
terminal_inited_p = true;
}
terminal_window.left = 0;
terminal_window.top = 0;
terminal_window.right = terminal_rows;
terminal_window.bottom = terminal_lines;
set_window (&terminal_window);
terminal_window.bottom -= 2;
set_window (&terminal_window);
init_echo_area (the_window.left, the_window.bottom + 1,
the_window.right, terminal_lines);
#ifndef MSDOS
/* Here is a list of things that the terminal has to be able to do. Do
you think that this is too harsh? */
if (
!terminal_goto || /* we can't move the cursor. */
!terminal_lines /* we don't how many lines it has. */
)
{
}
#endif /* not MSDOS */
}
VOID
ding ()
{
/* Ring the terminal bell. */
#ifndef MSDOS
extern char *terminal_ear_bell;
#endif
if (terminal_ear_bell)
do_term (terminal_ear_bell);
else
putchar (CTRL ('G'));
fflush (stdout);
}
int untyi_char = 0;
boolean inhibit_output = false;
blink_cursor ()
{
/* Return a character from stdin, or the last unread character
if there is one available. */
int character;
if (untyi_char)
{
character = untyi_char;
untyi_char = 0;
}
else
character = getc (stdin);
return (character);
}
VOID
charout (character)
int character;
{
/* Display single character on the terminal screen. If the
character would run off the right hand edge of the screen,
advance the cursor to the next line. */
if (inhibit_output)
return;
if (CTRL_P (character))
{
/* Display this character special if it is Control. */
switch (character)
{
case NEWLINE:
case RETURN:
print_cr ();
break;
case TAB:
print_tab ();
break;
default:
charout ('^');
charout (UNCTRL (character));
}
}
else
{
#ifdef MSDOS
do_term (character);
#else /* not MSDOS */
putchar (character);
#endif /* not MSDOS */
advance (1);
}
}
VOID
advance (amount)
int amount;
{
/* Move the cursor amount character positions. */
int old_window_cv = the_window.cv;
while (amount-- > 0)
{
the_window.ch ++;
if (the_window.ch >=the_window.right)
{
the_window.ch = (the_window.ch -the_window.right) +the_window.left;
the_window.cv++;
if (the_window.cv >= the_window.bottom)
{
the_window.cv = the_window.top;
}
}
}
if (the_window.cv != old_window_cv)
{
goto_xy (the_window.ch, the_window.cv);
}
}
#ifdef MSDOS
VOID CDECL
print_string (string, ...)
char *string;
{
/* Print string using charout */
int character;
char buffer[2048];
int index = 0;
va_list arg_ptr;
va_start (arg_ptr, string);
vsprintf (buffer, string, arg_ptr);
while (character = buffer[index++])
charout (character);
}
#else /* not MSDOS */
VOID
print_string (string, a1, a2, a3, a4, a5)
char *string;
{
/* Print string using charout */
int character;
char buffer[2048];
int index = 0;
sprintf (buffer, string, a1, a2, a3, a4, a5);
while (character = buffer[index++])
charout (character);
}
#endif /* not MSDOS */
VOID
print_cr ()
{
extern boolean typing_out;
/* Display a carriage return. Clears to the end of the line first. */
clear_eol ();
if (typing_out)
{ /* Do the "MORE" stuff. */
int response;
if (the_window.cv + 2 == the_window.bottom)
{
goto_xy (the_window.left, the_window.cv + 1);
clear_eol ();
print_string ("[More]");
response = blink_cursor ();
if (response != SPACE)
{
untyi_char = response;
inhibit_output = true;
return;
}
else
{
goto_xy (the_window.left, the_window.cv);
clear_eol ();
goto_xy (the_window.left, the_window.top);
return;
}
}
}
advance (the_window.right - the_window.ch);
}
VOID
print_tab ()
{
/* Move the cursor to the next tab stop, blanking the intervening
spaces along the way. */
int destination =
(((the_window.ch -the_window.left) +8) & 0x0f8) + the_window.left;
if (destination >= the_window.right)
destination -= the_window.right;
while (the_window.ch !=destination)
charout (SPACE);
}
display_width (character, hpos)
int character, hpos;
{
int width = 1;
if (CTRL_P (character))
{
switch (character)
{
case RETURN:
case NEWLINE:
width = the_window.right - hpos;
break;
case TAB:
width = ((hpos + 8) & 0xf7) - hpos;
break;
default:
width = 2;
}
}
return (width);
}
VOID
I_goto_xy (xpos, ypos)
int xpos, ypos;
{
/* Like GOTO_XY, but do it right away. */
goto_xy (xpos, ypos);
fflush (stdout);
}
VOID
goto_xy (xpos, ypos)
int xpos, ypos;
{
/* Move the cursor, (and cursor variables) to xpos, ypos. */
the_window.ch = xpos;
the_window.cv = ypos;
opsys_goto_pos (xpos, ypos);
}
#ifdef SIGWINCH
clear_screen ()
{
/* Clear the screen, leaving ch and cv at the top of the window. */
goto_xy (the_window.left, the_window.top);
clear_eop_slowly ();
}
#endif /* SIGWINCH */
VOID
clear_eop_slowly ()
{
int temp_ch = the_window.ch;
int temp_cv = the_window.cv;
clear_eol ();
while (++the_window.cv < the_window.bottom)
{
goto_xy (the_window.left, the_window.cv);
clear_eol ();
}
goto_xy (temp_ch, temp_cv);
}
VOID
clear_eop ()
{
/* Clear from current cursor position to end of page. */
if (terminal_clearEOP)
do_term (terminal_clearEOP);
else
clear_eop_slowly ();
}
VOID
clear_eol ()
{
/* Clear from current cursor position to end of screen line */
int temp_ch = the_window.ch;
if (terminal_clearEOL)
do_term (terminal_clearEOL);
else
{
char *line = widest_line;
int i;
for (i = 0; i < the_window.right - the_window.ch; i++)
line[i] = ' ';
line[i] = '\0';
printf ("%s", line);
}
goto_xy (temp_ch, the_window.cv);
}
#ifdef SIGWINCH
with_output_to_window (window, function, arg1, arg2, arg3, arg4, arg5)
WINDOW *window;
Function *function;
{
/* call FUNCTION with WINDOW active. You can pass upto 5 args to the
function. This returns whatever FUNCTION returns. */
int result;
push_window ();
set_window (window);
result = (*function) (arg1, arg2, arg3, arg4, arg5);
pop_window ();
return (result);
}
#endif /* SIGWINCH */
VOID
set_window (window)
WINDOW *window;
{
/* Given a pointer to a window data structure, make that the current
window. */
bcopy (window, &the_window, sizeof (WINDOW));
}
VOID
push_window ()
{
/* save the current window on the window stack. */
WINDOW_LIST *new_window = (WINDOW_LIST *) xmalloc (sizeof (WINDOW_LIST));
new_window->next_window = window_stack;
window_stack = new_window;
new_window->ch = the_window.ch;
new_window->cv = the_window.cv;
new_window->top = the_window.top;
new_window->bottom = the_window.bottom;
new_window->left = the_window.left;
new_window->right = the_window.right;
}
VOID
pop_window ()
{
/* pop the top of the window_stack into the_window. */
set_window ((WINDOW *) window_stack);
if (window_stack->next_window)
{
WINDOW_LIST *thing_to_free = window_stack;
window_stack = window_stack->next_window;
free (thing_to_free);
}
goto_xy (the_window.ch, the_window.cv);
}
/* **************************************************************** */
/* */
/* "Opsys" functions. */
/* */
/* **************************************************************** */
/* The lowlevel terminal/file interface. Nothing ever really gets low level
when you're writing in C, though.
This file contains all of the "opsys" labels. You have to make a different
one if you want GNU Infos to run on machines that don't have unix. */
#ifndef MSDOS
extern char *terminal_use_begin, *terminal_use_end, *terminal_goto;
#endif
#ifdef TIOCGLTC
struct tchars original_tchars;
#endif
#ifdef TIOCGLTC
struct ltchars original_ltchars;
#endif
int original_tty_flags = 0;
int original_lmode;
#ifndef MSDOS
struct sgttyb ttybuff;
/* Yes, that's right, do things that the machine needs to get the terminal
into a usable mode. */
opsys_init_terminal ()
{
int tty = fileno (stdin);
ioctl (tty, TIOCGETP, &ttybuff);
if (!original_tty_flags)
original_tty_flags = ttybuff.sg_flags;
/* Make this terminal pass 8 bits around while we are using it. */
#ifdef PASS8
ttybuff.sg_flags |= PASS8;
#endif
#if defined (TIOCLGET) && defined (LPASS8)
{
int flags;
ioctl (tty, TIOCLGET, &flags);
original_lmode = flags;
flags |= LPASS8;
ioctl (tty, TIOCLSET, &flags);
}
#endif
#ifdef TIOCGETC
{
struct tchars temp;
ioctl (tty, TIOCGETC, &original_tchars);
bcopy (&original_tchars, &temp, sizeof (struct tchars));
temp.t_startc = temp.t_stopc = -1;
/* If the quit character conflicts with one of our commands, then
make it go away. */
if (temp.t_intrc == DELETE)
temp.t_intrc == -1;
if (temp.t_quitc == DELETE)
temp.t_quitc == -1;
ioctl (tty, TIOCSETC, &temp);
}
#endif /* TIOCGETC */
#ifdef TIOCGLTC
{
struct ltchars temp;
ioctl (tty, TIOCGLTC, &original_ltchars);
bcopy (&original_ltchars, &temp, sizeof (struct ltchars));
/* Make the interrupt keys go away. Just enough to make people happy. */
temp.t_lnextc = -1; /* C-v */
ioctl (tty, TIOCSLTC, &temp);
}
#endif /* TIOCGLTC */
ttybuff.sg_flags &= ~ECHO;
ttybuff.sg_flags |= CBREAK;
ioctl (tty, TIOCSETN, &ttybuff);
open_terminal_io ();
do_term (terminal_use_begin);
}
#endif /* not MSDOS */
/* Fix the terminal that I broke. */
VOID
restore_io ()
{
#ifndef MSDOS
int tty = fileno (stdin);
ioctl (tty, TIOCGETP, &ttybuff);
ttybuff.sg_flags = original_tty_flags;
ioctl (tty, TIOCSETN, &ttybuff);
#ifdef TIOCGETC
ioctl (tty, TIOCSETC, &original_tchars);
#endif /* TIOCGETC */
#ifdef TIOCGLTC
ioctl (tty, TIOCSLTC, &original_ltchars);
#endif /* TIOCGLTC */
#if defined (TIOCLGET) && defined (LPASS8)
ioctl (tty, TIOCLSET, &original_lmode);
#endif
#endif /* not MSDOS */
do_term (terminal_use_end);
}
#ifndef MSDOS
opsys_goto_pos (xpos, ypos)
int xpos, ypos;
{
do_term (tgoto (terminal_goto, xpos, ypos));
}
character_output_function (character)
char character;
{
putchar (character);
}
/* Generic interface to tputs. */
do_term (command)
char *command;
{
/* Send command to the terminal, with appropriate padding. */
tputs (command, 1, character_output_function);
}
#endif /* not MSDOS */
/* Filename manipulators, and the like. */
char local_temp_filename[FILENAME_LEN];
/* Expand the filename in partial to make a real name for
this operating system. This looks in INFO_PATHS in order to
find the correct file. If it can't find the file, it just
returns the path as you gave it. */
char *
opsys_filename (partial)
char *partial;
{
int initial_character;
if (partial && (initial_character = *partial))
{
if (initial_character == '/')
return (partial);
if (initial_character == '~')
{
if (partial[1] == '/')
{
/* Return the concatenation of HOME and the rest
of the string. */
strcpy (local_temp_filename, getenv ("HOME"));
strcat (local_temp_filename, &partial[2]);
return (local_temp_filename);
}
else
{
#ifndef MSDOS
struct passwd *user_entry;
#endif /* not MSDOS */
int i, c;
char username[257];
for (i = 1; c = partial[i]; i++)
{
if (c == '/')
break;
else
username[i - 1] = c;
}
username[i - 1] = '\0';
#ifdef MSDOS
strcpy (local_temp_filename, &partial[i]);
#else /* not MSDOS */
if (!(user_entry = getpwnam (username)))
{
display_error ("Not a registered user!");
return (partial);
}
strcpy (local_temp_filename, user_entry->pw_dir);
strcat (local_temp_filename, &partial[i]);
#endif /* not MSDOS */
return (local_temp_filename);
}
}
if (initial_character == '.')
{
#ifndef MSDOS
#ifdef SYSV
if (!getwd (local_term_filename, FILENAME_LEN))
#else
if (!getwd (local_temp_filename))
#endif
#endif /* not MSDOS */
{
display_error (local_temp_filename);
return (partial);
}
strcat (local_temp_filename, &partial[1]);
return (local_temp_filename);
}
/* Scan the list of directories in INFOPATH. */
{
struct stat finfo;
char *temp_dirname, *extract_colon_unit ();
int dirname_index = 0;
while (temp_dirname = extract_colon_unit (infopath, &dirname_index))
{
strcpy (local_temp_filename, temp_dirname);
if (temp_dirname[(strlen (temp_dirname)) - 1] != '/')
strcat (local_temp_filename, "/");
strcat (local_temp_filename, partial);
free (temp_dirname);
if (stat (local_temp_filename, &finfo) == 0)
return (local_temp_filename);
}
}
}
return (partial);
}
/* Given a string containing units of information separated by colons,
return the next one pointed to by INDEX, or NULL if there are no more.
Advance INDEX to the character after the colon. */
/* Note: the MS-DOS version looks for semi-colons. */
char *
extract_colon_unit (string, index)
char *string;
int *index;
{
register int i, start;
i = start = *index;
if ((i >= strlen (string)) || !string)
return ((char *) NULL);
#ifdef MSDOS
while (string[i] && string[i] != ';')
#else /* not MSDOS */
while (string[i] && string[i] != ':')
#endif /* not MSDOS */
i++;
if (i == start)
{
return ((char *) NULL);
}
else
{
char *value = xmalloc (1 + (i - start));
strncpy (value, &string[start], (i - start));
value[i - start] = '\0';
if (string[i])
++i;
*index = i;
return (value);
}
}
/* **************************************************************** */
/* */
/* The echo area. */
/* */
/* **************************************************************** */
/* echoarea.c -- some functions to aid in user interaction. */
WINDOW echo_area = {0, 0, 0, 0, 0, 0};
boolean echo_area_open_p = false;
char modeline[256];
WINDOW modeline_window = {0, 0, 0, 0, 0, 0};
VOID
init_echo_area (left, top, right, bottom)
int left, top, right, bottom;
{
/* define the location of the echo area. Also inits the
modeline as well. */
echo_area.left = modeline_window.left = left;
echo_area.top = top;
modeline_window.top = top - 1;
echo_area.right = modeline_window.right = right;
echo_area.bottom = bottom;
modeline_window.bottom = modeline_window.top;
}
VOID
new_echo_area ()
{
/* Make the echo_area_window be the current window, and only allow */
/* output in there. Clear the window to start. */
if (!echo_area_open_p)
{
push_window ();
set_window (&echo_area);
echo_area_open_p = true;
}
goto_xy (the_window.left, the_window.top);
clear_eop ();
}
VOID
close_echo_area ()
{
/* Return output to the previous window. */
if (!echo_area_open_p)
return;
pop_window ();
echo_area_open_p = false;
}
#if 0
with_output_to_echo_area (function, arg1, arg2, arg3, arg4, arg5)
Function *function;
{
/* Do FUNCTION with output taking place in the echo area. */
with_output_to_window (&echo_area, function, arg1, arg2, arg3, arg4, arg5);
}
#endif
VOID
clear_echo_area ()
{
/* Clear the contents of the echo area. */
new_echo_area ();
close_echo_area ();
}
VOID
make_modeline ()
{
/* Create and display the modeline. */
extern LONG info_buffer_len;
int width = modeline_window.right - modeline_window.left;
sprintf (modeline, "Info: (%s)%s, %d lines",
current_info_file, current_info_node, nodelines);
if (strnicmp
(opsys_filename (current_info_file), last_loaded_info_file,
strlen (last_loaded_info_file)) != 0)
{
sprintf (&modeline[strlen (modeline)], ", Subfile: %s", last_loaded_info_file);
}
if (strlen (modeline) < width)
{
int index = strlen (modeline);
while (index != width)
modeline[index++] = '-';
modeline[index] = '\0';
}
if (strlen (modeline) > width)
modeline[width] = '\0';
push_window ();
set_window (&modeline_window);
goto_xy (the_window.left, the_window.top);
if (terminal_inverse_begin)
do_term (terminal_inverse_begin);
print_string (modeline);
if (terminal_inverse_begin)
do_term (terminal_end_attributes);
pop_window ();
}
boolean typing_out = false;
VOID
open_typeout ()
{
/* Prepare to do output to the typeout window. If the
typeout window is already open, ignore this clown. */
if (typing_out)
return;
push_window ();
set_window (&terminal_window);
goto_xy (the_window.ch, the_window.cv);
typing_out = window_bashed = true;
}
VOID
close_typeout ()
{
/* Close the currently open typeout window. */
if (inhibit_output)
inhibit_output = false;
else
{
untyi_char = getc (stdin);
if (untyi_char == SPACE)
untyi_char = 0;
}
pop_window ();
typing_out = false;
}
#if 0
char *
xrealloc (pointer, bytes)
char *pointer;
int bytes;
{
char *temp = (char *) realloc (pointer, bytes);
if (!temp)
{
fprintf (stderr, "Virtual memory exhausted\n");
restore_io ();
exit (2);
}
return (temp);
}
#endif
char *
xmalloc (bytes)
int bytes;
{
char *temp = (char *) malloc (bytes);
if (!temp)
{
fprintf (stderr, "Virtual memory exhausted\n");
restore_io ();
exit (2);
}
return (temp);
}
/*
* Local Variables:
* mode:C
* ChangeLog:ChangeLog
* End:
*/