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