2
/* This file contains the terminal "driver" code for splitsh.
3
It is designed to keep track of the position of the cursor
4
while handling a split window of vt100 emulation.
5
All of the routines assume that there is no other output
6
going onto the standard output screen, to mess it up.
8
Many thanks to Matt Ostanik who wrote the ANSI Handbook.
11
#include <sys/types.h>
13
#include <termio.h> /* Used only for TIOCGWINSZ */
15
#include <sys/ioctl.h> /* Used only for TIOCGWINSZ */
26
#define SEP_CHAR ' ' /* Separator bar character */
28
int TABSTOP=8; /* The default tabstop value */
30
/* Two virtual windows + a pointer to the current one */
31
static window upper, lower;
34
/* One physical window */
35
struct physical physical;
37
static char terminal_type[BUFSIZ]; /* Our terminal type */
38
static char *sep; /* The window separator string */
40
/* The various output processing functions, based on state */
42
void E_(), E_brac(), E_brac_Q(), E_lparen(), E_rparen(), E_pound();
44
/* Make these four variables accessable to the calling program */
45
int UU_lines=0; /* The user requested lines for the upper window */
46
int WU_lines=0; /* The number of lines for the upper window */
47
int WL_lines=0; /* The number of lines for the lower window */
48
int W_columns=0; /* The number of columns per window */
50
static int LU_lines; /* A local copy of UU_lines that is modified */
52
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
53
/* Reset the escape scanning sequence: */
54
static void reset_escape(win)
59
win->process_char=scan_for_esc;
60
for ( i=0; i<MAX_PARAMS; ++i )
63
win->cur_param=(&win->esc_param[win->param_idx]);
65
static void reset_esc()
69
/* Initialize a window structure: */
70
static void vt_resetwin(win)
75
win->saved_cursor.x=1;
76
win->saved_cursor.y=1;
77
win->cols=physical.cols;
79
win->scr_lower=win->rows;
80
win->saved_cursor.x=0;
81
win->saved_cursor.y=0;
82
win->key_state=normal;
84
win->saved_textattr=NORMAL;
85
win->charset[G0]=US_CHARSET;
86
win->charset[G1]=US_CHARSET;
89
/* Check to make sure the window cursor values are sane. */
90
static void vt_checkwin(win)
93
if ( win->cursor.x > win->rows )
94
win->cursor.x=win->rows;
95
if ( win->cursor.y > win->cols )
96
win->cursor.y=win->cols;
97
if ( win->scr_lower > win->rows )
98
win->scr_lower=win->rows;
100
/* Set the current window: */
101
static int lastwin = (-1);
108
/* Are we already in position? */
109
if ( which == lastwin )
112
/* Set the current window and move the cursor into position */
113
curwin = physical.subwins[which];
114
other = physical.subwins[!which];
115
vt_setscroll(curwin->scr_upper+curwin->row_offset,
116
curwin->scr_lower+curwin->row_offset);
117
vt_goto(curwin->cursor.x+curwin->row_offset, curwin->cursor.y);
119
/* Make sure the terminal is in the current window's state */
120
for ( i=0; i<NCHARSETS; ++i ) {
121
if ( curwin->charset[i] != other->charset[i] )
122
vt_altcharset(i, curwin->charset[i]);
124
if ( curwin->key_state != other->key_state )
125
vt_keystate(curwin->key_state);
126
if ( curwin->textattr != other->textattr )
127
vt_setattr((int)curwin->textattr);
132
/* Set the terminal attributes to those of the specified window */
133
/* This must be called _after_ vt_restcursor(), or it won't work */
134
static void set_attr(win)
137
unsigned char on=NORMAL;
140
(void) check_attr(0, win->textattr, &on);
143
/* Process the ^[[X;Xm escape. Made into a separate routine to support
145
static void process_m(win, n)
150
case 0: /* Turn all attributes off */
151
win->textattr=NORMAL;
154
case 1: /* Turn on bold */
155
win->textattr |= BOLD;
158
case 2: /* Half brightness */
161
case 4: /* Turn on underlining */
162
win->textattr |= UNDERLINE;
165
case 5: /* Turn on blinking */
166
win->textattr |= BLINK;
169
case 7: /* Turn on reverse */
170
win->textattr |= REVERSE;
173
case 21: /* Normal brightness */
176
case 22: /* Turn off bold */
177
win->textattr &= ~BOLD;
180
case 24: /* Turn off underlining */
181
win->textattr &= ~UNDERLINE;
184
case 25: /* Turn off blinking */
185
win->textattr &= ~BLINK;
188
case 27: /* Turn off reverse */
189
win->textattr &= ~REVERSE;
199
case 37: /* Set foreground color */
209
case 47: /* Set background color */
212
default: /* Unknown escape */
216
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
217
void scan_for_esc(c, source)
224
/* Taken from vt102.codes */
225
case '\000': /* NULL (fill character) */
226
case '\003': /* EXT (half duplex turnaround) */
227
case '\004': /* EOT (can be disconnect char) */
228
case '\005': /* ENQ (generate answerback) */
231
case '\007': /* BEL (sound terminal bell) */
234
case '\b': /* Backspace; move left one character */
235
if ( curwin->cursor.y != 1 ) {
237
vt_left(curwin->esc_param[0]);
240
case '\t': /* Tab. Handle with direct motion (Buggy) */
244
} while ( !curwin->tabstops[curwin->cursor.y-1]
245
&& (curwin->cursor.y < curwin->cols) );
246
vt_right(curwin->cursor.y - i);
248
case '\013': /* Processed as linefeeds */
249
case '\014': /* Don't let the cursor move below window or scrolling region */
250
case '\n': if ( curwin->cursor.x < curwin->scr_lower )
253
scroll_video(curwin, 1);
256
case '\r': /* Move cursor to left margin */
257
curwin->cursor.y = 1;
260
case '\016': /* S0 (selects G1 charset) */
261
case '\017': /* S1 (selects G0 charset) */
262
case '\021': /* XON (continue transmission) */
263
case '\022': /* XOFF (stop transmission) */
266
case '\030': /* Processed as escape cancel */
267
case '\032': reset_esc();
269
case '\033': curwin->process_char=E_;
271
default: if ( curwin->cursor.y > curwin->cols )
273
if (curwin->cursor.x<curwin->scr_lower)
277
scroll_video(curwin, 1);
281
add_video(curwin, c); printf("%c", c);
291
/* Return inside the switch to prevent reset_esc() */
293
case '\030': /* Processed as escape cancel */
294
case '\032': reset_esc();
296
case '[': curwin->process_char=E_brac;
298
case '(': curwin->process_char=E_lparen;
300
case ')': curwin->process_char=E_rparen;
302
case '#': curwin->process_char=E_pound;
304
case 'D': /* Cursor down with scroll up at margin */
305
if ( curwin->cursor.x < curwin->scr_lower ) {
308
scroll_video(curwin, 1);
311
case 'M': /* Reverse scroll (move up; scroll at top) */
312
if ( (curwin->cursor.x > curwin->scr_upper) )
315
revscroll_video(curwin, 1);
318
case 'E': /* Next line (CR-LF) */
319
if ( curwin->cursor.x < curwin->scr_lower )
322
scroll_video(curwin, 1);
323
curwin->cursor.y = 1;
326
case '7': /* Save cursor and attribute */
327
curwin->saved_cursor=curwin->cursor;
328
curwin->saved_textattr=curwin->textattr;
330
case '8': /* Restore saved cursor and attribute */
331
curwin->cursor=curwin->saved_cursor;
332
if ( curwin->cursor.x > curwin->rows )
333
curwin->cursor.x = curwin->rows;
334
if ( curwin->cursor.y > curwin->cols )
335
curwin->cursor.y = curwin->cols;
336
vt_goto(curwin->cursor.x+curwin->row_offset,
338
curwin->textattr=curwin->saved_textattr;
341
case '=': /* Set application keypad mode */
342
curwin->key_state=application;
343
vt_keystate(curwin->key_state);
345
case '>': /* Set numeric keypad mode */
346
curwin->key_state=normal;
347
vt_keystate(curwin->key_state);
349
case 'N': /* Select charset G2 for one character */
352
case 'O': /* Select charset G3 for one character */
355
case 'H': /* Set horizontal tab */
356
curwin->tabstops[curwin->cursor.y-1]=1;
358
case 'Z': /* Request terminal identification string */
359
/* Respond with "I am a vt102" */
360
write(*source, "\033[?6c", 5);
362
case 'c': /* Terminal reset */
365
default: /* Unrecognized escape: ignore */
370
void E_brac(c, source)
377
/* Check for numeric argument first */
379
*curwin->cur_param *= 10;
380
*curwin->cur_param += (c-'0');
384
/* Return inside the switch to prevent reset_esc() */
386
case '\030': /* Processed as escape cancel */
387
case '\032': reset_esc();
389
case '?': /* Format should be \E[?<n> */
390
if ( *curwin->cur_param )
393
curwin->process_char=E_brac_Q;
395
case ';': if ( ++curwin->param_idx < MAX_PARAMS ) {
397
&curwin->esc_param[curwin->param_idx];
400
case 'h': /* Set modes */
401
switch (curwin->esc_param[0]) {
402
case 2: /* Lock keyboard */
404
case 4: /* Character insert mode */
406
case 12: /* Local echo on */
407
/* UNSUPPORTED (easily supported) */
408
case 20: /* <Return> = CR */
409
/* UNSUPPORTED (easily supported) */
413
case 'l': /* Reset modes */
414
switch (curwin->esc_param[0]) {
415
case 2: /* Unlock keyboard */
417
case 4: /* Character overstrike mode */
419
case 12: /* Local echo off */
420
/* UNSUPPORTED (easily supported) */
421
case 20: /* <Return> = CR-LF */
422
/* UNSUPPORTED (easily supported) */
426
case 'r': /* Set scroll region */
427
if ( ! curwin->esc_param[0] && ! curwin->esc_param[1] ) {
429
curwin->scr_lower=curwin->rows;
431
/* Check parameters: VERY important. :) */
432
if (curwin->esc_param[0] < 1) /* Not needed */
435
curwin->scr_upper=curwin->esc_param[0];
437
if ( curwin->esc_param[1] > curwin->rows )
438
curwin->scr_lower=curwin->rows;
440
curwin->scr_lower=curwin->esc_param[1];
442
if ( curwin->scr_upper > curwin->scr_lower ) {
443
/* Reset scroll region */
445
curwin->scr_lower=curwin->rows;
450
vt_setscroll(curwin->scr_upper+curwin->row_offset,
451
curwin->scr_lower+curwin->row_offset);
452
vt_goto(curwin->cursor.x+curwin->row_offset, 1);
454
case 'A': /* Cursor UP */
455
if ( curwin->cursor.x == curwin->scr_upper )
457
if ( ! curwin->esc_param[0] )
458
curwin->esc_param[0]=1;
459
newx = (curwin->cursor.x - curwin->esc_param[0]);
460
if ( newx > curwin->scr_upper ) {
461
curwin->cursor.x=newx;
462
vt_up(curwin->esc_param[0]);
464
curwin->cursor.x=curwin->scr_upper;
465
vt_goto(curwin->cursor.x+curwin->row_offset,
469
case 'B': /* Cursor DOWN */
470
if ( curwin->cursor.x == curwin->scr_lower )
472
if ( ! curwin->esc_param[0] )
473
curwin->esc_param[0]=1;
474
newx = (curwin->cursor.x + curwin->esc_param[0]);
475
if ( newx <= curwin->scr_lower ) {
476
curwin->cursor.x=newx;
477
vt_down(curwin->esc_param[0]);
479
curwin->cursor.x=curwin->scr_lower;
480
vt_goto(curwin->cursor.x+curwin->row_offset,
484
case 'C': /* Cursor RIGHT */
485
if ( curwin->cursor.y == curwin->cols )
487
if ( ! curwin->esc_param[0] )
488
curwin->esc_param[0]=1;
489
newy = (curwin->cursor.y + curwin->esc_param[0]);
490
if ( newy < curwin->cols ) {
491
curwin->cursor.y=newy;
492
vt_right(curwin->esc_param[0]);
494
curwin->cursor.y=curwin->cols;
495
vt_goto(curwin->cursor.x+curwin->row_offset,
499
case 'D': /* Cursor LEFT */
500
if ( curwin->cursor.y == 1 )
502
if ( ! curwin->esc_param[0] )
503
curwin->esc_param[0]=1;
504
newy = (curwin->cursor.y - curwin->esc_param[0]);
506
curwin->cursor.y=newy;
507
vt_left(curwin->esc_param[0]);
514
case 'H': /* Move cursor to coordinates */
515
if ( ! curwin->esc_param[0] )
516
curwin->esc_param[0]=1;
517
if ( ! curwin->esc_param[1] )
518
curwin->esc_param[1]=1;
519
if ( (curwin->cursor.x=curwin->esc_param[0]) >
521
curwin->cursor.x=curwin->rows;
522
if ( (curwin->cursor.y=curwin->esc_param[1]) >
524
curwin->cursor.y=curwin->cols;
525
vt_goto(curwin->cursor.x+curwin->row_offset,
528
case 'g': /* Clear tabstops */
529
switch (curwin->esc_param[0]) {
530
case 0: /* Clear a tabstop */
531
curwin->tabstops[curwin->cursor.y-1]=0;
533
case 3: /* Clear all tabstops */
534
for (newy=0; newy<curwin->cols; ++newy)
535
curwin->tabstops[newy]=0;
540
case 'm': /* Set terminal attributes */
541
process_m(curwin, curwin->esc_param[0]);
542
for ( i=1; curwin->esc_param[i] && i<MAX_PARAMS; ++i )
543
process_m(curwin, curwin->esc_param[i]);
545
case 'J': /* Clear screen */
546
switch (curwin->esc_param[0]) {
547
case 0: /* Clear from cursor down */
549
curwin->cursor.x, curwin->rows,
551
newx=curwin->cursor.x;
554
while ( newx++ < curwin->rows ) {
561
case 1: /* Clear from cursor up */
565
newx=curwin->cursor.x;
568
while ( --newx > 0 ) {
575
case 2: /* Clear whole screen */
579
vt_goto(curwin->row_offset+1, 1);
582
newx=curwin->cursor.x;
585
while ( newx++ < curwin->rows ) {
595
case 'K': /* Clear line */
596
switch (curwin->esc_param[0]) {
597
case 0: /* Clear to end of line */
599
curwin->cursor.x, curwin->cursor.x,
600
curwin->cursor.y, curwin->cols);
603
case 1: /* Clear to beginning of line */
605
curwin->cursor.x, curwin->cursor.x,
606
1, curwin->cursor.y);
609
case 2: /* Clear whole line */
611
curwin->cursor.x, curwin->cursor.x,
617
case 'P': /* Delete under cursor */
619
curwin->cursor.x, curwin->cursor.x,
620
curwin->cursor.y, curwin->cursor.y);
621
vt_delunder(curwin->esc_param[0]);
623
case 'M': /* Delete lines */
624
revscroll_video(curwin, 1);
625
vt_delline(curwin->esc_param[0]);
627
case 'L': /* Insert lines */
628
vt_insline(curwin->esc_param[0]);
630
case '@': /* Insert characters */
631
if ( ! curwin->esc_param[0] )
632
curwin->esc_param[0] = 1;
633
vt_insertchar(curwin->esc_param[0]);
634
rshift_video(curwin, curwin->esc_param[0]);
636
case 'i': /* Printing (UNSUPPORTED) */
638
case 'n': /* Device status request */
639
switch (curwin->esc_param[0]) {
640
case 5: /* Status report request */
641
/* Say we're just fine. */
642
write(*source, "\033[0n", 4);
644
case 6: /* Cursor position request */
645
sprintf(reply, "\033[%d;%dR",
648
write(*source, reply, strlen(reply));
652
case 'c': /* Request terminal identification string */
653
/* Respond with "I am a vt102" */
654
write(*source, "\033[?6c", 5);
656
default: /* Unrecognized escape: ignore */
661
void E_brac_Q(c, source)
665
/* Check for numeric argument first */
667
*curwin->cur_param *= 10;
668
*curwin->cur_param += (c-'0');
672
/* Return inside the switch to prevent reset_esc() */
674
case '\030': /* Processed as escape cancel */
675
case '\032': reset_esc();
677
case 'h': /* Set modes */
678
switch (curwin->esc_param[0]) {
679
case 1: /* Cursorkeys in application mode */
680
curwin->key_state=application;
681
vt_keystate(curwin->key_state);
683
case 2: /* Set ansi mode */
686
case 3: /* 132 char/row */
687
if ( physical.cols != 132 ) {
694
case 4: /* Set jump scroll */
697
case 5: /* Set reverse screen */
700
case 6: /* Set relative coordinates */
703
case 7: /* Set auto wrap on */
706
case 8: /* Set auto repeat on */
709
case 25: /* Set cursor on */
712
case 47: /* Switch to alternate buffer */
713
/* UNSUPPORTED (xterm sequence) */
720
case 'l': /* Reset modes */
721
switch (curwin->esc_param[0]) {
722
case 1: /* Cursorkeys in normal mode */
723
curwin->key_state=normal;
724
vt_keystate(curwin->key_state);
726
case 2: /* Set VT52 mode */
729
case 3: /* 80 char/row */
730
if ( physical.cols == 132 ) {
731
vt_rows_cols(terminal_type,
732
NULL, &physical.cols);
733
upper.cols=physical.cols;
734
lower.cols=physical.cols;
738
case 4: /* Set smooth scroll */
741
case 5: /* Set non-reversed (normal) screen */
744
case 6: /* Set absolute coordinates */
747
case 7: /* Set auto wrap off */
750
case 8: /* Set auto repeat off */
753
case 25: /* Set cursor off */
756
case 47: /* Switch from alternate buffer */
757
/* UNSUPPORTED (xterm sequence) */
764
default: /* Unrecognized escape: ignore */
769
void E_lparen(c, source)
773
/* Return inside the switch to prevent reset_esc() */
775
case '\030': /* Processed as escape cancel */
776
case '\032': reset_esc();
778
/* Select character sets */
779
case 'A': /* UK as G0 */
780
curwin->charset[G0]=UK_CHARSET;
781
vt_altcharset(G0, UK_CHARSET);
783
case 'B': /* US as G0 */
784
curwin->charset[G0]=US_CHARSET;
785
vt_altcharset(G0, US_CHARSET);
787
case '0': /* Special character set as G0 */
788
curwin->charset[G0]=GRAPHICS;
789
vt_altcharset(G0, GRAPHICS);
791
case '1': /* Alternate ROM as G0 */
792
case '2': /* Alternate ROM special character set as G0 */
793
default: /* Unrecognized escape: ignore */
798
void E_rparen(c, source)
802
/* Return inside the switch to prevent reset_esc() */
804
case '\030': /* Processed as escape cancel */
805
case '\032': reset_esc();
807
/* Select character sets */
808
case 'A': /* UK as G1 */
809
curwin->charset[G1]=UK_CHARSET;
810
vt_altcharset(G1, UK_CHARSET);
812
case 'B': /* US as G1 */
813
curwin->charset[G1]=US_CHARSET;
814
vt_altcharset(G1, US_CHARSET);
816
case '0': /* Special character set as G1 */
817
curwin->charset[G1]=GRAPHICS;
818
vt_altcharset(G1, GRAPHICS);
819
case '1': /* Alternate ROM as G1 */
820
case '2': /* Alternate ROM special character set as G1 */
821
default: /* Unrecognized escape: ignore */
826
void E_pound(c, source)
830
switch (c) { /* Line attributes not supported */
831
case '3': /* Double height (top half) */
832
case '4': /* Double height (bottom half) */
833
case '5': /* Single width, single height */
834
case '6': /* Double width */
841
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
843
/* Routine to initialize the vt100 screening, returning an error message,
844
or NULL if all went well. */
846
static int setup_vt100 = 0; /* Have we initialized the vt100 system? */
851
struct /* winsize */ {
852
unsigned short ws_row; /* rows, in characters */
853
unsigned short ws_col; /* columns, in characters */
854
unsigned short ws_xpixel; /* horizontal size - not used */
855
unsigned short ws_ypixel; /* vertical size - not used */
858
int i, **videomem, oldrows, newrows, newcols;
862
/* Check to make sure it's okay to run */
863
if ( ! isatty(0) || ! isatty(1) )
864
return("Standard input and output must be a tty");
866
/* Initialize the termcap environment */
867
if ( ! setup_vt100 ) {
868
if ( (errmesg=vt_initterm(terminal_type,
869
&physical.rows, &physical.cols)) != NULL )
875
if ( ioctl(0, TIOCGWINSZ, &mywinz) == 0 ) {
877
physical.rows=mywinz.ws_row;
879
physical.cols=mywinz.ws_col;
882
if ( (ptr=(char *)getenv("LINES")) != NULL )
883
physical.rows=atoi(ptr);
884
if ( (ptr=(char *)getenv("COLUMNS")) != NULL )
885
physical.cols=atoi(ptr);
887
/* Now set defaults if we can't find the window size */
888
if ( ! physical.rows ) physical.rows=24;
889
if ( ! physical.cols ) physical.cols=80;
890
physical.subwins[UPPER] = &upper;
891
physical.subwins[LOWER] = &lower;
893
/* Check that each window is at least 3 lines tall */
894
if ( physical.rows < 7 )
895
return("Screen is not tall enough to split.");
897
/* If physical.cols has been set to 132, assume we are on a
898
vt100 wide terminal, and set 132 column mode. Note that
899
setting COLUMNS in the environment will override termcap */
900
if ( physical.cols == 132 )
903
/* Set the exportable variables */
905
/* Check the user set # of lines */
906
if ( UU_lines > (physical.rows-1-3) )
907
LU_lines=(physical.rows-1-3);
908
else if ( UU_lines < 3 )
914
WL_lines=(physical.rows-1-LU_lines);
916
WL_lines=WU_lines=((physical.rows-1)/2);
917
W_columns=physical.cols;
919
/* Set up the window structures */
920
newcols=physical.cols;
922
if ( (videomem=alloc_video(newrows, newcols)) == NULL )
923
return("Out of memory");
926
copy_video(&upper, videomem, newrows, newcols, &newpos);
927
for ( i=0; i<upper.rows; ++i )
928
(void) free(upper.videomem[i]);
929
(void) free(upper.videomem);
930
(void) free(upper.tabstops);
932
if ( (upper.tabstops=(int *)malloc(newcols*sizeof(int))) == NULL )
933
return("Out of memory");
934
for ( i=0; i<newcols; ++i ) {
935
if ( (i%TABSTOP) == 0 )
940
upper.videomem=videomem;
941
upper.cols=physical.cols;
945
if ( upper.scr_lower == oldrows )
946
upper.scr_lower=newrows;
952
if ( (videomem=alloc_video(newrows, newcols)) == NULL )
953
return("Out of memory");
956
copy_video(&lower, videomem, newrows, newcols, &newpos);
957
for ( i=0; i<lower.rows; ++i )
958
(void) free(lower.videomem[i]);
959
(void) free(lower.videomem);
960
(void) free(lower.tabstops);
962
if ( (lower.tabstops=(int *)malloc(newcols*sizeof(int))) == NULL )
963
return("Out of memory");
964
for ( i=0; i<newcols; ++i ) {
965
if ( (i%TABSTOP) == 0 )
970
lower.videomem=videomem;
971
lower.cols=physical.cols;
973
lower.row_offset=(upper.rows+1);
975
if ( lower.scr_lower == oldrows )
976
lower.scr_lower=newrows;
982
/* Set up the separator (cols-1) */
985
if ( (sep=(char *)malloc(physical.cols+1)) == NULL )
986
return("Out of memory");
987
for ( i=0; i<(physical.cols-1); ++i )
991
/* Clear the screen, and set up the windows */
992
if ( ! setup_vt100 ) {
995
vt_goto((WU_lines+1), 1); /* Move past the top win */
997
printf("%s", sep); /* Print separator */
1004
++setup_vt100; /* Set setup_vt100 flag */
1008
int vt_write(win, data, len, source)
1009
int win; /* The window; 0 if top, 1 if bottom */
1010
char *data; /* The data to write */
1011
int len; /* The amount of data to write */
1012
int *source; /* File descriptor through which to reply to Esc-Z */
1016
/* First set the proper window */
1019
/* Now cycle through the input */
1020
for ( i=0; i<len; ++i )
1021
(*curwin->process_char)((int)*(data++), source);
1026
/* Print out a prompt on the screen, get a character in response, and
1027
return it. (Assume a one line prompt)
1030
char vt_prompt(prompt)
1033
char format[BUFSIZ], buff[1];
1035
/* Save cursor position, go home, clear line and print prompt */
1039
vt_goto(WU_lines+1, 0);
1041
sprintf(format, "%%.%ds", physical.cols);
1043
printf(format, prompt);
1047
/* Read the response */
1048
if ( read(0, buff, 1) <= 0 )
1051
/* Print out the top separator and go back to where we were */
1055
printf("\r%s", sep);
1064
/* Print out information at the bottom of the screen */
1071
/* Save cursor, go to info bar, clear it */
1074
vt_goto(WU_lines+1, 0);
1078
sprintf(format, "%%.%ds", physical.cols);
1080
printf(format, info);
1082
else { /* Get rid of the info message */
1084
printf("\r%s", sep);
1087
/* Then go back where we were supposed to be and update it */
1093
/* Repaint both of the screens */
1096
/* We need to paint current window last so scrolling works */
1098
paint_video(lastwin == UPPER ? &lower : &upper);
1099
vt_goto(WU_lines+1, 0);
1102
paint_video(lastwin == UPPER ? &upper : &lower);
1106
/* Show a (help) screen, wait, then refresh the screen */
1107
void vt_showscreen(title, text)
1117
printf("%s\r\n\r\n", title);
1119
for ( i=0; text[i]; ++i )
1120
printf("%s\r\n", text[i]);
1123
printf("Press any key to continue: ");
1130
/* Clean up the screen and clear the scrolling regions */
1135
if ( ! setup_vt100 )
1138
/* Clear any old setup */
1140
for ( i=0; i<upper.rows; ++i )
1141
(void) free(upper.videomem[i]);
1142
(void) free(upper.videomem);
1143
(void) free(upper.tabstops);
1144
for ( i=0; i<lower.rows; ++i )
1145
(void) free(lower.videomem[i]);
1146
(void) free(lower.videomem);
1147
(void) free(lower.tabstops);
1150
/* Fix up the display */
1152
vt_goto(physical.rows, 1);