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