diff options
author | Miles Bader <miles@gnu.org> | 2007-05-20 23:29:14 +0000 |
---|---|---|
committer | Miles Bader <miles@gnu.org> | 2007-05-20 23:29:14 +0000 |
commit | 7be1c21aedb2f8e7b7831d494e065a31afe13146 (patch) | |
tree | a998f949002bf05307fe6b59969e6ebfb0c88b8d /src | |
parent | 3c28868aeb2d445830019837294e96f432456754 (diff) | |
parent | 26114bc08f03789f30f0acca925955f2139df690 (diff) | |
download | emacs-7be1c21aedb2f8e7b7831d494e065a31afe13146.tar.gz emacs-7be1c21aedb2f8e7b7831d494e065a31afe13146.tar.bz2 emacs-7be1c21aedb2f8e7b7831d494e065a31afe13146.zip |
Merged from emacs--devo--0
Patches applied:
* emacs@sv.gnu.org/emacs--devo--0--patch-744
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-745
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-746
Merge from emacs--rel--22
* emacs@sv.gnu.org/emacs--devo--0--patch-747
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-748
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-749
Merge from gnus--rel--5.10
* emacs@sv.gnu.org/emacs--devo--0--patch-750
Merge from emacs--rel--22
* emacs@sv.gnu.org/emacs--devo--0--patch-751
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-752
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-753
Merge from emacs--rel--22
* emacs@sv.gnu.org/emacs--devo--0--patch-754
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-755
Merge from emacs--rel--22
* emacs@sv.gnu.org/emacs--devo--0--patch-756
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-757
Update from CVS: lisp/textmodes/sgml-mode.el: Revert last change.
* emacs@sv.gnu.org/emacs--devo--0--patch-758
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-759
Merge from emacs--rel--22
* emacs@sv.gnu.org/emacs--devo--0--patch-760
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-761
Update from CVS
* emacs@sv.gnu.org/emacs--rel--22--patch-14
Update from CVS
* emacs@sv.gnu.org/emacs--rel--22--patch-15
Update from CVS
* emacs@sv.gnu.org/emacs--rel--22--patch-16
Update from CVS: src/xterm.c (XTread_socket): Revert last change.
* emacs@sv.gnu.org/emacs--rel--22--patch-17
Update from CVS
* emacs@sv.gnu.org/emacs--rel--22--patch-18
Update from CVS
* emacs@sv.gnu.org/emacs--rel--22--patch-19
Update from CVS
* emacs@sv.gnu.org/emacs--rel--22--patch-20
Update from CVS
* emacs@sv.gnu.org/emacs--rel--22--patch-21
Update from CVS
* emacs@sv.gnu.org/gnus--rel--5.10--patch-221
Update from CVS
Revision: emacs@sv.gnu.org/emacs--multi-tty--0--patch-12
Creator: Karoly Lorentey <karoly@lorentey.hu>
Diffstat (limited to 'src')
-rw-r--r-- | src/ChangeLog | 100 | ||||
-rw-r--r-- | src/Makefile.in | 11 | ||||
-rw-r--r-- | src/config.in | 3 | ||||
-rw-r--r-- | src/image.c | 18 | ||||
-rw-r--r-- | src/keyboard.c | 108 | ||||
-rw-r--r-- | src/lisp.h | 2 | ||||
-rw-r--r-- | src/m/alpha.h | 4 | ||||
-rw-r--r-- | src/m/macppc.h | 4 | ||||
-rw-r--r-- | src/macterm.c | 19 | ||||
-rw-r--r-- | src/process.c | 49 | ||||
-rw-r--r-- | src/syntax.c | 2 | ||||
-rw-r--r-- | src/sysdep.c | 8 | ||||
-rw-r--r-- | src/term.c | 761 | ||||
-rw-r--r-- | src/termhooks.h | 17 | ||||
-rw-r--r-- | src/xdisp.c | 50 |
15 files changed, 1086 insertions, 70 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 59a0af5e2c8..67f6bd282c2 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,103 @@ +2007-05-20 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> + + * Makefile.in: Move GPM check outside HAVE_X_WINDOWS. + +2007-05-20 Nick Roberts <nickrob@snap.net.nz> + + * config.in, keyboard.c, Makefile.in, sysdep.c, term.c, + * termhooks.h: Use HAVE_GPM instead of HAVE_GPM_H. + +2007-05-20 Nick Roberts <nickrob@snap.net.nz> + + * keyboard.c (make_lispy_event): Make case GPM_CLICK_EVENT + conditional on [HAVE_GPM_H]. + +2007-05-19 Stefan Monnier <monnier@iro.umontreal.ca> + + * syntax.c (skip_chars): Update syntax-table only after we checked that + the new location is valid. + +2007-05-19 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * macterm.c (x_calc_absolute_position): Add BLOCK_INPUT around + mac_get_window_bounds. + +2007-05-20 Nick Roberts <nickrob@snap.net.nz> + + * Makefile.in (LIBGPM): Allow it to be set from configure. + If set then link Emacs with it. + + * config.in: Regenerate. + + * lisp.h (add_gpm_wait_descriptor, delete_gpm_wait_descriptor): + New externs. + + * termhooks.h [HAVE_GPM_H] (enum event_kind): Add GPM_CLICK_EVENT. + Include gpm.h. + (handle_one_term_event, term_gpm) New externs. + + * sysdep.c [HAVE_GPM_H] (init_sys_modes): Make gpm_fd nonblocking + and allow it to be interrupted by SIGIO. + + * process.c (gpm_wait_mask, max_gpm_desc): New variables. + (wait_reading_process_output): Wait on gpm_fd too. + (add_gpm_wait_descriptor, delete_gpm_wait_descriptor)): New functions. + (add_gpm_wait_descriptor_called_flag): New variable. + (delete_keyboard_wait_descriptor): Check gpm_wait_mask. + + * keyboard.c [HAVE_GPM_H] (Qmouse_fixup_help_message) + (make_lispy_movement, tracking_off, Ftrack_mouse, some_mouse_moved) + (show_help_echo, readable_events, kbd_buffer_get_event, init_keyboard): + Extend HAVE_MOUSE ifdefs to HAVE_GPM_H. + (make_lispy_event): Add case GPM_CLICK_EVENT. + (read_avail_input): Handle mouse input. + + * term.c (write_glyphs_with_face): New function. + [HAVE_GPM_H]: Include buffer.h, sys/fcntl.h. + (mouse_face_beg_row, mouse_face_beg_col, mouse_face_end_row) + (mouse_face_end_col, mouse_face_past_end, mouse_face_window) + (mouse_face_face_id, term_gpm, pos_x, pos_y) + (last_mouse_x, last_mouse_y): New variables. + (term_show_mouse_face, term_clear_mouse_face, fast_find_position) + (term_mouse_highlight, term_mouse_movement, term_mouse_position) + (term_mouse_click, handle_one_term_event, Fterm_open_connection) + (Fterm_close_connection): New functions. + (term_init): Initialise mouse_face_window. + +2007-05-19 Chong Yidong <cyd@stupidchicken.com> + + * xdisp.c (redisplay_window): If first window line is a + continuation line, recompute the new window start instead of + recentering. + +2007-05-18 Glenn Morris <rgm@gnu.org> + + * m/alpha.h (ORDINARY_LINK): No longer define on OpenBSD. + Suggested by Alfred M. Szmidt <ams@gnu.org>. + +2007-05-17 Glenn Morris <rgm@gnu.org> + + * m/macppc.h (ORDINARY_LINK): No longer define on OpenBSD. + +2007-05-16 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * macterm.c [USE_CARBON_EVENTS] (mac_convert_event_ref): Also convert + dead key repeat and up events. + +2007-05-14 Chong Yidong <cyd@stupidchicken.com> + + * image.c (pbm_load): Check image size for monochrome pbm. + +2007-05-13 Chong Yidong <cyd@stupidchicken.com> + + * xterm.c (XTread_socket): Revert last change. + +2007-05-12 Chong Yidong <cyd@stupidchicken.com> + + * image.c (pbm_load): Correctly check image size for greyscale pbm. + + * xterm.c (XTread_socket): Yet Another Uncaught X Error Crash (YAUXEC). + 2007-05-07 Stefan Monnier <monnier@iro.umontreal.ca> * editfns.c (Ftranspose_regions): Yet another int/Lisp_Object mixup (YAILOM) diff --git a/src/Makefile.in b/src/Makefile.in index 31fc7b5c23e..c8db387328d 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -457,6 +457,15 @@ LIBX= $(LIBXMENU) LD_SWITCH_X_SITE -lX10 LIBX10_MACHINE LIBX10_SYSTEM #else /* not HAVE_X_WINDOWS */ #endif /* not HAVE_X_WINDOWS */ +#if HAVE_GPM +#ifndef LIBGPM +#define LIBGPM -lgpm +#endif /* not defined LIBGPM */ +#else /* not HAVE_GPM */ +#define LIBGPM +#endif /* not HAVE_GPM */ + + LIBSOUND= @LIBSOUND@ CFLAGS_SOUND= @CFLAGS_SOUND@ @@ -939,7 +948,7 @@ SOME_MACHINE_LISP = ${dotdot}/lisp/mouse.elc \ Note that SunOS needs -lm to come before -lc; otherwise, you get duplicated symbols. If the standard libraries were compiled with GCC, we might need gnulib again after them. */ -LIBES = $(LOADLIBES) $(LIBS) $(LIBX) $(LIBSOUND) \ +LIBES = $(LOADLIBES) $(LIBS) $(LIBX) $(LIBSOUND) LIBGPM \ LIBS_SYSTEM LIBS_MACHINE LIBS_TERMCAP \ LIBS_DEBUG $(GETLOADAVG_LIBS) $(GNULIB_VAR) LIB_MATH LIB_STANDARD \ $(GNULIB_VAR) diff --git a/src/config.in b/src/config.in index 71b4af0c839..6d945d4bfdc 100644 --- a/src/config.in +++ b/src/config.in @@ -231,6 +231,9 @@ Boston, MA 02110-1301, USA. */ /* Define to 1 if you have the ungif library (-lungif). */ #undef HAVE_GIF +/* Define to 1 if you have the gpm library (-lgpm). */ +#undef HAVE_GPM + /* Define to 1 if you have the `grantpt' function. */ #undef HAVE_GRANTPT diff --git a/src/image.c b/src/image.c index 198ffaf4651..5243778526e 100644 --- a/src/image.c +++ b/src/image.c @@ -5732,7 +5732,17 @@ pbm_load (f, img) if (raw_p) { if ((x & 7) == 0) - c = *p++; + { + if (p >= end) + { + x_destroy_x_image (ximg); + x_clear_image (f, img); + image_error ("Invalid image size in image `%s'", + img->spec, Qnil); + goto error; + } + c = *p++; + } g = c & 0x80; c <<= 1; } @@ -5744,9 +5754,13 @@ pbm_load (f, img) } else { - if (raw_p && (p + 3 * height * width > end)) + if (raw_p + && ((type == PBM_GRAY) + ? (p + height * width > end) + : (p + 3 * height * width > end))) { x_destroy_x_image (ximg); + x_clear_image (f, img); image_error ("Invalid image size in image `%s'", img->spec, Qnil); goto error; diff --git a/src/keyboard.c b/src/keyboard.c index 50c1d5a43b8..4658fdcca51 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -508,7 +508,7 @@ Lisp_Object Qmake_frame_visible; Lisp_Object Qselect_window; Lisp_Object Qhelp_echo; -#ifdef HAVE_MOUSE +#if defined (HAVE_MOUSE) || defined (HAVE_GPM) Lisp_Object Qmouse_fixup_help_message; #endif @@ -661,7 +661,7 @@ static Lisp_Object read_char_x_menu_prompt (); static Lisp_Object read_char_minibuf_menu_prompt P_ ((int, int, Lisp_Object *)); static Lisp_Object make_lispy_event P_ ((struct input_event *)); -#ifdef HAVE_MOUSE +#if defined (HAVE_MOUSE) || defined (HAVE_GPM) static Lisp_Object make_lispy_movement P_ ((struct frame *, Lisp_Object, enum scroll_bar_part, Lisp_Object, Lisp_Object, @@ -1466,7 +1466,7 @@ DEFUN ("abort-recursive-edit", Fabort_recursive_edit, Sabort_recursive_edit, 0, return Qnil; } -#ifdef HAVE_MOUSE +#if defined (HAVE_MOUSE) || defined (HAVE_GPM) /* Restore mouse tracking enablement. See Ftrack_mouse for the only use of this function. */ @@ -1542,7 +1542,7 @@ some_mouse_moved () return 0; } -#endif /* HAVE_MOUSE */ +#endif /* HAVE_MOUSE || HAVE_GPM */ /* This is the actual command reading loop, sans error-handling encapsulation. */ @@ -2476,7 +2476,7 @@ show_help_echo (help, window, object, pos, ok_to_overwrite_keystroke_echo) return; } -#ifdef HAVE_MOUSE +#if defined (HAVE_MOUSE) || defined (HAVE_GPM) if (!noninteractive && STRINGP (help)) { /* The mouse-fixup-help-message Lisp function can call @@ -3753,7 +3753,7 @@ readable_events (flags) return 1; } -#ifdef HAVE_MOUSE +#if defined (HAVE_MOUSE) || defined (HAVE_GPM) if (!(flags & READABLE_EVENTS_IGNORE_SQUEEZABLES) && !NILP (do_mouse_tracking) && some_mouse_moved ()) return 1; @@ -4103,7 +4103,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time) { if (kbd_fetch_ptr != kbd_store_ptr) break; -#ifdef HAVE_MOUSE +#if defined (HAVE_MOUSE) || defined (HAVE_GPM) if (!NILP (do_mouse_tracking) && some_mouse_moved ()) break; #endif @@ -4125,7 +4125,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time) #endif /* SIGIO */ if (kbd_fetch_ptr != kbd_store_ptr) break; -#ifdef HAVE_MOUSE +#if defined (HAVE_MOUSE) || defined (HAVE_GPM) if (!NILP (do_mouse_tracking) && some_mouse_moved ()) break; #endif @@ -4361,7 +4361,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time) } } } -#ifdef HAVE_MOUSE +#if defined (HAVE_MOUSE) || defined (HAVE_GPM) /* Try generating a mouse motion event. */ else if (!NILP (do_mouse_tracking) && some_mouse_moved ()) { @@ -4406,7 +4406,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time) if (!NILP (x) && NILP (obj)) obj = make_lispy_movement (f, bar_window, part, x, y, time); } -#endif /* HAVE_MOUSE */ +#endif /* HAVE_MOUSE || HAVE GPM */ else /* We were promised by the above while loop that there was something for us to read! */ @@ -6123,6 +6123,66 @@ make_lispy_event (event) } #endif +#ifdef HAVE_GPM + case GPM_CLICK_EVENT: + { + FRAME_PTR f = XFRAME (event->frame_or_window); + Lisp_Object head, position; + Lisp_Object *start_pos_ptr; + Lisp_Object start_pos; + int button = event->code; + + if (button >= ASIZE (button_down_location)) + { + button_down_location = larger_vector (button_down_location, + button + 1, Qnil); + mouse_syms = larger_vector (mouse_syms, button + 1, Qnil); + } + + start_pos_ptr = &AREF (button_down_location, button); + start_pos = *start_pos_ptr; + + position = make_lispy_position (f, &event->x, &event->y, + event->timestamp); + + if (event->modifiers & down_modifier) + *start_pos_ptr = Fcopy_alist (position); + else if (event->modifiers & (up_modifier | drag_modifier)) + { + if (!CONSP (start_pos)) + return Qnil; + event->modifiers &= ~up_modifier; + } + + head = modify_event_symbol (button, + event->modifiers, + Qmouse_click, Vlispy_mouse_stem, + NULL, + &mouse_syms, + XVECTOR (mouse_syms)->size); + + if (event->modifiers & drag_modifier) + return Fcons (head, + Fcons (start_pos, + Fcons (position, + Qnil))); + else if (event->modifiers & double_modifier) + return Fcons (head, + Fcons (position, + Fcons (make_number (2), + Qnil))); + else if (event->modifiers & triple_modifier) + return Fcons (head, + Fcons (position, + Fcons (make_number (3), + Qnil))); + else + return Fcons (head, + Fcons (position, + Qnil)); + } +#endif /* HAVE_GPM */ + /* The 'kind' field of the event is something we don't recognize. */ default: abort (); @@ -7057,7 +7117,27 @@ tty_read_avail_input (struct terminal *terminal, if (! tty->input) return 0; /* The terminal is suspended. */ - /* Determine how many characters we should *try* to read. */ +#ifdef HAVE_GPM + if (term_gpm && gpm_tty == tty->terminal->id) + { + Gpm_Event event; + struct input_event hold_quit; + int gpm; + + EVENT_INIT (hold_quit); + hold_quit.kind = NO_EVENT; + + while (gpm = Gpm_GetEvent (&event), gpm == 1) { + nread += handle_one_term_event (tty, &event, &hold_quit); + } + if (hold_quit.kind != NO_EVENT) + kbd_buffer_store_event (&hold_quit); + if (nread) + return nread; + } +#endif /* HAVE_GPM */ + +/* Determine how many characters we should *try* to read. */ #ifdef FIONREAD /* Find out how much input is available. */ if (ioctl (fileno (tty->input), FIONREAD, &n_to_read) < 0) @@ -11440,7 +11520,7 @@ init_keyboard () recent_keys_index = 0; kbd_fetch_ptr = kbd_buffer; kbd_store_ptr = kbd_buffer; -#ifdef HAVE_MOUSE +#if defined (HAVE_MOUSE) || defined (HAVE_GPM) do_mouse_tracking = Qnil; #endif input_pending = 0; @@ -11636,7 +11716,7 @@ syms_of_keyboard () Qmenu_bar = intern ("menu-bar"); staticpro (&Qmenu_bar); -#ifdef HAVE_MOUSE +#if defined (HAVE_MOUSE) || defined (HAVE_GPM) Qmouse_fixup_help_message = intern ("mouse-fixup-help-message"); staticpro (&Qmouse_fixup_help_message); #endif @@ -11768,7 +11848,7 @@ syms_of_keyboard () defsubr (&Sread_key_sequence); defsubr (&Sread_key_sequence_vector); defsubr (&Srecursive_edit); -#ifdef HAVE_MOUSE +#if defined (HAVE_MOUSE) || defined (HAVE_GPM) defsubr (&Strack_mouse); #endif defsubr (&Sinput_pending_p); diff --git a/src/lisp.h b/src/lisp.h index 4ae55c5519e..82036f3030e 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -3101,6 +3101,8 @@ extern int wait_reading_process_output P_ ((int, int, int, int, int)); extern void add_keyboard_wait_descriptor P_ ((int)); extern void delete_keyboard_wait_descriptor P_ ((int)); +extern void add_gpm_wait_descriptor P_ ((int)); +extern void delete_gpm_wait_descriptor P_ ((int)); extern void close_process_descs P_ ((void)); extern void init_process P_ ((void)); extern void syms_of_process P_ ((void)); diff --git a/src/m/alpha.h b/src/m/alpha.h index 6a9f09ed0bd..3b29a8ee7be 100644 --- a/src/m/alpha.h +++ b/src/m/alpha.h @@ -99,10 +99,6 @@ NOTE-END # endif #endif -#if defined(__OpenBSD__) -#define ORDINARY_LINK -#endif - #ifdef __ELF__ #undef UNEXEC #define UNEXEC unexelf.o diff --git a/src/m/macppc.h b/src/m/macppc.h index 117d7a11dc4..26994575edd 100644 --- a/src/m/macppc.h +++ b/src/m/macppc.h @@ -66,10 +66,6 @@ Boston, MA 02110-1301, USA. */ /* #define NO_SOCK_SIGIO */ -#if defined(__OpenBSD__) -#define ORDINARY_LINK -#endif - #define UNEXEC unexelf.o #define NO_TERMIO diff --git a/src/macterm.c b/src/macterm.c index b48ffb47fdb..e31fba134f5 100644 --- a/src/macterm.c +++ b/src/macterm.c @@ -6079,7 +6079,9 @@ x_calc_absolute_position (f) /* Find the offsets of the outside upper-left corner of the inner window, with respect to the outer window. */ + BLOCK_INPUT; mac_get_window_bounds (f, &inner, &outer); + UNBLOCK_INPUT; width_diff = (outer.right - outer.left) - (inner.right - inner.left); height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top); @@ -9159,15 +9161,16 @@ mac_get_mouse_btn (EventRef ref) /* Normally, ConvertEventRefToEventRecord will correctly handle all events. However the click of the mouse wheel is not converted to a - mouseDown or mouseUp event. Likewise for dead key down events. - This calls ConvertEventRef, but then checks to see if it is a mouse - up/down, or a dead key down carbon event that has not been + mouseDown or mouseUp event. Likewise for dead key events. This + calls ConvertEventRefToEventRecord, but then checks to see if it is + a mouse up/down, or a dead key Carbon event that has not been converted, and if so, converts it by hand (to be picked up in the XTread_socket loop). */ static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec) { OSStatus err; Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec); + EventKind action; if (result) return result; @@ -9196,6 +9199,14 @@ static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec) switch (GetEventKind (eventRef)) { case kEventRawKeyDown: + action = keyDown; + goto keystroke_common; + case kEventRawKeyRepeat: + action = autoKey; + goto keystroke_common; + case kEventRawKeyUp: + action = keyUp; + keystroke_common: { unsigned char char_codes; UInt32 key_code; @@ -9209,7 +9220,7 @@ static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec) NULL, &key_code); if (err == noErr) { - eventRec->what = keyDown; + eventRec->what = action; eventRec->message = char_codes | ((key_code & 0xff) << 8); result = 1; } diff --git a/src/process.c b/src/process.c index bd12f3e1a68..9a7cf29963f 100644 --- a/src/process.c +++ b/src/process.c @@ -336,6 +336,10 @@ static SELECT_TYPE non_keyboard_wait_mask; static SELECT_TYPE non_process_wait_mask; +/* Mask for the gpm mouse input descriptor. */ + +static SELECT_TYPE gpm_wait_mask; + #ifdef NON_BLOCKING_CONNECT /* Mask of bits indicating the descriptors that we wait for connect to complete on. Once they complete, they are removed from this mask @@ -357,6 +361,9 @@ static int max_process_desc; /* The largest descriptor currently in use for keyboard input. */ static int max_keyboard_desc; +/* The largest descriptor currently in use for gpm mouse input. */ +static int max_gpm_desc; + /* Nonzero means delete a process right away if it exits. */ static int delete_exited_processes; @@ -4451,7 +4458,8 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display, IF_NON_BLOCKING_CONNECT (Ctemp = connect_wait_mask); EMACS_SET_SECS_USECS (timeout, 0, 0); - if ((select (max (max_process_desc, max_keyboard_desc) + 1, + if ((select (max (max (max_process_desc, max_keyboard_desc), + max_gpm_desc) + 1, &Atemp, #ifdef NON_BLOCKING_CONNECT (num_pending_connects > 0 ? &Ctemp : (SELECT_TYPE *)0), @@ -4596,7 +4604,8 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display, } #endif - nfds = select (max (max_process_desc, max_keyboard_desc) + 1, + nfds = select (max (max (max_process_desc, max_keyboard_desc), + max_gpm_desc) + 1, &Available, #ifdef NON_BLOCKING_CONNECT (check_connect ? &Connecting : (SELECT_TYPE *)0), @@ -6975,6 +6984,21 @@ add_keyboard_wait_descriptor (desc) max_keyboard_desc = desc; } +static int add_gpm_wait_descriptor_called_flag; + +void +add_gpm_wait_descriptor (desc) + int desc; +{ + if (! add_gpm_wait_descriptor_called_flag) + FD_CLR (0, &input_wait_mask); + add_gpm_wait_descriptor_called_flag = 1; + FD_SET (desc, &input_wait_mask); + FD_SET (desc, &gpm_wait_mask); + if (desc > max_gpm_desc) + max_gpm_desc = desc; +} + /* From now on, do not expect DESC to give keyboard input. */ void @@ -6990,10 +7014,29 @@ delete_keyboard_wait_descriptor (desc) if (desc == max_keyboard_desc) for (fd = 0; fd < lim; fd++) if (FD_ISSET (fd, &input_wait_mask) - && !FD_ISSET (fd, &non_keyboard_wait_mask)) + && !FD_ISSET (fd, &non_keyboard_wait_mask) + && !FD_ISSET (fd, &gpm_wait_mask)) max_keyboard_desc = fd; } +void +delete_gpm_wait_descriptor (desc) + int desc; +{ + int fd; + int lim = max_gpm_desc; + + FD_CLR (desc, &input_wait_mask); + FD_CLR (desc, &non_process_wait_mask); + + if (desc == max_gpm_desc) + for (fd = 0; fd < lim; fd++) + if (FD_ISSET (fd, &input_wait_mask) + && !FD_ISSET (fd, &non_keyboard_wait_mask) + && !FD_ISSET (fd, &non_process_wait_mask)) + max_gpm_desc = fd; +} + /* Return nonzero if *MASK has a bit set that corresponds to one of the keyboard input descriptors. */ diff --git a/src/syntax.c b/src/syntax.c index a9e6dda81fe..acb5d37825c 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -1669,10 +1669,10 @@ skip_chars (forwardp, syntaxp, string, lim, handle_iso_classes) p = GPT_ADDR; stop = endp; } + UPDATE_SYNTAX_TABLE_BACKWARD (pos - 1); if (! fastmap[(int) SYNTAX (p[-1])]) break; p--, pos--; - UPDATE_SYNTAX_TABLE_BACKWARD (pos - 1); } } } diff --git a/src/sysdep.c b/src/sysdep.c index bbaa09fbf27..ba55d2361bb 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -1747,6 +1747,14 @@ init_sys_modes (tty_out) fcntl (fileno (tty_out->input), F_GETOWN, 0); fcntl (fileno (tty_out->input), F_SETOWN, getpid ()); init_sigio (fileno (tty_out->input)); +#ifdef HAVE_GPM + if (term_gpm) + { + fcntl (gpm_fd, F_SETOWN, getpid ()); + fcntl (gpm_fd, F_SETFL, O_NONBLOCK); + init_sigio (gpm_fd); + } +#endif /* HAVE_GPM */ } #endif /* F_GETOWN */ #endif /* F_SETOWN_BUG */ diff --git a/src/term.c b/src/term.c index 53727a975ea..1d8e885ade9 100644 --- a/src/term.c +++ b/src/term.c @@ -171,6 +171,9 @@ static int system_uses_terminfo; char *tparam (); extern char *tgetstr (); + +static void term_clear_mouse_face (); +static void term_mouse_highlight (struct frame *f, int x, int y); #ifdef WINDOWSNT @@ -184,6 +187,35 @@ extern char *tgetstr (); #define FRAME_TERMCAP_P(_f_) 0 #endif /* WINDOWSNT */ +#ifdef HAVE_GPM +#include <sys/fcntl.h> +#include "buffer.h" + +/* Nonzero means mouse is enabled on Linux console. */ +int term_gpm = 0; + +/* The id of the terminal device for which we have gpm support. */ +int gpm_tty; + +/* These variables describe the range of text currently shown in its + mouse-face, together with the window they apply to. As long as + the mouse stays within this range, we need not redraw anything on + its account. Rows and columns are glyph matrix positions in + MOUSE_FACE_WINDOW. */ +static int mouse_face_beg_row, mouse_face_beg_col; +static int mouse_face_end_row, mouse_face_end_col; +static int mouse_face_past_end; +static Lisp_Object mouse_face_window; +static int mouse_face_face_id; + +/* FRAME and X, Y position of mouse when last checked for + highlighting. X and Y can be negative or out of range for the frame. */ +struct frame *mouse_face_mouse_frame; +int mouse_face_mouse_x, mouse_face_mouse_y; + +static int pos_x, pos_y; +static int last_mouse_x, last_mouse_y; +#endif /* HAVE_GPM */ /* Ring the bell on a tty. */ @@ -715,6 +747,66 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len) cmcheckmagic (tty); } +static void +tty_write_glyphs_with_face (f, string, len, face_id) + register struct frame *f; + register struct glyph *string; + register int len, face_id; +{ + unsigned char *conversion_buffer; + struct coding_system *coding; + + struct tty_display_info *tty = FRAME_TTY (f); + + tty_turn_off_insert (tty); + tty_hide_cursor (tty); + + /* Don't dare write in last column of bottom line, if Auto-Wrap, + since that would scroll the whole frame on some terminals. */ + + if (AutoWrap (tty) + && curY (tty) + 1 == FRAME_LINES (f) + && (curX (tty) + len) == FRAME_COLS (f)) + len --; + if (len <= 0) + return; + + cmplus (tty, len); + + /* If terminal_coding does any conversion, use it, otherwise use + safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here + because it always return 1 if the member src_multibyte is 1. */ + coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK + ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding); + /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at + the tail. */ + coding->mode &= ~CODING_MODE_LAST_BLOCK; + + /* Turn appearance modes of the face. */ + tty_highlight_if_desired (tty); + turn_on_face (f, face_id); + + coding->mode |= CODING_MODE_LAST_BLOCK; + conversion_buffer = encode_terminal_code (string, len, coding); + if (coding->produced > 0) + { + BLOCK_INPUT; + fwrite (conversion_buffer, 1, coding->produced, tty->output); + if (ferror (tty->output)) + clearerr (tty->output); + if (tty->termscript) + fwrite (conversion_buffer, 1, coding->produced, tty->termscript); + UNBLOCK_INPUT; + } + + /* Turn appearance modes off. */ + turn_off_face (f, face_id); + tty_turn_off_highlight (tty); + + cmcheckmagic (tty); +} + + /* An implementation of insert_glyphs for termcap frames. */ static void @@ -2248,6 +2340,663 @@ the currently selected frame. */) /*********************************************************************** + Mouse + ***********************************************************************/ + +#ifdef HAVE_GPM +static void +term_show_mouse_face (enum draw_glyphs_face draw) +{ + struct window *w = XWINDOW (mouse_face_window); + int save_x, save_y; + int i, j; + + struct frame *f = XFRAME (w->frame); + struct tty_display_info *tty = FRAME_TTY (f); + + if (/* If window is in the process of being destroyed, don't bother + to do anything. */ + w->current_matrix != NULL + /* Recognize when we are called to operate on rows that don't exist + anymore. This can happen when a window is split. */ + && mouse_face_end_row < w->current_matrix->nrows) + { + /* write_glyphs writes at cursor position, so we need to + temporarily move cursor coordinates to the beginning of + the highlight region. */ + + /* Save current cursor co-ordinates */ + save_y = curY (tty); + save_x = curX (tty); + + /* Note that mouse_face_beg_row etc. are window relative. */ + for (i = mouse_face_beg_row; i <= mouse_face_end_row; i++) + { + int start_hpos, end_hpos, nglyphs; + struct glyph_row *row = MATRIX_ROW (w->current_matrix, i); + + /* Don't do anything if row doesn't have valid contents. */ + if (!row->enabled_p) + continue; + + /* For all but the first row, the highlight starts at column 0. */ + if (i == mouse_face_beg_row) + start_hpos = mouse_face_beg_col; + else + start_hpos = 0; + + if (i == mouse_face_end_row) + end_hpos = mouse_face_end_col; + else + { + end_hpos = row->used[TEXT_AREA]; + if (draw == DRAW_NORMAL_TEXT) + row->fill_line_p = 1; /* Clear to end of line */ + } + + if (end_hpos <= start_hpos) + continue; + /* Record that some glyphs of this row are displayed in + mouse-face. */ + row->mouse_face_p = draw > 0; + + nglyphs = end_hpos - start_hpos; + + if (end_hpos >= row->used[TEXT_AREA]) + nglyphs = row->used[TEXT_AREA] - start_hpos; + + pos_y = row->y + WINDOW_TOP_EDGE_Y (w); + pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + + WINDOW_LEFT_EDGE_X (w); + + cursor_to (f, pos_y, pos_x); + + if (draw == DRAW_MOUSE_FACE) + { + tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos, + nglyphs, mouse_face_face_id); + } + else /* draw == DRAW_NORMAL_TEXT */ + write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs); + } + cursor_to (f, save_y, save_x); + } +} + +static void +term_clear_mouse_face () +{ + if (!NILP (mouse_face_window)) + term_show_mouse_face (DRAW_NORMAL_TEXT); + + mouse_face_beg_row = mouse_face_beg_col = -1; + mouse_face_end_row = mouse_face_end_col = -1; + mouse_face_window = Qnil; +} + +/* Find the glyph matrix position of buffer position POS in window W. + *HPOS and *VPOS are set to the positions found. W's current glyphs + must be up to date. If POS is above window start return (0, 0). + If POS is after end of W, return end of last line in W. + - taken from msdos.c */ +static int +fast_find_position (struct window *w, int pos, int *hpos, int *vpos) +{ + int i, lastcol, line_start_position, maybe_next_line_p = 0; + int yb = window_text_bottom_y (w); + struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0), *best_row = row; + + while (row->y < yb) + { + if (row->used[TEXT_AREA]) + line_start_position = row->glyphs[TEXT_AREA]->charpos; + else + line_start_position = 0; + + if (line_start_position > pos) + break; + /* If the position sought is the end of the buffer, + don't include the blank lines at the bottom of the window. */ + else if (line_start_position == pos + && pos == BUF_ZV (XBUFFER (w->buffer))) + { + maybe_next_line_p = 1; + break; + } + else if (line_start_position > 0) + best_row = row; + + /* Don't overstep the last matrix row, lest we get into the + never-never land... */ + if (row->y + 1 >= yb) + break; + + ++row; + } + + /* Find the right column within BEST_ROW. */ + lastcol = 0; + row = best_row; + for (i = 0; i < row->used[TEXT_AREA]; i++) + { + struct glyph *glyph = row->glyphs[TEXT_AREA] + i; + int charpos; + + charpos = glyph->charpos; + if (charpos == pos) + { + *hpos = i; + *vpos = row->y; + return 1; + } + else if (charpos > pos) + break; + else if (charpos > 0) + lastcol = i; + } + + /* If we're looking for the end of the buffer, + and we didn't find it in the line we scanned, + use the start of the following line. */ + if (maybe_next_line_p) + { + ++row; + lastcol = 0; + } + + *vpos = row->y; + *hpos = lastcol + 1; + return 0; +} + +static void +term_mouse_highlight (struct frame *f, int x, int y) +{ + enum window_part part; + Lisp_Object window; + struct window *w; + struct buffer *b; + + if (NILP (Vmouse_highlight) + || !f->glyphs_initialized_p) + return; + + mouse_face_mouse_x = x; + mouse_face_mouse_y = y; + mouse_face_mouse_frame = f; + + /* Which window is that in? */ + window = window_from_coordinates (f, x, y, &part, &x, &y, 0); + + /* Not on a window -> return. */ + if (!WINDOWP (window)) + return; + + if (!EQ (window, mouse_face_window)) + term_clear_mouse_face (); + + w = XWINDOW (window); + + /* Are we in a window whose display is up to date? + And verify the buffer's text has not changed. */ + b = XBUFFER (w->buffer); + if (part == ON_TEXT + && EQ (w->window_end_valid, w->buffer) + && XFASTINT (w->last_modified) == BUF_MODIFF (b) + && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b)) + { + int pos, i, nrows = w->current_matrix->nrows; + struct glyph_row *row; + struct glyph *glyph; + + /* Find the glyph under X/Y. */ + glyph = NULL; + if (y >= 0 && y < nrows) + { + row = MATRIX_ROW (w->current_matrix, y); + /* Give up if some row before the one we are looking for is + not enabled. */ + for (i = 0; i <= y; i++) + if (!MATRIX_ROW (w->current_matrix, i)->enabled_p) + break; + if (i > y /* all rows upto and including the one at Y are enabled */ + && row->displays_text_p + && x < window_box_width (w, TEXT_AREA)) + { + glyph = row->glyphs[TEXT_AREA]; + if (x >= row->used[TEXT_AREA]) + glyph = NULL; + else + { + glyph += x; + if (!BUFFERP (glyph->object)) + glyph = NULL; + } + } + } + + /* Clear mouse face if X/Y not over text. */ + if (glyph == NULL) + { + term_clear_mouse_face (); + return; + } + + if (!BUFFERP (glyph->object)) + abort (); + pos = glyph->charpos; + + /* Check for mouse-face. */ + { + extern Lisp_Object Qmouse_face; + Lisp_Object mouse_face, overlay, position, *overlay_vec; + int noverlays, obegv, ozv;; + struct buffer *obuf; + + /* If we get an out-of-range value, return now; avoid an error. */ + if (pos > BUF_Z (b)) + return; + + /* Make the window's buffer temporarily current for + overlays_at and compute_char_face. */ + obuf = current_buffer; + current_buffer = b; + obegv = BEGV; + ozv = ZV; + BEGV = BEG; + ZV = Z; + + /* Is this char mouse-active? */ + XSETINT (position, pos); + + /* Put all the overlays we want in a vector in overlay_vec. */ + GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, 0); + /* Sort overlays into increasing priority order. */ + noverlays = sort_overlays (overlay_vec, noverlays, w); + + /* Check mouse-face highlighting. */ + if (!(EQ (window, mouse_face_window) + && y >= mouse_face_beg_row + && y <= mouse_face_end_row + && (y > mouse_face_beg_row + || x >= mouse_face_beg_col) + && (y < mouse_face_end_row + || x < mouse_face_end_col + || mouse_face_past_end))) + { + /* Clear the display of the old active region, if any. */ + term_clear_mouse_face (); + + /* Find the highest priority overlay that has a mouse-face + property. */ + overlay = Qnil; + for (i = noverlays - 1; i >= 0; --i) + { + mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face); + if (!NILP (mouse_face)) + { + overlay = overlay_vec[i]; + break; + } + } + + /* If no overlay applies, get a text property. */ + if (NILP (overlay)) + mouse_face = Fget_text_property (position, Qmouse_face, + w->buffer); + + /* Handle the overlay case. */ + if (!NILP (overlay)) + { + /* Find the range of text around this char that + should be active. */ + Lisp_Object before, after; + int ignore; + + + before = Foverlay_start (overlay); + after = Foverlay_end (overlay); + /* Record this as the current active region. */ + fast_find_position (w, XFASTINT (before), + &mouse_face_beg_col, + &mouse_face_beg_row); + + mouse_face_past_end + = !fast_find_position (w, XFASTINT (after), + &mouse_face_end_col, + &mouse_face_end_row); + mouse_face_window = window; + + mouse_face_face_id + = face_at_buffer_position (w, pos, 0, 0, + &ignore, pos + 1, 1); + + /* Display it as active. */ + term_show_mouse_face (DRAW_MOUSE_FACE); + } + /* Handle the text property case. */ + else if (!NILP (mouse_face)) + { + /* Find the range of text around this char that + should be active. */ + Lisp_Object before, after, beginning, end; + int ignore; + + beginning = Fmarker_position (w->start); + XSETINT (end, (BUF_Z (b) - XFASTINT (w->window_end_pos))); + before + = Fprevious_single_property_change (make_number (pos + 1), + Qmouse_face, + w->buffer, beginning); + after + = Fnext_single_property_change (position, Qmouse_face, + w->buffer, end); + + /* Record this as the current active region. */ + fast_find_position (w, XFASTINT (before), + &mouse_face_beg_col, + &mouse_face_beg_row); + mouse_face_past_end + = !fast_find_position (w, XFASTINT (after), + &mouse_face_end_col, + &mouse_face_end_row); + mouse_face_window = window; + + mouse_face_face_id + = face_at_buffer_position (w, pos, 0, 0, + &ignore, pos + 1, 1); + + /* Display it as active. */ + term_show_mouse_face (DRAW_MOUSE_FACE); + } + } + + /* Look for a `help-echo' property. */ + { + Lisp_Object help; + extern Lisp_Object Qhelp_echo; + + /* Check overlays first. */ + help = Qnil; + for (i = noverlays - 1; i >= 0 && NILP (help); --i) + { + overlay = overlay_vec[i]; + help = Foverlay_get (overlay, Qhelp_echo); + } + + if (!NILP (help)) + { + help_echo_string = help; + help_echo_window = window; + help_echo_object = overlay; + help_echo_pos = pos; + } + /* Try text properties. */ + else if (NILP (help) + && ((STRINGP (glyph->object) + && glyph->charpos >= 0 + && glyph->charpos < SCHARS (glyph->object)) + || (BUFFERP (glyph->object) + && glyph->charpos >= BEGV + && glyph->charpos < ZV))) + { + help = Fget_text_property (make_number (glyph->charpos), + Qhelp_echo, glyph->object); + if (!NILP (help)) + { + help_echo_string = help; + help_echo_window = window; + help_echo_object = glyph->object; + help_echo_pos = glyph->charpos; + } + } + } + + BEGV = obegv; + ZV = ozv; + current_buffer = obuf; + } + } +} + +static int +term_mouse_movement (FRAME_PTR frame, Gpm_Event *event) +{ + /* Has the mouse moved off the glyph it was on at the last sighting? */ + if (event->x != last_mouse_x || event->y != last_mouse_y) + { + frame->mouse_moved = 1; + term_mouse_highlight (frame, event->x - 1, event->y - 1); + /* Remember which glyph we're now on. */ + last_mouse_x = event->x; + last_mouse_y = event->y; + return 1; + } + return 0; +} + +/* Return the current position of the mouse. + + Set *f to the frame the mouse is in, or zero if the mouse is in no + Emacs frame. If it is set to zero, all the other arguments are + garbage. + + Set *bar_window to Qnil, and *x and *y to the column and + row of the character cell the mouse is over. + + Set *time to the time the mouse was at the returned position. + + This should clear mouse_moved until the next motion + event arrives. + + NOT CURRENTLY INVOKED: see mouse_position_hook below. */ +static void +term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window, + enum scroll_bar_part *part, Lisp_Object *x, + Lisp_Object *y, unsigned long *time) +{ + Gpm_Event event; + struct timeval now; + int i; + + BLOCK_INPUT; + + *fp = SELECTED_FRAME (); + + *bar_window = Qnil; + *part = 0; + + i = Gpm_GetSnapshot (&event); + + XSETINT (*x, event.x); + XSETINT (*y, event.y); + gettimeofday(&now, 0); + *time = (now.tv_sec * 1000) + (now.tv_usec / 1000); + + UNBLOCK_INPUT; +} + +/* Prepare a mouse-event in *RESULT for placement in the input queue. + + If the event is a button press, then note that we have grabbed + the mouse. */ + +static Lisp_Object +term_mouse_click (struct input_event *result, Gpm_Event *event, + struct frame *f) +{ + struct timeval now; + int i, j; + + result->kind = GPM_CLICK_EVENT; + for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 ) + { + if (event->buttons & j) { + result->code = i; /* button number */ + break; + } + } + gettimeofday(&now, 0); + result->timestamp = (now.tv_sec * 1000) + (now.tv_usec / 1000); + + if (event->type & GPM_UP) + result->modifiers = up_modifier; + else if (event->type & GPM_DOWN) + result->modifiers = down_modifier; + else + result->modifiers = 0; + + if (event->type & GPM_SINGLE) + result->modifiers |= click_modifier; + + if (event->type & GPM_DOUBLE) + result->modifiers |= double_modifier; + + if (event->type & GPM_TRIPLE) + result->modifiers |= triple_modifier; + + if (event->type & GPM_DRAG) + result->modifiers |= drag_modifier; + + if (!(event->type & (GPM_MOVE|GPM_DRAG))) { + + /* 1 << KG_SHIFT */ + if (event->modifiers & (1 << 0)) + result->modifiers |= shift_modifier; + + /* 1 << KG_CTRL */ + if (event->modifiers & (1 << 2)) + result->modifiers |= ctrl_modifier; + + /* 1 << KG_ALT || KG_ALTGR */ + if (event->modifiers & (1 << 3) + || event->modifiers & (1 << 1)) + result->modifiers |= meta_modifier; + } + + XSETINT (result->x, event->x - 1); + XSETINT (result->y, event->y - 1); + XSETFRAME (result->frame_or_window, f); + result->arg = Qnil; + return Qnil; +} + +int +handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit) +{ + struct frame *f = XFRAME (tty->top_frame); + int i, j, fd; + struct input_event ie; + int do_help = 0; + int count = 0; + + EVENT_INIT (ie); + ie.kind = NO_EVENT; + ie.arg = Qnil; + + if (event->type & GPM_MOVE) { + unsigned char buf[6 * sizeof (short)]; + unsigned short *arg = (unsigned short *) buf + 1; + const char *name; + + previous_help_echo_string = help_echo_string; + help_echo_string = Qnil; + + /* Display mouse pointer */ + buf[sizeof(short) - 1] = 2; /* set selection */ + + arg[0] = arg[2] = (unsigned short) event->x; + arg[1] = arg[3] = (unsigned short) event->y; + arg[4] = (unsigned short) 3; + + name = (const char *) ttyname (0); + fd = open (name, O_WRONLY); + ioctl (fd, TIOCLINUX, buf + sizeof (short) - 1); + close(fd); + + term_mouse_movement (f, event); + + /* If the contents of the global variable help_echo_string + has changed, generate a HELP_EVENT. */ + if (!NILP (help_echo_string) + || !NILP (previous_help_echo_string)) + do_help = 1; + + goto done; + } + else { + f->mouse_moved = 0; + term_mouse_click (&ie, event, f); + //kbd_buffer_store_event_hold (&ie, hold_quit); + } + + done: + if (ie.kind != NO_EVENT) + { + kbd_buffer_store_event_hold (&ie, hold_quit); + count++; + } + + if (do_help + && !(hold_quit && hold_quit->kind != NO_EVENT)) + { + Lisp_Object frame; + + if (f) + XSETFRAME (frame, f); + else + frame = Qnil; + + gen_help_event (help_echo_string, frame, help_echo_window, + help_echo_object, help_echo_pos); + count++; + } + + return count; +} + +DEFUN ("term-open-connection", Fterm_open_connection, Sterm_open_connection, + 0, 0, 0, + doc: /* Open a connection to Gpm. */) + () +{ + struct tty_display_info *tty = FRAME_TTY (SELECTED_FRAME ()); + Gpm_Connect connection; + + connection.eventMask = ~0; + connection.defaultMask = ~GPM_HARD; + connection.maxMod = ~0; + connection.minMod = 0; + + /* We only support GPM on the controlling tty. */ + if (term_gpm || tty->terminal->id > 1 + || Gpm_Open (&connection, 0) < 0) + return Qnil; + else + { + term_gpm = 1; + gpm_tty = tty->terminal->id; + reset_sys_modes (tty); + init_sys_modes (tty); + add_gpm_wait_descriptor (gpm_fd); + return Qt; + } +} + +DEFUN ("term-close-connection", Fterm_close_connection, Sterm_close_connection, + 0, 0, 0, + doc: /* Close a connection to Gpm. */) + () +{ + delete_gpm_wait_descriptor (gpm_fd); + while (Gpm_Close()); /* close all the stack */ + term_gpm = 0; + return Qnil; +} +#endif /* HAVE_GPM */ + + +/*********************************************************************** Initialization ***********************************************************************/ @@ -2509,6 +3258,14 @@ init_tty (char *name, char *terminal_type, int must_succeed) encode_terminal_bufsize = 0; +#ifdef HAVE_GPM + /* TODO: Can't get Gpm_Snapshot in term_mouse_position to work: test with + (mouse-position). Also set-mouse-position won't work as is. */ + /* mouse_position_hook = term_mouse_position; */ + + mouse_face_window = Qnil; +#endif + #ifdef WINDOWSNT initialize_w32_display (); @@ -3139,6 +3896,10 @@ bigger, or it may make it blink, or it may do nothing at all. */); defsubr (&Scontrolling_tty_p); defsubr (&Ssuspend_tty); defsubr (&Sresume_tty); +#ifdef HAVE_GPM + defsubr (&Sterm_open_connection); + defsubr (&Sterm_close_connection); +#endif /* HAVE_GPM */ } diff --git a/src/termhooks.h b/src/termhooks.h index e9fcbb37750..373d1e34987 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -191,7 +191,11 @@ enum event_kind symbols, respectively. Member `arg' is a Lisp object converted from the received Apple event. Parameters for non-Apple events are converted to those in Apple events. */ - MAC_APPLE_EVENT + MAC_APPLE_EVENT, +#endif + +#ifdef HAVE_GPM + GPM_CLICK_EVENT #endif }; @@ -290,6 +294,17 @@ enum { meta_modifier = CHAR_META /* Under X, the XK_Meta_[LR] keysyms. */ }; +#ifdef HAVE_GPM +#include <gpm.h> +extern int handle_one_term_event (struct tty_display_info *, Gpm_Event *, struct input_event *); + +/* Nonzero means mouse is enabled on Linux console */ +extern int term_gpm; + +/* The id of the terminal device for which we have gpm support. */ +extern int gpm_tty; +#endif + #endif /* CONSP */ diff --git a/src/xdisp.c b/src/xdisp.c index da2c0e7c7a0..8459be7abb7 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -12786,7 +12786,7 @@ redisplay_window (window, just_this_one_p) int rc; int centering_position = -1; int last_line_misfit = 0; - int save_beg_unchanged, save_end_unchanged; + int beg_unchanged, end_unchanged; SET_TEXT_POS (lpoint, PT, PT_BYTE); opoint = lpoint; @@ -12851,8 +12851,8 @@ redisplay_window (window, just_this_one_p) set_buffer_internal_1 (XBUFFER (w->buffer)); SET_TEXT_POS (opoint, PT, PT_BYTE); - save_beg_unchanged = BEG_UNCHANGED; - save_end_unchanged = END_UNCHANGED; + beg_unchanged = BEG_UNCHANGED; + end_unchanged = END_UNCHANGED; current_matrix_up_to_date_p = (!NILP (w->window_end_valid) @@ -12977,6 +12977,8 @@ redisplay_window (window, just_this_one_p) w->force_start = Qt; } + force_start: + /* Handle case where place to start displaying has been specified, unless the specified location is outside the accessible range. */ if (!NILP (w->force_start) @@ -13156,40 +13158,16 @@ redisplay_window (window, just_this_one_p) than a simple mouse-click. */ if (NILP (w->start_at_line_beg) && NILP (do_mouse_tracking) - && CHARPOS (startp) > BEGV) + && CHARPOS (startp) > BEGV + && CHARPOS (startp) > BEG + beg_unchanged + && CHARPOS (startp) <= Z - end_unchanged) { -#if 0 - /* The following code tried to make BEG_UNCHANGED and - END_UNCHANGED up to date (similar to try_window_id). - Is it important to do so? - - The trouble is that it's a little too strict when it - comes to overlays: modify_overlay can call - BUF_COMPUTE_UNCHANGED, which alters BUF_BEG_UNCHANGED and - BUF_END_UNCHANGED directly without moving the gap. - - This can result in spurious recentering when overlays are - altered in the buffer. So unless it's proven necessary, - let's leave this commented out for now. -- cyd. */ - if (MODIFF > SAVE_MODIFF - || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE) - { - if (GPT - BEG < BEG_UNCHANGED) - BEG_UNCHANGED = GPT - BEG; - if (Z - GPT < END_UNCHANGED) - END_UNCHANGED = Z - GPT; - } -#endif - - if (CHARPOS (startp) > BEG + save_beg_unchanged - && CHARPOS (startp) <= Z - save_end_unchanged) - { - /* There doesn't seems to be a simple way to find a new - window start that is near the old window start, so - we just recenter. */ - goto recenter; - } - } + w->force_start = Qt; + if (XMARKER (w->start)->buffer == current_buffer) + compute_window_start_on_continuation_line (w); + SET_TEXT_POS_FROM_MARKER (startp, w->start); + goto force_start; + } #if GLYPH_DEBUG debug_method_add (w, "same window start"); |