xref: /openbsd-src/usr.bin/talk/display.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: display.c,v 1.8 2000/12/31 00:24:51 hugh Exp $	*/
2 /*	$NetBSD: display.c,v 1.3 1994/12/09 02:14:13 jtc Exp $	*/
3 
4 /*
5  * Copyright (c) 1983, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by the University of
19  *	California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36 
37 #ifndef lint
38 #if 0
39 static char sccsid[] = "@(#)display.c	8.1 (Berkeley) 6/6/93";
40 #endif
41 static char rcsid[] = "$OpenBSD: display.c,v 1.8 2000/12/31 00:24:51 hugh Exp $";
42 #endif /* not lint */
43 
44 /*
45  * The window 'manager', initializes curses and handles the actual
46  * displaying of text
47  */
48 #include "talk.h"
49 #include <ctype.h>
50 
51 xwin_t	my_win;
52 xwin_t	his_win;
53 WINDOW	*line_win;
54 
55 int	curses_initialized = 0;
56 int	high_print = 0;
57 
58 /*
59  * max HAS to be a function, it is called with
60  * a argument of the form --foo at least once.
61  */
62 int
63 max(a,b)
64 	int a, b;
65 {
66 
67 	return (a > b ? a : b);
68 }
69 
70 /*
71  * Display some text on somebody's window, processing some control
72  * characters while we are at it.
73  */
74 void
75 display(win, text, size)
76 	register xwin_t *win;
77 	register char *text;
78 	int size;
79 {
80 	register int i;
81 	char cch;
82 
83 	for (i = 0; i < size; i++) {
84 		/*
85 		 * Since we do not use curses's input routines we must
86 		 * convert '\r' -> '\n' ourselves.
87 		 */
88 		if (*text == '\r')
89 			*text = '\n';
90 		if (*text == '\n') {
91 			xscroll(win, 0);
92 			text++;
93 			continue;
94 		}
95 		/* erase character */
96 		if (*text == win->cerase) {
97 			wmove(win->x_win, win->x_line, max(--win->x_col, 0));
98 			getyx(win->x_win, win->x_line, win->x_col);
99 			waddch(win->x_win, ' ');
100 			wmove(win->x_win, win->x_line, win->x_col);
101 			getyx(win->x_win, win->x_line, win->x_col);
102 			text++;
103 			continue;
104 		}
105 		/*
106 		 * On word erase search backwards until we find
107 		 * the beginning of a word or the beginning of
108 		 * the line.
109 		 */
110 		if (*text == win->werase) {
111 			int endcol, xcol, i, c;
112 
113 			endcol = win->x_col;
114 			xcol = endcol - 1;
115 			while (xcol >= 0) {
116 				c = readwin(win->x_win, win->x_line, xcol);
117 				if (c != ' ')
118 					break;
119 				xcol--;
120 			}
121 			while (xcol >= 0) {
122 				c = readwin(win->x_win, win->x_line, xcol);
123 				if (c == ' ')
124 					break;
125 				xcol--;
126 			}
127 			wmove(win->x_win, win->x_line, xcol + 1);
128 			for (i = xcol + 1; i < endcol; i++)
129 				waddch(win->x_win, ' ');
130 			wmove(win->x_win, win->x_line, xcol + 1);
131 			getyx(win->x_win, win->x_line, win->x_col);
132 			text++;
133 			continue;
134 		}
135 		/* line kill */
136 		if (*text == win->kill) {
137 			wmove(win->x_win, win->x_line, 0);
138 			wclrtoeol(win->x_win);
139 			getyx(win->x_win, win->x_line, win->x_col);
140 			text++;
141 			continue;
142 		}
143 		if (*text == '\f') {
144 			if (win == &my_win)
145 				wrefresh(curscr);
146 			text++;
147 			continue;
148 		}
149 		if (win->x_col == COLS-1) {
150 			/* check for wraparound */
151 			xscroll(win, 0);
152 		}
153 		if (*text != '\t' &&
154 		    ((!high_print && !isprint(*text)) || iscntrl(*text))) {
155 			waddch(win->x_win, '^');
156 			getyx(win->x_win, win->x_line, win->x_col);
157 			if (win->x_col == COLS-1) /* check for wraparound */
158 				xscroll(win, 0);
159 			cch = (*text & 63) + 64;
160 			waddch(win->x_win, cch);
161 		} else
162 			waddch(win->x_win, (unsigned char)(*text));
163 		getyx(win->x_win, win->x_line, win->x_col);
164 		text++;
165 	}
166 	wrefresh(win->x_win);
167 }
168 
169 /*
170  * Read the character at the indicated position in win
171  */
172 int
173 readwin(win, line, col)
174 	WINDOW *win;
175 	int line, col;
176 {
177 	int oldline, oldcol;
178 	register int c;
179 
180 	getyx(win, oldline, oldcol);
181 	wmove(win, line, col);
182 	c = winch(win);
183 	wmove(win, oldline, oldcol);
184 	return (c);
185 }
186 
187 /*
188  * Scroll a window, blanking out the line following the current line
189  * so that the current position is obvious
190  */
191 void
192 xscroll(win, flag)
193 	register xwin_t *win;
194 	int flag;
195 {
196 
197 	if (flag == -1) {
198 		wmove(win->x_win, 0, 0);
199 		win->x_line = 0;
200 		win->x_col = 0;
201 		return;
202 	}
203 	win->x_line = (win->x_line + 1) % win->x_nlines;
204 	win->x_col = 0;
205 	wmove(win->x_win, win->x_line, win->x_col);
206 	wclrtoeol(win->x_win);
207 	wmove(win->x_win, (win->x_line + 1) % win->x_nlines, win->x_col);
208 	wclrtoeol(win->x_win);
209 	wmove(win->x_win, win->x_line, win->x_col);
210 }
211