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