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