/* screenio.c - 16:00 GMT +10:00 Wed 4 Aug 1993 - modifier Geoffrey Tobin */ /* From input file "../include/globals.p" */ #include "config.h" #include "globals.h" #include "screenio.h" #include "unixio.h" #include "vdu.h" /* Variables Exported, via "screenio.h" */ Char TeXtoASCII[XXX]; /* IMPORT InitVDU, LogClearScreen, 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 */ /******************************************************************************/ #ifdef __STDC__ int MesgChar (int ch) #else int MesgChar (ch) int ch; #endif { 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); if (logfile != NULL) putc (ch, logfile); ++ textcolumn; } #ifdef COLUMN_LOG fflush (logfile); fprintf (logfile, "%% MesgChar: textcolumn = %d\n", textcolumn); fflush (logfile); #endif return status; } /* MesgChar */ /******************************************************************************/ #ifdef __STDC__ int MesgString (const char * s) #else int MesgString (s) char * s; #endif { 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, ""); if (logfile != NULL) { fprintf (logfile, "textcolumn = %d : must be 0 <= textcolumn < maxcol = %d\n", textcolumn, maxcol); } } else { strncpy (message, s, maxcol-textcolumn); message[maxcol-textcolumn] = '\0'; } status = fputs (message, stdout); if (logfile != NULL) fputs (message, logfile); textcolumn += strlen (message); #ifdef COLUMN_LOG fflush (logfile); fprintf (logfile, "%% MesgString: textcolumn = %d\n", textcolumn); fflush (logfile); #endif return status; } /* MesgString */ /******************************************************************************/ int MesgFlush (VOID) { int status = fflush (stdout); textcolumn = 0; if (logfile != NULL) { fflush (logfile); #ifdef COLUMN_LOG fprintf (logfile, "%% MesgFlush: textcolumn = %d\n", textcolumn); fflush (logfile); #endif } return status; } /* MesgFlush */ /******************************************************************************/ Void MesgLine (VOID) { save_temp_tty(); rawoutoff(); /* Enable NL to CR+LF mapping */ putchar (CR); /* SYSDEP: Really an NL */ if (logfile != NULL) fprintf (logfile, "\n"); MesgFlush(); /* MesgLine also updates terminal */ restore_temp_tty(); } /* MesgLine */ /******************************************************************************/ #ifdef __STDC__ Static int MesgCard (int c) #else Static int MesgCard (c) int c; #endif { /* 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 */ /******************************************************************************/ #ifdef __STDC__ int MesgInt (int i) #else int MesgInt (i) int i; #endif { int len = 0; if (i < 0) { MesgChar ('-'); ++ len; i = abs (i); } len += MesgCard (i); return (len); } /* MesgInt */ /******************************************************************************/ Void WriteLine (VOID) { WriteChar (CR); WriteFlush(); /* WriteLine also updates terminal */ } /* WriteLine */ /******************************************************************************/ #ifdef __STDC__ Static Void WriteCard (int c) #else Static Void WriteCard (c) int c; #endif { /* 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 */ /******************************************************************************/ #ifdef __STDC__ Void WriteInt (int i) #else Void WriteInt (i) int i; #endif { if (i < 0) { WriteChar ('-'); i = abs (i); } WriteCard (i); } /* WriteInt */ /******************************************************************************/ static Void Restore_Temp_Terminal (VOID) { /* 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 (VOID) { /* 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 */ /******************************************************************************/ #ifdef __STDC__ Void ReadChar (Char *ch) #else Void ReadChar (ch) Char * ch; #endif { /* gt - if cbreak's off, turn it on */ if (cmode_flags.cbreak == 0) singlecharon(); /* gt - if echo's on, turn it off */ if (cmode_flags.echo == 1) 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(); LogClearScreen(); MesgLine(); ResetVDU(); Restore_Temp_Terminal(); suspend(); save_temp_tty(); singlecharon(); rawouton(); echooff(); InitVDU(); StartText(); LogClearScreen(); *ch = CR; /* return to Command: level */ } else { (void) putchar (*ch = getchar()); if (logfile != NULL) putc (*ch, logfile); } } /* ReadChar */ /******************************************************************************/ #ifdef __STDC__ Void ReadString (Char *s) #else Void ReadString (s) Char * s; #endif { /* 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(); LogClearScreen(); MesgLine(); ResetVDU(); Restore_Temp_Terminal(); suspend(); save_temp_tty(); /* singlecharon and echooff are called below */ InitVDU(); StartText(); LogClearScreen(); s[0] = '\0'; break; } ch = getchar(); if (ch == CR) { s[i] = 0; if (logfile != NULL) fprintf (logfile, "\n"); break; } s[i] = ch; if (logfile != NULL) putc (ch, logfile); if (i == maxstring) { s[i] = '\0'; break; } } singlecharon(); /* return to cbreak mode */ rawouton(); echooff(); /* and no echo */ } /* ReadString */ /******************************************************************************/ #ifdef __STDC__ boolean BusyRead (Char *ch) #else boolean BusyRead (ch) Char * ch; #endif { /* 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(); LogClearScreen(); MesgLine(); ResetVDU(); Restore_Temp_Terminal(); suspend(); save_temp_tty(); /* singlecharon and echooff are called below */ InitVDU(); StartText(); LogClearScreen(); *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(); if (logfile != NULL) putc (*ch, logfile); return true; } } /* BusyRead */ /******************************************************************************/ Static Void InitTeXtoASCII (VOID) { /* 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 (VOID) { 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(); singlecharon(); /* cbreak mode for ReadChar and BusyRead */ echooff(); /* no echo for BusyRead */ rawouton(); if (setvbuf (stdout, NULL, _IOFBF, BUFSIZ/4) != 0) { MesgString ("screenio.c: InitScreenIO: setvbuf failed!"); MesgLine(); } } /* InitScreenIO */ /******************************************************************************/ /* end screenio.c */