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