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