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