diff --git a/7.4.803 b/7.4.803 new file mode 100644 index 0000000..e40a745 --- /dev/null +++ b/7.4.803 @@ -0,0 +1,1493 @@ +To: vim_dev@googlegroups.com +Subject: Patch 7.4.803 +Fcc: outbox +From: Bram Moolenaar +Mime-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +------------ + +Patch 7.4.803 +Problem: C indent does not support C11 raw strings. (Mark Lodato) +Solution: Do not change indent inside the raw string. +Files: src/search.c, src/misc1.c, src/edit.c, src/ops.c, + src/testdir/test3.in, src/testdir/test3.ok + + +*** ../vim-7.4.802/src/search.c 2015-07-21 17:53:11.585527913 +0200 +--- src/search.c 2015-07-28 21:14:08.968071627 +0200 +*************** +*** 1725,1744 **** + return (col >= 0 && linep[col] == ch) ? TRUE : FALSE; + } + + /* + * findmatchlimit -- find the matching paren or brace, if it exists within +! * maxtravel lines of here. A maxtravel of 0 means search until falling off +! * the edge of the file. + * + * "initc" is the character to find a match for. NUL means to find the +! * character at or after the cursor. + * + * flags: FM_BACKWARD search backwards (when initc is '/', '*' or '#') + * FM_FORWARD search forwards (when initc is '/', '*' or '#') + * FM_BLOCKSTOP stop at start/end of block ({ or } in column 0) + * FM_SKIPCOMM skip comments (not implemented yet!) + * +! * "oap" is only used to set oap->motion_type for a linewise motion, it be + * NULL + */ + +--- 1725,1795 ---- + return (col >= 0 && linep[col] == ch) ? TRUE : FALSE; + } + ++ static int find_rawstring_end __ARGS((char_u *linep, pos_T *startpos, pos_T *endpos)); ++ ++ /* ++ * Raw string start is found at linep[startpos.col - 1]. ++ * Return TRUE if the matching end can be found between startpos and endpos. ++ */ ++ static int ++ find_rawstring_end(linep, startpos, endpos) ++ char_u *linep; ++ pos_T *startpos; ++ pos_T *endpos; ++ { ++ char_u *p; ++ char_u *delim_copy; ++ size_t delim_len; ++ linenr_T lnum; ++ int found = FALSE; ++ ++ for (p = linep + startpos->col + 1; *p && *p != '('; ++p) ++ ; ++ delim_len = (p - linep) - startpos->col - 1; ++ delim_copy = vim_strnsave(linep + startpos->col + 1, delim_len); ++ if (delim_copy == NULL) ++ return FALSE; ++ for (lnum = startpos->lnum; lnum <= endpos->lnum; ++lnum) ++ { ++ char_u *line = ml_get(lnum); ++ ++ for (p = line + (lnum == startpos->lnum ++ ? startpos->col + 1 : 0); *p; ++p) ++ { ++ if (lnum == endpos->lnum && (colnr_T)(p - line) >= endpos->col) ++ break; ++ if (*p == ')' && p[delim_len + 1] == '"' ++ && STRNCMP(delim_copy, p + 1, delim_len) == 0) ++ { ++ found = TRUE; ++ break; ++ } ++ } ++ if (found) ++ break; ++ } ++ vim_free(delim_copy); ++ return found; ++ } ++ + /* + * findmatchlimit -- find the matching paren or brace, if it exists within +! * maxtravel lines of the cursor. A maxtravel of 0 means search until falling +! * off the edge of the file. + * + * "initc" is the character to find a match for. NUL means to find the +! * character at or after the cursor. Special values: +! * '*' look for C-style comment / * +! * '/' look for C-style comment / *, ignoring comment-end +! * '#' look for preprocessor directives +! * 'R' look for raw string start: R"delim(text)delim" (only backwards) + * + * flags: FM_BACKWARD search backwards (when initc is '/', '*' or '#') + * FM_FORWARD search forwards (when initc is '/', '*' or '#') + * FM_BLOCKSTOP stop at start/end of block ({ or } in column 0) + * FM_SKIPCOMM skip comments (not implemented yet!) + * +! * "oap" is only used to set oap->motion_type for a linewise motion, it can be + * NULL + */ + +*************** +*** 1754,1759 **** +--- 1805,1811 ---- + int c; + int count = 0; /* cumulative number of braces */ + int backwards = FALSE; /* init for gcc */ ++ int raw_string = FALSE; /* search for raw string */ + int inquote = FALSE; /* TRUE when inside quotes */ + char_u *linep; /* pointer to current line */ + char_u *ptr; +*************** +*** 1798,1809 **** + * When '/' is used, we ignore running backwards into an star-slash, for + * "[*" command, we just want to find any comment. + */ +! if (initc == '/' || initc == '*') + { + comment_dir = dir; + if (initc == '/') + ignore_cend = TRUE; + backwards = (dir == FORWARD) ? FALSE : TRUE; + initc = NUL; + } + else if (initc != '#' && initc != NUL) +--- 1850,1862 ---- + * When '/' is used, we ignore running backwards into an star-slash, for + * "[*" command, we just want to find any comment. + */ +! if (initc == '/' || initc == '*' || initc == 'R') + { + comment_dir = dir; + if (initc == '/') + ignore_cend = TRUE; + backwards = (dir == FORWARD) ? FALSE : TRUE; ++ raw_string = (initc == 'R'); + initc = NUL; + } + else if (initc != '#' && initc != NUL) +*************** +*** 1812,1823 **** + if (findc == NUL) + return NULL; + } +- /* +- * Either initc is '#', or no initc was given and we need to look under the +- * cursor. +- */ + else + { + if (initc == '#') + { + hash_dir = dir; +--- 1865,1876 ---- + if (findc == NUL) + return NULL; + } + else + { ++ /* ++ * Either initc is '#', or no initc was given and we need to look ++ * under the cursor. ++ */ + if (initc == '#') + { + hash_dir = dir; +*************** +*** 2135,2140 **** +--- 2188,2213 ---- + */ + if (pos.col == 0) + continue; ++ else if (raw_string) ++ { ++ if (linep[pos.col - 1] == 'R' ++ && linep[pos.col] == '"' ++ && vim_strchr(linep + pos.col + 1, '(') != NULL) ++ { ++ /* Possible start of raw string. Now that we have the ++ * delimiter we can check if it ends before where we ++ * started searching, or before the previously found ++ * raw string start. */ ++ if (!find_rawstring_end(linep, &pos, ++ count > 0 ? &match_pos : &curwin->w_cursor)) ++ { ++ count++; ++ match_pos = pos; ++ match_pos.col--; ++ } ++ linep = ml_get(pos.lnum); /* may have been released */ ++ } ++ } + else if ( linep[pos.col - 1] == '/' + && linep[pos.col] == '*' + && (int)pos.col < comment_col) +*** ../vim-7.4.802/src/misc1.c 2015-07-21 17:53:11.581527951 +0200 +--- src/misc1.c 2015-07-28 21:06:38.908518760 +0200 +*************** +*** 5267,5276 **** +--- 5267,5279 ---- + + static char_u *skip_string __ARGS((char_u *p)); + static pos_T *ind_find_start_comment __ARGS((void)); ++ static pos_T *ind_find_start_CORS __ARGS((void)); ++ static pos_T *find_start_rawstring __ARGS((int ind_maxcomment)); + + /* + * Find the start of a comment, not knowing if we are in a comment right now. + * Search starts at w_cursor.lnum and goes backwards. ++ * Return NULL when not inside a comment. + */ + static pos_T * + ind_find_start_comment() /* XXX */ +*************** +*** 5313,5318 **** +--- 5316,5380 ---- + } + + /* ++ * Find the start of a comment or raw string, not knowing if we are in a ++ * comment or raw string right now. ++ * Search starts at w_cursor.lnum and goes backwards. ++ * Return NULL when not inside a comment or raw string. ++ * "CORS" -> Comment Or Raw String ++ */ ++ static pos_T * ++ ind_find_start_CORS() /* XXX */ ++ { ++ pos_T *comment_pos = find_start_comment(curbuf->b_ind_maxcomment); ++ pos_T *rs_pos = find_start_rawstring(curbuf->b_ind_maxcomment); ++ ++ /* If comment_pos is before rs_pos the raw string is inside the comment. ++ * If rs_pos is before comment_pos the comment is inside the raw string. */ ++ if (comment_pos == NULL || (rs_pos != NULL && lt(*rs_pos, *comment_pos))) ++ return rs_pos; ++ return comment_pos; ++ } ++ ++ /* ++ * Find the start of a raw string, not knowing if we are in one right now. ++ * Search starts at w_cursor.lnum and goes backwards. ++ * Return NULL when not inside a raw string. ++ */ ++ static pos_T * ++ find_start_rawstring(ind_maxcomment) /* XXX */ ++ int ind_maxcomment; ++ { ++ pos_T *pos; ++ char_u *line; ++ char_u *p; ++ int cur_maxcomment = ind_maxcomment; ++ ++ for (;;) ++ { ++ pos = findmatchlimit(NULL, 'R', FM_BACKWARD, cur_maxcomment); ++ if (pos == NULL) ++ break; ++ ++ /* ++ * Check if the raw string start we found is inside a string. ++ * If it is then restrict the search to below this line and try again. ++ */ ++ line = ml_get(pos->lnum); ++ for (p = line; *p && (colnr_T)(p - line) < pos->col; ++p) ++ p = skip_string(p); ++ if ((colnr_T)(p - line) <= pos->col) ++ break; ++ cur_maxcomment = curwin->w_cursor.lnum - pos->lnum - 1; ++ if (cur_maxcomment <= 0) ++ { ++ pos = NULL; ++ break; ++ } ++ } ++ return pos; ++ } ++ ++ /* + * Skip to the end of a "string" and a 'c' character. + * If there is no string or character, return argument unmodified. + */ +*************** +*** 5354,5360 **** + break; + } + if (p[0] == '"') +! continue; + } + break; /* no string found */ + } +--- 5416,5443 ---- + break; + } + if (p[0] == '"') +! continue; /* continue for another string */ +! } +! else if (p[0] == 'R' && p[1] == '"') +! { +! /* Raw string: R"[delim](...)[delim]" */ +! char_u *delim = p + 2; +! char_u *paren = vim_strchr(delim, '('); +! +! if (paren != NULL) +! { +! size_t delim_len = paren - delim; +! +! for (p += 3; *p; ++p) +! if (p[0] == ')' && STRNCMP(p + 1, delim, delim_len) == 0 +! && p[delim_len + 1] == '"') +! { +! p += delim_len + 1; +! break; +! } +! if (p[0] == '"') +! continue; /* continue for another string */ +! } + } + break; /* no string found */ + } +*************** +*** 5596,5605 **** + --curwin->w_cursor.lnum; + + /* +! * If we're in a comment now, skip to the start of the comment. + */ + curwin->w_cursor.col = 0; +! if ((trypos = ind_find_start_comment()) != NULL) /* XXX */ + curwin->w_cursor = *trypos; + + line = ml_get_curline(); +--- 5679,5689 ---- + --curwin->w_cursor.lnum; + + /* +! * If we're in a comment or raw string now, skip to the start of +! * it. + */ + curwin->w_cursor.col = 0; +! if ((trypos = ind_find_start_CORS()) != NULL) /* XXX */ + curwin->w_cursor = *trypos; + + line = ml_get_curline(); +*************** +*** 6454,6460 **** + continue; + } + +! if (s[0] == '"') + s = skip_string(s) + 1; + else if (s[0] == ':') + { +--- 6538,6544 ---- + continue; + } + +! if (s[0] == '"' || (s[0] == 'R' && s[1] == '"')) + s = skip_string(s) + 1; + else if (s[0] == ':') + { +*************** +*** 6660,6666 **** + pos = NULL; + /* ignore the { if it's in a // or / * * / comment */ + if ((colnr_T)cin_skip2pos(trypos) == trypos->col +! && (pos = ind_find_start_comment()) == NULL) /* XXX */ + break; + if (pos != NULL) + curwin->w_cursor.lnum = pos->lnum; +--- 6744,6750 ---- + pos = NULL; + /* ignore the { if it's in a // or / * * / comment */ + if ((colnr_T)cin_skip2pos(trypos) == trypos->col +! && (pos = ind_find_start_CORS()) == NULL) /* XXX */ + break; + if (pos != NULL) + curwin->w_cursor.lnum = pos->lnum; +*************** +*** 6714,6720 **** + pos_copy = *trypos; /* copy trypos, findmatch will change it */ + trypos = &pos_copy; + curwin->w_cursor = *trypos; +! if ((trypos_wk = ind_find_start_comment()) != NULL) /* XXX */ + { + ind_maxp_wk = ind_maxparen - (int)(cursor_save.lnum + - trypos_wk->lnum); +--- 6798,6804 ---- + pos_copy = *trypos; /* copy trypos, findmatch will change it */ + trypos = &pos_copy; + curwin->w_cursor = *trypos; +! if ((trypos_wk = ind_find_start_CORS()) != NULL) /* XXX */ + { + ind_maxp_wk = ind_maxparen - (int)(cursor_save.lnum + - trypos_wk->lnum); +*************** +*** 7029,7034 **** +--- 7113,7122 ---- + } + } + ++ /* ++ * Return the desired indent for C code. ++ * Return -1 if the indent should be left alone (inside a raw string). ++ */ + int + get_c_indent() + { +*************** +*** 7040,7047 **** + char_u *theline; + char_u *linecopy; + pos_T *trypos; + pos_T *tryposBrace = NULL; +! pos_T tryposBraceCopy; + pos_T our_paren_pos; + char_u *start; + int start_brace; +--- 7128,7136 ---- + char_u *theline; + char_u *linecopy; + pos_T *trypos; ++ pos_T *comment_pos; + pos_T *tryposBrace = NULL; +! pos_T tryposCopy; + pos_T our_paren_pos; + char_u *start; + int start_brace; +*************** +*** 7085,7091 **** + /* remember where the cursor was when we started */ + cur_curpos = curwin->w_cursor; + +! /* if we are at line 1 0 is fine, right? */ + if (cur_curpos.lnum == 1) + return 0; + +--- 7174,7180 ---- + /* remember where the cursor was when we started */ + cur_curpos = curwin->w_cursor; + +! /* if we are at line 1 zero indent is fine, right? */ + if (cur_curpos.lnum == 1) + return 0; + +*************** +*** 7117,7157 **** + original_line_islabel = cin_islabel(); /* XXX */ + + /* + * #defines and so on always go at the left when included in 'cinkeys'. + */ + if (*theline == '#' && (*linecopy == '#' || in_cinkeys('#', ' ', TRUE))) + amount = curbuf->b_ind_hash_comment; + + /* + * Is it a non-case label? Then that goes at the left margin too unless: + * - JS flag is set. + * - 'L' item has a positive value. + */ +! else if (original_line_islabel && !curbuf->b_ind_js + && curbuf->b_ind_jump_label < 0) + { + amount = 0; + } + + /* + * If we're inside a "//" comment and there is a "//" comment in a + * previous line, lineup with that one. + */ +! else if (cin_islinecomment(theline) + && (trypos = find_line_comment()) != NULL) /* XXX */ + { + /* find how indented the line beginning the comment is */ + getvcol(curwin, trypos, &col, NULL, NULL); + amount = col; + } + + /* + * If we're inside a comment and not looking at the start of the + * comment, try using the 'comments' option. + */ +! else if (!cin_iscomment(theline) +! && (trypos = ind_find_start_comment()) != NULL) +! /* XXX */ + { + int lead_start_len = 2; + int lead_middle_len = 1; +--- 7206,7267 ---- + original_line_islabel = cin_islabel(); /* XXX */ + + /* ++ * If we are inside a raw string don't change the indent. ++ * Ignore a raw string inside a comment. ++ */ ++ comment_pos = ind_find_start_comment(); ++ if (comment_pos != NULL) ++ { ++ /* findmatchlimit() static pos is overwritten, make a copy */ ++ tryposCopy = *comment_pos; ++ comment_pos = &tryposCopy; ++ } ++ trypos = find_start_rawstring(curbuf->b_ind_maxcomment); ++ if (trypos != NULL && (comment_pos == NULL || lt(*trypos, *comment_pos))) ++ { ++ amount = -1; ++ goto laterend; ++ } ++ ++ /* + * #defines and so on always go at the left when included in 'cinkeys'. + */ + if (*theline == '#' && (*linecopy == '#' || in_cinkeys('#', ' ', TRUE))) ++ { + amount = curbuf->b_ind_hash_comment; ++ goto theend; ++ } + + /* + * Is it a non-case label? Then that goes at the left margin too unless: + * - JS flag is set. + * - 'L' item has a positive value. + */ +! if (original_line_islabel && !curbuf->b_ind_js + && curbuf->b_ind_jump_label < 0) + { + amount = 0; ++ goto theend; + } + + /* + * If we're inside a "//" comment and there is a "//" comment in a + * previous line, lineup with that one. + */ +! if (cin_islinecomment(theline) + && (trypos = find_line_comment()) != NULL) /* XXX */ + { + /* find how indented the line beginning the comment is */ + getvcol(curwin, trypos, &col, NULL, NULL); + amount = col; ++ goto theend; + } + + /* + * If we're inside a comment and not looking at the start of the + * comment, try using the 'comments' option. + */ +! if (!cin_iscomment(theline) && comment_pos != NULL) /* XXX */ + { + int lead_start_len = 2; + int lead_middle_len = 1; +*************** +*** 7164,7170 **** + int done = FALSE; + + /* find how indented the line beginning the comment is */ +! getvcol(curwin, trypos, &col, NULL, NULL); + amount = col; + *lead_start = NUL; + *lead_middle = NUL; +--- 7274,7280 ---- + int done = FALSE; + + /* find how indented the line beginning the comment is */ +! getvcol(curwin, comment_pos, &col, NULL, NULL); + amount = col; + *lead_start = NUL; + *lead_middle = NUL; +*************** +*** 7228,7234 **** + } + /* If the start comment string doesn't match with the + * start of the comment, skip this entry. XXX */ +! else if (STRNCMP(ml_get(trypos->lnum) + trypos->col, + lead_start, lead_start_len) != 0) + continue; + } +--- 7338,7344 ---- + } + /* If the start comment string doesn't match with the + * start of the comment, skip this entry. XXX */ +! else if (STRNCMP(ml_get(comment_pos->lnum) + comment_pos->col, + lead_start, lead_start_len) != 0) + continue; + } +*************** +*** 7276,7282 **** + * otherwise, add the amount specified by "c" in 'cino' + */ + amount = -1; +! for (lnum = cur_curpos.lnum - 1; lnum > trypos->lnum; --lnum) + { + if (linewhite(lnum)) /* skip blank lines */ + continue; +--- 7386,7392 ---- + * otherwise, add the amount specified by "c" in 'cino' + */ + amount = -1; +! for (lnum = cur_curpos.lnum - 1; lnum > comment_pos->lnum; --lnum) + { + if (linewhite(lnum)) /* skip blank lines */ + continue; +*************** +*** 7287,7319 **** + { + if (!curbuf->b_ind_in_comment2) + { +! start = ml_get(trypos->lnum); +! look = start + trypos->col + 2; /* skip / and * */ + if (*look != NUL) /* if something after it */ +! trypos->col = (colnr_T)(skipwhite(look) - start); + } +! getvcol(curwin, trypos, &col, NULL, NULL); + amount = col; + if (curbuf->b_ind_in_comment2 || *look == NUL) + amount += curbuf->b_ind_in_comment; + } + } + } + + /* + * Are we looking at a ']' that has a match? + */ +! else if (*skipwhite(theline) == ']' + && (trypos = find_match_char('[', curbuf->b_ind_maxparen)) != NULL) + { + /* align with the line containing the '['. */ + amount = get_indent_lnum(trypos->lnum); + } + + /* + * Are we inside parentheses or braces? + */ /* XXX */ +! else if (((trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL + && curbuf->b_ind_java == 0) + || (tryposBrace = find_start_brace()) != NULL + || trypos != NULL) +--- 7397,7431 ---- + { + if (!curbuf->b_ind_in_comment2) + { +! start = ml_get(comment_pos->lnum); +! look = start + comment_pos->col + 2; /* skip / and * */ + if (*look != NUL) /* if something after it */ +! comment_pos->col = (colnr_T)(skipwhite(look) - start); + } +! getvcol(curwin, comment_pos, &col, NULL, NULL); + amount = col; + if (curbuf->b_ind_in_comment2 || *look == NUL) + amount += curbuf->b_ind_in_comment; + } + } ++ goto theend; + } + + /* + * Are we looking at a ']' that has a match? + */ +! if (*skipwhite(theline) == ']' + && (trypos = find_match_char('[', curbuf->b_ind_maxparen)) != NULL) + { + /* align with the line containing the '['. */ + amount = get_indent_lnum(trypos->lnum); ++ goto theend; + } + + /* + * Are we inside parentheses or braces? + */ /* XXX */ +! if (((trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL + && curbuf->b_ind_java == 0) + || (tryposBrace = find_start_brace()) != NULL + || trypos != NULL) +*************** +*** 7354,7361 **** + continue; /* ignore #define, #if, etc. */ + curwin->w_cursor.lnum = lnum; + +! /* Skip a comment. XXX */ +! if ((trypos = ind_find_start_comment()) != NULL) + { + lnum = trypos->lnum + 1; + continue; +--- 7466,7473 ---- + continue; /* ignore #define, #if, etc. */ + curwin->w_cursor.lnum = lnum; + +! /* Skip a comment or raw string. XXX */ +! if ((trypos = ind_find_start_CORS()) != NULL) + { + lnum = trypos->lnum + 1; + continue; +*************** +*** 7583,7590 **** + * Make a copy of tryposBrace, it may point to pos_copy inside + * find_start_brace(), which may be changed somewhere. + */ +! tryposBraceCopy = *tryposBrace; +! tryposBrace = &tryposBraceCopy; + trypos = tryposBrace; + ourscope = trypos->lnum; + start = ml_get(ourscope); +--- 7695,7702 ---- + * Make a copy of tryposBrace, it may point to pos_copy inside + * find_start_brace(), which may be changed somewhere. + */ +! tryposCopy = *tryposBrace; +! tryposBrace = &tryposCopy; + trypos = tryposBrace; + ourscope = trypos->lnum; + start = ml_get(ourscope); +*************** +*** 7791,7800 **** + l = ml_get_curline(); + + /* +! * If we're in a comment now, skip to the start of the +! * comment. + */ +! trypos = ind_find_start_comment(); + if (trypos != NULL) + { + curwin->w_cursor.lnum = trypos->lnum + 1; +--- 7903,7912 ---- + l = ml_get_curline(); + + /* +! * If we're in a comment or raw string now, skip to +! * the start of it. + */ +! trypos = ind_find_start_CORS(); + if (trypos != NULL) + { + curwin->w_cursor.lnum = trypos->lnum + 1; +*************** +*** 7911,7919 **** + + l = ml_get_curline(); + +! /* If we're in a comment now, skip to the start of +! * the comment. */ +! trypos = ind_find_start_comment(); + if (trypos != NULL) + { + curwin->w_cursor.lnum = trypos->lnum + 1; +--- 8023,8031 ---- + + l = ml_get_curline(); + +! /* If we're in a comment or raw string now, skip +! * to the start of it. */ +! trypos = ind_find_start_CORS(); + if (trypos != NULL) + { + curwin->w_cursor.lnum = trypos->lnum + 1; +*************** +*** 7941,7949 **** + } + + /* +! * If we're in a comment now, skip to the start of the comment. + */ /* XXX */ +! if ((trypos = ind_find_start_comment()) != NULL) + { + curwin->w_cursor.lnum = trypos->lnum + 1; + curwin->w_cursor.col = 0; +--- 8053,8062 ---- + } + + /* +! * If we're in a comment or raw string now, skip to the start +! * of it. + */ /* XXX */ +! if ((trypos = ind_find_start_CORS()) != NULL) + { + curwin->w_cursor.lnum = trypos->lnum + 1; + curwin->w_cursor.col = 0; +*************** +*** 8729,9004 **** + /* subtract extra left-shift for jump labels */ + if (curbuf->b_ind_jump_label > 0 && original_line_islabel) + amount -= curbuf->b_ind_jump_label; + } +! else + { +! /* +! * ok -- we're not inside any sort of structure at all! +! * +! * This means we're at the top level, and everything should +! * basically just match where the previous line is, except +! * for the lines immediately following a function declaration, +! * which are K&R-style parameters and need to be indented. +! * +! * if our line starts with an open brace, forget about any +! * prevailing indent and make sure it looks like the start +! * of a function +! */ + +! if (theline[0] == '{') + { +! amount = curbuf->b_ind_first_open; + } + + /* +! * If the NEXT line is a function declaration, the current +! * line needs to be indented as a function type spec. +! * Don't do this if the current line looks like a comment or if the +! * current line is terminated, ie. ends in ';', or if the current line +! * contains { or }: "void f() {\n if (1)" +! */ +! else if (cur_curpos.lnum < curbuf->b_ml.ml_line_count +! && !cin_nocode(theline) +! && vim_strchr(theline, '{') == NULL +! && vim_strchr(theline, '}') == NULL +! && !cin_ends_in(theline, (char_u *)":", NULL) +! && !cin_ends_in(theline, (char_u *)",", NULL) +! && cin_isfuncdecl(NULL, cur_curpos.lnum + 1, +! cur_curpos.lnum + 1) +! && !cin_isterminated(theline, FALSE, TRUE)) + { +! amount = curbuf->b_ind_func_type; + } +! else + { +! amount = 0; +! curwin->w_cursor = cur_curpos; +! +! /* search backwards until we find something we recognize */ + +! while (curwin->w_cursor.lnum > 1) +! { +! curwin->w_cursor.lnum--; +! curwin->w_cursor.col = 0; + +! l = ml_get_curline(); + +! /* +! * If we're in a comment now, skip to the start of the comment. +! */ /* XXX */ +! if ((trypos = ind_find_start_comment()) != NULL) +! { +! curwin->w_cursor.lnum = trypos->lnum + 1; +! curwin->w_cursor.col = 0; +! continue; +! } + +! /* +! * Are we at the start of a cpp base class declaration or +! * constructor initialization? +! */ /* XXX */ +! n = FALSE; +! if (curbuf->b_ind_cpp_baseclass != 0 && theline[0] != '{') +! { +! n = cin_is_cpp_baseclass(&cache_cpp_baseclass); +! l = ml_get_curline(); +! } +! if (n) +! { +! /* XXX */ +! amount = get_baseclass_amount(cache_cpp_baseclass.lpos.col); + break; +! } +! +! /* +! * Skip preprocessor directives and blank lines. +! */ +! if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum)) +! continue; +! +! if (cin_nocode(l)) +! continue; + +! /* +! * If the previous line ends in ',', use one level of +! * indentation: +! * int foo, +! * bar; +! * do this before checking for '}' in case of eg. +! * enum foobar +! * { +! * ... +! * } foo, +! * bar; +! */ +! n = 0; +! if (cin_ends_in(l, (char_u *)",", NULL) +! || (*l != NUL && (n = l[STRLEN(l) - 1]) == '\\')) +! { +! /* take us back to opening paren */ +! if (find_last_paren(l, '(', ')') +! && (trypos = find_match_paren( +! curbuf->b_ind_maxparen)) != NULL) +! curwin->w_cursor = *trypos; + +! /* For a line ending in ',' that is a continuation line go +! * back to the first line with a backslash: +! * char *foo = "bla\ +! * bla", +! * here; +! */ +! while (n == 0 && curwin->w_cursor.lnum > 1) +! { +! l = ml_get(curwin->w_cursor.lnum - 1); +! if (*l == NUL || l[STRLEN(l) - 1] != '\\') +! break; +! --curwin->w_cursor.lnum; +! curwin->w_cursor.col = 0; +! } + +! amount = get_indent(); /* XXX */ + +! if (amount == 0) +! amount = cin_first_id_amount(); +! if (amount == 0) +! amount = ind_continuation; +! break; +! } + +! /* +! * If the line looks like a function declaration, and we're +! * not in a comment, put it the left margin. +! */ +! if (cin_isfuncdecl(NULL, cur_curpos.lnum, 0)) /* XXX */ +! break; +! l = ml_get_curline(); + +! /* +! * Finding the closing '}' of a previous function. Put +! * current line at the left margin. For when 'cino' has "fs". +! */ +! if (*skipwhite(l) == '}') +! break; + +! /* (matching {) +! * If the previous line ends on '};' (maybe followed by +! * comments) align at column 0. For example: +! * char *string_array[] = { "foo", +! * / * x * / "b};ar" }; / * foobar * / +! */ +! if (cin_ends_in(l, (char_u *)"};", NULL)) +! break; + +! /* +! * If the previous line ends on '[' we are probably in an +! * array constant: +! * something = [ +! * 234, <- extra indent +! */ +! if (cin_ends_in(l, (char_u *)"[", NULL)) +! { +! amount = get_indent() + ind_continuation; + break; +! } +! +! /* +! * Find a line only has a semicolon that belongs to a previous +! * line ending in '}', e.g. before an #endif. Don't increase +! * indent then. +! */ +! if (*(look = skipwhite(l)) == ';' && cin_nocode(look + 1)) +! { +! pos_T curpos_save = curwin->w_cursor; +! +! while (curwin->w_cursor.lnum > 1) +! { +! look = ml_get(--curwin->w_cursor.lnum); +! if (!(cin_nocode(look) || cin_ispreproc_cont( +! &look, &curwin->w_cursor.lnum))) +! break; +! } +! if (curwin->w_cursor.lnum > 0 +! && cin_ends_in(look, (char_u *)"}", NULL)) +! break; + +! curwin->w_cursor = curpos_save; +! } + +! /* +! * If the PREVIOUS line is a function declaration, the current +! * line (and the ones that follow) needs to be indented as +! * parameters. +! */ +! if (cin_isfuncdecl(&l, curwin->w_cursor.lnum, 0)) +! { +! amount = curbuf->b_ind_param; +! break; +! } + +! /* +! * If the previous line ends in ';' and the line before the +! * previous line ends in ',' or '\', ident to column zero: +! * int foo, +! * bar; +! * indent_to_0 here; +! */ +! if (cin_ends_in(l, (char_u *)";", NULL)) +! { +! l = ml_get(curwin->w_cursor.lnum - 1); +! if (cin_ends_in(l, (char_u *)",", NULL) +! || (*l != NUL && l[STRLEN(l) - 1] == '\\')) +! break; +! l = ml_get_curline(); +! } + +! /* +! * Doesn't look like anything interesting -- so just +! * use the indent of this line. +! * +! * Position the cursor over the rightmost paren, so that +! * matching it will take us back to the start of the line. +! */ +! find_last_paren(l, '(', ')'); + +! if ((trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL) +! curwin->w_cursor = *trypos; +! amount = get_indent(); /* XXX */ +! break; +! } + +! /* add extra indent for a comment */ +! if (cin_iscomment(theline)) +! amount += curbuf->b_ind_comment; +! +! /* add extra indent if the previous line ended in a backslash: +! * "asdfasdf\ +! * here"; +! * char *foo = "asdf\ +! * here"; +! */ +! if (cur_curpos.lnum > 1) +! { +! l = ml_get(cur_curpos.lnum - 1); +! if (*l != NUL && l[STRLEN(l) - 1] == '\\') +! { +! cur_amount = cin_get_equal_amount(cur_curpos.lnum - 1); +! if (cur_amount > 0) +! amount = cur_amount; +! else if (cur_amount == 0) +! amount += ind_continuation; +! } +! } + } + } + + theend: + /* put the cursor back where it belongs */ + curwin->w_cursor = cur_curpos; + + vim_free(linecopy); + +- if (amount < 0) +- return 0; + return amount; + } + +--- 8842,9118 ---- + /* subtract extra left-shift for jump labels */ + if (curbuf->b_ind_jump_label > 0 && original_line_islabel) + amount -= curbuf->b_ind_jump_label; ++ ++ goto theend; + } +! +! /* +! * ok -- we're not inside any sort of structure at all! +! * +! * This means we're at the top level, and everything should +! * basically just match where the previous line is, except +! * for the lines immediately following a function declaration, +! * which are K&R-style parameters and need to be indented. +! * +! * if our line starts with an open brace, forget about any +! * prevailing indent and make sure it looks like the start +! * of a function +! */ +! +! if (theline[0] == '{') + { +! amount = curbuf->b_ind_first_open; +! goto theend; +! } + +! /* +! * If the NEXT line is a function declaration, the current +! * line needs to be indented as a function type spec. +! * Don't do this if the current line looks like a comment or if the +! * current line is terminated, ie. ends in ';', or if the current line +! * contains { or }: "void f() {\n if (1)" +! */ +! if (cur_curpos.lnum < curbuf->b_ml.ml_line_count +! && !cin_nocode(theline) +! && vim_strchr(theline, '{') == NULL +! && vim_strchr(theline, '}') == NULL +! && !cin_ends_in(theline, (char_u *)":", NULL) +! && !cin_ends_in(theline, (char_u *)",", NULL) +! && cin_isfuncdecl(NULL, cur_curpos.lnum + 1, +! cur_curpos.lnum + 1) +! && !cin_isterminated(theline, FALSE, TRUE)) +! { +! amount = curbuf->b_ind_func_type; +! goto theend; +! } +! +! /* search backwards until we find something we recognize */ +! amount = 0; +! curwin->w_cursor = cur_curpos; +! while (curwin->w_cursor.lnum > 1) +! { +! curwin->w_cursor.lnum--; +! curwin->w_cursor.col = 0; +! +! l = ml_get_curline(); +! +! /* +! * If we're in a comment or raw string now, skip to the start +! * of it. +! */ /* XXX */ +! if ((trypos = ind_find_start_CORS()) != NULL) + { +! curwin->w_cursor.lnum = trypos->lnum + 1; +! curwin->w_cursor.col = 0; +! continue; + } + + /* +! * Are we at the start of a cpp base class declaration or +! * constructor initialization? +! */ /* XXX */ +! n = FALSE; +! if (curbuf->b_ind_cpp_baseclass != 0 && theline[0] != '{') + { +! n = cin_is_cpp_baseclass(&cache_cpp_baseclass); +! l = ml_get_curline(); + } +! if (n) + { +! /* XXX */ +! amount = get_baseclass_amount(cache_cpp_baseclass.lpos.col); +! break; +! } + +! /* +! * Skip preprocessor directives and blank lines. +! */ +! if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum)) +! continue; + +! if (cin_nocode(l)) +! continue; + +! /* +! * If the previous line ends in ',', use one level of +! * indentation: +! * int foo, +! * bar; +! * do this before checking for '}' in case of eg. +! * enum foobar +! * { +! * ... +! * } foo, +! * bar; +! */ +! n = 0; +! if (cin_ends_in(l, (char_u *)",", NULL) +! || (*l != NUL && (n = l[STRLEN(l) - 1]) == '\\')) +! { +! /* take us back to opening paren */ +! if (find_last_paren(l, '(', ')') +! && (trypos = find_match_paren( +! curbuf->b_ind_maxparen)) != NULL) +! curwin->w_cursor = *trypos; + +! /* For a line ending in ',' that is a continuation line go +! * back to the first line with a backslash: +! * char *foo = "bla\ +! * bla", +! * here; +! */ +! while (n == 0 && curwin->w_cursor.lnum > 1) +! { +! l = ml_get(curwin->w_cursor.lnum - 1); +! if (*l == NUL || l[STRLEN(l) - 1] != '\\') + break; +! --curwin->w_cursor.lnum; +! curwin->w_cursor.col = 0; +! } + +! amount = get_indent(); /* XXX */ + +! if (amount == 0) +! amount = cin_first_id_amount(); +! if (amount == 0) +! amount = ind_continuation; +! break; +! } + +! /* +! * If the line looks like a function declaration, and we're +! * not in a comment, put it the left margin. +! */ +! if (cin_isfuncdecl(NULL, cur_curpos.lnum, 0)) /* XXX */ +! break; +! l = ml_get_curline(); + +! /* +! * Finding the closing '}' of a previous function. Put +! * current line at the left margin. For when 'cino' has "fs". +! */ +! if (*skipwhite(l) == '}') +! break; + +! /* (matching {) +! * If the previous line ends on '};' (maybe followed by +! * comments) align at column 0. For example: +! * char *string_array[] = { "foo", +! * / * x * / "b};ar" }; / * foobar * / +! */ +! if (cin_ends_in(l, (char_u *)"};", NULL)) +! break; + +! /* +! * If the previous line ends on '[' we are probably in an +! * array constant: +! * something = [ +! * 234, <- extra indent +! */ +! if (cin_ends_in(l, (char_u *)"[", NULL)) +! { +! amount = get_indent() + ind_continuation; +! break; +! } + +! /* +! * Find a line only has a semicolon that belongs to a previous +! * line ending in '}', e.g. before an #endif. Don't increase +! * indent then. +! */ +! if (*(look = skipwhite(l)) == ';' && cin_nocode(look + 1)) +! { +! pos_T curpos_save = curwin->w_cursor; + +! while (curwin->w_cursor.lnum > 1) +! { +! look = ml_get(--curwin->w_cursor.lnum); +! if (!(cin_nocode(look) || cin_ispreproc_cont( +! &look, &curwin->w_cursor.lnum))) + break; +! } +! if (curwin->w_cursor.lnum > 0 +! && cin_ends_in(look, (char_u *)"}", NULL)) +! break; + +! curwin->w_cursor = curpos_save; +! } + +! /* +! * If the PREVIOUS line is a function declaration, the current +! * line (and the ones that follow) needs to be indented as +! * parameters. +! */ +! if (cin_isfuncdecl(&l, curwin->w_cursor.lnum, 0)) +! { +! amount = curbuf->b_ind_param; +! break; +! } + +! /* +! * If the previous line ends in ';' and the line before the +! * previous line ends in ',' or '\', ident to column zero: +! * int foo, +! * bar; +! * indent_to_0 here; +! */ +! if (cin_ends_in(l, (char_u *)";", NULL)) +! { +! l = ml_get(curwin->w_cursor.lnum - 1); +! if (cin_ends_in(l, (char_u *)",", NULL) +! || (*l != NUL && l[STRLEN(l) - 1] == '\\')) +! break; +! l = ml_get_curline(); +! } + +! /* +! * Doesn't look like anything interesting -- so just +! * use the indent of this line. +! * +! * Position the cursor over the rightmost paren, so that +! * matching it will take us back to the start of the line. +! */ +! find_last_paren(l, '(', ')'); + +! if ((trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL) +! curwin->w_cursor = *trypos; +! amount = get_indent(); /* XXX */ +! break; +! } + +! /* add extra indent for a comment */ +! if (cin_iscomment(theline)) +! amount += curbuf->b_ind_comment; +! +! /* add extra indent if the previous line ended in a backslash: +! * "asdfasdf\ +! * here"; +! * char *foo = "asdf\ +! * here"; +! */ +! if (cur_curpos.lnum > 1) +! { +! l = ml_get(cur_curpos.lnum - 1); +! if (*l != NUL && l[STRLEN(l) - 1] == '\\') +! { +! cur_amount = cin_get_equal_amount(cur_curpos.lnum - 1); +! if (cur_amount > 0) +! amount = cur_amount; +! else if (cur_amount == 0) +! amount += ind_continuation; + } + } + + theend: ++ if (amount < 0) ++ amount = 0; ++ ++ laterend: + /* put the cursor back where it belongs */ + curwin->w_cursor = cur_curpos; + + vim_free(linecopy); + + return amount; + } + +*** ../vim-7.4.802/src/edit.c 2015-07-21 17:53:11.577527989 +0200 +--- src/edit.c 2015-07-28 19:40:27.771945786 +0200 +*************** +*** 7813,7821 **** + fixthisline(get_the_indent) + int (*get_the_indent) __ARGS((void)); + { +! change_indent(INDENT_SET, get_the_indent(), FALSE, 0, TRUE); +! if (linewhite(curwin->w_cursor.lnum)) +! did_ai = TRUE; /* delete the indent if the line stays empty */ + } + + void +--- 7813,7826 ---- + fixthisline(get_the_indent) + int (*get_the_indent) __ARGS((void)); + { +! int amount = get_the_indent(); +! +! if (amount >= 0) +! { +! change_indent(INDENT_SET, amount, FALSE, 0, TRUE); +! if (linewhite(curwin->w_cursor.lnum)) +! did_ai = TRUE; /* delete the indent if the line stays empty */ +! } + } + + void +*** ../vim-7.4.802/src/ops.c 2015-07-22 22:46:08.127010101 +0200 +--- src/ops.c 2015-07-28 19:45:37.060848436 +0200 +*************** +*** 686,692 **** + { + long i; + char_u *l; +! int count; + linenr_T first_changed = 0; + linenr_T last_changed = 0; + linenr_T start_lnum = curwin->w_cursor.lnum; +--- 686,692 ---- + { + long i; + char_u *l; +! int amount; + linenr_T first_changed = 0; + linenr_T last_changed = 0; + linenr_T start_lnum = curwin->w_cursor.lnum; +*************** +*** 719,729 **** + { + l = skipwhite(ml_get_curline()); + if (*l == NUL) /* empty or blank line */ +! count = 0; + else +! count = how(); /* get the indent for this line */ + +! if (set_indent(count, SIN_UNDO)) + { + /* did change the indent, call changed_lines() later */ + if (first_changed == 0) +--- 719,729 ---- + { + l = skipwhite(ml_get_curline()); + if (*l == NUL) /* empty or blank line */ +! amount = 0; + else +! amount = how(); /* get the indent for this line */ + +! if (amount >= 0 && set_indent(amount, SIN_UNDO)) + { + /* did change the indent, call changed_lines() later */ + if (first_changed == 0) +*** ../vim-7.4.802/src/testdir/test3.in 2015-03-20 19:06:01.982429823 +0100 +--- src/testdir/test3.in 2015-07-28 20:03:32.290099553 +0200 +*************** +*** 891,896 **** +--- 891,915 ---- + 111111111111111111; + } + ++ void getstring() { ++ /* Raw strings */ ++ const char* s = R"( ++ test { ++ # comment ++ field: 123 ++ } ++ )"; ++ } ++ ++ void getstring() { ++ const char* s = R"foo( ++ test { ++ # comment ++ field: 123 ++ } ++ )foo"; ++ } ++ + /* end of AUTO */ + + STARTTEST +*** ../vim-7.4.802/src/testdir/test3.ok 2015-03-20 19:06:01.986429778 +0100 +--- src/testdir/test3.ok 2015-07-28 20:03:59.985823030 +0200 +*************** +*** 879,884 **** +--- 879,903 ---- + 111111111111111111; + } + ++ void getstring() { ++ /* Raw strings */ ++ const char* s = R"( ++ test { ++ # comment ++ field: 123 ++ } ++ )"; ++ } ++ ++ void getstring() { ++ const char* s = R"foo( ++ test { ++ # comment ++ field: 123 ++ } ++ )foo"; ++ } ++ + /* end of AUTO */ + + +*** ../vim-7.4.802/src/version.c 2015-07-28 17:16:28.302488118 +0200 +--- src/version.c 2015-07-28 21:07:42.219893314 +0200 +*************** +*** 743,744 **** +--- 743,746 ---- + { /* Add new patch number below this line */ ++ /**/ ++ 803, + /**/ + +-- +Facepalm statement #4: "3000 year old graves? That's not possible, it's only +2014!" + + /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ +/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ +\\\ an exciting new programming language -- http://www.Zimbu.org /// + \\\ help me help AIDS victims -- http://ICCF-Holland.org ///