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