]> code.delx.au - gnu-emacs/blob - src/xfns.c
(Fx_create_frame): Default Qinternal_border_width to 1.
[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) = 3;
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 change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0);
1987 }
1988 \f
1989 /* Subroutines of creating an X frame. */
1990
1991 /* Make sure that Vx_resource_name is set to a reasonable value.
1992 Fix it up, or set it to `emacs' if it is too hopeless. */
1993
1994 static void
1995 validate_x_resource_name ()
1996 {
1997 int len;
1998 /* Number of valid characters in the resource name. */
1999 int good_count = 0;
2000 /* Number of invalid characters in the resource name. */
2001 int bad_count = 0;
2002 Lisp_Object new;
2003 int i;
2004
2005 if (STRINGP (Vx_resource_name))
2006 {
2007 unsigned char *p = XSTRING (Vx_resource_name)->data;
2008 int i;
2009
2010 len = XSTRING (Vx_resource_name)->size;
2011
2012 /* Only letters, digits, - and _ are valid in resource names.
2013 Count the valid characters and count the invalid ones. */
2014 for (i = 0; i < len; i++)
2015 {
2016 int c = p[i];
2017 if (! ((c >= 'a' && c <= 'z')
2018 || (c >= 'A' && c <= 'Z')
2019 || (c >= '0' && c <= '9')
2020 || c == '-' || c == '_'))
2021 bad_count++;
2022 else
2023 good_count++;
2024 }
2025 }
2026 else
2027 /* Not a string => completely invalid. */
2028 bad_count = 5, good_count = 0;
2029
2030 /* If name is valid already, return. */
2031 if (bad_count == 0)
2032 return;
2033
2034 /* If name is entirely invalid, or nearly so, use `emacs'. */
2035 if (good_count == 0
2036 || (good_count == 1 && bad_count > 0))
2037 {
2038 Vx_resource_name = build_string ("emacs");
2039 return;
2040 }
2041
2042 /* Name is partly valid. Copy it and replace the invalid characters
2043 with underscores. */
2044
2045 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
2046
2047 for (i = 0; i < len; i++)
2048 {
2049 int c = XSTRING (new)->data[i];
2050 if (! ((c >= 'a' && c <= 'z')
2051 || (c >= 'A' && c <= 'Z')
2052 || (c >= '0' && c <= '9')
2053 || c == '-' || c == '_'))
2054 XSTRING (new)->data[i] = '_';
2055 }
2056 }
2057
2058
2059 extern char *x_get_string_resource ();
2060
2061 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
2062 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2063 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2064 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2065 the name specified by the `-name' or `-rn' command-line arguments.\n\
2066 \n\
2067 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2068 class, respectively. You must specify both of them or neither.\n\
2069 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2070 and the class is `Emacs.CLASS.SUBCLASS'.")
2071 (attribute, class, component, subclass)
2072 Lisp_Object attribute, class, component, subclass;
2073 {
2074 register char *value;
2075 char *name_key;
2076 char *class_key;
2077
2078 check_x ();
2079
2080 CHECK_STRING (attribute, 0);
2081 CHECK_STRING (class, 0);
2082
2083 if (!NILP (component))
2084 CHECK_STRING (component, 1);
2085 if (!NILP (subclass))
2086 CHECK_STRING (subclass, 2);
2087 if (NILP (component) != NILP (subclass))
2088 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2089
2090 validate_x_resource_name ();
2091
2092 /* Allocate space for the components, the dots which separate them,
2093 and the final '\0'. Make them big enough for the worst case. */
2094 name_key = (char *) alloca (XSTRING (Vx_resource_name)->size
2095 + (STRINGP (component)
2096 ? XSTRING (component)->size : 0)
2097 + XSTRING (attribute)->size
2098 + 3);
2099
2100 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2101 + XSTRING (class)->size
2102 + (STRINGP (subclass)
2103 ? XSTRING (subclass)->size : 0)
2104 + 3);
2105
2106 /* Start with emacs.FRAMENAME for the name (the specific one)
2107 and with `Emacs' for the class key (the general one). */
2108 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2109 strcpy (class_key, EMACS_CLASS);
2110
2111 strcat (class_key, ".");
2112 strcat (class_key, XSTRING (class)->data);
2113
2114 if (!NILP (component))
2115 {
2116 strcat (class_key, ".");
2117 strcat (class_key, XSTRING (subclass)->data);
2118
2119 strcat (name_key, ".");
2120 strcat (name_key, XSTRING (component)->data);
2121 }
2122
2123 strcat (name_key, ".");
2124 strcat (name_key, XSTRING (attribute)->data);
2125
2126 value = x_get_string_resource (check_x_display_info (Qnil)->xrdb,
2127 name_key, class_key);
2128
2129 if (value != (char *) 0)
2130 return build_string (value);
2131 else
2132 return Qnil;
2133 }
2134
2135 /* Used when C code wants a resource value. */
2136
2137 char *
2138 x_get_resource_string (attribute, class)
2139 char *attribute, *class;
2140 {
2141 register char *value;
2142 char *name_key;
2143 char *class_key;
2144
2145 /* Allocate space for the components, the dots which separate them,
2146 and the final '\0'. */
2147 name_key = (char *) alloca (XSTRING (Vinvocation_name)->size
2148 + strlen (attribute) + 2);
2149 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2150 + strlen (class) + 2);
2151
2152 sprintf (name_key, "%s.%s",
2153 XSTRING (Vinvocation_name)->data,
2154 attribute);
2155 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
2156
2157 return x_get_string_resource (FRAME_X_DISPLAY_INFO (selected_frame)->xrdb,
2158 name_key, class_key);
2159 }
2160
2161 /* Types we might convert a resource string into. */
2162 enum resource_types
2163 {
2164 number, boolean, string, symbol
2165 };
2166
2167 /* Return the value of parameter PARAM.
2168
2169 First search ALIST, then Vdefault_frame_alist, then the X defaults
2170 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2171
2172 Convert the resource to the type specified by desired_type.
2173
2174 If no default is specified, return Qunbound. If you call
2175 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2176 and don't let it get stored in any Lisp-visible variables! */
2177
2178 static Lisp_Object
2179 x_get_arg (alist, param, attribute, class, type)
2180 Lisp_Object alist, param;
2181 char *attribute;
2182 char *class;
2183 enum resource_types type;
2184 {
2185 register Lisp_Object tem;
2186
2187 tem = Fassq (param, alist);
2188 if (EQ (tem, Qnil))
2189 tem = Fassq (param, Vdefault_frame_alist);
2190 if (EQ (tem, Qnil))
2191 {
2192
2193 if (attribute)
2194 {
2195 tem = Fx_get_resource (build_string (attribute),
2196 build_string (class),
2197 Qnil, Qnil);
2198
2199 if (NILP (tem))
2200 return Qunbound;
2201
2202 switch (type)
2203 {
2204 case number:
2205 return make_number (atoi (XSTRING (tem)->data));
2206
2207 case boolean:
2208 tem = Fdowncase (tem);
2209 if (!strcmp (XSTRING (tem)->data, "on")
2210 || !strcmp (XSTRING (tem)->data, "true"))
2211 return Qt;
2212 else
2213 return Qnil;
2214
2215 case string:
2216 return tem;
2217
2218 case symbol:
2219 /* As a special case, we map the values `true' and `on'
2220 to Qt, and `false' and `off' to Qnil. */
2221 {
2222 Lisp_Object lower;
2223 lower = Fdowncase (tem);
2224 if (!strcmp (XSTRING (lower)->data, "on")
2225 || !strcmp (XSTRING (lower)->data, "true"))
2226 return Qt;
2227 else if (!strcmp (XSTRING (lower)->data, "off")
2228 || !strcmp (XSTRING (lower)->data, "false"))
2229 return Qnil;
2230 else
2231 return Fintern (tem, Qnil);
2232 }
2233
2234 default:
2235 abort ();
2236 }
2237 }
2238 else
2239 return Qunbound;
2240 }
2241 return Fcdr (tem);
2242 }
2243
2244 /* Like x_get_arg, but also record the value in f->param_alist. */
2245
2246 static Lisp_Object
2247 x_get_and_record_arg (f, alist, param, attribute, class, type)
2248 struct frame *f;
2249 Lisp_Object alist, param;
2250 char *attribute;
2251 char *class;
2252 enum resource_types type;
2253 {
2254 Lisp_Object value;
2255
2256 value = x_get_arg (alist, param, attribute, class, type);
2257 if (! NILP (value))
2258 store_frame_param (f, param, value);
2259
2260 return value;
2261 }
2262
2263 /* Record in frame F the specified or default value according to ALIST
2264 of the parameter named PARAM (a Lisp symbol).
2265 If no value is specified for PARAM, look for an X default for XPROP
2266 on the frame named NAME.
2267 If that is not found either, use the value DEFLT. */
2268
2269 static Lisp_Object
2270 x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
2271 struct frame *f;
2272 Lisp_Object alist;
2273 Lisp_Object prop;
2274 Lisp_Object deflt;
2275 char *xprop;
2276 char *xclass;
2277 enum resource_types type;
2278 {
2279 Lisp_Object tem;
2280
2281 tem = x_get_arg (alist, prop, xprop, xclass, type);
2282 if (EQ (tem, Qunbound))
2283 tem = deflt;
2284 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2285 return tem;
2286 }
2287 \f
2288 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
2289 "Parse an X-style geometry string STRING.\n\
2290 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2291 The properties returned may include `top', `left', `height', and `width'.\n\
2292 The value of `left' or `top' may be an integer,\n\
2293 or a list (+ N) meaning N pixels relative to top/left corner,\n\
2294 or a list (- N) meaning -N pixels relative to bottom/right corner.")
2295 (string)
2296 Lisp_Object string;
2297 {
2298 int geometry, x, y;
2299 unsigned int width, height;
2300 Lisp_Object result;
2301
2302 CHECK_STRING (string, 0);
2303
2304 geometry = XParseGeometry ((char *) XSTRING (string)->data,
2305 &x, &y, &width, &height);
2306
2307 #if 0
2308 if (!!(geometry & XValue) != !!(geometry & YValue))
2309 error ("Must specify both x and y position, or neither");
2310 #endif
2311
2312 result = Qnil;
2313 if (geometry & XValue)
2314 {
2315 Lisp_Object element;
2316
2317 if (x >= 0 && (geometry & XNegative))
2318 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
2319 else if (x < 0 && ! (geometry & XNegative))
2320 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
2321 else
2322 element = Fcons (Qleft, make_number (x));
2323 result = Fcons (element, result);
2324 }
2325
2326 if (geometry & YValue)
2327 {
2328 Lisp_Object element;
2329
2330 if (y >= 0 && (geometry & YNegative))
2331 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
2332 else if (y < 0 && ! (geometry & YNegative))
2333 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
2334 else
2335 element = Fcons (Qtop, make_number (y));
2336 result = Fcons (element, result);
2337 }
2338
2339 if (geometry & WidthValue)
2340 result = Fcons (Fcons (Qwidth, make_number (width)), result);
2341 if (geometry & HeightValue)
2342 result = Fcons (Fcons (Qheight, make_number (height)), result);
2343
2344 return result;
2345 }
2346
2347 /* Calculate the desired size and position of this window,
2348 and return the flags saying which aspects were specified.
2349
2350 This function does not make the coordinates positive. */
2351
2352 #define DEFAULT_ROWS 40
2353 #define DEFAULT_COLS 80
2354
2355 static int
2356 x_figure_window_size (f, parms)
2357 struct frame *f;
2358 Lisp_Object parms;
2359 {
2360 register Lisp_Object tem0, tem1, tem2;
2361 int height, width, left, top;
2362 register int geometry;
2363 long window_prompting = 0;
2364
2365 /* Default values if we fall through.
2366 Actually, if that happens we should get
2367 window manager prompting. */
2368 SET_FRAME_WIDTH (f, DEFAULT_COLS);
2369 f->height = DEFAULT_ROWS;
2370 /* Window managers expect that if program-specified
2371 positions are not (0,0), they're intentional, not defaults. */
2372 f->output_data.x->top_pos = 0;
2373 f->output_data.x->left_pos = 0;
2374
2375 tem0 = x_get_arg (parms, Qheight, 0, 0, number);
2376 tem1 = x_get_arg (parms, Qwidth, 0, 0, number);
2377 tem2 = x_get_arg (parms, Quser_size, 0, 0, number);
2378 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
2379 {
2380 if (!EQ (tem0, Qunbound))
2381 {
2382 CHECK_NUMBER (tem0, 0);
2383 f->height = XINT (tem0);
2384 }
2385 if (!EQ (tem1, Qunbound))
2386 {
2387 CHECK_NUMBER (tem1, 0);
2388 SET_FRAME_WIDTH (f, XINT (tem1));
2389 }
2390 if (!NILP (tem2) && !EQ (tem2, Qunbound))
2391 window_prompting |= USSize;
2392 else
2393 window_prompting |= PSize;
2394 }
2395
2396 f->output_data.x->vertical_scroll_bar_extra
2397 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
2398 ? 0
2399 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
2400 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
2401 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
2402 f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
2403 f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
2404
2405 tem0 = x_get_arg (parms, Qtop, 0, 0, number);
2406 tem1 = x_get_arg (parms, Qleft, 0, 0, number);
2407 tem2 = x_get_arg (parms, Quser_position, 0, 0, number);
2408 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
2409 {
2410 if (EQ (tem0, Qminus))
2411 {
2412 f->output_data.x->top_pos = 0;
2413 window_prompting |= YNegative;
2414 }
2415 else if (CONSP (tem0) && EQ (XCONS (tem0)->car, Qminus)
2416 && CONSP (XCONS (tem0)->cdr)
2417 && INTEGERP (XCONS (XCONS (tem0)->cdr)->car))
2418 {
2419 f->output_data.x->top_pos = - XINT (XCONS (XCONS (tem0)->cdr)->car);
2420 window_prompting |= YNegative;
2421 }
2422 else if (CONSP (tem0) && EQ (XCONS (tem0)->car, Qplus)
2423 && CONSP (XCONS (tem0)->cdr)
2424 && INTEGERP (XCONS (XCONS (tem0)->cdr)->car))
2425 {
2426 f->output_data.x->top_pos = XINT (XCONS (XCONS (tem0)->cdr)->car);
2427 }
2428 else if (EQ (tem0, Qunbound))
2429 f->output_data.x->top_pos = 0;
2430 else
2431 {
2432 CHECK_NUMBER (tem0, 0);
2433 f->output_data.x->top_pos = XINT (tem0);
2434 if (f->output_data.x->top_pos < 0)
2435 window_prompting |= YNegative;
2436 }
2437
2438 if (EQ (tem1, Qminus))
2439 {
2440 f->output_data.x->left_pos = 0;
2441 window_prompting |= XNegative;
2442 }
2443 else if (CONSP (tem1) && EQ (XCONS (tem1)->car, Qminus)
2444 && CONSP (XCONS (tem1)->cdr)
2445 && INTEGERP (XCONS (XCONS (tem1)->cdr)->car))
2446 {
2447 f->output_data.x->left_pos = - XINT (XCONS (XCONS (tem1)->cdr)->car);
2448 window_prompting |= XNegative;
2449 }
2450 else if (CONSP (tem1) && EQ (XCONS (tem1)->car, Qplus)
2451 && CONSP (XCONS (tem1)->cdr)
2452 && INTEGERP (XCONS (XCONS (tem1)->cdr)->car))
2453 {
2454 f->output_data.x->left_pos = XINT (XCONS (XCONS (tem1)->cdr)->car);
2455 }
2456 else if (EQ (tem1, Qunbound))
2457 f->output_data.x->left_pos = 0;
2458 else
2459 {
2460 CHECK_NUMBER (tem1, 0);
2461 f->output_data.x->left_pos = XINT (tem1);
2462 if (f->output_data.x->left_pos < 0)
2463 window_prompting |= XNegative;
2464 }
2465
2466 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
2467 window_prompting |= USPosition;
2468 else
2469 window_prompting |= PPosition;
2470 }
2471
2472 return window_prompting;
2473 }
2474
2475 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
2476
2477 Status
2478 XSetWMProtocols (dpy, w, protocols, count)
2479 Display *dpy;
2480 Window w;
2481 Atom *protocols;
2482 int count;
2483 {
2484 Atom prop;
2485 prop = XInternAtom (dpy, "WM_PROTOCOLS", False);
2486 if (prop == None) return False;
2487 XChangeProperty (dpy, w, prop, XA_ATOM, 32, PropModeReplace,
2488 (unsigned char *) protocols, count);
2489 return True;
2490 }
2491 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
2492 \f
2493 #ifdef USE_X_TOOLKIT
2494
2495 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
2496 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
2497 already be present because of the toolkit (Motif adds some of them,
2498 for example, but Xt doesn't). */
2499
2500 static void
2501 hack_wm_protocols (f, widget)
2502 FRAME_PTR f;
2503 Widget widget;
2504 {
2505 Display *dpy = XtDisplay (widget);
2506 Window w = XtWindow (widget);
2507 int need_delete = 1;
2508 int need_focus = 1;
2509 int need_save = 1;
2510
2511 BLOCK_INPUT;
2512 {
2513 Atom type, *atoms = 0;
2514 int format = 0;
2515 unsigned long nitems = 0;
2516 unsigned long bytes_after;
2517
2518 if ((XGetWindowProperty (dpy, w,
2519 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
2520 (long)0, (long)100, False, XA_ATOM,
2521 &type, &format, &nitems, &bytes_after,
2522 (unsigned char **) &atoms)
2523 == Success)
2524 && format == 32 && type == XA_ATOM)
2525 while (nitems > 0)
2526 {
2527 nitems--;
2528 if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
2529 need_delete = 0;
2530 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
2531 need_focus = 0;
2532 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
2533 need_save = 0;
2534 }
2535 if (atoms) XFree ((char *) atoms);
2536 }
2537 {
2538 Atom props [10];
2539 int count = 0;
2540 if (need_delete)
2541 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
2542 if (need_focus)
2543 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus;
2544 if (need_save)
2545 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
2546 if (count)
2547 XChangeProperty (dpy, w, FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
2548 XA_ATOM, 32, PropModeAppend,
2549 (unsigned char *) props, count);
2550 }
2551 UNBLOCK_INPUT;
2552 }
2553 #endif
2554 \f
2555 #ifdef USE_X_TOOLKIT
2556
2557 /* Create and set up the X widget for frame F. */
2558
2559 static void
2560 x_window (f, window_prompting, minibuffer_only)
2561 struct frame *f;
2562 long window_prompting;
2563 int minibuffer_only;
2564 {
2565 XClassHint class_hints;
2566 XSetWindowAttributes attributes;
2567 unsigned long attribute_mask;
2568
2569 Widget shell_widget;
2570 Widget pane_widget;
2571 Widget frame_widget;
2572 Arg al [25];
2573 int ac;
2574
2575 BLOCK_INPUT;
2576
2577 /* Use the resource name as the top-level widget name
2578 for looking up resources. Make a non-Lisp copy
2579 for the window manager, so GC relocation won't bother it.
2580
2581 Elsewhere we specify the window name for the window manager. */
2582
2583 {
2584 char *str = (char *) XSTRING (Vx_resource_name)->data;
2585 f->namebuf = (char *) xmalloc (strlen (str) + 1);
2586 strcpy (f->namebuf, str);
2587 }
2588
2589 ac = 0;
2590 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
2591 XtSetArg (al[ac], XtNinput, 1); ac++;
2592 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
2593 XtSetArg (al[ac], XtNborderWidth, f->output_data.x->border_width); ac++;
2594 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
2595 applicationShellWidgetClass,
2596 FRAME_X_DISPLAY (f), al, ac);
2597
2598 f->output_data.x->widget = shell_widget;
2599 /* maybe_set_screen_title_format (shell_widget); */
2600
2601 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
2602 (widget_value *) NULL,
2603 shell_widget, False,
2604 (lw_callback) NULL,
2605 (lw_callback) NULL,
2606 (lw_callback) NULL);
2607
2608 f->output_data.x->column_widget = pane_widget;
2609
2610 /* mappedWhenManaged to false tells to the paned window to not map/unmap
2611 the emacs screen when changing menubar. This reduces flickering. */
2612
2613 ac = 0;
2614 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
2615 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
2616 XtSetArg (al[ac], XtNallowResize, 1); ac++;
2617 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
2618 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
2619 frame_widget = XtCreateWidget (f->namebuf,
2620 emacsFrameClass,
2621 pane_widget, al, ac);
2622
2623 f->output_data.x->edit_widget = frame_widget;
2624
2625 XtManageChild (frame_widget);
2626
2627 /* Do some needed geometry management. */
2628 {
2629 int len;
2630 char *tem, shell_position[32];
2631 Arg al[2];
2632 int ac = 0;
2633 int extra_borders = 0;
2634 int menubar_size
2635 = (f->output_data.x->menubar_widget
2636 ? (f->output_data.x->menubar_widget->core.height
2637 + f->output_data.x->menubar_widget->core.border_width)
2638 : 0);
2639 extern char *lwlib_toolkit_type;
2640
2641 #if 0 /* Experimentally, we now get the right results
2642 for -geometry -0-0 without this. 24 Aug 96, rms. */
2643 if (FRAME_EXTERNAL_MENU_BAR (f))
2644 {
2645 Dimension ibw = 0;
2646 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
2647 menubar_size += ibw;
2648 }
2649 #endif
2650
2651 f->output_data.x->menubar_height = menubar_size;
2652
2653 /* Motif seems to need this amount added to the sizes
2654 specified for the shell widget. The Athena/Lucid widgets don't.
2655 Both conclusions reached experimentally. -- rms. */
2656 if (!strcmp (lwlib_toolkit_type, "motif"))
2657 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
2658 &extra_borders, NULL);
2659
2660 /* Convert our geometry parameters into a geometry string
2661 and specify it.
2662 Note that we do not specify here whether the position
2663 is a user-specified or program-specified one.
2664 We pass that information later, in x_wm_set_size_hints. */
2665 {
2666 int left = f->output_data.x->left_pos;
2667 int xneg = window_prompting & XNegative;
2668 int top = f->output_data.x->top_pos;
2669 int yneg = window_prompting & YNegative;
2670 if (xneg)
2671 left = -left;
2672 if (yneg)
2673 top = -top;
2674
2675 if (window_prompting & USPosition)
2676 sprintf (shell_position, "=%dx%d%c%d%c%d",
2677 PIXEL_WIDTH (f) + extra_borders,
2678 PIXEL_HEIGHT (f) + menubar_size + extra_borders,
2679 (xneg ? '-' : '+'), left,
2680 (yneg ? '-' : '+'), top);
2681 else
2682 sprintf (shell_position, "=%dx%d",
2683 PIXEL_WIDTH (f) + extra_borders,
2684 PIXEL_HEIGHT (f) + menubar_size + extra_borders);
2685 }
2686
2687 len = strlen (shell_position) + 1;
2688 tem = (char *) xmalloc (len);
2689 strncpy (tem, shell_position, len);
2690 XtSetArg (al[ac], XtNgeometry, tem); ac++;
2691 XtSetValues (shell_widget, al, ac);
2692 }
2693
2694 XtManageChild (pane_widget);
2695 XtRealizeWidget (shell_widget);
2696
2697 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
2698
2699 validate_x_resource_name ();
2700
2701 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
2702 class_hints.res_class = EMACS_CLASS;
2703 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
2704
2705 #ifdef HAVE_X_I18N
2706 #ifndef X_I18N_INHIBITED
2707 {
2708 XIM xim;
2709 XIC xic = NULL;
2710
2711 xim = XOpenIM (FRAME_X_DISPLAY (f), NULL, NULL, NULL);
2712
2713 if (xim)
2714 {
2715 xic = XCreateIC (xim,
2716 XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
2717 XNClientWindow, FRAME_X_WINDOW(f),
2718 XNFocusWindow, FRAME_X_WINDOW(f),
2719 NULL);
2720
2721 if (xic == 0)
2722 {
2723 XCloseIM (xim);
2724 xim = NULL;
2725 }
2726 }
2727 FRAME_XIM (f) = xim;
2728 FRAME_XIC (f) = xic;
2729 }
2730 #else /* X_I18N_INHIBITED */
2731 FRAME_XIM (f) = 0;
2732 FRAME_XIC (f) = 0;
2733 #endif /* X_I18N_INHIBITED */
2734 #endif /* HAVE_X_I18N */
2735
2736 f->output_data.x->wm_hints.input = True;
2737 f->output_data.x->wm_hints.flags |= InputHint;
2738 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2739 &f->output_data.x->wm_hints);
2740
2741 hack_wm_protocols (f, shell_widget);
2742
2743 #ifdef HACK_EDITRES
2744 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
2745 #endif
2746
2747 /* Do a stupid property change to force the server to generate a
2748 propertyNotify event so that the event_stream server timestamp will
2749 be initialized to something relevant to the time we created the window.
2750 */
2751 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
2752 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
2753 XA_ATOM, 32, PropModeAppend,
2754 (unsigned char*) NULL, 0);
2755
2756 /* Make all the standard events reach the Emacs frame. */
2757 attributes.event_mask = STANDARD_EVENT_SET;
2758 attribute_mask = CWEventMask;
2759 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
2760 attribute_mask, &attributes);
2761
2762 XtMapWidget (frame_widget);
2763
2764 /* x_set_name normally ignores requests to set the name if the
2765 requested name is the same as the current name. This is the one
2766 place where that assumption isn't correct; f->name is set, but
2767 the X server hasn't been told. */
2768 {
2769 Lisp_Object name;
2770 int explicit = f->explicit_name;
2771
2772 f->explicit_name = 0;
2773 name = f->name;
2774 f->name = Qnil;
2775 x_set_name (f, name, explicit);
2776 }
2777
2778 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2779 f->output_data.x->text_cursor);
2780
2781 UNBLOCK_INPUT;
2782
2783 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
2784 initialize_frame_menubar (f);
2785 lw_set_main_areas (pane_widget, f->output_data.x->menubar_widget, frame_widget);
2786
2787 if (FRAME_X_WINDOW (f) == 0)
2788 error ("Unable to create window");
2789 }
2790
2791 #else /* not USE_X_TOOLKIT */
2792
2793 /* Create and set up the X window for frame F. */
2794
2795 x_window (f)
2796 struct frame *f;
2797
2798 {
2799 XClassHint class_hints;
2800 XSetWindowAttributes attributes;
2801 unsigned long attribute_mask;
2802
2803 attributes.background_pixel = f->output_data.x->background_pixel;
2804 attributes.border_pixel = f->output_data.x->border_pixel;
2805 attributes.bit_gravity = StaticGravity;
2806 attributes.backing_store = NotUseful;
2807 attributes.save_under = True;
2808 attributes.event_mask = STANDARD_EVENT_SET;
2809 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity
2810 #if 0
2811 | CWBackingStore | CWSaveUnder
2812 #endif
2813 | CWEventMask);
2814
2815 BLOCK_INPUT;
2816 FRAME_X_WINDOW (f)
2817 = XCreateWindow (FRAME_X_DISPLAY (f),
2818 f->output_data.x->parent_desc,
2819 f->output_data.x->left_pos,
2820 f->output_data.x->top_pos,
2821 PIXEL_WIDTH (f), PIXEL_HEIGHT (f),
2822 f->output_data.x->border_width,
2823 CopyFromParent, /* depth */
2824 InputOutput, /* class */
2825 FRAME_X_DISPLAY_INFO (f)->visual,
2826 attribute_mask, &attributes);
2827 #ifdef HAVE_X_I18N
2828 #ifndef X_I18N_INHIBITED
2829 {
2830 XIM xim;
2831 XIC xic = NULL;
2832
2833 xim = XOpenIM (FRAME_X_DISPLAY(f), NULL, NULL, NULL);
2834
2835 if (xim)
2836 {
2837 xic = XCreateIC (xim,
2838 XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
2839 XNClientWindow, FRAME_X_WINDOW(f),
2840 XNFocusWindow, FRAME_X_WINDOW(f),
2841 NULL);
2842
2843 if (!xic)
2844 {
2845 XCloseIM (xim);
2846 xim = NULL;
2847 }
2848 }
2849
2850 FRAME_XIM (f) = xim;
2851 FRAME_XIC (f) = xic;
2852 }
2853 #else /* X_I18N_INHIBITED */
2854 FRAME_XIM (f) = 0;
2855 FRAME_XIC (f) = 0;
2856 #endif /* X_I18N_INHIBITED */
2857 #endif /* HAVE_X_I18N */
2858
2859 validate_x_resource_name ();
2860
2861 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
2862 class_hints.res_class = EMACS_CLASS;
2863 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
2864
2865 /* The menubar is part of the ordinary display;
2866 it does not count in addition to the height of the window. */
2867 f->output_data.x->menubar_height = 0;
2868
2869 /* This indicates that we use the "Passive Input" input model.
2870 Unless we do this, we don't get the Focus{In,Out} events that we
2871 need to draw the cursor correctly. Accursed bureaucrats.
2872 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
2873
2874 f->output_data.x->wm_hints.input = True;
2875 f->output_data.x->wm_hints.flags |= InputHint;
2876 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2877 &f->output_data.x->wm_hints);
2878 f->output_data.x->wm_hints.icon_pixmap = None;
2879
2880 /* Request "save yourself" and "delete window" commands from wm. */
2881 {
2882 Atom protocols[2];
2883 protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
2884 protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
2885 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
2886 }
2887
2888 /* x_set_name normally ignores requests to set the name if the
2889 requested name is the same as the current name. This is the one
2890 place where that assumption isn't correct; f->name is set, but
2891 the X server hasn't been told. */
2892 {
2893 Lisp_Object name;
2894 int explicit = f->explicit_name;
2895
2896 f->explicit_name = 0;
2897 name = f->name;
2898 f->name = Qnil;
2899 x_set_name (f, name, explicit);
2900 }
2901
2902 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2903 f->output_data.x->text_cursor);
2904
2905 UNBLOCK_INPUT;
2906
2907 if (FRAME_X_WINDOW (f) == 0)
2908 error ("Unable to create window");
2909 }
2910
2911 #endif /* not USE_X_TOOLKIT */
2912
2913 /* Handle the icon stuff for this window. Perhaps later we might
2914 want an x_set_icon_position which can be called interactively as
2915 well. */
2916
2917 static void
2918 x_icon (f, parms)
2919 struct frame *f;
2920 Lisp_Object parms;
2921 {
2922 Lisp_Object icon_x, icon_y;
2923
2924 /* Set the position of the icon. Note that twm groups all
2925 icons in an icon window. */
2926 icon_x = x_get_and_record_arg (f, parms, Qicon_left, 0, 0, number);
2927 icon_y = x_get_and_record_arg (f, parms, Qicon_top, 0, 0, number);
2928 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
2929 {
2930 CHECK_NUMBER (icon_x, 0);
2931 CHECK_NUMBER (icon_y, 0);
2932 }
2933 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
2934 error ("Both left and top icon corners of icon must be specified");
2935
2936 BLOCK_INPUT;
2937
2938 if (! EQ (icon_x, Qunbound))
2939 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
2940
2941 /* Start up iconic or window? */
2942 x_wm_set_window_state
2943 (f, (EQ (x_get_arg (parms, Qvisibility, 0, 0, symbol), Qicon)
2944 ? IconicState
2945 : NormalState));
2946
2947 x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
2948 ? f->icon_name
2949 : f->name))->data);
2950
2951 UNBLOCK_INPUT;
2952 }
2953
2954 /* Make the GC's needed for this window, setting the
2955 background, border and mouse colors; also create the
2956 mouse cursor and the gray border tile. */
2957
2958 static char cursor_bits[] =
2959 {
2960 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2961 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2962 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2963 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2964 };
2965
2966 static void
2967 x_make_gc (f)
2968 struct frame *f;
2969 {
2970 XGCValues gc_values;
2971 GC temp_gc;
2972 XImage tileimage;
2973
2974 BLOCK_INPUT;
2975
2976 /* Create the GC's of this frame.
2977 Note that many default values are used. */
2978
2979 /* Normal video */
2980 gc_values.font = f->output_data.x->font->fid;
2981 gc_values.foreground = f->output_data.x->foreground_pixel;
2982 gc_values.background = f->output_data.x->background_pixel;
2983 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
2984 f->output_data.x->normal_gc = XCreateGC (FRAME_X_DISPLAY (f),
2985 FRAME_X_WINDOW (f),
2986 GCLineWidth | GCFont
2987 | GCForeground | GCBackground,
2988 &gc_values);
2989
2990 /* Reverse video style. */
2991 gc_values.foreground = f->output_data.x->background_pixel;
2992 gc_values.background = f->output_data.x->foreground_pixel;
2993 f->output_data.x->reverse_gc = XCreateGC (FRAME_X_DISPLAY (f),
2994 FRAME_X_WINDOW (f),
2995 GCFont | GCForeground | GCBackground
2996 | GCLineWidth,
2997 &gc_values);
2998
2999 /* Cursor has cursor-color background, background-color foreground. */
3000 gc_values.foreground = f->output_data.x->background_pixel;
3001 gc_values.background = f->output_data.x->cursor_pixel;
3002 gc_values.fill_style = FillOpaqueStippled;
3003 gc_values.stipple
3004 = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
3005 FRAME_X_DISPLAY_INFO (f)->root_window,
3006 cursor_bits, 16, 16);
3007 f->output_data.x->cursor_gc
3008 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3009 (GCFont | GCForeground | GCBackground
3010 | GCFillStyle | GCStipple | GCLineWidth),
3011 &gc_values);
3012
3013 /* Create the gray border tile used when the pointer is not in
3014 the frame. Since this depends on the frame's pixel values,
3015 this must be done on a per-frame basis. */
3016 f->output_data.x->border_tile
3017 = (XCreatePixmapFromBitmapData
3018 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
3019 gray_bits, gray_width, gray_height,
3020 f->output_data.x->foreground_pixel,
3021 f->output_data.x->background_pixel,
3022 DefaultDepth (FRAME_X_DISPLAY (f),
3023 XScreenNumberOfScreen (FRAME_X_SCREEN (f)))));
3024
3025 UNBLOCK_INPUT;
3026 }
3027
3028 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
3029 1, 1, 0,
3030 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
3031 Returns an Emacs frame object.\n\
3032 ALIST is an alist of frame parameters.\n\
3033 If the parameters specify that the frame should not have a minibuffer,\n\
3034 and do not specify a specific minibuffer window to use,\n\
3035 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
3036 be shared by the new frame.\n\
3037 \n\
3038 This function is an internal primitive--use `make-frame' instead.")
3039 (parms)
3040 Lisp_Object parms;
3041 {
3042 struct frame *f;
3043 Lisp_Object frame, tem;
3044 Lisp_Object name;
3045 int minibuffer_only = 0;
3046 long window_prompting = 0;
3047 int width, height;
3048 int count = specpdl_ptr - specpdl;
3049 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3050 Lisp_Object display;
3051 struct x_display_info *dpyinfo;
3052 Lisp_Object parent;
3053 struct kboard *kb;
3054
3055 check_x ();
3056
3057 /* Use this general default value to start with
3058 until we know if this frame has a specified name. */
3059 Vx_resource_name = Vinvocation_name;
3060
3061 display = x_get_arg (parms, Qdisplay, 0, 0, string);
3062 if (EQ (display, Qunbound))
3063 display = Qnil;
3064 dpyinfo = check_x_display_info (display);
3065 #ifdef MULTI_KBOARD
3066 kb = dpyinfo->kboard;
3067 #else
3068 kb = &the_only_kboard;
3069 #endif
3070
3071 name = x_get_arg (parms, Qname, "name", "Name", string);
3072 if (!STRINGP (name)
3073 && ! EQ (name, Qunbound)
3074 && ! NILP (name))
3075 error ("Invalid frame name--not a string or nil");
3076
3077 if (STRINGP (name))
3078 Vx_resource_name = name;
3079
3080 /* See if parent window is specified. */
3081 parent = x_get_arg (parms, Qparent_id, NULL, NULL, number);
3082 if (EQ (parent, Qunbound))
3083 parent = Qnil;
3084 if (! NILP (parent))
3085 CHECK_NUMBER (parent, 0);
3086
3087 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
3088 /* No need to protect DISPLAY because that's not used after passing
3089 it to make_frame_without_minibuffer. */
3090 frame = Qnil;
3091 GCPRO4 (parms, parent, name, frame);
3092 tem = x_get_arg (parms, Qminibuffer, 0, 0, symbol);
3093 if (EQ (tem, Qnone) || NILP (tem))
3094 f = make_frame_without_minibuffer (Qnil, kb, display);
3095 else if (EQ (tem, Qonly))
3096 {
3097 f = make_minibuffer_frame ();
3098 minibuffer_only = 1;
3099 }
3100 else if (WINDOWP (tem))
3101 f = make_frame_without_minibuffer (tem, kb, display);
3102 else
3103 f = make_frame (1);
3104
3105 XSETFRAME (frame, f);
3106
3107 /* Note that X Windows does support scroll bars. */
3108 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
3109
3110 f->output_method = output_x_window;
3111 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
3112 bzero (f->output_data.x, sizeof (struct x_output));
3113 f->output_data.x->icon_bitmap = -1;
3114
3115 f->icon_name
3116 = x_get_arg (parms, Qicon_name, "iconName", "Title", string);
3117 if (! STRINGP (f->icon_name))
3118 f->icon_name = Qnil;
3119
3120 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
3121 #ifdef MULTI_KBOARD
3122 FRAME_KBOARD (f) = kb;
3123 #endif
3124
3125 /* Specify the parent under which to make this X window. */
3126
3127 if (!NILP (parent))
3128 {
3129 f->output_data.x->parent_desc = parent;
3130 f->output_data.x->explicit_parent = 1;
3131 }
3132 else
3133 {
3134 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
3135 f->output_data.x->explicit_parent = 0;
3136 }
3137
3138 /* Note that the frame has no physical cursor right now. */
3139 f->phys_cursor_x = -1;
3140
3141 /* Set the name; the functions to which we pass f expect the name to
3142 be set. */
3143 if (EQ (name, Qunbound) || NILP (name))
3144 {
3145 f->name = build_string (dpyinfo->x_id_name);
3146 f->explicit_name = 0;
3147 }
3148 else
3149 {
3150 f->name = name;
3151 f->explicit_name = 1;
3152 /* use the frame's title when getting resources for this frame. */
3153 specbind (Qx_resource_name, name);
3154 }
3155
3156 /* Extract the window parameters from the supplied values
3157 that are needed to determine window geometry. */
3158 {
3159 Lisp_Object font;
3160
3161 font = x_get_arg (parms, Qfont, "font", "Font", string);
3162 BLOCK_INPUT;
3163 /* First, try whatever font the caller has specified. */
3164 if (STRINGP (font))
3165 font = x_new_font (f, XSTRING (font)->data);
3166 /* Try out a font which we hope has bold and italic variations. */
3167 if (!STRINGP (font))
3168 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3169 if (! STRINGP (font))
3170 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3171 if (! STRINGP (font))
3172 /* This was formerly the first thing tried, but it finds too many fonts
3173 and takes too long. */
3174 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
3175 /* If those didn't work, look for something which will at least work. */
3176 if (! STRINGP (font))
3177 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
3178 UNBLOCK_INPUT;
3179 if (! STRINGP (font))
3180 font = build_string ("fixed");
3181
3182 x_default_parameter (f, parms, Qfont, font,
3183 "font", "Font", string);
3184 }
3185
3186 #ifdef USE_LUCID
3187 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
3188 whereby it fails to get any font. */
3189 xlwmenu_default_font = f->output_data.x->font;
3190 #endif
3191
3192 x_default_parameter (f, parms, Qborder_width, make_number (2),
3193 "borderwidth", "BorderWidth", number);
3194 /* This defaults to 2 in order to match xterm. We recognize either
3195 internalBorderWidth or internalBorder (which is what xterm calls
3196 it). */
3197 if (NILP (Fassq (Qinternal_border_width, parms)))
3198 {
3199 Lisp_Object value;
3200
3201 value = x_get_arg (parms, Qinternal_border_width,
3202 "internalBorder", "BorderWidth", number);
3203 if (! EQ (value, Qunbound))
3204 parms = Fcons (Fcons (Qinternal_border_width, value),
3205 parms);
3206 }
3207 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
3208 "internalBorderWidth", "BorderWidth", number);
3209 x_default_parameter (f, parms, Qvertical_scroll_bars, Qleft,
3210 "verticalScrollBars", "ScrollBars", boolean);
3211
3212 /* Also do the stuff which must be set before the window exists. */
3213 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
3214 "foreground", "Foreground", string);
3215 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
3216 "background", "Background", string);
3217 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
3218 "pointerColor", "Foreground", string);
3219 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
3220 "cursorColor", "Foreground", string);
3221 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
3222 "borderColor", "BorderColor", string);
3223
3224 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
3225 "menuBar", "MenuBar", number);
3226 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
3227 "scrollBarWidth", "ScrollBarWidth", number);
3228 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
3229 "bufferPredicate", "BufferPredicate", symbol);
3230 x_default_parameter (f, parms, Qtitle, Qnil,
3231 "title", "Title", string);
3232
3233 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
3234 window_prompting = x_figure_window_size (f, parms);
3235
3236 if (window_prompting & XNegative)
3237 {
3238 if (window_prompting & YNegative)
3239 f->output_data.x->win_gravity = SouthEastGravity;
3240 else
3241 f->output_data.x->win_gravity = NorthEastGravity;
3242 }
3243 else
3244 {
3245 if (window_prompting & YNegative)
3246 f->output_data.x->win_gravity = SouthWestGravity;
3247 else
3248 f->output_data.x->win_gravity = NorthWestGravity;
3249 }
3250
3251 f->output_data.x->size_hint_flags = window_prompting;
3252
3253 #ifdef USE_X_TOOLKIT
3254 x_window (f, window_prompting, minibuffer_only);
3255 #else
3256 x_window (f);
3257 #endif
3258 x_icon (f, parms);
3259 x_make_gc (f);
3260 init_frame_faces (f);
3261
3262 /* We need to do this after creating the X window, so that the
3263 icon-creation functions can say whose icon they're describing. */
3264 x_default_parameter (f, parms, Qicon_type, Qnil,
3265 "bitmapIcon", "BitmapIcon", symbol);
3266
3267 x_default_parameter (f, parms, Qauto_raise, Qnil,
3268 "autoRaise", "AutoRaiseLower", boolean);
3269 x_default_parameter (f, parms, Qauto_lower, Qnil,
3270 "autoLower", "AutoRaiseLower", boolean);
3271 x_default_parameter (f, parms, Qcursor_type, Qbox,
3272 "cursorType", "CursorType", symbol);
3273
3274 /* Dimensions, especially f->height, must be done via change_frame_size.
3275 Change will not be effected unless different from the current
3276 f->height. */
3277 width = f->width;
3278 height = f->height;
3279 f->height = 0;
3280 SET_FRAME_WIDTH (f, 0);
3281 change_frame_size (f, height, width, 1, 0);
3282
3283 /* Tell the server what size and position, etc, we want,
3284 and how badly we want them. */
3285 BLOCK_INPUT;
3286 x_wm_set_size_hint (f, window_prompting, 0);
3287 UNBLOCK_INPUT;
3288
3289 tem = x_get_arg (parms, Qunsplittable, 0, 0, boolean);
3290 f->no_split = minibuffer_only || EQ (tem, Qt);
3291
3292 UNGCPRO;
3293
3294 /* It is now ok to make the frame official
3295 even if we get an error below.
3296 And the frame needs to be on Vframe_list
3297 or making it visible won't work. */
3298 Vframe_list = Fcons (frame, Vframe_list);
3299
3300 /* Now that the frame is official, it counts as a reference to
3301 its display. */
3302 FRAME_X_DISPLAY_INFO (f)->reference_count++;
3303
3304 /* Make the window appear on the frame and enable display,
3305 unless the caller says not to. However, with explicit parent,
3306 Emacs cannot control visibility, so don't try. */
3307 if (! f->output_data.x->explicit_parent)
3308 {
3309 Lisp_Object visibility;
3310
3311 visibility = x_get_arg (parms, Qvisibility, 0, 0, symbol);
3312 if (EQ (visibility, Qunbound))
3313 visibility = Qt;
3314
3315 if (EQ (visibility, Qicon))
3316 x_iconify_frame (f);
3317 else if (! NILP (visibility))
3318 x_make_frame_visible (f);
3319 else
3320 /* Must have been Qnil. */
3321 ;
3322 }
3323
3324 return unbind_to (count, frame);
3325 }
3326
3327 /* FRAME is used only to get a handle on the X display. We don't pass the
3328 display info directly because we're called from frame.c, which doesn't
3329 know about that structure. */
3330
3331 Lisp_Object
3332 x_get_focus_frame (frame)
3333 struct frame *frame;
3334 {
3335 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
3336 Lisp_Object xfocus;
3337 if (! dpyinfo->x_focus_frame)
3338 return Qnil;
3339
3340 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
3341 return xfocus;
3342 }
3343 \f
3344 DEFUN ("x-list-fonts", Fx_list_fonts, Sx_list_fonts, 1, 4, 0,
3345 "Return a list of the names of available fonts matching PATTERN.\n\
3346 If optional arguments FACE and FRAME are specified, return only fonts\n\
3347 the same size as FACE on FRAME.\n\
3348 \n\
3349 PATTERN is a string, perhaps with wildcard characters;\n\
3350 the * character matches any substring, and\n\
3351 the ? character matches any single character.\n\
3352 PATTERN is case-insensitive.\n\
3353 FACE is a face name--a symbol.\n\
3354 \n\
3355 The return value is a list of strings, suitable as arguments to\n\
3356 set-face-font.\n\
3357 \n\
3358 Fonts Emacs can't use (i.e. proportional fonts) may or may not be excluded\n\
3359 even if they match PATTERN and FACE.\n\
3360 \n\
3361 The optional fourth argument MAXIMUM sets a limit on how many\n\
3362 fonts to match. The first MAXIMUM fonts are reported.")
3363 (pattern, face, frame, maximum)
3364 Lisp_Object pattern, face, frame, maximum;
3365 {
3366 int num_fonts;
3367 char **names;
3368 #ifndef BROKEN_XLISTFONTSWITHINFO
3369 XFontStruct *info;
3370 #endif
3371 XFontStruct *size_ref;
3372 Lisp_Object list;
3373 FRAME_PTR f;
3374 Lisp_Object key;
3375 int maxnames;
3376
3377 check_x ();
3378 CHECK_STRING (pattern, 0);
3379 if (!NILP (face))
3380 CHECK_SYMBOL (face, 1);
3381
3382 if (NILP (maximum))
3383 maxnames = 2000;
3384 else
3385 {
3386 CHECK_NATNUM (maximum, 0);
3387 maxnames = XINT (maximum);
3388 }
3389
3390 f = check_x_frame (frame);
3391
3392 /* Determine the width standard for comparison with the fonts we find. */
3393
3394 if (NILP (face))
3395 size_ref = 0;
3396 else
3397 {
3398 int face_id;
3399
3400 /* Don't die if we get called with a terminal frame. */
3401 if (! FRAME_X_P (f))
3402 error ("Non-X frame used in `x-list-fonts'");
3403
3404 face_id = face_name_id_number (f, face);
3405
3406 if (face_id < 0 || face_id >= FRAME_N_PARAM_FACES (f)
3407 || FRAME_PARAM_FACES (f) [face_id] == 0)
3408 size_ref = f->output_data.x->font;
3409 else
3410 {
3411 size_ref = FRAME_PARAM_FACES (f) [face_id]->font;
3412 if (size_ref == (XFontStruct *) (~0))
3413 size_ref = f->output_data.x->font;
3414 }
3415 }
3416
3417 /* See if we cached the result for this particular query. */
3418 key = Fcons (pattern, maximum);
3419 list = Fassoc (key,
3420 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr);
3421
3422 /* We have info in the cache for this PATTERN. */
3423 if (!NILP (list))
3424 {
3425 Lisp_Object tem, newlist;
3426
3427 /* We have info about this pattern. */
3428 list = XCONS (list)->cdr;
3429
3430 if (size_ref == 0)
3431 return list;
3432
3433 BLOCK_INPUT;
3434
3435 /* Filter the cached info and return just the fonts that match FACE. */
3436 newlist = Qnil;
3437 for (tem = list; CONSP (tem); tem = XCONS (tem)->cdr)
3438 {
3439 XFontStruct *thisinfo;
3440
3441 x_catch_errors (FRAME_X_DISPLAY (f));
3442
3443 thisinfo = XLoadQueryFont (FRAME_X_DISPLAY (f),
3444 XSTRING (XCONS (tem)->car)->data);
3445
3446 x_check_errors (FRAME_X_DISPLAY (f), "XLoadQueryFont failure: %s");
3447 x_uncatch_errors (FRAME_X_DISPLAY (f));
3448
3449 if (thisinfo && same_size_fonts (thisinfo, size_ref))
3450 newlist = Fcons (XCONS (tem)->car, newlist);
3451
3452 if (thisinfo != 0)
3453 XFreeFont (FRAME_X_DISPLAY (f), thisinfo);
3454 }
3455
3456 UNBLOCK_INPUT;
3457
3458 return newlist;
3459 }
3460
3461 BLOCK_INPUT;
3462
3463 x_catch_errors (FRAME_X_DISPLAY (f));
3464
3465 /* Solaris 2.3 has a bug in XListFontsWithInfo. */
3466 #ifndef BROKEN_XLISTFONTSWITHINFO
3467 if (size_ref)
3468 names = XListFontsWithInfo (FRAME_X_DISPLAY (f),
3469 XSTRING (pattern)->data,
3470 maxnames,
3471 &num_fonts, /* count_return */
3472 &info); /* info_return */
3473 else
3474 #endif
3475 names = XListFonts (FRAME_X_DISPLAY (f),
3476 XSTRING (pattern)->data,
3477 maxnames,
3478 &num_fonts); /* count_return */
3479
3480 x_check_errors (FRAME_X_DISPLAY (f), "XListFonts failure: %s");
3481 x_uncatch_errors (FRAME_X_DISPLAY (f));
3482
3483 UNBLOCK_INPUT;
3484
3485 list = Qnil;
3486
3487 if (names)
3488 {
3489 int i;
3490 Lisp_Object full_list;
3491
3492 /* Make a list of all the fonts we got back.
3493 Store that in the font cache for the display. */
3494 full_list = Qnil;
3495 for (i = 0; i < num_fonts; i++)
3496 full_list = Fcons (build_string (names[i]), full_list);
3497 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr
3498 = Fcons (Fcons (key, full_list),
3499 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr);
3500
3501 /* Make a list of the fonts that have the right width. */
3502 list = Qnil;
3503 for (i = 0; i < num_fonts; i++)
3504 {
3505 int keeper;
3506
3507 if (!size_ref)
3508 keeper = 1;
3509 else
3510 {
3511 #ifdef BROKEN_XLISTFONTSWITHINFO
3512 XFontStruct *thisinfo;
3513
3514 BLOCK_INPUT;
3515
3516 x_catch_errors (FRAME_X_DISPLAY (f));
3517 thisinfo = XLoadQueryFont (FRAME_X_DISPLAY (f), names[i]);
3518 x_check_errors (FRAME_X_DISPLAY (f),
3519 "XLoadQueryFont failure: %s");
3520 x_uncatch_errors (FRAME_X_DISPLAY (f));
3521
3522 UNBLOCK_INPUT;
3523
3524 keeper = thisinfo && same_size_fonts (thisinfo, size_ref);
3525 BLOCK_INPUT;
3526 if (thisinfo && ! keeper)
3527 XFreeFont (FRAME_X_DISPLAY (f), thisinfo);
3528 else if (thisinfo)
3529 XFreeFontInfo (NULL, thisinfo, 1);
3530 UNBLOCK_INPUT;
3531 #else
3532 keeper = same_size_fonts (&info[i], size_ref);
3533 #endif
3534 }
3535 if (keeper)
3536 list = Fcons (build_string (names[i]), list);
3537 }
3538 list = Fnreverse (list);
3539
3540 BLOCK_INPUT;
3541 #ifndef BROKEN_XLISTFONTSWITHINFO
3542 if (size_ref)
3543 XFreeFontInfo (names, info, num_fonts);
3544 else
3545 #endif
3546 XFreeFontNames (names);
3547 UNBLOCK_INPUT;
3548 }
3549
3550 return list;
3551 }
3552
3553 \f
3554 DEFUN ("x-color-defined-p", Fx_color_defined_p, Sx_color_defined_p, 1, 2, 0,
3555 "Return non-nil if color COLOR is supported on frame FRAME.\n\
3556 If FRAME is omitted or nil, use the selected frame.")
3557 (color, frame)
3558 Lisp_Object color, frame;
3559 {
3560 XColor foo;
3561 FRAME_PTR f = check_x_frame (frame);
3562
3563 CHECK_STRING (color, 1);
3564
3565 if (defined_color (f, XSTRING (color)->data, &foo, 0))
3566 return Qt;
3567 else
3568 return Qnil;
3569 }
3570
3571 DEFUN ("x-color-values", Fx_color_values, Sx_color_values, 1, 2, 0,
3572 "Return a description of the color named COLOR on frame FRAME.\n\
3573 The value is a list of integer RGB values--(RED GREEN BLUE).\n\
3574 These values appear to range from 0 to 65280 or 65535, depending\n\
3575 on the system; white is (65280 65280 65280) or (65535 65535 65535).\n\
3576 If FRAME is omitted or nil, use the selected frame.")
3577 (color, frame)
3578 Lisp_Object color, frame;
3579 {
3580 XColor foo;
3581 FRAME_PTR f = check_x_frame (frame);
3582
3583 CHECK_STRING (color, 1);
3584
3585 if (defined_color (f, XSTRING (color)->data, &foo, 0))
3586 {
3587 Lisp_Object rgb[3];
3588
3589 rgb[0] = make_number (foo.red);
3590 rgb[1] = make_number (foo.green);
3591 rgb[2] = make_number (foo.blue);
3592 return Flist (3, rgb);
3593 }
3594 else
3595 return Qnil;
3596 }
3597
3598 DEFUN ("x-display-color-p", Fx_display_color_p, Sx_display_color_p, 0, 1, 0,
3599 "Return t if the X display supports color.\n\
3600 The optional argument DISPLAY specifies which display to ask about.\n\
3601 DISPLAY should be either a frame or a display name (a string).\n\
3602 If omitted or nil, that stands for the selected frame's display.")
3603 (display)
3604 Lisp_Object display;
3605 {
3606 struct x_display_info *dpyinfo = check_x_display_info (display);
3607
3608 if (dpyinfo->n_planes <= 2)
3609 return Qnil;
3610
3611 switch (dpyinfo->visual->class)
3612 {
3613 case StaticColor:
3614 case PseudoColor:
3615 case TrueColor:
3616 case DirectColor:
3617 return Qt;
3618
3619 default:
3620 return Qnil;
3621 }
3622 }
3623
3624 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
3625 0, 1, 0,
3626 "Return t if the X display supports shades of gray.\n\
3627 Note that color displays do support shades of gray.\n\
3628 The optional argument DISPLAY specifies which display to ask about.\n\
3629 DISPLAY should be either a frame or a display name (a string).\n\
3630 If omitted or nil, that stands for the selected frame's display.")
3631 (display)
3632 Lisp_Object display;
3633 {
3634 struct x_display_info *dpyinfo = check_x_display_info (display);
3635
3636 if (dpyinfo->n_planes <= 1)
3637 return Qnil;
3638
3639 switch (dpyinfo->visual->class)
3640 {
3641 case StaticColor:
3642 case PseudoColor:
3643 case TrueColor:
3644 case DirectColor:
3645 case StaticGray:
3646 case GrayScale:
3647 return Qt;
3648
3649 default:
3650 return Qnil;
3651 }
3652 }
3653
3654 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
3655 0, 1, 0,
3656 "Returns the width in pixels of the X display DISPLAY.\n\
3657 The optional argument DISPLAY specifies which display to ask about.\n\
3658 DISPLAY should be either a frame or a display name (a string).\n\
3659 If omitted or nil, that stands for the selected frame's display.")
3660 (display)
3661 Lisp_Object display;
3662 {
3663 struct x_display_info *dpyinfo = check_x_display_info (display);
3664
3665 return make_number (dpyinfo->width);
3666 }
3667
3668 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
3669 Sx_display_pixel_height, 0, 1, 0,
3670 "Returns the height in pixels of the X display DISPLAY.\n\
3671 The optional argument DISPLAY specifies which display to ask about.\n\
3672 DISPLAY should be either a frame or a display name (a string).\n\
3673 If omitted or nil, that stands for the selected frame's display.")
3674 (display)
3675 Lisp_Object display;
3676 {
3677 struct x_display_info *dpyinfo = check_x_display_info (display);
3678
3679 return make_number (dpyinfo->height);
3680 }
3681
3682 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
3683 0, 1, 0,
3684 "Returns the number of bitplanes of the X display DISPLAY.\n\
3685 The optional argument DISPLAY specifies which display to ask about.\n\
3686 DISPLAY should be either a frame or a display name (a string).\n\
3687 If omitted or nil, that stands for the selected frame's display.")
3688 (display)
3689 Lisp_Object display;
3690 {
3691 struct x_display_info *dpyinfo = check_x_display_info (display);
3692
3693 return make_number (dpyinfo->n_planes);
3694 }
3695
3696 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
3697 0, 1, 0,
3698 "Returns the number of color cells of the X display DISPLAY.\n\
3699 The optional argument DISPLAY specifies which display to ask about.\n\
3700 DISPLAY should be either a frame or a display name (a string).\n\
3701 If omitted or nil, that stands for the selected frame's display.")
3702 (display)
3703 Lisp_Object display;
3704 {
3705 struct x_display_info *dpyinfo = check_x_display_info (display);
3706
3707 return make_number (DisplayCells (dpyinfo->display,
3708 XScreenNumberOfScreen (dpyinfo->screen)));
3709 }
3710
3711 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
3712 Sx_server_max_request_size,
3713 0, 1, 0,
3714 "Returns the maximum request size of the X server of display DISPLAY.\n\
3715 The optional argument DISPLAY specifies which display to ask about.\n\
3716 DISPLAY should be either a frame or a display name (a string).\n\
3717 If omitted or nil, that stands for the selected frame's display.")
3718 (display)
3719 Lisp_Object display;
3720 {
3721 struct x_display_info *dpyinfo = check_x_display_info (display);
3722
3723 return make_number (MAXREQUEST (dpyinfo->display));
3724 }
3725
3726 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
3727 "Returns the vendor ID string of the X server of display DISPLAY.\n\
3728 The optional argument DISPLAY specifies which display to ask about.\n\
3729 DISPLAY should be either a frame or a display name (a string).\n\
3730 If omitted or nil, that stands for the selected frame's display.")
3731 (display)
3732 Lisp_Object display;
3733 {
3734 struct x_display_info *dpyinfo = check_x_display_info (display);
3735 char *vendor = ServerVendor (dpyinfo->display);
3736
3737 if (! vendor) vendor = "";
3738 return build_string (vendor);
3739 }
3740
3741 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
3742 "Returns the version numbers of the X server of display DISPLAY.\n\
3743 The value is a list of three integers: the major and minor\n\
3744 version numbers of the X Protocol in use, and the vendor-specific release\n\
3745 number. See also the function `x-server-vendor'.\n\n\
3746 The optional argument DISPLAY specifies which display to ask about.\n\
3747 DISPLAY should be either a frame or a display name (a string).\n\
3748 If omitted or nil, that stands for the selected frame's display.")
3749 (display)
3750 Lisp_Object display;
3751 {
3752 struct x_display_info *dpyinfo = check_x_display_info (display);
3753 Display *dpy = dpyinfo->display;
3754
3755 return Fcons (make_number (ProtocolVersion (dpy)),
3756 Fcons (make_number (ProtocolRevision (dpy)),
3757 Fcons (make_number (VendorRelease (dpy)), Qnil)));
3758 }
3759
3760 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
3761 "Returns the number of screens on the X server of display DISPLAY.\n\
3762 The optional argument DISPLAY specifies which display to ask about.\n\
3763 DISPLAY should be either a frame or a display name (a string).\n\
3764 If omitted or nil, that stands for the selected frame's display.")
3765 (display)
3766 Lisp_Object display;
3767 {
3768 struct x_display_info *dpyinfo = check_x_display_info (display);
3769
3770 return make_number (ScreenCount (dpyinfo->display));
3771 }
3772
3773 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
3774 "Returns the height in millimeters of the X display DISPLAY.\n\
3775 The optional argument DISPLAY specifies which display to ask about.\n\
3776 DISPLAY should be either a frame or a display name (a string).\n\
3777 If omitted or nil, that stands for the selected frame's display.")
3778 (display)
3779 Lisp_Object display;
3780 {
3781 struct x_display_info *dpyinfo = check_x_display_info (display);
3782
3783 return make_number (HeightMMOfScreen (dpyinfo->screen));
3784 }
3785
3786 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
3787 "Returns the width in millimeters of the X display DISPLAY.\n\
3788 The optional argument DISPLAY specifies which display to ask about.\n\
3789 DISPLAY should be either a frame or a display name (a string).\n\
3790 If omitted or nil, that stands for the selected frame's display.")
3791 (display)
3792 Lisp_Object display;
3793 {
3794 struct x_display_info *dpyinfo = check_x_display_info (display);
3795
3796 return make_number (WidthMMOfScreen (dpyinfo->screen));
3797 }
3798
3799 DEFUN ("x-display-backing-store", Fx_display_backing_store,
3800 Sx_display_backing_store, 0, 1, 0,
3801 "Returns an indication of whether X display DISPLAY does backing store.\n\
3802 The value may be `always', `when-mapped', or `not-useful'.\n\
3803 The optional argument DISPLAY specifies which display to ask about.\n\
3804 DISPLAY should be either a frame or a display name (a string).\n\
3805 If omitted or nil, that stands for the selected frame's display.")
3806 (display)
3807 Lisp_Object display;
3808 {
3809 struct x_display_info *dpyinfo = check_x_display_info (display);
3810
3811 switch (DoesBackingStore (dpyinfo->screen))
3812 {
3813 case Always:
3814 return intern ("always");
3815
3816 case WhenMapped:
3817 return intern ("when-mapped");
3818
3819 case NotUseful:
3820 return intern ("not-useful");
3821
3822 default:
3823 error ("Strange value for BackingStore parameter of screen");
3824 }
3825 }
3826
3827 DEFUN ("x-display-visual-class", Fx_display_visual_class,
3828 Sx_display_visual_class, 0, 1, 0,
3829 "Returns the visual class of the X display DISPLAY.\n\
3830 The value is one of the symbols `static-gray', `gray-scale',\n\
3831 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
3832 The optional argument DISPLAY specifies which display to ask about.\n\
3833 DISPLAY should be either a frame or a display name (a string).\n\
3834 If omitted or nil, that stands for the selected frame's display.")
3835 (display)
3836 Lisp_Object display;
3837 {
3838 struct x_display_info *dpyinfo = check_x_display_info (display);
3839
3840 switch (dpyinfo->visual->class)
3841 {
3842 case StaticGray: return (intern ("static-gray"));
3843 case GrayScale: return (intern ("gray-scale"));
3844 case StaticColor: return (intern ("static-color"));
3845 case PseudoColor: return (intern ("pseudo-color"));
3846 case TrueColor: return (intern ("true-color"));
3847 case DirectColor: return (intern ("direct-color"));
3848 default:
3849 error ("Display has an unknown visual class");
3850 }
3851 }
3852
3853 DEFUN ("x-display-save-under", Fx_display_save_under,
3854 Sx_display_save_under, 0, 1, 0,
3855 "Returns t if the X display DISPLAY supports the save-under feature.\n\
3856 The optional argument DISPLAY specifies which display to ask about.\n\
3857 DISPLAY should be either a frame or a display name (a string).\n\
3858 If omitted or nil, that stands for the selected frame's display.")
3859 (display)
3860 Lisp_Object display;
3861 {
3862 struct x_display_info *dpyinfo = check_x_display_info (display);
3863
3864 if (DoesSaveUnders (dpyinfo->screen) == True)
3865 return Qt;
3866 else
3867 return Qnil;
3868 }
3869 \f
3870 int
3871 x_pixel_width (f)
3872 register struct frame *f;
3873 {
3874 return PIXEL_WIDTH (f);
3875 }
3876
3877 int
3878 x_pixel_height (f)
3879 register struct frame *f;
3880 {
3881 return PIXEL_HEIGHT (f);
3882 }
3883
3884 int
3885 x_char_width (f)
3886 register struct frame *f;
3887 {
3888 return FONT_WIDTH (f->output_data.x->font);
3889 }
3890
3891 int
3892 x_char_height (f)
3893 register struct frame *f;
3894 {
3895 return f->output_data.x->line_height;
3896 }
3897
3898 int
3899 x_screen_planes (frame)
3900 Lisp_Object frame;
3901 {
3902 return FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_planes;
3903 }
3904 \f
3905 #if 0 /* These no longer seem like the right way to do things. */
3906
3907 /* Draw a rectangle on the frame with left top corner including
3908 the character specified by LEFT_CHAR and TOP_CHAR. The rectangle is
3909 CHARS by LINES wide and long and is the color of the cursor. */
3910
3911 void
3912 x_rectangle (f, gc, left_char, top_char, chars, lines)
3913 register struct frame *f;
3914 GC gc;
3915 register int top_char, left_char, chars, lines;
3916 {
3917 int width;
3918 int height;
3919 int left = (left_char * FONT_WIDTH (f->output_data.x->font)
3920 + f->output_data.x->internal_border_width);
3921 int top = (top_char * f->output_data.x->line_height
3922 + f->output_data.x->internal_border_width);
3923
3924 if (chars < 0)
3925 width = FONT_WIDTH (f->output_data.x->font) / 2;
3926 else
3927 width = FONT_WIDTH (f->output_data.x->font) * chars;
3928 if (lines < 0)
3929 height = f->output_data.x->line_height / 2;
3930 else
3931 height = f->output_data.x->line_height * lines;
3932
3933 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3934 gc, left, top, width, height);
3935 }
3936
3937 DEFUN ("x-draw-rectangle", Fx_draw_rectangle, Sx_draw_rectangle, 5, 5, 0,
3938 "Draw a rectangle on FRAME between coordinates specified by\n\
3939 numbers X0, Y0, X1, Y1 in the cursor pixel.")
3940 (frame, X0, Y0, X1, Y1)
3941 register Lisp_Object frame, X0, X1, Y0, Y1;
3942 {
3943 register int x0, y0, x1, y1, top, left, n_chars, n_lines;
3944
3945 CHECK_LIVE_FRAME (frame, 0);
3946 CHECK_NUMBER (X0, 0);
3947 CHECK_NUMBER (Y0, 1);
3948 CHECK_NUMBER (X1, 2);
3949 CHECK_NUMBER (Y1, 3);
3950
3951 x0 = XINT (X0);
3952 x1 = XINT (X1);
3953 y0 = XINT (Y0);
3954 y1 = XINT (Y1);
3955
3956 if (y1 > y0)
3957 {
3958 top = y0;
3959 n_lines = y1 - y0 + 1;
3960 }
3961 else
3962 {
3963 top = y1;
3964 n_lines = y0 - y1 + 1;
3965 }
3966
3967 if (x1 > x0)
3968 {
3969 left = x0;
3970 n_chars = x1 - x0 + 1;
3971 }
3972 else
3973 {
3974 left = x1;
3975 n_chars = x0 - x1 + 1;
3976 }
3977
3978 BLOCK_INPUT;
3979 x_rectangle (XFRAME (frame), XFRAME (frame)->output_data.x->cursor_gc,
3980 left, top, n_chars, n_lines);
3981 UNBLOCK_INPUT;
3982
3983 return Qt;
3984 }
3985
3986 DEFUN ("x-erase-rectangle", Fx_erase_rectangle, Sx_erase_rectangle, 5, 5, 0,
3987 "Draw a rectangle drawn on FRAME between coordinates\n\
3988 X0, Y0, X1, Y1 in the regular background-pixel.")
3989 (frame, X0, Y0, X1, Y1)
3990 register Lisp_Object frame, X0, Y0, X1, Y1;
3991 {
3992 register int x0, y0, x1, y1, top, left, n_chars, n_lines;
3993
3994 CHECK_LIVE_FRAME (frame, 0);
3995 CHECK_NUMBER (X0, 0);
3996 CHECK_NUMBER (Y0, 1);
3997 CHECK_NUMBER (X1, 2);
3998 CHECK_NUMBER (Y1, 3);
3999
4000 x0 = XINT (X0);
4001 x1 = XINT (X1);
4002 y0 = XINT (Y0);
4003 y1 = XINT (Y1);
4004
4005 if (y1 > y0)
4006 {
4007 top = y0;
4008 n_lines = y1 - y0 + 1;
4009 }
4010 else
4011 {
4012 top = y1;
4013 n_lines = y0 - y1 + 1;
4014 }
4015
4016 if (x1 > x0)
4017 {
4018 left = x0;
4019 n_chars = x1 - x0 + 1;
4020 }
4021 else
4022 {
4023 left = x1;
4024 n_chars = x0 - x1 + 1;
4025 }
4026
4027 BLOCK_INPUT;
4028 x_rectangle (XFRAME (frame), XFRAME (frame)->output_data.x->reverse_gc,
4029 left, top, n_chars, n_lines);
4030 UNBLOCK_INPUT;
4031
4032 return Qt;
4033 }
4034
4035 /* Draw lines around the text region beginning at the character position
4036 TOP_X, TOP_Y and ending at BOTTOM_X and BOTTOM_Y. GC specifies the
4037 pixel and line characteristics. */
4038
4039 #define line_len(line) (FRAME_CURRENT_GLYPHS (f)->used[(line)])
4040
4041 static void
4042 outline_region (f, gc, top_x, top_y, bottom_x, bottom_y)
4043 register struct frame *f;
4044 GC gc;
4045 int top_x, top_y, bottom_x, bottom_y;
4046 {
4047 register int ibw = f->output_data.x->internal_border_width;
4048 register int font_w = FONT_WIDTH (f->output_data.x->font);
4049 register int font_h = f->output_data.x->line_height;
4050 int y = top_y;
4051 int x = line_len (y);
4052 XPoint *pixel_points
4053 = (XPoint *) alloca (((bottom_y - top_y + 2) * 4) * sizeof (XPoint));
4054 register XPoint *this_point = pixel_points;
4055
4056 /* Do the horizontal top line/lines */
4057 if (top_x == 0)
4058 {
4059 this_point->x = ibw;
4060 this_point->y = ibw + (font_h * top_y);
4061 this_point++;
4062 if (x == 0)
4063 this_point->x = ibw + (font_w / 2); /* Half-size for newline chars. */
4064 else
4065 this_point->x = ibw + (font_w * x);
4066 this_point->y = (this_point - 1)->y;
4067 }
4068 else
4069 {
4070 this_point->x = ibw;
4071 this_point->y = ibw + (font_h * (top_y + 1));
4072 this_point++;
4073 this_point->x = ibw + (font_w * top_x);
4074 this_point->y = (this_point - 1)->y;
4075 this_point++;
4076 this_point->x = (this_point - 1)->x;
4077 this_point->y = ibw + (font_h * top_y);
4078 this_point++;
4079 this_point->x = ibw + (font_w * x);
4080 this_point->y = (this_point - 1)->y;
4081 }
4082
4083 /* Now do the right side. */
4084 while (y < bottom_y)
4085 { /* Right vertical edge */
4086 this_point++;
4087 this_point->x = (this_point - 1)->x;
4088 this_point->y = ibw + (font_h * (y + 1));
4089 this_point++;
4090
4091 y++; /* Horizontal connection to next line */
4092 x = line_len (y);
4093 if (x == 0)
4094 this_point->x = ibw + (font_w / 2);
4095 else
4096 this_point->x = ibw + (font_w * x);
4097
4098 this_point->y = (this_point - 1)->y;
4099 }
4100
4101 /* Now do the bottom and connect to the top left point. */
4102 this_point->x = ibw + (font_w * (bottom_x + 1));
4103
4104 this_point++;
4105 this_point->x = (this_point - 1)->x;
4106 this_point->y = ibw + (font_h * (bottom_y + 1));
4107 this_point++;
4108 this_point->x = ibw;
4109 this_point->y = (this_point - 1)->y;
4110 this_point++;
4111 this_point->x = pixel_points->x;
4112 this_point->y = pixel_points->y;
4113
4114 XDrawLines (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4115 gc, pixel_points,
4116 (this_point - pixel_points + 1), CoordModeOrigin);
4117 }
4118
4119 DEFUN ("x-contour-region", Fx_contour_region, Sx_contour_region, 1, 1, 0,
4120 "Highlight the region between point and the character under the mouse\n\
4121 selected frame.")
4122 (event)
4123 register Lisp_Object event;
4124 {
4125 register int x0, y0, x1, y1;
4126 register struct frame *f = selected_frame;
4127 register int p1, p2;
4128
4129 CHECK_CONS (event, 0);
4130
4131 BLOCK_INPUT;
4132 x0 = XINT (Fcar (Fcar (event)));
4133 y0 = XINT (Fcar (Fcdr (Fcar (event))));
4134
4135 /* If the mouse is past the end of the line, don't that area. */
4136 /* ReWrite this... */
4137
4138 x1 = f->cursor_x;
4139 y1 = f->cursor_y;
4140
4141 if (y1 > y0) /* point below mouse */
4142 outline_region (f, f->output_data.x->cursor_gc,
4143 x0, y0, x1, y1);
4144 else if (y1 < y0) /* point above mouse */
4145 outline_region (f, f->output_data.x->cursor_gc,
4146 x1, y1, x0, y0);
4147 else /* same line: draw horizontal rectangle */
4148 {
4149 if (x1 > x0)
4150 x_rectangle (f, f->output_data.x->cursor_gc,
4151 x0, y0, (x1 - x0 + 1), 1);
4152 else if (x1 < x0)
4153 x_rectangle (f, f->output_data.x->cursor_gc,
4154 x1, y1, (x0 - x1 + 1), 1);
4155 }
4156
4157 XFlush (FRAME_X_DISPLAY (f));
4158 UNBLOCK_INPUT;
4159
4160 return Qnil;
4161 }
4162
4163 DEFUN ("x-uncontour-region", Fx_uncontour_region, Sx_uncontour_region, 1, 1, 0,
4164 "Erase any highlighting of the region between point and the character\n\
4165 at X, Y on the selected frame.")
4166 (event)
4167 register Lisp_Object event;
4168 {
4169 register int x0, y0, x1, y1;
4170 register struct frame *f = selected_frame;
4171
4172 BLOCK_INPUT;
4173 x0 = XINT (Fcar (Fcar (event)));
4174 y0 = XINT (Fcar (Fcdr (Fcar (event))));
4175 x1 = f->cursor_x;
4176 y1 = f->cursor_y;
4177
4178 if (y1 > y0) /* point below mouse */
4179 outline_region (f, f->output_data.x->reverse_gc,
4180 x0, y0, x1, y1);
4181 else if (y1 < y0) /* point above mouse */
4182 outline_region (f, f->output_data.x->reverse_gc,
4183 x1, y1, x0, y0);
4184 else /* same line: draw horizontal rectangle */
4185 {
4186 if (x1 > x0)
4187 x_rectangle (f, f->output_data.x->reverse_gc,
4188 x0, y0, (x1 - x0 + 1), 1);
4189 else if (x1 < x0)
4190 x_rectangle (f, f->output_data.x->reverse_gc,
4191 x1, y1, (x0 - x1 + 1), 1);
4192 }
4193 UNBLOCK_INPUT;
4194
4195 return Qnil;
4196 }
4197
4198 #if 0
4199 int contour_begin_x, contour_begin_y;
4200 int contour_end_x, contour_end_y;
4201 int contour_npoints;
4202
4203 /* Clip the top part of the contour lines down (and including) line Y_POS.
4204 If X_POS is in the middle (rather than at the end) of the line, drop
4205 down a line at that character. */
4206
4207 static void
4208 clip_contour_top (y_pos, x_pos)
4209 {
4210 register XPoint *begin = contour_lines[y_pos].top_left;
4211 register XPoint *end;
4212 register int npoints;
4213 register struct display_line *line = selected_frame->phys_lines[y_pos + 1];
4214
4215 if (x_pos >= line->len - 1) /* Draw one, straight horizontal line. */
4216 {
4217 end = contour_lines[y_pos].top_right;
4218 npoints = (end - begin + 1);
4219 XDrawLines (x_current_display, contour_window,
4220 contour_erase_gc, begin_erase, npoints, CoordModeOrigin);
4221
4222 bcopy (end, begin + 1, contour_last_point - end + 1);
4223 contour_last_point -= (npoints - 2);
4224 XDrawLines (x_current_display, contour_window,
4225 contour_erase_gc, begin, 2, CoordModeOrigin);
4226 XFlush (x_current_display);
4227
4228 /* Now, update contour_lines structure. */
4229 }
4230 /* ______. */
4231 else /* |________*/
4232 {
4233 register XPoint *p = begin + 1;
4234 end = contour_lines[y_pos].bottom_right;
4235 npoints = (end - begin + 1);
4236 XDrawLines (x_current_display, contour_window,
4237 contour_erase_gc, begin_erase, npoints, CoordModeOrigin);
4238
4239 p->y = begin->y;
4240 p->x = ibw + (font_w * (x_pos + 1));
4241 p++;
4242 p->y = begin->y + font_h;
4243 p->x = (p - 1)->x;
4244 bcopy (end, begin + 3, contour_last_point - end + 1);
4245 contour_last_point -= (npoints - 5);
4246 XDrawLines (x_current_display, contour_window,
4247 contour_erase_gc, begin, 4, CoordModeOrigin);
4248 XFlush (x_current_display);
4249
4250 /* Now, update contour_lines structure. */
4251 }
4252 }
4253
4254 /* Erase the top horizontal lines of the contour, and then extend
4255 the contour upwards. */
4256
4257 static void
4258 extend_contour_top (line)
4259 {
4260 }
4261
4262 static void
4263 clip_contour_bottom (x_pos, y_pos)
4264 int x_pos, y_pos;
4265 {
4266 }
4267
4268 static void
4269 extend_contour_bottom (x_pos, y_pos)
4270 {
4271 }
4272
4273 DEFUN ("x-select-region", Fx_select_region, Sx_select_region, 1, 1, "e",
4274 "")
4275 (event)
4276 Lisp_Object event;
4277 {
4278 register struct frame *f = selected_frame;
4279 register int point_x = f->cursor_x;
4280 register int point_y = f->cursor_y;
4281 register int mouse_below_point;
4282 register Lisp_Object obj;
4283 register int x_contour_x, x_contour_y;
4284
4285 x_contour_x = x_mouse_x;
4286 x_contour_y = x_mouse_y;
4287 if (x_contour_y > point_y || (x_contour_y == point_y
4288 && x_contour_x > point_x))
4289 {
4290 mouse_below_point = 1;
4291 outline_region (f, f->output_data.x->cursor_gc, point_x, point_y,
4292 x_contour_x, x_contour_y);
4293 }
4294 else
4295 {
4296 mouse_below_point = 0;
4297 outline_region (f, f->output_data.x->cursor_gc, x_contour_x, x_contour_y,
4298 point_x, point_y);
4299 }
4300
4301 while (1)
4302 {
4303 obj = read_char (-1, 0, 0, Qnil, 0);
4304 if (!CONSP (obj))
4305 break;
4306
4307 if (mouse_below_point)
4308 {
4309 if (x_mouse_y <= point_y) /* Flipped. */
4310 {
4311 mouse_below_point = 0;
4312
4313 outline_region (f, f->output_data.x->reverse_gc, point_x, point_y,
4314 x_contour_x, x_contour_y);
4315 outline_region (f, f->output_data.x->cursor_gc, x_mouse_x, x_mouse_y,
4316 point_x, point_y);
4317 }
4318 else if (x_mouse_y < x_contour_y) /* Bottom clipped. */
4319 {
4320 clip_contour_bottom (x_mouse_y);
4321 }
4322 else if (x_mouse_y > x_contour_y) /* Bottom extended. */
4323 {
4324 extend_bottom_contour (x_mouse_y);
4325 }
4326
4327 x_contour_x = x_mouse_x;
4328 x_contour_y = x_mouse_y;
4329 }
4330 else /* mouse above or same line as point */
4331 {
4332 if (x_mouse_y >= point_y) /* Flipped. */
4333 {
4334 mouse_below_point = 1;
4335
4336 outline_region (f, f->output_data.x->reverse_gc,
4337 x_contour_x, x_contour_y, point_x, point_y);
4338 outline_region (f, f->output_data.x->cursor_gc, point_x, point_y,
4339 x_mouse_x, x_mouse_y);
4340 }
4341 else if (x_mouse_y > x_contour_y) /* Top clipped. */
4342 {
4343 clip_contour_top (x_mouse_y);
4344 }
4345 else if (x_mouse_y < x_contour_y) /* Top extended. */
4346 {
4347 extend_contour_top (x_mouse_y);
4348 }
4349 }
4350 }
4351
4352 unread_command_event = obj;
4353 if (mouse_below_point)
4354 {
4355 contour_begin_x = point_x;
4356 contour_begin_y = point_y;
4357 contour_end_x = x_contour_x;
4358 contour_end_y = x_contour_y;
4359 }
4360 else
4361 {
4362 contour_begin_x = x_contour_x;
4363 contour_begin_y = x_contour_y;
4364 contour_end_x = point_x;
4365 contour_end_y = point_y;
4366 }
4367 }
4368 #endif
4369
4370 DEFUN ("x-horizontal-line", Fx_horizontal_line, Sx_horizontal_line, 1, 1, "e",
4371 "")
4372 (event)
4373 Lisp_Object event;
4374 {
4375 register Lisp_Object obj;
4376 struct frame *f = selected_frame;
4377 register struct window *w = XWINDOW (selected_window);
4378 register GC line_gc = f->output_data.x->cursor_gc;
4379 register GC erase_gc = f->output_data.x->reverse_gc;
4380 #if 0
4381 char dash_list[] = {6, 4, 6, 4};
4382 int dashes = 4;
4383 XGCValues gc_values;
4384 #endif
4385 register int previous_y;
4386 register int line = (x_mouse_y + 1) * f->output_data.x->line_height
4387 + f->output_data.x->internal_border_width;
4388 register int left = f->output_data.x->internal_border_width
4389 + (WINDOW_LEFT_MARGIN (w)
4390 * FONT_WIDTH (f->output_data.x->font));
4391 register int right = left + (w->width
4392 * FONT_WIDTH (f->output_data.x->font))
4393 - f->output_data.x->internal_border_width;
4394
4395 #if 0
4396 BLOCK_INPUT;
4397 gc_values.foreground = f->output_data.x->cursor_pixel;
4398 gc_values.background = f->output_data.x->background_pixel;
4399 gc_values.line_width = 1;
4400 gc_values.line_style = LineOnOffDash;
4401 gc_values.cap_style = CapRound;
4402 gc_values.join_style = JoinRound;
4403
4404 line_gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4405 GCLineStyle | GCJoinStyle | GCCapStyle
4406 | GCLineWidth | GCForeground | GCBackground,
4407 &gc_values);
4408 XSetDashes (FRAME_X_DISPLAY (f), line_gc, 0, dash_list, dashes);
4409 gc_values.foreground = f->output_data.x->background_pixel;
4410 gc_values.background = f->output_data.x->foreground_pixel;
4411 erase_gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4412 GCLineStyle | GCJoinStyle | GCCapStyle
4413 | GCLineWidth | GCForeground | GCBackground,
4414 &gc_values);
4415 XSetDashes (FRAME_X_DISPLAY (f), erase_gc, 0, dash_list, dashes);
4416 UNBLOCK_INPUT;
4417 #endif
4418
4419 while (1)
4420 {
4421 BLOCK_INPUT;
4422 if (x_mouse_y >= XINT (w->top)
4423 && x_mouse_y < XINT (w->top) + XINT (w->height) - 1)
4424 {
4425 previous_y = x_mouse_y;
4426 line = (x_mouse_y + 1) * f->output_data.x->line_height
4427 + f->output_data.x->internal_border_width;
4428 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4429 line_gc, left, line, right, line);
4430 }
4431 XFlush (FRAME_X_DISPLAY (f));
4432 UNBLOCK_INPUT;
4433
4434 do
4435 {
4436 obj = read_char (-1, 0, 0, Qnil, 0);
4437 if (!CONSP (obj)
4438 || (! EQ (Fcar (Fcdr (Fcdr (obj))),
4439 Qvertical_scroll_bar))
4440 || x_mouse_grabbed)
4441 {
4442 BLOCK_INPUT;
4443 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4444 erase_gc, left, line, right, line);
4445 unread_command_event = obj;
4446 #if 0
4447 XFreeGC (FRAME_X_DISPLAY (f), line_gc);
4448 XFreeGC (FRAME_X_DISPLAY (f), erase_gc);
4449 #endif
4450 UNBLOCK_INPUT;
4451 return Qnil;
4452 }
4453 }
4454 while (x_mouse_y == previous_y);
4455
4456 BLOCK_INPUT;
4457 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4458 erase_gc, left, line, right, line);
4459 UNBLOCK_INPUT;
4460 }
4461 }
4462 #endif
4463 \f
4464 #if 0
4465 /* These keep track of the rectangle following the pointer. */
4466 int mouse_track_top, mouse_track_left, mouse_track_width;
4467
4468 /* Offset in buffer of character under the pointer, or 0. */
4469 int mouse_buffer_offset;
4470
4471 DEFUN ("x-track-pointer", Fx_track_pointer, Sx_track_pointer, 0, 0, 0,
4472 "Track the pointer.")
4473 ()
4474 {
4475 static Cursor current_pointer_shape;
4476 FRAME_PTR f = x_mouse_frame;
4477
4478 BLOCK_INPUT;
4479 if (EQ (Vmouse_frame_part, Qtext_part)
4480 && (current_pointer_shape != f->output_data.x->nontext_cursor))
4481 {
4482 unsigned char c;
4483 struct buffer *buf;
4484
4485 current_pointer_shape = f->output_data.x->nontext_cursor;
4486 XDefineCursor (FRAME_X_DISPLAY (f),
4487 FRAME_X_WINDOW (f),
4488 current_pointer_shape);
4489
4490 buf = XBUFFER (XWINDOW (Vmouse_window)->buffer);
4491 c = *(BUF_CHAR_ADDRESS (buf, mouse_buffer_offset));
4492 }
4493 else if (EQ (Vmouse_frame_part, Qmodeline_part)
4494 && (current_pointer_shape != f->output_data.x->modeline_cursor))
4495 {
4496 current_pointer_shape = f->output_data.x->modeline_cursor;
4497 XDefineCursor (FRAME_X_DISPLAY (f),
4498 FRAME_X_WINDOW (f),
4499 current_pointer_shape);
4500 }
4501
4502 XFlush (FRAME_X_DISPLAY (f));
4503 UNBLOCK_INPUT;
4504 }
4505 #endif
4506
4507 #if 0
4508 DEFUN ("x-track-pointer", Fx_track_pointer, Sx_track_pointer, 1, 1, "e",
4509 "Draw rectangle around character under mouse pointer, if there is one.")
4510 (event)
4511 Lisp_Object event;
4512 {
4513 struct window *w = XWINDOW (Vmouse_window);
4514 struct frame *f = XFRAME (WINDOW_FRAME (w));
4515 struct buffer *b = XBUFFER (w->buffer);
4516 Lisp_Object obj;
4517
4518 if (! EQ (Vmouse_window, selected_window))
4519 return Qnil;
4520
4521 if (EQ (event, Qnil))
4522 {
4523 int x, y;
4524
4525 x_read_mouse_position (selected_frame, &x, &y);
4526 }
4527
4528 BLOCK_INPUT;
4529 mouse_track_width = 0;
4530 mouse_track_left = mouse_track_top = -1;
4531
4532 do
4533 {
4534 if ((x_mouse_x != mouse_track_left
4535 && (x_mouse_x < mouse_track_left
4536 || x_mouse_x > (mouse_track_left + mouse_track_width)))
4537 || x_mouse_y != mouse_track_top)
4538 {
4539 int hp = 0; /* Horizontal position */
4540 int len = FRAME_CURRENT_GLYPHS (f)->used[x_mouse_y];
4541 int p = FRAME_CURRENT_GLYPHS (f)->bufp[x_mouse_y];
4542 int tab_width = XINT (b->tab_width);
4543 int ctl_arrow_p = !NILP (b->ctl_arrow);
4544 unsigned char c;
4545 int mode_line_vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
4546 int in_mode_line = 0;
4547
4548 if (! FRAME_CURRENT_GLYPHS (f)->enable[x_mouse_y])
4549 break;
4550
4551 /* Erase previous rectangle. */
4552 if (mouse_track_width)
4553 {
4554 x_rectangle (f, f->output_data.x->reverse_gc,
4555 mouse_track_left, mouse_track_top,
4556 mouse_track_width, 1);
4557
4558 if ((mouse_track_left == f->phys_cursor_x
4559 || mouse_track_left == f->phys_cursor_x - 1)
4560 && mouse_track_top == f->phys_cursor_y)
4561 {
4562 x_display_cursor (f, 1);
4563 }
4564 }
4565
4566 mouse_track_left = x_mouse_x;
4567 mouse_track_top = x_mouse_y;
4568 mouse_track_width = 0;
4569
4570 if (mouse_track_left > len) /* Past the end of line. */
4571 goto draw_or_not;
4572
4573 if (mouse_track_top == mode_line_vpos)
4574 {
4575 in_mode_line = 1;
4576 goto draw_or_not;
4577 }
4578
4579 if (tab_width <= 0 || tab_width > 20) tab_width = 8;
4580 do
4581 {
4582 c = FETCH_CHAR (p);
4583 if (len == f->width && hp == len - 1 && c != '\n')
4584 goto draw_or_not;
4585
4586 switch (c)
4587 {
4588 case '\t':
4589 mouse_track_width = tab_width - (hp % tab_width);
4590 p++;
4591 hp += mouse_track_width;
4592 if (hp > x_mouse_x)
4593 {
4594 mouse_track_left = hp - mouse_track_width;
4595 goto draw_or_not;
4596 }
4597 continue;
4598
4599 case '\n':
4600 mouse_track_width = -1;
4601 goto draw_or_not;
4602
4603 default:
4604 if (ctl_arrow_p && (c < 040 || c == 0177))
4605 {
4606 if (p > ZV)
4607 goto draw_or_not;
4608
4609 mouse_track_width = 2;
4610 p++;
4611 hp +=2;
4612 if (hp > x_mouse_x)
4613 {
4614 mouse_track_left = hp - mouse_track_width;
4615 goto draw_or_not;
4616 }
4617 }
4618 else
4619 {
4620 mouse_track_width = 1;
4621 p++;
4622 hp++;
4623 }
4624 continue;
4625 }
4626 }
4627 while (hp <= x_mouse_x);
4628
4629 draw_or_not:
4630 if (mouse_track_width) /* Over text; use text pointer shape. */
4631 {
4632 XDefineCursor (FRAME_X_DISPLAY (f),
4633 FRAME_X_WINDOW (f),
4634 f->output_data.x->text_cursor);
4635 x_rectangle (f, f->output_data.x->cursor_gc,
4636 mouse_track_left, mouse_track_top,
4637 mouse_track_width, 1);
4638 }
4639 else if (in_mode_line)
4640 XDefineCursor (FRAME_X_DISPLAY (f),
4641 FRAME_X_WINDOW (f),
4642 f->output_data.x->modeline_cursor);
4643 else
4644 XDefineCursor (FRAME_X_DISPLAY (f),
4645 FRAME_X_WINDOW (f),
4646 f->output_data.x->nontext_cursor);
4647 }
4648
4649 XFlush (FRAME_X_DISPLAY (f));
4650 UNBLOCK_INPUT;
4651
4652 obj = read_char (-1, 0, 0, Qnil, 0);
4653 BLOCK_INPUT;
4654 }
4655 while (CONSP (obj) /* Mouse event */
4656 && EQ (Fcar (Fcdr (Fcdr (obj))), Qnil) /* Not scroll bar */
4657 && EQ (Vmouse_depressed, Qnil) /* Only motion events */
4658 && EQ (Vmouse_window, selected_window) /* In this window */
4659 && x_mouse_frame);
4660
4661 unread_command_event = obj;
4662
4663 if (mouse_track_width)
4664 {
4665 x_rectangle (f, f->output_data.x->reverse_gc,
4666 mouse_track_left, mouse_track_top,
4667 mouse_track_width, 1);
4668 mouse_track_width = 0;
4669 if ((mouse_track_left == f->phys_cursor_x
4670 || mouse_track_left - 1 == f->phys_cursor_x)
4671 && mouse_track_top == f->phys_cursor_y)
4672 {
4673 x_display_cursor (f, 1);
4674 }
4675 }
4676 XDefineCursor (FRAME_X_DISPLAY (f),
4677 FRAME_X_WINDOW (f),
4678 f->output_data.x->nontext_cursor);
4679 XFlush (FRAME_X_DISPLAY (f));
4680 UNBLOCK_INPUT;
4681
4682 return Qnil;
4683 }
4684 #endif
4685 \f
4686 #if 0
4687 #include "glyphs.h"
4688
4689 /* Draw a pixmap specified by IMAGE_DATA of dimensions WIDTH and HEIGHT
4690 on the frame F at position X, Y. */
4691
4692 x_draw_pixmap (f, x, y, image_data, width, height)
4693 struct frame *f;
4694 int x, y, width, height;
4695 char *image_data;
4696 {
4697 Pixmap image;
4698
4699 image = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
4700 FRAME_X_WINDOW (f), image_data,
4701 width, height);
4702 XCopyPlane (FRAME_X_DISPLAY (f), image, FRAME_X_WINDOW (f),
4703 f->output_data.x->normal_gc, 0, 0, width, height, x, y);
4704 }
4705 #endif
4706 \f
4707 #if 0 /* I'm told these functions are superfluous
4708 given the ability to bind function keys. */
4709
4710 #ifdef HAVE_X11
4711 DEFUN ("x-rebind-key", Fx_rebind_key, Sx_rebind_key, 3, 3, 0,
4712 "Rebind X keysym KEYSYM, with MODIFIERS, to generate NEWSTRING.\n\
4713 KEYSYM is a string which conforms to the X keysym definitions found\n\
4714 in X11/keysymdef.h, sans the initial XK_. MODIFIERS is nil or a\n\
4715 list of strings specifying modifier keys such as Control_L, which must\n\
4716 also be depressed for NEWSTRING to appear.")
4717 (x_keysym, modifiers, newstring)
4718 register Lisp_Object x_keysym;
4719 register Lisp_Object modifiers;
4720 register Lisp_Object newstring;
4721 {
4722 char *rawstring;
4723 register KeySym keysym;
4724 KeySym modifier_list[16];
4725
4726 check_x ();
4727 CHECK_STRING (x_keysym, 1);
4728 CHECK_STRING (newstring, 3);
4729
4730 keysym = XStringToKeysym ((char *) XSTRING (x_keysym)->data);
4731 if (keysym == NoSymbol)
4732 error ("Keysym does not exist");
4733
4734 if (NILP (modifiers))
4735 XRebindKeysym (x_current_display, keysym, modifier_list, 0,
4736 XSTRING (newstring)->data, XSTRING (newstring)->size);
4737 else
4738 {
4739 register Lisp_Object rest, mod;
4740 register int i = 0;
4741
4742 for (rest = modifiers; !NILP (rest); rest = Fcdr (rest))
4743 {
4744 if (i == 16)
4745 error ("Can't have more than 16 modifiers");
4746
4747 mod = Fcar (rest);
4748 CHECK_STRING (mod, 3);
4749 modifier_list[i] = XStringToKeysym ((char *) XSTRING (mod)->data);
4750 #ifndef HAVE_X11R5
4751 if (modifier_list[i] == NoSymbol
4752 || !(IsModifierKey (modifier_list[i])
4753 || ((unsigned)(modifier_list[i]) == XK_Mode_switch)
4754 || ((unsigned)(modifier_list[i]) == XK_Num_Lock)))
4755 #else
4756 if (modifier_list[i] == NoSymbol
4757 || !IsModifierKey (modifier_list[i]))
4758 #endif
4759 error ("Element is not a modifier keysym");
4760 i++;
4761 }
4762
4763 XRebindKeysym (x_current_display, keysym, modifier_list, i,
4764 XSTRING (newstring)->data, XSTRING (newstring)->size);
4765 }
4766
4767 return Qnil;
4768 }
4769
4770 DEFUN ("x-rebind-keys", Fx_rebind_keys, Sx_rebind_keys, 2, 2, 0,
4771 "Rebind KEYCODE to list of strings STRINGS.\n\
4772 STRINGS should be a list of 16 elements, one for each shift combination.\n\
4773 nil as element means don't change.\n\
4774 See the documentation of `x-rebind-key' for more information.")
4775 (keycode, strings)
4776 register Lisp_Object keycode;
4777 register Lisp_Object strings;
4778 {
4779 register Lisp_Object item;
4780 register unsigned char *rawstring;
4781 KeySym rawkey, modifier[1];
4782 int strsize;
4783 register unsigned i;
4784
4785 check_x ();
4786 CHECK_NUMBER (keycode, 1);
4787 CHECK_CONS (strings, 2);
4788 rawkey = (KeySym) ((unsigned) (XINT (keycode))) & 255;
4789 for (i = 0; i <= 15; strings = Fcdr (strings), i++)
4790 {
4791 item = Fcar (strings);
4792 if (!NILP (item))
4793 {
4794 CHECK_STRING (item, 2);
4795 strsize = XSTRING (item)->size;
4796 rawstring = (unsigned char *) xmalloc (strsize);
4797 bcopy (XSTRING (item)->data, rawstring, strsize);
4798 modifier[1] = 1 << i;
4799 XRebindKeysym (x_current_display, rawkey, modifier, 1,
4800 rawstring, strsize);
4801 }
4802 }
4803 return Qnil;
4804 }
4805 #endif /* HAVE_X11 */
4806 #endif /* 0 */
4807 \f
4808 #ifndef HAVE_XSCREENNUMBEROFSCREEN
4809 int
4810 XScreenNumberOfScreen (scr)
4811 register Screen *scr;
4812 {
4813 register Display *dpy;
4814 register Screen *dpyscr;
4815 register int i;
4816
4817 dpy = scr->display;
4818 dpyscr = dpy->screens;
4819
4820 for (i = 0; i < dpy->nscreens; i++, dpyscr++)
4821 if (scr == dpyscr)
4822 return i;
4823
4824 return -1;
4825 }
4826 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
4827
4828 Visual *
4829 select_visual (dpy, screen, depth)
4830 Display *dpy;
4831 Screen *screen;
4832 unsigned int *depth;
4833 {
4834 Visual *v;
4835 XVisualInfo *vinfo, vinfo_template;
4836 int n_visuals;
4837
4838 v = DefaultVisualOfScreen (screen);
4839
4840 #ifdef HAVE_X11R4
4841 vinfo_template.visualid = XVisualIDFromVisual (v);
4842 #else
4843 vinfo_template.visualid = v->visualid;
4844 #endif
4845
4846 vinfo_template.screen = XScreenNumberOfScreen (screen);
4847
4848 vinfo = XGetVisualInfo (dpy,
4849 VisualIDMask | VisualScreenMask, &vinfo_template,
4850 &n_visuals);
4851 if (n_visuals != 1)
4852 fatal ("Can't get proper X visual info");
4853
4854 if ((1 << vinfo->depth) == vinfo->colormap_size)
4855 *depth = vinfo->depth;
4856 else
4857 {
4858 int i = 0;
4859 int n = vinfo->colormap_size - 1;
4860 while (n)
4861 {
4862 n = n >> 1;
4863 i++;
4864 }
4865 *depth = i;
4866 }
4867
4868 XFree ((char *) vinfo);
4869 return v;
4870 }
4871
4872 /* Return the X display structure for the display named NAME.
4873 Open a new connection if necessary. */
4874
4875 struct x_display_info *
4876 x_display_info_for_name (name)
4877 Lisp_Object name;
4878 {
4879 Lisp_Object names;
4880 struct x_display_info *dpyinfo;
4881
4882 CHECK_STRING (name, 0);
4883
4884 if (! EQ (Vwindow_system, intern ("x")))
4885 error ("Not using X Windows");
4886
4887 for (dpyinfo = x_display_list, names = x_display_name_list;
4888 dpyinfo;
4889 dpyinfo = dpyinfo->next, names = XCONS (names)->cdr)
4890 {
4891 Lisp_Object tem;
4892 tem = Fstring_equal (XCONS (XCONS (names)->car)->car, name);
4893 if (!NILP (tem))
4894 return dpyinfo;
4895 }
4896
4897 /* Use this general default value to start with. */
4898 Vx_resource_name = Vinvocation_name;
4899
4900 validate_x_resource_name ();
4901
4902 dpyinfo = x_term_init (name, (unsigned char *)0,
4903 (char *) XSTRING (Vx_resource_name)->data);
4904
4905 if (dpyinfo == 0)
4906 error ("Cannot connect to X server %s", XSTRING (name)->data);
4907
4908 x_in_use = 1;
4909 XSETFASTINT (Vwindow_system_version, 11);
4910
4911 return dpyinfo;
4912 }
4913
4914 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
4915 1, 3, 0, "Open a connection to an X server.\n\
4916 DISPLAY is the name of the display to connect to.\n\
4917 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
4918 If the optional third arg MUST-SUCCEED is non-nil,\n\
4919 terminate Emacs if we can't open the connection.")
4920 (display, xrm_string, must_succeed)
4921 Lisp_Object display, xrm_string, must_succeed;
4922 {
4923 unsigned int n_planes;
4924 unsigned char *xrm_option;
4925 struct x_display_info *dpyinfo;
4926
4927 CHECK_STRING (display, 0);
4928 if (! NILP (xrm_string))
4929 CHECK_STRING (xrm_string, 1);
4930
4931 if (! EQ (Vwindow_system, intern ("x")))
4932 error ("Not using X Windows");
4933
4934 if (! NILP (xrm_string))
4935 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
4936 else
4937 xrm_option = (unsigned char *) 0;
4938
4939 validate_x_resource_name ();
4940
4941 /* This is what opens the connection and sets x_current_display.
4942 This also initializes many symbols, such as those used for input. */
4943 dpyinfo = x_term_init (display, xrm_option,
4944 (char *) XSTRING (Vx_resource_name)->data);
4945
4946 if (dpyinfo == 0)
4947 {
4948 if (!NILP (must_succeed))
4949 fatal ("Cannot connect to X server %s.\n\
4950 Check the DISPLAY environment variable or use `-d'.\n\
4951 Also use the `xhost' program to verify that it is set to permit\n\
4952 connections from your machine.\n",
4953 XSTRING (display)->data);
4954 else
4955 error ("Cannot connect to X server %s", XSTRING (display)->data);
4956 }
4957
4958 x_in_use = 1;
4959
4960 XSETFASTINT (Vwindow_system_version, 11);
4961 return Qnil;
4962 }
4963
4964 DEFUN ("x-close-connection", Fx_close_connection,
4965 Sx_close_connection, 1, 1, 0,
4966 "Close the connection to DISPLAY's X server.\n\
4967 For DISPLAY, specify either a frame or a display name (a string).\n\
4968 If DISPLAY is nil, that stands for the selected frame's display.")
4969 (display)
4970 Lisp_Object display;
4971 {
4972 struct x_display_info *dpyinfo = check_x_display_info (display);
4973 struct x_display_info *tail;
4974 int i;
4975
4976 if (dpyinfo->reference_count > 0)
4977 error ("Display still has frames on it");
4978
4979 BLOCK_INPUT;
4980 /* Free the fonts in the font table. */
4981 for (i = 0; i < dpyinfo->n_fonts; i++)
4982 {
4983 if (dpyinfo->font_table[i].name)
4984 free (dpyinfo->font_table[i].name);
4985 /* Don't free the full_name string;
4986 it is always shared with something else. */
4987 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
4988 }
4989 x_destroy_all_bitmaps (dpyinfo);
4990 XSetCloseDownMode (dpyinfo->display, DestroyAll);
4991
4992 #ifdef USE_X_TOOLKIT
4993 XtCloseDisplay (dpyinfo->display);
4994 #else
4995 XCloseDisplay (dpyinfo->display);
4996 #endif
4997
4998 x_delete_display (dpyinfo);
4999 UNBLOCK_INPUT;
5000
5001 return Qnil;
5002 }
5003
5004 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
5005 "Return the list of display names that Emacs has connections to.")
5006 ()
5007 {
5008 Lisp_Object tail, result;
5009
5010 result = Qnil;
5011 for (tail = x_display_name_list; ! NILP (tail); tail = XCONS (tail)->cdr)
5012 result = Fcons (XCONS (XCONS (tail)->car)->car, result);
5013
5014 return result;
5015 }
5016
5017 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
5018 "If ON is non-nil, report X errors as soon as the erring request is made.\n\
5019 If ON is nil, allow buffering of requests.\n\
5020 Turning on synchronization prohibits the Xlib routines from buffering\n\
5021 requests and seriously degrades performance, but makes debugging much\n\
5022 easier.\n\
5023 The optional second argument DISPLAY specifies which display to act on.\n\
5024 DISPLAY should be either a frame or a display name (a string).\n\
5025 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
5026 (on, display)
5027 Lisp_Object display, on;
5028 {
5029 struct x_display_info *dpyinfo = check_x_display_info (display);
5030
5031 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
5032
5033 return Qnil;
5034 }
5035
5036 /* Wait for responses to all X commands issued so far for frame F. */
5037
5038 void
5039 x_sync (f)
5040 FRAME_PTR f;
5041 {
5042 BLOCK_INPUT;
5043 XSync (FRAME_X_DISPLAY (f), False);
5044 UNBLOCK_INPUT;
5045 }
5046 \f
5047 syms_of_xfns ()
5048 {
5049 /* This is zero if not using X windows. */
5050 x_in_use = 0;
5051
5052 /* The section below is built by the lisp expression at the top of the file,
5053 just above where these variables are declared. */
5054 /*&&& init symbols here &&&*/
5055 Qauto_raise = intern ("auto-raise");
5056 staticpro (&Qauto_raise);
5057 Qauto_lower = intern ("auto-lower");
5058 staticpro (&Qauto_lower);
5059 Qbackground_color = intern ("background-color");
5060 staticpro (&Qbackground_color);
5061 Qbar = intern ("bar");
5062 staticpro (&Qbar);
5063 Qborder_color = intern ("border-color");
5064 staticpro (&Qborder_color);
5065 Qborder_width = intern ("border-width");
5066 staticpro (&Qborder_width);
5067 Qbox = intern ("box");
5068 staticpro (&Qbox);
5069 Qcursor_color = intern ("cursor-color");
5070 staticpro (&Qcursor_color);
5071 Qcursor_type = intern ("cursor-type");
5072 staticpro (&Qcursor_type);
5073 Qforeground_color = intern ("foreground-color");
5074 staticpro (&Qforeground_color);
5075 Qgeometry = intern ("geometry");
5076 staticpro (&Qgeometry);
5077 Qicon_left = intern ("icon-left");
5078 staticpro (&Qicon_left);
5079 Qicon_top = intern ("icon-top");
5080 staticpro (&Qicon_top);
5081 Qicon_type = intern ("icon-type");
5082 staticpro (&Qicon_type);
5083 Qicon_name = intern ("icon-name");
5084 staticpro (&Qicon_name);
5085 Qinternal_border_width = intern ("internal-border-width");
5086 staticpro (&Qinternal_border_width);
5087 Qleft = intern ("left");
5088 staticpro (&Qleft);
5089 Qright = intern ("right");
5090 staticpro (&Qright);
5091 Qmouse_color = intern ("mouse-color");
5092 staticpro (&Qmouse_color);
5093 Qnone = intern ("none");
5094 staticpro (&Qnone);
5095 Qparent_id = intern ("parent-id");
5096 staticpro (&Qparent_id);
5097 Qscroll_bar_width = intern ("scroll-bar-width");
5098 staticpro (&Qscroll_bar_width);
5099 Qsuppress_icon = intern ("suppress-icon");
5100 staticpro (&Qsuppress_icon);
5101 Qtop = intern ("top");
5102 staticpro (&Qtop);
5103 Qundefined_color = intern ("undefined-color");
5104 staticpro (&Qundefined_color);
5105 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
5106 staticpro (&Qvertical_scroll_bars);
5107 Qvisibility = intern ("visibility");
5108 staticpro (&Qvisibility);
5109 Qwindow_id = intern ("window-id");
5110 staticpro (&Qwindow_id);
5111 Qx_frame_parameter = intern ("x-frame-parameter");
5112 staticpro (&Qx_frame_parameter);
5113 Qx_resource_name = intern ("x-resource-name");
5114 staticpro (&Qx_resource_name);
5115 Quser_position = intern ("user-position");
5116 staticpro (&Quser_position);
5117 Quser_size = intern ("user-size");
5118 staticpro (&Quser_size);
5119 Qdisplay = intern ("display");
5120 staticpro (&Qdisplay);
5121 /* This is the end of symbol initialization. */
5122
5123 Fput (Qundefined_color, Qerror_conditions,
5124 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
5125 Fput (Qundefined_color, Qerror_message,
5126 build_string ("Undefined color"));
5127
5128 init_x_parm_symbols ();
5129
5130 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
5131 "List of directories to search for bitmap files for X.");
5132 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
5133
5134 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
5135 "The shape of the pointer when over text.\n\
5136 Changing the value does not affect existing frames\n\
5137 unless you set the mouse color.");
5138 Vx_pointer_shape = Qnil;
5139
5140 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
5141 "The name Emacs uses to look up X resources; for internal use only.\n\
5142 `x-get-resource' uses this as the first component of the instance name\n\
5143 when requesting resource values.\n\
5144 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
5145 was invoked, or to the value specified with the `-name' or `-rn'\n\
5146 switches, if present.");
5147 Vx_resource_name = Qnil;
5148
5149 #if 0 /* This doesn't really do anything. */
5150 DEFVAR_INT ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
5151 "The shape of the pointer when not over text.\n\
5152 This variable takes effect when you create a new frame\n\
5153 or when you set the mouse color.");
5154 #endif
5155 Vx_nontext_pointer_shape = Qnil;
5156
5157 #if 0 /* This doesn't really do anything. */
5158 DEFVAR_INT ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
5159 "The shape of the pointer when over the mode line.\n\
5160 This variable takes effect when you create a new frame\n\
5161 or when you set the mouse color.");
5162 #endif
5163 Vx_mode_pointer_shape = Qnil;
5164
5165 DEFVAR_INT ("x-sensitive-text-pointer-shape",
5166 &Vx_sensitive_text_pointer_shape,
5167 "The shape of the pointer when over mouse-sensitive text.\n\
5168 This variable takes effect when you create a new frame\n\
5169 or when you set the mouse color.");
5170 Vx_sensitive_text_pointer_shape = Qnil;
5171
5172 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
5173 "A string indicating the foreground color of the cursor box.");
5174 Vx_cursor_fore_pixel = Qnil;
5175
5176 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
5177 "Non-nil if no X window manager is in use.\n\
5178 Emacs doesn't try to figure this out; this is always nil\n\
5179 unless you set it to something else.");
5180 /* We don't have any way to find this out, so set it to nil
5181 and maybe the user would like to set it to t. */
5182 Vx_no_window_manager = Qnil;
5183
5184 #ifdef USE_X_TOOLKIT
5185 Fprovide (intern ("x-toolkit"));
5186 #endif
5187 #ifdef USE_MOTIF
5188 Fprovide (intern ("motif"));
5189 #endif
5190
5191 defsubr (&Sx_get_resource);
5192 #if 0
5193 defsubr (&Sx_draw_rectangle);
5194 defsubr (&Sx_erase_rectangle);
5195 defsubr (&Sx_contour_region);
5196 defsubr (&Sx_uncontour_region);
5197 #endif
5198 defsubr (&Sx_list_fonts);
5199 defsubr (&Sx_display_color_p);
5200 defsubr (&Sx_display_grayscale_p);
5201 defsubr (&Sx_color_defined_p);
5202 defsubr (&Sx_color_values);
5203 defsubr (&Sx_server_max_request_size);
5204 defsubr (&Sx_server_vendor);
5205 defsubr (&Sx_server_version);
5206 defsubr (&Sx_display_pixel_width);
5207 defsubr (&Sx_display_pixel_height);
5208 defsubr (&Sx_display_mm_width);
5209 defsubr (&Sx_display_mm_height);
5210 defsubr (&Sx_display_screens);
5211 defsubr (&Sx_display_planes);
5212 defsubr (&Sx_display_color_cells);
5213 defsubr (&Sx_display_visual_class);
5214 defsubr (&Sx_display_backing_store);
5215 defsubr (&Sx_display_save_under);
5216 #if 0
5217 defsubr (&Sx_rebind_key);
5218 defsubr (&Sx_rebind_keys);
5219 defsubr (&Sx_track_pointer);
5220 defsubr (&Sx_grab_pointer);
5221 defsubr (&Sx_ungrab_pointer);
5222 #endif
5223 defsubr (&Sx_parse_geometry);
5224 defsubr (&Sx_create_frame);
5225 #if 0
5226 defsubr (&Sx_horizontal_line);
5227 #endif
5228 defsubr (&Sx_open_connection);
5229 defsubr (&Sx_close_connection);
5230 defsubr (&Sx_display_list);
5231 defsubr (&Sx_synchronize);
5232 }
5233
5234 #endif /* HAVE_X_WINDOWS */