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 }