home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / UE311C.ZIP / MOUSE.C < prev    next >
C/C++ Source or Header  |  1991-10-25  |  16KB  |  652 lines

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