xref: /openbsd-src/usr.bin/talk/init_disp.c (revision 898184e3e61f9129feb5978fad5a8c6865f00b92)
1 /*	$OpenBSD: init_disp.c,v 1.20 2009/10/27 23:59:44 deraadt Exp $	*/
2 /*	$NetBSD: init_disp.c,v 1.6 1994/12/09 02:14:17 jtc Exp $	*/
3 
4 /*
5  * Copyright (c) 1983, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 /*
34  * Initialization code for the display package,
35  * as well as the signal handling routines.
36  */
37 
38 #include "talk.h"
39 #include <sys/ioctl.h>
40 #include <sys/ioctl_compat.h>
41 #include <err.h>
42 #include <stdlib.h>
43 #include <termios.h>
44 #include <unistd.h>
45 
46 /*
47  * Set up curses, catch the appropriate signals,
48  * and build the various windows.
49  */
50 void
51 init_display(void)
52 {
53 	struct sigaction sa;
54 
55 	if (initscr() == NULL)
56 		errx(1, "Terminal type unset or lacking necessary features.");
57 	(void) sigaction(SIGTSTP, NULL, &sa);
58 	sigaddset(&sa.sa_mask, SIGALRM);
59 	(void) sigaction(SIGTSTP, &sa, NULL);
60 	curses_initialized = 1;
61 	clear();
62 	refresh();
63 	noecho();
64 	cbreak();
65 	signal(SIGINT, sig_sent);
66 	signal(SIGPIPE, sig_sent);
67 	signal(SIGWINCH, sig_winch);
68 	/* curses takes care of ^Z */
69 	my_win.x_nlines = LINES / 2;
70 	my_win.x_ncols = COLS;
71 	my_win.x_win = newwin(my_win.x_nlines, my_win.x_ncols, 0, 0);
72 	scrollok(my_win.x_win, smooth_scroll);
73 	wclear(my_win.x_win);
74 
75 	his_win.x_nlines = LINES / 2 - 1;
76 	his_win.x_ncols = COLS;
77 	his_win.x_win = newwin(his_win.x_nlines, his_win.x_ncols,
78 	    my_win.x_nlines+1, 0);
79 	scrollok(his_win.x_win, smooth_scroll);
80 	wclear(his_win.x_win);
81 
82 	line_win = newwin(1, COLS, my_win.x_nlines, 0);
83 #if defined(NCURSES_VERSION) || defined(whline)
84 	whline(line_win, '-', COLS);
85 #else
86 	box(line_win, '-', '-');
87 #endif
88 	wrefresh(line_win);
89 	/* let them know we are working on it */
90 	current_state = "No connection yet";
91 }
92 
93 /*
94  * Trade edit characters with the other talk. By agreement
95  * the first three characters each talk transmits after
96  * connection are the three edit characters.
97  */
98 void
99 set_edit_chars(void)
100 {
101 	u_char buf[3];
102 	int cc;
103 	struct termios tty;
104 
105 	tcgetattr(STDIN_FILENO, &tty);
106 	buf[0] = my_win.cerase = (tty.c_cc[VERASE] == (u_char)_POSIX_VDISABLE)
107 	    ? CERASE : tty.c_cc[VERASE];
108 	buf[1] = my_win.kill = (tty.c_cc[VKILL] == (u_char)_POSIX_VDISABLE)
109 	    ? CKILL : tty.c_cc[VKILL];
110 	buf[2] = my_win.werase = (tty.c_cc[VWERASE] == (u_char)_POSIX_VDISABLE)
111 	    ? CWERASE : tty.c_cc[VWERASE];
112 	cc = write(sockt, buf, sizeof(buf));
113 	if (cc != sizeof(buf) )
114 		quit("Lost the connection", 1);
115 	cc = read(sockt, buf, sizeof(buf));
116 	if (cc != sizeof(buf) )
117 		quit("Lost the connection", 1);
118 	his_win.cerase = buf[0];
119 	his_win.kill = buf[1];
120 	his_win.werase = buf[2];
121 }
122 
123 void
124 sig_sent(int dummy)
125 {
126 
127 	quit("Connection closing.  Exiting", 0);
128 }
129 
130 void
131 sig_winch(int dummy)
132 {
133 
134 	gotwinch = 1;
135 }
136 
137 /*
138  * All done talking...hang up the phone and reset terminal thingy's
139  */
140 void
141 quit(char *warning, int do_perror)
142 {
143 
144 	if (curses_initialized) {
145 		wmove(his_win.x_win, his_win.x_nlines-1, 0);
146 		wclrtoeol(his_win.x_win);
147 		wrefresh(his_win.x_win);
148 		endwin();
149 	}
150 	if (invitation_waiting)
151 		send_delete();
152 	if (warning) {
153 		if (do_perror)
154 			warn("%s", warning);
155 		else
156 			warnx("%s", warning);
157 	}
158 	exit(0);
159 }
160 
161 /*
162  * If we get SIGWINCH, recompute both window sizes and refresh things.
163  */
164 void
165 resize_display(void)
166 {
167 	struct winsize ws;
168 
169 	if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0 ||
170 	    (ws.ws_row == LINES && ws.ws_col == COLS))
171 		return;
172 
173 	/* Update curses' internal state with new window size. */
174 	resizeterm(ws.ws_row, ws.ws_col);
175 
176 	/*
177 	 * Resize each window but wait to refresh the screen until
178 	 * everything has been drawn so the cursor is in the right spot.
179 	 */
180 	my_win.x_nlines = LINES / 2;
181 	my_win.x_ncols = COLS;
182 	wresize(my_win.x_win, my_win.x_nlines, my_win.x_ncols);
183 	mvwin(my_win.x_win, 0, 0);
184 	clearok(my_win.x_win, TRUE);
185 
186 	his_win.x_nlines = LINES / 2 - 1;
187 	his_win.x_ncols = COLS;
188 	wresize(his_win.x_win, his_win.x_nlines, his_win.x_ncols);
189 	mvwin(his_win.x_win, my_win.x_nlines + 1, 0);
190 	clearok(his_win.x_win, TRUE);
191 
192 	wresize(line_win, 1, COLS);
193 	mvwin(line_win, my_win.x_nlines, 0);
194 #if defined(NCURSES_VERSION) || defined(whline)
195 	whline(line_win, '-', COLS);
196 #else
197 	wmove(line_win, my_win.x_nlines, 0);
198 	box(line_win, '-', '-');
199 #endif
200 
201 	/* Now redraw the screen. */
202 	wrefresh(his_win.x_win);
203 	wrefresh(line_win);
204 	wrefresh(my_win.x_win);
205 }
206