/**********************************************************************/
/*                                                                    */
/*	CRISP - Programmable editor                                   */
/*	===========================                                   */
/*                                                                    */
/*  File:          mouse.cr                                           */
/*  Author:        P. D. Fox                                          */
/*  Created:       14 Jun 1991                     		      */
/*                                                                    */
/*  Copyright (c) 1990, 1991 Paul Fox                                 */
/*                All Rights Reserved.                                */
/*                                                                    */
/*                                                                    */
/*--------------------------------------------------------------------*/
/*  Description:  Mouse driver macros                                 */
/*                                                                    */
/*   This  file  contains  code  to support the mouse. This has been  */
/*   tested  and  implemented  for the X11 version of CRISP only. It  */
/*   will  not  work  for  the  xterm/mouse  or  the Microsoft Mouse  */
/*   under Unix V.3 (yet).					      */
/*                                                                    */
/*   Refer to the user guide for information on using the mouse.      */
/*                                                                    */
/*   This  code  is  experimental  and  subject  to  change  but  is  */
/*   designed   to  be  more  or  less  usable  even  if  not  fully  */
/*   functional.						      */
/**********************************************************************/

/* SCCS ID: %Z% %M% %R%.%L% */

/* Prototype mouse driver code.

	Button1		Warp cursor
	Shift-Button1	Hilight region
	Meta-Button1
	Ctrl-Button1
	
	Button2
	Shift-Button2
	Meta-Button2
	Ctrl-Button2
*/
# if !defined(TRUE)
#	define	TRUE	1
#	define	FALSE	0
# endif

/**********************************************************************/
/*   Definitions for where the mouse is on the screen.		      */
/**********************************************************************/
# define	LEFT_EDGE	1
# define	RIGHT_EDGE	2
# define	TOP_EDGE	3
# define	BOTTOM_EDGE	4
# define	INSIDE_WINDOW	5
# define	TITLE		6
int	down_x, down_y;
int	last_mx, last_my, last_mwin;
int	num_motion;
extern int popup_level;
/**********************************************************************/
/*   This   variable  is  essentially  read-only.  The  variable  is  */
/*   overloaded  in  select_buffer()  for  popups  where the current  */
/*   line must always be hilighted.				      */
/**********************************************************************/
int	sel_warpable = FALSE;

/**********************************************************************/
/*   This  macro  is called on startup and by popup macros to define  */
/*   the mouse key events.					      */
/**********************************************************************/
void
define_mouse_buttons()
{
	assign_to_key("<Shift-Button1-down>", "s_button1_down");
	assign_to_key("<Shift-Button1-up>", "s_button1_up");
	assign_to_key("<Shift-Button1-motion>", "s_button1_motion");
	
	assign_to_key("<Button1-down>", "button1_down 1");
	assign_to_key("<Button1-up>", "button1_down 0");
	assign_to_key("<Button1-motion>", "button1_motion");

	assign_to_key("<Button2-down>", "button_down 2");
	assign_to_key("<Button3-down>", "button_down 3");
	assign_to_key("<Button2-up>", "button_up 2");
	assign_to_key("<Button3-up>", "button_up 3");
	
}
void
button1_down(int down_button)
{	int	x, y;
	int   	ret, win;
	int	line, col, buf;


	if ((down_button == 1) && (num_motion > 0))
	{
		raise_anchor();
		num_motion = 0;
	}
	get_mouse_pos(x, y);
	ret = translate_pos(x, y, win, line, col);
	last_mx = x;
	last_my = y;
	last_mwin = win;
	if (popup_level && win != inq_window())
		return;
	if (win >= 0) {
		inq_top_left(NULL, NULL, win, NULL, NULL, buf);
		set_window(win);
		set_buffer(buf);
		}
	switch (ret) {
	  case INSIDE_WINDOW:
		move_abs(line, col);
		if (sel_warpable)
			sel_warp();
		break;
	  case TITLE:
	  	if (down_button && popup_level == 0)
		  	edit_next_buffer();
		break;
	  case LEFT_EDGE:
	  case RIGHT_EDGE:
	  	break;
	  }
}
void
button1_motion()
{	int	x, y;
	int	ret, win;
	int	line, col;
	int	buf;
	
	if (num_motion == 0)
		drop_anchor(1);
	if (num_motion >= 0)
		num_motion++;
	get_mouse_pos(x, y);
	ret = translate_pos(x, y, win, line, col);
/*	message("MOT1 down at (%d, %d) = %d l=%d c=%d, win=%d", 
			x, y, ret, line, col, win);
*/
	if (win == last_mwin && win >= 0) {
		inq_top_left(NULL, NULL, win, NULL, NULL, buf);
		set_window(win);
		set_buffer(buf);
		move_abs(line, col);
		}
	else {
		/***********************************************/
		/*   Mouse  no  longer  in  same window so we  */
		/*   calculate  what  to do ourselves. Simply  */
		/*   go up or down a line.		       */
		/***********************************************/
		if (y > last_my)
			down();
		else if (y  < last_my)
			up();
		}
	last_mx = x;
	last_my = y;
}
void
s_button1_down()
{	int	x, y;
	int   	ret, win;
	int	line, col;
	int	buf;
	
	get_mouse_pos(x, y);
	ret = translate_pos(x, y, win, line, col);
/*	message("but1 down at (%d, %d) = %d l=%d c=%d, win=%d", 
			x, y, ret, line, col, win);
*/
	last_mx = x;
	last_my = y;
	last_mwin = win;
	num_motion = 0;
	if (win >= 0) {
		inq_top_left(NULL, NULL, win, NULL, NULL, buf);
		set_window(win);
		set_buffer(buf);
		move_abs(line, col);
		if (inq_marked())
			num_motion = -1;
		else
			drop_anchor(1);
		}
}
void
s_button1_motion()
{	int	x, y;
	int	ret, win;
	int	line, col;
	int	buf;
	
	if (num_motion >= 0)
		num_motion++;
	get_mouse_pos(x, y);
	ret = translate_pos(x, y, win, line, col);
/*	message("MOT1 down at (%d, %d) = %d l=%d c=%d, win=%d", 
			x, y, ret, line, col, win);
*/
	if (win == last_mwin && win >= 0) {
		inq_top_left(NULL, NULL, win, NULL, NULL, buf);
		set_window(win);
		set_buffer(buf);
		move_abs(line, col);
		}
	else {
		/***********************************************/
		/*   Mouse  no  longer  in  same window so we  */
		/*   calculate  what  to do ourselves. Simply  */
		/*   go up or down a line.		       */
		/***********************************************/
		if (y > last_my)
			down();
		else if (y  < last_my)
			up();
		}
	last_mx = x;
	last_my = y;
}
void
s_button1_up()
{
	if (num_motion == 0)
		raise_anchor();
}
void
button_down(int n)
{	int	x, y;
	int   	ret, win;
	int	line, col;
	list types = {
		"LEFT_EDGE", "RIGHT_EDGE", "TOP_EDGE", "BOTTOM_EDGE",
		"INSIDE_WINDOW", "TITLE"};
	
	get_mouse_pos(x, y);
	ret = translate_pos(x, y, win, line, col);
/*	message("but%d: %s (%d, %d) l=%d c=%d, win=%d", 
		n, 
		ret >= 1 && ret <= 6 ? types[ret - 1] : ("" + ret),
		x, y, line, col, win);
*/
}
