(syms_of_ntproc) <w32-get-true-file-attributes>: Doc fix.
[bpt/emacs.git] / src / xfns.c
CommitLineData
01f1ba30 1/* Functions for the X window system.
97f4312d 2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
8cabe764
GM
3 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
4 Free Software Foundation, Inc.
01f1ba30
JB
5
6This file is part of GNU Emacs.
7
8GNU Emacs is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
684d6f5b 10the Free Software Foundation; either version 3, or (at your option)
01f1ba30
JB
11any later version.
12
13GNU Emacs is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with GNU Emacs; see the file COPYING. If not, write to
4fc5845f
LK
20the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21Boston, MA 02110-1301, USA. */
01f1ba30 22
c389a86d 23#include <config.h>
333b20bb 24#include <stdio.h>
d62c8769 25#include <math.h>
c389a86d 26
3ecaf7e5
RS
27#ifdef HAVE_UNISTD_H
28#include <unistd.h>
29#endif
30
40e6f148 31/* This makes the fields of a Display accessible, in Xlib header files. */
333b20bb 32
40e6f148
RS
33#define XLIB_ILLEGAL_ACCESS
34
01f1ba30
JB
35#include "lisp.h"
36#include "xterm.h"
f676886a 37#include "frame.h"
01f1ba30
JB
38#include "window.h"
39#include "buffer.h"
58cad5ed 40#include "intervals.h"
01f1ba30 41#include "dispextern.h"
1f98fa48 42#include "keyboard.h"
9ac0d9e0 43#include "blockinput.h"
57bda87a 44#include <epaths.h>
0f8c4c4f 45#include "character.h"
942ea06d 46#include "charset.h"
96db09e4 47#include "coding.h"
942ea06d 48#include "fontset.h"
333b20bb
GM
49#include "systime.h"
50#include "termhooks.h"
4ae9a85e 51#include "atimer.h"
28d440ab 52#include "termchar.h"
01f1ba30 53
02ed2ea8
KH
54#ifdef USE_FONT_BACKEND
55#include "font.h"
56#endif /* USE_FONT_BACKEND */
57
01f1ba30 58#ifdef HAVE_X_WINDOWS
67ba84d1 59
67ba84d1 60#include <ctype.h>
63cec32f
GM
61#include <sys/types.h>
62#include <sys/stat.h>
01f1ba30 63
0a93081c 64#ifndef VMS
0505a740 65#if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
ef493a27
RS
66#include "bitmaps/gray.xbm"
67#else
dbc4e1c1 68#include <X11/bitmaps/gray>
ef493a27 69#endif
0a93081c
JB
70#else
71#include "[.bitmaps]gray.xbm"
72#endif
dbc4e1c1 73
488dd4c4
JD
74#ifdef USE_GTK
75#include "gtkutil.h"
76#endif
77
9ef48a9d
RS
78#ifdef USE_X_TOOLKIT
79#include <X11/Shell.h>
80
398ffa92 81#ifndef USE_MOTIF
8ab9202e
CY
82#ifdef HAVE_XAW3D
83#include <X11/Xaw3d/Paned.h>
a6ec6cfb 84#include <X11/Xaw3d/Label.h>
8ab9202e 85#else /* !HAVE_XAW3D */
9ef48a9d
RS
86#include <X11/Xaw/Paned.h>
87#include <X11/Xaw/Label.h>
8ab9202e 88#endif /* HAVE_XAW3D */
398ffa92 89#endif /* USE_MOTIF */
9ef48a9d
RS
90
91#ifdef USG
92#undef USG /* ####KLUDGE for Solaris 2.2 and up */
93#include <X11/Xos.h>
94#define USG
95#else
96#include <X11/Xos.h>
97#endif
98
99#include "widget.h"
100
101#include "../lwlib/lwlib.h"
102
333b20bb
GM
103#ifdef USE_MOTIF
104#include <Xm/Xm.h>
105#include <Xm/DialogS.h>
106#include <Xm/FileSB.h>
107#endif
108
3b882b1d
RS
109/* Do the EDITRES protocol if running X11R5
110 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
333b20bb 111
3b882b1d 112#if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
6c32dd68 113#define HACK_EDITRES
b9dc4443 114extern void _XEditResCheckMessages ();
6c32dd68
PR
115#endif /* R5 + Athena */
116
333b20bb
GM
117/* Unique id counter for widgets created by the Lucid Widget Library. */
118
6c32dd68
PR
119extern LWLIB_ID widget_id_tick;
120
e3881aa0 121#ifdef USE_LUCID
82c90203 122/* This is part of a kludge--see lwlib/xlwmenu.c. */
03e2c340 123extern XFontStruct *xlwmenu_default_font;
e3881aa0 124#endif
9ef48a9d 125
6bc20398 126extern void free_frame_menubar ();
d62c8769 127extern double atof ();
333b20bb 128
fc2cdd9a
GM
129#ifdef USE_MOTIF
130
131/* LessTif/Motif version info. */
132
133static Lisp_Object Vmotif_version_string;
134
135#endif /* USE_MOTIF */
136
9ef48a9d
RS
137#endif /* USE_X_TOOLKIT */
138
6b61353c
KH
139#ifdef USE_GTK
140
141/* GTK+ version info */
142
143static Lisp_Object Vgtk_version_string;
144
145#endif /* USE_GTK */
146
9d317b2c 147#define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
9d317b2c 148
333b20bb
GM
149/* The gray bitmap `bitmaps/gray'. This is done because xterm.c uses
150 it, and including `bitmaps/gray' more than once is a problem when
151 config.h defines `static' as an empty replacement string. */
152
153int gray_bitmap_width = gray_width;
154int gray_bitmap_height = gray_height;
62906360 155char *gray_bitmap_bits = gray_bits;
333b20bb 156
0af913d7 157/* Non-zero means we're allowed to display an hourglass cursor. */
333b20bb 158
0af913d7 159int display_hourglass_p;
333b20bb 160
255e4140
JD
161/* Non-zero means prompt with the old GTK file selection dialog. */
162
fe2b14b7 163int x_gtk_use_old_file_dialog;
255e4140 164
a8a35720
JD
165/* If non-zero, by default show hidden files in the GTK file chooser. */
166
167int x_gtk_show_hidden_files;
168
641c0105
JD
169/* If non-zero, don't show additional help text in the GTK file chooser. */
170
159f8da7 171int x_gtk_file_dialog_help_text;
641c0105 172
e0f467cb
JD
173/* If non-zero, don't collapse to tool bar when it is detached. */
174
175int x_gtk_whole_detached_tool_bar;
176
01f1ba30 177/* The background and shape of the mouse pointer, and shape when not
b9dc4443 178 over text or in the modeline. */
333b20bb 179
01f1ba30 180Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
0af913d7 181Lisp_Object Vx_hourglass_pointer_shape;
333b20bb 182
ca0ecbf5 183/* The shape when over mouse-sensitive text. */
333b20bb 184
ca0ecbf5 185Lisp_Object Vx_sensitive_text_pointer_shape;
01f1ba30 186
8fb4ec9c
GM
187/* If non-nil, the pointer shape to indicate that windows can be
188 dragged horizontally. */
189
190Lisp_Object Vx_window_horizontal_drag_shape;
191
b9dc4443 192/* Color of chars displayed in cursor box. */
333b20bb 193
01f1ba30
JB
194Lisp_Object Vx_cursor_fore_pixel;
195
b9dc4443 196/* Nonzero if using X. */
333b20bb 197
b9dc4443 198static int x_in_use;
01f1ba30 199
b9dc4443 200/* Non nil if no window manager is in use. */
333b20bb 201
01f1ba30
JB
202Lisp_Object Vx_no_window_manager;
203
942ea06d 204/* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
333b20bb 205
942ea06d
KH
206Lisp_Object Vx_pixel_size_width_font_regexp;
207
baaed68e 208Lisp_Object Qnone;
8af1d7ca 209Lisp_Object Qsuppress_icon;
01f1ba30 210Lisp_Object Qundefined_color;
ae782866 211Lisp_Object Qcompound_text, Qcancel_timer;
01f1ba30 212
7c0d3ed8 213/* In dispnew.c */
f9942c9e 214
01f1ba30
JB
215extern Lisp_Object Vwindow_system_version;
216
7c0d3ed8 217/* The below are defined in frame.c. */
333b20bb 218
f1d2ce7f 219#if GLYPH_DEBUG
eaf1eea9
GM
220int image_cache_refcount, dpyinfo_refcount;
221#endif
222
223
01f1ba30 224\f
11ae94fe 225/* Error if we are not connected to X. */
333b20bb 226
7fc9de26 227void
11ae94fe
RS
228check_x ()
229{
b9dc4443 230 if (! x_in_use)
11ae94fe
RS
231 error ("X windows are not in use or not initialized");
232}
233
1c59f5df
RS
234/* Nonzero if we can use mouse menus.
235 You should not call this unless HAVE_MENUS is defined. */
75cc8ee5
RS
236
237int
1c59f5df 238have_menus_p ()
75cc8ee5 239{
b9dc4443
RS
240 return x_in_use;
241}
242
243/* Extract a frame as a FRAME_PTR, defaulting to the selected frame
244 and checking validity for X. */
245
246FRAME_PTR
247check_x_frame (frame)
248 Lisp_Object frame;
249{
250 FRAME_PTR f;
251
252 if (NILP (frame))
0fe92f72 253 frame = selected_frame;
b7826503 254 CHECK_LIVE_FRAME (frame);
0fe92f72 255 f = XFRAME (frame);
b9dc4443 256 if (! FRAME_X_P (f))
1c59f5df 257 error ("Non-X frame used");
b9dc4443 258 return f;
75cc8ee5
RS
259}
260
7e59217d 261/* Let the user specify an X display with a Lisp object.
6ed8eeff 262 OBJECT may be nil, a frame or a terminal id.
b9dc4443
RS
263 nil stands for the selected frame--or, if that is not an X frame,
264 the first X display on the list. */
265
7c0d3ed8 266struct x_display_info *
7e59217d
KL
267check_x_display_info (object)
268 Lisp_Object object;
b9dc4443 269{
8ec8a5ec 270 struct x_display_info *dpyinfo = NULL;
177c0ea7 271
7e59217d 272 if (NILP (object))
b9dc4443 273 {
0fe92f72 274 struct frame *sf = XFRAME (selected_frame);
177c0ea7 275
0fe92f72 276 if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
8ec8a5ec 277 dpyinfo = FRAME_X_DISPLAY_INFO (sf);
b9dc4443 278 else if (x_display_list != 0)
8ec8a5ec 279 dpyinfo = x_display_list;
b9dc4443
RS
280 else
281 error ("X windows are not in use or not initialized");
282 }
7e59217d 283 else if (INTEGERP (object))
b6660415 284 {
fd0f53a9 285 struct terminal *t = get_terminal (object, 1);
b6660415 286
6ed8eeff
KL
287 if (t->type != output_x_window)
288 error ("Terminal %d is not an X display", XINT (object));
b6660415 289
6ed8eeff 290 dpyinfo = t->display_info.x;
b6660415 291 }
7e59217d
KL
292 else if (STRINGP (object))
293 dpyinfo = x_display_info_for_name (object);
b9dc4443
RS
294 else
295 {
7e59217d 296 FRAME_PTR f = check_x_frame (object);
8ec8a5ec 297 dpyinfo = FRAME_X_DISPLAY_INFO (f);
b9dc4443 298 }
8ec8a5ec
GM
299
300 return dpyinfo;
b9dc4443 301}
333b20bb 302
b9dc4443 303\f
f676886a
JB
304/* Return the Emacs frame-object corresponding to an X window.
305 It could be the frame's main window or an icon window. */
01f1ba30 306
34ca5317 307/* This function can be called during GC, so use GC_xxx type test macros. */
bcb2db92 308
f676886a 309struct frame *
2d271e2e
KH
310x_window_to_frame (dpyinfo, wdesc)
311 struct x_display_info *dpyinfo;
01f1ba30
JB
312 int wdesc;
313{
f676886a
JB
314 Lisp_Object tail, frame;
315 struct frame *f;
01f1ba30 316
10b43ac3
JD
317 if (wdesc == None) return 0;
318
8e50cc2d 319 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
01f1ba30 320 {
8e713be6 321 frame = XCAR (tail);
8e50cc2d 322 if (!FRAMEP (frame))
01f1ba30 323 continue;
f676886a 324 f = XFRAME (frame);
2d764c78 325 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
2d271e2e 326 continue;
0af913d7 327 if (f->output_data.x->hourglass_window == wdesc)
17cbbf95 328 return f;
9ef48a9d 329#ifdef USE_X_TOOLKIT
177c0ea7 330 if ((f->output_data.x->edit_widget
7556890b 331 && XtWindow (f->output_data.x->edit_widget) == wdesc)
333b20bb
GM
332 /* A tooltip frame? */
333 || (!f->output_data.x->edit_widget
334 && FRAME_X_WINDOW (f) == wdesc)
7556890b 335 || f->output_data.x->icon_desc == wdesc)
9ef48a9d
RS
336 return f;
337#else /* not USE_X_TOOLKIT */
488dd4c4
JD
338#ifdef USE_GTK
339 if (f->output_data.x->edit_widget)
340 {
6b61353c 341 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
488dd4c4
JD
342 struct x_output *x = f->output_data.x;
343 if (gwdesc != 0 && gwdesc == x->edit_widget)
344 return f;
345 }
346#endif /* USE_GTK */
fe24a618 347 if (FRAME_X_WINDOW (f) == wdesc
7556890b 348 || f->output_data.x->icon_desc == wdesc)
f676886a 349 return f;
9ef48a9d
RS
350#endif /* not USE_X_TOOLKIT */
351 }
352 return 0;
353}
354
488dd4c4 355#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
9ef48a9d
RS
356/* Like x_window_to_frame but also compares the window with the widget's
357 windows. */
358
359struct frame *
2d271e2e
KH
360x_any_window_to_frame (dpyinfo, wdesc)
361 struct x_display_info *dpyinfo;
9ef48a9d
RS
362 int wdesc;
363{
364 Lisp_Object tail, frame;
17cbbf95 365 struct frame *f, *found;
7556890b 366 struct x_output *x;
9ef48a9d 367
10b43ac3
JD
368 if (wdesc == None) return NULL;
369
17cbbf95 370 found = NULL;
8e50cc2d 371 for (tail = Vframe_list; CONSP (tail) && !found; tail = XCDR (tail))
9ef48a9d 372 {
8e713be6 373 frame = XCAR (tail);
8e50cc2d 374 if (!FRAMEP (frame))
9ef48a9d 375 continue;
177c0ea7 376
9ef48a9d 377 f = XFRAME (frame);
17cbbf95 378 if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
333b20bb 379 {
17cbbf95
GM
380 /* This frame matches if the window is any of its widgets. */
381 x = f->output_data.x;
0af913d7 382 if (x->hourglass_window == wdesc)
17cbbf95
GM
383 found = f;
384 else if (x->widget)
385 {
488dd4c4 386#ifdef USE_GTK
6b61353c 387 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
488dd4c4
JD
388 if (gwdesc != 0
389 && (gwdesc == x->widget
390 || gwdesc == x->edit_widget
391 || gwdesc == x->vbox_widget
392 || gwdesc == x->menubar_widget))
393 found = f;
394#else
177c0ea7
JB
395 if (wdesc == XtWindow (x->widget)
396 || wdesc == XtWindow (x->column_widget)
17cbbf95
GM
397 || wdesc == XtWindow (x->edit_widget))
398 found = f;
399 /* Match if the window is this frame's menubar. */
400 else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
401 found = f;
488dd4c4 402#endif
17cbbf95
GM
403 }
404 else if (FRAME_X_WINDOW (f) == wdesc)
405 /* A tooltip frame. */
406 found = f;
333b20bb 407 }
01f1ba30 408 }
177c0ea7 409
17cbbf95 410 return found;
01f1ba30 411}
5e65b9ab 412
5fbc3f3a
KH
413/* Likewise, but exclude the menu bar widget. */
414
415struct frame *
416x_non_menubar_window_to_frame (dpyinfo, wdesc)
417 struct x_display_info *dpyinfo;
418 int wdesc;
419{
420 Lisp_Object tail, frame;
421 struct frame *f;
7556890b 422 struct x_output *x;
5fbc3f3a 423
10b43ac3
JD
424 if (wdesc == None) return 0;
425
8e50cc2d 426 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
5fbc3f3a 427 {
8e713be6 428 frame = XCAR (tail);
8e50cc2d 429 if (!FRAMEP (frame))
5fbc3f3a
KH
430 continue;
431 f = XFRAME (frame);
2d764c78 432 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
5fbc3f3a 433 continue;
7556890b 434 x = f->output_data.x;
5fbc3f3a 435 /* This frame matches if the window is any of its widgets. */
0af913d7 436 if (x->hourglass_window == wdesc)
17cbbf95
GM
437 return f;
438 else if (x->widget)
333b20bb 439 {
488dd4c4 440#ifdef USE_GTK
6b61353c 441 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
488dd4c4
JD
442 if (gwdesc != 0
443 && (gwdesc == x->widget
444 || gwdesc == x->edit_widget
445 || gwdesc == x->vbox_widget))
446 return f;
447#else
177c0ea7
JB
448 if (wdesc == XtWindow (x->widget)
449 || wdesc == XtWindow (x->column_widget)
333b20bb
GM
450 || wdesc == XtWindow (x->edit_widget))
451 return f;
488dd4c4 452#endif
333b20bb
GM
453 }
454 else if (FRAME_X_WINDOW (f) == wdesc)
455 /* A tooltip frame. */
5fbc3f3a
KH
456 return f;
457 }
458 return 0;
459}
460
fd3a3022
RS
461/* Likewise, but consider only the menu bar widget. */
462
463struct frame *
464x_menubar_window_to_frame (dpyinfo, wdesc)
465 struct x_display_info *dpyinfo;
466 int wdesc;
467{
468 Lisp_Object tail, frame;
469 struct frame *f;
7556890b 470 struct x_output *x;
fd3a3022 471
10b43ac3
JD
472 if (wdesc == None) return 0;
473
8e50cc2d 474 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
fd3a3022 475 {
8e713be6 476 frame = XCAR (tail);
8e50cc2d 477 if (!FRAMEP (frame))
fd3a3022
RS
478 continue;
479 f = XFRAME (frame);
2d764c78 480 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
fd3a3022 481 continue;
7556890b 482 x = f->output_data.x;
fd3a3022 483 /* Match if the window is this frame's menubar. */
488dd4c4
JD
484#ifdef USE_GTK
485 if (x->menubar_widget)
486 {
6b61353c 487 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
488dd4c4 488 int found = 0;
177c0ea7 489
488dd4c4
JD
490 BLOCK_INPUT;
491 if (gwdesc != 0
492 && (gwdesc == x->menubar_widget
493 || gtk_widget_get_parent (gwdesc) == x->menubar_widget))
494 found = 1;
495 UNBLOCK_INPUT;
496 if (found) return f;
497 }
498#else
333b20bb
GM
499 if (x->menubar_widget
500 && lw_window_is_in_menubar (wdesc, x->menubar_widget))
fd3a3022 501 return f;
488dd4c4 502#endif
fd3a3022
RS
503 }
504 return 0;
505}
506
5e65b9ab
RS
507/* Return the frame whose principal (outermost) window is WDESC.
508 If WDESC is some other (smaller) window, we return 0. */
509
510struct frame *
2d271e2e
KH
511x_top_window_to_frame (dpyinfo, wdesc)
512 struct x_display_info *dpyinfo;
5e65b9ab
RS
513 int wdesc;
514{
515 Lisp_Object tail, frame;
516 struct frame *f;
7556890b 517 struct x_output *x;
5e65b9ab 518
10b43ac3
JD
519 if (wdesc == None) return 0;
520
8e50cc2d 521 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
5e65b9ab 522 {
8e713be6 523 frame = XCAR (tail);
8e50cc2d 524 if (!FRAMEP (frame))
5e65b9ab
RS
525 continue;
526 f = XFRAME (frame);
2d764c78 527 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
2d271e2e 528 continue;
7556890b 529 x = f->output_data.x;
333b20bb
GM
530
531 if (x->widget)
532 {
533 /* This frame matches if the window is its topmost widget. */
488dd4c4 534#ifdef USE_GTK
6b61353c 535 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
488dd4c4
JD
536 if (gwdesc == x->widget)
537 return f;
538#else
333b20bb
GM
539 if (wdesc == XtWindow (x->widget))
540 return f;
7a994728
KH
541#if 0 /* I don't know why it did this,
542 but it seems logically wrong,
543 and it causes trouble for MapNotify events. */
333b20bb 544 /* Match if the window is this frame's menubar. */
177c0ea7 545 if (x->menubar_widget
333b20bb
GM
546 && wdesc == XtWindow (x->menubar_widget))
547 return f;
488dd4c4 548#endif
7a994728 549#endif
333b20bb
GM
550 }
551 else if (FRAME_X_WINDOW (f) == wdesc)
552 /* Tooltip frame. */
553 return f;
5e65b9ab
RS
554 }
555 return 0;
556}
488dd4c4 557#endif /* USE_X_TOOLKIT || USE_GTK */
01f1ba30 558
01f1ba30 559\f
203c1d73 560
02ed2ea8
KH
561static void x_default_font_parameter P_ ((struct frame *, Lisp_Object));
562
eaf1eea9
GM
563static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
564static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object));
7c0d3ed8 565
d62c8769 566void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
ea0a1f53 567static void x_set_wait_for_wm P_ ((struct frame *, Lisp_Object, Lisp_Object));
d62c8769
GM
568void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
569void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
570void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
571void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
572void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
573void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
574void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
d62c8769 575void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
d62c8769 576void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
d62c8769 577void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
9ea173e8 578void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
333b20bb
GM
579void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
580 Lisp_Object));
581void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
582 Lisp_Object));
583static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
584 Lisp_Object,
585 Lisp_Object,
586 char *, char *,
587 int));
01f1ba30 588\f
49d41073 589
08a90d6a 590/* Store the screen positions of frame F into XPTR and YPTR.
e9445337
RS
591 These are the positions of the containing window manager window,
592 not Emacs's own window. */
593
594void
595x_real_positions (f, xptr, yptr)
596 FRAME_PTR f;
597 int *xptr, *yptr;
598{
49d41073
EZ
599 int win_x, win_y, outer_x, outer_y;
600 int real_x = 0, real_y = 0;
601 int had_errors = 0;
602 Window win = f->output_data.x->parent_desc;
e9445337 603
49d41073
EZ
604 BLOCK_INPUT;
605
9ba8e10d 606 x_catch_errors (FRAME_X_DISPLAY (f));
043835a3 607
49d41073
EZ
608 if (win == FRAME_X_DISPLAY_INFO (f)->root_window)
609 win = FRAME_OUTER_WINDOW (f);
610
611 /* This loop traverses up the containment tree until we hit the root
612 window. Window managers may intersect many windows between our window
613 and the root window. The window we find just before the root window
614 should be the outer WM window. */
615 for (;;)
e9445337 616 {
49d41073
EZ
617 Window wm_window, rootw;
618 Window *tmp_children;
619 unsigned int tmp_nchildren;
e7161ad9 620 int success;
ca7bac79 621
e7161ad9
RS
622 success = XQueryTree (FRAME_X_DISPLAY (f), win, &rootw,
623 &wm_window, &tmp_children, &tmp_nchildren);
08a90d6a 624
49d41073 625 had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
08a90d6a 626
e7161ad9
RS
627 /* Don't free tmp_children if XQueryTree failed. */
628 if (! success)
629 break;
630
631 XFree ((char *) tmp_children);
632
49d41073
EZ
633 if (wm_window == rootw || had_errors)
634 break;
08a90d6a 635
49d41073
EZ
636 win = wm_window;
637 }
177c0ea7 638
49d41073
EZ
639 if (! had_errors)
640 {
47c53789 641 unsigned int ign;
49d41073 642 Window child, rootw;
177c0ea7 643
49d41073
EZ
644 /* Get the real coordinates for the WM window upper left corner */
645 XGetGeometry (FRAME_X_DISPLAY (f), win,
646 &rootw, &real_x, &real_y, &ign, &ign, &ign, &ign);
647
648 /* Translate real coordinates to coordinates relative to our
649 window. For our window, the upper left corner is 0, 0.
650 Since the upper left corner of the WM window is outside
651 our window, win_x and win_y will be negative:
652
653 ------------------ ---> x
654 | title |
655 | ----------------- v y
656 | | our window
657 */
8a07bba0 658 XTranslateCoordinates (FRAME_X_DISPLAY (f),
e9445337 659
8a07bba0 660 /* From-window, to-window. */
8a07bba0 661 FRAME_X_DISPLAY_INFO (f)->root_window,
49d41073 662 FRAME_X_WINDOW (f),
e9445337 663
8a07bba0 664 /* From-position, to-position. */
49d41073 665 real_x, real_y, &win_x, &win_y,
08a90d6a 666
8a07bba0
RS
667 /* Child of win. */
668 &child);
e9445337 669
49d41073 670 if (FRAME_X_WINDOW (f) == FRAME_OUTER_WINDOW (f))
845e9d85 671 {
49d41073
EZ
672 outer_x = win_x;
673 outer_y = win_y;
845e9d85 674 }
49d41073
EZ
675 else
676 {
677 XTranslateCoordinates (FRAME_X_DISPLAY (f),
ca7bac79 678
49d41073
EZ
679 /* From-window, to-window. */
680 FRAME_X_DISPLAY_INFO (f)->root_window,
681 FRAME_OUTER_WINDOW (f),
177c0ea7 682
49d41073
EZ
683 /* From-position, to-position. */
684 real_x, real_y, &outer_x, &outer_y,
177c0ea7 685
49d41073
EZ
686 /* Child of win. */
687 &child);
be786000 688 }
08a90d6a 689
49d41073
EZ
690 had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
691 }
177c0ea7 692
4545fa20 693 x_uncatch_errors ();
177c0ea7 694
49d41073
EZ
695 UNBLOCK_INPUT;
696
697 if (had_errors) return;
177c0ea7 698
be786000
KS
699 f->x_pixels_diff = -win_x;
700 f->y_pixels_diff = -win_y;
701
702 FRAME_X_OUTPUT (f)->x_pixels_outer_diff = -outer_x;
703 FRAME_X_OUTPUT (f)->y_pixels_outer_diff = -outer_y;
49d41073
EZ
704
705 *xptr = real_x;
706 *yptr = real_y;
e9445337
RS
707}
708
01f1ba30 709\f
82978295 710
d62c8769
GM
711
712/* Gamma-correct COLOR on frame F. */
713
714void
715gamma_correct (f, color)
716 struct frame *f;
717 XColor *color;
718{
719 if (f->gamma)
720 {
721 color->red = pow (color->red / 65535.0, f->gamma) * 65535.0 + 0.5;
722 color->green = pow (color->green / 65535.0, f->gamma) * 65535.0 + 0.5;
723 color->blue = pow (color->blue / 65535.0, f->gamma) * 65535.0 + 0.5;
724 }
725}
726
727
7b746c38
GM
728/* Decide if color named COLOR_NAME is valid for use on frame F. If
729 so, return the RGB values in COLOR. If ALLOC_P is non-zero,
730 allocate the color. Value is zero if COLOR_NAME is invalid, or
731 no color could be allocated. */
e12d55b2 732
01f1ba30 733int
7b746c38
GM
734x_defined_color (f, color_name, color, alloc_p)
735 struct frame *f;
736 char *color_name;
737 XColor *color;
738 int alloc_p;
01f1ba30 739{
7b746c38
GM
740 int success_p;
741 Display *dpy = FRAME_X_DISPLAY (f);
742 Colormap cmap = FRAME_X_COLORMAP (f);
01f1ba30
JB
743
744 BLOCK_INPUT;
7b746c38
GM
745 success_p = XParseColor (dpy, cmap, color_name, color);
746 if (success_p && alloc_p)
747 success_p = x_alloc_nearest_color (f, cmap, color);
01f1ba30
JB
748 UNBLOCK_INPUT;
749
7b746c38 750 return success_p;
01f1ba30
JB
751}
752
9b2956e2
GM
753
754/* Return the pixel color value for color COLOR_NAME on frame F. If F
755 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
756 Signal an error if color can't be allocated. */
01f1ba30
JB
757
758int
9b2956e2 759x_decode_color (f, color_name, mono_color)
b9dc4443 760 FRAME_PTR f;
9b2956e2
GM
761 Lisp_Object color_name;
762 int mono_color;
01f1ba30 763{
b9dc4443 764 XColor cdef;
01f1ba30 765
b7826503 766 CHECK_STRING (color_name);
01f1ba30 767
9b2956e2
GM
768#if 0 /* Don't do this. It's wrong when we're not using the default
769 colormap, it makes freeing difficult, and it's probably not
770 an important optimization. */
d5db4077 771 if (strcmp (SDATA (color_name), "black") == 0)
b9dc4443 772 return BLACK_PIX_DEFAULT (f);
d5db4077 773 else if (strcmp (SDATA (color_name), "white") == 0)
b9dc4443 774 return WHITE_PIX_DEFAULT (f);
9b2956e2 775#endif
01f1ba30 776
9b2956e2 777 /* Return MONO_COLOR for monochrome frames. */
b9dc4443 778 if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
9b2956e2 779 return mono_color;
01f1ba30 780
2d764c78 781 /* x_defined_color is responsible for coping with failures
95626e11 782 by looking for a near-miss. */
d5db4077 783 if (x_defined_color (f, SDATA (color_name), &cdef, 1))
95626e11
RS
784 return cdef.pixel;
785
93217cef 786 signal_error ("Undefined color", color_name);
01f1ba30 787}
9b2956e2
GM
788
789
01f1ba30 790\f
ea0a1f53
GM
791/* Change the `wait-for-wm' frame parameter of frame F. OLD_VALUE is
792 the previous value of that parameter, NEW_VALUE is the new value.
793 See also the comment of wait_for_wm in struct x_output. */
794
795static void
796x_set_wait_for_wm (f, new_value, old_value)
797 struct frame *f;
798 Lisp_Object new_value, old_value;
799{
800 f->output_data.x->wait_for_wm = !NILP (new_value);
801}
802
993d0721
JB
803#ifdef USE_GTK
804
465aa50a
JD
805/* Set icon from FILE for frame F. By using GTK functions the icon
806 may be any format that GdkPixbuf knows about, i.e. not just bitmaps. */
993d0721
JB
807
808int
6b61353c 809xg_set_icon (f, file)
465aa50a 810 FRAME_PTR f;
993d0721
JB
811 Lisp_Object file;
812{
465aa50a
JD
813 int result = 0;
814 Lisp_Object found;
993d0721 815
465aa50a
JD
816 found = x_find_image_file (file);
817
818 if (! NILP (found))
819 {
820 GdkPixbuf *pixbuf;
821 GError *err = NULL;
47c53789 822 char *filename = (char *) SDATA (found);
465aa50a
JD
823 BLOCK_INPUT;
824
825 pixbuf = gdk_pixbuf_new_from_file (filename, &err);
826
827 if (pixbuf)
828 {
829 gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
830 pixbuf);
831 g_object_unref (pixbuf);
832
833 result = 1;
834 }
835 else
836 g_error_free (err);
837
838 UNBLOCK_INPUT;
839 }
840
465aa50a 841 return result;
993d0721 842}
9f7b984b
CY
843
844int
845xg_set_icon_from_xpm_data (f, data)
846 FRAME_PTR f;
847 char **data;
848{
849 int result = 0;
47c53789 850 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **) data);
9f7b984b
CY
851
852 if (!pixbuf)
47c53789 853 return 0;
9f7b984b 854
47c53789 855 gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf);
9f7b984b
CY
856 g_object_unref (pixbuf);
857 return 1;
858}
993d0721
JB
859#endif /* USE_GTK */
860
ea0a1f53 861
f676886a 862/* Functions called only from `x_set_frame_param'
01f1ba30
JB
863 to set individual parameters.
864
fe24a618 865 If FRAME_X_WINDOW (f) is 0,
f676886a 866 the frame is being created and its X-window does not exist yet.
01f1ba30
JB
867 In that case, just record the parameter's new value
868 in the standard place; do not attempt to change the window. */
869
870void
f676886a
JB
871x_set_foreground_color (f, arg, oldval)
872 struct frame *f;
01f1ba30
JB
873 Lisp_Object arg, oldval;
874{
09393d07
GM
875 struct x_output *x = f->output_data.x;
876 unsigned long fg, old_fg;
a76206dc 877
09393d07 878 fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
ce593f6e
KL
879 old_fg = FRAME_FOREGROUND_PIXEL (f);
880 FRAME_FOREGROUND_PIXEL (f) = fg;
a76206dc 881
fe24a618 882 if (FRAME_X_WINDOW (f) != 0)
01f1ba30 883 {
09393d07 884 Display *dpy = FRAME_X_DISPLAY (f);
177c0ea7 885
09393d07
GM
886 BLOCK_INPUT;
887 XSetForeground (dpy, x->normal_gc, fg);
888 XSetBackground (dpy, x->reverse_gc, fg);
36d42089 889
09393d07
GM
890 if (x->cursor_pixel == old_fg)
891 {
892 unload_color (f, x->cursor_pixel);
893 x->cursor_pixel = x_copy_color (f, fg);
894 XSetBackground (dpy, x->cursor_gc, x->cursor_pixel);
895 }
177c0ea7 896
01f1ba30 897 UNBLOCK_INPUT;
177c0ea7 898
05c8abbe 899 update_face_from_frame_parameter (f, Qforeground_color, arg);
177c0ea7 900
179956b9 901 if (FRAME_VISIBLE_P (f))
f676886a 902 redraw_frame (f);
01f1ba30 903 }
177c0ea7 904
09393d07 905 unload_color (f, old_fg);
01f1ba30
JB
906}
907
908void
f676886a
JB
909x_set_background_color (f, arg, oldval)
910 struct frame *f;
01f1ba30
JB
911 Lisp_Object arg, oldval;
912{
09393d07
GM
913 struct x_output *x = f->output_data.x;
914 unsigned long bg;
01f1ba30 915
09393d07 916 bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
ce593f6e
KL
917 unload_color (f, FRAME_BACKGROUND_PIXEL (f));
918 FRAME_BACKGROUND_PIXEL (f) = bg;
a76206dc 919
fe24a618 920 if (FRAME_X_WINDOW (f) != 0)
01f1ba30 921 {
09393d07 922 Display *dpy = FRAME_X_DISPLAY (f);
177c0ea7 923
09393d07
GM
924 BLOCK_INPUT;
925 XSetBackground (dpy, x->normal_gc, bg);
926 XSetForeground (dpy, x->reverse_gc, bg);
927 XSetWindowBackground (dpy, FRAME_X_WINDOW (f), bg);
928 XSetForeground (dpy, x->cursor_gc, bg);
929
488dd4c4
JD
930#ifdef USE_GTK
931 xg_set_background_color (f, bg);
932#endif
933
f76e0368
GM
934#ifndef USE_TOOLKIT_SCROLL_BARS /* Turns out to be annoying with
935 toolkit scroll bars. */
936 {
937 Lisp_Object bar;
938 for (bar = FRAME_SCROLL_BARS (f);
939 !NILP (bar);
940 bar = XSCROLL_BAR (bar)->next)
941 {
056ce195 942 Window window = XSCROLL_BAR (bar)->x_window;
f76e0368
GM
943 XSetWindowBackground (dpy, window, bg);
944 }
945 }
946#endif /* USE_TOOLKIT_SCROLL_BARS */
01f1ba30 947
09393d07 948 UNBLOCK_INPUT;
05c8abbe 949 update_face_from_frame_parameter (f, Qbackground_color, arg);
ea96210c 950
179956b9 951 if (FRAME_VISIBLE_P (f))
f676886a 952 redraw_frame (f);
01f1ba30
JB
953 }
954}
955
956void
f676886a
JB
957x_set_mouse_color (f, arg, oldval)
958 struct frame *f;
01f1ba30
JB
959 Lisp_Object arg, oldval;
960{
09393d07
GM
961 struct x_output *x = f->output_data.x;
962 Display *dpy = FRAME_X_DISPLAY (f);
3d970f28 963 Cursor cursor, nontext_cursor, mode_cursor, hand_cursor;
0af913d7 964 Cursor hourglass_cursor, horizontal_drag_cursor;
51a1d2d8 965 unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
ce593f6e 966 unsigned long mask_color = FRAME_BACKGROUND_PIXEL (f);
a76206dc 967
51a1d2d8 968 /* Don't let pointers be invisible. */
09393d07 969 if (mask_color == pixel)
bcf26b38
GM
970 {
971 x_free_colors (f, &pixel, 1);
ce593f6e 972 pixel = x_copy_color (f, FRAME_FOREGROUND_PIXEL (f));
bcf26b38 973 }
a76206dc 974
09393d07
GM
975 unload_color (f, x->mouse_pixel);
976 x->mouse_pixel = pixel;
01f1ba30
JB
977
978 BLOCK_INPUT;
fe24a618 979
eb8c3be9 980 /* It's not okay to crash if the user selects a screwy cursor. */
9ba8e10d 981 x_catch_errors (dpy);
fe24a618 982
09393d07 983 if (!NILP (Vx_pointer_shape))
01f1ba30 984 {
b7826503 985 CHECK_NUMBER (Vx_pointer_shape);
09393d07 986 cursor = XCreateFontCursor (dpy, XINT (Vx_pointer_shape));
01f1ba30
JB
987 }
988 else
09393d07
GM
989 cursor = XCreateFontCursor (dpy, XC_xterm);
990 x_check_errors (dpy, "bad text pointer cursor: %s");
01f1ba30 991
09393d07 992 if (!NILP (Vx_nontext_pointer_shape))
01f1ba30 993 {
b7826503 994 CHECK_NUMBER (Vx_nontext_pointer_shape);
09393d07
GM
995 nontext_cursor
996 = XCreateFontCursor (dpy, XINT (Vx_nontext_pointer_shape));
01f1ba30
JB
997 }
998 else
09393d07
GM
999 nontext_cursor = XCreateFontCursor (dpy, XC_left_ptr);
1000 x_check_errors (dpy, "bad nontext pointer cursor: %s");
01f1ba30 1001
09393d07 1002 if (!NILP (Vx_hourglass_pointer_shape))
333b20bb 1003 {
b7826503 1004 CHECK_NUMBER (Vx_hourglass_pointer_shape);
09393d07
GM
1005 hourglass_cursor
1006 = XCreateFontCursor (dpy, XINT (Vx_hourglass_pointer_shape));
333b20bb
GM
1007 }
1008 else
09393d07
GM
1009 hourglass_cursor = XCreateFontCursor (dpy, XC_watch);
1010 x_check_errors (dpy, "bad hourglass pointer cursor: %s");
177c0ea7 1011
09393d07 1012 if (!NILP (Vx_mode_pointer_shape))
01f1ba30 1013 {
b7826503 1014 CHECK_NUMBER (Vx_mode_pointer_shape);
09393d07 1015 mode_cursor = XCreateFontCursor (dpy, XINT (Vx_mode_pointer_shape));
01f1ba30
JB
1016 }
1017 else
09393d07
GM
1018 mode_cursor = XCreateFontCursor (dpy, XC_xterm);
1019 x_check_errors (dpy, "bad modeline pointer cursor: %s");
95f80c78 1020
09393d07 1021 if (!NILP (Vx_sensitive_text_pointer_shape))
95f80c78 1022 {
b7826503 1023 CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
3d970f28 1024 hand_cursor
09393d07 1025 = XCreateFontCursor (dpy, XINT (Vx_sensitive_text_pointer_shape));
95f80c78
FP
1026 }
1027 else
3d970f28 1028 hand_cursor = XCreateFontCursor (dpy, XC_hand2);
01f1ba30 1029
8fb4ec9c
GM
1030 if (!NILP (Vx_window_horizontal_drag_shape))
1031 {
b7826503 1032 CHECK_NUMBER (Vx_window_horizontal_drag_shape);
8fb4ec9c 1033 horizontal_drag_cursor
09393d07 1034 = XCreateFontCursor (dpy, XINT (Vx_window_horizontal_drag_shape));
8fb4ec9c
GM
1035 }
1036 else
1037 horizontal_drag_cursor
09393d07 1038 = XCreateFontCursor (dpy, XC_sb_h_double_arrow);
8fb4ec9c 1039
fe24a618 1040 /* Check and report errors with the above calls. */
09393d07 1041 x_check_errors (dpy, "can't set cursor shape: %s");
4545fa20 1042 x_uncatch_errors ();
fe24a618 1043
01f1ba30
JB
1044 {
1045 XColor fore_color, back_color;
1046
09393d07 1047 fore_color.pixel = x->mouse_pixel;
a31fedb7 1048 x_query_color (f, &fore_color);
01f1ba30 1049 back_color.pixel = mask_color;
a31fedb7 1050 x_query_color (f, &back_color);
177c0ea7 1051
09393d07
GM
1052 XRecolorCursor (dpy, cursor, &fore_color, &back_color);
1053 XRecolorCursor (dpy, nontext_cursor, &fore_color, &back_color);
1054 XRecolorCursor (dpy, mode_cursor, &fore_color, &back_color);
3d970f28 1055 XRecolorCursor (dpy, hand_cursor, &fore_color, &back_color);
09393d07
GM
1056 XRecolorCursor (dpy, hourglass_cursor, &fore_color, &back_color);
1057 XRecolorCursor (dpy, horizontal_drag_cursor, &fore_color, &back_color);
01f1ba30 1058 }
01f1ba30 1059
fe24a618 1060 if (FRAME_X_WINDOW (f) != 0)
09393d07
GM
1061 XDefineCursor (dpy, FRAME_X_WINDOW (f), cursor);
1062
1063 if (cursor != x->text_cursor
1064 && x->text_cursor != 0)
1065 XFreeCursor (dpy, x->text_cursor);
1066 x->text_cursor = cursor;
1067
1068 if (nontext_cursor != x->nontext_cursor
1069 && x->nontext_cursor != 0)
1070 XFreeCursor (dpy, x->nontext_cursor);
1071 x->nontext_cursor = nontext_cursor;
1072
1073 if (hourglass_cursor != x->hourglass_cursor
1074 && x->hourglass_cursor != 0)
1075 XFreeCursor (dpy, x->hourglass_cursor);
1076 x->hourglass_cursor = hourglass_cursor;
1077
1078 if (mode_cursor != x->modeline_cursor
1079 && x->modeline_cursor != 0)
1080 XFreeCursor (dpy, f->output_data.x->modeline_cursor);
1081 x->modeline_cursor = mode_cursor;
177c0ea7 1082
3d970f28
KS
1083 if (hand_cursor != x->hand_cursor
1084 && x->hand_cursor != 0)
1085 XFreeCursor (dpy, x->hand_cursor);
1086 x->hand_cursor = hand_cursor;
01f1ba30 1087
09393d07
GM
1088 if (horizontal_drag_cursor != x->horizontal_drag_cursor
1089 && x->horizontal_drag_cursor != 0)
1090 XFreeCursor (dpy, x->horizontal_drag_cursor);
1091 x->horizontal_drag_cursor = horizontal_drag_cursor;
8fb4ec9c 1092
09393d07 1093 XFlush (dpy);
01f1ba30 1094 UNBLOCK_INPUT;
05c8abbe
GM
1095
1096 update_face_from_frame_parameter (f, Qmouse_color, arg);
01f1ba30
JB
1097}
1098
1099void
f676886a
JB
1100x_set_cursor_color (f, arg, oldval)
1101 struct frame *f;
01f1ba30
JB
1102 Lisp_Object arg, oldval;
1103{
a76206dc 1104 unsigned long fore_pixel, pixel;
10168ebb 1105 int fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
09393d07 1106 struct x_output *x = f->output_data.x;
01f1ba30 1107
10168ebb
GM
1108 if (!NILP (Vx_cursor_fore_pixel))
1109 {
1110 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1111 WHITE_PIX_DEFAULT (f));
1112 fore_pixel_allocated_p = 1;
1113 }
01f1ba30 1114 else
ce593f6e 1115 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
177c0ea7 1116
a76206dc 1117 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
10168ebb 1118 pixel_allocated_p = 1;
a76206dc 1119
f9942c9e 1120 /* Make sure that the cursor color differs from the background color. */
ce593f6e 1121 if (pixel == FRAME_BACKGROUND_PIXEL (f))
01f1ba30 1122 {
10168ebb
GM
1123 if (pixel_allocated_p)
1124 {
1125 x_free_colors (f, &pixel, 1);
1126 pixel_allocated_p = 0;
1127 }
177c0ea7 1128
09393d07 1129 pixel = x->mouse_pixel;
a76206dc 1130 if (pixel == fore_pixel)
10168ebb
GM
1131 {
1132 if (fore_pixel_allocated_p)
1133 {
1134 x_free_colors (f, &fore_pixel, 1);
1135 fore_pixel_allocated_p = 0;
1136 }
ce593f6e 1137 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
10168ebb 1138 }
01f1ba30 1139 }
a76206dc 1140
09393d07 1141 unload_color (f, x->cursor_foreground_pixel);
10168ebb
GM
1142 if (!fore_pixel_allocated_p)
1143 fore_pixel = x_copy_color (f, fore_pixel);
09393d07 1144 x->cursor_foreground_pixel = fore_pixel;
01f1ba30 1145
09393d07 1146 unload_color (f, x->cursor_pixel);
10168ebb
GM
1147 if (!pixel_allocated_p)
1148 pixel = x_copy_color (f, pixel);
09393d07 1149 x->cursor_pixel = pixel;
a76206dc 1150
fe24a618 1151 if (FRAME_X_WINDOW (f) != 0)
01f1ba30 1152 {
01f1ba30 1153 BLOCK_INPUT;
09393d07
GM
1154 XSetBackground (FRAME_X_DISPLAY (f), x->cursor_gc, x->cursor_pixel);
1155 XSetForeground (FRAME_X_DISPLAY (f), x->cursor_gc, fore_pixel);
01f1ba30 1156 UNBLOCK_INPUT;
01f1ba30 1157
179956b9 1158 if (FRAME_VISIBLE_P (f))
01f1ba30 1159 {
cedadcfa
RS
1160 x_update_cursor (f, 0);
1161 x_update_cursor (f, 1);
01f1ba30
JB
1162 }
1163 }
05c8abbe
GM
1164
1165 update_face_from_frame_parameter (f, Qcursor_color, arg);
01f1ba30 1166}
943b580d 1167\f
f676886a 1168/* Set the border-color of frame F to pixel value PIX.
01f1ba30 1169 Note that this does not fully take effect if done before
f676886a 1170 F has an x-window. */
01f1ba30 1171
968b1234 1172void
f676886a
JB
1173x_set_border_pixel (f, pix)
1174 struct frame *f;
01f1ba30
JB
1175 int pix;
1176{
a76206dc 1177 unload_color (f, f->output_data.x->border_pixel);
7556890b 1178 f->output_data.x->border_pixel = pix;
01f1ba30 1179
be786000 1180 if (FRAME_X_WINDOW (f) != 0 && f->border_width > 0)
01f1ba30 1181 {
01f1ba30 1182 BLOCK_INPUT;
b9dc4443 1183 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
270958e8 1184 (unsigned long)pix);
01f1ba30
JB
1185 UNBLOCK_INPUT;
1186
179956b9 1187 if (FRAME_VISIBLE_P (f))
f676886a 1188 redraw_frame (f);
01f1ba30
JB
1189 }
1190}
1191
7c0d3ed8
KS
1192/* Set the border-color of frame F to value described by ARG.
1193 ARG can be a string naming a color.
1194 The border-color is used for the border that is drawn by the X server.
1195 Note that this does not fully take effect if done before
1196 F has an x-window; it must be redone when the window is created.
1197
1198 Note: this is done in two routines because of the way X10 works.
1199
1200 Note: under X11, this is normally the province of the window manager,
1201 and so emacs' border colors may be overridden. */
1202
1203void
1204x_set_border_color (f, arg, oldval)
1205 struct frame *f;
1206 Lisp_Object arg, oldval;
1207{
1208 int pix;
1209
1210 CHECK_STRING (arg);
1211 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1212 x_set_border_pixel (f, pix);
1213 update_face_from_frame_parameter (f, Qborder_color, arg);
1214}
0d1469d6 1215
0d1469d6
GM
1216
1217void
1218x_set_cursor_type (f, arg, oldval)
1219 FRAME_PTR f;
1220 Lisp_Object arg, oldval;
1221{
33b2311e 1222 set_frame_cursor_types (f, arg);
dbc4e1c1 1223
75691005
RS
1224 /* Make sure the cursor gets redrawn. */
1225 cursor_type_changed = 1;
dbc4e1c1 1226}
943b580d 1227\f
01f1ba30 1228void
f676886a
JB
1229x_set_icon_type (f, arg, oldval)
1230 struct frame *f;
01f1ba30
JB
1231 Lisp_Object arg, oldval;
1232{
01f1ba30
JB
1233 int result;
1234
203c1d73
RS
1235 if (STRINGP (arg))
1236 {
1237 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1238 return;
1239 }
1240 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
01f1ba30
JB
1241 return;
1242
1243 BLOCK_INPUT;
265a9e55 1244 if (NILP (arg))
80534dd6 1245 result = x_text_icon (f,
d5db4077 1246 (char *) SDATA ((!NILP (f->icon_name)
f468da95 1247 ? f->icon_name
d5db4077 1248 : f->name)));
f1c7b5a6
RS
1249 else
1250 result = x_bitmap_icon (f, arg);
01f1ba30
JB
1251
1252 if (result)
1253 {
01f1ba30 1254 UNBLOCK_INPUT;
0fb53770 1255 error ("No icon window available");
01f1ba30
JB
1256 }
1257
b9dc4443 1258 XFlush (FRAME_X_DISPLAY (f));
01f1ba30
JB
1259 UNBLOCK_INPUT;
1260}
1261
80534dd6
KH
1262void
1263x_set_icon_name (f, arg, oldval)
1264 struct frame *f;
1265 Lisp_Object arg, oldval;
1266{
80534dd6
KH
1267 int result;
1268
1269 if (STRINGP (arg))
1270 {
1271 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1272 return;
1273 }
56f41f98 1274 else if (!NILP (arg) || NILP (oldval))
80534dd6
KH
1275 return;
1276
f468da95 1277 f->icon_name = arg;
80534dd6 1278
7556890b 1279 if (f->output_data.x->icon_bitmap != 0)
80534dd6
KH
1280 return;
1281
1282 BLOCK_INPUT;
1283
1284 result = x_text_icon (f,
d5db4077
KR
1285 (char *) SDATA ((!NILP (f->icon_name)
1286 ? f->icon_name
1287 : !NILP (f->title)
1288 ? f->title
1289 : f->name)));
80534dd6
KH
1290
1291 if (result)
1292 {
1293 UNBLOCK_INPUT;
1294 error ("No icon window available");
1295 }
1296
80534dd6
KH
1297 XFlush (FRAME_X_DISPLAY (f));
1298 UNBLOCK_INPUT;
1299}
7c0d3ed8 1300
943b580d 1301\f
01f1ba30 1302void
7c0d3ed8 1303x_set_menu_bar_lines (f, value, oldval)
f676886a 1304 struct frame *f;
7c0d3ed8 1305 Lisp_Object value, oldval;
01f1ba30 1306{
7c0d3ed8 1307 int nlines;
6b61353c 1308#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
7c0d3ed8
KS
1309 int olines = FRAME_MENU_BAR_LINES (f);
1310#endif
177c0ea7 1311
7c0d3ed8
KS
1312 /* Right now, menu bars don't work properly in minibuf-only frames;
1313 most of the commands try to apply themselves to the minibuffer
1314 frame itself, and get an error because you can't switch buffers
1315 in or split the minibuffer window. */
1316 if (FRAME_MINIBUF_ONLY_P (f))
1317 return;
177c0ea7 1318
7c0d3ed8
KS
1319 if (INTEGERP (value))
1320 nlines = XINT (value);
ea96210c 1321 else
7c0d3ed8 1322 nlines = 0;
a367641f 1323
7c0d3ed8
KS
1324 /* Make sure we redisplay all windows in this frame. */
1325 windows_or_buffers_changed++;
3d09b6be 1326
488dd4c4 1327#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
9ef48a9d
RS
1328 FRAME_MENU_BAR_LINES (f) = 0;
1329 if (nlines)
0d8ef3f4
RS
1330 {
1331 FRAME_EXTERNAL_MENU_BAR (f) = 1;
97a1ff91 1332 if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
0d8ef3f4
RS
1333 /* Make sure next redisplay shows the menu bar. */
1334 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt;
1335 }
9ef48a9d
RS
1336 else
1337 {
6bc20398
FP
1338 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
1339 free_frame_menubar (f);
9ef48a9d 1340 FRAME_EXTERNAL_MENU_BAR (f) = 0;
97a1ff91
RS
1341 if (FRAME_X_P (f))
1342 f->output_data.x->menubar_widget = 0;
9ef48a9d 1343 }
488dd4c4 1344#else /* not USE_X_TOOLKIT && not USE_GTK */
d043f1a4 1345 FRAME_MENU_BAR_LINES (f) = nlines;
7c0d3ed8 1346 change_window_heights (f->root_window, nlines - olines);
9ef48a9d 1347#endif /* not USE_X_TOOLKIT */
333b20bb
GM
1348 adjust_glyphs (f);
1349}
1350
1351
1352/* Set the number of lines used for the tool bar of frame F to VALUE.
1353 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
1354 is the old number of tool bar lines. This function changes the
1355 height of all windows on frame F to match the new tool bar height.
1356 The frame's height doesn't change. */
1357
1358void
9ea173e8 1359x_set_tool_bar_lines (f, value, oldval)
333b20bb
GM
1360 struct frame *f;
1361 Lisp_Object value, oldval;
1362{
52de7ce9
GM
1363 int delta, nlines, root_height;
1364 Lisp_Object root_window;
333b20bb 1365
e870b7ba
GM
1366 /* Treat tool bars like menu bars. */
1367 if (FRAME_MINIBUF_ONLY_P (f))
1368 return;
1369
333b20bb
GM
1370 /* Use VALUE only if an integer >= 0. */
1371 if (INTEGERP (value) && XINT (value) >= 0)
1372 nlines = XFASTINT (value);
1373 else
1374 nlines = 0;
1375
488dd4c4
JD
1376#ifdef USE_GTK
1377 FRAME_TOOL_BAR_LINES (f) = 0;
1378 if (nlines)
1379 {
1380 FRAME_EXTERNAL_TOOL_BAR (f) = 1;
1381 if (FRAME_X_P (f) && f->output_data.x->toolbar_widget == 0)
1382 /* Make sure next redisplay shows the tool bar. */
1383 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt;
1384 update_frame_tool_bar (f);
1385 }
1386 else
1387 {
1388 if (FRAME_EXTERNAL_TOOL_BAR (f))
1389 free_frame_tool_bar (f);
1390 FRAME_EXTERNAL_TOOL_BAR (f) = 0;
1391 }
1392
1393 return;
1394#endif
177c0ea7 1395
488dd4c4 1396 /* Make sure we redisplay all windows in this frame. */
333b20bb
GM
1397 ++windows_or_buffers_changed;
1398
9ea173e8 1399 delta = nlines - FRAME_TOOL_BAR_LINES (f);
52de7ce9
GM
1400
1401 /* Don't resize the tool-bar to more than we have room for. */
1402 root_window = FRAME_ROOT_WINDOW (f);
be786000 1403 root_height = WINDOW_TOTAL_LINES (XWINDOW (root_window));
52de7ce9
GM
1404 if (root_height - delta < 1)
1405 {
1406 delta = root_height - 1;
1407 nlines = FRAME_TOOL_BAR_LINES (f) + delta;
1408 }
1409
9ea173e8 1410 FRAME_TOOL_BAR_LINES (f) = nlines;
7c0d3ed8 1411 change_window_heights (root_window, delta);
333b20bb 1412 adjust_glyphs (f);
177c0ea7 1413
ccba751c
GM
1414 /* We also have to make sure that the internal border at the top of
1415 the frame, below the menu bar or tool bar, is redrawn when the
1416 tool bar disappears. This is so because the internal border is
1417 below the tool bar if one is displayed, but is below the menu bar
1418 if there isn't a tool bar. The tool bar draws into the area
1419 below the menu bar. */
1420 if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
1421 {
385ed61f 1422 clear_frame (f);
fb3cd89b 1423 clear_current_matrices (f);
ccba751c 1424 }
b6f91066
GM
1425
1426 /* If the tool bar gets smaller, the internal border below it
1427 has to be cleared. It was formerly part of the display
1428 of the larger tool bar, and updating windows won't clear it. */
1429 if (delta < 0)
1430 {
1431 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
be786000
KS
1432 int width = FRAME_PIXEL_WIDTH (f);
1433 int y = nlines * FRAME_LINE_HEIGHT (f);
b6f91066 1434
caacfeb8
JD
1435 /* height can be zero here. */
1436 if (height > 0 && width > 0)
1437 {
1438 BLOCK_INPUT;
1439 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1440 0, y, width, height, False);
1441 UNBLOCK_INPUT;
1442 }
ddc24747
GM
1443
1444 if (WINDOWP (f->tool_bar_window))
1445 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
b6f91066 1446 }
333b20bb
GM
1447}
1448
1449
1450/* Set the foreground color for scroll bars on frame F to VALUE.
1451 VALUE should be a string, a color name. If it isn't a string or
1452 isn't a valid color name, do nothing. OLDVAL is the old value of
1453 the frame parameter. */
1454
1455void
1456x_set_scroll_bar_foreground (f, value, oldval)
1457 struct frame *f;
1458 Lisp_Object value, oldval;
1459{
1460 unsigned long pixel;
177c0ea7 1461
333b20bb
GM
1462 if (STRINGP (value))
1463 pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
1464 else
1465 pixel = -1;
1466
1467 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
1468 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
177c0ea7 1469
333b20bb
GM
1470 f->output_data.x->scroll_bar_foreground_pixel = pixel;
1471 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
1472 {
1473 /* Remove all scroll bars because they have wrong colors. */
6ed8eeff
KL
1474 if (FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
1475 (*FRAME_TERMINAL (f)->condemn_scroll_bars_hook) (f);
1476 if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
1477 (*FRAME_TERMINAL (f)->judge_scroll_bars_hook) (f);
05c8abbe
GM
1478
1479 update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
333b20bb
GM
1480 redraw_frame (f);
1481 }
1482}
1483
1484
1485/* Set the background color for scroll bars on frame F to VALUE VALUE
1486 should be a string, a color name. If it isn't a string or isn't a
1487 valid color name, do nothing. OLDVAL is the old value of the frame
1488 parameter. */
1489
1490void
1491x_set_scroll_bar_background (f, value, oldval)
1492 struct frame *f;
1493 Lisp_Object value, oldval;
1494{
1495 unsigned long pixel;
1496
1497 if (STRINGP (value))
1498 pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
1499 else
1500 pixel = -1;
177c0ea7 1501
333b20bb
GM
1502 if (f->output_data.x->scroll_bar_background_pixel != -1)
1503 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
177c0ea7 1504
f15340b7
MB
1505#ifdef USE_TOOLKIT_SCROLL_BARS
1506 /* Scrollbar shadow colors. */
1507 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
1508 {
1509 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
1510 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
1511 }
1512 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
1513 {
1514 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
1515 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
1516 }
1517#endif /* USE_TOOLKIT_SCROLL_BARS */
1518
333b20bb
GM
1519 f->output_data.x->scroll_bar_background_pixel = pixel;
1520 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
1521 {
1522 /* Remove all scroll bars because they have wrong colors. */
6ed8eeff
KL
1523 if (FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
1524 (*FRAME_TERMINAL (f)->condemn_scroll_bars_hook) (f);
1525 if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
1526 (*FRAME_TERMINAL (f)->judge_scroll_bars_hook) (f);
177c0ea7 1527
05c8abbe 1528 update_face_from_frame_parameter (f, Qscroll_bar_background, value);
333b20bb
GM
1529 redraw_frame (f);
1530 }
d043f1a4 1531}
333b20bb 1532
943b580d 1533\f
3a258507 1534/* Encode Lisp string STRING as a text in a format appropriate for
96db09e4
KH
1535 XICCC (X Inter Client Communication Conventions).
1536
6f103132
RS
1537 This can call Lisp code, so callers must GCPRO.
1538
96db09e4
KH
1539 If STRING contains only ASCII characters, do no conversion and
1540 return the string data of STRING. Otherwise, encode the text by
1541 CODING_SYSTEM, and return a newly allocated memory area which
1542 should be freed by `xfree' by a caller.
1543
37323f34
EZ
1544 SELECTIONP non-zero means the string is being encoded for an X
1545 selection, so it is safe to run pre-write conversions (which
1546 may run Lisp code).
1547
96db09e4
KH
1548 Store the byte length of resulting text in *TEXT_BYTES.
1549
d60660d6 1550 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
96db09e4 1551 which means that the `encoding' of the result can be `STRING'.
d60660d6 1552 Otherwise store 0 in *STRINGP, which means that the `encoding' of
96db09e4
KH
1553 the result should be `COMPOUND_TEXT'. */
1554
df630496
KS
1555static unsigned char *
1556x_encode_text (string, coding_system, selectionp, text_bytes, stringp, freep)
96db09e4 1557 Lisp_Object string, coding_system;
d60660d6 1558 int *text_bytes, *stringp;
37323f34 1559 int selectionp;
df630496 1560 int *freep;
96db09e4 1561{
0f8c4c4f 1562 int result = string_xstring_p (string);
96db09e4
KH
1563 struct coding_system coding;
1564
0f8c4c4f 1565 if (result == 0)
96db09e4
KH
1566 {
1567 /* No multibyte character in OBJ. We need not encode it. */
8f924df7 1568 *text_bytes = SBYTES (string);
d60660d6 1569 *stringp = 1;
df630496 1570 *freep = 0;
8f924df7 1571 return SDATA (string);
96db09e4
KH
1572 }
1573
1574 setup_coding_system (coding_system, &coding);
0f8c4c4f 1575 coding.mode |= (CODING_MODE_SAFE_ENCODING | CODING_MODE_LAST_BLOCK);
35bc5887 1576 /* We suppress producing escape sequences for composition. */
0f8c4c4f 1577 coding.common_flags &= ~CODING_ANNOTATION_MASK;
8f924df7 1578 coding.dst_bytes = SCHARS (string) * 2;
b954d586 1579 coding.destination = (unsigned char *) xmalloc (coding.dst_bytes);
0f8c4c4f 1580 encode_coding_object (&coding, string, 0, 0,
8f924df7 1581 SCHARS (string), SBYTES (string), Qnil);
96db09e4 1582 *text_bytes = coding.produced;
0f8c4c4f 1583 *stringp = (result == 1 || !EQ (coding_system, Qcompound_text));
df630496 1584 *freep = 1;
b954d586 1585 return coding.destination;
96db09e4
KH
1586}
1587
1588\f
b10daec7
JD
1589/* Set the WM name to NAME for frame F. Also set the icon name.
1590 If the frame already has an icon name, use that, otherwise set the
1591 icon name to NAME. */
f945b920 1592
b10daec7
JD
1593static void
1594x_set_name_internal (f, name)
1595 FRAME_PTR f;
f945b920 1596 Lisp_Object name;
f945b920 1597{
fe24a618 1598 if (FRAME_X_WINDOW (f))
01f1ba30 1599 {
01f1ba30 1600 BLOCK_INPUT;
fe24a618 1601 {
80534dd6 1602 XTextProperty text, icon;
d60660d6 1603 int bytes, stringp;
b10daec7 1604 int do_free_icon_value = 0, do_free_text_value = 0;
11270583 1605 Lisp_Object coding_system;
c2915ced
CY
1606#ifdef USE_GTK
1607 Lisp_Object encoded_name;
1608 struct gcpro gcpro1;
1609
1610 /* As ENCODE_UTF_8 may cause GC and relocation of string data,
1611 we use it before x_encode_text that may return string data. */
1612 GCPRO1 (name);
1613 encoded_name = ENCODE_UTF_8 (name);
1614 UNGCPRO;
1615#endif
80534dd6 1616
b10daec7 1617 coding_system = Qcompound_text;
3201ea57
KH
1618 /* Note: Encoding strategy
1619
1620 We encode NAME by compound-text and use "COMPOUND-TEXT" in
1621 text.encoding. But, there are non-internationalized window
1622 managers which don't support that encoding. So, if NAME
1623 contains only ASCII and 8859-1 characters, encode it by
1624 iso-latin-1, and use "STRING" in text.encoding hoping that
34e8c597 1625 such window managers at least analyze this format correctly,
3201ea57
KH
1626 i.e. treat 8-bit bytes as 8859-1 characters.
1627
1628 We may also be able to use "UTF8_STRING" in text.encoding
34e8c597 1629 in the future which can encode all Unicode characters.
3201ea57
KH
1630 But, for the moment, there's no way to know that the
1631 current window manager supports it or not. */
df630496
KS
1632 text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp,
1633 &do_free_text_value);
d60660d6 1634 text.encoding = (stringp ? XA_STRING
96db09e4 1635 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
fe24a618 1636 text.format = 8;
96db09e4 1637 text.nitems = bytes;
80534dd6 1638
4985dde2 1639 if (!STRINGP (f->icon_name))
96db09e4
KH
1640 {
1641 icon = text;
1642 }
1643 else
1644 {
3201ea57 1645 /* See the above comment "Note: Encoding strategy". */
37323f34 1646 icon.value = x_encode_text (f->icon_name, coding_system, 0,
df630496 1647 &bytes, &stringp, &do_free_icon_value);
d60660d6 1648 icon.encoding = (stringp ? XA_STRING
96db09e4
KH
1649 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
1650 icon.format = 8;
1651 icon.nitems = bytes;
1652 }
b10daec7 1653
488dd4c4
JD
1654#ifdef USE_GTK
1655 gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
c2915ced 1656 (char *) SDATA (encoded_name));
488dd4c4 1657#else /* not USE_GTK */
2436a4e4 1658 XSetWMName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
7c0d3ed8 1659#endif /* not USE_GTK */
abb4b7ec 1660
7c0d3ed8 1661 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &icon);
abb4b7ec 1662
b10daec7 1663 if (do_free_icon_value)
7c0d3ed8 1664 xfree (icon.value);
b10daec7 1665 if (do_free_text_value)
7c0d3ed8
KS
1666 xfree (text.value);
1667 }
7c0d3ed8
KS
1668 UNBLOCK_INPUT;
1669 }
abb4b7ec
RS
1670}
1671
b10daec7
JD
1672/* Change the name of frame F to NAME. If NAME is nil, set F's name to
1673 x_id_name.
1674
1675 If EXPLICIT is non-zero, that indicates that lisp code is setting the
1676 name; if NAME is a string, set F's name to NAME and set
1677 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1678
1679 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1680 suggesting a new name, which lisp code should override; if
1681 F->explicit_name is set, ignore the new name; otherwise, set it. */
1682
1683void
1684x_set_name (f, name, explicit)
1685 struct frame *f;
1686 Lisp_Object name;
1687 int explicit;
1688{
1689 /* Make sure that requests from lisp code override requests from
1690 Emacs redisplay code. */
1691 if (explicit)
1692 {
1693 /* If we're switching from explicit to implicit, we had better
1694 update the mode lines and thereby update the title. */
1695 if (f->explicit_name && NILP (name))
1696 update_mode_lines = 1;
1697
1698 f->explicit_name = ! NILP (name);
1699 }
1700 else if (f->explicit_name)
1701 return;
1702
1703 /* If NAME is nil, set the name to the x_id_name. */
1704 if (NILP (name))
1705 {
1706 /* Check for no change needed in this very common case
1707 before we do any consing. */
1708 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
1709 SDATA (f->name)))
1710 return;
1711 name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
1712 }
1713 else
1714 CHECK_STRING (name);
1715
1716 /* Don't change the name if it's already NAME. */
1717 if (! NILP (Fstring_equal (name, f->name)))
1718 return;
1719
1720 f->name = name;
1721
1722 /* For setting the frame title, the title parameter should override
1723 the name parameter. */
1724 if (! NILP (f->title))
1725 name = f->title;
1726
1727 x_set_name_internal (f, name);
1728}
1729
7c0d3ed8
KS
1730/* This function should be called when the user's lisp code has
1731 specified a name for the frame; the name will override any set by the
1732 redisplay code. */
1733void
1734x_explicitly_set_name (f, arg, oldval)
1735 FRAME_PTR f;
1736 Lisp_Object arg, oldval;
3402e1a4 1737{
7c0d3ed8 1738 x_set_name (f, arg, 1);
3402e1a4
RS
1739}
1740
7c0d3ed8
KS
1741/* This function should be called by Emacs redisplay code to set the
1742 name; names set this way will never override names set by the user's
1743 lisp code. */
1744void
1745x_implicitly_set_name (f, arg, oldval)
1746 FRAME_PTR f;
1747 Lisp_Object arg, oldval;
333b20bb 1748{
7c0d3ed8
KS
1749 x_set_name (f, arg, 0);
1750}
1751\f
1752/* Change the title of frame F to NAME.
40aa4c27 1753 If NAME is nil, use the frame name as the title. */
01f1ba30 1754
7c0d3ed8
KS
1755void
1756x_set_title (f, name, old_name)
1757 struct frame *f;
1758 Lisp_Object name, old_name;
01f1ba30 1759{
7c0d3ed8
KS
1760 /* Don't change the title if it's already NAME. */
1761 if (EQ (name, f->title))
1762 return;
01f1ba30 1763
7c0d3ed8 1764 update_mode_lines = 1;
60fb3ee1 1765
7c0d3ed8 1766 f->title = name;
f9942c9e 1767
7c0d3ed8
KS
1768 if (NILP (name))
1769 name = f->name;
1770 else
1771 CHECK_STRING (name);
f9942c9e 1772
b10daec7 1773 x_set_name_internal (f, name);
01f1ba30
JB
1774}
1775
7c0d3ed8
KS
1776void
1777x_set_scroll_bar_default_width (f)
e4f79258 1778 struct frame *f;
e4f79258 1779{
be786000 1780 int wid = FRAME_COLUMN_WIDTH (f);
01f1ba30 1781
7c0d3ed8
KS
1782#ifdef USE_TOOLKIT_SCROLL_BARS
1783 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
1784 int width = 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM;
be786000
KS
1785 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (width + wid - 1) / wid;
1786 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = width;
7c0d3ed8
KS
1787#else
1788 /* Make the actual width at least 14 pixels and a multiple of a
1789 character width. */
be786000 1790 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
01f1ba30 1791
7c0d3ed8
KS
1792 /* Use all of that space (aside from required margins) for the
1793 scroll bar. */
be786000 1794 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = 0;
7c0d3ed8 1795#endif
01f1ba30 1796}
333b20bb 1797
7c0d3ed8 1798\f
333b20bb
GM
1799/* Record in frame F the specified or default value according to ALIST
1800 of the parameter named PROP (a Lisp symbol). If no value is
1801 specified for PROP, look for an X default for XPROP on the frame
1802 named NAME. If that is not found either, use the value DEFLT. */
1803
1804static Lisp_Object
1805x_default_scroll_bar_color_parameter (f, alist, prop, xprop, xclass,
1806 foreground_p)
1807 struct frame *f;
1808 Lisp_Object alist;
1809 Lisp_Object prop;
1810 char *xprop;
1811 char *xclass;
1812 int foreground_p;
1813{
1814 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
1815 Lisp_Object tem;
1816
1817 tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING);
1818 if (EQ (tem, Qunbound))
1819 {
1820#ifdef USE_TOOLKIT_SCROLL_BARS
1821
1822 /* See if an X resource for the scroll bar color has been
1823 specified. */
1824 tem = display_x_get_resource (dpyinfo,
1825 build_string (foreground_p
1826 ? "foreground"
1827 : "background"),
6ecd75be 1828 empty_unibyte_string,
333b20bb 1829 build_string ("verticalScrollBar"),
6ecd75be 1830 empty_unibyte_string);
333b20bb
GM
1831 if (!STRINGP (tem))
1832 {
1833 /* If nothing has been specified, scroll bars will use a
1834 toolkit-dependent default. Because these defaults are
1835 difficult to get at without actually creating a scroll
1836 bar, use nil to indicate that no color has been
1837 specified. */
1838 tem = Qnil;
1839 }
177c0ea7 1840
333b20bb 1841#else /* not USE_TOOLKIT_SCROLL_BARS */
177c0ea7 1842
333b20bb 1843 tem = Qnil;
177c0ea7 1844
333b20bb
GM
1845#endif /* not USE_TOOLKIT_SCROLL_BARS */
1846 }
1847
1848 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
1849 return tem;
1850}
1851
1852
01f1ba30 1853
9ef48a9d
RS
1854\f
1855#ifdef USE_X_TOOLKIT
1856
8e3d10a9
RS
1857/* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
1858 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
59aa6c90
RS
1859 already be present because of the toolkit (Motif adds some of them,
1860 for example, but Xt doesn't). */
9ef48a9d
RS
1861
1862static void
b9dc4443
RS
1863hack_wm_protocols (f, widget)
1864 FRAME_PTR f;
9ef48a9d
RS
1865 Widget widget;
1866{
1867 Display *dpy = XtDisplay (widget);
1868 Window w = XtWindow (widget);
1869 int need_delete = 1;
1870 int need_focus = 1;
59aa6c90 1871 int need_save = 1;
9ef48a9d
RS
1872
1873 BLOCK_INPUT;
1874 {
a3db4b26
AS
1875 Atom type;
1876 unsigned char *catoms;
9ef48a9d
RS
1877 int format = 0;
1878 unsigned long nitems = 0;
1879 unsigned long bytes_after;
1880
270958e8
KH
1881 if ((XGetWindowProperty (dpy, w,
1882 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
34d5ae1e 1883 (long)0, (long)100, False, XA_ATOM,
270958e8 1884 &type, &format, &nitems, &bytes_after,
a3db4b26 1885 &catoms)
270958e8 1886 == Success)
9ef48a9d 1887 && format == 32 && type == XA_ATOM)
a3db4b26
AS
1888 {
1889 Atom *atoms = (Atom *) catoms;
1890 while (nitems > 0)
1891 {
1892 nitems--;
1893 if (atoms[nitems]
1894 == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
1895 need_delete = 0;
1896 else if (atoms[nitems]
1897 == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
1898 need_focus = 0;
1899 else if (atoms[nitems]
1900 == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
1901 need_save = 0;
1902 }
1903 }
1904 if (catoms)
1905 XFree (catoms);
9ef48a9d
RS
1906 }
1907 {
1908 Atom props [10];
1909 int count = 0;
b9dc4443
RS
1910 if (need_delete)
1911 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
1912 if (need_focus)
1913 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus;
1914 if (need_save)
1915 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
9ef48a9d 1916 if (count)
b9dc4443
RS
1917 XChangeProperty (dpy, w, FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
1918 XA_ATOM, 32, PropModeAppend,
9ef48a9d
RS
1919 (unsigned char *) props, count);
1920 }
1921 UNBLOCK_INPUT;
1922}
1923#endif
86779fac
GM
1924
1925
5a7df7d7
GM
1926\f
1927/* Support routines for XIC (X Input Context). */
86779fac 1928
5a7df7d7
GM
1929#ifdef HAVE_X_I18N
1930
1931static XFontSet xic_create_xfontset P_ ((struct frame *, char *));
a32f056c 1932static XFontSet xic_create_xfontset2 P_ ((struct frame *));
5a7df7d7
GM
1933static XIMStyle best_xim_style P_ ((XIMStyles *, XIMStyles *));
1934
1935
1576f1ad 1936/* Supported XIM styles, ordered by preference. */
5a7df7d7
GM
1937
1938static XIMStyle supported_xim_styles[] =
1939{
1940 XIMPreeditPosition | XIMStatusArea,
1941 XIMPreeditPosition | XIMStatusNothing,
1942 XIMPreeditPosition | XIMStatusNone,
1943 XIMPreeditNothing | XIMStatusArea,
1944 XIMPreeditNothing | XIMStatusNothing,
1945 XIMPreeditNothing | XIMStatusNone,
1946 XIMPreeditNone | XIMStatusArea,
1947 XIMPreeditNone | XIMStatusNothing,
1948 XIMPreeditNone | XIMStatusNone,
1949 0,
1950};
1951
1952
c27ed90a 1953/* Create an X fontset on frame F with base font name BASE_FONTNAME. */
5a7df7d7 1954
bb07fa29
SM
1955char xic_defaut_fontset[] = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
1956
c28e7ae8
SM
1957/* Create an Xt fontset spec from the name of a base font.
1958 If `motif' is True use the Motif syntax. */
bb07fa29 1959char *
c28e7ae8 1960xic_create_fontsetname (base_fontname, motif)
bb07fa29 1961 char *base_fontname;
c28e7ae8 1962 Bool motif;
bb07fa29 1963{
c28e7ae8
SM
1964 const char *sep = motif ? ";" : ",";
1965 char *fontsetname;
1966
bb07fa29
SM
1967 /* Make a fontset name from the base font name. */
1968 if (xic_defaut_fontset == base_fontname)
c28e7ae8
SM
1969 { /* There is no base font name, use the default. */
1970 int len = strlen (base_fontname) + 2;
1971 fontsetname = xmalloc (len);
1972 bzero (fontsetname, len);
1973 strcpy (fontsetname, base_fontname);
1974 }
bb07fa29
SM
1975 else
1976 {
1977 /* Make a fontset name from the base font name.
1978 The font set will be made of the following elements:
1979 - the base font.
1980 - the base font where the charset spec is replaced by -*-*.
1981 - the same but with the family also replaced with -*-*-. */
1982 char *p = base_fontname;
bb07fa29 1983 int i;
df630496 1984
bb07fa29
SM
1985 for (i = 0; *p; p++)
1986 if (*p == '-') i++;
1987 if (i != 14)
1988 { /* As the font name doesn't conform to XLFD, we can't
1989 modify it to generalize it to allcs and allfamilies.
1990 Use the specified font plus the default. */
c28e7ae8 1991 int len = strlen (base_fontname) + strlen (xic_defaut_fontset) + 3;
bb07fa29
SM
1992 fontsetname = xmalloc (len);
1993 bzero (fontsetname, len);
1994 strcpy (fontsetname, base_fontname);
c28e7ae8 1995 strcat (fontsetname, sep);
bb07fa29
SM
1996 strcat (fontsetname, xic_defaut_fontset);
1997 }
1998 else
1999 {
2000 int len;
cd987aaa 2001 char *p1 = NULL, *p2 = NULL, *p3 = NULL;
bb07fa29
SM
2002 char *font_allcs = NULL;
2003 char *font_allfamilies = NULL;
968a6679 2004 char *font_all = NULL;
bb07fa29
SM
2005 char *allcs = "*-*-*-*-*-*-*";
2006 char *allfamilies = "-*-*-";
968a6679 2007 char *all = "*-*-*-*-";
cd987aaa 2008 char *base;
df630496 2009
bb07fa29
SM
2010 for (i = 0, p = base_fontname; i < 8; p++)
2011 {
2012 if (*p == '-')
2013 {
2014 i++;
2015 if (i == 3)
2016 p1 = p + 1;
968a6679
SM
2017 else if (i == 7)
2018 p2 = p + 1;
cd987aaa
KH
2019 else if (i == 6)
2020 p3 = p + 1;
bb07fa29
SM
2021 }
2022 }
cd987aaa
KH
2023 /* If base_fontname specifies ADSTYLE, make it a
2024 wildcard. */
2025 if (*p3 != '*')
2026 {
2027 int diff = (p2 - p3) - 2;
2028
2029 base = alloca (strlen (base_fontname) + 1);
2030 bcopy (base_fontname, base, p3 - base_fontname);
2031 base[p3 - base_fontname] = '*';
2032 base[(p3 - base_fontname) + 1] = '-';
2033 strcpy (base + (p3 - base_fontname) + 2, p2);
2034 p = base + (p - base_fontname) - diff;
2035 p1 = base + (p1 - base_fontname);
2036 p2 = base + (p2 - base_fontname) - diff;
2037 base_fontname = base;
2038 }
2039
bb07fa29
SM
2040 /* Build the font spec that matches all charsets. */
2041 len = p - base_fontname + strlen (allcs) + 1;
2042 font_allcs = (char *) alloca (len);
2043 bzero (font_allcs, len);
2044 bcopy (base_fontname, font_allcs, p - base_fontname);
2045 strcat (font_allcs, allcs);
2046
cd987aaa
KH
2047 /* Build the font spec that matches all families and
2048 add-styles. */
bb07fa29
SM
2049 len = p - p1 + strlen (allcs) + strlen (allfamilies) + 1;
2050 font_allfamilies = (char *) alloca (len);
2051 bzero (font_allfamilies, len);
2052 strcpy (font_allfamilies, allfamilies);
968a6679 2053 bcopy (p1, font_allfamilies + strlen (allfamilies), p - p1);
bb07fa29
SM
2054 strcat (font_allfamilies, allcs);
2055
968a6679
SM
2056 /* Build the font spec that matches all. */
2057 len = p - p2 + strlen (allcs) + strlen (all) + strlen (allfamilies) + 1;
2058 font_all = (char *) alloca (len);
2059 bzero (font_all, len);
2060 strcpy (font_all, allfamilies);
2061 strcat (font_all, all);
2062 bcopy (p2, font_all + strlen (all) + strlen (allfamilies), p - p2);
2063 strcat (font_all, allcs);
2064
bb07fa29
SM
2065 /* Build the actual font set name. */
2066 len = strlen (base_fontname) + strlen (font_allcs)
968a6679 2067 + strlen (font_allfamilies) + strlen (font_all) + 5;
bb07fa29
SM
2068 fontsetname = xmalloc (len);
2069 bzero (fontsetname, len);
2070 strcpy (fontsetname, base_fontname);
c28e7ae8 2071 strcat (fontsetname, sep);
bb07fa29 2072 strcat (fontsetname, font_allcs);
c28e7ae8 2073 strcat (fontsetname, sep);
bb07fa29 2074 strcat (fontsetname, font_allfamilies);
968a6679
SM
2075 strcat (fontsetname, sep);
2076 strcat (fontsetname, font_all);
bb07fa29 2077 }
bb07fa29 2078 }
c28e7ae8
SM
2079 if (motif)
2080 strcat (fontsetname, ":");
2081 return fontsetname;
bb07fa29
SM
2082}
2083
2da34f50
KH
2084#ifdef DEBUG_XIC_FONTSET
2085static void
2086print_fontset_result (xfs, name, missing_list, missing_count)
2087 XFontSet xfs;
2088 char *name;
2089 char **missing_list;
2090 int missing_count;
2091{
2092 if (xfs)
2093 fprintf (stderr, "XIC Fontset created: %s\n", name);
2094 else
2095 {
2096 fprintf (stderr, "XIC Fontset failed: %s\n", name);
2097 while (missing_count-- > 0)
2098 {
2099 fprintf (stderr, " missing: %s\n", *missing_list);
2100 missing_list++;
2101 }
2102 }
2103
2104}
2105#endif
2106
5a7df7d7
GM
2107static XFontSet
2108xic_create_xfontset (f, base_fontname)
86779fac 2109 struct frame *f;
5a7df7d7 2110 char *base_fontname;
86779fac 2111{
c27ed90a 2112 XFontSet xfs = NULL;
63ea8ea5 2113 char **missing_list = NULL;
5a7df7d7
GM
2114 int missing_count;
2115 char *def_string;
c27ed90a
JD
2116 Lisp_Object rest, frame;
2117
bb07fa29
SM
2118 if (!base_fontname)
2119 base_fontname = xic_defaut_fontset;
2120
c27ed90a
JD
2121 /* See if there is another frame already using same fontset. */
2122 FOR_EACH_FRAME (rest, frame)
2123 {
2124 struct frame *cf = XFRAME (frame);
2125 if (cf != f && FRAME_LIVE_P (f) && FRAME_X_P (cf)
2126 && FRAME_X_DISPLAY_INFO (cf) == FRAME_X_DISPLAY_INFO (f)
9db6ae81 2127 && FRAME_XIC_BASE_FONTNAME (cf)
c27ed90a
JD
2128 && !strcmp (FRAME_XIC_BASE_FONTNAME (cf), base_fontname))
2129 {
2130 xfs = FRAME_XIC_FONTSET (cf);
2131 break;
2132 }
2133 }
177c0ea7 2134
c27ed90a 2135 if (!xfs)
63ea8ea5 2136 {
c28e7ae8 2137 char *fontsetname = xic_create_fontsetname (base_fontname, False);
bb07fa29 2138
63ea8ea5 2139 /* New fontset. */
7147863a
KH
2140 xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
2141 fontsetname, &missing_list,
2142 &missing_count, &def_string);
2da34f50
KH
2143#ifdef DEBUG_XIC_FONTSET
2144 print_fontset_result (xfs, fontsetname, missing_list, missing_count);
2145#endif
7147863a
KH
2146 if (missing_list)
2147 XFreeStringList (missing_list);
2148 if (! xfs)
cd987aaa 2149 {
7147863a
KH
2150 /* FONTSETNAME contains a list of font names (specific fonts
2151 first, general fonts last), but giving that to
2152 XCreateFontSet at once occasionally fails (bug of X?).
2153 So, we try to call XCreateFontSet for each fontname. */
2154 char *p0 = fontsetname, *p1;
2155
2156 while (p0)
2157 {
2158 p1 = strchr (p0, ',');
2159 if (p1)
2160 *p1 = '\0';
2161 xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
2162 p0, &missing_list,
2163 &missing_count, &def_string);
2da34f50
KH
2164#ifdef DEBUG_XIC_FONTSET
2165 print_fontset_result (xfs, p0, missing_list, missing_count);
2166#endif
7147863a
KH
2167 if (missing_list)
2168 XFreeStringList (missing_list);
2169 if (xfs)
2170 break;
2171 p0 = p1 ? p1 + 1 : NULL;
2172 }
cd987aaa 2173 }
c28e7ae8 2174 xfree (fontsetname);
278109a9
KH
2175 if (! xfs && base_fontname != xic_defaut_fontset)
2176 {
2177 /* Try the default fontset name at a last resort. */
2178 fontsetname = xic_create_fontsetname (xic_defaut_fontset, False);
2179 xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
2180 fontsetname, &missing_list,
2181 &missing_count, &def_string);
2da34f50
KH
2182#ifdef DEBUG_XIC_FONTSET
2183 print_fontset_result (xfs, fontsetname, missing_list, missing_count);
2184#endif
278109a9
KH
2185 if (missing_list)
2186 XFreeStringList (missing_list);
2187 xfree (fontsetname);
2188 }
63ea8ea5 2189 }
177c0ea7 2190
c27ed90a
JD
2191 if (FRAME_XIC_BASE_FONTNAME (f))
2192 xfree (FRAME_XIC_BASE_FONTNAME (f));
2193 FRAME_XIC_BASE_FONTNAME (f) = xstrdup (base_fontname);
2194
2195 /* No need to free def_string. */
5a7df7d7
GM
2196 return xfs;
2197}
2198
a32f056c 2199#ifdef USE_FONT_BACKEND
d3483d71 2200
a32f056c
KH
2201static XFontSet
2202xic_create_xfontset2 (f)
2203 struct frame *f;
2204{
2205 XFontSet xfs = NULL;
2206 struct font *font = FRAME_FONT_OBJECT (f);
2207 int pixel_size = font->pixel_size;
2208 Lisp_Object rest, frame;
2209
2210 /* See if there is another frame already using same fontset. */
2211 FOR_EACH_FRAME (rest, frame)
2212 {
2213 struct frame *cf = XFRAME (frame);
2214
2215 if (cf != f && FRAME_LIVE_P (f) && FRAME_X_P (cf)
2216 && FRAME_X_DISPLAY_INFO (cf) == FRAME_X_DISPLAY_INFO (f)
2217 && FRAME_FONT_OBJECT (f)
2218 && FRAME_FONT_OBJECT (f)->pixel_size == pixel_size)
2219 {
2220 xfs = FRAME_XIC_FONTSET (cf);
2221 break;
2222 }
2223 }
2224
2225 if (! xfs)
2226 {
2227 char buf[256];
2228 char **missing_list;
2229 int missing_count;
2230 char *def_string;
2231 char *xlfd_format = "-*-*-medium-r-normal--%d-*-*-*-*-*";
2232
2233 sprintf (buf, xlfd_format, pixel_size);
2234 missing_list = NULL;
2235 xfs = XCreateFontSet (FRAME_X_DISPLAY (f), buf,
2236 &missing_list, &missing_count, &def_string);
d3483d71 2237#ifdef DEBUG_XIC_FONTSET
22a8f595 2238 print_fontset_result (xfs, buf, missing_list, missing_count);
d3483d71 2239#endif
a32f056c
KH
2240 if (missing_list)
2241 XFreeStringList (missing_list);
2242 if (! xfs)
2243 {
2244 /* List of pixel sizes most likely available. Find one that
2245 is closest to pixel_size. */
2246 int sizes[] = {0, 8, 10, 11, 12, 14, 17, 18, 20, 24, 26, 34, 0};
2247 int *smaller, *larger;
2248
2249 for (smaller = sizes; smaller[1]; smaller++)
2250 if (smaller[1] >= pixel_size)
2251 break;
2252 larger = smaller + 1;
2253 if (*larger == pixel_size)
2254 larger++;
2255 while (*smaller || *larger)
2256 {
2257 int this_size;
2258
2259 if (! *larger)
2260 this_size = *smaller--;
2261 else if (! *smaller)
2262 this_size = *larger++;
2263 else if (pixel_size - *smaller < *larger - pixel_size)
2264 this_size = *smaller--;
2265 else
2266 this_size = *larger++;
2267 sprintf (buf, xlfd_format, this_size);
2268 missing_list = NULL;
2269 xfs = XCreateFontSet (FRAME_X_DISPLAY (f), buf,
2270 &missing_list, &missing_count, &def_string);
d3483d71 2271#ifdef DEBUG_XIC_FONTSET
22a8f595 2272 print_fontset_result (xfs, buf, missing_list, missing_count);
d3483d71 2273#endif
a32f056c
KH
2274 if (missing_list)
2275 XFreeStringList (missing_list);
2276 if (xfs)
2277 break;
2278 }
2279 }
2da34f50
KH
2280 if (! xfs)
2281 {
2282 char *last_resort = "-*-*-*-r-normal--*-*-*-*-*-*";
2283
2284 missing_list = NULL;
2285 xfs = XCreateFontSet (FRAME_X_DISPLAY (f), last_resort,
2286 &missing_list, &missing_count, &def_string);
2287#ifdef DEBUG_XIC_FONTSET
2288 print_fontset_result (xfs, last_resort, missing_list, missing_count);
2289#endif
2290 if (missing_list)
2291 XFreeStringList (missing_list);
2292 }
2293
a32f056c
KH
2294 }
2295
2296 return xfs;
2297}
2298#endif /* USE_FONT_BACKEND */
2299
c27ed90a
JD
2300/* Free the X fontset of frame F if it is the last frame using it. */
2301
2302void
2303xic_free_xfontset (f)
2304 struct frame *f;
2305{
2306 Lisp_Object rest, frame;
2307 int shared_p = 0;
2308
2309 if (!FRAME_XIC_FONTSET (f))
2310 return;
2311
2312 /* See if there is another frame sharing the same fontset. */
2313 FOR_EACH_FRAME (rest, frame)
2314 {
2315 struct frame *cf = XFRAME (frame);
2316 if (cf != f && FRAME_LIVE_P (f) && FRAME_X_P (cf)
2317 && FRAME_X_DISPLAY_INFO (cf) == FRAME_X_DISPLAY_INFO (f)
2318 && FRAME_XIC_FONTSET (cf) == FRAME_XIC_FONTSET (f))
2319 {
2320 shared_p = 1;
2321 break;
2322 }
2323 }
2324
2325 if (!shared_p)
2326 /* The fontset is not used anymore. It is safe to free it. */
2327 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
2328
2329 if (FRAME_XIC_BASE_FONTNAME (f))
2330 xfree (FRAME_XIC_BASE_FONTNAME (f));
2331 FRAME_XIC_BASE_FONTNAME (f) = NULL;
2332 FRAME_XIC_FONTSET (f) = NULL;
2333}
2334
5a7df7d7
GM
2335
2336/* Value is the best input style, given user preferences USER (already
2337 checked to be supported by Emacs), and styles supported by the
2338 input method XIM. */
2339
2340static XIMStyle
2341best_xim_style (user, xim)
2342 XIMStyles *user;
2343 XIMStyles *xim;
2344{
2345 int i, j;
2346
2347 for (i = 0; i < user->count_styles; ++i)
2348 for (j = 0; j < xim->count_styles; ++j)
2349 if (user->supported_styles[i] == xim->supported_styles[j])
2350 return user->supported_styles[i];
2351
2352 /* Return the default style. */
2353 return XIMPreeditNothing | XIMStatusNothing;
2354}
2355
2356/* Create XIC for frame F. */
2357
5df79d3d
GM
2358static XIMStyle xic_style;
2359
5a7df7d7
GM
2360void
2361create_frame_xic (f)
2362 struct frame *f;
2363{
5a7df7d7
GM
2364 XIM xim;
2365 XIC xic = NULL;
2366 XFontSet xfs = NULL;
86779fac 2367
5a7df7d7
GM
2368 if (FRAME_XIC (f))
2369 return;
177c0ea7 2370
bb07fa29 2371 /* Create X fontset. */
a32f056c
KH
2372#ifdef USE_FONT_BACKEND
2373 if (enable_font_backend)
2374 xfs = xic_create_xfontset2 (f);
2375 else
2376#endif
bb07fa29
SM
2377 xfs = xic_create_xfontset
2378 (f, (FRAME_FONTSET (f) < 0) ? NULL
2379 : (char *) SDATA (fontset_ascii (FRAME_FONTSET (f))));
2380
5a7df7d7
GM
2381 xim = FRAME_X_XIM (f);
2382 if (xim)
2383 {
d9d57cb2
DL
2384 XRectangle s_area;
2385 XPoint spot;
5a7df7d7
GM
2386 XVaNestedList preedit_attr;
2387 XVaNestedList status_attr;
5a7df7d7 2388
d9d57cb2
DL
2389 s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
2390 spot.x = 0; spot.y = 1;
86779fac 2391
5a7df7d7
GM
2392 /* Determine XIC style. */
2393 if (xic_style == 0)
2394 {
2395 XIMStyles supported_list;
2396 supported_list.count_styles = (sizeof supported_xim_styles
2397 / sizeof supported_xim_styles[0]);
2398 supported_list.supported_styles = supported_xim_styles;
2399 xic_style = best_xim_style (&supported_list,
2400 FRAME_X_XIM_STYLES (f));
2401 }
86779fac 2402
5a7df7d7
GM
2403 preedit_attr = XVaCreateNestedList (0,
2404 XNFontSet, xfs,
2405 XNForeground,
2406 FRAME_FOREGROUND_PIXEL (f),
2407 XNBackground,
2408 FRAME_BACKGROUND_PIXEL (f),
2409 (xic_style & XIMPreeditPosition
2410 ? XNSpotLocation
2411 : NULL),
2412 &spot,
2413 NULL);
2414 status_attr = XVaCreateNestedList (0,
2415 XNArea,
2416 &s_area,
2417 XNFontSet,
2418 xfs,
2419 XNForeground,
2420 FRAME_FOREGROUND_PIXEL (f),
2421 XNBackground,
2422 FRAME_BACKGROUND_PIXEL (f),
2423 NULL);
2424
2425 xic = XCreateIC (xim,
2426 XNInputStyle, xic_style,
6b61353c
KH
2427 XNClientWindow, FRAME_X_WINDOW (f),
2428 XNFocusWindow, FRAME_X_WINDOW (f),
5a7df7d7
GM
2429 XNStatusAttributes, status_attr,
2430 XNPreeditAttributes, preedit_attr,
2431 NULL);
2432 XFree (preedit_attr);
2433 XFree (status_attr);
2434 }
177c0ea7 2435
5a7df7d7
GM
2436 FRAME_XIC (f) = xic;
2437 FRAME_XIC_STYLE (f) = xic_style;
2438 FRAME_XIC_FONTSET (f) = xfs;
86779fac
GM
2439}
2440
5a7df7d7
GM
2441
2442/* Destroy XIC and free XIC fontset of frame F, if any. */
2443
2444void
2445free_frame_xic (f)
2446 struct frame *f;
2447{
2448 if (FRAME_XIC (f) == NULL)
2449 return;
177c0ea7 2450
5a7df7d7 2451 XDestroyIC (FRAME_XIC (f));
c27ed90a 2452 xic_free_xfontset (f);
5a7df7d7
GM
2453
2454 FRAME_XIC (f) = NULL;
5a7df7d7
GM
2455}
2456
2457
2458/* Place preedit area for XIC of window W's frame to specified
2459 pixel position X/Y. X and Y are relative to window W. */
2460
2461void
2462xic_set_preeditarea (w, x, y)
2463 struct window *w;
2464 int x, y;
2465{
2466 struct frame *f = XFRAME (w->frame);
2467 XVaNestedList attr;
2468 XPoint spot;
177c0ea7 2469
17e6d491 2470 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x) + WINDOW_LEFT_FRINGE_WIDTH (w);
5a7df7d7
GM
2471 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
2472 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
2473 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
2474 XFree (attr);
2475}
2476
2477
2478/* Place status area for XIC in bottom right corner of frame F.. */
2479
2480void
2481xic_set_statusarea (f)
2482 struct frame *f;
2483{
2484 XIC xic = FRAME_XIC (f);
2485 XVaNestedList attr;
2486 XRectangle area;
2487 XRectangle *needed;
2488
2489 /* Negotiate geometry of status area. If input method has existing
2490 status area, use its current size. */
2491 area.x = area.y = area.width = area.height = 0;
2492 attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
2493 XSetICValues (xic, XNStatusAttributes, attr, NULL);
2494 XFree (attr);
177c0ea7 2495
5a7df7d7
GM
2496 attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
2497 XGetICValues (xic, XNStatusAttributes, attr, NULL);
2498 XFree (attr);
2499
2500 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
2501 {
2502 attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
2503 XGetICValues (xic, XNStatusAttributes, attr, NULL);
2504 XFree (attr);
2505 }
2506
2507 area.width = needed->width;
2508 area.height = needed->height;
be786000
KS
2509 area.x = FRAME_PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
2510 area.y = (FRAME_PIXEL_HEIGHT (f) - area.height
488dd4c4
JD
2511 - FRAME_MENUBAR_HEIGHT (f)
2512 - FRAME_TOOLBAR_HEIGHT (f)
2513 - FRAME_INTERNAL_BORDER_WIDTH (f));
5a7df7d7
GM
2514 XFree (needed);
2515
2516 attr = XVaCreateNestedList (0, XNArea, &area, NULL);
6b61353c 2517 XSetICValues (xic, XNStatusAttributes, attr, NULL);
5a7df7d7
GM
2518 XFree (attr);
2519}
2520
2521
2522/* Set X fontset for XIC of frame F, using base font name
2523 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
2524
2525void
2526xic_set_xfontset (f, base_fontname)
2527 struct frame *f;
2528 char *base_fontname;
2529{
2530 XVaNestedList attr;
2531 XFontSet xfs;
2532
c27ed90a
JD
2533 xic_free_xfontset (f);
2534
a32f056c
KH
2535#ifdef USE_FONT_BACKEND
2536 if (enable_font_backend)
2537 xfs = xic_create_xfontset2 (f);
2538 else
2539#endif
5a7df7d7
GM
2540 xfs = xic_create_xfontset (f, base_fontname);
2541
2542 attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
2543 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
2544 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
2545 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
2546 XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
2547 XFree (attr);
177c0ea7 2548
5a7df7d7
GM
2549 FRAME_XIC_FONTSET (f) = xfs;
2550}
2551
2552#endif /* HAVE_X_I18N */
2553
2554
9ef48a9d 2555\f
8fc2766b
RS
2556#ifdef USE_X_TOOLKIT
2557
2558/* Create and set up the X widget for frame F. */
f58534a3 2559
01f1ba30 2560static void
a7f7d550
FP
2561x_window (f, window_prompting, minibuffer_only)
2562 struct frame *f;
2563 long window_prompting;
2564 int minibuffer_only;
01f1ba30 2565{
9ef48a9d 2566 XClassHint class_hints;
31ac8d8c
FP
2567 XSetWindowAttributes attributes;
2568 unsigned long attribute_mask;
9ef48a9d
RS
2569 Widget shell_widget;
2570 Widget pane_widget;
6c32dd68 2571 Widget frame_widget;
9ef48a9d
RS
2572 Arg al [25];
2573 int ac;
2574
2575 BLOCK_INPUT;
2576
b7975ee4
KH
2577 /* Use the resource name as the top-level widget name
2578 for looking up resources. Make a non-Lisp copy
2579 for the window manager, so GC relocation won't bother it.
2580
2581 Elsewhere we specify the window name for the window manager. */
177c0ea7 2582
cca176a0 2583 {
d5db4077 2584 char *str = (char *) SDATA (Vx_resource_name);
b7975ee4 2585 f->namebuf = (char *) xmalloc (strlen (str) + 1);
cca176a0
KH
2586 strcpy (f->namebuf, str);
2587 }
9ef48a9d
RS
2588
2589 ac = 0;
2590 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
2591 XtSetArg (al[ac], XtNinput, 1); ac++;
97787173 2592 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
be786000 2593 XtSetArg (al[ac], XtNborderWidth, f->border_width); ac++;
9b2956e2
GM
2594 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2595 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
2596 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
cca176a0 2597 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
7a994728 2598 applicationShellWidgetClass,
82c90203 2599 FRAME_X_DISPLAY (f), al, ac);
9ef48a9d 2600
7556890b 2601 f->output_data.x->widget = shell_widget;
9ef48a9d
RS
2602 /* maybe_set_screen_title_format (shell_widget); */
2603
6c32dd68
PR
2604 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
2605 (widget_value *) NULL,
2606 shell_widget, False,
2607 (lw_callback) NULL,
2608 (lw_callback) NULL,
b6e11efd 2609 (lw_callback) NULL,
6c32dd68 2610 (lw_callback) NULL);
9ef48a9d 2611
9b2956e2
GM
2612 ac = 0;
2613 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2614 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
2615 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2616 XtSetValues (pane_widget, al, ac);
7556890b 2617 f->output_data.x->column_widget = pane_widget;
a7f7d550 2618
177c0ea7 2619 /* mappedWhenManaged to false tells to the paned window to not map/unmap
5e65b9ab 2620 the emacs screen when changing menubar. This reduces flickering. */
9ef48a9d
RS
2621
2622 ac = 0;
2623 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
2624 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
2625 XtSetArg (al[ac], XtNallowResize, 1); ac++;
2626 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
2627 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
9b2956e2
GM
2628 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2629 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
2630 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2631 frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget,
2632 al, ac);
177c0ea7 2633
7556890b 2634 f->output_data.x->edit_widget = frame_widget;
177c0ea7
JB
2635
2636 XtManageChild (frame_widget);
a7f7d550
FP
2637
2638 /* Do some needed geometry management. */
2639 {
2640 int len;
2641 char *tem, shell_position[32];
6b61353c 2642 Arg al[10];
a7f7d550 2643 int ac = 0;
5031cc10 2644 int extra_borders = 0;
177c0ea7 2645 int menubar_size
7556890b
RS
2646 = (f->output_data.x->menubar_widget
2647 ? (f->output_data.x->menubar_widget->core.height
2648 + f->output_data.x->menubar_widget->core.border_width)
8fc2766b 2649 : 0);
a7f7d550 2650
f7008aff
RS
2651#if 0 /* Experimentally, we now get the right results
2652 for -geometry -0-0 without this. 24 Aug 96, rms. */
01cbdba5
RS
2653 if (FRAME_EXTERNAL_MENU_BAR (f))
2654 {
dd254b21 2655 Dimension ibw = 0;
01cbdba5
RS
2656 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
2657 menubar_size += ibw;
2658 }
f7008aff 2659#endif
01cbdba5 2660
7556890b 2661 f->output_data.x->menubar_height = menubar_size;
00983aba 2662
440b0bfd 2663#ifndef USE_LUCID
5031cc10
KH
2664 /* Motif seems to need this amount added to the sizes
2665 specified for the shell widget. The Athena/Lucid widgets don't.
2666 Both conclusions reached experimentally. -- rms. */
440b0bfd
RS
2667 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
2668 &extra_borders, NULL);
2669 extra_borders *= 2;
2670#endif
5031cc10 2671
97787173
RS
2672 /* Convert our geometry parameters into a geometry string
2673 and specify it.
2674 Note that we do not specify here whether the position
2675 is a user-specified or program-specified one.
2676 We pass that information later, in x_wm_set_size_hints. */
2677 {
be786000 2678 int left = f->left_pos;
97787173 2679 int xneg = window_prompting & XNegative;
be786000 2680 int top = f->top_pos;
97787173
RS
2681 int yneg = window_prompting & YNegative;
2682 if (xneg)
2683 left = -left;
2684 if (yneg)
2685 top = -top;
c760f47e
KH
2686
2687 if (window_prompting & USPosition)
5031cc10 2688 sprintf (shell_position, "=%dx%d%c%d%c%d",
be786000
KS
2689 FRAME_PIXEL_WIDTH (f) + extra_borders,
2690 FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders,
c760f47e
KH
2691 (xneg ? '-' : '+'), left,
2692 (yneg ? '-' : '+'), top);
2693 else
6b61353c
KH
2694 {
2695 sprintf (shell_position, "=%dx%d",
2696 FRAME_PIXEL_WIDTH (f) + extra_borders,
2697 FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders);
2698
2699 /* Setting x and y when the position is not specified in
2700 the geometry string will set program position in the WM hints.
2701 If Emacs had just one program position, we could set it in
2702 fallback resources, but since each make-frame call can specify
2703 different program positions, this is easier. */
2704 XtSetArg (al[ac], XtNx, left); ac++;
2705 XtSetArg (al[ac], XtNy, top); ac++;
2706 }
97787173
RS
2707 }
2708
a7f7d550 2709 len = strlen (shell_position) + 1;
77110caa
RS
2710 /* We don't free this because we don't know whether
2711 it is safe to free it while the frame exists.
2712 It isn't worth the trouble of arranging to free it
2713 when the frame is deleted. */
a7f7d550
FP
2714 tem = (char *) xmalloc (len);
2715 strncpy (tem, shell_position, len);
2716 XtSetArg (al[ac], XtNgeometry, tem); ac++;
2717 XtSetValues (shell_widget, al, ac);
2718 }
2719
9ef48a9d
RS
2720 XtManageChild (pane_widget);
2721 XtRealizeWidget (shell_widget);
2722
2532f20c
JD
2723 if (FRAME_X_EMBEDDED_P (f))
2724 XReparentWindow (FRAME_X_DISPLAY (f), XtWindow (shell_widget),
2725 f->output_data.x->parent_desc, 0, 0);
2726
177c0ea7 2727 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
9ef48a9d
RS
2728
2729 validate_x_resource_name ();
b7975ee4 2730
d5db4077
KR
2731 class_hints.res_name = (char *) SDATA (Vx_resource_name);
2732 class_hints.res_class = (char *) SDATA (Vx_resource_class);
b9dc4443 2733 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
5a7df7d7
GM
2734
2735#ifdef HAVE_X_I18N
2736 FRAME_XIC (f) = NULL;
1576f1ad
DL
2737 if (use_xim)
2738 create_frame_xic (f);
5a7df7d7 2739#endif
64d16748 2740
7556890b
RS
2741 f->output_data.x->wm_hints.input = True;
2742 f->output_data.x->wm_hints.flags |= InputHint;
b9dc4443 2743 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 2744 &f->output_data.x->wm_hints);
b8228beb 2745
c4ec904f 2746 hack_wm_protocols (f, shell_widget);
9ef48a9d 2747
6c32dd68
PR
2748#ifdef HACK_EDITRES
2749 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
2750#endif
2751
9ef48a9d 2752 /* Do a stupid property change to force the server to generate a
333b20bb 2753 PropertyNotify event so that the event_stream server timestamp will
9ef48a9d
RS
2754 be initialized to something relevant to the time we created the window.
2755 */
6c32dd68 2756 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
b9dc4443
RS
2757 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
2758 XA_ATOM, 32, PropModeAppend,
9ef48a9d
RS
2759 (unsigned char*) NULL, 0);
2760
5a7df7d7 2761 /* Make all the standard events reach the Emacs frame. */
31ac8d8c 2762 attributes.event_mask = STANDARD_EVENT_SET;
5a7df7d7
GM
2763
2764#ifdef HAVE_X_I18N
2765 if (FRAME_XIC (f))
2766 {
2767 /* XIM server might require some X events. */
2768 unsigned long fevent = NoEventMask;
6b61353c 2769 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
5a7df7d7
GM
2770 attributes.event_mask |= fevent;
2771 }
2772#endif /* HAVE_X_I18N */
177c0ea7 2773
31ac8d8c
FP
2774 attribute_mask = CWEventMask;
2775 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
2776 attribute_mask, &attributes);
2777
6c32dd68 2778 XtMapWidget (frame_widget);
9ef48a9d 2779
8fc2766b
RS
2780 /* x_set_name normally ignores requests to set the name if the
2781 requested name is the same as the current name. This is the one
2782 place where that assumption isn't correct; f->name is set, but
2783 the X server hasn't been told. */
2784 {
2785 Lisp_Object name;
2786 int explicit = f->explicit_name;
2787
2788 f->explicit_name = 0;
2789 name = f->name;
2790 f->name = Qnil;
2791 x_set_name (f, name, explicit);
2792 }
2793
b9dc4443 2794 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 2795 f->output_data.x->text_cursor);
8fc2766b
RS
2796
2797 UNBLOCK_INPUT;
2798
495fa05e
GM
2799 /* This is a no-op, except under Motif. Make sure main areas are
2800 set to something reasonable, in case we get an error later. */
2801 lw_set_main_areas (pane_widget, 0, frame_widget);
8fc2766b
RS
2802}
2803
9ef48a9d 2804#else /* not USE_X_TOOLKIT */
488dd4c4
JD
2805#ifdef USE_GTK
2806void
2807x_window (f)
2808 FRAME_PTR f;
2809{
2810 if (! xg_create_frame_widgets (f))
2811 error ("Unable to create window");
1fcfb866
JD
2812
2813#ifdef HAVE_X_I18N
2814 FRAME_XIC (f) = NULL;
6b61353c 2815 if (use_xim)
1576f1ad
DL
2816 {
2817 BLOCK_INPUT;
2818 create_frame_xic (f);
2819 if (FRAME_XIC (f))
2820 {
2821 /* XIM server might require some X events. */
2822 unsigned long fevent = NoEventMask;
6b61353c 2823 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
1fcfb866 2824
1576f1ad
DL
2825 if (fevent != NoEventMask)
2826 {
2827 XSetWindowAttributes attributes;
2828 XWindowAttributes wattr;
2829 unsigned long attribute_mask;
2830
2831 XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2832 &wattr);
2833 attributes.event_mask = wattr.your_event_mask | fevent;
2834 attribute_mask = CWEventMask;
2835 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2836 attribute_mask, &attributes);
2837 }
2838 }
2839 UNBLOCK_INPUT;
2840 }
1fcfb866 2841#endif
488dd4c4 2842}
9ef48a9d 2843
488dd4c4 2844#else /*! USE_GTK */
8fc2766b
RS
2845/* Create and set up the X window for frame F. */
2846
201d8c78 2847void
8fc2766b
RS
2848x_window (f)
2849 struct frame *f;
2850
2851{
2852 XClassHint class_hints;
2853 XSetWindowAttributes attributes;
2854 unsigned long attribute_mask;
2855
5bcee7ef 2856 attributes.background_pixel = FRAME_BACKGROUND_PIXEL (f);
7556890b 2857 attributes.border_pixel = f->output_data.x->border_pixel;
01f1ba30
JB
2858 attributes.bit_gravity = StaticGravity;
2859 attributes.backing_store = NotUseful;
2860 attributes.save_under = True;
2861 attributes.event_mask = STANDARD_EVENT_SET;
9b2956e2
GM
2862 attributes.colormap = FRAME_X_COLORMAP (f);
2863 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
2864 | CWColormap);
01f1ba30
JB
2865
2866 BLOCK_INPUT;
fe24a618 2867 FRAME_X_WINDOW (f)
b9dc4443 2868 = XCreateWindow (FRAME_X_DISPLAY (f),
7556890b 2869 f->output_data.x->parent_desc,
be786000
KS
2870 f->left_pos,
2871 f->top_pos,
2872 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
2873 f->border_width,
01f1ba30
JB
2874 CopyFromParent, /* depth */
2875 InputOutput, /* class */
383d6ffc 2876 FRAME_X_VISUAL (f),
01f1ba30 2877 attribute_mask, &attributes);
5a7df7d7
GM
2878
2879#ifdef HAVE_X_I18N
4dacadcc 2880 if (use_xim)
5a7df7d7 2881 {
1576f1ad
DL
2882 create_frame_xic (f);
2883 if (FRAME_XIC (f))
2884 {
2885 /* XIM server might require some X events. */
2886 unsigned long fevent = NoEventMask;
6b61353c 2887 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
1576f1ad
DL
2888 attributes.event_mask |= fevent;
2889 attribute_mask = CWEventMask;
2890 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2891 attribute_mask, &attributes);
2892 }
5a7df7d7
GM
2893 }
2894#endif /* HAVE_X_I18N */
177c0ea7 2895
d387c960 2896 validate_x_resource_name ();
b7975ee4 2897
d5db4077
KR
2898 class_hints.res_name = (char *) SDATA (Vx_resource_name);
2899 class_hints.res_class = (char *) SDATA (Vx_resource_class);
b9dc4443 2900 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
01f1ba30 2901
00983aba
KH
2902 /* The menubar is part of the ordinary display;
2903 it does not count in addition to the height of the window. */
7556890b 2904 f->output_data.x->menubar_height = 0;
00983aba 2905
179956b9
JB
2906 /* This indicates that we use the "Passive Input" input model.
2907 Unless we do this, we don't get the Focus{In,Out} events that we
2908 need to draw the cursor correctly. Accursed bureaucrats.
b9dc4443 2909 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
179956b9 2910
7556890b
RS
2911 f->output_data.x->wm_hints.input = True;
2912 f->output_data.x->wm_hints.flags |= InputHint;
b9dc4443 2913 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 2914 &f->output_data.x->wm_hints);
6d078211 2915 f->output_data.x->wm_hints.icon_pixmap = None;
179956b9 2916
032e4ebe
RS
2917 /* Request "save yourself" and "delete window" commands from wm. */
2918 {
2919 Atom protocols[2];
b9dc4443
RS
2920 protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
2921 protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
2922 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
032e4ebe 2923 }
9ef48a9d 2924
e373f201
JB
2925 /* x_set_name normally ignores requests to set the name if the
2926 requested name is the same as the current name. This is the one
2927 place where that assumption isn't correct; f->name is set, but
2928 the X server hasn't been told. */
2929 {
98381190 2930 Lisp_Object name;
cf177271 2931 int explicit = f->explicit_name;
e373f201 2932
cf177271 2933 f->explicit_name = 0;
98381190
KH
2934 name = f->name;
2935 f->name = Qnil;
cf177271 2936 x_set_name (f, name, explicit);
e373f201
JB
2937 }
2938
b9dc4443 2939 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 2940 f->output_data.x->text_cursor);
9ef48a9d 2941
01f1ba30
JB
2942 UNBLOCK_INPUT;
2943
fe24a618 2944 if (FRAME_X_WINDOW (f) == 0)
9ef48a9d 2945 error ("Unable to create window");
01f1ba30
JB
2946}
2947
488dd4c4 2948#endif /* not USE_GTK */
8fc2766b
RS
2949#endif /* not USE_X_TOOLKIT */
2950
289978b5
LT
2951/* Verify that the icon position args for this window are valid. */
2952
2953static void
2954x_icon_verify (f, parms)
2955 struct frame *f;
2956 Lisp_Object parms;
2957{
2958 Lisp_Object icon_x, icon_y;
2959
2960 /* Set the position of the icon. Note that twm groups all
2961 icons in an icon window. */
2962 icon_x = x_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
2963 icon_y = x_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
2964 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
2965 {
2966 CHECK_NUMBER (icon_x);
2967 CHECK_NUMBER (icon_y);
2968 }
2969 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
2970 error ("Both left and top icon corners of icon must be specified");
2971}
2972
01f1ba30
JB
2973/* Handle the icon stuff for this window. Perhaps later we might
2974 want an x_set_icon_position which can be called interactively as
b9dc4443 2975 well. */
01f1ba30
JB
2976
2977static void
f676886a
JB
2978x_icon (f, parms)
2979 struct frame *f;
01f1ba30
JB
2980 Lisp_Object parms;
2981{
f9942c9e 2982 Lisp_Object icon_x, icon_y;
fd0f53a9 2983#if 0
abb4b7ec 2984 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
fd0f53a9 2985#endif
01f1ba30
JB
2986
2987 /* Set the position of the icon. Note that twm groups all
b9dc4443 2988 icons in an icon window. */
7c0d3ed8
KS
2989 icon_x = x_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
2990 icon_y = x_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
f9942c9e 2991 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
01f1ba30 2992 {
b7826503
PJ
2993 CHECK_NUMBER (icon_x);
2994 CHECK_NUMBER (icon_y);
01f1ba30 2995 }
f9942c9e 2996 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
01f1ba30 2997 error ("Both left and top icon corners of icon must be specified");
01f1ba30 2998
f9942c9e
JB
2999 BLOCK_INPUT;
3000
fe24a618
JB
3001 if (! EQ (icon_x, Qunbound))
3002 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
f9942c9e 3003
a9d54793
KL
3004#if 0 /* x_get_arg removes the visibility parameter as a side effect,
3005 but x_create_frame still needs it. */
01f1ba30 3006 /* Start up iconic or window? */
49795535 3007 x_wm_set_window_state
333b20bb
GM
3008 (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
3009 Qicon)
49795535
JB
3010 ? IconicState
3011 : NormalState));
a9d54793 3012#endif
01f1ba30 3013
d5db4077 3014 x_text_icon (f, (char *) SDATA ((!NILP (f->icon_name)
f468da95 3015 ? f->icon_name
d5db4077 3016 : f->name)));
80534dd6 3017
01f1ba30
JB
3018 UNBLOCK_INPUT;
3019}
3020
b243755a 3021/* Make the GCs needed for this window, setting the
01f1ba30
JB
3022 background, border and mouse colors; also create the
3023 mouse cursor and the gray border tile. */
3024
f945b920
JB
3025static char cursor_bits[] =
3026 {
3027 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3028 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3029 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3030 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3031 };
3032
01f1ba30 3033static void
f676886a
JB
3034x_make_gc (f)
3035 struct frame *f;
01f1ba30
JB
3036{
3037 XGCValues gc_values;
01f1ba30 3038
6afb1d07
JB
3039 BLOCK_INPUT;
3040
b243755a 3041 /* Create the GCs of this frame.
9ef48a9d 3042 Note that many default values are used. */
01f1ba30
JB
3043
3044 /* Normal video */
74170e38
KH
3045#ifdef USE_FONT_BACKEND
3046 if (enable_font_backend)
3047 gc_values.font = FRAME_X_DISPLAY_INFO (f)->font->fid;
3048 else
3049#endif
be786000 3050 gc_values.font = FRAME_FONT (f)->fid;
ce593f6e
KL
3051 gc_values.foreground = FRAME_FOREGROUND_PIXEL (f);
3052 gc_values.background = FRAME_BACKGROUND_PIXEL (f);
9ef48a9d 3053 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
959e647d
GM
3054 f->output_data.x->normal_gc
3055 = XCreateGC (FRAME_X_DISPLAY (f),
3056 FRAME_X_WINDOW (f),
3057 GCLineWidth | GCFont | GCForeground | GCBackground,
3058 &gc_values);
01f1ba30 3059
b9dc4443 3060 /* Reverse video style. */
ce593f6e
KL
3061 gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
3062 gc_values.background = FRAME_FOREGROUND_PIXEL (f);
959e647d
GM
3063 f->output_data.x->reverse_gc
3064 = XCreateGC (FRAME_X_DISPLAY (f),
3065 FRAME_X_WINDOW (f),
3066 GCFont | GCForeground | GCBackground | GCLineWidth,
3067 &gc_values);
01f1ba30 3068
9ef48a9d 3069 /* Cursor has cursor-color background, background-color foreground. */
ce593f6e 3070 gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
7556890b 3071 gc_values.background = f->output_data.x->cursor_pixel;
01f1ba30
JB
3072 gc_values.fill_style = FillOpaqueStippled;
3073 gc_values.stipple
b9dc4443
RS
3074 = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
3075 FRAME_X_DISPLAY_INFO (f)->root_window,
01f1ba30 3076 cursor_bits, 16, 16);
7556890b 3077 f->output_data.x->cursor_gc
b9dc4443 3078 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
01f1ba30 3079 (GCFont | GCForeground | GCBackground
ac1f48a4 3080 | GCFillStyle /* | GCStipple */ | GCLineWidth),
01f1ba30
JB
3081 &gc_values);
3082
333b20bb
GM
3083 /* Reliefs. */
3084 f->output_data.x->white_relief.gc = 0;
3085 f->output_data.x->black_relief.gc = 0;
3086
01f1ba30 3087 /* Create the gray border tile used when the pointer is not in
f676886a 3088 the frame. Since this depends on the frame's pixel values,
9ef48a9d 3089 this must be done on a per-frame basis. */
7556890b 3090 f->output_data.x->border_tile
d043f1a4 3091 = (XCreatePixmapFromBitmapData
177c0ea7 3092 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
d043f1a4 3093 gray_bits, gray_width, gray_height,
ce593f6e
KL
3094 FRAME_FOREGROUND_PIXEL (f),
3095 FRAME_BACKGROUND_PIXEL (f),
ab452f99 3096 DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
6afb1d07
JB
3097
3098 UNBLOCK_INPUT;
01f1ba30 3099}
01f1ba30 3100
959e647d
GM
3101
3102/* Free what was was allocated in x_make_gc. */
3103
3104void
3105x_free_gcs (f)
3106 struct frame *f;
3107{
3108 Display *dpy = FRAME_X_DISPLAY (f);
3109
3110 BLOCK_INPUT;
177c0ea7 3111
959e647d
GM
3112 if (f->output_data.x->normal_gc)
3113 {
3114 XFreeGC (dpy, f->output_data.x->normal_gc);
3115 f->output_data.x->normal_gc = 0;
3116 }
3117
3118 if (f->output_data.x->reverse_gc)
3119 {
3120 XFreeGC (dpy, f->output_data.x->reverse_gc);
3121 f->output_data.x->reverse_gc = 0;
3122 }
177c0ea7 3123
959e647d
GM
3124 if (f->output_data.x->cursor_gc)
3125 {
3126 XFreeGC (dpy, f->output_data.x->cursor_gc);
3127 f->output_data.x->cursor_gc = 0;
3128 }
3129
3130 if (f->output_data.x->border_tile)
3131 {
3132 XFreePixmap (dpy, f->output_data.x->border_tile);
3133 f->output_data.x->border_tile = 0;
3134 }
3135
3136 UNBLOCK_INPUT;
3137}
3138
3139
eaf1eea9
GM
3140/* Handler for signals raised during x_create_frame and
3141 x_create_top_frame. FRAME is the frame which is partially
3142 constructed. */
3143
3144static Lisp_Object
3145unwind_create_frame (frame)
3146 Lisp_Object frame;
3147{
3148 struct frame *f = XFRAME (frame);
3149
8346e08b
KL
3150 /* If frame is already dead, nothing to do. This can happen if the
3151 display is disconnected after the frame has become official, but
3152 before x_create_frame removes the unwind protect. */
3153 if (!FRAME_LIVE_P (f))
3154 return Qnil;
3155
eaf1eea9
GM
3156 /* If frame is ``official'', nothing to do. */
3157 if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
3158 {
f1d2ce7f 3159#if GLYPH_DEBUG
eaf1eea9
GM
3160 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3161#endif
177c0ea7 3162
eaf1eea9
GM
3163 x_free_frame_resources (f);
3164
5b3f8550 3165#if GLYPH_DEBUG
eaf1eea9
GM
3166 /* Check that reference counts are indeed correct. */
3167 xassert (dpyinfo->reference_count == dpyinfo_refcount);
3168 xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
5b3f8550 3169#endif
c844a81a 3170 return Qt;
eaf1eea9 3171 }
177c0ea7 3172
eaf1eea9
GM
3173 return Qnil;
3174}
3175
02ed2ea8
KH
3176#ifdef USE_FONT_BACKEND
3177static void
3178x_default_font_parameter (f, parms)
3179 struct frame *f;
3180 Lisp_Object parms;
3181{
3182 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3183 Lisp_Object font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font",
3184 RES_TYPE_STRING);
3185
3186 if (! STRINGP (font))
3187 {
3188 char *names[]
3189 = { "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1",
3190 "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1",
3191 "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1",
3192 /* This was formerly the first thing tried, but it finds
3193 too many fonts and takes too long. */
3194 "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1",
3195 /* If those didn't work, look for something which will
3196 at least work. */
3197 "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1",
25c25256 3198 "fixed",
02ed2ea8
KH
3199 NULL };
3200 int i;
3201
3202 for (i = 0; names[i]; i++)
3203 {
3204 font = font_open_by_name (f, names[i]);
3205 if (! NILP (font))
3206 break;
3207 }
3208 if (NILP (font))
25c25256 3209 error ("No suitable font was found");
02ed2ea8
KH
3210 }
3211 x_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING);
3212}
3213#endif /* USE_FONT_BACKEND */
eaf1eea9 3214
f676886a 3215DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
01f1ba30 3216 1, 1, 0,
7ee72033 3217 doc: /* Make a new X window, which is called a "frame" in Emacs terms.
d29a9848 3218Return an Emacs frame object.
c061c855
GM
3219ALIST is an alist of frame parameters.
3220If the parameters specify that the frame should not have a minibuffer,
3221and do not specify a specific minibuffer window to use,
3222then `default-minibuffer-frame' must be a frame whose minibuffer can
3223be shared by the new frame.
3224
7ee72033
MB
3225This function is an internal primitive--use `make-frame' instead. */)
3226 (parms)
01f1ba30
JB
3227 Lisp_Object parms;
3228{
f676886a 3229 struct frame *f;
2365c027 3230 Lisp_Object frame, tem;
01f1ba30
JB
3231 Lisp_Object name;
3232 int minibuffer_only = 0;
3233 long window_prompting = 0;
3234 int width, height;
331379bf 3235 int count = SPECPDL_INDEX ();
ecaca587 3236 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
b9dc4443 3237 Lisp_Object display;
333b20bb 3238 struct x_display_info *dpyinfo = NULL;
a59e4f3d 3239 Lisp_Object parent;
e557f19d 3240 struct kboard *kb;
01f1ba30 3241
5fa98fcf
RS
3242 parms = Fcopy_alist (parms);
3243
b7975ee4
KH
3244 /* Use this general default value to start with
3245 until we know if this frame has a specified name. */
3246 Vx_resource_name = Vinvocation_name;
3247
6ed8eeff 3248 display = x_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_NUMBER);
1705c933 3249 if (EQ (display, Qunbound))
b6660415 3250 display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
b9dc4443
RS
3251 if (EQ (display, Qunbound))
3252 display = Qnil;
3253 dpyinfo = check_x_display_info (display);
e557f19d 3254#ifdef MULTI_KBOARD
6ed8eeff 3255 kb = dpyinfo->terminal->kboard;
e557f19d
KH
3256#else
3257 kb = &the_only_kboard;
3258#endif
b9dc4443 3259
89acb56d
SM
3260 if (!dpyinfo->terminal->name)
3261 error ("Terminal is not live, can't create new frames on it");
ab797f65 3262
333b20bb 3263 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
6a5e54e2 3264 if (!STRINGP (name)
cf177271
JB
3265 && ! EQ (name, Qunbound)
3266 && ! NILP (name))
08a90d6a 3267 error ("Invalid frame name--not a string or nil");
01f1ba30 3268
b7975ee4
KH
3269 if (STRINGP (name))
3270 Vx_resource_name = name;
3271
a59e4f3d 3272 /* See if parent window is specified. */
333b20bb 3273 parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
a59e4f3d
RS
3274 if (EQ (parent, Qunbound))
3275 parent = Qnil;
3276 if (! NILP (parent))
b7826503 3277 CHECK_NUMBER (parent);
a59e4f3d 3278
ecaca587
RS
3279 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
3280 /* No need to protect DISPLAY because that's not used after passing
3281 it to make_frame_without_minibuffer. */
3282 frame = Qnil;
3283 GCPRO4 (parms, parent, name, frame);
333b20bb
GM
3284 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
3285 RES_TYPE_SYMBOL);
f9942c9e 3286 if (EQ (tem, Qnone) || NILP (tem))
2526c290 3287 f = make_frame_without_minibuffer (Qnil, kb, display);
f9942c9e 3288 else if (EQ (tem, Qonly))
01f1ba30 3289 {
f676886a 3290 f = make_minibuffer_frame ();
01f1ba30
JB
3291 minibuffer_only = 1;
3292 }
6a5e54e2 3293 else if (WINDOWP (tem))
2526c290 3294 f = make_frame_without_minibuffer (tem, kb, display);
f9942c9e
JB
3295 else
3296 f = make_frame (1);
01f1ba30 3297
ecaca587
RS
3298 XSETFRAME (frame, f);
3299
a3c87d4e
JB
3300 /* Note that X Windows does support scroll bars. */
3301 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
179956b9 3302
6ed8eeff
KL
3303 f->terminal = dpyinfo->terminal;
3304 f->terminal->reference_count++;
428a555e 3305
08a90d6a 3306 f->output_method = output_x_window;
7556890b
RS
3307 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
3308 bzero (f->output_data.x, sizeof (struct x_output));
3309 f->output_data.x->icon_bitmap = -1;
be786000 3310 FRAME_FONTSET (f) = -1;
333b20bb
GM
3311 f->output_data.x->scroll_bar_foreground_pixel = -1;
3312 f->output_data.x->scroll_bar_background_pixel = -1;
f15340b7
MB
3313#ifdef USE_TOOLKIT_SCROLL_BARS
3314 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
3315 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
3316#endif /* USE_TOOLKIT_SCROLL_BARS */
08a90d6a 3317
f468da95 3318 f->icon_name
333b20bb
GM
3319 = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
3320 RES_TYPE_STRING);
f468da95
RS
3321 if (! STRINGP (f->icon_name))
3322 f->icon_name = Qnil;
80534dd6 3323
08a90d6a 3324 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
e3d56613
RS
3325
3326 /* With FRAME_X_DISPLAY_INFO set up, this unwind-protect is safe. */
3327 record_unwind_protect (unwind_create_frame, frame);
f1d2ce7f 3328#if GLYPH_DEBUG
354884c4 3329 image_cache_refcount = FRAME_IMAGE_CACHE (f)->refcount;
eaf1eea9
GM
3330 dpyinfo_refcount = dpyinfo->reference_count;
3331#endif /* GLYPH_DEBUG */
08a90d6a 3332
9b2956e2
GM
3333 /* These colors will be set anyway later, but it's important
3334 to get the color reference counts right, so initialize them! */
3335 {
3336 Lisp_Object black;
3337 struct gcpro gcpro1;
cefecbcf
GM
3338
3339 /* Function x_decode_color can signal an error. Make
3340 sure to initialize color slots so that we won't try
3341 to free colors we haven't allocated. */
ce593f6e
KL
3342 FRAME_FOREGROUND_PIXEL (f) = -1;
3343 FRAME_BACKGROUND_PIXEL (f) = -1;
cefecbcf
GM
3344 f->output_data.x->cursor_pixel = -1;
3345 f->output_data.x->cursor_foreground_pixel = -1;
3346 f->output_data.x->border_pixel = -1;
3347 f->output_data.x->mouse_pixel = -1;
177c0ea7 3348
9b2956e2
GM
3349 black = build_string ("black");
3350 GCPRO1 (black);
ce593f6e 3351 FRAME_FOREGROUND_PIXEL (f)
9b2956e2 3352 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
ce593f6e 3353 FRAME_BACKGROUND_PIXEL (f)
9b2956e2
GM
3354 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3355 f->output_data.x->cursor_pixel
3356 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3357 f->output_data.x->cursor_foreground_pixel
3358 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3359 f->output_data.x->border_pixel
3360 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3361 f->output_data.x->mouse_pixel
3362 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3363 UNGCPRO;
3364 }
3365
a59e4f3d
RS
3366 /* Specify the parent under which to make this X window. */
3367
3368 if (!NILP (parent))
3369 {
8c239ac3 3370 f->output_data.x->parent_desc = (Window) XFASTINT (parent);
7556890b 3371 f->output_data.x->explicit_parent = 1;
a59e4f3d
RS
3372 }
3373 else
3374 {
7556890b
RS
3375 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
3376 f->output_data.x->explicit_parent = 0;
a59e4f3d
RS
3377 }
3378
cf177271
JB
3379 /* Set the name; the functions to which we pass f expect the name to
3380 be set. */
3381 if (EQ (name, Qunbound) || NILP (name))
3382 {
08a90d6a 3383 f->name = build_string (dpyinfo->x_id_name);
cf177271
JB
3384 f->explicit_name = 0;
3385 }
3386 else
3387 {
3388 f->name = name;
3389 f->explicit_name = 1;
9ef48a9d
RS
3390 /* use the frame's title when getting resources for this frame. */
3391 specbind (Qx_resource_name, name);
cf177271 3392 }
01f1ba30 3393
02ed2ea8
KH
3394 f->resx = dpyinfo->resx;
3395 f->resy = dpyinfo->resy;
3396
3397#ifdef USE_FONT_BACKEND
3398 if (enable_font_backend)
3399 {
3400 /* Perhaps, we must allow frame parameter, say `font-backend',
3401 to specify which font backends to use. */
3402#ifdef HAVE_FREETYPE
3403#ifdef HAVE_XFT
3404 register_font_driver (&xftfont_driver, f);
3405#else /* not HAVE_XFT */
3406 register_font_driver (&ftxfont_driver, f);
3407#endif /* not HAVE_XFT */
3408#endif /* HAVE_FREETYPE */
3409 register_font_driver (&xfont_driver, f);
297cc20a
KH
3410
3411 x_default_parameter (f, parms, Qfont_backend, Qnil,
3412 "fontBackend", "FontBackend", RES_TYPE_STRING);
02ed2ea8
KH
3413 }
3414#endif /* USE_FONT_BACKEND */
3415
01f1ba30
JB
3416 /* Extract the window parameters from the supplied values
3417 that are needed to determine window geometry. */
02ed2ea8
KH
3418#ifdef USE_FONT_BACKEND
3419 if (enable_font_backend)
3420 x_default_font_parameter (f, parms);
3421else
3422#endif /* USE_FONT_BACKEND */
d387c960
JB
3423 {
3424 Lisp_Object font;
3425
333b20bb 3426 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
2ee3abaa 3427
7fb92cb1
KH
3428 /* If the caller has specified no font, try out fonts which we
3429 hope have bold and italic variations. */
e5e548e3 3430 if (!STRINGP (font))
7fb92cb1
KH
3431 {
3432 char *names[]
3433 = { "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1",
3434 "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1",
3435 "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1",
3436 /* This was formerly the first thing tried, but it finds
3437 too many fonts and takes too long. */
3438 "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1",
3439 /* If those didn't work, look for something which will
3440 at least work. */
3441 "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1",
3442 NULL };
3443 int i;
3444
3445 BLOCK_INPUT;
3446 for (i = 0; names[i]; i++)
3447 {
3448 Lisp_Object list;
e5e548e3 3449
7fb92cb1
KH
3450 list = x_list_fonts (f, build_string (names[i]), 0, 1);
3451 if (CONSP (list))
3452 {
3453 font = XCAR (list);
3454 break;
3455 }
3456 }
3457 UNBLOCK_INPUT;
3458 if (! STRINGP (font))
3459 font = build_string ("fixed");
3460 }
477f8642 3461 x_default_parameter (f, parms, Qfont, font,
333b20bb 3462 "font", "Font", RES_TYPE_STRING);
d387c960 3463 }
9ef48a9d 3464
e3881aa0 3465#ifdef USE_LUCID
82c90203
RS
3466 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
3467 whereby it fails to get any font. */
be786000 3468 xlwmenu_default_font = FRAME_FONT (f);
dd254b21 3469#endif
82c90203 3470
2532f20c
JD
3471 /* Frame contents get displaced if an embedded X window has a border. */
3472 if (! FRAME_X_EMBEDDED_P (f))
3473 x_default_parameter (f, parms, Qborder_width, make_number (2),
3474 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
177c0ea7 3475
4e397688 3476 /* This defaults to 1 in order to match xterm. We recognize either
ddf768c3
JB
3477 internalBorderWidth or internalBorder (which is what xterm calls
3478 it). */
3479 if (NILP (Fassq (Qinternal_border_width, parms)))
3480 {
3481 Lisp_Object value;
3482
abb4b7ec 3483 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
333b20bb 3484 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
ddf768c3
JB
3485 if (! EQ (value, Qunbound))
3486 parms = Fcons (Fcons (Qinternal_border_width, value),
3487 parms);
3488 }
dca97592 3489 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
333b20bb
GM
3490 "internalBorderWidth", "internalBorderWidth",
3491 RES_TYPE_NUMBER);
1ab3d87e 3492 x_default_parameter (f, parms, Qvertical_scroll_bars, Qleft,
333b20bb
GM
3493 "verticalScrollBars", "ScrollBars",
3494 RES_TYPE_SYMBOL);
01f1ba30 3495
b9dc4443 3496 /* Also do the stuff which must be set before the window exists. */
cf177271 3497 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
333b20bb 3498 "foreground", "Foreground", RES_TYPE_STRING);
cf177271 3499 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
0b60fc91 3500 "background", "Background", RES_TYPE_STRING);
cf177271 3501 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
333b20bb 3502 "pointerColor", "Foreground", RES_TYPE_STRING);
cf177271 3503 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
333b20bb 3504 "cursorColor", "Foreground", RES_TYPE_STRING);
cf177271 3505 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
333b20bb 3506 "borderColor", "BorderColor", RES_TYPE_STRING);
d62c8769
GM
3507 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
3508 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
563b67aa
GM
3509 x_default_parameter (f, parms, Qline_spacing, Qnil,
3510 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
b3ba0aa8
KS
3511 x_default_parameter (f, parms, Qleft_fringe, Qnil,
3512 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
3513 x_default_parameter (f, parms, Qright_fringe, Qnil,
3514 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
333b20bb
GM
3515
3516 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
3517 "scrollBarForeground",
3518 "ScrollBarForeground", 1);
3519 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
3520 "scrollBarBackground",
3521 "ScrollBarBackground", 0);
3522
3523 /* Init faces before x_default_parameter is called for scroll-bar
3524 parameters because that function calls x_set_scroll_bar_width,
3525 which calls change_frame_size, which calls Fset_window_buffer,
3526 which runs hooks, which call Fvertical_motion. At the end, we
3527 end up in init_iterator with a null face cache, which should not
3528 happen. */
3529 init_frame_faces (f);
177c0ea7 3530
c7bcb20d 3531 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
333b20bb 3532 "menuBar", "MenuBar", RES_TYPE_NUMBER);
e33455ca 3533 x_default_parameter (f, parms, Qtool_bar_lines, make_number (1),
333b20bb 3534 "toolBar", "ToolBar", RES_TYPE_NUMBER);
79873d50 3535 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
333b20bb
GM
3536 "bufferPredicate", "BufferPredicate",
3537 RES_TYPE_SYMBOL);
c2304e02 3538 x_default_parameter (f, parms, Qtitle, Qnil,
333b20bb 3539 "title", "Title", RES_TYPE_STRING);
ea0a1f53
GM
3540 x_default_parameter (f, parms, Qwait_for_wm, Qt,
3541 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
49d41073
EZ
3542 x_default_parameter (f, parms, Qfullscreen, Qnil,
3543 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
90eb1019 3544
35f59f6b 3545 /* Compute the size of the X window. */
7c0d3ed8 3546 window_prompting = x_figure_window_size (f, parms, 1);
38d22040 3547
495fa05e
GM
3548 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
3549 f->no_split = minibuffer_only || EQ (tem, Qt);
3550
289978b5
LT
3551 x_icon_verify (f, parms);
3552
6a1bcd01 3553 /* Create the X widget or window. */
a7f7d550
FP
3554#ifdef USE_X_TOOLKIT
3555 x_window (f, window_prompting, minibuffer_only);
3556#else
f676886a 3557 x_window (f);
a7f7d550 3558#endif
177c0ea7 3559
f676886a
JB
3560 x_icon (f, parms);
3561 x_make_gc (f);
01f1ba30 3562
495fa05e
GM
3563 /* Now consider the frame official. */
3564 FRAME_X_DISPLAY_INFO (f)->reference_count++;
3565 Vframe_list = Fcons (frame, Vframe_list);
3566
f9942c9e
JB
3567 /* We need to do this after creating the X window, so that the
3568 icon-creation functions can say whose icon they're describing. */
84f25880 3569 x_default_parameter (f, parms, Qicon_type, Qt,
333b20bb 3570 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
f9942c9e 3571
cf177271 3572 x_default_parameter (f, parms, Qauto_raise, Qnil,
333b20bb 3573 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
cf177271 3574 x_default_parameter (f, parms, Qauto_lower, Qnil,
333b20bb 3575 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
dbc4e1c1 3576 x_default_parameter (f, parms, Qcursor_type, Qbox,
333b20bb 3577 "cursorType", "CursorType", RES_TYPE_SYMBOL);
28d7281d
GM
3578 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
3579 "scrollBarWidth", "ScrollBarWidth",
3580 RES_TYPE_NUMBER);
f9942c9e 3581
be786000 3582 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
01f1ba30 3583 Change will not be effected unless different from the current
be786000
KS
3584 FRAME_LINES (f). */
3585 width = FRAME_COLS (f);
3586 height = FRAME_LINES (f);
177c0ea7 3587
be786000
KS
3588 SET_FRAME_COLS (f, 0);
3589 FRAME_LINES (f) = 0;
8938a4fb 3590 change_frame_size (f, height, width, 1, 0, 0);
d043f1a4 3591
488dd4c4 3592#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
495fa05e
GM
3593 /* Create the menu bar. */
3594 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
3595 {
3596 /* If this signals an error, we haven't set size hints for the
3597 frame and we didn't make it visible. */
3598 initialize_frame_menubar (f);
3599
488dd4c4 3600#ifndef USE_GTK
495fa05e
GM
3601 /* This is a no-op, except under Motif where it arranges the
3602 main window for the widgets on it. */
3603 lw_set_main_areas (f->output_data.x->column_widget,
3604 f->output_data.x->menubar_widget,
3605 f->output_data.x->edit_widget);
488dd4c4 3606#endif /* not USE_GTK */
495fa05e 3607 }
488dd4c4 3608#endif /* USE_X_TOOLKIT || USE_GTK */
495fa05e
GM
3609
3610 /* Tell the server what size and position, etc, we want, and how
3611 badly we want them. This should be done after we have the menu
3612 bar so that its size can be taken into account. */
01f1ba30 3613 BLOCK_INPUT;
7989f084 3614 x_wm_set_size_hint (f, window_prompting, 0);
01f1ba30
JB
3615 UNBLOCK_INPUT;
3616
495fa05e
GM
3617 /* Make the window appear on the frame and enable display, unless
3618 the caller says not to. However, with explicit parent, Emacs
3619 cannot control visibility, so don't try. */
7556890b 3620 if (! f->output_data.x->explicit_parent)
a59e4f3d
RS
3621 {
3622 Lisp_Object visibility;
49795535 3623
333b20bb
GM
3624 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
3625 RES_TYPE_SYMBOL);
a59e4f3d
RS
3626 if (EQ (visibility, Qunbound))
3627 visibility = Qt;
49795535 3628
a59e4f3d
RS
3629 if (EQ (visibility, Qicon))
3630 x_iconify_frame (f);
3631 else if (! NILP (visibility))
3632 x_make_frame_visible (f);
3633 else
3634 /* Must have been Qnil. */
3635 ;
3636 }
01f1ba30 3637
6b61353c
KH
3638 /* Set the WM leader property. GTK does this itself, so this is not
3639 needed when using GTK. */
3640 if (dpyinfo->client_leader_window != 0)
3641 {
3642 BLOCK_INPUT;
3643 XChangeProperty (FRAME_X_DISPLAY (f),
3644 FRAME_OUTER_WINDOW (f),
3645 dpyinfo->Xatom_wm_client_leader,
3646 XA_WINDOW, 32, PropModeReplace,
47c53789 3647 (unsigned char *) &dpyinfo->client_leader_window, 1);
6b61353c
KH
3648 UNBLOCK_INPUT;
3649 }
3650
225c13a5 3651 /* Initialize `default-minibuffer-frame' in case this is the first
6ed8eeff 3652 frame on this terminal. */
225c13a5
KL
3653 if (FRAME_HAS_MINIBUF_P (f)
3654 && (!FRAMEP (kb->Vdefault_minibuffer_frame)
3655 || !FRAME_LIVE_P (XFRAME (kb->Vdefault_minibuffer_frame))))
3656 kb->Vdefault_minibuffer_frame = frame;
3657
5fa98fcf
RS
3658 /* All remaining specified parameters, which have not been "used"
3659 by x_get_arg and friends, now go in the misc. alist of the frame. */
9beb8baa 3660 for (tem = parms; CONSP (tem); tem = XCDR (tem))
5fa98fcf
RS
3661 if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
3662 f->param_alist = Fcons (XCAR (tem), f->param_alist);
3663
495fa05e 3664 UNGCPRO;
9e57df62
GM
3665
3666 /* Make sure windows on this frame appear in calls to next-window
3667 and similar functions. */
3668 Vwindow_list = Qnil;
177c0ea7 3669
9ef48a9d 3670 return unbind_to (count, frame);
01f1ba30
JB
3671}
3672
eaf1eea9 3673
0d17d282
KH
3674/* FRAME is used only to get a handle on the X display. We don't pass the
3675 display info directly because we're called from frame.c, which doesn't
3676 know about that structure. */
e4f79258 3677
87498171 3678Lisp_Object
0d17d282
KH
3679x_get_focus_frame (frame)
3680 struct frame *frame;
87498171 3681{
0d17d282 3682 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
87498171 3683 Lisp_Object xfocus;
0d17d282 3684 if (! dpyinfo->x_focus_frame)
87498171
KH
3685 return Qnil;
3686
0d17d282 3687 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
87498171
KH
3688 return xfocus;
3689}
f0614854 3690
3decc1e7
GM
3691
3692/* In certain situations, when the window manager follows a
3693 click-to-focus policy, there seems to be no way around calling
3694 XSetInputFocus to give another frame the input focus .
3695
3696 In an ideal world, XSetInputFocus should generally be avoided so
3697 that applications don't interfere with the window manager's focus
3698 policy. But I think it's okay to use when it's clearly done
3699 following a user-command. */
3700
3701DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
7ee72033
MB
3702 doc: /* Set the input focus to FRAME.
3703FRAME nil means use the selected frame. */)
3704 (frame)
3decc1e7
GM
3705 Lisp_Object frame;
3706{
3707 struct frame *f = check_x_frame (frame);
3708 Display *dpy = FRAME_X_DISPLAY (f);
3decc1e7
GM
3709
3710 BLOCK_INPUT;
9ba8e10d 3711 x_catch_errors (dpy);
3decc1e7
GM
3712 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3713 RevertToParent, CurrentTime);
457a6b0a 3714 x_ewmh_activate_frame (f);
4545fa20 3715 x_uncatch_errors ();
3decc1e7 3716 UNBLOCK_INPUT;
177c0ea7 3717
3decc1e7
GM
3718 return Qnil;
3719}
3720
f0614854 3721\f
2d764c78 3722DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
7ee72033
MB
3723 doc: /* Internal function called by `color-defined-p', which see. */)
3724 (color, frame)
b9dc4443 3725 Lisp_Object color, frame;
e12d55b2 3726{
b9dc4443
RS
3727 XColor foo;
3728 FRAME_PTR f = check_x_frame (frame);
e12d55b2 3729
b7826503 3730 CHECK_STRING (color);
b9dc4443 3731
d5db4077 3732 if (x_defined_color (f, SDATA (color), &foo, 0))
e12d55b2
RS
3733 return Qt;
3734 else
3735 return Qnil;
3736}
3737
2d764c78 3738DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
7ee72033
MB
3739 doc: /* Internal function called by `color-values', which see. */)
3740 (color, frame)
b9dc4443 3741 Lisp_Object color, frame;
01f1ba30 3742{
b9dc4443
RS
3743 XColor foo;
3744 FRAME_PTR f = check_x_frame (frame);
3745
b7826503 3746 CHECK_STRING (color);
01f1ba30 3747
d5db4077 3748 if (x_defined_color (f, SDATA (color), &foo, 0))
a508663b
KS
3749 return list3 (make_number (foo.red),
3750 make_number (foo.green),
3751 make_number (foo.blue));
01f1ba30
JB
3752 else
3753 return Qnil;
3754}
3755
2d764c78 3756DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
7ee72033 3757 doc: /* Internal function called by `display-color-p', which see. */)
6ed8eeff
KL
3758 (terminal)
3759 Lisp_Object terminal;
01f1ba30 3760{
6ed8eeff 3761 struct x_display_info *dpyinfo = check_x_display_info (terminal);
11ae94fe 3762
b9dc4443 3763 if (dpyinfo->n_planes <= 2)
01f1ba30
JB
3764 return Qnil;
3765
b9dc4443 3766 switch (dpyinfo->visual->class)
01f1ba30
JB
3767 {
3768 case StaticColor:
3769 case PseudoColor:
3770 case TrueColor:
3771 case DirectColor:
3772 return Qt;
3773
3774 default:
3775 return Qnil;
3776 }
3777}
3778
d0c9d219 3779DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
c061c855 3780 0, 1, 0,
7ee72033 3781 doc: /* Return t if the X display supports shades of gray.
c061c855 3782Note that color displays do support shades of gray.
6ed8eeff
KL
3783The optional argument TERMINAL specifies which display to ask about.
3784TERMINAL should be a terminal id, a frame or a display name (a string).
7ee72033 3785If omitted or nil, that stands for the selected frame's display. */)
6ed8eeff
KL
3786 (terminal)
3787 Lisp_Object terminal;
d0c9d219 3788{
6ed8eeff 3789 struct x_display_info *dpyinfo = check_x_display_info (terminal);
d0c9d219 3790
ae6b58f9 3791 if (dpyinfo->n_planes <= 1)
b9dc4443
RS
3792 return Qnil;
3793
ae6b58f9
RS
3794 switch (dpyinfo->visual->class)
3795 {
3796 case StaticColor:
3797 case PseudoColor:
3798 case TrueColor:
3799 case DirectColor:
3800 case StaticGray:
3801 case GrayScale:
3802 return Qt;
3803
3804 default:
3805 return Qnil;
3806 }
d0c9d219
RS
3807}
3808
41beb8fc 3809DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
c061c855 3810 0, 1, 0,
d29a9848 3811 doc: /* Return the width in pixels of the X display TERMINAL.
6ed8eeff
KL
3812The optional argument TERMINAL specifies which display to ask about.
3813TERMINAL should be a terminal id, a frame or a display name (a string).
7ee72033 3814If omitted or nil, that stands for the selected frame's display. */)
6ed8eeff
KL
3815 (terminal)
3816 Lisp_Object terminal;
41beb8fc 3817{
6ed8eeff 3818 struct x_display_info *dpyinfo = check_x_display_info (terminal);
b9dc4443
RS
3819
3820 return make_number (dpyinfo->width);
41beb8fc
RS
3821}
3822
3823DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
c061c855 3824 Sx_display_pixel_height, 0, 1, 0,
d29a9848 3825 doc: /* Return the height in pixels of the X display TERMINAL.
6ed8eeff
KL
3826The optional argument TERMINAL specifies which display to ask about.
3827TERMINAL should be a terminal id, a frame or a display name (a string).
7ee72033 3828If omitted or nil, that stands for the selected frame's display. */)
6ed8eeff
KL
3829 (terminal)
3830 Lisp_Object terminal;
41beb8fc 3831{
6ed8eeff 3832 struct x_display_info *dpyinfo = check_x_display_info (terminal);
b9dc4443
RS
3833
3834 return make_number (dpyinfo->height);
41beb8fc
RS
3835}
3836
3837DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
c061c855 3838 0, 1, 0,
d29a9848 3839 doc: /* Return the number of bitplanes of the X display TERMINAL.
6ed8eeff
KL
3840The optional argument TERMINAL specifies which display to ask about.
3841TERMINAL should be a terminal id, a frame or a display name (a string).
7ee72033 3842If omitted or nil, that stands for the selected frame's display. */)
6ed8eeff
KL
3843 (terminal)
3844 Lisp_Object terminal;
41beb8fc 3845{
6ed8eeff 3846 struct x_display_info *dpyinfo = check_x_display_info (terminal);
b9dc4443
RS
3847
3848 return make_number (dpyinfo->n_planes);
41beb8fc
RS
3849}
3850
3851DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
c061c855 3852 0, 1, 0,
d29a9848 3853 doc: /* Return the number of color cells of the X display TERMINAL.
6ed8eeff
KL
3854The optional argument TERMINAL specifies which display to ask about.
3855TERMINAL should be a terminal id, a frame or a display name (a string).
7ee72033 3856If omitted or nil, that stands for the selected frame's display. */)
6ed8eeff
KL
3857 (terminal)
3858 Lisp_Object terminal;
41beb8fc 3859{
6ed8eeff 3860 struct x_display_info *dpyinfo = check_x_display_info (terminal);
b9dc4443 3861
6b61353c
KH
3862 int nr_planes = DisplayPlanes (dpyinfo->display,
3863 XScreenNumberOfScreen (dpyinfo->screen));
3864
3865 /* Truncate nr_planes to 24 to avoid integer overflow.
3866 Some displays says 32, but only 24 bits are actually significant.
3867 There are only very few and rare video cards that have more than
3868 24 significant bits. Also 24 bits is more than 16 million colors,
3869 it "should be enough for everyone". */
3870 if (nr_planes > 24) nr_planes = 24;
3871
3872 return make_number (1 << nr_planes);
41beb8fc
RS
3873}
3874
9d317b2c
RS
3875DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
3876 Sx_server_max_request_size,
c061c855 3877 0, 1, 0,
d29a9848 3878 doc: /* Return the maximum request size of the X server of display TERMINAL.
6ed8eeff
KL
3879The optional argument TERMINAL specifies which display to ask about.
3880TERMINAL should be a terminal id, a frame or a display name (a string).
7ee72033 3881If omitted or nil, that stands for the selected frame's display. */)
6ed8eeff
KL
3882 (terminal)
3883 Lisp_Object terminal;
9d317b2c 3884{
6ed8eeff 3885 struct x_display_info *dpyinfo = check_x_display_info (terminal);
b9dc4443
RS
3886
3887 return make_number (MAXREQUEST (dpyinfo->display));
9d317b2c
RS
3888}
3889
41beb8fc 3890DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
d29a9848 3891 doc: /* Return the "vendor ID" string of the X server of display TERMINAL.
95d62d8a
RS
3892\(Labelling every distributor as a "vendor" embodies the false assumption
3893that operating systems cannot be developed and distributed noncommercially.)
6ed8eeff
KL
3894The optional argument TERMINAL specifies which display to ask about.
3895TERMINAL should be a terminal id, a frame or a display name (a string).
7ee72033 3896If omitted or nil, that stands for the selected frame's display. */)
6ed8eeff
KL
3897 (terminal)
3898 Lisp_Object terminal;
41beb8fc 3899{
6ed8eeff 3900 struct x_display_info *dpyinfo = check_x_display_info (terminal);
b9dc4443
RS
3901 char *vendor = ServerVendor (dpyinfo->display);
3902
41beb8fc
RS
3903 if (! vendor) vendor = "";
3904 return build_string (vendor);
3905}
3906
3907DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
d29a9848 3908 doc: /* Return the version numbers of the X server of display TERMINAL.
c061c855 3909The value is a list of three integers: the major and minor
95d62d8a 3910version numbers of the X Protocol in use, and the distributor-specific release
c061c855
GM
3911number. See also the function `x-server-vendor'.
3912
6ed8eeff
KL
3913The optional argument TERMINAL specifies which display to ask about.
3914TERMINAL should be a terminal id, a frame or a display name (a string).
7ee72033 3915If omitted or nil, that stands for the selected frame's display. */)
6ed8eeff
KL
3916 (terminal)
3917 Lisp_Object terminal;
41beb8fc 3918{
6ed8eeff 3919 struct x_display_info *dpyinfo = check_x_display_info (terminal);
b9dc4443 3920 Display *dpy = dpyinfo->display;
11ae94fe 3921
41beb8fc
RS
3922 return Fcons (make_number (ProtocolVersion (dpy)),
3923 Fcons (make_number (ProtocolRevision (dpy)),
3924 Fcons (make_number (VendorRelease (dpy)), Qnil)));
3925}
3926
3927DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
6ed8eeff
KL
3928 doc: /* Return the number of screens on the X server of display TERMINAL.
3929The optional argument TERMINAL specifies which display to ask about.
3930TERMINAL should be a terminal id, a frame or a display name (a string).
7ee72033 3931If omitted or nil, that stands for the selected frame's display. */)
6ed8eeff
KL
3932 (terminal)
3933 Lisp_Object terminal;
41beb8fc 3934{
6ed8eeff 3935 struct x_display_info *dpyinfo = check_x_display_info (terminal);
b9dc4443
RS
3936
3937 return make_number (ScreenCount (dpyinfo->display));
41beb8fc
RS
3938}
3939
3940DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
6ed8eeff
KL
3941 doc: /* Return the height in millimeters of the X display TERMINAL.
3942The optional argument TERMINAL specifies which display to ask about.
3943TERMINAL should be a terminal id, a frame or a display name (a string).
7ee72033 3944If omitted or nil, that stands for the selected frame's display. */)
6ed8eeff
KL
3945 (terminal)
3946 Lisp_Object terminal;
41beb8fc 3947{
6ed8eeff 3948 struct x_display_info *dpyinfo = check_x_display_info (terminal);
b9dc4443
RS
3949
3950 return make_number (HeightMMOfScreen (dpyinfo->screen));
41beb8fc
RS
3951}
3952
3953DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
6ed8eeff
KL
3954 doc: /* Return the width in millimeters of the X display TERMINAL.
3955The optional argument TERMINAL specifies which display to ask about.
3956TERMINAL should be a terminal id, a frame or a display name (a string).
7ee72033 3957If omitted or nil, that stands for the selected frame's display. */)
6ed8eeff
KL
3958 (terminal)
3959 Lisp_Object terminal;
41beb8fc 3960{
6ed8eeff 3961 struct x_display_info *dpyinfo = check_x_display_info (terminal);
b9dc4443
RS
3962
3963 return make_number (WidthMMOfScreen (dpyinfo->screen));
41beb8fc
RS
3964}
3965
3966DEFUN ("x-display-backing-store", Fx_display_backing_store,
c061c855 3967 Sx_display_backing_store, 0, 1, 0,
d29a9848 3968 doc: /* Return an indication of whether X display TERMINAL does backing store.
c061c855 3969The value may be `always', `when-mapped', or `not-useful'.
6ed8eeff
KL
3970The optional argument TERMINAL specifies which display to ask about.
3971TERMINAL should be a terminal id, a frame or a display name (a string).
7ee72033 3972If omitted or nil, that stands for the selected frame's display. */)
6ed8eeff
KL
3973 (terminal)
3974 Lisp_Object terminal;
41beb8fc 3975{
6ed8eeff 3976 struct x_display_info *dpyinfo = check_x_display_info (terminal);
8ec8a5ec 3977 Lisp_Object result;
11ae94fe 3978
b9dc4443 3979 switch (DoesBackingStore (dpyinfo->screen))
41beb8fc
RS
3980 {
3981 case Always:
8ec8a5ec
GM
3982 result = intern ("always");
3983 break;
41beb8fc
RS
3984
3985 case WhenMapped:
8ec8a5ec
GM
3986 result = intern ("when-mapped");
3987 break;
41beb8fc
RS
3988
3989 case NotUseful:
8ec8a5ec
GM
3990 result = intern ("not-useful");
3991 break;
41beb8fc
RS
3992
3993 default:
3994 error ("Strange value for BackingStore parameter of screen");
8ec8a5ec 3995 result = Qnil;
41beb8fc 3996 }
8ec8a5ec
GM
3997
3998 return result;
41beb8fc
RS
3999}
4000
4001DEFUN ("x-display-visual-class", Fx_display_visual_class,
c061c855 4002 Sx_display_visual_class, 0, 1, 0,
6ed8eeff 4003 doc: /* Return the visual class of the X display TERMINAL.
c061c855
GM
4004The value is one of the symbols `static-gray', `gray-scale',
4005`static-color', `pseudo-color', `true-color', or `direct-color'.
4006
6ed8eeff
KL
4007The optional argument TERMINAL specifies which display to ask about.
4008TERMINAL should a terminal id, a frame or a display name (a string).
7ee72033 4009If omitted or nil, that stands for the selected frame's display. */)
6ed8eeff
KL
4010 (terminal)
4011 Lisp_Object terminal;
41beb8fc 4012{
6ed8eeff 4013 struct x_display_info *dpyinfo = check_x_display_info (terminal);
8ec8a5ec 4014 Lisp_Object result;
11ae94fe 4015
b9dc4443 4016 switch (dpyinfo->visual->class)
41beb8fc 4017 {
8ec8a5ec
GM
4018 case StaticGray:
4019 result = intern ("static-gray");
4020 break;
4021 case GrayScale:
4022 result = intern ("gray-scale");
4023 break;
4024 case StaticColor:
4025 result = intern ("static-color");
4026 break;
4027 case PseudoColor:
4028 result = intern ("pseudo-color");
4029 break;
4030 case TrueColor:
4031 result = intern ("true-color");
4032 break;
4033 case DirectColor:
4034 result = intern ("direct-color");
4035 break;
41beb8fc
RS
4036 default:
4037 error ("Display has an unknown visual class");
8ec8a5ec 4038 result = Qnil;
41beb8fc 4039 }
177c0ea7 4040
8ec8a5ec 4041 return result;
41beb8fc
RS
4042}
4043
4044DEFUN ("x-display-save-under", Fx_display_save_under,
c061c855 4045 Sx_display_save_under, 0, 1, 0,
d29a9848 4046 doc: /* Return t if the X display TERMINAL supports the save-under feature.
6ed8eeff
KL
4047The optional argument TERMINAL specifies which display to ask about.
4048TERMINAL should be a terminal id, a frame or a display name (a string).
7ee72033 4049If omitted or nil, that stands for the selected frame's display. */)
6ed8eeff
KL
4050 (terminal)
4051 Lisp_Object terminal;
41beb8fc 4052{
6ed8eeff 4053 struct x_display_info *dpyinfo = check_x_display_info (terminal);
11ae94fe 4054
b9dc4443 4055 if (DoesSaveUnders (dpyinfo->screen) == True)
41beb8fc
RS
4056 return Qt;
4057 else
4058 return Qnil;
4059}
4060\f
b9dc4443 4061int
55caf99c
RS
4062x_pixel_width (f)
4063 register struct frame *f;
01f1ba30 4064{
be786000 4065 return FRAME_PIXEL_WIDTH (f);
01f1ba30
JB
4066}
4067
b9dc4443 4068int
55caf99c
RS
4069x_pixel_height (f)
4070 register struct frame *f;
01f1ba30 4071{
be786000 4072 return FRAME_PIXEL_HEIGHT (f);
55caf99c
RS
4073}
4074
b9dc4443 4075int
55caf99c
RS
4076x_char_width (f)
4077 register struct frame *f;
4078{
be786000 4079 return FRAME_COLUMN_WIDTH (f);
55caf99c
RS
4080}
4081
b9dc4443 4082int
55caf99c
RS
4083x_char_height (f)
4084 register struct frame *f;
4085{
be786000 4086 return FRAME_LINE_HEIGHT (f);
01f1ba30 4087}
b9dc4443
RS
4088
4089int
f03f2489
RS
4090x_screen_planes (f)
4091 register struct frame *f;
b9dc4443 4092{
f03f2489 4093 return FRAME_X_DISPLAY_INFO (f)->n_planes;
b9dc4443 4094}
01f1ba30 4095
a6ad00c0
GM
4096
4097\f
4098/************************************************************************
4099 X Displays
4100 ************************************************************************/
4101
01f1ba30 4102\f
a6ad00c0
GM
4103/* Mapping visual names to visuals. */
4104
4105static struct visual_class
4106{
4107 char *name;
4108 int class;
4109}
4110visual_classes[] =
4111{
4112 {"StaticGray", StaticGray},
4113 {"GrayScale", GrayScale},
4114 {"StaticColor", StaticColor},
4115 {"PseudoColor", PseudoColor},
4116 {"TrueColor", TrueColor},
4117 {"DirectColor", DirectColor},
9908a324 4118 {NULL, 0}
a6ad00c0
GM
4119};
4120
4121
404daac1 4122#ifndef HAVE_XSCREENNUMBEROFSCREEN
a6ad00c0
GM
4123
4124/* Value is the screen number of screen SCR. This is a substitute for
4125 the X function with the same name when that doesn't exist. */
4126
404daac1
RS
4127int
4128XScreenNumberOfScreen (scr)
4129 register Screen *scr;
4130{
a6ad00c0
GM
4131 Display *dpy = scr->display;
4132 int i;
3df34fdb 4133
a6ad00c0 4134 for (i = 0; i < dpy->nscreens; ++i)
fbd5ceb2 4135 if (scr == dpy->screens + i)
a6ad00c0 4136 break;
404daac1 4137
a6ad00c0 4138 return i;
404daac1 4139}
a6ad00c0 4140
404daac1
RS
4141#endif /* not HAVE_XSCREENNUMBEROFSCREEN */
4142
01f1ba30 4143
a6ad00c0
GM
4144/* Select the visual that should be used on display DPYINFO. Set
4145 members of DPYINFO appropriately. Called from x_term_init. */
fe24a618 4146
a6ad00c0
GM
4147void
4148select_visual (dpyinfo)
4149 struct x_display_info *dpyinfo;
4150{
4151 Display *dpy = dpyinfo->display;
4152 Screen *screen = dpyinfo->screen;
4153 Lisp_Object value;
fe24a618 4154
a6ad00c0
GM
4155 /* See if a visual is specified. */
4156 value = display_x_get_resource (dpyinfo,
4157 build_string ("visualClass"),
4158 build_string ("VisualClass"),
4159 Qnil, Qnil);
4160 if (STRINGP (value))
4161 {
4162 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
4163 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
4164 depth, a decimal number. NAME is compared with case ignored. */
d5db4077 4165 char *s = (char *) alloca (SBYTES (value) + 1);
a6ad00c0
GM
4166 char *dash;
4167 int i, class = -1;
4168 XVisualInfo vinfo;
4169
d5db4077 4170 strcpy (s, SDATA (value));
a6ad00c0
GM
4171 dash = index (s, '-');
4172 if (dash)
4173 {
4174 dpyinfo->n_planes = atoi (dash + 1);
4175 *dash = '\0';
4176 }
4177 else
4178 /* We won't find a matching visual with depth 0, so that
4179 an error will be printed below. */
4180 dpyinfo->n_planes = 0;
f0614854 4181
a6ad00c0
GM
4182 /* Determine the visual class. */
4183 for (i = 0; visual_classes[i].name; ++i)
4184 if (xstricmp (s, visual_classes[i].name) == 0)
4185 {
4186 class = visual_classes[i].class;
4187 break;
4188 }
01f1ba30 4189
a6ad00c0
GM
4190 /* Look up a matching visual for the specified class. */
4191 if (class == -1
4192 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
4193 dpyinfo->n_planes, class, &vinfo))
d5db4077 4194 fatal ("Invalid visual specification `%s'", SDATA (value));
177c0ea7 4195
a6ad00c0
GM
4196 dpyinfo->visual = vinfo.visual;
4197 }
01f1ba30
JB
4198 else
4199 {
a6ad00c0
GM
4200 int n_visuals;
4201 XVisualInfo *vinfo, vinfo_template;
177c0ea7 4202
a6ad00c0
GM
4203 dpyinfo->visual = DefaultVisualOfScreen (screen);
4204
a6ad00c0 4205 vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
a6ad00c0
GM
4206 vinfo_template.screen = XScreenNumberOfScreen (screen);
4207 vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
4208 &vinfo_template, &n_visuals);
4209 if (n_visuals != 1)
4210 fatal ("Can't get proper X visual info");
4211
94ac875b 4212 dpyinfo->n_planes = vinfo->depth;
a6ad00c0
GM
4213 XFree ((char *) vinfo);
4214 }
01f1ba30 4215}
01f1ba30 4216
a6ad00c0 4217
b9dc4443
RS
4218/* Return the X display structure for the display named NAME.
4219 Open a new connection if necessary. */
4220
4221struct x_display_info *
4222x_display_info_for_name (name)
4223 Lisp_Object name;
4224{
08a90d6a 4225 Lisp_Object names;
b9dc4443
RS
4226 struct x_display_info *dpyinfo;
4227
b7826503 4228 CHECK_STRING (name);
b9dc4443 4229
2246281f
KL
4230#if 0
4231 if (! EQ (Vinitial_window_system, intern ("x")))
4232 error ("Not using X Windows"); /* That doesn't stop us anymore. */
4233#endif
806048df 4234
08a90d6a
RS
4235 for (dpyinfo = x_display_list, names = x_display_name_list;
4236 dpyinfo;
8e713be6 4237 dpyinfo = dpyinfo->next, names = XCDR (names))
b9dc4443
RS
4238 {
4239 Lisp_Object tem;
8e713be6 4240 tem = Fstring_equal (XCAR (XCAR (names)), name);
08a90d6a 4241 if (!NILP (tem))
b9dc4443
RS
4242 return dpyinfo;
4243 }
4244
b7975ee4
KH
4245 /* Use this general default value to start with. */
4246 Vx_resource_name = Vinvocation_name;
4247
b9dc4443
RS
4248 validate_x_resource_name ();
4249
9b207e8e 4250 dpyinfo = x_term_init (name, (char *)0,
d5db4077 4251 (char *) SDATA (Vx_resource_name));
b9dc4443 4252
08a90d6a 4253 if (dpyinfo == 0)
d5db4077 4254 error ("Cannot connect to X server %s", SDATA (name));
08a90d6a 4255
b9dc4443
RS
4256 x_in_use = 1;
4257 XSETFASTINT (Vwindow_system_version, 11);
4258
4259 return dpyinfo;
4260}
4261
a6ad00c0 4262
01f1ba30 4263DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
c061c855 4264 1, 3, 0,
7ee72033 4265 doc: /* Open a connection to an X server.
c061c855
GM
4266DISPLAY is the name of the display to connect to.
4267Optional second arg XRM-STRING is a string of resources in xrdb format.
4268If the optional third arg MUST-SUCCEED is non-nil,
7ee72033
MB
4269terminate Emacs if we can't open the connection. */)
4270 (display, xrm_string, must_succeed)
08a90d6a 4271 Lisp_Object display, xrm_string, must_succeed;
01f1ba30 4272{
01f1ba30 4273 unsigned char *xrm_option;
b9dc4443 4274 struct x_display_info *dpyinfo;
01f1ba30 4275
b7826503 4276 CHECK_STRING (display);
d387c960 4277 if (! NILP (xrm_string))
b7826503 4278 CHECK_STRING (xrm_string);
01f1ba30 4279
2246281f
KL
4280#if 0
4281 if (! EQ (Vinitial_window_system, intern ("x")))
4282 error ("Not using X Windows"); /* That doesn't stop us anymore. */
4283#endif
806048df 4284
d387c960 4285 if (! NILP (xrm_string))
d5db4077 4286 xrm_option = (unsigned char *) SDATA (xrm_string);
01f1ba30
JB
4287 else
4288 xrm_option = (unsigned char *) 0;
d387c960
JB
4289
4290 validate_x_resource_name ();
4291
e1b1bee8 4292 /* This is what opens the connection and sets x_current_display.
b9dc4443
RS
4293 This also initializes many symbols, such as those used for input. */
4294 dpyinfo = x_term_init (display, xrm_option,
d5db4077 4295 (char *) SDATA (Vx_resource_name));
f1c16f36 4296
08a90d6a
RS
4297 if (dpyinfo == 0)
4298 {
4299 if (!NILP (must_succeed))
10ffbc14
GM
4300 fatal ("Cannot connect to X server %s.\n\
4301Check the DISPLAY environment variable or use `-d'.\n\
842a9389
JB
4302Also use the `xauth' program to verify that you have the proper\n\
4303authorization information needed to connect the X server.\n\
bf770132 4304An insecure way to solve the problem may be to use `xhost'.\n",
d5db4077 4305 SDATA (display));
08a90d6a 4306 else
d5db4077 4307 error ("Cannot connect to X server %s", SDATA (display));
08a90d6a
RS
4308 }
4309
b9dc4443 4310 x_in_use = 1;
01f1ba30 4311
b9dc4443 4312 XSETFASTINT (Vwindow_system_version, 11);
01f1ba30
JB
4313 return Qnil;
4314}
4315
08a90d6a
RS
4316DEFUN ("x-close-connection", Fx_close_connection,
4317 Sx_close_connection, 1, 1, 0,
00d385b0
KL
4318 doc: /* Close the connection to TERMINAL's X server.
4319For TERMINAL, specify a terminal id, a frame or a display name (a
4320string). If TERMINAL is nil, that stands for the selected frame's
4321terminal. */)
4322 (terminal)
4323 Lisp_Object terminal;
01f1ba30 4324{
00d385b0 4325 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3457bc6e 4326
08a90d6a
RS
4327 if (dpyinfo->reference_count > 0)
4328 error ("Display still has frames on it");
01f1ba30 4329
6ed8eeff 4330 x_delete_terminal (dpyinfo->terminal);
3457bc6e 4331
01f1ba30
JB
4332 return Qnil;
4333}
4334
08a90d6a 4335DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
7ee72033
MB
4336 doc: /* Return the list of display names that Emacs has connections to. */)
4337 ()
08a90d6a
RS
4338{
4339 Lisp_Object tail, result;
4340
4341 result = Qnil;
9beb8baa 4342 for (tail = x_display_name_list; CONSP (tail); tail = XCDR (tail))
8e713be6 4343 result = Fcons (XCAR (XCAR (tail)), result);
08a90d6a
RS
4344
4345 return result;
4346}
4347
4348DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
7ee72033 4349 doc: /* If ON is non-nil, report X errors as soon as the erring request is made.
c061c855
GM
4350If ON is nil, allow buffering of requests.
4351Turning on synchronization prohibits the Xlib routines from buffering
4352requests and seriously degrades performance, but makes debugging much
4353easier.
00d385b0
KL
4354The optional second argument TERMINAL specifies which display to act on.
4355TERMINAL should be a terminal id, a frame or a display name (a string).
4356If TERMINAL is omitted or nil, that stands for the selected frame's display. */)
4357 (on, terminal)
4358 Lisp_Object terminal, on;
01f1ba30 4359{
00d385b0 4360 struct x_display_info *dpyinfo = check_x_display_info (terminal);
11ae94fe 4361
b9dc4443 4362 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
01f1ba30
JB
4363
4364 return Qnil;
4365}
4366
b9dc4443 4367/* Wait for responses to all X commands issued so far for frame F. */
6b7b1820
RS
4368
4369void
b9dc4443
RS
4370x_sync (f)
4371 FRAME_PTR f;
6b7b1820 4372{
4e87f4d2 4373 BLOCK_INPUT;
b9dc4443 4374 XSync (FRAME_X_DISPLAY (f), False);
4e87f4d2 4375 UNBLOCK_INPUT;
6b7b1820 4376}
333b20bb 4377
01f1ba30 4378\f
333b20bb 4379/***********************************************************************
6b61353c 4380 Window properties
333b20bb 4381 ***********************************************************************/
f1c16f36 4382
6b61353c
KH
4383DEFUN ("x-change-window-property", Fx_change_window_property,
4384 Sx_change_window_property, 2, 6, 0,
4385 doc: /* Change window property PROP to VALUE on the X window of FRAME.
4386PROP must be a string.
4387VALUE may be a string or a list of conses, numbers and/or strings.
4388If an element in the list is a string, it is converted to
4389an Atom and the value of the Atom is used. If an element is a cons,
4390it is converted to a 32 bit number where the car is the 16 top bits and the
4391cdr is the lower 16 bits.
4392FRAME nil or omitted means use the selected frame.
4393If TYPE is given and non-nil, it is the name of the type of VALUE.
4394If TYPE is not given or nil, the type is STRING.
4395FORMAT gives the size in bits of each element if VALUE is a list.
4396It must be one of 8, 16 or 32.
4397If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to 8.
4398If OUTER_P is non-nil, the property is changed for the outer X window of
4399FRAME. Default is to change on the edit X window.
4400
4401Value is VALUE. */)
4402 (prop, value, frame, type, format, outer_p)
4403 Lisp_Object prop, value, frame, type, format, outer_p;
4404{
4405 struct frame *f = check_x_frame (frame);
4406 Atom prop_atom;
4407 Atom target_type = XA_STRING;
4408 int element_format = 8;
4409 unsigned char *data;
4410 int nelements;
4411 Window w;
333b20bb 4412
6b61353c 4413 CHECK_STRING (prop);
333b20bb 4414
6b61353c
KH
4415 if (! NILP (format))
4416 {
4417 CHECK_NUMBER (format);
4418 element_format = XFASTINT (format);
333b20bb 4419
6b61353c
KH
4420 if (element_format != 8 && element_format != 16
4421 && element_format != 32)
4422 error ("FORMAT must be one of 8, 16 or 32");
4423 }
333b20bb 4424
6b61353c
KH
4425 if (CONSP (value))
4426 {
4427 nelements = x_check_property_data (value);
4428 if (nelements == -1)
4429 error ("Bad data in VALUE, must be number, string or cons");
333b20bb 4430
6b61353c
KH
4431 if (element_format == 8)
4432 data = (unsigned char *) xmalloc (nelements);
4433 else if (element_format == 16)
4434 data = (unsigned char *) xmalloc (nelements*2);
fede04ef
JD
4435 else /* format == 32 */
4436 /* The man page for XChangeProperty:
4437 "If the specified format is 32, the property data must be a
4438 long array."
4439 This applies even if long is more than 64 bits. The X library
4440 converts to 32 bits before sending to the X server. */
4441 data = (unsigned char *) xmalloc (nelements * sizeof(long));
333b20bb 4442
6b61353c
KH
4443 x_fill_property_data (FRAME_X_DISPLAY (f), value, data, element_format);
4444 }
4445 else
4446 {
4447 CHECK_STRING (value);
4448 data = SDATA (value);
4449 nelements = SCHARS (value);
4450 }
333b20bb 4451
6b61353c
KH
4452 BLOCK_INPUT;
4453 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
4454 if (! NILP (type))
4455 {
4456 CHECK_STRING (type);
4457 target_type = XInternAtom (FRAME_X_DISPLAY (f), SDATA (type), False);
4458 }
333b20bb 4459
6b61353c
KH
4460 if (! NILP (outer_p)) w = FRAME_OUTER_WINDOW (f);
4461 else w = FRAME_X_WINDOW (f);
5b3f8550 4462
6b61353c
KH
4463 XChangeProperty (FRAME_X_DISPLAY (f), w,
4464 prop_atom, target_type, element_format, PropModeReplace,
4465 data, nelements);
333b20bb 4466
6b61353c 4467 if (CONSP (value)) xfree (data);
333b20bb 4468
6b61353c
KH
4469 /* Make sure the property is set when we return. */
4470 XFlush (FRAME_X_DISPLAY (f));
4471 UNBLOCK_INPUT;
333b20bb 4472
6b61353c 4473 return value;
333b20bb
GM
4474}
4475
4476
6b61353c
KH
4477DEFUN ("x-delete-window-property", Fx_delete_window_property,
4478 Sx_delete_window_property, 1, 2, 0,
4479 doc: /* Remove window property PROP from X window of FRAME.
4480FRAME nil or omitted means use the selected frame. Value is PROP. */)
4481 (prop, frame)
4482 Lisp_Object prop, frame;
333b20bb 4483{
6b61353c
KH
4484 struct frame *f = check_x_frame (frame);
4485 Atom prop_atom;
333b20bb 4486
6b61353c
KH
4487 CHECK_STRING (prop);
4488 BLOCK_INPUT;
4489 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
4490 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
333b20bb 4491
6b61353c
KH
4492 /* Make sure the property is removed when we return. */
4493 XFlush (FRAME_X_DISPLAY (f));
4494 UNBLOCK_INPUT;
333b20bb 4495
6b61353c
KH
4496 return prop;
4497}
333b20bb 4498
333b20bb 4499
6b61353c
KH
4500DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
4501 1, 6, 0,
4502 doc: /* Value is the value of window property PROP on FRAME.
4503If FRAME is nil or omitted, use the selected frame.
4504If TYPE is nil or omitted, get the property as a string. Otherwise TYPE
4505is the name of the Atom that denotes the type expected.
4506If SOURCE is non-nil, get the property on that window instead of from
4507FRAME. The number 0 denotes the root window.
4508If DELETE_P is non-nil, delete the property after retreiving it.
4509If VECTOR_RET_P is non-nil, don't return a string but a vector of values.
4510
4511Value is nil if FRAME hasn't a property with name PROP or if PROP has
4512no value of TYPE. */)
4513 (prop, frame, type, source, delete_p, vector_ret_p)
4514 Lisp_Object prop, frame, type, source, delete_p, vector_ret_p;
333b20bb 4515{
6b61353c
KH
4516 struct frame *f = check_x_frame (frame);
4517 Atom prop_atom;
4518 int rc;
4519 Lisp_Object prop_value = Qnil;
a3db4b26 4520 unsigned char *tmp_data = NULL;
6b61353c
KH
4521 Atom actual_type;
4522 Atom target_type = XA_STRING;
4523 int actual_format;
4524 unsigned long actual_size, bytes_remaining;
4525 Window target_window = FRAME_X_WINDOW (f);
4526 struct gcpro gcpro1;
177c0ea7 4527
6b61353c
KH
4528 GCPRO1 (prop_value);
4529 CHECK_STRING (prop);
1783ffa2 4530
6b61353c
KH
4531 if (! NILP (source))
4532 {
4533 if (NUMBERP (source))
4534 {
4535 if (FLOATP (source))
4536 target_window = (Window) XFLOAT (source);
4537 else
4538 target_window = XFASTINT (source);
177c0ea7 4539
6b61353c
KH
4540 if (target_window == 0)
4541 target_window = FRAME_X_DISPLAY_INFO (f)->root_window;
4542 }
4543 else if (CONSP (source))
4544 target_window = cons_to_long (source);
333b20bb
GM
4545 }
4546
6b61353c
KH
4547 BLOCK_INPUT;
4548 if (STRINGP (type))
4549 {
4550 if (strcmp ("AnyPropertyType", SDATA (type)) == 0)
4551 target_type = AnyPropertyType;
4552 else
4553 target_type = XInternAtom (FRAME_X_DISPLAY (f), SDATA (type), False);
4554 }
333b20bb 4555
6b61353c
KH
4556 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
4557 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
4558 prop_atom, 0, 0, False, target_type,
4559 &actual_type, &actual_format, &actual_size,
a3db4b26 4560 &bytes_remaining, &tmp_data);
6b61353c
KH
4561 if (rc == Success)
4562 {
4563 int size = bytes_remaining;
333b20bb 4564
6b61353c
KH
4565 XFree (tmp_data);
4566 tmp_data = NULL;
333b20bb 4567
6b61353c 4568 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
333b20bb 4569 prop_atom, 0, bytes_remaining,
6b61353c 4570 ! NILP (delete_p), target_type,
177c0ea7
JB
4571 &actual_type, &actual_format,
4572 &actual_size, &bytes_remaining,
a3db4b26 4573 &tmp_data);
4c8c7926 4574 if (rc == Success && tmp_data)
6b61353c 4575 {
fede04ef
JD
4576 /* The man page for XGetWindowProperty says:
4577 "If the returned format is 32, the returned data is represented
4578 as a long array and should be cast to that type to obtain the
4579 elements."
4580 This applies even if long is more than 32 bits, the X library
4581 converts from 32 bit elements received from the X server to long
4582 and passes the long array to us. Thus, for that case bcopy can not
4583 be used. We convert to a 32 bit type here, because so much code
4584 assume on that.
4585
4586 The bytes and offsets passed to XGetWindowProperty refers to the
4587 property and those are indeed in 32 bit quantities if format is
4588 32. */
4589
4590 if (actual_format == 32 && actual_format < BITS_PER_LONG)
4591 {
4592 unsigned long i;
4593 int *idata = (int *) tmp_data;
4594 long *ldata = (long *) tmp_data;
4595
4596 for (i = 0; i < actual_size; ++i)
a3db4b26 4597 idata[i] = (int) ldata[i];
fede04ef
JD
4598 }
4599
6b61353c
KH
4600 if (NILP (vector_ret_p))
4601 prop_value = make_string (tmp_data, size);
4602 else
4603 prop_value = x_property_data_to_lisp (f,
a3db4b26 4604 tmp_data,
6b61353c
KH
4605 actual_type,
4606 actual_format,
4607 actual_size);
4608 }
333b20bb 4609
6b61353c 4610 if (tmp_data) XFree (tmp_data);
333b20bb
GM
4611 }
4612
4613 UNBLOCK_INPUT;
6b61353c 4614 UNGCPRO;
333b20bb
GM
4615 return prop_value;
4616}
4617
4618
4619\f
4620/***********************************************************************
4621 Busy cursor
4622 ***********************************************************************/
4623
4ae9a85e 4624/* If non-null, an asynchronous timer that, when it expires, displays
0af913d7 4625 an hourglass cursor on all frames. */
333b20bb 4626
0af913d7 4627static struct atimer *hourglass_atimer;
333b20bb 4628
0af913d7 4629/* Non-zero means an hourglass cursor is currently shown. */
333b20bb 4630
0af913d7 4631static int hourglass_shown_p;
333b20bb 4632
0af913d7 4633/* Number of seconds to wait before displaying an hourglass cursor. */
333b20bb 4634
0af913d7 4635static Lisp_Object Vhourglass_delay;
333b20bb 4636
0af913d7 4637/* Default number of seconds to wait before displaying an hourglass
4ae9a85e
GM
4638 cursor. */
4639
0af913d7 4640#define DEFAULT_HOURGLASS_DELAY 1
4ae9a85e
GM
4641
4642/* Function prototypes. */
4643
0af913d7
GM
4644static void show_hourglass P_ ((struct atimer *));
4645static void hide_hourglass P_ ((void));
4ae9a85e 4646
83c31c8d
JD
4647/* Return non-zero if houglass timer has been started or hourglass is shown. */
4648
4649int
4650hourglass_started ()
4651{
4652 return hourglass_shown_p || hourglass_atimer != NULL;
4653}
4654
4ae9a85e 4655
0af913d7 4656/* Cancel a currently active hourglass timer, and start a new one. */
4ae9a85e
GM
4657
4658void
0af913d7 4659start_hourglass ()
333b20bb 4660{
4ae9a85e 4661 EMACS_TIME delay;
3caa99d3 4662 int secs, usecs = 0;
177c0ea7 4663
0af913d7 4664 cancel_hourglass ();
4ae9a85e 4665
0af913d7
GM
4666 if (INTEGERP (Vhourglass_delay)
4667 && XINT (Vhourglass_delay) > 0)
4668 secs = XFASTINT (Vhourglass_delay);
4669 else if (FLOATP (Vhourglass_delay)
4670 && XFLOAT_DATA (Vhourglass_delay) > 0)
3caa99d3
GM
4671 {
4672 Lisp_Object tem;
0af913d7 4673 tem = Ftruncate (Vhourglass_delay, Qnil);
3caa99d3 4674 secs = XFASTINT (tem);
0af913d7 4675 usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
3caa99d3 4676 }
4ae9a85e 4677 else
0af913d7 4678 secs = DEFAULT_HOURGLASS_DELAY;
177c0ea7 4679
3caa99d3 4680 EMACS_SET_SECS_USECS (delay, secs, usecs);
0af913d7
GM
4681 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
4682 show_hourglass, NULL);
4ae9a85e
GM
4683}
4684
4685
0af913d7 4686/* Cancel the hourglass cursor timer if active, hide a busy cursor if
4ae9a85e
GM
4687 shown. */
4688
4689void
0af913d7 4690cancel_hourglass ()
4ae9a85e 4691{
0af913d7 4692 if (hourglass_atimer)
99f01f62 4693 {
0af913d7
GM
4694 cancel_atimer (hourglass_atimer);
4695 hourglass_atimer = NULL;
99f01f62 4696 }
177c0ea7 4697
0af913d7
GM
4698 if (hourglass_shown_p)
4699 hide_hourglass ();
4ae9a85e
GM
4700}
4701
4702
0af913d7
GM
4703/* Timer function of hourglass_atimer. TIMER is equal to
4704 hourglass_atimer.
4ae9a85e 4705
0af913d7
GM
4706 Display an hourglass pointer on all frames by mapping the frames'
4707 hourglass_window. Set the hourglass_p flag in the frames'
4708 output_data.x structure to indicate that an hourglass cursor is
4709 shown on the frames. */
4ae9a85e
GM
4710
4711static void
0af913d7 4712show_hourglass (timer)
4ae9a85e
GM
4713 struct atimer *timer;
4714{
4715 /* The timer implementation will cancel this timer automatically
0af913d7 4716 after this function has run. Set hourglass_atimer to null
4ae9a85e 4717 so that we know the timer doesn't have to be canceled. */
0af913d7 4718 hourglass_atimer = NULL;
4ae9a85e 4719
0af913d7 4720 if (!hourglass_shown_p)
333b20bb
GM
4721 {
4722 Lisp_Object rest, frame;
177c0ea7 4723
4ae9a85e 4724 BLOCK_INPUT;
177c0ea7 4725
333b20bb 4726 FOR_EACH_FRAME (rest, frame)
5f7a1890
GM
4727 {
4728 struct frame *f = XFRAME (frame);
177c0ea7 4729
5f7a1890
GM
4730 if (FRAME_LIVE_P (f) && FRAME_X_P (f) && FRAME_X_DISPLAY (f))
4731 {
4732 Display *dpy = FRAME_X_DISPLAY (f);
177c0ea7 4733
5f7a1890
GM
4734#ifdef USE_X_TOOLKIT
4735 if (f->output_data.x->widget)
4736#else
4737 if (FRAME_OUTER_WINDOW (f))
4738#endif
4739 {
0af913d7 4740 f->output_data.x->hourglass_p = 1;
177c0ea7 4741
0af913d7 4742 if (!f->output_data.x->hourglass_window)
5f7a1890
GM
4743 {
4744 unsigned long mask = CWCursor;
4745 XSetWindowAttributes attrs;
49b8b5dc
JD
4746#ifdef USE_GTK
4747 Window parent = FRAME_X_WINDOW (f);
4748#else
4749 Window parent = FRAME_OUTER_WINDOW (f);
4750#endif
0af913d7 4751 attrs.cursor = f->output_data.x->hourglass_cursor;
177c0ea7 4752
0af913d7 4753 f->output_data.x->hourglass_window
49b8b5dc 4754 = XCreateWindow (dpy, parent,
5f7a1890
GM
4755 0, 0, 32000, 32000, 0, 0,
4756 InputOnly,
4757 CopyFromParent,
4758 mask, &attrs);
4759 }
177c0ea7 4760
0af913d7 4761 XMapRaised (dpy, f->output_data.x->hourglass_window);
5f7a1890
GM
4762 XFlush (dpy);
4763 }
4764 }
4765 }
333b20bb 4766
0af913d7 4767 hourglass_shown_p = 1;
4ae9a85e
GM
4768 UNBLOCK_INPUT;
4769 }
333b20bb
GM
4770}
4771
4772
0af913d7
GM
4773/* Hide the hourglass pointer on all frames, if it is currently
4774 shown. */
333b20bb 4775
4ae9a85e 4776static void
0af913d7 4777hide_hourglass ()
4ae9a85e 4778{
0af913d7 4779 if (hourglass_shown_p)
333b20bb 4780 {
4ae9a85e
GM
4781 Lisp_Object rest, frame;
4782
4783 BLOCK_INPUT;
4784 FOR_EACH_FRAME (rest, frame)
333b20bb 4785 {
4ae9a85e 4786 struct frame *f = XFRAME (frame);
177c0ea7 4787
4ae9a85e
GM
4788 if (FRAME_X_P (f)
4789 /* Watch out for newly created frames. */
0af913d7 4790 && f->output_data.x->hourglass_window)
4ae9a85e 4791 {
0af913d7
GM
4792 XUnmapWindow (FRAME_X_DISPLAY (f),
4793 f->output_data.x->hourglass_window);
4794 /* Sync here because XTread_socket looks at the
4795 hourglass_p flag that is reset to zero below. */
4ae9a85e 4796 XSync (FRAME_X_DISPLAY (f), False);
0af913d7 4797 f->output_data.x->hourglass_p = 0;
4ae9a85e 4798 }
333b20bb 4799 }
333b20bb 4800
0af913d7 4801 hourglass_shown_p = 0;
4ae9a85e
GM
4802 UNBLOCK_INPUT;
4803 }
333b20bb
GM
4804}
4805
4806
4807\f
4808/***********************************************************************
4809 Tool tips
4810 ***********************************************************************/
4811
4812static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
275841bf 4813 Lisp_Object, Lisp_Object));
06d62053 4814static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
ab452f99 4815 Lisp_Object, int, int, int *, int *));
177c0ea7 4816
44b5a125 4817/* The frame of a currently visible tooltip. */
333b20bb 4818
44b5a125 4819Lisp_Object tip_frame;
333b20bb
GM
4820
4821/* If non-nil, a timer started that hides the last tooltip when it
4822 fires. */
4823
4824Lisp_Object tip_timer;
4825Window tip_window;
4826
06d62053
GM
4827/* If non-nil, a vector of 3 elements containing the last args
4828 with which x-show-tip was called. See there. */
4829
4830Lisp_Object last_show_tip_args;
4831
d63931a2
GM
4832/* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
4833
4834Lisp_Object Vx_max_tooltip_size;
4835
eaf1eea9
GM
4836
4837static Lisp_Object
4838unwind_create_tip_frame (frame)
4839 Lisp_Object frame;
4840{
c844a81a
GM
4841 Lisp_Object deleted;
4842
4843 deleted = unwind_create_frame (frame);
4844 if (EQ (deleted, Qt))
4845 {
4846 tip_window = None;
4847 tip_frame = Qnil;
4848 }
177c0ea7 4849
c844a81a 4850 return deleted;
eaf1eea9
GM
4851}
4852
4853
333b20bb 4854/* Create a frame for a tooltip on the display described by DPYINFO.
275841bf
GM
4855 PARMS is a list of frame parameters. TEXT is the string to
4856 display in the tip frame. Value is the frame.
eaf1eea9
GM
4857
4858 Note that functions called here, esp. x_default_parameter can
4859 signal errors, for instance when a specified color name is
4860 undefined. We have to make sure that we're in a consistent state
4861 when this happens. */
333b20bb
GM
4862
4863static Lisp_Object
275841bf 4864x_create_tip_frame (dpyinfo, parms, text)
333b20bb 4865 struct x_display_info *dpyinfo;
275841bf 4866 Lisp_Object parms, text;
333b20bb
GM
4867{
4868 struct frame *f;
4869 Lisp_Object frame, tem;
4870 Lisp_Object name;
333b20bb
GM
4871 long window_prompting = 0;
4872 int width, height;
331379bf 4873 int count = SPECPDL_INDEX ();
b6d7acec 4874 struct gcpro gcpro1, gcpro2, gcpro3;
06d62053 4875 int face_change_count_before = face_change_count;
275841bf
GM
4876 Lisp_Object buffer;
4877 struct buffer *old_buffer;
333b20bb
GM
4878
4879 check_x ();
4880
89acb56d
SM
4881 if (!dpyinfo->terminal->name)
4882 error ("Terminal is not live, can't create new frames on it");
333b20bb 4883
47f3c6b4 4884 parms = Fcopy_alist (parms);
333b20bb
GM
4885
4886 /* Get the name of the frame to use for resource lookup. */
4887 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
4888 if (!STRINGP (name)
4889 && !EQ (name, Qunbound)
4890 && !NILP (name))
4891 error ("Invalid frame name--not a string or nil");
333b20bb
GM
4892
4893 frame = Qnil;
4894 GCPRO3 (parms, name, frame);
44b5a125 4895 f = make_frame (1);
333b20bb 4896 XSETFRAME (frame, f);
275841bf
GM
4897
4898 buffer = Fget_buffer_create (build_string (" *tip*"));
be786000 4899 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer, Qnil);
275841bf
GM
4900 old_buffer = current_buffer;
4901 set_buffer_internal_1 (XBUFFER (buffer));
d63931a2 4902 current_buffer->truncate_lines = Qnil;
5c2a995d
KH
4903 specbind (Qinhibit_read_only, Qt);
4904 specbind (Qinhibit_modification_hooks, Qt);
275841bf
GM
4905 Ferase_buffer ();
4906 Finsert (1, &text);
4907 set_buffer_internal_1 (old_buffer);
177c0ea7 4908
333b20bb 4909 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
8a1a7743 4910 record_unwind_protect (unwind_create_tip_frame, frame);
333b20bb 4911
6ed8eeff
KL
4912 f->terminal = dpyinfo->terminal;
4913 f->terminal->reference_count++;
daf01701 4914
eaf1eea9
GM
4915 /* By setting the output method, we're essentially saying that
4916 the frame is live, as per FRAME_LIVE_P. If we get a signal
4917 from this point on, x_destroy_window might screw up reference
4918 counts etc. */
333b20bb
GM
4919 f->output_method = output_x_window;
4920 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
4921 bzero (f->output_data.x, sizeof (struct x_output));
4922 f->output_data.x->icon_bitmap = -1;
be786000 4923 FRAME_FONTSET (f) = -1;
61d461a8
GM
4924 f->output_data.x->scroll_bar_foreground_pixel = -1;
4925 f->output_data.x->scroll_bar_background_pixel = -1;
f15340b7
MB
4926#ifdef USE_TOOLKIT_SCROLL_BARS
4927 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
4928 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
4929#endif /* USE_TOOLKIT_SCROLL_BARS */
333b20bb
GM
4930 f->icon_name = Qnil;
4931 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
f1d2ce7f 4932#if GLYPH_DEBUG
354884c4 4933 image_cache_refcount = FRAME_IMAGE_CACHE (f)->refcount;
eaf1eea9
GM
4934 dpyinfo_refcount = dpyinfo->reference_count;
4935#endif /* GLYPH_DEBUG */
333b20bb
GM
4936 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4937 f->output_data.x->explicit_parent = 0;
4938
61d461a8
GM
4939 /* These colors will be set anyway later, but it's important
4940 to get the color reference counts right, so initialize them! */
4941 {
4942 Lisp_Object black;
4943 struct gcpro gcpro1;
177c0ea7 4944
9d3d44ba
KL
4945 /* Function x_decode_color can signal an error. Make
4946 sure to initialize color slots so that we won't try
4947 to free colors we haven't allocated. */
ce593f6e
KL
4948 FRAME_FOREGROUND_PIXEL (f) = -1;
4949 FRAME_BACKGROUND_PIXEL (f) = -1;
9d3d44ba
KL
4950 f->output_data.x->cursor_pixel = -1;
4951 f->output_data.x->cursor_foreground_pixel = -1;
4952 f->output_data.x->border_pixel = -1;
4953 f->output_data.x->mouse_pixel = -1;
4954
61d461a8
GM
4955 black = build_string ("black");
4956 GCPRO1 (black);
ce593f6e 4957 FRAME_FOREGROUND_PIXEL (f)
61d461a8 4958 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
ce593f6e 4959 FRAME_BACKGROUND_PIXEL (f)
61d461a8
GM
4960 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4961 f->output_data.x->cursor_pixel
4962 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4963 f->output_data.x->cursor_foreground_pixel
4964 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4965 f->output_data.x->border_pixel
4966 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4967 f->output_data.x->mouse_pixel
4968 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4969 UNGCPRO;
4970 }
4971
333b20bb
GM
4972 /* Set the name; the functions to which we pass f expect the name to
4973 be set. */
4974 if (EQ (name, Qunbound) || NILP (name))
4975 {
4976 f->name = build_string (dpyinfo->x_id_name);
4977 f->explicit_name = 0;
4978 }
4979 else
4980 {
4981 f->name = name;
4982 f->explicit_name = 1;
4983 /* use the frame's title when getting resources for this frame. */
4984 specbind (Qx_resource_name, name);
4985 }
4986
02ed2ea8
KH
4987 f->resx = dpyinfo->resx;
4988 f->resy = dpyinfo->resy;
4989
4990#ifdef USE_FONT_BACKEND
4991 if (enable_font_backend)
4992 {
4993 /* Perhaps, we must allow frame parameter, say `font-backend',
4994 to specify which font backends to use. */
4995#ifdef HAVE_FREETYPE
4996#ifdef HAVE_XFT
4997 register_font_driver (&xftfont_driver, f);
4998#else /* not HAVE_XFT */
4999 register_font_driver (&ftxfont_driver, f);
5000#endif /* not HAVE_XFT */
5001#endif /* HAVE_FREETYPE */
5002 register_font_driver (&xfont_driver, f);
d43f6b74
KH
5003
5004 x_default_parameter (f, parms, Qfont_backend, Qnil,
5005 "fontBackend", "FontBackend", RES_TYPE_STRING);
02ed2ea8
KH
5006 }
5007#endif /* USE_FONT_BACKEND */
5008
eaf1eea9
GM
5009 /* Extract the window parameters from the supplied values that are
5010 needed to determine window geometry. */
02ed2ea8
KH
5011#ifdef USE_FONT_BACKEND
5012 if (enable_font_backend)
5013 x_default_font_parameter (f, parms);
5014else
5015#endif /* USE_FONT_BACKEND */
333b20bb
GM
5016 {
5017 Lisp_Object font;
5018
5019 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
5020
5021 BLOCK_INPUT;
5022 /* First, try whatever font the caller has specified. */
5023 if (STRINGP (font))
5024 {
5025 tem = Fquery_fontset (font, Qnil);
5026 if (STRINGP (tem))
7fb92cb1 5027 font = x_new_fontset (f, tem);
333b20bb 5028 else
d5db4077 5029 font = x_new_font (f, SDATA (font));
333b20bb 5030 }
177c0ea7 5031
333b20bb
GM
5032 /* Try out a font which we hope has bold and italic variations. */
5033 if (!STRINGP (font))
5034 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
5035 if (!STRINGP (font))
5036 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
5037 if (! STRINGP (font))
5038 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
5039 if (! STRINGP (font))
5040 /* This was formerly the first thing tried, but it finds too many fonts
5041 and takes too long. */
5042 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
5043 /* If those didn't work, look for something which will at least work. */
5044 if (! STRINGP (font))
5045 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
5046 UNBLOCK_INPUT;
5047 if (! STRINGP (font))
5048 font = build_string ("fixed");
5049
6a46b018 5050 x_set_frame_parameters (f, Fcons (Fcons (Qfont, font), Qnil));
333b20bb
GM
5051 }
5052
5053 x_default_parameter (f, parms, Qborder_width, make_number (2),
5054 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
177c0ea7 5055
333b20bb
GM
5056 /* This defaults to 2 in order to match xterm. We recognize either
5057 internalBorderWidth or internalBorder (which is what xterm calls
5058 it). */
5059 if (NILP (Fassq (Qinternal_border_width, parms)))
5060 {
5061 Lisp_Object value;
5062
5063 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
5064 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
5065 if (! EQ (value, Qunbound))
5066 parms = Fcons (Fcons (Qinternal_border_width, value),
5067 parms);
5068 }
5069
5070 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
5071 "internalBorderWidth", "internalBorderWidth",
5072 RES_TYPE_NUMBER);
5073
5074 /* Also do the stuff which must be set before the window exists. */
5075 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
5076 "foreground", "Foreground", RES_TYPE_STRING);
5077 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
5078 "background", "Background", RES_TYPE_STRING);
5079 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
5080 "pointerColor", "Foreground", RES_TYPE_STRING);
5081 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
5082 "cursorColor", "Foreground", RES_TYPE_STRING);
5083 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
5084 "borderColor", "BorderColor", RES_TYPE_STRING);
5085
5086 /* Init faces before x_default_parameter is called for scroll-bar
5087 parameters because that function calls x_set_scroll_bar_width,
5088 which calls change_frame_size, which calls Fset_window_buffer,
5089 which runs hooks, which call Fvertical_motion. At the end, we
5090 end up in init_iterator with a null face cache, which should not
5091 happen. */
5092 init_frame_faces (f);
177c0ea7 5093
333b20bb 5094 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
333b20bb 5095
7c0d3ed8 5096 window_prompting = x_figure_window_size (f, parms, 0);
333b20bb 5097
333b20bb
GM
5098 {
5099 XSetWindowAttributes attrs;
5100 unsigned long mask;
177c0ea7 5101
333b20bb 5102 BLOCK_INPUT;
c51d2b5e
GM
5103 mask = CWBackPixel | CWOverrideRedirect | CWEventMask;
5104 if (DoesSaveUnders (dpyinfo->screen))
5105 mask |= CWSaveUnder;
177c0ea7 5106
9b2956e2
GM
5107 /* Window managers look at the override-redirect flag to determine
5108 whether or net to give windows a decoration (Xlib spec, chapter
333b20bb
GM
5109 3.2.8). */
5110 attrs.override_redirect = True;
5111 attrs.save_under = True;
5112 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
5113 /* Arrange for getting MapNotify and UnmapNotify events. */
5114 attrs.event_mask = StructureNotifyMask;
5115 tip_window
5116 = FRAME_X_WINDOW (f)
5117 = XCreateWindow (FRAME_X_DISPLAY (f),
5118 FRAME_X_DISPLAY_INFO (f)->root_window,
5119 /* x, y, width, height */
5120 0, 0, 1, 1,
5121 /* Border. */
5122 1,
5123 CopyFromParent, InputOutput, CopyFromParent,
5124 mask, &attrs);
5125 UNBLOCK_INPUT;
5126 }
5127
5128 x_make_gc (f);
5129
333b20bb
GM
5130 x_default_parameter (f, parms, Qauto_raise, Qnil,
5131 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
5132 x_default_parameter (f, parms, Qauto_lower, Qnil,
5133 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
5134 x_default_parameter (f, parms, Qcursor_type, Qbox,
5135 "cursorType", "CursorType", RES_TYPE_SYMBOL);
5136
be786000 5137 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
333b20bb 5138 Change will not be effected unless different from the current
be786000
KS
5139 FRAME_LINES (f). */
5140 width = FRAME_COLS (f);
5141 height = FRAME_LINES (f);
5142 SET_FRAME_COLS (f, 0);
5143 FRAME_LINES (f) = 0;
8938a4fb 5144 change_frame_size (f, height, width, 1, 0, 0);
177c0ea7 5145
cd1d850f
JPW
5146 /* Add `tooltip' frame parameter's default value. */
5147 if (NILP (Fframe_parameter (frame, intern ("tooltip"))))
5148 Fmodify_frame_parameters (frame, Fcons (Fcons (intern ("tooltip"), Qt),
5149 Qnil));
177c0ea7 5150
cedb4d8b
GM
5151 /* FIXME - can this be done in a similar way to normal frames?
5152 http://lists.gnu.org/archive/html/emacs-devel/2007-10/msg00641.html */
5153
35fdaa62
GM
5154 /* Set the `display-type' frame parameter before setting up faces. */
5155 {
5156 Lisp_Object disptype;
5157
5158 if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
5159 disptype = intern ("mono");
219ccf1b
RS
5160 else if (FRAME_X_DISPLAY_INFO (f)->visual->class == GrayScale
5161 || FRAME_X_DISPLAY_INFO (f)->visual->class == StaticGray)
35fdaa62
GM
5162 disptype = intern ("grayscale");
5163 else
5164 disptype = intern ("color");
5165
5166 if (NILP (Fframe_parameter (frame, Qdisplay_type)))
5167 Fmodify_frame_parameters (frame, Fcons (Fcons (Qdisplay_type, disptype),
5168 Qnil));
5169 }
5170
035d5114 5171 /* Set up faces after all frame parameters are known. This call
6801a572
GM
5172 also merges in face attributes specified for new frames.
5173
5174 Frame parameters may be changed if .Xdefaults contains
5175 specifications for the default font. For example, if there is an
5176 `Emacs.default.attributeBackground: pink', the `background-color'
5177 attribute of the frame get's set, which let's the internal border
5178 of the tooltip frame appear in pink. Prevent this. */
5179 {
5180 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
5181
5182 /* Set tip_frame here, so that */
5183 tip_frame = frame;
5184 call1 (Qface_set_after_frame_default, frame);
177c0ea7 5185
6801a572
GM
5186 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
5187 Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
5188 Qnil));
5189 }
177c0ea7 5190
333b20bb
GM
5191 f->no_split = 1;
5192
5193 UNGCPRO;
5194
5195 /* It is now ok to make the frame official even if we get an error
5196 below. And the frame needs to be on Vframe_list or making it
5197 visible won't work. */
5198 Vframe_list = Fcons (frame, Vframe_list);
5199
5200 /* Now that the frame is official, it counts as a reference to
5201 its display. */
5202 FRAME_X_DISPLAY_INFO (f)->reference_count++;
5203
06d62053
GM
5204 /* Setting attributes of faces of the tooltip frame from resources
5205 and similar will increment face_change_count, which leads to the
5206 clearing of all current matrices. Since this isn't necessary
5207 here, avoid it by resetting face_change_count to the value it
5208 had before we created the tip frame. */
5209 face_change_count = face_change_count_before;
5210
eaf1eea9 5211 /* Discard the unwind_protect. */
333b20bb
GM
5212 return unbind_to (count, frame);
5213}
5214
5215
06d62053
GM
5216/* Compute where to display tip frame F. PARMS is the list of frame
5217 parameters for F. DX and DY are specified offsets from the current
ab452f99
GM
5218 location of the mouse. WIDTH and HEIGHT are the width and height
5219 of the tooltip. Return coordinates relative to the root window of
5220 the display in *ROOT_X, and *ROOT_Y. */
06d62053
GM
5221
5222static void
ab452f99 5223compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
06d62053
GM
5224 struct frame *f;
5225 Lisp_Object parms, dx, dy;
ab452f99 5226 int width, height;
06d62053
GM
5227 int *root_x, *root_y;
5228{
5229 Lisp_Object left, top;
5230 int win_x, win_y;
5231 Window root, child;
5232 unsigned pmask;
177c0ea7 5233
06d62053
GM
5234 /* User-specified position? */
5235 left = Fcdr (Fassq (Qleft, parms));
5236 top = Fcdr (Fassq (Qtop, parms));
177c0ea7 5237
06d62053
GM
5238 /* Move the tooltip window where the mouse pointer is. Resize and
5239 show it. */
570d22b0 5240 if (!INTEGERP (left) || !INTEGERP (top))
ab452f99
GM
5241 {
5242 BLOCK_INPUT;
5243 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
5244 &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
5245 UNBLOCK_INPUT;
5246 }
06d62053 5247
06d62053
GM
5248 if (INTEGERP (top))
5249 *root_y = XINT (top);
bf63eb69
JD
5250 else if (*root_y + XINT (dy) <= 0)
5251 *root_y = 0; /* Can happen for negative dy */
7e8410d1
JD
5252 else if (*root_y + XINT (dy) + height <= FRAME_X_DISPLAY_INFO (f)->height)
5253 /* It fits below the pointer */
ab452f99 5254 *root_y += XINT (dy);
7e8410d1
JD
5255 else if (height + XINT (dy) <= *root_y)
5256 /* It fits above the pointer. */
5257 *root_y -= height + XINT (dy);
5258 else
5259 /* Put it on the top. */
5260 *root_y = 0;
ab452f99
GM
5261
5262 if (INTEGERP (left))
5263 *root_x = XINT (left);
bf63eb69
JD
5264 else if (*root_x + XINT (dx) <= 0)
5265 *root_x = 0; /* Can happen for negative dx */
d682d3df
RS
5266 else if (*root_x + XINT (dx) + width <= FRAME_X_DISPLAY_INFO (f)->width)
5267 /* It fits to the right of the pointer. */
5268 *root_x += XINT (dx);
5269 else if (width + XINT (dx) <= *root_x)
5270 /* It fits to the left of the pointer. */
ab452f99
GM
5271 *root_x -= width + XINT (dx);
5272 else
d682d3df
RS
5273 /* Put it left-justified on the screen--it ought to fit that way. */
5274 *root_x = 0;
06d62053
GM
5275}
5276
5277
0634ce98 5278DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
7ee72033 5279 doc: /* Show STRING in a "tooltip" window on frame FRAME.
c061c855
GM
5280A tooltip window is a small X window displaying a string.
5281
87c891c7
EZ
5282This is an internal function; Lisp code should call `tooltip-show'.
5283
c061c855
GM
5284FRAME nil or omitted means use the selected frame.
5285
5286PARMS is an optional list of frame parameters which can be used to
5287change the tooltip's appearance.
5288
5289Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
5290means use the default timeout of 5 seconds.
5291
5292If the list of frame parameters PARAMS contains a `left' parameters,
5293the tooltip is displayed at that x-position. Otherwise it is
5294displayed at the mouse position, with offset DX added (default is 5 if
5295DX isn't specified). Likewise for the y-position; if a `top' frame
5296parameter is specified, it determines the y-position of the tooltip
5297window, otherwise it is displayed at the mouse position, with offset
5298DY added (default is -10).
5299
5300A tooltip's maximum size is specified by `x-max-tooltip-size'.
7ee72033
MB
5301Text larger than the specified size is clipped. */)
5302 (string, frame, parms, timeout, dx, dy)
0634ce98 5303 Lisp_Object string, frame, parms, timeout, dx, dy;
333b20bb
GM
5304{
5305 struct frame *f;
5306 struct window *w;
06d62053 5307 int root_x, root_y;
333b20bb
GM
5308 struct buffer *old_buffer;
5309 struct text_pos pos;
5310 int i, width, height;
393f2d14 5311 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
333b20bb 5312 int old_windows_or_buffers_changed = windows_or_buffers_changed;
331379bf 5313 int count = SPECPDL_INDEX ();
177c0ea7 5314
333b20bb
GM
5315 specbind (Qinhibit_redisplay, Qt);
5316
393f2d14 5317 GCPRO4 (string, parms, frame, timeout);
333b20bb 5318
b7826503 5319 CHECK_STRING (string);
2d7117fe
JD
5320 if (SCHARS (string) == 0)
5321 string = make_unibyte_string (" ", 1);
5322
333b20bb
GM
5323 f = check_x_frame (frame);
5324 if (NILP (timeout))
5325 timeout = make_number (5);
5326 else
b7826503 5327 CHECK_NATNUM (timeout);
177c0ea7 5328
0634ce98
GM
5329 if (NILP (dx))
5330 dx = make_number (5);
5331 else
b7826503 5332 CHECK_NUMBER (dx);
177c0ea7 5333
0634ce98 5334 if (NILP (dy))
12c67a7f 5335 dy = make_number (-10);
0634ce98 5336 else
b7826503 5337 CHECK_NUMBER (dy);
333b20bb 5338
06d62053
GM
5339 if (NILP (last_show_tip_args))
5340 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
5341
5342 if (!NILP (tip_frame))
5343 {
5344 Lisp_Object last_string = AREF (last_show_tip_args, 0);
5345 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
5346 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
5347
5348 if (EQ (frame, last_frame)
5349 && !NILP (Fequal (last_string, string))
5350 && !NILP (Fequal (last_parms, parms)))
5351 {
5352 struct frame *f = XFRAME (tip_frame);
177c0ea7 5353
06d62053
GM
5354 /* Only DX and DY have changed. */
5355 if (!NILP (tip_timer))
ae782866
GM
5356 {
5357 Lisp_Object timer = tip_timer;
5358 tip_timer = Qnil;
5359 call1 (Qcancel_timer, timer);
5360 }
06d62053
GM
5361
5362 BLOCK_INPUT;
be786000
KS
5363 compute_tip_xy (f, parms, dx, dy, FRAME_PIXEL_WIDTH (f),
5364 FRAME_PIXEL_HEIGHT (f), &root_x, &root_y);
06d62053 5365 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
ab452f99 5366 root_x, root_y);
06d62053
GM
5367 UNBLOCK_INPUT;
5368 goto start_timer;
5369 }
5370 }
5371
333b20bb
GM
5372 /* Hide a previous tip, if any. */
5373 Fx_hide_tip ();
5374
06d62053
GM
5375 ASET (last_show_tip_args, 0, string);
5376 ASET (last_show_tip_args, 1, frame);
5377 ASET (last_show_tip_args, 2, parms);
5378
333b20bb
GM
5379 /* Add default values to frame parameters. */
5380 if (NILP (Fassq (Qname, parms)))
5381 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
5382 if (NILP (Fassq (Qinternal_border_width, parms)))
5383 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
5384 if (NILP (Fassq (Qborder_width, parms)))
5385 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
5386 if (NILP (Fassq (Qborder_color, parms)))
5387 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
5388 if (NILP (Fassq (Qbackground_color, parms)))
5389 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
5390 parms);
5391
5392 /* Create a frame for the tooltip, and record it in the global
5393 variable tip_frame. */
275841bf 5394 frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms, string);
44b5a125 5395 f = XFRAME (frame);
333b20bb 5396
d63931a2 5397 /* Set up the frame's root window. */
333b20bb 5398 w = XWINDOW (FRAME_ROOT_WINDOW (f));
be786000 5399 w->left_col = w->top_line = make_number (0);
177c0ea7 5400
d63931a2
GM
5401 if (CONSP (Vx_max_tooltip_size)
5402 && INTEGERP (XCAR (Vx_max_tooltip_size))
5403 && XINT (XCAR (Vx_max_tooltip_size)) > 0
5404 && INTEGERP (XCDR (Vx_max_tooltip_size))
5405 && XINT (XCDR (Vx_max_tooltip_size)) > 0)
5406 {
be786000
KS
5407 w->total_cols = XCAR (Vx_max_tooltip_size);
5408 w->total_lines = XCDR (Vx_max_tooltip_size);
d63931a2
GM
5409 }
5410 else
5411 {
be786000
KS
5412 w->total_cols = make_number (80);
5413 w->total_lines = make_number (40);
d63931a2 5414 }
177c0ea7 5415
be786000 5416 FRAME_TOTAL_COLS (f) = XINT (w->total_cols);
333b20bb
GM
5417 adjust_glyphs (f);
5418 w->pseudo_window_p = 1;
5419
5420 /* Display the tooltip text in a temporary buffer. */
333b20bb 5421 old_buffer = current_buffer;
275841bf 5422 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
d63931a2 5423 current_buffer->truncate_lines = Qnil;
333b20bb
GM
5424 clear_glyph_matrix (w->desired_matrix);
5425 clear_glyph_matrix (w->current_matrix);
5426 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
29e95254 5427 try_window (FRAME_ROOT_WINDOW (f), pos, 0);
333b20bb
GM
5428
5429 /* Compute width and height of the tooltip. */
5430 width = height = 0;
5431 for (i = 0; i < w->desired_matrix->nrows; ++i)
5432 {
5433 struct glyph_row *row = &w->desired_matrix->rows[i];
5434 struct glyph *last;
5435 int row_width;
5436
5437 /* Stop at the first empty row at the end. */
5438 if (!row->enabled_p || !row->displays_text_p)
5439 break;
5440
d7bf0342
GM
5441 /* Let the row go over the full width of the frame. */
5442 row->full_width_p = 1;
333b20bb 5443
e3130015 5444 /* There's a glyph at the end of rows that is used to place
333b20bb
GM
5445 the cursor there. Don't include the width of this glyph. */
5446 if (row->used[TEXT_AREA])
5447 {
5448 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
5449 row_width = row->pixel_width - last->pixel_width;
5450 }
5451 else
5452 row_width = row->pixel_width;
177c0ea7 5453
333b20bb
GM
5454 height += row->height;
5455 width = max (width, row_width);
5456 }
5457
5458 /* Add the frame's internal border to the width and height the X
5459 window should have. */
5460 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
5461 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
5462
5463 /* Move the tooltip window where the mouse pointer is. Resize and
5464 show it. */
ab452f99 5465 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
0634ce98 5466
0634ce98 5467 BLOCK_INPUT;
333b20bb 5468 XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
ab452f99 5469 root_x, root_y, width, height);
333b20bb
GM
5470 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5471 UNBLOCK_INPUT;
177c0ea7 5472
333b20bb
GM
5473 /* Draw into the window. */
5474 w->must_be_updated_p = 1;
5475 update_single_window (w, 1);
5476
5477 /* Restore original current buffer. */
5478 set_buffer_internal_1 (old_buffer);
5479 windows_or_buffers_changed = old_windows_or_buffers_changed;
5480
06d62053 5481 start_timer:
333b20bb
GM
5482 /* Let the tip disappear after timeout seconds. */
5483 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
5484 intern ("x-hide-tip"));
a744a2ec
DL
5485
5486 UNGCPRO;
333b20bb
GM
5487 return unbind_to (count, Qnil);
5488}
5489
5490
5491DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
7ee72033
MB
5492 doc: /* Hide the current tooltip window, if there is any.
5493Value is t if tooltip was open, nil otherwise. */)
5494 ()
333b20bb 5495{
44b5a125 5496 int count;
c0006262
GM
5497 Lisp_Object deleted, frame, timer;
5498 struct gcpro gcpro1, gcpro2;
44b5a125
GM
5499
5500 /* Return quickly if nothing to do. */
c0006262 5501 if (NILP (tip_timer) && NILP (tip_frame))
44b5a125 5502 return Qnil;
177c0ea7 5503
c0006262
GM
5504 frame = tip_frame;
5505 timer = tip_timer;
5506 GCPRO2 (frame, timer);
5507 tip_frame = tip_timer = deleted = Qnil;
177c0ea7 5508
331379bf 5509 count = SPECPDL_INDEX ();
333b20bb 5510 specbind (Qinhibit_redisplay, Qt);
44b5a125 5511 specbind (Qinhibit_quit, Qt);
177c0ea7 5512
c0006262 5513 if (!NILP (timer))
ae782866 5514 call1 (Qcancel_timer, timer);
333b20bb 5515
c0006262 5516 if (FRAMEP (frame))
333b20bb 5517 {
44b5a125
GM
5518 Fdelete_frame (frame, Qnil);
5519 deleted = Qt;
f6c44811
GM
5520
5521#ifdef USE_LUCID
5522 /* Bloodcurdling hack alert: The Lucid menu bar widget's
5523 redisplay procedure is not called when a tip frame over menu
5524 items is unmapped. Redisplay the menu manually... */
5525 {
5526 struct frame *f = SELECTED_FRAME ();
5527 Widget w = f->output_data.x->menubar_widget;
5528 extern void xlwmenu_redisplay P_ ((Widget));
9180dc8c 5529
f6c44811 5530 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen)
dbc64aa7 5531 && w != NULL)
f6c44811
GM
5532 {
5533 BLOCK_INPUT;
5534 xlwmenu_redisplay (w);
5535 UNBLOCK_INPUT;
5536 }
5537 }
5538#endif /* USE_LUCID */
333b20bb
GM
5539 }
5540
c0006262 5541 UNGCPRO;
44b5a125 5542 return unbind_to (count, deleted);
333b20bb
GM
5543}
5544
5545
5546\f
5547/***********************************************************************
5548 File selection dialog
5549 ***********************************************************************/
5550
90f2e16b
JD
5551DEFUN ("x-uses-old-gtk-dialog", Fx_uses_old_gtk_dialog,
5552 Sx_uses_old_gtk_dialog,
5553 0, 0, 0,
5554 doc: /* Return t if the old Gtk+ file selection dialog is used. */)
5555 ()
5556{
5557#ifdef USE_GTK
5558 extern int use_dialog_box;
5559 extern int use_file_dialog;
333b20bb 5560
90f2e16b
JD
5561 if (use_dialog_box
5562 && use_file_dialog
5563 && have_menus_p ()
5564 && xg_uses_old_file_dialog ())
5565 return Qt;
5566#endif
5567 return Qnil;
5568}
5569
333b20bb 5570
90f2e16b 5571#ifdef USE_MOTIF
333b20bb
GM
5572/* Callback for "OK" and "Cancel" on file selection dialog. */
5573
5574static void
5575file_dialog_cb (widget, client_data, call_data)
5576 Widget widget;
5577 XtPointer call_data, client_data;
5578{
5579 int *result = (int *) client_data;
5580 XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
5581 *result = cb->reason;
5582}
5583
5584
a779d213
GM
5585/* Callback for unmapping a file selection dialog. This is used to
5586 capture the case where a dialog is closed via a window manager's
5587 closer button, for example. Using a XmNdestroyCallback didn't work
5588 in this case. */
5589
5590static void
5591file_dialog_unmap_cb (widget, client_data, call_data)
5592 Widget widget;
5593 XtPointer call_data, client_data;
5594{
5595 int *result = (int *) client_data;
5596 *result = XmCR_CANCEL;
5597}
5598
24ca7c5a
JD
5599static Lisp_Object
5600clean_up_file_dialog (arg)
5601 Lisp_Object arg;
5602{
5603 struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
5604 Widget dialog = (Widget) p->pointer;
5605
5606 /* Clean up. */
5607 BLOCK_INPUT;
5608 XtUnmanageChild (dialog);
5609 XtDestroyWidget (dialog);
5610 x_menu_set_in_use (0);
5611 UNBLOCK_INPUT;
5612
5613 return Qnil;
5614}
5615
a779d213 5616
f9d64bb3 5617DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
7ee72033 5618 doc: /* Read file name, prompting with PROMPT in directory DIR.
f9d64bb3
JD
5619Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
5620selection box, if specified. If MUSTMATCH is non-nil, the returned file
5621or directory must exist. ONLY-DIR-P is ignored." */)
5622 (prompt, dir, default_filename, mustmatch, only_dir_p)
5623 Lisp_Object prompt, dir, default_filename, mustmatch, only_dir_p;
333b20bb
GM
5624{
5625 int result;
0fe92f72 5626 struct frame *f = SELECTED_FRAME ();
333b20bb 5627 Lisp_Object file = Qnil;
a8f4bdc6 5628 Lisp_Object decoded_file;
f9d64bb3 5629 Widget dialog, text, help;
333b20bb
GM
5630 Arg al[10];
5631 int ac = 0;
5632 extern XtAppContext Xt_app_con;
333b20bb 5633 XmString dir_xmstring, pattern_xmstring;
65b21658 5634 int count = SPECPDL_INDEX ();
f9d64bb3 5635 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
333b20bb 5636
6eeee4d6
YM
5637 check_x ();
5638
f9d64bb3 5639 GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
24ca7c5a 5640
5ae53dcf 5641 if (popup_activated ())
24ca7c5a
JD
5642 error ("Trying to use a menu from within a menu-entry");
5643
b7826503
PJ
5644 CHECK_STRING (prompt);
5645 CHECK_STRING (dir);
333b20bb
GM
5646
5647 /* Prevent redisplay. */
5648 specbind (Qinhibit_redisplay, Qt);
5649
5650 BLOCK_INPUT;
5651
5652 /* Create the dialog with PROMPT as title, using DIR as initial
5653 directory and using "*" as pattern. */
5654 dir = Fexpand_file_name (dir, Qnil);
d5db4077 5655 dir_xmstring = XmStringCreateLocalized (SDATA (dir));
333b20bb 5656 pattern_xmstring = XmStringCreateLocalized ("*");
177c0ea7 5657
d5db4077 5658 XtSetArg (al[ac], XmNtitle, SDATA (prompt)); ++ac;
333b20bb
GM
5659 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
5660 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
5661 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
5662 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
5663 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
5664 "fsb", al, ac);
5665 XmStringFree (dir_xmstring);
5666 XmStringFree (pattern_xmstring);
5667
5668 /* Add callbacks for OK and Cancel. */
5669 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
5670 (XtPointer) &result);
5671 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
5672 (XtPointer) &result);
a779d213
GM
5673 XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
5674 (XtPointer) &result);
333b20bb 5675
f9d64bb3 5676 /* Remove the help button since we can't display help. */
333b20bb 5677 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
f9d64bb3 5678 XtUnmanageChild (help);
333b20bb 5679
177c0ea7 5680 /* Mark OK button as default. */
333b20bb
GM
5681 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
5682 XmNshowAsDefault, True, NULL);
5683
5684 /* If MUSTMATCH is non-nil, disable the file entry field of the
5685 dialog, so that the user must select a file from the files list
5686 box. We can't remove it because we wouldn't have a way to get at
5687 the result file name, then. */
5688 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
5689 if (!NILP (mustmatch))
5690 {
5691 Widget label;
5692 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
5693 XtSetSensitive (text, False);
5694 XtSetSensitive (label, False);
5695 }
5696
5697 /* Manage the dialog, so that list boxes get filled. */
5698 XtManageChild (dialog);
5699
333b20bb
GM
5700 if (STRINGP (default_filename))
5701 {
5702 XmString default_xmstring;
f9d64bb3
JD
5703 Widget wtext = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
5704 Widget list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
333b20bb 5705
f9d64bb3
JD
5706 XmTextPosition last_pos = XmTextFieldGetLastPosition (wtext);
5707 XmTextFieldReplace (wtext, 0, last_pos,
5708 (SDATA (Ffile_name_nondirectory (default_filename))));
333b20bb 5709
f9d64bb3
JD
5710 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
5711 must include the path for this to work. */
5712
5713 default_xmstring = XmStringCreateLocalized (SDATA (default_filename));
333b20bb 5714
f9d64bb3
JD
5715 if (XmListItemExists (list, default_xmstring))
5716 {
5717 int item_pos = XmListItemPos (list, default_xmstring);
5718 /* Select the item and scroll it into view. */
5719 XmListSelectPos (list, item_pos, True);
5720 XmListSetPos (list, item_pos);
5721 }
5722
5723 XmStringFree (default_xmstring);
333b20bb
GM
5724 }
5725
24ca7c5a
JD
5726 record_unwind_protect (clean_up_file_dialog, make_save_value (dialog, 0));
5727
bf338245 5728 /* Process events until the user presses Cancel or OK. */
5ae53dcf 5729 x_menu_set_in_use (1);
03100098 5730 result = 0;
a779d213 5731 while (result == 0)
563b384d 5732 {
bf338245 5733 XEvent event;
24ca7c5a 5734 x_menu_wait_for_event (0);
bf338245 5735 XtAppNextEvent (Xt_app_con, &event);
9f6fcdc5
JD
5736 if (event.type == KeyPress
5737 && FRAME_X_DISPLAY (f) == event.xkey.display)
5738 {
5739 KeySym keysym = XLookupKeysym (&event.xkey, 0);
5740
5741 /* Pop down on C-g. */
5742 if (keysym == XK_g && (event.xkey.state & ControlMask) != 0)
5743 XtUnmanageChild (dialog);
5744 }
5b3f8550 5745
24ca7c5a 5746 (void) x_dispatch_event (&event, FRAME_X_DISPLAY (f));
563b384d 5747 }
03100098 5748
333b20bb
GM
5749 /* Get the result. */
5750 if (result == XmCR_OK)
5751 {
5752 XmString text;
5753 String data;
177c0ea7 5754
d1670063 5755 XtVaGetValues (dialog, XmNtextString, &text, NULL);
333b20bb
GM
5756 XmStringGetLtoR (text, XmFONTLIST_DEFAULT_TAG, &data);
5757 XmStringFree (text);
5758 file = build_string (data);
5759 XtFree (data);
5760 }
5761 else
5762 file = Qnil;
5763
333b20bb
GM
5764 UNBLOCK_INPUT;
5765 UNGCPRO;
5766
5767 /* Make "Cancel" equivalent to C-g. */
5768 if (NILP (file))
5769 Fsignal (Qquit, Qnil);
177c0ea7 5770
a8f4bdc6
JD
5771 decoded_file = DECODE_FILE (file);
5772
5773 return unbind_to (count, decoded_file);
333b20bb
GM
5774}
5775
5776#endif /* USE_MOTIF */
5777
488dd4c4
JD
5778#ifdef USE_GTK
5779
24ca7c5a
JD
5780static Lisp_Object
5781clean_up_dialog (arg)
5782 Lisp_Object arg;
5783{
5784 x_menu_set_in_use (0);
5785
5786 return Qnil;
5787}
5788
f9d64bb3
JD
5789DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
5790 doc: /* Read file name, prompting with PROMPT in directory DIR.
5791Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
5792selection box, if specified. If MUSTMATCH is non-nil, the returned file
5793or directory must exist. If ONLY-DIR-P is non-nil, the user can only select
5794directories. */)
5795 (prompt, dir, default_filename, mustmatch, only_dir_p)
5796 Lisp_Object prompt, dir, default_filename, mustmatch, only_dir_p;
488dd4c4
JD
5797{
5798 FRAME_PTR f = SELECTED_FRAME ();
5799 char *fn;
5800 Lisp_Object file = Qnil;
a8f4bdc6 5801 Lisp_Object decoded_file;
24ca7c5a 5802 int count = SPECPDL_INDEX ();
f9d64bb3 5803 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
488dd4c4 5804 char *cdef_file;
177c0ea7 5805
6eeee4d6
YM
5806 check_x ();
5807
f9d64bb3 5808 GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
24ca7c5a 5809
5ae53dcf 5810 if (popup_activated ())
24ca7c5a
JD
5811 error ("Trying to use a menu from within a menu-entry");
5812
488dd4c4
JD
5813 CHECK_STRING (prompt);
5814 CHECK_STRING (dir);
5815
5816 /* Prevent redisplay. */
5817 specbind (Qinhibit_redisplay, Qt);
24ca7c5a 5818 record_unwind_protect (clean_up_dialog, Qnil);
488dd4c4
JD
5819
5820 BLOCK_INPUT;
5821
5822 if (STRINGP (default_filename))
5823 cdef_file = SDATA (default_filename);
5824 else
5825 cdef_file = SDATA (dir);
5826
f9d64bb3
JD
5827 fn = xg_get_file_name (f, SDATA (prompt), cdef_file,
5828 ! NILP (mustmatch),
5829 ! NILP (only_dir_p));
177c0ea7 5830
488dd4c4
JD
5831 if (fn)
5832 {
5833 file = build_string (fn);
5834 xfree (fn);
5835 }
5836
5837 UNBLOCK_INPUT;
5838 UNGCPRO;
5839
5840 /* Make "Cancel" equivalent to C-g. */
5841 if (NILP (file))
5842 Fsignal (Qquit, Qnil);
177c0ea7 5843
a8f4bdc6
JD
5844 decoded_file = DECODE_FILE (file);
5845
5846 return unbind_to (count, decoded_file);
488dd4c4
JD
5847}
5848
5849#endif /* USE_GTK */
333b20bb
GM
5850
5851\f
82bab41c
GM
5852/***********************************************************************
5853 Keyboard
5854 ***********************************************************************/
5855
5856#ifdef HAVE_XKBGETKEYBOARD
5857#include <X11/XKBlib.h>
5858#include <X11/keysym.h>
5859#endif
5860
5861DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
5862 Sx_backspace_delete_keys_p, 0, 1, 0,
7ee72033 5863 doc: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
c061c855
GM
5864FRAME nil means use the selected frame.
5865Value is t if we know that both keys are present, and are mapped to the
20d1c5c5
DN
5866usual X keysyms. Value is `lambda' if we cannot determine if both keys are
5867present and mapped to the usual X keysyms. */)
7ee72033 5868 (frame)
82bab41c
GM
5869 Lisp_Object frame;
5870{
5871#ifdef HAVE_XKBGETKEYBOARD
5872 XkbDescPtr kb;
5873 struct frame *f = check_x_frame (frame);
5874 Display *dpy = FRAME_X_DISPLAY (f);
5875 Lisp_Object have_keys;
46f6a258 5876 int major, minor, op, event, error;
82bab41c
GM
5877
5878 BLOCK_INPUT;
46f6a258
GM
5879
5880 /* Check library version in case we're dynamically linked. */
5881 major = XkbMajorVersion;
5882 minor = XkbMinorVersion;
5883 if (!XkbLibraryVersion (&major, &minor))
c1efd260
GM
5884 {
5885 UNBLOCK_INPUT;
20d1c5c5 5886 return Qlambda;
c1efd260 5887 }
46f6a258
GM
5888
5889 /* Check that the server supports XKB. */
5890 major = XkbMajorVersion;
5891 minor = XkbMinorVersion;
5892 if (!XkbQueryExtension (dpy, &op, &event, &error, &major, &minor))
c1efd260
GM
5893 {
5894 UNBLOCK_INPUT;
20d1c5c5 5895 return Qlambda;
c1efd260 5896 }
177c0ea7 5897
3a441526
JD
5898 /* In this code we check that the keyboard has physical keys with names
5899 that start with BKSP (Backspace) and DELE (Delete), and that they
5900 generate keysym XK_BackSpace and XK_Delete respectively.
5901 This function is used to test if normal-erase-is-backspace should be
5902 turned on.
5903 An alternative approach would be to just check if XK_BackSpace and
5904 XK_Delete are mapped to any key. But if any of those are mapped to
5905 some non-intuitive key combination (Meta-Shift-Ctrl-whatever) and the
5906 user doesn't know about it, it is better to return false here.
5907 It is more obvious to the user what to do if she/he has two keys
5908 clearly marked with names/symbols and one key does something not
5909 expected (i.e. she/he then tries the other).
5910 The cases where Backspace/Delete is mapped to some other key combination
5911 are rare, and in those cases, normal-erase-is-backspace can be turned on
5912 manually. */
5913
46f6a258 5914 have_keys = Qnil;
c1efd260 5915 kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
82bab41c
GM
5916 if (kb)
5917 {
5918 int delete_keycode = 0, backspace_keycode = 0, i;
c1efd260
GM
5919
5920 if (XkbGetNames (dpy, XkbAllNamesMask, kb) == Success)
82bab41c 5921 {
c1efd260
GM
5922 for (i = kb->min_key_code;
5923 (i < kb->max_key_code
5924 && (delete_keycode == 0 || backspace_keycode == 0));
5925 ++i)
5926 {
d63931a2
GM
5927 /* The XKB symbolic key names can be seen most easily in
5928 the PS file generated by `xkbprint -label name
5929 $DISPLAY'. */
c1efd260
GM
5930 if (bcmp ("DELE", kb->names->keys[i].name, 4) == 0)
5931 delete_keycode = i;
5932 else if (bcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
5933 backspace_keycode = i;
5934 }
5935
5936 XkbFreeNames (kb, 0, True);
82bab41c
GM
5937 }
5938
c1efd260 5939 XkbFreeClientMap (kb, 0, True);
177c0ea7 5940
82bab41c
GM
5941 if (delete_keycode
5942 && backspace_keycode
5943 && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
5944 && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
5945 have_keys = Qt;
5946 }
5947 UNBLOCK_INPUT;
5948 return have_keys;
5949#else /* not HAVE_XKBGETKEYBOARD */
20d1c5c5 5950 return Qlambda;
82bab41c
GM
5951#endif /* not HAVE_XKBGETKEYBOARD */
5952}
5953
5954
5955\f
333b20bb
GM
5956/***********************************************************************
5957 Initialization
5958 ***********************************************************************/
5959
4dacadcc 5960/* Keep this list in the same order as frame_parms in frame.c.
7c0d3ed8
KS
5961 Use 0 for unsupported frame parameters. */
5962
5963frame_parm_handler x_frame_parm_handlers[] =
5964{
5965 x_set_autoraise,
5966 x_set_autolower,
5967 x_set_background_color,
5968 x_set_border_color,
5969 x_set_border_width,
5970 x_set_cursor_color,
5971 x_set_cursor_type,
5972 x_set_font,
5973 x_set_foreground_color,
5974 x_set_icon_name,
5975 x_set_icon_type,
5976 x_set_internal_border_width,
5977 x_set_menu_bar_lines,
5978 x_set_mouse_color,
5979 x_explicitly_set_name,
5980 x_set_scroll_bar_width,
5981 x_set_title,
5982 x_set_unsplittable,
5983 x_set_vertical_scroll_bars,
5984 x_set_visibility,
5985 x_set_tool_bar_lines,
5986 x_set_scroll_bar_foreground,
5987 x_set_scroll_bar_background,
5988 x_set_screen_gamma,
5989 x_set_line_spacing,
5990 x_set_fringe_width,
5991 x_set_fringe_width,
5992 x_set_wait_for_wm,
5993 x_set_fullscreen,
297cc20a
KH
5994#ifdef USE_FONT_BACKEND
5995 x_set_font_backend
5996#endif /* USE_FONT_BACKEND */
7c0d3ed8
KS
5997};
5998
333b20bb
GM
5999void
6000syms_of_xfns ()
6001{
6002 /* This is zero if not using X windows. */
6003 x_in_use = 0;
6004
6005 /* The section below is built by the lisp expression at the top of the file,
6006 just above where these variables are declared. */
6007 /*&&& init symbols here &&&*/
baaed68e
JB
6008 Qnone = intern ("none");
6009 staticpro (&Qnone);
8af1d7ca
JB
6010 Qsuppress_icon = intern ("suppress-icon");
6011 staticpro (&Qsuppress_icon);
01f1ba30 6012 Qundefined_color = intern ("undefined-color");
f9942c9e 6013 staticpro (&Qundefined_color);
96db09e4
KH
6014 Qcompound_text = intern ("compound-text");
6015 staticpro (&Qcompound_text);
ae782866
GM
6016 Qcancel_timer = intern ("cancel-timer");
6017 staticpro (&Qcancel_timer);
f9942c9e
JB
6018 /* This is the end of symbol initialization. */
6019
58cad5ed
KH
6020 /* Text property `display' should be nonsticky by default. */
6021 Vtext_property_default_nonsticky
6022 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
6023
6024
01f1ba30
JB
6025 Fput (Qundefined_color, Qerror_conditions,
6026 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
6027 Fput (Qundefined_color, Qerror_message,
6028 build_string ("Undefined color"));
6029
7ee72033
MB
6030 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
6031 doc: /* The shape of the pointer when over text.
c061c855
GM
6032Changing the value does not affect existing frames
6033unless you set the mouse color. */);
01f1ba30
JB
6034 Vx_pointer_shape = Qnil;
6035
ca0ecbf5 6036#if 0 /* This doesn't really do anything. */
7ee72033
MB
6037 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
6038 doc: /* The shape of the pointer when not over text.
c061c855
GM
6039This variable takes effect when you create a new frame
6040or when you set the mouse color. */);
af01ef26 6041#endif
01f1ba30
JB
6042 Vx_nontext_pointer_shape = Qnil;
6043
7ee72033
MB
6044 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
6045 doc: /* The shape of the pointer when Emacs is busy.
c061c855
GM
6046This variable takes effect when you create a new frame
6047or when you set the mouse color. */);
0af913d7 6048 Vx_hourglass_pointer_shape = Qnil;
333b20bb 6049
7ee72033
MB
6050 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
6051 doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
0af913d7 6052 display_hourglass_p = 1;
177c0ea7 6053
7ee72033
MB
6054 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
6055 doc: /* *Seconds to wait before displaying an hourglass pointer.
c061c855 6056Value must be an integer or float. */);
0af913d7 6057 Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
4ae9a85e 6058
ca0ecbf5 6059#if 0 /* This doesn't really do anything. */
7ee72033
MB
6060 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
6061 doc: /* The shape of the pointer when over the mode line.
c061c855
GM
6062This variable takes effect when you create a new frame
6063or when you set the mouse color. */);
af01ef26 6064#endif
01f1ba30
JB
6065 Vx_mode_pointer_shape = Qnil;
6066
d3b06468 6067 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
7ee72033
MB
6068 &Vx_sensitive_text_pointer_shape,
6069 doc: /* The shape of the pointer when over mouse-sensitive text.
c061c855
GM
6070This variable takes effect when you create a new frame
6071or when you set the mouse color. */);
ca0ecbf5 6072 Vx_sensitive_text_pointer_shape = Qnil;
95f80c78 6073
8fb4ec9c 6074 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
7ee72033
MB
6075 &Vx_window_horizontal_drag_shape,
6076 doc: /* Pointer shape to use for indicating a window can be dragged horizontally.
c061c855
GM
6077This variable takes effect when you create a new frame
6078or when you set the mouse color. */);
8fb4ec9c
GM
6079 Vx_window_horizontal_drag_shape = Qnil;
6080
7ee72033
MB
6081 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
6082 doc: /* A string indicating the foreground color of the cursor box. */);
01f1ba30
JB
6083 Vx_cursor_fore_pixel = Qnil;
6084
7ee72033
MB
6085 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size,
6086 doc: /* Maximum size for tooltips. Value is a pair (COLUMNS . ROWS).
c061c855 6087Text larger than this is clipped. */);
d63931a2 6088 Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
177c0ea7 6089
7ee72033
MB
6090 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
6091 doc: /* Non-nil if no X window manager is in use.
c061c855
GM
6092Emacs doesn't try to figure this out; this is always nil
6093unless you set it to something else. */);
2d38195d
RS
6094 /* We don't have any way to find this out, so set it to nil
6095 and maybe the user would like to set it to t. */
6096 Vx_no_window_manager = Qnil;
1d3dac41 6097
942ea06d 6098 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
7ee72033
MB
6099 &Vx_pixel_size_width_font_regexp,
6100 doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
c061c855
GM
6101
6102Since Emacs gets width of a font matching with this regexp from
6103PIXEL_SIZE field of the name, font finding mechanism gets faster for
6104such a font. This is especially effective for such large fonts as
6105Chinese, Japanese, and Korean. */);
942ea06d
KH
6106 Vx_pixel_size_width_font_regexp = Qnil;
6107
255e4140 6108/* This is not ifdef:ed, so other builds than GTK can customize it. */
fe2b14b7 6109 DEFVAR_BOOL ("x-gtk-use-old-file-dialog", &x_gtk_use_old_file_dialog,
255e4140
JD
6110 doc: /* *Non-nil means prompt with the old GTK file selection dialog.
6111If nil or if the file selection dialog is not available, the new GTK file
6112chooser is used instead. To turn off all file dialogs set the
6113variable `use-file-dialog'. */);
fe2b14b7 6114 x_gtk_use_old_file_dialog = 0;
255e4140 6115
a8a35720
JD
6116 DEFVAR_BOOL ("x-gtk-show-hidden-files", &x_gtk_show_hidden_files,
6117 doc: /* *If non-nil, the GTK file chooser will by default show hidden files.
6118Note that this is just the default, there is a toggle button on the file
6119chooser to show or not show hidden files on a case by case basis. */);
6120 x_gtk_show_hidden_files = 0;
6121
159f8da7 6122 DEFVAR_BOOL ("x-gtk-file-dialog-help-text", &x_gtk_file_dialog_help_text,
66687b7c 6123 doc: /* *If non-nil, the GTK file chooser will show additional help text.
641c0105
JD
6124If more space for files in the file chooser dialog is wanted, set this to nil
6125to turn the additional text off. */);
159f8da7 6126 x_gtk_file_dialog_help_text = 1;
641c0105 6127
e0f467cb
JD
6128 DEFVAR_BOOL ("x-gtk-whole-detached-tool-bar", &x_gtk_whole_detached_tool_bar,
6129 doc: /* *If non-nil, a detached tool bar is shown in full.
6130The default is to just show an arrow and pressing on that arrow shows
6131the tool bar buttons. */);
6132 x_gtk_whole_detached_tool_bar = 0;
6133
49be9d28
RS
6134 Fprovide (intern ("x"), Qnil);
6135
1d3dac41 6136#ifdef USE_X_TOOLKIT
6f3f6a8d 6137 Fprovide (intern ("x-toolkit"), Qnil);
5b827abb 6138#ifdef USE_MOTIF
6f3f6a8d 6139 Fprovide (intern ("motif"), Qnil);
fc2cdd9a 6140
7ee72033
MB
6141 DEFVAR_LISP ("motif-version-string", &Vmotif_version_string,
6142 doc: /* Version info for LessTif/Motif. */);
fc2cdd9a
GM
6143 Vmotif_version_string = build_string (XmVERSION_STRING);
6144#endif /* USE_MOTIF */
6145#endif /* USE_X_TOOLKIT */
01f1ba30 6146
6b61353c 6147#ifdef USE_GTK
1ec2a572
JD
6148 /* Provide x-toolkit also for GTK. Internally GTK does not use Xt so it
6149 is not an X toolkit in that sense (USE_X_TOOLKIT is not defined).
6150 But for a user it is a toolkit for X, and indeed, configure
6151 accepts --with-x-toolkit=gtk. */
6152 Fprovide (intern ("x-toolkit"), Qnil);
6b61353c
KH
6153 Fprovide (intern ("gtk"), Qnil);
6154
6155 DEFVAR_LISP ("gtk-version-string", &Vgtk_version_string,
6156 doc: /* Version info for GTK+. */);
6157 {
6158 char gtk_version[40];
6159 g_snprintf (gtk_version, sizeof (gtk_version), "%u.%u.%u",
6160 GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
6161 Vgtk_version_string = build_string (gtk_version);
6162 }
6163#endif /* USE_GTK */
6164
333b20bb
GM
6165 /* X window properties. */
6166 defsubr (&Sx_change_window_property);
6167 defsubr (&Sx_delete_window_property);
6168 defsubr (&Sx_window_property);
6169
2d764c78 6170 defsubr (&Sxw_display_color_p);
d0c9d219 6171 defsubr (&Sx_display_grayscale_p);
2d764c78
EZ
6172 defsubr (&Sxw_color_defined_p);
6173 defsubr (&Sxw_color_values);
9d317b2c 6174 defsubr (&Sx_server_max_request_size);
41beb8fc
RS
6175 defsubr (&Sx_server_vendor);
6176 defsubr (&Sx_server_version);
6177 defsubr (&Sx_display_pixel_width);
6178 defsubr (&Sx_display_pixel_height);
6179 defsubr (&Sx_display_mm_width);
6180 defsubr (&Sx_display_mm_height);
6181 defsubr (&Sx_display_screens);
6182 defsubr (&Sx_display_planes);
6183 defsubr (&Sx_display_color_cells);
6184 defsubr (&Sx_display_visual_class);
6185 defsubr (&Sx_display_backing_store);
6186 defsubr (&Sx_display_save_under);
f676886a 6187 defsubr (&Sx_create_frame);
01f1ba30 6188 defsubr (&Sx_open_connection);
08a90d6a
RS
6189 defsubr (&Sx_close_connection);
6190 defsubr (&Sx_display_list);
01f1ba30 6191 defsubr (&Sx_synchronize);
3decc1e7 6192 defsubr (&Sx_focus_frame);
82bab41c 6193 defsubr (&Sx_backspace_delete_keys_p);
177c0ea7 6194
942ea06d
KH
6195 /* Setting callback functions for fontset handler. */
6196 get_font_info_func = x_get_font_info;
333b20bb
GM
6197
6198#if 0 /* This function pointer doesn't seem to be used anywhere.
6199 And the pointer assigned has the wrong type, anyway. */
942ea06d 6200 list_fonts_func = x_list_fonts;
333b20bb 6201#endif
177c0ea7 6202
942ea06d 6203 load_font_func = x_load_font;
bc1958c4 6204 find_ccl_program_func = x_find_ccl_program;
942ea06d
KH
6205 query_font_func = x_query_font;
6206 set_frame_fontset_func = x_set_font;
5f652afc 6207 get_font_repertory_func = x_get_font_repertory;
942ea06d 6208 check_window_system_func = check_x;
333b20bb 6209
0af913d7
GM
6210 hourglass_atimer = NULL;
6211 hourglass_shown_p = 0;
333b20bb
GM
6212
6213 defsubr (&Sx_show_tip);
6214 defsubr (&Sx_hide_tip);
333b20bb 6215 tip_timer = Qnil;
44b5a125
GM
6216 staticpro (&tip_timer);
6217 tip_frame = Qnil;
6218 staticpro (&tip_frame);
333b20bb 6219
06d62053
GM
6220 last_show_tip_args = Qnil;
6221 staticpro (&last_show_tip_args);
6222
90f2e16b 6223 defsubr (&Sx_uses_old_gtk_dialog);
29fabd8c 6224#if defined (USE_MOTIF) || defined (USE_GTK)
333b20bb
GM
6225 defsubr (&Sx_file_dialog);
6226#endif
6227}
6228
01f1ba30 6229#endif /* HAVE_X_WINDOWS */
6b61353c
KH
6230
6231/* arch-tag: 55040d02-5485-4d58-8b22-95a7a05f3288
6232 (do not change this comment) */