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