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