Beispiel #1
0
EMACS_INT
buf_bytepos_to_charpos (struct buffer *b, EMACS_INT bytepos)
{
  struct Lisp_Marker *tail;
  EMACS_INT best_above, best_above_byte;
  EMACS_INT best_below, best_below_byte;

  if (bytepos < BUF_BEG_BYTE (b) || bytepos > BUF_Z_BYTE (b))
    abort ();

  best_above = BUF_Z (b);
  best_above_byte = BUF_Z_BYTE (b);

  /* If this buffer has as many characters as bytes,
     each character must be one byte.
     This takes care of the case where enable-multibyte-characters is nil.  */
  if (best_above == best_above_byte)
    return bytepos;

  best_below = BEG;
  best_below_byte = BEG_BYTE;

  CONSIDER (BUF_PT_BYTE (b), BUF_PT (b));
  CONSIDER (BUF_GPT_BYTE (b), BUF_GPT (b));
  CONSIDER (BUF_BEGV_BYTE (b), BUF_BEGV (b));
  CONSIDER (BUF_ZV_BYTE (b), BUF_ZV (b));

  if (b == cached_buffer && BUF_MODIFF (b) == cached_modiff)
    CONSIDER (cached_bytepos, cached_charpos);

  for (tail = BUF_MARKERS (b); tail; tail = tail->next)
    {
      CONSIDER (tail->bytepos, tail->charpos);

      /* If we are down to a range of 50 chars,
	 don't bother checking any other markers;
	 scan the intervening chars directly now.  */
      if (best_above - best_below < 50)
	break;
    }

  /* We get here if we did not exactly hit one of the known places.
     We have one known above and one known below.
     Scan, counting characters, from whichever one is closer.  */

  if (bytepos - best_below_byte < best_above_byte - bytepos)
    {
      int record = bytepos - best_below_byte > 5000;

      while (best_below_byte < bytepos)
	{
	  best_below++;
	  BUF_INC_POS (b, best_below_byte);
	}

      /* If this position is quite far from the nearest known position,
	 cache the correspondence by creating a marker here.
	 It will last until the next GC.
	 But don't do it if BUF_MARKERS is nil;
	 that is a signal from Fset_buffer_multibyte.  */
      if (record && BUF_MARKERS (b))
	{
	  Lisp_Object marker, buffer;
	  marker = Fmake_marker ();
	  XSETBUFFER (buffer, b);
	  set_marker_both (marker, buffer, best_below, best_below_byte);
	}

      if (byte_debug_flag)
	byte_char_debug_check (b, best_below, bytepos);

      cached_buffer = b;
      cached_modiff = BUF_MODIFF (b);
      cached_charpos = best_below;
      cached_bytepos = best_below_byte;

      return best_below;
    }
  else
    {
      int record = best_above_byte - bytepos > 5000;

      while (best_above_byte > bytepos)
	{
	  best_above--;
	  BUF_DEC_POS (b, best_above_byte);
	}

      /* If this position is quite far from the nearest known position,
	 cache the correspondence by creating a marker here.
	 It will last until the next GC.
	 But don't do it if BUF_MARKERS is nil;
	 that is a signal from Fset_buffer_multibyte.  */
      if (record && BUF_MARKERS (b))
	{
	  Lisp_Object marker, buffer;
	  marker = Fmake_marker ();
	  XSETBUFFER (buffer, b);
	  set_marker_both (marker, buffer, best_above, best_above_byte);
	}

      if (byte_debug_flag)
	byte_char_debug_check (b, best_above, bytepos);

      cached_buffer = b;
      cached_modiff = BUF_MODIFF (b);
      cached_charpos = best_above;
      cached_bytepos = best_above_byte;

      return best_above;
    }
}
Beispiel #2
0
ptrdiff_t
buf_charpos_to_bytepos (struct buffer *b, ptrdiff_t charpos)
{
    struct Lisp_Marker *tail;
    ptrdiff_t best_above, best_above_byte;
    ptrdiff_t best_below, best_below_byte;

    eassert (BUF_BEG (b) <= charpos && charpos <= BUF_Z (b));

    best_above = BUF_Z (b);
    best_above_byte = BUF_Z_BYTE (b);

    /* If this buffer has as many characters as bytes,
       each character must be one byte.
       This takes care of the case where enable-multibyte-characters is nil.  */
    if (best_above == best_above_byte)
        return charpos;

    best_below = BEG;
    best_below_byte = BEG_BYTE;

    /* We find in best_above and best_above_byte
       the closest known point above CHARPOS,
       and in best_below and best_below_byte
       the closest known point below CHARPOS,

       If at any point we can tell that the space between those
       two best approximations is all single-byte,
       we interpolate the result immediately.  */

    CONSIDER (BUF_PT (b), BUF_PT_BYTE (b));
    CONSIDER (BUF_GPT (b), BUF_GPT_BYTE (b));
    CONSIDER (BUF_BEGV (b), BUF_BEGV_BYTE (b));
    CONSIDER (BUF_ZV (b), BUF_ZV_BYTE (b));

    if (b == cached_buffer && BUF_MODIFF (b) == cached_modiff)
        CONSIDER (cached_charpos, cached_bytepos);

    for (tail = BUF_MARKERS (b); tail; tail = tail->next)
    {
        CONSIDER (tail->charpos, tail->bytepos);

        /* If we are down to a range of 50 chars,
        don't bother checking any other markers;
         scan the intervening chars directly now.  */
        if (best_above - best_below < 50)
            break;
    }

    /* We get here if we did not exactly hit one of the known places.
       We have one known above and one known below.
       Scan, counting characters, from whichever one is closer.  */

    if (charpos - best_below < best_above - charpos)
    {
        bool record = charpos - best_below > 5000;

        while (best_below != charpos)
        {
            best_below++;
            BUF_INC_POS (b, best_below_byte);
        }

        /* If this position is quite far from the nearest known position,
        cache the correspondence by creating a marker here.
         It will last until the next GC.  */
        if (record)
            build_marker (b, best_below, best_below_byte);

        byte_char_debug_check (b, best_below, best_below_byte);

        cached_buffer = b;
        cached_modiff = BUF_MODIFF (b);
        cached_charpos = best_below;
        cached_bytepos = best_below_byte;

        return best_below_byte;
    }
    else
    {
        bool record = best_above - charpos > 5000;

        while (best_above != charpos)
        {
            best_above--;
            BUF_DEC_POS (b, best_above_byte);
        }

        /* If this position is quite far from the nearest known position,
        cache the correspondence by creating a marker here.
         It will last until the next GC.  */
        if (record)
            build_marker (b, best_above, best_above_byte);

        byte_char_debug_check (b, best_above, best_above_byte);

        cached_buffer = b;
        cached_modiff = BUF_MODIFF (b);
        cached_charpos = best_above;
        cached_bytepos = best_above_byte;

        return best_above_byte;
    }
}