summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-01-31 13:48:09 +0100
committerBram Moolenaar <Bram@vim.org>2019-01-31 13:48:09 +0100
commit4b47162ccede0b6d9cbb9473ad870220a24fbf54 (patch)
treece99699b4391edf919bc8a849653516f231d3ef7 /src
parentbbb5f8d4c2cbc5f48556008875f57cbe7fc4ac6c (diff)
patch 8.1.0857: indent functionality is not separatedv8.1.0857
Problem: Ignore functionality is not separated. Solution: Move indent functionality into a new file. (Yegappan Lakshmanan, closes #3886)
Diffstat (limited to 'src')
-rw-r--r--src/Make_bc5.mak1
-rw-r--r--src/Make_cyg_ming.mak1
-rw-r--r--src/Make_dice.mak4
-rw-r--r--src/Make_ivc.mak5
-rw-r--r--src/Make_manx.mak6
-rw-r--r--src/Make_morph.mak1
-rw-r--r--src/Make_mvc.mak4
-rw-r--r--src/Make_sas.mak5
-rw-r--r--src/Make_vms.mms5
-rw-r--r--src/Makefile10
-rw-r--r--src/edit.c331
-rw-r--r--src/indent.c4683
-rw-r--r--src/misc1.c4346
-rw-r--r--src/proto.h1
-rw-r--r--src/proto/edit.pro3
-rw-r--r--src/proto/indent.pro16
-rw-r--r--src/proto/misc1.pro9
-rw-r--r--src/version.c2
18 files changed, 4744 insertions, 4689 deletions
diff --git a/src/Make_bc5.mak b/src/Make_bc5.mak
index d0d31d4eb9..b2977e7007 100644
--- a/src/Make_bc5.mak
+++ b/src/Make_bc5.mak
@@ -548,6 +548,7 @@ vimobj = \
$(OBJDIR)\getchar.obj \
$(OBJDIR)\hardcopy.obj \
$(OBJDIR)\hashtab.obj \
+ $(OBJDIR)\indent.obj \
$(OBJDIR)\json.obj \
$(OBJDIR)\list.obj \
$(OBJDIR)\main.obj \
diff --git a/src/Make_cyg_ming.mak b/src/Make_cyg_ming.mak
index 8d8666ffbe..5795b50752 100644
--- a/src/Make_cyg_ming.mak
+++ b/src/Make_cyg_ming.mak
@@ -720,6 +720,7 @@ OBJ = \
$(OUTDIR)/getchar.o \
$(OUTDIR)/hardcopy.o \
$(OUTDIR)/hashtab.o \
+ $(OUTDIR)/indent.o \
$(OUTDIR)/json.o \
$(OUTDIR)/list.o \
$(OUTDIR)/main.o \
diff --git a/src/Make_dice.mak b/src/Make_dice.mak
index 83614ca911..57aed477b9 100644
--- a/src/Make_dice.mak
+++ b/src/Make_dice.mak
@@ -50,6 +50,7 @@ SRC = \
getchar.c \
hardcopy.c \
hashtab.c \
+ indent.c \
json.c \
list.c \
main.c \
@@ -108,6 +109,7 @@ OBJ = o/arabic.o \
o/getchar.o \
o/hardcopy.o \
o/hashtab.o \
+ o/indent.o \
o/json.o \
o/list.o \
o/main.o \
@@ -209,6 +211,8 @@ o/hardcopy.o: hardcopy.c $(SYMS)
o/hashtab.o: hashtab.c $(SYMS)
+o/indent.o: indent.c $(SYMS)
+
o/json.o: json.c $(SYMS)
o/list.o: list.c $(SYMS)
diff --git a/src/Make_ivc.mak b/src/Make_ivc.mak
index 0459984dab..96d6a47b54 100644
--- a/src/Make_ivc.mak
+++ b/src/Make_ivc.mak
@@ -234,6 +234,7 @@ LINK32_OBJS= \
"$(INTDIR)/getchar.obj" \
"$(INTDIR)/hardcopy.obj" \
"$(INTDIR)/hashtab.obj" \
+ "$(INTDIR)/indent.obj" \
"$(INTDIR)/json.obj" \
"$(INTDIR)/list.obj" \
"$(INTDIR)/main.obj" \
@@ -434,6 +435,10 @@ SOURCE=.\hardcopy.c
SOURCE=.\hashtab.c
# End Source File
# Begin Source File
+#
+SOURCE=.\indent.c
+# End Source File
+# Begin Source File
SOURCE=.\gui.c
diff --git a/src/Make_manx.mak b/src/Make_manx.mak
index b71b923ded..a44ad6558c 100644
--- a/src/Make_manx.mak
+++ b/src/Make_manx.mak
@@ -60,6 +60,7 @@ SRC = arabic.c \
getchar.c \
hardcopy.c \
hashtab.c \
+ indent.c \
json.c \
list.c \
main.c \
@@ -120,6 +121,7 @@ OBJ = obj/arabic.o \
obj/getchar.o \
obj/hardcopy.o \
obj/hashtab.o \
+ obj/indent.o \
obj/json.o \
obj/list.o \
obj/main.o \
@@ -178,6 +180,7 @@ PRO = proto/arabic.pro \
proto/getchar.pro \
proto/hardcopy.pro \
proto/hashtab.pro \
+ proto/indent.pro \
proto/json.pro \
proto/list.pro \
proto/main.pro \
@@ -329,6 +332,9 @@ obj/hardcopy.o: hardcopy.c
obj/hashtab.o: hashtab.c
$(CCSYM) $@ hashtab.c
+obj/indent.o: indent.c
+ $(CCSYM) $@ indent.c
+
obj/json.o: json.c
$(CCSYM) $@ json.c
diff --git a/src/Make_morph.mak b/src/Make_morph.mak
index ae490416f4..6bcae1a0b1 100644
--- a/src/Make_morph.mak
+++ b/src/Make_morph.mak
@@ -48,6 +48,7 @@ SRC = arabic.c \
getchar.c \
hardcopy.c \
hashtab.c \
+ indent.c \
json.c \
list.c \
main.c \
diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak
index 3f8c8a0384..52deb549c3 100644
--- a/src/Make_mvc.mak
+++ b/src/Make_mvc.mak
@@ -725,6 +725,7 @@ OBJ = \
$(OUTDIR)\getchar.obj \
$(OUTDIR)\hardcopy.obj \
$(OUTDIR)\hashtab.obj \
+ $(OUTDIR)\indent.obj \
$(OUTDIR)\json.obj \
$(OUTDIR)\list.obj \
$(OUTDIR)\main.obj \
@@ -1414,6 +1415,8 @@ $(OUTDIR)/hardcopy.obj: $(OUTDIR) hardcopy.c $(INCL)
$(OUTDIR)/hashtab.obj: $(OUTDIR) hashtab.c $(INCL)
+$(OUTDIR)/indent.obj: $(OUTDIR) indent.c $(INCL)
+
$(OUTDIR)/gui.obj: $(OUTDIR) gui.c $(INCL) $(GUI_INCL)
$(OUTDIR)/gui_beval.obj: $(OUTDIR) gui_beval.c $(INCL) $(GUI_INCL)
@@ -1645,6 +1648,7 @@ proto.h: \
proto/getchar.pro \
proto/hardcopy.pro \
proto/hashtab.pro \
+ proto/indent.pro \
proto/json.pro \
proto/list.pro \
proto/main.pro \
diff --git a/src/Make_sas.mak b/src/Make_sas.mak
index c621360eab..e7faf56771 100644
--- a/src/Make_sas.mak
+++ b/src/Make_sas.mak
@@ -113,6 +113,7 @@ SRC = \
getchar.c \
hardcopy.c \
hashtab.c \
+ indent.c \
json.c \
list.c \
main.c \
@@ -172,6 +173,7 @@ OBJ = \
getchar.o \
hardcopy.o \
hashtab.o \
+ indent.o \
json.o \
list.o \
main.o \
@@ -231,6 +233,7 @@ PRO = \
proto/getchar.pro \
proto/hardcopy.pro \
proto/hashtab.pro \
+ proto/indent.pro \
proto/json.pro \
proto/list.pro \
proto/main.pro \
@@ -368,6 +371,8 @@ hardcopy.o: hardcopy.c
proto/hardcopy.pro: hardcopy.c
hashtab.o: hashtab.c
proto/hashtab.pro: hashtab.c
+indent.o: indent.c
+proto/indent.pro: indent.c
json.o: json.c
proto/json.pro: json.c
list.o: list.c
diff --git a/src/Make_vms.mms b/src/Make_vms.mms
index 6a3508980f..1a21d15fb9 100644
--- a/src/Make_vms.mms
+++ b/src/Make_vms.mms
@@ -314,7 +314,7 @@ ALL_LIBS = $(LIBS) $(GUI_LIB_DIR) $(GUI_LIB) \
SRC = arabic.c autocmd.c beval.c blob.c blowfish.c buffer.c charset.c crypt.c crypt_zip.c dict.c diff.c digraph.c edit.c eval.c \
evalfunc.c ex_cmds.c ex_cmds2.c ex_docmd.c ex_eval.c ex_getln.c if_cscope.c if_xcmdsrv.c farsi.c fileio.c fold.c \
- getchar.c hardcopy.c hashtab.c json.c list.c main.c mark.c menu.c mbyte.c memfile.c memline.c message.c misc1.c \
+ getchar.c hardcopy.c hashtab.c indent.c json.c list.c main.c mark.c menu.c mbyte.c memfile.c memline.c message.c misc1.c \
misc2.c move.c normal.c ops.c option.c popupmnu.c quickfix.c regexp.c search.c sha256.c sign.c \
spell.c spellfile.c syntax.c tag.c term.c termlib.c textprop.c ui.c undo.c userfunc.c version.c screen.c \
window.c os_unix.c os_vms.c pathdef.c \
@@ -323,7 +323,7 @@ SRC = arabic.c autocmd.c beval.c blob.c blowfish.c buffer.c charset.c crypt.c cr
OBJ = arabic.obj autocmd.obj beval.obj blob.obj blowfish.obj buffer.obj charset.obj crypt.obj crypt_zip.obj dict.obj diff.obj digraph.obj \
edit.obj eval.obj evalfunc.obj ex_cmds.obj ex_cmds2.obj ex_docmd.obj ex_eval.obj ex_getln.obj if_cscope.obj \
- if_xcmdsrv.obj farsi.obj fileio.obj fold.obj getchar.obj hardcopy.obj hashtab.obj json.obj list.obj main.obj mark.obj \
+ if_xcmdsrv.obj farsi.obj fileio.obj fold.obj getchar.obj hardcopy.obj hashtab.obj indent.obj json.obj list.obj main.obj mark.obj \
menu.obj memfile.obj memline.obj message.obj misc1.obj misc2.obj \
move.obj mbyte.obj normal.obj ops.obj option.obj popupmnu.obj quickfix.obj \
regexp.obj search.obj sha256.obj sign.obj spell.obj spellfile.obj syntax.obj tag.obj term.obj termlib.obj textprop.obj \
@@ -596,6 +596,7 @@ if_mzsch.obj : if_mzsch.c vim.h [.auto]config.h feature.h os_unix.h \
ascii.h keymap.h term.h macros.h option.h structs.h \
regexp.h gui.h beval.h [.proto]gui_beval.pro ex_cmds.h proto.h \
globals.h farsi.h arabic.h if_mzsch.h
+indent.obj : indent.c vim.h [.auto]config.h feature.h os_unix.h
json.obj : json.c vim.h [.auto]config.h feature.h os_unix.h \
ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \
[.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h farsi.h \
diff --git a/src/Makefile b/src/Makefile
index 3f54184564..12229a4476 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1599,6 +1599,7 @@ BASIC_SRC = \
hashtab.c \
if_cscope.c \
if_xcmdsrv.c \
+ indent.c \
json.c \
list.c \
main.c \
@@ -1712,6 +1713,7 @@ OBJ_COMMON = \
$(HANGULIN_OBJ) \
objects/if_cscope.o \
objects/if_xcmdsrv.o \
+ objects/indent.o \
objects/list.o \
objects/mark.o \
objects/memline.o \
@@ -1842,6 +1844,7 @@ PRO_AUTO = \
if_python3.pro \
if_ruby.pro \
if_xcmdsrv.pro \
+ indent.pro \
json.pro \
list.pro \
main.pro \
@@ -3093,6 +3096,9 @@ objects/if_ruby.o: if_ruby.c
objects/if_tcl.o: if_tcl.c
$(CCC_NF) $(TCL_CFLAGS) $(ALL_CFLAGS) -o $@ if_tcl.c
+objects/indent.o: indent.c
+ $(CCC) -o $@ indent.c
+
objects/json.o: json.c
$(CCC) -o $@ json.c
@@ -3490,6 +3496,10 @@ objects/if_xcmdsrv.o: if_xcmdsrv.c vim.h protodef.h auto/config.h feature.h \
os_unix.h auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
proto.h globals.h farsi.h arabic.h version.h
+objects/indent.o: indent.c vim.h protodef.h auto/config.h feature.h os_unix.h \
+ os_mac.h ascii.h keymap.h term.h macros.h option.h beval.h structs.h \
+ regexp.h gui.h alloc.h ex_cmds.h spell.h proto.h globals.h farsi.h \
+ arabic.h
objects/json.o: json.c vim.h protodef.h auto/config.h feature.h os_unix.h \
auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
diff --git a/src/edit.c b/src/edit.c
index de5adcb197..b226636aaa 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -216,9 +216,6 @@ static void mb_replace_pop_ins(int cc);
static void replace_flush(void);
static void replace_do_bs(int limit_col);
static int del_char_after_col(int limit_col);
-#ifdef FEAT_CINDENT
-static int cindent_on(void);
-#endif
static void ins_reg(void);
static void ins_ctrl_g(void);
static void ins_ctrl_hat(void);
@@ -380,6 +377,7 @@ edit(
ins_compl_clear(); /* clear stuff for CTRL-X mode */
#endif
+ch_log(NULL, "ENTERING Insert mode");
/*
* Trigger InsertEnter autocommands. Do not do this for "r<CR>" or "grx".
*/
@@ -1050,6 +1048,7 @@ doESCkey:
if (cmdchar != 'r' && cmdchar != 'v' && c != Ctrl_C)
ins_apply_autocmds(EVENT_INSERTLEAVE);
did_cursorhold = FALSE;
+ch_log(NULL, "LEAVING Insert mode");
return (c == Ctrl_O);
}
continue;
@@ -7923,332 +7922,6 @@ replace_do_bs(int limit_col)
(void)del_char_after_col(limit_col);
}
-#ifdef FEAT_CINDENT
-/*
- * Return TRUE if C-indenting is on.
- */
- static int
-cindent_on(void)
-{
- return (!p_paste && (curbuf->b_p_cin
-# ifdef FEAT_EVAL
- || *curbuf->b_p_inde != NUL
-# endif
- ));
-}
-#endif
-
-#if defined(FEAT_LISP) || defined(FEAT_CINDENT) || defined(PROTO)
-/*
- * Re-indent the current line, based on the current contents of it and the
- * surrounding lines. Fixing the cursor position seems really easy -- I'm very
- * confused what all the part that handles Control-T is doing that I'm not.
- * "get_the_indent" should be get_c_indent, get_expr_indent or get_lisp_indent.
- */
-
- void
-fixthisline(int (*get_the_indent)(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
-fix_indent(void)
-{
- if (p_paste)
- return;
-# ifdef FEAT_LISP
- if (curbuf->b_p_lisp && curbuf->b_p_ai)
- fixthisline(get_lisp_indent);
-# endif
-# if defined(FEAT_LISP) && defined(FEAT_CINDENT)
- else
-# endif
-# ifdef FEAT_CINDENT
- if (cindent_on())
- do_c_expr_indent();
-# endif
-}
-
-#endif
-
-#ifdef FEAT_CINDENT
-/*
- * return TRUE if 'cinkeys' contains the key "keytyped",
- * when == '*': Only if key is preceded with '*' (indent before insert)
- * when == '!': Only if key is preceded with '!' (don't insert)
- * when == ' ': Only if key is not preceded with '*'(indent afterwards)
- *
- * "keytyped" can have a few special values:
- * KEY_OPEN_FORW
- * KEY_OPEN_BACK
- * KEY_COMPLETE just finished completion.
- *
- * If line_is_empty is TRUE accept keys with '0' before them.
- */
- int
-in_cinkeys(
- int keytyped,
- int when,
- int line_is_empty)
-{
- char_u *look;
- int try_match;
- int try_match_word;
- char_u *p;
- char_u *line;
- int icase;
- int i;
-
- if (keytyped == NUL)
- /* Can happen with CTRL-Y and CTRL-E on a short line. */
- return FALSE;
-
-#ifdef FEAT_EVAL
- if (*curbuf->b_p_inde != NUL)
- look = curbuf->b_p_indk; /* 'indentexpr' set: use 'indentkeys' */
- else
-#endif
- look = curbuf->b_p_cink; /* 'indentexpr' empty: use 'cinkeys' */
- while (*look)
- {
- /*
- * Find out if we want to try a match with this key, depending on
- * 'when' and a '*' or '!' before the key.
- */
- switch (when)
- {
- case '*': try_match = (*look == '*'); break;
- case '!': try_match = (*look == '!'); break;
- default: try_match = (*look != '*'); break;
- }
- if (*look == '*' || *look == '!')
- ++look;
-
- /*
- * If there is a '0', only accept a match if the line is empty.
- * But may still match when typing last char of a word.
- */
- if (*look == '0')
- {
- try_match_word = try_match;
- if (!line_is_empty)
- try_match = FALSE;
- ++look;
- }
- else
- try_match_word = FALSE;
-
- /*
- * does it look like a control character?
- */
- if (*look == '^'
-#ifdef EBCDIC
- && (Ctrl_chr(look[1]) != 0)
-#else
- && look[1] >= '?' && look[1] <= '_'
-#endif
- )
- {
- if (try_match && keytyped == Ctrl_chr(look[1]))
- return TRUE;
- look += 2;
- }
- /*
- * 'o' means "o" command, open forward.
- * 'O' means "O" command, open backward.
- */
- else if (*look == 'o')
- {
- if (try_match && keytyped == KEY_OPEN_FORW)
- return TRUE;
- ++look;
- }
- else if (*look == 'O')
- {
- if (try_match && keytyped == KEY_OPEN_BACK)
- return TRUE;
- ++look;
- }
-
- /*
- * 'e' means to check for "else" at start of line and just before the
- * cursor.
- */
- else if (*look == 'e')
- {
- if (try_match && keytyped == 'e' && curwin->w_cursor.col >= 4)
- {
- p = ml_get_curline();
- if (skipwhite(p) == p + curwin->w_cursor.col - 4 &&
- STRNCMP(p + curwin->w_cursor.col - 4, "else", 4) == 0)
- return TRUE;
- }
- ++look;
- }
-
- /*
- * ':' only causes an indent if it is at the end of a label or case
- * statement, or when it was before typing the ':' (to fix
- * class::method for C++).
- */
- else if (*look == ':')
- {
- if (try_match && keytyped == ':')
- {
- p = ml_get_curline();
- if (cin_iscase(p, FALSE) || cin_isscopedecl(p) || cin_islabel())
- return TRUE;
- /* Need to get the line again after cin_islabel(). */
- p = ml_get_curline();
- if (curwin->w_cursor.col > 2
- && p[curwin->w_cursor.col - 1] == ':'
- && p[curwin->w_cursor.col - 2] == ':')
- {
- p[curwin->w_cursor.col - 1] = ' ';
- i = (cin_iscase(p, FALSE) || cin_isscopedecl(p)
- || cin_islabel());
- p = ml_get_curline();
- p[curwin->w_cursor.col - 1] = ':';
- if (i)
- return TRUE;
- }
- }
- ++look;
- }
-
-
- /*
- * Is it a key in <>, maybe?
- */
- else if (*look == '<')
- {
- if (try_match)
- {
- /*
- * make up some named keys <o>, <O>, <e>, <0>, <>>, <<>, <*>,
- * <:> and <!> so that people can re-indent on o, O, e, 0, <,
- * >, *, : and ! keys if they really really want to.
- */
- if (vim_strchr((char_u *)"<>!*oOe0:", look[1]) != NULL
- && keytyped == look[1])
- return TRUE;
-
- if (keytyped == get_special_key_code(look + 1))
- return TRUE;
- }
- while (*look && *look != '>')
- look++;
- while (*look == '>')
- look++;
- }
-
- /*
- * Is it a word: "=word"?
- */
- else if (*look == '=' && look[1] != ',' && look[1] != NUL)
- {
- ++look;
- if (*look == '~')
- {
- icase = TRUE;
- ++look;
- }
- else
- icase = FALSE;
- p = vim_strchr(look, ',');
- if (p == NULL)
- p = look + STRLEN(look);
- if ((try_match || try_match_word)
- && curwin->w_cursor.col >= (colnr_T)(p - look))
- {
- int match = FALSE;
-
-#ifdef FEAT_INS_EXPAND
- if (keytyped == KEY_COMPLETE)
- {
- char_u *s;
-
- /* Just completed a word, check if it starts with "look".
- * search back for the start of a word. */
- line = ml_get_curline();
- if (has_mbyte)
- {
- char_u *n;
-
- for (s = line + curwin->w_cursor.col; s > line; s = n)
- {
- n = mb_prevptr(line, s);
- if (!vim_iswordp(n))
- break;
- }
- }
- else
- for (s = line + curwin->w_cursor.col; s > line; --s)
- if (!vim_iswordc(s[-1]))
- break;
- if (s + (p - look) <= line + curwin->w_cursor.col
- && (icase
- ? MB_STRNICMP(s, look, p - look)
- : STRNCMP(s, look, p - look)) == 0)
- match = TRUE;
- }
- else
-#endif
- /* TODO: multi-byte */
- if (keytyped == (int)p[-1] || (icase && keytyped < 256
- && TOLOWER_LOC(keytyped) == TOLOWER_LOC((int)p[-1])))
- {
- line = ml_get_cursor();
- if ((curwin->w_cursor.col == (colnr_T)(p - look)
- || !vim_iswordc(line[-(p - look) - 1]))
- && (icase
- ? MB_STRNICMP(line - (p - look), look, p - look)
- : STRNCMP(line - (p - look), look, p - look))
- == 0)
- match = TRUE;
- }
- if (match && try_match_word && !try_match)
- {
- /* "0=word": Check if there are only blanks before the
- * word. */
- if (getwhitecols_curline() !=
- (int)(curwin->w_cursor.col - (p - look)))
- match = FALSE;
- }
- if (match)
- return TRUE;
- }
- look = p;
- }
-
- /*
- * ok, it's a boring generic character.
- */
- else
- {
- if (try_match && *look == keytyped)
- return TRUE;
- if (*look != NUL)
- ++look;
- }
-
- /*
- * Skip over ", ".
- */
- look = skip_to_option_part(look);
- }
- return FALSE;
-}
-#endif /* FEAT_CINDENT */
-
#if defined(FEAT_RIGHTLEFT) || defined(PROTO)
/*
* Map Hebrew keyboard when in hkmap mode.
diff --git a/src/indent.c b/src/indent.c
new file mode 100644
index 0000000000..af401ee7ad
--- /dev/null
+++ b/src/indent.c
@@ -0,0 +1,4683 @@
+/* vi:set ts=8 sts=4 sw=4 noet:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * indent.c: Indentation related functions
+ */
+
+#include "vim.h"
+
+#if defined(FEAT_CINDENT) || defined(FEAT_SMARTINDENT)
+
+/*
+ * Return TRUE if the string "line" starts with a word from 'cinwords'.
+ */
+ int
+cin_is_cinword(char_u *line)
+{
+ char_u *cinw;
+ char_u *cinw_buf;
+ int cinw_len;
+ int retval = FALSE;
+ int len;
+
+ cinw_len = (int)STRLEN(curbuf->b_p_cinw) + 1;
+ cinw_buf = alloc((unsigned)cinw_len);
+ if (cinw_buf != NULL)
+ {
+ line = skipwhite(line);
+ for (cinw = curbuf->b_p_cinw; *cinw; )
+ {
+ len = copy_option_part(&cinw, cinw_buf, cinw_len, ",");
+ if (STRNCMP(line, cinw_buf, len) == 0
+ && (!vim_iswordc(line[len]) || !vim_iswordc(line[len - 1])))
+ {
+ retval = TRUE;
+ break;
+ }
+ }
+ vim_free(cinw_buf);
+ }
+ return retval;
+}
+#endif
+
+#if defined(FEAT_CINDENT) || defined(FEAT_SYN_HL)
+
+static char_u *skip_string(char_u *p);
+static pos_T *find_start_rawstring(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(void) /* XXX */
+{
+ return find_start_comment(curbuf->b_ind_maxcomment);
+}
+
+ pos_T *
+find_start_comment(int ind_maxcomment) /* XXX */
+{
+ pos_T *pos;
+ char_u *line;
+ char_u *p;
+ int cur_maxcomment = ind_maxcomment;
+
+ for (;;)
+ {
+ pos = findmatchlimit(NULL, '*', FM_BACKWARD, cur_maxcomment);
+ if (pos == NULL)
+ break;
+
+ /*
+ * Check if the comment 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;
+}
+
+/*
+ * 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.
+ * If is_raw is given and returns start of raw_string, sets it to true.
+ * Return NULL when not inside a comment or raw string.
+ * "CORS" -> Comment Or Raw String
+ */
+ static pos_T *
+ind_find_start_CORS(linenr_T *is_raw) /* XXX */
+{
+ static pos_T comment_pos_copy;
+ pos_T *comment_pos;
+ pos_T *rs_pos;
+
+ comment_pos = find_start_comment(curbuf->b_ind_maxcomment);
+ if (comment_pos != NULL)
+ {
+ /* Need to make a copy of the static pos in findmatchlimit(),
+ * calling find_start_rawstring() may change it. */
+ comment_pos_copy = *comment_pos;
+ comment_pos = &comment_pos_copy;
+ }
+ 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_POS(*rs_pos, *comment_pos)))
+ {
+ if (is_raw != NULL && rs_pos != NULL)
+ *is_raw = rs_pos->lnum;
+ 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(int ind_maxcomment) /* XXX */
+{
+ 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.
+ */
+ static char_u *
+skip_string(char_u *p)
+{
+ int i;
+
+ /*
+ * We loop, because strings may be concatenated: "date""time".
+ */
+ for ( ; ; ++p)
+ {
+ if (p[0] == '\'') /* 'c' or '\n' or '\000' */
+ {
+ if (!p[1]) /* ' at end of line */
+ break;
+ i = 2;
+ if (p[1] == '\\') /* '\n' or '\000' */
+ {
+ ++i;
+ while (vim_isdigit(p[i - 1])) /* '\000' */
+ ++i;
+ }
+ if (p[i] == '\'') /* check for trailing ' */
+ {
+ p += i;
+ continue;
+ }
+ }
+ else if (p[0] == '"') /* start of string */
+ {
+ for (++p; p[0]; ++p)
+ {
+ if (p[0] == '\\' && p[1] != NUL)
+ ++p;
+ else if (p[0] == '"') /* end of string */
+ 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 */
+ }
+ if (!*p)
+ --p; /* backup from NUL */
+ return p;
+}
+#endif /* FEAT_CINDENT || FEAT_SYN_HL */
+
+#if defined(FEAT_CINDENT) || defined(PROTO)
+
+/*
+ * Return TRUE if C-indenting is on.
+ */
+ int
+cindent_on(void)
+{
+ return (!p_paste && (curbuf->b_p_cin
+# ifdef FEAT_EVAL
+ || *curbuf->b_p_inde != NUL
+# endif
+ ));
+}
+
+/* Find result cache for cpp_baseclass */
+typedef struct {
+ int found;
+ lpos_T lpos;
+} cpp_baseclass_cache_T;
+
+/*
+ * Functions for C-indenting.
+ * Most of this originally comes from Eric Fischer.
+ */
+/*
+ * Below "XXX" means that this function may unlock the current line.
+ */
+
+static int cin_isdefault(char_u *);
+static int cin_ispreproc(char_u *);
+static int cin_iscomment(char_u *);
+static int cin_islinecomment(char_u *);
+static int cin_isterminated(char_u *, int, int);
+static int cin_iselse(char_u *);
+static int cin_ends_in(char_u *, char_u *, char_u *);
+static int cin_starts_with(char_u *s, char *word);
+static pos_T *find_match_paren(int);
+static pos_T *find_match_char(int c, int ind_maxparen);
+static int find_last_paren(char_u *l, int start, int end);
+static int find_match(int lookfor, linenr_T ourscope);
+
+/*
+ * Skip over white space and C comments within the line.
+ * Also skip over Perl/shell comments if desired.
+ */
+ static char_u *
+cin_skipcomment(char_u *s)
+{
+ while (*s)
+ {
+ char_u *prev_s = s;
+
+ s = skipwhite(s);
+
+ /* Perl/shell # comment comment continues until eol. Require a space
+ * before # to avoid recognizing $#array. */
+ if (curbuf->b_ind_hash_comment != 0 && s != prev_s && *s == '#')
+ {
+ s += STRLEN(s);
+ break;
+ }
+ if (*s != '/')
+ break;
+ ++s;
+ if (*s == '/') /* slash-slash comment continues till eol */
+ {
+ s += STRLEN(s);
+ break;
+ }
+ if (*s != '*')
+ break;
+ for (++s; *s; ++s) /* skip slash-star comment */
+ if (s[0] == '*' && s[1] == '/')
+ {
+ s += 2;
+ break;
+ }
+ }
+ return s;
+}
+
+/*
+ * Return TRUE if there is no code at *s. White space and comments are
+ * not considered code.
+ */
+ static int
+cin_nocode(char_u *s)
+{
+ return *cin_skipcomment(s) == NUL;
+}
+
+/*
+ * Check previous lines for a "//" line comment, skipping over blank lines.
+ */
+ static pos_T *
+find_line_comment(void) /* XXX */
+{
+ static pos_T pos;
+ char_u *line;
+ char_u *p;
+
+ pos = curwin->w_cursor;
+ while (--pos.lnum > 0)
+ {
+ line = ml_get(pos.lnum);
+ p = skipwhite(line);
+ if (cin_islinecomment(p))
+ {
+ pos.col = (int)(p - line);
+ return &pos;
+ }
+ if (*p != NUL)
+ break;
+ }
+ return NULL;
+}
+
+/*
+ * Return TRUE if "text" starts with "key:".
+ */
+ static int
+cin_has_js_key(char_u *text)
+{
+ char_u *s = skipwhite(text);
+ int quote = -1;
+
+ if (*s == '\'' || *s == '"')
+ {
+ /* can be 'key': or "key": */
+ quote = *s;
+ ++s;
+ }
+ if (!vim_isIDc(*s)) /* need at least one ID character */
+ return FALSE;
+
+ while (vim_isIDc(*s))
+ ++s;
+ if (*s == quote)
+ ++s;
+
+ s = cin_skipcomment(s);
+
+ /* "::" is not a label, it's C++ */
+ return (*s == ':' && s[1] != ':');
+}
+
+/*
+ * Check if string matches "label:"; move to character after ':' if true.
+ * "*s" must point to the start of the label, if there is one.
+ */
+ static int
+cin_islabel_skip(char_u **s)
+{
+ if (!vim_isIDc(**s)) /* need at least one ID character */
+ return FALSE;
+
+ while (vim_isIDc(**s))
+ (*s)++;
+
<