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