428
|
1 /* Console functions for X windows.
|
793
|
2 Copyright (C) 1996, 2002 Ben Wing.
|
428
|
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
|
442
|
23 /* This file Mule-ized by Ben Wing, 7-10-00. */
|
|
24
|
428
|
25 /* Authorship:
|
|
26
|
|
27 Ben Wing: January 1996, for 19.14.
|
|
28 */
|
|
29
|
|
30 #include <config.h>
|
|
31 #include "lisp.h"
|
|
32
|
442
|
33 #include "buffer.h"
|
2828
|
34 #include "device.h"
|
|
35 #include "elhash.h"
|
428
|
36 #include "process.h" /* canonicalize_host_name */
|
|
37 #include "redisplay.h" /* for display_arg */
|
|
38
|
2828
|
39 #include "device-impl.h"
|
872
|
40 #include "console-x-impl.h"
|
|
41
|
428
|
42 DEFINE_CONSOLE_TYPE (x);
|
|
43
|
2828
|
44 extern void x_has_keysym (KeySym, Lisp_Object, int);
|
|
45
|
428
|
46 static int
|
2286
|
47 x_initially_selected_for_input (struct console *UNUSED (con))
|
428
|
48 {
|
|
49 return 1;
|
|
50 }
|
|
51
|
444
|
52 /* Parse a DISPLAY specification like "host:10.0" or ":0" */
|
428
|
53 static void
|
|
54 split_up_display_spec (Lisp_Object display, int *hostname_length,
|
|
55 int *display_length, int *screen_length)
|
|
56 {
|
867
|
57 Ibyte *beg = XSTRING_DATA (display);
|
|
58 Ibyte *end = beg + XSTRING_LENGTH (display);
|
|
59 Ibyte *p = end;
|
428
|
60
|
444
|
61 while (p > beg)
|
428
|
62 {
|
867
|
63 DEC_IBYTEPTR (p);
|
|
64 if (itext_ichar (p) == ':')
|
444
|
65 {
|
|
66 *hostname_length = p - beg;
|
428
|
67
|
444
|
68 while (p < end - 1)
|
|
69 {
|
867
|
70 INC_IBYTEPTR (p);
|
|
71 if (itext_ichar (p) == '.')
|
444
|
72 {
|
|
73 *display_length = p - beg - *hostname_length;
|
|
74 *screen_length = end - p;
|
|
75 return;
|
|
76 }
|
|
77 }
|
|
78 /* No '.' found. */
|
|
79 *display_length = XSTRING_LENGTH (display) - *hostname_length;
|
|
80 *screen_length = 0;
|
|
81 return;
|
|
82 }
|
428
|
83 }
|
|
84
|
444
|
85 /* No ':' found. */
|
|
86 *hostname_length = XSTRING_LENGTH (display);
|
|
87 *display_length = 0;
|
|
88 *screen_length = 0;
|
428
|
89 }
|
|
90
|
|
91 /* Remember, in all of the following functions, we have to verify
|
|
92 the integrity of our input, because the generic functions don't. */
|
|
93
|
|
94 static Lisp_Object
|
578
|
95 x_device_to_console_connection (Lisp_Object connection, Error_Behavior errb)
|
428
|
96 {
|
|
97 /* Strip the trailing .# off of the connection, if it's there. */
|
|
98
|
|
99 if (NILP (connection))
|
|
100 return Qnil;
|
|
101 else
|
|
102 {
|
|
103 int hostname_length, display_length, screen_length;
|
|
104
|
|
105 if (!ERRB_EQ (errb, ERROR_ME))
|
|
106 {
|
|
107 if (!STRINGP (connection))
|
|
108 return Qunbound;
|
|
109 }
|
|
110 else
|
|
111 CHECK_STRING (connection);
|
|
112
|
|
113 split_up_display_spec (connection, &hostname_length, &display_length,
|
|
114 &screen_length);
|
|
115 connection = make_string (XSTRING_DATA (connection),
|
|
116 hostname_length + display_length);
|
|
117 }
|
|
118
|
|
119 return connection;
|
|
120 }
|
|
121
|
|
122 static Lisp_Object
|
|
123 get_display_arg_connection (void)
|
|
124 {
|
442
|
125 const Extbyte *disp_name;
|
428
|
126
|
|
127 /* If the user didn't explicitly specify a display to use when
|
|
128 they called make-x-device, then we first check to see if a
|
|
129 display was specified on the command line with -display. If
|
|
130 so, we set disp_name to it. Otherwise we use XDisplayName to
|
|
131 see what DISPLAY is set to. XtOpenDisplay knows how to do
|
|
132 both of these things, but we need to know the name to use. */
|
|
133 if (display_arg)
|
|
134 {
|
|
135 int elt;
|
|
136 int argc;
|
442
|
137 Extbyte **argv;
|
428
|
138 Lisp_Object conn;
|
|
139
|
|
140 make_argc_argv (Vx_initial_argv_list, &argc, &argv);
|
|
141
|
|
142 disp_name = NULL;
|
|
143 for (elt = 0; elt < argc; elt++)
|
|
144 {
|
|
145 if (!strcmp (argv[elt], "-d") || !strcmp (argv[elt], "-display"))
|
|
146 {
|
|
147 if (elt + 1 == argc)
|
|
148 {
|
|
149 suppress_early_error_handler_backtrace = 1;
|
563
|
150 invalid_argument ("-display specified with no arg", Qunbound);
|
428
|
151 }
|
|
152 else
|
|
153 {
|
|
154 disp_name = argv[elt + 1];
|
|
155 break;
|
|
156 }
|
|
157 }
|
|
158 }
|
|
159
|
|
160 /* assert: display_arg is only set if we found the display
|
|
161 arg earlier so we can't fail to find it now. */
|
|
162 assert (disp_name != NULL);
|
442
|
163 conn = build_ext_string (disp_name, Qcommand_argument_encoding);
|
428
|
164 free_argc_argv (argv);
|
|
165 return conn;
|
|
166 }
|
|
167 else
|
442
|
168 return build_ext_string (XDisplayName (0), Qx_display_name_encoding);
|
428
|
169 }
|
|
170
|
|
171 /* "semi-canonicalize" means convert to a nicer form for printing, but
|
|
172 don't completely canonicalize (into some likely ugly form) */
|
|
173
|
|
174 static Lisp_Object
|
|
175 x_semi_canonicalize_console_connection (Lisp_Object connection,
|
578
|
176 Error_Behavior errb)
|
428
|
177 {
|
|
178 struct gcpro gcpro1;
|
|
179
|
|
180 GCPRO1 (connection);
|
|
181
|
|
182 if (NILP (connection))
|
|
183 connection = get_display_arg_connection ();
|
|
184 else
|
|
185 {
|
|
186 if (!ERRB_EQ (errb, ERROR_ME))
|
|
187 {
|
|
188 if (!STRINGP (connection))
|
|
189 RETURN_UNGCPRO (Qunbound);
|
|
190 }
|
|
191 else
|
|
192 CHECK_STRING (connection);
|
|
193 }
|
|
194
|
|
195
|
|
196 /* Be lenient, allow people to specify a device connection instead of
|
|
197 a console connection -- e.g. "foo:0.0" instead of "foo:0". This
|
|
198 only happens in `find-console' and `get-console'. */
|
|
199 connection = x_device_to_console_connection (connection, errb);
|
|
200
|
|
201 /* Check for a couple of standard special cases */
|
867
|
202 if (string_ichar (connection, 0) == ':')
|
428
|
203 connection = concat2 (build_string ("localhost"), connection);
|
444
|
204 else
|
|
205 {
|
|
206 /* connection =~ s/^unix:/localhost:/; */
|
867
|
207 const Ibyte *p = XSTRING_DATA (connection);
|
|
208 const Ibyte *end = XSTRING_DATA (connection) + XSTRING_LENGTH (connection);
|
647
|
209 int i;
|
444
|
210
|
647
|
211 for (i = 0; i < (int) sizeof ("unix:") - 1; i++)
|
444
|
212 {
|
867
|
213 if (p == end || itext_ichar (p) != "unix:"[i])
|
444
|
214 goto ok;
|
867
|
215 INC_IBYTEPTR (p);
|
444
|
216 }
|
|
217
|
|
218 connection = concat2 (build_string ("localhost:"),
|
|
219 make_string (p, end - p));
|
|
220 }
|
|
221 ok:
|
428
|
222
|
|
223 RETURN_UNGCPRO (connection);
|
|
224 }
|
|
225
|
|
226 static Lisp_Object
|
578
|
227 x_canonicalize_console_connection (Lisp_Object connection, Error_Behavior errb)
|
428
|
228 {
|
|
229 Lisp_Object hostname = Qnil;
|
|
230 struct gcpro gcpro1, gcpro2;
|
|
231
|
|
232 GCPRO2 (connection, hostname);
|
|
233
|
|
234 connection = x_semi_canonicalize_console_connection (connection, errb);
|
|
235 if (UNBOUNDP (connection))
|
|
236 RETURN_UNGCPRO (Qunbound);
|
|
237
|
|
238 {
|
|
239 int hostname_length, display_length, screen_length;
|
|
240
|
|
241 split_up_display_spec (connection, &hostname_length, &display_length,
|
|
242 &screen_length);
|
|
243 hostname = Fsubstring (connection, Qzero, make_int (hostname_length));
|
|
244 hostname = canonicalize_host_name (hostname);
|
|
245 connection = concat2 (hostname,
|
|
246 make_string (XSTRING_DATA (connection)
|
|
247 + hostname_length, display_length));
|
|
248 }
|
|
249
|
|
250 RETURN_UNGCPRO (connection);
|
|
251 }
|
|
252
|
|
253 static Lisp_Object
|
|
254 x_semi_canonicalize_device_connection (Lisp_Object connection,
|
578
|
255 Error_Behavior errb)
|
428
|
256 {
|
|
257 int hostname_length, display_length, screen_length;
|
|
258 struct gcpro gcpro1;
|
|
259
|
|
260 GCPRO1 (connection);
|
|
261 if (NILP (connection))
|
|
262 connection = get_display_arg_connection ();
|
|
263 else
|
|
264 {
|
|
265 if (!ERRB_EQ (errb, ERROR_ME))
|
|
266 {
|
|
267 if (!STRINGP (connection))
|
|
268 RETURN_UNGCPRO (Qunbound);
|
|
269 }
|
|
270 else
|
|
271 CHECK_STRING (connection);
|
|
272 }
|
|
273
|
|
274 split_up_display_spec (connection, &hostname_length, &display_length,
|
|
275 &screen_length);
|
|
276
|
|
277 if (!screen_length)
|
|
278 connection = concat2 (connection, build_string (".0"));
|
|
279 RETURN_UNGCPRO (connection);
|
|
280 }
|
|
281
|
|
282 static Lisp_Object
|
578
|
283 x_canonicalize_device_connection (Lisp_Object connection, Error_Behavior errb)
|
428
|
284 {
|
|
285 int hostname_length, display_length, screen_length;
|
|
286 Lisp_Object screen_str = Qnil;
|
|
287 struct gcpro gcpro1, gcpro2;
|
|
288
|
|
289 GCPRO2 (screen_str, connection);
|
|
290 connection = x_semi_canonicalize_device_connection (connection, errb);
|
|
291 if (UNBOUNDP (connection))
|
|
292 RETURN_UNGCPRO (Qunbound);
|
|
293
|
|
294 split_up_display_spec (connection, &hostname_length, &display_length,
|
|
295 &screen_length);
|
|
296
|
444
|
297 screen_str = make_string (XSTRING_DATA (connection)
|
|
298 + hostname_length + display_length, screen_length);
|
428
|
299 connection = x_canonicalize_console_connection (connection, errb);
|
|
300
|
|
301 RETURN_UNGCPRO (concat2 (connection, screen_str));
|
|
302 }
|
|
303
|
2828
|
304 /* Given a key, if it maps to a character and we weren't previously aware
|
|
305 that it could be generated on console CON, and if it's unbound in the
|
|
306 global map, bind it to self-insert-command. Return Qt if the binding was
|
|
307 done; Qnil if not. */
|
|
308
|
|
309 static Lisp_Object
|
|
310 x_perhaps_init_unseen_key_defaults (struct console *con, Lisp_Object key)
|
|
311 {
|
|
312 KeySym xkeysym;
|
|
313 const Extbyte *keysym_ext;
|
|
314 Lisp_Object key_name, previous_binding = Qnil;
|
|
315 extern Lisp_Object Qcharacter_of_keysym, Vcurrent_global_map;
|
|
316
|
|
317 /* Getting the device exactly right is not horrendously important; as long
|
|
318 as it's an X11 device it should be okay, because the global keymap (and
|
|
319 whether the key is bound) _is_ global, and any previously seen keysym
|
|
320 will already be bound, or not, in it. However, there is a corner case
|
|
321 where a symbol has been typed, and then explicitly unbound; if the next
|
|
322 event using that symbol comes in on some other frame, it'll get bound
|
|
323 again. This is not realistically an issue. */
|
|
324 struct device *d = XDEVICE(con->selected_device);
|
|
325
|
|
326 if (SYMBOLP (key))
|
|
327 {
|
|
328 key_name = symbol_name(XSYMBOL(key));
|
|
329 }
|
|
330 else
|
|
331 {
|
|
332 Ibyte buf[MAX_ICHAR_LEN + 1];
|
|
333 CHECK_CHAR(key);
|
|
334
|
|
335 buf[set_itext_ichar(buf, XCHAR(key))] = '\0';
|
2837
|
336 key_name = build_intstring (buf);
|
2828
|
337
|
|
338 /* We need to do the lookup and compare later, because we can't check
|
|
339 the Qcharacter_of_keysym property belonging to an actual character. */
|
|
340 previous_binding = Flookup_key (Vcurrent_global_map, key, Qnil);
|
|
341 }
|
|
342
|
|
343 if (!NILP(Fgethash(key, DEVICE_X_KEYSYM_MAP_HASH_TABLE (d), Qnil)))
|
|
344 {
|
|
345 return Qnil;
|
|
346 }
|
|
347
|
|
348 LISP_STRING_TO_EXTERNAL (key_name, keysym_ext, Qctext);
|
|
349 xkeysym = XStringToKeysym(keysym_ext);
|
|
350 if (NoSymbol == xkeysym)
|
|
351 {
|
3142
|
352 /* Keysym is NoSymbol; this may mean the key event passed to us came
|
|
353 from an input method, which stored the actual character intended to
|
|
354 be inserted in the key name, and didn't trouble itself to set the
|
|
355 keycode to anything useful. Thus, if the key name is a single
|
|
356 character, and the keysym is NoSymbol, give it a default binding,
|
|
357 if that is possible. */
|
|
358 Lisp_Object keychar;
|
|
359
|
|
360 if (1 != string_char_length(key_name))
|
|
361 {
|
|
362 /* Don't let them pass us more than one character. */
|
|
363 return Qnil;
|
|
364 }
|
|
365 keychar = make_char(itext_ichar(XSTRING_DATA(key_name)));
|
|
366 if (NILP (Flookup_key (Vcurrent_global_map, keychar, Qnil)))
|
|
367 {
|
|
368 Fdefine_key (Vcurrent_global_map, keychar, Qself_insert_command);
|
|
369 Fputhash (keychar, Qt, DEVICE_X_KEYSYM_MAP_HASH_TABLE (d));
|
|
370 return Qt;
|
|
371 }
|
2828
|
372 return Qnil;
|
|
373 }
|
|
374
|
|
375 x_has_keysym(xkeysym, DEVICE_X_KEYSYM_MAP_HASH_TABLE (d), 0);
|
|
376
|
|
377 if (SYMBOLP(key))
|
|
378 {
|
|
379 return NILP(Fget (key, Qcharacter_of_keysym, Qnil)) ? Qnil : Qt;
|
|
380 }
|
|
381 else
|
|
382 {
|
|
383 return EQ(previous_binding, Flookup_key(Vcurrent_global_map, key, Qnil))
|
|
384 ? Qnil : Qt;
|
|
385 }
|
|
386 }
|
|
387
|
428
|
388 void
|
|
389 console_type_create_x (void)
|
|
390 {
|
|
391 INITIALIZE_CONSOLE_TYPE (x, "x", "console-x-p");
|
|
392
|
|
393 CONSOLE_HAS_METHOD (x, semi_canonicalize_console_connection);
|
|
394 CONSOLE_HAS_METHOD (x, canonicalize_console_connection);
|
|
395 CONSOLE_HAS_METHOD (x, semi_canonicalize_device_connection);
|
|
396 CONSOLE_HAS_METHOD (x, canonicalize_device_connection);
|
|
397 CONSOLE_HAS_METHOD (x, device_to_console_connection);
|
|
398 CONSOLE_HAS_METHOD (x, initially_selected_for_input);
|
2828
|
399 CONSOLE_HAS_METHOD (x, perhaps_init_unseen_key_defaults);
|
428
|
400 }
|
|
401
|
|
402
|
|
403 void
|
|
404 reinit_console_type_create_x (void)
|
|
405 {
|
|
406 REINITIALIZE_CONSOLE_TYPE (x);
|
|
407 }
|