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