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