131105Sminshall /* 231105Sminshall * Copyright (c) 1984, 1985, 1986 by the Regents of the 331105Sminshall * University of California and by Gregory Glenn Minshall. 431105Sminshall * 531105Sminshall * Permission to use, copy, modify, and distribute these 631105Sminshall * programs and their documentation for any purpose and 731105Sminshall * without fee is hereby granted, provided that this 831105Sminshall * copyright and permission appear on all copies and 931105Sminshall * supporting documentation, the name of the Regents of 1031105Sminshall * the University of California not be used in advertising 1131105Sminshall * or publicity pertaining to distribution of the programs 1231105Sminshall * without specific prior permission, and notice be given in 1331105Sminshall * supporting documentation that copying and distribution is 1431105Sminshall * by permission of the Regents of the University of California 1531105Sminshall * and by Gregory Glenn Minshall. Neither the Regents of the 1631105Sminshall * University of California nor Gregory Glenn Minshall make 1731105Sminshall * representations about the suitability of this software 1831105Sminshall * for any purpose. It is provided "as is" without 1931105Sminshall * express or implied warranty. 2031105Sminshall */ 2131105Sminshall 2231105Sminshall #ifndef lint 2331105Sminshall static char sccsid[] = "@(#)outbound.c 3.1 10/29/86"; 2431105Sminshall #endif /* lint */ 2531105Sminshall 2631105Sminshall 2731105Sminshall #include <stdio.h> 2831105Sminshall #include "../general.h" 2931105Sminshall 3031105Sminshall #include "../telnet.ext" 3131105Sminshall 3231105Sminshall #include "../ctlr/hostctlr.h" 3331105Sminshall #include "../ctlr/inbound.ext" 34*31117Sminshall #include "../ctlr/oia.h" 3531105Sminshall #include "../ctlr/options.ext" 3631105Sminshall #include "../ctlr/outbound.ext" 3731105Sminshall #include "../ctlr/screen.h" 3831105Sminshall 3931105Sminshall #include "../keyboard/map3270.ext" 4031105Sminshall 4131105Sminshall #include "../system/globals.h" 4231105Sminshall 4331105Sminshall extern void EmptyTerminal(); 4431105Sminshall 4531105Sminshall #define CorrectTerminalCursor() ((TransparentClock == OutputClock)? \ 4631105Sminshall terminalCursorAddress:UnLocked? CursorAddress: HighestScreen()) 4731105Sminshall 4831105Sminshall 4931105Sminshall static int terminalCursorAddress; /* where the cursor is on term */ 5031105Sminshall static int screenInitd; /* the screen has been initialized */ 5131105Sminshall static int screenStopped; /* the screen has been stopped */ 5231105Sminshall 5331105Sminshall static int needToRing; /* need to ring terinal bell */ 5431105Sminshall 55*31117Sminshall typedef struct { 56*31117Sminshall char 57*31117Sminshall data, /* The data for this position */ 58*31117Sminshall attr; /* The attributes for this position */ 59*31117Sminshall } ScreenBuffer; 6031105Sminshall 61*31117Sminshall ScreenBuffer Screen[MAXNUMBERLINES*MAXNUMBERCOLUMNS]; 6231105Sminshall 6331105Sminshall /* Variables for transparent mode */ 6431105Sminshall 6531105Sminshall #include "disp_asc.out" 6631105Sminshall 6731105Sminshall 6831105Sminshall /* OurExitString - designed to keep us from going through infinite recursion */ 6931105Sminshall 7031105Sminshall static void 7131105Sminshall OurExitString(file, string, value) 7231105Sminshall FILE *file; 7331105Sminshall char *string; 7431105Sminshall int value; 7531105Sminshall { 7631105Sminshall static int recursion = 0; 7731105Sminshall 7831105Sminshall if (!recursion) { 7931105Sminshall recursion = 1; 8031105Sminshall ExitString(file, string, value); 8131105Sminshall } 8231105Sminshall } 8331105Sminshall 8431105Sminshall 8531105Sminshall static void 8631105Sminshall GoAway(from, where) 8731105Sminshall char *from; /* routine that gave error */ 8831105Sminshall int where; /* cursor address */ 8931105Sminshall { 9031105Sminshall char foo[100]; 9131105Sminshall 9231105Sminshall sprintf(foo, "ERR from %s at %d (%d, %d)\n", 9331105Sminshall from, where, ScreenLine(where), ScreenLineOffset(where)); 9431105Sminshall OurExitString(stderr, foo, 1); 9531105Sminshall /* NOTREACHED */ 9631105Sminshall } 9731105Sminshall 9831105Sminshall static void 99*31117Sminshall TryToSend() 10031105Sminshall { 101*31117Sminshall #define STANDOUT 0x0a 102*31117Sminshall #define NORMAL 0x02 /* Normal mode */ 10331105Sminshall 10431105Sminshall #define DoAttribute(a) if (IsHighlightedAttr(a)) { \ 105*31117Sminshall a = STANDOUT; \ 10631105Sminshall } else { \ 107*31117Sminshall a = NORMAL; \ 10831105Sminshall } \ 10931105Sminshall if (IsNonDisplayAttr(a)) { \ 11031105Sminshall a = 0; /* zero == don't display */ \ 11131105Sminshall } \ 11231105Sminshall if (!FormattedScreen()) { \ 11331105Sminshall a = 1; /* one ==> do display on unformatted */\ 11431105Sminshall } 11531105Sminshall ScreenImage *p, *upper; 116*31117Sminshall ScreenBuffer *sp; 11731105Sminshall int fieldattr; /* spends most of its time == 0 or 1 */ 11831105Sminshall 11931105Sminshall /* OK. We want to do this a quickly as possible. So, we assume we 12031105Sminshall * only need to go from Lowest to Highest. However, if we find a 12131105Sminshall * field in the middle, we do the whole screen. 12231105Sminshall * 12331105Sminshall * In particular, we separate out the two cases from the beginning. 12431105Sminshall */ 12531105Sminshall if ((Highest != HighestScreen()) || (Lowest != LowestScreen())) { 12631105Sminshall register int columnsleft; 12731105Sminshall 128*31117Sminshall sp = &Screen[Lowest]; 12931105Sminshall p = &Host[Lowest]; 13031105Sminshall upper = &Host[Highest]; 13131105Sminshall fieldattr = FieldAttributes(Lowest); 13231105Sminshall DoAttribute(fieldattr); /* Set standout, non-display status */ 13331105Sminshall columnsleft = NumberColumns-ScreenLineOffset(p-Host); 13431105Sminshall 13531105Sminshall while (p <= upper) { 13631105Sminshall if (IsStartFieldPointer(p)) { /* New field? */ 13731105Sminshall Highest = HighestScreen(); 13831105Sminshall Lowest = LowestScreen(); 139*31117Sminshall TryToSend(); /* Recurse */ 14031105Sminshall return; 14131105Sminshall } else if (fieldattr) { /* Should we display? */ 142*31117Sminshall sp->data = disp_asc[p->data]; /* Display translated data */ 143*31117Sminshall sp->attr = fieldattr; 14431105Sminshall } else { 145*31117Sminshall sp->data = ' '; 146*31117Sminshall sp->attr = NORMAL; 14731105Sminshall } 14831105Sminshall /* If the physical screen is larger than what we 14931105Sminshall * are using, we need to make sure that each line 15031105Sminshall * starts at the beginning of the line. Otherwise, 15131105Sminshall * we will just string all the lines together. 15231105Sminshall */ 15331105Sminshall p++; 154*31117Sminshall sp++; 15531105Sminshall } 15631105Sminshall } else { /* Going from Lowest to Highest */ 157*31117Sminshall ScreenImage *End = &Host[ScreenSize]-1; 15831105Sminshall 159*31117Sminshall sp = Screen; 16031105Sminshall p = Host; 16131105Sminshall fieldattr = FieldAttributes(LowestScreen()); 16231105Sminshall DoAttribute(fieldattr); /* Set standout, non-display status */ 16331105Sminshall 16431105Sminshall while (p <= End) { 16531105Sminshall if (IsStartFieldPointer(p)) { /* New field? */ 16631105Sminshall fieldattr = FieldAttributesPointer(p); /* Get attributes */ 16731105Sminshall DoAttribute(fieldattr); /* Set standout, non-display */ 16831105Sminshall } else { 16931105Sminshall if (fieldattr) { /* Should we display? */ 17031105Sminshall /* Display translated data */ 171*31117Sminshall sp->data = disp_asc[p->data]; 172*31117Sminshall sp->attr = fieldattr; 17331105Sminshall } else { 174*31117Sminshall sp->data = ' '; 175*31117Sminshall sp->attr = NORMAL; 17631105Sminshall } 17731105Sminshall } 17831105Sminshall /* If the physical screen is larger than what we 17931105Sminshall * are using, we need to make sure that each line 18031105Sminshall * starts at the beginning of the line. Otherwise, 18131105Sminshall * we will just string all the lines together. 18231105Sminshall */ 18331105Sminshall p++; 184*31117Sminshall sp++; 18531105Sminshall } 18631105Sminshall } 187*31117Sminshall terminalCursorAddress = CorrectTerminalCursor(); 188*31117Sminshall scrwrite(Screen+Lowest, sizeof Screen[0]*(Highest-Lowest), Lowest); 189*31117Sminshall VideoSetCursorPosition(ScreenLine(terminalCursorAddress), 190*31117Sminshall ScreenLineOffset(terminalCursorAddress), 0); 19131105Sminshall Lowest = HighestScreen()+1; 19231105Sminshall Highest = LowestScreen()-1; 19331105Sminshall if (needToRing) { 194*31117Sminshall DataToTerminal("\7", 1); 19531105Sminshall needToRing = 0; 19631105Sminshall } 19731105Sminshall return; 19831105Sminshall } 19931105Sminshall 20031105Sminshall /* InitTerminal - called to initialize the screen, etc. */ 20131105Sminshall 20231105Sminshall void 20331105Sminshall InitTerminal() 20431105Sminshall { 20531105Sminshall InitMapping(); /* Go do mapping file (MAP3270) first */ 20631105Sminshall if (!screenInitd) { /* not initialized */ 207*31117Sminshall NumberLines = 24; /* XXX */ 208*31117Sminshall NumberColumns = 80; /* XXX */ 209*31117Sminshall scrini(); 210*31117Sminshall savescr(); /* Save the screen buffer away */ 211*31117Sminshall ClearArray(Screen); 21231105Sminshall terminalCursorAddress = SetBufferAddress(0,0); 21331105Sminshall screenInitd = 1; 21431105Sminshall screenStopped = 0; /* Not stopped */ 21531105Sminshall } 21631105Sminshall Initialized = 1; 21731105Sminshall } 21831105Sminshall 21931105Sminshall 22031105Sminshall /* StopScreen - called when we are going away... */ 22131105Sminshall 22231105Sminshall void 22331105Sminshall StopScreen(doNewLine) 22431105Sminshall int doNewLine; 22531105Sminshall { 22631105Sminshall if (screenInitd && !screenStopped) { 227*31117Sminshall scrrest(); 228*31117Sminshall VideoSetCursorPosition(NumberLines-1, NumberColumns-1, 0); 22931105Sminshall } 23031105Sminshall } 23131105Sminshall 23231105Sminshall 23331105Sminshall /* RefreshScreen - called to cause the screen to be refreshed */ 23431105Sminshall 23531105Sminshall void 23631105Sminshall RefreshScreen() 23731105Sminshall { 238*31117Sminshall Highest = HighestScreen(); 239*31117Sminshall Lowest = LowestScreen(); 240*31117Sminshall TryToSend(); 24131105Sminshall } 24231105Sminshall 24331105Sminshall 24431105Sminshall /* ConnectScreen - called to reconnect to the screen */ 24531105Sminshall 24631105Sminshall void 24731105Sminshall ConnectScreen() 24831105Sminshall { 24931105Sminshall if (screenInitd) { 25031105Sminshall RefreshScreen(); 25131105Sminshall screenStopped = 0; 25231105Sminshall } 25331105Sminshall } 25431105Sminshall 25531105Sminshall /* LocalClearScreen() - clear the whole ball of wax, cheaply */ 25631105Sminshall 25731105Sminshall void 25831105Sminshall LocalClearScreen() 25931105Sminshall { 26031105Sminshall Clear3270(); 261*31117Sminshall Lowest = LowestScreen(); /* everything in sync... */ 262*31117Sminshall Highest = HighestScreen(); 263*31117Sminshall TryToSend(); 26431105Sminshall } 265*31117Sminshall 266*31117Sminshall /* 267*31117Sminshall * Implement the bell/error message function. 268*31117Sminshall */ 26931105Sminshall 270*31117Sminshall int 271*31117Sminshall bellwinup = 0; /* If != 0, length of bell message */ 272*31117Sminshall static int 273*31117Sminshall bellpos0 = 0; /* Where error message goes */ 27431105Sminshall 275*31117Sminshall static char bellstring[100];/* Where message goes */ 276*31117Sminshall 277*31117Sminshall #define BELL_SPACES 2 /* 2 spaces between border and bell */ 278*31117Sminshall 279*31117Sminshall #define BELL_HIGH_LOW(h,l) { \ 280*31117Sminshall h = bellpos0+2*NumberColumns+bellwinup+BELL_SPACES*2; \ 281*31117Sminshall l = bellpos0; \ 282*31117Sminshall } 283*31117Sminshall 28431105Sminshall void 28531105Sminshall BellOff() 28631105Sminshall { 28731105Sminshall if (bellwinup) { 288*31117Sminshall BELL_HIGH_LOW(Highest,Lowest); 289*31117Sminshall TryToSend(); 29031105Sminshall } 29131105Sminshall } 29231105Sminshall 29331105Sminshall 29431105Sminshall void 29531105Sminshall RingBell(s) 29631105Sminshall char *s; 29731105Sminshall { 29831105Sminshall needToRing = 1; 29931105Sminshall if (s) { 30031105Sminshall int len = strlen(s); 30131105Sminshall 302*31117Sminshall if (len > sizeof bellstring-1) { 303*31117Sminshall OurExitString(stderr, "Bell string too long.", 1); 30431105Sminshall } 305*31117Sminshall memcpy(bellstring, s, len+1); 306*31117Sminshall BELL_HIGH_LOW(Highest,Lowest); 307*31117Sminshall TryToSend(); 30831105Sminshall } 30931105Sminshall } 31031105Sminshall 311*31117Sminshall /* 312*31117Sminshall * Update the OIA area. 313*31117Sminshall */ 31431105Sminshall 315*31117Sminshall void 316*31117Sminshall ScreenOIA(oia) 317*31117Sminshall OIA *oia; 318*31117Sminshall { 319*31117Sminshall } 320*31117Sminshall 321*31117Sminshall 32231105Sminshall /* returns a 1 if no more output available (so, go ahead and block), 32331105Sminshall or a 0 if there is more output available (so, just poll the other 32431105Sminshall sources/destinations, don't block). 32531105Sminshall */ 32631105Sminshall 32731105Sminshall int 32831105Sminshall DoTerminalOutput() 32931105Sminshall { 33031105Sminshall /* called just before a select to conserve IO to terminal */ 33131105Sminshall if (!Initialized) { 33231105Sminshall return 1; /* No output if not initialized */ 33331105Sminshall } 33431105Sminshall if ((Lowest <= Highest) || needToRing || 33531105Sminshall (terminalCursorAddress != CorrectTerminalCursor())) { 336*31117Sminshall TryToSend(); 33731105Sminshall } 33831105Sminshall if (Lowest > Highest) { 33931105Sminshall return 1; /* no more output now */ 34031105Sminshall } else { 34131105Sminshall return 0; /* more output for future */ 34231105Sminshall } 34331105Sminshall } 34431105Sminshall 34531105Sminshall /* 34631105Sminshall * The following are defined to handle transparent data. 34731105Sminshall */ 34831105Sminshall 34931105Sminshall void 35031105Sminshall TransStop() 35131105Sminshall { 35231105Sminshall RefreshScreen(); 35331105Sminshall } 35431105Sminshall 35531105Sminshall void 35631105Sminshall TransOut(buffer, count) 35731105Sminshall unsigned char *buffer; 35831105Sminshall int count; 35931105Sminshall { 36031105Sminshall 36131105Sminshall while (DoTerminalOutput() == 0) { 362*31117Sminshall ; 36331105Sminshall } 36431105Sminshall (void) DataToTerminal(buffer, count); 36531105Sminshall } 366*31117Sminshall 367*31117Sminshall /* 368*31117Sminshall * init_screen() 369*31117Sminshall * 370*31117Sminshall * Initialize variables used by screen. 371*31117Sminshall */ 37231105Sminshall 373*31117Sminshall void 374*31117Sminshall init_screen() 37531105Sminshall { 376*31117Sminshall bellwinup = 0; 377*31117Sminshall } 37831105Sminshall 379*31117Sminshall 380