(frame-initialize): Set cursor-color last.
[bpt/emacs.git] / src / xfns.c
CommitLineData
01f1ba30 1/* Functions for the X window system.
cf177271 2 Copyright (C) 1989, 1992, 1993 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
24#if 0
25#include <stdio.h>
26#endif
27#include <signal.h>
28#include "config.h"
29#include "lisp.h"
30#include "xterm.h"
f676886a 31#include "frame.h"
01f1ba30
JB
32#include "window.h"
33#include "buffer.h"
34#include "dispextern.h"
1f98fa48 35#include "keyboard.h"
9ac0d9e0 36#include "blockinput.h"
01f1ba30
JB
37
38#ifdef HAVE_X_WINDOWS
39extern void abort ();
40
0a93081c 41#ifndef VMS
dbc4e1c1 42#include <X11/bitmaps/gray>
0a93081c
JB
43#else
44#include "[.bitmaps]gray.xbm"
45#endif
dbc4e1c1 46
01f1ba30
JB
47#define min(a,b) ((a) < (b) ? (a) : (b))
48#define max(a,b) ((a) > (b) ? (a) : (b))
49
50#ifdef HAVE_X11
51/* X Resource data base */
52static XrmDatabase xrdb;
53
54/* The class of this X application. */
55#define EMACS_CLASS "Emacs"
56
ac63d3d6
JB
57/* The name we're using for this X application. */
58Lisp_Object Vxrdb_name;
59
01f1ba30 60/* Title name and application name for X stuff. */
60fb3ee1 61extern char *x_id_name;
01f1ba30
JB
62
63/* The background and shape of the mouse pointer, and shape when not
64 over text or in the modeline. */
65Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
66
67/* Color of chars displayed in cursor box. */
68Lisp_Object Vx_cursor_fore_pixel;
69
41beb8fc
RS
70/* The screen being used. */
71static Screen *x_screen;
72
01f1ba30
JB
73/* The X Visual we are using for X windows (the default) */
74Visual *screen_visual;
75
01f1ba30
JB
76/* Height of this X screen in pixels. */
77int x_screen_height;
78
01f1ba30
JB
79/* Width of this X screen in pixels. */
80int x_screen_width;
81
01f1ba30
JB
82/* Number of planes for this screen. */
83int x_screen_planes;
84
01f1ba30
JB
85/* Non nil if no window manager is in use. */
86Lisp_Object Vx_no_window_manager;
87
01f1ba30
JB
88/* `t' if a mouse button is depressed. */
89
90Lisp_Object Vmouse_depressed;
91
f370ccb7 92extern unsigned int x_mouse_x, x_mouse_y, x_mouse_grabbed;
f370ccb7 93
01f1ba30 94/* Atom for indicating window state to the window manager. */
99e72068 95extern Atom Xatom_wm_change_state;
01f1ba30 96
3c254570
JA
97/* Communication with window managers. */
98extern Atom Xatom_wm_protocols;
99
100/* Kinds of protocol things we may receive. */
101extern Atom Xatom_wm_take_focus;
102extern Atom Xatom_wm_save_yourself;
103extern Atom Xatom_wm_delete_window;
104
105/* Other WM communication */
c047688c
JA
106extern Atom Xatom_wm_configure_denied; /* When our config request is denied */
107extern Atom Xatom_wm_window_moved; /* When the WM moves us. */
3c254570 108
01f1ba30
JB
109#else /* X10 */
110
179956b9 111/* Default size of an Emacs window. */
01f1ba30
JB
112static char *default_window = "=80x24+0+0";
113
114#define MAXICID 80
115char iconidentity[MAXICID];
116#define ICONTAG "emacs@"
117char minibuffer_iconidentity[MAXICID];
118#define MINIBUFFER_ICONTAG "minibuffer@"
119
120#endif /* X10 */
121
122/* The last 23 bits of the timestamp of the last mouse button event. */
123Time mouse_timestamp;
124
f9942c9e
JB
125/* Evaluate this expression to rebuild the section of syms_of_xfns
126 that initializes and staticpros the symbols declared below. Note
127 that Emacs 18 has a bug that keeps C-x C-e from being able to
128 evaluate this expression.
129
130(progn
131 ;; Accumulate a list of the symbols we want to initialize from the
132 ;; declarations at the top of the file.
133 (goto-char (point-min))
134 (search-forward "/\*&&& symbols declared here &&&*\/\n")
135 (let (symbol-list)
136 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
137 (setq symbol-list
138 (cons (buffer-substring (match-beginning 1) (match-end 1))
139 symbol-list))
140 (forward-line 1))
141 (setq symbol-list (nreverse symbol-list))
142 ;; Delete the section of syms_of_... where we initialize the symbols.
143 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
144 (let ((start (point)))
145 (while (looking-at "^ Q")
146 (forward-line 2))
147 (kill-region start (point)))
148 ;; Write a new symbol initialization section.
149 (while symbol-list
150 (insert (format " %s = intern (\"" (car symbol-list)))
151 (let ((start (point)))
152 (insert (substring (car symbol-list) 1))
153 (subst-char-in-region start (point) ?_ ?-))
154 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
155 (setq symbol-list (cdr symbol-list)))))
156
157 */
158
159/*&&& symbols declared here &&&*/
160Lisp_Object Qauto_raise;
161Lisp_Object Qauto_lower;
162Lisp_Object Qbackground_color;
dbc4e1c1 163Lisp_Object Qbar;
f9942c9e
JB
164Lisp_Object Qborder_color;
165Lisp_Object Qborder_width;
dbc4e1c1 166Lisp_Object Qbox;
f9942c9e 167Lisp_Object Qcursor_color;
dbc4e1c1 168Lisp_Object Qcursor_type;
f9942c9e
JB
169Lisp_Object Qfont;
170Lisp_Object Qforeground_color;
171Lisp_Object Qgeometry;
49795535 172Lisp_Object Qicon;
f9942c9e
JB
173Lisp_Object Qicon_left;
174Lisp_Object Qicon_top;
175Lisp_Object Qicon_type;
f9942c9e
JB
176Lisp_Object Qinternal_border_width;
177Lisp_Object Qleft;
178Lisp_Object Qmouse_color;
baaed68e 179Lisp_Object Qnone;
f9942c9e 180Lisp_Object Qparent_id;
8af1d7ca 181Lisp_Object Qsuppress_icon;
f9942c9e 182Lisp_Object Qtop;
01f1ba30 183Lisp_Object Qundefined_color;
a3c87d4e 184Lisp_Object Qvertical_scroll_bars;
49795535 185Lisp_Object Qvisibility;
f9942c9e 186Lisp_Object Qwindow_id;
f676886a 187Lisp_Object Qx_frame_parameter;
01f1ba30 188
f9942c9e 189/* The below are defined in frame.c. */
baaed68e 190extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
d043f1a4 191extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qicon;
f9942c9e 192
01f1ba30
JB
193extern Lisp_Object Vwindow_system_version;
194
195/* Mouse map for clicks in windows. */
196extern Lisp_Object Vglobal_mouse_map;
197
01f1ba30 198\f
11ae94fe
RS
199/* Error if we are not connected to X. */
200static void
201check_x ()
202{
203 if (x_current_display == 0)
204 error ("X windows are not in use or not initialized");
205}
206
f676886a
JB
207/* Return the Emacs frame-object corresponding to an X window.
208 It could be the frame's main window or an icon window. */
01f1ba30 209
bcb2db92
RS
210/* This function can be called during GC, so use XGCTYPE. */
211
f676886a
JB
212struct frame *
213x_window_to_frame (wdesc)
01f1ba30
JB
214 int wdesc;
215{
f676886a
JB
216 Lisp_Object tail, frame;
217 struct frame *f;
01f1ba30 218
bcb2db92
RS
219 for (tail = Vframe_list; XGCTYPE (tail) == Lisp_Cons;
220 tail = XCONS (tail)->cdr)
01f1ba30 221 {
f676886a 222 frame = XCONS (tail)->car;
bcb2db92 223 if (XGCTYPE (frame) != Lisp_Frame)
01f1ba30 224 continue;
f676886a 225 f = XFRAME (frame);
fe24a618 226 if (FRAME_X_WINDOW (f) == wdesc
f676886a
JB
227 || f->display.x->icon_desc == wdesc)
228 return f;
01f1ba30
JB
229 }
230 return 0;
231}
232
01f1ba30 233\f
f676886a 234/* Connect the frame-parameter names for X frames
01f1ba30
JB
235 to the ways of passing the parameter values to the window system.
236
237 The name of a parameter, as a Lisp symbol,
f676886a
JB
238 has an `x-frame-parameter' property which is an integer in Lisp
239 but can be interpreted as an `enum x_frame_parm' in C. */
01f1ba30 240
f676886a 241enum x_frame_parm
01f1ba30
JB
242{
243 X_PARM_FOREGROUND_COLOR,
244 X_PARM_BACKGROUND_COLOR,
245 X_PARM_MOUSE_COLOR,
246 X_PARM_CURSOR_COLOR,
247 X_PARM_BORDER_COLOR,
248 X_PARM_ICON_TYPE,
249 X_PARM_FONT,
250 X_PARM_BORDER_WIDTH,
251 X_PARM_INTERNAL_BORDER_WIDTH,
252 X_PARM_NAME,
253 X_PARM_AUTORAISE,
254 X_PARM_AUTOLOWER,
a3c87d4e 255 X_PARM_VERT_SCROLL_BAR,
d043f1a4
RS
256 X_PARM_VISIBILITY,
257 X_PARM_MENU_BAR_LINES
01f1ba30
JB
258};
259
260
f676886a 261struct x_frame_parm_table
01f1ba30
JB
262{
263 char *name;
f676886a 264 void (*setter)( /* struct frame *frame, Lisp_Object val, oldval */ );
01f1ba30
JB
265};
266
267void x_set_foreground_color ();
268void x_set_background_color ();
269void x_set_mouse_color ();
270void x_set_cursor_color ();
271void x_set_border_color ();
dbc4e1c1 272void x_set_cursor_type ();
01f1ba30
JB
273void x_set_icon_type ();
274void x_set_font ();
275void x_set_border_width ();
276void x_set_internal_border_width ();
f945b920 277void x_explicitly_set_name ();
01f1ba30
JB
278void x_set_autoraise ();
279void x_set_autolower ();
a3c87d4e 280void x_set_vertical_scroll_bars ();
d043f1a4
RS
281void x_set_visibility ();
282void x_set_menu_bar_lines ();
01f1ba30 283
f676886a 284static struct x_frame_parm_table x_frame_parms[] =
01f1ba30
JB
285{
286 "foreground-color", x_set_foreground_color,
287 "background-color", x_set_background_color,
288 "mouse-color", x_set_mouse_color,
289 "cursor-color", x_set_cursor_color,
290 "border-color", x_set_border_color,
dbc4e1c1 291 "cursor-type", x_set_cursor_type,
01f1ba30
JB
292 "icon-type", x_set_icon_type,
293 "font", x_set_font,
294 "border-width", x_set_border_width,
295 "internal-border-width", x_set_internal_border_width,
f945b920 296 "name", x_explicitly_set_name,
baaed68e
JB
297 "auto-raise", x_set_autoraise,
298 "auto-lower", x_set_autolower,
a3c87d4e 299 "vertical-scroll-bars", x_set_vertical_scroll_bars,
d043f1a4
RS
300 "visibility", x_set_visibility,
301 "menu-bar-lines", x_set_menu_bar_lines,
01f1ba30
JB
302};
303
f676886a 304/* Attach the `x-frame-parameter' properties to
01f1ba30
JB
305 the Lisp symbol names of parameters relevant to X. */
306
307init_x_parm_symbols ()
308{
309 int i;
310
d043f1a4 311 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
f676886a 312 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
01f1ba30
JB
313 make_number (i));
314}
315\f
f9942c9e
JB
316/* Change the parameters of FRAME as specified by ALIST.
317 If a parameter is not specially recognized, do nothing;
318 otherwise call the `x_set_...' function for that parameter. */
d043f1a4 319
f9942c9e
JB
320void
321x_set_frame_parameters (f, alist)
322 FRAME_PTR f;
323 Lisp_Object alist;
324{
325 Lisp_Object tail;
326
327 /* If both of these parameters are present, it's more efficient to
328 set them both at once. So we wait until we've looked at the
329 entire list before we set them. */
330 Lisp_Object width, height;
331
332 /* Same here. */
333 Lisp_Object left, top;
f9942c9e 334
312b93ee 335 width = height = top = left = Qnil;
f9942c9e
JB
336
337 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
338 {
339 Lisp_Object elt, prop, val;
340
341 elt = Fcar (tail);
342 prop = Fcar (elt);
343 val = Fcdr (elt);
344
312b93ee
JB
345 /* Ignore all but the first set presented. You're supposed to
346 be able to append two parameter lists and have the first
347 shadow the second. */
348 if (EQ (prop, Qwidth) && NILP (width))
f9942c9e 349 width = val;
312b93ee 350 else if (EQ (prop, Qheight) && NILP (height))
f9942c9e 351 height = val;
312b93ee 352 else if (EQ (prop, Qtop) && NILP (top))
f9942c9e 353 top = val;
312b93ee 354 else if (EQ (prop, Qleft) && NILP (left))
f9942c9e
JB
355 left = val;
356 else
357 {
ea96210c
JB
358 register Lisp_Object param_index = Fget (prop, Qx_frame_parameter);
359 register Lisp_Object old_value = get_frame_param (f, prop);
360
f9942c9e 361 store_frame_param (f, prop, val);
ea96210c
JB
362 if (XTYPE (param_index) == Lisp_Int
363 && XINT (param_index) >= 0
364 && (XINT (param_index)
365 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
366 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
f9942c9e
JB
367 }
368 }
369
370 /* Don't call these unless they've changed; the window may not actually
371 exist yet. */
372 {
373 Lisp_Object frame;
374
312b93ee
JB
375 if (NILP (width)) XSET (width, Lisp_Int, FRAME_WIDTH (f));
376 if (NILP (height)) XSET (height, Lisp_Int, FRAME_HEIGHT (f));
377
378 if (NILP (top)) XSET (top, Lisp_Int, f->display.x->top_pos);
379 if (NILP (left)) XSET (left, Lisp_Int, f->display.x->left_pos);
380
f9942c9e
JB
381 XSET (frame, Lisp_Frame, f);
382 if (XINT (width) != FRAME_WIDTH (f)
383 || XINT (height) != FRAME_HEIGHT (f))
384 Fset_frame_size (frame, width, height);
385 if (XINT (left) != f->display.x->left_pos
386 || XINT (top) != f->display.x->top_pos)
387 Fset_frame_position (frame, left, top);
388 }
389}
01f1ba30 390
f676886a 391/* Insert a description of internally-recorded parameters of frame X
01f1ba30
JB
392 into the parameter alist *ALISTPTR that is to be given to the user.
393 Only parameters that are specific to the X window system
f676886a 394 and whose values are not correctly recorded in the frame's
01f1ba30
JB
395 param_alist need to be considered here. */
396
f676886a
JB
397x_report_frame_params (f, alistptr)
398 struct frame *f;
01f1ba30
JB
399 Lisp_Object *alistptr;
400{
401 char buf[16];
402
f9942c9e
JB
403 store_in_alist (alistptr, Qleft, make_number (f->display.x->left_pos));
404 store_in_alist (alistptr, Qtop, make_number (f->display.x->top_pos));
405 store_in_alist (alistptr, Qborder_width,
f676886a 406 make_number (f->display.x->border_width));
f9942c9e 407 store_in_alist (alistptr, Qinternal_border_width,
f676886a 408 make_number (f->display.x->internal_border_width));
fe24a618 409 sprintf (buf, "%d", FRAME_X_WINDOW (f));
f9942c9e 410 store_in_alist (alistptr, Qwindow_id,
01f1ba30 411 build_string (buf));
d043f1a4
RS
412 store_in_alist (alistptr, Qvisibility,
413 (FRAME_VISIBLE_P (f) ? Qt
414 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
01f1ba30
JB
415}
416\f
417/* Decide if color named COLOR is valid for the display
f676886a 418 associated with the selected frame. */
01f1ba30
JB
419int
420defined_color (color, color_def)
421 char *color;
422 Color *color_def;
423{
424 register int foo;
425 Colormap screen_colormap;
426
427 BLOCK_INPUT;
428#ifdef HAVE_X11
429 screen_colormap
430 = DefaultColormap (x_current_display, XDefaultScreen (x_current_display));
431
432 foo = XParseColor (x_current_display, screen_colormap,
433 color, color_def)
434 && XAllocColor (x_current_display, screen_colormap, color_def);
435#else
436 foo = XParseColor (color, color_def) && XGetHardwareColor (color_def);
437#endif /* not HAVE_X11 */
438 UNBLOCK_INPUT;
439
440 if (foo)
441 return 1;
442 else
443 return 0;
444}
445
446/* Given a string ARG naming a color, compute a pixel value from it
f676886a
JB
447 suitable for screen F.
448 If F is not a color screen, return DEF (default) regardless of what
01f1ba30
JB
449 ARG says. */
450
451int
452x_decode_color (arg, def)
453 Lisp_Object arg;
454 int def;
455{
456 Color cdef;
457
458 CHECK_STRING (arg, 0);
459
460 if (strcmp (XSTRING (arg)->data, "black") == 0)
461 return BLACK_PIX_DEFAULT;
462 else if (strcmp (XSTRING (arg)->data, "white") == 0)
463 return WHITE_PIX_DEFAULT;
464
465#ifdef HAVE_X11
a6605e5c 466 if (x_screen_planes == 1)
01f1ba30
JB
467 return def;
468#else
265a9e55 469 if (DISPLAY_CELLS == 1)
01f1ba30
JB
470 return def;
471#endif
472
473 if (defined_color (XSTRING (arg)->data, &cdef))
474 return cdef.pixel;
475 else
476 Fsignal (Qundefined_color, Fcons (arg, Qnil));
477}
478\f
f676886a 479/* Functions called only from `x_set_frame_param'
01f1ba30
JB
480 to set individual parameters.
481
fe24a618 482 If FRAME_X_WINDOW (f) is 0,
f676886a 483 the frame is being created and its X-window does not exist yet.
01f1ba30
JB
484 In that case, just record the parameter's new value
485 in the standard place; do not attempt to change the window. */
486
487void
f676886a
JB
488x_set_foreground_color (f, arg, oldval)
489 struct frame *f;
01f1ba30
JB
490 Lisp_Object arg, oldval;
491{
f676886a 492 f->display.x->foreground_pixel = x_decode_color (arg, BLACK_PIX_DEFAULT);
fe24a618 493 if (FRAME_X_WINDOW (f) != 0)
01f1ba30
JB
494 {
495#ifdef HAVE_X11
496 BLOCK_INPUT;
f676886a
JB
497 XSetForeground (x_current_display, f->display.x->normal_gc,
498 f->display.x->foreground_pixel);
499 XSetBackground (x_current_display, f->display.x->reverse_gc,
500 f->display.x->foreground_pixel);
01f1ba30
JB
501 UNBLOCK_INPUT;
502#endif /* HAVE_X11 */
ea96210c 503 recompute_basic_faces (f);
179956b9 504 if (FRAME_VISIBLE_P (f))
f676886a 505 redraw_frame (f);
01f1ba30
JB
506 }
507}
508
509void
f676886a
JB
510x_set_background_color (f, arg, oldval)
511 struct frame *f;
01f1ba30
JB
512 Lisp_Object arg, oldval;
513{
514 Pixmap temp;
515 int mask;
516
f676886a 517 f->display.x->background_pixel = x_decode_color (arg, WHITE_PIX_DEFAULT);
01f1ba30 518
fe24a618 519 if (FRAME_X_WINDOW (f) != 0)
01f1ba30
JB
520 {
521 BLOCK_INPUT;
522#ifdef HAVE_X11
f676886a
JB
523 /* The main frame area. */
524 XSetBackground (x_current_display, f->display.x->normal_gc,
525 f->display.x->background_pixel);
526 XSetForeground (x_current_display, f->display.x->reverse_gc,
527 f->display.x->background_pixel);
fe24a618 528 XSetWindowBackground (x_current_display, FRAME_X_WINDOW (f),
f676886a 529 f->display.x->background_pixel);
01f1ba30 530
01f1ba30 531#else
f676886a 532 temp = XMakeTile (f->display.x->background_pixel);
fe24a618 533 XChangeBackground (FRAME_X_WINDOW (f), temp);
01f1ba30
JB
534 XFreePixmap (temp);
535#endif /* not HAVE_X11 */
536 UNBLOCK_INPUT;
537
ea96210c
JB
538 recompute_basic_faces (f);
539
179956b9 540 if (FRAME_VISIBLE_P (f))
f676886a 541 redraw_frame (f);
01f1ba30
JB
542 }
543}
544
545void
f676886a
JB
546x_set_mouse_color (f, arg, oldval)
547 struct frame *f;
01f1ba30
JB
548 Lisp_Object arg, oldval;
549{
550 Cursor cursor, nontext_cursor, mode_cursor;
551 int mask_color;
552
553 if (!EQ (Qnil, arg))
f676886a
JB
554 f->display.x->mouse_pixel = x_decode_color (arg, BLACK_PIX_DEFAULT);
555 mask_color = f->display.x->background_pixel;
01f1ba30 556 /* No invisible pointers. */
f676886a
JB
557 if (mask_color == f->display.x->mouse_pixel
558 && mask_color == f->display.x->background_pixel)
559 f->display.x->mouse_pixel = f->display.x->foreground_pixel;
01f1ba30
JB
560
561 BLOCK_INPUT;
562#ifdef HAVE_X11
fe24a618
JB
563
564 /* It's not okay to crash if the user selects a screwey cursor. */
565 x_catch_errors ();
566
01f1ba30
JB
567 if (!EQ (Qnil, Vx_pointer_shape))
568 {
569 CHECK_NUMBER (Vx_pointer_shape, 0);
570 cursor = XCreateFontCursor (x_current_display, XINT (Vx_pointer_shape));
571 }
572 else
573 cursor = XCreateFontCursor (x_current_display, XC_xterm);
a6605e5c 574 x_check_errors ("bad text pointer cursor: %s");
01f1ba30
JB
575
576 if (!EQ (Qnil, Vx_nontext_pointer_shape))
577 {
578 CHECK_NUMBER (Vx_nontext_pointer_shape, 0);
579 nontext_cursor = XCreateFontCursor (x_current_display,
580 XINT (Vx_nontext_pointer_shape));
581 }
582 else
583 nontext_cursor = XCreateFontCursor (x_current_display, XC_left_ptr);
a6605e5c 584 x_check_errors ("bad nontext pointer cursor: %s");
01f1ba30
JB
585
586 if (!EQ (Qnil, Vx_mode_pointer_shape))
587 {
588 CHECK_NUMBER (Vx_mode_pointer_shape, 0);
589 mode_cursor = XCreateFontCursor (x_current_display,
590 XINT (Vx_mode_pointer_shape));
591 }
592 else
593 mode_cursor = XCreateFontCursor (x_current_display, XC_xterm);
594
fe24a618
JB
595 /* Check and report errors with the above calls. */
596 x_check_errors ("can't set cursor shape: %s");
597 x_uncatch_errors ();
598
01f1ba30
JB
599 {
600 XColor fore_color, back_color;
601
f676886a 602 fore_color.pixel = f->display.x->mouse_pixel;
01f1ba30
JB
603 back_color.pixel = mask_color;
604 XQueryColor (x_current_display,
605 DefaultColormap (x_current_display,
606 DefaultScreen (x_current_display)),
607 &fore_color);
608 XQueryColor (x_current_display,
609 DefaultColormap (x_current_display,
610 DefaultScreen (x_current_display)),
611 &back_color);
612 XRecolorCursor (x_current_display, cursor,
613 &fore_color, &back_color);
614 XRecolorCursor (x_current_display, nontext_cursor,
615 &fore_color, &back_color);
616 XRecolorCursor (x_current_display, mode_cursor,
617 &fore_color, &back_color);
618 }
619#else /* X10 */
620 cursor = XCreateCursor (16, 16, MouseCursor, MouseMask,
621 0, 0,
f676886a
JB
622 f->display.x->mouse_pixel,
623 f->display.x->background_pixel,
01f1ba30
JB
624 GXcopy);
625#endif /* X10 */
626
fe24a618 627 if (FRAME_X_WINDOW (f) != 0)
01f1ba30 628 {
fe24a618 629 XDefineCursor (XDISPLAY FRAME_X_WINDOW (f), cursor);
01f1ba30
JB
630 }
631
f676886a
JB
632 if (cursor != f->display.x->text_cursor && f->display.x->text_cursor != 0)
633 XFreeCursor (XDISPLAY f->display.x->text_cursor);
634 f->display.x->text_cursor = cursor;
01f1ba30 635#ifdef HAVE_X11
f676886a
JB
636 if (nontext_cursor != f->display.x->nontext_cursor
637 && f->display.x->nontext_cursor != 0)
638 XFreeCursor (XDISPLAY f->display.x->nontext_cursor);
639 f->display.x->nontext_cursor = nontext_cursor;
640
641 if (mode_cursor != f->display.x->modeline_cursor
642 && f->display.x->modeline_cursor != 0)
643 XFreeCursor (XDISPLAY f->display.x->modeline_cursor);
644 f->display.x->modeline_cursor = mode_cursor;
01f1ba30
JB
645#endif /* HAVE_X11 */
646
647 XFlushQueue ();
648 UNBLOCK_INPUT;
649}
650
651void
f676886a
JB
652x_set_cursor_color (f, arg, oldval)
653 struct frame *f;
01f1ba30
JB
654 Lisp_Object arg, oldval;
655{
656 unsigned long fore_pixel;
657
658 if (!EQ (Vx_cursor_fore_pixel, Qnil))
659 fore_pixel = x_decode_color (Vx_cursor_fore_pixel, WHITE_PIX_DEFAULT);
660 else
f676886a
JB
661 fore_pixel = f->display.x->background_pixel;
662 f->display.x->cursor_pixel = x_decode_color (arg, BLACK_PIX_DEFAULT);
f9942c9e
JB
663
664 /* Make sure that the cursor color differs from the background color. */
f676886a 665 if (f->display.x->cursor_pixel == f->display.x->background_pixel)
01f1ba30 666 {
f676886a
JB
667 f->display.x->cursor_pixel == f->display.x->mouse_pixel;
668 if (f->display.x->cursor_pixel == fore_pixel)
669 fore_pixel = f->display.x->background_pixel;
01f1ba30 670 }
c49cbce2 671 f->display.x->cursor_foreground_pixel = fore_pixel;
01f1ba30 672
fe24a618 673 if (FRAME_X_WINDOW (f) != 0)
01f1ba30
JB
674 {
675#ifdef HAVE_X11
676 BLOCK_INPUT;
f676886a
JB
677 XSetBackground (x_current_display, f->display.x->cursor_gc,
678 f->display.x->cursor_pixel);
679 XSetForeground (x_current_display, f->display.x->cursor_gc,
01f1ba30
JB
680 fore_pixel);
681 UNBLOCK_INPUT;
682#endif /* HAVE_X11 */
683
179956b9 684 if (FRAME_VISIBLE_P (f))
01f1ba30 685 {
f676886a
JB
686 x_display_cursor (f, 0);
687 x_display_cursor (f, 1);
01f1ba30
JB
688 }
689 }
690}
691
f676886a 692/* Set the border-color of frame F to value described by ARG.
01f1ba30
JB
693 ARG can be a string naming a color.
694 The border-color is used for the border that is drawn by the X server.
695 Note that this does not fully take effect if done before
f676886a 696 F has an x-window; it must be redone when the window is created.
01f1ba30
JB
697
698 Note: this is done in two routines because of the way X10 works.
699
700 Note: under X11, this is normally the province of the window manager,
701 and so emacs' border colors may be overridden. */
702
703void
f676886a
JB
704x_set_border_color (f, arg, oldval)
705 struct frame *f;
01f1ba30
JB
706 Lisp_Object arg, oldval;
707{
708 unsigned char *str;
709 int pix;
710
711 CHECK_STRING (arg, 0);
712 str = XSTRING (arg)->data;
713
714#ifndef HAVE_X11
715 if (!strcmp (str, "grey") || !strcmp (str, "Grey")
716 || !strcmp (str, "gray") || !strcmp (str, "Gray"))
717 pix = -1;
718 else
719#endif /* X10 */
720
721 pix = x_decode_color (arg, BLACK_PIX_DEFAULT);
722
f676886a 723 x_set_border_pixel (f, pix);
01f1ba30
JB
724}
725
f676886a 726/* Set the border-color of frame F to pixel value PIX.
01f1ba30 727 Note that this does not fully take effect if done before
f676886a 728 F has an x-window. */
01f1ba30 729
f676886a
JB
730x_set_border_pixel (f, pix)
731 struct frame *f;
01f1ba30
JB
732 int pix;
733{
f676886a 734 f->display.x->border_pixel = pix;
01f1ba30 735
fe24a618 736 if (FRAME_X_WINDOW (f) != 0 && f->display.x->border_width > 0)
01f1ba30
JB
737 {
738 Pixmap temp;
739 int mask;
740
741 BLOCK_INPUT;
742#ifdef HAVE_X11
fe24a618 743 XSetWindowBorder (x_current_display, FRAME_X_WINDOW (f),
01f1ba30 744 pix);
01f1ba30
JB
745#else
746 if (pix < 0)
dbc4e1c1
JB
747 temp = XMakePixmap ((Bitmap) XStoreBitmap (gray_width, gray_height,
748 gray_bits),
01f1ba30
JB
749 BLACK_PIX_DEFAULT, WHITE_PIX_DEFAULT);
750 else
751 temp = XMakeTile (pix);
fe24a618 752 XChangeBorder (FRAME_X_WINDOW (f), temp);
01f1ba30
JB
753 XFreePixmap (XDISPLAY temp);
754#endif /* not HAVE_X11 */
755 UNBLOCK_INPUT;
756
179956b9 757 if (FRAME_VISIBLE_P (f))
f676886a 758 redraw_frame (f);
01f1ba30
JB
759 }
760}
761
dbc4e1c1
JB
762void
763x_set_cursor_type (f, arg, oldval)
764 FRAME_PTR f;
765 Lisp_Object arg, oldval;
766{
767 if (EQ (arg, Qbar))
768 FRAME_DESIRED_CURSOR (f) = bar_cursor;
15ab234b
RS
769 else
770#if 0
771 if (EQ (arg, Qbox))
772#endif
773 FRAME_DESIRED_CURSOR (f) = filled_box_cursor;
774 /* Error messages commented out because people have trouble fixing
775 .Xdefaults with Emacs, when it has something bad in it. */
776#if 0
dbc4e1c1
JB
777 else
778 error
779 ("the `cursor-type' frame parameter should be either `bar' or `box'");
15ab234b 780#endif
dbc4e1c1
JB
781
782 /* Make sure the cursor gets redrawn. This is overkill, but how
783 often do people change cursor types? */
784 update_mode_lines++;
785}
786
01f1ba30 787void
f676886a
JB
788x_set_icon_type (f, arg, oldval)
789 struct frame *f;
01f1ba30
JB
790 Lisp_Object arg, oldval;
791{
792 Lisp_Object tem;
793 int result;
794
795 if (EQ (oldval, Qnil) == EQ (arg, Qnil))
796 return;
797
798 BLOCK_INPUT;
265a9e55 799 if (NILP (arg))
f676886a 800 result = x_text_icon (f, 0);
01f1ba30 801 else
f111a131 802 result = x_bitmap_icon (f);
01f1ba30
JB
803
804 if (result)
805 {
01f1ba30 806 UNBLOCK_INPUT;
f9942c9e 807 error ("No icon window available.");
01f1ba30
JB
808 }
809
810 /* If the window was unmapped (and its icon was mapped),
811 the new icon is not mapped, so map the window in its stead. */
179956b9 812 if (FRAME_VISIBLE_P (f))
fe24a618 813 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
01f1ba30
JB
814
815 XFlushQueue ();
816 UNBLOCK_INPUT;
817}
818
ea96210c
JB
819extern Lisp_Object x_new_font ();
820
01f1ba30 821void
f676886a
JB
822x_set_font (f, arg, oldval)
823 struct frame *f;
01f1ba30
JB
824 Lisp_Object arg, oldval;
825{
ea96210c 826 Lisp_Object result;
01f1ba30
JB
827
828 CHECK_STRING (arg, 1);
01f1ba30
JB
829
830 BLOCK_INPUT;
ea96210c 831 result = x_new_font (f, XSTRING (arg)->data);
01f1ba30
JB
832 UNBLOCK_INPUT;
833
ea96210c
JB
834 if (EQ (result, Qnil))
835 error ("Font \"%s\" is not defined", XSTRING (arg)->data);
836 else if (EQ (result, Qt))
c7e1d890 837 error ("the characters of the given font have varying widths");
ea96210c
JB
838 else if (STRINGP (result))
839 {
840 recompute_basic_faces (f);
841 store_frame_param (f, Qfont, result);
842 }
843 else
844 abort ();
01f1ba30
JB
845}
846
847void
f676886a
JB
848x_set_border_width (f, arg, oldval)
849 struct frame *f;
01f1ba30
JB
850 Lisp_Object arg, oldval;
851{
852 CHECK_NUMBER (arg, 0);
853
f676886a 854 if (XINT (arg) == f->display.x->border_width)
01f1ba30
JB
855 return;
856
fe24a618 857 if (FRAME_X_WINDOW (f) != 0)
01f1ba30
JB
858 error ("Cannot change the border width of a window");
859
f676886a 860 f->display.x->border_width = XINT (arg);
01f1ba30
JB
861}
862
863void
f676886a
JB
864x_set_internal_border_width (f, arg, oldval)
865 struct frame *f;
01f1ba30
JB
866 Lisp_Object arg, oldval;
867{
868 int mask;
f676886a 869 int old = f->display.x->internal_border_width;
01f1ba30
JB
870
871 CHECK_NUMBER (arg, 0);
f676886a
JB
872 f->display.x->internal_border_width = XINT (arg);
873 if (f->display.x->internal_border_width < 0)
874 f->display.x->internal_border_width = 0;
01f1ba30 875
f676886a 876 if (f->display.x->internal_border_width == old)
01f1ba30
JB
877 return;
878
fe24a618 879 if (FRAME_X_WINDOW (f) != 0)
01f1ba30
JB
880 {
881 BLOCK_INPUT;
f676886a 882 x_set_window_size (f, f->width, f->height);
01f1ba30 883#if 0
f676886a 884 x_set_resize_hint (f);
01f1ba30
JB
885#endif
886 XFlushQueue ();
887 UNBLOCK_INPUT;
f676886a 888 SET_FRAME_GARBAGED (f);
01f1ba30
JB
889 }
890}
891
d043f1a4
RS
892void
893x_set_visibility (f, value, oldval)
894 struct frame *f;
895 Lisp_Object value, oldval;
896{
897 Lisp_Object frame;
898 XSET (frame, Lisp_Frame, f);
899
900 if (NILP (value))
901 Fmake_frame_invisible (frame);
49795535 902 else if (EQ (value, Qicon))
d043f1a4 903 Ficonify_frame (frame);
49795535
JB
904 else
905 Fmake_frame_visible (frame);
d043f1a4
RS
906}
907
908static void
909x_set_menu_bar_lines_1 (window, n)
910 Lisp_Object window;
911 int n;
912{
913 for (; !NILP (window); window = XWINDOW (window)->next)
914 {
915 struct window *w = XWINDOW (window);
916
11ae94fe 917 XFASTINT (w->top) += n;
d043f1a4
RS
918
919 if (!NILP (w->vchild))
11ae94fe 920 x_set_menu_bar_lines_1 (w->vchild, n);
d043f1a4
RS
921
922 if (!NILP (w->hchild))
11ae94fe 923 x_set_menu_bar_lines_1 (w->hchild, n);
d043f1a4
RS
924 }
925}
926
927void
928x_set_menu_bar_lines (f, value, oldval)
929 struct frame *f;
930 Lisp_Object value, oldval;
931{
932 int nlines;
933 int olines = FRAME_MENU_BAR_LINES (f);
934
f64ba6ea
JB
935 /* Right now, menu bars don't work properly in minibuf-only frames;
936 most of the commands try to apply themselves to the minibuffer
937 frame itslef, and get an error because you can't switch buffers
938 in or split the minibuffer window. */
519066d2 939 if (FRAME_MINIBUF_ONLY_P (f))
f64ba6ea
JB
940 return;
941
d043f1a4
RS
942 if (XTYPE (value) == Lisp_Int)
943 nlines = XINT (value);
944 else
945 nlines = 0;
946
947 FRAME_MENU_BAR_LINES (f) = nlines;
948 x_set_menu_bar_lines_1 (f->root_window, nlines - olines);
714fd2ea
RS
949 /* Use FRAME_NEW_WIDTH, HEIGHT so as not to override a size change
950 made by the user but not fully reflected in the Emacs frame object. */
951 x_set_window_size (f,
952 (FRAME_NEW_WIDTH (f)
953 ? FRAME_NEW_WIDTH (f)
954 : FRAME_WIDTH (f)),
955 ((FRAME_NEW_HEIGHT (f)
956 ? FRAME_NEW_HEIGHT (f)
957 : FRAME_HEIGHT (f))
958 + nlines - olines));
d043f1a4
RS
959}
960
f945b920
JB
961/* Change the name of frame F to ARG. If ARG is nil, set F's name to
962 x_id_name.
963
964 If EXPLICIT is non-zero, that indicates that lisp code is setting the
965 name; if ARG is a string, set F's name to ARG and set
966 F->explicit_name; if ARG is Qnil, then clear F->explicit_name.
967
968 If EXPLICIT is zero, that indicates that Emacs redisplay code is
969 suggesting a new name, which lisp code should override; if
970 F->explicit_name is set, ignore the new name; otherwise, set it. */
971
972void
973x_set_name (f, name, explicit)
974 struct frame *f;
975 Lisp_Object name;
976 int explicit;
977{
978 /* Make sure that requests from lisp code override requests from
979 Emacs redisplay code. */
980 if (explicit)
981 {
982 /* If we're switching from explicit to implicit, we had better
983 update the mode lines and thereby update the title. */
984 if (f->explicit_name && NILP (name))
cf177271 985 update_mode_lines = 1;
f945b920
JB
986
987 f->explicit_name = ! NILP (name);
988 }
989 else if (f->explicit_name)
990 return;
991
992 /* If NAME is nil, set the name to the x_id_name. */
993 if (NILP (name))
994 name = build_string (x_id_name);
62265f1c 995 else
f945b920 996 CHECK_STRING (name, 0);
01f1ba30 997
f945b920
JB
998 /* Don't change the name if it's already NAME. */
999 if (! NILP (Fstring_equal (name, f->name)))
daa37602
JB
1000 return;
1001
fe24a618 1002 if (FRAME_X_WINDOW (f))
01f1ba30 1003 {
01f1ba30 1004 BLOCK_INPUT;
fe24a618
JB
1005
1006#ifdef HAVE_X11R4
1007 {
1008 XTextProperty text;
1009 text.value = XSTRING (name)->data;
1010 text.encoding = XA_STRING;
1011 text.format = 8;
1012 text.nitems = XSTRING (name)->size;
1013 XSetWMName (x_current_display, FRAME_X_WINDOW (f), &text);
1014 XSetWMIconName (x_current_display, FRAME_X_WINDOW (f), &text);
1015 }
1016#else
1017 XSetIconName (XDISPLAY FRAME_X_WINDOW (f),
1018 XSTRING (name)->data);
1019 XStoreName (XDISPLAY FRAME_X_WINDOW (f),
1020 XSTRING (name)->data);
1021#endif
1022
01f1ba30
JB
1023 UNBLOCK_INPUT;
1024 }
daa37602 1025
f945b920
JB
1026 f->name = name;
1027}
1028
1029/* This function should be called when the user's lisp code has
1030 specified a name for the frame; the name will override any set by the
1031 redisplay code. */
1032void
1033x_explicitly_set_name (f, arg, oldval)
1034 FRAME_PTR f;
1035 Lisp_Object arg, oldval;
1036{
1037 x_set_name (f, arg, 1);
1038}
1039
1040/* This function should be called by Emacs redisplay code to set the
1041 name; names set this way will never override names set by the user's
1042 lisp code. */
25250031 1043void
f945b920
JB
1044x_implicitly_set_name (f, arg, oldval)
1045 FRAME_PTR f;
1046 Lisp_Object arg, oldval;
1047{
1048 x_set_name (f, arg, 0);
01f1ba30
JB
1049}
1050
1051void
f676886a
JB
1052x_set_autoraise (f, arg, oldval)
1053 struct frame *f;
01f1ba30
JB
1054 Lisp_Object arg, oldval;
1055{
f676886a 1056 f->auto_raise = !EQ (Qnil, arg);
01f1ba30
JB
1057}
1058
1059void
f676886a
JB
1060x_set_autolower (f, arg, oldval)
1061 struct frame *f;
01f1ba30
JB
1062 Lisp_Object arg, oldval;
1063{
f676886a 1064 f->auto_lower = !EQ (Qnil, arg);
01f1ba30 1065}
179956b9
JB
1066
1067void
a3c87d4e 1068x_set_vertical_scroll_bars (f, arg, oldval)
179956b9
JB
1069 struct frame *f;
1070 Lisp_Object arg, oldval;
1071{
a3c87d4e 1072 if (NILP (arg) != ! FRAME_HAS_VERTICAL_SCROLL_BARS (f))
179956b9 1073 {
a3c87d4e 1074 FRAME_HAS_VERTICAL_SCROLL_BARS (f) = ! NILP (arg);
179956b9 1075
cf177271
JB
1076 /* We set this parameter before creating the X window for the
1077 frame, so we can get the geometry right from the start.
1078 However, if the window hasn't been created yet, we shouldn't
1079 call x_set_window_size. */
1080 if (FRAME_X_WINDOW (f))
1081 x_set_window_size (f, FRAME_WIDTH (f), FRAME_HEIGHT (f));
179956b9
JB
1082 }
1083}
01f1ba30 1084\f
f676886a 1085/* Subroutines of creating an X frame. */
01f1ba30
JB
1086
1087#ifdef HAVE_X11
1088extern char *x_get_string_resource ();
1089extern XrmDatabase x_load_resources ();
1090
cf177271
JB
1091DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
1092 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
1093This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
1094class, where INSTANCE is the name under which Emacs was invoked.\n\
01f1ba30 1095\n\
8fabe6f4
RS
1096The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
1097class, respectively. You must specify both of them or neither.\n\
1098If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
cf177271
JB
1099and the class is `Emacs.CLASS.SUBCLASS'.")
1100 (attribute, class, component, subclass)
1101 Lisp_Object attribute, class, component, subclass;
01f1ba30
JB
1102{
1103 register char *value;
1104 char *name_key;
1105 char *class_key;
1106
11ae94fe
RS
1107 check_x ();
1108
01f1ba30 1109 CHECK_STRING (attribute, 0);
cf177271
JB
1110 CHECK_STRING (class, 0);
1111
8fabe6f4
RS
1112 if (!NILP (component))
1113 CHECK_STRING (component, 1);
1114 if (!NILP (subclass))
1115 CHECK_STRING (subclass, 2);
1116 if (NILP (component) != NILP (subclass))
1117 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
1118
1119 if (NILP (component))
01f1ba30 1120 {
cf177271
JB
1121 /* Allocate space for the components, the dots which separate them,
1122 and the final '\0'. */
ac63d3d6 1123 name_key = (char *) alloca (XSTRING (Vxrdb_name)->size
cf177271
JB
1124 + XSTRING (attribute)->size
1125 + 2);
1126 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
1127 + XSTRING (class)->size
1128 + 2);
60fb3ee1 1129
01f1ba30 1130 sprintf (name_key, "%s.%s",
ac63d3d6 1131 XSTRING (Vxrdb_name)->data,
01f1ba30 1132 XSTRING (attribute)->data);
cf177271
JB
1133 sprintf (class_key, "%s.%s",
1134 EMACS_CLASS,
1135 XSTRING (class)->data);
01f1ba30
JB
1136 }
1137 else
1138 {
ac63d3d6 1139 name_key = (char *) alloca (XSTRING (Vxrdb_name)->size
cf177271
JB
1140 + XSTRING (component)->size
1141 + XSTRING (attribute)->size
1142 + 3);
60fb3ee1 1143
cf177271
JB
1144 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
1145 + XSTRING (class)->size
1146 + XSTRING (subclass)->size
1147 + 3);
01f1ba30
JB
1148
1149 sprintf (name_key, "%s.%s.%s",
ac63d3d6 1150 XSTRING (Vxrdb_name)->data,
8fabe6f4 1151 XSTRING (component)->data,
01f1ba30 1152 XSTRING (attribute)->data);
ac63d3d6 1153 sprintf (class_key, "%s.%s.%s",
cf177271
JB
1154 EMACS_CLASS,
1155 XSTRING (class)->data,
1156 XSTRING (subclass)->data);
01f1ba30
JB
1157 }
1158
1159 value = x_get_string_resource (xrdb, name_key, class_key);
1160
1161 if (value != (char *) 0)
1162 return build_string (value);
1163 else
1164 return Qnil;
1165}
1166
3402e1a4
RS
1167/* Used when C code wants a resource value. */
1168
1169char *
1170x_get_resource_string (attribute, class)
1171 char *attribute, *class;
1172{
1173 register char *value;
1174 char *name_key;
1175 char *class_key;
1176
1177 /* Allocate space for the components, the dots which separate them,
1178 and the final '\0'. */
1179 name_key = (char *) alloca (XSTRING (Vinvocation_name)->size
1180 + strlen (attribute) + 2);
1181 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
1182 + strlen (class) + 2);
1183
1184 sprintf (name_key, "%s.%s",
1185 XSTRING (Vinvocation_name)->data,
1186 attribute);
1187 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
1188
1189 return x_get_string_resource (xrdb, name_key, class_key);
1190}
1191
01f1ba30
JB
1192#else /* X10 */
1193
60fb3ee1 1194DEFUN ("x-get-default", Fx_get_default, Sx_get_default, 1, 1, 0,
f9942c9e 1195 "Get X default ATTRIBUTE from the system, or nil if no default.\n\
01f1ba30
JB
1196Value is a string (when not nil) and ATTRIBUTE is also a string.\n\
1197The defaults are specified in the file `~/.Xdefaults'.")
60fb3ee1
JB
1198 (arg)
1199 Lisp_Object arg;
01f1ba30
JB
1200{
1201 register unsigned char *value;
1202
1203 CHECK_STRING (arg, 1);
1204
1205 value = (unsigned char *) XGetDefault (XDISPLAY
59653951 1206 XSTRING (Vinvocation_name)->data,
01f1ba30
JB
1207 XSTRING (arg)->data);
1208 if (value == 0)
1209 /* Try reversing last two args, in case this is the buggy version of X. */
1210 value = (unsigned char *) XGetDefault (XDISPLAY
1211 XSTRING (arg)->data,
59653951 1212 XSTRING (Vinvocation_name)->data);
01f1ba30
JB
1213 if (value != 0)
1214 return build_string (value);
1215 else
1216 return (Qnil);
1217}
1218
cf177271
JB
1219#define Fx_get_resource(attribute, class, component, subclass) \
1220 Fx_get_default(attribute)
01f1ba30
JB
1221
1222#endif /* X10 */
1223
60fb3ee1
JB
1224/* Types we might convert a resource string into. */
1225enum resource_types
1226 {
f945b920 1227 number, boolean, string, symbol,
60fb3ee1
JB
1228 };
1229
01f1ba30 1230/* Return the value of parameter PARAM.
60fb3ee1 1231
f676886a 1232 First search ALIST, then Vdefault_frame_alist, then the X defaults
cf177271 1233 database, using ATTRIBUTE as the attribute name and CLASS as its class.
60fb3ee1
JB
1234
1235 Convert the resource to the type specified by desired_type.
1236
f9942c9e
JB
1237 If no default is specified, return Qunbound. If you call
1238 x_get_arg, make sure you deal with Qunbound in a reasonable way,
1239 and don't let it get stored in any lisp-visible variables! */
01f1ba30
JB
1240
1241static Lisp_Object
cf177271 1242x_get_arg (alist, param, attribute, class, type)
3c254570 1243 Lisp_Object alist, param;
60fb3ee1 1244 char *attribute;
cf177271 1245 char *class;
60fb3ee1 1246 enum resource_types type;
01f1ba30
JB
1247{
1248 register Lisp_Object tem;
1249
1250 tem = Fassq (param, alist);
1251 if (EQ (tem, Qnil))
f676886a 1252 tem = Fassq (param, Vdefault_frame_alist);
f9942c9e 1253 if (EQ (tem, Qnil))
01f1ba30 1254 {
60fb3ee1 1255
f9942c9e 1256 if (attribute)
60fb3ee1 1257 {
cf177271
JB
1258 tem = Fx_get_resource (build_string (attribute),
1259 build_string (class),
1260 Qnil, Qnil);
f9942c9e
JB
1261
1262 if (NILP (tem))
1263 return Qunbound;
1264
1265 switch (type)
1266 {
1267 case number:
1268 return make_number (atoi (XSTRING (tem)->data));
1269
1270 case boolean:
1271 tem = Fdowncase (tem);
1272 if (!strcmp (XSTRING (tem)->data, "on")
1273 || !strcmp (XSTRING (tem)->data, "true"))
1274 return Qt;
1275 else
1276 return Qnil;
1277
1278 case string:
1279 return tem;
1280
f945b920 1281 case symbol:
49795535
JB
1282 /* As a special case, we map the values `true' and `on'
1283 to Qt, and `false' and `off' to Qnil. */
1284 {
1285 Lisp_Object lower = Fdowncase (tem);
1286 if (!strcmp (XSTRING (tem)->data, "on")
1287 || !strcmp (XSTRING (tem)->data, "true"))
1288 return Qt;
8bc59570 1289 else if (!strcmp (XSTRING (tem)->data, "off")
49795535
JB
1290 || !strcmp (XSTRING (tem)->data, "false"))
1291 return Qnil;
1292 else
89032215 1293 return Fintern (tem, Qnil);
49795535 1294 }
f945b920 1295
f9942c9e
JB
1296 default:
1297 abort ();
1298 }
60fb3ee1 1299 }
f9942c9e
JB
1300 else
1301 return Qunbound;
01f1ba30
JB
1302 }
1303 return Fcdr (tem);
1304}
1305
f676886a 1306/* Record in frame F the specified or default value according to ALIST
01f1ba30
JB
1307 of the parameter named PARAM (a Lisp symbol).
1308 If no value is specified for PARAM, look for an X default for XPROP
f676886a 1309 on the frame named NAME.
01f1ba30
JB
1310 If that is not found either, use the value DEFLT. */
1311
1312static Lisp_Object
cf177271 1313x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
f676886a 1314 struct frame *f;
01f1ba30 1315 Lisp_Object alist;
f9942c9e 1316 Lisp_Object prop;
01f1ba30
JB
1317 Lisp_Object deflt;
1318 char *xprop;
cf177271 1319 char *xclass;
60fb3ee1 1320 enum resource_types type;
01f1ba30 1321{
01f1ba30
JB
1322 Lisp_Object tem;
1323
cf177271 1324 tem = x_get_arg (alist, prop, xprop, xclass, type);
f9942c9e 1325 if (EQ (tem, Qunbound))
01f1ba30 1326 tem = deflt;
f9942c9e 1327 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
01f1ba30
JB
1328 return tem;
1329}
1330\f
8af1d7ca 1331DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
01f1ba30
JB
1332 "Parse an X-style geometry string STRING.\n\
1333Returns an alist of the form ((top . TOP), (left . LEFT) ... ).")
1334 (string)
a6605e5c 1335 Lisp_Object string;
01f1ba30
JB
1336{
1337 int geometry, x, y;
1338 unsigned int width, height;
1339 Lisp_Object values[4];
1340
1341 CHECK_STRING (string, 0);
1342
1343 geometry = XParseGeometry ((char *) XSTRING (string)->data,
1344 &x, &y, &width, &height);
1345
1346 switch (geometry & 0xf) /* Mask out {X,Y}Negative */
1347 {
1348 case (XValue | YValue):
1349 /* What's one pixel among friends?
1350 Perhaps fix this some day by returning symbol `extreme-top'... */
1351 if (x == 0 && (geometry & XNegative))
1352 x = -1;
1353 if (y == 0 && (geometry & YNegative))
1354 y = -1;
f9942c9e
JB
1355 values[0] = Fcons (Qleft, make_number (x));
1356 values[1] = Fcons (Qtop, make_number (y));
01f1ba30
JB
1357 return Flist (2, values);
1358 break;
1359
1360 case (WidthValue | HeightValue):
f9942c9e
JB
1361 values[0] = Fcons (Qwidth, make_number (width));
1362 values[1] = Fcons (Qheight, make_number (height));
01f1ba30
JB
1363 return Flist (2, values);
1364 break;
1365
1366 case (XValue | YValue | WidthValue | HeightValue):
1367 if (x == 0 && (geometry & XNegative))
1368 x = -1;
1369 if (y == 0 && (geometry & YNegative))
1370 y = -1;
f9942c9e
JB
1371 values[0] = Fcons (Qwidth, make_number (width));
1372 values[1] = Fcons (Qheight, make_number (height));
1373 values[2] = Fcons (Qleft, make_number (x));
1374 values[3] = Fcons (Qtop, make_number (y));
01f1ba30
JB
1375 return Flist (4, values);
1376 break;
1377
1378 case 0:
1379 return Qnil;
1380
1381 default:
1382 error ("Must specify x and y value, and/or width and height");
1383 }
1384}
1385
1386#ifdef HAVE_X11
1387/* Calculate the desired size and position of this window,
1388 or set rubber-band prompting if none. */
1389
1390#define DEFAULT_ROWS 40
1391#define DEFAULT_COLS 80
1392
f9942c9e 1393static int
f676886a
JB
1394x_figure_window_size (f, parms)
1395 struct frame *f;
01f1ba30
JB
1396 Lisp_Object parms;
1397{
1398 register Lisp_Object tem0, tem1;
1399 int height, width, left, top;
1400 register int geometry;
1401 long window_prompting = 0;
1402
1403 /* Default values if we fall through.
1404 Actually, if that happens we should get
1405 window manager prompting. */
f676886a
JB
1406 f->width = DEFAULT_COLS;
1407 f->height = DEFAULT_ROWS;
bd0b85c3
RS
1408 /* Window managers expect that if program-specified
1409 positions are not (0,0), they're intentional, not defaults. */
1410 f->display.x->top_pos = 0;
1411 f->display.x->left_pos = 0;
01f1ba30 1412
cf177271
JB
1413 tem0 = x_get_arg (parms, Qheight, 0, 0, number);
1414 tem1 = x_get_arg (parms, Qwidth, 0, 0, number);
f9942c9e 1415 if (! EQ (tem0, Qunbound) && ! EQ (tem1, Qunbound))
01f1ba30
JB
1416 {
1417 CHECK_NUMBER (tem0, 0);
1418 CHECK_NUMBER (tem1, 0);
f676886a
JB
1419 f->height = XINT (tem0);
1420 f->width = XINT (tem1);
01f1ba30
JB
1421 window_prompting |= USSize;
1422 }
f9942c9e 1423 else if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
01f1ba30
JB
1424 error ("Must specify *both* height and width");
1425
739f2f53
RS
1426 f->display.x->vertical_scroll_bar_extra
1427 = (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
1428 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f)
1429 : 0);
179956b9
JB
1430 f->display.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
1431 f->display.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
01f1ba30 1432
cf177271
JB
1433 tem0 = x_get_arg (parms, Qtop, 0, 0, number);
1434 tem1 = x_get_arg (parms, Qleft, 0, 0, number);
f9942c9e 1435 if (! EQ (tem0, Qunbound) && ! EQ (tem1, Qunbound))
01f1ba30
JB
1436 {
1437 CHECK_NUMBER (tem0, 0);
1438 CHECK_NUMBER (tem1, 0);
f676886a
JB
1439 f->display.x->top_pos = XINT (tem0);
1440 f->display.x->left_pos = XINT (tem1);
1441 x_calc_absolute_position (f);
01f1ba30
JB
1442 window_prompting |= USPosition;
1443 }
f9942c9e 1444 else if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
01f1ba30
JB
1445 error ("Must specify *both* top and left corners");
1446
739f2f53
RS
1447#if 0 /* PPosition and PSize mean "specified explicitly,
1448 by the program rather than by the user". So it is wrong to
1449 set them if nothing was specified. */
01f1ba30
JB
1450 switch (window_prompting)
1451 {
1452 case USSize | USPosition:
1453 return window_prompting;
1454 break;
1455
1456 case USSize: /* Got the size, need the position. */
1457 window_prompting |= PPosition;
1458 return window_prompting;
1459 break;
1460
1461 case USPosition: /* Got the position, need the size. */
1462 window_prompting |= PSize;
1463 return window_prompting;
1464 break;
1465
1466 case 0: /* Got nothing, take both from geometry. */
1467 window_prompting |= PPosition | PSize;
1468 return window_prompting;
1469 break;
1470
1471 default:
1472 /* Somehow a bit got set in window_prompting that we didn't
1473 put there. */
1474 abort ();
1475 }
739f2f53
RS
1476#endif
1477 return window_prompting;
01f1ba30
JB
1478}
1479
1480static void
f676886a
JB
1481x_window (f)
1482 struct frame *f;
01f1ba30
JB
1483{
1484 XSetWindowAttributes attributes;
1485 unsigned long attribute_mask;
1486 XClassHint class_hints;
714fd2ea
RS
1487 char *shortname;
1488 char *p;
01f1ba30 1489
f676886a
JB
1490 attributes.background_pixel = f->display.x->background_pixel;
1491 attributes.border_pixel = f->display.x->border_pixel;
01f1ba30
JB
1492 attributes.bit_gravity = StaticGravity;
1493 attributes.backing_store = NotUseful;
1494 attributes.save_under = True;
1495 attributes.event_mask = STANDARD_EVENT_SET;
1496 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity
1497#if 0
1498 | CWBackingStore | CWSaveUnder
1499#endif
1500 | CWEventMask);
1501
1502 BLOCK_INPUT;
fe24a618 1503 FRAME_X_WINDOW (f)
01f1ba30 1504 = XCreateWindow (x_current_display, ROOT_WINDOW,
f676886a
JB
1505 f->display.x->left_pos,
1506 f->display.x->top_pos,
1507 PIXEL_WIDTH (f), PIXEL_HEIGHT (f),
1508 f->display.x->border_width,
01f1ba30
JB
1509 CopyFromParent, /* depth */
1510 InputOutput, /* class */
1511 screen_visual, /* set in Fx_open_connection */
1512 attribute_mask, &attributes);
1513
714fd2ea
RS
1514 /* X resource names should not have periods in them.
1515 So copy the frame name, discarding from the first period onward. */
1516 shortname = (char *) alloca (XSTRING (f->name)->size + 1);
1517 bcopy (XSTRING (f->name)->data, shortname, XSTRING (f->name)->size + 1);
1518 for (p = shortname; *p; p++)
1519 if (*p == '.')
1520 *p = 0;
1521
1522 class_hints.res_name = shortname;
01f1ba30 1523 class_hints.res_class = EMACS_CLASS;
fe24a618 1524 XSetClassHint (x_current_display, FRAME_X_WINDOW (f), &class_hints);
01f1ba30 1525
179956b9
JB
1526 /* This indicates that we use the "Passive Input" input model.
1527 Unless we do this, we don't get the Focus{In,Out} events that we
1528 need to draw the cursor correctly. Accursed bureaucrats.
1529 XWhipsAndChains (x_current_display, IronMaiden, &TheRack); */
1530
1531 f->display.x->wm_hints.input = True;
1532 f->display.x->wm_hints.flags |= InputHint;
1533 XSetWMHints (x_current_display, FRAME_X_WINDOW (f), &f->display.x->wm_hints);
1534
e373f201
JB
1535 /* x_set_name normally ignores requests to set the name if the
1536 requested name is the same as the current name. This is the one
1537 place where that assumption isn't correct; f->name is set, but
1538 the X server hasn't been told. */
1539 {
1540 Lisp_Object name = f->name;
cf177271 1541 int explicit = f->explicit_name;
e373f201
JB
1542
1543 f->name = Qnil;
cf177271
JB
1544 f->explicit_name = 0;
1545 x_set_name (f, name, explicit);
e373f201
JB
1546 }
1547
fe24a618 1548 XDefineCursor (XDISPLAY FRAME_X_WINDOW (f),
f676886a 1549 f->display.x->text_cursor);
01f1ba30
JB
1550 UNBLOCK_INPUT;
1551
fe24a618 1552 if (FRAME_X_WINDOW (f) == 0)
01f1ba30
JB
1553 error ("Unable to create window.");
1554}
1555
1556/* Handle the icon stuff for this window. Perhaps later we might
1557 want an x_set_icon_position which can be called interactively as
1558 well. */
1559
1560static void
f676886a
JB
1561x_icon (f, parms)
1562 struct frame *f;
01f1ba30
JB
1563 Lisp_Object parms;
1564{
f9942c9e 1565 Lisp_Object icon_x, icon_y;
01f1ba30
JB
1566
1567 /* Set the position of the icon. Note that twm groups all
1568 icons in an icon window. */
cf177271
JB
1569 icon_x = x_get_arg (parms, Qicon_left, 0, 0, number);
1570 icon_y = x_get_arg (parms, Qicon_top, 0, 0, number);
f9942c9e 1571 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
01f1ba30 1572 {
f9942c9e
JB
1573 CHECK_NUMBER (icon_x, 0);
1574 CHECK_NUMBER (icon_y, 0);
01f1ba30 1575 }
f9942c9e 1576 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
01f1ba30 1577 error ("Both left and top icon corners of icon must be specified");
01f1ba30 1578
f9942c9e
JB
1579 BLOCK_INPUT;
1580
fe24a618
JB
1581 if (! EQ (icon_x, Qunbound))
1582 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
f9942c9e 1583
01f1ba30 1584 /* Start up iconic or window? */
49795535
JB
1585 x_wm_set_window_state
1586 (f, (EQ (x_get_arg (parms, Qvisibility, 0, 0, symbol), Qicon)
1587 ? IconicState
1588 : NormalState));
01f1ba30 1589
01f1ba30
JB
1590 UNBLOCK_INPUT;
1591}
1592
1593/* Make the GC's needed for this window, setting the
1594 background, border and mouse colors; also create the
1595 mouse cursor and the gray border tile. */
1596
f945b920
JB
1597static char cursor_bits[] =
1598 {
1599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1601 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1602 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1603 };
1604
01f1ba30 1605static void
f676886a
JB
1606x_make_gc (f)
1607 struct frame *f;
01f1ba30
JB
1608{
1609 XGCValues gc_values;
1610 GC temp_gc;
1611 XImage tileimage;
01f1ba30 1612
6afb1d07
JB
1613 BLOCK_INPUT;
1614
f676886a 1615 /* Create the GC's of this frame.
01f1ba30
JB
1616 Note that many default values are used. */
1617
1618 /* Normal video */
f676886a
JB
1619 gc_values.font = f->display.x->font->fid;
1620 gc_values.foreground = f->display.x->foreground_pixel;
1621 gc_values.background = f->display.x->background_pixel;
01f1ba30 1622 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
f676886a 1623 f->display.x->normal_gc = XCreateGC (x_current_display,
fe24a618 1624 FRAME_X_WINDOW (f),
01f1ba30
JB
1625 GCLineWidth | GCFont
1626 | GCForeground | GCBackground,
1627 &gc_values);
1628
1629 /* Reverse video style. */
f676886a
JB
1630 gc_values.foreground = f->display.x->background_pixel;
1631 gc_values.background = f->display.x->foreground_pixel;
1632 f->display.x->reverse_gc = XCreateGC (x_current_display,
fe24a618 1633 FRAME_X_WINDOW (f),
01f1ba30
JB
1634 GCFont | GCForeground | GCBackground
1635 | GCLineWidth,
1636 &gc_values);
1637
1638 /* Cursor has cursor-color background, background-color foreground. */
f676886a
JB
1639 gc_values.foreground = f->display.x->background_pixel;
1640 gc_values.background = f->display.x->cursor_pixel;
01f1ba30
JB
1641 gc_values.fill_style = FillOpaqueStippled;
1642 gc_values.stipple
1643 = XCreateBitmapFromData (x_current_display, ROOT_WINDOW,
1644 cursor_bits, 16, 16);
f676886a 1645 f->display.x->cursor_gc
fe24a618 1646 = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
01f1ba30
JB
1647 (GCFont | GCForeground | GCBackground
1648 | GCFillStyle | GCStipple | GCLineWidth),
1649 &gc_values);
1650
1651 /* Create the gray border tile used when the pointer is not in
f676886a
JB
1652 the frame. Since this depends on the frame's pixel values,
1653 this must be done on a per-frame basis. */
d043f1a4
RS
1654 f->display.x->border_tile
1655 = (XCreatePixmapFromBitmapData
1656 (x_current_display, ROOT_WINDOW,
1657 gray_bits, gray_width, gray_height,
1658 f->display.x->foreground_pixel,
1659 f->display.x->background_pixel,
1660 DefaultDepth (x_current_display, XDefaultScreen (x_current_display))));
6afb1d07
JB
1661
1662 UNBLOCK_INPUT;
01f1ba30
JB
1663}
1664#endif /* HAVE_X11 */
1665
f676886a 1666DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
01f1ba30 1667 1, 1, 0,
f676886a
JB
1668 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
1669Return an Emacs frame object representing the X window.\n\
1670ALIST is an alist of frame parameters.\n\
1671If the parameters specify that the frame should not have a minibuffer,\n\
e22d6b02 1672and do not specify a specific minibuffer window to use,\n\
f676886a
JB
1673then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
1674be shared by the new frame.")
01f1ba30
JB
1675 (parms)
1676 Lisp_Object parms;
1677{
1678#ifdef HAVE_X11
f676886a
JB
1679 struct frame *f;
1680 Lisp_Object frame, tem;
01f1ba30
JB
1681 Lisp_Object name;
1682 int minibuffer_only = 0;
1683 long window_prompting = 0;
1684 int width, height;
1685
11ae94fe 1686 check_x ();
01f1ba30 1687
cf177271
JB
1688 name = x_get_arg (parms, Qname, "title", "Title", string);
1689 if (XTYPE (name) != Lisp_String
1690 && ! EQ (name, Qunbound)
1691 && ! NILP (name))
f676886a 1692 error ("x-create-frame: name parameter must be a string");
01f1ba30 1693
cf177271 1694 tem = x_get_arg (parms, Qminibuffer, 0, 0, symbol);
f9942c9e 1695 if (EQ (tem, Qnone) || NILP (tem))
f676886a 1696 f = make_frame_without_minibuffer (Qnil);
f9942c9e 1697 else if (EQ (tem, Qonly))
01f1ba30 1698 {
f676886a 1699 f = make_minibuffer_frame ();
01f1ba30
JB
1700 minibuffer_only = 1;
1701 }
f9942c9e 1702 else if (XTYPE (tem) == Lisp_Window)
f676886a 1703 f = make_frame_without_minibuffer (tem);
f9942c9e
JB
1704 else
1705 f = make_frame (1);
01f1ba30 1706
a3c87d4e
JB
1707 /* Note that X Windows does support scroll bars. */
1708 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
179956b9 1709
cf177271
JB
1710 /* Set the name; the functions to which we pass f expect the name to
1711 be set. */
1712 if (EQ (name, Qunbound) || NILP (name))
1713 {
1714 f->name = build_string (x_id_name);
1715 f->explicit_name = 0;
1716 }
1717 else
1718 {
1719 f->name = name;
1720 f->explicit_name = 1;
1721 }
01f1ba30 1722
f676886a
JB
1723 XSET (frame, Lisp_Frame, f);
1724 f->output_method = output_x_window;
1725 f->display.x = (struct x_display *) xmalloc (sizeof (struct x_display));
1726 bzero (f->display.x, sizeof (struct x_display));
01f1ba30 1727
f676886a
JB
1728 /* Note that the frame has no physical cursor right now. */
1729 f->phys_cursor_x = -1;
265a9e55 1730
01f1ba30
JB
1731 /* Extract the window parameters from the supplied values
1732 that are needed to determine window geometry. */
ee8f40cc
JB
1733 x_default_parameter (f, parms, Qfont,
1734 build_string
1735 /* If we use an XLFD name for this font, the lisp code
1736 knows how to find variants which are bold, italic,
1737 etcetera. */
1738 ("-*-fixed-*-*-*-*-*-120-*-*-c-*-iso8859-1"),
cf177271
JB
1739 "font", "Font", string);
1740 x_default_parameter (f, parms, Qborder_width, make_number (2),
1741 "borderwidth", "BorderWidth", number);
1742 /* This defaults to 2 in order to match xterm. */
1743 x_default_parameter (f, parms, Qinternal_border_width, make_number (2),
1744 "internalBorderWidth", "BorderWidth", number);
a3c87d4e
JB
1745 x_default_parameter (f, parms, Qvertical_scroll_bars, Qt,
1746 "verticalScrollBars", "ScrollBars", boolean);
01f1ba30
JB
1747
1748 /* Also do the stuff which must be set before the window exists. */
cf177271
JB
1749 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
1750 "foreground", "Foreground", string);
1751 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
1752 "background", "Background", string);
1753 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
1754 "pointerColor", "Foreground", string);
1755 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
1756 "cursorColor", "Foreground", string);
1757 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
1758 "borderColor", "BorderColor", string);
01f1ba30 1759
f676886a
JB
1760 f->display.x->parent_desc = ROOT_WINDOW;
1761 window_prompting = x_figure_window_size (f, parms);
01f1ba30 1762
f676886a
JB
1763 x_window (f);
1764 x_icon (f, parms);
1765 x_make_gc (f);
ea96210c 1766 init_frame_faces (f);
01f1ba30 1767
f9942c9e
JB
1768 /* We need to do this after creating the X window, so that the
1769 icon-creation functions can say whose icon they're describing. */
cf177271 1770 x_default_parameter (f, parms, Qicon_type, Qnil,
6998a3b4 1771 "bitmapIcon", "BitmapIcon", symbol);
f9942c9e 1772
cf177271
JB
1773 x_default_parameter (f, parms, Qauto_raise, Qnil,
1774 "autoRaise", "AutoRaiseLower", boolean);
1775 x_default_parameter (f, parms, Qauto_lower, Qnil,
1776 "autoLower", "AutoRaiseLower", boolean);
dbc4e1c1
JB
1777 x_default_parameter (f, parms, Qcursor_type, Qbox,
1778 "cursorType", "CursorType", symbol);
f9942c9e 1779
f676886a 1780 /* Dimensions, especially f->height, must be done via change_frame_size.
01f1ba30 1781 Change will not be effected unless different from the current
f676886a
JB
1782 f->height. */
1783 width = f->width;
1784 height = f->height;
1785 f->height = f->width = 0;
f9942c9e 1786 change_frame_size (f, height, width, 1, 0);
d043f1a4
RS
1787
1788 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (0),
1789 "menuBarLines", "MenuBarLines", number);
1790
01f1ba30 1791 BLOCK_INPUT;
f676886a 1792 x_wm_set_size_hint (f, window_prompting);
01f1ba30
JB
1793 UNBLOCK_INPUT;
1794
cf177271 1795 tem = x_get_arg (parms, Qunsplittable, 0, 0, boolean);
f676886a 1796 f->no_split = minibuffer_only || EQ (tem, Qt);
01f1ba30 1797
d043f1a4
RS
1798 /* Make the window appear on the frame and enable display,
1799 unless the caller says not to. */
49795535
JB
1800 {
1801 Lisp_Object visibility = x_get_arg (parms, Qvisibility, 0, 0, symbol);
1802
1803 if (EQ (visibility, Qunbound))
1804 visibility = Qt;
1805
1806 if (EQ (visibility, Qicon))
1807 x_iconify_frame (f);
1808 else if (! NILP (visibility))
1809 x_make_frame_visible (f);
1810 else
1811 /* Must have been Qnil. */
1812 ;
1813 }
01f1ba30 1814
f676886a 1815 return frame;
01f1ba30 1816#else /* X10 */
f676886a
JB
1817 struct frame *f;
1818 Lisp_Object frame, tem;
01f1ba30
JB
1819 Lisp_Object name;
1820 int pixelwidth, pixelheight;
1821 Cursor cursor;
1822 int height, width;
1823 Window parent;
1824 Pixmap temp;
1825 int minibuffer_only = 0;
1826 Lisp_Object vscroll, hscroll;
1827
1828 if (x_current_display == 0)
1829 error ("X windows are not in use or not initialized");
1830
f9942c9e 1831 name = Fassq (Qname, parms);
01f1ba30 1832
cf177271 1833 tem = x_get_arg (parms, Qminibuffer, 0, 0, symbol);
f9942c9e 1834 if (EQ (tem, Qnone))
f676886a 1835 f = make_frame_without_minibuffer (Qnil);
f9942c9e 1836 else if (EQ (tem, Qonly))
01f1ba30 1837 {
f676886a 1838 f = make_minibuffer_frame ();
01f1ba30
JB
1839 minibuffer_only = 1;
1840 }
f9942c9e 1841 else if (EQ (tem, Qnil) || EQ (tem, Qunbound))
f676886a 1842 f = make_frame (1);
f9942c9e
JB
1843 else
1844 f = make_frame_without_minibuffer (tem);
01f1ba30
JB
1845
1846 parent = ROOT_WINDOW;
1847
f676886a
JB
1848 XSET (frame, Lisp_Frame, f);
1849 f->output_method = output_x_window;
1850 f->display.x = (struct x_display *) xmalloc (sizeof (struct x_display));
1851 bzero (f->display.x, sizeof (struct x_display));
01f1ba30
JB
1852
1853 /* Some temprorary default values for height and width. */
1854 width = 80;
1855 height = 40;
f676886a
JB
1856 f->display.x->left_pos = -1;
1857 f->display.x->top_pos = -1;
01f1ba30 1858
f676886a 1859 /* Give the frame a default name (which may be overridden with PARMS). */
01f1ba30
JB
1860
1861 strncpy (iconidentity, ICONTAG, MAXICID);
1862 if (gethostname (&iconidentity[sizeof (ICONTAG) - 1],
1863 (MAXICID - 1) - sizeof (ICONTAG)))
1864 iconidentity[sizeof (ICONTAG) - 2] = '\0';
f676886a 1865 f->name = build_string (iconidentity);
01f1ba30
JB
1866
1867 /* Extract some window parameters from the supplied values.
1868 These are the parameters that affect window geometry. */
1869
cf177271 1870 tem = x_get_arg (parms, Qfont, "BodyFont", 0, string);
f9942c9e 1871 if (EQ (tem, Qunbound))
01f1ba30 1872 tem = build_string ("9x15");
f9942c9e
JB
1873 x_set_font (f, tem, Qnil);
1874 x_default_parameter (f, parms, Qborder_color,
cf177271 1875 build_string ("black"), "Border", 0, string);
f9942c9e 1876 x_default_parameter (f, parms, Qbackground_color,
cf177271 1877 build_string ("white"), "Background", 0, string);
f9942c9e 1878 x_default_parameter (f, parms, Qforeground_color,
cf177271 1879 build_string ("black"), "Foreground", 0, string);
f9942c9e 1880 x_default_parameter (f, parms, Qmouse_color,
cf177271 1881 build_string ("black"), "Mouse", 0, string);
f9942c9e 1882 x_default_parameter (f, parms, Qcursor_color,
cf177271 1883 build_string ("black"), "Cursor", 0, string);
f9942c9e 1884 x_default_parameter (f, parms, Qborder_width,
cf177271 1885 make_number (2), "BorderWidth", 0, number);
f9942c9e 1886 x_default_parameter (f, parms, Qinternal_border_width,
cf177271 1887 make_number (4), "InternalBorderWidth", 0, number);
f9942c9e 1888 x_default_parameter (f, parms, Qauto_raise,
cf177271 1889 Qnil, "AutoRaise", 0, boolean);
01f1ba30 1890
cf177271
JB
1891 hscroll = EQ (x_get_arg (parms, Qhorizontal_scroll_bar, 0, 0, boolean), Qt);
1892 vscroll = EQ (x_get_arg (parms, Qvertical_scroll_bar, 0, 0, boolean), Qt);
01f1ba30 1893
f676886a
JB
1894 if (f->display.x->internal_border_width < 0)
1895 f->display.x->internal_border_width = 0;
01f1ba30 1896
cf177271 1897 tem = x_get_arg (parms, Qwindow_id, 0, 0, number);
f9942c9e 1898 if (!EQ (tem, Qunbound))
01f1ba30
JB
1899 {
1900 WINDOWINFO_TYPE wininfo;
1901 int nchildren;
1902 Window *children, root;
1903
f9942c9e 1904 CHECK_NUMBER (tem, 0);
fe24a618 1905 FRAME_X_WINDOW (f) = (Window) XINT (tem);
01f1ba30
JB
1906
1907 BLOCK_INPUT;
fe24a618
JB
1908 XGetWindowInfo (FRAME_X_WINDOW (f), &wininfo);
1909 XQueryTree (FRAME_X_WINDOW (f), &parent, &nchildren, &children);
9ac0d9e0 1910 xfree (children);
01f1ba30
JB
1911 UNBLOCK_INPUT;
1912
cf177271
JB
1913 height = PIXEL_TO_CHAR_HEIGHT (f, wininfo.height);
1914 width = PIXEL_TO_CHAR_WIDTH (f, wininfo.width);
f676886a
JB
1915 f->display.x->left_pos = wininfo.x;
1916 f->display.x->top_pos = wininfo.y;
179956b9 1917 FRAME_SET_VISIBILITY (f, wininfo.mapped != 0);
f676886a
JB
1918 f->display.x->border_width = wininfo.bdrwidth;
1919 f->display.x->parent_desc = parent;
01f1ba30
JB
1920 }
1921 else
1922 {
cf177271 1923 tem = x_get_arg (parms, Qparent_id, 0, 0, number);
f9942c9e 1924 if (!EQ (tem, Qunbound))
01f1ba30 1925 {
f9942c9e
JB
1926 CHECK_NUMBER (tem, 0);
1927 parent = (Window) XINT (tem);
01f1ba30 1928 }
f676886a 1929 f->display.x->parent_desc = parent;
cf177271 1930 tem = x_get_arg (parms, Qheight, 0, 0, number);
f9942c9e 1931 if (EQ (tem, Qunbound))
01f1ba30 1932 {
cf177271 1933 tem = x_get_arg (parms, Qwidth, 0, 0, number);
f9942c9e 1934 if (EQ (tem, Qunbound))
01f1ba30 1935 {
cf177271 1936 tem = x_get_arg (parms, Qtop, 0, 0, number);
f9942c9e 1937 if (EQ (tem, Qunbound))
cf177271 1938 tem = x_get_arg (parms, Qleft, 0, 0, number);
01f1ba30
JB
1939 }
1940 }
f9942c9e 1941 /* Now TEM is Qunbound if no edge or size was specified.
01f1ba30 1942 In that case, we must do rubber-banding. */
f9942c9e 1943 if (EQ (tem, Qunbound))
01f1ba30 1944 {
cf177271 1945 tem = x_get_arg (parms, Qgeometry, 0, 0, number);
f676886a
JB
1946 x_rubber_band (f,
1947 &f->display.x->left_pos, &f->display.x->top_pos,
01f1ba30
JB
1948 &width, &height,
1949 (XTYPE (tem) == Lisp_String
1950 ? (char *) XSTRING (tem)->data : ""),
f676886a 1951 XSTRING (f->name)->data,
265a9e55 1952 !NILP (hscroll), !NILP (vscroll));
01f1ba30
JB
1953 }
1954 else
1955 {
1956 /* Here if at least one edge or size was specified.
1957 Demand that they all were specified, and use them. */
cf177271 1958 tem = x_get_arg (parms, Qheight, 0, 0, number);
f9942c9e 1959 if (EQ (tem, Qunbound))
01f1ba30
JB
1960 error ("Height not specified");
1961 CHECK_NUMBER (tem, 0);
1962 height = XINT (tem);
1963
cf177271 1964 tem = x_get_arg (parms, Qwidth, 0, 0, number);
f9942c9e 1965 if (EQ (tem, Qunbound))
01f1ba30
JB
1966 error ("Width not specified");
1967 CHECK_NUMBER (tem, 0);
1968 width = XINT (tem);
1969
cf177271 1970 tem = x_get_arg (parms, Qtop, 0, 0, number);
f9942c9e 1971 if (EQ (tem, Qunbound))
01f1ba30
JB
1972 error ("Top position not specified");
1973 CHECK_NUMBER (tem, 0);
f676886a 1974 f->display.x->left_pos = XINT (tem);
01f1ba30 1975
cf177271 1976 tem = x_get_arg (parms, Qleft, 0, 0, number);
f9942c9e 1977 if (EQ (tem, Qunbound))
01f1ba30
JB
1978 error ("Left position not specified");
1979 CHECK_NUMBER (tem, 0);
f676886a 1980 f->display.x->top_pos = XINT (tem);
01f1ba30
JB
1981 }
1982
cf177271
JB
1983 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, width);
1984 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, height);
01f1ba30
JB
1985
1986 BLOCK_INPUT;
fe24a618 1987 FRAME_X_WINDOW (f)
01f1ba30 1988 = XCreateWindow (parent,
f676886a
JB
1989 f->display.x->left_pos, /* Absolute horizontal offset */
1990 f->display.x->top_pos, /* Absolute Vertical offset */
01f1ba30 1991 pixelwidth, pixelheight,
f676886a 1992 f->display.x->border_width,
01f1ba30
JB
1993 BLACK_PIX_DEFAULT, WHITE_PIX_DEFAULT);
1994 UNBLOCK_INPUT;
fe24a618 1995 if (FRAME_X_WINDOW (f) == 0)
01f1ba30
JB
1996 error ("Unable to create window.");
1997 }
1998
1999 /* Install the now determined height and width
2000 in the windows and in phys_lines and desired_lines. */
f9942c9e 2001 change_frame_size (f, height, width, 1, 0);
fe24a618 2002 XSelectInput (FRAME_X_WINDOW (f), KeyPressed | ExposeWindow
01f1ba30
JB
2003 | ButtonPressed | ButtonReleased | ExposeRegion | ExposeCopy
2004 | EnterWindow | LeaveWindow | UnmapWindow );
f676886a 2005 x_set_resize_hint (f);
01f1ba30
JB
2006
2007 /* Tell the server the window's default name. */
fe24a618 2008 XStoreName (XDISPLAY FRAME_X_WINDOW (f), XSTRING (f->name)->data);
1113d9db 2009
01f1ba30
JB
2010 /* Now override the defaults with all the rest of the specified
2011 parms. */
cf177271 2012 tem = x_get_arg (parms, Qunsplittable, 0, 0, boolean);
f676886a 2013 f->no_split = minibuffer_only || EQ (tem, Qt);
01f1ba30 2014
8af1d7ca
JB
2015 /* Do not create an icon window if the caller says not to */
2016 if (!EQ (x_get_arg (parms, Qsuppress_icon, 0, 0, boolean), Qt)
2017 || f->display.x->parent_desc != ROOT_WINDOW)
2018 {
2019 x_text_icon (f, iconidentity);
2020 x_default_parameter (f, parms, Qicon_type, Qnil,
2021 "BitmapIcon", 0, symbol);
2022 }
01f1ba30
JB
2023
2024 /* Tell the X server the previously set values of the
2025 background, border and mouse colors; also create the mouse cursor. */
2026 BLOCK_INPUT;
f676886a 2027 temp = XMakeTile (f->display.x->background_pixel);
fe24a618 2028 XChangeBackground (FRAME_X_WINDOW (f), temp);
01f1ba30
JB
2029 XFreePixmap (temp);
2030 UNBLOCK_INPUT;
f676886a 2031 x_set_border_pixel (f, f->display.x->border_pixel);
01f1ba30 2032
f676886a 2033 x_set_mouse_color (f, Qnil, Qnil);
01f1ba30
JB
2034
2035 /* Now override the defaults with all the rest of the specified parms. */
2036
f676886a 2037 Fmodify_frame_parameters (frame, parms);
01f1ba30 2038
f676886a 2039 /* Make the window appear on the frame and enable display. */
49795535
JB
2040 {
2041 Lisp_Object visibility = x_get_arg (parms, Qvisibility, 0, 0, symbol);
2042
2043 if (EQ (visibility, Qunbound))
2044 visibility = Qt;
2045
2046 if (! EQ (visibility, Qicon)
2047 && ! NILP (visibility))
2048 x_make_window_visible (f);
2049 }
01f1ba30 2050
cf177271 2051 SET_FRAME_GARBAGED (f);
01f1ba30 2052
f676886a 2053 return frame;
01f1ba30
JB
2054#endif /* X10 */
2055}
2056
f676886a
JB
2057DEFUN ("focus-frame", Ffocus_frame, Sfocus_frame, 1, 1, 0,
2058 "Set the focus on FRAME.")
2059 (frame)
2060 Lisp_Object frame;
01f1ba30 2061{
f676886a 2062 CHECK_LIVE_FRAME (frame, 0);
01f1ba30 2063
f9942c9e 2064 if (FRAME_X_P (XFRAME (frame)))
01f1ba30
JB
2065 {
2066 BLOCK_INPUT;
f676886a 2067 x_focus_on_frame (XFRAME (frame));
01f1ba30 2068 UNBLOCK_INPUT;
f676886a 2069 return frame;
01f1ba30
JB
2070 }
2071
2072 return Qnil;
2073}
2074
f676886a
JB
2075DEFUN ("unfocus-frame", Funfocus_frame, Sunfocus_frame, 0, 0, 0,
2076 "If a frame has been focused, release it.")
01f1ba30
JB
2077 ()
2078{
f676886a 2079 if (x_focus_frame)
01f1ba30
JB
2080 {
2081 BLOCK_INPUT;
f676886a 2082 x_unfocus_frame (x_focus_frame);
01f1ba30
JB
2083 UNBLOCK_INPUT;
2084 }
2085
2086 return Qnil;
2087}
2088\f
2089#ifndef HAVE_X11
2090/* Computes an X-window size and position either from geometry GEO
2091 or with the mouse.
2092
f676886a 2093 F is a frame. It specifies an X window which is used to
01f1ba30
JB
2094 determine which display to compute for. Its font, borders
2095 and colors control how the rectangle will be displayed.
2096
2097 X and Y are where to store the positions chosen.
2098 WIDTH and HEIGHT are where to store the sizes chosen.
2099
2100 GEO is the geometry that may specify some of the info.
2101 STR is a prompt to display.
2102 HSCROLL and VSCROLL say whether we have horiz and vert scroll bars. */
2103
2104int
f676886a
JB
2105x_rubber_band (f, x, y, width, height, geo, str, hscroll, vscroll)
2106 struct frame *f;
01f1ba30
JB
2107 int *x, *y, *width, *height;
2108 char *geo;
2109 char *str;
2110 int hscroll, vscroll;
2111{
2112 OpaqueFrame frame;
2113 Window tempwindow;
2114 WindowInfo wininfo;
2115 int border_color;
2116 int background_color;
2117 Lisp_Object tem;
2118 int mask;
2119
2120 BLOCK_INPUT;
2121
f676886a
JB
2122 background_color = f->display.x->background_pixel;
2123 border_color = f->display.x->border_pixel;
01f1ba30 2124
f676886a 2125 frame.bdrwidth = f->display.x->border_width;
01f1ba30
JB
2126 frame.border = XMakeTile (border_color);
2127 frame.background = XMakeTile (background_color);
2128 tempwindow = XCreateTerm (str, "emacs", geo, default_window, &frame, 10, 5,
f676886a 2129 (2 * f->display.x->internal_border_width
01f1ba30 2130 + (vscroll ? VSCROLL_WIDTH : 0)),
f676886a 2131 (2 * f->display.x->internal_border_width
01f1ba30 2132 + (hscroll ? HSCROLL_HEIGHT : 0)),
f676886a
JB
2133 width, height, f->display.x->font,
2134 FONT_WIDTH (f->display.x->font),
2135 FONT_HEIGHT (f->display.x->font));
01f1ba30
JB
2136 XFreePixmap (frame.border);
2137 XFreePixmap (frame.background);
2138
2139 if (tempwindow != 0)
2140 {
2141 XQueryWindow (tempwindow, &wininfo);
2142 XDestroyWindow (tempwindow);
2143 *x = wininfo.x;
2144 *y = wininfo.y;
2145 }
2146
2147 /* Coordinates we got are relative to the root window.
2148 Convert them to coordinates relative to desired parent window
2149 by scanning from there up to the root. */
f676886a 2150 tempwindow = f->display.x->parent_desc;
01f1ba30
JB
2151 while (tempwindow != ROOT_WINDOW)
2152 {
2153 int nchildren;
2154 Window *children;
2155 XQueryWindow (tempwindow, &wininfo);
2156 *x -= wininfo.x;
2157 *y -= wininfo.y;
2158 XQueryTree (tempwindow, &tempwindow, &nchildren, &children);
9ac0d9e0 2159 xfree (children);
01f1ba30
JB
2160 }
2161
2162 UNBLOCK_INPUT;
2163 return tempwindow != 0;
2164}
2165#endif /* not HAVE_X11 */
2166\f
f0614854
JB
2167DEFUN ("x-list-fonts", Fx_list_fonts, Sx_list_fonts, 1, 3, 0,
2168 "Return a list of the names of available fonts matching PATTERN.\n\
2169If optional arguments FACE and FRAME are specified, return only fonts\n\
2170the same size as FACE on FRAME.\n\
2171\n\
2172PATTERN is a string, perhaps with wildcard characters;\n\
2173 the * character matches any substring, and\n\
2174 the ? character matches any single character.\n\
2175 PATTERN is case-insensitive.\n\
2176FACE is a face name - a symbol.\n\
2177\n\
2178The return value is a list of strings, suitable as arguments to\n\
2179set-face-font.\n\
2180\n\
2181The list does not include fonts Emacs can't use (i.e. proportional\n\
2182fonts), even if they match PATTERN and FACE.")
2183 (pattern, face, frame)
2184 Lisp_Object pattern, face, frame;
2185{
2186 int num_fonts;
2187 char **names;
2188 XFontStruct *info;
2189 XFontStruct *size_ref;
2190 Lisp_Object list;
2191
2192 CHECK_STRING (pattern, 0);
2193 if (!NILP (face))
2194 CHECK_SYMBOL (face, 1);
2195 if (!NILP (frame))
739f2f53 2196 CHECK_LIVE_FRAME (frame, 2);
f0614854
JB
2197
2198 if (NILP (face))
2199 size_ref = 0;
2200 else
2201 {
2202 FRAME_PTR f = NILP (frame) ? selected_frame : XFRAME (frame);
2203 int face_id = face_name_id_number (f, face);
2204
6998a3b4
RS
2205 if (face_id < 0 || face_id >= FRAME_N_FACES (f)
2206 || FRAME_FACES (f) [face_id] == 0)
ea96210c 2207 size_ref = f->display.x->font;
6998a3b4
RS
2208 else
2209 {
2210 size_ref = FRAME_FACES (f) [face_id]->font;
2211 if (size_ref == (XFontStruct *) (~0))
2212 size_ref = f->display.x->font;
2213 }
f0614854
JB
2214 }
2215
2216 BLOCK_INPUT;
2217 names = XListFontsWithInfo (x_current_display,
2218 XSTRING (pattern)->data,
ea96210c 2219 2000, /* maxnames */
f0614854
JB
2220 &num_fonts, /* count_return */
2221 &info); /* info_return */
2222 UNBLOCK_INPUT;
2223
2224 {
2225 Lisp_Object *tail;
2226 int i;
2227
2228 list = Qnil;
2229 tail = &list;
2230 for (i = 0; i < num_fonts; i++)
ea96210c
JB
2231 if (! size_ref
2232 || same_size_fonts (&info[i], size_ref))
f0614854
JB
2233 {
2234 *tail = Fcons (build_string (names[i]), Qnil);
2235 tail = &XCONS (*tail)->cdr;
2236 }
2237
2238 XFreeFontInfo (names, info, num_fonts);
2239 }
2240
2241 return list;
2242}
2243
2244\f
8af1d7ca 2245DEFUN ("x-color-defined-p", Fx_color_defined_p, Sx_color_defined_p, 1, 1, 0,
01f1ba30
JB
2246 "Return t if the current X display supports the color named COLOR.")
2247 (color)
2248 Lisp_Object color;
2249{
2250 Color foo;
2251
11ae94fe 2252 check_x ();
01f1ba30
JB
2253 CHECK_STRING (color, 0);
2254
2255 if (defined_color (XSTRING (color)->data, &foo))
2256 return Qt;
2257 else
2258 return Qnil;
2259}
2260
bcc426b4
RS
2261DEFUN ("x-display-color-p", Fx_display_color_p, Sx_display_color_p, 0, 0, 0,
2262 "Return t if the X screen currently in use supports color.")
01f1ba30
JB
2263 ()
2264{
11ae94fe
RS
2265 check_x ();
2266
a6605e5c 2267 if (x_screen_planes <= 2)
01f1ba30
JB
2268 return Qnil;
2269
2270 switch (screen_visual->class)
2271 {
2272 case StaticColor:
2273 case PseudoColor:
2274 case TrueColor:
2275 case DirectColor:
2276 return Qt;
2277
2278 default:
2279 return Qnil;
2280 }
2281}
2282
41beb8fc
RS
2283DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
2284 0, 1, 0,
2285 "Returns the width in pixels of the display FRAME is on.")
2286 (frame)
2287 Lisp_Object frame;
2288{
2289 Display *dpy = x_current_display;
11ae94fe 2290 check_x ();
41beb8fc
RS
2291 return make_number (DisplayWidth (dpy, DefaultScreen (dpy)));
2292}
2293
2294DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
2295 Sx_display_pixel_height, 0, 1, 0,
2296 "Returns the height in pixels of the display FRAME is on.")
2297 (frame)
2298 Lisp_Object frame;
2299{
2300 Display *dpy = x_current_display;
11ae94fe 2301 check_x ();
41beb8fc
RS
2302 return make_number (DisplayHeight (dpy, DefaultScreen (dpy)));
2303}
2304
2305DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
2306 0, 1, 0,
2307 "Returns the number of bitplanes of the display FRAME is on.")
2308 (frame)
2309 Lisp_Object frame;
2310{
2311 Display *dpy = x_current_display;
11ae94fe 2312 check_x ();
41beb8fc
RS
2313 return make_number (DisplayPlanes (dpy, DefaultScreen (dpy)));
2314}
2315
2316DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
2317 0, 1, 0,
2318 "Returns the number of color cells of the display FRAME is on.")
2319 (frame)
2320 Lisp_Object frame;
2321{
2322 Display *dpy = x_current_display;
11ae94fe 2323 check_x ();
41beb8fc
RS
2324 return make_number (DisplayCells (dpy, DefaultScreen (dpy)));
2325}
2326
2327DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
2328 "Returns the vendor ID string of the X server FRAME is on.")
2329 (frame)
2330 Lisp_Object frame;
2331{
2332 Display *dpy = x_current_display;
2333 char *vendor;
11ae94fe 2334 check_x ();
41beb8fc
RS
2335 vendor = ServerVendor (dpy);
2336 if (! vendor) vendor = "";
2337 return build_string (vendor);
2338}
2339
2340DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
2341 "Returns the version numbers of the X server in use.\n\
2342The value is a list of three integers: the major and minor\n\
2343version numbers of the X Protocol in use, and the vendor-specific release\n\
2344number. See also the variable `x-server-vendor'.")
2345 (frame)
2346 Lisp_Object frame;
2347{
2348 Display *dpy = x_current_display;
11ae94fe
RS
2349
2350 check_x ();
41beb8fc
RS
2351 return Fcons (make_number (ProtocolVersion (dpy)),
2352 Fcons (make_number (ProtocolRevision (dpy)),
2353 Fcons (make_number (VendorRelease (dpy)), Qnil)));
2354}
2355
2356DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
2357 "Returns the number of screens on the X server FRAME is on.")
2358 (frame)
2359 Lisp_Object frame;
2360{
11ae94fe 2361 check_x ();
41beb8fc
RS
2362 return make_number (ScreenCount (x_current_display));
2363}
2364
2365DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
2366 "Returns the height in millimeters of the X screen FRAME is on.")
2367 (frame)
2368 Lisp_Object frame;
2369{
11ae94fe 2370 check_x ();
41beb8fc
RS
2371 return make_number (HeightMMOfScreen (x_screen));
2372}
2373
2374DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
2375 "Returns the width in millimeters of the X screen FRAME is on.")
2376 (frame)
2377 Lisp_Object frame;
2378{
11ae94fe 2379 check_x ();
41beb8fc
RS
2380 return make_number (WidthMMOfScreen (x_screen));
2381}
2382
2383DEFUN ("x-display-backing-store", Fx_display_backing_store,
2384 Sx_display_backing_store, 0, 1, 0,
2385 "Returns an indication of whether the X screen FRAME is on does backing store.\n\
2386The value may be `always', `when-mapped', or `not-useful'.")
2387 (frame)
2388 Lisp_Object frame;
2389{
11ae94fe
RS
2390 check_x ();
2391
41beb8fc
RS
2392 switch (DoesBackingStore (x_screen))
2393 {
2394 case Always:
2395 return intern ("always");
2396
2397 case WhenMapped:
2398 return intern ("when-mapped");
2399
2400 case NotUseful:
2401 return intern ("not-useful");
2402
2403 default:
2404 error ("Strange value for BackingStore parameter of screen");
2405 }
2406}
2407
2408DEFUN ("x-display-visual-class", Fx_display_visual_class,
2409 Sx_display_visual_class, 0, 1, 0,
2410 "Returns the visual class of the display `screen' is on.\n\
2411The value is one of the symbols `static-gray', `gray-scale',\n\
2412`static-color', `pseudo-color', `true-color', or `direct-color'.")
2413 (screen)
2414 Lisp_Object screen;
2415{
11ae94fe
RS
2416 check_x ();
2417
41beb8fc
RS
2418 switch (screen_visual->class)
2419 {
2420 case StaticGray: return (intern ("static-gray"));
2421 case GrayScale: return (intern ("gray-scale"));
2422 case StaticColor: return (intern ("static-color"));
2423 case PseudoColor: return (intern ("pseudo-color"));
2424 case TrueColor: return (intern ("true-color"));
2425 case DirectColor: return (intern ("direct-color"));
2426 default:
2427 error ("Display has an unknown visual class");
2428 }
2429}
2430
2431DEFUN ("x-display-save-under", Fx_display_save_under,
2432 Sx_display_save_under, 0, 1, 0,
2433 "Returns t if the X screen FRAME is on supports the save-under feature.")
2434 (frame)
2435 Lisp_Object frame;
2436{
11ae94fe
RS
2437 check_x ();
2438
41beb8fc
RS
2439 if (DoesSaveUnders (x_screen) == True)
2440 return Qt;
2441 else
2442 return Qnil;
2443}
2444\f
55caf99c
RS
2445x_pixel_width (f)
2446 register struct frame *f;
01f1ba30 2447{
55caf99c 2448 return PIXEL_WIDTH (f);
01f1ba30
JB
2449}
2450
55caf99c
RS
2451x_pixel_height (f)
2452 register struct frame *f;
01f1ba30 2453{
55caf99c
RS
2454 return PIXEL_HEIGHT (f);
2455}
2456
2457x_char_width (f)
2458 register struct frame *f;
2459{
2460 return FONT_WIDTH (f->display.x->font);
2461}
2462
2463x_char_height (f)
2464 register struct frame *f;
2465{
2466 return FONT_HEIGHT (f->display.x->font);
01f1ba30
JB
2467}
2468\f
85ffea93
RS
2469#if 0 /* These no longer seem like the right way to do things. */
2470
f676886a 2471/* Draw a rectangle on the frame with left top corner including
01f1ba30
JB
2472 the character specified by LEFT_CHAR and TOP_CHAR. The rectangle is
2473 CHARS by LINES wide and long and is the color of the cursor. */
2474
2475void
f676886a
JB
2476x_rectangle (f, gc, left_char, top_char, chars, lines)
2477 register struct frame *f;
01f1ba30
JB
2478 GC gc;
2479 register int top_char, left_char, chars, lines;
2480{
2481 int width;
2482 int height;
f676886a
JB
2483 int left = (left_char * FONT_WIDTH (f->display.x->font)
2484 + f->display.x->internal_border_width);
2485 int top = (top_char * FONT_HEIGHT (f->display.x->font)
2486 + f->display.x->internal_border_width);
01f1ba30
JB
2487
2488 if (chars < 0)
f676886a 2489 width = FONT_WIDTH (f->display.x->font) / 2;
01f1ba30 2490 else
f676886a 2491 width = FONT_WIDTH (f->display.x->font) * chars;
01f1ba30 2492 if (lines < 0)
f676886a 2493 height = FONT_HEIGHT (f->display.x->font) / 2;
01f1ba30 2494 else
f676886a 2495 height = FONT_HEIGHT (f->display.x->font) * lines;
01f1ba30 2496
fe24a618 2497 XDrawRectangle (x_current_display, FRAME_X_WINDOW (f),
01f1ba30
JB
2498 gc, left, top, width, height);
2499}
2500
2501DEFUN ("x-draw-rectangle", Fx_draw_rectangle, Sx_draw_rectangle, 5, 5, 0,
f676886a 2502 "Draw a rectangle on FRAME between coordinates specified by\n\
01f1ba30 2503numbers X0, Y0, X1, Y1 in the cursor pixel.")
f676886a
JB
2504 (frame, X0, Y0, X1, Y1)
2505 register Lisp_Object frame, X0, X1, Y0, Y1;
01f1ba30
JB
2506{
2507 register int x0, y0, x1, y1, top, left, n_chars, n_lines;
2508
f676886a 2509 CHECK_LIVE_FRAME (frame, 0);
01f1ba30
JB
2510 CHECK_NUMBER (X0, 0);
2511 CHECK_NUMBER (Y0, 1);
2512 CHECK_NUMBER (X1, 2);
2513 CHECK_NUMBER (Y1, 3);
2514
2515 x0 = XINT (X0);
2516 x1 = XINT (X1);
2517 y0 = XINT (Y0);
2518 y1 = XINT (Y1);
2519
2520 if (y1 > y0)
2521 {
2522 top = y0;
2523 n_lines = y1 - y0 + 1;
2524 }
2525 else
2526 {
2527 top = y1;
2528 n_lines = y0 - y1 + 1;
2529 }
2530
2531 if (x1 > x0)
2532 {
2533 left = x0;
2534 n_chars = x1 - x0 + 1;
2535 }
2536 else
2537 {
2538 left = x1;
2539 n_chars = x0 - x1 + 1;
2540 }
2541
2542 BLOCK_INPUT;
f676886a 2543 x_rectangle (XFRAME (frame), XFRAME (frame)->display.x->cursor_gc,
01f1ba30
JB
2544 left, top, n_chars, n_lines);
2545 UNBLOCK_INPUT;
2546
2547 return Qt;
2548}
2549
2550DEFUN ("x-erase-rectangle", Fx_erase_rectangle, Sx_erase_rectangle, 5, 5, 0,
f676886a 2551 "Draw a rectangle drawn on FRAME between coordinates\n\
01f1ba30 2552X0, Y0, X1, Y1 in the regular background-pixel.")
f676886a
JB
2553 (frame, X0, Y0, X1, Y1)
2554 register Lisp_Object frame, X0, Y0, X1, Y1;
01f1ba30
JB
2555{
2556 register int x0, y0, x1, y1, top, left, n_chars, n_lines;
2557
f676886a 2558 CHECK_FRAME (frame, 0);
01f1ba30
JB
2559 CHECK_NUMBER (X0, 0);
2560 CHECK_NUMBER (Y0, 1);
2561 CHECK_NUMBER (X1, 2);
2562 CHECK_NUMBER (Y1, 3);
2563
2564 x0 = XINT (X0);
2565 x1 = XINT (X1);
2566 y0 = XINT (Y0);
2567 y1 = XINT (Y1);
2568
2569 if (y1 > y0)
2570 {
2571 top = y0;
2572 n_lines = y1 - y0 + 1;
2573 }
2574 else
2575 {
2576 top = y1;
2577 n_lines = y0 - y1 + 1;
2578 }
2579
2580 if (x1 > x0)
2581 {
2582 left = x0;
2583 n_chars = x1 - x0 + 1;
2584 }
2585 else
2586 {
2587 left = x1;
2588 n_chars = x0 - x1 + 1;
2589 }
2590
2591 BLOCK_INPUT;
f676886a 2592 x_rectangle (XFRAME (frame), XFRAME (frame)->display.x->reverse_gc,
01f1ba30
JB
2593 left, top, n_chars, n_lines);
2594 UNBLOCK_INPUT;
2595
2596 return Qt;
2597}
2598
2599/* Draw lines around the text region beginning at the character position
2600 TOP_X, TOP_Y and ending at BOTTOM_X and BOTTOM_Y. GC specifies the
2601 pixel and line characteristics. */
2602
f676886a 2603#define line_len(line) (FRAME_CURRENT_GLYPHS (f)->used[(line)])
01f1ba30
JB
2604
2605static void
f676886a
JB
2606outline_region (f, gc, top_x, top_y, bottom_x, bottom_y)
2607 register struct frame *f;
01f1ba30
JB
2608 GC gc;
2609 int top_x, top_y, bottom_x, bottom_y;
2610{
f676886a
JB
2611 register int ibw = f->display.x->internal_border_width;
2612 register int font_w = FONT_WIDTH (f->display.x->font);
2613 register int font_h = FONT_HEIGHT (f->display.x->font);
01f1ba30
JB
2614 int y = top_y;
2615 int x = line_len (y);
2616 XPoint *pixel_points = (XPoint *)
2617 alloca (((bottom_y - top_y + 2) * 4) * sizeof (XPoint));
2618 register XPoint *this_point = pixel_points;
2619
2620 /* Do the horizontal top line/lines */
2621 if (top_x == 0)
2622 {
2623 this_point->x = ibw;
2624 this_point->y = ibw + (font_h * top_y);
2625 this_point++;
2626 if (x == 0)
2627 this_point->x = ibw + (font_w / 2); /* Half-size for newline chars. */
2628 else
2629 this_point->x = ibw + (font_w * x);
2630 this_point->y = (this_point - 1)->y;
2631 }
2632 else
2633 {
2634 this_point->x = ibw;
2635 this_point->y = ibw + (font_h * (top_y + 1));
2636 this_point++;
2637 this_point->x = ibw + (font_w * top_x);
2638 this_point->y = (this_point - 1)->y;
2639 this_point++;
2640 this_point->x = (this_point - 1)->x;
2641 this_point->y = ibw + (font_h * top_y);
2642 this_point++;
2643 this_point->x = ibw + (font_w * x);
2644 this_point->y = (this_point - 1)->y;
2645 }
2646
2647 /* Now do the right side. */
2648 while (y < bottom_y)
2649 { /* Right vertical edge */
2650 this_point++;
2651 this_point->x = (this_point - 1)->x;
2652 this_point->y = ibw + (font_h * (y + 1));
2653 this_point++;
2654
2655 y++; /* Horizontal connection to next line */
2656 x = line_len (y);
2657 if (x == 0)
2658 this_point->x = ibw + (font_w / 2);
2659 else
2660 this_point->x = ibw + (font_w * x);
2661
2662 this_point->y = (this_point - 1)->y;
2663 }
2664
2665 /* Now do the bottom and connect to the top left point. */
2666 this_point->x = ibw + (font_w * (bottom_x + 1));
2667
2668 this_point++;
2669 this_point->x = (this_point - 1)->x;
2670 this_point->y = ibw + (font_h * (bottom_y + 1));
2671 this_point++;
2672 this_point->x = ibw;
2673 this_point->y = (this_point - 1)->y;
2674 this_point++;
2675 this_point->x = pixel_points->x;
2676 this_point->y = pixel_points->y;
2677
fe24a618 2678 XDrawLines (x_current_display, FRAME_X_WINDOW (f),
01f1ba30
JB
2679 gc, pixel_points,
2680 (this_point - pixel_points + 1), CoordModeOrigin);
2681}
2682
2683DEFUN ("x-contour-region", Fx_contour_region, Sx_contour_region, 1, 1, 0,
2684 "Highlight the region between point and the character under the mouse\n\
f676886a 2685selected frame.")
01f1ba30
JB
2686 (event)
2687 register Lisp_Object event;
2688{
2689 register int x0, y0, x1, y1;
f676886a 2690 register struct frame *f = selected_frame;
01f1ba30
JB
2691 register int p1, p2;
2692
2693 CHECK_CONS (event, 0);
2694
2695 BLOCK_INPUT;
2696 x0 = XINT (Fcar (Fcar (event)));
2697 y0 = XINT (Fcar (Fcdr (Fcar (event))));
2698
2699 /* If the mouse is past the end of the line, don't that area. */
2700 /* ReWrite this... */
2701
f676886a
JB
2702 x1 = f->cursor_x;
2703 y1 = f->cursor_y;
01f1ba30
JB
2704
2705 if (y1 > y0) /* point below mouse */
f676886a 2706 outline_region (f, f->display.x->cursor_gc,
01f1ba30
JB
2707 x0, y0, x1, y1);
2708 else if (y1 < y0) /* point above mouse */
f676886a 2709 outline_region (f, f->display.x->cursor_gc,
01f1ba30
JB
2710 x1, y1, x0, y0);
2711 else /* same line: draw horizontal rectangle */
2712 {
2713 if (x1 > x0)
f676886a 2714 x_rectangle (f, f->display.x->cursor_gc,
01f1ba30
JB
2715 x0, y0, (x1 - x0 + 1), 1);
2716 else if (x1 < x0)
f676886a 2717 x_rectangle (f, f->display.x->cursor_gc,
01f1ba30
JB
2718 x1, y1, (x0 - x1 + 1), 1);
2719 }
2720
2721 XFlush (x_current_display);
2722 UNBLOCK_INPUT;
2723
2724 return Qnil;
2725}
2726
2727DEFUN ("x-uncontour-region", Fx_uncontour_region, Sx_uncontour_region, 1, 1, 0,
2728 "Erase any highlighting of the region between point and the character\n\
f676886a 2729at X, Y on the selected frame.")
01f1ba30
JB
2730 (event)
2731 register Lisp_Object event;
2732{
2733 register int x0, y0, x1, y1;
f676886a 2734 register struct frame *f = selected_frame;
01f1ba30
JB
2735
2736 BLOCK_INPUT;
2737 x0 = XINT (Fcar (Fcar (event)));
2738 y0 = XINT (Fcar (Fcdr (Fcar (event))));
f676886a
JB
2739 x1 = f->cursor_x;
2740 y1 = f->cursor_y;
01f1ba30
JB
2741
2742 if (y1 > y0) /* point below mouse */
f676886a 2743 outline_region (f, f->display.x->reverse_gc,
01f1ba30
JB
2744 x0, y0, x1, y1);
2745 else if (y1 < y0) /* point above mouse */
f676886a 2746 outline_region (f, f->display.x->reverse_gc,
01f1ba30
JB
2747 x1, y1, x0, y0);
2748 else /* same line: draw horizontal rectangle */
2749 {
2750 if (x1 > x0)
f676886a 2751 x_rectangle (f, f->display.x->reverse_gc,
01f1ba30
JB
2752 x0, y0, (x1 - x0 + 1), 1);
2753 else if (x1 < x0)
f676886a 2754 x_rectangle (f, f->display.x->reverse_gc,
01f1ba30
JB
2755 x1, y1, (x0 - x1 + 1), 1);
2756 }
2757 UNBLOCK_INPUT;
2758
2759 return Qnil;
2760}
2761
01f1ba30
JB
2762#if 0
2763int contour_begin_x, contour_begin_y;
2764int contour_end_x, contour_end_y;
2765int contour_npoints;
2766
2767/* Clip the top part of the contour lines down (and including) line Y_POS.
2768 If X_POS is in the middle (rather than at the end) of the line, drop
2769 down a line at that character. */
2770
2771static void
2772clip_contour_top (y_pos, x_pos)
2773{
2774 register XPoint *begin = contour_lines[y_pos].top_left;
2775 register XPoint *end;
2776 register int npoints;
f676886a 2777 register struct display_line *line = selected_frame->phys_lines[y_pos + 1];
01f1ba30
JB
2778
2779 if (x_pos >= line->len - 1) /* Draw one, straight horizontal line. */
2780 {
2781 end = contour_lines[y_pos].top_right;
2782 npoints = (end - begin + 1);
2783 XDrawLines (x_current_display, contour_window,
2784 contour_erase_gc, begin_erase, npoints, CoordModeOrigin);
2785
2786 bcopy (end, begin + 1, contour_last_point - end + 1);
2787 contour_last_point -= (npoints - 2);
2788 XDrawLines (x_current_display, contour_window,
2789 contour_erase_gc, begin, 2, CoordModeOrigin);
2790 XFlush (x_current_display);
2791
2792 /* Now, update contour_lines structure. */
2793 }
2794 /* ______. */
2795 else /* |________*/
2796 {
2797 register XPoint *p = begin + 1;
2798 end = contour_lines[y_pos].bottom_right;
2799 npoints = (end - begin + 1);
2800 XDrawLines (x_current_display, contour_window,
2801 contour_erase_gc, begin_erase, npoints, CoordModeOrigin);
2802
2803 p->y = begin->y;
2804 p->x = ibw + (font_w * (x_pos + 1));
2805 p++;
2806 p->y = begin->y + font_h;
2807 p->x = (p - 1)->x;
2808 bcopy (end, begin + 3, contour_last_point - end + 1);
2809 contour_last_point -= (npoints - 5);
2810 XDrawLines (x_current_display, contour_window,
2811 contour_erase_gc, begin, 4, CoordModeOrigin);
2812 XFlush (x_current_display);
2813
2814 /* Now, update contour_lines structure. */
2815 }
2816}
2817
2818/* Erase the top horzontal lines of the contour, and then extend
2819 the contour upwards. */
2820
2821static void
2822extend_contour_top (line)
2823{
2824}
2825
2826static void
2827clip_contour_bottom (x_pos, y_pos)
2828 int x_pos, y_pos;
2829{
2830}
2831
2832static void
2833extend_contour_bottom (x_pos, y_pos)
2834{
2835}
2836
2837DEFUN ("x-select-region", Fx_select_region, Sx_select_region, 1, 1, "e",
2838 "")
2839 (event)
2840 Lisp_Object event;
2841{
f676886a
JB
2842 register struct frame *f = selected_frame;
2843 register int point_x = f->cursor_x;
2844 register int point_y = f->cursor_y;
01f1ba30
JB
2845 register int mouse_below_point;
2846 register Lisp_Object obj;
2847 register int x_contour_x, x_contour_y;
2848
2849 x_contour_x = x_mouse_x;
2850 x_contour_y = x_mouse_y;
2851 if (x_contour_y > point_y || (x_contour_y == point_y
2852 && x_contour_x > point_x))
2853 {
2854 mouse_below_point = 1;
f676886a 2855 outline_region (f, f->display.x->cursor_gc, point_x, point_y,
01f1ba30
JB
2856 x_contour_x, x_contour_y);
2857 }
2858 else
2859 {
2860 mouse_below_point = 0;
f676886a 2861 outline_region (f, f->display.x->cursor_gc, x_contour_x, x_contour_y,
01f1ba30
JB
2862 point_x, point_y);
2863 }
2864
2865 while (1)
2866 {
95be70ed 2867 obj = read_char (-1, 0, 0, Qnil, 0);
01f1ba30
JB
2868 if (XTYPE (obj) != Lisp_Cons)
2869 break;
2870
2871 if (mouse_below_point)
2872 {
2873 if (x_mouse_y <= point_y) /* Flipped. */
2874 {
2875 mouse_below_point = 0;
2876
f676886a 2877 outline_region (f, f->display.x->reverse_gc, point_x, point_y,
01f1ba30 2878 x_contour_x, x_contour_y);
f676886a 2879 outline_region (f, f->display.x->cursor_gc, x_mouse_x, x_mouse_y,
01f1ba30
JB
2880 point_x, point_y);
2881 }
2882 else if (x_mouse_y < x_contour_y) /* Bottom clipped. */
2883 {
2884 clip_contour_bottom (x_mouse_y);
2885 }
2886 else if (x_mouse_y > x_contour_y) /* Bottom extended. */
2887 {
2888 extend_bottom_contour (x_mouse_y);
2889 }
2890
2891 x_contour_x = x_mouse_x;
2892 x_contour_y = x_mouse_y;
2893 }
2894 else /* mouse above or same line as point */
2895 {
2896 if (x_mouse_y >= point_y) /* Flipped. */
2897 {
2898 mouse_below_point = 1;
2899
f676886a 2900 outline_region (f, f->display.x->reverse_gc,
01f1ba30 2901 x_contour_x, x_contour_y, point_x, point_y);
f676886a 2902 outline_region (f, f->display.x->cursor_gc, point_x, point_y,
01f1ba30
JB
2903 x_mouse_x, x_mouse_y);
2904 }
2905 else if (x_mouse_y > x_contour_y) /* Top clipped. */
2906 {
2907 clip_contour_top (x_mouse_y);
2908 }
2909 else if (x_mouse_y < x_contour_y) /* Top extended. */
2910 {
2911 extend_contour_top (x_mouse_y);
2912 }
2913 }
2914 }
2915
b4f5687c 2916 unread_command_event = obj;
01f1ba30
JB
2917 if (mouse_below_point)
2918 {
2919 contour_begin_x = point_x;
2920 contour_begin_y = point_y;
2921 contour_end_x = x_contour_x;
2922 contour_end_y = x_contour_y;
2923 }
2924 else
2925 {
2926 contour_begin_x = x_contour_x;
2927 contour_begin_y = x_contour_y;
2928 contour_end_x = point_x;
2929 contour_end_y = point_y;
2930 }
2931}
2932#endif
2933
2934DEFUN ("x-horizontal-line", Fx_horizontal_line, Sx_horizontal_line, 1, 1, "e",
2935 "")
2936 (event)
2937 Lisp_Object event;
2938{
2939 register Lisp_Object obj;
f676886a 2940 struct frame *f = selected_frame;
01f1ba30 2941 register struct window *w = XWINDOW (selected_window);
f676886a
JB
2942 register GC line_gc = f->display.x->cursor_gc;
2943 register GC erase_gc = f->display.x->reverse_gc;
01f1ba30
JB
2944#if 0
2945 char dash_list[] = {6, 4, 6, 4};
2946 int dashes = 4;
2947 XGCValues gc_values;
2948#endif
2949 register int previous_y;
f676886a
JB
2950 register int line = (x_mouse_y + 1) * FONT_HEIGHT (f->display.x->font)
2951 + f->display.x->internal_border_width;
2952 register int left = f->display.x->internal_border_width
01f1ba30 2953 + (w->left
f676886a 2954 * FONT_WIDTH (f->display.x->font));
01f1ba30 2955 register int right = left + (w->width
f676886a
JB
2956 * FONT_WIDTH (f->display.x->font))
2957 - f->display.x->internal_border_width;
01f1ba30
JB
2958
2959#if 0
2960 BLOCK_INPUT;
f676886a
JB
2961 gc_values.foreground = f->display.x->cursor_pixel;
2962 gc_values.background = f->display.x->background_pixel;
01f1ba30
JB
2963 gc_values.line_width = 1;
2964 gc_values.line_style = LineOnOffDash;
2965 gc_values.cap_style = CapRound;
2966 gc_values.join_style = JoinRound;
2967
fe24a618 2968 line_gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
01f1ba30
JB
2969 GCLineStyle | GCJoinStyle | GCCapStyle
2970 | GCLineWidth | GCForeground | GCBackground,
2971 &gc_values);
2972 XSetDashes (x_current_display, line_gc, 0, dash_list, dashes);
f676886a
JB
2973 gc_values.foreground = f->display.x->background_pixel;
2974 gc_values.background = f->display.x->foreground_pixel;
fe24a618 2975 erase_gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
01f1ba30
JB
2976 GCLineStyle | GCJoinStyle | GCCapStyle
2977 | GCLineWidth | GCForeground | GCBackground,
2978 &gc_values);
2979 XSetDashes (x_current_display, erase_gc, 0, dash_list, dashes);
2980#endif
2981
2982 while (1)
2983 {
2984 BLOCK_INPUT;
2985 if (x_mouse_y >= XINT (w->top)
2986 && x_mouse_y < XINT (w->top) + XINT (w->height) - 1)
2987 {
2988 previous_y = x_mouse_y;
f676886a
JB
2989 line = (x_mouse_y + 1) * FONT_HEIGHT (f->display.x->font)
2990 + f->display.x->internal_border_width;
fe24a618 2991 XDrawLine (x_current_display, FRAME_X_WINDOW (f),
01f1ba30
JB
2992 line_gc, left, line, right, line);
2993 }
2994 XFlushQueue ();
2995 UNBLOCK_INPUT;
2996
2997 do
2998 {
95be70ed 2999 obj = read_char (-1, 0, 0, Qnil, 0);
01f1ba30
JB
3000 if ((XTYPE (obj) != Lisp_Cons)
3001 || (! EQ (Fcar (Fcdr (Fcdr (obj))),
f9942c9e 3002 Qvertical_scroll_bar))
01f1ba30
JB
3003 || x_mouse_grabbed)
3004 {
3005 BLOCK_INPUT;
fe24a618 3006 XDrawLine (x_current_display, FRAME_X_WINDOW (f),
01f1ba30
JB
3007 erase_gc, left, line, right, line);
3008 UNBLOCK_INPUT;
b4f5687c 3009 unread_command_event = obj;
01f1ba30
JB
3010#if 0
3011 XFreeGC (x_current_display, line_gc);
3012 XFreeGC (x_current_display, erase_gc);
3013#endif
3014 return Qnil;
3015 }
3016 }
3017 while (x_mouse_y == previous_y);
3018
3019 BLOCK_INPUT;
fe24a618 3020 XDrawLine (x_current_display, FRAME_X_WINDOW (f),
01f1ba30
JB
3021 erase_gc, left, line, right, line);
3022 UNBLOCK_INPUT;
3023 }
3024}
06ef7355 3025#endif
01f1ba30 3026\f
01f1ba30
JB
3027/* Offset in buffer of character under the pointer, or 0. */
3028int mouse_buffer_offset;
3029
3030#if 0
3031/* These keep track of the rectangle following the pointer. */
3032int mouse_track_top, mouse_track_left, mouse_track_width;
3033
3034DEFUN ("x-track-pointer", Fx_track_pointer, Sx_track_pointer, 0, 0, 0,
3035 "Track the pointer.")
3036 ()
3037{
3038 static Cursor current_pointer_shape;
f676886a 3039 FRAME_PTR f = x_mouse_frame;
01f1ba30
JB
3040
3041 BLOCK_INPUT;
f676886a
JB
3042 if (EQ (Vmouse_frame_part, Qtext_part)
3043 && (current_pointer_shape != f->display.x->nontext_cursor))
01f1ba30
JB
3044 {
3045 unsigned char c;
3046 struct buffer *buf;
3047
f676886a 3048 current_pointer_shape = f->display.x->nontext_cursor;
01f1ba30 3049 XDefineCursor (x_current_display,
fe24a618 3050 FRAME_X_WINDOW (f),
01f1ba30
JB
3051 current_pointer_shape);
3052
3053 buf = XBUFFER (XWINDOW (Vmouse_window)->buffer);
3054 c = *(BUF_CHAR_ADDRESS (buf, mouse_buffer_offset));
3055 }
f676886a
JB
3056 else if (EQ (Vmouse_frame_part, Qmodeline_part)
3057 && (current_pointer_shape != f->display.x->modeline_cursor))
01f1ba30 3058 {
f676886a 3059 current_pointer_shape = f->display.x->modeline_cursor;
01f1ba30 3060 XDefineCursor (x_current_display,
fe24a618 3061 FRAME_X_WINDOW (f),
01f1ba30
JB
3062 current_pointer_shape);
3063 }
3064
3065 XFlushQueue ();
3066 UNBLOCK_INPUT;
3067}
3068#endif
3069
3070#if 0
3071DEFUN ("x-track-pointer", Fx_track_pointer, Sx_track_pointer, 1, 1, "e",
3072 "Draw rectangle around character under mouse pointer, if there is one.")
3073 (event)
3074 Lisp_Object event;
3075{
3076 struct window *w = XWINDOW (Vmouse_window);
f676886a 3077 struct frame *f = XFRAME (WINDOW_FRAME (w));
01f1ba30
JB
3078 struct buffer *b = XBUFFER (w->buffer);
3079 Lisp_Object obj;
3080
3081 if (! EQ (Vmouse_window, selected_window))
3082 return Qnil;
3083
3084 if (EQ (event, Qnil))
3085 {
3086 int x, y;
3087
f676886a 3088 x_read_mouse_position (selected_frame, &x, &y);
01f1ba30
JB
3089 }
3090
3091 BLOCK_INPUT;
3092 mouse_track_width = 0;
3093 mouse_track_left = mouse_track_top = -1;
3094
3095 do
3096 {
3097 if ((x_mouse_x != mouse_track_left
3098 && (x_mouse_x < mouse_track_left
3099 || x_mouse_x > (mouse_track_left + mouse_track_width)))
3100 || x_mouse_y != mouse_track_top)
3101 {
3102 int hp = 0; /* Horizontal position */
f676886a
JB
3103 int len = FRAME_CURRENT_GLYPHS (f)->used[x_mouse_y];
3104 int p = FRAME_CURRENT_GLYPHS (f)->bufp[x_mouse_y];
01f1ba30 3105 int tab_width = XINT (b->tab_width);
265a9e55 3106 int ctl_arrow_p = !NILP (b->ctl_arrow);
01f1ba30
JB
3107 unsigned char c;
3108 int mode_line_vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
3109 int in_mode_line = 0;
3110
f676886a 3111 if (! FRAME_CURRENT_GLYPHS (f)->enable[x_mouse_y])
01f1ba30
JB
3112 break;
3113
3114 /* Erase previous rectangle. */
3115 if (mouse_track_width)
3116 {
f676886a 3117 x_rectangle (f, f->display.x->reverse_gc,
01f1ba30
JB
3118 mouse_track_left, mouse_track_top,
3119 mouse_track_width, 1);
3120
f676886a
JB
3121 if ((mouse_track_left == f->phys_cursor_x
3122 || mouse_track_left == f->phys_cursor_x - 1)
3123 && mouse_track_top == f->phys_cursor_y)
01f1ba30 3124 {
f676886a 3125 x_display_cursor (f, 1);
01f1ba30
JB
3126 }
3127 }
3128
3129 mouse_track_left = x_mouse_x;
3130 mouse_track_top = x_mouse_y;
3131 mouse_track_width = 0;
3132
3133 if (mouse_track_left > len) /* Past the end of line. */
3134 goto draw_or_not;
3135
3136 if (mouse_track_top == mode_line_vpos)
3137 {
3138 in_mode_line = 1;
3139 goto draw_or_not;
3140 }
3141
3142 if (tab_width <= 0 || tab_width > 20) tab_width = 8;
3143 do
3144 {
3145 c = FETCH_CHAR (p);
f676886a 3146 if (len == f->width && hp == len - 1 && c != '\n')
01f1ba30
JB
3147 goto draw_or_not;
3148
3149 switch (c)
3150 {
3151 case '\t':
3152 mouse_track_width = tab_width - (hp % tab_width);
3153 p++;
3154 hp += mouse_track_width;
3155 if (hp > x_mouse_x)
3156 {
3157 mouse_track_left = hp - mouse_track_width;
3158 goto draw_or_not;
3159 }
3160 continue;
3161
3162 case '\n':
3163 mouse_track_width = -1;
3164 goto draw_or_not;
3165
3166 default:
3167 if (ctl_arrow_p && (c < 040 || c == 0177))
3168 {
3169 if (p > ZV)
3170 goto draw_or_not;
3171
3172 mouse_track_width = 2;
3173 p++;
3174 hp +=2;
3175 if (hp > x_mouse_x)
3176 {
3177 mouse_track_left = hp - mouse_track_width;
3178 goto draw_or_not;
3179 }
3180 }
3181 else
3182 {
3183 mouse_track_width = 1;
3184 p++;
3185 hp++;
3186 }
3187 continue;
3188 }
3189 }
3190 while (hp <= x_mouse_x);
3191
3192 draw_or_not:
3193 if (mouse_track_width) /* Over text; use text pointer shape. */
3194 {
3195 XDefineCursor (x_current_display,
fe24a618 3196 FRAME_X_WINDOW (f),
f676886a
JB
3197 f->display.x->text_cursor);
3198 x_rectangle (f, f->display.x->cursor_gc,
01f1ba30
JB
3199 mouse_track_left, mouse_track_top,
3200 mouse_track_width, 1);
3201 }
3202 else if (in_mode_line)
3203 XDefineCursor (x_current_display,
fe24a618 3204 FRAME_X_WINDOW (f),
f676886a 3205 f->display.x->modeline_cursor);
01f1ba30
JB
3206 else
3207 XDefineCursor (x_current_display,
fe24a618 3208 FRAME_X_WINDOW (f),
f676886a 3209 f->display.x->nontext_cursor);
01f1ba30
JB
3210 }
3211
3212 XFlush (x_current_display);
3213 UNBLOCK_INPUT;
3214
95be70ed 3215 obj = read_char (-1, 0, 0, Qnil, 0);
01f1ba30
JB
3216 BLOCK_INPUT;
3217 }
3218 while (XTYPE (obj) == Lisp_Cons /* Mouse event */
a3c87d4e 3219 && EQ (Fcar (Fcdr (Fcdr (obj))), Qnil) /* Not scroll bar */
01f1ba30
JB
3220 && EQ (Vmouse_depressed, Qnil) /* Only motion events */
3221 && EQ (Vmouse_window, selected_window) /* In this window */
f676886a 3222 && x_mouse_frame);
01f1ba30 3223
b4f5687c 3224 unread_command_event = obj;
01f1ba30
JB
3225
3226 if (mouse_track_width)
3227 {
f676886a 3228 x_rectangle (f, f->display.x->reverse_gc,
01f1ba30
JB
3229 mouse_track_left, mouse_track_top,
3230 mouse_track_width, 1);
3231 mouse_track_width = 0;
f676886a
JB
3232 if ((mouse_track_left == f->phys_cursor_x
3233 || mouse_track_left - 1 == f->phys_cursor_x)
3234 && mouse_track_top == f->phys_cursor_y)
01f1ba30 3235 {
f676886a 3236 x_display_cursor (f, 1);
01f1ba30
JB
3237 }
3238 }
3239 XDefineCursor (x_current_display,
fe24a618 3240 FRAME_X_WINDOW (f),
f676886a 3241 f->display.x->nontext_cursor);
01f1ba30
JB
3242 XFlush (x_current_display);
3243 UNBLOCK_INPUT;
3244
3245 return Qnil;
3246}
3247#endif
3248\f
3249#if 0
3250#include "glyphs.h"
3251
3252/* Draw a pixmap specified by IMAGE_DATA of dimensions WIDTH and HEIGHT
f676886a 3253 on the frame F at position X, Y. */
01f1ba30 3254
f676886a
JB
3255x_draw_pixmap (f, x, y, image_data, width, height)
3256 struct frame *f;
01f1ba30
JB
3257 int x, y, width, height;
3258 char *image_data;
3259{
3260 Pixmap image;
3261
3262 image = XCreateBitmapFromData (x_current_display,
fe24a618 3263 FRAME_X_WINDOW (f), image_data,
01f1ba30 3264 width, height);
fe24a618 3265 XCopyPlane (x_current_display, image, FRAME_X_WINDOW (f),
f676886a 3266 f->display.x->normal_gc, 0, 0, width, height, x, y);
01f1ba30
JB
3267}
3268#endif
3269\f
01f1ba30
JB
3270#ifndef HAVE_X11
3271DEFUN ("x-store-cut-buffer", Fx_store_cut_buffer, Sx_store_cut_buffer,
3272 1, 1, "sStore text in cut buffer: ",
3273 "Store contents of STRING into the cut buffer of the X window system.")
3274 (string)
3275 register Lisp_Object string;
3276{
3277 int mask;
3278
3279 CHECK_STRING (string, 1);
f9942c9e 3280 if (! FRAME_X_P (selected_frame))
f676886a 3281 error ("Selected frame does not understand X protocol.");
01f1ba30
JB
3282
3283 BLOCK_INPUT;
3284 XStoreBytes ((char *) XSTRING (string)->data, XSTRING (string)->size);
3285 UNBLOCK_INPUT;
3286
3287 return Qnil;
3288}
3289
3290DEFUN ("x-get-cut-buffer", Fx_get_cut_buffer, Sx_get_cut_buffer, 0, 0, 0,
3291 "Return contents of cut buffer of the X window system, as a string.")
3292 ()
3293{
3294 int len;
3295 register Lisp_Object string;
3296 int mask;
3297 register char *d;
3298
3299 BLOCK_INPUT;
3300 d = XFetchBytes (&len);
3301 string = make_string (d, len);
3302 XFree (d);
3303 UNBLOCK_INPUT;
3304 return string;
3305}
3306#endif /* X10 */
3307\f
3308#ifdef HAVE_X11
3309DEFUN ("x-rebind-key", Fx_rebind_key, Sx_rebind_key, 3, 3, 0,
3310"Rebind X keysym KEYSYM, with MODIFIERS, to generate NEWSTRING.\n\
3311KEYSYM is a string which conforms to the X keysym definitions found\n\
3312in X11/keysymdef.h, sans the initial XK_. MODIFIERS is nil or a\n\
3313list of strings specifying modifier keys such as Control_L, which must\n\
3314also be depressed for NEWSTRING to appear.")
3315 (x_keysym, modifiers, newstring)
3316 register Lisp_Object x_keysym;
3317 register Lisp_Object modifiers;
3318 register Lisp_Object newstring;
3319{
3320 char *rawstring;
c047688c
JA
3321 register KeySym keysym;
3322 KeySym modifier_list[16];
01f1ba30 3323
11ae94fe 3324 check_x ();
01f1ba30
JB
3325 CHECK_STRING (x_keysym, 1);
3326 CHECK_STRING (newstring, 3);
3327
3328 keysym = XStringToKeysym ((char *) XSTRING (x_keysym)->data);
3329 if (keysym == NoSymbol)
3330 error ("Keysym does not exist");
3331
265a9e55 3332 if (NILP (modifiers))
01f1ba30
JB
3333 XRebindKeysym (x_current_display, keysym, modifier_list, 0,
3334 XSTRING (newstring)->data, XSTRING (newstring)->size);
3335 else
3336 {
3337 register Lisp_Object rest, mod;
3338 register int i = 0;
3339
265a9e55 3340 for (rest = modifiers; !NILP (rest); rest = Fcdr (rest))
01f1ba30
JB
3341 {
3342 if (i == 16)
3343 error ("Can't have more than 16 modifiers");
3344
3345 mod = Fcar (rest);
3346 CHECK_STRING (mod, 3);
3347 modifier_list[i] = XStringToKeysym ((char *) XSTRING (mod)->data);
3348 if (modifier_list[i] == NoSymbol
3349 || !IsModifierKey (modifier_list[i]))
3350 error ("Element is not a modifier keysym");
3351 i++;
3352 }
3353
3354 XRebindKeysym (x_current_display, keysym, modifier_list, i,
3355 XSTRING (newstring)->data, XSTRING (newstring)->size);
3356 }
3357
3358 return Qnil;
3359}
3360
3361DEFUN ("x-rebind-keys", Fx_rebind_keys, Sx_rebind_keys, 2, 2, 0,
3362 "Rebind KEYCODE to list of strings STRINGS.\n\
3363STRINGS should be a list of 16 elements, one for each shift combination.\n\
3364nil as element means don't change.\n\
3365See the documentation of `x-rebind-key' for more information.")
3366 (keycode, strings)
3367 register Lisp_Object keycode;
3368 register Lisp_Object strings;
3369{
3370 register Lisp_Object item;
3371 register unsigned char *rawstring;
3372 KeySym rawkey, modifier[1];
3373 int strsize;
3374 register unsigned i;
3375
11ae94fe 3376 check_x ();
01f1ba30
JB
3377 CHECK_NUMBER (keycode, 1);
3378 CHECK_CONS (strings, 2);
3379 rawkey = (KeySym) ((unsigned) (XINT (keycode))) & 255;
3380 for (i = 0; i <= 15; strings = Fcdr (strings), i++)
3381 {
3382 item = Fcar (strings);
265a9e55 3383 if (!NILP (item))
01f1ba30
JB
3384 {
3385 CHECK_STRING (item, 2);
3386 strsize = XSTRING (item)->size;
3387 rawstring = (unsigned char *) xmalloc (strsize);
3388 bcopy (XSTRING (item)->data, rawstring, strsize);
3389 modifier[1] = 1 << i;
3390 XRebindKeysym (x_current_display, rawkey, modifier, 1,
3391 rawstring, strsize);
3392 }
3393 }
3394 return Qnil;
3395}
9d04a87a 3396#endif /* HAVE_X11 */
01f1ba30
JB
3397\f
3398#ifdef HAVE_X11
3399Visual *
3400select_visual (screen, depth)
3401 Screen *screen;
3402 unsigned int *depth;
3403{
3404 Visual *v;
3405 XVisualInfo *vinfo, vinfo_template;
3406 int n_visuals;
3407
3408 v = DefaultVisualOfScreen (screen);
fe24a618
JB
3409
3410#ifdef HAVE_X11R4
3411 vinfo_template.visualid = XVisualIDFromVisual (v);
3412#else
6afb1d07 3413 vinfo_template.visualid = v->visualid;
fe24a618
JB
3414#endif
3415
f0614854
JB
3416 vinfo_template.screen = XScreenNumberOfScreen (screen);
3417
3418 vinfo = XGetVisualInfo (x_current_display,
3419 VisualIDMask | VisualScreenMask, &vinfo_template,
01f1ba30
JB
3420 &n_visuals);
3421 if (n_visuals != 1)
3422 fatal ("Can't get proper X visual info");
3423
3424 if ((1 << vinfo->depth) == vinfo->colormap_size)
3425 *depth = vinfo->depth;
3426 else
3427 {
3428 int i = 0;
3429 int n = vinfo->colormap_size - 1;
3430 while (n)
3431 {
3432 n = n >> 1;
3433 i++;
3434 }
3435 *depth = i;
3436 }
3437
3438 XFree ((char *) vinfo);
3439 return v;
3440}
3441#endif /* HAVE_X11 */
3442
3443DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
3444 1, 2, 0, "Open a connection to an X server.\n\
3445DISPLAY is the name of the display to connect to. Optional second\n\
3446arg XRM_STRING is a string of resources in xrdb format.")
3447 (display, xrm_string)
3448 Lisp_Object display, xrm_string;
3449{
3450 unsigned int n_planes;
01f1ba30
JB
3451 unsigned char *xrm_option;
3452
3453 CHECK_STRING (display, 0);
3454 if (x_current_display != 0)
3455 error ("X server connection is already initialized");
3456
3457 /* This is what opens the connection and sets x_current_display.
3458 This also initializes many symbols, such as those used for input. */
3459 x_term_init (XSTRING (display)->data);
3460
01f1ba30
JB
3461#ifdef HAVE_X11
3462 XFASTINT (Vwindow_system_version) = 11;
3463
3464 if (!EQ (xrm_string, Qnil))
3465 {
3466 CHECK_STRING (xrm_string, 1);
6c703f4a 3467 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
01f1ba30
JB
3468 }
3469 else
3470 xrm_option = (unsigned char *) 0;
3471 xrdb = x_load_resources (x_current_display, xrm_option, EMACS_CLASS);
c58a1a0c 3472#if defined (HAVE_X11R5) && ! defined (NO_XRM_SET_DATBASE)
eb5d618c
JB
3473 XrmSetDatabase (x_current_display, xrdb);
3474#else
01f1ba30 3475 x_current_display->db = xrdb;
eb5d618c 3476#endif
01f1ba30 3477
ac63d3d6
JB
3478 /* Make a version of Vinvocation_name suitable for use in xrdb
3479 queries - i.e. containing no dots or asterisks. */
3480 Vxrdb_name = Fcopy_sequence (Vinvocation_name);
3481 {
3482 int i;
3483 int len = XSTRING (Vxrdb_name)->size;
3484 char *data = XSTRING (Vxrdb_name)->data;
3485
3486 for (i = 0; i < len; i++)
3487 if (data[i] == '.' || data[i] == '*')
3488 data[i] = '-';
3489 }
3490
01f1ba30
JB
3491 x_screen = DefaultScreenOfDisplay (x_current_display);
3492
01f1ba30 3493 screen_visual = select_visual (x_screen, &n_planes);
a6605e5c 3494 x_screen_planes = n_planes;
41beb8fc
RS
3495 x_screen_height = HeightOfScreen (x_screen);
3496 x_screen_width = WidthOfScreen (x_screen);
01f1ba30
JB
3497
3498 /* X Atoms used by emacs. */
99e72068 3499 Xatoms_of_xselect ();
01f1ba30 3500 BLOCK_INPUT;
3c254570
JA
3501 Xatom_wm_protocols = XInternAtom (x_current_display, "WM_PROTOCOLS",
3502 False);
3503 Xatom_wm_take_focus = XInternAtom (x_current_display, "WM_TAKE_FOCUS",
3504 False);
3505 Xatom_wm_save_yourself = XInternAtom (x_current_display, "WM_SAVE_YOURSELF",
3506 False);
3507 Xatom_wm_delete_window = XInternAtom (x_current_display, "WM_DELETE_WINDOW",
3508 False);
3509 Xatom_wm_change_state = XInternAtom (x_current_display, "WM_CHANGE_STATE",
3510 False);
3511 Xatom_wm_configure_denied = XInternAtom (x_current_display,
3512 "WM_CONFIGURE_DENIED", False);
3513 Xatom_wm_window_moved = XInternAtom (x_current_display, "WM_MOVED",
3514 False);
01f1ba30
JB
3515 UNBLOCK_INPUT;
3516#else /* not HAVE_X11 */
3517 XFASTINT (Vwindow_system_version) = 10;
3518#endif /* not HAVE_X11 */
3519 return Qnil;
3520}
3521
3522DEFUN ("x-close-current-connection", Fx_close_current_connection,
3523 Sx_close_current_connection,
3524 0, 0, 0, "Close the connection to the current X server.")
3525 ()
3526{
3527#ifdef HAVE_X11
3528 /* This is ONLY used when killing emacs; For switching displays
3529 we'll have to take care of setting CloseDownMode elsewhere. */
3530
3531 if (x_current_display)
3532 {
3533 BLOCK_INPUT;
3534 XSetCloseDownMode (x_current_display, DestroyAll);
3535 XCloseDisplay (x_current_display);
739f2f53 3536 x_current_display = 0;
01f1ba30
JB
3537 }
3538 else
3539 fatal ("No current X display connection to close\n");
3540#endif
3541 return Qnil;
3542}
3543
3544DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize,
3545 1, 1, 0, "If ON is non-nil, report X errors as soon as the erring request is made.\n\
3546If ON is nil, allow buffering of requests.\n\
3547Turning on synchronization prohibits the Xlib routines from buffering\n\
3548requests and seriously degrades performance, but makes debugging much\n\
3549easier.")
3550 (on)
3551 Lisp_Object on;
3552{
11ae94fe
RS
3553 check_x ();
3554
01f1ba30
JB
3555 XSynchronize (x_current_display, !EQ (on, Qnil));
3556
3557 return Qnil;
3558}
3559
3560\f
3561syms_of_xfns ()
3562{
01f1ba30
JB
3563 /* This is zero if not using X windows. */
3564 x_current_display = 0;
3565
f9942c9e
JB
3566 /* The section below is built by the lisp expression at the top of the file,
3567 just above where these variables are declared. */
3568 /*&&& init symbols here &&&*/
3569 Qauto_raise = intern ("auto-raise");
3570 staticpro (&Qauto_raise);
3571 Qauto_lower = intern ("auto-lower");
3572 staticpro (&Qauto_lower);
3573 Qbackground_color = intern ("background-color");
3574 staticpro (&Qbackground_color);
dbc4e1c1
JB
3575 Qbar = intern ("bar");
3576 staticpro (&Qbar);
f9942c9e
JB
3577 Qborder_color = intern ("border-color");
3578 staticpro (&Qborder_color);
3579 Qborder_width = intern ("border-width");
3580 staticpro (&Qborder_width);
dbc4e1c1
JB
3581 Qbox = intern ("box");
3582 staticpro (&Qbox);
f9942c9e
JB
3583 Qcursor_color = intern ("cursor-color");
3584 staticpro (&Qcursor_color);
dbc4e1c1
JB
3585 Qcursor_type = intern ("cursor-type");
3586 staticpro (&Qcursor_type);
f9942c9e
JB
3587 Qfont = intern ("font");
3588 staticpro (&Qfont);
3589 Qforeground_color = intern ("foreground-color");
3590 staticpro (&Qforeground_color);
3591 Qgeometry = intern ("geometry");
3592 staticpro (&Qgeometry);
49795535
JB
3593 Qicon = intern ("icon");
3594 staticpro (&Qicon);
f9942c9e
JB
3595 Qicon_left = intern ("icon-left");
3596 staticpro (&Qicon_left);
3597 Qicon_top = intern ("icon-top");
3598 staticpro (&Qicon_top);
3599 Qicon_type = intern ("icon-type");
3600 staticpro (&Qicon_type);
f9942c9e
JB
3601 Qinternal_border_width = intern ("internal-border-width");
3602 staticpro (&Qinternal_border_width);
3603 Qleft = intern ("left");
3604 staticpro (&Qleft);
3605 Qmouse_color = intern ("mouse-color");
3606 staticpro (&Qmouse_color);
baaed68e
JB
3607 Qnone = intern ("none");
3608 staticpro (&Qnone);
f9942c9e
JB
3609 Qparent_id = intern ("parent-id");
3610 staticpro (&Qparent_id);
8af1d7ca
JB
3611 Qsuppress_icon = intern ("suppress-icon");
3612 staticpro (&Qsuppress_icon);
f9942c9e
JB
3613 Qtop = intern ("top");
3614 staticpro (&Qtop);
01f1ba30 3615 Qundefined_color = intern ("undefined-color");
f9942c9e 3616 staticpro (&Qundefined_color);
a3c87d4e
JB
3617 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
3618 staticpro (&Qvertical_scroll_bars);
49795535
JB
3619 Qvisibility = intern ("visibility");
3620 staticpro (&Qvisibility);
f9942c9e
JB
3621 Qwindow_id = intern ("window-id");
3622 staticpro (&Qwindow_id);
3623 Qx_frame_parameter = intern ("x-frame-parameter");
3624 staticpro (&Qx_frame_parameter);
3625 /* This is the end of symbol initialization. */
3626
01f1ba30
JB
3627 Fput (Qundefined_color, Qerror_conditions,
3628 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
3629 Fput (Qundefined_color, Qerror_message,
3630 build_string ("Undefined color"));
3631
f9942c9e
JB
3632 init_x_parm_symbols ();
3633
01f1ba30
JB
3634 DEFVAR_INT ("mouse-buffer-offset", &mouse_buffer_offset,
3635 "The buffer offset of the character under the pointer.");
a6605e5c 3636 mouse_buffer_offset = 0;
01f1ba30 3637
01f1ba30 3638 DEFVAR_INT ("x-pointer-shape", &Vx_pointer_shape,
af01ef26
RS
3639 "The shape of the pointer when over text.\n\
3640Changing the value does not affect existing frames\n\
3641unless you set the mouse color.");
01f1ba30
JB
3642 Vx_pointer_shape = Qnil;
3643
ac63d3d6
JB
3644 staticpro (&Vxrdb_name);
3645
af01ef26 3646#if 0
01f1ba30
JB
3647 DEFVAR_INT ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
3648 "The shape of the pointer when not over text.");
af01ef26 3649#endif
01f1ba30
JB
3650 Vx_nontext_pointer_shape = Qnil;
3651
af01ef26 3652#if 0
01f1ba30 3653 DEFVAR_INT ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
06ef7355 3654 "The shape of the pointer when over the mode line.");
af01ef26 3655#endif
01f1ba30
JB
3656 Vx_mode_pointer_shape = Qnil;
3657
01f1ba30
JB
3658 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
3659 "A string indicating the foreground color of the cursor box.");
3660 Vx_cursor_fore_pixel = Qnil;
3661
3662 DEFVAR_LISP ("mouse-grabbed", &Vmouse_depressed,
3663 "Non-nil if a mouse button is currently depressed.");
3664 Vmouse_depressed = Qnil;
3665
01f1ba30
JB
3666 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
3667 "t if no X window manager is in use.");
3668
3669#ifdef HAVE_X11
3670 defsubr (&Sx_get_resource);
85ffea93 3671#if 0
01f1ba30
JB
3672 defsubr (&Sx_draw_rectangle);
3673 defsubr (&Sx_erase_rectangle);
3674 defsubr (&Sx_contour_region);
3675 defsubr (&Sx_uncontour_region);
85ffea93 3676#endif
bcc426b4 3677 defsubr (&Sx_display_color_p);
f0614854 3678 defsubr (&Sx_list_fonts);
8af1d7ca 3679 defsubr (&Sx_color_defined_p);
41beb8fc
RS
3680 defsubr (&Sx_server_vendor);
3681 defsubr (&Sx_server_version);
3682 defsubr (&Sx_display_pixel_width);
3683 defsubr (&Sx_display_pixel_height);
3684 defsubr (&Sx_display_mm_width);
3685 defsubr (&Sx_display_mm_height);
3686 defsubr (&Sx_display_screens);
3687 defsubr (&Sx_display_planes);
3688 defsubr (&Sx_display_color_cells);
3689 defsubr (&Sx_display_visual_class);
3690 defsubr (&Sx_display_backing_store);
3691 defsubr (&Sx_display_save_under);
9d04a87a
RS
3692 defsubr (&Sx_rebind_key);
3693 defsubr (&Sx_rebind_keys);
01f1ba30
JB
3694#if 0
3695 defsubr (&Sx_track_pointer);
01f1ba30
JB
3696 defsubr (&Sx_grab_pointer);
3697 defsubr (&Sx_ungrab_pointer);
809ca691 3698#endif
01f1ba30
JB
3699#else
3700 defsubr (&Sx_get_default);
3701 defsubr (&Sx_store_cut_buffer);
3702 defsubr (&Sx_get_cut_buffer);
01f1ba30 3703#endif
8af1d7ca 3704 defsubr (&Sx_parse_geometry);
f676886a
JB
3705 defsubr (&Sx_create_frame);
3706 defsubr (&Sfocus_frame);
3707 defsubr (&Sunfocus_frame);
06ef7355 3708#if 0
01f1ba30 3709 defsubr (&Sx_horizontal_line);
06ef7355 3710#endif
01f1ba30
JB
3711 defsubr (&Sx_open_connection);
3712 defsubr (&Sx_close_current_connection);
3713 defsubr (&Sx_synchronize);
01f1ba30
JB
3714}
3715
3716#endif /* HAVE_X_WINDOWS */