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