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