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