comparison src/intervals.c @ 43898:8b2a2bd229c3

(adjust_for_invis_intang): New function. (set_point_both): Use `adjust_for_invis_intang' to do most of the work for dealing with invisible+intangible regions. Do so before and after both forward and backward movements, to handle both front-sticky and rear-sticky cases.
author Miles Bader <miles@gnu.org>
date Thu, 14 Mar 2002 08:11:46 +0000
parents 3af09e7320c0
children b9f2c8b7c60e
comparison
equal deleted inserted replaced
43897:46cd50d89b5b 43898:8b2a2bd229c3
1 /* Code for doing intervals. 1 /* Code for doing intervals.
2 Copyright (C) 1993, 1994, 1995, 1997, 1998 Free Software Foundation, Inc. 2 Copyright (C) 1993, 1994, 1995, 1997, 1998, 2002 Free Software Foundation, Inc.
3 3
4 This file is part of GNU Emacs. 4 This file is part of GNU Emacs.
5 5
6 GNU Emacs is free software; you can redistribute it and/or modify 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 7 it under the terms of the GNU General Public License as published by
1881 register int charpos; 1881 register int charpos;
1882 { 1882 {
1883 set_point_both (buffer, charpos, buf_charpos_to_bytepos (buffer, charpos)); 1883 set_point_both (buffer, charpos, buf_charpos_to_bytepos (buffer, charpos));
1884 } 1884 }
1885 1885
1886 /* If there's an invisible character at position POS + TEST_OFFS in the
1887 current buffer, and the invisible property has a `stickiness' such that
1888 inserting a character at position POS would inherit the property it,
1889 return POS + ADJ, otherwise return POS. If TEST_INTANG is non-zero,
1890 then intangibility is required as well as invisibleness.
1891
1892 TEST_OFFS should be either 0 or -1, and ADJ should be either 1 or -1.
1893
1894 Note that `stickiness' is determined by overlay marker insertion types,
1895 if the invisible property comes from an overlay. */
1896
1897 static int
1898 adjust_for_invis_intang (pos, test_offs, adj, test_intang)
1899 int pos, test_offs, adj, test_intang;
1900 {
1901 Lisp_Object invis_propval, invis_overlay;
1902 Lisp_Object test_pos;
1903
1904 if ((adj < 0 && pos + adj < BEGV) || (adj > 0 && pos + adj > ZV))
1905 /* POS + ADJ would be beyond the buffer bounds, so do no adjustment. */
1906 return pos;
1907
1908 test_pos = make_number (pos + test_offs);
1909
1910 invis_propval
1911 = get_char_property_and_overlay (test_pos, Qinvisible, Qnil,
1912 &invis_overlay);
1913
1914 if ((!test_intang
1915 || ! NILP (Fget_char_property (test_pos, Qintangible, Qnil)))
1916 && TEXT_PROP_MEANS_INVISIBLE (invis_propval)
1917 /* This next test is true if the invisible property has a stickiness
1918 such that an insertion at POS would inherit it. */
1919 && (NILP (invis_overlay)
1920 /* Invisible property is from a text-property. */
1921 ? (text_property_stickiness (Qinvisible, make_number (pos))
1922 == (test_offs == 0 ? 1 : -1))
1923 /* Invisible property is from an overlay. */
1924 : (test_offs == 0
1925 ? XMARKER (OVERLAY_START (invis_overlay))->insertion_type == 0
1926 : XMARKER (OVERLAY_END (invis_overlay))->insertion_type == 1)))
1927 pos += adj;
1928
1929 return pos;
1930 }
1931
1886 /* Set point in BUFFER to CHARPOS, which corresponds to byte 1932 /* Set point in BUFFER to CHARPOS, which corresponds to byte
1887 position BYTEPOS. If the target position is 1933 position BYTEPOS. If the target position is
1888 before an intangible character, move to an ok place. */ 1934 before an intangible character, move to an ok place. */
1889 1935
1890 void 1936 void
1973 || have_overlays) 2019 || have_overlays)
1974 /* Intangibility never stops us from positioning at the beginning 2020 /* Intangibility never stops us from positioning at the beginning
1975 or end of the buffer, so don't bother checking in that case. */ 2021 or end of the buffer, so don't bother checking in that case. */
1976 && charpos != BEGV && charpos != ZV) 2022 && charpos != BEGV && charpos != ZV)
1977 { 2023 {
1978 Lisp_Object intangible_propval, invisible_propval;
1979 Lisp_Object pos; 2024 Lisp_Object pos;
1980 int invis_p; 2025 Lisp_Object intangible_propval;
1981
1982 XSETINT (pos, charpos);
1983 2026
1984 if (backwards) 2027 if (backwards)
1985 { 2028 {
1986 /* If the preceding char is both invisible and intangible, 2029 /* If the preceeding character is both intangible and invisible,
1987 start backing up from just before that one. */ 2030 and the invisible property is `rear-sticky', perturb it so
1988 2031 that the search starts one character earlier -- this ensures
1989 intangible_propval 2032 that point can never move to the end of an invisible/
1990 = Fget_char_property (make_number (charpos - 1), 2033 intangible/rear-sticky region. */
1991 Qintangible, Qnil); 2034 charpos = adjust_for_invis_intang (charpos, -1, -1, 1);
1992 invisible_propval 2035
1993 = Fget_char_property (make_number (charpos - 1), Qinvisible, Qnil); 2036 XSETINT (pos, charpos);
1994 invis_p = TEXT_PROP_MEANS_INVISIBLE (invisible_propval);
1995
1996 if (! NILP (intangible_propval) && invis_p)
1997 XSETINT (pos, --charpos);
1998 2037
1999 /* If following char is intangible, 2038 /* If following char is intangible,
2000 skip back over all chars with matching intangible property. */ 2039 skip back over all chars with matching intangible property. */
2001 2040
2002 intangible_propval = Fget_char_property (pos, Qintangible, Qnil); 2041 intangible_propval = Fget_char_property (pos, Qintangible, Qnil);
2006 while (XINT (pos) > BUF_BEGV (buffer) 2045 while (XINT (pos) > BUF_BEGV (buffer)
2007 && EQ (Fget_char_property (make_number (XINT (pos) - 1), 2046 && EQ (Fget_char_property (make_number (XINT (pos) - 1),
2008 Qintangible, Qnil), 2047 Qintangible, Qnil),
2009 intangible_propval)) 2048 intangible_propval))
2010 pos = Fprevious_char_property_change (pos, Qnil); 2049 pos = Fprevious_char_property_change (pos, Qnil);
2050
2051 /* Set CHARPOS from POS, and if the final intangible character
2052 that we skipped over is also invisible, and the invisible
2053 property is `front-sticky', perturb it to be one character
2054 earlier -- this ensures that point can never move to the
2055 beginning of an invisible/intangible/front-sticky region. */
2056 charpos = adjust_for_invis_intang (XINT (pos), 0, -1, 0);
2011 } 2057 }
2012 } 2058 }
2013 else 2059 else
2014 { 2060 {
2061 /* If the following character is both intangible and invisible,
2062 and the invisible property is `front-sticky', perturb it so
2063 that the search starts one character later -- this ensures
2064 that point can never move to the beginning of an
2065 invisible/intangible/front-sticky region. */
2066 charpos = adjust_for_invis_intang (charpos, 0, 1, 1);
2067
2068 XSETINT (pos, charpos);
2069
2015 /* If preceding char is intangible, 2070 /* If preceding char is intangible,
2016 skip forward over all chars with matching intangible property. */ 2071 skip forward over all chars with matching intangible property. */
2017 2072
2018 intangible_propval = Fget_char_property (make_number (charpos - 1), 2073 intangible_propval = Fget_char_property (make_number (charpos - 1),
2019 Qintangible, Qnil); 2074 Qintangible, Qnil);
2023 while (XINT (pos) < BUF_ZV (buffer) 2078 while (XINT (pos) < BUF_ZV (buffer)
2024 && EQ (Fget_char_property (pos, Qintangible, Qnil), 2079 && EQ (Fget_char_property (pos, Qintangible, Qnil),
2025 intangible_propval)) 2080 intangible_propval))
2026 pos = Fnext_char_property_change (pos, Qnil); 2081 pos = Fnext_char_property_change (pos, Qnil);
2027 2082
2028 /* Is the last one invisible as well as intangible? */ 2083 /* Set CHARPOS from POS, and if the final intangible character
2029 2084 that we skipped over is also invisible, and the invisible
2030 invisible_propval 2085 property is `rear-sticky', perturb it to be one character
2031 = Fget_char_property (make_number (XINT (pos) - 1), 2086 later -- this ensures that point can never move to the
2032 Qinvisible, Qnil); 2087 end of an invisible/intangible/rear-sticky region. */
2033 invis_p = TEXT_PROP_MEANS_INVISIBLE (invisible_propval); 2088 charpos = adjust_for_invis_intang (XINT (pos), -1, 1, 0);
2034
2035 /* If so, advance one character more:
2036 don't stop after an invisible, intangible character. */
2037
2038 if (invis_p && XINT (pos) < BUF_ZV (buffer))
2039 XSETINT (pos, XINT (pos) + 1);
2040 } 2089 }
2041 } 2090 }
2042 2091
2043 charpos = XINT (pos);
2044 bytepos = buf_charpos_to_bytepos (buffer, charpos); 2092 bytepos = buf_charpos_to_bytepos (buffer, charpos);
2045 } 2093 }
2046 2094
2047 if (charpos != original_position) 2095 if (charpos != original_position)
2048 { 2096 {