From f9ab90d9d6d02989a075d0f0074496d5b1045e4b Mon Sep 17 00:00:00 2001 From: rgrimes Date: Fri, 27 May 1994 12:33:43 +0000 Subject: BSD 4.4 Lite Usr.bin Sources --- usr.bin/tn3270/sys_curses/termout.c | 957 ++++++++++++++++++++++++++++++++++++ 1 file changed, 957 insertions(+) create mode 100644 usr.bin/tn3270/sys_curses/termout.c (limited to 'usr.bin/tn3270/sys_curses/termout.c') 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 +#include +#endif +#include +#include +#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) */ -- cgit v1.1