comparison src/misc1.c @ 6971:e859731ea1cd v7.4.803

patch 7.4.803 Problem: C indent does not support C11 raw strings. (Mark Lodato) Solution: Do not change indent inside the raw string.
author Bram Moolenaar <bram@vim.org>
date Tue, 28 Jul 2015 21:17:36 +0200
parents 1e621b31948b
children 5f00b8d7148f
comparison
equal deleted inserted replaced
6970:589a962ecc16 6971:e859731ea1cd
5265 5265
5266 #if defined(FEAT_CINDENT) || defined(FEAT_SYN_HL) 5266 #if defined(FEAT_CINDENT) || defined(FEAT_SYN_HL)
5267 5267
5268 static char_u *skip_string __ARGS((char_u *p)); 5268 static char_u *skip_string __ARGS((char_u *p));
5269 static pos_T *ind_find_start_comment __ARGS((void)); 5269 static pos_T *ind_find_start_comment __ARGS((void));
5270 static pos_T *ind_find_start_CORS __ARGS((void));
5271 static pos_T *find_start_rawstring __ARGS((int ind_maxcomment));
5270 5272
5271 /* 5273 /*
5272 * Find the start of a comment, not knowing if we are in a comment right now. 5274 * Find the start of a comment, not knowing if we are in a comment right now.
5273 * Search starts at w_cursor.lnum and goes backwards. 5275 * Search starts at w_cursor.lnum and goes backwards.
5276 * Return NULL when not inside a comment.
5274 */ 5277 */
5275 static pos_T * 5278 static pos_T *
5276 ind_find_start_comment() /* XXX */ 5279 ind_find_start_comment() /* XXX */
5277 { 5280 {
5278 return find_start_comment(curbuf->b_ind_maxcomment); 5281 return find_start_comment(curbuf->b_ind_maxcomment);
5311 } 5314 }
5312 return pos; 5315 return pos;
5313 } 5316 }
5314 5317
5315 /* 5318 /*
5319 * Find the start of a comment or raw string, not knowing if we are in a
5320 * comment or raw string right now.
5321 * Search starts at w_cursor.lnum and goes backwards.
5322 * Return NULL when not inside a comment or raw string.
5323 * "CORS" -> Comment Or Raw String
5324 */
5325 static pos_T *
5326 ind_find_start_CORS() /* XXX */
5327 {
5328 pos_T *comment_pos = find_start_comment(curbuf->b_ind_maxcomment);
5329 pos_T *rs_pos = find_start_rawstring(curbuf->b_ind_maxcomment);
5330
5331 /* If comment_pos is before rs_pos the raw string is inside the comment.
5332 * If rs_pos is before comment_pos the comment is inside the raw string. */
5333 if (comment_pos == NULL || (rs_pos != NULL && lt(*rs_pos, *comment_pos)))
5334 return rs_pos;
5335 return comment_pos;
5336 }
5337
5338 /*
5339 * Find the start of a raw string, not knowing if we are in one right now.
5340 * Search starts at w_cursor.lnum and goes backwards.
5341 * Return NULL when not inside a raw string.
5342 */
5343 static pos_T *
5344 find_start_rawstring(ind_maxcomment) /* XXX */
5345 int ind_maxcomment;
5346 {
5347 pos_T *pos;
5348 char_u *line;
5349 char_u *p;
5350 int cur_maxcomment = ind_maxcomment;
5351
5352 for (;;)
5353 {
5354 pos = findmatchlimit(NULL, 'R', FM_BACKWARD, cur_maxcomment);
5355 if (pos == NULL)
5356 break;
5357
5358 /*
5359 * Check if the raw string start we found is inside a string.
5360 * If it is then restrict the search to below this line and try again.
5361 */
5362 line = ml_get(pos->lnum);
5363 for (p = line; *p && (colnr_T)(p - line) < pos->col; ++p)
5364 p = skip_string(p);
5365 if ((colnr_T)(p - line) <= pos->col)
5366 break;
5367 cur_maxcomment = curwin->w_cursor.lnum - pos->lnum - 1;
5368 if (cur_maxcomment <= 0)
5369 {
5370 pos = NULL;
5371 break;
5372 }
5373 }
5374 return pos;
5375 }
5376
5377 /*
5316 * Skip to the end of a "string" and a 'c' character. 5378 * Skip to the end of a "string" and a 'c' character.
5317 * If there is no string or character, return argument unmodified. 5379 * If there is no string or character, return argument unmodified.
5318 */ 5380 */
5319 static char_u * 5381 static char_u *
5320 skip_string(p) 5382 skip_string(p)
5352 ++p; 5414 ++p;
5353 else if (p[0] == '"') /* end of string */ 5415 else if (p[0] == '"') /* end of string */
5354 break; 5416 break;
5355 } 5417 }
5356 if (p[0] == '"') 5418 if (p[0] == '"')
5357 continue; 5419 continue; /* continue for another string */
5420 }
5421 else if (p[0] == 'R' && p[1] == '"')
5422 {
5423 /* Raw string: R"[delim](...)[delim]" */
5424 char_u *delim = p + 2;
5425 char_u *paren = vim_strchr(delim, '(');
5426
5427 if (paren != NULL)
5428 {
5429 size_t delim_len = paren - delim;
5430
5431 for (p += 3; *p; ++p)
5432 if (p[0] == ')' && STRNCMP(p + 1, delim, delim_len) == 0
5433 && p[delim_len + 1] == '"')
5434 {
5435 p += delim_len + 1;
5436 break;
5437 }
5438 if (p[0] == '"')
5439 continue; /* continue for another string */
5440 }
5358 } 5441 }
5359 break; /* no string found */ 5442 break; /* no string found */
5360 } 5443 }
5361 if (!*p) 5444 if (!*p)
5362 --p; /* backup from NUL */ 5445 --p; /* backup from NUL */
5594 while (curwin->w_cursor.lnum > 1) 5677 while (curwin->w_cursor.lnum > 1)
5595 { 5678 {
5596 --curwin->w_cursor.lnum; 5679 --curwin->w_cursor.lnum;
5597 5680
5598 /* 5681 /*
5599 * If we're in a comment now, skip to the start of the comment. 5682 * If we're in a comment or raw string now, skip to the start of
5683 * it.
5600 */ 5684 */
5601 curwin->w_cursor.col = 0; 5685 curwin->w_cursor.col = 0;
5602 if ((trypos = ind_find_start_comment()) != NULL) /* XXX */ 5686 if ((trypos = ind_find_start_CORS()) != NULL) /* XXX */
5603 curwin->w_cursor = *trypos; 5687 curwin->w_cursor = *trypos;
5604 5688
5605 line = ml_get_curline(); 5689 line = ml_get_curline();
5606 if (cin_ispreproc(line)) /* ignore #defines, #if, etc. */ 5690 if (cin_ispreproc(line)) /* ignore #defines, #if, etc. */
5607 continue; 5691 continue;
6452 s = cin_skipcomment(line); 6536 s = cin_skipcomment(line);
6453 if (*s == NUL) 6537 if (*s == NUL)
6454 continue; 6538 continue;
6455 } 6539 }
6456 6540
6457 if (s[0] == '"') 6541 if (s[0] == '"' || (s[0] == 'R' && s[1] == '"'))
6458 s = skip_string(s) + 1; 6542 s = skip_string(s) + 1;
6459 else if (s[0] == ':') 6543 else if (s[0] == ':')
6460 { 6544 {
6461 if (s[1] == ':') 6545 if (s[1] == ':')
6462 { 6546 {
6658 trypos = &pos_copy; 6742 trypos = &pos_copy;
6659 curwin->w_cursor = *trypos; 6743 curwin->w_cursor = *trypos;
6660 pos = NULL; 6744 pos = NULL;
6661 /* ignore the { if it's in a // or / * * / comment */ 6745 /* ignore the { if it's in a // or / * * / comment */
6662 if ((colnr_T)cin_skip2pos(trypos) == trypos->col 6746 if ((colnr_T)cin_skip2pos(trypos) == trypos->col
6663 && (pos = ind_find_start_comment()) == NULL) /* XXX */ 6747 && (pos = ind_find_start_CORS()) == NULL) /* XXX */
6664 break; 6748 break;
6665 if (pos != NULL) 6749 if (pos != NULL)
6666 curwin->w_cursor.lnum = pos->lnum; 6750 curwin->w_cursor.lnum = pos->lnum;
6667 } 6751 }
6668 curwin->w_cursor = cursor_save; 6752 curwin->w_cursor = cursor_save;
6712 pos_T *trypos_wk; 6796 pos_T *trypos_wk;
6713 6797
6714 pos_copy = *trypos; /* copy trypos, findmatch will change it */ 6798 pos_copy = *trypos; /* copy trypos, findmatch will change it */
6715 trypos = &pos_copy; 6799 trypos = &pos_copy;
6716 curwin->w_cursor = *trypos; 6800 curwin->w_cursor = *trypos;
6717 if ((trypos_wk = ind_find_start_comment()) != NULL) /* XXX */ 6801 if ((trypos_wk = ind_find_start_CORS()) != NULL) /* XXX */
6718 { 6802 {
6719 ind_maxp_wk = ind_maxparen - (int)(cursor_save.lnum 6803 ind_maxp_wk = ind_maxparen - (int)(cursor_save.lnum
6720 - trypos_wk->lnum); 6804 - trypos_wk->lnum);
6721 if (ind_maxp_wk > 0) 6805 if (ind_maxp_wk > 0)
6722 { 6806 {
7027 if (*p == ',') 7111 if (*p == ',')
7028 ++p; 7112 ++p;
7029 } 7113 }
7030 } 7114 }
7031 7115
7116 /*
7117 * Return the desired indent for C code.
7118 * Return -1 if the indent should be left alone (inside a raw string).
7119 */
7032 int 7120 int
7033 get_c_indent() 7121 get_c_indent()
7034 { 7122 {
7035 pos_T cur_curpos; 7123 pos_T cur_curpos;
7036 int amount; 7124 int amount;
7038 int cur_amount = MAXCOL; 7126 int cur_amount = MAXCOL;
7039 colnr_T col; 7127 colnr_T col;
7040 char_u *theline; 7128 char_u *theline;
7041 char_u *linecopy; 7129 char_u *linecopy;
7042 pos_T *trypos; 7130 pos_T *trypos;
7131 pos_T *comment_pos;
7043 pos_T *tryposBrace = NULL; 7132 pos_T *tryposBrace = NULL;
7044 pos_T tryposBraceCopy; 7133 pos_T tryposCopy;
7045 pos_T our_paren_pos; 7134 pos_T our_paren_pos;
7046 char_u *start; 7135 char_u *start;
7047 int start_brace; 7136 int start_brace;
7048 #define BRACE_IN_COL0 1 /* '{' is in column 0 */ 7137 #define BRACE_IN_COL0 1 /* '{' is in column 0 */
7049 #define BRACE_AT_START 2 /* '{' is at start of line */ 7138 #define BRACE_AT_START 2 /* '{' is at start of line */
7083 int ind_continuation = curbuf->b_ind_continuation; 7172 int ind_continuation = curbuf->b_ind_continuation;
7084 7173
7085 /* remember where the cursor was when we started */ 7174 /* remember where the cursor was when we started */
7086 cur_curpos = curwin->w_cursor; 7175 cur_curpos = curwin->w_cursor;
7087 7176
7088 /* if we are at line 1 0 is fine, right? */ 7177 /* if we are at line 1 zero indent is fine, right? */
7089 if (cur_curpos.lnum == 1) 7178 if (cur_curpos.lnum == 1)
7090 return 0; 7179 return 0;
7091 7180
7092 /* Get a copy of the current contents of the line. 7181 /* Get a copy of the current contents of the line.
7093 * This is required, because only the most recent line obtained with 7182 * This is required, because only the most recent line obtained with
7115 curwin->w_cursor.col = 0; 7204 curwin->w_cursor.col = 0;
7116 7205
7117 original_line_islabel = cin_islabel(); /* XXX */ 7206 original_line_islabel = cin_islabel(); /* XXX */
7118 7207
7119 /* 7208 /*
7209 * If we are inside a raw string don't change the indent.
7210 * Ignore a raw string inside a comment.
7211 */
7212 comment_pos = ind_find_start_comment();
7213 if (comment_pos != NULL)
7214 {
7215 /* findmatchlimit() static pos is overwritten, make a copy */
7216 tryposCopy = *comment_pos;
7217 comment_pos = &tryposCopy;
7218 }
7219 trypos = find_start_rawstring(curbuf->b_ind_maxcomment);
7220 if (trypos != NULL && (comment_pos == NULL || lt(*trypos, *comment_pos)))
7221 {
7222 amount = -1;
7223 goto laterend;
7224 }
7225
7226 /*
7120 * #defines and so on always go at the left when included in 'cinkeys'. 7227 * #defines and so on always go at the left when included in 'cinkeys'.
7121 */ 7228 */
7122 if (*theline == '#' && (*linecopy == '#' || in_cinkeys('#', ' ', TRUE))) 7229 if (*theline == '#' && (*linecopy == '#' || in_cinkeys('#', ' ', TRUE)))
7230 {
7123 amount = curbuf->b_ind_hash_comment; 7231 amount = curbuf->b_ind_hash_comment;
7232 goto theend;
7233 }
7124 7234
7125 /* 7235 /*
7126 * Is it a non-case label? Then that goes at the left margin too unless: 7236 * Is it a non-case label? Then that goes at the left margin too unless:
7127 * - JS flag is set. 7237 * - JS flag is set.
7128 * - 'L' item has a positive value. 7238 * - 'L' item has a positive value.
7129 */ 7239 */
7130 else if (original_line_islabel && !curbuf->b_ind_js 7240 if (original_line_islabel && !curbuf->b_ind_js
7131 && curbuf->b_ind_jump_label < 0) 7241 && curbuf->b_ind_jump_label < 0)
7132 { 7242 {
7133 amount = 0; 7243 amount = 0;
7244 goto theend;
7134 } 7245 }
7135 7246
7136 /* 7247 /*
7137 * If we're inside a "//" comment and there is a "//" comment in a 7248 * If we're inside a "//" comment and there is a "//" comment in a
7138 * previous line, lineup with that one. 7249 * previous line, lineup with that one.
7139 */ 7250 */
7140 else if (cin_islinecomment(theline) 7251 if (cin_islinecomment(theline)
7141 && (trypos = find_line_comment()) != NULL) /* XXX */ 7252 && (trypos = find_line_comment()) != NULL) /* XXX */
7142 { 7253 {
7143 /* find how indented the line beginning the comment is */ 7254 /* find how indented the line beginning the comment is */
7144 getvcol(curwin, trypos, &col, NULL, NULL); 7255 getvcol(curwin, trypos, &col, NULL, NULL);
7145 amount = col; 7256 amount = col;
7257 goto theend;
7146 } 7258 }
7147 7259
7148 /* 7260 /*
7149 * If we're inside a comment and not looking at the start of the 7261 * If we're inside a comment and not looking at the start of the
7150 * comment, try using the 'comments' option. 7262 * comment, try using the 'comments' option.
7151 */ 7263 */
7152 else if (!cin_iscomment(theline) 7264 if (!cin_iscomment(theline) && comment_pos != NULL) /* XXX */
7153 && (trypos = ind_find_start_comment()) != NULL)
7154 /* XXX */
7155 { 7265 {
7156 int lead_start_len = 2; 7266 int lead_start_len = 2;
7157 int lead_middle_len = 1; 7267 int lead_middle_len = 1;
7158 char_u lead_start[COM_MAX_LEN]; /* start-comment string */ 7268 char_u lead_start[COM_MAX_LEN]; /* start-comment string */
7159 char_u lead_middle[COM_MAX_LEN]; /* middle-comment string */ 7269 char_u lead_middle[COM_MAX_LEN]; /* middle-comment string */
7162 int start_align = 0; 7272 int start_align = 0;
7163 int start_off = 0; 7273 int start_off = 0;
7164 int done = FALSE; 7274 int done = FALSE;
7165 7275
7166 /* find how indented the line beginning the comment is */ 7276 /* find how indented the line beginning the comment is */
7167 getvcol(curwin, trypos, &col, NULL, NULL); 7277 getvcol(curwin, comment_pos, &col, NULL, NULL);
7168 amount = col; 7278 amount = col;
7169 *lead_start = NUL; 7279 *lead_start = NUL;
7170 *lead_middle = NUL; 7280 *lead_middle = NUL;
7171 7281
7172 p = curbuf->b_p_com; 7282 p = curbuf->b_p_com;
7226 amount = get_indent_lnum(curwin->w_cursor.lnum - 1); 7336 amount = get_indent_lnum(curwin->w_cursor.lnum - 1);
7227 break; 7337 break;
7228 } 7338 }
7229 /* If the start comment string doesn't match with the 7339 /* If the start comment string doesn't match with the
7230 * start of the comment, skip this entry. XXX */ 7340 * start of the comment, skip this entry. XXX */
7231 else if (STRNCMP(ml_get(trypos->lnum) + trypos->col, 7341 else if (STRNCMP(ml_get(comment_pos->lnum) + comment_pos->col,
7232 lead_start, lead_start_len) != 0) 7342 lead_start, lead_start_len) != 0)
7233 continue; 7343 continue;
7234 } 7344 }
7235 if (start_off != 0) 7345 if (start_off != 0)
7236 amount += start_off; 7346 amount += start_off;
7274 * and we are just below the comment opener and there are any 7384 * and we are just below the comment opener and there are any
7275 * white characters after it line up with the text after it; 7385 * white characters after it line up with the text after it;
7276 * otherwise, add the amount specified by "c" in 'cino' 7386 * otherwise, add the amount specified by "c" in 'cino'
7277 */ 7387 */
7278 amount = -1; 7388 amount = -1;
7279 for (lnum = cur_curpos.lnum - 1; lnum > trypos->lnum; --lnum) 7389 for (lnum = cur_curpos.lnum - 1; lnum > comment_pos->lnum; --lnum)
7280 { 7390 {
7281 if (linewhite(lnum)) /* skip blank lines */ 7391 if (linewhite(lnum)) /* skip blank lines */
7282 continue; 7392 continue;
7283 amount = get_indent_lnum(lnum); /* XXX */ 7393 amount = get_indent_lnum(lnum); /* XXX */
7284 break; 7394 break;
7285 } 7395 }
7286 if (amount == -1) /* use the comment opener */ 7396 if (amount == -1) /* use the comment opener */
7287 { 7397 {
7288 if (!curbuf->b_ind_in_comment2) 7398 if (!curbuf->b_ind_in_comment2)
7289 { 7399 {
7290 start = ml_get(trypos->lnum); 7400 start = ml_get(comment_pos->lnum);
7291 look = start + trypos->col + 2; /* skip / and * */ 7401 look = start + comment_pos->col + 2; /* skip / and * */
7292 if (*look != NUL) /* if something after it */ 7402 if (*look != NUL) /* if something after it */
7293 trypos->col = (colnr_T)(skipwhite(look) - start); 7403 comment_pos->col = (colnr_T)(skipwhite(look) - start);
7294 } 7404 }
7295 getvcol(curwin, trypos, &col, NULL, NULL); 7405 getvcol(curwin, comment_pos, &col, NULL, NULL);
7296 amount = col; 7406 amount = col;
7297 if (curbuf->b_ind_in_comment2 || *look == NUL) 7407 if (curbuf->b_ind_in_comment2 || *look == NUL)
7298 amount += curbuf->b_ind_in_comment; 7408 amount += curbuf->b_ind_in_comment;
7299 } 7409 }
7300 } 7410 }
7411 goto theend;
7301 } 7412 }
7302 7413
7303 /* 7414 /*
7304 * Are we looking at a ']' that has a match? 7415 * Are we looking at a ']' that has a match?
7305 */ 7416 */
7306 else if (*skipwhite(theline) == ']' 7417 if (*skipwhite(theline) == ']'
7307 && (trypos = find_match_char('[', curbuf->b_ind_maxparen)) != NULL) 7418 && (trypos = find_match_char('[', curbuf->b_ind_maxparen)) != NULL)
7308 { 7419 {
7309 /* align with the line containing the '['. */ 7420 /* align with the line containing the '['. */
7310 amount = get_indent_lnum(trypos->lnum); 7421 amount = get_indent_lnum(trypos->lnum);
7422 goto theend;
7311 } 7423 }
7312 7424
7313 /* 7425 /*
7314 * Are we inside parentheses or braces? 7426 * Are we inside parentheses or braces?
7315 */ /* XXX */ 7427 */ /* XXX */
7316 else if (((trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL 7428 if (((trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL
7317 && curbuf->b_ind_java == 0) 7429 && curbuf->b_ind_java == 0)
7318 || (tryposBrace = find_start_brace()) != NULL 7430 || (tryposBrace = find_start_brace()) != NULL
7319 || trypos != NULL) 7431 || trypos != NULL)
7320 { 7432 {
7321 if (trypos != NULL && tryposBrace != NULL) 7433 if (trypos != NULL && tryposBrace != NULL)
7352 continue; 7464 continue;
7353 if (cin_ispreproc_cont(&l, &lnum)) 7465 if (cin_ispreproc_cont(&l, &lnum))
7354 continue; /* ignore #define, #if, etc. */ 7466 continue; /* ignore #define, #if, etc. */
7355 curwin->w_cursor.lnum = lnum; 7467 curwin->w_cursor.lnum = lnum;
7356 7468
7357 /* Skip a comment. XXX */ 7469 /* Skip a comment or raw string. XXX */
7358 if ((trypos = ind_find_start_comment()) != NULL) 7470 if ((trypos = ind_find_start_CORS()) != NULL)
7359 { 7471 {
7360 lnum = trypos->lnum + 1; 7472 lnum = trypos->lnum + 1;
7361 continue; 7473 continue;
7362 } 7474 }
7363 7475
7581 * We are inside braces, there is a { before this line at the position 7693 * We are inside braces, there is a { before this line at the position
7582 * stored in tryposBrace. 7694 * stored in tryposBrace.
7583 * Make a copy of tryposBrace, it may point to pos_copy inside 7695 * Make a copy of tryposBrace, it may point to pos_copy inside
7584 * find_start_brace(), which may be changed somewhere. 7696 * find_start_brace(), which may be changed somewhere.
7585 */ 7697 */
7586 tryposBraceCopy = *tryposBrace; 7698 tryposCopy = *tryposBrace;
7587 tryposBrace = &tryposBraceCopy; 7699 tryposBrace = &tryposCopy;
7588 trypos = tryposBrace; 7700 trypos = tryposBrace;
7589 ourscope = trypos->lnum; 7701 ourscope = trypos->lnum;
7590 start = ml_get(ourscope); 7702 start = ml_get(ourscope);
7591 7703
7592 /* 7704 /*
7789 } 7901 }
7790 7902
7791 l = ml_get_curline(); 7903 l = ml_get_curline();
7792 7904
7793 /* 7905 /*
7794 * If we're in a comment now, skip to the start of the 7906 * If we're in a comment or raw string now, skip to
7795 * comment. 7907 * the start of it.
7796 */ 7908 */
7797 trypos = ind_find_start_comment(); 7909 trypos = ind_find_start_CORS();
7798 if (trypos != NULL) 7910 if (trypos != NULL)
7799 { 7911 {
7800 curwin->w_cursor.lnum = trypos->lnum + 1; 7912 curwin->w_cursor.lnum = trypos->lnum + 1;
7801 curwin->w_cursor.col = 0; 7913 curwin->w_cursor.col = 0;
7802 continue; 7914 continue;
7909 < ourscope - FIND_NAMESPACE_LIM) 8021 < ourscope - FIND_NAMESPACE_LIM)
7910 break; 8022 break;
7911 8023
7912 l = ml_get_curline(); 8024 l = ml_get_curline();
7913 8025
7914 /* If we're in a comment now, skip to the start of 8026 /* If we're in a comment or raw string now, skip
7915 * the comment. */ 8027 * to the start of it. */
7916 trypos = ind_find_start_comment(); 8028 trypos = ind_find_start_CORS();
7917 if (trypos != NULL) 8029 if (trypos != NULL)
7918 { 8030 {
7919 curwin->w_cursor.lnum = trypos->lnum + 1; 8031 curwin->w_cursor.lnum = trypos->lnum + 1;
7920 curwin->w_cursor.col = 0; 8032 curwin->w_cursor.col = 0;
7921 continue; 8033 continue;
7939 } 8051 }
7940 break; 8052 break;
7941 } 8053 }
7942 8054
7943 /* 8055 /*
7944 * If we're in a comment now, skip to the start of the comment. 8056 * If we're in a comment or raw string now, skip to the start
8057 * of it.
7945 */ /* XXX */ 8058 */ /* XXX */
7946 if ((trypos = ind_find_start_comment()) != NULL) 8059 if ((trypos = ind_find_start_CORS()) != NULL)
7947 { 8060 {
7948 curwin->w_cursor.lnum = trypos->lnum + 1; 8061 curwin->w_cursor.lnum = trypos->lnum + 1;
7949 curwin->w_cursor.col = 0; 8062 curwin->w_cursor.col = 0;
7950 continue; 8063 continue;
7951 } 8064 }
8727 amount += curbuf->b_ind_comment; 8840 amount += curbuf->b_ind_comment;
8728 8841
8729 /* subtract extra left-shift for jump labels */ 8842 /* subtract extra left-shift for jump labels */
8730 if (curbuf->b_ind_jump_label > 0 && original_line_islabel) 8843 if (curbuf->b_ind_jump_label > 0 && original_line_islabel)
8731 amount -= curbuf->b_ind_jump_label; 8844 amount -= curbuf->b_ind_jump_label;
8732 } 8845
8733 else 8846 goto theend;
8734 { 8847 }
8848
8849 /*
8850 * ok -- we're not inside any sort of structure at all!
8851 *
8852 * This means we're at the top level, and everything should
8853 * basically just match where the previous line is, except
8854 * for the lines immediately following a function declaration,
8855 * which are K&R-style parameters and need to be indented.
8856 *
8857 * if our line starts with an open brace, forget about any
8858 * prevailing indent and make sure it looks like the start
8859 * of a function
8860 */
8861
8862 if (theline[0] == '{')
8863 {
8864 amount = curbuf->b_ind_first_open;
8865 goto theend;
8866 }
8867
8868 /*
8869 * If the NEXT line is a function declaration, the current
8870 * line needs to be indented as a function type spec.
8871 * Don't do this if the current line looks like a comment or if the
8872 * current line is terminated, ie. ends in ';', or if the current line
8873 * contains { or }: "void f() {\n if (1)"
8874 */
8875 if (cur_curpos.lnum < curbuf->b_ml.ml_line_count
8876 && !cin_nocode(theline)
8877 && vim_strchr(theline, '{') == NULL
8878 && vim_strchr(theline, '}') == NULL
8879 && !cin_ends_in(theline, (char_u *)":", NULL)
8880 && !cin_ends_in(theline, (char_u *)",", NULL)
8881 && cin_isfuncdecl(NULL, cur_curpos.lnum + 1,
8882 cur_curpos.lnum + 1)
8883 && !cin_isterminated(theline, FALSE, TRUE))
8884 {
8885 amount = curbuf->b_ind_func_type;
8886 goto theend;
8887 }
8888
8889 /* search backwards until we find something we recognize */
8890 amount = 0;
8891 curwin->w_cursor = cur_curpos;
8892 while (curwin->w_cursor.lnum > 1)
8893 {
8894 curwin->w_cursor.lnum--;
8895 curwin->w_cursor.col = 0;
8896
8897 l = ml_get_curline();
8898
8735 /* 8899 /*
8736 * ok -- we're not inside any sort of structure at all! 8900 * If we're in a comment or raw string now, skip to the start
8901 * of it.
8902 */ /* XXX */
8903 if ((trypos = ind_find_start_CORS()) != NULL)
8904 {
8905 curwin->w_cursor.lnum = trypos->lnum + 1;
8906 curwin->w_cursor.col = 0;
8907 continue;
8908 }
8909
8910 /*
8911 * Are we at the start of a cpp base class declaration or
8912 * constructor initialization?
8913 */ /* XXX */
8914 n = FALSE;
8915 if (curbuf->b_ind_cpp_baseclass != 0 && theline[0] != '{')
8916 {
8917 n = cin_is_cpp_baseclass(&cache_cpp_baseclass);
8918 l = ml_get_curline();
8919 }
8920 if (n)
8921 {
8922 /* XXX */
8923 amount = get_baseclass_amount(cache_cpp_baseclass.lpos.col);
8924 break;
8925 }
8926
8927 /*
8928 * Skip preprocessor directives and blank lines.
8929 */
8930 if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum))
8931 continue;
8932
8933 if (cin_nocode(l))
8934 continue;
8935
8936 /*
8937 * If the previous line ends in ',', use one level of
8938 * indentation:
8939 * int foo,
8940 * bar;
8941 * do this before checking for '}' in case of eg.
8942 * enum foobar
8943 * {
8944 * ...
8945 * } foo,
8946 * bar;
8947 */
8948 n = 0;
8949 if (cin_ends_in(l, (char_u *)",", NULL)
8950 || (*l != NUL && (n = l[STRLEN(l) - 1]) == '\\'))
8951 {
8952 /* take us back to opening paren */
8953 if (find_last_paren(l, '(', ')')
8954 && (trypos = find_match_paren(
8955 curbuf->b_ind_maxparen)) != NULL)
8956 curwin->w_cursor = *trypos;
8957
8958 /* For a line ending in ',' that is a continuation line go
8959 * back to the first line with a backslash:
8960 * char *foo = "bla\
8961 * bla",
8962 * here;
8963 */
8964 while (n == 0 && curwin->w_cursor.lnum > 1)
8965 {
8966 l = ml_get(curwin->w_cursor.lnum - 1);
8967 if (*l == NUL || l[STRLEN(l) - 1] != '\\')
8968 break;
8969 --curwin->w_cursor.lnum;
8970 curwin->w_cursor.col = 0;
8971 }
8972
8973 amount = get_indent(); /* XXX */
8974
8975 if (amount == 0)
8976 amount = cin_first_id_amount();
8977 if (amount == 0)
8978 amount = ind_continuation;
8979 break;
8980 }
8981
8982 /*
8983 * If the line looks like a function declaration, and we're
8984 * not in a comment, put it the left margin.
8985 */
8986 if (cin_isfuncdecl(NULL, cur_curpos.lnum, 0)) /* XXX */
8987 break;
8988 l = ml_get_curline();
8989
8990 /*
8991 * Finding the closing '}' of a previous function. Put
8992 * current line at the left margin. For when 'cino' has "fs".
8993 */
8994 if (*skipwhite(l) == '}')
8995 break;
8996
8997 /* (matching {)
8998 * If the previous line ends on '};' (maybe followed by
8999 * comments) align at column 0. For example:
9000 * char *string_array[] = { "foo",
9001 * / * x * / "b};ar" }; / * foobar * /
9002 */
9003 if (cin_ends_in(l, (char_u *)"};", NULL))
9004 break;
9005
9006 /*
9007 * If the previous line ends on '[' we are probably in an
9008 * array constant:
9009 * something = [
9010 * 234, <- extra indent
9011 */
9012 if (cin_ends_in(l, (char_u *)"[", NULL))
9013 {
9014 amount = get_indent() + ind_continuation;
9015 break;
9016 }
9017
9018 /*
9019 * Find a line only has a semicolon that belongs to a previous
9020 * line ending in '}', e.g. before an #endif. Don't increase
9021 * indent then.
9022 */
9023 if (*(look = skipwhite(l)) == ';' && cin_nocode(look + 1))
9024 {
9025 pos_T curpos_save = curwin->w_cursor;
9026
9027 while (curwin->w_cursor.lnum > 1)
9028 {
9029 look = ml_get(--curwin->w_cursor.lnum);
9030 if (!(cin_nocode(look) || cin_ispreproc_cont(
9031 &look, &curwin->w_cursor.lnum)))
9032 break;
9033 }
9034 if (curwin->w_cursor.lnum > 0
9035 && cin_ends_in(look, (char_u *)"}", NULL))
9036 break;
9037
9038 curwin->w_cursor = curpos_save;
9039 }
9040
9041 /*
9042 * If the PREVIOUS line is a function declaration, the current
9043 * line (and the ones that follow) needs to be indented as
9044 * parameters.
9045 */
9046 if (cin_isfuncdecl(&l, curwin->w_cursor.lnum, 0))
9047 {
9048 amount = curbuf->b_ind_param;
9049 break;
9050 }
9051
9052 /*
9053 * If the previous line ends in ';' and the line before the
9054 * previous line ends in ',' or '\', ident to column zero:
9055 * int foo,
9056 * bar;
9057 * indent_to_0 here;
9058 */
9059 if (cin_ends_in(l, (char_u *)";", NULL))
9060 {
9061 l = ml_get(curwin->w_cursor.lnum - 1);
9062 if (cin_ends_in(l, (char_u *)",", NULL)
9063 || (*l != NUL && l[STRLEN(l) - 1] == '\\'))
9064 break;
9065 l = ml_get_curline();
9066 }
9067
9068 /*
9069 * Doesn't look like anything interesting -- so just
9070 * use the indent of this line.
8737 * 9071 *
8738 * This means we're at the top level, and everything should 9072 * Position the cursor over the rightmost paren, so that
8739 * basically just match where the previous line is, except 9073 * matching it will take us back to the start of the line.
8740 * for the lines immediately following a function declaration,
8741 * which are K&R-style parameters and need to be indented.
8742 *
8743 * if our line starts with an open brace, forget about any
8744 * prevailing indent and make sure it looks like the start
8745 * of a function
8746 */ 9074 */
8747 9075 find_last_paren(l, '(', ')');
8748 if (theline[0] == '{') 9076
8749 { 9077 if ((trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL)
8750 amount = curbuf->b_ind_first_open; 9078 curwin->w_cursor = *trypos;
8751 } 9079 amount = get_indent(); /* XXX */
8752 9080 break;
8753 /* 9081 }
8754 * If the NEXT line is a function declaration, the current 9082
8755 * line needs to be indented as a function type spec. 9083 /* add extra indent for a comment */
8756 * Don't do this if the current line looks like a comment or if the 9084 if (cin_iscomment(theline))
8757 * current line is terminated, ie. ends in ';', or if the current line 9085 amount += curbuf->b_ind_comment;
8758 * contains { or }: "void f() {\n if (1)" 9086
8759 */ 9087 /* add extra indent if the previous line ended in a backslash:
8760 else if (cur_curpos.lnum < curbuf->b_ml.ml_line_count 9088 * "asdfasdf\
8761 && !cin_nocode(theline) 9089 * here";
8762 && vim_strchr(theline, '{') == NULL 9090 * char *foo = "asdf\
8763 && vim_strchr(theline, '}') == NULL 9091 * here";
8764 && !cin_ends_in(theline, (char_u *)":", NULL) 9092 */
8765 && !cin_ends_in(theline, (char_u *)",", NULL) 9093 if (cur_curpos.lnum > 1)
8766 && cin_isfuncdecl(NULL, cur_curpos.lnum + 1, 9094 {
8767 cur_curpos.lnum + 1) 9095 l = ml_get(cur_curpos.lnum - 1);
8768 && !cin_isterminated(theline, FALSE, TRUE)) 9096 if (*l != NUL && l[STRLEN(l) - 1] == '\\')
8769 { 9097 {
8770 amount = curbuf->b_ind_func_type; 9098 cur_amount = cin_get_equal_amount(cur_curpos.lnum - 1);
8771 } 9099 if (cur_amount > 0)
8772 else 9100 amount = cur_amount;
8773 { 9101 else if (cur_amount == 0)
8774 amount = 0; 9102 amount += ind_continuation;
8775 curwin->w_cursor = cur_curpos;
8776
8777 /* search backwards until we find something we recognize */
8778
8779 while (curwin->w_cursor.lnum > 1)
8780 {
8781 curwin->w_cursor.lnum--;
8782 curwin->w_cursor.col = 0;
8783
8784 l = ml_get_curline();
8785
8786 /*
8787 * If we're in a comment now, skip to the start of the comment.
8788 */ /* XXX */
8789 if ((trypos = ind_find_start_comment()) != NULL)
8790 {
8791 curwin->w_cursor.lnum = trypos->lnum + 1;
8792 curwin->w_cursor.col = 0;
8793 continue;
8794 }
8795
8796 /*
8797 * Are we at the start of a cpp base class declaration or
8798 * constructor initialization?
8799 */ /* XXX */
8800 n = FALSE;
8801 if (curbuf->b_ind_cpp_baseclass != 0 && theline[0] != '{')
8802 {
8803 n = cin_is_cpp_baseclass(&cache_cpp_baseclass);
8804 l = ml_get_curline();
8805 }
8806 if (n)
8807 {
8808 /* XXX */
8809 amount = get_baseclass_amount(cache_cpp_baseclass.lpos.col);
8810 break;
8811 }
8812
8813 /*
8814 * Skip preprocessor directives and blank lines.
8815 */
8816 if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum))
8817 continue;
8818
8819 if (cin_nocode(l))
8820 continue;
8821
8822 /*
8823 * If the previous line ends in ',', use one level of
8824 * indentation:
8825 * int foo,
8826 * bar;
8827 * do this before checking for '}' in case of eg.
8828 * enum foobar
8829 * {
8830 * ...
8831 * } foo,
8832 * bar;
8833 */
8834 n = 0;
8835 if (cin_ends_in(l, (char_u *)",", NULL)
8836 || (*l != NUL && (n = l[STRLEN(l) - 1]) == '\\'))
8837 {
8838 /* take us back to opening paren */
8839 if (find_last_paren(l, '(', ')')
8840 && (trypos = find_match_paren(
8841 curbuf->b_ind_maxparen)) != NULL)
8842 curwin->w_cursor = *trypos;
8843
8844 /* For a line ending in ',' that is a continuation line go
8845 * back to the first line with a backslash:
8846 * char *foo = "bla\
8847 * bla",
8848 * here;
8849 */
8850 while (n == 0 && curwin->w_cursor.lnum > 1)
8851 {
8852 l = ml_get(curwin->w_cursor.lnum - 1);
8853 if (*l == NUL || l[STRLEN(l) - 1] != '\\')
8854 break;
8855 --curwin->w_cursor.lnum;
8856 curwin->w_cursor.col = 0;
8857 }
8858
8859 amount = get_indent(); /* XXX */
8860
8861 if (amount == 0)
8862 amount = cin_first_id_amount();
8863 if (amount == 0)
8864 amount = ind_continuation;
8865 break;
8866 }
8867
8868 /*
8869 * If the line looks like a function declaration, and we're
8870 * not in a comment, put it the left margin.
8871 */
8872 if (cin_isfuncdecl(NULL, cur_curpos.lnum, 0)) /* XXX */
8873 break;
8874 l = ml_get_curline();
8875
8876 /*
8877 * Finding the closing '}' of a previous function. Put
8878 * current line at the left margin. For when 'cino' has "fs".
8879 */
8880 if (*skipwhite(l) == '}')
8881 break;
8882
8883 /* (matching {)
8884 * If the previous line ends on '};' (maybe followed by
8885 * comments) align at column 0. For example:
8886 * char *string_array[] = { "foo",
8887 * / * x * / "b};ar" }; / * foobar * /
8888 */
8889 if (cin_ends_in(l, (char_u *)"};", NULL))
8890 break;
8891
8892 /*
8893 * If the previous line ends on '[' we are probably in an
8894 * array constant:
8895 * something = [
8896 * 234, <- extra indent
8897 */
8898 if (cin_ends_in(l, (char_u *)"[", NULL))
8899 {
8900 amount = get_indent() + ind_continuation;
8901 break;
8902 }
8903
8904 /*
8905 * Find a line only has a semicolon that belongs to a previous
8906 * line ending in '}', e.g. before an #endif. Don't increase
8907 * indent then.
8908 */
8909 if (*(look = skipwhite(l)) == ';' && cin_nocode(look + 1))
8910 {
8911 pos_T curpos_save = curwin->w_cursor;
8912
8913 while (curwin->w_cursor.lnum > 1)
8914 {
8915 look = ml_get(--curwin->w_cursor.lnum);
8916 if (!(cin_nocode(look) || cin_ispreproc_cont(
8917 &look, &curwin->w_cursor.lnum)))
8918 break;
8919 }
8920 if (curwin->w_cursor.lnum > 0
8921 && cin_ends_in(look, (char_u *)"}", NULL))
8922 break;
8923
8924 curwin->w_cursor = curpos_save;
8925 }
8926
8927 /*
8928 * If the PREVIOUS line is a function declaration, the current
8929 * line (and the ones that follow) needs to be indented as
8930 * parameters.
8931 */
8932 if (cin_isfuncdecl(&l, curwin->w_cursor.lnum, 0))
8933 {
8934 amount = curbuf->b_ind_param;
8935 break;
8936 }
8937
8938 /*
8939 * If the previous line ends in ';' and the line before the
8940 * previous line ends in ',' or '\', ident to column zero:
8941 * int foo,
8942 * bar;
8943 * indent_to_0 here;
8944 */
8945 if (cin_ends_in(l, (char_u *)";", NULL))
8946 {
8947 l = ml_get(curwin->w_cursor.lnum - 1);
8948 if (cin_ends_in(l, (char_u *)",", NULL)
8949 || (*l != NUL && l[STRLEN(l) - 1] == '\\'))
8950 break;
8951 l = ml_get_curline();
8952 }
8953
8954 /*
8955 * Doesn't look like anything interesting -- so just
8956 * use the indent of this line.
8957 *
8958 * Position the cursor over the rightmost paren, so that
8959 * matching it will take us back to the start of the line.
8960 */
8961 find_last_paren(l, '(', ')');
8962
8963 if ((trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL)
8964 curwin->w_cursor = *trypos;
8965 amount = get_indent(); /* XXX */
8966 break;
8967 }
8968
8969 /* add extra indent for a comment */
8970 if (cin_iscomment(theline))
8971 amount += curbuf->b_ind_comment;
8972
8973 /* add extra indent if the previous line ended in a backslash:
8974 * "asdfasdf\
8975 * here";
8976 * char *foo = "asdf\
8977 * here";
8978 */
8979 if (cur_curpos.lnum > 1)
8980 {
8981 l = ml_get(cur_curpos.lnum - 1);
8982 if (*l != NUL && l[STRLEN(l) - 1] == '\\')
8983 {
8984 cur_amount = cin_get_equal_amount(cur_curpos.lnum - 1);
8985 if (cur_amount > 0)
8986 amount = cur_amount;
8987 else if (cur_amount == 0)
8988 amount += ind_continuation;
8989 }
8990 }
8991 } 9103 }
8992 } 9104 }
8993 9105
8994 theend: 9106 theend:
9107 if (amount < 0)
9108 amount = 0;
9109
9110 laterend:
8995 /* put the cursor back where it belongs */ 9111 /* put the cursor back where it belongs */
8996 curwin->w_cursor = cur_curpos; 9112 curwin->w_cursor = cur_curpos;
8997 9113
8998 vim_free(linecopy); 9114 vim_free(linecopy);
8999 9115
9000 if (amount < 0)
9001 return 0;
9002 return amount; 9116 return amount;
9003 } 9117 }
9004 9118
9005 static int 9119 static int
9006 find_match(lookfor, ourscope) 9120 find_match(lookfor, ourscope)