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