aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNick Roberts2007-05-20 02:27:53 +0000
committerNick Roberts2007-05-20 02:27:53 +0000
commite882229cca36a3c24031e18fe44be1865f282659 (patch)
treee4368d0c6bf62b3d78106b3fd622a13c31eab4dd /src
parent60889ffab9383f2972e59eaebe4d60d91a92ad90 (diff)
downloademacs-e882229cca36a3c24031e18fe44be1865f282659.tar.gz
emacs-e882229cca36a3c24031e18fe44be1865f282659.zip
(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.
Diffstat (limited to 'src')
-rw-r--r--src/term.c770
1 files changed, 751 insertions, 19 deletions
diff --git a/src/term.c b/src/term.c
index 556ae9f65b1..5422d29efb9 100644
--- a/src/term.c
+++ b/src/term.c
@@ -144,25 +144,6 @@ int (*read_socket_hook) P_ ((int, int, struct input_event *));
144 144
145void (*frame_up_to_date_hook) P_ ((struct frame *)); 145void (*frame_up_to_date_hook) P_ ((struct frame *));
146 146
147/* Return the current position of the mouse.
148
149 Set *f to the frame the mouse is in, or zero if the mouse is in no
150 Emacs frame. If it is set to zero, all the other arguments are
151 garbage.
152
153 If the motion started in a scroll bar, set *bar_window to the
154 scroll bar's window, *part to the part the mouse is currently over,
155 *x to the position of the mouse along the scroll bar, and *y to the
156 overall length of the scroll bar.
157
158 Otherwise, set *bar_window to Qnil, and *x and *y to the column and
159 row of the character cell the mouse is over.
160
161 Set *time to the time the mouse was at the returned position.
162
163 This should clear mouse_moved until the next motion
164 event arrives. */
165
166void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist, 147void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist,
167 Lisp_Object *bar_window, 148 Lisp_Object *bar_window,
168 enum scroll_bar_part *part, 149 enum scroll_bar_part *part,
@@ -413,6 +394,9 @@ static int tty_cursor_hidden;
413char *tparam (); 394char *tparam ();
414 395
415extern char *tgetstr (); 396extern char *tgetstr ();
397
398static void term_clear_mouse_face ();
399static void term_mouse_highlight (struct frame *f, int x, int y);
416 400
417 401
418#ifdef WINDOWSNT 402#ifdef WINDOWSNT
@@ -426,6 +410,33 @@ extern char *tgetstr ();
426#define FRAME_TERMCAP_P(_f_) 0 410#define FRAME_TERMCAP_P(_f_) 0
427#endif /* WINDOWSNT */ 411#endif /* WINDOWSNT */
428 412
413#ifdef HAVE_GPM_H
414#include <sys/fcntl.h>
415#include "buffer.h"
416
417/* Nonzero means mouse is enabled on Linux console. */
418int term_gpm = 0;
419
420/* These variables describe the range of text currently shown in its
421 mouse-face, together with the window they apply to. As long as
422 the mouse stays within this range, we need not redraw anything on
423 its account. Rows and columns are glyph matrix positions in
424 MOUSE_FACE_WINDOW. */
425static int mouse_face_beg_row, mouse_face_beg_col;
426static int mouse_face_end_row, mouse_face_end_col;
427static int mouse_face_past_end;
428static Lisp_Object mouse_face_window;
429static int mouse_face_face_id;
430
431/* FRAME and X, Y position of mouse when last checked for
432 highlighting. X and Y can be negative or out of range for the frame. */
433struct frame *mouse_face_mouse_frame;
434int mouse_face_mouse_x, mouse_face_mouse_y;
435
436static int pos_x, pos_y;
437static int last_mouse_x, last_mouse_y;
438#endif /* HAVE_GPM_H */
439
429void 440void
430ring_bell () 441ring_bell ()
431{ 442{
@@ -1010,6 +1021,65 @@ write_glyphs (string, len)
1010 cmcheckmagic (); 1021 cmcheckmagic ();
1011} 1022}
1012 1023
1024void
1025write_glyphs_with_face (string, len, face_id)
1026 register struct glyph *string;
1027 register int len, face_id;
1028{
1029 struct frame *sf = XFRAME (selected_frame);
1030 struct frame *f = updating_frame ? updating_frame : sf;
1031 unsigned char *conversion_buffer;
1032 struct coding_system *coding;
1033
1034 turn_off_insert ();
1035 tty_hide_cursor ();
1036
1037 /* Don't dare write in last column of bottom line, if Auto-Wrap,
1038 since that would scroll the whole frame on some terminals. */
1039
1040 if (AutoWrap
1041 && curY + 1 == FRAME_LINES (sf)
1042 && (curX + len) == FRAME_COLS (sf))
1043 len --;
1044 if (len <= 0)
1045 return;
1046
1047 cmplus (len);
1048
1049 /* If terminal_coding does any conversion, use it, otherwise use
1050 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
1051 because it always return 1 if the member src_multibyte is 1. */
1052 coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
1053 ? &terminal_coding : &safe_terminal_coding);
1054 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
1055 the tail. */
1056 coding->mode &= ~CODING_MODE_LAST_BLOCK;
1057
1058
1059 /* Turn appearance modes of the face. */
1060 highlight_if_desired ();
1061 turn_on_face (f, face_id);
1062
1063 coding->mode |= CODING_MODE_LAST_BLOCK;
1064 conversion_buffer = encode_terminal_code (string, len, coding);
1065 if (coding->produced > 0)
1066 {
1067 BLOCK_INPUT;
1068 fwrite (conversion_buffer, 1, coding->produced, stdout);
1069 if (ferror (stdout))
1070 clearerr (stdout);
1071 if (termscript)
1072 fwrite (conversion_buffer, 1, coding->produced, termscript);
1073 UNBLOCK_INPUT;
1074 }
1075
1076 /* Turn appearance modes off. */
1077 turn_off_face (f, face_id);
1078 turn_off_highlight ();
1079
1080 cmcheckmagic ();
1081}
1082
1013/* If start is zero, insert blanks instead of a string at start */ 1083/* If start is zero, insert blanks instead of a string at start */
1014 1084
1015void 1085void
@@ -2308,6 +2378,656 @@ set_tty_color_mode (f, val)
2308 2378
2309 2379
2310/*********************************************************************** 2380/***********************************************************************
2381 Mouse
2382 ***********************************************************************/
2383
2384#ifdef HAVE_GPM_H
2385static void
2386term_show_mouse_face (enum draw_glyphs_face draw)
2387{
2388 struct window *w = XWINDOW (mouse_face_window);
2389 int save_x, save_y;
2390 int i, j;
2391
2392 if (/* If window is in the process of being destroyed, don't bother
2393 to do anything. */
2394 w->current_matrix != NULL
2395 /* Recognize when we are called to operate on rows that don't exist
2396 anymore. This can happen when a window is split. */
2397 && mouse_face_end_row < w->current_matrix->nrows)
2398 {
2399 /* write_glyphs writes at cursor position, so we need to
2400 temporarily move cursor coordinates to the beginning of
2401 the highlight region. */
2402
2403 /* Save current cursor co-ordinates */
2404 save_y = curY;
2405 save_x = curX;
2406
2407 /* Note that mouse_face_beg_row etc. are window relative. */
2408 for (i = mouse_face_beg_row; i <= mouse_face_end_row; i++)
2409 {
2410 int start_hpos, end_hpos, nglyphs;
2411 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
2412
2413 /* Don't do anything if row doesn't have valid contents. */
2414 if (!row->enabled_p)
2415 continue;
2416
2417 /* For all but the first row, the highlight starts at column 0. */
2418 if (i == mouse_face_beg_row)
2419 start_hpos = mouse_face_beg_col;
2420 else
2421 start_hpos = 0;
2422
2423 if (i == mouse_face_end_row)
2424 end_hpos = mouse_face_end_col;
2425 else
2426 {
2427 end_hpos = row->used[TEXT_AREA];
2428 if (draw == DRAW_NORMAL_TEXT)
2429 row->fill_line_p = 1; /* Clear to end of line */
2430 }
2431
2432 if (end_hpos <= start_hpos)
2433 continue;
2434 /* Record that some glyphs of this row are displayed in
2435 mouse-face. */
2436 row->mouse_face_p = draw > 0;
2437
2438 nglyphs = end_hpos - start_hpos;
2439
2440 if (end_hpos >= row->used[TEXT_AREA])
2441 nglyphs = row->used[TEXT_AREA] - start_hpos;
2442
2443 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2444 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos
2445 + WINDOW_LEFT_EDGE_X (w);
2446
2447 cursor_to (pos_y, pos_x);
2448
2449 if (draw == DRAW_MOUSE_FACE)
2450 {
2451 write_glyphs_with_face (row->glyphs[TEXT_AREA] + start_hpos,
2452 nglyphs, mouse_face_face_id);
2453 }
2454 else /* draw == DRAW_NORMAL_TEXT */
2455 write_glyphs (row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2456 }
2457 cursor_to (save_y, save_x);
2458 }
2459}
2460
2461static void
2462term_clear_mouse_face ()
2463{
2464 if (!NILP (mouse_face_window))
2465 term_show_mouse_face (DRAW_NORMAL_TEXT);
2466
2467 mouse_face_beg_row = mouse_face_beg_col = -1;
2468 mouse_face_end_row = mouse_face_end_col = -1;
2469 mouse_face_window = Qnil;
2470}
2471
2472/* Find the glyph matrix position of buffer position POS in window W.
2473 *HPOS and *VPOS are set to the positions found. W's current glyphs
2474 must be up to date. If POS is above window start return (0, 0).
2475 If POS is after end of W, return end of last line in W.
2476 - taken from msdos.c */
2477static int
2478fast_find_position (struct window *w, int pos, int *hpos, int *vpos)
2479{
2480 int i, lastcol, line_start_position, maybe_next_line_p = 0;
2481 int yb = window_text_bottom_y (w);
2482 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0), *best_row = row;
2483
2484 while (row->y < yb)
2485 {
2486 if (row->used[TEXT_AREA])
2487 line_start_position = row->glyphs[TEXT_AREA]->charpos;
2488 else
2489 line_start_position = 0;
2490
2491 if (line_start_position > pos)
2492 break;
2493 /* If the position sought is the end of the buffer,
2494 don't include the blank lines at the bottom of the window. */
2495 else if (line_start_position == pos
2496 && pos == BUF_ZV (XBUFFER (w->buffer)))
2497 {
2498 maybe_next_line_p = 1;
2499 break;
2500 }
2501 else if (line_start_position > 0)
2502 best_row = row;
2503
2504 /* Don't overstep the last matrix row, lest we get into the
2505 never-never land... */
2506 if (row->y + 1 >= yb)
2507 break;
2508
2509 ++row;
2510 }
2511
2512 /* Find the right column within BEST_ROW. */
2513 lastcol = 0;
2514 row = best_row;
2515 for (i = 0; i < row->used[TEXT_AREA]; i++)
2516 {
2517 struct glyph *glyph = row->glyphs[TEXT_AREA] + i;
2518 int charpos;
2519
2520 charpos = glyph->charpos;
2521 if (charpos == pos)
2522 {
2523 *hpos = i;
2524 *vpos = row->y;
2525 return 1;
2526 }
2527 else if (charpos > pos)
2528 break;
2529 else if (charpos > 0)
2530 lastcol = i;
2531 }
2532
2533 /* If we're looking for the end of the buffer,
2534 and we didn't find it in the line we scanned,
2535 use the start of the following line. */
2536 if (maybe_next_line_p)
2537 {
2538 ++row;
2539 lastcol = 0;
2540 }
2541
2542 *vpos = row->y;
2543 *hpos = lastcol + 1;
2544 return 0;
2545}
2546
2547static void
2548term_mouse_highlight (struct frame *f, int x, int y)
2549{
2550 enum window_part part;
2551 Lisp_Object window;
2552 struct window *w;
2553 struct buffer *b;
2554
2555 if (NILP (Vmouse_highlight)
2556 || !f->glyphs_initialized_p)
2557 return;
2558
2559 mouse_face_mouse_x = x;
2560 mouse_face_mouse_y = y;
2561 mouse_face_mouse_frame = f;
2562
2563 /* Which window is that in? */
2564 window = window_from_coordinates (f, x, y, &part, &x, &y, 0);
2565
2566 /* Not on a window -> return. */
2567 if (!WINDOWP (window))
2568 return;
2569
2570 if (!EQ (window, mouse_face_window))
2571 term_clear_mouse_face ();
2572
2573 w = XWINDOW (window);
2574
2575 /* Are we in a window whose display is up to date?
2576 And verify the buffer's text has not changed. */
2577 b = XBUFFER (w->buffer);
2578 if (part == ON_TEXT
2579 && EQ (w->window_end_valid, w->buffer)
2580 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
2581 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
2582 {
2583 int pos, i, nrows = w->current_matrix->nrows;
2584 struct glyph_row *row;
2585 struct glyph *glyph;
2586
2587 /* Find the glyph under X/Y. */
2588 glyph = NULL;
2589 if (y >= 0 && y < nrows)
2590 {
2591 row = MATRIX_ROW (w->current_matrix, y);
2592 /* Give up if some row before the one we are looking for is
2593 not enabled. */
2594 for (i = 0; i <= y; i++)
2595 if (!MATRIX_ROW (w->current_matrix, i)->enabled_p)
2596 break;
2597 if (i > y /* all rows upto and including the one at Y are enabled */
2598 && row->displays_text_p
2599 && x < window_box_width (w, TEXT_AREA))
2600 {
2601 glyph = row->glyphs[TEXT_AREA];
2602 if (x >= row->used[TEXT_AREA])
2603 glyph = NULL;
2604 else
2605 {
2606 glyph += x;
2607 if (!BUFFERP (glyph->object))
2608 glyph = NULL;
2609 }
2610 }
2611 }
2612
2613 /* Clear mouse face if X/Y not over text. */
2614 if (glyph == NULL)
2615 {
2616 term_clear_mouse_face ();
2617 return;
2618 }
2619
2620 if (!BUFFERP (glyph->object))
2621 abort ();
2622 pos = glyph->charpos;
2623
2624 /* Check for mouse-face. */
2625 {
2626 extern Lisp_Object Qmouse_face;
2627 Lisp_Object mouse_face, overlay, position, *overlay_vec;
2628 int noverlays, obegv, ozv;;
2629 struct buffer *obuf;
2630
2631 /* If we get an out-of-range value, return now; avoid an error. */
2632 if (pos > BUF_Z (b))
2633 return;
2634
2635 /* Make the window's buffer temporarily current for
2636 overlays_at and compute_char_face. */
2637 obuf = current_buffer;
2638 current_buffer = b;
2639 obegv = BEGV;
2640 ozv = ZV;
2641 BEGV = BEG;
2642 ZV = Z;
2643
2644 /* Is this char mouse-active? */
2645 XSETINT (position, pos);
2646
2647 /* Put all the overlays we want in a vector in overlay_vec. */
2648 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, 0);
2649 /* Sort overlays into increasing priority order. */
2650 noverlays = sort_overlays (overlay_vec, noverlays, w);
2651
2652 /* Check mouse-face highlighting. */
2653 if (!(EQ (window, mouse_face_window)
2654 && y >= mouse_face_beg_row
2655 && y <= mouse_face_end_row
2656 && (y > mouse_face_beg_row
2657 || x >= mouse_face_beg_col)
2658 && (y < mouse_face_end_row
2659 || x < mouse_face_end_col
2660 || mouse_face_past_end)))
2661 {
2662 /* Clear the display of the old active region, if any. */
2663 term_clear_mouse_face ();
2664
2665 /* Find the highest priority overlay that has a mouse-face
2666 property. */
2667 overlay = Qnil;
2668 for (i = noverlays - 1; i >= 0; --i)
2669 {
2670 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
2671 if (!NILP (mouse_face))
2672 {
2673 overlay = overlay_vec[i];
2674 break;
2675 }
2676 }
2677
2678 /* If no overlay applies, get a text property. */
2679 if (NILP (overlay))
2680 mouse_face = Fget_text_property (position, Qmouse_face,
2681 w->buffer);
2682
2683 /* Handle the overlay case. */
2684 if (!NILP (overlay))
2685 {
2686 /* Find the range of text around this char that
2687 should be active. */
2688 Lisp_Object before, after;
2689 int ignore;
2690
2691
2692 before = Foverlay_start (overlay);
2693 after = Foverlay_end (overlay);
2694 /* Record this as the current active region. */
2695 fast_find_position (w, XFASTINT (before),
2696 &mouse_face_beg_col,
2697 &mouse_face_beg_row);
2698
2699 mouse_face_past_end
2700 = !fast_find_position (w, XFASTINT (after),
2701 &mouse_face_end_col,
2702 &mouse_face_end_row);
2703 mouse_face_window = window;
2704
2705 mouse_face_face_id
2706 = face_at_buffer_position (w, pos, 0, 0,
2707 &ignore, pos + 1, 1);
2708
2709 /* Display it as active. */
2710 term_show_mouse_face (DRAW_MOUSE_FACE);
2711 }
2712 /* Handle the text property case. */
2713 else if (!NILP (mouse_face))
2714 {
2715 /* Find the range of text around this char that
2716 should be active. */
2717 Lisp_Object before, after, beginning, end;
2718 int ignore;
2719
2720 beginning = Fmarker_position (w->start);
2721 XSETINT (end, (BUF_Z (b) - XFASTINT (w->window_end_pos)));
2722 before
2723 = Fprevious_single_property_change (make_number (pos + 1),
2724 Qmouse_face,
2725 w->buffer, beginning);
2726 after
2727 = Fnext_single_property_change (position, Qmouse_face,
2728 w->buffer, end);
2729
2730 /* Record this as the current active region. */
2731 fast_find_position (w, XFASTINT (before),
2732 &mouse_face_beg_col,
2733 &mouse_face_beg_row);
2734 mouse_face_past_end
2735 = !fast_find_position (w, XFASTINT (after),
2736 &mouse_face_end_col,
2737 &mouse_face_end_row);
2738 mouse_face_window = window;
2739
2740 mouse_face_face_id
2741 = face_at_buffer_position (w, pos, 0, 0,
2742 &ignore, pos + 1, 1);
2743
2744 /* Display it as active. */
2745 term_show_mouse_face (DRAW_MOUSE_FACE);
2746 }
2747 }
2748
2749 /* Look for a `help-echo' property. */
2750 {
2751 Lisp_Object help;
2752 extern Lisp_Object Qhelp_echo;
2753
2754 /* Check overlays first. */
2755 help = Qnil;
2756 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
2757 {
2758 overlay = overlay_vec[i];
2759 help = Foverlay_get (overlay, Qhelp_echo);
2760 }
2761
2762 if (!NILP (help))
2763 {
2764 help_echo_string = help;
2765 help_echo_window = window;
2766 help_echo_object = overlay;
2767 help_echo_pos = pos;
2768 }
2769 /* Try text properties. */
2770 else if (NILP (help)
2771 && ((STRINGP (glyph->object)
2772 && glyph->charpos >= 0
2773 && glyph->charpos < SCHARS (glyph->object))
2774 || (BUFFERP (glyph->object)
2775 && glyph->charpos >= BEGV
2776 && glyph->charpos < ZV)))
2777 {
2778 help = Fget_text_property (make_number (glyph->charpos),
2779 Qhelp_echo, glyph->object);
2780 if (!NILP (help))
2781 {
2782 help_echo_string = help;
2783 help_echo_window = window;
2784 help_echo_object = glyph->object;
2785 help_echo_pos = glyph->charpos;
2786 }
2787 }
2788 }
2789
2790 BEGV = obegv;
2791 ZV = ozv;
2792 current_buffer = obuf;
2793 }
2794 }
2795}
2796
2797static int
2798term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2799{
2800 /* Has the mouse moved off the glyph it was on at the last sighting? */
2801 if (event->x != last_mouse_x || event->y != last_mouse_y)
2802 {
2803 frame->mouse_moved = 1;
2804 term_mouse_highlight (frame, event->x - 1, event->y - 1);
2805 /* Remember which glyph we're now on. */
2806 last_mouse_x = event->x;
2807 last_mouse_y = event->y;
2808 return 1;
2809 }
2810 return 0;
2811}
2812
2813/* Return the current position of the mouse.
2814
2815 Set *f to the frame the mouse is in, or zero if the mouse is in no
2816 Emacs frame. If it is set to zero, all the other arguments are
2817 garbage.
2818
2819 Set *bar_window to Qnil, and *x and *y to the column and
2820 row of the character cell the mouse is over.
2821
2822 Set *time to the time the mouse was at the returned position.
2823
2824 This should clear mouse_moved until the next motion
2825 event arrives.
2826
2827 NOT CURRENTLY INVOKED: see mouse_position_hook below. */
2828static void
2829term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
2830 enum scroll_bar_part *part, Lisp_Object *x,
2831 Lisp_Object *y, unsigned long *time)
2832{
2833 Gpm_Event event;
2834 struct timeval now;
2835 int i;
2836
2837 BLOCK_INPUT;
2838
2839 *fp = SELECTED_FRAME ();
2840
2841 *bar_window = Qnil;
2842 *part = 0;
2843
2844 i = Gpm_GetSnapshot (&event);
2845
2846 XSETINT (*x, event.x);
2847 XSETINT (*y, event.y);
2848 gettimeofday(&now, 0);
2849 *time = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2850
2851 UNBLOCK_INPUT;
2852}
2853
2854/* Prepare a mouse-event in *RESULT for placement in the input queue.
2855
2856 If the event is a button press, then note that we have grabbed
2857 the mouse. */
2858
2859static Lisp_Object
2860term_mouse_click (struct input_event *result, Gpm_Event *event,
2861 struct frame *f)
2862{
2863 struct timeval now;
2864 int i, j;
2865
2866 result->kind = GPM_CLICK_EVENT;
2867 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
2868 {
2869 if (event->buttons & j) {
2870 result->code = i; /* button number */
2871 break;
2872 }
2873 }
2874 gettimeofday(&now, 0);
2875 result->timestamp = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2876
2877 if (event->type & GPM_UP)
2878 result->modifiers = up_modifier;
2879 else if (event->type & GPM_DOWN)
2880 result->modifiers = down_modifier;
2881 else
2882 result->modifiers = 0;
2883
2884 if (event->type & GPM_SINGLE)
2885 result->modifiers |= click_modifier;
2886
2887 if (event->type & GPM_DOUBLE)
2888 result->modifiers |= double_modifier;
2889
2890 if (event->type & GPM_TRIPLE)
2891 result->modifiers |= triple_modifier;
2892
2893 if (event->type & GPM_DRAG)
2894 result->modifiers |= drag_modifier;
2895
2896 if (!(event->type & (GPM_MOVE|GPM_DRAG))) {
2897
2898 /* 1 << KG_SHIFT */
2899 if (event->modifiers & (1 << 0))
2900 result->modifiers |= shift_modifier;
2901
2902 /* 1 << KG_CTRL */
2903 if (event->modifiers & (1 << 2))
2904 result->modifiers |= ctrl_modifier;
2905
2906 /* 1 << KG_ALT || KG_ALTGR */
2907 if (event->modifiers & (1 << 3)
2908 || event->modifiers & (1 << 1))
2909 result->modifiers |= meta_modifier;
2910 }
2911
2912 XSETINT (result->x, event->x - 1);
2913 XSETINT (result->y, event->y - 1);
2914 XSETFRAME (result->frame_or_window, f);
2915 result->arg = Qnil;
2916 return Qnil;
2917}
2918
2919int
2920handle_one_term_event (Gpm_Event *event, struct input_event* hold_quit)
2921{
2922 struct frame *f = SELECTED_FRAME ();
2923 int i, j, fd;
2924 struct input_event ie;
2925 int do_help = 0;
2926 int count = 0;
2927
2928 EVENT_INIT (ie);
2929 ie.kind = NO_EVENT;
2930 ie.arg = Qnil;
2931
2932 if (event->type & GPM_MOVE) {
2933 unsigned char buf[6 * sizeof (short)];
2934 unsigned short *arg = (unsigned short *) buf + 1;
2935 const char *name;
2936
2937 previous_help_echo_string = help_echo_string;
2938 help_echo_string = Qnil;
2939
2940 /* Display mouse pointer */
2941 buf[sizeof(short) - 1] = 2; /* set selection */
2942
2943 arg[0] = arg[2] = (unsigned short) event->x;
2944 arg[1] = arg[3] = (unsigned short) event->y;
2945 arg[4] = (unsigned short) 3;
2946
2947 name = (const char *) ttyname (0);
2948 fd = open (name, O_WRONLY);
2949 ioctl (fd, TIOCLINUX, buf + sizeof (short) - 1);
2950 close(fd);
2951
2952 term_mouse_movement (f, event);
2953
2954 /* If the contents of the global variable help_echo_string
2955 has changed, generate a HELP_EVENT. */
2956 if (!NILP (help_echo_string)
2957 || !NILP (previous_help_echo_string))
2958 do_help = 1;
2959
2960 goto done;
2961 }
2962 else {
2963 f->mouse_moved = 0;
2964 term_mouse_click (&ie, event, f);
2965 //kbd_buffer_store_event_hold (&ie, hold_quit);
2966 }
2967
2968 done:
2969 if (ie.kind != NO_EVENT)
2970 {
2971 kbd_buffer_store_event_hold (&ie, hold_quit);
2972 count++;
2973 }
2974
2975 if (do_help
2976 && !(hold_quit && hold_quit->kind != NO_EVENT))
2977 {
2978 Lisp_Object frame;
2979
2980 if (f)
2981 XSETFRAME (frame, f);
2982 else
2983 frame = Qnil;
2984
2985 gen_help_event (help_echo_string, frame, help_echo_window,
2986 help_echo_object, help_echo_pos);
2987 count++;
2988 }
2989
2990 return count;
2991}
2992
2993DEFUN ("term-open-connection", Fterm_open_connection, Sterm_open_connection,
2994 0, 0, 0,
2995 doc: /* Open a connection to Gpm. */)
2996 ()
2997{
2998 Gpm_Connect connection;
2999
3000 connection.eventMask = ~0;
3001 connection.defaultMask = ~GPM_HARD;
3002 connection.maxMod = ~0;
3003 connection.minMod = 0;
3004
3005 if (Gpm_Open (&connection, 0) < 0)
3006 return Qnil;
3007 else
3008 {
3009 term_gpm = 1;
3010 reset_sys_modes ();
3011 init_sys_modes ();
3012 add_gpm_wait_descriptor (gpm_fd);
3013 return Qt;
3014 }
3015}
3016
3017DEFUN ("term-close-connection", Fterm_close_connection, Sterm_close_connection,
3018 0, 0, 0,
3019 doc: /* Close a connection to Gpm. */)
3020 ()
3021{
3022 delete_gpm_wait_descriptor (gpm_fd);
3023 while (Gpm_Close()); /* close all the stack */
3024 term_gpm = 0;
3025 return Qnil;
3026}
3027#endif /* HAVE_GPM_H */
3028
3029
3030/***********************************************************************
2311 Initialization 3031 Initialization
2312 ***********************************************************************/ 3032 ***********************************************************************/
2313 3033
@@ -2325,6 +3045,14 @@ term_init (terminal_type)
2325 3045
2326 encode_terminal_bufsize = 0; 3046 encode_terminal_bufsize = 0;
2327 3047
3048#ifdef HAVE_GPM_H
3049 /* TODO: Can't get Gpm_Snapshot in term_mouse_position to work: test with
3050 (mouse-position). Also set-mouse-position won't work as is. */
3051 /* mouse_position_hook = term_mouse_position; */
3052
3053 mouse_face_window = Qnil;
3054#endif
3055
2328#ifdef WINDOWSNT 3056#ifdef WINDOWSNT
2329 initialize_w32_display (); 3057 initialize_w32_display ();
2330 3058
@@ -2772,6 +3500,10 @@ bigger, or it may make it blink, or it may do nothing at all. */);
2772 defsubr (&Stty_display_color_p); 3500 defsubr (&Stty_display_color_p);
2773 defsubr (&Stty_display_color_cells); 3501 defsubr (&Stty_display_color_cells);
2774 defsubr (&Stty_no_underline); 3502 defsubr (&Stty_no_underline);
3503#ifdef HAVE_GPM_H
3504 defsubr (&Sterm_open_connection);
3505 defsubr (&Sterm_close_connection);
3506#endif /* HAVE_GPM_H */
2775 3507
2776 fullscreen_hook = NULL; 3508 fullscreen_hook = NULL;
2777} 3509}