(x_set_frame_parameters): Make height and width ints.
[bpt/emacs.git] / src / xfns.c
1 /* Functions for the X window system.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996 Free Software Foundation.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 /* Completely rewritten by Richard Stallman. */
22
23 /* Rewritten for X11 by Joseph Arceneaux */
24
25 #include <signal.h>
26 #include <config.h>
27
28 /* This makes the fields of a Display accessible, in Xlib header files. */
29 #define XLIB_ILLEGAL_ACCESS
30
31 #include "lisp.h"
32 #include "xterm.h"
33 #include "frame.h"
34 #include "window.h"
35 #include "buffer.h"
36 #include "dispextern.h"
37 #include "keyboard.h"
38 #include "blockinput.h"
39 #include <paths.h>
40
41 #ifdef HAVE_X_WINDOWS
42 extern void abort ();
43
44 /* On some systems, the character-composition stuff is broken in X11R5. */
45 #if defined (HAVE_X11R5) && ! defined (HAVE_X11R6)
46 #ifdef X11R5_INHIBIT_I18N
47 #define X_I18N_INHIBITED
48 #endif
49 #endif
50
51 #ifndef VMS
52 #if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
53 #include "bitmaps/gray.xbm"
54 #else
55 #include <X11/bitmaps/gray>
56 #endif
57 #else
58 #include "[.bitmaps]gray.xbm"
59 #endif
60
61 #ifdef USE_X_TOOLKIT
62 #include <X11/Shell.h>
63
64 #ifndef USE_MOTIF
65 #include <X11/Xaw/Paned.h>
66 #include <X11/Xaw/Label.h>
67 #endif /* USE_MOTIF */
68
69 #ifdef USG
70 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
71 #include <X11/Xos.h>
72 #define USG
73 #else
74 #include <X11/Xos.h>
75 #endif
76
77 #include "widget.h"
78
79 #include "../lwlib/lwlib.h"
80
81 /* Do the EDITRES protocol if running X11R5
82 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
83 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
84 #define HACK_EDITRES
85 extern void _XEditResCheckMessages ();
86 #endif /* R5 + Athena */
87
88 /* Unique id counter for widgets created by the Lucid Widget
89 Library. */
90 extern LWLIB_ID widget_id_tick;
91
92 #ifdef USE_LUCID
93 /* This is part of a kludge--see lwlib/xlwmenu.c. */
94 extern XFontStruct *xlwmenu_default_font;
95 #endif
96
97 extern void free_frame_menubar ();
98 #endif /* USE_X_TOOLKIT */
99
100 #define min(a,b) ((a) < (b) ? (a) : (b))
101 #define max(a,b) ((a) > (b) ? (a) : (b))
102
103 #ifdef HAVE_X11R4
104 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
105 #else
106 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
107 #endif
108
109 /* The name we're using in resource queries. */
110 Lisp_Object Vx_resource_name;
111
112 /* The background and shape of the mouse pointer, and shape when not
113 over text or in the modeline. */
114 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
115 /* The shape when over mouse-sensitive text. */
116 Lisp_Object Vx_sensitive_text_pointer_shape;
117
118 /* Color of chars displayed in cursor box. */
119 Lisp_Object Vx_cursor_fore_pixel;
120
121 /* Nonzero if using X. */
122 static int x_in_use;
123
124 /* Non nil if no window manager is in use. */
125 Lisp_Object Vx_no_window_manager;
126
127 /* Search path for bitmap files. */
128 Lisp_Object Vx_bitmap_file_path;
129
130 /* Evaluate this expression to rebuild the section of syms_of_xfns
131 that initializes and staticpros the symbols declared below. Note
132 that Emacs 18 has a bug that keeps C-x C-e from being able to
133 evaluate this expression.
134
135 (progn
136 ;; Accumulate a list of the symbols we want to initialize from the
137 ;; declarations at the top of the file.
138 (goto-char (point-min))
139 (search-forward "/\*&&& symbols declared here &&&*\/\n")
140 (let (symbol-list)
141 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
142 (setq symbol-list
143 (cons (buffer-substring (match-beginning 1) (match-end 1))
144 symbol-list))
145 (forward-line 1))
146 (setq symbol-list (nreverse symbol-list))
147 ;; Delete the section of syms_of_... where we initialize the symbols.
148 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
149 (let ((start (point)))
150 (while (looking-at "^ Q")
151 (forward-line 2))
152 (kill-region start (point)))
153 ;; Write a new symbol initialization section.
154 (while symbol-list
155 (insert (format " %s = intern (\"" (car symbol-list)))
156 (let ((start (point)))
157 (insert (substring (car symbol-list) 1))
158 (subst-char-in-region start (point) ?_ ?-))
159 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
160 (setq symbol-list (cdr symbol-list)))))
161
162 */
163
164 /*&&& symbols declared here &&&*/
165 Lisp_Object Qauto_raise;
166 Lisp_Object Qauto_lower;
167 Lisp_Object Qbackground_color;
168 Lisp_Object Qbar;
169 Lisp_Object Qborder_color;
170 Lisp_Object Qborder_width;
171 Lisp_Object Qbox;
172 Lisp_Object Qcursor_color;
173 Lisp_Object Qcursor_type;
174 Lisp_Object Qforeground_color;
175 Lisp_Object Qgeometry;
176 Lisp_Object Qicon_left;
177 Lisp_Object Qicon_top;
178 Lisp_Object Qicon_type;
179 Lisp_Object Qicon_name;
180 Lisp_Object Qinternal_border_width;
181 Lisp_Object Qleft;
182 Lisp_Object Qmouse_color;
183 Lisp_Object Qnone;
184 Lisp_Object Qparent_id;
185 Lisp_Object Qscroll_bar_width;
186 Lisp_Object Qsuppress_icon;
187 Lisp_Object Qtop;
188 Lisp_Object Qundefined_color;
189 Lisp_Object Qvertical_scroll_bars;
190 Lisp_Object Qvisibility;
191 Lisp_Object Qwindow_id;
192 Lisp_Object Qx_frame_parameter;
193 Lisp_Object Qx_resource_name;
194 Lisp_Object Quser_position;
195 Lisp_Object Quser_size;
196 Lisp_Object Qdisplay;
197
198 /* The below are defined in frame.c. */
199 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
200 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
201
202 extern Lisp_Object Vwindow_system_version;
203
204 \f
205 /* Error if we are not connected to X. */
206 void
207 check_x ()
208 {
209 if (! x_in_use)
210 error ("X windows are not in use or not initialized");
211 }
212
213 /* Nonzero if we can use mouse menus.
214 You should not call this unless HAVE_MENUS is defined. */
215
216 int
217 have_menus_p ()
218 {
219 return x_in_use;
220 }
221
222 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
223 and checking validity for X. */
224
225 FRAME_PTR
226 check_x_frame (frame)
227 Lisp_Object frame;
228 {
229 FRAME_PTR f;
230
231 if (NILP (frame))
232 f = selected_frame;
233 else
234 {
235 CHECK_LIVE_FRAME (frame, 0);
236 f = XFRAME (frame);
237 }
238 if (! FRAME_X_P (f))
239 error ("Non-X frame used");
240 return f;
241 }
242
243 /* Let the user specify an X display with a frame.
244 nil stands for the selected frame--or, if that is not an X frame,
245 the first X display on the list. */
246
247 static struct x_display_info *
248 check_x_display_info (frame)
249 Lisp_Object frame;
250 {
251 if (NILP (frame))
252 {
253 if (FRAME_X_P (selected_frame))
254 return FRAME_X_DISPLAY_INFO (selected_frame);
255 else if (x_display_list != 0)
256 return x_display_list;
257 else
258 error ("X windows are not in use or not initialized");
259 }
260 else if (STRINGP (frame))
261 return x_display_info_for_name (frame);
262 else
263 {
264 FRAME_PTR f;
265
266 CHECK_LIVE_FRAME (frame, 0);
267 f = XFRAME (frame);
268 if (! FRAME_X_P (f))
269 error ("Non-X frame used");
270 return FRAME_X_DISPLAY_INFO (f);
271 }
272 }
273 \f
274 /* Return the Emacs frame-object corresponding to an X window.
275 It could be the frame's main window or an icon window. */
276
277 /* This function can be called during GC, so use GC_xxx type test macros. */
278
279 struct frame *
280 x_window_to_frame (dpyinfo, wdesc)
281 struct x_display_info *dpyinfo;
282 int wdesc;
283 {
284 Lisp_Object tail, frame;
285 struct frame *f;
286
287 for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
288 {
289 frame = XCONS (tail)->car;
290 if (!GC_FRAMEP (frame))
291 continue;
292 f = XFRAME (frame);
293 if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
294 continue;
295 #ifdef USE_X_TOOLKIT
296 if ((f->output_data.x->edit_widget
297 && XtWindow (f->output_data.x->edit_widget) == wdesc)
298 || f->output_data.x->icon_desc == wdesc)
299 return f;
300 #else /* not USE_X_TOOLKIT */
301 if (FRAME_X_WINDOW (f) == wdesc
302 || f->output_data.x->icon_desc == wdesc)
303 return f;
304 #endif /* not USE_X_TOOLKIT */
305 }
306 return 0;
307 }
308
309 #ifdef USE_X_TOOLKIT
310 /* Like x_window_to_frame but also compares the window with the widget's
311 windows. */
312
313 struct frame *
314 x_any_window_to_frame (dpyinfo, wdesc)
315 struct x_display_info *dpyinfo;
316 int wdesc;
317 {
318 Lisp_Object tail, frame;
319 struct frame *f;
320 struct x_output *x;
321
322 for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
323 {
324 frame = XCONS (tail)->car;
325 if (!GC_FRAMEP (frame))
326 continue;
327 f = XFRAME (frame);
328 if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
329 continue;
330 x = f->output_data.x;
331 /* This frame matches if the window is any of its widgets. */
332 if (wdesc == XtWindow (x->widget)
333 || wdesc == XtWindow (x->column_widget)
334 || wdesc == XtWindow (x->edit_widget))
335 return f;
336 /* Match if the window is this frame's menubar. */
337 if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
338 return f;
339 }
340 return 0;
341 }
342
343 /* Likewise, but exclude the menu bar widget. */
344
345 struct frame *
346 x_non_menubar_window_to_frame (dpyinfo, wdesc)
347 struct x_display_info *dpyinfo;
348 int wdesc;
349 {
350 Lisp_Object tail, frame;
351 struct frame *f;
352 struct x_output *x;
353
354 for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
355 {
356 frame = XCONS (tail)->car;
357 if (!GC_FRAMEP (frame))
358 continue;
359 f = XFRAME (frame);
360 if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
361 continue;
362 x = f->output_data.x;
363 /* This frame matches if the window is any of its widgets. */
364 if (wdesc == XtWindow (x->widget)
365 || wdesc == XtWindow (x->column_widget)
366 || wdesc == XtWindow (x->edit_widget))
367 return f;
368 }
369 return 0;
370 }
371
372 /* Likewise, but consider only the menu bar widget. */
373
374 struct frame *
375 x_menubar_window_to_frame (dpyinfo, wdesc)
376 struct x_display_info *dpyinfo;
377 int wdesc;
378 {
379 Lisp_Object tail, frame;
380 struct frame *f;
381 struct x_output *x;
382
383 for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
384 {
385 frame = XCONS (tail)->car;
386 if (!GC_FRAMEP (frame))
387 continue;
388 f = XFRAME (frame);
389 if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
390 continue;
391 x = f->output_data.x;
392 /* Match if the window is this frame's menubar. */
393 if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
394 return f;
395 }
396 return 0;
397 }
398
399 /* Return the frame whose principal (outermost) window is WDESC.
400 If WDESC is some other (smaller) window, we return 0. */
401
402 struct frame *
403 x_top_window_to_frame (dpyinfo, wdesc)
404 struct x_display_info *dpyinfo;
405 int wdesc;
406 {
407 Lisp_Object tail, frame;
408 struct frame *f;
409 struct x_output *x;
410
411 for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
412 {
413 frame = XCONS (tail)->car;
414 if (!GC_FRAMEP (frame))
415 continue;
416 f = XFRAME (frame);
417 if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
418 continue;
419 x = f->output_data.x;
420 /* This frame matches if the window is its topmost widget. */
421 if (wdesc == XtWindow (x->widget))
422 return f;
423 #if 0 /* I don't know why it did this,
424 but it seems logically wrong,
425 and it causes trouble for MapNotify events. */
426 /* Match if the window is this frame's menubar. */
427 if (x->menubar_widget
428 && wdesc == XtWindow (x->menubar_widget))
429 return f;
430 #endif
431 }
432 return 0;
433 }
434 #endif /* USE_X_TOOLKIT */
435
436 \f
437
438 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
439 id, which is just an int that this section returns. Bitmaps are
440 reference counted so they can be shared among frames.
441
442 Bitmap indices are guaranteed to be > 0, so a negative number can
443 be used to indicate no bitmap.
444
445 If you use x_create_bitmap_from_data, then you must keep track of
446 the bitmaps yourself. That is, creating a bitmap from the same
447 data more than once will not be caught. */
448
449
450 /* Functions to access the contents of a bitmap, given an id. */
451
452 int
453 x_bitmap_height (f, id)
454 FRAME_PTR f;
455 int id;
456 {
457 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
458 }
459
460 int
461 x_bitmap_width (f, id)
462 FRAME_PTR f;
463 int id;
464 {
465 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
466 }
467
468 int
469 x_bitmap_pixmap (f, id)
470 FRAME_PTR f;
471 int id;
472 {
473 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
474 }
475
476
477 /* Allocate a new bitmap record. Returns index of new record. */
478
479 static int
480 x_allocate_bitmap_record (f)
481 FRAME_PTR f;
482 {
483 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
484 int i;
485
486 if (dpyinfo->bitmaps == NULL)
487 {
488 dpyinfo->bitmaps_size = 10;
489 dpyinfo->bitmaps
490 = (struct x_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
491 dpyinfo->bitmaps_last = 1;
492 return 1;
493 }
494
495 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
496 return ++dpyinfo->bitmaps_last;
497
498 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
499 if (dpyinfo->bitmaps[i].refcount == 0)
500 return i + 1;
501
502 dpyinfo->bitmaps_size *= 2;
503 dpyinfo->bitmaps
504 = (struct x_bitmap_record *) xrealloc (dpyinfo->bitmaps,
505 dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
506 return ++dpyinfo->bitmaps_last;
507 }
508
509 /* Add one reference to the reference count of the bitmap with id ID. */
510
511 void
512 x_reference_bitmap (f, id)
513 FRAME_PTR f;
514 int id;
515 {
516 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
517 }
518
519 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
520
521 int
522 x_create_bitmap_from_data (f, bits, width, height)
523 struct frame *f;
524 char *bits;
525 unsigned int width, height;
526 {
527 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
528 Pixmap bitmap;
529 int id;
530
531 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
532 bits, width, height);
533
534 if (! bitmap)
535 return -1;
536
537 id = x_allocate_bitmap_record (f);
538 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
539 dpyinfo->bitmaps[id - 1].file = NULL;
540 dpyinfo->bitmaps[id - 1].refcount = 1;
541 dpyinfo->bitmaps[id - 1].depth = 1;
542 dpyinfo->bitmaps[id - 1].height = height;
543 dpyinfo->bitmaps[id - 1].width = width;
544
545 return id;
546 }
547
548 /* Create bitmap from file FILE for frame F. */
549
550 int
551 x_create_bitmap_from_file (f, file)
552 struct frame *f;
553 Lisp_Object file;
554 {
555 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
556 unsigned int width, height;
557 Pixmap bitmap;
558 int xhot, yhot, result, id;
559 Lisp_Object found;
560 int fd;
561 char *filename;
562
563 /* Look for an existing bitmap with the same name. */
564 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
565 {
566 if (dpyinfo->bitmaps[id].refcount
567 && dpyinfo->bitmaps[id].file
568 && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
569 {
570 ++dpyinfo->bitmaps[id].refcount;
571 return id + 1;
572 }
573 }
574
575 /* Search bitmap-file-path for the file, if appropriate. */
576 fd = openp (Vx_bitmap_file_path, file, "", &found, 0);
577 if (fd < 0)
578 return -1;
579 close (fd);
580
581 filename = (char *) XSTRING (found)->data;
582
583 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
584 filename, &width, &height, &bitmap, &xhot, &yhot);
585 if (result != BitmapSuccess)
586 return -1;
587
588 id = x_allocate_bitmap_record (f);
589 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
590 dpyinfo->bitmaps[id - 1].refcount = 1;
591 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (XSTRING (file)->size + 1);
592 dpyinfo->bitmaps[id - 1].depth = 1;
593 dpyinfo->bitmaps[id - 1].height = height;
594 dpyinfo->bitmaps[id - 1].width = width;
595 strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
596
597 return id;
598 }
599
600 /* Remove reference to bitmap with id number ID. */
601
602 int
603 x_destroy_bitmap (f, id)
604 FRAME_PTR f;
605 int id;
606 {
607 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
608
609 if (id > 0)
610 {
611 --dpyinfo->bitmaps[id - 1].refcount;
612 if (dpyinfo->bitmaps[id - 1].refcount == 0)
613 {
614 BLOCK_INPUT;
615 XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].pixmap);
616 if (dpyinfo->bitmaps[id - 1].file)
617 {
618 free (dpyinfo->bitmaps[id - 1].file);
619 dpyinfo->bitmaps[id - 1].file = NULL;
620 }
621 UNBLOCK_INPUT;
622 }
623 }
624 }
625
626 /* Free all the bitmaps for the display specified by DPYINFO. */
627
628 static void
629 x_destroy_all_bitmaps (dpyinfo)
630 struct x_display_info *dpyinfo;
631 {
632 int i;
633 for (i = 0; i < dpyinfo->bitmaps_last; i++)
634 if (dpyinfo->bitmaps[i].refcount > 0)
635 {
636 XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].pixmap);
637 if (dpyinfo->bitmaps[i].file)
638 free (dpyinfo->bitmaps[i].file);
639 }
640 dpyinfo->bitmaps_last = 0;
641 }
642 \f
643 /* Connect the frame-parameter names for X frames
644 to the ways of passing the parameter values to the window system.
645
646 The name of a parameter, as a Lisp symbol,
647 has an `x-frame-parameter' property which is an integer in Lisp
648 that is an index in this table. */
649
650 struct x_frame_parm_table
651 {
652 char *name;
653 void (*setter)( /* struct frame *frame, Lisp_Object val, oldval */ );
654 };
655
656 void x_set_foreground_color ();
657 void x_set_background_color ();
658 void x_set_mouse_color ();
659 void x_set_cursor_color ();
660 void x_set_border_color ();
661 void x_set_cursor_type ();
662 void x_set_icon_type ();
663 void x_set_icon_name ();
664 void x_set_font ();
665 void x_set_border_width ();
666 void x_set_internal_border_width ();
667 void x_explicitly_set_name ();
668 void x_set_autoraise ();
669 void x_set_autolower ();
670 void x_set_vertical_scroll_bars ();
671 void x_set_visibility ();
672 void x_set_menu_bar_lines ();
673 void x_set_scroll_bar_width ();
674 void x_set_title ();
675 void x_set_unsplittable ();
676
677 static struct x_frame_parm_table x_frame_parms[] =
678 {
679 "auto-raise", x_set_autoraise,
680 "auto-lower", x_set_autolower,
681 "background-color", x_set_background_color,
682 "border-color", x_set_border_color,
683 "border-width", x_set_border_width,
684 "cursor-color", x_set_cursor_color,
685 "cursor-type", x_set_cursor_type,
686 "font", x_set_font,
687 "foreground-color", x_set_foreground_color,
688 "icon-name", x_set_icon_name,
689 "icon-type", x_set_icon_type,
690 "internal-border-width", x_set_internal_border_width,
691 "menu-bar-lines", x_set_menu_bar_lines,
692 "mouse-color", x_set_mouse_color,
693 "name", x_explicitly_set_name,
694 "scroll-bar-width", x_set_scroll_bar_width,
695 "title", x_set_title,
696 "unsplittable", x_set_unsplittable,
697 "vertical-scroll-bars", x_set_vertical_scroll_bars,
698 "visibility", x_set_visibility,
699 };
700
701 /* Attach the `x-frame-parameter' properties to
702 the Lisp symbol names of parameters relevant to X. */
703
704 init_x_parm_symbols ()
705 {
706 int i;
707
708 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
709 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
710 make_number (i));
711 }
712 \f
713 /* Change the parameters of FRAME as specified by ALIST.
714 If a parameter is not specially recognized, do nothing;
715 otherwise call the `x_set_...' function for that parameter. */
716
717 void
718 x_set_frame_parameters (f, alist)
719 FRAME_PTR f;
720 Lisp_Object alist;
721 {
722 Lisp_Object tail;
723
724 /* If both of these parameters are present, it's more efficient to
725 set them both at once. So we wait until we've looked at the
726 entire list before we set them. */
727 int width, height;
728
729 /* Same here. */
730 Lisp_Object left, top;
731
732 /* Same with these. */
733 Lisp_Object icon_left, icon_top;
734
735 /* Record in these vectors all the parms specified. */
736 Lisp_Object *parms;
737 Lisp_Object *values;
738 int i;
739 int left_no_change = 0, top_no_change = 0;
740 int icon_left_no_change = 0, icon_top_no_change = 0;
741
742 i = 0;
743 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
744 i++;
745
746 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
747 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
748
749 /* Extract parm names and values into those vectors. */
750
751 i = 0;
752 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
753 {
754 Lisp_Object elt, prop, val;
755
756 elt = Fcar (tail);
757 parms[i] = Fcar (elt);
758 values[i] = Fcdr (elt);
759 i++;
760 }
761
762 top = left = Qunbound;
763 icon_left = icon_top = Qunbound;
764
765 /* Provide default values for HEIGHT and WIDTH. */
766 if (FRAME_NEW_WIDTH (f))
767 width = FRAME_NEW_WIDTH (f);
768 else
769 width = FRAME_WIDTH (f);
770
771 if (FRAME_NEW_HEIGHT (f))
772 height = FRAME_NEW_HEIGHT (f);
773 else
774 height = FRAME_HEIGHT (f);
775
776 /* Now process them in reverse of specified order. */
777 for (i--; i >= 0; i--)
778 {
779 Lisp_Object prop, val;
780
781 prop = parms[i];
782 val = values[i];
783
784 if (EQ (prop, Qwidth) && NUMBERP (val))
785 width = XFASTINT (val);
786 else if (EQ (prop, Qheight) && NUMBERP (val))
787 height = XFASTINT (val);
788 else if (EQ (prop, Qtop))
789 top = val;
790 else if (EQ (prop, Qleft))
791 left = val;
792 else if (EQ (prop, Qicon_top))
793 icon_top = val;
794 else if (EQ (prop, Qicon_left))
795 icon_left = val;
796 else
797 {
798 register Lisp_Object param_index, old_value;
799
800 param_index = Fget (prop, Qx_frame_parameter);
801 old_value = get_frame_param (f, prop);
802 store_frame_param (f, prop, val);
803 if (NATNUMP (param_index)
804 && (XFASTINT (param_index)
805 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
806 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
807 }
808 }
809
810 /* Don't die if just one of these was set. */
811 if (EQ (left, Qunbound))
812 {
813 left_no_change = 1;
814 if (f->output_data.x->left_pos < 0)
815 left = Fcons (Qplus, Fcons (make_number (f->output_data.x->left_pos), Qnil));
816 else
817 XSETINT (left, f->output_data.x->left_pos);
818 }
819 if (EQ (top, Qunbound))
820 {
821 top_no_change = 1;
822 if (f->output_data.x->top_pos < 0)
823 top = Fcons (Qplus, Fcons (make_number (f->output_data.x->top_pos), Qnil));
824 else
825 XSETINT (top, f->output_data.x->top_pos);
826 }
827
828 /* If one of the icon positions was not set, preserve or default it. */
829 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
830 {
831 icon_left_no_change = 1;
832 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
833 if (NILP (icon_left))
834 XSETINT (icon_left, 0);
835 }
836 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
837 {
838 icon_top_no_change = 1;
839 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
840 if (NILP (icon_top))
841 XSETINT (icon_top, 0);
842 }
843
844 /* Don't set these parameters unless they've been explicitly
845 specified. The window might be mapped or resized while we're in
846 this function, and we don't want to override that unless the lisp
847 code has asked for it.
848
849 Don't set these parameters unless they actually differ from the
850 window's current parameters; the window may not actually exist
851 yet. */
852 {
853 Lisp_Object frame;
854
855 check_frame_size (f, &height, &width);
856
857 XSETFRAME (frame, f);
858
859 if (width != FRAME_WIDTH (f)
860 || height != FRAME_HEIGHT (f)
861 || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
862 Fset_frame_size (frame, make_number (width), make_number (height));
863
864 if ((!NILP (left) || !NILP (top))
865 && ! (left_no_change && top_no_change)
866 && ! (NUMBERP (left) && XINT (left) == f->output_data.x->left_pos
867 && NUMBERP (top) && XINT (top) == f->output_data.x->top_pos))
868 {
869 int leftpos = 0;
870 int toppos = 0;
871
872 /* Record the signs. */
873 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
874 if (EQ (left, Qminus))
875 f->output_data.x->size_hint_flags |= XNegative;
876 else if (INTEGERP (left))
877 {
878 leftpos = XINT (left);
879 if (leftpos < 0)
880 f->output_data.x->size_hint_flags |= XNegative;
881 }
882 else if (CONSP (left) && EQ (XCONS (left)->car, Qminus)
883 && CONSP (XCONS (left)->cdr)
884 && INTEGERP (XCONS (XCONS (left)->cdr)->car))
885 {
886 leftpos = - XINT (XCONS (XCONS (left)->cdr)->car);
887 f->output_data.x->size_hint_flags |= XNegative;
888 }
889 else if (CONSP (left) && EQ (XCONS (left)->car, Qplus)
890 && CONSP (XCONS (left)->cdr)
891 && INTEGERP (XCONS (XCONS (left)->cdr)->car))
892 {
893 leftpos = XINT (XCONS (XCONS (left)->cdr)->car);
894 }
895
896 if (EQ (top, Qminus))
897 f->output_data.x->size_hint_flags |= YNegative;
898 else if (INTEGERP (top))
899 {
900 toppos = XINT (top);
901 if (toppos < 0)
902 f->output_data.x->size_hint_flags |= YNegative;
903 }
904 else if (CONSP (top) && EQ (XCONS (top)->car, Qminus)
905 && CONSP (XCONS (top)->cdr)
906 && INTEGERP (XCONS (XCONS (top)->cdr)->car))
907 {
908 toppos = - XINT (XCONS (XCONS (top)->cdr)->car);
909 f->output_data.x->size_hint_flags |= YNegative;
910 }
911 else if (CONSP (top) && EQ (XCONS (top)->car, Qplus)
912 && CONSP (XCONS (top)->cdr)
913 && INTEGERP (XCONS (XCONS (top)->cdr)->car))
914 {
915 toppos = XINT (XCONS (XCONS (top)->cdr)->car);
916 }
917
918
919 /* Store the numeric value of the position. */
920 f->output_data.x->top_pos = toppos;
921 f->output_data.x->left_pos = leftpos;
922
923 f->output_data.x->win_gravity = NorthWestGravity;
924
925 /* Actually set that position, and convert to absolute. */
926 x_set_offset (f, leftpos, toppos, -1);
927 }
928
929 if ((!NILP (icon_left) || !NILP (icon_top))
930 && ! (icon_left_no_change && icon_top_no_change))
931 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
932 }
933 }
934
935 /* Store the screen positions of frame F into XPTR and YPTR.
936 These are the positions of the containing window manager window,
937 not Emacs's own window. */
938
939 void
940 x_real_positions (f, xptr, yptr)
941 FRAME_PTR f;
942 int *xptr, *yptr;
943 {
944 int win_x, win_y;
945 Window child;
946
947 /* This is pretty gross, but seems to be the easiest way out of
948 the problem that arises when restarting window-managers. */
949
950 #ifdef USE_X_TOOLKIT
951 Window outer = XtWindow (f->output_data.x->widget);
952 #else
953 Window outer = f->output_data.x->window_desc;
954 #endif
955 Window tmp_root_window;
956 Window *tmp_children;
957 int tmp_nchildren;
958
959 while (1)
960 {
961 x_catch_errors (FRAME_X_DISPLAY (f));
962
963 XQueryTree (FRAME_X_DISPLAY (f), outer, &tmp_root_window,
964 &f->output_data.x->parent_desc,
965 &tmp_children, &tmp_nchildren);
966 XFree ((char *) tmp_children);
967
968 win_x = win_y = 0;
969
970 /* Find the position of the outside upper-left corner of
971 the inner window, with respect to the outer window. */
972 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
973 {
974 XTranslateCoordinates (FRAME_X_DISPLAY (f),
975
976 /* From-window, to-window. */
977 #ifdef USE_X_TOOLKIT
978 XtWindow (f->output_data.x->widget),
979 #else
980 f->output_data.x->window_desc,
981 #endif
982 f->output_data.x->parent_desc,
983
984 /* From-position, to-position. */
985 0, 0, &win_x, &win_y,
986
987 /* Child of win. */
988 &child);
989
990 #if 0 /* The values seem to be right without this and wrong with. */
991 win_x += f->output_data.x->border_width;
992 win_y += f->output_data.x->border_width;
993 #endif
994 }
995
996 /* It is possible for the window returned by the XQueryNotify
997 to become invalid by the time we call XTranslateCoordinates.
998 That can happen when you restart some window managers.
999 If so, we get an error in XTranslateCoordinates.
1000 Detect that and try the whole thing over. */
1001 if (! x_had_errors_p (FRAME_X_DISPLAY (f)))
1002 {
1003 x_uncatch_errors (FRAME_X_DISPLAY (f));
1004 break;
1005 }
1006
1007 x_uncatch_errors (FRAME_X_DISPLAY (f));
1008 }
1009
1010 *xptr = f->output_data.x->left_pos - win_x;
1011 *yptr = f->output_data.x->top_pos - win_y;
1012 }
1013
1014 /* Insert a description of internally-recorded parameters of frame X
1015 into the parameter alist *ALISTPTR that is to be given to the user.
1016 Only parameters that are specific to the X window system
1017 and whose values are not correctly recorded in the frame's
1018 param_alist need to be considered here. */
1019
1020 x_report_frame_params (f, alistptr)
1021 struct frame *f;
1022 Lisp_Object *alistptr;
1023 {
1024 char buf[16];
1025 Lisp_Object tem;
1026
1027 /* Represent negative positions (off the top or left screen edge)
1028 in a way that Fmodify_frame_parameters will understand correctly. */
1029 XSETINT (tem, f->output_data.x->left_pos);
1030 if (f->output_data.x->left_pos >= 0)
1031 store_in_alist (alistptr, Qleft, tem);
1032 else
1033 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
1034
1035 XSETINT (tem, f->output_data.x->top_pos);
1036 if (f->output_data.x->top_pos >= 0)
1037 store_in_alist (alistptr, Qtop, tem);
1038 else
1039 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
1040
1041 store_in_alist (alistptr, Qborder_width,
1042 make_number (f->output_data.x->border_width));
1043 store_in_alist (alistptr, Qinternal_border_width,
1044 make_number (f->output_data.x->internal_border_width));
1045 sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f));
1046 store_in_alist (alistptr, Qwindow_id,
1047 build_string (buf));
1048 store_in_alist (alistptr, Qicon_name, f->icon_name);
1049 FRAME_SAMPLE_VISIBILITY (f);
1050 store_in_alist (alistptr, Qvisibility,
1051 (FRAME_VISIBLE_P (f) ? Qt
1052 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
1053 store_in_alist (alistptr, Qdisplay,
1054 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->car);
1055
1056 store_in_alist (alistptr, Qparent_id,
1057 (f->output_data.x->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window
1058 ? Qnil : f->output_data.x->parent_desc));
1059 }
1060 \f
1061
1062 /* Decide if color named COLOR is valid for the display associated with
1063 the selected frame; if so, return the rgb values in COLOR_DEF.
1064 If ALLOC is nonzero, allocate a new colormap cell. */
1065
1066 int
1067 defined_color (f, color, color_def, alloc)
1068 FRAME_PTR f;
1069 char *color;
1070 XColor *color_def;
1071 int alloc;
1072 {
1073 register int status;
1074 Colormap screen_colormap;
1075 Display *display = FRAME_X_DISPLAY (f);
1076
1077 BLOCK_INPUT;
1078 screen_colormap = DefaultColormap (display, XDefaultScreen (display));
1079
1080 status = XParseColor (display, screen_colormap, color, color_def);
1081 if (status && alloc)
1082 {
1083 status = XAllocColor (display, screen_colormap, color_def);
1084 if (!status)
1085 {
1086 /* If we got to this point, the colormap is full, so we're
1087 going to try and get the next closest color.
1088 The algorithm used is a least-squares matching, which is
1089 what X uses for closest color matching with StaticColor visuals. */
1090
1091 XColor *cells;
1092 int no_cells;
1093 int nearest;
1094 long nearest_delta, trial_delta;
1095 int x;
1096
1097 no_cells = XDisplayCells (display, XDefaultScreen (display));
1098 cells = (XColor *) alloca (sizeof (XColor) * no_cells);
1099
1100 for (x = 0; x < no_cells; x++)
1101 cells[x].pixel = x;
1102
1103 XQueryColors (display, screen_colormap, cells, no_cells);
1104 nearest = 0;
1105 /* I'm assuming CSE so I'm not going to condense this. */
1106 nearest_delta = ((((color_def->red >> 8) - (cells[0].red >> 8))
1107 * ((color_def->red >> 8) - (cells[0].red >> 8)))
1108 +
1109 (((color_def->green >> 8) - (cells[0].green >> 8))
1110 * ((color_def->green >> 8) - (cells[0].green >> 8)))
1111 +
1112 (((color_def->blue >> 8) - (cells[0].blue >> 8))
1113 * ((color_def->blue >> 8) - (cells[0].blue >> 8))));
1114 for (x = 1; x < no_cells; x++)
1115 {
1116 trial_delta = ((((color_def->red >> 8) - (cells[x].red >> 8))
1117 * ((color_def->red >> 8) - (cells[x].red >> 8)))
1118 +
1119 (((color_def->green >> 8) - (cells[x].green >> 8))
1120 * ((color_def->green >> 8) - (cells[x].green >> 8)))
1121 +
1122 (((color_def->blue >> 8) - (cells[x].blue >> 8))
1123 * ((color_def->blue >> 8) - (cells[x].blue >> 8))));
1124 if (trial_delta < nearest_delta)
1125 {
1126 XColor temp;
1127 temp.red = cells[x].red;
1128 temp.green = cells[x].green;
1129 temp.blue = cells[x].blue;
1130 status = XAllocColor (display, screen_colormap, &temp);
1131 if (status)
1132 {
1133 nearest = x;
1134 nearest_delta = trial_delta;
1135 }
1136 }
1137 }
1138 color_def->red = cells[nearest].red;
1139 color_def->green = cells[nearest].green;
1140 color_def->blue = cells[nearest].blue;
1141 status = XAllocColor (display, screen_colormap, color_def);
1142 }
1143 }
1144 UNBLOCK_INPUT;
1145
1146 if (status)
1147 return 1;
1148 else
1149 return 0;
1150 }
1151
1152 /* Given a string ARG naming a color, compute a pixel value from it
1153 suitable for screen F.
1154 If F is not a color screen, return DEF (default) regardless of what
1155 ARG says. */
1156
1157 int
1158 x_decode_color (f, arg, def)
1159 FRAME_PTR f;
1160 Lisp_Object arg;
1161 int def;
1162 {
1163 XColor cdef;
1164
1165 CHECK_STRING (arg, 0);
1166
1167 if (strcmp (XSTRING (arg)->data, "black") == 0)
1168 return BLACK_PIX_DEFAULT (f);
1169 else if (strcmp (XSTRING (arg)->data, "white") == 0)
1170 return WHITE_PIX_DEFAULT (f);
1171
1172 if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
1173 return def;
1174
1175 /* defined_color is responsible for coping with failures
1176 by looking for a near-miss. */
1177 if (defined_color (f, XSTRING (arg)->data, &cdef, 1))
1178 return cdef.pixel;
1179
1180 Fsignal (Qerror, Fcons (build_string ("undefined color"),
1181 Fcons (arg, Qnil)));
1182 }
1183 \f
1184 /* Functions called only from `x_set_frame_param'
1185 to set individual parameters.
1186
1187 If FRAME_X_WINDOW (f) is 0,
1188 the frame is being created and its X-window does not exist yet.
1189 In that case, just record the parameter's new value
1190 in the standard place; do not attempt to change the window. */
1191
1192 void
1193 x_set_foreground_color (f, arg, oldval)
1194 struct frame *f;
1195 Lisp_Object arg, oldval;
1196 {
1197 f->output_data.x->foreground_pixel
1198 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1199 if (FRAME_X_WINDOW (f) != 0)
1200 {
1201 BLOCK_INPUT;
1202 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
1203 f->output_data.x->foreground_pixel);
1204 XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
1205 f->output_data.x->foreground_pixel);
1206 UNBLOCK_INPUT;
1207 recompute_basic_faces (f);
1208 if (FRAME_VISIBLE_P (f))
1209 redraw_frame (f);
1210 }
1211 }
1212
1213 void
1214 x_set_background_color (f, arg, oldval)
1215 struct frame *f;
1216 Lisp_Object arg, oldval;
1217 {
1218 Pixmap temp;
1219 int mask;
1220
1221 f->output_data.x->background_pixel
1222 = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1223
1224 if (FRAME_X_WINDOW (f) != 0)
1225 {
1226 BLOCK_INPUT;
1227 /* The main frame area. */
1228 XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
1229 f->output_data.x->background_pixel);
1230 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
1231 f->output_data.x->background_pixel);
1232 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
1233 f->output_data.x->background_pixel);
1234 XSetWindowBackground (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1235 f->output_data.x->background_pixel);
1236 {
1237 Lisp_Object bar;
1238 for (bar = FRAME_SCROLL_BARS (f); !NILP (bar);
1239 bar = XSCROLL_BAR (bar)->next)
1240 XSetWindowBackground (FRAME_X_DISPLAY (f),
1241 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
1242 f->output_data.x->background_pixel);
1243 }
1244 UNBLOCK_INPUT;
1245
1246 recompute_basic_faces (f);
1247
1248 if (FRAME_VISIBLE_P (f))
1249 redraw_frame (f);
1250 }
1251 }
1252
1253 void
1254 x_set_mouse_color (f, arg, oldval)
1255 struct frame *f;
1256 Lisp_Object arg, oldval;
1257 {
1258 Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
1259 int mask_color;
1260
1261 if (!EQ (Qnil, arg))
1262 f->output_data.x->mouse_pixel
1263 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1264 mask_color = f->output_data.x->background_pixel;
1265 /* No invisible pointers. */
1266 if (mask_color == f->output_data.x->mouse_pixel
1267 && mask_color == f->output_data.x->background_pixel)
1268 f->output_data.x->mouse_pixel = f->output_data.x->foreground_pixel;
1269
1270 BLOCK_INPUT;
1271
1272 /* It's not okay to crash if the user selects a screwy cursor. */
1273 x_catch_errors (FRAME_X_DISPLAY (f));
1274
1275 if (!EQ (Qnil, Vx_pointer_shape))
1276 {
1277 CHECK_NUMBER (Vx_pointer_shape, 0);
1278 cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XINT (Vx_pointer_shape));
1279 }
1280 else
1281 cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_xterm);
1282 x_check_errors (FRAME_X_DISPLAY (f), "bad text pointer cursor: %s");
1283
1284 if (!EQ (Qnil, Vx_nontext_pointer_shape))
1285 {
1286 CHECK_NUMBER (Vx_nontext_pointer_shape, 0);
1287 nontext_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
1288 XINT (Vx_nontext_pointer_shape));
1289 }
1290 else
1291 nontext_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_left_ptr);
1292 x_check_errors (FRAME_X_DISPLAY (f), "bad nontext pointer cursor: %s");
1293
1294 if (!EQ (Qnil, Vx_mode_pointer_shape))
1295 {
1296 CHECK_NUMBER (Vx_mode_pointer_shape, 0);
1297 mode_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
1298 XINT (Vx_mode_pointer_shape));
1299 }
1300 else
1301 mode_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_xterm);
1302 x_check_errors (FRAME_X_DISPLAY (f), "bad modeline pointer cursor: %s");
1303
1304 if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
1305 {
1306 CHECK_NUMBER (Vx_sensitive_text_pointer_shape, 0);
1307 cross_cursor
1308 = XCreateFontCursor (FRAME_X_DISPLAY (f),
1309 XINT (Vx_sensitive_text_pointer_shape));
1310 }
1311 else
1312 cross_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_crosshair);
1313
1314 /* Check and report errors with the above calls. */
1315 x_check_errors (FRAME_X_DISPLAY (f), "can't set cursor shape: %s");
1316 x_uncatch_errors (FRAME_X_DISPLAY (f));
1317
1318 {
1319 XColor fore_color, back_color;
1320
1321 fore_color.pixel = f->output_data.x->mouse_pixel;
1322 back_color.pixel = mask_color;
1323 XQueryColor (FRAME_X_DISPLAY (f),
1324 DefaultColormap (FRAME_X_DISPLAY (f),
1325 DefaultScreen (FRAME_X_DISPLAY (f))),
1326 &fore_color);
1327 XQueryColor (FRAME_X_DISPLAY (f),
1328 DefaultColormap (FRAME_X_DISPLAY (f),
1329 DefaultScreen (FRAME_X_DISPLAY (f))),
1330 &back_color);
1331 XRecolorCursor (FRAME_X_DISPLAY (f), cursor,
1332 &fore_color, &back_color);
1333 XRecolorCursor (FRAME_X_DISPLAY (f), nontext_cursor,
1334 &fore_color, &back_color);
1335 XRecolorCursor (FRAME_X_DISPLAY (f), mode_cursor,
1336 &fore_color, &back_color);
1337 XRecolorCursor (FRAME_X_DISPLAY (f), cross_cursor,
1338 &fore_color, &back_color);
1339 }
1340
1341 if (FRAME_X_WINDOW (f) != 0)
1342 {
1343 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
1344 }
1345
1346 if (cursor != f->output_data.x->text_cursor && f->output_data.x->text_cursor != 0)
1347 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->text_cursor);
1348 f->output_data.x->text_cursor = cursor;
1349
1350 if (nontext_cursor != f->output_data.x->nontext_cursor
1351 && f->output_data.x->nontext_cursor != 0)
1352 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->nontext_cursor);
1353 f->output_data.x->nontext_cursor = nontext_cursor;
1354
1355 if (mode_cursor != f->output_data.x->modeline_cursor
1356 && f->output_data.x->modeline_cursor != 0)
1357 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->modeline_cursor);
1358 f->output_data.x->modeline_cursor = mode_cursor;
1359 if (cross_cursor != f->output_data.x->cross_cursor
1360 && f->output_data.x->cross_cursor != 0)
1361 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->cross_cursor);
1362 f->output_data.x->cross_cursor = cross_cursor;
1363
1364 XFlush (FRAME_X_DISPLAY (f));
1365 UNBLOCK_INPUT;
1366 }
1367
1368 void
1369 x_set_cursor_color (f, arg, oldval)
1370 struct frame *f;
1371 Lisp_Object arg, oldval;
1372 {
1373 unsigned long fore_pixel;
1374
1375 if (!EQ (Vx_cursor_fore_pixel, Qnil))
1376 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1377 WHITE_PIX_DEFAULT (f));
1378 else
1379 fore_pixel = f->output_data.x->background_pixel;
1380 f->output_data.x->cursor_pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1381
1382 /* Make sure that the cursor color differs from the background color. */
1383 if (f->output_data.x->cursor_pixel == f->output_data.x->background_pixel)
1384 {
1385 f->output_data.x->cursor_pixel = f->output_data.x->mouse_pixel;
1386 if (f->output_data.x->cursor_pixel == fore_pixel)
1387 fore_pixel = f->output_data.x->background_pixel;
1388 }
1389 f->output_data.x->cursor_foreground_pixel = fore_pixel;
1390
1391 if (FRAME_X_WINDOW (f) != 0)
1392 {
1393 BLOCK_INPUT;
1394 XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
1395 f->output_data.x->cursor_pixel);
1396 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
1397 fore_pixel);
1398 UNBLOCK_INPUT;
1399
1400 if (FRAME_VISIBLE_P (f))
1401 {
1402 x_update_cursor (f, 0);
1403 x_update_cursor (f, 1);
1404 }
1405 }
1406 }
1407 \f
1408 /* Set the border-color of frame F to value described by ARG.
1409 ARG can be a string naming a color.
1410 The border-color is used for the border that is drawn by the X server.
1411 Note that this does not fully take effect if done before
1412 F has an x-window; it must be redone when the window is created.
1413
1414 Note: this is done in two routines because of the way X10 works.
1415
1416 Note: under X11, this is normally the province of the window manager,
1417 and so emacs' border colors may be overridden. */
1418
1419 void
1420 x_set_border_color (f, arg, oldval)
1421 struct frame *f;
1422 Lisp_Object arg, oldval;
1423 {
1424 unsigned char *str;
1425 int pix;
1426
1427 CHECK_STRING (arg, 0);
1428 str = XSTRING (arg)->data;
1429
1430 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1431
1432 x_set_border_pixel (f, pix);
1433 }
1434
1435 /* Set the border-color of frame F to pixel value PIX.
1436 Note that this does not fully take effect if done before
1437 F has an x-window. */
1438
1439 x_set_border_pixel (f, pix)
1440 struct frame *f;
1441 int pix;
1442 {
1443 f->output_data.x->border_pixel = pix;
1444
1445 if (FRAME_X_WINDOW (f) != 0 && f->output_data.x->border_width > 0)
1446 {
1447 Pixmap temp;
1448 int mask;
1449
1450 BLOCK_INPUT;
1451 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1452 (unsigned long)pix);
1453 UNBLOCK_INPUT;
1454
1455 if (FRAME_VISIBLE_P (f))
1456 redraw_frame (f);
1457 }
1458 }
1459
1460 void
1461 x_set_cursor_type (f, arg, oldval)
1462 FRAME_PTR f;
1463 Lisp_Object arg, oldval;
1464 {
1465 if (EQ (arg, Qbar))
1466 {
1467 FRAME_DESIRED_CURSOR (f) = bar_cursor;
1468 f->output_data.x->cursor_width = 2;
1469 }
1470 else if (CONSP (arg) && EQ (XCONS (arg)->car, Qbar)
1471 && INTEGERP (XCONS (arg)->cdr))
1472 {
1473 FRAME_DESIRED_CURSOR (f) = bar_cursor;
1474 f->output_data.x->cursor_width = XINT (XCONS (arg)->cdr);
1475 }
1476 else
1477 /* Treat anything unknown as "box cursor".
1478 It was bad to signal an error; people have trouble fixing
1479 .Xdefaults with Emacs, when it has something bad in it. */
1480 FRAME_DESIRED_CURSOR (f) = filled_box_cursor;
1481
1482 /* Make sure the cursor gets redrawn. This is overkill, but how
1483 often do people change cursor types? */
1484 update_mode_lines++;
1485 }
1486 \f
1487 void
1488 x_set_icon_type (f, arg, oldval)
1489 struct frame *f;
1490 Lisp_Object arg, oldval;
1491 {
1492 Lisp_Object tem;
1493 int result;
1494
1495 if (STRINGP (arg))
1496 {
1497 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1498 return;
1499 }
1500 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1501 return;
1502
1503 BLOCK_INPUT;
1504 if (NILP (arg))
1505 result = x_text_icon (f,
1506 (char *) XSTRING ((!NILP (f->icon_name)
1507 ? f->icon_name
1508 : f->name))->data);
1509 else
1510 result = x_bitmap_icon (f, arg);
1511
1512 if (result)
1513 {
1514 UNBLOCK_INPUT;
1515 error ("No icon window available");
1516 }
1517
1518 XFlush (FRAME_X_DISPLAY (f));
1519 UNBLOCK_INPUT;
1520 }
1521
1522 /* Return non-nil if frame F wants a bitmap icon. */
1523
1524 Lisp_Object
1525 x_icon_type (f)
1526 FRAME_PTR f;
1527 {
1528 Lisp_Object tem;
1529
1530 tem = assq_no_quit (Qicon_type, f->param_alist);
1531 if (CONSP (tem))
1532 return XCONS (tem)->cdr;
1533 else
1534 return Qnil;
1535 }
1536
1537 void
1538 x_set_icon_name (f, arg, oldval)
1539 struct frame *f;
1540 Lisp_Object arg, oldval;
1541 {
1542 Lisp_Object tem;
1543 int result;
1544
1545 if (STRINGP (arg))
1546 {
1547 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1548 return;
1549 }
1550 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1551 return;
1552
1553 f->icon_name = arg;
1554
1555 if (f->output_data.x->icon_bitmap != 0)
1556 return;
1557
1558 BLOCK_INPUT;
1559
1560 result = x_text_icon (f,
1561 (char *) XSTRING ((!NILP (f->icon_name)
1562 ? f->icon_name
1563 : !NILP (f->title)
1564 ? f->title
1565 : f->name))->data);
1566
1567 if (result)
1568 {
1569 UNBLOCK_INPUT;
1570 error ("No icon window available");
1571 }
1572
1573 XFlush (FRAME_X_DISPLAY (f));
1574 UNBLOCK_INPUT;
1575 }
1576 \f
1577 extern Lisp_Object x_new_font ();
1578
1579 void
1580 x_set_font (f, arg, oldval)
1581 struct frame *f;
1582 Lisp_Object arg, oldval;
1583 {
1584 Lisp_Object result;
1585
1586 CHECK_STRING (arg, 1);
1587
1588 BLOCK_INPUT;
1589 result = x_new_font (f, XSTRING (arg)->data);
1590 UNBLOCK_INPUT;
1591
1592 if (EQ (result, Qnil))
1593 error ("Font `%s' is not defined", XSTRING (arg)->data);
1594 else if (EQ (result, Qt))
1595 error ("the characters of the given font have varying widths");
1596 else if (STRINGP (result))
1597 {
1598 recompute_basic_faces (f);
1599 store_frame_param (f, Qfont, result);
1600 }
1601 else
1602 abort ();
1603 }
1604
1605 void
1606 x_set_border_width (f, arg, oldval)
1607 struct frame *f;
1608 Lisp_Object arg, oldval;
1609 {
1610 CHECK_NUMBER (arg, 0);
1611
1612 if (XINT (arg) == f->output_data.x->border_width)
1613 return;
1614
1615 if (FRAME_X_WINDOW (f) != 0)
1616 error ("Cannot change the border width of a window");
1617
1618 f->output_data.x->border_width = XINT (arg);
1619 }
1620
1621 void
1622 x_set_internal_border_width (f, arg, oldval)
1623 struct frame *f;
1624 Lisp_Object arg, oldval;
1625 {
1626 int mask;
1627 int old = f->output_data.x->internal_border_width;
1628
1629 CHECK_NUMBER (arg, 0);
1630 f->output_data.x->internal_border_width = XINT (arg);
1631 if (f->output_data.x->internal_border_width < 0)
1632 f->output_data.x->internal_border_width = 0;
1633
1634 if (f->output_data.x->internal_border_width == old)
1635 return;
1636
1637 if (FRAME_X_WINDOW (f) != 0)
1638 {
1639 BLOCK_INPUT;
1640 x_set_window_size (f, 0, f->width, f->height);
1641 #if 0
1642 x_set_resize_hint (f);
1643 #endif
1644 XFlush (FRAME_X_DISPLAY (f));
1645 UNBLOCK_INPUT;
1646 SET_FRAME_GARBAGED (f);
1647 }
1648 }
1649
1650 void
1651 x_set_visibility (f, value, oldval)
1652 struct frame *f;
1653 Lisp_Object value, oldval;
1654 {
1655 Lisp_Object frame;
1656 XSETFRAME (frame, f);
1657
1658 if (NILP (value))
1659 Fmake_frame_invisible (frame, Qt);
1660 else if (EQ (value, Qicon))
1661 Ficonify_frame (frame);
1662 else
1663 Fmake_frame_visible (frame);
1664 }
1665 \f
1666 static void
1667 x_set_menu_bar_lines_1 (window, n)
1668 Lisp_Object window;
1669 int n;
1670 {
1671 struct window *w = XWINDOW (window);
1672
1673 XSETFASTINT (w->top, XFASTINT (w->top) + n);
1674 XSETFASTINT (w->height, XFASTINT (w->height) - n);
1675
1676 /* Handle just the top child in a vertical split. */
1677 if (!NILP (w->vchild))
1678 x_set_menu_bar_lines_1 (w->vchild, n);
1679
1680 /* Adjust all children in a horizontal split. */
1681 for (window = w->hchild; !NILP (window); window = w->next)
1682 {
1683 w = XWINDOW (window);
1684 x_set_menu_bar_lines_1 (window, n);
1685 }
1686 }
1687
1688 void
1689 x_set_menu_bar_lines (f, value, oldval)
1690 struct frame *f;
1691 Lisp_Object value, oldval;
1692 {
1693 int nlines;
1694 int olines = FRAME_MENU_BAR_LINES (f);
1695
1696 /* Right now, menu bars don't work properly in minibuf-only frames;
1697 most of the commands try to apply themselves to the minibuffer
1698 frame itslef, and get an error because you can't switch buffers
1699 in or split the minibuffer window. */
1700 if (FRAME_MINIBUF_ONLY_P (f))
1701 return;
1702
1703 if (INTEGERP (value))
1704 nlines = XINT (value);
1705 else
1706 nlines = 0;
1707
1708 #ifdef USE_X_TOOLKIT
1709 FRAME_MENU_BAR_LINES (f) = 0;
1710 if (nlines)
1711 {
1712 FRAME_EXTERNAL_MENU_BAR (f) = 1;
1713 if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
1714 /* Make sure next redisplay shows the menu bar. */
1715 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt;
1716 }
1717 else
1718 {
1719 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
1720 free_frame_menubar (f);
1721 FRAME_EXTERNAL_MENU_BAR (f) = 0;
1722 if (FRAME_X_P (f))
1723 f->output_data.x->menubar_widget = 0;
1724 }
1725 #else /* not USE_X_TOOLKIT */
1726 FRAME_MENU_BAR_LINES (f) = nlines;
1727 x_set_menu_bar_lines_1 (f->root_window, nlines - olines);
1728 #endif /* not USE_X_TOOLKIT */
1729 }
1730 \f
1731 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
1732 x_id_name.
1733
1734 If EXPLICIT is non-zero, that indicates that lisp code is setting the
1735 name; if NAME is a string, set F's name to NAME and set
1736 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1737
1738 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1739 suggesting a new name, which lisp code should override; if
1740 F->explicit_name is set, ignore the new name; otherwise, set it. */
1741
1742 void
1743 x_set_name (f, name, explicit)
1744 struct frame *f;
1745 Lisp_Object name;
1746 int explicit;
1747 {
1748 /* Make sure that requests from lisp code override requests from
1749 Emacs redisplay code. */
1750 if (explicit)
1751 {
1752 /* If we're switching from explicit to implicit, we had better
1753 update the mode lines and thereby update the title. */
1754 if (f->explicit_name && NILP (name))
1755 update_mode_lines = 1;
1756
1757 f->explicit_name = ! NILP (name);
1758 }
1759 else if (f->explicit_name)
1760 return;
1761
1762 /* If NAME is nil, set the name to the x_id_name. */
1763 if (NILP (name))
1764 {
1765 /* Check for no change needed in this very common case
1766 before we do any consing. */
1767 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
1768 XSTRING (f->name)->data))
1769 return;
1770 name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
1771 }
1772 else
1773 CHECK_STRING (name, 0);
1774
1775 /* Don't change the name if it's already NAME. */
1776 if (! NILP (Fstring_equal (name, f->name)))
1777 return;
1778
1779 f->name = name;
1780
1781 /* For setting the frame title, the title parameter should override
1782 the name parameter. */
1783 if (! NILP (f->title))
1784 name = f->title;
1785
1786 if (FRAME_X_WINDOW (f))
1787 {
1788 BLOCK_INPUT;
1789 #ifdef HAVE_X11R4
1790 {
1791 XTextProperty text, icon;
1792 Lisp_Object icon_name;
1793
1794 text.value = XSTRING (name)->data;
1795 text.encoding = XA_STRING;
1796 text.format = 8;
1797 text.nitems = XSTRING (name)->size;
1798
1799 icon_name = (!NILP (f->icon_name) ? f->icon_name : name);
1800
1801 icon.value = XSTRING (icon_name)->data;
1802 icon.encoding = XA_STRING;
1803 icon.format = 8;
1804 icon.nitems = XSTRING (icon_name)->size;
1805 #ifdef USE_X_TOOLKIT
1806 XSetWMName (FRAME_X_DISPLAY (f),
1807 XtWindow (f->output_data.x->widget), &text);
1808 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
1809 &icon);
1810 #else /* not USE_X_TOOLKIT */
1811 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
1812 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
1813 #endif /* not USE_X_TOOLKIT */
1814 }
1815 #else /* not HAVE_X11R4 */
1816 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1817 XSTRING (name)->data);
1818 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1819 XSTRING (name)->data);
1820 #endif /* not HAVE_X11R4 */
1821 UNBLOCK_INPUT;
1822 }
1823 }
1824
1825 /* This function should be called when the user's lisp code has
1826 specified a name for the frame; the name will override any set by the
1827 redisplay code. */
1828 void
1829 x_explicitly_set_name (f, arg, oldval)
1830 FRAME_PTR f;
1831 Lisp_Object arg, oldval;
1832 {
1833 x_set_name (f, arg, 1);
1834 }
1835
1836 /* This function should be called by Emacs redisplay code to set the
1837 name; names set this way will never override names set by the user's
1838 lisp code. */
1839 void
1840 x_implicitly_set_name (f, arg, oldval)
1841 FRAME_PTR f;
1842 Lisp_Object arg, oldval;
1843 {
1844 x_set_name (f, arg, 0);
1845 }
1846 \f
1847 /* Change the title of frame F to NAME.
1848 If NAME is nil, use the frame name as the title.
1849
1850 If EXPLICIT is non-zero, that indicates that lisp code is setting the
1851 name; if NAME is a string, set F's name to NAME and set
1852 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1853
1854 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1855 suggesting a new name, which lisp code should override; if
1856 F->explicit_name is set, ignore the new name; otherwise, set it. */
1857
1858 void
1859 x_set_title (f, name)
1860 struct frame *f;
1861 Lisp_Object name;
1862 {
1863 /* Don't change the title if it's already NAME. */
1864 if (EQ (name, f->title))
1865 return;
1866
1867 update_mode_lines = 1;
1868
1869 f->title = name;
1870
1871 if (NILP (name))
1872 name = f->name;
1873
1874 if (FRAME_X_WINDOW (f))
1875 {
1876 BLOCK_INPUT;
1877 #ifdef HAVE_X11R4
1878 {
1879 XTextProperty text, icon;
1880 Lisp_Object icon_name;
1881
1882 text.value = XSTRING (name)->data;
1883 text.encoding = XA_STRING;
1884 text.format = 8;
1885 text.nitems = XSTRING (name)->size;
1886
1887 icon_name = (!NILP (f->icon_name) ? f->icon_name : name);
1888
1889 icon.value = XSTRING (icon_name)->data;
1890 icon.encoding = XA_STRING;
1891 icon.format = 8;
1892 icon.nitems = XSTRING (icon_name)->size;
1893 #ifdef USE_X_TOOLKIT
1894 XSetWMName (FRAME_X_DISPLAY (f),
1895 XtWindow (f->output_data.x->widget), &text);
1896 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
1897 &icon);
1898 #else /* not USE_X_TOOLKIT */
1899 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
1900 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
1901 #endif /* not USE_X_TOOLKIT */
1902 }
1903 #else /* not HAVE_X11R4 */
1904 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1905 XSTRING (name)->data);
1906 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1907 XSTRING (name)->data);
1908 #endif /* not HAVE_X11R4 */
1909 UNBLOCK_INPUT;
1910 }
1911 }
1912 \f
1913 void
1914 x_set_autoraise (f, arg, oldval)
1915 struct frame *f;
1916 Lisp_Object arg, oldval;
1917 {
1918 f->auto_raise = !EQ (Qnil, arg);
1919 }
1920
1921 void
1922 x_set_autolower (f, arg, oldval)
1923 struct frame *f;
1924 Lisp_Object arg, oldval;
1925 {
1926 f->auto_lower = !EQ (Qnil, arg);
1927 }
1928
1929 void
1930 x_set_unsplittable (f, arg, oldval)
1931 struct frame *f;
1932 Lisp_Object arg, oldval;
1933 {
1934 f->no_split = !NILP (arg);
1935 }
1936
1937 void
1938 x_set_vertical_scroll_bars (f, arg, oldval)
1939 struct frame *f;
1940 Lisp_Object arg, oldval;
1941 {
1942 if (NILP (arg) != ! FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1943 {
1944 FRAME_HAS_VERTICAL_SCROLL_BARS (f) = ! NILP (arg);
1945
1946 /* We set this parameter before creating the X window for the
1947 frame, so we can get the geometry right from the start.
1948 However, if the window hasn't been created yet, we shouldn't
1949 call x_set_window_size. */
1950 if (FRAME_X_WINDOW (f))
1951 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
1952 }
1953 }
1954
1955 void
1956 x_set_scroll_bar_width (f, arg, oldval)
1957 struct frame *f;
1958 Lisp_Object arg, oldval;
1959 {
1960 if (NILP (arg))
1961 {
1962 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
1963 FRAME_SCROLL_BAR_COLS (f) = 2;
1964 if (FRAME_X_WINDOW (f))
1965 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
1966 }
1967 else if (INTEGERP (arg) && XINT (arg) > 0
1968 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
1969 {
1970 int wid = FONT_WIDTH (f->output_data.x->font);
1971 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
1972 FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
1973 if (FRAME_X_WINDOW (f))
1974 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
1975 }
1976 }
1977 \f
1978 /* Subroutines of creating an X frame. */
1979
1980 /* Make sure that Vx_resource_name is set to a reasonable value.
1981 Fix it up, or set it to `emacs' if it is too hopeless. */
1982
1983 static void
1984 validate_x_resource_name ()
1985 {
1986 int len;
1987 /* Number of valid characters in the resource name. */
1988 int good_count = 0;
1989 /* Number of invalid characters in the resource name. */
1990 int bad_count = 0;
1991 Lisp_Object new;
1992 int i;
1993
1994 if (STRINGP (Vx_resource_name))
1995 {
1996 unsigned char *p = XSTRING (Vx_resource_name)->data;
1997 int i;
1998
1999 len = XSTRING (Vx_resource_name)->size;
2000
2001 /* Only letters, digits, - and _ are valid in resource names.
2002 Count the valid characters and count the invalid ones. */
2003 for (i = 0; i < len; i++)
2004 {
2005 int c = p[i];
2006 if (! ((c >= 'a' && c <= 'z')
2007 || (c >= 'A' && c <= 'Z')
2008 || (c >= '0' && c <= '9')
2009 || c == '-' || c == '_'))
2010 bad_count++;
2011 else
2012 good_count++;
2013 }
2014 }
2015 else
2016 /* Not a string => completely invalid. */
2017 bad_count = 5, good_count = 0;
2018
2019 /* If name is valid already, return. */
2020 if (bad_count == 0)
2021 return;
2022
2023 /* If name is entirely invalid, or nearly so, use `emacs'. */
2024 if (good_count == 0
2025 || (good_count == 1 && bad_count > 0))
2026 {
2027 Vx_resource_name = build_string ("emacs");
2028 return;
2029 }
2030
2031 /* Name is partly valid. Copy it and replace the invalid characters
2032 with underscores. */
2033
2034 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
2035
2036 for (i = 0; i < len; i++)
2037 {
2038 int c = XSTRING (new)->data[i];
2039 if (! ((c >= 'a' && c <= 'z')
2040 || (c >= 'A' && c <= 'Z')
2041 || (c >= '0' && c <= '9')
2042 || c == '-' || c == '_'))
2043 XSTRING (new)->data[i] = '_';
2044 }
2045 }
2046
2047
2048 extern char *x_get_string_resource ();
2049
2050 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
2051 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2052 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2053 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2054 the name specified by the `-name' or `-rn' command-line arguments.\n\
2055 \n\
2056 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2057 class, respectively. You must specify both of them or neither.\n\
2058 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2059 and the class is `Emacs.CLASS.SUBCLASS'.")
2060 (attribute, class, component, subclass)
2061 Lisp_Object attribute, class, component, subclass;
2062 {
2063 register char *value;
2064 char *name_key;
2065 char *class_key;
2066
2067 check_x ();
2068
2069 CHECK_STRING (attribute, 0);
2070 CHECK_STRING (class, 0);
2071
2072 if (!NILP (component))
2073 CHECK_STRING (component, 1);
2074 if (!NILP (subclass))
2075 CHECK_STRING (subclass, 2);
2076 if (NILP (component) != NILP (subclass))
2077 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2078
2079 validate_x_resource_name ();
2080
2081 /* Allocate space for the components, the dots which separate them,
2082 and the final '\0'. Make them big enough for the worst case. */
2083 name_key = (char *) alloca (XSTRING (Vx_resource_name)->size
2084 + (STRINGP (component)
2085 ? XSTRING (component)->size : 0)
2086 + XSTRING (attribute)->size
2087 + 3);
2088
2089 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2090 + XSTRING (class)->size
2091 + (STRINGP (subclass)
2092 ? XSTRING (subclass)->size : 0)
2093 + 3);
2094
2095 /* Start with emacs.FRAMENAME for the name (the specific one)
2096 and with `Emacs' for the class key (the general one). */
2097 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2098 strcpy (class_key, EMACS_CLASS);
2099
2100 strcat (class_key, ".");
2101 strcat (class_key, XSTRING (class)->data);
2102
2103 if (!NILP (component))
2104 {
2105 strcat (class_key, ".");
2106 strcat (class_key, XSTRING (subclass)->data);
2107
2108 strcat (name_key, ".");
2109 strcat (name_key, XSTRING (component)->data);
2110 }
2111
2112 strcat (name_key, ".");
2113 strcat (name_key, XSTRING (attribute)->data);
2114
2115 value = x_get_string_resource (check_x_display_info (Qnil)->xrdb,
2116 name_key, class_key);
2117
2118 if (value != (char *) 0)
2119 return build_string (value);
2120 else
2121 return Qnil;
2122 }
2123
2124 /* Used when C code wants a resource value. */
2125
2126 char *
2127 x_get_resource_string (attribute, class)
2128 char *attribute, *class;
2129 {
2130 register char *value;
2131 char *name_key;
2132 char *class_key;
2133
2134 /* Allocate space for the components, the dots which separate them,
2135 and the final '\0'. */
2136 name_key = (char *) alloca (XSTRING (Vinvocation_name)->size
2137 + strlen (attribute) + 2);
2138 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2139 + strlen (class) + 2);
2140
2141 sprintf (name_key, "%s.%s",
2142 XSTRING (Vinvocation_name)->data,
2143 attribute);
2144 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
2145
2146 return x_get_string_resource (FRAME_X_DISPLAY_INFO (selected_frame)->xrdb,
2147 name_key, class_key);
2148 }
2149
2150 /* Types we might convert a resource string into. */
2151 enum resource_types
2152 {
2153 number, boolean, string, symbol
2154 };
2155
2156 /* Return the value of parameter PARAM.
2157
2158 First search ALIST, then Vdefault_frame_alist, then the X defaults
2159 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2160
2161 Convert the resource to the type specified by desired_type.
2162
2163 If no default is specified, return Qunbound. If you call
2164 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2165 and don't let it get stored in any Lisp-visible variables! */
2166
2167 static Lisp_Object
2168 x_get_arg (alist, param, attribute, class, type)
2169 Lisp_Object alist, param;
2170 char *attribute;
2171 char *class;
2172 enum resource_types type;
2173 {
2174 register Lisp_Object tem;
2175
2176 tem = Fassq (param, alist);
2177 if (EQ (tem, Qnil))
2178 tem = Fassq (param, Vdefault_frame_alist);
2179 if (EQ (tem, Qnil))
2180 {
2181
2182 if (attribute)
2183 {
2184 tem = Fx_get_resource (build_string (attribute),
2185 build_string (class),
2186 Qnil, Qnil);
2187
2188 if (NILP (tem))
2189 return Qunbound;
2190
2191 switch (type)
2192 {
2193 case number:
2194 return make_number (atoi (XSTRING (tem)->data));
2195
2196 case boolean:
2197 tem = Fdowncase (tem);
2198 if (!strcmp (XSTRING (tem)->data, "on")
2199 || !strcmp (XSTRING (tem)->data, "true"))
2200 return Qt;
2201 else
2202 return Qnil;
2203
2204 case string:
2205 return tem;
2206
2207 case symbol:
2208 /* As a special case, we map the values `true' and `on'
2209 to Qt, and `false' and `off' to Qnil. */
2210 {
2211 Lisp_Object lower;
2212 lower = Fdowncase (tem);
2213 if (!strcmp (XSTRING (lower)->data, "on")
2214 || !strcmp (XSTRING (lower)->data, "true"))
2215 return Qt;
2216 else if (!strcmp (XSTRING (lower)->data, "off")
2217 || !strcmp (XSTRING (lower)->data, "false"))
2218 return Qnil;
2219 else
2220 return Fintern (tem, Qnil);
2221 }
2222
2223 default:
2224 abort ();
2225 }
2226 }
2227 else
2228 return Qunbound;
2229 }
2230 return Fcdr (tem);
2231 }
2232
2233 /* Like x_get_arg, but also record the value in f->param_alist. */
2234
2235 static Lisp_Object
2236 x_get_and_record_arg (f, alist, param, attribute, class, type)
2237 struct frame *f;
2238 Lisp_Object alist, param;
2239 char *attribute;
2240 char *class;
2241 enum resource_types type;
2242 {
2243 Lisp_Object value;
2244
2245 value = x_get_arg (alist, param, attribute, class, type);
2246 if (! NILP (value))
2247 store_frame_param (f, param, value);
2248
2249 return value;
2250 }
2251
2252 /* Record in frame F the specified or default value according to ALIST
2253 of the parameter named PARAM (a Lisp symbol).
2254 If no value is specified for PARAM, look for an X default for XPROP
2255 on the frame named NAME.
2256 If that is not found either, use the value DEFLT. */
2257
2258 static Lisp_Object
2259 x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
2260 struct frame *f;
2261 Lisp_Object alist;
2262 Lisp_Object prop;
2263 Lisp_Object deflt;
2264 char *xprop;
2265 char *xclass;
2266 enum resource_types type;
2267 {
2268 Lisp_Object tem;
2269
2270 tem = x_get_arg (alist, prop, xprop, xclass, type);
2271 if (EQ (tem, Qunbound))
2272 tem = deflt;
2273 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2274 return tem;
2275 }
2276 \f
2277 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
2278 "Parse an X-style geometry string STRING.\n\
2279 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2280 The properties returned may include `top', `left', `height', and `width'.\n\
2281 The value of `left' or `top' may be an integer,\n\
2282 or a list (+ N) meaning N pixels relative to top/left corner,\n\
2283 or a list (- N) meaning -N pixels relative to bottom/right corner.")
2284 (string)
2285 Lisp_Object string;
2286 {
2287 int geometry, x, y;
2288 unsigned int width, height;
2289 Lisp_Object result;
2290
2291 CHECK_STRING (string, 0);
2292
2293 geometry = XParseGeometry ((char *) XSTRING (string)->data,
2294 &x, &y, &width, &height);
2295
2296 #if 0
2297 if (!!(geometry & XValue) != !!(geometry & YValue))
2298 error ("Must specify both x and y position, or neither");
2299 #endif
2300
2301 result = Qnil;
2302 if (geometry & XValue)
2303 {
2304 Lisp_Object element;
2305
2306 if (x >= 0 && (geometry & XNegative))
2307 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
2308 else if (x < 0 && ! (geometry & XNegative))
2309 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
2310 else
2311 element = Fcons (Qleft, make_number (x));
2312 result = Fcons (element, result);
2313 }
2314
2315 if (geometry & YValue)
2316 {
2317 Lisp_Object element;
2318
2319 if (y >= 0 && (geometry & YNegative))
2320 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
2321 else if (y < 0 && ! (geometry & YNegative))
2322 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
2323 else
2324 element = Fcons (Qtop, make_number (y));
2325 result = Fcons (element, result);
2326 }
2327
2328 if (geometry & WidthValue)
2329 result = Fcons (Fcons (Qwidth, make_number (width)), result);
2330 if (geometry & HeightValue)
2331 result = Fcons (Fcons (Qheight, make_number (height)), result);
2332
2333 return result;
2334 }
2335
2336 /* Calculate the desired size and position of this window,
2337 and return the flags saying which aspects were specified.
2338
2339 This function does not make the coordinates positive. */
2340
2341 #define DEFAULT_ROWS 40
2342 #define DEFAULT_COLS 80
2343
2344 static int
2345 x_figure_window_size (f, parms)
2346 struct frame *f;
2347 Lisp_Object parms;
2348 {
2349 register Lisp_Object tem0, tem1, tem2;
2350 int height, width, left, top;
2351 register int geometry;
2352 long window_prompting = 0;
2353
2354 /* Default values if we fall through.
2355 Actually, if that happens we should get
2356 window manager prompting. */
2357 f->width = DEFAULT_COLS;
2358 f->height = DEFAULT_ROWS;
2359 /* Window managers expect that if program-specified
2360 positions are not (0,0), they're intentional, not defaults. */
2361 f->output_data.x->top_pos = 0;
2362 f->output_data.x->left_pos = 0;
2363
2364 tem0 = x_get_arg (parms, Qheight, 0, 0, number);
2365 tem1 = x_get_arg (parms, Qwidth, 0, 0, number);
2366 tem2 = x_get_arg (parms, Quser_size, 0, 0, number);
2367 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
2368 {
2369 if (!EQ (tem0, Qunbound))
2370 {
2371 CHECK_NUMBER (tem0, 0);
2372 f->height = XINT (tem0);
2373 }
2374 if (!EQ (tem1, Qunbound))
2375 {
2376 CHECK_NUMBER (tem1, 0);
2377 f->width = XINT (tem1);
2378 }
2379 if (!NILP (tem2) && !EQ (tem2, Qunbound))
2380 window_prompting |= USSize;
2381 else
2382 window_prompting |= PSize;
2383 }
2384
2385 f->output_data.x->vertical_scroll_bar_extra
2386 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
2387 ? 0
2388 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
2389 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
2390 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
2391 f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
2392 f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
2393
2394 tem0 = x_get_arg (parms, Qtop, 0, 0, number);
2395 tem1 = x_get_arg (parms, Qleft, 0, 0, number);
2396 tem2 = x_get_arg (parms, Quser_position, 0, 0, number);
2397 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
2398 {
2399 if (EQ (tem0, Qminus))
2400 {
2401 f->output_data.x->top_pos = 0;
2402 window_prompting |= YNegative;
2403 }
2404 else if (CONSP (tem0) && EQ (XCONS (tem0)->car, Qminus)
2405 && CONSP (XCONS (tem0)->cdr)
2406 && INTEGERP (XCONS (XCONS (tem0)->cdr)->car))
2407 {
2408 f->output_data.x->top_pos = - XINT (XCONS (XCONS (tem0)->cdr)->car);
2409 window_prompting |= YNegative;
2410 }
2411 else if (CONSP (tem0) && EQ (XCONS (tem0)->car, Qplus)
2412 && CONSP (XCONS (tem0)->cdr)
2413 && INTEGERP (XCONS (XCONS (tem0)->cdr)->car))
2414 {
2415 f->output_data.x->top_pos = XINT (XCONS (XCONS (tem0)->cdr)->car);
2416 }
2417 else if (EQ (tem0, Qunbound))
2418 f->output_data.x->top_pos = 0;
2419 else
2420 {
2421 CHECK_NUMBER (tem0, 0);
2422 f->output_data.x->top_pos = XINT (tem0);
2423 if (f->output_data.x->top_pos < 0)
2424 window_prompting |= YNegative;
2425 }
2426
2427 if (EQ (tem1, Qminus))
2428 {
2429 f->output_data.x->left_pos = 0;
2430 window_prompting |= XNegative;
2431 }
2432 else if (CONSP (tem1) && EQ (XCONS (tem1)->car, Qminus)
2433 && CONSP (XCONS (tem1)->cdr)
2434 && INTEGERP (XCONS (XCONS (tem1)->cdr)->car))
2435 {
2436 f->output_data.x->left_pos = - XINT (XCONS (XCONS (tem1)->cdr)->car);
2437 window_prompting |= XNegative;
2438 }
2439 else if (CONSP (tem1) && EQ (XCONS (tem1)->car, Qplus)
2440 && CONSP (XCONS (tem1)->cdr)
2441 && INTEGERP (XCONS (XCONS (tem1)->cdr)->car))
2442 {
2443 f->output_data.x->left_pos = XINT (XCONS (XCONS (tem1)->cdr)->car);
2444 }
2445 else if (EQ (tem1, Qunbound))
2446 f->output_data.x->left_pos = 0;
2447 else
2448 {
2449 CHECK_NUMBER (tem1, 0);
2450 f->output_data.x->left_pos = XINT (tem1);
2451 if (f->output_data.x->left_pos < 0)
2452 window_prompting |= XNegative;
2453 }
2454
2455 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
2456 window_prompting |= USPosition;
2457 else
2458 window_prompting |= PPosition;
2459 }
2460
2461 return window_prompting;
2462 }
2463
2464 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
2465
2466 Status
2467 XSetWMProtocols (dpy, w, protocols, count)
2468 Display *dpy;
2469 Window w;
2470 Atom *protocols;
2471 int count;
2472 {
2473 Atom prop;
2474 prop = XInternAtom (dpy, "WM_PROTOCOLS", False);
2475 if (prop == None) return False;
2476 XChangeProperty (dpy, w, prop, XA_ATOM, 32, PropModeReplace,
2477 (unsigned char *) protocols, count);
2478 return True;
2479 }
2480 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
2481 \f
2482 #ifdef USE_X_TOOLKIT
2483
2484 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
2485 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
2486 already be present because of the toolkit (Motif adds some of them,
2487 for example, but Xt doesn't). */
2488
2489 static void
2490 hack_wm_protocols (f, widget)
2491 FRAME_PTR f;
2492 Widget widget;
2493 {
2494 Display *dpy = XtDisplay (widget);
2495 Window w = XtWindow (widget);
2496 int need_delete = 1;
2497 int need_focus = 1;
2498 int need_save = 1;
2499
2500 BLOCK_INPUT;
2501 {
2502 Atom type, *atoms = 0;
2503 int format = 0;
2504 unsigned long nitems = 0;
2505 unsigned long bytes_after;
2506
2507 if ((XGetWindowProperty (dpy, w,
2508 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
2509 (long)0, (long)100, False, XA_ATOM,
2510 &type, &format, &nitems, &bytes_after,
2511 (unsigned char **) &atoms)
2512 == Success)
2513 && format == 32 && type == XA_ATOM)
2514 while (nitems > 0)
2515 {
2516 nitems--;
2517 if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
2518 need_delete = 0;
2519 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
2520 need_focus = 0;
2521 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
2522 need_save = 0;
2523 }
2524 if (atoms) XFree ((char *) atoms);
2525 }
2526 {
2527 Atom props [10];
2528 int count = 0;
2529 if (need_delete)
2530 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
2531 if (need_focus)
2532 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus;
2533 if (need_save)
2534 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
2535 if (count)
2536 XChangeProperty (dpy, w, FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
2537 XA_ATOM, 32, PropModeAppend,
2538 (unsigned char *) props, count);
2539 }
2540 UNBLOCK_INPUT;
2541 }
2542 #endif
2543 \f
2544 #ifdef USE_X_TOOLKIT
2545
2546 /* Create and set up the X widget for frame F. */
2547
2548 static void
2549 x_window (f, window_prompting, minibuffer_only)
2550 struct frame *f;
2551 long window_prompting;
2552 int minibuffer_only;
2553 {
2554 XClassHint class_hints;
2555 XSetWindowAttributes attributes;
2556 unsigned long attribute_mask;
2557
2558 Widget shell_widget;
2559 Widget pane_widget;
2560 Widget frame_widget;
2561 Arg al [25];
2562 int ac;
2563
2564 BLOCK_INPUT;
2565
2566 /* Use the resource name as the top-level widget name
2567 for looking up resources. Make a non-Lisp copy
2568 for the window manager, so GC relocation won't bother it.
2569
2570 Elsewhere we specify the window name for the window manager. */
2571
2572 {
2573 char *str = (char *) XSTRING (Vx_resource_name)->data;
2574 f->namebuf = (char *) xmalloc (strlen (str) + 1);
2575 strcpy (f->namebuf, str);
2576 }
2577
2578 ac = 0;
2579 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
2580 XtSetArg (al[ac], XtNinput, 1); ac++;
2581 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
2582 XtSetArg (al[ac], XtNborderWidth, f->output_data.x->border_width); ac++;
2583 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
2584 applicationShellWidgetClass,
2585 FRAME_X_DISPLAY (f), al, ac);
2586
2587 f->output_data.x->widget = shell_widget;
2588 /* maybe_set_screen_title_format (shell_widget); */
2589
2590 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
2591 (widget_value *) NULL,
2592 shell_widget, False,
2593 (lw_callback) NULL,
2594 (lw_callback) NULL,
2595 (lw_callback) NULL);
2596
2597 f->output_data.x->column_widget = pane_widget;
2598
2599 /* mappedWhenManaged to false tells to the paned window to not map/unmap
2600 the emacs screen when changing menubar. This reduces flickering. */
2601
2602 ac = 0;
2603 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
2604 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
2605 XtSetArg (al[ac], XtNallowResize, 1); ac++;
2606 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
2607 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
2608 frame_widget = XtCreateWidget (f->namebuf,
2609 emacsFrameClass,
2610 pane_widget, al, ac);
2611
2612 f->output_data.x->edit_widget = frame_widget;
2613
2614 XtManageChild (frame_widget);
2615
2616 /* Do some needed geometry management. */
2617 {
2618 int len;
2619 char *tem, shell_position[32];
2620 Arg al[2];
2621 int ac = 0;
2622 int extra_borders = 0;
2623 int menubar_size
2624 = (f->output_data.x->menubar_widget
2625 ? (f->output_data.x->menubar_widget->core.height
2626 + f->output_data.x->menubar_widget->core.border_width)
2627 : 0);
2628 extern char *lwlib_toolkit_type;
2629
2630 #if 0 /* Experimentally, we now get the right results
2631 for -geometry -0-0 without this. 24 Aug 96, rms. */
2632 if (FRAME_EXTERNAL_MENU_BAR (f))
2633 {
2634 Dimension ibw = 0;
2635 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
2636 menubar_size += ibw;
2637 }
2638 #endif
2639
2640 f->output_data.x->menubar_height = menubar_size;
2641
2642 /* Motif seems to need this amount added to the sizes
2643 specified for the shell widget. The Athena/Lucid widgets don't.
2644 Both conclusions reached experimentally. -- rms. */
2645 if (!strcmp (lwlib_toolkit_type, "motif"))
2646 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
2647 &extra_borders, NULL);
2648
2649 /* Convert our geometry parameters into a geometry string
2650 and specify it.
2651 Note that we do not specify here whether the position
2652 is a user-specified or program-specified one.
2653 We pass that information later, in x_wm_set_size_hints. */
2654 {
2655 int left = f->output_data.x->left_pos;
2656 int xneg = window_prompting & XNegative;
2657 int top = f->output_data.x->top_pos;
2658 int yneg = window_prompting & YNegative;
2659 if (xneg)
2660 left = -left;
2661 if (yneg)
2662 top = -top;
2663
2664 if (window_prompting & USPosition)
2665 sprintf (shell_position, "=%dx%d%c%d%c%d",
2666 PIXEL_WIDTH (f) + extra_borders,
2667 PIXEL_HEIGHT (f) + menubar_size + extra_borders,
2668 (xneg ? '-' : '+'), left,
2669 (yneg ? '-' : '+'), top);
2670 else
2671 sprintf (shell_position, "=%dx%d",
2672 PIXEL_WIDTH (f) + extra_borders,
2673 PIXEL_HEIGHT (f) + menubar_size + extra_borders);
2674 }
2675
2676 len = strlen (shell_position) + 1;
2677 tem = (char *) xmalloc (len);
2678 strncpy (tem, shell_position, len);
2679 XtSetArg (al[ac], XtNgeometry, tem); ac++;
2680 XtSetValues (shell_widget, al, ac);
2681 }
2682
2683 XtManageChild (pane_widget);
2684 XtRealizeWidget (shell_widget);
2685
2686 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
2687
2688 validate_x_resource_name ();
2689
2690 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
2691 class_hints.res_class = EMACS_CLASS;
2692 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
2693
2694 #ifdef HAVE_X_I18N
2695 #ifndef X_I18N_INHIBITED
2696 {
2697 XIM xim;
2698 XIC xic = NULL;
2699
2700 xim = XOpenIM (FRAME_X_DISPLAY (f), NULL, NULL, NULL);
2701
2702 if (xim)
2703 {
2704 xic = XCreateIC (xim,
2705 XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
2706 XNClientWindow, FRAME_X_WINDOW(f),
2707 XNFocusWindow, FRAME_X_WINDOW(f),
2708 NULL);
2709
2710 if (xic == 0)
2711 {
2712 XCloseIM (xim);
2713 xim = NULL;
2714 }
2715 }
2716 FRAME_XIM (f) = xim;
2717 FRAME_XIC (f) = xic;
2718 }
2719 #else /* X_I18N_INHIBITED */
2720 FRAME_XIM (f) = 0;
2721 FRAME_XIC (f) = 0;
2722 #endif /* X_I18N_INHIBITED */
2723 #endif /* HAVE_X_I18N */
2724
2725 f->output_data.x->wm_hints.input = True;
2726 f->output_data.x->wm_hints.flags |= InputHint;
2727 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2728 &f->output_data.x->wm_hints);
2729
2730 hack_wm_protocols (f, shell_widget);
2731
2732 #ifdef HACK_EDITRES
2733 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
2734 #endif
2735
2736 /* Do a stupid property change to force the server to generate a
2737 propertyNotify event so that the event_stream server timestamp will
2738 be initialized to something relevant to the time we created the window.
2739 */
2740 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
2741 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
2742 XA_ATOM, 32, PropModeAppend,
2743 (unsigned char*) NULL, 0);
2744
2745 /* Make all the standard events reach the Emacs frame. */
2746 attributes.event_mask = STANDARD_EVENT_SET;
2747 attribute_mask = CWEventMask;
2748 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
2749 attribute_mask, &attributes);
2750
2751 XtMapWidget (frame_widget);
2752
2753 /* x_set_name normally ignores requests to set the name if the
2754 requested name is the same as the current name. This is the one
2755 place where that assumption isn't correct; f->name is set, but
2756 the X server hasn't been told. */
2757 {
2758 Lisp_Object name;
2759 int explicit = f->explicit_name;
2760
2761 f->explicit_name = 0;
2762 name = f->name;
2763 f->name = Qnil;
2764 x_set_name (f, name, explicit);
2765 }
2766
2767 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2768 f->output_data.x->text_cursor);
2769
2770 UNBLOCK_INPUT;
2771
2772 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
2773 initialize_frame_menubar (f);
2774 lw_set_main_areas (pane_widget, f->output_data.x->menubar_widget, frame_widget);
2775
2776 if (FRAME_X_WINDOW (f) == 0)
2777 error ("Unable to create window");
2778 }
2779
2780 #else /* not USE_X_TOOLKIT */
2781
2782 /* Create and set up the X window for frame F. */
2783
2784 x_window (f)
2785 struct frame *f;
2786
2787 {
2788 XClassHint class_hints;
2789 XSetWindowAttributes attributes;
2790 unsigned long attribute_mask;
2791
2792 attributes.background_pixel = f->output_data.x->background_pixel;
2793 attributes.border_pixel = f->output_data.x->border_pixel;
2794 attributes.bit_gravity = StaticGravity;
2795 attributes.backing_store = NotUseful;
2796 attributes.save_under = True;
2797 attributes.event_mask = STANDARD_EVENT_SET;
2798 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity
2799 #if 0
2800 | CWBackingStore | CWSaveUnder
2801 #endif
2802 | CWEventMask);
2803
2804 BLOCK_INPUT;
2805 FRAME_X_WINDOW (f)
2806 = XCreateWindow (FRAME_X_DISPLAY (f),
2807 f->output_data.x->parent_desc,
2808 f->output_data.x->left_pos,
2809 f->output_data.x->top_pos,
2810 PIXEL_WIDTH (f), PIXEL_HEIGHT (f),
2811 f->output_data.x->border_width,
2812 CopyFromParent, /* depth */
2813 InputOutput, /* class */
2814 FRAME_X_DISPLAY_INFO (f)->visual,
2815 attribute_mask, &attributes);
2816 #ifdef HAVE_X_I18N
2817 #ifndef X_I18N_INHIBITED
2818 {
2819 XIM xim;
2820 XIC xic = NULL;
2821
2822 xim = XOpenIM (FRAME_X_DISPLAY(f), NULL, NULL, NULL);
2823
2824 if (xim)
2825 {
2826 xic = XCreateIC (xim,
2827 XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
2828 XNClientWindow, FRAME_X_WINDOW(f),
2829 XNFocusWindow, FRAME_X_WINDOW(f),
2830 NULL);
2831
2832 if (!xic)
2833 {
2834 XCloseIM (xim);
2835 xim = NULL;
2836 }
2837 }
2838
2839 FRAME_XIM (f) = xim;
2840 FRAME_XIC (f) = xic;
2841 }
2842 #else /* X_I18N_INHIBITED */
2843 FRAME_XIM (f) = 0;
2844 FRAME_XIC (f) = 0;
2845 #endif /* X_I18N_INHIBITED */
2846 #endif /* HAVE_X_I18N */
2847
2848 validate_x_resource_name ();
2849
2850 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
2851 class_hints.res_class = EMACS_CLASS;
2852 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
2853
2854 /* The menubar is part of the ordinary display;
2855 it does not count in addition to the height of the window. */
2856 f->output_data.x->menubar_height = 0;
2857
2858 /* This indicates that we use the "Passive Input" input model.
2859 Unless we do this, we don't get the Focus{In,Out} events that we
2860 need to draw the cursor correctly. Accursed bureaucrats.
2861 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
2862
2863 f->output_data.x->wm_hints.input = True;
2864 f->output_data.x->wm_hints.flags |= InputHint;
2865 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2866 &f->output_data.x->wm_hints);
2867 f->output_data.x->wm_hints.icon_pixmap = None;
2868
2869 /* Request "save yourself" and "delete window" commands from wm. */
2870 {
2871 Atom protocols[2];
2872 protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
2873 protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
2874 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
2875 }
2876
2877 /* x_set_name normally ignores requests to set the name if the
2878 requested name is the same as the current name. This is the one
2879 place where that assumption isn't correct; f->name is set, but
2880 the X server hasn't been told. */
2881 {
2882 Lisp_Object name;
2883 int explicit = f->explicit_name;
2884
2885 f->explicit_name = 0;
2886 name = f->name;
2887 f->name = Qnil;
2888 x_set_name (f, name, explicit);
2889 }
2890
2891 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2892 f->output_data.x->text_cursor);
2893
2894 UNBLOCK_INPUT;
2895
2896 if (FRAME_X_WINDOW (f) == 0)
2897 error ("Unable to create window");
2898 }
2899
2900 #endif /* not USE_X_TOOLKIT */
2901
2902 /* Handle the icon stuff for this window. Perhaps later we might
2903 want an x_set_icon_position which can be called interactively as
2904 well. */
2905
2906 static void
2907 x_icon (f, parms)
2908 struct frame *f;
2909 Lisp_Object parms;
2910 {
2911 Lisp_Object icon_x, icon_y;
2912
2913 /* Set the position of the icon. Note that twm groups all
2914 icons in an icon window. */
2915 icon_x = x_get_and_record_arg (f, parms, Qicon_left, 0, 0, number);
2916 icon_y = x_get_and_record_arg (f, parms, Qicon_top, 0, 0, number);
2917 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
2918 {
2919 CHECK_NUMBER (icon_x, 0);
2920 CHECK_NUMBER (icon_y, 0);
2921 }
2922 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
2923 error ("Both left and top icon corners of icon must be specified");
2924
2925 BLOCK_INPUT;
2926
2927 if (! EQ (icon_x, Qunbound))
2928 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
2929
2930 /* Start up iconic or window? */
2931 x_wm_set_window_state
2932 (f, (EQ (x_get_arg (parms, Qvisibility, 0, 0, symbol), Qicon)
2933 ? IconicState
2934 : NormalState));
2935
2936 x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
2937 ? f->icon_name
2938 : f->name))->data);
2939
2940 UNBLOCK_INPUT;
2941 }
2942
2943 /* Make the GC's needed for this window, setting the
2944 background, border and mouse colors; also create the
2945 mouse cursor and the gray border tile. */
2946
2947 static char cursor_bits[] =
2948 {
2949 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2950 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2951 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2952 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2953 };
2954
2955 static void
2956 x_make_gc (f)
2957 struct frame *f;
2958 {
2959 XGCValues gc_values;
2960 GC temp_gc;
2961 XImage tileimage;
2962
2963 BLOCK_INPUT;
2964
2965 /* Create the GC's of this frame.
2966 Note that many default values are used. */
2967
2968 /* Normal video */
2969 gc_values.font = f->output_data.x->font->fid;
2970 gc_values.foreground = f->output_data.x->foreground_pixel;
2971 gc_values.background = f->output_data.x->background_pixel;
2972 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
2973 f->output_data.x->normal_gc = XCreateGC (FRAME_X_DISPLAY (f),
2974 FRAME_X_WINDOW (f),
2975 GCLineWidth | GCFont
2976 | GCForeground | GCBackground,
2977 &gc_values);
2978
2979 /* Reverse video style. */
2980 gc_values.foreground = f->output_data.x->background_pixel;
2981 gc_values.background = f->output_data.x->foreground_pixel;
2982 f->output_data.x->reverse_gc = XCreateGC (FRAME_X_DISPLAY (f),
2983 FRAME_X_WINDOW (f),
2984 GCFont | GCForeground | GCBackground
2985 | GCLineWidth,
2986 &gc_values);
2987
2988 /* Cursor has cursor-color background, background-color foreground. */
2989 gc_values.foreground = f->output_data.x->background_pixel;
2990 gc_values.background = f->output_data.x->cursor_pixel;
2991 gc_values.fill_style = FillOpaqueStippled;
2992 gc_values.stipple
2993 = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
2994 FRAME_X_DISPLAY_INFO (f)->root_window,
2995 cursor_bits, 16, 16);
2996 f->output_data.x->cursor_gc
2997 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2998 (GCFont | GCForeground | GCBackground
2999 | GCFillStyle | GCStipple | GCLineWidth),
3000 &gc_values);
3001
3002 /* Create the gray border tile used when the pointer is not in
3003 the frame. Since this depends on the frame's pixel values,
3004 this must be done on a per-frame basis. */
3005 f->output_data.x->border_tile
3006 = (XCreatePixmapFromBitmapData
3007 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
3008 gray_bits, gray_width, gray_height,
3009 f->output_data.x->foreground_pixel,
3010 f->output_data.x->background_pixel,
3011 DefaultDepth (FRAME_X_DISPLAY (f),
3012 XScreenNumberOfScreen (FRAME_X_SCREEN (f)))));
3013
3014 UNBLOCK_INPUT;
3015 }
3016
3017 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
3018 1, 1, 0,
3019 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
3020 Returns an Emacs frame object.\n\
3021 ALIST is an alist of frame parameters.\n\
3022 If the parameters specify that the frame should not have a minibuffer,\n\
3023 and do not specify a specific minibuffer window to use,\n\
3024 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
3025 be shared by the new frame.\n\
3026 \n\
3027 This function is an internal primitive--use `make-frame' instead.")
3028 (parms)
3029 Lisp_Object parms;
3030 {
3031 struct frame *f;
3032 Lisp_Object frame, tem;
3033 Lisp_Object name;
3034 int minibuffer_only = 0;
3035 long window_prompting = 0;
3036 int width, height;
3037 int count = specpdl_ptr - specpdl;
3038 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3039 Lisp_Object display;
3040 struct x_display_info *dpyinfo;
3041 Lisp_Object parent;
3042 struct kboard *kb;
3043
3044 check_x ();
3045
3046 /* Use this general default value to start with
3047 until we know if this frame has a specified name. */
3048 Vx_resource_name = Vinvocation_name;
3049
3050 display = x_get_arg (parms, Qdisplay, 0, 0, string);
3051 if (EQ (display, Qunbound))
3052 display = Qnil;
3053 dpyinfo = check_x_display_info (display);
3054 #ifdef MULTI_KBOARD
3055 kb = dpyinfo->kboard;
3056 #else
3057 kb = &the_only_kboard;
3058 #endif
3059
3060 name = x_get_arg (parms, Qname, "name", "Name", string);
3061 if (!STRINGP (name)
3062 && ! EQ (name, Qunbound)
3063 && ! NILP (name))
3064 error ("Invalid frame name--not a string or nil");
3065
3066 if (STRINGP (name))
3067 Vx_resource_name = name;
3068
3069 /* See if parent window is specified. */
3070 parent = x_get_arg (parms, Qparent_id, NULL, NULL, number);
3071 if (EQ (parent, Qunbound))
3072 parent = Qnil;
3073 if (! NILP (parent))
3074 CHECK_NUMBER (parent, 0);
3075
3076 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
3077 /* No need to protect DISPLAY because that's not used after passing
3078 it to make_frame_without_minibuffer. */
3079 frame = Qnil;
3080 GCPRO4 (parms, parent, name, frame);
3081 tem = x_get_arg (parms, Qminibuffer, 0, 0, symbol);
3082 if (EQ (tem, Qnone) || NILP (tem))
3083 f = make_frame_without_minibuffer (Qnil, kb, display);
3084 else if (EQ (tem, Qonly))
3085 {
3086 f = make_minibuffer_frame ();
3087 minibuffer_only = 1;
3088 }
3089 else if (WINDOWP (tem))
3090 f = make_frame_without_minibuffer (tem, kb, display);
3091 else
3092 f = make_frame (1);
3093
3094 XSETFRAME (frame, f);
3095
3096 /* Note that X Windows does support scroll bars. */
3097 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
3098
3099 f->output_method = output_x_window;
3100 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
3101 bzero (f->output_data.x, sizeof (struct x_output));
3102 f->output_data.x->icon_bitmap = -1;
3103
3104 f->icon_name
3105 = x_get_arg (parms, Qicon_name, "iconName", "Title", string);
3106 if (! STRINGP (f->icon_name))
3107 f->icon_name = Qnil;
3108
3109 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
3110 #ifdef MULTI_KBOARD
3111 FRAME_KBOARD (f) = kb;
3112 #endif
3113
3114 /* Specify the parent under which to make this X window. */
3115
3116 if (!NILP (parent))
3117 {
3118 f->output_data.x->parent_desc = parent;
3119 f->output_data.x->explicit_parent = 1;
3120 }
3121 else
3122 {
3123 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
3124 f->output_data.x->explicit_parent = 0;
3125 }
3126
3127 /* Note that the frame has no physical cursor right now. */
3128 f->phys_cursor_x = -1;
3129
3130 /* Set the name; the functions to which we pass f expect the name to
3131 be set. */
3132 if (EQ (name, Qunbound) || NILP (name))
3133 {
3134 f->name = build_string (dpyinfo->x_id_name);
3135 f->explicit_name = 0;
3136 }
3137 else
3138 {
3139 f->name = name;
3140 f->explicit_name = 1;
3141 /* use the frame's title when getting resources for this frame. */
3142 specbind (Qx_resource_name, name);
3143 }
3144
3145 /* Extract the window parameters from the supplied values
3146 that are needed to determine window geometry. */
3147 {
3148 Lisp_Object font;
3149
3150 font = x_get_arg (parms, Qfont, "font", "Font", string);
3151 BLOCK_INPUT;
3152 /* First, try whatever font the caller has specified. */
3153 if (STRINGP (font))
3154 font = x_new_font (f, XSTRING (font)->data);
3155 /* Try out a font which we hope has bold and italic variations. */
3156 if (!STRINGP (font))
3157 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3158 if (! STRINGP (font))
3159 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3160 if (! STRINGP (font))
3161 /* This was formerly the first thing tried, but it finds too many fonts
3162 and takes too long. */
3163 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
3164 /* If those didn't work, look for something which will at least work. */
3165 if (! STRINGP (font))
3166 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
3167 UNBLOCK_INPUT;
3168 if (! STRINGP (font))
3169 font = build_string ("fixed");
3170
3171 x_default_parameter (f, parms, Qfont, font,
3172 "font", "Font", string);
3173 }
3174
3175 #ifdef USE_LUCID
3176 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
3177 whereby it fails to get any font. */
3178 xlwmenu_default_font = f->output_data.x->font;
3179 #endif
3180
3181 x_default_parameter (f, parms, Qborder_width, make_number (2),
3182 "borderwidth", "BorderWidth", number);
3183 /* This defaults to 2 in order to match xterm. We recognize either
3184 internalBorderWidth or internalBorder (which is what xterm calls
3185 it). */
3186 if (NILP (Fassq (Qinternal_border_width, parms)))
3187 {
3188 Lisp_Object value;
3189
3190 value = x_get_arg (parms, Qinternal_border_width,
3191 "internalBorder", "BorderWidth", number);
3192 if (! EQ (value, Qunbound))
3193 parms = Fcons (Fcons (Qinternal_border_width, value),
3194 parms);
3195 }
3196 x_default_parameter (f, parms, Qinternal_border_width, make_number (2),
3197 "internalBorderWidth", "BorderWidth", number);
3198 x_default_parameter (f, parms, Qvertical_scroll_bars, Qt,
3199 "verticalScrollBars", "ScrollBars", boolean);
3200
3201 /* Also do the stuff which must be set before the window exists. */
3202 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
3203 "foreground", "Foreground", string);
3204 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
3205 "background", "Background", string);
3206 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
3207 "pointerColor", "Foreground", string);
3208 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
3209 "cursorColor", "Foreground", string);
3210 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
3211 "borderColor", "BorderColor", string);
3212
3213 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
3214 "menuBar", "MenuBar", number);
3215 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
3216 "scrollBarWidth", "ScrollBarWidth", number);
3217 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
3218 "bufferPredicate", "BufferPredicate", symbol);
3219 x_default_parameter (f, parms, Qtitle, Qnil,
3220 "title", "Title", string);
3221
3222 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
3223 window_prompting = x_figure_window_size (f, parms);
3224
3225 if (window_prompting & XNegative)
3226 {
3227 if (window_prompting & YNegative)
3228 f->output_data.x->win_gravity = SouthEastGravity;
3229 else
3230 f->output_data.x->win_gravity = NorthEastGravity;
3231 }
3232 else
3233 {
3234 if (window_prompting & YNegative)
3235 f->output_data.x->win_gravity = SouthWestGravity;
3236 else
3237 f->output_data.x->win_gravity = NorthWestGravity;
3238 }
3239
3240 f->output_data.x->size_hint_flags = window_prompting;
3241
3242 #ifdef USE_X_TOOLKIT
3243 x_window (f, window_prompting, minibuffer_only);
3244 #else
3245 x_window (f);
3246 #endif
3247 x_icon (f, parms);
3248 x_make_gc (f);
3249 init_frame_faces (f);
3250
3251 /* We need to do this after creating the X window, so that the
3252 icon-creation functions can say whose icon they're describing. */
3253 x_default_parameter (f, parms, Qicon_type, Qnil,
3254 "bitmapIcon", "BitmapIcon", symbol);
3255
3256 x_default_parameter (f, parms, Qauto_raise, Qnil,
3257 "autoRaise", "AutoRaiseLower", boolean);
3258 x_default_parameter (f, parms, Qauto_lower, Qnil,
3259 "autoLower", "AutoRaiseLower", boolean);
3260 x_default_parameter (f, parms, Qcursor_type, Qbox,
3261 "cursorType", "CursorType", symbol);
3262
3263 /* Dimensions, especially f->height, must be done via change_frame_size.
3264 Change will not be effected unless different from the current
3265 f->height. */
3266 width = f->width;
3267 height = f->height;
3268 f->height = f->width = 0;
3269 change_frame_size (f, height, width, 1, 0);
3270
3271 /* Tell the server what size and position, etc, we want,
3272 and how badly we want them. */
3273 BLOCK_INPUT;
3274 x_wm_set_size_hint (f, window_prompting, 0);
3275 UNBLOCK_INPUT;
3276
3277 tem = x_get_arg (parms, Qunsplittable, 0, 0, boolean);
3278 f->no_split = minibuffer_only || EQ (tem, Qt);
3279
3280 UNGCPRO;
3281
3282 /* It is now ok to make the frame official
3283 even if we get an error below.
3284 And the frame needs to be on Vframe_list
3285 or making it visible won't work. */
3286 Vframe_list = Fcons (frame, Vframe_list);
3287
3288 /* Now that the frame is official, it counts as a reference to
3289 its display. */
3290 FRAME_X_DISPLAY_INFO (f)->reference_count++;
3291
3292 /* Make the window appear on the frame and enable display,
3293 unless the caller says not to. However, with explicit parent,
3294 Emacs cannot control visibility, so don't try. */
3295 if (! f->output_data.x->explicit_parent)
3296 {
3297 Lisp_Object visibility;
3298
3299 visibility = x_get_arg (parms, Qvisibility, 0, 0, symbol);
3300 if (EQ (visibility, Qunbound))
3301 visibility = Qt;
3302
3303 if (EQ (visibility, Qicon))
3304 x_iconify_frame (f);
3305 else if (! NILP (visibility))
3306 x_make_frame_visible (f);
3307 else
3308 /* Must have been Qnil. */
3309 ;
3310 }
3311
3312 return unbind_to (count, frame);
3313 }
3314
3315 /* FRAME is used only to get a handle on the X display. We don't pass the
3316 display info directly because we're called from frame.c, which doesn't
3317 know about that structure. */
3318
3319 Lisp_Object
3320 x_get_focus_frame (frame)
3321 struct frame *frame;
3322 {
3323 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
3324 Lisp_Object xfocus;
3325 if (! dpyinfo->x_focus_frame)
3326 return Qnil;
3327
3328 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
3329 return xfocus;
3330 }
3331 \f
3332 DEFUN ("x-list-fonts", Fx_list_fonts, Sx_list_fonts, 1, 4, 0,
3333 "Return a list of the names of available fonts matching PATTERN.\n\
3334 If optional arguments FACE and FRAME are specified, return only fonts\n\
3335 the same size as FACE on FRAME.\n\
3336 \n\
3337 PATTERN is a string, perhaps with wildcard characters;\n\
3338 the * character matches any substring, and\n\
3339 the ? character matches any single character.\n\
3340 PATTERN is case-insensitive.\n\
3341 FACE is a face name--a symbol.\n\
3342 \n\
3343 The return value is a list of strings, suitable as arguments to\n\
3344 set-face-font.\n\
3345 \n\
3346 Fonts Emacs can't use (i.e. proportional fonts) may or may not be excluded\n\
3347 even if they match PATTERN and FACE.\n\
3348 \n\
3349 The optional fourth argument MAXIMUM sets a limit on how many\n\
3350 fonts to match. The first MAXIMUM fonts are reported.")
3351 (pattern, face, frame, maximum)
3352 Lisp_Object pattern, face, frame, maximum;
3353 {
3354 int num_fonts;
3355 char **names;
3356 #ifndef BROKEN_XLISTFONTSWITHINFO
3357 XFontStruct *info;
3358 #endif
3359 XFontStruct *size_ref;
3360 Lisp_Object list;
3361 FRAME_PTR f;
3362 Lisp_Object key;
3363 int maxnames;
3364
3365 check_x ();
3366 CHECK_STRING (pattern, 0);
3367 if (!NILP (face))
3368 CHECK_SYMBOL (face, 1);
3369
3370 if (NILP (maximum))
3371 maxnames = 2000;
3372 else
3373 {
3374 CHECK_NATNUM (maximum, 0);
3375 maxnames = XINT (maximum);
3376 }
3377
3378 f = check_x_frame (frame);
3379
3380 /* Determine the width standard for comparison with the fonts we find. */
3381
3382 if (NILP (face))
3383 size_ref = 0;
3384 else
3385 {
3386 int face_id;
3387
3388 /* Don't die if we get called with a terminal frame. */
3389 if (! FRAME_X_P (f))
3390 error ("Non-X frame used in `x-list-fonts'");
3391
3392 face_id = face_name_id_number (f, face);
3393
3394 if (face_id < 0 || face_id >= FRAME_N_PARAM_FACES (f)
3395 || FRAME_PARAM_FACES (f) [face_id] == 0)
3396 size_ref = f->output_data.x->font;
3397 else
3398 {
3399 size_ref = FRAME_PARAM_FACES (f) [face_id]->font;
3400 if (size_ref == (XFontStruct *) (~0))
3401 size_ref = f->output_data.x->font;
3402 }
3403 }
3404
3405 /* See if we cached the result for this particular query. */
3406 key = Fcons (pattern, maximum);
3407 list = Fassoc (key,
3408 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr);
3409
3410 /* We have info in the cache for this PATTERN. */
3411 if (!NILP (list))
3412 {
3413 Lisp_Object tem, newlist;
3414
3415 /* We have info about this pattern. */
3416 list = XCONS (list)->cdr;
3417
3418 if (size_ref == 0)
3419 return list;
3420
3421 BLOCK_INPUT;
3422
3423 /* Filter the cached info and return just the fonts that match FACE. */
3424 newlist = Qnil;
3425 for (tem = list; CONSP (tem); tem = XCONS (tem)->cdr)
3426 {
3427 XFontStruct *thisinfo;
3428
3429 x_catch_errors (FRAME_X_DISPLAY (f));
3430
3431 thisinfo = XLoadQueryFont (FRAME_X_DISPLAY (f),
3432 XSTRING (XCONS (tem)->car)->data);
3433
3434 x_check_errors (FRAME_X_DISPLAY (f), "XLoadQueryFont failure: %s");
3435 x_uncatch_errors (FRAME_X_DISPLAY (f));
3436
3437 if (thisinfo && same_size_fonts (thisinfo, size_ref))
3438 newlist = Fcons (XCONS (tem)->car, newlist);
3439
3440 if (thisinfo != 0)
3441 XFreeFont (FRAME_X_DISPLAY (f), thisinfo);
3442 }
3443
3444 UNBLOCK_INPUT;
3445
3446 return newlist;
3447 }
3448
3449 BLOCK_INPUT;
3450
3451 x_catch_errors (FRAME_X_DISPLAY (f));
3452
3453 /* Solaris 2.3 has a bug in XListFontsWithInfo. */
3454 #ifndef BROKEN_XLISTFONTSWITHINFO
3455 if (size_ref)
3456 names = XListFontsWithInfo (FRAME_X_DISPLAY (f),
3457 XSTRING (pattern)->data,
3458 maxnames,
3459 &num_fonts, /* count_return */
3460 &info); /* info_return */
3461 else
3462 #endif
3463 names = XListFonts (FRAME_X_DISPLAY (f),
3464 XSTRING (pattern)->data,
3465 maxnames,
3466 &num_fonts); /* count_return */
3467
3468 x_check_errors (FRAME_X_DISPLAY (f), "XListFonts failure: %s");
3469 x_uncatch_errors (FRAME_X_DISPLAY (f));
3470
3471 UNBLOCK_INPUT;
3472
3473 list = Qnil;
3474
3475 if (names)
3476 {
3477 int i;
3478 Lisp_Object full_list;
3479
3480 /* Make a list of all the fonts we got back.
3481 Store that in the font cache for the display. */
3482 full_list = Qnil;
3483 for (i = 0; i < num_fonts; i++)
3484 full_list = Fcons (build_string (names[i]), full_list);
3485 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr
3486 = Fcons (Fcons (key, full_list),
3487 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr);
3488
3489 /* Make a list of the fonts that have the right width. */
3490 list = Qnil;
3491 for (i = 0; i < num_fonts; i++)
3492 {
3493 int keeper;
3494
3495 if (!size_ref)
3496 keeper = 1;
3497 else
3498 {
3499 #ifdef BROKEN_XLISTFONTSWITHINFO
3500 XFontStruct *thisinfo;
3501
3502 BLOCK_INPUT;
3503
3504 x_catch_errors (FRAME_X_DISPLAY (f));
3505 thisinfo = XLoadQueryFont (FRAME_X_DISPLAY (f), names[i]);
3506 x_check_errors (FRAME_X_DISPLAY (f),
3507 "XLoadQueryFont failure: %s");
3508 x_uncatch_errors (FRAME_X_DISPLAY (f));
3509
3510 UNBLOCK_INPUT;
3511
3512 keeper = thisinfo && same_size_fonts (thisinfo, size_ref);
3513 BLOCK_INPUT;
3514 if (thisinfo && ! keeper)
3515 XFreeFont (FRAME_X_DISPLAY (f), thisinfo);
3516 else if (thisinfo)
3517 XFreeFontInfo (NULL, thisinfo, 1);
3518 UNBLOCK_INPUT;
3519 #else
3520 keeper = same_size_fonts (&info[i], size_ref);
3521 #endif
3522 }
3523 if (keeper)
3524 list = Fcons (build_string (names[i]), list);
3525 }
3526 list = Fnreverse (list);
3527
3528 BLOCK_INPUT;
3529 #ifndef BROKEN_XLISTFONTSWITHINFO
3530 if (size_ref)
3531 XFreeFontInfo (names, info, num_fonts);
3532 else
3533 #endif
3534 XFreeFontNames (names);
3535 UNBLOCK_INPUT;
3536 }
3537
3538 return list;
3539 }
3540
3541 \f
3542 DEFUN ("x-color-defined-p", Fx_color_defined_p, Sx_color_defined_p, 1, 2, 0,
3543 "Return non-nil if color COLOR is supported on frame FRAME.\n\
3544 If FRAME is omitted or nil, use the selected frame.")
3545 (color, frame)
3546 Lisp_Object color, frame;
3547 {
3548 XColor foo;
3549 FRAME_PTR f = check_x_frame (frame);
3550
3551 CHECK_STRING (color, 1);
3552
3553 if (defined_color (f, XSTRING (color)->data, &foo, 0))
3554 return Qt;
3555 else
3556 return Qnil;
3557 }
3558
3559 DEFUN ("x-color-values", Fx_color_values, Sx_color_values, 1, 2, 0,
3560 "Return a description of the color named COLOR on frame FRAME.\n\
3561 The value is a list of integer RGB values--(RED GREEN BLUE).\n\
3562 These values appear to range from 0 to 65280 or 65535, depending\n\
3563 on the system; white is (65280 65280 65280) or (65535 65535 65535).\n\
3564 If FRAME is omitted or nil, use the selected frame.")
3565 (color, frame)
3566 Lisp_Object color, frame;
3567 {
3568 XColor foo;
3569 FRAME_PTR f = check_x_frame (frame);
3570
3571 CHECK_STRING (color, 1);
3572
3573 if (defined_color (f, XSTRING (color)->data, &foo, 0))
3574 {
3575 Lisp_Object rgb[3];
3576
3577 rgb[0] = make_number (foo.red);
3578 rgb[1] = make_number (foo.green);
3579 rgb[2] = make_number (foo.blue);
3580 return Flist (3, rgb);
3581 }
3582 else
3583 return Qnil;
3584 }
3585
3586 DEFUN ("x-display-color-p", Fx_display_color_p, Sx_display_color_p, 0, 1, 0,
3587 "Return t if the X display supports color.\n\
3588 The optional argument DISPLAY specifies which display to ask about.\n\
3589 DISPLAY should be either a frame or a display name (a string).\n\
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
3596 if (dpyinfo->n_planes <= 2)
3597 return Qnil;
3598
3599 switch (dpyinfo->visual->class)
3600 {
3601 case StaticColor:
3602 case PseudoColor:
3603 case TrueColor:
3604 case DirectColor:
3605 return Qt;
3606
3607 default:
3608 return Qnil;
3609 }
3610 }
3611
3612 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
3613 0, 1, 0,
3614 "Return t if the X display supports shades of gray.\n\
3615 Note that color displays do support shades of gray.\n\
3616 The optional argument DISPLAY specifies which display to ask about.\n\
3617 DISPLAY should be either a frame or a display name (a string).\n\
3618 If omitted or nil, that stands for the selected frame's display.")
3619 (display)
3620 Lisp_Object display;
3621 {
3622 struct x_display_info *dpyinfo = check_x_display_info (display);
3623
3624 if (dpyinfo->n_planes <= 1)
3625 return Qnil;
3626
3627 switch (dpyinfo->visual->class)
3628 {
3629 case StaticColor:
3630 case PseudoColor:
3631 case TrueColor:
3632 case DirectColor:
3633 case StaticGray:
3634 case GrayScale:
3635 return Qt;
3636
3637 default:
3638 return Qnil;
3639 }
3640 }
3641
3642 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
3643 0, 1, 0,
3644 "Returns the width in pixels of the X display DISPLAY.\n\
3645 The optional argument DISPLAY specifies which display to ask about.\n\
3646 DISPLAY should be either a frame or a display name (a string).\n\
3647 If omitted or nil, that stands for the selected frame's display.")
3648 (display)
3649 Lisp_Object display;
3650 {
3651 struct x_display_info *dpyinfo = check_x_display_info (display);
3652
3653 return make_number (dpyinfo->width);
3654 }
3655
3656 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
3657 Sx_display_pixel_height, 0, 1, 0,
3658 "Returns the height in pixels of the X display DISPLAY.\n\
3659 The optional argument DISPLAY specifies which display to ask about.\n\
3660 DISPLAY should be either a frame or a display name (a string).\n\
3661 If omitted or nil, that stands for the selected frame's display.")
3662 (display)
3663 Lisp_Object display;
3664 {
3665 struct x_display_info *dpyinfo = check_x_display_info (display);
3666
3667 return make_number (dpyinfo->height);
3668 }
3669
3670 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
3671 0, 1, 0,
3672 "Returns the number of bitplanes of the X display DISPLAY.\n\
3673 The optional argument DISPLAY specifies which display to ask about.\n\
3674 DISPLAY should be either a frame or a display name (a string).\n\
3675 If omitted or nil, that stands for the selected frame's display.")
3676 (display)
3677 Lisp_Object display;
3678 {
3679 struct x_display_info *dpyinfo = check_x_display_info (display);
3680
3681 return make_number (dpyinfo->n_planes);
3682 }
3683
3684 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
3685 0, 1, 0,
3686 "Returns the number of color cells of the X display DISPLAY.\n\
3687 The optional argument DISPLAY specifies which display to ask about.\n\
3688 DISPLAY should be either a frame or a display name (a string).\n\
3689 If omitted or nil, that stands for the selected frame's display.")
3690 (display)
3691 Lisp_Object display;
3692 {
3693 struct x_display_info *dpyinfo = check_x_display_info (display);
3694
3695 return make_number (DisplayCells (dpyinfo->display,
3696 XScreenNumberOfScreen (dpyinfo->screen)));
3697 }
3698
3699 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
3700 Sx_server_max_request_size,
3701 0, 1, 0,
3702 "Returns the maximum request size of the X server of display DISPLAY.\n\
3703 The optional argument DISPLAY specifies which display to ask about.\n\
3704 DISPLAY should be either a frame or a display name (a string).\n\
3705 If omitted or nil, that stands for the selected frame's display.")
3706 (display)
3707 Lisp_Object display;
3708 {
3709 struct x_display_info *dpyinfo = check_x_display_info (display);
3710
3711 return make_number (MAXREQUEST (dpyinfo->display));
3712 }
3713
3714 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
3715 "Returns the vendor ID string of the X server of display DISPLAY.\n\
3716 The optional argument DISPLAY specifies which display to ask about.\n\
3717 DISPLAY should be either a frame or a display name (a string).\n\
3718 If omitted or nil, that stands for the selected frame's display.")
3719 (display)
3720 Lisp_Object display;
3721 {
3722 struct x_display_info *dpyinfo = check_x_display_info (display);
3723 char *vendor = ServerVendor (dpyinfo->display);
3724
3725 if (! vendor) vendor = "";
3726 return build_string (vendor);
3727 }
3728
3729 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
3730 "Returns the version numbers of the X server of display DISPLAY.\n\
3731 The value is a list of three integers: the major and minor\n\
3732 version numbers of the X Protocol in use, and the vendor-specific release\n\
3733 number. See also the function `x-server-vendor'.\n\n\
3734 The optional argument DISPLAY specifies which display to ask about.\n\
3735 DISPLAY should be either a frame or a display name (a string).\n\
3736 If omitted or nil, that stands for the selected frame's display.")
3737 (display)
3738 Lisp_Object display;
3739 {
3740 struct x_display_info *dpyinfo = check_x_display_info (display);
3741 Display *dpy = dpyinfo->display;
3742
3743 return Fcons (make_number (ProtocolVersion (dpy)),
3744 Fcons (make_number (ProtocolRevision (dpy)),
3745 Fcons (make_number (VendorRelease (dpy)), Qnil)));
3746 }
3747
3748 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
3749 "Returns the number of screens on the X server of display DISPLAY.\n\
3750 The optional argument DISPLAY specifies which display to ask about.\n\
3751 DISPLAY should be either a frame or a display name (a string).\n\
3752 If omitted or nil, that stands for the selected frame's display.")
3753 (display)
3754 Lisp_Object display;
3755 {
3756 struct x_display_info *dpyinfo = check_x_display_info (display);
3757
3758 return make_number (ScreenCount (dpyinfo->display));
3759 }
3760
3761 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
3762 "Returns the height in millimeters of the X display DISPLAY.\n\
3763 The optional argument DISPLAY specifies which display to ask about.\n\
3764 DISPLAY should be either a frame or a display name (a string).\n\
3765 If omitted or nil, that stands for the selected frame's display.")
3766 (display)
3767 Lisp_Object display;
3768 {
3769 struct x_display_info *dpyinfo = check_x_display_info (display);
3770
3771 return make_number (HeightMMOfScreen (dpyinfo->screen));
3772 }
3773
3774 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
3775 "Returns the width in millimeters of the X display DISPLAY.\n\
3776 The optional argument DISPLAY specifies which display to ask about.\n\
3777 DISPLAY should be either a frame or a display name (a string).\n\
3778 If omitted or nil, that stands for the selected frame's display.")
3779 (display)
3780 Lisp_Object display;
3781 {
3782 struct x_display_info *dpyinfo = check_x_display_info (display);
3783
3784 return make_number (WidthMMOfScreen (dpyinfo->screen));
3785 }
3786
3787 DEFUN ("x-display-backing-store", Fx_display_backing_store,
3788 Sx_display_backing_store, 0, 1, 0,
3789 "Returns an indication of whether X display DISPLAY does backing store.\n\
3790 The value may be `always', `when-mapped', or `not-useful'.\n\
3791 The optional argument DISPLAY specifies which display to ask about.\n\
3792 DISPLAY should be either a frame or a display name (a string).\n\
3793 If omitted or nil, that stands for the selected frame's display.")
3794 (display)
3795 Lisp_Object display;
3796 {
3797 struct x_display_info *dpyinfo = check_x_display_info (display);
3798
3799 switch (DoesBackingStore (dpyinfo->screen))
3800 {
3801 case Always:
3802 return intern ("always");
3803
3804 case WhenMapped:
3805 return intern ("when-mapped");
3806
3807 case NotUseful:
3808 return intern ("not-useful");
3809
3810 default:
3811 error ("Strange value for BackingStore parameter of screen");
3812 }
3813 }
3814
3815 DEFUN ("x-display-visual-class", Fx_display_visual_class,
3816 Sx_display_visual_class, 0, 1, 0,
3817 "Returns the visual class of the X display DISPLAY.\n\
3818 The value is one of the symbols `static-gray', `gray-scale',\n\
3819 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
3820 The optional argument DISPLAY specifies which display to ask about.\n\
3821 DISPLAY should be either a frame or a display name (a string).\n\
3822 If omitted or nil, that stands for the selected frame's display.")
3823 (display)
3824 Lisp_Object display;
3825 {
3826 struct x_display_info *dpyinfo = check_x_display_info (display);
3827
3828 switch (dpyinfo->visual->class)
3829 {
3830 case StaticGray: return (intern ("static-gray"));
3831 case GrayScale: return (intern ("gray-scale"));
3832 case StaticColor: return (intern ("static-color"));
3833 case PseudoColor: return (intern ("pseudo-color"));
3834 case TrueColor: return (intern ("true-color"));
3835 case DirectColor: return (intern ("direct-color"));
3836 default:
3837 error ("Display has an unknown visual class");
3838 }
3839 }
3840
3841 DEFUN ("x-display-save-under", Fx_display_save_under,
3842 Sx_display_save_under, 0, 1, 0,
3843 "Returns t if the X display DISPLAY supports the save-under feature.\n\
3844 The optional argument DISPLAY specifies which display to ask about.\n\
3845 DISPLAY should be either a frame or a display name (a string).\n\
3846 If omitted or nil, that stands for the selected frame's display.")
3847 (display)
3848 Lisp_Object display;
3849 {
3850 struct x_display_info *dpyinfo = check_x_display_info (display);
3851
3852 if (DoesSaveUnders (dpyinfo->screen) == True)
3853 return Qt;
3854 else
3855 return Qnil;
3856 }
3857 \f
3858 int
3859 x_pixel_width (f)
3860 register struct frame *f;
3861 {
3862 return PIXEL_WIDTH (f);
3863 }
3864
3865 int
3866 x_pixel_height (f)
3867 register struct frame *f;
3868 {
3869 return PIXEL_HEIGHT (f);
3870 }
3871
3872 int
3873 x_char_width (f)
3874 register struct frame *f;
3875 {
3876 return FONT_WIDTH (f->output_data.x->font);
3877 }
3878
3879 int
3880 x_char_height (f)
3881 register struct frame *f;
3882 {
3883 return f->output_data.x->line_height;
3884 }
3885
3886 int
3887 x_screen_planes (frame)
3888 Lisp_Object frame;
3889 {
3890 return FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_planes;
3891 }
3892 \f
3893 #if 0 /* These no longer seem like the right way to do things. */
3894
3895 /* Draw a rectangle on the frame with left top corner including
3896 the character specified by LEFT_CHAR and TOP_CHAR. The rectangle is
3897 CHARS by LINES wide and long and is the color of the cursor. */
3898
3899 void
3900 x_rectangle (f, gc, left_char, top_char, chars, lines)
3901 register struct frame *f;
3902 GC gc;
3903 register int top_char, left_char, chars, lines;
3904 {
3905 int width;
3906 int height;
3907 int left = (left_char * FONT_WIDTH (f->output_data.x->font)
3908 + f->output_data.x->internal_border_width);
3909 int top = (top_char * f->output_data.x->line_height
3910 + f->output_data.x->internal_border_width);
3911
3912 if (chars < 0)
3913 width = FONT_WIDTH (f->output_data.x->font) / 2;
3914 else
3915 width = FONT_WIDTH (f->output_data.x->font) * chars;
3916 if (lines < 0)
3917 height = f->output_data.x->line_height / 2;
3918 else
3919 height = f->output_data.x->line_height * lines;
3920
3921 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3922 gc, left, top, width, height);
3923 }
3924
3925 DEFUN ("x-draw-rectangle", Fx_draw_rectangle, Sx_draw_rectangle, 5, 5, 0,
3926 "Draw a rectangle on FRAME between coordinates specified by\n\
3927 numbers X0, Y0, X1, Y1 in the cursor pixel.")
3928 (frame, X0, Y0, X1, Y1)
3929 register Lisp_Object frame, X0, X1, Y0, Y1;
3930 {
3931 register int x0, y0, x1, y1, top, left, n_chars, n_lines;
3932
3933 CHECK_LIVE_FRAME (frame, 0);
3934 CHECK_NUMBER (X0, 0);
3935 CHECK_NUMBER (Y0, 1);
3936 CHECK_NUMBER (X1, 2);
3937 CHECK_NUMBER (Y1, 3);
3938
3939 x0 = XINT (X0);
3940 x1 = XINT (X1);
3941 y0 = XINT (Y0);
3942 y1 = XINT (Y1);
3943
3944 if (y1 > y0)
3945 {
3946 top = y0;
3947 n_lines = y1 - y0 + 1;
3948 }
3949 else
3950 {
3951 top = y1;
3952 n_lines = y0 - y1 + 1;
3953 }
3954
3955 if (x1 > x0)
3956 {
3957 left = x0;
3958 n_chars = x1 - x0 + 1;
3959 }
3960 else
3961 {
3962 left = x1;
3963 n_chars = x0 - x1 + 1;
3964 }
3965
3966 BLOCK_INPUT;
3967 x_rectangle (XFRAME (frame), XFRAME (frame)->output_data.x->cursor_gc,
3968 left, top, n_chars, n_lines);
3969 UNBLOCK_INPUT;
3970
3971 return Qt;
3972 }
3973
3974 DEFUN ("x-erase-rectangle", Fx_erase_rectangle, Sx_erase_rectangle, 5, 5, 0,
3975 "Draw a rectangle drawn on FRAME between coordinates\n\
3976 X0, Y0, X1, Y1 in the regular background-pixel.")
3977 (frame, X0, Y0, X1, Y1)
3978 register Lisp_Object frame, X0, Y0, X1, Y1;
3979 {
3980 register int x0, y0, x1, y1, top, left, n_chars, n_lines;
3981
3982 CHECK_LIVE_FRAME (frame, 0);
3983 CHECK_NUMBER (X0, 0);
3984 CHECK_NUMBER (Y0, 1);
3985 CHECK_NUMBER (X1, 2);
3986 CHECK_NUMBER (Y1, 3);
3987
3988 x0 = XINT (X0);
3989 x1 = XINT (X1);
3990 y0 = XINT (Y0);
3991 y1 = XINT (Y1);
3992
3993 if (y1 > y0)
3994 {
3995 top = y0;
3996 n_lines = y1 - y0 + 1;
3997 }
3998 else
3999 {
4000 top = y1;
4001 n_lines = y0 - y1 + 1;
4002 }
4003
4004 if (x1 > x0)
4005 {
4006 left = x0;
4007 n_chars = x1 - x0 + 1;
4008 }
4009 else
4010 {
4011 left = x1;
4012 n_chars = x0 - x1 + 1;
4013 }
4014
4015 BLOCK_INPUT;
4016 x_rectangle (XFRAME (frame), XFRAME (frame)->output_data.x->reverse_gc,
4017 left, top, n_chars, n_lines);
4018 UNBLOCK_INPUT;
4019
4020 return Qt;
4021 }
4022
4023 /* Draw lines around the text region beginning at the character position
4024 TOP_X, TOP_Y and ending at BOTTOM_X and BOTTOM_Y. GC specifies the
4025 pixel and line characteristics. */
4026
4027 #define line_len(line) (FRAME_CURRENT_GLYPHS (f)->used[(line)])
4028
4029 static void
4030 outline_region (f, gc, top_x, top_y, bottom_x, bottom_y)
4031 register struct frame *f;
4032 GC gc;
4033 int top_x, top_y, bottom_x, bottom_y;
4034 {
4035 register int ibw = f->output_data.x->internal_border_width;
4036 register int font_w = FONT_WIDTH (f->output_data.x->font);
4037 register int font_h = f->output_data.x->line_height;
4038 int y = top_y;
4039 int x = line_len (y);
4040 XPoint *pixel_points
4041 = (XPoint *) alloca (((bottom_y - top_y + 2) * 4) * sizeof (XPoint));
4042 register XPoint *this_point = pixel_points;
4043
4044 /* Do the horizontal top line/lines */
4045 if (top_x == 0)
4046 {
4047 this_point->x = ibw;
4048 this_point->y = ibw + (font_h * top_y);
4049 this_point++;
4050 if (x == 0)
4051 this_point->x = ibw + (font_w / 2); /* Half-size for newline chars. */
4052 else
4053 this_point->x = ibw + (font_w * x);
4054 this_point->y = (this_point - 1)->y;
4055 }
4056 else
4057 {
4058 this_point->x = ibw;
4059 this_point->y = ibw + (font_h * (top_y + 1));
4060 this_point++;
4061 this_point->x = ibw + (font_w * top_x);
4062 this_point->y = (this_point - 1)->y;
4063 this_point++;
4064 this_point->x = (this_point - 1)->x;
4065 this_point->y = ibw + (font_h * top_y);
4066 this_point++;
4067 this_point->x = ibw + (font_w * x);
4068 this_point->y = (this_point - 1)->y;
4069 }
4070
4071 /* Now do the right side. */
4072 while (y < bottom_y)
4073 { /* Right vertical edge */
4074 this_point++;
4075 this_point->x = (this_point - 1)->x;
4076 this_point->y = ibw + (font_h * (y + 1));
4077 this_point++;
4078
4079 y++; /* Horizontal connection to next line */
4080 x = line_len (y);
4081 if (x == 0)
4082 this_point->x = ibw + (font_w / 2);
4083 else
4084 this_point->x = ibw + (font_w * x);
4085
4086 this_point->y = (this_point - 1)->y;
4087 }
4088
4089 /* Now do the bottom and connect to the top left point. */
4090 this_point->x = ibw + (font_w * (bottom_x + 1));
4091
4092 this_point++;
4093 this_point->x = (this_point - 1)->x;
4094 this_point->y = ibw + (font_h * (bottom_y + 1));
4095 this_point++;
4096 this_point->x = ibw;
4097 this_point->y = (this_point - 1)->y;
4098 this_point++;
4099 this_point->x = pixel_points->x;
4100 this_point->y = pixel_points->y;
4101
4102 XDrawLines (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4103 gc, pixel_points,
4104 (this_point - pixel_points + 1), CoordModeOrigin);
4105 }
4106
4107 DEFUN ("x-contour-region", Fx_contour_region, Sx_contour_region, 1, 1, 0,
4108 "Highlight the region between point and the character under the mouse\n\
4109 selected frame.")
4110 (event)
4111 register Lisp_Object event;
4112 {
4113 register int x0, y0, x1, y1;
4114 register struct frame *f = selected_frame;
4115 register int p1, p2;
4116
4117 CHECK_CONS (event, 0);
4118
4119 BLOCK_INPUT;
4120 x0 = XINT (Fcar (Fcar (event)));
4121 y0 = XINT (Fcar (Fcdr (Fcar (event))));
4122
4123 /* If the mouse is past the end of the line, don't that area. */
4124 /* ReWrite this... */
4125
4126 x1 = f->cursor_x;
4127 y1 = f->cursor_y;
4128
4129 if (y1 > y0) /* point below mouse */
4130 outline_region (f, f->output_data.x->cursor_gc,
4131 x0, y0, x1, y1);
4132 else if (y1 < y0) /* point above mouse */
4133 outline_region (f, f->output_data.x->cursor_gc,
4134 x1, y1, x0, y0);
4135 else /* same line: draw horizontal rectangle */
4136 {
4137 if (x1 > x0)
4138 x_rectangle (f, f->output_data.x->cursor_gc,
4139 x0, y0, (x1 - x0 + 1), 1);
4140 else if (x1 < x0)
4141 x_rectangle (f, f->output_data.x->cursor_gc,
4142 x1, y1, (x0 - x1 + 1), 1);
4143 }
4144
4145 XFlush (FRAME_X_DISPLAY (f));
4146 UNBLOCK_INPUT;
4147
4148 return Qnil;
4149 }
4150
4151 DEFUN ("x-uncontour-region", Fx_uncontour_region, Sx_uncontour_region, 1, 1, 0,
4152 "Erase any highlighting of the region between point and the character\n\
4153 at X, Y on the selected frame.")
4154 (event)
4155 register Lisp_Object event;
4156 {
4157 register int x0, y0, x1, y1;
4158 register struct frame *f = selected_frame;
4159
4160 BLOCK_INPUT;
4161 x0 = XINT (Fcar (Fcar (event)));
4162 y0 = XINT (Fcar (Fcdr (Fcar (event))));
4163 x1 = f->cursor_x;
4164 y1 = f->cursor_y;
4165
4166 if (y1 > y0) /* point below mouse */
4167 outline_region (f, f->output_data.x->reverse_gc,
4168 x0, y0, x1, y1);
4169 else if (y1 < y0) /* point above mouse */
4170 outline_region (f, f->output_data.x->reverse_gc,
4171 x1, y1, x0, y0);
4172 else /* same line: draw horizontal rectangle */
4173 {
4174 if (x1 > x0)
4175 x_rectangle (f, f->output_data.x->reverse_gc,
4176 x0, y0, (x1 - x0 + 1), 1);
4177 else if (x1 < x0)
4178 x_rectangle (f, f->output_data.x->reverse_gc,
4179 x1, y1, (x0 - x1 + 1), 1);
4180 }
4181 UNBLOCK_INPUT;
4182
4183 return Qnil;
4184 }
4185
4186 #if 0
4187 int contour_begin_x, contour_begin_y;
4188 int contour_end_x, contour_end_y;
4189 int contour_npoints;
4190
4191 /* Clip the top part of the contour lines down (and including) line Y_POS.
4192 If X_POS is in the middle (rather than at the end) of the line, drop
4193 down a line at that character. */
4194
4195 static void
4196 clip_contour_top (y_pos, x_pos)
4197 {
4198 register XPoint *begin = contour_lines[y_pos].top_left;
4199 register XPoint *end;
4200 register int npoints;
4201 register struct display_line *line = selected_frame->phys_lines[y_pos + 1];
4202
4203 if (x_pos >= line->len - 1) /* Draw one, straight horizontal line. */
4204 {
4205 end = contour_lines[y_pos].top_right;
4206 npoints = (end - begin + 1);
4207 XDrawLines (x_current_display, contour_window,
4208 contour_erase_gc, begin_erase, npoints, CoordModeOrigin);
4209
4210 bcopy (end, begin + 1, contour_last_point - end + 1);
4211 contour_last_point -= (npoints - 2);
4212 XDrawLines (x_current_display, contour_window,
4213 contour_erase_gc, begin, 2, CoordModeOrigin);
4214 XFlush (x_current_display);
4215
4216 /* Now, update contour_lines structure. */
4217 }
4218 /* ______. */
4219 else /* |________*/
4220 {
4221 register XPoint *p = begin + 1;
4222 end = contour_lines[y_pos].bottom_right;
4223 npoints = (end - begin + 1);
4224 XDrawLines (x_current_display, contour_window,
4225 contour_erase_gc, begin_erase, npoints, CoordModeOrigin);
4226
4227 p->y = begin->y;
4228 p->x = ibw + (font_w * (x_pos + 1));
4229 p++;
4230 p->y = begin->y + font_h;
4231 p->x = (p - 1)->x;
4232 bcopy (end, begin + 3, contour_last_point - end + 1);
4233 contour_last_point -= (npoints - 5);
4234 XDrawLines (x_current_display, contour_window,
4235 contour_erase_gc, begin, 4, CoordModeOrigin);
4236 XFlush (x_current_display);
4237
4238 /* Now, update contour_lines structure. */
4239 }
4240 }
4241
4242 /* Erase the top horizontal lines of the contour, and then extend
4243 the contour upwards. */
4244
4245 static void
4246 extend_contour_top (line)
4247 {
4248 }
4249
4250 static void
4251 clip_contour_bottom (x_pos, y_pos)
4252 int x_pos, y_pos;
4253 {
4254 }
4255
4256 static void
4257 extend_contour_bottom (x_pos, y_pos)
4258 {
4259 }
4260
4261 DEFUN ("x-select-region", Fx_select_region, Sx_select_region, 1, 1, "e",
4262 "")
4263 (event)
4264 Lisp_Object event;
4265 {
4266 register struct frame *f = selected_frame;
4267 register int point_x = f->cursor_x;
4268 register int point_y = f->cursor_y;
4269 register int mouse_below_point;
4270 register Lisp_Object obj;
4271 register int x_contour_x, x_contour_y;
4272
4273 x_contour_x = x_mouse_x;
4274 x_contour_y = x_mouse_y;
4275 if (x_contour_y > point_y || (x_contour_y == point_y
4276 && x_contour_x > point_x))
4277 {
4278 mouse_below_point = 1;
4279 outline_region (f, f->output_data.x->cursor_gc, point_x, point_y,
4280 x_contour_x, x_contour_y);
4281 }
4282 else
4283 {
4284 mouse_below_point = 0;
4285 outline_region (f, f->output_data.x->cursor_gc, x_contour_x, x_contour_y,
4286 point_x, point_y);
4287 }
4288
4289 while (1)
4290 {
4291 obj = read_char (-1, 0, 0, Qnil, 0);
4292 if (!CONSP (obj))
4293 break;
4294
4295 if (mouse_below_point)
4296 {
4297 if (x_mouse_y <= point_y) /* Flipped. */
4298 {
4299 mouse_below_point = 0;
4300
4301 outline_region (f, f->output_data.x->reverse_gc, point_x, point_y,
4302 x_contour_x, x_contour_y);
4303 outline_region (f, f->output_data.x->cursor_gc, x_mouse_x, x_mouse_y,
4304 point_x, point_y);
4305 }
4306 else if (x_mouse_y < x_contour_y) /* Bottom clipped. */
4307 {
4308 clip_contour_bottom (x_mouse_y);
4309 }
4310 else if (x_mouse_y > x_contour_y) /* Bottom extended. */
4311 {
4312 extend_bottom_contour (x_mouse_y);
4313 }
4314
4315 x_contour_x = x_mouse_x;
4316 x_contour_y = x_mouse_y;
4317 }
4318 else /* mouse above or same line as point */
4319 {
4320 if (x_mouse_y >= point_y) /* Flipped. */
4321 {
4322 mouse_below_point = 1;
4323
4324 outline_region (f, f->output_data.x->reverse_gc,
4325 x_contour_x, x_contour_y, point_x, point_y);
4326 outline_region (f, f->output_data.x->cursor_gc, point_x, point_y,
4327 x_mouse_x, x_mouse_y);
4328 }
4329 else if (x_mouse_y > x_contour_y) /* Top clipped. */
4330 {
4331 clip_contour_top (x_mouse_y);
4332 }
4333 else if (x_mouse_y < x_contour_y) /* Top extended. */
4334 {
4335 extend_contour_top (x_mouse_y);
4336 }
4337 }
4338 }
4339
4340 unread_command_event = obj;
4341 if (mouse_below_point)
4342 {
4343 contour_begin_x = point_x;
4344 contour_begin_y = point_y;
4345 contour_end_x = x_contour_x;
4346 contour_end_y = x_contour_y;
4347 }
4348 else
4349 {
4350 contour_begin_x = x_contour_x;
4351 contour_begin_y = x_contour_y;
4352 contour_end_x = point_x;
4353 contour_end_y = point_y;
4354 }
4355 }
4356 #endif
4357
4358 DEFUN ("x-horizontal-line", Fx_horizontal_line, Sx_horizontal_line, 1, 1, "e",
4359 "")
4360 (event)
4361 Lisp_Object event;
4362 {
4363 register Lisp_Object obj;
4364 struct frame *f = selected_frame;
4365 register struct window *w = XWINDOW (selected_window);
4366 register GC line_gc = f->output_data.x->cursor_gc;
4367 register GC erase_gc = f->output_data.x->reverse_gc;
4368 #if 0
4369 char dash_list[] = {6, 4, 6, 4};
4370 int dashes = 4;
4371 XGCValues gc_values;
4372 #endif
4373 register int previous_y;
4374 register int line = (x_mouse_y + 1) * f->output_data.x->line_height
4375 + f->output_data.x->internal_border_width;
4376 register int left = f->output_data.x->internal_border_width
4377 + (w->left
4378 * FONT_WIDTH (f->output_data.x->font));
4379 register int right = left + (w->width
4380 * FONT_WIDTH (f->output_data.x->font))
4381 - f->output_data.x->internal_border_width;
4382
4383 #if 0
4384 BLOCK_INPUT;
4385 gc_values.foreground = f->output_data.x->cursor_pixel;
4386 gc_values.background = f->output_data.x->background_pixel;
4387 gc_values.line_width = 1;
4388 gc_values.line_style = LineOnOffDash;
4389 gc_values.cap_style = CapRound;
4390 gc_values.join_style = JoinRound;
4391
4392 line_gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4393 GCLineStyle | GCJoinStyle | GCCapStyle
4394 | GCLineWidth | GCForeground | GCBackground,
4395 &gc_values);
4396 XSetDashes (FRAME_X_DISPLAY (f), line_gc, 0, dash_list, dashes);
4397 gc_values.foreground = f->output_data.x->background_pixel;
4398 gc_values.background = f->output_data.x->foreground_pixel;
4399 erase_gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4400 GCLineStyle | GCJoinStyle | GCCapStyle
4401 | GCLineWidth | GCForeground | GCBackground,
4402 &gc_values);
4403 XSetDashes (FRAME_X_DISPLAY (f), erase_gc, 0, dash_list, dashes);
4404 UNBLOCK_INPUT;
4405 #endif
4406
4407 while (1)
4408 {
4409 BLOCK_INPUT;
4410 if (x_mouse_y >= XINT (w->top)
4411 && x_mouse_y < XINT (w->top) + XINT (w->height) - 1)
4412 {
4413 previous_y = x_mouse_y;
4414 line = (x_mouse_y + 1) * f->output_data.x->line_height
4415 + f->output_data.x->internal_border_width;
4416 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4417 line_gc, left, line, right, line);
4418 }
4419 XFlush (FRAME_X_DISPLAY (f));
4420 UNBLOCK_INPUT;
4421
4422 do
4423 {
4424 obj = read_char (-1, 0, 0, Qnil, 0);
4425 if (!CONSP (obj)
4426 || (! EQ (Fcar (Fcdr (Fcdr (obj))),
4427 Qvertical_scroll_bar))
4428 || x_mouse_grabbed)
4429 {
4430 BLOCK_INPUT;
4431 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4432 erase_gc, left, line, right, line);
4433 unread_command_event = obj;
4434 #if 0
4435 XFreeGC (FRAME_X_DISPLAY (f), line_gc);
4436 XFreeGC (FRAME_X_DISPLAY (f), erase_gc);
4437 #endif
4438 UNBLOCK_INPUT;
4439 return Qnil;
4440 }
4441 }
4442 while (x_mouse_y == previous_y);
4443
4444 BLOCK_INPUT;
4445 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4446 erase_gc, left, line, right, line);
4447 UNBLOCK_INPUT;
4448 }
4449 }
4450 #endif
4451 \f
4452 #if 0
4453 /* These keep track of the rectangle following the pointer. */
4454 int mouse_track_top, mouse_track_left, mouse_track_width;
4455
4456 /* Offset in buffer of character under the pointer, or 0. */
4457 int mouse_buffer_offset;
4458
4459 DEFUN ("x-track-pointer", Fx_track_pointer, Sx_track_pointer, 0, 0, 0,
4460 "Track the pointer.")
4461 ()
4462 {
4463 static Cursor current_pointer_shape;
4464 FRAME_PTR f = x_mouse_frame;
4465
4466 BLOCK_INPUT;
4467 if (EQ (Vmouse_frame_part, Qtext_part)
4468 && (current_pointer_shape != f->output_data.x->nontext_cursor))
4469 {
4470 unsigned char c;
4471 struct buffer *buf;
4472
4473 current_pointer_shape = f->output_data.x->nontext_cursor;
4474 XDefineCursor (FRAME_X_DISPLAY (f),
4475 FRAME_X_WINDOW (f),
4476 current_pointer_shape);
4477
4478 buf = XBUFFER (XWINDOW (Vmouse_window)->buffer);
4479 c = *(BUF_CHAR_ADDRESS (buf, mouse_buffer_offset));
4480 }
4481 else if (EQ (Vmouse_frame_part, Qmodeline_part)
4482 && (current_pointer_shape != f->output_data.x->modeline_cursor))
4483 {
4484 current_pointer_shape = f->output_data.x->modeline_cursor;
4485 XDefineCursor (FRAME_X_DISPLAY (f),
4486 FRAME_X_WINDOW (f),
4487 current_pointer_shape);
4488 }
4489
4490 XFlush (FRAME_X_DISPLAY (f));
4491 UNBLOCK_INPUT;
4492 }
4493 #endif
4494
4495 #if 0
4496 DEFUN ("x-track-pointer", Fx_track_pointer, Sx_track_pointer, 1, 1, "e",
4497 "Draw rectangle around character under mouse pointer, if there is one.")
4498 (event)
4499 Lisp_Object event;
4500 {
4501 struct window *w = XWINDOW (Vmouse_window);
4502 struct frame *f = XFRAME (WINDOW_FRAME (w));
4503 struct buffer *b = XBUFFER (w->buffer);
4504 Lisp_Object obj;
4505
4506 if (! EQ (Vmouse_window, selected_window))
4507 return Qnil;
4508
4509 if (EQ (event, Qnil))
4510 {
4511 int x, y;
4512
4513 x_read_mouse_position (selected_frame, &x, &y);
4514 }
4515
4516 BLOCK_INPUT;
4517 mouse_track_width = 0;
4518 mouse_track_left = mouse_track_top = -1;
4519
4520 do
4521 {
4522 if ((x_mouse_x != mouse_track_left
4523 && (x_mouse_x < mouse_track_left
4524 || x_mouse_x > (mouse_track_left + mouse_track_width)))
4525 || x_mouse_y != mouse_track_top)
4526 {
4527 int hp = 0; /* Horizontal position */
4528 int len = FRAME_CURRENT_GLYPHS (f)->used[x_mouse_y];
4529 int p = FRAME_CURRENT_GLYPHS (f)->bufp[x_mouse_y];
4530 int tab_width = XINT (b->tab_width);
4531 int ctl_arrow_p = !NILP (b->ctl_arrow);
4532 unsigned char c;
4533 int mode_line_vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
4534 int in_mode_line = 0;
4535
4536 if (! FRAME_CURRENT_GLYPHS (f)->enable[x_mouse_y])
4537 break;
4538
4539 /* Erase previous rectangle. */
4540 if (mouse_track_width)
4541 {
4542 x_rectangle (f, f->output_data.x->reverse_gc,
4543 mouse_track_left, mouse_track_top,
4544 mouse_track_width, 1);
4545
4546 if ((mouse_track_left == f->phys_cursor_x
4547 || mouse_track_left == f->phys_cursor_x - 1)
4548 && mouse_track_top == f->phys_cursor_y)
4549 {
4550 x_display_cursor (f, 1);
4551 }
4552 }
4553
4554 mouse_track_left = x_mouse_x;
4555 mouse_track_top = x_mouse_y;
4556 mouse_track_width = 0;
4557
4558 if (mouse_track_left > len) /* Past the end of line. */
4559 goto draw_or_not;
4560
4561 if (mouse_track_top == mode_line_vpos)
4562 {
4563 in_mode_line = 1;
4564 goto draw_or_not;
4565 }
4566
4567 if (tab_width <= 0 || tab_width > 20) tab_width = 8;
4568 do
4569 {
4570 c = FETCH_CHAR (p);
4571 if (len == f->width && hp == len - 1 && c != '\n')
4572 goto draw_or_not;
4573
4574 switch (c)
4575 {
4576 case '\t':
4577 mouse_track_width = tab_width - (hp % tab_width);
4578 p++;
4579 hp += mouse_track_width;
4580 if (hp > x_mouse_x)
4581 {
4582 mouse_track_left = hp - mouse_track_width;
4583 goto draw_or_not;
4584 }
4585 continue;
4586
4587 case '\n':
4588 mouse_track_width = -1;
4589 goto draw_or_not;
4590
4591 default:
4592 if (ctl_arrow_p && (c < 040 || c == 0177))
4593 {
4594 if (p > ZV)
4595 goto draw_or_not;
4596
4597 mouse_track_width = 2;
4598 p++;
4599 hp +=2;
4600 if (hp > x_mouse_x)
4601 {
4602 mouse_track_left = hp - mouse_track_width;
4603 goto draw_or_not;
4604 }
4605 }
4606 else
4607 {
4608 mouse_track_width = 1;
4609 p++;
4610 hp++;
4611 }
4612 continue;
4613 }
4614 }
4615 while (hp <= x_mouse_x);
4616
4617 draw_or_not:
4618 if (mouse_track_width) /* Over text; use text pointer shape. */
4619 {
4620 XDefineCursor (FRAME_X_DISPLAY (f),
4621 FRAME_X_WINDOW (f),
4622 f->output_data.x->text_cursor);
4623 x_rectangle (f, f->output_data.x->cursor_gc,
4624 mouse_track_left, mouse_track_top,
4625 mouse_track_width, 1);
4626 }
4627 else if (in_mode_line)
4628 XDefineCursor (FRAME_X_DISPLAY (f),
4629 FRAME_X_WINDOW (f),
4630 f->output_data.x->modeline_cursor);
4631 else
4632 XDefineCursor (FRAME_X_DISPLAY (f),
4633 FRAME_X_WINDOW (f),
4634 f->output_data.x->nontext_cursor);
4635 }
4636
4637 XFlush (FRAME_X_DISPLAY (f));
4638 UNBLOCK_INPUT;
4639
4640 obj = read_char (-1, 0, 0, Qnil, 0);
4641 BLOCK_INPUT;
4642 }
4643 while (CONSP (obj) /* Mouse event */
4644 && EQ (Fcar (Fcdr (Fcdr (obj))), Qnil) /* Not scroll bar */
4645 && EQ (Vmouse_depressed, Qnil) /* Only motion events */
4646 && EQ (Vmouse_window, selected_window) /* In this window */
4647 && x_mouse_frame);
4648
4649 unread_command_event = obj;
4650
4651 if (mouse_track_width)
4652 {
4653 x_rectangle (f, f->output_data.x->reverse_gc,
4654 mouse_track_left, mouse_track_top,
4655 mouse_track_width, 1);
4656 mouse_track_width = 0;
4657 if ((mouse_track_left == f->phys_cursor_x
4658 || mouse_track_left - 1 == f->phys_cursor_x)
4659 && mouse_track_top == f->phys_cursor_y)
4660 {
4661 x_display_cursor (f, 1);
4662 }
4663 }
4664 XDefineCursor (FRAME_X_DISPLAY (f),
4665 FRAME_X_WINDOW (f),
4666 f->output_data.x->nontext_cursor);
4667 XFlush (FRAME_X_DISPLAY (f));
4668 UNBLOCK_INPUT;
4669
4670 return Qnil;
4671 }
4672 #endif
4673 \f
4674 #if 0
4675 #include "glyphs.h"
4676
4677 /* Draw a pixmap specified by IMAGE_DATA of dimensions WIDTH and HEIGHT
4678 on the frame F at position X, Y. */
4679
4680 x_draw_pixmap (f, x, y, image_data, width, height)
4681 struct frame *f;
4682 int x, y, width, height;
4683 char *image_data;
4684 {
4685 Pixmap image;
4686
4687 image = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
4688 FRAME_X_WINDOW (f), image_data,
4689 width, height);
4690 XCopyPlane (FRAME_X_DISPLAY (f), image, FRAME_X_WINDOW (f),
4691 f->output_data.x->normal_gc, 0, 0, width, height, x, y);
4692 }
4693 #endif
4694 \f
4695 #if 0 /* I'm told these functions are superfluous
4696 given the ability to bind function keys. */
4697
4698 #ifdef HAVE_X11
4699 DEFUN ("x-rebind-key", Fx_rebind_key, Sx_rebind_key, 3, 3, 0,
4700 "Rebind X keysym KEYSYM, with MODIFIERS, to generate NEWSTRING.\n\
4701 KEYSYM is a string which conforms to the X keysym definitions found\n\
4702 in X11/keysymdef.h, sans the initial XK_. MODIFIERS is nil or a\n\
4703 list of strings specifying modifier keys such as Control_L, which must\n\
4704 also be depressed for NEWSTRING to appear.")
4705 (x_keysym, modifiers, newstring)
4706 register Lisp_Object x_keysym;
4707 register Lisp_Object modifiers;
4708 register Lisp_Object newstring;
4709 {
4710 char *rawstring;
4711 register KeySym keysym;
4712 KeySym modifier_list[16];
4713
4714 check_x ();
4715 CHECK_STRING (x_keysym, 1);
4716 CHECK_STRING (newstring, 3);
4717
4718 keysym = XStringToKeysym ((char *) XSTRING (x_keysym)->data);
4719 if (keysym == NoSymbol)
4720 error ("Keysym does not exist");
4721
4722 if (NILP (modifiers))
4723 XRebindKeysym (x_current_display, keysym, modifier_list, 0,
4724 XSTRING (newstring)->data, XSTRING (newstring)->size);
4725 else
4726 {
4727 register Lisp_Object rest, mod;
4728 register int i = 0;
4729
4730 for (rest = modifiers; !NILP (rest); rest = Fcdr (rest))
4731 {
4732 if (i == 16)
4733 error ("Can't have more than 16 modifiers");
4734
4735 mod = Fcar (rest);
4736 CHECK_STRING (mod, 3);
4737 modifier_list[i] = XStringToKeysym ((char *) XSTRING (mod)->data);
4738 #ifndef HAVE_X11R5
4739 if (modifier_list[i] == NoSymbol
4740 || !(IsModifierKey (modifier_list[i])
4741 || ((unsigned)(modifier_list[i]) == XK_Mode_switch)
4742 || ((unsigned)(modifier_list[i]) == XK_Num_Lock)))
4743 #else
4744 if (modifier_list[i] == NoSymbol
4745 || !IsModifierKey (modifier_list[i]))
4746 #endif
4747 error ("Element is not a modifier keysym");
4748 i++;
4749 }
4750
4751 XRebindKeysym (x_current_display, keysym, modifier_list, i,
4752 XSTRING (newstring)->data, XSTRING (newstring)->size);
4753 }
4754
4755 return Qnil;
4756 }
4757
4758 DEFUN ("x-rebind-keys", Fx_rebind_keys, Sx_rebind_keys, 2, 2, 0,
4759 "Rebind KEYCODE to list of strings STRINGS.\n\
4760 STRINGS should be a list of 16 elements, one for each shift combination.\n\
4761 nil as element means don't change.\n\
4762 See the documentation of `x-rebind-key' for more information.")
4763 (keycode, strings)
4764 register Lisp_Object keycode;
4765 register Lisp_Object strings;
4766 {
4767 register Lisp_Object item;
4768 register unsigned char *rawstring;
4769 KeySym rawkey, modifier[1];
4770 int strsize;
4771 register unsigned i;
4772
4773 check_x ();
4774 CHECK_NUMBER (keycode, 1);
4775 CHECK_CONS (strings, 2);
4776 rawkey = (KeySym) ((unsigned) (XINT (keycode))) & 255;
4777 for (i = 0; i <= 15; strings = Fcdr (strings), i++)
4778 {
4779 item = Fcar (strings);
4780 if (!NILP (item))
4781 {
4782 CHECK_STRING (item, 2);
4783 strsize = XSTRING (item)->size;
4784 rawstring = (unsigned char *) xmalloc (strsize);
4785 bcopy (XSTRING (item)->data, rawstring, strsize);
4786 modifier[1] = 1 << i;
4787 XRebindKeysym (x_current_display, rawkey, modifier, 1,
4788 rawstring, strsize);
4789 }
4790 }
4791 return Qnil;
4792 }
4793 #endif /* HAVE_X11 */
4794 #endif /* 0 */
4795 \f
4796 #ifndef HAVE_XSCREENNUMBEROFSCREEN
4797 int
4798 XScreenNumberOfScreen (scr)
4799 register Screen *scr;
4800 {
4801 register Display *dpy;
4802 register Screen *dpyscr;
4803 register int i;
4804
4805 dpy = scr->display;
4806 dpyscr = dpy->screens;
4807
4808 for (i = 0; i < dpy->nscreens; i++, dpyscr++)
4809 if (scr == dpyscr)
4810 return i;
4811
4812 return -1;
4813 }
4814 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
4815
4816 Visual *
4817 select_visual (dpy, screen, depth)
4818 Display *dpy;
4819 Screen *screen;
4820 unsigned int *depth;
4821 {
4822 Visual *v;
4823 XVisualInfo *vinfo, vinfo_template;
4824 int n_visuals;
4825
4826 v = DefaultVisualOfScreen (screen);
4827
4828 #ifdef HAVE_X11R4
4829 vinfo_template.visualid = XVisualIDFromVisual (v);
4830 #else
4831 vinfo_template.visualid = v->visualid;
4832 #endif
4833
4834 vinfo_template.screen = XScreenNumberOfScreen (screen);
4835
4836 vinfo = XGetVisualInfo (dpy,
4837 VisualIDMask | VisualScreenMask, &vinfo_template,
4838 &n_visuals);
4839 if (n_visuals != 1)
4840 fatal ("Can't get proper X visual info");
4841
4842 if ((1 << vinfo->depth) == vinfo->colormap_size)
4843 *depth = vinfo->depth;
4844 else
4845 {
4846 int i = 0;
4847 int n = vinfo->colormap_size - 1;
4848 while (n)
4849 {
4850 n = n >> 1;
4851 i++;
4852 }
4853 *depth = i;
4854 }
4855
4856 XFree ((char *) vinfo);
4857 return v;
4858 }
4859
4860 /* Return the X display structure for the display named NAME.
4861 Open a new connection if necessary. */
4862
4863 struct x_display_info *
4864 x_display_info_for_name (name)
4865 Lisp_Object name;
4866 {
4867 Lisp_Object names;
4868 struct x_display_info *dpyinfo;
4869
4870 CHECK_STRING (name, 0);
4871
4872 if (! EQ (Vwindow_system, intern ("x")))
4873 error ("Not using X Windows");
4874
4875 for (dpyinfo = x_display_list, names = x_display_name_list;
4876 dpyinfo;
4877 dpyinfo = dpyinfo->next, names = XCONS (names)->cdr)
4878 {
4879 Lisp_Object tem;
4880 tem = Fstring_equal (XCONS (XCONS (names)->car)->car, name);
4881 if (!NILP (tem))
4882 return dpyinfo;
4883 }
4884
4885 /* Use this general default value to start with. */
4886 Vx_resource_name = Vinvocation_name;
4887
4888 validate_x_resource_name ();
4889
4890 dpyinfo = x_term_init (name, (unsigned char *)0,
4891 (char *) XSTRING (Vx_resource_name)->data);
4892
4893 if (dpyinfo == 0)
4894 error ("Cannot connect to X server %s", XSTRING (name)->data);
4895
4896 x_in_use = 1;
4897 XSETFASTINT (Vwindow_system_version, 11);
4898
4899 return dpyinfo;
4900 }
4901
4902 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
4903 1, 3, 0, "Open a connection to an X server.\n\
4904 DISPLAY is the name of the display to connect to.\n\
4905 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
4906 If the optional third arg MUST-SUCCEED is non-nil,\n\
4907 terminate Emacs if we can't open the connection.")
4908 (display, xrm_string, must_succeed)
4909 Lisp_Object display, xrm_string, must_succeed;
4910 {
4911 unsigned int n_planes;
4912 unsigned char *xrm_option;
4913 struct x_display_info *dpyinfo;
4914
4915 CHECK_STRING (display, 0);
4916 if (! NILP (xrm_string))
4917 CHECK_STRING (xrm_string, 1);
4918
4919 if (! EQ (Vwindow_system, intern ("x")))
4920 error ("Not using X Windows");
4921
4922 if (! NILP (xrm_string))
4923 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
4924 else
4925 xrm_option = (unsigned char *) 0;
4926
4927 validate_x_resource_name ();
4928
4929 /* This is what opens the connection and sets x_current_display.
4930 This also initializes many symbols, such as those used for input. */
4931 dpyinfo = x_term_init (display, xrm_option,
4932 (char *) XSTRING (Vx_resource_name)->data);
4933
4934 if (dpyinfo == 0)
4935 {
4936 if (!NILP (must_succeed))
4937 fatal ("Cannot connect to X server %s.\n\
4938 Check the DISPLAY environment variable or use `-d'.\n\
4939 Also use the `xhost' program to verify that it is set to permit\n\
4940 connections from your machine.\n",
4941 XSTRING (display)->data);
4942 else
4943 error ("Cannot connect to X server %s", XSTRING (display)->data);
4944 }
4945
4946 x_in_use = 1;
4947
4948 XSETFASTINT (Vwindow_system_version, 11);
4949 return Qnil;
4950 }
4951
4952 DEFUN ("x-close-connection", Fx_close_connection,
4953 Sx_close_connection, 1, 1, 0,
4954 "Close the connection to DISPLAY's X server.\n\
4955 For DISPLAY, specify either a frame or a display name (a string).\n\
4956 If DISPLAY is nil, that stands for the selected frame's display.")
4957 (display)
4958 Lisp_Object display;
4959 {
4960 struct x_display_info *dpyinfo = check_x_display_info (display);
4961 struct x_display_info *tail;
4962 int i;
4963
4964 if (dpyinfo->reference_count > 0)
4965 error ("Display still has frames on it");
4966
4967 BLOCK_INPUT;
4968 /* Free the fonts in the font table. */
4969 for (i = 0; i < dpyinfo->n_fonts; i++)
4970 {
4971 if (dpyinfo->font_table[i].name)
4972 free (dpyinfo->font_table[i].name);
4973 /* Don't free the full_name string;
4974 it is always shared with something else. */
4975 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
4976 }
4977 x_destroy_all_bitmaps (dpyinfo);
4978 XSetCloseDownMode (dpyinfo->display, DestroyAll);
4979
4980 #ifdef USE_X_TOOLKIT
4981 XtCloseDisplay (dpyinfo->display);
4982 #else
4983 XCloseDisplay (dpyinfo->display);
4984 #endif
4985
4986 x_delete_display (dpyinfo);
4987 UNBLOCK_INPUT;
4988
4989 return Qnil;
4990 }
4991
4992 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
4993 "Return the list of display names that Emacs has connections to.")
4994 ()
4995 {
4996 Lisp_Object tail, result;
4997
4998 result = Qnil;
4999 for (tail = x_display_name_list; ! NILP (tail); tail = XCONS (tail)->cdr)
5000 result = Fcons (XCONS (XCONS (tail)->car)->car, result);
5001
5002 return result;
5003 }
5004
5005 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
5006 "If ON is non-nil, report X errors as soon as the erring request is made.\n\
5007 If ON is nil, allow buffering of requests.\n\
5008 Turning on synchronization prohibits the Xlib routines from buffering\n\
5009 requests and seriously degrades performance, but makes debugging much\n\
5010 easier.\n\
5011 The optional second argument DISPLAY specifies which display to act on.\n\
5012 DISPLAY should be either a frame or a display name (a string).\n\
5013 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
5014 (on, display)
5015 Lisp_Object display, on;
5016 {
5017 struct x_display_info *dpyinfo = check_x_display_info (display);
5018
5019 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
5020
5021 return Qnil;
5022 }
5023
5024 /* Wait for responses to all X commands issued so far for frame F. */
5025
5026 void
5027 x_sync (f)
5028 FRAME_PTR f;
5029 {
5030 BLOCK_INPUT;
5031 XSync (FRAME_X_DISPLAY (f), False);
5032 UNBLOCK_INPUT;
5033 }
5034 \f
5035 syms_of_xfns ()
5036 {
5037 /* This is zero if not using X windows. */
5038 x_in_use = 0;
5039
5040 /* The section below is built by the lisp expression at the top of the file,
5041 just above where these variables are declared. */
5042 /*&&& init symbols here &&&*/
5043 Qauto_raise = intern ("auto-raise");
5044 staticpro (&Qauto_raise);
5045 Qauto_lower = intern ("auto-lower");
5046 staticpro (&Qauto_lower);
5047 Qbackground_color = intern ("background-color");
5048 staticpro (&Qbackground_color);
5049 Qbar = intern ("bar");
5050 staticpro (&Qbar);
5051 Qborder_color = intern ("border-color");
5052 staticpro (&Qborder_color);
5053 Qborder_width = intern ("border-width");
5054 staticpro (&Qborder_width);
5055 Qbox = intern ("box");
5056 staticpro (&Qbox);
5057 Qcursor_color = intern ("cursor-color");
5058 staticpro (&Qcursor_color);
5059 Qcursor_type = intern ("cursor-type");
5060 staticpro (&Qcursor_type);
5061 Qforeground_color = intern ("foreground-color");
5062 staticpro (&Qforeground_color);
5063 Qgeometry = intern ("geometry");
5064 staticpro (&Qgeometry);
5065 Qicon_left = intern ("icon-left");
5066 staticpro (&Qicon_left);
5067 Qicon_top = intern ("icon-top");
5068 staticpro (&Qicon_top);
5069 Qicon_type = intern ("icon-type");
5070 staticpro (&Qicon_type);
5071 Qicon_name = intern ("icon-name");
5072 staticpro (&Qicon_name);
5073 Qinternal_border_width = intern ("internal-border-width");
5074 staticpro (&Qinternal_border_width);
5075 Qleft = intern ("left");
5076 staticpro (&Qleft);
5077 Qmouse_color = intern ("mouse-color");
5078 staticpro (&Qmouse_color);
5079 Qnone = intern ("none");
5080 staticpro (&Qnone);
5081 Qparent_id = intern ("parent-id");
5082 staticpro (&Qparent_id);
5083 Qscroll_bar_width = intern ("scroll-bar-width");
5084 staticpro (&Qscroll_bar_width);
5085 Qsuppress_icon = intern ("suppress-icon");
5086 staticpro (&Qsuppress_icon);
5087 Qtop = intern ("top");
5088 staticpro (&Qtop);
5089 Qundefined_color = intern ("undefined-color");
5090 staticpro (&Qundefined_color);
5091 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
5092 staticpro (&Qvertical_scroll_bars);
5093 Qvisibility = intern ("visibility");
5094 staticpro (&Qvisibility);
5095 Qwindow_id = intern ("window-id");
5096 staticpro (&Qwindow_id);
5097 Qx_frame_parameter = intern ("x-frame-parameter");
5098 staticpro (&Qx_frame_parameter);
5099 Qx_resource_name = intern ("x-resource-name");
5100 staticpro (&Qx_resource_name);
5101 Quser_position = intern ("user-position");
5102 staticpro (&Quser_position);
5103 Quser_size = intern ("user-size");
5104 staticpro (&Quser_size);
5105 Qdisplay = intern ("display");
5106 staticpro (&Qdisplay);
5107 /* This is the end of symbol initialization. */
5108
5109 Fput (Qundefined_color, Qerror_conditions,
5110 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
5111 Fput (Qundefined_color, Qerror_message,
5112 build_string ("Undefined color"));
5113
5114 init_x_parm_symbols ();
5115
5116 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
5117 "List of directories to search for bitmap files for X.");
5118 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
5119
5120 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
5121 "The shape of the pointer when over text.\n\
5122 Changing the value does not affect existing frames\n\
5123 unless you set the mouse color.");
5124 Vx_pointer_shape = Qnil;
5125
5126 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
5127 "The name Emacs uses to look up X resources; for internal use only.\n\
5128 `x-get-resource' uses this as the first component of the instance name\n\
5129 when requesting resource values.\n\
5130 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
5131 was invoked, or to the value specified with the `-name' or `-rn'\n\
5132 switches, if present.");
5133 Vx_resource_name = Qnil;
5134
5135 #if 0 /* This doesn't really do anything. */
5136 DEFVAR_INT ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
5137 "The shape of the pointer when not over text.\n\
5138 This variable takes effect when you create a new frame\n\
5139 or when you set the mouse color.");
5140 #endif
5141 Vx_nontext_pointer_shape = Qnil;
5142
5143 #if 0 /* This doesn't really do anything. */
5144 DEFVAR_INT ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
5145 "The shape of the pointer when over the mode line.\n\
5146 This variable takes effect when you create a new frame\n\
5147 or when you set the mouse color.");
5148 #endif
5149 Vx_mode_pointer_shape = Qnil;
5150
5151 DEFVAR_INT ("x-sensitive-text-pointer-shape",
5152 &Vx_sensitive_text_pointer_shape,
5153 "The shape of the pointer when over mouse-sensitive text.\n\
5154 This variable takes effect when you create a new frame\n\
5155 or when you set the mouse color.");
5156 Vx_sensitive_text_pointer_shape = Qnil;
5157
5158 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
5159 "A string indicating the foreground color of the cursor box.");
5160 Vx_cursor_fore_pixel = Qnil;
5161
5162 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
5163 "Non-nil if no X window manager is in use.\n\
5164 Emacs doesn't try to figure this out; this is always nil\n\
5165 unless you set it to something else.");
5166 /* We don't have any way to find this out, so set it to nil
5167 and maybe the user would like to set it to t. */
5168 Vx_no_window_manager = Qnil;
5169
5170 #ifdef USE_X_TOOLKIT
5171 Fprovide (intern ("x-toolkit"));
5172 #endif
5173 #ifdef USE_MOTIF
5174 Fprovide (intern ("motif"));
5175 #endif
5176
5177 defsubr (&Sx_get_resource);
5178 #if 0
5179 defsubr (&Sx_draw_rectangle);
5180 defsubr (&Sx_erase_rectangle);
5181 defsubr (&Sx_contour_region);
5182 defsubr (&Sx_uncontour_region);
5183 #endif
5184 defsubr (&Sx_list_fonts);
5185 defsubr (&Sx_display_color_p);
5186 defsubr (&Sx_display_grayscale_p);
5187 defsubr (&Sx_color_defined_p);
5188 defsubr (&Sx_color_values);
5189 defsubr (&Sx_server_max_request_size);
5190 defsubr (&Sx_server_vendor);
5191 defsubr (&Sx_server_version);
5192 defsubr (&Sx_display_pixel_width);
5193 defsubr (&Sx_display_pixel_height);
5194 defsubr (&Sx_display_mm_width);
5195 defsubr (&Sx_display_mm_height);
5196 defsubr (&Sx_display_screens);
5197 defsubr (&Sx_display_planes);
5198 defsubr (&Sx_display_color_cells);
5199 defsubr (&Sx_display_visual_class);
5200 defsubr (&Sx_display_backing_store);
5201 defsubr (&Sx_display_save_under);
5202 #if 0
5203 defsubr (&Sx_rebind_key);
5204 defsubr (&Sx_rebind_keys);
5205 defsubr (&Sx_track_pointer);
5206 defsubr (&Sx_grab_pointer);
5207 defsubr (&Sx_ungrab_pointer);
5208 #endif
5209 defsubr (&Sx_parse_geometry);
5210 defsubr (&Sx_create_frame);
5211 #if 0
5212 defsubr (&Sx_horizontal_line);
5213 #endif
5214 defsubr (&Sx_open_connection);
5215 defsubr (&Sx_close_connection);
5216 defsubr (&Sx_display_list);
5217 defsubr (&Sx_synchronize);
5218 }
5219
5220 #endif /* HAVE_X_WINDOWS */