+#if 0
+static Lisp_Object
+tty_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
+ Lisp_Object how_to_add, Lisp_Object selection_type)
+{
+ /* There is no way to do this cleanly - the GPM selection
+ ** 'protocol' (actually the TIOCLINUX ioctl) requires a start and
+ ** end position on the _screen_, not a string to stick in there.
+ ** Lame.
+ **
+ ** William Perry Nov 4, 1999
+ */
+}
+#endif
+
+/* This function appears to work once in a blue moon. I'm not sure
+** exactly why either. *sigh*
+**
+** William Perry Nov 4, 1999
+**
+** Apparently, this is the way (mouse-position) is supposed to work,
+** and I was just expecting something else. (mouse-pixel-position)
+** works just fine.
+**
+** William Perry Nov 7, 1999
+*/
+static int
+tty_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y)
+{
+ Gpm_Event ev;
+ int num_buttons;
+
+ memset(&ev,'\0',sizeof(ev));
+
+ num_buttons = Gpm_GetSnapshot(&ev);
+
+ if (!num_buttons)
+ {
+ /* This means there are events pending... */
+
+ /* #### In theory, we should drain the events pending, stick
+ ** #### them in the queue, and return the mouse position
+ ** #### anyway.
+ */
+ return(-1);
+ }
+ *x = ev.x;
+ *y = ev.y;
+ *frame = DEVICE_SELECTED_FRAME (d);
+ return (1);
+}
+
+static void
+tty_set_mouse_position (struct window *w, int x, int y)
+{
+ /*
+ #### I couldn't find any GPM functions that set the mouse position.
+ #### Mr. Perry had left this function empty; that must be why.
+ #### karlheg
+ */
+}
+
+static int gpm_event_pending_p (int user_p)
+{
+ Lisp_Object event;
+
+ EVENT_CHAIN_LOOP (event, gpm_event_queue)
+ {
+ if (!user_p || command_event_p (event))
+ {
+ return (1);
+ }
+ }
+ return (orig_event_pending_p (user_p));
+}
+
+static void gpm_next_event_cb (Lisp_Event *event)
+{
+ /* #### It would be nice to preserve some sort of ordering of the
+ ** #### different types of events, but that would be quite a bit
+ ** #### of work, and would more than likely break the abstraction
+ ** #### between the other event loops and this one.
+ */
+
+ if (!NILP (gpm_event_queue))
+ {
+ Lisp_Object queued_event = dequeue_event (&gpm_event_queue, &gpm_event_queue_tail);
+ *event = *(XEVENT (queued_event));
+
+ if (event->event_type == pointer_motion_event)
+ {
+ struct device *d = decode_device (event->channel);
+ int fd = DEVICE_INFD (d);
+
+ /* Ok, now this is just freaky. Bear with me though.
+ **
+ ** If you run gnuclient and attach to a XEmacs running in
+ ** X or on another TTY, the mouse cursor does not get
+ ** drawn correctly. This is because the ioctl() fails
+ ** with EPERM because the TTY specified is not our
+ ** controlling terminal. If you are the superuser, it
+ ** will work just spiffy. The appropriate source file (at
+ ** least in linux 2.2.x) is
+ ** .../linux/drivers/char/console.c in the function
+ ** tioclinux(). The following bit of code is brutal to
+ ** us:
+ **
+ ** if (current->tty != tty && !suser())
+ ** return -EPERM;
+ **
+ ** I even tried setting us as a process leader, removing
+ ** our controlling terminal, and then using the TIOCSCTTY
+ ** to set up a new controlling terminal, all with no luck.
+ **
+ ** What is even weirder is if you run XEmacs in a VC, and
+ ** attach to it from another VC with gnuclient, go back to
+ ** the original VC and hit a key, the mouse pointer
+ ** displays (in BOTH VCs), until you hit a key in the
+ ** second VC, after which it does not display in EITHER
+ ** VC. Bizarre, no?
+ **
+ ** All I can say is thank god Linux comes with source code
+ ** or I would have been completely confused. Well, ok,
+ ** I'm still completely confused. I don't see why they
+ ** don't just check the permissions on the device
+ ** (actually, if you have enough access to it to get the
+ ** console's file descriptor, you should be able to do
+ ** with it as you wish, but maybe that is just me).
+ **
+ ** William M. Perry - Nov 9, 1999
+ */
+
+ Gpm_DrawPointer (event->event.motion.x,event->event.motion.y, fd);
+ }
+
+ return;
+ }
+
+ orig_next_event_cb (event);
+}
+
+static void hook_event_callbacks_once (void)
+{
+ static int hooker;
+
+ if (!hooker)
+ {
+ orig_event_pending_p = event_stream->event_pending_p;
+ orig_next_event_cb = event_stream->next_event_cb;
+ event_stream->event_pending_p = gpm_event_pending_p;
+ event_stream->next_event_cb = gpm_next_event_cb;
+ hooker = 1;
+ }
+}
+
+static void hook_console_methods_once (void)
+{
+ static int hooker;
+
+ if (!hooker)
+ {
+ /* Install the mouse position methods for the TTY console type */
+ CONSOLE_HAS_METHOD (tty, get_mouse_position);
+ CONSOLE_HAS_METHOD (tty, set_mouse_position);
+ CONSOLE_HAS_METHOD (tty, get_foreign_selection);
+ CONSOLE_HAS_METHOD (tty, selection_exists_p);
+#if 0
+ CONSOLE_HAS_METHOD (tty, own_selection);