148757Sbostic /*-
2*62343Sbostic * Copyright (c) 1988, 1993
3*62343Sbostic * The Regents of the University of California. All rights reserved.
431105Sminshall *
548757Sbostic * %sccs.include.redist.c%
631105Sminshall */
731105Sminshall
831105Sminshall #ifndef lint
9*62343Sbostic static char sccsid[] = "@(#)termout.c 8.1 (Berkeley) 06/06/93";
1033814Sbostic #endif /* not lint */
1131105Sminshall
1231105Sminshall #include <stdio.h>
1331120Sminshall #include <dos.h>
1431185Sminshall #include "../general/general.h"
1531105Sminshall
1631105Sminshall #include "../telnet.ext"
1731105Sminshall
1831881Sminshall #include "../api/disp_asc.h"
1931225Sminshall #include "../ascii/map3270.ext"
2031225Sminshall
2131105Sminshall #include "../ctlr/hostctlr.h"
2235424Sminshall #include "../ctlr/externs.h"
2335424Sminshall #include "../ctlr/declare.h"
2431117Sminshall #include "../ctlr/oia.h"
2531105Sminshall #include "../ctlr/screen.h"
2631105Sminshall
2731185Sminshall #include "../general/globals.h"
2831105Sminshall
2931120Sminshall #include "video.h"
3031120Sminshall
3131105Sminshall extern void EmptyTerminal();
3231105Sminshall
3331105Sminshall #define CorrectTerminalCursor() ((TransparentClock == OutputClock)? \
3431105Sminshall terminalCursorAddress:UnLocked? CursorAddress: HighestScreen())
3531105Sminshall
3631105Sminshall
3731105Sminshall static int terminalCursorAddress; /* where the cursor is on term */
3831105Sminshall static int screenInitd; /* the screen has been initialized */
3931105Sminshall static int screenStopped; /* the screen has been stopped */
4031105Sminshall
4131105Sminshall static int needToRing; /* need to ring terinal bell */
4231105Sminshall
4331117Sminshall typedef struct {
4431117Sminshall char
4531117Sminshall data, /* The data for this position */
4631117Sminshall attr; /* The attributes for this position */
4731117Sminshall } ScreenBuffer;
4831105Sminshall
4931117Sminshall ScreenBuffer Screen[MAXNUMBERLINES*MAXNUMBERCOLUMNS];
5031120Sminshall ScreenBuffer saveScreen[sizeof Screen/sizeof Screen[0]];
5131105Sminshall
5231105Sminshall /* OurExitString - designed to keep us from going through infinite recursion */
5331105Sminshall
5431105Sminshall static void
OurExitString(file,string,value)5531105Sminshall OurExitString(file, string, value)
5631105Sminshall FILE *file;
5731105Sminshall char *string;
5831105Sminshall int value;
5931105Sminshall {
6031105Sminshall static int recursion = 0;
6131105Sminshall
6231105Sminshall if (!recursion) {
6331105Sminshall recursion = 1;
6431105Sminshall ExitString(file, string, value);
6531105Sminshall }
6631105Sminshall }
6731105Sminshall
6831105Sminshall
6931105Sminshall static void
GoAway(from,where)7031105Sminshall GoAway(from, where)
7131105Sminshall char *from; /* routine that gave error */
7231105Sminshall int where; /* cursor address */
7331105Sminshall {
7431105Sminshall char foo[100];
7531105Sminshall
7631105Sminshall sprintf(foo, "ERR from %s at %d (%d, %d)\n",
7731105Sminshall from, where, ScreenLine(where), ScreenLineOffset(where));
7831105Sminshall OurExitString(stderr, foo, 1);
7931105Sminshall /* NOTREACHED */
8031105Sminshall }
8131105Sminshall
8231120Sminshall /*
8331120Sminshall * Routines to deal with the screen. These routines are lifted
8431120Sminshall * from mskermit.
8531120Sminshall */
8631120Sminshall
8731120Sminshall #define CRT_STATUS 0x3da /* Color card */
8831120Sminshall #define DISPLAY_ENABLE 0x08 /* Enable */
8931120Sminshall #define scrseg() ((crt_mode == 7)? 0xb000 : 0xb800)
9031120Sminshall #define scrwait() if (crt_mode != 7) { \
9131120Sminshall while ((inp(CRT_STATUS)&DISPLAY_ENABLE) == 0) { \
9231120Sminshall ; \
9331120Sminshall } \
9431120Sminshall }
9531120Sminshall static int
9631120Sminshall crt_mode,
9731120Sminshall crt_cols,
9831120Sminshall crt_lins,
9931120Sminshall curpage;
10031120Sminshall
10131120Sminshall /*
10231120Sminshall * Set the cursor position to where it belongs.
10331120Sminshall */
10431120Sminshall
10531105Sminshall static void
setcursor(row,column,page)10631120Sminshall setcursor(row, column, page)
10731120Sminshall int
10831120Sminshall row,
10931120Sminshall column,
11031120Sminshall page;
11131120Sminshall {
11231120Sminshall union REGS inregs, outregs;
11331120Sminshall
11431120Sminshall inregs.h.dh = row;
11531120Sminshall inregs.h.dl = column;
11631120Sminshall inregs.h.bh = page;
11731120Sminshall inregs.h.ah = SetCursorPosition;
11831120Sminshall
11931120Sminshall int86(BIOS_VIDEO, &inregs, &outregs);
12031120Sminshall }
12131120Sminshall /*
12231120Sminshall * Read the state of the video system. Put the cursor somewhere
12331120Sminshall * reasonable.
12431120Sminshall */
12531120Sminshall
12631120Sminshall static void
scrini()12731120Sminshall scrini()
12831120Sminshall {
12931120Sminshall union REGS inregs, outregs;
13031120Sminshall
13131120Sminshall inregs.h.ah = CurrentVideoState;
13231120Sminshall int86(BIOS_VIDEO, &inregs, &outregs);
13331120Sminshall
13431120Sminshall crt_mode = outregs.h.al;
13531120Sminshall crt_cols = outregs.h.ah;
13631120Sminshall crt_lins = 25;
13731120Sminshall curpage = outregs.h.bh;
13831120Sminshall
13931120Sminshall inregs.h.ah = ReadCursorPosition;
14031120Sminshall inregs.h.bh = curpage;
14131120Sminshall
14231120Sminshall int86(BIOS_VIDEO, &inregs, &outregs);
14331120Sminshall
14431120Sminshall if (outregs.h.dh > crt_lins) {
14531120Sminshall outregs.h.dh = crt_lins;
14631120Sminshall }
14731120Sminshall if (outregs.h.dl > crt_cols) {
14831120Sminshall outregs.h.dl = crt_cols;
14931120Sminshall }
15031120Sminshall inregs.h.dh = outregs.h.dh;
15131120Sminshall inregs.h.dl = outregs.h.dl;
15231120Sminshall inregs.h.bh = curpage;
15331120Sminshall
15431120Sminshall inregs.h.ah = SetCursorPosition;
15531120Sminshall int86(BIOS_VIDEO, &inregs, &outregs);
15631120Sminshall }
15731120Sminshall
15831120Sminshall
15931120Sminshall static void
scrwrite(source,length,offset)16031120Sminshall scrwrite(source, length, offset)
16131120Sminshall ScreenBuffer *source;
16231120Sminshall int
16331120Sminshall length,
16431120Sminshall offset;
16531120Sminshall {
16631120Sminshall struct SREGS segregs;
16731120Sminshall
16831120Sminshall segread(&segregs); /* read the current segment register */
16931120Sminshall
17031120Sminshall scrwait();
17131154Sminshall movedata(segregs.ds, source, scrseg(), sizeof *source*offset,
17231154Sminshall sizeof *source*length);
17331120Sminshall }
17431120Sminshall
17531120Sminshall static void
scrsave(buffer)17631120Sminshall scrsave(buffer)
17731120Sminshall ScreenBuffer *buffer;
17831120Sminshall {
17931120Sminshall struct SREGS segregs;
18031120Sminshall
18131120Sminshall segread(&segregs); /* read the current segment register */
18231120Sminshall
18331120Sminshall scrwait();
18431154Sminshall movedata(scrseg(), 0, segregs.ds, buffer, crt_cols*crt_lins*2);
18531120Sminshall }
18631120Sminshall
18731120Sminshall static void
scrrest(buffer)18831120Sminshall scrrest(buffer)
18931120Sminshall ScreenBuffer *buffer;
19031120Sminshall {
19131154Sminshall scrwrite(buffer, crt_cols*crt_lins, 0);
19231120Sminshall }
19331120Sminshall
19431120Sminshall static void
TryToSend()19531117Sminshall TryToSend()
19631105Sminshall {
19731154Sminshall #define STANDOUT 0x0a /* Highlighted mode */
19831117Sminshall #define NORMAL 0x02 /* Normal mode */
19931154Sminshall #define NONDISPLAY 0x00 /* Don't display */
20031105Sminshall
20131154Sminshall #define DoAttribute(a) \
20231154Sminshall if (screenIsFormatted) { \
20331154Sminshall if (IsNonDisplayAttr(a)) { \
20431154Sminshall a = NONDISPLAY; /* don't display */ \
20531154Sminshall } else if (IsHighlightedAttr(a)) { \
20631154Sminshall a = STANDOUT; \
20731154Sminshall } else { \
20831154Sminshall a = NORMAL; \
20931154Sminshall } \
21031154Sminshall } else { \
21131154Sminshall a = NORMAL; /* do display on unformatted */\
21231105Sminshall }
21331105Sminshall ScreenImage *p, *upper;
21431117Sminshall ScreenBuffer *sp;
21531105Sminshall int fieldattr; /* spends most of its time == 0 or 1 */
21631154Sminshall int screenIsFormatted = FormattedScreen();
21731105Sminshall
21831105Sminshall /* OK. We want to do this a quickly as possible. So, we assume we
21931105Sminshall * only need to go from Lowest to Highest. However, if we find a
22031105Sminshall * field in the middle, we do the whole screen.
22131105Sminshall *
22231105Sminshall * In particular, we separate out the two cases from the beginning.
22331105Sminshall */
22431105Sminshall if ((Highest != HighestScreen()) || (Lowest != LowestScreen())) {
22531117Sminshall sp = &Screen[Lowest];
22631105Sminshall p = &Host[Lowest];
22731105Sminshall upper = &Host[Highest];
22831105Sminshall fieldattr = FieldAttributes(Lowest);
22931105Sminshall DoAttribute(fieldattr); /* Set standout, non-display status */
23031105Sminshall
23131105Sminshall while (p <= upper) {
23231105Sminshall if (IsStartFieldPointer(p)) { /* New field? */
23331105Sminshall Highest = HighestScreen();
23431105Sminshall Lowest = LowestScreen();
23531117Sminshall TryToSend(); /* Recurse */
23631105Sminshall return;
23731105Sminshall } else if (fieldattr) { /* Should we display? */
23831154Sminshall /* Display translated data */
23931154Sminshall sp->data = disp_asc[GetHostPointer(p)];
24031105Sminshall } else {
24131117Sminshall sp->data = ' ';
24231105Sminshall }
24331154Sminshall sp->attr = fieldattr;
24431105Sminshall p++;
24531117Sminshall sp++;
24631105Sminshall }
24731105Sminshall } else { /* Going from Lowest to Highest */
24831117Sminshall ScreenImage *End = &Host[ScreenSize]-1;
24931105Sminshall
25031117Sminshall sp = Screen;
25131105Sminshall p = Host;
25231105Sminshall fieldattr = FieldAttributes(LowestScreen());
25331105Sminshall DoAttribute(fieldattr); /* Set standout, non-display status */
25431105Sminshall
25531105Sminshall while (p <= End) {
25631105Sminshall if (IsStartFieldPointer(p)) { /* New field? */
25731105Sminshall fieldattr = FieldAttributesPointer(p); /* Get attributes */
25831105Sminshall DoAttribute(fieldattr); /* Set standout, non-display */
25931154Sminshall }
26031154Sminshall if (fieldattr) { /* Should we display? */
26131154Sminshall /* Display translated data */
26231154Sminshall sp->data = disp_asc[GetHostPointer(p)];
26331105Sminshall } else {
26431154Sminshall sp->data = ' ';
26531105Sminshall }
26631154Sminshall sp->attr = fieldattr;
26731105Sminshall p++;
26831117Sminshall sp++;
26931105Sminshall }
27031105Sminshall }
27131117Sminshall terminalCursorAddress = CorrectTerminalCursor();
27231154Sminshall /*
27331154Sminshall * We might be here just to update the cursor address.
27431154Sminshall */
27531154Sminshall if (Highest >= Lowest) {
27631154Sminshall scrwrite(Screen+Lowest, (1+Highest-Lowest), Lowest);
27731154Sminshall }
27831120Sminshall setcursor(ScreenLine(terminalCursorAddress),
27931117Sminshall ScreenLineOffset(terminalCursorAddress), 0);
28031105Sminshall Lowest = HighestScreen()+1;
28131105Sminshall Highest = LowestScreen()-1;
28231105Sminshall if (needToRing) {
28331117Sminshall DataToTerminal("\7", 1);
28431105Sminshall needToRing = 0;
28531105Sminshall }
28631105Sminshall return;
28731105Sminshall }
28831105Sminshall
28931105Sminshall /* InitTerminal - called to initialize the screen, etc. */
29031105Sminshall
29131105Sminshall void
InitTerminal()29231105Sminshall InitTerminal()
29331105Sminshall {
29431105Sminshall InitMapping(); /* Go do mapping file (MAP3270) first */
29531105Sminshall if (!screenInitd) { /* not initialized */
29631129Sminshall MaxNumberLines = 24; /* XXX */
29731129Sminshall MaxNumberColumns = 80; /* XXX */
29831117Sminshall scrini();
29931120Sminshall scrsave(saveScreen); /* Save the screen buffer away */
30031117Sminshall ClearArray(Screen);
30131105Sminshall terminalCursorAddress = SetBufferAddress(0,0);
30231105Sminshall screenInitd = 1;
30331105Sminshall screenStopped = 0; /* Not stopped */
30431105Sminshall }
30531105Sminshall }
30631105Sminshall
30731105Sminshall
30831105Sminshall /* StopScreen - called when we are going away... */
30931105Sminshall
31031105Sminshall void
StopScreen(doNewLine)31131105Sminshall StopScreen(doNewLine)
31231105Sminshall int doNewLine;
31331105Sminshall {
31431105Sminshall if (screenInitd && !screenStopped) {
31531120Sminshall scrrest(saveScreen);
31631208Sminshall setcursor(NumberLines-1, 1, 0);
31731208Sminshall if (doNewLine) {
31831208Sminshall StringToTerminal("\r\n");
31931208Sminshall }
32031208Sminshall EmptyTerminal();
32131208Sminshall screenStopped = 1;
32231105Sminshall }
32331105Sminshall }
32431105Sminshall
32531105Sminshall
32631105Sminshall /* RefreshScreen - called to cause the screen to be refreshed */
32731105Sminshall
32831105Sminshall void
RefreshScreen()32931105Sminshall RefreshScreen()
33031105Sminshall {
33131117Sminshall Highest = HighestScreen();
33231117Sminshall Lowest = LowestScreen();
33331117Sminshall TryToSend();
33431105Sminshall }
33531105Sminshall
33631105Sminshall
33731105Sminshall /* ConnectScreen - called to reconnect to the screen */
33831105Sminshall
33931105Sminshall void
ConnectScreen()34031105Sminshall ConnectScreen()
34131105Sminshall {
34231105Sminshall if (screenInitd) {
34331105Sminshall RefreshScreen();
34431105Sminshall screenStopped = 0;
34531105Sminshall }
34631105Sminshall }
34731105Sminshall
34831105Sminshall /* LocalClearScreen() - clear the whole ball of wax, cheaply */
34931105Sminshall
35031105Sminshall void
LocalClearScreen()35131105Sminshall LocalClearScreen()
35231105Sminshall {
35331105Sminshall Clear3270();
35431117Sminshall Lowest = LowestScreen(); /* everything in sync... */
35531117Sminshall Highest = HighestScreen();
35631117Sminshall TryToSend();
35731105Sminshall }
35831117Sminshall
35931117Sminshall /*
36031117Sminshall * Implement the bell/error message function.
36131117Sminshall */
36231105Sminshall
36331117Sminshall int
36431117Sminshall bellwinup = 0; /* If != 0, length of bell message */
36531117Sminshall static int
36631883Sminshall bell_len = 0; /* Length of error message */
36731105Sminshall
36831117Sminshall
36931105Sminshall void
BellOff()37031105Sminshall BellOff()
37131105Sminshall {
37231883Sminshall ScreenBuffer a[100];
37331883Sminshall int i;
37431883Sminshall
37531105Sminshall if (bellwinup) {
37631883Sminshall unsigned char blank = ' ';
37731883Sminshall
37831883Sminshall for (i = 0; i < bell_len; i++) {
37931883Sminshall a[i].attr = NORMAL;
38031883Sminshall a[i].data = ' ';
38131883Sminshall }
38231105Sminshall }
38331883Sminshall scrwrite(a, bell_len, 24*80); /* XXX */
38431105Sminshall }
38531105Sminshall
38631105Sminshall
38731105Sminshall void
RingBell(s)38831105Sminshall RingBell(s)
38931105Sminshall char *s;
39031105Sminshall {
39131105Sminshall needToRing = 1;
39231105Sminshall if (s) {
39331883Sminshall int i;
39431883Sminshall ScreenBuffer bellstring[100];
39531105Sminshall
39631883Sminshall bell_len = strlen(s);
39731883Sminshall bellwinup = 1;
39831883Sminshall if (bell_len > sizeof bellstring-1) {
39931117Sminshall OurExitString(stderr, "Bell string too long.", 1);
40031105Sminshall }
40131883Sminshall for (i = 0; i < bell_len; i++) {
40231883Sminshall bellstring[i].attr = STANDOUT;
40331883Sminshall bellstring[i].data = s[i];
40431883Sminshall }
40531883Sminshall scrwrite(bellstring, bell_len, 24*80); /* XXX */
40631105Sminshall }
40731105Sminshall }
40831105Sminshall
40931117Sminshall /*
41031117Sminshall * Update the OIA area.
41131117Sminshall */
41231105Sminshall
41331117Sminshall void
ScreenOIA(oia)41431117Sminshall ScreenOIA(oia)
41531117Sminshall OIA *oia;
41631117Sminshall {
41731117Sminshall }
41831117Sminshall
41931117Sminshall
42031105Sminshall /* returns a 1 if no more output available (so, go ahead and block),
42131105Sminshall or a 0 if there is more output available (so, just poll the other
42231105Sminshall sources/destinations, don't block).
42331105Sminshall */
42431105Sminshall
42531105Sminshall int
DoTerminalOutput()42631105Sminshall DoTerminalOutput()
42731105Sminshall {
42831105Sminshall /* called just before a select to conserve IO to terminal */
42931490Sminshall if (!(screenInitd||screenStopped)) {
43031105Sminshall return 1; /* No output if not initialized */
43131105Sminshall }
43231105Sminshall if ((Lowest <= Highest) || needToRing ||
43331105Sminshall (terminalCursorAddress != CorrectTerminalCursor())) {
43431117Sminshall TryToSend();
43531105Sminshall }
43631105Sminshall if (Lowest > Highest) {
43731105Sminshall return 1; /* no more output now */
43831105Sminshall } else {
43931105Sminshall return 0; /* more output for future */
44031105Sminshall }
44131105Sminshall }
44231105Sminshall
44331105Sminshall /*
44431105Sminshall * The following are defined to handle transparent data.
44531105Sminshall */
44631105Sminshall
44731105Sminshall void
TransStop()44831105Sminshall TransStop()
44931105Sminshall {
45031105Sminshall RefreshScreen();
45131105Sminshall }
45231105Sminshall
45331105Sminshall void
TransOut(buffer,count,kind,control)45431885Sminshall TransOut(buffer, count, kind, control)
45531105Sminshall unsigned char *buffer;
45631105Sminshall int count;
45731885Sminshall int kind; /* 0 or 5 */
45831885Sminshall int control; /* To see if we are done */
45931105Sminshall {
46031885Sminshall char *ptr;
46131105Sminshall
46231105Sminshall while (DoTerminalOutput() == 0) {
46331117Sminshall ;
46431105Sminshall }
46531885Sminshall for (ptr = buffer; ptr < buffer+count; ptr++) {
46631885Sminshall *ptr &= 0x7f; /* Turn off parity bit */
46731885Sminshall }
46831105Sminshall (void) DataToTerminal(buffer, count);
46931885Sminshall if (control && (kind == 0)) { /* Send in AID byte */
47031885Sminshall SendToIBM();
47131885Sminshall } else {
47231885Sminshall TransInput(1, kind); /* Go get some data */
47331885Sminshall }
47431105Sminshall }
47531117Sminshall
47631117Sminshall /*
47731117Sminshall * init_screen()
47831117Sminshall *
47931117Sminshall * Initialize variables used by screen.
48031117Sminshall */
48131105Sminshall
48231117Sminshall void
init_screen()48331117Sminshall init_screen()
48431105Sminshall {
48531117Sminshall bellwinup = 0;
48631117Sminshall }
48731105Sminshall
48831117Sminshall
489