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