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