home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / e20313sr.zip / emacs / 20.3.1 / src / pmfaces.c < prev    next >
C/C++ Source or Header  |  1999-07-31  |  13KB  |  415 lines

  1. /* pmfaces.c -- mouse face code from xterm.c for the OS/2 Presentation Manager
  2.    Copyright (C) 1994, 1995 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU Emacs.
  5.  
  6. GNU Emacs is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GNU Emacs is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Emacs; see the file COPYING.  If not, write to
  18. the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  19. Boston, MA 02111-1307, USA.  */
  20.  
  21.  
  22. #include <stdlib.h>
  23. #include "config.h"
  24. #include "lisp.h"
  25. #include "buffer.h"
  26. #include "window.h"
  27. #include "frame.h"
  28. #include "dispextern.h"
  29. #include "pmterm.h"
  30.  
  31. extern int curs_x;
  32. extern int curs_y;
  33.  
  34. /* Borrowed from xterm.c. */
  35.  
  36. extern Lisp_Object Qmouse_face;
  37.  
  38. /* This is used for debugging, to turn off note_mouse_highlight.  */
  39. static int disable_mouse_highlight;
  40.  
  41.  
  42. /* Borrowed from xterm.c. */
  43.  
  44. #define min(a,b) ((a)<(b) ? (a) : (b))
  45.  
  46. /* TODO */
  47. #define CHAR_TO_PIXEL_ROW(f, row) (row)
  48. #define CHAR_TO_PIXEL_COL(f, col) (col)
  49.  
  50. /* Find the row and column of position POS in window WINDOW.
  51.    Store them in *COLUMNP and *ROWP.
  52.    This assumes display in WINDOW is up to date.
  53.    If POS is above start of WINDOW, return coords
  54.    of start of first screen line.
  55.    If POS is after end of WINDOW, return coords of end of last screen line.
  56.  
  57.    Value is 1 if POS is in range, 0 if it was off screen.  */
  58.  
  59. static int
  60. fast_find_position (window, pos, columnp, rowp)
  61.      Lisp_Object window;
  62.      int pos;
  63.      int *columnp, *rowp;
  64. {
  65.   struct window *w = XWINDOW (window);
  66.   FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
  67.   int i;
  68.   int row = 0;
  69.   int left = w->left;
  70.   int top = w->top;
  71.   int height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
  72.   int width = window_internal_width (w);
  73.   int *charstarts;
  74.   int lastcol;
  75.   int maybe_next_line = 0;
  76.  
  77.   /* Find the right row.  */
  78.   for (i = 0;
  79.        i < height;
  80.        i++)
  81.     {
  82.       int linestart = FRAME_CURRENT_GLYPHS (f)->charstarts[top + i][left];
  83.       if (linestart > pos)
  84.     break;
  85.       /* If the position sought is the end of the buffer,
  86.      don't include the blank lines at the bottom of the window.  */
  87.       if (linestart == pos && pos == BUF_ZV (XBUFFER (w->buffer)))
  88.     {
  89.       maybe_next_line = 1;
  90.       break;
  91.     }
  92.       if (linestart > 0)
  93.     row = i;
  94.     }
  95.  
  96.   /* Find the right column with in it.  */
  97.   charstarts = FRAME_CURRENT_GLYPHS (f)->charstarts[top + row];
  98.   lastcol = left;
  99.   for (i = 0; i < width; i++)
  100.     {
  101.       if (charstarts[left + i] == pos)
  102.     {
  103.       *rowp = row + top;
  104.       *columnp = i + left;
  105.       return 1;
  106.     }
  107.       else if (charstarts[left + i] > pos)
  108.     break;
  109.       else if (charstarts[left + i] > 0)
  110.     lastcol = left + i;
  111.     }
  112.  
  113.   /* If we're looking for the end of the buffer,
  114.      and we didn't find it in the line we scanned,
  115.      use the start of the following line.  */
  116.   if (maybe_next_line)
  117.     {
  118.       row++;
  119.       i = 0;
  120.     }
  121.  
  122.   *rowp = row + top;
  123.   *columnp = lastcol;
  124.   return 0;
  125. }
  126.  
  127. /* Display the active region described by mouse_face_*
  128.    in its mouse-face if HL > 0, in its normal face if HL = 0.  */
  129.  
  130. static void
  131. show_mouse_face (dpyinfo, hl)
  132.      struct x_display_info *dpyinfo;
  133.      int hl;
  134. {
  135.   struct window *w = XWINDOW (dpyinfo->mouse_face_window);
  136.   int width = window_internal_width (w);
  137.   FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
  138.   int i;
  139.   int cursor_off = 0;
  140.   int old_curs_x = curs_x;
  141.   int old_curs_y = curs_y;
  142.  
  143.   /* Set these variables temporarily
  144.      so that if we have to turn the cursor off and on again
  145.      we will put it back at the same place.  */
  146.   curs_x = f->phys_cursor_x;
  147.   curs_y = f->phys_cursor_y;
  148.  
  149.   for (i = FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row;
  150.        i <= FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row; i++)
  151.     {
  152.       int column = (i == FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
  153.             ? FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col
  154.             : w->left);
  155.       int endcolumn = (i == FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
  156.                ? FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col
  157.                : w->left + width);
  158.       endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i]);
  159.  
  160.       /*TODO*/
  161. #ifndef EMX
  162.       /* If the cursor's in the text we are about to rewrite,
  163.      turn the cursor off.  */
  164.       if (i == curs_y
  165.       && curs_x >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col - 1
  166.       && curs_x <= FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col)
  167.     {
  168.       x_display_cursor (f, 0);
  169.       cursor_off = 1;
  170.     }
  171.  
  172.       dumpglyphs (f,
  173.           CHAR_TO_PIXEL_COL (f, column),
  174.           CHAR_TO_PIXEL_ROW (f, i),
  175.           FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column,
  176.           endcolumn - column,
  177.           /* Highlight with mouse face if hl > 0.  */
  178.           hl > 0 ? 3 : 0, 0);
  179. #else /* EMX */
  180.       dump_glyphs (f,
  181.            FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column,
  182.                    FRAME_CURRENT_GLYPHS (f)->enable[i],
  183.                    FRAME_CURRENT_GLYPHS (f)->used[i],
  184.            CHAR_TO_PIXEL_COL (f, column),
  185.            CHAR_TO_PIXEL_ROW (f, i),
  186.            endcolumn - column,
  187.            /* Highlight with mouse face if hl > 0.  */
  188.            hl > 0 ? 3 : 0);
  189. #endif /* EMX */
  190.     }
  191.  
  192.   /*TODO*/
  193. #ifdef EMX
  194.   curs_x = old_curs_x;
  195.   curs_y = old_curs_y;
  196. #else /* not EMX */
  197.   /* If we turned the cursor off, turn it back on.  */
  198.   if (cursor_off)
  199.     x_display_cursor (f, 1);
  200.  
  201.   curs_x = old_curs_x;
  202.   curs_y = old_curs_y;
  203.  
  204.   /* Change the mouse cursor according to the value of HL.  */
  205.   if (hl > 0)
  206.     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
  207.            f->display.x->cross_cursor);
  208.   else
  209.     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
  210.            f->display.x->text_cursor);
  211. #endif /* not EMX */
  212. }
  213.  
  214. /* Clear out the mouse-highlighted active region.
  215.    Redraw it unhighlighted first.  */
  216.  
  217. void
  218. clear_mouse_face (dpyinfo)
  219.      struct x_display_info *dpyinfo;
  220. {
  221.   if (! NILP (dpyinfo->mouse_face_window))
  222.     show_mouse_face (dpyinfo, 0);
  223.  
  224.   dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
  225.   dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
  226.   dpyinfo->mouse_face_window = Qnil;
  227. }
  228.  
  229. /* Take proper action when the mouse has moved to position X, Y on frame F
  230.    as regards highlighting characters that have mouse-face properties.
  231.    Also dehighlighting chars where the mouse was before.
  232.    X and Y can be negative or out of range.  */
  233.  
  234. void
  235. note_mouse_highlight (f, x, y)
  236.      FRAME_PTR f;
  237.      int x, y;
  238. {
  239.   int row, column, portion;
  240.   XRectangle new_glyph;
  241.   Lisp_Object window;
  242.   struct window *w;
  243.  
  244.   if (disable_mouse_highlight)
  245.     return;
  246.  
  247.   FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_x = x;
  248.   FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_y = y;
  249.   FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame = f;
  250.  
  251.   if (FRAME_X_DISPLAY_INFO (f)->mouse_face_defer)
  252.     return;
  253.  
  254.   if (gc_in_progress)
  255.     {
  256.       FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc = 1;
  257.       return;
  258.     }
  259.  
  260.   /* Find out which glyph the mouse is on.  */
  261.   pixel_to_glyph_coords (f, x, y, &column, &row,
  262.              &new_glyph, FRAME_X_DISPLAY_INFO (f)->grabbed);
  263.  
  264.   /* Which window is that in?  */
  265.   window = window_from_coordinates (f, column, row, &portion);
  266.   w = XWINDOW (window);
  267.  
  268.   /* If we were displaying active text in another window, clear that.  */
  269.   if (! EQ (window, FRAME_X_DISPLAY_INFO (f)->mouse_face_window))
  270.     clear_mouse_face (FRAME_X_DISPLAY_INFO (f));
  271.  
  272.   /* Are we in a window whose display is up to date?
  273.      And verify the buffer's text has not changed.  */
  274.   if (WINDOWP (window) && portion == 0 && row >= 0 && column >= 0
  275.       && row < FRAME_HEIGHT (f) && column < FRAME_WIDTH (f)
  276.       && EQ (w->window_end_valid, w->buffer)
  277.       && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer)))
  278.     {
  279.       int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
  280.       int i, pos;
  281.  
  282.       /* Find which buffer position the mouse corresponds to.  */
  283.       for (i = column; i >= 0; i--)
  284.     if (ptr[i] > 0)
  285.       break;
  286.       pos = ptr[i];
  287.       /* Is it outside the displayed active region (if any)?  */
  288.       if (pos <= 0)
  289.     clear_mouse_face (FRAME_X_DISPLAY_INFO (f));
  290.       else if (! (EQ (window, FRAME_X_DISPLAY_INFO (f)->mouse_face_window)
  291.           && row >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
  292.           && row <= FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
  293.           && (row > FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
  294.               || column >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col)
  295.           && (row < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
  296.               || column < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col
  297.               || FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end)))
  298.     {
  299.       Lisp_Object mouse_face, overlay, position;
  300.       Lisp_Object *overlay_vec;
  301.       int len, noverlays, ignor1;
  302.       struct buffer *obuf;
  303.       int obegv, ozv;
  304.  
  305.       /* If we get an out-of-range value, return now; avoid an error.  */
  306.       if (pos > BUF_Z (XBUFFER (w->buffer)))
  307.         return;
  308.  
  309.       /* Make the window's buffer temporarily current for
  310.          overlays_at and compute_char_face.  */
  311.       obuf = current_buffer;
  312.       current_buffer = XBUFFER (w->buffer);
  313.       obegv = BEGV;
  314.       ozv = ZV;
  315.       BEGV = BEG;
  316.       ZV = Z;
  317.  
  318.       /* Yes.  Clear the display of the old active region, if any.  */
  319.       clear_mouse_face (FRAME_X_DISPLAY_INFO (f));
  320.  
  321.       /* Is this char mouse-active?  */
  322.       XSETINT (position, pos);
  323.  
  324.       len = 10;
  325.       overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
  326.  
  327.       /* Put all the overlays we want in a vector in overlay_vec.
  328.          Store the length in len.  */
  329.       noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
  330.                    NULL, NULL);
  331.       noverlays = sort_overlays (overlay_vec, noverlays, w);
  332.  
  333.       /* Find the highest priority overlay that has a mouse-face prop.  */
  334.       overlay = Qnil;
  335.       for (i = 0; i < noverlays; i++)
  336.         {
  337.           mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
  338.           if (!NILP (mouse_face))
  339.         {
  340.           overlay = overlay_vec[i];
  341.           break;
  342.         }
  343.         }
  344.       free (overlay_vec);
  345.       /* If no overlay applies, get a text property.  */
  346.       if (NILP (overlay))
  347.         mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
  348.  
  349.       /* Handle the overlay case.  */
  350.       if (! NILP (overlay))
  351.         {
  352.           /* Find the range of text around this char that
  353.          should be active.  */
  354.           Lisp_Object before, after;
  355.           int ignore;
  356.  
  357.           before = Foverlay_start (overlay);
  358.           after = Foverlay_end (overlay);
  359.           /* Record this as the current active region.  */
  360.           fast_find_position (window, before,
  361.                   &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col,
  362.                   &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row);
  363.           FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end
  364.         = !fast_find_position (window, after,
  365.                        &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col,
  366.                        &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row);
  367.           FRAME_X_DISPLAY_INFO (f)->mouse_face_window = window;
  368.           FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id
  369.         = compute_char_face (f, w, pos, 0, 0,
  370.                      &ignore, pos + 1, 1);
  371.  
  372.           /* Display it as active.  */
  373.           show_mouse_face (FRAME_X_DISPLAY_INFO (f), 1);
  374.         }
  375.       /* Handle the text property case.  */
  376.       else if (! NILP (mouse_face))
  377.         {
  378.           /* Find the range of text around this char that
  379.          should be active.  */
  380.           Lisp_Object before, after, beginning, end;
  381.           int ignore;
  382.  
  383.           beginning = Fmarker_position (w->start);
  384.           XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
  385.                  - XFASTINT (w->window_end_pos)));
  386.           before
  387.         = Fprevious_single_property_change (make_number (pos + 1),
  388.                             Qmouse_face,
  389.                             w->buffer, beginning);
  390.           after
  391.         = Fnext_single_property_change (position, Qmouse_face,
  392.                         w->buffer, end);
  393.           /* Record this as the current active region.  */
  394.           fast_find_position (window, before,
  395.                   &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col,
  396.                   &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row);
  397.           FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end
  398.         = !fast_find_position (window, after,
  399.                        &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col,
  400.                        &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row);
  401.           FRAME_X_DISPLAY_INFO (f)->mouse_face_window = window;
  402.           FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id
  403.         = compute_char_face (f, w, pos, 0, 0,
  404.                      &ignore, pos + 1, 1);
  405.  
  406.           /* Display it as active.  */
  407.           show_mouse_face (FRAME_X_DISPLAY_INFO (f), 1);
  408.         }
  409.       BEGV = obegv;
  410.       ZV = ozv;
  411.       current_buffer = obuf;
  412.     }
  413.     }
  414. }
  415.