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