GTK eradication -- the build chain.
[sxemacs] / src / ui / X11 / console-x.c
1 /* Console functions for X windows.
2    Copyright (C) 1996 Ben Wing.
3
4 This file is part of SXEmacs
5
6 SXEmacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 SXEmacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
18
19
20 /* Synched up with: Not in FSF. */
21
22 /* This file Mule-ized by Ben Wing, 7-10-00. */
23
24 /* Authorship:
25
26    Ben Wing: January 1996, for 19.14.
27  */
28
29 #include <config.h>
30 #include "lisp.h"
31
32 #include "console-x.h"
33 #include "buffer.h"
34 #include "process.h"            /* canonicalize_host_name */
35 #include "ui/redisplay.h"               /* for display_arg */
36
37 DEFINE_CONSOLE_TYPE(x);
38
39 static int x_initially_selected_for_input(struct console *con)
40 {
41         return 1;
42 }
43
44 /* Parse a DISPLAY specification like "host:10.0" or ":0" */
45 static void
46 split_up_display_spec(Lisp_Object display, int *hostname_length,
47                       int *display_length, int *screen_length)
48 {
49         Bufbyte *beg = XSTRING_DATA(display);
50         Bufbyte *end = beg + XSTRING_LENGTH(display);
51         Bufbyte const *p = end;
52
53         while (p > beg) {
54                 DEC_CHARPTR(p);
55                 if (charptr_emchar(p) == ':') {
56                         *hostname_length = p - beg;
57
58                         while (p < end - 1) {
59                                 INC_CHARPTR(p);
60                                 if (charptr_emchar(p) == '.') {
61                                         *display_length =
62                                             p - beg - *hostname_length;
63                                         *screen_length = end - p;
64                                         return;
65                                 }
66                         }
67                         /* No '.' found. */
68                         *display_length =
69                             XSTRING_LENGTH(display) - *hostname_length;
70                         *screen_length = 0;
71                         return;
72                 }
73         }
74
75         /* No ':' found. */
76         *hostname_length = XSTRING_LENGTH(display);
77         *display_length = 0;
78         *screen_length = 0;
79 }
80
81 /* Remember, in all of the following functions, we have to verify
82    the integrity of our input, because the generic functions don't. */
83
84 static Lisp_Object
85 x_device_to_console_connection(Lisp_Object connection, Error_behavior errb)
86 {
87         /* Strip the trailing .# off of the connection, if it's there. */
88
89         if (NILP(connection))
90                 return Qnil;
91         else {
92                 int hostname_length, display_length, screen_length;
93
94                 if (!ERRB_EQ(errb, ERROR_ME)) {
95                         if (!STRINGP(connection))
96                                 return Qunbound;
97                 } else
98                         CHECK_STRING(connection);
99
100                 split_up_display_spec(connection, &hostname_length,
101                                       &display_length, &screen_length);
102                 connection =
103                     make_string(XSTRING_DATA(connection),
104                                 hostname_length + display_length);
105         }
106
107         return connection;
108 }
109
110 static Lisp_Object get_display_arg_connection(void)
111 {
112         const Extbyte *disp_name;
113
114         /* If the user didn't explicitly specify a display to use when
115            they called make-x-device, then we first check to see if a
116            display was specified on the command line with -display.  If
117            so, we set disp_name to it.  Otherwise we use XDisplayName to
118            see what DISPLAY is set to.  XtOpenDisplay knows how to do
119            both of these things, but we need to know the name to use. */
120         if (display_arg) {
121                 int elt;
122                 int argc;
123                 Extbyte **argv;
124                 Lisp_Object conn;
125
126                 make_argc_argv(Vx_initial_argv_list, &argc, &argv);
127
128                 disp_name = NULL;
129                 for (elt = 0; elt < argc; elt++) {
130                         if (!strcmp(argv[elt], "-d")
131                             || !strcmp(argv[elt], "-display")) {
132                                 if (elt + 1 == argc) {
133                                         suppress_early_error_handler_backtrace =
134                                             1;
135                                         type_error(Qinvalid_argument,
136                                                    "-display specified with no arg");
137                                 } else {
138                                         disp_name = argv[elt + 1];
139                                         break;
140                                 }
141                         }
142                 }
143
144                 /* assert: display_arg is only set if we found the display
145                    arg earlier so we can't fail to find it now. */
146                 assert(disp_name != NULL);
147                 conn = build_ext_string(disp_name, Qcommand_argument_encoding);
148                 free_argc_argv(argv);
149                 return conn;
150         } else
151                 return build_ext_string(XDisplayName(0),
152                                         Qx_display_name_encoding);
153 }
154
155 /* "semi-canonicalize" means convert to a nicer form for printing, but
156    don't completely canonicalize (into some likely ugly form) */
157
158 static Lisp_Object
159 x_semi_canonicalize_console_connection(Lisp_Object connection,
160                                        Error_behavior errb)
161 {
162         struct gcpro gcpro1;
163
164         GCPRO1(connection);
165
166         if (NILP(connection))
167                 connection = get_display_arg_connection();
168         else {
169                 if (!ERRB_EQ(errb, ERROR_ME)) {
170                         if (!STRINGP(connection))
171                                 RETURN_UNGCPRO(Qunbound);
172                 } else
173                         CHECK_STRING(connection);
174         }
175
176         /* Be lenient, allow people to specify a device connection instead of
177            a console connection -- e.g. "foo:0.0" instead of "foo:0".  This
178            only happens in `find-console' and `get-console'. */
179         connection = x_device_to_console_connection(connection, errb);
180
181         /* Check for a couple of standard special cases */
182         if (string_char(XSTRING(connection), 0) == ':') {
183                 connection = concat2(build_string("localhost"), connection);
184         } else {
185                 /* connection =~ s/^unix:/localhost:/; */
186                 Bufbyte *p = XSTRING_DATA(connection);
187                 const Bufbyte *end =
188                         XSTRING_DATA(connection) + XSTRING_LENGTH(connection);
189                 size_t i;
190
191                 for (i = 0; i < sizeof("unix:") - 1; i++) {
192                         if (p == end || charptr_emchar(p) != "unix:"[i])
193                                 goto ok;
194                         INC_CHARPTR(p);
195                 }
196
197                 connection = concat2(build_string("localhost:"),
198                                      make_string(p, end - p));
199         }
200 ok:
201         RETURN_UNGCPRO(connection);
202 }
203
204 static Lisp_Object
205 x_canonicalize_console_connection(Lisp_Object connection, Error_behavior errb)
206 {
207         Lisp_Object hostname = Qnil;
208         struct gcpro gcpro1, gcpro2;
209
210         GCPRO2(connection, hostname);
211
212         connection = x_semi_canonicalize_console_connection(connection, errb);
213         if (UNBOUNDP(connection))
214                 RETURN_UNGCPRO(Qunbound);
215
216         {
217                 int hostname_length, display_length, screen_length;
218
219                 split_up_display_spec(connection, &hostname_length,
220                                       &display_length, &screen_length);
221                 hostname =
222                     Fsubstring(connection, Qzero, make_int(hostname_length));
223                 hostname = canonicalize_host_name(hostname);
224                 connection = concat2(hostname,
225                                      make_string(XSTRING_DATA(connection)
226                                                  + hostname_length,
227                                                  display_length));
228         }
229
230         RETURN_UNGCPRO(connection);
231 }
232
233 static Lisp_Object
234 x_semi_canonicalize_device_connection(Lisp_Object connection,
235                                       Error_behavior errb)
236 {
237         int hostname_length, display_length, screen_length;
238         struct gcpro gcpro1;
239
240         GCPRO1(connection);
241         if (NILP(connection))
242                 connection = get_display_arg_connection();
243         else {
244                 if (!ERRB_EQ(errb, ERROR_ME)) {
245                         if (!STRINGP(connection))
246                                 RETURN_UNGCPRO(Qunbound);
247                 } else
248                         CHECK_STRING(connection);
249         }
250
251         split_up_display_spec(connection, &hostname_length, &display_length,
252                               &screen_length);
253
254         if (!screen_length)
255                 connection = concat2(connection, build_string(".0"));
256         RETURN_UNGCPRO(connection);
257 }
258
259 static Lisp_Object
260 x_canonicalize_device_connection(Lisp_Object connection, Error_behavior errb)
261 {
262         int hostname_length, display_length, screen_length;
263         Lisp_Object screen_str = Qnil;
264         struct gcpro gcpro1, gcpro2;
265
266         GCPRO2(screen_str, connection);
267         connection = x_semi_canonicalize_device_connection(connection, errb);
268         if (UNBOUNDP(connection))
269                 RETURN_UNGCPRO(Qunbound);
270
271         split_up_display_spec(connection, &hostname_length, &display_length,
272                               &screen_length);
273
274         screen_str = make_string(XSTRING_DATA(connection)
275                                  + hostname_length + display_length,
276                                  screen_length);
277         connection = x_canonicalize_console_connection(connection, errb);
278
279         RETURN_UNGCPRO(concat2(connection, screen_str));
280 }
281
282 void console_type_create_x(void)
283 {
284         INITIALIZE_CONSOLE_TYPE(x, "x", "console-x-p");
285
286         CONSOLE_HAS_METHOD(x, semi_canonicalize_console_connection);
287         CONSOLE_HAS_METHOD(x, canonicalize_console_connection);
288         CONSOLE_HAS_METHOD(x, semi_canonicalize_device_connection);
289         CONSOLE_HAS_METHOD(x, canonicalize_device_connection);
290         CONSOLE_HAS_METHOD(x, device_to_console_connection);
291         CONSOLE_HAS_METHOD(x, initially_selected_for_input);
292 }
293
294 void reinit_console_type_create_x(void)
295 {
296         REINITIALIZE_CONSOLE_TYPE(x);
297 }