/* Define X specific device and frame object for XEmacs.
   Copyright (C) 1989, 1992, 1993 1994 Free Software Foundation, Inc.
   Copyright (C) 1994, 1995 Board of Trustees, University of Illinois
   Copyright (C) 1994, 1995 Amdahl Corporation

This file is part of XEmacs.

XEmacs is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.

XEmacs 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 XEmacs; see the file COPYING.  If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */

/* Synched up with: Not in FSF. */

/* Written by Chuck Thompson and Ben Wing. */

#ifndef _XEMACS_DEVICE_X_H_
#define _XEMACS_DEVICE_X_H_

#ifdef HAVE_X_WINDOWS

#include "device.h"
#include "xintrinsic.h"

#include <X11/cursorfont.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>

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

#include <X11/StringDefs.h>

#ifdef HAVE_XPM
#include <X11/xpm.h>
#endif

/* R5 defines the XPointer type, but R4 doesn't.  
   R4 also doesn't define a version number, but R5 does. */
#if (XlibSpecificationRelease < 5)
# define XPointer char *
#endif

DECLARE_DEVICE_TYPE (x);

struct x_device
{
  /* The X connection of this device. */
  Display *display;

  /* The name of the display connected to. */
  char *display_name;

  /* Xt application info. */
  Widget Xt_app_shell;

  /* Cache of GC's for frame's on this device. */
  struct gc_cache *gc_cache;

  /* Used by x_bevel_modeline in redisplay-x.c */
  Pixmap gray_pixmap;

  /* Atoms associated with this device. */
  Atom Xatom[29];	/* use macros to access */

  /* The following items are all used exclusively in event-Xt.c. */
  int MetaMask, HyperMask, SuperMask, AltMask, ModeMask;
  KeySym lock_interpretation;

  XModifierKeymap *x_modifier_keymap;

  KeySym *x_keysym_map;
  int x_keysym_map_min_code;
  int x_keysym_map_keysyms_per_code;

  Lisp_Object argv_list;

  /* frame that holds the WM_COMMAND property; there should be exactly
     one of these per device. */
  Lisp_Object WM_COMMAND_frame;

  /* #### It's not clear that there is much distinction anymore
     between mouse_timestamp and global_mouse_timestamp, now that
     Emacs doesn't see most (all?) events not destined for it. */

  /* The timestamp of the last button or key event used by emacs itself.
     This is used for asserting selections and input focus. */
  Time mouse_timestamp;

  /* This is the timestamp the last button or key event whether it was
     dispatched to emacs or widgets. */
  Time global_mouse_timestamp;

  /* This is the last known timestamp received from the server.  It is 
     maintained by x_event_to_emacs_event and used to patch bogus 
     WM_TAKE_FOCUS messages sent by Mwm. */
  Time last_server_timestamp;

  /* Used by Xlib to preserve information across calls to
     XLookupString(), to implement compose processing.

     According to The X Window System, p. 467, "The creation of
     XComposeStatus structures is implementation dependent;
     a portable program must pass NULL for this argument."
     But this means that a portable program cannot implement
     compose processing! WTF?

     So we just set it to all zeros. */

  XComposeStatus x_compose_status;

  /* stuff for sticky modifiers: */

  unsigned int need_to_add_mask, down_mask;
  KeyCode last_downkey;
  Time release_time;
};

#define DEVICE_X_DATA(d) DEVICE_TYPE_DATA (d, x)

#define FRAME_X_DISPLAY(f) (DEVICE_X_DISPLAY (XDEVICE (f->device)))
#define DEVICE_X_DISPLAY(d) (DEVICE_X_DATA (d)->display)
#define DEVICE_XT_APP_SHELL(d) (DEVICE_X_DATA (d)->Xt_app_shell)
#define DEVICE_X_GC_CACHE(d) (DEVICE_X_DATA (d)->gc_cache)
#define DEVICE_X_GRAY_PIXMAP(d) (DEVICE_X_DATA (d)->gray_pixmap)
#define DEVICE_X_WM_COMMAND_FRAME(d) (DEVICE_X_DATA (d)->WM_COMMAND_frame)
#define DEVICE_X_MOUSE_TIMESTAMP(d) (DEVICE_X_DATA (d)->mouse_timestamp)
#define DEVICE_X_GLOBAL_MOUSE_TIMESTAMP(d) \
  (DEVICE_X_DATA (d)->global_mouse_timestamp)
#define DEVICE_X_LAST_SERVER_TIMESTAMP(d) \
  (DEVICE_X_DATA (d)->last_server_timestamp)
#define DEVICE_X_X_COMPOSE_STATUS(d) (DEVICE_X_DATA (d)->x_compose_status)

/* allocated in Xatoms_of_xfns in xfns.c */
#define DEVICE_XATOM_WM_PROTOCOLS(d) (DEVICE_X_DATA (d)->Xatom[0])
#define DEVICE_XATOM_WM_DELETE_WINDOW(d) (DEVICE_X_DATA (d)->Xatom[1])
#define DEVICE_XATOM_WM_SAVE_YOURSELF(d) (DEVICE_X_DATA (d)->Xatom[2])
#define DEVICE_XATOM_WM_TAKE_FOCUS(d) (DEVICE_X_DATA (d)->Xatom[3])
#define DEVICE_XATOM_WM_STATE(d) (DEVICE_X_DATA (d)->Xatom[4])

/* allocated in Xatoms_of_xselect in xselect.c */
#define DEVICE_XATOM_CLIPBOARD(d) (DEVICE_X_DATA (d)->Xatom[5])
#define DEVICE_XATOM_TIMESTAMP(d) (DEVICE_X_DATA (d)->Xatom[6])
#define DEVICE_XATOM_TEXT(d) (DEVICE_X_DATA (d)->Xatom[7])
#define DEVICE_XATOM_DELETE(d) (DEVICE_X_DATA (d)->Xatom[8])
#define DEVICE_XATOM_MULTIPLE(d) (DEVICE_X_DATA (d)->Xatom[9])
#define DEVICE_XATOM_INCR(d) (DEVICE_X_DATA (d)->Xatom[10])
#define DEVICE_XATOM_EMACS_TMP(d) (DEVICE_X_DATA (d)->Xatom[11])
#define DEVICE_XATOM_TARGETS(d) (DEVICE_X_DATA (d)->Xatom[12])
#define DEVICE_XATOM_NULL(d) (DEVICE_X_DATA (d)->Xatom[13])
#define DEVICE_XATOM_ATOM_PAIR(d) (DEVICE_X_DATA (d)->Xatom[14])

/* allocated in Xatoms_of_objects_x in objects-x.c */
#define DEVICE_XATOM_FOUNDRY(d) (DEVICE_X_DATA (d)->Xatom[15])
#define DEVICE_XATOM_FAMILY_NAME(d) (DEVICE_X_DATA (d)->Xatom[16])
#define DEVICE_XATOM_WEIGHT_NAME(d) (DEVICE_X_DATA (d)->Xatom[17])
#define DEVICE_XATOM_SLANT(d) (DEVICE_X_DATA (d)->Xatom[18])
#define DEVICE_XATOM_SETWIDTH_NAME(d) (DEVICE_X_DATA (d)->Xatom[19])
#define DEVICE_XATOM_ADD_STYLE_NAME(d) (DEVICE_X_DATA (d)->Xatom[20])
#define DEVICE_XATOM_PIXEL_SIZE(d) (DEVICE_X_DATA (d)->Xatom[21])
#define DEVICE_XATOM_POINT_SIZE(d) (DEVICE_X_DATA (d)->Xatom[22])
#define DEVICE_XATOM_RESOLUTION_X(d) (DEVICE_X_DATA (d)->Xatom[23])
#define DEVICE_XATOM_RESOLUTION_Y(d) (DEVICE_X_DATA (d)->Xatom[24])
#define DEVICE_XATOM_SPACING(d) (DEVICE_X_DATA (d)->Xatom[25])
#define DEVICE_XATOM_AVERAGE_WIDTH(d) (DEVICE_X_DATA (d)->Xatom[26])
#define DEVICE_XATOM_CHARSET_REGISTRY(d) (DEVICE_X_DATA (d)->Xatom[27])
#define DEVICE_XATOM_CHARSET_ENCODING(d) (DEVICE_X_DATA (d)->Xatom[28])


/* Variables associated with the X display frame this emacs is using. */
extern XtAppContext Xt_app_con;

extern Lisp_Object Vx_gc_pointer_shape;
extern Lisp_Object Vx_scrollbar_pointer_shape;
extern Lisp_Object Qx_error;

extern struct device_type *x_device_type;
extern Lisp_Object Vdefault_x_device;

/* Number of pixels below each line. */
extern int x_interline_space;

extern int x_selection_timeout;

extern struct frame *x_any_window_to_frame (struct device *d, Window);
extern struct frame *get_x_frame (Lisp_Object);
extern Display *get_x_display (Lisp_Object);
extern struct frame *x_window_to_frame (struct device *d, Window);
extern struct device *get_device_from_display (Display *dpy);
extern struct device *get_x_device (Lisp_Object);

extern void x_handle_selection_notify (XSelectionEvent *event);
extern void x_handle_selection_request (XSelectionRequestEvent *event);
extern void x_handle_selection_clear (XSelectionClearEvent *event);
extern void x_handle_property_notify (XPropertyEvent *event);

extern void Xatoms_of_xselect (struct device *d);
extern void Xatoms_of_objects_x (struct device *d);

extern void x_wm_set_shell_iconic_p (Widget shell, int iconic_p);
extern void x_wm_set_cell_size (Widget wmshell, int cw, int ch);
extern void x_wm_set_variable_size (Widget wmshell, int width, int height);
extern int x_show_gc_cursor (struct frame *f, Lisp_Object cursor);

extern CONST char *x_event_name (int event_type);
extern int x_error_handler (Display *disp, XErrorEvent *event);
extern void expect_x_error (Display *dpy);
extern int x_error_occurred_p (Display *dpy);
extern int signal_if_x_error (Display *dpy, int resumable_p);
extern int x_IO_error_handler (Display *disp);

extern void x_redraw_exposed_area (struct frame *f, int x, int y,
				   int width, int height);
struct Lisp_Image_Instance;
extern void x_output_string (struct window *w, struct display_line *dl,
			     emchar_dynarr *buf, int xpos, int xoffset,
			     int start_pixpos, int width, face_index findex,
			     int cursor, int cursor_start, int cursor_width,
			     int cursor_height);
extern void x_output_x_pixmap (struct frame *f, struct Lisp_Image_Instance *p,
			       int x, int y, int clip_x, int clip_y,
			       int clip_width, int clip_height, int width,
			       int height, int pixmap_offset,
			       unsigned long fg, unsigned long bg,
			       GC override_gc);
extern void x_output_shadows (struct frame *f, int x, int y, int width,
			      int height, GC top_shadow_gc,
			      GC bottom_shadow_gc, GC background_gc,
			      int shadow_thickness);
extern void x_generate_shadow_pixels (struct frame *f,
				      unsigned long *top_shadow,
				      unsigned long *bottom_shadow,
				      unsigned long background,
				      unsigned long core_background);

extern void free_frame_menubar (struct frame *f);
extern void x_init_modifier_mapping (struct device *d);

#define X_ERROR_OCCURRED(dpy, body)	\
     (expect_x_error ((dpy)), (body), x_error_occurred_p (dpy))

#define HANDLING_X_ERROR(dpy, body)	\
     ( expect_x_error ((dpy)), (body), signal_if_x_error ((dpy), 0))

struct Lisp_Face;
struct font_metric_info;
struct display_line;

extern Lisp_Object x_atom_to_symbol (struct device *d, Atom atom);

#ifdef I18N4

extern XIM input_method;
extern XIMStyle input_method_style;
extern XIC initial_input_context;

extern unsigned long input_method_event_mask;
extern Atom wc_atom;
extern Window main_window;

extern void get_composed_input (XKeyPressedEvent *x_event, XIC context,
				Display *display);

#endif /* I18N4 */

#ifdef EPOCH
extern Lisp_Object Qx_property_change, Qx_client_message, Qx_map, Qx_unmap;
extern Lisp_Object Vepoch_event, Vepoch_event_handler;
#endif

extern int in_resource_setting;
extern int in_specifier_change_function;

#endif /* HAVE_X_WINDOWS */
#endif /* _XEMACS_DEVICE_X_H_ */
