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 /*
41  * The window 'manager', initializes curses and handles the actual
42  * displaying of text
43  */
44 
45 #include "talk.h"
46 #include <ctype.h>
47 
48 static int readwin(WINDOW *, int, int);
49 static void xscroll(register xwin_t *, int);
50 
51 xwin_t my_win;
52 xwin_t rem_win;
53 WINDOW *line_win;
54 
55 int curses_initialized = 0;
56 
57 /*
58  * max HAS to be a function, it is called with
59  * a argument of the form --foo at least once.
60  */
61 
62 static int
max(a,b)63 max(a, b)
64 int a, b;
65 {
66 	if (a > b) {
67 	return (a);
68 	} else {
69 	return (b);
70 	}
71 }
72 
73 /*
74  * Display some text on somebody's window, processing some control
75  * characters while we are at it.
76  */
77 
78 int
display(win,text,size)79 display(win, text, size)
80 register xwin_t *win;
81 register char *text;
82 int size;
83 {
84 	register int i;
85 	int mb_cur_max = MB_CUR_MAX;
86 
87 	for (i = 0; i < size; i++) {
88 	int itext;
89 
90 	if (*text == '\n'|| *text == '\r') {
91 		xscroll(win, 0);
92 		text++;
93 		continue;
94 	}
95 
96 		/* erase character */
97 
98 	if (*text == win->cerase) {
99 		wmove(win->x_win, win->x_line, max(--win->x_col, 0));
100 		getyx(win->x_win, win->x_line, win->x_col);
101 		waddch(win->x_win, ' ');
102 		wmove(win->x_win, win->x_line, win->x_col);
103 		getyx(win->x_win, win->x_line, win->x_col);
104 		text++;
105 		continue;
106 	}
107 	/*
108 	 * On word erase search backwards until we find
109 	 * the beginning of a word or the beginning of
110 	 * the line.
111 	 */
112 	if (*text == win->werase) {
113 		int endcol, xcol, i, c;
114 
115 		endcol = win->x_col;
116 		xcol = endcol - 1;
117 		while (xcol >= 0) {
118 		c = readwin(win->x_win, win->x_line, xcol);
119 		if (c != ' ')
120 			break;
121 		xcol--;
122 		}
123 		while (xcol >= 0) {
124 		c = readwin(win->x_win, win->x_line, xcol);
125 		if (c == ' ')
126 			break;
127 		xcol--;
128 		}
129 		wmove(win->x_win, win->x_line, xcol + 1);
130 		for (i = xcol + 1; i < endcol; i++)
131 		waddch(win->x_win, ' ');
132 		wmove(win->x_win, win->x_line, xcol + 1);
133 		getyx(win->x_win, win->x_line, win->x_col);
134 		continue;
135 	}
136 		/* line kill */
137 	if (*text == win->kill) {
138 		wmove(win->x_win, win->x_line, 0);
139 		wclrtoeol(win->x_win);
140 		getyx(win->x_win, win->x_line, win->x_col);
141 		text++;
142 		continue;
143 	}
144 	if (*text == '\f') {
145 		if (win == &my_win)
146 		wrefresh(curscr);
147 		text++;
148 		continue;
149 	}
150 	/* EOF character */
151 	if (*text == '\004') {
152 		quit();
153 	}
154 
155 	/* typing alert character will alert recipient's terminal */
156 
157 	if (*text == '\007') {
158 		beep();
159 		continue;
160 	}
161 
162 	/* check for wrap around */
163 	if (win->x_col == COLS-1) {
164 		xscroll(win, 0);
165 	}
166 
167 	/*
168 	 * Handle the multibyte case
169 	 * We print '?' for nonprintable widechars.
170 	 */
171 
172 	if (mb_cur_max > 1 && mblen(text, mb_cur_max) > 1) {
173 		wchar_t wc;
174 		int len;
175 
176 		len = mbtowc(&wc, text, mb_cur_max);
177 
178 		if (iswprint(wc) || iswspace(wc)) {
179 		/* its printable, put out the bytes */
180 			do {
181 				if (win->x_col == COLS-1) /* wraparound */
182 					xscroll(win, 0);
183 				waddch(win->x_win, *text++);
184 				getyx(win->x_win, win->x_line, win->x_col);
185 			} while (--len > 0);
186 			continue;
187 		}
188 		/*
189 		 * otherwise, punt and print a question mark.
190 		 */
191 		text += len;
192 		waddch(win->x_win, '?');
193 		getyx(win->x_win, win->x_line, win->x_col);
194 		continue;
195 	}
196 
197 	itext = (unsigned int) *text;
198 	if (isprint(itext) || *text == ' ' || *text == '\t' ||
199 		*text == '\013' || *text == '\007' /* bell */) {
200 		waddch(win->x_win, *text);
201 	} else {
202 
203 		if (!isascii(*text)) {
204 			/* check for wrap around */
205 			if (win->x_col == COLS-3) {
206 				xscroll(win, 0);
207 			}
208 			waddch(win->x_win, 'M');
209 			waddch(win->x_win, '-');
210 			*text = toascii(*text);
211 		}
212 		if (iscntrl(*text)) {
213 
214 			/* check for wrap around */
215 			getyx(win->x_win, win->x_line, win->x_col);
216 			if (win->x_col == COLS-2) {
217 				xscroll(win, 0);
218 			}
219 
220 			waddch(win->x_win, '^');
221 			waddch(win->x_win, *text + 0100);
222 		}
223 		else
224 			waddch(win->x_win, *text);
225 	}
226 
227 	getyx(win->x_win, win->x_line, win->x_col);
228 	text++;
229 
230 	}  /* for loop */
231 	wrefresh(win->x_win);
232 	return (0);
233 }
234 
235 /*
236  * Read the character at the indicated position in win
237  */
238 
239 static int
readwin(win,line,col)240 readwin(win, line, col)
241 WINDOW *win;
242 int line, col;
243 {
244 int oldline, oldcol;
245 register int c;
246 
247 	getyx(win, oldline, oldcol);
248 	wmove(win, line, col);
249 	c = winch(win);
250 	wmove(win, oldline, oldcol);
251 	return (c);
252 }
253 
254 /*
255  * Scroll a window, blanking out the line following the current line
256  * so that the current position is obvious
257  */
258 
259 static void
xscroll(win,flag)260 xscroll(win, flag)
261 register xwin_t *win;
262 int flag;
263 {
264 	if (flag == -1) {
265 		wmove(win->x_win, 0, 0);
266 		win->x_line = 0;
267 		win->x_col = 0;
268 		return;
269 	}
270 	win->x_line = (win->x_line + 1) % win->x_nlines;
271 	win->x_col = 0;
272 	wmove(win->x_win, win->x_line, win->x_col);
273 	wclrtoeol(win->x_win);
274 	wmove(win->x_win, (win->x_line + 1) % win->x_nlines, win->x_col);
275 	wclrtoeol(win->x_win);
276 	wmove(win->x_win, win->x_line, win->x_col);
277 }
278