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