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