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