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