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