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