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