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