Undo previous change.
[bpt/emacs.git] / src / xfns.c
CommitLineData
01f1ba30 1/* Functions for the X window system.
637ad741 2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996 Free Software Foundation.
01f1ba30
JB
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
1113d9db 8the Free Software Foundation; either version 2, or (at your option)
01f1ba30
JB
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
01f1ba30
JB
20
21/* Completely rewritten by Richard Stallman. */
22
23/* Rewritten for X11 by Joseph Arceneaux */
24
c389a86d
RS
25#include <signal.h>
26#include <config.h>
27
40e6f148
RS
28/* This makes the fields of a Display accessible, in Xlib header files. */
29#define XLIB_ILLEGAL_ACCESS
30
01f1ba30
JB
31#include "lisp.h"
32#include "xterm.h"
f676886a 33#include "frame.h"
01f1ba30
JB
34#include "window.h"
35#include "buffer.h"
36#include "dispextern.h"
1f98fa48 37#include "keyboard.h"
9ac0d9e0 38#include "blockinput.h"
ef818feb 39#include <paths.h>
01f1ba30
JB
40
41#ifdef HAVE_X_WINDOWS
42extern void abort ();
43
271d6c1c
KH
44/* On some systems, the character-composition stuff is broken in X11R5. */
45#if defined (HAVE_X11R5) && ! defined (HAVE_X11R6)
46#ifdef X11R5_INHIBIT_I18N
32e2bcb8 47#define X_I18N_INHIBITED
271d6c1c
KH
48#endif
49#endif
50
0a93081c 51#ifndef VMS
0505a740 52#if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
ef493a27
RS
53#include "bitmaps/gray.xbm"
54#else
dbc4e1c1 55#include <X11/bitmaps/gray>
ef493a27 56#endif
0a93081c
JB
57#else
58#include "[.bitmaps]gray.xbm"
59#endif
dbc4e1c1 60
9ef48a9d
RS
61#ifdef USE_X_TOOLKIT
62#include <X11/Shell.h>
63
398ffa92 64#ifndef USE_MOTIF
9ef48a9d
RS
65#include <X11/Xaw/Paned.h>
66#include <X11/Xaw/Label.h>
398ffa92 67#endif /* USE_MOTIF */
9ef48a9d
RS
68
69#ifdef USG
70#undef USG /* ####KLUDGE for Solaris 2.2 and up */
71#include <X11/Xos.h>
72#define USG
73#else
74#include <X11/Xos.h>
75#endif
76
77#include "widget.h"
78
79#include "../lwlib/lwlib.h"
80
3b882b1d
RS
81/* Do the EDITRES protocol if running X11R5
82 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
83#if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
6c32dd68 84#define HACK_EDITRES
b9dc4443 85extern void _XEditResCheckMessages ();
6c32dd68
PR
86#endif /* R5 + Athena */
87
88/* Unique id counter for widgets created by the Lucid Widget
b9dc4443 89 Library. */
6c32dd68
PR
90extern LWLIB_ID widget_id_tick;
91
82c90203 92/* This is part of a kludge--see lwlib/xlwmenu.c. */
03e2c340 93extern XFontStruct *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 Qforeground_color;
173Lisp_Object Qgeometry;
f9942c9e
JB
174Lisp_Object Qicon_left;
175Lisp_Object Qicon_top;
176Lisp_Object Qicon_type;
80534dd6 177Lisp_Object Qicon_name;
f9942c9e
JB
178Lisp_Object Qinternal_border_width;
179Lisp_Object Qleft;
180Lisp_Object Qmouse_color;
baaed68e 181Lisp_Object Qnone;
f9942c9e 182Lisp_Object Qparent_id;
4701395c 183Lisp_Object Qscroll_bar_width;
8af1d7ca 184Lisp_Object Qsuppress_icon;
f9942c9e 185Lisp_Object Qtop;
01f1ba30 186Lisp_Object Qundefined_color;
a3c87d4e 187Lisp_Object Qvertical_scroll_bars;
49795535 188Lisp_Object Qvisibility;
f9942c9e 189Lisp_Object Qwindow_id;
f676886a 190Lisp_Object Qx_frame_parameter;
9ef48a9d 191Lisp_Object Qx_resource_name;
4fe1de12
RS
192Lisp_Object Quser_position;
193Lisp_Object Quser_size;
b9dc4443 194Lisp_Object Qdisplay;
01f1ba30 195
b9dc4443 196/* The below are defined in frame.c. */
baaed68e 197extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
c2304e02 198extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
f9942c9e 199
01f1ba30
JB
200extern Lisp_Object Vwindow_system_version;
201
01f1ba30 202\f
11ae94fe 203/* Error if we are not connected to X. */
7fc9de26 204void
11ae94fe
RS
205check_x ()
206{
b9dc4443 207 if (! x_in_use)
11ae94fe
RS
208 error ("X windows are not in use or not initialized");
209}
210
1c59f5df
RS
211/* Nonzero if we can use mouse menus.
212 You should not call this unless HAVE_MENUS is defined. */
75cc8ee5
RS
213
214int
1c59f5df 215have_menus_p ()
75cc8ee5 216{
b9dc4443
RS
217 return x_in_use;
218}
219
220/* Extract a frame as a FRAME_PTR, defaulting to the selected frame
221 and checking validity for X. */
222
223FRAME_PTR
224check_x_frame (frame)
225 Lisp_Object frame;
226{
227 FRAME_PTR f;
228
229 if (NILP (frame))
230 f = selected_frame;
231 else
232 {
233 CHECK_LIVE_FRAME (frame, 0);
234 f = XFRAME (frame);
235 }
236 if (! FRAME_X_P (f))
1c59f5df 237 error ("Non-X frame used");
b9dc4443 238 return f;
75cc8ee5
RS
239}
240
b9dc4443
RS
241/* Let the user specify an X display with a frame.
242 nil stands for the selected frame--or, if that is not an X frame,
243 the first X display on the list. */
244
245static struct x_display_info *
246check_x_display_info (frame)
247 Lisp_Object frame;
248{
249 if (NILP (frame))
250 {
251 if (FRAME_X_P (selected_frame))
252 return FRAME_X_DISPLAY_INFO (selected_frame);
253 else if (x_display_list != 0)
254 return x_display_list;
255 else
256 error ("X windows are not in use or not initialized");
257 }
258 else if (STRINGP (frame))
259 return x_display_info_for_name (frame);
260 else
261 {
262 FRAME_PTR f;
263
264 CHECK_LIVE_FRAME (frame, 0);
265 f = XFRAME (frame);
266 if (! FRAME_X_P (f))
1c59f5df 267 error ("Non-X frame used");
b9dc4443
RS
268 return FRAME_X_DISPLAY_INFO (f);
269 }
270}
271\f
f676886a
JB
272/* Return the Emacs frame-object corresponding to an X window.
273 It could be the frame's main window or an icon window. */
01f1ba30 274
34ca5317 275/* This function can be called during GC, so use GC_xxx type test macros. */
bcb2db92 276
f676886a 277struct frame *
2d271e2e
KH
278x_window_to_frame (dpyinfo, wdesc)
279 struct x_display_info *dpyinfo;
01f1ba30
JB
280 int wdesc;
281{
f676886a
JB
282 Lisp_Object tail, frame;
283 struct frame *f;
01f1ba30 284
34ca5317 285 for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
01f1ba30 286 {
f676886a 287 frame = XCONS (tail)->car;
34ca5317 288 if (!GC_FRAMEP (frame))
01f1ba30 289 continue;
f676886a 290 f = XFRAME (frame);
7556890b 291 if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
2d271e2e 292 continue;
9ef48a9d 293#ifdef USE_X_TOOLKIT
7556890b
RS
294 if ((f->output_data.x->edit_widget
295 && XtWindow (f->output_data.x->edit_widget) == wdesc)
296 || f->output_data.x->icon_desc == wdesc)
9ef48a9d
RS
297 return f;
298#else /* not USE_X_TOOLKIT */
fe24a618 299 if (FRAME_X_WINDOW (f) == wdesc
7556890b 300 || f->output_data.x->icon_desc == wdesc)
f676886a 301 return f;
9ef48a9d
RS
302#endif /* not USE_X_TOOLKIT */
303 }
304 return 0;
305}
306
307#ifdef USE_X_TOOLKIT
308/* Like x_window_to_frame but also compares the window with the widget's
309 windows. */
310
311struct frame *
2d271e2e
KH
312x_any_window_to_frame (dpyinfo, wdesc)
313 struct x_display_info *dpyinfo;
9ef48a9d
RS
314 int wdesc;
315{
316 Lisp_Object tail, frame;
317 struct frame *f;
7556890b 318 struct x_output *x;
9ef48a9d 319
34ca5317 320 for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
9ef48a9d
RS
321 {
322 frame = XCONS (tail)->car;
34ca5317 323 if (!GC_FRAMEP (frame))
9ef48a9d
RS
324 continue;
325 f = XFRAME (frame);
54e9e953 326 if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
2d271e2e 327 continue;
7556890b 328 x = f->output_data.x;
9ef48a9d
RS
329 /* This frame matches if the window is any of its widgets. */
330 if (wdesc == XtWindow (x->widget)
331 || wdesc == XtWindow (x->column_widget)
332 || wdesc == XtWindow (x->edit_widget))
333 return f;
334 /* Match if the window is this frame's menubar. */
6c32dd68 335 if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
9ef48a9d 336 return f;
01f1ba30
JB
337 }
338 return 0;
339}
5e65b9ab 340
5fbc3f3a
KH
341/* Likewise, but exclude the menu bar widget. */
342
343struct frame *
344x_non_menubar_window_to_frame (dpyinfo, wdesc)
345 struct x_display_info *dpyinfo;
346 int wdesc;
347{
348 Lisp_Object tail, frame;
349 struct frame *f;
7556890b 350 struct x_output *x;
5fbc3f3a
KH
351
352 for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
353 {
354 frame = XCONS (tail)->car;
355 if (!GC_FRAMEP (frame))
356 continue;
357 f = XFRAME (frame);
54e9e953 358 if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
5fbc3f3a 359 continue;
7556890b 360 x = f->output_data.x;
5fbc3f3a
KH
361 /* This frame matches if the window is any of its widgets. */
362 if (wdesc == XtWindow (x->widget)
363 || wdesc == XtWindow (x->column_widget)
364 || wdesc == XtWindow (x->edit_widget))
365 return f;
366 }
367 return 0;
368}
369
fd3a3022
RS
370/* Likewise, but consider only the menu bar widget. */
371
372struct frame *
373x_menubar_window_to_frame (dpyinfo, wdesc)
374 struct x_display_info *dpyinfo;
375 int wdesc;
376{
377 Lisp_Object tail, frame;
378 struct frame *f;
7556890b 379 struct x_output *x;
fd3a3022
RS
380
381 for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
382 {
383 frame = XCONS (tail)->car;
384 if (!GC_FRAMEP (frame))
385 continue;
386 f = XFRAME (frame);
54e9e953 387 if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
fd3a3022 388 continue;
7556890b 389 x = f->output_data.x;
fd3a3022
RS
390 /* Match if the window is this frame's menubar. */
391 if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
392 return f;
393 }
394 return 0;
395}
396
5e65b9ab
RS
397/* Return the frame whose principal (outermost) window is WDESC.
398 If WDESC is some other (smaller) window, we return 0. */
399
400struct frame *
2d271e2e
KH
401x_top_window_to_frame (dpyinfo, wdesc)
402 struct x_display_info *dpyinfo;
5e65b9ab
RS
403 int wdesc;
404{
405 Lisp_Object tail, frame;
406 struct frame *f;
7556890b 407 struct x_output *x;
5e65b9ab 408
34ca5317 409 for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
5e65b9ab
RS
410 {
411 frame = XCONS (tail)->car;
34ca5317 412 if (!GC_FRAMEP (frame))
5e65b9ab
RS
413 continue;
414 f = XFRAME (frame);
54e9e953 415 if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
2d271e2e 416 continue;
7556890b 417 x = f->output_data.x;
5e65b9ab
RS
418 /* This frame matches if the window is its topmost widget. */
419 if (wdesc == XtWindow (x->widget))
420 return f;
7a994728
KH
421#if 0 /* I don't know why it did this,
422 but it seems logically wrong,
423 and it causes trouble for MapNotify events. */
5e65b9ab
RS
424 /* Match if the window is this frame's menubar. */
425 if (x->menubar_widget
426 && wdesc == XtWindow (x->menubar_widget))
427 return f;
7a994728 428#endif
5e65b9ab
RS
429 }
430 return 0;
431}
9ef48a9d 432#endif /* USE_X_TOOLKIT */
01f1ba30 433
01f1ba30 434\f
203c1d73
RS
435
436/* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
437 id, which is just an int that this section returns. Bitmaps are
438 reference counted so they can be shared among frames.
439
440 Bitmap indices are guaranteed to be > 0, so a negative number can
441 be used to indicate no bitmap.
442
443 If you use x_create_bitmap_from_data, then you must keep track of
444 the bitmaps yourself. That is, creating a bitmap from the same
b9dc4443 445 data more than once will not be caught. */
203c1d73
RS
446
447
f1c7b5a6
RS
448/* Functions to access the contents of a bitmap, given an id. */
449
450int
451x_bitmap_height (f, id)
452 FRAME_PTR f;
453 int id;
454{
08a90d6a 455 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
f1c7b5a6
RS
456}
457
458int
459x_bitmap_width (f, id)
460 FRAME_PTR f;
461 int id;
462{
08a90d6a 463 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
f1c7b5a6
RS
464}
465
466int
467x_bitmap_pixmap (f, id)
468 FRAME_PTR f;
469 int id;
470{
08a90d6a 471 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
f1c7b5a6
RS
472}
473
474
203c1d73
RS
475/* Allocate a new bitmap record. Returns index of new record. */
476
477static int
08a90d6a
RS
478x_allocate_bitmap_record (f)
479 FRAME_PTR f;
203c1d73 480{
08a90d6a
RS
481 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
482 int i;
483
484 if (dpyinfo->bitmaps == NULL)
203c1d73 485 {
08a90d6a
RS
486 dpyinfo->bitmaps_size = 10;
487 dpyinfo->bitmaps
488 = (struct x_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
489 dpyinfo->bitmaps_last = 1;
203c1d73
RS
490 return 1;
491 }
492
08a90d6a
RS
493 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
494 return ++dpyinfo->bitmaps_last;
203c1d73 495
08a90d6a
RS
496 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
497 if (dpyinfo->bitmaps[i].refcount == 0)
498 return i + 1;
203c1d73 499
08a90d6a
RS
500 dpyinfo->bitmaps_size *= 2;
501 dpyinfo->bitmaps
502 = (struct x_bitmap_record *) xrealloc (dpyinfo->bitmaps,
503 dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
504 return ++dpyinfo->bitmaps_last;
203c1d73
RS
505}
506
507/* Add one reference to the reference count of the bitmap with id ID. */
508
509void
f1c7b5a6
RS
510x_reference_bitmap (f, id)
511 FRAME_PTR f;
203c1d73
RS
512 int id;
513{
08a90d6a 514 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
203c1d73
RS
515}
516
517/* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
518
519int
520x_create_bitmap_from_data (f, bits, width, height)
521 struct frame *f;
522 char *bits;
523 unsigned int width, height;
524{
08a90d6a 525 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
203c1d73
RS
526 Pixmap bitmap;
527 int id;
528
b9dc4443 529 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
203c1d73
RS
530 bits, width, height);
531
532 if (! bitmap)
533 return -1;
534
08a90d6a
RS
535 id = x_allocate_bitmap_record (f);
536 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
537 dpyinfo->bitmaps[id - 1].file = NULL;
538 dpyinfo->bitmaps[id - 1].refcount = 1;
539 dpyinfo->bitmaps[id - 1].depth = 1;
540 dpyinfo->bitmaps[id - 1].height = height;
541 dpyinfo->bitmaps[id - 1].width = width;
203c1d73
RS
542
543 return id;
544}
545
546/* Create bitmap from file FILE for frame F. */
547
548int
549x_create_bitmap_from_file (f, file)
550 struct frame *f;
f1c7b5a6 551 Lisp_Object file;
203c1d73 552{
08a90d6a 553 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
203c1d73
RS
554 unsigned int width, height;
555 Pixmap bitmap;
556 int xhot, yhot, result, id;
f1c7b5a6
RS
557 Lisp_Object found;
558 int fd;
559 char *filename;
203c1d73
RS
560
561 /* Look for an existing bitmap with the same name. */
08a90d6a 562 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
203c1d73 563 {
08a90d6a
RS
564 if (dpyinfo->bitmaps[id].refcount
565 && dpyinfo->bitmaps[id].file
566 && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
203c1d73 567 {
08a90d6a 568 ++dpyinfo->bitmaps[id].refcount;
203c1d73
RS
569 return id + 1;
570 }
571 }
572
f1c7b5a6
RS
573 /* Search bitmap-file-path for the file, if appropriate. */
574 fd = openp (Vx_bitmap_file_path, file, "", &found, 0);
575 if (fd < 0)
576 return -1;
577 close (fd);
578
579 filename = (char *) XSTRING (found)->data;
580
b9dc4443 581 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f1c7b5a6 582 filename, &width, &height, &bitmap, &xhot, &yhot);
203c1d73
RS
583 if (result != BitmapSuccess)
584 return -1;
585
08a90d6a
RS
586 id = x_allocate_bitmap_record (f);
587 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
588 dpyinfo->bitmaps[id - 1].refcount = 1;
589 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (XSTRING (file)->size + 1);
590 dpyinfo->bitmaps[id - 1].depth = 1;
591 dpyinfo->bitmaps[id - 1].height = height;
592 dpyinfo->bitmaps[id - 1].width = width;
593 strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
203c1d73
RS
594
595 return id;
596}
597
598/* Remove reference to bitmap with id number ID. */
599
600int
f1c7b5a6
RS
601x_destroy_bitmap (f, id)
602 FRAME_PTR f;
203c1d73
RS
603 int id;
604{
08a90d6a
RS
605 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
606
203c1d73
RS
607 if (id > 0)
608 {
08a90d6a
RS
609 --dpyinfo->bitmaps[id - 1].refcount;
610 if (dpyinfo->bitmaps[id - 1].refcount == 0)
203c1d73 611 {
ed662bdd 612 BLOCK_INPUT;
08a90d6a
RS
613 XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].pixmap);
614 if (dpyinfo->bitmaps[id - 1].file)
203c1d73 615 {
08a90d6a
RS
616 free (dpyinfo->bitmaps[id - 1].file);
617 dpyinfo->bitmaps[id - 1].file = NULL;
203c1d73 618 }
ed662bdd 619 UNBLOCK_INPUT;
203c1d73
RS
620 }
621 }
622}
623
08a90d6a 624/* Free all the bitmaps for the display specified by DPYINFO. */
203c1d73 625
08a90d6a
RS
626static void
627x_destroy_all_bitmaps (dpyinfo)
628 struct x_display_info *dpyinfo;
203c1d73 629{
08a90d6a
RS
630 int i;
631 for (i = 0; i < dpyinfo->bitmaps_last; i++)
632 if (dpyinfo->bitmaps[i].refcount > 0)
633 {
634 XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].pixmap);
635 if (dpyinfo->bitmaps[i].file)
636 free (dpyinfo->bitmaps[i].file);
637 }
638 dpyinfo->bitmaps_last = 0;
203c1d73
RS
639}
640\f
f676886a 641/* Connect the frame-parameter names for X frames
01f1ba30
JB
642 to the ways of passing the parameter values to the window system.
643
644 The name of a parameter, as a Lisp symbol,
f676886a 645 has an `x-frame-parameter' property which is an integer in Lisp
9fb026ab 646 that is an index in this table. */
01f1ba30 647
f676886a 648struct x_frame_parm_table
01f1ba30
JB
649{
650 char *name;
f676886a 651 void (*setter)( /* struct frame *frame, Lisp_Object val, oldval */ );
01f1ba30
JB
652};
653
654void x_set_foreground_color ();
655void x_set_background_color ();
656void x_set_mouse_color ();
657void x_set_cursor_color ();
658void x_set_border_color ();
dbc4e1c1 659void x_set_cursor_type ();
01f1ba30 660void x_set_icon_type ();
80534dd6 661void x_set_icon_name ();
01f1ba30
JB
662void x_set_font ();
663void x_set_border_width ();
664void x_set_internal_border_width ();
f945b920 665void x_explicitly_set_name ();
01f1ba30
JB
666void x_set_autoraise ();
667void x_set_autolower ();
a3c87d4e 668void x_set_vertical_scroll_bars ();
d043f1a4
RS
669void x_set_visibility ();
670void x_set_menu_bar_lines ();
4701395c 671void x_set_scroll_bar_width ();
943b580d 672void x_set_title ();
eac358ef 673void x_set_unsplittable ();
01f1ba30 674
f676886a 675static struct x_frame_parm_table x_frame_parms[] =
01f1ba30 676{
9fb026ab
RS
677 "auto-raise", x_set_autoraise,
678 "auto-lower", x_set_autolower,
01f1ba30 679 "background-color", x_set_background_color,
01f1ba30 680 "border-color", x_set_border_color,
9fb026ab
RS
681 "border-width", x_set_border_width,
682 "cursor-color", x_set_cursor_color,
dbc4e1c1 683 "cursor-type", x_set_cursor_type,
01f1ba30 684 "font", x_set_font,
9fb026ab
RS
685 "foreground-color", x_set_foreground_color,
686 "icon-name", x_set_icon_name,
687 "icon-type", x_set_icon_type,
01f1ba30 688 "internal-border-width", x_set_internal_border_width,
d043f1a4 689 "menu-bar-lines", x_set_menu_bar_lines,
9fb026ab
RS
690 "mouse-color", x_set_mouse_color,
691 "name", x_explicitly_set_name,
4701395c 692 "scroll-bar-width", x_set_scroll_bar_width,
943b580d 693 "title", x_set_title,
eac358ef 694 "unsplittable", x_set_unsplittable,
9fb026ab
RS
695 "vertical-scroll-bars", x_set_vertical_scroll_bars,
696 "visibility", x_set_visibility,
01f1ba30
JB
697};
698
f676886a 699/* Attach the `x-frame-parameter' properties to
01f1ba30
JB
700 the Lisp symbol names of parameters relevant to X. */
701
702init_x_parm_symbols ()
703{
704 int i;
705
d043f1a4 706 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
f676886a 707 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
01f1ba30
JB
708 make_number (i));
709}
710\f
f9942c9e
JB
711/* Change the parameters of FRAME as specified by ALIST.
712 If a parameter is not specially recognized, do nothing;
713 otherwise call the `x_set_...' function for that parameter. */
d043f1a4 714
f9942c9e
JB
715void
716x_set_frame_parameters (f, alist)
717 FRAME_PTR f;
718 Lisp_Object alist;
719{
720 Lisp_Object tail;
721
722 /* If both of these parameters are present, it's more efficient to
723 set them both at once. So we wait until we've looked at the
724 entire list before we set them. */
725 Lisp_Object width, height;
726
727 /* Same here. */
728 Lisp_Object left, top;
f9942c9e 729
a59e4f3d
RS
730 /* Same with these. */
731 Lisp_Object icon_left, icon_top;
732
f5e70acd
RS
733 /* Record in these vectors all the parms specified. */
734 Lisp_Object *parms;
735 Lisp_Object *values;
736 int i;
e1d962d7 737 int left_no_change = 0, top_no_change = 0;
a59e4f3d 738 int icon_left_no_change = 0, icon_top_no_change = 0;
203c1d73 739
f5e70acd
RS
740 i = 0;
741 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
742 i++;
743
744 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
745 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
f9942c9e 746
f5e70acd
RS
747 /* Extract parm names and values into those vectors. */
748
749 i = 0;
f9942c9e
JB
750 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
751 {
752 Lisp_Object elt, prop, val;
753
754 elt = Fcar (tail);
f5e70acd
RS
755 parms[i] = Fcar (elt);
756 values[i] = Fcdr (elt);
757 i++;
758 }
759
d387c960 760 width = height = top = left = Qunbound;
a59e4f3d 761 icon_left = icon_top = Qunbound;
f9942c9e 762
f5e70acd
RS
763 /* Now process them in reverse of specified order. */
764 for (i--; i >= 0; i--)
765 {
766 Lisp_Object prop, val;
767
768 prop = parms[i];
769 val = values[i];
770
771 if (EQ (prop, Qwidth))
f9942c9e 772 width = val;
f5e70acd 773 else if (EQ (prop, Qheight))
f9942c9e 774 height = val;
f5e70acd 775 else if (EQ (prop, Qtop))
f9942c9e 776 top = val;
f5e70acd 777 else if (EQ (prop, Qleft))
f9942c9e 778 left = val;
a59e4f3d
RS
779 else if (EQ (prop, Qicon_top))
780 icon_top = val;
781 else if (EQ (prop, Qicon_left))
782 icon_left = val;
f9942c9e
JB
783 else
784 {
98381190 785 register Lisp_Object param_index, old_value;
ea96210c 786
98381190
KH
787 param_index = Fget (prop, Qx_frame_parameter);
788 old_value = get_frame_param (f, prop);
f9942c9e 789 store_frame_param (f, prop, val);
40c03e12
KH
790 if (NATNUMP (param_index)
791 && (XFASTINT (param_index)
ea96210c
JB
792 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
793 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
f9942c9e
JB
794 }
795 }
796
11378c41
RS
797 /* Don't die if just one of these was set. */
798 if (EQ (left, Qunbound))
e1d962d7
RS
799 {
800 left_no_change = 1;
7556890b
RS
801 if (f->output_data.x->left_pos < 0)
802 left = Fcons (Qplus, Fcons (make_number (f->output_data.x->left_pos), Qnil));
e1d962d7 803 else
7556890b 804 XSETINT (left, f->output_data.x->left_pos);
e1d962d7 805 }
11378c41 806 if (EQ (top, Qunbound))
e1d962d7
RS
807 {
808 top_no_change = 1;
7556890b
RS
809 if (f->output_data.x->top_pos < 0)
810 top = Fcons (Qplus, Fcons (make_number (f->output_data.x->top_pos), Qnil));
e1d962d7 811 else
7556890b 812 XSETINT (top, f->output_data.x->top_pos);
e1d962d7 813 }
11378c41 814
a59e4f3d
RS
815 /* If one of the icon positions was not set, preserve or default it. */
816 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
817 {
818 icon_left_no_change = 1;
819 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
820 if (NILP (icon_left))
821 XSETINT (icon_left, 0);
822 }
823 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
824 {
825 icon_top_no_change = 1;
826 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
827 if (NILP (icon_top))
828 XSETINT (icon_top, 0);
829 }
830
11378c41
RS
831 /* Don't die if just one of these was set. */
832 if (EQ (width, Qunbound))
093dd95b
RS
833 {
834 if (FRAME_NEW_WIDTH (f))
835 XSETINT (width, FRAME_NEW_WIDTH (f));
836 else
837 XSETINT (width, FRAME_WIDTH (f));
838 }
11378c41 839 if (EQ (height, Qunbound))
093dd95b
RS
840 {
841 if (FRAME_NEW_HEIGHT (f))
842 XSETINT (height, FRAME_NEW_HEIGHT (f));
843 else
844 XSETINT (height, FRAME_HEIGHT (f));
845 }
11378c41 846
499ea23b 847 /* Don't set these parameters unless they've been explicitly
d387c960
JB
848 specified. The window might be mapped or resized while we're in
849 this function, and we don't want to override that unless the lisp
850 code has asked for it.
851
852 Don't set these parameters unless they actually differ from the
853 window's current parameters; the window may not actually exist
854 yet. */
f9942c9e
JB
855 {
856 Lisp_Object frame;
857
1f11a5ca
RS
858 check_frame_size (f, &height, &width);
859
191ed777 860 XSETFRAME (frame, f);
11378c41 861
d387c960 862 if ((NUMBERP (width) && XINT (width) != FRAME_WIDTH (f))
d6f80ae9
RS
863 || (NUMBERP (height) && XINT (height) != FRAME_HEIGHT (f))
864 || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
f9942c9e 865 Fset_frame_size (frame, width, height);
f10f0b79
RS
866
867 if ((!NILP (left) || !NILP (top))
e1d962d7 868 && ! (left_no_change && top_no_change)
7556890b
RS
869 && ! (NUMBERP (left) && XINT (left) == f->output_data.x->left_pos
870 && NUMBERP (top) && XINT (top) == f->output_data.x->top_pos))
f10f0b79 871 {
e1d962d7
RS
872 int leftpos = 0;
873 int toppos = 0;
f10f0b79
RS
874
875 /* Record the signs. */
7556890b 876 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
e1d962d7 877 if (EQ (left, Qminus))
7556890b 878 f->output_data.x->size_hint_flags |= XNegative;
e1d962d7
RS
879 else if (INTEGERP (left))
880 {
881 leftpos = XINT (left);
882 if (leftpos < 0)
7556890b 883 f->output_data.x->size_hint_flags |= XNegative;
e1d962d7
RS
884 }
885 else if (CONSP (left) && EQ (XCONS (left)->car, Qminus)
886 && CONSP (XCONS (left)->cdr)
887 && INTEGERP (XCONS (XCONS (left)->cdr)->car))
888 {
889 leftpos = - XINT (XCONS (XCONS (left)->cdr)->car);
7556890b 890 f->output_data.x->size_hint_flags |= XNegative;
e1d962d7
RS
891 }
892 else if (CONSP (left) && EQ (XCONS (left)->car, Qplus)
893 && CONSP (XCONS (left)->cdr)
894 && INTEGERP (XCONS (XCONS (left)->cdr)->car))
895 {
896 leftpos = XINT (XCONS (XCONS (left)->cdr)->car);
897 }
898
899 if (EQ (top, Qminus))
7556890b 900 f->output_data.x->size_hint_flags |= YNegative;
e1d962d7
RS
901 else if (INTEGERP (top))
902 {
903 toppos = XINT (top);
904 if (toppos < 0)
7556890b 905 f->output_data.x->size_hint_flags |= YNegative;
e1d962d7
RS
906 }
907 else if (CONSP (top) && EQ (XCONS (top)->car, Qminus)
908 && CONSP (XCONS (top)->cdr)
909 && INTEGERP (XCONS (XCONS (top)->cdr)->car))
910 {
911 toppos = - XINT (XCONS (XCONS (top)->cdr)->car);
7556890b 912 f->output_data.x->size_hint_flags |= YNegative;
e1d962d7
RS
913 }
914 else if (CONSP (top) && EQ (XCONS (top)->car, Qplus)
915 && CONSP (XCONS (top)->cdr)
916 && INTEGERP (XCONS (XCONS (top)->cdr)->car))
917 {
918 toppos = XINT (XCONS (XCONS (top)->cdr)->car);
919 }
920
921
922 /* Store the numeric value of the position. */
7556890b
RS
923 f->output_data.x->top_pos = toppos;
924 f->output_data.x->left_pos = leftpos;
e1d962d7 925
7556890b 926 f->output_data.x->win_gravity = NorthWestGravity;
f10f0b79
RS
927
928 /* Actually set that position, and convert to absolute. */
f0e72e79 929 x_set_offset (f, leftpos, toppos, -1);
f10f0b79 930 }
a59e4f3d
RS
931
932 if ((!NILP (icon_left) || !NILP (icon_top))
933 && ! (icon_left_no_change && icon_top_no_change))
934 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
f9942c9e
JB
935 }
936}
01f1ba30 937
08a90d6a 938/* Store the screen positions of frame F into XPTR and YPTR.
e9445337
RS
939 These are the positions of the containing window manager window,
940 not Emacs's own window. */
941
942void
943x_real_positions (f, xptr, yptr)
944 FRAME_PTR f;
945 int *xptr, *yptr;
946{
08a90d6a 947 int win_x, win_y;
e9445337
RS
948 Window child;
949
043835a3
RS
950 /* This is pretty gross, but seems to be the easiest way out of
951 the problem that arises when restarting window-managers. */
952
953#ifdef USE_X_TOOLKIT
7556890b 954 Window outer = XtWindow (f->output_data.x->widget);
043835a3 955#else
7556890b 956 Window outer = f->output_data.x->window_desc;
043835a3
RS
957#endif
958 Window tmp_root_window;
959 Window *tmp_children;
960 int tmp_nchildren;
961
08a90d6a 962 while (1)
e9445337 963 {
ca7bac79
KH
964 x_catch_errors (FRAME_X_DISPLAY (f));
965
08a90d6a 966 XQueryTree (FRAME_X_DISPLAY (f), outer, &tmp_root_window,
7556890b 967 &f->output_data.x->parent_desc,
08a90d6a 968 &tmp_children, &tmp_nchildren);
72dc3bc7 969 XFree ((char *) tmp_children);
08a90d6a
RS
970
971 win_x = win_y = 0;
972
973 /* Find the position of the outside upper-left corner of
974 the inner window, with respect to the outer window. */
7556890b 975 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
08a90d6a
RS
976 {
977 XTranslateCoordinates (FRAME_X_DISPLAY (f),
978
979 /* From-window, to-window. */
e9445337 980#ifdef USE_X_TOOLKIT
7556890b 981 XtWindow (f->output_data.x->widget),
e9445337 982#else
7556890b 983 f->output_data.x->window_desc,
e9445337 984#endif
7556890b 985 f->output_data.x->parent_desc,
e9445337 986
08a90d6a
RS
987 /* From-position, to-position. */
988 0, 0, &win_x, &win_y,
e9445337 989
08a90d6a
RS
990 /* Child of win. */
991 &child);
992
07a63816 993#if 0 /* The values seem to be right without this and wrong with. */
7556890b
RS
994 win_x += f->output_data.x->border_width;
995 win_y += f->output_data.x->border_width;
07a63816 996#endif
08a90d6a 997 }
e9445337 998
08a90d6a
RS
999 /* It is possible for the window returned by the XQueryNotify
1000 to become invalid by the time we call XTranslateCoordinates.
1001 That can happen when you restart some window managers.
1002 If so, we get an error in XTranslateCoordinates.
1003 Detect that and try the whole thing over. */
c4ec904f 1004 if (! x_had_errors_p (FRAME_X_DISPLAY (f)))
845e9d85
RS
1005 {
1006 x_uncatch_errors (FRAME_X_DISPLAY (f));
1007 break;
1008 }
ca7bac79
KH
1009
1010 x_uncatch_errors (FRAME_X_DISPLAY (f));
e9445337 1011 }
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);
6d078211 2842 f->output_data.x->wm_hints.icon_pixmap = None;
179956b9 2843
032e4ebe
RS
2844 /* Request "save yourself" and "delete window" commands from wm. */
2845 {
2846 Atom protocols[2];
b9dc4443
RS
2847 protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
2848 protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
2849 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
032e4ebe 2850 }
9ef48a9d 2851
e373f201
JB
2852 /* x_set_name normally ignores requests to set the name if the
2853 requested name is the same as the current name. This is the one
2854 place where that assumption isn't correct; f->name is set, but
2855 the X server hasn't been told. */
2856 {
98381190 2857 Lisp_Object name;
cf177271 2858 int explicit = f->explicit_name;
e373f201 2859
cf177271 2860 f->explicit_name = 0;
98381190
KH
2861 name = f->name;
2862 f->name = Qnil;
cf177271 2863 x_set_name (f, name, explicit);
e373f201
JB
2864 }
2865
b9dc4443 2866 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 2867 f->output_data.x->text_cursor);
9ef48a9d 2868
01f1ba30
JB
2869 UNBLOCK_INPUT;
2870
fe24a618 2871 if (FRAME_X_WINDOW (f) == 0)
9ef48a9d 2872 error ("Unable to create window");
01f1ba30
JB
2873}
2874
8fc2766b
RS
2875#endif /* not USE_X_TOOLKIT */
2876
01f1ba30
JB
2877/* Handle the icon stuff for this window. Perhaps later we might
2878 want an x_set_icon_position which can be called interactively as
b9dc4443 2879 well. */
01f1ba30
JB
2880
2881static void
f676886a
JB
2882x_icon (f, parms)
2883 struct frame *f;
01f1ba30
JB
2884 Lisp_Object parms;
2885{
f9942c9e 2886 Lisp_Object icon_x, icon_y;
01f1ba30
JB
2887
2888 /* Set the position of the icon. Note that twm groups all
b9dc4443 2889 icons in an icon window. */
cf177271
JB
2890 icon_x = x_get_arg (parms, Qicon_left, 0, 0, number);
2891 icon_y = x_get_arg (parms, Qicon_top, 0, 0, number);
f9942c9e 2892 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
01f1ba30 2893 {
f9942c9e
JB
2894 CHECK_NUMBER (icon_x, 0);
2895 CHECK_NUMBER (icon_y, 0);
01f1ba30 2896 }
f9942c9e 2897 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
01f1ba30 2898 error ("Both left and top icon corners of icon must be specified");
01f1ba30 2899
f9942c9e
JB
2900 BLOCK_INPUT;
2901
fe24a618
JB
2902 if (! EQ (icon_x, Qunbound))
2903 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
f9942c9e 2904
01f1ba30 2905 /* Start up iconic or window? */
49795535
JB
2906 x_wm_set_window_state
2907 (f, (EQ (x_get_arg (parms, Qvisibility, 0, 0, symbol), Qicon)
2908 ? IconicState
2909 : NormalState));
01f1ba30 2910
f468da95
RS
2911 x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
2912 ? f->icon_name
2913 : f->name))->data);
80534dd6 2914
01f1ba30
JB
2915 UNBLOCK_INPUT;
2916}
2917
2918/* Make the GC's needed for this window, setting the
2919 background, border and mouse colors; also create the
2920 mouse cursor and the gray border tile. */
2921
f945b920
JB
2922static char cursor_bits[] =
2923 {
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2928 };
2929
01f1ba30 2930static void
f676886a
JB
2931x_make_gc (f)
2932 struct frame *f;
01f1ba30
JB
2933{
2934 XGCValues gc_values;
2935 GC temp_gc;
2936 XImage tileimage;
01f1ba30 2937
6afb1d07
JB
2938 BLOCK_INPUT;
2939
f676886a 2940 /* Create the GC's of this frame.
9ef48a9d 2941 Note that many default values are used. */
01f1ba30
JB
2942
2943 /* Normal video */
7556890b
RS
2944 gc_values.font = f->output_data.x->font->fid;
2945 gc_values.foreground = f->output_data.x->foreground_pixel;
2946 gc_values.background = f->output_data.x->background_pixel;
9ef48a9d 2947 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
7556890b 2948 f->output_data.x->normal_gc = XCreateGC (FRAME_X_DISPLAY (f),
fe24a618 2949 FRAME_X_WINDOW (f),
01f1ba30
JB
2950 GCLineWidth | GCFont
2951 | GCForeground | GCBackground,
2952 &gc_values);
2953
b9dc4443 2954 /* Reverse video style. */
7556890b
RS
2955 gc_values.foreground = f->output_data.x->background_pixel;
2956 gc_values.background = f->output_data.x->foreground_pixel;
2957 f->output_data.x->reverse_gc = XCreateGC (FRAME_X_DISPLAY (f),
fe24a618 2958 FRAME_X_WINDOW (f),
01f1ba30
JB
2959 GCFont | GCForeground | GCBackground
2960 | GCLineWidth,
2961 &gc_values);
2962
9ef48a9d 2963 /* Cursor has cursor-color background, background-color foreground. */
7556890b
RS
2964 gc_values.foreground = f->output_data.x->background_pixel;
2965 gc_values.background = f->output_data.x->cursor_pixel;
01f1ba30
JB
2966 gc_values.fill_style = FillOpaqueStippled;
2967 gc_values.stipple
b9dc4443
RS
2968 = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
2969 FRAME_X_DISPLAY_INFO (f)->root_window,
01f1ba30 2970 cursor_bits, 16, 16);
7556890b 2971 f->output_data.x->cursor_gc
b9dc4443 2972 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
01f1ba30
JB
2973 (GCFont | GCForeground | GCBackground
2974 | GCFillStyle | GCStipple | GCLineWidth),
2975 &gc_values);
2976
2977 /* Create the gray border tile used when the pointer is not in
f676886a 2978 the frame. Since this depends on the frame's pixel values,
9ef48a9d 2979 this must be done on a per-frame basis. */
7556890b 2980 f->output_data.x->border_tile
d043f1a4 2981 = (XCreatePixmapFromBitmapData
b9dc4443 2982 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
d043f1a4 2983 gray_bits, gray_width, gray_height,
7556890b
RS
2984 f->output_data.x->foreground_pixel,
2985 f->output_data.x->background_pixel,
b9dc4443
RS
2986 DefaultDepth (FRAME_X_DISPLAY (f),
2987 XScreenNumberOfScreen (FRAME_X_SCREEN (f)))));
6afb1d07
JB
2988
2989 UNBLOCK_INPUT;
01f1ba30 2990}
01f1ba30 2991
f676886a 2992DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
01f1ba30 2993 1, 1, 0,
f676886a 2994 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
08a90d6a 2995Returns an Emacs frame object.\n\
f676886a
JB
2996ALIST is an alist of frame parameters.\n\
2997If the parameters specify that the frame should not have a minibuffer,\n\
e22d6b02 2998and do not specify a specific minibuffer window to use,\n\
f676886a 2999then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
08a90d6a
RS
3000be shared by the new frame.\n\
3001\n\
3002This function is an internal primitive--use `make-frame' instead.")
01f1ba30
JB
3003 (parms)
3004 Lisp_Object parms;
3005{
f676886a 3006 struct frame *f;
2365c027 3007 Lisp_Object frame, tem;
01f1ba30
JB
3008 Lisp_Object name;
3009 int minibuffer_only = 0;
3010 long window_prompting = 0;
3011 int width, height;
9ef48a9d 3012 int count = specpdl_ptr - specpdl;
ecaca587 3013 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
b9dc4443
RS
3014 Lisp_Object display;
3015 struct x_display_info *dpyinfo;
a59e4f3d 3016 Lisp_Object parent;
e557f19d 3017 struct kboard *kb;
01f1ba30 3018
11ae94fe 3019 check_x ();
01f1ba30 3020
b7975ee4
KH
3021 /* Use this general default value to start with
3022 until we know if this frame has a specified name. */
3023 Vx_resource_name = Vinvocation_name;
3024
714812eb 3025 display = x_get_arg (parms, Qdisplay, 0, 0, string);
b9dc4443
RS
3026 if (EQ (display, Qunbound))
3027 display = Qnil;
3028 dpyinfo = check_x_display_info (display);
e557f19d
KH
3029#ifdef MULTI_KBOARD
3030 kb = dpyinfo->kboard;
3031#else
3032 kb = &the_only_kboard;
3033#endif
b9dc4443 3034
c2304e02 3035 name = x_get_arg (parms, Qname, "name", "Name", string);
6a5e54e2 3036 if (!STRINGP (name)
cf177271
JB
3037 && ! EQ (name, Qunbound)
3038 && ! NILP (name))
08a90d6a 3039 error ("Invalid frame name--not a string or nil");
01f1ba30 3040
b7975ee4
KH
3041 if (STRINGP (name))
3042 Vx_resource_name = name;
3043
a59e4f3d
RS
3044 /* See if parent window is specified. */
3045 parent = x_get_arg (parms, Qparent_id, NULL, NULL, number);
3046 if (EQ (parent, Qunbound))
3047 parent = Qnil;
3048 if (! NILP (parent))
3049 CHECK_NUMBER (parent, 0);
3050
ecaca587
RS
3051 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
3052 /* No need to protect DISPLAY because that's not used after passing
3053 it to make_frame_without_minibuffer. */
3054 frame = Qnil;
3055 GCPRO4 (parms, parent, name, frame);
cf177271 3056 tem = x_get_arg (parms, Qminibuffer, 0, 0, symbol);
f9942c9e 3057 if (EQ (tem, Qnone) || NILP (tem))
2526c290 3058 f = make_frame_without_minibuffer (Qnil, kb, display);
f9942c9e 3059 else if (EQ (tem, Qonly))
01f1ba30 3060 {
f676886a 3061 f = make_minibuffer_frame ();
01f1ba30
JB
3062 minibuffer_only = 1;
3063 }
6a5e54e2 3064 else if (WINDOWP (tem))
2526c290 3065 f = make_frame_without_minibuffer (tem, kb, display);
f9942c9e
JB
3066 else
3067 f = make_frame (1);
01f1ba30 3068
ecaca587
RS
3069 XSETFRAME (frame, f);
3070
a3c87d4e
JB
3071 /* Note that X Windows does support scroll bars. */
3072 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
179956b9 3073
08a90d6a 3074 f->output_method = output_x_window;
7556890b
RS
3075 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
3076 bzero (f->output_data.x, sizeof (struct x_output));
3077 f->output_data.x->icon_bitmap = -1;
08a90d6a 3078
f468da95 3079 f->icon_name
80534dd6 3080 = x_get_arg (parms, Qicon_name, "iconName", "Title", string);
f468da95
RS
3081 if (! STRINGP (f->icon_name))
3082 f->icon_name = Qnil;
80534dd6 3083
08a90d6a 3084 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
73410c76 3085#ifdef MULTI_KBOARD
e557f19d 3086 FRAME_KBOARD (f) = kb;
73410c76 3087#endif
08a90d6a 3088
a59e4f3d
RS
3089 /* Specify the parent under which to make this X window. */
3090
3091 if (!NILP (parent))
3092 {
7556890b
RS
3093 f->output_data.x->parent_desc = parent;
3094 f->output_data.x->explicit_parent = 1;
a59e4f3d
RS
3095 }
3096 else
3097 {
7556890b
RS
3098 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
3099 f->output_data.x->explicit_parent = 0;
a59e4f3d
RS
3100 }
3101
08a90d6a
RS
3102 /* Note that the frame has no physical cursor right now. */
3103 f->phys_cursor_x = -1;
3104
cf177271
JB
3105 /* Set the name; the functions to which we pass f expect the name to
3106 be set. */
3107 if (EQ (name, Qunbound) || NILP (name))
3108 {
08a90d6a 3109 f->name = build_string (dpyinfo->x_id_name);
cf177271
JB
3110 f->explicit_name = 0;
3111 }
3112 else
3113 {
3114 f->name = name;
3115 f->explicit_name = 1;
9ef48a9d
RS
3116 /* use the frame's title when getting resources for this frame. */
3117 specbind (Qx_resource_name, name);
cf177271 3118 }
01f1ba30 3119
01f1ba30
JB
3120 /* Extract the window parameters from the supplied values
3121 that are needed to determine window geometry. */
d387c960
JB
3122 {
3123 Lisp_Object font;
3124
e5e548e3 3125 font = x_get_arg (parms, Qfont, "font", "Font", string);
6817eab4 3126 BLOCK_INPUT;
e5e548e3
RS
3127 /* First, try whatever font the caller has specified. */
3128 if (STRINGP (font))
e5229110 3129 font = x_new_font (f, XSTRING (font)->data);
e5e548e3
RS
3130 /* Try out a font which we hope has bold and italic variations. */
3131 if (!STRINGP (font))
a6ac02af 3132 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
e5e548e3 3133 if (! STRINGP (font))
a6ac02af 3134 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
e5e548e3
RS
3135 if (! STRINGP (font))
3136 /* This was formerly the first thing tried, but it finds too many fonts
3137 and takes too long. */
3138 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
3139 /* If those didn't work, look for something which will at least work. */
3140 if (! STRINGP (font))
a6ac02af 3141 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
6817eab4
JB
3142 UNBLOCK_INPUT;
3143 if (! STRINGP (font))
e5e548e3
RS
3144 font = build_string ("fixed");
3145
d387c960
JB
3146 x_default_parameter (f, parms, Qfont, font,
3147 "font", "Font", string);
3148 }
9ef48a9d 3149
dd254b21 3150#ifdef USE_X_TOOLKIT
82c90203
RS
3151 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
3152 whereby it fails to get any font. */
7556890b 3153 xlwmenu_default_font = f->output_data.x->font;
dd254b21 3154#endif
82c90203 3155
cf177271
JB
3156 x_default_parameter (f, parms, Qborder_width, make_number (2),
3157 "borderwidth", "BorderWidth", number);
ddf768c3
JB
3158 /* This defaults to 2 in order to match xterm. We recognize either
3159 internalBorderWidth or internalBorder (which is what xterm calls
3160 it). */
3161 if (NILP (Fassq (Qinternal_border_width, parms)))
3162 {
3163 Lisp_Object value;
3164
3165 value = x_get_arg (parms, Qinternal_border_width,
3166 "internalBorder", "BorderWidth", number);
3167 if (! EQ (value, Qunbound))
3168 parms = Fcons (Fcons (Qinternal_border_width, value),
3169 parms);
3170 }
cf177271
JB
3171 x_default_parameter (f, parms, Qinternal_border_width, make_number (2),
3172 "internalBorderWidth", "BorderWidth", number);
a3c87d4e
JB
3173 x_default_parameter (f, parms, Qvertical_scroll_bars, Qt,
3174 "verticalScrollBars", "ScrollBars", boolean);
01f1ba30 3175
b9dc4443 3176 /* Also do the stuff which must be set before the window exists. */
cf177271
JB
3177 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
3178 "foreground", "Foreground", string);
3179 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
3180 "background", "Background", string);
3181 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
3182 "pointerColor", "Foreground", string);
3183 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
3184 "cursorColor", "Foreground", string);
3185 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
3186 "borderColor", "BorderColor", string);
01f1ba30 3187
c7bcb20d 3188 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
e1d962d7 3189 "menuBar", "MenuBar", number);
dff9a538 3190 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
4701395c 3191 "scrollBarWidth", "ScrollBarWidth", number);
79873d50
RS
3192 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
3193 "bufferPredicate", "BufferPredicate", symbol);
c2304e02 3194 x_default_parameter (f, parms, Qtitle, Qnil,
ce3cadf4 3195 "title", "Title", string);
90eb1019 3196
7556890b 3197 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
f676886a 3198 window_prompting = x_figure_window_size (f, parms);
01f1ba30 3199
f83f10ba 3200 if (window_prompting & XNegative)
2365c027 3201 {
f83f10ba 3202 if (window_prompting & YNegative)
7556890b 3203 f->output_data.x->win_gravity = SouthEastGravity;
f83f10ba 3204 else
7556890b 3205 f->output_data.x->win_gravity = NorthEastGravity;
f83f10ba
RS
3206 }
3207 else
3208 {
3209 if (window_prompting & YNegative)
7556890b 3210 f->output_data.x->win_gravity = SouthWestGravity;
f83f10ba 3211 else
7556890b 3212 f->output_data.x->win_gravity = NorthWestGravity;
2365c027
RS
3213 }
3214
7556890b 3215 f->output_data.x->size_hint_flags = window_prompting;
38d22040 3216
a7f7d550
FP
3217#ifdef USE_X_TOOLKIT
3218 x_window (f, window_prompting, minibuffer_only);
3219#else
f676886a 3220 x_window (f);
a7f7d550 3221#endif
f676886a
JB
3222 x_icon (f, parms);
3223 x_make_gc (f);
ea96210c 3224 init_frame_faces (f);
01f1ba30 3225
f9942c9e
JB
3226 /* We need to do this after creating the X window, so that the
3227 icon-creation functions can say whose icon they're describing. */
cf177271 3228 x_default_parameter (f, parms, Qicon_type, Qnil,
6998a3b4 3229 "bitmapIcon", "BitmapIcon", symbol);
f9942c9e 3230
cf177271
JB
3231 x_default_parameter (f, parms, Qauto_raise, Qnil,
3232 "autoRaise", "AutoRaiseLower", boolean);
3233 x_default_parameter (f, parms, Qauto_lower, Qnil,
3234 "autoLower", "AutoRaiseLower", boolean);
dbc4e1c1
JB
3235 x_default_parameter (f, parms, Qcursor_type, Qbox,
3236 "cursorType", "CursorType", symbol);
f9942c9e 3237
f676886a 3238 /* Dimensions, especially f->height, must be done via change_frame_size.
01f1ba30 3239 Change will not be effected unless different from the current
b9dc4443 3240 f->height. */
f676886a
JB
3241 width = f->width;
3242 height = f->height;
3243 f->height = f->width = 0;
f9942c9e 3244 change_frame_size (f, height, width, 1, 0);
d043f1a4 3245
97787173
RS
3246 /* Tell the server what size and position, etc, we want,
3247 and how badly we want them. */
01f1ba30 3248 BLOCK_INPUT;
7989f084 3249 x_wm_set_size_hint (f, window_prompting, 0);
01f1ba30
JB
3250 UNBLOCK_INPUT;
3251
cf177271 3252 tem = x_get_arg (parms, Qunsplittable, 0, 0, boolean);
f676886a 3253 f->no_split = minibuffer_only || EQ (tem, Qt);
01f1ba30 3254
f8ea8499
PR
3255 UNGCPRO;
3256
59d61058
RS
3257 /* It is now ok to make the frame official
3258 even if we get an error below.
3259 And the frame needs to be on Vframe_list
3260 or making it visible won't work. */
3261 Vframe_list = Fcons (frame, Vframe_list);
3262
08a90d6a
RS
3263 /* Now that the frame is official, it counts as a reference to
3264 its display. */
3265 FRAME_X_DISPLAY_INFO (f)->reference_count++;
3266
d043f1a4 3267 /* Make the window appear on the frame and enable display,
a59e4f3d
RS
3268 unless the caller says not to. However, with explicit parent,
3269 Emacs cannot control visibility, so don't try. */
7556890b 3270 if (! f->output_data.x->explicit_parent)
a59e4f3d
RS
3271 {
3272 Lisp_Object visibility;
49795535 3273
a59e4f3d
RS
3274 visibility = x_get_arg (parms, Qvisibility, 0, 0, symbol);
3275 if (EQ (visibility, Qunbound))
3276 visibility = Qt;
49795535 3277
a59e4f3d
RS
3278 if (EQ (visibility, Qicon))
3279 x_iconify_frame (f);
3280 else if (! NILP (visibility))
3281 x_make_frame_visible (f);
3282 else
3283 /* Must have been Qnil. */
3284 ;
3285 }
01f1ba30 3286
9ef48a9d 3287 return unbind_to (count, frame);
01f1ba30
JB
3288}
3289
0d17d282
KH
3290/* FRAME is used only to get a handle on the X display. We don't pass the
3291 display info directly because we're called from frame.c, which doesn't
3292 know about that structure. */
87498171 3293Lisp_Object
0d17d282
KH
3294x_get_focus_frame (frame)
3295 struct frame *frame;
87498171 3296{
0d17d282 3297 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
87498171 3298 Lisp_Object xfocus;
0d17d282 3299 if (! dpyinfo->x_focus_frame)
87498171
KH
3300 return Qnil;
3301
0d17d282 3302 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
87498171
KH
3303 return xfocus;
3304}
3305
f676886a 3306DEFUN ("focus-frame", Ffocus_frame, Sfocus_frame, 1, 1, 0,
9ae77b81 3307 "This function is obsolete, and does nothing.")
f676886a
JB
3308 (frame)
3309 Lisp_Object frame;
01f1ba30 3310{
01f1ba30
JB
3311 return Qnil;
3312}
3313
f676886a 3314DEFUN ("unfocus-frame", Funfocus_frame, Sunfocus_frame, 0, 0, 0,
9ae77b81 3315 "This function is obsolete, and does nothing.")
01f1ba30
JB
3316 ()
3317{
01f1ba30
JB
3318 return Qnil;
3319}
3320\f
f0614854
JB
3321DEFUN ("x-list-fonts", Fx_list_fonts, Sx_list_fonts, 1, 3, 0,
3322 "Return a list of the names of available fonts matching PATTERN.\n\
3323If optional arguments FACE and FRAME are specified, return only fonts\n\
3324the same size as FACE on FRAME.\n\
3325\n\
3326PATTERN is a string, perhaps with wildcard characters;\n\
3327 the * character matches any substring, and\n\
3328 the ? character matches any single character.\n\
3329 PATTERN is case-insensitive.\n\
08a90d6a 3330FACE is a face name--a symbol.\n\
f0614854
JB
3331\n\
3332The return value is a list of strings, suitable as arguments to\n\
3333set-face-font.\n\
3334\n\
410d4321
RS
3335Fonts Emacs can't use (i.e. proportional fonts) may or may not be excluded\n\
3336even if they match PATTERN and FACE.")
f0614854
JB
3337 (pattern, face, frame)
3338 Lisp_Object pattern, face, frame;
3339{
3340 int num_fonts;
3341 char **names;
40a5b2e1 3342#ifndef BROKEN_XLISTFONTSWITHINFO
f0614854 3343 XFontStruct *info;
40a5b2e1 3344#endif
f0614854
JB
3345 XFontStruct *size_ref;
3346 Lisp_Object list;
f1c16f36 3347 FRAME_PTR f;
f0614854 3348
7fc9de26 3349 check_x ();
f0614854
JB
3350 CHECK_STRING (pattern, 0);
3351 if (!NILP (face))
3352 CHECK_SYMBOL (face, 1);
f0614854 3353
b9dc4443 3354 f = check_x_frame (frame);
f1c16f36
RS
3355
3356 /* Determine the width standard for comparison with the fonts we find. */
3357
f0614854
JB
3358 if (NILP (face))
3359 size_ref = 0;
3360 else
3361 {
90eb1019
RS
3362 int face_id;
3363
3364 /* Don't die if we get called with a terminal frame. */
3365 if (! FRAME_X_P (f))
1c59f5df 3366 error ("Non-X frame used in `x-list-fonts'");
90eb1019
RS
3367
3368 face_id = face_name_id_number (f, face);
f0614854 3369
a081bd37
JB
3370 if (face_id < 0 || face_id >= FRAME_N_PARAM_FACES (f)
3371 || FRAME_PARAM_FACES (f) [face_id] == 0)
7556890b 3372 size_ref = f->output_data.x->font;
6998a3b4
RS
3373 else
3374 {
a081bd37 3375 size_ref = FRAME_PARAM_FACES (f) [face_id]->font;
6998a3b4 3376 if (size_ref == (XFontStruct *) (~0))
7556890b 3377 size_ref = f->output_data.x->font;
6998a3b4 3378 }
f0614854
JB
3379 }
3380
f1c16f36 3381 /* See if we cached the result for this particular query. */
08a90d6a
RS
3382 list = Fassoc (pattern,
3383 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr);
f1c16f36
RS
3384
3385 /* We have info in the cache for this PATTERN. */
3386 if (!NILP (list))
3387 {
3388 Lisp_Object tem, newlist;
3389
3390 /* We have info about this pattern. */
3391 list = XCONS (list)->cdr;
3392
3393 if (size_ref == 0)
3394 return list;
3395
3396 BLOCK_INPUT;
3397
3398 /* Filter the cached info and return just the fonts that match FACE. */
3399 newlist = Qnil;
3400 for (tem = list; CONSP (tem); tem = XCONS (tem)->cdr)
3401 {
3402 XFontStruct *thisinfo;
3403
25c26e74
RS
3404 x_catch_errors (FRAME_X_DISPLAY (f));
3405
3406 thisinfo = XLoadQueryFont (FRAME_X_DISPLAY (f),
f1c16f36
RS
3407 XSTRING (XCONS (tem)->car)->data);
3408
25c26e74
RS
3409 x_check_errors (FRAME_X_DISPLAY (f), "XLoadQueryFont failure: %s");
3410 x_uncatch_errors (FRAME_X_DISPLAY (f));
3411
3412 if (thisinfo && same_size_fonts (thisinfo, size_ref))
f1c16f36
RS
3413 newlist = Fcons (XCONS (tem)->car, newlist);
3414
a03a26db
KH
3415 if (thisinfo != 0)
3416 XFreeFont (FRAME_X_DISPLAY (f), thisinfo);
f1c16f36
RS
3417 }
3418
3419 UNBLOCK_INPUT;
3420
3421 return newlist;
3422 }
3423
f0614854 3424 BLOCK_INPUT;
f58534a3 3425
25c26e74
RS
3426 x_catch_errors (FRAME_X_DISPLAY (f));
3427
f58534a3 3428 /* Solaris 2.3 has a bug in XListFontsWithInfo. */
40a5b2e1
KH
3429#ifndef BROKEN_XLISTFONTSWITHINFO
3430 if (size_ref)
3431 names = XListFontsWithInfo (FRAME_X_DISPLAY (f),
3432 XSTRING (pattern)->data,
3433 2000, /* maxnames */
3434 &num_fonts, /* count_return */
3435 &info); /* info_return */
3436 else
f58534a3 3437#endif
40a5b2e1
KH
3438 names = XListFonts (FRAME_X_DISPLAY (f),
3439 XSTRING (pattern)->data,
3440 2000, /* maxnames */
3441 &num_fonts); /* count_return */
3442
25c26e74
RS
3443 x_check_errors (FRAME_X_DISPLAY (f), "XListFonts failure: %s");
3444 x_uncatch_errors (FRAME_X_DISPLAY (f));
3445
f0614854
JB
3446 UNBLOCK_INPUT;
3447
a9107360 3448 list = Qnil;
f0614854 3449
a9107360
RS
3450 if (names)
3451 {
a9107360 3452 int i;
f1c16f36
RS
3453 Lisp_Object full_list;
3454
3455 /* Make a list of all the fonts we got back.
3456 Store that in the font cache for the display. */
3457 full_list = Qnil;
3458 for (i = 0; i < num_fonts; i++)
3459 full_list = Fcons (build_string (names[i]), full_list);
08a90d6a 3460 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr
f1c16f36 3461 = Fcons (Fcons (pattern, full_list),
08a90d6a 3462 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr);
a9107360 3463
f1c16f36
RS
3464 /* Make a list of the fonts that have the right width. */
3465 list = Qnil;
a9107360 3466 for (i = 0; i < num_fonts; i++)
f58534a3 3467 {
40a5b2e1 3468 int keeper;
74712156 3469
40a5b2e1
KH
3470 if (!size_ref)
3471 keeper = 1;
3472 else
3473 {
f58534a3 3474#ifdef BROKEN_XLISTFONTSWITHINFO
40a5b2e1
KH
3475 XFontStruct *thisinfo;
3476
3477 BLOCK_INPUT;
25c26e74
RS
3478
3479 x_catch_errors (FRAME_X_DISPLAY (f));
40a5b2e1 3480 thisinfo = XLoadQueryFont (FRAME_X_DISPLAY (f), names[i]);
25c26e74
RS
3481 x_check_errors (FRAME_X_DISPLAY (f),
3482 "XLoadQueryFont failure: %s");
3483 x_uncatch_errors (FRAME_X_DISPLAY (f));
3484
40a5b2e1
KH
3485 UNBLOCK_INPUT;
3486
3487 keeper = thisinfo && same_size_fonts (thisinfo, size_ref);
e74c4350
RS
3488 BLOCK_INPUT;
3489 if (thisinfo && ! keeper)
3490 XFreeFont (FRAME_X_DISPLAY (f), thisinfo);
3491 else if (thisinfo)
3492 XFreeFontInfo (NULL, thisinfo, 1);
3493 UNBLOCK_INPUT;
f58534a3 3494#else
40a5b2e1 3495 keeper = same_size_fonts (&info[i], size_ref);
f58534a3 3496#endif
40a5b2e1
KH
3497 }
3498 if (keeper)
f1c16f36 3499 list = Fcons (build_string (names[i]), list);
f58534a3 3500 }
f1c16f36 3501 list = Fnreverse (list);
a9107360 3502
f58534a3 3503 BLOCK_INPUT;
40a5b2e1
KH
3504#ifndef BROKEN_XLISTFONTSWITHINFO
3505 if (size_ref)
3506 XFreeFontInfo (names, info, num_fonts);
3507 else
f58534a3 3508#endif
40a5b2e1 3509 XFreeFontNames (names);
f58534a3 3510 UNBLOCK_INPUT;
a9107360 3511 }
f0614854
JB
3512
3513 return list;
3514}
3515
3516\f
b9dc4443 3517DEFUN ("x-color-defined-p", Fx_color_defined_p, Sx_color_defined_p, 1, 2, 0,
e207bc6e 3518 "Return non-nil if color COLOR is supported on frame FRAME.\n\
08a90d6a 3519If FRAME is omitted or nil, use the selected frame.")
b9dc4443
RS
3520 (color, frame)
3521 Lisp_Object color, frame;
e12d55b2 3522{
b9dc4443
RS
3523 XColor foo;
3524 FRAME_PTR f = check_x_frame (frame);
e12d55b2 3525
b9dc4443
RS
3526 CHECK_STRING (color, 1);
3527
3528 if (defined_color (f, XSTRING (color)->data, &foo, 0))
e12d55b2
RS
3529 return Qt;
3530 else
3531 return Qnil;
3532}
3533
b9dc4443
RS
3534DEFUN ("x-color-values", Fx_color_values, Sx_color_values, 1, 2, 0,
3535 "Return a description of the color named COLOR on frame FRAME.\n\
e12d55b2 3536The value is a list of integer RGB values--(RED GREEN BLUE).\n\
a59e4f3d
RS
3537These values appear to range from 0 to 65280 or 65535, depending\n\
3538on the system; white is (65280 65280 65280) or (65535 65535 65535).\n\
08a90d6a 3539If FRAME is omitted or nil, use the selected frame.")
b9dc4443
RS
3540 (color, frame)
3541 Lisp_Object color, frame;
01f1ba30 3542{
b9dc4443
RS
3543 XColor foo;
3544 FRAME_PTR f = check_x_frame (frame);
3545
3546 CHECK_STRING (color, 1);
01f1ba30 3547
b9dc4443 3548 if (defined_color (f, XSTRING (color)->data, &foo, 0))
57c82a63
RS
3549 {
3550 Lisp_Object rgb[3];
3551
3552 rgb[0] = make_number (foo.red);
3553 rgb[1] = make_number (foo.green);
3554 rgb[2] = make_number (foo.blue);
3555 return Flist (3, rgb);
3556 }
01f1ba30
JB
3557 else
3558 return Qnil;
3559}
3560
b9dc4443 3561DEFUN ("x-display-color-p", Fx_display_color_p, Sx_display_color_p, 0, 1, 0,
08a90d6a
RS
3562 "Return t if the X display supports color.\n\
3563The optional argument DISPLAY specifies which display to ask about.\n\
3564DISPLAY should be either a frame or a display name (a string).\n\
3565If omitted or nil, that stands for the selected frame's display.")
3566 (display)
3567 Lisp_Object display;
01f1ba30 3568{
08a90d6a 3569 struct x_display_info *dpyinfo = check_x_display_info (display);
11ae94fe 3570
b9dc4443 3571 if (dpyinfo->n_planes <= 2)
01f1ba30
JB
3572 return Qnil;
3573
b9dc4443 3574 switch (dpyinfo->visual->class)
01f1ba30
JB
3575 {
3576 case StaticColor:
3577 case PseudoColor:
3578 case TrueColor:
3579 case DirectColor:
3580 return Qt;
3581
3582 default:
3583 return Qnil;
3584 }
3585}
3586
d0c9d219 3587DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
b9dc4443 3588 0, 1, 0,
08a90d6a 3589 "Return t if the X display supports shades of gray.\n\
ae6b58f9 3590Note that color displays do support shades of gray.\n\
08a90d6a
RS
3591The optional argument DISPLAY specifies which display to ask about.\n\
3592DISPLAY should be either a frame or a display name (a string).\n\
3593If omitted or nil, that stands for the selected frame's display.")
3594 (display)
3595 Lisp_Object display;
d0c9d219 3596{
08a90d6a 3597 struct x_display_info *dpyinfo = check_x_display_info (display);
d0c9d219 3598
ae6b58f9 3599 if (dpyinfo->n_planes <= 1)
b9dc4443
RS
3600 return Qnil;
3601
ae6b58f9
RS
3602 switch (dpyinfo->visual->class)
3603 {
3604 case StaticColor:
3605 case PseudoColor:
3606 case TrueColor:
3607 case DirectColor:
3608 case StaticGray:
3609 case GrayScale:
3610 return Qt;
3611
3612 default:
3613 return Qnil;
3614 }
d0c9d219
RS
3615}
3616
41beb8fc
RS
3617DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
3618 0, 1, 0,
08a90d6a
RS
3619 "Returns the width in pixels of the X display DISPLAY.\n\
3620The optional argument DISPLAY specifies which display to ask about.\n\
3621DISPLAY should be either a frame or a display name (a string).\n\
3622If omitted or nil, that stands for the selected frame's display.")
3623 (display)
3624 Lisp_Object display;
41beb8fc 3625{
08a90d6a 3626 struct x_display_info *dpyinfo = check_x_display_info (display);
b9dc4443
RS
3627
3628 return make_number (dpyinfo->width);
41beb8fc
RS
3629}
3630
3631DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
3632 Sx_display_pixel_height, 0, 1, 0,
08a90d6a
RS
3633 "Returns the height in pixels of the X display DISPLAY.\n\
3634The optional argument DISPLAY specifies which display to ask about.\n\
3635DISPLAY should be either a frame or a display name (a string).\n\
3636If omitted or nil, that stands for the selected frame's display.")
3637 (display)
3638 Lisp_Object display;
41beb8fc 3639{
08a90d6a 3640 struct x_display_info *dpyinfo = check_x_display_info (display);
b9dc4443
RS
3641
3642 return make_number (dpyinfo->height);
41beb8fc
RS
3643}
3644
3645DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
3646 0, 1, 0,
08a90d6a
RS
3647 "Returns the number of bitplanes of the X display DISPLAY.\n\
3648The optional argument DISPLAY specifies which display to ask about.\n\
3649DISPLAY should be either a frame or a display name (a string).\n\
3650If omitted or nil, that stands for the selected frame's display.")
3651 (display)
3652 Lisp_Object display;
41beb8fc 3653{
08a90d6a 3654 struct x_display_info *dpyinfo = check_x_display_info (display);
b9dc4443
RS
3655
3656 return make_number (dpyinfo->n_planes);
41beb8fc
RS
3657}
3658
3659DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
3660 0, 1, 0,
08a90d6a
RS
3661 "Returns the number of color cells of the X display DISPLAY.\n\
3662The optional argument DISPLAY specifies which display to ask about.\n\
3663DISPLAY should be either a frame or a display name (a string).\n\
3664If omitted or nil, that stands for the selected frame's display.")
3665 (display)
3666 Lisp_Object display;
41beb8fc 3667{
08a90d6a 3668 struct x_display_info *dpyinfo = check_x_display_info (display);
b9dc4443
RS
3669
3670 return make_number (DisplayCells (dpyinfo->display,
3671 XScreenNumberOfScreen (dpyinfo->screen)));
41beb8fc
RS
3672}
3673
9d317b2c
RS
3674DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
3675 Sx_server_max_request_size,
3676 0, 1, 0,
08a90d6a
RS
3677 "Returns the maximum request size of the X server of display DISPLAY.\n\
3678The optional argument DISPLAY specifies which display to ask about.\n\
3679DISPLAY should be either a frame or a display name (a string).\n\
3680If omitted or nil, that stands for the selected frame's display.")
3681 (display)
3682 Lisp_Object display;
9d317b2c 3683{
08a90d6a 3684 struct x_display_info *dpyinfo = check_x_display_info (display);
b9dc4443
RS
3685
3686 return make_number (MAXREQUEST (dpyinfo->display));
9d317b2c
RS
3687}
3688
41beb8fc 3689DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
08a90d6a
RS
3690 "Returns the vendor ID string of the X server of display DISPLAY.\n\
3691The optional argument DISPLAY specifies which display to ask about.\n\
3692DISPLAY should be either a frame or a display name (a string).\n\
3693If omitted or nil, that stands for the selected frame's display.")
3694 (display)
3695 Lisp_Object display;
41beb8fc 3696{
08a90d6a 3697 struct x_display_info *dpyinfo = check_x_display_info (display);
b9dc4443
RS
3698 char *vendor = ServerVendor (dpyinfo->display);
3699
41beb8fc
RS
3700 if (! vendor) vendor = "";
3701 return build_string (vendor);
3702}
3703
3704DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
08a90d6a 3705 "Returns the version numbers of the X server of display DISPLAY.\n\
41beb8fc
RS
3706The value is a list of three integers: the major and minor\n\
3707version numbers of the X Protocol in use, and the vendor-specific release\n\
08a90d6a
RS
3708number. See also the function `x-server-vendor'.\n\n\
3709The optional argument DISPLAY specifies which display to ask about.\n\
3710DISPLAY should be either a frame or a display name (a string).\n\
3711If omitted or nil, that stands for the selected frame's display.")
3712 (display)
3713 Lisp_Object display;
41beb8fc 3714{
08a90d6a 3715 struct x_display_info *dpyinfo = check_x_display_info (display);
b9dc4443 3716 Display *dpy = dpyinfo->display;
11ae94fe 3717
41beb8fc
RS
3718 return Fcons (make_number (ProtocolVersion (dpy)),
3719 Fcons (make_number (ProtocolRevision (dpy)),
3720 Fcons (make_number (VendorRelease (dpy)), Qnil)));
3721}
3722
3723DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
08a90d6a
RS
3724 "Returns the number of screens on the X server of display DISPLAY.\n\
3725The optional argument DISPLAY specifies which display to ask about.\n\
3726DISPLAY should be either a frame or a display name (a string).\n\
3727If omitted or nil, that stands for the selected frame's display.")
3728 (display)
3729 Lisp_Object display;
41beb8fc 3730{
08a90d6a 3731 struct x_display_info *dpyinfo = check_x_display_info (display);
b9dc4443
RS
3732
3733 return make_number (ScreenCount (dpyinfo->display));
41beb8fc
RS
3734}
3735
3736DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
08a90d6a
RS
3737 "Returns the height in millimeters of the X display DISPLAY.\n\
3738The optional argument DISPLAY specifies which display to ask about.\n\
3739DISPLAY should be either a frame or a display name (a string).\n\
3740If omitted or nil, that stands for the selected frame's display.")
3741 (display)
3742 Lisp_Object display;
41beb8fc 3743{
08a90d6a 3744 struct x_display_info *dpyinfo = check_x_display_info (display);
b9dc4443
RS
3745
3746 return make_number (HeightMMOfScreen (dpyinfo->screen));
41beb8fc
RS
3747}
3748
3749DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
08a90d6a
RS
3750 "Returns the width in millimeters of the X display DISPLAY.\n\
3751The optional argument DISPLAY specifies which display to ask about.\n\
3752DISPLAY should be either a frame or a display name (a string).\n\
3753If omitted or nil, that stands for the selected frame's display.")
3754 (display)
3755 Lisp_Object display;
41beb8fc 3756{
08a90d6a 3757 struct x_display_info *dpyinfo = check_x_display_info (display);
b9dc4443
RS
3758
3759 return make_number (WidthMMOfScreen (dpyinfo->screen));
41beb8fc
RS
3760}
3761
3762DEFUN ("x-display-backing-store", Fx_display_backing_store,
3763 Sx_display_backing_store, 0, 1, 0,
08a90d6a
RS
3764 "Returns an indication of whether X display DISPLAY does backing store.\n\
3765The value may be `always', `when-mapped', or `not-useful'.\n\
3766The optional argument DISPLAY specifies which display to ask about.\n\
3767DISPLAY should be either a frame or a display name (a string).\n\
3768If omitted or nil, that stands for the selected frame's display.")
3769 (display)
3770 Lisp_Object display;
41beb8fc 3771{
08a90d6a 3772 struct x_display_info *dpyinfo = check_x_display_info (display);
11ae94fe 3773
b9dc4443 3774 switch (DoesBackingStore (dpyinfo->screen))
41beb8fc
RS
3775 {
3776 case Always:
3777 return intern ("always");
3778
3779 case WhenMapped:
3780 return intern ("when-mapped");
3781
3782 case NotUseful:
3783 return intern ("not-useful");
3784
3785 default:
3786 error ("Strange value for BackingStore parameter of screen");
3787 }
3788}
3789
3790DEFUN ("x-display-visual-class", Fx_display_visual_class,
3791 Sx_display_visual_class, 0, 1, 0,
08a90d6a 3792 "Returns the visual class of the X display DISPLAY.\n\
41beb8fc 3793The value is one of the symbols `static-gray', `gray-scale',\n\
08a90d6a
RS
3794`static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
3795The optional argument DISPLAY specifies which display to ask about.\n\
3796DISPLAY should be either a frame or a display name (a string).\n\
3797If omitted or nil, that stands for the selected frame's display.")
3798 (display)
3799 Lisp_Object display;
41beb8fc 3800{
08a90d6a 3801 struct x_display_info *dpyinfo = check_x_display_info (display);
11ae94fe 3802
b9dc4443 3803 switch (dpyinfo->visual->class)
41beb8fc
RS
3804 {
3805 case StaticGray: return (intern ("static-gray"));
3806 case GrayScale: return (intern ("gray-scale"));
3807 case StaticColor: return (intern ("static-color"));
3808 case PseudoColor: return (intern ("pseudo-color"));
3809 case TrueColor: return (intern ("true-color"));
3810 case DirectColor: return (intern ("direct-color"));
3811 default:
3812 error ("Display has an unknown visual class");
3813 }
3814}
3815
3816DEFUN ("x-display-save-under", Fx_display_save_under,
3817 Sx_display_save_under, 0, 1, 0,
08a90d6a
RS
3818 "Returns t if the X display DISPLAY supports the save-under feature.\n\
3819The optional argument DISPLAY specifies which display to ask about.\n\
3820DISPLAY should be either a frame or a display name (a string).\n\
3821If omitted or nil, that stands for the selected frame's display.")
3822 (display)
3823 Lisp_Object display;
41beb8fc 3824{
08a90d6a 3825 struct x_display_info *dpyinfo = check_x_display_info (display);
11ae94fe 3826
b9dc4443 3827 if (DoesSaveUnders (dpyinfo->screen) == True)
41beb8fc
RS
3828 return Qt;
3829 else
3830 return Qnil;
3831}
3832\f
b9dc4443 3833int
55caf99c
RS
3834x_pixel_width (f)
3835 register struct frame *f;
01f1ba30 3836{
55caf99c 3837 return PIXEL_WIDTH (f);
01f1ba30
JB
3838}
3839
b9dc4443 3840int
55caf99c
RS
3841x_pixel_height (f)
3842 register struct frame *f;
01f1ba30 3843{
55caf99c
RS
3844 return PIXEL_HEIGHT (f);
3845}
3846
b9dc4443 3847int
55caf99c
RS
3848x_char_width (f)
3849 register struct frame *f;
3850{
7556890b 3851 return FONT_WIDTH (f->output_data.x->font);
55caf99c
RS
3852}
3853
b9dc4443 3854int
55caf99c
RS
3855x_char_height (f)
3856 register struct frame *f;
3857{
7556890b 3858 return f->output_data.x->line_height;
01f1ba30 3859}
b9dc4443
RS
3860
3861int
3862x_screen_planes (frame)
3863 Lisp_Object frame;
3864{
3865 return FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_planes;
3866}
01f1ba30 3867\f
85ffea93
RS
3868#if 0 /* These no longer seem like the right way to do things. */
3869
f676886a 3870/* Draw a rectangle on the frame with left top corner including
01f1ba30 3871 the character specified by LEFT_CHAR and TOP_CHAR. The rectangle is
b9dc4443 3872 CHARS by LINES wide and long and is the color of the cursor. */
01f1ba30
JB
3873
3874void
f676886a
JB
3875x_rectangle (f, gc, left_char, top_char, chars, lines)
3876 register struct frame *f;
01f1ba30
JB
3877 GC gc;
3878 register int top_char, left_char, chars, lines;
3879{
3880 int width;
3881 int height;
7556890b
RS
3882 int left = (left_char * FONT_WIDTH (f->output_data.x->font)
3883 + f->output_data.x->internal_border_width);
3884 int top = (top_char * f->output_data.x->line_height
3885 + f->output_data.x->internal_border_width);
01f1ba30
JB
3886
3887 if (chars < 0)
7556890b 3888 width = FONT_WIDTH (f->output_data.x->font) / 2;
01f1ba30 3889 else
7556890b 3890 width = FONT_WIDTH (f->output_data.x->font) * chars;
01f1ba30 3891 if (lines < 0)
7556890b 3892 height = f->output_data.x->line_height / 2;
01f1ba30 3893 else
7556890b 3894 height = f->output_data.x->line_height * lines;
01f1ba30 3895
b9dc4443 3896 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
01f1ba30
JB
3897 gc, left, top, width, height);
3898}
3899
3900DEFUN ("x-draw-rectangle", Fx_draw_rectangle, Sx_draw_rectangle, 5, 5, 0,
f676886a 3901 "Draw a rectangle on FRAME between coordinates specified by\n\
01f1ba30 3902numbers X0, Y0, X1, Y1 in the cursor pixel.")
f676886a
JB
3903 (frame, X0, Y0, X1, Y1)
3904 register Lisp_Object frame, X0, X1, Y0, Y1;
01f1ba30
JB
3905{
3906 register int x0, y0, x1, y1, top, left, n_chars, n_lines;
3907
f676886a 3908 CHECK_LIVE_FRAME (frame, 0);
01f1ba30
JB
3909 CHECK_NUMBER (X0, 0);
3910 CHECK_NUMBER (Y0, 1);
3911 CHECK_NUMBER (X1, 2);
3912 CHECK_NUMBER (Y1, 3);
3913
3914 x0 = XINT (X0);
3915 x1 = XINT (X1);
3916 y0 = XINT (Y0);
3917 y1 = XINT (Y1);
3918
3919 if (y1 > y0)
3920 {
3921 top = y0;
3922 n_lines = y1 - y0 + 1;
3923 }
3924 else
3925 {
3926 top = y1;
3927 n_lines = y0 - y1 + 1;
3928 }
3929
3930 if (x1 > x0)
3931 {
3932 left = x0;
3933 n_chars = x1 - x0 + 1;
3934 }
3935 else
3936 {
3937 left = x1;
3938 n_chars = x0 - x1 + 1;
3939 }
3940
3941 BLOCK_INPUT;
7556890b 3942 x_rectangle (XFRAME (frame), XFRAME (frame)->output_data.x->cursor_gc,
01f1ba30
JB
3943 left, top, n_chars, n_lines);
3944 UNBLOCK_INPUT;
3945
3946 return Qt;
3947}
3948
3949DEFUN ("x-erase-rectangle", Fx_erase_rectangle, Sx_erase_rectangle, 5, 5, 0,
f676886a 3950 "Draw a rectangle drawn on FRAME between coordinates\n\
01f1ba30 3951X0, Y0, X1, Y1 in the regular background-pixel.")
f676886a
JB
3952 (frame, X0, Y0, X1, Y1)
3953 register Lisp_Object frame, X0, Y0, X1, Y1;
01f1ba30
JB
3954{
3955 register int x0, y0, x1, y1, top, left, n_chars, n_lines;
3956
b9dc4443 3957 CHECK_LIVE_FRAME (frame, 0);
01f1ba30
JB
3958 CHECK_NUMBER (X0, 0);
3959 CHECK_NUMBER (Y0, 1);
3960 CHECK_NUMBER (X1, 2);
3961 CHECK_NUMBER (Y1, 3);
3962
3963 x0 = XINT (X0);
3964 x1 = XINT (X1);
3965 y0 = XINT (Y0);
3966 y1 = XINT (Y1);
3967
3968 if (y1 > y0)
3969 {
3970 top = y0;
3971 n_lines = y1 - y0 + 1;
3972 }
3973 else
3974 {
3975 top = y1;
3976 n_lines = y0 - y1 + 1;
3977 }
3978
3979 if (x1 > x0)
3980 {
3981 left = x0;
3982 n_chars = x1 - x0 + 1;
3983 }
3984 else
3985 {
3986 left = x1;
3987 n_chars = x0 - x1 + 1;
3988 }
3989
3990 BLOCK_INPUT;
7556890b 3991 x_rectangle (XFRAME (frame), XFRAME (frame)->output_data.x->reverse_gc,
01f1ba30
JB
3992 left, top, n_chars, n_lines);
3993 UNBLOCK_INPUT;
3994
3995 return Qt;
3996}
3997
3998/* Draw lines around the text region beginning at the character position
3999 TOP_X, TOP_Y and ending at BOTTOM_X and BOTTOM_Y. GC specifies the
b9dc4443 4000 pixel and line characteristics. */
01f1ba30 4001
f676886a 4002#define line_len(line) (FRAME_CURRENT_GLYPHS (f)->used[(line)])
01f1ba30
JB
4003
4004static void
f676886a
JB
4005outline_region (f, gc, top_x, top_y, bottom_x, bottom_y)
4006 register struct frame *f;
01f1ba30
JB
4007 GC gc;
4008 int top_x, top_y, bottom_x, bottom_y;
4009{
7556890b
RS
4010 register int ibw = f->output_data.x->internal_border_width;
4011 register int font_w = FONT_WIDTH (f->output_data.x->font);
4012 register int font_h = f->output_data.x->line_height;
01f1ba30
JB
4013 int y = top_y;
4014 int x = line_len (y);
9ef48a9d
RS
4015 XPoint *pixel_points
4016 = (XPoint *) alloca (((bottom_y - top_y + 2) * 4) * sizeof (XPoint));
01f1ba30
JB
4017 register XPoint *this_point = pixel_points;
4018
4019 /* Do the horizontal top line/lines */
4020 if (top_x == 0)
4021 {
4022 this_point->x = ibw;
4023 this_point->y = ibw + (font_h * top_y);
4024 this_point++;
4025 if (x == 0)
b9dc4443 4026 this_point->x = ibw + (font_w / 2); /* Half-size for newline chars. */
01f1ba30
JB
4027 else
4028 this_point->x = ibw + (font_w * x);
4029 this_point->y = (this_point - 1)->y;
4030 }
4031 else
4032 {
4033 this_point->x = ibw;
4034 this_point->y = ibw + (font_h * (top_y + 1));
4035 this_point++;
4036 this_point->x = ibw + (font_w * top_x);
4037 this_point->y = (this_point - 1)->y;
4038 this_point++;
4039 this_point->x = (this_point - 1)->x;
4040 this_point->y = ibw + (font_h * top_y);
4041 this_point++;
4042 this_point->x = ibw + (font_w * x);
4043 this_point->y = (this_point - 1)->y;
4044 }
4045
b9dc4443 4046 /* Now do the right side. */
01f1ba30
JB
4047 while (y < bottom_y)
4048 { /* Right vertical edge */
4049 this_point++;
4050 this_point->x = (this_point - 1)->x;
4051 this_point->y = ibw + (font_h * (y + 1));
4052 this_point++;
4053
4054 y++; /* Horizontal connection to next line */
4055 x = line_len (y);
4056 if (x == 0)
4057 this_point->x = ibw + (font_w / 2);
4058 else
4059 this_point->x = ibw + (font_w * x);
4060
4061 this_point->y = (this_point - 1)->y;
4062 }
4063
b9dc4443 4064 /* Now do the bottom and connect to the top left point. */
01f1ba30
JB
4065 this_point->x = ibw + (font_w * (bottom_x + 1));
4066
4067 this_point++;
4068 this_point->x = (this_point - 1)->x;
4069 this_point->y = ibw + (font_h * (bottom_y + 1));
4070 this_point++;
4071 this_point->x = ibw;
4072 this_point->y = (this_point - 1)->y;
4073 this_point++;
4074 this_point->x = pixel_points->x;
4075 this_point->y = pixel_points->y;
4076
b9dc4443 4077 XDrawLines (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
01f1ba30
JB
4078 gc, pixel_points,
4079 (this_point - pixel_points + 1), CoordModeOrigin);
4080}
4081
4082DEFUN ("x-contour-region", Fx_contour_region, Sx_contour_region, 1, 1, 0,
4083 "Highlight the region between point and the character under the mouse\n\
f676886a 4084selected frame.")
01f1ba30
JB
4085 (event)
4086 register Lisp_Object event;
4087{
4088 register int x0, y0, x1, y1;
f676886a 4089 register struct frame *f = selected_frame;
01f1ba30
JB
4090 register int p1, p2;
4091
4092 CHECK_CONS (event, 0);
4093
4094 BLOCK_INPUT;
4095 x0 = XINT (Fcar (Fcar (event)));
4096 y0 = XINT (Fcar (Fcdr (Fcar (event))));
4097
b9dc4443
RS
4098 /* If the mouse is past the end of the line, don't that area. */
4099 /* ReWrite this... */
01f1ba30 4100
f676886a
JB
4101 x1 = f->cursor_x;
4102 y1 = f->cursor_y;
01f1ba30
JB
4103
4104 if (y1 > y0) /* point below mouse */
7556890b 4105 outline_region (f, f->output_data.x->cursor_gc,
01f1ba30
JB
4106 x0, y0, x1, y1);
4107 else if (y1 < y0) /* point above mouse */
7556890b 4108 outline_region (f, f->output_data.x->cursor_gc,
01f1ba30
JB
4109 x1, y1, x0, y0);
4110 else /* same line: draw horizontal rectangle */
4111 {
4112 if (x1 > x0)
7556890b 4113 x_rectangle (f, f->output_data.x->cursor_gc,
01f1ba30
JB
4114 x0, y0, (x1 - x0 + 1), 1);
4115 else if (x1 < x0)
7556890b 4116 x_rectangle (f, f->output_data.x->cursor_gc,
01f1ba30
JB
4117 x1, y1, (x0 - x1 + 1), 1);
4118 }
4119
b9dc4443 4120 XFlush (FRAME_X_DISPLAY (f));
01f1ba30
JB
4121 UNBLOCK_INPUT;
4122
4123 return Qnil;
4124}
4125
4126DEFUN ("x-uncontour-region", Fx_uncontour_region, Sx_uncontour_region, 1, 1, 0,
4127 "Erase any highlighting of the region between point and the character\n\
f676886a 4128at X, Y on the selected frame.")
01f1ba30
JB
4129 (event)
4130 register Lisp_Object event;
4131{
4132 register int x0, y0, x1, y1;
f676886a 4133 register struct frame *f = selected_frame;
01f1ba30
JB
4134
4135 BLOCK_INPUT;
4136 x0 = XINT (Fcar (Fcar (event)));
4137 y0 = XINT (Fcar (Fcdr (Fcar (event))));
f676886a
JB
4138 x1 = f->cursor_x;
4139 y1 = f->cursor_y;
01f1ba30
JB
4140
4141 if (y1 > y0) /* point below mouse */
7556890b 4142 outline_region (f, f->output_data.x->reverse_gc,
01f1ba30
JB
4143 x0, y0, x1, y1);
4144 else if (y1 < y0) /* point above mouse */
7556890b 4145 outline_region (f, f->output_data.x->reverse_gc,
01f1ba30
JB
4146 x1, y1, x0, y0);
4147 else /* same line: draw horizontal rectangle */
4148 {
4149 if (x1 > x0)
7556890b 4150 x_rectangle (f, f->output_data.x->reverse_gc,
01f1ba30
JB
4151 x0, y0, (x1 - x0 + 1), 1);
4152 else if (x1 < x0)
7556890b 4153 x_rectangle (f, f->output_data.x->reverse_gc,
01f1ba30
JB
4154 x1, y1, (x0 - x1 + 1), 1);
4155 }
4156 UNBLOCK_INPUT;
4157
4158 return Qnil;
4159}
4160
01f1ba30
JB
4161#if 0
4162int contour_begin_x, contour_begin_y;
4163int contour_end_x, contour_end_y;
4164int contour_npoints;
4165
4166/* Clip the top part of the contour lines down (and including) line Y_POS.
4167 If X_POS is in the middle (rather than at the end) of the line, drop
b9dc4443 4168 down a line at that character. */
01f1ba30
JB
4169
4170static void
4171clip_contour_top (y_pos, x_pos)
4172{
4173 register XPoint *begin = contour_lines[y_pos].top_left;
4174 register XPoint *end;
4175 register int npoints;
f676886a 4176 register struct display_line *line = selected_frame->phys_lines[y_pos + 1];
01f1ba30 4177
b9dc4443 4178 if (x_pos >= line->len - 1) /* Draw one, straight horizontal line. */
01f1ba30
JB
4179 {
4180 end = contour_lines[y_pos].top_right;
4181 npoints = (end - begin + 1);
4182 XDrawLines (x_current_display, contour_window,
4183 contour_erase_gc, begin_erase, npoints, CoordModeOrigin);
4184
4185 bcopy (end, begin + 1, contour_last_point - end + 1);
4186 contour_last_point -= (npoints - 2);
4187 XDrawLines (x_current_display, contour_window,
4188 contour_erase_gc, begin, 2, CoordModeOrigin);
4189 XFlush (x_current_display);
4190
b9dc4443 4191 /* Now, update contour_lines structure. */
01f1ba30
JB
4192 }
4193 /* ______. */
4194 else /* |________*/
4195 {
4196 register XPoint *p = begin + 1;
4197 end = contour_lines[y_pos].bottom_right;
4198 npoints = (end - begin + 1);
4199 XDrawLines (x_current_display, contour_window,
4200 contour_erase_gc, begin_erase, npoints, CoordModeOrigin);
4201
4202 p->y = begin->y;
4203 p->x = ibw + (font_w * (x_pos + 1));
4204 p++;
4205 p->y = begin->y + font_h;
4206 p->x = (p - 1)->x;
4207 bcopy (end, begin + 3, contour_last_point - end + 1);
4208 contour_last_point -= (npoints - 5);
4209 XDrawLines (x_current_display, contour_window,
4210 contour_erase_gc, begin, 4, CoordModeOrigin);
4211 XFlush (x_current_display);
4212
b9dc4443 4213 /* Now, update contour_lines structure. */
01f1ba30
JB
4214 }
4215}
4216
eb8c3be9 4217/* Erase the top horizontal lines of the contour, and then extend
b9dc4443 4218 the contour upwards. */
01f1ba30
JB
4219
4220static void
4221extend_contour_top (line)
4222{
4223}
4224
4225static void
4226clip_contour_bottom (x_pos, y_pos)
4227 int x_pos, y_pos;
4228{
4229}
4230
4231static void
4232extend_contour_bottom (x_pos, y_pos)
4233{
4234}
4235
4236DEFUN ("x-select-region", Fx_select_region, Sx_select_region, 1, 1, "e",
4237 "")
4238 (event)
4239 Lisp_Object event;
4240{
f676886a
JB
4241 register struct frame *f = selected_frame;
4242 register int point_x = f->cursor_x;
4243 register int point_y = f->cursor_y;
01f1ba30
JB
4244 register int mouse_below_point;
4245 register Lisp_Object obj;
4246 register int x_contour_x, x_contour_y;
4247
4248 x_contour_x = x_mouse_x;
4249 x_contour_y = x_mouse_y;
4250 if (x_contour_y > point_y || (x_contour_y == point_y
4251 && x_contour_x > point_x))
4252 {
4253 mouse_below_point = 1;
7556890b 4254 outline_region (f, f->output_data.x->cursor_gc, point_x, point_y,
01f1ba30
JB
4255 x_contour_x, x_contour_y);
4256 }
4257 else
4258 {
4259 mouse_below_point = 0;
7556890b 4260 outline_region (f, f->output_data.x->cursor_gc, x_contour_x, x_contour_y,
01f1ba30
JB
4261 point_x, point_y);
4262 }
4263
4264 while (1)
4265 {
95be70ed 4266 obj = read_char (-1, 0, 0, Qnil, 0);
6a5e54e2 4267 if (!CONSP (obj))
01f1ba30
JB
4268 break;
4269
4270 if (mouse_below_point)
4271 {
b9dc4443 4272 if (x_mouse_y <= point_y) /* Flipped. */
01f1ba30
JB
4273 {
4274 mouse_below_point = 0;
4275
7556890b 4276 outline_region (f, f->output_data.x->reverse_gc, point_x, point_y,
01f1ba30 4277 x_contour_x, x_contour_y);
7556890b 4278 outline_region (f, f->output_data.x->cursor_gc, x_mouse_x, x_mouse_y,
01f1ba30
JB
4279 point_x, point_y);
4280 }
b9dc4443 4281 else if (x_mouse_y < x_contour_y) /* Bottom clipped. */
01f1ba30
JB
4282 {
4283 clip_contour_bottom (x_mouse_y);
4284 }
b9dc4443 4285 else if (x_mouse_y > x_contour_y) /* Bottom extended. */
01f1ba30
JB
4286 {
4287 extend_bottom_contour (x_mouse_y);
4288 }
4289
4290 x_contour_x = x_mouse_x;
4291 x_contour_y = x_mouse_y;
4292 }
4293 else /* mouse above or same line as point */
4294 {
b9dc4443 4295 if (x_mouse_y >= point_y) /* Flipped. */
01f1ba30
JB
4296 {
4297 mouse_below_point = 1;
4298
7556890b 4299 outline_region (f, f->output_data.x->reverse_gc,
01f1ba30 4300 x_contour_x, x_contour_y, point_x, point_y);
7556890b 4301 outline_region (f, f->output_data.x->cursor_gc, point_x, point_y,
01f1ba30
JB
4302 x_mouse_x, x_mouse_y);
4303 }
b9dc4443 4304 else if (x_mouse_y > x_contour_y) /* Top clipped. */
01f1ba30
JB
4305 {
4306 clip_contour_top (x_mouse_y);
4307 }
b9dc4443 4308 else if (x_mouse_y < x_contour_y) /* Top extended. */
01f1ba30
JB
4309 {
4310 extend_contour_top (x_mouse_y);
4311 }
4312 }
4313 }
4314
b4f5687c 4315 unread_command_event = obj;
01f1ba30
JB
4316 if (mouse_below_point)
4317 {
4318 contour_begin_x = point_x;
4319 contour_begin_y = point_y;
4320 contour_end_x = x_contour_x;
4321 contour_end_y = x_contour_y;
4322 }
4323 else
4324 {
4325 contour_begin_x = x_contour_x;
4326 contour_begin_y = x_contour_y;
4327 contour_end_x = point_x;
4328 contour_end_y = point_y;
4329 }
4330}
4331#endif
4332
4333DEFUN ("x-horizontal-line", Fx_horizontal_line, Sx_horizontal_line, 1, 1, "e",
4334 "")
4335 (event)
4336 Lisp_Object event;
4337{
4338 register Lisp_Object obj;
f676886a 4339 struct frame *f = selected_frame;
01f1ba30 4340 register struct window *w = XWINDOW (selected_window);
7556890b
RS
4341 register GC line_gc = f->output_data.x->cursor_gc;
4342 register GC erase_gc = f->output_data.x->reverse_gc;
01f1ba30
JB
4343#if 0
4344 char dash_list[] = {6, 4, 6, 4};
4345 int dashes = 4;
4346 XGCValues gc_values;
4347#endif
4348 register int previous_y;
7556890b
RS
4349 register int line = (x_mouse_y + 1) * f->output_data.x->line_height
4350 + f->output_data.x->internal_border_width;
4351 register int left = f->output_data.x->internal_border_width
01f1ba30 4352 + (w->left
7556890b 4353 * FONT_WIDTH (f->output_data.x->font));
01f1ba30 4354 register int right = left + (w->width
7556890b
RS
4355 * FONT_WIDTH (f->output_data.x->font))
4356 - f->output_data.x->internal_border_width;
01f1ba30
JB
4357
4358#if 0
4359 BLOCK_INPUT;
7556890b
RS
4360 gc_values.foreground = f->output_data.x->cursor_pixel;
4361 gc_values.background = f->output_data.x->background_pixel;
01f1ba30
JB
4362 gc_values.line_width = 1;
4363 gc_values.line_style = LineOnOffDash;
4364 gc_values.cap_style = CapRound;
4365 gc_values.join_style = JoinRound;
4366
b9dc4443 4367 line_gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
01f1ba30
JB
4368 GCLineStyle | GCJoinStyle | GCCapStyle
4369 | GCLineWidth | GCForeground | GCBackground,
4370 &gc_values);
b9dc4443 4371 XSetDashes (FRAME_X_DISPLAY (f), line_gc, 0, dash_list, dashes);
7556890b
RS
4372 gc_values.foreground = f->output_data.x->background_pixel;
4373 gc_values.background = f->output_data.x->foreground_pixel;
b9dc4443 4374 erase_gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
01f1ba30
JB
4375 GCLineStyle | GCJoinStyle | GCCapStyle
4376 | GCLineWidth | GCForeground | GCBackground,
4377 &gc_values);
b9dc4443 4378 XSetDashes (FRAME_X_DISPLAY (f), erase_gc, 0, dash_list, dashes);
ed662bdd 4379 UNBLOCK_INPUT;
01f1ba30
JB
4380#endif
4381
4382 while (1)
4383 {
4384 BLOCK_INPUT;
4385 if (x_mouse_y >= XINT (w->top)
4386 && x_mouse_y < XINT (w->top) + XINT (w->height) - 1)
4387 {
4388 previous_y = x_mouse_y;
7556890b
RS
4389 line = (x_mouse_y + 1) * f->output_data.x->line_height
4390 + f->output_data.x->internal_border_width;
b9dc4443 4391 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
01f1ba30
JB
4392 line_gc, left, line, right, line);
4393 }
b9dc4443 4394 XFlush (FRAME_X_DISPLAY (f));
01f1ba30
JB
4395 UNBLOCK_INPUT;
4396
4397 do
4398 {
95be70ed 4399 obj = read_char (-1, 0, 0, Qnil, 0);
6a5e54e2 4400 if (!CONSP (obj)
01f1ba30 4401 || (! EQ (Fcar (Fcdr (Fcdr (obj))),
6a5e54e2 4402 Qvertical_scroll_bar))
01f1ba30
JB
4403 || x_mouse_grabbed)
4404 {
4405 BLOCK_INPUT;
b9dc4443 4406 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
01f1ba30 4407 erase_gc, left, line, right, line);
b4f5687c 4408 unread_command_event = obj;
01f1ba30 4409#if 0
b9dc4443
RS
4410 XFreeGC (FRAME_X_DISPLAY (f), line_gc);
4411 XFreeGC (FRAME_X_DISPLAY (f), erase_gc);
01f1ba30 4412#endif
ed662bdd 4413 UNBLOCK_INPUT;
01f1ba30
JB
4414 return Qnil;
4415 }
4416 }
4417 while (x_mouse_y == previous_y);
4418
4419 BLOCK_INPUT;
b9dc4443 4420 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
01f1ba30
JB
4421 erase_gc, left, line, right, line);
4422 UNBLOCK_INPUT;
4423 }
4424}
06ef7355 4425#endif
01f1ba30 4426\f
01f1ba30 4427#if 0
b9dc4443 4428/* These keep track of the rectangle following the pointer. */
01f1ba30
JB
4429int mouse_track_top, mouse_track_left, mouse_track_width;
4430
b9dc4443
RS
4431/* Offset in buffer of character under the pointer, or 0. */
4432int mouse_buffer_offset;
4433
01f1ba30
JB
4434DEFUN ("x-track-pointer", Fx_track_pointer, Sx_track_pointer, 0, 0, 0,
4435 "Track the pointer.")
4436 ()
4437{
4438 static Cursor current_pointer_shape;
f676886a 4439 FRAME_PTR f = x_mouse_frame;
01f1ba30
JB
4440
4441 BLOCK_INPUT;
f676886a 4442 if (EQ (Vmouse_frame_part, Qtext_part)
7556890b 4443 && (current_pointer_shape != f->output_data.x->nontext_cursor))
01f1ba30
JB
4444 {
4445 unsigned char c;
4446 struct buffer *buf;
4447
7556890b 4448 current_pointer_shape = f->output_data.x->nontext_cursor;
b9dc4443 4449 XDefineCursor (FRAME_X_DISPLAY (f),
fe24a618 4450 FRAME_X_WINDOW (f),
01f1ba30
JB
4451 current_pointer_shape);
4452
4453 buf = XBUFFER (XWINDOW (Vmouse_window)->buffer);
4454 c = *(BUF_CHAR_ADDRESS (buf, mouse_buffer_offset));
4455 }
f676886a 4456 else if (EQ (Vmouse_frame_part, Qmodeline_part)
7556890b 4457 && (current_pointer_shape != f->output_data.x->modeline_cursor))
01f1ba30 4458 {
7556890b 4459 current_pointer_shape = f->output_data.x->modeline_cursor;
b9dc4443 4460 XDefineCursor (FRAME_X_DISPLAY (f),
fe24a618 4461 FRAME_X_WINDOW (f),
01f1ba30
JB
4462 current_pointer_shape);
4463 }
4464
b9dc4443 4465 XFlush (FRAME_X_DISPLAY (f));
01f1ba30
JB
4466 UNBLOCK_INPUT;
4467}
4468#endif
4469
4470#if 0
4471DEFUN ("x-track-pointer", Fx_track_pointer, Sx_track_pointer, 1, 1, "e",
4472 "Draw rectangle around character under mouse pointer, if there is one.")
4473 (event)
4474 Lisp_Object event;
4475{
4476 struct window *w = XWINDOW (Vmouse_window);
f676886a 4477 struct frame *f = XFRAME (WINDOW_FRAME (w));
01f1ba30
JB
4478 struct buffer *b = XBUFFER (w->buffer);
4479 Lisp_Object obj;
4480
4481 if (! EQ (Vmouse_window, selected_window))
4482 return Qnil;
4483
4484 if (EQ (event, Qnil))
4485 {
4486 int x, y;
4487
f676886a 4488 x_read_mouse_position (selected_frame, &x, &y);
01f1ba30
JB
4489 }
4490
4491 BLOCK_INPUT;
4492 mouse_track_width = 0;
4493 mouse_track_left = mouse_track_top = -1;
4494
4495 do
4496 {
4497 if ((x_mouse_x != mouse_track_left
4498 && (x_mouse_x < mouse_track_left
4499 || x_mouse_x > (mouse_track_left + mouse_track_width)))
4500 || x_mouse_y != mouse_track_top)
4501 {
4502 int hp = 0; /* Horizontal position */
f676886a
JB
4503 int len = FRAME_CURRENT_GLYPHS (f)->used[x_mouse_y];
4504 int p = FRAME_CURRENT_GLYPHS (f)->bufp[x_mouse_y];
01f1ba30 4505 int tab_width = XINT (b->tab_width);
265a9e55 4506 int ctl_arrow_p = !NILP (b->ctl_arrow);
01f1ba30
JB
4507 unsigned char c;
4508 int mode_line_vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
4509 int in_mode_line = 0;
4510
f676886a 4511 if (! FRAME_CURRENT_GLYPHS (f)->enable[x_mouse_y])
01f1ba30
JB
4512 break;
4513
b9dc4443 4514 /* Erase previous rectangle. */
01f1ba30
JB
4515 if (mouse_track_width)
4516 {
7556890b 4517 x_rectangle (f, f->output_data.x->reverse_gc,
01f1ba30
JB
4518 mouse_track_left, mouse_track_top,
4519 mouse_track_width, 1);
4520
f676886a
JB
4521 if ((mouse_track_left == f->phys_cursor_x
4522 || mouse_track_left == f->phys_cursor_x - 1)
4523 && mouse_track_top == f->phys_cursor_y)
01f1ba30 4524 {
f676886a 4525 x_display_cursor (f, 1);
01f1ba30
JB
4526 }
4527 }
4528
4529 mouse_track_left = x_mouse_x;
4530 mouse_track_top = x_mouse_y;
4531 mouse_track_width = 0;
4532
b9dc4443 4533 if (mouse_track_left > len) /* Past the end of line. */
01f1ba30
JB
4534 goto draw_or_not;
4535
4536 if (mouse_track_top == mode_line_vpos)
4537 {
4538 in_mode_line = 1;
4539 goto draw_or_not;
4540 }
4541
4542 if (tab_width <= 0 || tab_width > 20) tab_width = 8;
4543 do
4544 {
4545 c = FETCH_CHAR (p);
f676886a 4546 if (len == f->width && hp == len - 1 && c != '\n')
01f1ba30
JB
4547 goto draw_or_not;
4548
4549 switch (c)
4550 {
4551 case '\t':
4552 mouse_track_width = tab_width - (hp % tab_width);
4553 p++;
4554 hp += mouse_track_width;
4555 if (hp > x_mouse_x)
4556 {
4557 mouse_track_left = hp - mouse_track_width;
4558 goto draw_or_not;
4559 }
4560 continue;
4561
4562 case '\n':
4563 mouse_track_width = -1;
4564 goto draw_or_not;
4565
4566 default:
4567 if (ctl_arrow_p && (c < 040 || c == 0177))
4568 {
4569 if (p > ZV)
4570 goto draw_or_not;
4571
4572 mouse_track_width = 2;
4573 p++;
4574 hp +=2;
4575 if (hp > x_mouse_x)
4576 {
4577 mouse_track_left = hp - mouse_track_width;
4578 goto draw_or_not;
4579 }
4580 }
4581 else
4582 {
4583 mouse_track_width = 1;
4584 p++;
4585 hp++;
4586 }
4587 continue;
4588 }
4589 }
4590 while (hp <= x_mouse_x);
4591
4592 draw_or_not:
b9dc4443 4593 if (mouse_track_width) /* Over text; use text pointer shape. */
01f1ba30 4594 {
b9dc4443 4595 XDefineCursor (FRAME_X_DISPLAY (f),
fe24a618 4596 FRAME_X_WINDOW (f),
7556890b
RS
4597 f->output_data.x->text_cursor);
4598 x_rectangle (f, f->output_data.x->cursor_gc,
01f1ba30
JB
4599 mouse_track_left, mouse_track_top,
4600 mouse_track_width, 1);
4601 }
4602 else if (in_mode_line)
b9dc4443 4603 XDefineCursor (FRAME_X_DISPLAY (f),
fe24a618 4604 FRAME_X_WINDOW (f),
7556890b 4605 f->output_data.x->modeline_cursor);
01f1ba30 4606 else
b9dc4443 4607 XDefineCursor (FRAME_X_DISPLAY (f),
fe24a618 4608 FRAME_X_WINDOW (f),
7556890b 4609 f->output_data.x->nontext_cursor);
01f1ba30
JB
4610 }
4611
b9dc4443 4612 XFlush (FRAME_X_DISPLAY (f));
01f1ba30
JB
4613 UNBLOCK_INPUT;
4614
95be70ed 4615 obj = read_char (-1, 0, 0, Qnil, 0);
01f1ba30
JB
4616 BLOCK_INPUT;
4617 }
6a5e54e2 4618 while (CONSP (obj) /* Mouse event */
a3c87d4e 4619 && EQ (Fcar (Fcdr (Fcdr (obj))), Qnil) /* Not scroll bar */
01f1ba30
JB
4620 && EQ (Vmouse_depressed, Qnil) /* Only motion events */
4621 && EQ (Vmouse_window, selected_window) /* In this window */
f676886a 4622 && x_mouse_frame);
01f1ba30 4623
b4f5687c 4624 unread_command_event = obj;
01f1ba30
JB
4625
4626 if (mouse_track_width)
4627 {
7556890b 4628 x_rectangle (f, f->output_data.x->reverse_gc,
01f1ba30
JB
4629 mouse_track_left, mouse_track_top,
4630 mouse_track_width, 1);
4631 mouse_track_width = 0;
f676886a
JB
4632 if ((mouse_track_left == f->phys_cursor_x
4633 || mouse_track_left - 1 == f->phys_cursor_x)
4634 && mouse_track_top == f->phys_cursor_y)
01f1ba30 4635 {
f676886a 4636 x_display_cursor (f, 1);
01f1ba30
JB
4637 }
4638 }
b9dc4443 4639 XDefineCursor (FRAME_X_DISPLAY (f),
fe24a618 4640 FRAME_X_WINDOW (f),
7556890b 4641 f->output_data.x->nontext_cursor);
b9dc4443 4642 XFlush (FRAME_X_DISPLAY (f));
01f1ba30
JB
4643 UNBLOCK_INPUT;
4644
4645 return Qnil;
4646}
4647#endif
4648\f
4649#if 0
4650#include "glyphs.h"
4651
4652/* Draw a pixmap specified by IMAGE_DATA of dimensions WIDTH and HEIGHT
b9dc4443 4653 on the frame F at position X, Y. */
01f1ba30 4654
f676886a
JB
4655x_draw_pixmap (f, x, y, image_data, width, height)
4656 struct frame *f;
01f1ba30
JB
4657 int x, y, width, height;
4658 char *image_data;
4659{
4660 Pixmap image;
4661
b9dc4443 4662 image = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
fe24a618 4663 FRAME_X_WINDOW (f), image_data,
01f1ba30 4664 width, height);
b9dc4443 4665 XCopyPlane (FRAME_X_DISPLAY (f), image, FRAME_X_WINDOW (f),
7556890b 4666 f->output_data.x->normal_gc, 0, 0, width, height, x, y);
01f1ba30
JB
4667}
4668#endif
4669\f
01567351
RS
4670#if 0 /* I'm told these functions are superfluous
4671 given the ability to bind function keys. */
4672
01f1ba30
JB
4673#ifdef HAVE_X11
4674DEFUN ("x-rebind-key", Fx_rebind_key, Sx_rebind_key, 3, 3, 0,
4675"Rebind X keysym KEYSYM, with MODIFIERS, to generate NEWSTRING.\n\
4676KEYSYM is a string which conforms to the X keysym definitions found\n\
4677in X11/keysymdef.h, sans the initial XK_. MODIFIERS is nil or a\n\
4678list of strings specifying modifier keys such as Control_L, which must\n\
4679also be depressed for NEWSTRING to appear.")
4680 (x_keysym, modifiers, newstring)
4681 register Lisp_Object x_keysym;
4682 register Lisp_Object modifiers;
4683 register Lisp_Object newstring;
4684{
4685 char *rawstring;
c047688c
JA
4686 register KeySym keysym;
4687 KeySym modifier_list[16];
01f1ba30 4688
11ae94fe 4689 check_x ();
01f1ba30
JB
4690 CHECK_STRING (x_keysym, 1);
4691 CHECK_STRING (newstring, 3);
4692
4693 keysym = XStringToKeysym ((char *) XSTRING (x_keysym)->data);
4694 if (keysym == NoSymbol)
4695 error ("Keysym does not exist");
4696
265a9e55 4697 if (NILP (modifiers))
01f1ba30
JB
4698 XRebindKeysym (x_current_display, keysym, modifier_list, 0,
4699 XSTRING (newstring)->data, XSTRING (newstring)->size);
4700 else
4701 {
4702 register Lisp_Object rest, mod;
4703 register int i = 0;
4704
265a9e55 4705 for (rest = modifiers; !NILP (rest); rest = Fcdr (rest))
01f1ba30
JB
4706 {
4707 if (i == 16)
4708 error ("Can't have more than 16 modifiers");
4709
4710 mod = Fcar (rest);
4711 CHECK_STRING (mod, 3);
4712 modifier_list[i] = XStringToKeysym ((char *) XSTRING (mod)->data);
fb351039
JB
4713#ifndef HAVE_X11R5
4714 if (modifier_list[i] == NoSymbol
4715 || !(IsModifierKey (modifier_list[i])
4716 || ((unsigned)(modifier_list[i]) == XK_Mode_switch)
4717 || ((unsigned)(modifier_list[i]) == XK_Num_Lock)))
4718#else
01f1ba30
JB
4719 if (modifier_list[i] == NoSymbol
4720 || !IsModifierKey (modifier_list[i]))
fb351039 4721#endif
01f1ba30
JB
4722 error ("Element is not a modifier keysym");
4723 i++;
4724 }
4725
4726 XRebindKeysym (x_current_display, keysym, modifier_list, i,
4727 XSTRING (newstring)->data, XSTRING (newstring)->size);
4728 }
4729
4730 return Qnil;
4731}
4732
4733DEFUN ("x-rebind-keys", Fx_rebind_keys, Sx_rebind_keys, 2, 2, 0,
4734 "Rebind KEYCODE to list of strings STRINGS.\n\
4735STRINGS should be a list of 16 elements, one for each shift combination.\n\
4736nil as element means don't change.\n\
4737See the documentation of `x-rebind-key' for more information.")
4738 (keycode, strings)
4739 register Lisp_Object keycode;
4740 register Lisp_Object strings;
4741{
4742 register Lisp_Object item;
4743 register unsigned char *rawstring;
4744 KeySym rawkey, modifier[1];
4745 int strsize;
4746 register unsigned i;
4747
11ae94fe 4748 check_x ();
01f1ba30
JB
4749 CHECK_NUMBER (keycode, 1);
4750 CHECK_CONS (strings, 2);
4751 rawkey = (KeySym) ((unsigned) (XINT (keycode))) & 255;
4752 for (i = 0; i <= 15; strings = Fcdr (strings), i++)
4753 {
4754 item = Fcar (strings);
265a9e55 4755 if (!NILP (item))
01f1ba30
JB
4756 {
4757 CHECK_STRING (item, 2);
4758 strsize = XSTRING (item)->size;
4759 rawstring = (unsigned char *) xmalloc (strsize);
4760 bcopy (XSTRING (item)->data, rawstring, strsize);
4761 modifier[1] = 1 << i;
4762 XRebindKeysym (x_current_display, rawkey, modifier, 1,
4763 rawstring, strsize);
4764 }
4765 }
4766 return Qnil;
4767}
9d04a87a 4768#endif /* HAVE_X11 */
01567351 4769#endif /* 0 */
01f1ba30 4770\f
404daac1
RS
4771#ifndef HAVE_XSCREENNUMBEROFSCREEN
4772int
4773XScreenNumberOfScreen (scr)
4774 register Screen *scr;
4775{
3df34fdb
BF
4776 register Display *dpy;
4777 register Screen *dpyscr;
404daac1
RS
4778 register int i;
4779
3df34fdb
BF
4780 dpy = scr->display;
4781 dpyscr = dpy->screens;
4782
404daac1
RS
4783 for (i = 0; i < dpy->nscreens; i++, dpyscr++)
4784 if (scr == dpyscr)
4785 return i;
4786
4787 return -1;
4788}
4789#endif /* not HAVE_XSCREENNUMBEROFSCREEN */
4790
01f1ba30 4791Visual *
b9dc4443
RS
4792select_visual (dpy, screen, depth)
4793 Display *dpy;
01f1ba30
JB
4794 Screen *screen;
4795 unsigned int *depth;
4796{
4797 Visual *v;
4798 XVisualInfo *vinfo, vinfo_template;
4799 int n_visuals;
4800
4801 v = DefaultVisualOfScreen (screen);
fe24a618
JB
4802
4803#ifdef HAVE_X11R4
4804 vinfo_template.visualid = XVisualIDFromVisual (v);
4805#else
6afb1d07 4806 vinfo_template.visualid = v->visualid;
fe24a618
JB
4807#endif
4808
f0614854
JB
4809 vinfo_template.screen = XScreenNumberOfScreen (screen);
4810
b9dc4443 4811 vinfo = XGetVisualInfo (dpy,
f0614854 4812 VisualIDMask | VisualScreenMask, &vinfo_template,
01f1ba30
JB
4813 &n_visuals);
4814 if (n_visuals != 1)
4815 fatal ("Can't get proper X visual info");
4816
4817 if ((1 << vinfo->depth) == vinfo->colormap_size)
4818 *depth = vinfo->depth;
4819 else
4820 {
4821 int i = 0;
4822 int n = vinfo->colormap_size - 1;
4823 while (n)
4824 {
4825 n = n >> 1;
4826 i++;
4827 }
4828 *depth = i;
4829 }
4830
4831 XFree ((char *) vinfo);
4832 return v;
4833}
01f1ba30 4834
b9dc4443
RS
4835/* Return the X display structure for the display named NAME.
4836 Open a new connection if necessary. */
4837
4838struct x_display_info *
4839x_display_info_for_name (name)
4840 Lisp_Object name;
4841{
08a90d6a 4842 Lisp_Object names;
b9dc4443
RS
4843 struct x_display_info *dpyinfo;
4844
4845 CHECK_STRING (name, 0);
4846
806048df
RS
4847 if (! EQ (Vwindow_system, intern ("x")))
4848 error ("Not using X Windows");
4849
08a90d6a
RS
4850 for (dpyinfo = x_display_list, names = x_display_name_list;
4851 dpyinfo;
4852 dpyinfo = dpyinfo->next, names = XCONS (names)->cdr)
b9dc4443
RS
4853 {
4854 Lisp_Object tem;
08a90d6a
RS
4855 tem = Fstring_equal (XCONS (XCONS (names)->car)->car, name);
4856 if (!NILP (tem))
b9dc4443
RS
4857 return dpyinfo;
4858 }
4859
b7975ee4
KH
4860 /* Use this general default value to start with. */
4861 Vx_resource_name = Vinvocation_name;
4862
b9dc4443
RS
4863 validate_x_resource_name ();
4864
4865 dpyinfo = x_term_init (name, (unsigned char *)0,
b7975ee4 4866 (char *) XSTRING (Vx_resource_name)->data);
b9dc4443 4867
08a90d6a 4868 if (dpyinfo == 0)
1b4ec1c8 4869 error ("Cannot connect to X server %s", XSTRING (name)->data);
08a90d6a 4870
b9dc4443
RS
4871 x_in_use = 1;
4872 XSETFASTINT (Vwindow_system_version, 11);
4873
4874 return dpyinfo;
4875}
4876
01f1ba30 4877DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
08a90d6a 4878 1, 3, 0, "Open a connection to an X server.\n\
d387c960 4879DISPLAY is the name of the display to connect to.\n\
08a90d6a
RS
4880Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
4881If the optional third arg MUST-SUCCEED is non-nil,\n\
4882terminate Emacs if we can't open the connection.")
4883 (display, xrm_string, must_succeed)
4884 Lisp_Object display, xrm_string, must_succeed;
01f1ba30
JB
4885{
4886 unsigned int n_planes;
01f1ba30 4887 unsigned char *xrm_option;
b9dc4443 4888 struct x_display_info *dpyinfo;
01f1ba30
JB
4889
4890 CHECK_STRING (display, 0);
d387c960
JB
4891 if (! NILP (xrm_string))
4892 CHECK_STRING (xrm_string, 1);
01f1ba30 4893
806048df
RS
4894 if (! EQ (Vwindow_system, intern ("x")))
4895 error ("Not using X Windows");
4896
d387c960
JB
4897 if (! NILP (xrm_string))
4898 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
01f1ba30
JB
4899 else
4900 xrm_option = (unsigned char *) 0;
d387c960 4901
b7975ee4
KH
4902 /* Use this general default value to start with. */
4903 Vx_resource_name = Vinvocation_name;
4904
d387c960
JB
4905 validate_x_resource_name ();
4906
e1b1bee8 4907 /* This is what opens the connection and sets x_current_display.
b9dc4443
RS
4908 This also initializes many symbols, such as those used for input. */
4909 dpyinfo = x_term_init (display, xrm_option,
b7975ee4 4910 (char *) XSTRING (Vx_resource_name)->data);
f1c16f36 4911
08a90d6a
RS
4912 if (dpyinfo == 0)
4913 {
4914 if (!NILP (must_succeed))
1b4ec1c8
KH
4915 fatal ("Cannot connect to X server %s.\n\
4916Check the DISPLAY environment variable or use `-d'.\n\
4917Also use the `xhost' program to verify that it is set to permit\n\
4918connections from your machine.\n",
08a90d6a
RS
4919 XSTRING (display)->data);
4920 else
1b4ec1c8 4921 error ("Cannot connect to X server %s", XSTRING (display)->data);
08a90d6a
RS
4922 }
4923
b9dc4443 4924 x_in_use = 1;
01f1ba30 4925
b9dc4443 4926 XSETFASTINT (Vwindow_system_version, 11);
01f1ba30
JB
4927 return Qnil;
4928}
4929
08a90d6a
RS
4930DEFUN ("x-close-connection", Fx_close_connection,
4931 Sx_close_connection, 1, 1, 0,
4932 "Close the connection to DISPLAY's X server.\n\
4933For DISPLAY, specify either a frame or a display name (a string).\n\
4934If DISPLAY is nil, that stands for the selected frame's display.")
4935 (display)
4936 Lisp_Object display;
01f1ba30 4937{
08a90d6a
RS
4938 struct x_display_info *dpyinfo = check_x_display_info (display);
4939 struct x_display_info *tail;
4940 int i;
3457bc6e 4941
08a90d6a
RS
4942 if (dpyinfo->reference_count > 0)
4943 error ("Display still has frames on it");
01f1ba30 4944
08a90d6a
RS
4945 BLOCK_INPUT;
4946 /* Free the fonts in the font table. */
4947 for (i = 0; i < dpyinfo->n_fonts; i++)
01f1ba30 4948 {
08a90d6a
RS
4949 if (dpyinfo->font_table[i].name)
4950 free (dpyinfo->font_table[i].name);
4951 /* Don't free the full_name string;
4952 it is always shared with something else. */
4953 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
01f1ba30 4954 }
08a90d6a
RS
4955 x_destroy_all_bitmaps (dpyinfo);
4956 XSetCloseDownMode (dpyinfo->display, DestroyAll);
82c90203
RS
4957
4958#ifdef USE_X_TOOLKIT
4959 XtCloseDisplay (dpyinfo->display);
4960#else
08a90d6a 4961 XCloseDisplay (dpyinfo->display);
82c90203 4962#endif
08a90d6a
RS
4963
4964 x_delete_display (dpyinfo);
4965 UNBLOCK_INPUT;
3457bc6e 4966
01f1ba30
JB
4967 return Qnil;
4968}
4969
08a90d6a
RS
4970DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
4971 "Return the list of display names that Emacs has connections to.")
4972 ()
4973{
4974 Lisp_Object tail, result;
4975
4976 result = Qnil;
4977 for (tail = x_display_name_list; ! NILP (tail); tail = XCONS (tail)->cdr)
4978 result = Fcons (XCONS (XCONS (tail)->car)->car, result);
4979
4980 return result;
4981}
4982
4983DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
4984 "If ON is non-nil, report X errors as soon as the erring request is made.\n\
01f1ba30
JB
4985If ON is nil, allow buffering of requests.\n\
4986Turning on synchronization prohibits the Xlib routines from buffering\n\
4987requests and seriously degrades performance, but makes debugging much\n\
7a9a9813 4988easier.\n\
08a90d6a
RS
4989The optional second argument DISPLAY specifies which display to act on.\n\
4990DISPLAY should be either a frame or a display name (a string).\n\
4991If DISPLAY is omitted or nil, that stands for the selected frame's display.")
4992 (on, display)
4993 Lisp_Object display, on;
01f1ba30 4994{
08a90d6a 4995 struct x_display_info *dpyinfo = check_x_display_info (display);
11ae94fe 4996
b9dc4443 4997 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
01f1ba30
JB
4998
4999 return Qnil;
5000}
5001
b9dc4443 5002/* Wait for responses to all X commands issued so far for frame F. */
6b7b1820
RS
5003
5004void
b9dc4443
RS
5005x_sync (f)
5006 FRAME_PTR f;
6b7b1820 5007{
4e87f4d2 5008 BLOCK_INPUT;
b9dc4443 5009 XSync (FRAME_X_DISPLAY (f), False);
4e87f4d2 5010 UNBLOCK_INPUT;
6b7b1820 5011}
01f1ba30
JB
5012\f
5013syms_of_xfns ()
5014{
01f1ba30 5015 /* This is zero if not using X windows. */
b9dc4443 5016 x_in_use = 0;
f1c16f36 5017
f9942c9e
JB
5018 /* The section below is built by the lisp expression at the top of the file,
5019 just above where these variables are declared. */
5020 /*&&& init symbols here &&&*/
5021 Qauto_raise = intern ("auto-raise");
5022 staticpro (&Qauto_raise);
5023 Qauto_lower = intern ("auto-lower");
5024 staticpro (&Qauto_lower);
5025 Qbackground_color = intern ("background-color");
5026 staticpro (&Qbackground_color);
dbc4e1c1
JB
5027 Qbar = intern ("bar");
5028 staticpro (&Qbar);
f9942c9e
JB
5029 Qborder_color = intern ("border-color");
5030 staticpro (&Qborder_color);
5031 Qborder_width = intern ("border-width");
5032 staticpro (&Qborder_width);
dbc4e1c1
JB
5033 Qbox = intern ("box");
5034 staticpro (&Qbox);
f9942c9e
JB
5035 Qcursor_color = intern ("cursor-color");
5036 staticpro (&Qcursor_color);
dbc4e1c1
JB
5037 Qcursor_type = intern ("cursor-type");
5038 staticpro (&Qcursor_type);
f9942c9e
JB
5039 Qforeground_color = intern ("foreground-color");
5040 staticpro (&Qforeground_color);
5041 Qgeometry = intern ("geometry");
5042 staticpro (&Qgeometry);
f9942c9e
JB
5043 Qicon_left = intern ("icon-left");
5044 staticpro (&Qicon_left);
5045 Qicon_top = intern ("icon-top");
5046 staticpro (&Qicon_top);
5047 Qicon_type = intern ("icon-type");
5048 staticpro (&Qicon_type);
80534dd6
KH
5049 Qicon_name = intern ("icon-name");
5050 staticpro (&Qicon_name);
f9942c9e
JB
5051 Qinternal_border_width = intern ("internal-border-width");
5052 staticpro (&Qinternal_border_width);
5053 Qleft = intern ("left");
5054 staticpro (&Qleft);
5055 Qmouse_color = intern ("mouse-color");
5056 staticpro (&Qmouse_color);
baaed68e
JB
5057 Qnone = intern ("none");
5058 staticpro (&Qnone);
f9942c9e
JB
5059 Qparent_id = intern ("parent-id");
5060 staticpro (&Qparent_id);
4701395c
KH
5061 Qscroll_bar_width = intern ("scroll-bar-width");
5062 staticpro (&Qscroll_bar_width);
8af1d7ca
JB
5063 Qsuppress_icon = intern ("suppress-icon");
5064 staticpro (&Qsuppress_icon);
f9942c9e
JB
5065 Qtop = intern ("top");
5066 staticpro (&Qtop);
01f1ba30 5067 Qundefined_color = intern ("undefined-color");
f9942c9e 5068 staticpro (&Qundefined_color);
a3c87d4e
JB
5069 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
5070 staticpro (&Qvertical_scroll_bars);
49795535
JB
5071 Qvisibility = intern ("visibility");
5072 staticpro (&Qvisibility);
f9942c9e
JB
5073 Qwindow_id = intern ("window-id");
5074 staticpro (&Qwindow_id);
5075 Qx_frame_parameter = intern ("x-frame-parameter");
5076 staticpro (&Qx_frame_parameter);
9ef48a9d
RS
5077 Qx_resource_name = intern ("x-resource-name");
5078 staticpro (&Qx_resource_name);
4fe1de12
RS
5079 Quser_position = intern ("user-position");
5080 staticpro (&Quser_position);
5081 Quser_size = intern ("user-size");
5082 staticpro (&Quser_size);
b9dc4443
RS
5083 Qdisplay = intern ("display");
5084 staticpro (&Qdisplay);
f9942c9e
JB
5085 /* This is the end of symbol initialization. */
5086
01f1ba30
JB
5087 Fput (Qundefined_color, Qerror_conditions,
5088 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
5089 Fput (Qundefined_color, Qerror_message,
5090 build_string ("Undefined color"));
5091
f9942c9e
JB
5092 init_x_parm_symbols ();
5093
f1c7b5a6
RS
5094 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
5095 "List of directories to search for bitmap files for X.");
e241c09b 5096 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
f1c7b5a6 5097
16ae08a9 5098 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
d387c960 5099 "The shape of the pointer when over text.\n\
af01ef26
RS
5100Changing the value does not affect existing frames\n\
5101unless you set the mouse color.");
01f1ba30
JB
5102 Vx_pointer_shape = Qnil;
5103
d387c960
JB
5104 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
5105 "The name Emacs uses to look up X resources; for internal use only.\n\
5106`x-get-resource' uses this as the first component of the instance name\n\
5107when requesting resource values.\n\
5108Emacs initially sets `x-resource-name' to the name under which Emacs\n\
5109was invoked, or to the value specified with the `-name' or `-rn'\n\
5110switches, if present.");
5111 Vx_resource_name = Qnil;
ac63d3d6 5112
ca0ecbf5 5113#if 0 /* This doesn't really do anything. */
01f1ba30 5114 DEFVAR_INT ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
ca0ecbf5
RS
5115 "The shape of the pointer when not over text.\n\
5116This variable takes effect when you create a new frame\n\
5117or when you set the mouse color.");
af01ef26 5118#endif
01f1ba30
JB
5119 Vx_nontext_pointer_shape = Qnil;
5120
ca0ecbf5 5121#if 0 /* This doesn't really do anything. */
01f1ba30 5122 DEFVAR_INT ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
ca0ecbf5
RS
5123 "The shape of the pointer when over the mode line.\n\
5124This variable takes effect when you create a new frame\n\
5125or when you set the mouse color.");
af01ef26 5126#endif
01f1ba30
JB
5127 Vx_mode_pointer_shape = Qnil;
5128
ca0ecbf5
RS
5129 DEFVAR_INT ("x-sensitive-text-pointer-shape",
5130 &Vx_sensitive_text_pointer_shape,
5131 "The shape of the pointer when over mouse-sensitive text.\n\
5132This variable takes effect when you create a new frame\n\
5133or when you set the mouse color.");
5134 Vx_sensitive_text_pointer_shape = Qnil;
95f80c78 5135
01f1ba30
JB
5136 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
5137 "A string indicating the foreground color of the cursor box.");
5138 Vx_cursor_fore_pixel = Qnil;
5139
01f1ba30 5140 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
2d38195d
RS
5141 "Non-nil if no X window manager is in use.\n\
5142Emacs doesn't try to figure this out; this is always nil\n\
5143unless you set it to something else.");
5144 /* We don't have any way to find this out, so set it to nil
5145 and maybe the user would like to set it to t. */
5146 Vx_no_window_manager = Qnil;
1d3dac41 5147
1d3dac41 5148#ifdef USE_X_TOOLKIT
f1d238ef 5149 Fprovide (intern ("x-toolkit"));
1d3dac41 5150#endif
5b827abb
KH
5151#ifdef USE_MOTIF
5152 Fprovide (intern ("motif"));
5153#endif
01f1ba30 5154
01f1ba30 5155 defsubr (&Sx_get_resource);
85ffea93 5156#if 0
01f1ba30
JB
5157 defsubr (&Sx_draw_rectangle);
5158 defsubr (&Sx_erase_rectangle);
5159 defsubr (&Sx_contour_region);
5160 defsubr (&Sx_uncontour_region);
85ffea93 5161#endif
f0614854 5162 defsubr (&Sx_list_fonts);
d0c9d219
RS
5163 defsubr (&Sx_display_color_p);
5164 defsubr (&Sx_display_grayscale_p);
8af1d7ca 5165 defsubr (&Sx_color_defined_p);
e12d55b2 5166 defsubr (&Sx_color_values);
9d317b2c 5167 defsubr (&Sx_server_max_request_size);
41beb8fc
RS
5168 defsubr (&Sx_server_vendor);
5169 defsubr (&Sx_server_version);
5170 defsubr (&Sx_display_pixel_width);
5171 defsubr (&Sx_display_pixel_height);
5172 defsubr (&Sx_display_mm_width);
5173 defsubr (&Sx_display_mm_height);
5174 defsubr (&Sx_display_screens);
5175 defsubr (&Sx_display_planes);
5176 defsubr (&Sx_display_color_cells);
5177 defsubr (&Sx_display_visual_class);
5178 defsubr (&Sx_display_backing_store);
5179 defsubr (&Sx_display_save_under);
01567351 5180#if 0
9d04a87a
RS
5181 defsubr (&Sx_rebind_key);
5182 defsubr (&Sx_rebind_keys);
01f1ba30 5183 defsubr (&Sx_track_pointer);
01f1ba30
JB
5184 defsubr (&Sx_grab_pointer);
5185 defsubr (&Sx_ungrab_pointer);
01f1ba30 5186#endif
8af1d7ca 5187 defsubr (&Sx_parse_geometry);
f676886a
JB
5188 defsubr (&Sx_create_frame);
5189 defsubr (&Sfocus_frame);
5190 defsubr (&Sunfocus_frame);
06ef7355 5191#if 0
01f1ba30 5192 defsubr (&Sx_horizontal_line);
06ef7355 5193#endif
01f1ba30 5194 defsubr (&Sx_open_connection);
08a90d6a
RS
5195 defsubr (&Sx_close_connection);
5196 defsubr (&Sx_display_list);
01f1ba30 5197 defsubr (&Sx_synchronize);
01f1ba30
JB
5198}
5199
5200#endif /* HAVE_X_WINDOWS */