+/* Skip some invisible characters starting from POS.
+ This includes characters invisible because of text properties
+ and characters invisible because of overlays.
+
+ If position POS is followed by invisible characters,
+ skip some of them and return the position after them.
+ Otherwise return POS itself.
+
+ Set *NEXT_BOUNDARY_P to the next position at which
+ it will be necessary to call this function again.
+
+ Don't scan past TO, and don't set *NEXT_BOUNDARY_P
+ to a value greater than TO.
+
+ If WINDOW is non-nil, and this buffer is displayed in WINDOW,
+ take account of overlays that apply only in WINDOW.
+
+ We don't necessarily skip all the invisible characters after POS
+ because that could take a long time. We skip a reasonable number
+ which can be skipped quickly. If there might be more invisible
+ characters immediately following, then *NEXT_BOUNDARY_P
+ will equal the return value. */
+
+int
+skip_invisible (pos, next_boundary_p, to, window)
+ int pos;
+ int *next_boundary_p;
+ int to;
+ Lisp_Object window;
+{
+ Lisp_Object prop, position, overlay_limit, proplimit;
+ Lisp_Object buffer;
+ int end;
+
+ XSETFASTINT (position, pos);
+ XSETBUFFER (buffer, current_buffer);
+
+ /* Give faster response for overlay lookup near POS. */
+ recenter_overlay_lists (current_buffer, pos);
+
+ /* We must not advance farther than the next overlay change.
+ The overlay change might change the invisible property;
+ or there might be overlay strings to be displayed there. */
+ overlay_limit = Fnext_overlay_change (position);
+ /* As for text properties, this gives a lower bound
+ for where the invisible text property could change. */
+ proplimit = Fnext_property_change (position, buffer, Qt);
+ if (XFASTINT (overlay_limit) < XFASTINT (proplimit))
+ proplimit = overlay_limit;
+ /* PROPLIMIT is now a lower bound for the next change
+ in invisible status. If that is plenty far away,
+ use that lower bound. */
+ if (XFASTINT (proplimit) > pos + 100 || XFASTINT (proplimit) >= to)
+ *next_boundary_p = XFASTINT (proplimit);
+ /* Otherwise, scan for the next `invisible' property change. */
+ else
+ {
+ /* Don't scan terribly far. */
+ XSETFASTINT (proplimit, min (pos + 100, to));
+ /* No matter what. don't go past next overlay change. */
+ if (XFASTINT (overlay_limit) < XFASTINT (proplimit))
+ proplimit = overlay_limit;
+ end = XFASTINT (Fnext_single_property_change (position, Qinvisible,
+ buffer, proplimit));
+#if 0
+ /* Don't put the boundary in the middle of multibyte form if
+ there is no actual property change. */
+ if (end == pos + 100
+ && !NILP (current_buffer->enable_multibyte_characters)
+ && end < ZV)
+ while (pos < end && !CHAR_HEAD_P (POS_ADDR (end)))
+ end--;
+#endif
+ *next_boundary_p = end;
+ }
+ /* if the `invisible' property is set, we can skip to
+ the next property change */
+ if (!NILP (window) && EQ (XWINDOW (window)->buffer, buffer))
+ prop = Fget_char_property (position, Qinvisible, window);
+ else
+ prop = Fget_char_property (position, Qinvisible, buffer);
+ if (TEXT_PROP_MEANS_INVISIBLE (prop))
+ return *next_boundary_p;
+ return pos;
+}
+\f
+/* If a composition starts at POS/POS_BYTE and it doesn't stride over
+ POINT, set *LEN / *LEN_BYTE to the character and byte lengths, *WIDTH
+ to the width, and return 1. Otherwise, return 0. */
+
+static int
+check_composition (pos, pos_byte, point, len, len_byte, width)
+ int pos, pos_byte, point;
+ int *len, *len_byte, *width;
+{
+ Lisp_Object prop;
+ int start, end;
+ int id;
+
+ if (! find_composition (pos, -1, &start, &end, &prop, Qnil)
+ || pos != start || point < end
+ || !COMPOSITION_VALID_P (start, end, prop))
+ return 0;
+ if ((id = get_composition_id (pos, pos_byte, end - pos, prop, Qnil)) < 0)
+ return 0;
+
+ *len = COMPOSITION_LENGTH (prop);
+ *len_byte = CHAR_TO_BYTE (end) - pos_byte;
+ *width = composition_table[id]->width;
+ return 1;
+}
+\f
+/* Set variables WIDTH and BYTES for a multibyte sequence starting at P.
+
+ DP is a display table or NULL.
+
+ This macro is used in current_column_1, Fmove_to_column, and
+ compute_motion. */
+
+#define MULTIBYTE_BYTES_WIDTH(p, dp) \
+ do { \
+ int c; \
+ \
+ wide_column = 0; \
+ c = STRING_CHAR_AND_LENGTH (p, MAX_MULTIBYTE_LENGTH, bytes); \
+ if (BYTES_BY_CHAR_HEAD (*p) != bytes) \
+ width = bytes * 4; \
+ else \
+ { \
+ if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c))) \
+ width = XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; \
+ else \
+ width = WIDTH_BY_CHAR_HEAD (*p); \
+ if (width > 1) \
+ wide_column = width; \
+ } \
+ } while (0)
+