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