Lint (and new copyrights).
[unix-history] / usr / src / usr.bin / tn3270 / distribution / sys_dos / termout.c
CommitLineData
7f35cb09 1/*
2d415723
KB
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
7f35cb09 4 *
2d415723 5 * Redistribution and use in source and binary forms are permitted
b36fc510
KB
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
7f35cb09
GM
16 */
17
18#ifndef lint
b36fc510 19static char sccsid[] = "@(#)termout.c 3.3 (Berkeley) %G%";
2d415723 20#endif /* not lint */
7f35cb09 21
7f35cb09 22#include <stdio.h>
da3205fa 23#include <dos.h>
f478095f 24#include "../general/general.h"
7f35cb09 25
7f35cb09
GM
26#include "../telnet.ext"
27
29d0babb 28#include "../api/disp_asc.h"
321beb6b
GM
29#include "../ascii/map3270.ext"
30
7f35cb09
GM
31#include "../ctlr/hostctlr.h"
32#include "../ctlr/inbound.ext"
98e793e6 33#include "../ctlr/oia.h"
7f35cb09
GM
34#include "../ctlr/options.ext"
35#include "../ctlr/outbound.ext"
36#include "../ctlr/screen.h"
37
f478095f 38#include "../general/globals.h"
7f35cb09 39
da3205fa
GM
40#include "video.h"
41
7f35cb09
GM
42extern void EmptyTerminal();
43
44#define CorrectTerminalCursor() ((TransparentClock == OutputClock)? \
45 terminalCursorAddress:UnLocked? CursorAddress: HighestScreen())
46
47
48static int terminalCursorAddress; /* where the cursor is on term */
49static int screenInitd; /* the screen has been initialized */
50static int screenStopped; /* the screen has been stopped */
7f35cb09
GM
51
52static int needToRing; /* need to ring terinal bell */
7f35cb09 53
98e793e6
GM
54typedef struct {
55 char
56 data, /* The data for this position */
57 attr; /* The attributes for this position */
58} ScreenBuffer;
7f35cb09 59
98e793e6 60ScreenBuffer Screen[MAXNUMBERLINES*MAXNUMBERCOLUMNS];
da3205fa 61ScreenBuffer saveScreen[sizeof Screen/sizeof Screen[0]];
7f35cb09 62\f
7f35cb09
GM
63/* OurExitString - designed to keep us from going through infinite recursion */
64
65static void
66OurExitString(file, string, value)
67FILE *file;
68char *string;
69int value;
70{
71 static int recursion = 0;
72
73 if (!recursion) {
74 recursion = 1;
75 ExitString(file, string, value);
76 }
77}
78
79
7f35cb09
GM
80static void
81GoAway(from, where)
82char *from; /* routine that gave error */
83int where; /* cursor address */
84{
85 char foo[100];
86
87 sprintf(foo, "ERR from %s at %d (%d, %d)\n",
88 from, where, ScreenLine(where), ScreenLineOffset(where));
89 OurExitString(stderr, foo, 1);
90 /* NOTREACHED */
91}
92\f
da3205fa
GM
93/*
94 * Routines to deal with the screen. These routines are lifted
95 * from mskermit.
96 */
97
98#define CRT_STATUS 0x3da /* Color card */
99#define DISPLAY_ENABLE 0x08 /* Enable */
100#define scrseg() ((crt_mode == 7)? 0xb000 : 0xb800)
101#define scrwait() if (crt_mode != 7) { \
102 while ((inp(CRT_STATUS)&DISPLAY_ENABLE) == 0) { \
103 ; \
104 } \
105 }
106static int
107 crt_mode,
108 crt_cols,
109 crt_lins,
110 curpage;
111
112/*
113 * Set the cursor position to where it belongs.
114 */
115
116static void
117setcursor(row, column, page)
118int
119 row,
120 column,
121 page;
122{
123 union REGS inregs, outregs;
124
125 inregs.h.dh = row;
126 inregs.h.dl = column;
127 inregs.h.bh = page;
128 inregs.h.ah = SetCursorPosition;
129
130 int86(BIOS_VIDEO, &inregs, &outregs);
131}
132/*
133 * Read the state of the video system. Put the cursor somewhere
134 * reasonable.
135 */
136
137static void
138scrini()
139{
140 union REGS inregs, outregs;
141
142 inregs.h.ah = CurrentVideoState;
143 int86(BIOS_VIDEO, &inregs, &outregs);
144
145 crt_mode = outregs.h.al;
146 crt_cols = outregs.h.ah;
147 crt_lins = 25;
148 curpage = outregs.h.bh;
149
150 inregs.h.ah = ReadCursorPosition;
151 inregs.h.bh = curpage;
152
153 int86(BIOS_VIDEO, &inregs, &outregs);
154
155 if (outregs.h.dh > crt_lins) {
156 outregs.h.dh = crt_lins;
157 }
158 if (outregs.h.dl > crt_cols) {
159 outregs.h.dl = crt_cols;
160 }
161 inregs.h.dh = outregs.h.dh;
162 inregs.h.dl = outregs.h.dl;
163 inregs.h.bh = curpage;
164
165 inregs.h.ah = SetCursorPosition;
166 int86(BIOS_VIDEO, &inregs, &outregs);
167}
168
169
170static void
171scrwrite(source, length, offset)
172ScreenBuffer *source;
173int
174 length,
175 offset;
176{
177 struct SREGS segregs;
178
179 segread(&segregs); /* read the current segment register */
180
181 scrwait();
84f75426
GM
182 movedata(segregs.ds, source, scrseg(), sizeof *source*offset,
183 sizeof *source*length);
da3205fa
GM
184}
185
186static void
187scrsave(buffer)
188ScreenBuffer *buffer;
189{
190 struct SREGS segregs;
191
192 segread(&segregs); /* read the current segment register */
193
194 scrwait();
84f75426 195 movedata(scrseg(), 0, segregs.ds, buffer, crt_cols*crt_lins*2);
da3205fa
GM
196}
197
198static void
199scrrest(buffer)
200ScreenBuffer *buffer;
201{
84f75426 202 scrwrite(buffer, crt_cols*crt_lins, 0);
da3205fa
GM
203}
204\f
7f35cb09 205static void
98e793e6 206TryToSend()
7f35cb09 207{
84f75426 208#define STANDOUT 0x0a /* Highlighted mode */
98e793e6 209#define NORMAL 0x02 /* Normal mode */
84f75426
GM
210#define NONDISPLAY 0x00 /* Don't display */
211
212#define DoAttribute(a) \
213 if (screenIsFormatted) { \
214 if (IsNonDisplayAttr(a)) { \
215 a = NONDISPLAY; /* don't display */ \
216 } else if (IsHighlightedAttr(a)) { \
217 a = STANDOUT; \
218 } else { \
219 a = NORMAL; \
220 } \
221 } else { \
222 a = NORMAL; /* do display on unformatted */\
7f35cb09
GM
223 }
224 ScreenImage *p, *upper;
98e793e6 225 ScreenBuffer *sp;
7f35cb09 226 int fieldattr; /* spends most of its time == 0 or 1 */
84f75426 227 int screenIsFormatted = FormattedScreen();
7f35cb09
GM
228
229/* OK. We want to do this a quickly as possible. So, we assume we
230 * only need to go from Lowest to Highest. However, if we find a
231 * field in the middle, we do the whole screen.
232 *
233 * In particular, we separate out the two cases from the beginning.
234 */
235 if ((Highest != HighestScreen()) || (Lowest != LowestScreen())) {
98e793e6 236 sp = &Screen[Lowest];
7f35cb09 237 p = &Host[Lowest];
7f35cb09
GM
238 upper = &Host[Highest];
239 fieldattr = FieldAttributes(Lowest);
240 DoAttribute(fieldattr); /* Set standout, non-display status */
7f35cb09
GM
241
242 while (p <= upper) {
243 if (IsStartFieldPointer(p)) { /* New field? */
244 Highest = HighestScreen();
245 Lowest = LowestScreen();
98e793e6 246 TryToSend(); /* Recurse */
7f35cb09
GM
247 return;
248 } else if (fieldattr) { /* Should we display? */
84f75426
GM
249 /* Display translated data */
250 sp->data = disp_asc[GetHostPointer(p)];
7f35cb09 251 } else {
98e793e6 252 sp->data = ' ';
7f35cb09 253 }
84f75426 254 sp->attr = fieldattr;
7f35cb09 255 p++;
98e793e6 256 sp++;
7f35cb09
GM
257 }
258 } else { /* Going from Lowest to Highest */
98e793e6 259 ScreenImage *End = &Host[ScreenSize]-1;
7f35cb09 260
98e793e6 261 sp = Screen;
7f35cb09
GM
262 p = Host;
263 fieldattr = FieldAttributes(LowestScreen());
264 DoAttribute(fieldattr); /* Set standout, non-display status */
265
266 while (p <= End) {
267 if (IsStartFieldPointer(p)) { /* New field? */
7f35cb09
GM
268 fieldattr = FieldAttributesPointer(p); /* Get attributes */
269 DoAttribute(fieldattr); /* Set standout, non-display */
84f75426
GM
270 }
271 if (fieldattr) { /* Should we display? */
272 /* Display translated data */
273 sp->data = disp_asc[GetHostPointer(p)];
7f35cb09 274 } else {
84f75426 275 sp->data = ' ';
7f35cb09 276 }
84f75426 277 sp->attr = fieldattr;
7f35cb09 278 p++;
98e793e6 279 sp++;
7f35cb09
GM
280 }
281 }
98e793e6 282 terminalCursorAddress = CorrectTerminalCursor();
84f75426
GM
283 /*
284 * We might be here just to update the cursor address.
285 */
286 if (Highest >= Lowest) {
287 scrwrite(Screen+Lowest, (1+Highest-Lowest), Lowest);
288 }
da3205fa 289 setcursor(ScreenLine(terminalCursorAddress),
98e793e6 290 ScreenLineOffset(terminalCursorAddress), 0);
7f35cb09
GM
291 Lowest = HighestScreen()+1;
292 Highest = LowestScreen()-1;
7f35cb09 293 if (needToRing) {
98e793e6 294 DataToTerminal("\7", 1);
7f35cb09
GM
295 needToRing = 0;
296 }
7f35cb09
GM
297 return;
298}
7f35cb09
GM
299\f
300/* InitTerminal - called to initialize the screen, etc. */
301
302void
303InitTerminal()
304{
7f35cb09
GM
305 InitMapping(); /* Go do mapping file (MAP3270) first */
306 if (!screenInitd) { /* not initialized */
01929848
GM
307 MaxNumberLines = 24; /* XXX */
308 MaxNumberColumns = 80; /* XXX */
98e793e6 309 scrini();
da3205fa 310 scrsave(saveScreen); /* Save the screen buffer away */
98e793e6 311 ClearArray(Screen);
7f35cb09 312 terminalCursorAddress = SetBufferAddress(0,0);
7f35cb09
GM
313 screenInitd = 1;
314 screenStopped = 0; /* Not stopped */
315 }
7f35cb09
GM
316}
317
318
319/* StopScreen - called when we are going away... */
320
321void
322StopScreen(doNewLine)
323int doNewLine;
324{
325 if (screenInitd && !screenStopped) {
da3205fa 326 scrrest(saveScreen);
6d444e60
GM
327 setcursor(NumberLines-1, 1, 0);
328 if (doNewLine) {
329 StringToTerminal("\r\n");
330 }
331 EmptyTerminal();
332 screenStopped = 1;
7f35cb09
GM
333 }
334}
335
336
337/* RefreshScreen - called to cause the screen to be refreshed */
338
339void
340RefreshScreen()
341{
98e793e6
GM
342 Highest = HighestScreen();
343 Lowest = LowestScreen();
344 TryToSend();
7f35cb09
GM
345}
346
347
348/* ConnectScreen - called to reconnect to the screen */
349
350void
351ConnectScreen()
352{
353 if (screenInitd) {
7f35cb09 354 RefreshScreen();
7f35cb09
GM
355 screenStopped = 0;
356 }
357}
358
359/* LocalClearScreen() - clear the whole ball of wax, cheaply */
360
361void
362LocalClearScreen()
363{
7f35cb09 364 Clear3270();
98e793e6
GM
365 Lowest = LowestScreen(); /* everything in sync... */
366 Highest = HighestScreen();
367 TryToSend();
7f35cb09 368}
98e793e6
GM
369\f
370/*
371 * Implement the bell/error message function.
372 */
373
374int
375 bellwinup = 0; /* If != 0, length of bell message */
376static int
9da6eef6 377 bell_len = 0; /* Length of error message */
98e793e6 378
7f35cb09
GM
379
380void
381BellOff()
382{
9da6eef6
GM
383 ScreenBuffer a[100];
384 int i;
385
7f35cb09 386 if (bellwinup) {
9da6eef6
GM
387 unsigned char blank = ' ';
388
389 for (i = 0; i < bell_len; i++) {
390 a[i].attr = NORMAL;
391 a[i].data = ' ';
392 }
7f35cb09 393 }
9da6eef6 394 scrwrite(a, bell_len, 24*80); /* XXX */
7f35cb09
GM
395}
396
397
398void
399RingBell(s)
400char *s;
401{
402 needToRing = 1;
403 if (s) {
9da6eef6
GM
404 int i;
405 ScreenBuffer bellstring[100];
7f35cb09 406
9da6eef6
GM
407 bell_len = strlen(s);
408 bellwinup = 1;
409 if (bell_len > sizeof bellstring-1) {
98e793e6 410 OurExitString(stderr, "Bell string too long.", 1);
7f35cb09 411 }
9da6eef6
GM
412 for (i = 0; i < bell_len; i++) {
413 bellstring[i].attr = STANDOUT;
414 bellstring[i].data = s[i];
415 }
416 scrwrite(bellstring, bell_len, 24*80); /* XXX */
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 */
1b911685 440 if (!(screenInitd||screenStopped)) {
7f35cb09
GM
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
24f81074 465TransOut(buffer, count, kind, control)
7f35cb09
GM
466unsigned char *buffer;
467int count;
24f81074
GM
468int kind; /* 0 or 5 */
469int control; /* To see if we are done */
7f35cb09 470{
24f81074 471 char *ptr;
7f35cb09
GM
472
473 while (DoTerminalOutput() == 0) {
98e793e6 474 ;
7f35cb09 475 }
24f81074
GM
476 for (ptr = buffer; ptr < buffer+count; ptr++) {
477 *ptr &= 0x7f; /* Turn off parity bit */
478 }
7f35cb09 479 (void) DataToTerminal(buffer, count);
24f81074
GM
480 if (control && (kind == 0)) { /* Send in AID byte */
481 SendToIBM();
482 } else {
483 TransInput(1, kind); /* Go get some data */
484 }
7f35cb09 485}
98e793e6
GM
486\f
487/*
488 * init_screen()
489 *
490 * Initialize variables used by screen.
491 */
7f35cb09 492
98e793e6
GM
493void
494init_screen()
7f35cb09 495{
98e793e6 496 bellwinup = 0;
7f35cb09 497}
98e793e6
GM
498
499