]> ncurses.scripts.mit.edu Git - ncurses.git/blobdiff - ncurses/base/lib_mouse.c
ncurses 5.0
[ncurses.git] / ncurses / base / lib_mouse.c
similarity index 78%
rename from ncurses/lib_mouse.c
rename to ncurses/base/lib_mouse.c
index c4f510db247a1d1ed17c209426e363402560d2a1..d34d48342e4febc339c67c6958a497b70bc5deec 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 1998 Free Software Foundation, Inc.                        *
+ * Copyright (c) 1998,1999 Free Software Foundation, Inc.                   *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -36,7 +36,7 @@
  * devices.
  *
  * The first method used is xterm's internal mouse-tracking facility.
- * The second (not yet implemented) will be Alessandro Rubini's GPM server.
+ * The second is Alessandro Rubini's GPM server.
  *
  * Notes for implementors of new mouse-interface methods:
  *
  * used yet, and a couple of bits open at the high end.
  */
 
+#ifdef __EMX__
+#  include "io.h"
+#  include "fcntl.h"
+#  define  INCL_DOS
+#  define  INCL_VIO
+#  define  INCL_KBD
+#  define  INCL_MOU
+#  define  INCL_DOSPROCESS
+#  include <os2.h>             /* Need to include before the others */
+#endif
+
 #include <curses.priv.h>
 #include <term.h>
 
 #if USE_GPM_SUPPORT
-#ifndef LINT           /* don't need this for llib-lncurses */
-#undef buttons         /* term.h defines this, and gpm uses it! */
+#ifndef LINT                   /* don't need this for llib-lncurses */
+#undef buttons                 /* term.h defines this, and gpm uses it! */
 #include <gpm.h>
+#include <linux/keyboard.h>    /* defines KG_* macros */
 #endif
 #endif
 
-MODULE_ID("$Id: lib_mouse.c,v 1.35 1998/02/11 12:13:55 tom Exp $")
+MODULE_ID("$Id: lib_mouse.c,v 1.45 1999/10/22 21:39:02 tom Exp $")
 
 #define MY_TRACE TRACE_ICALLS|TRACE_IEVENT
 
@@ -117,24 +129,104 @@ static void _trace_slot(const char *tag)
        _tracef(tag);
 
        for (ep = events; ep < events + EV_MAX; ep++)
-               _tracef("mouse event queue slot %d = %s", ep-events, _tracemouse(ep));
+               _tracef("mouse event queue slot %ld = %s",
+                       (long) (ep - events),
+                       _tracemouse(ep));
 }
 #endif
 
-/* FIXME: The list of names should be configurable */
-static int is_xterm(const char *name)
+#ifdef USE_EMX_MOUSE
+
+#  define TOP_ROW          0
+#  define LEFT_COL         0
+
+static int mouse_wfd;
+static int mouse_thread;
+static int mouse_activated;
+static char mouse_buttons[] = { 0, 1, 3, 2};
+
+
+#  define M_FD(sp) sp->_mouse_fd
+
+static void
+write_event(int down, int button, int x, int y)
 {
-    return (!strncmp(name, "xterm", 5)
-      ||    !strncmp(name, "rxvt",  4)
-      ||    !strncmp(name, "kterm", 5)
-      ||    !strncmp(name, "color_xterm", 11));
+    char buf[6];
+    unsigned long ignore;
+
+    strcpy(buf, key_mouse);
+    buf[3] = ' ' + (button - 1) + (down ? 0 : 0x40);
+    buf[4] = ' ' + x - LEFT_COL + 1;
+    buf[5] = ' ' + y - TOP_ROW + 1;
+    DosWrite(mouse_wfd, buf, 6, &ignore);
 }
 
+static void
+mouse_server(unsigned long ignored GCC_UNUSED)
+{
+    unsigned short fWait = MOU_WAIT;
+    /* NOPTRRECT mourt = { 0,0,24,79 }; */
+    MOUEVENTINFO mouev;
+    HMOU hmou;
+    unsigned short mask = MOUSE_BN1_DOWN | MOUSE_BN2_DOWN | MOUSE_BN3_DOWN;
+    int oldstate = 0;
+    char errmess[] = "Unexpected termination of mouse thread\r\n";
+    unsigned long ignore;
+
+    /* open the handle for the mouse */
+    if (MouOpen(NULL,&hmou) == 0) {
+
+       if (MouSetEventMask(&mask,hmou) == 0
+        && MouDrawPtr(hmou) == 0) {
+
+           for (;;) {
+               /* sit and wait on the event queue */
+               if (MouReadEventQue(&mouev,&fWait,hmou))
+                       break;
+               if (!mouse_activated)
+                   goto finish;
+
+               /*
+                * OS/2 numbers a 3-button mouse inconsistently from other
+                * platforms:
+                *      1 = left
+                *      2 = right
+                *      3 = middle.
+                */
+               if ((mouev.fs ^ oldstate) & MOUSE_BN1_DOWN)
+                   write_event(mouev.fs  & MOUSE_BN1_DOWN,
+                               mouse_buttons[1], mouev.col, mouev.row);
+               if ((mouev.fs ^ oldstate) & MOUSE_BN2_DOWN)
+                   write_event(mouev.fs  & MOUSE_BN2_DOWN,
+                               mouse_buttons[3], mouev.col, mouev.row);
+               if ((mouev.fs ^ oldstate) & MOUSE_BN3_DOWN)
+                   write_event(mouev.fs  & MOUSE_BN3_DOWN,
+                               mouse_buttons[2], mouev.col, mouev.row);
+
+             finish:
+               oldstate = mouev.fs;
+           }
+       }
+
+       DosWrite(2, errmess, strlen(errmess), &ignore);
+       MouClose(hmou);
+    }
+    DosExit(EXIT_THREAD, 0L );
+}
+static void
+server_state(const int state)
+{ /* It would be nice to implement pointer-off and stop looping... */
+    mouse_activated = state;
+}
+
+#endif
+
+static int initialized;
+
 static void _nc_mouse_init(void)
 /* initialize the mouse */
 {
     int i;
-    static int initialized;
 
     if (initialized) {
        return;
@@ -148,7 +240,7 @@ static void _nc_mouse_init(void)
 
     /* we know how to recognize mouse events under xterm */
     if (key_mouse != 0
-     && is_xterm(cur_term->type.term_names))
+     && getenv("DISPLAY") != 0)
        mousetype = M_XTERM;
 
 #if USE_GPM_SUPPORT
@@ -156,9 +248,9 @@ static void _nc_mouse_init(void)
     {
        /* GPM: initialize connection to gpm server */
        gpm_connect.eventMask = GPM_DOWN|GPM_UP;
-       gpm_connect.defaultMask = ~gpm_connect.eventMask;
+       gpm_connect.defaultMask = ~(gpm_connect.eventMask|GPM_HARD);
        gpm_connect.minMod = 0;
-       gpm_connect.maxMod = ~0;
+       gpm_connect.maxMod = ~((1<<KG_SHIFT)|(1<<KG_SHIFTL)|(1<<KG_SHIFTR));
        if (Gpm_Open (&gpm_connect, 0) >= 0) { /* returns the file-descriptor */
            mousetype = M_GPM;
            SP->_mouse_fd = gpm_fd;
@@ -166,6 +258,40 @@ static void _nc_mouse_init(void)
     }
 #endif
 
+    /* OS/2 VIO */
+#ifdef USE_EMX_MOUSE
+    if (!mouse_thread && mousetype != M_XTERM && key_mouse) {
+       int handles[2];
+       if (pipe(handles) < 0) {
+           perror("mouse pipe error");
+       } else {
+           int rc;
+
+           if (!mouse_buttons[0]) {
+               char *s = getenv("MOUSE_BUTTONS_123");
+
+               mouse_buttons[0] = 1;
+               if (s && strlen(s) >= 3) {
+                   mouse_buttons[1] = s[0] - '0';
+                   mouse_buttons[2] = s[1] - '0';
+                   mouse_buttons[3] = s[2] - '0';
+               }
+           }
+           mouse_wfd = handles[1];
+           M_FD(SP) = handles[0];
+           /* Needed? */
+           setmode(handles[0], O_BINARY);
+           setmode(handles[1], O_BINARY);
+           /* Do not use CRT functions, we may single-threaded. */
+           rc = DosCreateThread((unsigned long*)&mouse_thread, mouse_server, 0, 0, 8192);
+           if (rc)
+               printf("mouse thread error %d=%#x", rc, rc);
+           else
+               mousetype = M_XTERM;
+       }
+    }
+#endif
+
     T(("_nc_mouse_init() set mousetype to %d", mousetype));
 }
 
@@ -257,7 +383,13 @@ static bool _nc_mouse_inline(SCREEN *sp)
         */
        for (grabbed = 0; grabbed < 3; grabbed += res)
        {
+
+       /* For VIO mouse we add extra bit 64 to disambiguate button-up. */
+#ifdef USE_EMX_MOUSE
+            res = read( M_FD(sp) >= 0 ? M_FD(sp) : sp->_ifd, &kbuf, 3);
+#else
             res = read(sp->_ifd, kbuf + grabbed, 3-grabbed);
+#endif
             if (res == -1)
                 break;
        }
@@ -273,14 +405,26 @@ static bool _nc_mouse_inline(SCREEN *sp)
        {
        case 0x0:
            eventp->bstate = BUTTON1_PRESSED;
+#ifdef USE_EMX_MOUSE
+           if (kbuf[0] & 0x40)
+               eventp->bstate = BUTTON1_RELEASED;
+#endif
            break;
 
        case 0x1:
            eventp->bstate = BUTTON2_PRESSED;
+#ifdef USE_EMX_MOUSE
+           if (kbuf[0] & 0x40)
+               eventp->bstate = BUTTON2_RELEASED;
+#endif
            break;
 
        case 0x2:
            eventp->bstate = BUTTON3_PRESSED;
+#ifdef USE_EMX_MOUSE
+           if (kbuf[0] & 0x40)
+               eventp->bstate = BUTTON3_RELEASED;
+#endif
            break;
 
        case 0x3:
@@ -320,7 +464,9 @@ static bool _nc_mouse_inline(SCREEN *sp)
 
        eventp->x = (kbuf[1] - ' ') - 1;
        eventp->y = (kbuf[2] - ' ') - 1;
-       TR(MY_TRACE, ("_nc_mouse_inline: primitive mouse-event %s has slot %d", _tracemouse(eventp), eventp - events));
+       TR(MY_TRACE, ("_nc_mouse_inline: primitive mouse-event %s has slot %ld",
+               _tracemouse(eventp),
+               (long) (eventp - events)));
 
        /* bump the next-free pointer into the circular list */
        eventp = NEXT(eventp);
@@ -334,6 +480,9 @@ static bool _nc_mouse_inline(SCREEN *sp)
 
 static void mouse_activate(bool on)
 {
+    if (!on && !initialized)
+       return;
+
     _nc_mouse_init();
 
     if (on) {
@@ -344,7 +493,11 @@ static void mouse_activate(bool on)
            keyok(KEY_MOUSE, on);
 #endif
            TPUTS_TRACE("xterm mouse initialization");
+#ifdef USE_EMX_MOUSE
+           server_state(1);
+#else
            putp("\033[?1000h");
+#endif
            break;
 #if USE_GPM_SUPPORT
        case M_GPM:
@@ -366,7 +519,11 @@ static void mouse_activate(bool on)
        switch (mousetype) {
        case M_XTERM:
            TPUTS_TRACE("xterm mouse deinitialization");
+#ifdef USE_EMX_MOUSE
+           server_state(0);
+#else
            putp("\033[?1000l");
+#endif
            break;
 #if USE_GPM_SUPPORT
        case M_GPM:
@@ -374,7 +531,7 @@ static void mouse_activate(bool on)
 #endif
        }
     }
-    (void) fflush(SP->_ofp);
+    _nc_flush();
 }
 
 /**************************************************************************
@@ -415,8 +572,9 @@ static bool _nc_mouse_parse(int runcount)
      */
     if (runcount == 1)
     {
-       TR(MY_TRACE, ("_nc_mouse_parse: returning simple mouse event %s at slot %d",
-          _tracemouse(prev), prev-events));
+       TR(MY_TRACE, ("_nc_mouse_parse: returning simple mouse event %s at slot %ld",
+          _tracemouse(prev),
+          (long) (prev - events)));
        return (prev->id >= 0)
                ? ((prev->bstate & eventmask) ? TRUE : FALSE)
                : FALSE;
@@ -432,8 +590,10 @@ static bool _nc_mouse_parse(int runcount)
     if (_nc_tracing & TRACE_IEVENT)
     {
        _trace_slot("before mouse press/release merge:");
-       _tracef("_nc_mouse_parse: run starts at %d, ends at %d, count %d",
-           runp-events, ((eventp - events) + (EV_MAX-1)) % EV_MAX, runcount);
+       _tracef("_nc_mouse_parse: run starts at %ld, ends at %ld, count %d",
+           (long) (runp - events),
+           (long) ((eventp - events) + (EV_MAX-1)) % EV_MAX,
+           runcount);
     }
 #endif /* TRACE */
 
@@ -484,8 +644,10 @@ static bool _nc_mouse_parse(int runcount)
     if (_nc_tracing & TRACE_IEVENT)
     {
        _trace_slot("before mouse click merge:");
-       _tracef("_nc_mouse_parse: run starts at %d, ends at %d, count %d",
-           runp-events, ((eventp - events) + (EV_MAX-1)) % EV_MAX, runcount);
+       _tracef("_nc_mouse_parse: run starts at %ld, ends at %ld, count %d",
+           (long) (runp - events),
+           (long) ((eventp - events) + (EV_MAX-1)) % EV_MAX,
+           runcount);
     }
 #endif /* TRACE */
 
@@ -589,8 +751,10 @@ static bool _nc_mouse_parse(int runcount)
     if (_nc_tracing & TRACE_IEVENT)
     {
        _trace_slot("before mouse event queue compaction:");
-       _tracef("_nc_mouse_parse: run starts at %d, ends at %d, count %d",
-           runp-events, ((eventp - events) + (EV_MAX-1)) % EV_MAX, runcount);
+       _tracef("_nc_mouse_parse: run starts at %ld, ends at %ld, count %d",
+           (long) (runp - events),
+           (long) ((eventp - events) + (EV_MAX-1)) % EV_MAX,
+           runcount);
     }
 #endif /* TRACE */
 
@@ -607,13 +771,16 @@ static bool _nc_mouse_parse(int runcount)
     if (_nc_tracing & TRACE_IEVENT)
     {
        _trace_slot("after mouse event queue compaction:");
-       _tracef("_nc_mouse_parse: run starts at %d, ends at %d, count %d",
-           runp-events, ((eventp - events) + (EV_MAX-1)) % EV_MAX, runcount);
+       _tracef("_nc_mouse_parse: run starts at %ld, ends at %ld, count %d",
+           (long) (runp - events),
+           (long) ((eventp - events) + (EV_MAX-1)) % EV_MAX,
+           runcount);
     }
     for (ep = runp; ep != eventp; ep = NEXT(ep))
        if (ep->id != INVALID_EVENT)
-           TR(MY_TRACE, ("_nc_mouse_parse: returning composite mouse event %s at slot %d",
-               _tracemouse(ep), ep-events));
+           TR(MY_TRACE, ("_nc_mouse_parse: returning composite mouse event %s at slot %ld",
+               _tracemouse(ep),
+               (long) (ep - events)));
 #endif /* TRACE */
 
     /* after all this, do we have a valid event? */
@@ -627,9 +794,9 @@ static void _nc_mouse_wrap(SCREEN *sp GCC_UNUSED)
 
     switch (mousetype) {
     case M_XTERM:
-        if (eventmask)
-            mouse_activate(FALSE);
-        break;
+       if (eventmask)
+           mouse_activate(FALSE);
+       break;
 #if USE_GPM_SUPPORT
        /* GPM: pass all mouse events to next client */
        case M_GPM:
@@ -669,8 +836,9 @@ int getmouse(MEVENT *aevent)
        /* copy the event we find there */
        *aevent = *prev;
 
-       TR(TRACE_IEVENT, ("getmouse: returning event %s from slot %d",
-           _tracemouse(prev), prev-events));
+       TR(TRACE_IEVENT, ("getmouse: returning event %s from slot %ld",
+           _tracemouse(prev),
+           (long) (prev - events)));
 
        prev->id = INVALID_EVENT;       /* so the queue slot becomes free */
        returnCode(OK);
@@ -701,6 +869,9 @@ mmask_t mousemask(mmask_t newmask, mmask_t *oldmask)
     if (oldmask)
        *oldmask = eventmask;
 
+    if (!newmask && !initialized)
+       returnCode(0);
+
     _nc_mouse_init();
     if ( mousetype != M_NONE )
     {
@@ -757,4 +928,37 @@ int _nc_has_mouse(void) {
   return (mousetype==M_NONE ? 0:1);
 }
 
+bool wmouse_trafo(const WINDOW* win, int* pY, int* pX, bool to_screen)
+{
+  bool result = FALSE;
+
+  if (win && pY && pX)
+    {
+      int y = *pY; int x = *pX;
+
+      if (to_screen)
+       {
+         y += win->_begy + win->_yoffset;
+         x += win->_begx;
+         if (wenclose(win,y,x))
+           result = TRUE;
+       }
+      else
+       {
+         if (wenclose(win,y,x))
+           {
+             y -= (win->_begy + win->_yoffset);
+             x -= win->_begx;
+             result = TRUE;
+           }
+       }
+      if (result)
+       {
+         *pX = x;
+         *pY = y;
+       }
+    }
+  return(result);
+}
+
 /* lib_mouse.c ends here */