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