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