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