|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T o
Length: 13175 (0x3377) Types: TextFile Names: »otek4010vdu.c«
└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12 └─⟦883b7f77d⟧ »dvi2vdu.tar.Z« └─⟦f158c222e⟧ └─⟦this⟧ »dvi2vdu/dvi2vdu-1.1J/src/otek4010vdu.c«
/* Original Author: Andrew Trevorrow Implementation: Modula-2 under VAX/UNIX 4.2 BSD Date Started: June, 1986 Description: Implements the routines used in VDU-specific modules that emulate a Tektronix 4010 terminal (VIS500/550, VT640). The screen is assumed to be 780 pixels high by 1024 pixels wide. (The actual resolution of an emulating screen may be different, but such terminals provide automatic scaling.) The bottom left pixel is the point (x=0,y=0); x coordinates increase to the right and y coordinates increase up the screen. DVItoVDU uses a coordinate scheme in which horizontal (=h) coordinates also increase to the right but vertical (=v) coordinates increase DOWN the screen, i.e. the top left pixel on the screen is the point (h=0,v=0). This means that the Tektronix 4010 routines will have to do a simple translation of the vertical coordinates passed by DVItoVDU. This version converted to C and ported to BSD and System V UNIX by some chaps at Kernel Technology up to September 1989. Contact mjh@uk.co.kernel (Mark J. Hewitt) with bug fixes etc. Involved were: Mark J. Hewitt Dave Dixon Marc Hadley */ #include "def.h" static char *sccsid[] = "@(#)tek4010vdu.c 1.1"; unsigned int maxy = 779; /* TEK4010 vertical coordinates are in 0..maxy; some VDUs may change default value of 779 */ unsigned int lineht = 26; /* height in TEK4010 pixels of a text line; some VDUs may change default value of 26 */ unsigned int dragdown ; /*550 VDUs can use this value to drag Terse character baseline down to TeX ref pt */ short havesentxy = 0x00; /* don't need to send all 4 bytes of address? */ unsigned int oldhiy; /* for remembering old address in SendXYtek() */ unsigned int oldhix; unsigned int oldloy; unsigned int charwidth = 13; /* set by LoadFont and used in ShowChar */ unsigned int loadedsize = 0; /* remember alpha size set by last LoadFont; 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. */ unsigned int charsize = 0; /* used to select alpha character size */ /******************************************************************************/ void SendXYtek (x, y) unsigned int x, 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. */ unsigned int hiy, loy, hix, lox; short sendhix; /* we assume y is in [0..maxy] and x is in [0..1023] */ hiy = ((int) ' ') + (y / 32); hix = ((int) ' ') + (x / 32); loy = ((int) '`') + (y % 32); lox = ((int) '@') + (x % 32); if (havesentxy) { if (hiy != oldhiy) { Write ((char) hiy); oldhiy = hiy; } sendhix = (hix != oldhix); if ((loy != oldloy) || sendhix) { Write ((char) loy); oldloy = loy; } if (sendhix) { Write ((char) hix); oldhix = hix; } Write ((char) lox); } else /* send first 4 bytes */ { Write ((char) hiy); oldhiy = hiy; Write ((char) loy); oldloy = loy; Write ((char) hix); oldhix = hix; Write ((char) lox); havesentxy = TRUE; } /* SYSDEP: We assume XON/XOFF flow control is enabled to avoid data loss. */ } /******************************************************************************/ Void TEK4010StartText () { /* DVItoVDU will only call MoveToTextLine, ClearTextLine, ClearScreen and ResetVDU while in text mode. */ Write (US); } /******************************************************************************/ Void TEK4010MoveToTextLine (line) unsigned 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. */ Write (GS); /* switch to graphics mode */ SendXYtek (0, maxy + 1 - (line * lineht)); Write (ESC); /* reset alpha character size */ Write ('0'); charsize = 0; charwidth = 13; Write (US); /* back to alpha mode */ } /******************************************************************************/ Void TEK4010ClearScreen () { Write (GS); /* make sure we're in graphics mode */ Write (ESC); Write (FF); /* erase graphics and put in alpha mode */ havesentxy = FALSE; /* ESC FF will home cursor */ charsize = 0; /* ESC FF resets character size */ charwidth = 13; } /******************************************************************************/ Void TEK4010StartGraphics () { /* DVItoVDU will only call LoadFont, ShowChar and ShowRectangle while in graphics mode. */ if (charsize != loadedsize) { /* graphics mode was interrupted */ charsize = loadedsize; dragdown = (charsize + 1) * 5;/* used by VIS500/550 ShowChar */ Write (GS); Write (ESC); Write ((char) (((int) '0') + charsize)); /* recall last LoadFont character size */ } Write (GS); havesentxy = FALSE; /* safer to send all location bytes anew */ } /******************************************************************************/ /*ARGSUSED*/ Void TEK4010LoadFont (fontname, fontsize, localmag, hscale, vscale) char fontname[]; unsigned int fontsize; float localmag, hscale, vscale; /* Use the given fontsize to select an appropriate character size (based on horizontal scaling only!) for future ShowChar calls. */ { unsigned int newsize; /* convert fontsize into scaled screen pixels using localmag and hscale */ fontsize = (int) (((float) fontsize) * localmag * hscale + 0.5); /* Chooose one of the 4 alpha mode character sizes based on fontsize: charsize maxchars/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; Write (ESC); Write ((char) (((int) '0') + charsize)); } /* 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 ShowChar. */ dragdown = (charsize + 1) * 5;/* used by VIS500/550 ShowChar */ Write (GS); /* must exit in graphics mode */ } /******************************************************************************/ Void TEK4010ShowChar (screenh, screenv, ch) unsigned int screenh, screenv; char ch; /* Show the given Terse character (mapped to ASCII) at the given ref pt. We use the charwidth set by last LoadFont call. */ { char newch; /* = TeXtoASCII[ch] */ /* shift character left if it will overlap right edge of screen */ if ((screenh + charwidth) > 1023) { screenh = 1023 - charwidth; } /* we assume StartGraphics, LoadFont or last ShowChar has just sent GS */ SendXYtek (screenh, maxy - screenv);/* move cursor to ref pt */ /* We use TeXtoASCII to map ch into a comparable ASCII character, apart from most of the ? characters which we attempt to simulate. */ Write (US); /* enter alpha mode */ newch = TeXtoASCII[ch]; if (newch != '?') { /* newch is similar to TeX ch */ Write (newch); } else { /* attempt to display something other than ? */ switch (ch) { case 013: case 014: case 015: case 016: case 017: /* ff, fi, fl, ffi, ffl */ ; { Write ('f'); /* only simulate rest of ligature if room at right edge */ if ((screenh + 2 * charwidth - (charwidth / 2)) <= 1023) { Write (GS); SendXYtek (screenh + charwidth - (charwidth / 2), maxy - screenv); Write (US); switch (ch) { case 013: { Write ('f'); break; } case 014: { Write ('i'); break; } case 015: { Write ('l'); break; } case 016: case 017: { Write ('f'); if (screenh + 3 * charwidth - 2 * (charwidth / 2) <= 1023) { Write (GS); SendXYtek (screenh + 2 * charwidth - 2 * (charwidth / 2), maxy - screenv); Write (US); if (ch == 016) Write ('i'); else Write ('l'); } } } } break; } case 031: { Write ('B'); break; } /* German sharp S */ case 032: case 033: case 035: case 036: /* diphthongs: ae, oe, AE, OE */ { switch (ch) { case 032: { Write ('a'); break; } case 033: { Write ('o'); break; } case 035: { Write ('A'); break; } case 036: { Write ('O'); break; } } if ((screenh + 2 * charwidth - (charwidth / 2)) <= 1023) { Write (GS); SendXYtek (screenh + charwidth - (charwidth / 2), maxy - screenv); Write (US); switch (ch) { case 032: case 033: { Write ('e'); break; } case 035: case 036: { Write ('E'); break; } } } break; } case 034: case 037: /* Scandinavian slashed o and O */ { switch (ch) { case 034: { Write ('o'); break; } case 037: { Write ('O'); break; } } Write (GS); SendXYtek (screenh, maxy - screenv);/* overwrite */ Write (US); Write ('/'); break; } case 040: { Write ('\''); break; } /* Polish suppressed l and L */ default: Write ('?'); } } Write (GS); /* must exit in graphics mode */ } /******************************************************************************/ /*ARGSUSED*/ Void TEK4010ShowRectangle (screenh, screenv,/* top left pixel */ width, height, /* of rectangle */ ch) /* black pixel */ unsigned int screenh, screenv, width, 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. */ { unsigned int i, endpt; /* DVItoVDU ensures width and height > 0 */ if (height < width) { /* show row vectors */ endpt = screenh + width - 1; for (i = 0; i <= height - 1; i++) { Write (GS); SendXYtek (screenh, maxy - (screenv + i));/* move cursor to start of row */ SendXYtek (endpt, maxy - (screenv + i));/* draw vector to end of row */ } } else /* show column vectors */ { endpt = maxy - (screenv + height - 1); for (i = 0; i <= width - 1; i++) { Write (GS); SendXYtek (screenh + i, maxy - screenv);/* move cursor to start of column */ SendXYtek (screenh + i, endpt);/* draw vector to end of column */ } } } /******************************************************************************/ Void TEK4010ClearTextLine (line) unsigned int line; { Write (CAN); /* switch to Alphanumeric mode */ TEK4010MoveToTextLine (line); /* move to start of line */ Write (ESC); Write ('K'); /* erase to end of line */ } Void TEK4010ResetVDU () { Write (CAN); } void InitTEK4010 () { DVIstatusl = 1; /* DVItoVDU assumes top text line = 1 */ windowstatusl = 2; messagel = 3; commandl = 4; bottoml = 33; /* also number of text lines on VIS500 screen */ /* The above values assume the VIS500 is in Alphanumeric mode; the following values assume it 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). */ windowv = 92; /* approx. height in TEK4010 pixels of 4 text lines; i.e. 4 * 780/34 */ windowh = 0; windowht = 780 - windowv; windowwd = 1024; MoveToTextLine = TEK4010MoveToTextLine; ClearTextLine = TEK4010ClearTextLine; ClearScreen = TEK4010ClearScreen; StartText = TEK4010StartText; StartGraphics = TEK4010StartGraphics; LoadFont = TEK4010LoadFont; ShowChar = TEK4010ShowChar; ShowRectangle = TEK4010ShowRectangle; ResetVDU = TEK4010ResetVDU; Write (GS); Write (ESC); Write ('@'); /* solid fill for rectangular draw and fill */ Write (CAN); }