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