/* AbiSource Program Utilities
 * Copyright (C) 1998 AbiSource, Inc.
 * 
 * This program 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
 * of the License, or (at your option) any later version.
 * 
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  
 * 02111-1307, USA.
 */
 



#ifndef EV_EDITEVENTMAPPER_H
#define EV_EDITEVENTMAPPER_H

/****************************************************************
*****************************************************************
** EditEventMapper, EditBinding, and EditMethod form the basis for
** all editing operations.  All keystrokes and mouse events
** are directed thru here.  These are
** defined as classes outside of the document so that we may switch
** between different implementations as we want.
**
** EditEventMapper is in charge.  It receives each event, applies
** any policy decisions, and then uses the EditBindings to decide
** what to do.  (An example policy decision might be whether or
** not to do sticky-control and -shift keys for one-handed users;
** we may have 2 different implementations of EditEventMapper --
** a normal one and a sticky one, for example.  (Another policy
** decision might be whether or not to support Control- and
** Shift- toolbar events.)
**
** EditBindings provides an emacs-like single/multiple key/event
** sequence to action mapping.  Each EditBinding table provides
** a mapping from a single event (key, mouse, etc.) to an action.
** If the action maps to a EditMethod, the key/event sequence is
** considered complete and the indicated EditMethod is returned
** to allow the caller to invoke it.  If the action maps to another
** EditBinding table, the key/event sequence is considered to be
** a prefix to a longer sequence; in this case, the EditEventMapper
** updates it state and waits for the next key/event.  We can
** think of these EditBinding tables as forming a tree.
**
** An EditMethod (and EditMethodContainer) provides a handle to
** a specific editing operation (such as InsertCharacter, NextLine,
** etc).  The EditMethodContainer should contain a static set of
** builtin methods and a set of dynamically created ones (dare
** I say JavaScript macros).  Provision has been made to allow
** the implementation of the static methods to be switched based
** upon user language or some other criteria; this allows us to 
** define multiple sets of the basic primitives, in case we want
** to simplify the selection of various WordProcessor emmulations
** or language quirks.  For example, does NextWord() go to the 
** first whitespace at the end of the current word or go to the
** beginning of the next word and for those languages which don't
** use whitespace, where does it go or is it even defined.
**
** The EditEventMapper may have more than one set of EditBinding
** trees -- much like emacs's global bindings and mode bindings.
** A key/event sequence will searched for in the mode bindings
** and then in the global bindings.
**
** The EditEventMapper returns the EditMethod rather than invoking
** it directly.  This allows our caller to query the EditMethod
** for it's properties (such as a short description for the 
** status bar when the menu item is highlighted).
**
** The EditEventMapper has seperate event methods for keystrokes,
** and mouse operations.
**
** Keystroke Events:
**
** Mouse Events:
**   Mouse buttons are numbered from 1 to n.  It is upto the GUI/OS
**   to decide which physical button is mapped to 1 and which to n.
**
**   Keyboard modifiers are respected.
**
**   Depending upon the GUI, a Double click may also generate Single
**   (and Double) click and release events, so be aware.
**
**   A drag is processed as a sequence of mouse movements.
**   The quantity and granularity of the movement is GUI/OS
**   dependent; we will simply map each of them as we see
**   them.  We allow the keyboard modifiers to change during
**   the drag, so the mapping may change between successive
**   drag events.  Again, be aware.
**
**   We do not attempt to support sequences where a second
**   mouse button is pressed during a drag (while the first
**   mouse button is still down).
**
**   We now support mouse events for button-up-motion events.
**   (These are primarily used for context cursors.)
**
**   We now suport the notion of mouse contexts.
**
**   TODO Question: If another event (keystroke, mouse click)
**   TODO           occurs during a drag, do we:
**   TODO           (1) end the drag with or without issuing an
**   TODO           implicit release and then process the new
**   TODO           event (and ignore the eventual actual 
**   TODO           release), or
**   TODO           (2) ignore the new event and keep the
**   TODO           drag active until the actual release, or
**   TODO           (3) ??
**
**
** TODO Question: Should Menus and Toolbars recognize keyboard
** TODO           modifiers (control, shift, etc) like keystroke
** TODO           and mouse events ??
**
** TODO Question: Should we distinguish between left- and right-versions
** TODO           of SHFIT, CONTROL, ALT, etc ??
**
******************************************************************
*****************************************************************/

#include "ut_types.h"
#include "ev_EditBits.h"
#include "ev_EditMethod.h"

typedef UT_uint32 EV_EditEventMapperResult;
#define EV_EEMR_BOGUS_START		((EV_EditEventMapperResult) 1) /* start of unknown event sequence */
#define EV_EEMR_BOGUS_CONT		((EV_EditEventMapperResult) 2) /* unknown continuation event sequence */
#define EV_EEMR_INCOMPLETE		((EV_EditEventMapperResult) 3) /* accumulating valid prefix */
#define EV_EEMR_COMPLETE		((EV_EditEventMapperResult) 4) /* complete sequence */

/****************************************************************/
/****************************************************************/

class EV_EditEventMapper
{
public:
	EV_EditEventMapper(EV_EditBindingMap * pebm);

	EV_EditEventMapperResult Keystroke(EV_EditBits eb, EV_EditMethod ** ppEM);
	EV_EditEventMapperResult Mouse(EV_EditBits eb, EV_EditMethod ** ppEM);

	const char *			getShortcutFor(const EV_EditMethod * pEM) const;

protected:
	EV_EditBindingMap *		m_pebmTopLevel;
	EV_EditBindingMap *		m_pebmInProgress;
};

#endif /* EV_EDITEVENTMAPPER_H */
