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