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