comparison src/edit.c @ 18265:fe5afdc03bd2 v8.1.2127

patch 8.1.2127: the indent.c file is a bit big Commit: https://github.com/vim/vim/commit/14c01f83487d5c53192297a710eda2b8a4ab17c9 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Oct 9 22:53:08 2019 +0200 patch 8.1.2127: the indent.c file is a bit big Problem: The indent.c file is a bit big. Solution: Move C-indent code a a new cindent.c file. Move other indent-related code to indent.c. (Yegappan Lakshmanan, closes #5031)
author Bram Moolenaar <Bram@vim.org>
date Wed, 09 Oct 2019 23:00:04 +0200
parents e0ec4cd7a865
children 9f51d0cef8da
comparison
equal deleted inserted replaced
18264:5202d9b99bee 18265:fe5afdc03bd2
35 #ifdef FEAT_SPELL 35 #ifdef FEAT_SPELL
36 static void check_spell_redraw(void); 36 static void check_spell_redraw(void);
37 #endif 37 #endif
38 static void stop_insert(pos_T *end_insert_pos, int esc, int nomove); 38 static void stop_insert(pos_T *end_insert_pos, int esc, int nomove);
39 static int echeck_abbr(int); 39 static int echeck_abbr(int);
40 static void replace_join(int off);
41 static void mb_replace_pop_ins(int cc); 40 static void mb_replace_pop_ins(int cc);
42 static void replace_flush(void); 41 static void replace_flush(void);
43 static void replace_do_bs(int limit_col); 42 static void replace_do_bs(int limit_col);
44 static int del_char_after_col(int limit_col); 43 static int del_char_after_col(int limit_col);
45 static void ins_reg(void); 44 static void ins_reg(void);
74 static int ins_tab(void); 73 static int ins_tab(void);
75 #ifdef FEAT_DIGRAPHS 74 #ifdef FEAT_DIGRAPHS
76 static int ins_digraph(void); 75 static int ins_digraph(void);
77 #endif 76 #endif
78 static int ins_ctrl_ey(int tc); 77 static int ins_ctrl_ey(int tc);
79 #ifdef FEAT_SMARTINDENT
80 static void ins_try_si(int c);
81 #endif
82 #if defined(FEAT_EVAL) 78 #if defined(FEAT_EVAL)
83 static char_u *do_insert_char_pre(int c); 79 static char_u *do_insert_char_pre(int c);
84 #endif 80 #endif
85 81
86 static colnr_T Insstart_textlen; /* length of line when insert started */ 82 static colnr_T Insstart_textlen; /* length of line when insert started */
94 static int did_restart_edit; /* "restart_edit" when calling edit() */ 90 static int did_restart_edit; /* "restart_edit" when calling edit() */
95 91
96 #ifdef FEAT_CINDENT 92 #ifdef FEAT_CINDENT
97 static int can_cindent; /* may do cindenting on this line */ 93 static int can_cindent; /* may do cindenting on this line */
98 #endif 94 #endif
99
100 static int old_indent = 0; /* for ^^D command in insert mode */
101 95
102 #ifdef FEAT_RIGHTLEFT 96 #ifdef FEAT_RIGHTLEFT
103 static int revins_on; /* reverse insert mode on */ 97 static int revins_on; /* reverse insert mode on */
104 static int revins_chars; /* how much to skip after edit */ 98 static int revins_chars; /* how much to skip after edit */
105 static int revins_legal; /* was the last char 'legal'? */ 99 static int revins_legal; /* was the last char 'legal'? */
1757 { 1751 {
1758 if (dollar_vcol >= 0) 1752 if (dollar_vcol >= 0)
1759 { 1753 {
1760 dollar_vcol = -1; 1754 dollar_vcol = -1;
1761 redrawWinline(curwin, curwin->w_cursor.lnum); 1755 redrawWinline(curwin, curwin->w_cursor.lnum);
1762 }
1763 }
1764
1765 /*
1766 * Insert an indent (for <Tab> or CTRL-T) or delete an indent (for CTRL-D).
1767 * Keep the cursor on the same character.
1768 * type == INDENT_INC increase indent (for CTRL-T or <Tab>)
1769 * type == INDENT_DEC decrease indent (for CTRL-D)
1770 * type == INDENT_SET set indent to "amount"
1771 * if round is TRUE, round the indent to 'shiftwidth' (only with _INC and _Dec).
1772 */
1773 void
1774 change_indent(
1775 int type,
1776 int amount,
1777 int round,
1778 int replaced, /* replaced character, put on replace stack */
1779 int call_changed_bytes) /* call changed_bytes() */
1780 {
1781 int vcol;
1782 int last_vcol;
1783 int insstart_less; /* reduction for Insstart.col */
1784 int new_cursor_col;
1785 int i;
1786 char_u *ptr;
1787 int save_p_list;
1788 int start_col;
1789 colnr_T vc;
1790 colnr_T orig_col = 0; /* init for GCC */
1791 char_u *new_line, *orig_line = NULL; /* init for GCC */
1792
1793 /* VREPLACE mode needs to know what the line was like before changing */
1794 if (State & VREPLACE_FLAG)
1795 {
1796 orig_line = vim_strsave(ml_get_curline()); /* Deal with NULL below */
1797 orig_col = curwin->w_cursor.col;
1798 }
1799
1800 /* for the following tricks we don't want list mode */
1801 save_p_list = curwin->w_p_list;
1802 curwin->w_p_list = FALSE;
1803 vc = getvcol_nolist(&curwin->w_cursor);
1804 vcol = vc;
1805
1806 /*
1807 * For Replace mode we need to fix the replace stack later, which is only
1808 * possible when the cursor is in the indent. Remember the number of
1809 * characters before the cursor if it's possible.
1810 */
1811 start_col = curwin->w_cursor.col;
1812
1813 /* determine offset from first non-blank */
1814 new_cursor_col = curwin->w_cursor.col;
1815 beginline(BL_WHITE);
1816 new_cursor_col -= curwin->w_cursor.col;
1817
1818 insstart_less = curwin->w_cursor.col;
1819
1820 /*
1821 * If the cursor is in the indent, compute how many screen columns the
1822 * cursor is to the left of the first non-blank.
1823 */
1824 if (new_cursor_col < 0)
1825 vcol = get_indent() - vcol;
1826
1827 if (new_cursor_col > 0) /* can't fix replace stack */
1828 start_col = -1;
1829
1830 /*
1831 * Set the new indent. The cursor will be put on the first non-blank.
1832 */
1833 if (type == INDENT_SET)
1834 (void)set_indent(amount, call_changed_bytes ? SIN_CHANGED : 0);
1835 else
1836 {
1837 int save_State = State;
1838
1839 /* Avoid being called recursively. */
1840 if (State & VREPLACE_FLAG)
1841 State = INSERT;
1842 shift_line(type == INDENT_DEC, round, 1, call_changed_bytes);
1843 State = save_State;
1844 }
1845 insstart_less -= curwin->w_cursor.col;
1846
1847 /*
1848 * Try to put cursor on same character.
1849 * If the cursor is at or after the first non-blank in the line,
1850 * compute the cursor column relative to the column of the first
1851 * non-blank character.
1852 * If we are not in insert mode, leave the cursor on the first non-blank.
1853 * If the cursor is before the first non-blank, position it relative
1854 * to the first non-blank, counted in screen columns.
1855 */
1856 if (new_cursor_col >= 0)
1857 {
1858 /*
1859 * When changing the indent while the cursor is touching it, reset
1860 * Insstart_col to 0.
1861 */
1862 if (new_cursor_col == 0)
1863 insstart_less = MAXCOL;
1864 new_cursor_col += curwin->w_cursor.col;
1865 }
1866 else if (!(State & INSERT))
1867 new_cursor_col = curwin->w_cursor.col;
1868 else
1869 {
1870 /*
1871 * Compute the screen column where the cursor should be.
1872 */
1873 vcol = get_indent() - vcol;
1874 curwin->w_virtcol = (colnr_T)((vcol < 0) ? 0 : vcol);
1875
1876 /*
1877 * Advance the cursor until we reach the right screen column.
1878 */
1879 vcol = last_vcol = 0;
1880 new_cursor_col = -1;
1881 ptr = ml_get_curline();
1882 while (vcol <= (int)curwin->w_virtcol)
1883 {
1884 last_vcol = vcol;
1885 if (has_mbyte && new_cursor_col >= 0)
1886 new_cursor_col += (*mb_ptr2len)(ptr + new_cursor_col);
1887 else
1888 ++new_cursor_col;
1889 vcol += lbr_chartabsize(ptr, ptr + new_cursor_col, (colnr_T)vcol);
1890 }
1891 vcol = last_vcol;
1892
1893 /*
1894 * May need to insert spaces to be able to position the cursor on
1895 * the right screen column.
1896 */
1897 if (vcol != (int)curwin->w_virtcol)
1898 {
1899 curwin->w_cursor.col = (colnr_T)new_cursor_col;
1900 i = (int)curwin->w_virtcol - vcol;
1901 ptr = alloc(i + 1);
1902 if (ptr != NULL)
1903 {
1904 new_cursor_col += i;
1905 ptr[i] = NUL;
1906 while (--i >= 0)
1907 ptr[i] = ' ';
1908 ins_str(ptr);
1909 vim_free(ptr);
1910 }
1911 }
1912
1913 /*
1914 * When changing the indent while the cursor is in it, reset
1915 * Insstart_col to 0.
1916 */
1917 insstart_less = MAXCOL;
1918 }
1919
1920 curwin->w_p_list = save_p_list;
1921
1922 if (new_cursor_col <= 0)
1923 curwin->w_cursor.col = 0;
1924 else
1925 curwin->w_cursor.col = (colnr_T)new_cursor_col;
1926 curwin->w_set_curswant = TRUE;
1927 changed_cline_bef_curs();
1928
1929 /*
1930 * May have to adjust the start of the insert.
1931 */
1932 if (State & INSERT)
1933 {
1934 if (curwin->w_cursor.lnum == Insstart.lnum && Insstart.col != 0)
1935 {
1936 if ((int)Insstart.col <= insstart_less)
1937 Insstart.col = 0;
1938 else
1939 Insstart.col -= insstart_less;
1940 }
1941 if ((int)ai_col <= insstart_less)
1942 ai_col = 0;
1943 else
1944 ai_col -= insstart_less;
1945 }
1946
1947 /*
1948 * For REPLACE mode, may have to fix the replace stack, if it's possible.
1949 * If the number of characters before the cursor decreased, need to pop a
1950 * few characters from the replace stack.
1951 * If the number of characters before the cursor increased, need to push a
1952 * few NULs onto the replace stack.
1953 */
1954 if (REPLACE_NORMAL(State) && start_col >= 0)
1955 {
1956 while (start_col > (int)curwin->w_cursor.col)
1957 {
1958 replace_join(0); /* remove a NUL from the replace stack */
1959 --start_col;
1960 }
1961 while (start_col < (int)curwin->w_cursor.col || replaced)
1962 {
1963 replace_push(NUL);
1964 if (replaced)
1965 {
1966 replace_push(replaced);
1967 replaced = NUL;
1968 }
1969 ++start_col;
1970 }
1971 }
1972
1973 /*
1974 * For VREPLACE mode, we also have to fix the replace stack. In this case
1975 * it is always possible because we backspace over the whole line and then
1976 * put it back again the way we wanted it.
1977 */
1978 if (State & VREPLACE_FLAG)
1979 {
1980 /* If orig_line didn't allocate, just return. At least we did the job,
1981 * even if you can't backspace. */
1982 if (orig_line == NULL)
1983 return;
1984
1985 /* Save new line */
1986 new_line = vim_strsave(ml_get_curline());
1987 if (new_line == NULL)
1988 return;
1989
1990 /* We only put back the new line up to the cursor */
1991 new_line[curwin->w_cursor.col] = NUL;
1992
1993 /* Put back original line */
1994 ml_replace(curwin->w_cursor.lnum, orig_line, FALSE);
1995 curwin->w_cursor.col = orig_col;
1996
1997 /* Backspace from cursor to start of line */
1998 backspace_until_column(0);
1999
2000 /* Insert new stuff into line again */
2001 ins_bytes(new_line);
2002
2003 vim_free(new_line);
2004 } 1756 }
2005 } 1757 }
2006 1758
2007 /* 1759 /*
2008 * Truncate the space at the end of a line. This is to be used only in an 1760 * Truncate the space at the end of a line. This is to be used only in an
3838 3590
3839 /* 3591 /*
3840 * Join the top two items on the replace stack. This removes to "off"'th NUL 3592 * Join the top two items on the replace stack. This removes to "off"'th NUL
3841 * encountered. 3593 * encountered.
3842 */ 3594 */
3843 static void 3595 void
3844 replace_join( 3596 replace_join(
3845 int off) /* offset for which NUL to remove */ 3597 int off) /* offset for which NUL to remove */
3846 { 3598 {
3847 int i; 3599 int i;
3848 3600
6068 } 5820 }
6069 } 5821 }
6070 return c; 5822 return c;
6071 } 5823 }
6072 5824
6073 #ifdef FEAT_SMARTINDENT
6074 /*
6075 * Try to do some very smart auto-indenting.
6076 * Used when inserting a "normal" character.
6077 */
6078 static void
6079 ins_try_si(int c)
6080 {
6081 pos_T *pos, old_pos;
6082 char_u *ptr;
6083 int i;
6084 int temp;
6085
6086 /*
6087 * do some very smart indenting when entering '{' or '}'
6088 */
6089 if (((did_si || can_si_back) && c == '{') || (can_si && c == '}'))
6090 {
6091 /*
6092 * for '}' set indent equal to indent of line containing matching '{'
6093 */
6094 if (c == '}' && (pos = findmatch(NULL, '{')) != NULL)
6095 {
6096 old_pos = curwin->w_cursor;
6097 /*
6098 * If the matching '{' has a ')' immediately before it (ignoring
6099 * white-space), then line up with the start of the line
6100 * containing the matching '(' if there is one. This handles the
6101 * case where an "if (..\n..) {" statement continues over multiple
6102 * lines -- webb
6103 */
6104 ptr = ml_get(pos->lnum);
6105 i = pos->col;
6106 if (i > 0) /* skip blanks before '{' */
6107 while (--i > 0 && VIM_ISWHITE(ptr[i]))
6108 ;
6109 curwin->w_cursor.lnum = pos->lnum;
6110 curwin->w_cursor.col = i;
6111 if (ptr[i] == ')' && (pos = findmatch(NULL, '(')) != NULL)
6112 curwin->w_cursor = *pos;
6113 i = get_indent();
6114 curwin->w_cursor = old_pos;
6115 if (State & VREPLACE_FLAG)
6116 change_indent(INDENT_SET, i, FALSE, NUL, TRUE);
6117 else
6118 (void)set_indent(i, SIN_CHANGED);
6119 }
6120 else if (curwin->w_cursor.col > 0)
6121 {
6122 /*
6123 * when inserting '{' after "O" reduce indent, but not
6124 * more than indent of previous line
6125 */
6126 temp = TRUE;
6127 if (c == '{' && can_si_back && curwin->w_cursor.lnum > 1)
6128 {
6129 old_pos = curwin->w_cursor;
6130 i = get_indent();
6131 while (curwin->w_cursor.lnum > 1)
6132 {
6133 ptr = skipwhite(ml_get(--(curwin->w_cursor.lnum)));
6134
6135 /* ignore empty lines and lines starting with '#'. */
6136 if (*ptr != '#' && *ptr != NUL)
6137 break;
6138 }
6139 if (get_indent() >= i)
6140 temp = FALSE;
6141 curwin->w_cursor = old_pos;
6142 }
6143 if (temp)
6144 shift_line(TRUE, FALSE, 1, TRUE);
6145 }
6146 }
6147
6148 /*
6149 * set indent of '#' always to 0
6150 */
6151 if (curwin->w_cursor.col > 0 && can_si && c == '#')
6152 {
6153 /* remember current indent for next line */
6154 old_indent = get_indent();
6155 (void)set_indent(0, SIN_CHANGED);
6156 }
6157
6158 /* Adjust ai_col, the char at this position can be deleted. */
6159 if (ai_col > curwin->w_cursor.col)
6160 ai_col = curwin->w_cursor.col;
6161 }
6162 #endif
6163
6164 /* 5825 /*
6165 * Get the value that w_virtcol would have when 'list' is off. 5826 * Get the value that w_virtcol would have when 'list' is off.
6166 * Unless 'cpo' contains the 'L' flag. 5827 * Unless 'cpo' contains the 'L' flag.
6167 */ 5828 */
6168 colnr_T 5829 colnr_T