summaryrefslogtreecommitdiffstats
path: root/usr.bin/tn3270/distribution/sys_dos/termout.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/tn3270/distribution/sys_dos/termout.c')
-rw-r--r--usr.bin/tn3270/distribution/sys_dos/termout.c514
1 files changed, 514 insertions, 0 deletions
diff --git a/usr.bin/tn3270/distribution/sys_dos/termout.c b/usr.bin/tn3270/distribution/sys_dos/termout.c
new file mode 100644
index 0000000..0339072
--- /dev/null
+++ b/usr.bin/tn3270/distribution/sys_dos/termout.c
@@ -0,0 +1,514 @@
+/*-
+ * 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 */
+
+#include <stdio.h>
+#include <dos.h>
+#include "../general/general.h"
+
+#include "../telnet.ext"
+
+#include "../api/disp_asc.h"
+#include "../ascii/map3270.ext"
+
+#include "../ctlr/hostctlr.h"
+#include "../ctlr/externs.h"
+#include "../ctlr/declare.h"
+#include "../ctlr/oia.h"
+#include "../ctlr/screen.h"
+
+#include "../general/globals.h"
+
+#include "video.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 */
+
+typedef struct {
+ char
+ data, /* The data for this position */
+ attr; /* The attributes for this position */
+} ScreenBuffer;
+
+ScreenBuffer Screen[MAXNUMBERLINES*MAXNUMBERCOLUMNS];
+ScreenBuffer saveScreen[sizeof Screen/sizeof Screen[0]];
+
+/* OurExitString - designed to keep us from going through infinite recursion */
+
+static void
+OurExitString(file, string, value)
+FILE *file;
+char *string;
+int value;
+{
+ static int recursion = 0;
+
+ if (!recursion) {
+ recursion = 1;
+ ExitString(file, string, value);
+ }
+}
+
+
+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(stderr, foo, 1);
+ /* NOTREACHED */
+}
+
+/*
+ * Routines to deal with the screen. These routines are lifted
+ * from mskermit.
+ */
+
+#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) { \
+ ; \
+ } \
+ }
+static int
+ crt_mode,
+ crt_cols,
+ crt_lins,
+ curpage;
+
+/*
+ * Set the cursor position to where it belongs.
+ */
+
+static void
+setcursor(row, column, page)
+int
+ row,
+ column,
+ page;
+{
+ union REGS inregs, outregs;
+
+ inregs.h.dh = row;
+ inregs.h.dl = column;
+ inregs.h.bh = page;
+ inregs.h.ah = SetCursorPosition;
+
+ int86(BIOS_VIDEO, &inregs, &outregs);
+}
+/*
+ * Read the state of the video system. Put the cursor somewhere
+ * reasonable.
+ */
+
+static void
+scrini()
+{
+ union REGS inregs, outregs;
+
+ inregs.h.ah = CurrentVideoState;
+ int86(BIOS_VIDEO, &inregs, &outregs);
+
+ crt_mode = outregs.h.al;
+ crt_cols = outregs.h.ah;
+ crt_lins = 25;
+ curpage = outregs.h.bh;
+
+ inregs.h.ah = ReadCursorPosition;
+ inregs.h.bh = curpage;
+
+ int86(BIOS_VIDEO, &inregs, &outregs);
+
+ if (outregs.h.dh > crt_lins) {
+ outregs.h.dh = crt_lins;
+ }
+ if (outregs.h.dl > crt_cols) {
+ outregs.h.dl = crt_cols;
+ }
+ inregs.h.dh = outregs.h.dh;
+ inregs.h.dl = outregs.h.dl;
+ inregs.h.bh = curpage;
+
+ inregs.h.ah = SetCursorPosition;
+ int86(BIOS_VIDEO, &inregs, &outregs);
+}
+
+
+static void
+scrwrite(source, length, offset)
+ScreenBuffer *source;
+int
+ length,
+ offset;
+{
+ struct SREGS segregs;
+
+ segread(&segregs); /* read the current segment register */
+
+ scrwait();
+ movedata(segregs.ds, source, scrseg(), sizeof *source*offset,
+ sizeof *source*length);
+}
+
+static void
+scrsave(buffer)
+ScreenBuffer *buffer;
+{
+ struct SREGS segregs;
+
+ segread(&segregs); /* read the current segment register */
+
+ scrwait();
+ movedata(scrseg(), 0, segregs.ds, buffer, crt_cols*crt_lins*2);
+}
+
+static void
+scrrest(buffer)
+ScreenBuffer *buffer;
+{
+ scrwrite(buffer, crt_cols*crt_lins, 0);
+}
+
+static void
+TryToSend()
+{
+#define STANDOUT 0x0a /* Highlighted mode */
+#define NORMAL 0x02 /* Normal mode */
+#define NONDISPLAY 0x00 /* Don't display */
+
+#define DoAttribute(a) \
+ if (screenIsFormatted) { \
+ if (IsNonDisplayAttr(a)) { \
+ a = NONDISPLAY; /* don't display */ \
+ } else if (IsHighlightedAttr(a)) { \
+ a = STANDOUT; \
+ } else { \
+ a = NORMAL; \
+ } \
+ } else { \
+ a = NORMAL; /* do display on unformatted */\
+ }
+ ScreenImage *p, *upper;
+ ScreenBuffer *sp;
+ 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())) {
+ sp = &Screen[Lowest];
+ p = &Host[Lowest];
+ upper = &Host[Highest];
+ fieldattr = FieldAttributes(Lowest);
+ DoAttribute(fieldattr); /* Set standout, non-display status */
+
+ while (p <= upper) {
+ if (IsStartFieldPointer(p)) { /* New field? */
+ Highest = HighestScreen();
+ Lowest = LowestScreen();
+ TryToSend(); /* Recurse */
+ return;
+ } else if (fieldattr) { /* Should we display? */
+ /* Display translated data */
+ sp->data = disp_asc[GetHostPointer(p)];
+ } else {
+ sp->data = ' ';
+ }
+ sp->attr = fieldattr;
+ p++;
+ sp++;
+ }
+ } else { /* Going from Lowest to Highest */
+ ScreenImage *End = &Host[ScreenSize]-1;
+
+ sp = Screen;
+ p = Host;
+ fieldattr = FieldAttributes(LowestScreen());
+ DoAttribute(fieldattr); /* Set standout, non-display status */
+
+ while (p <= End) {
+ 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)];
+ } else {
+ sp->data = ' ';
+ }
+ sp->attr = fieldattr;
+ p++;
+ sp++;
+ }
+ }
+ terminalCursorAddress = CorrectTerminalCursor();
+ /*
+ * We might be here just to update the cursor address.
+ */
+ if (Highest >= Lowest) {
+ scrwrite(Screen+Lowest, (1+Highest-Lowest), Lowest);
+ }
+ setcursor(ScreenLine(terminalCursorAddress),
+ ScreenLineOffset(terminalCursorAddress), 0);
+ Lowest = HighestScreen()+1;
+ Highest = LowestScreen()-1;
+ if (needToRing) {
+ DataToTerminal("\7", 1);
+ needToRing = 0;
+ }
+ return;
+}
+
+/* InitTerminal - called to initialize the screen, etc. */
+
+void
+InitTerminal()
+{
+ InitMapping(); /* Go do mapping file (MAP3270) first */
+ if (!screenInitd) { /* not initialized */
+ MaxNumberLines = 24; /* XXX */
+ MaxNumberColumns = 80; /* XXX */
+ scrini();
+ scrsave(saveScreen); /* Save the screen buffer away */
+ ClearArray(Screen);
+ terminalCursorAddress = SetBufferAddress(0,0);
+ screenInitd = 1;
+ screenStopped = 0; /* Not stopped */
+ }
+}
+
+
+/* StopScreen - called when we are going away... */
+
+void
+StopScreen(doNewLine)
+int doNewLine;
+{
+ if (screenInitd && !screenStopped) {
+ scrrest(saveScreen);
+ setcursor(NumberLines-1, 1, 0);
+ if (doNewLine) {
+ StringToTerminal("\r\n");
+ }
+ EmptyTerminal();
+ screenStopped = 1;
+ }
+}
+
+
+/* RefreshScreen - called to cause the screen to be refreshed */
+
+void
+RefreshScreen()
+{
+ Highest = HighestScreen();
+ Lowest = LowestScreen();
+ TryToSend();
+}
+
+
+/* ConnectScreen - called to reconnect to the screen */
+
+void
+ConnectScreen()
+{
+ if (screenInitd) {
+ RefreshScreen();
+ screenStopped = 0;
+ }
+}
+
+/* LocalClearScreen() - clear the whole ball of wax, cheaply */
+
+void
+LocalClearScreen()
+{
+ Clear3270();
+ Lowest = LowestScreen(); /* everything in sync... */
+ Highest = HighestScreen();
+ TryToSend();
+}
+
+/*
+ * Implement the bell/error message function.
+ */
+
+int
+ bellwinup = 0; /* If != 0, length of bell message */
+static int
+ bell_len = 0; /* Length of error message */
+
+
+void
+BellOff()
+{
+ ScreenBuffer a[100];
+ int i;
+
+ if (bellwinup) {
+ unsigned char blank = ' ';
+
+ for (i = 0; i < bell_len; i++) {
+ a[i].attr = NORMAL;
+ a[i].data = ' ';
+ }
+ }
+ scrwrite(a, bell_len, 24*80); /* XXX */
+}
+
+
+void
+RingBell(s)
+char *s;
+{
+ needToRing = 1;
+ if (s) {
+ int i;
+ ScreenBuffer bellstring[100];
+
+ bell_len = strlen(s);
+ bellwinup = 1;
+ 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 */
+ }
+}
+
+/*
+ * Update the OIA area.
+ */
+
+void
+ScreenOIA(oia)
+OIA *oia;
+{
+}
+
+
+/* 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()
+{
+ 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 */
+{
+ char *ptr;
+
+ 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 */
+ SendToIBM();
+ } else {
+ TransInput(1, kind); /* Go get some data */
+ }
+}
+
+/*
+ * init_screen()
+ *
+ * Initialize variables used by screen.
+ */
+
+void
+init_screen()
+{
+ bellwinup = 0;
+}
+
+
OpenPOWER on IntegriCloud