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