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