comparison src/gpmevent.c @ 793:e38acbeb1cae

[xemacs-hg @ 2002-03-29 04:46:17 by ben] lots o' fixes etc/ChangeLog: New file. Separated out all entries for etc/ into their own ChangeLog. Includes entries for the following files: etc/BABYL, etc/BETA, etc/CHARSETS, etc/DISTRIB, etc/Emacs.ad, etc/FTP, etc/GNUS-NEWS, etc/GOATS, etc/HELLO, etc/INSTALL, etc/MACHINES, etc/MAILINGLISTS, etc/MSDOS, etc/MYTHOLOGY, etc/NEWS, etc/OXYMORONS, etc/PACKAGES, etc/README, etc/TUTORIAL, etc/TUTORIAL.de, etc/TUTORIAL.ja, etc/TUTORIAL.ko, etc/TUTORIAL.se, etc/aliases.ksh, etc/altrasoft-logo.xpm, etc/check_cygwin_setup.sh, etc/custom/example-themes/europe-theme.el, etc/custom/example-themes/ex-custom-file, etc/custom/example-themes/example-theme.el, etc/e/eterm.ti, etc/edt-user.doc, etc/enriched.doc, etc/etags.1, etc/gnuserv.1, etc/gnuserv.README, etc/package-index.LATEST.gpg, etc/package-index.LATEST.pgp, etc/photos/jan.png, etc/recycle.xpm, etc/refcard.tex, etc/sample.Xdefaults, etc/sample.emacs, etc/sgml/CATALOG, etc/sgml/HTML32.dtd, etc/skk/SKK.tut.E, etc/smilies/Face_ase.xbm, etc/smilies/Face_ase2.xbm, etc/smilies/Face_ase3.xbm, etc/smilies/Face_smile.xbm, etc/smilies/Face_weep.xbm, etc/sounds, etc/toolbar, etc/toolbar/workshop-cap-up.xpm, etc/xemacs-ja.1, etc/xemacs.1, etc/yow.lines, etc\BETA, etc\NEWS, etc\README, etc\TUTORIAL, etc\TUTORIAL.de, etc\check_cygwin_setup.sh, etc\sample.init.el, etc\unicode\README, etc\unicode\mule-ucs\*, etc\unicode\other\* unicode/unicode-consortium/8859-16.TXT: New file. mule/english.el: Define this charset now, since a bug was fixed that formerly prevented it. mule/ethio-util.el: Fix compile errors involving Unicode `characters', which should be integers. Makefile.in.in: Always include gui.c, to fix compile error when TTY-only. EmacsFrame.c, abbrev.c, alloc.c, buffer.c, buffer.h, bytecode.c, bytecode.h, callint.c, callproc.c, casetab.c, casetab.h, charset.h, chartab.c, chartab.h, cmds.c, console-msw.c, console-msw.h, console-tty.c, console-x.c, console-x.h, console.c, console.h, data.c, database.c, device-gtk.c, device-msw.c, device-x.c, device.c, device.h, dialog-msw.c, doc.c, doprnt.c, dumper.c, dynarr.c, editfns.c, eldap.c, eldap.h, elhash.c, elhash.h, emacs.c, eval.c, event-Xt.c, event-gtk.c, event-msw.c, event-stream.c, event-tty.c, event-unixoid.c, events.c, events.h, extents.c, extents.h, faces.c, faces.h, file-coding.c, file-coding.h, fileio.c, filelock.c, fns.c, frame-gtk.c, frame-msw.c, frame-tty.c, frame-x.c, frame.c, frame.h, free-hook.c, general-slots.h, glyphs-eimage.c, glyphs-gtk.c, glyphs-msw.c, glyphs-widget.c, glyphs-x.c, glyphs.c, glyphs.h, gpmevent.c, gtk-xemacs.c, gui-msw.c, gui-x.c, gui-x.h, gui.c, gui.h, gutter.c, gutter.h, indent.c, input-method-xlib.c, insdel.c, keymap.c, keymap.h, lisp-disunion.h, lisp-union.h, lisp.h, lread.c, lrecord.h, lstream.c, lstream.h, marker.c, menubar-gtk.c, menubar-msw.c, menubar-x.c, menubar.c, minibuf.c, mule-canna.c, mule-ccl.c, mule-charset.c, mule-wnnfns.c, native-gtk-toolbar.c, objects-msw.c, objects-tty.c, objects-x.c, objects.c, objects.h, opaque.c, opaque.h, postgresql.c, postgresql.h, print.c, process-unix.c, process.c, process.h, rangetab.c, rangetab.h, redisplay-gtk.c, redisplay-msw.c, redisplay-output.c, redisplay-tty.c, redisplay-x.c, redisplay.c, scrollbar-gtk.c, scrollbar-msw.c, scrollbar-x.c, scrollbar.c, scrollbar.h, search.c, select-gtk.c, select-x.c, sound.c, specifier.c, specifier.h, strftime.c, symbols.c, symeval.h, syntax.h, text.c, text.h, toolbar-common.c, toolbar-msw.c, toolbar.c, toolbar.h, tooltalk.c, tooltalk.h, ui-gtk.c, ui-gtk.h, undo.c, vm-limit.c, window.c, window.h: Eliminate XSETFOO. Replace all usages with wrap_foo(). Make symbol->name a Lisp_Object, not Lisp_String *. Eliminate nearly all uses of Lisp_String * in favor of Lisp_Object, and correct macros so most of them favor Lisp_Object. Create new error-behavior ERROR_ME_DEBUG_WARN -- output warnings, but at level `debug' (usually ignored). Use it when instantiating specifiers, so problems can be debugged. Move log-warning-minimum-level into C so that we can optimize ERROR_ME_DEBUG_WARN. Fix warning levels consistent with new definitions. Add default_ and parent fields to char table; not yet implemented. New fun Dynarr_verify(); use for further error checking on Dynarrs. Rearrange code at top of lisp.h in conjunction with dynarr changes. Fix eifree(). Use Eistrings in various places (format_event_object(), where_is_to_char(), and callers thereof) to avoid fixed-size strings buffers. New fun write_eistring(). Reindent and fix GPM code to follow standards. Set default MS Windows font to Lucida Console (same size as Courier New but less interline spacing, so more lines fit). Increase default frame size on Windows to 50 lines. (If that's too big for the workspace, the frame will be shrunk as necessary.) Fix problem with text files with no newlines (). (Change `convert-eol' coding system to use `nil' for autodetect, consistent with make-coding-system.) Correct compile warnings in vm-limit.c. Fix handling of reverse-direction charsets to avoid errors when opening (e.g.) mule-ucs/lisp/reldata/uiso8859-6.el. Recode some object printing methods to use write_fmt_string() instead of a fixed buffer and sprintf. Turn on display of png comments as warnings (level `info'), now that they're unobtrusive. Revamped the sound documentation. Fixed bug in redisplay w.r.t. hscroll/truncation/continuation glyphs causing jumping up and down of the lines, since they're bigger than the line size. (It was seen most obviously when there's a horizontal scroll bar, e.g. do C-h a glyph or something like that.) The problem was that the glyph-contrib-p setting on glyphs was ignored even if it was set properly, which it wasn't until now.
author ben
date Fri, 29 Mar 2002 04:49:13 +0000
parents fdefd0186b75
children 2b6fa2618f76
comparison
equal deleted inserted replaced
792:4e83fdb13eb9 793:e38acbeb1cae
1 /* GPM (General purpose mouse) functions 1 /* GPM (General purpose mouse) functions
2 Copyright (C) 1997 William M. Perry <wmperry@gnu.org> 2 Copyright (C) 1997 William M. Perry <wmperry@gnu.org>
3 Copyright (C) 1999 Free Software Foundation, Inc. 3 Copyright (C) 1999 Free Software Foundation, Inc.
4 4 Copyright (C) 2002 Ben Wing.
5 This file is part of XEmacs. 5
6 6 This file is part of XEmacs.
7 XEmacs is free software; you can redistribute it and/or modify it 7
8 under the terms of the GNU General Public License as published by the 8 XEmacs is free software; you can redistribute it and/or modify it
9 Free Software Foundation; either version 2, or (at your option) any 9 under the terms of the GNU General Public License as published by the
10 later version. 10 Free Software Foundation; either version 2, or (at your option) any
11 11 later version.
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT 12
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 for more details. 15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 16 for more details.
17 You should have received a copy of the GNU General Public License 17
18 along with XEmacs; see the file COPYING. If not, write to 18 You should have received a copy of the GNU General Public License
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 along with XEmacs; see the file COPYING. If not, write to
20 Boston, MA 02111-1307, USA. */ 20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
21 22
22 /* Synched up with: Not in FSF. */ 23 /* Synched up with: Not in FSF. */
23 24
24 /* Authors: William Perry */ 25 /* Authors: William Perry */
25 26
26 #include <config.h> 27 #include <config.h>
27 #include "lisp.h" 28 #include "lisp.h"
29
30 #include "commands.h"
31 #include "console-tty.h"
28 #include "console.h" 32 #include "console.h"
29 #include "console-tty.h"
30 #include "device.h" 33 #include "device.h"
31 #include "events.h" 34 #include "events.h"
35 #include "lstream.h"
36 #include "process.h"
32 #include "sysdep.h" 37 #include "sysdep.h"
33 #include "commands.h" 38
34 #include "lstream.h"
35 #include "sysproc.h" /* for MAXDESC */ 39 #include "sysproc.h" /* for MAXDESC */
36 #include "process.h"
37 40
38 #ifdef HAVE_GPM 41 #ifdef HAVE_GPM
39 #include "gpmevent.h" 42 #include "gpmevent.h"
40 #include <gpm.h> 43 #include <gpm.h>
41 44
50 static void (*orig_next_event_cb) (Lisp_Event *); 53 static void (*orig_next_event_cb) (Lisp_Event *);
51 54
52 static Lisp_Object gpm_event_queue; 55 static Lisp_Object gpm_event_queue;
53 static Lisp_Object gpm_event_queue_tail; 56 static Lisp_Object gpm_event_queue_tail;
54 57
55 struct __gpm_state { 58 struct __gpm_state
56 int gpm_tried; 59 {
57 int gpm_flag; 60 int gpm_tried;
58 void *gpm_stack; 61 int gpm_flag;
62 void *gpm_stack;
59 }; 63 };
60 64
61 static struct __gpm_state gpm_state_information[MAXDESC]; 65 static struct __gpm_state gpm_state_information[MAXDESC];
62 66
63 static void 67 static void
64 store_gpm_state (int fd) 68 store_gpm_state (int fd)
65 { 69 {
66 gpm_state_information[fd].gpm_tried = gpm_tried; 70 gpm_state_information[fd].gpm_tried = gpm_tried;
67 gpm_state_information[fd].gpm_flag = gpm_flag; 71 gpm_state_information[fd].gpm_flag = gpm_flag;
68 gpm_state_information[fd].gpm_stack = gpm_stack; 72 gpm_state_information[fd].gpm_stack = gpm_stack;
69 } 73 }
70 74
71 static void 75 static void
72 restore_gpm_state (int fd) 76 restore_gpm_state (int fd)
73 { 77 {
74 gpm_tried = gpm_state_information[fd].gpm_tried; 78 gpm_tried = gpm_state_information[fd].gpm_tried;
75 gpm_flag = gpm_state_information[fd].gpm_flag; 79 gpm_flag = gpm_state_information[fd].gpm_flag;
76 gpm_stack = gpm_state_information[fd].gpm_stack; 80 gpm_stack = gpm_state_information[fd].gpm_stack;
77 gpm_consolefd = gpm_fd = fd; 81 gpm_consolefd = gpm_fd = fd;
78 } 82 }
79 83
80 static void 84 static void
81 clear_gpm_state (int fd) 85 clear_gpm_state (int fd)
82 { 86 {
83 if (fd >= 0) 87 if (fd >= 0)
84 { 88 memset (&gpm_state_information[fd], '\0', sizeof (struct __gpm_state));
85 memset(&gpm_state_information[fd], '\0', sizeof(struct __gpm_state)); 89 gpm_tried = gpm_flag = 1;
86 } 90 gpm_fd = gpm_consolefd = -1;
87 gpm_tried = gpm_flag = 1; 91 gpm_stack = NULL;
88 gpm_fd = gpm_consolefd = -1;
89 gpm_stack = NULL;
90 } 92 }
91 93
92 static int 94 static int
93 get_process_infd (Lisp_Process *p) 95 get_process_infd (Lisp_Process *p)
94 { 96 {
102 Run GPM_GetEvent(). 104 Run GPM_GetEvent().
103 This function is the process handler for the GPM connection. 105 This function is the process handler for the GPM connection.
104 */ 106 */
105 (process, string)) 107 (process, string))
106 { 108 {
107 Gpm_Event ev; 109 Gpm_Event ev;
108 int modifiers = 0; 110 int modifiers = 0;
109 int button = 1; 111 int button = 1;
110 Lisp_Object fake_event = Qnil; 112 Lisp_Object fake_event = Qnil;
111 Lisp_Event *event = NULL; 113 Lisp_Event *event = NULL;
112 struct gcpro gcpro1; 114 struct gcpro gcpro1;
113 static int num_events; 115 static int num_events;
114 116
115 CHECK_PROCESS (process); 117 CHECK_PROCESS (process);
116 118
117 restore_gpm_state (get_process_infd (XPROCESS (process))); 119 restore_gpm_state (get_process_infd (XPROCESS (process)));
118 120
119 if (!Gpm_GetEvent(&ev)) 121 if (!Gpm_GetEvent (&ev))
120 { 122 {
121 warn_when_safe (Qnil, Qcritical, "Gpm_GetEvent failed - %d", gpm_fd); 123 warn_when_safe (Qnil, Qerror,
122 return(Qzero); 124 "Gpm_GetEvent failed - %d", gpm_fd);
123 } 125 return (Qzero);
124 126 }
125 GCPRO1(fake_event); 127
126 128 GCPRO1 (fake_event);
127 num_events++; 129
128 130 num_events++;
129 fake_event = Fmake_event (Qnil, Qnil); 131
130 event = XEVENT(fake_event); 132 fake_event = Fmake_event (Qnil, Qnil);
131 133 event = XEVENT (fake_event);
132 event->timestamp = 0; 134
133 event->channel = Fselected_frame (Qnil); /* CONSOLE_SELECTED_FRAME (con); */ 135 event->timestamp = 0;
134 136 event->channel = Fselected_frame (Qnil); /* CONSOLE_SELECTED_FRAME (con); */
135 /* Whow, wouldn't named defines be NICE!?!?! */ 137
136 modifiers = 0; 138 /* Whow, wouldn't named defines be NICE!?!?! */
137 139 modifiers = 0;
138 if (ev.modifiers & 1) modifiers |= XEMACS_MOD_SHIFT; 140
139 if (ev.modifiers & 2) modifiers |= XEMACS_MOD_META; 141 if (ev.modifiers & 1) modifiers |= XEMACS_MOD_SHIFT;
140 if (ev.modifiers & 4) modifiers |= XEMACS_MOD_CONTROL; 142 if (ev.modifiers & 2) modifiers |= XEMACS_MOD_META;
141 if (ev.modifiers & 8) modifiers |= XEMACS_MOD_META; 143 if (ev.modifiers & 4) modifiers |= XEMACS_MOD_CONTROL;
142 144 if (ev.modifiers & 8) modifiers |= XEMACS_MOD_META;
143 if (ev.buttons & GPM_B_LEFT) 145
144 { 146 if (ev.buttons & GPM_B_LEFT)
145 button = 1; 147 button = 1;
146 } 148 else if (ev.buttons & GPM_B_MIDDLE)
147 else if (ev.buttons & GPM_B_MIDDLE) 149 button = 2;
148 { 150 else if (ev.buttons & GPM_B_RIGHT)
149 button = 2; 151 button = 3;
150 } 152
151 else if (ev.buttons & GPM_B_RIGHT) 153 switch (GPM_BARE_EVENTS (ev.type))
152 { 154 {
153 button = 3; 155 case GPM_DOWN:
154 } 156 case GPM_UP:
155 157 event->event_type =
156 switch (GPM_BARE_EVENTS(ev.type)) { 158 (ev.type & GPM_DOWN) ? button_press_event : button_release_event;
157 case GPM_DOWN: 159 event->event.button.x = ev.x;
158 case GPM_UP: 160 event->event.button.y = ev.y;
159 event->event_type = 161 event->event.button.button = button;
160 (ev.type & GPM_DOWN) ? button_press_event : button_release_event; 162 event->event.button.modifiers = modifiers;
161 event->event.button.x = ev.x; 163 break;
162 event->event.button.y = ev.y; 164 case GPM_MOVE:
163 event->event.button.button = button; 165 case GPM_DRAG:
164 event->event.button.modifiers = modifiers; 166 event->event_type = pointer_motion_event;
165 break; 167 event->event.motion.x = ev.x;
166 case GPM_MOVE: 168 event->event.motion.y = ev.y;
167 case GPM_DRAG: 169 event->event.motion.modifiers = modifiers;
168 event->event_type = pointer_motion_event; 170 default:
169 event->event.motion.x = ev.x; 171 /* This will never happen */
170 event->event.motion.y = ev.y; 172 break;
171 event->event.motion.modifiers = modifiers; 173 }
172 default: 174
173 /* This will never happen */ 175 /* Handle the event */
174 break; 176 enqueue_event (fake_event, &gpm_event_queue, &gpm_event_queue_tail);
175 } 177
176 178 UNGCPRO;
177 /* Handle the event */ 179
178 enqueue_event (fake_event, &gpm_event_queue, &gpm_event_queue_tail); 180 return (Qzero);
179
180 UNGCPRO;
181
182 return (Qzero);
183 } 181 }
184 182
185 static void turn_off_gpm (char *process_name) 183 static void turn_off_gpm (char *process_name)
186 { 184 {
187 Lisp_Object process = Fget_process (build_string (process_name)); 185 Lisp_Object process = Fget_process (build_string (process_name));
188 int fd = -1; 186 int fd = -1;
189 187
190 if (NILP (process)) 188 if (NILP (process))
191 { 189 /* Something happened to our GPM process - fail silently */
192 /* Something happened to our GPM process - fail silently */ 190 return;
193 return; 191
194 } 192 fd = get_process_infd (XPROCESS (process));
195 193
196 fd = get_process_infd (XPROCESS (process)); 194 restore_gpm_state (fd);
197 195
198 restore_gpm_state (fd); 196 Gpm_Close();
199 197
200 Gpm_Close(); 198 clear_gpm_state (fd);
201 199
202 clear_gpm_state (fd); 200 Fdelete_process (build_string (process_name));
203
204 Fdelete_process (build_string (process_name));
205 } 201 }
206 202
207 #ifdef TIOCLINUX 203 #ifdef TIOCLINUX
208 static Lisp_Object 204 static Lisp_Object
209 tty_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type) 205 tty_get_foreign_selection (Lisp_Object selection_symbol,
210 { 206 Lisp_Object target_type)
211 /* This function can GC */ 207 {
212 struct device *d = decode_device (Qnil); 208 /* This function can GC */
213 int fd = DEVICE_INFD (d); 209 struct device *d = decode_device (Qnil);
214 char c = 3; 210 int fd = DEVICE_INFD (d);
215 Lisp_Object output_stream = Qnil; 211 char c = 3;
216 Lisp_Object terminal_stream = Qnil ; 212 Lisp_Object output_stream = Qnil;
217 Lisp_Object output_string = Qnil; 213 Lisp_Object terminal_stream = Qnil;
218 struct gcpro gcpro1,gcpro2,gcpro3; 214 Lisp_Object output_string = Qnil;
219 215 struct gcpro gcpro1,gcpro2,gcpro3;
220 GCPRO3(output_stream,terminal_stream,output_string); 216
221 217 GCPRO3(output_stream,terminal_stream,output_string);
222 /* The ioctl() to paste actually puts things in the input queue of 218
223 ** the virtual console, so we need to trap that data, since we are 219 /* The ioctl() to paste actually puts things in the input queue of
224 ** supposed to return the actual string selection from this 220 ** the virtual console, so we need to trap that data, since we are
225 ** function. 221 ** supposed to return the actual string selection from this
226 */ 222 ** function.
227 223 */
228 /* I really hate doing this, but it doesn't seem to cause any 224
229 ** problems, and it makes the Lstream_read stuff further down 225 /* I really hate doing this, but it doesn't seem to cause any
230 ** error out correctly instead of trying to indefinitely read from 226 ** problems, and it makes the Lstream_read stuff further down
231 ** the console. 227 ** error out correctly instead of trying to indefinitely read from
232 ** 228 ** the console.
233 ** There is no set_descriptor_blocking() function call, but in my 229 **
234 ** testing under linux, it has not proved fatal to leave the 230 ** There is no set_descriptor_blocking() function call, but in my
235 ** descriptor in non-blocking mode. 231 ** testing under linux, it has not proved fatal to leave the
236 ** 232 ** descriptor in non-blocking mode.
237 ** William Perry Nov 5, 1999 233 **
238 */ 234 ** William Perry Nov 5, 1999
239 set_descriptor_non_blocking (fd); 235 */
240 236 set_descriptor_non_blocking (fd);
241 /* We need two streams, one for reading from the selected device, 237
242 ** and one to write the data into. There is no writable version 238 /* We need two streams, one for reading from the selected device,
243 ** of the lisp-string lstream, so we make do with a resizing 239 ** and one to write the data into. There is no writable version
244 ** buffer stream, and make a string out of it after we are 240 ** of the lisp-string lstream, so we make do with a resizing
245 ** done. 241 ** buffer stream, and make a string out of it after we are
246 */ 242 ** done.
247 output_stream = make_resizing_buffer_output_stream (); 243 */
248 terminal_stream = make_filedesc_input_stream (fd, 0, -1, LSTR_BLOCKED_OK); 244 output_stream = make_resizing_buffer_output_stream ();
249 output_string = Qnil; 245 terminal_stream = make_filedesc_input_stream (fd, 0, -1, LSTR_BLOCKED_OK);
250 246 output_string = Qnil;
251 /* #### We should arguably use a specbind() and an unwind routine here, 247
252 ** #### but I don't care that much right now. 248 /* #### We should arguably use a specbind() and an unwind routine here,
253 */ 249 ** #### but I don't care that much right now.
254 if (NILP (output_stream) || NILP (terminal_stream)) 250 */
251 if (NILP (output_stream) || NILP (terminal_stream))
252 /* Should we signal an error here? */
253 goto out;
254
255 if (ioctl (fd, TIOCLINUX, &c) < 0)
256 {
257 /* Could not get the selection - eek */
258 UNGCPRO;
259 return (Qnil);
260 }
261
262 while (1)
263 {
264 Intbyte tempbuf[1024]; /* some random amount */
265 Bytecount i;
266 Bytecount size_in_bytes =
267 Lstream_read (XLSTREAM (terminal_stream),
268 tempbuf, sizeof (tempbuf));
269
270 if (size_in_bytes <= 0)
271 /* end of the stream */
272 break;
273
274 /* convert CR->LF */
275 for (i = 0; i < size_in_bytes; i++)
255 { 276 {
256 /* Should we signal an error here? */ 277 if (tempbuf[i] == '\r')
257 goto out; 278 tempbuf[i] = '\n';
258 } 279 }
259 280
260 if (ioctl (fd, TIOCLINUX, &c) < 0) 281 Lstream_write (XLSTREAM (output_stream), tempbuf, size_in_bytes);
261 { 282 }
262 /* Could not get the selection - eek */ 283
263 UNGCPRO; 284 Lstream_flush (XLSTREAM (output_stream));
264 return (Qnil); 285
265 } 286 output_string =
266 287 make_string (resizing_buffer_stream_ptr (XLSTREAM (output_stream)),
267 while (1) 288 Lstream_byte_count (XLSTREAM (output_stream)));
268 { 289
269 Intbyte tempbuf[1024]; /* some random amount */ 290 Lstream_delete (XLSTREAM (output_stream));
270 Bytecount i; 291 Lstream_delete (XLSTREAM (terminal_stream));
271 Bytecount size_in_bytes =
272 Lstream_read (XLSTREAM (terminal_stream),
273 tempbuf, sizeof (tempbuf));
274
275 if (size_in_bytes <= 0)
276 {
277 /* end of the stream */
278 break;
279 }
280
281 /* convert CR->LF */
282 for (i = 0; i < size_in_bytes; i++)
283 {
284 if (tempbuf[i] == '\r')
285 {
286 tempbuf[i] = '\n';
287 }
288 }
289
290 Lstream_write (XLSTREAM (output_stream), tempbuf, size_in_bytes);
291 }
292
293 Lstream_flush (XLSTREAM (output_stream));
294
295 output_string = make_string (resizing_buffer_stream_ptr (XLSTREAM (output_stream)),
296 Lstream_byte_count (XLSTREAM (output_stream)));
297
298 Lstream_delete (XLSTREAM (output_stream));
299 Lstream_delete (XLSTREAM (terminal_stream));
300 292
301 out: 293 out:
302 UNGCPRO; 294 UNGCPRO;
303 return (output_string); 295 return (output_string);
304 } 296 }
305 297
306 static Lisp_Object 298 static Lisp_Object
307 tty_selection_exists_p (Lisp_Object selection, Lisp_Object selection_type) 299 tty_selection_exists_p (Lisp_Object selection, Lisp_Object selection_type)
308 { 300 {
309 return (Qt); 301 return (Qt);
310 } 302 }
311 #endif /* TIOCLINUX */ 303 #endif /* TIOCLINUX */
312 304
313 #if 0 305 #if 0
314 static Lisp_Object 306 static Lisp_Object
315 tty_own_selection (Lisp_Object selection_name, Lisp_Object selection_value, 307 tty_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
316 Lisp_Object how_to_add, Lisp_Object selection_type) 308 Lisp_Object how_to_add, Lisp_Object selection_type)
317 { 309 {
318 /* There is no way to do this cleanly - the GPM selection 310 /* There is no way to do this cleanly - the GPM selection
319 ** 'protocol' (actually the TIOCLINUX ioctl) requires a start and 311 ** 'protocol' (actually the TIOCLINUX ioctl) requires a start and
320 ** end position on the _screen_, not a string to stick in there. 312 ** end position on the _screen_, not a string to stick in there.
321 ** Lame. 313 ** Lame.
322 ** 314 **
323 ** William Perry Nov 4, 1999 315 ** William Perry Nov 4, 1999
324 */ 316 */
325 } 317 }
326 #endif 318 #endif
327 319
328 /* This function appears to work once in a blue moon. I'm not sure 320 /* This function appears to work once in a blue moon. I'm not sure
329 ** exactly why either. *sigh* 321 ** exactly why either. *sigh*
330 ** 322 **
331 ** William Perry Nov 4, 1999 323 ** William Perry Nov 4, 1999
332 ** 324 **
333 ** Apparently, this is the way (mouse-position) is supposed to work, 325 ** Apparently, this is the way (mouse-position) is supposed to work,
334 ** and I was just expecting something else. (mouse-pixel-position) 326 ** and I was just expecting something else. (mouse-pixel-position)
335 ** works just fine. 327 ** works just fine.
336 ** 328 **
337 ** William Perry Nov 7, 1999 329 ** William Perry Nov 7, 1999
338 */ 330 */
339 static int 331 static int
340 tty_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y) 332 tty_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y)
341 { 333 {
342 Gpm_Event ev; 334 Gpm_Event ev;
343 int num_buttons; 335 int num_buttons;
344 336
345 memset(&ev,'\0',sizeof(ev)); 337 memset(&ev,'\0',sizeof(ev));
346 338
347 num_buttons = Gpm_GetSnapshot(&ev); 339 num_buttons = Gpm_GetSnapshot(&ev);
348 340
349 if (!num_buttons) 341 if (!num_buttons)
350 { 342 /* This means there are events pending... */
351 /* This means there are events pending... */ 343
352 344 /* #### In theory, we should drain the events pending, stick
353 /* #### In theory, we should drain the events pending, stick 345 ** #### them in the queue, and return the mouse position
354 ** #### them in the queue, and return the mouse position 346 ** #### anyway.
355 ** #### anyway. 347 */
356 */ 348 return (-1);
357 return(-1); 349 *x = ev.x;
358 } 350 *y = ev.y;
359 *x = ev.x; 351 *frame = DEVICE_SELECTED_FRAME (d);
360 *y = ev.y; 352 return (1);
361 *frame = DEVICE_SELECTED_FRAME (d);
362 return (1);
363 } 353 }
364 354
365 static void 355 static void
366 tty_set_mouse_position (struct window *w, int x, int y) 356 tty_set_mouse_position (struct window *w, int x, int y)
367 { 357 {
368 /* 358 /*
369 #### I couldn't find any GPM functions that set the mouse position. 359 #### I couldn't find any GPM functions that set the mouse position.
370 #### Mr. Perry had left this function empty; that must be why. 360 #### Mr. Perry had left this function empty; that must be why.
371 #### karlheg 361 #### karlheg
372 */ 362 */
373 } 363 }
374 364
375 static int gpm_event_pending_p (int user_p) 365 static int gpm_event_pending_p (int user_p)
376 { 366 {
377 Lisp_Object event; 367 Lisp_Object event;
378 368
379 EVENT_CHAIN_LOOP (event, gpm_event_queue) 369 EVENT_CHAIN_LOOP (event, gpm_event_queue)
370 {
371 if (!user_p || command_event_p (event))
372 return (1);
373 }
374 return (orig_event_pending_p (user_p));
375 }
376
377 static void gpm_next_event_cb (Lisp_Event *event)
378 {
379 /* #### It would be nice to preserve some sort of ordering of the
380 ** #### different types of events, but that would be quite a bit
381 ** #### of work, and would more than likely break the abstraction
382 ** #### between the other event loops and this one.
383 */
384
385 if (!NILP (gpm_event_queue))
386 {
387 Lisp_Object queued_event =
388 dequeue_event (&gpm_event_queue, &gpm_event_queue_tail);
389 *event = *(XEVENT (queued_event));
390
391 if (event->event_type == pointer_motion_event)
380 { 392 {
381 if (!user_p || command_event_p (event)) 393 struct device *d = decode_device (event->channel);
382 { 394 int fd = DEVICE_INFD (d);
383 return (1); 395
384 } 396 /* Ok, now this is just freaky. Bear with me though.
397 **
398 ** If you run gnuclient and attach to a XEmacs running in
399 ** X or on another TTY, the mouse cursor does not get
400 ** drawn correctly. This is because the ioctl() fails
401 ** with EPERM because the TTY specified is not our
402 ** controlling terminal. If you are the superuser, it
403 ** will work just spiffy. The appropriate source file (at
404 ** least in linux 2.2.x) is
405 ** .../linux/drivers/char/console.c in the function
406 ** tioclinux(). The following bit of code is brutal to
407 ** us:
408 **
409 ** if (current->tty != tty && !suser())
410 ** return -EPERM;
411 **
412 ** I even tried setting us as a process leader, removing
413 ** our controlling terminal, and then using the TIOCSCTTY
414 ** to set up a new controlling terminal, all with no luck.
415 **
416 ** What is even weirder is if you run XEmacs in a VC, and
417 ** attach to it from another VC with gnuclient, go back to
418 ** the original VC and hit a key, the mouse pointer
419 ** displays (in BOTH VCs), until you hit a key in the
420 ** second VC, after which it does not display in EITHER
421 ** VC. Bizarre, no?
422 **
423 ** All I can say is thank god Linux comes with source code
424 ** or I would have been completely confused. Well, ok,
425 ** I'm still completely confused. I don't see why they
426 ** don't just check the permissions on the device
427 ** (actually, if you have enough access to it to get the
428 ** console's file descriptor, you should be able to do
429 ** with it as you wish, but maybe that is just me).
430 **
431 ** William M. Perry - Nov 9, 1999
432 */
433
434 Gpm_DrawPointer (event->event.motion.x,event->event.motion.y, fd);
385 } 435 }
386 return (orig_event_pending_p (user_p)); 436
387 } 437 return;
388 438 }
389 static void gpm_next_event_cb (Lisp_Event *event) 439
390 { 440 orig_next_event_cb (event);
391 /* #### It would be nice to preserve some sort of ordering of the
392 ** #### different types of events, but that would be quite a bit
393 ** #### of work, and would more than likely break the abstraction
394 ** #### between the other event loops and this one.
395 */
396
397 if (!NILP (gpm_event_queue))
398 {
399 Lisp_Object queued_event = dequeue_event (&gpm_event_queue, &gpm_event_queue_tail);
400 *event = *(XEVENT (queued_event));
401
402 if (event->event_type == pointer_motion_event)
403 {
404 struct device *d = decode_device (event->channel);
405 int fd = DEVICE_INFD (d);
406
407 /* Ok, now this is just freaky. Bear with me though.
408 **
409 ** If you run gnuclient and attach to a XEmacs running in
410 ** X or on another TTY, the mouse cursor does not get
411 ** drawn correctly. This is because the ioctl() fails
412 ** with EPERM because the TTY specified is not our
413 ** controlling terminal. If you are the superuser, it
414 ** will work just spiffy. The appropriate source file (at
415 ** least in linux 2.2.x) is
416 ** .../linux/drivers/char/console.c in the function
417 ** tioclinux(). The following bit of code is brutal to
418 ** us:
419 **
420 ** if (current->tty != tty && !suser())
421 ** return -EPERM;
422 **
423 ** I even tried setting us as a process leader, removing
424 ** our controlling terminal, and then using the TIOCSCTTY
425 ** to set up a new controlling terminal, all with no luck.
426 **
427 ** What is even weirder is if you run XEmacs in a VC, and
428 ** attach to it from another VC with gnuclient, go back to
429 ** the original VC and hit a key, the mouse pointer
430 ** displays (in BOTH VCs), until you hit a key in the
431 ** second VC, after which it does not display in EITHER
432 ** VC. Bizarre, no?
433 **
434 ** All I can say is thank god Linux comes with source code
435 ** or I would have been completely confused. Well, ok,
436 ** I'm still completely confused. I don't see why they
437 ** don't just check the permissions on the device
438 ** (actually, if you have enough access to it to get the
439 ** console's file descriptor, you should be able to do
440 ** with it as you wish, but maybe that is just me).
441 **
442 ** William M. Perry - Nov 9, 1999
443 */
444
445 Gpm_DrawPointer (event->event.motion.x,event->event.motion.y, fd);
446 }
447
448 return;
449 }
450
451 orig_next_event_cb (event);
452 } 441 }
453 442
454 static void hook_event_callbacks_once (void) 443 static void hook_event_callbacks_once (void)
455 { 444 {
456 static int hooker; 445 static int hooker;
457 446
458 if (!hooker) 447 if (!hooker)
459 { 448 {
460 orig_event_pending_p = event_stream->event_pending_p; 449 orig_event_pending_p = event_stream->event_pending_p;
461 orig_next_event_cb = event_stream->next_event_cb; 450 orig_next_event_cb = event_stream->next_event_cb;
462 event_stream->event_pending_p = gpm_event_pending_p; 451 event_stream->event_pending_p = gpm_event_pending_p;
463 event_stream->next_event_cb = gpm_next_event_cb; 452 event_stream->next_event_cb = gpm_next_event_cb;
464 hooker = 1; 453 hooker = 1;
465 } 454 }
466 } 455 }
467 456
468 static void hook_console_methods_once (void) 457 static void hook_console_methods_once (void)
469 { 458 {
470 static int hooker; 459 static int hooker;
471 460
472 if (!hooker) 461 if (!hooker)
473 { 462 {
474 /* Install the mouse position methods for the TTY console type */ 463 /* Install the mouse position methods for the TTY console type */
475 CONSOLE_HAS_METHOD (tty, get_mouse_position); 464 CONSOLE_HAS_METHOD (tty, get_mouse_position);
476 CONSOLE_HAS_METHOD (tty, set_mouse_position); 465 CONSOLE_HAS_METHOD (tty, set_mouse_position);
477 CONSOLE_HAS_METHOD (tty, get_foreign_selection); 466 CONSOLE_HAS_METHOD (tty, get_foreign_selection);
478 CONSOLE_HAS_METHOD (tty, selection_exists_p); 467 CONSOLE_HAS_METHOD (tty, selection_exists_p);
479 #if 0 468 #if 0
480 CONSOLE_HAS_METHOD (tty, own_selection); 469 CONSOLE_HAS_METHOD (tty, own_selection);
481 #endif 470 #endif
482 } 471 }
483 } 472 }
484 473
485 DEFUN ("gpm-enabled-p", Fgpm_enabled_p, 0, 1, 0, /* 474 DEFUN ("gpm-enabled-p", Fgpm_enabled_p, 0, 1, 0, /*
486 Return non-nil if GPM mouse support is currently enabled on DEVICE. 475 Return non-nil if GPM mouse support is currently enabled on DEVICE.
487 */ 476 */
488 (device)) 477 (device))
489 { 478 {
490 char *console_name = ttyname (DEVICE_INFD (decode_device (device))); 479 char *console_name = ttyname (DEVICE_INFD (decode_device (device)));
491 char process_name[1024]; 480 char process_name[1024];
492 Lisp_Object proc; 481 Lisp_Object proc;
493 482
494 if (!console_name) 483 if (!console_name)
495 { 484 return (Qnil);
496 return (Qnil); 485
497 } 486 memset (process_name, '\0', sizeof(process_name));
498 487 snprintf (process_name, sizeof(process_name) - 1, "gpm for %s",
499 memset (process_name, '\0', sizeof(process_name)); 488 console_name);
500 snprintf (process_name, sizeof(process_name) - 1, "gpm for %s", console_name); 489
501 490 proc = Fget_process (build_string (process_name));
502 proc = Fget_process (build_string (process_name)); 491
503 492 if (NILP (proc))
504 if (NILP (proc)) 493 return (Qnil);
505 { 494
506 return (Qnil); 495 if (1) /* (PROCESS_LIVE_P (proc)) */
507 } 496 return (Qt);
508 497 return (Qnil);
509 if (1) /* (PROCESS_LIVE_P (proc)) */
510 {
511 return (Qt);
512 }
513 return (Qnil);
514 } 498 }
515 499
516 DEFUN ("gpm-enable", Fgpm_enable, 0, 2, 0, /* 500 DEFUN ("gpm-enable", Fgpm_enable, 0, 2, 0, /*
517 Toggle accepting of GPM mouse events. 501 Toggle accepting of GPM mouse events.
518 */ 502 */
519 (device, arg)) 503 (device, arg))
520 { 504 {
521 Gpm_Connect conn; 505 Gpm_Connect conn;
522 int rval; 506 int rval;
523 Lisp_Object gpm_process; 507 Lisp_Object gpm_process;
524 Lisp_Object gpm_filter; 508 Lisp_Object gpm_filter;
525 struct device *d = decode_device (device); 509 struct device *d = decode_device (device);
526 int fd = DEVICE_INFD (d); 510 int fd = DEVICE_INFD (d);
527 char *console_name = ttyname (fd); 511 char *console_name = ttyname (fd);
528 char process_name[1024]; 512 char process_name[1024];
529 513
530 hook_event_callbacks_once (); 514 hook_event_callbacks_once ();
531 hook_console_methods_once (); 515 hook_console_methods_once ();
532 516
533 if (noninteractive) 517 if (noninteractive)
518 invalid_operation ("Can't connect to GPM in batch mode", Qunbound);
519
520 if (!console_name)
521 /* Something seriously wrong here... */
522 return (Qnil);
523
524 memset (process_name, '\0', sizeof(process_name));
525 snprintf (process_name, sizeof(process_name) - 1, "gpm for %s",
526 console_name);
527
528 if (NILP (arg))
529 {
530 turn_off_gpm (process_name);
531 return (Qnil);
532 }
533
534 /* DANGER DANGER.
535 ** Though shalt not call (gpm-enable t) after we have already
536 ** started, or stuff blows up.
537 */
538 if (!NILP (Fgpm_enabled_p (device)))
539 invalid_operation ("GPM already enabled for this console", Qunbound);
540
541 conn.eventMask = GPM_DOWN|GPM_UP|GPM_MOVE|GPM_DRAG;
542 conn.defaultMask = GPM_MOVE;
543 conn.minMod = 0;
544 conn.maxMod = ((1 << KG_SHIFT) | (1 << KG_ALT) | (1 << KG_CTRL));
545
546 /* Reset some silly static variables so that multiple Gpm_Open()
547 ** calls have even a slight chance of working
548 */
549 gpm_tried = 0;
550 gpm_flag = 0;
551 gpm_stack = NULL;
552
553 /* Make sure Gpm_Open() does ioctl() on the correct
554 ** descriptor, or it can get the wrong terminal sizes, etc.
555 */
556 gpm_consolefd = fd;
557
558 /* We have to pass the virtual console manually, otherwise if you
559 ** use 'gnuclient -nw' to connect to an XEmacs that is running in
560 ** X, Gpm_Open() tries to use ttyname(0 | 1 | 2) to find out which
561 ** console you are using, which is of course not correct for the
562 ** new tty device.
563 */
564 if (strncmp (console_name, "/dev/tty", 8) || !isdigit (console_name[8]))
565 /* Urk, something really wrong */
566 return (Qnil);
567
568 rval = Gpm_Open (&conn, atoi (console_name + 8));
569
570 switch (rval)
571 {
572 case -1: /* General failure */
573 break;
574 case -2: /* We are running under an XTerm */
575 Gpm_Close();
576 break;
577 default:
578 /* Is this really necessary? */
579 set_descriptor_non_blocking (gpm_fd);
580 store_gpm_state (gpm_fd);
581 gpm_process =
582 connect_to_file_descriptor (build_string (process_name), Qnil,
583 make_int (gpm_fd),
584 make_int (gpm_fd));
585
586 if (!NILP (gpm_process))
534 { 587 {
535 invalid_operation ("Can't connect to GPM in batch mode.", Qunbound); 588 rval = 0;
589 Fprocess_kill_without_query (gpm_process, Qnil);
590 gpm_filter = wrap_subr (&SFreceive_gpm_event);
591 set_process_filter (gpm_process, gpm_filter, 1);
592
593 /* Keep track of the device for later */
594 /* Fput (gpm_process, intern ("gpm-device"), device); */
536 } 595 }
537 596 else
538 if (!console_name)
539 { 597 {
540 /* Something seriously wrong here... */ 598 Gpm_Close ();
541 return (Qnil); 599 rval = -1;
542 } 600 }
543 601 }
544 memset (process_name, '\0', sizeof(process_name)); 602
545 snprintf (process_name, sizeof(process_name) - 1, "gpm for %s", console_name); 603 return (rval ? Qnil : Qt);
546
547 if (NILP (arg))
548 {
549 turn_off_gpm (process_name);
550 return (Qnil);
551 }
552
553 /* DANGER DANGER.
554 ** Though shalt not call (gpm-enable t) after we have already
555 ** started, or stuff blows up.
556 */
557 if (!NILP (Fgpm_enabled_p (device)))
558 {
559 invalid_operation ("GPM already enabled for this console.", Qunbound);
560 }
561
562 conn.eventMask = GPM_DOWN|GPM_UP|GPM_MOVE|GPM_DRAG;
563 conn.defaultMask = GPM_MOVE;
564 conn.minMod = 0;
565 conn.maxMod = ((1<<KG_SHIFT)|(1<<KG_ALT)|(1<<KG_CTRL));
566
567 /* Reset some silly static variables so that multiple Gpm_Open()
568 ** calls have even a slight chance of working
569 */
570 gpm_tried = 0;
571 gpm_flag = 0;
572 gpm_stack = NULL;
573
574 /* Make sure Gpm_Open() does ioctl() on the correct
575 ** descriptor, or it can get the wrong terminal sizes, etc.
576 */
577 gpm_consolefd = fd;
578
579 /* We have to pass the virtual console manually, otherwise if you
580 ** use 'gnuclient -nw' to connect to an XEmacs that is running in
581 ** X, Gpm_Open() tries to use ttyname(0 | 1 | 2) to find out which
582 ** console you are using, which is of course not correct for the
583 ** new tty device.
584 */
585 if (strncmp (console_name, "/dev/tty",8) || !isdigit (console_name[8]))
586 {
587 /* Urk, something really wrong */
588 return (Qnil);
589 }
590
591 rval = Gpm_Open (&conn, atoi(console_name + 8));
592
593 switch (rval) {
594 case -1: /* General failure */
595 break;
596 case -2: /* We are running under an XTerm */
597 Gpm_Close();
598 break;
599 default:
600 /* Is this really necessary? */
601 set_descriptor_non_blocking (gpm_fd);
602 store_gpm_state (gpm_fd);
603 gpm_process = connect_to_file_descriptor (build_string (process_name), Qnil,
604 make_int (gpm_fd),
605 make_int (gpm_fd));
606
607 if (!NILP (gpm_process))
608 {
609 rval = 0;
610 Fprocess_kill_without_query (gpm_process, Qnil);
611 XSETSUBR (gpm_filter, &SFreceive_gpm_event);
612 set_process_filter (gpm_process, gpm_filter, 1);
613
614 /* Keep track of the device for later */
615 /* Fput (gpm_process, intern ("gpm-device"), device); */
616 }
617 else
618 {
619 Gpm_Close();
620 rval = -1;
621 }
622 }
623
624 return(rval ? Qnil : Qt);
625 } 604 }
626 605
627 void vars_of_gpmevent (void) 606 void vars_of_gpmevent (void)
628 { 607 {
629 gpm_event_queue = Qnil; 608 gpm_event_queue = Qnil;
630 gpm_event_queue_tail = Qnil; 609 gpm_event_queue_tail = Qnil;
631 staticpro (&gpm_event_queue); 610 staticpro (&gpm_event_queue);
632 staticpro (&gpm_event_queue_tail); 611 staticpro (&gpm_event_queue_tail);
633 dump_add_root_object (&gpm_event_queue); 612 dump_add_root_object (&gpm_event_queue);
634 dump_add_root_object (&gpm_event_queue_tail); 613 dump_add_root_object (&gpm_event_queue_tail);
635 } 614 }
636 615
637 void syms_of_gpmevent (void) 616 void syms_of_gpmevent (void)
638 { 617 {
639 DEFSUBR (Freceive_gpm_event); 618 DEFSUBR (Freceive_gpm_event);
640 DEFSUBR (Fgpm_enable); 619 DEFSUBR (Fgpm_enable);
641 DEFSUBR (Fgpm_enabled_p); 620 DEFSUBR (Fgpm_enabled_p);
642 } 621 }
643 622
644 #endif /* HAVE_GPM */ 623 #endif /* HAVE_GPM */