* Copyright (c) 1984, 1985, 1986 by the Regents of the
* University of California and by Gregory Glenn Minshall.
* Permission to use, copy, modify, and distribute these
* programs and their documentation for any purpose and
* without fee is hereby granted, provided that this
* copyright and permission appear on all copies and
* supporting documentation, the name of the Regents of
* the University of California not be used in advertising
* or publicity pertaining to distribution of the programs
* without specific prior permission, and notice be given in
* supporting documentation that copying and distribution is
* by permission of the Regents of the University of California
* and by Gregory Glenn Minshall. Neither the Regents of the
* University of California nor Gregory Glenn Minshall make
* representations about the suitability of this software
* for any purpose. It is provided "as is" without
* express or implied warranty.
static char sccsid
[] = "@(#)inbound.c 3.1 10/29/86";
#include "../system/globals.h"
#define EmptyChar() (ourPTail == ourPHead)
#define FullChar() (ourPHead == ourBuffer+sizeof ourBuffer)
* We define something to allow us to to IsProtected() quickly
* on unformatted screens (with the current algorithm for fields,
* unprotected takes exponential time...).
* The idea is to call SetXIsProtected() BEFORE the
* loop, then use XIsProtected().
#define SetXIsProtected() (XWasSF = 1)
#define XIsProtected(p) (IsStartField(p)? \
(XWasSF = 0, XProtected = IsProtected(p)) : \
static char ourBuffer
[400];
static char *ourPHead
= ourBuffer
,
static int HadAid
; /* Had an AID haven't sent */
static int shifted
, /* Shift state of terminal */
alted
; /* Alt state of terminal */
static int InsertMode
; /* is the terminal in insert mode? */
static int XWasSF
, XProtected
; /* For optimizations */
extern int TransparentClock
, OutputClock
;
#endif /* !defined(PURE3274) */
#include "kbd.out" /* Get keyboard mapping function */
/* the following are global variables */
extern int UnLocked
; /* keyboard is UnLocked? */
* Reset variables to initial state.
ourPHead
= ourPTail
= ourBuffer
;
/* Tab() - sets cursor to the start of the next unprotected field */
j
= WhereAttrByte(CursorAddress
);
if (IsStartField(i
) && IsUnProtected(ScreenInc(i
))) {
if (IsStartField(i
) && IsUnProtected(ScreenInc(i
))) {
CursorAddress
= ScreenInc(i
);
CursorAddress
= SetBufferAddress(0,0);
/* BackTab() - sets cursor to the start of the most recent field */
i
= ScreenDec(CursorAddress
);
if (IsStartField(ScreenDec(i
)) && IsUnProtected(i
)) {
if (i
== CursorAddress
) {
CursorAddress
= SetBufferAddress(0,0);
/* EraseEndOfField - erase all characters to the end of a field */
if (IsProtected(CursorAddress
)) {
RingBell("Protected Field");
TurnOnMdt(CursorAddress
);
} while ((i
!= CursorAddress
) && !IsStartField(i
));
} else { /* Screen is Unformatted */
} while (i
!= HighestScreen());
/* Delete() - deletes a character from the screen
* What we want to do is delete the section
* [where, from-1] from the screen,
* filling in with what comes at from.
* The deleting continues to the end of the field (or
* until the cursor wraps).
* From can be a start of a field. We
* check for that. However, there can't be any
* fields that start between where and from.
* We don't check for that.
* Also, we assume that the protection status of
* everything has been checked by the caller.
register int where
, /* Where to start deleting from */
from
; /* Where to pull back from */
TurnOnMdt(where
); /* Only do this once in this field */
if (IsStartField(from
)) {
AddHost(i
, 0); /* Stick the edge at the start field */
AddHost(i
, GetHost(from
));
from
= ScreenInc(from
); /* Move the edge */
} while ((!IsStartField(i
)) && (i
!= where
));
i
= ScreenLineOffset(CursorAddress
);
for (i
= i
-1; i
>= 0; i
--) {
CursorAddress
= SetBufferAddress(ScreenLine(CursorAddress
), i
);
i
= ScreenLineOffset(CursorAddress
);
for (i
= i
+1; i
< NumberColumns
; i
++) {
if (i
>= NumberColumns
) {
CursorAddress
= SetBufferAddress(ScreenLine(CursorAddress
), i
);
i
= SetBufferAddress(OptHome
, 0);
/* the following could be a problem if we got here with an
* unformatted screen. However, this is "impossible", since
* with an unformatted screen, the IsUnProtected(i) above
i
= ScreenInc(FieldInc(i
));
CursorAddress
= LowestScreen();
register int i
; /* position to start from */
while (XIsProtected(i
) || Disspace(GetHost(i
))) {
/* We are now IN a word IN an unprotected field (or wrapped) */
while (!XIsProtected(i
)) {
if (!Disspace(GetHost(i
))) {
ourPTail
= ourPHead
= ourBuffer
;
* Add one EBCDIC (NOT display code) character to the buffer.
ourPTail
+= DataToNetwork(ourPTail
, ourPHead
-ourPTail
, 0);
sprintf(buffer
, "File %s, line %d: No room in network buffer!\n",
ExitString(stderr
, buffer
, 1);
/* look for start of field */
AddChar(EBCDIC_BLANK
); /* put in blanks */
register int i
; /* where we saw MDT bit */
int command
; /* The command code (type of read) */
/* look for start of field */
/* On a test_request_read, don't send sba and address */
if ((AidByte
!= AID_TREQ
)
|| (command
== CMD_SNA_READ_MODIFIED_ALL
)) {
AddChar(ORDER_SBA
); /* set start field */
AddChar(BufferTo3270_0(j
)); /* set address of this field */
AddChar(BufferTo3270_1(j
));
* Only on read_modified_all do we return the contents
* of the field when the attention was caused by a
if ((AidByte
!= AID_SELPEN
)
|| (command
== CMD_SNA_READ_MODIFIED_ALL
)) {
k
= ScreenInc(WhereHighByte(j
));
AddChar(EBCDIC_BLANK
); /* put in blanks */
} while ((j
!= k
) && (j
!= i
));
/* Various types of reads... */
int command
; /* The command sent */
if (AidByte
!= AID_TREQ
) {
/* Test Request Read header */
if (((AidByte
!= AID_PA1
) && (AidByte
!= AID_PA2
)
&& (AidByte
!= AID_PA3
) && (AidByte
!= AID_CLEAR
))
|| (command
== CMD_SNA_READ_MODIFIED_ALL
)) {
if ((AidByte
!= AID_TREQ
)
|| (command
== CMD_SNA_READ_MODIFIED_ALL
)) {
/* Test request read_modified doesn't give cursor address */
AddChar(BufferTo3270_0(CursorAddress
));
AddChar(BufferTo3270_1(CursorAddress
));
i
= j
= WhereAttrByte(LowestScreen());
/* Is this an unformatted screen? */
if (!IsStartField(i
)) { /* yes, handle separate */
i
= SendField(i
, command
);
ourPTail
+= DataToNetwork(ourPTail
, ourPHead
-ourPTail
, 1);
HadAid
= 0; /* killed that buffer */
/* A read buffer operation... */
AddChar(BufferTo3270_0(CursorAddress
));
AddChar(BufferTo3270_1(CursorAddress
));
AddChar(BufferTo3270_1(FieldAttributes(i
)));
AddChar(disp_ebc
[GetHost(i
)]);
ourPTail
+= DataToNetwork(ourPTail
, ourPHead
-ourPTail
, 1);
HadAid
= 0; /* killed that buffer */
/* Try to send some data to host */
if (TransparentClock
== OutputClock
) {
AddChar(AID_NONE_PRINTER
);
ourPTail
+= DataToNetwork(ourPTail
, ourPHead
-ourPTail
, 1);
DoReadModified(CMD_READ_MODIFIED
);
#else /* !defined(PURE3274) */
DoReadModified(CMD_READ_MODIFIED
);
#endif /* !defined(PURE3274) */
/* This takes in one character from the keyboard and places it on the
int c
; /* character (Ebcdic) to be shoved in */
int insert
; /* are we in insert mode? */
if (IsProtected(CursorAddress
)) {
RingBell("Protected Field");
/* is the last character in the field a blank or null? */
i
= ScreenDec(FieldInc(CursorAddress
));
RingBell("No more room for insert");
for (j
= ScreenDec(i
); i
!= CursorAddress
;
j
= ScreenDec(j
), i
= ScreenDec(i
)) {
AddHost(CursorAddress
, c
);
TurnOnMdt(CursorAddress
);
CursorAddress
= ScreenInc(CursorAddress
);
if (IsStartField(CursorAddress
) &&
((FieldAttributes(CursorAddress
)&ATTR_AUTO_SKIP_MASK
) ==
/* go through data until an AID character is hit, then generate an interrupt */
DataFrom3270(buffer
, count
)
unsigned char *buffer
; /* where the data is */
int count
; /* how much data there is */
# define HITNUM() ((shifted? 1:0) + ((alted?1:0)<<1))
if (*buffer
>= numberof(hits
)) {
"Unknown scancode encountered in DataFrom3270.\n", 1);
ctlrfcn
= hits
[*buffer
].hit
[HITNUM()].ctlrfcn
;
c
= hits
[*buffer
].hit
[HITNUM()].code
;
if (!UnLocked
|| HadAid
) {
return(0); /* nothing to do */
if (!HadAid
&& EmptyChar()) {
if ((ctlrfcn
== FCN_RESET
) || (ctlrfcn
== FCN_MASTER_RESET
)) {
#endif /* !defined(PURE3274) */
/* now, either empty, or haven't seen aid yet */
if (TransparentClock
== OutputClock
) {
if (*buffer
>= numberof(hits
)) {
"Unknown scancode encountered in DataFrom3270.\n", 1);
ctlrfcn
= hits
[*buffer
].hit
[HITNUM()].ctlrfcn
;
c
= hits
[*buffer
].hit
[HITNUM()].code
;
if (ctlrfcn
== FCN_AID
) {
return(origCount
-(count
+1));
#endif /* !defined(PURE3274) */
if (*buffer
>= numberof(hits
)) {
"Unknown scancode encountered in DataFrom3270.\n", 1);
ctlrfcn
= hits
[*buffer
].hit
[HITNUM()].ctlrfcn
;
c
= hits
[*buffer
].hit
[HITNUM()].code
;
if (ctlrfcn
== FCN_CHARACTER
) {
/* Add the character to the buffer */
OneCharacter(c
, InsertMode
);
} else if (ctlrfcn
== FCN_AID
) { /* got Aid */
LocalClearScreen(); /* Side effect is to clear 3270 */
InsertMode
= 0; /* just like a 3278 */
"More BREAK_SHIFT than MAKE_SHIFT.\n", 1);
ExitString(stderr
, "More BREAK_ALT than MAKE_ALT.\n", 1);
c
= FieldAttributes(CursorAddress
)&ATTR_DSPD_MASK
;
|| ((c
!= ATTR_DSPD_DSPD
) && (c
!= ATTR_DSPD_HIGH
))) {
RingBell("Cursor not in selectable field");
i
= ScreenInc(WhereAttrByte(CursorAddress
));
if (c
== DISP_QUESTION
) {
AddHost(i
, DISP_GREATER_THAN
);
} else if (c
== DISP_GREATER_THAN
) {
AddHost(i
, DISP_QUESTION
);
} else if (c
== DISP_BLANK
|| c
== DISP_NULL
|| c
== DISP_AMPERSAND
) {
if (c
== DISP_AMPERSAND
) {
TurnOnMdt(i
); /* Only for & type */
"Cursor not in a selectable field (designator)");
if (IsProtected(ScreenDec(CursorAddress
))) {
RingBell("Protected Field");
CursorAddress
= ScreenDec(CursorAddress
);
Delete(CursorAddress
, ScreenInc(CursorAddress
));
RingBell("Protected Field");
while ((!XIsProtected(i
) && Disspace(GetHost(i
)))
/* we are pointing at a character in a word, or
* at a protected position
while ((!XIsProtected(i
) && !Disspace(GetHost(i
)))
/* we are pointing at a space, or at a protected
CursorAddress
= ScreenInc(i
);
Delete(CursorAddress
, j
);
if (IsProtected(CursorAddress
)) {
RingBell("Protected Field");
CursorAddress
= ScreenInc(CursorAddress
); /* for btab */
#endif /* !defined(PURE3274) */
CursorAddress
= ScreenUp(CursorAddress
);
CursorAddress
= ScreenDec(CursorAddress
);
CursorAddress
= ScreenInc(CursorAddress
);
CursorAddress
= ScreenDown(CursorAddress
);
if (IsProtected(CursorAddress
)) {
RingBell("Protected Field");
Delete(CursorAddress
, ScreenInc(CursorAddress
));
InsertMode
= !InsertMode
;
/* The algorithm is to look for the first unprotected
* column after column 0 of the following line. Having
* found that unprotected column, we check whether the
* cursor-address-at-entry is at or to the right of the
* LeftMargin AND the LeftMargin column of the found line
* is unprotected. If this conjunction is true, then
* we set the found pointer to the address of the LeftMargin
* column in the found line.
* Then, we set the cursor address to the found address.
i
= SetBufferAddress(ScreenLine(ScreenDown(CursorAddress
)), 0);
j
= ScreenInc(WhereAttrByte(CursorAddress
));
/* Again (see comment in Home()), this COULD be a problem
* with an unformatted screen.
/* If there was a field with only an attribute byte,
* we may be pointing to the attribute byte of the NEXT
* field, so just look at the next byte.
i
= ScreenInc(FieldInc(i
));
if (!IsUnProtected(i
)) { /* couldn't find unprotected */
i
= SetBufferAddress(0,0);
if (OptLeftMargin
<= ScreenLineOffset(CursorAddress
)) {
if (IsUnProtected(SetBufferAddress(ScreenLine(i
),
i
= SetBufferAddress(ScreenLine(i
), OptLeftMargin
);
if (!FormattedScreen()) {
} while (i
!= CursorAddress
);
* The algorithm is: go through each unprotected
* field on the screen, clearing it out. When
* we are at the start of a field, skip that field
* if its contents are protected.
i
= j
= FieldInc(CursorAddress
);
if (IsUnProtected(ScreenInc(i
))) {
} while (!IsStartField(i
));
OneCharacter(DISP_BLANK
, InsertMode
); /* Add cent */
OneCharacter(DISP_CENTSIGN
, InsertMode
); /* Add cent */
OneCharacter(DISP_FM
, InsertMode
); /* Add field mark */
if (IsProtected(CursorAddress
)) {
RingBell("Protected Field");
OneCharacter(DISP_DUP
, InsertMode
);/* Add dup character */
#ifdef NOTUSED /* Actually, this is superseded by unix flow
Flow
= 0; /* stop output */
Flow
= 1; /* turn it back on */
/* FlushChar(); do we want to flush characters from before? */
OptColTabs
[ScreenLineOffset(CursorAddress
)] = 1;
OptColTabs
[ScreenLineOffset(CursorAddress
)] = 0;
* Clear all tabs, home line, and left margin.
for (i
= 0; i
< sizeof OptColTabs
; i
++) {
OptLeftMargin
= ScreenLineOffset(CursorAddress
);
OptLeftMargin
= ScreenLineOffset(CursorAddress
);
OptLeftMargin
= ScreenLineOffset(CursorAddress
);
OptHome
= ScreenLine(CursorAddress
);
* Point to first character of next unprotected word on
while (!XIsProtected(i
) && !Disspace(GetHost(i
))) {
if (i
== CursorAddress
) {
/* i is either protected, a space (blank or null),
while (XIsProtected(i
) || Disspace(GetHost(i
))) {
if (i
== CursorAddress
) {
i
= ScreenDec(CursorAddress
);
while (XIsProtected(i
) || Disspace(GetHost(i
))) {
if (i
== CursorAddress
) {
/* i is pointing to a character IN an unprotected word
while (!Disspace(GetHost(i
))) {
if (i
== CursorAddress
) {
CursorAddress
= ScreenInc(i
);
/* Point to last non-blank character of this/next
i
= ScreenInc(CursorAddress
);
while (XIsProtected(i
) || Disspace(GetHost(i
))) {
if (i
== CursorAddress
) {
/* we are pointing at a character IN an
* unprotected word (or we wrapped)
while (!Disspace(GetHost(i
))) {
if (i
== CursorAddress
) {
CursorAddress
= ScreenDec(i
);
/* Get to last non-blank of this/next unprotected
i
= LastOfField(CursorAddress
);
if (i
!= CursorAddress
) {
CursorAddress
= i
; /* We moved; take this */
j
= FieldInc(CursorAddress
); /* Move to next field */
CursorAddress
= i
; /* We moved; take this */
/* else - nowhere else on screen to be; stay here */
#endif /* !defined(PURE3274) */
/* We don't handle this yet */
RingBell("Function not implemented");