* Copyright (c) 1988 Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
static char sccsid
[] = "@(#)termout.c 4.1 (Berkeley) 12/4/88";
#include "../general/general.h"
#include "../api/disp_asc.h"
#include "../ascii/map3270.ext"
#include "../ctlr/hostctlr.h"
#include "../ctlr/externs.h"
#include "../ctlr/declare.h"
#include "../ctlr/screen.h"
#include "../general/globals.h"
extern void EmptyTerminal();
#define CorrectTerminalCursor() ((TransparentClock == OutputClock)? \
terminalCursorAddress:UnLocked? CursorAddress: HighestScreen())
static int terminalCursorAddress
; /* where the cursor is on term */
static int screenInitd
; /* the screen has been initialized */
static int screenStopped
; /* the screen has been stopped */
static int needToRing
; /* need to ring terinal bell */
data
, /* The data for this position */
attr
; /* The attributes for this position */
ScreenBuffer Screen
[MAXNUMBERLINES
*MAXNUMBERCOLUMNS
];
ScreenBuffer saveScreen
[sizeof Screen
/sizeof Screen
[0]];
/* OurExitString - designed to keep us from going through infinite recursion */
OurExitString(file
, string
, value
)
static int recursion
= 0;
ExitString(file
, string
, value
);
char *from
; /* routine that gave error */
int where
; /* cursor address */
sprintf(foo
, "ERR from %s at %d (%d, %d)\n",
from
, where
, ScreenLine(where
), ScreenLineOffset(where
));
OurExitString(stderr
, foo
, 1);
* Routines to deal with the screen. These routines are lifted
#define CRT_STATUS 0x3da /* Color card */
#define DISPLAY_ENABLE 0x08 /* Enable */
#define scrseg() ((crt_mode == 7)? 0xb000 : 0xb800)
#define scrwait() if (crt_mode != 7) { \
while ((inp(CRT_STATUS)&DISPLAY_ENABLE) == 0) { \
* Set the cursor position to where it belongs.
setcursor(row
, column
, page
)
union REGS inregs
, outregs
;
inregs
.h
.ah
= SetCursorPosition
;
int86(BIOS_VIDEO
, &inregs
, &outregs
);
* Read the state of the video system. Put the cursor somewhere
union REGS inregs
, outregs
;
inregs
.h
.ah
= CurrentVideoState
;
int86(BIOS_VIDEO
, &inregs
, &outregs
);
inregs
.h
.ah
= ReadCursorPosition
;
int86(BIOS_VIDEO
, &inregs
, &outregs
);
if (outregs
.h
.dh
> crt_lins
) {
if (outregs
.h
.dl
> crt_cols
) {
inregs
.h
.dh
= outregs
.h
.dh
;
inregs
.h
.dl
= outregs
.h
.dl
;
inregs
.h
.ah
= SetCursorPosition
;
int86(BIOS_VIDEO
, &inregs
, &outregs
);
scrwrite(source
, length
, offset
)
segread(&segregs
); /* read the current segment register */
movedata(segregs
.ds
, source
, scrseg(), sizeof *source
*offset
,
segread(&segregs
); /* read the current segment register */
movedata(scrseg(), 0, segregs
.ds
, buffer
, crt_cols
*crt_lins
*2);
scrwrite(buffer
, crt_cols
*crt_lins
, 0);
#define STANDOUT 0x0a /* Highlighted mode */
#define NORMAL 0x02 /* Normal mode */
#define NONDISPLAY 0x00 /* Don't display */
if (screenIsFormatted) { \
if (IsNonDisplayAttr(a)) { \
a = NONDISPLAY; /* don't display */ \
} else if (IsHighlightedAttr(a)) { \
a = NORMAL; /* do display on unformatted */\
int fieldattr
; /* spends most of its time == 0 or 1 */
int screenIsFormatted
= FormattedScreen();
/* OK. We want to do this a quickly as possible. So, we assume we
* only need to go from Lowest to Highest. However, if we find a
* field in the middle, we do the whole screen.
* In particular, we separate out the two cases from the beginning.
if ((Highest
!= HighestScreen()) || (Lowest
!= LowestScreen())) {
fieldattr
= FieldAttributes(Lowest
);
DoAttribute(fieldattr
); /* Set standout, non-display status */
if (IsStartFieldPointer(p
)) { /* New field? */
Highest
= HighestScreen();
TryToSend(); /* Recurse */
} else if (fieldattr
) { /* Should we display? */
/* Display translated data */
sp
->data
= disp_asc
[GetHostPointer(p
)];
} else { /* Going from Lowest to Highest */
ScreenImage
*End
= &Host
[ScreenSize
]-1;
fieldattr
= FieldAttributes(LowestScreen());
DoAttribute(fieldattr
); /* Set standout, non-display status */
if (IsStartFieldPointer(p
)) { /* New field? */
fieldattr
= FieldAttributesPointer(p
); /* Get attributes */
DoAttribute(fieldattr
); /* Set standout, non-display */
if (fieldattr
) { /* Should we display? */
/* Display translated data */
sp
->data
= disp_asc
[GetHostPointer(p
)];
terminalCursorAddress
= CorrectTerminalCursor();
* We might be here just to update the cursor address.
scrwrite(Screen
+Lowest
, (1+Highest
-Lowest
), Lowest
);
setcursor(ScreenLine(terminalCursorAddress
),
ScreenLineOffset(terminalCursorAddress
), 0);
Lowest
= HighestScreen()+1;
Highest
= LowestScreen()-1;
/* InitTerminal - called to initialize the screen, etc. */
InitMapping(); /* Go do mapping file (MAP3270) first */
if (!screenInitd
) { /* not initialized */
MaxNumberLines
= 24; /* XXX */
MaxNumberColumns
= 80; /* XXX */
scrsave(saveScreen
); /* Save the screen buffer away */
terminalCursorAddress
= SetBufferAddress(0,0);
screenStopped
= 0; /* Not stopped */
/* StopScreen - called when we are going away... */
if (screenInitd
&& !screenStopped
) {
setcursor(NumberLines
-1, 1, 0);
StringToTerminal("\r\n");
/* RefreshScreen - called to cause the screen to be refreshed */
Highest
= HighestScreen();
/* ConnectScreen - called to reconnect to the screen */
/* LocalClearScreen() - clear the whole ball of wax, cheaply */
Lowest
= LowestScreen(); /* everything in sync... */
Highest
= HighestScreen();
* Implement the bell/error message function.
bellwinup
= 0; /* If != 0, length of bell message */
bell_len
= 0; /* Length of error message */
unsigned char blank
= ' ';
for (i
= 0; i
< bell_len
; i
++) {
scrwrite(a
, bell_len
, 24*80); /* XXX */
ScreenBuffer bellstring
[100];
if (bell_len
> sizeof bellstring
-1) {
OurExitString(stderr
, "Bell string too long.", 1);
for (i
= 0; i
< bell_len
; i
++) {
bellstring
[i
].attr
= STANDOUT
;
bellstring
[i
].data
= s
[i
];
scrwrite(bellstring
, bell_len
, 24*80); /* XXX */
/* returns a 1 if no more output available (so, go ahead and block),
or a 0 if there is more output available (so, just poll the other
sources/destinations, don't block).
/* called just before a select to conserve IO to terminal */
if (!(screenInitd
||screenStopped
)) {
return 1; /* No output if not initialized */
if ((Lowest
<= Highest
) || needToRing
||
(terminalCursorAddress
!= CorrectTerminalCursor())) {
return 1; /* no more output now */
return 0; /* more output for future */
* The following are defined to handle transparent data.
TransOut(buffer
, count
, kind
, control
)
int control
; /* To see if we are done */
while (DoTerminalOutput() == 0) {
for (ptr
= buffer
; ptr
< buffer
+count
; ptr
++) {
*ptr
&= 0x7f; /* Turn off parity bit */
(void) DataToTerminal(buffer
, count
);
if (control
&& (kind
== 0)) { /* Send in AID byte */
TransInput(1, kind
); /* Go get some data */
* Initialize variables used by screen.