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> 2931105Sminshall #include "../general.h" 3031105Sminshall 3131105Sminshall #include "../telnet.ext" 3231105Sminshall 3331105Sminshall #include "../ctlr/hostctlr.h" 3431105Sminshall #include "../ctlr/inbound.ext" 3531117Sminshall #include "../ctlr/oia.h" 3631105Sminshall #include "../ctlr/options.ext" 3731105Sminshall #include "../ctlr/outbound.ext" 3831105Sminshall #include "../ctlr/screen.h" 3931105Sminshall 4031105Sminshall #include "../keyboard/map3270.ext" 4131105Sminshall 4231105Sminshall #include "../system/globals.h" 4331105Sminshall 4431120Sminshall #include "video.h" 4531120Sminshall 4631105Sminshall extern void EmptyTerminal(); 4731105Sminshall 4831105Sminshall #define CorrectTerminalCursor() ((TransparentClock == OutputClock)? \ 4931105Sminshall terminalCursorAddress:UnLocked? CursorAddress: HighestScreen()) 5031105Sminshall 5131105Sminshall 5231105Sminshall static int terminalCursorAddress; /* where the cursor is on term */ 5331105Sminshall static int screenInitd; /* the screen has been initialized */ 5431105Sminshall static int screenStopped; /* the screen has been stopped */ 5531105Sminshall 5631105Sminshall static int needToRing; /* need to ring terinal bell */ 5731105Sminshall 5831117Sminshall typedef struct { 5931117Sminshall char 6031117Sminshall data, /* The data for this position */ 6131117Sminshall attr; /* The attributes for this position */ 6231117Sminshall } ScreenBuffer; 6331105Sminshall 6431117Sminshall ScreenBuffer Screen[MAXNUMBERLINES*MAXNUMBERCOLUMNS]; 6531120Sminshall ScreenBuffer saveScreen[sizeof Screen/sizeof Screen[0]]; 6631105Sminshall 6731105Sminshall /* Variables for transparent mode */ 6831105Sminshall 6931105Sminshall #include "disp_asc.out" 7031105Sminshall 7131105Sminshall 7231105Sminshall /* OurExitString - designed to keep us from going through infinite recursion */ 7331105Sminshall 7431105Sminshall static void 7531105Sminshall OurExitString(file, string, value) 7631105Sminshall FILE *file; 7731105Sminshall char *string; 7831105Sminshall int value; 7931105Sminshall { 8031105Sminshall static int recursion = 0; 8131105Sminshall 8231105Sminshall if (!recursion) { 8331105Sminshall recursion = 1; 8431105Sminshall ExitString(file, string, value); 8531105Sminshall } 8631105Sminshall } 8731105Sminshall 8831105Sminshall 8931105Sminshall static void 9031105Sminshall GoAway(from, where) 9131105Sminshall char *from; /* routine that gave error */ 9231105Sminshall int where; /* cursor address */ 9331105Sminshall { 9431105Sminshall char foo[100]; 9531105Sminshall 9631105Sminshall sprintf(foo, "ERR from %s at %d (%d, %d)\n", 9731105Sminshall from, where, ScreenLine(where), ScreenLineOffset(where)); 9831105Sminshall OurExitString(stderr, foo, 1); 9931105Sminshall /* NOTREACHED */ 10031105Sminshall } 10131105Sminshall 10231120Sminshall /* 10331120Sminshall * Routines to deal with the screen. These routines are lifted 10431120Sminshall * from mskermit. 10531120Sminshall */ 10631120Sminshall 10731120Sminshall #define CRT_STATUS 0x3da /* Color card */ 10831120Sminshall #define DISPLAY_ENABLE 0x08 /* Enable */ 10931120Sminshall #define scrseg() ((crt_mode == 7)? 0xb000 : 0xb800) 11031120Sminshall #define scrwait() if (crt_mode != 7) { \ 11131120Sminshall while ((inp(CRT_STATUS)&DISPLAY_ENABLE) == 0) { \ 11231120Sminshall ; \ 11331120Sminshall } \ 11431120Sminshall } 11531120Sminshall static int 11631120Sminshall crt_mode, 11731120Sminshall crt_cols, 11831120Sminshall crt_lins, 11931120Sminshall curpage; 12031120Sminshall 12131120Sminshall /* 12231120Sminshall * Set the cursor position to where it belongs. 12331120Sminshall */ 12431120Sminshall 12531105Sminshall static void 12631120Sminshall setcursor(row, column, page) 12731120Sminshall int 12831120Sminshall row, 12931120Sminshall column, 13031120Sminshall page; 13131120Sminshall { 13231120Sminshall union REGS inregs, outregs; 13331120Sminshall 13431120Sminshall inregs.h.dh = row; 13531120Sminshall inregs.h.dl = column; 13631120Sminshall inregs.h.bh = page; 13731120Sminshall inregs.h.ah = SetCursorPosition; 13831120Sminshall 13931120Sminshall int86(BIOS_VIDEO, &inregs, &outregs); 14031120Sminshall } 14131120Sminshall /* 14231120Sminshall * Read the state of the video system. Put the cursor somewhere 14331120Sminshall * reasonable. 14431120Sminshall */ 14531120Sminshall 14631120Sminshall static void 14731120Sminshall scrini() 14831120Sminshall { 14931120Sminshall union REGS inregs, outregs; 15031120Sminshall 15131120Sminshall inregs.h.ah = CurrentVideoState; 15231120Sminshall int86(BIOS_VIDEO, &inregs, &outregs); 15331120Sminshall 15431120Sminshall crt_mode = outregs.h.al; 15531120Sminshall crt_cols = outregs.h.ah; 15631120Sminshall crt_lins = 25; 15731120Sminshall curpage = outregs.h.bh; 15831120Sminshall 15931120Sminshall inregs.h.ah = ReadCursorPosition; 16031120Sminshall inregs.h.bh = curpage; 16131120Sminshall 16231120Sminshall int86(BIOS_VIDEO, &inregs, &outregs); 16331120Sminshall 16431120Sminshall if (outregs.h.dh > crt_lins) { 16531120Sminshall outregs.h.dh = crt_lins; 16631120Sminshall } 16731120Sminshall if (outregs.h.dl > crt_cols) { 16831120Sminshall outregs.h.dl = crt_cols; 16931120Sminshall } 17031120Sminshall inregs.h.dh = outregs.h.dh; 17131120Sminshall inregs.h.dl = outregs.h.dl; 17231120Sminshall inregs.h.bh = curpage; 17331120Sminshall 17431120Sminshall inregs.h.ah = SetCursorPosition; 17531120Sminshall int86(BIOS_VIDEO, &inregs, &outregs); 17631120Sminshall } 17731120Sminshall 17831120Sminshall 17931120Sminshall static void 18031120Sminshall scrwrite(source, length, offset) 18131120Sminshall ScreenBuffer *source; 18231120Sminshall int 18331120Sminshall length, 18431120Sminshall offset; 18531120Sminshall { 18631120Sminshall struct SREGS segregs; 18731120Sminshall 18831120Sminshall segread(&segregs); /* read the current segment register */ 18931120Sminshall 19031120Sminshall scrwait(); 19131120Sminshall movedata(segregs.ds, source, scrseg(), offset, length); 19231120Sminshall } 19331120Sminshall 19431120Sminshall static void 19531120Sminshall scrsave(buffer) 19631120Sminshall ScreenBuffer *buffer; 19731120Sminshall { 19831120Sminshall struct SREGS segregs; 19931120Sminshall 20031120Sminshall segread(&segregs); /* read the current segment register */ 20131120Sminshall 20231120Sminshall scrwait(); 20331120Sminshall movedata(scrseg(), 0, segregs.ds, buffer, scrseg(), 0, crt_cols*crt_lins*2); 20431120Sminshall } 20531120Sminshall 20631120Sminshall static void 20731120Sminshall scrrest(buffer) 20831120Sminshall ScreenBuffer *buffer; 20931120Sminshall { 21031120Sminshall scrwrite(buffer, 2*crt_cols*crt_lins, 0); 21131120Sminshall } 21231120Sminshall 21331120Sminshall static void 21431117Sminshall TryToSend() 21531105Sminshall { 21631117Sminshall #define STANDOUT 0x0a 21731117Sminshall #define NORMAL 0x02 /* Normal mode */ 21831105Sminshall 21931105Sminshall #define DoAttribute(a) if (IsHighlightedAttr(a)) { \ 22031117Sminshall a = STANDOUT; \ 22131105Sminshall } else { \ 22231117Sminshall a = NORMAL; \ 22331105Sminshall } \ 22431105Sminshall if (IsNonDisplayAttr(a)) { \ 22531105Sminshall a = 0; /* zero == don't display */ \ 22631105Sminshall } \ 22731105Sminshall if (!FormattedScreen()) { \ 22831105Sminshall a = 1; /* one ==> do display on unformatted */\ 22931105Sminshall } 23031105Sminshall ScreenImage *p, *upper; 23131117Sminshall ScreenBuffer *sp; 23231105Sminshall int fieldattr; /* spends most of its time == 0 or 1 */ 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())) { 24131105Sminshall register int columnsleft; 24231105Sminshall 24331117Sminshall sp = &Screen[Lowest]; 24431105Sminshall p = &Host[Lowest]; 24531105Sminshall upper = &Host[Highest]; 24631105Sminshall fieldattr = FieldAttributes(Lowest); 24731105Sminshall DoAttribute(fieldattr); /* Set standout, non-display status */ 24831105Sminshall columnsleft = NumberColumns-ScreenLineOffset(p-Host); 24931105Sminshall 25031105Sminshall while (p <= upper) { 25131105Sminshall if (IsStartFieldPointer(p)) { /* New field? */ 25231105Sminshall Highest = HighestScreen(); 25331105Sminshall Lowest = LowestScreen(); 25431117Sminshall TryToSend(); /* Recurse */ 25531105Sminshall return; 25631105Sminshall } else if (fieldattr) { /* Should we display? */ 25731117Sminshall sp->data = disp_asc[p->data]; /* Display translated data */ 25831117Sminshall sp->attr = fieldattr; 25931105Sminshall } else { 26031117Sminshall sp->data = ' '; 26131117Sminshall sp->attr = NORMAL; 26231105Sminshall } 26331105Sminshall /* If the physical screen is larger than what we 26431105Sminshall * are using, we need to make sure that each line 26531105Sminshall * starts at the beginning of the line. Otherwise, 26631105Sminshall * we will just string all the lines together. 26731105Sminshall */ 26831105Sminshall p++; 26931117Sminshall sp++; 27031105Sminshall } 27131105Sminshall } else { /* Going from Lowest to Highest */ 27231117Sminshall ScreenImage *End = &Host[ScreenSize]-1; 27331105Sminshall 27431117Sminshall sp = Screen; 27531105Sminshall p = Host; 27631105Sminshall fieldattr = FieldAttributes(LowestScreen()); 27731105Sminshall DoAttribute(fieldattr); /* Set standout, non-display status */ 27831105Sminshall 27931105Sminshall while (p <= End) { 28031105Sminshall if (IsStartFieldPointer(p)) { /* New field? */ 28131105Sminshall fieldattr = FieldAttributesPointer(p); /* Get attributes */ 28231105Sminshall DoAttribute(fieldattr); /* Set standout, non-display */ 28331105Sminshall } else { 28431105Sminshall if (fieldattr) { /* Should we display? */ 28531105Sminshall /* Display translated data */ 28631117Sminshall sp->data = disp_asc[p->data]; 28731117Sminshall sp->attr = fieldattr; 28831105Sminshall } else { 28931117Sminshall sp->data = ' '; 29031117Sminshall sp->attr = NORMAL; 29131105Sminshall } 29231105Sminshall } 29331105Sminshall /* If the physical screen is larger than what we 29431105Sminshall * are using, we need to make sure that each line 29531105Sminshall * starts at the beginning of the line. Otherwise, 29631105Sminshall * we will just string all the lines together. 29731105Sminshall */ 29831105Sminshall p++; 29931117Sminshall sp++; 30031105Sminshall } 30131105Sminshall } 30231117Sminshall terminalCursorAddress = CorrectTerminalCursor(); 30331117Sminshall scrwrite(Screen+Lowest, sizeof Screen[0]*(Highest-Lowest), Lowest); 30431120Sminshall setcursor(ScreenLine(terminalCursorAddress), 30531117Sminshall ScreenLineOffset(terminalCursorAddress), 0); 30631105Sminshall Lowest = HighestScreen()+1; 30731105Sminshall Highest = LowestScreen()-1; 30831105Sminshall if (needToRing) { 30931117Sminshall DataToTerminal("\7", 1); 31031105Sminshall needToRing = 0; 31131105Sminshall } 31231105Sminshall return; 31331105Sminshall } 31431105Sminshall 31531105Sminshall /* InitTerminal - called to initialize the screen, etc. */ 31631105Sminshall 31731105Sminshall void 31831105Sminshall InitTerminal() 31931105Sminshall { 32031105Sminshall InitMapping(); /* Go do mapping file (MAP3270) first */ 32131105Sminshall if (!screenInitd) { /* not initialized */ 322*31129Sminshall MaxNumberLines = 24; /* XXX */ 323*31129Sminshall MaxNumberColumns = 80; /* XXX */ 32431117Sminshall scrini(); 32531120Sminshall scrsave(saveScreen); /* Save the screen buffer away */ 32631117Sminshall ClearArray(Screen); 32731105Sminshall terminalCursorAddress = SetBufferAddress(0,0); 32831105Sminshall screenInitd = 1; 32931105Sminshall screenStopped = 0; /* Not stopped */ 33031105Sminshall } 33131105Sminshall Initialized = 1; 33231105Sminshall } 33331105Sminshall 33431105Sminshall 33531105Sminshall /* StopScreen - called when we are going away... */ 33631105Sminshall 33731105Sminshall void 33831105Sminshall StopScreen(doNewLine) 33931105Sminshall int doNewLine; 34031105Sminshall { 34131105Sminshall if (screenInitd && !screenStopped) { 34231120Sminshall scrrest(saveScreen); 34331120Sminshall setcursor(NumberLines-1, NumberColumns-1, 0); 34431105Sminshall } 34531105Sminshall } 34631105Sminshall 34731105Sminshall 34831105Sminshall /* RefreshScreen - called to cause the screen to be refreshed */ 34931105Sminshall 35031105Sminshall void 35131105Sminshall RefreshScreen() 35231105Sminshall { 35331117Sminshall Highest = HighestScreen(); 35431117Sminshall Lowest = LowestScreen(); 35531117Sminshall TryToSend(); 35631105Sminshall } 35731105Sminshall 35831105Sminshall 35931105Sminshall /* ConnectScreen - called to reconnect to the screen */ 36031105Sminshall 36131105Sminshall void 36231105Sminshall ConnectScreen() 36331105Sminshall { 36431105Sminshall if (screenInitd) { 36531105Sminshall RefreshScreen(); 36631105Sminshall screenStopped = 0; 36731105Sminshall } 36831105Sminshall } 36931105Sminshall 37031105Sminshall /* LocalClearScreen() - clear the whole ball of wax, cheaply */ 37131105Sminshall 37231105Sminshall void 37331105Sminshall LocalClearScreen() 37431105Sminshall { 37531105Sminshall Clear3270(); 37631117Sminshall Lowest = LowestScreen(); /* everything in sync... */ 37731117Sminshall Highest = HighestScreen(); 37831117Sminshall TryToSend(); 37931105Sminshall } 38031117Sminshall 38131117Sminshall /* 38231117Sminshall * Implement the bell/error message function. 38331117Sminshall */ 38431105Sminshall 38531117Sminshall int 38631117Sminshall bellwinup = 0; /* If != 0, length of bell message */ 38731117Sminshall static int 38831117Sminshall bellpos0 = 0; /* Where error message goes */ 38931105Sminshall 39031117Sminshall static char bellstring[100];/* Where message goes */ 39131117Sminshall 39231117Sminshall #define BELL_SPACES 2 /* 2 spaces between border and bell */ 39331117Sminshall 39431117Sminshall #define BELL_HIGH_LOW(h,l) { \ 39531117Sminshall h = bellpos0+2*NumberColumns+bellwinup+BELL_SPACES*2; \ 39631117Sminshall l = bellpos0; \ 39731117Sminshall } 39831117Sminshall 39931105Sminshall void 40031105Sminshall BellOff() 40131105Sminshall { 40231105Sminshall if (bellwinup) { 40331117Sminshall BELL_HIGH_LOW(Highest,Lowest); 40431117Sminshall TryToSend(); 40531105Sminshall } 40631105Sminshall } 40731105Sminshall 40831105Sminshall 40931105Sminshall void 41031105Sminshall RingBell(s) 41131105Sminshall char *s; 41231105Sminshall { 41331105Sminshall needToRing = 1; 41431105Sminshall if (s) { 41531105Sminshall int len = strlen(s); 41631105Sminshall 41731117Sminshall if (len > sizeof bellstring-1) { 41831117Sminshall OurExitString(stderr, "Bell string too long.", 1); 41931105Sminshall } 42031117Sminshall memcpy(bellstring, s, len+1); 42131117Sminshall BELL_HIGH_LOW(Highest,Lowest); 42231117Sminshall TryToSend(); 42331105Sminshall } 42431105Sminshall } 42531105Sminshall 42631117Sminshall /* 42731117Sminshall * Update the OIA area. 42831117Sminshall */ 42931105Sminshall 43031117Sminshall void 43131117Sminshall ScreenOIA(oia) 43231117Sminshall OIA *oia; 43331117Sminshall { 43431117Sminshall } 43531117Sminshall 43631117Sminshall 43731105Sminshall /* returns a 1 if no more output available (so, go ahead and block), 43831105Sminshall or a 0 if there is more output available (so, just poll the other 43931105Sminshall sources/destinations, don't block). 44031105Sminshall */ 44131105Sminshall 44231105Sminshall int 44331105Sminshall DoTerminalOutput() 44431105Sminshall { 44531105Sminshall /* called just before a select to conserve IO to terminal */ 44631105Sminshall if (!Initialized) { 44731105Sminshall return 1; /* No output if not initialized */ 44831105Sminshall } 44931105Sminshall if ((Lowest <= Highest) || needToRing || 45031105Sminshall (terminalCursorAddress != CorrectTerminalCursor())) { 45131117Sminshall TryToSend(); 45231105Sminshall } 45331105Sminshall if (Lowest > Highest) { 45431105Sminshall return 1; /* no more output now */ 45531105Sminshall } else { 45631105Sminshall return 0; /* more output for future */ 45731105Sminshall } 45831105Sminshall } 45931105Sminshall 46031105Sminshall /* 46131105Sminshall * The following are defined to handle transparent data. 46231105Sminshall */ 46331105Sminshall 46431105Sminshall void 46531105Sminshall TransStop() 46631105Sminshall { 46731105Sminshall RefreshScreen(); 46831105Sminshall } 46931105Sminshall 47031105Sminshall void 47131105Sminshall TransOut(buffer, count) 47231105Sminshall unsigned char *buffer; 47331105Sminshall int count; 47431105Sminshall { 47531105Sminshall 47631105Sminshall while (DoTerminalOutput() == 0) { 47731117Sminshall ; 47831105Sminshall } 47931105Sminshall (void) DataToTerminal(buffer, count); 48031105Sminshall } 48131117Sminshall 48231117Sminshall /* 48331117Sminshall * init_screen() 48431117Sminshall * 48531117Sminshall * Initialize variables used by screen. 48631117Sminshall */ 48731105Sminshall 48831117Sminshall void 48931117Sminshall init_screen() 49031105Sminshall { 49131117Sminshall bellwinup = 0; 49231117Sminshall } 49331105Sminshall 49431117Sminshall 495