|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T h
Length: 19751 (0x4d27)
Types: TextFile
Names: »help.c«
└─⟦a05ed705a⟧ Bits:30007078 DKUUG GNU 2/12/89
└─⟦e0e3e8967⟧ »./gnuplot.tar.Z«
└─⟦01af444b1⟧
└─⟦this⟧ »gnuplot/mainplot/help.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec1/gnuplot/help.c«
#include <stdio.h>
#include <io.h>
#include <stdlib.h>
#include <conio.h>
#include <signal.h>
#include <ctype.h>
#include <direct.h>
#include <process.h>
#include <string.h>
#include <dos.h>
/*****************************************************************************
* HELP
*
* This program provides a HELP environment similar to the VMS help facility.
* Instead of using a help library, however, this version uses a directory
* tree of text files. This was done primarily to allow easy editing and
* addition of help entries.
*
* The set of arguments passed from DOS is first scanned for switches. Then
* the remaining arguments are passed to the main help routine as a single
* string which is reparsed. This was done to allow easy recursion.
*
* Similar to the public domain help utility found on many UNIX systems, a
* help directory contains five possible entries in it.
* main help text: HELP.HLM
* manual page name: HELP.MAN
* subtopic texts: <topicname>.HLP
* subtopic directories: <topicname>
*
* Due to the filename size limitation of DOS, command line tokens are
* limited to eight characters.
*/
#define HELPVER "HELP - VMS-like help utility\nVersion 1.0.014NL - 6 January 1986\nRobert P. Scott\nDTS Engineering & Consulting\n29 Heritage Circle\nHudson, NH 03051-3427\n(603)886-1383\n"
#define STDDELIM " \r\n\t;" /* delimiters for parsing */
#define HELPMAIN "HELP.HLM" /* main help text filename */
#define MAXENT 128 /* maximum number of help entries*/
#define HELPEX ".HLP" /* help extension */
#define SWITCHR1 '-' /* unix like switch char */
#define SWITCHR2 '/' /* PC/MS-DOS std switch char */
#define PROMPT "Topic? "
#define DEFSEARCH "*.HLP" /* Default search string */
#define R_OK 04
#define MAXLINELEN 90
#define MAXNAMELEN 13 /* max length of NAME */
#define COLUMNSPACE 4
#define TERMWID 76
#define HELPDIR "."
#define ALL 0x37
#define DEFSCRLEN 17
int scrnlen;
int status;
int olddisk;
char dent[MAXENT][MAXNAMELEN];
char lent1[MAXENT][MAXLINELEN];
char lent2[MAXENT][MAXLINELEN];
char progname[MAXNAMELEN+4];
char olddir[MAXLINELEN];
char newdir[MAXLINELEN];
char currdir[MAXLINELEN];
char prompt[MAXLINELEN];
char *helpdir;
char dta[80];
int help(char *);
int outhelp(char *);
int allsel(void);
void set_dta(char *);
void select_disk(int);
int dir_get(char *,int );
char *gettok(char *,char *,char *,char *);
int isdelim(char ,char *);
int more(char *);
int pgbrk(void);
void stripnl(char *);
void setprompt(void);
void fstobs(char *);
void handler(void);
int kget(void);
void main(argc, argv)
int argc;
char *argv[];
{
char inbuf[MAXLINELEN];
int il; /* input buffer length */
int sl; /* token length */
int done; /* temporary flag */
char c; /* temporary char holder */
char *op; /* single argument pointer */
strcpy( progname,*argv++ ); /* Always save the program name */
helpdir = getenv( "HELP" ); /* use EV for directory if set */
olddisk = curr_disk(); /* save our starting disk */
getcwd( olddir, MAXLINELEN ); /* save our starting directory */
if ( signal( SIGINT, handler ) < 0 ) /* uh oh */
{
fprintf( stderr, "%s could not set SIGINT. Action undefined upon INT\n", progname );
}
argc--;
while (( argc ) && ( ( c = *(*argv) ) == SWITCHR1 ) || ( c == SWITCHR2 ))
{ /* must be options */
for (op = *argv; *op != '\0'; op++)
{
switch(*op)
{
case SWITCHR1 : /* ignore first and extras */
case SWITCHR2 :
break;
case 'd' : /* specifying help directory path explicitly */
helpdir = *++argv;
break;
case 'h' :
case 'v' : /* show version number */
fprintf( stdout, HELPVER );
bye( 0 );
default:
fprintf(stderr,"%s: %c: bad option.\n",
progname,*op);
break;
} /* switch */
} /* for ( steps through token ) */
argc--; argv++;
} /* while ( loops on argv arguments ) */
if (helpdir == NULL) /* if all else fails, use default */
helpdir = HELPDIR;
fstobs( helpdir ); /* normalize to dos directory seps */
if (isalpha(helpdir[0]) && helpdir[1] == ':')
select_disk(helpdir[0] - 'A');
if (chdir(helpdir) < 0) /* move to the help root */
{
fprintf(stderr,"%s: %s: help directory not found.\n",
progname,helpdir);
bye(1);
}
done = il = 0; /* reset input length */
inbuf[0] = 0; /* start with a null buffer */
while ( ( argc ) && ( *argv ) && !done ) /* concat. all remaining args */
{
sl = strlen( *argv ); /* new token length */
if ( ( il + sl ) < MAXLINELEN ) /* if enough room for added token */
{
if ( il && ( il < MAXLINELEN ) ) /* if not the first token */
{
strcat( inbuf, " " ); /* add a space */
strcat( inbuf, *argv ); /* and add the token */
}
else /* the first token */
strcpy( inbuf, *argv ); /* copy in the first token */
il += sl + 1; /* adjust the inbuf length ctr */
}
else /* no more room for added tokens */
done = 1; /* and we don't want junk added */
argv++;
argc--;
}
strupr( inbuf ); /* convert to upper case */
help( inbuf );
bye(0);
}
\f
/****************************************************************************
*/
help( buf )
char *buf;
{
enum {BOTH, JUSTMENU, NONE} subj; /* choice of .HLM and menu */
int done = 0;
char lbuf[MAXLINELEN]; /* local temporary copy */
char tbuf[MAXLINELEN]; /* local token buffer */
char *bufptr;
int lbufl, bufl; /* buffer lengths */
subj = BOTH;
for( ;; ) /* loop until user is tired */
{
if ( !buf || !*buf ) /* was input specified? */
{
switch (subj) {
case BOTH:
more( HELPMAIN );
/* no break; ! */
case JUSTMENU:
allsel();
/* case NONE: does none of this */
}
subj = JUSTMENU;
setprompt();
fputs( prompt, stdout ); /* prompt user for input */
if ( fgets( buf, MAXLINELEN, stdin ) == NULL ) /* EOF or error */
return( -1 );
}
strupr( buf ); /* convert to upper case */
stripnl( buf ); /* get rid of new line */
if ( gettok( buf, STDDELIM, tbuf, lbuf ) == NULL ) /* no input token */
return( 0 );
strcpy( buf, lbuf ); /* for next pass */
if ( tbuf[0] == '?' ) /* redisplay current main help */
{
subj = BOTH;
}
else
{
/* go ahead and assume the input is a request for more help! */
bufptr = tbuf;
while (( status = outhelp( bufptr ) ) != -1 )
{
bufptr = NULL; /* flag for next iteration */
if ( status == 1 )
{ /* it was a subdir! */
if ( ( status = help( buf ) ) < 0) /* parse further... */
return( status ); /* EOF or error */
else
{
chdir( ".." ); /* go back up for dos */
subj = NONE; /* suppress printing of .HLM and menu */
}
}
/* else bottom-level help was found */
}
}
}
}
\f
/****************************************************************************
* outhelp( filename ) - Output the given help file or ...
* char *filename; A text file name or directory name
*
*/
outhelp( filename )
char *filename;
{
static int counter;
char fullname[MAXLINELEN];
if (filename) { /* new filename (not a repeat) */
strcat(strcpy(fullname,filename),"*.HLP");
if ( !wildcard(fullname) ) {
fprintf( stdout, "\nSorry, no help found on '%s'\n", filename );
return( -1 ); /* no help available */
}
counter = 0;
} else if ( !dent[++counter][0] ) /* end of repeat search */
return( -1 );
if ( chdir(dent[counter]) == 0 ) /* see if it is a subdir by */
{ /* trying to go to it */
return( 1 ); /* tell caller we are there */
}
else {
more( dent[counter] ); /* output the file */
return( 0 );
}
}
\f
/****************************************************************************
* allsel() print the topics available in this directory
*
* This function prints a directory of the help files and dirs within this
* dir. Extensions are stripped off.
*
*/
allsel()
{
int totalnames;
int counter;
int j;
int longlen;
int rowcnt;
int colcnt;
int namewidth;
char *s1;
char row[TERMWID+1];
if ( !(totalnames = wildcard( DEFSEARCH )) )
return( 0 );
for (counter = 0; counter < totalnames; counter++) {
s1 = dent[counter];
while (*s1 && *s1 != '.')
s1++;
*s1 = '\0'; /* get rid of extension */
}
/* this next section will be made into a subroutine */
/* rebuild code from here --\/ */
longlen = 0;
for(counter=0; counter < totalnames; counter++ )
longlen = ((j=strlen(dent[counter]))>longlen)?j:longlen;
/* here print the names out in nice columns */
namewidth = longlen + COLUMNSPACE;
rowcnt = TERMWID / namewidth;
colcnt = (totalnames + (rowcnt-1)) / rowcnt ;
if (colcnt <= 0)
colcnt = 1;
/* if (col_flag && rowcnt > 1) */
if ( rowcnt > 1 )
{
fprintf( stdout, "\n Topics:\n\n");
for(counter=0; counter < colcnt ; counter++ )
{
for(j=0; j < TERMWID; row[j++] = ' ');
row[j] = '\0';
for(j=0, s1 = row; (counter+j) < totalnames; j += colcnt)
{
row[strlen(row)] = ' ';
strcpy(s1,dent[counter+j]);
s1 = s1 + namewidth;
}
fprintf( stdout, " %s\n",row);
}
putchar('\n');
}
else
{
for(counter=0; counter < totalnames; counter++)
fprintf( stdout, "%s\n", dent[counter] );
}
/* to here --/\ */
return( 0 );
}
\f
/*
* wildcard( filename ) searches out all wildcard matches for filename
* and puts them in dent[][]
*/
wildcard( filename )
char *filename;
{
register int j, counter, totalnames = 0;
static char tmpbuf[MAXLINELEN];
set_dta( dta );
while( ( dir_get( filename, ALL ) == 0 ) && ( totalnames < (MAXENT-1) ) )
{
filename = NULL;
strcpy(dent[totalnames++],&dta[30]);
}
dent[totalnames][0] = '\0'; /* terminating entry */
/* sort the names in ascending order with exchange algorithm */
for (counter = 0; counter < totalnames - 1; counter++)
for (j = counter+1; j <totalnames; j++)
if (strcmp(dent[counter],dent[j]) > 0)
{
strcpy( tmpbuf, dent[counter] );
strcpy( dent[counter], dent[j] );
strcpy( dent[j], tmpbuf );
}
return( totalnames );
}
\f
int curr_disk()
{
union REGS rg;
rg.h.ah = 0x19;
int86( 0x21, &rg, &rg);
return( rg.h.al );
}
void select_disk(num)
int num;
{
union REGS rg;
rg.h.ah = 0x0e;
rg.h.dl = num;
int86( 0x21, &rg, &rg);
}
void set_dta( dta )
char *dta;
{
union REGS rg;
rg.h.ah = 0x1a;
rg.x.dx = ( unsigned int )dta;
int86( 0x21, &rg, &rg );
}
dir_get( fn, type )
char *fn;
int type;
{
union REGS rg;
if ( fn )
{
rg.x.dx = ( unsigned int )fn;
rg.x.cx = type;
rg.h.ah = 0x4e;
int86( 0x21, &rg, &rg );
if ( rg.x.cflag & 0x01 )
return( rg.x.ax );
}
else
{
rg.h.ah = 0x4f;
int86( 0x21, &rg, &rg );
if ( rg.x.cflag & 0x01 )
return( rg.x.ax );
}
return( 0 );
}
\f
/****************************************************************************
* gettok( is, delim, tb, rb ) - Find token in input string
* char *is; Pointer to input string
* char *delim; Pointer to set of delimiting characters
* tb *tb Pointer to buffer to place token
* rb *rb Pointer to buffer to place ( input string - token )
*
* This function reads the input string looking for a token delimited by
* the beginning of the input buffer or a character in the delimiting set
* on the leading edge, and the end of the input buffer or a delimiting
* character on the trailing edge. The first character of the buffer
* which is not a character in the set of delimiting characters is taken as
* the first character of the token.
*
* If a pointer is passed in tb and/or rb, it is assumed to be a buffer of
* adequate size to hold the resultant string. A NULL may be passed in these
* variables if the result is not desired.
*
* Returns: A pointer to the first not delimiting character.
*/
char *gettok( is, delim, tb, rb )
char *is;
char *delim;
char *tb;
char *rb;
{
char *fc; /* pointer to first character of token */
fc = NULL; /* default no token found */
if ( tb ) /* if user gave us a token buffer */
*tb = 0; /* terminate the token buffer */
if ( rb ) /* if user gave us a remainder buffer */
*rb = 0; /* terminate the token buffer */
if ( is == NULL ) /* oops, got a 2001 */
return( NULL );
while ( *is && isdelim( *is, delim ) ) /* while leading delimiter */
is++; /* skip it */
if ( !*is )
return( NULL );
fc = is; /* save the pointer the first char */
while ( *is && !isdelim( *is, delim ) ) /* while not a delimiter */
{
if ( tb ) /* if user gave us a token buffer */
{
*tb = *is; /* move the character */
tb++; /* increment token buffer ptr */
}
is++;
}
if ( tb ) /* if user gave us a token buffer */
*tb = 0; /* terminate the token buffer */
if ( rb ) /* if user gave us a remainder buffer */
strcpy( rb, is ); /* copy the remainder */
return( fc );
}
isdelim( c, delim )
char c;
char *delim;
{
int dc; /* delimiter count */
int i; /* temporary counter */
char *tc; /* termporary pointer */
tc = delim; /* time to count the donuts */
dc = 0;
while ( *tc++ )
dc++;
for ( i=0; i<dc; i++ ) /* loop through the delimiters */
{
if ( c == delim[i] ) /* if a delimiter */
return( 1 ); /* return found */
}
return( 0 ); /* return not found */
}
\f
more( fn )
char *fn;
{
FILE *sfd;
char buf[512];
int lct;
lct = 0;
scrnlen = DEFSCRLEN;
if ( ( sfd = fopen( fn, "r" ) ) != NULL ) /* got a file */
{
putchar('\n');
while( fgets( buf, 512, sfd ) )
{
if ( lct == scrnlen )
{
lct = 0;
if ( pgbrk() )
{
fclose( sfd );
return( 1 );
}
}
fputs( buf, stdout );
lct++;
}
fclose( sfd );
}
return( 0 );
}
pgbrk()
{
register int c,i;
static char moreprompt[] = "More? ";
printf( moreprompt );
c = kget();
putchar( '\r' );
for (i = sizeof(moreprompt); i--;) /* erase the prompt */
putchar( ' ' );
putchar( '\r' );
return ( c == 'N' );
}
void stripnl( buf )
char *buf;
{
while ( *buf )
{
if ( *buf == '\n' )
*buf = 0;
buf++;
}
}
\f
void setprompt()
{
char *hs; /* pointer to the first / in helpdir */
char *cs; /* pointer to first / in current dir */
char *pp; /* pointer into prompt */
getcwd( currdir, MAXLINELEN );
hs = strchr( helpdir, '\\' ); /* ignore drive names */
cs = strchr( currdir, '\\' ); /* ignore drive names */
while ( *hs && ( *hs == *cs ) ) /* skip help directory root */
{
hs++;
cs++;
}
pp = prompt;
while ( *cs ) /* use the rest for the prompt */
{
switch (*cs) {
case '\\': /* convert to spaces for readability */
*pp++ = ' ';
cs++;
break;
case '.':
while (*++cs && *cs != '\\')
;
break;
default:
*pp++ = *cs++;
}
}
/* if ( pp != prompt ) /* not at root... */
*pp++ = ' '; /* add a pleasing space */
*pp = '\0'; /* terminate the string */
strcat( prompt, PROMPT ); /* and the default ending */
}
void fstobs( str )
char *str;
{
strupr( str ); /* dos only understands one case */
while ( *str )
{
if ( *str == '/' ) /* convert UNIX to MSDOS seps */
*str = '\\';
str++;
}
}
void handler()
{
int c;
if ( signal( SIGINT, handler ) < 0 ) /* uh oh */
{
fprintf( stderr, "%s could not set SIGINT. Action undefined upon INT\n", progname );
}
fprintf( stdout, "Terminate process [y|N]" );
c = kget();
fputc( '\n', stdout );
if ( c == 'Y' )
bye(0);
}
kget()
{
char c;
while ( kbhit() == 0 )
{
}
c = ( char )getche();
c = toupper( c );
return( c );
}
bye(status)
{
select_disk( olddisk );
chdir( olddir ); /* go back to our origin */
exit(status);
}