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