Merged in changes from CVS HEAD
[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 updating_frame = f;
1374 clear_frame ();
1375 clear_current_matrices (f);
1376 updating_frame = NULL;
1377 }
1378
1379 /* If the tool bar gets smaller, the internal border below it
1380 has to be cleared. It was formerly part of the display
1381 of the larger tool bar, and updating windows won't clear it. */
1382 if (delta < 0)
1383 {
1384 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
1385 int width = FRAME_PIXEL_WIDTH (f);
1386 int y = nlines * FRAME_LINE_HEIGHT (f);
1387
1388 BLOCK_INPUT;
1389 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1390 0, y, width, height, False);
1391 UNBLOCK_INPUT;
1392
1393 if (WINDOWP (f->tool_bar_window))
1394 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
1395 }
1396 }
1397
1398
1399 /* Set the foreground color for scroll bars on frame F to VALUE.
1400 VALUE should be a string, a color name. If it isn't a string or
1401 isn't a valid color name, do nothing. OLDVAL is the old value of
1402 the frame parameter. */
1403
1404 void
1405 x_set_scroll_bar_foreground (f, value, oldval)
1406 struct frame *f;
1407 Lisp_Object value, oldval;
1408 {
1409 unsigned long pixel;
1410
1411 if (STRINGP (value))
1412 pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
1413 else
1414 pixel = -1;
1415
1416 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
1417 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
1418
1419 f->output_data.x->scroll_bar_foreground_pixel = pixel;
1420 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
1421 {
1422 /* Remove all scroll bars because they have wrong colors. */
1423 if (FRAME_DISPLAY (f)->condemn_scroll_bars_hook)
1424 (*FRAME_DISPLAY (f)->condemn_scroll_bars_hook) (f);
1425 if (FRAME_DISPLAY (f)->judge_scroll_bars_hook)
1426 (*FRAME_DISPLAY (f)->judge_scroll_bars_hook) (f);
1427
1428 update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
1429 redraw_frame (f);
1430 }
1431 }
1432
1433
1434 /* Set the background color for scroll bars on frame F to VALUE VALUE
1435 should be a string, a color name. If it isn't a string or isn't a
1436 valid color name, do nothing. OLDVAL is the old value of the frame
1437 parameter. */
1438
1439 void
1440 x_set_scroll_bar_background (f, value, oldval)
1441 struct frame *f;
1442 Lisp_Object value, oldval;
1443 {
1444 unsigned long pixel;
1445
1446 if (STRINGP (value))
1447 pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
1448 else
1449 pixel = -1;
1450
1451 if (f->output_data.x->scroll_bar_background_pixel != -1)
1452 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
1453
1454 #ifdef USE_TOOLKIT_SCROLL_BARS
1455 /* Scrollbar shadow colors. */
1456 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
1457 {
1458 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
1459 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
1460 }
1461 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
1462 {
1463 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
1464 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
1465 }
1466 #endif /* USE_TOOLKIT_SCROLL_BARS */
1467
1468 f->output_data.x->scroll_bar_background_pixel = pixel;
1469 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
1470 {
1471 /* Remove all scroll bars because they have wrong colors. */
1472 if (FRAME_DISPLAY (f)->condemn_scroll_bars_hook)
1473 (*FRAME_DISPLAY (f)->condemn_scroll_bars_hook) (f);
1474 if (FRAME_DISPLAY (f)->judge_scroll_bars_hook)
1475 (*FRAME_DISPLAY (f)->judge_scroll_bars_hook) (f);
1476
1477 update_face_from_frame_parameter (f, Qscroll_bar_background, value);
1478 redraw_frame (f);
1479 }
1480 }
1481
1482 \f
1483 /* Encode Lisp string STRING as a text in a format appropriate for
1484 XICCC (X Inter Client Communication Conventions).
1485
1486 If STRING contains only ASCII characters, do no conversion and
1487 return the string data of STRING. Otherwise, encode the text by
1488 CODING_SYSTEM, and return a newly allocated memory area which
1489 should be freed by `xfree' by a caller.
1490
1491 SELECTIONP non-zero means the string is being encoded for an X
1492 selection, so it is safe to run pre-write conversions (which
1493 may run Lisp code).
1494
1495 Store the byte length of resulting text in *TEXT_BYTES.
1496
1497 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
1498 which means that the `encoding' of the result can be `STRING'.
1499 Otherwise store 0 in *STRINGP, which means that the `encoding' of
1500 the result should be `COMPOUND_TEXT'. */
1501
1502 unsigned char *
1503 x_encode_text (string, coding_system, selectionp, text_bytes, stringp)
1504 Lisp_Object string, coding_system;
1505 int *text_bytes, *stringp;
1506 int selectionp;
1507 {
1508 unsigned char *str = SDATA (string);
1509 int chars = SCHARS (string);
1510 int bytes = SBYTES (string);
1511 int charset_info;
1512 int bufsize;
1513 unsigned char *buf;
1514 struct coding_system coding;
1515 extern Lisp_Object Qcompound_text_with_extensions;
1516
1517 charset_info = find_charset_in_text (str, chars, bytes, NULL, Qnil);
1518 if (charset_info == 0)
1519 {
1520 /* No multibyte character in OBJ. We need not encode it. */
1521 *text_bytes = bytes;
1522 *stringp = 1;
1523 return str;
1524 }
1525
1526 setup_coding_system (coding_system, &coding);
1527 if (selectionp
1528 && SYMBOLP (coding.pre_write_conversion)
1529 && !NILP (Ffboundp (coding.pre_write_conversion)))
1530 {
1531 string = run_pre_post_conversion_on_str (string, &coding, 1);
1532 str = SDATA (string);
1533 chars = SCHARS (string);
1534 bytes = SBYTES (string);
1535 }
1536 coding.src_multibyte = 1;
1537 coding.dst_multibyte = 0;
1538 coding.mode |= CODING_MODE_LAST_BLOCK;
1539 if (coding.type == coding_type_iso2022)
1540 coding.flags |= CODING_FLAG_ISO_SAFE;
1541 /* We suppress producing escape sequences for composition. */
1542 coding.composing = COMPOSITION_DISABLED;
1543 bufsize = encoding_buffer_size (&coding, bytes);
1544 buf = (unsigned char *) xmalloc (bufsize);
1545 encode_coding (&coding, str, buf, bytes, bufsize);
1546 *text_bytes = coding.produced;
1547 *stringp = (charset_info == 1
1548 || (!EQ (coding_system, Qcompound_text)
1549 && !EQ (coding_system, Qcompound_text_with_extensions)));
1550 return buf;
1551 }
1552
1553 \f
1554 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
1555 x_id_name.
1556
1557 If EXPLICIT is non-zero, that indicates that lisp code is setting the
1558 name; if NAME is a string, set F's name to NAME and set
1559 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1560
1561 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1562 suggesting a new name, which lisp code should override; if
1563 F->explicit_name is set, ignore the new name; otherwise, set it. */
1564
1565 void
1566 x_set_name (f, name, explicit)
1567 struct frame *f;
1568 Lisp_Object name;
1569 int explicit;
1570 {
1571 /* Make sure that requests from lisp code override requests from
1572 Emacs redisplay code. */
1573 if (explicit)
1574 {
1575 /* If we're switching from explicit to implicit, we had better
1576 update the mode lines and thereby update the title. */
1577 if (f->explicit_name && NILP (name))
1578 update_mode_lines = 1;
1579
1580 f->explicit_name = ! NILP (name);
1581 }
1582 else if (f->explicit_name)
1583 return;
1584
1585 /* If NAME is nil, set the name to the x_id_name. */
1586 if (NILP (name))
1587 {
1588 /* Check for no change needed in this very common case
1589 before we do any consing. */
1590 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
1591 SDATA (f->name)))
1592 return;
1593 name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
1594 }
1595 else
1596 CHECK_STRING (name);
1597
1598 /* Don't change the name if it's already NAME. */
1599 if (! NILP (Fstring_equal (name, f->name)))
1600 return;
1601
1602 f->name = name;
1603
1604 /* For setting the frame title, the title parameter should override
1605 the name parameter. */
1606 if (! NILP (f->title))
1607 name = f->title;
1608
1609 if (FRAME_X_WINDOW (f))
1610 {
1611 BLOCK_INPUT;
1612 #ifdef HAVE_X11R4
1613 {
1614 XTextProperty text, icon;
1615 int bytes, stringp;
1616 Lisp_Object coding_system;
1617
1618 /* Note: Encoding strategy
1619
1620 We encode NAME by compound-text and use "COMPOUND-TEXT" in
1621 text.encoding. But, there are non-internationalized window
1622 managers which don't support that encoding. So, if NAME
1623 contains only ASCII and 8859-1 characters, encode it by
1624 iso-latin-1, and use "STRING" in text.encoding hoping that
1625 such window managers at least analyze this format correctly,
1626 i.e. treat 8-bit bytes as 8859-1 characters.
1627
1628 We may also be able to use "UTF8_STRING" in text.encoding
1629 in the future which can encode all Unicode characters.
1630 But, for the moment, there's no way to know that the
1631 current window manager supports it or not. */
1632 coding_system = Qcompound_text;
1633 text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp);
1634 text.encoding = (stringp ? XA_STRING
1635 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
1636 text.format = 8;
1637 text.nitems = bytes;
1638
1639 if (NILP (f->icon_name))
1640 {
1641 icon = text;
1642 }
1643 else
1644 {
1645 /* See the above comment "Note: Encoding strategy". */
1646 icon.value = x_encode_text (f->icon_name, coding_system, 0,
1647 &bytes, &stringp);
1648 icon.encoding = (stringp ? XA_STRING
1649 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
1650 icon.format = 8;
1651 icon.nitems = bytes;
1652 }
1653 #ifdef USE_GTK
1654 gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
1655 SDATA (name));
1656 #else /* not USE_GTK */
1657 XSetWMName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
1658 #endif /* not USE_GTK */
1659
1660 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &icon);
1661
1662 if (!NILP (f->icon_name)
1663 && icon.value != (unsigned char *) SDATA (f->icon_name))
1664 xfree (icon.value);
1665 if (text.value != (unsigned char *) SDATA (name))
1666 xfree (text.value);
1667 }
1668 #else /* not HAVE_X11R4 */
1669 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1670 SDATA (name));
1671 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1672 SDATA (name));
1673 #endif /* not HAVE_X11R4 */
1674 UNBLOCK_INPUT;
1675 }
1676 }
1677
1678 /* This function should be called when the user's lisp code has
1679 specified a name for the frame; the name will override any set by the
1680 redisplay code. */
1681 void
1682 x_explicitly_set_name (f, arg, oldval)
1683 FRAME_PTR f;
1684 Lisp_Object arg, oldval;
1685 {
1686 x_set_name (f, arg, 1);
1687 }
1688
1689 /* This function should be called by Emacs redisplay code to set the
1690 name; names set this way will never override names set by the user's
1691 lisp code. */
1692 void
1693 x_implicitly_set_name (f, arg, oldval)
1694 FRAME_PTR f;
1695 Lisp_Object arg, oldval;
1696 {
1697 x_set_name (f, arg, 0);
1698 }
1699 \f
1700 /* Change the title of frame F to NAME.
1701 If NAME is nil, use the frame name as the title.
1702
1703 If EXPLICIT is non-zero, that indicates that lisp code is setting the
1704 name; if NAME is a string, set F's name to NAME and set
1705 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1706
1707 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1708 suggesting a new name, which lisp code should override; if
1709 F->explicit_name is set, ignore the new name; otherwise, set it. */
1710
1711 void
1712 x_set_title (f, name, old_name)
1713 struct frame *f;
1714 Lisp_Object name, old_name;
1715 {
1716 /* Don't change the title if it's already NAME. */
1717 if (EQ (name, f->title))
1718 return;
1719
1720 update_mode_lines = 1;
1721
1722 f->title = name;
1723
1724 if (NILP (name))
1725 name = f->name;
1726 else
1727 CHECK_STRING (name);
1728
1729 if (FRAME_X_WINDOW (f))
1730 {
1731 BLOCK_INPUT;
1732 #ifdef HAVE_X11R4
1733 {
1734 XTextProperty text, icon;
1735 int bytes, stringp;
1736 Lisp_Object coding_system;
1737
1738 coding_system = Qcompound_text;
1739 /* See the comment "Note: Encoding strategy" in x_set_name. */
1740 text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp);
1741 text.encoding = (stringp ? XA_STRING
1742 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
1743 text.format = 8;
1744 text.nitems = bytes;
1745
1746 if (NILP (f->icon_name))
1747 {
1748 icon = text;
1749 }
1750 else
1751 {
1752 /* See the comment "Note: Encoding strategy" in x_set_name. */
1753 icon.value = x_encode_text (f->icon_name, coding_system, 0,
1754 &bytes, &stringp);
1755 icon.encoding = (stringp ? XA_STRING
1756 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
1757 icon.format = 8;
1758 icon.nitems = bytes;
1759 }
1760
1761 #ifdef USE_GTK
1762 gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
1763 SDATA (name));
1764 #else /* not USE_GTK */
1765 XSetWMName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
1766 #endif /* not USE_GTK */
1767
1768 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
1769 &icon);
1770
1771 if (!NILP (f->icon_name)
1772 && icon.value != (unsigned char *) SDATA (f->icon_name))
1773 xfree (icon.value);
1774 if (text.value != (unsigned char *) SDATA (name))
1775 xfree (text.value);
1776 }
1777 #else /* not HAVE_X11R4 */
1778 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1779 SDATA (name));
1780 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1781 SDATA (name));
1782 #endif /* not HAVE_X11R4 */
1783 UNBLOCK_INPUT;
1784 }
1785 }
1786
1787 void
1788 x_set_scroll_bar_default_width (f)
1789 struct frame *f;
1790 {
1791 int wid = FRAME_COLUMN_WIDTH (f);
1792
1793 #ifdef USE_TOOLKIT_SCROLL_BARS
1794 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
1795 int width = 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM;
1796 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (width + wid - 1) / wid;
1797 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = width;
1798 #else
1799 /* Make the actual width at least 14 pixels and a multiple of a
1800 character width. */
1801 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
1802
1803 /* Use all of that space (aside from required margins) for the
1804 scroll bar. */
1805 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = 0;
1806 #endif
1807 }
1808
1809 \f
1810 /* Record in frame F the specified or default value according to ALIST
1811 of the parameter named PROP (a Lisp symbol). If no value is
1812 specified for PROP, look for an X default for XPROP on the frame
1813 named NAME. If that is not found either, use the value DEFLT. */
1814
1815 static Lisp_Object
1816 x_default_scroll_bar_color_parameter (f, alist, prop, xprop, xclass,
1817 foreground_p)
1818 struct frame *f;
1819 Lisp_Object alist;
1820 Lisp_Object prop;
1821 char *xprop;
1822 char *xclass;
1823 int foreground_p;
1824 {
1825 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
1826 Lisp_Object tem;
1827
1828 tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING);
1829 if (EQ (tem, Qunbound))
1830 {
1831 #ifdef USE_TOOLKIT_SCROLL_BARS
1832
1833 /* See if an X resource for the scroll bar color has been
1834 specified. */
1835 tem = display_x_get_resource (dpyinfo,
1836 build_string (foreground_p
1837 ? "foreground"
1838 : "background"),
1839 empty_string,
1840 build_string ("verticalScrollBar"),
1841 empty_string);
1842 if (!STRINGP (tem))
1843 {
1844 /* If nothing has been specified, scroll bars will use a
1845 toolkit-dependent default. Because these defaults are
1846 difficult to get at without actually creating a scroll
1847 bar, use nil to indicate that no color has been
1848 specified. */
1849 tem = Qnil;
1850 }
1851
1852 #else /* not USE_TOOLKIT_SCROLL_BARS */
1853
1854 tem = Qnil;
1855
1856 #endif /* not USE_TOOLKIT_SCROLL_BARS */
1857 }
1858
1859 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
1860 return tem;
1861 }
1862
1863
1864
1865 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
1866
1867 Status
1868 XSetWMProtocols (dpy, w, protocols, count)
1869 Display *dpy;
1870 Window w;
1871 Atom *protocols;
1872 int count;
1873 {
1874 Atom prop;
1875 prop = XInternAtom (dpy, "WM_PROTOCOLS", False);
1876 if (prop == None) return False;
1877 XChangeProperty (dpy, w, prop, XA_ATOM, 32, PropModeReplace,
1878 (unsigned char *) protocols, count);
1879 return True;
1880 }
1881 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
1882 \f
1883 #ifdef USE_X_TOOLKIT
1884
1885 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
1886 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
1887 already be present because of the toolkit (Motif adds some of them,
1888 for example, but Xt doesn't). */
1889
1890 static void
1891 hack_wm_protocols (f, widget)
1892 FRAME_PTR f;
1893 Widget widget;
1894 {
1895 Display *dpy = XtDisplay (widget);
1896 Window w = XtWindow (widget);
1897 int need_delete = 1;
1898 int need_focus = 1;
1899 int need_save = 1;
1900
1901 BLOCK_INPUT;
1902 {
1903 Atom type, *atoms = 0;
1904 int format = 0;
1905 unsigned long nitems = 0;
1906 unsigned long bytes_after;
1907
1908 if ((XGetWindowProperty (dpy, w,
1909 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
1910 (long)0, (long)100, False, XA_ATOM,
1911 &type, &format, &nitems, &bytes_after,
1912 (unsigned char **) &atoms)
1913 == Success)
1914 && format == 32 && type == XA_ATOM)
1915 while (nitems > 0)
1916 {
1917 nitems--;
1918 if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
1919 need_delete = 0;
1920 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
1921 need_focus = 0;
1922 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
1923 need_save = 0;
1924 }
1925 if (atoms) XFree ((char *) atoms);
1926 }
1927 {
1928 Atom props [10];
1929 int count = 0;
1930 if (need_delete)
1931 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
1932 if (need_focus)
1933 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus;
1934 if (need_save)
1935 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
1936 if (count)
1937 XChangeProperty (dpy, w, FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
1938 XA_ATOM, 32, PropModeAppend,
1939 (unsigned char *) props, count);
1940 }
1941 UNBLOCK_INPUT;
1942 }
1943 #endif
1944
1945
1946 \f
1947 /* Support routines for XIC (X Input Context). */
1948
1949 #ifdef HAVE_X_I18N
1950
1951 static XFontSet xic_create_xfontset P_ ((struct frame *, char *));
1952 static XIMStyle best_xim_style P_ ((XIMStyles *, XIMStyles *));
1953
1954
1955 /* Supported XIM styles, ordered by preference. */
1956
1957 static XIMStyle supported_xim_styles[] =
1958 {
1959 XIMPreeditPosition | XIMStatusArea,
1960 XIMPreeditPosition | XIMStatusNothing,
1961 XIMPreeditPosition | XIMStatusNone,
1962 XIMPreeditNothing | XIMStatusArea,
1963 XIMPreeditNothing | XIMStatusNothing,
1964 XIMPreeditNothing | XIMStatusNone,
1965 XIMPreeditNone | XIMStatusArea,
1966 XIMPreeditNone | XIMStatusNothing,
1967 XIMPreeditNone | XIMStatusNone,
1968 0,
1969 };
1970
1971
1972 /* Create an X fontset on frame F with base font name
1973 BASE_FONTNAME.. */
1974
1975 static XFontSet
1976 xic_create_xfontset (f, base_fontname)
1977 struct frame *f;
1978 char *base_fontname;
1979 {
1980 XFontSet xfs;
1981 char **missing_list;
1982 int missing_count;
1983 char *def_string;
1984
1985 xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
1986 base_fontname, &missing_list,
1987 &missing_count, &def_string);
1988 if (missing_list)
1989 XFreeStringList (missing_list);
1990
1991 /* No need to free def_string. */
1992 return xfs;
1993 }
1994
1995
1996 /* Value is the best input style, given user preferences USER (already
1997 checked to be supported by Emacs), and styles supported by the
1998 input method XIM. */
1999
2000 static XIMStyle
2001 best_xim_style (user, xim)
2002 XIMStyles *user;
2003 XIMStyles *xim;
2004 {
2005 int i, j;
2006
2007 for (i = 0; i < user->count_styles; ++i)
2008 for (j = 0; j < xim->count_styles; ++j)
2009 if (user->supported_styles[i] == xim->supported_styles[j])
2010 return user->supported_styles[i];
2011
2012 /* Return the default style. */
2013 return XIMPreeditNothing | XIMStatusNothing;
2014 }
2015
2016 /* Create XIC for frame F. */
2017
2018 static XIMStyle xic_style;
2019
2020 void
2021 create_frame_xic (f)
2022 struct frame *f;
2023 {
2024 XIM xim;
2025 XIC xic = NULL;
2026 XFontSet xfs = NULL;
2027
2028 if (FRAME_XIC (f))
2029 return;
2030
2031 xim = FRAME_X_XIM (f);
2032 if (xim)
2033 {
2034 XRectangle s_area;
2035 XPoint spot;
2036 XVaNestedList preedit_attr;
2037 XVaNestedList status_attr;
2038 char *base_fontname;
2039 int fontset;
2040
2041 s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
2042 spot.x = 0; spot.y = 1;
2043 /* Create X fontset. */
2044 fontset = FRAME_FONTSET (f);
2045 if (fontset < 0)
2046 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
2047 else
2048 {
2049 /* Determine the base fontname from the ASCII font name of
2050 FONTSET. */
2051 char *ascii_font = (char *) SDATA (fontset_ascii (fontset));
2052 char *p = ascii_font;
2053 int i;
2054
2055 for (i = 0; *p; p++)
2056 if (*p == '-') i++;
2057 if (i != 14)
2058 /* As the font name doesn't conform to XLFD, we can't
2059 modify it to get a suitable base fontname for the
2060 frame. */
2061 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
2062 else
2063 {
2064 int len = strlen (ascii_font) + 1;
2065 char *p1 = NULL;
2066
2067 for (i = 0, p = ascii_font; i < 8; p++)
2068 {
2069 if (*p == '-')
2070 {
2071 i++;
2072 if (i == 3)
2073 p1 = p + 1;
2074 }
2075 }
2076 base_fontname = (char *) alloca (len);
2077 bzero (base_fontname, len);
2078 strcpy (base_fontname, "-*-*-");
2079 bcopy (p1, base_fontname + 5, p - p1);
2080 strcat (base_fontname, "*-*-*-*-*-*-*");
2081 }
2082 }
2083 xfs = xic_create_xfontset (f, base_fontname);
2084
2085 /* Determine XIC style. */
2086 if (xic_style == 0)
2087 {
2088 XIMStyles supported_list;
2089 supported_list.count_styles = (sizeof supported_xim_styles
2090 / sizeof supported_xim_styles[0]);
2091 supported_list.supported_styles = supported_xim_styles;
2092 xic_style = best_xim_style (&supported_list,
2093 FRAME_X_XIM_STYLES (f));
2094 }
2095
2096 preedit_attr = XVaCreateNestedList (0,
2097 XNFontSet, xfs,
2098 XNForeground,
2099 FRAME_FOREGROUND_PIXEL (f),
2100 XNBackground,
2101 FRAME_BACKGROUND_PIXEL (f),
2102 (xic_style & XIMPreeditPosition
2103 ? XNSpotLocation
2104 : NULL),
2105 &spot,
2106 NULL);
2107 status_attr = XVaCreateNestedList (0,
2108 XNArea,
2109 &s_area,
2110 XNFontSet,
2111 xfs,
2112 XNForeground,
2113 FRAME_FOREGROUND_PIXEL (f),
2114 XNBackground,
2115 FRAME_BACKGROUND_PIXEL (f),
2116 NULL);
2117
2118 xic = XCreateIC (xim,
2119 XNInputStyle, xic_style,
2120 XNClientWindow, FRAME_X_WINDOW (f),
2121 XNFocusWindow, FRAME_X_WINDOW (f),
2122 XNStatusAttributes, status_attr,
2123 XNPreeditAttributes, preedit_attr,
2124 NULL);
2125 XFree (preedit_attr);
2126 XFree (status_attr);
2127 }
2128
2129 FRAME_XIC (f) = xic;
2130 FRAME_XIC_STYLE (f) = xic_style;
2131 FRAME_XIC_FONTSET (f) = xfs;
2132 }
2133
2134
2135 /* Destroy XIC and free XIC fontset of frame F, if any. */
2136
2137 void
2138 free_frame_xic (f)
2139 struct frame *f;
2140 {
2141 if (FRAME_XIC (f) == NULL)
2142 return;
2143
2144 XDestroyIC (FRAME_XIC (f));
2145 if (FRAME_XIC_FONTSET (f))
2146 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
2147
2148 FRAME_XIC (f) = NULL;
2149 FRAME_XIC_FONTSET (f) = NULL;
2150 }
2151
2152
2153 /* Place preedit area for XIC of window W's frame to specified
2154 pixel position X/Y. X and Y are relative to window W. */
2155
2156 void
2157 xic_set_preeditarea (w, x, y)
2158 struct window *w;
2159 int x, y;
2160 {
2161 struct frame *f = XFRAME (w->frame);
2162 XVaNestedList attr;
2163 XPoint spot;
2164
2165 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x) + WINDOW_LEFT_FRINGE_WIDTH (w);
2166 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
2167 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
2168 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
2169 XFree (attr);
2170 }
2171
2172
2173 /* Place status area for XIC in bottom right corner of frame F.. */
2174
2175 void
2176 xic_set_statusarea (f)
2177 struct frame *f;
2178 {
2179 XIC xic = FRAME_XIC (f);
2180 XVaNestedList attr;
2181 XRectangle area;
2182 XRectangle *needed;
2183
2184 /* Negotiate geometry of status area. If input method has existing
2185 status area, use its current size. */
2186 area.x = area.y = area.width = area.height = 0;
2187 attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
2188 XSetICValues (xic, XNStatusAttributes, attr, NULL);
2189 XFree (attr);
2190
2191 attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
2192 XGetICValues (xic, XNStatusAttributes, attr, NULL);
2193 XFree (attr);
2194
2195 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
2196 {
2197 attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
2198 XGetICValues (xic, XNStatusAttributes, attr, NULL);
2199 XFree (attr);
2200 }
2201
2202 area.width = needed->width;
2203 area.height = needed->height;
2204 area.x = FRAME_PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
2205 area.y = (FRAME_PIXEL_HEIGHT (f) - area.height
2206 - FRAME_MENUBAR_HEIGHT (f)
2207 - FRAME_TOOLBAR_HEIGHT (f)
2208 - FRAME_INTERNAL_BORDER_WIDTH (f));
2209 XFree (needed);
2210
2211 attr = XVaCreateNestedList (0, XNArea, &area, NULL);
2212 XSetICValues (xic, XNStatusAttributes, attr, NULL);
2213 XFree (attr);
2214 }
2215
2216
2217 /* Set X fontset for XIC of frame F, using base font name
2218 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
2219
2220 void
2221 xic_set_xfontset (f, base_fontname)
2222 struct frame *f;
2223 char *base_fontname;
2224 {
2225 XVaNestedList attr;
2226 XFontSet xfs;
2227
2228 xfs = xic_create_xfontset (f, base_fontname);
2229
2230 attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
2231 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
2232 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
2233 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
2234 XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
2235 XFree (attr);
2236
2237 if (FRAME_XIC_FONTSET (f))
2238 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
2239 FRAME_XIC_FONTSET (f) = xfs;
2240 }
2241
2242 #endif /* HAVE_X_I18N */
2243
2244
2245 \f
2246 #ifdef USE_X_TOOLKIT
2247
2248 /* Create and set up the X widget for frame F. */
2249
2250 static void
2251 x_window (f, window_prompting, minibuffer_only)
2252 struct frame *f;
2253 long window_prompting;
2254 int minibuffer_only;
2255 {
2256 XClassHint class_hints;
2257 XSetWindowAttributes attributes;
2258 unsigned long attribute_mask;
2259 Widget shell_widget;
2260 Widget pane_widget;
2261 Widget frame_widget;
2262 Arg al [25];
2263 int ac;
2264
2265 BLOCK_INPUT;
2266
2267 /* Use the resource name as the top-level widget name
2268 for looking up resources. Make a non-Lisp copy
2269 for the window manager, so GC relocation won't bother it.
2270
2271 Elsewhere we specify the window name for the window manager. */
2272
2273 {
2274 char *str = (char *) SDATA (Vx_resource_name);
2275 f->namebuf = (char *) xmalloc (strlen (str) + 1);
2276 strcpy (f->namebuf, str);
2277 }
2278
2279 ac = 0;
2280 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
2281 XtSetArg (al[ac], XtNinput, 1); ac++;
2282 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
2283 XtSetArg (al[ac], XtNborderWidth, f->border_width); ac++;
2284 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2285 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
2286 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2287 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
2288 applicationShellWidgetClass,
2289 FRAME_X_DISPLAY (f), al, ac);
2290
2291 f->output_data.x->widget = shell_widget;
2292 /* maybe_set_screen_title_format (shell_widget); */
2293
2294 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
2295 (widget_value *) NULL,
2296 shell_widget, False,
2297 (lw_callback) NULL,
2298 (lw_callback) NULL,
2299 (lw_callback) NULL,
2300 (lw_callback) NULL);
2301
2302 ac = 0;
2303 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2304 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
2305 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2306 XtSetValues (pane_widget, al, ac);
2307 f->output_data.x->column_widget = pane_widget;
2308
2309 /* mappedWhenManaged to false tells to the paned window to not map/unmap
2310 the emacs screen when changing menubar. This reduces flickering. */
2311
2312 ac = 0;
2313 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
2314 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
2315 XtSetArg (al[ac], XtNallowResize, 1); ac++;
2316 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
2317 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
2318 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2319 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
2320 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2321 frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget,
2322 al, ac);
2323
2324 f->output_data.x->edit_widget = frame_widget;
2325
2326 XtManageChild (frame_widget);
2327
2328 /* Do some needed geometry management. */
2329 {
2330 int len;
2331 char *tem, shell_position[32];
2332 Arg al[10];
2333 int ac = 0;
2334 int extra_borders = 0;
2335 int menubar_size
2336 = (f->output_data.x->menubar_widget
2337 ? (f->output_data.x->menubar_widget->core.height
2338 + f->output_data.x->menubar_widget->core.border_width)
2339 : 0);
2340
2341 #if 0 /* Experimentally, we now get the right results
2342 for -geometry -0-0 without this. 24 Aug 96, rms. */
2343 if (FRAME_EXTERNAL_MENU_BAR (f))
2344 {
2345 Dimension ibw = 0;
2346 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
2347 menubar_size += ibw;
2348 }
2349 #endif
2350
2351 f->output_data.x->menubar_height = menubar_size;
2352
2353 #ifndef USE_LUCID
2354 /* Motif seems to need this amount added to the sizes
2355 specified for the shell widget. The Athena/Lucid widgets don't.
2356 Both conclusions reached experimentally. -- rms. */
2357 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
2358 &extra_borders, NULL);
2359 extra_borders *= 2;
2360 #endif
2361
2362 /* Convert our geometry parameters into a geometry string
2363 and specify it.
2364 Note that we do not specify here whether the position
2365 is a user-specified or program-specified one.
2366 We pass that information later, in x_wm_set_size_hints. */
2367 {
2368 int left = f->left_pos;
2369 int xneg = window_prompting & XNegative;
2370 int top = f->top_pos;
2371 int yneg = window_prompting & YNegative;
2372 if (xneg)
2373 left = -left;
2374 if (yneg)
2375 top = -top;
2376
2377 if (window_prompting & USPosition)
2378 sprintf (shell_position, "=%dx%d%c%d%c%d",
2379 FRAME_PIXEL_WIDTH (f) + extra_borders,
2380 FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders,
2381 (xneg ? '-' : '+'), left,
2382 (yneg ? '-' : '+'), top);
2383 else
2384 {
2385 sprintf (shell_position, "=%dx%d",
2386 FRAME_PIXEL_WIDTH (f) + extra_borders,
2387 FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders);
2388
2389 /* Setting x and y when the position is not specified in
2390 the geometry string will set program position in the WM hints.
2391 If Emacs had just one program position, we could set it in
2392 fallback resources, but since each make-frame call can specify
2393 different program positions, this is easier. */
2394 XtSetArg (al[ac], XtNx, left); ac++;
2395 XtSetArg (al[ac], XtNy, top); ac++;
2396 }
2397 }
2398
2399 len = strlen (shell_position) + 1;
2400 /* We don't free this because we don't know whether
2401 it is safe to free it while the frame exists.
2402 It isn't worth the trouble of arranging to free it
2403 when the frame is deleted. */
2404 tem = (char *) xmalloc (len);
2405 strncpy (tem, shell_position, len);
2406 XtSetArg (al[ac], XtNgeometry, tem); ac++;
2407 XtSetValues (shell_widget, al, ac);
2408 }
2409
2410 XtManageChild (pane_widget);
2411 XtRealizeWidget (shell_widget);
2412
2413 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
2414
2415 validate_x_resource_name ();
2416
2417 class_hints.res_name = (char *) SDATA (Vx_resource_name);
2418 class_hints.res_class = (char *) SDATA (Vx_resource_class);
2419 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
2420
2421 #ifdef HAVE_X_I18N
2422 FRAME_XIC (f) = NULL;
2423 if (use_xim)
2424 create_frame_xic (f);
2425 #endif
2426
2427 f->output_data.x->wm_hints.input = True;
2428 f->output_data.x->wm_hints.flags |= InputHint;
2429 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2430 &f->output_data.x->wm_hints);
2431
2432 hack_wm_protocols (f, shell_widget);
2433
2434 #ifdef HACK_EDITRES
2435 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
2436 #endif
2437
2438 /* Do a stupid property change to force the server to generate a
2439 PropertyNotify event so that the event_stream server timestamp will
2440 be initialized to something relevant to the time we created the window.
2441 */
2442 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
2443 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
2444 XA_ATOM, 32, PropModeAppend,
2445 (unsigned char*) NULL, 0);
2446
2447 /* Make all the standard events reach the Emacs frame. */
2448 attributes.event_mask = STANDARD_EVENT_SET;
2449
2450 #ifdef HAVE_X_I18N
2451 if (FRAME_XIC (f))
2452 {
2453 /* XIM server might require some X events. */
2454 unsigned long fevent = NoEventMask;
2455 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
2456 attributes.event_mask |= fevent;
2457 }
2458 #endif /* HAVE_X_I18N */
2459
2460 attribute_mask = CWEventMask;
2461 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
2462 attribute_mask, &attributes);
2463
2464 XtMapWidget (frame_widget);
2465
2466 /* x_set_name normally ignores requests to set the name if the
2467 requested name is the same as the current name. This is the one
2468 place where that assumption isn't correct; f->name is set, but
2469 the X server hasn't been told. */
2470 {
2471 Lisp_Object name;
2472 int explicit = f->explicit_name;
2473
2474 f->explicit_name = 0;
2475 name = f->name;
2476 f->name = Qnil;
2477 x_set_name (f, name, explicit);
2478 }
2479
2480 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2481 f->output_data.x->text_cursor);
2482
2483 UNBLOCK_INPUT;
2484
2485 /* This is a no-op, except under Motif. Make sure main areas are
2486 set to something reasonable, in case we get an error later. */
2487 lw_set_main_areas (pane_widget, 0, frame_widget);
2488 }
2489
2490 #else /* not USE_X_TOOLKIT */
2491 #ifdef USE_GTK
2492 void
2493 x_window (f)
2494 FRAME_PTR f;
2495 {
2496 if (! xg_create_frame_widgets (f))
2497 error ("Unable to create window");
2498
2499 #ifdef HAVE_X_I18N
2500 FRAME_XIC (f) = NULL;
2501 if (use_xim)
2502 {
2503 BLOCK_INPUT;
2504 create_frame_xic (f);
2505 if (FRAME_XIC (f))
2506 {
2507 /* XIM server might require some X events. */
2508 unsigned long fevent = NoEventMask;
2509 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
2510
2511 if (fevent != NoEventMask)
2512 {
2513 XSetWindowAttributes attributes;
2514 XWindowAttributes wattr;
2515 unsigned long attribute_mask;
2516
2517 XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2518 &wattr);
2519 attributes.event_mask = wattr.your_event_mask | fevent;
2520 attribute_mask = CWEventMask;
2521 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2522 attribute_mask, &attributes);
2523 }
2524 }
2525 UNBLOCK_INPUT;
2526 }
2527 #endif
2528 }
2529
2530 #else /*! USE_GTK */
2531 /* Create and set up the X window for frame F. */
2532
2533 void
2534 x_window (f)
2535 struct frame *f;
2536
2537 {
2538 XClassHint class_hints;
2539 XSetWindowAttributes attributes;
2540 unsigned long attribute_mask;
2541
2542 attributes.background_pixel = f->output_data.x->background_pixel;
2543 attributes.border_pixel = f->output_data.x->border_pixel;
2544 attributes.bit_gravity = StaticGravity;
2545 attributes.backing_store = NotUseful;
2546 attributes.save_under = True;
2547 attributes.event_mask = STANDARD_EVENT_SET;
2548 attributes.colormap = FRAME_X_COLORMAP (f);
2549 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
2550 | CWColormap);
2551
2552 BLOCK_INPUT;
2553 FRAME_X_WINDOW (f)
2554 = XCreateWindow (FRAME_X_DISPLAY (f),
2555 f->output_data.x->parent_desc,
2556 f->left_pos,
2557 f->top_pos,
2558 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
2559 f->border_width,
2560 CopyFromParent, /* depth */
2561 InputOutput, /* class */
2562 FRAME_X_VISUAL (f),
2563 attribute_mask, &attributes);
2564
2565 #ifdef HAVE_X_I18N
2566 if (use_xim)
2567 {
2568 create_frame_xic (f);
2569 if (FRAME_XIC (f))
2570 {
2571 /* XIM server might require some X events. */
2572 unsigned long fevent = NoEventMask;
2573 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
2574 attributes.event_mask |= fevent;
2575 attribute_mask = CWEventMask;
2576 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2577 attribute_mask, &attributes);
2578 }
2579 }
2580 #endif /* HAVE_X_I18N */
2581
2582 validate_x_resource_name ();
2583
2584 class_hints.res_name = (char *) SDATA (Vx_resource_name);
2585 class_hints.res_class = (char *) SDATA (Vx_resource_class);
2586 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
2587
2588 /* The menubar is part of the ordinary display;
2589 it does not count in addition to the height of the window. */
2590 f->output_data.x->menubar_height = 0;
2591
2592 /* This indicates that we use the "Passive Input" input model.
2593 Unless we do this, we don't get the Focus{In,Out} events that we
2594 need to draw the cursor correctly. Accursed bureaucrats.
2595 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
2596
2597 f->output_data.x->wm_hints.input = True;
2598 f->output_data.x->wm_hints.flags |= InputHint;
2599 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2600 &f->output_data.x->wm_hints);
2601 f->output_data.x->wm_hints.icon_pixmap = None;
2602
2603 /* Request "save yourself" and "delete window" commands from wm. */
2604 {
2605 Atom protocols[2];
2606 protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
2607 protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
2608 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
2609 }
2610
2611 /* x_set_name normally ignores requests to set the name if the
2612 requested name is the same as the current name. This is the one
2613 place where that assumption isn't correct; f->name is set, but
2614 the X server hasn't been told. */
2615 {
2616 Lisp_Object name;
2617 int explicit = f->explicit_name;
2618
2619 f->explicit_name = 0;
2620 name = f->name;
2621 f->name = Qnil;
2622 x_set_name (f, name, explicit);
2623 }
2624
2625 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2626 f->output_data.x->text_cursor);
2627
2628 UNBLOCK_INPUT;
2629
2630 if (FRAME_X_WINDOW (f) == 0)
2631 error ("Unable to create window");
2632 }
2633
2634 #endif /* not USE_GTK */
2635 #endif /* not USE_X_TOOLKIT */
2636
2637 /* Handle the icon stuff for this window. Perhaps later we might
2638 want an x_set_icon_position which can be called interactively as
2639 well. */
2640
2641 static void
2642 x_icon (f, parms)
2643 struct frame *f;
2644 Lisp_Object parms;
2645 {
2646 Lisp_Object icon_x, icon_y;
2647 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2648
2649 /* Set the position of the icon. Note that twm groups all
2650 icons in an icon window. */
2651 icon_x = x_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
2652 icon_y = x_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
2653 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
2654 {
2655 CHECK_NUMBER (icon_x);
2656 CHECK_NUMBER (icon_y);
2657 }
2658 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
2659 error ("Both left and top icon corners of icon must be specified");
2660
2661 BLOCK_INPUT;
2662
2663 if (! EQ (icon_x, Qunbound))
2664 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
2665
2666 /* Start up iconic or window? */
2667 x_wm_set_window_state
2668 (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
2669 Qicon)
2670 ? IconicState
2671 : NormalState));
2672
2673 x_text_icon (f, (char *) SDATA ((!NILP (f->icon_name)
2674 ? f->icon_name
2675 : f->name)));
2676
2677 UNBLOCK_INPUT;
2678 }
2679
2680 /* Make the GCs needed for this window, setting the
2681 background, border and mouse colors; also create the
2682 mouse cursor and the gray border tile. */
2683
2684 static char cursor_bits[] =
2685 {
2686 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2687 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2688 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2689 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2690 };
2691
2692 static void
2693 x_make_gc (f)
2694 struct frame *f;
2695 {
2696 XGCValues gc_values;
2697
2698 BLOCK_INPUT;
2699
2700 /* Create the GCs of this frame.
2701 Note that many default values are used. */
2702
2703 /* Normal video */
2704 gc_values.font = FRAME_FONT (f)->fid;
2705 gc_values.foreground = f->output_data.x->foreground_pixel;
2706 gc_values.background = f->output_data.x->background_pixel;
2707 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
2708 f->output_data.x->normal_gc
2709 = XCreateGC (FRAME_X_DISPLAY (f),
2710 FRAME_X_WINDOW (f),
2711 GCLineWidth | GCFont | GCForeground | GCBackground,
2712 &gc_values);
2713
2714 /* Reverse video style. */
2715 gc_values.foreground = f->output_data.x->background_pixel;
2716 gc_values.background = f->output_data.x->foreground_pixel;
2717 f->output_data.x->reverse_gc
2718 = XCreateGC (FRAME_X_DISPLAY (f),
2719 FRAME_X_WINDOW (f),
2720 GCFont | GCForeground | GCBackground | GCLineWidth,
2721 &gc_values);
2722
2723 /* Cursor has cursor-color background, background-color foreground. */
2724 gc_values.foreground = f->output_data.x->background_pixel;
2725 gc_values.background = f->output_data.x->cursor_pixel;
2726 gc_values.fill_style = FillOpaqueStippled;
2727 gc_values.stipple
2728 = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
2729 FRAME_X_DISPLAY_INFO (f)->root_window,
2730 cursor_bits, 16, 16);
2731 f->output_data.x->cursor_gc
2732 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2733 (GCFont | GCForeground | GCBackground
2734 | GCFillStyle /* | GCStipple */ | GCLineWidth),
2735 &gc_values);
2736
2737 /* Reliefs. */
2738 f->output_data.x->white_relief.gc = 0;
2739 f->output_data.x->black_relief.gc = 0;
2740
2741 /* Create the gray border tile used when the pointer is not in
2742 the frame. Since this depends on the frame's pixel values,
2743 this must be done on a per-frame basis. */
2744 f->output_data.x->border_tile
2745 = (XCreatePixmapFromBitmapData
2746 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
2747 gray_bits, gray_width, gray_height,
2748 f->output_data.x->foreground_pixel,
2749 f->output_data.x->background_pixel,
2750 DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
2751
2752 UNBLOCK_INPUT;
2753 }
2754
2755
2756 /* Free what was was allocated in x_make_gc. */
2757
2758 void
2759 x_free_gcs (f)
2760 struct frame *f;
2761 {
2762 Display *dpy = FRAME_X_DISPLAY (f);
2763
2764 BLOCK_INPUT;
2765
2766 if (f->output_data.x->normal_gc)
2767 {
2768 XFreeGC (dpy, f->output_data.x->normal_gc);
2769 f->output_data.x->normal_gc = 0;
2770 }
2771
2772 if (f->output_data.x->reverse_gc)
2773 {
2774 XFreeGC (dpy, f->output_data.x->reverse_gc);
2775 f->output_data.x->reverse_gc = 0;
2776 }
2777
2778 if (f->output_data.x->cursor_gc)
2779 {
2780 XFreeGC (dpy, f->output_data.x->cursor_gc);
2781 f->output_data.x->cursor_gc = 0;
2782 }
2783
2784 if (f->output_data.x->border_tile)
2785 {
2786 XFreePixmap (dpy, f->output_data.x->border_tile);
2787 f->output_data.x->border_tile = 0;
2788 }
2789
2790 UNBLOCK_INPUT;
2791 }
2792
2793
2794 /* Handler for signals raised during x_create_frame and
2795 x_create_top_frame. FRAME is the frame which is partially
2796 constructed. */
2797
2798 static Lisp_Object
2799 unwind_create_frame (frame)
2800 Lisp_Object frame;
2801 {
2802 struct frame *f = XFRAME (frame);
2803
2804 /* If frame is ``official'', nothing to do. */
2805 if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
2806 {
2807 #if GLYPH_DEBUG
2808 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2809 #endif
2810
2811 x_free_frame_resources (f);
2812
2813 /* Check that reference counts are indeed correct. */
2814 xassert (dpyinfo->reference_count == dpyinfo_refcount);
2815 xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
2816 return Qt;
2817 }
2818
2819 return Qnil;
2820 }
2821
2822
2823 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
2824 1, 1, 0,
2825 doc: /* Make a new X window, which is called a "frame" in Emacs terms.
2826 Returns an Emacs frame object.
2827 ALIST is an alist of frame parameters.
2828 If the parameters specify that the frame should not have a minibuffer,
2829 and do not specify a specific minibuffer window to use,
2830 then `default-minibuffer-frame' must be a frame whose minibuffer can
2831 be shared by the new frame.
2832
2833 This function is an internal primitive--use `make-frame' instead. */)
2834 (parms)
2835 Lisp_Object parms;
2836 {
2837 struct frame *f;
2838 Lisp_Object frame, tem;
2839 Lisp_Object name;
2840 int minibuffer_only = 0;
2841 long window_prompting = 0;
2842 int width, height;
2843 int count = SPECPDL_INDEX ();
2844 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2845 Lisp_Object display;
2846 struct x_display_info *dpyinfo = NULL;
2847 Lisp_Object parent;
2848 struct kboard *kb;
2849
2850 /* Use this general default value to start with
2851 until we know if this frame has a specified name. */
2852 Vx_resource_name = Vinvocation_name;
2853
2854 display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
2855 if (EQ (display, Qunbound))
2856 display = Qnil;
2857 dpyinfo = check_x_display_info (display);
2858 #ifdef MULTI_KBOARD
2859 kb = dpyinfo->kboard;
2860 #else
2861 kb = &the_only_kboard;
2862 #endif
2863
2864 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
2865 if (!STRINGP (name)
2866 && ! EQ (name, Qunbound)
2867 && ! NILP (name))
2868 error ("Invalid frame name--not a string or nil");
2869
2870 if (STRINGP (name))
2871 Vx_resource_name = name;
2872
2873 /* See if parent window is specified. */
2874 parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
2875 if (EQ (parent, Qunbound))
2876 parent = Qnil;
2877 if (! NILP (parent))
2878 CHECK_NUMBER (parent);
2879
2880 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
2881 /* No need to protect DISPLAY because that's not used after passing
2882 it to make_frame_without_minibuffer. */
2883 frame = Qnil;
2884 GCPRO4 (parms, parent, name, frame);
2885 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
2886 RES_TYPE_SYMBOL);
2887 if (EQ (tem, Qnone) || NILP (tem))
2888 f = make_frame_without_minibuffer (Qnil, kb, display);
2889 else if (EQ (tem, Qonly))
2890 {
2891 f = make_minibuffer_frame ();
2892 minibuffer_only = 1;
2893 }
2894 else if (WINDOWP (tem))
2895 f = make_frame_without_minibuffer (tem, kb, display);
2896 else
2897 f = make_frame (1);
2898
2899 XSETFRAME (frame, f);
2900
2901 /* Note that X Windows does support scroll bars. */
2902 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
2903
2904 f->display = dpyinfo->frame_display;
2905 f->display->reference_count++;
2906
2907 f->output_method = output_x_window;
2908 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
2909 bzero (f->output_data.x, sizeof (struct x_output));
2910 f->output_data.x->icon_bitmap = -1;
2911 FRAME_FONTSET (f) = -1;
2912 f->output_data.x->scroll_bar_foreground_pixel = -1;
2913 f->output_data.x->scroll_bar_background_pixel = -1;
2914 #ifdef USE_TOOLKIT_SCROLL_BARS
2915 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
2916 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
2917 #endif /* USE_TOOLKIT_SCROLL_BARS */
2918 record_unwind_protect (unwind_create_frame, frame);
2919
2920 f->icon_name
2921 = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
2922 RES_TYPE_STRING);
2923 if (! STRINGP (f->icon_name))
2924 f->icon_name = Qnil;
2925
2926 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
2927 #if GLYPH_DEBUG
2928 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
2929 dpyinfo_refcount = dpyinfo->reference_count;
2930 #endif /* GLYPH_DEBUG */
2931 #ifdef MULTI_KBOARD
2932 FRAME_KBOARD (f) = kb;
2933 #endif
2934
2935 /* These colors will be set anyway later, but it's important
2936 to get the color reference counts right, so initialize them! */
2937 {
2938 Lisp_Object black;
2939 struct gcpro gcpro1;
2940
2941 /* Function x_decode_color can signal an error. Make
2942 sure to initialize color slots so that we won't try
2943 to free colors we haven't allocated. */
2944 f->output_data.x->foreground_pixel = -1;
2945 f->output_data.x->background_pixel = -1;
2946 f->output_data.x->cursor_pixel = -1;
2947 f->output_data.x->cursor_foreground_pixel = -1;
2948 f->output_data.x->border_pixel = -1;
2949 f->output_data.x->mouse_pixel = -1;
2950
2951 black = build_string ("black");
2952 GCPRO1 (black);
2953 f->output_data.x->foreground_pixel
2954 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
2955 f->output_data.x->background_pixel
2956 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
2957 f->output_data.x->cursor_pixel
2958 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
2959 f->output_data.x->cursor_foreground_pixel
2960 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
2961 f->output_data.x->border_pixel
2962 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
2963 f->output_data.x->mouse_pixel
2964 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
2965 UNGCPRO;
2966 }
2967
2968 /* Specify the parent under which to make this X window. */
2969
2970 if (!NILP (parent))
2971 {
2972 f->output_data.x->parent_desc = (Window) XFASTINT (parent);
2973 f->output_data.x->explicit_parent = 1;
2974 }
2975 else
2976 {
2977 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
2978 f->output_data.x->explicit_parent = 0;
2979 }
2980
2981 /* Set the name; the functions to which we pass f expect the name to
2982 be set. */
2983 if (EQ (name, Qunbound) || NILP (name))
2984 {
2985 f->name = build_string (dpyinfo->x_id_name);
2986 f->explicit_name = 0;
2987 }
2988 else
2989 {
2990 f->name = name;
2991 f->explicit_name = 1;
2992 /* use the frame's title when getting resources for this frame. */
2993 specbind (Qx_resource_name, name);
2994 }
2995
2996 Fmodify_frame_parameters (frame, Fcons (Fcons (Qwindow_system, Qx), Qnil));
2997
2998 /* Extract the window parameters from the supplied values
2999 that are needed to determine window geometry. */
3000 {
3001 Lisp_Object font;
3002
3003 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
3004
3005 BLOCK_INPUT;
3006 /* First, try whatever font the caller has specified. */
3007 if (STRINGP (font))
3008 {
3009 tem = Fquery_fontset (font, Qnil);
3010 if (STRINGP (tem))
3011 font = x_new_fontset (f, SDATA (tem));
3012 else
3013 font = x_new_font (f, SDATA (font));
3014 }
3015
3016 /* Try out a font which we hope has bold and italic variations. */
3017 if (!STRINGP (font))
3018 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
3019 if (!STRINGP (font))
3020 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3021 if (! STRINGP (font))
3022 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3023 if (! STRINGP (font))
3024 /* This was formerly the first thing tried, but it finds too many fonts
3025 and takes too long. */
3026 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
3027 /* If those didn't work, look for something which will at least work. */
3028 if (! STRINGP (font))
3029 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
3030 UNBLOCK_INPUT;
3031 if (! STRINGP (font))
3032 font = build_string ("fixed");
3033
3034 x_default_parameter (f, parms, Qfont, font,
3035 "font", "Font", RES_TYPE_STRING);
3036 }
3037
3038 #ifdef USE_LUCID
3039 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
3040 whereby it fails to get any font. */
3041 xlwmenu_default_font = FRAME_FONT (f);
3042 #endif
3043
3044 x_default_parameter (f, parms, Qborder_width, make_number (2),
3045 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
3046
3047 /* This defaults to 1 in order to match xterm. We recognize either
3048 internalBorderWidth or internalBorder (which is what xterm calls
3049 it). */
3050 if (NILP (Fassq (Qinternal_border_width, parms)))
3051 {
3052 Lisp_Object value;
3053
3054 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
3055 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
3056 if (! EQ (value, Qunbound))
3057 parms = Fcons (Fcons (Qinternal_border_width, value),
3058 parms);
3059 }
3060 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
3061 "internalBorderWidth", "internalBorderWidth",
3062 RES_TYPE_NUMBER);
3063 x_default_parameter (f, parms, Qvertical_scroll_bars, Qleft,
3064 "verticalScrollBars", "ScrollBars",
3065 RES_TYPE_SYMBOL);
3066
3067 /* Also do the stuff which must be set before the window exists. */
3068 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
3069 "foreground", "Foreground", RES_TYPE_STRING);
3070 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
3071 "background", "Background", RES_TYPE_STRING);
3072 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
3073 "pointerColor", "Foreground", RES_TYPE_STRING);
3074 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
3075 "cursorColor", "Foreground", RES_TYPE_STRING);
3076 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
3077 "borderColor", "BorderColor", RES_TYPE_STRING);
3078 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
3079 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
3080 x_default_parameter (f, parms, Qline_spacing, Qnil,
3081 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
3082 x_default_parameter (f, parms, Qleft_fringe, Qnil,
3083 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
3084 x_default_parameter (f, parms, Qright_fringe, Qnil,
3085 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
3086
3087 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
3088 "scrollBarForeground",
3089 "ScrollBarForeground", 1);
3090 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
3091 "scrollBarBackground",
3092 "ScrollBarBackground", 0);
3093
3094 /* Init faces before x_default_parameter is called for scroll-bar
3095 parameters because that function calls x_set_scroll_bar_width,
3096 which calls change_frame_size, which calls Fset_window_buffer,
3097 which runs hooks, which call Fvertical_motion. At the end, we
3098 end up in init_iterator with a null face cache, which should not
3099 happen. */
3100 init_frame_faces (f);
3101
3102 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
3103 "menuBar", "MenuBar", RES_TYPE_NUMBER);
3104 x_default_parameter (f, parms, Qtool_bar_lines, make_number (1),
3105 "toolBar", "ToolBar", RES_TYPE_NUMBER);
3106 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
3107 "bufferPredicate", "BufferPredicate",
3108 RES_TYPE_SYMBOL);
3109 x_default_parameter (f, parms, Qtitle, Qnil,
3110 "title", "Title", RES_TYPE_STRING);
3111 x_default_parameter (f, parms, Qwait_for_wm, Qt,
3112 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
3113 x_default_parameter (f, parms, Qfullscreen, Qnil,
3114 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
3115
3116 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
3117
3118 /* Compute the size of the X window. */
3119 window_prompting = x_figure_window_size (f, parms, 1);
3120
3121 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
3122 f->no_split = minibuffer_only || EQ (tem, Qt);
3123
3124 /* Create the X widget or window. */
3125 #ifdef USE_X_TOOLKIT
3126 x_window (f, window_prompting, minibuffer_only);
3127 #else
3128 x_window (f);
3129 #endif
3130
3131 x_icon (f, parms);
3132 x_make_gc (f);
3133
3134 /* Now consider the frame official. */
3135 FRAME_X_DISPLAY_INFO (f)->reference_count++;
3136 Vframe_list = Fcons (frame, Vframe_list);
3137
3138 /* We need to do this after creating the X window, so that the
3139 icon-creation functions can say whose icon they're describing. */
3140 x_default_parameter (f, parms, Qicon_type, Qnil,
3141 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
3142
3143 x_default_parameter (f, parms, Qauto_raise, Qnil,
3144 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
3145 x_default_parameter (f, parms, Qauto_lower, Qnil,
3146 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
3147 x_default_parameter (f, parms, Qcursor_type, Qbox,
3148 "cursorType", "CursorType", RES_TYPE_SYMBOL);
3149 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
3150 "scrollBarWidth", "ScrollBarWidth",
3151 RES_TYPE_NUMBER);
3152
3153 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
3154 Change will not be effected unless different from the current
3155 FRAME_LINES (f). */
3156 width = FRAME_COLS (f);
3157 height = FRAME_LINES (f);
3158
3159 SET_FRAME_COLS (f, 0);
3160 FRAME_LINES (f) = 0;
3161 change_frame_size (f, height, width, 1, 0, 0);
3162
3163 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
3164 /* Create the menu bar. */
3165 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
3166 {
3167 /* If this signals an error, we haven't set size hints for the
3168 frame and we didn't make it visible. */
3169 initialize_frame_menubar (f);
3170
3171 #ifndef USE_GTK
3172 /* This is a no-op, except under Motif where it arranges the
3173 main window for the widgets on it. */
3174 lw_set_main_areas (f->output_data.x->column_widget,
3175 f->output_data.x->menubar_widget,
3176 f->output_data.x->edit_widget);
3177 #endif /* not USE_GTK */
3178 }
3179 #endif /* USE_X_TOOLKIT || USE_GTK */
3180
3181 /* Tell the server what size and position, etc, we want, and how
3182 badly we want them. This should be done after we have the menu
3183 bar so that its size can be taken into account. */
3184 BLOCK_INPUT;
3185 x_wm_set_size_hint (f, window_prompting, 0);
3186 UNBLOCK_INPUT;
3187
3188 /* Make the window appear on the frame and enable display, unless
3189 the caller says not to. However, with explicit parent, Emacs
3190 cannot control visibility, so don't try. */
3191 if (! f->output_data.x->explicit_parent)
3192 {
3193 Lisp_Object visibility;
3194
3195 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
3196 RES_TYPE_SYMBOL);
3197 if (EQ (visibility, Qunbound))
3198 visibility = Qt;
3199
3200 if (EQ (visibility, Qicon))
3201 x_iconify_frame (f);
3202 else if (! NILP (visibility))
3203 x_make_frame_visible (f);
3204 else
3205 /* Must have been Qnil. */
3206 ;
3207 }
3208
3209 /* Set the WM leader property. GTK does this itself, so this is not
3210 needed when using GTK. */
3211 if (dpyinfo->client_leader_window != 0)
3212 {
3213 BLOCK_INPUT;
3214 XChangeProperty (FRAME_X_DISPLAY (f),
3215 FRAME_OUTER_WINDOW (f),
3216 dpyinfo->Xatom_wm_client_leader,
3217 XA_WINDOW, 32, PropModeReplace,
3218 (char *) &dpyinfo->client_leader_window, 1);
3219 UNBLOCK_INPUT;
3220 }
3221
3222 UNGCPRO;
3223
3224 /* Make sure windows on this frame appear in calls to next-window
3225 and similar functions. */
3226 Vwindow_list = Qnil;
3227
3228 return unbind_to (count, frame);
3229 }
3230
3231
3232 /* FRAME is used only to get a handle on the X display. We don't pass the
3233 display info directly because we're called from frame.c, which doesn't
3234 know about that structure. */
3235
3236 Lisp_Object
3237 x_get_focus_frame (frame)
3238 struct frame *frame;
3239 {
3240 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
3241 Lisp_Object xfocus;
3242 if (! dpyinfo->x_focus_frame)
3243 return Qnil;
3244
3245 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
3246 return xfocus;
3247 }
3248
3249
3250 /* In certain situations, when the window manager follows a
3251 click-to-focus policy, there seems to be no way around calling
3252 XSetInputFocus to give another frame the input focus .
3253
3254 In an ideal world, XSetInputFocus should generally be avoided so
3255 that applications don't interfere with the window manager's focus
3256 policy. But I think it's okay to use when it's clearly done
3257 following a user-command. */
3258
3259 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
3260 doc: /* Set the input focus to FRAME.
3261 FRAME nil means use the selected frame. */)
3262 (frame)
3263 Lisp_Object frame;
3264 {
3265 struct frame *f = check_x_frame (frame);
3266 Display *dpy = FRAME_X_DISPLAY (f);
3267 int count;
3268
3269 BLOCK_INPUT;
3270 count = x_catch_errors (dpy);
3271 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3272 RevertToParent, CurrentTime);
3273 x_uncatch_errors (dpy, count);
3274 UNBLOCK_INPUT;
3275
3276 return Qnil;
3277 }
3278
3279 \f
3280 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
3281 doc: /* Internal function called by `color-defined-p', which see. */)
3282 (color, frame)
3283 Lisp_Object color, frame;
3284 {
3285 XColor foo;
3286 FRAME_PTR f = check_x_frame (frame);
3287
3288 CHECK_STRING (color);
3289
3290 if (x_defined_color (f, SDATA (color), &foo, 0))
3291 return Qt;
3292 else
3293 return Qnil;
3294 }
3295
3296 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
3297 doc: /* Internal function called by `color-values', which see. */)
3298 (color, frame)
3299 Lisp_Object color, frame;
3300 {
3301 XColor foo;
3302 FRAME_PTR f = check_x_frame (frame);
3303
3304 CHECK_STRING (color);
3305
3306 if (x_defined_color (f, SDATA (color), &foo, 0))
3307 {
3308 Lisp_Object rgb[3];
3309
3310 rgb[0] = make_number (foo.red);
3311 rgb[1] = make_number (foo.green);
3312 rgb[2] = make_number (foo.blue);
3313 return Flist (3, rgb);
3314 }
3315 else
3316 return Qnil;
3317 }
3318
3319 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
3320 doc: /* Internal function called by `display-color-p', which see. */)
3321 (display)
3322 Lisp_Object display;
3323 {
3324 struct x_display_info *dpyinfo = check_x_display_info (display);
3325
3326 if (dpyinfo->n_planes <= 2)
3327 return Qnil;
3328
3329 switch (dpyinfo->visual->class)
3330 {
3331 case StaticColor:
3332 case PseudoColor:
3333 case TrueColor:
3334 case DirectColor:
3335 return Qt;
3336
3337 default:
3338 return Qnil;
3339 }
3340 }
3341
3342 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
3343 0, 1, 0,
3344 doc: /* Return t if the X display supports shades of gray.
3345 Note that color displays do support shades of gray.
3346 The optional argument DISPLAY specifies which display to ask about.
3347 DISPLAY should be either a frame or a display name (a string).
3348 If omitted or nil, that stands for the selected frame's display. */)
3349 (display)
3350 Lisp_Object display;
3351 {
3352 struct x_display_info *dpyinfo = check_x_display_info (display);
3353
3354 if (dpyinfo->n_planes <= 1)
3355 return Qnil;
3356
3357 switch (dpyinfo->visual->class)
3358 {
3359 case StaticColor:
3360 case PseudoColor:
3361 case TrueColor:
3362 case DirectColor:
3363 case StaticGray:
3364 case GrayScale:
3365 return Qt;
3366
3367 default:
3368 return Qnil;
3369 }
3370 }
3371
3372 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
3373 0, 1, 0,
3374 doc: /* Returns the width in pixels of the X display DISPLAY.
3375 The optional argument DISPLAY specifies which display to ask about.
3376 DISPLAY should be either a frame or a display name (a string).
3377 If omitted or nil, that stands for the selected frame's display. */)
3378 (display)
3379 Lisp_Object display;
3380 {
3381 struct x_display_info *dpyinfo = check_x_display_info (display);
3382
3383 return make_number (dpyinfo->width);
3384 }
3385
3386 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
3387 Sx_display_pixel_height, 0, 1, 0,
3388 doc: /* Returns the height in pixels of the X display DISPLAY.
3389 The optional argument DISPLAY specifies which display to ask about.
3390 DISPLAY should be either a frame or a display name (a string).
3391 If omitted or nil, that stands for the selected frame's display. */)
3392 (display)
3393 Lisp_Object display;
3394 {
3395 struct x_display_info *dpyinfo = check_x_display_info (display);
3396
3397 return make_number (dpyinfo->height);
3398 }
3399
3400 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
3401 0, 1, 0,
3402 doc: /* Returns the number of bitplanes of the X display DISPLAY.
3403 The optional argument DISPLAY specifies which display to ask about.
3404 DISPLAY should be either a frame or a display name (a string).
3405 If omitted or nil, that stands for the selected frame's display. */)
3406 (display)
3407 Lisp_Object display;
3408 {
3409 struct x_display_info *dpyinfo = check_x_display_info (display);
3410
3411 return make_number (dpyinfo->n_planes);
3412 }
3413
3414 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
3415 0, 1, 0,
3416 doc: /* Returns the number of color cells of the X display DISPLAY.
3417 The optional argument DISPLAY specifies which display to ask about.
3418 DISPLAY should be either a frame or a display name (a string).
3419 If omitted or nil, that stands for the selected frame's display. */)
3420 (display)
3421 Lisp_Object display;
3422 {
3423 struct x_display_info *dpyinfo = check_x_display_info (display);
3424
3425 int nr_planes = DisplayPlanes (dpyinfo->display,
3426 XScreenNumberOfScreen (dpyinfo->screen));
3427
3428 /* Truncate nr_planes to 24 to avoid integer overflow.
3429 Some displays says 32, but only 24 bits are actually significant.
3430 There are only very few and rare video cards that have more than
3431 24 significant bits. Also 24 bits is more than 16 million colors,
3432 it "should be enough for everyone". */
3433 if (nr_planes > 24) nr_planes = 24;
3434
3435 return make_number (1 << nr_planes);
3436 }
3437
3438 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
3439 Sx_server_max_request_size,
3440 0, 1, 0,
3441 doc: /* Returns the maximum request size of the X server of display DISPLAY.
3442 The optional argument DISPLAY specifies which display to ask about.
3443 DISPLAY should be either a frame or a display name (a string).
3444 If omitted or nil, that stands for the selected frame's display. */)
3445 (display)
3446 Lisp_Object display;
3447 {
3448 struct x_display_info *dpyinfo = check_x_display_info (display);
3449
3450 return make_number (MAXREQUEST (dpyinfo->display));
3451 }
3452
3453 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
3454 doc: /* Returns the vendor ID string of the X server of display DISPLAY.
3455 The optional argument DISPLAY specifies which display to ask about.
3456 DISPLAY should be either a frame or a display name (a string).
3457 If omitted or nil, that stands for the selected frame's display. */)
3458 (display)
3459 Lisp_Object display;
3460 {
3461 struct x_display_info *dpyinfo = check_x_display_info (display);
3462 char *vendor = ServerVendor (dpyinfo->display);
3463
3464 if (! vendor) vendor = "";
3465 return build_string (vendor);
3466 }
3467
3468 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
3469 doc: /* Returns the version numbers of the X server of display DISPLAY.
3470 The value is a list of three integers: the major and minor
3471 version numbers of the X Protocol in use, and the vendor-specific release
3472 number. See also the function `x-server-vendor'.
3473
3474 The optional argument DISPLAY specifies which display to ask about.
3475 DISPLAY should be either a frame or a display name (a string).
3476 If omitted or nil, that stands for the selected frame's display. */)
3477 (display)
3478 Lisp_Object display;
3479 {
3480 struct x_display_info *dpyinfo = check_x_display_info (display);
3481 Display *dpy = dpyinfo->display;
3482
3483 return Fcons (make_number (ProtocolVersion (dpy)),
3484 Fcons (make_number (ProtocolRevision (dpy)),
3485 Fcons (make_number (VendorRelease (dpy)), Qnil)));
3486 }
3487
3488 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
3489 doc: /* Return the number of screens on the X server of display DISPLAY.
3490 The optional argument DISPLAY specifies which display to ask about.
3491 DISPLAY should be either a frame or a display name (a string).
3492 If omitted or nil, that stands for the selected frame's display. */)
3493 (display)
3494 Lisp_Object display;
3495 {
3496 struct x_display_info *dpyinfo = check_x_display_info (display);
3497
3498 return make_number (ScreenCount (dpyinfo->display));
3499 }
3500
3501 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
3502 doc: /* Return the height in millimeters of the X display DISPLAY.
3503 The optional argument DISPLAY specifies which display to ask about.
3504 DISPLAY should be either a frame or a display name (a string).
3505 If omitted or nil, that stands for the selected frame's display. */)
3506 (display)
3507 Lisp_Object display;
3508 {
3509 struct x_display_info *dpyinfo = check_x_display_info (display);
3510
3511 return make_number (HeightMMOfScreen (dpyinfo->screen));
3512 }
3513
3514 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
3515 doc: /* Return the width in millimeters of the X display DISPLAY.
3516 The optional argument DISPLAY specifies which display to ask about.
3517 DISPLAY should be either a frame or a display name (a string).
3518 If omitted or nil, that stands for the selected frame's display. */)
3519 (display)
3520 Lisp_Object display;
3521 {
3522 struct x_display_info *dpyinfo = check_x_display_info (display);
3523
3524 return make_number (WidthMMOfScreen (dpyinfo->screen));
3525 }
3526
3527 DEFUN ("x-display-backing-store", Fx_display_backing_store,
3528 Sx_display_backing_store, 0, 1, 0,
3529 doc: /* Returns an indication of whether X display DISPLAY does backing store.
3530 The value may be `always', `when-mapped', or `not-useful'.
3531 The optional argument DISPLAY specifies which display to ask about.
3532 DISPLAY should be either a frame or a display name (a string).
3533 If omitted or nil, that stands for the selected frame's display. */)
3534 (display)
3535 Lisp_Object display;
3536 {
3537 struct x_display_info *dpyinfo = check_x_display_info (display);
3538 Lisp_Object result;
3539
3540 switch (DoesBackingStore (dpyinfo->screen))
3541 {
3542 case Always:
3543 result = intern ("always");
3544 break;
3545
3546 case WhenMapped:
3547 result = intern ("when-mapped");
3548 break;
3549
3550 case NotUseful:
3551 result = intern ("not-useful");
3552 break;
3553
3554 default:
3555 error ("Strange value for BackingStore parameter of screen");
3556 result = Qnil;
3557 }
3558
3559 return result;
3560 }
3561
3562 DEFUN ("x-display-visual-class", Fx_display_visual_class,
3563 Sx_display_visual_class, 0, 1, 0,
3564 doc: /* Return the visual class of the X display DISPLAY.
3565 The value is one of the symbols `static-gray', `gray-scale',
3566 `static-color', `pseudo-color', `true-color', or `direct-color'.
3567
3568 The optional argument DISPLAY specifies which display to ask about.
3569 DISPLAY should be either a frame or a display name (a string).
3570 If omitted or nil, that stands for the selected frame's display. */)
3571 (display)
3572 Lisp_Object display;
3573 {
3574 struct x_display_info *dpyinfo = check_x_display_info (display);
3575 Lisp_Object result;
3576
3577 switch (dpyinfo->visual->class)
3578 {
3579 case StaticGray:
3580 result = intern ("static-gray");
3581 break;
3582 case GrayScale:
3583 result = intern ("gray-scale");
3584 break;
3585 case StaticColor:
3586 result = intern ("static-color");
3587 break;
3588 case PseudoColor:
3589 result = intern ("pseudo-color");
3590 break;
3591 case TrueColor:
3592 result = intern ("true-color");
3593 break;
3594 case DirectColor:
3595 result = intern ("direct-color");
3596 break;
3597 default:
3598 error ("Display has an unknown visual class");
3599 result = Qnil;
3600 }
3601
3602 return result;
3603 }
3604
3605 DEFUN ("x-display-save-under", Fx_display_save_under,
3606 Sx_display_save_under, 0, 1, 0,
3607 doc: /* Returns t if the X display DISPLAY supports the save-under feature.
3608 The optional argument DISPLAY specifies which display to ask about.
3609 DISPLAY should be either a frame or a display name (a string).
3610 If omitted or nil, that stands for the selected frame's display. */)
3611 (display)
3612 Lisp_Object display;
3613 {
3614 struct x_display_info *dpyinfo = check_x_display_info (display);
3615
3616 if (DoesSaveUnders (dpyinfo->screen) == True)
3617 return Qt;
3618 else
3619 return Qnil;
3620 }
3621 \f
3622 int
3623 x_pixel_width (f)
3624 register struct frame *f;
3625 {
3626 return FRAME_PIXEL_WIDTH (f);
3627 }
3628
3629 int
3630 x_pixel_height (f)
3631 register struct frame *f;
3632 {
3633 return FRAME_PIXEL_HEIGHT (f);
3634 }
3635
3636 int
3637 x_char_width (f)
3638 register struct frame *f;
3639 {
3640 return FRAME_COLUMN_WIDTH (f);
3641 }
3642
3643 int
3644 x_char_height (f)
3645 register struct frame *f;
3646 {
3647 return FRAME_LINE_HEIGHT (f);
3648 }
3649
3650 int
3651 x_screen_planes (f)
3652 register struct frame *f;
3653 {
3654 return FRAME_X_DISPLAY_INFO (f)->n_planes;
3655 }
3656
3657
3658 \f
3659 /************************************************************************
3660 X Displays
3661 ************************************************************************/
3662
3663 \f
3664 /* Mapping visual names to visuals. */
3665
3666 static struct visual_class
3667 {
3668 char *name;
3669 int class;
3670 }
3671 visual_classes[] =
3672 {
3673 {"StaticGray", StaticGray},
3674 {"GrayScale", GrayScale},
3675 {"StaticColor", StaticColor},
3676 {"PseudoColor", PseudoColor},
3677 {"TrueColor", TrueColor},
3678 {"DirectColor", DirectColor},
3679 {NULL, 0}
3680 };
3681
3682
3683 #ifndef HAVE_XSCREENNUMBEROFSCREEN
3684
3685 /* Value is the screen number of screen SCR. This is a substitute for
3686 the X function with the same name when that doesn't exist. */
3687
3688 int
3689 XScreenNumberOfScreen (scr)
3690 register Screen *scr;
3691 {
3692 Display *dpy = scr->display;
3693 int i;
3694
3695 for (i = 0; i < dpy->nscreens; ++i)
3696 if (scr == dpy->screens + i)
3697 break;
3698
3699 return i;
3700 }
3701
3702 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
3703
3704
3705 /* Select the visual that should be used on display DPYINFO. Set
3706 members of DPYINFO appropriately. Called from x_term_init. */
3707
3708 void
3709 select_visual (dpyinfo)
3710 struct x_display_info *dpyinfo;
3711 {
3712 Display *dpy = dpyinfo->display;
3713 Screen *screen = dpyinfo->screen;
3714 Lisp_Object value;
3715
3716 /* See if a visual is specified. */
3717 value = display_x_get_resource (dpyinfo,
3718 build_string ("visualClass"),
3719 build_string ("VisualClass"),
3720 Qnil, Qnil);
3721 if (STRINGP (value))
3722 {
3723 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
3724 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
3725 depth, a decimal number. NAME is compared with case ignored. */
3726 char *s = (char *) alloca (SBYTES (value) + 1);
3727 char *dash;
3728 int i, class = -1;
3729 XVisualInfo vinfo;
3730
3731 strcpy (s, SDATA (value));
3732 dash = index (s, '-');
3733 if (dash)
3734 {
3735 dpyinfo->n_planes = atoi (dash + 1);
3736 *dash = '\0';
3737 }
3738 else
3739 /* We won't find a matching visual with depth 0, so that
3740 an error will be printed below. */
3741 dpyinfo->n_planes = 0;
3742
3743 /* Determine the visual class. */
3744 for (i = 0; visual_classes[i].name; ++i)
3745 if (xstricmp (s, visual_classes[i].name) == 0)
3746 {
3747 class = visual_classes[i].class;
3748 break;
3749 }
3750
3751 /* Look up a matching visual for the specified class. */
3752 if (class == -1
3753 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
3754 dpyinfo->n_planes, class, &vinfo))
3755 fatal ("Invalid visual specification `%s'", SDATA (value));
3756
3757 dpyinfo->visual = vinfo.visual;
3758 }
3759 else
3760 {
3761 int n_visuals;
3762 XVisualInfo *vinfo, vinfo_template;
3763
3764 dpyinfo->visual = DefaultVisualOfScreen (screen);
3765
3766 #ifdef HAVE_X11R4
3767 vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
3768 #else
3769 vinfo_template.visualid = dpyinfo->visual->visualid;
3770 #endif
3771 vinfo_template.screen = XScreenNumberOfScreen (screen);
3772 vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
3773 &vinfo_template, &n_visuals);
3774 if (n_visuals != 1)
3775 fatal ("Can't get proper X visual info");
3776
3777 dpyinfo->n_planes = vinfo->depth;
3778 XFree ((char *) vinfo);
3779 }
3780 }
3781
3782
3783 /* Return the X display structure for the display named NAME.
3784 Open a new connection if necessary. */
3785
3786 struct x_display_info *
3787 x_display_info_for_name (name)
3788 Lisp_Object name;
3789 {
3790 Lisp_Object names;
3791 struct x_display_info *dpyinfo;
3792
3793 CHECK_STRING (name);
3794
3795 #if 0
3796 if (! EQ (Vinitial_window_system, intern ("x")))
3797 error ("Not using X Windows"); /* That doesn't stop us anymore. */
3798 #endif
3799
3800 for (dpyinfo = x_display_list, names = x_display_name_list;
3801 dpyinfo;
3802 dpyinfo = dpyinfo->next, names = XCDR (names))
3803 {
3804 Lisp_Object tem;
3805 tem = Fstring_equal (XCAR (XCAR (names)), name);
3806 if (!NILP (tem))
3807 return dpyinfo;
3808 }
3809
3810 /* Use this general default value to start with. */
3811 Vx_resource_name = Vinvocation_name;
3812
3813 validate_x_resource_name ();
3814
3815 dpyinfo = x_term_init (name, (char *)0,
3816 (char *) SDATA (Vx_resource_name));
3817
3818 if (dpyinfo == 0)
3819 error ("Cannot connect to X server %s", SDATA (name));
3820
3821 x_in_use = 1;
3822 XSETFASTINT (Vwindow_system_version, 11);
3823
3824 return dpyinfo;
3825 }
3826
3827
3828 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
3829 1, 3, 0,
3830 doc: /* Open a connection to an X server.
3831 DISPLAY is the name of the display to connect to.
3832 Optional second arg XRM-STRING is a string of resources in xrdb format.
3833 If the optional third arg MUST-SUCCEED is non-nil,
3834 terminate Emacs if we can't open the connection. */)
3835 (display, xrm_string, must_succeed)
3836 Lisp_Object display, xrm_string, must_succeed;
3837 {
3838 unsigned char *xrm_option;
3839 struct x_display_info *dpyinfo;
3840
3841 CHECK_STRING (display);
3842 if (! NILP (xrm_string))
3843 CHECK_STRING (xrm_string);
3844
3845 #if 0
3846 if (! EQ (Vinitial_window_system, intern ("x")))
3847 error ("Not using X Windows"); /* That doesn't stop us anymore. */
3848 #endif
3849
3850 if (! NILP (xrm_string))
3851 xrm_option = (unsigned char *) SDATA (xrm_string);
3852 else
3853 xrm_option = (unsigned char *) 0;
3854
3855 validate_x_resource_name ();
3856
3857 /* This is what opens the connection and sets x_current_display.
3858 This also initializes many symbols, such as those used for input. */
3859 dpyinfo = x_term_init (display, xrm_option,
3860 (char *) SDATA (Vx_resource_name));
3861
3862 if (dpyinfo == 0)
3863 {
3864 if (!NILP (must_succeed))
3865 fatal ("Cannot connect to X server %s.\n\
3866 Check the DISPLAY environment variable or use `-d'.\n\
3867 Also use the `xauth' program to verify that you have the proper\n\
3868 authorization information needed to connect the X server.\n\
3869 An insecure way to solve the problem may be to use `xhost'.\n",
3870 SDATA (display));
3871 else
3872 error ("Cannot connect to X server %s", SDATA (display));
3873 }
3874
3875 x_in_use = 1;
3876
3877 XSETFASTINT (Vwindow_system_version, 11);
3878 return Qnil;
3879 }
3880
3881 DEFUN ("x-close-connection", Fx_close_connection,
3882 Sx_close_connection, 1, 1, 0,
3883 doc: /* Close the connection to DISPLAY's X server.
3884 For DISPLAY, specify either a frame or a display name (a string).
3885 If DISPLAY is nil, that stands for the selected frame's display. */)
3886 (display)
3887 Lisp_Object display;
3888 {
3889 struct x_display_info *dpyinfo = check_x_display_info (display);
3890 int i;
3891
3892 if (dpyinfo->reference_count > 0)
3893 error ("Display still has frames on it");
3894
3895 BLOCK_INPUT;
3896 /* Free the fonts in the font table. */
3897 for (i = 0; i < dpyinfo->n_fonts; i++)
3898 if (dpyinfo->font_table[i].name)
3899 {
3900 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
3901 }
3902
3903 x_destroy_all_bitmaps (dpyinfo);
3904 XSetCloseDownMode (dpyinfo->display, DestroyAll);
3905
3906 #ifdef USE_X_TOOLKIT
3907 XtCloseDisplay (dpyinfo->display);
3908 #else
3909 XCloseDisplay (dpyinfo->display);
3910 #endif
3911
3912 x_delete_display (dpyinfo);
3913 UNBLOCK_INPUT;
3914
3915 return Qnil;
3916 }
3917
3918 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
3919 doc: /* Return the list of display names that Emacs has connections to. */)
3920 ()
3921 {
3922 Lisp_Object tail, result;
3923
3924 result = Qnil;
3925 for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
3926 result = Fcons (XCAR (XCAR (tail)), result);
3927
3928 return result;
3929 }
3930
3931 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
3932 doc: /* If ON is non-nil, report X errors as soon as the erring request is made.
3933 If ON is nil, allow buffering of requests.
3934 Turning on synchronization prohibits the Xlib routines from buffering
3935 requests and seriously degrades performance, but makes debugging much
3936 easier.
3937 The optional second argument DISPLAY specifies which display to act on.
3938 DISPLAY should be either a frame or a display name (a string).
3939 If DISPLAY is omitted or nil, that stands for the selected frame's display. */)
3940 (on, display)
3941 Lisp_Object display, on;
3942 {
3943 struct x_display_info *dpyinfo = check_x_display_info (display);
3944
3945 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
3946
3947 return Qnil;
3948 }
3949
3950 /* Wait for responses to all X commands issued so far for frame F. */
3951
3952 void
3953 x_sync (f)
3954 FRAME_PTR f;
3955 {
3956 BLOCK_INPUT;
3957 XSync (FRAME_X_DISPLAY (f), False);
3958 UNBLOCK_INPUT;
3959 }
3960
3961 \f
3962 /***********************************************************************
3963 Window properties
3964 ***********************************************************************/
3965
3966 DEFUN ("x-change-window-property", Fx_change_window_property,
3967 Sx_change_window_property, 2, 6, 0,
3968 doc: /* Change window property PROP to VALUE on the X window of FRAME.
3969 PROP must be a string.
3970 VALUE may be a string or a list of conses, numbers and/or strings.
3971 If an element in the list is a string, it is converted to
3972 an Atom and the value of the Atom is used. If an element is a cons,
3973 it is converted to a 32 bit number where the car is the 16 top bits and the
3974 cdr is the lower 16 bits.
3975 FRAME nil or omitted means use the selected frame.
3976 If TYPE is given and non-nil, it is the name of the type of VALUE.
3977 If TYPE is not given or nil, the type is STRING.
3978 FORMAT gives the size in bits of each element if VALUE is a list.
3979 It must be one of 8, 16 or 32.
3980 If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to 8.
3981 If OUTER_P is non-nil, the property is changed for the outer X window of
3982 FRAME. Default is to change on the edit X window.
3983
3984 Value is VALUE. */)
3985 (prop, value, frame, type, format, outer_p)
3986 Lisp_Object prop, value, frame, type, format, outer_p;
3987 {
3988 struct frame *f = check_x_frame (frame);
3989 Atom prop_atom;
3990 Atom target_type = XA_STRING;
3991 int element_format = 8;
3992 unsigned char *data;
3993 int nelements;
3994 Window w;
3995
3996 CHECK_STRING (prop);
3997
3998 if (! NILP (format))
3999 {
4000 CHECK_NUMBER (format);
4001 element_format = XFASTINT (format);
4002
4003 if (element_format != 8 && element_format != 16
4004 && element_format != 32)
4005 error ("FORMAT must be one of 8, 16 or 32");
4006 }
4007
4008 if (CONSP (value))
4009 {
4010 nelements = x_check_property_data (value);
4011 if (nelements == -1)
4012 error ("Bad data in VALUE, must be number, string or cons");
4013
4014 if (element_format == 8)
4015 data = (unsigned char *) xmalloc (nelements);
4016 else if (element_format == 16)
4017 data = (unsigned char *) xmalloc (nelements*2);
4018 else
4019 data = (unsigned char *) xmalloc (nelements*4);
4020
4021 x_fill_property_data (FRAME_X_DISPLAY (f), value, data, element_format);
4022 }
4023 else
4024 {
4025 CHECK_STRING (value);
4026 data = SDATA (value);
4027 nelements = SCHARS (value);
4028 }
4029
4030 BLOCK_INPUT;
4031 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
4032 if (! NILP (type))
4033 {
4034 CHECK_STRING (type);
4035 target_type = XInternAtom (FRAME_X_DISPLAY (f), SDATA (type), False);
4036 }
4037
4038 if (! NILP (outer_p)) w = FRAME_OUTER_WINDOW (f);
4039 else w = FRAME_X_WINDOW (f);
4040
4041 XChangeProperty (FRAME_X_DISPLAY (f), w,
4042 prop_atom, target_type, element_format, PropModeReplace,
4043 data, nelements);
4044
4045 if (CONSP (value)) xfree (data);
4046
4047 /* Make sure the property is set when we return. */
4048 XFlush (FRAME_X_DISPLAY (f));
4049 UNBLOCK_INPUT;
4050
4051 return value;
4052 }
4053
4054
4055 DEFUN ("x-delete-window-property", Fx_delete_window_property,
4056 Sx_delete_window_property, 1, 2, 0,
4057 doc: /* Remove window property PROP from X window of FRAME.
4058 FRAME nil or omitted means use the selected frame. Value is PROP. */)
4059 (prop, frame)
4060 Lisp_Object prop, frame;
4061 {
4062 struct frame *f = check_x_frame (frame);
4063 Atom prop_atom;
4064
4065 CHECK_STRING (prop);
4066 BLOCK_INPUT;
4067 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
4068 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
4069
4070 /* Make sure the property is removed when we return. */
4071 XFlush (FRAME_X_DISPLAY (f));
4072 UNBLOCK_INPUT;
4073
4074 return prop;
4075 }
4076
4077
4078 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
4079 1, 6, 0,
4080 doc: /* Value is the value of window property PROP on FRAME.
4081 If FRAME is nil or omitted, use the selected frame.
4082 If TYPE is nil or omitted, get the property as a string. Otherwise TYPE
4083 is the name of the Atom that denotes the type expected.
4084 If SOURCE is non-nil, get the property on that window instead of from
4085 FRAME. The number 0 denotes the root window.
4086 If DELETE_P is non-nil, delete the property after retreiving it.
4087 If VECTOR_RET_P is non-nil, don't return a string but a vector of values.
4088
4089 Value is nil if FRAME hasn't a property with name PROP or if PROP has
4090 no value of TYPE. */)
4091 (prop, frame, type, source, delete_p, vector_ret_p)
4092 Lisp_Object prop, frame, type, source, delete_p, vector_ret_p;
4093 {
4094 struct frame *f = check_x_frame (frame);
4095 Atom prop_atom;
4096 int rc;
4097 Lisp_Object prop_value = Qnil;
4098 char *tmp_data = NULL;
4099 Atom actual_type;
4100 Atom target_type = XA_STRING;
4101 int actual_format;
4102 unsigned long actual_size, bytes_remaining;
4103 Window target_window = FRAME_X_WINDOW (f);
4104 struct gcpro gcpro1;
4105
4106 GCPRO1 (prop_value);
4107 CHECK_STRING (prop);
4108
4109 if (! NILP (source))
4110 {
4111 if (NUMBERP (source))
4112 {
4113 if (FLOATP (source))
4114 target_window = (Window) XFLOAT (source);
4115 else
4116 target_window = XFASTINT (source);
4117
4118 if (target_window == 0)
4119 target_window = FRAME_X_DISPLAY_INFO (f)->root_window;
4120 }
4121 else if (CONSP (source))
4122 target_window = cons_to_long (source);
4123 }
4124
4125 BLOCK_INPUT;
4126 if (STRINGP (type))
4127 {
4128 if (strcmp ("AnyPropertyType", SDATA (type)) == 0)
4129 target_type = AnyPropertyType;
4130 else
4131 target_type = XInternAtom (FRAME_X_DISPLAY (f), SDATA (type), False);
4132 }
4133
4134 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
4135 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
4136 prop_atom, 0, 0, False, target_type,
4137 &actual_type, &actual_format, &actual_size,
4138 &bytes_remaining, (unsigned char **) &tmp_data);
4139 if (rc == Success)
4140 {
4141 int size = bytes_remaining;
4142
4143 XFree (tmp_data);
4144 tmp_data = NULL;
4145
4146 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
4147 prop_atom, 0, bytes_remaining,
4148 ! NILP (delete_p), target_type,
4149 &actual_type, &actual_format,
4150 &actual_size, &bytes_remaining,
4151 (unsigned char **) &tmp_data);
4152 if (rc == Success && tmp_data)
4153 {
4154 if (NILP (vector_ret_p))
4155 prop_value = make_string (tmp_data, size);
4156 else
4157 prop_value = x_property_data_to_lisp (f,
4158 (unsigned char *) tmp_data,
4159 actual_type,
4160 actual_format,
4161 actual_size);
4162 }
4163
4164 if (tmp_data) XFree (tmp_data);
4165 }
4166
4167 UNBLOCK_INPUT;
4168 UNGCPRO;
4169 return prop_value;
4170 }
4171
4172
4173 \f
4174 /***********************************************************************
4175 Busy cursor
4176 ***********************************************************************/
4177
4178 /* If non-null, an asynchronous timer that, when it expires, displays
4179 an hourglass cursor on all frames. */
4180
4181 static struct atimer *hourglass_atimer;
4182
4183 /* Non-zero means an hourglass cursor is currently shown. */
4184
4185 static int hourglass_shown_p;
4186
4187 /* Number of seconds to wait before displaying an hourglass cursor. */
4188
4189 static Lisp_Object Vhourglass_delay;
4190
4191 /* Default number of seconds to wait before displaying an hourglass
4192 cursor. */
4193
4194 #define DEFAULT_HOURGLASS_DELAY 1
4195
4196 /* Function prototypes. */
4197
4198 static void show_hourglass P_ ((struct atimer *));
4199 static void hide_hourglass P_ ((void));
4200
4201
4202 /* Cancel a currently active hourglass timer, and start a new one. */
4203
4204 void
4205 start_hourglass ()
4206 {
4207 EMACS_TIME delay;
4208 int secs, usecs = 0;
4209
4210 cancel_hourglass ();
4211
4212 if (INTEGERP (Vhourglass_delay)
4213 && XINT (Vhourglass_delay) > 0)
4214 secs = XFASTINT (Vhourglass_delay);
4215 else if (FLOATP (Vhourglass_delay)
4216 && XFLOAT_DATA (Vhourglass_delay) > 0)
4217 {
4218 Lisp_Object tem;
4219 tem = Ftruncate (Vhourglass_delay, Qnil);
4220 secs = XFASTINT (tem);
4221 usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
4222 }
4223 else
4224 secs = DEFAULT_HOURGLASS_DELAY;
4225
4226 EMACS_SET_SECS_USECS (delay, secs, usecs);
4227 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
4228 show_hourglass, NULL);
4229 }
4230
4231
4232 /* Cancel the hourglass cursor timer if active, hide a busy cursor if
4233 shown. */
4234
4235 void
4236 cancel_hourglass ()
4237 {
4238 if (hourglass_atimer)
4239 {
4240 cancel_atimer (hourglass_atimer);
4241 hourglass_atimer = NULL;
4242 }
4243
4244 if (hourglass_shown_p)
4245 hide_hourglass ();
4246 }
4247
4248
4249 /* Timer function of hourglass_atimer. TIMER is equal to
4250 hourglass_atimer.
4251
4252 Display an hourglass pointer on all frames by mapping the frames'
4253 hourglass_window. Set the hourglass_p flag in the frames'
4254 output_data.x structure to indicate that an hourglass cursor is
4255 shown on the frames. */
4256
4257 static void
4258 show_hourglass (timer)
4259 struct atimer *timer;
4260 {
4261 /* The timer implementation will cancel this timer automatically
4262 after this function has run. Set hourglass_atimer to null
4263 so that we know the timer doesn't have to be canceled. */
4264 hourglass_atimer = NULL;
4265
4266 if (!hourglass_shown_p)
4267 {
4268 Lisp_Object rest, frame;
4269
4270 BLOCK_INPUT;
4271
4272 FOR_EACH_FRAME (rest, frame)
4273 {
4274 struct frame *f = XFRAME (frame);
4275
4276 if (FRAME_LIVE_P (f) && FRAME_X_P (f) && FRAME_X_DISPLAY (f))
4277 {
4278 Display *dpy = FRAME_X_DISPLAY (f);
4279
4280 #ifdef USE_X_TOOLKIT
4281 if (f->output_data.x->widget)
4282 #else
4283 if (FRAME_OUTER_WINDOW (f))
4284 #endif
4285 {
4286 f->output_data.x->hourglass_p = 1;
4287
4288 if (!f->output_data.x->hourglass_window)
4289 {
4290 unsigned long mask = CWCursor;
4291 XSetWindowAttributes attrs;
4292
4293 attrs.cursor = f->output_data.x->hourglass_cursor;
4294
4295 f->output_data.x->hourglass_window
4296 = XCreateWindow (dpy, FRAME_OUTER_WINDOW (f),
4297 0, 0, 32000, 32000, 0, 0,
4298 InputOnly,
4299 CopyFromParent,
4300 mask, &attrs);
4301 }
4302
4303 XMapRaised (dpy, f->output_data.x->hourglass_window);
4304 XFlush (dpy);
4305 }
4306 }
4307 }
4308
4309 hourglass_shown_p = 1;
4310 UNBLOCK_INPUT;
4311 }
4312 }
4313
4314
4315 /* Hide the hourglass pointer on all frames, if it is currently
4316 shown. */
4317
4318 static void
4319 hide_hourglass ()
4320 {
4321 if (hourglass_shown_p)
4322 {
4323 Lisp_Object rest, frame;
4324
4325 BLOCK_INPUT;
4326 FOR_EACH_FRAME (rest, frame)
4327 {
4328 struct frame *f = XFRAME (frame);
4329
4330 if (FRAME_X_P (f)
4331 /* Watch out for newly created frames. */
4332 && f->output_data.x->hourglass_window)
4333 {
4334 XUnmapWindow (FRAME_X_DISPLAY (f),
4335 f->output_data.x->hourglass_window);
4336 /* Sync here because XTread_socket looks at the
4337 hourglass_p flag that is reset to zero below. */
4338 XSync (FRAME_X_DISPLAY (f), False);
4339 f->output_data.x->hourglass_p = 0;
4340 }
4341 }
4342
4343 hourglass_shown_p = 0;
4344 UNBLOCK_INPUT;
4345 }
4346 }
4347
4348
4349 \f
4350 /***********************************************************************
4351 Tool tips
4352 ***********************************************************************/
4353
4354 static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
4355 Lisp_Object, Lisp_Object));
4356 static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
4357 Lisp_Object, int, int, int *, int *));
4358
4359 /* The frame of a currently visible tooltip. */
4360
4361 Lisp_Object tip_frame;
4362
4363 /* If non-nil, a timer started that hides the last tooltip when it
4364 fires. */
4365
4366 Lisp_Object tip_timer;
4367 Window tip_window;
4368
4369 /* If non-nil, a vector of 3 elements containing the last args
4370 with which x-show-tip was called. See there. */
4371
4372 Lisp_Object last_show_tip_args;
4373
4374 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
4375
4376 Lisp_Object Vx_max_tooltip_size;
4377
4378
4379 static Lisp_Object
4380 unwind_create_tip_frame (frame)
4381 Lisp_Object frame;
4382 {
4383 Lisp_Object deleted;
4384
4385 deleted = unwind_create_frame (frame);
4386 if (EQ (deleted, Qt))
4387 {
4388 tip_window = None;
4389 tip_frame = Qnil;
4390 }
4391
4392 return deleted;
4393 }
4394
4395
4396 /* Create a frame for a tooltip on the display described by DPYINFO.
4397 PARMS is a list of frame parameters. TEXT is the string to
4398 display in the tip frame. Value is the frame.
4399
4400 Note that functions called here, esp. x_default_parameter can
4401 signal errors, for instance when a specified color name is
4402 undefined. We have to make sure that we're in a consistent state
4403 when this happens. */
4404
4405 static Lisp_Object
4406 x_create_tip_frame (dpyinfo, parms, text)
4407 struct x_display_info *dpyinfo;
4408 Lisp_Object parms, text;
4409 {
4410 struct frame *f;
4411 Lisp_Object frame, tem;
4412 Lisp_Object name;
4413 long window_prompting = 0;
4414 int width, height;
4415 int count = SPECPDL_INDEX ();
4416 struct gcpro gcpro1, gcpro2, gcpro3;
4417 struct kboard *kb;
4418 int face_change_count_before = face_change_count;
4419 Lisp_Object buffer;
4420 struct buffer *old_buffer;
4421
4422 check_x ();
4423
4424 /* Use this general default value to start with until we know if
4425 this frame has a specified name. */
4426 Vx_resource_name = Vinvocation_name;
4427
4428 #ifdef MULTI_KBOARD
4429 kb = dpyinfo->kboard;
4430 #else
4431 kb = &the_only_kboard;
4432 #endif
4433
4434 /* Get the name of the frame to use for resource lookup. */
4435 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
4436 if (!STRINGP (name)
4437 && !EQ (name, Qunbound)
4438 && !NILP (name))
4439 error ("Invalid frame name--not a string or nil");
4440 Vx_resource_name = name;
4441
4442 frame = Qnil;
4443 GCPRO3 (parms, name, frame);
4444 f = make_frame (1);
4445 XSETFRAME (frame, f);
4446
4447 buffer = Fget_buffer_create (build_string (" *tip*"));
4448 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer, Qnil);
4449 old_buffer = current_buffer;
4450 set_buffer_internal_1 (XBUFFER (buffer));
4451 current_buffer->truncate_lines = Qnil;
4452 Ferase_buffer ();
4453 Finsert (1, &text);
4454 set_buffer_internal_1 (old_buffer);
4455
4456 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
4457 record_unwind_protect (unwind_create_tip_frame, frame);
4458
4459 f->display = dpyinfo->frame_display;
4460 f->display->reference_count++;
4461
4462 /* By setting the output method, we're essentially saying that
4463 the frame is live, as per FRAME_LIVE_P. If we get a signal
4464 from this point on, x_destroy_window might screw up reference
4465 counts etc. */
4466 f->output_method = output_x_window;
4467 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
4468 bzero (f->output_data.x, sizeof (struct x_output));
4469 f->output_data.x->icon_bitmap = -1;
4470 FRAME_FONTSET (f) = -1;
4471 f->output_data.x->scroll_bar_foreground_pixel = -1;
4472 f->output_data.x->scroll_bar_background_pixel = -1;
4473 #ifdef USE_TOOLKIT_SCROLL_BARS
4474 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
4475 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
4476 #endif /* USE_TOOLKIT_SCROLL_BARS */
4477 f->icon_name = Qnil;
4478 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
4479 #if GLYPH_DEBUG
4480 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
4481 dpyinfo_refcount = dpyinfo->reference_count;
4482 #endif /* GLYPH_DEBUG */
4483 #ifdef MULTI_KBOARD
4484 FRAME_KBOARD (f) = kb;
4485 #endif
4486 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4487 f->output_data.x->explicit_parent = 0;
4488
4489 /* These colors will be set anyway later, but it's important
4490 to get the color reference counts right, so initialize them! */
4491 {
4492 Lisp_Object black;
4493 struct gcpro gcpro1;
4494
4495 black = build_string ("black");
4496 GCPRO1 (black);
4497 f->output_data.x->foreground_pixel
4498 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4499 f->output_data.x->background_pixel
4500 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4501 f->output_data.x->cursor_pixel
4502 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4503 f->output_data.x->cursor_foreground_pixel
4504 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4505 f->output_data.x->border_pixel
4506 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4507 f->output_data.x->mouse_pixel
4508 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4509 UNGCPRO;
4510 }
4511
4512 /* Set the name; the functions to which we pass f expect the name to
4513 be set. */
4514 if (EQ (name, Qunbound) || NILP (name))
4515 {
4516 f->name = build_string (dpyinfo->x_id_name);
4517 f->explicit_name = 0;
4518 }
4519 else
4520 {
4521 f->name = name;
4522 f->explicit_name = 1;
4523 /* use the frame's title when getting resources for this frame. */
4524 specbind (Qx_resource_name, name);
4525 }
4526
4527 /* Extract the window parameters from the supplied values that are
4528 needed to determine window geometry. */
4529 {
4530 Lisp_Object font;
4531
4532 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
4533
4534 BLOCK_INPUT;
4535 /* First, try whatever font the caller has specified. */
4536 if (STRINGP (font))
4537 {
4538 tem = Fquery_fontset (font, Qnil);
4539 if (STRINGP (tem))
4540 font = x_new_fontset (f, SDATA (tem));
4541 else
4542 font = x_new_font (f, SDATA (font));
4543 }
4544
4545 /* Try out a font which we hope has bold and italic variations. */
4546 if (!STRINGP (font))
4547 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4548 if (!STRINGP (font))
4549 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4550 if (! STRINGP (font))
4551 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4552 if (! STRINGP (font))
4553 /* This was formerly the first thing tried, but it finds too many fonts
4554 and takes too long. */
4555 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4556 /* If those didn't work, look for something which will at least work. */
4557 if (! STRINGP (font))
4558 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4559 UNBLOCK_INPUT;
4560 if (! STRINGP (font))
4561 font = build_string ("fixed");
4562
4563 x_default_parameter (f, parms, Qfont, font,
4564 "font", "Font", RES_TYPE_STRING);
4565 }
4566
4567 x_default_parameter (f, parms, Qborder_width, make_number (2),
4568 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
4569
4570 /* This defaults to 2 in order to match xterm. We recognize either
4571 internalBorderWidth or internalBorder (which is what xterm calls
4572 it). */
4573 if (NILP (Fassq (Qinternal_border_width, parms)))
4574 {
4575 Lisp_Object value;
4576
4577 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
4578 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
4579 if (! EQ (value, Qunbound))
4580 parms = Fcons (Fcons (Qinternal_border_width, value),
4581 parms);
4582 }
4583
4584 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
4585 "internalBorderWidth", "internalBorderWidth",
4586 RES_TYPE_NUMBER);
4587
4588 /* Also do the stuff which must be set before the window exists. */
4589 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
4590 "foreground", "Foreground", RES_TYPE_STRING);
4591 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
4592 "background", "Background", RES_TYPE_STRING);
4593 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
4594 "pointerColor", "Foreground", RES_TYPE_STRING);
4595 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
4596 "cursorColor", "Foreground", RES_TYPE_STRING);
4597 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
4598 "borderColor", "BorderColor", RES_TYPE_STRING);
4599
4600 /* Init faces before x_default_parameter is called for scroll-bar
4601 parameters because that function calls x_set_scroll_bar_width,
4602 which calls change_frame_size, which calls Fset_window_buffer,
4603 which runs hooks, which call Fvertical_motion. At the end, we
4604 end up in init_iterator with a null face cache, which should not
4605 happen. */
4606 init_frame_faces (f);
4607
4608 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4609
4610 window_prompting = x_figure_window_size (f, parms, 0);
4611
4612 {
4613 XSetWindowAttributes attrs;
4614 unsigned long mask;
4615
4616 BLOCK_INPUT;
4617 mask = CWBackPixel | CWOverrideRedirect | CWEventMask;
4618 if (DoesSaveUnders (dpyinfo->screen))
4619 mask |= CWSaveUnder;
4620
4621 /* Window managers look at the override-redirect flag to determine
4622 whether or net to give windows a decoration (Xlib spec, chapter
4623 3.2.8). */
4624 attrs.override_redirect = True;
4625 attrs.save_under = True;
4626 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
4627 /* Arrange for getting MapNotify and UnmapNotify events. */
4628 attrs.event_mask = StructureNotifyMask;
4629 tip_window
4630 = FRAME_X_WINDOW (f)
4631 = XCreateWindow (FRAME_X_DISPLAY (f),
4632 FRAME_X_DISPLAY_INFO (f)->root_window,
4633 /* x, y, width, height */
4634 0, 0, 1, 1,
4635 /* Border. */
4636 1,
4637 CopyFromParent, InputOutput, CopyFromParent,
4638 mask, &attrs);
4639 UNBLOCK_INPUT;
4640 }
4641
4642 x_make_gc (f);
4643
4644 x_default_parameter (f, parms, Qauto_raise, Qnil,
4645 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4646 x_default_parameter (f, parms, Qauto_lower, Qnil,
4647 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4648 x_default_parameter (f, parms, Qcursor_type, Qbox,
4649 "cursorType", "CursorType", RES_TYPE_SYMBOL);
4650
4651 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
4652 Change will not be effected unless different from the current
4653 FRAME_LINES (f). */
4654 width = FRAME_COLS (f);
4655 height = FRAME_LINES (f);
4656 SET_FRAME_COLS (f, 0);
4657 FRAME_LINES (f) = 0;
4658 change_frame_size (f, height, width, 1, 0, 0);
4659
4660 /* Add `tooltip' frame parameter's default value. */
4661 if (NILP (Fframe_parameter (frame, intern ("tooltip"))))
4662 Fmodify_frame_parameters (frame, Fcons (Fcons (intern ("tooltip"), Qt),
4663 Qnil));
4664
4665 /* Set up faces after all frame parameters are known. This call
4666 also merges in face attributes specified for new frames.
4667
4668 Frame parameters may be changed if .Xdefaults contains
4669 specifications for the default font. For example, if there is an
4670 `Emacs.default.attributeBackground: pink', the `background-color'
4671 attribute of the frame get's set, which let's the internal border
4672 of the tooltip frame appear in pink. Prevent this. */
4673 {
4674 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
4675
4676 /* Set tip_frame here, so that */
4677 tip_frame = frame;
4678 call1 (Qface_set_after_frame_default, frame);
4679
4680 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
4681 Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
4682 Qnil));
4683 }
4684
4685 Fmodify_frame_parameters (frame, Fcons (Fcons (Qwindow_system, Qx), Qnil));
4686
4687 f->no_split = 1;
4688
4689 UNGCPRO;
4690
4691 /* It is now ok to make the frame official even if we get an error
4692 below. And the frame needs to be on Vframe_list or making it
4693 visible won't work. */
4694 Vframe_list = Fcons (frame, Vframe_list);
4695
4696 /* Now that the frame is official, it counts as a reference to
4697 its display. */
4698 FRAME_X_DISPLAY_INFO (f)->reference_count++;
4699
4700 /* Setting attributes of faces of the tooltip frame from resources
4701 and similar will increment face_change_count, which leads to the
4702 clearing of all current matrices. Since this isn't necessary
4703 here, avoid it by resetting face_change_count to the value it
4704 had before we created the tip frame. */
4705 face_change_count = face_change_count_before;
4706
4707 /* Discard the unwind_protect. */
4708 return unbind_to (count, frame);
4709 }
4710
4711
4712 /* Compute where to display tip frame F. PARMS is the list of frame
4713 parameters for F. DX and DY are specified offsets from the current
4714 location of the mouse. WIDTH and HEIGHT are the width and height
4715 of the tooltip. Return coordinates relative to the root window of
4716 the display in *ROOT_X, and *ROOT_Y. */
4717
4718 static void
4719 compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
4720 struct frame *f;
4721 Lisp_Object parms, dx, dy;
4722 int width, height;
4723 int *root_x, *root_y;
4724 {
4725 Lisp_Object left, top;
4726 int win_x, win_y;
4727 Window root, child;
4728 unsigned pmask;
4729
4730 /* User-specified position? */
4731 left = Fcdr (Fassq (Qleft, parms));
4732 top = Fcdr (Fassq (Qtop, parms));
4733
4734 /* Move the tooltip window where the mouse pointer is. Resize and
4735 show it. */
4736 if (!INTEGERP (left) || !INTEGERP (top))
4737 {
4738 BLOCK_INPUT;
4739 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
4740 &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
4741 UNBLOCK_INPUT;
4742 }
4743
4744 if (INTEGERP (top))
4745 *root_y = XINT (top);
4746 else if (*root_y + XINT (dy) - height < 0)
4747 *root_y -= XINT (dy);
4748 else
4749 {
4750 *root_y -= height;
4751 *root_y += XINT (dy);
4752 }
4753
4754 if (INTEGERP (left))
4755 *root_x = XINT (left);
4756 else if (*root_x + XINT (dx) + width <= FRAME_X_DISPLAY_INFO (f)->width)
4757 /* It fits to the right of the pointer. */
4758 *root_x += XINT (dx);
4759 else if (width + XINT (dx) <= *root_x)
4760 /* It fits to the left of the pointer. */
4761 *root_x -= width + XINT (dx);
4762 else
4763 /* Put it left-justified on the screen--it ought to fit that way. */
4764 *root_x = 0;
4765 }
4766
4767
4768 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
4769 doc: /* Show STRING in a "tooltip" window on frame FRAME.
4770 A tooltip window is a small X window displaying a string.
4771
4772 FRAME nil or omitted means use the selected frame.
4773
4774 PARMS is an optional list of frame parameters which can be used to
4775 change the tooltip's appearance.
4776
4777 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
4778 means use the default timeout of 5 seconds.
4779
4780 If the list of frame parameters PARAMS contains a `left' parameters,
4781 the tooltip is displayed at that x-position. Otherwise it is
4782 displayed at the mouse position, with offset DX added (default is 5 if
4783 DX isn't specified). Likewise for the y-position; if a `top' frame
4784 parameter is specified, it determines the y-position of the tooltip
4785 window, otherwise it is displayed at the mouse position, with offset
4786 DY added (default is -10).
4787
4788 A tooltip's maximum size is specified by `x-max-tooltip-size'.
4789 Text larger than the specified size is clipped. */)
4790 (string, frame, parms, timeout, dx, dy)
4791 Lisp_Object string, frame, parms, timeout, dx, dy;
4792 {
4793 struct frame *f;
4794 struct window *w;
4795 int root_x, root_y;
4796 struct buffer *old_buffer;
4797 struct text_pos pos;
4798 int i, width, height;
4799 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
4800 int old_windows_or_buffers_changed = windows_or_buffers_changed;
4801 int count = SPECPDL_INDEX ();
4802
4803 specbind (Qinhibit_redisplay, Qt);
4804
4805 GCPRO4 (string, parms, frame, timeout);
4806
4807 CHECK_STRING (string);
4808 f = check_x_frame (frame);
4809 if (NILP (timeout))
4810 timeout = make_number (5);
4811 else
4812 CHECK_NATNUM (timeout);
4813
4814 if (NILP (dx))
4815 dx = make_number (5);
4816 else
4817 CHECK_NUMBER (dx);
4818
4819 if (NILP (dy))
4820 dy = make_number (-10);
4821 else
4822 CHECK_NUMBER (dy);
4823
4824 if (NILP (last_show_tip_args))
4825 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
4826
4827 if (!NILP (tip_frame))
4828 {
4829 Lisp_Object last_string = AREF (last_show_tip_args, 0);
4830 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
4831 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
4832
4833 if (EQ (frame, last_frame)
4834 && !NILP (Fequal (last_string, string))
4835 && !NILP (Fequal (last_parms, parms)))
4836 {
4837 struct frame *f = XFRAME (tip_frame);
4838
4839 /* Only DX and DY have changed. */
4840 if (!NILP (tip_timer))
4841 {
4842 Lisp_Object timer = tip_timer;
4843 tip_timer = Qnil;
4844 call1 (Qcancel_timer, timer);
4845 }
4846
4847 BLOCK_INPUT;
4848 compute_tip_xy (f, parms, dx, dy, FRAME_PIXEL_WIDTH (f),
4849 FRAME_PIXEL_HEIGHT (f), &root_x, &root_y);
4850 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4851 root_x, root_y);
4852 UNBLOCK_INPUT;
4853 goto start_timer;
4854 }
4855 }
4856
4857 /* Hide a previous tip, if any. */
4858 Fx_hide_tip ();
4859
4860 ASET (last_show_tip_args, 0, string);
4861 ASET (last_show_tip_args, 1, frame);
4862 ASET (last_show_tip_args, 2, parms);
4863
4864 /* Add default values to frame parameters. */
4865 if (NILP (Fassq (Qname, parms)))
4866 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
4867 if (NILP (Fassq (Qinternal_border_width, parms)))
4868 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
4869 if (NILP (Fassq (Qborder_width, parms)))
4870 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
4871 if (NILP (Fassq (Qborder_color, parms)))
4872 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
4873 if (NILP (Fassq (Qbackground_color, parms)))
4874 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
4875 parms);
4876
4877 /* Create a frame for the tooltip, and record it in the global
4878 variable tip_frame. */
4879 frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms, string);
4880 f = XFRAME (frame);
4881
4882 /* Set up the frame's root window. */
4883 w = XWINDOW (FRAME_ROOT_WINDOW (f));
4884 w->left_col = w->top_line = make_number (0);
4885
4886 if (CONSP (Vx_max_tooltip_size)
4887 && INTEGERP (XCAR (Vx_max_tooltip_size))
4888 && XINT (XCAR (Vx_max_tooltip_size)) > 0
4889 && INTEGERP (XCDR (Vx_max_tooltip_size))
4890 && XINT (XCDR (Vx_max_tooltip_size)) > 0)
4891 {
4892 w->total_cols = XCAR (Vx_max_tooltip_size);
4893 w->total_lines = XCDR (Vx_max_tooltip_size);
4894 }
4895 else
4896 {
4897 w->total_cols = make_number (80);
4898 w->total_lines = make_number (40);
4899 }
4900
4901 FRAME_TOTAL_COLS (f) = XINT (w->total_cols);
4902 adjust_glyphs (f);
4903 w->pseudo_window_p = 1;
4904
4905 /* Display the tooltip text in a temporary buffer. */
4906 old_buffer = current_buffer;
4907 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
4908 current_buffer->truncate_lines = Qnil;
4909 clear_glyph_matrix (w->desired_matrix);
4910 clear_glyph_matrix (w->current_matrix);
4911 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
4912 try_window (FRAME_ROOT_WINDOW (f), pos);
4913
4914 /* Compute width and height of the tooltip. */
4915 width = height = 0;
4916 for (i = 0; i < w->desired_matrix->nrows; ++i)
4917 {
4918 struct glyph_row *row = &w->desired_matrix->rows[i];
4919 struct glyph *last;
4920 int row_width;
4921
4922 /* Stop at the first empty row at the end. */
4923 if (!row->enabled_p || !row->displays_text_p)
4924 break;
4925
4926 /* Let the row go over the full width of the frame. */
4927 row->full_width_p = 1;
4928
4929 /* There's a glyph at the end of rows that is used to place
4930 the cursor there. Don't include the width of this glyph. */
4931 if (row->used[TEXT_AREA])
4932 {
4933 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
4934 row_width = row->pixel_width - last->pixel_width;
4935 }
4936 else
4937 row_width = row->pixel_width;
4938
4939 height += row->height;
4940 width = max (width, row_width);
4941 }
4942
4943 /* Add the frame's internal border to the width and height the X
4944 window should have. */
4945 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
4946 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
4947
4948 /* Move the tooltip window where the mouse pointer is. Resize and
4949 show it. */
4950 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
4951
4952 BLOCK_INPUT;
4953 XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4954 root_x, root_y, width, height);
4955 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
4956 UNBLOCK_INPUT;
4957
4958 /* Draw into the window. */
4959 w->must_be_updated_p = 1;
4960 update_single_window (w, 1);
4961
4962 /* Restore original current buffer. */
4963 set_buffer_internal_1 (old_buffer);
4964 windows_or_buffers_changed = old_windows_or_buffers_changed;
4965
4966 start_timer:
4967 /* Let the tip disappear after timeout seconds. */
4968 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
4969 intern ("x-hide-tip"));
4970
4971 UNGCPRO;
4972 return unbind_to (count, Qnil);
4973 }
4974
4975
4976 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
4977 doc: /* Hide the current tooltip window, if there is any.
4978 Value is t if tooltip was open, nil otherwise. */)
4979 ()
4980 {
4981 int count;
4982 Lisp_Object deleted, frame, timer;
4983 struct gcpro gcpro1, gcpro2;
4984
4985 /* Return quickly if nothing to do. */
4986 if (NILP (tip_timer) && NILP (tip_frame))
4987 return Qnil;
4988
4989 frame = tip_frame;
4990 timer = tip_timer;
4991 GCPRO2 (frame, timer);
4992 tip_frame = tip_timer = deleted = Qnil;
4993
4994 count = SPECPDL_INDEX ();
4995 specbind (Qinhibit_redisplay, Qt);
4996 specbind (Qinhibit_quit, Qt);
4997
4998 if (!NILP (timer))
4999 call1 (Qcancel_timer, timer);
5000
5001 if (FRAMEP (frame))
5002 {
5003 Fdelete_frame (frame, Qnil);
5004 deleted = Qt;
5005
5006 #ifdef USE_LUCID
5007 /* Bloodcurdling hack alert: The Lucid menu bar widget's
5008 redisplay procedure is not called when a tip frame over menu
5009 items is unmapped. Redisplay the menu manually... */
5010 {
5011 struct frame *f = SELECTED_FRAME ();
5012 Widget w = f->output_data.x->menubar_widget;
5013 extern void xlwmenu_redisplay P_ ((Widget));
5014
5015 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen)
5016 && w != NULL)
5017 {
5018 BLOCK_INPUT;
5019 xlwmenu_redisplay (w);
5020 UNBLOCK_INPUT;
5021 }
5022 }
5023 #endif /* USE_LUCID */
5024 }
5025
5026 UNGCPRO;
5027 return unbind_to (count, deleted);
5028 }
5029
5030
5031 \f
5032 /***********************************************************************
5033 File selection dialog
5034 ***********************************************************************/
5035
5036 #ifdef USE_MOTIF
5037
5038 /* Callback for "OK" and "Cancel" on file selection dialog. */
5039
5040 static void
5041 file_dialog_cb (widget, client_data, call_data)
5042 Widget widget;
5043 XtPointer call_data, client_data;
5044 {
5045 int *result = (int *) client_data;
5046 XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
5047 *result = cb->reason;
5048 }
5049
5050
5051 /* Callback for unmapping a file selection dialog. This is used to
5052 capture the case where a dialog is closed via a window manager's
5053 closer button, for example. Using a XmNdestroyCallback didn't work
5054 in this case. */
5055
5056 static void
5057 file_dialog_unmap_cb (widget, client_data, call_data)
5058 Widget widget;
5059 XtPointer call_data, client_data;
5060 {
5061 int *result = (int *) client_data;
5062 *result = XmCR_CANCEL;
5063 }
5064
5065
5066 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
5067 doc: /* Read file name, prompting with PROMPT in directory DIR.
5068 Use a file selection dialog.
5069 Select DEFAULT-FILENAME in the dialog's file selection box, if
5070 specified. Don't let the user enter a file name in the file
5071 selection dialog's entry field, if MUSTMATCH is non-nil. */)
5072 (prompt, dir, default_filename, mustmatch)
5073 Lisp_Object prompt, dir, default_filename, mustmatch;
5074 {
5075 int result;
5076 struct frame *f = SELECTED_FRAME ();
5077 Lisp_Object file = Qnil;
5078 Widget dialog, text, list, help;
5079 Arg al[10];
5080 int ac = 0;
5081 extern XtAppContext Xt_app_con;
5082 XmString dir_xmstring, pattern_xmstring;
5083 int count = SPECPDL_INDEX ();
5084 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
5085
5086 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
5087 CHECK_STRING (prompt);
5088 CHECK_STRING (dir);
5089
5090 /* Prevent redisplay. */
5091 specbind (Qinhibit_redisplay, Qt);
5092
5093 BLOCK_INPUT;
5094
5095 /* Create the dialog with PROMPT as title, using DIR as initial
5096 directory and using "*" as pattern. */
5097 dir = Fexpand_file_name (dir, Qnil);
5098 dir_xmstring = XmStringCreateLocalized (SDATA (dir));
5099 pattern_xmstring = XmStringCreateLocalized ("*");
5100
5101 XtSetArg (al[ac], XmNtitle, SDATA (prompt)); ++ac;
5102 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
5103 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
5104 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
5105 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
5106 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
5107 "fsb", al, ac);
5108 XmStringFree (dir_xmstring);
5109 XmStringFree (pattern_xmstring);
5110
5111 /* Add callbacks for OK and Cancel. */
5112 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
5113 (XtPointer) &result);
5114 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
5115 (XtPointer) &result);
5116 XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
5117 (XtPointer) &result);
5118
5119 /* Disable the help button since we can't display help. */
5120 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
5121 XtSetSensitive (help, False);
5122
5123 /* Mark OK button as default. */
5124 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
5125 XmNshowAsDefault, True, NULL);
5126
5127 /* If MUSTMATCH is non-nil, disable the file entry field of the
5128 dialog, so that the user must select a file from the files list
5129 box. We can't remove it because we wouldn't have a way to get at
5130 the result file name, then. */
5131 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
5132 if (!NILP (mustmatch))
5133 {
5134 Widget label;
5135 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
5136 XtSetSensitive (text, False);
5137 XtSetSensitive (label, False);
5138 }
5139
5140 /* Manage the dialog, so that list boxes get filled. */
5141 XtManageChild (dialog);
5142
5143 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
5144 must include the path for this to work. */
5145 list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
5146 if (STRINGP (default_filename))
5147 {
5148 XmString default_xmstring;
5149 int item_pos;
5150
5151 default_xmstring
5152 = XmStringCreateLocalized (SDATA (default_filename));
5153
5154 if (!XmListItemExists (list, default_xmstring))
5155 {
5156 /* Add a new item if DEFAULT_FILENAME is not in the list. */
5157 XmListAddItem (list, default_xmstring, 0);
5158 item_pos = 0;
5159 }
5160 else
5161 item_pos = XmListItemPos (list, default_xmstring);
5162 XmStringFree (default_xmstring);
5163
5164 /* Select the item and scroll it into view. */
5165 XmListSelectPos (list, item_pos, True);
5166 XmListSetPos (list, item_pos);
5167 }
5168
5169 /* Process events until the user presses Cancel or OK. */
5170 result = 0;
5171 while (result == 0)
5172 {
5173 XEvent event;
5174 XtAppNextEvent (Xt_app_con, &event);
5175 (void) x_dispatch_event (&event, FRAME_X_DISPLAY (f) );
5176 }
5177
5178 /* Get the result. */
5179 if (result == XmCR_OK)
5180 {
5181 XmString text;
5182 String data;
5183
5184 XtVaGetValues (dialog, XmNtextString, &text, NULL);
5185 XmStringGetLtoR (text, XmFONTLIST_DEFAULT_TAG, &data);
5186 XmStringFree (text);
5187 file = build_string (data);
5188 XtFree (data);
5189 }
5190 else
5191 file = Qnil;
5192
5193 /* Clean up. */
5194 XtUnmanageChild (dialog);
5195 XtDestroyWidget (dialog);
5196 UNBLOCK_INPUT;
5197 UNGCPRO;
5198
5199 /* Make "Cancel" equivalent to C-g. */
5200 if (NILP (file))
5201 Fsignal (Qquit, Qnil);
5202
5203 return unbind_to (count, file);
5204 }
5205
5206 #endif /* USE_MOTIF */
5207
5208 #ifdef USE_GTK
5209
5210 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
5211 "Read file name, prompting with PROMPT in directory DIR.\n\
5212 Use a file selection dialog.\n\
5213 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
5214 specified. Don't let the user enter a file name in the file\n\
5215 selection dialog's entry field, if MUSTMATCH is non-nil.")
5216 (prompt, dir, default_filename, mustmatch)
5217 Lisp_Object prompt, dir, default_filename, mustmatch;
5218 {
5219 FRAME_PTR f = SELECTED_FRAME ();
5220 char *fn;
5221 Lisp_Object file = Qnil;
5222 int count = specpdl_ptr - specpdl;
5223 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
5224 char *cdef_file;
5225
5226 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
5227 CHECK_STRING (prompt);
5228 CHECK_STRING (dir);
5229
5230 /* Prevent redisplay. */
5231 specbind (Qinhibit_redisplay, Qt);
5232
5233 BLOCK_INPUT;
5234
5235 if (STRINGP (default_filename))
5236 cdef_file = SDATA (default_filename);
5237 else
5238 cdef_file = SDATA (dir);
5239
5240 fn = xg_get_file_name (f, SDATA (prompt), cdef_file, ! NILP (mustmatch));
5241
5242 if (fn)
5243 {
5244 file = build_string (fn);
5245 xfree (fn);
5246 }
5247
5248 UNBLOCK_INPUT;
5249 UNGCPRO;
5250
5251 /* Make "Cancel" equivalent to C-g. */
5252 if (NILP (file))
5253 Fsignal (Qquit, Qnil);
5254
5255 return unbind_to (count, file);
5256 }
5257
5258 #endif /* USE_GTK */
5259
5260 \f
5261 /***********************************************************************
5262 Keyboard
5263 ***********************************************************************/
5264
5265 #ifdef HAVE_XKBGETKEYBOARD
5266 #include <X11/XKBlib.h>
5267 #include <X11/keysym.h>
5268 #endif
5269
5270 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
5271 Sx_backspace_delete_keys_p, 0, 1, 0,
5272 doc: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
5273 FRAME nil means use the selected frame.
5274 Value is t if we know that both keys are present, and are mapped to the
5275 usual X keysyms. */)
5276 (frame)
5277 Lisp_Object frame;
5278 {
5279 #ifdef HAVE_XKBGETKEYBOARD
5280 XkbDescPtr kb;
5281 struct frame *f = check_x_frame (frame);
5282 Display *dpy = FRAME_X_DISPLAY (f);
5283 Lisp_Object have_keys;
5284 int major, minor, op, event, error;
5285
5286 BLOCK_INPUT;
5287
5288 /* Check library version in case we're dynamically linked. */
5289 major = XkbMajorVersion;
5290 minor = XkbMinorVersion;
5291 if (!XkbLibraryVersion (&major, &minor))
5292 {
5293 UNBLOCK_INPUT;
5294 return Qnil;
5295 }
5296
5297 /* Check that the server supports XKB. */
5298 major = XkbMajorVersion;
5299 minor = XkbMinorVersion;
5300 if (!XkbQueryExtension (dpy, &op, &event, &error, &major, &minor))
5301 {
5302 UNBLOCK_INPUT;
5303 return Qnil;
5304 }
5305
5306 have_keys = Qnil;
5307 kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
5308 if (kb)
5309 {
5310 int delete_keycode = 0, backspace_keycode = 0, i;
5311
5312 if (XkbGetNames (dpy, XkbAllNamesMask, kb) == Success)
5313 {
5314 for (i = kb->min_key_code;
5315 (i < kb->max_key_code
5316 && (delete_keycode == 0 || backspace_keycode == 0));
5317 ++i)
5318 {
5319 /* The XKB symbolic key names can be seen most easily in
5320 the PS file generated by `xkbprint -label name
5321 $DISPLAY'. */
5322 if (bcmp ("DELE", kb->names->keys[i].name, 4) == 0)
5323 delete_keycode = i;
5324 else if (bcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
5325 backspace_keycode = i;
5326 }
5327
5328 XkbFreeNames (kb, 0, True);
5329 }
5330
5331 XkbFreeClientMap (kb, 0, True);
5332
5333 if (delete_keycode
5334 && backspace_keycode
5335 && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
5336 && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
5337 have_keys = Qt;
5338 }
5339 UNBLOCK_INPUT;
5340 return have_keys;
5341 #else /* not HAVE_XKBGETKEYBOARD */
5342 return Qnil;
5343 #endif /* not HAVE_XKBGETKEYBOARD */
5344 }
5345
5346
5347 \f
5348 /***********************************************************************
5349 Initialization
5350 ***********************************************************************/
5351
5352 /* Keep this list in the same order as frame_parms in frame.c.
5353 Use 0 for unsupported frame parameters. */
5354
5355 frame_parm_handler x_frame_parm_handlers[] =
5356 {
5357 x_set_autoraise,
5358 x_set_autolower,
5359 x_set_background_color,
5360 x_set_border_color,
5361 x_set_border_width,
5362 x_set_cursor_color,
5363 x_set_cursor_type,
5364 x_set_font,
5365 x_set_foreground_color,
5366 x_set_icon_name,
5367 x_set_icon_type,
5368 x_set_internal_border_width,
5369 x_set_menu_bar_lines,
5370 x_set_mouse_color,
5371 x_explicitly_set_name,
5372 x_set_scroll_bar_width,
5373 x_set_title,
5374 x_set_unsplittable,
5375 x_set_vertical_scroll_bars,
5376 x_set_visibility,
5377 x_set_tool_bar_lines,
5378 x_set_scroll_bar_foreground,
5379 x_set_scroll_bar_background,
5380 x_set_screen_gamma,
5381 x_set_line_spacing,
5382 x_set_fringe_width,
5383 x_set_fringe_width,
5384 x_set_wait_for_wm,
5385 x_set_fullscreen,
5386 };
5387
5388 void
5389 syms_of_xfns ()
5390 {
5391 /* This is zero if not using X windows. */
5392 x_in_use = 0;
5393
5394 /* The section below is built by the lisp expression at the top of the file,
5395 just above where these variables are declared. */
5396 /*&&& init symbols here &&&*/
5397 Qnone = intern ("none");
5398 staticpro (&Qnone);
5399 Qsuppress_icon = intern ("suppress-icon");
5400 staticpro (&Qsuppress_icon);
5401 Qundefined_color = intern ("undefined-color");
5402 staticpro (&Qundefined_color);
5403 Qcompound_text = intern ("compound-text");
5404 staticpro (&Qcompound_text);
5405 Qcancel_timer = intern ("cancel-timer");
5406 staticpro (&Qcancel_timer);
5407 /* This is the end of symbol initialization. */
5408
5409 /* Text property `display' should be nonsticky by default. */
5410 Vtext_property_default_nonsticky
5411 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
5412
5413
5414 Fput (Qundefined_color, Qerror_conditions,
5415 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
5416 Fput (Qundefined_color, Qerror_message,
5417 build_string ("Undefined color"));
5418
5419 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
5420 doc: /* The shape of the pointer when over text.
5421 Changing the value does not affect existing frames
5422 unless you set the mouse color. */);
5423 Vx_pointer_shape = Qnil;
5424
5425 #if 0 /* This doesn't really do anything. */
5426 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
5427 doc: /* The shape of the pointer when not over text.
5428 This variable takes effect when you create a new frame
5429 or when you set the mouse color. */);
5430 #endif
5431 Vx_nontext_pointer_shape = Qnil;
5432
5433 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
5434 doc: /* The shape of the pointer when Emacs is busy.
5435 This variable takes effect when you create a new frame
5436 or when you set the mouse color. */);
5437 Vx_hourglass_pointer_shape = Qnil;
5438
5439 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
5440 doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
5441 display_hourglass_p = 1;
5442
5443 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
5444 doc: /* *Seconds to wait before displaying an hourglass pointer.
5445 Value must be an integer or float. */);
5446 Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
5447
5448 #if 0 /* This doesn't really do anything. */
5449 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
5450 doc: /* The shape of the pointer when over the mode line.
5451 This variable takes effect when you create a new frame
5452 or when you set the mouse color. */);
5453 #endif
5454 Vx_mode_pointer_shape = Qnil;
5455
5456 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
5457 &Vx_sensitive_text_pointer_shape,
5458 doc: /* The shape of the pointer when over mouse-sensitive text.
5459 This variable takes effect when you create a new frame
5460 or when you set the mouse color. */);
5461 Vx_sensitive_text_pointer_shape = Qnil;
5462
5463 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
5464 &Vx_window_horizontal_drag_shape,
5465 doc: /* Pointer shape to use for indicating a window can be dragged horizontally.
5466 This variable takes effect when you create a new frame
5467 or when you set the mouse color. */);
5468 Vx_window_horizontal_drag_shape = Qnil;
5469
5470 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
5471 doc: /* A string indicating the foreground color of the cursor box. */);
5472 Vx_cursor_fore_pixel = Qnil;
5473
5474 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size,
5475 doc: /* Maximum size for tooltips. Value is a pair (COLUMNS . ROWS).
5476 Text larger than this is clipped. */);
5477 Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
5478
5479 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
5480 doc: /* Non-nil if no X window manager is in use.
5481 Emacs doesn't try to figure this out; this is always nil
5482 unless you set it to something else. */);
5483 /* We don't have any way to find this out, so set it to nil
5484 and maybe the user would like to set it to t. */
5485 Vx_no_window_manager = Qnil;
5486
5487 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
5488 &Vx_pixel_size_width_font_regexp,
5489 doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
5490
5491 Since Emacs gets width of a font matching with this regexp from
5492 PIXEL_SIZE field of the name, font finding mechanism gets faster for
5493 such a font. This is especially effective for such large fonts as
5494 Chinese, Japanese, and Korean. */);
5495 Vx_pixel_size_width_font_regexp = Qnil;
5496
5497 #ifdef USE_X_TOOLKIT
5498 Fprovide (intern ("x-toolkit"), Qnil);
5499 #ifdef USE_MOTIF
5500 Fprovide (intern ("motif"), Qnil);
5501
5502 DEFVAR_LISP ("motif-version-string", &Vmotif_version_string,
5503 doc: /* Version info for LessTif/Motif. */);
5504 Vmotif_version_string = build_string (XmVERSION_STRING);
5505 #endif /* USE_MOTIF */
5506 #endif /* USE_X_TOOLKIT */
5507
5508 #ifdef USE_GTK
5509 Fprovide (intern ("gtk"), Qnil);
5510
5511 DEFVAR_LISP ("gtk-version-string", &Vgtk_version_string,
5512 doc: /* Version info for GTK+. */);
5513 {
5514 char gtk_version[40];
5515 g_snprintf (gtk_version, sizeof (gtk_version), "%u.%u.%u",
5516 GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
5517 Vgtk_version_string = build_string (gtk_version);
5518 }
5519 #endif /* USE_GTK */
5520
5521 /* X window properties. */
5522 defsubr (&Sx_change_window_property);
5523 defsubr (&Sx_delete_window_property);
5524 defsubr (&Sx_window_property);
5525
5526 defsubr (&Sxw_display_color_p);
5527 defsubr (&Sx_display_grayscale_p);
5528 defsubr (&Sxw_color_defined_p);
5529 defsubr (&Sxw_color_values);
5530 defsubr (&Sx_server_max_request_size);
5531 defsubr (&Sx_server_vendor);
5532 defsubr (&Sx_server_version);
5533 defsubr (&Sx_display_pixel_width);
5534 defsubr (&Sx_display_pixel_height);
5535 defsubr (&Sx_display_mm_width);
5536 defsubr (&Sx_display_mm_height);
5537 defsubr (&Sx_display_screens);
5538 defsubr (&Sx_display_planes);
5539 defsubr (&Sx_display_color_cells);
5540 defsubr (&Sx_display_visual_class);
5541 defsubr (&Sx_display_backing_store);
5542 defsubr (&Sx_display_save_under);
5543 defsubr (&Sx_create_frame);
5544 defsubr (&Sx_open_connection);
5545 defsubr (&Sx_close_connection);
5546 defsubr (&Sx_display_list);
5547 defsubr (&Sx_synchronize);
5548 defsubr (&Sx_focus_frame);
5549 defsubr (&Sx_backspace_delete_keys_p);
5550
5551 /* Setting callback functions for fontset handler. */
5552 get_font_info_func = x_get_font_info;
5553
5554 #if 0 /* This function pointer doesn't seem to be used anywhere.
5555 And the pointer assigned has the wrong type, anyway. */
5556 list_fonts_func = x_list_fonts;
5557 #endif
5558
5559 load_font_func = x_load_font;
5560 find_ccl_program_func = x_find_ccl_program;
5561 query_font_func = x_query_font;
5562 set_frame_fontset_func = x_set_font;
5563 check_window_system_func = check_x;
5564
5565 hourglass_atimer = NULL;
5566 hourglass_shown_p = 0;
5567
5568 defsubr (&Sx_show_tip);
5569 defsubr (&Sx_hide_tip);
5570 tip_timer = Qnil;
5571 staticpro (&tip_timer);
5572 tip_frame = Qnil;
5573 staticpro (&tip_frame);
5574
5575 last_show_tip_args = Qnil;
5576 staticpro (&last_show_tip_args);
5577
5578 #ifdef USE_MOTIF
5579 defsubr (&Sx_file_dialog);
5580 #endif
5581 }
5582
5583 #endif /* HAVE_X_WINDOWS */
5584
5585 /* arch-tag: 55040d02-5485-4d58-8b22-95a7a05f3288
5586 (do not change this comment) */