diff options
| author | Miles Bader | 2007-05-24 21:31:10 +0000 |
|---|---|---|
| committer | Miles Bader | 2007-05-24 21:31:10 +0000 |
| commit | 262be72a9aaa800d38cd25b12acb8c9b7b21d5d6 (patch) | |
| tree | 0940ebc7acd6379243e7194446acbd4f062be4f3 /src/term.c | |
| parent | 5e1d0c0a38c22adc02d1b77bdc1d620fab26e52d (diff) | |
| parent | a02a3c235e3ec24acaf2014e6c60c0b4138ff86f (diff) | |
| download | emacs-262be72a9aaa800d38cd25b12acb8c9b7b21d5d6.tar.gz emacs-262be72a9aaa800d38cd25b12acb8c9b7b21d5d6.zip | |
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
Diffstat (limited to 'src/term.c')
| -rw-r--r-- | src/term.c | 770 |
1 files changed, 751 insertions, 19 deletions
diff --git a/src/term.c b/src/term.c index 1fcda1abb77..6df6ef08918 100644 --- a/src/term.c +++ b/src/term.c | |||
| @@ -147,25 +147,6 @@ 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 | 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 | |||
| 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, |
| @@ -416,6 +397,9 @@ static int tty_cursor_hidden; | |||
| 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 |
| @@ -429,6 +413,33 @@ extern char *tgetstr (); | |||
| 429 | #define FRAME_TERMCAP_P(_f_) 0 | 413 | #define FRAME_TERMCAP_P(_f_) 0 |
| 430 | #endif /* WINDOWSNT */ | 414 | #endif /* WINDOWSNT */ |
| 431 | 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 */ | ||
| 442 | |||
| 432 | void | 443 | void |
| 433 | ring_bell () | 444 | ring_bell () |
| 434 | { | 445 | { |
| @@ -1077,6 +1088,65 @@ write_glyphs (string, len) | |||
| 1077 | cmcheckmagic (); | 1088 | cmcheckmagic (); |
| 1078 | } | 1089 | } |
| 1079 | 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 (); | ||
| 1146 | |||
| 1147 | cmcheckmagic (); | ||
| 1148 | } | ||
| 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 */ |
| 1081 | 1151 | ||
| 1082 | void | 1152 | void |
| @@ -2421,6 +2491,656 @@ set_tty_color_mode (f, val) | |||
| 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 | ||
| @@ -2439,6 +3159,14 @@ term_init (terminal_type) | |||
| 2439 | encode_terminal_src_size = 0; | 3159 | encode_terminal_src_size = 0; |
| 2440 | encode_terminal_dst_size = 0; | 3160 | encode_terminal_dst_size = 0; |
| 2441 | 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 | ||
| 3169 | |||
| 2442 | #ifdef WINDOWSNT | 3170 | #ifdef WINDOWSNT |
| 2443 | initialize_w32_display (); | 3171 | initialize_w32_display (); |
| 2444 | 3172 | ||
| @@ -2886,6 +3614,10 @@ bigger, or it may make it blink, or it may do nothing at all. */); | |||
| 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 | } |