xref: /freebsd/usr.bin/talk/display.c (revision bdcbfde31e8e9b343f113a1956384bdf30d1ed62)
1*8a16b7a1SPedro F. Giffuni /*-
2*8a16b7a1SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
3*8a16b7a1SPedro F. Giffuni  *
49b50d902SRodney W. Grimes  * Copyright (c) 1983, 1993
59b50d902SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
69b50d902SRodney W. Grimes  *
79b50d902SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
89b50d902SRodney W. Grimes  * modification, are permitted provided that the following conditions
99b50d902SRodney W. Grimes  * are met:
109b50d902SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
119b50d902SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
129b50d902SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
139b50d902SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
149b50d902SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
15fbbd9655SWarner Losh  * 3. Neither the name of the University nor the names of its contributors
169b50d902SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
179b50d902SRodney W. Grimes  *    without specific prior written permission.
189b50d902SRodney W. Grimes  *
199b50d902SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
209b50d902SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
219b50d902SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
229b50d902SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
239b50d902SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
249b50d902SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
259b50d902SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
269b50d902SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
279b50d902SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
289b50d902SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
299b50d902SRodney W. Grimes  * SUCH DAMAGE.
309b50d902SRodney W. Grimes  */
319b50d902SRodney W. Grimes 
32caa64801SMark Murray 
339b50d902SRodney W. Grimes 
349b50d902SRodney W. Grimes /*
359b50d902SRodney W. Grimes  * The window 'manager', initializes curses and handles the actual
369b50d902SRodney W. Grimes  * displaying of text
379b50d902SRodney W. Grimes  */
38edee6d38SAndrey A. Chernov #include <ctype.h>
393daadfc8SXin LI #include <unistd.h>
4005b0160eSGleb Smirnoff #include <wctype.h>
4105b0160eSGleb Smirnoff #define _XOPEN_SOURCE_EXTENDED
4205b0160eSGleb Smirnoff #include <curses.h>
439b50d902SRodney W. Grimes 
44caa64801SMark Murray #include "talk.h"
45caa64801SMark Murray 
4605b0160eSGleb Smirnoff void	display(xwin_t *, wchar_t *);
4705b0160eSGleb Smirnoff 
489b50d902SRodney W. Grimes xwin_t	my_win;
499b50d902SRodney W. Grimes xwin_t	his_win;
509b50d902SRodney W. Grimes WINDOW	*line_win;
519b50d902SRodney W. Grimes 
529b50d902SRodney W. Grimes int	curses_initialized = 0;
539b50d902SRodney W. Grimes 
549b50d902SRodney W. Grimes /*
559b50d902SRodney W. Grimes  * max HAS to be a function, it is called with
569d5abbddSJens Schweikhardt  * an argument of the form --foo at least once.
579b50d902SRodney W. Grimes  */
5828592604SJoerg Wunsch int
max(int a,int b)59b6d9e1f3SXin LI max(int a, int b)
609b50d902SRodney W. Grimes {
619b50d902SRodney W. Grimes 
629b50d902SRodney W. Grimes 	return (a > b ? a : b);
639b50d902SRodney W. Grimes }
649b50d902SRodney W. Grimes 
6505b0160eSGleb Smirnoff static cchar_t *
makecchar(wchar_t in)6605b0160eSGleb Smirnoff makecchar(wchar_t in)
6705b0160eSGleb Smirnoff {
6805b0160eSGleb Smirnoff 	static cchar_t cc;
6905b0160eSGleb Smirnoff 	wchar_t wc[2];
7005b0160eSGleb Smirnoff 
7105b0160eSGleb Smirnoff 	wc[0] = in;
7205b0160eSGleb Smirnoff 	wc[1] = L'\0';
7305b0160eSGleb Smirnoff 
7405b0160eSGleb Smirnoff 	if (setcchar(&cc, wc, A_NORMAL, 0, NULL) != OK)
7505b0160eSGleb Smirnoff 		p_error("settchar(3) failure");
7605b0160eSGleb Smirnoff 
7705b0160eSGleb Smirnoff 	return (&cc);
7805b0160eSGleb Smirnoff }
7905b0160eSGleb Smirnoff 
809b50d902SRodney W. Grimes /*
8105b0160eSGleb Smirnoff  * Display a symbol on somebody's window, processing some control
829b50d902SRodney W. Grimes  * characters while we are at it.
839b50d902SRodney W. Grimes  */
8428592604SJoerg Wunsch void
display(xwin_t * win,wchar_t * wc)8505b0160eSGleb Smirnoff display(xwin_t *win, wchar_t *wc)
869b50d902SRodney W. Grimes {
879b50d902SRodney W. Grimes 
8805b0160eSGleb Smirnoff 	/*
8905b0160eSGleb Smirnoff 	 * Alas, can't use variables in C switch statement.
9005b0160eSGleb Smirnoff 	 * Workaround these 3 cases with goto.
9105b0160eSGleb Smirnoff 	 */
9205b0160eSGleb Smirnoff 	if (*wc == win->kill)
9305b0160eSGleb Smirnoff 		goto kill;
9405b0160eSGleb Smirnoff 	else if (*wc == win->cerase)
9505b0160eSGleb Smirnoff 		goto cerase;
9605b0160eSGleb Smirnoff 	else if (*wc == win->werase)
9705b0160eSGleb Smirnoff 		goto werase;
9805b0160eSGleb Smirnoff 
9905b0160eSGleb Smirnoff 	switch (*wc) {
10005b0160eSGleb Smirnoff 	case L'\n':
10105b0160eSGleb Smirnoff 	case L'\r':
10205b0160eSGleb Smirnoff 		wadd_wch(win->x_win, makecchar(L'\n'));
103edee6d38SAndrey A. Chernov 		getyx(win->x_win, win->x_line, win->x_col);
10405b0160eSGleb Smirnoff 		wrefresh(win->x_win);
10505b0160eSGleb Smirnoff 		return;
10605b0160eSGleb Smirnoff 
10705b0160eSGleb Smirnoff 	case 004:
10805b0160eSGleb Smirnoff 		if (win == &my_win) {
10905b0160eSGleb Smirnoff 			/* Ctrl-D clears the screen. */
1108aed91caSLuigi Rizzo 			werase(my_win.x_win);
1118aed91caSLuigi Rizzo 			getyx(my_win.x_win, my_win.x_line, my_win.x_col);
1128aed91caSLuigi Rizzo 			wrefresh(my_win.x_win);
1138aed91caSLuigi Rizzo 			werase(his_win.x_win);
1148aed91caSLuigi Rizzo 			getyx(his_win.x_win, his_win.x_line, his_win.x_col);
1158aed91caSLuigi Rizzo 			wrefresh(his_win.x_win);
1168aed91caSLuigi Rizzo 		}
11705b0160eSGleb Smirnoff 		return;
1188aed91caSLuigi Rizzo 
11905b0160eSGleb Smirnoff 	/* Erase character. */
12005b0160eSGleb Smirnoff 	case 010:	/* BS */
12105b0160eSGleb Smirnoff 	case 0177:	/* DEL */
12205b0160eSGleb Smirnoff cerase:
1239b50d902SRodney W. Grimes 		wmove(win->x_win, win->x_line, max(--win->x_col, 0));
1249b50d902SRodney W. Grimes 		getyx(win->x_win, win->x_line, win->x_col);
1259b50d902SRodney W. Grimes 		waddch(win->x_win, ' ');
1269b50d902SRodney W. Grimes 		wmove(win->x_win, win->x_line, win->x_col);
1279b50d902SRodney W. Grimes 		getyx(win->x_win, win->x_line, win->x_col);
12805b0160eSGleb Smirnoff 		wrefresh(win->x_win);
12905b0160eSGleb Smirnoff 		return;
13005b0160eSGleb Smirnoff 
13105b0160eSGleb Smirnoff 	case 027:	/* ^W */
13205b0160eSGleb Smirnoff werase:
13305b0160eSGleb Smirnoff 	    {
1349b50d902SRodney W. Grimes 		/*
1359b50d902SRodney W. Grimes 		 * On word erase search backwards until we find
1369b50d902SRodney W. Grimes 		 * the beginning of a word or the beginning of
1379b50d902SRodney W. Grimes 		 * the line.
1389b50d902SRodney W. Grimes 		 */
13905b0160eSGleb Smirnoff 		int endcol, xcol, c;
1409b50d902SRodney W. Grimes 
1419b50d902SRodney W. Grimes 		endcol = win->x_col;
1429b50d902SRodney W. Grimes 		xcol = endcol - 1;
1439b50d902SRodney W. Grimes 		while (xcol >= 0) {
1449b50d902SRodney W. Grimes 			c = readwin(win->x_win, win->x_line, xcol);
1459b50d902SRodney W. Grimes 			if (c != ' ')
1469b50d902SRodney W. Grimes 				break;
1479b50d902SRodney W. Grimes 			xcol--;
1489b50d902SRodney W. Grimes 		}
1499b50d902SRodney W. Grimes 		while (xcol >= 0) {
1509b50d902SRodney W. Grimes 			c = readwin(win->x_win, win->x_line, xcol);
1519b50d902SRodney W. Grimes 			if (c == ' ')
1529b50d902SRodney W. Grimes 				break;
1539b50d902SRodney W. Grimes 			xcol--;
1549b50d902SRodney W. Grimes 		}
1559b50d902SRodney W. Grimes 		wmove(win->x_win, win->x_line, xcol + 1);
15605b0160eSGleb Smirnoff 		for (int i = xcol + 1; i < endcol; i++)
1579b50d902SRodney W. Grimes 			waddch(win->x_win, ' ');
1589b50d902SRodney W. Grimes 		wmove(win->x_win, win->x_line, xcol + 1);
1599b50d902SRodney W. Grimes 		getyx(win->x_win, win->x_line, win->x_col);
16005b0160eSGleb Smirnoff 		wrefresh(win->x_win);
16105b0160eSGleb Smirnoff 		return;
1629b50d902SRodney W. Grimes 	    }
16305b0160eSGleb Smirnoff 
16405b0160eSGleb Smirnoff 	case 025:	/* ^U */
16505b0160eSGleb Smirnoff kill:
1669b50d902SRodney W. Grimes 		wmove(win->x_win, win->x_line, 0);
1679b50d902SRodney W. Grimes 		wclrtoeol(win->x_win);
1689b50d902SRodney W. Grimes 		getyx(win->x_win, win->x_line, win->x_col);
16905b0160eSGleb Smirnoff 		wrefresh(win->x_win);
17005b0160eSGleb Smirnoff 		return;
17105b0160eSGleb Smirnoff 
17205b0160eSGleb Smirnoff 	case L'\f':
1739b50d902SRodney W. Grimes 		if (win == &my_win)
1749b50d902SRodney W. Grimes 			wrefresh(curscr);
17505b0160eSGleb Smirnoff 		return;
17605b0160eSGleb Smirnoff 
17705b0160eSGleb Smirnoff 	case L'\7':
17805b0160eSGleb Smirnoff 		write(STDOUT_FILENO, wc, sizeof(*wc));
17905b0160eSGleb Smirnoff 		return;
1809b50d902SRodney W. Grimes 	}
18105b0160eSGleb Smirnoff 
18205b0160eSGleb Smirnoff 
18305b0160eSGleb Smirnoff 	if (iswprint(*wc) || *wc == L'\t')
18405b0160eSGleb Smirnoff 		wadd_wch(win->x_win, makecchar(*wc));
18505b0160eSGleb Smirnoff 	else
18605b0160eSGleb Smirnoff 		beep();
18705b0160eSGleb Smirnoff 
1889b50d902SRodney W. Grimes 	getyx(win->x_win, win->x_line, win->x_col);
1899b50d902SRodney W. Grimes 	wrefresh(win->x_win);
1909b50d902SRodney W. Grimes }
1919b50d902SRodney W. Grimes 
1929b50d902SRodney W. Grimes /*
1939b50d902SRodney W. Grimes  * Read the character at the indicated position in win
1949b50d902SRodney W. Grimes  */
19528592604SJoerg Wunsch int
readwin(WINDOW * win,int line,int col)196b6d9e1f3SXin LI readwin(WINDOW *win, int line, int col)
1979b50d902SRodney W. Grimes {
1989b50d902SRodney W. Grimes 	int oldline, oldcol;
199caa64801SMark Murray 	int c;
2009b50d902SRodney W. Grimes 
2019b50d902SRodney W. Grimes 	getyx(win, oldline, oldcol);
2029b50d902SRodney W. Grimes 	wmove(win, line, col);
2039b50d902SRodney W. Grimes 	c = winch(win);
2049b50d902SRodney W. Grimes 	wmove(win, oldline, oldcol);
2059b50d902SRodney W. Grimes 	return (c);
2069b50d902SRodney W. Grimes }
207