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