]> 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; !NILP (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 store_frame_param (f, Qwindow_system, Qx);
3683
3684 UNGCPRO;
3685
3686 /* Make sure windows on this frame appear in calls to next-window
3687 and similar functions. */
3688 Vwindow_list = Qnil;
3689
3690 return unbind_to (count, frame);
3691 }
3692
3693
3694 /* FRAME is used only to get a handle on the X display. We don't pass the
3695 display info directly because we're called from frame.c, which doesn't
3696 know about that structure. */
3697
3698 Lisp_Object
3699 x_get_focus_frame (frame)
3700 struct frame *frame;
3701 {
3702 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
3703 Lisp_Object xfocus;
3704 if (! dpyinfo->x_focus_frame)
3705 return Qnil;
3706
3707 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
3708 return xfocus;
3709 }
3710
3711
3712 /* In certain situations, when the window manager follows a
3713 click-to-focus policy, there seems to be no way around calling
3714 XSetInputFocus to give another frame the input focus .
3715
3716 In an ideal world, XSetInputFocus should generally be avoided so
3717 that applications don't interfere with the window manager's focus
3718 policy. But I think it's okay to use when it's clearly done
3719 following a user-command. */
3720
3721 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
3722 doc: /* Set the input focus to FRAME.
3723 FRAME nil means use the selected frame. */)
3724 (frame)
3725 Lisp_Object frame;
3726 {
3727 struct frame *f = check_x_frame (frame);
3728 Display *dpy = FRAME_X_DISPLAY (f);
3729
3730 BLOCK_INPUT;
3731 x_catch_errors (dpy);
3732 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3733 RevertToParent, CurrentTime);
3734 x_ewmh_activate_frame (f);
3735 x_uncatch_errors ();
3736 UNBLOCK_INPUT;
3737
3738 return Qnil;
3739 }
3740
3741 \f
3742 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
3743 doc: /* Internal function called by `color-defined-p', which see. */)
3744 (color, frame)
3745 Lisp_Object color, frame;
3746 {
3747 XColor foo;
3748 FRAME_PTR f = check_x_frame (frame);
3749
3750 CHECK_STRING (color);
3751
3752 if (x_defined_color (f, SDATA (color), &foo, 0))
3753 return Qt;
3754 else
3755 return Qnil;
3756 }
3757
3758 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
3759 doc: /* Internal function called by `color-values', which see. */)
3760 (color, frame)
3761 Lisp_Object color, frame;
3762 {
3763 XColor foo;
3764 FRAME_PTR f = check_x_frame (frame);
3765
3766 CHECK_STRING (color);
3767
3768 if (x_defined_color (f, SDATA (color), &foo, 0))
3769 return list3 (make_number (foo.red),
3770 make_number (foo.green),
3771 make_number (foo.blue));
3772 else
3773 return Qnil;
3774 }
3775
3776 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
3777 doc: /* Internal function called by `display-color-p', which see. */)
3778 (terminal)
3779 Lisp_Object terminal;
3780 {
3781 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3782
3783 if (dpyinfo->n_planes <= 2)
3784 return Qnil;
3785
3786 switch (dpyinfo->visual->class)
3787 {
3788 case StaticColor:
3789 case PseudoColor:
3790 case TrueColor:
3791 case DirectColor:
3792 return Qt;
3793
3794 default:
3795 return Qnil;
3796 }
3797 }
3798
3799 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
3800 0, 1, 0,
3801 doc: /* Return t if the X display supports shades of gray.
3802 Note that color displays do support shades of gray.
3803 The optional argument TERMINAL specifies which display to ask about.
3804 TERMINAL should be a terminal id, a frame or a display name (a string).
3805 If omitted or nil, that stands for the selected frame's display. */)
3806 (terminal)
3807 Lisp_Object terminal;
3808 {
3809 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3810
3811 if (dpyinfo->n_planes <= 1)
3812 return Qnil;
3813
3814 switch (dpyinfo->visual->class)
3815 {
3816 case StaticColor:
3817 case PseudoColor:
3818 case TrueColor:
3819 case DirectColor:
3820 case StaticGray:
3821 case GrayScale:
3822 return Qt;
3823
3824 default:
3825 return Qnil;
3826 }
3827 }
3828
3829 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
3830 0, 1, 0,
3831 doc: /* Returns the width in pixels of the X display TERMINAL.
3832 The optional argument TERMINAL specifies which display to ask about.
3833 TERMINAL should be a terminal id, a frame or a display name (a string).
3834 If omitted or nil, that stands for the selected frame's display. */)
3835 (terminal)
3836 Lisp_Object terminal;
3837 {
3838 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3839
3840 return make_number (dpyinfo->width);
3841 }
3842
3843 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
3844 Sx_display_pixel_height, 0, 1, 0,
3845 doc: /* Returns the height in pixels of the X display TERMINAL.
3846 The optional argument TERMINAL specifies which display to ask about.
3847 TERMINAL should be a terminal id, a frame or a display name (a string).
3848 If omitted or nil, that stands for the selected frame's display. */)
3849 (terminal)
3850 Lisp_Object terminal;
3851 {
3852 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3853
3854 return make_number (dpyinfo->height);
3855 }
3856
3857 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
3858 0, 1, 0,
3859 doc: /* Returns the number of bitplanes of the X display TERMINAL.
3860 The optional argument TERMINAL specifies which display to ask about.
3861 TERMINAL should be a terminal id, a frame or a display name (a string).
3862 If omitted or nil, that stands for the selected frame's display. */)
3863 (terminal)
3864 Lisp_Object terminal;
3865 {
3866 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3867
3868 return make_number (dpyinfo->n_planes);
3869 }
3870
3871 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
3872 0, 1, 0,
3873 doc: /* Returns the number of color cells of the X display TERMINAL.
3874 The optional argument TERMINAL specifies which display to ask about.
3875 TERMINAL should be a terminal id, a frame or a display name (a string).
3876 If omitted or nil, that stands for the selected frame's display. */)
3877 (terminal)
3878 Lisp_Object terminal;
3879 {
3880 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3881
3882 int nr_planes = DisplayPlanes (dpyinfo->display,
3883 XScreenNumberOfScreen (dpyinfo->screen));
3884
3885 /* Truncate nr_planes to 24 to avoid integer overflow.
3886 Some displays says 32, but only 24 bits are actually significant.
3887 There are only very few and rare video cards that have more than
3888 24 significant bits. Also 24 bits is more than 16 million colors,
3889 it "should be enough for everyone". */
3890 if (nr_planes > 24) nr_planes = 24;
3891
3892 return make_number (1 << nr_planes);
3893 }
3894
3895 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
3896 Sx_server_max_request_size,
3897 0, 1, 0,
3898 doc: /* Returns the maximum request size of the X server of display TERMINAL.
3899 The optional argument TERMINAL specifies which display to ask about.
3900 TERMINAL should be a terminal id, a frame or a display name (a string).
3901 If omitted or nil, that stands for the selected frame's display. */)
3902 (terminal)
3903 Lisp_Object terminal;
3904 {
3905 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3906
3907 return make_number (MAXREQUEST (dpyinfo->display));
3908 }
3909
3910 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
3911 doc: /* Returns the "vendor ID" string of the X server of display TERMINAL.
3912 \(Labelling every distributor as a "vendor" embodies the false assumption
3913 that operating systems cannot be developed and distributed noncommercially.)
3914 The optional argument TERMINAL specifies which display to ask about.
3915 TERMINAL should be a terminal id, a frame or a display name (a string).
3916 If omitted or nil, that stands for the selected frame's display. */)
3917 (terminal)
3918 Lisp_Object terminal;
3919 {
3920 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3921 char *vendor = ServerVendor (dpyinfo->display);
3922
3923 if (! vendor) vendor = "";
3924 return build_string (vendor);
3925 }
3926
3927 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
3928 doc: /* Returns the version numbers of the X server of display TERMINAL.
3929 The value is a list of three integers: the major and minor
3930 version numbers of the X Protocol in use, and the distributor-specific release
3931 number. See also the function `x-server-vendor'.
3932
3933 The optional argument TERMINAL specifies which display to ask about.
3934 TERMINAL should be a terminal id, a frame or a display name (a string).
3935 If omitted or nil, that stands for the selected frame's display. */)
3936 (terminal)
3937 Lisp_Object terminal;
3938 {
3939 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3940 Display *dpy = dpyinfo->display;
3941
3942 return Fcons (make_number (ProtocolVersion (dpy)),
3943 Fcons (make_number (ProtocolRevision (dpy)),
3944 Fcons (make_number (VendorRelease (dpy)), Qnil)));
3945 }
3946
3947 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
3948 doc: /* Return the number of screens on the X server of display TERMINAL.
3949 The optional argument TERMINAL specifies which display to ask about.
3950 TERMINAL should be a terminal id, a frame or a display name (a string).
3951 If omitted or nil, that stands for the selected frame's display. */)
3952 (terminal)
3953 Lisp_Object terminal;
3954 {
3955 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3956
3957 return make_number (ScreenCount (dpyinfo->display));
3958 }
3959
3960 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
3961 doc: /* Return the height in millimeters of the X display TERMINAL.
3962 The optional argument TERMINAL specifies which display to ask about.
3963 TERMINAL should be a terminal id, a frame or a display name (a string).
3964 If omitted or nil, that stands for the selected frame's display. */)
3965 (terminal)
3966 Lisp_Object terminal;
3967 {
3968 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3969
3970 return make_number (HeightMMOfScreen (dpyinfo->screen));
3971 }
3972
3973 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
3974 doc: /* Return the width in millimeters of the X display TERMINAL.
3975 The optional argument TERMINAL specifies which display to ask about.
3976 TERMINAL should be a terminal id, a frame or a display name (a string).
3977 If omitted or nil, that stands for the selected frame's display. */)
3978 (terminal)
3979 Lisp_Object terminal;
3980 {
3981 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3982
3983 return make_number (WidthMMOfScreen (dpyinfo->screen));
3984 }
3985
3986 DEFUN ("x-display-backing-store", Fx_display_backing_store,
3987 Sx_display_backing_store, 0, 1, 0,
3988 doc: /* Returns an indication of whether X display TERMINAL does backing store.
3989 The value may be `always', `when-mapped', or `not-useful'.
3990 The optional argument TERMINAL specifies which display to ask about.
3991 TERMINAL should be a terminal id, a frame or a display name (a string).
3992 If omitted or nil, that stands for the selected frame's display. */)
3993 (terminal)
3994 Lisp_Object terminal;
3995 {
3996 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3997 Lisp_Object result;
3998
3999 switch (DoesBackingStore (dpyinfo->screen))
4000 {
4001 case Always:
4002 result = intern ("always");
4003 break;
4004
4005 case WhenMapped:
4006 result = intern ("when-mapped");
4007 break;
4008
4009 case NotUseful:
4010 result = intern ("not-useful");
4011 break;
4012
4013 default:
4014 error ("Strange value for BackingStore parameter of screen");
4015 result = Qnil;
4016 }
4017
4018 return result;
4019 }
4020
4021 DEFUN ("x-display-visual-class", Fx_display_visual_class,
4022 Sx_display_visual_class, 0, 1, 0,
4023 doc: /* Return the visual class of the X display TERMINAL.
4024 The value is one of the symbols `static-gray', `gray-scale',
4025 `static-color', `pseudo-color', `true-color', or `direct-color'.
4026
4027 The optional argument TERMINAL specifies which display to ask about.
4028 TERMINAL should a terminal id, a frame or a display name (a string).
4029 If omitted or nil, that stands for the selected frame's display. */)
4030 (terminal)
4031 Lisp_Object terminal;
4032 {
4033 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4034 Lisp_Object result;
4035
4036 switch (dpyinfo->visual->class)
4037 {
4038 case StaticGray:
4039 result = intern ("static-gray");
4040 break;
4041 case GrayScale:
4042 result = intern ("gray-scale");
4043 break;
4044 case StaticColor:
4045 result = intern ("static-color");
4046 break;
4047 case PseudoColor:
4048 result = intern ("pseudo-color");
4049 break;
4050 case TrueColor:
4051 result = intern ("true-color");
4052 break;
4053 case DirectColor:
4054 result = intern ("direct-color");
4055 break;
4056 default:
4057 error ("Display has an unknown visual class");
4058 result = Qnil;
4059 }
4060
4061 return result;
4062 }
4063
4064 DEFUN ("x-display-save-under", Fx_display_save_under,
4065 Sx_display_save_under, 0, 1, 0,
4066 doc: /* Returns t if the X display TERMINAL supports the save-under feature.
4067 The optional argument TERMINAL specifies which display to ask about.
4068 TERMINAL should be a terminal id, a frame or a display name (a string).
4069 If omitted or nil, that stands for the selected frame's display. */)
4070 (terminal)
4071 Lisp_Object terminal;
4072 {
4073 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4074
4075 if (DoesSaveUnders (dpyinfo->screen) == True)
4076 return Qt;
4077 else
4078 return Qnil;
4079 }
4080 \f
4081 int
4082 x_pixel_width (f)
4083 register struct frame *f;
4084 {
4085 return FRAME_PIXEL_WIDTH (f);
4086 }
4087
4088 int
4089 x_pixel_height (f)
4090 register struct frame *f;
4091 {
4092 return FRAME_PIXEL_HEIGHT (f);
4093 }
4094
4095 int
4096 x_char_width (f)
4097 register struct frame *f;
4098 {
4099 return FRAME_COLUMN_WIDTH (f);
4100 }
4101
4102 int
4103 x_char_height (f)
4104 register struct frame *f;
4105 {
4106 return FRAME_LINE_HEIGHT (f);
4107 }
4108
4109 int
4110 x_screen_planes (f)
4111 register struct frame *f;
4112 {
4113 return FRAME_X_DISPLAY_INFO (f)->n_planes;
4114 }
4115
4116
4117 \f
4118 /************************************************************************
4119 X Displays
4120 ************************************************************************/
4121
4122 \f
4123 /* Mapping visual names to visuals. */
4124
4125 static struct visual_class
4126 {
4127 char *name;
4128 int class;
4129 }
4130 visual_classes[] =
4131 {
4132 {"StaticGray", StaticGray},
4133 {"GrayScale", GrayScale},
4134 {"StaticColor", StaticColor},
4135 {"PseudoColor", PseudoColor},
4136 {"TrueColor", TrueColor},
4137 {"DirectColor", DirectColor},
4138 {NULL, 0}
4139 };
4140
4141
4142 #ifndef HAVE_XSCREENNUMBEROFSCREEN
4143
4144 /* Value is the screen number of screen SCR. This is a substitute for
4145 the X function with the same name when that doesn't exist. */
4146
4147 int
4148 XScreenNumberOfScreen (scr)
4149 register Screen *scr;
4150 {
4151 Display *dpy = scr->display;
4152 int i;
4153
4154 for (i = 0; i < dpy->nscreens; ++i)
4155 if (scr == dpy->screens + i)
4156 break;
4157
4158 return i;
4159 }
4160
4161 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
4162
4163
4164 /* Select the visual that should be used on display DPYINFO. Set
4165 members of DPYINFO appropriately. Called from x_term_init. */
4166
4167 void
4168 select_visual (dpyinfo)
4169 struct x_display_info *dpyinfo;
4170 {
4171 Display *dpy = dpyinfo->display;
4172 Screen *screen = dpyinfo->screen;
4173 Lisp_Object value;
4174
4175 /* See if a visual is specified. */
4176 value = display_x_get_resource (dpyinfo,
4177 build_string ("visualClass"),
4178 build_string ("VisualClass"),
4179 Qnil, Qnil);
4180 if (STRINGP (value))
4181 {
4182 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
4183 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
4184 depth, a decimal number. NAME is compared with case ignored. */
4185 char *s = (char *) alloca (SBYTES (value) + 1);
4186 char *dash;
4187 int i, class = -1;
4188 XVisualInfo vinfo;
4189
4190 strcpy (s, SDATA (value));
4191 dash = index (s, '-');
4192 if (dash)
4193 {
4194 dpyinfo->n_planes = atoi (dash + 1);
4195 *dash = '\0';
4196 }
4197 else
4198 /* We won't find a matching visual with depth 0, so that
4199 an error will be printed below. */
4200 dpyinfo->n_planes = 0;
4201
4202 /* Determine the visual class. */
4203 for (i = 0; visual_classes[i].name; ++i)
4204 if (xstricmp (s, visual_classes[i].name) == 0)
4205 {
4206 class = visual_classes[i].class;
4207 break;
4208 }
4209
4210 /* Look up a matching visual for the specified class. */
4211 if (class == -1
4212 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
4213 dpyinfo->n_planes, class, &vinfo))
4214 fatal ("Invalid visual specification `%s'", SDATA (value));
4215
4216 dpyinfo->visual = vinfo.visual;
4217 }
4218 else
4219 {
4220 int n_visuals;
4221 XVisualInfo *vinfo, vinfo_template;
4222
4223 dpyinfo->visual = DefaultVisualOfScreen (screen);
4224
4225 #ifdef HAVE_X11R4
4226 vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
4227 #else
4228 vinfo_template.visualid = dpyinfo->visual->visualid;
4229 #endif
4230 vinfo_template.screen = XScreenNumberOfScreen (screen);
4231 vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
4232 &vinfo_template, &n_visuals);
4233 if (n_visuals != 1)
4234 fatal ("Can't get proper X visual info");
4235
4236 dpyinfo->n_planes = vinfo->depth;
4237 XFree ((char *) vinfo);
4238 }
4239 }
4240
4241
4242 /* Return the X display structure for the display named NAME.
4243 Open a new connection if necessary. */
4244
4245 struct x_display_info *
4246 x_display_info_for_name (name)
4247 Lisp_Object name;
4248 {
4249 Lisp_Object names;
4250 struct x_display_info *dpyinfo;
4251
4252 CHECK_STRING (name);
4253
4254 #if 0
4255 if (! EQ (Vinitial_window_system, intern ("x")))
4256 error ("Not using X Windows"); /* That doesn't stop us anymore. */
4257 #endif
4258
4259 for (dpyinfo = x_display_list, names = x_display_name_list;
4260 dpyinfo;
4261 dpyinfo = dpyinfo->next, names = XCDR (names))
4262 {
4263 Lisp_Object tem;
4264 tem = Fstring_equal (XCAR (XCAR (names)), name);
4265 if (!NILP (tem))
4266 return dpyinfo;
4267 }
4268
4269 /* Use this general default value to start with. */
4270 Vx_resource_name = Vinvocation_name;
4271
4272 validate_x_resource_name ();
4273
4274 dpyinfo = x_term_init (name, (char *)0,
4275 (char *) SDATA (Vx_resource_name));
4276
4277 if (dpyinfo == 0)
4278 error ("Cannot connect to X server %s", SDATA (name));
4279
4280 x_in_use = 1;
4281 XSETFASTINT (Vwindow_system_version, 11);
4282
4283 return dpyinfo;
4284 }
4285
4286
4287 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
4288 1, 3, 0,
4289 doc: /* Open a connection to an X server.
4290 DISPLAY is the name of the display to connect to.
4291 Optional second arg XRM-STRING is a string of resources in xrdb format.
4292 If the optional third arg MUST-SUCCEED is non-nil,
4293 terminate Emacs if we can't open the connection. */)
4294 (display, xrm_string, must_succeed)
4295 Lisp_Object display, xrm_string, must_succeed;
4296 {
4297 unsigned char *xrm_option;
4298 struct x_display_info *dpyinfo;
4299
4300 CHECK_STRING (display);
4301 if (! NILP (xrm_string))
4302 CHECK_STRING (xrm_string);
4303
4304 #if 0
4305 if (! EQ (Vinitial_window_system, intern ("x")))
4306 error ("Not using X Windows"); /* That doesn't stop us anymore. */
4307 #endif
4308
4309 if (! NILP (xrm_string))
4310 xrm_option = (unsigned char *) SDATA (xrm_string);
4311 else
4312 xrm_option = (unsigned char *) 0;
4313
4314 validate_x_resource_name ();
4315
4316 /* This is what opens the connection and sets x_current_display.
4317 This also initializes many symbols, such as those used for input. */
4318 dpyinfo = x_term_init (display, xrm_option,
4319 (char *) SDATA (Vx_resource_name));
4320
4321 if (dpyinfo == 0)
4322 {
4323 if (!NILP (must_succeed))
4324 fatal ("Cannot connect to X server %s.\n\
4325 Check the DISPLAY environment variable or use `-d'.\n\
4326 Also use the `xauth' program to verify that you have the proper\n\
4327 authorization information needed to connect the X server.\n\
4328 An insecure way to solve the problem may be to use `xhost'.\n",
4329 SDATA (display));
4330 else
4331 error ("Cannot connect to X server %s", SDATA (display));
4332 }
4333
4334 x_in_use = 1;
4335
4336 XSETFASTINT (Vwindow_system_version, 11);
4337 return Qnil;
4338 }
4339
4340 DEFUN ("x-close-connection", Fx_close_connection,
4341 Sx_close_connection, 1, 1, 0,
4342 doc: /* Close the connection to TERMINAL's X server.
4343 For TERMINAL, specify a terminal id, a frame or a display name (a
4344 string). If TERMINAL is nil, that stands for the selected frame's
4345 terminal. */)
4346 (terminal)
4347 Lisp_Object terminal;
4348 {
4349 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4350
4351 if (dpyinfo->reference_count > 0)
4352 error ("Display still has frames on it");
4353
4354 x_delete_terminal (dpyinfo->terminal);
4355
4356 return Qnil;
4357 }
4358
4359 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
4360 doc: /* Return the list of display names that Emacs has connections to. */)
4361 ()
4362 {
4363 Lisp_Object tail, result;
4364
4365 result = Qnil;
4366 for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
4367 result = Fcons (XCAR (XCAR (tail)), result);
4368
4369 return result;
4370 }
4371
4372 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
4373 doc: /* If ON is non-nil, report X errors as soon as the erring request is made.
4374 If ON is nil, allow buffering of requests.
4375 Turning on synchronization prohibits the Xlib routines from buffering
4376 requests and seriously degrades performance, but makes debugging much
4377 easier.
4378 The optional second argument TERMINAL specifies which display to act on.
4379 TERMINAL should be a terminal id, a frame or a display name (a string).
4380 If TERMINAL is omitted or nil, that stands for the selected frame's display. */)
4381 (on, terminal)
4382 Lisp_Object terminal, on;
4383 {
4384 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4385
4386 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
4387
4388 return Qnil;
4389 }
4390
4391 /* Wait for responses to all X commands issued so far for frame F. */
4392
4393 void
4394 x_sync (f)
4395 FRAME_PTR f;
4396 {
4397 BLOCK_INPUT;
4398 XSync (FRAME_X_DISPLAY (f), False);
4399 UNBLOCK_INPUT;
4400 }
4401
4402 \f
4403 /***********************************************************************
4404 Window properties
4405 ***********************************************************************/
4406
4407 DEFUN ("x-change-window-property", Fx_change_window_property,
4408 Sx_change_window_property, 2, 6, 0,
4409 doc: /* Change window property PROP to VALUE on the X window of FRAME.
4410 PROP must be a string.
4411 VALUE may be a string or a list of conses, numbers and/or strings.
4412 If an element in the list is a string, it is converted to
4413 an Atom and the value of the Atom is used. If an element is a cons,
4414 it is converted to a 32 bit number where the car is the 16 top bits and the
4415 cdr is the lower 16 bits.
4416 FRAME nil or omitted means use the selected frame.
4417 If TYPE is given and non-nil, it is the name of the type of VALUE.
4418 If TYPE is not given or nil, the type is STRING.
4419 FORMAT gives the size in bits of each element if VALUE is a list.
4420 It must be one of 8, 16 or 32.
4421 If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to 8.
4422 If OUTER_P is non-nil, the property is changed for the outer X window of
4423 FRAME. Default is to change on the edit X window.
4424
4425 Value is VALUE. */)
4426 (prop, value, frame, type, format, outer_p)
4427 Lisp_Object prop, value, frame, type, format, outer_p;
4428 {
4429 struct frame *f = check_x_frame (frame);
4430 Atom prop_atom;
4431 Atom target_type = XA_STRING;
4432 int element_format = 8;
4433 unsigned char *data;
4434 int nelements;
4435 Window w;
4436
4437 CHECK_STRING (prop);
4438
4439 if (! NILP (format))
4440 {
4441 CHECK_NUMBER (format);
4442 element_format = XFASTINT (format);
4443
4444 if (element_format != 8 && element_format != 16
4445 && element_format != 32)
4446 error ("FORMAT must be one of 8, 16 or 32");
4447 }
4448
4449 if (CONSP (value))
4450 {
4451 nelements = x_check_property_data (value);
4452 if (nelements == -1)
4453 error ("Bad data in VALUE, must be number, string or cons");
4454
4455 if (element_format == 8)
4456 data = (unsigned char *) xmalloc (nelements);
4457 else if (element_format == 16)
4458 data = (unsigned char *) xmalloc (nelements*2);
4459 else /* format == 32 */
4460 /* The man page for XChangeProperty:
4461 "If the specified format is 32, the property data must be a
4462 long array."
4463 This applies even if long is more than 64 bits. The X library
4464 converts to 32 bits before sending to the X server. */
4465 data = (unsigned char *) xmalloc (nelements * sizeof(long));
4466
4467 x_fill_property_data (FRAME_X_DISPLAY (f), value, data, element_format);
4468 }
4469 else
4470 {
4471 CHECK_STRING (value);
4472 data = SDATA (value);
4473 nelements = SCHARS (value);
4474 }
4475
4476 BLOCK_INPUT;
4477 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
4478 if (! NILP (type))
4479 {
4480 CHECK_STRING (type);
4481 target_type = XInternAtom (FRAME_X_DISPLAY (f), SDATA (type), False);
4482 }
4483
4484 if (! NILP (outer_p)) w = FRAME_OUTER_WINDOW (f);
4485 else w = FRAME_X_WINDOW (f);
4486
4487 XChangeProperty (FRAME_X_DISPLAY (f), w,
4488 prop_atom, target_type, element_format, PropModeReplace,
4489 data, nelements);
4490
4491 if (CONSP (value)) xfree (data);
4492
4493 /* Make sure the property is set when we return. */
4494 XFlush (FRAME_X_DISPLAY (f));
4495 UNBLOCK_INPUT;
4496
4497 return value;
4498 }
4499
4500
4501 DEFUN ("x-delete-window-property", Fx_delete_window_property,
4502 Sx_delete_window_property, 1, 2, 0,
4503 doc: /* Remove window property PROP from X window of FRAME.
4504 FRAME nil or omitted means use the selected frame. Value is PROP. */)
4505 (prop, frame)
4506 Lisp_Object prop, frame;
4507 {
4508 struct frame *f = check_x_frame (frame);
4509 Atom prop_atom;
4510
4511 CHECK_STRING (prop);
4512 BLOCK_INPUT;
4513 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
4514 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
4515
4516 /* Make sure the property is removed when we return. */
4517 XFlush (FRAME_X_DISPLAY (f));
4518 UNBLOCK_INPUT;
4519
4520 return prop;
4521 }
4522
4523
4524 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
4525 1, 6, 0,
4526 doc: /* Value is the value of window property PROP on FRAME.
4527 If FRAME is nil or omitted, use the selected frame.
4528 If TYPE is nil or omitted, get the property as a string. Otherwise TYPE
4529 is the name of the Atom that denotes the type expected.
4530 If SOURCE is non-nil, get the property on that window instead of from
4531 FRAME. The number 0 denotes the root window.
4532 If DELETE_P is non-nil, delete the property after retreiving it.
4533 If VECTOR_RET_P is non-nil, don't return a string but a vector of values.
4534
4535 Value is nil if FRAME hasn't a property with name PROP or if PROP has
4536 no value of TYPE. */)
4537 (prop, frame, type, source, delete_p, vector_ret_p)
4538 Lisp_Object prop, frame, type, source, delete_p, vector_ret_p;
4539 {
4540 struct frame *f = check_x_frame (frame);
4541 Atom prop_atom;
4542 int rc;
4543 Lisp_Object prop_value = Qnil;
4544 unsigned char *tmp_data = NULL;
4545 Atom actual_type;
4546 Atom target_type = XA_STRING;
4547 int actual_format;
4548 unsigned long actual_size, bytes_remaining;
4549 Window target_window = FRAME_X_WINDOW (f);
4550 struct gcpro gcpro1;
4551
4552 GCPRO1 (prop_value);
4553 CHECK_STRING (prop);
4554
4555 if (! NILP (source))
4556 {
4557 if (NUMBERP (source))
4558 {
4559 if (FLOATP (source))
4560 target_window = (Window) XFLOAT (source);
4561 else
4562 target_window = XFASTINT (source);
4563
4564 if (target_window == 0)
4565 target_window = FRAME_X_DISPLAY_INFO (f)->root_window;
4566 }
4567 else if (CONSP (source))
4568 target_window = cons_to_long (source);
4569 }
4570
4571 BLOCK_INPUT;
4572 if (STRINGP (type))
4573 {
4574 if (strcmp ("AnyPropertyType", SDATA (type)) == 0)
4575 target_type = AnyPropertyType;
4576 else
4577 target_type = XInternAtom (FRAME_X_DISPLAY (f), SDATA (type), False);
4578 }
4579
4580 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
4581 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
4582 prop_atom, 0, 0, False, target_type,
4583 &actual_type, &actual_format, &actual_size,
4584 &bytes_remaining, &tmp_data);
4585 if (rc == Success)
4586 {
4587 int size = bytes_remaining;
4588
4589 XFree (tmp_data);
4590 tmp_data = NULL;
4591
4592 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
4593 prop_atom, 0, bytes_remaining,
4594 ! NILP (delete_p), target_type,
4595 &actual_type, &actual_format,
4596 &actual_size, &bytes_remaining,
4597 &tmp_data);
4598 if (rc == Success && tmp_data)
4599 {
4600 /* The man page for XGetWindowProperty says:
4601 "If the returned format is 32, the returned data is represented
4602 as a long array and should be cast to that type to obtain the
4603 elements."
4604 This applies even if long is more than 32 bits, the X library
4605 converts from 32 bit elements received from the X server to long
4606 and passes the long array to us. Thus, for that case bcopy can not
4607 be used. We convert to a 32 bit type here, because so much code
4608 assume on that.
4609
4610 The bytes and offsets passed to XGetWindowProperty refers to the
4611 property and those are indeed in 32 bit quantities if format is
4612 32. */
4613
4614 if (actual_format == 32 && actual_format < BITS_PER_LONG)
4615 {
4616 unsigned long i;
4617 int *idata = (int *) tmp_data;
4618 long *ldata = (long *) tmp_data;
4619
4620 for (i = 0; i < actual_size; ++i)
4621 idata[i] = (int) ldata[i];
4622 }
4623
4624 if (NILP (vector_ret_p))
4625 prop_value = make_string (tmp_data, size);
4626 else
4627 prop_value = x_property_data_to_lisp (f,
4628 tmp_data,
4629 actual_type,
4630 actual_format,
4631 actual_size);
4632 }
4633
4634 if (tmp_data) XFree (tmp_data);
4635 }
4636
4637 UNBLOCK_INPUT;
4638 UNGCPRO;
4639 return prop_value;
4640 }
4641
4642
4643 \f
4644 /***********************************************************************
4645 Busy cursor
4646 ***********************************************************************/
4647
4648 /* If non-null, an asynchronous timer that, when it expires, displays
4649 an hourglass cursor on all frames. */
4650
4651 static struct atimer *hourglass_atimer;
4652
4653 /* Non-zero means an hourglass cursor is currently shown. */
4654
4655 static int hourglass_shown_p;
4656
4657 /* Number of seconds to wait before displaying an hourglass cursor. */
4658
4659 static Lisp_Object Vhourglass_delay;
4660
4661 /* Default number of seconds to wait before displaying an hourglass
4662 cursor. */
4663
4664 #define DEFAULT_HOURGLASS_DELAY 1
4665
4666 /* Function prototypes. */
4667
4668 static void show_hourglass P_ ((struct atimer *));
4669 static void hide_hourglass P_ ((void));
4670
4671 /* Return non-zero if houglass timer has been started or hourglass is shown. */
4672
4673 int
4674 hourglass_started ()
4675 {
4676 return hourglass_shown_p || hourglass_atimer != NULL;
4677 }
4678
4679
4680 /* Cancel a currently active hourglass timer, and start a new one. */
4681
4682 void
4683 start_hourglass ()
4684 {
4685 EMACS_TIME delay;
4686 int secs, usecs = 0;
4687
4688 cancel_hourglass ();
4689
4690 if (INTEGERP (Vhourglass_delay)
4691 && XINT (Vhourglass_delay) > 0)
4692 secs = XFASTINT (Vhourglass_delay);
4693 else if (FLOATP (Vhourglass_delay)
4694 && XFLOAT_DATA (Vhourglass_delay) > 0)
4695 {
4696 Lisp_Object tem;
4697 tem = Ftruncate (Vhourglass_delay, Qnil);
4698 secs = XFASTINT (tem);
4699 usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
4700 }
4701 else
4702 secs = DEFAULT_HOURGLASS_DELAY;
4703
4704 EMACS_SET_SECS_USECS (delay, secs, usecs);
4705 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
4706 show_hourglass, NULL);
4707 }
4708
4709
4710 /* Cancel the hourglass cursor timer if active, hide a busy cursor if
4711 shown. */
4712
4713 void
4714 cancel_hourglass ()
4715 {
4716 if (hourglass_atimer)
4717 {
4718 cancel_atimer (hourglass_atimer);
4719 hourglass_atimer = NULL;
4720 }
4721
4722 if (hourglass_shown_p)
4723 hide_hourglass ();
4724 }
4725
4726
4727 /* Timer function of hourglass_atimer. TIMER is equal to
4728 hourglass_atimer.
4729
4730 Display an hourglass pointer on all frames by mapping the frames'
4731 hourglass_window. Set the hourglass_p flag in the frames'
4732 output_data.x structure to indicate that an hourglass cursor is
4733 shown on the frames. */
4734
4735 static void
4736 show_hourglass (timer)
4737 struct atimer *timer;
4738 {
4739 /* The timer implementation will cancel this timer automatically
4740 after this function has run. Set hourglass_atimer to null
4741 so that we know the timer doesn't have to be canceled. */
4742 hourglass_atimer = NULL;
4743
4744 if (!hourglass_shown_p)
4745 {
4746 Lisp_Object rest, frame;
4747
4748 BLOCK_INPUT;
4749
4750 FOR_EACH_FRAME (rest, frame)
4751 {
4752 struct frame *f = XFRAME (frame);
4753
4754 if (FRAME_LIVE_P (f) && FRAME_X_P (f) && FRAME_X_DISPLAY (f))
4755 {
4756 Display *dpy = FRAME_X_DISPLAY (f);
4757
4758 #ifdef USE_X_TOOLKIT
4759 if (f->output_data.x->widget)
4760 #else
4761 if (FRAME_OUTER_WINDOW (f))
4762 #endif
4763 {
4764 f->output_data.x->hourglass_p = 1;
4765
4766 if (!f->output_data.x->hourglass_window)
4767 {
4768 unsigned long mask = CWCursor;
4769 XSetWindowAttributes attrs;
4770 #ifdef USE_GTK
4771 Window parent = FRAME_X_WINDOW (f);
4772 #else
4773 Window parent = FRAME_OUTER_WINDOW (f);
4774 #endif
4775 attrs.cursor = f->output_data.x->hourglass_cursor;
4776
4777 f->output_data.x->hourglass_window
4778 = XCreateWindow (dpy, parent,
4779 0, 0, 32000, 32000, 0, 0,
4780 InputOnly,
4781 CopyFromParent,
4782 mask, &attrs);
4783 }
4784
4785 XMapRaised (dpy, f->output_data.x->hourglass_window);
4786 XFlush (dpy);
4787 }
4788 }
4789 }
4790
4791 hourglass_shown_p = 1;
4792 UNBLOCK_INPUT;
4793 }
4794 }
4795
4796
4797 /* Hide the hourglass pointer on all frames, if it is currently
4798 shown. */
4799
4800 static void
4801 hide_hourglass ()
4802 {
4803 if (hourglass_shown_p)
4804 {
4805 Lisp_Object rest, frame;
4806
4807 BLOCK_INPUT;
4808 FOR_EACH_FRAME (rest, frame)
4809 {
4810 struct frame *f = XFRAME (frame);
4811
4812 if (FRAME_X_P (f)
4813 /* Watch out for newly created frames. */
4814 && f->output_data.x->hourglass_window)
4815 {
4816 XUnmapWindow (FRAME_X_DISPLAY (f),
4817 f->output_data.x->hourglass_window);
4818 /* Sync here because XTread_socket looks at the
4819 hourglass_p flag that is reset to zero below. */
4820 XSync (FRAME_X_DISPLAY (f), False);
4821 f->output_data.x->hourglass_p = 0;
4822 }
4823 }
4824
4825 hourglass_shown_p = 0;
4826 UNBLOCK_INPUT;
4827 }
4828 }
4829
4830
4831 \f
4832 /***********************************************************************
4833 Tool tips
4834 ***********************************************************************/
4835
4836 static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
4837 Lisp_Object, Lisp_Object));
4838 static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
4839 Lisp_Object, int, int, int *, int *));
4840
4841 /* The frame of a currently visible tooltip. */
4842
4843 Lisp_Object tip_frame;
4844
4845 /* If non-nil, a timer started that hides the last tooltip when it
4846 fires. */
4847
4848 Lisp_Object tip_timer;
4849 Window tip_window;
4850
4851 /* If non-nil, a vector of 3 elements containing the last args
4852 with which x-show-tip was called. See there. */
4853
4854 Lisp_Object last_show_tip_args;
4855
4856 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
4857
4858 Lisp_Object Vx_max_tooltip_size;
4859
4860
4861 static Lisp_Object
4862 unwind_create_tip_frame (frame)
4863 Lisp_Object frame;
4864 {
4865 Lisp_Object deleted;
4866
4867 deleted = unwind_create_frame (frame);
4868 if (EQ (deleted, Qt))
4869 {
4870 tip_window = None;
4871 tip_frame = Qnil;
4872 }
4873
4874 return deleted;
4875 }
4876
4877
4878 /* Create a frame for a tooltip on the display described by DPYINFO.
4879 PARMS is a list of frame parameters. TEXT is the string to
4880 display in the tip frame. Value is the frame.
4881
4882 Note that functions called here, esp. x_default_parameter can
4883 signal errors, for instance when a specified color name is
4884 undefined. We have to make sure that we're in a consistent state
4885 when this happens. */
4886
4887 static Lisp_Object
4888 x_create_tip_frame (dpyinfo, parms, text)
4889 struct x_display_info *dpyinfo;
4890 Lisp_Object parms, text;
4891 {
4892 struct frame *f;
4893 Lisp_Object frame, tem;
4894 Lisp_Object name;
4895 long window_prompting = 0;
4896 int width, height;
4897 int count = SPECPDL_INDEX ();
4898 struct gcpro gcpro1, gcpro2, gcpro3;
4899 int face_change_count_before = face_change_count;
4900 Lisp_Object buffer;
4901 struct buffer *old_buffer;
4902
4903 check_x ();
4904
4905 if (!dpyinfo->terminal->name)
4906 error ("Terminal is not live, can't create new frames on it");
4907
4908 parms = Fcopy_alist (parms);
4909
4910 /* Get the name of the frame to use for resource lookup. */
4911 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
4912 if (!STRINGP (name)
4913 && !EQ (name, Qunbound)
4914 && !NILP (name))
4915 error ("Invalid frame name--not a string or nil");
4916
4917 frame = Qnil;
4918 GCPRO3 (parms, name, frame);
4919 f = make_frame (1);
4920 XSETFRAME (frame, f);
4921
4922 buffer = Fget_buffer_create (build_string (" *tip*"));
4923 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer, Qnil);
4924 old_buffer = current_buffer;
4925 set_buffer_internal_1 (XBUFFER (buffer));
4926 current_buffer->truncate_lines = Qnil;
4927 specbind (Qinhibit_read_only, Qt);
4928 specbind (Qinhibit_modification_hooks, Qt);
4929 Ferase_buffer ();
4930 Finsert (1, &text);
4931 set_buffer_internal_1 (old_buffer);
4932
4933 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
4934 record_unwind_protect (unwind_create_tip_frame, frame);
4935
4936 f->terminal = dpyinfo->terminal;
4937 f->terminal->reference_count++;
4938
4939 /* By setting the output method, we're essentially saying that
4940 the frame is live, as per FRAME_LIVE_P. If we get a signal
4941 from this point on, x_destroy_window might screw up reference
4942 counts etc. */
4943 f->output_method = output_x_window;
4944 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
4945 bzero (f->output_data.x, sizeof (struct x_output));
4946 f->output_data.x->icon_bitmap = -1;
4947 FRAME_FONTSET (f) = -1;
4948 f->output_data.x->scroll_bar_foreground_pixel = -1;
4949 f->output_data.x->scroll_bar_background_pixel = -1;
4950 #ifdef USE_TOOLKIT_SCROLL_BARS
4951 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
4952 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
4953 #endif /* USE_TOOLKIT_SCROLL_BARS */
4954 f->icon_name = Qnil;
4955 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
4956 #if GLYPH_DEBUG
4957 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
4958 dpyinfo_refcount = dpyinfo->reference_count;
4959 #endif /* GLYPH_DEBUG */
4960 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4961 f->output_data.x->explicit_parent = 0;
4962
4963 /* These colors will be set anyway later, but it's important
4964 to get the color reference counts right, so initialize them! */
4965 {
4966 Lisp_Object black;
4967 struct gcpro gcpro1;
4968
4969 /* Function x_decode_color can signal an error. Make
4970 sure to initialize color slots so that we won't try
4971 to free colors we haven't allocated. */
4972 FRAME_FOREGROUND_PIXEL (f) = -1;
4973 FRAME_BACKGROUND_PIXEL (f) = -1;
4974 f->output_data.x->cursor_pixel = -1;
4975 f->output_data.x->cursor_foreground_pixel = -1;
4976 f->output_data.x->border_pixel = -1;
4977 f->output_data.x->mouse_pixel = -1;
4978
4979 black = build_string ("black");
4980 GCPRO1 (black);
4981 FRAME_FOREGROUND_PIXEL (f)
4982 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4983 FRAME_BACKGROUND_PIXEL (f)
4984 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4985 f->output_data.x->cursor_pixel
4986 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4987 f->output_data.x->cursor_foreground_pixel
4988 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4989 f->output_data.x->border_pixel
4990 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4991 f->output_data.x->mouse_pixel
4992 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4993 UNGCPRO;
4994 }
4995
4996 /* Set the name; the functions to which we pass f expect the name to
4997 be set. */
4998 if (EQ (name, Qunbound) || NILP (name))
4999 {
5000 f->name = build_string (dpyinfo->x_id_name);
5001 f->explicit_name = 0;
5002 }
5003 else
5004 {
5005 f->name = name;
5006 f->explicit_name = 1;
5007 /* use the frame's title when getting resources for this frame. */
5008 specbind (Qx_resource_name, name);
5009 }
5010
5011 f->resx = dpyinfo->resx;
5012 f->resy = dpyinfo->resy;
5013
5014 #ifdef USE_FONT_BACKEND
5015 if (enable_font_backend)
5016 {
5017 /* Perhaps, we must allow frame parameter, say `font-backend',
5018 to specify which font backends to use. */
5019 #ifdef HAVE_FREETYPE
5020 #ifdef HAVE_XFT
5021 register_font_driver (&xftfont_driver, f);
5022 #else /* not HAVE_XFT */
5023 register_font_driver (&ftxfont_driver, f);
5024 #endif /* not HAVE_XFT */
5025 #endif /* HAVE_FREETYPE */
5026 register_font_driver (&xfont_driver, f);
5027
5028 x_default_parameter (f, parms, Qfont_backend, Qnil,
5029 "fontBackend", "FontBackend", RES_TYPE_STRING);
5030 }
5031 #endif /* USE_FONT_BACKEND */
5032
5033 /* Extract the window parameters from the supplied values that are
5034 needed to determine window geometry. */
5035 #ifdef USE_FONT_BACKEND
5036 if (enable_font_backend)
5037 x_default_font_parameter (f, parms);
5038 else
5039 #endif /* USE_FONT_BACKEND */
5040 {
5041 Lisp_Object font;
5042
5043 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
5044
5045 BLOCK_INPUT;
5046 /* First, try whatever font the caller has specified. */
5047 if (STRINGP (font))
5048 {
5049 tem = Fquery_fontset (font, Qnil);
5050 if (STRINGP (tem))
5051 font = x_new_fontset (f, tem);
5052 else
5053 font = x_new_font (f, SDATA (font));
5054 }
5055
5056 /* Try out a font which we hope has bold and italic variations. */
5057 if (!STRINGP (font))
5058 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
5059 if (!STRINGP (font))
5060 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
5061 if (! STRINGP (font))
5062 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
5063 if (! STRINGP (font))
5064 /* This was formerly the first thing tried, but it finds too many fonts
5065 and takes too long. */
5066 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
5067 /* If those didn't work, look for something which will at least work. */
5068 if (! STRINGP (font))
5069 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
5070 UNBLOCK_INPUT;
5071 if (! STRINGP (font))
5072 font = build_string ("fixed");
5073
5074 x_set_frame_parameters (f, Fcons (Fcons (Qfont, font), Qnil));
5075 }
5076
5077 x_default_parameter (f, parms, Qborder_width, make_number (2),
5078 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
5079
5080 /* This defaults to 2 in order to match xterm. We recognize either
5081 internalBorderWidth or internalBorder (which is what xterm calls
5082 it). */
5083 if (NILP (Fassq (Qinternal_border_width, parms)))
5084 {
5085 Lisp_Object value;
5086
5087 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
5088 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
5089 if (! EQ (value, Qunbound))
5090 parms = Fcons (Fcons (Qinternal_border_width, value),
5091 parms);
5092 }
5093
5094 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
5095 "internalBorderWidth", "internalBorderWidth",
5096 RES_TYPE_NUMBER);
5097
5098 /* Also do the stuff which must be set before the window exists. */
5099 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
5100 "foreground", "Foreground", RES_TYPE_STRING);
5101 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
5102 "background", "Background", RES_TYPE_STRING);
5103 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
5104 "pointerColor", "Foreground", RES_TYPE_STRING);
5105 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
5106 "cursorColor", "Foreground", RES_TYPE_STRING);
5107 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
5108 "borderColor", "BorderColor", RES_TYPE_STRING);
5109
5110 /* Init faces before x_default_parameter is called for scroll-bar
5111 parameters because that function calls x_set_scroll_bar_width,
5112 which calls change_frame_size, which calls Fset_window_buffer,
5113 which runs hooks, which call Fvertical_motion. At the end, we
5114 end up in init_iterator with a null face cache, which should not
5115 happen. */
5116 init_frame_faces (f);
5117
5118 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
5119
5120 window_prompting = x_figure_window_size (f, parms, 0);
5121
5122 {
5123 XSetWindowAttributes attrs;
5124 unsigned long mask;
5125
5126 BLOCK_INPUT;
5127 mask = CWBackPixel | CWOverrideRedirect | CWEventMask;
5128 if (DoesSaveUnders (dpyinfo->screen))
5129 mask |= CWSaveUnder;
5130
5131 /* Window managers look at the override-redirect flag to determine
5132 whether or net to give windows a decoration (Xlib spec, chapter
5133 3.2.8). */
5134 attrs.override_redirect = True;
5135 attrs.save_under = True;
5136 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
5137 /* Arrange for getting MapNotify and UnmapNotify events. */
5138 attrs.event_mask = StructureNotifyMask;
5139 tip_window
5140 = FRAME_X_WINDOW (f)
5141 = XCreateWindow (FRAME_X_DISPLAY (f),
5142 FRAME_X_DISPLAY_INFO (f)->root_window,
5143 /* x, y, width, height */
5144 0, 0, 1, 1,
5145 /* Border. */
5146 1,
5147 CopyFromParent, InputOutput, CopyFromParent,
5148 mask, &attrs);
5149 UNBLOCK_INPUT;
5150 }
5151
5152 x_make_gc (f);
5153
5154 x_default_parameter (f, parms, Qauto_raise, Qnil,
5155 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
5156 x_default_parameter (f, parms, Qauto_lower, Qnil,
5157 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
5158 x_default_parameter (f, parms, Qcursor_type, Qbox,
5159 "cursorType", "CursorType", RES_TYPE_SYMBOL);
5160
5161 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
5162 Change will not be effected unless different from the current
5163 FRAME_LINES (f). */
5164 width = FRAME_COLS (f);
5165 height = FRAME_LINES (f);
5166 SET_FRAME_COLS (f, 0);
5167 FRAME_LINES (f) = 0;
5168 change_frame_size (f, height, width, 1, 0, 0);
5169
5170 /* Add `tooltip' frame parameter's default value. */
5171 if (NILP (Fframe_parameter (frame, intern ("tooltip"))))
5172 Fmodify_frame_parameters (frame, Fcons (Fcons (intern ("tooltip"), Qt),
5173 Qnil));
5174
5175 /* FIXME - can this be done in a similar way to normal frames?
5176 http://lists.gnu.org/archive/html/emacs-devel/2007-10/msg00641.html */
5177
5178 /* Set the `display-type' frame parameter before setting up faces. */
5179 {
5180 Lisp_Object disptype;
5181
5182 if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
5183 disptype = intern ("mono");
5184 else if (FRAME_X_DISPLAY_INFO (f)->visual->class == GrayScale
5185 || FRAME_X_DISPLAY_INFO (f)->visual->class == StaticGray)
5186 disptype = intern ("grayscale");
5187 else
5188 disptype = intern ("color");
5189
5190 if (NILP (Fframe_parameter (frame, Qdisplay_type)))
5191 Fmodify_frame_parameters (frame, Fcons (Fcons (Qdisplay_type, disptype),
5192 Qnil));
5193 }
5194
5195 /* Set up faces after all frame parameters are known. This call
5196 also merges in face attributes specified for new frames.
5197
5198 Frame parameters may be changed if .Xdefaults contains
5199 specifications for the default font. For example, if there is an
5200 `Emacs.default.attributeBackground: pink', the `background-color'
5201 attribute of the frame get's set, which let's the internal border
5202 of the tooltip frame appear in pink. Prevent this. */
5203 {
5204 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
5205
5206 /* Set tip_frame here, so that */
5207 tip_frame = frame;
5208 call1 (Qface_set_after_frame_default, frame);
5209
5210 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
5211 Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
5212 Qnil));
5213 }
5214
5215 Fmodify_frame_parameters (frame, Fcons (Fcons (Qwindow_system, Qx), Qnil));
5216
5217 f->no_split = 1;
5218
5219 UNGCPRO;
5220
5221 /* It is now ok to make the frame official even if we get an error
5222 below. And the frame needs to be on Vframe_list or making it
5223 visible won't work. */
5224 Vframe_list = Fcons (frame, Vframe_list);
5225
5226 /* Now that the frame is official, it counts as a reference to
5227 its display. */
5228 FRAME_X_DISPLAY_INFO (f)->reference_count++;
5229
5230 /* Setting attributes of faces of the tooltip frame from resources
5231 and similar will increment face_change_count, which leads to the
5232 clearing of all current matrices. Since this isn't necessary
5233 here, avoid it by resetting face_change_count to the value it
5234 had before we created the tip frame. */
5235 face_change_count = face_change_count_before;
5236
5237 /* Discard the unwind_protect. */
5238 return unbind_to (count, frame);
5239 }
5240
5241
5242 /* Compute where to display tip frame F. PARMS is the list of frame
5243 parameters for F. DX and DY are specified offsets from the current
5244 location of the mouse. WIDTH and HEIGHT are the width and height
5245 of the tooltip. Return coordinates relative to the root window of
5246 the display in *ROOT_X, and *ROOT_Y. */
5247
5248 static void
5249 compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
5250 struct frame *f;
5251 Lisp_Object parms, dx, dy;
5252 int width, height;
5253 int *root_x, *root_y;
5254 {
5255 Lisp_Object left, top;
5256 int win_x, win_y;
5257 Window root, child;
5258 unsigned pmask;
5259
5260 /* User-specified position? */
5261 left = Fcdr (Fassq (Qleft, parms));
5262 top = Fcdr (Fassq (Qtop, parms));
5263
5264 /* Move the tooltip window where the mouse pointer is. Resize and
5265 show it. */
5266 if (!INTEGERP (left) || !INTEGERP (top))
5267 {
5268 BLOCK_INPUT;
5269 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
5270 &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
5271 UNBLOCK_INPUT;
5272 }
5273
5274 if (INTEGERP (top))
5275 *root_y = XINT (top);
5276 else if (*root_y + XINT (dy) <= 0)
5277 *root_y = 0; /* Can happen for negative dy */
5278 else if (*root_y + XINT (dy) + height <= FRAME_X_DISPLAY_INFO (f)->height)
5279 /* It fits below the pointer */
5280 *root_y += XINT (dy);
5281 else if (height + XINT (dy) <= *root_y)
5282 /* It fits above the pointer. */
5283 *root_y -= height + XINT (dy);
5284 else
5285 /* Put it on the top. */
5286 *root_y = 0;
5287
5288 if (INTEGERP (left))
5289 *root_x = XINT (left);
5290 else if (*root_x + XINT (dx) <= 0)
5291 *root_x = 0; /* Can happen for negative dx */
5292 else if (*root_x + XINT (dx) + width <= FRAME_X_DISPLAY_INFO (f)->width)
5293 /* It fits to the right of the pointer. */
5294 *root_x += XINT (dx);
5295 else if (width + XINT (dx) <= *root_x)
5296 /* It fits to the left of the pointer. */
5297 *root_x -= width + XINT (dx);
5298 else
5299 /* Put it left-justified on the screen--it ought to fit that way. */
5300 *root_x = 0;
5301 }
5302
5303
5304 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
5305 doc: /* Show STRING in a "tooltip" window on frame FRAME.
5306 A tooltip window is a small X window displaying a string.
5307
5308 This is an internal function; Lisp code should call `tooltip-show'.
5309
5310 FRAME nil or omitted means use the selected frame.
5311
5312 PARMS is an optional list of frame parameters which can be used to
5313 change the tooltip's appearance.
5314
5315 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
5316 means use the default timeout of 5 seconds.
5317
5318 If the list of frame parameters PARAMS contains a `left' parameters,
5319 the tooltip is displayed at that x-position. Otherwise it is
5320 displayed at the mouse position, with offset DX added (default is 5 if
5321 DX isn't specified). Likewise for the y-position; if a `top' frame
5322 parameter is specified, it determines the y-position of the tooltip
5323 window, otherwise it is displayed at the mouse position, with offset
5324 DY added (default is -10).
5325
5326 A tooltip's maximum size is specified by `x-max-tooltip-size'.
5327 Text larger than the specified size is clipped. */)
5328 (string, frame, parms, timeout, dx, dy)
5329 Lisp_Object string, frame, parms, timeout, dx, dy;
5330 {
5331 struct frame *f;
5332 struct window *w;
5333 int root_x, root_y;
5334 struct buffer *old_buffer;
5335 struct text_pos pos;
5336 int i, width, height;
5337 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
5338 int old_windows_or_buffers_changed = windows_or_buffers_changed;
5339 int count = SPECPDL_INDEX ();
5340
5341 specbind (Qinhibit_redisplay, Qt);
5342
5343 GCPRO4 (string, parms, frame, timeout);
5344
5345 CHECK_STRING (string);
5346 f = check_x_frame (frame);
5347 if (NILP (timeout))
5348 timeout = make_number (5);
5349 else
5350 CHECK_NATNUM (timeout);
5351
5352 if (NILP (dx))
5353 dx = make_number (5);
5354 else
5355 CHECK_NUMBER (dx);
5356
5357 if (NILP (dy))
5358 dy = make_number (-10);
5359 else
5360 CHECK_NUMBER (dy);
5361
5362 if (NILP (last_show_tip_args))
5363 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
5364
5365 if (!NILP (tip_frame))
5366 {
5367 Lisp_Object last_string = AREF (last_show_tip_args, 0);
5368 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
5369 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
5370
5371 if (EQ (frame, last_frame)
5372 && !NILP (Fequal (last_string, string))
5373 && !NILP (Fequal (last_parms, parms)))
5374 {
5375 struct frame *f = XFRAME (tip_frame);
5376
5377 /* Only DX and DY have changed. */
5378 if (!NILP (tip_timer))
5379 {
5380 Lisp_Object timer = tip_timer;
5381 tip_timer = Qnil;
5382 call1 (Qcancel_timer, timer);
5383 }
5384
5385 BLOCK_INPUT;
5386 compute_tip_xy (f, parms, dx, dy, FRAME_PIXEL_WIDTH (f),
5387 FRAME_PIXEL_HEIGHT (f), &root_x, &root_y);
5388 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5389 root_x, root_y);
5390 UNBLOCK_INPUT;
5391 goto start_timer;
5392 }
5393 }
5394
5395 /* Hide a previous tip, if any. */
5396 Fx_hide_tip ();
5397
5398 ASET (last_show_tip_args, 0, string);
5399 ASET (last_show_tip_args, 1, frame);
5400 ASET (last_show_tip_args, 2, parms);
5401
5402 /* Add default values to frame parameters. */
5403 if (NILP (Fassq (Qname, parms)))
5404 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
5405 if (NILP (Fassq (Qinternal_border_width, parms)))
5406 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
5407 if (NILP (Fassq (Qborder_width, parms)))
5408 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
5409 if (NILP (Fassq (Qborder_color, parms)))
5410 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
5411 if (NILP (Fassq (Qbackground_color, parms)))
5412 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
5413 parms);
5414
5415 /* Create a frame for the tooltip, and record it in the global
5416 variable tip_frame. */
5417 frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms, string);
5418 f = XFRAME (frame);
5419
5420 /* Set up the frame's root window. */
5421 w = XWINDOW (FRAME_ROOT_WINDOW (f));
5422 w->left_col = w->top_line = make_number (0);
5423
5424 if (CONSP (Vx_max_tooltip_size)
5425 && INTEGERP (XCAR (Vx_max_tooltip_size))
5426 && XINT (XCAR (Vx_max_tooltip_size)) > 0
5427 && INTEGERP (XCDR (Vx_max_tooltip_size))
5428 && XINT (XCDR (Vx_max_tooltip_size)) > 0)
5429 {
5430 w->total_cols = XCAR (Vx_max_tooltip_size);
5431 w->total_lines = XCDR (Vx_max_tooltip_size);
5432 }
5433 else
5434 {
5435 w->total_cols = make_number (80);
5436 w->total_lines = make_number (40);
5437 }
5438
5439 FRAME_TOTAL_COLS (f) = XINT (w->total_cols);
5440 adjust_glyphs (f);
5441 w->pseudo_window_p = 1;
5442
5443 /* Display the tooltip text in a temporary buffer. */
5444 old_buffer = current_buffer;
5445 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
5446 current_buffer->truncate_lines = Qnil;
5447 clear_glyph_matrix (w->desired_matrix);
5448 clear_glyph_matrix (w->current_matrix);
5449 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
5450 try_window (FRAME_ROOT_WINDOW (f), pos, 0);
5451
5452 /* Compute width and height of the tooltip. */
5453 width = height = 0;
5454 for (i = 0; i < w->desired_matrix->nrows; ++i)
5455 {
5456 struct glyph_row *row = &w->desired_matrix->rows[i];
5457 struct glyph *last;
5458 int row_width;
5459
5460 /* Stop at the first empty row at the end. */
5461 if (!row->enabled_p || !row->displays_text_p)
5462 break;
5463
5464 /* Let the row go over the full width of the frame. */
5465 row->full_width_p = 1;
5466
5467 /* There's a glyph at the end of rows that is used to place
5468 the cursor there. Don't include the width of this glyph. */
5469 if (row->used[TEXT_AREA])
5470 {
5471 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
5472 row_width = row->pixel_width - last->pixel_width;
5473 }
5474 else
5475 row_width = row->pixel_width;
5476
5477 height += row->height;
5478 width = max (width, row_width);
5479 }
5480
5481 /* Add the frame's internal border to the width and height the X
5482 window should have. */
5483 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
5484 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
5485
5486 /* Move the tooltip window where the mouse pointer is. Resize and
5487 show it. */
5488 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
5489
5490 BLOCK_INPUT;
5491 XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5492 root_x, root_y, width, height);
5493 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5494 UNBLOCK_INPUT;
5495
5496 /* Draw into the window. */
5497 w->must_be_updated_p = 1;
5498 update_single_window (w, 1);
5499
5500 /* Restore original current buffer. */
5501 set_buffer_internal_1 (old_buffer);
5502 windows_or_buffers_changed = old_windows_or_buffers_changed;
5503
5504 start_timer:
5505 /* Let the tip disappear after timeout seconds. */
5506 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
5507 intern ("x-hide-tip"));
5508
5509 UNGCPRO;
5510 return unbind_to (count, Qnil);
5511 }
5512
5513
5514 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
5515 doc: /* Hide the current tooltip window, if there is any.
5516 Value is t if tooltip was open, nil otherwise. */)
5517 ()
5518 {
5519 int count;
5520 Lisp_Object deleted, frame, timer;
5521 struct gcpro gcpro1, gcpro2;
5522
5523 /* Return quickly if nothing to do. */
5524 if (NILP (tip_timer) && NILP (tip_frame))
5525 return Qnil;
5526
5527 frame = tip_frame;
5528 timer = tip_timer;
5529 GCPRO2 (frame, timer);
5530 tip_frame = tip_timer = deleted = Qnil;
5531
5532 count = SPECPDL_INDEX ();
5533 specbind (Qinhibit_redisplay, Qt);
5534 specbind (Qinhibit_quit, Qt);
5535
5536 if (!NILP (timer))
5537 call1 (Qcancel_timer, timer);
5538
5539 if (FRAMEP (frame))
5540 {
5541 Fdelete_frame (frame, Qnil);
5542 deleted = Qt;
5543
5544 #ifdef USE_LUCID
5545 /* Bloodcurdling hack alert: The Lucid menu bar widget's
5546 redisplay procedure is not called when a tip frame over menu
5547 items is unmapped. Redisplay the menu manually... */
5548 {
5549 struct frame *f = SELECTED_FRAME ();
5550 Widget w = f->output_data.x->menubar_widget;
5551 extern void xlwmenu_redisplay P_ ((Widget));
5552
5553 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen)
5554 && w != NULL)
5555 {
5556 BLOCK_INPUT;
5557 xlwmenu_redisplay (w);
5558 UNBLOCK_INPUT;
5559 }
5560 }
5561 #endif /* USE_LUCID */
5562 }
5563
5564 UNGCPRO;
5565 return unbind_to (count, deleted);
5566 }
5567
5568
5569 \f
5570 /***********************************************************************
5571 File selection dialog
5572 ***********************************************************************/
5573
5574 DEFUN ("x-uses-old-gtk-dialog", Fx_uses_old_gtk_dialog,
5575 Sx_uses_old_gtk_dialog,
5576 0, 0, 0,
5577 doc: /* Return t if the old Gtk+ file selection dialog is used. */)
5578 ()
5579 {
5580 #ifdef USE_GTK
5581 extern int use_dialog_box;
5582 extern int use_file_dialog;
5583
5584 if (use_dialog_box
5585 && use_file_dialog
5586 && have_menus_p ()
5587 && xg_uses_old_file_dialog ())
5588 return Qt;
5589 #endif
5590 return Qnil;
5591 }
5592
5593
5594 #ifdef USE_MOTIF
5595 /* Callback for "OK" and "Cancel" on file selection dialog. */
5596
5597 static void
5598 file_dialog_cb (widget, client_data, call_data)
5599 Widget widget;
5600 XtPointer call_data, client_data;
5601 {
5602 int *result = (int *) client_data;
5603 XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
5604 *result = cb->reason;
5605 }
5606
5607
5608 /* Callback for unmapping a file selection dialog. This is used to
5609 capture the case where a dialog is closed via a window manager's
5610 closer button, for example. Using a XmNdestroyCallback didn't work
5611 in this case. */
5612
5613 static void
5614 file_dialog_unmap_cb (widget, client_data, call_data)
5615 Widget widget;
5616 XtPointer call_data, client_data;
5617 {
5618 int *result = (int *) client_data;
5619 *result = XmCR_CANCEL;
5620 }
5621
5622 static Lisp_Object
5623 clean_up_file_dialog (arg)
5624 Lisp_Object arg;
5625 {
5626 struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
5627 Widget dialog = (Widget) p->pointer;
5628
5629 /* Clean up. */
5630 BLOCK_INPUT;
5631 XtUnmanageChild (dialog);
5632 XtDestroyWidget (dialog);
5633 x_menu_set_in_use (0);
5634 UNBLOCK_INPUT;
5635
5636 return Qnil;
5637 }
5638
5639
5640 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
5641 doc: /* Read file name, prompting with PROMPT in directory DIR.
5642 Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
5643 selection box, if specified. If MUSTMATCH is non-nil, the returned file
5644 or directory must exist. ONLY-DIR-P is ignored." */)
5645 (prompt, dir, default_filename, mustmatch, only_dir_p)
5646 Lisp_Object prompt, dir, default_filename, mustmatch, only_dir_p;
5647 {
5648 int result;
5649 struct frame *f = SELECTED_FRAME ();
5650 Lisp_Object file = Qnil;
5651 Lisp_Object decoded_file;
5652 Widget dialog, text, help;
5653 Arg al[10];
5654 int ac = 0;
5655 extern XtAppContext Xt_app_con;
5656 XmString dir_xmstring, pattern_xmstring;
5657 int count = SPECPDL_INDEX ();
5658 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
5659
5660 check_x ();
5661
5662 GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
5663
5664 if (popup_activated ())
5665 error ("Trying to use a menu from within a menu-entry");
5666
5667 CHECK_STRING (prompt);
5668 CHECK_STRING (dir);
5669
5670 /* Prevent redisplay. */
5671 specbind (Qinhibit_redisplay, Qt);
5672
5673 BLOCK_INPUT;
5674
5675 /* Create the dialog with PROMPT as title, using DIR as initial
5676 directory and using "*" as pattern. */
5677 dir = Fexpand_file_name (dir, Qnil);
5678 dir_xmstring = XmStringCreateLocalized (SDATA (dir));
5679 pattern_xmstring = XmStringCreateLocalized ("*");
5680
5681 XtSetArg (al[ac], XmNtitle, SDATA (prompt)); ++ac;
5682 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
5683 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
5684 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
5685 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
5686 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
5687 "fsb", al, ac);
5688 XmStringFree (dir_xmstring);
5689 XmStringFree (pattern_xmstring);
5690
5691 /* Add callbacks for OK and Cancel. */
5692 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
5693 (XtPointer) &result);
5694 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
5695 (XtPointer) &result);
5696 XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
5697 (XtPointer) &result);
5698
5699 /* Remove the help button since we can't display help. */
5700 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
5701 XtUnmanageChild (help);
5702
5703 /* Mark OK button as default. */
5704 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
5705 XmNshowAsDefault, True, NULL);
5706
5707 /* If MUSTMATCH is non-nil, disable the file entry field of the
5708 dialog, so that the user must select a file from the files list
5709 box. We can't remove it because we wouldn't have a way to get at
5710 the result file name, then. */
5711 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
5712 if (!NILP (mustmatch))
5713 {
5714 Widget label;
5715 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
5716 XtSetSensitive (text, False);
5717 XtSetSensitive (label, False);
5718 }
5719
5720 /* Manage the dialog, so that list boxes get filled. */
5721 XtManageChild (dialog);
5722
5723 if (STRINGP (default_filename))
5724 {
5725 XmString default_xmstring;
5726 Widget wtext = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
5727 Widget list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
5728
5729 XmTextPosition last_pos = XmTextFieldGetLastPosition (wtext);
5730 XmTextFieldReplace (wtext, 0, last_pos,
5731 (SDATA (Ffile_name_nondirectory (default_filename))));
5732
5733 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
5734 must include the path for this to work. */
5735
5736 default_xmstring = XmStringCreateLocalized (SDATA (default_filename));
5737
5738 if (XmListItemExists (list, default_xmstring))
5739 {
5740 int item_pos = XmListItemPos (list, default_xmstring);
5741 /* Select the item and scroll it into view. */
5742 XmListSelectPos (list, item_pos, True);
5743 XmListSetPos (list, item_pos);
5744 }
5745
5746 XmStringFree (default_xmstring);
5747 }
5748
5749 record_unwind_protect (clean_up_file_dialog, make_save_value (dialog, 0));
5750
5751 /* Process events until the user presses Cancel or OK. */
5752 x_menu_set_in_use (1);
5753 result = 0;
5754 while (result == 0)
5755 {
5756 XEvent event;
5757 x_menu_wait_for_event (0);
5758 XtAppNextEvent (Xt_app_con, &event);
5759 if (event.type == KeyPress
5760 && FRAME_X_DISPLAY (f) == event.xkey.display)
5761 {
5762 KeySym keysym = XLookupKeysym (&event.xkey, 0);
5763
5764 /* Pop down on C-g. */
5765 if (keysym == XK_g && (event.xkey.state & ControlMask) != 0)
5766 XtUnmanageChild (dialog);
5767 }
5768
5769 (void) x_dispatch_event (&event, FRAME_X_DISPLAY (f));
5770 }
5771
5772 /* Get the result. */
5773 if (result == XmCR_OK)
5774 {
5775 XmString text;
5776 String data;
5777
5778 XtVaGetValues (dialog, XmNtextString, &text, NULL);
5779 XmStringGetLtoR (text, XmFONTLIST_DEFAULT_TAG, &data);
5780 XmStringFree (text);
5781 file = build_string (data);
5782 XtFree (data);
5783 }
5784 else
5785 file = Qnil;
5786
5787 UNBLOCK_INPUT;
5788 UNGCPRO;
5789
5790 /* Make "Cancel" equivalent to C-g. */
5791 if (NILP (file))
5792 Fsignal (Qquit, Qnil);
5793
5794 decoded_file = DECODE_FILE (file);
5795
5796 return unbind_to (count, decoded_file);
5797 }
5798
5799 #endif /* USE_MOTIF */
5800
5801 #ifdef USE_GTK
5802
5803 static Lisp_Object
5804 clean_up_dialog (arg)
5805 Lisp_Object arg;
5806 {
5807 x_menu_set_in_use (0);
5808
5809 return Qnil;
5810 }
5811
5812 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
5813 doc: /* Read file name, prompting with PROMPT in directory DIR.
5814 Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
5815 selection box, if specified. If MUSTMATCH is non-nil, the returned file
5816 or directory must exist. If ONLY-DIR-P is non-nil, the user can only select
5817 directories. */)
5818 (prompt, dir, default_filename, mustmatch, only_dir_p)
5819 Lisp_Object prompt, dir, default_filename, mustmatch, only_dir_p;
5820 {
5821 FRAME_PTR f = SELECTED_FRAME ();
5822 char *fn;
5823 Lisp_Object file = Qnil;
5824 Lisp_Object decoded_file;
5825 int count = SPECPDL_INDEX ();
5826 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
5827 char *cdef_file;
5828
5829 check_x ();
5830
5831 GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
5832
5833 if (popup_activated ())
5834 error ("Trying to use a menu from within a menu-entry");
5835
5836 CHECK_STRING (prompt);
5837 CHECK_STRING (dir);
5838
5839 /* Prevent redisplay. */
5840 specbind (Qinhibit_redisplay, Qt);
5841 record_unwind_protect (clean_up_dialog, Qnil);
5842
5843 BLOCK_INPUT;
5844
5845 if (STRINGP (default_filename))
5846 cdef_file = SDATA (default_filename);
5847 else
5848 cdef_file = SDATA (dir);
5849
5850 fn = xg_get_file_name (f, SDATA (prompt), cdef_file,
5851 ! NILP (mustmatch),
5852 ! NILP (only_dir_p));
5853
5854 if (fn)
5855 {
5856 file = build_string (fn);
5857 xfree (fn);
5858 }
5859
5860 UNBLOCK_INPUT;
5861 UNGCPRO;
5862
5863 /* Make "Cancel" equivalent to C-g. */
5864 if (NILP (file))
5865 Fsignal (Qquit, Qnil);
5866
5867 decoded_file = DECODE_FILE (file);
5868
5869 return unbind_to (count, decoded_file);
5870 }
5871
5872 #endif /* USE_GTK */
5873
5874 \f
5875 /***********************************************************************
5876 Keyboard
5877 ***********************************************************************/
5878
5879 #ifdef HAVE_XKBGETKEYBOARD
5880 #include <X11/XKBlib.h>
5881 #include <X11/keysym.h>
5882 #endif
5883
5884 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
5885 Sx_backspace_delete_keys_p, 0, 1, 0,
5886 doc: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
5887 FRAME nil means use the selected frame.
5888 Value is t if we know that both keys are present, and are mapped to the
5889 usual X keysyms. Value is `lambda' if we cannot determine if both keys are
5890 present and mapped to the usual X keysyms. */)
5891 (frame)
5892 Lisp_Object frame;
5893 {
5894 #ifdef HAVE_XKBGETKEYBOARD
5895 XkbDescPtr kb;
5896 struct frame *f = check_x_frame (frame);
5897 Display *dpy = FRAME_X_DISPLAY (f);
5898 Lisp_Object have_keys;
5899 int major, minor, op, event, error;
5900
5901 BLOCK_INPUT;
5902
5903 /* Check library version in case we're dynamically linked. */
5904 major = XkbMajorVersion;
5905 minor = XkbMinorVersion;
5906 if (!XkbLibraryVersion (&major, &minor))
5907 {
5908 UNBLOCK_INPUT;
5909 return Qlambda;
5910 }
5911
5912 /* Check that the server supports XKB. */
5913 major = XkbMajorVersion;
5914 minor = XkbMinorVersion;
5915 if (!XkbQueryExtension (dpy, &op, &event, &error, &major, &minor))
5916 {
5917 UNBLOCK_INPUT;
5918 return Qlambda;
5919 }
5920
5921 /* In this code we check that the keyboard has physical keys with names
5922 that start with BKSP (Backspace) and DELE (Delete), and that they
5923 generate keysym XK_BackSpace and XK_Delete respectively.
5924 This function is used to test if normal-erase-is-backspace should be
5925 turned on.
5926 An alternative approach would be to just check if XK_BackSpace and
5927 XK_Delete are mapped to any key. But if any of those are mapped to
5928 some non-intuitive key combination (Meta-Shift-Ctrl-whatever) and the
5929 user doesn't know about it, it is better to return false here.
5930 It is more obvious to the user what to do if she/he has two keys
5931 clearly marked with names/symbols and one key does something not
5932 expected (i.e. she/he then tries the other).
5933 The cases where Backspace/Delete is mapped to some other key combination
5934 are rare, and in those cases, normal-erase-is-backspace can be turned on
5935 manually. */
5936
5937 have_keys = Qnil;
5938 kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
5939 if (kb)
5940 {
5941 int delete_keycode = 0, backspace_keycode = 0, i;
5942
5943 if (XkbGetNames (dpy, XkbAllNamesMask, kb) == Success)
5944 {
5945 for (i = kb->min_key_code;
5946 (i < kb->max_key_code
5947 && (delete_keycode == 0 || backspace_keycode == 0));
5948 ++i)
5949 {
5950 /* The XKB symbolic key names can be seen most easily in
5951 the PS file generated by `xkbprint -label name
5952 $DISPLAY'. */
5953 if (bcmp ("DELE", kb->names->keys[i].name, 4) == 0)
5954 delete_keycode = i;
5955 else if (bcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
5956 backspace_keycode = i;
5957 }
5958
5959 XkbFreeNames (kb, 0, True);
5960 }
5961
5962 XkbFreeClientMap (kb, 0, True);
5963
5964 if (delete_keycode
5965 && backspace_keycode
5966 && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
5967 && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
5968 have_keys = Qt;
5969 }
5970 UNBLOCK_INPUT;
5971 return have_keys;
5972 #else /* not HAVE_XKBGETKEYBOARD */
5973 return Qlambda;
5974 #endif /* not HAVE_XKBGETKEYBOARD */
5975 }
5976
5977
5978 \f
5979 /***********************************************************************
5980 Initialization
5981 ***********************************************************************/
5982
5983 /* Keep this list in the same order as frame_parms in frame.c.
5984 Use 0 for unsupported frame parameters. */
5985
5986 frame_parm_handler x_frame_parm_handlers[] =
5987 {
5988 x_set_autoraise,
5989 x_set_autolower,
5990 x_set_background_color,
5991 x_set_border_color,
5992 x_set_border_width,
5993 x_set_cursor_color,
5994 x_set_cursor_type,
5995 x_set_font,
5996 x_set_foreground_color,
5997 x_set_icon_name,
5998 x_set_icon_type,
5999 x_set_internal_border_width,
6000 x_set_menu_bar_lines,
6001 x_set_mouse_color,
6002 x_explicitly_set_name,
6003 x_set_scroll_bar_width,
6004 x_set_title,
6005 x_set_unsplittable,
6006 x_set_vertical_scroll_bars,
6007 x_set_visibility,
6008 x_set_tool_bar_lines,
6009 x_set_scroll_bar_foreground,
6010 x_set_scroll_bar_background,
6011 x_set_screen_gamma,
6012 x_set_line_spacing,
6013 x_set_fringe_width,
6014 x_set_fringe_width,
6015 x_set_wait_for_wm,
6016 x_set_fullscreen,
6017 #ifdef USE_FONT_BACKEND
6018 x_set_font_backend
6019 #endif /* USE_FONT_BACKEND */
6020 };
6021
6022 void
6023 syms_of_xfns ()
6024 {
6025 /* This is zero if not using X windows. */
6026 x_in_use = 0;
6027
6028 /* The section below is built by the lisp expression at the top of the file,
6029 just above where these variables are declared. */
6030 /*&&& init symbols here &&&*/
6031 Qnone = intern ("none");
6032 staticpro (&Qnone);
6033 Qsuppress_icon = intern ("suppress-icon");
6034 staticpro (&Qsuppress_icon);
6035 Qundefined_color = intern ("undefined-color");
6036 staticpro (&Qundefined_color);
6037 Qcompound_text = intern ("compound-text");
6038 staticpro (&Qcompound_text);
6039 Qcancel_timer = intern ("cancel-timer");
6040 staticpro (&Qcancel_timer);
6041 /* This is the end of symbol initialization. */
6042
6043 /* Text property `display' should be nonsticky by default. */
6044 Vtext_property_default_nonsticky
6045 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
6046
6047
6048 Fput (Qundefined_color, Qerror_conditions,
6049 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
6050 Fput (Qundefined_color, Qerror_message,
6051 build_string ("Undefined color"));
6052
6053 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
6054 doc: /* The shape of the pointer when over text.
6055 Changing the value does not affect existing frames
6056 unless you set the mouse color. */);
6057 Vx_pointer_shape = Qnil;
6058
6059 #if 0 /* This doesn't really do anything. */
6060 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
6061 doc: /* The shape of the pointer when not over text.
6062 This variable takes effect when you create a new frame
6063 or when you set the mouse color. */);
6064 #endif
6065 Vx_nontext_pointer_shape = Qnil;
6066
6067 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
6068 doc: /* The shape of the pointer when Emacs is busy.
6069 This variable takes effect when you create a new frame
6070 or when you set the mouse color. */);
6071 Vx_hourglass_pointer_shape = Qnil;
6072
6073 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
6074 doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
6075 display_hourglass_p = 1;
6076
6077 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
6078 doc: /* *Seconds to wait before displaying an hourglass pointer.
6079 Value must be an integer or float. */);
6080 Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
6081
6082 #if 0 /* This doesn't really do anything. */
6083 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
6084 doc: /* The shape of the pointer when over the mode line.
6085 This variable takes effect when you create a new frame
6086 or when you set the mouse color. */);
6087 #endif
6088 Vx_mode_pointer_shape = Qnil;
6089
6090 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
6091 &Vx_sensitive_text_pointer_shape,
6092 doc: /* The shape of the pointer when over mouse-sensitive text.
6093 This variable takes effect when you create a new frame
6094 or when you set the mouse color. */);
6095 Vx_sensitive_text_pointer_shape = Qnil;
6096
6097 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
6098 &Vx_window_horizontal_drag_shape,
6099 doc: /* Pointer shape to use for indicating a window can be dragged horizontally.
6100 This variable takes effect when you create a new frame
6101 or when you set the mouse color. */);
6102 Vx_window_horizontal_drag_shape = Qnil;
6103
6104 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
6105 doc: /* A string indicating the foreground color of the cursor box. */);
6106 Vx_cursor_fore_pixel = Qnil;
6107
6108 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size,
6109 doc: /* Maximum size for tooltips. Value is a pair (COLUMNS . ROWS).
6110 Text larger than this is clipped. */);
6111 Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
6112
6113 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
6114 doc: /* Non-nil if no X window manager is in use.
6115 Emacs doesn't try to figure this out; this is always nil
6116 unless you set it to something else. */);
6117 /* We don't have any way to find this out, so set it to nil
6118 and maybe the user would like to set it to t. */
6119 Vx_no_window_manager = Qnil;
6120
6121 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
6122 &Vx_pixel_size_width_font_regexp,
6123 doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
6124
6125 Since Emacs gets width of a font matching with this regexp from
6126 PIXEL_SIZE field of the name, font finding mechanism gets faster for
6127 such a font. This is especially effective for such large fonts as
6128 Chinese, Japanese, and Korean. */);
6129 Vx_pixel_size_width_font_regexp = Qnil;
6130
6131 /* This is not ifdef:ed, so other builds than GTK can customize it. */
6132 DEFVAR_BOOL ("x-gtk-use-old-file-dialog", &x_gtk_use_old_file_dialog,
6133 doc: /* *Non-nil means prompt with the old GTK file selection dialog.
6134 If nil or if the file selection dialog is not available, the new GTK file
6135 chooser is used instead. To turn off all file dialogs set the
6136 variable `use-file-dialog'. */);
6137 x_gtk_use_old_file_dialog = 0;
6138
6139 DEFVAR_BOOL ("x-gtk-show-hidden-files", &x_gtk_show_hidden_files,
6140 doc: /* *If non-nil, the GTK file chooser will by default show hidden files.
6141 Note that this is just the default, there is a toggle button on the file
6142 chooser to show or not show hidden files on a case by case basis. */);
6143 x_gtk_show_hidden_files = 0;
6144
6145 DEFVAR_BOOL ("x-gtk-file-dialog-help-text", &x_gtk_file_dialog_help_text,
6146 doc: /* *If non-nil, the GTK file chooser will show additional help text.
6147 If more space for files in the file chooser dialog is wanted, set this to nil
6148 to turn the additional text off. */);
6149 x_gtk_file_dialog_help_text = 1;
6150
6151 DEFVAR_BOOL ("x-gtk-whole-detached-tool-bar", &x_gtk_whole_detached_tool_bar,
6152 doc: /* *If non-nil, a detached tool bar is shown in full.
6153 The default is to just show an arrow and pressing on that arrow shows
6154 the tool bar buttons. */);
6155 x_gtk_whole_detached_tool_bar = 0;
6156
6157 Fprovide (intern ("x"), Qnil);
6158
6159 #ifdef USE_X_TOOLKIT
6160 Fprovide (intern ("x-toolkit"), Qnil);
6161 #ifdef USE_MOTIF
6162 Fprovide (intern ("motif"), Qnil);
6163
6164 DEFVAR_LISP ("motif-version-string", &Vmotif_version_string,
6165 doc: /* Version info for LessTif/Motif. */);
6166 Vmotif_version_string = build_string (XmVERSION_STRING);
6167 #endif /* USE_MOTIF */
6168 #endif /* USE_X_TOOLKIT */
6169
6170 #ifdef USE_GTK
6171 /* Provide x-toolkit also for GTK. Internally GTK does not use Xt so it
6172 is not an X toolkit in that sense (USE_X_TOOLKIT is not defined).
6173 But for a user it is a toolkit for X, and indeed, configure
6174 accepts --with-x-toolkit=gtk. */
6175 Fprovide (intern ("x-toolkit"), Qnil);
6176 Fprovide (intern ("gtk"), Qnil);
6177
6178 DEFVAR_LISP ("gtk-version-string", &Vgtk_version_string,
6179 doc: /* Version info for GTK+. */);
6180 {
6181 char gtk_version[40];
6182 g_snprintf (gtk_version, sizeof (gtk_version), "%u.%u.%u",
6183 GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
6184 Vgtk_version_string = build_string (gtk_version);
6185 }
6186 #endif /* USE_GTK */
6187
6188 /* X window properties. */
6189 defsubr (&Sx_change_window_property);
6190 defsubr (&Sx_delete_window_property);
6191 defsubr (&Sx_window_property);
6192
6193 defsubr (&Sxw_display_color_p);
6194 defsubr (&Sx_display_grayscale_p);
6195 defsubr (&Sxw_color_defined_p);
6196 defsubr (&Sxw_color_values);
6197 defsubr (&Sx_server_max_request_size);
6198 defsubr (&Sx_server_vendor);
6199 defsubr (&Sx_server_version);
6200 defsubr (&Sx_display_pixel_width);
6201 defsubr (&Sx_display_pixel_height);
6202 defsubr (&Sx_display_mm_width);
6203 defsubr (&Sx_display_mm_height);
6204 defsubr (&Sx_display_screens);
6205 defsubr (&Sx_display_planes);
6206 defsubr (&Sx_display_color_cells);
6207 defsubr (&Sx_display_visual_class);
6208 defsubr (&Sx_display_backing_store);
6209 defsubr (&Sx_display_save_under);
6210 defsubr (&Sx_create_frame);
6211 defsubr (&Sx_open_connection);
6212 defsubr (&Sx_close_connection);
6213 defsubr (&Sx_display_list);
6214 defsubr (&Sx_synchronize);
6215 defsubr (&Sx_focus_frame);
6216 defsubr (&Sx_backspace_delete_keys_p);
6217
6218 /* Setting callback functions for fontset handler. */
6219 get_font_info_func = x_get_font_info;
6220
6221 #if 0 /* This function pointer doesn't seem to be used anywhere.
6222 And the pointer assigned has the wrong type, anyway. */
6223 list_fonts_func = x_list_fonts;
6224 #endif
6225
6226 load_font_func = x_load_font;
6227 find_ccl_program_func = x_find_ccl_program;
6228 query_font_func = x_query_font;
6229 set_frame_fontset_func = x_set_font;
6230 get_font_repertory_func = x_get_font_repertory;
6231 check_window_system_func = check_x;
6232
6233 hourglass_atimer = NULL;
6234 hourglass_shown_p = 0;
6235
6236 defsubr (&Sx_show_tip);
6237 defsubr (&Sx_hide_tip);
6238 tip_timer = Qnil;
6239 staticpro (&tip_timer);
6240 tip_frame = Qnil;
6241 staticpro (&tip_frame);
6242
6243 last_show_tip_args = Qnil;
6244 staticpro (&last_show_tip_args);
6245
6246 defsubr (&Sx_uses_old_gtk_dialog);
6247 #if defined (USE_MOTIF) || defined (USE_GTK)
6248 defsubr (&Sx_file_dialog);
6249 #endif
6250 }
6251
6252 #endif /* HAVE_X_WINDOWS */
6253
6254 /* arch-tag: 55040d02-5485-4d58-8b22-95a7a05f3288
6255 (do not change this comment) */