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