ftp.nice.ch/pub/next/unix/editor/me.3.10.N.bs.tar.gz#/me-3.10.N.bs/src/mouse.c

This is mouse.c in view mode; [Download] [Up]

/*	MOUSE.C:	Mouse functionality commands
			for MicroEMACS 3.10
			originally written by Dave G. Conroy
			modified by Jeff Lomicka and Daniel Lawrence
*/

#include	<stdio.h>
#include	"estruct.h"
#include	"etype.h"
#include        "edef.h"
#include	"elang.h"

#define	MNONE	0			/* Mouse commands.		*/
#define	MMOVE	1
#define	MREG	2

#if	MOUSE
NOSHARE int	lastypos = HUGE;	/* Last mouse event row.	*/
NOSHARE int	lastxpos = HUGE;	/* Last mouse event column.	*/
NOSHARE int	lastmcmd = MNONE;	/* Last mouse command.		*/

/*
 * Move mouse button, down. The window that the
 * mouse is in is always selected (this lets you select a
 * window by clicking anyplace in it, even off the end
 * of the text). If the mouse points at text then dot is
 * moved to that location.
 */
PASCAL NEAR movemd(f, n)
{
	register WINDOW	*wp;
	register WINDOW	*lastwp;
	register LINE	*lp;

	/* if anything has changed, reset the click count */
	if (lastmcmd != MMOVE || lastypos!=ypos || lastxpos!=xpos)
		nclicks = 0;
	++nclicks;
	lastwp = mousewindow(lastypos);		/* remember least window */

	/* reset the last position */
	lastypos = ypos;
	lastxpos = xpos;
	lastmcmd = MMOVE;

	/* if we move the mouse off the windows, don't move anything */
	if ((wp=mousewindow(ypos)) == NULL)
		return(FALSE);

	/* if we are on the line with the point, adjust for extended lines */
	if (wp == curwp && (lp = mouseline(wp, ypos)) == curwp->w_dotp)
		xpos += lbound;

	/* make the window the mouse points to current */
	curwp = wp;
	curbp = wp->w_bufp;

	/* if we changed windows, update the modelines */
	if (wp != lastwp)
		upmode();

	/* if we aren't off the end of the text, move the point to the mouse */
	if ((lp=mouseline(wp, ypos)) != NULL) {
		curwp->w_dotp = lp;
		curwp->w_doto = mouseoffset(wp, lp, xpos);
	}

	return(TRUE);
}


/*	mouse-region-down:	mouse region operations

	nclicks = 0:	move cursor to mouse
			set-mark

		  1:	move cursor to mouse
			kill-region
*/

PASCAL NEAR mregdown(f, n)
{
	register WINDOW	*wp;
	register WINDOW	*lastwp;
	register LINE	*lp;

	/* if anything has changed, reset the click count */
	if (lastmcmd != MREG || lastypos != ypos || lastxpos != xpos)
		nclicks = 0;
	++nclicks;
	lastwp = mousewindow(lastypos);		/* remember least window */

	/* reset the last position */
	lastypos = ypos;
	lastxpos = xpos;
	lastmcmd = MREG;

	/* if we move the mouse off the windows, don't move anything */
	if ((wp=mousewindow(ypos)) == NULL)
		return(FALSE);

	/* if we are on the line with the point, adjust for extended lines */
	if (wp == curwp && (lp = mouseline(wp, ypos)) == curwp->w_dotp)
		xpos += lbound;

	/* make the window the mouse points to current */
	curwp = wp;
	curbp = wp->w_bufp;

	/* if we changed windows, update the modelines */
	if (wp != lastwp)
		upmode();

	/* if we aren't off the end of the text, move the point to the mouse */
	if ((lp=mouseline(wp, ypos)) != NULL) {
		curwp->w_dotp = lp;
		curwp->w_doto = mouseoffset(wp, lp, xpos);
	}

	/* perform the region function */
	if (nclicks == 1) {
		return(setmark(FALSE, 0));
	} else {
		lastflag &= ~CFKILL;
		return(killregion(FALSE, 0));
	}
}

/*	mouse-region-up:	mouse region operations

	If the corrosponding downclick was on a modeline, then we
	wish to delete the indicated window. Otherwise we are using
	this button to copy/paste.

	nclicks = 0:	move cursor to mouse
			copy-region

		  1:	move cursor to mouse
			yank

		  3:	reset nclicks to 0
*/

PASCAL NEAR mregup(f, n)

{
	register WINDOW	*wp;
	register WINDOW	*lastwp;
	register LINE *lp;
	register int lastmodeline;	/* was the dowbclick on a modeline? */

	/* if anything has changed, reset the click count */
	if (lastmcmd != MREG || lastypos != ypos || lastxpos != xpos)
		nclicks = 0;
	++nclicks;
	lastwp = mousewindow(lastypos);		/* remember least window */

	/* did we down click on a modeline? */
	lastmodeline = ismodeline(lastwp, lastypos);

	/* reset the last position */
	lastypos = ypos;
	lastxpos = xpos;
	lastmcmd = MREG;

	/* if we started on a modeline.... */
	if (lastmodeline)
		return(delwind(TRUE, 0));

	/* if we move the mouse off the windows, don't move anything */
	if ((wp=mousewindow(ypos)) == NULL)
		return(FALSE);

	/* if we are on the line with the point, adjust for extended lines */
	if (wp == curwp && (lp = mouseline(wp, ypos)) == curwp->w_dotp)
		xpos += lbound;

	/* make the window the mouse points to current */
	curwp = wp;
	curbp = wp->w_bufp;

	/* if we aren't off the end of the text, move the point to the mouse */
	if ((lp=mouseline(wp, ypos)) != NULL && nclicks < 3) {
		curwp->w_dotp = lp;
		curwp->w_doto = mouseoffset(wp, lp, xpos);
	}

	/* if we changed windows, update the modelines, abort the new op */
	if (wp != lastwp) {
		upmode();
		return(TRUE);
	}

	/* perform the region function */
	if (nclicks == 1) {
		return(copyregion(FALSE, 0));
	} else if (nclicks == 2) {
		return(yank(FALSE, 1));
	} else {
		nclicks = 0;
		return(TRUE);
	}
}

/*
 * Move mouse button, up. The up click must be
 * in the text region of a window. If the old click was in a
 * mode line then the mode line moves to the row of the
 * up click. If the old click is not in a mode line then the
 * window scrolls. The code in this function is just
 * too complex!
 */
PASCAL NEAR movemu(f, n)
{
	register WINDOW	*lastwp;
	register WINDOW	*wp;
	register int	lastmodeline;	/* was the dowbclick on a modeline? */
	register int	deltay;
	register int	deltax;

	/* no movement... fail the command */
	if (lastypos==ypos && lastxpos==xpos)
		return(FALSE);

	/* if the down click was in the bottom right corner...
	   then we are resizing */
	if (lastypos == term.t_nrow && lastxpos + 1 == term.t_ncol) {
		(*term.t_eeop)();
		newwidth(TRUE, xpos + 1);
		newsize(TRUE, ypos + 1);
		return(TRUE);
	}

	/* if the down click was not in a window.. fail the command
	   (for example, if we click on the command line) */
	if ((lastwp=mousewindow(lastypos)) == NULL)
		return(FALSE);

	/* did we down click on a modeline? */
	lastmodeline = ismodeline(lastwp, lastypos);

	/* are we not in a window? fail it then */
	if ((wp=mousewindow(ypos)) == NULL)
		return(FALSE);

	/* how far did we move? */
	deltay = lastypos-ypos;
	deltax = lastxpos-xpos;
	lastypos = ypos;
	lastxpos = xpos;

	/* if we started on a modeline.... */
	if (lastmodeline) {

		/* move the window horizontally */
		if (deltax != 0 && (diagflag || deltay == 0)) {
			lastwp->w_fcol += deltax;
			if (lastwp->w_fcol < 0)
				lastwp->w_fcol = 0;
			lastwp->w_flag |= WFMODE|WFHARD;
			if (deltay == 0)
				return(TRUE);
		}

		/* don't allow the bottom modeline to move */
		if (lastwp->w_wndp == NULL)
			return(FALSE);

		/* shrink the current window */
		if (deltay > 0) {
			if (lastwp != wp)
				return(FALSE);
			curwp = wp;
			curbp = wp->w_bufp;
			return(shrinkwind(TRUE, deltay));
		}

		/* or grow it */
		if (deltay < 0) {
			if (wp != lastwp->w_wndp)
				return(FALSE);
			curwp = lastwp;
			curbp = lastwp->w_bufp;
			return(enlargewind(TRUE, -deltay));
		}
	}

	/* did we up click in a modeline? fail it them */
	if (ismodeline(wp, ypos) != FALSE)
		return(FALSE);

	/* we can not move outside the current window */
	if (lastwp != wp)
		return(FALSE);

	/* move horizontally as well? */
	if (deltax != 0 && (diagflag || deltay == 0)) {
		wp->w_fcol += deltax;
		if (wp->w_fcol < 0)
			wp->w_fcol = 0;
		wp->w_flag |= WFMODE;
	}

	/* and move the screen */
	return(mvdnwind(TRUE, deltay));
}

/*
 * Return a pointer to the WINDOW structure
 * for the window in which "row" is located, or NULL
 * if "row" isn't in any window. The mode line is
 * considered to be part of the window.
 */

WINDOW *PASCAL NEAR mousewindow(row)

register int	row;

{
	register WINDOW	*wp;

	wp = wheadp;
	while (wp != NULL) {
		if (row < wp->w_ntrows+1)
			return(wp);
		row -= wp->w_ntrows+1;
		wp = wp->w_wndp;
	}
	return(NULL);
}

/*
 * The row "row" is a row within the window
 * whose WINDOW structure is pointed to by the "wp"
 * argument. Find the associated line, and return a pointer
 * to it. Return NULL if the mouse is on the mode line,
 * or if the mouse is pointed off the end of the
 * text in the buffer.
 */

LINE *PASCAL NEAR mouseline(wp, row)

register WINDOW	*wp;
register int	row;

{
	register LINE	*lp;

	row -= wp->w_toprow;
	if (row >= wp->w_ntrows)
		return(NULL);
	lp = wp->w_linep;
	while (row--) {
		if (lp == wp->w_bufp->b_linep)	/* Hit the end.		*/
			return(NULL);
		lp = lforw(lp);
	}
	return(lp);
}

/*
 * Return the best character offset to use
 * to describe column "col", as viewed from the line whose
 * LINE structure is pointed to by "lp".
 */

PASCAL NEAR mouseoffset(wp, lp, col)

register WINDOW *wp;
register LINE	*lp;
register int	col;

{
	register int	c;
	register int	offset;
	register int	curcol;
	register int	newcol;

	offset = 0;
	curcol = 0;
	col += wp->w_fcol;	/* adjust for extended lines */
	while (offset != llength(lp)) {
		newcol = curcol;
		if ((c=lgetc(lp, offset)) == '\t')
			newcol += -(newcol % tabsize) + (tabsize - 1);
		else if (c<32)	/* ISCTRL */
			++newcol;
		++newcol;
		if (newcol > col)
			break;
		curcol = newcol;
		++offset;
	}
	return(offset);
}

PASCAL NEAR ismodeline(wp, row)
WINDOW	*wp;
{
	if (row == wp->w_toprow+wp->w_ntrows && modeflag)
		return(TRUE);
	return(FALSE);
}

/* The mouse has been used to resize the physical window. Now we need to
   let emacs know about the newsize, and have him force a re-draw
*/

PASCAL NEAR resizm(f, n)

int f, n;	/* these are ignored... we get the new size info from
		   the mouse driver */
{
	(*term.t_eeop)();
	newwidth(TRUE, xpos);
	newsize(TRUE, ypos);
	return(TRUE);
}

#else
mousehello()
{
}
#endif

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.