comparison src/term.c @ 90851:31beec9ee600

Merge from emacs--devo--0 Patches applied: * emacs--devo--0 (patch 751-770) - Update from CVS - Merge from emacs--rel--22 - Update from CVS: lisp/textmodes/sgml-mode.el: Revert last change. - Merge from gnus--rel--5.10 * emacs--rel--22 (patch 18-25) * gnus--rel--5.10 (patch 222-223) - Update from CVS Revision: emacs@sv.gnu.org/emacs--unicode--0--patch-208
author Miles Bader <miles@gnu.org>
date Thu, 24 May 2007 21:31:10 +0000
parents c0409ee15cee 62b6aa7f8c37
children d17324297760
comparison
equal deleted inserted replaced
90850:7d184cd91770 90851:31beec9ee600
144 void (*delete_glyphs_hook) P_ ((int)); 144 void (*delete_glyphs_hook) P_ ((int));
145 145
146 int (*read_socket_hook) P_ ((int, int, struct input_event *)); 146 int (*read_socket_hook) P_ ((int, int, struct input_event *));
147 147
148 void (*frame_up_to_date_hook) P_ ((struct frame *)); 148 void (*frame_up_to_date_hook) P_ ((struct frame *));
149
150 /* Return the current position of the mouse.
151
152 Set *f to the frame the mouse is in, or zero if the mouse is in no
153 Emacs frame. If it is set to zero, all the other arguments are
154 garbage.
155
156 If the motion started in a scroll bar, set *bar_window to the
157 scroll bar's window, *part to the part the mouse is currently over,
158 *x to the position of the mouse along the scroll bar, and *y to the
159 overall length of the scroll bar.
160
161 Otherwise, set *bar_window to Qnil, and *x and *y to the column and
162 row of the character cell the mouse is over.
163
164 Set *time to the time the mouse was at the returned position.
165
166 This should clear mouse_moved until the next motion
167 event arrives. */
168 149
169 void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist, 150 void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist,
170 Lisp_Object *bar_window, 151 Lisp_Object *bar_window,
171 enum scroll_bar_part *part, 152 enum scroll_bar_part *part,
172 Lisp_Object *x, 153 Lisp_Object *x,
414 static int tty_cursor_hidden; 395 static int tty_cursor_hidden;
415 396
416 char *tparam (); 397 char *tparam ();
417 398
418 extern char *tgetstr (); 399 extern char *tgetstr ();
400
401 static void term_clear_mouse_face ();
402 static void term_mouse_highlight (struct frame *f, int x, int y);
419 403
420 404
421 #ifdef WINDOWSNT 405 #ifdef WINDOWSNT
422 /* We aren't X windows, but we aren't termcap either. This makes me 406 /* We aren't X windows, but we aren't termcap either. This makes me
423 uncertain as to what value to use for frame.output_method. For 407 uncertain as to what value to use for frame.output_method. For
426 the best long-term solution is to define an output_windows_nt... */ 410 the best long-term solution is to define an output_windows_nt... */
427 411
428 #undef FRAME_TERMCAP_P 412 #undef FRAME_TERMCAP_P
429 #define FRAME_TERMCAP_P(_f_) 0 413 #define FRAME_TERMCAP_P(_f_) 0
430 #endif /* WINDOWSNT */ 414 #endif /* WINDOWSNT */
415
416 #ifdef HAVE_GPM
417 #include <sys/fcntl.h>
418 #include "buffer.h"
419
420 /* Nonzero means mouse is enabled on Linux console. */
421 int term_gpm = 0;
422
423 /* These variables describe the range of text currently shown in its
424 mouse-face, together with the window they apply to. As long as
425 the mouse stays within this range, we need not redraw anything on
426 its account. Rows and columns are glyph matrix positions in
427 MOUSE_FACE_WINDOW. */
428 static int mouse_face_beg_row, mouse_face_beg_col;
429 static int mouse_face_end_row, mouse_face_end_col;
430 static int mouse_face_past_end;
431 static Lisp_Object mouse_face_window;
432 static int mouse_face_face_id;
433
434 /* FRAME and X, Y position of mouse when last checked for
435 highlighting. X and Y can be negative or out of range for the frame. */
436 struct frame *mouse_face_mouse_frame;
437 int mouse_face_mouse_x, mouse_face_mouse_y;
438
439 static int pos_x, pos_y;
440 static int last_mouse_x, last_mouse_y;
441 #endif /* HAVE_GPM */
431 442
432 void 443 void
433 ring_bell () 444 ring_bell ()
434 { 445 {
435 if (!NILP (Vring_bell_function)) 446 if (!NILP (Vring_bell_function))
1071 1082
1072 /* Turn appearance modes off. */ 1083 /* Turn appearance modes off. */
1073 turn_off_face (f, face_id); 1084 turn_off_face (f, face_id);
1074 turn_off_highlight (); 1085 turn_off_highlight ();
1075 } 1086 }
1087
1088 cmcheckmagic ();
1089 }
1090
1091 void
1092 write_glyphs_with_face (string, len, face_id)
1093 register struct glyph *string;
1094 register int len, face_id;
1095 {
1096 struct frame *sf = XFRAME (selected_frame);
1097 struct frame *f = updating_frame ? updating_frame : sf;
1098 unsigned char *conversion_buffer;
1099 struct coding_system *coding;
1100
1101 turn_off_insert ();
1102 tty_hide_cursor ();
1103
1104 /* Don't dare write in last column of bottom line, if Auto-Wrap,
1105 since that would scroll the whole frame on some terminals. */
1106
1107 if (AutoWrap
1108 && curY + 1 == FRAME_LINES (sf)
1109 && (curX + len) == FRAME_COLS (sf))
1110 len --;
1111 if (len <= 0)
1112 return;
1113
1114 cmplus (len);
1115
1116 /* If terminal_coding does any conversion, use it, otherwise use
1117 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
1118 because it always return 1 if the member src_multibyte is 1. */
1119 coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
1120 ? &terminal_coding : &safe_terminal_coding);
1121 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
1122 the tail. */
1123 coding->mode &= ~CODING_MODE_LAST_BLOCK;
1124
1125
1126 /* Turn appearance modes of the face. */
1127 highlight_if_desired ();
1128 turn_on_face (f, face_id);
1129
1130 coding->mode |= CODING_MODE_LAST_BLOCK;
1131 conversion_buffer = encode_terminal_code (string, len, coding);
1132 if (coding->produced > 0)
1133 {
1134 BLOCK_INPUT;
1135 fwrite (conversion_buffer, 1, coding->produced, stdout);
1136 if (ferror (stdout))
1137 clearerr (stdout);
1138 if (termscript)
1139 fwrite (conversion_buffer, 1, coding->produced, termscript);
1140 UNBLOCK_INPUT;
1141 }
1142
1143 /* Turn appearance modes off. */
1144 turn_off_face (f, face_id);
1145 turn_off_highlight ();
1076 1146
1077 cmcheckmagic (); 1147 cmcheckmagic ();
1078 } 1148 }
1079 1149
1080 /* If start is zero, insert blanks instead of a string at start */ 1150 /* If start is zero, insert blanks instead of a string at start */
2419 2489
2420 #endif /* !WINDOWSNT */ 2490 #endif /* !WINDOWSNT */
2421 2491
2422 2492
2423 /*********************************************************************** 2493 /***********************************************************************
2494 Mouse
2495 ***********************************************************************/
2496
2497 #ifdef HAVE_GPM
2498 static void
2499 term_show_mouse_face (enum draw_glyphs_face draw)
2500 {
2501 struct window *w = XWINDOW (mouse_face_window);
2502 int save_x, save_y;
2503 int i, j;
2504
2505 if (/* If window is in the process of being destroyed, don't bother
2506 to do anything. */
2507 w->current_matrix != NULL
2508 /* Recognize when we are called to operate on rows that don't exist
2509 anymore. This can happen when a window is split. */
2510 && mouse_face_end_row < w->current_matrix->nrows)
2511 {
2512 /* write_glyphs writes at cursor position, so we need to
2513 temporarily move cursor coordinates to the beginning of
2514 the highlight region. */
2515
2516 /* Save current cursor co-ordinates */
2517 save_y = curY;
2518 save_x = curX;
2519
2520 /* Note that mouse_face_beg_row etc. are window relative. */
2521 for (i = mouse_face_beg_row; i <= mouse_face_end_row; i++)
2522 {
2523 int start_hpos, end_hpos, nglyphs;
2524 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
2525
2526 /* Don't do anything if row doesn't have valid contents. */
2527 if (!row->enabled_p)
2528 continue;
2529
2530 /* For all but the first row, the highlight starts at column 0. */
2531 if (i == mouse_face_beg_row)
2532 start_hpos = mouse_face_beg_col;
2533 else
2534 start_hpos = 0;
2535
2536 if (i == mouse_face_end_row)
2537 end_hpos = mouse_face_end_col;
2538 else
2539 {
2540 end_hpos = row->used[TEXT_AREA];
2541 if (draw == DRAW_NORMAL_TEXT)
2542 row->fill_line_p = 1; /* Clear to end of line */
2543 }
2544
2545 if (end_hpos <= start_hpos)
2546 continue;
2547 /* Record that some glyphs of this row are displayed in
2548 mouse-face. */
2549 row->mouse_face_p = draw > 0;
2550
2551 nglyphs = end_hpos - start_hpos;
2552
2553 if (end_hpos >= row->used[TEXT_AREA])
2554 nglyphs = row->used[TEXT_AREA] - start_hpos;
2555
2556 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2557 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos
2558 + WINDOW_LEFT_EDGE_X (w);
2559
2560 cursor_to (pos_y, pos_x);
2561
2562 if (draw == DRAW_MOUSE_FACE)
2563 {
2564 write_glyphs_with_face (row->glyphs[TEXT_AREA] + start_hpos,
2565 nglyphs, mouse_face_face_id);
2566 }
2567 else /* draw == DRAW_NORMAL_TEXT */
2568 write_glyphs (row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2569 }
2570 cursor_to (save_y, save_x);
2571 }
2572 }
2573
2574 static void
2575 term_clear_mouse_face ()
2576 {
2577 if (!NILP (mouse_face_window))
2578 term_show_mouse_face (DRAW_NORMAL_TEXT);
2579
2580 mouse_face_beg_row = mouse_face_beg_col = -1;
2581 mouse_face_end_row = mouse_face_end_col = -1;
2582 mouse_face_window = Qnil;
2583 }
2584
2585 /* Find the glyph matrix position of buffer position POS in window W.
2586 *HPOS and *VPOS are set to the positions found. W's current glyphs
2587 must be up to date. If POS is above window start return (0, 0).
2588 If POS is after end of W, return end of last line in W.
2589 - taken from msdos.c */
2590 static int
2591 fast_find_position (struct window *w, int pos, int *hpos, int *vpos)
2592 {
2593 int i, lastcol, line_start_position, maybe_next_line_p = 0;
2594 int yb = window_text_bottom_y (w);
2595 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0), *best_row = row;
2596
2597 while (row->y < yb)
2598 {
2599 if (row->used[TEXT_AREA])
2600 line_start_position = row->glyphs[TEXT_AREA]->charpos;
2601 else
2602 line_start_position = 0;
2603
2604 if (line_start_position > pos)
2605 break;
2606 /* If the position sought is the end of the buffer,
2607 don't include the blank lines at the bottom of the window. */
2608 else if (line_start_position == pos
2609 && pos == BUF_ZV (XBUFFER (w->buffer)))
2610 {
2611 maybe_next_line_p = 1;
2612 break;
2613 }
2614 else if (line_start_position > 0)
2615 best_row = row;
2616
2617 /* Don't overstep the last matrix row, lest we get into the
2618 never-never land... */
2619 if (row->y + 1 >= yb)
2620 break;
2621
2622 ++row;
2623 }
2624
2625 /* Find the right column within BEST_ROW. */
2626 lastcol = 0;
2627 row = best_row;
2628 for (i = 0; i < row->used[TEXT_AREA]; i++)
2629 {
2630 struct glyph *glyph = row->glyphs[TEXT_AREA] + i;
2631 int charpos;
2632
2633 charpos = glyph->charpos;
2634 if (charpos == pos)
2635 {
2636 *hpos = i;
2637 *vpos = row->y;
2638 return 1;
2639 }
2640 else if (charpos > pos)
2641 break;
2642 else if (charpos > 0)
2643 lastcol = i;
2644 }
2645
2646 /* If we're looking for the end of the buffer,
2647 and we didn't find it in the line we scanned,
2648 use the start of the following line. */
2649 if (maybe_next_line_p)
2650 {
2651 ++row;
2652 lastcol = 0;
2653 }
2654
2655 *vpos = row->y;
2656 *hpos = lastcol + 1;
2657 return 0;
2658 }
2659
2660 static void
2661 term_mouse_highlight (struct frame *f, int x, int y)
2662 {
2663 enum window_part part;
2664 Lisp_Object window;
2665 struct window *w;
2666 struct buffer *b;
2667
2668 if (NILP (Vmouse_highlight)
2669 || !f->glyphs_initialized_p)
2670 return;
2671
2672 mouse_face_mouse_x = x;
2673 mouse_face_mouse_y = y;
2674 mouse_face_mouse_frame = f;
2675
2676 /* Which window is that in? */
2677 window = window_from_coordinates (f, x, y, &part, &x, &y, 0);
2678
2679 /* Not on a window -> return. */
2680 if (!WINDOWP (window))
2681 return;
2682
2683 if (!EQ (window, mouse_face_window))
2684 term_clear_mouse_face ();
2685
2686 w = XWINDOW (window);
2687
2688 /* Are we in a window whose display is up to date?
2689 And verify the buffer's text has not changed. */
2690 b = XBUFFER (w->buffer);
2691 if (part == ON_TEXT
2692 && EQ (w->window_end_valid, w->buffer)
2693 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
2694 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
2695 {
2696 int pos, i, nrows = w->current_matrix->nrows;
2697 struct glyph_row *row;
2698 struct glyph *glyph;
2699
2700 /* Find the glyph under X/Y. */
2701 glyph = NULL;
2702 if (y >= 0 && y < nrows)
2703 {
2704 row = MATRIX_ROW (w->current_matrix, y);
2705 /* Give up if some row before the one we are looking for is
2706 not enabled. */
2707 for (i = 0; i <= y; i++)
2708 if (!MATRIX_ROW (w->current_matrix, i)->enabled_p)
2709 break;
2710 if (i > y /* all rows upto and including the one at Y are enabled */
2711 && row->displays_text_p
2712 && x < window_box_width (w, TEXT_AREA))
2713 {
2714 glyph = row->glyphs[TEXT_AREA];
2715 if (x >= row->used[TEXT_AREA])
2716 glyph = NULL;
2717 else
2718 {
2719 glyph += x;
2720 if (!BUFFERP (glyph->object))
2721 glyph = NULL;
2722 }
2723 }
2724 }
2725
2726 /* Clear mouse face if X/Y not over text. */
2727 if (glyph == NULL)
2728 {
2729 term_clear_mouse_face ();
2730 return;
2731 }
2732
2733 if (!BUFFERP (glyph->object))
2734 abort ();
2735 pos = glyph->charpos;
2736
2737 /* Check for mouse-face. */
2738 {
2739 extern Lisp_Object Qmouse_face;
2740 Lisp_Object mouse_face, overlay, position, *overlay_vec;
2741 int noverlays, obegv, ozv;;
2742 struct buffer *obuf;
2743
2744 /* If we get an out-of-range value, return now; avoid an error. */
2745 if (pos > BUF_Z (b))
2746 return;
2747
2748 /* Make the window's buffer temporarily current for
2749 overlays_at and compute_char_face. */
2750 obuf = current_buffer;
2751 current_buffer = b;
2752 obegv = BEGV;
2753 ozv = ZV;
2754 BEGV = BEG;
2755 ZV = Z;
2756
2757 /* Is this char mouse-active? */
2758 XSETINT (position, pos);
2759
2760 /* Put all the overlays we want in a vector in overlay_vec. */
2761 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, 0);
2762 /* Sort overlays into increasing priority order. */
2763 noverlays = sort_overlays (overlay_vec, noverlays, w);
2764
2765 /* Check mouse-face highlighting. */
2766 if (!(EQ (window, mouse_face_window)
2767 && y >= mouse_face_beg_row
2768 && y <= mouse_face_end_row
2769 && (y > mouse_face_beg_row
2770 || x >= mouse_face_beg_col)
2771 && (y < mouse_face_end_row
2772 || x < mouse_face_end_col
2773 || mouse_face_past_end)))
2774 {
2775 /* Clear the display of the old active region, if any. */
2776 term_clear_mouse_face ();
2777
2778 /* Find the highest priority overlay that has a mouse-face
2779 property. */
2780 overlay = Qnil;
2781 for (i = noverlays - 1; i >= 0; --i)
2782 {
2783 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
2784 if (!NILP (mouse_face))
2785 {
2786 overlay = overlay_vec[i];
2787 break;
2788 }
2789 }
2790
2791 /* If no overlay applies, get a text property. */
2792 if (NILP (overlay))
2793 mouse_face = Fget_text_property (position, Qmouse_face,
2794 w->buffer);
2795
2796 /* Handle the overlay case. */
2797 if (!NILP (overlay))
2798 {
2799 /* Find the range of text around this char that
2800 should be active. */
2801 Lisp_Object before, after;
2802 int ignore;
2803
2804
2805 before = Foverlay_start (overlay);
2806 after = Foverlay_end (overlay);
2807 /* Record this as the current active region. */
2808 fast_find_position (w, XFASTINT (before),
2809 &mouse_face_beg_col,
2810 &mouse_face_beg_row);
2811
2812 mouse_face_past_end
2813 = !fast_find_position (w, XFASTINT (after),
2814 &mouse_face_end_col,
2815 &mouse_face_end_row);
2816 mouse_face_window = window;
2817
2818 mouse_face_face_id
2819 = face_at_buffer_position (w, pos, 0, 0,
2820 &ignore, pos + 1, 1);
2821
2822 /* Display it as active. */
2823 term_show_mouse_face (DRAW_MOUSE_FACE);
2824 }
2825 /* Handle the text property case. */
2826 else if (!NILP (mouse_face))
2827 {
2828 /* Find the range of text around this char that
2829 should be active. */
2830 Lisp_Object before, after, beginning, end;
2831 int ignore;
2832
2833 beginning = Fmarker_position (w->start);
2834 XSETINT (end, (BUF_Z (b) - XFASTINT (w->window_end_pos)));
2835 before
2836 = Fprevious_single_property_change (make_number (pos + 1),
2837 Qmouse_face,
2838 w->buffer, beginning);
2839 after
2840 = Fnext_single_property_change (position, Qmouse_face,
2841 w->buffer, end);
2842
2843 /* Record this as the current active region. */
2844 fast_find_position (w, XFASTINT (before),
2845 &mouse_face_beg_col,
2846 &mouse_face_beg_row);
2847 mouse_face_past_end
2848 = !fast_find_position (w, XFASTINT (after),
2849 &mouse_face_end_col,
2850 &mouse_face_end_row);
2851 mouse_face_window = window;
2852
2853 mouse_face_face_id
2854 = face_at_buffer_position (w, pos, 0, 0,
2855 &ignore, pos + 1, 1);
2856
2857 /* Display it as active. */
2858 term_show_mouse_face (DRAW_MOUSE_FACE);
2859 }
2860 }
2861
2862 /* Look for a `help-echo' property. */
2863 {
2864 Lisp_Object help;
2865 extern Lisp_Object Qhelp_echo;
2866
2867 /* Check overlays first. */
2868 help = Qnil;
2869 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
2870 {
2871 overlay = overlay_vec[i];
2872 help = Foverlay_get (overlay, Qhelp_echo);
2873 }
2874
2875 if (!NILP (help))
2876 {
2877 help_echo_string = help;
2878 help_echo_window = window;
2879 help_echo_object = overlay;
2880 help_echo_pos = pos;
2881 }
2882 /* Try text properties. */
2883 else if (NILP (help)
2884 && ((STRINGP (glyph->object)
2885 && glyph->charpos >= 0
2886 && glyph->charpos < SCHARS (glyph->object))
2887 || (BUFFERP (glyph->object)
2888 && glyph->charpos >= BEGV
2889 && glyph->charpos < ZV)))
2890 {
2891 help = Fget_text_property (make_number (glyph->charpos),
2892 Qhelp_echo, glyph->object);
2893 if (!NILP (help))
2894 {
2895 help_echo_string = help;
2896 help_echo_window = window;
2897 help_echo_object = glyph->object;
2898 help_echo_pos = glyph->charpos;
2899 }
2900 }
2901 }
2902
2903 BEGV = obegv;
2904 ZV = ozv;
2905 current_buffer = obuf;
2906 }
2907 }
2908 }
2909
2910 static int
2911 term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2912 {
2913 /* Has the mouse moved off the glyph it was on at the last sighting? */
2914 if (event->x != last_mouse_x || event->y != last_mouse_y)
2915 {
2916 frame->mouse_moved = 1;
2917 term_mouse_highlight (frame, event->x - 1, event->y - 1);
2918 /* Remember which glyph we're now on. */
2919 last_mouse_x = event->x;
2920 last_mouse_y = event->y;
2921 return 1;
2922 }
2923 return 0;
2924 }
2925
2926 /* Return the current position of the mouse.
2927
2928 Set *f to the frame the mouse is in, or zero if the mouse is in no
2929 Emacs frame. If it is set to zero, all the other arguments are
2930 garbage.
2931
2932 Set *bar_window to Qnil, and *x and *y to the column and
2933 row of the character cell the mouse is over.
2934
2935 Set *time to the time the mouse was at the returned position.
2936
2937 This should clear mouse_moved until the next motion
2938 event arrives.
2939
2940 NOT CURRENTLY INVOKED: see mouse_position_hook below. */
2941 static void
2942 term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
2943 enum scroll_bar_part *part, Lisp_Object *x,
2944 Lisp_Object *y, unsigned long *time)
2945 {
2946 Gpm_Event event;
2947 struct timeval now;
2948 int i;
2949
2950 BLOCK_INPUT;
2951
2952 *fp = SELECTED_FRAME ();
2953
2954 *bar_window = Qnil;
2955 *part = 0;
2956
2957 i = Gpm_GetSnapshot (&event);
2958
2959 XSETINT (*x, event.x);
2960 XSETINT (*y, event.y);
2961 gettimeofday(&now, 0);
2962 *time = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2963
2964 UNBLOCK_INPUT;
2965 }
2966
2967 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2968
2969 If the event is a button press, then note that we have grabbed
2970 the mouse. */
2971
2972 static Lisp_Object
2973 term_mouse_click (struct input_event *result, Gpm_Event *event,
2974 struct frame *f)
2975 {
2976 struct timeval now;
2977 int i, j;
2978
2979 result->kind = GPM_CLICK_EVENT;
2980 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
2981 {
2982 if (event->buttons & j) {
2983 result->code = i; /* button number */
2984 break;
2985 }
2986 }
2987 gettimeofday(&now, 0);
2988 result->timestamp = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2989
2990 if (event->type & GPM_UP)
2991 result->modifiers = up_modifier;
2992 else if (event->type & GPM_DOWN)
2993 result->modifiers = down_modifier;
2994 else
2995 result->modifiers = 0;
2996
2997 if (event->type & GPM_SINGLE)
2998 result->modifiers |= click_modifier;
2999
3000 if (event->type & GPM_DOUBLE)
3001 result->modifiers |= double_modifier;
3002
3003 if (event->type & GPM_TRIPLE)
3004 result->modifiers |= triple_modifier;
3005
3006 if (event->type & GPM_DRAG)
3007 result->modifiers |= drag_modifier;
3008
3009 if (!(event->type & (GPM_MOVE|GPM_DRAG))) {
3010
3011 /* 1 << KG_SHIFT */
3012 if (event->modifiers & (1 << 0))
3013 result->modifiers |= shift_modifier;
3014
3015 /* 1 << KG_CTRL */
3016 if (event->modifiers & (1 << 2))
3017 result->modifiers |= ctrl_modifier;
3018
3019 /* 1 << KG_ALT || KG_ALTGR */
3020 if (event->modifiers & (1 << 3)
3021 || event->modifiers & (1 << 1))
3022 result->modifiers |= meta_modifier;
3023 }
3024
3025 XSETINT (result->x, event->x - 1);
3026 XSETINT (result->y, event->y - 1);
3027 XSETFRAME (result->frame_or_window, f);
3028 result->arg = Qnil;
3029 return Qnil;
3030 }
3031
3032 int
3033 handle_one_term_event (Gpm_Event *event, struct input_event* hold_quit)
3034 {
3035 struct frame *f = SELECTED_FRAME ();
3036 int i, j, fd;
3037 struct input_event ie;
3038 int do_help = 0;
3039 int count = 0;
3040
3041 EVENT_INIT (ie);
3042 ie.kind = NO_EVENT;
3043 ie.arg = Qnil;
3044
3045 if (event->type & GPM_MOVE) {
3046 unsigned char buf[6 * sizeof (short)];
3047 unsigned short *arg = (unsigned short *) buf + 1;
3048 const char *name;
3049
3050 previous_help_echo_string = help_echo_string;
3051 help_echo_string = Qnil;
3052
3053 /* Display mouse pointer */
3054 buf[sizeof(short) - 1] = 2; /* set selection */
3055
3056 arg[0] = arg[2] = (unsigned short) event->x;
3057 arg[1] = arg[3] = (unsigned short) event->y;
3058 arg[4] = (unsigned short) 3;
3059
3060 name = (const char *) ttyname (0);
3061 fd = open (name, O_WRONLY);
3062 ioctl (fd, TIOCLINUX, buf + sizeof (short) - 1);
3063 close(fd);
3064
3065 term_mouse_movement (f, event);
3066
3067 /* If the contents of the global variable help_echo_string
3068 has changed, generate a HELP_EVENT. */
3069 if (!NILP (help_echo_string)
3070 || !NILP (previous_help_echo_string))
3071 do_help = 1;
3072
3073 goto done;
3074 }
3075 else {
3076 f->mouse_moved = 0;
3077 term_mouse_click (&ie, event, f);
3078 //kbd_buffer_store_event_hold (&ie, hold_quit);
3079 }
3080
3081 done:
3082 if (ie.kind != NO_EVENT)
3083 {
3084 kbd_buffer_store_event_hold (&ie, hold_quit);
3085 count++;
3086 }
3087
3088 if (do_help
3089 && !(hold_quit && hold_quit->kind != NO_EVENT))
3090 {
3091 Lisp_Object frame;
3092
3093 if (f)
3094 XSETFRAME (frame, f);
3095 else
3096 frame = Qnil;
3097
3098 gen_help_event (help_echo_string, frame, help_echo_window,
3099 help_echo_object, help_echo_pos);
3100 count++;
3101 }
3102
3103 return count;
3104 }
3105
3106 DEFUN ("term-open-connection", Fterm_open_connection, Sterm_open_connection,
3107 0, 0, 0,
3108 doc: /* Open a connection to Gpm. */)
3109 ()
3110 {
3111 Gpm_Connect connection;
3112
3113 connection.eventMask = ~0;
3114 connection.defaultMask = ~GPM_HARD;
3115 connection.maxMod = ~0;
3116 connection.minMod = 0;
3117
3118 if (Gpm_Open (&connection, 0) < 0)
3119 return Qnil;
3120 else
3121 {
3122 term_gpm = 1;
3123 reset_sys_modes ();
3124 init_sys_modes ();
3125 add_gpm_wait_descriptor (gpm_fd);
3126 return Qt;
3127 }
3128 }
3129
3130 DEFUN ("term-close-connection", Fterm_close_connection, Sterm_close_connection,
3131 0, 0, 0,
3132 doc: /* Close a connection to Gpm. */)
3133 ()
3134 {
3135 delete_gpm_wait_descriptor (gpm_fd);
3136 while (Gpm_Close()); /* close all the stack */
3137 term_gpm = 0;
3138 return Qnil;
3139 }
3140 #endif /* HAVE_GPM */
3141
3142
3143 /***********************************************************************
2424 Initialization 3144 Initialization
2425 ***********************************************************************/ 3145 ***********************************************************************/
2426 3146
2427 void 3147 void
2428 term_init (terminal_type) 3148 term_init (terminal_type)
2436 int status; 3156 int status;
2437 struct frame *sf = XFRAME (selected_frame); 3157 struct frame *sf = XFRAME (selected_frame);
2438 3158
2439 encode_terminal_src_size = 0; 3159 encode_terminal_src_size = 0;
2440 encode_terminal_dst_size = 0; 3160 encode_terminal_dst_size = 0;
3161
3162 #ifdef HAVE_GPM
3163 /* TODO: Can't get Gpm_Snapshot in term_mouse_position to work: test with
3164 (mouse-position). Also set-mouse-position won't work as is. */
3165 /* mouse_position_hook = term_mouse_position; */
3166
3167 mouse_face_window = Qnil;
3168 #endif
2441 3169
2442 #ifdef WINDOWSNT 3170 #ifdef WINDOWSNT
2443 initialize_w32_display (); 3171 initialize_w32_display ();
2444 3172
2445 Wcm_clear (); 3173 Wcm_clear ();
2884 visible_cursor = 1; 3612 visible_cursor = 1;
2885 3613
2886 defsubr (&Stty_display_color_p); 3614 defsubr (&Stty_display_color_p);
2887 defsubr (&Stty_display_color_cells); 3615 defsubr (&Stty_display_color_cells);
2888 defsubr (&Stty_no_underline); 3616 defsubr (&Stty_no_underline);
3617 #ifdef HAVE_GPM
3618 defsubr (&Sterm_open_connection);
3619 defsubr (&Sterm_close_connection);
3620 #endif /* HAVE_GPM */
2889 3621
2890 fullscreen_hook = NULL; 3622 fullscreen_hook = NULL;
2891 } 3623 }
2892 3624
2893 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193 3625 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193