xref: /freebsd/usr.bin/talk/display.c (revision fbbd9655e5107c68e4e0146ff22b73d7350475bc)
19b50d902SRodney W. Grimes /*
29b50d902SRodney W. Grimes  * Copyright (c) 1983, 1993
39b50d902SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
49b50d902SRodney W. Grimes  *
59b50d902SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
69b50d902SRodney W. Grimes  * modification, are permitted provided that the following conditions
79b50d902SRodney W. Grimes  * are met:
89b50d902SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
99b50d902SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
109b50d902SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
119b50d902SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
129b50d902SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
13*fbbd9655SWarner Losh  * 3. Neither the name of the University nor the names of its contributors
149b50d902SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
159b50d902SRodney W. Grimes  *    without specific prior written permission.
169b50d902SRodney W. Grimes  *
179b50d902SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
189b50d902SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
199b50d902SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
209b50d902SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
219b50d902SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
229b50d902SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
239b50d902SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
249b50d902SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
259b50d902SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
269b50d902SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
279b50d902SRodney W. Grimes  * SUCH DAMAGE.
289b50d902SRodney W. Grimes  */
299b50d902SRodney W. Grimes 
30caa64801SMark Murray #include <sys/cdefs.h>
31caa64801SMark Murray 
32caa64801SMark Murray __FBSDID("$FreeBSD$");
33caa64801SMark Murray 
349b50d902SRodney W. Grimes #ifndef lint
35caa64801SMark Murray static const char sccsid[] = "@(#)display.c	8.1 (Berkeley) 6/6/93";
3620868061SPhilippe Charnier #endif
379b50d902SRodney W. Grimes 
389b50d902SRodney W. Grimes /*
399b50d902SRodney W. Grimes  * The window 'manager', initializes curses and handles the actual
409b50d902SRodney W. Grimes  * displaying of text
419b50d902SRodney W. Grimes  */
42edee6d38SAndrey A. Chernov #include <ctype.h>
433daadfc8SXin LI #include <unistd.h>
4405b0160eSGleb Smirnoff #include <wctype.h>
4505b0160eSGleb Smirnoff #define _XOPEN_SOURCE_EXTENDED
4605b0160eSGleb Smirnoff #include <curses.h>
479b50d902SRodney W. Grimes 
48caa64801SMark Murray #include "talk.h"
49caa64801SMark Murray 
5005b0160eSGleb Smirnoff void	display(xwin_t *, wchar_t *);
5105b0160eSGleb Smirnoff 
529b50d902SRodney W. Grimes xwin_t	my_win;
539b50d902SRodney W. Grimes xwin_t	his_win;
549b50d902SRodney W. Grimes WINDOW	*line_win;
559b50d902SRodney W. Grimes 
569b50d902SRodney W. Grimes int	curses_initialized = 0;
579b50d902SRodney W. Grimes 
589b50d902SRodney W. Grimes /*
599b50d902SRodney W. Grimes  * max HAS to be a function, it is called with
609d5abbddSJens Schweikhardt  * an argument of the form --foo at least once.
619b50d902SRodney W. Grimes  */
6228592604SJoerg Wunsch int
63b6d9e1f3SXin LI max(int a, int b)
649b50d902SRodney W. Grimes {
659b50d902SRodney W. Grimes 
669b50d902SRodney W. Grimes 	return (a > b ? a : b);
679b50d902SRodney W. Grimes }
689b50d902SRodney W. Grimes 
6905b0160eSGleb Smirnoff static cchar_t *
7005b0160eSGleb Smirnoff makecchar(wchar_t in)
7105b0160eSGleb Smirnoff {
7205b0160eSGleb Smirnoff 	static cchar_t cc;
7305b0160eSGleb Smirnoff 	wchar_t wc[2];
7405b0160eSGleb Smirnoff 
7505b0160eSGleb Smirnoff 	wc[0] = in;
7605b0160eSGleb Smirnoff 	wc[1] = L'\0';
7705b0160eSGleb Smirnoff 
7805b0160eSGleb Smirnoff 	if (setcchar(&cc, wc, A_NORMAL, 0, NULL) != OK)
7905b0160eSGleb Smirnoff 		p_error("settchar(3) failure");
8005b0160eSGleb Smirnoff 
8105b0160eSGleb Smirnoff 	return (&cc);
8205b0160eSGleb Smirnoff }
8305b0160eSGleb Smirnoff 
849b50d902SRodney W. Grimes /*
8505b0160eSGleb Smirnoff  * Display a symbol on somebody's window, processing some control
869b50d902SRodney W. Grimes  * characters while we are at it.
879b50d902SRodney W. Grimes  */
8828592604SJoerg Wunsch void
8905b0160eSGleb Smirnoff display(xwin_t *win, wchar_t *wc)
909b50d902SRodney W. Grimes {
919b50d902SRodney W. Grimes 
9205b0160eSGleb Smirnoff 	/*
9305b0160eSGleb Smirnoff 	 * Alas, can't use variables in C switch statement.
9405b0160eSGleb Smirnoff 	 * Workaround these 3 cases with goto.
9505b0160eSGleb Smirnoff 	 */
9605b0160eSGleb Smirnoff 	if (*wc == win->kill)
9705b0160eSGleb Smirnoff 		goto kill;
9805b0160eSGleb Smirnoff 	else if (*wc == win->cerase)
9905b0160eSGleb Smirnoff 		goto cerase;
10005b0160eSGleb Smirnoff 	else if (*wc == win->werase)
10105b0160eSGleb Smirnoff 		goto werase;
10205b0160eSGleb Smirnoff 
10305b0160eSGleb Smirnoff 	switch (*wc) {
10405b0160eSGleb Smirnoff 	case L'\n':
10505b0160eSGleb Smirnoff 	case L'\r':
10605b0160eSGleb Smirnoff 		wadd_wch(win->x_win, makecchar(L'\n'));
107edee6d38SAndrey A. Chernov 		getyx(win->x_win, win->x_line, win->x_col);
10805b0160eSGleb Smirnoff 		wrefresh(win->x_win);
10905b0160eSGleb Smirnoff 		return;
11005b0160eSGleb Smirnoff 
11105b0160eSGleb Smirnoff 	case 004:
11205b0160eSGleb Smirnoff 		if (win == &my_win) {
11305b0160eSGleb Smirnoff 			/* Ctrl-D clears the screen. */
1148aed91caSLuigi Rizzo 			werase(my_win.x_win);
1158aed91caSLuigi Rizzo 			getyx(my_win.x_win, my_win.x_line, my_win.x_col);
1168aed91caSLuigi Rizzo 			wrefresh(my_win.x_win);
1178aed91caSLuigi Rizzo 			werase(his_win.x_win);
1188aed91caSLuigi Rizzo 			getyx(his_win.x_win, his_win.x_line, his_win.x_col);
1198aed91caSLuigi Rizzo 			wrefresh(his_win.x_win);
1208aed91caSLuigi Rizzo 		}
12105b0160eSGleb Smirnoff 		return;
1228aed91caSLuigi Rizzo 
12305b0160eSGleb Smirnoff 	/* Erase character. */
12405b0160eSGleb Smirnoff 	case 010:	/* BS */
12505b0160eSGleb Smirnoff 	case 0177:	/* DEL */
12605b0160eSGleb Smirnoff cerase:
1279b50d902SRodney W. Grimes 		wmove(win->x_win, win->x_line, max(--win->x_col, 0));
1289b50d902SRodney W. Grimes 		getyx(win->x_win, win->x_line, win->x_col);
1299b50d902SRodney W. Grimes 		waddch(win->x_win, ' ');
1309b50d902SRodney W. Grimes 		wmove(win->x_win, win->x_line, win->x_col);
1319b50d902SRodney W. Grimes 		getyx(win->x_win, win->x_line, win->x_col);
13205b0160eSGleb Smirnoff 		wrefresh(win->x_win);
13305b0160eSGleb Smirnoff 		return;
13405b0160eSGleb Smirnoff 
13505b0160eSGleb Smirnoff 	case 027:	/* ^W */
13605b0160eSGleb Smirnoff werase:
13705b0160eSGleb Smirnoff 	    {
1389b50d902SRodney W. Grimes 		/*
1399b50d902SRodney W. Grimes 		 * On word erase search backwards until we find
1409b50d902SRodney W. Grimes 		 * the beginning of a word or the beginning of
1419b50d902SRodney W. Grimes 		 * the line.
1429b50d902SRodney W. Grimes 		 */
14305b0160eSGleb Smirnoff 		int endcol, xcol, c;
1449b50d902SRodney W. Grimes 
1459b50d902SRodney W. Grimes 		endcol = win->x_col;
1469b50d902SRodney W. Grimes 		xcol = endcol - 1;
1479b50d902SRodney W. Grimes 		while (xcol >= 0) {
1489b50d902SRodney W. Grimes 			c = readwin(win->x_win, win->x_line, xcol);
1499b50d902SRodney W. Grimes 			if (c != ' ')
1509b50d902SRodney W. Grimes 				break;
1519b50d902SRodney W. Grimes 			xcol--;
1529b50d902SRodney W. Grimes 		}
1539b50d902SRodney W. Grimes 		while (xcol >= 0) {
1549b50d902SRodney W. Grimes 			c = readwin(win->x_win, win->x_line, xcol);
1559b50d902SRodney W. Grimes 			if (c == ' ')
1569b50d902SRodney W. Grimes 				break;
1579b50d902SRodney W. Grimes 			xcol--;
1589b50d902SRodney W. Grimes 		}
1599b50d902SRodney W. Grimes 		wmove(win->x_win, win->x_line, xcol + 1);
16005b0160eSGleb Smirnoff 		for (int i = xcol + 1; i < endcol; i++)
1619b50d902SRodney W. Grimes 			waddch(win->x_win, ' ');
1629b50d902SRodney W. Grimes 		wmove(win->x_win, win->x_line, xcol + 1);
1639b50d902SRodney W. Grimes 		getyx(win->x_win, win->x_line, win->x_col);
16405b0160eSGleb Smirnoff 		wrefresh(win->x_win);
16505b0160eSGleb Smirnoff 		return;
1669b50d902SRodney W. Grimes 	    }
16705b0160eSGleb Smirnoff 
16805b0160eSGleb Smirnoff 	case 025:	/* ^U */
16905b0160eSGleb Smirnoff kill:
1709b50d902SRodney W. Grimes 		wmove(win->x_win, win->x_line, 0);
1719b50d902SRodney W. Grimes 		wclrtoeol(win->x_win);
1729b50d902SRodney W. Grimes 		getyx(win->x_win, win->x_line, win->x_col);
17305b0160eSGleb Smirnoff 		wrefresh(win->x_win);
17405b0160eSGleb Smirnoff 		return;
17505b0160eSGleb Smirnoff 
17605b0160eSGleb Smirnoff 	case L'\f':
1779b50d902SRodney W. Grimes 		if (win == &my_win)
1789b50d902SRodney W. Grimes 			wrefresh(curscr);
17905b0160eSGleb Smirnoff 		return;
18005b0160eSGleb Smirnoff 
18105b0160eSGleb Smirnoff 	case L'\7':
18205b0160eSGleb Smirnoff 		write(STDOUT_FILENO, wc, sizeof(*wc));
18305b0160eSGleb Smirnoff 		return;
1849b50d902SRodney W. Grimes 	}
18505b0160eSGleb Smirnoff 
18605b0160eSGleb Smirnoff 
18705b0160eSGleb Smirnoff 	if (iswprint(*wc) || *wc == L'\t')
18805b0160eSGleb Smirnoff 		wadd_wch(win->x_win, makecchar(*wc));
18905b0160eSGleb Smirnoff 	else
19005b0160eSGleb Smirnoff 		beep();
19105b0160eSGleb Smirnoff 
1929b50d902SRodney W. Grimes 	getyx(win->x_win, win->x_line, win->x_col);
1939b50d902SRodney W. Grimes 	wrefresh(win->x_win);
1949b50d902SRodney W. Grimes }
1959b50d902SRodney W. Grimes 
1969b50d902SRodney W. Grimes /*
1979b50d902SRodney W. Grimes  * Read the character at the indicated position in win
1989b50d902SRodney W. Grimes  */
19928592604SJoerg Wunsch int
200b6d9e1f3SXin LI readwin(WINDOW *win, int line, int col)
2019b50d902SRodney W. Grimes {
2029b50d902SRodney W. Grimes 	int oldline, oldcol;
203caa64801SMark Murray 	int c;
2049b50d902SRodney W. Grimes 
2059b50d902SRodney W. Grimes 	getyx(win, oldline, oldcol);
2069b50d902SRodney W. Grimes 	wmove(win, line, col);
2079b50d902SRodney W. Grimes 	c = winch(win);
2089b50d902SRodney W. Grimes 	wmove(win, oldline, oldcol);
2099b50d902SRodney W. Grimes 	return (c);
2109b50d902SRodney W. Grimes }
211