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