Function: bidi-resolved-levels

bidi-resolved-levels is a function defined in xdisp.c.

Signature

(bidi-resolved-levels &optional VPOS)

Documentation

Return the resolved bidirectional levels of characters at VPOS.

The resolved levels are produced by the Emacs bidi reordering engine that implements the UBA, the Unicode Bidirectional Algorithm. Please read the Unicode Standard Annex 9 (UAX#9) for background information about these levels.

VPOS is the zero-based number of the current window's screen line for which to produce the resolved levels. If VPOS is nil or omitted, it defaults to the screen line of point. If the window displays a header line, VPOS of zero will report on the header line, and first line of text in the window will have VPOS of 1.

Value is an array of resolved levels, indexed by glyph number. Glyphs are numbered from zero starting from the beginning of the screen line, i.e. the left edge of the window for left-to-right lines and from the right edge for right-to-left lines. The resolved levels are produced only for the window's text area; text in display margins is not included.

If the selected window's display is not up-to-date, or if the specified screen line does not display text, this function returns nil. It is highly recommended to bind this function to some simple key, like F8, in order to avoid these problems.

This function exists mainly for testing the correctness of the Emacs UBA implementation, in particular with the test suite.

Source Code

// Defined in /usr/src/emacs/src/xdisp.c
{
  struct window *w = XWINDOW (selected_window);
  struct buffer *b = XBUFFER (w->contents);
  int nrow;
  struct glyph_row *row;

  if (NILP (vpos))
    {
      int d1, d2, d3, d4, d5;

      pos_visible_p (w, PT, &d1, &d2, &d3, &d4, &d5, &nrow);
    }
  else
    {
      CHECK_FIXNUM (vpos);
      nrow = XFIXNUM (vpos);
    }

  /* We require up-to-date glyph matrix for this window.  */
  if (w->window_end_valid
      && !windows_or_buffers_changed
      && b
      && !b->clip_changed
      && !b->prevent_redisplay_optimizations_p
      && !window_outdated (w)
      && nrow >= 0
      && nrow < w->current_matrix->nrows
      && (row = MATRIX_ROW (w->current_matrix, nrow))->enabled_p
      && MATRIX_ROW_DISPLAYS_TEXT_P (row))
    {
      struct glyph *g, *e, *g1;
      int nglyphs, i;
      Lisp_Object levels;

      if (!row->reversed_p)	/* Left-to-right glyph row.  */
	{
	  g = g1 = row->glyphs[TEXT_AREA];
	  e = g + row->used[TEXT_AREA];

	  /* Skip over glyphs at the start of the row that was
	     generated by redisplay for its own needs.  */
	  while (g < e
		 && NILP (g->object)
		 && g->charpos < 0)
	    g++;
	  g1 = g;

	  /* Count the "interesting" glyphs in this row.  */
	  for (nglyphs = 0; g < e && !NILP (g->object); g++)
	    nglyphs++;

	  /* Create and fill the array.  */
	  levels = make_uninit_vector (nglyphs);
	  for (i = 0; g1 < g; i++, g1++)
	    ASET (levels, i, make_fixnum (g1->resolved_level));
	}
      else			/* Right-to-left glyph row.  */
	{
	  g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
	  e = row->glyphs[TEXT_AREA] - 1;
	  while (g > e
		 && NILP (g->object)
		 && g->charpos < 0)
	    g--;
	  g1 = g;
	  for (nglyphs = 0; g > e && !NILP (g->object); g--)
	    nglyphs++;
	  levels = make_uninit_vector (nglyphs);
	  for (i = 0; g1 > g; i++, g1--)
	    ASET (levels, i, make_fixnum (g1->resolved_level));
	}
      return levels;
    }
  else
    return Qnil;
}