/* screenio.c - display functions $Id: screenio.c,v 0.2 1997/03/28 03:17:23 tjchol01 Exp $ Authors: Andrew Trevorrow, Ian Dall, Geoffrey Tobin, Tomasz J. Cholewo */ #include "dvgt.h" #include "screenio.h" #include "unixio.h" #include "vdu.h" /* Variables Exported, via "screenio.h" */ char TeXtoASCII[XXX]; /* IMPORT InitVDU, ClearScreen, StartText, ClearScreen, ResetVDU. To handle ^Z suspension properly, ScreenIO needs to use some VDU routines. */ /* SYSDEP: We need to use the Unix write routine. In particular, using Pascal's write/writeln has some nasty side-effect that prevents BusyRead from working! */ int textlinewidth; /* text characters (columns) per line */ int textcolumn = 0; /* column number in current text line */ /*--------------------------------------------------------------------*/ int MesgChar (int ch) { int status; /* maxcol <= both size of a string, and width of a line */ int maxcol = (maxstring < textlinewidth ? maxstring : textlinewidth); /* Keep messages within maxcol columns */ if (textcolumn >= maxcol) status = EOF; else { status = putchar (ch); ++textcolumn; } return status; } /* MesgChar */ /*--------------------------------------------------------------------*/ int MesgString (const char *s) { int status; String message; /* maxcol <= both size of a string, and width of a line */ int maxcol = (maxstring < textlinewidth ? maxstring : textlinewidth); /* Keep messages within maxcol columns */ if (textcolumn < 0 || textcolumn >= maxcol) { strcpy (message, ""); } else { strncpy (message, s, maxcol - textcolumn); message[maxcol - textcolumn] = '\0'; } status = fputs (message, stdout); textcolumn += strlen (message); return status; } /* MesgString */ /*--------------------------------------------------------------------*/ int MesgFlush () { int status = fflush (stdout); textcolumn = 0; return status; } /* MesgFlush */ /*--------------------------------------------------------------------*/ void MesgLine () { save_temp_tty (); rawoutoff (); /* Enable NL to CR+LF mapping */ /*!!! putchar (CR); *//* SYSDEP: Really an NL */ putchar ('\r'); /* SYSDEP: Really an NL */ putchar ('\n'); /* SYSDEP: Really an NL */ MesgFlush (); /* MesgLine also updates terminal */ restore_temp_tty (); } /* MesgLine */ /*--------------------------------------------------------------------*/ static int MesgCard (int c) { /* Since the vast majority of given values will be small numbers, we avoid recursion until c >= 100. */ int len = 0; if (c < 10) { MesgChar (c + '0'); ++len; } else if (c < 100) { MesgChar (c / 10 + '0'); MesgChar (c % 10 + '0'); len += 2; } else { /* c >= 100 */ len += MesgCard (c / 100); /* recursive if c >= 100 */ c %= 100; MesgChar (c / 10 + '0'); MesgChar (c % 10 + '0'); len += 2; } return (len); } /* MesgCard */ /*--------------------------------------------------------------------*/ int MesgInt (int i) { int len = 0; if (i < 0) { MesgChar ('-'); ++len; i = abs (i); } len += MesgCard (i); return (len); } /* MesgInt */ /*--------------------------------------------------------------------*/ void WriteLine () { WriteChar (CR); WriteFlush (); /* WriteLine also updates terminal */ } /* WriteLine */ /*--------------------------------------------------------------------*/ static void WriteCard (int c) { /* Since the vast majority of given values will be small numbers, we avoid recursion until c >= 100. */ if (c < 10) { WriteChar (c + '0'); return; } if (c < 100) { WriteChar (c / 10 + '0'); WriteChar (c % 10 + '0'); return; } else { WriteCard (c / 100); /* recursive if c >= 100 */ c %= 100; WriteChar (c / 10 + '0'); WriteChar (c % 10 + '0'); } } /* WriteCard */ /*--------------------------------------------------------------------*/ void WriteInt (int i) { if (i < 0) { WriteChar ('-'); i = abs (i); } WriteCard (i); } /* WriteInt */ /*--------------------------------------------------------------------*/ static void Restore_Temp_Terminal () { /* Restore_Temp_Terminal is for screenio.c only. */ MesgFlush (); /* make sure terminal is up-to-date */ restore_temp_tty (); /* restore terminal characteristics saved below */ } /* Restore_Temp_Terminal */ /*--------------------------------------------------------------------*/ void RestoreTerminal () { /* RestoreTerminal restores the initial terminal setting. */ /* It should be called before any client module terminates. */ MesgFlush (); /* make sure terminal is up-to-date */ restore_init_tty (); /* restore terminal characteristics saved below */ } /* RestoreTerminal */ /*--------------------------------------------------------------------*/ void ReadChar (char *ch) { /* gt - if cbreak's off, turn it on */ singlecharon (); /* gt - if echo's on, turn it off */ echooff (); /* gt - at this point, we need singlechar (cbreak) on and echo off. */ /* gt - BUT WHY? */ /* check for CTRL-C or CTRL-Z */ /* Interrupted by user? (CTRL-C) */ if (sig_flags.intr) { /* echo ch since echooff has been called */ /* interrupt */ sig_flags.intr = 0; /* reset intr flag */ *ch = CR; /* return to "Command: " prompt level */ } else if (sig_flags.tstop) { /* Suspended by user? (CTRL-Z) */ /* suspend */ sig_flags.tstop = 0; /* reset tstop flag */ StartText (); ClearScreen (); MesgLine (); ResetVDU (); Restore_Temp_Terminal (); suspend (); save_temp_tty (); singlecharon (); rawouton (); echooff (); InitVDU (); StartText (); ClearScreen (); *ch = CR; /* return to Command: level */ } else { putchar (*ch = getchar ()); } } /* ReadChar */ /*--------------------------------------------------------------------*/ void ReadString (char *s) { /* Read a string of characters. The routine is terminated upon carriage return. */ char ch; int i; singlecharoff (); /* read string in cooked mode */ rawoutoff (); echoon (); /* echo characters */ for (i = 0; true; i++) { if (sig_flags.intr) { /* interrupt */ sig_flags.intr = 0; /* reset intr flag */ s[0] = '\0'; break; } if (sig_flags.tstop) { /* suspend */ sig_flags.tstop = 0; /* reset tstop flag */ StartText (); ClearScreen (); MesgLine (); ResetVDU (); Restore_Temp_Terminal (); suspend (); save_temp_tty (); /* singlecharon and echooff are called below */ InitVDU (); StartText (); ClearScreen (); s[0] = '\0'; break; } ch = getchar (); if (ch == CR) { s[i] = '\0'; break; } s[i] = ch; if (i == maxstring) { s[i] = '\0'; break; } } singlecharon (); /* return to cbreak mode */ rawouton (); echooff (); /* and no echo */ } /* ReadString */ /*--------------------------------------------------------------------*/ boolean BusyRead (char *ch) { /* Return TRUE if ch is waiting in input buffer or if a ^C or ^Z has been typed. Set ch to CR or the character read (no echo). If nothing in input buffer, then ch is undefined and we return FALSE. */ if (sig_flags.intr) { /* interrupt */ sig_flags.intr = 0; *ch = CR; /* main module will return to Command: level */ return true; } if (sig_flags.tstop) { /* suspend */ sig_flags.tstop = 0; StartText (); ClearScreen (); MesgLine (); ResetVDU (); Restore_Temp_Terminal (); suspend (); save_temp_tty (); /* singlecharon and echooff are called below */ InitVDU (); StartText (); ClearScreen (); *ch = CR; /* after suspend, return to Command: level */ return true; } /* SYSDEP: buffercount assumes singlecharon and echooff have been called */ /* gt - check whether singlecharon and echooff have been called */ if (cmode_flags.cbreak == 0) singlecharon (); if (cmode_flags.echo == 1) echooff (); if (buffercount () == 0) return false; else { *ch = getchar (); return true; } } /* BusyRead */ /*--------------------------------------------------------------------*/ static void InitTeXtoASCII () { /* Initialize TeXtoASCII array used in specific ShowChar/Rectangle routines to map a given TeX char into a similar, displayable ASCII char. */ int i; for (i = 0; i <= 0xa; i++) /* Greek letters */ TeXtoASCII[i] = '?'; for (i = 0xb; i <= 0xf; i++) /* ligatures */ TeXtoASCII[i] = '?'; TeXtoASCII[0x10] = 'i'; /* dotless i */ TeXtoASCII[0x11] = 'j'; /* dotless j */ TeXtoASCII[0x12] = '`'; /* grave accent */ TeXtoASCII[0x13] = '\''; /* acute accent */ for (i = 0x14; i <= 0x17; i++) /* high accents */ TeXtoASCII[i] = '~'; TeXtoASCII[0x18] = ','; /* cedilla */ for (i = 0x19; i <= 0x20; i++) /* foreigns */ TeXtoASCII[i] = '?'; for (i = 0x21; i <= 0x5b; i++) /* same */ TeXtoASCII[i] = i; TeXtoASCII[0x5c] = '"'; /* open dble quote */ TeXtoASCII[0x5d] = ']'; /* same */ for (i = 0x5e; i <= 0x5f; i++) /* more accents */ TeXtoASCII[i] = '^'; for (i = 0x60; i <= 0x7a; i++) /* same */ TeXtoASCII[i] = i; for (i = 0x7b; i <= 0x7c; i++) /* en & em dash */ TeXtoASCII[i] = '-'; for (i = 0x7d; i <= 0x7f; i++) /* more accents */ TeXtoASCII[i] = '~'; for (i = 0x80; i <= 0xff; i++) /* non-ASCII, but 8-bit: 128 to 255 */ TeXtoASCII[i] = '?'; } /* InitTeXtoASCII */ /*--------------------------------------------------------------------*/ void InitScreenIO () { InitTeXtoASCII (); /* We first save the current terminal characteristics. save_init_tty also calls save_temp_tty, which sets up ^C/^Z interrupt handlers; see unixio.c. */ save_init_tty (); atexit (RestoreTerminal); singlecharon (); /* cbreak mode for ReadChar and BusyRead */ echooff (); /* no echo for BusyRead */ rawouton (); /* was _IOFBF */ #ifdef SETVBUF_REVERSED if (setvbuf (stdout, _IONBF, NULL, BUFSIZ / 4) != 0) { #else if (setvbuf (stdout, NULL, _IONBF, BUFSIZ / 4) != 0) { #endif MesgString ("screenio.c: InitScreenIO: setvbuf failed!"); MesgLine (); } } /* InitScreenIO */ /*--------------------------------------------------------------------*/ /* end screenio.c */