1 /* @(#)textio.c	1.2	04/18/83
2  *
3  * Copyright -C- 1982 Barry S. Roitblat
4  *
5  *
6  * This file contains functions that manipulate the text interface
7  *
8  * (Modified from software written by John Ousterhout for the caesar
9  *  program)
10  */
11 
12 #include "gremlin.h"
13 #include <sgtty.h>
14 
15 /* Library routines: */
16 
17 char *tgetstr(), *sprintf(), *tgoto(), *strcpy(), *strcat();
18 
19 /* The following definitions are used by the termlib routines
20  */
21 
22 char PC;
23 char *BC, *UP, *cm, *ce, *vs, *cl;
24 short ospeed, lastline=23,msgline=23,inline=22;
25 
26 static char bp[1024];		/* Holds the termcap entry for the tty */
27 static char buf[256];		/* Holds selected strings from bp */
28 static struct sgttyb sttybuf;	/* Holds stty information for resetting tty */
29 static int sttyflags;		/* Flag word from sttybuf */
30 static struct tchars tchars;	/* Holds tchars information for resetting */
31 static char brkc, eofc;		/* Fields from tchars, saved for resetting */
32 static int c100;		/* TRUE means text display is c100 */
33 static putmsg;			/* TRUE means TxPutMsg has been called
34 				 * since last character input.
35 				 */
36 
37 
38 /* The following structures define the various fields that are available
39  * on the terminal screen.
40  */
41 
42 TXFIELD
43     TAlign = {56, 1, 3},
44     TAdjust = {63, 1, 13},
45     TBrush = {30, 1, 1},
46     TEdit = {10, 2, 32},
47     TJustmode = {76, 2, 2},
48     TFont = {10, 1, 1},
49     TGravity = {43, 1, 4},
50     TCSize = {19, 1, 1};
51 
52 
53 OutChar(val)
54 char val;			/* The character to be output */
55 
56 /*-----------------------------------------------------------------------------
57  *	OutChar merely outputs a character on the file being used for
58  *	text I/O.  This routine is passed as a parameter to the tputs
59  *	pad-generating routine.
60  *
61  *	Results:	None.
62  *	Side Effects:	The character is output.
63  *	Errors:		None.
64  *-----------------------------------------------------------------------------
65  */
66 
67 {
68     putc(val, stdout);
69 }
70 
71 
72 TxInit(ttytype)
73 char *ttytype;			/* The name of the terminal type, as returned
74 				 * by getenv("TERM") */
75 
76 /*-----------------------------------------------------------------------------
77  *	TxInit initializes the text terminal and saves state information
78  *	so that we can restore its characteristics later.
79  *
80  *	Results:	None.
81  *	Side Effects:	Terminal characteristics are saved.
82  *-----------------------------------------------------------------------------
83  */
84 
85 {
86     char *p1, *p2, *pcap;
87     int i;
88 
89     /* Turn off buffering.  This is necessary to avoid mess-ups during
90      * the constant mode changes.
91      */
92 
93     setbuf(stdin, NULL);
94 
95     /* Find the termcap entry, and set up the strings and constants
96      * required by the termlib routines.
97      */
98 
99     if (tgetent(bp, ttytype) != 1)
100 	error("Cannot find terminal characteristics");
101     (void) gtty(fileno(stdout), &sttybuf);
102     ospeed = sttybuf.sg_ospeed;
103     pcap = buf;
104     p1 = tgetstr("pc", &pcap);  if (p1 == NULL) PC = 0; else PC = *p1;
105     pcap = buf;
106     BC = tgetstr("bc", &pcap);
107     UP = tgetstr("up", &pcap);
108     cm = tgetstr("cm", &pcap);
109     ce = tgetstr("ce", &pcap);
110     vs = tgetstr("vs", &pcap);
111     cl = tgetstr("cl", &pcap);
112     (void) gtty(fileno(stdin), &sttybuf);
113     sttyflags = sttybuf.sg_flags;
114     (void) ioctl(fileno(stdin), TIOCGETC, (char *) &tchars);
115     eofc = tchars.t_eofc;
116     brkc = tchars.t_brkc;
117     p1 = "c100";
118     p2 = ttytype;
119     c100 = FALSE;
120     putmsg = FALSE;
121     for (i = 4; i; i = i-1)
122     {
123 	if (*p1 != *p2) break;
124 	if (i=1) c100 = TRUE;
125     }
126 }
127 
128 
129 TxRedisplay()
130 
131 /*-----------------------------------------------------------------------------
132  *	This routine merely redisplays the command menu on the text screen,
133  *	and modifies text display parameters for menu processing.
134  *
135  *	Results:	None.
136  *
137  *	Side Effects:
138  *	The text display is cleared, menu information is reprinted, and
139  *	terminal characteristics are set for menu processing.
140  *-----------------------------------------------------------------------------
141  */
142 
143 {
144     static char initstring1[] = "\n\
145      font 1   size 1    brush 6    gravi\
146 ty OFF    align   4    NO ADJUSTMENT \n\
147 Editing:                                \
148                      Justification: BL \n\
149 ----------------------------------------\
150 ---------------------------------------\n\
151     Long Commands:          |\
152          Short Commands:\n\
153                             |\n\
154    Align          MSize     |\
155    a - draw arc         ! - shell escape\n\
156    BRush          MText     |\
157    b - draw curve       . - repeat last command\n\
158    BUffer         Orient    |\
159    c - copy set        ^L - redraw picture\n\
160    Clearpoints    PAth      |\
161    d - define set       l - redisplay text screen\n\
162 ";
163     static char initstring2[] = "\
164    Deletepoint    POint     |\
165    e - erase      1,2,3,4 - store set buffer\n\
166    Edit<!>        Quit<!>   |\
167    f - define area \n\
168    Font           Read      |\
169    g - gravity\n\
170    Gripe          SAveset<!>|\
171    q - grid\n\
172    Hadjust        SHowpoints|\
173    r - rotate set\n\
174    Includeset     SIze      |\
175    s - scale set\n\
176    Justify        Text      |\
177    t - translate set\n\
178    Littlepoint    Undo      |\
179    v - draw vectors\n\
180    MBrush         Vadjust   |\
181    w - draw arrow \n\
182    MFont          Write<!>  |\
183    x - draw box\n\
184    MIrror                   |\
185    z - manhattan adjust\n\
186    MPoint                   |\
187    \n\
188 ";
189 
190     /* Clear the terminal screen and output the gremlin menu.  The
191      * TxClose call is necessary to put the terminal back into its standard
192      * operating mode;  otherwise this stuff will appear as garbage!
193      * However, turn off echoing to keep type-ahead from appearing
194      * in the middle of the screen.
195      */
196 
197     TxClose();
198     sttybuf.sg_flags &= ~ECHO;
199     (void) ioctl(fileno(stdin), TIOCSETN, (char *) &sttybuf);
200     fputs(vs, stdout);
201     tputs(cl, tgetnum("li"), OutChar);
202     fputs(tgoto(cm, 0, 0), stdout);
203     fputs(initstring1, stdout);
204     fputs(initstring2, stdout);
205 
206     /* If the terminal is a Concept 100, then output special characters
207      * for the border lines between the three screen areas.
208      */
209 
210     if (c100)
211     {
212 	fputs(tgoto(cm, 0, 3), stdout);
213 	fputs("\33U\33r\1p", stdout);
214 	putchar(0);
215 	putchar(0);
216 	putchar(0);
217 	putchar(0);
218 	fputs(tgoto(cm, 28, 4), stdout);
219 	putchar('\0');
220 	putchar('\0');
221 	fputs("\33R", stdout);
222 	putchar('\0');
223 	putchar('2');
224     }
225 
226     /* Place the cursor in the lower-left corner, save terminal
227      * characteristics so we can restore them later, then make ^M
228      * into a break character, put the terminal into CBREAK mode,
229      * and turn off echoing.
230      */
231 
232     fputs(tgoto(cm, 0, lastline), stdout);
233     sttybuf.sg_flags |= CBREAK;
234     sttybuf.sg_flags &= ~(ECHO|CRMOD);
235     (void) ioctl(fileno(stdin), TIOCSETN, (char *) &sttybuf);
236     tchars.t_eofc = -1;
237     tchars.t_brkc = '\r';
238     (void) ioctl(fileno(stdin), TIOCSETC, (char *) &tchars);
239     (void) fflush(stdout);
240     putmsg = FALSE;
241 }
242 
243 
244 TxClose()
245 
246 /*-----------------------------------------------------------------------------
247  *	TxClose resets the terminal to the way we found it.
248  *
249  *	Results:	None.
250  *	Side Effects:	None.
251  *	Errors:		None.
252  *-----------------------------------------------------------------------------
253  */
254 
255 {
256     char *dummy, buf [100];
257     sttybuf.sg_flags = sttyflags;
258     (void) ioctl(fileno(stdin), TIOCSETN, (char *) &sttybuf);
259     tchars.t_eofc = eofc;
260     tchars.t_brkc = brkc;
261     (void) ioctl(fileno(stdin), TIOCSETC, (char *) &tchars);
262     fputs(tgoto(cm, 0, tgetnum("li")-1), stdout);
263     dummy = buf;
264     fputs(tgetstr("ve", &dummy), stdout);
265     fputs("\n", stdout);
266     (void) fflush(stdout);
267 }
268 
269 
270 TxPutString(field, string)
271 TXFIELD *field;			/* The screen field to be overwritten */
272 char *string;			/* The character string to be written */
273 
274 /*-----------------------------------------------------------------------------
275  *	TxPutString displays a string in a given field of the text display.
276  *
277  *	Results:	None.
278  *
279  *	Side Effects:
280  *	The given text screen field is overwritten with the given text
281  *	string, blank filled and left justified.
282  *
283  *	Errors:		None.
284  *-----------------------------------------------------------------------------
285  */
286 
287 {
288     char format[20];
289     (void) sprintf(format, "%%s%%-%d.%ds", field->tx_size, field->tx_size);
290     (void) printf(format, tgoto(cm, field->tx_x, field->tx_y), string);
291     (void) fflush(stdout);
292 }
293 
294 
295 char
296 TxGetChar()
297 
298 /*-----------------------------------------------------------------------------
299  *	TxGetChar gets the next character from the text keyboard.
300  *
301  *	Results:	The next character.
302  *	Side Effects:	None.
303  *-----------------------------------------------------------------------------
304  */
305 
306 {
307     putmsg = FALSE;
308     return getchar();
309 }
310 
311 
312 TxMsgOK()
313 
314 /*-----------------------------------------------------------------------------
315  *	This routine marks it OK to output messages again, just as if text
316  *	had been input.
317  *
318  *	Results:	None.
319  *	Side Effects:	As above.
320  *-----------------------------------------------------------------------------
321  */
322 
323 {
324 	if (putmsg)          /* message on the screen to be blanked */
325 	{
326 		TxLine(msgline);
327 		printf("                                                                            ");
328 		TxLine(msgline);
329 	}
330 	putmsg = FALSE;
331 }
332 
333 
334 TxGetLine(prompt, ptr, maxsize)
335 char *prompt;			/* Prompt to be output at beginning of line */
336 char *ptr;			/* Place to store the input line */
337 int maxsize;			/* Maximum number of characters to be read */
338 
339 /*-----------------------------------------------------------------------------
340  *	TxGetLine reads a line of text from the terminal.  It does so
341  *	by positioning the cursor at the bottom of the screen and enabling
342  *	echoes again.  When the line has been read, echoes etc. are turned
343  *	off once more.
344  *
345  *	Results:	None.
346  *	Side Effects:	The last line of the text screen is destroyed.
347  *	Errors:		None.
348  *-----------------------------------------------------------------------------
349  */
350 
351 {
352     int i, j;
353 
354     putmsg = FALSE;
355     fputs(tgoto(cm, 0, inline), stdout);
356     tputs(ce, 1, OutChar);
357     fputs(prompt, stdout);
358     sttybuf.sg_flags |= ECHO;
359     sttybuf.sg_flags &= ~CBREAK;
360     (void) ioctl(fileno(stdin), TIOCSETN, (char *) &sttybuf);
361 
362     /* Input characters until a carriage return is found.  Then
363      * erase the control character from the screen.
364      */
365 
366     for (i=0; i<maxsize; i++)
367     {
368 	ptr[i] = getchar();
369 	if (ptr[i] == '\r') break;
370     }
371     for (j=i; j<maxsize; j++)
372         ptr[j] = '\0';
373     fputs("\b\b  \b\b", stdout);
374     (void) fflush(stdout);
375 
376     /* Reset the terminal into no-echo mode */
377 
378     sttybuf.sg_flags |= CBREAK;
379     sttybuf.sg_flags &= ~ECHO;
380     (void) ioctl(fileno(stdin), TIOCSETN, (char *) &sttybuf);
381 }
382 
383 
384 TxPutMsg(msg)
385 char *msg;			/* A message (not containing \r or \n) to
386 				 * be output on the text screen.  It must
387 				 * fit on a single line.  /*
388 
389 /*-----------------------------------------------------------------------------
390  *	TPutMsg outputs a one-line message onto the text screen.
391  *
392  *	Results:	None.
393  *
394  *	Side Effects:
395  *	The string in msg is output on the last line of the text display.
396  *	If TxPutMsg is called twice between calls to TxGetLine or TxGetChar
397  *	then we output the message "More" at the end of the line and
398  *	wait for a space to be typed.  This is to protect against
399  *	multiple error messages overwriting each other.
400  *
401  *	Errors:		None.
402  *-----------------------------------------------------------------------------
403  */
404 
405 {
406     if (putmsg)
407     {
408 	fputs(tgoto(cm, 50, msgline), stdout);
409 	if (msg[0] == '\7')
410 	{
411 	    putchar ('\7');
412 	    msg++;
413 	}
414 	fputs("--More--", stdout);
415 	(void) fflush(stdout);
416 	while (getchar() != ' ');
417     }
418     putmsg = TRUE;
419     fputs(tgoto(cm, 0, msgline), stdout);
420     tputs(ce, 1, OutChar);
421     fputs(msg, stdout);
422     (void) fflush(stdout);
423 }
424 
425 TxLine(line)
426 short line;
427 
428 /*-----------------------------------------------------------------------------
429  *	TxLastLine moves the cursor to the first character of the specified
430  *	line of the text display.
431  *
432  *	Results:	None.
433  *	Side Effects:	None.
434  *-----------------------------------------------------------------------------
435  */
436 
437 {
438     fputs(tgoto(cm, 0, line), stdout);
439     (void) fflush(stdout);
440 }
441