+ original_position = charpos;
+
+ /* If the new position is between two intangible characters
+ with the same intangible property value,
+ move forward or backward until a change in that property. */
+ if (NILP (Vinhibit_point_motion_hooks)
+ && ((! NULL_INTERVAL_P (to) && ! NULL_INTERVAL_P (toprev))
+ || have_overlays)
+ /* Intangibility never stops us from positioning at the beginning
+ or end of the buffer, so don't bother checking in that case. */
+ && charpos != BEGV && charpos != ZV)
+ {
+ Lisp_Object pos;
+ Lisp_Object intangible_propval;
+
+ if (backwards)
+ {
+ /* If the preceeding character is both intangible and invisible,
+ and the invisible property is `rear-sticky', perturb it so
+ that the search starts one character earlier -- this ensures
+ that point can never move to the end of an invisible/
+ intangible/rear-sticky region. */
+ charpos = adjust_for_invis_intang (charpos, -1, -1, 1);
+
+ XSETINT (pos, charpos);
+
+ /* If following char is intangible,
+ skip back over all chars with matching intangible property. */
+
+ intangible_propval = Fget_char_property (pos, Qintangible, Qnil);
+
+ if (! NILP (intangible_propval))
+ {
+ while (XINT (pos) > BUF_BEGV (buffer)
+ && EQ (Fget_char_property (make_number (XINT (pos) - 1),
+ Qintangible, Qnil),
+ intangible_propval))
+ pos = Fprevious_char_property_change (pos, Qnil);
+
+ /* Set CHARPOS from POS, and if the final intangible character
+ that we skipped over is also invisible, and the invisible
+ property is `front-sticky', perturb it to be one character
+ earlier -- this ensures that point can never move to the
+ beginning of an invisible/intangible/front-sticky region. */
+ charpos = adjust_for_invis_intang (XINT (pos), 0, -1, 0);
+ }
+ }
+ else
+ {
+ /* If the following character is both intangible and invisible,
+ and the invisible property is `front-sticky', perturb it so
+ that the search starts one character later -- this ensures
+ that point can never move to the beginning of an
+ invisible/intangible/front-sticky region. */
+ charpos = adjust_for_invis_intang (charpos, 0, 1, 1);
+
+ XSETINT (pos, charpos);
+
+ /* If preceding char is intangible,
+ skip forward over all chars with matching intangible property. */
+
+ intangible_propval = Fget_char_property (make_number (charpos - 1),
+ Qintangible, Qnil);
+
+ if (! NILP (intangible_propval))
+ {
+ while (XINT (pos) < BUF_ZV (buffer)
+ && EQ (Fget_char_property (pos, Qintangible, Qnil),
+ intangible_propval))
+ pos = Fnext_char_property_change (pos, Qnil);
+
+ /* Set CHARPOS from POS, and if the final intangible character
+ that we skipped over is also invisible, and the invisible
+ property is `rear-sticky', perturb it to be one character
+ later -- this ensures that point can never move to the
+ end of an invisible/intangible/rear-sticky region. */
+ charpos = adjust_for_invis_intang (XINT (pos), -1, 1, 0);
+ }
+ }
+
+ bytepos = buf_charpos_to_bytepos (buffer, charpos);
+ }
+
+ if (charpos != original_position)