jct@jct.UUCP (jct) (07/11/89)
#! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 9 (of 9)." # Contents: lib/help.c # Wrapped by jct@ on Mon Jul 10 22:48:37 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'lib/help.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'lib/help.c'\" else echo shar: Extracting \"'lib/help.c'\" \(40463 characters\) sed "s/^X//" >'lib/help.c' <<'END_OF_FILE' X/* Module help */ X X/* X Provides context sensitive help functions for screen operations X Uses Uniplex II+ format files with optional KM index at front of file X file indexing is invisable to Uniplex II+, use hindex to make index. X The index will speed operations but it is not required. X X Allows "subsections" for nested help menus. Subsection entries come X after a help section end, "))", and are indicated by a leading ".XXS". X That is followed by a required title an optional file and a required X section. The first non-blank line that does not begin with a ".XXS" X terminates that help menu. ".XXT" may be used to give a sub-help menu X a title other that "Help Menu". X X Help windows smaller than full_screen may be specified by ".XXW" after X the section name and the title line. ".XXW" is followed by 4 X integers-> y_max, x_max, y_org, x_org. X X For example : X #HELP X Help Title X .XXW 10 30 7 40 X Help text X )) X .XXT " Sub-Help Test Menu " X .XXS "Sub help a" HELPA X .XXS HelpB file_two helpb X X This indicates a help section named HELP, that has one line of help text. X The help window is 10 lines x 30 columns starting at line 7 and column 40. X After that text is displayed, 2 entry menu is shown that consists of the X titles "Sub help a" and "HelpB". "Sub help a" section is in the same file X as the current section and is named "HELPA". "HelpB" section is in another X file, "file_two", and is section "helpb" of that other file. The title of X the menu is " Sub-Help Test Menu ". X X Subsections that begin with .XXR are for redirecting help information X to another section and optional file. X X Example : X #HELP X )) X .XXR /usr/mine/help extra X X This redirects to the extra help section in file /usr/min/help. X*/ X X/* X Created February 21, 1987 by JCT X*/ X X/* X For non-screen oriented programs define NONSCREEN X*/ X X/* X * Copyright (c) John C. Tompkins 1989 X * All rights reserved. X * X * Permission is granted to use this for any personal, noncommercial use. X * You may not distribute source or executable code for profit, nor X * may you distribute it with a commercial product without the prior X * written consent of the author. Please send modifications to the X * author for inclusion in updates to the program. X */ X X#include <stdio.h> X#include <ctype.h> X#include <string.h> X X#include <km/defs.h> X#include <km/ascii.h> X#include <km/string1.h> X X#ifdef DOS /* must come after <km/defs.h> */ X#include <stdlib.h> X#define HELPHELP "\\help\\help.hlp" X#else X#define HELPHELP "/usr/lib/help/help.hlp" X#endif X X#ifdef NONSCREEN X#include <km/tcap.h> X#ifdef DOS X#include <conio.h> X#else X#include <km/tctl.h> X#endif X#else X#include <km/scrio.h> X#include <km/scrops.h> X#endif X X#define DEF_SECTION "STANDARD" X#define STACK_SIZE 10 X#define HEAD_SIZE 50 X#define BUF_SIZE 150 X#define SS_MAX 17 /* A thru P */ X#define SS_SIZE 500 /* allows 30 chars per entry avg */ X X#define END_SECTION 0x0001 X#define HELP_EMPTY 0x0002 X#define STOP 0x0004 X#define IN_INDEX 0x0010 X#define GOT_INDEX 0x0020 X#define FOUND_SECTION 0x0040 X#define HAVE_KEY 0x0080 X#define PAGE_FULL 0x0400 X#define HELP_NUMERIC 0x0800 X#define NO_REFRESH 0x1000 X X#ifdef NONSCREEN typedef struct X { X short key; X char *text; X char *pointer; X char *help_section; X } SCR_ENTRY; X#endif X X#define END1_PROMPT " END OF HELP, (Q)uit, (S)top, (T)op, <SPACE> to backup or <RETURN> to continue " X#define END1S_PROMPT " END (Q) (S) (T) <SPC> <RET> " X#define END1M_PROMPT " END (Q)uit, (S)top, (T)op, <SPACE> or <RETURN> " X#define END2_PROMPT " END OF HELP, (Q)uit, (S)top or <RETURN> to continue " X#define END2S_PROMPT " END (Q) (S) <RET> " X#define END2M_PROMPT " END (Q)uit, (S)top or <RETURN> " X#define MORE1_PROMPT " (Q)uit, (S)top or <RETURN> to continue " X#define MORE1S_PROMPT " (Q) (S) <RET> " X#define MORE1M_PROMPT " (Q)uit, (S)top or <RETURN> " X#define MORE2_PROMPT " (Q)uit, (S)top, (T)op, <SPACE> to backup or <RETURN> to continue " X#define MORE2S_PROMPT " (Q) (S) (T) <SPC> <RET> " X#define MORE2M_PROMPT " (Q)uit, (S)top, (T)op, <SPACE> or <RETURN> " X X#ifndef NONSCREEN int help_fg, help_bg; X#endif X X#ifdef NONSCREEN X#define BOX_SIZE 11 X static int i, scr_lines, line_count, highlight, no_help = FALSE; X#ifdef DOS static int graphic = TRUE, LINES = 25, COLS = 80; static char box_tbl[BOX_SIZE] = { 196, 179, 197, 218, 194, 191, 180, 217, 193, 192, 195 }; static char *_SO = "\033[7m", *_SE = "\033[m"; static char *_GS = "", *_GE = ""; static char *_GB = box_tbl; X#else static int graphic, LINES, COLS; static int tcap_done = FALSE; static char *_SO, *_SE, *_GB, *_GS, *_GE; static char box_tbl[BOX_SIZE]; static char fake_tbl[] = {'-', '|', '+', '+', '+', '+', '+', '+', '+', '+', '+'}; X#endif X#endif X static int quit, backup, *pflags; static int ss_count, ss_index, stack_index, level = 0; static int page_length, page; static char ss_array[SS_SIZE], *ss_ptr, *title, *more = NULL; static char buf1[BUF_SIZE], buf2[BUF_SIZE]; static char head[HEAD_SIZE]; static long stack[STACK_SIZE]; static FILE *pfile; static SCR_ENTRY subsection[SS_MAX]; X X#ifndef NONSCREEN static int help_y_max, help_x_max, help_y_org, help_x_org; static int len1, len2, len_eff, adjust, win_fg, win_bg, fs_count = 0; static char *more_eff = NULL; static WINDOW *fs_help = 0; X#endif X extern long atol(); X#ifndef DOS extern char *malloc(); X#endif X static char *ss_store(p1, p2) X REGISTER char *p1; X REGISTER char *p2; X{ X X/* X Copies from p1 up to p2 into the current free area in the ss_array X marked by ss_ptr. Checks for overflow on ss_array. X*/ X X char *temp; X X temp = ss_ptr; X if (ss_count >= (SS_SIZE - 1)) X return(NULL); X while ((p1 < p2) && (ss_count < (SS_SIZE - 1))) X { X *ss_ptr++ = *p1++; X ss_count++; X } X *ss_ptr++ = '\0'; X return(temp); X} X static char *eatspace(p) X REGISTER char *p; X{ X X/* X Skips over leading whitespace. X*/ X X while (isspace(*p)) X p++; X return(p); X} X static char *get_name(in_p, end_pp) X char *in_p; X char **end_pp; X{ X X/* X Starts at in_p, skipping leading whitespace. If next non-space is ", then X sets flag and skips the " also. Copies until whitespace or, if flag set, X until " character is found or end of line. If ended on ", the " is X changed to whitespace. X*/ X X int have_quote; X char *p1, *p2; X X in_p = eatspace(in_p); X if ((have_quote = (*in_p == '"')) != FALSE) X in_p++; X p1 = in_p; X while (*in_p) X { X if (have_quote) X { X if ((*in_p == '"') || (*in_p == '\n')) X break; X } X else X { X if (isspace(*in_p)) X break; X } X in_p++; X } X if (*in_p == '"') X *in_p = ' '; X p2 = in_p; X if (end_pp) X *end_pp = p2; X if (p1 != p2) X return(ss_store(p1, p2)); X else X return(NULL); X} X static char *findend(p) X REGISTER char *p; X{ X X/* X Finds whitespace or end of line. X*/ X X while (*p && !isspace(*p)) X p++; X return(p); X} X static char *delimit(p) X REGISTER char *p; X{ X X/* X Substitutes null character, \0, for first whitespace found X*/ X X while (*p) X { X if (isspace(*p)) X { X *p++ = '\0'; X break; X } X else X p++; X } X return(p); X} X static int line_empty() X{ X X/* X Looks through a "line", actually a string, if any non whitespace X character the line is not empty. If all whitespace, its empty. X*/ X X REGISTER char *p; X X p = buf1; X while (*p) X { X if (*p == '\n') X return(TRUE); X if (!isspace(*p)) X return(FALSE); X p++; X } X return(TRUE); X} X X#ifdef NONSCREEN static void GB_analyze() X{ X char *temp; X int i; X X if (!_GB || !_GS || !_GE) X { X _GS = NULL; X _GE = NULL; X return; X } X temp = _GB; X for (i = 0; i < BOX_SIZE; i++) X box_tbl[i] = '\0'; X while (*temp) X { X i = 0; X while (*temp && (i < BOX_SIZE)) X { X box_tbl[i] = *temp; X temp++; X i++; X } X } X if (i != BOX_SIZE) X { X _GS = NULL; X _GE = NULL; X return; X } X return; X} X static int center(p) X REGISTER char *p; X{ X X/* X Returns the number of spaces needed to center the passed string on screen X In screen mode, this function provided in scrops.c X*/ X X return(((COLS - strlen(p)) / 2) - 1); X} X static int addgraphic(ch) X int ch; X{ X X/* X Displays the coded "graphic" character. Uses normal ASCII in nonscreen mode. X In screen mode, this function provided by scrops.c and makes use of a X terminals line drawing set, if available. X*/ X X if (graphic) X { X if ((ch >= 'A') && (ch <= 'K')) X fputc(box_tbl[ch - 'A'], stdout); X else X fputc(' ', stdout); X } X#ifndef DOS X else X { X if ((ch >= 'A') && (ch <= 'K')) X fputc(fake_tbl[ch - 'A'], stdout); X else X fputc(' ', stdout); X } X#endif X return(TRUE); X} X static int graphbegin() X{ X if (!graphic && _GS) X { X fflush(stdout); X put_cap(_GS); X graphic = TRUE; X return(TRUE); X } X return(FALSE); X} X static int graphend() X{ X if (graphic && _GE) X { X fflush(stdout); X put_cap(_GE); X graphic = FALSE; X return(TRUE); X } X return(FALSE); X} X static int standout() X{ X if (!highlight && _SO) X { X fflush(stdout); X put_cap(_SO); X highlight = TRUE; X return(TRUE); X } X return(FALSE); X} X static int standend() X{ X if (highlight && _SE) X { X fflush(stdout); X put_cap(_SE); X highlight = FALSE; X return(TRUE); X } X return(FALSE); X} X static void put_prompt(str) X char *str; X{ X standout(); X fputs(str, stdout); X standend(); X} X#endif X static char *get_head() X{ X X/* X The first line after the section introduction is the help section name X that is displayed at the top center of the screen. This function returns X a pointer to that name or to a default name if the first line is blank. X Strips leading and trailing whitespace, but pads the name with 1 leading X and trailing blank. The name is the full line, " not special. X*/ X X int count = 0; X REGISTER char *p1; X REGISTER char *p2; X X p1 = eatspace(buf1); X p2 = head; X if (!*p1 || (*p1 == '\n')) X return(NULL); X *p2++ = ' '; X while (*p1 && (*p1 != '\n') && (++count < 48)) X *p2++ = *p1++; X p2--; X while (isspace(*p2)) X p2--; X p2++; X *p2++ = ' '; X *p2 = '\0'; X return(head); X} X static int is_ruler() X{ X X/* X If more than 40 dots on the line, we assume its a ruler X*/ X X REGISTER char *p1; X REGISTER int count = 0; X X p1 = buf1; X while (*p1) X { X if (*p1++ == '.') X count++; X } X return(count > 40); X} X X#ifndef NONSCREEN static void get_wsize() X{ X REGISTER char *p1; X X p1 = buf1 + 4; X help_y_max = atoi(p1); X p1 = eatspace(p1); X p1 = findend(p1); X help_x_max = atoi(p1); X p1 = eatspace(p1); X p1 = findend(p1); X help_y_org = atoi(p1); X p1 = eatspace(p1); X p1 = findend(p1); X help_x_org = atoi(p1); X} X static void get_wcolor() X{ X REGISTER char *p1; X REGISTER char *p2; X X p1 = eatspace(buf1 + 4); X p2 = delimit(p1); X win_fg = get_color(p1); X p1 = eatspace(p2); X p2 = delimit(p1); X win_bg = get_color(p1); X} X#endif X static int get_intro(help_file, flags) X FILE *help_file; X int *flags; X{ X X/* X Reads the beginning of a help section to determine a possible window X size (.XXW) and section "title". X*/ X X title = NULL; X more = NULL; X#ifndef NONSCREEN X more_eff = NULL; X#endif X *flags &= ~PAGE_FULL; X while (TRUE) X { X if (fgets(buf1, sizeof(buf1), help_file)) X { X if (is_ruler()) X ; X else if (substr(buf1, "))", TRUE)) X { X *flags |= END_SECTION; X *flags |= PAGE_FULL; X return(FALSE); X } X else X { X if (title) X { X if (substr(buf1, ".XXW", TRUE)) X#ifdef NONSCREEN X ; X#else X get_wsize(); X#endif X else if (substr(buf1, ".XXC", TRUE)) X#ifdef NONSCREEN X ; X#else X get_wcolor(); X#endif X else X { X more = buf1; X break; X } X } X else X title = get_head(); X } X } X else X { X *flags |= END_SECTION; X *flags |= PAGE_FULL; X return(FALSE); X } X } X return(TRUE); X} X static int find_section(help_file, section, offset_end, flags) X FILE *help_file; X char *section; X long *offset_end; X int *flags; X{ X X/* X Searches the start of the help file for an index and if found, searches X the index for the desired section for direct fseek()-ing to. If the index X exists but the section is not found, aborts. If the index does not exist, X searches the file sequentally until section found or end of file, much X slower. X*/ X X REGISTER char *p1; X REGISTER char *p2; X X#ifndef NONSCREEN X help_y_max = LINES; X help_x_max = COLS; X help_y_org = 0; X help_x_org = 0; X win_fg = help_fg; X win_bg = help_bg; X#endif X while (!(*flags & FOUND_SECTION) && (fgets(buf1, sizeof(buf1), help_file))) X { X if (*flags & IN_INDEX) X { X if (substr(buf1, ".XXI", TRUE)) X { X *flags |= GOT_INDEX; X p1 = eatspace(buf1 + 4); X p2 = delimit(p1); X if (substr(p1, section, TRUE)) X { X stack[0] = atol(p2); X p2 = eatspace(p2); X p2 = findend(p2); X *offset_end = atol(p2); X fseek(help_file, stack[0], 0); X *flags |= FOUND_SECTION; X } X } X else if (!line_empty()) X { X if (*flags & GOT_INDEX) X return(FALSE); X *flags &= ~IN_INDEX; X } X } X if (*buf1 == '#') X { X delimit(buf1); X if (substr((buf1 + 1), section, TRUE)) X { X stack[0] = ftell(help_file); X *flags |= FOUND_SECTION; X } X } X } X get_intro(help_file, flags); X return(*flags & FOUND_SECTION); X} X X#ifdef NONSCREEN static int is_dot(flags) X int *flags; X#else static int is_dot(scr, flags) X SCR *scr; X int *flags; X#endif X{ X int temp; X X if (*buf1 == '.') X { X if (substr((buf1 + 1), "PA", TRUE)) X *flags |= PAGE_FULL; X else if (substr((buf1 + 1), "PL", TRUE)) X { X#ifdef NONSCREEN X if ((temp = atoi(buf1 + 3)) <= (LINES - 4)) X#else X if ((temp = atoi(buf1 + 3)) <= (scr->win->y_max - 4)) X#endif X page_length = temp; X else X#ifdef NONSCREEN X page_length = LINES - 4; X#else X page_length = scr->win->y_max - 4; X#endif X } X return(TRUE); X } X else X return(FALSE); X} X X#ifdef NONSCREEN static int is_effect(help_file) X FILE *help_file; X#else static int is_effect(scr, help_file) X SCR *scr; X FILE *help_file; X#endif X{ X#ifdef NONSCREEN X char *p1, *p2; X#endif X char *p3; X int count; X X count = UNDETERMINED; X p3 = (strend(buf1) - 3); X if (substr(p3, "@@\n", TRUE)) /* attribute mark? */ X { X#ifdef NONSCREEN X if (fgets(buf2, sizeof(buf2), help_file)) /* get attributes */ X { X count = 0; X p1 = buf1; X p2 = buf2; X while (p1 < p3) X { X if (*p2 == '[') X { X if (!graphic) X graphbegin(); X addgraphic(*p1); X } X else if (*p2 == ' ') X { X if (highlight) X standend(); X if (graphic) X graphend(); X fputc(*p1, stdout); X } X else X { X if (graphic) X graphend(); X if (!highlight) X standout(); X fputc(*p1, stdout); X } X count++; X p1++; X if (*p2) X p2++; X } X if (highlight) X standend(); X if (graphic) X graphend(); X fputc('\n', stdout); X count++; X } X#else X if (more_eff || fgets(buf2, sizeof(buf2), help_file)) X { X if (more_eff) X { X strcpy(buf2, more_eff); X len2 = strlen(buf2); X more_eff = NULL; X } X else X { X len2 = strlen(buf2); X len_eff = len2; X } X len1 = strlen(buf1); X if (len2 > (len1 - 2)) X { X strcpy(buf2, (buf2 + len2 - (len1 - 2))); X len2 = len1 - 2; X } X count = waddtext(scr->win, buf1, buf2, (scr->win->flags & BOX_FLAG)); X } X#endif X } X return(count); X} X X#ifdef NONSCREEN static int get_page(help_file, flags) X FILE *help_file; X int *flags; X#else static int get_page(scr, help_file, flags) X SCR *scr; X FILE *help_file; X int *flags; X#endif X{ X X/* X Reads enough lines to fill a help page and puts up the header info X*/ X X#ifdef NONSCREEN X int temp; X#else X int count, did_eff; X REGISTER WINDOW *win; X#endif X X if (*flags & END_SECTION) X return(FALSE); X *flags &= ~PAGE_FULL; X#ifdef NONSCREEN X line_count = 0; X printf("\n Page %2d", page); X for (i = 0, (temp = center(title) - 8); i < temp; i++) X fputc(' ', stdout); X standout(); X fputs(title, stdout); X standend(); X fputc('\n', stdout); X fputc('\n', stdout); X scr_lines = 2; X#else X win = scr->win; X werase(win); X if (win->flags & BOX_FLAG) X wmove(win, 2, 1); X else X { X wmove(win, 0, 1); X wprintw(win, "Page %2d", page); X wmove(win, 2, 0); X } X#endif X while (!(*flags & PAGE_FULL) && (more || fgets(buf1, sizeof(buf1), help_file))) X { X if (more) X { X strcpy(buf1, more); X more = NULL; X } X#ifndef NONSCREEN X else X more_eff = NULL; X#endif X if (is_ruler()) X ; X#ifdef NONSCREEN X else if (is_dot(flags)) X#else X else if (is_dot(scr, flags)) X#endif X ; X else if (substr(buf1, "))", TRUE)) X { X *flags |= END_SECTION; X *flags |= PAGE_FULL; X } X else X { X#ifdef NONSCREEN X if (is_effect(help_file) == UNDETERMINED) X fputs(buf1, stdout); X if (strlen(buf1) <= COLS) X temp = 1; X else X temp = 2; X line_count += temp; X scr_lines += temp; X if (line_count >= page_length) X *flags |= PAGE_FULL; X#else X if ((count = did_eff = is_effect(scr, help_file)) == UNDETERMINED) X count = waddtext(win, buf1, NULL, (win->flags & BOX_FLAG)); X more = buf1 + count; X if (*more) X { X if (did_eff == UNDETERMINED) X more_eff = NULL; X else X more_eff = buf2 + ((count < len2) ? count : len2); X } X else X { X more = NULL; X more_eff = NULL; X } X if (win->y_cur > (page_length + 1)) X *flags |= PAGE_FULL; X#endif X if ((*flags & HELP_EMPTY) && !line_empty()) X *flags &= ~HELP_EMPTY; X } X } X#ifndef NONSCREEN X if (more) X { X adjust = strlen(more); X if (more_eff) X adjust += len_eff; X } X else X adjust = 0; X#endif X if (*flags & HELP_EMPTY) X return(FALSE); X#ifdef NONSCREEN X else X { X while (scr_lines < (LINES - 1)) X { X fputc('\n', stdout); X scr_lines++; X } X return(TRUE); X } X#else X return(TRUE); X#endif X} X X#ifdef NONSCREEN static void helphelp(seek) X int seek; X#else static void helphelp(scr) X SCR *scr; X#endif X{ X char save_head[HEAD_SIZE], *save_title; X char save_buf1[BUF_SIZE], save_buf2[BUF_SIZE]; X char *save_more; X long save_stack[STACK_SIZE]; X FILE *save_file; X int *save_flags, save_page, save_pl, save_si; X#ifndef NONSCREEN X char *save_me; X SCR new_scr; X#endif X X#ifdef NONSCREEN X no_help = TRUE; X#else X new_scr.win = scr->win; X new_scr.head = 0; X new_scr.func_entry = 0; X new_scr.func_loop = scr->func_loop; X new_scr.func_chk = 0; X new_scr.prompt = 0; X new_scr.entry = 0; X new_scr.active_entry = 0; X new_scr.last_active = 0; X new_scr.timeout = scr->timeout; X new_scr.help_file = HELPHELP; X new_scr.help_section = NULL; X new_scr.flags = (scr->flags & (SCR_HELP_LOOP | SCR_NUMERIC)); X new_scr.flags |= (SCR_RAW | SCR_NO_ERASE | SCR_NO_HELP); X new_scr.lflags = 0; X new_scr.color = 0; X#endif X save_file = pfile; X save_flags = pflags; X save_page = page; X save_pl = page_length; X save_si = stack_index; X memcpy(save_stack, stack, sizeof(stack)); X save_title = title; X strcpy(save_head, head); X save_more = more; X#ifndef NONSCREEN X save_me = more_eff; X#endif X memcpy(save_buf1, buf1, sizeof(buf1)); X memcpy(save_buf2, buf2, sizeof(buf2)); X#ifdef NONSCREEN X do_help(HELPHELP, NULL, 0); X#else X sdo_help(&new_scr); X#endif X pfile = save_file; X pflags = save_flags; X page = save_page; X page_length = save_pl; X stack_index = save_si; X memcpy(stack, save_stack, sizeof(stack)); X title = save_title; X strcpy(head, save_head); X more = save_more; X#ifndef NONSCREEN X more_eff = save_me; X#endif X memcpy(buf1, save_buf1, sizeof(buf1)); X memcpy(buf2, save_buf2, sizeof(buf2)); X quit = FALSE; X backup = FALSE; X#ifdef NONSCREEN X if (seek) X { X fseek(pfile, stack[stack_index], 0); X more = NULL; X if (stack_index == 0) X get_intro(pfile, pflags); X *pflags &= ~END_SECTION; X } X no_help = FALSE; X#endif X} X X#ifdef NONSCREEN static int help_chk_key(flags, key) X REGISTER int *flags; X REGISTER int key; X#else static int help_chk_key(scr, key) X REGISTER SCR *scr; X REGISTER int key; X#endif X{ X int i; X X switch (tolower(key)) X { X case UNDETERMINED : X break; X case 'q' : X case K_QUIT : X case K_CANCEL : X quit = TRUE; X#ifdef NONSCREEN X *flags |= HAVE_KEY; X#else X scr->lflags |= SCR_QUIT; X#endif X break; X case 's' : X case K_END_SCREEN : X case K_END_BUF : X case K_END_LINE : X *pflags |= STOP; X#ifdef NONSCREEN X *flags |= HAVE_KEY; X#else X scr->lflags |= SCR_QUIT; X#endif X break; X case 't' : X case K_BEG_SCREEN : X case K_BEG_BUF : X case K_BEG_LINE : X if (stack_index >= 1) X { X stack_index = 0; X fseek(pfile, stack[stack_index], 0); X more = NULL; X#ifndef NONSCREEN X more_eff = NULL; X#endif X get_intro(pfile, pflags); X page = 1; X *pflags &= ~END_SECTION; X#ifdef NONSCREEN X *flags |= HAVE_KEY; X#else X scr->lflags |= SCR_QUIT; X#endif X } X break; X case ' ' : X case K_UP : X case K_BACKUP : X case K_BWD_SCREEN : X case K_BWD_WORD : X if (stack_index >= 1) X { X stack_index--; X fseek(pfile, stack[stack_index], 0); X more = NULL; X#ifndef NONSCREEN X more_eff = NULL; X#endif X if (stack_index > 0) X page--; X else X { X get_intro(pfile, pflags); X page = 1; X } X *pflags &= ~END_SECTION; X#ifdef NONSCREEN X *flags |= HAVE_KEY; X#else X scr->lflags |= SCR_QUIT; X#endif X } X break; X case K_HELP : X case K_F0 : X case '?' : X#ifdef NONSCREEN X if (!no_help) X helphelp(TRUE); X *flags |= HAVE_KEY; X#else X if (!(scr->flags & SCR_NO_HELP)) X helphelp(scr); X#endif X break; X case LF : X case CR : X case K_DOWN : X case K_FWD_SCREEN : X case K_FWD_WORD : X if (!(*pflags & END_SECTION)) X { X stack_index++; X if (stack_index >= STACK_SIZE) X { X for (i = 1; i < (STACK_SIZE - 1); i++) X stack[i] = stack[i + 1]; X stack_index--; X } X#ifdef NONSCREEN X stack[stack_index] = ftell(pfile); X#else X stack[stack_index] = ftell(pfile) - adjust; X#endif X page++; X } X#ifdef NONSCREEN X *flags |= HAVE_KEY; X#else X scr->lflags |= SCR_QUIT; X#endif X break; X } X return(TRUE); X} X X#ifdef NONSCREEN static int put_page(help_file, flags) X FILE *help_file; X int *flags; X#else static int put_page(scr, help_file, flags) X SCR *scr; X FILE *help_file; X int *flags; X#endif X{ X X/* X Puts the prompt at the bottom of a full page then inputs and interprets X the user input X*/ X X#ifndef NONSCREEN X REGISTER WINDOW *win; X#endif X X#ifndef NONSCREEN X win = scr->win; X scr->flags &= ~SCR_NO_PROMPT; X#endif X if (*flags & END_SECTION) X { X if (stack_index >= 1) X#ifdef NONSCREEN X put_prompt(END1_PROMPT); X#else X { X if (win->x_max < 30) X scr->flags |= SCR_NO_PROMPT; X else if (win->x_max < 50) X scr->prompt = END1S_PROMPT; X else if (win->x_max < 80) X scr->prompt = END1M_PROMPT; X else X scr->prompt = END1_PROMPT; X } X#endif X else X#ifdef NONSCREEN X put_prompt(END2_PROMPT); X#else X { X if (win->x_max < 30) X scr->flags |= SCR_NO_PROMPT; X else if (win->x_max < 50) X scr->prompt = END2S_PROMPT; X else if (win->x_max < 80) X scr->prompt = END2M_PROMPT; X else X scr->prompt = END2_PROMPT; X } X#endif X } X else X { X if (stack_index >= 1) X#ifdef NONSCREEN X put_prompt(MORE2_PROMPT); X#else X { X if (win->x_max < 30) X scr->flags |= SCR_NO_PROMPT; X else if (win->x_max < 50) X scr->prompt = MORE2S_PROMPT; X else if (win->x_max < 80) X scr->prompt = MORE2M_PROMPT; X else X scr->prompt = MORE2_PROMPT; X } X#endif X else X#ifdef NONSCREEN X put_prompt(MORE1_PROMPT); X#else X { X if (win->x_max < 30) X scr->flags |= SCR_NO_PROMPT; X else if (win->x_max < 50) X scr->prompt = MORE1S_PROMPT; X else if (win->x_max < 80) X scr->prompt = MORE1M_PROMPT; X else X scr->prompt = MORE1_PROMPT; X } X#endif X } X pflags = flags; X pfile = help_file; X#ifdef NONSCREEN X *flags &= ~HAVE_KEY; X do X { X#ifdef DOS X help_chk_key(flags, getch()); X#else X help_chk_key(flags, getchar()); X#endif X } X while (!(*flags & HAVE_KEY)); X fputc('\n', stdout); X#else X do_scr(scr); X#endif X return(TRUE); X} X static void get_end(help_file, offset_end, flags) X FILE *help_file; X long *offset_end; X int *flags; X{ X if (*flags & GOT_INDEX) X { X if (!(*flags & END_SECTION)) X { X if (*offset_end != UNDETERMINED) X { X fseek(help_file, *offset_end, 0); X *flags |= END_SECTION; X } X else X { X while (!(*flags & END_SECTION) && fgets(buf1, sizeof(buf1), help_file)) X { X if (substr(buf1, "))", TRUE)) X *flags |= END_SECTION; X } X *offset_end = ftell(help_file); X } X } X } X else X { X while (!(*flags & END_SECTION) && fgets(buf1, sizeof(buf1), help_file)) X { X if (substr(buf1, "))", TRUE)) X *flags |= END_SECTION; X } X *offset_end = ftell(help_file); X } X} X X#ifdef NONSCREEN static void redirect(file) X char *file; X#else static void redirect(scr) X SCR *scr; X#endif X{ X char *p2; X char *help_file, *help_section, *help_buf; X X if (level > 0) X level--; X#ifndef NONSCREEN X if (fs_help && (fs_help == scr->win)) X { X if (--fs_count == 0) X { X delwin(scr->win, FALSE); X fs_help = WIN_NULL; X } X } X else X delwin(scr->win, FALSE); X scr->win = WIN_NULL; X#endif X if ((help_section = get_name(buf1 + 4, &p2)) == NULL) X return; X if ((p2 = get_name(p2, NULL)) != NULL) X { X help_file = help_section; X help_section = p2; X } X else X#ifdef NONSCREEN X help_file = file; X#else X help_file = scr->help_file; X#endif X if ((help_buf = malloc(strlen(help_file) + 1)) == NULL) X return; X strcpy(help_buf, help_file); X#ifdef NONSCREEN X do_help(help_buf, help_section, 0); X#else X scr->help_file = help_buf; X scr->help_section = help_section; X sdo_help(scr); X#endif X free(help_buf); X} X X#ifdef NONSCREEN static int subhelp_chk_key(flags, file, key) X int *flags; X char *file; X int key; X#else static int subhelp_chk_key(scr, key) X SCR *scr; X int key; X#endif X{ X char *help_buf = 0; X int stat; X#ifdef NONSCREEN X static SCR_ENTRY *p; X#else X static int entry_number = 0; X#endif X X X key = tolower(key); X switch (key) X { X case UNDETERMINED : X break; X case 'q' : X case K_QUIT : X quit = TRUE; X#ifdef NONSCREEN X *flags |= HAVE_KEY; X fputc('\n', stdout); X#else X scr->lflags |= SCR_QUIT; X#endif X break; X case ' ' : X case K_BACKUP : X case K_BWD_SCREEN : X case K_BWD_WORD : X if (level > 1) X { X backup = TRUE; X#ifdef NONSCREEN X *flags |= HAVE_KEY; X fputc('\n', stdout); X#else X scr->lflags |= SCR_QUIT; X#endif X } X break; X case K_HELP : X case K_F0 : X case '?' : X#ifdef NONSCREEN X if (!no_help) X helphelp(FALSE); X *flags |= HAVE_KEY; X#else X if (!(scr->flags & SCR_NO_HELP)) X helphelp(scr); X#endif X break; X#ifndef NONSCREEN X case CR : X case LF : X if (scr->flags & SCR_NUMERIC) X { X if ((entry_number > 0) && (entry_number <= ss_index)) X scr->active_entry = &subsection[entry_number - 1]; X entry_number = 0; X } X if (scr->active_entry) X { X if (scr->active_entry->pointer) X { X if ((help_buf = malloc(strlen(scr->active_entry->pointer) + 1)) == NULL) X break; X strcpy(help_buf, scr->active_entry->pointer); X scr->help_file = help_buf; X } X scr->help_section = scr->active_entry->help_section; X scr->active_entry->func = sdo_help; X scr->active_entry->pointer = (char*)scr; X scr->active_entry->flags = (SCR_PPARM | SCR_PUT_ACTIVE); X stat = do_active_entry(scr); X if (help_buf) X free(help_buf); X if (stat) X scr->lflags |= SCR_QUIT; X } X break; X case K_UP : X if (scr->active_entry) X { X put_entry(scr, scr->active_entry, FALSE); X if (scr->active_entry == scr->entry) X scr->active_entry = 0; X else X scr->active_entry--; X } X else X scr->active_entry = &subsection[ss_index - 1]; X if (scr->active_entry) X put_entry(scr, scr->active_entry, TRUE); X scr->last_active = scr->active_entry; X break; X case K_DOWN : X if (scr->active_entry) X { X put_entry(scr, scr->active_entry, FALSE); X scr->active_entry++; X if (scr->active_entry->key == UNDETERMINED) X scr->active_entry = 0; X } X else X scr->active_entry = scr->entry; X if (scr->active_entry) X put_entry(scr, scr->active_entry, TRUE); X scr->last_active = scr->active_entry; X break; X case '0' : X case '1' : X case '2' : X case '3' : X case '4' : X case '5' : X case '6' : X case '7' : X case '8' : X case '9' : X if (scr->flags & HELP_NUMERIC) X { X entry_number = (entry_number * 10) + key - '0'; X if (entry_number > 99) X entry_number = 0; X } X break; X#endif X default : X key = key - 'a'; X if ((key >= 0) && (key < ss_index)) X { X#ifdef NONSCREEN X p = &subsection[key]; X if ((help_buf = malloc(strlen(p->pointer ? p->pointer : file) + 1)) == NULL) X break; X strcpy(help_buf, p->pointer ? p->pointer : file); X stat = do_help(help_buf, p->help_section, 0); X if (help_buf) X free(help_buf); X if (stat) X *flags |= HAVE_KEY; X#else X scr->active_entry = &subsection[key]; X if (scr->active_entry->pointer) X { X if ((help_buf = malloc(strlen(scr->active_entry->pointer) + 1)) == NULL) X break; X strcpy(help_buf, scr->active_entry->pointer); X scr->help_file = help_buf; X } X scr->help_section = scr->active_entry->help_section; X scr->active_entry->func = sdo_help; X scr->active_entry->pointer = (char*)scr; X scr->active_entry->flags = (SCR_PPARM | SCR_PUT_ACTIVE); X stat = do_active_entry(scr); X if (help_buf) X free(help_buf); X if (stat) X scr->lflags |= SCR_QUIT; X#endif X } X break; X } X return(TRUE); X} X X#ifndef NONSCREEN char *set_prompt(scr) X SCR *scr; X{ X if (level > 1) X { X if (scr->win->x_max < 30) X scr->flags |= SCR_NO_PROMPT; X else if (scr->win->x_max < 45) X scr->prompt = " (Q)uit, <SPACE> or select "; X else X scr->prompt = " (Q)uit, <SPACE> to backup or selection "; X } X else X { X if (scr->win->x_max < 25) X scr->flags |= SCR_NO_PROMPT; X else X scr->prompt = " (Q)uit or selection "; X } X} X#endif X X#ifdef NONSCREEN static int do_subhelp(file, help_file, offset_end, flags) X char *file; X FILE *help_file; X long *offset_end; X int *flags; X#else static int do_subhelp(scr, help_file, offset_end, flags) X SCR *scr; X FILE *help_file; X long *offset_end; X int *flags; X#endif X{ X X/* X If at the end of the help section there is a subsection description, this X function processes that description to call nested help. X*/ X X#ifdef NONSCREEN X int temp; X#else X int have_window = FALSE; X int full_screen; X WINDOW *new_win; X#endif X int empty; X char *help_title, *p1, *p2; X X#ifdef NONSCREEN X static SCR_ENTRY *p; X#endif X X backup = FALSE; X#ifndef NONSCREEN X scr->func_chk = subhelp_chk_key; X scr->entry = subsection; X scr->active_entry = 0; X scr->last_active = 0; X#endif X while (!quit && !backup) X { X *flags &= ~STOP; X#ifndef NONSCREEN X help_y_max = LINES; X help_x_max = COLS; X help_y_org = 0; X help_x_org = 0; X win_fg = help_fg; X win_bg = help_bg; X scr->flags &= (SCR_NUMERIC | SCR_HELP_LOOP | SCR_MPOPUP); X scr->flags |= (SCR_NO_INI | SCR_RAW | SCR_MENU); X scr->lflags = 0; X#endif X get_end(help_file, offset_end, flags); X ss_ptr = ss_array; X ss_index = 0; X ss_count = 0; X help_title = NULL; X while (fgets(buf1, sizeof(buf1), help_file)) X { X if ((empty = !line_empty()) != FALSE) X { X if (substr(buf1, ".XXR", TRUE)) X { X#ifdef NONSCREEN X redirect(file); X#else X redirect(scr); X#endif X return(TRUE); X } X else if (substr(buf1, ".XXW", TRUE)) X#ifdef NONSCREEN X ; X#else X { X get_wsize(); X have_window = TRUE; X } X#endif X else if (substr(buf1, ".XXC", TRUE)) X#ifdef NONSCREEN X ; X#else X get_wcolor(); X#endif X else if (substr(buf1, ".XXT", TRUE)) X { X if ((help_title = get_name(buf1 + 4, NULL)) == NULL) X break; X } X else if (substr(buf1, ".XXS", TRUE)) X { X if (ss_index >= (SS_MAX - 1)) X break; X subsection[ss_index].key = 0; X subsection[ss_index].pointer = NULL; X subsection[ss_index].help_section = NULL; X if ((subsection[ss_index].text = get_name(buf1 + 4, &p2)) == NULL) X break; X if ((subsection[ss_index].help_section = get_name(p2, &p2)) == NULL) X break; X if ((p2 = get_name(p2, NULL)) != NULL) X { X subsection[ss_index].pointer = subsection[ss_index].help_section; X subsection[ss_index].help_section = p2; X } X ss_index++; X } X else X break; X } X else if (empty) X break; X } X subsection[ss_index].key = UNDETERMINED; X if (!backup && (ss_index > 0)) X { X#ifndef NONSCREEN X if (have_window && ((new_win = newwin(help_y_max, help_x_max, help_y_org, help_x_org)) != WIN_NULL)) X { X if (fs_help && (fs_help == scr->win)) X { X if (--fs_count == 0) X { X delwin(scr->win, FALSE); X fs_help = WIN_NULL; X } X } X else X delwin(scr->win, FALSE); X scr->win = new_win; X full_screen = ((help_y_max == LINES) && (help_x_max == COLS) && X (help_y_org == 0) && (help_x_org == 0)); X if (full_screen) X { X fs_help = new_win; X fs_count++; X } X else X { X if (scr->win->x_max < 30) X scr->flags |= SCR_NO_PROMPT; X } X } X else X full_screen = TRUE; X wsetcolor(scr->win, win_fg, win_bg); X if (!full_screen) X { X box(scr->win); X scr->flags |= SCR_MPOPUP; X } X#endif X if (help_title) X p1 = help_title; X else if (*flags & HELP_EMPTY) X p1 = " Help Menu "; X else X p1 = " Additional Help Menu "; X#ifdef NONSCREEN X fputc('\n', stdout); X for (i = 0, temp = center(p1); i < temp; i++) X fputc(' ', stdout); X standout(); X fputs(p1, stdout); X standend(); X fputc('\n', stdout); X fputc('\n', stdout); X fputc('\n', stdout); X#else X scr->head = p1; X#endif X#ifdef NONSCREEN X for (temp = 0, p = subsection, scr_lines = 3; scr_lines < (LINES - 1); temp++, p++, scr_lines++) X { X if (temp < ss_index) X printf(" %c : %s\n", (temp + 'A'), p->text); X else X fputc('\n', stdout); X } X#endif X#ifdef NONSCREEN X if (level > 1) X put_prompt(" (Q)uit, <SPACE> to backup or selection "); X else X put_prompt(" (Q)uit or selection "); X#else X set_prompt(scr); X#endif X *flags &= ~HAVE_KEY; X pfile = help_file; X#ifdef NONSCREEN X do X { X#ifdef DOS X subhelp_chk_key(flags, file, getch()); X#else X subhelp_chk_key(flags, file, getchar()); X#endif X } X while (!(*flags & HAVE_KEY)); X#else X do_scr(scr); X#endif X *flags &= ~END_SECTION; X } X else X backup = TRUE; X } X backup = FALSE; X return(TRUE); X} X X#ifndef NONSCREEN static WINDOW *get_window(scr) X REGISTER SCR *scr; X{ X int full_screen; X WINDOW *new_win; X X full_screen = ((help_y_max == LINES) && (help_x_max == COLS) && X (help_y_org == 0) && (help_x_org == 0)); X if (full_screen && fs_help) X { X new_win = fs_help; X fs_count++; X } X else if ((new_win = newwin(help_y_max, help_x_max, help_y_org, help_x_org)) != WIN_NULL) X { X if (full_screen) X { X fs_help = new_win; X fs_count++; X } X } X else X return((WINDOW*)0); X wsetcolor(new_win, win_fg, win_bg); X if (!full_screen) X { X box(new_win); X page_length = new_win->y_max - 4; X } X else X page_length = new_win->y_max - 4; X scr->win = new_win; X scr->head = title; X scr->func_entry = 0; X scr->func_loop = 0; X scr->func_chk = help_chk_key; X scr->prompt = 0; X scr->entry = 0; X scr->active_entry = 0; X scr->last_active = 0; X scr->timeout = UNDETERMINED; X scr->help_file = 0; X scr->help_section = 0; X scr->flags = (SCR_RAW | SCR_NO_ERASE); X scr->lflags = 0; X scr->color = 0; X return(new_win); X} X#endif X X#ifdef NONSCREEN int do_help(file, section, xflags) X char *file; X char *section; X int xflags; X#else int sdo_help(scr) X SCR *scr; X#endif X{ X FILE *help_file; X long offset_end; X int stat, flags; X X#ifndef NONSCREEN X char *section; X SCR help_scr; X#endif X X#ifdef NONSCREEN X if (file) X { X if ((help_file = fopen(file, "r")) != NULL) X#else X if (scr->help_file) X { X if ((help_file = fopen(scr->help_file, "r")) != NULL) X#endif X { X if (level == 0) X { X#ifdef NONSCREEN X#ifdef UNIX X if (!tcap_done) X { X if ((LINES = get_icap("li")) == ERROR) X LINES = 24; X if ((COLS = get_icap("co")) == ERROR) X COLS = 80; X tcap_done = TRUE; X if (!(_SO = get_scap("so")) || !(_SE = get_scap("se"))) X { X _SO = NULL; X _SE = NULL; X } X graphic = FALSE; X _GS = get_scap("GS"); X _GE = get_scap("GE"); X _GB = get_scap("GB"); X GB_analyze(); X } X if (xflags) X { X tc_crmode(); X tc_noecho(); X } X#endif X#endif X quit = FALSE; X backup = FALSE; X } X level++; X flags = (IN_INDEX | HELP_EMPTY); X offset_end = 0; X stack_index = 0; X page = 1; X#ifndef NONSCREEN X if (scr->active_entry) X section = scr->active_entry->help_section; X else X section = scr->help_section; X#endif X if (!section) X section = DEF_SECTION; X if (find_section(help_file, section, &offset_end, &flags)) X { X#ifdef NONSCREEN X page_length = LINES - 4; X#else X if (!get_window(&help_scr)) X { X fclose(help_file); X return(FALSE); X } X help_scr.help_file = scr->help_file; X help_scr.flags |= (scr->flags & SCR_NO_HELP); X if (scr->flags & SCR_NUMERIC) X { X help_scr.flags |= SCR_NUMERIC; X flags |= HELP_NUMERIC; X } X if (scr->flags & SCR_HELP_LOOP) X { X help_scr.flags |= SCR_HELP_LOOP; X help_scr.func_loop = scr->func_loop; X help_scr.timeout = scr->timeout; X } X if ((scr->flags & SCR_TYPE_AHEAD) && !(scr->lflags & SCR_UP)) X flags |= NO_REFRESH; X#endif X while (!quit && !(flags & STOP) && !(flags & END_SECTION)) X { X#ifdef NONSCREEN X if (get_page(help_file, &flags)) X put_page(help_file, &flags); X#else X if (get_page(&help_scr, help_file, &flags)) X put_page(&help_scr, help_file, &flags); X#endif X } X if (!quit) X#ifdef NONSCREEN X do_subhelp(file, help_file, &offset_end, &flags); X#else X do_subhelp(&help_scr, help_file, &offset_end, &flags); X#endif X#ifndef NONSCREEN X if (fs_help && (fs_help == help_scr.win)) X { X if (--fs_count == 0) X { X if (help_scr.win) X delwin(help_scr.win, !(flags & NO_REFRESH)); X fs_help = WIN_NULL; X } X } X else X { X if (help_scr.win) X delwin(help_scr.win, !(flags & NO_REFRESH)); X } X#endif X stat = TRUE; X } X else X stat = FALSE; X fclose(help_file); X if (level > 0) X level--; X#ifdef NONSCREEN X if (level == 0) X { X#ifdef UNIX X if (xflags) X { X tc_nocrmode(); X tc_echo(); X } X#endif X } X#endif X } X else X stat = FALSE; X } X return(stat); X} X X#ifndef NONSCREEN int wdo_help(win, file, section, flags) X WINDOW *win; X char *file; X char *section; X int flags; X{ X SCR scr; X X scr.win = win; X scr.head = 0; X scr.func_entry = 0; X scr.func_loop = 0; X scr.func_chk = 0; X scr.prompt = 0; X scr.entry = 0; X scr.active_entry = 0; X scr.last_active = 0; X scr.timeout = UNDETERMINED; X scr.help_file = file; X scr.help_section = section; X scr.flags = flags; X scr.lflags = 0; X scr.color = 0; X return(sdo_help(&scr)); X} X#endif X END_OF_FILE if test 40463 -ne `wc -c <'lib/help.c'`; then echo shar: \"'lib/help.c'\" unpacked with wrong size! fi # end of 'lib/help.c' fi echo shar: End of archive 9 \(of 9\). cp /dev/null ark9isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 9 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0