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