Exemplo n.º 1
0
/* Calculate the line number in buffer B at position POS.  If CACHEP
   is non-zero, initialize and facilitate the line-number cache.  The
   line number of the first line is 0.  If narrowing is in effect,
   count the lines are counted from the beginning of the visible
   portion of the buffer.

   The cache works as follows: To calculate the line number, we need
   two positions: position of point (POS) and the position from which
   to count newlines (BEG).  We start by setting BEG to BUF_BEGV.  If
   this would require too much searching (i.e. pos - BUF_BEGV >
   LINE_NUMBER_FAR), try to find a closer position in the ring.  If it
   is found, use that position for BEG, and increment the line number
   appropriately.

   If the calculation (with or without the cache lookup) required more
   than LINE_NUMBER_FAR characters of traversal, update the cache.  */
EMACS_INT
buffer_line_number (struct buffer *b, Charbpos pos, Boolint cachep,
                    Boolint respect_narrowing)
{
  Charbpos beg = respect_narrowing ? BUF_BEGV (b) : BUF_BEG (b);
  EMACS_INT cached_lines = 0;
  EMACS_INT shortage, line;

  if ((pos > beg ? pos - beg : beg - pos) <= LINE_NUMBER_FAR)
    cachep = 0;

  if (cachep && (respect_narrowing || BUF_BEG (b) == BUF_BEGV (b)))
    {
      if (NILP (b->text->line_number_cache))
	allocate_line_number_cache (b);
      /* If we don't know the line number of BUF_BEGV, calculate it now.  */
      if (XFIXNUM (LINE_NUMBER_BEGV (b)) == -1)
	{
	  LINE_NUMBER_BEGV (b) = Qzero;
	  /* #### This has a side-effect of changing the cache.  */
	  LINE_NUMBER_BEGV (b) =
	    make_fixnum (buffer_line_number (b, BUF_BEGV (b), 1, 0));
	}
      cached_lines = XFIXNUM (LINE_NUMBER_BEGV (b));
      get_nearest_line_number (b, &beg, pos, &cached_lines);
    }

  scan_buffer (b, '\n', beg, pos,
               pos > beg ? MOST_POSITIVE_FIXNUM : -MOST_POSITIVE_FIXNUM,
	       &shortage, 0);

  line = MOST_POSITIVE_FIXNUM - shortage;
  if (beg > pos)
    line = -line;
  line += cached_lines;

  if (cachep && (respect_narrowing || BUF_BEG (b) == BUF_BEGV (b)))
    {
      /* If too far, update the cache. */
      if ((pos > beg ? pos - beg : beg - pos) > LINE_NUMBER_FAR)
	add_position_to_cache (b, pos, line);
      /* Account for narrowing.  If cache is not used, this is
	 unnecessary, because we counted from BUF_BEGV anyway.  */
      line -= XFIXNUM (LINE_NUMBER_BEGV (b));
    }

  return line;
}
Exemplo n.º 2
0
/* Match the buffer text against names of symbols in obarray.  Returns
   the matching symbol, or 0 if not found.  */
static Lisp_Symbol *abbrev_match(struct buffer *buf, Lisp_Object obarray)
{
	struct abbrev_match_mapper_closure closure;

	/* Precalculate some stuff, so mapper function needn't to it in each
	   iteration.  */
	closure.buf = buf;
	closure.point = BUF_PT(buf);
	closure.maxlen = closure.point - BUF_BEGV(buf);
	closure.chartab = XCHAR_TABLE(buf->mirror_syntax_table);
	closure.found = 0;

	map_obarray(obarray, abbrev_match_mapper, &closure);

	return closure.found;
}
Exemplo n.º 3
0
/* Flag LINE_NUMBER_BEGV (b) as dirty.  Do it only if the line number
   cache is already initialized.  */
void
narrow_line_number_cache (struct buffer *b)
{
  if (NILP (b->text->line_number_cache))
    return;

  if (BUF_BEG (b) == BUF_BEGV (b))
    /* The is the case Fwiden and save_restriction_restore.  Since we
       know the correct value, we can update it now.  */
    LINE_NUMBER_BEGV (b) = Qzero;
  else
    /* Calculating the line number of BUF_BEGV here is a bad idea,
       because there is absolutely no reason to do it before the next
       redisplay.  We simply mark it as dirty instead.  */
    LINE_NUMBER_BEGV (b) = make_fixnum (-1);
}
Exemplo n.º 4
0
static Bufpos
beginning_of_defun (struct buffer *buf, Bufpos pt)
{
  /* This function can GC */
  Bufpos opt = BUF_PT (buf);
  if (pt == BUF_BEGV (buf))
    return pt;
  BUF_SET_PT (buf, pt);
  /* There used to be some kludginess to call c++-beginning-of-defun
     if we're in C++ mode.  There's no point in this any more;
     we're using cc-mode.  If you really want to get the old c++
     mode working, fix it rather than the C code. */
  call0_in_buffer (buf, Qbeginning_of_defun);
  pt = BUF_PT (buf);
  BUF_SET_PT (buf, opt);
  return pt;
}
Exemplo n.º 5
0
int
update_window_fringes (struct window *w, int keep_current_p)
{
  struct glyph_row *row, *cur = 0;
  int yb = window_text_bottom_y (w);
  int rn, nrows = w->current_matrix->nrows;
  int y;
  int redraw_p = 0;
  Lisp_Object boundary_top = Qnil, boundary_bot = Qnil;
  Lisp_Object arrow_top = Qnil, arrow_bot = Qnil;
  Lisp_Object empty_pos;
  Lisp_Object ind = Qnil;
#define MAX_BITMAP_CACHE (8*4)
  int bitmap_cache[MAX_BITMAP_CACHE];
  int top_ind_rn, bot_ind_rn;
  int top_ind_min_y, bot_ind_max_y;

  /* top_ind_rn is set to a nonnegative value whenver
     row->indicate_bob_p is set, so it's OK that top_row_ends_at_zv_p
     is not initialized here.  Similarly for bot_ind_rn,
     row->indicate_eob_p and bot_row_ends_at_zv_p.  */
  int top_row_ends_at_zv_p IF_LINT (= 0), bot_row_ends_at_zv_p IF_LINT (= 0);

  if (w->pseudo_window_p)
    return 0;

  if (!MINI_WINDOW_P (w)
      && (ind = BVAR (XBUFFER (w->buffer), indicate_buffer_boundaries), !NILP (ind)))
    {
      if (EQ (ind, Qleft) || EQ (ind, Qright))
	boundary_top = boundary_bot = arrow_top = arrow_bot = ind;
      else if (CONSP (ind) && CONSP (XCAR (ind)))
	{
	  Lisp_Object pos;
	  if (pos = Fassq (Qt, ind), !NILP (pos))
	    boundary_top = boundary_bot = arrow_top = arrow_bot = XCDR (pos);
	  if (pos = Fassq (Qtop, ind), !NILP (pos))
	    boundary_top = XCDR (pos);
	  if (pos = Fassq (Qbottom, ind), !NILP (pos))
	    boundary_bot = XCDR (pos);
	  if (pos = Fassq (Qup, ind), !NILP (pos))
	    arrow_top = XCDR (pos);
	  if (pos = Fassq (Qdown, ind), !NILP (pos))
	    arrow_bot = XCDR (pos);
	}
      else
	/* Anything else means boundary on left and no arrows.  */
	boundary_top = boundary_bot = Qleft;
    }

  top_ind_rn = bot_ind_rn = -1;
  if (!NILP (ind))
    {
      for (y = w->vscroll, rn = 0;
	   y < yb && rn < nrows;
	   y += row->height, ++rn)
	{
	  row = w->desired_matrix->rows + rn;
	  if (!row->enabled_p)
	    row = w->current_matrix->rows + rn;

	  row->indicate_bob_p = row->indicate_top_line_p = 0;
	  row->indicate_eob_p = row->indicate_bottom_line_p = 0;

	  if (!row->mode_line_p)
	    {
	      if (top_ind_rn < 0 && row->visible_height > 0)
		{
		  if (MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->buffer))
		      && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
		    row->indicate_bob_p = !NILP (boundary_top);
		  else
		    row->indicate_top_line_p = !NILP (arrow_top);
		  top_ind_rn = rn;
		}

	      if (bot_ind_rn < 0)
		{
		  if (MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->buffer))
		      && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row))
		    row->indicate_eob_p = !NILP (boundary_bot), bot_ind_rn = rn;
		  else if (y + row->height >= yb)
		    row->indicate_bottom_line_p = !NILP (arrow_bot), bot_ind_rn = rn;
		}
	    }
	}
    }

  empty_pos = BVAR (XBUFFER (w->buffer), indicate_empty_lines);
  if (!NILP (empty_pos) && !EQ (empty_pos, Qright))
    empty_pos = WINDOW_LEFT_FRINGE_WIDTH (w) == 0 ? Qright : Qleft;

  for (y = 0; y < MAX_BITMAP_CACHE; y++)
    bitmap_cache[y] = -1;

#define LEFT_FRINGE(cache, which, partial_p)			\
  (bitmap_cache[cache*4+partial_p] >= 0				\
   ? bitmap_cache[cache*4+partial_p]				\
   : (bitmap_cache[cache*4+partial_p] =				\
      get_logical_fringe_bitmap (w, which, 0, partial_p)))

#define RIGHT_FRINGE(cache, which, partial_p)			\
  (bitmap_cache[cache*4+2+partial_p] >= 0			\
   ? bitmap_cache[cache*4+2+partial_p]				\
   : (bitmap_cache[cache*4+2+partial_p] =			\
      get_logical_fringe_bitmap (w, which, 1, partial_p)))


  /* Extend top-aligned top indicator (or bottom-aligned bottom
     indicator) to adjacent rows if it doesn't fit in one row.  */
  top_ind_min_y = bot_ind_max_y = -1;
  if (top_ind_rn >= 0)
    {
      int bn = NO_FRINGE_BITMAP;

      row = w->desired_matrix->rows + top_ind_rn;
      if (!row->enabled_p)
	row = w->current_matrix->rows + top_ind_rn;

      top_row_ends_at_zv_p = row->ends_at_zv_p;
      if (row->indicate_bob_p)
	{
	  if (EQ (boundary_top, Qleft))
	    bn = ((row->indicate_eob_p && EQ (boundary_bot, Qleft))
		  ? LEFT_FRINGE (1, Qtop_bottom, row->ends_at_zv_p)
		  : LEFT_FRINGE (2, Qtop, 0));
	  else
	    bn = ((row->indicate_eob_p && EQ (boundary_bot, Qright))
		  ? RIGHT_FRINGE (1, Qtop_bottom, row->ends_at_zv_p)
		  : RIGHT_FRINGE (2, Qtop, 0));
	}
      else if (row->indicate_top_line_p)
	{
	  if (EQ (arrow_top, Qleft))
	    bn = LEFT_FRINGE (6, Qup, 0);
	  else
	    bn = RIGHT_FRINGE (6, Qup, 0);
	}

      if (bn != NO_FRINGE_BITMAP)
	{
	  struct fringe_bitmap *fb = get_fringe_bitmap_data (bn);

	  if (fb->align == ALIGN_BITMAP_TOP && fb->period == 0)
	    {
	      struct glyph_row *row1;
	      int top_ind_max_y;

	      top_ind_min_y = WINDOW_HEADER_LINE_HEIGHT (w);
	      top_ind_max_y = top_ind_min_y + fb->height;
	      if (top_ind_max_y > yb)
		top_ind_max_y = yb;

	      for (y = row->y + row->height, rn = top_ind_rn + 1;
		   y < top_ind_max_y && rn < nrows;
		   y += row1->height, rn++)
		{
		  if (bot_ind_rn >= 0 && rn >= bot_ind_rn)
		    break;

		  row1 = w->desired_matrix->rows + rn;
		  if (!row1->enabled_p)
		    row1 = w->current_matrix->rows + rn;

		  row1->indicate_bob_p = row->indicate_bob_p;
		  row1->indicate_top_line_p = row->indicate_top_line_p;
		}
	    }
	}
    }
  if (bot_ind_rn >= 0)
    {
      int bn = NO_FRINGE_BITMAP;

      row = w->desired_matrix->rows + bot_ind_rn;
      if (!row->enabled_p)
	row = w->current_matrix->rows + bot_ind_rn;

      bot_row_ends_at_zv_p = row->ends_at_zv_p;
      if (row->indicate_eob_p)
	{
	  if (EQ (boundary_bot, Qleft))
	    bn = LEFT_FRINGE (3, Qbottom, row->ends_at_zv_p);
	  else
	    bn = RIGHT_FRINGE (3, Qbottom, row->ends_at_zv_p);
	}
      else if (row->indicate_bottom_line_p)
	{
	  if (EQ (arrow_bot, Qleft))
	    bn = LEFT_FRINGE (7, Qdown, 0);
	  else
	    bn = RIGHT_FRINGE (7, Qdown, 0);
	}

      if (bn != NO_FRINGE_BITMAP)
	{
	  struct fringe_bitmap *fb = get_fringe_bitmap_data (bn);

	  if (fb->align == ALIGN_BITMAP_BOTTOM && fb->period == 0)
	    {
	      struct glyph_row *row1;
	      int bot_ind_min_y;

	      bot_ind_max_y = row->y + row->visible_height;
	      bot_ind_min_y = bot_ind_max_y - fb->height;
	      if (bot_ind_min_y < WINDOW_HEADER_LINE_HEIGHT (w))
		bot_ind_min_y = WINDOW_HEADER_LINE_HEIGHT (w);

	      for (y = row->y, rn = bot_ind_rn - 1;
		   y >= bot_ind_min_y && rn >= 0;
		   y -= row1->height, rn--)
		{
		  if (top_ind_rn >= 0 && rn <= top_ind_rn)
		    break;

		  row1 = w->desired_matrix->rows + rn;
		  if (!row1->enabled_p)
		    row1 = w->current_matrix->rows + rn;

		  row1->indicate_eob_p = row->indicate_eob_p;
		  row1->indicate_bottom_line_p = row->indicate_bottom_line_p;
		}
	    }
	}
    }

  for (y = w->vscroll, rn = 0;
       y < yb && rn < nrows;
       y += row->height, rn++)
    {
      int left, right;
      unsigned left_face_id, right_face_id;
      int left_offset, right_offset;
      int periodic_p;

      row = w->desired_matrix->rows + rn;
      cur = w->current_matrix->rows + rn;
      if (!row->enabled_p)
	row = cur;

      left_face_id = right_face_id = DEFAULT_FACE_ID;
      left_offset = right_offset = 0;
      periodic_p = 0;

      /* Decide which bitmap to draw in the left fringe.  */
      if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
	left = NO_FRINGE_BITMAP;
      else if (row->left_user_fringe_bitmap != NO_FRINGE_BITMAP)
	{
	  left = row->left_user_fringe_bitmap;
	  left_face_id = row->left_user_fringe_face_id;
	}
      else if ((!row->reversed_p && row->truncated_on_left_p)
	       || (row->reversed_p && row->truncated_on_right_p))
	left = LEFT_FRINGE (0, Qtruncation, 0);
      else if (row->indicate_bob_p && EQ (boundary_top, Qleft))
	{
	  left = ((row->indicate_eob_p && EQ (boundary_bot, Qleft))
		  ? LEFT_FRINGE (1, Qtop_bottom, top_row_ends_at_zv_p)
		  : LEFT_FRINGE (2, Qtop, 0));
	  if (top_ind_min_y >= 0)
	    left_offset = top_ind_min_y - row->y;
	}
      else if (row->indicate_eob_p && EQ (boundary_bot, Qleft))
	{
	  left = LEFT_FRINGE (3, Qbottom, bot_row_ends_at_zv_p);
	  if (bot_ind_max_y >= 0)
	    left_offset = bot_ind_max_y - (row->y + row->visible_height);
	}
      else if ((!row->reversed_p && MATRIX_ROW_CONTINUATION_LINE_P (row))
	       || (row->reversed_p && row->continued_p))
	left = LEFT_FRINGE (4, Qcontinuation, 0);
      else if (row->indicate_empty_line_p && EQ (empty_pos, Qleft))
	left = LEFT_FRINGE (5, Qempty_line, 0);
      else if (row->indicate_top_line_p && EQ (arrow_top, Qleft))
	{
	  left = LEFT_FRINGE (6, Qup, 0);
	  if (top_ind_min_y >= 0)
	    left_offset = top_ind_min_y - row->y;
	}
      else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qleft))
	{
	  left = LEFT_FRINGE (7, Qdown, 0);
	  if (bot_ind_max_y >= 0)
	    left_offset = bot_ind_max_y - (row->y + row->visible_height);
	}
      else
	left = NO_FRINGE_BITMAP;

      /* Decide which bitmap to draw in the right fringe.  */
      if (WINDOW_RIGHT_FRINGE_WIDTH (w) == 0)
	right = NO_FRINGE_BITMAP;
      else if (row->right_user_fringe_bitmap != NO_FRINGE_BITMAP)
	{
	  right = row->right_user_fringe_bitmap;
	  right_face_id = row->right_user_fringe_face_id;
	}
      else if ((!row->reversed_p && row->truncated_on_right_p)
	       || (row->reversed_p && row->truncated_on_left_p))
	right = RIGHT_FRINGE (0, Qtruncation, 0);
      else if (row->indicate_bob_p && EQ (boundary_top, Qright))
	{
	  right = ((row->indicate_eob_p && EQ (boundary_bot, Qright))
		   ? RIGHT_FRINGE (1, Qtop_bottom, top_row_ends_at_zv_p)
		   : RIGHT_FRINGE (2, Qtop, 0));
	  if (top_ind_min_y >= 0)
	    right_offset = top_ind_min_y - row->y;
	}
      else if (row->indicate_eob_p && EQ (boundary_bot, Qright))
	{
	  right = RIGHT_FRINGE (3, Qbottom, bot_row_ends_at_zv_p);
	  if (bot_ind_max_y >= 0)
	    right_offset = bot_ind_max_y - (row->y + row->visible_height);
	}
      else if ((!row->reversed_p && row->continued_p)
	       || (row->reversed_p && MATRIX_ROW_CONTINUATION_LINE_P (row)))
	right = RIGHT_FRINGE (4, Qcontinuation, 0);
      else if (row->indicate_top_line_p && EQ (arrow_top, Qright))
	{
	  right = RIGHT_FRINGE (6, Qup, 0);
	  if (top_ind_min_y >= 0)
	    right_offset = top_ind_min_y - row->y;
	}
      else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qright))
	{
	  right = RIGHT_FRINGE (7, Qdown, 0);
	  if (bot_ind_max_y >= 0)
	    right_offset = bot_ind_max_y - (row->y + row->visible_height);
	}
      else if (row->indicate_empty_line_p && EQ (empty_pos, Qright))
	right = RIGHT_FRINGE (5, Qempty_line, 0);
      else
	right = NO_FRINGE_BITMAP;

      periodic_p = (get_fringe_bitmap_data (left)->period != 0
		    || get_fringe_bitmap_data (right)->period != 0);

      if (row->y != cur->y
	  || row->visible_height != cur->visible_height
	  || row->ends_at_zv_p != cur->ends_at_zv_p
	  || left != cur->left_fringe_bitmap
	  || right != cur->right_fringe_bitmap
	  || left_face_id != cur->left_fringe_face_id
	  || right_face_id != cur->right_fringe_face_id
	  || left_offset != cur->left_fringe_offset
	  || right_offset != cur->right_fringe_offset
	  || periodic_p != cur->fringe_bitmap_periodic_p
	  || cur->redraw_fringe_bitmaps_p)
	{
	  redraw_p = row->redraw_fringe_bitmaps_p = 1;
	  if (!keep_current_p)
	    {
	      cur->redraw_fringe_bitmaps_p = 1;
	      cur->left_fringe_bitmap = left;
	      cur->right_fringe_bitmap = right;
	      cur->left_fringe_face_id = left_face_id;
	      cur->right_fringe_face_id = right_face_id;
	      cur->left_fringe_offset = left_offset;
	      cur->right_fringe_offset = right_offset;
	      cur->fringe_bitmap_periodic_p = periodic_p;
	    }
	}

      if (row->overlay_arrow_bitmap < 0)
	row->overlay_arrow_bitmap = get_logical_fringe_bitmap (w, Qoverlay_arrow, 0, 0);

      if (row->overlay_arrow_bitmap != cur->overlay_arrow_bitmap)
	{
	  redraw_p = row->redraw_fringe_bitmaps_p = 1;
	  if (!keep_current_p)
	    {
	      cur->redraw_fringe_bitmaps_p = 1;
	      cur->overlay_arrow_bitmap = row->overlay_arrow_bitmap;
	    }
	}

      row->left_fringe_bitmap = left;
      row->right_fringe_bitmap = right;
      row->left_fringe_face_id = left_face_id;
      row->right_fringe_face_id = right_face_id;
      row->left_fringe_offset = left_offset;
      row->right_fringe_offset = right_offset;
      row->fringe_bitmap_periodic_p = periodic_p;
    }

  return redraw_p && !keep_current_p;
}
Exemplo n.º 6
0
static void
find_context (struct buffer *buf, Bufpos pt)
{
  /* This function can GC */
#ifndef emacs
#ifdef UTF2000
  Lisp_Char_Table *mirrortab = XCHAR_TABLE (buf->syntax_table);
#else
  Lisp_Char_Table *mirrortab = XCHAR_TABLE (buf->mirror_syntax_table);
#endif
  Lisp_Object syntaxtab = buf->syntax_table;
#endif
  Emchar prev_c, c;
  int prev_syncode, syncode;
  Bufpos target = pt;
  setup_context_cache (buf, pt);
  pt = context_cache.cur_point;

  SCS_STATISTICS_SET_FUNCTION (scs_find_context);
  SETUP_SYNTAX_CACHE (pt - 1, 1);
  if (pt > BUF_BEGV (buf))
    {
      c = BUF_FETCH_CHAR (buf, pt - 1);
      syncode = SYNTAX_CODE_FROM_CACHE (mirrortab, c);
    }
  else
    {
      c = '\n'; /* to get bol_context_cache at point-min */
      syncode = Swhitespace;
    }

  for (; pt < target; pt++, context_cache.cur_point = pt)
    {
      if (context_cache.needs_its_head_reexamined)
	{
	  if (context_cache.depth == 0
	      && context_cache.context == context_none)
	    {
	      /* We've found an anchor spot.
		 Try to put the start of defun within 6000 chars of
		 the target, and the end of defun as close as possible.
		 6000 is also arbitrary but tries to strike a balance
		 between two conflicting pulls when dealing with a
		 file that has lots of stuff sitting outside of a top-
		 level form:

		 a) If you move past the start of defun, you will
		    have to recompute defun, which in this case
		    means that start of defun goes all the way back
		    to the beginning of the file; so you want
		    to set start of defun a ways back from the
		    current point.
		 b) If you move a line backwards but within start of
		    defun, you have to move back to start of defun;
		    so you don't want start of defun too far from
		    the current point.
		 */
	      if (target - context_cache.start_point > 6000)
		context_cache.start_point = pt;
	      context_cache.end_point = pt;
	      bol_context_cache = context_cache;
	    }
	}

      UPDATE_SYNTAX_CACHE_FORWARD (pt);
      prev_c = c;
      prev_syncode = syncode;
      c = BUF_FETCH_CHAR (buf, pt);
      syncode = SYNTAX_CODE_FROM_CACHE (mirrortab, c);

      if (prev_c == '\n')
	bol_context_cache = context_cache;

      if (context_cache.backslash_p)
	{
	  context_cache.backslash_p = 0;
	  continue;
	}

      switch (SYNTAX_FROM_CACHE (mirrortab, c))
	{
	case Sescape:
	  context_cache.backslash_p = 1;
	  break;

	case Sopen:
	  if (context_cache.context == context_none)
	    context_cache.depth++;
	  break;

	case Sclose:
	  if (context_cache.context == context_none)
	    context_cache.depth--;
	  break;

	case Scomment:
	  if (context_cache.context == context_none)
	    {
	      context_cache.context = context_comment;
	      context_cache.ccontext = ccontext_none;
	      context_cache.style = SINGLE_SYNTAX_STYLE (syncode);
	      if (context_cache.style == comment_style_none) ABORT ();
	    }
	  break;

	case Sendcomment:
	  if (context_cache.style != SINGLE_SYNTAX_STYLE (syncode))
	    ;
	  else if (context_cache.context == context_comment)
	    {
	      context_cache.context = context_none;
	      context_cache.style = comment_style_none;
	    }
	  else if (context_cache.context == context_block_comment &&
		   (context_cache.ccontext == ccontext_start2 ||
		    context_cache.ccontext == ccontext_end1))
	    {
	      context_cache.context = context_none;
	      context_cache.ccontext = ccontext_none;
	      context_cache.style = comment_style_none;
	    }
	  break;

	case Sstring:
          {
            if (context_cache.context == context_string &&
                context_cache.scontext == c)
	      {
		context_cache.context = context_none;
		context_cache.scontext = '\000';
	      }
            else if (context_cache.context == context_none)
	      {
		Lisp_Object stringtermobj =
		  syntax_match (syntax_cache.current_syntax_table, c);
		Emchar stringterm;

		if (CHARP (stringtermobj))
		  stringterm = XCHAR (stringtermobj);
		else
		  stringterm = c;
		context_cache.context = context_string;
		context_cache.scontext = stringterm;
		context_cache.ccontext = ccontext_none;
	      }
            break;
          }

	case Scomment_fence:
	  {
	    if (context_cache.context == context_generic_comment)
	      {
		context_cache.context = context_none;
	      }
	    else if (context_cache.context == context_none)
	      {
		context_cache.context = context_generic_comment;
		context_cache.ccontext = ccontext_none;
	      }
	    break;
	  }

	case Sstring_fence:
	  {
	    if (context_cache.context == context_generic_string)
	      {
		context_cache.context = context_none;
	      }
	    else if (context_cache.context == context_none)
	      {
		context_cache.context = context_generic_string;
		context_cache.ccontext = ccontext_none;
	      }
	    break;
	  }

	default:
	  ;
	}

      /* That takes care of the characters with manifest syntax.
	 Now we've got to hack multi-char sequences that start
	 and end block comments.
       */
      if ((SYNTAX_CODE_COMMENT_BITS (syncode) &
	   SYNTAX_SECOND_CHAR_START) &&
	  context_cache.context == context_none &&
	  context_cache.ccontext == ccontext_start1 &&
	  SYNTAX_CODES_START_P (prev_syncode, syncode) /* the two chars match */
	  )
	{
	  context_cache.ccontext = ccontext_start2;
	  context_cache.style = SYNTAX_START_STYLE (prev_syncode, syncode);
	  if (context_cache.style == comment_style_none) ABORT ();
	}
      else if ((SYNTAX_CODE_COMMENT_BITS (syncode) &
		SYNTAX_FIRST_CHAR_START) &&
	       context_cache.context == context_none &&
	       (context_cache.ccontext == ccontext_none ||
		context_cache.ccontext == ccontext_start1))
	{
	  context_cache.ccontext = ccontext_start1;
	  context_cache.style = comment_style_none; /* should be this already*/
	}
      else if ((SYNTAX_CODE_COMMENT_BITS (syncode) &
		SYNTAX_SECOND_CHAR_END) &&
	       context_cache.context == context_block_comment &&
	       context_cache.ccontext == ccontext_end1 &&
	       SYNTAX_CODES_END_P (prev_syncode, syncode) &&
	       /* the two chars match */
	       context_cache.style ==
	       SYNTAX_END_STYLE (prev_syncode, syncode)
	       )
	{
	  context_cache.context = context_none;
	  context_cache.ccontext = ccontext_none;
	  context_cache.style = comment_style_none;
	}
      else if ((SYNTAX_CODE_COMMENT_BITS (syncode) &
		SYNTAX_FIRST_CHAR_END) &&
	       context_cache.context == context_block_comment &&
#if 0
	       /* #### pre-Matt code had: */
	       (context_cache.style ==
		SYNTAX_END_STYLE (c, BUF_FETCH_CHAR (buf, pt+1))) &&
	       /* why do these differ here?! */
#endif
	       context_cache.style == SINGLE_SYNTAX_STYLE (syncode) &&
	       (context_cache.ccontext == ccontext_start2 ||
		context_cache.ccontext == ccontext_end1))
	/* check end1, to detect a repetition of the first char of a
	   comment-end sequence. ie, '/xxx foo xxx/' or '/xxx foo x/',
	   where 'x' = '*' -- mct */
	{
	  if (context_cache.style == comment_style_none) ABORT ();
	  context_cache.ccontext = ccontext_end1;
	}

      else if (context_cache.ccontext == ccontext_start1)
	{
	  if (context_cache.context != context_none) ABORT ();
	  context_cache.ccontext = ccontext_none;
	}
      else if (context_cache.ccontext == ccontext_end1)
	{
	  if (context_cache.context != context_block_comment) ABORT ();
	  context_cache.context = context_none;
	  context_cache.ccontext = ccontext_start2;
	}

      if (context_cache.ccontext == ccontext_start2 &&
	  context_cache.context == context_none)
	{
	  context_cache.context = context_block_comment;
	  if (context_cache.style == comment_style_none) ABORT ();
	}
      else if (context_cache.ccontext == ccontext_none &&
	       context_cache.context == context_block_comment)
	{
	  context_cache.context = context_none;
	}
    }

  context_cache.needs_its_head_reexamined = 0;
}
Exemplo n.º 7
0
int
column_at_point (struct buffer *buf, Bufpos init_pos, int cur_col)
{
  int col;
  int tab_seen;
  int tab_width = XINT (buf->tab_width);
  int post_tab;
  Bufpos pos = init_pos;
  Emchar c;

  if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
  col = tab_seen = post_tab = 0;

  while (1)
    {
      if (pos <= BUF_BEGV (buf))
	break;

      pos--;
      c = BUF_FETCH_CHAR (buf, pos);
      if (c == '\t')
	{
	  if (tab_seen)
	    col = ((col + tab_width) / tab_width) * tab_width;

	  post_tab += col;
	  col = 0;
	  tab_seen = 1;
	}
      else if (c == '\n' ||
	       (EQ (buf->selective_display, Qt) && c == '\r'))
	break;
      else
	{
	  /* #### This needs updating to handle the new redisplay. */
	  /* #### FSFmacs looks at ctl_arrow, display tables.
	     We need to do similar. */
#if 0
	  displayed_glyphs = glyphs_from_bufpos (sel_frame, buf,
						 XWINDOW (selected_window),
						 pos, dp, 0, col, 0, 0, 0);
	  col += (displayed_glyphs->columns
		  - (displayed_glyphs->begin_columns
		     + displayed_glyphs->end_columns));
#else /* XEmacs */
#ifdef MULE
	  col += CHAR_COLUMNS (c);
#else
	  col ++;
#endif /* MULE */
#endif /* XEmacs */
	}
    }

  if (tab_seen)
    {
      col = ((col + tab_width) / tab_width) * tab_width;
      col += post_tab;
    }

  if (cur_col)
    {
      last_known_column_buffer = buf;
      last_known_column = col;
      last_known_column_point = init_pos;
      last_known_column_modified = BUF_MODIFF (buf);
    }

  return col;
}
Exemplo n.º 8
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;
    }
}
Exemplo n.º 9
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;
    }
}