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