1 /*	MOUSE.C:	Mouse functionality commands
2 			for MicroEMACS 4.00
3 			originally written by Dave G. Conroy
4 			modified by Jeff Lomicka and Daniel Lawrence
5 */
6 
7 #include	<stdio.h>
8 #include	"estruct.h"
9 #include	"eproto.h"
10 #include        "edef.h"
11 #include	"elang.h"
12 
13 #define	MNONE	0			/* Mouse commands.		*/
14 #define	MMOVE	1
15 #define	MREGDWN	2
16 #define	MREGUP	3
17 #define	MCREATE	4
18 #define MDELETE	5
19 
20 #if	MOUSE
21 NOSHARE int	lastypos = HUGE;	/* Last mouse event row.	*/
22 NOSHARE int	lastxpos = HUGE;	/* Last mouse event column.	*/
23 NOSHARE int	lastmcmd = MNONE;	/* Last mouse command.		*/
24 
25 /*
26  * Move mouse button, down. The window that the
27  * mouse is in is always selected (this lets you select a
28  * window by clicking anyplace in it, even off the end
29  * of the text). If the mouse points at text then dot is
30  * moved to that location.
31  */
movemd(f,n)32 PASCAL NEAR movemd(f, n)
33 
34 int f,n;	/* prefix flag and argument */
35 
36 {
37 	register EWINDOW *wp;
38 	register EWINDOW *lastwp;
39 	register LINE	*lp;
40 
41 	/* make sure we are on the proper screen */
42 	mouse_screen();
43 
44 	/* adjust position by screen offset */
45 	ypos -= term.t_roworg;
46 	xpos -= term.t_colorg;
47 
48 	/* if anything has changed, reset the click count */
49 	if (lastmcmd != MMOVE || lastypos!=ypos || lastxpos!=xpos)
50 		nclicks = 0;
51 	++nclicks;
52 	lastwp = mousewindow(lastypos);		/* remember last window */
53 
54 	/* reset the last position */
55 	lastypos = ypos;
56 	lastxpos = xpos;
57 	lastmcmd = MMOVE;
58 
59 	/* if we move the mouse off the windows, don't do anything with it */
60 	if ((wp=mousewindow(ypos)) == NULL)
61 		return(FALSE);
62 
63 	/* if we are on the line with the point, adjust for extended lines */
64 	if (wp == curwp && (lp = mouseline(wp, ypos)) == curwp->w_dotp)
65 		xpos += lbound;
66 
67 	/* make the window the mouse points to current */
68 	curwp = wp;
69 	curbp = wp->w_bufp;
70 
71 	/* if we changed windows, update the modelines */
72 	if (wp != lastwp)
73 		upmode();
74 
75 	/* if we aren't off the end of the text, move the point to the mouse */
76 	if ((lp=mouseline(wp, ypos)) != NULL) {
77 		curwp->w_dotp = lp;
78 		curwp->w_doto = mouseoffset(wp, lp, xpos);
79 	}
80 
81 	return(TRUE);
82 }
83 
84 
85 /*	mouse-move:	adjust the hilited region by setting mark(hilite+1)
86 			only if we are holding down the proper button
87 */
88 
mmove(f,n)89 PASCAL NEAR mmove(f, n)
90 
91 int f,n;	/* prefix flag and argument */
92 
93 {
94 	register EWINDOW *wp;
95 	register EWINDOW *lastwp;
96 	register LINE *lp;
97 	register int lastmodeline;	/* was the dowbclick on a modeline? */
98 	register int lastcmdline;	/* was the downclick on the command line? */
99 
100 	/* ignore this if not hilighting */
101 	if (hilite >= NMARKS)
102 		return(TRUE);
103 
104 	/* ignore this if we did not just do a mouse region down */
105 	if (lastmcmd != MREGDWN)
106 		return(TRUE);
107 
108 	/* adjust position by screen offset */
109 	ypos -= term.t_roworg;
110 	xpos -= term.t_colorg;
111 
112 	/* Just where was the last click? */
113 	lastwp = mousewindow(lastypos);
114 	lastmodeline = ismodeline(lastwp, lastypos);
115 	lastcmdline = (lastypos == term.t_nrow);
116 
117 	/* if it was on a modeline or the command line, don't do things here */
118 	if (lastmodeline || lastcmdline)
119 		return(FALSE);
120 
121 	/* if we move the mouse off the window, abort this */
122 	if ((wp = mousewindow(ypos)) == NULL || wp != lastwp)
123 		return(FALSE);
124 
125 	/* if we are on the line with the point, adjust for extended lines */
126 	if (wp == curwp && (lp = mouseline(wp, ypos)) == curwp->w_dotp)
127 		xpos += lbound;
128 
129 	/* if we aren't off the end of the text, set mark $hilight+1 */
130 	if ((lp=mouseline(wp, ypos)) != NULL) {
131 		wp->w_markp[hilite+1] = lp;
132 		wp->w_marko[hilite+1] = mouseoffset(wp, lp, xpos);
133 	}
134 
135 	return(TRUE);
136 }
137 
138 /*	mouse-region-down:	mouse region operations
139 
140 	nclicks = 0:	move cursor to mouse
141 			if hiliting then
142 				hilite set-mark
143 			set-mark
144 
145 		  1:	move cursor to mouse
146 			kill-region
147 */
148 
mregdown(f,n)149 PASCAL NEAR mregdown(f, n)
150 
151 int f,n;	/* prefix flag and argument */
152 
153 {
154 	register EWINDOW *wp;
155 	register EWINDOW *lastwp;
156 	register LINE	*lp;
157 	SCREEN *sp;
158 	char scr_name[12];		/* constructed temp screen name */
159 	static int temp_count = 0;	/* next temp screen number! */
160 
161 	/* make sure we are on the proper screen */
162 	mouse_screen();
163 
164 	/* adjust position by screen offset */
165 	ypos -= term.t_roworg;
166 	xpos -= term.t_colorg;
167 
168 	/* if anything has changed, reset the click count */
169 	if (((lastmcmd != MREGUP) && (lastmcmd != MREGDWN))
170 	    || lastypos != ypos || lastxpos != xpos)
171 		nclicks = 0;
172 	++nclicks;
173 	lastwp = mousewindow(lastypos);		/* remember last window */
174 
175 	/* reset the last position */
176 	lastypos = ypos;
177 	lastxpos = xpos;
178 	lastmcmd = MREGDWN;
179 
180 #if	!WINDOW_MSWIN
181 	/* if we are in the upper left corner, create a new window */
182 	if (xpos == 0 && ypos == 0) {
183 
184 		/* get the name of the screen to create */
185 		strcpy(scr_name, "SCREEN");
186 		strcat(scr_name, int_asc(temp_count++));
187 		while (lookup_screen(scr_name) != (SCREEN *)NULL) {
188 			strcpy(scr_name, "SCREEN");
189 			strcat(scr_name, int_asc(temp_count++));
190 		}
191 
192 		/* save the current dot position in the buffer info
193 		   so the new screen will start there! */
194 		curbp->b_dotp = curwp->w_dotp;
195 		curbp->b_doto = curwp->w_doto;
196 
197 		/* screen does not exist, create it */
198 		sp = init_screen(scr_name, curbp);
199 
200 		/* and make this screen current */
201 		return(select_screen(sp, TRUE));
202 	}
203 #endif
204 
205 	/* if we move the mouse off the windows, don't move anything */
206 	if ((wp=mousewindow(ypos)) == NULL)
207 		return(FALSE);
208 
209 	/* if we are on the line with the point, adjust for extended lines */
210 	if (wp == curwp && (lp = mouseline(wp, ypos)) == curwp->w_dotp)
211 		xpos += lbound;
212 
213 	/* make the window the mouse points to current */
214 	curwp = wp;
215 	curbp = wp->w_bufp;
216 
217 	/* if we changed windows, update the modelines */
218 	if (wp != lastwp)
219 		upmode();
220 
221 	/* if we aren't off the end of the text, move the point to the mouse */
222 	if ((lp=mouseline(wp, ypos)) != NULL) {
223 		curwp->w_dotp = lp;
224 		curwp->w_doto = mouseoffset(wp, lp, xpos);
225 	}
226 
227 	/* perform the region function */
228 	if (nclicks == 1) {
229 		if (hilite < NMARKS) {
230 			curwp->w_markp[hilite+1] = NULL;
231 			curwp->w_marko[hilite+1] = 0;
232 			curwp->w_markp[hilite] = curwp->w_dotp;
233 			curwp->w_marko[hilite] = curwp->w_doto;
234 		}
235 		return(setmark(FALSE, 0));
236 	} else {
237 		lastflag &= ~CFKILL;
238 		return(killregion(FALSE, 0));
239 	}
240 }
241 
242 /*	mouse-region-up:	mouse region operations
243 
244 	If the corrosponding downclick was on a modeline, then we
245 	wish to delete the indicated window. Otherwise we are using
246 	this button to copy/paste.
247 
248 	nclicks = 0:	move cursor to mouse
249 			copy-region
250 
251 		  1:	move cursor to mouse
252 			yank
253 
254 		  3:	reset nclicks to 0
255 */
256 
mregup(f,n)257 PASCAL NEAR mregup(f, n)
258 
259 int f,n;	/* prefix flag and argument */
260 
261 {
262 	register EWINDOW *wp;
263 	register EWINDOW *lastwp;
264 	register LINE *lp;
265 	register SCREEN *sp;		/* ptr to screen to delete */
266 	register int lastmodeline;	/* was the dowbclick on a modeline? */
267 	register int lastcmdline;	/* was the downclick on the command line? */
268 
269 	/* adjust position by screen offset */
270 	ypos -= term.t_roworg;
271 	xpos -= term.t_colorg;
272 
273 	/* if anything has changed, reset the click count */
274 	if (((lastmcmd != MREGUP) && (lastmcmd != MREGDWN))
275 	    || lastypos != ypos || lastxpos != xpos)
276 		nclicks = 0;
277 	++nclicks;
278 	lastwp = mousewindow(lastypos);		/* remember last window */
279 
280 #if	!WINDOW_MSWIN
281 	/* if the down click was in the upper left corner...
282 	   then we are moving a just created screen */
283 	if (lastypos == 0 && lastxpos == 0) {
284 		new_row_org(TRUE, ypos + term.t_roworg);
285 		new_col_org(TRUE, xpos + term.t_colorg);
286 #if	WINDOW_TEXT
287 		refresh_screen(first_screen);
288 #endif
289 		return(TRUE);
290 	}
291 #endif
292 
293 	/* Just where was the last click? */
294 	lastmodeline = ismodeline(lastwp, lastypos);
295 	lastcmdline = (lastypos == term.t_nrow);
296 
297 	/* reset the last position */
298 	lastypos = ypos;
299 	lastxpos = xpos;
300 	lastmcmd = MREGUP;
301 
302 	/* if we started on a modeline.... */
303 	if (lastmodeline)
304 		return(delwind(TRUE, 0));
305 
306 	/* if we are on a command line */
307 	if (lastcmdline) {
308 		if (ypos != term.t_nrow)
309 
310 			/* ABORT ABORT ABORT screen deletion */
311 			return(TRUE);
312 		else {
313 
314 			/* delete the screen last screen means exiting */
315 			if (first_screen->s_next_screen == (SCREEN *)NULL)
316 				return(quit(FALSE, 0));
317 
318 			/* bring the second last screen to front*/
319 			sp = first_screen;
320 			select_screen(sp->s_next_screen, FALSE);
321 
322 			/* and dump the front screen */
323 			first_screen->s_next_screen = sp->s_next_screen;
324 			free_screen(sp);
325 #if	WINDOW_TEXT
326 			refresh_screen(first_screen);
327 #endif
328 			return(TRUE);
329 		}
330 	}
331 
332 	/* if we move the mouse off the windows, don't move anything */
333 	if ((wp=mousewindow(ypos)) == NULL)
334 		return(FALSE);
335 
336 	/* if we are on the line with the point, adjust for extended lines */
337 	if (wp == curwp && (lp = mouseline(wp, ypos)) == curwp->w_dotp)
338 		xpos += lbound;
339 
340 	/* make the window the mouse points to current */
341 	curwp = wp;
342 	curbp = wp->w_bufp;
343 
344 	/* if we aren't off the end of the text, move the point to the mouse */
345 	if ((lp=mouseline(wp, ypos)) != NULL && nclicks < 3) {
346 		curwp->w_dotp = lp;
347 		curwp->w_doto = mouseoffset(wp, lp, xpos);
348 	}
349 
350 	/* if we changed windows, update the modelines, abort the new op */
351 	if (wp != lastwp) {
352 		upmode();
353 		return(TRUE);
354 	}
355 
356 	/* perform the region function */
357 	if (nclicks == 1) {
358 		return(copyregion(FALSE, 0));
359 	} else if (nclicks == 2) {
360 		return(yank(FALSE, 1));
361 	} else {
362 		nclicks = 0;
363 		return(TRUE);
364 	}
365 }
366 
367 /*
368  * Move mouse button, up. The up click must be
369  * in the text region of a window. If the old click was in a
370  * mode line then the mode line moves to the row of the
371  * up click. If the old click is not in a mode line then the
372  * window scrolls. The code in this function is just
373  * too complex!
374  */
movemu(f,n)375 PASCAL NEAR movemu(f, n)
376 
377 int f,n;	/* prefix flag and argument */
378 
379 {
380 	register EWINDOW *lastwp;
381 	register EWINDOW *wp;
382 	register int lastmodeline;	/* was the downclick on a modeline? */
383 	register int deltay;
384 	register int deltax;
385 #if	WINDOW_TEXT
386 	register int redraw_needed;	/* is a screen redraw required */
387 #endif
388 
389 	/* adjust position by screen offset */
390 	ypos -= term.t_roworg;
391 	xpos -= term.t_colorg;
392 
393 	/* no movement... fail the command */
394 	if (lastypos==ypos && lastxpos==xpos)
395 		return(FALSE);
396 
397 #if	!WINDOW_MSWIN
398 	/* if the down click was in the bottom right corner...
399 	   then we are resizing */
400 	if (lastypos == term.t_nrow && lastxpos + 1 == term.t_ncol) {
401 #if	WINDOW_TEXT
402 		if (xpos < term.t_ncol || ypos < term.t_nrow)
403 			redraw_needed = TRUE;
404 		else
405 			redraw_needed = FALSE;
406 #endif
407 		newwidth(TRUE, xpos + 1);
408 		newsize(TRUE, ypos + 1);
409 #if	WINDOW_TEXT
410 		if (redraw_needed) {
411 			refresh_screen(first_screen);
412 		}
413 #endif
414 		return(TRUE);
415 	}
416 
417 	/* if the down click was in the upper left corner...
418 	   then we are moving the screen */
419 	if (lastypos == 0 && lastxpos == 0) {
420 		new_row_org(TRUE, ypos + term.t_roworg);
421 		new_col_org(TRUE, xpos + term.t_colorg);
422 #if	WINDOW_TEXT
423 		refresh_screen(first_screen);
424 #endif
425 		return(TRUE);
426 	}
427 #endif
428 
429 	/* if the down click was not in a window.. fail the command
430 	   (for example, if we click on the command line) */
431 	if ((lastwp=mousewindow(lastypos)) == NULL)
432 		return(FALSE);
433 
434 	/* did we down click on a modeline? */
435 	lastmodeline = ismodeline(lastwp, lastypos);
436 
437 	/* are we not in a window? fail it then */
438 	if ((wp=mousewindow(ypos)) == NULL)
439 		return(FALSE);
440 
441 	/* how far did we move? */
442 	deltay = lastypos-ypos;
443 	deltax = lastxpos-xpos;
444 	lastypos = ypos;
445 	lastxpos = xpos;
446 
447 	/* if we started on a modeline.... */
448 	if (lastmodeline) {
449 
450 		/* move the window horizontally */
451 		if (deltax != 0 && (diagflag || deltay == 0)) {
452 			lastwp->w_fcol += deltax;
453 			if (lastwp->w_fcol < 0)
454 				lastwp->w_fcol = 0;
455 			lastwp->w_flag |= WFMODE|WFHARD;
456 			if (deltay == 0)
457 				return(TRUE);
458 		}
459 
460 		/* don't allow the bottom modeline to move */
461 		if (lastwp->w_wndp == NULL)
462 			return(FALSE);
463 
464 		/* shrink the current window */
465 		if (deltay > 0) {
466 			if (lastwp != wp)
467 				return(FALSE);
468 			curwp = wp;
469 			curbp = wp->w_bufp;
470 			return(shrinkwind(TRUE, deltay));
471 		}
472 
473 		/* or grow it */
474 		if (deltay < 0) {
475 			if (wp != lastwp->w_wndp)
476 				return(FALSE);
477 			curwp = lastwp;
478 			curbp = lastwp->w_bufp;
479 			return(enlargewind(TRUE, -deltay));
480 		}
481 	}
482 
483 	/* did we up click in a modeline? fail it them */
484 	if (ismodeline(wp, ypos) != FALSE)
485 		return(FALSE);
486 
487 	/* we can not move outside the current window */
488 	if (lastwp != wp)
489 		return(FALSE);
490 
491 	/* move horizontally as well? */
492 	if (deltax != 0 && (diagflag || deltay == 0)) {
493 		wp->w_fcol += deltax;
494 		if (wp->w_fcol < 0)
495 			wp->w_fcol = 0;
496 		wp->w_flag |= WFMODE;
497 	}
498 
499 	/* and move the screen */
500 	return(mvdnwind(TRUE, deltay));
501 }
502 
503 /*
504  * Return a pointer to the WINDOW structure
505  * for the window in which "row" is located, or NULL
506  * if "row" isn't in any window. The mode line is
507  * considered to be part of the window.
508  */
509 
mousewindow(row)510 EWINDOW *PASCAL NEAR mousewindow(row)
511 
512 register int	row;
513 
514 {
515 	register EWINDOW *wp;
516 
517 	/* must be a positiove row! */
518 	if (row < 0)
519 		return(NULL);
520 
521 	/* step through each window on the active screen */
522 	wp = wheadp;
523 	while (wp != NULL) {
524 
525 		/* is this row within the current window? */
526 		if (row < wp->w_ntrows+1)
527 			return(wp);
528 
529 		/* advance to the next window */
530 		row -= wp->w_ntrows+1;
531 		wp = wp->w_wndp;
532 	}
533 	return(NULL);
534 }
535 
536 /*
537  * The row "row" is a row within the window
538  * whose WINDOW structure is pointed to by the "wp"
539  * argument. Find the associated line, and return a pointer
540  * to it. Return NULL if the mouse is on the mode line,
541  * or if the mouse is pointed off the end of the
542  * text in the buffer.
543  */
544 
mouseline(wp,row)545 LINE *PASCAL NEAR mouseline(wp, row)
546 
547 register EWINDOW *wp;
548 register int	row;
549 
550 {
551 	register LINE	*lp;
552 
553 	row -= wp->w_toprow;
554 	if (row >= wp->w_ntrows + (modeflag ? 0 : 1))
555 		return(NULL);
556 	lp = wp->w_linep;
557 	while (row--) {
558 		if (lp == wp->w_bufp->b_linep)	/* Hit the end.		*/
559 			return(NULL);
560 		lp = lforw(lp);
561 	}
562 	return(lp);
563 }
564 
565 /*
566  * Return the best character offset to use
567  * to describe column "col", as viewed from the line whose
568  * LINE structure is pointed to by "lp".
569  */
570 
mouseoffset(wp,lp,col)571 PASCAL NEAR mouseoffset(wp, lp, col)
572 
573 register EWINDOW *wp;
574 register LINE	*lp;
575 register int	col;
576 
577 {
578 	register int	c;
579 	register int	offset;
580 	register int	curcol;
581 	register int	newcol;
582 
583 	offset = 0;
584 	curcol = 0;
585 	col += wp->w_fcol;	/* adjust for extended lines */
586 	while (offset != lused(lp)) {
587 		newcol = curcol;
588 		if ((c=lgetc(lp, offset)) == '\t' && tabsize > 0)
589 			newcol += -(newcol % tabsize) + (tabsize - 1);
590 		else {
591 			if (disphigh && c > 0x7f) {
592 				newcol += 2;
593 				c -= 0x80;
594 			}
595 			if (c < 0x20 || c == 0x7f)	/* ISCTRL */
596 				++newcol;
597 		}
598 		++newcol;
599 		if (newcol > col)
600 			break;
601 		curcol = newcol;
602 		++offset;
603 	}
604 	return(offset);
605 }
606 
mouse_screen()607 PASCAL NEAR mouse_screen()
608 
609 {
610 	register SCREEN *screen_ptr;	/* screen to test mouse in */
611 
612 	/* if we move the mouse off the windows, check for other windows */
613 	if ((ypos < term.t_roworg) || (xpos < term.t_colorg) ||
614 	    (ypos > term.t_roworg + term.t_nrow) ||
615 	    (xpos >= term.t_colorg + term.t_ncol)) {
616 
617 		/* scan through the other windows */
618 		screen_ptr = first_screen->s_next_screen;
619 		while (screen_ptr != (SCREEN *)NULL) {
620 
621 			/* is the mouse in this window? */
622 			if ((ypos >= screen_ptr->s_roworg) &&
623 			    (xpos >= screen_ptr->s_colorg) &&
624 			    (ypos <= screen_ptr->s_roworg + screen_ptr->s_nrow) &&
625 			    (xpos <= screen_ptr->s_colorg + screen_ptr->s_ncol)) {
626 
627 				/* select this screen */
628 				select_screen(screen_ptr, FALSE);
629 				lastxpos = -1;
630 				lastypos = -1;
631 				break;
632 			}
633 
634 			/* on to the next screen */
635 			screen_ptr = screen_ptr->s_next_screen;
636 		}
637 	}
638 }
639 
ismodeline(wp,row)640 PASCAL NEAR ismodeline(wp, row)
641 
642 EWINDOW *wp;
643 int row;
644 
645 {
646 	/* not on a legal window, say we aren't on a mode line either */
647 	if (wp == (EWINDOW *)NULL)
648 		return(FALSE);
649 
650 	/* are we on a modeline? */
651 	if (row == wp->w_toprow+wp->w_ntrows && modeflag)
652 		return(TRUE);
653 
654 	/* no */
655 	return(FALSE);
656 }
657 
658 /* The mouse has been used to resize the physical window. Now we need to
659    let emacs know about the newsize, and have him force a re-draw
660 */
661 
resizm(f,n)662 PASCAL NEAR resizm(f, n)
663 
664 int f, n;	/* these are ignored... we get the new size info from
665 		   the mouse driver */
666 {
667 #if	WINDOW_TEXT
668 	register int redraw_needed;	/* is a screen redraw required */
669 #endif
670 
671 	/* make sure we are on the proper screen */
672 	mouse_screen();
673 
674 	/* adjust position by screen offset */
675 	ypos -= term.t_roworg;
676 	xpos -= term.t_colorg;
677 
678 #if	WINDOW_TEXT
679 		if (xpos < term.t_ncol || ypos < term.t_nrow)
680 			redraw_needed = TRUE;
681 		else
682 			redraw_needed = FALSE;
683 #endif
684 
685 	/* change to the new size */
686 	newwidth(TRUE, xpos + 1);
687 	newsize(TRUE, ypos + 1);
688 
689 #if	WINDOW_TEXT
690 	if (redraw_needed) {
691 		refresh_screen(first_screen);
692 	}
693 #endif
694 	return(TRUE);
695 }
696 
697 #else
mousehello()698 mousehello()
699 {
700 }
701 #endif
702