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