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