]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - usr.bin/talk/display.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / usr.bin / talk / display.c
1 /*
2  * Copyright (c) 1983, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 4. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <sys/cdefs.h>
31
32 __FBSDID("$FreeBSD$");
33
34 #ifndef lint
35 static const char sccsid[] = "@(#)display.c     8.1 (Berkeley) 6/6/93";
36 #endif
37
38 /*
39  * The window 'manager', initializes curses and handles the actual
40  * displaying of text
41  */
42 #include <ctype.h>
43 #include <unistd.h>
44 #include <wctype.h>
45 #define _XOPEN_SOURCE_EXTENDED
46 #include <curses.h>
47
48 #include "talk.h"
49
50 void    display(xwin_t *, wchar_t *);
51
52 xwin_t  my_win;
53 xwin_t  his_win;
54 WINDOW  *line_win;
55
56 int     curses_initialized = 0;
57
58 /*
59  * max HAS to be a function, it is called with
60  * an argument of the form --foo at least once.
61  */
62 int
63 max(int a, int b)
64 {
65
66         return (a > b ? a : b);
67 }
68
69 static cchar_t *
70 makecchar(wchar_t in)
71 {
72         static cchar_t cc;
73         wchar_t wc[2];
74
75         wc[0] = in;
76         wc[1] = L'\0';
77
78         if (setcchar(&cc, wc, A_NORMAL, 0, NULL) != OK)
79                 p_error("settchar(3) failure");
80
81         return (&cc);
82 }
83
84 /*
85  * Display a symbol on somebody's window, processing some control
86  * characters while we are at it.
87  */
88 void
89 display(xwin_t *win, wchar_t *wc)
90 {
91
92         /*
93          * Alas, can't use variables in C switch statement.
94          * Workaround these 3 cases with goto.
95          */
96         if (*wc == win->kill)
97                 goto kill;
98         else if (*wc == win->cerase)
99                 goto cerase;
100         else if (*wc == win->werase)
101                 goto werase;
102
103         switch (*wc) {
104         case L'\n':
105         case L'\r':
106                 wadd_wch(win->x_win, makecchar(L'\n'));
107                 getyx(win->x_win, win->x_line, win->x_col);
108                 wrefresh(win->x_win);
109                 return;
110
111         case 004:
112                 if (win == &my_win) {
113                         /* Ctrl-D clears the screen. */
114                         werase(my_win.x_win);
115                         getyx(my_win.x_win, my_win.x_line, my_win.x_col);
116                         wrefresh(my_win.x_win);
117                         werase(his_win.x_win);
118                         getyx(his_win.x_win, his_win.x_line, his_win.x_col);
119                         wrefresh(his_win.x_win);
120                 }
121                 return;
122
123         /* Erase character. */
124         case 010:       /* BS */
125         case 0177:      /* DEL */
126 cerase:
127                 wmove(win->x_win, win->x_line, max(--win->x_col, 0));
128                 getyx(win->x_win, win->x_line, win->x_col);
129                 waddch(win->x_win, ' ');
130                 wmove(win->x_win, win->x_line, win->x_col);
131                 getyx(win->x_win, win->x_line, win->x_col);
132                 wrefresh(win->x_win);
133                 return;
134
135         case 027:       /* ^W */
136 werase:
137             {
138                 /*
139                  * On word erase search backwards until we find
140                  * the beginning of a word or the beginning of
141                  * the line.
142                  */
143                 int endcol, xcol, c;
144
145                 endcol = win->x_col;
146                 xcol = endcol - 1;
147                 while (xcol >= 0) {
148                         c = readwin(win->x_win, win->x_line, xcol);
149                         if (c != ' ')
150                                 break;
151                         xcol--;
152                 }
153                 while (xcol >= 0) {
154                         c = readwin(win->x_win, win->x_line, xcol);
155                         if (c == ' ')
156                                 break;
157                         xcol--;
158                 }
159                 wmove(win->x_win, win->x_line, xcol + 1);
160                 for (int i = xcol + 1; i < endcol; i++)
161                         waddch(win->x_win, ' ');
162                 wmove(win->x_win, win->x_line, xcol + 1);
163                 getyx(win->x_win, win->x_line, win->x_col);
164                 wrefresh(win->x_win);
165                 return;
166             }
167
168         case 025:       /* ^U */
169 kill:
170                 wmove(win->x_win, win->x_line, 0);
171                 wclrtoeol(win->x_win);
172                 getyx(win->x_win, win->x_line, win->x_col);
173                 wrefresh(win->x_win);
174                 return;
175
176         case L'\f':
177                 if (win == &my_win)
178                         wrefresh(curscr);
179                 return;
180
181         case L'\7':
182                 write(STDOUT_FILENO, wc, sizeof(*wc));
183                 return;
184         }
185
186
187         if (iswprint(*wc) || *wc == L'\t')
188                 wadd_wch(win->x_win, makecchar(*wc));
189         else
190                 beep();
191
192         getyx(win->x_win, win->x_line, win->x_col);
193         wrefresh(win->x_win);
194 }
195
196 /*
197  * Read the character at the indicated position in win
198  */
199 int
200 readwin(WINDOW *win, int line, int col)
201 {
202         int oldline, oldcol;
203         int c;
204
205         getyx(win, oldline, oldcol);
206         wmove(win, line, col);
207         c = winch(win);
208         wmove(win, oldline, oldcol);
209         return (c);
210 }