1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 1994 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 /*
31  * University Copyright- Copyright (c) 1982, 1986, 1988
32  * The Regents of the University of California
33  * All Rights Reserved
34  *
35  * University Acknowledgment- Portions of this document are derived from
36  * software developed by the University of California, Berkeley, and its
37  * contributors.
38  */
39 
40 #pragma ident	"%Z%%M%	%I%	%E% SMI"
41 
42 /*
43  * The window 'manager', initializes curses and handles the actual
44  * displaying of text
45  */
46 
47 #include "talk.h"
48 #include <ctype.h>
49 
50 static int readwin(WINDOW *, int, int);
51 static void xscroll(register xwin_t *, int);
52 
53 xwin_t my_win;
54 xwin_t rem_win;
55 WINDOW *line_win;
56 
57 int curses_initialized = 0;
58 
59 /*
60  * max HAS to be a function, it is called with
61  * a argument of the form --foo at least once.
62  */
63 
64 static int
65 max(a, b)
66 int a, b;
67 {
68 	if (a > b) {
69 	return (a);
70 	} else {
71 	return (b);
72 	}
73 }
74 
75 /*
76  * Display some text on somebody's window, processing some control
77  * characters while we are at it.
78  */
79 
80 int
81 display(win, text, size)
82 register xwin_t *win;
83 register char *text;
84 int size;
85 {
86 	register int i;
87 	int mb_cur_max = MB_CUR_MAX;
88 
89 	for (i = 0; i < size; i++) {
90 	int itext;
91 
92 	if (*text == '\n'|| *text == '\r') {
93 		xscroll(win, 0);
94 		text++;
95 		continue;
96 	}
97 
98 		/* erase character */
99 
100 	if (*text == win->cerase) {
101 		wmove(win->x_win, win->x_line, max(--win->x_col, 0));
102 		getyx(win->x_win, win->x_line, win->x_col);
103 		waddch(win->x_win, ' ');
104 		wmove(win->x_win, win->x_line, win->x_col);
105 		getyx(win->x_win, win->x_line, win->x_col);
106 		text++;
107 		continue;
108 	}
109 	/*
110 	 * On word erase search backwards until we find
111 	 * the beginning of a word or the beginning of
112 	 * the line.
113 	 */
114 	if (*text == win->werase) {
115 		int endcol, xcol, i, c;
116 
117 		endcol = win->x_col;
118 		xcol = endcol - 1;
119 		while (xcol >= 0) {
120 		c = readwin(win->x_win, win->x_line, xcol);
121 		if (c != ' ')
122 			break;
123 		xcol--;
124 		}
125 		while (xcol >= 0) {
126 		c = readwin(win->x_win, win->x_line, xcol);
127 		if (c == ' ')
128 			break;
129 		xcol--;
130 		}
131 		wmove(win->x_win, win->x_line, xcol + 1);
132 		for (i = xcol + 1; i < endcol; i++)
133 		waddch(win->x_win, ' ');
134 		wmove(win->x_win, win->x_line, xcol + 1);
135 		getyx(win->x_win, win->x_line, win->x_col);
136 		continue;
137 	}
138 		/* line kill */
139 	if (*text == win->kill) {
140 		wmove(win->x_win, win->x_line, 0);
141 		wclrtoeol(win->x_win);
142 		getyx(win->x_win, win->x_line, win->x_col);
143 		text++;
144 		continue;
145 	}
146 	if (*text == '\f') {
147 		if (win == &my_win)
148 		wrefresh(curscr);
149 		text++;
150 		continue;
151 	}
152 	/* EOF character */
153 	if (*text == '\004') {
154 		quit();
155 	}
156 
157 	/* typing alert character will alert recipient's terminal */
158 
159 	if (*text == '\007') {
160 		beep();
161 		continue;
162 	}
163 
164 	/* check for wrap around */
165 	if (win->x_col == COLS-1) {
166 		xscroll(win, 0);
167 	}
168 
169 	/*
170 	 * Handle the multibyte case
171 	 * We print '?' for nonprintable widechars.
172 	 */
173 
174 	if (mb_cur_max > 1 && mblen(text, mb_cur_max) > 1) {
175 		wchar_t wc;
176 		int len;
177 
178 		len = mbtowc(&wc, text, mb_cur_max);
179 
180 		if (iswprint(wc) || iswspace(wc)) {
181 		/* its printable, put out the bytes */
182 			do {
183 				if (win->x_col == COLS-1) /* wraparound */
184 					xscroll(win, 0);
185 				waddch(win->x_win, *text++);
186 				getyx(win->x_win, win->x_line, win->x_col);
187 			} while (--len > 0);
188 			continue;
189 		}
190 		/*
191 		 * otherwise, punt and print a question mark.
192 		 */
193 		text += len;
194 		waddch(win->x_win, '?');
195 		getyx(win->x_win, win->x_line, win->x_col);
196 		continue;
197 	}
198 
199 	itext = (unsigned int) *text;
200 	if (isprint(itext) || *text == ' ' || *text == '\t' ||
201 		*text == '\013' || *text == '\007' /* bell */) {
202 		waddch(win->x_win, *text);
203 	} else {
204 
205 		if (!isascii(*text)) {
206 			/* check for wrap around */
207 			if (win->x_col == COLS-3) {
208 				xscroll(win, 0);
209 			}
210 			waddch(win->x_win, 'M');
211 			waddch(win->x_win, '-');
212 			*text = toascii(*text);
213 		}
214 		if (iscntrl(*text)) {
215 
216 			/* check for wrap around */
217 			getyx(win->x_win, win->x_line, win->x_col);
218 			if (win->x_col == COLS-2) {
219 				xscroll(win, 0);
220 			}
221 
222 			waddch(win->x_win, '^');
223 			waddch(win->x_win, *text + 0100);
224 		}
225 		else
226 			waddch(win->x_win, *text);
227 	}
228 
229 	getyx(win->x_win, win->x_line, win->x_col);
230 	text++;
231 
232 	}  /* for loop */
233 	wrefresh(win->x_win);
234 	return (0);
235 }
236 
237 /*
238  * Read the character at the indicated position in win
239  */
240 
241 static int
242 readwin(win, line, col)
243 WINDOW *win;
244 int line, col;
245 {
246 int oldline, oldcol;
247 register int c;
248 
249 	getyx(win, oldline, oldcol);
250 	wmove(win, line, col);
251 	c = winch(win);
252 	wmove(win, oldline, oldcol);
253 	return (c);
254 }
255 
256 /*
257  * Scroll a window, blanking out the line following the current line
258  * so that the current position is obvious
259  */
260 
261 static void
262 xscroll(win, flag)
263 register xwin_t *win;
264 int flag;
265 {
266 	if (flag == -1) {
267 		wmove(win->x_win, 0, 0);
268 		win->x_line = 0;
269 		win->x_col = 0;
270 		return;
271 	}
272 	win->x_line = (win->x_line + 1) % win->x_nlines;
273 	win->x_col = 0;
274 	wmove(win->x_win, win->x_line, win->x_col);
275 	wclrtoeol(win->x_win);
276 	wmove(win->x_win, (win->x_line + 1) % win->x_nlines, win->x_col);
277 	wclrtoeol(win->x_win);
278 	wmove(win->x_win, win->x_line, win->x_col);
279 }
280