Revision: miles@gnu.org--gnu-2005/emacs--unicode--0--patch-68
[bpt/emacs.git] / 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.
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 unsigned char *
1520 x_encode_text (string, coding_system, selectionp, text_bytes, stringp)
1521 Lisp_Object string, coding_system;
1522 int *text_bytes, *stringp;
1523 int selectionp;
1524 {
1525 int result = string_xstring_p (string);
1526 struct coding_system coding;
1527
1528 if (result == 0)
1529 {
1530 /* No multibyte character in OBJ. We need not encode it. */
1531 *text_bytes = SBYTES (string);
1532 *stringp = 1;
1533 return SDATA (string);
1534 }
1535
1536 setup_coding_system (coding_system, &coding);
1537 coding.mode |= (CODING_MODE_SAFE_ENCODING | CODING_MODE_LAST_BLOCK);
1538 /* We suppress producing escape sequences for composition. */
1539 coding.common_flags &= ~CODING_ANNOTATION_MASK;
1540 coding.dst_bytes = SCHARS (string) * 2;
1541 coding.destination = (unsigned char *) xmalloc (coding.dst_bytes);
1542 encode_coding_object (&coding, string, 0, 0,
1543 SCHARS (string), SBYTES (string), Qnil);
1544 *text_bytes = coding.produced;
1545 *stringp = (result == 1 || !EQ (coding_system, Qcompound_text));
1546 return coding.destination;
1547 }
1548
1549 \f
1550 /* Set the WM name to NAME for frame F. Also set the icon name.
1551 If the frame already has an icon name, use that, otherwise set the
1552 icon name to NAME. */
1553
1554 static void
1555 x_set_name_internal (f, name)
1556 FRAME_PTR f;
1557 Lisp_Object name;
1558 {
1559 if (FRAME_X_WINDOW (f))
1560 {
1561 BLOCK_INPUT;
1562 #ifdef HAVE_X11R4
1563 {
1564 XTextProperty text, icon;
1565 int bytes, stringp;
1566 int do_free_icon_value = 0, do_free_text_value = 0;
1567 Lisp_Object coding_system;
1568
1569 coding_system = Qcompound_text;
1570 /* Note: Encoding strategy
1571
1572 We encode NAME by compound-text and use "COMPOUND-TEXT" in
1573 text.encoding. But, there are non-internationalized window
1574 managers which don't support that encoding. So, if NAME
1575 contains only ASCII and 8859-1 characters, encode it by
1576 iso-latin-1, and use "STRING" in text.encoding hoping that
1577 such window managers at least analyze this format correctly,
1578 i.e. treat 8-bit bytes as 8859-1 characters.
1579
1580 We may also be able to use "UTF8_STRING" in text.encoding
1581 in the future which can encode all Unicode characters.
1582 But, for the moment, there's no way to know that the
1583 current window manager supports it or not. */
1584 text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp);
1585 text.encoding = (stringp ? XA_STRING
1586 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
1587 text.format = 8;
1588 text.nitems = bytes;
1589
1590 /* Check early, because ENCODE_UTF_8 below may GC and name may be
1591 relocated. */
1592 do_free_text_value = text.value != SDATA (name);
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);
1603 icon.encoding = (stringp ? XA_STRING
1604 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
1605 icon.format = 8;
1606 icon.nitems = bytes;
1607 do_free_icon_value = icon.value != SDATA (f->icon_name);
1608 }
1609
1610 #ifdef USE_GTK
1611 gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
1612 SDATA (ENCODE_UTF_8 (name)));
1613 #else /* not USE_GTK */
1614 XSetWMName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
1615 #endif /* not USE_GTK */
1616
1617 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &icon);
1618
1619 if (do_free_icon_value)
1620 xfree (icon.value);
1621 if (do_free_text_value)
1622 xfree (text.value);
1623 }
1624 #else /* not HAVE_X11R4 */
1625 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1626 SDATA (name));
1627 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1628 SDATA (name));
1629 #endif /* not HAVE_X11R4 */
1630 UNBLOCK_INPUT;
1631 }
1632 }
1633
1634 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
1635 x_id_name.
1636
1637 If EXPLICIT is non-zero, that indicates that lisp code is setting the
1638 name; if NAME is a string, set F's name to NAME and set
1639 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1640
1641 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1642 suggesting a new name, which lisp code should override; if
1643 F->explicit_name is set, ignore the new name; otherwise, set it. */
1644
1645 void
1646 x_set_name (f, name, explicit)
1647 struct frame *f;
1648 Lisp_Object name;
1649 int explicit;
1650 {
1651 /* Make sure that requests from lisp code override requests from
1652 Emacs redisplay code. */
1653 if (explicit)
1654 {
1655 /* If we're switching from explicit to implicit, we had better
1656 update the mode lines and thereby update the title. */
1657 if (f->explicit_name && NILP (name))
1658 update_mode_lines = 1;
1659
1660 f->explicit_name = ! NILP (name);
1661 }
1662 else if (f->explicit_name)
1663 return;
1664
1665 /* If NAME is nil, set the name to the x_id_name. */
1666 if (NILP (name))
1667 {
1668 /* Check for no change needed in this very common case
1669 before we do any consing. */
1670 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
1671 SDATA (f->name)))
1672 return;
1673 name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
1674 }
1675 else
1676 CHECK_STRING (name);
1677
1678 /* Don't change the name if it's already NAME. */
1679 if (! NILP (Fstring_equal (name, f->name)))
1680 return;
1681
1682 f->name = name;
1683
1684 /* For setting the frame title, the title parameter should override
1685 the name parameter. */
1686 if (! NILP (f->title))
1687 name = f->title;
1688
1689 x_set_name_internal (f, name);
1690 }
1691
1692 /* This function should be called when the user's lisp code has
1693 specified a name for the frame; the name will override any set by the
1694 redisplay code. */
1695 void
1696 x_explicitly_set_name (f, arg, oldval)
1697 FRAME_PTR f;
1698 Lisp_Object arg, oldval;
1699 {
1700 x_set_name (f, arg, 1);
1701 }
1702
1703 /* This function should be called by Emacs redisplay code to set the
1704 name; names set this way will never override names set by the user's
1705 lisp code. */
1706 void
1707 x_implicitly_set_name (f, arg, oldval)
1708 FRAME_PTR f;
1709 Lisp_Object arg, oldval;
1710 {
1711 x_set_name (f, arg, 0);
1712 }
1713 \f
1714 /* Change the title of frame F to NAME.
1715 If NAME is nil, use the frame name as the title.
1716
1717 If EXPLICIT is non-zero, that indicates that lisp code is setting the
1718 name; if NAME is a string, set F's name to NAME and set
1719 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1720
1721 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1722 suggesting a new name, which lisp code should override; if
1723 F->explicit_name is set, ignore the new name; otherwise, set it. */
1724
1725 void
1726 x_set_title (f, name, old_name)
1727 struct frame *f;
1728 Lisp_Object name, old_name;
1729 {
1730 /* Don't change the title if it's already NAME. */
1731 if (EQ (name, f->title))
1732 return;
1733
1734 update_mode_lines = 1;
1735
1736 f->title = name;
1737
1738 if (NILP (name))
1739 name = f->name;
1740 else
1741 CHECK_STRING (name);
1742
1743 x_set_name_internal (f, name);
1744 }
1745
1746 void
1747 x_set_scroll_bar_default_width (f)
1748 struct frame *f;
1749 {
1750 int wid = FRAME_COLUMN_WIDTH (f);
1751
1752 #ifdef USE_TOOLKIT_SCROLL_BARS
1753 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
1754 int width = 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM;
1755 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (width + wid - 1) / wid;
1756 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = width;
1757 #else
1758 /* Make the actual width at least 14 pixels and a multiple of a
1759 character width. */
1760 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
1761
1762 /* Use all of that space (aside from required margins) for the
1763 scroll bar. */
1764 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = 0;
1765 #endif
1766 }
1767
1768 \f
1769 /* Record in frame F the specified or default value according to ALIST
1770 of the parameter named PROP (a Lisp symbol). If no value is
1771 specified for PROP, look for an X default for XPROP on the frame
1772 named NAME. If that is not found either, use the value DEFLT. */
1773
1774 static Lisp_Object
1775 x_default_scroll_bar_color_parameter (f, alist, prop, xprop, xclass,
1776 foreground_p)
1777 struct frame *f;
1778 Lisp_Object alist;
1779 Lisp_Object prop;
1780 char *xprop;
1781 char *xclass;
1782 int foreground_p;
1783 {
1784 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
1785 Lisp_Object tem;
1786
1787 tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING);
1788 if (EQ (tem, Qunbound))
1789 {
1790 #ifdef USE_TOOLKIT_SCROLL_BARS
1791
1792 /* See if an X resource for the scroll bar color has been
1793 specified. */
1794 tem = display_x_get_resource (dpyinfo,
1795 build_string (foreground_p
1796 ? "foreground"
1797 : "background"),
1798 empty_string,
1799 build_string ("verticalScrollBar"),
1800 empty_string);
1801 if (!STRINGP (tem))
1802 {
1803 /* If nothing has been specified, scroll bars will use a
1804 toolkit-dependent default. Because these defaults are
1805 difficult to get at without actually creating a scroll
1806 bar, use nil to indicate that no color has been
1807 specified. */
1808 tem = Qnil;
1809 }
1810
1811 #else /* not USE_TOOLKIT_SCROLL_BARS */
1812
1813 tem = Qnil;
1814
1815 #endif /* not USE_TOOLKIT_SCROLL_BARS */
1816 }
1817
1818 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
1819 return tem;
1820 }
1821
1822
1823
1824 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
1825
1826 Status
1827 XSetWMProtocols (dpy, w, protocols, count)
1828 Display *dpy;
1829 Window w;
1830 Atom *protocols;
1831 int count;
1832 {
1833 Atom prop;
1834 prop = XInternAtom (dpy, "WM_PROTOCOLS", False);
1835 if (prop == None) return False;
1836 XChangeProperty (dpy, w, prop, XA_ATOM, 32, PropModeReplace,
1837 (unsigned char *) protocols, count);
1838 return True;
1839 }
1840 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
1841 \f
1842 #ifdef USE_X_TOOLKIT
1843
1844 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
1845 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
1846 already be present because of the toolkit (Motif adds some of them,
1847 for example, but Xt doesn't). */
1848
1849 static void
1850 hack_wm_protocols (f, widget)
1851 FRAME_PTR f;
1852 Widget widget;
1853 {
1854 Display *dpy = XtDisplay (widget);
1855 Window w = XtWindow (widget);
1856 int need_delete = 1;
1857 int need_focus = 1;
1858 int need_save = 1;
1859
1860 BLOCK_INPUT;
1861 {
1862 Atom type;
1863 unsigned char *catoms;
1864 int format = 0;
1865 unsigned long nitems = 0;
1866 unsigned long bytes_after;
1867
1868 if ((XGetWindowProperty (dpy, w,
1869 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
1870 (long)0, (long)100, False, XA_ATOM,
1871 &type, &format, &nitems, &bytes_after,
1872 &catoms)
1873 == Success)
1874 && format == 32 && type == XA_ATOM)
1875 {
1876 Atom *atoms = (Atom *) catoms;
1877 while (nitems > 0)
1878 {
1879 nitems--;
1880 if (atoms[nitems]
1881 == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
1882 need_delete = 0;
1883 else if (atoms[nitems]
1884 == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
1885 need_focus = 0;
1886 else if (atoms[nitems]
1887 == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
1888 need_save = 0;
1889 }
1890 }
1891 if (catoms)
1892 XFree (catoms);
1893 }
1894 {
1895 Atom props [10];
1896 int count = 0;
1897 if (need_delete)
1898 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
1899 if (need_focus)
1900 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus;
1901 if (need_save)
1902 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
1903 if (count)
1904 XChangeProperty (dpy, w, FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
1905 XA_ATOM, 32, PropModeAppend,
1906 (unsigned char *) props, count);
1907 }
1908 UNBLOCK_INPUT;
1909 }
1910 #endif
1911
1912
1913 \f
1914 /* Support routines for XIC (X Input Context). */
1915
1916 #ifdef HAVE_X_I18N
1917
1918 static XFontSet xic_create_xfontset P_ ((struct frame *, char *));
1919 static XIMStyle best_xim_style P_ ((XIMStyles *, XIMStyles *));
1920
1921
1922 /* Supported XIM styles, ordered by preference. */
1923
1924 static XIMStyle supported_xim_styles[] =
1925 {
1926 XIMPreeditPosition | XIMStatusArea,
1927 XIMPreeditPosition | XIMStatusNothing,
1928 XIMPreeditPosition | XIMStatusNone,
1929 XIMPreeditNothing | XIMStatusArea,
1930 XIMPreeditNothing | XIMStatusNothing,
1931 XIMPreeditNothing | XIMStatusNone,
1932 XIMPreeditNone | XIMStatusArea,
1933 XIMPreeditNone | XIMStatusNothing,
1934 XIMPreeditNone | XIMStatusNone,
1935 0,
1936 };
1937
1938
1939 /* Create an X fontset on frame F with base font name BASE_FONTNAME. */
1940
1941 char xic_defaut_fontset[] = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
1942
1943 /* Create an Xt fontset spec from the name of a base font.
1944 If `motif' is True use the Motif syntax. */
1945 char *
1946 xic_create_fontsetname (base_fontname, motif)
1947 char *base_fontname;
1948 Bool motif;
1949 {
1950 const char *sep = motif ? ";" : ",";
1951 char *fontsetname;
1952
1953 /* Make a fontset name from the base font name. */
1954 if (xic_defaut_fontset == base_fontname)
1955 { /* There is no base font name, use the default. */
1956 int len = strlen (base_fontname) + 2;
1957 fontsetname = xmalloc (len);
1958 bzero (fontsetname, len);
1959 strcpy (fontsetname, base_fontname);
1960 }
1961 else
1962 {
1963 /* Make a fontset name from the base font name.
1964 The font set will be made of the following elements:
1965 - the base font.
1966 - the base font where the charset spec is replaced by -*-*.
1967 - the same but with the family also replaced with -*-*-. */
1968 char *p = base_fontname;
1969 int i;
1970
1971 for (i = 0; *p; p++)
1972 if (*p == '-') i++;
1973 if (i != 14)
1974 { /* As the font name doesn't conform to XLFD, we can't
1975 modify it to generalize it to allcs and allfamilies.
1976 Use the specified font plus the default. */
1977 int len = strlen (base_fontname) + strlen (xic_defaut_fontset) + 3;
1978 fontsetname = xmalloc (len);
1979 bzero (fontsetname, len);
1980 strcpy (fontsetname, base_fontname);
1981 strcat (fontsetname, sep);
1982 strcat (fontsetname, xic_defaut_fontset);
1983 }
1984 else
1985 {
1986 int len;
1987 char *p1 = NULL, *p2 = NULL;
1988 char *font_allcs = NULL;
1989 char *font_allfamilies = NULL;
1990 char *font_all = NULL;
1991 char *allcs = "*-*-*-*-*-*-*";
1992 char *allfamilies = "-*-*-";
1993 char *all = "*-*-*-*-";
1994
1995 for (i = 0, p = base_fontname; i < 8; p++)
1996 {
1997 if (*p == '-')
1998 {
1999 i++;
2000 if (i == 3)
2001 p1 = p + 1;
2002 else if (i == 7)
2003 p2 = p + 1;
2004 }
2005 }
2006 /* Build the font spec that matches all charsets. */
2007 len = p - base_fontname + strlen (allcs) + 1;
2008 font_allcs = (char *) alloca (len);
2009 bzero (font_allcs, len);
2010 bcopy (base_fontname, font_allcs, p - base_fontname);
2011 strcat (font_allcs, allcs);
2012
2013 /* Build the font spec that matches all families. */
2014 len = p - p1 + strlen (allcs) + strlen (allfamilies) + 1;
2015 font_allfamilies = (char *) alloca (len);
2016 bzero (font_allfamilies, len);
2017 strcpy (font_allfamilies, allfamilies);
2018 bcopy (p1, font_allfamilies + strlen (allfamilies), p - p1);
2019 strcat (font_allfamilies, allcs);
2020
2021 /* Build the font spec that matches all. */
2022 len = p - p2 + strlen (allcs) + strlen (all) + strlen (allfamilies) + 1;
2023 font_all = (char *) alloca (len);
2024 bzero (font_all, len);
2025 strcpy (font_all, allfamilies);
2026 strcat (font_all, all);
2027 bcopy (p2, font_all + strlen (all) + strlen (allfamilies), p - p2);
2028 strcat (font_all, allcs);
2029
2030 /* Build the actual font set name. */
2031 len = strlen (base_fontname) + strlen (font_allcs)
2032 + strlen (font_allfamilies) + strlen (font_all) + 5;
2033 fontsetname = xmalloc (len);
2034 bzero (fontsetname, len);
2035 strcpy (fontsetname, base_fontname);
2036 strcat (fontsetname, sep);
2037 strcat (fontsetname, font_allcs);
2038 strcat (fontsetname, sep);
2039 strcat (fontsetname, font_allfamilies);
2040 strcat (fontsetname, sep);
2041 strcat (fontsetname, font_all);
2042 }
2043 }
2044 if (motif)
2045 strcat (fontsetname, ":");
2046 return fontsetname;
2047 }
2048
2049 static XFontSet
2050 xic_create_xfontset (f, base_fontname)
2051 struct frame *f;
2052 char *base_fontname;
2053 {
2054 XFontSet xfs = NULL;
2055 char **missing_list = NULL;
2056 int missing_count;
2057 char *def_string;
2058 Lisp_Object rest, frame;
2059
2060 if (!base_fontname)
2061 base_fontname = xic_defaut_fontset;
2062
2063 /* See if there is another frame already using same fontset. */
2064 FOR_EACH_FRAME (rest, frame)
2065 {
2066 struct frame *cf = XFRAME (frame);
2067 if (cf != f && FRAME_LIVE_P (f) && FRAME_X_P (cf)
2068 && FRAME_X_DISPLAY_INFO (cf) == FRAME_X_DISPLAY_INFO (f)
2069 && FRAME_XIC_BASE_FONTNAME (cf)
2070 && !strcmp (FRAME_XIC_BASE_FONTNAME (cf), base_fontname))
2071 {
2072 xfs = FRAME_XIC_FONTSET (cf);
2073 break;
2074 }
2075 }
2076
2077 if (!xfs)
2078 {
2079 char *fontsetname = xic_create_fontsetname (base_fontname, False);
2080
2081 /* New fontset. */
2082 xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
2083 fontsetname, &missing_list,
2084 &missing_count, &def_string);
2085 if (missing_list)
2086 XFreeStringList (missing_list);
2087 xfree (fontsetname);
2088 }
2089
2090 if (FRAME_XIC_BASE_FONTNAME (f))
2091 xfree (FRAME_XIC_BASE_FONTNAME (f));
2092 FRAME_XIC_BASE_FONTNAME (f) = xstrdup (base_fontname);
2093
2094 /* No need to free def_string. */
2095 return xfs;
2096 }
2097
2098 /* Free the X fontset of frame F if it is the last frame using it. */
2099
2100 void
2101 xic_free_xfontset (f)
2102 struct frame *f;
2103 {
2104 Lisp_Object rest, frame;
2105 int shared_p = 0;
2106
2107 if (!FRAME_XIC_FONTSET (f))
2108 return;
2109
2110 /* See if there is another frame sharing the same fontset. */
2111 FOR_EACH_FRAME (rest, frame)
2112 {
2113 struct frame *cf = XFRAME (frame);
2114 if (cf != f && FRAME_LIVE_P (f) && FRAME_X_P (cf)
2115 && FRAME_X_DISPLAY_INFO (cf) == FRAME_X_DISPLAY_INFO (f)
2116 && FRAME_XIC_FONTSET (cf) == FRAME_XIC_FONTSET (f))
2117 {
2118 shared_p = 1;
2119 break;
2120 }
2121 }
2122
2123 if (!shared_p)
2124 /* The fontset is not used anymore. It is safe to free it. */
2125 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
2126
2127 if (FRAME_XIC_BASE_FONTNAME (f))
2128 xfree (FRAME_XIC_BASE_FONTNAME (f));
2129 FRAME_XIC_BASE_FONTNAME (f) = NULL;
2130 FRAME_XIC_FONTSET (f) = NULL;
2131 }
2132
2133
2134 /* Value is the best input style, given user preferences USER (already
2135 checked to be supported by Emacs), and styles supported by the
2136 input method XIM. */
2137
2138 static XIMStyle
2139 best_xim_style (user, xim)
2140 XIMStyles *user;
2141 XIMStyles *xim;
2142 {
2143 int i, j;
2144
2145 for (i = 0; i < user->count_styles; ++i)
2146 for (j = 0; j < xim->count_styles; ++j)
2147 if (user->supported_styles[i] == xim->supported_styles[j])
2148 return user->supported_styles[i];
2149
2150 /* Return the default style. */
2151 return XIMPreeditNothing | XIMStatusNothing;
2152 }
2153
2154 /* Create XIC for frame F. */
2155
2156 static XIMStyle xic_style;
2157
2158 void
2159 create_frame_xic (f)
2160 struct frame *f;
2161 {
2162 XIM xim;
2163 XIC xic = NULL;
2164 XFontSet xfs = NULL;
2165
2166 if (FRAME_XIC (f))
2167 return;
2168
2169 /* Create X fontset. */
2170 xfs = xic_create_xfontset
2171 (f, (FRAME_FONTSET (f) < 0) ? NULL
2172 : (char *) SDATA (fontset_ascii (FRAME_FONTSET (f))));
2173
2174 xim = FRAME_X_XIM (f);
2175 if (xim)
2176 {
2177 XRectangle s_area;
2178 XPoint spot;
2179 XVaNestedList preedit_attr;
2180 XVaNestedList status_attr;
2181
2182 s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
2183 spot.x = 0; spot.y = 1;
2184
2185 /* Determine XIC style. */
2186 if (xic_style == 0)
2187 {
2188 XIMStyles supported_list;
2189 supported_list.count_styles = (sizeof supported_xim_styles
2190 / sizeof supported_xim_styles[0]);
2191 supported_list.supported_styles = supported_xim_styles;
2192 xic_style = best_xim_style (&supported_list,
2193 FRAME_X_XIM_STYLES (f));
2194 }
2195
2196 preedit_attr = XVaCreateNestedList (0,
2197 XNFontSet, xfs,
2198 XNForeground,
2199 FRAME_FOREGROUND_PIXEL (f),
2200 XNBackground,
2201 FRAME_BACKGROUND_PIXEL (f),
2202 (xic_style & XIMPreeditPosition
2203 ? XNSpotLocation
2204 : NULL),
2205 &spot,
2206 NULL);
2207 status_attr = XVaCreateNestedList (0,
2208 XNArea,
2209 &s_area,
2210 XNFontSet,
2211 xfs,
2212 XNForeground,
2213 FRAME_FOREGROUND_PIXEL (f),
2214 XNBackground,
2215 FRAME_BACKGROUND_PIXEL (f),
2216 NULL);
2217
2218 xic = XCreateIC (xim,
2219 XNInputStyle, xic_style,
2220 XNClientWindow, FRAME_X_WINDOW (f),
2221 XNFocusWindow, FRAME_X_WINDOW (f),
2222 XNStatusAttributes, status_attr,
2223 XNPreeditAttributes, preedit_attr,
2224 NULL);
2225 XFree (preedit_attr);
2226 XFree (status_attr);
2227 }
2228
2229 FRAME_XIC (f) = xic;
2230 FRAME_XIC_STYLE (f) = xic_style;
2231 FRAME_XIC_FONTSET (f) = xfs;
2232 }
2233
2234
2235 /* Destroy XIC and free XIC fontset of frame F, if any. */
2236
2237 void
2238 free_frame_xic (f)
2239 struct frame *f;
2240 {
2241 if (FRAME_XIC (f) == NULL)
2242 return;
2243
2244 XDestroyIC (FRAME_XIC (f));
2245 xic_free_xfontset (f);
2246
2247 FRAME_XIC (f) = NULL;
2248 }
2249
2250
2251 /* Place preedit area for XIC of window W's frame to specified
2252 pixel position X/Y. X and Y are relative to window W. */
2253
2254 void
2255 xic_set_preeditarea (w, x, y)
2256 struct window *w;
2257 int x, y;
2258 {
2259 struct frame *f = XFRAME (w->frame);
2260 XVaNestedList attr;
2261 XPoint spot;
2262
2263 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x) + WINDOW_LEFT_FRINGE_WIDTH (w);
2264 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
2265 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
2266 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
2267 XFree (attr);
2268 }
2269
2270
2271 /* Place status area for XIC in bottom right corner of frame F.. */
2272
2273 void
2274 xic_set_statusarea (f)
2275 struct frame *f;
2276 {
2277 XIC xic = FRAME_XIC (f);
2278 XVaNestedList attr;
2279 XRectangle area;
2280 XRectangle *needed;
2281
2282 /* Negotiate geometry of status area. If input method has existing
2283 status area, use its current size. */
2284 area.x = area.y = area.width = area.height = 0;
2285 attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
2286 XSetICValues (xic, XNStatusAttributes, attr, NULL);
2287 XFree (attr);
2288
2289 attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
2290 XGetICValues (xic, XNStatusAttributes, attr, NULL);
2291 XFree (attr);
2292
2293 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
2294 {
2295 attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
2296 XGetICValues (xic, XNStatusAttributes, attr, NULL);
2297 XFree (attr);
2298 }
2299
2300 area.width = needed->width;
2301 area.height = needed->height;
2302 area.x = FRAME_PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
2303 area.y = (FRAME_PIXEL_HEIGHT (f) - area.height
2304 - FRAME_MENUBAR_HEIGHT (f)
2305 - FRAME_TOOLBAR_HEIGHT (f)
2306 - FRAME_INTERNAL_BORDER_WIDTH (f));
2307 XFree (needed);
2308
2309 attr = XVaCreateNestedList (0, XNArea, &area, NULL);
2310 XSetICValues (xic, XNStatusAttributes, attr, NULL);
2311 XFree (attr);
2312 }
2313
2314
2315 /* Set X fontset for XIC of frame F, using base font name
2316 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
2317
2318 void
2319 xic_set_xfontset (f, base_fontname)
2320 struct frame *f;
2321 char *base_fontname;
2322 {
2323 XVaNestedList attr;
2324 XFontSet xfs;
2325
2326 xic_free_xfontset (f);
2327
2328 xfs = xic_create_xfontset (f, base_fontname);
2329
2330 attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
2331 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
2332 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
2333 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
2334 XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
2335 XFree (attr);
2336
2337 FRAME_XIC_FONTSET (f) = xfs;
2338 }
2339
2340 #endif /* HAVE_X_I18N */
2341
2342
2343 \f
2344 #ifdef USE_X_TOOLKIT
2345
2346 /* Create and set up the X widget for frame F. */
2347
2348 static void
2349 x_window (f, window_prompting, minibuffer_only)
2350 struct frame *f;
2351 long window_prompting;
2352 int minibuffer_only;
2353 {
2354 XClassHint class_hints;
2355 XSetWindowAttributes attributes;
2356 unsigned long attribute_mask;
2357 Widget shell_widget;
2358 Widget pane_widget;
2359 Widget frame_widget;
2360 Arg al [25];
2361 int ac;
2362
2363 BLOCK_INPUT;
2364
2365 /* Use the resource name as the top-level widget name
2366 for looking up resources. Make a non-Lisp copy
2367 for the window manager, so GC relocation won't bother it.
2368
2369 Elsewhere we specify the window name for the window manager. */
2370
2371 {
2372 char *str = (char *) SDATA (Vx_resource_name);
2373 f->namebuf = (char *) xmalloc (strlen (str) + 1);
2374 strcpy (f->namebuf, str);
2375 }
2376
2377 ac = 0;
2378 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
2379 XtSetArg (al[ac], XtNinput, 1); ac++;
2380 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
2381 XtSetArg (al[ac], XtNborderWidth, f->border_width); ac++;
2382 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2383 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
2384 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2385 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
2386 applicationShellWidgetClass,
2387 FRAME_X_DISPLAY (f), al, ac);
2388
2389 f->output_data.x->widget = shell_widget;
2390 /* maybe_set_screen_title_format (shell_widget); */
2391
2392 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
2393 (widget_value *) NULL,
2394 shell_widget, False,
2395 (lw_callback) NULL,
2396 (lw_callback) NULL,
2397 (lw_callback) NULL,
2398 (lw_callback) NULL);
2399
2400 ac = 0;
2401 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2402 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
2403 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2404 XtSetValues (pane_widget, al, ac);
2405 f->output_data.x->column_widget = pane_widget;
2406
2407 /* mappedWhenManaged to false tells to the paned window to not map/unmap
2408 the emacs screen when changing menubar. This reduces flickering. */
2409
2410 ac = 0;
2411 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
2412 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
2413 XtSetArg (al[ac], XtNallowResize, 1); ac++;
2414 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
2415 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
2416 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2417 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
2418 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2419 frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget,
2420 al, ac);
2421
2422 f->output_data.x->edit_widget = frame_widget;
2423
2424 XtManageChild (frame_widget);
2425
2426 /* Do some needed geometry management. */
2427 {
2428 int len;
2429 char *tem, shell_position[32];
2430 Arg al[10];
2431 int ac = 0;
2432 int extra_borders = 0;
2433 int menubar_size
2434 = (f->output_data.x->menubar_widget
2435 ? (f->output_data.x->menubar_widget->core.height
2436 + f->output_data.x->menubar_widget->core.border_width)
2437 : 0);
2438
2439 #if 0 /* Experimentally, we now get the right results
2440 for -geometry -0-0 without this. 24 Aug 96, rms. */
2441 if (FRAME_EXTERNAL_MENU_BAR (f))
2442 {
2443 Dimension ibw = 0;
2444 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
2445 menubar_size += ibw;
2446 }
2447 #endif
2448
2449 f->output_data.x->menubar_height = menubar_size;
2450
2451 #ifndef USE_LUCID
2452 /* Motif seems to need this amount added to the sizes
2453 specified for the shell widget. The Athena/Lucid widgets don't.
2454 Both conclusions reached experimentally. -- rms. */
2455 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
2456 &extra_borders, NULL);
2457 extra_borders *= 2;
2458 #endif
2459
2460 /* Convert our geometry parameters into a geometry string
2461 and specify it.
2462 Note that we do not specify here whether the position
2463 is a user-specified or program-specified one.
2464 We pass that information later, in x_wm_set_size_hints. */
2465 {
2466 int left = f->left_pos;
2467 int xneg = window_prompting & XNegative;
2468 int top = f->top_pos;
2469 int yneg = window_prompting & YNegative;
2470 if (xneg)
2471 left = -left;
2472 if (yneg)
2473 top = -top;
2474
2475 if (window_prompting & USPosition)
2476 sprintf (shell_position, "=%dx%d%c%d%c%d",
2477 FRAME_PIXEL_WIDTH (f) + extra_borders,
2478 FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders,
2479 (xneg ? '-' : '+'), left,
2480 (yneg ? '-' : '+'), top);
2481 else
2482 {
2483 sprintf (shell_position, "=%dx%d",
2484 FRAME_PIXEL_WIDTH (f) + extra_borders,
2485 FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders);
2486
2487 /* Setting x and y when the position is not specified in
2488 the geometry string will set program position in the WM hints.
2489 If Emacs had just one program position, we could set it in
2490 fallback resources, but since each make-frame call can specify
2491 different program positions, this is easier. */
2492 XtSetArg (al[ac], XtNx, left); ac++;
2493 XtSetArg (al[ac], XtNy, top); ac++;
2494 }
2495 }
2496
2497 len = strlen (shell_position) + 1;
2498 /* We don't free this because we don't know whether
2499 it is safe to free it while the frame exists.
2500 It isn't worth the trouble of arranging to free it
2501 when the frame is deleted. */
2502 tem = (char *) xmalloc (len);
2503 strncpy (tem, shell_position, len);
2504 XtSetArg (al[ac], XtNgeometry, tem); ac++;
2505 XtSetValues (shell_widget, al, ac);
2506 }
2507
2508 XtManageChild (pane_widget);
2509 XtRealizeWidget (shell_widget);
2510
2511 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
2512
2513 validate_x_resource_name ();
2514
2515 class_hints.res_name = (char *) SDATA (Vx_resource_name);
2516 class_hints.res_class = (char *) SDATA (Vx_resource_class);
2517 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
2518
2519 #ifdef HAVE_X_I18N
2520 FRAME_XIC (f) = NULL;
2521 if (use_xim)
2522 create_frame_xic (f);
2523 #endif
2524
2525 f->output_data.x->wm_hints.input = True;
2526 f->output_data.x->wm_hints.flags |= InputHint;
2527 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2528 &f->output_data.x->wm_hints);
2529
2530 hack_wm_protocols (f, shell_widget);
2531
2532 #ifdef HACK_EDITRES
2533 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
2534 #endif
2535
2536 /* Do a stupid property change to force the server to generate a
2537 PropertyNotify event so that the event_stream server timestamp will
2538 be initialized to something relevant to the time we created the window.
2539 */
2540 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
2541 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
2542 XA_ATOM, 32, PropModeAppend,
2543 (unsigned char*) NULL, 0);
2544
2545 /* Make all the standard events reach the Emacs frame. */
2546 attributes.event_mask = STANDARD_EVENT_SET;
2547
2548 #ifdef HAVE_X_I18N
2549 if (FRAME_XIC (f))
2550 {
2551 /* XIM server might require some X events. */
2552 unsigned long fevent = NoEventMask;
2553 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
2554 attributes.event_mask |= fevent;
2555 }
2556 #endif /* HAVE_X_I18N */
2557
2558 attribute_mask = CWEventMask;
2559 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
2560 attribute_mask, &attributes);
2561
2562 XtMapWidget (frame_widget);
2563
2564 /* x_set_name normally ignores requests to set the name if the
2565 requested name is the same as the current name. This is the one
2566 place where that assumption isn't correct; f->name is set, but
2567 the X server hasn't been told. */
2568 {
2569 Lisp_Object name;
2570 int explicit = f->explicit_name;
2571
2572 f->explicit_name = 0;
2573 name = f->name;
2574 f->name = Qnil;
2575 x_set_name (f, name, explicit);
2576 }
2577
2578 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2579 f->output_data.x->text_cursor);
2580
2581 UNBLOCK_INPUT;
2582
2583 /* This is a no-op, except under Motif. Make sure main areas are
2584 set to something reasonable, in case we get an error later. */
2585 lw_set_main_areas (pane_widget, 0, frame_widget);
2586 }
2587
2588 #else /* not USE_X_TOOLKIT */
2589 #ifdef USE_GTK
2590 void
2591 x_window (f)
2592 FRAME_PTR f;
2593 {
2594 if (! xg_create_frame_widgets (f))
2595 error ("Unable to create window");
2596
2597 #ifdef HAVE_X_I18N
2598 FRAME_XIC (f) = NULL;
2599 if (use_xim)
2600 {
2601 BLOCK_INPUT;
2602 create_frame_xic (f);
2603 if (FRAME_XIC (f))
2604 {
2605 /* XIM server might require some X events. */
2606 unsigned long fevent = NoEventMask;
2607 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
2608
2609 if (fevent != NoEventMask)
2610 {
2611 XSetWindowAttributes attributes;
2612 XWindowAttributes wattr;
2613 unsigned long attribute_mask;
2614
2615 XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2616 &wattr);
2617 attributes.event_mask = wattr.your_event_mask | fevent;
2618 attribute_mask = CWEventMask;
2619 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2620 attribute_mask, &attributes);
2621 }
2622 }
2623 UNBLOCK_INPUT;
2624 }
2625 #endif
2626 }
2627
2628 #else /*! USE_GTK */
2629 /* Create and set up the X window for frame F. */
2630
2631 void
2632 x_window (f)
2633 struct frame *f;
2634
2635 {
2636 XClassHint class_hints;
2637 XSetWindowAttributes attributes;
2638 unsigned long attribute_mask;
2639
2640 attributes.background_pixel = f->output_data.x->background_pixel;
2641 attributes.border_pixel = f->output_data.x->border_pixel;
2642 attributes.bit_gravity = StaticGravity;
2643 attributes.backing_store = NotUseful;
2644 attributes.save_under = True;
2645 attributes.event_mask = STANDARD_EVENT_SET;
2646 attributes.colormap = FRAME_X_COLORMAP (f);
2647 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
2648 | CWColormap);
2649
2650 BLOCK_INPUT;
2651 FRAME_X_WINDOW (f)
2652 = XCreateWindow (FRAME_X_DISPLAY (f),
2653 f->output_data.x->parent_desc,
2654 f->left_pos,
2655 f->top_pos,
2656 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
2657 f->border_width,
2658 CopyFromParent, /* depth */
2659 InputOutput, /* class */
2660 FRAME_X_VISUAL (f),
2661 attribute_mask, &attributes);
2662
2663 #ifdef HAVE_X_I18N
2664 if (use_xim)
2665 {
2666 create_frame_xic (f);
2667 if (FRAME_XIC (f))
2668 {
2669 /* XIM server might require some X events. */
2670 unsigned long fevent = NoEventMask;
2671 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
2672 attributes.event_mask |= fevent;
2673 attribute_mask = CWEventMask;
2674 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2675 attribute_mask, &attributes);
2676 }
2677 }
2678 #endif /* HAVE_X_I18N */
2679
2680 validate_x_resource_name ();
2681
2682 class_hints.res_name = (char *) SDATA (Vx_resource_name);
2683 class_hints.res_class = (char *) SDATA (Vx_resource_class);
2684 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
2685
2686 /* The menubar is part of the ordinary display;
2687 it does not count in addition to the height of the window. */
2688 f->output_data.x->menubar_height = 0;
2689
2690 /* This indicates that we use the "Passive Input" input model.
2691 Unless we do this, we don't get the Focus{In,Out} events that we
2692 need to draw the cursor correctly. Accursed bureaucrats.
2693 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
2694
2695 f->output_data.x->wm_hints.input = True;
2696 f->output_data.x->wm_hints.flags |= InputHint;
2697 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2698 &f->output_data.x->wm_hints);
2699 f->output_data.x->wm_hints.icon_pixmap = None;
2700
2701 /* Request "save yourself" and "delete window" commands from wm. */
2702 {
2703 Atom protocols[2];
2704 protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
2705 protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
2706 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
2707 }
2708
2709 /* x_set_name normally ignores requests to set the name if the
2710 requested name is the same as the current name. This is the one
2711 place where that assumption isn't correct; f->name is set, but
2712 the X server hasn't been told. */
2713 {
2714 Lisp_Object name;
2715 int explicit = f->explicit_name;
2716
2717 f->explicit_name = 0;
2718 name = f->name;
2719 f->name = Qnil;
2720 x_set_name (f, name, explicit);
2721 }
2722
2723 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2724 f->output_data.x->text_cursor);
2725
2726 UNBLOCK_INPUT;
2727
2728 if (FRAME_X_WINDOW (f) == 0)
2729 error ("Unable to create window");
2730 }
2731
2732 #endif /* not USE_GTK */
2733 #endif /* not USE_X_TOOLKIT */
2734
2735 /* Verify that the icon position args for this window are valid. */
2736
2737 static void
2738 x_icon_verify (f, parms)
2739 struct frame *f;
2740 Lisp_Object parms;
2741 {
2742 Lisp_Object icon_x, icon_y;
2743
2744 /* Set the position of the icon. Note that twm groups all
2745 icons in an icon window. */
2746 icon_x = x_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
2747 icon_y = x_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
2748 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
2749 {
2750 CHECK_NUMBER (icon_x);
2751 CHECK_NUMBER (icon_y);
2752 }
2753 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
2754 error ("Both left and top icon corners of icon must be specified");
2755 }
2756
2757 /* Handle the icon stuff for this window. Perhaps later we might
2758 want an x_set_icon_position which can be called interactively as
2759 well. */
2760
2761 static void
2762 x_icon (f, parms)
2763 struct frame *f;
2764 Lisp_Object parms;
2765 {
2766 Lisp_Object icon_x, icon_y;
2767 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2768
2769 /* Set the position of the icon. Note that twm groups all
2770 icons in an icon window. */
2771 icon_x = x_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
2772 icon_y = x_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
2773 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
2774 {
2775 CHECK_NUMBER (icon_x);
2776 CHECK_NUMBER (icon_y);
2777 }
2778 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
2779 error ("Both left and top icon corners of icon must be specified");
2780
2781 BLOCK_INPUT;
2782
2783 if (! EQ (icon_x, Qunbound))
2784 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
2785
2786 /* Start up iconic or window? */
2787 x_wm_set_window_state
2788 (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
2789 Qicon)
2790 ? IconicState
2791 : NormalState));
2792
2793 x_text_icon (f, (char *) SDATA ((!NILP (f->icon_name)
2794 ? f->icon_name
2795 : f->name)));
2796
2797 UNBLOCK_INPUT;
2798 }
2799
2800 /* Make the GCs needed for this window, setting the
2801 background, border and mouse colors; also create the
2802 mouse cursor and the gray border tile. */
2803
2804 static char cursor_bits[] =
2805 {
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2810 };
2811
2812 static void
2813 x_make_gc (f)
2814 struct frame *f;
2815 {
2816 XGCValues gc_values;
2817
2818 BLOCK_INPUT;
2819
2820 /* Create the GCs of this frame.
2821 Note that many default values are used. */
2822
2823 /* Normal video */
2824 gc_values.font = FRAME_FONT (f)->fid;
2825 gc_values.foreground = f->output_data.x->foreground_pixel;
2826 gc_values.background = f->output_data.x->background_pixel;
2827 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
2828 f->output_data.x->normal_gc
2829 = XCreateGC (FRAME_X_DISPLAY (f),
2830 FRAME_X_WINDOW (f),
2831 GCLineWidth | GCFont | GCForeground | GCBackground,
2832 &gc_values);
2833
2834 /* Reverse video style. */
2835 gc_values.foreground = f->output_data.x->background_pixel;
2836 gc_values.background = f->output_data.x->foreground_pixel;
2837 f->output_data.x->reverse_gc
2838 = XCreateGC (FRAME_X_DISPLAY (f),
2839 FRAME_X_WINDOW (f),
2840 GCFont | GCForeground | GCBackground | GCLineWidth,
2841 &gc_values);
2842
2843 /* Cursor has cursor-color background, background-color foreground. */
2844 gc_values.foreground = f->output_data.x->background_pixel;
2845 gc_values.background = f->output_data.x->cursor_pixel;
2846 gc_values.fill_style = FillOpaqueStippled;
2847 gc_values.stipple
2848 = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
2849 FRAME_X_DISPLAY_INFO (f)->root_window,
2850 cursor_bits, 16, 16);
2851 f->output_data.x->cursor_gc
2852 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2853 (GCFont | GCForeground | GCBackground
2854 | GCFillStyle /* | GCStipple */ | GCLineWidth),
2855 &gc_values);
2856
2857 /* Reliefs. */
2858 f->output_data.x->white_relief.gc = 0;
2859 f->output_data.x->black_relief.gc = 0;
2860
2861 /* Create the gray border tile used when the pointer is not in
2862 the frame. Since this depends on the frame's pixel values,
2863 this must be done on a per-frame basis. */
2864 f->output_data.x->border_tile
2865 = (XCreatePixmapFromBitmapData
2866 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
2867 gray_bits, gray_width, gray_height,
2868 f->output_data.x->foreground_pixel,
2869 f->output_data.x->background_pixel,
2870 DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
2871
2872 UNBLOCK_INPUT;
2873 }
2874
2875
2876 /* Free what was was allocated in x_make_gc. */
2877
2878 void
2879 x_free_gcs (f)
2880 struct frame *f;
2881 {
2882 Display *dpy = FRAME_X_DISPLAY (f);
2883
2884 BLOCK_INPUT;
2885
2886 if (f->output_data.x->normal_gc)
2887 {
2888 XFreeGC (dpy, f->output_data.x->normal_gc);
2889 f->output_data.x->normal_gc = 0;
2890 }
2891
2892 if (f->output_data.x->reverse_gc)
2893 {
2894 XFreeGC (dpy, f->output_data.x->reverse_gc);
2895 f->output_data.x->reverse_gc = 0;
2896 }
2897
2898 if (f->output_data.x->cursor_gc)
2899 {
2900 XFreeGC (dpy, f->output_data.x->cursor_gc);
2901 f->output_data.x->cursor_gc = 0;
2902 }
2903
2904 if (f->output_data.x->border_tile)
2905 {
2906 XFreePixmap (dpy, f->output_data.x->border_tile);
2907 f->output_data.x->border_tile = 0;
2908 }
2909
2910 UNBLOCK_INPUT;
2911 }
2912
2913
2914 /* Handler for signals raised during x_create_frame and
2915 x_create_top_frame. FRAME is the frame which is partially
2916 constructed. */
2917
2918 static Lisp_Object
2919 unwind_create_frame (frame)
2920 Lisp_Object frame;
2921 {
2922 struct frame *f = XFRAME (frame);
2923
2924 /* If frame is ``official'', nothing to do. */
2925 if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
2926 {
2927 #if GLYPH_DEBUG
2928 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2929 #endif
2930
2931 x_free_frame_resources (f);
2932
2933 #if GLYPH_DEBUG
2934 /* Check that reference counts are indeed correct. */
2935 xassert (dpyinfo->reference_count == dpyinfo_refcount);
2936 xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
2937 #endif
2938 return Qt;
2939 }
2940
2941 return Qnil;
2942 }
2943
2944
2945 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
2946 1, 1, 0,
2947 doc: /* Make a new X window, which is called a "frame" in Emacs terms.
2948 Returns an Emacs frame object.
2949 ALIST is an alist of frame parameters.
2950 If the parameters specify that the frame should not have a minibuffer,
2951 and do not specify a specific minibuffer window to use,
2952 then `default-minibuffer-frame' must be a frame whose minibuffer can
2953 be shared by the new frame.
2954
2955 This function is an internal primitive--use `make-frame' instead. */)
2956 (parms)
2957 Lisp_Object parms;
2958 {
2959 struct frame *f;
2960 Lisp_Object frame, tem;
2961 Lisp_Object name;
2962 int minibuffer_only = 0;
2963 long window_prompting = 0;
2964 int width, height;
2965 int count = SPECPDL_INDEX ();
2966 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2967 Lisp_Object display;
2968 struct x_display_info *dpyinfo = NULL;
2969 Lisp_Object parent;
2970 struct kboard *kb;
2971
2972 check_x ();
2973
2974 /* Use this general default value to start with
2975 until we know if this frame has a specified name. */
2976 Vx_resource_name = Vinvocation_name;
2977
2978 display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
2979 if (EQ (display, Qunbound))
2980 display = Qnil;
2981 dpyinfo = check_x_display_info (display);
2982 #ifdef MULTI_KBOARD
2983 kb = dpyinfo->kboard;
2984 #else
2985 kb = &the_only_kboard;
2986 #endif
2987
2988 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
2989 if (!STRINGP (name)
2990 && ! EQ (name, Qunbound)
2991 && ! NILP (name))
2992 error ("Invalid frame name--not a string or nil");
2993
2994 if (STRINGP (name))
2995 Vx_resource_name = name;
2996
2997 /* See if parent window is specified. */
2998 parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
2999 if (EQ (parent, Qunbound))
3000 parent = Qnil;
3001 if (! NILP (parent))
3002 CHECK_NUMBER (parent);
3003
3004 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
3005 /* No need to protect DISPLAY because that's not used after passing
3006 it to make_frame_without_minibuffer. */
3007 frame = Qnil;
3008 GCPRO4 (parms, parent, name, frame);
3009 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
3010 RES_TYPE_SYMBOL);
3011 if (EQ (tem, Qnone) || NILP (tem))
3012 f = make_frame_without_minibuffer (Qnil, kb, display);
3013 else if (EQ (tem, Qonly))
3014 {
3015 f = make_minibuffer_frame ();
3016 minibuffer_only = 1;
3017 }
3018 else if (WINDOWP (tem))
3019 f = make_frame_without_minibuffer (tem, kb, display);
3020 else
3021 f = make_frame (1);
3022
3023 XSETFRAME (frame, f);
3024
3025 /* Note that X Windows does support scroll bars. */
3026 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
3027
3028 f->output_method = output_x_window;
3029 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
3030 bzero (f->output_data.x, sizeof (struct x_output));
3031 f->output_data.x->icon_bitmap = -1;
3032 FRAME_FONTSET (f) = -1;
3033 f->output_data.x->scroll_bar_foreground_pixel = -1;
3034 f->output_data.x->scroll_bar_background_pixel = -1;
3035 #ifdef USE_TOOLKIT_SCROLL_BARS
3036 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
3037 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
3038 #endif /* USE_TOOLKIT_SCROLL_BARS */
3039 record_unwind_protect (unwind_create_frame, frame);
3040
3041 f->icon_name
3042 = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
3043 RES_TYPE_STRING);
3044 if (! STRINGP (f->icon_name))
3045 f->icon_name = Qnil;
3046
3047 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
3048 #if GLYPH_DEBUG
3049 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
3050 dpyinfo_refcount = dpyinfo->reference_count;
3051 #endif /* GLYPH_DEBUG */
3052 #ifdef MULTI_KBOARD
3053 FRAME_KBOARD (f) = kb;
3054 #endif
3055
3056 /* These colors will be set anyway later, but it's important
3057 to get the color reference counts right, so initialize them! */
3058 {
3059 Lisp_Object black;
3060 struct gcpro gcpro1;
3061
3062 /* Function x_decode_color can signal an error. Make
3063 sure to initialize color slots so that we won't try
3064 to free colors we haven't allocated. */
3065 f->output_data.x->foreground_pixel = -1;
3066 f->output_data.x->background_pixel = -1;
3067 f->output_data.x->cursor_pixel = -1;
3068 f->output_data.x->cursor_foreground_pixel = -1;
3069 f->output_data.x->border_pixel = -1;
3070 f->output_data.x->mouse_pixel = -1;
3071
3072 black = build_string ("black");
3073 GCPRO1 (black);
3074 f->output_data.x->foreground_pixel
3075 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3076 f->output_data.x->background_pixel
3077 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3078 f->output_data.x->cursor_pixel
3079 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3080 f->output_data.x->cursor_foreground_pixel
3081 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3082 f->output_data.x->border_pixel
3083 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3084 f->output_data.x->mouse_pixel
3085 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3086 UNGCPRO;
3087 }
3088
3089 /* Specify the parent under which to make this X window. */
3090
3091 if (!NILP (parent))
3092 {
3093 f->output_data.x->parent_desc = (Window) XFASTINT (parent);
3094 f->output_data.x->explicit_parent = 1;
3095 }
3096 else
3097 {
3098 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
3099 f->output_data.x->explicit_parent = 0;
3100 }
3101
3102 /* Set the name; the functions to which we pass f expect the name to
3103 be set. */
3104 if (EQ (name, Qunbound) || NILP (name))
3105 {
3106 f->name = build_string (dpyinfo->x_id_name);
3107 f->explicit_name = 0;
3108 }
3109 else
3110 {
3111 f->name = name;
3112 f->explicit_name = 1;
3113 /* use the frame's title when getting resources for this frame. */
3114 specbind (Qx_resource_name, name);
3115 }
3116
3117 /* Extract the window parameters from the supplied values
3118 that are needed to determine window geometry. */
3119 {
3120 Lisp_Object font;
3121
3122 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
3123
3124 /* If the caller has specified no font, try out fonts which we
3125 hope have bold and italic variations. */
3126 if (!STRINGP (font))
3127 {
3128 char *names[]
3129 = { "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1",
3130 "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1",
3131 "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1",
3132 /* This was formerly the first thing tried, but it finds
3133 too many fonts and takes too long. */
3134 "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1",
3135 /* If those didn't work, look for something which will
3136 at least work. */
3137 "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1",
3138 NULL };
3139 int i;
3140
3141 BLOCK_INPUT;
3142 for (i = 0; names[i]; i++)
3143 {
3144 Lisp_Object list;
3145
3146 list = x_list_fonts (f, build_string (names[i]), 0, 1);
3147 if (CONSP (list))
3148 {
3149 font = XCAR (list);
3150 break;
3151 }
3152 }
3153 UNBLOCK_INPUT;
3154 if (! STRINGP (font))
3155 font = build_string ("fixed");
3156 }
3157 x_default_parameter (f, parms, Qfont, font,
3158 "font", "Font", RES_TYPE_STRING);
3159 }
3160
3161 #ifdef USE_LUCID
3162 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
3163 whereby it fails to get any font. */
3164 xlwmenu_default_font = FRAME_FONT (f);
3165 #endif
3166
3167 x_default_parameter (f, parms, Qborder_width, make_number (2),
3168 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
3169
3170 /* This defaults to 1 in order to match xterm. We recognize either
3171 internalBorderWidth or internalBorder (which is what xterm calls
3172 it). */
3173 if (NILP (Fassq (Qinternal_border_width, parms)))
3174 {
3175 Lisp_Object value;
3176
3177 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
3178 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
3179 if (! EQ (value, Qunbound))
3180 parms = Fcons (Fcons (Qinternal_border_width, value),
3181 parms);
3182 }
3183 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
3184 "internalBorderWidth", "internalBorderWidth",
3185 RES_TYPE_NUMBER);
3186 x_default_parameter (f, parms, Qvertical_scroll_bars, Qleft,
3187 "verticalScrollBars", "ScrollBars",
3188 RES_TYPE_SYMBOL);
3189
3190 /* Also do the stuff which must be set before the window exists. */
3191 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
3192 "foreground", "Foreground", RES_TYPE_STRING);
3193 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
3194 "background", "Background", RES_TYPE_STRING);
3195 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
3196 "pointerColor", "Foreground", RES_TYPE_STRING);
3197 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
3198 "cursorColor", "Foreground", RES_TYPE_STRING);
3199 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
3200 "borderColor", "BorderColor", RES_TYPE_STRING);
3201 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
3202 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
3203 x_default_parameter (f, parms, Qline_spacing, Qnil,
3204 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
3205 x_default_parameter (f, parms, Qleft_fringe, Qnil,
3206 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
3207 x_default_parameter (f, parms, Qright_fringe, Qnil,
3208 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
3209
3210 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
3211 "scrollBarForeground",
3212 "ScrollBarForeground", 1);
3213 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
3214 "scrollBarBackground",
3215 "ScrollBarBackground", 0);
3216
3217 /* Init faces before x_default_parameter is called for scroll-bar
3218 parameters because that function calls x_set_scroll_bar_width,
3219 which calls change_frame_size, which calls Fset_window_buffer,
3220 which runs hooks, which call Fvertical_motion. At the end, we
3221 end up in init_iterator with a null face cache, which should not
3222 happen. */
3223 init_frame_faces (f);
3224
3225 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
3226 "menuBar", "MenuBar", RES_TYPE_NUMBER);
3227 x_default_parameter (f, parms, Qtool_bar_lines, make_number (1),
3228 "toolBar", "ToolBar", RES_TYPE_NUMBER);
3229 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
3230 "bufferPredicate", "BufferPredicate",
3231 RES_TYPE_SYMBOL);
3232 x_default_parameter (f, parms, Qtitle, Qnil,
3233 "title", "Title", RES_TYPE_STRING);
3234 x_default_parameter (f, parms, Qwait_for_wm, Qt,
3235 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
3236 x_default_parameter (f, parms, Qfullscreen, Qnil,
3237 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
3238
3239 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
3240
3241 /* Compute the size of the X window. */
3242 window_prompting = x_figure_window_size (f, parms, 1);
3243
3244 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
3245 f->no_split = minibuffer_only || EQ (tem, Qt);
3246
3247 x_icon_verify (f, parms);
3248
3249 /* Create the X widget or window. */
3250 #ifdef USE_X_TOOLKIT
3251 x_window (f, window_prompting, minibuffer_only);
3252 #else
3253 x_window (f);
3254 #endif
3255
3256 x_icon (f, parms);
3257 x_make_gc (f);
3258
3259 /* Now consider the frame official. */
3260 FRAME_X_DISPLAY_INFO (f)->reference_count++;
3261 Vframe_list = Fcons (frame, Vframe_list);
3262
3263 /* We need to do this after creating the X window, so that the
3264 icon-creation functions can say whose icon they're describing. */
3265 x_default_parameter (f, parms, Qicon_type, Qnil,
3266 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
3267
3268 x_default_parameter (f, parms, Qauto_raise, Qnil,
3269 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
3270 x_default_parameter (f, parms, Qauto_lower, Qnil,
3271 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
3272 x_default_parameter (f, parms, Qcursor_type, Qbox,
3273 "cursorType", "CursorType", RES_TYPE_SYMBOL);
3274 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
3275 "scrollBarWidth", "ScrollBarWidth",
3276 RES_TYPE_NUMBER);
3277
3278 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
3279 Change will not be effected unless different from the current
3280 FRAME_LINES (f). */
3281 width = FRAME_COLS (f);
3282 height = FRAME_LINES (f);
3283
3284 SET_FRAME_COLS (f, 0);
3285 FRAME_LINES (f) = 0;
3286 change_frame_size (f, height, width, 1, 0, 0);
3287
3288 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
3289 /* Create the menu bar. */
3290 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
3291 {
3292 /* If this signals an error, we haven't set size hints for the
3293 frame and we didn't make it visible. */
3294 initialize_frame_menubar (f);
3295
3296 #ifndef USE_GTK
3297 /* This is a no-op, except under Motif where it arranges the
3298 main window for the widgets on it. */
3299 lw_set_main_areas (f->output_data.x->column_widget,
3300 f->output_data.x->menubar_widget,
3301 f->output_data.x->edit_widget);
3302 #endif /* not USE_GTK */
3303 }
3304 #endif /* USE_X_TOOLKIT || USE_GTK */
3305
3306 /* Tell the server what size and position, etc, we want, and how
3307 badly we want them. This should be done after we have the menu
3308 bar so that its size can be taken into account. */
3309 BLOCK_INPUT;
3310 x_wm_set_size_hint (f, window_prompting, 0);
3311 UNBLOCK_INPUT;
3312
3313 /* Make the window appear on the frame and enable display, unless
3314 the caller says not to. However, with explicit parent, Emacs
3315 cannot control visibility, so don't try. */
3316 if (! f->output_data.x->explicit_parent)
3317 {
3318 Lisp_Object visibility;
3319
3320 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
3321 RES_TYPE_SYMBOL);
3322 if (EQ (visibility, Qunbound))
3323 visibility = Qt;
3324
3325 if (EQ (visibility, Qicon))
3326 x_iconify_frame (f);
3327 else if (! NILP (visibility))
3328 x_make_frame_visible (f);
3329 else
3330 /* Must have been Qnil. */
3331 ;
3332 }
3333
3334 /* Set the WM leader property. GTK does this itself, so this is not
3335 needed when using GTK. */
3336 if (dpyinfo->client_leader_window != 0)
3337 {
3338 BLOCK_INPUT;
3339 XChangeProperty (FRAME_X_DISPLAY (f),
3340 FRAME_OUTER_WINDOW (f),
3341 dpyinfo->Xatom_wm_client_leader,
3342 XA_WINDOW, 32, PropModeReplace,
3343 (char *) &dpyinfo->client_leader_window, 1);
3344 UNBLOCK_INPUT;
3345 }
3346
3347 UNGCPRO;
3348
3349 /* Make sure windows on this frame appear in calls to next-window
3350 and similar functions. */
3351 Vwindow_list = Qnil;
3352
3353 return unbind_to (count, frame);
3354 }
3355
3356
3357 /* FRAME is used only to get a handle on the X display. We don't pass the
3358 display info directly because we're called from frame.c, which doesn't
3359 know about that structure. */
3360
3361 Lisp_Object
3362 x_get_focus_frame (frame)
3363 struct frame *frame;
3364 {
3365 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
3366 Lisp_Object xfocus;
3367 if (! dpyinfo->x_focus_frame)
3368 return Qnil;
3369
3370 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
3371 return xfocus;
3372 }
3373
3374
3375 /* In certain situations, when the window manager follows a
3376 click-to-focus policy, there seems to be no way around calling
3377 XSetInputFocus to give another frame the input focus .
3378
3379 In an ideal world, XSetInputFocus should generally be avoided so
3380 that applications don't interfere with the window manager's focus
3381 policy. But I think it's okay to use when it's clearly done
3382 following a user-command. */
3383
3384 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
3385 doc: /* Set the input focus to FRAME.
3386 FRAME nil means use the selected frame. */)
3387 (frame)
3388 Lisp_Object frame;
3389 {
3390 struct frame *f = check_x_frame (frame);
3391 Display *dpy = FRAME_X_DISPLAY (f);
3392 int count;
3393
3394 BLOCK_INPUT;
3395 count = x_catch_errors (dpy);
3396 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3397 RevertToParent, CurrentTime);
3398 x_uncatch_errors (dpy, count);
3399 UNBLOCK_INPUT;
3400
3401 return Qnil;
3402 }
3403
3404 \f
3405 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
3406 doc: /* Internal function called by `color-defined-p', which see. */)
3407 (color, frame)
3408 Lisp_Object color, frame;
3409 {
3410 XColor foo;
3411 FRAME_PTR f = check_x_frame (frame);
3412
3413 CHECK_STRING (color);
3414
3415 if (x_defined_color (f, SDATA (color), &foo, 0))
3416 return Qt;
3417 else
3418 return Qnil;
3419 }
3420
3421 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
3422 doc: /* Internal function called by `color-values', which see. */)
3423 (color, frame)
3424 Lisp_Object color, frame;
3425 {
3426 XColor foo;
3427 FRAME_PTR f = check_x_frame (frame);
3428
3429 CHECK_STRING (color);
3430
3431 if (x_defined_color (f, SDATA (color), &foo, 0))
3432 {
3433 Lisp_Object rgb[3];
3434
3435 rgb[0] = make_number (foo.red);
3436 rgb[1] = make_number (foo.green);
3437 rgb[2] = make_number (foo.blue);
3438 return Flist (3, rgb);
3439 }
3440 else
3441 return Qnil;
3442 }
3443
3444 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
3445 doc: /* Internal function called by `display-color-p', which see. */)
3446 (display)
3447 Lisp_Object display;
3448 {
3449 struct x_display_info *dpyinfo = check_x_display_info (display);
3450
3451 if (dpyinfo->n_planes <= 2)
3452 return Qnil;
3453
3454 switch (dpyinfo->visual->class)
3455 {
3456 case StaticColor:
3457 case PseudoColor:
3458 case TrueColor:
3459 case DirectColor:
3460 return Qt;
3461
3462 default:
3463 return Qnil;
3464 }
3465 }
3466
3467 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
3468 0, 1, 0,
3469 doc: /* Return t if the X display supports shades of gray.
3470 Note that color displays do support shades of gray.
3471 The optional argument DISPLAY specifies which display to ask about.
3472 DISPLAY should be either a frame or a display name (a string).
3473 If omitted or nil, that stands for the selected frame's display. */)
3474 (display)
3475 Lisp_Object display;
3476 {
3477 struct x_display_info *dpyinfo = check_x_display_info (display);
3478
3479 if (dpyinfo->n_planes <= 1)
3480 return Qnil;
3481
3482 switch (dpyinfo->visual->class)
3483 {
3484 case StaticColor:
3485 case PseudoColor:
3486 case TrueColor:
3487 case DirectColor:
3488 case StaticGray:
3489 case GrayScale:
3490 return Qt;
3491
3492 default:
3493 return Qnil;
3494 }
3495 }
3496
3497 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
3498 0, 1, 0,
3499 doc: /* Returns the width in pixels of the X display DISPLAY.
3500 The optional argument DISPLAY specifies which display to ask about.
3501 DISPLAY should be either a frame or a display name (a string).
3502 If omitted or nil, that stands for the selected frame's display. */)
3503 (display)
3504 Lisp_Object display;
3505 {
3506 struct x_display_info *dpyinfo = check_x_display_info (display);
3507
3508 return make_number (dpyinfo->width);
3509 }
3510
3511 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
3512 Sx_display_pixel_height, 0, 1, 0,
3513 doc: /* Returns the height in pixels of the X display DISPLAY.
3514 The optional argument DISPLAY specifies which display to ask about.
3515 DISPLAY should be either a frame or a display name (a string).
3516 If omitted or nil, that stands for the selected frame's display. */)
3517 (display)
3518 Lisp_Object display;
3519 {
3520 struct x_display_info *dpyinfo = check_x_display_info (display);
3521
3522 return make_number (dpyinfo->height);
3523 }
3524
3525 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
3526 0, 1, 0,
3527 doc: /* Returns the number of bitplanes of the X display DISPLAY.
3528 The optional argument DISPLAY specifies which display to ask about.
3529 DISPLAY should be either a frame or a display name (a string).
3530 If omitted or nil, that stands for the selected frame's display. */)
3531 (display)
3532 Lisp_Object display;
3533 {
3534 struct x_display_info *dpyinfo = check_x_display_info (display);
3535
3536 return make_number (dpyinfo->n_planes);
3537 }
3538
3539 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
3540 0, 1, 0,
3541 doc: /* Returns the number of color cells of the X display DISPLAY.
3542 The optional argument DISPLAY specifies which display to ask about.
3543 DISPLAY should be either a frame or a display name (a string).
3544 If omitted or nil, that stands for the selected frame's display. */)
3545 (display)
3546 Lisp_Object display;
3547 {
3548 struct x_display_info *dpyinfo = check_x_display_info (display);
3549
3550 int nr_planes = DisplayPlanes (dpyinfo->display,
3551 XScreenNumberOfScreen (dpyinfo->screen));
3552
3553 /* Truncate nr_planes to 24 to avoid integer overflow.
3554 Some displays says 32, but only 24 bits are actually significant.
3555 There are only very few and rare video cards that have more than
3556 24 significant bits. Also 24 bits is more than 16 million colors,
3557 it "should be enough for everyone". */
3558 if (nr_planes > 24) nr_planes = 24;
3559
3560 return make_number (1 << nr_planes);
3561 }
3562
3563 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
3564 Sx_server_max_request_size,
3565 0, 1, 0,
3566 doc: /* Returns the maximum request size of the X server of display DISPLAY.
3567 The optional argument DISPLAY specifies which display to ask about.
3568 DISPLAY should be either a frame or a display name (a string).
3569 If omitted or nil, that stands for the selected frame's display. */)
3570 (display)
3571 Lisp_Object display;
3572 {
3573 struct x_display_info *dpyinfo = check_x_display_info (display);
3574
3575 return make_number (MAXREQUEST (dpyinfo->display));
3576 }
3577
3578 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
3579 doc: /* Returns the "vendor ID" string of the X server of display DISPLAY.
3580 \(Labelling every distributor as a "vendor" embodies the false assumption
3581 that operating systems cannot be developed and distributed noncommercially.)
3582 The optional argument DISPLAY specifies which display to ask about.
3583 DISPLAY should be either a frame or a display name (a string).
3584 If omitted or nil, that stands for the selected frame's display. */)
3585 (display)
3586 Lisp_Object display;
3587 {
3588 struct x_display_info *dpyinfo = check_x_display_info (display);
3589 char *vendor = ServerVendor (dpyinfo->display);
3590
3591 if (! vendor) vendor = "";
3592 return build_string (vendor);
3593 }
3594
3595 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
3596 doc: /* Returns the version numbers of the X server of display DISPLAY.
3597 The value is a list of three integers: the major and minor
3598 version numbers of the X Protocol in use, and the distributor-specific release
3599 number. See also the function `x-server-vendor'.
3600
3601 The optional argument DISPLAY specifies which display to ask about.
3602 DISPLAY should be either a frame or a display name (a string).
3603 If omitted or nil, that stands for the selected frame's display. */)
3604 (display)
3605 Lisp_Object display;
3606 {
3607 struct x_display_info *dpyinfo = check_x_display_info (display);
3608 Display *dpy = dpyinfo->display;
3609
3610 return Fcons (make_number (ProtocolVersion (dpy)),
3611 Fcons (make_number (ProtocolRevision (dpy)),
3612 Fcons (make_number (VendorRelease (dpy)), Qnil)));
3613 }
3614
3615 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
3616 doc: /* Return the number of screens on the X server of display DISPLAY.
3617 The optional argument DISPLAY specifies which display to ask about.
3618 DISPLAY should be either a frame or a display name (a string).
3619 If omitted or nil, that stands for the selected frame's display. */)
3620 (display)
3621 Lisp_Object display;
3622 {
3623 struct x_display_info *dpyinfo = check_x_display_info (display);
3624
3625 return make_number (ScreenCount (dpyinfo->display));
3626 }
3627
3628 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
3629 doc: /* Return the height in millimeters of the X display DISPLAY.
3630 The optional argument DISPLAY specifies which display to ask about.
3631 DISPLAY should be either a frame or a display name (a string).
3632 If omitted or nil, that stands for the selected frame's display. */)
3633 (display)
3634 Lisp_Object display;
3635 {
3636 struct x_display_info *dpyinfo = check_x_display_info (display);
3637
3638 return make_number (HeightMMOfScreen (dpyinfo->screen));
3639 }
3640
3641 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
3642 doc: /* Return the width in millimeters of the X display DISPLAY.
3643 The optional argument DISPLAY specifies which display to ask about.
3644 DISPLAY should be either a frame or a display name (a string).
3645 If omitted or nil, that stands for the selected frame's display. */)
3646 (display)
3647 Lisp_Object display;
3648 {
3649 struct x_display_info *dpyinfo = check_x_display_info (display);
3650
3651 return make_number (WidthMMOfScreen (dpyinfo->screen));
3652 }
3653
3654 DEFUN ("x-display-backing-store", Fx_display_backing_store,
3655 Sx_display_backing_store, 0, 1, 0,
3656 doc: /* Returns an indication of whether X display DISPLAY does backing store.
3657 The value may be `always', `when-mapped', or `not-useful'.
3658 The optional argument DISPLAY specifies which display to ask about.
3659 DISPLAY should be either a frame or a display name (a string).
3660 If omitted or nil, that stands for the selected frame's display. */)
3661 (display)
3662 Lisp_Object display;
3663 {
3664 struct x_display_info *dpyinfo = check_x_display_info (display);
3665 Lisp_Object result;
3666
3667 switch (DoesBackingStore (dpyinfo->screen))
3668 {
3669 case Always:
3670 result = intern ("always");
3671 break;
3672
3673 case WhenMapped:
3674 result = intern ("when-mapped");
3675 break;
3676
3677 case NotUseful:
3678 result = intern ("not-useful");
3679 break;
3680
3681 default:
3682 error ("Strange value for BackingStore parameter of screen");
3683 result = Qnil;
3684 }
3685
3686 return result;
3687 }
3688
3689 DEFUN ("x-display-visual-class", Fx_display_visual_class,
3690 Sx_display_visual_class, 0, 1, 0,
3691 doc: /* Return the visual class of the X display DISPLAY.
3692 The value is one of the symbols `static-gray', `gray-scale',
3693 `static-color', `pseudo-color', `true-color', or `direct-color'.
3694
3695 The optional argument DISPLAY specifies which display to ask about.
3696 DISPLAY should be either a frame or a display name (a string).
3697 If omitted or nil, that stands for the selected frame's display. */)
3698 (display)
3699 Lisp_Object display;
3700 {
3701 struct x_display_info *dpyinfo = check_x_display_info (display);
3702 Lisp_Object result;
3703
3704 switch (dpyinfo->visual->class)
3705 {
3706 case StaticGray:
3707 result = intern ("static-gray");
3708 break;
3709 case GrayScale:
3710 result = intern ("gray-scale");
3711 break;
3712 case StaticColor:
3713 result = intern ("static-color");
3714 break;
3715 case PseudoColor:
3716 result = intern ("pseudo-color");
3717 break;
3718 case TrueColor:
3719 result = intern ("true-color");
3720 break;
3721 case DirectColor:
3722 result = intern ("direct-color");
3723 break;
3724 default:
3725 error ("Display has an unknown visual class");
3726 result = Qnil;
3727 }
3728
3729 return result;
3730 }
3731
3732 DEFUN ("x-display-save-under", Fx_display_save_under,
3733 Sx_display_save_under, 0, 1, 0,
3734 doc: /* Returns t if the X display DISPLAY supports the save-under feature.
3735 The optional argument DISPLAY specifies which display to ask about.
3736 DISPLAY should be either a frame or a display name (a string).
3737 If omitted or nil, that stands for the selected frame's display. */)
3738 (display)
3739 Lisp_Object display;
3740 {
3741 struct x_display_info *dpyinfo = check_x_display_info (display);
3742
3743 if (DoesSaveUnders (dpyinfo->screen) == True)
3744 return Qt;
3745 else
3746 return Qnil;
3747 }
3748 \f
3749 int
3750 x_pixel_width (f)
3751 register struct frame *f;
3752 {
3753 return FRAME_PIXEL_WIDTH (f);
3754 }
3755
3756 int
3757 x_pixel_height (f)
3758 register struct frame *f;
3759 {
3760 return FRAME_PIXEL_HEIGHT (f);
3761 }
3762
3763 int
3764 x_char_width (f)
3765 register struct frame *f;
3766 {
3767 return FRAME_COLUMN_WIDTH (f);
3768 }
3769
3770 int
3771 x_char_height (f)
3772 register struct frame *f;
3773 {
3774 return FRAME_LINE_HEIGHT (f);
3775 }
3776
3777 int
3778 x_screen_planes (f)
3779 register struct frame *f;
3780 {
3781 return FRAME_X_DISPLAY_INFO (f)->n_planes;
3782 }
3783
3784
3785 \f
3786 /************************************************************************
3787 X Displays
3788 ************************************************************************/
3789
3790 \f
3791 /* Mapping visual names to visuals. */
3792
3793 static struct visual_class
3794 {
3795 char *name;
3796 int class;
3797 }
3798 visual_classes[] =
3799 {
3800 {"StaticGray", StaticGray},
3801 {"GrayScale", GrayScale},
3802 {"StaticColor", StaticColor},
3803 {"PseudoColor", PseudoColor},
3804 {"TrueColor", TrueColor},
3805 {"DirectColor", DirectColor},
3806 {NULL, 0}
3807 };
3808
3809
3810 #ifndef HAVE_XSCREENNUMBEROFSCREEN
3811
3812 /* Value is the screen number of screen SCR. This is a substitute for
3813 the X function with the same name when that doesn't exist. */
3814
3815 int
3816 XScreenNumberOfScreen (scr)
3817 register Screen *scr;
3818 {
3819 Display *dpy = scr->display;
3820 int i;
3821
3822 for (i = 0; i < dpy->nscreens; ++i)
3823 if (scr == dpy->screens + i)
3824 break;
3825
3826 return i;
3827 }
3828
3829 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
3830
3831
3832 /* Select the visual that should be used on display DPYINFO. Set
3833 members of DPYINFO appropriately. Called from x_term_init. */
3834
3835 void
3836 select_visual (dpyinfo)
3837 struct x_display_info *dpyinfo;
3838 {
3839 Display *dpy = dpyinfo->display;
3840 Screen *screen = dpyinfo->screen;
3841 Lisp_Object value;
3842
3843 /* See if a visual is specified. */
3844 value = display_x_get_resource (dpyinfo,
3845 build_string ("visualClass"),
3846 build_string ("VisualClass"),
3847 Qnil, Qnil);
3848 if (STRINGP (value))
3849 {
3850 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
3851 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
3852 depth, a decimal number. NAME is compared with case ignored. */
3853 char *s = (char *) alloca (SBYTES (value) + 1);
3854 char *dash;
3855 int i, class = -1;
3856 XVisualInfo vinfo;
3857
3858 strcpy (s, SDATA (value));
3859 dash = index (s, '-');
3860 if (dash)
3861 {
3862 dpyinfo->n_planes = atoi (dash + 1);
3863 *dash = '\0';
3864 }
3865 else
3866 /* We won't find a matching visual with depth 0, so that
3867 an error will be printed below. */
3868 dpyinfo->n_planes = 0;
3869
3870 /* Determine the visual class. */
3871 for (i = 0; visual_classes[i].name; ++i)
3872 if (xstricmp (s, visual_classes[i].name) == 0)
3873 {
3874 class = visual_classes[i].class;
3875 break;
3876 }
3877
3878 /* Look up a matching visual for the specified class. */
3879 if (class == -1
3880 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
3881 dpyinfo->n_planes, class, &vinfo))
3882 fatal ("Invalid visual specification `%s'", SDATA (value));
3883
3884 dpyinfo->visual = vinfo.visual;
3885 }
3886 else
3887 {
3888 int n_visuals;
3889 XVisualInfo *vinfo, vinfo_template;
3890
3891 dpyinfo->visual = DefaultVisualOfScreen (screen);
3892
3893 #ifdef HAVE_X11R4
3894 vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
3895 #else
3896 vinfo_template.visualid = dpyinfo->visual->visualid;
3897 #endif
3898 vinfo_template.screen = XScreenNumberOfScreen (screen);
3899 vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
3900 &vinfo_template, &n_visuals);
3901 if (n_visuals != 1)
3902 fatal ("Can't get proper X visual info");
3903
3904 dpyinfo->n_planes = vinfo->depth;
3905 XFree ((char *) vinfo);
3906 }
3907 }
3908
3909
3910 /* Return the X display structure for the display named NAME.
3911 Open a new connection if necessary. */
3912
3913 struct x_display_info *
3914 x_display_info_for_name (name)
3915 Lisp_Object name;
3916 {
3917 Lisp_Object names;
3918 struct x_display_info *dpyinfo;
3919
3920 CHECK_STRING (name);
3921
3922 if (! EQ (Vwindow_system, intern ("x")))
3923 error ("Not using X Windows");
3924
3925 for (dpyinfo = x_display_list, names = x_display_name_list;
3926 dpyinfo;
3927 dpyinfo = dpyinfo->next, names = XCDR (names))
3928 {
3929 Lisp_Object tem;
3930 tem = Fstring_equal (XCAR (XCAR (names)), name);
3931 if (!NILP (tem))
3932 return dpyinfo;
3933 }
3934
3935 /* Use this general default value to start with. */
3936 Vx_resource_name = Vinvocation_name;
3937
3938 validate_x_resource_name ();
3939
3940 dpyinfo = x_term_init (name, (char *)0,
3941 (char *) SDATA (Vx_resource_name));
3942
3943 if (dpyinfo == 0)
3944 error ("Cannot connect to X server %s", SDATA (name));
3945
3946 x_in_use = 1;
3947 XSETFASTINT (Vwindow_system_version, 11);
3948
3949 return dpyinfo;
3950 }
3951
3952
3953 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
3954 1, 3, 0,
3955 doc: /* Open a connection to an X server.
3956 DISPLAY is the name of the display to connect to.
3957 Optional second arg XRM-STRING is a string of resources in xrdb format.
3958 If the optional third arg MUST-SUCCEED is non-nil,
3959 terminate Emacs if we can't open the connection. */)
3960 (display, xrm_string, must_succeed)
3961 Lisp_Object display, xrm_string, must_succeed;
3962 {
3963 unsigned char *xrm_option;
3964 struct x_display_info *dpyinfo;
3965
3966 CHECK_STRING (display);
3967 if (! NILP (xrm_string))
3968 CHECK_STRING (xrm_string);
3969
3970 if (! EQ (Vwindow_system, intern ("x")))
3971 error ("Not using X Windows");
3972
3973 if (! NILP (xrm_string))
3974 xrm_option = (unsigned char *) SDATA (xrm_string);
3975 else
3976 xrm_option = (unsigned char *) 0;
3977
3978 validate_x_resource_name ();
3979
3980 /* This is what opens the connection and sets x_current_display.
3981 This also initializes many symbols, such as those used for input. */
3982 dpyinfo = x_term_init (display, xrm_option,
3983 (char *) SDATA (Vx_resource_name));
3984
3985 if (dpyinfo == 0)
3986 {
3987 if (!NILP (must_succeed))
3988 fatal ("Cannot connect to X server %s.\n\
3989 Check the DISPLAY environment variable or use `-d'.\n\
3990 Also use the `xauth' program to verify that you have the proper\n\
3991 authorization information needed to connect the X server.\n\
3992 An insecure way to solve the problem may be to use `xhost'.\n",
3993 SDATA (display));
3994 else
3995 error ("Cannot connect to X server %s", SDATA (display));
3996 }
3997
3998 x_in_use = 1;
3999
4000 XSETFASTINT (Vwindow_system_version, 11);
4001 return Qnil;
4002 }
4003
4004 DEFUN ("x-close-connection", Fx_close_connection,
4005 Sx_close_connection, 1, 1, 0,
4006 doc: /* Close the connection to DISPLAY's X server.
4007 For DISPLAY, specify either a frame or a display name (a string).
4008 If DISPLAY is nil, that stands for the selected frame's display. */)
4009 (display)
4010 Lisp_Object display;
4011 {
4012 struct x_display_info *dpyinfo = check_x_display_info (display);
4013 int i;
4014
4015 if (dpyinfo->reference_count > 0)
4016 error ("Display still has frames on it");
4017
4018 BLOCK_INPUT;
4019 /* Free the fonts in the font table. */
4020 for (i = 0; i < dpyinfo->n_fonts; i++)
4021 if (dpyinfo->font_table[i].name)
4022 {
4023 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
4024 }
4025
4026 x_destroy_all_bitmaps (dpyinfo);
4027 XSetCloseDownMode (dpyinfo->display, DestroyAll);
4028
4029 #ifdef USE_X_TOOLKIT
4030 XtCloseDisplay (dpyinfo->display);
4031 #else
4032 XCloseDisplay (dpyinfo->display);
4033 #endif
4034
4035 x_delete_display (dpyinfo);
4036 UNBLOCK_INPUT;
4037
4038 return Qnil;
4039 }
4040
4041 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
4042 doc: /* Return the list of display names that Emacs has connections to. */)
4043 ()
4044 {
4045 Lisp_Object tail, result;
4046
4047 result = Qnil;
4048 for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
4049 result = Fcons (XCAR (XCAR (tail)), result);
4050
4051 return result;
4052 }
4053
4054 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
4055 doc: /* If ON is non-nil, report X errors as soon as the erring request is made.
4056 If ON is nil, allow buffering of requests.
4057 Turning on synchronization prohibits the Xlib routines from buffering
4058 requests and seriously degrades performance, but makes debugging much
4059 easier.
4060 The optional second argument DISPLAY specifies which display to act on.
4061 DISPLAY should be either a frame or a display name (a string).
4062 If DISPLAY is omitted or nil, that stands for the selected frame's display. */)
4063 (on, display)
4064 Lisp_Object display, on;
4065 {
4066 struct x_display_info *dpyinfo = check_x_display_info (display);
4067
4068 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
4069
4070 return Qnil;
4071 }
4072
4073 /* Wait for responses to all X commands issued so far for frame F. */
4074
4075 void
4076 x_sync (f)
4077 FRAME_PTR f;
4078 {
4079 BLOCK_INPUT;
4080 XSync (FRAME_X_DISPLAY (f), False);
4081 UNBLOCK_INPUT;
4082 }
4083
4084 \f
4085 /***********************************************************************
4086 Window properties
4087 ***********************************************************************/
4088
4089 DEFUN ("x-change-window-property", Fx_change_window_property,
4090 Sx_change_window_property, 2, 6, 0,
4091 doc: /* Change window property PROP to VALUE on the X window of FRAME.
4092 PROP must be a string.
4093 VALUE may be a string or a list of conses, numbers and/or strings.
4094 If an element in the list is a string, it is converted to
4095 an Atom and the value of the Atom is used. If an element is a cons,
4096 it is converted to a 32 bit number where the car is the 16 top bits and the
4097 cdr is the lower 16 bits.
4098 FRAME nil or omitted means use the selected frame.
4099 If TYPE is given and non-nil, it is the name of the type of VALUE.
4100 If TYPE is not given or nil, the type is STRING.
4101 FORMAT gives the size in bits of each element if VALUE is a list.
4102 It must be one of 8, 16 or 32.
4103 If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to 8.
4104 If OUTER_P is non-nil, the property is changed for the outer X window of
4105 FRAME. Default is to change on the edit X window.
4106
4107 Value is VALUE. */)
4108 (prop, value, frame, type, format, outer_p)
4109 Lisp_Object prop, value, frame, type, format, outer_p;
4110 {
4111 struct frame *f = check_x_frame (frame);
4112 Atom prop_atom;
4113 Atom target_type = XA_STRING;
4114 int element_format = 8;
4115 unsigned char *data;
4116 int nelements;
4117 Window w;
4118
4119 CHECK_STRING (prop);
4120
4121 if (! NILP (format))
4122 {
4123 CHECK_NUMBER (format);
4124 element_format = XFASTINT (format);
4125
4126 if (element_format != 8 && element_format != 16
4127 && element_format != 32)
4128 error ("FORMAT must be one of 8, 16 or 32");
4129 }
4130
4131 if (CONSP (value))
4132 {
4133 nelements = x_check_property_data (value);
4134 if (nelements == -1)
4135 error ("Bad data in VALUE, must be number, string or cons");
4136
4137 if (element_format == 8)
4138 data = (unsigned char *) xmalloc (nelements);
4139 else if (element_format == 16)
4140 data = (unsigned char *) xmalloc (nelements*2);
4141 else /* format == 32 */
4142 /* The man page for XChangeProperty:
4143 "If the specified format is 32, the property data must be a
4144 long array."
4145 This applies even if long is more than 64 bits. The X library
4146 converts to 32 bits before sending to the X server. */
4147 data = (unsigned char *) xmalloc (nelements * sizeof(long));
4148
4149 x_fill_property_data (FRAME_X_DISPLAY (f), value, data, element_format);
4150 }
4151 else
4152 {
4153 CHECK_STRING (value);
4154 data = SDATA (value);
4155 nelements = SCHARS (value);
4156 }
4157
4158 BLOCK_INPUT;
4159 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
4160 if (! NILP (type))
4161 {
4162 CHECK_STRING (type);
4163 target_type = XInternAtom (FRAME_X_DISPLAY (f), SDATA (type), False);
4164 }
4165
4166 if (! NILP (outer_p)) w = FRAME_OUTER_WINDOW (f);
4167 else w = FRAME_X_WINDOW (f);
4168
4169 XChangeProperty (FRAME_X_DISPLAY (f), w,
4170 prop_atom, target_type, element_format, PropModeReplace,
4171 data, nelements);
4172
4173 if (CONSP (value)) xfree (data);
4174
4175 /* Make sure the property is set when we return. */
4176 XFlush (FRAME_X_DISPLAY (f));
4177 UNBLOCK_INPUT;
4178
4179 return value;
4180 }
4181
4182
4183 DEFUN ("x-delete-window-property", Fx_delete_window_property,
4184 Sx_delete_window_property, 1, 2, 0,
4185 doc: /* Remove window property PROP from X window of FRAME.
4186 FRAME nil or omitted means use the selected frame. Value is PROP. */)
4187 (prop, frame)
4188 Lisp_Object prop, frame;
4189 {
4190 struct frame *f = check_x_frame (frame);
4191 Atom prop_atom;
4192
4193 CHECK_STRING (prop);
4194 BLOCK_INPUT;
4195 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
4196 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
4197
4198 /* Make sure the property is removed when we return. */
4199 XFlush (FRAME_X_DISPLAY (f));
4200 UNBLOCK_INPUT;
4201
4202 return prop;
4203 }
4204
4205
4206 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
4207 1, 6, 0,
4208 doc: /* Value is the value of window property PROP on FRAME.
4209 If FRAME is nil or omitted, use the selected frame.
4210 If TYPE is nil or omitted, get the property as a string. Otherwise TYPE
4211 is the name of the Atom that denotes the type expected.
4212 If SOURCE is non-nil, get the property on that window instead of from
4213 FRAME. The number 0 denotes the root window.
4214 If DELETE_P is non-nil, delete the property after retreiving it.
4215 If VECTOR_RET_P is non-nil, don't return a string but a vector of values.
4216
4217 Value is nil if FRAME hasn't a property with name PROP or if PROP has
4218 no value of TYPE. */)
4219 (prop, frame, type, source, delete_p, vector_ret_p)
4220 Lisp_Object prop, frame, type, source, delete_p, vector_ret_p;
4221 {
4222 struct frame *f = check_x_frame (frame);
4223 Atom prop_atom;
4224 int rc;
4225 Lisp_Object prop_value = Qnil;
4226 unsigned char *tmp_data = NULL;
4227 Atom actual_type;
4228 Atom target_type = XA_STRING;
4229 int actual_format;
4230 unsigned long actual_size, bytes_remaining;
4231 Window target_window = FRAME_X_WINDOW (f);
4232 struct gcpro gcpro1;
4233
4234 GCPRO1 (prop_value);
4235 CHECK_STRING (prop);
4236
4237 if (! NILP (source))
4238 {
4239 if (NUMBERP (source))
4240 {
4241 if (FLOATP (source))
4242 target_window = (Window) XFLOAT (source);
4243 else
4244 target_window = XFASTINT (source);
4245
4246 if (target_window == 0)
4247 target_window = FRAME_X_DISPLAY_INFO (f)->root_window;
4248 }
4249 else if (CONSP (source))
4250 target_window = cons_to_long (source);
4251 }
4252
4253 BLOCK_INPUT;
4254 if (STRINGP (type))
4255 {
4256 if (strcmp ("AnyPropertyType", SDATA (type)) == 0)
4257 target_type = AnyPropertyType;
4258 else
4259 target_type = XInternAtom (FRAME_X_DISPLAY (f), SDATA (type), False);
4260 }
4261
4262 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
4263 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
4264 prop_atom, 0, 0, False, target_type,
4265 &actual_type, &actual_format, &actual_size,
4266 &bytes_remaining, &tmp_data);
4267 if (rc == Success)
4268 {
4269 int size = bytes_remaining;
4270
4271 XFree (tmp_data);
4272 tmp_data = NULL;
4273
4274 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
4275 prop_atom, 0, bytes_remaining,
4276 ! NILP (delete_p), target_type,
4277 &actual_type, &actual_format,
4278 &actual_size, &bytes_remaining,
4279 &tmp_data);
4280 if (rc == Success && tmp_data)
4281 {
4282 /* The man page for XGetWindowProperty says:
4283 "If the returned format is 32, the returned data is represented
4284 as a long array and should be cast to that type to obtain the
4285 elements."
4286 This applies even if long is more than 32 bits, the X library
4287 converts from 32 bit elements received from the X server to long
4288 and passes the long array to us. Thus, for that case bcopy can not
4289 be used. We convert to a 32 bit type here, because so much code
4290 assume on that.
4291
4292 The bytes and offsets passed to XGetWindowProperty refers to the
4293 property and those are indeed in 32 bit quantities if format is
4294 32. */
4295
4296 if (actual_format == 32 && actual_format < BITS_PER_LONG)
4297 {
4298 unsigned long i;
4299 int *idata = (int *) tmp_data;
4300 long *ldata = (long *) tmp_data;
4301
4302 for (i = 0; i < actual_size; ++i)
4303 idata[i] = (int) ldata[i];
4304 }
4305
4306 if (NILP (vector_ret_p))
4307 prop_value = make_string (tmp_data, size);
4308 else
4309 prop_value = x_property_data_to_lisp (f,
4310 tmp_data,
4311 actual_type,
4312 actual_format,
4313 actual_size);
4314 }
4315
4316 if (tmp_data) XFree (tmp_data);
4317 }
4318
4319 UNBLOCK_INPUT;
4320 UNGCPRO;
4321 return prop_value;
4322 }
4323
4324
4325 \f
4326 /***********************************************************************
4327 Busy cursor
4328 ***********************************************************************/
4329
4330 /* If non-null, an asynchronous timer that, when it expires, displays
4331 an hourglass cursor on all frames. */
4332
4333 static struct atimer *hourglass_atimer;
4334
4335 /* Non-zero means an hourglass cursor is currently shown. */
4336
4337 static int hourglass_shown_p;
4338
4339 /* Number of seconds to wait before displaying an hourglass cursor. */
4340
4341 static Lisp_Object Vhourglass_delay;
4342
4343 /* Default number of seconds to wait before displaying an hourglass
4344 cursor. */
4345
4346 #define DEFAULT_HOURGLASS_DELAY 1
4347
4348 /* Function prototypes. */
4349
4350 static void show_hourglass P_ ((struct atimer *));
4351 static void hide_hourglass P_ ((void));
4352
4353 /* Return non-zero if houglass timer has been started or hourglass is shown. */
4354
4355 int
4356 hourglass_started ()
4357 {
4358 return hourglass_shown_p || hourglass_atimer != NULL;
4359 }
4360
4361
4362 /* Cancel a currently active hourglass timer, and start a new one. */
4363
4364 void
4365 start_hourglass ()
4366 {
4367 EMACS_TIME delay;
4368 int secs, usecs = 0;
4369
4370 /* Don't bother for ttys. */
4371 if (NILP (Vwindow_system))
4372 return;
4373
4374 cancel_hourglass ();
4375
4376 if (INTEGERP (Vhourglass_delay)
4377 && XINT (Vhourglass_delay) > 0)
4378 secs = XFASTINT (Vhourglass_delay);
4379 else if (FLOATP (Vhourglass_delay)
4380 && XFLOAT_DATA (Vhourglass_delay) > 0)
4381 {
4382 Lisp_Object tem;
4383 tem = Ftruncate (Vhourglass_delay, Qnil);
4384 secs = XFASTINT (tem);
4385 usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
4386 }
4387 else
4388 secs = DEFAULT_HOURGLASS_DELAY;
4389
4390 EMACS_SET_SECS_USECS (delay, secs, usecs);
4391 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
4392 show_hourglass, NULL);
4393 }
4394
4395
4396 /* Cancel the hourglass cursor timer if active, hide a busy cursor if
4397 shown. */
4398
4399 void
4400 cancel_hourglass ()
4401 {
4402 if (hourglass_atimer)
4403 {
4404 cancel_atimer (hourglass_atimer);
4405 hourglass_atimer = NULL;
4406 }
4407
4408 if (hourglass_shown_p)
4409 hide_hourglass ();
4410 }
4411
4412
4413 /* Timer function of hourglass_atimer. TIMER is equal to
4414 hourglass_atimer.
4415
4416 Display an hourglass pointer on all frames by mapping the frames'
4417 hourglass_window. Set the hourglass_p flag in the frames'
4418 output_data.x structure to indicate that an hourglass cursor is
4419 shown on the frames. */
4420
4421 static void
4422 show_hourglass (timer)
4423 struct atimer *timer;
4424 {
4425 /* The timer implementation will cancel this timer automatically
4426 after this function has run. Set hourglass_atimer to null
4427 so that we know the timer doesn't have to be canceled. */
4428 hourglass_atimer = NULL;
4429
4430 if (!hourglass_shown_p)
4431 {
4432 Lisp_Object rest, frame;
4433
4434 BLOCK_INPUT;
4435
4436 FOR_EACH_FRAME (rest, frame)
4437 {
4438 struct frame *f = XFRAME (frame);
4439
4440 if (FRAME_LIVE_P (f) && FRAME_X_P (f) && FRAME_X_DISPLAY (f))
4441 {
4442 Display *dpy = FRAME_X_DISPLAY (f);
4443
4444 #ifdef USE_X_TOOLKIT
4445 if (f->output_data.x->widget)
4446 #else
4447 if (FRAME_OUTER_WINDOW (f))
4448 #endif
4449 {
4450 f->output_data.x->hourglass_p = 1;
4451
4452 if (!f->output_data.x->hourglass_window)
4453 {
4454 unsigned long mask = CWCursor;
4455 XSetWindowAttributes attrs;
4456 #ifdef USE_GTK
4457 Window parent = FRAME_X_WINDOW (f);
4458 #else
4459 Window parent = FRAME_OUTER_WINDOW (f);
4460 #endif
4461 attrs.cursor = f->output_data.x->hourglass_cursor;
4462
4463 f->output_data.x->hourglass_window
4464 = XCreateWindow (dpy, parent,
4465 0, 0, 32000, 32000, 0, 0,
4466 InputOnly,
4467 CopyFromParent,
4468 mask, &attrs);
4469 }
4470
4471 XMapRaised (dpy, f->output_data.x->hourglass_window);
4472 XFlush (dpy);
4473 }
4474 }
4475 }
4476
4477 hourglass_shown_p = 1;
4478 UNBLOCK_INPUT;
4479 }
4480 }
4481
4482
4483 /* Hide the hourglass pointer on all frames, if it is currently
4484 shown. */
4485
4486 static void
4487 hide_hourglass ()
4488 {
4489 if (hourglass_shown_p)
4490 {
4491 Lisp_Object rest, frame;
4492
4493 BLOCK_INPUT;
4494 FOR_EACH_FRAME (rest, frame)
4495 {
4496 struct frame *f = XFRAME (frame);
4497
4498 if (FRAME_X_P (f)
4499 /* Watch out for newly created frames. */
4500 && f->output_data.x->hourglass_window)
4501 {
4502 XUnmapWindow (FRAME_X_DISPLAY (f),
4503 f->output_data.x->hourglass_window);
4504 /* Sync here because XTread_socket looks at the
4505 hourglass_p flag that is reset to zero below. */
4506 XSync (FRAME_X_DISPLAY (f), False);
4507 f->output_data.x->hourglass_p = 0;
4508 }
4509 }
4510
4511 hourglass_shown_p = 0;
4512 UNBLOCK_INPUT;
4513 }
4514 }
4515
4516
4517 \f
4518 /***********************************************************************
4519 Tool tips
4520 ***********************************************************************/
4521
4522 static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
4523 Lisp_Object, Lisp_Object));
4524 static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
4525 Lisp_Object, int, int, int *, int *));
4526
4527 /* The frame of a currently visible tooltip. */
4528
4529 Lisp_Object tip_frame;
4530
4531 /* If non-nil, a timer started that hides the last tooltip when it
4532 fires. */
4533
4534 Lisp_Object tip_timer;
4535 Window tip_window;
4536
4537 /* If non-nil, a vector of 3 elements containing the last args
4538 with which x-show-tip was called. See there. */
4539
4540 Lisp_Object last_show_tip_args;
4541
4542 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
4543
4544 Lisp_Object Vx_max_tooltip_size;
4545
4546
4547 static Lisp_Object
4548 unwind_create_tip_frame (frame)
4549 Lisp_Object frame;
4550 {
4551 Lisp_Object deleted;
4552
4553 deleted = unwind_create_frame (frame);
4554 if (EQ (deleted, Qt))
4555 {
4556 tip_window = None;
4557 tip_frame = Qnil;
4558 }
4559
4560 return deleted;
4561 }
4562
4563
4564 /* Create a frame for a tooltip on the display described by DPYINFO.
4565 PARMS is a list of frame parameters. TEXT is the string to
4566 display in the tip frame. Value is the frame.
4567
4568 Note that functions called here, esp. x_default_parameter can
4569 signal errors, for instance when a specified color name is
4570 undefined. We have to make sure that we're in a consistent state
4571 when this happens. */
4572
4573 static Lisp_Object
4574 x_create_tip_frame (dpyinfo, parms, text)
4575 struct x_display_info *dpyinfo;
4576 Lisp_Object parms, text;
4577 {
4578 struct frame *f;
4579 Lisp_Object frame, tem;
4580 Lisp_Object name;
4581 long window_prompting = 0;
4582 int width, height;
4583 int count = SPECPDL_INDEX ();
4584 struct gcpro gcpro1, gcpro2, gcpro3;
4585 struct kboard *kb;
4586 int face_change_count_before = face_change_count;
4587 Lisp_Object buffer;
4588 struct buffer *old_buffer;
4589
4590 check_x ();
4591
4592
4593 #ifdef MULTI_KBOARD
4594 kb = dpyinfo->kboard;
4595 #else
4596 kb = &the_only_kboard;
4597 #endif
4598
4599 /* Get the name of the frame to use for resource lookup. */
4600 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
4601 if (!STRINGP (name)
4602 && !EQ (name, Qunbound)
4603 && !NILP (name))
4604 error ("Invalid frame name--not a string or nil");
4605
4606 frame = Qnil;
4607 GCPRO3 (parms, name, frame);
4608 f = make_frame (1);
4609 XSETFRAME (frame, f);
4610
4611 buffer = Fget_buffer_create (build_string (" *tip*"));
4612 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer, Qnil);
4613 old_buffer = current_buffer;
4614 set_buffer_internal_1 (XBUFFER (buffer));
4615 current_buffer->truncate_lines = Qnil;
4616 specbind (Qinhibit_read_only, Qt);
4617 specbind (Qinhibit_modification_hooks, Qt);
4618 Ferase_buffer ();
4619 Finsert (1, &text);
4620 set_buffer_internal_1 (old_buffer);
4621
4622 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
4623 record_unwind_protect (unwind_create_tip_frame, frame);
4624
4625 /* By setting the output method, we're essentially saying that
4626 the frame is live, as per FRAME_LIVE_P. If we get a signal
4627 from this point on, x_destroy_window might screw up reference
4628 counts etc. */
4629 f->output_method = output_x_window;
4630 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
4631 bzero (f->output_data.x, sizeof (struct x_output));
4632 f->output_data.x->icon_bitmap = -1;
4633 FRAME_FONTSET (f) = -1;
4634 f->output_data.x->scroll_bar_foreground_pixel = -1;
4635 f->output_data.x->scroll_bar_background_pixel = -1;
4636 #ifdef USE_TOOLKIT_SCROLL_BARS
4637 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
4638 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
4639 #endif /* USE_TOOLKIT_SCROLL_BARS */
4640 f->icon_name = Qnil;
4641 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
4642 #if GLYPH_DEBUG
4643 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
4644 dpyinfo_refcount = dpyinfo->reference_count;
4645 #endif /* GLYPH_DEBUG */
4646 #ifdef MULTI_KBOARD
4647 FRAME_KBOARD (f) = kb;
4648 #endif
4649 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4650 f->output_data.x->explicit_parent = 0;
4651
4652 /* These colors will be set anyway later, but it's important
4653 to get the color reference counts right, so initialize them! */
4654 {
4655 Lisp_Object black;
4656 struct gcpro gcpro1;
4657
4658 black = build_string ("black");
4659 GCPRO1 (black);
4660 f->output_data.x->foreground_pixel
4661 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4662 f->output_data.x->background_pixel
4663 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4664 f->output_data.x->cursor_pixel
4665 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4666 f->output_data.x->cursor_foreground_pixel
4667 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4668 f->output_data.x->border_pixel
4669 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4670 f->output_data.x->mouse_pixel
4671 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4672 UNGCPRO;
4673 }
4674
4675 /* Set the name; the functions to which we pass f expect the name to
4676 be set. */
4677 if (EQ (name, Qunbound) || NILP (name))
4678 {
4679 f->name = build_string (dpyinfo->x_id_name);
4680 f->explicit_name = 0;
4681 }
4682 else
4683 {
4684 f->name = name;
4685 f->explicit_name = 1;
4686 /* use the frame's title when getting resources for this frame. */
4687 specbind (Qx_resource_name, name);
4688 }
4689
4690 /* Extract the window parameters from the supplied values that are
4691 needed to determine window geometry. */
4692 {
4693 Lisp_Object font;
4694
4695 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
4696
4697 BLOCK_INPUT;
4698 /* First, try whatever font the caller has specified. */
4699 if (STRINGP (font))
4700 {
4701 tem = Fquery_fontset (font, Qnil);
4702 if (STRINGP (tem))
4703 font = x_new_fontset (f, tem);
4704 else
4705 font = x_new_font (f, SDATA (font));
4706 }
4707
4708 /* Try out a font which we hope has bold and italic variations. */
4709 if (!STRINGP (font))
4710 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4711 if (!STRINGP (font))
4712 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4713 if (! STRINGP (font))
4714 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4715 if (! STRINGP (font))
4716 /* This was formerly the first thing tried, but it finds too many fonts
4717 and takes too long. */
4718 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4719 /* If those didn't work, look for something which will at least work. */
4720 if (! STRINGP (font))
4721 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4722 UNBLOCK_INPUT;
4723 if (! STRINGP (font))
4724 font = build_string ("fixed");
4725
4726 x_default_parameter (f, parms, Qfont, font,
4727 "font", "Font", RES_TYPE_STRING);
4728 }
4729
4730 x_default_parameter (f, parms, Qborder_width, make_number (2),
4731 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
4732
4733 /* This defaults to 2 in order to match xterm. We recognize either
4734 internalBorderWidth or internalBorder (which is what xterm calls
4735 it). */
4736 if (NILP (Fassq (Qinternal_border_width, parms)))
4737 {
4738 Lisp_Object value;
4739
4740 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
4741 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
4742 if (! EQ (value, Qunbound))
4743 parms = Fcons (Fcons (Qinternal_border_width, value),
4744 parms);
4745 }
4746
4747 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
4748 "internalBorderWidth", "internalBorderWidth",
4749 RES_TYPE_NUMBER);
4750
4751 /* Also do the stuff which must be set before the window exists. */
4752 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
4753 "foreground", "Foreground", RES_TYPE_STRING);
4754 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
4755 "background", "Background", RES_TYPE_STRING);
4756 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
4757 "pointerColor", "Foreground", RES_TYPE_STRING);
4758 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
4759 "cursorColor", "Foreground", RES_TYPE_STRING);
4760 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
4761 "borderColor", "BorderColor", RES_TYPE_STRING);
4762
4763 /* Init faces before x_default_parameter is called for scroll-bar
4764 parameters because that function calls x_set_scroll_bar_width,
4765 which calls change_frame_size, which calls Fset_window_buffer,
4766 which runs hooks, which call Fvertical_motion. At the end, we
4767 end up in init_iterator with a null face cache, which should not
4768 happen. */
4769 init_frame_faces (f);
4770
4771 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4772
4773 window_prompting = x_figure_window_size (f, parms, 0);
4774
4775 {
4776 XSetWindowAttributes attrs;
4777 unsigned long mask;
4778
4779 BLOCK_INPUT;
4780 mask = CWBackPixel | CWOverrideRedirect | CWEventMask;
4781 if (DoesSaveUnders (dpyinfo->screen))
4782 mask |= CWSaveUnder;
4783
4784 /* Window managers look at the override-redirect flag to determine
4785 whether or net to give windows a decoration (Xlib spec, chapter
4786 3.2.8). */
4787 attrs.override_redirect = True;
4788 attrs.save_under = True;
4789 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
4790 /* Arrange for getting MapNotify and UnmapNotify events. */
4791 attrs.event_mask = StructureNotifyMask;
4792 tip_window
4793 = FRAME_X_WINDOW (f)
4794 = XCreateWindow (FRAME_X_DISPLAY (f),
4795 FRAME_X_DISPLAY_INFO (f)->root_window,
4796 /* x, y, width, height */
4797 0, 0, 1, 1,
4798 /* Border. */
4799 1,
4800 CopyFromParent, InputOutput, CopyFromParent,
4801 mask, &attrs);
4802 UNBLOCK_INPUT;
4803 }
4804
4805 x_make_gc (f);
4806
4807 x_default_parameter (f, parms, Qauto_raise, Qnil,
4808 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4809 x_default_parameter (f, parms, Qauto_lower, Qnil,
4810 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4811 x_default_parameter (f, parms, Qcursor_type, Qbox,
4812 "cursorType", "CursorType", RES_TYPE_SYMBOL);
4813
4814 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
4815 Change will not be effected unless different from the current
4816 FRAME_LINES (f). */
4817 width = FRAME_COLS (f);
4818 height = FRAME_LINES (f);
4819 SET_FRAME_COLS (f, 0);
4820 FRAME_LINES (f) = 0;
4821 change_frame_size (f, height, width, 1, 0, 0);
4822
4823 /* Add `tooltip' frame parameter's default value. */
4824 if (NILP (Fframe_parameter (frame, intern ("tooltip"))))
4825 Fmodify_frame_parameters (frame, Fcons (Fcons (intern ("tooltip"), Qt),
4826 Qnil));
4827
4828 /* Set up faces after all frame parameters are known. This call
4829 also merges in face attributes specified for new frames.
4830
4831 Frame parameters may be changed if .Xdefaults contains
4832 specifications for the default font. For example, if there is an
4833 `Emacs.default.attributeBackground: pink', the `background-color'
4834 attribute of the frame get's set, which let's the internal border
4835 of the tooltip frame appear in pink. Prevent this. */
4836 {
4837 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
4838
4839 /* Set tip_frame here, so that */
4840 tip_frame = frame;
4841 call1 (Qface_set_after_frame_default, frame);
4842
4843 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
4844 Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
4845 Qnil));
4846 }
4847
4848 f->no_split = 1;
4849
4850 UNGCPRO;
4851
4852 /* It is now ok to make the frame official even if we get an error
4853 below. And the frame needs to be on Vframe_list or making it
4854 visible won't work. */
4855 Vframe_list = Fcons (frame, Vframe_list);
4856
4857 /* Now that the frame is official, it counts as a reference to
4858 its display. */
4859 FRAME_X_DISPLAY_INFO (f)->reference_count++;
4860
4861 /* Setting attributes of faces of the tooltip frame from resources
4862 and similar will increment face_change_count, which leads to the
4863 clearing of all current matrices. Since this isn't necessary
4864 here, avoid it by resetting face_change_count to the value it
4865 had before we created the tip frame. */
4866 face_change_count = face_change_count_before;
4867
4868 /* Discard the unwind_protect. */
4869 return unbind_to (count, frame);
4870 }
4871
4872
4873 /* Compute where to display tip frame F. PARMS is the list of frame
4874 parameters for F. DX and DY are specified offsets from the current
4875 location of the mouse. WIDTH and HEIGHT are the width and height
4876 of the tooltip. Return coordinates relative to the root window of
4877 the display in *ROOT_X, and *ROOT_Y. */
4878
4879 static void
4880 compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
4881 struct frame *f;
4882 Lisp_Object parms, dx, dy;
4883 int width, height;
4884 int *root_x, *root_y;
4885 {
4886 Lisp_Object left, top;
4887 int win_x, win_y;
4888 Window root, child;
4889 unsigned pmask;
4890
4891 /* User-specified position? */
4892 left = Fcdr (Fassq (Qleft, parms));
4893 top = Fcdr (Fassq (Qtop, parms));
4894
4895 /* Move the tooltip window where the mouse pointer is. Resize and
4896 show it. */
4897 if (!INTEGERP (left) || !INTEGERP (top))
4898 {
4899 BLOCK_INPUT;
4900 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
4901 &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
4902 UNBLOCK_INPUT;
4903 }
4904
4905 if (INTEGERP (top))
4906 *root_y = XINT (top);
4907 else if (*root_y + XINT (dy) - height < 0)
4908 *root_y -= XINT (dy);
4909 else
4910 {
4911 *root_y -= height;
4912 *root_y += XINT (dy);
4913 }
4914
4915 if (INTEGERP (left))
4916 *root_x = XINT (left);
4917 else if (*root_x + XINT (dx) + width <= FRAME_X_DISPLAY_INFO (f)->width)
4918 /* It fits to the right of the pointer. */
4919 *root_x += XINT (dx);
4920 else if (width + XINT (dx) <= *root_x)
4921 /* It fits to the left of the pointer. */
4922 *root_x -= width + XINT (dx);
4923 else
4924 /* Put it left-justified on the screen--it ought to fit that way. */
4925 *root_x = 0;
4926 }
4927
4928
4929 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
4930 doc: /* Show STRING in a "tooltip" window on frame FRAME.
4931 A tooltip window is a small X window displaying a string.
4932
4933 FRAME nil or omitted means use the selected frame.
4934
4935 PARMS is an optional list of frame parameters which can be used to
4936 change the tooltip's appearance.
4937
4938 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
4939 means use the default timeout of 5 seconds.
4940
4941 If the list of frame parameters PARAMS contains a `left' parameters,
4942 the tooltip is displayed at that x-position. Otherwise it is
4943 displayed at the mouse position, with offset DX added (default is 5 if
4944 DX isn't specified). Likewise for the y-position; if a `top' frame
4945 parameter is specified, it determines the y-position of the tooltip
4946 window, otherwise it is displayed at the mouse position, with offset
4947 DY added (default is -10).
4948
4949 A tooltip's maximum size is specified by `x-max-tooltip-size'.
4950 Text larger than the specified size is clipped. */)
4951 (string, frame, parms, timeout, dx, dy)
4952 Lisp_Object string, frame, parms, timeout, dx, dy;
4953 {
4954 struct frame *f;
4955 struct window *w;
4956 int root_x, root_y;
4957 struct buffer *old_buffer;
4958 struct text_pos pos;
4959 int i, width, height;
4960 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
4961 int old_windows_or_buffers_changed = windows_or_buffers_changed;
4962 int count = SPECPDL_INDEX ();
4963
4964 specbind (Qinhibit_redisplay, Qt);
4965
4966 GCPRO4 (string, parms, frame, timeout);
4967
4968 CHECK_STRING (string);
4969 f = check_x_frame (frame);
4970 if (NILP (timeout))
4971 timeout = make_number (5);
4972 else
4973 CHECK_NATNUM (timeout);
4974
4975 if (NILP (dx))
4976 dx = make_number (5);
4977 else
4978 CHECK_NUMBER (dx);
4979
4980 if (NILP (dy))
4981 dy = make_number (-10);
4982 else
4983 CHECK_NUMBER (dy);
4984
4985 if (NILP (last_show_tip_args))
4986 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
4987
4988 if (!NILP (tip_frame))
4989 {
4990 Lisp_Object last_string = AREF (last_show_tip_args, 0);
4991 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
4992 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
4993
4994 if (EQ (frame, last_frame)
4995 && !NILP (Fequal (last_string, string))
4996 && !NILP (Fequal (last_parms, parms)))
4997 {
4998 struct frame *f = XFRAME (tip_frame);
4999
5000 /* Only DX and DY have changed. */
5001 if (!NILP (tip_timer))
5002 {
5003 Lisp_Object timer = tip_timer;
5004 tip_timer = Qnil;
5005 call1 (Qcancel_timer, timer);
5006 }
5007
5008 BLOCK_INPUT;
5009 compute_tip_xy (f, parms, dx, dy, FRAME_PIXEL_WIDTH (f),
5010 FRAME_PIXEL_HEIGHT (f), &root_x, &root_y);
5011 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5012 root_x, root_y);
5013 UNBLOCK_INPUT;
5014 goto start_timer;
5015 }
5016 }
5017
5018 /* Hide a previous tip, if any. */
5019 Fx_hide_tip ();
5020
5021 ASET (last_show_tip_args, 0, string);
5022 ASET (last_show_tip_args, 1, frame);
5023 ASET (last_show_tip_args, 2, parms);
5024
5025 /* Add default values to frame parameters. */
5026 if (NILP (Fassq (Qname, parms)))
5027 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
5028 if (NILP (Fassq (Qinternal_border_width, parms)))
5029 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
5030 if (NILP (Fassq (Qborder_width, parms)))
5031 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
5032 if (NILP (Fassq (Qborder_color, parms)))
5033 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
5034 if (NILP (Fassq (Qbackground_color, parms)))
5035 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
5036 parms);
5037
5038 /* Create a frame for the tooltip, and record it in the global
5039 variable tip_frame. */
5040 frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms, string);
5041 f = XFRAME (frame);
5042
5043 /* Set up the frame's root window. */
5044 w = XWINDOW (FRAME_ROOT_WINDOW (f));
5045 w->left_col = w->top_line = make_number (0);
5046
5047 if (CONSP (Vx_max_tooltip_size)
5048 && INTEGERP (XCAR (Vx_max_tooltip_size))
5049 && XINT (XCAR (Vx_max_tooltip_size)) > 0
5050 && INTEGERP (XCDR (Vx_max_tooltip_size))
5051 && XINT (XCDR (Vx_max_tooltip_size)) > 0)
5052 {
5053 w->total_cols = XCAR (Vx_max_tooltip_size);
5054 w->total_lines = XCDR (Vx_max_tooltip_size);
5055 }
5056 else
5057 {
5058 w->total_cols = make_number (80);
5059 w->total_lines = make_number (40);
5060 }
5061
5062 FRAME_TOTAL_COLS (f) = XINT (w->total_cols);
5063 adjust_glyphs (f);
5064 w->pseudo_window_p = 1;
5065
5066 /* Display the tooltip text in a temporary buffer. */
5067 old_buffer = current_buffer;
5068 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
5069 current_buffer->truncate_lines = Qnil;
5070 clear_glyph_matrix (w->desired_matrix);
5071 clear_glyph_matrix (w->current_matrix);
5072 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
5073 try_window (FRAME_ROOT_WINDOW (f), pos, 0);
5074
5075 /* Compute width and height of the tooltip. */
5076 width = height = 0;
5077 for (i = 0; i < w->desired_matrix->nrows; ++i)
5078 {
5079 struct glyph_row *row = &w->desired_matrix->rows[i];
5080 struct glyph *last;
5081 int row_width;
5082
5083 /* Stop at the first empty row at the end. */
5084 if (!row->enabled_p || !row->displays_text_p)
5085 break;
5086
5087 /* Let the row go over the full width of the frame. */
5088 row->full_width_p = 1;
5089
5090 /* There's a glyph at the end of rows that is used to place
5091 the cursor there. Don't include the width of this glyph. */
5092 if (row->used[TEXT_AREA])
5093 {
5094 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
5095 row_width = row->pixel_width - last->pixel_width;
5096 }
5097 else
5098 row_width = row->pixel_width;
5099
5100 height += row->height;
5101 width = max (width, row_width);
5102 }
5103
5104 /* Add the frame's internal border to the width and height the X
5105 window should have. */
5106 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
5107 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
5108
5109 /* Move the tooltip window where the mouse pointer is. Resize and
5110 show it. */
5111 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
5112
5113 BLOCK_INPUT;
5114 XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5115 root_x, root_y, width, height);
5116 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5117 UNBLOCK_INPUT;
5118
5119 /* Draw into the window. */
5120 w->must_be_updated_p = 1;
5121 update_single_window (w, 1);
5122
5123 /* Restore original current buffer. */
5124 set_buffer_internal_1 (old_buffer);
5125 windows_or_buffers_changed = old_windows_or_buffers_changed;
5126
5127 start_timer:
5128 /* Let the tip disappear after timeout seconds. */
5129 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
5130 intern ("x-hide-tip"));
5131
5132 UNGCPRO;
5133 return unbind_to (count, Qnil);
5134 }
5135
5136
5137 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
5138 doc: /* Hide the current tooltip window, if there is any.
5139 Value is t if tooltip was open, nil otherwise. */)
5140 ()
5141 {
5142 int count;
5143 Lisp_Object deleted, frame, timer;
5144 struct gcpro gcpro1, gcpro2;
5145
5146 /* Return quickly if nothing to do. */
5147 if (NILP (tip_timer) && NILP (tip_frame))
5148 return Qnil;
5149
5150 frame = tip_frame;
5151 timer = tip_timer;
5152 GCPRO2 (frame, timer);
5153 tip_frame = tip_timer = deleted = Qnil;
5154
5155 count = SPECPDL_INDEX ();
5156 specbind (Qinhibit_redisplay, Qt);
5157 specbind (Qinhibit_quit, Qt);
5158
5159 if (!NILP (timer))
5160 call1 (Qcancel_timer, timer);
5161
5162 if (FRAMEP (frame))
5163 {
5164 Fdelete_frame (frame, Qnil);
5165 deleted = Qt;
5166
5167 #ifdef USE_LUCID
5168 /* Bloodcurdling hack alert: The Lucid menu bar widget's
5169 redisplay procedure is not called when a tip frame over menu
5170 items is unmapped. Redisplay the menu manually... */
5171 {
5172 struct frame *f = SELECTED_FRAME ();
5173 Widget w = f->output_data.x->menubar_widget;
5174 extern void xlwmenu_redisplay P_ ((Widget));
5175
5176 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen)
5177 && w != NULL)
5178 {
5179 BLOCK_INPUT;
5180 xlwmenu_redisplay (w);
5181 UNBLOCK_INPUT;
5182 }
5183 }
5184 #endif /* USE_LUCID */
5185 }
5186
5187 UNGCPRO;
5188 return unbind_to (count, deleted);
5189 }
5190
5191
5192 \f
5193 /***********************************************************************
5194 File selection dialog
5195 ***********************************************************************/
5196
5197 #ifdef USE_MOTIF
5198
5199 /* Callback for "OK" and "Cancel" on file selection dialog. */
5200
5201 static void
5202 file_dialog_cb (widget, client_data, call_data)
5203 Widget widget;
5204 XtPointer call_data, client_data;
5205 {
5206 int *result = (int *) client_data;
5207 XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
5208 *result = cb->reason;
5209 }
5210
5211
5212 /* Callback for unmapping a file selection dialog. This is used to
5213 capture the case where a dialog is closed via a window manager's
5214 closer button, for example. Using a XmNdestroyCallback didn't work
5215 in this case. */
5216
5217 static void
5218 file_dialog_unmap_cb (widget, client_data, call_data)
5219 Widget widget;
5220 XtPointer call_data, client_data;
5221 {
5222 int *result = (int *) client_data;
5223 *result = XmCR_CANCEL;
5224 }
5225
5226 static Lisp_Object
5227 clean_up_file_dialog (arg)
5228 Lisp_Object arg;
5229 {
5230 struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
5231 Widget dialog = (Widget) p->pointer;
5232
5233 /* Clean up. */
5234 BLOCK_INPUT;
5235 XtUnmanageChild (dialog);
5236 XtDestroyWidget (dialog);
5237 x_menu_set_in_use (0);
5238 UNBLOCK_INPUT;
5239
5240 return Qnil;
5241 }
5242
5243
5244 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
5245 doc: /* Read file name, prompting with PROMPT in directory DIR.
5246 Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
5247 selection box, if specified. If MUSTMATCH is non-nil, the returned file
5248 or directory must exist. ONLY-DIR-P is ignored." */)
5249 (prompt, dir, default_filename, mustmatch, only_dir_p)
5250 Lisp_Object prompt, dir, default_filename, mustmatch, only_dir_p;
5251 {
5252 int result;
5253 struct frame *f = SELECTED_FRAME ();
5254 Lisp_Object file = Qnil;
5255 Widget dialog, text, help;
5256 Arg al[10];
5257 int ac = 0;
5258 extern XtAppContext Xt_app_con;
5259 XmString dir_xmstring, pattern_xmstring;
5260 int count = SPECPDL_INDEX ();
5261 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
5262
5263 GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
5264
5265 if (popup_activated ())
5266 error ("Trying to use a menu from within a menu-entry");
5267
5268 CHECK_STRING (prompt);
5269 CHECK_STRING (dir);
5270
5271 /* Prevent redisplay. */
5272 specbind (Qinhibit_redisplay, Qt);
5273
5274 BLOCK_INPUT;
5275
5276 /* Create the dialog with PROMPT as title, using DIR as initial
5277 directory and using "*" as pattern. */
5278 dir = Fexpand_file_name (dir, Qnil);
5279 dir_xmstring = XmStringCreateLocalized (SDATA (dir));
5280 pattern_xmstring = XmStringCreateLocalized ("*");
5281
5282 XtSetArg (al[ac], XmNtitle, SDATA (prompt)); ++ac;
5283 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
5284 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
5285 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
5286 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
5287 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
5288 "fsb", al, ac);
5289 XmStringFree (dir_xmstring);
5290 XmStringFree (pattern_xmstring);
5291
5292 /* Add callbacks for OK and Cancel. */
5293 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
5294 (XtPointer) &result);
5295 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
5296 (XtPointer) &result);
5297 XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
5298 (XtPointer) &result);
5299
5300 /* Remove the help button since we can't display help. */
5301 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
5302 XtUnmanageChild (help);
5303
5304 /* Mark OK button as default. */
5305 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
5306 XmNshowAsDefault, True, NULL);
5307
5308 /* If MUSTMATCH is non-nil, disable the file entry field of the
5309 dialog, so that the user must select a file from the files list
5310 box. We can't remove it because we wouldn't have a way to get at
5311 the result file name, then. */
5312 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
5313 if (!NILP (mustmatch))
5314 {
5315 Widget label;
5316 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
5317 XtSetSensitive (text, False);
5318 XtSetSensitive (label, False);
5319 }
5320
5321 /* Manage the dialog, so that list boxes get filled. */
5322 XtManageChild (dialog);
5323
5324 if (STRINGP (default_filename))
5325 {
5326 XmString default_xmstring;
5327 Widget wtext = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
5328 Widget list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
5329
5330 XmTextPosition last_pos = XmTextFieldGetLastPosition (wtext);
5331 XmTextFieldReplace (wtext, 0, last_pos,
5332 (SDATA (Ffile_name_nondirectory (default_filename))));
5333
5334 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
5335 must include the path for this to work. */
5336
5337 default_xmstring = XmStringCreateLocalized (SDATA (default_filename));
5338
5339 if (XmListItemExists (list, default_xmstring))
5340 {
5341 int item_pos = XmListItemPos (list, default_xmstring);
5342 /* Select the item and scroll it into view. */
5343 XmListSelectPos (list, item_pos, True);
5344 XmListSetPos (list, item_pos);
5345 }
5346
5347 XmStringFree (default_xmstring);
5348 }
5349
5350 record_unwind_protect (clean_up_file_dialog, make_save_value (dialog, 0));
5351
5352 /* Process events until the user presses Cancel or OK. */
5353 x_menu_set_in_use (1);
5354 result = 0;
5355 while (result == 0)
5356 {
5357 XEvent event;
5358 x_menu_wait_for_event (0);
5359 XtAppNextEvent (Xt_app_con, &event);
5360 if (event.type == KeyPress
5361 && FRAME_X_DISPLAY (f) == event.xkey.display)
5362 {
5363 KeySym keysym = XLookupKeysym (&event.xkey, 0);
5364
5365 /* Pop down on C-g. */
5366 if (keysym == XK_g && (event.xkey.state & ControlMask) != 0)
5367 XtUnmanageChild (dialog);
5368 }
5369
5370 (void) x_dispatch_event (&event, FRAME_X_DISPLAY (f));
5371 }
5372
5373 /* Get the result. */
5374 if (result == XmCR_OK)
5375 {
5376 XmString text;
5377 String data;
5378
5379 XtVaGetValues (dialog, XmNtextString, &text, NULL);
5380 XmStringGetLtoR (text, XmFONTLIST_DEFAULT_TAG, &data);
5381 XmStringFree (text);
5382 file = build_string (data);
5383 XtFree (data);
5384 }
5385 else
5386 file = Qnil;
5387
5388 UNBLOCK_INPUT;
5389 UNGCPRO;
5390
5391 /* Make "Cancel" equivalent to C-g. */
5392 if (NILP (file))
5393 Fsignal (Qquit, Qnil);
5394
5395 return unbind_to (count, file);
5396 }
5397
5398 #endif /* USE_MOTIF */
5399
5400 #ifdef USE_GTK
5401
5402 static Lisp_Object
5403 clean_up_dialog (arg)
5404 Lisp_Object arg;
5405 {
5406 x_menu_set_in_use (0);
5407
5408 return Qnil;
5409 }
5410
5411 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
5412 doc: /* Read file name, prompting with PROMPT in directory DIR.
5413 Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
5414 selection box, if specified. If MUSTMATCH is non-nil, the returned file
5415 or directory must exist. If ONLY-DIR-P is non-nil, the user can only select
5416 directories. */)
5417 (prompt, dir, default_filename, mustmatch, only_dir_p)
5418 Lisp_Object prompt, dir, default_filename, mustmatch, only_dir_p;
5419 {
5420 FRAME_PTR f = SELECTED_FRAME ();
5421 char *fn;
5422 Lisp_Object file = Qnil;
5423 int count = SPECPDL_INDEX ();
5424 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
5425 char *cdef_file;
5426
5427 GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
5428
5429 if (popup_activated ())
5430 error ("Trying to use a menu from within a menu-entry");
5431
5432 CHECK_STRING (prompt);
5433 CHECK_STRING (dir);
5434
5435 /* Prevent redisplay. */
5436 specbind (Qinhibit_redisplay, Qt);
5437 record_unwind_protect (clean_up_dialog, Qnil);
5438
5439 BLOCK_INPUT;
5440
5441 if (STRINGP (default_filename))
5442 cdef_file = SDATA (default_filename);
5443 else
5444 cdef_file = SDATA (dir);
5445
5446 fn = xg_get_file_name (f, SDATA (prompt), cdef_file,
5447 ! NILP (mustmatch),
5448 ! NILP (only_dir_p));
5449
5450 if (fn)
5451 {
5452 file = build_string (fn);
5453 xfree (fn);
5454 }
5455
5456 UNBLOCK_INPUT;
5457 UNGCPRO;
5458
5459 /* Make "Cancel" equivalent to C-g. */
5460 if (NILP (file))
5461 Fsignal (Qquit, Qnil);
5462
5463 return unbind_to (count, file);
5464 }
5465
5466 #endif /* USE_GTK */
5467
5468 \f
5469 /***********************************************************************
5470 Keyboard
5471 ***********************************************************************/
5472
5473 #ifdef HAVE_XKBGETKEYBOARD
5474 #include <X11/XKBlib.h>
5475 #include <X11/keysym.h>
5476 #endif
5477
5478 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
5479 Sx_backspace_delete_keys_p, 0, 1, 0,
5480 doc: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
5481 FRAME nil means use the selected frame.
5482 Value is t if we know that both keys are present, and are mapped to the
5483 usual X keysyms. */)
5484 (frame)
5485 Lisp_Object frame;
5486 {
5487 #ifdef HAVE_XKBGETKEYBOARD
5488 XkbDescPtr kb;
5489 struct frame *f = check_x_frame (frame);
5490 Display *dpy = FRAME_X_DISPLAY (f);
5491 Lisp_Object have_keys;
5492 int major, minor, op, event, error;
5493
5494 BLOCK_INPUT;
5495
5496 /* Check library version in case we're dynamically linked. */
5497 major = XkbMajorVersion;
5498 minor = XkbMinorVersion;
5499 if (!XkbLibraryVersion (&major, &minor))
5500 {
5501 UNBLOCK_INPUT;
5502 return Qnil;
5503 }
5504
5505 /* Check that the server supports XKB. */
5506 major = XkbMajorVersion;
5507 minor = XkbMinorVersion;
5508 if (!XkbQueryExtension (dpy, &op, &event, &error, &major, &minor))
5509 {
5510 UNBLOCK_INPUT;
5511 return Qnil;
5512 }
5513
5514 /* In this code we check that the keyboard has physical keys with names
5515 that start with BKSP (Backspace) and DELE (Delete), and that they
5516 generate keysym XK_BackSpace and XK_Delete respectively.
5517 This function is used to test if normal-erase-is-backspace should be
5518 turned on.
5519 An alternative approach would be to just check if XK_BackSpace and
5520 XK_Delete are mapped to any key. But if any of those are mapped to
5521 some non-intuitive key combination (Meta-Shift-Ctrl-whatever) and the
5522 user doesn't know about it, it is better to return false here.
5523 It is more obvious to the user what to do if she/he has two keys
5524 clearly marked with names/symbols and one key does something not
5525 expected (i.e. she/he then tries the other).
5526 The cases where Backspace/Delete is mapped to some other key combination
5527 are rare, and in those cases, normal-erase-is-backspace can be turned on
5528 manually. */
5529
5530 have_keys = Qnil;
5531 kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
5532 if (kb)
5533 {
5534 int delete_keycode = 0, backspace_keycode = 0, i;
5535
5536 if (XkbGetNames (dpy, XkbAllNamesMask, kb) == Success)
5537 {
5538 for (i = kb->min_key_code;
5539 (i < kb->max_key_code
5540 && (delete_keycode == 0 || backspace_keycode == 0));
5541 ++i)
5542 {
5543 /* The XKB symbolic key names can be seen most easily in
5544 the PS file generated by `xkbprint -label name
5545 $DISPLAY'. */
5546 if (bcmp ("DELE", kb->names->keys[i].name, 4) == 0)
5547 delete_keycode = i;
5548 else if (bcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
5549 backspace_keycode = i;
5550 }
5551
5552 XkbFreeNames (kb, 0, True);
5553 }
5554
5555 XkbFreeClientMap (kb, 0, True);
5556
5557 if (delete_keycode
5558 && backspace_keycode
5559 && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
5560 && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
5561 have_keys = Qt;
5562 }
5563 UNBLOCK_INPUT;
5564 return have_keys;
5565 #else /* not HAVE_XKBGETKEYBOARD */
5566 return Qnil;
5567 #endif /* not HAVE_XKBGETKEYBOARD */
5568 }
5569
5570
5571 \f
5572 /***********************************************************************
5573 Initialization
5574 ***********************************************************************/
5575
5576 /* Keep this list in the same order as frame_parms in frame.c.
5577 Use 0 for unsupported frame parameters. */
5578
5579 frame_parm_handler x_frame_parm_handlers[] =
5580 {
5581 x_set_autoraise,
5582 x_set_autolower,
5583 x_set_background_color,
5584 x_set_border_color,
5585 x_set_border_width,
5586 x_set_cursor_color,
5587 x_set_cursor_type,
5588 x_set_font,
5589 x_set_foreground_color,
5590 x_set_icon_name,
5591 x_set_icon_type,
5592 x_set_internal_border_width,
5593 x_set_menu_bar_lines,
5594 x_set_mouse_color,
5595 x_explicitly_set_name,
5596 x_set_scroll_bar_width,
5597 x_set_title,
5598 x_set_unsplittable,
5599 x_set_vertical_scroll_bars,
5600 x_set_visibility,
5601 x_set_tool_bar_lines,
5602 x_set_scroll_bar_foreground,
5603 x_set_scroll_bar_background,
5604 x_set_screen_gamma,
5605 x_set_line_spacing,
5606 x_set_fringe_width,
5607 x_set_fringe_width,
5608 x_set_wait_for_wm,
5609 x_set_fullscreen,
5610 };
5611
5612 void
5613 syms_of_xfns ()
5614 {
5615 /* This is zero if not using X windows. */
5616 x_in_use = 0;
5617
5618 /* The section below is built by the lisp expression at the top of the file,
5619 just above where these variables are declared. */
5620 /*&&& init symbols here &&&*/
5621 Qnone = intern ("none");
5622 staticpro (&Qnone);
5623 Qsuppress_icon = intern ("suppress-icon");
5624 staticpro (&Qsuppress_icon);
5625 Qundefined_color = intern ("undefined-color");
5626 staticpro (&Qundefined_color);
5627 Qcompound_text = intern ("compound-text");
5628 staticpro (&Qcompound_text);
5629 Qcancel_timer = intern ("cancel-timer");
5630 staticpro (&Qcancel_timer);
5631 /* This is the end of symbol initialization. */
5632
5633 /* Text property `display' should be nonsticky by default. */
5634 Vtext_property_default_nonsticky
5635 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
5636
5637
5638 Fput (Qundefined_color, Qerror_conditions,
5639 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
5640 Fput (Qundefined_color, Qerror_message,
5641 build_string ("Undefined color"));
5642
5643 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
5644 doc: /* The shape of the pointer when over text.
5645 Changing the value does not affect existing frames
5646 unless you set the mouse color. */);
5647 Vx_pointer_shape = Qnil;
5648
5649 #if 0 /* This doesn't really do anything. */
5650 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
5651 doc: /* The shape of the pointer when not over text.
5652 This variable takes effect when you create a new frame
5653 or when you set the mouse color. */);
5654 #endif
5655 Vx_nontext_pointer_shape = Qnil;
5656
5657 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
5658 doc: /* The shape of the pointer when Emacs is busy.
5659 This variable takes effect when you create a new frame
5660 or when you set the mouse color. */);
5661 Vx_hourglass_pointer_shape = Qnil;
5662
5663 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
5664 doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
5665 display_hourglass_p = 1;
5666
5667 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
5668 doc: /* *Seconds to wait before displaying an hourglass pointer.
5669 Value must be an integer or float. */);
5670 Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
5671
5672 #if 0 /* This doesn't really do anything. */
5673 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
5674 doc: /* The shape of the pointer when over the mode line.
5675 This variable takes effect when you create a new frame
5676 or when you set the mouse color. */);
5677 #endif
5678 Vx_mode_pointer_shape = Qnil;
5679
5680 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
5681 &Vx_sensitive_text_pointer_shape,
5682 doc: /* The shape of the pointer when over mouse-sensitive text.
5683 This variable takes effect when you create a new frame
5684 or when you set the mouse color. */);
5685 Vx_sensitive_text_pointer_shape = Qnil;
5686
5687 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
5688 &Vx_window_horizontal_drag_shape,
5689 doc: /* Pointer shape to use for indicating a window can be dragged horizontally.
5690 This variable takes effect when you create a new frame
5691 or when you set the mouse color. */);
5692 Vx_window_horizontal_drag_shape = Qnil;
5693
5694 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
5695 doc: /* A string indicating the foreground color of the cursor box. */);
5696 Vx_cursor_fore_pixel = Qnil;
5697
5698 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size,
5699 doc: /* Maximum size for tooltips. Value is a pair (COLUMNS . ROWS).
5700 Text larger than this is clipped. */);
5701 Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
5702
5703 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
5704 doc: /* Non-nil if no X window manager is in use.
5705 Emacs doesn't try to figure this out; this is always nil
5706 unless you set it to something else. */);
5707 /* We don't have any way to find this out, so set it to nil
5708 and maybe the user would like to set it to t. */
5709 Vx_no_window_manager = Qnil;
5710
5711 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
5712 &Vx_pixel_size_width_font_regexp,
5713 doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
5714
5715 Since Emacs gets width of a font matching with this regexp from
5716 PIXEL_SIZE field of the name, font finding mechanism gets faster for
5717 such a font. This is especially effective for such large fonts as
5718 Chinese, Japanese, and Korean. */);
5719 Vx_pixel_size_width_font_regexp = Qnil;
5720
5721 /* This is not ifdef:ed, so other builds than GTK can customize it. */
5722 DEFVAR_BOOL ("x-use-old-gtk-file-dialog", &x_use_old_gtk_file_dialog,
5723 doc: /* *Non-nil means prompt with the old GTK file selection dialog.
5724 If nil or if the file selection dialog is not available, the new GTK file
5725 chooser is used instead. To turn off all file dialogs set the
5726 variable `use-file-dialog'. */);
5727 x_use_old_gtk_file_dialog = 0;
5728
5729 #ifdef USE_X_TOOLKIT
5730 Fprovide (intern ("x-toolkit"), Qnil);
5731 #ifdef USE_MOTIF
5732 Fprovide (intern ("motif"), Qnil);
5733
5734 DEFVAR_LISP ("motif-version-string", &Vmotif_version_string,
5735 doc: /* Version info for LessTif/Motif. */);
5736 Vmotif_version_string = build_string (XmVERSION_STRING);
5737 #endif /* USE_MOTIF */
5738 #endif /* USE_X_TOOLKIT */
5739
5740 #ifdef USE_GTK
5741 /* Provide x-toolkit also for GTK. Internally GTK does not use Xt so it
5742 is not an X toolkit in that sense (USE_X_TOOLKIT is not defined).
5743 But for a user it is a toolkit for X, and indeed, configure
5744 accepts --with-x-toolkit=gtk. */
5745 Fprovide (intern ("x-toolkit"), Qnil);
5746 Fprovide (intern ("gtk"), Qnil);
5747
5748 DEFVAR_LISP ("gtk-version-string", &Vgtk_version_string,
5749 doc: /* Version info for GTK+. */);
5750 {
5751 char gtk_version[40];
5752 g_snprintf (gtk_version, sizeof (gtk_version), "%u.%u.%u",
5753 GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
5754 Vgtk_version_string = build_string (gtk_version);
5755 }
5756 #endif /* USE_GTK */
5757
5758 /* X window properties. */
5759 defsubr (&Sx_change_window_property);
5760 defsubr (&Sx_delete_window_property);
5761 defsubr (&Sx_window_property);
5762
5763 defsubr (&Sxw_display_color_p);
5764 defsubr (&Sx_display_grayscale_p);
5765 defsubr (&Sxw_color_defined_p);
5766 defsubr (&Sxw_color_values);
5767 defsubr (&Sx_server_max_request_size);
5768 defsubr (&Sx_server_vendor);
5769 defsubr (&Sx_server_version);
5770 defsubr (&Sx_display_pixel_width);
5771 defsubr (&Sx_display_pixel_height);
5772 defsubr (&Sx_display_mm_width);
5773 defsubr (&Sx_display_mm_height);
5774 defsubr (&Sx_display_screens);
5775 defsubr (&Sx_display_planes);
5776 defsubr (&Sx_display_color_cells);
5777 defsubr (&Sx_display_visual_class);
5778 defsubr (&Sx_display_backing_store);
5779 defsubr (&Sx_display_save_under);
5780 defsubr (&Sx_create_frame);
5781 defsubr (&Sx_open_connection);
5782 defsubr (&Sx_close_connection);
5783 defsubr (&Sx_display_list);
5784 defsubr (&Sx_synchronize);
5785 defsubr (&Sx_focus_frame);
5786 defsubr (&Sx_backspace_delete_keys_p);
5787
5788 /* Setting callback functions for fontset handler. */
5789 get_font_info_func = x_get_font_info;
5790
5791 #if 0 /* This function pointer doesn't seem to be used anywhere.
5792 And the pointer assigned has the wrong type, anyway. */
5793 list_fonts_func = x_list_fonts;
5794 #endif
5795
5796 load_font_func = x_load_font;
5797 find_ccl_program_func = x_find_ccl_program;
5798 query_font_func = x_query_font;
5799 set_frame_fontset_func = x_set_font;
5800 get_font_repertory_func = x_get_font_repertory;
5801 check_window_system_func = check_x;
5802
5803 hourglass_atimer = NULL;
5804 hourglass_shown_p = 0;
5805
5806 defsubr (&Sx_show_tip);
5807 defsubr (&Sx_hide_tip);
5808 tip_timer = Qnil;
5809 staticpro (&tip_timer);
5810 tip_frame = Qnil;
5811 staticpro (&tip_frame);
5812
5813 last_show_tip_args = Qnil;
5814 staticpro (&last_show_tip_args);
5815
5816 #if defined (USE_MOTIF) || defined (USE_GTK)
5817 defsubr (&Sx_file_dialog);
5818 #endif
5819 }
5820
5821 #endif /* HAVE_X_WINDOWS */
5822
5823 /* arch-tag: 55040d02-5485-4d58-8b22-95a7a05f3288
5824 (do not change this comment) */