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