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