]> 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 /* Verify that the icon position args for this window are valid. */
2647
2648 static void
2649 x_icon_verify (f, parms)
2650 struct frame *f;
2651 Lisp_Object parms;
2652 {
2653 Lisp_Object icon_x, icon_y;
2654
2655 /* Set the position of the icon. Note that twm groups all
2656 icons in an icon window. */
2657 icon_x = x_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
2658 icon_y = x_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
2659 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
2660 {
2661 CHECK_NUMBER (icon_x);
2662 CHECK_NUMBER (icon_y);
2663 }
2664 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
2665 error ("Both left and top icon corners of icon must be specified");
2666 }
2667
2668 /* Handle the icon stuff for this window. Perhaps later we might
2669 want an x_set_icon_position which can be called interactively as
2670 well. */
2671
2672 static void
2673 x_icon (f, parms)
2674 struct frame *f;
2675 Lisp_Object parms;
2676 {
2677 Lisp_Object icon_x, icon_y;
2678 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2679
2680 /* Set the position of the icon. Note that twm groups all
2681 icons in an icon window. */
2682 icon_x = x_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
2683 icon_y = x_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
2684 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
2685 {
2686 CHECK_NUMBER (icon_x);
2687 CHECK_NUMBER (icon_y);
2688 }
2689 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
2690 error ("Both left and top icon corners of icon must be specified");
2691
2692 BLOCK_INPUT;
2693
2694 if (! EQ (icon_x, Qunbound))
2695 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
2696
2697 /* Start up iconic or window? */
2698 x_wm_set_window_state
2699 (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
2700 Qicon)
2701 ? IconicState
2702 : NormalState));
2703
2704 x_text_icon (f, (char *) SDATA ((!NILP (f->icon_name)
2705 ? f->icon_name
2706 : f->name)));
2707
2708 UNBLOCK_INPUT;
2709 }
2710
2711 /* Make the GCs needed for this window, setting the
2712 background, border and mouse colors; also create the
2713 mouse cursor and the gray border tile. */
2714
2715 static char cursor_bits[] =
2716 {
2717 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2718 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2719 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2720 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2721 };
2722
2723 static void
2724 x_make_gc (f)
2725 struct frame *f;
2726 {
2727 XGCValues gc_values;
2728
2729 BLOCK_INPUT;
2730
2731 /* Create the GCs of this frame.
2732 Note that many default values are used. */
2733
2734 /* Normal video */
2735 gc_values.font = FRAME_FONT (f)->fid;
2736 gc_values.foreground = f->output_data.x->foreground_pixel;
2737 gc_values.background = f->output_data.x->background_pixel;
2738 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
2739 f->output_data.x->normal_gc
2740 = XCreateGC (FRAME_X_DISPLAY (f),
2741 FRAME_X_WINDOW (f),
2742 GCLineWidth | GCFont | GCForeground | GCBackground,
2743 &gc_values);
2744
2745 /* Reverse video style. */
2746 gc_values.foreground = f->output_data.x->background_pixel;
2747 gc_values.background = f->output_data.x->foreground_pixel;
2748 f->output_data.x->reverse_gc
2749 = XCreateGC (FRAME_X_DISPLAY (f),
2750 FRAME_X_WINDOW (f),
2751 GCFont | GCForeground | GCBackground | GCLineWidth,
2752 &gc_values);
2753
2754 /* Cursor has cursor-color background, background-color foreground. */
2755 gc_values.foreground = f->output_data.x->background_pixel;
2756 gc_values.background = f->output_data.x->cursor_pixel;
2757 gc_values.fill_style = FillOpaqueStippled;
2758 gc_values.stipple
2759 = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
2760 FRAME_X_DISPLAY_INFO (f)->root_window,
2761 cursor_bits, 16, 16);
2762 f->output_data.x->cursor_gc
2763 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2764 (GCFont | GCForeground | GCBackground
2765 | GCFillStyle /* | GCStipple */ | GCLineWidth),
2766 &gc_values);
2767
2768 /* Reliefs. */
2769 f->output_data.x->white_relief.gc = 0;
2770 f->output_data.x->black_relief.gc = 0;
2771
2772 /* Create the gray border tile used when the pointer is not in
2773 the frame. Since this depends on the frame's pixel values,
2774 this must be done on a per-frame basis. */
2775 f->output_data.x->border_tile
2776 = (XCreatePixmapFromBitmapData
2777 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
2778 gray_bits, gray_width, gray_height,
2779 f->output_data.x->foreground_pixel,
2780 f->output_data.x->background_pixel,
2781 DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
2782
2783 UNBLOCK_INPUT;
2784 }
2785
2786
2787 /* Free what was was allocated in x_make_gc. */
2788
2789 void
2790 x_free_gcs (f)
2791 struct frame *f;
2792 {
2793 Display *dpy = FRAME_X_DISPLAY (f);
2794
2795 BLOCK_INPUT;
2796
2797 if (f->output_data.x->normal_gc)
2798 {
2799 XFreeGC (dpy, f->output_data.x->normal_gc);
2800 f->output_data.x->normal_gc = 0;
2801 }
2802
2803 if (f->output_data.x->reverse_gc)
2804 {
2805 XFreeGC (dpy, f->output_data.x->reverse_gc);
2806 f->output_data.x->reverse_gc = 0;
2807 }
2808
2809 if (f->output_data.x->cursor_gc)
2810 {
2811 XFreeGC (dpy, f->output_data.x->cursor_gc);
2812 f->output_data.x->cursor_gc = 0;
2813 }
2814
2815 if (f->output_data.x->border_tile)
2816 {
2817 XFreePixmap (dpy, f->output_data.x->border_tile);
2818 f->output_data.x->border_tile = 0;
2819 }
2820
2821 UNBLOCK_INPUT;
2822 }
2823
2824
2825 /* Handler for signals raised during x_create_frame and
2826 x_create_top_frame. FRAME is the frame which is partially
2827 constructed. */
2828
2829 static Lisp_Object
2830 unwind_create_frame (frame)
2831 Lisp_Object frame;
2832 {
2833 struct frame *f = XFRAME (frame);
2834
2835 /* If frame is ``official'', nothing to do. */
2836 if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
2837 {
2838 #if GLYPH_DEBUG
2839 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2840 #endif
2841
2842 x_free_frame_resources (f);
2843
2844 /* Check that reference counts are indeed correct. */
2845 xassert (dpyinfo->reference_count == dpyinfo_refcount);
2846 xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
2847 return Qt;
2848 }
2849
2850 return Qnil;
2851 }
2852
2853
2854 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
2855 1, 1, 0,
2856 doc: /* Make a new X window, which is called a "frame" in Emacs terms.
2857 Returns an Emacs frame object.
2858 ALIST is an alist of frame parameters.
2859 If the parameters specify that the frame should not have a minibuffer,
2860 and do not specify a specific minibuffer window to use,
2861 then `default-minibuffer-frame' must be a frame whose minibuffer can
2862 be shared by the new frame.
2863
2864 This function is an internal primitive--use `make-frame' instead. */)
2865 (parms)
2866 Lisp_Object parms;
2867 {
2868 struct frame *f;
2869 Lisp_Object frame, tem;
2870 Lisp_Object name;
2871 int minibuffer_only = 0;
2872 long window_prompting = 0;
2873 int width, height;
2874 int count = SPECPDL_INDEX ();
2875 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2876 Lisp_Object display;
2877 struct x_display_info *dpyinfo = NULL;
2878 Lisp_Object parent;
2879 struct kboard *kb;
2880
2881 /* Use this general default value to start with
2882 until we know if this frame has a specified name. */
2883 Vx_resource_name = Vinvocation_name;
2884
2885 display = x_get_arg (dpyinfo, parms, Qdisplay_id, 0, 0, RES_TYPE_NUMBER);
2886 if (EQ (display, Qunbound))
2887 display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
2888 if (EQ (display, Qunbound))
2889 display = Qnil;
2890 dpyinfo = check_x_display_info (display);
2891 #ifdef MULTI_KBOARD
2892 kb = dpyinfo->kboard;
2893 #else
2894 kb = &the_only_kboard;
2895 #endif
2896
2897 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
2898 if (!STRINGP (name)
2899 && ! EQ (name, Qunbound)
2900 && ! NILP (name))
2901 error ("Invalid frame name--not a string or nil");
2902
2903 if (STRINGP (name))
2904 Vx_resource_name = name;
2905
2906 /* See if parent window is specified. */
2907 parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
2908 if (EQ (parent, Qunbound))
2909 parent = Qnil;
2910 if (! NILP (parent))
2911 CHECK_NUMBER (parent);
2912
2913 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
2914 /* No need to protect DISPLAY because that's not used after passing
2915 it to make_frame_without_minibuffer. */
2916 frame = Qnil;
2917 GCPRO4 (parms, parent, name, frame);
2918 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
2919 RES_TYPE_SYMBOL);
2920 if (EQ (tem, Qnone) || NILP (tem))
2921 f = make_frame_without_minibuffer (Qnil, kb, display);
2922 else if (EQ (tem, Qonly))
2923 {
2924 f = make_minibuffer_frame ();
2925 minibuffer_only = 1;
2926 }
2927 else if (WINDOWP (tem))
2928 f = make_frame_without_minibuffer (tem, kb, display);
2929 else
2930 f = make_frame (1);
2931
2932 XSETFRAME (frame, f);
2933
2934 /* Note that X Windows does support scroll bars. */
2935 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
2936
2937 f->display = dpyinfo->frame_display;
2938 f->display->reference_count++;
2939
2940 f->output_method = output_x_window;
2941 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
2942 bzero (f->output_data.x, sizeof (struct x_output));
2943 f->output_data.x->icon_bitmap = -1;
2944 FRAME_FONTSET (f) = -1;
2945 f->output_data.x->scroll_bar_foreground_pixel = -1;
2946 f->output_data.x->scroll_bar_background_pixel = -1;
2947 #ifdef USE_TOOLKIT_SCROLL_BARS
2948 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
2949 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
2950 #endif /* USE_TOOLKIT_SCROLL_BARS */
2951 record_unwind_protect (unwind_create_frame, frame);
2952
2953 f->icon_name
2954 = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
2955 RES_TYPE_STRING);
2956 if (! STRINGP (f->icon_name))
2957 f->icon_name = Qnil;
2958
2959 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
2960 #if GLYPH_DEBUG
2961 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
2962 dpyinfo_refcount = dpyinfo->reference_count;
2963 #endif /* GLYPH_DEBUG */
2964 #ifdef MULTI_KBOARD
2965 FRAME_KBOARD (f) = kb;
2966 #endif
2967
2968 /* These colors will be set anyway later, but it's important
2969 to get the color reference counts right, so initialize them! */
2970 {
2971 Lisp_Object black;
2972 struct gcpro gcpro1;
2973
2974 /* Function x_decode_color can signal an error. Make
2975 sure to initialize color slots so that we won't try
2976 to free colors we haven't allocated. */
2977 f->output_data.x->foreground_pixel = -1;
2978 f->output_data.x->background_pixel = -1;
2979 f->output_data.x->cursor_pixel = -1;
2980 f->output_data.x->cursor_foreground_pixel = -1;
2981 f->output_data.x->border_pixel = -1;
2982 f->output_data.x->mouse_pixel = -1;
2983
2984 black = build_string ("black");
2985 GCPRO1 (black);
2986 f->output_data.x->foreground_pixel
2987 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
2988 f->output_data.x->background_pixel
2989 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
2990 f->output_data.x->cursor_pixel
2991 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
2992 f->output_data.x->cursor_foreground_pixel
2993 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
2994 f->output_data.x->border_pixel
2995 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
2996 f->output_data.x->mouse_pixel
2997 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
2998 UNGCPRO;
2999 }
3000
3001 /* Specify the parent under which to make this X window. */
3002
3003 if (!NILP (parent))
3004 {
3005 f->output_data.x->parent_desc = (Window) XFASTINT (parent);
3006 f->output_data.x->explicit_parent = 1;
3007 }
3008 else
3009 {
3010 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
3011 f->output_data.x->explicit_parent = 0;
3012 }
3013
3014 /* Set the name; the functions to which we pass f expect the name to
3015 be set. */
3016 if (EQ (name, Qunbound) || NILP (name))
3017 {
3018 f->name = build_string (dpyinfo->x_id_name);
3019 f->explicit_name = 0;
3020 }
3021 else
3022 {
3023 f->name = name;
3024 f->explicit_name = 1;
3025 /* use the frame's title when getting resources for this frame. */
3026 specbind (Qx_resource_name, name);
3027 }
3028
3029 Fmodify_frame_parameters (frame, Fcons (Fcons (Qwindow_system, Qx), Qnil));
3030
3031 /* Extract the window parameters from the supplied values
3032 that are needed to determine window geometry. */
3033 {
3034 Lisp_Object font;
3035
3036 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
3037
3038 BLOCK_INPUT;
3039 /* First, try whatever font the caller has specified. */
3040 if (STRINGP (font))
3041 {
3042 tem = Fquery_fontset (font, Qnil);
3043 if (STRINGP (tem))
3044 font = x_new_fontset (f, SDATA (tem));
3045 else
3046 font = x_new_font (f, SDATA (font));
3047 }
3048
3049 /* Try out a font which we hope has bold and italic variations. */
3050 if (!STRINGP (font))
3051 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
3052 if (!STRINGP (font))
3053 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3054 if (! STRINGP (font))
3055 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3056 if (! STRINGP (font))
3057 /* This was formerly the first thing tried, but it finds too many fonts
3058 and takes too long. */
3059 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
3060 /* If those didn't work, look for something which will at least work. */
3061 if (! STRINGP (font))
3062 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
3063 UNBLOCK_INPUT;
3064 if (! STRINGP (font))
3065 font = build_string ("fixed");
3066
3067 x_default_parameter (f, parms, Qfont, font,
3068 "font", "Font", RES_TYPE_STRING);
3069 }
3070
3071 #ifdef USE_LUCID
3072 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
3073 whereby it fails to get any font. */
3074 xlwmenu_default_font = FRAME_FONT (f);
3075 #endif
3076
3077 x_default_parameter (f, parms, Qborder_width, make_number (2),
3078 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
3079
3080 /* This defaults to 1 in order to match xterm. We recognize either
3081 internalBorderWidth or internalBorder (which is what xterm calls
3082 it). */
3083 if (NILP (Fassq (Qinternal_border_width, parms)))
3084 {
3085 Lisp_Object value;
3086
3087 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
3088 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
3089 if (! EQ (value, Qunbound))
3090 parms = Fcons (Fcons (Qinternal_border_width, value),
3091 parms);
3092 }
3093 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
3094 "internalBorderWidth", "internalBorderWidth",
3095 RES_TYPE_NUMBER);
3096 x_default_parameter (f, parms, Qvertical_scroll_bars, Qleft,
3097 "verticalScrollBars", "ScrollBars",
3098 RES_TYPE_SYMBOL);
3099
3100 /* Also do the stuff which must be set before the window exists. */
3101 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
3102 "foreground", "Foreground", RES_TYPE_STRING);
3103 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
3104 "background", "Background", RES_TYPE_STRING);
3105 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
3106 "pointerColor", "Foreground", RES_TYPE_STRING);
3107 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
3108 "cursorColor", "Foreground", RES_TYPE_STRING);
3109 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
3110 "borderColor", "BorderColor", RES_TYPE_STRING);
3111 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
3112 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
3113 x_default_parameter (f, parms, Qline_spacing, Qnil,
3114 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
3115 x_default_parameter (f, parms, Qleft_fringe, Qnil,
3116 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
3117 x_default_parameter (f, parms, Qright_fringe, Qnil,
3118 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
3119
3120 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
3121 "scrollBarForeground",
3122 "ScrollBarForeground", 1);
3123 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
3124 "scrollBarBackground",
3125 "ScrollBarBackground", 0);
3126
3127 /* Init faces before x_default_parameter is called for scroll-bar
3128 parameters because that function calls x_set_scroll_bar_width,
3129 which calls change_frame_size, which calls Fset_window_buffer,
3130 which runs hooks, which call Fvertical_motion. At the end, we
3131 end up in init_iterator with a null face cache, which should not
3132 happen. */
3133 init_frame_faces (f);
3134
3135 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
3136 "menuBar", "MenuBar", RES_TYPE_NUMBER);
3137 x_default_parameter (f, parms, Qtool_bar_lines, make_number (1),
3138 "toolBar", "ToolBar", RES_TYPE_NUMBER);
3139 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
3140 "bufferPredicate", "BufferPredicate",
3141 RES_TYPE_SYMBOL);
3142 x_default_parameter (f, parms, Qtitle, Qnil,
3143 "title", "Title", RES_TYPE_STRING);
3144 x_default_parameter (f, parms, Qwait_for_wm, Qt,
3145 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
3146 x_default_parameter (f, parms, Qfullscreen, Qnil,
3147 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
3148
3149 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
3150
3151 /* Compute the size of the X window. */
3152 window_prompting = x_figure_window_size (f, parms, 1);
3153
3154 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
3155 f->no_split = minibuffer_only || EQ (tem, Qt);
3156
3157 x_icon_verify (f, parms);
3158
3159 /* Create the X widget or window. */
3160 #ifdef USE_X_TOOLKIT
3161 x_window (f, window_prompting, minibuffer_only);
3162 #else
3163 x_window (f);
3164 #endif
3165
3166 x_icon (f, parms);
3167 x_make_gc (f);
3168
3169 /* Now consider the frame official. */
3170 FRAME_X_DISPLAY_INFO (f)->reference_count++;
3171 Vframe_list = Fcons (frame, Vframe_list);
3172
3173 /* We need to do this after creating the X window, so that the
3174 icon-creation functions can say whose icon they're describing. */
3175 x_default_parameter (f, parms, Qicon_type, Qnil,
3176 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
3177
3178 x_default_parameter (f, parms, Qauto_raise, Qnil,
3179 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
3180 x_default_parameter (f, parms, Qauto_lower, Qnil,
3181 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
3182 x_default_parameter (f, parms, Qcursor_type, Qbox,
3183 "cursorType", "CursorType", RES_TYPE_SYMBOL);
3184 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
3185 "scrollBarWidth", "ScrollBarWidth",
3186 RES_TYPE_NUMBER);
3187
3188 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
3189 Change will not be effected unless different from the current
3190 FRAME_LINES (f). */
3191 width = FRAME_COLS (f);
3192 height = FRAME_LINES (f);
3193
3194 SET_FRAME_COLS (f, 0);
3195 FRAME_LINES (f) = 0;
3196 change_frame_size (f, height, width, 1, 0, 0);
3197
3198 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
3199 /* Create the menu bar. */
3200 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
3201 {
3202 /* If this signals an error, we haven't set size hints for the
3203 frame and we didn't make it visible. */
3204 initialize_frame_menubar (f);
3205
3206 #ifndef USE_GTK
3207 /* This is a no-op, except under Motif where it arranges the
3208 main window for the widgets on it. */
3209 lw_set_main_areas (f->output_data.x->column_widget,
3210 f->output_data.x->menubar_widget,
3211 f->output_data.x->edit_widget);
3212 #endif /* not USE_GTK */
3213 }
3214 #endif /* USE_X_TOOLKIT || USE_GTK */
3215
3216 /* Tell the server what size and position, etc, we want, and how
3217 badly we want them. This should be done after we have the menu
3218 bar so that its size can be taken into account. */
3219 BLOCK_INPUT;
3220 x_wm_set_size_hint (f, window_prompting, 0);
3221 UNBLOCK_INPUT;
3222
3223 /* Make the window appear on the frame and enable display, unless
3224 the caller says not to. However, with explicit parent, Emacs
3225 cannot control visibility, so don't try. */
3226 if (! f->output_data.x->explicit_parent)
3227 {
3228 Lisp_Object visibility;
3229
3230 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
3231 RES_TYPE_SYMBOL);
3232 if (EQ (visibility, Qunbound))
3233 visibility = Qt;
3234
3235 if (EQ (visibility, Qicon))
3236 x_iconify_frame (f);
3237 else if (! NILP (visibility))
3238 x_make_frame_visible (f);
3239 else
3240 /* Must have been Qnil. */
3241 ;
3242 }
3243
3244 /* Set the WM leader property. GTK does this itself, so this is not
3245 needed when using GTK. */
3246 if (dpyinfo->client_leader_window != 0)
3247 {
3248 BLOCK_INPUT;
3249 XChangeProperty (FRAME_X_DISPLAY (f),
3250 FRAME_OUTER_WINDOW (f),
3251 dpyinfo->Xatom_wm_client_leader,
3252 XA_WINDOW, 32, PropModeReplace,
3253 (char *) &dpyinfo->client_leader_window, 1);
3254 UNBLOCK_INPUT;
3255 }
3256
3257 UNGCPRO;
3258
3259 /* Make sure windows on this frame appear in calls to next-window
3260 and similar functions. */
3261 Vwindow_list = Qnil;
3262
3263 return unbind_to (count, frame);
3264 }
3265
3266
3267 /* FRAME is used only to get a handle on the X display. We don't pass the
3268 display info directly because we're called from frame.c, which doesn't
3269 know about that structure. */
3270
3271 Lisp_Object
3272 x_get_focus_frame (frame)
3273 struct frame *frame;
3274 {
3275 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
3276 Lisp_Object xfocus;
3277 if (! dpyinfo->x_focus_frame)
3278 return Qnil;
3279
3280 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
3281 return xfocus;
3282 }
3283
3284
3285 /* In certain situations, when the window manager follows a
3286 click-to-focus policy, there seems to be no way around calling
3287 XSetInputFocus to give another frame the input focus .
3288
3289 In an ideal world, XSetInputFocus should generally be avoided so
3290 that applications don't interfere with the window manager's focus
3291 policy. But I think it's okay to use when it's clearly done
3292 following a user-command. */
3293
3294 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
3295 doc: /* Set the input focus to FRAME.
3296 FRAME nil means use the selected frame. */)
3297 (frame)
3298 Lisp_Object frame;
3299 {
3300 struct frame *f = check_x_frame (frame);
3301 Display *dpy = FRAME_X_DISPLAY (f);
3302 int count;
3303
3304 BLOCK_INPUT;
3305 count = x_catch_errors (dpy);
3306 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3307 RevertToParent, CurrentTime);
3308 x_uncatch_errors (dpy, count);
3309 UNBLOCK_INPUT;
3310
3311 return Qnil;
3312 }
3313
3314 \f
3315 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
3316 doc: /* Internal function called by `color-defined-p', which see. */)
3317 (color, frame)
3318 Lisp_Object color, frame;
3319 {
3320 XColor foo;
3321 FRAME_PTR f = check_x_frame (frame);
3322
3323 CHECK_STRING (color);
3324
3325 if (x_defined_color (f, SDATA (color), &foo, 0))
3326 return Qt;
3327 else
3328 return Qnil;
3329 }
3330
3331 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
3332 doc: /* Internal function called by `color-values', which see. */)
3333 (color, frame)
3334 Lisp_Object color, frame;
3335 {
3336 XColor foo;
3337 FRAME_PTR f = check_x_frame (frame);
3338
3339 CHECK_STRING (color);
3340
3341 if (x_defined_color (f, SDATA (color), &foo, 0))
3342 {
3343 Lisp_Object rgb[3];
3344
3345 rgb[0] = make_number (foo.red);
3346 rgb[1] = make_number (foo.green);
3347 rgb[2] = make_number (foo.blue);
3348 return Flist (3, rgb);
3349 }
3350 else
3351 return Qnil;
3352 }
3353
3354 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
3355 doc: /* Internal function called by `display-color-p', which see. */)
3356 (display)
3357 Lisp_Object display;
3358 {
3359 struct x_display_info *dpyinfo = check_x_display_info (display);
3360
3361 if (dpyinfo->n_planes <= 2)
3362 return Qnil;
3363
3364 switch (dpyinfo->visual->class)
3365 {
3366 case StaticColor:
3367 case PseudoColor:
3368 case TrueColor:
3369 case DirectColor:
3370 return Qt;
3371
3372 default:
3373 return Qnil;
3374 }
3375 }
3376
3377 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
3378 0, 1, 0,
3379 doc: /* Return t if the X display supports shades of gray.
3380 Note that color displays do support shades of gray.
3381 The optional argument DISPLAY specifies which display to ask about.
3382 DISPLAY should be either a frame or a display name (a string).
3383 If omitted or nil, that stands for the selected frame's display. */)
3384 (display)
3385 Lisp_Object display;
3386 {
3387 struct x_display_info *dpyinfo = check_x_display_info (display);
3388
3389 if (dpyinfo->n_planes <= 1)
3390 return Qnil;
3391
3392 switch (dpyinfo->visual->class)
3393 {
3394 case StaticColor:
3395 case PseudoColor:
3396 case TrueColor:
3397 case DirectColor:
3398 case StaticGray:
3399 case GrayScale:
3400 return Qt;
3401
3402 default:
3403 return Qnil;
3404 }
3405 }
3406
3407 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
3408 0, 1, 0,
3409 doc: /* Returns the width in pixels of the X display DISPLAY.
3410 The optional argument DISPLAY specifies which display to ask about.
3411 DISPLAY should be either a frame or a display name (a string).
3412 If omitted or nil, that stands for the selected frame's display. */)
3413 (display)
3414 Lisp_Object display;
3415 {
3416 struct x_display_info *dpyinfo = check_x_display_info (display);
3417
3418 return make_number (dpyinfo->width);
3419 }
3420
3421 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
3422 Sx_display_pixel_height, 0, 1, 0,
3423 doc: /* Returns the height in pixels of the X display DISPLAY.
3424 The optional argument DISPLAY specifies which display to ask about.
3425 DISPLAY should be either a frame or a display name (a string).
3426 If omitted or nil, that stands for the selected frame's display. */)
3427 (display)
3428 Lisp_Object display;
3429 {
3430 struct x_display_info *dpyinfo = check_x_display_info (display);
3431
3432 return make_number (dpyinfo->height);
3433 }
3434
3435 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
3436 0, 1, 0,
3437 doc: /* Returns the number of bitplanes of the X display DISPLAY.
3438 The optional argument DISPLAY specifies which display to ask about.
3439 DISPLAY should be either a frame or a display name (a string).
3440 If omitted or nil, that stands for the selected frame's display. */)
3441 (display)
3442 Lisp_Object display;
3443 {
3444 struct x_display_info *dpyinfo = check_x_display_info (display);
3445
3446 return make_number (dpyinfo->n_planes);
3447 }
3448
3449 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
3450 0, 1, 0,
3451 doc: /* Returns the number of color cells of the X display DISPLAY.
3452 The optional argument DISPLAY specifies which display to ask about.
3453 DISPLAY should be either a frame or a display name (a string).
3454 If omitted or nil, that stands for the selected frame's display. */)
3455 (display)
3456 Lisp_Object display;
3457 {
3458 struct x_display_info *dpyinfo = check_x_display_info (display);
3459
3460 int nr_planes = DisplayPlanes (dpyinfo->display,
3461 XScreenNumberOfScreen (dpyinfo->screen));
3462
3463 /* Truncate nr_planes to 24 to avoid integer overflow.
3464 Some displays says 32, but only 24 bits are actually significant.
3465 There are only very few and rare video cards that have more than
3466 24 significant bits. Also 24 bits is more than 16 million colors,
3467 it "should be enough for everyone". */
3468 if (nr_planes > 24) nr_planes = 24;
3469
3470 return make_number (1 << nr_planes);
3471 }
3472
3473 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
3474 Sx_server_max_request_size,
3475 0, 1, 0,
3476 doc: /* Returns the maximum request size of the X server of display DISPLAY.
3477 The optional argument DISPLAY specifies which display to ask about.
3478 DISPLAY should be either a frame or a display name (a string).
3479 If omitted or nil, that stands for the selected frame's display. */)
3480 (display)
3481 Lisp_Object display;
3482 {
3483 struct x_display_info *dpyinfo = check_x_display_info (display);
3484
3485 return make_number (MAXREQUEST (dpyinfo->display));
3486 }
3487
3488 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
3489 doc: /* Returns the vendor ID string of the X server of display DISPLAY.
3490 The optional argument DISPLAY specifies which display to ask about.
3491 DISPLAY should be either a frame or a display name (a string).
3492 If omitted or nil, that stands for the selected frame's display. */)
3493 (display)
3494 Lisp_Object display;
3495 {
3496 struct x_display_info *dpyinfo = check_x_display_info (display);
3497 char *vendor = ServerVendor (dpyinfo->display);
3498
3499 if (! vendor) vendor = "";
3500 return build_string (vendor);
3501 }
3502
3503 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
3504 doc: /* Returns the version numbers of the X server of display DISPLAY.
3505 The value is a list of three integers: the major and minor
3506 version numbers of the X Protocol in use, and the vendor-specific release
3507 number. See also the function `x-server-vendor'.
3508
3509 The optional argument DISPLAY specifies which display to ask about.
3510 DISPLAY should be either a frame or a display name (a string).
3511 If omitted or nil, that stands for the selected frame's display. */)
3512 (display)
3513 Lisp_Object display;
3514 {
3515 struct x_display_info *dpyinfo = check_x_display_info (display);
3516 Display *dpy = dpyinfo->display;
3517
3518 return Fcons (make_number (ProtocolVersion (dpy)),
3519 Fcons (make_number (ProtocolRevision (dpy)),
3520 Fcons (make_number (VendorRelease (dpy)), Qnil)));
3521 }
3522
3523 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
3524 doc: /* Return the number of screens on the X server of display DISPLAY.
3525 The optional argument DISPLAY specifies which display to ask about.
3526 DISPLAY should be either a frame or a display name (a string).
3527 If omitted or nil, that stands for the selected frame's display. */)
3528 (display)
3529 Lisp_Object display;
3530 {
3531 struct x_display_info *dpyinfo = check_x_display_info (display);
3532
3533 return make_number (ScreenCount (dpyinfo->display));
3534 }
3535
3536 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
3537 doc: /* Return the height in millimeters of the X display DISPLAY.
3538 The optional argument DISPLAY specifies which display to ask about.
3539 DISPLAY should be either a frame or a display name (a string).
3540 If omitted or nil, that stands for the selected frame's display. */)
3541 (display)
3542 Lisp_Object display;
3543 {
3544 struct x_display_info *dpyinfo = check_x_display_info (display);
3545
3546 return make_number (HeightMMOfScreen (dpyinfo->screen));
3547 }
3548
3549 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
3550 doc: /* Return the width in millimeters of the X display DISPLAY.
3551 The optional argument DISPLAY specifies which display to ask about.
3552 DISPLAY should be either a frame or a display name (a string).
3553 If omitted or nil, that stands for the selected frame's display. */)
3554 (display)
3555 Lisp_Object display;
3556 {
3557 struct x_display_info *dpyinfo = check_x_display_info (display);
3558
3559 return make_number (WidthMMOfScreen (dpyinfo->screen));
3560 }
3561
3562 DEFUN ("x-display-backing-store", Fx_display_backing_store,
3563 Sx_display_backing_store, 0, 1, 0,
3564 doc: /* Returns an indication of whether X display DISPLAY does backing store.
3565 The value may be `always', `when-mapped', or `not-useful'.
3566 The optional argument DISPLAY specifies which display to ask about.
3567 DISPLAY should be either a frame or a display name (a string).
3568 If omitted or nil, that stands for the selected frame's display. */)
3569 (display)
3570 Lisp_Object display;
3571 {
3572 struct x_display_info *dpyinfo = check_x_display_info (display);
3573 Lisp_Object result;
3574
3575 switch (DoesBackingStore (dpyinfo->screen))
3576 {
3577 case Always:
3578 result = intern ("always");
3579 break;
3580
3581 case WhenMapped:
3582 result = intern ("when-mapped");
3583 break;
3584
3585 case NotUseful:
3586 result = intern ("not-useful");
3587 break;
3588
3589 default:
3590 error ("Strange value for BackingStore parameter of screen");
3591 result = Qnil;
3592 }
3593
3594 return result;
3595 }
3596
3597 DEFUN ("x-display-visual-class", Fx_display_visual_class,
3598 Sx_display_visual_class, 0, 1, 0,
3599 doc: /* Return the visual class of the X display DISPLAY.
3600 The value is one of the symbols `static-gray', `gray-scale',
3601 `static-color', `pseudo-color', `true-color', or `direct-color'.
3602
3603 The optional argument DISPLAY specifies which display to ask about.
3604 DISPLAY should be either a frame or a display name (a string).
3605 If omitted or nil, that stands for the selected frame's display. */)
3606 (display)
3607 Lisp_Object display;
3608 {
3609 struct x_display_info *dpyinfo = check_x_display_info (display);
3610 Lisp_Object result;
3611
3612 switch (dpyinfo->visual->class)
3613 {
3614 case StaticGray:
3615 result = intern ("static-gray");
3616 break;
3617 case GrayScale:
3618 result = intern ("gray-scale");
3619 break;
3620 case StaticColor:
3621 result = intern ("static-color");
3622 break;
3623 case PseudoColor:
3624 result = intern ("pseudo-color");
3625 break;
3626 case TrueColor:
3627 result = intern ("true-color");
3628 break;
3629 case DirectColor:
3630 result = intern ("direct-color");
3631 break;
3632 default:
3633 error ("Display has an unknown visual class");
3634 result = Qnil;
3635 }
3636
3637 return result;
3638 }
3639
3640 DEFUN ("x-display-save-under", Fx_display_save_under,
3641 Sx_display_save_under, 0, 1, 0,
3642 doc: /* Returns t if the X display DISPLAY supports the save-under feature.
3643 The optional argument DISPLAY specifies which display to ask about.
3644 DISPLAY should be either a frame or a display name (a string).
3645 If omitted or nil, that stands for the selected frame's display. */)
3646 (display)
3647 Lisp_Object display;
3648 {
3649 struct x_display_info *dpyinfo = check_x_display_info (display);
3650
3651 if (DoesSaveUnders (dpyinfo->screen) == True)
3652 return Qt;
3653 else
3654 return Qnil;
3655 }
3656 \f
3657 int
3658 x_pixel_width (f)
3659 register struct frame *f;
3660 {
3661 return FRAME_PIXEL_WIDTH (f);
3662 }
3663
3664 int
3665 x_pixel_height (f)
3666 register struct frame *f;
3667 {
3668 return FRAME_PIXEL_HEIGHT (f);
3669 }
3670
3671 int
3672 x_char_width (f)
3673 register struct frame *f;
3674 {
3675 return FRAME_COLUMN_WIDTH (f);
3676 }
3677
3678 int
3679 x_char_height (f)
3680 register struct frame *f;
3681 {
3682 return FRAME_LINE_HEIGHT (f);
3683 }
3684
3685 int
3686 x_screen_planes (f)
3687 register struct frame *f;
3688 {
3689 return FRAME_X_DISPLAY_INFO (f)->n_planes;
3690 }
3691
3692
3693 \f
3694 /************************************************************************
3695 X Displays
3696 ************************************************************************/
3697
3698 \f
3699 /* Mapping visual names to visuals. */
3700
3701 static struct visual_class
3702 {
3703 char *name;
3704 int class;
3705 }
3706 visual_classes[] =
3707 {
3708 {"StaticGray", StaticGray},
3709 {"GrayScale", GrayScale},
3710 {"StaticColor", StaticColor},
3711 {"PseudoColor", PseudoColor},
3712 {"TrueColor", TrueColor},
3713 {"DirectColor", DirectColor},
3714 {NULL, 0}
3715 };
3716
3717
3718 #ifndef HAVE_XSCREENNUMBEROFSCREEN
3719
3720 /* Value is the screen number of screen SCR. This is a substitute for
3721 the X function with the same name when that doesn't exist. */
3722
3723 int
3724 XScreenNumberOfScreen (scr)
3725 register Screen *scr;
3726 {
3727 Display *dpy = scr->display;
3728 int i;
3729
3730 for (i = 0; i < dpy->nscreens; ++i)
3731 if (scr == dpy->screens + i)
3732 break;
3733
3734 return i;
3735 }
3736
3737 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
3738
3739
3740 /* Select the visual that should be used on display DPYINFO. Set
3741 members of DPYINFO appropriately. Called from x_term_init. */
3742
3743 void
3744 select_visual (dpyinfo)
3745 struct x_display_info *dpyinfo;
3746 {
3747 Display *dpy = dpyinfo->display;
3748 Screen *screen = dpyinfo->screen;
3749 Lisp_Object value;
3750
3751 /* See if a visual is specified. */
3752 value = display_x_get_resource (dpyinfo,
3753 build_string ("visualClass"),
3754 build_string ("VisualClass"),
3755 Qnil, Qnil);
3756 if (STRINGP (value))
3757 {
3758 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
3759 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
3760 depth, a decimal number. NAME is compared with case ignored. */
3761 char *s = (char *) alloca (SBYTES (value) + 1);
3762 char *dash;
3763 int i, class = -1;
3764 XVisualInfo vinfo;
3765
3766 strcpy (s, SDATA (value));
3767 dash = index (s, '-');
3768 if (dash)
3769 {
3770 dpyinfo->n_planes = atoi (dash + 1);
3771 *dash = '\0';
3772 }
3773 else
3774 /* We won't find a matching visual with depth 0, so that
3775 an error will be printed below. */
3776 dpyinfo->n_planes = 0;
3777
3778 /* Determine the visual class. */
3779 for (i = 0; visual_classes[i].name; ++i)
3780 if (xstricmp (s, visual_classes[i].name) == 0)
3781 {
3782 class = visual_classes[i].class;
3783 break;
3784 }
3785
3786 /* Look up a matching visual for the specified class. */
3787 if (class == -1
3788 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
3789 dpyinfo->n_planes, class, &vinfo))
3790 fatal ("Invalid visual specification `%s'", SDATA (value));
3791
3792 dpyinfo->visual = vinfo.visual;
3793 }
3794 else
3795 {
3796 int n_visuals;
3797 XVisualInfo *vinfo, vinfo_template;
3798
3799 dpyinfo->visual = DefaultVisualOfScreen (screen);
3800
3801 #ifdef HAVE_X11R4
3802 vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
3803 #else
3804 vinfo_template.visualid = dpyinfo->visual->visualid;
3805 #endif
3806 vinfo_template.screen = XScreenNumberOfScreen (screen);
3807 vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
3808 &vinfo_template, &n_visuals);
3809 if (n_visuals != 1)
3810 fatal ("Can't get proper X visual info");
3811
3812 dpyinfo->n_planes = vinfo->depth;
3813 XFree ((char *) vinfo);
3814 }
3815 }
3816
3817
3818 /* Return the X display structure for the display named NAME.
3819 Open a new connection if necessary. */
3820
3821 struct x_display_info *
3822 x_display_info_for_name (name)
3823 Lisp_Object name;
3824 {
3825 Lisp_Object names;
3826 struct x_display_info *dpyinfo;
3827
3828 CHECK_STRING (name);
3829
3830 #if 0
3831 if (! EQ (Vinitial_window_system, intern ("x")))
3832 error ("Not using X Windows"); /* That doesn't stop us anymore. */
3833 #endif
3834
3835 for (dpyinfo = x_display_list, names = x_display_name_list;
3836 dpyinfo;
3837 dpyinfo = dpyinfo->next, names = XCDR (names))
3838 {
3839 Lisp_Object tem;
3840 tem = Fstring_equal (XCAR (XCAR (names)), name);
3841 if (!NILP (tem))
3842 return dpyinfo;
3843 }
3844
3845 /* Use this general default value to start with. */
3846 Vx_resource_name = Vinvocation_name;
3847
3848 validate_x_resource_name ();
3849
3850 dpyinfo = x_term_init (name, (char *)0,
3851 (char *) SDATA (Vx_resource_name));
3852
3853 if (dpyinfo == 0)
3854 error ("Cannot connect to X server %s", SDATA (name));
3855
3856 x_in_use = 1;
3857 XSETFASTINT (Vwindow_system_version, 11);
3858
3859 return dpyinfo;
3860 }
3861
3862
3863 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
3864 1, 3, 0,
3865 doc: /* Open a connection to an X server.
3866 DISPLAY is the name of the display to connect to.
3867 Optional second arg XRM-STRING is a string of resources in xrdb format.
3868 If the optional third arg MUST-SUCCEED is non-nil,
3869 terminate Emacs if we can't open the connection. */)
3870 (display, xrm_string, must_succeed)
3871 Lisp_Object display, xrm_string, must_succeed;
3872 {
3873 unsigned char *xrm_option;
3874 struct x_display_info *dpyinfo;
3875
3876 CHECK_STRING (display);
3877 if (! NILP (xrm_string))
3878 CHECK_STRING (xrm_string);
3879
3880 #if 0
3881 if (! EQ (Vinitial_window_system, intern ("x")))
3882 error ("Not using X Windows"); /* That doesn't stop us anymore. */
3883 #endif
3884
3885 if (! NILP (xrm_string))
3886 xrm_option = (unsigned char *) SDATA (xrm_string);
3887 else
3888 xrm_option = (unsigned char *) 0;
3889
3890 validate_x_resource_name ();
3891
3892 /* This is what opens the connection and sets x_current_display.
3893 This also initializes many symbols, such as those used for input. */
3894 dpyinfo = x_term_init (display, xrm_option,
3895 (char *) SDATA (Vx_resource_name));
3896
3897 if (dpyinfo == 0)
3898 {
3899 if (!NILP (must_succeed))
3900 fatal ("Cannot connect to X server %s.\n\
3901 Check the DISPLAY environment variable or use `-d'.\n\
3902 Also use the `xauth' program to verify that you have the proper\n\
3903 authorization information needed to connect the X server.\n\
3904 An insecure way to solve the problem may be to use `xhost'.\n",
3905 SDATA (display));
3906 else
3907 error ("Cannot connect to X server %s", SDATA (display));
3908 }
3909
3910 x_in_use = 1;
3911
3912 XSETFASTINT (Vwindow_system_version, 11);
3913 return Qnil;
3914 }
3915
3916 DEFUN ("x-close-connection", Fx_close_connection,
3917 Sx_close_connection, 1, 1, 0,
3918 doc: /* Close the connection to DISPLAY's X server.
3919 For DISPLAY, specify either a frame or a display name (a string).
3920 If DISPLAY is nil, that stands for the selected frame's display. */)
3921 (display)
3922 Lisp_Object display;
3923 {
3924 struct x_display_info *dpyinfo = check_x_display_info (display);
3925 int i;
3926
3927 if (dpyinfo->reference_count > 0)
3928 error ("Display still has frames on it");
3929
3930 BLOCK_INPUT;
3931 /* Free the fonts in the font table. */
3932 for (i = 0; i < dpyinfo->n_fonts; i++)
3933 if (dpyinfo->font_table[i].name)
3934 {
3935 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
3936 }
3937
3938 x_destroy_all_bitmaps (dpyinfo);
3939 XSetCloseDownMode (dpyinfo->display, DestroyAll);
3940
3941 #ifdef USE_X_TOOLKIT
3942 XtCloseDisplay (dpyinfo->display);
3943 #else
3944 XCloseDisplay (dpyinfo->display);
3945 #endif
3946
3947 x_delete_display (dpyinfo);
3948 UNBLOCK_INPUT;
3949
3950 return Qnil;
3951 }
3952
3953 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
3954 doc: /* Return the list of display names that Emacs has connections to. */)
3955 ()
3956 {
3957 Lisp_Object tail, result;
3958
3959 result = Qnil;
3960 for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
3961 result = Fcons (XCAR (XCAR (tail)), result);
3962
3963 return result;
3964 }
3965
3966 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
3967 doc: /* If ON is non-nil, report X errors as soon as the erring request is made.
3968 If ON is nil, allow buffering of requests.
3969 Turning on synchronization prohibits the Xlib routines from buffering
3970 requests and seriously degrades performance, but makes debugging much
3971 easier.
3972 The optional second argument DISPLAY specifies which display to act on.
3973 DISPLAY should be either a frame or a display name (a string).
3974 If DISPLAY is omitted or nil, that stands for the selected frame's display. */)
3975 (on, display)
3976 Lisp_Object display, on;
3977 {
3978 struct x_display_info *dpyinfo = check_x_display_info (display);
3979
3980 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
3981
3982 return Qnil;
3983 }
3984
3985 /* Wait for responses to all X commands issued so far for frame F. */
3986
3987 void
3988 x_sync (f)
3989 FRAME_PTR f;
3990 {
3991 BLOCK_INPUT;
3992 XSync (FRAME_X_DISPLAY (f), False);
3993 UNBLOCK_INPUT;
3994 }
3995
3996 \f
3997 /***********************************************************************
3998 Window properties
3999 ***********************************************************************/
4000
4001 DEFUN ("x-change-window-property", Fx_change_window_property,
4002 Sx_change_window_property, 2, 6, 0,
4003 doc: /* Change window property PROP to VALUE on the X window of FRAME.
4004 PROP must be a string.
4005 VALUE may be a string or a list of conses, numbers and/or strings.
4006 If an element in the list is a string, it is converted to
4007 an Atom and the value of the Atom is used. If an element is a cons,
4008 it is converted to a 32 bit number where the car is the 16 top bits and the
4009 cdr is the lower 16 bits.
4010 FRAME nil or omitted means use the selected frame.
4011 If TYPE is given and non-nil, it is the name of the type of VALUE.
4012 If TYPE is not given or nil, the type is STRING.
4013 FORMAT gives the size in bits of each element if VALUE is a list.
4014 It must be one of 8, 16 or 32.
4015 If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to 8.
4016 If OUTER_P is non-nil, the property is changed for the outer X window of
4017 FRAME. Default is to change on the edit X window.
4018
4019 Value is VALUE. */)
4020 (prop, value, frame, type, format, outer_p)
4021 Lisp_Object prop, value, frame, type, format, outer_p;
4022 {
4023 struct frame *f = check_x_frame (frame);
4024 Atom prop_atom;
4025 Atom target_type = XA_STRING;
4026 int element_format = 8;
4027 unsigned char *data;
4028 int nelements;
4029 Window w;
4030
4031 CHECK_STRING (prop);
4032
4033 if (! NILP (format))
4034 {
4035 CHECK_NUMBER (format);
4036 element_format = XFASTINT (format);
4037
4038 if (element_format != 8 && element_format != 16
4039 && element_format != 32)
4040 error ("FORMAT must be one of 8, 16 or 32");
4041 }
4042
4043 if (CONSP (value))
4044 {
4045 nelements = x_check_property_data (value);
4046 if (nelements == -1)
4047 error ("Bad data in VALUE, must be number, string or cons");
4048
4049 if (element_format == 8)
4050 data = (unsigned char *) xmalloc (nelements);
4051 else if (element_format == 16)
4052 data = (unsigned char *) xmalloc (nelements*2);
4053 else
4054 data = (unsigned char *) xmalloc (nelements*4);
4055
4056 x_fill_property_data (FRAME_X_DISPLAY (f), value, data, element_format);
4057 }
4058 else
4059 {
4060 CHECK_STRING (value);
4061 data = SDATA (value);
4062 nelements = SCHARS (value);
4063 }
4064
4065 BLOCK_INPUT;
4066 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
4067 if (! NILP (type))
4068 {
4069 CHECK_STRING (type);
4070 target_type = XInternAtom (FRAME_X_DISPLAY (f), SDATA (type), False);
4071 }
4072
4073 if (! NILP (outer_p)) w = FRAME_OUTER_WINDOW (f);
4074 else w = FRAME_X_WINDOW (f);
4075
4076 XChangeProperty (FRAME_X_DISPLAY (f), w,
4077 prop_atom, target_type, element_format, PropModeReplace,
4078 data, nelements);
4079
4080 if (CONSP (value)) xfree (data);
4081
4082 /* Make sure the property is set when we return. */
4083 XFlush (FRAME_X_DISPLAY (f));
4084 UNBLOCK_INPUT;
4085
4086 return value;
4087 }
4088
4089
4090 DEFUN ("x-delete-window-property", Fx_delete_window_property,
4091 Sx_delete_window_property, 1, 2, 0,
4092 doc: /* Remove window property PROP from X window of FRAME.
4093 FRAME nil or omitted means use the selected frame. Value is PROP. */)
4094 (prop, frame)
4095 Lisp_Object prop, frame;
4096 {
4097 struct frame *f = check_x_frame (frame);
4098 Atom prop_atom;
4099
4100 CHECK_STRING (prop);
4101 BLOCK_INPUT;
4102 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
4103 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
4104
4105 /* Make sure the property is removed when we return. */
4106 XFlush (FRAME_X_DISPLAY (f));
4107 UNBLOCK_INPUT;
4108
4109 return prop;
4110 }
4111
4112
4113 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
4114 1, 6, 0,
4115 doc: /* Value is the value of window property PROP on FRAME.
4116 If FRAME is nil or omitted, use the selected frame.
4117 If TYPE is nil or omitted, get the property as a string. Otherwise TYPE
4118 is the name of the Atom that denotes the type expected.
4119 If SOURCE is non-nil, get the property on that window instead of from
4120 FRAME. The number 0 denotes the root window.
4121 If DELETE_P is non-nil, delete the property after retreiving it.
4122 If VECTOR_RET_P is non-nil, don't return a string but a vector of values.
4123
4124 Value is nil if FRAME hasn't a property with name PROP or if PROP has
4125 no value of TYPE. */)
4126 (prop, frame, type, source, delete_p, vector_ret_p)
4127 Lisp_Object prop, frame, type, source, delete_p, vector_ret_p;
4128 {
4129 struct frame *f = check_x_frame (frame);
4130 Atom prop_atom;
4131 int rc;
4132 Lisp_Object prop_value = Qnil;
4133 char *tmp_data = NULL;
4134 Atom actual_type;
4135 Atom target_type = XA_STRING;
4136 int actual_format;
4137 unsigned long actual_size, bytes_remaining;
4138 Window target_window = FRAME_X_WINDOW (f);
4139 struct gcpro gcpro1;
4140
4141 GCPRO1 (prop_value);
4142 CHECK_STRING (prop);
4143
4144 if (! NILP (source))
4145 {
4146 if (NUMBERP (source))
4147 {
4148 if (FLOATP (source))
4149 target_window = (Window) XFLOAT (source);
4150 else
4151 target_window = XFASTINT (source);
4152
4153 if (target_window == 0)
4154 target_window = FRAME_X_DISPLAY_INFO (f)->root_window;
4155 }
4156 else if (CONSP (source))
4157 target_window = cons_to_long (source);
4158 }
4159
4160 BLOCK_INPUT;
4161 if (STRINGP (type))
4162 {
4163 if (strcmp ("AnyPropertyType", SDATA (type)) == 0)
4164 target_type = AnyPropertyType;
4165 else
4166 target_type = XInternAtom (FRAME_X_DISPLAY (f), SDATA (type), False);
4167 }
4168
4169 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
4170 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
4171 prop_atom, 0, 0, False, target_type,
4172 &actual_type, &actual_format, &actual_size,
4173 &bytes_remaining, (unsigned char **) &tmp_data);
4174 if (rc == Success)
4175 {
4176 int size = bytes_remaining;
4177
4178 XFree (tmp_data);
4179 tmp_data = NULL;
4180
4181 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
4182 prop_atom, 0, bytes_remaining,
4183 ! NILP (delete_p), target_type,
4184 &actual_type, &actual_format,
4185 &actual_size, &bytes_remaining,
4186 (unsigned char **) &tmp_data);
4187 if (rc == Success && tmp_data)
4188 {
4189 if (NILP (vector_ret_p))
4190 prop_value = make_string (tmp_data, size);
4191 else
4192 prop_value = x_property_data_to_lisp (f,
4193 (unsigned char *) tmp_data,
4194 actual_type,
4195 actual_format,
4196 actual_size);
4197 }
4198
4199 if (tmp_data) XFree (tmp_data);
4200 }
4201
4202 UNBLOCK_INPUT;
4203 UNGCPRO;
4204 return prop_value;
4205 }
4206
4207
4208 \f
4209 /***********************************************************************
4210 Busy cursor
4211 ***********************************************************************/
4212
4213 /* If non-null, an asynchronous timer that, when it expires, displays
4214 an hourglass cursor on all frames. */
4215
4216 static struct atimer *hourglass_atimer;
4217
4218 /* Non-zero means an hourglass cursor is currently shown. */
4219
4220 static int hourglass_shown_p;
4221
4222 /* Number of seconds to wait before displaying an hourglass cursor. */
4223
4224 static Lisp_Object Vhourglass_delay;
4225
4226 /* Default number of seconds to wait before displaying an hourglass
4227 cursor. */
4228
4229 #define DEFAULT_HOURGLASS_DELAY 1
4230
4231 /* Function prototypes. */
4232
4233 static void show_hourglass P_ ((struct atimer *));
4234 static void hide_hourglass P_ ((void));
4235
4236
4237 /* Cancel a currently active hourglass timer, and start a new one. */
4238
4239 void
4240 start_hourglass ()
4241 {
4242 EMACS_TIME delay;
4243 int secs, usecs = 0;
4244
4245 cancel_hourglass ();
4246
4247 if (INTEGERP (Vhourglass_delay)
4248 && XINT (Vhourglass_delay) > 0)
4249 secs = XFASTINT (Vhourglass_delay);
4250 else if (FLOATP (Vhourglass_delay)
4251 && XFLOAT_DATA (Vhourglass_delay) > 0)
4252 {
4253 Lisp_Object tem;
4254 tem = Ftruncate (Vhourglass_delay, Qnil);
4255 secs = XFASTINT (tem);
4256 usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
4257 }
4258 else
4259 secs = DEFAULT_HOURGLASS_DELAY;
4260
4261 EMACS_SET_SECS_USECS (delay, secs, usecs);
4262 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
4263 show_hourglass, NULL);
4264 }
4265
4266
4267 /* Cancel the hourglass cursor timer if active, hide a busy cursor if
4268 shown. */
4269
4270 void
4271 cancel_hourglass ()
4272 {
4273 if (hourglass_atimer)
4274 {
4275 cancel_atimer (hourglass_atimer);
4276 hourglass_atimer = NULL;
4277 }
4278
4279 if (hourglass_shown_p)
4280 hide_hourglass ();
4281 }
4282
4283
4284 /* Timer function of hourglass_atimer. TIMER is equal to
4285 hourglass_atimer.
4286
4287 Display an hourglass pointer on all frames by mapping the frames'
4288 hourglass_window. Set the hourglass_p flag in the frames'
4289 output_data.x structure to indicate that an hourglass cursor is
4290 shown on the frames. */
4291
4292 static void
4293 show_hourglass (timer)
4294 struct atimer *timer;
4295 {
4296 /* The timer implementation will cancel this timer automatically
4297 after this function has run. Set hourglass_atimer to null
4298 so that we know the timer doesn't have to be canceled. */
4299 hourglass_atimer = NULL;
4300
4301 if (!hourglass_shown_p)
4302 {
4303 Lisp_Object rest, frame;
4304
4305 BLOCK_INPUT;
4306
4307 FOR_EACH_FRAME (rest, frame)
4308 {
4309 struct frame *f = XFRAME (frame);
4310
4311 if (FRAME_LIVE_P (f) && FRAME_X_P (f) && FRAME_X_DISPLAY (f))
4312 {
4313 Display *dpy = FRAME_X_DISPLAY (f);
4314
4315 #ifdef USE_X_TOOLKIT
4316 if (f->output_data.x->widget)
4317 #else
4318 if (FRAME_OUTER_WINDOW (f))
4319 #endif
4320 {
4321 f->output_data.x->hourglass_p = 1;
4322
4323 if (!f->output_data.x->hourglass_window)
4324 {
4325 unsigned long mask = CWCursor;
4326 XSetWindowAttributes attrs;
4327
4328 attrs.cursor = f->output_data.x->hourglass_cursor;
4329
4330 f->output_data.x->hourglass_window
4331 = XCreateWindow (dpy, FRAME_OUTER_WINDOW (f),
4332 0, 0, 32000, 32000, 0, 0,
4333 InputOnly,
4334 CopyFromParent,
4335 mask, &attrs);
4336 }
4337
4338 XMapRaised (dpy, f->output_data.x->hourglass_window);
4339 XFlush (dpy);
4340 }
4341 }
4342 }
4343
4344 hourglass_shown_p = 1;
4345 UNBLOCK_INPUT;
4346 }
4347 }
4348
4349
4350 /* Hide the hourglass pointer on all frames, if it is currently
4351 shown. */
4352
4353 static void
4354 hide_hourglass ()
4355 {
4356 if (hourglass_shown_p)
4357 {
4358 Lisp_Object rest, frame;
4359
4360 BLOCK_INPUT;
4361 FOR_EACH_FRAME (rest, frame)
4362 {
4363 struct frame *f = XFRAME (frame);
4364
4365 if (FRAME_X_P (f)
4366 /* Watch out for newly created frames. */
4367 && f->output_data.x->hourglass_window)
4368 {
4369 XUnmapWindow (FRAME_X_DISPLAY (f),
4370 f->output_data.x->hourglass_window);
4371 /* Sync here because XTread_socket looks at the
4372 hourglass_p flag that is reset to zero below. */
4373 XSync (FRAME_X_DISPLAY (f), False);
4374 f->output_data.x->hourglass_p = 0;
4375 }
4376 }
4377
4378 hourglass_shown_p = 0;
4379 UNBLOCK_INPUT;
4380 }
4381 }
4382
4383
4384 \f
4385 /***********************************************************************
4386 Tool tips
4387 ***********************************************************************/
4388
4389 static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
4390 Lisp_Object, Lisp_Object));
4391 static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
4392 Lisp_Object, int, int, int *, int *));
4393
4394 /* The frame of a currently visible tooltip. */
4395
4396 Lisp_Object tip_frame;
4397
4398 /* If non-nil, a timer started that hides the last tooltip when it
4399 fires. */
4400
4401 Lisp_Object tip_timer;
4402 Window tip_window;
4403
4404 /* If non-nil, a vector of 3 elements containing the last args
4405 with which x-show-tip was called. See there. */
4406
4407 Lisp_Object last_show_tip_args;
4408
4409 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
4410
4411 Lisp_Object Vx_max_tooltip_size;
4412
4413
4414 static Lisp_Object
4415 unwind_create_tip_frame (frame)
4416 Lisp_Object frame;
4417 {
4418 Lisp_Object deleted;
4419
4420 deleted = unwind_create_frame (frame);
4421 if (EQ (deleted, Qt))
4422 {
4423 tip_window = None;
4424 tip_frame = Qnil;
4425 }
4426
4427 return deleted;
4428 }
4429
4430
4431 /* Create a frame for a tooltip on the display described by DPYINFO.
4432 PARMS is a list of frame parameters. TEXT is the string to
4433 display in the tip frame. Value is the frame.
4434
4435 Note that functions called here, esp. x_default_parameter can
4436 signal errors, for instance when a specified color name is
4437 undefined. We have to make sure that we're in a consistent state
4438 when this happens. */
4439
4440 static Lisp_Object
4441 x_create_tip_frame (dpyinfo, parms, text)
4442 struct x_display_info *dpyinfo;
4443 Lisp_Object parms, text;
4444 {
4445 struct frame *f;
4446 Lisp_Object frame, tem;
4447 Lisp_Object name;
4448 long window_prompting = 0;
4449 int width, height;
4450 int count = SPECPDL_INDEX ();
4451 struct gcpro gcpro1, gcpro2, gcpro3;
4452 struct kboard *kb;
4453 int face_change_count_before = face_change_count;
4454 Lisp_Object buffer;
4455 struct buffer *old_buffer;
4456
4457 check_x ();
4458
4459 /* Use this general default value to start with until we know if
4460 this frame has a specified name. */
4461 Vx_resource_name = Vinvocation_name;
4462
4463 #ifdef MULTI_KBOARD
4464 kb = dpyinfo->kboard;
4465 #else
4466 kb = &the_only_kboard;
4467 #endif
4468
4469 /* Get the name of the frame to use for resource lookup. */
4470 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
4471 if (!STRINGP (name)
4472 && !EQ (name, Qunbound)
4473 && !NILP (name))
4474 error ("Invalid frame name--not a string or nil");
4475 Vx_resource_name = name;
4476
4477 frame = Qnil;
4478 GCPRO3 (parms, name, frame);
4479 f = make_frame (1);
4480 XSETFRAME (frame, f);
4481
4482 buffer = Fget_buffer_create (build_string (" *tip*"));
4483 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer, Qnil);
4484 old_buffer = current_buffer;
4485 set_buffer_internal_1 (XBUFFER (buffer));
4486 current_buffer->truncate_lines = Qnil;
4487 specbind (Qinhibit_read_only, Qt);
4488 specbind (Qinhibit_modification_hooks, Qt);
4489 Ferase_buffer ();
4490 Finsert (1, &text);
4491 set_buffer_internal_1 (old_buffer);
4492
4493 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
4494 record_unwind_protect (unwind_create_tip_frame, frame);
4495
4496 f->display = dpyinfo->frame_display;
4497 f->display->reference_count++;
4498
4499 /* By setting the output method, we're essentially saying that
4500 the frame is live, as per FRAME_LIVE_P. If we get a signal
4501 from this point on, x_destroy_window might screw up reference
4502 counts etc. */
4503 f->output_method = output_x_window;
4504 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
4505 bzero (f->output_data.x, sizeof (struct x_output));
4506 f->output_data.x->icon_bitmap = -1;
4507 FRAME_FONTSET (f) = -1;
4508 f->output_data.x->scroll_bar_foreground_pixel = -1;
4509 f->output_data.x->scroll_bar_background_pixel = -1;
4510 #ifdef USE_TOOLKIT_SCROLL_BARS
4511 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
4512 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
4513 #endif /* USE_TOOLKIT_SCROLL_BARS */
4514 f->icon_name = Qnil;
4515 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
4516 #if GLYPH_DEBUG
4517 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
4518 dpyinfo_refcount = dpyinfo->reference_count;
4519 #endif /* GLYPH_DEBUG */
4520 #ifdef MULTI_KBOARD
4521 FRAME_KBOARD (f) = kb;
4522 #endif
4523 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4524 f->output_data.x->explicit_parent = 0;
4525
4526 /* These colors will be set anyway later, but it's important
4527 to get the color reference counts right, so initialize them! */
4528 {
4529 Lisp_Object black;
4530 struct gcpro gcpro1;
4531
4532 black = build_string ("black");
4533 GCPRO1 (black);
4534 f->output_data.x->foreground_pixel
4535 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4536 f->output_data.x->background_pixel
4537 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4538 f->output_data.x->cursor_pixel
4539 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4540 f->output_data.x->cursor_foreground_pixel
4541 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4542 f->output_data.x->border_pixel
4543 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4544 f->output_data.x->mouse_pixel
4545 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4546 UNGCPRO;
4547 }
4548
4549 /* Set the name; the functions to which we pass f expect the name to
4550 be set. */
4551 if (EQ (name, Qunbound) || NILP (name))
4552 {
4553 f->name = build_string (dpyinfo->x_id_name);
4554 f->explicit_name = 0;
4555 }
4556 else
4557 {
4558 f->name = name;
4559 f->explicit_name = 1;
4560 /* use the frame's title when getting resources for this frame. */
4561 specbind (Qx_resource_name, name);
4562 }
4563
4564 /* Extract the window parameters from the supplied values that are
4565 needed to determine window geometry. */
4566 {
4567 Lisp_Object font;
4568
4569 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
4570
4571 BLOCK_INPUT;
4572 /* First, try whatever font the caller has specified. */
4573 if (STRINGP (font))
4574 {
4575 tem = Fquery_fontset (font, Qnil);
4576 if (STRINGP (tem))
4577 font = x_new_fontset (f, SDATA (tem));
4578 else
4579 font = x_new_font (f, SDATA (font));
4580 }
4581
4582 /* Try out a font which we hope has bold and italic variations. */
4583 if (!STRINGP (font))
4584 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4585 if (!STRINGP (font))
4586 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4587 if (! STRINGP (font))
4588 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4589 if (! STRINGP (font))
4590 /* This was formerly the first thing tried, but it finds too many fonts
4591 and takes too long. */
4592 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4593 /* If those didn't work, look for something which will at least work. */
4594 if (! STRINGP (font))
4595 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4596 UNBLOCK_INPUT;
4597 if (! STRINGP (font))
4598 font = build_string ("fixed");
4599
4600 x_default_parameter (f, parms, Qfont, font,
4601 "font", "Font", RES_TYPE_STRING);
4602 }
4603
4604 x_default_parameter (f, parms, Qborder_width, make_number (2),
4605 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
4606
4607 /* This defaults to 2 in order to match xterm. We recognize either
4608 internalBorderWidth or internalBorder (which is what xterm calls
4609 it). */
4610 if (NILP (Fassq (Qinternal_border_width, parms)))
4611 {
4612 Lisp_Object value;
4613
4614 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
4615 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
4616 if (! EQ (value, Qunbound))
4617 parms = Fcons (Fcons (Qinternal_border_width, value),
4618 parms);
4619 }
4620
4621 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
4622 "internalBorderWidth", "internalBorderWidth",
4623 RES_TYPE_NUMBER);
4624
4625 /* Also do the stuff which must be set before the window exists. */
4626 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
4627 "foreground", "Foreground", RES_TYPE_STRING);
4628 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
4629 "background", "Background", RES_TYPE_STRING);
4630 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
4631 "pointerColor", "Foreground", RES_TYPE_STRING);
4632 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
4633 "cursorColor", "Foreground", RES_TYPE_STRING);
4634 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
4635 "borderColor", "BorderColor", RES_TYPE_STRING);
4636
4637 /* Init faces before x_default_parameter is called for scroll-bar
4638 parameters because that function calls x_set_scroll_bar_width,
4639 which calls change_frame_size, which calls Fset_window_buffer,
4640 which runs hooks, which call Fvertical_motion. At the end, we
4641 end up in init_iterator with a null face cache, which should not
4642 happen. */
4643 init_frame_faces (f);
4644
4645 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4646
4647 window_prompting = x_figure_window_size (f, parms, 0);
4648
4649 {
4650 XSetWindowAttributes attrs;
4651 unsigned long mask;
4652
4653 BLOCK_INPUT;
4654 mask = CWBackPixel | CWOverrideRedirect | CWEventMask;
4655 if (DoesSaveUnders (dpyinfo->screen))
4656 mask |= CWSaveUnder;
4657
4658 /* Window managers look at the override-redirect flag to determine
4659 whether or net to give windows a decoration (Xlib spec, chapter
4660 3.2.8). */
4661 attrs.override_redirect = True;
4662 attrs.save_under = True;
4663 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
4664 /* Arrange for getting MapNotify and UnmapNotify events. */
4665 attrs.event_mask = StructureNotifyMask;
4666 tip_window
4667 = FRAME_X_WINDOW (f)
4668 = XCreateWindow (FRAME_X_DISPLAY (f),
4669 FRAME_X_DISPLAY_INFO (f)->root_window,
4670 /* x, y, width, height */
4671 0, 0, 1, 1,
4672 /* Border. */
4673 1,
4674 CopyFromParent, InputOutput, CopyFromParent,
4675 mask, &attrs);
4676 UNBLOCK_INPUT;
4677 }
4678
4679 x_make_gc (f);
4680
4681 x_default_parameter (f, parms, Qauto_raise, Qnil,
4682 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4683 x_default_parameter (f, parms, Qauto_lower, Qnil,
4684 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4685 x_default_parameter (f, parms, Qcursor_type, Qbox,
4686 "cursorType", "CursorType", RES_TYPE_SYMBOL);
4687
4688 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
4689 Change will not be effected unless different from the current
4690 FRAME_LINES (f). */
4691 width = FRAME_COLS (f);
4692 height = FRAME_LINES (f);
4693 SET_FRAME_COLS (f, 0);
4694 FRAME_LINES (f) = 0;
4695 change_frame_size (f, height, width, 1, 0, 0);
4696
4697 /* Add `tooltip' frame parameter's default value. */
4698 if (NILP (Fframe_parameter (frame, intern ("tooltip"))))
4699 Fmodify_frame_parameters (frame, Fcons (Fcons (intern ("tooltip"), Qt),
4700 Qnil));
4701
4702 /* Set up faces after all frame parameters are known. This call
4703 also merges in face attributes specified for new frames.
4704
4705 Frame parameters may be changed if .Xdefaults contains
4706 specifications for the default font. For example, if there is an
4707 `Emacs.default.attributeBackground: pink', the `background-color'
4708 attribute of the frame get's set, which let's the internal border
4709 of the tooltip frame appear in pink. Prevent this. */
4710 {
4711 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
4712
4713 /* Set tip_frame here, so that */
4714 tip_frame = frame;
4715 call1 (Qface_set_after_frame_default, frame);
4716
4717 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
4718 Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
4719 Qnil));
4720 }
4721
4722 Fmodify_frame_parameters (frame, Fcons (Fcons (Qwindow_system, Qx), Qnil));
4723
4724 f->no_split = 1;
4725
4726 UNGCPRO;
4727
4728 /* It is now ok to make the frame official even if we get an error
4729 below. And the frame needs to be on Vframe_list or making it
4730 visible won't work. */
4731 Vframe_list = Fcons (frame, Vframe_list);
4732
4733 /* Now that the frame is official, it counts as a reference to
4734 its display. */
4735 FRAME_X_DISPLAY_INFO (f)->reference_count++;
4736
4737 /* Setting attributes of faces of the tooltip frame from resources
4738 and similar will increment face_change_count, which leads to the
4739 clearing of all current matrices. Since this isn't necessary
4740 here, avoid it by resetting face_change_count to the value it
4741 had before we created the tip frame. */
4742 face_change_count = face_change_count_before;
4743
4744 /* Discard the unwind_protect. */
4745 return unbind_to (count, frame);
4746 }
4747
4748
4749 /* Compute where to display tip frame F. PARMS is the list of frame
4750 parameters for F. DX and DY are specified offsets from the current
4751 location of the mouse. WIDTH and HEIGHT are the width and height
4752 of the tooltip. Return coordinates relative to the root window of
4753 the display in *ROOT_X, and *ROOT_Y. */
4754
4755 static void
4756 compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
4757 struct frame *f;
4758 Lisp_Object parms, dx, dy;
4759 int width, height;
4760 int *root_x, *root_y;
4761 {
4762 Lisp_Object left, top;
4763 int win_x, win_y;
4764 Window root, child;
4765 unsigned pmask;
4766
4767 /* User-specified position? */
4768 left = Fcdr (Fassq (Qleft, parms));
4769 top = Fcdr (Fassq (Qtop, parms));
4770
4771 /* Move the tooltip window where the mouse pointer is. Resize and
4772 show it. */
4773 if (!INTEGERP (left) || !INTEGERP (top))
4774 {
4775 BLOCK_INPUT;
4776 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
4777 &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
4778 UNBLOCK_INPUT;
4779 }
4780
4781 if (INTEGERP (top))
4782 *root_y = XINT (top);
4783 else if (*root_y + XINT (dy) - height < 0)
4784 *root_y -= XINT (dy);
4785 else
4786 {
4787 *root_y -= height;
4788 *root_y += XINT (dy);
4789 }
4790
4791 if (INTEGERP (left))
4792 *root_x = XINT (left);
4793 else if (*root_x + XINT (dx) + width <= FRAME_X_DISPLAY_INFO (f)->width)
4794 /* It fits to the right of the pointer. */
4795 *root_x += XINT (dx);
4796 else if (width + XINT (dx) <= *root_x)
4797 /* It fits to the left of the pointer. */
4798 *root_x -= width + XINT (dx);
4799 else
4800 /* Put it left-justified on the screen--it ought to fit that way. */
4801 *root_x = 0;
4802 }
4803
4804
4805 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
4806 doc: /* Show STRING in a "tooltip" window on frame FRAME.
4807 A tooltip window is a small X window displaying a string.
4808
4809 FRAME nil or omitted means use the selected frame.
4810
4811 PARMS is an optional list of frame parameters which can be used to
4812 change the tooltip's appearance.
4813
4814 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
4815 means use the default timeout of 5 seconds.
4816
4817 If the list of frame parameters PARAMS contains a `left' parameters,
4818 the tooltip is displayed at that x-position. Otherwise it is
4819 displayed at the mouse position, with offset DX added (default is 5 if
4820 DX isn't specified). Likewise for the y-position; if a `top' frame
4821 parameter is specified, it determines the y-position of the tooltip
4822 window, otherwise it is displayed at the mouse position, with offset
4823 DY added (default is -10).
4824
4825 A tooltip's maximum size is specified by `x-max-tooltip-size'.
4826 Text larger than the specified size is clipped. */)
4827 (string, frame, parms, timeout, dx, dy)
4828 Lisp_Object string, frame, parms, timeout, dx, dy;
4829 {
4830 struct frame *f;
4831 struct window *w;
4832 int root_x, root_y;
4833 struct buffer *old_buffer;
4834 struct text_pos pos;
4835 int i, width, height;
4836 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
4837 int old_windows_or_buffers_changed = windows_or_buffers_changed;
4838 int count = SPECPDL_INDEX ();
4839
4840 specbind (Qinhibit_redisplay, Qt);
4841
4842 GCPRO4 (string, parms, frame, timeout);
4843
4844 CHECK_STRING (string);
4845 f = check_x_frame (frame);
4846 if (NILP (timeout))
4847 timeout = make_number (5);
4848 else
4849 CHECK_NATNUM (timeout);
4850
4851 if (NILP (dx))
4852 dx = make_number (5);
4853 else
4854 CHECK_NUMBER (dx);
4855
4856 if (NILP (dy))
4857 dy = make_number (-10);
4858 else
4859 CHECK_NUMBER (dy);
4860
4861 if (NILP (last_show_tip_args))
4862 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
4863
4864 if (!NILP (tip_frame))
4865 {
4866 Lisp_Object last_string = AREF (last_show_tip_args, 0);
4867 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
4868 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
4869
4870 if (EQ (frame, last_frame)
4871 && !NILP (Fequal (last_string, string))
4872 && !NILP (Fequal (last_parms, parms)))
4873 {
4874 struct frame *f = XFRAME (tip_frame);
4875
4876 /* Only DX and DY have changed. */
4877 if (!NILP (tip_timer))
4878 {
4879 Lisp_Object timer = tip_timer;
4880 tip_timer = Qnil;
4881 call1 (Qcancel_timer, timer);
4882 }
4883
4884 BLOCK_INPUT;
4885 compute_tip_xy (f, parms, dx, dy, FRAME_PIXEL_WIDTH (f),
4886 FRAME_PIXEL_HEIGHT (f), &root_x, &root_y);
4887 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4888 root_x, root_y);
4889 UNBLOCK_INPUT;
4890 goto start_timer;
4891 }
4892 }
4893
4894 /* Hide a previous tip, if any. */
4895 Fx_hide_tip ();
4896
4897 ASET (last_show_tip_args, 0, string);
4898 ASET (last_show_tip_args, 1, frame);
4899 ASET (last_show_tip_args, 2, parms);
4900
4901 /* Add default values to frame parameters. */
4902 if (NILP (Fassq (Qname, parms)))
4903 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
4904 if (NILP (Fassq (Qinternal_border_width, parms)))
4905 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
4906 if (NILP (Fassq (Qborder_width, parms)))
4907 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
4908 if (NILP (Fassq (Qborder_color, parms)))
4909 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
4910 if (NILP (Fassq (Qbackground_color, parms)))
4911 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
4912 parms);
4913
4914 /* Create a frame for the tooltip, and record it in the global
4915 variable tip_frame. */
4916 frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms, string);
4917 f = XFRAME (frame);
4918
4919 /* Set up the frame's root window. */
4920 w = XWINDOW (FRAME_ROOT_WINDOW (f));
4921 w->left_col = w->top_line = make_number (0);
4922
4923 if (CONSP (Vx_max_tooltip_size)
4924 && INTEGERP (XCAR (Vx_max_tooltip_size))
4925 && XINT (XCAR (Vx_max_tooltip_size)) > 0
4926 && INTEGERP (XCDR (Vx_max_tooltip_size))
4927 && XINT (XCDR (Vx_max_tooltip_size)) > 0)
4928 {
4929 w->total_cols = XCAR (Vx_max_tooltip_size);
4930 w->total_lines = XCDR (Vx_max_tooltip_size);
4931 }
4932 else
4933 {
4934 w->total_cols = make_number (80);
4935 w->total_lines = make_number (40);
4936 }
4937
4938 FRAME_TOTAL_COLS (f) = XINT (w->total_cols);
4939 adjust_glyphs (f);
4940 w->pseudo_window_p = 1;
4941
4942 /* Display the tooltip text in a temporary buffer. */
4943 old_buffer = current_buffer;
4944 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
4945 current_buffer->truncate_lines = Qnil;
4946 clear_glyph_matrix (w->desired_matrix);
4947 clear_glyph_matrix (w->current_matrix);
4948 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
4949 try_window (FRAME_ROOT_WINDOW (f), pos);
4950
4951 /* Compute width and height of the tooltip. */
4952 width = height = 0;
4953 for (i = 0; i < w->desired_matrix->nrows; ++i)
4954 {
4955 struct glyph_row *row = &w->desired_matrix->rows[i];
4956 struct glyph *last;
4957 int row_width;
4958
4959 /* Stop at the first empty row at the end. */
4960 if (!row->enabled_p || !row->displays_text_p)
4961 break;
4962
4963 /* Let the row go over the full width of the frame. */
4964 row->full_width_p = 1;
4965
4966 /* There's a glyph at the end of rows that is used to place
4967 the cursor there. Don't include the width of this glyph. */
4968 if (row->used[TEXT_AREA])
4969 {
4970 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
4971 row_width = row->pixel_width - last->pixel_width;
4972 }
4973 else
4974 row_width = row->pixel_width;
4975
4976 height += row->height;
4977 width = max (width, row_width);
4978 }
4979
4980 /* Add the frame's internal border to the width and height the X
4981 window should have. */
4982 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
4983 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
4984
4985 /* Move the tooltip window where the mouse pointer is. Resize and
4986 show it. */
4987 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
4988
4989 BLOCK_INPUT;
4990 XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4991 root_x, root_y, width, height);
4992 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
4993 UNBLOCK_INPUT;
4994
4995 /* Draw into the window. */
4996 w->must_be_updated_p = 1;
4997 update_single_window (w, 1);
4998
4999 /* Restore original current buffer. */
5000 set_buffer_internal_1 (old_buffer);
5001 windows_or_buffers_changed = old_windows_or_buffers_changed;
5002
5003 start_timer:
5004 /* Let the tip disappear after timeout seconds. */
5005 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
5006 intern ("x-hide-tip"));
5007
5008 UNGCPRO;
5009 return unbind_to (count, Qnil);
5010 }
5011
5012
5013 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
5014 doc: /* Hide the current tooltip window, if there is any.
5015 Value is t if tooltip was open, nil otherwise. */)
5016 ()
5017 {
5018 int count;
5019 Lisp_Object deleted, frame, timer;
5020 struct gcpro gcpro1, gcpro2;
5021
5022 /* Return quickly if nothing to do. */
5023 if (NILP (tip_timer) && NILP (tip_frame))
5024 return Qnil;
5025
5026 frame = tip_frame;
5027 timer = tip_timer;
5028 GCPRO2 (frame, timer);
5029 tip_frame = tip_timer = deleted = Qnil;
5030
5031 count = SPECPDL_INDEX ();
5032 specbind (Qinhibit_redisplay, Qt);
5033 specbind (Qinhibit_quit, Qt);
5034
5035 if (!NILP (timer))
5036 call1 (Qcancel_timer, timer);
5037
5038 if (FRAMEP (frame))
5039 {
5040 Fdelete_frame (frame, Qnil);
5041 deleted = Qt;
5042
5043 #ifdef USE_LUCID
5044 /* Bloodcurdling hack alert: The Lucid menu bar widget's
5045 redisplay procedure is not called when a tip frame over menu
5046 items is unmapped. Redisplay the menu manually... */
5047 {
5048 struct frame *f = SELECTED_FRAME ();
5049 Widget w = f->output_data.x->menubar_widget;
5050 extern void xlwmenu_redisplay P_ ((Widget));
5051
5052 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen)
5053 && w != NULL)
5054 {
5055 BLOCK_INPUT;
5056 xlwmenu_redisplay (w);
5057 UNBLOCK_INPUT;
5058 }
5059 }
5060 #endif /* USE_LUCID */
5061 }
5062
5063 UNGCPRO;
5064 return unbind_to (count, deleted);
5065 }
5066
5067
5068 \f
5069 /***********************************************************************
5070 File selection dialog
5071 ***********************************************************************/
5072
5073 #ifdef USE_MOTIF
5074
5075 /* Callback for "OK" and "Cancel" on file selection dialog. */
5076
5077 static void
5078 file_dialog_cb (widget, client_data, call_data)
5079 Widget widget;
5080 XtPointer call_data, client_data;
5081 {
5082 int *result = (int *) client_data;
5083 XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
5084 *result = cb->reason;
5085 }
5086
5087
5088 /* Callback for unmapping a file selection dialog. This is used to
5089 capture the case where a dialog is closed via a window manager's
5090 closer button, for example. Using a XmNdestroyCallback didn't work
5091 in this case. */
5092
5093 static void
5094 file_dialog_unmap_cb (widget, client_data, call_data)
5095 Widget widget;
5096 XtPointer call_data, client_data;
5097 {
5098 int *result = (int *) client_data;
5099 *result = XmCR_CANCEL;
5100 }
5101
5102
5103 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
5104 doc: /* Read file name, prompting with PROMPT in directory DIR.
5105 Use a file selection dialog.
5106 Select DEFAULT-FILENAME in the dialog's file selection box, if
5107 specified. Don't let the user enter a file name in the file
5108 selection dialog's entry field, if MUSTMATCH is non-nil. */)
5109 (prompt, dir, default_filename, mustmatch)
5110 Lisp_Object prompt, dir, default_filename, mustmatch;
5111 {
5112 int result;
5113 struct frame *f = SELECTED_FRAME ();
5114 Lisp_Object file = Qnil;
5115 Widget dialog, text, list, help;
5116 Arg al[10];
5117 int ac = 0;
5118 extern XtAppContext Xt_app_con;
5119 XmString dir_xmstring, pattern_xmstring;
5120 int count = SPECPDL_INDEX ();
5121 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
5122
5123 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
5124 CHECK_STRING (prompt);
5125 CHECK_STRING (dir);
5126
5127 /* Prevent redisplay. */
5128 specbind (Qinhibit_redisplay, Qt);
5129
5130 BLOCK_INPUT;
5131
5132 /* Create the dialog with PROMPT as title, using DIR as initial
5133 directory and using "*" as pattern. */
5134 dir = Fexpand_file_name (dir, Qnil);
5135 dir_xmstring = XmStringCreateLocalized (SDATA (dir));
5136 pattern_xmstring = XmStringCreateLocalized ("*");
5137
5138 XtSetArg (al[ac], XmNtitle, SDATA (prompt)); ++ac;
5139 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
5140 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
5141 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
5142 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
5143 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
5144 "fsb", al, ac);
5145 XmStringFree (dir_xmstring);
5146 XmStringFree (pattern_xmstring);
5147
5148 /* Add callbacks for OK and Cancel. */
5149 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
5150 (XtPointer) &result);
5151 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
5152 (XtPointer) &result);
5153 XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
5154 (XtPointer) &result);
5155
5156 /* Disable the help button since we can't display help. */
5157 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
5158 XtSetSensitive (help, False);
5159
5160 /* Mark OK button as default. */
5161 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
5162 XmNshowAsDefault, True, NULL);
5163
5164 /* If MUSTMATCH is non-nil, disable the file entry field of the
5165 dialog, so that the user must select a file from the files list
5166 box. We can't remove it because we wouldn't have a way to get at
5167 the result file name, then. */
5168 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
5169 if (!NILP (mustmatch))
5170 {
5171 Widget label;
5172 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
5173 XtSetSensitive (text, False);
5174 XtSetSensitive (label, False);
5175 }
5176
5177 /* Manage the dialog, so that list boxes get filled. */
5178 XtManageChild (dialog);
5179
5180 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
5181 must include the path for this to work. */
5182 list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
5183 if (STRINGP (default_filename))
5184 {
5185 XmString default_xmstring;
5186 int item_pos;
5187
5188 default_xmstring
5189 = XmStringCreateLocalized (SDATA (default_filename));
5190
5191 if (!XmListItemExists (list, default_xmstring))
5192 {
5193 /* Add a new item if DEFAULT_FILENAME is not in the list. */
5194 XmListAddItem (list, default_xmstring, 0);
5195 item_pos = 0;
5196 }
5197 else
5198 item_pos = XmListItemPos (list, default_xmstring);
5199 XmStringFree (default_xmstring);
5200
5201 /* Select the item and scroll it into view. */
5202 XmListSelectPos (list, item_pos, True);
5203 XmListSetPos (list, item_pos);
5204 }
5205
5206 /* Process events until the user presses Cancel or OK. */
5207 result = 0;
5208 while (result == 0)
5209 {
5210 XEvent event;
5211 XtAppNextEvent (Xt_app_con, &event);
5212 (void) x_dispatch_event (&event, FRAME_X_DISPLAY (f) );
5213 }
5214
5215 /* Get the result. */
5216 if (result == XmCR_OK)
5217 {
5218 XmString text;
5219 String data;
5220
5221 XtVaGetValues (dialog, XmNtextString, &text, NULL);
5222 XmStringGetLtoR (text, XmFONTLIST_DEFAULT_TAG, &data);
5223 XmStringFree (text);
5224 file = build_string (data);
5225 XtFree (data);
5226 }
5227 else
5228 file = Qnil;
5229
5230 /* Clean up. */
5231 XtUnmanageChild (dialog);
5232 XtDestroyWidget (dialog);
5233 UNBLOCK_INPUT;
5234 UNGCPRO;
5235
5236 /* Make "Cancel" equivalent to C-g. */
5237 if (NILP (file))
5238 Fsignal (Qquit, Qnil);
5239
5240 return unbind_to (count, file);
5241 }
5242
5243 #endif /* USE_MOTIF */
5244
5245 #ifdef USE_GTK
5246
5247 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
5248 "Read file name, prompting with PROMPT in directory DIR.\n\
5249 Use a file selection dialog.\n\
5250 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
5251 specified. Don't let the user enter a file name in the file\n\
5252 selection dialog's entry field, if MUSTMATCH is non-nil.")
5253 (prompt, dir, default_filename, mustmatch)
5254 Lisp_Object prompt, dir, default_filename, mustmatch;
5255 {
5256 FRAME_PTR f = SELECTED_FRAME ();
5257 char *fn;
5258 Lisp_Object file = Qnil;
5259 int count = specpdl_ptr - specpdl;
5260 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
5261 char *cdef_file;
5262
5263 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
5264 CHECK_STRING (prompt);
5265 CHECK_STRING (dir);
5266
5267 /* Prevent redisplay. */
5268 specbind (Qinhibit_redisplay, Qt);
5269
5270 BLOCK_INPUT;
5271
5272 if (STRINGP (default_filename))
5273 cdef_file = SDATA (default_filename);
5274 else
5275 cdef_file = SDATA (dir);
5276
5277 fn = xg_get_file_name (f, SDATA (prompt), cdef_file, ! NILP (mustmatch));
5278
5279 if (fn)
5280 {
5281 file = build_string (fn);
5282 xfree (fn);
5283 }
5284
5285 UNBLOCK_INPUT;
5286 UNGCPRO;
5287
5288 /* Make "Cancel" equivalent to C-g. */
5289 if (NILP (file))
5290 Fsignal (Qquit, Qnil);
5291
5292 return unbind_to (count, file);
5293 }
5294
5295 #endif /* USE_GTK */
5296
5297 \f
5298 /***********************************************************************
5299 Keyboard
5300 ***********************************************************************/
5301
5302 #ifdef HAVE_XKBGETKEYBOARD
5303 #include <X11/XKBlib.h>
5304 #include <X11/keysym.h>
5305 #endif
5306
5307 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
5308 Sx_backspace_delete_keys_p, 0, 1, 0,
5309 doc: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
5310 FRAME nil means use the selected frame.
5311 Value is t if we know that both keys are present, and are mapped to the
5312 usual X keysyms. */)
5313 (frame)
5314 Lisp_Object frame;
5315 {
5316 #ifdef HAVE_XKBGETKEYBOARD
5317 XkbDescPtr kb;
5318 struct frame *f = check_x_frame (frame);
5319 Display *dpy = FRAME_X_DISPLAY (f);
5320 Lisp_Object have_keys;
5321 int major, minor, op, event, error;
5322
5323 BLOCK_INPUT;
5324
5325 /* Check library version in case we're dynamically linked. */
5326 major = XkbMajorVersion;
5327 minor = XkbMinorVersion;
5328 if (!XkbLibraryVersion (&major, &minor))
5329 {
5330 UNBLOCK_INPUT;
5331 return Qnil;
5332 }
5333
5334 /* Check that the server supports XKB. */
5335 major = XkbMajorVersion;
5336 minor = XkbMinorVersion;
5337 if (!XkbQueryExtension (dpy, &op, &event, &error, &major, &minor))
5338 {
5339 UNBLOCK_INPUT;
5340 return Qnil;
5341 }
5342
5343 have_keys = Qnil;
5344 kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
5345 if (kb)
5346 {
5347 int delete_keycode = 0, backspace_keycode = 0, i;
5348
5349 if (XkbGetNames (dpy, XkbAllNamesMask, kb) == Success)
5350 {
5351 for (i = kb->min_key_code;
5352 (i < kb->max_key_code
5353 && (delete_keycode == 0 || backspace_keycode == 0));
5354 ++i)
5355 {
5356 /* The XKB symbolic key names can be seen most easily in
5357 the PS file generated by `xkbprint -label name
5358 $DISPLAY'. */
5359 if (bcmp ("DELE", kb->names->keys[i].name, 4) == 0)
5360 delete_keycode = i;
5361 else if (bcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
5362 backspace_keycode = i;
5363 }
5364
5365 XkbFreeNames (kb, 0, True);
5366 }
5367
5368 XkbFreeClientMap (kb, 0, True);
5369
5370 if (delete_keycode
5371 && backspace_keycode
5372 && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
5373 && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
5374 have_keys = Qt;
5375 }
5376 UNBLOCK_INPUT;
5377 return have_keys;
5378 #else /* not HAVE_XKBGETKEYBOARD */
5379 return Qnil;
5380 #endif /* not HAVE_XKBGETKEYBOARD */
5381 }
5382
5383
5384 \f
5385 /***********************************************************************
5386 Initialization
5387 ***********************************************************************/
5388
5389 /* Keep this list in the same order as frame_parms in frame.c.
5390 Use 0 for unsupported frame parameters. */
5391
5392 frame_parm_handler x_frame_parm_handlers[] =
5393 {
5394 x_set_autoraise,
5395 x_set_autolower,
5396 x_set_background_color,
5397 x_set_border_color,
5398 x_set_border_width,
5399 x_set_cursor_color,
5400 x_set_cursor_type,
5401 x_set_font,
5402 x_set_foreground_color,
5403 x_set_icon_name,
5404 x_set_icon_type,
5405 x_set_internal_border_width,
5406 x_set_menu_bar_lines,
5407 x_set_mouse_color,
5408 x_explicitly_set_name,
5409 x_set_scroll_bar_width,
5410 x_set_title,
5411 x_set_unsplittable,
5412 x_set_vertical_scroll_bars,
5413 x_set_visibility,
5414 x_set_tool_bar_lines,
5415 x_set_scroll_bar_foreground,
5416 x_set_scroll_bar_background,
5417 x_set_screen_gamma,
5418 x_set_line_spacing,
5419 x_set_fringe_width,
5420 x_set_fringe_width,
5421 x_set_wait_for_wm,
5422 x_set_fullscreen,
5423 };
5424
5425 void
5426 syms_of_xfns ()
5427 {
5428 /* This is zero if not using X windows. */
5429 x_in_use = 0;
5430
5431 /* The section below is built by the lisp expression at the top of the file,
5432 just above where these variables are declared. */
5433 /*&&& init symbols here &&&*/
5434 Qnone = intern ("none");
5435 staticpro (&Qnone);
5436 Qsuppress_icon = intern ("suppress-icon");
5437 staticpro (&Qsuppress_icon);
5438 Qundefined_color = intern ("undefined-color");
5439 staticpro (&Qundefined_color);
5440 Qcompound_text = intern ("compound-text");
5441 staticpro (&Qcompound_text);
5442 Qcancel_timer = intern ("cancel-timer");
5443 staticpro (&Qcancel_timer);
5444 /* This is the end of symbol initialization. */
5445
5446 /* Text property `display' should be nonsticky by default. */
5447 Vtext_property_default_nonsticky
5448 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
5449
5450
5451 Fput (Qundefined_color, Qerror_conditions,
5452 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
5453 Fput (Qundefined_color, Qerror_message,
5454 build_string ("Undefined color"));
5455
5456 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
5457 doc: /* The shape of the pointer when over text.
5458 Changing the value does not affect existing frames
5459 unless you set the mouse color. */);
5460 Vx_pointer_shape = Qnil;
5461
5462 #if 0 /* This doesn't really do anything. */
5463 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
5464 doc: /* The shape of the pointer when not over text.
5465 This variable takes effect when you create a new frame
5466 or when you set the mouse color. */);
5467 #endif
5468 Vx_nontext_pointer_shape = Qnil;
5469
5470 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
5471 doc: /* The shape of the pointer when Emacs is busy.
5472 This variable takes effect when you create a new frame
5473 or when you set the mouse color. */);
5474 Vx_hourglass_pointer_shape = Qnil;
5475
5476 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
5477 doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
5478 display_hourglass_p = 1;
5479
5480 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
5481 doc: /* *Seconds to wait before displaying an hourglass pointer.
5482 Value must be an integer or float. */);
5483 Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
5484
5485 #if 0 /* This doesn't really do anything. */
5486 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
5487 doc: /* The shape of the pointer when over the mode line.
5488 This variable takes effect when you create a new frame
5489 or when you set the mouse color. */);
5490 #endif
5491 Vx_mode_pointer_shape = Qnil;
5492
5493 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
5494 &Vx_sensitive_text_pointer_shape,
5495 doc: /* The shape of the pointer when over mouse-sensitive text.
5496 This variable takes effect when you create a new frame
5497 or when you set the mouse color. */);
5498 Vx_sensitive_text_pointer_shape = Qnil;
5499
5500 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
5501 &Vx_window_horizontal_drag_shape,
5502 doc: /* Pointer shape to use for indicating a window can be dragged horizontally.
5503 This variable takes effect when you create a new frame
5504 or when you set the mouse color. */);
5505 Vx_window_horizontal_drag_shape = Qnil;
5506
5507 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
5508 doc: /* A string indicating the foreground color of the cursor box. */);
5509 Vx_cursor_fore_pixel = Qnil;
5510
5511 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size,
5512 doc: /* Maximum size for tooltips. Value is a pair (COLUMNS . ROWS).
5513 Text larger than this is clipped. */);
5514 Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
5515
5516 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
5517 doc: /* Non-nil if no X window manager is in use.
5518 Emacs doesn't try to figure this out; this is always nil
5519 unless you set it to something else. */);
5520 /* We don't have any way to find this out, so set it to nil
5521 and maybe the user would like to set it to t. */
5522 Vx_no_window_manager = Qnil;
5523
5524 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
5525 &Vx_pixel_size_width_font_regexp,
5526 doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
5527
5528 Since Emacs gets width of a font matching with this regexp from
5529 PIXEL_SIZE field of the name, font finding mechanism gets faster for
5530 such a font. This is especially effective for such large fonts as
5531 Chinese, Japanese, and Korean. */);
5532 Vx_pixel_size_width_font_regexp = Qnil;
5533
5534 #ifdef USE_X_TOOLKIT
5535 Fprovide (intern ("x-toolkit"), Qnil);
5536 #ifdef USE_MOTIF
5537 Fprovide (intern ("motif"), Qnil);
5538
5539 DEFVAR_LISP ("motif-version-string", &Vmotif_version_string,
5540 doc: /* Version info for LessTif/Motif. */);
5541 Vmotif_version_string = build_string (XmVERSION_STRING);
5542 #endif /* USE_MOTIF */
5543 #endif /* USE_X_TOOLKIT */
5544
5545 #ifdef USE_GTK
5546 /* Provide x-toolkit also for GTK. Internally GTK does not use Xt so it
5547 is not an X toolkit in that sense (USE_X_TOOLKIT is not defined).
5548 But for a user it is a toolkit for X, and indeed, configure
5549 accepts --with-x-toolkit=gtk. */
5550 Fprovide (intern ("x-toolkit"), Qnil);
5551 Fprovide (intern ("gtk"), Qnil);
5552
5553 DEFVAR_LISP ("gtk-version-string", &Vgtk_version_string,
5554 doc: /* Version info for GTK+. */);
5555 {
5556 char gtk_version[40];
5557 g_snprintf (gtk_version, sizeof (gtk_version), "%u.%u.%u",
5558 GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
5559 Vgtk_version_string = build_string (gtk_version);
5560 }
5561 #endif /* USE_GTK */
5562
5563 /* X window properties. */
5564 defsubr (&Sx_change_window_property);
5565 defsubr (&Sx_delete_window_property);
5566 defsubr (&Sx_window_property);
5567
5568 defsubr (&Sxw_display_color_p);
5569 defsubr (&Sx_display_grayscale_p);
5570 defsubr (&Sxw_color_defined_p);
5571 defsubr (&Sxw_color_values);
5572 defsubr (&Sx_server_max_request_size);
5573 defsubr (&Sx_server_vendor);
5574 defsubr (&Sx_server_version);
5575 defsubr (&Sx_display_pixel_width);
5576 defsubr (&Sx_display_pixel_height);
5577 defsubr (&Sx_display_mm_width);
5578 defsubr (&Sx_display_mm_height);
5579 defsubr (&Sx_display_screens);
5580 defsubr (&Sx_display_planes);
5581 defsubr (&Sx_display_color_cells);
5582 defsubr (&Sx_display_visual_class);
5583 defsubr (&Sx_display_backing_store);
5584 defsubr (&Sx_display_save_under);
5585 defsubr (&Sx_create_frame);
5586 defsubr (&Sx_open_connection);
5587 defsubr (&Sx_close_connection);
5588 defsubr (&Sx_display_list);
5589 defsubr (&Sx_synchronize);
5590 defsubr (&Sx_focus_frame);
5591 defsubr (&Sx_backspace_delete_keys_p);
5592
5593 /* Setting callback functions for fontset handler. */
5594 get_font_info_func = x_get_font_info;
5595
5596 #if 0 /* This function pointer doesn't seem to be used anywhere.
5597 And the pointer assigned has the wrong type, anyway. */
5598 list_fonts_func = x_list_fonts;
5599 #endif
5600
5601 load_font_func = x_load_font;
5602 find_ccl_program_func = x_find_ccl_program;
5603 query_font_func = x_query_font;
5604 set_frame_fontset_func = x_set_font;
5605 check_window_system_func = check_x;
5606
5607 hourglass_atimer = NULL;
5608 hourglass_shown_p = 0;
5609
5610 defsubr (&Sx_show_tip);
5611 defsubr (&Sx_hide_tip);
5612 tip_timer = Qnil;
5613 staticpro (&tip_timer);
5614 tip_frame = Qnil;
5615 staticpro (&tip_frame);
5616
5617 last_show_tip_args = Qnil;
5618 staticpro (&last_show_tip_args);
5619
5620 #ifdef USE_MOTIF
5621 defsubr (&Sx_file_dialog);
5622 #endif
5623 }
5624
5625 #endif /* HAVE_X_WINDOWS */
5626
5627 /* arch-tag: 55040d02-5485-4d58-8b22-95a7a05f3288
5628 (do not change this comment) */