1 /*
2  * TIPC.C - TI Professional and compatible terminal driver for MicroEmacs.
3  *      This version by Ronald Lepine, Moderator - TI Conference
4  *      Byte Information Exchange.
5  *
6  *      BIX ID. ronlepine
7  *      Programers Room - Ronald Lepine (317) 742-5533  2400 baud
8  *      AT&T: (302) 836-8398
9  *      US Mail:
10  *          Ron Lepine
11  *          434 Shai Circle
12  *          Bear, DE   19701-3604
13  *
14  *      Adapted from code by Danial Lawrence for the IBM-PC.
15  *
16  *      February 1993, David G. Holm (email address: dgh@bix.com)
17  *               Updated to work with new TERM structure in 3.12 BETA 1.
18  *               Updated to work with Borland's C/C++ compilers.
19  *
20  * The routines in this file provide support for the TI-PC and other
21  * compatible terminals. It truely writes directly to the screen RAM to do
22  * screen output. It compiles into nothing if not a TI-PC driver.
23  *
24  * This driver for the TIPC is not the same one that Daniel Lawrence
25  * distributes.  He uses TI's DSRs for most functions as you can see by
26  * looking at the driver in ue311c.arc.  Dan's reverse video
27  * also does not work.  But do not blame him as I'm sure he does not
28  * have a TIPC to test Emacs on and he *is* supportting the TIPC.
29  * [Well, as you can see, it is the one I distribute now! - DAN]
30  * This driver uses direct writes to screen memory except for the message
31  * line like the IBM driver.  In fact I keep TI and IBM versions around by
32  * having my make file replace estruct.h with one that has a IBMPC defined
33  * only when I compile IBMPC.C and then switching back to estruct.h with
34  * TIPC defined. Its last step is of course linking in the correct object
35  * module for each exe.
36  *
37  * You can define any buffer to be reverse video by setting the
38  * foreground to "BLACK" and the background to any other color
39  * such as "cyan" to get Black on Cyan text.  There is no way to get
40  * colors such as 'White on blue' on the TIPC unless it has a
41  * least a 1-plane graphics card in it.  If it does have a graphics
42  * card installed the code to change overall background
43  * color is tied to the $palette variable with the same values as
44  * TI BASIC and the Tech Reference manual section 3.5.2 as well as
45  * being the #define for the color here without the enable attribute.
46  * The text mode forground/background code still works even when you
47  * use a $palette backgound giving you a wide range of what can be
48  * done even though some combinations don't really work too well.
49  *
50  * The only reason that there are any '#if color' directives is because of
51  * the need to maintain structure alignments.  This is because TI's mono
52  * is really 8 shades instead of 8 colors and all attributes  remain the
53  * same.  You can have color and mono attached at the same time and
54  * display on both without any program support or hardware changes.  So
55  * you should define color. It *will* make a difference in other areas of
56  * the MicroEmacs code. You also do not have to do anything special for
57  * the palette code because writing to a nonexistant graphics plane on a
58  * TI causes *no* ill effects (at least according to the tech manual).
59  *
60  * Note that if you recieve MicroEmacs for the TIPC compiled by me
61  * it is compiled/linked so that wildcard file names on the command
62  * line are automagicly expanded in case you want to work with several
63  * similarly named files.
64  *
65  * Changes to the other files to support the the TIPC MEMAPed
66  * version compiled under Zortech C/C++ 1.02 to 2.10 follow.
67  * BTW - The version I used is 2.18 but the earlier versions should
68  * still be similar since I have compiled previous versions under whatever
69  * was current at the time and even the previous ZTC version sometimes.
70  *
71  * [I simply added Ron's #ifdef changes to the master sources - Dan]
72  *
73  *     I once thought there were three ways to correct the problems with
74  * DSR writes to the *25th* line, I now know some don't work.
75  *     One was to check the start register before all screen writes. After
76  * some investigation and testing I found that the  6545A Start of screen
77  * registers are write only.  So there is not way to correct cursor
78  * postioning and line position whenever DOS has changed the register.
79  * Changing the start of screen pointer to offset 0 before screen writes
80  * also didn't solve the problem completely.  As soon as you touched a key
81  * after the error you ended up with the screen properly postioned, but
82  * you had the error message on the screen until that line was updated so
83  * you still ended up using a ^L to correct the screen.
84  *     Two is to capture critical errors (mlwrite and errors are the sources
85  * of DSR writes to the 25th line) and handle them myself (asm is
86  * only clean way) and now looks like the only way it is possible but must
87  * be used in conjuction with a modified method three too.
88  *     Three was change writes to the message line to direct screen writes
89  * and initialize the screen so that a critical error will write to the
90  * text portion of the screen where any repaints would clear it.  The same
91  * problems cropped up that did in number one where you needed to do a ^L
92  * to totally clean up the screen if the error occured while on the message
93  * line anyway so....
94  *     Therefore a combination of two and three is most likely the best
95  * way if it can be done since TI does not recommend mixing DSR and direct
96  * writes to screen (if  I could read the 6545 registers 0Bh and 0Ch I
97  * could manage it though).  This is because the DSR writes *can* change
98  * the screen start register. The problem with a 2+3 solution is mainly
99  * that the extra code to handle single character writes, directly
100  * controlling the cursor though the CRTC cursor registers, and the
101  * intercept/write/read error code handling bloats the code a bit and
102  * coding in anything but assembly language (which  then needs to be
103  * interfaced to each C compiler that might be in use) is the only reasonable
104  * way.  I just came came to the conclusion that it wasn't worth it since
105  * a ^L will clear things up anyway after the error is corrected.
106  *
107  * 12/29/89 -
108  *   Changed lnptr, sline, and scptr to char/char*'s because TI writes
109  *   only a character at a screen position and IBM a char + attribute.  TI's
110  *   attributes are kept up by the hardware except when changed. So we only
111  *   write a char at a time, not an int like the IBM code did.  This also
112  *   corrected a minor bug with the message line eeol's which is why I
113  *   looked at the driver code again.
114  *
115  * 12/30/89 -
116  *   added the capability of setting the background on machines with
117  *   graphics by setting the palette string with a number from 0 to 7.
118  *   you do this with ^XA $palette  (note small letters) and a value.
119  *   Values >= 8 will work since I do modulo division on the value
120  *   but results are the same as the color values in TI BASIC.  The
121  *   code, as always, works on all TI's but will not produce a change
122  *   on non-graphics equiped TI's.  This code also does not need a color
123  *   monitor to work since a TI doesn't know what kind of monitor is
124  *   attached and may even have color and mono attached at once.
125  *
126  *   With the code set up so you can still do reverse video on any TI
127  *   by defining BLACK and yellow (or any other background color) you
128  *   have a large variety of posible screen setups.  So experiment.
129  *
130  * 12/31/89 to 1/7/90 - experimented with various methods of eliminating
131  *   problems with mixed DSR/Direct_Memory writes.  Decided not to really
132  *   attempt a solution at this time.  Write Ron Lepine if you have
133  *   any feelings/suggestions on this problem, they are welcome.
134  *
135  * 1-9-90
136  *   3.10.c(Beta) New IBMPC reverse video code added to TIPC driver.
137  *
138  *   Addional changes to 3.10.c(beta) to get it to compile with Zortech C/C++
139  *     **** NOTE THESE CHANGES ARE NO LONGER NEEDED FOR ZTC 2.10 *****
140  *      isearch line 172/5, 191 - change lines to
141  *
142  *            if (kfunc == &forwsearch || kfunc == &forwhunt ||
143  *                kfunc == &backsearch || kfunc == &backhunt)
144  *            {
145  *                dir = (kfunc == &backsearch || kfunc == &backhunt)?
146  *                REVERSE: FORWARD;
147  *
148  * 5-26-90
149  *   Updated first part of this file to reflect 3.11beta line numbers
150  *   while compiling 3.11 beta under Zortech C/C++ 2.1.
151  *
152  * 6-04-91
153  *   Added last eight needed values to ctrans[] so standard emacs.rc file
154  *   now works.
155  */
156 
157 #define termdef 1                       /* don't define "term" external */
158 
159 #include        <stdio.h>
160 #include        "estruct.h"
161 #include        "eproto.h"
162 #include        "edef.h"
163 #include        "elang.h"
164 
165 #if     TIPC
166 
167 #define NROW    25                      /* Screen height.               */
168 #define NCOL    80                      /* Screen width                 */
169 #define MARGIN  8                       /* size of minimim margin and   */
170 #define SCRSIZ  64                      /* scroll size for extended lines */
171 #define NPAUSE  200                     /* # times thru update to pause */
172 #define BEL     0x07                    /* BEL character.               */
173 #define ESC     0x1B                    /* ESC character.               */
174 #define SPACE   32                      /* space character              */
175 #define SCADD       0xDE000000L         /* address of screen RAM        */
176 #define ATTRADD     0xDE001800L         /* Address for attribute latch  */
177 #define BLUE_PLANE  0xC0000000L         /* Address Blue graphics plane  */
178 #define RED_PLANE   0xC8000000L         /* Address Red graphics plane   */
179 #define GREEN_PLANE 0xD0000000L         /* Address Green graphics plane */
180 #define CRTC_REG    0xDF810000L         /* 6545 CRT Controller access addr */
181 #define CHAR_ENABLE     0x08            /* TI attribute to show char    */
182 #define TI_REVERSE      0x10            /* TI attribute to reverse char */
183 #define BLACK   0+CHAR_ENABLE           /* TI attribute for Black       */
184 #define BLUE    1+CHAR_ENABLE           /* TI attribute for Blue        */
185 #define RED     2+CHAR_ENABLE           /* TI attribute for Red         */
186 #define MAGENTA 3+CHAR_ENABLE           /* TI attribute for Magenta     */
187 #define GREEN   4+CHAR_ENABLE           /* TI attribute for Green       */
188 #define CYAN    5+CHAR_ENABLE           /* TI attribute for Cyan        */
189 #define YELLOW  6+CHAR_ENABLE           /* TI attribute for Yellow      */
190 #define WHITE   7+CHAR_ENABLE           /* TI attribute for White       */
191 
192 
193 PASCAL NEAR ttopen();               /* Forward references.          */
194 PASCAL NEAR ttgetc();
195 PASCAL NEAR ttputc();
196 PASCAL NEAR ttflush();
197 PASCAL NEAR ttclose();
198 PASCAL NEAR timove();
199 PASCAL NEAR tieeol();
200 PASCAL NEAR tieeop();
201 PASCAL NEAR tibeep();
202 PASCAL NEAR tiopen();
203 PASCAL NEAR tikopen();
204 PASCAL NEAR tirev();
205 PASCAL NEAR ticres();
206 PASCAL NEAR ticlose();
207 PASCAL NEAR tikclose();
208 PASCAL NEAR tiputc();
209 PASCAL NEAR tifcol();
210 PASCAL NEAR tibcol();
211 PASCAL NEAR scinit();
212 
213 int     revflag = FALSE;        /* are we currently in rev video?       */
214 int     cfcolor = -1;           /* current forground color              */
215 int     cbcolor = -1;           /* current background color             */
216 int     ctrans[] =              /* ANSI to TI color translation table   */
217         {BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE,
218          BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE};
219 
220 char *scptr[NROW];                      /* pointer to screen lines-8 bit on ti *
221 char sline[NCOL];                       /* screen line image               */
222 
223 #if  __TURBOC__
224 
225 char far * scadd       = SCADD;        /* address of screen ram           */
226 char far * attradd     = ATTRADD;      /* address of attribute latch      */
227 char far * blue_plane  = BLUE_PLANE;   /* address of blue graphics plane  */
228 char far * red_plane   = RED_PLANE;    /* address of red graphics plane   */
229 char far * green_plane = GREEN_PLANE;  /* address of green graphics plane */
230 char far * crtc_reg    = CRTC_REG;     /* 6545 CRT controller address     */
231 
232 #else
233 
234 long scadd       = SCADD;               /* address of screen ram           */
235 long attradd     = ATTRADD;             /* address of attribute latch      */
236 long blue_plane  = BLUE_PLANE;          /* address of blue graphics plane  */
237 long red_plane   = RED_PLANE;           /* address of red graphics plane   */
238 long green_plane = GREEN_PLANE;         /* address of green graphics plane */
239 long crtc_reg    = CRTC_REG;            /* 6545 CRT controller address     */
240 
241 #endif
242 
243 /*
244  * Standard terminal interface dispatch table. Most of the fields point into
245  * "termio" code.
246  */
247 TERM    term    = {
248         NROW-1,
249         NROW-1,
250         NCOL,
251         NCOL,
252         0,
253         0,
254         MARGIN,
255         SCRSIZ,
256         NPAUSE,
257         tiopen,
258         ticlose,
259         tikopen,
260         tikclose,
261         ttgetc,
262         tiputc,
263         ttflush,
264         timove,
265         tieeol,
266         tieeop,
267         tieeop,
268         tibeep,
269         tirev,
270         ticres
271 #if COLOR
272         , tifcol,
273         tibcol
274 #endif
275 };
276 
277 extern union REGS rg;
278 
279 
tifcol(color)280 PASCAL NEAR tifcol(color)           /* set the current output color */
281 
282 int color;                          /* color to set */
283 {
284     cfcolor = ctrans[color];
285 }
286 
287 
tibcol(color)288 PASCAL NEAR tibcol(color)           /* set the current background color */
289                                     /* color to set */
290 int color;
291 {
292     cbcolor = ctrans[color];
293 }
294 
295 
timove(row,col)296 PASCAL NEAR timove(row, col)
297 
298 int row;
299 int col;
300 {
301     rg.h.ah = 2;            /* set cursor position function code */
302     rg.h.dh = col;
303     rg.h.dl = row;
304     int86(0x49, &rg, &rg);
305 }
306 
307 
tieeol()308 PASCAL NEAR tieeol()        /* erase to the end of the line */
309 
310 {
311     int i;                  /* loop variable                    */
312     char *lnptr;            /* pointer to the destination line  */
313     int ccol;               /* current column cursor lives      */
314     int crow;               /* current row  cursor lives        */
315 
316     /* find the current cursor position */
317     rg.h.ah = 3;            /* read cursor position function code */
318     int86(0x49, &rg, &rg);
319     ccol = rg.h.dh;         /* record current column */
320     crow = rg.h.dl;         /* and row */
321 
322     lnptr = &sline[0];      /* set things up */
323     for (i=0; i < term.t_ncol; i++)
324         *lnptr++ = SPACE;
325 
326     _fmemset(attradd, cfcolor, 1);                /* write current attrs to latc
327     movmem(&sline[0], scptr[crow]+ccol, term.t_ncol-ccol);
328 
329 }
330 
331 
332 PASCAL NEAR tiputc(ch)      /* put a character at the current position */
333                             /* in the current colors */
334 int ch;
335 {
336     _fmemset(attradd, cfcolor, 1);    /* write current attrs to latch */
337     rg.h.ah = 0x0E;                 /* write char to screen with DSR */
338     rg.h.al = ch;
339     int86(0x49, &rg, &rg);
340 }
341 
342 
343 PASCAL NEAR tieeop()        /* Actually a clear screen */
344 
345 {
346     rg.h.ah = 0x13;         /* Clear Text Screen, Home Cursor and */
347     int86(0x49, &rg, &rg);  /* Set screen start register to 0     */
348 }
349 
350 
351 PASCAL NEAR tirev(state)    /* change reverse video state */
352 
353 int state;          /* TRUE = reverse, FALSE = normal */
354 {
355     revflag = state;
356 }
357 
358 
359 PASCAL NEAR ticres()    /* Change screen resolution. Should we add the  */
360                         /* the 720x350 mode besides the normal 720x300  */
361                         /* mode for those who can handle it?  It really */
362                         /* gains us nothing since we don't gain lines   */
363                         /* and the code works when started in that res. */
364                         /* Let me (Ron Lepine) know what you think      */
365 {
366     return(TRUE);
367 }
368 
369 
370 PASCAL NEAR tibeep()
371 
372 {
373     bdos(6, BEL, 0);
374 }
375 
376 
377 PASCAL NEAR tiopen()
378 
379 {
380     strcpy(sres, "NORMAL");
381     revexist = TRUE;
382     revflag = FALSE;
383     scinit();
384     ttopen();
385 }
386 
387 
388 PASCAL NEAR tikopen()
389 
390 {
391     /* Does nothing */
392 }
393 
394 
395 PASCAL NEAR ticlose()
396 
397 {
398     _fmemset(attradd, WHITE, 1);  /* write normal attrbute to latch      */
399                     /* Makes sure we return with a normal color        */
400                     /* and not reverse video or such.  Attribute       */
401                     /* Latch will otherwise hold last color and        */
402                     /* attributes it wrote to the screen, which in     */
403                     /* some cases is reverse video.                    */
404 }
405 
406 
407 PASCAL NEAR tikclose()
408 
409 {
410     _fmemset(attradd, WHITE, 1);  /* write normal attrbute to latch         */
411                     /* Dan doesn't close the the terminal when shelling   */
412                     /* This ensures the shell starts with a normal color  */
413                     /* the same way ticlose does without changing         */
414                     /* *any* other source file.  The only real reason we  */
415                     /* place it here is to change as few files as posible */
416 }
417 
418 
419 PASCAL NEAR scinit()    /* initialize the screen head pointers to */
420                         /* logical screen */
421 {
422     union {
423         long laddr;     /* long form of address */
424         char *paddr;    /* pointer form of address */
425     } addr;
426 
427     char i;
428 
429     tieeop();           /* set logical = physical start of screen   */
430         /* initialize The screen pointer array */
431     for (i = 0; i < NROW; i++) {
432         addr.laddr = scadd + (long)(NCOL * i);
433         scptr[i] = addr.paddr;
434     }
435 }
436 
437 
438 PASCAL NEAR scwrite(int row, char *outstr, int forg, int bacg, int revleft, int
439 /* write a line out */
440 {
441     char    *lnptr;         /* Pointer to the destination line */
442     char    i;
443 
444     /* Write the attribute byte to latch and setup the screen pointer      */
445     /* If forg == 0 then you can change the back ground to color.  TI      */
446     /* won't let you use two colors for forground and background unless    */
447     /* you have graphics and set the graphics color to your background     */
448     /* This is enabled in this driver though the $palette variable         */
449 
450     if ((forg != 0) & (!revflag)) {
451         forg = ctrans[forg];
452         _fmemset(attradd, forg, 1);
453     }else if ((forg != 0) & (revflag)) {
454         forg = ctrans[forg] + TI_REVERSE;
455         _fmemset(attradd, forg, 1);
456     }else{
457         bacg = ctrans[bacg] + TI_REVERSE;
458         _fmemset(attradd, bacg, 1);
459     }
460     lnptr = &sline[0];
461     for (i=0; i<term.t_ncol; i++)
462         *lnptr++ = outstr[i];
463     /* and send the string out */
464     movmem(&sline[0], scptr[row], term.t_ncol);
465 }
466 
467 
468 PASCAL NEAR spal(palette)      /* change palette string */
469 
470 char *palette;
471 {
472     /* Turns on a graphics plane if it is installed         */
473     /* Set value of $palette works the same as in TI BASIC  */
474     /* and the Technical Reference manual section 3.5.2     */
475     /* ie. Set $palette to 7 for a white background or to   */
476     /* 1 for a blue background.                             */
477     /* Causes no problems when graphics are not installed   */
478     /* so there is no reason to check for the number of     */
479     /* graphics planes installed.                           */
480 
481     switch ((atoi(palette) % 8)) {
482         case 0:
483             _fmemset(blue_plane,   0,  0x7fff);
484             _fmemset(red_plane,    0,  0x7fff);
485             _fmemset(green_plane,  0,  0x7fff);
486             break;
487         case 1:
488             _fmemset(blue_plane,   0xff,  0x7fff);
489             _fmemset(red_plane,    0,     0x7fff);
490             _fmemset(green_plane,  0,     0x7fff);
491             break;
492         case 2:
493             _fmemset(blue_plane,   0,    0x7fff);
494             _fmemset(red_plane,    0xff, 0x7fff);
495             _fmemset(green_plane,  0,    0x7fff);
496             break;
497         case 3:
498             _fmemset(blue_plane,   0xff, 0x7fff);
499             _fmemset(red_plane,    0xff, 0x7fff);
500             _fmemset(green_plane,  0,    0x7fff);
501             break;
502         case 4:
503             _fmemset(blue_plane,   0,    0x7fff);
504             _fmemset(red_plane,    0,    0x7fff);
505             _fmemset(green_plane,  0xff, 0x7fff);
506             break;
507         case 5:
508             _fmemset(blue_plane,   0xff, 0x7fff);
509             _fmemset(red_plane,    0,    0x7fff);
510             _fmemset(green_plane,  0xff, 0x7fff);
511             break;
512         case 6:
513             _fmemset(blue_plane,   0,    0x7fff);
514             _fmemset(red_plane,    0xff, 0x7fff);
515             _fmemset(green_plane,  0xff, 0x7fff);
516             break;
517         case 7:
518             _fmemset(blue_plane,   0xff, 0x7fff);
519             _fmemset(red_plane,    0xff, 0x7fff);
520             _fmemset(green_plane,  0xff, 0x7fff);
521             break;
522     }
523 }
524 
525 
526 #if     FLABEL
527 PASCAL NEAR fnclabel(f, n)      /* label a function key */
528 
529 int f,n;        /* default flag, numeric argument [unused] */
530 
531 {
532         /* on machines with no function keys...don't bother */
533         /* TI/IBM function keys are handled in other code   */
534         return(TRUE);
535 }
536 #endif
537 
538 
539 #else
540 tihello()
541 {
542 }
543 #endif
544