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