1 /* $Id: tty.c,v 1.1.1.1 2000/06/27 01:48:01 amura Exp $ */
2 /*
3 * Name: MG 2a
4 * Amiga console device virtual terminal display
5 * Last Edit: 29-Nov-87 mic@emx.cc.utexas.edu
6 * Created: 19-Apr-86 mic@emx.cc.utexas.edu
7 *
8 * Drives the Amiga console device display. The code is basically
9 * like the termcap driver in that it uses the console device
10 * scrolling region. It also has some hacks to manage the console
11 * device colors. The latest hack is to inform the terminal I/O
12 * driver when we intend to do an escape sequence; this allows the
13 * terminal I/O driver to turn off the cursor without breaking up
14 * the sequences, leading to a garbled screen.
15 */
16
17 /*
18 * $Log: tty.c,v $
19 * Revision 1.1.1.1 2000/06/27 01:48:01 amura
20 * import to CVS
21 *
22 */
23
24 #include <exec/types.h>
25 #include <exec/nodes.h>
26 #include <exec/lists.h>
27 #include <exec/tasks.h>
28 #include <exec/ports.h>
29 #include <exec/io.h>
30 #include <devices/console.h>
31 #include <libraries/dos.h>
32 #include <graphics/clip.h>
33 #include <graphics/view.h>
34 #include <graphics/rastport.h>
35 #include <graphics/layers.h>
36 #include <graphics/text.h>
37 #include <graphics/gfxbase.h>
38 #ifndef MANX
39 #include <intuition/intuitionbase.h>
40 #endif
41 #include <intuition/intuition.h>
42
43 #undef TRUE
44 #undef FALSE
45 #include "config.h" /* Dec. 15, 1992 by H.Ohkubo */
46 #include "def.h"
47
48 #define BEL 0x07 /* BEL character. */
49 #define ESC 0x1B /* ESC character. */
50 #define LF 0x0A /* Linefeed character */
51 #define CSI 0x9B /* Command Sequence Introducer */
52
53 extern int ttrow;
54 extern int ttcol;
55 extern int tttop;
56 extern int ttbot;
57 extern int tthue;
58
59 int tceeol = 3; /* Costs, ANSI display. */
60 int tcinsl = 17;
61 int tcdell = 16;
62
63
64 #ifdef CHANGE_COLOR
65 short mode_rendition = MODE_RENDITION, /* set standard colors */
66 text_rendition = TEXT_RENDITION,
67 text_fg = TEXT_FG + 30,
68 text_bg = TEXT_BG + 40,
69 mode_fg = MODE_FG + 30,
70 mode_bg = MODE_BG + 40;
71 #else /* colors are hard-coded */
72 #define mode_rendition MODE_RENDITION
73 #define text_rendition TEXT_RENDITION
74 #define text_fg (TEXT_FG + 30)
75 #define text_bg (TEXT_BG + 40)
76 #define mode_fg (MODE_FG + 30)
77 #define mode_bg (MODE_BG + 40)
78 #endif
79
80 #ifdef SUPPORT_ANSI
81 VOID asciiparm(int) ;
82 #else
83 VOID asciiparm() ;
84 #endif
85 /* VOID ttnowindow() ; */
86 VOID ttwindow() ;
87
88 extern struct Screen WBInfo; /* For Font Sensitive by H.Konishi */
89
90 /*
91 * Initialize the terminal when the editor
92 * Initialize the virtual terminal.
93 * Set the console device's top edge below
94 * the front-to-back gadgets, to avoid
95 * garbage when scrolling.
96 */
97 /* VOID */
ttinit()98 ttinit()
99 {
100 ttputc(CSI);
101 asciiparm(TOP_OFFSET);
102 ttputc('y');
103 }
104
105 /*
106 * Clean up the terminal, in anticipation of
107 * a return to the command interpreter. This
108 * is a no-op on the Amiga, since the window
109 * is deleted anyway.
110 */
111 /* VOID */
tttidy()112 tttidy()
113 {
114 }
115
116 /*
117 * Move the cursor to the specified origin 0 row and column position. Try to
118 * optimize out extra moves; redisplay may have left the cursor in the right
119 * location last time!
120 */
121 /* VOID */
ttmove(row,col)122 ttmove(row, col)
123 {
124 if (ttrow!=row || ttcol!=col) {
125 ttnflush(8); /* flush if buffer too full */
126 ttputc(CSI);
127 asciiparm(row+1);
128 ttputc(';');
129 asciiparm(col+1);
130 ttputc('H');
131 ttrow = row;
132 ttcol = col;
133 }
134 }
135
136 /*
137 * Erase to end of line.
138 */
139 /* VOID */
tteeol()140 tteeol()
141 {
142 ttnflush(2); /* flush if not enough room to fit in buffer */
143 ttputc(CSI);
144 ttputc('K');
145 }
146
147 /*
148 * Erase to end of page.
149 */
150 /* VOID */
tteeop()151 tteeop()
152 {
153 ttnflush(12); /* flush (but only if not enough room for seq */
154 ttputc(CSI);
155 asciiparm((tthue == CTEXT) ? text_rendition : mode_rendition);
156 ttputc(';');
157 asciiparm(text_fg);
158 ttputc(';');
159 asciiparm(text_bg);
160 ttputc('m');
161 ttputc(CSI); /* clear to end of display */
162 ttputc('J');
163 }
164
165 /*
166 * Make a noise.
167 */
168 /* VOID */
ttbeep()169 ttbeep()
170 {
171 ttputc(BEL);
172 ttflush();
173 }
174
175 /*
176 * Convert a number to decimal
177 * ascii, and write it out. Used to
178 * deal with numeric arguments.
179 */
180 VOID
asciiparm(n)181 asciiparm(n)
182 register int n;
183 {
184 if (n > 9)
185 asciiparm(n/10);
186 #ifdef BUGFIX /* Jan.4,1993 by H.Ohkubo */
187 ttputc((unsigned char)((n%10) + '0'));
188 #else /* Original code */
189 ttputc((n%10) + '0');
190 #endif
191 }
192
193 /*
194 * Insert a block of blank lines onto the
195 * screen, using a scrolling region that starts at row
196 * "row" and extends down to row "bot". Deal with the one
197 * line case, which is a little bit special, with special
198 * case code.
199 */
200 /* VOID */
ttinsl(row,bot,nchunk)201 ttinsl(row, bot, nchunk)
202 {
203 if (row == bot) { /* Funny case. */
204 if (nchunk != 1)
205 panic("ttinsl: nchunk != 1");
206 ttmove(row, 0);
207 tteeol();
208 return;
209 }
210 ttmove(1+bot-nchunk, 0);
211 if (nchunk > 0) {
212 ttwindow(row, bot);
213 ttnflush(4); /* don't break the sequence */
214 ttputc(CSI);
215 asciiparm(nchunk);
216 ttputc('T'); /* Scroll scrolling region down */
217 ttnowindow();
218 }
219 }
220
221 /*
222 * Delete a block of lines, with the uppermost
223 * line at row "row", in a screen slice that extends to
224 * row "bot". The "nchunk" is the number of lines that have
225 * to be deleted. It's really easy with the console
226 * device scrolling region.
227 */
228 /* VOID */
ttdell(row,bot,nchunk)229 ttdell(row, bot, nchunk)
230 {
231 if (row == bot) { /* One line special case */
232 ttmove(row, 0);
233 tteeol();
234 return;
235 }
236 if (nchunk > 0) {
237 ttwindow(row, bot);
238 ttnflush(4); /* don't break esc. sequence */
239 ttputc(CSI);
240 asciiparm(nchunk);
241 ttputc('S'); /* Scroll scrolling region up */
242 ttnowindow();
243 }
244 ttrow = HUGE;
245 ttcol = HUGE;
246 ttmove(bot-nchunk,0);
247 }
248
249 /*
250 * This routine sets the scrolling window on the display to go from line
251 * "top" to line "bot" (origin 0, inclusive). The caller checks for the
252 * pathalogical 1 line scroll window that doesn't work right on all
253 * systems, and avoids it. The "ttrow" and "ttcol" variables are set
254 * to a crazy value to ensure that ttmove() actually does something.
255 */
256
257 extern struct Window *EmW; /* The window MG uses */
258
259 VOID
ttwindow(top,bot)260 ttwindow(top,bot)
261 {
262 if (tttop != top || ttbot != bot) {
263 ttnflush(10); /* Flush if necessary */
264 ttputc(CSI); /* Home cursor */
265 ttputc('H');
266
267 ttputc(CSI); /* Set top offset */
268 asciiparm(TOP_OFFSET + top * FontHeight(EmW));
269 ttputc('y');
270
271 ttputc(CSI);
272 asciiparm(bot - top + 1); /* Set page length */
273 ttputc('t');
274
275 ttrow = HUGE; /* Force cursor reset */
276 ttcol = HUGE;
277 tttop = top; /* Save region state */
278 ttbot = bot;
279 }
280 }
281
282 /*
283 * Switch to full screen scrolling
284 */
285 /* VOID */
ttnowindow()286 ttnowindow()
287 {
288 ttnflush(10); /* Flush if necessary */
289 ttputc(CSI); /* Home cursor */
290 ttputc('H');
291
292 ttputc(CSI); /* Set top offset to normal */
293 asciiparm(TOP_OFFSET);
294 ttputc('y');
295
296 ttputc(CSI); /* Set page length to nrow */
297 asciiparm(nrow);
298 ttputc('t');
299
300 ttrow = HUGE; /* Make cursor unknown. */
301 ttcol = HUGE;
302 tttop = HUGE;
303 ttbot = HUGE;
304 }
305
306 #ifdef CHANGE_COLOR
307 /*
308 * Set the rendition of the mode line by
309 * selecting colors from the following:
310 * 0 -- plain text
311 * 1 -- bold-face
312 * 3 -- italic
313 * 4 -- underscore
314 * 7 -- inverse video
315 * Certain of these selections may be less than
316 * appealing :-)
317 */
318
ttmode(f,n)319 ttmode(f, n)
320 {
321 register int s;
322 char buf[2];
323
324 if (!(f & FFARG)) {
325 if ((s = ereply("Set mode line rendition (0-7): ",
326 buf, sizeof(buf))) != TRUE)
327 return (s);
328 n = atoi(buf);
329 }
330 if (n < 0 || n > 7)
331 return (FALSE);
332
333 mode_rendition = n; /* store the color */
334 sgarbf = TRUE;
335 return (TRUE);
336 }
337
338 /*
339 * Set the rendition of the text area.
340 * Most of these selections will be
341 * less than appealing :-]
342 */
343
tttext(f,n)344 tttext(f, n)
345 {
346 register int s;
347 char buf[2];
348
349 if (!(f & FFARG)) {
350 if ((s = ereply("Set text rendition (0-7): ",
351 buf, sizeof(buf))) != TRUE)
352 return (s);
353 n = atoi(buf);
354 }
355 if (n < 0 || n > 7)
356 return (FALSE);
357
358 text_rendition = n; /* store the color */
359 sgarbf = TRUE;
360 return (TRUE);
361 }
362
363 /*
364 * Set foreground color for entire window
365 * to a value between 30 and 37, which
366 * corresponds to the arguments 0-7.
367 * This requires a total refresh, which
368 * sets up the screen.
369 */
370
textforeground(f,n)371 textforeground(f, n)
372 {
373 register int s;
374 char buf[2];
375
376 if (!(f & FFARG)) {
377 if ((s = ereply("Text foreground color (0-7): ",
378 buf, sizeof(buf))) != TRUE)
379 return (s);
380 n = atoi(buf);
381 }
382 if (n < 0 || n > 7)
383 return (FALSE);
384
385 text_fg = n + 30;
386 sgarbf = TRUE;
387 return (TRUE);
388 }
389
390 /*
391 * Set background color for entire window
392 * to a value between 40 and 47 inclusive.
393 */
394
textbackground(f,n)395 textbackground(f, n)
396 {
397 register int s;
398 char buf[2];
399
400 if (!(f & FFARG)) {
401 if ((s = ereply("Text background color (0-7): ",
402 buf, sizeof(buf))) != TRUE)
403 return (s);
404 n = atoi(buf);
405 }
406 if (n < 0 || n > 7)
407 return (FALSE);
408
409 text_bg = n + 40;
410 sgarbf = TRUE;
411 return (TRUE);
412 }
413
414 /*
415 * Set foreground color for entire the mode line
416 */
417
modeforeground(f,n)418 modeforeground(f, n)
419 {
420 register int s;
421 char buf[2];
422
423 if (!(f & FFARG)) {
424 if ((s = ereply("Mode line foreground color (0-7): ",
425 buf, sizeof(buf))) != TRUE)
426 return (s);
427 n = atoi(buf);
428 }
429 if (n < 0 || n > 7)
430 return (FALSE);
431
432 mode_fg = n + 30;
433 sgarbf = TRUE;
434 return (TRUE);
435 }
436
437 /*
438 * Set background color for the mode line
439 */
440
modebackground(f,n)441 modebackground(f, n)
442 {
443 register int s;
444 char buf[2];
445
446 if (!(f & FFARG)) {
447 if ((s = ereply("Mode line background color (0-7): ",
448 buf, sizeof(buf))) != TRUE)
449 return (s);
450 n = atoi(buf);
451 }
452 if (n < 0 || n > 7)
453 return (FALSE);
454
455 mode_bg = n + 40;
456 sgarbf = TRUE;
457 return (TRUE);
458 }
459 #endif
460
461 /*
462 * Set the current writing color to the
463 * specified color. Watch for color changes that are
464 * not going to do anything (the color is already right)
465 * and don't send anything to the display.
466 */
467
468 /* VOID */
ttcolor(color)469 ttcolor(color)
470 register int color;
471 {
472 if (color != tthue) {
473 ttnflush(12); /* Flush if necessary */
474 if (color == CTEXT) { /* Normal video. */
475 ttputc(CSI); /* Reset to 0 */
476 ttputc('m');
477 ttputc(CSI); /* Set text style */
478 asciiparm(text_rendition);
479 ttputc(';');
480 asciiparm(text_fg);
481 ttputc(';');
482 asciiparm(text_bg);
483 ttputc('m');
484 } else if (color == CMODE) { /* Standout mode */
485 ttputc(CSI); /* Reset to 0 */
486 ttputc('m');
487 ttputc(CSI); /* Set standout mode */
488 asciiparm(mode_rendition);
489 ttputc(';');
490 asciiparm(mode_fg); /* Use mode line colors */
491 ttputc(';');
492 asciiparm(mode_bg);
493 ttputc('m');
494 }
495 tthue = color; /* Save the color. */
496 }
497 }
498
499 /*
500 * This routine is called by the "refresh the screen" command to try and resize
501 * the display. The new size, which must be deadstopped to not exceed the NROW
502 * and NCOL limits, is stored back into "nrow" and "ncol". Display can always
503 * deal with a screen NROW by NCOL. Look in "window.c" to see how the caller
504 * deals with a change. On the Amiga, we make the Intuition terminal driver
505 * do all the work.
506 */
507
508 /* VOID */
ttresize()509 ttresize()
510 {
511 setttysize();
512 }
513