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