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$");
3387710Smarkm
341590Srgrimes#ifndef lint
3587710Smarkmstatic const char sccsid[] = "@(#)init_disp.c	8.2 (Berkeley) 2/16/94";
3632503Scharnier#endif
371590Srgrimes
381590Srgrimes/*
391590Srgrimes * Initialization code for the display package,
401590Srgrimes * as well as the signal handling routines.
411590Srgrimes */
421590Srgrimes
4387710Smarkm#include <sys/stat.h>
4487710Smarkm
4532503Scharnier#include <err.h>
4632503Scharnier#include <signal.h>
4778733Sdd#include <stdlib.h>
485297Sache#include <unistd.h>
4950636Speter#include <termios.h>
5087710Smarkm
511590Srgrimes#include "talk.h"
521590Srgrimes
538874Srgrimes/*
545297Sache * Make sure the callee can write to the screen
555297Sache */
5614443Sjoergvoid
57178642Sdelphijcheck_writeable(void)
585297Sache{
595297Sache	char *tty;
605297Sache	struct stat sb;
615297Sache
625297Sache	if ((tty = ttyname(STDERR_FILENO)) == NULL)
635297Sache		err(1, "ttyname");
645297Sache	if (stat(tty, &sb) < 0)
655297Sache		err(1, "%s", tty);
665297Sache	if (!(sb.st_mode & S_IWGRP))
675297Sache		errx(1, "The callee cannot write to this terminal, use \"mesg y\".");
685297Sache}
695297Sache
708874Srgrimes/*
711590Srgrimes * Set up curses, catch the appropriate signals,
721590Srgrimes * and build the various windows.
731590Srgrimes */
7414443Sjoergvoid
75178642Sdelphijinit_display(void)
761590Srgrimes{
7717676Speter	struct sigaction sa;
781590Srgrimes
791590Srgrimes	if (initscr() == NULL)
801590Srgrimes		errx(1, "Terminal type unset or lacking necessary features.");
8117676Speter	(void) sigaction(SIGTSTP, (struct sigaction *)0, &sa);
8217676Speter	sigaddset(&sa.sa_mask, SIGALRM);
8317676Speter	(void) sigaction(SIGTSTP, &sa, (struct sigaction *)0);
841590Srgrimes	curses_initialized = 1;
851590Srgrimes	clear();
861590Srgrimes	refresh();
871590Srgrimes	noecho();
881590Srgrimes	crmode();
891590Srgrimes	signal(SIGINT, sig_sent);
901590Srgrimes	signal(SIGPIPE, sig_sent);
91128445Scognet	signal(SIGWINCH, sig_winch);
921590Srgrimes	/* curses takes care of ^Z */
931590Srgrimes	my_win.x_nlines = LINES / 2;
941590Srgrimes	my_win.x_ncols = COLS;
951590Srgrimes	my_win.x_win = newwin(my_win.x_nlines, my_win.x_ncols, 0, 0);
9620988Speter	idlok(my_win.x_win, TRUE);
972929Sache	scrollok(my_win.x_win, TRUE);
981590Srgrimes	wclear(my_win.x_win);
991590Srgrimes
1001590Srgrimes	his_win.x_nlines = LINES / 2 - 1;
1011590Srgrimes	his_win.x_ncols = COLS;
1021590Srgrimes	his_win.x_win = newwin(his_win.x_nlines, his_win.x_ncols,
1031590Srgrimes	    my_win.x_nlines+1, 0);
10420988Speter	idlok(my_win.x_win, TRUE);
1052929Sache	scrollok(his_win.x_win, TRUE);
1061590Srgrimes	wclear(his_win.x_win);
1071590Srgrimes
1081590Srgrimes	line_win = newwin(1, COLS, my_win.x_nlines, 0);
10917698Speter#if defined(hline) || defined(whline) || defined(NCURSES_VERSION)
11017698Speter	whline(line_win, 0, COLS);
11117698Speter#else
11217698Speter	box(line_win, '-', '-');
11317698Speter#endif
1141590Srgrimes	wrefresh(line_win);
1151590Srgrimes	/* let them know we are working on it */
1161590Srgrimes	current_state = "No connection yet";
1171590Srgrimes}
1181590Srgrimes
1191590Srgrimes/*
1201590Srgrimes * Trade edit characters with the other talk. By agreement
1211590Srgrimes * the first three characters each talk transmits after
1221590Srgrimes * connection are the three edit characters.
1231590Srgrimes */
12414443Sjoergvoid
125178642Sdelphijset_edit_chars(void)
1261590Srgrimes{
1271590Srgrimes	char buf[3];
1281590Srgrimes	int cc;
12917676Speter	struct termios tio;
1308874Srgrimes
13117676Speter	tcgetattr(0, &tio);
13217676Speter	my_win.cerase = tio.c_cc[VERASE];
13317676Speter	my_win.kill = tio.c_cc[VKILL];
13417676Speter	my_win.werase = tio.c_cc[VWERASE];
13517676Speter	if (my_win.cerase == (char)_POSIX_VDISABLE)
13617676Speter		my_win.kill = CERASE;
13717676Speter	if (my_win.kill == (char)_POSIX_VDISABLE)
13817676Speter		my_win.kill = CKILL;
13917676Speter	if (my_win.werase == (char)_POSIX_VDISABLE)
14017676Speter		my_win.werase = CWERASE;
1411590Srgrimes	buf[0] = my_win.cerase;
1421590Srgrimes	buf[1] = my_win.kill;
1431590Srgrimes	buf[2] = my_win.werase;
1441590Srgrimes	cc = write(sockt, buf, sizeof(buf));
1451590Srgrimes	if (cc != sizeof(buf) )
1461590Srgrimes		p_error("Lost the connection");
1471590Srgrimes	cc = read(sockt, buf, sizeof(buf));
1481590Srgrimes	if (cc != sizeof(buf) )
1491590Srgrimes		p_error("Lost the connection");
1501590Srgrimes	his_win.cerase = buf[0];
1511590Srgrimes	his_win.kill = buf[1];
1521590Srgrimes	his_win.werase = buf[2];
1531590Srgrimes}
1541590Srgrimes
15514443Sjoerg/* ARGSUSED */
1561590Srgrimesvoid
157178642Sdelphijsig_sent(int signo __unused)
1581590Srgrimes{
1591590Srgrimes
1601590Srgrimes	message("Connection closing. Exiting");
1611590Srgrimes	quit();
1621590Srgrimes}
1631590Srgrimes
164128445Scognetvoid
165178642Sdelphijsig_winch(int dummy __unused)
166128445Scognet{
167128445Scognet
168128445Scognet	gotwinch = 1;
169128445Scognet}
170128445Scognet
1711590Srgrimes/*
1721590Srgrimes * All done talking...hang up the phone and reset terminal thingy's
1731590Srgrimes */
17414443Sjoergvoid
175178642Sdelphijquit(void)
1761590Srgrimes{
1771590Srgrimes
1781590Srgrimes	if (curses_initialized) {
1791590Srgrimes		wmove(his_win.x_win, his_win.x_nlines-1, 0);
1801590Srgrimes		wclrtoeol(his_win.x_win);
1811590Srgrimes		wrefresh(his_win.x_win);
1821590Srgrimes		endwin();
1831590Srgrimes	}
1841590Srgrimes	if (invitation_waiting)
1851590Srgrimes		send_delete();
1861590Srgrimes	exit(0);
1871590Srgrimes}
188128445Scognet
189128445Scognet/*
190128445Scognet * If we get SIGWINCH, recompute both window sizes and refresh things.
191128445Scognet */
192128445Scognetvoid
193128445Scognetresize_display(void)
194128445Scognet{
195128445Scognet	struct winsize ws;
196128445Scognet
197128445Scognet	if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0 ||
198128445Scognet	    (ws.ws_row == LINES && ws.ws_col == COLS))
199128445Scognet		return;
200128445Scognet
201128445Scognet	/* Update curses' internal state with new window size. */
202128445Scognet	resizeterm(ws.ws_row, ws.ws_col);
203128445Scognet
204128445Scognet	/*
205128445Scognet	 * Resize each window but wait to refresh the screen until
206128445Scognet	 * everything has been drawn so the cursor is in the right spot.
207128445Scognet	 */
208128445Scognet	my_win.x_nlines = LINES / 2;
209128445Scognet	my_win.x_ncols = COLS;
210128445Scognet	wresize(my_win.x_win, my_win.x_nlines, my_win.x_ncols);
211128445Scognet	mvwin(my_win.x_win, 0, 0);
212128445Scognet	clearok(my_win.x_win, TRUE);
213128445Scognet
214128445Scognet	his_win.x_nlines = LINES / 2 - 1;
215128445Scognet	his_win.x_ncols = COLS;
216128445Scognet	wresize(his_win.x_win, his_win.x_nlines, his_win.x_ncols);
217128445Scognet	mvwin(his_win.x_win, my_win.x_nlines + 1, 0);
218128445Scognet	clearok(his_win.x_win, TRUE);
219128445Scognet
220128445Scognet	wresize(line_win, 1, COLS);
221128445Scognet	mvwin(line_win, my_win.x_nlines, 0);
222128445Scognet#if defined(NCURSES_VERSION) || defined(whline)
223128445Scognet	whline(line_win, '-', COLS);
224128445Scognet#else
225128445Scognet	wmove(line_win, my_win.x_nlines, 0);
226128445Scognet	box(line_win, '-', '-');
227128445Scognet#endif
228128445Scognet
229128445Scognet	/* Now redraw the screen. */
230128445Scognet	wrefresh(his_win.x_win);
231128445Scognet	wrefresh(line_win);
232128445Scognet	wrefresh(my_win.x_win);
233128445Scognet}
234