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