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