summaryrefslogtreecommitdiff
path: root/dviware/dvgtk/vdu.c
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /dviware/dvgtk/vdu.c
Initial commit
Diffstat (limited to 'dviware/dvgtk/vdu.c')
-rw-r--r--dviware/dvgtk/vdu.c547
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 */