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