/* tek4010emu.c - 19:21 GMT +10:00 Thu 29 July 1993 - modifier Geoffrey Tobin */ /* Not a complete description. * This file contains routines for use by TEK4010 emulating VDUs. * A real TEK4010 is not supported. */ /* From input file "../include/globals.p" */ #include "config.h" #include "globals.h" #include "screenio.h" #include "vdu.h" #include "tek4010emu.h" /* Variables Exported, via "tek4010emu.h" */ int maxy, lineht, dragdown; boolean havesentxy; Static int oldhiy; /* for remembering old address in SendXY */ Static int oldhix, oldloy, charwidth; /* set by TEK4010LoadFont and used in TEK4010ShowChar */ 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 (VOID) { WriteChar (GS); /* switch to graphics mode */ } /* Graphic */ /******************************************************************************/ Static Void Alpha (VOID) { WriteChar (US); /* switch to alphanumeric mode */ } /* Alpha */ /******************************************************************************/ #ifdef __STDC__ Void SendXY (int x, int y) #else Void SendXY (x, y) int x; int y; #endif { /* 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 TEK4010StartText (VOID) { Alpha(); } /* TEK4010StartText */ /******************************************************************************/ #ifdef __STDC__ Void TEK4010MoveToTextLine (int line) #else Void TEK4010MoveToTextLine (line) int line; #endif { /* 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 */ } /* TEK4010MoveToTextLine */ /******************************************************************************/ Void TEK4010ClearScreen (VOID) { 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; } /* TEK4010ClearScreen */ /******************************************************************************/ Void TEK4010StartGraphics (VOID) { if (charsize != loadedsize) { /* graphics mode was interrupted */ charsize = loadedsize; dragdown = (charsize + 1) * 5; /* used by VIS500/550 TEK4010ShowChar */ Graphic(); WriteChar (ESC); WriteChar (charsize + '0'); /* recall last TEK4010LoadFont character size */ } Graphic(); havesentxy = false; /* safer to send all bytes anew */ } /* TEK4010StartGraphics */ /******************************************************************************/ #ifdef __STDC__ Void TEK4010LoadFont (Char *fontname, int fontsize, double mag, double hscale, double vscale) #else Void TEK4010LoadFont (fontname, fontsize, mag, hscale, vscale) Char *fontname; int fontsize; double mag; double hscale; double vscale; #endif { /* 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); /* Chooose 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 */ } /* TEK4010LoadFont */ /******************************************************************************/ #ifdef __STDC__ Void TEK4010ShowChar (int screenh, int screenv, Char ch) #else Void TEK4010ShowChar (screenh, screenv, ch) int screenh; int screenv; Char ch; #endif { /* 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 */ } /* TEK4010ShowChar */ /******************************************************************************/ #ifdef __STDC__ Void TEK4010ShowRectangle (int screenh, int screenv, int width, int height, Char ch) #else Void TEK4010ShowRectangle (screenh, screenv, width, height, ch) int screenh, screenv; /* top left pixel */ int width, height; /* of rectangle */ Char ch; /* black pixel */ #endif { /* 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 */ } } } /* TEK4010ShowRectangle */ /******************************************************************************/ Void InitTEK4010emu (VOID) { 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 */ } /* InitTEK4010emu */ /******************************************************************************/ /* end tek4010emu.c */