Mercurial > emacs
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 |