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