view lwlib/dispatch.c @ 23977:abc9bc6aef59

Can use linear algorithm for indentation if Emacs supports it. (cperl-after-expr-p): It is BLOCK if we reach lim when backup sexp. (cperl-after-block-p): Likewise. (cperl-after-block-and-statement-beg): Likewise. (cperl-after-block-p): After END/BEGIN we are a block. (cperl-after-expr-p): Skip labels when checking (cperl-indent-region): Make a marker for END - text added/removed. Disable hooks during the call (how to call them later?). Now indents 820-line-long function in 6.5 sec (including syntaxification) the first time (when buffer has few properties), 7.1 sec the second time. (cperl-indent-region): Do not indent whitespace lines (cperl-style-alist) Include `cperl-merge-trailing-else' where the value is clear. (cperl-styles-entries): Likewise. (cperl-problems): Improvements to docs. (cperl-tips): Likewise. (cperl-non-problems): Likewise. (cperl-mode): Make lazy syntaxification possible. Loads pseudo-faces for the sake of `cperl-find-pods-heres' (for 19.30). `font-lock-unfontify-region-function' was set to a wrong function. (cperl-find-pods-heres): Safe a position in buffer where it is safe to restart syntaxification. Changed so that -d ?foo? is a RE. Do not warn on `=cut' if doing a chunk only. 1 << 6 was OK, but 1<<6 was considered as HERE-doc. <file/glob> made into a string. Postpone addition of faces after syntactic step. Recognition of <FH> was wrong. Highlight `gem' in s///gem as a keyword. `qr' recognized. Knows that split// is null-RE. Highlights separators in 3-parts expressions as labels. <> was considered as a glob. Would err if the last line is `=head1'. $a-1 ? foo : bar; was a considered a regexp. `<< (' was considered a start of HERE-doc. mark qq[]-etc sections as syntax-type=string Was not processing sub protos after a comment ine. Was treating $a++ <= 5 as a glob. Tolerate unfinished REx at end-of-buffer. `unwind-protect' was left commented. / and ? after : start a REx. (cperl-syntaxify-by-font-lock): Set to t, should be safe now. Better default, customizes to `message' too, off in text-mode. (cperl-array-face): Renamed from `font-lock-emphasized-face', `defface'd. (cperl-hash-face): Renamed from `font-lock-other-emphasized-face'. `defface'd. (cperl-emacs-can-parse): New state variable. (cperl-indent-line): Corrected to use global state. (cperl-calculate-indent): Likewise. (cperl-fix-line-spacing): Likewise (not used yet). (cperl-calculate-indent): Did not consider `,' as continuation mark for statements. (cperl-calculate-indent): Avoid parse-data optimization at toplevel. Remove another parse-data optimization at toplevel: would indent correctly. Correct for labels when calculating indentation of continuations. Docstring updated. (cperl-choose-color): Converted to a function (to be compilable in text-mode). (cperl-dark-background): Disable without window-system. Do `defface' only if window-system. (cperl-fix-line-spacing): sped up to bail out early. (x-color-defined-p): was not compiling on XEmacs Was defmacro'ed with a tick. Remove another def. (cperl-clobber-lisp-bindings): if set, C-c variants are the old ones (cperl-unwind-to-safe): New function. (cperl-fontify-syntaxically): Use `cperl-unwind-to-safe' to start at reasonable position. (cperl-fontify-syntaxically): Unwinds start and end to go out of long strings (not very successful). (cperl-forward-re): Highlight the trailing / in s/foo// as string. Highlight the starting // in s//foo/ as function-name. Emit a meaningful error instead of a cryptic one for an uncomplete REx near end-of-buffer. (cperl-electric-keyword): `qr' recognized. (cperl-electric-else): Likewise (cperl-to-comment-or-eol): Likewise (cperl-make-regexp-x): Likewise (cperl-init-faces): Likewise, and `lock' (as overridable?). Corrected to use new macros; `if' for copying `reference-face' to `constant-face' was backward. remove init `font-lock-other-emphasized-face', `font-lock-emphasized-face', `font-lock-keyword-face'. Interpolate `cperl-invalid-face'. (cperl-make-regexp-x): Misprint in a message. (cperl-syntaxify-unwind): New configuration variable (cperl-fontify-m-as-s): New configuration variable (cperl-electric-pod): check for after-expr was performed inside of POD too. (cperl-backward-to-noncomment): better treatment of PODs and HEREs. (cperl-clobber-mode-lists): New configuration variable. (cperl-not-bad-style-regexp): Updated. Init: `cperl-is-face' was busted. (cperl-make-face): New macros. (cperl-force-face): New macros. (font-lock-other-type-face): Done via `defface' too. (cperl-nonoverridable-face): New face. Renamed from `font-lock-other-type-face'. (cperl-init-faces-weak): use `cperl-force-face'. (cperl-comment-indent): Commenting __END__ was not working. (cperl-indent-for-comment): Likewise. (cperl-write-tags): Correct for XEmacs's `visit-tags-table-buffer'. When removing old TAGS info was not relativizing filename. (cperl-tags-hier-init): Gross hack to pretend we work (are we?). Another try to work around XEmacs problems. Better progress messages. (toplevel): require custom unprotected => failure on 19.28. (cperl-xemacs-p): defined when compile too (cperl-find-tags): Was writing line/pos in a wrong order, pos off by 1 and not at beg-of-line. (cperl-etags-snarf-tag): New macro (cperl-etags-goto-tag-location): New macro (cperl-version): New variable. New menu entry random docstrings: References to "future" 20.3 removed. Menu was described as `CPerl' instead of `Perl' (perl-font-lock-keywords): Would not highlight `sub foo($$);'. (cperl-toggle-construct-fix): Was toggling to t instead of 1. (cperl-ps-print-init): Associate `cperl-array-face', `cperl-hash-face' Remove `font-lock-emphasized-face', `font-lock-other-emphasized-face', `font-lock-reference-face', `font-lock-keyword-face'. Use `eval-after-load'. Remove not-CPerl-related faces. (cperl-tips-faces): New variable and an entry into Mini-docs. (cperl-indent-exp): Was not processing else-blocks. (cperl-get-state): NOP line removed. (cperl-ps-print): New function and menu entry. (cperl-ps-print-face-properties): New configuration variable. (cperl-invalid-face): New configuration variable. (perl-font-lock-keywords): Highlight trailing whitespace (cperl-contract-levels): Documentation corrected. (cperl-contract-level): Likewise. (cperl-ps-extend-face-list): New macro. (cperl-invalid-face): Change to ''underline.
author Richard M. Stallman <rms@gnu.org>
date Sat, 02 Jan 1999 00:16:05 +0000
parents ee40177f6c68
children e0d966fb548f
line wrap: on
line source

/* Defines a function to find the Widget that XtDispatchEvent() would use.
   Copyright (C) 1992 Lucid, Inc.

This file is part of the Lucid Widget Library.

The Lucid Widget Library 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 1, or (at your option)
any later version.

The Lucid Widget Library 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
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */

/* 
 *   The function XtWidgetToDispatchTo(), given an XEvent, returns the 
 *   widget that XtDispatchEvent() would send that event to if called now.
 *   This file copies much code from the X11r4 Xt source, and is thus a
 *   portability problem.  It also requires data structures defined in
 *   IntrinsicI.h, which is a non-exported Xt header file, so you can't
 *   compile this file unless you have the Xt sources online.
 */

#include <IntrinsicI.h>   /* Don't change this: see comments in Imakefile. */
#include <X11/Xatom.h>
#include "dispatch.h"

#include <X11/Xlib.h>
#include <X11/cursorfont.h>
#include <X11/Xutil.h>

#ifdef XlibSpecificationRelease
#if XlibSpecificationRelease >= 5
#define HAVE_X11R5
#endif
#endif

/* ##  All of the code on this page was copied from the X11R5 lib/Xt/Event.c,
   ##  but is compatible with X11R4; the code in Event.c is different, but
   ##  functionally equivalent for our purposes.
 */

#if __STDC__
#define Const const
#else
#define Const /**/
#endif

#define NonMaskableMask ((EventMask)0x80000000L)

#define COMP_EXPOSE   (widget->core.widget_class->core_class.compress_exposure)
#define COMP_EXPOSE_TYPE (COMP_EXPOSE & 0x0f)
#define GRAPHICS_EXPOSE  ((XtExposeGraphicsExpose & COMP_EXPOSE) || \
			  (XtExposeGraphicsExposeMerged & COMP_EXPOSE))
#define NO_EXPOSE        (XtExposeNoExpose & COMP_EXPOSE)


/* -- lots of stuff we don't need to copy, omitted -- */


static EventMask Const masks[] = {
	0,			    /* Error, should never see  */
	0,			    /* Reply, should never see  */
	KeyPressMask,		    /* KeyPress			*/
	KeyReleaseMask,		    /* KeyRelease		*/
	ButtonPressMask,	    /* ButtonPress		*/
	ButtonReleaseMask,	    /* ButtonRelease		*/
	PointerMotionMask	    /* MotionNotify		*/
		| ButtonMotionMask,
	EnterWindowMask,	    /* EnterNotify		*/
	LeaveWindowMask,	    /* LeaveNotify		*/
	FocusChangeMask,	    /* FocusIn			*/
	FocusChangeMask,	    /* FocusOut			*/
	KeymapStateMask,	    /* KeymapNotify		*/
	ExposureMask,		    /* Expose			*/
	NonMaskableMask,	    /* GraphicsExpose, in GC    */
	NonMaskableMask,	    /* NoExpose, in GC		*/
	VisibilityChangeMask,       /* VisibilityNotify		*/
	SubstructureNotifyMask,     /* CreateNotify		*/
	StructureNotifyMask	    /* DestroyNotify		*/
		| SubstructureNotifyMask,
	StructureNotifyMask	    /* UnmapNotify		*/
		| SubstructureNotifyMask,
	StructureNotifyMask	    /* MapNotify		*/
		| SubstructureNotifyMask,
	SubstructureRedirectMask,   /* MapRequest		*/
	StructureNotifyMask	    /* ReparentNotify		*/
		| SubstructureNotifyMask,
	StructureNotifyMask	    /* ConfigureNotify		*/
		| SubstructureNotifyMask,
	SubstructureRedirectMask,   /* ConfigureRequest		*/
	StructureNotifyMask	    /* GravityNotify		*/
		| SubstructureNotifyMask,
	ResizeRedirectMask,	    /* ResizeRequest		*/
	StructureNotifyMask	    /* CirculateNotify		*/
		| SubstructureNotifyMask,
	SubstructureRedirectMask,   /* CirculateRequest		*/
	PropertyChangeMask,	    /* PropertyNotify		*/
	NonMaskableMask,	    /* SelectionClear		*/
	NonMaskableMask,	    /* SelectionRequest		*/
	NonMaskableMask,	    /* SelectionNotify		*/
	ColormapChangeMask,	    /* ColormapNotify		*/
	NonMaskableMask,	    /* ClientMessage		*/
	NonMaskableMask		    /* MappingNotify		*/
};

#ifndef HAVE_X11R5

static /* in R5, this is not static, so we don't need to define it at all */
EventMask _XtConvertTypeToMask (eventType)
    int		eventType;
{
    eventType &= 0x7f;	/* Events sent with XSendEvent have high bit set. */
    if (eventType < XtNumber(masks))
	return masks[eventType];
    else
	return 0;
}

#endif /* not HAVE_X11R5 */

/* -- _XtOnGrabList() omitted -- */


static Widget LookupSpringLoaded(grabList)
    XtGrabList	grabList;
{
    XtGrabList	gl;

    for (gl = grabList; gl != NULL; gl = gl->next) {
	if (gl->spring_loaded)
	  if (XtIsSensitive(gl->widget))
	    return gl->widget;
	  else
	    return NULL;
	if (gl->exclusive) break;
    }
    return NULL;
}



/* This function is new. */

static Boolean WouldDispatchEvent(event, widget, mask, pd)
     register XEvent    *event;
     Widget    widget;
     EventMask mask;
     XtPerDisplay pd;
{
  XtEventRec *p;   
  Boolean would_dispatched = False;
  
  if ((mask == ExposureMask) ||
      ((event->type == NoExpose) && NO_EXPOSE) ||
      ((event->type == GraphicsExpose) && GRAPHICS_EXPOSE) )
    if (widget->core.widget_class->core_class.expose != NULL )
      return True;
  
  
  if ((mask == VisibilityChangeMask) &&
      XtClass(widget)->core_class.visible_interest) 
    return True;
  
  for (p=widget->core.event_table; p != NULL; p = p->next) 
    if ((mask & p->mask) != 0
#ifndef HAVE_X11R5
	|| (mask == 0 && p->non_filter)
#endif
	)
      return True;

  return False;
}


/* ####  This function is mostly copied from DecideToDispatch().
 */

typedef enum _GrabType {pass, ignore, remap} GrabType;

Widget
XtWidgetToDispatchTo (XEvent* event)
{
  register    Widget widget;
  EventMask   mask;
  GrabType    grabType;
  Widget	dspWidget;
  Time	time = 0;
  XtPerDisplay pd;
  XtPerDisplayInput pdi;
  XtGrabList  grabList;
  
  widget = XtWindowToWidget (event->xany.display, event->xany.window);
  pd = _XtGetPerDisplay(event->xany.display);
  pdi = _XtGetPerDisplayInput(event->xany.display);
  grabList = *_XtGetGrabList(pdi);
  
  mask = _XtConvertTypeToMask(event->xany.type);
  grabType = pass;
  switch (event->xany.type & 0x7f) {
  case KeyPress:
  case KeyRelease:	grabType = remap; break;
  case ButtonPress:
  case ButtonRelease:	grabType = remap; break;
  case MotionNotify:	grabType = ignore;
#define XKnownButtons (Button1MotionMask|Button2MotionMask|Button3MotionMask|\
                       Button4MotionMask|Button5MotionMask)
			mask |= (event->xmotion.state & XKnownButtons);
#undef XKnownButtons
				break;
  case EnterNotify:	grabType = ignore; break;
  }
  
  if (widget == NULL) {
    if (grabType != remap) return False;
    /* event occurred in a non-widget window, but we've promised also
       to dispatch it to the nearest accessible spring_loaded widget */
    else if ((widget = LookupSpringLoaded(grabList)) != NULL)
      return widget;
    return False;
  }

  switch(grabType) {
  case pass:
    return widget;
    
  case ignore:
    if ((grabList == NULL || _XtOnGrabList(widget,grabList))
	&& XtIsSensitive(widget)) {
      return widget;
    }
    return NULL;
    
  case remap:
    
    {
      Widget was_dispatched_to= NULL;
      extern Widget _XtFindRemapWidget();
      extern void _XtUngrabBadGrabs();
      
      dspWidget = _XtFindRemapWidget(event, widget, mask, pdi);
      
      if ((grabList == NULL || 
	   _XtOnGrabList(dspWidget, grabList)) &&
	  XtIsSensitive(dspWidget)) {
	if (WouldDispatchEvent (event, dspWidget, mask, pd))
	  was_dispatched_to = dspWidget;
      }
      
      /* Also dispatch to nearest accessible spring_loaded. */
      /* Fetch this afterward to reflect modal list changes */
      grabList = *_XtGetGrabList(pdi);
      widget = LookupSpringLoaded(grabList);
      if (widget != NULL && widget != dspWidget) {
	if (!was_dispatched_to)
	  was_dispatched_to =  widget;
      }
      
      return was_dispatched_to;
    }
  }
  /* should never reach here */
  return NULL;
}