Function: current-bidi-paragraph-direction

current-bidi-paragraph-direction is a function defined in xdisp.c.

Signature

(current-bidi-paragraph-direction &optional BUFFER)

Documentation

Return paragraph direction at point in BUFFER.

Value is either left-to-right or right-to-left. If BUFFER is omitted or nil, it defaults to the current buffer.

Paragraph direction determines how the text in the paragraph is displayed. In left-to-right paragraphs, text begins at the left margin of the window and the reading direction is generally left to right. In right-to-left paragraphs, text begins at the right margin and is read from right to left.

See also bidi-paragraph-direction.

View in manual

Probably introduced at or before Emacs version 24.1.

Source Code

// Defined in /usr/src/emacs/src/xdisp.c
{
  struct buffer *buf = current_buffer;
  struct buffer *old = buf;

  if (! NILP (buffer))
    {
      CHECK_BUFFER (buffer);
      buf = XBUFFER (buffer);
    }

  if (NILP (BVAR (buf, bidi_display_reordering))
      || NILP (BVAR (buf, enable_multibyte_characters))
      /* When we are loading loadup.el, the character property tables
	 needed for bidi iteration are not yet available.  */
      || redisplay__inhibit_bidi)
    return Qleft_to_right;
  else if (!NILP (BVAR (buf, bidi_paragraph_direction)))
    return BVAR (buf, bidi_paragraph_direction);
  else
    {
      /* Determine the direction from buffer text.  We could try to
	 use current_matrix if it is up to date, but this seems fast
	 enough as it is.  */
      struct bidi_it itb;
      ptrdiff_t pos = BUF_PT (buf);
      ptrdiff_t bytepos = BUF_PT_BYTE (buf);
      int c;
      void *itb_data = bidi_shelve_cache ();

      set_buffer_temp (buf);
      /* bidi_paragraph_init finds the base direction of the paragraph
	 by searching forward from paragraph start.  We need the base
	 direction of the current or _previous_ paragraph, so we need
	 to make sure we are within that paragraph.  To that end, find
	 the previous non-empty line.  */
      if (pos >= ZV && pos > BEGV)
	dec_both (&pos, &bytepos);
      AUTO_STRING (trailing_white_space, "[\f\t ]*\n");
      if (fast_looking_at (trailing_white_space,
			   pos, bytepos, ZV, ZV_BYTE, Qnil) > 0)
	{
	  while ((c = FETCH_BYTE (bytepos)) == '\n'
		 || c == ' ' || c == '\t' || c == '\f')
	    {
	      if (bytepos <= BEGV_BYTE)
		break;
	      bytepos--;
	      pos--;
	    }
	  while (!CHAR_HEAD_P (FETCH_BYTE (bytepos)))
	    bytepos--;
	}
      bidi_init_it (pos, bytepos, FRAME_WINDOW_P (SELECTED_FRAME ()), &itb);
      itb.paragraph_dir = NEUTRAL_DIR;
      itb.string.s = NULL;
      itb.string.lstring = Qnil;
      itb.string.bufpos = 0;
      itb.string.from_disp_str = false;
      itb.string.unibyte = false;
      /* We have no window to use here for ignoring window-specific
	 overlays.  Using NULL for window pointer will cause
	 compute_display_string_pos to use the current buffer.  */
      itb.w = NULL;
      bidi_paragraph_init (NEUTRAL_DIR, &itb, true);
      bidi_unshelve_cache (itb_data, false);
      set_buffer_temp (old);
      switch (itb.paragraph_dir)
	{
	case L2R:
	  return Qleft_to_right;
	  break;
	case R2L:
	  return Qright_to_left;
	  break;
	default:
	  emacs_abort ();
	}
    }
}