/* * High level routines dealing with the output to the screen. */ #ifdef AMIGA /* Compile with -HPreHeader.q to get "less.h"! */ #else #include "less.h" #endif public int errmsgs; /* Count of messages displayed by error() */ extern int sigs; extern int sc_width, sc_height; extern int ul_width, ue_width; extern int so_width, se_width; extern int bo_width, be_width; #ifdef AMIGA extern int it_width, ie_width; extern int nv_width, ne_width; extern int nrow; /* vertical screen size */ #endif #ifdef EIGHTBIT extern int bs_mode; #endif extern int tabstop; extern int twiddle; extern int any_display; extern char *line; extern char *first_cmd; /* * Display the line which is in the line buffer. */ #ifdef __STDC__ void put_line (void) #else public void put_line() #endif { #ifdef AMIGA register unsigned char *p; #else register char *p; #endif register int c; register int column; extern int auto_wrap, ignaw; if (sigs) /* * Don't output if a signal is pending. */ return; if (line == NULL) line = (twiddle) ? "~" : ""; column = 0; #ifdef AMIGA for (p = (unsigned char *)line; *p != '\0'; p++) #else for (p = line; *p != '\0'; p++) #endif { switch (c = *p) { case UL_CHAR: ul_enter(); column += ul_width; break; case UE_CHAR: ul_exit(); column += ue_width; break; case BO_CHAR: bo_enter(); column += bo_width; break; case BE_CHAR: bo_exit(); column += be_width; break; #ifdef AMIGA case IT_CHAR: it_enter(); column += it_width; break; case IE_CHAR: it_exit(); column += ie_width; break; case NV_CHAR: nv_enter(); column += nv_width; break; case NE_CHAR: nv_exit(); column += ne_width; break; #endif case '\t': do { putchr(' '); column++; } while ((column % tabstop) != 0); break; case '\b': #ifdef EIGHTBIT if (bs_mode == BS_CONTROL) { putchr('^'); putchr(carat_char(c)); column += 2; break; } #endif putbs(); column--; break; default: #ifdef EIGHTBIT /* Control characters are still control * characters. Replace them with some- * thing printable. */ if (control_char(c)) { putchr('^'); putchr(carat_char(c)); column += 2; } #else if (c & 0200) { /* * Control characters arrive here as the * normal character [carat_char(c)] with * the 0200 bit set. See pappend(). */ putchr('^'); putchr(c & 0177); column += 2; } #endif else { putchr(c); column++; } } } if (column < sc_width || !auto_wrap || ignaw) putchr('\n'); } /* * Is a given character a "control" character? * {{ ASCII DEPENDENT }} */ #ifdef __STDC__ int control_char (int c) #else public int control_char(c) int c; #endif { #ifdef EIGHTBIT /* SAS says 0xff is a control character, for some reason */ return iscntrl(c) && c != 0xff; #else return ( c < ' ' || c == '\177' ); #endif } /* * Return the printable character used to identify a control character * (printed after a carat; e.g. '\3' => "^C"). * {{ ASCII DEPENDENT }} */ #ifdef __STDC__ int carat_char (int c) #else public int carat_char(c) int c; #endif { return ((c == '\177') ? '?' : (c | 0100)); } static char obuf[1024]; static char *ob = obuf; /* * Flush buffered output. */ #ifdef __STDC__ void flush (void) #else public void flush() #endif { #ifdef AMIGA ttwrite ( obuf, (long) (ob-obuf)); #else write(1, obuf, ob-obuf); #endif ob = obuf; } /* * Discard buffered output. */ #ifdef __STDC__ void dropout (void) #else public void dropout() #endif { ob = obuf; } /* * Output a character. */ #ifdef __STDC__ void putchr (int c) #else public void putchr(c) int c; #endif { if (ob >= &obuf[sizeof(obuf)]) flush(); *ob++ = c; } /* * Output a string. */ #ifdef __STDC__ void putstr (register char *s) #else public void putstr(s) register char *s; #endif { while (*s != '\0') putchr(*s++); } /* * Output a message in the lower left corner of the screen * and wait for carriage return. */ static char return_to_continue[] = " (press RETURN)"; #ifdef __STDC__ void error (char *s) #else public void error(s) char *s; #endif { register int c; static char buf[2]; errmsgs++; #ifdef AMIGA /* nrow tells us if the window has been opened yet. any_display tells us if we have initialized reading a file yet. If either of these are false, trying to write to the screen now will cause trouble, either immediately or when we try to regenerate a non-existant display. */ if ( nrow < 2 || !any_display ) #else if (!any_display) #endif { /* * Nothing has been displayed yet. * Output this message on error output (file * descriptor 2) and don't wait for a keystroke * to continue. * * This has the desirable effect of producing all * error messages on error output if standard output * is directed to a file. It also does the same if * we never produce any real output; for example, if * the input file(s) cannot be opened. If we do * eventually produce output, code in edit() makes * sure these messages can be seen before they are * overwritten or scrolled away. */ #ifdef AMIGA /* If the window is too small, s may be NULL on Amiga */ if ( s ) MyRequester( s ); else MyRequester ( "Error" ); #else write(2, s, strlen(s)); write(2, "\n", 1); #endif return; } lower_left(); clear_eol(); so_enter(); #ifdef AMIGA if ( s ) #endif putstr(s); putstr(return_to_continue); so_exit(); #if ONLY_RETURN while ((c = getchr()) != '\n' && c != '\r') bell(); #else c = getchr(); if (c != '\n' && c != '\r' && c != ' ') { buf[0] = c; first_cmd = buf; } #endif lower_left(); #ifdef AMIGA if ( s && strlen(s) + sizeof(return_to_continue) + so_width + se_width + 1 > sc_width ) #else if (strlen(s) + sizeof(return_to_continue) + so_width + se_width + 1 > sc_width) #endif /* * Printing the message has probably scrolled the screen. * {{ Unless the terminal doesn't have auto margins, * in which case we just hammered on the right margin. }} */ repaint(); flush(); }