home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-11-01 | 41.9 KB | 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:
- */
-