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