Add a null ScreenOIA() routine.
[unix-history] / usr / src / usr.bin / tn3270 / sys_curses / termout.c
CommitLineData
d4c3b068
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
27#if defined(unix)
28#include <signal.h>
29#include <sgtty.h>
30#endif
31#include <stdio.h>
32#include <curses.h>
33
d4ee8ee5
GM
34#include "../general.h"
35
d4c3b068
GM
36#include "terminal.h"
37
38#include "../telnet.ext"
39
40#include "../ctlr/hostctlr.h"
41#include "../ctlr/inbound.ext"
4b3aebcc 42#include "../ctlr/oia.h"
d4c3b068
GM
43#include "../ctlr/options.ext"
44#include "../ctlr/outbound.ext"
45#include "../ctlr/screen.h"
46
47#include "../keyboard/map3270.ext"
48
49#include "../system/globals.h"
50
51extern void EmptyTerminal();
52
53#define CorrectTerminalCursor() ((TransparentClock == OutputClock)? \
54 terminalCursorAddress:UnLocked? CursorAddress: HighestScreen())
55
56
7e6a2e47
GM
57static int terminalCursorAddress; /* where the cursor is on term */
58static int screenInitd; /* the screen has been initialized */
59static int screenStopped; /* the screen has been stopped */
d4c3b068
GM
60#if defined(SLOWSCREEN)
61static int max_changes_before_poll; /* how many characters before looking */
62 /* at terminal and net again */
63#endif /* defined(SLOWSCREEN) */
64
7e6a2e47 65static int needToRing; /* need to ring terinal bell */
d4c3b068
GM
66static char *bellSequence = "\07"; /* bell sequence (may be replaced by
67 * VB during initialization)
68 */
7e6a2e47 69static WINDOW *bellwin = 0; /* The window the bell message is in */
d4c3b068
GM
70int bellwinup = 0; /* Are we up with it or not */
71
72#if defined(unix)
73static char *KS, *KE;
74#endif /* defined(unix) */
75
7e74e688
GM
76
77#if defined(SLOWSCREEN)
78static int inHighlightMode = 0;
d4ee8ee5 79ScreenImage Terminal[MAXSCREENSIZE];
7e74e688
GM
80#endif /* defined(SLOWSCREEN) */
81
82/* Variables for transparent mode */
d4c3b068
GM
83#if defined(unix)
84static int tcflag = -1; /* transparent mode command flag */
85static int savefd[2]; /* for storing fds during transcom */
7e74e688 86extern int tin, tout; /* file descriptors */
d4c3b068
GM
87#endif /* defined(unix) */
88
d4c3b068
GM
89
90#include "disp_asc.out"
91
92\f
19003317
GM
93
94/*
95 * init_screen()
96 *
97 * Initialize variables used by screen.
98 */
99
100void
101init_screen()
102{
103 bellwinup = 0;
104#if defined(SLOWSCREEN)
105 inHighlightMode = 0;
d4ee8ee5 106 ClearArray(Terminal);
19003317
GM
107#endif /* defined(SLOWSCREEN) */
108}
109
110
d4c3b068
GM
111/* OurExitString - designed to keep us from going through infinite recursion */
112
113static void
114OurExitString(file, string, value)
115FILE *file;
116char *string;
117int value;
118{
119 static int recursion = 0;
120
121 if (!recursion) {
122 recursion = 1;
123 ExitString(file, string, value);
124 }
125}
126
127
128/* DoARefresh */
129
130static void
131DoARefresh()
132{
133 if (ERR == refresh()) {
134 OurExitString(stderr, "ERR from refresh\n", 1);
135 }
136}
137
138static void
139GoAway(from, where)
140char *from; /* routine that gave error */
141int where; /* cursor address */
142{
143 char foo[100];
144
145 sprintf(foo, "ERR from %s at %d (%d, %d)\n",
146 from, where, ScreenLine(where), ScreenLineOffset(where));
147 OurExitString(stderr, foo, 1);
148 /* NOTREACHED */
149}
150\f
151#if defined(SLOWSCREEN)
152/* What is the screen address of the attribute byte for the terminal */
153
154static int
155WhereTermAttrByte(p)
156register int p;
157{
158 register int i;
159
160 i = p;
161
162 do {
163 if (TermIsStartField(i)) {
164 return(i);
165 }
166 i = ScreenDec(i);
167 } while (i != p);
168
169 return(LowestScreen()); /* unformatted screen... */
170}
171#endif /* defined(SLOWSCREEN) */
172\f
173/*
174 * There are two algorithms for updating the screen.
175 * The first, SlowScreen() optimizes the line between the
176 * computer and the screen (say a 9600 baud line). To do
177 * this, we break out of the loop every so often to look
178 * at any pending input from the network (so that successive
179 * screens will only partially print until the final screen,
180 * the one the user possibly wants to see, is displayed
181 * in its entirety).
182 *
183 * The second algorithm tries to optimize CPU time (by
184 * being simpler) at the cost of the bandwidth to the
185 * screen.
186 *
187 * Of course, curses(3X) gets in here also.
188 */
189
190
191#if defined(SLOWSCREEN)
192#if defined(NOT43)
193static int
194#else /* defined(NOT43) */
195static void
196#endif /* defined(NOT43) */
197SlowScreen()
198{
199 register int pointer;
200 register int c;
201 register int fieldattr;
202 register int columnsleft;
203
204# define SetHighlightMode(p) { \
205 if (!IsStartField(p) && IsHighlightedAttr(fieldattr)) { \
206 if (!inHighlightMode) { \
207 inHighlightMode = 1; \
208 standout(); \
209 } \
210 } else { \
211 if (inHighlightMode) { \
212 inHighlightMode = 0; \
213 standend(); \
214 } \
215 } \
216 }
217
218# define DoCharacterAt(c,p) { \
219 SetTerminal(p, c); \
220 if (p != HighestScreen()) { \
221 c = TerminalCharacterAttr(disp_asc[c&0xff], p, \
222 fieldattr); \
223 if (terminalCursorAddress != p) { \
224 if (ERR == mvaddch(ScreenLine(p), \
225 ScreenLineOffset(p), c)) {\
226 GoAway("mvaddch", p); \
227 } \
228 } else { \
229 if (ERR == addch(c)) {\
230 GoAway("addch", p); \
231 } \
232 } \
233 terminalCursorAddress = ScreenInc(p); \
234 } \
235 }
236
237
238 /* run through screen, printing out non-null lines */
239
240 /* There are two separate reasons for wanting to terminate this
241 * loop early. One is to respond to new input (either from
242 * the terminal or from the network [host]). For this reason,
243 * we expect to see 'HaveInput' come true when new input comes in.
244 *
245 * The second reason is a bit more difficult (for me) to understand.
246 * Basically, we don't want to get too far ahead of the characters that
247 * appear on the screen. Ideally, we would type out a few characters,
248 * wait until they appeared on the screen, then type out a few more.
249 * The reason for this is that the user, on seeing some characters
250 * appear on the screen may then start to type something. We would
251 * like to look at what the user types at about the same 'time'
252 * (measured by characters being sent to the terminal) that the
253 * user types them. For this reason, what we would like to do
254 * is update a bit, then call curses to do a refresh, flush the
255 * output to the terminal, then wait until the terminal data
256 * has been sent.
257 *
258 * Note that curses is useful for, among other things, deciding whether
259 * or not to send :ce: (clear to end of line), so we should call curses
260 * at end of lines (beginning of next lines).
261 *
262 * The problems here are the following: If we do lots of write(2)s,
263 * we will be doing lots of context switches, thus lots of overhead
264 * (which we have already). Second, if we do a select to wait for
265 * the output to drain, we have to contend with the fact that NOW
266 * we are scheduled to run, but who knows what the scheduler will
267 * decide when the output has caught up.
268 */
269
270 if (Highest == HighestScreen()) {
271 Highest = ScreenDec(Highest); /* else, while loop will never end */
272 }
273 if (Lowest < LowestScreen()) {
274 Lowest = LowestScreen(); /* could be -1 in some cases with
275 * unformatted screens.
276 */
277 }
278 if (Highest >= (pointer = Lowest)) {
279 /* if there is anything to do, do it. We won't terminate
280 * the loop until we've gone at least to Highest.
281 */
282 while ((pointer <= Highest) && !HaveInput) {
283
284 /* point at the next place of disagreement */
285 pointer += (bunequal(Host+pointer, Terminal+pointer,
286 (Highest-pointer+1)*sizeof Host[0])/sizeof Host[0]);
287
288 /* how many characters to change until the end of the
289 * current line
290 */
291 columnsleft = NumberColumns - ScreenLineOffset(pointer);
292 /*
293 * Make sure we are where we think we are.
294 */
295 move(ScreenLine(pointer), ScreenLineOffset(pointer));
296
297 /* what is the field attribute of the current position */
298 fieldattr = FieldAttributes(WhereAttrByte(pointer));
299
300 if ((IsStartField(pointer) != TermIsStartField(pointer)) ||
301 (IsStartField(pointer) &&
302 fieldattr != TermAttributes(pointer))) {
303
304 int oldterm;
305
306 oldterm = TermAttributes(pointer);
307 if (IsStartField(pointer)) {
308 TermNewField(pointer, fieldattr);
309 SetTerminal(pointer, 0);
310 } else {
311 TermDeleteField(pointer);
312 }
313 /* We always do the first character in a divergent
314 * field, since otherwise the start of a field in
315 * the Host structure may leave a highlighted blank
316 * on the screen, and the start of a field in the
317 * Terminal structure may leave a non-highlighted
318 * something in the middle of a highlighted field
319 * on the screen.
320 */
321 SetHighlightMode(pointer);
322 c = GetHost(pointer);
323 DoCharacterAt(c,pointer); /* MACRO */
324
325 if (NotVisuallyCompatibleAttributes
326 (pointer, fieldattr, oldterm)) {
327 int j;
328
329 j = pointer;
330
331 pointer = ScreenInc(pointer);
332 if (!(--columnsleft)) {
333 DoARefresh();
334 EmptyTerminal();
335 move(ScreenLine(pointer), 0);
336 columnsleft = NumberColumns;
337 }
338 SetHighlightMode(pointer); /* Turn on highlighting */
339 while (!IsStartField(pointer) &&
340 !TermIsStartField(pointer)) {
341 c = GetHost(pointer);
342 DoCharacterAt(c,pointer); /* MACRO */
343 pointer = ScreenInc(pointer);
344 if (!(--columnsleft)) {
345 DoARefresh();
346 EmptyTerminal();
347 move(ScreenLine(pointer), 0);
348 columnsleft = NumberColumns;
349 /* We don't look at HaveInput here, since
350 * if we leave this loop before the end of
351 * the 3270 field, we could have pointer
352 * higher than Highest. This would cause
353 * us to end the highest "while" loop,
354 * but we may, in fact, need to go around the
355 * screen once again.
356 */
357 }
358 /* The loop needs to be protected
359 * from the situation where there had been only
360 * one field on the Terminal, and none on the Host.
361 * In this case, we have just deleted our last
362 * field. Hence, the break.
363 */
364 if (j == pointer) {
365 break;
366 }
367 }
368 if (IsStartField(pointer) && !TermIsStartField(pointer)) {
369 /* Remember what the terminal looked like */
370 TermNewField(pointer, oldterm);
371 /*
372 * The danger here is that the current position may
373 * be the start of a Host field. If so, and the
374 * field is highlighted, and our terminal was
375 * highlighted, then we will leave a highlighted
376 * blank at this position.
377 */
378 SetHighlightMode(pointer);
379 c = GetHost(pointer);
380 DoCharacterAt(c,pointer);
381 }
382 /* We could be in the situation of needing to exit.
383 * This could happen if the current field wrapped around
384 * the end of the screen.
385 */
386 if (j > pointer) {
387 break;
388 }
389 } else {
390 c = GetHost(pointer);
391 /* We always do the first character in a divergent
392 * field, since otherwise the start of a field in
393 * the Host structure may leave a highlighted blank
394 * on the screen, and the start of a field in the
395 * Terminal structure may leave a non-highlighted
396 * something in the middle of a highlighted field
397 * on the screen.
398 */
399 SetHighlightMode(pointer);
400 DoCharacterAt(c,pointer);
401 }
402 } else {
403 SetHighlightMode(pointer);
a06dcafb
GM
404 /*
405 * The following will terminate at least when we get back
d4c3b068
GM
406 * to the original 'pointer' location (since we force
407 * things to be equal).
408 */
409 while (((c = GetHost(pointer)) != GetTerminal(pointer)) &&
410 !IsStartField(pointer) && !TermIsStartField(pointer)) {
411 DoCharacterAt(c, pointer);
412 pointer = ScreenInc(pointer);
413 if (!(--columnsleft)) {
414 DoARefresh();
415 EmptyTerminal();
416 if (HaveInput) { /* if input came in, take it */
417 break;
418 }
419 move(ScreenLine(pointer), 0);
420 columnsleft = NumberColumns;
421 }
422 }
423 }
424 }
425 }
426 DoARefresh();
427 Lowest = pointer;
428 if (Lowest > Highest) { /* if we finished input... */
429 Lowest = HighestScreen()+1;
430 Highest = LowestScreen()-1;
431 terminalCursorAddress = CorrectTerminalCursor();
432 if (ERR == move(ScreenLine(terminalCursorAddress),
433 ScreenLineOffset(terminalCursorAddress))) {
434 GoAway("move", terminalCursorAddress);
435 }
436 DoARefresh();
437 if (needToRing) {
438 StringToTerminal(bellSequence);
439 needToRing = 0;
440 }
441 }
442 EmptyTerminal(); /* move data along */
443 return;
444}
445#endif /* defined(SLOWSCREEN) */
446\f
447#if defined(NOT43)
448static int
449#else /* defined(NOT43) */
450static void
451#endif /* defined(NOT43) */
452FastScreen()
453{
335e9f60 454#if defined(MSDOS)
d4c3b068 455#define SaveCorner 0
335e9f60 456#else /* defined(MSDOS) */
d4c3b068 457#define SaveCorner 1
335e9f60 458#endif /* defined(MSDOS) */
d4c3b068
GM
459
460#define DoAttribute(a) if (IsHighlightedAttr(a)) { \
461 standout(); \
462 } else { \
463 standend(); \
464 } \
465 if (IsNonDisplayAttr(a)) { \
466 a = 0; /* zero == don't display */ \
467 } \
468 if (!FormattedScreen()) { \
469 a = 1; /* one ==> do display on unformatted */\
470 }
471 ScreenImage *p, *upper;
472 int fieldattr; /* spends most of its time == 0 or 1 */
473
474/* OK. We want to do this a quickly as possible. So, we assume we
475 * only need to go from Lowest to Highest. However, if we find a
476 * field in the middle, we do the whole screen.
477 *
478 * In particular, we separate out the two cases from the beginning.
479 */
480 if ((Highest != HighestScreen()) || (Lowest != LowestScreen())) {
481 register int columnsleft;
482
483 move(ScreenLine(Lowest), ScreenLineOffset(Lowest));
484 p = &Host[Lowest];
335e9f60 485#if !defined(MSDOS)
d4c3b068
GM
486 if (Highest == HighestScreen()) {
487 Highest = ScreenDec(Highest);
488 }
335e9f60 489#endif /* !defined(MSDOS) */
d4c3b068
GM
490 upper = &Host[Highest];
491 fieldattr = FieldAttributes(Lowest);
492 DoAttribute(fieldattr); /* Set standout, non-display status */
493 columnsleft = NumberColumns-ScreenLineOffset(p-Host);
494
495 while (p <= upper) {
a06dcafb 496 if (IsStartFieldPointer(p)) { /* New field? */
d4c3b068
GM
497 Highest = HighestScreen();
498 Lowest = LowestScreen();
499 FastScreen(); /* Recurse */
500 return;
501 } else if (fieldattr) { /* Should we display? */
502 addch(disp_asc[p->data]); /* Display translated data */
503 } else {
504 addch(' '); /* Display a blank */
505 }
506 /* If the physical screen is larger than what we
507 * are using, we need to make sure that each line
508 * starts at the beginning of the line. Otherwise,
509 * we will just string all the lines together.
510 */
511 p++;
512 if (--columnsleft == 0) {
513 int i = p-Host;
514
515 move(ScreenLine(i), 0);
516 columnsleft = NumberColumns;
517 }
518 }
519 } else { /* Going from Lowest to Highest */
520 unsigned char tmpbuf[MAXNUMBERCOLUMNS+1];
521 ScreenImage *End = &Host[ScreenSize]-1-SaveCorner;
522 register unsigned char *tmp = tmpbuf, *tmpend = tmpbuf+NumberColumns;
523
524 *tmpend = 0; /* terminate from the beginning */
525 move(0,0);
526 p = Host;
527 fieldattr = FieldAttributes(LowestScreen());
528 DoAttribute(fieldattr); /* Set standout, non-display status */
529
530 while (p <= End) {
a06dcafb 531 if (IsStartFieldPointer(p)) { /* New field? */
d4c3b068
GM
532 if (tmp != tmpbuf) {
533 *tmp++ = 0; /* close out */
534 addstr(tmpbuf);
535 tmp = tmpbuf;
536 tmpend = tmpbuf + NumberColumns - ScreenLineOffset(p-Host);
537 }
a06dcafb 538 fieldattr = FieldAttributesPointer(p); /* Get attributes */
d4c3b068
GM
539 DoAttribute(fieldattr); /* Set standout, non-display */
540 *tmp++ = ' ';
541 } else {
542 if (fieldattr) { /* Should we display? */
543 /* Display translated data */
544 *tmp++ = disp_asc[p->data];
545 } else {
546 *tmp++ = ' ';
547 }
548 }
549 /* If the physical screen is larger than what we
550 * are using, we need to make sure that each line
551 * starts at the beginning of the line. Otherwise,
552 * we will just string all the lines together.
553 */
554 p++;
555 if (tmp == tmpend) {
556 int i = p-Host; /* Be sure the "p++" happened first! */
557
558 *tmp++ = 0;
559 addstr(tmpbuf);
560 tmp = tmpbuf;
561 move(ScreenLine(i), 0);
562 tmpend = tmpbuf + NumberColumns;
563 }
564 }
565 if (tmp != tmpbuf) {
566 *tmp++ = 0;
567 addstr(tmpbuf);
568 tmp = tmpbuf;
569 }
570 }
571 Lowest = HighestScreen()+1;
572 Highest = LowestScreen()-1;
573 terminalCursorAddress = CorrectTerminalCursor();
574 if (ERR == move(ScreenLine(terminalCursorAddress),
575 ScreenLineOffset(terminalCursorAddress))) {
576 GoAway("move", terminalCursorAddress);
577 }
578 DoARefresh();
579 if (needToRing) {
580 StringToTerminal(bellSequence);
581 needToRing = 0;
582 }
583 EmptyTerminal(); /* move data along */
584 return;
585}
586
587
588/* TryToSend - send data out to user's terminal */
589
590#if defined(NOT43)
591int
592#else /* defined(NOT43) */
593void
594#endif /* defined(NOT43) */
595 (*TryToSend)() = FastScreen;
596\f
4b3aebcc
GM
597void
598ScreenOIA(oia)
599OIA *oia;
600{
601}
602
603
7e6a2e47 604/* InitTerminal - called to initialize the screen, etc. */
d4c3b068
GM
605
606void
7e6a2e47 607InitTerminal()
d4c3b068
GM
608{
609#if defined(unix)
610 struct sgttyb ourttyb;
611 static int speeds[] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800,
612 2400, 4800, 9600 };
613#endif
614
7e6a2e47 615 InitMapping(); /* Go do mapping file (MAP3270) first */
d4c3b068
GM
616 if (!screenInitd) { /* not initialized */
617#if defined(unix)
618 char KSEbuffer[2050];
619 char *lotsofspace = KSEbuffer;
620 extern int abort();
621 extern char *tgetstr();
622#endif /* defined(unix) */
623
d4c3b068 624#if defined(SLOWSCREEN)
335e9f60 625 ClearArray(Terminal);
d4c3b068 626#endif /* defined(SLOWSCREEN) */
7e6a2e47 627 terminalCursorAddress = SetBufferAddress(0,0);
d4c3b068
GM
628#if defined(unix)
629 signal(SIGHUP, abort);
630#endif
631
632 TryToSend = FastScreen;
633#if defined(unix) && defined(SLOWSCREEN)
634 ioctl(1, TIOCGETP, (char *) &ourttyb);
635 if ((ourttyb.sg_ospeed < 0) || (ourttyb.sg_ospeed > B9600)) {
636 max_changes_before_poll = 1920;
637 } else {
638 max_changes_before_poll = speeds[ourttyb.sg_ospeed]/10;
639 if (max_changes_before_poll < 40) {
640 max_changes_before_poll = 40;
641 }
642 TryToSend = SlowScreen;
643 HaveInput = 1; /* get signals going */
644 }
645#endif /* defined(unix) && defined(SLOWSCREEN) */
646 setcommandmode();
647 /*
648 * By now, initscr() (in curses) has been called (from telnet.c),
649 * and the screen has been initialized.
650 */
651#if defined(unix)
652 nonl();
653 /* the problem is that curses catches SIGTSTP to
654 * be nice, but it messes us up.
655 */
656 signal(SIGTSTP, SIG_DFL);
657 if ((KS = tgetstr("ks", &lotsofspace)) != 0) {
658 KS = strsave(KS);
659 StringToTerminal(KS);
660 }
661 if ((KE = tgetstr("ke", &lotsofspace)) != 0) {
662 KE = strsave(KE);
663 }
664 if (tgetstr("md", &lotsofspace) && tgetstr("me", &lotsofspace)) {
665 SO = strsave(tgetstr("md", &lotsofspace));
666 SE = strsave(tgetstr("me", &lotsofspace));
667 }
668#endif
669 DoARefresh();
670 setconnmode();
671 if (VB && *VB) {
672 bellSequence = VB; /* use visual bell */
673 }
674 screenInitd = 1;
675 screenStopped = 0; /* Not stopped */
676 }
7e6a2e47 677 Initialized = 1;
d4c3b068
GM
678}
679
680
681/* StopScreen - called when we are going away... */
682
683void
684StopScreen(doNewLine)
685int doNewLine;
686{
687 if (screenInitd && !screenStopped) {
688 move(NumberLines-1, 1);
689 standend();
690#if defined(SLOWSCREEN)
691 inHighlightMode = 0;
692#endif /* defined(SLOWSCREEN) */
693 DoARefresh();
694 setcommandmode();
695 endwin();
696 setconnmode();
697#if defined(unix)
698 if (KE) {
699 StringToTerminal(KE);
700 }
701#endif /* defined(unix) */
702 if (doNewLine) {
703 StringToTerminal("\r\n");
704 }
705 EmptyTerminal();
706 screenStopped = 1; /* This is stopped */
707 }
708}
709
710
711/* RefreshScreen - called to cause the screen to be refreshed */
712
713void
714RefreshScreen()
715{
716 clearok(curscr, TRUE);
717 (*TryToSend)();
718}
719
720
721/* ConnectScreen - called to reconnect to the screen */
722
723void
724ConnectScreen()
725{
726 if (screenInitd) {
727#if defined(unix)
728 if (KS) {
729 StringToTerminal(KS);
730 }
731#endif /* defined(unix) */
732 RefreshScreen();
733 (*TryToSend)();
734 screenStopped = 0;
735 }
736}
737
738/* LocalClearScreen() - clear the whole ball of wax, cheaply */
739
740void
741LocalClearScreen()
742{
743 outputPurge(); /* flush all data to terminal */
744 clear(); /* clear in curses */
745#if defined(SLOWSCREEN)
335e9f60 746 ClearArray(Terminal);
d4c3b068
GM
747#endif /* defined(SLOWSCREEN) */
748 Clear3270();
749 Lowest = HighestScreen()+1; /* everything in sync... */
750 Highest = LowestScreen()+1;
751}
752
753
754void
755BellOff()
756{
757 if (bellwinup) {
758 delwin(bellwin);
759 bellwin = 0;
760 bellwinup = 0;
761 Lowest = MIN(Lowest, LINES/2);
762 Highest = MAX(Highest, (LINES/2)+3);
763#if defined(SLOWSCREEN)
335e9f60 764 memset(Terminal+LINES/2, 0, (sizeof Terminal[0])*(3*COLS));
d4c3b068
GM
765#endif /* defined(SLOWSCREEN) */
766 touchwin(stdscr);
767 DoARefresh();
768 }
769}
770
771
772void
773RingBell(s)
774char *s;
775{
776 needToRing = 1;
777 if (s) {
778 int len = strlen(s);
779
780 if (len > COLS-2) {
781 len = COLS-2;
782 }
783 if ((bellwin = newwin(3, len+2, LINES/2, 0)) == NULL) {
784 OurExitString(stderr, "Error from newwin in RingBell", 1);
785 }
786 werase(bellwin);
787 wstandout(bellwin);
788 box(bellwin, '|', '-');
789 if (wmove(bellwin, 1, 1) == ERR) {
790 OurExitString(stderr, "Error from wmove in RingBell", 1);
791 }
792 while (len--) {
793 if (waddch(bellwin, *s++) == ERR) {
794 OurExitString(stderr, "Error from waddch in RingBell", 1);
795 }
796 }
797 wstandend(bellwin);
798 if (wrefresh(bellwin) == ERR) {
799 OurExitString(stderr, "Error from wrefresh in RingBell", 1);
800 }
801 bellwinup = 1;
802 }
803}
804\f
805
806/* returns a 1 if no more output available (so, go ahead and block),
807 or a 0 if there is more output available (so, just poll the other
808 sources/destinations, don't block).
809 */
810
811int
812DoTerminalOutput()
813{
814 /* called just before a select to conserve IO to terminal */
f7aa2cfa
GM
815 if (!Initialized) {
816 return 1; /* No output if not initialized */
817 }
818 if ((Lowest <= Highest) || needToRing ||
819 (terminalCursorAddress != CorrectTerminalCursor())) {
d4c3b068
GM
820 (*TryToSend)();
821 }
822 if (Lowest > Highest) {
f7aa2cfa 823 return 1; /* no more output now */
d4c3b068 824 } else {
f7aa2cfa 825 return 0; /* more output for future */
d4c3b068
GM
826 }
827}
7e74e688
GM
828\f
829/*
830 * The following are defined to handle transparent data.
831 */
832
833void
834TransStop()
835{
836#if defined(unix)
837 if (tcflag == 0) {
838 tcflag = -1;
839 (void) signal(SIGCHLD, SIG_DFL);
840 } else if (tcflag > 0) {
841 setcommandmode();
842 (void) close(tin);
843 (void) close(tout);
844 tin = savefd[0];
845 tout = savefd[1];
846 setconnmode();
847 tcflag = -1;
848 (void) signal(SIGCHLD, SIG_DFL);
849 }
850#endif /* defined(unix) */
851 RefreshScreen();
852}
853
854void
855TransOut(buffer, count)
856unsigned char *buffer;
857int count;
858{
859#if defined(unix)
860 extern char *transcom;
861 int inpipefd[2], outpipefd[2], savemode;
862 void aborttc();
863#endif /* defined(unix) */
864
865 while (DoTerminalOutput() == 0) {
866#if defined(unix)
867 HaveInput = 0;
868#endif /* defined(unix) */
869 }
870#if defined(unix)
871 if (transcom && tcflag == -1) {
872 while (1) { /* go thru once */
873 if (pipe(outpipefd) < 0) {
874 break;
875 }
876 if (pipe(inpipefd) < 0) {
877 break;
878 }
879 if ((tcflag = fork()) == 0) {
880 (void) close(outpipefd[1]);
881 (void) close(0);
882 if (dup(outpipefd[0]) < 0) {
883 exit(1);
884 }
885 (void) close(outpipefd[0]);
886 (void) close(inpipefd[0]);
887 (void) close(1);
888 if (dup(inpipefd[1]) < 0) {
889 exit(1);
890 }
891 (void) close(inpipefd[1]);
892 if (execl("/bin/csh", "csh", "-c", transcom, (char *) 0)) {
893 exit(1);
894 }
895 }
896 (void) close(inpipefd[1]);
897 (void) close(outpipefd[0]);
898 savefd[0] = tin;
899 savefd[1] = tout;
900 setcommandmode();
901 tin = inpipefd[0];
902 tout = outpipefd[1];
903 (void) signal(SIGCHLD, aborttc);
904 setconnmode();
905 tcflag = 1;
906 break;
907 }
908 if (tcflag < 1) {
909 tcflag = 0;
910 }
911 }
912#endif /* defined(unix) */
913 (void) DataToTerminal(buffer, count);
914}
915
916
917#if defined(unix)
918static void
919aborttc()
920{
921 int savemode;
922
923 setcommandmode();
924 (void) close(tin);
925 (void) close(tout);
926 tin = savefd[0];
927 tout = savefd[1];
928 setconnmode();
929 tcflag = 0;
930}
931#endif /* defined(unix) */