131105Sminshall /* 233814Sbostic * Copyright (c) 1988 Regents of the University of California. 333814Sbostic * All rights reserved. 431105Sminshall * 533814Sbostic * Redistribution and use in source and binary forms are permitted 634889Sbostic * provided that the above copyright notice and this paragraph are 734889Sbostic * duplicated in all such forms and that any documentation, 834889Sbostic * advertising materials, and other materials related to such 934889Sbostic * distribution and use acknowledge that the software was developed 1034889Sbostic * by the University of California, Berkeley. The name of the 1134889Sbostic * University may not be used to endorse or promote products derived 1234889Sbostic * from this software without specific prior written permission. 1334889Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434889Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534889Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1631105Sminshall */ 1731105Sminshall 1831105Sminshall #ifndef lint 19*35424Sminshall static char sccsid[] = "@(#)termout.c 3.4 (Berkeley) 08/28/88"; 2033814Sbostic #endif /* not lint */ 2131105Sminshall 2231105Sminshall #include <stdio.h> 2331120Sminshall #include <dos.h> 2431185Sminshall #include "../general/general.h" 2531105Sminshall 2631105Sminshall #include "../telnet.ext" 2731105Sminshall 2831881Sminshall #include "../api/disp_asc.h" 2931225Sminshall #include "../ascii/map3270.ext" 3031225Sminshall 3131105Sminshall #include "../ctlr/hostctlr.h" 32*35424Sminshall #include "../ctlr/externs.h" 33*35424Sminshall #include "../ctlr/declare.h" 3431117Sminshall #include "../ctlr/oia.h" 3531105Sminshall #include "../ctlr/screen.h" 3631105Sminshall 3731185Sminshall #include "../general/globals.h" 3831105Sminshall 3931120Sminshall #include "video.h" 4031120Sminshall 4131105Sminshall extern void EmptyTerminal(); 4231105Sminshall 4331105Sminshall #define CorrectTerminalCursor() ((TransparentClock == OutputClock)? \ 4431105Sminshall terminalCursorAddress:UnLocked? CursorAddress: HighestScreen()) 4531105Sminshall 4631105Sminshall 4731105Sminshall static int terminalCursorAddress; /* where the cursor is on term */ 4831105Sminshall static int screenInitd; /* the screen has been initialized */ 4931105Sminshall static int screenStopped; /* the screen has been stopped */ 5031105Sminshall 5131105Sminshall static int needToRing; /* need to ring terinal bell */ 5231105Sminshall 5331117Sminshall typedef struct { 5431117Sminshall char 5531117Sminshall data, /* The data for this position */ 5631117Sminshall attr; /* The attributes for this position */ 5731117Sminshall } ScreenBuffer; 5831105Sminshall 5931117Sminshall ScreenBuffer Screen[MAXNUMBERLINES*MAXNUMBERCOLUMNS]; 6031120Sminshall ScreenBuffer saveScreen[sizeof Screen/sizeof Screen[0]]; 6131105Sminshall 6231105Sminshall /* OurExitString - designed to keep us from going through infinite recursion */ 6331105Sminshall 6431105Sminshall static void 6531105Sminshall OurExitString(file, string, value) 6631105Sminshall FILE *file; 6731105Sminshall char *string; 6831105Sminshall int value; 6931105Sminshall { 7031105Sminshall static int recursion = 0; 7131105Sminshall 7231105Sminshall if (!recursion) { 7331105Sminshall recursion = 1; 7431105Sminshall ExitString(file, string, value); 7531105Sminshall } 7631105Sminshall } 7731105Sminshall 7831105Sminshall 7931105Sminshall static void 8031105Sminshall GoAway(from, where) 8131105Sminshall char *from; /* routine that gave error */ 8231105Sminshall int where; /* cursor address */ 8331105Sminshall { 8431105Sminshall char foo[100]; 8531105Sminshall 8631105Sminshall sprintf(foo, "ERR from %s at %d (%d, %d)\n", 8731105Sminshall from, where, ScreenLine(where), ScreenLineOffset(where)); 8831105Sminshall OurExitString(stderr, foo, 1); 8931105Sminshall /* NOTREACHED */ 9031105Sminshall } 9131105Sminshall 9231120Sminshall /* 9331120Sminshall * Routines to deal with the screen. These routines are lifted 9431120Sminshall * from mskermit. 9531120Sminshall */ 9631120Sminshall 9731120Sminshall #define CRT_STATUS 0x3da /* Color card */ 9831120Sminshall #define DISPLAY_ENABLE 0x08 /* Enable */ 9931120Sminshall #define scrseg() ((crt_mode == 7)? 0xb000 : 0xb800) 10031120Sminshall #define scrwait() if (crt_mode != 7) { \ 10131120Sminshall while ((inp(CRT_STATUS)&DISPLAY_ENABLE) == 0) { \ 10231120Sminshall ; \ 10331120Sminshall } \ 10431120Sminshall } 10531120Sminshall static int 10631120Sminshall crt_mode, 10731120Sminshall crt_cols, 10831120Sminshall crt_lins, 10931120Sminshall curpage; 11031120Sminshall 11131120Sminshall /* 11231120Sminshall * Set the cursor position to where it belongs. 11331120Sminshall */ 11431120Sminshall 11531105Sminshall static void 11631120Sminshall setcursor(row, column, page) 11731120Sminshall int 11831120Sminshall row, 11931120Sminshall column, 12031120Sminshall page; 12131120Sminshall { 12231120Sminshall union REGS inregs, outregs; 12331120Sminshall 12431120Sminshall inregs.h.dh = row; 12531120Sminshall inregs.h.dl = column; 12631120Sminshall inregs.h.bh = page; 12731120Sminshall inregs.h.ah = SetCursorPosition; 12831120Sminshall 12931120Sminshall int86(BIOS_VIDEO, &inregs, &outregs); 13031120Sminshall } 13131120Sminshall /* 13231120Sminshall * Read the state of the video system. Put the cursor somewhere 13331120Sminshall * reasonable. 13431120Sminshall */ 13531120Sminshall 13631120Sminshall static void 13731120Sminshall scrini() 13831120Sminshall { 13931120Sminshall union REGS inregs, outregs; 14031120Sminshall 14131120Sminshall inregs.h.ah = CurrentVideoState; 14231120Sminshall int86(BIOS_VIDEO, &inregs, &outregs); 14331120Sminshall 14431120Sminshall crt_mode = outregs.h.al; 14531120Sminshall crt_cols = outregs.h.ah; 14631120Sminshall crt_lins = 25; 14731120Sminshall curpage = outregs.h.bh; 14831120Sminshall 14931120Sminshall inregs.h.ah = ReadCursorPosition; 15031120Sminshall inregs.h.bh = curpage; 15131120Sminshall 15231120Sminshall int86(BIOS_VIDEO, &inregs, &outregs); 15331120Sminshall 15431120Sminshall if (outregs.h.dh > crt_lins) { 15531120Sminshall outregs.h.dh = crt_lins; 15631120Sminshall } 15731120Sminshall if (outregs.h.dl > crt_cols) { 15831120Sminshall outregs.h.dl = crt_cols; 15931120Sminshall } 16031120Sminshall inregs.h.dh = outregs.h.dh; 16131120Sminshall inregs.h.dl = outregs.h.dl; 16231120Sminshall inregs.h.bh = curpage; 16331120Sminshall 16431120Sminshall inregs.h.ah = SetCursorPosition; 16531120Sminshall int86(BIOS_VIDEO, &inregs, &outregs); 16631120Sminshall } 16731120Sminshall 16831120Sminshall 16931120Sminshall static void 17031120Sminshall scrwrite(source, length, offset) 17131120Sminshall ScreenBuffer *source; 17231120Sminshall int 17331120Sminshall length, 17431120Sminshall offset; 17531120Sminshall { 17631120Sminshall struct SREGS segregs; 17731120Sminshall 17831120Sminshall segread(&segregs); /* read the current segment register */ 17931120Sminshall 18031120Sminshall scrwait(); 18131154Sminshall movedata(segregs.ds, source, scrseg(), sizeof *source*offset, 18231154Sminshall sizeof *source*length); 18331120Sminshall } 18431120Sminshall 18531120Sminshall static void 18631120Sminshall scrsave(buffer) 18731120Sminshall ScreenBuffer *buffer; 18831120Sminshall { 18931120Sminshall struct SREGS segregs; 19031120Sminshall 19131120Sminshall segread(&segregs); /* read the current segment register */ 19231120Sminshall 19331120Sminshall scrwait(); 19431154Sminshall movedata(scrseg(), 0, segregs.ds, buffer, crt_cols*crt_lins*2); 19531120Sminshall } 19631120Sminshall 19731120Sminshall static void 19831120Sminshall scrrest(buffer) 19931120Sminshall ScreenBuffer *buffer; 20031120Sminshall { 20131154Sminshall scrwrite(buffer, crt_cols*crt_lins, 0); 20231120Sminshall } 20331120Sminshall 20431120Sminshall static void 20531117Sminshall TryToSend() 20631105Sminshall { 20731154Sminshall #define STANDOUT 0x0a /* Highlighted mode */ 20831117Sminshall #define NORMAL 0x02 /* Normal mode */ 20931154Sminshall #define NONDISPLAY 0x00 /* Don't display */ 21031105Sminshall 21131154Sminshall #define DoAttribute(a) \ 21231154Sminshall if (screenIsFormatted) { \ 21331154Sminshall if (IsNonDisplayAttr(a)) { \ 21431154Sminshall a = NONDISPLAY; /* don't display */ \ 21531154Sminshall } else if (IsHighlightedAttr(a)) { \ 21631154Sminshall a = STANDOUT; \ 21731154Sminshall } else { \ 21831154Sminshall a = NORMAL; \ 21931154Sminshall } \ 22031154Sminshall } else { \ 22131154Sminshall a = NORMAL; /* do display on unformatted */\ 22231105Sminshall } 22331105Sminshall ScreenImage *p, *upper; 22431117Sminshall ScreenBuffer *sp; 22531105Sminshall int fieldattr; /* spends most of its time == 0 or 1 */ 22631154Sminshall int screenIsFormatted = FormattedScreen(); 22731105Sminshall 22831105Sminshall /* OK. We want to do this a quickly as possible. So, we assume we 22931105Sminshall * only need to go from Lowest to Highest. However, if we find a 23031105Sminshall * field in the middle, we do the whole screen. 23131105Sminshall * 23231105Sminshall * In particular, we separate out the two cases from the beginning. 23331105Sminshall */ 23431105Sminshall if ((Highest != HighestScreen()) || (Lowest != LowestScreen())) { 23531117Sminshall sp = &Screen[Lowest]; 23631105Sminshall p = &Host[Lowest]; 23731105Sminshall upper = &Host[Highest]; 23831105Sminshall fieldattr = FieldAttributes(Lowest); 23931105Sminshall DoAttribute(fieldattr); /* Set standout, non-display status */ 24031105Sminshall 24131105Sminshall while (p <= upper) { 24231105Sminshall if (IsStartFieldPointer(p)) { /* New field? */ 24331105Sminshall Highest = HighestScreen(); 24431105Sminshall Lowest = LowestScreen(); 24531117Sminshall TryToSend(); /* Recurse */ 24631105Sminshall return; 24731105Sminshall } else if (fieldattr) { /* Should we display? */ 24831154Sminshall /* Display translated data */ 24931154Sminshall sp->data = disp_asc[GetHostPointer(p)]; 25031105Sminshall } else { 25131117Sminshall sp->data = ' '; 25231105Sminshall } 25331154Sminshall sp->attr = fieldattr; 25431105Sminshall p++; 25531117Sminshall sp++; 25631105Sminshall } 25731105Sminshall } else { /* Going from Lowest to Highest */ 25831117Sminshall ScreenImage *End = &Host[ScreenSize]-1; 25931105Sminshall 26031117Sminshall sp = Screen; 26131105Sminshall p = Host; 26231105Sminshall fieldattr = FieldAttributes(LowestScreen()); 26331105Sminshall DoAttribute(fieldattr); /* Set standout, non-display status */ 26431105Sminshall 26531105Sminshall while (p <= End) { 26631105Sminshall if (IsStartFieldPointer(p)) { /* New field? */ 26731105Sminshall fieldattr = FieldAttributesPointer(p); /* Get attributes */ 26831105Sminshall DoAttribute(fieldattr); /* Set standout, non-display */ 26931154Sminshall } 27031154Sminshall if (fieldattr) { /* Should we display? */ 27131154Sminshall /* Display translated data */ 27231154Sminshall sp->data = disp_asc[GetHostPointer(p)]; 27331105Sminshall } else { 27431154Sminshall sp->data = ' '; 27531105Sminshall } 27631154Sminshall sp->attr = fieldattr; 27731105Sminshall p++; 27831117Sminshall sp++; 27931105Sminshall } 28031105Sminshall } 28131117Sminshall terminalCursorAddress = CorrectTerminalCursor(); 28231154Sminshall /* 28331154Sminshall * We might be here just to update the cursor address. 28431154Sminshall */ 28531154Sminshall if (Highest >= Lowest) { 28631154Sminshall scrwrite(Screen+Lowest, (1+Highest-Lowest), Lowest); 28731154Sminshall } 28831120Sminshall setcursor(ScreenLine(terminalCursorAddress), 28931117Sminshall ScreenLineOffset(terminalCursorAddress), 0); 29031105Sminshall Lowest = HighestScreen()+1; 29131105Sminshall Highest = LowestScreen()-1; 29231105Sminshall if (needToRing) { 29331117Sminshall DataToTerminal("\7", 1); 29431105Sminshall needToRing = 0; 29531105Sminshall } 29631105Sminshall return; 29731105Sminshall } 29831105Sminshall 29931105Sminshall /* InitTerminal - called to initialize the screen, etc. */ 30031105Sminshall 30131105Sminshall void 30231105Sminshall InitTerminal() 30331105Sminshall { 30431105Sminshall InitMapping(); /* Go do mapping file (MAP3270) first */ 30531105Sminshall if (!screenInitd) { /* not initialized */ 30631129Sminshall MaxNumberLines = 24; /* XXX */ 30731129Sminshall MaxNumberColumns = 80; /* XXX */ 30831117Sminshall scrini(); 30931120Sminshall scrsave(saveScreen); /* Save the screen buffer away */ 31031117Sminshall ClearArray(Screen); 31131105Sminshall terminalCursorAddress = SetBufferAddress(0,0); 31231105Sminshall screenInitd = 1; 31331105Sminshall screenStopped = 0; /* Not stopped */ 31431105Sminshall } 31531105Sminshall } 31631105Sminshall 31731105Sminshall 31831105Sminshall /* StopScreen - called when we are going away... */ 31931105Sminshall 32031105Sminshall void 32131105Sminshall StopScreen(doNewLine) 32231105Sminshall int doNewLine; 32331105Sminshall { 32431105Sminshall if (screenInitd && !screenStopped) { 32531120Sminshall scrrest(saveScreen); 32631208Sminshall setcursor(NumberLines-1, 1, 0); 32731208Sminshall if (doNewLine) { 32831208Sminshall StringToTerminal("\r\n"); 32931208Sminshall } 33031208Sminshall EmptyTerminal(); 33131208Sminshall screenStopped = 1; 33231105Sminshall } 33331105Sminshall } 33431105Sminshall 33531105Sminshall 33631105Sminshall /* RefreshScreen - called to cause the screen to be refreshed */ 33731105Sminshall 33831105Sminshall void 33931105Sminshall RefreshScreen() 34031105Sminshall { 34131117Sminshall Highest = HighestScreen(); 34231117Sminshall Lowest = LowestScreen(); 34331117Sminshall TryToSend(); 34431105Sminshall } 34531105Sminshall 34631105Sminshall 34731105Sminshall /* ConnectScreen - called to reconnect to the screen */ 34831105Sminshall 34931105Sminshall void 35031105Sminshall ConnectScreen() 35131105Sminshall { 35231105Sminshall if (screenInitd) { 35331105Sminshall RefreshScreen(); 35431105Sminshall screenStopped = 0; 35531105Sminshall } 35631105Sminshall } 35731105Sminshall 35831105Sminshall /* LocalClearScreen() - clear the whole ball of wax, cheaply */ 35931105Sminshall 36031105Sminshall void 36131105Sminshall LocalClearScreen() 36231105Sminshall { 36331105Sminshall Clear3270(); 36431117Sminshall Lowest = LowestScreen(); /* everything in sync... */ 36531117Sminshall Highest = HighestScreen(); 36631117Sminshall TryToSend(); 36731105Sminshall } 36831117Sminshall 36931117Sminshall /* 37031117Sminshall * Implement the bell/error message function. 37131117Sminshall */ 37231105Sminshall 37331117Sminshall int 37431117Sminshall bellwinup = 0; /* If != 0, length of bell message */ 37531117Sminshall static int 37631883Sminshall bell_len = 0; /* Length of error message */ 37731105Sminshall 37831117Sminshall 37931105Sminshall void 38031105Sminshall BellOff() 38131105Sminshall { 38231883Sminshall ScreenBuffer a[100]; 38331883Sminshall int i; 38431883Sminshall 38531105Sminshall if (bellwinup) { 38631883Sminshall unsigned char blank = ' '; 38731883Sminshall 38831883Sminshall for (i = 0; i < bell_len; i++) { 38931883Sminshall a[i].attr = NORMAL; 39031883Sminshall a[i].data = ' '; 39131883Sminshall } 39231105Sminshall } 39331883Sminshall scrwrite(a, bell_len, 24*80); /* XXX */ 39431105Sminshall } 39531105Sminshall 39631105Sminshall 39731105Sminshall void 39831105Sminshall RingBell(s) 39931105Sminshall char *s; 40031105Sminshall { 40131105Sminshall needToRing = 1; 40231105Sminshall if (s) { 40331883Sminshall int i; 40431883Sminshall ScreenBuffer bellstring[100]; 40531105Sminshall 40631883Sminshall bell_len = strlen(s); 40731883Sminshall bellwinup = 1; 40831883Sminshall if (bell_len > sizeof bellstring-1) { 40931117Sminshall OurExitString(stderr, "Bell string too long.", 1); 41031105Sminshall } 41131883Sminshall for (i = 0; i < bell_len; i++) { 41231883Sminshall bellstring[i].attr = STANDOUT; 41331883Sminshall bellstring[i].data = s[i]; 41431883Sminshall } 41531883Sminshall scrwrite(bellstring, bell_len, 24*80); /* XXX */ 41631105Sminshall } 41731105Sminshall } 41831105Sminshall 41931117Sminshall /* 42031117Sminshall * Update the OIA area. 42131117Sminshall */ 42231105Sminshall 42331117Sminshall void 42431117Sminshall ScreenOIA(oia) 42531117Sminshall OIA *oia; 42631117Sminshall { 42731117Sminshall } 42831117Sminshall 42931117Sminshall 43031105Sminshall /* returns a 1 if no more output available (so, go ahead and block), 43131105Sminshall or a 0 if there is more output available (so, just poll the other 43231105Sminshall sources/destinations, don't block). 43331105Sminshall */ 43431105Sminshall 43531105Sminshall int 43631105Sminshall DoTerminalOutput() 43731105Sminshall { 43831105Sminshall /* called just before a select to conserve IO to terminal */ 43931490Sminshall if (!(screenInitd||screenStopped)) { 44031105Sminshall return 1; /* No output if not initialized */ 44131105Sminshall } 44231105Sminshall if ((Lowest <= Highest) || needToRing || 44331105Sminshall (terminalCursorAddress != CorrectTerminalCursor())) { 44431117Sminshall TryToSend(); 44531105Sminshall } 44631105Sminshall if (Lowest > Highest) { 44731105Sminshall return 1; /* no more output now */ 44831105Sminshall } else { 44931105Sminshall return 0; /* more output for future */ 45031105Sminshall } 45131105Sminshall } 45231105Sminshall 45331105Sminshall /* 45431105Sminshall * The following are defined to handle transparent data. 45531105Sminshall */ 45631105Sminshall 45731105Sminshall void 45831105Sminshall TransStop() 45931105Sminshall { 46031105Sminshall RefreshScreen(); 46131105Sminshall } 46231105Sminshall 46331105Sminshall void 46431885Sminshall TransOut(buffer, count, kind, control) 46531105Sminshall unsigned char *buffer; 46631105Sminshall int count; 46731885Sminshall int kind; /* 0 or 5 */ 46831885Sminshall int control; /* To see if we are done */ 46931105Sminshall { 47031885Sminshall char *ptr; 47131105Sminshall 47231105Sminshall while (DoTerminalOutput() == 0) { 47331117Sminshall ; 47431105Sminshall } 47531885Sminshall for (ptr = buffer; ptr < buffer+count; ptr++) { 47631885Sminshall *ptr &= 0x7f; /* Turn off parity bit */ 47731885Sminshall } 47831105Sminshall (void) DataToTerminal(buffer, count); 47931885Sminshall if (control && (kind == 0)) { /* Send in AID byte */ 48031885Sminshall SendToIBM(); 48131885Sminshall } else { 48231885Sminshall TransInput(1, kind); /* Go get some data */ 48331885Sminshall } 48431105Sminshall } 48531117Sminshall 48631117Sminshall /* 48731117Sminshall * init_screen() 48831117Sminshall * 48931117Sminshall * Initialize variables used by screen. 49031117Sminshall */ 49131105Sminshall 49231117Sminshall void 49331117Sminshall init_screen() 49431105Sminshall { 49531117Sminshall bellwinup = 0; 49631117Sminshall } 49731105Sminshall 49831117Sminshall 499