(Fsplit_window): Rename size to size_int and chsize to size.
[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"
ef818feb 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;
97a1ff91 1700 if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
0d8ef3f4
RS
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;
97a1ff91
RS
1709 if (FRAME_X_P (f))
1710 f->output_data.x->menubar_widget = 0;
9ef48a9d
RS
1711 }
1712#else /* not USE_X_TOOLKIT */
d043f1a4
RS
1713 FRAME_MENU_BAR_LINES (f) = nlines;
1714 x_set_menu_bar_lines_1 (f->root_window, nlines - olines);
9ef48a9d 1715#endif /* not USE_X_TOOLKIT */
d043f1a4
RS
1716}
1717
75f9d625 1718/* Change the name of frame F to NAME. If NAME is nil, set F's name to
f945b920
JB
1719 x_id_name.
1720
1721 If EXPLICIT is non-zero, that indicates that lisp code is setting the
75f9d625
DM
1722 name; if NAME is a string, set F's name to NAME and set
1723 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
f945b920
JB
1724
1725 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1726 suggesting a new name, which lisp code should override; if
1727 F->explicit_name is set, ignore the new name; otherwise, set it. */
1728
1729void
1730x_set_name (f, name, explicit)
1731 struct frame *f;
1732 Lisp_Object name;
1733 int explicit;
1734{
1735 /* Make sure that requests from lisp code override requests from
1736 Emacs redisplay code. */
1737 if (explicit)
1738 {
1739 /* If we're switching from explicit to implicit, we had better
1740 update the mode lines and thereby update the title. */
1741 if (f->explicit_name && NILP (name))
cf177271 1742 update_mode_lines = 1;
f945b920
JB
1743
1744 f->explicit_name = ! NILP (name);
1745 }
1746 else if (f->explicit_name)
1747 return;
1748
1749 /* If NAME is nil, set the name to the x_id_name. */
1750 if (NILP (name))
f10f0b79
RS
1751 {
1752 /* Check for no change needed in this very common case
1753 before we do any consing. */
08a90d6a
RS
1754 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
1755 XSTRING (f->name)->data))
f10f0b79 1756 return;
08a90d6a 1757 name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
f10f0b79 1758 }
62265f1c 1759 else
f945b920 1760 CHECK_STRING (name, 0);
01f1ba30 1761
f945b920
JB
1762 /* Don't change the name if it's already NAME. */
1763 if (! NILP (Fstring_equal (name, f->name)))
daa37602
JB
1764 return;
1765
fe24a618 1766 if (FRAME_X_WINDOW (f))
01f1ba30 1767 {
01f1ba30 1768 BLOCK_INPUT;
fe24a618
JB
1769#ifdef HAVE_X11R4
1770 {
80534dd6
KH
1771 XTextProperty text, icon;
1772 Lisp_Object icon_name;
1773
fe24a618
JB
1774 text.value = XSTRING (name)->data;
1775 text.encoding = XA_STRING;
1776 text.format = 8;
1777 text.nitems = XSTRING (name)->size;
80534dd6 1778
f468da95 1779 icon_name = (!NILP (f->icon_name) ? f->icon_name : name);
80534dd6
KH
1780
1781 icon.value = XSTRING (icon_name)->data;
1782 icon.encoding = XA_STRING;
1783 icon.format = 8;
1784 icon.nitems = XSTRING (icon_name)->size;
9ef48a9d 1785#ifdef USE_X_TOOLKIT
b9dc4443 1786 XSetWMName (FRAME_X_DISPLAY (f),
7556890b
RS
1787 XtWindow (f->output_data.x->widget), &text);
1788 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
80534dd6 1789 &icon);
9ef48a9d 1790#else /* not USE_X_TOOLKIT */
b9dc4443 1791 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
80534dd6 1792 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
9ef48a9d 1793#endif /* not USE_X_TOOLKIT */
fe24a618 1794 }
9ef48a9d 1795#else /* not HAVE_X11R4 */
b9dc4443 1796 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
fe24a618 1797 XSTRING (name)->data);
b9dc4443 1798 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
fe24a618 1799 XSTRING (name)->data);
9ef48a9d 1800#endif /* not HAVE_X11R4 */
01f1ba30
JB
1801 UNBLOCK_INPUT;
1802 }
daa37602 1803
f945b920
JB
1804 f->name = name;
1805}
1806
1807/* This function should be called when the user's lisp code has
1808 specified a name for the frame; the name will override any set by the
1809 redisplay code. */
1810void
1811x_explicitly_set_name (f, arg, oldval)
1812 FRAME_PTR f;
1813 Lisp_Object arg, oldval;
1814{
1815 x_set_name (f, arg, 1);
1816}
1817
1818/* This function should be called by Emacs redisplay code to set the
1819 name; names set this way will never override names set by the user's
1820 lisp code. */
25250031 1821void
f945b920
JB
1822x_implicitly_set_name (f, arg, oldval)
1823 FRAME_PTR f;
1824 Lisp_Object arg, oldval;
1825{
1826 x_set_name (f, arg, 0);
01f1ba30
JB
1827}
1828
1829void
f676886a
JB
1830x_set_autoraise (f, arg, oldval)
1831 struct frame *f;
01f1ba30
JB
1832 Lisp_Object arg, oldval;
1833{
f676886a 1834 f->auto_raise = !EQ (Qnil, arg);
01f1ba30
JB
1835}
1836
1837void
f676886a
JB
1838x_set_autolower (f, arg, oldval)
1839 struct frame *f;
01f1ba30
JB
1840 Lisp_Object arg, oldval;
1841{
f676886a 1842 f->auto_lower = !EQ (Qnil, arg);
01f1ba30 1843}
179956b9 1844
eac358ef
KH
1845void
1846x_set_unsplittable (f, arg, oldval)
1847 struct frame *f;
1848 Lisp_Object arg, oldval;
1849{
1850 f->no_split = !NILP (arg);
1851}
1852
179956b9 1853void
a3c87d4e 1854x_set_vertical_scroll_bars (f, arg, oldval)
179956b9
JB
1855 struct frame *f;
1856 Lisp_Object arg, oldval;
1857{
a3c87d4e 1858 if (NILP (arg) != ! FRAME_HAS_VERTICAL_SCROLL_BARS (f))
179956b9 1859 {
a3c87d4e 1860 FRAME_HAS_VERTICAL_SCROLL_BARS (f) = ! NILP (arg);
179956b9 1861
cf177271
JB
1862 /* We set this parameter before creating the X window for the
1863 frame, so we can get the geometry right from the start.
1864 However, if the window hasn't been created yet, we shouldn't
1865 call x_set_window_size. */
1866 if (FRAME_X_WINDOW (f))
363f7e15 1867 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
179956b9
JB
1868 }
1869}
4701395c
KH
1870
1871void
1872x_set_scroll_bar_width (f, arg, oldval)
1873 struct frame *f;
1874 Lisp_Object arg, oldval;
1875{
dff9a538
KH
1876 if (NILP (arg))
1877 {
1878 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
1879 FRAME_SCROLL_BAR_COLS (f) = 2;
1880 }
1881 else if (INTEGERP (arg) && XINT (arg) > 0
1882 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
4701395c 1883 {
7556890b 1884 int wid = FONT_WIDTH (f->output_data.x->font);
4701395c
KH
1885 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
1886 FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
1887 if (FRAME_X_WINDOW (f))
1888 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
1889 }
1890}
01f1ba30 1891\f
f676886a 1892/* Subroutines of creating an X frame. */
01f1ba30 1893
b7975ee4
KH
1894/* Make sure that Vx_resource_name is set to a reasonable value.
1895 Fix it up, or set it to `emacs' if it is too hopeless. */
1896
d387c960
JB
1897static void
1898validate_x_resource_name ()
1899{
0e78b377
RS
1900 int len;
1901 /* Number of valid characters in the resource name. */
1902 int good_count = 0;
1903 /* Number of invalid characters in the resource name. */
1904 int bad_count = 0;
1905 Lisp_Object new;
1906 int i;
1907
cf204347
RS
1908 if (STRINGP (Vx_resource_name))
1909 {
cf204347
RS
1910 unsigned char *p = XSTRING (Vx_resource_name)->data;
1911 int i;
1912
0e78b377
RS
1913 len = XSTRING (Vx_resource_name)->size;
1914
1915 /* Only letters, digits, - and _ are valid in resource names.
1916 Count the valid characters and count the invalid ones. */
cf204347
RS
1917 for (i = 0; i < len; i++)
1918 {
1919 int c = p[i];
1920 if (! ((c >= 'a' && c <= 'z')
1921 || (c >= 'A' && c <= 'Z')
1922 || (c >= '0' && c <= '9')
1923 || c == '-' || c == '_'))
0e78b377
RS
1924 bad_count++;
1925 else
1926 good_count++;
cf204347
RS
1927 }
1928 }
1929 else
0e78b377
RS
1930 /* Not a string => completely invalid. */
1931 bad_count = 5, good_count = 0;
1932
1933 /* If name is valid already, return. */
1934 if (bad_count == 0)
1935 return;
1936
1937 /* If name is entirely invalid, or nearly so, use `emacs'. */
1938 if (good_count == 0
1939 || (good_count == 1 && bad_count > 0))
1940 {
b7975ee4 1941 Vx_resource_name = build_string ("emacs");
0e78b377
RS
1942 return;
1943 }
1944
1945 /* Name is partly valid. Copy it and replace the invalid characters
1946 with underscores. */
1947
1948 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
1949
1950 for (i = 0; i < len; i++)
1951 {
1952 int c = XSTRING (new)->data[i];
1953 if (! ((c >= 'a' && c <= 'z')
1954 || (c >= 'A' && c <= 'Z')
1955 || (c >= '0' && c <= '9')
1956 || c == '-' || c == '_'))
1957 XSTRING (new)->data[i] = '_';
1958 }
d387c960
JB
1959}
1960
1961
01f1ba30 1962extern char *x_get_string_resource ();
01f1ba30 1963
cf177271
JB
1964DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
1965 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
287e500d 1966This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
d387c960
JB
1967class, where INSTANCE is the name under which Emacs was invoked, or\n\
1968the name specified by the `-name' or `-rn' command-line arguments.\n\
01f1ba30 1969\n\
8fabe6f4
RS
1970The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
1971class, respectively. You must specify both of them or neither.\n\
287e500d
RS
1972If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
1973and the class is `Emacs.CLASS.SUBCLASS'.")
cf177271
JB
1974 (attribute, class, component, subclass)
1975 Lisp_Object attribute, class, component, subclass;
01f1ba30
JB
1976{
1977 register char *value;
1978 char *name_key;
1979 char *class_key;
1980
11ae94fe
RS
1981 check_x ();
1982
01f1ba30 1983 CHECK_STRING (attribute, 0);
cf177271
JB
1984 CHECK_STRING (class, 0);
1985
8fabe6f4
RS
1986 if (!NILP (component))
1987 CHECK_STRING (component, 1);
1988 if (!NILP (subclass))
1989 CHECK_STRING (subclass, 2);
1990 if (NILP (component) != NILP (subclass))
1991 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
1992
d387c960
JB
1993 validate_x_resource_name ();
1994
b7975ee4
KH
1995 /* Allocate space for the components, the dots which separate them,
1996 and the final '\0'. Make them big enough for the worst case. */
1997 name_key = (char *) alloca (XSTRING (Vx_resource_name)->size
1998 + (STRINGP (component)
1999 ? XSTRING (component)->size : 0)
2000 + XSTRING (attribute)->size
2001 + 3);
2002
2003 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2004 + XSTRING (class)->size
2005 + (STRINGP (subclass)
2006 ? XSTRING (subclass)->size : 0)
2007 + 3);
2008
2009 /* Start with emacs.FRAMENAME for the name (the specific one)
2010 and with `Emacs' for the class key (the general one). */
2011 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2012 strcpy (class_key, EMACS_CLASS);
2013
2014 strcat (class_key, ".");
2015 strcat (class_key, XSTRING (class)->data);
2016
2017 if (!NILP (component))
01f1ba30 2018 {
b7975ee4
KH
2019 strcat (class_key, ".");
2020 strcat (class_key, XSTRING (subclass)->data);
2021
2022 strcat (name_key, ".");
2023 strcat (name_key, XSTRING (component)->data);
01f1ba30
JB
2024 }
2025
b7975ee4
KH
2026 strcat (name_key, ".");
2027 strcat (name_key, XSTRING (attribute)->data);
2028
b9dc4443
RS
2029 value = x_get_string_resource (check_x_display_info (Qnil)->xrdb,
2030 name_key, class_key);
01f1ba30
JB
2031
2032 if (value != (char *) 0)
2033 return build_string (value);
2034 else
2035 return Qnil;
2036}
2037
3402e1a4
RS
2038/* Used when C code wants a resource value. */
2039
2040char *
2041x_get_resource_string (attribute, class)
2042 char *attribute, *class;
2043{
2044 register char *value;
2045 char *name_key;
2046 char *class_key;
2047
2048 /* Allocate space for the components, the dots which separate them,
2049 and the final '\0'. */
2050 name_key = (char *) alloca (XSTRING (Vinvocation_name)->size
2051 + strlen (attribute) + 2);
2052 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2053 + strlen (class) + 2);
2054
2055 sprintf (name_key, "%s.%s",
2056 XSTRING (Vinvocation_name)->data,
2057 attribute);
2058 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
2059
b9dc4443
RS
2060 return x_get_string_resource (FRAME_X_DISPLAY_INFO (selected_frame)->xrdb,
2061 name_key, class_key);
3402e1a4
RS
2062}
2063
60fb3ee1
JB
2064/* Types we might convert a resource string into. */
2065enum resource_types
2066 {
f8f5a057 2067 number, boolean, string, symbol
60fb3ee1
JB
2068 };
2069
01f1ba30 2070/* Return the value of parameter PARAM.
60fb3ee1 2071
f676886a 2072 First search ALIST, then Vdefault_frame_alist, then the X defaults
cf177271 2073 database, using ATTRIBUTE as the attribute name and CLASS as its class.
60fb3ee1
JB
2074
2075 Convert the resource to the type specified by desired_type.
2076
f9942c9e
JB
2077 If no default is specified, return Qunbound. If you call
2078 x_get_arg, make sure you deal with Qunbound in a reasonable way,
a59e4f3d 2079 and don't let it get stored in any Lisp-visible variables! */
01f1ba30
JB
2080
2081static Lisp_Object
cf177271 2082x_get_arg (alist, param, attribute, class, type)
3c254570 2083 Lisp_Object alist, param;
60fb3ee1 2084 char *attribute;
cf177271 2085 char *class;
60fb3ee1 2086 enum resource_types type;
01f1ba30
JB
2087{
2088 register Lisp_Object tem;
2089
2090 tem = Fassq (param, alist);
2091 if (EQ (tem, Qnil))
f676886a 2092 tem = Fassq (param, Vdefault_frame_alist);
f9942c9e 2093 if (EQ (tem, Qnil))
01f1ba30 2094 {
60fb3ee1 2095
f9942c9e 2096 if (attribute)
60fb3ee1 2097 {
cf177271
JB
2098 tem = Fx_get_resource (build_string (attribute),
2099 build_string (class),
2100 Qnil, Qnil);
f9942c9e
JB
2101
2102 if (NILP (tem))
2103 return Qunbound;
2104
2105 switch (type)
2106 {
2107 case number:
2108 return make_number (atoi (XSTRING (tem)->data));
2109
2110 case boolean:
2111 tem = Fdowncase (tem);
2112 if (!strcmp (XSTRING (tem)->data, "on")
2113 || !strcmp (XSTRING (tem)->data, "true"))
2114 return Qt;
2115 else
2116 return Qnil;
2117
2118 case string:
2119 return tem;
2120
f945b920 2121 case symbol:
49795535
JB
2122 /* As a special case, we map the values `true' and `on'
2123 to Qt, and `false' and `off' to Qnil. */
2124 {
98381190
KH
2125 Lisp_Object lower;
2126 lower = Fdowncase (tem);
26ae6b61
KH
2127 if (!strcmp (XSTRING (lower)->data, "on")
2128 || !strcmp (XSTRING (lower)->data, "true"))
49795535 2129 return Qt;
26ae6b61
KH
2130 else if (!strcmp (XSTRING (lower)->data, "off")
2131 || !strcmp (XSTRING (lower)->data, "false"))
49795535
JB
2132 return Qnil;
2133 else
89032215 2134 return Fintern (tem, Qnil);
49795535 2135 }
f945b920 2136
f9942c9e
JB
2137 default:
2138 abort ();
2139 }
60fb3ee1 2140 }
f9942c9e
JB
2141 else
2142 return Qunbound;
01f1ba30
JB
2143 }
2144 return Fcdr (tem);
2145}
2146
f676886a 2147/* Record in frame F the specified or default value according to ALIST
01f1ba30
JB
2148 of the parameter named PARAM (a Lisp symbol).
2149 If no value is specified for PARAM, look for an X default for XPROP
f676886a 2150 on the frame named NAME.
01f1ba30
JB
2151 If that is not found either, use the value DEFLT. */
2152
2153static Lisp_Object
cf177271 2154x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
f676886a 2155 struct frame *f;
01f1ba30 2156 Lisp_Object alist;
f9942c9e 2157 Lisp_Object prop;
01f1ba30
JB
2158 Lisp_Object deflt;
2159 char *xprop;
cf177271 2160 char *xclass;
60fb3ee1 2161 enum resource_types type;
01f1ba30 2162{
01f1ba30
JB
2163 Lisp_Object tem;
2164
cf177271 2165 tem = x_get_arg (alist, prop, xprop, xclass, type);
f9942c9e 2166 if (EQ (tem, Qunbound))
01f1ba30 2167 tem = deflt;
f9942c9e 2168 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
01f1ba30
JB
2169 return tem;
2170}
2171\f
8af1d7ca 2172DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
01f1ba30 2173 "Parse an X-style geometry string STRING.\n\
f83f10ba
RS
2174Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2175The properties returned may include `top', `left', `height', and `width'.\n\
e1d962d7
RS
2176The value of `left' or `top' may be an integer,\n\
2177or a list (+ N) meaning N pixels relative to top/left corner,\n\
2178or a list (- N) meaning -N pixels relative to bottom/right corner.")
01f1ba30 2179 (string)
a6605e5c 2180 Lisp_Object string;
01f1ba30
JB
2181{
2182 int geometry, x, y;
2183 unsigned int width, height;
f83f10ba 2184 Lisp_Object result;
01f1ba30
JB
2185
2186 CHECK_STRING (string, 0);
2187
2188 geometry = XParseGeometry ((char *) XSTRING (string)->data,
2189 &x, &y, &width, &height);
2190
f83f10ba
RS
2191#if 0
2192 if (!!(geometry & XValue) != !!(geometry & YValue))
2193 error ("Must specify both x and y position, or neither");
2194#endif
2195
2196 result = Qnil;
2197 if (geometry & XValue)
01f1ba30 2198 {
f83f10ba
RS
2199 Lisp_Object element;
2200
e1d962d7
RS
2201 if (x >= 0 && (geometry & XNegative))
2202 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
2203 else if (x < 0 && ! (geometry & XNegative))
2204 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
f83f10ba
RS
2205 else
2206 element = Fcons (Qleft, make_number (x));
2207 result = Fcons (element, result);
2208 }
2209
2210 if (geometry & YValue)
2211 {
2212 Lisp_Object element;
2213
e1d962d7
RS
2214 if (y >= 0 && (geometry & YNegative))
2215 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
2216 else if (y < 0 && ! (geometry & YNegative))
2217 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
f83f10ba
RS
2218 else
2219 element = Fcons (Qtop, make_number (y));
2220 result = Fcons (element, result);
01f1ba30 2221 }
f83f10ba
RS
2222
2223 if (geometry & WidthValue)
2224 result = Fcons (Fcons (Qwidth, make_number (width)), result);
2225 if (geometry & HeightValue)
2226 result = Fcons (Fcons (Qheight, make_number (height)), result);
2227
2228 return result;
01f1ba30
JB
2229}
2230
01f1ba30 2231/* Calculate the desired size and position of this window,
f83f10ba 2232 and return the flags saying which aspects were specified.
8fc2766b
RS
2233
2234 This function does not make the coordinates positive. */
01f1ba30
JB
2235
2236#define DEFAULT_ROWS 40
2237#define DEFAULT_COLS 80
2238
f9942c9e 2239static int
f676886a
JB
2240x_figure_window_size (f, parms)
2241 struct frame *f;
01f1ba30
JB
2242 Lisp_Object parms;
2243{
4fe1de12 2244 register Lisp_Object tem0, tem1, tem2;
01f1ba30
JB
2245 int height, width, left, top;
2246 register int geometry;
2247 long window_prompting = 0;
2248
2249 /* Default values if we fall through.
2250 Actually, if that happens we should get
b9dc4443 2251 window manager prompting. */
f676886a
JB
2252 f->width = DEFAULT_COLS;
2253 f->height = DEFAULT_ROWS;
bd0b85c3
RS
2254 /* Window managers expect that if program-specified
2255 positions are not (0,0), they're intentional, not defaults. */
7556890b
RS
2256 f->output_data.x->top_pos = 0;
2257 f->output_data.x->left_pos = 0;
01f1ba30 2258
cf177271
JB
2259 tem0 = x_get_arg (parms, Qheight, 0, 0, number);
2260 tem1 = x_get_arg (parms, Qwidth, 0, 0, number);
4fe1de12 2261 tem2 = x_get_arg (parms, Quser_size, 0, 0, number);
f83f10ba 2262 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
01f1ba30 2263 {
f83f10ba
RS
2264 if (!EQ (tem0, Qunbound))
2265 {
2266 CHECK_NUMBER (tem0, 0);
2267 f->height = XINT (tem0);
2268 }
2269 if (!EQ (tem1, Qunbound))
2270 {
2271 CHECK_NUMBER (tem1, 0);
2272 f->width = XINT (tem1);
2273 }
2274 if (!NILP (tem2) && !EQ (tem2, Qunbound))
4fe1de12
RS
2275 window_prompting |= USSize;
2276 else
2277 window_prompting |= PSize;
01f1ba30 2278 }
01f1ba30 2279
7556890b 2280 f->output_data.x->vertical_scroll_bar_extra
a444c70b
KH
2281 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
2282 ? 0
2283 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
4701395c 2284 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
7556890b
RS
2285 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
2286 f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
2287 f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
01f1ba30 2288
cf177271
JB
2289 tem0 = x_get_arg (parms, Qtop, 0, 0, number);
2290 tem1 = x_get_arg (parms, Qleft, 0, 0, number);
4fe1de12 2291 tem2 = x_get_arg (parms, Quser_position, 0, 0, number);
f83f10ba 2292 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
01f1ba30 2293 {
f83f10ba
RS
2294 if (EQ (tem0, Qminus))
2295 {
7556890b 2296 f->output_data.x->top_pos = 0;
f83f10ba
RS
2297 window_prompting |= YNegative;
2298 }
e1d962d7
RS
2299 else if (CONSP (tem0) && EQ (XCONS (tem0)->car, Qminus)
2300 && CONSP (XCONS (tem0)->cdr)
2301 && INTEGERP (XCONS (XCONS (tem0)->cdr)->car))
2302 {
7556890b 2303 f->output_data.x->top_pos = - XINT (XCONS (XCONS (tem0)->cdr)->car);
e1d962d7
RS
2304 window_prompting |= YNegative;
2305 }
2306 else if (CONSP (tem0) && EQ (XCONS (tem0)->car, Qplus)
2307 && CONSP (XCONS (tem0)->cdr)
2308 && INTEGERP (XCONS (XCONS (tem0)->cdr)->car))
2309 {
7556890b 2310 f->output_data.x->top_pos = XINT (XCONS (XCONS (tem0)->cdr)->car);
e1d962d7 2311 }
f83f10ba 2312 else if (EQ (tem0, Qunbound))
7556890b 2313 f->output_data.x->top_pos = 0;
f83f10ba
RS
2314 else
2315 {
2316 CHECK_NUMBER (tem0, 0);
7556890b
RS
2317 f->output_data.x->top_pos = XINT (tem0);
2318 if (f->output_data.x->top_pos < 0)
f83f10ba
RS
2319 window_prompting |= YNegative;
2320 }
2321
2322 if (EQ (tem1, Qminus))
2323 {
7556890b 2324 f->output_data.x->left_pos = 0;
f83f10ba
RS
2325 window_prompting |= XNegative;
2326 }
e1d962d7
RS
2327 else if (CONSP (tem1) && EQ (XCONS (tem1)->car, Qminus)
2328 && CONSP (XCONS (tem1)->cdr)
2329 && INTEGERP (XCONS (XCONS (tem1)->cdr)->car))
2330 {
7556890b 2331 f->output_data.x->left_pos = - XINT (XCONS (XCONS (tem1)->cdr)->car);
e1d962d7
RS
2332 window_prompting |= XNegative;
2333 }
2334 else if (CONSP (tem1) && EQ (XCONS (tem1)->car, Qplus)
2335 && CONSP (XCONS (tem1)->cdr)
2336 && INTEGERP (XCONS (XCONS (tem1)->cdr)->car))
2337 {
7556890b 2338 f->output_data.x->left_pos = XINT (XCONS (XCONS (tem1)->cdr)->car);
e1d962d7 2339 }
f83f10ba 2340 else if (EQ (tem1, Qunbound))
7556890b 2341 f->output_data.x->left_pos = 0;
f83f10ba
RS
2342 else
2343 {
2344 CHECK_NUMBER (tem1, 0);
7556890b
RS
2345 f->output_data.x->left_pos = XINT (tem1);
2346 if (f->output_data.x->left_pos < 0)
f83f10ba
RS
2347 window_prompting |= XNegative;
2348 }
2349
c3724dc2 2350 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
4fe1de12
RS
2351 window_prompting |= USPosition;
2352 else
2353 window_prompting |= PPosition;
01f1ba30 2354 }
f83f10ba 2355
739f2f53 2356 return window_prompting;
01f1ba30
JB
2357}
2358
f58534a3
RS
2359#if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
2360
2361Status
2362XSetWMProtocols (dpy, w, protocols, count)
2363 Display *dpy;
2364 Window w;
2365 Atom *protocols;
2366 int count;
2367{
2368 Atom prop;
2369 prop = XInternAtom (dpy, "WM_PROTOCOLS", False);
2370 if (prop == None) return False;
2371 XChangeProperty (dpy, w, prop, XA_ATOM, 32, PropModeReplace,
2372 (unsigned char *) protocols, count);
2373 return True;
2374}
9ef48a9d
RS
2375#endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
2376\f
2377#ifdef USE_X_TOOLKIT
2378
8e3d10a9
RS
2379/* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
2380 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
59aa6c90
RS
2381 already be present because of the toolkit (Motif adds some of them,
2382 for example, but Xt doesn't). */
9ef48a9d
RS
2383
2384static void
b9dc4443
RS
2385hack_wm_protocols (f, widget)
2386 FRAME_PTR f;
9ef48a9d
RS
2387 Widget widget;
2388{
2389 Display *dpy = XtDisplay (widget);
2390 Window w = XtWindow (widget);
2391 int need_delete = 1;
2392 int need_focus = 1;
59aa6c90 2393 int need_save = 1;
9ef48a9d
RS
2394
2395 BLOCK_INPUT;
2396 {
2397 Atom type, *atoms = 0;
2398 int format = 0;
2399 unsigned long nitems = 0;
2400 unsigned long bytes_after;
2401
270958e8
KH
2402 if ((XGetWindowProperty (dpy, w,
2403 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
34d5ae1e 2404 (long)0, (long)100, False, XA_ATOM,
270958e8
KH
2405 &type, &format, &nitems, &bytes_after,
2406 (unsigned char **) &atoms)
2407 == Success)
9ef48a9d
RS
2408 && format == 32 && type == XA_ATOM)
2409 while (nitems > 0)
2410 {
2411 nitems--;
b9dc4443
RS
2412 if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
2413 need_delete = 0;
2414 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
2415 need_focus = 0;
2416 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
2417 need_save = 0;
9ef48a9d
RS
2418 }
2419 if (atoms) XFree ((char *) atoms);
2420 }
2421 {
2422 Atom props [10];
2423 int count = 0;
b9dc4443
RS
2424 if (need_delete)
2425 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
2426 if (need_focus)
2427 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus;
2428 if (need_save)
2429 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
9ef48a9d 2430 if (count)
b9dc4443
RS
2431 XChangeProperty (dpy, w, FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
2432 XA_ATOM, 32, PropModeAppend,
9ef48a9d
RS
2433 (unsigned char *) props, count);
2434 }
2435 UNBLOCK_INPUT;
2436}
2437#endif
2438\f
8fc2766b
RS
2439#ifdef USE_X_TOOLKIT
2440
2441/* Create and set up the X widget for frame F. */
f58534a3 2442
01f1ba30 2443static void
a7f7d550
FP
2444x_window (f, window_prompting, minibuffer_only)
2445 struct frame *f;
2446 long window_prompting;
2447 int minibuffer_only;
01f1ba30 2448{
9ef48a9d 2449 XClassHint class_hints;
31ac8d8c
FP
2450 XSetWindowAttributes attributes;
2451 unsigned long attribute_mask;
9ef48a9d 2452
9ef48a9d
RS
2453 Widget shell_widget;
2454 Widget pane_widget;
6c32dd68 2455 Widget frame_widget;
9ef48a9d
RS
2456 Arg al [25];
2457 int ac;
2458
2459 BLOCK_INPUT;
2460
b7975ee4
KH
2461 /* Use the resource name as the top-level widget name
2462 for looking up resources. Make a non-Lisp copy
2463 for the window manager, so GC relocation won't bother it.
2464
2465 Elsewhere we specify the window name for the window manager. */
2466
cca176a0 2467 {
b7975ee4
KH
2468 char *str = (char *) XSTRING (Vx_resource_name)->data;
2469 f->namebuf = (char *) xmalloc (strlen (str) + 1);
cca176a0
KH
2470 strcpy (f->namebuf, str);
2471 }
9ef48a9d
RS
2472
2473 ac = 0;
2474 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
2475 XtSetArg (al[ac], XtNinput, 1); ac++;
97787173 2476 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
7556890b 2477 XtSetArg (al[ac], XtNborderWidth, f->output_data.x->border_width); ac++;
cca176a0 2478 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
7a994728 2479 applicationShellWidgetClass,
82c90203 2480 FRAME_X_DISPLAY (f), al, ac);
9ef48a9d 2481
7556890b 2482 f->output_data.x->widget = shell_widget;
9ef48a9d
RS
2483 /* maybe_set_screen_title_format (shell_widget); */
2484
6c32dd68
PR
2485 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
2486 (widget_value *) NULL,
2487 shell_widget, False,
2488 (lw_callback) NULL,
2489 (lw_callback) NULL,
2490 (lw_callback) NULL);
9ef48a9d 2491
7556890b 2492 f->output_data.x->column_widget = pane_widget;
a7f7d550 2493
9ef48a9d 2494 /* mappedWhenManaged to false tells to the paned window to not map/unmap
5e65b9ab 2495 the emacs screen when changing menubar. This reduces flickering. */
9ef48a9d
RS
2496
2497 ac = 0;
2498 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
2499 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
2500 XtSetArg (al[ac], XtNallowResize, 1); ac++;
2501 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
2502 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
cca176a0 2503 frame_widget = XtCreateWidget (f->namebuf,
9ef48a9d
RS
2504 emacsFrameClass,
2505 pane_widget, al, ac);
2506
7556890b 2507 f->output_data.x->edit_widget = frame_widget;
9ef48a9d 2508
6c32dd68 2509 XtManageChild (frame_widget);
a7f7d550
FP
2510
2511 /* Do some needed geometry management. */
2512 {
2513 int len;
2514 char *tem, shell_position[32];
2515 Arg al[2];
2516 int ac = 0;
5031cc10 2517 int extra_borders = 0;
8fc2766b 2518 int menubar_size
7556890b
RS
2519 = (f->output_data.x->menubar_widget
2520 ? (f->output_data.x->menubar_widget->core.height
2521 + f->output_data.x->menubar_widget->core.border_width)
8fc2766b 2522 : 0);
5031cc10 2523 extern char *lwlib_toolkit_type;
a7f7d550 2524
01cbdba5
RS
2525 if (FRAME_EXTERNAL_MENU_BAR (f))
2526 {
dd254b21 2527 Dimension ibw = 0;
01cbdba5
RS
2528 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
2529 menubar_size += ibw;
2530 }
2531
7556890b 2532 f->output_data.x->menubar_height = menubar_size;
00983aba 2533
5031cc10
KH
2534 /* Motif seems to need this amount added to the sizes
2535 specified for the shell widget. The Athena/Lucid widgets don't.
2536 Both conclusions reached experimentally. -- rms. */
2537 if (!strcmp (lwlib_toolkit_type, "motif"))
7556890b 2538 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
5031cc10
KH
2539 &extra_borders, NULL);
2540
97787173
RS
2541 /* Convert our geometry parameters into a geometry string
2542 and specify it.
2543 Note that we do not specify here whether the position
2544 is a user-specified or program-specified one.
2545 We pass that information later, in x_wm_set_size_hints. */
2546 {
7556890b 2547 int left = f->output_data.x->left_pos;
97787173 2548 int xneg = window_prompting & XNegative;
7556890b 2549 int top = f->output_data.x->top_pos;
97787173
RS
2550 int yneg = window_prompting & YNegative;
2551 if (xneg)
2552 left = -left;
2553 if (yneg)
2554 top = -top;
c760f47e
KH
2555
2556 if (window_prompting & USPosition)
5031cc10
KH
2557 sprintf (shell_position, "=%dx%d%c%d%c%d",
2558 PIXEL_WIDTH (f) + extra_borders,
2559 PIXEL_HEIGHT (f) + menubar_size + extra_borders,
c760f47e
KH
2560 (xneg ? '-' : '+'), left,
2561 (yneg ? '-' : '+'), top);
2562 else
5031cc10
KH
2563 sprintf (shell_position, "=%dx%d",
2564 PIXEL_WIDTH (f) + extra_borders,
2565 PIXEL_HEIGHT (f) + menubar_size + extra_borders);
97787173
RS
2566 }
2567
a7f7d550
FP
2568 len = strlen (shell_position) + 1;
2569 tem = (char *) xmalloc (len);
2570 strncpy (tem, shell_position, len);
2571 XtSetArg (al[ac], XtNgeometry, tem); ac++;
2572 XtSetValues (shell_widget, al, ac);
2573 }
2574
9ef48a9d
RS
2575 XtManageChild (pane_widget);
2576 XtRealizeWidget (shell_widget);
2577
6c32dd68 2578 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
9ef48a9d
RS
2579
2580 validate_x_resource_name ();
b7975ee4 2581
9ef48a9d
RS
2582 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
2583 class_hints.res_class = EMACS_CLASS;
b9dc4443 2584 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
9ef48a9d 2585
64d16748
RS
2586#ifdef HAVE_X_I18N
2587 {
2588 XIM xim;
2589 XIC xic = NULL;
2590
2591 xim = XOpenIM (FRAME_X_DISPLAY (f), NULL, NULL, NULL);
2592
2593 if (xim)
2594 {
2595 xic = XCreateIC (xim,
2596 XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
2597 XNClientWindow, FRAME_X_WINDOW(f),
2598 XNFocusWindow, FRAME_X_WINDOW(f),
2599 NULL);
2600
2601 if (xic == 0)
2602 XCloseIM (xim);
2603 }
2604 FRAME_XIC (f) = xic;
2605 }
2606#endif
2607
7556890b
RS
2608 f->output_data.x->wm_hints.input = True;
2609 f->output_data.x->wm_hints.flags |= InputHint;
b9dc4443 2610 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 2611 &f->output_data.x->wm_hints);
b8228beb 2612
c4ec904f 2613 hack_wm_protocols (f, shell_widget);
9ef48a9d 2614
6c32dd68
PR
2615#ifdef HACK_EDITRES
2616 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
2617#endif
2618
9ef48a9d
RS
2619 /* Do a stupid property change to force the server to generate a
2620 propertyNotify event so that the event_stream server timestamp will
2621 be initialized to something relevant to the time we created the window.
2622 */
6c32dd68 2623 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
b9dc4443
RS
2624 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
2625 XA_ATOM, 32, PropModeAppend,
9ef48a9d
RS
2626 (unsigned char*) NULL, 0);
2627
31ac8d8c
FP
2628 /* Make all the standard events reach the Emacs frame. */
2629 attributes.event_mask = STANDARD_EVENT_SET;
2630 attribute_mask = CWEventMask;
2631 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
2632 attribute_mask, &attributes);
2633
6c32dd68 2634 XtMapWidget (frame_widget);
9ef48a9d 2635
8fc2766b
RS
2636 /* x_set_name normally ignores requests to set the name if the
2637 requested name is the same as the current name. This is the one
2638 place where that assumption isn't correct; f->name is set, but
2639 the X server hasn't been told. */
2640 {
2641 Lisp_Object name;
2642 int explicit = f->explicit_name;
2643
2644 f->explicit_name = 0;
2645 name = f->name;
2646 f->name = Qnil;
2647 x_set_name (f, name, explicit);
2648 }
2649
b9dc4443 2650 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 2651 f->output_data.x->text_cursor);
8fc2766b
RS
2652
2653 UNBLOCK_INPUT;
2654
422fbe5f
KH
2655 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
2656 initialize_frame_menubar (f);
7556890b 2657 lw_set_main_areas (pane_widget, f->output_data.x->menubar_widget, frame_widget);
422fbe5f 2658
8fc2766b
RS
2659 if (FRAME_X_WINDOW (f) == 0)
2660 error ("Unable to create window");
2661}
2662
9ef48a9d
RS
2663#else /* not USE_X_TOOLKIT */
2664
8fc2766b
RS
2665/* Create and set up the X window for frame F. */
2666
2667x_window (f)
2668 struct frame *f;
2669
2670{
2671 XClassHint class_hints;
2672 XSetWindowAttributes attributes;
2673 unsigned long attribute_mask;
2674
7556890b
RS
2675 attributes.background_pixel = f->output_data.x->background_pixel;
2676 attributes.border_pixel = f->output_data.x->border_pixel;
01f1ba30
JB
2677 attributes.bit_gravity = StaticGravity;
2678 attributes.backing_store = NotUseful;
2679 attributes.save_under = True;
2680 attributes.event_mask = STANDARD_EVENT_SET;
2681 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity
2682#if 0
2683 | CWBackingStore | CWSaveUnder
2684#endif
2685 | CWEventMask);
2686
2687 BLOCK_INPUT;
fe24a618 2688 FRAME_X_WINDOW (f)
b9dc4443 2689 = XCreateWindow (FRAME_X_DISPLAY (f),
7556890b
RS
2690 f->output_data.x->parent_desc,
2691 f->output_data.x->left_pos,
2692 f->output_data.x->top_pos,
f676886a 2693 PIXEL_WIDTH (f), PIXEL_HEIGHT (f),
7556890b 2694 f->output_data.x->border_width,
01f1ba30
JB
2695 CopyFromParent, /* depth */
2696 InputOutput, /* class */
b9dc4443 2697 FRAME_X_DISPLAY_INFO (f)->visual,
01f1ba30 2698 attribute_mask, &attributes);
64d16748
RS
2699#ifdef HAVE_X_I18N
2700 {
2701 XIM xim;
2702 XIC xic = NULL;
2703
2704 xim = XOpenIM (FRAME_X_DISPLAY(f), NULL, NULL, NULL);
2705
2706 if (xim)
2707 {
2708 xic = XCreateIC (xim,
2709 XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
2710 XNClientWindow, FRAME_X_WINDOW(f),
2711 XNFocusWindow, FRAME_X_WINDOW(f),
2712 NULL);
2713
2714 if (!xic)
2715 XCloseIM (xim);
2716 }
2717
2718 FRAME_XIC (f) = xic;
2719 }
2720#endif
01f1ba30 2721
d387c960 2722 validate_x_resource_name ();
b7975ee4 2723
d387c960 2724 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
01f1ba30 2725 class_hints.res_class = EMACS_CLASS;
b9dc4443 2726 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
01f1ba30 2727
00983aba
KH
2728 /* The menubar is part of the ordinary display;
2729 it does not count in addition to the height of the window. */
7556890b 2730 f->output_data.x->menubar_height = 0;
00983aba 2731
179956b9
JB
2732 /* This indicates that we use the "Passive Input" input model.
2733 Unless we do this, we don't get the Focus{In,Out} events that we
2734 need to draw the cursor correctly. Accursed bureaucrats.
b9dc4443 2735 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
179956b9 2736
7556890b
RS
2737 f->output_data.x->wm_hints.input = True;
2738 f->output_data.x->wm_hints.flags |= InputHint;
b9dc4443 2739 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 2740 &f->output_data.x->wm_hints);
179956b9 2741
032e4ebe
RS
2742 /* Request "save yourself" and "delete window" commands from wm. */
2743 {
2744 Atom protocols[2];
b9dc4443
RS
2745 protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
2746 protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
2747 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
032e4ebe 2748 }
9ef48a9d 2749
e373f201
JB
2750 /* x_set_name normally ignores requests to set the name if the
2751 requested name is the same as the current name. This is the one
2752 place where that assumption isn't correct; f->name is set, but
2753 the X server hasn't been told. */
2754 {
98381190 2755 Lisp_Object name;
cf177271 2756 int explicit = f->explicit_name;
e373f201 2757
cf177271 2758 f->explicit_name = 0;
98381190
KH
2759 name = f->name;
2760 f->name = Qnil;
cf177271 2761 x_set_name (f, name, explicit);
e373f201
JB
2762 }
2763
b9dc4443 2764 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 2765 f->output_data.x->text_cursor);
9ef48a9d 2766
01f1ba30
JB
2767 UNBLOCK_INPUT;
2768
fe24a618 2769 if (FRAME_X_WINDOW (f) == 0)
9ef48a9d 2770 error ("Unable to create window");
01f1ba30
JB
2771}
2772
8fc2766b
RS
2773#endif /* not USE_X_TOOLKIT */
2774
01f1ba30
JB
2775/* Handle the icon stuff for this window. Perhaps later we might
2776 want an x_set_icon_position which can be called interactively as
b9dc4443 2777 well. */
01f1ba30
JB
2778
2779static void
f676886a
JB
2780x_icon (f, parms)
2781 struct frame *f;
01f1ba30
JB
2782 Lisp_Object parms;
2783{
f9942c9e 2784 Lisp_Object icon_x, icon_y;
01f1ba30
JB
2785
2786 /* Set the position of the icon. Note that twm groups all
b9dc4443 2787 icons in an icon window. */
cf177271
JB
2788 icon_x = x_get_arg (parms, Qicon_left, 0, 0, number);
2789 icon_y = x_get_arg (parms, Qicon_top, 0, 0, number);
f9942c9e 2790 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
01f1ba30 2791 {
f9942c9e
JB
2792 CHECK_NUMBER (icon_x, 0);
2793 CHECK_NUMBER (icon_y, 0);
01f1ba30 2794 }
f9942c9e 2795 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
01f1ba30 2796 error ("Both left and top icon corners of icon must be specified");
01f1ba30 2797
f9942c9e
JB
2798 BLOCK_INPUT;
2799
fe24a618
JB
2800 if (! EQ (icon_x, Qunbound))
2801 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
f9942c9e 2802
01f1ba30 2803 /* Start up iconic or window? */
49795535
JB
2804 x_wm_set_window_state
2805 (f, (EQ (x_get_arg (parms, Qvisibility, 0, 0, symbol), Qicon)
2806 ? IconicState
2807 : NormalState));
01f1ba30 2808
f468da95
RS
2809 x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
2810 ? f->icon_name
2811 : f->name))->data);
80534dd6 2812
01f1ba30
JB
2813 UNBLOCK_INPUT;
2814}
2815
2816/* Make the GC's needed for this window, setting the
2817 background, border and mouse colors; also create the
2818 mouse cursor and the gray border tile. */
2819
f945b920
JB
2820static char cursor_bits[] =
2821 {
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2826 };
2827
01f1ba30 2828static void
f676886a
JB
2829x_make_gc (f)
2830 struct frame *f;
01f1ba30
JB
2831{
2832 XGCValues gc_values;
2833 GC temp_gc;
2834 XImage tileimage;
01f1ba30 2835
6afb1d07
JB
2836 BLOCK_INPUT;
2837
f676886a 2838 /* Create the GC's of this frame.
9ef48a9d 2839 Note that many default values are used. */
01f1ba30
JB
2840
2841 /* Normal video */
7556890b
RS
2842 gc_values.font = f->output_data.x->font->fid;
2843 gc_values.foreground = f->output_data.x->foreground_pixel;
2844 gc_values.background = f->output_data.x->background_pixel;
9ef48a9d 2845 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
7556890b 2846 f->output_data.x->normal_gc = XCreateGC (FRAME_X_DISPLAY (f),
fe24a618 2847 FRAME_X_WINDOW (f),
01f1ba30
JB
2848 GCLineWidth | GCFont
2849 | GCForeground | GCBackground,
2850 &gc_values);
2851
b9dc4443 2852 /* Reverse video style. */
7556890b
RS
2853 gc_values.foreground = f->output_data.x->background_pixel;
2854 gc_values.background = f->output_data.x->foreground_pixel;
2855 f->output_data.x->reverse_gc = XCreateGC (FRAME_X_DISPLAY (f),
fe24a618 2856 FRAME_X_WINDOW (f),
01f1ba30
JB
2857 GCFont | GCForeground | GCBackground
2858 | GCLineWidth,
2859 &gc_values);
2860
9ef48a9d 2861 /* Cursor has cursor-color background, background-color foreground. */
7556890b
RS
2862 gc_values.foreground = f->output_data.x->background_pixel;
2863 gc_values.background = f->output_data.x->cursor_pixel;
01f1ba30
JB
2864 gc_values.fill_style = FillOpaqueStippled;
2865 gc_values.stipple
b9dc4443
RS
2866 = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
2867 FRAME_X_DISPLAY_INFO (f)->root_window,
01f1ba30 2868 cursor_bits, 16, 16);
7556890b 2869 f->output_data.x->cursor_gc
b9dc4443 2870 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
01f1ba30
JB
2871 (GCFont | GCForeground | GCBackground
2872 | GCFillStyle | GCStipple | GCLineWidth),
2873 &gc_values);
2874
2875 /* Create the gray border tile used when the pointer is not in
f676886a 2876 the frame. Since this depends on the frame's pixel values,
9ef48a9d 2877 this must be done on a per-frame basis. */
7556890b 2878 f->output_data.x->border_tile
d043f1a4 2879 = (XCreatePixmapFromBitmapData
b9dc4443 2880 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
d043f1a4 2881 gray_bits, gray_width, gray_height,
7556890b
RS
2882 f->output_data.x->foreground_pixel,
2883 f->output_data.x->background_pixel,
b9dc4443
RS
2884 DefaultDepth (FRAME_X_DISPLAY (f),
2885 XScreenNumberOfScreen (FRAME_X_SCREEN (f)))));
6afb1d07
JB
2886
2887 UNBLOCK_INPUT;
01f1ba30 2888}
01f1ba30 2889
f676886a 2890DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
01f1ba30 2891 1, 1, 0,
f676886a 2892 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
08a90d6a 2893Returns an Emacs frame object.\n\
f676886a
JB
2894ALIST is an alist of frame parameters.\n\
2895If the parameters specify that the frame should not have a minibuffer,\n\
e22d6b02 2896and do not specify a specific minibuffer window to use,\n\
f676886a 2897then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
08a90d6a
RS
2898be shared by the new frame.\n\
2899\n\
2900This function is an internal primitive--use `make-frame' instead.")
01f1ba30
JB
2901 (parms)
2902 Lisp_Object parms;
2903{
f676886a 2904 struct frame *f;
2365c027 2905 Lisp_Object frame, tem;
01f1ba30
JB
2906 Lisp_Object name;
2907 int minibuffer_only = 0;
2908 long window_prompting = 0;
2909 int width, height;
9ef48a9d 2910 int count = specpdl_ptr - specpdl;
f8ea8499 2911 struct gcpro gcpro1;
b9dc4443
RS
2912 Lisp_Object display;
2913 struct x_display_info *dpyinfo;
a59e4f3d 2914 Lisp_Object parent;
e557f19d 2915 struct kboard *kb;
01f1ba30 2916
11ae94fe 2917 check_x ();
01f1ba30 2918
b7975ee4
KH
2919 /* Use this general default value to start with
2920 until we know if this frame has a specified name. */
2921 Vx_resource_name = Vinvocation_name;
2922
714812eb 2923 display = x_get_arg (parms, Qdisplay, 0, 0, string);
b9dc4443
RS
2924 if (EQ (display, Qunbound))
2925 display = Qnil;
2926 dpyinfo = check_x_display_info (display);
e557f19d
KH
2927#ifdef MULTI_KBOARD
2928 kb = dpyinfo->kboard;
2929#else
2930 kb = &the_only_kboard;
2931#endif
b9dc4443 2932
cf177271 2933 name = x_get_arg (parms, Qname, "title", "Title", string);
6a5e54e2 2934 if (!STRINGP (name)
cf177271
JB
2935 && ! EQ (name, Qunbound)
2936 && ! NILP (name))
08a90d6a 2937 error ("Invalid frame name--not a string or nil");
01f1ba30 2938
b7975ee4
KH
2939 if (STRINGP (name))
2940 Vx_resource_name = name;
2941
a59e4f3d
RS
2942 /* See if parent window is specified. */
2943 parent = x_get_arg (parms, Qparent_id, NULL, NULL, number);
2944 if (EQ (parent, Qunbound))
2945 parent = Qnil;
2946 if (! NILP (parent))
2947 CHECK_NUMBER (parent, 0);
2948
cf177271 2949 tem = x_get_arg (parms, Qminibuffer, 0, 0, symbol);
f9942c9e 2950 if (EQ (tem, Qnone) || NILP (tem))
2526c290 2951 f = make_frame_without_minibuffer (Qnil, kb, display);
f9942c9e 2952 else if (EQ (tem, Qonly))
01f1ba30 2953 {
f676886a 2954 f = make_minibuffer_frame ();
01f1ba30
JB
2955 minibuffer_only = 1;
2956 }
6a5e54e2 2957 else if (WINDOWP (tem))
2526c290 2958 f = make_frame_without_minibuffer (tem, kb, display);
f9942c9e
JB
2959 else
2960 f = make_frame (1);
01f1ba30 2961
a3c87d4e
JB
2962 /* Note that X Windows does support scroll bars. */
2963 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
179956b9 2964
08a90d6a
RS
2965 XSETFRAME (frame, f);
2966 GCPRO1 (frame);
2967
2968 f->output_method = output_x_window;
7556890b
RS
2969 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
2970 bzero (f->output_data.x, sizeof (struct x_output));
2971 f->output_data.x->icon_bitmap = -1;
08a90d6a 2972
f468da95 2973 f->icon_name
80534dd6 2974 = x_get_arg (parms, Qicon_name, "iconName", "Title", string);
f468da95
RS
2975 if (! STRINGP (f->icon_name))
2976 f->icon_name = Qnil;
80534dd6 2977
08a90d6a 2978 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
73410c76 2979#ifdef MULTI_KBOARD
e557f19d 2980 FRAME_KBOARD (f) = kb;
73410c76 2981#endif
08a90d6a 2982
a59e4f3d
RS
2983 /* Specify the parent under which to make this X window. */
2984
2985 if (!NILP (parent))
2986 {
7556890b
RS
2987 f->output_data.x->parent_desc = parent;
2988 f->output_data.x->explicit_parent = 1;
a59e4f3d
RS
2989 }
2990 else
2991 {
7556890b
RS
2992 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
2993 f->output_data.x->explicit_parent = 0;
a59e4f3d
RS
2994 }
2995
08a90d6a
RS
2996 /* Note that the frame has no physical cursor right now. */
2997 f->phys_cursor_x = -1;
2998
cf177271
JB
2999 /* Set the name; the functions to which we pass f expect the name to
3000 be set. */
3001 if (EQ (name, Qunbound) || NILP (name))
3002 {
08a90d6a 3003 f->name = build_string (dpyinfo->x_id_name);
cf177271
JB
3004 f->explicit_name = 0;
3005 }
3006 else
3007 {
3008 f->name = name;
3009 f->explicit_name = 1;
9ef48a9d
RS
3010 /* use the frame's title when getting resources for this frame. */
3011 specbind (Qx_resource_name, name);
cf177271 3012 }
01f1ba30 3013
01f1ba30
JB
3014 /* Extract the window parameters from the supplied values
3015 that are needed to determine window geometry. */
d387c960
JB
3016 {
3017 Lisp_Object font;
3018
e5e548e3 3019 font = x_get_arg (parms, Qfont, "font", "Font", string);
6817eab4 3020 BLOCK_INPUT;
e5e548e3
RS
3021 /* First, try whatever font the caller has specified. */
3022 if (STRINGP (font))
e5229110 3023 font = x_new_font (f, XSTRING (font)->data);
e5e548e3
RS
3024 /* Try out a font which we hope has bold and italic variations. */
3025 if (!STRINGP (font))
a6ac02af 3026 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
e5e548e3 3027 if (! STRINGP (font))
a6ac02af 3028 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
e5e548e3
RS
3029 if (! STRINGP (font))
3030 /* This was formerly the first thing tried, but it finds too many fonts
3031 and takes too long. */
3032 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
3033 /* If those didn't work, look for something which will at least work. */
3034 if (! STRINGP (font))
a6ac02af 3035 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
6817eab4
JB
3036 UNBLOCK_INPUT;
3037 if (! STRINGP (font))
e5e548e3
RS
3038 font = build_string ("fixed");
3039
d387c960
JB
3040 x_default_parameter (f, parms, Qfont, font,
3041 "font", "Font", string);
3042 }
9ef48a9d 3043
dd254b21 3044#ifdef USE_X_TOOLKIT
82c90203
RS
3045 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
3046 whereby it fails to get any font. */
7556890b 3047 xlwmenu_default_font = f->output_data.x->font;
dd254b21 3048#endif
82c90203 3049
cf177271
JB
3050 x_default_parameter (f, parms, Qborder_width, make_number (2),
3051 "borderwidth", "BorderWidth", number);
ddf768c3
JB
3052 /* This defaults to 2 in order to match xterm. We recognize either
3053 internalBorderWidth or internalBorder (which is what xterm calls
3054 it). */
3055 if (NILP (Fassq (Qinternal_border_width, parms)))
3056 {
3057 Lisp_Object value;
3058
3059 value = x_get_arg (parms, Qinternal_border_width,
3060 "internalBorder", "BorderWidth", number);
3061 if (! EQ (value, Qunbound))
3062 parms = Fcons (Fcons (Qinternal_border_width, value),
3063 parms);
3064 }
cf177271
JB
3065 x_default_parameter (f, parms, Qinternal_border_width, make_number (2),
3066 "internalBorderWidth", "BorderWidth", number);
a3c87d4e
JB
3067 x_default_parameter (f, parms, Qvertical_scroll_bars, Qt,
3068 "verticalScrollBars", "ScrollBars", boolean);
01f1ba30 3069
b9dc4443 3070 /* Also do the stuff which must be set before the window exists. */
cf177271
JB
3071 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
3072 "foreground", "Foreground", string);
3073 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
3074 "background", "Background", string);
3075 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
3076 "pointerColor", "Foreground", string);
3077 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
3078 "cursorColor", "Foreground", string);
3079 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
3080 "borderColor", "BorderColor", string);
01f1ba30 3081
c7bcb20d 3082 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
e1d962d7 3083 "menuBar", "MenuBar", number);
dff9a538 3084 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
4701395c 3085 "scrollBarWidth", "ScrollBarWidth", number);
79873d50
RS
3086 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
3087 "bufferPredicate", "BufferPredicate", symbol);
90eb1019 3088
7556890b 3089 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
f676886a 3090 window_prompting = x_figure_window_size (f, parms);
01f1ba30 3091
f83f10ba 3092 if (window_prompting & XNegative)
2365c027 3093 {
f83f10ba 3094 if (window_prompting & YNegative)
7556890b 3095 f->output_data.x->win_gravity = SouthEastGravity;
f83f10ba 3096 else
7556890b 3097 f->output_data.x->win_gravity = NorthEastGravity;
f83f10ba
RS
3098 }
3099 else
3100 {
3101 if (window_prompting & YNegative)
7556890b 3102 f->output_data.x->win_gravity = SouthWestGravity;
f83f10ba 3103 else
7556890b 3104 f->output_data.x->win_gravity = NorthWestGravity;
2365c027
RS
3105 }
3106
7556890b 3107 f->output_data.x->size_hint_flags = window_prompting;
38d22040 3108
a7f7d550
FP
3109#ifdef USE_X_TOOLKIT
3110 x_window (f, window_prompting, minibuffer_only);
3111#else
f676886a 3112 x_window (f);
a7f7d550 3113#endif
f676886a
JB
3114 x_icon (f, parms);
3115 x_make_gc (f);
ea96210c 3116 init_frame_faces (f);
01f1ba30 3117
f9942c9e
JB
3118 /* We need to do this after creating the X window, so that the
3119 icon-creation functions can say whose icon they're describing. */
cf177271 3120 x_default_parameter (f, parms, Qicon_type, Qnil,
6998a3b4 3121 "bitmapIcon", "BitmapIcon", symbol);
f9942c9e 3122
cf177271
JB
3123 x_default_parameter (f, parms, Qauto_raise, Qnil,
3124 "autoRaise", "AutoRaiseLower", boolean);
3125 x_default_parameter (f, parms, Qauto_lower, Qnil,
3126 "autoLower", "AutoRaiseLower", boolean);
dbc4e1c1
JB
3127 x_default_parameter (f, parms, Qcursor_type, Qbox,
3128 "cursorType", "CursorType", symbol);
f9942c9e 3129
f676886a 3130 /* Dimensions, especially f->height, must be done via change_frame_size.
01f1ba30 3131 Change will not be effected unless different from the current
b9dc4443 3132 f->height. */
f676886a
JB
3133 width = f->width;
3134 height = f->height;
3135 f->height = f->width = 0;
f9942c9e 3136 change_frame_size (f, height, width, 1, 0);
d043f1a4 3137
97787173
RS
3138 /* Tell the server what size and position, etc, we want,
3139 and how badly we want them. */
01f1ba30 3140 BLOCK_INPUT;
7989f084 3141 x_wm_set_size_hint (f, window_prompting, 0);
01f1ba30
JB
3142 UNBLOCK_INPUT;
3143
cf177271 3144 tem = x_get_arg (parms, Qunsplittable, 0, 0, boolean);
f676886a 3145 f->no_split = minibuffer_only || EQ (tem, Qt);
01f1ba30 3146
f8ea8499
PR
3147 UNGCPRO;
3148
59d61058
RS
3149 /* It is now ok to make the frame official
3150 even if we get an error below.
3151 And the frame needs to be on Vframe_list
3152 or making it visible won't work. */
3153 Vframe_list = Fcons (frame, Vframe_list);
3154
08a90d6a
RS
3155 /* Now that the frame is official, it counts as a reference to
3156 its display. */
3157 FRAME_X_DISPLAY_INFO (f)->reference_count++;
3158
d043f1a4 3159 /* Make the window appear on the frame and enable display,
a59e4f3d
RS
3160 unless the caller says not to. However, with explicit parent,
3161 Emacs cannot control visibility, so don't try. */
7556890b 3162 if (! f->output_data.x->explicit_parent)
a59e4f3d
RS
3163 {
3164 Lisp_Object visibility;
49795535 3165
a59e4f3d
RS
3166 visibility = x_get_arg (parms, Qvisibility, 0, 0, symbol);
3167 if (EQ (visibility, Qunbound))
3168 visibility = Qt;
49795535 3169
a59e4f3d
RS
3170 if (EQ (visibility, Qicon))
3171 x_iconify_frame (f);
3172 else if (! NILP (visibility))
3173 x_make_frame_visible (f);
3174 else
3175 /* Must have been Qnil. */
3176 ;
3177 }
01f1ba30 3178
9ef48a9d 3179 return unbind_to (count, frame);
01f1ba30
JB
3180}
3181
0d17d282
KH
3182/* FRAME is used only to get a handle on the X display. We don't pass the
3183 display info directly because we're called from frame.c, which doesn't
3184 know about that structure. */
87498171 3185Lisp_Object
0d17d282
KH
3186x_get_focus_frame (frame)
3187 struct frame *frame;
87498171 3188{
0d17d282 3189 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
87498171 3190 Lisp_Object xfocus;
0d17d282 3191 if (! dpyinfo->x_focus_frame)
87498171
KH
3192 return Qnil;
3193
0d17d282 3194 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
87498171
KH
3195 return xfocus;
3196}
3197
f676886a 3198DEFUN ("focus-frame", Ffocus_frame, Sfocus_frame, 1, 1, 0,
9ae77b81 3199 "This function is obsolete, and does nothing.")
f676886a
JB
3200 (frame)
3201 Lisp_Object frame;
01f1ba30 3202{
01f1ba30
JB
3203 return Qnil;
3204}
3205
f676886a 3206DEFUN ("unfocus-frame", Funfocus_frame, Sunfocus_frame, 0, 0, 0,
9ae77b81 3207 "This function is obsolete, and does nothing.")
01f1ba30
JB
3208 ()
3209{
01f1ba30
JB
3210 return Qnil;
3211}
3212\f
f0614854
JB
3213DEFUN ("x-list-fonts", Fx_list_fonts, Sx_list_fonts, 1, 3, 0,
3214 "Return a list of the names of available fonts matching PATTERN.\n\
3215If optional arguments FACE and FRAME are specified, return only fonts\n\
3216the same size as FACE on FRAME.\n\
3217\n\
3218PATTERN is a string, perhaps with wildcard characters;\n\
3219 the * character matches any substring, and\n\
3220 the ? character matches any single character.\n\
3221 PATTERN is case-insensitive.\n\
08a90d6a 3222FACE is a face name--a symbol.\n\
f0614854
JB
3223\n\
3224The return value is a list of strings, suitable as arguments to\n\
3225set-face-font.\n\
3226\n\
410d4321
RS
3227Fonts Emacs can't use (i.e. proportional fonts) may or may not be excluded\n\
3228even if they match PATTERN and FACE.")
f0614854
JB
3229 (pattern, face, frame)
3230 Lisp_Object pattern, face, frame;
3231{
3232 int num_fonts;
3233 char **names;
40a5b2e1 3234#ifndef BROKEN_XLISTFONTSWITHINFO
f0614854 3235 XFontStruct *info;
40a5b2e1 3236#endif
f0614854
JB
3237 XFontStruct *size_ref;
3238 Lisp_Object list;
f1c16f36 3239 FRAME_PTR f;
f0614854 3240
7fc9de26 3241 check_x ();
f0614854
JB
3242 CHECK_STRING (pattern, 0);
3243 if (!NILP (face))
3244 CHECK_SYMBOL (face, 1);
f0614854 3245
b9dc4443 3246 f = check_x_frame (frame);
f1c16f36
RS
3247
3248 /* Determine the width standard for comparison with the fonts we find. */
3249
f0614854
JB
3250 if (NILP (face))
3251 size_ref = 0;
3252 else
3253 {
90eb1019
RS
3254 int face_id;
3255
3256 /* Don't die if we get called with a terminal frame. */
3257 if (! FRAME_X_P (f))
3258 error ("non-X frame used in `x-list-fonts'");
3259
3260 face_id = face_name_id_number (f, face);
f0614854 3261
a081bd37
JB
3262 if (face_id < 0 || face_id >= FRAME_N_PARAM_FACES (f)
3263 || FRAME_PARAM_FACES (f) [face_id] == 0)
7556890b 3264 size_ref = f->output_data.x->font;
6998a3b4
RS
3265 else
3266 {
a081bd37 3267 size_ref = FRAME_PARAM_FACES (f) [face_id]->font;
6998a3b4 3268 if (size_ref == (XFontStruct *) (~0))
7556890b 3269 size_ref = f->output_data.x->font;
6998a3b4 3270 }
f0614854
JB
3271 }
3272
f1c16f36 3273 /* See if we cached the result for this particular query. */
08a90d6a
RS
3274 list = Fassoc (pattern,
3275 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr);
f1c16f36
RS
3276
3277 /* We have info in the cache for this PATTERN. */
3278 if (!NILP (list))
3279 {
3280 Lisp_Object tem, newlist;
3281
3282 /* We have info about this pattern. */
3283 list = XCONS (list)->cdr;
3284
3285 if (size_ref == 0)
3286 return list;
3287
3288 BLOCK_INPUT;
3289
3290 /* Filter the cached info and return just the fonts that match FACE. */
3291 newlist = Qnil;
3292 for (tem = list; CONSP (tem); tem = XCONS (tem)->cdr)
3293 {
3294 XFontStruct *thisinfo;
3295
b9dc4443 3296 thisinfo = XLoadQueryFont (FRAME_X_DISPLAY (f),
f1c16f36
RS
3297 XSTRING (XCONS (tem)->car)->data);
3298
3299 if (thisinfo && same_size_fonts (thisinfo, size_ref))
3300 newlist = Fcons (XCONS (tem)->car, newlist);
3301
a03a26db
KH
3302 if (thisinfo != 0)
3303 XFreeFont (FRAME_X_DISPLAY (f), thisinfo);
f1c16f36
RS
3304 }
3305
3306 UNBLOCK_INPUT;
3307
3308 return newlist;
3309 }
3310
f0614854 3311 BLOCK_INPUT;
f58534a3
RS
3312
3313 /* Solaris 2.3 has a bug in XListFontsWithInfo. */
40a5b2e1
KH
3314#ifndef BROKEN_XLISTFONTSWITHINFO
3315 if (size_ref)
3316 names = XListFontsWithInfo (FRAME_X_DISPLAY (f),
3317 XSTRING (pattern)->data,
3318 2000, /* maxnames */
3319 &num_fonts, /* count_return */
3320 &info); /* info_return */
3321 else
f58534a3 3322#endif
40a5b2e1
KH
3323 names = XListFonts (FRAME_X_DISPLAY (f),
3324 XSTRING (pattern)->data,
3325 2000, /* maxnames */
3326 &num_fonts); /* count_return */
3327
f0614854
JB
3328 UNBLOCK_INPUT;
3329
a9107360 3330 list = Qnil;
f0614854 3331
a9107360
RS
3332 if (names)
3333 {
a9107360 3334 int i;
f1c16f36
RS
3335 Lisp_Object full_list;
3336
3337 /* Make a list of all the fonts we got back.
3338 Store that in the font cache for the display. */
3339 full_list = Qnil;
3340 for (i = 0; i < num_fonts; i++)
3341 full_list = Fcons (build_string (names[i]), full_list);
08a90d6a 3342 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr
f1c16f36 3343 = Fcons (Fcons (pattern, full_list),
08a90d6a 3344 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr);
a9107360 3345
f1c16f36
RS
3346 /* Make a list of the fonts that have the right width. */
3347 list = Qnil;
a9107360 3348 for (i = 0; i < num_fonts; i++)
f58534a3 3349 {
40a5b2e1 3350 int keeper;
74712156 3351
40a5b2e1
KH
3352 if (!size_ref)
3353 keeper = 1;
3354 else
3355 {
f58534a3 3356#ifdef BROKEN_XLISTFONTSWITHINFO
40a5b2e1
KH
3357 XFontStruct *thisinfo;
3358
3359 BLOCK_INPUT;
3360 thisinfo = XLoadQueryFont (FRAME_X_DISPLAY (f), names[i]);
3361 UNBLOCK_INPUT;
3362
3363 keeper = thisinfo && same_size_fonts (thisinfo, size_ref);
f58534a3 3364#else
40a5b2e1 3365 keeper = same_size_fonts (&info[i], size_ref);
f58534a3 3366#endif
40a5b2e1
KH
3367 }
3368 if (keeper)
f1c16f36 3369 list = Fcons (build_string (names[i]), list);
f58534a3 3370 }
f1c16f36 3371 list = Fnreverse (list);
a9107360 3372
f58534a3 3373 BLOCK_INPUT;
40a5b2e1
KH
3374#ifndef BROKEN_XLISTFONTSWITHINFO
3375 if (size_ref)
3376 XFreeFontInfo (names, info, num_fonts);
3377 else
f58534a3 3378#endif
40a5b2e1 3379 XFreeFontNames (names);
f58534a3 3380 UNBLOCK_INPUT;
a9107360 3381 }
f0614854
JB
3382
3383 return list;
3384}
3385
3386\f
b9dc4443 3387DEFUN ("x-color-defined-p", Fx_color_defined_p, Sx_color_defined_p, 1, 2, 0,
e207bc6e 3388 "Return non-nil if color COLOR is supported on frame FRAME.\n\
08a90d6a 3389If FRAME is omitted or nil, use the selected frame.")
b9dc4443
RS
3390 (color, frame)
3391 Lisp_Object color, frame;
e12d55b2 3392{
b9dc4443
RS
3393 XColor foo;
3394 FRAME_PTR f = check_x_frame (frame);
e12d55b2 3395
b9dc4443
RS
3396 CHECK_STRING (color, 1);
3397
3398 if (defined_color (f, XSTRING (color)->data, &foo, 0))
e12d55b2
RS
3399 return Qt;
3400 else
3401 return Qnil;
3402}
3403
b9dc4443
RS
3404DEFUN ("x-color-values", Fx_color_values, Sx_color_values, 1, 2, 0,
3405 "Return a description of the color named COLOR on frame FRAME.\n\
e12d55b2 3406The value is a list of integer RGB values--(RED GREEN BLUE).\n\
a59e4f3d
RS
3407These values appear to range from 0 to 65280 or 65535, depending\n\
3408on the system; white is (65280 65280 65280) or (65535 65535 65535).\n\
08a90d6a 3409If FRAME is omitted or nil, use the selected frame.")
b9dc4443
RS
3410 (color, frame)
3411 Lisp_Object color, frame;
01f1ba30 3412{
b9dc4443
RS
3413 XColor foo;
3414 FRAME_PTR f = check_x_frame (frame);
3415
3416 CHECK_STRING (color, 1);
01f1ba30 3417
b9dc4443 3418 if (defined_color (f, XSTRING (color)->data, &foo, 0))
57c82a63
RS
3419 {
3420 Lisp_Object rgb[3];
3421
3422 rgb[0] = make_number (foo.red);
3423 rgb[1] = make_number (foo.green);
3424 rgb[2] = make_number (foo.blue);
3425 return Flist (3, rgb);
3426 }
01f1ba30
JB
3427 else
3428 return Qnil;
3429}
3430
b9dc4443 3431DEFUN ("x-display-color-p", Fx_display_color_p, Sx_display_color_p, 0, 1, 0,
08a90d6a
RS
3432 "Return t if the X display supports color.\n\
3433The optional argument DISPLAY specifies which display to ask about.\n\
3434DISPLAY should be either a frame or a display name (a string).\n\
3435If omitted or nil, that stands for the selected frame's display.")
3436 (display)
3437 Lisp_Object display;
01f1ba30 3438{
08a90d6a 3439 struct x_display_info *dpyinfo = check_x_display_info (display);
11ae94fe 3440
b9dc4443 3441 if (dpyinfo->n_planes <= 2)
01f1ba30
JB
3442 return Qnil;
3443
b9dc4443 3444 switch (dpyinfo->visual->class)
01f1ba30
JB
3445 {
3446 case StaticColor:
3447 case PseudoColor:
3448 case TrueColor:
3449 case DirectColor:
3450 return Qt;
3451
3452 default:
3453 return Qnil;
3454 }
3455}
3456
d0c9d219 3457DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
b9dc4443 3458 0, 1, 0,
08a90d6a 3459 "Return t if the X display supports shades of gray.\n\
ae6b58f9 3460Note that color displays do support shades of gray.\n\
08a90d6a
RS
3461The optional argument DISPLAY specifies which display to ask about.\n\
3462DISPLAY should be either a frame or a display name (a string).\n\
3463If omitted or nil, that stands for the selected frame's display.")
3464 (display)
3465 Lisp_Object display;
d0c9d219 3466{
08a90d6a 3467 struct x_display_info *dpyinfo = check_x_display_info (display);
d0c9d219 3468
ae6b58f9 3469 if (dpyinfo->n_planes <= 1)
b9dc4443
RS
3470 return Qnil;
3471
ae6b58f9
RS
3472 switch (dpyinfo->visual->class)
3473 {
3474 case StaticColor:
3475 case PseudoColor:
3476 case TrueColor:
3477 case DirectColor:
3478 case StaticGray:
3479 case GrayScale:
3480 return Qt;
3481
3482 default:
3483 return Qnil;
3484 }
d0c9d219
RS
3485}
3486
41beb8fc
RS
3487DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
3488 0, 1, 0,
08a90d6a
RS
3489 "Returns the width in pixels of the X display DISPLAY.\n\
3490The optional argument DISPLAY specifies which display to ask about.\n\
3491DISPLAY should be either a frame or a display name (a string).\n\
3492If omitted or nil, that stands for the selected frame's display.")
3493 (display)
3494 Lisp_Object display;
41beb8fc 3495{
08a90d6a 3496 struct x_display_info *dpyinfo = check_x_display_info (display);
b9dc4443
RS
3497
3498 return make_number (dpyinfo->width);
41beb8fc
RS
3499}
3500
3501DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
3502 Sx_display_pixel_height, 0, 1, 0,
08a90d6a
RS
3503 "Returns the height in pixels of the X display DISPLAY.\n\
3504The optional argument DISPLAY specifies which display to ask about.\n\
3505DISPLAY should be either a frame or a display name (a string).\n\
3506If omitted or nil, that stands for the selected frame's display.")
3507 (display)
3508 Lisp_Object display;
41beb8fc 3509{
08a90d6a 3510 struct x_display_info *dpyinfo = check_x_display_info (display);
b9dc4443
RS
3511
3512 return make_number (dpyinfo->height);
41beb8fc
RS
3513}
3514
3515DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
3516 0, 1, 0,
08a90d6a
RS
3517 "Returns the number of bitplanes of the X display DISPLAY.\n\
3518The optional argument DISPLAY specifies which display to ask about.\n\
3519DISPLAY should be either a frame or a display name (a string).\n\
3520If omitted or nil, that stands for the selected frame's display.")
3521 (display)
3522 Lisp_Object display;
41beb8fc 3523{
08a90d6a 3524 struct x_display_info *dpyinfo = check_x_display_info (display);
b9dc4443
RS
3525
3526 return make_number (dpyinfo->n_planes);
41beb8fc
RS
3527}
3528
3529DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
3530 0, 1, 0,
08a90d6a
RS
3531 "Returns the number of color cells of the X display DISPLAY.\n\
3532The optional argument DISPLAY specifies which display to ask about.\n\
3533DISPLAY should be either a frame or a display name (a string).\n\
3534If omitted or nil, that stands for the selected frame's display.")
3535 (display)
3536 Lisp_Object display;
41beb8fc 3537{
08a90d6a 3538 struct x_display_info *dpyinfo = check_x_display_info (display);
b9dc4443
RS
3539
3540 return make_number (DisplayCells (dpyinfo->display,
3541 XScreenNumberOfScreen (dpyinfo->screen)));
41beb8fc
RS
3542}
3543
9d317b2c
RS
3544DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
3545 Sx_server_max_request_size,
3546 0, 1, 0,
08a90d6a
RS
3547 "Returns the maximum request size of the X server of display DISPLAY.\n\
3548The optional argument DISPLAY specifies which display to ask about.\n\
3549DISPLAY should be either a frame or a display name (a string).\n\
3550If omitted or nil, that stands for the selected frame's display.")
3551 (display)
3552 Lisp_Object display;
9d317b2c 3553{
08a90d6a 3554 struct x_display_info *dpyinfo = check_x_display_info (display);
b9dc4443
RS
3555
3556 return make_number (MAXREQUEST (dpyinfo->display));
9d317b2c
RS
3557}
3558
41beb8fc 3559DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
08a90d6a
RS
3560 "Returns the vendor ID string of the X server of display DISPLAY.\n\
3561The optional argument DISPLAY specifies which display to ask about.\n\
3562DISPLAY should be either a frame or a display name (a string).\n\
3563If omitted or nil, that stands for the selected frame's display.")
3564 (display)
3565 Lisp_Object display;
41beb8fc 3566{
08a90d6a 3567 struct x_display_info *dpyinfo = check_x_display_info (display);
b9dc4443
RS
3568 char *vendor = ServerVendor (dpyinfo->display);
3569
41beb8fc
RS
3570 if (! vendor) vendor = "";
3571 return build_string (vendor);
3572}
3573
3574DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
08a90d6a 3575 "Returns the version numbers of the X server of display DISPLAY.\n\
41beb8fc
RS
3576The value is a list of three integers: the major and minor\n\
3577version numbers of the X Protocol in use, and the vendor-specific release\n\
08a90d6a
RS
3578number. See also the function `x-server-vendor'.\n\n\
3579The optional argument DISPLAY specifies which display to ask about.\n\
3580DISPLAY should be either a frame or a display name (a string).\n\
3581If omitted or nil, that stands for the selected frame's display.")
3582 (display)
3583 Lisp_Object display;
41beb8fc 3584{
08a90d6a 3585 struct x_display_info *dpyinfo = check_x_display_info (display);
b9dc4443 3586 Display *dpy = dpyinfo->display;
11ae94fe 3587
41beb8fc
RS
3588 return Fcons (make_number (ProtocolVersion (dpy)),
3589 Fcons (make_number (ProtocolRevision (dpy)),
3590 Fcons (make_number (VendorRelease (dpy)), Qnil)));
3591}
3592
3593DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
08a90d6a
RS
3594 "Returns the number of screens on the X server of display DISPLAY.\n\
3595The optional argument DISPLAY specifies which display to ask about.\n\
3596DISPLAY should be either a frame or a display name (a string).\n\
3597If omitted or nil, that stands for the selected frame's display.")
3598 (display)
3599 Lisp_Object display;
41beb8fc 3600{
08a90d6a 3601 struct x_display_info *dpyinfo = check_x_display_info (display);
b9dc4443
RS
3602
3603 return make_number (ScreenCount (dpyinfo->display));
41beb8fc
RS
3604}
3605
3606DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
08a90d6a
RS
3607 "Returns the height in millimeters of the X display DISPLAY.\n\
3608The optional argument DISPLAY specifies which display to ask about.\n\
3609DISPLAY should be either a frame or a display name (a string).\n\
3610If omitted or nil, that stands for the selected frame's display.")
3611 (display)
3612 Lisp_Object display;
41beb8fc 3613{
08a90d6a 3614 struct x_display_info *dpyinfo = check_x_display_info (display);
b9dc4443
RS
3615
3616 return make_number (HeightMMOfScreen (dpyinfo->screen));
41beb8fc
RS
3617}
3618
3619DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
08a90d6a
RS
3620 "Returns the width in millimeters of the X display DISPLAY.\n\
3621The optional argument DISPLAY specifies which display to ask about.\n\
3622DISPLAY should be either a frame or a display name (a string).\n\
3623If omitted or nil, that stands for the selected frame's display.")
3624 (display)
3625 Lisp_Object display;
41beb8fc 3626{
08a90d6a 3627 struct x_display_info *dpyinfo = check_x_display_info (display);
b9dc4443
RS
3628
3629 return make_number (WidthMMOfScreen (dpyinfo->screen));
41beb8fc
RS
3630}
3631
3632DEFUN ("x-display-backing-store", Fx_display_backing_store,
3633 Sx_display_backing_store, 0, 1, 0,
08a90d6a
RS
3634 "Returns an indication of whether X display DISPLAY does backing store.\n\
3635The value may be `always', `when-mapped', or `not-useful'.\n\
3636The optional argument DISPLAY specifies which display to ask about.\n\
3637DISPLAY should be either a frame or a display name (a string).\n\
3638If omitted or nil, that stands for the selected frame's display.")
3639 (display)
3640 Lisp_Object display;
41beb8fc 3641{
08a90d6a 3642 struct x_display_info *dpyinfo = check_x_display_info (display);
11ae94fe 3643
b9dc4443 3644 switch (DoesBackingStore (dpyinfo->screen))
41beb8fc
RS
3645 {
3646 case Always:
3647 return intern ("always");
3648
3649 case WhenMapped:
3650 return intern ("when-mapped");
3651
3652 case NotUseful:
3653 return intern ("not-useful");
3654
3655 default:
3656 error ("Strange value for BackingStore parameter of screen");
3657 }
3658}
3659
3660DEFUN ("x-display-visual-class", Fx_display_visual_class,
3661 Sx_display_visual_class, 0, 1, 0,
08a90d6a 3662 "Returns the visual class of the X display DISPLAY.\n\
41beb8fc 3663The value is one of the symbols `static-gray', `gray-scale',\n\
08a90d6a
RS
3664`static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
3665The optional argument DISPLAY specifies which display to ask about.\n\
3666DISPLAY should be either a frame or a display name (a string).\n\
3667If omitted or nil, that stands for the selected frame's display.")
3668 (display)
3669 Lisp_Object display;
41beb8fc 3670{
08a90d6a 3671 struct x_display_info *dpyinfo = check_x_display_info (display);
11ae94fe 3672
b9dc4443 3673 switch (dpyinfo->visual->class)
41beb8fc
RS
3674 {
3675 case StaticGray: return (intern ("static-gray"));
3676 case GrayScale: return (intern ("gray-scale"));
3677 case StaticColor: return (intern ("static-color"));
3678 case PseudoColor: return (intern ("pseudo-color"));
3679 case TrueColor: return (intern ("true-color"));
3680 case DirectColor: return (intern ("direct-color"));
3681 default:
3682 error ("Display has an unknown visual class");
3683 }
3684}
3685
3686DEFUN ("x-display-save-under", Fx_display_save_under,
3687 Sx_display_save_under, 0, 1, 0,
08a90d6a
RS
3688 "Returns t if the X display DISPLAY supports the save-under feature.\n\
3689The optional argument DISPLAY specifies which display to ask about.\n\
3690DISPLAY should be either a frame or a display name (a string).\n\
3691If omitted or nil, that stands for the selected frame's display.")
3692 (display)
3693 Lisp_Object display;
41beb8fc 3694{
08a90d6a 3695 struct x_display_info *dpyinfo = check_x_display_info (display);
11ae94fe 3696
b9dc4443 3697 if (DoesSaveUnders (dpyinfo->screen) == True)
41beb8fc
RS
3698 return Qt;
3699 else
3700 return Qnil;
3701}
3702\f
b9dc4443 3703int
55caf99c
RS
3704x_pixel_width (f)
3705 register struct frame *f;
01f1ba30 3706{
55caf99c 3707 return PIXEL_WIDTH (f);
01f1ba30
JB
3708}
3709
b9dc4443 3710int
55caf99c
RS
3711x_pixel_height (f)
3712 register struct frame *f;
01f1ba30 3713{
55caf99c
RS
3714 return PIXEL_HEIGHT (f);
3715}
3716
b9dc4443 3717int
55caf99c
RS
3718x_char_width (f)
3719 register struct frame *f;
3720{
7556890b 3721 return FONT_WIDTH (f->output_data.x->font);
55caf99c
RS
3722}
3723
b9dc4443 3724int
55caf99c
RS
3725x_char_height (f)
3726 register struct frame *f;
3727{
7556890b 3728 return f->output_data.x->line_height;
01f1ba30 3729}
b9dc4443
RS
3730
3731int
3732x_screen_planes (frame)
3733 Lisp_Object frame;
3734{
3735 return FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_planes;
3736}
01f1ba30 3737\f
85ffea93
RS
3738#if 0 /* These no longer seem like the right way to do things. */
3739
f676886a 3740/* Draw a rectangle on the frame with left top corner including
01f1ba30 3741 the character specified by LEFT_CHAR and TOP_CHAR. The rectangle is
b9dc4443 3742 CHARS by LINES wide and long and is the color of the cursor. */
01f1ba30
JB
3743
3744void
f676886a
JB
3745x_rectangle (f, gc, left_char, top_char, chars, lines)
3746 register struct frame *f;
01f1ba30
JB
3747 GC gc;
3748 register int top_char, left_char, chars, lines;
3749{
3750 int width;
3751 int height;
7556890b
RS
3752 int left = (left_char * FONT_WIDTH (f->output_data.x->font)
3753 + f->output_data.x->internal_border_width);
3754 int top = (top_char * f->output_data.x->line_height
3755 + f->output_data.x->internal_border_width);
01f1ba30
JB
3756
3757 if (chars < 0)
7556890b 3758 width = FONT_WIDTH (f->output_data.x->font) / 2;
01f1ba30 3759 else
7556890b 3760 width = FONT_WIDTH (f->output_data.x->font) * chars;
01f1ba30 3761 if (lines < 0)
7556890b 3762 height = f->output_data.x->line_height / 2;
01f1ba30 3763 else
7556890b 3764 height = f->output_data.x->line_height * lines;
01f1ba30 3765
b9dc4443 3766 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
01f1ba30
JB
3767 gc, left, top, width, height);
3768}
3769
3770DEFUN ("x-draw-rectangle", Fx_draw_rectangle, Sx_draw_rectangle, 5, 5, 0,
f676886a 3771 "Draw a rectangle on FRAME between coordinates specified by\n\
01f1ba30 3772numbers X0, Y0, X1, Y1 in the cursor pixel.")
f676886a
JB
3773 (frame, X0, Y0, X1, Y1)
3774 register Lisp_Object frame, X0, X1, Y0, Y1;
01f1ba30
JB
3775{
3776 register int x0, y0, x1, y1, top, left, n_chars, n_lines;
3777
f676886a 3778 CHECK_LIVE_FRAME (frame, 0);
01f1ba30
JB
3779 CHECK_NUMBER (X0, 0);
3780 CHECK_NUMBER (Y0, 1);
3781 CHECK_NUMBER (X1, 2);
3782 CHECK_NUMBER (Y1, 3);
3783
3784 x0 = XINT (X0);
3785 x1 = XINT (X1);
3786 y0 = XINT (Y0);
3787 y1 = XINT (Y1);
3788
3789 if (y1 > y0)
3790 {
3791 top = y0;
3792 n_lines = y1 - y0 + 1;
3793 }
3794 else
3795 {
3796 top = y1;
3797 n_lines = y0 - y1 + 1;
3798 }
3799
3800 if (x1 > x0)
3801 {
3802 left = x0;
3803 n_chars = x1 - x0 + 1;
3804 }
3805 else
3806 {
3807 left = x1;
3808 n_chars = x0 - x1 + 1;
3809 }
3810
3811 BLOCK_INPUT;
7556890b 3812 x_rectangle (XFRAME (frame), XFRAME (frame)->output_data.x->cursor_gc,
01f1ba30
JB
3813 left, top, n_chars, n_lines);
3814 UNBLOCK_INPUT;
3815
3816 return Qt;
3817}
3818
3819DEFUN ("x-erase-rectangle", Fx_erase_rectangle, Sx_erase_rectangle, 5, 5, 0,
f676886a 3820 "Draw a rectangle drawn on FRAME between coordinates\n\
01f1ba30 3821X0, Y0, X1, Y1 in the regular background-pixel.")
f676886a
JB
3822 (frame, X0, Y0, X1, Y1)
3823 register Lisp_Object frame, X0, Y0, X1, Y1;
01f1ba30
JB
3824{
3825 register int x0, y0, x1, y1, top, left, n_chars, n_lines;
3826
b9dc4443 3827 CHECK_LIVE_FRAME (frame, 0);
01f1ba30
JB
3828 CHECK_NUMBER (X0, 0);
3829 CHECK_NUMBER (Y0, 1);
3830 CHECK_NUMBER (X1, 2);
3831 CHECK_NUMBER (Y1, 3);
3832
3833 x0 = XINT (X0);
3834 x1 = XINT (X1);
3835 y0 = XINT (Y0);
3836 y1 = XINT (Y1);
3837
3838 if (y1 > y0)
3839 {
3840 top = y0;
3841 n_lines = y1 - y0 + 1;
3842 }
3843 else
3844 {
3845 top = y1;
3846 n_lines = y0 - y1 + 1;
3847 }
3848
3849 if (x1 > x0)
3850 {
3851 left = x0;
3852 n_chars = x1 - x0 + 1;
3853 }
3854 else
3855 {
3856 left = x1;
3857 n_chars = x0 - x1 + 1;
3858 }
3859
3860 BLOCK_INPUT;
7556890b 3861 x_rectangle (XFRAME (frame), XFRAME (frame)->output_data.x->reverse_gc,
01f1ba30
JB
3862 left, top, n_chars, n_lines);
3863 UNBLOCK_INPUT;
3864
3865 return Qt;
3866}
3867
3868/* Draw lines around the text region beginning at the character position
3869 TOP_X, TOP_Y and ending at BOTTOM_X and BOTTOM_Y. GC specifies the
b9dc4443 3870 pixel and line characteristics. */
01f1ba30 3871
f676886a 3872#define line_len(line) (FRAME_CURRENT_GLYPHS (f)->used[(line)])
01f1ba30
JB
3873
3874static void
f676886a
JB
3875outline_region (f, gc, top_x, top_y, bottom_x, bottom_y)
3876 register struct frame *f;
01f1ba30
JB
3877 GC gc;
3878 int top_x, top_y, bottom_x, bottom_y;
3879{
7556890b
RS
3880 register int ibw = f->output_data.x->internal_border_width;
3881 register int font_w = FONT_WIDTH (f->output_data.x->font);
3882 register int font_h = f->output_data.x->line_height;
01f1ba30
JB
3883 int y = top_y;
3884 int x = line_len (y);
9ef48a9d
RS
3885 XPoint *pixel_points
3886 = (XPoint *) alloca (((bottom_y - top_y + 2) * 4) * sizeof (XPoint));
01f1ba30
JB
3887 register XPoint *this_point = pixel_points;
3888
3889 /* Do the horizontal top line/lines */
3890 if (top_x == 0)
3891 {
3892 this_point->x = ibw;
3893 this_point->y = ibw + (font_h * top_y);
3894 this_point++;
3895 if (x == 0)
b9dc4443 3896 this_point->x = ibw + (font_w / 2); /* Half-size for newline chars. */
01f1ba30
JB
3897 else
3898 this_point->x = ibw + (font_w * x);
3899 this_point->y = (this_point - 1)->y;
3900 }
3901 else
3902 {
3903 this_point->x = ibw;
3904 this_point->y = ibw + (font_h * (top_y + 1));
3905 this_point++;
3906 this_point->x = ibw + (font_w * top_x);
3907 this_point->y = (this_point - 1)->y;
3908 this_point++;
3909 this_point->x = (this_point - 1)->x;
3910 this_point->y = ibw + (font_h * top_y);
3911 this_point++;
3912 this_point->x = ibw + (font_w * x);
3913 this_point->y = (this_point - 1)->y;
3914 }
3915
b9dc4443 3916 /* Now do the right side. */
01f1ba30
JB
3917 while (y < bottom_y)
3918 { /* Right vertical edge */
3919 this_point++;
3920 this_point->x = (this_point - 1)->x;
3921 this_point->y = ibw + (font_h * (y + 1));
3922 this_point++;
3923
3924 y++; /* Horizontal connection to next line */
3925 x = line_len (y);
3926 if (x == 0)
3927 this_point->x = ibw + (font_w / 2);
3928 else
3929 this_point->x = ibw + (font_w * x);
3930
3931 this_point->y = (this_point - 1)->y;
3932 }
3933
b9dc4443 3934 /* Now do the bottom and connect to the top left point. */
01f1ba30
JB
3935 this_point->x = ibw + (font_w * (bottom_x + 1));
3936
3937 this_point++;
3938 this_point->x = (this_point - 1)->x;
3939 this_point->y = ibw + (font_h * (bottom_y + 1));
3940 this_point++;
3941 this_point->x = ibw;
3942 this_point->y = (this_point - 1)->y;
3943 this_point++;
3944 this_point->x = pixel_points->x;
3945 this_point->y = pixel_points->y;
3946
b9dc4443 3947 XDrawLines (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
01f1ba30
JB
3948 gc, pixel_points,
3949 (this_point - pixel_points + 1), CoordModeOrigin);
3950}
3951
3952DEFUN ("x-contour-region", Fx_contour_region, Sx_contour_region, 1, 1, 0,
3953 "Highlight the region between point and the character under the mouse\n\
f676886a 3954selected frame.")
01f1ba30
JB
3955 (event)
3956 register Lisp_Object event;
3957{
3958 register int x0, y0, x1, y1;
f676886a 3959 register struct frame *f = selected_frame;
01f1ba30
JB
3960 register int p1, p2;
3961
3962 CHECK_CONS (event, 0);
3963
3964 BLOCK_INPUT;
3965 x0 = XINT (Fcar (Fcar (event)));
3966 y0 = XINT (Fcar (Fcdr (Fcar (event))));
3967
b9dc4443
RS
3968 /* If the mouse is past the end of the line, don't that area. */
3969 /* ReWrite this... */
01f1ba30 3970
f676886a
JB
3971 x1 = f->cursor_x;
3972 y1 = f->cursor_y;
01f1ba30
JB
3973
3974 if (y1 > y0) /* point below mouse */
7556890b 3975 outline_region (f, f->output_data.x->cursor_gc,
01f1ba30
JB
3976 x0, y0, x1, y1);
3977 else if (y1 < y0) /* point above mouse */
7556890b 3978 outline_region (f, f->output_data.x->cursor_gc,
01f1ba30
JB
3979 x1, y1, x0, y0);
3980 else /* same line: draw horizontal rectangle */
3981 {
3982 if (x1 > x0)
7556890b 3983 x_rectangle (f, f->output_data.x->cursor_gc,
01f1ba30
JB
3984 x0, y0, (x1 - x0 + 1), 1);
3985 else if (x1 < x0)
7556890b 3986 x_rectangle (f, f->output_data.x->cursor_gc,
01f1ba30
JB
3987 x1, y1, (x0 - x1 + 1), 1);
3988 }
3989
b9dc4443 3990 XFlush (FRAME_X_DISPLAY (f));
01f1ba30
JB
3991 UNBLOCK_INPUT;
3992
3993 return Qnil;
3994}
3995
3996DEFUN ("x-uncontour-region", Fx_uncontour_region, Sx_uncontour_region, 1, 1, 0,
3997 "Erase any highlighting of the region between point and the character\n\
f676886a 3998at X, Y on the selected frame.")
01f1ba30
JB
3999 (event)
4000 register Lisp_Object event;
4001{
4002 register int x0, y0, x1, y1;
f676886a 4003 register struct frame *f = selected_frame;
01f1ba30
JB
4004
4005 BLOCK_INPUT;
4006 x0 = XINT (Fcar (Fcar (event)));
4007 y0 = XINT (Fcar (Fcdr (Fcar (event))));
f676886a
JB
4008 x1 = f->cursor_x;
4009 y1 = f->cursor_y;
01f1ba30
JB
4010
4011 if (y1 > y0) /* point below mouse */
7556890b 4012 outline_region (f, f->output_data.x->reverse_gc,
01f1ba30
JB
4013 x0, y0, x1, y1);
4014 else if (y1 < y0) /* point above mouse */
7556890b 4015 outline_region (f, f->output_data.x->reverse_gc,
01f1ba30
JB
4016 x1, y1, x0, y0);
4017 else /* same line: draw horizontal rectangle */
4018 {
4019 if (x1 > x0)
7556890b 4020 x_rectangle (f, f->output_data.x->reverse_gc,
01f1ba30
JB
4021 x0, y0, (x1 - x0 + 1), 1);
4022 else if (x1 < x0)
7556890b 4023 x_rectangle (f, f->output_data.x->reverse_gc,
01f1ba30
JB
4024 x1, y1, (x0 - x1 + 1), 1);
4025 }
4026 UNBLOCK_INPUT;
4027
4028 return Qnil;
4029}
4030
01f1ba30
JB
4031#if 0
4032int contour_begin_x, contour_begin_y;
4033int contour_end_x, contour_end_y;
4034int contour_npoints;
4035
4036/* Clip the top part of the contour lines down (and including) line Y_POS.
4037 If X_POS is in the middle (rather than at the end) of the line, drop
b9dc4443 4038 down a line at that character. */
01f1ba30
JB
4039
4040static void
4041clip_contour_top (y_pos, x_pos)
4042{
4043 register XPoint *begin = contour_lines[y_pos].top_left;
4044 register XPoint *end;
4045 register int npoints;
f676886a 4046 register struct display_line *line = selected_frame->phys_lines[y_pos + 1];
01f1ba30 4047
b9dc4443 4048 if (x_pos >= line->len - 1) /* Draw one, straight horizontal line. */
01f1ba30
JB
4049 {
4050 end = contour_lines[y_pos].top_right;
4051 npoints = (end - begin + 1);
4052 XDrawLines (x_current_display, contour_window,
4053 contour_erase_gc, begin_erase, npoints, CoordModeOrigin);
4054
4055 bcopy (end, begin + 1, contour_last_point - end + 1);
4056 contour_last_point -= (npoints - 2);
4057 XDrawLines (x_current_display, contour_window,
4058 contour_erase_gc, begin, 2, CoordModeOrigin);
4059 XFlush (x_current_display);
4060
b9dc4443 4061 /* Now, update contour_lines structure. */
01f1ba30
JB
4062 }
4063 /* ______. */
4064 else /* |________*/
4065 {
4066 register XPoint *p = begin + 1;
4067 end = contour_lines[y_pos].bottom_right;
4068 npoints = (end - begin + 1);
4069 XDrawLines (x_current_display, contour_window,
4070 contour_erase_gc, begin_erase, npoints, CoordModeOrigin);
4071
4072 p->y = begin->y;
4073 p->x = ibw + (font_w * (x_pos + 1));
4074 p++;
4075 p->y = begin->y + font_h;
4076 p->x = (p - 1)->x;
4077 bcopy (end, begin + 3, contour_last_point - end + 1);
4078 contour_last_point -= (npoints - 5);
4079 XDrawLines (x_current_display, contour_window,
4080 contour_erase_gc, begin, 4, CoordModeOrigin);
4081 XFlush (x_current_display);
4082
b9dc4443 4083 /* Now, update contour_lines structure. */
01f1ba30
JB
4084 }
4085}
4086
eb8c3be9 4087/* Erase the top horizontal lines of the contour, and then extend
b9dc4443 4088 the contour upwards. */
01f1ba30
JB
4089
4090static void
4091extend_contour_top (line)
4092{
4093}
4094
4095static void
4096clip_contour_bottom (x_pos, y_pos)
4097 int x_pos, y_pos;
4098{
4099}
4100
4101static void
4102extend_contour_bottom (x_pos, y_pos)
4103{
4104}
4105
4106DEFUN ("x-select-region", Fx_select_region, Sx_select_region, 1, 1, "e",
4107 "")
4108 (event)
4109 Lisp_Object event;
4110{
f676886a
JB
4111 register struct frame *f = selected_frame;
4112 register int point_x = f->cursor_x;
4113 register int point_y = f->cursor_y;
01f1ba30
JB
4114 register int mouse_below_point;
4115 register Lisp_Object obj;
4116 register int x_contour_x, x_contour_y;
4117
4118 x_contour_x = x_mouse_x;
4119 x_contour_y = x_mouse_y;
4120 if (x_contour_y > point_y || (x_contour_y == point_y
4121 && x_contour_x > point_x))
4122 {
4123 mouse_below_point = 1;
7556890b 4124 outline_region (f, f->output_data.x->cursor_gc, point_x, point_y,
01f1ba30
JB
4125 x_contour_x, x_contour_y);
4126 }
4127 else
4128 {
4129 mouse_below_point = 0;
7556890b 4130 outline_region (f, f->output_data.x->cursor_gc, x_contour_x, x_contour_y,
01f1ba30
JB
4131 point_x, point_y);
4132 }
4133
4134 while (1)
4135 {
95be70ed 4136 obj = read_char (-1, 0, 0, Qnil, 0);
6a5e54e2 4137 if (!CONSP (obj))
01f1ba30
JB
4138 break;
4139
4140 if (mouse_below_point)
4141 {
b9dc4443 4142 if (x_mouse_y <= point_y) /* Flipped. */
01f1ba30
JB
4143 {
4144 mouse_below_point = 0;
4145
7556890b 4146 outline_region (f, f->output_data.x->reverse_gc, point_x, point_y,
01f1ba30 4147 x_contour_x, x_contour_y);
7556890b 4148 outline_region (f, f->output_data.x->cursor_gc, x_mouse_x, x_mouse_y,
01f1ba30
JB
4149 point_x, point_y);
4150 }
b9dc4443 4151 else if (x_mouse_y < x_contour_y) /* Bottom clipped. */
01f1ba30
JB
4152 {
4153 clip_contour_bottom (x_mouse_y);
4154 }
b9dc4443 4155 else if (x_mouse_y > x_contour_y) /* Bottom extended. */
01f1ba30
JB
4156 {
4157 extend_bottom_contour (x_mouse_y);
4158 }
4159
4160 x_contour_x = x_mouse_x;
4161 x_contour_y = x_mouse_y;
4162 }
4163 else /* mouse above or same line as point */
4164 {
b9dc4443 4165 if (x_mouse_y >= point_y) /* Flipped. */
01f1ba30
JB
4166 {
4167 mouse_below_point = 1;
4168
7556890b 4169 outline_region (f, f->output_data.x->reverse_gc,
01f1ba30 4170 x_contour_x, x_contour_y, point_x, point_y);
7556890b 4171 outline_region (f, f->output_data.x->cursor_gc, point_x, point_y,
01f1ba30
JB
4172 x_mouse_x, x_mouse_y);
4173 }
b9dc4443 4174 else if (x_mouse_y > x_contour_y) /* Top clipped. */
01f1ba30
JB
4175 {
4176 clip_contour_top (x_mouse_y);
4177 }
b9dc4443 4178 else if (x_mouse_y < x_contour_y) /* Top extended. */
01f1ba30
JB
4179 {
4180 extend_contour_top (x_mouse_y);
4181 }
4182 }
4183 }
4184
b4f5687c 4185 unread_command_event = obj;
01f1ba30
JB
4186 if (mouse_below_point)
4187 {
4188 contour_begin_x = point_x;
4189 contour_begin_y = point_y;
4190 contour_end_x = x_contour_x;
4191 contour_end_y = x_contour_y;
4192 }
4193 else
4194 {
4195 contour_begin_x = x_contour_x;
4196 contour_begin_y = x_contour_y;
4197 contour_end_x = point_x;
4198 contour_end_y = point_y;
4199 }
4200}
4201#endif
4202
4203DEFUN ("x-horizontal-line", Fx_horizontal_line, Sx_horizontal_line, 1, 1, "e",
4204 "")
4205 (event)
4206 Lisp_Object event;
4207{
4208 register Lisp_Object obj;
f676886a 4209 struct frame *f = selected_frame;
01f1ba30 4210 register struct window *w = XWINDOW (selected_window);
7556890b
RS
4211 register GC line_gc = f->output_data.x->cursor_gc;
4212 register GC erase_gc = f->output_data.x->reverse_gc;
01f1ba30
JB
4213#if 0
4214 char dash_list[] = {6, 4, 6, 4};
4215 int dashes = 4;
4216 XGCValues gc_values;
4217#endif
4218 register int previous_y;
7556890b
RS
4219 register int line = (x_mouse_y + 1) * f->output_data.x->line_height
4220 + f->output_data.x->internal_border_width;
4221 register int left = f->output_data.x->internal_border_width
01f1ba30 4222 + (w->left
7556890b 4223 * FONT_WIDTH (f->output_data.x->font));
01f1ba30 4224 register int right = left + (w->width
7556890b
RS
4225 * FONT_WIDTH (f->output_data.x->font))
4226 - f->output_data.x->internal_border_width;
01f1ba30
JB
4227
4228#if 0
4229 BLOCK_INPUT;
7556890b
RS
4230 gc_values.foreground = f->output_data.x->cursor_pixel;
4231 gc_values.background = f->output_data.x->background_pixel;
01f1ba30
JB
4232 gc_values.line_width = 1;
4233 gc_values.line_style = LineOnOffDash;
4234 gc_values.cap_style = CapRound;
4235 gc_values.join_style = JoinRound;
4236
b9dc4443 4237 line_gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
01f1ba30
JB
4238 GCLineStyle | GCJoinStyle | GCCapStyle
4239 | GCLineWidth | GCForeground | GCBackground,
4240 &gc_values);
b9dc4443 4241 XSetDashes (FRAME_X_DISPLAY (f), line_gc, 0, dash_list, dashes);
7556890b
RS
4242 gc_values.foreground = f->output_data.x->background_pixel;
4243 gc_values.background = f->output_data.x->foreground_pixel;
b9dc4443 4244 erase_gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
01f1ba30
JB
4245 GCLineStyle | GCJoinStyle | GCCapStyle
4246 | GCLineWidth | GCForeground | GCBackground,
4247 &gc_values);
b9dc4443 4248 XSetDashes (FRAME_X_DISPLAY (f), erase_gc, 0, dash_list, dashes);
ed662bdd 4249 UNBLOCK_INPUT;
01f1ba30
JB
4250#endif
4251
4252 while (1)
4253 {
4254 BLOCK_INPUT;
4255 if (x_mouse_y >= XINT (w->top)
4256 && x_mouse_y < XINT (w->top) + XINT (w->height) - 1)
4257 {
4258 previous_y = x_mouse_y;
7556890b
RS
4259 line = (x_mouse_y + 1) * f->output_data.x->line_height
4260 + f->output_data.x->internal_border_width;
b9dc4443 4261 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
01f1ba30
JB
4262 line_gc, left, line, right, line);
4263 }
b9dc4443 4264 XFlush (FRAME_X_DISPLAY (f));
01f1ba30
JB
4265 UNBLOCK_INPUT;
4266
4267 do
4268 {
95be70ed 4269 obj = read_char (-1, 0, 0, Qnil, 0);
6a5e54e2 4270 if (!CONSP (obj)
01f1ba30 4271 || (! EQ (Fcar (Fcdr (Fcdr (obj))),
6a5e54e2 4272 Qvertical_scroll_bar))
01f1ba30
JB
4273 || x_mouse_grabbed)
4274 {
4275 BLOCK_INPUT;
b9dc4443 4276 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
01f1ba30 4277 erase_gc, left, line, right, line);
b4f5687c 4278 unread_command_event = obj;
01f1ba30 4279#if 0
b9dc4443
RS
4280 XFreeGC (FRAME_X_DISPLAY (f), line_gc);
4281 XFreeGC (FRAME_X_DISPLAY (f), erase_gc);
01f1ba30 4282#endif
ed662bdd 4283 UNBLOCK_INPUT;
01f1ba30
JB
4284 return Qnil;
4285 }
4286 }
4287 while (x_mouse_y == previous_y);
4288
4289 BLOCK_INPUT;
b9dc4443 4290 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
01f1ba30
JB
4291 erase_gc, left, line, right, line);
4292 UNBLOCK_INPUT;
4293 }
4294}
06ef7355 4295#endif
01f1ba30 4296\f
01f1ba30 4297#if 0
b9dc4443 4298/* These keep track of the rectangle following the pointer. */
01f1ba30
JB
4299int mouse_track_top, mouse_track_left, mouse_track_width;
4300
b9dc4443
RS
4301/* Offset in buffer of character under the pointer, or 0. */
4302int mouse_buffer_offset;
4303
01f1ba30
JB
4304DEFUN ("x-track-pointer", Fx_track_pointer, Sx_track_pointer, 0, 0, 0,
4305 "Track the pointer.")
4306 ()
4307{
4308 static Cursor current_pointer_shape;
f676886a 4309 FRAME_PTR f = x_mouse_frame;
01f1ba30
JB
4310
4311 BLOCK_INPUT;
f676886a 4312 if (EQ (Vmouse_frame_part, Qtext_part)
7556890b 4313 && (current_pointer_shape != f->output_data.x->nontext_cursor))
01f1ba30
JB
4314 {
4315 unsigned char c;
4316 struct buffer *buf;
4317
7556890b 4318 current_pointer_shape = f->output_data.x->nontext_cursor;
b9dc4443 4319 XDefineCursor (FRAME_X_DISPLAY (f),
fe24a618 4320 FRAME_X_WINDOW (f),
01f1ba30
JB
4321 current_pointer_shape);
4322
4323 buf = XBUFFER (XWINDOW (Vmouse_window)->buffer);
4324 c = *(BUF_CHAR_ADDRESS (buf, mouse_buffer_offset));
4325 }
f676886a 4326 else if (EQ (Vmouse_frame_part, Qmodeline_part)
7556890b 4327 && (current_pointer_shape != f->output_data.x->modeline_cursor))
01f1ba30 4328 {
7556890b 4329 current_pointer_shape = f->output_data.x->modeline_cursor;
b9dc4443 4330 XDefineCursor (FRAME_X_DISPLAY (f),
fe24a618 4331 FRAME_X_WINDOW (f),
01f1ba30
JB
4332 current_pointer_shape);
4333 }
4334
b9dc4443 4335 XFlush (FRAME_X_DISPLAY (f));
01f1ba30
JB
4336 UNBLOCK_INPUT;
4337}
4338#endif
4339
4340#if 0
4341DEFUN ("x-track-pointer", Fx_track_pointer, Sx_track_pointer, 1, 1, "e",
4342 "Draw rectangle around character under mouse pointer, if there is one.")
4343 (event)
4344 Lisp_Object event;
4345{
4346 struct window *w = XWINDOW (Vmouse_window);
f676886a 4347 struct frame *f = XFRAME (WINDOW_FRAME (w));
01f1ba30
JB
4348 struct buffer *b = XBUFFER (w->buffer);
4349 Lisp_Object obj;
4350
4351 if (! EQ (Vmouse_window, selected_window))
4352 return Qnil;
4353
4354 if (EQ (event, Qnil))
4355 {
4356 int x, y;
4357
f676886a 4358 x_read_mouse_position (selected_frame, &x, &y);
01f1ba30
JB
4359 }
4360
4361 BLOCK_INPUT;
4362 mouse_track_width = 0;
4363 mouse_track_left = mouse_track_top = -1;
4364
4365 do
4366 {
4367 if ((x_mouse_x != mouse_track_left
4368 && (x_mouse_x < mouse_track_left
4369 || x_mouse_x > (mouse_track_left + mouse_track_width)))
4370 || x_mouse_y != mouse_track_top)
4371 {
4372 int hp = 0; /* Horizontal position */
f676886a
JB
4373 int len = FRAME_CURRENT_GLYPHS (f)->used[x_mouse_y];
4374 int p = FRAME_CURRENT_GLYPHS (f)->bufp[x_mouse_y];
01f1ba30 4375 int tab_width = XINT (b->tab_width);
265a9e55 4376 int ctl_arrow_p = !NILP (b->ctl_arrow);
01f1ba30
JB
4377 unsigned char c;
4378 int mode_line_vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
4379 int in_mode_line = 0;
4380
f676886a 4381 if (! FRAME_CURRENT_GLYPHS (f)->enable[x_mouse_y])
01f1ba30
JB
4382 break;
4383
b9dc4443 4384 /* Erase previous rectangle. */
01f1ba30
JB
4385 if (mouse_track_width)
4386 {
7556890b 4387 x_rectangle (f, f->output_data.x->reverse_gc,
01f1ba30
JB
4388 mouse_track_left, mouse_track_top,
4389 mouse_track_width, 1);
4390
f676886a
JB
4391 if ((mouse_track_left == f->phys_cursor_x
4392 || mouse_track_left == f->phys_cursor_x - 1)
4393 && mouse_track_top == f->phys_cursor_y)
01f1ba30 4394 {
f676886a 4395 x_display_cursor (f, 1);
01f1ba30
JB
4396 }
4397 }
4398
4399 mouse_track_left = x_mouse_x;
4400 mouse_track_top = x_mouse_y;
4401 mouse_track_width = 0;
4402
b9dc4443 4403 if (mouse_track_left > len) /* Past the end of line. */
01f1ba30
JB
4404 goto draw_or_not;
4405
4406 if (mouse_track_top == mode_line_vpos)
4407 {
4408 in_mode_line = 1;
4409 goto draw_or_not;
4410 }
4411
4412 if (tab_width <= 0 || tab_width > 20) tab_width = 8;
4413 do
4414 {
4415 c = FETCH_CHAR (p);
f676886a 4416 if (len == f->width && hp == len - 1 && c != '\n')
01f1ba30
JB
4417 goto draw_or_not;
4418
4419 switch (c)
4420 {
4421 case '\t':
4422 mouse_track_width = tab_width - (hp % tab_width);
4423 p++;
4424 hp += mouse_track_width;
4425 if (hp > x_mouse_x)
4426 {
4427 mouse_track_left = hp - mouse_track_width;
4428 goto draw_or_not;
4429 }
4430 continue;
4431
4432 case '\n':
4433 mouse_track_width = -1;
4434 goto draw_or_not;
4435
4436 default:
4437 if (ctl_arrow_p && (c < 040 || c == 0177))
4438 {
4439 if (p > ZV)
4440 goto draw_or_not;
4441
4442 mouse_track_width = 2;
4443 p++;
4444 hp +=2;
4445 if (hp > x_mouse_x)
4446 {
4447 mouse_track_left = hp - mouse_track_width;
4448 goto draw_or_not;
4449 }
4450 }
4451 else
4452 {
4453 mouse_track_width = 1;
4454 p++;
4455 hp++;
4456 }
4457 continue;
4458 }
4459 }
4460 while (hp <= x_mouse_x);
4461
4462 draw_or_not:
b9dc4443 4463 if (mouse_track_width) /* Over text; use text pointer shape. */
01f1ba30 4464 {
b9dc4443 4465 XDefineCursor (FRAME_X_DISPLAY (f),
fe24a618 4466 FRAME_X_WINDOW (f),
7556890b
RS
4467 f->output_data.x->text_cursor);
4468 x_rectangle (f, f->output_data.x->cursor_gc,
01f1ba30
JB
4469 mouse_track_left, mouse_track_top,
4470 mouse_track_width, 1);
4471 }
4472 else if (in_mode_line)
b9dc4443 4473 XDefineCursor (FRAME_X_DISPLAY (f),
fe24a618 4474 FRAME_X_WINDOW (f),
7556890b 4475 f->output_data.x->modeline_cursor);
01f1ba30 4476 else
b9dc4443 4477 XDefineCursor (FRAME_X_DISPLAY (f),
fe24a618 4478 FRAME_X_WINDOW (f),
7556890b 4479 f->output_data.x->nontext_cursor);
01f1ba30
JB
4480 }
4481
b9dc4443 4482 XFlush (FRAME_X_DISPLAY (f));
01f1ba30
JB
4483 UNBLOCK_INPUT;
4484
95be70ed 4485 obj = read_char (-1, 0, 0, Qnil, 0);
01f1ba30
JB
4486 BLOCK_INPUT;
4487 }
6a5e54e2 4488 while (CONSP (obj) /* Mouse event */
a3c87d4e 4489 && EQ (Fcar (Fcdr (Fcdr (obj))), Qnil) /* Not scroll bar */
01f1ba30
JB
4490 && EQ (Vmouse_depressed, Qnil) /* Only motion events */
4491 && EQ (Vmouse_window, selected_window) /* In this window */
f676886a 4492 && x_mouse_frame);
01f1ba30 4493
b4f5687c 4494 unread_command_event = obj;
01f1ba30
JB
4495
4496 if (mouse_track_width)
4497 {
7556890b 4498 x_rectangle (f, f->output_data.x->reverse_gc,
01f1ba30
JB
4499 mouse_track_left, mouse_track_top,
4500 mouse_track_width, 1);
4501 mouse_track_width = 0;
f676886a
JB
4502 if ((mouse_track_left == f->phys_cursor_x
4503 || mouse_track_left - 1 == f->phys_cursor_x)
4504 && mouse_track_top == f->phys_cursor_y)
01f1ba30 4505 {
f676886a 4506 x_display_cursor (f, 1);
01f1ba30
JB
4507 }
4508 }
b9dc4443 4509 XDefineCursor (FRAME_X_DISPLAY (f),
fe24a618 4510 FRAME_X_WINDOW (f),
7556890b 4511 f->output_data.x->nontext_cursor);
b9dc4443 4512 XFlush (FRAME_X_DISPLAY (f));
01f1ba30
JB
4513 UNBLOCK_INPUT;
4514
4515 return Qnil;
4516}
4517#endif
4518\f
4519#if 0
4520#include "glyphs.h"
4521
4522/* Draw a pixmap specified by IMAGE_DATA of dimensions WIDTH and HEIGHT
b9dc4443 4523 on the frame F at position X, Y. */
01f1ba30 4524
f676886a
JB
4525x_draw_pixmap (f, x, y, image_data, width, height)
4526 struct frame *f;
01f1ba30
JB
4527 int x, y, width, height;
4528 char *image_data;
4529{
4530 Pixmap image;
4531
b9dc4443 4532 image = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
fe24a618 4533 FRAME_X_WINDOW (f), image_data,
01f1ba30 4534 width, height);
b9dc4443 4535 XCopyPlane (FRAME_X_DISPLAY (f), image, FRAME_X_WINDOW (f),
7556890b 4536 f->output_data.x->normal_gc, 0, 0, width, height, x, y);
01f1ba30
JB
4537}
4538#endif
4539\f
01567351
RS
4540#if 0 /* I'm told these functions are superfluous
4541 given the ability to bind function keys. */
4542
01f1ba30
JB
4543#ifdef HAVE_X11
4544DEFUN ("x-rebind-key", Fx_rebind_key, Sx_rebind_key, 3, 3, 0,
4545"Rebind X keysym KEYSYM, with MODIFIERS, to generate NEWSTRING.\n\
4546KEYSYM is a string which conforms to the X keysym definitions found\n\
4547in X11/keysymdef.h, sans the initial XK_. MODIFIERS is nil or a\n\
4548list of strings specifying modifier keys such as Control_L, which must\n\
4549also be depressed for NEWSTRING to appear.")
4550 (x_keysym, modifiers, newstring)
4551 register Lisp_Object x_keysym;
4552 register Lisp_Object modifiers;
4553 register Lisp_Object newstring;
4554{
4555 char *rawstring;
c047688c
JA
4556 register KeySym keysym;
4557 KeySym modifier_list[16];
01f1ba30 4558
11ae94fe 4559 check_x ();
01f1ba30
JB
4560 CHECK_STRING (x_keysym, 1);
4561 CHECK_STRING (newstring, 3);
4562
4563 keysym = XStringToKeysym ((char *) XSTRING (x_keysym)->data);
4564 if (keysym == NoSymbol)
4565 error ("Keysym does not exist");
4566
265a9e55 4567 if (NILP (modifiers))
01f1ba30
JB
4568 XRebindKeysym (x_current_display, keysym, modifier_list, 0,
4569 XSTRING (newstring)->data, XSTRING (newstring)->size);
4570 else
4571 {
4572 register Lisp_Object rest, mod;
4573 register int i = 0;
4574
265a9e55 4575 for (rest = modifiers; !NILP (rest); rest = Fcdr (rest))
01f1ba30
JB
4576 {
4577 if (i == 16)
4578 error ("Can't have more than 16 modifiers");
4579
4580 mod = Fcar (rest);
4581 CHECK_STRING (mod, 3);
4582 modifier_list[i] = XStringToKeysym ((char *) XSTRING (mod)->data);
fb351039
JB
4583#ifndef HAVE_X11R5
4584 if (modifier_list[i] == NoSymbol
4585 || !(IsModifierKey (modifier_list[i])
4586 || ((unsigned)(modifier_list[i]) == XK_Mode_switch)
4587 || ((unsigned)(modifier_list[i]) == XK_Num_Lock)))
4588#else
01f1ba30
JB
4589 if (modifier_list[i] == NoSymbol
4590 || !IsModifierKey (modifier_list[i]))
fb351039 4591#endif
01f1ba30
JB
4592 error ("Element is not a modifier keysym");
4593 i++;
4594 }
4595
4596 XRebindKeysym (x_current_display, keysym, modifier_list, i,
4597 XSTRING (newstring)->data, XSTRING (newstring)->size);
4598 }
4599
4600 return Qnil;
4601}
4602
4603DEFUN ("x-rebind-keys", Fx_rebind_keys, Sx_rebind_keys, 2, 2, 0,
4604 "Rebind KEYCODE to list of strings STRINGS.\n\
4605STRINGS should be a list of 16 elements, one for each shift combination.\n\
4606nil as element means don't change.\n\
4607See the documentation of `x-rebind-key' for more information.")
4608 (keycode, strings)
4609 register Lisp_Object keycode;
4610 register Lisp_Object strings;
4611{
4612 register Lisp_Object item;
4613 register unsigned char *rawstring;
4614 KeySym rawkey, modifier[1];
4615 int strsize;
4616 register unsigned i;
4617
11ae94fe 4618 check_x ();
01f1ba30
JB
4619 CHECK_NUMBER (keycode, 1);
4620 CHECK_CONS (strings, 2);
4621 rawkey = (KeySym) ((unsigned) (XINT (keycode))) & 255;
4622 for (i = 0; i <= 15; strings = Fcdr (strings), i++)
4623 {
4624 item = Fcar (strings);
265a9e55 4625 if (!NILP (item))
01f1ba30
JB
4626 {
4627 CHECK_STRING (item, 2);
4628 strsize = XSTRING (item)->size;
4629 rawstring = (unsigned char *) xmalloc (strsize);
4630 bcopy (XSTRING (item)->data, rawstring, strsize);
4631 modifier[1] = 1 << i;
4632 XRebindKeysym (x_current_display, rawkey, modifier, 1,
4633 rawstring, strsize);
4634 }
4635 }
4636 return Qnil;
4637}
9d04a87a 4638#endif /* HAVE_X11 */
01567351 4639#endif /* 0 */
01f1ba30 4640\f
404daac1
RS
4641#ifndef HAVE_XSCREENNUMBEROFSCREEN
4642int
4643XScreenNumberOfScreen (scr)
4644 register Screen *scr;
4645{
3df34fdb
BF
4646 register Display *dpy;
4647 register Screen *dpyscr;
404daac1
RS
4648 register int i;
4649
3df34fdb
BF
4650 dpy = scr->display;
4651 dpyscr = dpy->screens;
4652
404daac1
RS
4653 for (i = 0; i < dpy->nscreens; i++, dpyscr++)
4654 if (scr == dpyscr)
4655 return i;
4656
4657 return -1;
4658}
4659#endif /* not HAVE_XSCREENNUMBEROFSCREEN */
4660
01f1ba30 4661Visual *
b9dc4443
RS
4662select_visual (dpy, screen, depth)
4663 Display *dpy;
01f1ba30
JB
4664 Screen *screen;
4665 unsigned int *depth;
4666{
4667 Visual *v;
4668 XVisualInfo *vinfo, vinfo_template;
4669 int n_visuals;
4670
4671 v = DefaultVisualOfScreen (screen);
fe24a618
JB
4672
4673#ifdef HAVE_X11R4
4674 vinfo_template.visualid = XVisualIDFromVisual (v);
4675#else
6afb1d07 4676 vinfo_template.visualid = v->visualid;
fe24a618
JB
4677#endif
4678
f0614854
JB
4679 vinfo_template.screen = XScreenNumberOfScreen (screen);
4680
b9dc4443 4681 vinfo = XGetVisualInfo (dpy,
f0614854 4682 VisualIDMask | VisualScreenMask, &vinfo_template,
01f1ba30
JB
4683 &n_visuals);
4684 if (n_visuals != 1)
4685 fatal ("Can't get proper X visual info");
4686
4687 if ((1 << vinfo->depth) == vinfo->colormap_size)
4688 *depth = vinfo->depth;
4689 else
4690 {
4691 int i = 0;
4692 int n = vinfo->colormap_size - 1;
4693 while (n)
4694 {
4695 n = n >> 1;
4696 i++;
4697 }
4698 *depth = i;
4699 }
4700
4701 XFree ((char *) vinfo);
4702 return v;
4703}
01f1ba30 4704
b9dc4443
RS
4705/* Return the X display structure for the display named NAME.
4706 Open a new connection if necessary. */
4707
4708struct x_display_info *
4709x_display_info_for_name (name)
4710 Lisp_Object name;
4711{
08a90d6a 4712 Lisp_Object names;
b9dc4443
RS
4713 struct x_display_info *dpyinfo;
4714
4715 CHECK_STRING (name, 0);
4716
806048df
RS
4717 if (! EQ (Vwindow_system, intern ("x")))
4718 error ("Not using X Windows");
4719
08a90d6a
RS
4720 for (dpyinfo = x_display_list, names = x_display_name_list;
4721 dpyinfo;
4722 dpyinfo = dpyinfo->next, names = XCONS (names)->cdr)
b9dc4443
RS
4723 {
4724 Lisp_Object tem;
08a90d6a
RS
4725 tem = Fstring_equal (XCONS (XCONS (names)->car)->car, name);
4726 if (!NILP (tem))
b9dc4443
RS
4727 return dpyinfo;
4728 }
4729
b7975ee4
KH
4730 /* Use this general default value to start with. */
4731 Vx_resource_name = Vinvocation_name;
4732
b9dc4443
RS
4733 validate_x_resource_name ();
4734
4735 dpyinfo = x_term_init (name, (unsigned char *)0,
b7975ee4 4736 (char *) XSTRING (Vx_resource_name)->data);
b9dc4443 4737
08a90d6a 4738 if (dpyinfo == 0)
1b4ec1c8 4739 error ("Cannot connect to X server %s", XSTRING (name)->data);
08a90d6a 4740
b9dc4443
RS
4741 x_in_use = 1;
4742 XSETFASTINT (Vwindow_system_version, 11);
4743
4744 return dpyinfo;
4745}
4746
01f1ba30 4747DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
08a90d6a 4748 1, 3, 0, "Open a connection to an X server.\n\
d387c960 4749DISPLAY is the name of the display to connect to.\n\
08a90d6a
RS
4750Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
4751If the optional third arg MUST-SUCCEED is non-nil,\n\
4752terminate Emacs if we can't open the connection.")
4753 (display, xrm_string, must_succeed)
4754 Lisp_Object display, xrm_string, must_succeed;
01f1ba30
JB
4755{
4756 unsigned int n_planes;
01f1ba30 4757 unsigned char *xrm_option;
b9dc4443 4758 struct x_display_info *dpyinfo;
01f1ba30
JB
4759
4760 CHECK_STRING (display, 0);
d387c960
JB
4761 if (! NILP (xrm_string))
4762 CHECK_STRING (xrm_string, 1);
01f1ba30 4763
806048df
RS
4764 if (! EQ (Vwindow_system, intern ("x")))
4765 error ("Not using X Windows");
4766
d387c960
JB
4767 if (! NILP (xrm_string))
4768 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
01f1ba30
JB
4769 else
4770 xrm_option = (unsigned char *) 0;
d387c960 4771
b7975ee4
KH
4772 /* Use this general default value to start with. */
4773 Vx_resource_name = Vinvocation_name;
4774
d387c960
JB
4775 validate_x_resource_name ();
4776
e1b1bee8 4777 /* This is what opens the connection and sets x_current_display.
b9dc4443
RS
4778 This also initializes many symbols, such as those used for input. */
4779 dpyinfo = x_term_init (display, xrm_option,
b7975ee4 4780 (char *) XSTRING (Vx_resource_name)->data);
f1c16f36 4781
08a90d6a
RS
4782 if (dpyinfo == 0)
4783 {
4784 if (!NILP (must_succeed))
1b4ec1c8
KH
4785 fatal ("Cannot connect to X server %s.\n\
4786Check the DISPLAY environment variable or use `-d'.\n\
4787Also use the `xhost' program to verify that it is set to permit\n\
4788connections from your machine.\n",
08a90d6a
RS
4789 XSTRING (display)->data);
4790 else
1b4ec1c8 4791 error ("Cannot connect to X server %s", XSTRING (display)->data);
08a90d6a
RS
4792 }
4793
b9dc4443 4794 x_in_use = 1;
01f1ba30 4795
b9dc4443 4796 XSETFASTINT (Vwindow_system_version, 11);
01f1ba30
JB
4797 return Qnil;
4798}
4799
08a90d6a
RS
4800DEFUN ("x-close-connection", Fx_close_connection,
4801 Sx_close_connection, 1, 1, 0,
4802 "Close the connection to DISPLAY's X server.\n\
4803For DISPLAY, specify either a frame or a display name (a string).\n\
4804If DISPLAY is nil, that stands for the selected frame's display.")
4805 (display)
4806 Lisp_Object display;
01f1ba30 4807{
08a90d6a
RS
4808 struct x_display_info *dpyinfo = check_x_display_info (display);
4809 struct x_display_info *tail;
4810 int i;
3457bc6e 4811
08a90d6a
RS
4812 if (dpyinfo->reference_count > 0)
4813 error ("Display still has frames on it");
01f1ba30 4814
08a90d6a
RS
4815 BLOCK_INPUT;
4816 /* Free the fonts in the font table. */
4817 for (i = 0; i < dpyinfo->n_fonts; i++)
01f1ba30 4818 {
08a90d6a
RS
4819 if (dpyinfo->font_table[i].name)
4820 free (dpyinfo->font_table[i].name);
4821 /* Don't free the full_name string;
4822 it is always shared with something else. */
4823 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
01f1ba30 4824 }
08a90d6a
RS
4825 x_destroy_all_bitmaps (dpyinfo);
4826 XSetCloseDownMode (dpyinfo->display, DestroyAll);
82c90203
RS
4827
4828#ifdef USE_X_TOOLKIT
4829 XtCloseDisplay (dpyinfo->display);
4830#else
08a90d6a 4831 XCloseDisplay (dpyinfo->display);
82c90203 4832#endif
08a90d6a
RS
4833
4834 x_delete_display (dpyinfo);
4835 UNBLOCK_INPUT;
3457bc6e 4836
01f1ba30
JB
4837 return Qnil;
4838}
4839
08a90d6a
RS
4840DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
4841 "Return the list of display names that Emacs has connections to.")
4842 ()
4843{
4844 Lisp_Object tail, result;
4845
4846 result = Qnil;
4847 for (tail = x_display_name_list; ! NILP (tail); tail = XCONS (tail)->cdr)
4848 result = Fcons (XCONS (XCONS (tail)->car)->car, result);
4849
4850 return result;
4851}
4852
4853DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
4854 "If ON is non-nil, report X errors as soon as the erring request is made.\n\
01f1ba30
JB
4855If ON is nil, allow buffering of requests.\n\
4856Turning on synchronization prohibits the Xlib routines from buffering\n\
4857requests and seriously degrades performance, but makes debugging much\n\
7a9a9813 4858easier.\n\
08a90d6a
RS
4859The optional second argument DISPLAY specifies which display to act on.\n\
4860DISPLAY should be either a frame or a display name (a string).\n\
4861If DISPLAY is omitted or nil, that stands for the selected frame's display.")
4862 (on, display)
4863 Lisp_Object display, on;
01f1ba30 4864{
08a90d6a 4865 struct x_display_info *dpyinfo = check_x_display_info (display);
11ae94fe 4866
b9dc4443 4867 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
01f1ba30
JB
4868
4869 return Qnil;
4870}
4871
b9dc4443 4872/* Wait for responses to all X commands issued so far for frame F. */
6b7b1820
RS
4873
4874void
b9dc4443
RS
4875x_sync (f)
4876 FRAME_PTR f;
6b7b1820 4877{
4e87f4d2 4878 BLOCK_INPUT;
b9dc4443 4879 XSync (FRAME_X_DISPLAY (f), False);
4e87f4d2 4880 UNBLOCK_INPUT;
6b7b1820 4881}
01f1ba30
JB
4882\f
4883syms_of_xfns ()
4884{
01f1ba30 4885 /* This is zero if not using X windows. */
b9dc4443 4886 x_in_use = 0;
f1c16f36 4887
f9942c9e
JB
4888 /* The section below is built by the lisp expression at the top of the file,
4889 just above where these variables are declared. */
4890 /*&&& init symbols here &&&*/
4891 Qauto_raise = intern ("auto-raise");
4892 staticpro (&Qauto_raise);
4893 Qauto_lower = intern ("auto-lower");
4894 staticpro (&Qauto_lower);
4895 Qbackground_color = intern ("background-color");
4896 staticpro (&Qbackground_color);
dbc4e1c1
JB
4897 Qbar = intern ("bar");
4898 staticpro (&Qbar);
f9942c9e
JB
4899 Qborder_color = intern ("border-color");
4900 staticpro (&Qborder_color);
4901 Qborder_width = intern ("border-width");
4902 staticpro (&Qborder_width);
dbc4e1c1
JB
4903 Qbox = intern ("box");
4904 staticpro (&Qbox);
f9942c9e
JB
4905 Qcursor_color = intern ("cursor-color");
4906 staticpro (&Qcursor_color);
dbc4e1c1
JB
4907 Qcursor_type = intern ("cursor-type");
4908 staticpro (&Qcursor_type);
f9942c9e
JB
4909 Qfont = intern ("font");
4910 staticpro (&Qfont);
4911 Qforeground_color = intern ("foreground-color");
4912 staticpro (&Qforeground_color);
4913 Qgeometry = intern ("geometry");
4914 staticpro (&Qgeometry);
f9942c9e
JB
4915 Qicon_left = intern ("icon-left");
4916 staticpro (&Qicon_left);
4917 Qicon_top = intern ("icon-top");
4918 staticpro (&Qicon_top);
4919 Qicon_type = intern ("icon-type");
4920 staticpro (&Qicon_type);
80534dd6
KH
4921 Qicon_name = intern ("icon-name");
4922 staticpro (&Qicon_name);
f9942c9e
JB
4923 Qinternal_border_width = intern ("internal-border-width");
4924 staticpro (&Qinternal_border_width);
4925 Qleft = intern ("left");
4926 staticpro (&Qleft);
4927 Qmouse_color = intern ("mouse-color");
4928 staticpro (&Qmouse_color);
baaed68e
JB
4929 Qnone = intern ("none");
4930 staticpro (&Qnone);
f9942c9e
JB
4931 Qparent_id = intern ("parent-id");
4932 staticpro (&Qparent_id);
4701395c
KH
4933 Qscroll_bar_width = intern ("scroll-bar-width");
4934 staticpro (&Qscroll_bar_width);
8af1d7ca
JB
4935 Qsuppress_icon = intern ("suppress-icon");
4936 staticpro (&Qsuppress_icon);
f9942c9e
JB
4937 Qtop = intern ("top");
4938 staticpro (&Qtop);
01f1ba30 4939 Qundefined_color = intern ("undefined-color");
f9942c9e 4940 staticpro (&Qundefined_color);
a3c87d4e
JB
4941 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
4942 staticpro (&Qvertical_scroll_bars);
49795535
JB
4943 Qvisibility = intern ("visibility");
4944 staticpro (&Qvisibility);
f9942c9e
JB
4945 Qwindow_id = intern ("window-id");
4946 staticpro (&Qwindow_id);
4947 Qx_frame_parameter = intern ("x-frame-parameter");
4948 staticpro (&Qx_frame_parameter);
9ef48a9d
RS
4949 Qx_resource_name = intern ("x-resource-name");
4950 staticpro (&Qx_resource_name);
4fe1de12
RS
4951 Quser_position = intern ("user-position");
4952 staticpro (&Quser_position);
4953 Quser_size = intern ("user-size");
4954 staticpro (&Quser_size);
b9dc4443
RS
4955 Qdisplay = intern ("display");
4956 staticpro (&Qdisplay);
f9942c9e
JB
4957 /* This is the end of symbol initialization. */
4958
01f1ba30
JB
4959 Fput (Qundefined_color, Qerror_conditions,
4960 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
4961 Fput (Qundefined_color, Qerror_message,
4962 build_string ("Undefined color"));
4963
f9942c9e
JB
4964 init_x_parm_symbols ();
4965
f1c7b5a6
RS
4966 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
4967 "List of directories to search for bitmap files for X.");
e241c09b 4968 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
f1c7b5a6 4969
16ae08a9 4970 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
d387c960 4971 "The shape of the pointer when over text.\n\
af01ef26
RS
4972Changing the value does not affect existing frames\n\
4973unless you set the mouse color.");
01f1ba30
JB
4974 Vx_pointer_shape = Qnil;
4975
d387c960
JB
4976 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
4977 "The name Emacs uses to look up X resources; for internal use only.\n\
4978`x-get-resource' uses this as the first component of the instance name\n\
4979when requesting resource values.\n\
4980Emacs initially sets `x-resource-name' to the name under which Emacs\n\
4981was invoked, or to the value specified with the `-name' or `-rn'\n\
4982switches, if present.");
4983 Vx_resource_name = Qnil;
ac63d3d6 4984
ca0ecbf5 4985#if 0 /* This doesn't really do anything. */
01f1ba30 4986 DEFVAR_INT ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
ca0ecbf5
RS
4987 "The shape of the pointer when not over text.\n\
4988This variable takes effect when you create a new frame\n\
4989or when you set the mouse color.");
af01ef26 4990#endif
01f1ba30
JB
4991 Vx_nontext_pointer_shape = Qnil;
4992
ca0ecbf5 4993#if 0 /* This doesn't really do anything. */
01f1ba30 4994 DEFVAR_INT ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
ca0ecbf5
RS
4995 "The shape of the pointer when over the mode line.\n\
4996This variable takes effect when you create a new frame\n\
4997or when you set the mouse color.");
af01ef26 4998#endif
01f1ba30
JB
4999 Vx_mode_pointer_shape = Qnil;
5000
ca0ecbf5
RS
5001 DEFVAR_INT ("x-sensitive-text-pointer-shape",
5002 &Vx_sensitive_text_pointer_shape,
5003 "The shape of the pointer when over mouse-sensitive text.\n\
5004This variable takes effect when you create a new frame\n\
5005or when you set the mouse color.");
5006 Vx_sensitive_text_pointer_shape = Qnil;
95f80c78 5007
01f1ba30
JB
5008 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
5009 "A string indicating the foreground color of the cursor box.");
5010 Vx_cursor_fore_pixel = Qnil;
5011
01f1ba30 5012 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
2d38195d
RS
5013 "Non-nil if no X window manager is in use.\n\
5014Emacs doesn't try to figure this out; this is always nil\n\
5015unless you set it to something else.");
5016 /* We don't have any way to find this out, so set it to nil
5017 and maybe the user would like to set it to t. */
5018 Vx_no_window_manager = Qnil;
1d3dac41 5019
1d3dac41 5020#ifdef USE_X_TOOLKIT
f1d238ef 5021 Fprovide (intern ("x-toolkit"));
1d3dac41 5022#endif
5b827abb
KH
5023#ifdef USE_MOTIF
5024 Fprovide (intern ("motif"));
5025#endif
01f1ba30 5026
01f1ba30 5027 defsubr (&Sx_get_resource);
85ffea93 5028#if 0
01f1ba30
JB
5029 defsubr (&Sx_draw_rectangle);
5030 defsubr (&Sx_erase_rectangle);
5031 defsubr (&Sx_contour_region);
5032 defsubr (&Sx_uncontour_region);
85ffea93 5033#endif
f0614854 5034 defsubr (&Sx_list_fonts);
d0c9d219
RS
5035 defsubr (&Sx_display_color_p);
5036 defsubr (&Sx_display_grayscale_p);
8af1d7ca 5037 defsubr (&Sx_color_defined_p);
e12d55b2 5038 defsubr (&Sx_color_values);
9d317b2c 5039 defsubr (&Sx_server_max_request_size);
41beb8fc
RS
5040 defsubr (&Sx_server_vendor);
5041 defsubr (&Sx_server_version);
5042 defsubr (&Sx_display_pixel_width);
5043 defsubr (&Sx_display_pixel_height);
5044 defsubr (&Sx_display_mm_width);
5045 defsubr (&Sx_display_mm_height);
5046 defsubr (&Sx_display_screens);
5047 defsubr (&Sx_display_planes);
5048 defsubr (&Sx_display_color_cells);
5049 defsubr (&Sx_display_visual_class);
5050 defsubr (&Sx_display_backing_store);
5051 defsubr (&Sx_display_save_under);
01567351 5052#if 0
9d04a87a
RS
5053 defsubr (&Sx_rebind_key);
5054 defsubr (&Sx_rebind_keys);
01f1ba30 5055 defsubr (&Sx_track_pointer);
01f1ba30
JB
5056 defsubr (&Sx_grab_pointer);
5057 defsubr (&Sx_ungrab_pointer);
01f1ba30 5058#endif
8af1d7ca 5059 defsubr (&Sx_parse_geometry);
f676886a
JB
5060 defsubr (&Sx_create_frame);
5061 defsubr (&Sfocus_frame);
5062 defsubr (&Sunfocus_frame);
06ef7355 5063#if 0
01f1ba30 5064 defsubr (&Sx_horizontal_line);
06ef7355 5065#endif
01f1ba30 5066 defsubr (&Sx_open_connection);
08a90d6a
RS
5067 defsubr (&Sx_close_connection);
5068 defsubr (&Sx_display_list);
01f1ba30 5069 defsubr (&Sx_synchronize);
01f1ba30
JB
5070}
5071
5072#endif /* HAVE_X_WINDOWS */