473 lines
8.9 KiB
C
473 lines
8.9 KiB
C
/****************************************************************/
|
|
/* */
|
|
/* ic_output.c */
|
|
/* */
|
|
/* Output routines for the "Integer Calculator". */
|
|
/* */
|
|
/****************************************************************/
|
|
/* origination 1988-Apr-6 Terrence W. Holm */
|
|
/****************************************************************/
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "ic.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************/
|
|
/* Code for handling termcap */
|
|
/****************************************************************/
|
|
|
|
|
|
#define TC_BUFFER 1024 /* Size of termcap(3) buffer */
|
|
#define TC_STRINGS 200 /* Enough room for cm,cl,so,se */
|
|
|
|
|
|
|
|
|
|
static char *Tmove; /* (cm) - Format for tgoto */
|
|
static char *Tclr_all; /* (cl) - String to clear screen */
|
|
static char *Treverse; /* (so) - String to reverse mode */
|
|
static char *Tnormal; /* (se) - String to undo reverse */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************/
|
|
/* */
|
|
/* Init_Termcap() */
|
|
/* */
|
|
/* Initializes the external variables for the */
|
|
/* current terminal. */
|
|
/* */
|
|
/* NULL is returned on error conditions. */
|
|
/* */
|
|
/****************************************************************/
|
|
|
|
|
|
Init_Termcap()
|
|
{
|
|
char *term;
|
|
char buffer[ TC_BUFFER ];
|
|
static char strings[ TC_STRINGS ];
|
|
char *s = &strings[0];
|
|
|
|
term = getenv( "TERM" );
|
|
|
|
if ( term == NULL )
|
|
return( 0 );
|
|
|
|
if ( tgetent( buffer, term ) != 1 )
|
|
return( 0 );
|
|
|
|
|
|
|
|
if ( (Tmove=tgetstr( "cm", &s )) == NULL )
|
|
return( 0 );
|
|
|
|
if ( (Tclr_all=tgetstr( "cl", &s )) == NULL )
|
|
return( 0 );
|
|
|
|
if ( (Treverse=tgetstr( "so", &s )) == NULL )
|
|
{
|
|
Treverse = s;
|
|
*s = '\0';
|
|
++s;
|
|
}
|
|
|
|
if ( (Tnormal=tgetstr( "se", &s )) == NULL )
|
|
{
|
|
Tnormal = s;
|
|
*s = '\0';
|
|
++s;
|
|
}
|
|
|
|
return( EOF );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************/
|
|
/* */
|
|
/* Move( column, line ) */
|
|
/* */
|
|
/* Use the termcap string to move the cursor. */
|
|
/* */
|
|
/****************************************************************/
|
|
|
|
|
|
Move( column, line )
|
|
int column;
|
|
int line;
|
|
|
|
{
|
|
Puts( tgoto( Tmove, column, line ) );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************/
|
|
/* */
|
|
/* Puts( string ) */
|
|
/* */
|
|
/* Write the given termcap string to the standard */
|
|
/* output device. */
|
|
/* */
|
|
/****************************************************************/
|
|
|
|
|
|
Puts( string )
|
|
char *string;
|
|
|
|
{
|
|
int Putchar();
|
|
|
|
tputs( string, 1, Putchar );
|
|
}
|
|
|
|
|
|
Putchar( c )
|
|
char c;
|
|
|
|
{
|
|
putchar( c );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************/
|
|
/* Output routines */
|
|
/****************************************************************/
|
|
|
|
|
|
|
|
|
|
/****************************************************************/
|
|
/* */
|
|
/* Draw_Help_Screen() */
|
|
/* */
|
|
/****************************************************************/
|
|
|
|
|
|
Draw_Help_Screen()
|
|
|
|
{
|
|
Puts( Tclr_all ); /* Clear the screen */
|
|
|
|
printf( "\n\n " );
|
|
Puts( Treverse );
|
|
printf( "IC COMMANDS" );
|
|
Puts( Tnormal );
|
|
printf( "\n\n\n" );
|
|
|
|
printf(" h Help ENTER Push stack\n");
|
|
printf(" i Input base (h d o b) DEL Clear entry\n" );
|
|
printf(" PGDN l Last top of stack\n" );
|
|
printf(" m Minix shell . Change sign\n" );
|
|
printf(" o Output base (h d o b a) + Add\n" );
|
|
printf(" DOWN p Pop stack - Subtract\n" );
|
|
printf(" END q Quit * Multiply\n" );
|
|
printf(" LEFT r Recall (0-9) / Divide\n" );
|
|
printf(" RIGHT s Store [+] (0-9) %% Remainder\n");
|
|
printf(" t Translate (char) ~ Not\n" );
|
|
printf(" PGUP w Write top to scratch pad & And\n" );
|
|
printf(" UP x Exchange top of stack | Or\n" );
|
|
printf(" HOME z Zero all state ^ Exclusive-or\n\n\n" );
|
|
|
|
printf( "\n\nPress a key to continue..." );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************/
|
|
/* */
|
|
/* Draw_Prompt( string ) */
|
|
/* */
|
|
/* Write a message in the "wait" area. */
|
|
/* */
|
|
/****************************************************************/
|
|
|
|
|
|
Draw_Prompt( string )
|
|
char *string;
|
|
|
|
{
|
|
Move( WAIT_COLUMN, WAIT_LINE );
|
|
|
|
Puts( Treverse );
|
|
printf( string );
|
|
Puts( Tnormal );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************/
|
|
/* */
|
|
/* Erase_Prompt() */
|
|
/* */
|
|
/* Erase the message in the "wait" area. */
|
|
/* */
|
|
/****************************************************************/
|
|
|
|
Erase_Prompt()
|
|
|
|
{
|
|
Move( WAIT_COLUMN, WAIT_LINE );
|
|
|
|
printf(" " );
|
|
|
|
Move( WAIT_COLUMN, WAIT_LINE );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************/
|
|
/* */
|
|
/* Draw_Screen( state ) */
|
|
/* */
|
|
/* Redraw everything. */
|
|
/* */
|
|
/****************************************************************/
|
|
|
|
|
|
Draw_Screen( s )
|
|
ic_state *s;
|
|
|
|
{
|
|
Puts( Tclr_all ); /* Clear the screen */
|
|
|
|
Draw_Stack( s );
|
|
Draw_Registers( s );
|
|
|
|
|
|
Move( STATUS_COLUMN, STATUS_LINE );
|
|
|
|
printf( "Input base = %2d ", s->input_base );
|
|
|
|
if ( s->output_base == ASCII )
|
|
printf( "Output is ASCII " );
|
|
else
|
|
printf( "Output base = %2d ", s->output_base );
|
|
|
|
if ( (int) s->scratch_pad != 0 )
|
|
printf( "Scratch file = %s", s->file_name );
|
|
|
|
Move( WAIT_COLUMN, WAIT_LINE );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************/
|
|
/* */
|
|
/* Draw_Stack( state ) */
|
|
/* */
|
|
/* Redraw the stack. */
|
|
/* */
|
|
/****************************************************************/
|
|
|
|
|
|
Draw_Stack( s )
|
|
ic_state *s;
|
|
|
|
{
|
|
int i;
|
|
|
|
for ( i = STACK_SIZE-1; i >= 0; --i )
|
|
{
|
|
Move( STACK_COLUMN, STACK_LINE + STACK_SIZE - 1 - i );
|
|
|
|
if ( i >= s->stack_size )
|
|
printf( "%*c", s->output_base == BINARY ? 32 : 17, ' ' );
|
|
else
|
|
Print_Number( stdout, s->stack[i], s->output_base );
|
|
}
|
|
|
|
Move( WAIT_COLUMN, WAIT_LINE );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************/
|
|
/* */
|
|
/* Draw_Registers( state ) */
|
|
/* */
|
|
/* Redraw the registers. Note that only registers */
|
|
/* in use are displayed. A register only drops */
|
|
/* out of use after a 'z' command, which will */
|
|
/* explicitly clear the display, thus we never */
|
|
/* have to "wipe off" a value, as the */
|
|
/* Draw_Stack() routine must. */
|
|
/* */
|
|
/****************************************************************/
|
|
|
|
|
|
Draw_Registers( s )
|
|
ic_state *s;
|
|
|
|
{
|
|
int i;
|
|
|
|
for ( i = 0; i < REGISTERS; ++i )
|
|
{
|
|
if ( (1 << i) & s->register_mask )
|
|
{
|
|
Move( REG_COLUMN, REG_LINE + i );
|
|
Print_Number( stdout, s->registers[i], s->output_base );
|
|
printf( " (r%1d)", i );
|
|
}
|
|
}
|
|
|
|
Move( WAIT_COLUMN, WAIT_LINE );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************/
|
|
/* */
|
|
/* Draw_Top_of_Stack( state ) */
|
|
/* */
|
|
/* Redraw only the entry on the top of the stack. */
|
|
/* */
|
|
/****************************************************************/
|
|
|
|
|
|
Draw_Top_of_Stack( s )
|
|
ic_state *s;
|
|
|
|
{
|
|
Move( STACK_COLUMN, STACK_LINE + STACK_SIZE - 1 );
|
|
|
|
Print_Number( stdout, s->stack[0], s->output_base );
|
|
|
|
Move( WAIT_COLUMN, WAIT_LINE );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************/
|
|
/* */
|
|
/* Print_Number( stream, number, output_base ) */
|
|
/* */
|
|
/* Output the "number" to "stream" in the */
|
|
/* specified "output_base". */
|
|
/* */
|
|
/****************************************************************/
|
|
|
|
|
|
Print_Number( stream, number, output_base )
|
|
FILE *stream;
|
|
long int number;
|
|
int output_base;
|
|
|
|
{
|
|
switch ( output_base )
|
|
{
|
|
case HEXADECIMAL : fprintf( stream, "%12lx", number );
|
|
break;
|
|
|
|
|
|
case DECIMAL : fprintf( stream, "%12ld", number );
|
|
break;
|
|
|
|
|
|
case OCTAL : fprintf( stream, "%12lo", number );
|
|
break;
|
|
|
|
|
|
case BINARY : {
|
|
unsigned long int mask;
|
|
char pad = ' ';
|
|
|
|
for ( mask = 0x80000000; mask > 1; mask >>= 1 )
|
|
putc( ( mask & number ) ? (pad = '0', '1') : pad, stream );
|
|
|
|
putc( ( 0x01 & number ) ? '1' : '0', stream );
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
case ASCII : {
|
|
char c = number & 0x7f;
|
|
|
|
if ( (number & ~ 0x7fL) == 0 )
|
|
fprintf( stream, "%15c", ' ' );
|
|
else
|
|
fprintf( stream, "%12lx + ", number & ~ 0x7fL );
|
|
|
|
if ( c < ' ' )
|
|
fprintf( stream, "^%c", c + '@' );
|
|
else if ( c == ' ' )
|
|
fprintf( stream, "sp" );
|
|
else if ( c < 0x7f )
|
|
fprintf( stream, " %c", c );
|
|
else
|
|
fprintf( stream, "^?" );
|
|
|
|
break;
|
|
}
|
|
|
|
default : fprintf( stderr, "Internal failure (output base)\n" );
|
|
Sigint();
|
|
}
|
|
}
|