init_disp.c revision 128445
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 * 3. All advertising materials mentioning features or use of this software
141590Srgrimes *    must display the following acknowledgement:
151590Srgrimes *	This product includes software developed by the University of
161590Srgrimes *	California, Berkeley and its contributors.
171590Srgrimes * 4. Neither the name of the University nor the names of its contributors
181590Srgrimes *    may be used to endorse or promote products derived from this software
191590Srgrimes *    without specific prior written permission.
201590Srgrimes *
211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311590Srgrimes * SUCH DAMAGE.
321590Srgrimes */
331590Srgrimes
3487710Smarkm#include <sys/cdefs.h>
3587710Smarkm
3687710Smarkm__FBSDID("$FreeBSD: head/usr.bin/talk/init_disp.c 128445 2004-04-19 21:37:29Z cognet $");
3787710Smarkm
381590Srgrimes#ifndef lint
3987710Smarkmstatic const char sccsid[] = "@(#)init_disp.c	8.2 (Berkeley) 2/16/94";
4032503Scharnier#endif
411590Srgrimes
421590Srgrimes/*
431590Srgrimes * Initialization code for the display package,
441590Srgrimes * as well as the signal handling routines.
451590Srgrimes */
461590Srgrimes
4787710Smarkm#include <sys/stat.h>
4887710Smarkm
4932503Scharnier#include <err.h>
5032503Scharnier#include <signal.h>
5178733Sdd#include <stdlib.h>
525297Sache#include <unistd.h>
5350636Speter#include <termios.h>
5487710Smarkm
551590Srgrimes#include "talk.h"
561590Srgrimes
57128445Scognetextern volatile sig_atomic_t gotwinch;
58128445Scognet
598874Srgrimes/*
605297Sache * Make sure the callee can write to the screen
615297Sache */
6214443Sjoergvoid
6314443Sjoergcheck_writeable()
645297Sache{
655297Sache	char *tty;
665297Sache	struct stat sb;
675297Sache
685297Sache	if ((tty = ttyname(STDERR_FILENO)) == NULL)
695297Sache		err(1, "ttyname");
705297Sache	if (stat(tty, &sb) < 0)
715297Sache		err(1, "%s", tty);
725297Sache	if (!(sb.st_mode & S_IWGRP))
735297Sache		errx(1, "The callee cannot write to this terminal, use \"mesg y\".");
745297Sache}
755297Sache
768874Srgrimes/*
771590Srgrimes * Set up curses, catch the appropriate signals,
781590Srgrimes * and build the various windows.
791590Srgrimes */
8014443Sjoergvoid
811590Srgrimesinit_display()
821590Srgrimes{
8317676Speter	struct sigaction sa;
841590Srgrimes
851590Srgrimes	if (initscr() == NULL)
861590Srgrimes		errx(1, "Terminal type unset or lacking necessary features.");
8717676Speter	(void) sigaction(SIGTSTP, (struct sigaction *)0, &sa);
8817676Speter	sigaddset(&sa.sa_mask, SIGALRM);
8917676Speter	(void) sigaction(SIGTSTP, &sa, (struct sigaction *)0);
901590Srgrimes	curses_initialized = 1;
911590Srgrimes	clear();
921590Srgrimes	refresh();
931590Srgrimes	noecho();
941590Srgrimes	crmode();
951590Srgrimes	signal(SIGINT, sig_sent);
961590Srgrimes	signal(SIGPIPE, sig_sent);
97128445Scognet	signal(SIGWINCH, sig_winch);
981590Srgrimes	/* curses takes care of ^Z */
991590Srgrimes	my_win.x_nlines = LINES / 2;
1001590Srgrimes	my_win.x_ncols = COLS;
1011590Srgrimes	my_win.x_win = newwin(my_win.x_nlines, my_win.x_ncols, 0, 0);
10220988Speter	idlok(my_win.x_win, TRUE);
1032929Sache	scrollok(my_win.x_win, TRUE);
1041590Srgrimes	wclear(my_win.x_win);
1051590Srgrimes
1061590Srgrimes	his_win.x_nlines = LINES / 2 - 1;
1071590Srgrimes	his_win.x_ncols = COLS;
1081590Srgrimes	his_win.x_win = newwin(his_win.x_nlines, his_win.x_ncols,
1091590Srgrimes	    my_win.x_nlines+1, 0);
11020988Speter	idlok(my_win.x_win, TRUE);
1112929Sache	scrollok(his_win.x_win, TRUE);
1121590Srgrimes	wclear(his_win.x_win);
1131590Srgrimes
1141590Srgrimes	line_win = newwin(1, COLS, my_win.x_nlines, 0);
11517698Speter#if defined(hline) || defined(whline) || defined(NCURSES_VERSION)
11617698Speter	whline(line_win, 0, COLS);
11717698Speter#else
11817698Speter	box(line_win, '-', '-');
11917698Speter#endif
1201590Srgrimes	wrefresh(line_win);
1211590Srgrimes	/* let them know we are working on it */
1221590Srgrimes	current_state = "No connection yet";
1231590Srgrimes}
1241590Srgrimes
1251590Srgrimes/*
1261590Srgrimes * Trade edit characters with the other talk. By agreement
1271590Srgrimes * the first three characters each talk transmits after
1281590Srgrimes * connection are the three edit characters.
1291590Srgrimes */
13014443Sjoergvoid
1311590Srgrimesset_edit_chars()
1321590Srgrimes{
1331590Srgrimes	char buf[3];
1341590Srgrimes	int cc;
13517676Speter	struct termios tio;
1368874Srgrimes
13717676Speter	tcgetattr(0, &tio);
13817676Speter	my_win.cerase = tio.c_cc[VERASE];
13917676Speter	my_win.kill = tio.c_cc[VKILL];
14017676Speter	my_win.werase = tio.c_cc[VWERASE];
14117676Speter	if (my_win.cerase == (char)_POSIX_VDISABLE)
14217676Speter		my_win.kill = CERASE;
14317676Speter	if (my_win.kill == (char)_POSIX_VDISABLE)
14417676Speter		my_win.kill = CKILL;
14517676Speter	if (my_win.werase == (char)_POSIX_VDISABLE)
14617676Speter		my_win.werase = CWERASE;
1471590Srgrimes	buf[0] = my_win.cerase;
1481590Srgrimes	buf[1] = my_win.kill;
1491590Srgrimes	buf[2] = my_win.werase;
1501590Srgrimes	cc = write(sockt, buf, sizeof(buf));
1511590Srgrimes	if (cc != sizeof(buf) )
1521590Srgrimes		p_error("Lost the connection");
1531590Srgrimes	cc = read(sockt, buf, sizeof(buf));
1541590Srgrimes	if (cc != sizeof(buf) )
1551590Srgrimes		p_error("Lost the connection");
1561590Srgrimes	his_win.cerase = buf[0];
1571590Srgrimes	his_win.kill = buf[1];
1581590Srgrimes	his_win.werase = buf[2];
1591590Srgrimes}
1601590Srgrimes
16114443Sjoerg/* ARGSUSED */
1621590Srgrimesvoid
16314443Sjoergsig_sent(signo)
16487710Smarkm	int signo __unused;
1651590Srgrimes{
1661590Srgrimes
1671590Srgrimes	message("Connection closing. Exiting");
1681590Srgrimes	quit();
1691590Srgrimes}
1701590Srgrimes
171128445Scognetvoid
172128445Scognetsig_winch(int dummy)
173128445Scognet{
174128445Scognet
175128445Scognet	gotwinch = 1;
176128445Scognet}
177128445Scognet
1781590Srgrimes/*
1791590Srgrimes * All done talking...hang up the phone and reset terminal thingy's
1801590Srgrimes */
18114443Sjoergvoid
1821590Srgrimesquit()
1831590Srgrimes{
1841590Srgrimes
1851590Srgrimes	if (curses_initialized) {
1861590Srgrimes		wmove(his_win.x_win, his_win.x_nlines-1, 0);
1871590Srgrimes		wclrtoeol(his_win.x_win);
1881590Srgrimes		wrefresh(his_win.x_win);
1891590Srgrimes		endwin();
1901590Srgrimes	}
1911590Srgrimes	if (invitation_waiting)
1921590Srgrimes		send_delete();
1931590Srgrimes	exit(0);
1941590Srgrimes}
195128445Scognet
196128445Scognet/*
197128445Scognet * If we get SIGWINCH, recompute both window sizes and refresh things.
198128445Scognet */
199128445Scognetvoid
200128445Scognetresize_display(void)
201128445Scognet{
202128445Scognet	struct winsize ws;
203128445Scognet
204128445Scognet	if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0 ||
205128445Scognet	    (ws.ws_row == LINES && ws.ws_col == COLS))
206128445Scognet		return;
207128445Scognet
208128445Scognet	/* Update curses' internal state with new window size. */
209128445Scognet	resizeterm(ws.ws_row, ws.ws_col);
210128445Scognet
211128445Scognet	/*
212128445Scognet	 * Resize each window but wait to refresh the screen until
213128445Scognet	 * everything has been drawn so the cursor is in the right spot.
214128445Scognet	 */
215128445Scognet	my_win.x_nlines = LINES / 2;
216128445Scognet	my_win.x_ncols = COLS;
217128445Scognet	wresize(my_win.x_win, my_win.x_nlines, my_win.x_ncols);
218128445Scognet	mvwin(my_win.x_win, 0, 0);
219128445Scognet	clearok(my_win.x_win, TRUE);
220128445Scognet
221128445Scognet	his_win.x_nlines = LINES / 2 - 1;
222128445Scognet	his_win.x_ncols = COLS;
223128445Scognet	wresize(his_win.x_win, his_win.x_nlines, his_win.x_ncols);
224128445Scognet	mvwin(his_win.x_win, my_win.x_nlines + 1, 0);
225128445Scognet	clearok(his_win.x_win, TRUE);
226128445Scognet
227128445Scognet	wresize(line_win, 1, COLS);
228128445Scognet	mvwin(line_win, my_win.x_nlines, 0);
229128445Scognet#if defined(NCURSES_VERSION) || defined(whline)
230128445Scognet	whline(line_win, '-', COLS);
231128445Scognet#else
232128445Scognet	wmove(line_win, my_win.x_nlines, 0);
233128445Scognet	box(line_win, '-', '-');
234128445Scognet#endif
235128445Scognet
236128445Scognet	/* Now redraw the screen. */
237128445Scognet	wrefresh(his_win.x_win);
238128445Scognet	wrefresh(line_win);
239128445Scognet	wrefresh(my_win.x_win);
240128445Scognet}
241