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