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