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