diff src/ops.c @ 20237:918245588b50 v8.2.0674

patch 8.2.0674: some source files are too big Commit: https://github.com/vim/vim/commit/11abd095210fc84e5dcee87b9baed86061caefe4 Author: Bram Moolenaar <Bram@vim.org> Date: Fri May 1 14:26:37 2020 +0200 patch 8.2.0674: some source files are too big Problem: Some source files are too big. Solution: Move text formatting functions to a new file. (Yegappan Lakshmanan, closes #6021)
author Bram Moolenaar <Bram@vim.org>
date Fri, 01 May 2020 14:30:04 +0200
parents aadd1cae2ff5
children d067be761cd7
line wrap: on
line diff
--- a/src/ops.c
+++ b/src/ops.c
@@ -17,8 +17,6 @@
 static void shift_block(oparg_T *oap, int amount);
 static void	mb_adjust_opend(oparg_T *oap);
 static int	do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1);
-static int	ends_in_white(linenr_T lnum);
-static int	fmt_check_par(linenr_T, int *, char_u **, int do_comments);
 
 // Flags for third item in "opchars".
 #define OPF_LINES  1	// operator always works on lines
@@ -591,46 +589,6 @@ block_insert(
 }
 
 /*
- * Stuff a string into the typeahead buffer, such that edit() will insert it
- * literally ("literally" TRUE) or interpret is as typed characters.
- */
-    void
-stuffescaped(char_u *arg, int literally)
-{
-    int		c;
-    char_u	*start;
-
-    while (*arg != NUL)
-    {
-	// Stuff a sequence of normal ASCII characters, that's fast.  Also
-	// stuff K_SPECIAL to get the effect of a special key when "literally"
-	// is TRUE.
-	start = arg;
-	while ((*arg >= ' '
-#ifndef EBCDIC
-		    && *arg < DEL // EBCDIC: chars above space are normal
-#endif
-		    )
-		|| (*arg == K_SPECIAL && !literally))
-	    ++arg;
-	if (arg > start)
-	    stuffReadbuffLen(start, (long)(arg - start));
-
-	// stuff a single special character
-	if (*arg != NUL)
-	{
-	    if (has_mbyte)
-		c = mb_cptr2char_adv(&arg);
-	    else
-		c = *arg++;
-	    if (literally && ((c < ' ' && c != TAB) || c == DEL))
-		stuffcharReadbuff(Ctrl_V);
-	    stuffcharReadbuff(c);
-	}
-    }
-}
-
-/*
  * Handle a delete operation.
  *
  * Return FAIL if undo failed, OK otherwise.
@@ -2171,554 +2129,6 @@ theend:
 }
 
 /*
- * Return TRUE if the two comment leaders given are the same.  "lnum" is
- * the first line.  White-space is ignored.  Note that the whole of
- * 'leader1' must match 'leader2_len' characters from 'leader2' -- webb
- */
-    static int
-same_leader(
-    linenr_T lnum,
-    int	    leader1_len,
-    char_u  *leader1_flags,
-    int	    leader2_len,
-    char_u  *leader2_flags)
-{
-    int	    idx1 = 0, idx2 = 0;
-    char_u  *p;
-    char_u  *line1;
-    char_u  *line2;
-
-    if (leader1_len == 0)
-	return (leader2_len == 0);
-
-    /*
-     * If first leader has 'f' flag, the lines can be joined only if the
-     * second line does not have a leader.
-     * If first leader has 'e' flag, the lines can never be joined.
-     * If fist leader has 's' flag, the lines can only be joined if there is
-     * some text after it and the second line has the 'm' flag.
-     */
-    if (leader1_flags != NULL)
-    {
-	for (p = leader1_flags; *p && *p != ':'; ++p)
-	{
-	    if (*p == COM_FIRST)
-		return (leader2_len == 0);
-	    if (*p == COM_END)
-		return FALSE;
-	    if (*p == COM_START)
-	    {
-		if (*(ml_get(lnum) + leader1_len) == NUL)
-		    return FALSE;
-		if (leader2_flags == NULL || leader2_len == 0)
-		    return FALSE;
-		for (p = leader2_flags; *p && *p != ':'; ++p)
-		    if (*p == COM_MIDDLE)
-			return TRUE;
-		return FALSE;
-	    }
-	}
-    }
-
-    /*
-     * Get current line and next line, compare the leaders.
-     * The first line has to be saved, only one line can be locked at a time.
-     */
-    line1 = vim_strsave(ml_get(lnum));
-    if (line1 != NULL)
-    {
-	for (idx1 = 0; VIM_ISWHITE(line1[idx1]); ++idx1)
-	    ;
-	line2 = ml_get(lnum + 1);
-	for (idx2 = 0; idx2 < leader2_len; ++idx2)
-	{
-	    if (!VIM_ISWHITE(line2[idx2]))
-	    {
-		if (line1[idx1++] != line2[idx2])
-		    break;
-	    }
-	    else
-		while (VIM_ISWHITE(line1[idx1]))
-		    ++idx1;
-	}
-	vim_free(line1);
-    }
-    return (idx2 == leader2_len && idx1 == leader1_len);
-}
-
-/*
- * Implementation of the format operator 'gq'.
- */
-    static void
-op_format(
-    oparg_T	*oap,
-    int		keep_cursor)		// keep cursor on same text char
-{
-    long	old_line_count = curbuf->b_ml.ml_line_count;
-
-    // Place the cursor where the "gq" or "gw" command was given, so that "u"
-    // can put it back there.
-    curwin->w_cursor = oap->cursor_start;
-
-    if (u_save((linenr_T)(oap->start.lnum - 1),
-				       (linenr_T)(oap->end.lnum + 1)) == FAIL)
-	return;
-    curwin->w_cursor = oap->start;
-
-    if (oap->is_VIsual)
-	// When there is no change: need to remove the Visual selection
-	redraw_curbuf_later(INVERTED);
-
-    if (!cmdmod.lockmarks)
-	// Set '[ mark at the start of the formatted area
-	curbuf->b_op_start = oap->start;
-
-    // For "gw" remember the cursor position and put it back below (adjusted
-    // for joined and split lines).
-    if (keep_cursor)
-	saved_cursor = oap->cursor_start;
-
-    format_lines(oap->line_count, keep_cursor);
-
-    /*
-     * Leave the cursor at the first non-blank of the last formatted line.
-     * If the cursor was moved one line back (e.g. with "Q}") go to the next
-     * line, so "." will do the next lines.
-     */
-    if (oap->end_adjusted && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
-	++curwin->w_cursor.lnum;
-    beginline(BL_WHITE | BL_FIX);
-    old_line_count = curbuf->b_ml.ml_line_count - old_line_count;
-    msgmore(old_line_count);
-
-    if (!cmdmod.lockmarks)
-	// put '] mark on the end of the formatted area
-	curbuf->b_op_end = curwin->w_cursor;
-
-    if (keep_cursor)
-    {
-	curwin->w_cursor = saved_cursor;
-	saved_cursor.lnum = 0;
-    }
-
-    if (oap->is_VIsual)
-    {
-	win_T	*wp;
-
-	FOR_ALL_WINDOWS(wp)
-	{
-	    if (wp->w_old_cursor_lnum != 0)
-	    {
-		// When lines have been inserted or deleted, adjust the end of
-		// the Visual area to be redrawn.
-		if (wp->w_old_cursor_lnum > wp->w_old_visual_lnum)
-		    wp->w_old_cursor_lnum += old_line_count;
-		else
-		    wp->w_old_visual_lnum += old_line_count;
-	    }
-	}
-    }
-}
-
-#if defined(FEAT_EVAL) || defined(PROTO)
-/*
- * Implementation of the format operator 'gq' for when using 'formatexpr'.
- */
-    static void
-op_formatexpr(oparg_T *oap)
-{
-    if (oap->is_VIsual)
-	// When there is no change: need to remove the Visual selection
-	redraw_curbuf_later(INVERTED);
-
-    if (fex_format(oap->start.lnum, oap->line_count, NUL) != 0)
-	// As documented: when 'formatexpr' returns non-zero fall back to
-	// internal formatting.
-	op_format(oap, FALSE);
-}
-
-    int
-fex_format(
-    linenr_T	lnum,
-    long	count,
-    int		c)	// character to be inserted
-{
-    int		use_sandbox = was_set_insecurely((char_u *)"formatexpr",
-								   OPT_LOCAL);
-    int		r;
-    char_u	*fex;
-
-    /*
-     * Set v:lnum to the first line number and v:count to the number of lines.
-     * Set v:char to the character to be inserted (can be NUL).
-     */
-    set_vim_var_nr(VV_LNUM, lnum);
-    set_vim_var_nr(VV_COUNT, count);
-    set_vim_var_char(c);
-
-    // Make a copy, the option could be changed while calling it.
-    fex = vim_strsave(curbuf->b_p_fex);
-    if (fex == NULL)
-	return 0;
-
-    /*
-     * Evaluate the function.
-     */
-    if (use_sandbox)
-	++sandbox;
-    r = (int)eval_to_number(fex);
-    if (use_sandbox)
-	--sandbox;
-
-    set_vim_var_string(VV_CHAR, NULL, -1);
-    vim_free(fex);
-
-    return r;
-}
-#endif
-
-/*
- * Format "line_count" lines, starting at the cursor position.
- * When "line_count" is negative, format until the end of the paragraph.
- * Lines after the cursor line are saved for undo, caller must have saved the
- * first line.
- */
-    void
-format_lines(
-    linenr_T	line_count,
-    int		avoid_fex)		// don't use 'formatexpr'
-{
-    int		max_len;
-    int		is_not_par;		// current line not part of parag.
-    int		next_is_not_par;	// next line not part of paragraph
-    int		is_end_par;		// at end of paragraph
-    int		prev_is_end_par = FALSE;// prev. line not part of parag.
-    int		next_is_start_par = FALSE;
-    int		leader_len = 0;		// leader len of current line
-    int		next_leader_len;	// leader len of next line
-    char_u	*leader_flags = NULL;	// flags for leader of current line
-    char_u	*next_leader_flags;	// flags for leader of next line
-    int		do_comments;		// format comments
-    int		do_comments_list = 0;	// format comments with 'n' or '2'
-    int		advance = TRUE;
-    int		second_indent = -1;	// indent for second line (comment
-					// aware)
-    int		do_second_indent;
-    int		do_number_indent;
-    int		do_trail_white;
-    int		first_par_line = TRUE;
-    int		smd_save;
-    long	count;
-    int		need_set_indent = TRUE;	// set indent of next paragraph
-    int		force_format = FALSE;
-    int		old_State = State;
-
-    // length of a line to force formatting: 3 * 'tw'
-    max_len = comp_textwidth(TRUE) * 3;
-
-    // check for 'q', '2' and '1' in 'formatoptions'
-    do_comments = has_format_option(FO_Q_COMS);
-    do_second_indent = has_format_option(FO_Q_SECOND);
-    do_number_indent = has_format_option(FO_Q_NUMBER);
-    do_trail_white = has_format_option(FO_WHITE_PAR);
-
-    /*
-     * Get info about the previous and current line.
-     */
-    if (curwin->w_cursor.lnum > 1)
-	is_not_par = fmt_check_par(curwin->w_cursor.lnum - 1
-				, &leader_len, &leader_flags, do_comments);
-    else
-	is_not_par = TRUE;
-    next_is_not_par = fmt_check_par(curwin->w_cursor.lnum
-			  , &next_leader_len, &next_leader_flags, do_comments);
-    is_end_par = (is_not_par || next_is_not_par);
-    if (!is_end_par && do_trail_white)
-	is_end_par = !ends_in_white(curwin->w_cursor.lnum - 1);
-
-    curwin->w_cursor.lnum--;
-    for (count = line_count; count != 0 && !got_int; --count)
-    {
-	/*
-	 * Advance to next paragraph.
-	 */
-	if (advance)
-	{
-	    curwin->w_cursor.lnum++;
-	    prev_is_end_par = is_end_par;
-	    is_not_par = next_is_not_par;
-	    leader_len = next_leader_len;
-	    leader_flags = next_leader_flags;
-	}
-
-	/*
-	 * The last line to be formatted.
-	 */
-	if (count == 1 || curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count)
-	{
-	    next_is_not_par = TRUE;
-	    next_leader_len = 0;
-	    next_leader_flags = NULL;
-	}
-	else
-	{
-	    next_is_not_par = fmt_check_par(curwin->w_cursor.lnum + 1
-			  , &next_leader_len, &next_leader_flags, do_comments);
-	    if (do_number_indent)
-		next_is_start_par =
-			   (get_number_indent(curwin->w_cursor.lnum + 1) > 0);
-	}
-	advance = TRUE;
-	is_end_par = (is_not_par || next_is_not_par || next_is_start_par);
-	if (!is_end_par && do_trail_white)
-	    is_end_par = !ends_in_white(curwin->w_cursor.lnum);
-
-	/*
-	 * Skip lines that are not in a paragraph.
-	 */
-	if (is_not_par)
-	{
-	    if (line_count < 0)
-		break;
-	}
-	else
-	{
-	    /*
-	     * For the first line of a paragraph, check indent of second line.
-	     * Don't do this for comments and empty lines.
-	     */
-	    if (first_par_line
-		    && (do_second_indent || do_number_indent)
-		    && prev_is_end_par
-		    && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
-	    {
-		if (do_second_indent && !LINEEMPTY(curwin->w_cursor.lnum + 1))
-		{
-		    if (leader_len == 0 && next_leader_len == 0)
-		    {
-			// no comment found
-			second_indent =
-				   get_indent_lnum(curwin->w_cursor.lnum + 1);
-		    }
-		    else
-		    {
-			second_indent = next_leader_len;
-			do_comments_list = 1;
-		    }
-		}
-		else if (do_number_indent)
-		{
-		    if (leader_len == 0 && next_leader_len == 0)
-		    {
-			// no comment found
-			second_indent =
-				     get_number_indent(curwin->w_cursor.lnum);
-		    }
-		    else
-		    {
-			// get_number_indent() is now "comment aware"...
-			second_indent =
-				     get_number_indent(curwin->w_cursor.lnum);
-			do_comments_list = 1;
-		    }
-		}
-	    }
-
-	    /*
-	     * When the comment leader changes, it's the end of the paragraph.
-	     */
-	    if (curwin->w_cursor.lnum >= curbuf->b_ml.ml_line_count
-		    || !same_leader(curwin->w_cursor.lnum,
-					leader_len, leader_flags,
-					   next_leader_len, next_leader_flags))
-		is_end_par = TRUE;
-
-	    /*
-	     * If we have got to the end of a paragraph, or the line is
-	     * getting long, format it.
-	     */
-	    if (is_end_par || force_format)
-	    {
-		if (need_set_indent)
-		    // replace indent in first line with minimal number of
-		    // tabs and spaces, according to current options
-		    (void)set_indent(get_indent(), SIN_CHANGED);
-
-		// put cursor on last non-space
-		State = NORMAL;	// don't go past end-of-line
-		coladvance((colnr_T)MAXCOL);
-		while (curwin->w_cursor.col && vim_isspace(gchar_cursor()))
-		    dec_cursor();
-
-		// do the formatting, without 'showmode'
-		State = INSERT;	// for open_line()
-		smd_save = p_smd;
-		p_smd = FALSE;
-		insertchar(NUL, INSCHAR_FORMAT
-			+ (do_comments ? INSCHAR_DO_COM : 0)
-			+ (do_comments && do_comments_list
-						       ? INSCHAR_COM_LIST : 0)
-			+ (avoid_fex ? INSCHAR_NO_FEX : 0), second_indent);
-		State = old_State;
-		p_smd = smd_save;
-		second_indent = -1;
-		// at end of par.: need to set indent of next par.
-		need_set_indent = is_end_par;
-		if (is_end_par)
-		{
-		    // When called with a negative line count, break at the
-		    // end of the paragraph.
-		    if (line_count < 0)
-			break;
-		    first_par_line = TRUE;
-		}
-		force_format = FALSE;
-	    }
-
-	    /*
-	     * When still in same paragraph, join the lines together.  But
-	     * first delete the leader from the second line.
-	     */
-	    if (!is_end_par)
-	    {
-		advance = FALSE;
-		curwin->w_cursor.lnum++;
-		curwin->w_cursor.col = 0;
-		if (line_count < 0 && u_save_cursor() == FAIL)
-		    break;
-		if (next_leader_len > 0)
-		{
-		    (void)del_bytes((long)next_leader_len, FALSE, FALSE);
-		    mark_col_adjust(curwin->w_cursor.lnum, (colnr_T)0, 0L,
-						    (long)-next_leader_len, 0);
-		}
-		else if (second_indent > 0)  // the "leader" for FO_Q_SECOND
-		{
-		    int indent = getwhitecols_curline();
-
-		    if (indent > 0)
-		    {
-			(void)del_bytes(indent, FALSE, FALSE);
-			mark_col_adjust(curwin->w_cursor.lnum,
-					       (colnr_T)0, 0L, (long)-indent, 0);
-		    }
-		}
-		curwin->w_cursor.lnum--;
-		if (do_join(2, TRUE, FALSE, FALSE, FALSE) == FAIL)
-		{
-		    beep_flush();
-		    break;
-		}
-		first_par_line = FALSE;
-		// If the line is getting long, format it next time
-		if (STRLEN(ml_get_curline()) > (size_t)max_len)
-		    force_format = TRUE;
-		else
-		    force_format = FALSE;
-	    }
-	}
-	line_breakcheck();
-    }
-}
-
-/*
- * Return TRUE if line "lnum" ends in a white character.
- */
-    static int
-ends_in_white(linenr_T lnum)
-{
-    char_u	*s = ml_get(lnum);
-    size_t	l;
-
-    if (*s == NUL)
-	return FALSE;
-    // Don't use STRLEN() inside VIM_ISWHITE(), SAS/C complains: "macro
-    // invocation may call function multiple times".
-    l = STRLEN(s) - 1;
-    return VIM_ISWHITE(s[l]);
-}
-
-/*
- * Blank lines, and lines containing only the comment leader, are left
- * untouched by the formatting.  The function returns TRUE in this
- * case.  It also returns TRUE when a line starts with the end of a comment
- * ('e' in comment flags), so that this line is skipped, and not joined to the
- * previous line.  A new paragraph starts after a blank line, or when the
- * comment leader changes -- webb.
- */
-    static int
-fmt_check_par(
-    linenr_T	lnum,
-    int		*leader_len,
-    char_u	**leader_flags,
-    int		do_comments)
-{
-    char_u	*flags = NULL;	    // init for GCC
-    char_u	*ptr;
-
-    ptr = ml_get(lnum);
-    if (do_comments)
-	*leader_len = get_leader_len(ptr, leader_flags, FALSE, TRUE);
-    else
-	*leader_len = 0;
-
-    if (*leader_len > 0)
-    {
-	/*
-	 * Search for 'e' flag in comment leader flags.
-	 */
-	flags = *leader_flags;
-	while (*flags && *flags != ':' && *flags != COM_END)
-	    ++flags;
-    }
-
-    return (*skipwhite(ptr + *leader_len) == NUL
-	    || (*leader_len > 0 && *flags == COM_END)
-	    || startPS(lnum, NUL, FALSE));
-}
-
-/*
- * Return TRUE when a paragraph starts in line "lnum".  Return FALSE when the
- * previous line is in the same paragraph.  Used for auto-formatting.
- */
-    int
-paragraph_start(linenr_T lnum)
-{
-    char_u	*p;
-    int		leader_len = 0;		// leader len of current line
-    char_u	*leader_flags = NULL;	// flags for leader of current line
-    int		next_leader_len;	// leader len of next line
-    char_u	*next_leader_flags;	// flags for leader of next line
-    int		do_comments;		// format comments
-
-    if (lnum <= 1)
-	return TRUE;		// start of the file
-
-    p = ml_get(lnum - 1);
-    if (*p == NUL)
-	return TRUE;		// after empty line
-
-    do_comments = has_format_option(FO_Q_COMS);
-    if (fmt_check_par(lnum - 1, &leader_len, &leader_flags, do_comments))
-	return TRUE;		// after non-paragraph line
-
-    if (fmt_check_par(lnum, &next_leader_len, &next_leader_flags, do_comments))
-	return TRUE;		// "lnum" is not a paragraph line
-
-    if (has_format_option(FO_WHITE_PAR) && !ends_in_white(lnum - 1))
-	return TRUE;		// missing trailing space in previous line.
-
-    if (has_format_option(FO_Q_NUMBER) && (get_number_indent(lnum) > 0))
-	return TRUE;		// numbered item starts in "lnum".
-
-    if (!same_leader(lnum - 1, leader_len, leader_flags,
-					  next_leader_len, next_leader_flags))
-	return TRUE;		// change of comment leader.
-
-    return FALSE;
-}
-
-/*
  * prepare a few things for block mode yank/delete/tilde
  *
  * for delete: