|
|
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.