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