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