11590Srgrimes/*
21590Srgrimes * Copyright (c) 1983, 1993
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes * 1. Redistributions of source code must retain the above copyright
91590Srgrimes *    notice, this list of conditions and the following disclaimer.
101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer in the
121590Srgrimes *    documentation and/or other materials provided with the distribution.
131590Srgrimes * 4. Neither the name of the University nor the names of its contributors
141590Srgrimes *    may be used to endorse or promote products derived from this software
151590Srgrimes *    without specific prior written permission.
161590Srgrimes *
171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271590Srgrimes * SUCH DAMAGE.
281590Srgrimes */
291590Srgrimes
3087710Smarkm#include <sys/cdefs.h>
3187710Smarkm
3287710Smarkm__FBSDID("$FreeBSD: releng/10.2/usr.bin/talk/display.c 273496 2014-10-23 00:39:19Z ngie $");
3387710Smarkm
341590Srgrimes#ifndef lint
3587710Smarkmstatic const char sccsid[] = "@(#)display.c	8.1 (Berkeley) 6/6/93";
3632503Scharnier#endif
371590Srgrimes
381590Srgrimes/*
391590Srgrimes * The window 'manager', initializes curses and handles the actual
401590Srgrimes * displaying of text
411590Srgrimes */
422929Sache#include <ctype.h>
43200418Sdelphij#include <unistd.h>
44273496Sngie#include <wctype.h>
45273496Sngie#define _XOPEN_SOURCE_EXTENDED
46273496Sngie#include <curses.h>
471590Srgrimes
4887710Smarkm#include "talk.h"
4987710Smarkm
50273496Sngievoid	display(xwin_t *, wchar_t *);
51273496Sngie
521590Srgrimesxwin_t	my_win;
531590Srgrimesxwin_t	his_win;
541590SrgrimesWINDOW	*line_win;
551590Srgrimes
561590Srgrimesint	curses_initialized = 0;
571590Srgrimes
581590Srgrimes/*
591590Srgrimes * max HAS to be a function, it is called with
60108533Sschweikh * an argument of the form --foo at least once.
611590Srgrimes */
6214443Sjoergint
63178642Sdelphijmax(int a, int b)
641590Srgrimes{
651590Srgrimes
661590Srgrimes	return (a > b ? a : b);
671590Srgrimes}
681590Srgrimes
69273496Sngiestatic cchar_t *
70273496Sngiemakecchar(wchar_t in)
71273496Sngie{
72273496Sngie	static cchar_t cc;
73273496Sngie	wchar_t wc[2];
74273496Sngie
75273496Sngie	wc[0] = in;
76273496Sngie	wc[1] = L'\0';
77273496Sngie
78273496Sngie	if (setcchar(&cc, wc, A_NORMAL, 0, NULL) != OK)
79273496Sngie		p_error("settchar(3) failure");
80273496Sngie
81273496Sngie	return (&cc);
82273496Sngie}
83273496Sngie
841590Srgrimes/*
85273496Sngie * Display a symbol on somebody's window, processing some control
861590Srgrimes * characters while we are at it.
871590Srgrimes */
8814443Sjoergvoid
89273496Sngiedisplay(xwin_t *win, wchar_t *wc)
901590Srgrimes{
911590Srgrimes
92273496Sngie	/*
93273496Sngie	 * Alas, can't use variables in C switch statement.
94273496Sngie	 * Workaround these 3 cases with goto.
95273496Sngie	 */
96273496Sngie	if (*wc == win->kill)
97273496Sngie		goto kill;
98273496Sngie	else if (*wc == win->cerase)
99273496Sngie		goto cerase;
100273496Sngie	else if (*wc == win->werase)
101273496Sngie		goto werase;
102273496Sngie
103273496Sngie	switch (*wc) {
104273496Sngie	case L'\n':
105273496Sngie	case L'\r':
106273496Sngie		wadd_wch(win->x_win, makecchar(L'\n'));
107273496Sngie		getyx(win->x_win, win->x_line, win->x_col);
108273496Sngie		wrefresh(win->x_win);
109273496Sngie		return;
110273496Sngie
111273496Sngie	case 004:
112273496Sngie		if (win == &my_win) {
113273496Sngie			/* Ctrl-D clears the screen. */
11499965Sluigi			werase(my_win.x_win);
11599965Sluigi			getyx(my_win.x_win, my_win.x_line, my_win.x_col);
11699965Sluigi			wrefresh(my_win.x_win);
11799965Sluigi			werase(his_win.x_win);
11899965Sluigi			getyx(his_win.x_win, his_win.x_line, his_win.x_col);
11999965Sluigi			wrefresh(his_win.x_win);
12099965Sluigi		}
121273496Sngie		return;
122117238Sluigi
123273496Sngie	/* Erase character. */
124273496Sngie	case 010:	/* BS */
125273496Sngie	case 0177:	/* DEL */
126273496Sngiecerase:
127273496Sngie		wmove(win->x_win, win->x_line, max(--win->x_col, 0));
128273496Sngie		getyx(win->x_win, win->x_line, win->x_col);
129273496Sngie		waddch(win->x_win, ' ');
130273496Sngie		wmove(win->x_win, win->x_line, win->x_col);
131273496Sngie		getyx(win->x_win, win->x_line, win->x_col);
132273496Sngie		wrefresh(win->x_win);
133273496Sngie		return;
134273496Sngie
135273496Sngie	case 027:	/* ^W */
136273496Sngiewerase:
137273496Sngie	    {
1381590Srgrimes		/*
1391590Srgrimes		 * On word erase search backwards until we find
1401590Srgrimes		 * the beginning of a word or the beginning of
1411590Srgrimes		 * the line.
1421590Srgrimes		 */
143273496Sngie		int endcol, xcol, c;
1441590Srgrimes
145273496Sngie		endcol = win->x_col;
146273496Sngie		xcol = endcol - 1;
147273496Sngie		while (xcol >= 0) {
148273496Sngie			c = readwin(win->x_win, win->x_line, xcol);
149273496Sngie			if (c != ' ')
150273496Sngie				break;
151273496Sngie			xcol--;
1521590Srgrimes		}
153273496Sngie		while (xcol >= 0) {
154273496Sngie			c = readwin(win->x_win, win->x_line, xcol);
155273496Sngie			if (c == ' ')
156273496Sngie				break;
157273496Sngie			xcol--;
1581590Srgrimes		}
159273496Sngie		wmove(win->x_win, win->x_line, xcol + 1);
160273496Sngie		for (int i = xcol + 1; i < endcol; i++)
161273496Sngie			waddch(win->x_win, ' ');
162273496Sngie		wmove(win->x_win, win->x_line, xcol + 1);
1631590Srgrimes		getyx(win->x_win, win->x_line, win->x_col);
164273496Sngie		wrefresh(win->x_win);
165273496Sngie		return;
166273496Sngie	    }
167273496Sngie
168273496Sngie	case 025:	/* ^U */
169273496Sngiekill:
170273496Sngie		wmove(win->x_win, win->x_line, 0);
171273496Sngie		wclrtoeol(win->x_win);
172273496Sngie		getyx(win->x_win, win->x_line, win->x_col);
173273496Sngie		wrefresh(win->x_win);
174273496Sngie		return;
175273496Sngie
176273496Sngie	case L'\f':
177273496Sngie		if (win == &my_win)
178273496Sngie			wrefresh(curscr);
179273496Sngie		return;
180273496Sngie
181273496Sngie	case L'\7':
182273496Sngie		write(STDOUT_FILENO, wc, sizeof(*wc));
183273496Sngie		return;
1841590Srgrimes	}
185273496Sngie
186273496Sngie
187273496Sngie	if (iswprint(*wc) || *wc == L'\t')
188273496Sngie		wadd_wch(win->x_win, makecchar(*wc));
189273496Sngie	else
190273496Sngie		beep();
191273496Sngie
192273496Sngie	getyx(win->x_win, win->x_line, win->x_col);
1931590Srgrimes	wrefresh(win->x_win);
1941590Srgrimes}
1951590Srgrimes
1961590Srgrimes/*
1971590Srgrimes * Read the character at the indicated position in win
1981590Srgrimes */
19914443Sjoergint
200178642Sdelphijreadwin(WINDOW *win, int line, int col)
2011590Srgrimes{
2021590Srgrimes	int oldline, oldcol;
20387710Smarkm	int c;
2041590Srgrimes
2051590Srgrimes	getyx(win, oldline, oldcol);
2061590Srgrimes	wmove(win, line, col);
2071590Srgrimes	c = winch(win);
2081590Srgrimes	wmove(win, oldline, oldcol);
2091590Srgrimes	return (c);
2101590Srgrimes}
211