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