view src/gtk-xemacs.c @ 930:eaedf30d9d76

[xemacs-hg @ 2002-07-23 08:34:59 by youngs] 2002-07-15 Jerry James <james@xemacs.org> * make-docfile.c: Change whitespace and organization to reduce the size of the diff against FSF Emacs sources and synch to Emacs 21.2. Remove unused DO_REALLOC. Mark XEmacs changes and additions more clearly. Reintroduce previously deleted Emacs code inside #if 0 ... #endif. * make-docfile.c (next_extra_elc): Replace goto with do-while. * make-docfile.c (main): Put XEmacs-only args in one place. * make-docfile.c (write_c_args): Change buff to buf to match Emacs. Replace pointer arithmetic with simpler array syntax. * make-docfile.c (scan_c_file): Note that DEFSIMPLE and DEFPRED no longer exist. Correct the "name too long" test (off by one). Die with message if a DEFUN has no docstring instead of hanging. * make-docfile.c (scan_lisp_file): Introduce while loops used in Emacs sources to skip consecutive blank lines. 2002-07-21 John Paul Wallington <jpw@xemacs.org> * process.el (substitute-env-vars): New function; sync with GNU Emacs 21.1.50. (setenv): Add optional arg SUBSTITUTE-ENV-VARS; sync with GNU Emacs 21.1.50. 2002-07-20 Mike Sperber <mike@xemacs.org> * eval.c (run_post_gc_hook): Use more correct flags when running post-gc-hook. 2002-07-20 Mike Sperber <mike@xemacs.org> * process-unix.c (child_setup): Don't try to close file descriptors for chid process once again---it's already being done in close_process_descs. (unix_create_process): Call begin_dont_check_for_quit to inhibit unwanted interaction (and thus breaking of X event synchronicity) in the child. 2002-07-15 Jerry James <james@xemacs.org> * lisp.h: Make Qdll_error visible globally. * symbols.c (check_sane_subr): Revert 2002-06-26 change. Check only if !initialized. * symbols.c (check_module_subr): Add parameter. Duplicate check_sane_subr checks, but signal an error instead of asserting. * symbols.c (defsubr): Use check_module_subr parameter. * symbols.c (defsubr_macro): Ditto.
author youngs
date Tue, 23 Jul 2002 08:35:11 +0000
parents 890f3cafe600
children e22b0213b713
line wrap: on
line source

/* gtk-xemacs.c
**
** Description: A widget to encapsulate a XEmacs 'text widget'
**
** Created by: William M. Perry
** Copyright (c) 2000 William M. Perry <wmperry@gnu.org>
**
*/

#include <config.h>

#include "lisp.h"
#include "console-gtk.h"
#include "objects-gtk.h"
#include "gtk-xemacs.h"
#include "device.h"
#include "glyphs.h"
#include "window.h"
#include "faces.h"
#include "event-gtk.h"
#include "frame-impl.h"
#include "console-gtk-impl.h"
#include "device-impl.h"

extern Lisp_Object Vmodeline_face;
extern Lisp_Object Vscrollbar_on_left_p;

EXFUN (Fmake_image_instance, 4);

static void gtk_xemacs_class_init	(GtkXEmacsClass *klass);
static void gtk_xemacs_init		(GtkXEmacs *xemacs);
static void gtk_xemacs_size_allocate	(GtkWidget *widget, GtkAllocation *allocaction);
static void gtk_xemacs_draw		(GtkWidget *widget, GdkRectangle *area);
static void gtk_xemacs_paint		(GtkWidget *widget, GdkRectangle *area);
static void gtk_xemacs_size_request	(GtkWidget *widget, GtkRequisition *requisition);
static void gtk_xemacs_realize		(GtkWidget *widget);
static void gtk_xemacs_style_set        (GtkWidget *widget, GtkStyle *previous_style);
static gint gtk_xemacs_expose		(GtkWidget *widget, GdkEventExpose *event);

guint
gtk_xemacs_get_type (void)
{
  static guint xemacs_type = 0;

  if (!xemacs_type)
    {
      static const GtkTypeInfo xemacs_info =
      {
	"GtkXEmacs",
	sizeof (GtkXEmacs),
	sizeof (GtkXEmacsClass),
	(GtkClassInitFunc) gtk_xemacs_class_init,
	(GtkObjectInitFunc) gtk_xemacs_init,
	/* reserved_1 */ NULL,
        /* reserved_2 */ NULL,
        (GtkClassInitFunc) NULL,
      };

      xemacs_type = gtk_type_unique (gtk_fixed_get_type (), &xemacs_info);
    }

  return xemacs_type;
}

static GtkWidgetClass *parent_class;

static void
gtk_xemacs_class_init (GtkXEmacsClass *class)
{
  GtkWidgetClass *widget_class;

  widget_class = (GtkWidgetClass*) class;
  parent_class = (GtkWidgetClass *) gtk_type_class (gtk_fixed_get_type ());

  widget_class->size_allocate = gtk_xemacs_size_allocate;
  widget_class->size_request = gtk_xemacs_size_request;
  widget_class->draw = gtk_xemacs_draw;
  widget_class->expose_event = gtk_xemacs_expose;
  widget_class->realize = gtk_xemacs_realize;
  widget_class->button_press_event = emacs_gtk_button_event_handler;
  widget_class->button_release_event = emacs_gtk_button_event_handler;
  widget_class->key_press_event = emacs_gtk_key_event_handler;
  widget_class->key_release_event = emacs_gtk_key_event_handler;
  widget_class->motion_notify_event = emacs_gtk_motion_event_handler;
  widget_class->style_set = gtk_xemacs_style_set;
}

static void
gtk_xemacs_init (GtkXEmacs *xemacs)
{
    GTK_WIDGET_SET_FLAGS (xemacs, GTK_CAN_FOCUS);
}

GtkWidget*
gtk_xemacs_new (struct frame *f)
{
  GtkXEmacs *xemacs;

  xemacs = gtk_type_new (gtk_xemacs_get_type ());
  xemacs->f = f;

  return GTK_WIDGET (xemacs);
}

static void
__nuke_background_items (GtkWidget *widget)
{
  /* This bit of voodoo is here to get around the annoying flicker
     when GDK tries to futz with our background pixmap as well as
     XEmacs doing it

     We do NOT set the background of this widget window, that way
     there is NO flickering, etc.  The downside is the XEmacs frame
     appears as 'seethru' when XEmacs is too busy to redraw the
     frame.

     Well, wait, we do... otherwise there sre weird 'seethru' areas
     even when XEmacs does a full redisplay.  Most noticable in some
     areas of the modeline, or in the right-hand-side of the window
     between the scrollbar ad n the edge of the window.
  */
  if (widget->window)
    {
      gdk_window_set_back_pixmap (widget->window, NULL, 0);
      gdk_window_set_back_pixmap (widget->parent->window, NULL, 0);
      gdk_window_set_background (widget->parent->window,
				 &widget->style->bg[GTK_STATE_NORMAL]);
      gdk_window_set_background (widget->window,
				 &widget->style->bg[GTK_STATE_NORMAL]);
    }
}

extern Lisp_Object xemacs_gtk_convert_color(GdkColor *c, GtkWidget *w);

/* From objects-gtk.c */
extern Lisp_Object __get_gtk_font_truename (GdkFont *gdk_font, int expandp);

#define convert_font(f) __get_gtk_font_truename (f, 0)

#ifdef SMASH_FACE_FALLBACKS
static void
smash_face_fallbacks (struct frame *f, GtkStyle *style)
{
#define FROB(face,prop,slot) do { 							\
				Lisp_Object fallback = Qnil;				\
				Lisp_Object specifier = Fget (face, prop, Qnil);	\
   				struct Lisp_Specifier *sp = NULL;			\
 				if (NILP (specifier)) continue;				\
 				sp = XSPECIFIER (specifier);				\
 				fallback = sp->fallback;				\
 				if (EQ (Fcar (Fcar (Fcar (fallback))), Qgtk))		\
 					fallback = XCDR (fallback);			\
 				if (! NILP (slot))					\
 					fallback = acons (list1 (Qgtk),			\
 								  slot,			\
 								  fallback);		\
 				set_specifier_fallback (specifier, fallback);		\
			     } while (0);
#define FROB_FACE(face,fg_slot,bg_slot) \
do {											\
	FROB (face, Qforeground, xemacs_gtk_convert_color (&style->fg_slot[GTK_STATE_NORMAL], FRAME_GTK_SHELL_WIDGET (f)));	\
	FROB (face, Qbackground, xemacs_gtk_convert_color (&style->bg_slot[GTK_STATE_NORMAL], FRAME_GTK_SHELL_WIDGET (f)));	\
	if (style->rc_style && style->rc_style->bg_pixmap_name[GTK_STATE_NORMAL])	\
	{										\
		FROB (Vdefault_face, Qbackground_pixmap,				\
			Fmake_image_instance (build_string (style->rc_style->bg_pixmap_name[GTK_STATE_NORMAL]), \
					  f->device, Qnil, make_int (5)));			\
	}										\
	else										\
	{										\
		FROB (Vdefault_face, Qbackground_pixmap, Qnil);				\
	}										\
} while (0)

  FROB (Vdefault_face, Qfont, convert_font (style->font));
  FROB_FACE (Vdefault_face, fg, bg);
  FROB_FACE (Vgui_element_face, text, mid);

#undef FROB
#undef FROB_FACE
}
#endif /* SMASH_FACE_FALLBACKS */

#ifdef HAVE_SCROLLBARS
static void
smash_scrollbar_specifiers (struct frame *f, GtkStyle *style)
{
  Lisp_Object frame;
  int slider_size = 0;
  int hsize, vsize;
  GtkRangeClass *klass;

  frame = wrap_frame (f);

  klass = (GtkRangeClass *) gtk_type_class (GTK_TYPE_SCROLLBAR);
  slider_size = klass->slider_width;
  hsize = slider_size + (style->klass->ythickness * 2);
  vsize = slider_size + (style->klass->xthickness * 2);

  style = gtk_style_attach (style,
			    GTK_WIDGET (DEVICE_GTK_APP_SHELL (XDEVICE (FRAME_DEVICE (f))))->window);

  Fadd_spec_to_specifier (Vscrollbar_width, make_int (vsize), frame, Qnil, Qnil);
  Fadd_spec_to_specifier (Vscrollbar_height, make_int (hsize), frame, Qnil, Qnil);
}
#endif /* HAVE_SCROLLBARS */

#ifdef HAVE_TOOLBARS
extern Lisp_Object Vtoolbar_shadow_thickness;

static void
smash_toolbar_specifiers(struct frame *f, GtkStyle *style)
{
  Lisp_Object frame;
  GtkStyleClass *klass = (GtkStyleClass *) style->klass;

  frame = wrap_frame (f);

  Fadd_spec_to_specifier (Vtoolbar_shadow_thickness, make_int (klass->xthickness),
			  Qnil, list2 (Qgtk, Qdefault), Qprepend);
}
#endif /* HAVE_TOOLBARS */

static void
gtk_xemacs_realize (GtkWidget *widget)
{
  parent_class->realize (widget);
  gtk_xemacs_style_set (widget, gtk_widget_get_style (widget));
}

static void
gtk_xemacs_style_set (GtkWidget *widget, GtkStyle *previous_style)
{
  GtkStyle *new_style = gtk_widget_get_style (widget);
  GtkXEmacs *x = GTK_XEMACS (widget);

  parent_class->style_set (widget, previous_style);

  if (x->f)
    {
      __nuke_background_items (widget);
#ifdef SMASH_FACE_FALLBACKS
      smash_face_fallbacks (x->f, new_style);
#endif
#ifdef HAVE_SCROLLBARS
      smash_scrollbar_specifiers (x->f, new_style);
#endif
#ifdef HAVE_TOOLBARS
      smash_toolbar_specifiers (x->f, new_style);
#endif
    }
}

static void
gtk_xemacs_size_request (GtkWidget *widget, GtkRequisition *requisition)
{
    GtkXEmacs *x = GTK_XEMACS (widget);
    struct frame *f = GTK_XEMACS_FRAME (x);
    int width, height;

    if (f)
      {
	char_to_pixel_size (f, FRAME_WIDTH (f), FRAME_HEIGHT (f),
			    &width, &height);
	requisition->width = width;
	requisition->height = height;
      }
    else
      {
	parent_class->size_request (widget, requisition);
      }
}

static void
gtk_xemacs_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
{
    GtkXEmacs *x = GTK_XEMACS (widget);
    struct frame *f = GTK_XEMACS_FRAME (x);
    int columns, rows;

    parent_class->size_allocate(widget, allocation);

    if (f)
      {
	f->pixwidth = allocation->width;
	f->pixheight = allocation->height;

	pixel_to_char_size (f,
			    allocation->width,
			    allocation->height, &columns, &rows);

	change_frame_size (f, rows, columns, 1);
      }
}

static void
gtk_xemacs_paint (GtkWidget *widget, GdkRectangle *area)
{
    GtkXEmacs *x = GTK_XEMACS (widget);
    struct frame *f = GTK_XEMACS_FRAME (x);
    gtk_redraw_exposed_area (f, area->x, area->y, area->width, area->height);
}

static void
gtk_xemacs_draw (GtkWidget *widget, GdkRectangle *area)
{
    GtkFixed *fixed = GTK_FIXED (widget);
    GtkFixedChild *child;
    GdkRectangle child_area;
    GList *children;

    /* I need to manually iterate over the children instead of just
       chaining to parent_class->draw() because it calls
       gtk_fixed_paint() directly, which clears the background window,
       which causes A LOT of flashing. */

    gtk_xemacs_paint (widget, area);

    children = fixed->children;

    while (children)
      {
	child = children->data;
	children = children->next;
	/* #### This is what causes the scrollbar flickering!
	   Evidently the scrollbars pretty much take care of drawing
	   themselves in most cases.  Then we come along and tell them
	   to redraw again!

	   But if we just leave it out, then they do not get drawn
	   correctly the first time!

	   Scrollbar flickering has been greatly helped by the
	   optimizations in scrollbar-gtk.c /
	   gtk_update_scrollbar_instance_status (), so this is not that
	   big a deal anymore.
	*/
	if (gtk_widget_intersect (child->widget, area, &child_area))
	  {
	    gtk_widget_draw (child->widget, &child_area);
	  }
      }
}

static gint
gtk_xemacs_expose (GtkWidget *widget, GdkEventExpose *event)
{
    GtkXEmacs *x = GTK_XEMACS (widget);
    struct frame *f = GTK_XEMACS_FRAME (x);
    GdkRectangle *a = &event->area;

    /* This takes care of drawing the scrollbars, etc */
    parent_class->expose_event (widget, event);

    /* Now draw the actual frame data */
    if (!check_for_ignored_expose (f, a->x, a->y, a->width, a->height) &&
	!find_matching_subwindow (f, a->x, a->y, a->width, a->height))
      gtk_redraw_exposed_area (f, a->x, a->y, a->width, a->height);
    return (TRUE);
}

Lisp_Object
xemacs_gtk_convert_color(GdkColor *c, GtkWidget *w)
{
  char color_buf[255];

  sprintf (color_buf, "#%04x%04x%04x", c->red, c->green, c->blue);

  return (build_string (color_buf));
}