summaryrefslogtreecommitdiffstats
path: root/usr.bin/tn3270/sys_curses/termout.c
diff options
context:
space:
mode:
authorrgrimes <rgrimes@FreeBSD.org>1994-05-27 12:33:43 +0000
committerrgrimes <rgrimes@FreeBSD.org>1994-05-27 12:33:43 +0000
commitf9ab90d9d6d02989a075d0f0074496d5b1045e4b (patch)
treeadd7e996bac5289cdc55e6935750c352505560a9 /usr.bin/tn3270/sys_curses/termout.c
parentbe22b15ae2ff8d7fe06b6e14fddf0c5b444a95da (diff)
downloadFreeBSD-src-f9ab90d9d6d02989a075d0f0074496d5b1045e4b.zip
FreeBSD-src-f9ab90d9d6d02989a075d0f0074496d5b1045e4b.tar.gz
BSD 4.4 Lite Usr.bin Sources
Diffstat (limited to 'usr.bin/tn3270/sys_curses/termout.c')
-rw-r--r--usr.bin/tn3270/sys_curses/termout.c957
1 files changed, 957 insertions, 0 deletions
diff --git a/usr.bin/tn3270/sys_curses/termout.c b/usr.bin/tn3270/sys_curses/termout.c
new file mode 100644
index 0000000..5dbe311
--- /dev/null
+++ b/usr.bin/tn3270/sys_curses/termout.c
@@ -0,0 +1,957 @@
+/*-
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)termout.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#if defined(unix)
+#include <signal.h>
+#include <sgtty.h>
+#endif
+#include <stdio.h>
+#include <curses.h>
+#if defined(ultrix)
+/* Some version of this OS has a bad definition for nonl() */
+#undef nl
+#undef nonl
+
+#define nl() (_tty.sg_flags |= CRMOD,_pfast = _rawmode,stty(_tty_ch, &_tty))
+#define nonl() (_tty.sg_flags &= ~CRMOD, _pfast = TRUE, stty(_tty_ch, &_tty))
+#endif /* defined(ultrix) */
+
+#include "../general/general.h"
+
+#include "terminal.h"
+
+#include "../api/disp_asc.h"
+
+#include "../ctlr/hostctlr.h"
+#include "../ctlr/externs.h"
+#include "../ctlr/declare.h"
+#include "../ctlr/oia.h"
+#include "../ctlr/screen.h"
+#include "../ctlr/scrnctlr.h"
+
+#include "../general/globals.h"
+
+#include "telextrn.h"
+
+#define CorrectTerminalCursor() ((TransparentClock == OutputClock)? \
+ CursorAddress: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 max_changes_before_poll; /* how many characters before looking */
+ /* at terminal and net again */
+
+static int needToRing; /* need to ring terinal bell */
+static char *bellSequence = "\07"; /* bell sequence (may be replaced by
+ * VB during initialization)
+ */
+static WINDOW *bellwin = 0; /* The window the bell message is in */
+int bellwinup = 0; /* Are we up with it or not */
+
+#if defined(unix)
+static char *myKS, *myKE;
+#endif /* defined(unix) */
+
+
+static int inHighlightMode = 0;
+ScreenImage Terminal[MAXSCREENSIZE];
+
+/* Variables for transparent mode */
+#if defined(unix)
+static int tcflag = -1; /* transparent mode command flag */
+static int savefd[2]; /* for storing fds during transcom */
+extern int tin, tout; /* file descriptors */
+#endif /* defined(unix) */
+
+
+/*
+ * init_screen()
+ *
+ * Initialize variables used by screen.
+ */
+
+void
+init_screen()
+{
+ bellwinup = 0;
+ inHighlightMode = 0;
+ ClearArray(Terminal);
+}
+
+
+/* OurExitString - designed to keep us from going through infinite recursion */
+
+static void
+OurExitString(string, value)
+char *string;
+int value;
+{
+ static int recursion = 0;
+
+ if (!recursion) {
+ recursion = 1;
+ ExitString(string, value);
+ }
+}
+
+
+/* DoARefresh */
+
+static void
+DoARefresh()
+{
+ if (ERR == refresh()) {
+ OurExitString("ERR from refresh\n", 1);
+ }
+}
+
+static void
+GoAway(from, where)
+char *from; /* routine that gave error */
+int where; /* cursor address */
+{
+ char foo[100];
+
+ sprintf(foo, "ERR from %s at %d (%d, %d)\n",
+ from, where, ScreenLine(where), ScreenLineOffset(where));
+ OurExitString(foo, 1);
+ /* NOTREACHED */
+}
+
+/* What is the screen address of the attribute byte for the terminal */
+
+static int
+WhereTermAttrByte(p)
+register int p;
+{
+ register int i;
+
+ i = p;
+
+ do {
+ if (TermIsStartField(i)) {
+ return(i);
+ }
+ i = ScreenDec(i);
+ } while (i != p);
+
+ return(LowestScreen()); /* unformatted screen... */
+}
+
+/*
+ * There are two algorithms for updating the screen.
+ * The first, SlowScreen() optimizes the line between the
+ * computer and the screen (say a 9600 baud line). To do
+ * this, we break out of the loop every so often to look
+ * at any pending input from the network (so that successive
+ * screens will only partially print until the final screen,
+ * the one the user possibly wants to see, is displayed
+ * in its entirety).
+ *
+ * The second algorithm tries to optimize CPU time (by
+ * being simpler) at the cost of the bandwidth to the
+ * screen.
+ *
+ * Of course, curses(3X) gets in here also.
+ */
+
+
+#if defined(NOT43)
+static int
+#else /* defined(NOT43) */
+static void
+#endif /* defined(NOT43) */
+SlowScreen()
+{
+ register int is, shouldbe, isattr, shouldattr;
+ register int pointer;
+ register int fieldattr, termattr;
+ register int columnsleft;
+
+#define NORMAL 0
+#define HIGHLIGHT 1 /* Mask bits */
+#define NONDISPLAY 4 /* Mask bits */
+#define UNDETERMINED 8 /* Mask bits */
+
+#define DoAttributes(x) \
+ switch (x&ATTR_DSPD_MASK) { \
+ case ATTR_DSPD_NONDISPLAY: \
+ x = NONDISPLAY; \
+ break; \
+ case ATTR_DSPD_HIGH: \
+ x = HIGHLIGHT; \
+ break; \
+ default: \
+ x = 0; \
+ break; \
+ }
+
+# define SetHighlightMode(x) \
+ { \
+ if ((x)&HIGHLIGHT) { \
+ if (!inHighlightMode) { \
+ inHighlightMode = HIGHLIGHT; \
+ standout(); \
+ } \
+ } else { \
+ if (inHighlightMode) { \
+ inHighlightMode = 0; \
+ standend(); \
+ } \
+ } \
+ }
+
+# define DoCharacterAt(c,p) { \
+ if (p != HighestScreen()) { \
+ c = disp_asc[c&0xff]; \
+ if (terminalCursorAddress != p) { \
+ if (ERR == mvaddch(ScreenLine(p), \
+ ScreenLineOffset(p), c)) {\
+ GoAway("mvaddch", p); \
+ } \
+ } else { \
+ if (ERR == addch(c)) {\
+ GoAway("addch", p); \
+ } \
+ } \
+ terminalCursorAddress = ScreenInc(p); \
+ } \
+ }
+
+
+ /* run through screen, printing out non-null lines */
+
+ /* There are two separate reasons for wanting to terminate this
+ * loop early. One is to respond to new input (either from
+ * the terminal or from the network [host]). For this reason,
+ * we expect to see 'HaveInput' come true when new input comes in.
+ *
+ * The second reason is a bit more difficult (for me) to understand.
+ * Basically, we don't want to get too far ahead of the characters that
+ * appear on the screen. Ideally, we would type out a few characters,
+ * wait until they appeared on the screen, then type out a few more.
+ * The reason for this is that the user, on seeing some characters
+ * appear on the screen may then start to type something. We would
+ * like to look at what the user types at about the same 'time'
+ * (measured by characters being sent to the terminal) that the
+ * user types them. For this reason, what we would like to do
+ * is update a bit, then call curses to do a refresh, flush the
+ * output to the terminal, then wait until the terminal data
+ * has been sent.
+ *
+ * Note that curses is useful for, among other things, deciding whether
+ * or not to send :ce: (clear to end of line), so we should call curses
+ * at end of lines (beginning of next lines).
+ *
+ * The problems here are the following: If we do lots of write(2)s,
+ * we will be doing lots of context switches, thus lots of overhead
+ * (which we have already). Second, if we do a select to wait for
+ * the output to drain, we have to contend with the fact that NOW
+ * we are scheduled to run, but who knows what the scheduler will
+ * decide when the output has caught up.
+ */
+
+ if (Highest >= HighestScreen()) { /* Could be > if screen shrunk... */
+ Highest = ScreenDec(Highest); /* else, while loop will never end */
+ }
+ if (Lowest < LowestScreen()) {
+ Lowest = LowestScreen(); /* could be -1 in some cases with
+ * unformatted screens.
+ */
+ }
+ if (Highest >= (pointer = Lowest)) {
+ /* if there is anything to do, do it. We won't terminate
+ * the loop until we've gone at least to Highest.
+ */
+ while ((pointer <= Highest) && !HaveInput) {
+
+ /* point at the next place of disagreement */
+ pointer += (bunequal(Host+pointer, Terminal+pointer,
+ (Highest-pointer+1)*sizeof Host[0])/sizeof Host[0]);
+
+ /*
+ * How many characters to change until the end of the
+ * current line
+ */
+ columnsleft = NumberColumns - ScreenLineOffset(pointer);
+ /*
+ * Make sure we are where we think we are.
+ */
+ move(ScreenLine(pointer), ScreenLineOffset(pointer));
+
+ /* what is the field attribute of the current position */
+ if (FormattedScreen()) {
+ fieldattr = FieldAttributes(pointer);
+ DoAttributes(fieldattr);
+ } else {
+ fieldattr = NORMAL;
+ }
+ if (TerminalFormattedScreen()) {
+ termattr = TermAttributes(pointer);
+ DoAttributes(termattr);
+ } else {
+ termattr = NORMAL;
+ }
+
+ SetHighlightMode(fieldattr);
+ /*
+ * The following will terminate at least when we get back
+ * to the original 'pointer' location (since we force
+ * things to be equal).
+ */
+ for (;;) {
+ if (IsStartField(pointer)) {
+ shouldbe = DISP_BLANK;
+ shouldattr = 0;
+ fieldattr = GetHost(pointer);
+ DoAttributes(fieldattr);
+ } else {
+ if (fieldattr&NONDISPLAY) {
+ shouldbe = DISP_BLANK;
+ } else {
+ shouldbe = GetHost(pointer);
+ }
+ shouldattr = fieldattr;
+ }
+ if (TermIsStartField(pointer)) {
+ is = DISP_BLANK;
+ isattr = 0;
+ termattr = UNDETERMINED; /* Need to find out AFTER update */
+ } else {
+ if (termattr&NONDISPLAY) {
+ is = DISP_BLANK;
+ } else {
+ is = GetTerminal(pointer);
+ }
+ isattr = termattr;
+ }
+ if ((shouldbe == is) && (shouldattr == isattr)
+ && (GetHost(pointer) == GetTerminal(pointer))
+ && (GetHost(ScreenInc(pointer))
+ == GetTerminal(ScreenInc(pointer)))) {
+ break;
+ }
+
+ if (shouldattr^inHighlightMode) {
+ SetHighlightMode(shouldattr);
+ }
+
+ DoCharacterAt(shouldbe, pointer);
+ if (IsStartField(pointer)) {
+ TermNewField(pointer, FieldAttributes(pointer));
+ termattr = GetTerminal(pointer);
+ DoAttributes(termattr);
+ } else {
+ SetTerminal(pointer, GetHost(pointer));
+ /*
+ * If this USED to be a start field location,
+ * recompute the terminal attributes.
+ */
+ if (termattr == UNDETERMINED) {
+ termattr = WhereTermAttrByte(pointer);
+ if ((termattr != 0) || TermIsStartField(0)) {
+ termattr = GetTerminal(termattr);
+ DoAttributes(termattr);
+ } else { /* Unformatted screen */
+ termattr = NORMAL;
+ }
+ }
+ }
+ pointer = ScreenInc(pointer);
+ if (!(--columnsleft)) {
+ DoARefresh();
+ EmptyTerminal();
+ if (HaveInput) { /* if input came in, take it */
+ int c, j;
+
+ /*
+ * We need to start a new terminal field
+ * at this location iff the terminal attributes
+ * of this location are not what we have had
+ * them as (ie: we've overwritten the terminal
+ * start field, a the previous field had different
+ * display characteristics).
+ */
+
+ isattr = TermAttributes(pointer);
+ DoAttributes(isattr);
+ if ((!TermIsStartField(pointer)) &&
+ (isattr != termattr)) {
+ /*
+ * Since we are going to leave a new field
+ * at this terminal position, we
+ * need to make sure that we get an actual
+ * non-highlighted blank on the screen.
+ */
+ if ((is != DISP_BLANK) || (termattr&HIGHLIGHT)) {
+ SetHighlightMode(0); /* Turn off highlight */
+ c = ScreenInc(pointer);
+ j = DISP_BLANK;
+ DoCharacterAt(j, c);
+ }
+ if (termattr&HIGHLIGHT) {
+ termattr = ATTR_DSPD_HIGH;
+ } else if (termattr&NONDISPLAY) {
+ termattr = ATTR_DSPD_NONDISPLAY;
+ } else {
+ termattr = 0;
+ }
+ TermNewField(pointer, termattr);
+ }
+ break;
+ }
+ move(ScreenLine(pointer), 0);
+ columnsleft = NumberColumns;
+ }
+ } /* end of for (;;) */
+ } /* end of while (...) */
+ }
+ DoARefresh();
+ Lowest = pointer;
+ if (Lowest > Highest) { /* if we finished input... */
+ Lowest = HighestScreen()+1;
+ Highest = LowestScreen()-1;
+ terminalCursorAddress = CorrectTerminalCursor();
+ if (ERR == move(ScreenLine(terminalCursorAddress),
+ ScreenLineOffset(terminalCursorAddress))) {
+ GoAway("move", terminalCursorAddress);
+ }
+ DoARefresh();
+ if (needToRing) {
+ StringToTerminal(bellSequence);
+ needToRing = 0;
+ }
+ }
+ EmptyTerminal(); /* move data along */
+ return;
+}
+
+#if defined(NOT43)
+static int
+#else /* defined(NOT43) */
+static void
+#endif /* defined(NOT43) */
+FastScreen()
+{
+#if defined(MSDOS)
+#define SaveCorner 0
+#else /* defined(MSDOS) */
+#define SaveCorner 1
+#endif /* defined(MSDOS) */
+
+#define DoAttribute(a) if (IsHighlightedAttr(a)) { \
+ standout(); \
+ } else { \
+ standend(); \
+ } \
+ if (IsNonDisplayAttr(a)) { \
+ a = 0; /* zero == don't display */ \
+ } \
+ if (!FormattedScreen()) { \
+ a = 1; /* one ==> do display on unformatted */\
+ }
+ ScreenImage *p, *upper;
+ int fieldattr; /* spends most of its time == 0 or 1 */
+
+/* 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())) {
+ register int columnsleft;
+
+ move(ScreenLine(Lowest), ScreenLineOffset(Lowest));
+ p = &Host[Lowest];
+#if !defined(MSDOS)
+ if (Highest == HighestScreen()) {
+ Highest = ScreenDec(Highest);
+ }
+#endif /* !defined(MSDOS) */
+ upper = &Host[Highest];
+ fieldattr = FieldAttributes(Lowest);
+ DoAttribute(fieldattr); /* Set standout, non-display status */
+ columnsleft = NumberColumns-ScreenLineOffset(p-Host);
+
+ while (p <= upper) {
+ if (IsStartFieldPointer(p)) { /* New field? */
+ Highest = HighestScreen();
+ Lowest = LowestScreen();
+ FastScreen(); /* Recurse */
+ return;
+ } else if (fieldattr) { /* Should we display? */
+ /* Display translated data */
+ addch((char)disp_asc[GetTerminalPointer(p)]);
+ } else {
+ addch(' '); /* Display a blank */
+ }
+ /* If the physical screen is larger than what we
+ * are using, we need to make sure that each line
+ * starts at the beginning of the line. Otherwise,
+ * we will just string all the lines together.
+ */
+ p++;
+ if (--columnsleft == 0) {
+ int i = p-Host;
+
+ move(ScreenLine(i), 0);
+ columnsleft = NumberColumns;
+ }
+ }
+ } else { /* Going from Lowest to Highest */
+ unsigned char tmpbuf[MAXNUMBERCOLUMNS+1];
+ ScreenImage *End = &Host[ScreenSize]-1-SaveCorner;
+ register unsigned char *tmp = tmpbuf, *tmpend = tmpbuf+NumberColumns;
+
+ *tmpend = 0; /* terminate from the beginning */
+ move(0,0);
+ p = Host;
+ fieldattr = FieldAttributes(LowestScreen());
+ DoAttribute(fieldattr); /* Set standout, non-display status */
+
+ while (p <= End) {
+ if (IsStartFieldPointer(p)) { /* New field? */
+ if (tmp != tmpbuf) {
+ *tmp++ = 0; /* close out */
+ addstr((char *)tmpbuf);
+ tmp = tmpbuf;
+ tmpend = tmpbuf+NumberColumns-ScreenLineOffset(p-Host)-1;
+ }
+ standend();
+ addch(' ');
+ fieldattr = FieldAttributesPointer(p); /* Get attributes */
+ DoAttribute(fieldattr); /* Set standout, non-display */
+ } else {
+ if (fieldattr) { /* Should we display? */
+ /* Display translated data */
+ *tmp++ = disp_asc[GetTerminalPointer(p)];
+ } else {
+ *tmp++ = ' ';
+ }
+ }
+ /* If the physical screen is larger than what we
+ * are using, we need to make sure that each line
+ * starts at the beginning of the line. Otherwise,
+ * we will just string all the lines together.
+ */
+ p++;
+ if (tmp == tmpend) {
+ int i = p-Host; /* Be sure the "p++" happened first! */
+
+ *tmp++ = 0;
+ addstr((char *)tmpbuf);
+ tmp = tmpbuf;
+ move(ScreenLine(i), 0);
+ tmpend = tmpbuf + NumberColumns;
+ }
+ }
+ if (tmp != tmpbuf) {
+ *tmp++ = 0;
+ addstr((char *)tmpbuf);
+ tmp = tmpbuf;
+ }
+ }
+ Lowest = HighestScreen()+1;
+ Highest = LowestScreen()-1;
+ terminalCursorAddress = CorrectTerminalCursor();
+ if (ERR == move(ScreenLine(terminalCursorAddress),
+ ScreenLineOffset(terminalCursorAddress))) {
+ GoAway("move", terminalCursorAddress);
+ }
+ DoARefresh();
+ if (needToRing) {
+ StringToTerminal(bellSequence);
+ needToRing = 0;
+ }
+ EmptyTerminal(); /* move data along */
+ return;
+}
+
+
+/* TryToSend - send data out to user's terminal */
+
+#if defined(NOT43)
+int
+#else /* defined(NOT43) */
+void
+#endif /* defined(NOT43) */
+ (*TryToSend)() = FastScreen;
+
+/*ARGSUSED*/
+void
+ScreenOIA(oia)
+OIA *oia;
+{
+}
+
+
+/* InitTerminal - called to initialize the screen, etc. */
+
+void
+InitTerminal()
+{
+#if defined(unix)
+ struct sgttyb ourttyb;
+ static int speeds[] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800,
+ 2400, 4800, 9600 };
+#endif
+ extern void InitMapping();
+
+ InitMapping(); /* Go do mapping file (MAP3270) first */
+ if (!screenInitd) { /* not initialized */
+#if defined(unix)
+ char KSEbuffer[2050];
+ char *lotsofspace = KSEbuffer;
+ extern void abort();
+ extern char *tgetstr();
+#endif /* defined(unix) */
+
+ if (initscr() == ERR) { /* Initialize curses to get line size */
+ ExitString("InitTerminal: Error initializing curses", 1);
+ /*NOTREACHED*/
+ }
+ MaxNumberLines = LINES;
+ MaxNumberColumns = COLS;
+ ClearArray(Terminal);
+ terminalCursorAddress = SetBufferAddress(0,0);
+#if defined(unix)
+ signal(SIGHUP, abort);
+#endif
+
+ TryToSend = FastScreen;
+#if defined(unix)
+ ioctl(1, TIOCGETP, (char *) &ourttyb);
+ if ((ourttyb.sg_ospeed < 0) || (ourttyb.sg_ospeed > B9600)) {
+ max_changes_before_poll = 1920;
+ } else {
+ max_changes_before_poll = speeds[ourttyb.sg_ospeed]/10;
+ if (max_changes_before_poll < 40) {
+ max_changes_before_poll = 40;
+ }
+ TryToSend = SlowScreen;
+ HaveInput = 1; /* get signals going */
+ }
+#endif /* defined(unix) */
+ setcommandmode();
+ /*
+ * By now, initscr() (in curses) has been called (from telnet.c),
+ * and the screen has been initialized.
+ */
+#if defined(unix)
+ nonl();
+ /* the problem is that curses catches SIGTSTP to
+ * be nice, but it messes us up.
+ */
+ signal(SIGTSTP, SIG_DFL);
+ if ((myKS = tgetstr("ks", &lotsofspace)) != 0) {
+ myKS = strsave(myKS);
+ StringToTerminal(myKS);
+ }
+ if ((myKE = tgetstr("ke", &lotsofspace)) != 0) {
+ myKE = strsave(myKE);
+ }
+ if (tgetstr("md", &lotsofspace) && tgetstr("me", &lotsofspace)) {
+ SO = strsave(tgetstr("md", &lotsofspace));
+ SE = strsave(tgetstr("me", &lotsofspace));
+ }
+#endif
+ DoARefresh();
+ setconnmode();
+ if (VB && *VB) {
+ bellSequence = VB; /* use visual bell */
+ }
+ screenInitd = 1;
+ screenStopped = 0; /* Not stopped */
+ }
+}
+
+
+/* StopScreen - called when we are going away... */
+
+void
+StopScreen(doNewLine)
+int doNewLine;
+{
+ if (screenInitd && !screenStopped) {
+ move(NumberLines-1, 1);
+ standend();
+ inHighlightMode = 0;
+ DoARefresh();
+ setcommandmode();
+ endwin();
+ setconnmode();
+#if defined(unix)
+ if (myKE) {
+ StringToTerminal(myKE);
+ }
+#endif /* defined(unix) */
+ if (doNewLine) {
+ StringToTerminal("\r\n");
+ }
+ EmptyTerminal();
+ screenStopped = 1; /* This is stopped */
+ }
+}
+
+
+/* RefreshScreen - called to cause the screen to be refreshed */
+
+void
+RefreshScreen()
+{
+ clearok(curscr, TRUE);
+ (*TryToSend)();
+}
+
+
+/* ConnectScreen - called to reconnect to the screen */
+
+void
+ConnectScreen()
+{
+ if (screenInitd) {
+#if defined(unix)
+ if (myKS) {
+ StringToTerminal(myKS);
+ }
+#endif /* defined(unix) */
+ RefreshScreen();
+ (*TryToSend)();
+ screenStopped = 0;
+ }
+}
+
+/* LocalClearScreen() - clear the whole ball of wax, cheaply */
+
+void
+LocalClearScreen()
+{
+ extern void Clear3270();
+
+ outputPurge(); /* flush all data to terminal */
+ clear(); /* clear in curses */
+ ClearArray(Terminal);
+ Clear3270();
+ Lowest = HighestScreen()+1; /* everything in sync... */
+ Highest = LowestScreen()+1;
+}
+
+
+void
+BellOff()
+{
+ if (bellwinup) {
+ delwin(bellwin);
+ bellwin = 0;
+ bellwinup = 0;
+ touchwin(stdscr);
+ DoARefresh();
+ }
+}
+
+
+void
+RingBell(s)
+char *s;
+{
+ needToRing = 1;
+ if (s) {
+ int len = strlen(s);
+
+ if (len > COLS-2) {
+ len = COLS-2;
+ }
+ if ((bellwin = newwin(3, len+2, LINES/2, 0)) == NULL) {
+ OurExitString("Error from newwin in RingBell", 1);
+ }
+ werase(bellwin);
+ wstandout(bellwin);
+ box(bellwin, '|', '-');
+ if (wmove(bellwin, 1, 1) == ERR) {
+ OurExitString("Error from wmove in RingBell", 1);
+ }
+ while (len--) {
+ if (waddch(bellwin, *s++) == ERR) {
+ OurExitString("Error from waddch in RingBell", 1);
+ }
+ }
+ wstandend(bellwin);
+ if (wrefresh(bellwin) == ERR) {
+ OurExitString("Error from wrefresh in RingBell", 1);
+ }
+ bellwinup = 1;
+ }
+}
+
+
+/* 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).
+ */
+
+int
+DoTerminalOutput()
+{
+ /* 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())) {
+ (*TryToSend)();
+ }
+ if (Lowest > Highest) {
+ return 1; /* no more output now */
+ } else {
+ return 0; /* more output for future */
+ }
+}
+
+/*
+ * The following are defined to handle transparent data.
+ */
+
+void
+TransStop()
+{
+#if defined(unix)
+ if (tcflag == 0) {
+ tcflag = -1;
+ (void) signal(SIGCHLD, SIG_DFL);
+ } else if (tcflag > 0) {
+ setcommandmode();
+ (void) close(tin);
+ (void) close(tout);
+ tin = savefd[0];
+ tout = savefd[1];
+ setconnmode();
+ tcflag = -1;
+ (void) signal(SIGCHLD, SIG_DFL);
+ }
+#endif /* defined(unix) */
+ RefreshScreen();
+}
+
+void
+TransOut(buffer, count, kind, control)
+unsigned char *buffer;
+int count;
+int kind; /* 0 or 5 */
+int control; /* To see if we are done */
+{
+#if defined(unix)
+ extern char *transcom;
+ int inpipefd[2], outpipefd[2];
+ static void aborttc();
+#endif /* defined(unix) */
+
+ while (DoTerminalOutput() == 0) {
+#if defined(unix)
+ HaveInput = 0;
+#endif /* defined(unix) */
+ }
+#if defined(unix)
+ if (transcom && tcflag == -1) {
+ while (1) { /* go thru once */
+ if (pipe(outpipefd) < 0) {
+ break;
+ }
+ if (pipe(inpipefd) < 0) {
+ break;
+ }
+ if ((tcflag = fork()) == 0) {
+ (void) close(outpipefd[1]);
+ (void) close(0);
+ if (dup(outpipefd[0]) < 0) {
+ exit(1);
+ }
+ (void) close(outpipefd[0]);
+ (void) close(inpipefd[0]);
+ (void) close(1);
+ if (dup(inpipefd[1]) < 0) {
+ exit(1);
+ }
+ (void) close(inpipefd[1]);
+ if (execl("/bin/csh", "csh", "-c", transcom, (char *) 0)) {
+ exit(1);
+ }
+ }
+ (void) close(inpipefd[1]);
+ (void) close(outpipefd[0]);
+ savefd[0] = tin;
+ savefd[1] = tout;
+ setcommandmode();
+ tin = inpipefd[0];
+ tout = outpipefd[1];
+ (void) signal(SIGCHLD, aborttc);
+ setconnmode();
+ tcflag = 1;
+ break;
+ }
+ if (tcflag < 1) {
+ tcflag = 0;
+ }
+ }
+#endif /* defined(unix) */
+ (void) DataToTerminal((char *)buffer, count);
+ if (control && (kind == 0)) { /* Send in AID byte */
+ SendToIBM();
+ } else {
+ extern void TransInput();
+
+ TransInput(1, kind); /* Go get some data */
+ }
+}
+
+
+#if defined(unix)
+static void
+aborttc(signo)
+ int signo;
+{
+ setcommandmode();
+ (void) close(tin);
+ (void) close(tout);
+ tin = savefd[0];
+ tout = savefd[1];
+ setconnmode();
+ tcflag = 0;
+}
+#endif /* defined(unix) */
OpenPOWER on IntegriCloud