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