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