xfns.c 297 KB
Newer Older
Jim Blandy's avatar
Jim Blandy committed
1
/* Functions for the X window system.
Dave Love's avatar
Dave Love committed
2
   Copyright (C) 1989, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 01, 02, 03
3
     Free Software Foundation.
Jim Blandy's avatar
Jim Blandy committed
4 5 6 7 8

This file is part of GNU Emacs.

GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Jim Blandy's avatar
Jim Blandy committed
9
the Free Software Foundation; either version 2, or (at your option)
Jim Blandy's avatar
Jim Blandy committed
10 11 12 13 14 15 16 17 18
any later version.

GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING.  If not, write to
19 20
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.  */
Jim Blandy's avatar
Jim Blandy committed
21

Richard M. Stallman's avatar
Richard M. Stallman committed
22
#include <config.h>
23
#include <signal.h>
24
#include <stdio.h>
25
#include <math.h>
Richard M. Stallman's avatar
Richard M. Stallman committed
26

27 28 29 30
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

31
/* This makes the fields of a Display accessible, in Xlib header files.  */
32

33 34
#define XLIB_ILLEGAL_ACCESS

Jim Blandy's avatar
Jim Blandy committed
35 36
#include "lisp.h"
#include "xterm.h"
Jim Blandy's avatar
Jim Blandy committed
37
#include "frame.h"
Jim Blandy's avatar
Jim Blandy committed
38 39
#include "window.h"
#include "buffer.h"
Kenichi Handa's avatar
Kenichi Handa committed
40
#include "intervals.h"
Jim Blandy's avatar
Jim Blandy committed
41
#include "dispextern.h"
Jim Blandy's avatar
Jim Blandy committed
42
#include "keyboard.h"
43
#include "blockinput.h"
44
#include <epaths.h>
Karl Heuer's avatar
Karl Heuer committed
45
#include "charset.h"
Kenichi Handa's avatar
Kenichi Handa committed
46
#include "coding.h"
Karl Heuer's avatar
Karl Heuer committed
47
#include "fontset.h"
48 49
#include "systime.h"
#include "termhooks.h"
50
#include "atimer.h"
Jim Blandy's avatar
Jim Blandy committed
51 52

#ifdef HAVE_X_WINDOWS
53 54

#include <ctype.h>
55 56
#include <sys/types.h>
#include <sys/stat.h>
Jim Blandy's avatar
Jim Blandy committed
57

58
#ifndef VMS
59
#if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work.  */
60 61
#include "bitmaps/gray.xbm"
#else
Jim Blandy's avatar
Jim Blandy committed
62
#include <X11/bitmaps/gray>
63
#endif
64 65 66
#else
#include "[.bitmaps]gray.xbm"
#endif
Jim Blandy's avatar
Jim Blandy committed
67

Jan Djärv's avatar
Jan Djärv committed
68 69 70 71
#ifdef USE_GTK
#include "gtkutil.h"
#endif

72 73 74
#ifdef USE_X_TOOLKIT
#include <X11/Shell.h>

75
#ifndef USE_MOTIF
76 77
#include <X11/Xaw/Paned.h>
#include <X11/Xaw/Label.h>
78
#endif /* USE_MOTIF */
79 80 81 82 83 84 85 86 87 88 89 90 91

#ifdef USG
#undef USG	/* ####KLUDGE for Solaris 2.2 and up */
#include <X11/Xos.h>
#define USG
#else
#include <X11/Xos.h>
#endif

#include "widget.h"

#include "../lwlib/lwlib.h"

92 93 94 95 96 97
#ifdef USE_MOTIF
#include <Xm/Xm.h>
#include <Xm/DialogS.h>
#include <Xm/FileSB.h>
#endif

98 99
/* Do the EDITRES protocol if running X11R5
   Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
100

101
#if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
102
#define HACK_EDITRES
103
extern void _XEditResCheckMessages ();
104 105
#endif /* R5 + Athena */

106 107
/* Unique id counter for widgets created by the Lucid Widget Library.  */

108 109
extern LWLIB_ID widget_id_tick;

110
#ifdef USE_LUCID
111
/* This is part of a kludge--see lwlib/xlwmenu.c.  */
112
extern XFontStruct *xlwmenu_default_font;
113
#endif
114

115
extern void free_frame_menubar ();
116
extern double atof ();
117

118 119 120 121 122 123 124 125
#ifdef USE_MOTIF

/* LessTif/Motif version info.  */

static Lisp_Object Vmotif_version_string;

#endif /* USE_MOTIF */

126 127
#endif /* USE_X_TOOLKIT */

128 129 130 131 132 133 134 135
#ifdef USE_GTK

/* GTK+ version info */

static Lisp_Object Vgtk_version_string;

#endif /* USE_GTK */

Richard M. Stallman's avatar
Richard M. Stallman committed
136 137 138 139 140 141
#ifdef HAVE_X11R4
#define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
#else
#define MAXREQUEST(dpy) ((dpy)->max_request_size)
#endif

142 143 144 145 146 147
/* The gray bitmap `bitmaps/gray'.  This is done because xterm.c uses
   it, and including `bitmaps/gray' more than once is a problem when
   config.h defines `static' as an empty replacement string.  */

int gray_bitmap_width = gray_width;
int gray_bitmap_height = gray_height;
148
char *gray_bitmap_bits = gray_bits;
149

150
/* Non-zero means we're allowed to display an hourglass cursor.  */
151

152
int display_hourglass_p;
153

Jim Blandy's avatar
Jim Blandy committed
154
/* The background and shape of the mouse pointer, and shape when not
155
   over text or in the modeline.  */
156

Jim Blandy's avatar
Jim Blandy committed
157
Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
158
Lisp_Object Vx_hourglass_pointer_shape;
159

160
/* The shape when over mouse-sensitive text.  */
161

162
Lisp_Object Vx_sensitive_text_pointer_shape;
Jim Blandy's avatar
Jim Blandy committed
163

164 165 166 167 168
/* If non-nil, the pointer shape to indicate that windows can be
   dragged horizontally.  */

Lisp_Object Vx_window_horizontal_drag_shape;

169
/* Color of chars displayed in cursor box.  */
170

Jim Blandy's avatar
Jim Blandy committed
171 172
Lisp_Object Vx_cursor_fore_pixel;

173
/* Nonzero if using X.  */
174

175
static int x_in_use;
Jim Blandy's avatar
Jim Blandy committed
176

177
/* Non nil if no window manager is in use.  */
178

Jim Blandy's avatar
Jim Blandy committed
179 180
Lisp_Object Vx_no_window_manager;

Richard M. Stallman's avatar
Richard M. Stallman committed
181
/* Search path for bitmap files.  */
182

Richard M. Stallman's avatar
Richard M. Stallman committed
183 184
Lisp_Object Vx_bitmap_file_path;

Karl Heuer's avatar
Karl Heuer committed
185
/* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.  */
186

Karl Heuer's avatar
Karl Heuer committed
187 188
Lisp_Object Vx_pixel_size_width_font_regexp;

189
Lisp_Object Qnone;
190
Lisp_Object Qsuppress_icon;
Jim Blandy's avatar
Jim Blandy committed
191
Lisp_Object Qundefined_color;
192
Lisp_Object Qcenter;
193
Lisp_Object Qcompound_text, Qcancel_timer;
Jim Blandy's avatar
Jim Blandy committed
194

195
/* In dispnew.c */
196

Jim Blandy's avatar
Jim Blandy committed
197 198
extern Lisp_Object Vwindow_system_version;

199
/* The below are defined in frame.c.  */
200

201
#if GLYPH_DEBUG
202 203 204 205
int image_cache_refcount, dpyinfo_refcount;
#endif


Jim Blandy's avatar
Jim Blandy committed
206

Richard M. Stallman's avatar
Richard M. Stallman committed
207
/* Error if we are not connected to X.  */
208

Karl Heuer's avatar
Karl Heuer committed
209
void
Richard M. Stallman's avatar
Richard M. Stallman committed
210 211
check_x ()
{
212
  if (! x_in_use)
Richard M. Stallman's avatar
Richard M. Stallman committed
213 214 215
    error ("X windows are not in use or not initialized");
}

216 217
/* Nonzero if we can use mouse menus.
   You should not call this unless HAVE_MENUS is defined.  */
218 219

int
220
have_menus_p ()
221
{
222 223 224 225 226 227 228 229 230 231 232 233 234
  return x_in_use;
}

/* Extract a frame as a FRAME_PTR, defaulting to the selected frame
   and checking validity for X.  */

FRAME_PTR
check_x_frame (frame)
     Lisp_Object frame;
{
  FRAME_PTR f;

  if (NILP (frame))
Gerd Moellmann's avatar
Gerd Moellmann committed
235
    frame = selected_frame;
236
  CHECK_LIVE_FRAME (frame);
Gerd Moellmann's avatar
Gerd Moellmann committed
237
  f = XFRAME (frame);
238
  if (! FRAME_X_P (f))
239
    error ("Non-X frame used");
240
  return f;
241 242
}

243 244 245 246
/* Let the user specify an X display with a frame.
   nil stands for the selected frame--or, if that is not an X frame,
   the first X display on the list.  */

247
struct x_display_info *
248 249 250
check_x_display_info (frame)
     Lisp_Object frame;
{
251
  struct x_display_info *dpyinfo = NULL;
252

253 254
  if (NILP (frame))
    {
Gerd Moellmann's avatar
Gerd Moellmann committed
255
      struct frame *sf = XFRAME (selected_frame);
256

Gerd Moellmann's avatar
Gerd Moellmann committed
257
      if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
258
	dpyinfo = FRAME_X_DISPLAY_INFO (sf);
259
      else if (x_display_list != 0)
260
	dpyinfo = x_display_list;
261 262 263 264
      else
	error ("X windows are not in use or not initialized");
    }
  else if (STRINGP (frame))
265
    dpyinfo = x_display_info_for_name (frame);
266 267
  else
    {
268
      FRAME_PTR f = check_x_frame (frame);
269
      dpyinfo = FRAME_X_DISPLAY_INFO (f);
270
    }
271 272

  return dpyinfo;
273
}
274

275

Jim Blandy's avatar
Jim Blandy committed
276 277
/* Return the Emacs frame-object corresponding to an X window.
   It could be the frame's main window or an icon window.  */
Jim Blandy's avatar
Jim Blandy committed
278

279
/* This function can be called during GC, so use GC_xxx type test macros.  */
280

Jim Blandy's avatar
Jim Blandy committed
281
struct frame *
282 283
x_window_to_frame (dpyinfo, wdesc)
     struct x_display_info *dpyinfo;
Jim Blandy's avatar
Jim Blandy committed
284 285
     int wdesc;
{
Jim Blandy's avatar
Jim Blandy committed
286 287
  Lisp_Object tail, frame;
  struct frame *f;
Jim Blandy's avatar
Jim Blandy committed
288

289
  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
Jim Blandy's avatar
Jim Blandy committed
290
    {
291
      frame = XCAR (tail);
292
      if (!GC_FRAMEP (frame))
Jim Blandy's avatar
Jim Blandy committed
293
        continue;
Jim Blandy's avatar
Jim Blandy committed
294
      f = XFRAME (frame);
295
      if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
296
	continue;
297
      if (f->output_data.x->hourglass_window == wdesc)
298
	return f;
299
#ifdef USE_X_TOOLKIT
300
      if ((f->output_data.x->edit_widget
301
	   && XtWindow (f->output_data.x->edit_widget) == wdesc)
302 303 304
	  /* A tooltip frame?  */
	  || (!f->output_data.x->edit_widget
	      && FRAME_X_WINDOW (f) == wdesc)
305
          || f->output_data.x->icon_desc == wdesc)
306 307
        return f;
#else /* not USE_X_TOOLKIT */
Jan Djärv's avatar
Jan Djärv committed
308 309 310 311 312 313 314 315 316
#ifdef USE_GTK
      if (f->output_data.x->edit_widget)
      {
        GtkWidget *gwdesc = xg_win_to_widget (wdesc);
        struct x_output *x = f->output_data.x;
        if (gwdesc != 0 && gwdesc == x->edit_widget)
          return f;
      }
#endif /* USE_GTK */
317
      if (FRAME_X_WINDOW (f) == wdesc
318
          || f->output_data.x->icon_desc == wdesc)
Jim Blandy's avatar
Jim Blandy committed
319
        return f;
320 321 322 323 324
#endif /* not USE_X_TOOLKIT */
    }
  return 0;
}

Jan Djärv's avatar
Jan Djärv committed
325
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
326 327 328 329
/* Like x_window_to_frame but also compares the window with the widget's
   windows.  */

struct frame *
330 331
x_any_window_to_frame (dpyinfo, wdesc)
     struct x_display_info *dpyinfo;
332 333 334
     int wdesc;
{
  Lisp_Object tail, frame;
335
  struct frame *f, *found;
336
  struct x_output *x;
337

338 339
  found = NULL;
  for (tail = Vframe_list; GC_CONSP (tail) && !found; tail = XCDR (tail))
340
    {
341
      frame = XCAR (tail);
342
      if (!GC_FRAMEP (frame))
343
        continue;
344

345
      f = XFRAME (frame);
346
      if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
347
	{
348 349
	  /* This frame matches if the window is any of its widgets.  */
	  x = f->output_data.x;
350
	  if (x->hourglass_window == wdesc)
351 352 353
	    found = f;
	  else if (x->widget)
	    {
Jan Djärv's avatar
Jan Djärv committed
354 355 356 357 358 359 360 361 362
#ifdef USE_GTK
              GtkWidget *gwdesc = xg_win_to_widget (wdesc);
              if (gwdesc != 0
                  && (gwdesc == x->widget
                      || gwdesc == x->edit_widget
                      || gwdesc == x->vbox_widget
                      || gwdesc == x->menubar_widget))
                found = f;
#else
363 364
	      if (wdesc == XtWindow (x->widget)
		  || wdesc == XtWindow (x->column_widget)
365 366 367 368 369
		  || wdesc == XtWindow (x->edit_widget))
		found = f;
	      /* Match if the window is this frame's menubar.  */
	      else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
		found = f;
Jan Djärv's avatar
Jan Djärv committed
370
#endif
371 372 373 374
	    }
	  else if (FRAME_X_WINDOW (f) == wdesc)
	    /* A tooltip frame.  */
	    found = f;
375
	}
Jim Blandy's avatar
Jim Blandy committed
376
    }
377

378
  return found;
Jim Blandy's avatar
Jim Blandy committed
379
}
380

381 382 383 384 385 386 387 388 389
/* Likewise, but exclude the menu bar widget.  */

struct frame *
x_non_menubar_window_to_frame (dpyinfo, wdesc)
     struct x_display_info *dpyinfo;
     int wdesc;
{
  Lisp_Object tail, frame;
  struct frame *f;
390
  struct x_output *x;
391

392
  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
393
    {
394
      frame = XCAR (tail);
395 396 397
      if (!GC_FRAMEP (frame))
        continue;
      f = XFRAME (frame);
398
      if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
399
	continue;
400
      x = f->output_data.x;
401
      /* This frame matches if the window is any of its widgets.  */
402
      if (x->hourglass_window == wdesc)
403 404
	return f;
      else if (x->widget)
405
	{
Jan Djärv's avatar
Jan Djärv committed
406 407 408 409 410 411 412 413
#ifdef USE_GTK
          GtkWidget *gwdesc = xg_win_to_widget (wdesc);
          if (gwdesc != 0
              && (gwdesc == x->widget
                  || gwdesc == x->edit_widget
                  || gwdesc == x->vbox_widget))
            return f;
#else
414 415
	  if (wdesc == XtWindow (x->widget)
	      || wdesc == XtWindow (x->column_widget)
416 417
	      || wdesc == XtWindow (x->edit_widget))
	    return f;
Jan Djärv's avatar
Jan Djärv committed
418
#endif
419 420 421
	}
      else if (FRAME_X_WINDOW (f) == wdesc)
	/* A tooltip frame.  */
422 423 424 425 426
	return f;
    }
  return 0;
}

427 428 429 430 431 432 433 434 435
/* Likewise, but consider only the menu bar widget.  */

struct frame *
x_menubar_window_to_frame (dpyinfo, wdesc)
     struct x_display_info *dpyinfo;
     int wdesc;
{
  Lisp_Object tail, frame;
  struct frame *f;
436
  struct x_output *x;
437

438
  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
439
    {
440
      frame = XCAR (tail);
441 442 443
      if (!GC_FRAMEP (frame))
        continue;
      f = XFRAME (frame);
444
      if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
445
	continue;
446
      x = f->output_data.x;
447
      /* Match if the window is this frame's menubar.  */
Jan Djärv's avatar
Jan Djärv committed
448 449 450 451 452
#ifdef USE_GTK
      if (x->menubar_widget)
        {
          GtkWidget *gwdesc = xg_win_to_widget (wdesc);
          int found = 0;
453

Jan Djärv's avatar
Jan Djärv committed
454 455 456 457 458 459 460 461 462
          BLOCK_INPUT;
          if (gwdesc != 0
              && (gwdesc == x->menubar_widget
                  || gtk_widget_get_parent (gwdesc) == x->menubar_widget))
            found = 1;
          UNBLOCK_INPUT;
          if (found) return f;
        }
#else
463 464
      if (x->menubar_widget
	  && lw_window_is_in_menubar (wdesc, x->menubar_widget))
465
	return f;
Jan Djärv's avatar
Jan Djärv committed
466
#endif
467 468 469 470
    }
  return 0;
}

471 472 473 474
/* Return the frame whose principal (outermost) window is WDESC.
   If WDESC is some other (smaller) window, we return 0.  */

struct frame *
475 476
x_top_window_to_frame (dpyinfo, wdesc)
     struct x_display_info *dpyinfo;
477 478 479 480
     int wdesc;
{
  Lisp_Object tail, frame;
  struct frame *f;
481
  struct x_output *x;
482

483
  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
484
    {
485
      frame = XCAR (tail);
486
      if (!GC_FRAMEP (frame))
487 488
        continue;
      f = XFRAME (frame);
489
      if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
490
	continue;
491
      x = f->output_data.x;
492 493 494 495

      if (x->widget)
	{
	  /* This frame matches if the window is its topmost widget.  */
Jan Djärv's avatar
Jan Djärv committed
496 497 498 499 500
#ifdef USE_GTK
          GtkWidget *gwdesc = xg_win_to_widget (wdesc);
          if (gwdesc == x->widget)
            return f;
#else
501 502
	  if (wdesc == XtWindow (x->widget))
	    return f;
503 504 505
#if 0 /* I don't know why it did this,
	 but it seems logically wrong,
	 and it causes trouble for MapNotify events.  */
506
	  /* Match if the window is this frame's menubar.  */
507
	  if (x->menubar_widget
508 509
	      && wdesc == XtWindow (x->menubar_widget))
	    return f;
Jan Djärv's avatar
Jan Djärv committed
510
#endif
511
#endif
512 513 514 515
	}
      else if (FRAME_X_WINDOW (f) == wdesc)
	/* Tooltip frame.  */
	return f;
516 517 518
    }
  return 0;
}
Jan Djärv's avatar
Jan Djärv committed
519
#endif /* USE_X_TOOLKIT || USE_GTK */
Jim Blandy's avatar
Jim Blandy committed
520

521 522 523 524 525 526 527 528 529 530 531


/* Code to deal with bitmaps.  Bitmaps are referenced by their bitmap
   id, which is just an int that this section returns.  Bitmaps are
   reference counted so they can be shared among frames.

   Bitmap indices are guaranteed to be > 0, so a negative number can
   be used to indicate no bitmap.

   If you use x_create_bitmap_from_data, then you must keep track of
   the bitmaps yourself.  That is, creating a bitmap from the same
532
   data more than once will not be caught.  */
533 534


Richard M. Stallman's avatar
Richard M. Stallman committed
535 536 537 538 539 540 541
/* Functions to access the contents of a bitmap, given an id.  */

int
x_bitmap_height (f, id)
     FRAME_PTR f;
     int id;
{
542
  return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
Richard M. Stallman's avatar
Richard M. Stallman committed
543 544 545 546 547 548 549
}

int
x_bitmap_width (f, id)
     FRAME_PTR f;
     int id;
{
550
  return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
Richard M. Stallman's avatar
Richard M. Stallman committed
551 552 553 554 555 556 557
}

int
x_bitmap_pixmap (f, id)
     FRAME_PTR f;
     int id;
{
558
  return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
Richard M. Stallman's avatar
Richard M. Stallman committed
559 560
}

561 562 563 564 565 566 567 568
int
x_bitmap_mask (f, id)
     FRAME_PTR f;
     int id;
{
  return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].mask;
}

Richard M. Stallman's avatar
Richard M. Stallman committed
569

570 571 572
/* Allocate a new bitmap record.  Returns index of new record.  */

static int
573 574
x_allocate_bitmap_record (f)
     FRAME_PTR f;
575
{
576 577 578 579
  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
  int i;

  if (dpyinfo->bitmaps == NULL)
580
    {
581 582 583 584
      dpyinfo->bitmaps_size = 10;
      dpyinfo->bitmaps
	= (struct x_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
      dpyinfo->bitmaps_last = 1;
585 586 587
      return 1;
    }

588 589
  if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
    return ++dpyinfo->bitmaps_last;
590

591 592 593
  for (i = 0; i < dpyinfo->bitmaps_size; ++i)
    if (dpyinfo->bitmaps[i].refcount == 0)
      return i + 1;
594

595 596 597 598 599
  dpyinfo->bitmaps_size *= 2;
  dpyinfo->bitmaps
    = (struct x_bitmap_record *) xrealloc (dpyinfo->bitmaps,
					   dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
  return ++dpyinfo->bitmaps_last;
600 601 602 603 604
}

/* Add one reference to the reference count of the bitmap with id ID.  */

void
Richard M. Stallman's avatar
Richard M. Stallman committed
605 606
x_reference_bitmap (f, id)
     FRAME_PTR f;
607 608
     int id;
{
609
  ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
610 611 612 613 614 615 616 617 618 619
}

/* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS.  */

int
x_create_bitmap_from_data (f, bits, width, height)
     struct frame *f;
     char *bits;
     unsigned int width, height;
{
620
  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
621 622 623
  Pixmap bitmap;
  int id;

624
  bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
625 626
				  bits, width, height);

627 628


629 630 631
  if (! bitmap)
    return -1;

632 633
  id = x_allocate_bitmap_record (f);
  dpyinfo->bitmaps[id - 1].pixmap = bitmap;
634
  dpyinfo->bitmaps[id - 1].have_mask = 0;
635 636 637 638 639
  dpyinfo->bitmaps[id - 1].file = NULL;
  dpyinfo->bitmaps[id - 1].refcount = 1;
  dpyinfo->bitmaps[id - 1].depth = 1;
  dpyinfo->bitmaps[id - 1].height = height;
  dpyinfo->bitmaps[id - 1].width = width;
640 641 642 643 644 645 646 647 648

  return id;
}

/* Create bitmap from file FILE for frame F.  */

int
x_create_bitmap_from_file (f, file)
     struct frame *f;
Richard M. Stallman's avatar
Richard M. Stallman committed
649
     Lisp_Object file;
650
{
651
  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
652 653 654
  unsigned int width, height;
  Pixmap bitmap;
  int xhot, yhot, result, id;
Richard M. Stallman's avatar
Richard M. Stallman committed
655 656 657
  Lisp_Object found;
  int fd;
  char *filename;
658 659

  /* Look for an existing bitmap with the same name.  */
660
  for (id = 0; id < dpyinfo->bitmaps_last; ++id)
661
    {
662 663
      if (dpyinfo->bitmaps[id].refcount
	  && dpyinfo->bitmaps[id].file
664
	  && !strcmp (dpyinfo->bitmaps[id].file, (char *) SDATA (file)))
665
	{
666
	  ++dpyinfo->bitmaps[id].refcount;
667 668 669 670
	  return id + 1;
	}
    }

Richard M. Stallman's avatar
Richard M. Stallman committed
671
  /* Search bitmap-file-path for the file, if appropriate.  */
672
  fd = openp (Vx_bitmap_file_path, file, Qnil, &found, Qnil);
Richard M. Stallman's avatar
Richard M. Stallman committed
673 674
  if (fd < 0)
    return -1;
675
  emacs_close (fd);
Richard M. Stallman's avatar
Richard M. Stallman committed
676

677
  filename = (char *) SDATA (found);
Richard M. Stallman's avatar
Richard M. Stallman committed
678

679
  result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
Richard M. Stallman's avatar
Richard M. Stallman committed
680
			    filename, &width, &height, &bitmap, &xhot, &yhot);
681 682 683
  if (result != BitmapSuccess)
    return -1;

684 685
  id = x_allocate_bitmap_record (f);
  dpyinfo->bitmaps[id - 1].pixmap = bitmap;
686
  dpyinfo->bitmaps[id - 1].have_mask = 0;
687
  dpyinfo->bitmaps[id - 1].refcount = 1;
688
  dpyinfo->bitmaps[id - 1].file
689
    = (char *) xmalloc (SBYTES (file) + 1);
690 691 692
  dpyinfo->bitmaps[id - 1].depth = 1;
  dpyinfo->bitmaps[id - 1].height = height;
  dpyinfo->bitmaps[id - 1].width = width;
693
  strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
694 695 696 697 698 699

  return id;
}

/* Remove reference to bitmap with id number ID.  */

700
void
Richard M. Stallman's avatar
Richard M. Stallman committed
701 702
x_destroy_bitmap (f, id)
     FRAME_PTR f;
703 704
     int id;
{
705 706
  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);

707 708
  if (id > 0)
    {
709 710
      --dpyinfo->bitmaps[id - 1].refcount;
      if (dpyinfo->bitmaps[id - 1].refcount == 0)
711
	{
712
	  BLOCK_INPUT;
713
	  XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].pixmap);
714 715
	  if (dpyinfo->bitmaps[id - 1].have_mask)
	    XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].mask);
716
	  if (dpyinfo->bitmaps[id - 1].file)
717
	    {
718
	      xfree (dpyinfo->bitmaps[id - 1].file);
719
	      dpyinfo->bitmaps[id - 1].file = NULL;
720
	    }
721
	  UNBLOCK_INPUT;
722 723 724 725
	}
    }
}

726
/* Free all the bitmaps for the display specified by DPYINFO.  */
727

728 729 730
static void
x_destroy_all_bitmaps (dpyinfo)
     struct x_display_info *dpyinfo;
731
{
732 733 734 735 736
  int i;
  for (i = 0; i < dpyinfo->bitmaps_last; i++)
    if (dpyinfo->bitmaps[i].refcount > 0)
      {
	XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].pixmap);
737 738
	if (dpyinfo->bitmaps[i].have_mask)
	  XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].mask);
739
	if (dpyinfo->bitmaps[i].file)
740
	  xfree (dpyinfo->bitmaps[i].file);
741 742
      }
  dpyinfo->bitmaps_last = 0;
743
}
Jim Blandy's avatar
Jim Blandy committed
744 745


746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836


/* Useful functions defined in the section
   `Image type independent image structures' below. */

static unsigned long four_corners_best P_ ((XImage *ximg, unsigned long width,
					    unsigned long height));

static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height,
					    int depth, XImage **ximg,
					    Pixmap *pixmap));

static void x_destroy_x_image P_ ((XImage *ximg));


/* Create a mask of a bitmap. Note is this not a perfect mask.
   It's nicer with some borders in this context */

int
x_create_bitmap_mask(f, id)
     struct frame *f;
     int id;
{
  Pixmap pixmap, mask;
  XImage *ximg, *mask_img;
  unsigned long width, height;
  int result;
  unsigned long bg;
  unsigned long x, y, xp, xm, yp, ym;
  GC gc;

  int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);

  if (!(id > 0))
    return -1;

  pixmap = x_bitmap_pixmap(f, id);
  width = x_bitmap_width(f, id);
  height = x_bitmap_height(f, id);

  BLOCK_INPUT;
  ximg = XGetImage (FRAME_X_DISPLAY (f), pixmap, 0, 0, width, height,
		    ~0, ZPixmap);

  if (!ximg)
    {
      UNBLOCK_INPUT;
      return -1;
    }

  result = x_create_x_image_and_pixmap (f, width, height, 1, &mask_img, &mask);

  UNBLOCK_INPUT;
  if (!result)
    {
      XDestroyImage(ximg);
      return -1;
    }

  bg = four_corners_best (ximg, width, height);

  for (y = 0; y < ximg->height; ++y)
    {
      for (x = 0; x < ximg->width; ++x)
	{
	  xp = x != ximg->width - 1 ? x + 1 : 0;
	  xm = x != 0 ? x - 1 : ximg->width - 1;
	  yp = y != ximg->height - 1 ? y + 1 : 0;
	  ym = y != 0 ? y - 1 : ximg->height - 1;
	  if (XGetPixel (ximg, x, y) == bg
	      && XGetPixel (ximg, x, yp) == bg
	      && XGetPixel (ximg, x, ym) == bg
	      && XGetPixel (ximg, xp, y) == bg
	      && XGetPixel (ximg, xp, yp) == bg
	      && XGetPixel (ximg, xp, ym) == bg
	      && XGetPixel (ximg, xm, y) == bg
	      && XGetPixel (ximg, xm, yp) == bg
	      && XGetPixel (ximg, xm, ym) == bg)
	    XPutPixel (mask_img, x, y, 0);
	  else
	    XPutPixel (mask_img, x, y, 1);
	}
    }

  xassert (interrupt_input_blocked);
  gc = XCreateGC (FRAME_X_DISPLAY (f), mask, 0, NULL);
  XPutImage (FRAME_X_DISPLAY (f), mask, gc, mask_img, 0, 0, 0, 0,
	     width, height);
  XFreeGC (FRAME_X_DISPLAY (f), gc);

837
  dpyinfo->bitmaps[id - 1].have_mask = 1;
838 839 840 841 842 843 844 845
  dpyinfo->bitmaps[id - 1].mask = mask;

  XDestroyImage (ximg);
  x_destroy_x_image(mask_img);

  return 0;
}

846 847
static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object));
848
static void x_disable_image P_ ((struct frame *, struct image *));
849

850
void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
Gerd Moellmann's avatar
Gerd Moellmann committed
851
static void x_set_wait_for_wm P_ ((struct frame *, Lisp_Object, Lisp_Object));
852 853 854 855 856 857 858 859 860 861
void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
862
void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
863 864 865 866 867 868 869 870 871
void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
				      Lisp_Object));
void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
				      Lisp_Object));
static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
							     Lisp_Object,
							     Lisp_Object,
							     char *, char *,
							     int));
872 873
static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
				  Lisp_Object));
874 875 876 877 878 879 880
static void init_color_table P_ ((void));
static void free_color_table P_ ((void));
static unsigned long *colors_in_color_table P_ ((int *n));
static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));


Jim Blandy's avatar
Jim Blandy committed
881 882


883

884
/* Store the screen positions of frame F into XPTR and YPTR.
885 886 887 888 889 890 891 892
   These are the positions of the containing window manager window,
   not Emacs's own window.  */

void
x_real_positions (f, xptr, yptr)
     FRAME_PTR f;
     int *xptr, *yptr;
{
893 894 895 896
  int win_x, win_y, outer_x, outer_y;
  int real_x = 0, real_y = 0;
  int had_errors = 0;
  Window win = f->output_data.x->parent_desc;
897

898
  int count;
899

900 901 902
  BLOCK_INPUT;

  count = x_catch_errors (FRAME_X_DISPLAY (f));
903

904 905 906 907 908 909 910 911
  if (win == FRAME_X_DISPLAY_INFO (f)->root_window)
    win = FRAME_OUTER_WINDOW (f);

  /* This loop traverses up the containment tree until we hit the root
     window.  Window managers may intersect many windows between our window
     and the root window.  The window we find just before the root window
     should be the outer WM window. */
  for (;;)
912
    {
913 914 915
      Window wm_window, rootw;
      Window *tmp_children;
      unsigned int tmp_nchildren;
916
      int success;
917

918 919
      success = XQueryTree (FRAME_X_DISPLAY (f), win, &rootw,
			    &wm_window, &tmp_children, &tmp_nchildren);
920

921
      had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
922

923 924 925 926 927 928
      /* Don't free tmp_children if XQueryTree failed.  */
      if (! success)
	break;

      XFree ((char *) tmp_children);

929 930
      if (wm_window == rootw || had_errors)
        break;
931

932 933
      win = wm_window;
    }
934

935 936 937 938
  if (! had_errors)
    {
      int ign;
      Window child, rootw;
939

940 941 942 943 944 945 946 947 948 949 950 951 952 953
      /* Get the real coordinates for the WM window upper left corner */
      XGetGeometry (FRAME_X_DISPLAY (f), win,
                    &rootw, &real_x, &real_y, &ign, &ign, &ign, &ign);

      /* Translate real coordinates to coordinates relative to our
         window.  For our window, the upper left corner is 0, 0.
         Since the upper left corner of the WM window is outside
         our window, win_x and win_y will be negative:

         ------------------          ---> x
         |      title                |
         | -----------------         v y
         | |  our window
      */
954
      XTranslateCoordinates (FRAME_X_DISPLAY (f),
955

956 957
			     /* From-window, to-window.  */
			     FRAME_X_DISPLAY_INFO (f)->root_window,
958
                             FRAME_X_WINDOW (f),
959

960
			     /* From-position, to-position.  */
961
                             real_x, real_y, &win_x, &win_y,
962

963 964
			     /* Child of win.  */
			     &child);
965

966
      if (FRAME_X_WINDOW (f) == FRAME_OUTER_WINDOW (f))
967
	{
968 969
          outer_x = win_x;
          outer_y = win_y;
970
	}
971 972 973
      else
        {
          XTranslateCoordinates (FRAME_X_DISPLAY (f),
Karl Heuer's avatar