diff options
Diffstat (limited to 'dviware/dvgtk/vdu.c')
-rw-r--r-- | dviware/dvgtk/vdu.c | 547 |
1 files changed, 547 insertions, 0 deletions
diff --git a/dviware/dvgtk/vdu.c b/dviware/dvgtk/vdu.c new file mode 100644 index 0000000000..c338ca7249 --- /dev/null +++ b/dviware/dvgtk/vdu.c @@ -0,0 +1,547 @@ +/* vdu.c - VDU driver interface + $Id: vdu.c,v 0.2 1997/03/28 03:17:44 tjchol01 Exp $ + Authors: Andrew Trevorrow, Ian Dall, Geoffrey Tobin, Tomasz J. Cholewo + */ + +#include "dvgt.h" +#include "vdu.h" +#include "options.h" +#include "screenio.h" + +/* Exported via "vdu.h" */ + +boolean vdu_clears_lines; /* Can current VDU clear a single line? */ + +int maxy, lineht, dragdown; +boolean havesentxy; + +static int oldhiy; /* for remembering old address in SendXY */ +static int oldhix, oldloy, charwidth; + /* set by LoadFont and used in ShowChar */ + +static int loadedsize; +/* remember alpha size set by last TEK4010LoadFont; + VT640, VIS500/550 VDUs don't actually need to worry about this, + since they use non-TEK4010 fonts to draw in dialogue region. + VIS240, however, uses alpha mode font. */ + +static int charsize; /* used to select alpha character size */ + + +/*--------------------------------------------------------------------*/ + +static void +Graphic () +{ + WriteChar (GS); /* switch to graphics mode */ +} + +/* Graphic */ + +/*--------------------------------------------------------------------*/ + +static void +Alpha () +{ + WriteChar (US); /* switch to alphanumeric mode */ +} + +/* Alpha */ + +/*--------------------------------------------------------------------*/ + +void +SendXY (int x, int y) +{ + /* Translates the given screen address into 4 bytes. + havesentxy is used to minimize the number of bytes sent: after the first + 4 bytes have been sent, subsequent bytes that don't change need not be sent + (except for the low x byte which is always sent). + If the high x byte changes then the low y byte must also be sent. + */ + + int hiy, loy, hix, lox; + boolean sendhix; + + /* we assume y is in [0..maxy] and x is in [0..1023] */ + hiy = y / 32 + ' '; + hix = x / 32 + ' '; + loy = (y & 31) + '`'; + lox = (x & 31) + '@'; + if (havesentxy) + { + if (hiy != oldhiy) + { + WriteChar (hiy); + oldhiy = hiy; + } + sendhix = (hix != oldhix); + if (loy != oldloy || sendhix) + { + WriteChar (loy); + oldloy = loy; + } + if (sendhix) + { + WriteChar (hix); + oldhix = hix; + } + WriteChar (lox); + } + else + { + /* + SYSDEP: We _assume_ XON/XOFF flow control is _enabled_, + to avoid data loss. + */ + WriteChar (hiy); + oldhiy = hiy; + WriteChar (loy); + oldloy = loy; + WriteChar (hix); + oldhix = hix; + WriteChar (lox); + havesentxy = true; + /* send first 4 bytes */ + } +} +/* SendXY */ + +/*--------------------------------------------------------------------*/ +void +ClearTextLine (int line) +{ + /* Do nothing as NCSA Telnet (version 2.3.0.3) can only clear + the entire screen in tek4010 and NOT just a line. + Live with the overwriting. In any case, + the next DisplayPage will clear and rewrite the status lines. + */ +} +/* ClearTextLine */ + +/*--------------------------------------------------------------------*/ + +void +ResetVDU () +{ + WriteChar (CAN); + WriteChar (CAN); +} +/* ResetVDU */ +/*--------------------------------------------------------------------*/ + +void +StartText () +{ + Alpha (); +} +/* StartText */ + +/*--------------------------------------------------------------------*/ + +void +MoveToTextLine (int line) +{ + /* Move cursor to start of given line using lineht. + At the end of this routine we must be in alpha mode, + and ready to display characters in the default charsize. + */ + + Graphic (); + + SendXY (0, maxy - line * lineht + 1); + textcolumn = 0; + + WriteChar (ESC); /* reset alpha character size */ + WriteChar ('0'); + charsize = 0; + charwidth = 13; + + Alpha (); /* back to alpha mode */ +} + +/* MoveToTextLine */ + +/*--------------------------------------------------------------------*/ + +void +ClearScreen () +{ +#ifdef NCSA_TELNET + WriteChar (ESC); + WriteChar (FF); /* erase graphics and put in alpha mode */ +#endif + + Graphic (); + + WriteChar (ESC); /* erase graphics and put in alpha mode */ + WriteChar (FF); + + havesentxy = false; /* ESC FF will home cursor */ + charsize = 0; /* ESC FF resets character size */ + charwidth = 13; +} + +/* ClearScreen */ + +/*--------------------------------------------------------------------*/ + +void +StartGraphics () +{ + if (charsize != loadedsize) + { /* graphics mode was interrupted */ + charsize = loadedsize; + dragdown = (charsize + 1) * 5; /* used by VIS500/550 ShowChar */ + + Graphic (); + + WriteChar (ESC); + WriteChar (charsize + '0'); /* recall last LoadFont character size */ + } + Graphic (); + + havesentxy = false; /* safer to send all bytes anew */ +} +/* StartGraphics */ + + +/*--------------------------------------------------------------------*/ + +void +LoadFont (char *fontname, int fontsize, double mag, + double hscale, double vscale) +{ + /* Use the given fontsize to select an appropriate character size + (based on horizontal scaling only!) for future TEK4010ShowChar calls. + */ + + int newsize; + + /* convert fontsize into scaled screen pixels using mag and hscale */ + fontsize = (int) (fontsize * mag * hscale + 0.5); + /* Choose one of the 4 alpha mode character sizes based on fontsize: + charsize max chars/line relative size fontsize range + 0 80 x1 0..40 + 1 40 x2 41..80 + 2 26 x3 81..120 + 3 20 x4 121... + The fontsize ranges were chosen by trial and error. + */ + if (fontsize < 41) + { + newsize = 0; + charwidth = 13; /* 1024/80 = 12.8 */ + } + else if (fontsize < 81) + { + newsize = 1; + charwidth = 26; /* 1024/40 = 25.6 */ + } + else if (fontsize < 121) + { + newsize = 2; + charwidth = 40; /* 1024/26 = 39.4 */ + } + else + { + newsize = 3; + charwidth = 52; /* 1024/20 = 51.2 */ + } + loadedsize = newsize; /* remember in case graphics mode is interrupted */ + if (charsize != newsize) + { /* change character size */ + charsize = newsize; + WriteChar (ESC); + WriteChar (charsize + '0'); + } + /* Alpha character reference pts on some emulating VDUs (VIS500/550) + are below baselines to allow for descenders. + Such VDUs can use dragdown to drag baselines down to TeX reference pts + when calling TEK4010ShowChar. + */ + dragdown = (charsize + 1) * 5; /* used by VIS500/550 TEK4010ShowChar */ + + Graphic (); /* must return from LoadFont in graphics mode */ +} +/* LoadFont */ + +/*--------------------------------------------------------------------*/ + +void +ShowChar (int screenh, int screenv, char ch) +{ + /* Show the given Terse character (mapped to ASCII) at the given ref pt. + We use the charwidth set by last TEK4010LoadFont call. + */ + + char newch; /* = TeXtoASCII[ch] */ + + /* shift character left if it will overlap right edge of screen */ + + if (screenh + charwidth > 1023) + screenh = 1023 - charwidth; + + /* We no longer _assume_ TEK4010StartGraphics, TEK4010LoadFont, + or last TEK4010ShowChar has just sent GS */ + + Graphic (); + SendXY (screenh, maxy - screenv); /* move cursor to ref pt */ + Alpha (); /* enter alpha mode */ + + /* We use TeXtoASCII to map ch into a comparable ASCII character, apart + from most of the ? characters which we attempt to simulate. + */ + + newch = TeXtoASCII[ch - NUL]; + if (newch != '?') + { + /* newch is similar to TeX ch */ + WriteChar (newch); + } + else + { + /* attempt to display something other than ? */ + switch (ch) + { + case 0xb: /* ff, fi, fl, ffi, ffl */ + case 0xc: + case 0xd: + case 0xe: + case 0xf: + WriteChar ('f'); + /* only simulate rest of ligature if room at right edge */ + if (screenh + charwidth * 2 <= 1023) + { + Graphic (); + SendXY (screenh + charwidth, maxy - screenv); + Alpha (); + + switch (ch) + { + case 0xb: /* ff */ + WriteChar ('f'); + break; + + case 0xc: /* fi */ + WriteChar ('i'); + break; + + case 0xd: /* fl */ + WriteChar ('l'); + break; + + case 0xe: + case 0xf: + WriteChar ('f'); + /* only simulate rest of ligature if room at right edge */ + if (screenh + charwidth * 3 <= 1023) + { + Graphic (); + SendXY (screenh + charwidth * 2, maxy - screenv); + Alpha (); + + if (ch == 0xe) /* ffi */ + WriteChar ('i'); + else /* if (ch == 0xf) */ + /* ffl */ + WriteChar ('l'); + } /* fi */ + break; + } /* switch */ + } /* fi */ + break; + case 0x19: /* German sharp S */ + WriteChar ('B'); + break; + case 0x1a: /* diphthongs: ae, oe, AE, OE */ + case 0x1b: + case 0x1d: + case 0x1e: + switch (ch) + { + case 0x1a: /* ae */ + WriteChar ('a'); + break; + case 0x1b: /* oe */ + WriteChar ('o'); + break; + case 0x1d: /* AE */ + WriteChar ('A'); + break; + case 0x1e: /* OE */ + WriteChar ('O'); + break; + } + if (screenh + charwidth * 2 <= 1023) + { + Graphic (); + SendXY (screenh + charwidth, maxy - screenv); + Alpha (); + + switch (ch) + { + case 0x1a: /* ae */ + case 0x1b: /* oe */ + WriteChar ('e'); + break; + + case 0x1d: /* AE */ + case 0x1e: /* OE */ + WriteChar ('E'); + break; + } + } + break; + case 0x1c: /* Scandinavian slashed o and O */ + case 0x1f: + switch (ch) + { + case 0x1c: /* o/ */ + WriteChar ('o'); + break; + + case 0x1f: /* O/ */ + WriteChar ('O'); + break; + } + + Graphic (); + SendXY (screenh, maxy - screenv); /* overwrite */ + Alpha (); + + WriteChar ('/'); + break; + case 0x20: /* Polish suppressed l and L */ + WriteChar ('\''); + break; + case '?': /* question mark */ + WriteChar ('?'); + + default: + /* WriteChar ('?'); */ + /* show hexadecimal character code, instead of question mark: */ + WriteChar ('\\'); + /* only simulate rest of ligature if room at right edge */ + if (screenh + charwidth * 3 <= 1023) + { + String outstr; /* ample size */ + + Graphic (); + SendXY (screenh + charwidth * 2, maxy - screenv); + Alpha (); + + sprintf (outstr, "%.2x", ch); + WriteChar (outstr[0]); + WriteChar (outstr[1]); + } + break; + } /* switch */ + } /* fi */ + + Graphic (); /* must return from ShowChar in graphics mode */ +} +/* ShowChar */ + +/*--------------------------------------------------------------------*/ + +void +ShowRectangle (int screenh, int screenv, int width, int height, + char ch) +{ + /* Display the given rectangle + (_without_ using the given black pixel character). + DVItoVDU ensures that the top left position is visible, + and that the given dimensions do not go beyond the window edges. + */ + + int i, endpt; + + /* DVItoVDU ensures width and height > 0 */ + if (height < width) + { + /* show row vectors */ + endpt = screenh + width - 1; + for (i = 0; i < height; i++) + { + Graphic (); + + SendXY (screenh, maxy - screenv - i); /* move cursor to start of row */ + SendXY (endpt, maxy - screenv - i); /* draw vector to end of row */ + } + } + else + { + /* show column vectors */ + endpt = maxy - screenv - height + 1; + for (i = 0; i < width; i++) + { + Graphic (); + + SendXY (screenh + i, maxy - screenv); + /* move cursor to start of column */ + SendXY (screenh + i, endpt); /* draw vector to end of column */ + } + } +} +/* ShowRectangle */ + +/*--------------------------------------------------------------------*/ + +void +InitVDU () +{ + vdu_clears_lines = false; + havesentxy = false; /* for first SendXY call */ + charsize = 0; /* the default character size */ + loadedsize = charsize; /* for first TEK4010StartGraphics call */ + charwidth = 13; /* 1024 / 80 = 12.8 */ + maxy = 779; /* some VDUs may want to change this */ + lineht = 26; /* 30 text lines; 26 * 30 = 780 */ + textlinewidth = 80; /* text characters per line */ + /* The dialog region will be the top 4 text lines in Tek mode: + Line 1 = DVI status line, + Line 2 = window status line, + Line 3 = message line, + Line 4 = command line. + The window region will be text lines 5 to 33 in TEK mode. + gt - in NCSA Telnet in TEK mode on my monitor (Viewsonic 5E VGA), + only 30 lines fit. If we use line 33, it wraps around! + */ + + /* The following line numbers assume NCSA Telnet is in VT100 mode. */ + DVIstatusl = 1; /* DVItoVDU assumes top text line = 1 */ + windowstatusl = 2; + messagel = 3; + commandl = 4; +#ifdef VIJAY_BOTTOML + bottoml = 33; /* also number of text lines on screen */ +#else /* according to gt's experience */ + bottoml = 30; /* also number of text lines on screen */ +#endif + + /* The following values assume NCSA Telnet is emulating + a Tektronix 4010. + Note that windowv must be given a value using DVItoVDU's + coordinate scheme, where top left pixel is (0,0). + */ + + /* + Approx. height, in TEK4010 pixels, of 4 text lines, viz. 92 + (i.e. ~ 4 * 780/34), does not work in the case of NCSA Telnet's + Tek mode. Value 115 arrived at by pure trial and error. + */ + windowv = 115; + windowh = 0; + windowht = 780 - windowv; + windowwd = 1024; + + textlinewidth = 72; /* text characters per line - a guess */ + + WriteChar (GS); +} +/* InitTEK4010emu */ + +/*--------------------------------------------------------------------*/ + +/* end vdu.c */ |