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
50static int readwin(WINDOW *, int, int);
51static void xscroll(register xwin_t *, int);
52
53xwin_t my_win;
54xwin_t rem_win;
55WINDOW *line_win;
56
57int 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
64static int
65max(a, b)
66int 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
80int
81display(win, text, size)
82register xwin_t *win;
83register char *text;
84int 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
241static int
242readwin(win, line, col)
243WINDOW *win;
244int line, col;
245{
246int oldline, oldcol;
247register 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
261static void
262xscroll(win, flag)
263register xwin_t *win;
264int 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