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> 2831120Sminshall #include <dos.h> 2931185Sminshall #include "../general/general.h" 3031105Sminshall 3131105Sminshall #include "../telnet.ext" 3231105Sminshall 3331881Sminshall #include "../api/disp_asc.h" 3431225Sminshall #include "../ascii/map3270.ext" 3531225Sminshall 3631105Sminshall #include "../ctlr/hostctlr.h" 3731105Sminshall #include "../ctlr/inbound.ext" 3831117Sminshall #include "../ctlr/oia.h" 3931105Sminshall #include "../ctlr/options.ext" 4031105Sminshall #include "../ctlr/outbound.ext" 4131105Sminshall #include "../ctlr/screen.h" 4231105Sminshall 4331185Sminshall #include "../general/globals.h" 4431105Sminshall 4531120Sminshall #include "video.h" 4631120Sminshall 4731105Sminshall extern void EmptyTerminal(); 4831105Sminshall 4931105Sminshall #define CorrectTerminalCursor() ((TransparentClock == OutputClock)? \ 5031105Sminshall terminalCursorAddress:UnLocked? CursorAddress: HighestScreen()) 5131105Sminshall 5231105Sminshall 5331105Sminshall static int terminalCursorAddress; /* where the cursor is on term */ 5431105Sminshall static int screenInitd; /* the screen has been initialized */ 5531105Sminshall static int screenStopped; /* the screen has been stopped */ 5631105Sminshall 5731105Sminshall static int needToRing; /* need to ring terinal bell */ 5831105Sminshall 5931117Sminshall typedef struct { 6031117Sminshall char 6131117Sminshall data, /* The data for this position */ 6231117Sminshall attr; /* The attributes for this position */ 6331117Sminshall } ScreenBuffer; 6431105Sminshall 6531117Sminshall ScreenBuffer Screen[MAXNUMBERLINES*MAXNUMBERCOLUMNS]; 6631120Sminshall ScreenBuffer saveScreen[sizeof Screen/sizeof Screen[0]]; 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 9831120Sminshall /* 9931120Sminshall * Routines to deal with the screen. These routines are lifted 10031120Sminshall * from mskermit. 10131120Sminshall */ 10231120Sminshall 10331120Sminshall #define CRT_STATUS 0x3da /* Color card */ 10431120Sminshall #define DISPLAY_ENABLE 0x08 /* Enable */ 10531120Sminshall #define scrseg() ((crt_mode == 7)? 0xb000 : 0xb800) 10631120Sminshall #define scrwait() if (crt_mode != 7) { \ 10731120Sminshall while ((inp(CRT_STATUS)&DISPLAY_ENABLE) == 0) { \ 10831120Sminshall ; \ 10931120Sminshall } \ 11031120Sminshall } 11131120Sminshall static int 11231120Sminshall crt_mode, 11331120Sminshall crt_cols, 11431120Sminshall crt_lins, 11531120Sminshall curpage; 11631120Sminshall 11731120Sminshall /* 11831120Sminshall * Set the cursor position to where it belongs. 11931120Sminshall */ 12031120Sminshall 12131105Sminshall static void 12231120Sminshall setcursor(row, column, page) 12331120Sminshall int 12431120Sminshall row, 12531120Sminshall column, 12631120Sminshall page; 12731120Sminshall { 12831120Sminshall union REGS inregs, outregs; 12931120Sminshall 13031120Sminshall inregs.h.dh = row; 13131120Sminshall inregs.h.dl = column; 13231120Sminshall inregs.h.bh = page; 13331120Sminshall inregs.h.ah = SetCursorPosition; 13431120Sminshall 13531120Sminshall int86(BIOS_VIDEO, &inregs, &outregs); 13631120Sminshall } 13731120Sminshall /* 13831120Sminshall * Read the state of the video system. Put the cursor somewhere 13931120Sminshall * reasonable. 14031120Sminshall */ 14131120Sminshall 14231120Sminshall static void 14331120Sminshall scrini() 14431120Sminshall { 14531120Sminshall union REGS inregs, outregs; 14631120Sminshall 14731120Sminshall inregs.h.ah = CurrentVideoState; 14831120Sminshall int86(BIOS_VIDEO, &inregs, &outregs); 14931120Sminshall 15031120Sminshall crt_mode = outregs.h.al; 15131120Sminshall crt_cols = outregs.h.ah; 15231120Sminshall crt_lins = 25; 15331120Sminshall curpage = outregs.h.bh; 15431120Sminshall 15531120Sminshall inregs.h.ah = ReadCursorPosition; 15631120Sminshall inregs.h.bh = curpage; 15731120Sminshall 15831120Sminshall int86(BIOS_VIDEO, &inregs, &outregs); 15931120Sminshall 16031120Sminshall if (outregs.h.dh > crt_lins) { 16131120Sminshall outregs.h.dh = crt_lins; 16231120Sminshall } 16331120Sminshall if (outregs.h.dl > crt_cols) { 16431120Sminshall outregs.h.dl = crt_cols; 16531120Sminshall } 16631120Sminshall inregs.h.dh = outregs.h.dh; 16731120Sminshall inregs.h.dl = outregs.h.dl; 16831120Sminshall inregs.h.bh = curpage; 16931120Sminshall 17031120Sminshall inregs.h.ah = SetCursorPosition; 17131120Sminshall int86(BIOS_VIDEO, &inregs, &outregs); 17231120Sminshall } 17331120Sminshall 17431120Sminshall 17531120Sminshall static void 17631120Sminshall scrwrite(source, length, offset) 17731120Sminshall ScreenBuffer *source; 17831120Sminshall int 17931120Sminshall length, 18031120Sminshall offset; 18131120Sminshall { 18231120Sminshall struct SREGS segregs; 18331120Sminshall 18431120Sminshall segread(&segregs); /* read the current segment register */ 18531120Sminshall 18631120Sminshall scrwait(); 18731154Sminshall movedata(segregs.ds, source, scrseg(), sizeof *source*offset, 18831154Sminshall sizeof *source*length); 18931120Sminshall } 19031120Sminshall 19131120Sminshall static void 19231120Sminshall scrsave(buffer) 19331120Sminshall ScreenBuffer *buffer; 19431120Sminshall { 19531120Sminshall struct SREGS segregs; 19631120Sminshall 19731120Sminshall segread(&segregs); /* read the current segment register */ 19831120Sminshall 19931120Sminshall scrwait(); 20031154Sminshall movedata(scrseg(), 0, segregs.ds, buffer, crt_cols*crt_lins*2); 20131120Sminshall } 20231120Sminshall 20331120Sminshall static void 20431120Sminshall scrrest(buffer) 20531120Sminshall ScreenBuffer *buffer; 20631120Sminshall { 20731154Sminshall scrwrite(buffer, crt_cols*crt_lins, 0); 20831120Sminshall } 20931120Sminshall 21031120Sminshall static void 21131117Sminshall TryToSend() 21231105Sminshall { 21331154Sminshall #define STANDOUT 0x0a /* Highlighted mode */ 21431117Sminshall #define NORMAL 0x02 /* Normal mode */ 21531154Sminshall #define NONDISPLAY 0x00 /* Don't display */ 21631105Sminshall 21731154Sminshall #define DoAttribute(a) \ 21831154Sminshall if (screenIsFormatted) { \ 21931154Sminshall if (IsNonDisplayAttr(a)) { \ 22031154Sminshall a = NONDISPLAY; /* don't display */ \ 22131154Sminshall } else if (IsHighlightedAttr(a)) { \ 22231154Sminshall a = STANDOUT; \ 22331154Sminshall } else { \ 22431154Sminshall a = NORMAL; \ 22531154Sminshall } \ 22631154Sminshall } else { \ 22731154Sminshall a = NORMAL; /* do display on unformatted */\ 22831105Sminshall } 22931105Sminshall ScreenImage *p, *upper; 23031117Sminshall ScreenBuffer *sp; 23131105Sminshall int fieldattr; /* spends most of its time == 0 or 1 */ 23231154Sminshall int screenIsFormatted = FormattedScreen(); 23331105Sminshall 23431105Sminshall /* OK. We want to do this a quickly as possible. So, we assume we 23531105Sminshall * only need to go from Lowest to Highest. However, if we find a 23631105Sminshall * field in the middle, we do the whole screen. 23731105Sminshall * 23831105Sminshall * In particular, we separate out the two cases from the beginning. 23931105Sminshall */ 24031105Sminshall if ((Highest != HighestScreen()) || (Lowest != LowestScreen())) { 24131117Sminshall sp = &Screen[Lowest]; 24231105Sminshall p = &Host[Lowest]; 24331105Sminshall upper = &Host[Highest]; 24431105Sminshall fieldattr = FieldAttributes(Lowest); 24531105Sminshall DoAttribute(fieldattr); /* Set standout, non-display status */ 24631105Sminshall 24731105Sminshall while (p <= upper) { 24831105Sminshall if (IsStartFieldPointer(p)) { /* New field? */ 24931105Sminshall Highest = HighestScreen(); 25031105Sminshall Lowest = LowestScreen(); 25131117Sminshall TryToSend(); /* Recurse */ 25231105Sminshall return; 25331105Sminshall } else if (fieldattr) { /* Should we display? */ 25431154Sminshall /* Display translated data */ 25531154Sminshall sp->data = disp_asc[GetHostPointer(p)]; 25631105Sminshall } else { 25731117Sminshall sp->data = ' '; 25831105Sminshall } 25931154Sminshall sp->attr = fieldattr; 26031105Sminshall p++; 26131117Sminshall sp++; 26231105Sminshall } 26331105Sminshall } else { /* Going from Lowest to Highest */ 26431117Sminshall ScreenImage *End = &Host[ScreenSize]-1; 26531105Sminshall 26631117Sminshall sp = Screen; 26731105Sminshall p = Host; 26831105Sminshall fieldattr = FieldAttributes(LowestScreen()); 26931105Sminshall DoAttribute(fieldattr); /* Set standout, non-display status */ 27031105Sminshall 27131105Sminshall while (p <= End) { 27231105Sminshall if (IsStartFieldPointer(p)) { /* New field? */ 27331105Sminshall fieldattr = FieldAttributesPointer(p); /* Get attributes */ 27431105Sminshall DoAttribute(fieldattr); /* Set standout, non-display */ 27531154Sminshall } 27631154Sminshall if (fieldattr) { /* Should we display? */ 27731154Sminshall /* Display translated data */ 27831154Sminshall sp->data = disp_asc[GetHostPointer(p)]; 27931105Sminshall } else { 28031154Sminshall sp->data = ' '; 28131105Sminshall } 28231154Sminshall sp->attr = fieldattr; 28331105Sminshall p++; 28431117Sminshall sp++; 28531105Sminshall } 28631105Sminshall } 28731117Sminshall terminalCursorAddress = CorrectTerminalCursor(); 28831154Sminshall /* 28931154Sminshall * We might be here just to update the cursor address. 29031154Sminshall */ 29131154Sminshall if (Highest >= Lowest) { 29231154Sminshall scrwrite(Screen+Lowest, (1+Highest-Lowest), Lowest); 29331154Sminshall } 29431120Sminshall setcursor(ScreenLine(terminalCursorAddress), 29531117Sminshall ScreenLineOffset(terminalCursorAddress), 0); 29631105Sminshall Lowest = HighestScreen()+1; 29731105Sminshall Highest = LowestScreen()-1; 29831105Sminshall if (needToRing) { 29931117Sminshall DataToTerminal("\7", 1); 30031105Sminshall needToRing = 0; 30131105Sminshall } 30231105Sminshall return; 30331105Sminshall } 30431105Sminshall 30531105Sminshall /* InitTerminal - called to initialize the screen, etc. */ 30631105Sminshall 30731105Sminshall void 30831105Sminshall InitTerminal() 30931105Sminshall { 31031105Sminshall InitMapping(); /* Go do mapping file (MAP3270) first */ 31131105Sminshall if (!screenInitd) { /* not initialized */ 31231129Sminshall MaxNumberLines = 24; /* XXX */ 31331129Sminshall MaxNumberColumns = 80; /* XXX */ 31431117Sminshall scrini(); 31531120Sminshall scrsave(saveScreen); /* Save the screen buffer away */ 31631117Sminshall ClearArray(Screen); 31731105Sminshall terminalCursorAddress = SetBufferAddress(0,0); 31831105Sminshall screenInitd = 1; 31931105Sminshall screenStopped = 0; /* Not stopped */ 32031105Sminshall } 32131105Sminshall } 32231105Sminshall 32331105Sminshall 32431105Sminshall /* StopScreen - called when we are going away... */ 32531105Sminshall 32631105Sminshall void 32731105Sminshall StopScreen(doNewLine) 32831105Sminshall int doNewLine; 32931105Sminshall { 33031105Sminshall if (screenInitd && !screenStopped) { 33131120Sminshall scrrest(saveScreen); 33231208Sminshall setcursor(NumberLines-1, 1, 0); 33331208Sminshall if (doNewLine) { 33431208Sminshall StringToTerminal("\r\n"); 33531208Sminshall } 33631208Sminshall EmptyTerminal(); 33731208Sminshall screenStopped = 1; 33831105Sminshall } 33931105Sminshall } 34031105Sminshall 34131105Sminshall 34231105Sminshall /* RefreshScreen - called to cause the screen to be refreshed */ 34331105Sminshall 34431105Sminshall void 34531105Sminshall RefreshScreen() 34631105Sminshall { 34731117Sminshall Highest = HighestScreen(); 34831117Sminshall Lowest = LowestScreen(); 34931117Sminshall TryToSend(); 35031105Sminshall } 35131105Sminshall 35231105Sminshall 35331105Sminshall /* ConnectScreen - called to reconnect to the screen */ 35431105Sminshall 35531105Sminshall void 35631105Sminshall ConnectScreen() 35731105Sminshall { 35831105Sminshall if (screenInitd) { 35931105Sminshall RefreshScreen(); 36031105Sminshall screenStopped = 0; 36131105Sminshall } 36231105Sminshall } 36331105Sminshall 36431105Sminshall /* LocalClearScreen() - clear the whole ball of wax, cheaply */ 36531105Sminshall 36631105Sminshall void 36731105Sminshall LocalClearScreen() 36831105Sminshall { 36931105Sminshall Clear3270(); 37031117Sminshall Lowest = LowestScreen(); /* everything in sync... */ 37131117Sminshall Highest = HighestScreen(); 37231117Sminshall TryToSend(); 37331105Sminshall } 37431117Sminshall 37531117Sminshall /* 37631117Sminshall * Implement the bell/error message function. 37731117Sminshall */ 37831105Sminshall 37931117Sminshall int 38031117Sminshall bellwinup = 0; /* If != 0, length of bell message */ 38131117Sminshall static int 38231883Sminshall bell_len = 0; /* Length of error message */ 38331105Sminshall 38431117Sminshall 38531105Sminshall void 38631105Sminshall BellOff() 38731105Sminshall { 38831883Sminshall ScreenBuffer a[100]; 38931883Sminshall int i; 39031883Sminshall 39131105Sminshall if (bellwinup) { 39231883Sminshall unsigned char blank = ' '; 39331883Sminshall 39431883Sminshall for (i = 0; i < bell_len; i++) { 39531883Sminshall a[i].attr = NORMAL; 39631883Sminshall a[i].data = ' '; 39731883Sminshall } 39831105Sminshall } 39931883Sminshall scrwrite(a, bell_len, 24*80); /* XXX */ 40031105Sminshall } 40131105Sminshall 40231105Sminshall 40331105Sminshall void 40431105Sminshall RingBell(s) 40531105Sminshall char *s; 40631105Sminshall { 40731105Sminshall needToRing = 1; 40831105Sminshall if (s) { 40931883Sminshall int i; 41031883Sminshall ScreenBuffer bellstring[100]; 41131105Sminshall 41231883Sminshall bell_len = strlen(s); 41331883Sminshall bellwinup = 1; 41431883Sminshall if (bell_len > sizeof bellstring-1) { 41531117Sminshall OurExitString(stderr, "Bell string too long.", 1); 41631105Sminshall } 41731883Sminshall for (i = 0; i < bell_len; i++) { 41831883Sminshall bellstring[i].attr = STANDOUT; 41931883Sminshall bellstring[i].data = s[i]; 42031883Sminshall } 42131883Sminshall scrwrite(bellstring, bell_len, 24*80); /* XXX */ 42231105Sminshall } 42331105Sminshall } 42431105Sminshall 42531117Sminshall /* 42631117Sminshall * Update the OIA area. 42731117Sminshall */ 42831105Sminshall 42931117Sminshall void 43031117Sminshall ScreenOIA(oia) 43131117Sminshall OIA *oia; 43231117Sminshall { 43331117Sminshall } 43431117Sminshall 43531117Sminshall 43631105Sminshall /* returns a 1 if no more output available (so, go ahead and block), 43731105Sminshall or a 0 if there is more output available (so, just poll the other 43831105Sminshall sources/destinations, don't block). 43931105Sminshall */ 44031105Sminshall 44131105Sminshall int 44231105Sminshall DoTerminalOutput() 44331105Sminshall { 44431105Sminshall /* called just before a select to conserve IO to terminal */ 44531490Sminshall if (!(screenInitd||screenStopped)) { 44631105Sminshall return 1; /* No output if not initialized */ 44731105Sminshall } 44831105Sminshall if ((Lowest <= Highest) || needToRing || 44931105Sminshall (terminalCursorAddress != CorrectTerminalCursor())) { 45031117Sminshall TryToSend(); 45131105Sminshall } 45231105Sminshall if (Lowest > Highest) { 45331105Sminshall return 1; /* no more output now */ 45431105Sminshall } else { 45531105Sminshall return 0; /* more output for future */ 45631105Sminshall } 45731105Sminshall } 45831105Sminshall 45931105Sminshall /* 46031105Sminshall * The following are defined to handle transparent data. 46131105Sminshall */ 46231105Sminshall 46331105Sminshall void 46431105Sminshall TransStop() 46531105Sminshall { 46631105Sminshall RefreshScreen(); 46731105Sminshall } 46831105Sminshall 46931105Sminshall void 470*31885Sminshall TransOut(buffer, count, kind, control) 47131105Sminshall unsigned char *buffer; 47231105Sminshall int count; 473*31885Sminshall int kind; /* 0 or 5 */ 474*31885Sminshall int control; /* To see if we are done */ 47531105Sminshall { 476*31885Sminshall char *ptr; 47731105Sminshall 47831105Sminshall while (DoTerminalOutput() == 0) { 47931117Sminshall ; 48031105Sminshall } 481*31885Sminshall for (ptr = buffer; ptr < buffer+count; ptr++) { 482*31885Sminshall *ptr &= 0x7f; /* Turn off parity bit */ 483*31885Sminshall } 48431105Sminshall (void) DataToTerminal(buffer, count); 485*31885Sminshall if (control && (kind == 0)) { /* Send in AID byte */ 486*31885Sminshall SendToIBM(); 487*31885Sminshall } else { 488*31885Sminshall TransInput(1, kind); /* Go get some data */ 489*31885Sminshall } 49031105Sminshall } 49131117Sminshall 49231117Sminshall /* 49331117Sminshall * init_screen() 49431117Sminshall * 49531117Sminshall * Initialize variables used by screen. 49631117Sminshall */ 49731105Sminshall 49831117Sminshall void 49931117Sminshall init_screen() 50031105Sminshall { 50131117Sminshall bellwinup = 0; 50231117Sminshall } 50331105Sminshall 50431117Sminshall 505