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