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