date and time created 87/05/22 12:01:28 by minshall
[unix-history] / usr / src / usr.bin / tn3270 / distribution / sys_dos / termout.c
CommitLineData
7f35cb09
GM
1/*
2 * Copyright (c) 1984, 1985, 1986 by the Regents of the
3 * University of California and by Gregory Glenn Minshall.
4 *
5 * Permission to use, copy, modify, and distribute these
6 * programs and their documentation for any purpose and
7 * without fee is hereby granted, provided that this
8 * copyright and permission appear on all copies and
9 * supporting documentation, the name of the Regents of
10 * the University of California not be used in advertising
11 * or publicity pertaining to distribution of the programs
12 * without specific prior permission, and notice be given in
13 * supporting documentation that copying and distribution is
14 * by permission of the Regents of the University of California
15 * and by Gregory Glenn Minshall. Neither the Regents of the
16 * University of California nor Gregory Glenn Minshall make
17 * representations about the suitability of this software
18 * for any purpose. It is provided "as is" without
19 * express or implied warranty.
20 */
21
22#ifndef lint
23static char sccsid[] = "@(#)outbound.c 3.1 10/29/86";
24#endif /* lint */
25
26
7f35cb09 27#include <stdio.h>
da3205fa 28#include <dos.h>
7f35cb09
GM
29#include "../general.h"
30
7f35cb09
GM
31#include "../telnet.ext"
32
33#include "../ctlr/hostctlr.h"
34#include "../ctlr/inbound.ext"
98e793e6 35#include "../ctlr/oia.h"
7f35cb09
GM
36#include "../ctlr/options.ext"
37#include "../ctlr/outbound.ext"
38#include "../ctlr/screen.h"
39
40#include "../keyboard/map3270.ext"
41
42#include "../system/globals.h"
43
da3205fa
GM
44#include "video.h"
45
7f35cb09
GM
46extern void EmptyTerminal();
47
48#define CorrectTerminalCursor() ((TransparentClock == OutputClock)? \
49 terminalCursorAddress:UnLocked? CursorAddress: HighestScreen())
50
51
52static int terminalCursorAddress; /* where the cursor is on term */
53static int screenInitd; /* the screen has been initialized */
54static int screenStopped; /* the screen has been stopped */
7f35cb09
GM
55
56static int needToRing; /* need to ring terinal bell */
7f35cb09 57
98e793e6
GM
58typedef struct {
59 char
60 data, /* The data for this position */
61 attr; /* The attributes for this position */
62} ScreenBuffer;
7f35cb09 63
98e793e6 64ScreenBuffer Screen[MAXNUMBERLINES*MAXNUMBERCOLUMNS];
da3205fa 65ScreenBuffer saveScreen[sizeof Screen/sizeof Screen[0]];
7f35cb09
GM
66
67/* Variables for transparent mode */
7f35cb09
GM
68
69#include "disp_asc.out"
70
71\f
7f35cb09
GM
72/* OurExitString - designed to keep us from going through infinite recursion */
73
74static void
75OurExitString(file, string, value)
76FILE *file;
77char *string;
78int value;
79{
80 static int recursion = 0;
81
82 if (!recursion) {
83 recursion = 1;
84 ExitString(file, string, value);
85 }
86}
87
88
7f35cb09
GM
89static void
90GoAway(from, where)
91char *from; /* routine that gave error */
92int where; /* cursor address */
93{
94 char foo[100];
95
96 sprintf(foo, "ERR from %s at %d (%d, %d)\n",
97 from, where, ScreenLine(where), ScreenLineOffset(where));
98 OurExitString(stderr, foo, 1);
99 /* NOTREACHED */
100}
101\f
da3205fa
GM
102/*
103 * Routines to deal with the screen. These routines are lifted
104 * from mskermit.
105 */
106
107#define CRT_STATUS 0x3da /* Color card */
108#define DISPLAY_ENABLE 0x08 /* Enable */
109#define scrseg() ((crt_mode == 7)? 0xb000 : 0xb800)
110#define scrwait() if (crt_mode != 7) { \
111 while ((inp(CRT_STATUS)&DISPLAY_ENABLE) == 0) { \
112 ; \
113 } \
114 }
115static int
116 crt_mode,
117 crt_cols,
118 crt_lins,
119 curpage;
120
121/*
122 * Set the cursor position to where it belongs.
123 */
124
125static void
126setcursor(row, column, page)
127int
128 row,
129 column,
130 page;
131{
132 union REGS inregs, outregs;
133
134 inregs.h.dh = row;
135 inregs.h.dl = column;
136 inregs.h.bh = page;
137 inregs.h.ah = SetCursorPosition;
138
139 int86(BIOS_VIDEO, &inregs, &outregs);
140}
141/*
142 * Read the state of the video system. Put the cursor somewhere
143 * reasonable.
144 */
145
146static void
147scrini()
148{
149 union REGS inregs, outregs;
150
151 inregs.h.ah = CurrentVideoState;
152 int86(BIOS_VIDEO, &inregs, &outregs);
153
154 crt_mode = outregs.h.al;
155 crt_cols = outregs.h.ah;
156 crt_lins = 25;
157 curpage = outregs.h.bh;
158
159 inregs.h.ah = ReadCursorPosition;
160 inregs.h.bh = curpage;
161
162 int86(BIOS_VIDEO, &inregs, &outregs);
163
164 if (outregs.h.dh > crt_lins) {
165 outregs.h.dh = crt_lins;
166 }
167 if (outregs.h.dl > crt_cols) {
168 outregs.h.dl = crt_cols;
169 }
170 inregs.h.dh = outregs.h.dh;
171 inregs.h.dl = outregs.h.dl;
172 inregs.h.bh = curpage;
173
174 inregs.h.ah = SetCursorPosition;
175 int86(BIOS_VIDEO, &inregs, &outregs);
176}
177
178
179static void
180scrwrite(source, length, offset)
181ScreenBuffer *source;
182int
183 length,
184 offset;
185{
186 struct SREGS segregs;
187
188 segread(&segregs); /* read the current segment register */
189
190 scrwait();
84f75426
GM
191 movedata(segregs.ds, source, scrseg(), sizeof *source*offset,
192 sizeof *source*length);
da3205fa
GM
193}
194
195static void
196scrsave(buffer)
197ScreenBuffer *buffer;
198{
199 struct SREGS segregs;
200
201 segread(&segregs); /* read the current segment register */
202
203 scrwait();
84f75426 204 movedata(scrseg(), 0, segregs.ds, buffer, crt_cols*crt_lins*2);
da3205fa
GM
205}
206
207static void
208scrrest(buffer)
209ScreenBuffer *buffer;
210{
84f75426 211 scrwrite(buffer, crt_cols*crt_lins, 0);
da3205fa
GM
212}
213\f
7f35cb09 214static void
98e793e6 215TryToSend()
7f35cb09 216{
84f75426 217#define STANDOUT 0x0a /* Highlighted mode */
98e793e6 218#define NORMAL 0x02 /* Normal mode */
84f75426
GM
219#define NONDISPLAY 0x00 /* Don't display */
220
221#define DoAttribute(a) \
222 if (screenIsFormatted) { \
223 if (IsNonDisplayAttr(a)) { \
224 a = NONDISPLAY; /* don't display */ \
225 } else if (IsHighlightedAttr(a)) { \
226 a = STANDOUT; \
227 } else { \
228 a = NORMAL; \
229 } \
230 } else { \
231 a = NORMAL; /* do display on unformatted */\
7f35cb09
GM
232 }
233 ScreenImage *p, *upper;
98e793e6 234 ScreenBuffer *sp;
7f35cb09 235 int fieldattr; /* spends most of its time == 0 or 1 */
84f75426 236 int screenIsFormatted = FormattedScreen();
7f35cb09
GM
237
238/* OK. We want to do this a quickly as possible. So, we assume we
239 * only need to go from Lowest to Highest. However, if we find a
240 * field in the middle, we do the whole screen.
241 *
242 * In particular, we separate out the two cases from the beginning.
243 */
244 if ((Highest != HighestScreen()) || (Lowest != LowestScreen())) {
98e793e6 245 sp = &Screen[Lowest];
7f35cb09 246 p = &Host[Lowest];
7f35cb09
GM
247 upper = &Host[Highest];
248 fieldattr = FieldAttributes(Lowest);
249 DoAttribute(fieldattr); /* Set standout, non-display status */
7f35cb09
GM
250
251 while (p <= upper) {
252 if (IsStartFieldPointer(p)) { /* New field? */
253 Highest = HighestScreen();
254 Lowest = LowestScreen();
98e793e6 255 TryToSend(); /* Recurse */
7f35cb09
GM
256 return;
257 } else if (fieldattr) { /* Should we display? */
84f75426
GM
258 /* Display translated data */
259 sp->data = disp_asc[GetHostPointer(p)];
7f35cb09 260 } else {
98e793e6 261 sp->data = ' ';
7f35cb09 262 }
84f75426 263 sp->attr = fieldattr;
7f35cb09 264 p++;
98e793e6 265 sp++;
7f35cb09
GM
266 }
267 } else { /* Going from Lowest to Highest */
98e793e6 268 ScreenImage *End = &Host[ScreenSize]-1;
7f35cb09 269
98e793e6 270 sp = Screen;
7f35cb09
GM
271 p = Host;
272 fieldattr = FieldAttributes(LowestScreen());
273 DoAttribute(fieldattr); /* Set standout, non-display status */
274
275 while (p <= End) {
276 if (IsStartFieldPointer(p)) { /* New field? */
7f35cb09
GM
277 fieldattr = FieldAttributesPointer(p); /* Get attributes */
278 DoAttribute(fieldattr); /* Set standout, non-display */
84f75426
GM
279 }
280 if (fieldattr) { /* Should we display? */
281 /* Display translated data */
282 sp->data = disp_asc[GetHostPointer(p)];
7f35cb09 283 } else {
84f75426 284 sp->data = ' ';
7f35cb09 285 }
84f75426 286 sp->attr = fieldattr;
7f35cb09 287 p++;
98e793e6 288 sp++;
7f35cb09
GM
289 }
290 }
98e793e6 291 terminalCursorAddress = CorrectTerminalCursor();
84f75426
GM
292 /*
293 * We might be here just to update the cursor address.
294 */
295 if (Highest >= Lowest) {
296 scrwrite(Screen+Lowest, (1+Highest-Lowest), Lowest);
297 }
da3205fa 298 setcursor(ScreenLine(terminalCursorAddress),
98e793e6 299 ScreenLineOffset(terminalCursorAddress), 0);
7f35cb09
GM
300 Lowest = HighestScreen()+1;
301 Highest = LowestScreen()-1;
7f35cb09 302 if (needToRing) {
98e793e6 303 DataToTerminal("\7", 1);
7f35cb09
GM
304 needToRing = 0;
305 }
7f35cb09
GM
306 return;
307}
7f35cb09
GM
308\f
309/* InitTerminal - called to initialize the screen, etc. */
310
311void
312InitTerminal()
313{
7f35cb09
GM
314 InitMapping(); /* Go do mapping file (MAP3270) first */
315 if (!screenInitd) { /* not initialized */
01929848
GM
316 MaxNumberLines = 24; /* XXX */
317 MaxNumberColumns = 80; /* XXX */
98e793e6 318 scrini();
da3205fa 319 scrsave(saveScreen); /* Save the screen buffer away */
98e793e6 320 ClearArray(Screen);
7f35cb09 321 terminalCursorAddress = SetBufferAddress(0,0);
7f35cb09
GM
322 screenInitd = 1;
323 screenStopped = 0; /* Not stopped */
324 }
325 Initialized = 1;
326}
327
328
329/* StopScreen - called when we are going away... */
330
331void
332StopScreen(doNewLine)
333int doNewLine;
334{
335 if (screenInitd && !screenStopped) {
da3205fa
GM
336 scrrest(saveScreen);
337 setcursor(NumberLines-1, NumberColumns-1, 0);
7f35cb09
GM
338 }
339}
340
341
342/* RefreshScreen - called to cause the screen to be refreshed */
343
344void
345RefreshScreen()
346{
98e793e6
GM
347 Highest = HighestScreen();
348 Lowest = LowestScreen();
349 TryToSend();
7f35cb09
GM
350}
351
352
353/* ConnectScreen - called to reconnect to the screen */
354
355void
356ConnectScreen()
357{
358 if (screenInitd) {
7f35cb09 359 RefreshScreen();
7f35cb09
GM
360 screenStopped = 0;
361 }
362}
363
364/* LocalClearScreen() - clear the whole ball of wax, cheaply */
365
366void
367LocalClearScreen()
368{
7f35cb09 369 Clear3270();
98e793e6
GM
370 Lowest = LowestScreen(); /* everything in sync... */
371 Highest = HighestScreen();
372 TryToSend();
7f35cb09 373}
98e793e6
GM
374\f
375/*
376 * Implement the bell/error message function.
377 */
378
379int
380 bellwinup = 0; /* If != 0, length of bell message */
381static int
382 bellpos0 = 0; /* Where error message goes */
383
384static char bellstring[100];/* Where message goes */
7f35cb09 385
98e793e6
GM
386#define BELL_SPACES 2 /* 2 spaces between border and bell */
387
388#define BELL_HIGH_LOW(h,l) { \
389 h = bellpos0+2*NumberColumns+bellwinup+BELL_SPACES*2; \
390 l = bellpos0; \
391 }
7f35cb09
GM
392
393void
394BellOff()
395{
396 if (bellwinup) {
98e793e6
GM
397 BELL_HIGH_LOW(Highest,Lowest);
398 TryToSend();
7f35cb09
GM
399 }
400}
401
402
403void
404RingBell(s)
405char *s;
406{
407 needToRing = 1;
408 if (s) {
409 int len = strlen(s);
410
98e793e6
GM
411 if (len > sizeof bellstring-1) {
412 OurExitString(stderr, "Bell string too long.", 1);
7f35cb09 413 }
98e793e6
GM
414 memcpy(bellstring, s, len+1);
415 BELL_HIGH_LOW(Highest,Lowest);
416 TryToSend();
7f35cb09
GM
417 }
418}
419\f
98e793e6
GM
420/*
421 * Update the OIA area.
422 */
423
424void
425ScreenOIA(oia)
426OIA *oia;
427{
428}
429\f
7f35cb09
GM
430
431/* returns a 1 if no more output available (so, go ahead and block),
432 or a 0 if there is more output available (so, just poll the other
433 sources/destinations, don't block).
434 */
435
436int
437DoTerminalOutput()
438{
439 /* called just before a select to conserve IO to terminal */
440 if (!Initialized) {
441 return 1; /* No output if not initialized */
442 }
443 if ((Lowest <= Highest) || needToRing ||
444 (terminalCursorAddress != CorrectTerminalCursor())) {
98e793e6 445 TryToSend();
7f35cb09
GM
446 }
447 if (Lowest > Highest) {
448 return 1; /* no more output now */
449 } else {
450 return 0; /* more output for future */
451 }
452}
453\f
454/*
455 * The following are defined to handle transparent data.
456 */
457
458void
459TransStop()
460{
7f35cb09
GM
461 RefreshScreen();
462}
463
464void
465TransOut(buffer, count)
466unsigned char *buffer;
467int count;
468{
7f35cb09
GM
469
470 while (DoTerminalOutput() == 0) {
98e793e6 471 ;
7f35cb09 472 }
7f35cb09
GM
473 (void) DataToTerminal(buffer, count);
474}
98e793e6
GM
475\f
476/*
477 * init_screen()
478 *
479 * Initialize variables used by screen.
480 */
7f35cb09 481
98e793e6
GM
482void
483init_screen()
7f35cb09 484{
98e793e6 485 bellwinup = 0;
7f35cb09 486}
98e793e6
GM
487
488