Initial git import
[sxemacs] / src / ui / TTY / device-tty.c
1 /* TTY device functions.
2    Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
3    Copyright (C) 1994, 1995 Free Software Foundation, Inc.
4    Copyright (C) 1996 Ben Wing.
5
6 This file is part of SXEmacs
7
8 SXEmacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 SXEmacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
20
21
22 /* Synched up with: Not in FSF. */
23
24 /* Authors: Ben Wing and Chuck Thompson. */
25
26 #include <config.h>
27 #include "lisp.h"
28
29 #include "console-tty.h"
30 #include "ui/console-stream.h"
31 #include "events/events.h"
32 #include "ui/faces.h"
33 #include "ui/frame.h"
34 #include "lstream.h"
35 #include "ui/redisplay.h"
36 #include "sysdep.h"
37
38 #include "syssignal.h"          /* for SIGWINCH */
39
40 #include <errno.h>
41
42 Lisp_Object Qinit_pre_tty_win, Qinit_post_tty_win;
43 \f
44 static void allocate_tty_device_struct(struct device *d)
45 {
46         d->device_data = xnew_and_zero(struct tty_device);
47 }
48
49 static void tty_init_device(struct device *d, Lisp_Object props)
50 {
51         struct console *con = XCONSOLE(DEVICE_CONSOLE(d));
52         Lisp_Object terminal_type = CONSOLE_TTY_DATA(con)->terminal_type;
53
54         DEVICE_INFD(d) = CONSOLE_TTY_DATA(con)->infd;
55         DEVICE_OUTFD(d) = CONSOLE_TTY_DATA(con)->outfd;
56
57         allocate_tty_device_struct(d);
58         init_baud_rate(d);
59
60         switch (init_tty_for_redisplay(d, (char *)XSTRING_DATA(terminal_type))) {
61
62         case TTY_UNABLE_OPEN_DATABASE:
63                 suppress_early_error_handler_backtrace = 1;
64                 error("Can't access terminal information database");
65                 break;
66
67         case TTY_TYPE_UNDEFINED:
68                 suppress_early_error_handler_backtrace = 1;
69                 error
70                     ("Terminal type `%s' undefined (or can't access database?)",
71                      XSTRING_DATA(terminal_type));
72                 break;
73         case TTY_TYPE_INSUFFICIENT:
74                 suppress_early_error_handler_backtrace = 1;
75                 error("Terminal type `%s' not powerful enough to run Emacs",
76                       XSTRING_DATA(terminal_type));
77                 break;
78         case TTY_SIZE_UNSPECIFIED:
79                 suppress_early_error_handler_backtrace = 1;
80                 error("Can't determine window size of terminal");
81                 break;
82         case TTY_INIT_SUCCESS:
83                 break;
84         default:
85                 abort();
86         }
87
88         init_one_device(d);
89
90         /* Run part of the elisp side of the TTY device initialization.
91            The post-init is run in the tty_after_init_frame() method. */
92         call0(Qinit_pre_tty_win);
93 }
94
95 static void free_tty_device_struct(struct device *d)
96 {
97         struct tty_device *td = (struct tty_device *)d->device_data;
98         if (td)
99                 xfree(td);
100 }
101
102 static void tty_delete_device(struct device *d)
103 {
104         free_tty_device_struct(d);
105 }
106
107 #ifdef SIGWINCH
108
109 static SIGTYPE tty_device_size_change_signal(int signo)
110 {
111         int old_errno = errno;
112         asynch_device_change_pending++;
113 #ifdef HAVE_UNIXOID_EVENT_LOOP
114         signal_fake_event();
115 #endif
116         EMACS_REESTABLISH_SIGNAL(SIGWINCH, tty_device_size_change_signal);
117         errno = old_errno;
118         SIGRETURN;
119 }
120
121 /* frame_change_signal does nothing but set a flag that it was called.
122    When redisplay is called, it will notice that the flag is set and
123    call handle_pending_device_size_change to do the actual work. */
124 static void tty_asynch_device_change(void)
125 {
126         Lisp_Object devcons, concons;
127
128         DEVICE_LOOP_NO_BREAK(devcons, concons) {
129                 int width, height;
130                 Lisp_Object tail;
131                 struct device *d = XDEVICE(XCAR(devcons));
132                 struct console *con = XCONSOLE(DEVICE_CONSOLE(d));
133
134                 if (!DEVICE_TTY_P(d))
135                         continue;
136
137                 get_tty_device_size(d, &width, &height);
138                 if (width > 0 && height > 0
139                     && (CONSOLE_TTY_DATA(con)->width != width
140                         || CONSOLE_TTY_DATA(con)->height != height)) {
141                         CONSOLE_TTY_DATA(con)->width = width;
142                         CONSOLE_TTY_DATA(con)->height = height;
143
144                         for (tail = DEVICE_FRAME_LIST(d);
145                              !NILP(tail); tail = XCDR(tail)) {
146                                 struct frame *f = XFRAME(XCAR(tail));
147
148                                 /* We know the frame is tty because we made sure that the
149                                    device is tty. */
150                                 change_frame_size(f, height, width, 1);
151                         }
152                 }
153         }
154 }
155
156 #endif                          /* SIGWINCH */
157
158 static Lisp_Object
159 tty_device_system_metrics(struct device *d, enum device_metrics m)
160 {
161         struct console *con = XCONSOLE(DEVICE_CONSOLE(d));
162         switch ((unsigned int)m) {
163         case DM_size_device:
164                 return Fcons(make_int(CONSOLE_TTY_DATA(con)->width),
165                              make_int(CONSOLE_TTY_DATA(con)->height));
166         default:
167                 /* No such device metric property for TTY devices */
168                 return Qunbound;
169         }
170 }
171 \f
172 /************************************************************************/
173 /*                            initialization                            */
174 /************************************************************************/
175
176 void syms_of_device_tty(void)
177 {
178         defsymbol(&Qinit_pre_tty_win, "init-pre-tty-win");
179         defsymbol(&Qinit_post_tty_win, "init-post-tty-win");
180 }
181
182 void console_type_create_device_tty(void)
183 {
184         /* device methods */
185         CONSOLE_HAS_METHOD(tty, init_device);
186         CONSOLE_HAS_METHOD(tty, delete_device);
187 #ifdef SIGWINCH
188         CONSOLE_HAS_METHOD(tty, asynch_device_change);
189 #endif                          /* SIGWINCH */
190         CONSOLE_HAS_METHOD(tty, device_system_metrics);
191 }
192
193 void init_device_tty(void)
194 {
195 #ifdef SIGWINCH
196         if (initialized && !noninteractive)
197                 signal(SIGWINCH, tty_device_size_change_signal);
198 #endif                          /* SIGWINCH */
199 }