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