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