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