Files
open-simh.simtools/extracters/ods2/termio.c
Timothe Litt 66e00b9900 Backlog of work since 2016
Too much to list all, but includes (in no particular order):
 - Cleanup for 64-bit builds, MSVC warnings.
 - Structured help
 - Help file compiler.
 - Supports volsets, writes/create work.
 - Support for I18n in messages, help.
 - Makefiles.
 - Initialize volume/volset
 - Command line editing/history

Builds and works on Linux and Windows (VS).
Not recently built or tested on other platforms, but
not intentinonally broken.
2022-10-10 11:00:20 -04:00

348 lines
9.3 KiB
C

/* This is part of ODS2, originally written by Paul Nankervis,
* email address: Paulnank@au1.ibm.com
* ODS2 is distributed freely for all members of the
* VMS community to use. However all derived works
* must maintain comments in their source to acknowledge
* the contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#if !defined( DEBUG ) && defined( DEBUG_TERMIO )
#define DEBUG DEBUG_TERMIO
#else
#ifndef DEBUG
#define DEBUG 0
#endif
#endif
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#include <sys/ioctl.h>
#endif
#include "cmddef.h"
extern int interactive;
#ifdef USE_LIBEDIT
#include <histedit.h>
#ifdef HAVE_TERMCAP_H
#include <termcap.h>
#elif defined HAVE_TERM_H
#include <term.h>
#elif defined HAVE_CURSES_H
#include <curses.h>
#else
int tgetent (char *buffer, char *termtype);
char *tgetstr (char *name, char **area);
int tgetnum (char *name);
int tgetflag (char *name);
#endif
extern EditLine *editline;
/* Max size of a terminal description - documented as ">1024, probably 2048"
*/
#define TERMENTMAX (4096)
#define TERM_CLR_EOL caps[0].val
#define TERM_CUR_UP caps[1].val
#define TERM_CR caps[2].val
static struct cap {
char *id;
char *val;
char *def; } caps[] = {
{"ce", NULL,"\r "\
" \r" },
{"up", NULL, ""},
{"cr", NULL, "\r"},
{NULL, NULL, NULL} };
static int have_caps = 0;
static void get_termattrs(void) {
int ok;
struct cap *cp;
char *tentbuf, *term;
if( have_caps ) {
return;
}
have_caps = 1;
tentbuf = (char *)calloc( 1, TERMENTMAX ); /* May be ignored, or have desc. */
if( !tentbuf ) {
perror( "calloc" );
exit( EXIT_FAILURE );
}
term = getenv( "TERM" );
if( !(term && *term) ) {
term = "vt100";
}
ok = tgetent(tentbuf, term );
if( ok <= 0 ) {
if( ok < 0 )
fprintf( stderr, "Can't access termcap database\n" );
else
fprintf( stderr, "Terminal '%s' is not defined in termcap\n", term );
for( cp = caps; cp->id; cp++ )
cp->val = cp->def;
} else {
char *parbuf;
parbuf = calloc( 1, TERMENTMAX );
if( !parbuf ) {
perror("calloc");
exit( EXIT_FAILURE );
}
for( cp = caps; cp->id; cp++ ) {
char *area = parbuf;
cp->val = tgetstr( cp->id, &area );
if( cp->val ) {
size_t vlen;
vlen = strlen( cp->val ) + 1;
area = malloc( vlen );
if( !area ) {
perror( "malloc");
exit( EXIT_FAILURE );
}
memcpy( area, cp->val, vlen );
cp->val = area;
} else {
fprintf( stderr, "No %s for %s terminal\n", cp->id, term );
cp->val = cp->def;
}
}
free( parbuf );
}
free( tentbuf );
}
#endif
/******************************************************************* confirm_cmd() */
vmscond_t confirm_cmd( vmscond_t status, ... ) {
va_list ap;
char *response, *mp, *buf = NULL;
size_t bufsize = 16;
vmscond_t rcode;
do {
va_start( ap, status );
(void) vprintmsg( status,
MSG_TEXT | MSG_WITHARGS | MSG_NOCRLF,
ap );
va_end( ap );
fflush( stdout );
mp =
response = fgetline( stdin, FALSE, &buf, &bufsize );
while( mp != NULL && (*mp == ' ' || *mp == '\t') )
++mp;
if( mp != NULL && ( *mp == '\0' ||
keycomp( mp, "NO" ) ||
keycomp( mp, "FALSE" ) ||
keycomp( mp, "0" ) ) ) {
rcode = ODS2_CONFIRM_NO;
break;
}
if( mp == NULL || keycomp( mp, "ALL" ) ) {
rcode = ODS2_CONFIRM_ALL;
break;
}
if( keycomp( mp, "YES" ) ||
keycomp( mp, "TRUE" ) ||
keycomp( mp, "1" ) ) {
rcode = ODS2_CONFIRM_YES;
break;
}
if( keycomp( mp, "QUIT" ) ) {
rcode = ODS2_CONFIRM_QUIT;
break;
}
putchar( '\b' );
} while( 1 );
if( buf != NULL ) free( buf );
return rcode | STS$M_INHIB_MSG;
}
/******************************************************************* put_str() */
vmscond_t put_str( const char *buf, FILE *outf, pause_t *pause ) {
return put_strn( buf, strlen( buf ), outf, pause );
}
/******************************************************************* put_str() */
vmscond_t put_strn( const char *buf, size_t len,
FILE *outf, pause_t *pause ) {
vmscond_t sts;
if( len == 0 )
return SS$_NORMAL;
if( pause == NULL || pause->interval == 0 ) {
fwrite( buf, len, 1, outf );
return SS$_NORMAL;
}
while( len-- )
if( $FAILS(sts = put_c( *buf++, outf, pause )) )
return sts;
return SS$_NORMAL;
}
/******************************************************************* put_c() */
vmscond_t put_c( int c, FILE *outf, pause_t *pause ) {
vmscond_t sts;
fputc( c, outf );
if( c != '\n' || pause == NULL || pause->interval == 0 ) {
return SS$_NORMAL;
}
sts = SS$_NORMAL;
if( ++pause->lineno < pause->interval )
return SS$_NORMAL;
printmsg( pause->prompt, MSG_TEXT | MSG_NOCRLF );
fflush( stdout );
#ifdef USE_LIBEDIT
if( interactive ) {
get_termattrs();
while( 1 ) {
char ch;
c = el_getc( editline, &ch );
if( c > 0 ) {
putchar( ch );
fflush( stdout );
if( ch == '\r' )
continue;
}
if( c == 0 ) {
ch = '\n';
sts = SS$_ABORT;
} else if( tolower( ch ) == 'q' ) {
sts = SS$_ABORT;
continue;
} else if( tolower( ch ) == 'f' ) {
pause->interval = 0;
continue;
}
if( ch == '\n' ) {
pause->lineno = 0;
printf( "%s%s%s", TERM_CR, TERM_CUR_UP, TERM_CLR_EOL );
fflush( stdout );
return sts | STS$M_INHIB_MSG;
}
el_beep(editline);
}
} else
#endif
{
while( 1 ) {
c = getchar();
if( c == '\r' ) {
continue;
}
if( c == EOF ) {
c = '\n';
sts = SS$_ABORT;
} else if( tolower( c ) == 'q' ) {
sts = SS$_ABORT;
continue;
} else if( tolower( c ) == 'f' ) {
pause->interval = 0;
continue;
}
if( c == '\n' ) {
#ifdef _WIN32
CONSOLE_SCREEN_BUFFER_INFO csbi;
size_t wid;
fflush( stdout );
GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE ),
&csbi );
wid = (size_t)csbi.srWindow.Right - csbi.srWindow.Left + 1;
--csbi.dwCursorPosition.Y;
csbi.dwCursorPosition.X = 0;
SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ),
csbi.dwCursorPosition );
while( wid-- )
putchar( ' ' );
SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ),
csbi.dwCursorPosition );
#else
putchar( '\r' );
#endif
pause->lineno = 0;
fflush( stdout );
return sts | STS$M_INHIB_MSG;
}
putchar( '\b' );
}
}
}
/******************************************************************* termchar() */
void termchar( int *width, int *height ) {
if( width != NULL )
*width = 80;
if( height != NULL )
*height = 24;
{
#ifdef _WIN32
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
if( width != NULL )
*width = csbi.srWindow.Right - csbi.srWindow.Left + 1;
if( height != NULL )
*height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
#else
#ifdef TIOCGSIZE
struct ttysize ts;
ioctl(STDIN_FILENO, TIOCGSIZE, &ts);
if( width != NULL )
*width = ts.ts_cols;
if( height != NULL )
*height = ts.ts_lines;
#elif defined(TIOCGWINSZ)
struct winsize ts;
ioctl(STDIN_FILENO, TIOCGWINSZ, &ts);
if( width != NULL )
*width = ts.ws_col;
if( height != NULL )
*height = ts.ws_row;
#endif /* TIOCGSIZE */
#endif
}
return;
}