/* 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; }
/* 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; }
/* 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); }
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; }
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; }
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; }
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; }
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; } }
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; } }