summaryrefslogtreecommitdiff
path: root/data/vim/patches/8.1.0857
diff options
context:
space:
mode:
Diffstat (limited to 'data/vim/patches/8.1.0857')
-rw-r--r--data/vim/patches/8.1.08579872
1 files changed, 9872 insertions, 0 deletions
diff --git a/data/vim/patches/8.1.0857 b/data/vim/patches/8.1.0857
new file mode 100644
index 000000000..06d20502e
--- /dev/null
+++ b/data/vim/patches/8.1.0857
@@ -0,0 +1,9872 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 8.1.0857
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 8.1.0857
+Problem: Indent functionality is not separated.
+Solution: Move indent functionality into a new file. (Yegappan Lakshmanan,
+ closes #3886)
+Files: Filelist, src/Make_bc5.mak, src/Make_cyg_ming.mak,
+ src/Make_dice.mak, src/Make_ivc.mak, src/Make_manx.mak,
+ src/Make_morph.mak, src/Make_mvc.mak, src/Make_sas.mak,
+ src/Make_vms.mms, src/Makefile, src/edit.c, src/indent.c,
+ src/misc1.c, src/proto.h, src/proto/edit.pro,
+ src/proto/indent.pro, src/proto/misc1.pro
+
+
+*** ../vim-8.1.0856/Filelist 2019-01-26 16:20:44.256683619 +0100
+--- Filelist 2019-01-31 13:43:23.348467289 +0100
+***************
+*** 49,54 ****
+--- 49,55 ----
+ src/gui_beval.c \
+ src/hardcopy.c \
+ src/hashtab.c \
++ src/indent.c \
+ src/json.c \
+ src/json_test.c \
+ src/kword_test.c \
+***************
+*** 175,180 ****
+--- 176,182 ----
+ src/proto/gui_beval.pro \
+ src/proto/hardcopy.pro \
+ src/proto/hashtab.pro \
++ src/proto/indent.pro \
+ src/proto/json.pro \
+ src/proto/list.pro \
+ src/proto/main.pro \
+*** ../vim-8.1.0856/src/Make_bc5.mak 2019-01-26 16:20:44.256683619 +0100
+--- src/Make_bc5.mak 2019-01-31 13:43:23.348467289 +0100
+***************
+*** 548,553 ****
+--- 548,554 ----
+ $(OBJDIR)\getchar.obj \
+ $(OBJDIR)\hardcopy.obj \
+ $(OBJDIR)\hashtab.obj \
++ $(OBJDIR)\indent.obj \
+ $(OBJDIR)\json.obj \
+ $(OBJDIR)\list.obj \
+ $(OBJDIR)\main.obj \
+*** ../vim-8.1.0856/src/Make_cyg_ming.mak 2019-01-26 16:20:44.256683619 +0100
+--- src/Make_cyg_ming.mak 2019-01-31 13:43:23.348467289 +0100
+***************
+*** 720,725 ****
+--- 720,726 ----
+ $(OUTDIR)/getchar.o \
+ $(OUTDIR)/hardcopy.o \
+ $(OUTDIR)/hashtab.o \
++ $(OUTDIR)/indent.o \
+ $(OUTDIR)/json.o \
+ $(OUTDIR)/list.o \
+ $(OUTDIR)/main.o \
+*** ../vim-8.1.0856/src/Make_dice.mak 2019-01-26 16:20:44.256683619 +0100
+--- src/Make_dice.mak 2019-01-31 13:43:23.348467289 +0100
+***************
+*** 50,55 ****
+--- 50,56 ----
+ getchar.c \
+ hardcopy.c \
+ hashtab.c \
++ indent.c \
+ json.c \
+ list.c \
+ main.c \
+***************
+*** 108,113 ****
+--- 109,115 ----
+ o/getchar.o \
+ o/hardcopy.o \
+ o/hashtab.o \
++ o/indent.o \
+ o/json.o \
+ o/list.o \
+ o/main.o \
+***************
+*** 209,214 ****
+--- 211,218 ----
+
+ o/hashtab.o: hashtab.c $(SYMS)
+
++ o/indent.o: indent.c $(SYMS)
++
+ o/json.o: json.c $(SYMS)
+
+ o/list.o: list.c $(SYMS)
+*** ../vim-8.1.0856/src/Make_ivc.mak 2019-01-26 16:20:44.256683619 +0100
+--- src/Make_ivc.mak 2019-01-31 13:43:23.348467289 +0100
+***************
+*** 234,239 ****
+--- 234,240 ----
+ "$(INTDIR)/getchar.obj" \
+ "$(INTDIR)/hardcopy.obj" \
+ "$(INTDIR)/hashtab.obj" \
++ "$(INTDIR)/indent.obj" \
+ "$(INTDIR)/json.obj" \
+ "$(INTDIR)/list.obj" \
+ "$(INTDIR)/main.obj" \
+***************
+*** 434,439 ****
+--- 435,444 ----
+ SOURCE=.\hashtab.c
+ # End Source File
+ # Begin Source File
++ #
++ SOURCE=.\indent.c
++ # End Source File
++ # Begin Source File
+
+ SOURCE=.\gui.c
+
+*** ../vim-8.1.0856/src/Make_manx.mak 2019-01-26 16:20:44.260683581 +0100
+--- src/Make_manx.mak 2019-01-31 13:43:23.348467289 +0100
+***************
+*** 60,65 ****
+--- 60,66 ----
+ getchar.c \
+ hardcopy.c \
+ hashtab.c \
++ indent.c \
+ json.c \
+ list.c \
+ main.c \
+***************
+*** 120,125 ****
+--- 121,127 ----
+ obj/getchar.o \
+ obj/hardcopy.o \
+ obj/hashtab.o \
++ obj/indent.o \
+ obj/json.o \
+ obj/list.o \
+ obj/main.o \
+***************
+*** 178,183 ****
+--- 180,186 ----
+ proto/getchar.pro \
+ proto/hardcopy.pro \
+ proto/hashtab.pro \
++ proto/indent.pro \
+ proto/json.pro \
+ proto/list.pro \
+ proto/main.pro \
+***************
+*** 329,334 ****
+--- 332,340 ----
+ obj/hashtab.o: hashtab.c
+ $(CCSYM) $@ hashtab.c
+
++ obj/indent.o: indent.c
++ $(CCSYM) $@ indent.c
++
+ obj/json.o: json.c
+ $(CCSYM) $@ json.c
+
+*** ../vim-8.1.0856/src/Make_morph.mak 2019-01-26 16:20:44.260683581 +0100
+--- src/Make_morph.mak 2019-01-31 13:43:23.348467289 +0100
+***************
+*** 48,53 ****
+--- 48,54 ----
+ getchar.c \
+ hardcopy.c \
+ hashtab.c \
++ indent.c \
+ json.c \
+ list.c \
+ main.c \
+*** ../vim-8.1.0856/src/Make_mvc.mak 2019-01-26 16:20:44.260683581 +0100
+--- src/Make_mvc.mak 2019-01-31 13:43:23.348467289 +0100
+***************
+*** 725,730 ****
+--- 725,731 ----
+ $(OUTDIR)\getchar.obj \
+ $(OUTDIR)\hardcopy.obj \
+ $(OUTDIR)\hashtab.obj \
++ $(OUTDIR)\indent.obj \
+ $(OUTDIR)\json.obj \
+ $(OUTDIR)\list.obj \
+ $(OUTDIR)\main.obj \
+***************
+*** 1414,1419 ****
+--- 1415,1422 ----
+
+ $(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,1650 ****
+--- 1648,1654 ----
+ proto/getchar.pro \
+ proto/hardcopy.pro \
+ proto/hashtab.pro \
++ proto/indent.pro \
+ proto/json.pro \
+ proto/list.pro \
+ proto/main.pro \
+*** ../vim-8.1.0856/src/Make_sas.mak 2019-01-26 16:20:44.260683581 +0100
+--- src/Make_sas.mak 2019-01-31 13:43:23.348467289 +0100
+***************
+*** 113,118 ****
+--- 113,119 ----
+ getchar.c \
+ hardcopy.c \
+ hashtab.c \
++ indent.c \
+ json.c \
+ list.c \
+ main.c \
+***************
+*** 172,177 ****
+--- 173,179 ----
+ getchar.o \
+ hardcopy.o \
+ hashtab.o \
++ indent.o \
+ json.o \
+ list.o \
+ main.o \
+***************
+*** 231,236 ****
+--- 233,239 ----
+ proto/getchar.pro \
+ proto/hardcopy.pro \
+ proto/hashtab.pro \
++ proto/indent.pro \
+ proto/json.pro \
+ proto/list.pro \
+ proto/main.pro \
+***************
+*** 368,373 ****
+--- 371,378 ----
+ 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
+*** ../vim-8.1.0856/src/Make_vms.mms 2019-01-26 16:20:44.260683581 +0100
+--- src/Make_vms.mms 2019-01-31 13:43:23.352467260 +0100
+***************
+*** 314,320 ****
+
+ 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 \
+ 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 \
+--- 314,320 ----
+
+ 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 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,329 ****
+
+ 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 \
+ 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 \
+--- 323,329 ----
+
+ 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 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,601 ****
+--- 596,602 ----
+ 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 \
+*** ../vim-8.1.0856/src/Makefile 2019-01-26 17:36:46.997192946 +0100
+--- src/Makefile 2019-01-31 13:43:23.352467260 +0100
+***************
+*** 1599,1604 ****
+--- 1598,1604 ----
+ hashtab.c \
+ if_cscope.c \
+ if_xcmdsrv.c \
++ indent.c \
+ json.c \
+ list.c \
+ main.c \
+***************
+*** 1712,1717 ****
+--- 1712,1718 ----
+ $(HANGULIN_OBJ) \
+ objects/if_cscope.o \
+ objects/if_xcmdsrv.o \
++ objects/indent.o \
+ objects/list.o \
+ objects/mark.o \
+ objects/memline.o \
+***************
+*** 1842,1847 ****
+--- 1843,1849 ----
+ if_python3.pro \
+ if_ruby.pro \
+ if_xcmdsrv.pro \
++ indent.pro \
+ json.pro \
+ list.pro \
+ main.pro \
+***************
+*** 3093,3098 ****
+--- 3095,3103 ----
+ 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,3495 ****
+--- 3495,3504 ----
+ 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 \
+*** ../vim-8.1.0856/src/edit.c 2019-01-26 17:28:22.220599167 +0100
+--- src/edit.c 2019-01-31 13:43:23.352467260 +0100
+***************
+*** 216,224 ****
+ 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);
+--- 216,221 ----
+***************
+*** 380,385 ****
+--- 377,383 ----
+ 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,1055 ****
+--- 1048,1054 ----
+ 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,8254 ****
+ (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.
+--- 7922,7927 ----
+*** ../vim-8.1.0856/src/indent.c 2019-01-31 13:47:08.550925126 +0100
+--- src/indent.c 2019-01-31 13:43:23.352467260 +0100
+***************
+*** 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)++;
++
++ *s = cin_skipcomment(*s);
++
++ /* "::" is not a label, it's C++ */
++ return (**s == ':' && *++*s != ':');
++ }
++
++ /*
++ * Recognize a label: "label:".
++ * Note: curwin->w_cursor must be where we are looking for the label.
++ */
++ int
++ cin_islabel(void) /* XXX */
++ {
++ char_u *s;
++
++ s = cin_skipcomment(ml_get_curline());
++
++ /*
++ * Exclude "default" from labels, since it should be indented
++ * like a switch label. Same for C++ scope declarations.
++ */
++ if (cin_isdefault(s))
++ return FALSE;
++ if (cin_isscopedecl(s))
++ return FALSE;
++
++ if (cin_islabel_skip(&s))
++ {
++ /*
++ * Only accept a label if the previous line is terminated or is a case
++ * label.
++ */
++ pos_T cursor_save;
++ pos_T *trypos;
++ char_u *line;
++
++ cursor_save = curwin->w_cursor;
++ while (curwin->w_cursor.lnum > 1)
++ {
++ --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)) != NULL) /* XXX */
++ curwin->w_cursor = *trypos;
++
++ line = ml_get_curline();
++ if (cin_ispreproc(line)) /* ignore #defines, #if, etc. */
++ continue;
++ if (*(line = cin_skipcomment(line)) == NUL)
++ continue;
++
++ curwin->w_cursor = cursor_save;
++ if (cin_isterminated(line, TRUE, FALSE)
++ || cin_isscopedecl(line)
++ || cin_iscase(line, TRUE)
++ || (cin_islabel_skip(&line) && cin_nocode(line)))
++ return TRUE;
++ return FALSE;
++ }
++ curwin->w_cursor = cursor_save;
++ return TRUE; /* label at start of file??? */
++ }
++ return FALSE;
++ }
++
++ /*
++ * Recognize structure initialization and enumerations:
++ * "[typedef] [static|public|protected|private] enum"
++ * "[typedef] [static|public|protected|private] = {"
++ */
++ static int
++ cin_isinit(void)
++ {
++ char_u *s;
++ static char *skip[] = {"static", "public", "protected", "private"};
++
++ s = cin_skipcomment(ml_get_curline());
++
++ if (cin_starts_with(s, "typedef"))
++ s = cin_skipcomment(s + 7);
++
++ for (;;)
++ {
++ int i, l;
++
++ for (i = 0; i < (int)(sizeof(skip) / sizeof(char *)); ++i)
++ {
++ l = (int)strlen(skip[i]);
++ if (cin_starts_with(s, skip[i]))
++ {
++ s = cin_skipcomment(s + l);
++ l = 0;
++ break;
++ }
++ }
++ if (l != 0)
++ break;
++ }
++
++ if (cin_starts_with(s, "enum"))
++ return TRUE;
++
++ if (cin_ends_in(s, (char_u *)"=", (char_u *)"{"))
++ return TRUE;
++
++ return FALSE;
++ }
++
++ /*
++ * Recognize a switch label: "case .*:" or "default:".
++ */
++ int
++ cin_iscase(
++ char_u *s,
++ int strict) /* Allow relaxed check of case statement for JS */
++ {
++ s = cin_skipcomment(s);
++ if (cin_starts_with(s, "case"))
++ {
++ for (s += 4; *s; ++s)
++ {
++ s = cin_skipcomment(s);
++ if (*s == ':')
++ {
++ if (s[1] == ':') /* skip over "::" for C++ */
++ ++s;
++ else
++ return TRUE;
++ }
++ if (*s == '\'' && s[1] && s[2] == '\'')
++ s += 2; /* skip over ':' */
++ else if (*s == '/' && (s[1] == '*' || s[1] == '/'))
++ return FALSE; /* stop at comment */
++ else if (*s == '"')
++ {
++ /* JS etc. */
++ if (strict)
++ return FALSE; /* stop at string */
++ else
++ return TRUE;
++ }
++ }
++ return FALSE;
++ }
++
++ if (cin_isdefault(s))
++ return TRUE;
++ return FALSE;
++ }
++
++ /*
++ * Recognize a "default" switch label.
++ */
++ static int
++ cin_isdefault(char_u *s)
++ {
++ return (STRNCMP(s, "default", 7) == 0
++ && *(s = cin_skipcomment(s + 7)) == ':'
++ && s[1] != ':');
++ }
++
++ /*
++ * Recognize a "public/private/protected" scope declaration label.
++ */
++ int
++ cin_isscopedecl(char_u *s)
++ {
++ int i;
++
++ s = cin_skipcomment(s);
++ if (STRNCMP(s, "public", 6) == 0)
++ i = 6;
++ else if (STRNCMP(s, "protected", 9) == 0)
++ i = 9;
++ else if (STRNCMP(s, "private", 7) == 0)
++ i = 7;
++ else
++ return FALSE;
++ return (*(s = cin_skipcomment(s + i)) == ':' && s[1] != ':');
++ }
++
++ /* Maximum number of lines to search back for a "namespace" line. */
++ #define FIND_NAMESPACE_LIM 20
++
++ /*
++ * Recognize a "namespace" scope declaration.
++ */
++ static int
++ cin_is_cpp_namespace(char_u *s)
++ {
++ char_u *p;
++ int has_name = FALSE;
++ int has_name_start = FALSE;
++
++ s = cin_skipcomment(s);
++ if (STRNCMP(s, "namespace", 9) == 0 && (s[9] == NUL || !vim_iswordc(s[9])))
++ {
++ p = cin_skipcomment(skipwhite(s + 9));
++ while (*p != NUL)
++ {
++ if (VIM_ISWHITE(*p))
++ {
++ has_name = TRUE; /* found end of a name */
++ p = cin_skipcomment(skipwhite(p));
++ }
++ else if (*p == '{')
++ {
++ break;
++ }
++ else if (vim_iswordc(*p))
++ {
++ has_name_start = TRUE;
++ if (has_name)
++ return FALSE; /* word character after skipping past name */
++ ++p;
++ }
++ else if (p[0] == ':' && p[1] == ':' && vim_iswordc(p[2]))
++ {
++ if (!has_name_start || has_name)
++ return FALSE;
++ /* C++ 17 nested namespace */
++ p += 3;
++ }
++ else
++ {
++ return FALSE;
++ }
++ }
++ return TRUE;
++ }
++ return FALSE;
++ }
++
++ /*
++ * Recognize a `extern "C"` or `extern "C++"` linkage specifications.
++ */
++ static int
++ cin_is_cpp_extern_c(char_u *s)
++ {
++ char_u *p;
++ int has_string_literal = FALSE;
++
++ s = cin_skipcomment(s);
++ if (STRNCMP(s, "extern", 6) == 0 && (s[6] == NUL || !vim_iswordc(s[6])))
++ {
++ p = cin_skipcomment(skipwhite(s + 6));
++ while (*p != NUL)
++ {
++ if (VIM_ISWHITE(*p))
++ {
++ p = cin_skipcomment(skipwhite(p));
++ }
++ else if (*p == '{')
++ {
++ break;
++ }
++ else if (p[0] == '"' && p[1] == 'C' && p[2] == '"')
++ {
++ if (has_string_literal)
++ return FALSE;
++ has_string_literal = TRUE;
++ p += 3;
++ }
++ else if (p[0] == '"' && p[1] == 'C' && p[2] == '+' && p[3] == '+'
++ && p[4] == '"')
++ {
++ if (has_string_literal)
++ return FALSE;
++ has_string_literal = TRUE;
++ p += 5;
++ }
++ else
++ {
++ return FALSE;
++ }
++ }
++ return has_string_literal ? TRUE : FALSE;
++ }
++ return FALSE;
++ }
++
++ /*
++ * Return a pointer to the first non-empty non-comment character after a ':'.
++ * Return NULL if not found.
++ * case 234: a = b;
++ * ^
++ */
++ static char_u *
++ after_label(char_u *l)
++ {
++ for ( ; *l; ++l)
++ {
++ if (*l == ':')
++ {
++ if (l[1] == ':') /* skip over "::" for C++ */
++ ++l;
++ else if (!cin_iscase(l + 1, FALSE))
++ break;
++ }
++ else if (*l == '\'' && l[1] && l[2] == '\'')
++ l += 2; /* skip over 'x' */
++ }
++ if (*l == NUL)
++ return NULL;
++ l = cin_skipcomment(l + 1);
++ if (*l == NUL)
++ return NULL;
++ return l;
++ }
++
++ /*
++ * Get indent of line "lnum", skipping a label.
++ * Return 0 if there is nothing after the label.
++ */
++ static int
++ get_indent_nolabel (linenr_T lnum) /* XXX */
++ {
++ char_u *l;
++ pos_T fp;
++ colnr_T col;
++ char_u *p;
++
++ l = ml_get(lnum);
++ p = after_label(l);
++ if (p == NULL)
++ return 0;
++
++ fp.col = (colnr_T)(p - l);
++ fp.lnum = lnum;
++ getvcol(curwin, &fp, &col, NULL, NULL);
++ return (int)col;
++ }
++
++ /*
++ * Find indent for line "lnum", ignoring any case or jump label.
++ * Also return a pointer to the text (after the label) in "pp".
++ * label: if (asdf && asdfasdf)
++ * ^
++ */
++ static int
++ skip_label(linenr_T lnum, char_u **pp)
++ {
++ char_u *l;
++ int amount;
++ pos_T cursor_save;
++
++ cursor_save = curwin->w_cursor;
++ curwin->w_cursor.lnum = lnum;
++ l = ml_get_curline();
++ /* XXX */
++ if (cin_iscase(l, FALSE) || cin_isscopedecl(l) || cin_islabel())
++ {
++ amount = get_indent_nolabel(lnum);
++ l = after_label(ml_get_curline());
++ if (l == NULL) /* just in case */
++ l = ml_get_curline();
++ }
++ else
++ {
++ amount = get_indent();
++ l = ml_get_curline();
++ }
++ *pp = l;
++
++ curwin->w_cursor = cursor_save;
++ return amount;
++ }
++
++ /*
++ * Return the indent of the first variable name after a type in a declaration.
++ * int a, indent of "a"
++ * static struct foo b, indent of "b"
++ * enum bla c, indent of "c"
++ * Returns zero when it doesn't look like a declaration.
++ */
++ static int
++ cin_first_id_amount(void)
++ {
++ char_u *line, *p, *s;
++ int len;
++ pos_T fp;
++ colnr_T col;
++
++ line = ml_get_curline();
++ p = skipwhite(line);
++ len = (int)(skiptowhite(p) - p);
++ if (len == 6 && STRNCMP(p, "static", 6) == 0)
++ {
++ p = skipwhite(p + 6);
++ len = (int)(skiptowhite(p) - p);
++ }
++ if (len == 6 && STRNCMP(p, "struct", 6) == 0)
++ p = skipwhite(p + 6);
++ else if (len == 4 && STRNCMP(p, "enum", 4) == 0)
++ p = skipwhite(p + 4);
++ else if ((len == 8 && STRNCMP(p, "unsigned", 8) == 0)
++ || (len == 6 && STRNCMP(p, "signed", 6) == 0))
++ {
++ s = skipwhite(p + len);
++ if ((STRNCMP(s, "int", 3) == 0 && VIM_ISWHITE(s[3]))
++ || (STRNCMP(s, "long", 4) == 0 && VIM_ISWHITE(s[4]))
++ || (STRNCMP(s, "short", 5) == 0 && VIM_ISWHITE(s[5]))
++ || (STRNCMP(s, "char", 4) == 0 && VIM_ISWHITE(s[4])))
++ p = s;
++ }
++ for (len = 0; vim_isIDc(p[len]); ++len)
++ ;
++ if (len == 0 || !VIM_ISWHITE(p[len]) || cin_nocode(p))
++ return 0;
++
++ p = skipwhite(p + len);
++ fp.lnum = curwin->w_cursor.lnum;
++ fp.col = (colnr_T)(p - line);
++ getvcol(curwin, &fp, &col, NULL, NULL);
++ return (int)col;
++ }
++
++ /*
++ * Return the indent of the first non-blank after an equal sign.
++ * char *foo = "here";
++ * Return zero if no (useful) equal sign found.
++ * Return -1 if the line above "lnum" ends in a backslash.
++ * foo = "asdf\
++ * asdf\
++ * here";
++ */
++ static int
++ cin_get_equal_amount(linenr_T lnum)
++ {
++ char_u *line;
++ char_u *s;
++ colnr_T col;
++ pos_T fp;
++
++ if (lnum > 1)
++ {
++ line = ml_get(lnum - 1);
++ if (*line != NUL && line[STRLEN(line) - 1] == '\\')
++ return -1;
++ }
++
++ line = s = ml_get(lnum);
++ while (*s != NUL && vim_strchr((char_u *)"=;{}\"'", *s) == NULL)
++ {
++ if (cin_iscomment(s)) /* ignore comments */
++ s = cin_skipcomment(s);
++ else
++ ++s;
++ }
++ if (*s != '=')
++ return 0;
++
++ s = skipwhite(s + 1);
++ if (cin_nocode(s))
++ return 0;
++
++ if (*s == '"') /* nice alignment for continued strings */
++ ++s;
++
++ fp.lnum = lnum;
++ fp.col = (colnr_T)(s - line);
++ getvcol(curwin, &fp, &col, NULL, NULL);
++ return (int)col;
++ }
++
++ /*
++ * Recognize a preprocessor statement: Any line that starts with '#'.
++ */
++ static int
++ cin_ispreproc(char_u *s)
++ {
++ if (*skipwhite(s) == '#')
++ return TRUE;
++ return FALSE;
++ }
++
++ /*
++ * Return TRUE if line "*pp" at "*lnump" is a preprocessor statement or a
++ * continuation line of a preprocessor statement. Decrease "*lnump" to the
++ * start and return the line in "*pp".
++ * Put the amount of indent in "*amount".
++ */
++ static int
++ cin_ispreproc_cont(char_u **pp, linenr_T *lnump, int *amount)
++ {
++ char_u *line = *pp;
++ linenr_T lnum = *lnump;
++ int retval = FALSE;
++ int candidate_amount = *amount;
++
++ if (*line != NUL && line[STRLEN(line) - 1] == '\\')
++ candidate_amount = get_indent_lnum(lnum);
++
++ for (;;)
++ {
++ if (cin_ispreproc(line))
++ {
++ retval = TRUE;
++ *lnump = lnum;
++ break;
++ }
++ if (lnum == 1)
++ break;
++ line = ml_get(--lnum);
++ if (*line == NUL || line[STRLEN(line) - 1] != '\\')
++ break;
++ }
++
++ if (lnum != *lnump)
++ *pp = ml_get(*lnump);
++ if (retval)
++ *amount = candidate_amount;
++ return retval;
++ }
++
++ /*
++ * Recognize the start of a C or C++ comment.
++ */
++ static int
++ cin_iscomment(char_u *p)
++ {
++ return (p[0] == '/' && (p[1] == '*' || p[1] == '/'));
++ }
++
++ /*
++ * Recognize the start of a "//" comment.
++ */
++ static int
++ cin_islinecomment(char_u *p)
++ {
++ return (p[0] == '/' && p[1] == '/');
++ }
++
++ /*
++ * Recognize a line that starts with '{' or '}', or ends with ';', ',', '{' or
++ * '}'.
++ * Don't consider "} else" a terminated line.
++ * If a line begins with an "else", only consider it terminated if no unmatched
++ * opening braces follow (handle "else { foo();" correctly).
++ * Return the character terminating the line (ending char's have precedence if
++ * both apply in order to determine initializations).
++ */
++ static int
++ cin_isterminated(
++ char_u *s,
++ int incl_open, /* include '{' at the end as terminator */
++ int incl_comma) /* recognize a trailing comma */
++ {
++ char_u found_start = 0;
++ unsigned n_open = 0;
++ int is_else = FALSE;
++
++ s = cin_skipcomment(s);
++
++ if (*s == '{' || (*s == '}' && !cin_iselse(s)))
++ found_start = *s;
++
++ if (!found_start)
++ is_else = cin_iselse(s);
++
++ while (*s)
++ {
++ /* skip over comments, "" strings and 'c'haracters */
++ s = skip_string(cin_skipcomment(s));
++ if (*s == '}' && n_open > 0)
++ --n_open;
++ if ((!is_else || n_open == 0)
++ && (*s == ';' || *s == '}' || (incl_comma && *s == ','))
++ && cin_nocode(s + 1))
++ return *s;
++ else if (*s == '{')
++ {
++ if (incl_open && cin_nocode(s + 1))
++ return *s;
++ else
++ ++n_open;
++ }
++
++ if (*s)
++ s++;
++ }
++ return found_start;
++ }
++
++ /*
++ * Recognize the basic picture of a function declaration -- it needs to
++ * have an open paren somewhere and a close paren at the end of the line and
++ * no semicolons anywhere.
++ * When a line ends in a comma we continue looking in the next line.
++ * "sp" points to a string with the line. When looking at other lines it must
++ * be restored to the line. When it's NULL fetch lines here.
++ * "first_lnum" is where we start looking.
++ * "min_lnum" is the line before which we will not be looking.
++ */
++ static int
++ cin_isfuncdecl(
++ char_u **sp,
++ linenr_T first_lnum,
++ linenr_T min_lnum)
++ {
++ char_u *s;
++ linenr_T lnum = first_lnum;
++ linenr_T save_lnum = curwin->w_cursor.lnum;
++ int retval = FALSE;
++ pos_T *trypos;
++ int just_started = TRUE;
++
++ if (sp == NULL)
++ s = ml_get(lnum);
++ else
++ s = *sp;
++
++ curwin->w_cursor.lnum = lnum;
++ if (find_last_paren(s, '(', ')')
++ && (trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL)
++ {
++ lnum = trypos->lnum;
++ if (lnum < min_lnum)
++ {
++ curwin->w_cursor.lnum = save_lnum;
++ return FALSE;
++ }
++
++ s = ml_get(lnum);
++ }
++ curwin->w_cursor.lnum = save_lnum;
++
++ /* Ignore line starting with #. */
++ if (cin_ispreproc(s))
++ return FALSE;
++
++ while (*s && *s != '(' && *s != ';' && *s != '\'' && *s != '"')
++ {
++ if (cin_iscomment(s)) /* ignore comments */
++ s = cin_skipcomment(s);
++ else if (*s == ':')
++ {
++ if (*(s + 1) == ':')
++ s += 2;
++ else
++ /* To avoid a mistake in the following situation:
++ * A::A(int a, int b)
++ * : a(0) // <--not a function decl
++ * , b(0)
++ * {...
++ */
++ return FALSE;
++ }
++ else
++ ++s;
++ }
++ if (*s != '(')
++ return FALSE; /* ';', ' or " before any () or no '(' */
++
++ while (*s && *s != ';' && *s != '\'' && *s != '"')
++ {
++ if (*s == ')' && cin_nocode(s + 1))
++ {
++ /* ')' at the end: may have found a match
++ * Check for he previous line not to end in a backslash:
++ * #if defined(x) && \
++ * defined(y)
++ */
++ lnum = first_lnum - 1;
++ s = ml_get(lnum);
++ if (*s == NUL || s[STRLEN(s) - 1] != '\\')
++ retval = TRUE;
++ goto done;
++ }
++ if ((*s == ',' && cin_nocode(s + 1)) || s[1] == NUL || cin_nocode(s))
++ {
++ int comma = (*s == ',');
++
++ /* ',' at the end: continue looking in the next line.
++ * At the end: check for ',' in the next line, for this style:
++ * func(arg1
++ * , arg2) */
++ for (;;)
++ {
++ if (lnum >= curbuf->b_ml.ml_line_count)
++ break;
++ s = ml_get(++lnum);
++ if (!cin_ispreproc(s))
++ break;
++ }
++ if (lnum >= curbuf->b_ml.ml_line_count)
++ break;
++ /* Require a comma at end of the line or a comma or ')' at the
++ * start of next line. */
++ s = skipwhite(s);
++ if (!just_started && (!comma && *s != ',' && *s != ')'))
++ break;
++ just_started = FALSE;
++ }
++ else if (cin_iscomment(s)) /* ignore comments */
++ s = cin_skipcomment(s);
++ else
++ {
++ ++s;
++ just_started = FALSE;
++ }
++ }
++
++ done:
++ if (lnum != first_lnum && sp != NULL)
++ *sp = ml_get(first_lnum);
++
++ return retval;
++ }
++
++ static int
++ cin_isif(char_u *p)
++ {
++ return (STRNCMP(p, "if", 2) == 0 && !vim_isIDc(p[2]));
++ }
++
++ static int
++ cin_iselse(
++ char_u *p)
++ {
++ if (*p == '}') /* accept "} else" */
++ p = cin_skipcomment(p + 1);
++ return (STRNCMP(p, "else", 4) == 0 && !vim_isIDc(p[4]));
++ }
++
++ static int
++ cin_isdo(char_u *p)
++ {
++ return (STRNCMP(p, "do", 2) == 0 && !vim_isIDc(p[2]));
++ }
++
++ /*
++ * Check if this is a "while" that should have a matching "do".
++ * We only accept a "while (condition) ;", with only white space between the
++ * ')' and ';'. The condition may be spread over several lines.
++ */
++ static int
++ cin_iswhileofdo (char_u *p, linenr_T lnum) /* XXX */
++ {
++ pos_T cursor_save;
++ pos_T *trypos;
++ int retval = FALSE;
++
++ p = cin_skipcomment(p);
++ if (*p == '}') /* accept "} while (cond);" */
++ p = cin_skipcomment(p + 1);
++ if (cin_starts_with(p, "while"))
++ {
++ cursor_save = curwin->w_cursor;
++ curwin->w_cursor.lnum = lnum;
++ curwin->w_cursor.col = 0;
++ p = ml_get_curline();
++ while (*p && *p != 'w') /* skip any '}', until the 'w' of the "while" */
++ {
++ ++p;
++ ++curwin->w_cursor.col;
++ }
++ if ((trypos = findmatchlimit(NULL, 0, 0,
++ curbuf->b_ind_maxparen)) != NULL
++ && *cin_skipcomment(ml_get_pos(trypos) + 1) == ';')
++ retval = TRUE;
++ curwin->w_cursor = cursor_save;
++ }
++ return retval;
++ }
++
++ /*
++ * Check whether in "p" there is an "if", "for" or "while" before "*poffset".
++ * Return 0 if there is none.
++ * Otherwise return !0 and update "*poffset" to point to the place where the
++ * string was found.
++ */
++ static int
++ cin_is_if_for_while_before_offset(char_u *line, int *poffset)
++ {
++ int offset = *poffset;
++
++ if (offset-- < 2)
++ return 0;
++ while (offset > 2 && VIM_ISWHITE(line[offset]))
++ --offset;
++
++ offset -= 1;
++ if (!STRNCMP(line + offset, "if", 2))
++ goto probablyFound;
++
++ if (offset >= 1)
++ {
++ offset -= 1;
++ if (!STRNCMP(line + offset, "for", 3))
++ goto probablyFound;
++
++ if (offset >= 2)
++ {
++ offset -= 2;
++ if (!STRNCMP(line + offset, "while", 5))
++ goto probablyFound;
++ }
++ }
++ return 0;
++
++ probablyFound:
++ if (!offset || !vim_isIDc(line[offset - 1]))
++ {
++ *poffset = offset;
++ return 1;
++ }
++ return 0;
++ }
++
++ /*
++ * Return TRUE if we are at the end of a do-while.
++ * do
++ * nothing;
++ * while (foo
++ * && bar); <-- here
++ * Adjust the cursor to the line with "while".
++ */
++ static int
++ cin_iswhileofdo_end(int terminated)
++ {
++ char_u *line;
++ char_u *p;
++ char_u *s;
++ pos_T *trypos;
++ int i;
++
++ if (terminated != ';') /* there must be a ';' at the end */
++ return FALSE;
++
++ p = line = ml_get_curline();
++ while (*p != NUL)
++ {
++ p = cin_skipcomment(p);
++ if (*p == ')')
++ {
++ s = skipwhite(p + 1);
++ if (*s == ';' && cin_nocode(s + 1))
++ {
++ /* Found ");" at end of the line, now check there is "while"
++ * before the matching '('. XXX */
++ i = (int)(p - line);
++ curwin->w_cursor.col = i;
++ trypos = find_match_paren(curbuf->b_ind_maxparen);
++ if (trypos != NULL)
++ {
++ s = cin_skipcomment(ml_get(trypos->lnum));
++ if (*s == '}') /* accept "} while (cond);" */
++ s = cin_skipcomment(s + 1);
++ if (cin_starts_with(s, "while"))
++ {
++ curwin->w_cursor.lnum = trypos->lnum;
++ return TRUE;
++ }
++ }
++
++ /* Searching may have made "line" invalid, get it again. */
++ line = ml_get_curline();
++ p = line + i;
++ }
++ }
++ if (*p != NUL)
++ ++p;
++ }
++ return FALSE;
++ }
++
++ static int
++ cin_isbreak(char_u *p)
++ {
++ return (STRNCMP(p, "break", 5) == 0 && !vim_isIDc(p[5]));
++ }
++
++ /*
++ * Find the position of a C++ base-class declaration or
++ * constructor-initialization. eg:
++ *
++ * class MyClass :
++ * baseClass <-- here
++ * class MyClass : public baseClass,
++ * anotherBaseClass <-- here (should probably lineup ??)
++ * MyClass::MyClass(...) :
++ * baseClass(...) <-- here (constructor-initialization)
++ *
++ * This is a lot of guessing. Watch out for "cond ? func() : foo".
++ */
++ static int
++ cin_is_cpp_baseclass(
++ cpp_baseclass_cache_T *cached) /* input and output */
++ {
++ lpos_T *pos = &cached->lpos; /* find position */
++ char_u *s;
++ int class_or_struct, lookfor_ctor_init, cpp_base_class;
++ linenr_T lnum = curwin->w_cursor.lnum;
++ char_u *line = ml_get_curline();
++
++ if (pos->lnum <= lnum)
++ return cached->found; /* Use the cached result */
++
++ pos->col = 0;
++
++ s = skipwhite(line);
++ if (*s == '#') /* skip #define FOO x ? (x) : x */
++ return FALSE;
++ s = cin_skipcomment(s);
++ if (*s == NUL)
++ return FALSE;
++
++ cpp_base_class = lookfor_ctor_init = class_or_struct = FALSE;
++
++ /* Search for a line starting with '#', empty, ending in ';' or containing
++ * '{' or '}' and start below it. This handles the following situations:
++ * a = cond ?
++ * func() :
++ * asdf;
++ * func::foo()
++ * : something
++ * {}
++ * Foo::Foo (int one, int two)
++ * : something(4),
++ * somethingelse(3)
++ * {}
++ */
++ while (lnum > 1)
++ {
++ line = ml_get(lnum - 1);
++ s = skipwhite(line);
++ if (*s == '#' || *s == NUL)
++ break;
++ while (*s != NUL)
++ {
++ s = cin_skipcomment(s);
++ if (*s == '{' || *s == '}'
++ || (*s == ';' && cin_nocode(s + 1)))
++ break;
++ if (*s != NUL)
++ ++s;
++ }
++ if (*s != NUL)
++ break;
++ --lnum;
++ }
++
++ pos->lnum = lnum;
++ line = ml_get(lnum);
++ s = line;
++ for (;;)
++ {
++ if (*s == NUL)
++ {
++ if (lnum == curwin->w_cursor.lnum)
++ break;
++ /* Continue in the cursor line. */
++ line = ml_get(++lnum);
++ s = line;
++ }
++ if (s == line)
++ {
++ /* don't recognize "case (foo):" as a baseclass */
++ if (cin_iscase(s, FALSE))
++ break;
++ s = cin_skipcomment(line);
++ if (*s == NUL)
++ continue;
++ }
++
++ if (s[0] == '"' || (s[0] == 'R' && s[1] == '"'))
++ s = skip_string(s) + 1;
++ else if (s[0] == ':')
++ {
++ if (s[1] == ':')
++ {
++ /* skip double colon. It can't be a constructor
++ * initialization any more */
++ lookfor_ctor_init = FALSE;
++ s = cin_skipcomment(s + 2);
++ }
++ else if (lookfor_ctor_init || class_or_struct)
++ {
++ /* we have something found, that looks like the start of
++ * cpp-base-class-declaration or constructor-initialization */
++ cpp_base_class = TRUE;
++ lookfor_ctor_init = class_or_struct = FALSE;
++ pos->col = 0;
++ s = cin_skipcomment(s + 1);
++ }
++ else
++ s = cin_skipcomment(s + 1);
++ }
++ else if ((STRNCMP(s, "class", 5) == 0 && !vim_isIDc(s[5]))
++ || (STRNCMP(s, "struct", 6) == 0 && !vim_isIDc(s[6])))
++ {
++ class_or_struct = TRUE;
++ lookfor_ctor_init = FALSE;
++
++ if (*s == 'c')
++ s = cin_skipcomment(s + 5);
++ else
++ s = cin_skipcomment(s + 6);
++ }
++ else
++ {
++ if (s[0] == '{' || s[0] == '}' || s[0] == ';')
++ {
++ cpp_base_class = lookfor_ctor_init = class_or_struct = FALSE;
++ }
++ else if (s[0] == ')')
++ {
++ /* Constructor-initialization is assumed if we come across
++ * something like "):" */
++ class_or_struct = FALSE;
++ lookfor_ctor_init = TRUE;
++ }
++ else if (s[0] == '?')
++ {
++ /* Avoid seeing '() :' after '?' as constructor init. */
++ return FALSE;
++ }
++ else if (!vim_isIDc(s[0]))
++ {
++ /* if it is not an identifier, we are wrong */
++ class_or_struct = FALSE;
++ lookfor_ctor_init = FALSE;
++ }
++ else if (pos->col == 0)
++ {
++ /* it can't be a constructor-initialization any more */
++ lookfor_ctor_init = FALSE;
++
++ /* the first statement starts here: lineup with this one... */
++ if (cpp_base_class)
++ pos->col = (colnr_T)(s - line);
++ }
++
++ /* When the line ends in a comma don't align with it. */
++ if (lnum == curwin->w_cursor.lnum && *s == ',' && cin_nocode(s + 1))
++ pos->col = 0;
++
++ s = cin_skipcomment(s + 1);
++ }
++ }
++
++ cached->found = cpp_base_class;
++ if (cpp_base_class)
++ pos->lnum = lnum;
++ return cpp_base_class;
++ }
++
++ static int
++ get_baseclass_amount(int col)
++ {
++ int amount;
++ colnr_T vcol;
++ pos_T *trypos;
++
++ if (col == 0)
++ {
++ amount = get_indent();
++ if (find_last_paren(ml_get_curline(), '(', ')')
++ && (trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL)
++ amount = get_indent_lnum(trypos->lnum); /* XXX */
++ if (!cin_ends_in(ml_get_curline(), (char_u *)",", NULL))
++ amount += curbuf->b_ind_cpp_baseclass;
++ }
++ else
++ {
++ curwin->w_cursor.col = col;
++ getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
++ amount = (int)vcol;
++ }
++ if (amount < curbuf->b_ind_cpp_baseclass)
++ amount = curbuf->b_ind_cpp_baseclass;
++ return amount;
++ }
++
++ /*
++ * Return TRUE if string "s" ends with the string "find", possibly followed by
++ * white space and comments. Skip strings and comments.
++ * Ignore "ignore" after "find" if it's not NULL.
++ */
++ static int
++ cin_ends_in(char_u *s, char_u *find, char_u *ignore)
++ {
++ char_u *p = s;
++ char_u *r;
++ int len = (int)STRLEN(find);
++
++ while (*p != NUL)
++ {
++ p = cin_skipcomment(p);
++ if (STRNCMP(p, find, len) == 0)
++ {
++ r = skipwhite(p + len);
++ if (ignore != NULL && STRNCMP(r, ignore, STRLEN(ignore)) == 0)
++ r = skipwhite(r + STRLEN(ignore));
++ if (cin_nocode(r))
++ return TRUE;
++ }
++ if (*p != NUL)
++ ++p;
++ }
++ return FALSE;
++ }
++
++ /*
++ * Return TRUE when "s" starts with "word" and then a non-ID character.
++ */
++ static int
++ cin_starts_with(char_u *s, char *word)
++ {
++ int l = (int)STRLEN(word);
++
++ return (STRNCMP(s, word, l) == 0 && !vim_isIDc(s[l]));
++ }
++
++ /*
++ * Skip strings, chars and comments until at or past "trypos".
++ * Return the column found.
++ */
++ static int
++ cin_skip2pos(pos_T *trypos)
++ {
++ char_u *line;
++ char_u *p;
++ char_u *new_p;
++
++ p = line = ml_get(trypos->lnum);
++ while (*p && (colnr_T)(p - line) < trypos->col)
++ {
++ if (cin_iscomment(p))
++ p = cin_skipcomment(p);
++ else
++ {
++ new_p = skip_string(p);
++ if (new_p == p)
++ ++p;
++ else
++ p = new_p;
++ }
++ }
++ return (int)(p - line);
++ }
++
++ /*
++ * Find the '{' at the start of the block we are in.
++ * Return NULL if no match found.
++ * Ignore a '{' that is in a comment, makes indenting the next three lines
++ * work. */
++ /* foo() */
++ /* { */
++ /* } */
++
++ static pos_T *
++ find_start_brace(void) /* XXX */
++ {
++ pos_T cursor_save;
++ pos_T *trypos;
++ pos_T *pos;
++ static pos_T pos_copy;
++
++ cursor_save = curwin->w_cursor;
++ while ((trypos = findmatchlimit(NULL, '{', FM_BLOCKSTOP, 0)) != NULL)
++ {
++ pos_copy = *trypos; /* copy pos_T, next findmatch will change it */
++ trypos = &pos_copy;
++ curwin->w_cursor = *trypos;
++ 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)) == NULL) /* XXX */
++ break;
++ if (pos != NULL)
++ curwin->w_cursor.lnum = pos->lnum;
++ }
++ curwin->w_cursor = cursor_save;
++ return trypos;
++ }
++
++ /*
++ * Find the matching '(', ignoring it if it is in a comment.
++ * Return NULL if no match found.
++ */
++ static pos_T *
++ find_match_paren(int ind_maxparen) /* XXX */
++ {
++ return find_match_char('(', ind_maxparen);
++ }
++
++ static pos_T *
++ find_match_char(int c, int ind_maxparen) /* XXX */
++ {
++ pos_T cursor_save;
++ pos_T *trypos;
++ static pos_T pos_copy;
++ int ind_maxp_wk;
++
++ cursor_save = curwin->w_cursor;
++ ind_maxp_wk = ind_maxparen;
++ retry:
++ if ((trypos = findmatchlimit(NULL, c, 0, ind_maxp_wk)) != NULL)
++ {
++ /* check if the ( is in a // comment */
++ if ((colnr_T)cin_skip2pos(trypos) > trypos->col)
++ {
++ ind_maxp_wk = ind_maxparen - (int)(cursor_save.lnum - trypos->lnum);
++ if (ind_maxp_wk > 0)
++ {
++ curwin->w_cursor = *trypos;
++ curwin->w_cursor.col = 0; /* XXX */
++ goto retry;
++ }
++ trypos = NULL;
++ }
++ else
++ {
++ pos_T *trypos_wk;
++
++ pos_copy = *trypos; /* copy trypos, findmatch will change it */
++ trypos = &pos_copy;
++ curwin->w_cursor = *trypos;
++ if ((trypos_wk = ind_find_start_CORS(NULL)) != NULL) /* XXX */
++ {
++ ind_maxp_wk = ind_maxparen - (int)(cursor_save.lnum
++ - trypos_wk->lnum);
++ if (ind_maxp_wk > 0)
++ {
++ curwin->w_cursor = *trypos_wk;
++ goto retry;
++ }
++ trypos = NULL;
++ }
++ }
++ }
++ curwin->w_cursor = cursor_save;
++ return trypos;
++ }
++
++ /*
++ * Find the matching '(', ignoring it if it is in a comment or before an
++ * unmatched {.
++ * Return NULL if no match found.
++ */
++ static pos_T *
++ find_match_paren_after_brace (int ind_maxparen) /* XXX */
++ {
++ pos_T *trypos = find_match_paren(ind_maxparen);
++
++ if (trypos != NULL)
++ {
++ pos_T *tryposBrace = find_start_brace();
++
++ /* If both an unmatched '(' and '{' is found. Ignore the '('
++ * position if the '{' is further down. */
++ if (tryposBrace != NULL
++ && (trypos->lnum != tryposBrace->lnum
++ ? trypos->lnum < tryposBrace->lnum
++ : trypos->col < tryposBrace->col))
++ trypos = NULL;
++ }
++ return trypos;
++ }
++
++ /*
++ * Return ind_maxparen corrected for the difference in line number between the
++ * cursor position and "startpos". This makes sure that searching for a
++ * matching paren above the cursor line doesn't find a match because of
++ * looking a few lines further.
++ */
++ static int
++ corr_ind_maxparen(pos_T *startpos)
++ {
++ long n = (long)startpos->lnum - (long)curwin->w_cursor.lnum;
++
++ if (n > 0 && n < curbuf->b_ind_maxparen / 2)
++ return curbuf->b_ind_maxparen - (int)n;
++ return curbuf->b_ind_maxparen;
++ }
++
++ /*
++ * Set w_cursor.col to the column number of the last unmatched ')' or '{' in
++ * line "l". "l" must point to the start of the line.
++ */
++ static int
++ find_last_paren(char_u *l, int start, int end)
++ {
++ int i;
++ int retval = FALSE;
++ int open_count = 0;
++
++ curwin->w_cursor.col = 0; /* default is start of line */
++
++ for (i = 0; l[i] != NUL; i++)
++ {
++ i = (int)(cin_skipcomment(l + i) - l); /* ignore parens in comments */
++ i = (int)(skip_string(l + i) - l); /* ignore parens in quotes */
++ if (l[i] == start)
++ ++open_count;
++ else if (l[i] == end)
++ {
++ if (open_count > 0)
++ --open_count;
++ else
++ {
++ curwin->w_cursor.col = i;
++ retval = TRUE;
++ }
++ }
++ }
++ return retval;
++ }
++
++ /*
++ * Parse 'cinoptions' and set the values in "curbuf".
++ * Must be called when 'cinoptions', 'shiftwidth' and/or 'tabstop' changes.
++ */
++ void
++ parse_cino(buf_T *buf)
++ {
++ char_u *p;
++ char_u *l;
++ char_u *digits;
++ int n;
++ int divider;
++ int fraction = 0;
++ int sw = (int)get_sw_value(buf);
++
++ /*
++ * Set the default values.
++ */
++ /* Spaces from a block's opening brace the prevailing indent for that
++ * block should be. */
++ buf->b_ind_level = sw;
++
++ /* Spaces from the edge of the line an open brace that's at the end of a
++ * line is imagined to be. */
++ buf->b_ind_open_imag = 0;
++
++ /* Spaces from the prevailing indent for a line that is not preceded by
++ * an opening brace. */
++ buf->b_ind_no_brace = 0;
++
++ /* Column where the first { of a function should be located }. */
++ buf->b_ind_first_open = 0;
++
++ /* Spaces from the prevailing indent a leftmost open brace should be
++ * located. */
++ buf->b_ind_open_extra = 0;
++
++ /* Spaces from the matching open brace (real location for one at the left
++ * edge; imaginary location from one that ends a line) the matching close
++ * brace should be located. */
++ buf->b_ind_close_extra = 0;
++
++ /* Spaces from the edge of the line an open brace sitting in the leftmost
++ * column is imagined to be. */
++ buf->b_ind_open_left_imag = 0;
++
++ /* Spaces jump labels should be shifted to the left if N is non-negative,
++ * otherwise the jump label will be put to column 1. */
++ buf->b_ind_jump_label = -1;
++
++ /* Spaces from the switch() indent a "case xx" label should be located. */
++ buf->b_ind_case = sw;
++
++ /* Spaces from the "case xx:" code after a switch() should be located. */
++ buf->b_ind_case_code = sw;
++
++ /* Lineup break at end of case in switch() with case label. */
++ buf->b_ind_case_break = 0;
++
++ /* Spaces from the class declaration indent a scope declaration label
++ * should be located. */
++ buf->b_ind_scopedecl = sw;
++
++ /* Spaces from the scope declaration label code should be located. */
++ buf->b_ind_scopedecl_code = sw;
++
++ /* Amount K&R-style parameters should be indented. */
++ buf->b_ind_param = sw;
++
++ /* Amount a function type spec should be indented. */
++ buf->b_ind_func_type = sw;
++
++ /* Amount a cpp base class declaration or constructor initialization
++ * should be indented. */
++ buf->b_ind_cpp_baseclass = sw;
++
++ /* additional spaces beyond the prevailing indent a continuation line
++ * should be located. */
++ buf->b_ind_continuation = sw;
++
++ /* Spaces from the indent of the line with an unclosed parentheses. */
++ buf->b_ind_unclosed = sw * 2;
++
++ /* Spaces from the indent of the line with an unclosed parentheses, which
++ * itself is also unclosed. */
++ buf->b_ind_unclosed2 = sw;
++
++ /* Suppress ignoring spaces from the indent of a line starting with an
++ * unclosed parentheses. */
++ buf->b_ind_unclosed_noignore = 0;
++
++ /* If the opening paren is the last nonwhite character on the line, and
++ * b_ind_unclosed_wrapped is nonzero, use this indent relative to the outer
++ * context (for very long lines). */
++ buf->b_ind_unclosed_wrapped = 0;
++
++ /* Suppress ignoring white space when lining up with the character after
++ * an unclosed parentheses. */
++ buf->b_ind_unclosed_whiteok = 0;
++
++ /* Indent a closing parentheses under the line start of the matching
++ * opening parentheses. */
++ buf->b_ind_matching_paren = 0;
++
++ /* Indent a closing parentheses under the previous line. */
++ buf->b_ind_paren_prev = 0;
++
++ /* Extra indent for comments. */
++ buf->b_ind_comment = 0;
++
++ /* Spaces from the comment opener when there is nothing after it. */
++ buf->b_ind_in_comment = 3;
++
++ /* Boolean: if non-zero, use b_ind_in_comment even if there is something
++ * after the comment opener. */
++ buf->b_ind_in_comment2 = 0;
++
++ /* Max lines to search for an open paren. */
++ buf->b_ind_maxparen = 20;
++
++ /* Max lines to search for an open comment. */
++ buf->b_ind_maxcomment = 70;
++
++ /* Handle braces for java code. */
++ buf->b_ind_java = 0;
++
++ /* Not to confuse JS object properties with labels. */
++ buf->b_ind_js = 0;
++
++ /* Handle blocked cases correctly. */
++ buf->b_ind_keep_case_label = 0;
++
++ /* Handle C++ namespace. */
++ buf->b_ind_cpp_namespace = 0;
++
++ /* Handle continuation lines containing conditions of if(), for() and
++ * while(). */
++ buf->b_ind_if_for_while = 0;
++
++ /* indentation for # comments */
++ buf->b_ind_hash_comment = 0;
++
++ /* Handle C++ extern "C" or "C++" */
++ buf->b_ind_cpp_extern_c = 0;
++
++ for (p = buf->b_p_cino; *p; )
++ {
++ l = p++;
++ if (*p == '-')
++ ++p;
++ digits = p; /* remember where the digits start */
++ n = getdigits(&p);
++ divider = 0;
++ if (*p == '.') /* ".5s" means a fraction */
++ {
++ fraction = atol((char *)++p);
++ while (VIM_ISDIGIT(*p))
++ {
++ ++p;
++ if (divider)
++ divider *= 10;
++ else
++ divider = 10;
++ }
++ }
++ if (*p == 's') /* "2s" means two times 'shiftwidth' */
++ {
++ if (p == digits)
++ n = sw; /* just "s" is one 'shiftwidth' */
++ else
++ {
++ n *= sw;
++ if (divider)
++ n += (sw * fraction + divider / 2) / divider;
++ }
++ ++p;
++ }
++ if (l[1] == '-')
++ n = -n;
++
++ /* When adding an entry here, also update the default 'cinoptions' in
++ * doc/indent.txt, and add explanation for it! */
++ switch (*l)
++ {
++ case '>': buf->b_ind_level = n; break;
++ case 'e': buf->b_ind_open_imag = n; break;
++ case 'n': buf->b_ind_no_brace = n; break;
++ case 'f': buf->b_ind_first_open = n; break;
++ case '{': buf->b_ind_open_extra = n; break;
++ case '}': buf->b_ind_close_extra = n; break;
++ case '^': buf->b_ind_open_left_imag = n; break;
++ case 'L': buf->b_ind_jump_label = n; break;
++ case ':': buf->b_ind_case = n; break;
++ case '=': buf->b_ind_case_code = n; break;
++ case 'b': buf->b_ind_case_break = n; break;
++ case 'p': buf->b_ind_param = n; break;
++ case 't': buf->b_ind_func_type = n; break;
++ case '/': buf->b_ind_comment = n; break;
++ case 'c': buf->b_ind_in_comment = n; break;
++ case 'C': buf->b_ind_in_comment2 = n; break;
++ case 'i': buf->b_ind_cpp_baseclass = n; break;
++ case '+': buf->b_ind_continuation = n; break;
++ case '(': buf->b_ind_unclosed = n; break;
++ case 'u': buf->b_ind_unclosed2 = n; break;
++ case 'U': buf->b_ind_unclosed_noignore = n; break;
++ case 'W': buf->b_ind_unclosed_wrapped = n; break;
++ case 'w': buf->b_ind_unclosed_whiteok = n; break;
++ case 'm': buf->b_ind_matching_paren = n; break;
++ case 'M': buf->b_ind_paren_prev = n; break;
++ case ')': buf->b_ind_maxparen = n; break;
++ case '*': buf->b_ind_maxcomment = n; break;
++ case 'g': buf->b_ind_scopedecl = n; break;
++ case 'h': buf->b_ind_scopedecl_code = n; break;
++ case 'j': buf->b_ind_java = n; break;
++ case 'J': buf->b_ind_js = n; break;
++ case 'l': buf->b_ind_keep_case_label = n; break;
++ case '#': buf->b_ind_hash_comment = n; break;
++ case 'N': buf->b_ind_cpp_namespace = n; break;
++ case 'k': buf->b_ind_if_for_while = n; break;
++ case 'E': buf->b_ind_cpp_extern_c = n; break;
++ }
++ if (*p == ',')
++ ++p;
++ }
++ }
++
++ /*
++ * Return the desired indent for C code.
++ * Return -1 if the indent should be left alone (inside a raw string).
++ */
++ int
++ get_c_indent(void)
++ {
++ pos_T cur_curpos;
++ int amount;
++ int scope_amount;
++ int cur_amount = MAXCOL;
++ colnr_T col;
++ 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;
++ #define BRACE_IN_COL0 1 /* '{' is in column 0 */
++ #define BRACE_AT_START 2 /* '{' is at start of line */
++ #define BRACE_AT_END 3 /* '{' is at end of line */
++ linenr_T ourscope;
++ char_u *l;
++ char_u *look;
++ char_u terminated;
++ int lookfor;
++ #define LOOKFOR_INITIAL 0
++ #define LOOKFOR_IF 1
++ #define LOOKFOR_DO 2
++ #define LOOKFOR_CASE 3
++ #define LOOKFOR_ANY 4
++ #define LOOKFOR_TERM 5
++ #define LOOKFOR_UNTERM 6
++ #define LOOKFOR_SCOPEDECL 7
++ #define LOOKFOR_NOBREAK 8
++ #define LOOKFOR_CPP_BASECLASS 9
++ #define LOOKFOR_ENUM_OR_INIT 10
++ #define LOOKFOR_JS_KEY 11
++ #define LOOKFOR_COMMA 12
++
++ int whilelevel;
++ linenr_T lnum;
++ int n;
++ int iscase;
++ int lookfor_break;
++ int lookfor_cpp_namespace = FALSE;
++ int cont_amount = 0; /* amount for continuation line */
++ int original_line_islabel;
++ int added_to_amount = 0;
++ int js_cur_has_key = 0;
++ linenr_T raw_string_start = 0;
++ cpp_baseclass_cache_T cache_cpp_baseclass = { FALSE, { MAXLNUM, 0 } };
++
++ /* make a copy, value is changed below */
++ int ind_continuation = curbuf->b_ind_continuation;
++
++ /* 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;
++
++ /* Get a copy of the current contents of the line.
++ * This is required, because only the most recent line obtained with
++ * ml_get is valid! */
++ linecopy = vim_strsave(ml_get(cur_curpos.lnum));
++ if (linecopy == NULL)
++ return 0;
++
++ /*
++ * In insert mode and the cursor is on a ')' truncate the line at the
++ * cursor position. We don't want to line up with the matching '(' when
++ * inserting new stuff.
++ * For unknown reasons the cursor might be past the end of the line, thus
++ * check for that.
++ */
++ if ((State & INSERT)
++ && curwin->w_cursor.col < (colnr_T)STRLEN(linecopy)
++ && linecopy[curwin->w_cursor.col] == ')')
++ linecopy[curwin->w_cursor.col] = NUL;
++
++ theline = skipwhite(linecopy);
++
++ /* move the cursor to the start of the line */
++
++ curwin->w_cursor.col = 0;
++
++ 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_POS(*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;
++ char_u lead_start[COM_MAX_LEN]; /* start-comment string */
++ char_u lead_middle[COM_MAX_LEN]; /* middle-comment string */
++ char_u lead_end[COM_MAX_LEN]; /* end-comment string */
++ char_u *p;
++ int start_align = 0;
++ int start_off = 0;
++ 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;
++
++ p = curbuf->b_p_com;
++ while (*p != NUL)
++ {
++ int align = 0;
++ int off = 0;
++ int what = 0;
++
++ while (*p != NUL && *p != ':')
++ {
++ if (*p == COM_START || *p == COM_END || *p == COM_MIDDLE)
++ what = *p++;
++ else if (*p == COM_LEFT || *p == COM_RIGHT)
++ align = *p++;
++ else if (VIM_ISDIGIT(*p) || *p == '-')
++ off = getdigits(&p);
++ else
++ ++p;
++ }
++
++ if (*p == ':')
++ ++p;
++ (void)copy_option_part(&p, lead_end, COM_MAX_LEN, ",");
++ if (what == COM_START)
++ {
++ STRCPY(lead_start, lead_end);
++ lead_start_len = (int)STRLEN(lead_start);
++ start_off = off;
++ start_align = align;
++ }
++ else if (what == COM_MIDDLE)
++ {
++ STRCPY(lead_middle, lead_end);
++ lead_middle_len = (int)STRLEN(lead_middle);
++ }
++ else if (what == COM_END)
++ {
++ /* If our line starts with the middle comment string, line it
++ * up with the comment opener per the 'comments' option. */
++ if (STRNCMP(theline, lead_middle, lead_middle_len) == 0
++ && STRNCMP(theline, lead_end, STRLEN(lead_end)) != 0)
++ {
++ done = TRUE;
++ if (curwin->w_cursor.lnum > 1)
++ {
++ /* If the start comment string matches in the previous
++ * line, use the indent of that line plus offset. If
++ * the middle comment string matches in the previous
++ * line, use the indent of that line. XXX */
++ look = skipwhite(ml_get(curwin->w_cursor.lnum - 1));
++ if (STRNCMP(look, lead_start, lead_start_len) == 0)
++ amount = get_indent_lnum(curwin->w_cursor.lnum - 1);
++ else if (STRNCMP(look, lead_middle,
++ lead_middle_len) == 0)
++ {
++ amount = get_indent_lnum(curwin->w_cursor.lnum - 1);
++ break;
++ }
++ /* 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;
++ }
++ if (start_off != 0)
++ amount += start_off;
++ else if (start_align == COM_RIGHT)
++ amount += vim_strsize(lead_start)
++ - vim_strsize(lead_middle);
++ break;
++ }
++
++ /* If our line starts with the end comment string, line it up
++ * with the middle comment */
++ if (STRNCMP(theline, lead_middle, lead_middle_len) != 0
++ && STRNCMP(theline, lead_end, STRLEN(lead_end)) == 0)
++ {
++ amount = get_indent_lnum(curwin->w_cursor.lnum - 1);
++ /* XXX */
++ if (off != 0)
++ amount += off;
++ else if (align == COM_RIGHT)
++ amount += vim_strsize(lead_start)
++ - vim_strsize(lead_middle);
++ done = TRUE;
++ break;
++ }
++ }
++ }
++
++ /* If our line starts with an asterisk, line up with the
++ * asterisk in the comment opener; otherwise, line up
++ * with the first character of the comment text.
++ */
++ if (done)
++ ;
++ else if (theline[0] == '*')
++ amount += 1;
++ else
++ {
++ /*
++ * If we are more than one line away from the comment opener, take
++ * the indent of the previous non-empty line. If 'cino' has "CO"
++ * and we are just below the comment opener and there are any
++ * white characters after it line up with the text after it;
++ * 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;
++ amount = get_indent_lnum(lnum); /* XXX */
++ break;
++ }
++ if (amount == -1) /* use the comment opener */
++ {
++ 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)
++ {
++ if (trypos != NULL && tryposBrace != NULL)
++ {
++ /* Both an unmatched '(' and '{' is found. Use the one which is
++ * closer to the current cursor position, set the other to NULL. */
++ if (trypos->lnum != tryposBrace->lnum
++ ? trypos->lnum < tryposBrace->lnum
++ : trypos->col < tryposBrace->col)
++ trypos = NULL;
++ else
++ tryposBrace = NULL;
++ }
++
++ if (trypos != NULL)
++ {
++ /*
++ * If the matching paren is more than one line away, use the indent of
++ * a previous non-empty line that matches the same paren.
++ */
++ if (theline[0] == ')' && curbuf->b_ind_paren_prev)
++ {
++ /* Line up with the start of the matching paren line. */
++ amount = get_indent_lnum(curwin->w_cursor.lnum - 1); /* XXX */
++ }
++ else
++ {
++ amount = -1;
++ our_paren_pos = *trypos;
++ for (lnum = cur_curpos.lnum - 1; lnum > our_paren_pos.lnum; --lnum)
++ {
++ l = skipwhite(ml_get(lnum));
++ if (cin_nocode(l)) /* skip comment lines */
++ continue;
++ if (cin_ispreproc_cont(&l, &lnum, &amount))
++ continue; /* ignore #define, #if, etc. */
++ curwin->w_cursor.lnum = lnum;
++
++ /* Skip a comment or raw string. XXX */
++ if ((trypos = ind_find_start_CORS(NULL)) != NULL)
++ {
++ lnum = trypos->lnum + 1;
++ continue;
++ }
++
++ /* XXX */
++ if ((trypos = find_match_paren(
++ corr_ind_maxparen(&cur_curpos))) != NULL
++ && trypos->lnum == our_paren_pos.lnum
++ && trypos->col == our_paren_pos.col)
++ {
++ amount = get_indent_lnum(lnum); /* XXX */
++
++ if (theline[0] == ')')
++ {
++ if (our_paren_pos.lnum != lnum
++ && cur_amount > amount)
++ cur_amount = amount;
++ amount = -1;
++ }
++ break;
++ }
++ }
++ }
++
++ /*
++ * Line up with line where the matching paren is. XXX
++ * If the line starts with a '(' or the indent for unclosed
++ * parentheses is zero, line up with the unclosed parentheses.
++ */
++ if (amount == -1)
++ {
++ int ignore_paren_col = 0;
++ int is_if_for_while = 0;
++
++ if (curbuf->b_ind_if_for_while)
++ {
++ /* Look for the outermost opening parenthesis on this line
++ * and check whether it belongs to an "if", "for" or "while". */
++
++ pos_T cursor_save = curwin->w_cursor;
++ pos_T outermost;
++ char_u *line;
++
++ trypos = &our_paren_pos;
++ do {
++ outermost = *trypos;
++ curwin->w_cursor.lnum = outermost.lnum;
++ curwin->w_cursor.col = outermost.col;
++
++ trypos = find_match_paren(curbuf->b_ind_maxparen);
++ } while (trypos && trypos->lnum == outermost.lnum);
++
++ curwin->w_cursor = cursor_save;
++
++ line = ml_get(outermost.lnum);
++
++ is_if_for_while =
++ cin_is_if_for_while_before_offset(line, &outermost.col);
++ }
++
++ amount = skip_label(our_paren_pos.lnum, &look);
++ look = skipwhite(look);
++ if (*look == '(')
++ {
++ linenr_T save_lnum = curwin->w_cursor.lnum;
++ char_u *line;
++ int look_col;
++
++ /* Ignore a '(' in front of the line that has a match before
++ * our matching '('. */
++ curwin->w_cursor.lnum = our_paren_pos.lnum;
++ line = ml_get_curline();
++ look_col = (int)(look - line);
++ curwin->w_cursor.col = look_col + 1;
++ if ((trypos = findmatchlimit(NULL, ')', 0,
++ curbuf->b_ind_maxparen))
++ != NULL
++ && trypos->lnum == our_paren_pos.lnum
++ && trypos->col < our_paren_pos.col)
++ ignore_paren_col = trypos->col + 1;
++
++ curwin->w_cursor.lnum = save_lnum;
++ look = ml_get(our_paren_pos.lnum) + look_col;
++ }
++ if (theline[0] == ')' || (curbuf->b_ind_unclosed == 0
++ && is_if_for_while == 0)
++ || (!curbuf->b_ind_unclosed_noignore && *look == '('
++ && ignore_paren_col == 0))
++ {
++ /*
++ * If we're looking at a close paren, line up right there;
++ * otherwise, line up with the next (non-white) character.
++ * When b_ind_unclosed_wrapped is set and the matching paren is
++ * the last nonwhite character of the line, use either the
++ * indent of the current line or the indentation of the next
++ * outer paren and add b_ind_unclosed_wrapped (for very long
++ * lines).
++ */
++ if (theline[0] != ')')
++ {
++ cur_amount = MAXCOL;
++ l = ml_get(our_paren_pos.lnum);
++ if (curbuf->b_ind_unclosed_wrapped
++ && cin_ends_in(l, (char_u *)"(", NULL))
++ {
++ /* look for opening unmatched paren, indent one level
++ * for each additional level */
++ n = 1;
++ for (col = 0; col < our_paren_pos.col; ++col)
++ {
++ switch (l[col])
++ {
++ case '(':
++ case '{': ++n;
++ break;
++
++ case ')':
++ case '}': if (n > 1)
++ --n;
++ break;
++ }
++ }
++
++ our_paren_pos.col = 0;
++ amount += n * curbuf->b_ind_unclosed_wrapped;
++ }
++ else if (curbuf->b_ind_unclosed_whiteok)
++ our_paren_pos.col++;
++ else
++ {
++ col = our_paren_pos.col + 1;
++ while (VIM_ISWHITE(l[col]))
++ col++;
++ if (l[col] != NUL) /* In case of trailing space */
++ our_paren_pos.col = col;
++ else
++ our_paren_pos.col++;
++ }
++ }
++
++ /*
++ * Find how indented the paren is, or the character after it
++ * if we did the above "if".
++ */
++ if (our_paren_pos.col > 0)
++ {
++ getvcol(curwin, &our_paren_pos, &col, NULL, NULL);
++ if (cur_amount > (int)col)
++ cur_amount = col;
++ }
++ }
++
++ if (theline[0] == ')' && curbuf->b_ind_matching_paren)
++ {
++ /* Line up with the start of the matching paren line. */
++ }
++ else if ((curbuf->b_ind_unclosed == 0 && is_if_for_while == 0)
++ || (!curbuf->b_ind_unclosed_noignore
++ && *look == '(' && ignore_paren_col == 0))
++ {
++ if (cur_amount != MAXCOL)
++ amount = cur_amount;
++ }
++ else
++ {
++ /* Add b_ind_unclosed2 for each '(' before our matching one,
++ * but ignore (void) before the line (ignore_paren_col). */
++ col = our_paren_pos.col;
++ while ((int)our_paren_pos.col > ignore_paren_col)
++ {
++ --our_paren_pos.col;
++ switch (*ml_get_pos(&our_paren_pos))
++ {
++ case '(': amount += curbuf->b_ind_unclosed2;
++ col = our_paren_pos.col;
++ break;
++ case ')': amount -= curbuf->b_ind_unclosed2;
++ col = MAXCOL;
++ break;
++ }
++ }
++
++ /* Use b_ind_unclosed once, when the first '(' is not inside
++ * braces */
++ if (col == MAXCOL)
++ amount += curbuf->b_ind_unclosed;
++ else
++ {
++ curwin->w_cursor.lnum = our_paren_pos.lnum;
++ curwin->w_cursor.col = col;
++ if (find_match_paren_after_brace(curbuf->b_ind_maxparen)
++ != NULL)
++ amount += curbuf->b_ind_unclosed2;
++ else
++ {
++ if (is_if_for_while)
++ amount += curbuf->b_ind_if_for_while;
++ else
++ amount += curbuf->b_ind_unclosed;
++ }
++ }
++ /*
++ * For a line starting with ')' use the minimum of the two
++ * positions, to avoid giving it more indent than the previous
++ * lines:
++ * func_long_name( if (x
++ * arg && yy
++ * ) ^ not here ) ^ not here
++ */
++ if (cur_amount < amount)
++ amount = cur_amount;
++ }
++ }
++
++ /* add extra indent for a comment */
++ if (cin_iscomment(theline))
++ amount += curbuf->b_ind_comment;
++ }
++ else
++ {
++ /*
++ * We are inside braces, there is a { before this line at the position
++ * stored in tryposBrace.
++ * 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);
++
++ /*
++ * Now figure out how indented the line is in general.
++ * If the brace was at the start of the line, we use that;
++ * otherwise, check out the indentation of the line as
++ * a whole and then add the "imaginary indent" to that.
++ */
++ look = skipwhite(start);
++ if (*look == '{')
++ {
++ getvcol(curwin, trypos, &col, NULL, NULL);
++ amount = col;
++ if (*start == '{')
++ start_brace = BRACE_IN_COL0;
++ else
++ start_brace = BRACE_AT_START;
++ }
++ else
++ {
++ /* That opening brace might have been on a continuation
++ * line. if so, find the start of the line. */
++ curwin->w_cursor.lnum = ourscope;
++
++ /* Position the cursor over the rightmost paren, so that
++ * matching it will take us back to the start of the line. */
++ lnum = ourscope;
++ if (find_last_paren(start, '(', ')')
++ && (trypos = find_match_paren(curbuf->b_ind_maxparen))
++ != NULL)
++ lnum = trypos->lnum;
++
++ /* It could have been something like
++ * case 1: if (asdf &&
++ * ldfd) {
++ * }
++ */
++ if ((curbuf->b_ind_js || curbuf->b_ind_keep_case_label)
++ && cin_iscase(skipwhite(ml_get_curline()), FALSE))
++ amount = get_indent();
++ else if (curbuf->b_ind_js)
++ amount = get_indent_lnum(lnum);
++ else
++ amount = skip_label(lnum, &l);
++
++ start_brace = BRACE_AT_END;
++ }
++
++ /* For Javascript check if the line starts with "key:". */
++ if (curbuf->b_ind_js)
++ js_cur_has_key = cin_has_js_key(theline);
++
++ /*
++ * If we're looking at a closing brace, that's where
++ * we want to be. otherwise, add the amount of room
++ * that an indent is supposed to be.
++ */
++ if (theline[0] == '}')
++ {
++ /*
++ * they may want closing braces to line up with something
++ * other than the open brace. indulge them, if so.
++ */
++ amount += curbuf->b_ind_close_extra;
++ }
++ else
++ {
++ /*
++ * If we're looking at an "else", try to find an "if"
++ * to match it with.
++ * If we're looking at a "while", try to find a "do"
++ * to match it with.
++ */
++ lookfor = LOOKFOR_INITIAL;
++ if (cin_iselse(theline))
++ lookfor = LOOKFOR_IF;
++ else if (cin_iswhileofdo(theline, cur_curpos.lnum)) /* XXX */
++ lookfor = LOOKFOR_DO;
++ if (lookfor != LOOKFOR_INITIAL)
++ {
++ curwin->w_cursor.lnum = cur_curpos.lnum;
++ if (find_match(lookfor, ourscope) == OK)
++ {
++ amount = get_indent(); /* XXX */
++ goto theend;
++ }
++ }
++
++ /*
++ * We get here if we are not on an "while-of-do" or "else" (or
++ * failed to find a matching "if").
++ * Search backwards for something to line up with.
++ * First set amount for when we don't find anything.
++ */
++
++ /*
++ * if the '{' is _really_ at the left margin, use the imaginary
++ * location of a left-margin brace. Otherwise, correct the
++ * location for b_ind_open_extra.
++ */
++
++ if (start_brace == BRACE_IN_COL0) /* '{' is in column 0 */
++ {
++ amount = curbuf->b_ind_open_left_imag;
++ lookfor_cpp_namespace = TRUE;
++ }
++ else if (start_brace == BRACE_AT_START &&
++ lookfor_cpp_namespace) /* '{' is at start */
++ {
++
++ lookfor_cpp_namespace = TRUE;
++ }
++ else
++ {
++ if (start_brace == BRACE_AT_END) /* '{' is at end of line */
++ {
++ amount += curbuf->b_ind_open_imag;
++
++ l = skipwhite(ml_get_curline());
++ if (cin_is_cpp_namespace(l))
++ amount += curbuf->b_ind_cpp_namespace;
++ else if (cin_is_cpp_extern_c(l))
++ amount += curbuf->b_ind_cpp_extern_c;
++ }
++ else
++ {
++ /* Compensate for adding b_ind_open_extra later. */
++ amount -= curbuf->b_ind_open_extra;
++ if (amount < 0)
++ amount = 0;
++ }
++ }
++
++ lookfor_break = FALSE;
++
++ if (cin_iscase(theline, FALSE)) /* it's a switch() label */
++ {
++ lookfor = LOOKFOR_CASE; /* find a previous switch() label */
++ amount += curbuf->b_ind_case;
++ }
++ else if (cin_isscopedecl(theline)) /* private:, ... */
++ {
++ lookfor = LOOKFOR_SCOPEDECL; /* class decl is this block */
++ amount += curbuf->b_ind_scopedecl;
++ }
++ else
++ {
++ if (curbuf->b_ind_case_break && cin_isbreak(theline))
++ /* break; ... */
++ lookfor_break = TRUE;
++
++ lookfor = LOOKFOR_INITIAL;
++ /* b_ind_level from start of block */
++ amount += curbuf->b_ind_level;
++ }
++ scope_amount = amount;
++ whilelevel = 0;
++
++ /*
++ * Search backwards. If we find something we recognize, line up
++ * with that.
++ *
++ * If we're looking at an open brace, indent
++ * the usual amount relative to the conditional
++ * that opens the block.
++ */
++ curwin->w_cursor = cur_curpos;
++ for (;;)
++ {
++ curwin->w_cursor.lnum--;
++ curwin->w_cursor.col = 0;
++
++ /*
++ * If we went all the way back to the start of our scope, line
++ * up with it.
++ */
++ if (curwin->w_cursor.lnum <= ourscope)
++ {
++ /* We reached end of scope:
++ * If looking for a enum or structure initialization
++ * go further back:
++ * If it is an initializer (enum xxx or xxx =), then
++ * don't add ind_continuation, otherwise it is a variable
++ * declaration:
++ * int x,
++ * here; <-- add ind_continuation
++ */
++ if (lookfor == LOOKFOR_ENUM_OR_INIT)
++ {
++ if (curwin->w_cursor.lnum == 0
++ || curwin->w_cursor.lnum
++ < ourscope - curbuf->b_ind_maxparen)
++ {
++ /* nothing found (abuse curbuf->b_ind_maxparen as
++ * limit) assume terminated line (i.e. a variable
++ * initialization) */
++ if (cont_amount > 0)
++ amount = cont_amount;
++ else if (!curbuf->b_ind_js)
++ amount += ind_continuation;
++ break;
++ }
++
++ 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(NULL);
++ if (trypos != NULL)
++ {
++ curwin->w_cursor.lnum = trypos->lnum + 1;
++ curwin->w_cursor.col = 0;
++ continue;
++ }
++
++ /*
++ * Skip preprocessor directives and blank lines.
++ */
++ if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum,
++ &amount))
++ continue;
++
++ if (cin_nocode(l))
++ continue;
++
++ terminated = cin_isterminated(l, FALSE, TRUE);
++
++ /*
++ * If we are at top level and the line looks like a
++ * function declaration, we are done
++ * (it's a variable declaration).
++ */
++ if (start_brace != BRACE_IN_COL0
++ || !cin_isfuncdecl(&l, curwin->w_cursor.lnum, 0))
++ {
++ /* if the line is terminated with another ','
++ * it is a continued variable initialization.
++ * don't add extra indent.
++ * TODO: does not work, if a function
++ * declaration is split over multiple lines:
++ * cin_isfuncdecl returns FALSE then.
++ */
++ if (terminated == ',')
++ break;
++
++ /* if it es a enum declaration or an assignment,
++ * we are done.
++ */
++ if (terminated != ';' && cin_isinit())
++ break;
++
++ /* nothing useful found */
++ if (terminated == 0 || terminated == '{')
++ continue;
++ }
++
++ if (terminated != ';')
++ {
++ /* Skip parens and braces. Position the cursor
++ * over the rightmost paren, so that matching it
++ * will take us back to the start of the line.
++ */ /* XXX */
++ trypos = NULL;
++ if (find_last_paren(l, '(', ')'))
++ trypos = find_match_paren(
++ curbuf->b_ind_maxparen);
++
++ if (trypos == NULL && find_last_paren(l, '{', '}'))
++ trypos = find_start_brace();
++
++ if (trypos != NULL)
++ {
++ curwin->w_cursor.lnum = trypos->lnum + 1;
++ curwin->w_cursor.col = 0;
++ continue;
++ }
++ }
++
++ /* it's a variable declaration, add indentation
++ * like in
++ * int a,
++ * b;
++ */
++ if (cont_amount > 0)
++ amount = cont_amount;
++ else
++ amount += ind_continuation;
++ }
++ else if (lookfor == LOOKFOR_UNTERM)
++ {
++ if (cont_amount > 0)
++ amount = cont_amount;
++ else
++ amount += ind_continuation;
++ }
++ else
++ {
++ if (lookfor != LOOKFOR_TERM
++ && lookfor != LOOKFOR_CPP_BASECLASS
++ && lookfor != LOOKFOR_COMMA)
++ {
++ amount = scope_amount;
++ if (theline[0] == '{')
++ {
++ amount += curbuf->b_ind_open_extra;
++ added_to_amount = curbuf->b_ind_open_extra;
++ }
++ }
++
++ if (lookfor_cpp_namespace)
++ {
++ /*
++ * Looking for C++ namespace, need to look further
++ * back.
++ */
++ if (curwin->w_cursor.lnum == ourscope)
++ continue;
++
++ if (curwin->w_cursor.lnum == 0
++ || curwin->w_cursor.lnum
++ < ourscope - FIND_NAMESPACE_LIM)
++ break;
++
++ 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(NULL);
++ if (trypos != NULL)
++ {
++ curwin->w_cursor.lnum = trypos->lnum + 1;
++ curwin->w_cursor.col = 0;
++ continue;
++ }
++
++ /* Skip preprocessor directives and blank lines. */
++ if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum,
++ &amount))
++ continue;
++
++ /* Finally the actual check for "namespace". */
++ if (cin_is_cpp_namespace(l))
++ {
++ amount += curbuf->b_ind_cpp_namespace
++ - added_to_amount;
++ break;
++ }
++ else if (cin_is_cpp_extern_c(l))
++ {
++ amount += curbuf->b_ind_cpp_extern_c
++ - added_to_amount;
++ break;
++ }
++
++ if (cin_nocode(l))
++ continue;
++ }
++ }
++ break;
++ }
++
++ /*
++ * If we're in a comment or raw string now, skip to the start
++ * of it.
++ */ /* XXX */
++ if ((trypos = ind_find_start_CORS(&raw_string_start)) != NULL)
++ {
++ curwin->w_cursor.lnum = trypos->lnum + 1;
++ curwin->w_cursor.col = 0;
++ continue;
++ }
++
++ l = ml_get_curline();
++
++ /*
++ * If this is a switch() label, may line up relative to that.
++ * If this is a C++ scope declaration, do the same.
++ */
++ iscase = cin_iscase(l, FALSE);
++ if (iscase || cin_isscopedecl(l))
++ {
++ /* we are only looking for cpp base class
++ * declaration/initialization any longer */
++ if (lookfor == LOOKFOR_CPP_BASECLASS)
++ break;
++
++ /* When looking for a "do" we are not interested in
++ * labels. */
++ if (whilelevel > 0)
++ continue;
++
++ /*
++ * case xx:
++ * c = 99 + <- this indent plus continuation
++ *-> here;
++ */
++ if (lookfor == LOOKFOR_UNTERM
++ || lookfor == LOOKFOR_ENUM_OR_INIT)
++ {
++ if (cont_amount > 0)
++ amount = cont_amount;
++ else
++ amount += ind_continuation;
++ break;
++ }
++
++ /*
++ * case xx: <- line up with this case
++ * x = 333;
++ * case yy:
++ */
++ if ( (iscase && lookfor == LOOKFOR_CASE)
++ || (iscase && lookfor_break)
++ || (!iscase && lookfor == LOOKFOR_SCOPEDECL))
++ {
++ /*
++ * Check that this case label is not for another
++ * switch()
++ */ /* XXX */
++ if ((trypos = find_start_brace()) == NULL
++ || trypos->lnum == ourscope)
++ {
++ amount = get_indent(); /* XXX */
++ break;
++ }
++ continue;
++ }
++
++ n = get_indent_nolabel(curwin->w_cursor.lnum); /* XXX */
++
++ /*
++ * case xx: if (cond) <- line up with this if
++ * y = y + 1;
++ * -> s = 99;
++ *
++ * case xx:
++ * if (cond) <- line up with this line
++ * y = y + 1;
++ * -> s = 99;
++ */
++ if (lookfor == LOOKFOR_TERM)
++ {
++ if (n)
++ amount = n;
++
++ if (!lookfor_break)
++ break;
++ }
++
++ /*
++ * case xx: x = x + 1; <- line up with this x
++ * -> y = y + 1;
++ *
++ * case xx: if (cond) <- line up with this if
++ * -> y = y + 1;
++ */
++ if (n)
++ {
++ amount = n;
++ l = after_label(ml_get_curline());
++ if (l != NULL && cin_is_cinword(l))
++ {
++ if (theline[0] == '{')
++ amount += curbuf->b_ind_open_extra;
++ else
++ amount += curbuf->b_ind_level
++ + curbuf->b_ind_no_brace;
++ }
++ break;
++ }
++
++ /*
++ * Try to get the indent of a statement before the switch
++ * label. If nothing is found, line up relative to the
++ * switch label.
++ * break; <- may line up with this line
++ * case xx:
++ * -> y = 1;
++ */
++ scope_amount = get_indent() + (iscase /* XXX */
++ ? curbuf->b_ind_case_code
++ : curbuf->b_ind_scopedecl_code);
++ lookfor = curbuf->b_ind_case_break
++ ? LOOKFOR_NOBREAK : LOOKFOR_ANY;
++ continue;
++ }
++
++ /*
++ * Looking for a switch() label or C++ scope declaration,
++ * ignore other lines, skip {}-blocks.
++ */
++ if (lookfor == LOOKFOR_CASE || lookfor == LOOKFOR_SCOPEDECL)
++ {
++ if (find_last_paren(l, '{', '}')
++ && (trypos = find_start_brace()) != NULL)
++ {
++ curwin->w_cursor.lnum = trypos->lnum + 1;
++ curwin->w_cursor.col = 0;
++ }
++ continue;
++ }
++
++ /*
++ * Ignore jump labels with nothing after them.
++ */
++ if (!curbuf->b_ind_js && cin_islabel())
++ {
++ l = after_label(ml_get_curline());
++ if (l == NULL || cin_nocode(l))
++ continue;
++ }
++
++ /*
++ * Ignore #defines, #if, etc.
++ * Ignore comment and empty lines.
++ * (need to get the line again, cin_islabel() may have
++ * unlocked it)
++ */
++ l = ml_get_curline();
++ if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum, &amount)
++ || cin_nocode(l))
++ continue;
++
++ /*
++ * Are we at the start of a cpp base class declaration or
++ * constructor initialization?
++ */ /* XXX */
++ n = FALSE;
++ if (lookfor != LOOKFOR_TERM && curbuf->b_ind_cpp_baseclass > 0)
++ {
++ n = cin_is_cpp_baseclass(&cache_cpp_baseclass);
++ l = ml_get_curline();
++ }
++ if (n)
++ {
++ if (lookfor == LOOKFOR_UNTERM)
++ {
++ if (cont_amount > 0)
++ amount = cont_amount;
++ else
++ amount += ind_continuation;
++ }
++ else if (theline[0] == '{')
++ {
++ /* Need to find start of the declaration. */
++ lookfor = LOOKFOR_UNTERM;
++ ind_continuation = 0;
++ continue;
++ }
++ else
++ /* XXX */
++ amount = get_baseclass_amount(
++ cache_cpp_baseclass.lpos.col);
++ break;
++ }
++ else if (lookfor == LOOKFOR_CPP_BASECLASS)
++ {
++ /* only look, whether there is a cpp base class
++ * declaration or initialization before the opening brace.
++ */
++ if (cin_isterminated(l, TRUE, FALSE))
++ break;
++ else
++ continue;
++ }
++
++ /*
++ * What happens next depends on the line being terminated.
++ * If terminated with a ',' only consider it terminating if
++ * there is another unterminated statement behind, eg:
++ * 123,
++ * sizeof
++ * here
++ * Otherwise check whether it is a enumeration or structure
++ * initialisation (not indented) or a variable declaration
++ * (indented).
++ */
++ terminated = cin_isterminated(l, FALSE, TRUE);
++
++ if (js_cur_has_key)
++ {
++ js_cur_has_key = 0; /* only check the first line */
++ if (curbuf->b_ind_js && terminated == ',')
++ {
++ /* For Javascript we might be inside an object:
++ * key: something, <- align with this
++ * key: something
++ * or:
++ * key: something + <- align with this
++ * something,
++ * key: something
++ */
++ lookfor = LOOKFOR_JS_KEY;
++ }
++ }
++ if (lookfor == LOOKFOR_JS_KEY && cin_has_js_key(l))
++ {
++ amount = get_indent();
++ break;
++ }
++ if (lookfor == LOOKFOR_COMMA)
++ {
++ if (tryposBrace != NULL && tryposBrace->lnum
++ >= curwin->w_cursor.lnum)
++ break;
++ if (terminated == ',')
++ /* line below current line is the one that starts a
++ * (possibly broken) line ending in a comma. */
++ break;
++ else
++ {
++ amount = get_indent();
++ if (curwin->w_cursor.lnum - 1 == ourscope)
++ /* line above is start of the scope, thus current
++ * line is the one that stars a (possibly broken)
++ * line ending in a comma. */
++ break;
++ }
++ }
++
++ if (terminated == 0 || (lookfor != LOOKFOR_UNTERM
++ && terminated == ','))
++ {
++ if (lookfor != LOOKFOR_ENUM_OR_INIT &&
++ (*skipwhite(l) == '[' || l[STRLEN(l) - 1] == '['))
++ amount += ind_continuation;
++ /*
++ * if we're in the middle of a paren thing,
++ * go back to the line that starts it so
++ * we can get the right prevailing indent
++ * if ( foo &&
++ * bar )
++ */
++ /*
++ * Position the cursor over the rightmost paren, so that
++ * matching it will take us back to the start of the line.
++ * Ignore a match before the start of the block.
++ */
++ (void)find_last_paren(l, '(', ')');
++ trypos = find_match_paren(corr_ind_maxparen(&cur_curpos));
++ if (trypos != NULL && (trypos->lnum < tryposBrace->lnum
++ || (trypos->lnum == tryposBrace->lnum
++ && trypos->col < tryposBrace->col)))
++ trypos = NULL;
++
++ /*
++ * If we are looking for ',', we also look for matching
++ * braces.
++ */
++ if (trypos == NULL && terminated == ','
++ && find_last_paren(l, '{', '}'))
++ trypos = find_start_brace();
++
++ if (trypos != NULL)
++ {
++ /*
++ * Check if we are on a case label now. This is
++ * handled above.
++ * case xx: if ( asdf &&
++ * asdf)
++ */
++ curwin->w_cursor = *trypos;
++ l = ml_get_curline();
++ if (cin_iscase(l, FALSE) || cin_isscopedecl(l))
++ {
++ ++curwin->w_cursor.lnum;
++ curwin->w_cursor.col = 0;
++ continue;
++ }
++ }
++
++ /*
++ * Skip over continuation lines to find the one to get the
++ * indent from
++ * char *usethis = "bla\
++ * bla",
++ * here;
++ */
++ if (terminated == ',')
++ {
++ while (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;
++ }
++ }
++
++ /*
++ * Get indent and pointer to text for current line,
++ * ignoring any jump label. XXX
++ */
++ if (curbuf->b_ind_js)
++ cur_amount = get_indent();
++ else
++ cur_amount = skip_label(curwin->w_cursor.lnum, &l);
++ /*
++ * If this is just above the line we are indenting, and it
++ * starts with a '{', line it up with this line.
++ * while (not)
++ * -> {
++ * }
++ */
++ if (terminated != ',' && lookfor != LOOKFOR_TERM
++ && theline[0] == '{')
++ {
++ amount = cur_amount;
++ /*
++ * Only add b_ind_open_extra when the current line
++ * doesn't start with a '{', which must have a match
++ * in the same line (scope is the same). Probably:
++ * { 1, 2 },
++ * -> { 3, 4 }
++ */
++ if (*skipwhite(l) != '{')
++ amount += curbuf->b_ind_open_extra;
++
++ if (curbuf->b_ind_cpp_baseclass && !curbuf->b_ind_js)
++ {
++ /* have to look back, whether it is a cpp base
++ * class declaration or initialization */
++ lookfor = LOOKFOR_CPP_BASECLASS;
++ continue;
++ }
++ break;
++ }
++
++ /*
++ * Check if we are after an "if", "while", etc.
++ * Also allow " } else".
++ */
++ if (cin_is_cinword(l) || cin_iselse(skipwhite(l)))
++ {
++ /*
++ * Found an unterminated line after an if (), line up
++ * with the last one.
++ * if (cond)
++ * 100 +
++ * -> here;
++ */
++ if (lookfor == LOOKFOR_UNTERM
++ || lookfor == LOOKFOR_ENUM_OR_INIT)
++ {
++ if (cont_amount > 0)
++ amount = cont_amount;
++ else
++ amount += ind_continuation;
++ break;
++ }
++
++ /*
++ * If this is just above the line we are indenting, we
++ * are finished.
++ * while (not)
++ * -> here;
++ * Otherwise this indent can be used when the line
++ * before this is terminated.
++ * yyy;
++ * if (stat)
++ * while (not)
++ * xxx;
++ * -> here;
++ */
++ amount = cur_amount;
++ if (theline[0] == '{')
++ amount += curbuf->b_ind_open_extra;
++ if (lookfor != LOOKFOR_TERM)
++ {
++ amount += curbuf->b_ind_level
++ + curbuf->b_ind_no_brace;
++ break;
++ }
++
++ /*
++ * Special trick: when expecting the while () after a
++ * do, line up with the while()
++ * do
++ * x = 1;
++ * -> here
++ */
++ l = skipwhite(ml_get_curline());
++ if (cin_isdo(l))
++ {
++ if (whilelevel == 0)
++ break;
++ --whilelevel;
++ }
++
++ /*
++ * When searching for a terminated line, don't use the
++ * one between the "if" and the matching "else".
++ * Need to use the scope of this "else". XXX
++ * If whilelevel != 0 continue looking for a "do {".
++ */
++ if (cin_iselse(l) && whilelevel == 0)
++ {
++ /* If we're looking at "} else", let's make sure we
++ * find the opening brace of the enclosing scope,
++ * not the one from "if () {". */
++ if (*l == '}')
++ curwin->w_cursor.col =
++ (colnr_T)(l - ml_get_curline()) + 1;
++
++ if ((trypos = find_start_brace()) == NULL
++ || find_match(LOOKFOR_IF, trypos->lnum)
++ == FAIL)
++ break;
++ }
++ }
++
++ /*
++ * If we're below an unterminated line that is not an
++ * "if" or something, we may line up with this line or
++ * add something for a continuation line, depending on
++ * the line before this one.
++ */
++ else
++ {
++ /*
++ * Found two unterminated lines on a row, line up with
++ * the last one.
++ * c = 99 +
++ * 100 +
++ * -> here;
++ */
++ if (lookfor == LOOKFOR_UNTERM)
++ {
++ /* When line ends in a comma add extra indent */
++ if (terminated == ',')
++ amount += ind_continuation;
++ break;
++ }
++
++ if (lookfor == LOOKFOR_ENUM_OR_INIT)
++ {
++ /* Found two lines ending in ',', lineup with the
++ * lowest one, but check for cpp base class
++ * declaration/initialization, if it is an
++ * opening brace or we are looking just for
++ * enumerations/initializations. */
++ if (terminated == ',')
++ {
++ if (curbuf->b_ind_cpp_baseclass == 0)
++ break;
++
++ lookfor = LOOKFOR_CPP_BASECLASS;
++ continue;
++ }
++
++ /* Ignore unterminated lines in between, but
++ * reduce indent. */
++ if (amount > cur_amount)
++ amount = cur_amount;
++ }
++ else
++ {
++ /*
++ * Found first unterminated line on a row, may
++ * line up with this line, remember its indent
++ * 100 +
++ * -> here;
++ */
++ l = ml_get_curline();
++ amount = cur_amount;
++
++ n = (int)STRLEN(l);
++ if (terminated == ',' && (*skipwhite(l) == ']'
++ || (n >=2 && l[n - 2] == ']')))
++ break;
++
++ /*
++ * If previous line ends in ',', check whether we
++ * are in an initialization or enum
++ * struct xxx =
++ * {
++ * sizeof a,
++ * 124 };
++ * or a normal possible continuation line.
++ * but only, of no other statement has been found
++ * yet.
++ */
++ if (lookfor == LOOKFOR_INITIAL && terminated == ',')
++ {
++ if (curbuf->b_ind_js)
++ {
++ /* Search for a line ending in a comma
++ * and line up with the line below it
++ * (could be the current line).
++ * some = [
++ * 1, <- line up here
++ * 2,
++ * some = [
++ * 3 + <- line up here
++ * 4 *
++ * 5,
++ * 6,
++ */
++ if (cin_iscomment(skipwhite(l)))
++ break;
++ lookfor = LOOKFOR_COMMA;
++ trypos = find_match_char('[',
++ curbuf->b_ind_maxparen);
++ if (trypos != NULL)
++ {
++ if (trypos->lnum
++ == curwin->w_cursor.lnum - 1)
++ {
++ /* Current line is first inside
++ * [], line up with it. */
++ break;
++ }
++ ourscope = trypos->lnum;
++ }
++ }
++ else
++ {
++ lookfor = LOOKFOR_ENUM_OR_INIT;
++ cont_amount = cin_first_id_amount();
++ }
++ }
++ else
++ {
++ if (lookfor == LOOKFOR_INITIAL
++ && *l != NUL
++ && l[STRLEN(l) - 1] == '\\')
++ /* XXX */
++ cont_amount = cin_get_equal_amount(
++ curwin->w_cursor.lnum);
++ if (lookfor != LOOKFOR_TERM
++ && lookfor != LOOKFOR_JS_KEY
++ && lookfor != LOOKFOR_COMMA
++ && raw_string_start != curwin->w_cursor.lnum)
++ lookfor = LOOKFOR_UNTERM;
++ }
++ }
++ }
++ }
++
++ /*
++ * Check if we are after a while (cond);
++ * If so: Ignore until the matching "do".
++ */
++ else if (cin_iswhileofdo_end(terminated)) /* XXX */
++ {
++ /*
++ * Found an unterminated line after a while ();, line up
++ * with the last one.
++ * while (cond);
++ * 100 + <- line up with this one
++ * -> here;
++ */
++ if (lookfor == LOOKFOR_UNTERM
++ || lookfor == LOOKFOR_ENUM_OR_INIT)
++ {
++ if (cont_amount > 0)
++ amount = cont_amount;
++ else
++ amount += ind_continuation;
++ break;
++ }
++
++ if (whilelevel == 0)
++ {
++ lookfor = LOOKFOR_TERM;
++ amount = get_indent(); /* XXX */
++ if (theline[0] == '{')
++ amount += curbuf->b_ind_open_extra;
++ }
++ ++whilelevel;
++ }
++
++ /*
++ * We are after a "normal" statement.
++ * If we had another statement we can stop now and use the
++ * indent of that other statement.
++ * Otherwise the indent of the current statement may be used,
++ * search backwards for the next "normal" statement.
++ */
++ else
++ {
++ /*
++ * Skip single break line, if before a switch label. It
++ * may be lined up with the case label.
++ */
++ if (lookfor == LOOKFOR_NOBREAK
++ && cin_isbreak(skipwhite(ml_get_curline())))
++ {
++ lookfor = LOOKFOR_ANY;
++ continue;
++ }
++
++ /*
++ * Handle "do {" line.
++ */
++ if (whilelevel > 0)
++ {
++ l = cin_skipcomment(ml_get_curline());
++ if (cin_isdo(l))
++ {
++ amount = get_indent(); /* XXX */
++ --whilelevel;
++ continue;
++ }
++ }
++
++ /*
++ * Found a terminated line above an unterminated line. Add
++ * the amount for a continuation line.
++ * x = 1;
++ * y = foo +
++ * -> here;
++ * or
++ * int x = 1;
++ * int foo,
++ * -> here;
++ */
++ if (lookfor == LOOKFOR_UNTERM
++ || lookfor == LOOKFOR_ENUM_OR_INIT)
++ {
++ if (cont_amount > 0)
++ amount = cont_amount;
++ else
++ amount += ind_continuation;
++ break;
++ }
++
++ /*
++ * Found a terminated line above a terminated line or "if"
++ * etc. line. Use the amount of the line below us.
++ * x = 1; x = 1;
++ * if (asdf) y = 2;
++ * while (asdf) ->here;
++ * here;
++ * ->foo;
++ */
++ if (lookfor == LOOKFOR_TERM)
++ {
++ if (!lookfor_break && whilelevel == 0)
++ break;
++ }
++
++ /*
++ * First line above the one we're indenting is terminated.
++ * To know what needs to be done look further backward for
++ * a terminated line.
++ */
++ else
++ {
++ /*
++ * position the cursor over the rightmost paren, so
++ * that matching it will take us back to the start of
++ * the line. Helps for:
++ * func(asdr,
++ * asdfasdf);
++ * here;
++ */
++ term_again:
++ l = ml_get_curline();
++ if (find_last_paren(l, '(', ')')
++ && (trypos = find_match_paren(
++ curbuf->b_ind_maxparen)) != NULL)
++ {
++ /*
++ * Check if we are on a case label now. This is
++ * handled above.
++ * case xx: if ( asdf &&
++ * asdf)
++ */
++ curwin->w_cursor = *trypos;
++ l = ml_get_curline();
++ if (cin_iscase(l, FALSE) || cin_isscopedecl(l))
++ {
++ ++curwin->w_cursor.lnum;
++ curwin->w_cursor.col = 0;
++ continue;
++ }
++ }
++
++ /* When aligning with the case statement, don't align
++ * with a statement after it.
++ * case 1: { <-- don't use this { position
++ * stat;
++ * }
++ * case 2:
++ * stat;
++ * }
++ */
++ iscase = (curbuf->b_ind_keep_case_label
++ && cin_iscase(l, FALSE));
++
++ /*
++ * Get indent and pointer to text for current line,
++ * ignoring any jump label.
++ */
++ amount = skip_label(curwin->w_cursor.lnum, &l);
++
++ if (theline[0] == '{')
++ amount += curbuf->b_ind_open_extra;
++ /* See remark above: "Only add b_ind_open_extra.." */
++ l = skipwhite(l);
++ if (*l == '{')
++ amount -= curbuf->b_ind_open_extra;
++ lookfor = iscase ? LOOKFOR_ANY : LOOKFOR_TERM;
++
++ /*
++ * When a terminated line starts with "else" skip to
++ * the matching "if":
++ * else 3;
++ * indent this;
++ * Need to use the scope of this "else". XXX
++ * If whilelevel != 0 continue looking for a "do {".
++ */
++ if (lookfor == LOOKFOR_TERM
++ && *l != '}'
++ && cin_iselse(l)
++ && whilelevel == 0)
++ {
++ if ((trypos = find_start_brace()) == NULL
++ || find_match(LOOKFOR_IF, trypos->lnum)
++ == FAIL)
++ break;
++ continue;
++ }
++
++ /*
++ * If we're at the end of a block, skip to the start of
++ * that block.
++ */
++ l = ml_get_curline();
++ if (find_last_paren(l, '{', '}') /* XXX */
++ && (trypos = find_start_brace()) != NULL)
++ {
++ curwin->w_cursor = *trypos;
++ /* if not "else {" check for terminated again */
++ /* but skip block for "} else {" */
++ l = cin_skipcomment(ml_get_curline());
++ if (*l == '}' || !cin_iselse(l))
++ goto term_again;
++ ++curwin->w_cursor.lnum;
++ curwin->w_cursor.col = 0;
++ }
++ }
++ }
++ }
++ }
++ }
++
++ /* add extra indent for a comment */
++ if (cin_iscomment(theline))
++ amount += curbuf->b_ind_comment;
++
++ /* 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)) != 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, &amount))
++ 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, &amount)))
++ 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;
++ }
++
++ static int
++ find_match(int lookfor, linenr_T ourscope)
++ {
++ char_u *look;
++ pos_T *theirscope;
++ char_u *mightbeif;
++ int elselevel;
++ int whilelevel;
++
++ if (lookfor == LOOKFOR_IF)
++ {
++ elselevel = 1;
++ whilelevel = 0;
++ }
++ else
++ {
++ elselevel = 0;
++ whilelevel = 1;
++ }
++
++ curwin->w_cursor.col = 0;
++
++ while (curwin->w_cursor.lnum > ourscope + 1)
++ {
++ curwin->w_cursor.lnum--;
++ curwin->w_cursor.col = 0;
++
++ look = cin_skipcomment(ml_get_curline());
++ if (cin_iselse(look)
++ || cin_isif(look)
++ || cin_isdo(look) /* XXX */
++ || cin_iswhileofdo(look, curwin->w_cursor.lnum))
++ {
++ /*
++ * if we've gone outside the braces entirely,
++ * we must be out of scope...
++ */
++ theirscope = find_start_brace(); /* XXX */
++ if (theirscope == NULL)
++ break;
++
++ /*
++ * and if the brace enclosing this is further
++ * back than the one enclosing the else, we're
++ * out of luck too.
++ */
++ if (theirscope->lnum < ourscope)
++ break;
++
++ /*
++ * and if they're enclosed in a *deeper* brace,
++ * then we can ignore it because it's in a
++ * different scope...
++ */
++ if (theirscope->lnum > ourscope)
++ continue;
++
++ /*
++ * if it was an "else" (that's not an "else if")
++ * then we need to go back to another if, so
++ * increment elselevel
++ */
++ look = cin_skipcomment(ml_get_curline());
++ if (cin_iselse(look))
++ {
++ mightbeif = cin_skipcomment(look + 4);
++ if (!cin_isif(mightbeif))
++ ++elselevel;
++ continue;
++ }
++
++ /*
++ * if it was a "while" then we need to go back to
++ * another "do", so increment whilelevel. XXX
++ */
++ if (cin_iswhileofdo(look, curwin->w_cursor.lnum))
++ {
++ ++whilelevel;
++ continue;
++ }
++
++ /* If it's an "if" decrement elselevel */
++ look = cin_skipcomment(ml_get_curline());
++ if (cin_isif(look))
++ {
++ elselevel--;
++ /*
++ * When looking for an "if" ignore "while"s that
++ * get in the way.
++ */
++ if (elselevel == 0 && lookfor == LOOKFOR_IF)
++ whilelevel = 0;
++ }
++
++ /* If it's a "do" decrement whilelevel */
++ if (cin_isdo(look))
++ whilelevel--;
++
++ /*
++ * if we've used up all the elses, then
++ * this must be the if that we want!
++ * match the indent level of that if.
++ */
++ if (elselevel <= 0 && whilelevel <= 0)
++ {
++ return OK;
++ }
++ }
++ }
++ return FAIL;
++ }
++
++ # if defined(FEAT_EVAL) || defined(PROTO)
++ /*
++ * Get indent level from 'indentexpr'.
++ */
++ int
++ get_expr_indent(void)
++ {
++ int indent = -1;
++ char_u *inde_copy;
++ pos_T save_pos;
++ colnr_T save_curswant;
++ int save_set_curswant;
++ int save_State;
++ int use_sandbox = was_set_insecurely((char_u *)"indentexpr",
++ OPT_LOCAL);
++
++ /* Save and restore cursor position and curswant, in case it was changed
++ * via :normal commands */
++ save_pos = curwin->w_cursor;
++ save_curswant = curwin->w_curswant;
++ save_set_curswant = curwin->w_set_curswant;
++ set_vim_var_nr(VV_LNUM, curwin->w_cursor.lnum);
++ if (use_sandbox)
++ ++sandbox;
++ ++textlock;
++
++ /* Need to make a copy, the 'indentexpr' option could be changed while
++ * evaluating it. */
++ inde_copy = vim_strsave(curbuf->b_p_inde);
++ if (inde_copy != NULL)
++ {
++ indent = (int)eval_to_number(inde_copy);
++ vim_free(inde_copy);
++ }
++
++ if (use_sandbox)
++ --sandbox;
++ --textlock;
++
++ /* Restore the cursor position so that 'indentexpr' doesn't need to.
++ * Pretend to be in Insert mode, allow cursor past end of line for "o"
++ * command. */
++ save_State = State;
++ State = INSERT;
++ curwin->w_cursor = save_pos;
++ curwin->w_curswant = save_curswant;
++ curwin->w_set_curswant = save_set_curswant;
++ check_cursor();
++ State = save_State;
++
++ /* If there is an error, just keep the current indent. */
++ if (indent < 0)
++ indent = get_indent();
++
++ return indent;
++ }
++ # endif
++
++ /*
++ * 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_LISP) || defined(PROTO)
++
++ static int
++ lisp_match(char_u *p)
++ {
++ char_u buf[LSIZE];
++ int len;
++ char_u *word = *curbuf->b_p_lw != NUL ? curbuf->b_p_lw : p_lispwords;
++
++ while (*word != NUL)
++ {
++ (void)copy_option_part(&word, buf, LSIZE, ",");
++ len = (int)STRLEN(buf);
++ if (STRNCMP(buf, p, len) == 0 && p[len] == ' ')
++ return TRUE;
++ }
++ return FALSE;
++ }
++
++ /*
++ * When 'p' is present in 'cpoptions, a Vi compatible method is used.
++ * The incompatible newer method is quite a bit better at indenting
++ * code in lisp-like languages than the traditional one; it's still
++ * mostly heuristics however -- Dirk van Deun, dirk@rave.org
++ *
++ * TODO:
++ * Findmatch() should be adapted for lisp, also to make showmatch
++ * work correctly: now (v5.3) it seems all C/C++ oriented:
++ * - it does not recognize the #\( and #\) notations as character literals
++ * - it doesn't know about comments starting with a semicolon
++ * - it incorrectly interprets '(' as a character literal
++ * All this messes up get_lisp_indent in some rare cases.
++ * Update from Sergey Khorev:
++ * I tried to fix the first two issues.
++ */
++ int
++ get_lisp_indent(void)
++ {
++ pos_T *pos, realpos, paren;
++ int amount;
++ char_u *that;
++ colnr_T col;
++ colnr_T firsttry;
++ int parencount, quotecount;
++ int vi_lisp;
++
++ /* Set vi_lisp to use the vi-compatible method */
++ vi_lisp = (vim_strchr(p_cpo, CPO_LISP) != NULL);
++
++ realpos = curwin->w_cursor;
++ curwin->w_cursor.col = 0;
++
++ if ((pos = findmatch(NULL, '(')) == NULL)
++ pos = findmatch(NULL, '[');
++ else
++ {
++ paren = *pos;
++ pos = findmatch(NULL, '[');
++ if (pos == NULL || LT_POSP(pos, &paren))
++ pos = &paren;
++ }
++ if (pos != NULL)
++ {
++ /* Extra trick: Take the indent of the first previous non-white
++ * line that is at the same () level. */
++ amount = -1;
++ parencount = 0;
++
++ while (--curwin->w_cursor.lnum >= pos->lnum)
++ {
++ if (linewhite(curwin->w_cursor.lnum))
++ continue;
++ for (that = ml_get_curline(); *that != NUL; ++that)
++ {
++ if (*that == ';')
++ {
++ while (*(that + 1) != NUL)
++ ++that;
++ continue;
++ }
++ if (*that == '\\')
++ {
++ if (*(that + 1) != NUL)
++ ++that;
++ continue;
++ }
++ if (*that == '"' && *(that + 1) != NUL)
++ {
++ while (*++that && *that != '"')
++ {
++ /* skipping escaped characters in the string */
++ if (*that == '\\')
++ {
++ if (*++that == NUL)
++ break;
++ if (that[1] == NUL)
++ {
++ ++that;
++ break;
++ }
++ }
++ }
++ }
++ if (*that == '(' || *that == '[')
++ ++parencount;
++ else if (*that == ')' || *that == ']')
++ --parencount;
++ }
++ if (parencount == 0)
++ {
++ amount = get_indent();
++ break;
++ }
++ }
++
++ if (amount == -1)
++ {
++ curwin->w_cursor.lnum = pos->lnum;
++ curwin->w_cursor.col = pos->col;
++ col = pos->col;
++
++ that = ml_get_curline();
++
++ if (vi_lisp && get_indent() == 0)
++ amount = 2;
++ else
++ {
++ char_u *line = that;
++
++ amount = 0;
++ while (*that && col)
++ {
++ amount += lbr_chartabsize_adv(line, &that, (colnr_T)amount);
++ col--;
++ }
++
++ /*
++ * Some keywords require "body" indenting rules (the
++ * non-standard-lisp ones are Scheme special forms):
++ *
++ * (let ((a 1)) instead (let ((a 1))
++ * (...)) of (...))
++ */
++
++ if (!vi_lisp && (*that == '(' || *that == '[')
++ && lisp_match(that + 1))
++ amount += 2;
++ else
++ {
++ that++;
++ amount++;
++ firsttry = amount;
++
++ while (VIM_ISWHITE(*that))
++ {
++ amount += lbr_chartabsize(line, that, (colnr_T)amount);
++ ++that;
++ }
++
++ if (*that && *that != ';') /* not a comment line */
++ {
++ /* test *that != '(' to accommodate first let/do
++ * argument if it is more than one line */
++ if (!vi_lisp && *that != '(' && *that != '[')
++ firsttry++;
++
++ parencount = 0;
++ quotecount = 0;
++
++ if (vi_lisp
++ || (*that != '"'
++ && *that != '\''
++ && *that != '#'
++ && (*that < '0' || *that > '9')))
++ {
++ while (*that
++ && (!VIM_ISWHITE(*that)
++ || quotecount
++ || parencount)
++ && (!((*that == '(' || *that == '[')
++ && !quotecount
++ && !parencount
++ && vi_lisp)))
++ {
++ if (*that == '"')
++ quotecount = !quotecount;
++ if ((*that == '(' || *that == '[')
++ && !quotecount)
++ ++parencount;
++ if ((*that == ')' || *that == ']')
++ && !quotecount)
++ --parencount;
++ if (*that == '\\' && *(that+1) != NUL)
++ amount += lbr_chartabsize_adv(
++ line, &that, (colnr_T)amount);
++ amount += lbr_chartabsize_adv(
++ line, &that, (colnr_T)amount);
++ }
++ }
++ while (VIM_ISWHITE(*that))
++ {
++ amount += lbr_chartabsize(
++ line, that, (colnr_T)amount);
++ that++;
++ }
++ if (!*that || *that == ';')
++ amount = firsttry;
++ }
++ }
++ }
++ }
++ }
++ else
++ amount = 0; /* no matching '(' or '[' found, use zero indent */
++
++ curwin->w_cursor = realpos;
++
++ return amount;
++ }
++ #endif /* FEAT_LISP */
++
++ #if defined(FEAT_CINDENT) || defined(PROTO)
++ /*
++ * Do C or expression indenting on the current line.
++ */
++ void
++ do_c_expr_indent(void)
++ {
++ # ifdef FEAT_EVAL
++ if (*curbuf->b_p_inde != NUL)
++ fixthisline(get_expr_indent);
++ else
++ # endif
++ fixthisline(get_c_indent);
++ }
++ #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
+*** ../vim-8.1.0856/src/misc1.c 2019-01-26 17:28:22.228599112 +0100
+--- src/misc1.c 2019-01-31 13:43:23.356467234 +0100
+***************
+*** 702,742 ****
+ #endif
+
+
+- #if defined(FEAT_CINDENT) || defined(FEAT_SMARTINDENT)
+-
+- /*
+- * Return TRUE if the string "line" starts with a word from 'cinwords'.
+- */
+- static 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
+-
+ /*
+ * open_line: Add a new line below or above the current line.
+ *
+--- 702,707 ----
+***************
+*** 5404,9720 ****
+ return new_fname;
+ }
+
+- #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)
+-
+- /*
+- * Do C or expression indenting on the current line.
+- */
+- void
+- do_c_expr_indent(void)
+- {
+- # ifdef FEAT_EVAL
+- if (*curbuf->b_p_inde != NUL)
+- fixthisline(get_expr_indent);
+- else
+- # endif
+- fixthisline(get_c_indent);
+- }
+-
+- /* 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)++;
+-
+- *s = cin_skipcomment(*s);
+-
+- /* "::" is not a label, it's C++ */
+- return (**s == ':' && *++*s != ':');
+- }
+-
+- /*
+- * Recognize a label: "label:".
+- * Note: curwin->w_cursor must be where we are looking for the label.
+- */
+- int
+- cin_islabel(void) /* XXX */
+- {
+- char_u *s;
+-
+- s = cin_skipcomment(ml_get_curline());
+-
+- /*
+- * Exclude "default" from labels, since it should be indented
+- * like a switch label. Same for C++ scope declarations.
+- */
+- if (cin_isdefault(s))
+- return FALSE;
+- if (cin_isscopedecl(s))
+- return FALSE;
+-
+- if (cin_islabel_skip(&s))
+- {
+- /*
+- * Only accept a label if the previous line is terminated or is a case
+- * label.
+- */
+- pos_T cursor_save;
+- pos_T *trypos;
+- char_u *line;
+-
+- cursor_save = curwin->w_cursor;
+- while (curwin->w_cursor.lnum > 1)
+- {
+- --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)) != NULL) /* XXX */
+- curwin->w_cursor = *trypos;
+-
+- line = ml_get_curline();
+- if (cin_ispreproc(line)) /* ignore #defines, #if, etc. */
+- continue;
+- if (*(line = cin_skipcomment(line)) == NUL)
+- continue;
+-
+- curwin->w_cursor = cursor_save;
+- if (cin_isterminated(line, TRUE, FALSE)
+- || cin_isscopedecl(line)
+- || cin_iscase(line, TRUE)
+- || (cin_islabel_skip(&line) && cin_nocode(line)))
+- return TRUE;
+- return FALSE;
+- }
+- curwin->w_cursor = cursor_save;
+- return TRUE; /* label at start of file??? */
+- }
+- return FALSE;
+- }
+-
+- /*
+- * Recognize structure initialization and enumerations:
+- * "[typedef] [static|public|protected|private] enum"
+- * "[typedef] [static|public|protected|private] = {"
+- */
+- static int
+- cin_isinit(void)
+- {
+- char_u *s;
+- static char *skip[] = {"static", "public", "protected", "private"};
+-
+- s = cin_skipcomment(ml_get_curline());
+-
+- if (cin_starts_with(s, "typedef"))
+- s = cin_skipcomment(s + 7);
+-
+- for (;;)
+- {
+- int i, l;
+-
+- for (i = 0; i < (int)(sizeof(skip) / sizeof(char *)); ++i)
+- {
+- l = (int)strlen(skip[i]);
+- if (cin_starts_with(s, skip[i]))
+- {
+- s = cin_skipcomment(s + l);
+- l = 0;
+- break;
+- }
+- }
+- if (l != 0)
+- break;
+- }
+-
+- if (cin_starts_with(s, "enum"))
+- return TRUE;
+-
+- if (cin_ends_in(s, (char_u *)"=", (char_u *)"{"))
+- return TRUE;
+-
+- return FALSE;
+- }
+-
+- /*
+- * Recognize a switch label: "case .*:" or "default:".
+- */
+- int
+- cin_iscase(
+- char_u *s,
+- int strict) /* Allow relaxed check of case statement for JS */
+- {
+- s = cin_skipcomment(s);
+- if (cin_starts_with(s, "case"))
+- {
+- for (s += 4; *s; ++s)
+- {
+- s = cin_skipcomment(s);
+- if (*s == ':')
+- {
+- if (s[1] == ':') /* skip over "::" for C++ */
+- ++s;
+- else
+- return TRUE;
+- }
+- if (*s == '\'' && s[1] && s[2] == '\'')
+- s += 2; /* skip over ':' */
+- else if (*s == '/' && (s[1] == '*' || s[1] == '/'))
+- return FALSE; /* stop at comment */
+- else if (*s == '"')
+- {
+- /* JS etc. */
+- if (strict)
+- return FALSE; /* stop at string */
+- else
+- return TRUE;
+- }
+- }
+- return FALSE;
+- }
+-
+- if (cin_isdefault(s))
+- return TRUE;
+- return FALSE;
+- }
+-
+- /*
+- * Recognize a "default" switch label.
+- */
+- static int
+- cin_isdefault(char_u *s)
+- {
+- return (STRNCMP(s, "default", 7) == 0
+- && *(s = cin_skipcomment(s + 7)) == ':'
+- && s[1] != ':');
+- }
+-
+- /*
+- * Recognize a "public/private/protected" scope declaration label.
+- */
+- int
+- cin_isscopedecl(char_u *s)
+- {
+- int i;
+-
+- s = cin_skipcomment(s);
+- if (STRNCMP(s, "public", 6) == 0)
+- i = 6;
+- else if (STRNCMP(s, "protected", 9) == 0)
+- i = 9;
+- else if (STRNCMP(s, "private", 7) == 0)
+- i = 7;
+- else
+- return FALSE;
+- return (*(s = cin_skipcomment(s + i)) == ':' && s[1] != ':');
+- }
+-
+- /* Maximum number of lines to search back for a "namespace" line. */
+- #define FIND_NAMESPACE_LIM 20
+-
+- /*
+- * Recognize a "namespace" scope declaration.
+- */
+- static int
+- cin_is_cpp_namespace(char_u *s)
+- {
+- char_u *p;
+- int has_name = FALSE;
+- int has_name_start = FALSE;
+-
+- s = cin_skipcomment(s);
+- if (STRNCMP(s, "namespace", 9) == 0 && (s[9] == NUL || !vim_iswordc(s[9])))
+- {
+- p = cin_skipcomment(skipwhite(s + 9));
+- while (*p != NUL)
+- {
+- if (VIM_ISWHITE(*p))
+- {
+- has_name = TRUE; /* found end of a name */
+- p = cin_skipcomment(skipwhite(p));
+- }
+- else if (*p == '{')
+- {
+- break;
+- }
+- else if (vim_iswordc(*p))
+- {
+- has_name_start = TRUE;
+- if (has_name)
+- return FALSE; /* word character after skipping past name */
+- ++p;
+- }
+- else if (p[0] == ':' && p[1] == ':' && vim_iswordc(p[2]))
+- {
+- if (!has_name_start || has_name)
+- return FALSE;
+- /* C++ 17 nested namespace */
+- p += 3;
+- }
+- else
+- {
+- return FALSE;
+- }
+- }
+- return TRUE;
+- }
+- return FALSE;
+- }
+-
+- /*
+- * Recognize a `extern "C"` or `extern "C++"` linkage specifications.
+- */
+- static int
+- cin_is_cpp_extern_c(char_u *s)
+- {
+- char_u *p;
+- int has_string_literal = FALSE;
+-
+- s = cin_skipcomment(s);
+- if (STRNCMP(s, "extern", 6) == 0 && (s[6] == NUL || !vim_iswordc(s[6])))
+- {
+- p = cin_skipcomment(skipwhite(s + 6));
+- while (*p != NUL)
+- {
+- if (VIM_ISWHITE(*p))
+- {
+- p = cin_skipcomment(skipwhite(p));
+- }
+- else if (*p == '{')
+- {
+- break;
+- }
+- else if (p[0] == '"' && p[1] == 'C' && p[2] == '"')
+- {
+- if (has_string_literal)
+- return FALSE;
+- has_string_literal = TRUE;
+- p += 3;
+- }
+- else if (p[0] == '"' && p[1] == 'C' && p[2] == '+' && p[3] == '+'
+- && p[4] == '"')
+- {
+- if (has_string_literal)
+- return FALSE;
+- has_string_literal = TRUE;
+- p += 5;
+- }
+- else
+- {
+- return FALSE;
+- }
+- }
+- return has_string_literal ? TRUE : FALSE;
+- }
+- return FALSE;
+- }
+-
+- /*
+- * Return a pointer to the first non-empty non-comment character after a ':'.
+- * Return NULL if not found.
+- * case 234: a = b;
+- * ^
+- */
+- static char_u *
+- after_label(char_u *l)
+- {
+- for ( ; *l; ++l)
+- {
+- if (*l == ':')
+- {
+- if (l[1] == ':') /* skip over "::" for C++ */
+- ++l;
+- else if (!cin_iscase(l + 1, FALSE))
+- break;
+- }
+- else if (*l == '\'' && l[1] && l[2] == '\'')
+- l += 2; /* skip over 'x' */
+- }
+- if (*l == NUL)
+- return NULL;
+- l = cin_skipcomment(l + 1);
+- if (*l == NUL)
+- return NULL;
+- return l;
+- }
+-
+- /*
+- * Get indent of line "lnum", skipping a label.
+- * Return 0 if there is nothing after the label.
+- */
+- static int
+- get_indent_nolabel (linenr_T lnum) /* XXX */
+- {
+- char_u *l;
+- pos_T fp;
+- colnr_T col;
+- char_u *p;
+-
+- l = ml_get(lnum);
+- p = after_label(l);
+- if (p == NULL)
+- return 0;
+-
+- fp.col = (colnr_T)(p - l);
+- fp.lnum = lnum;
+- getvcol(curwin, &fp, &col, NULL, NULL);
+- return (int)col;
+- }
+-
+- /*
+- * Find indent for line "lnum", ignoring any case or jump label.
+- * Also return a pointer to the text (after the label) in "pp".
+- * label: if (asdf && asdfasdf)
+- * ^
+- */
+- static int
+- skip_label(linenr_T lnum, char_u **pp)
+- {
+- char_u *l;
+- int amount;
+- pos_T cursor_save;
+-
+- cursor_save = curwin->w_cursor;
+- curwin->w_cursor.lnum = lnum;
+- l = ml_get_curline();
+- /* XXX */
+- if (cin_iscase(l, FALSE) || cin_isscopedecl(l) || cin_islabel())
+- {
+- amount = get_indent_nolabel(lnum);
+- l = after_label(ml_get_curline());
+- if (l == NULL) /* just in case */
+- l = ml_get_curline();
+- }
+- else
+- {
+- amount = get_indent();
+- l = ml_get_curline();
+- }
+- *pp = l;
+-
+- curwin->w_cursor = cursor_save;
+- return amount;
+- }
+-
+- /*
+- * Return the indent of the first variable name after a type in a declaration.
+- * int a, indent of "a"
+- * static struct foo b, indent of "b"
+- * enum bla c, indent of "c"
+- * Returns zero when it doesn't look like a declaration.
+- */
+- static int
+- cin_first_id_amount(void)
+- {
+- char_u *line, *p, *s;
+- int len;
+- pos_T fp;
+- colnr_T col;
+-
+- line = ml_get_curline();
+- p = skipwhite(line);
+- len = (int)(skiptowhite(p) - p);
+- if (len == 6 && STRNCMP(p, "static", 6) == 0)
+- {
+- p = skipwhite(p + 6);
+- len = (int)(skiptowhite(p) - p);
+- }
+- if (len == 6 && STRNCMP(p, "struct", 6) == 0)
+- p = skipwhite(p + 6);
+- else if (len == 4 && STRNCMP(p, "enum", 4) == 0)
+- p = skipwhite(p + 4);
+- else if ((len == 8 && STRNCMP(p, "unsigned", 8) == 0)
+- || (len == 6 && STRNCMP(p, "signed", 6) == 0))
+- {
+- s = skipwhite(p + len);
+- if ((STRNCMP(s, "int", 3) == 0 && VIM_ISWHITE(s[3]))
+- || (STRNCMP(s, "long", 4) == 0 && VIM_ISWHITE(s[4]))
+- || (STRNCMP(s, "short", 5) == 0 && VIM_ISWHITE(s[5]))
+- || (STRNCMP(s, "char", 4) == 0 && VIM_ISWHITE(s[4])))
+- p = s;
+- }
+- for (len = 0; vim_isIDc(p[len]); ++len)
+- ;
+- if (len == 0 || !VIM_ISWHITE(p[len]) || cin_nocode(p))
+- return 0;
+-
+- p = skipwhite(p + len);
+- fp.lnum = curwin->w_cursor.lnum;
+- fp.col = (colnr_T)(p - line);
+- getvcol(curwin, &fp, &col, NULL, NULL);
+- return (int)col;
+- }
+-
+- /*
+- * Return the indent of the first non-blank after an equal sign.
+- * char *foo = "here";
+- * Return zero if no (useful) equal sign found.
+- * Return -1 if the line above "lnum" ends in a backslash.
+- * foo = "asdf\
+- * asdf\
+- * here";
+- */
+- static int
+- cin_get_equal_amount(linenr_T lnum)
+- {
+- char_u *line;
+- char_u *s;
+- colnr_T col;
+- pos_T fp;
+-
+- if (lnum > 1)
+- {
+- line = ml_get(lnum - 1);
+- if (*line != NUL && line[STRLEN(line) - 1] == '\\')
+- return -1;
+- }
+-
+- line = s = ml_get(lnum);
+- while (*s != NUL && vim_strchr((char_u *)"=;{}\"'", *s) == NULL)
+- {
+- if (cin_iscomment(s)) /* ignore comments */
+- s = cin_skipcomment(s);
+- else
+- ++s;
+- }
+- if (*s != '=')
+- return 0;
+-
+- s = skipwhite(s + 1);
+- if (cin_nocode(s))
+- return 0;
+-
+- if (*s == '"') /* nice alignment for continued strings */
+- ++s;
+-
+- fp.lnum = lnum;
+- fp.col = (colnr_T)(s - line);
+- getvcol(curwin, &fp, &col, NULL, NULL);
+- return (int)col;
+- }
+-
+- /*
+- * Recognize a preprocessor statement: Any line that starts with '#'.
+- */
+- static int
+- cin_ispreproc(char_u *s)
+- {
+- if (*skipwhite(s) == '#')
+- return TRUE;
+- return FALSE;
+- }
+-
+- /*
+- * Return TRUE if line "*pp" at "*lnump" is a preprocessor statement or a
+- * continuation line of a preprocessor statement. Decrease "*lnump" to the
+- * start and return the line in "*pp".
+- * Put the amount of indent in "*amount".
+- */
+- static int
+- cin_ispreproc_cont(char_u **pp, linenr_T *lnump, int *amount)
+- {
+- char_u *line = *pp;
+- linenr_T lnum = *lnump;
+- int retval = FALSE;
+- int candidate_amount = *amount;
+-
+- if (*line != NUL && line[STRLEN(line) - 1] == '\\')
+- candidate_amount = get_indent_lnum(lnum);
+-
+- for (;;)
+- {
+- if (cin_ispreproc(line))
+- {
+- retval = TRUE;
+- *lnump = lnum;
+- break;
+- }
+- if (lnum == 1)
+- break;
+- line = ml_get(--lnum);
+- if (*line == NUL || line[STRLEN(line) - 1] != '\\')
+- break;
+- }
+-
+- if (lnum != *lnump)
+- *pp = ml_get(*lnump);
+- if (retval)
+- *amount = candidate_amount;
+- return retval;
+- }
+-
+- /*
+- * Recognize the start of a C or C++ comment.
+- */
+- static int
+- cin_iscomment(char_u *p)
+- {
+- return (p[0] == '/' && (p[1] == '*' || p[1] == '/'));
+- }
+-
+- /*
+- * Recognize the start of a "//" comment.
+- */
+- static int
+- cin_islinecomment(char_u *p)
+- {
+- return (p[0] == '/' && p[1] == '/');
+- }
+-
+- /*
+- * Recognize a line that starts with '{' or '}', or ends with ';', ',', '{' or
+- * '}'.
+- * Don't consider "} else" a terminated line.
+- * If a line begins with an "else", only consider it terminated if no unmatched
+- * opening braces follow (handle "else { foo();" correctly).
+- * Return the character terminating the line (ending char's have precedence if
+- * both apply in order to determine initializations).
+- */
+- static int
+- cin_isterminated(
+- char_u *s,
+- int incl_open, /* include '{' at the end as terminator */
+- int incl_comma) /* recognize a trailing comma */
+- {
+- char_u found_start = 0;
+- unsigned n_open = 0;
+- int is_else = FALSE;
+-
+- s = cin_skipcomment(s);
+-
+- if (*s == '{' || (*s == '}' && !cin_iselse(s)))
+- found_start = *s;
+-
+- if (!found_start)
+- is_else = cin_iselse(s);
+-
+- while (*s)
+- {
+- /* skip over comments, "" strings and 'c'haracters */
+- s = skip_string(cin_skipcomment(s));
+- if (*s == '}' && n_open > 0)
+- --n_open;
+- if ((!is_else || n_open == 0)
+- && (*s == ';' || *s == '}' || (incl_comma && *s == ','))
+- && cin_nocode(s + 1))
+- return *s;
+- else if (*s == '{')
+- {
+- if (incl_open && cin_nocode(s + 1))
+- return *s;
+- else
+- ++n_open;
+- }
+-
+- if (*s)
+- s++;
+- }
+- return found_start;
+- }
+-
+- /*
+- * Recognize the basic picture of a function declaration -- it needs to
+- * have an open paren somewhere and a close paren at the end of the line and
+- * no semicolons anywhere.
+- * When a line ends in a comma we continue looking in the next line.
+- * "sp" points to a string with the line. When looking at other lines it must
+- * be restored to the line. When it's NULL fetch lines here.
+- * "first_lnum" is where we start looking.
+- * "min_lnum" is the line before which we will not be looking.
+- */
+- static int
+- cin_isfuncdecl(
+- char_u **sp,
+- linenr_T first_lnum,
+- linenr_T min_lnum)
+- {
+- char_u *s;
+- linenr_T lnum = first_lnum;
+- linenr_T save_lnum = curwin->w_cursor.lnum;
+- int retval = FALSE;
+- pos_T *trypos;
+- int just_started = TRUE;
+-
+- if (sp == NULL)
+- s = ml_get(lnum);
+- else
+- s = *sp;
+-
+- curwin->w_cursor.lnum = lnum;
+- if (find_last_paren(s, '(', ')')
+- && (trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL)
+- {
+- lnum = trypos->lnum;
+- if (lnum < min_lnum)
+- {
+- curwin->w_cursor.lnum = save_lnum;
+- return FALSE;
+- }
+-
+- s = ml_get(lnum);
+- }
+- curwin->w_cursor.lnum = save_lnum;
+-
+- /* Ignore line starting with #. */
+- if (cin_ispreproc(s))
+- return FALSE;
+-
+- while (*s && *s != '(' && *s != ';' && *s != '\'' && *s != '"')
+- {
+- if (cin_iscomment(s)) /* ignore comments */
+- s = cin_skipcomment(s);
+- else if (*s == ':')
+- {
+- if (*(s + 1) == ':')
+- s += 2;
+- else
+- /* To avoid a mistake in the following situation:
+- * A::A(int a, int b)
+- * : a(0) // <--not a function decl
+- * , b(0)
+- * {...
+- */
+- return FALSE;
+- }
+- else
+- ++s;
+- }
+- if (*s != '(')
+- return FALSE; /* ';', ' or " before any () or no '(' */
+-
+- while (*s && *s != ';' && *s != '\'' && *s != '"')
+- {
+- if (*s == ')' && cin_nocode(s + 1))
+- {
+- /* ')' at the end: may have found a match
+- * Check for he previous line not to end in a backslash:
+- * #if defined(x) && \
+- * defined(y)
+- */
+- lnum = first_lnum - 1;
+- s = ml_get(lnum);
+- if (*s == NUL || s[STRLEN(s) - 1] != '\\')
+- retval = TRUE;
+- goto done;
+- }
+- if ((*s == ',' && cin_nocode(s + 1)) || s[1] == NUL || cin_nocode(s))
+- {
+- int comma = (*s == ',');
+-
+- /* ',' at the end: continue looking in the next line.
+- * At the end: check for ',' in the next line, for this style:
+- * func(arg1
+- * , arg2) */
+- for (;;)
+- {
+- if (lnum >= curbuf->b_ml.ml_line_count)
+- break;
+- s = ml_get(++lnum);
+- if (!cin_ispreproc(s))
+- break;
+- }
+- if (lnum >= curbuf->b_ml.ml_line_count)
+- break;
+- /* Require a comma at end of the line or a comma or ')' at the
+- * start of next line. */
+- s = skipwhite(s);
+- if (!just_started && (!comma && *s != ',' && *s != ')'))
+- break;
+- just_started = FALSE;
+- }
+- else if (cin_iscomment(s)) /* ignore comments */
+- s = cin_skipcomment(s);
+- else
+- {
+- ++s;
+- just_started = FALSE;
+- }
+- }
+-
+- done:
+- if (lnum != first_lnum && sp != NULL)
+- *sp = ml_get(first_lnum);
+-
+- return retval;
+- }
+-
+- static int
+- cin_isif(char_u *p)
+- {
+- return (STRNCMP(p, "if", 2) == 0 && !vim_isIDc(p[2]));
+- }
+-
+- static int
+- cin_iselse(
+- char_u *p)
+- {
+- if (*p == '}') /* accept "} else" */
+- p = cin_skipcomment(p + 1);
+- return (STRNCMP(p, "else", 4) == 0 && !vim_isIDc(p[4]));
+- }
+-
+- static int
+- cin_isdo(char_u *p)
+- {
+- return (STRNCMP(p, "do", 2) == 0 && !vim_isIDc(p[2]));
+- }
+-
+- /*
+- * Check if this is a "while" that should have a matching "do".
+- * We only accept a "while (condition) ;", with only white space between the
+- * ')' and ';'. The condition may be spread over several lines.
+- */
+- static int
+- cin_iswhileofdo (char_u *p, linenr_T lnum) /* XXX */
+- {
+- pos_T cursor_save;
+- pos_T *trypos;
+- int retval = FALSE;
+-
+- p = cin_skipcomment(p);
+- if (*p == '}') /* accept "} while (cond);" */
+- p = cin_skipcomment(p + 1);
+- if (cin_starts_with(p, "while"))
+- {
+- cursor_save = curwin->w_cursor;
+- curwin->w_cursor.lnum = lnum;
+- curwin->w_cursor.col = 0;
+- p = ml_get_curline();
+- while (*p && *p != 'w') /* skip any '}', until the 'w' of the "while" */
+- {
+- ++p;
+- ++curwin->w_cursor.col;
+- }
+- if ((trypos = findmatchlimit(NULL, 0, 0,
+- curbuf->b_ind_maxparen)) != NULL
+- && *cin_skipcomment(ml_get_pos(trypos) + 1) == ';')
+- retval = TRUE;
+- curwin->w_cursor = cursor_save;
+- }
+- return retval;
+- }
+-
+- /*
+- * Check whether in "p" there is an "if", "for" or "while" before "*poffset".
+- * Return 0 if there is none.
+- * Otherwise return !0 and update "*poffset" to point to the place where the
+- * string was found.
+- */
+- static int
+- cin_is_if_for_while_before_offset(char_u *line, int *poffset)
+- {
+- int offset = *poffset;
+-
+- if (offset-- < 2)
+- return 0;
+- while (offset > 2 && VIM_ISWHITE(line[offset]))
+- --offset;
+-
+- offset -= 1;
+- if (!STRNCMP(line + offset, "if", 2))
+- goto probablyFound;
+-
+- if (offset >= 1)
+- {
+- offset -= 1;
+- if (!STRNCMP(line + offset, "for", 3))
+- goto probablyFound;
+-
+- if (offset >= 2)
+- {
+- offset -= 2;
+- if (!STRNCMP(line + offset, "while", 5))
+- goto probablyFound;
+- }
+- }
+- return 0;
+-
+- probablyFound:
+- if (!offset || !vim_isIDc(line[offset - 1]))
+- {
+- *poffset = offset;
+- return 1;
+- }
+- return 0;
+- }
+-
+- /*
+- * Return TRUE if we are at the end of a do-while.
+- * do
+- * nothing;
+- * while (foo
+- * && bar); <-- here
+- * Adjust the cursor to the line with "while".
+- */
+- static int
+- cin_iswhileofdo_end(int terminated)
+- {
+- char_u *line;
+- char_u *p;
+- char_u *s;
+- pos_T *trypos;
+- int i;
+-
+- if (terminated != ';') /* there must be a ';' at the end */
+- return FALSE;
+-
+- p = line = ml_get_curline();
+- while (*p != NUL)
+- {
+- p = cin_skipcomment(p);
+- if (*p == ')')
+- {
+- s = skipwhite(p + 1);
+- if (*s == ';' && cin_nocode(s + 1))
+- {
+- /* Found ");" at end of the line, now check there is "while"
+- * before the matching '('. XXX */
+- i = (int)(p - line);
+- curwin->w_cursor.col = i;
+- trypos = find_match_paren(curbuf->b_ind_maxparen);
+- if (trypos != NULL)
+- {
+- s = cin_skipcomment(ml_get(trypos->lnum));
+- if (*s == '}') /* accept "} while (cond);" */
+- s = cin_skipcomment(s + 1);
+- if (cin_starts_with(s, "while"))
+- {
+- curwin->w_cursor.lnum = trypos->lnum;
+- return TRUE;
+- }
+- }
+-
+- /* Searching may have made "line" invalid, get it again. */
+- line = ml_get_curline();
+- p = line + i;
+- }
+- }
+- if (*p != NUL)
+- ++p;
+- }
+- return FALSE;
+- }
+-
+- static int
+- cin_isbreak(char_u *p)
+- {
+- return (STRNCMP(p, "break", 5) == 0 && !vim_isIDc(p[5]));
+- }
+-
+- /*
+- * Find the position of a C++ base-class declaration or
+- * constructor-initialization. eg:
+- *
+- * class MyClass :
+- * baseClass <-- here
+- * class MyClass : public baseClass,
+- * anotherBaseClass <-- here (should probably lineup ??)
+- * MyClass::MyClass(...) :
+- * baseClass(...) <-- here (constructor-initialization)
+- *
+- * This is a lot of guessing. Watch out for "cond ? func() : foo".
+- */
+- static int
+- cin_is_cpp_baseclass(
+- cpp_baseclass_cache_T *cached) /* input and output */
+- {
+- lpos_T *pos = &cached->lpos; /* find position */
+- char_u *s;
+- int class_or_struct, lookfor_ctor_init, cpp_base_class;
+- linenr_T lnum = curwin->w_cursor.lnum;
+- char_u *line = ml_get_curline();
+-
+- if (pos->lnum <= lnum)
+- return cached->found; /* Use the cached result */
+-
+- pos->col = 0;
+-
+- s = skipwhite(line);
+- if (*s == '#') /* skip #define FOO x ? (x) : x */
+- return FALSE;
+- s = cin_skipcomment(s);
+- if (*s == NUL)
+- return FALSE;
+-
+- cpp_base_class = lookfor_ctor_init = class_or_struct = FALSE;
+-
+- /* Search for a line starting with '#', empty, ending in ';' or containing
+- * '{' or '}' and start below it. This handles the following situations:
+- * a = cond ?
+- * func() :
+- * asdf;
+- * func::foo()
+- * : something
+- * {}
+- * Foo::Foo (int one, int two)
+- * : something(4),
+- * somethingelse(3)
+- * {}
+- */
+- while (lnum > 1)
+- {
+- line = ml_get(lnum - 1);
+- s = skipwhite(line);
+- if (*s == '#' || *s == NUL)
+- break;
+- while (*s != NUL)
+- {
+- s = cin_skipcomment(s);
+- if (*s == '{' || *s == '}'
+- || (*s == ';' && cin_nocode(s + 1)))
+- break;
+- if (*s != NUL)
+- ++s;
+- }
+- if (*s != NUL)
+- break;
+- --lnum;
+- }
+-
+- pos->lnum = lnum;
+- line = ml_get(lnum);
+- s = line;
+- for (;;)
+- {
+- if (*s == NUL)
+- {
+- if (lnum == curwin->w_cursor.lnum)
+- break;
+- /* Continue in the cursor line. */
+- line = ml_get(++lnum);
+- s = line;
+- }
+- if (s == line)
+- {
+- /* don't recognize "case (foo):" as a baseclass */
+- if (cin_iscase(s, FALSE))
+- break;
+- s = cin_skipcomment(line);
+- if (*s == NUL)
+- continue;
+- }
+-
+- if (s[0] == '"' || (s[0] == 'R' && s[1] == '"'))
+- s = skip_string(s) + 1;
+- else if (s[0] == ':')
+- {
+- if (s[1] == ':')
+- {
+- /* skip double colon. It can't be a constructor
+- * initialization any more */
+- lookfor_ctor_init = FALSE;
+- s = cin_skipcomment(s + 2);
+- }
+- else if (lookfor_ctor_init || class_or_struct)
+- {
+- /* we have something found, that looks like the start of
+- * cpp-base-class-declaration or constructor-initialization */
+- cpp_base_class = TRUE;
+- lookfor_ctor_init = class_or_struct = FALSE;
+- pos->col = 0;
+- s = cin_skipcomment(s + 1);
+- }
+- else
+- s = cin_skipcomment(s + 1);
+- }
+- else if ((STRNCMP(s, "class", 5) == 0 && !vim_isIDc(s[5]))
+- || (STRNCMP(s, "struct", 6) == 0 && !vim_isIDc(s[6])))
+- {
+- class_or_struct = TRUE;
+- lookfor_ctor_init = FALSE;
+-
+- if (*s == 'c')
+- s = cin_skipcomment(s + 5);
+- else
+- s = cin_skipcomment(s + 6);
+- }
+- else
+- {
+- if (s[0] == '{' || s[0] == '}' || s[0] == ';')
+- {
+- cpp_base_class = lookfor_ctor_init = class_or_struct = FALSE;
+- }
+- else if (s[0] == ')')
+- {
+- /* Constructor-initialization is assumed if we come across
+- * something like "):" */
+- class_or_struct = FALSE;
+- lookfor_ctor_init = TRUE;
+- }
+- else if (s[0] == '?')
+- {
+- /* Avoid seeing '() :' after '?' as constructor init. */
+- return FALSE;
+- }
+- else if (!vim_isIDc(s[0]))
+- {
+- /* if it is not an identifier, we are wrong */
+- class_or_struct = FALSE;
+- lookfor_ctor_init = FALSE;
+- }
+- else if (pos->col == 0)
+- {
+- /* it can't be a constructor-initialization any more */
+- lookfor_ctor_init = FALSE;
+-
+- /* the first statement starts here: lineup with this one... */
+- if (cpp_base_class)
+- pos->col = (colnr_T)(s - line);
+- }
+-
+- /* When the line ends in a comma don't align with it. */
+- if (lnum == curwin->w_cursor.lnum && *s == ',' && cin_nocode(s + 1))
+- pos->col = 0;
+-
+- s = cin_skipcomment(s + 1);
+- }
+- }
+-
+- cached->found = cpp_base_class;
+- if (cpp_base_class)
+- pos->lnum = lnum;
+- return cpp_base_class;
+- }
+-
+- static int
+- get_baseclass_amount(int col)
+- {
+- int amount;
+- colnr_T vcol;
+- pos_T *trypos;
+-
+- if (col == 0)
+- {
+- amount = get_indent();
+- if (find_last_paren(ml_get_curline(), '(', ')')
+- && (trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL)
+- amount = get_indent_lnum(trypos->lnum); /* XXX */
+- if (!cin_ends_in(ml_get_curline(), (char_u *)",", NULL))
+- amount += curbuf->b_ind_cpp_baseclass;
+- }
+- else
+- {
+- curwin->w_cursor.col = col;
+- getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
+- amount = (int)vcol;
+- }
+- if (amount < curbuf->b_ind_cpp_baseclass)
+- amount = curbuf->b_ind_cpp_baseclass;
+- return amount;
+- }
+-
+- /*
+- * Return TRUE if string "s" ends with the string "find", possibly followed by
+- * white space and comments. Skip strings and comments.
+- * Ignore "ignore" after "find" if it's not NULL.
+- */
+- static int
+- cin_ends_in(char_u *s, char_u *find, char_u *ignore)
+- {
+- char_u *p = s;
+- char_u *r;
+- int len = (int)STRLEN(find);
+-
+- while (*p != NUL)
+- {
+- p = cin_skipcomment(p);
+- if (STRNCMP(p, find, len) == 0)
+- {
+- r = skipwhite(p + len);
+- if (ignore != NULL && STRNCMP(r, ignore, STRLEN(ignore)) == 0)
+- r = skipwhite(r + STRLEN(ignore));
+- if (cin_nocode(r))
+- return TRUE;
+- }
+- if (*p != NUL)
+- ++p;
+- }
+- return FALSE;
+- }
+-
+- /*
+- * Return TRUE when "s" starts with "word" and then a non-ID character.
+- */
+- static int
+- cin_starts_with(char_u *s, char *word)
+- {
+- int l = (int)STRLEN(word);
+-
+- return (STRNCMP(s, word, l) == 0 && !vim_isIDc(s[l]));
+- }
+-
+- /*
+- * Skip strings, chars and comments until at or past "trypos".
+- * Return the column found.
+- */
+- static int
+- cin_skip2pos(pos_T *trypos)
+- {
+- char_u *line;
+- char_u *p;
+- char_u *new_p;
+-
+- p = line = ml_get(trypos->lnum);
+- while (*p && (colnr_T)(p - line) < trypos->col)
+- {
+- if (cin_iscomment(p))
+- p = cin_skipcomment(p);
+- else
+- {
+- new_p = skip_string(p);
+- if (new_p == p)
+- ++p;
+- else
+- p = new_p;
+- }
+- }
+- return (int)(p - line);
+- }
+-
+- /*
+- * Find the '{' at the start of the block we are in.
+- * Return NULL if no match found.
+- * Ignore a '{' that is in a comment, makes indenting the next three lines
+- * work. */
+- /* foo() */
+- /* { */
+- /* } */
+-
+- static pos_T *
+- find_start_brace(void) /* XXX */
+- {
+- pos_T cursor_save;
+- pos_T *trypos;
+- pos_T *pos;
+- static pos_T pos_copy;
+-
+- cursor_save = curwin->w_cursor;
+- while ((trypos = findmatchlimit(NULL, '{', FM_BLOCKSTOP, 0)) != NULL)
+- {
+- pos_copy = *trypos; /* copy pos_T, next findmatch will change it */
+- trypos = &pos_copy;
+- curwin->w_cursor = *trypos;
+- 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)) == NULL) /* XXX */
+- break;
+- if (pos != NULL)
+- curwin->w_cursor.lnum = pos->lnum;
+- }
+- curwin->w_cursor = cursor_save;
+- return trypos;
+- }
+-
+- /*
+- * Find the matching '(', ignoring it if it is in a comment.
+- * Return NULL if no match found.
+- */
+- static pos_T *
+- find_match_paren(int ind_maxparen) /* XXX */
+- {
+- return find_match_char('(', ind_maxparen);
+- }
+-
+- static pos_T *
+- find_match_char(int c, int ind_maxparen) /* XXX */
+- {
+- pos_T cursor_save;
+- pos_T *trypos;
+- static pos_T pos_copy;
+- int ind_maxp_wk;
+-
+- cursor_save = curwin->w_cursor;
+- ind_maxp_wk = ind_maxparen;
+- retry:
+- if ((trypos = findmatchlimit(NULL, c, 0, ind_maxp_wk)) != NULL)
+- {
+- /* check if the ( is in a // comment */
+- if ((colnr_T)cin_skip2pos(trypos) > trypos->col)
+- {
+- ind_maxp_wk = ind_maxparen - (int)(cursor_save.lnum - trypos->lnum);
+- if (ind_maxp_wk > 0)
+- {
+- curwin->w_cursor = *trypos;
+- curwin->w_cursor.col = 0; /* XXX */
+- goto retry;
+- }
+- trypos = NULL;
+- }
+- else
+- {
+- pos_T *trypos_wk;
+-
+- pos_copy = *trypos; /* copy trypos, findmatch will change it */
+- trypos = &pos_copy;
+- curwin->w_cursor = *trypos;
+- if ((trypos_wk = ind_find_start_CORS(NULL)) != NULL) /* XXX */
+- {
+- ind_maxp_wk = ind_maxparen - (int)(cursor_save.lnum
+- - trypos_wk->lnum);
+- if (ind_maxp_wk > 0)
+- {
+- curwin->w_cursor = *trypos_wk;
+- goto retry;
+- }
+- trypos = NULL;
+- }
+- }
+- }
+- curwin->w_cursor = cursor_save;
+- return trypos;
+- }
+-
+- /*
+- * Find the matching '(', ignoring it if it is in a comment or before an
+- * unmatched {.
+- * Return NULL if no match found.
+- */
+- static pos_T *
+- find_match_paren_after_brace (int ind_maxparen) /* XXX */
+- {
+- pos_T *trypos = find_match_paren(ind_maxparen);
+-
+- if (trypos != NULL)
+- {
+- pos_T *tryposBrace = find_start_brace();
+-
+- /* If both an unmatched '(' and '{' is found. Ignore the '('
+- * position if the '{' is further down. */
+- if (tryposBrace != NULL
+- && (trypos->lnum != tryposBrace->lnum
+- ? trypos->lnum < tryposBrace->lnum
+- : trypos->col < tryposBrace->col))
+- trypos = NULL;
+- }
+- return trypos;
+- }
+-
+- /*
+- * Return ind_maxparen corrected for the difference in line number between the
+- * cursor position and "startpos". This makes sure that searching for a
+- * matching paren above the cursor line doesn't find a match because of
+- * looking a few lines further.
+- */
+- static int
+- corr_ind_maxparen(pos_T *startpos)
+- {
+- long n = (long)startpos->lnum - (long)curwin->w_cursor.lnum;
+-
+- if (n > 0 && n < curbuf->b_ind_maxparen / 2)
+- return curbuf->b_ind_maxparen - (int)n;
+- return curbuf->b_ind_maxparen;
+- }
+-
+- /*
+- * Set w_cursor.col to the column number of the last unmatched ')' or '{' in
+- * line "l". "l" must point to the start of the line.
+- */
+- static int
+- find_last_paren(char_u *l, int start, int end)
+- {
+- int i;
+- int retval = FALSE;
+- int open_count = 0;
+-
+- curwin->w_cursor.col = 0; /* default is start of line */
+-
+- for (i = 0; l[i] != NUL; i++)
+- {
+- i = (int)(cin_skipcomment(l + i) - l); /* ignore parens in comments */
+- i = (int)(skip_string(l + i) - l); /* ignore parens in quotes */
+- if (l[i] == start)
+- ++open_count;
+- else if (l[i] == end)
+- {
+- if (open_count > 0)
+- --open_count;
+- else
+- {
+- curwin->w_cursor.col = i;
+- retval = TRUE;
+- }
+- }
+- }
+- return retval;
+- }
+-
+- /*
+- * Parse 'cinoptions' and set the values in "curbuf".
+- * Must be called when 'cinoptions', 'shiftwidth' and/or 'tabstop' changes.
+- */
+- void
+- parse_cino(buf_T *buf)
+- {
+- char_u *p;
+- char_u *l;
+- char_u *digits;
+- int n;
+- int divider;
+- int fraction = 0;
+- int sw = (int)get_sw_value(buf);
+-
+- /*
+- * Set the default values.
+- */
+- /* Spaces from a block's opening brace the prevailing indent for that
+- * block should be. */
+- buf->b_ind_level = sw;
+-
+- /* Spaces from the edge of the line an open brace that's at the end of a
+- * line is imagined to be. */
+- buf->b_ind_open_imag = 0;
+-
+- /* Spaces from the prevailing indent for a line that is not preceded by
+- * an opening brace. */
+- buf->b_ind_no_brace = 0;
+-
+- /* Column where the first { of a function should be located }. */
+- buf->b_ind_first_open = 0;
+-
+- /* Spaces from the prevailing indent a leftmost open brace should be
+- * located. */
+- buf->b_ind_open_extra = 0;
+-
+- /* Spaces from the matching open brace (real location for one at the left
+- * edge; imaginary location from one that ends a line) the matching close
+- * brace should be located. */
+- buf->b_ind_close_extra = 0;
+-
+- /* Spaces from the edge of the line an open brace sitting in the leftmost
+- * column is imagined to be. */
+- buf->b_ind_open_left_imag = 0;
+-
+- /* Spaces jump labels should be shifted to the left if N is non-negative,
+- * otherwise the jump label will be put to column 1. */
+- buf->b_ind_jump_label = -1;
+-
+- /* Spaces from the switch() indent a "case xx" label should be located. */
+- buf->b_ind_case = sw;
+-
+- /* Spaces from the "case xx:" code after a switch() should be located. */
+- buf->b_ind_case_code = sw;
+-
+- /* Lineup break at end of case in switch() with case label. */
+- buf->b_ind_case_break = 0;
+-
+- /* Spaces from the class declaration indent a scope declaration label
+- * should be located. */
+- buf->b_ind_scopedecl = sw;
+-
+- /* Spaces from the scope declaration label code should be located. */
+- buf->b_ind_scopedecl_code = sw;
+-
+- /* Amount K&R-style parameters should be indented. */
+- buf->b_ind_param = sw;
+-
+- /* Amount a function type spec should be indented. */
+- buf->b_ind_func_type = sw;
+-
+- /* Amount a cpp base class declaration or constructor initialization
+- * should be indented. */
+- buf->b_ind_cpp_baseclass = sw;
+-
+- /* additional spaces beyond the prevailing indent a continuation line
+- * should be located. */
+- buf->b_ind_continuation = sw;
+-
+- /* Spaces from the indent of the line with an unclosed parentheses. */
+- buf->b_ind_unclosed = sw * 2;
+-
+- /* Spaces from the indent of the line with an unclosed parentheses, which
+- * itself is also unclosed. */
+- buf->b_ind_unclosed2 = sw;
+-
+- /* Suppress ignoring spaces from the indent of a line starting with an
+- * unclosed parentheses. */
+- buf->b_ind_unclosed_noignore = 0;
+-
+- /* If the opening paren is the last nonwhite character on the line, and
+- * b_ind_unclosed_wrapped is nonzero, use this indent relative to the outer
+- * context (for very long lines). */
+- buf->b_ind_unclosed_wrapped = 0;
+-
+- /* Suppress ignoring white space when lining up with the character after
+- * an unclosed parentheses. */
+- buf->b_ind_unclosed_whiteok = 0;
+-
+- /* Indent a closing parentheses under the line start of the matching
+- * opening parentheses. */
+- buf->b_ind_matching_paren = 0;
+-
+- /* Indent a closing parentheses under the previous line. */
+- buf->b_ind_paren_prev = 0;
+-
+- /* Extra indent for comments. */
+- buf->b_ind_comment = 0;
+-
+- /* Spaces from the comment opener when there is nothing after it. */
+- buf->b_ind_in_comment = 3;
+-
+- /* Boolean: if non-zero, use b_ind_in_comment even if there is something
+- * after the comment opener. */
+- buf->b_ind_in_comment2 = 0;
+-
+- /* Max lines to search for an open paren. */
+- buf->b_ind_maxparen = 20;
+-
+- /* Max lines to search for an open comment. */
+- buf->b_ind_maxcomment = 70;
+-
+- /* Handle braces for java code. */
+- buf->b_ind_java = 0;
+-
+- /* Not to confuse JS object properties with labels. */
+- buf->b_ind_js = 0;
+-
+- /* Handle blocked cases correctly. */
+- buf->b_ind_keep_case_label = 0;
+-
+- /* Handle C++ namespace. */
+- buf->b_ind_cpp_namespace = 0;
+-
+- /* Handle continuation lines containing conditions of if(), for() and
+- * while(). */
+- buf->b_ind_if_for_while = 0;
+-
+- /* indentation for # comments */
+- buf->b_ind_hash_comment = 0;
+-
+- /* Handle C++ extern "C" or "C++" */
+- buf->b_ind_cpp_extern_c = 0;
+-
+- for (p = buf->b_p_cino; *p; )
+- {
+- l = p++;
+- if (*p == '-')
+- ++p;
+- digits = p; /* remember where the digits start */
+- n = getdigits(&p);
+- divider = 0;
+- if (*p == '.') /* ".5s" means a fraction */
+- {
+- fraction = atol((char *)++p);
+- while (VIM_ISDIGIT(*p))
+- {
+- ++p;
+- if (divider)
+- divider *= 10;
+- else
+- divider = 10;
+- }
+- }
+- if (*p == 's') /* "2s" means two times 'shiftwidth' */
+- {
+- if (p == digits)
+- n = sw; /* just "s" is one 'shiftwidth' */
+- else
+- {
+- n *= sw;
+- if (divider)
+- n += (sw * fraction + divider / 2) / divider;
+- }
+- ++p;
+- }
+- if (l[1] == '-')
+- n = -n;
+-
+- /* When adding an entry here, also update the default 'cinoptions' in
+- * doc/indent.txt, and add explanation for it! */
+- switch (*l)
+- {
+- case '>': buf->b_ind_level = n; break;
+- case 'e': buf->b_ind_open_imag = n; break;
+- case 'n': buf->b_ind_no_brace = n; break;
+- case 'f': buf->b_ind_first_open = n; break;
+- case '{': buf->b_ind_open_extra = n; break;
+- case '}': buf->b_ind_close_extra = n; break;
+- case '^': buf->b_ind_open_left_imag = n; break;
+- case 'L': buf->b_ind_jump_label = n; break;
+- case ':': buf->b_ind_case = n; break;
+- case '=': buf->b_ind_case_code = n; break;
+- case 'b': buf->b_ind_case_break = n; break;
+- case 'p': buf->b_ind_param = n; break;
+- case 't': buf->b_ind_func_type = n; break;
+- case '/': buf->b_ind_comment = n; break;
+- case 'c': buf->b_ind_in_comment = n; break;
+- case 'C': buf->b_ind_in_comment2 = n; break;
+- case 'i': buf->b_ind_cpp_baseclass = n; break;
+- case '+': buf->b_ind_continuation = n; break;
+- case '(': buf->b_ind_unclosed = n; break;
+- case 'u': buf->b_ind_unclosed2 = n; break;
+- case 'U': buf->b_ind_unclosed_noignore = n; break;
+- case 'W': buf->b_ind_unclosed_wrapped = n; break;
+- case 'w': buf->b_ind_unclosed_whiteok = n; break;
+- case 'm': buf->b_ind_matching_paren = n; break;
+- case 'M': buf->b_ind_paren_prev = n; break;
+- case ')': buf->b_ind_maxparen = n; break;
+- case '*': buf->b_ind_maxcomment = n; break;
+- case 'g': buf->b_ind_scopedecl = n; break;
+- case 'h': buf->b_ind_scopedecl_code = n; break;
+- case 'j': buf->b_ind_java = n; break;
+- case 'J': buf->b_ind_js = n; break;
+- case 'l': buf->b_ind_keep_case_label = n; break;
+- case '#': buf->b_ind_hash_comment = n; break;
+- case 'N': buf->b_ind_cpp_namespace = n; break;
+- case 'k': buf->b_ind_if_for_while = n; break;
+- case 'E': buf->b_ind_cpp_extern_c = n; break;
+- }
+- if (*p == ',')
+- ++p;
+- }
+- }
+-
+- /*
+- * Return the desired indent for C code.
+- * Return -1 if the indent should be left alone (inside a raw string).
+- */
+- int
+- get_c_indent(void)
+- {
+- pos_T cur_curpos;
+- int amount;
+- int scope_amount;
+- int cur_amount = MAXCOL;
+- colnr_T col;
+- 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;
+- #define BRACE_IN_COL0 1 /* '{' is in column 0 */
+- #define BRACE_AT_START 2 /* '{' is at start of line */
+- #define BRACE_AT_END 3 /* '{' is at end of line */
+- linenr_T ourscope;
+- char_u *l;
+- char_u *look;
+- char_u terminated;
+- int lookfor;
+- #define LOOKFOR_INITIAL 0
+- #define LOOKFOR_IF 1
+- #define LOOKFOR_DO 2
+- #define LOOKFOR_CASE 3
+- #define LOOKFOR_ANY 4
+- #define LOOKFOR_TERM 5
+- #define LOOKFOR_UNTERM 6
+- #define LOOKFOR_SCOPEDECL 7
+- #define LOOKFOR_NOBREAK 8
+- #define LOOKFOR_CPP_BASECLASS 9
+- #define LOOKFOR_ENUM_OR_INIT 10
+- #define LOOKFOR_JS_KEY 11
+- #define LOOKFOR_COMMA 12
+-
+- int whilelevel;
+- linenr_T lnum;
+- int n;
+- int iscase;
+- int lookfor_break;
+- int lookfor_cpp_namespace = FALSE;
+- int cont_amount = 0; /* amount for continuation line */
+- int original_line_islabel;
+- int added_to_amount = 0;
+- int js_cur_has_key = 0;
+- linenr_T raw_string_start = 0;
+- cpp_baseclass_cache_T cache_cpp_baseclass = { FALSE, { MAXLNUM, 0 } };
+-
+- /* make a copy, value is changed below */
+- int ind_continuation = curbuf->b_ind_continuation;
+-
+- /* 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;
+-
+- /* Get a copy of the current contents of the line.
+- * This is required, because only the most recent line obtained with
+- * ml_get is valid! */
+- linecopy = vim_strsave(ml_get(cur_curpos.lnum));
+- if (linecopy == NULL)
+- return 0;
+-
+- /*
+- * In insert mode and the cursor is on a ')' truncate the line at the
+- * cursor position. We don't want to line up with the matching '(' when
+- * inserting new stuff.
+- * For unknown reasons the cursor might be past the end of the line, thus
+- * check for that.
+- */
+- if ((State & INSERT)
+- && curwin->w_cursor.col < (colnr_T)STRLEN(linecopy)
+- && linecopy[curwin->w_cursor.col] == ')')
+- linecopy[curwin->w_cursor.col] = NUL;
+-
+- theline = skipwhite(linecopy);
+-
+- /* move the cursor to the start of the line */
+-
+- curwin->w_cursor.col = 0;
+-
+- 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_POS(*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;
+- char_u lead_start[COM_MAX_LEN]; /* start-comment string */
+- char_u lead_middle[COM_MAX_LEN]; /* middle-comment string */
+- char_u lead_end[COM_MAX_LEN]; /* end-comment string */
+- char_u *p;
+- int start_align = 0;
+- int start_off = 0;
+- 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;
+-
+- p = curbuf->b_p_com;
+- while (*p != NUL)
+- {
+- int align = 0;
+- int off = 0;
+- int what = 0;
+-
+- while (*p != NUL && *p != ':')
+- {
+- if (*p == COM_START || *p == COM_END || *p == COM_MIDDLE)
+- what = *p++;
+- else if (*p == COM_LEFT || *p == COM_RIGHT)
+- align = *p++;
+- else if (VIM_ISDIGIT(*p) || *p == '-')
+- off = getdigits(&p);
+- else
+- ++p;
+- }
+-
+- if (*p == ':')
+- ++p;
+- (void)copy_option_part(&p, lead_end, COM_MAX_LEN, ",");
+- if (what == COM_START)
+- {
+- STRCPY(lead_start, lead_end);
+- lead_start_len = (int)STRLEN(lead_start);
+- start_off = off;
+- start_align = align;
+- }
+- else if (what == COM_MIDDLE)
+- {
+- STRCPY(lead_middle, lead_end);
+- lead_middle_len = (int)STRLEN(lead_middle);
+- }
+- else if (what == COM_END)
+- {
+- /* If our line starts with the middle comment string, line it
+- * up with the comment opener per the 'comments' option. */
+- if (STRNCMP(theline, lead_middle, lead_middle_len) == 0
+- && STRNCMP(theline, lead_end, STRLEN(lead_end)) != 0)
+- {
+- done = TRUE;
+- if (curwin->w_cursor.lnum > 1)
+- {
+- /* If the start comment string matches in the previous
+- * line, use the indent of that line plus offset. If
+- * the middle comment string matches in the previous
+- * line, use the indent of that line. XXX */
+- look = skipwhite(ml_get(curwin->w_cursor.lnum - 1));
+- if (STRNCMP(look, lead_start, lead_start_len) == 0)
+- amount = get_indent_lnum(curwin->w_cursor.lnum - 1);
+- else if (STRNCMP(look, lead_middle,
+- lead_middle_len) == 0)
+- {
+- amount = get_indent_lnum(curwin->w_cursor.lnum - 1);
+- break;
+- }
+- /* 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;
+- }
+- if (start_off != 0)
+- amount += start_off;
+- else if (start_align == COM_RIGHT)
+- amount += vim_strsize(lead_start)
+- - vim_strsize(lead_middle);
+- break;
+- }
+-
+- /* If our line starts with the end comment string, line it up
+- * with the middle comment */
+- if (STRNCMP(theline, lead_middle, lead_middle_len) != 0
+- && STRNCMP(theline, lead_end, STRLEN(lead_end)) == 0)
+- {
+- amount = get_indent_lnum(curwin->w_cursor.lnum - 1);
+- /* XXX */
+- if (off != 0)
+- amount += off;
+- else if (align == COM_RIGHT)
+- amount += vim_strsize(lead_start)
+- - vim_strsize(lead_middle);
+- done = TRUE;
+- break;
+- }
+- }
+- }
+-
+- /* If our line starts with an asterisk, line up with the
+- * asterisk in the comment opener; otherwise, line up
+- * with the first character of the comment text.
+- */
+- if (done)
+- ;
+- else if (theline[0] == '*')
+- amount += 1;
+- else
+- {
+- /*
+- * If we are more than one line away from the comment opener, take
+- * the indent of the previous non-empty line. If 'cino' has "CO"
+- * and we are just below the comment opener and there are any
+- * white characters after it line up with the text after it;
+- * 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;
+- amount = get_indent_lnum(lnum); /* XXX */
+- break;
+- }
+- if (amount == -1) /* use the comment opener */
+- {
+- 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)
+- {
+- if (trypos != NULL && tryposBrace != NULL)
+- {
+- /* Both an unmatched '(' and '{' is found. Use the one which is
+- * closer to the current cursor position, set the other to NULL. */
+- if (trypos->lnum != tryposBrace->lnum
+- ? trypos->lnum < tryposBrace->lnum
+- : trypos->col < tryposBrace->col)
+- trypos = NULL;
+- else
+- tryposBrace = NULL;
+- }
+-
+- if (trypos != NULL)
+- {
+- /*
+- * If the matching paren is more than one line away, use the indent of
+- * a previous non-empty line that matches the same paren.
+- */
+- if (theline[0] == ')' && curbuf->b_ind_paren_prev)
+- {
+- /* Line up with the start of the matching paren line. */
+- amount = get_indent_lnum(curwin->w_cursor.lnum - 1); /* XXX */
+- }
+- else
+- {
+- amount = -1;
+- our_paren_pos = *trypos;
+- for (lnum = cur_curpos.lnum - 1; lnum > our_paren_pos.lnum; --lnum)
+- {
+- l = skipwhite(ml_get(lnum));
+- if (cin_nocode(l)) /* skip comment lines */
+- continue;
+- if (cin_ispreproc_cont(&l, &lnum, &amount))
+- continue; /* ignore #define, #if, etc. */
+- curwin->w_cursor.lnum = lnum;
+-
+- /* Skip a comment or raw string. XXX */
+- if ((trypos = ind_find_start_CORS(NULL)) != NULL)
+- {
+- lnum = trypos->lnum + 1;
+- continue;
+- }
+-
+- /* XXX */
+- if ((trypos = find_match_paren(
+- corr_ind_maxparen(&cur_curpos))) != NULL
+- && trypos->lnum == our_paren_pos.lnum
+- && trypos->col == our_paren_pos.col)
+- {
+- amount = get_indent_lnum(lnum); /* XXX */
+-
+- if (theline[0] == ')')
+- {
+- if (our_paren_pos.lnum != lnum
+- && cur_amount > amount)
+- cur_amount = amount;
+- amount = -1;
+- }
+- break;
+- }
+- }
+- }
+-
+- /*
+- * Line up with line where the matching paren is. XXX
+- * If the line starts with a '(' or the indent for unclosed
+- * parentheses is zero, line up with the unclosed parentheses.
+- */
+- if (amount == -1)
+- {
+- int ignore_paren_col = 0;
+- int is_if_for_while = 0;
+-
+- if (curbuf->b_ind_if_for_while)
+- {
+- /* Look for the outermost opening parenthesis on this line
+- * and check whether it belongs to an "if", "for" or "while". */
+-
+- pos_T cursor_save = curwin->w_cursor;
+- pos_T outermost;
+- char_u *line;
+-
+- trypos = &our_paren_pos;
+- do {
+- outermost = *trypos;
+- curwin->w_cursor.lnum = outermost.lnum;
+- curwin->w_cursor.col = outermost.col;
+-
+- trypos = find_match_paren(curbuf->b_ind_maxparen);
+- } while (trypos && trypos->lnum == outermost.lnum);
+-
+- curwin->w_cursor = cursor_save;
+-
+- line = ml_get(outermost.lnum);
+-
+- is_if_for_while =
+- cin_is_if_for_while_before_offset(line, &outermost.col);
+- }
+-
+- amount = skip_label(our_paren_pos.lnum, &look);
+- look = skipwhite(look);
+- if (*look == '(')
+- {
+- linenr_T save_lnum = curwin->w_cursor.lnum;
+- char_u *line;
+- int look_col;
+-
+- /* Ignore a '(' in front of the line that has a match before
+- * our matching '('. */
+- curwin->w_cursor.lnum = our_paren_pos.lnum;
+- line = ml_get_curline();
+- look_col = (int)(look - line);
+- curwin->w_cursor.col = look_col + 1;
+- if ((trypos = findmatchlimit(NULL, ')', 0,
+- curbuf->b_ind_maxparen))
+- != NULL
+- && trypos->lnum == our_paren_pos.lnum
+- && trypos->col < our_paren_pos.col)
+- ignore_paren_col = trypos->col + 1;
+-
+- curwin->w_cursor.lnum = save_lnum;
+- look = ml_get(our_paren_pos.lnum) + look_col;
+- }
+- if (theline[0] == ')' || (curbuf->b_ind_unclosed == 0
+- && is_if_for_while == 0)
+- || (!curbuf->b_ind_unclosed_noignore && *look == '('
+- && ignore_paren_col == 0))
+- {
+- /*
+- * If we're looking at a close paren, line up right there;
+- * otherwise, line up with the next (non-white) character.
+- * When b_ind_unclosed_wrapped is set and the matching paren is
+- * the last nonwhite character of the line, use either the
+- * indent of the current line or the indentation of the next
+- * outer paren and add b_ind_unclosed_wrapped (for very long
+- * lines).
+- */
+- if (theline[0] != ')')
+- {
+- cur_amount = MAXCOL;
+- l = ml_get(our_paren_pos.lnum);
+- if (curbuf->b_ind_unclosed_wrapped
+- && cin_ends_in(l, (char_u *)"(", NULL))
+- {
+- /* look for opening unmatched paren, indent one level
+- * for each additional level */
+- n = 1;
+- for (col = 0; col < our_paren_pos.col; ++col)
+- {
+- switch (l[col])
+- {
+- case '(':
+- case '{': ++n;
+- break;
+-
+- case ')':
+- case '}': if (n > 1)
+- --n;
+- break;
+- }
+- }
+-
+- our_paren_pos.col = 0;
+- amount += n * curbuf->b_ind_unclosed_wrapped;
+- }
+- else if (curbuf->b_ind_unclosed_whiteok)
+- our_paren_pos.col++;
+- else
+- {
+- col = our_paren_pos.col + 1;
+- while (VIM_ISWHITE(l[col]))
+- col++;
+- if (l[col] != NUL) /* In case of trailing space */
+- our_paren_pos.col = col;
+- else
+- our_paren_pos.col++;
+- }
+- }
+-
+- /*
+- * Find how indented the paren is, or the character after it
+- * if we did the above "if".
+- */
+- if (our_paren_pos.col > 0)
+- {
+- getvcol(curwin, &our_paren_pos, &col, NULL, NULL);
+- if (cur_amount > (int)col)
+- cur_amount = col;
+- }
+- }
+-
+- if (theline[0] == ')' && curbuf->b_ind_matching_paren)
+- {
+- /* Line up with the start of the matching paren line. */
+- }
+- else if ((curbuf->b_ind_unclosed == 0 && is_if_for_while == 0)
+- || (!curbuf->b_ind_unclosed_noignore
+- && *look == '(' && ignore_paren_col == 0))
+- {
+- if (cur_amount != MAXCOL)
+- amount = cur_amount;
+- }
+- else
+- {
+- /* Add b_ind_unclosed2 for each '(' before our matching one,
+- * but ignore (void) before the line (ignore_paren_col). */
+- col = our_paren_pos.col;
+- while ((int)our_paren_pos.col > ignore_paren_col)
+- {
+- --our_paren_pos.col;
+- switch (*ml_get_pos(&our_paren_pos))
+- {
+- case '(': amount += curbuf->b_ind_unclosed2;
+- col = our_paren_pos.col;
+- break;
+- case ')': amount -= curbuf->b_ind_unclosed2;
+- col = MAXCOL;
+- break;
+- }
+- }
+-
+- /* Use b_ind_unclosed once, when the first '(' is not inside
+- * braces */
+- if (col == MAXCOL)
+- amount += curbuf->b_ind_unclosed;
+- else
+- {
+- curwin->w_cursor.lnum = our_paren_pos.lnum;
+- curwin->w_cursor.col = col;
+- if (find_match_paren_after_brace(curbuf->b_ind_maxparen)
+- != NULL)
+- amount += curbuf->b_ind_unclosed2;
+- else
+- {
+- if (is_if_for_while)
+- amount += curbuf->b_ind_if_for_while;
+- else
+- amount += curbuf->b_ind_unclosed;
+- }
+- }
+- /*
+- * For a line starting with ')' use the minimum of the two
+- * positions, to avoid giving it more indent than the previous
+- * lines:
+- * func_long_name( if (x
+- * arg && yy
+- * ) ^ not here ) ^ not here
+- */
+- if (cur_amount < amount)
+- amount = cur_amount;
+- }
+- }
+-
+- /* add extra indent for a comment */
+- if (cin_iscomment(theline))
+- amount += curbuf->b_ind_comment;
+- }
+- else
+- {
+- /*
+- * We are inside braces, there is a { before this line at the position
+- * stored in tryposBrace.
+- * 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);
+-
+- /*
+- * Now figure out how indented the line is in general.
+- * If the brace was at the start of the line, we use that;
+- * otherwise, check out the indentation of the line as
+- * a whole and then add the "imaginary indent" to that.
+- */
+- look = skipwhite(start);
+- if (*look == '{')
+- {
+- getvcol(curwin, trypos, &col, NULL, NULL);
+- amount = col;
+- if (*start == '{')
+- start_brace = BRACE_IN_COL0;
+- else
+- start_brace = BRACE_AT_START;
+- }
+- else
+- {
+- /* That opening brace might have been on a continuation
+- * line. if so, find the start of the line. */
+- curwin->w_cursor.lnum = ourscope;
+-
+- /* Position the cursor over the rightmost paren, so that
+- * matching it will take us back to the start of the line. */
+- lnum = ourscope;
+- if (find_last_paren(start, '(', ')')
+- && (trypos = find_match_paren(curbuf->b_ind_maxparen))
+- != NULL)
+- lnum = trypos->lnum;
+-
+- /* It could have been something like
+- * case 1: if (asdf &&
+- * ldfd) {
+- * }
+- */
+- if ((curbuf->b_ind_js || curbuf->b_ind_keep_case_label)
+- && cin_iscase(skipwhite(ml_get_curline()), FALSE))
+- amount = get_indent();
+- else if (curbuf->b_ind_js)
+- amount = get_indent_lnum(lnum);
+- else
+- amount = skip_label(lnum, &l);
+-
+- start_brace = BRACE_AT_END;
+- }
+-
+- /* For Javascript check if the line starts with "key:". */
+- if (curbuf->b_ind_js)
+- js_cur_has_key = cin_has_js_key(theline);
+-
+- /*
+- * If we're looking at a closing brace, that's where
+- * we want to be. otherwise, add the amount of room
+- * that an indent is supposed to be.
+- */
+- if (theline[0] == '}')
+- {
+- /*
+- * they may want closing braces to line up with something
+- * other than the open brace. indulge them, if so.
+- */
+- amount += curbuf->b_ind_close_extra;
+- }
+- else
+- {
+- /*
+- * If we're looking at an "else", try to find an "if"
+- * to match it with.
+- * If we're looking at a "while", try to find a "do"
+- * to match it with.
+- */
+- lookfor = LOOKFOR_INITIAL;
+- if (cin_iselse(theline))
+- lookfor = LOOKFOR_IF;
+- else if (cin_iswhileofdo(theline, cur_curpos.lnum)) /* XXX */
+- lookfor = LOOKFOR_DO;
+- if (lookfor != LOOKFOR_INITIAL)
+- {
+- curwin->w_cursor.lnum = cur_curpos.lnum;
+- if (find_match(lookfor, ourscope) == OK)
+- {
+- amount = get_indent(); /* XXX */
+- goto theend;
+- }
+- }
+-
+- /*
+- * We get here if we are not on an "while-of-do" or "else" (or
+- * failed to find a matching "if").
+- * Search backwards for something to line up with.
+- * First set amount for when we don't find anything.
+- */
+-
+- /*
+- * if the '{' is _really_ at the left margin, use the imaginary
+- * location of a left-margin brace. Otherwise, correct the
+- * location for b_ind_open_extra.
+- */
+-
+- if (start_brace == BRACE_IN_COL0) /* '{' is in column 0 */
+- {
+- amount = curbuf->b_ind_open_left_imag;
+- lookfor_cpp_namespace = TRUE;
+- }
+- else if (start_brace == BRACE_AT_START &&
+- lookfor_cpp_namespace) /* '{' is at start */
+- {
+-
+- lookfor_cpp_namespace = TRUE;
+- }
+- else
+- {
+- if (start_brace == BRACE_AT_END) /* '{' is at end of line */
+- {
+- amount += curbuf->b_ind_open_imag;
+-
+- l = skipwhite(ml_get_curline());
+- if (cin_is_cpp_namespace(l))
+- amount += curbuf->b_ind_cpp_namespace;
+- else if (cin_is_cpp_extern_c(l))
+- amount += curbuf->b_ind_cpp_extern_c;
+- }
+- else
+- {
+- /* Compensate for adding b_ind_open_extra later. */
+- amount -= curbuf->b_ind_open_extra;
+- if (amount < 0)
+- amount = 0;
+- }
+- }
+-
+- lookfor_break = FALSE;
+-
+- if (cin_iscase(theline, FALSE)) /* it's a switch() label */
+- {
+- lookfor = LOOKFOR_CASE; /* find a previous switch() label */
+- amount += curbuf->b_ind_case;
+- }
+- else if (cin_isscopedecl(theline)) /* private:, ... */
+- {
+- lookfor = LOOKFOR_SCOPEDECL; /* class decl is this block */
+- amount += curbuf->b_ind_scopedecl;
+- }
+- else
+- {
+- if (curbuf->b_ind_case_break && cin_isbreak(theline))
+- /* break; ... */
+- lookfor_break = TRUE;
+-
+- lookfor = LOOKFOR_INITIAL;
+- /* b_ind_level from start of block */
+- amount += curbuf->b_ind_level;
+- }
+- scope_amount = amount;
+- whilelevel = 0;
+-
+- /*
+- * Search backwards. If we find something we recognize, line up
+- * with that.
+- *
+- * If we're looking at an open brace, indent
+- * the usual amount relative to the conditional
+- * that opens the block.
+- */
+- curwin->w_cursor = cur_curpos;
+- for (;;)
+- {
+- curwin->w_cursor.lnum--;
+- curwin->w_cursor.col = 0;
+-
+- /*
+- * If we went all the way back to the start of our scope, line
+- * up with it.
+- */
+- if (curwin->w_cursor.lnum <= ourscope)
+- {
+- /* We reached end of scope:
+- * If looking for a enum or structure initialization
+- * go further back:
+- * If it is an initializer (enum xxx or xxx =), then
+- * don't add ind_continuation, otherwise it is a variable
+- * declaration:
+- * int x,
+- * here; <-- add ind_continuation
+- */
+- if (lookfor == LOOKFOR_ENUM_OR_INIT)
+- {
+- if (curwin->w_cursor.lnum == 0
+- || curwin->w_cursor.lnum
+- < ourscope - curbuf->b_ind_maxparen)
+- {
+- /* nothing found (abuse curbuf->b_ind_maxparen as
+- * limit) assume terminated line (i.e. a variable
+- * initialization) */
+- if (cont_amount > 0)
+- amount = cont_amount;
+- else if (!curbuf->b_ind_js)
+- amount += ind_continuation;
+- break;
+- }
+-
+- 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(NULL);
+- if (trypos != NULL)
+- {
+- curwin->w_cursor.lnum = trypos->lnum + 1;
+- curwin->w_cursor.col = 0;
+- continue;
+- }
+-
+- /*
+- * Skip preprocessor directives and blank lines.
+- */
+- if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum,
+- &amount))
+- continue;
+-
+- if (cin_nocode(l))
+- continue;
+-
+- terminated = cin_isterminated(l, FALSE, TRUE);
+-
+- /*
+- * If we are at top level and the line looks like a
+- * function declaration, we are done
+- * (it's a variable declaration).
+- */
+- if (start_brace != BRACE_IN_COL0
+- || !cin_isfuncdecl(&l, curwin->w_cursor.lnum, 0))
+- {
+- /* if the line is terminated with another ','
+- * it is a continued variable initialization.
+- * don't add extra indent.
+- * TODO: does not work, if a function
+- * declaration is split over multiple lines:
+- * cin_isfuncdecl returns FALSE then.
+- */
+- if (terminated == ',')
+- break;
+-
+- /* if it es a enum declaration or an assignment,
+- * we are done.
+- */
+- if (terminated != ';' && cin_isinit())
+- break;
+-
+- /* nothing useful found */
+- if (terminated == 0 || terminated == '{')
+- continue;
+- }
+-
+- if (terminated != ';')
+- {
+- /* Skip parens and braces. Position the cursor
+- * over the rightmost paren, so that matching it
+- * will take us back to the start of the line.
+- */ /* XXX */
+- trypos = NULL;
+- if (find_last_paren(l, '(', ')'))
+- trypos = find_match_paren(
+- curbuf->b_ind_maxparen);
+-
+- if (trypos == NULL && find_last_paren(l, '{', '}'))
+- trypos = find_start_brace();
+-
+- if (trypos != NULL)
+- {
+- curwin->w_cursor.lnum = trypos->lnum + 1;
+- curwin->w_cursor.col = 0;
+- continue;
+- }
+- }
+-
+- /* it's a variable declaration, add indentation
+- * like in
+- * int a,
+- * b;
+- */
+- if (cont_amount > 0)
+- amount = cont_amount;
+- else
+- amount += ind_continuation;
+- }
+- else if (lookfor == LOOKFOR_UNTERM)
+- {
+- if (cont_amount > 0)
+- amount = cont_amount;
+- else
+- amount += ind_continuation;
+- }
+- else
+- {
+- if (lookfor != LOOKFOR_TERM
+- && lookfor != LOOKFOR_CPP_BASECLASS
+- && lookfor != LOOKFOR_COMMA)
+- {
+- amount = scope_amount;
+- if (theline[0] == '{')
+- {
+- amount += curbuf->b_ind_open_extra;
+- added_to_amount = curbuf->b_ind_open_extra;
+- }
+- }
+-
+- if (lookfor_cpp_namespace)
+- {
+- /*
+- * Looking for C++ namespace, need to look further
+- * back.
+- */
+- if (curwin->w_cursor.lnum == ourscope)
+- continue;
+-
+- if (curwin->w_cursor.lnum == 0
+- || curwin->w_cursor.lnum
+- < ourscope - FIND_NAMESPACE_LIM)
+- break;
+-
+- 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(NULL);
+- if (trypos != NULL)
+- {
+- curwin->w_cursor.lnum = trypos->lnum + 1;
+- curwin->w_cursor.col = 0;
+- continue;
+- }
+-
+- /* Skip preprocessor directives and blank lines. */
+- if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum,
+- &amount))
+- continue;
+-
+- /* Finally the actual check for "namespace". */
+- if (cin_is_cpp_namespace(l))
+- {
+- amount += curbuf->b_ind_cpp_namespace
+- - added_to_amount;
+- break;
+- }
+- else if (cin_is_cpp_extern_c(l))
+- {
+- amount += curbuf->b_ind_cpp_extern_c
+- - added_to_amount;
+- break;
+- }
+-
+- if (cin_nocode(l))
+- continue;
+- }
+- }
+- break;
+- }
+-
+- /*
+- * If we're in a comment or raw string now, skip to the start
+- * of it.
+- */ /* XXX */
+- if ((trypos = ind_find_start_CORS(&raw_string_start)) != NULL)
+- {
+- curwin->w_cursor.lnum = trypos->lnum + 1;
+- curwin->w_cursor.col = 0;
+- continue;
+- }
+-
+- l = ml_get_curline();
+-
+- /*
+- * If this is a switch() label, may line up relative to that.
+- * If this is a C++ scope declaration, do the same.
+- */
+- iscase = cin_iscase(l, FALSE);
+- if (iscase || cin_isscopedecl(l))
+- {
+- /* we are only looking for cpp base class
+- * declaration/initialization any longer */
+- if (lookfor == LOOKFOR_CPP_BASECLASS)
+- break;
+-
+- /* When looking for a "do" we are not interested in
+- * labels. */
+- if (whilelevel > 0)
+- continue;
+-
+- /*
+- * case xx:
+- * c = 99 + <- this indent plus continuation
+- *-> here;
+- */
+- if (lookfor == LOOKFOR_UNTERM
+- || lookfor == LOOKFOR_ENUM_OR_INIT)
+- {
+- if (cont_amount > 0)
+- amount = cont_amount;
+- else
+- amount += ind_continuation;
+- break;
+- }
+-
+- /*
+- * case xx: <- line up with this case
+- * x = 333;
+- * case yy:
+- */
+- if ( (iscase && lookfor == LOOKFOR_CASE)
+- || (iscase && lookfor_break)
+- || (!iscase && lookfor == LOOKFOR_SCOPEDECL))
+- {
+- /*
+- * Check that this case label is not for another
+- * switch()
+- */ /* XXX */
+- if ((trypos = find_start_brace()) == NULL
+- || trypos->lnum == ourscope)
+- {
+- amount = get_indent(); /* XXX */
+- break;
+- }
+- continue;
+- }
+-
+- n = get_indent_nolabel(curwin->w_cursor.lnum); /* XXX */
+-
+- /*
+- * case xx: if (cond) <- line up with this if
+- * y = y + 1;
+- * -> s = 99;
+- *
+- * case xx:
+- * if (cond) <- line up with this line
+- * y = y + 1;
+- * -> s = 99;
+- */
+- if (lookfor == LOOKFOR_TERM)
+- {
+- if (n)
+- amount = n;
+-
+- if (!lookfor_break)
+- break;
+- }
+-
+- /*
+- * case xx: x = x + 1; <- line up with this x
+- * -> y = y + 1;
+- *
+- * case xx: if (cond) <- line up with this if
+- * -> y = y + 1;
+- */
+- if (n)
+- {
+- amount = n;
+- l = after_label(ml_get_curline());
+- if (l != NULL && cin_is_cinword(l))
+- {
+- if (theline[0] == '{')
+- amount += curbuf->b_ind_open_extra;
+- else
+- amount += curbuf->b_ind_level
+- + curbuf->b_ind_no_brace;
+- }
+- break;
+- }
+-
+- /*
+- * Try to get the indent of a statement before the switch
+- * label. If nothing is found, line up relative to the
+- * switch label.
+- * break; <- may line up with this line
+- * case xx:
+- * -> y = 1;
+- */
+- scope_amount = get_indent() + (iscase /* XXX */
+- ? curbuf->b_ind_case_code
+- : curbuf->b_ind_scopedecl_code);
+- lookfor = curbuf->b_ind_case_break
+- ? LOOKFOR_NOBREAK : LOOKFOR_ANY;
+- continue;
+- }
+-
+- /*
+- * Looking for a switch() label or C++ scope declaration,
+- * ignore other lines, skip {}-blocks.
+- */
+- if (lookfor == LOOKFOR_CASE || lookfor == LOOKFOR_SCOPEDECL)
+- {
+- if (find_last_paren(l, '{', '}')
+- && (trypos = find_start_brace()) != NULL)
+- {
+- curwin->w_cursor.lnum = trypos->lnum + 1;
+- curwin->w_cursor.col = 0;
+- }
+- continue;
+- }
+-
+- /*
+- * Ignore jump labels with nothing after them.
+- */
+- if (!curbuf->b_ind_js && cin_islabel())
+- {
+- l = after_label(ml_get_curline());
+- if (l == NULL || cin_nocode(l))
+- continue;
+- }
+-
+- /*
+- * Ignore #defines, #if, etc.
+- * Ignore comment and empty lines.
+- * (need to get the line again, cin_islabel() may have
+- * unlocked it)
+- */
+- l = ml_get_curline();
+- if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum, &amount)
+- || cin_nocode(l))
+- continue;
+-
+- /*
+- * Are we at the start of a cpp base class declaration or
+- * constructor initialization?
+- */ /* XXX */
+- n = FALSE;
+- if (lookfor != LOOKFOR_TERM && curbuf->b_ind_cpp_baseclass > 0)
+- {
+- n = cin_is_cpp_baseclass(&cache_cpp_baseclass);
+- l = ml_get_curline();
+- }
+- if (n)
+- {
+- if (lookfor == LOOKFOR_UNTERM)
+- {
+- if (cont_amount > 0)
+- amount = cont_amount;
+- else
+- amount += ind_continuation;
+- }
+- else if (theline[0] == '{')
+- {
+- /* Need to find start of the declaration. */
+- lookfor = LOOKFOR_UNTERM;
+- ind_continuation = 0;
+- continue;
+- }
+- else
+- /* XXX */
+- amount = get_baseclass_amount(
+- cache_cpp_baseclass.lpos.col);
+- break;
+- }
+- else if (lookfor == LOOKFOR_CPP_BASECLASS)
+- {
+- /* only look, whether there is a cpp base class
+- * declaration or initialization before the opening brace.
+- */
+- if (cin_isterminated(l, TRUE, FALSE))
+- break;
+- else
+- continue;
+- }
+-
+- /*
+- * What happens next depends on the line being terminated.
+- * If terminated with a ',' only consider it terminating if
+- * there is another unterminated statement behind, eg:
+- * 123,
+- * sizeof
+- * here
+- * Otherwise check whether it is a enumeration or structure
+- * initialisation (not indented) or a variable declaration
+- * (indented).
+- */
+- terminated = cin_isterminated(l, FALSE, TRUE);
+-
+- if (js_cur_has_key)
+- {
+- js_cur_has_key = 0; /* only check the first line */
+- if (curbuf->b_ind_js && terminated == ',')
+- {
+- /* For Javascript we might be inside an object:
+- * key: something, <- align with this
+- * key: something
+- * or:
+- * key: something + <- align with this
+- * something,
+- * key: something
+- */
+- lookfor = LOOKFOR_JS_KEY;
+- }
+- }
+- if (lookfor == LOOKFOR_JS_KEY && cin_has_js_key(l))
+- {
+- amount = get_indent();
+- break;
+- }
+- if (lookfor == LOOKFOR_COMMA)
+- {
+- if (tryposBrace != NULL && tryposBrace->lnum
+- >= curwin->w_cursor.lnum)
+- break;
+- if (terminated == ',')
+- /* line below current line is the one that starts a
+- * (possibly broken) line ending in a comma. */
+- break;
+- else
+- {
+- amount = get_indent();
+- if (curwin->w_cursor.lnum - 1 == ourscope)
+- /* line above is start of the scope, thus current
+- * line is the one that stars a (possibly broken)
+- * line ending in a comma. */
+- break;
+- }
+- }
+-
+- if (terminated == 0 || (lookfor != LOOKFOR_UNTERM
+- && terminated == ','))
+- {
+- if (lookfor != LOOKFOR_ENUM_OR_INIT &&
+- (*skipwhite(l) == '[' || l[STRLEN(l) - 1] == '['))
+- amount += ind_continuation;
+- /*
+- * if we're in the middle of a paren thing,
+- * go back to the line that starts it so
+- * we can get the right prevailing indent
+- * if ( foo &&
+- * bar )
+- */
+- /*
+- * Position the cursor over the rightmost paren, so that
+- * matching it will take us back to the start of the line.
+- * Ignore a match before the start of the block.
+- */
+- (void)find_last_paren(l, '(', ')');
+- trypos = find_match_paren(corr_ind_maxparen(&cur_curpos));
+- if (trypos != NULL && (trypos->lnum < tryposBrace->lnum
+- || (trypos->lnum == tryposBrace->lnum
+- && trypos->col < tryposBrace->col)))
+- trypos = NULL;
+-
+- /*
+- * If we are looking for ',', we also look for matching
+- * braces.
+- */
+- if (trypos == NULL && terminated == ','
+- && find_last_paren(l, '{', '}'))
+- trypos = find_start_brace();
+-
+- if (trypos != NULL)
+- {
+- /*
+- * Check if we are on a case label now. This is
+- * handled above.
+- * case xx: if ( asdf &&
+- * asdf)
+- */
+- curwin->w_cursor = *trypos;
+- l = ml_get_curline();
+- if (cin_iscase(l, FALSE) || cin_isscopedecl(l))
+- {
+- ++curwin->w_cursor.lnum;
+- curwin->w_cursor.col = 0;
+- continue;
+- }
+- }
+-
+- /*
+- * Skip over continuation lines to find the one to get the
+- * indent from
+- * char *usethis = "bla\
+- * bla",
+- * here;
+- */
+- if (terminated == ',')
+- {
+- while (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;
+- }
+- }
+-
+- /*
+- * Get indent and pointer to text for current line,
+- * ignoring any jump label. XXX
+- */
+- if (curbuf->b_ind_js)
+- cur_amount = get_indent();
+- else
+- cur_amount = skip_label(curwin->w_cursor.lnum, &l);
+- /*
+- * If this is just above the line we are indenting, and it
+- * starts with a '{', line it up with this line.
+- * while (not)
+- * -> {
+- * }
+- */
+- if (terminated != ',' && lookfor != LOOKFOR_TERM
+- && theline[0] == '{')
+- {
+- amount = cur_amount;
+- /*
+- * Only add b_ind_open_extra when the current line
+- * doesn't start with a '{', which must have a match
+- * in the same line (scope is the same). Probably:
+- * { 1, 2 },
+- * -> { 3, 4 }
+- */
+- if (*skipwhite(l) != '{')
+- amount += curbuf->b_ind_open_extra;
+-
+- if (curbuf->b_ind_cpp_baseclass && !curbuf->b_ind_js)
+- {
+- /* have to look back, whether it is a cpp base
+- * class declaration or initialization */
+- lookfor = LOOKFOR_CPP_BASECLASS;
+- continue;
+- }
+- break;
+- }
+-
+- /*
+- * Check if we are after an "if", "while", etc.
+- * Also allow " } else".
+- */
+- if (cin_is_cinword(l) || cin_iselse(skipwhite(l)))
+- {
+- /*
+- * Found an unterminated line after an if (), line up
+- * with the last one.
+- * if (cond)
+- * 100 +
+- * -> here;
+- */
+- if (lookfor == LOOKFOR_UNTERM
+- || lookfor == LOOKFOR_ENUM_OR_INIT)
+- {
+- if (cont_amount > 0)
+- amount = cont_amount;
+- else
+- amount += ind_continuation;
+- break;
+- }
+-
+- /*
+- * If this is just above the line we are indenting, we
+- * are finished.
+- * while (not)
+- * -> here;
+- * Otherwise this indent can be used when the line
+- * before this is terminated.
+- * yyy;
+- * if (stat)
+- * while (not)
+- * xxx;
+- * -> here;
+- */
+- amount = cur_amount;
+- if (theline[0] == '{')
+- amount += curbuf->b_ind_open_extra;
+- if (lookfor != LOOKFOR_TERM)
+- {
+- amount += curbuf->b_ind_level
+- + curbuf->b_ind_no_brace;
+- break;
+- }
+-
+- /*
+- * Special trick: when expecting the while () after a
+- * do, line up with the while()
+- * do
+- * x = 1;
+- * -> here
+- */
+- l = skipwhite(ml_get_curline());
+- if (cin_isdo(l))
+- {
+- if (whilelevel == 0)
+- break;
+- --whilelevel;
+- }
+-
+- /*
+- * When searching for a terminated line, don't use the
+- * one between the "if" and the matching "else".
+- * Need to use the scope of this "else". XXX
+- * If whilelevel != 0 continue looking for a "do {".
+- */
+- if (cin_iselse(l) && whilelevel == 0)
+- {
+- /* If we're looking at "} else", let's make sure we
+- * find the opening brace of the enclosing scope,
+- * not the one from "if () {". */
+- if (*l == '}')
+- curwin->w_cursor.col =
+- (colnr_T)(l - ml_get_curline()) + 1;
+-
+- if ((trypos = find_start_brace()) == NULL
+- || find_match(LOOKFOR_IF, trypos->lnum)
+- == FAIL)
+- break;
+- }
+- }
+-
+- /*
+- * If we're below an unterminated line that is not an
+- * "if" or something, we may line up with this line or
+- * add something for a continuation line, depending on
+- * the line before this one.
+- */
+- else
+- {
+- /*
+- * Found two unterminated lines on a row, line up with
+- * the last one.
+- * c = 99 +
+- * 100 +
+- * -> here;
+- */
+- if (lookfor == LOOKFOR_UNTERM)
+- {
+- /* When line ends in a comma add extra indent */
+- if (terminated == ',')
+- amount += ind_continuation;
+- break;
+- }
+-
+- if (lookfor == LOOKFOR_ENUM_OR_INIT)
+- {
+- /* Found two lines ending in ',', lineup with the
+- * lowest one, but check for cpp base class
+- * declaration/initialization, if it is an
+- * opening brace or we are looking just for
+- * enumerations/initializations. */
+- if (terminated == ',')
+- {
+- if (curbuf->b_ind_cpp_baseclass == 0)
+- break;
+-
+- lookfor = LOOKFOR_CPP_BASECLASS;
+- continue;
+- }
+-
+- /* Ignore unterminated lines in between, but
+- * reduce indent. */
+- if (amount > cur_amount)
+- amount = cur_amount;
+- }
+- else
+- {
+- /*
+- * Found first unterminated line on a row, may
+- * line up with this line, remember its indent
+- * 100 +
+- * -> here;
+- */
+- l = ml_get_curline();
+- amount = cur_amount;
+-
+- n = (int)STRLEN(l);
+- if (terminated == ',' && (*skipwhite(l) == ']'
+- || (n >=2 && l[n - 2] == ']')))
+- break;
+-
+- /*
+- * If previous line ends in ',', check whether we
+- * are in an initialization or enum
+- * struct xxx =
+- * {
+- * sizeof a,
+- * 124 };
+- * or a normal possible continuation line.
+- * but only, of no other statement has been found
+- * yet.
+- */
+- if (lookfor == LOOKFOR_INITIAL && terminated == ',')
+- {
+- if (curbuf->b_ind_js)
+- {
+- /* Search for a line ending in a comma
+- * and line up with the line below it
+- * (could be the current line).
+- * some = [
+- * 1, <- line up here
+- * 2,
+- * some = [
+- * 3 + <- line up here
+- * 4 *
+- * 5,
+- * 6,
+- */
+- if (cin_iscomment(skipwhite(l)))
+- break;
+- lookfor = LOOKFOR_COMMA;
+- trypos = find_match_char('[',
+- curbuf->b_ind_maxparen);
+- if (trypos != NULL)
+- {
+- if (trypos->lnum
+- == curwin->w_cursor.lnum - 1)
+- {
+- /* Current line is first inside
+- * [], line up with it. */
+- break;
+- }
+- ourscope = trypos->lnum;
+- }
+- }
+- else
+- {
+- lookfor = LOOKFOR_ENUM_OR_INIT;
+- cont_amount = cin_first_id_amount();
+- }
+- }
+- else
+- {
+- if (lookfor == LOOKFOR_INITIAL
+- && *l != NUL
+- && l[STRLEN(l) - 1] == '\\')
+- /* XXX */
+- cont_amount = cin_get_equal_amount(
+- curwin->w_cursor.lnum);
+- if (lookfor != LOOKFOR_TERM
+- && lookfor != LOOKFOR_JS_KEY
+- && lookfor != LOOKFOR_COMMA
+- && raw_string_start != curwin->w_cursor.lnum)
+- lookfor = LOOKFOR_UNTERM;
+- }
+- }
+- }
+- }
+-
+- /*
+- * Check if we are after a while (cond);
+- * If so: Ignore until the matching "do".
+- */
+- else if (cin_iswhileofdo_end(terminated)) /* XXX */
+- {
+- /*
+- * Found an unterminated line after a while ();, line up
+- * with the last one.
+- * while (cond);
+- * 100 + <- line up with this one
+- * -> here;
+- */
+- if (lookfor == LOOKFOR_UNTERM
+- || lookfor == LOOKFOR_ENUM_OR_INIT)
+- {
+- if (cont_amount > 0)
+- amount = cont_amount;
+- else
+- amount += ind_continuation;
+- break;
+- }
+-
+- if (whilelevel == 0)
+- {
+- lookfor = LOOKFOR_TERM;
+- amount = get_indent(); /* XXX */
+- if (theline[0] == '{')
+- amount += curbuf->b_ind_open_extra;
+- }
+- ++whilelevel;
+- }
+-
+- /*
+- * We are after a "normal" statement.
+- * If we had another statement we can stop now and use the
+- * indent of that other statement.
+- * Otherwise the indent of the current statement may be used,
+- * search backwards for the next "normal" statement.
+- */
+- else
+- {
+- /*
+- * Skip single break line, if before a switch label. It
+- * may be lined up with the case label.
+- */
+- if (lookfor == LOOKFOR_NOBREAK
+- && cin_isbreak(skipwhite(ml_get_curline())))
+- {
+- lookfor = LOOKFOR_ANY;
+- continue;
+- }
+-
+- /*
+- * Handle "do {" line.
+- */
+- if (whilelevel > 0)
+- {
+- l = cin_skipcomment(ml_get_curline());
+- if (cin_isdo(l))
+- {
+- amount = get_indent(); /* XXX */
+- --whilelevel;
+- continue;
+- }
+- }
+-
+- /*
+- * Found a terminated line above an unterminated line. Add
+- * the amount for a continuation line.
+- * x = 1;
+- * y = foo +
+- * -> here;
+- * or
+- * int x = 1;
+- * int foo,
+- * -> here;
+- */
+- if (lookfor == LOOKFOR_UNTERM
+- || lookfor == LOOKFOR_ENUM_OR_INIT)
+- {
+- if (cont_amount > 0)
+- amount = cont_amount;
+- else
+- amount += ind_continuation;
+- break;
+- }
+-
+- /*
+- * Found a terminated line above a terminated line or "if"
+- * etc. line. Use the amount of the line below us.
+- * x = 1; x = 1;
+- * if (asdf) y = 2;
+- * while (asdf) ->here;
+- * here;
+- * ->foo;
+- */
+- if (lookfor == LOOKFOR_TERM)
+- {
+- if (!lookfor_break && whilelevel == 0)
+- break;
+- }
+-
+- /*
+- * First line above the one we're indenting is terminated.
+- * To know what needs to be done look further backward for
+- * a terminated line.
+- */
+- else
+- {
+- /*
+- * position the cursor over the rightmost paren, so
+- * that matching it will take us back to the start of
+- * the line. Helps for:
+- * func(asdr,
+- * asdfasdf);
+- * here;
+- */
+- term_again:
+- l = ml_get_curline();
+- if (find_last_paren(l, '(', ')')
+- && (trypos = find_match_paren(
+- curbuf->b_ind_maxparen)) != NULL)
+- {
+- /*
+- * Check if we are on a case label now. This is
+- * handled above.
+- * case xx: if ( asdf &&
+- * asdf)
+- */
+- curwin->w_cursor = *trypos;
+- l = ml_get_curline();
+- if (cin_iscase(l, FALSE) || cin_isscopedecl(l))
+- {
+- ++curwin->w_cursor.lnum;
+- curwin->w_cursor.col = 0;
+- continue;
+- }
+- }
+-
+- /* When aligning with the case statement, don't align
+- * with a statement after it.
+- * case 1: { <-- don't use this { position
+- * stat;
+- * }
+- * case 2:
+- * stat;
+- * }
+- */
+- iscase = (curbuf->b_ind_keep_case_label
+- && cin_iscase(l, FALSE));
+-
+- /*
+- * Get indent and pointer to text for current line,
+- * ignoring any jump label.
+- */
+- amount = skip_label(curwin->w_cursor.lnum, &l);
+-
+- if (theline[0] == '{')
+- amount += curbuf->b_ind_open_extra;
+- /* See remark above: "Only add b_ind_open_extra.." */
+- l = skipwhite(l);
+- if (*l == '{')
+- amount -= curbuf->b_ind_open_extra;
+- lookfor = iscase ? LOOKFOR_ANY : LOOKFOR_TERM;
+-
+- /*
+- * When a terminated line starts with "else" skip to
+- * the matching "if":
+- * else 3;
+- * indent this;
+- * Need to use the scope of this "else". XXX
+- * If whilelevel != 0 continue looking for a "do {".
+- */
+- if (lookfor == LOOKFOR_TERM
+- && *l != '}'
+- && cin_iselse(l)
+- && whilelevel == 0)
+- {
+- if ((trypos = find_start_brace()) == NULL
+- || find_match(LOOKFOR_IF, trypos->lnum)
+- == FAIL)
+- break;
+- continue;
+- }
+-
+- /*
+- * If we're at the end of a block, skip to the start of
+- * that block.
+- */
+- l = ml_get_curline();
+- if (find_last_paren(l, '{', '}') /* XXX */
+- && (trypos = find_start_brace()) != NULL)
+- {
+- curwin->w_cursor = *trypos;
+- /* if not "else {" check for terminated again */
+- /* but skip block for "} else {" */
+- l = cin_skipcomment(ml_get_curline());
+- if (*l == '}' || !cin_iselse(l))
+- goto term_again;
+- ++curwin->w_cursor.lnum;
+- curwin->w_cursor.col = 0;
+- }
+- }
+- }
+- }
+- }
+- }
+-
+- /* add extra indent for a comment */
+- if (cin_iscomment(theline))
+- amount += curbuf->b_ind_comment;
+-
+- /* 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)) != 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, &amount))
+- 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, &amount)))
+- 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;
+- }
+-
+- static int
+- find_match(int lookfor, linenr_T ourscope)
+- {
+- char_u *look;
+- pos_T *theirscope;
+- char_u *mightbeif;
+- int elselevel;
+- int whilelevel;
+-
+- if (lookfor == LOOKFOR_IF)
+- {
+- elselevel = 1;
+- whilelevel = 0;
+- }
+- else
+- {
+- elselevel = 0;
+- whilelevel = 1;
+- }
+-
+- curwin->w_cursor.col = 0;
+-
+- while (curwin->w_cursor.lnum > ourscope + 1)
+- {
+- curwin->w_cursor.lnum--;
+- curwin->w_cursor.col = 0;
+-
+- look = cin_skipcomment(ml_get_curline());
+- if (cin_iselse(look)
+- || cin_isif(look)
+- || cin_isdo(look) /* XXX */
+- || cin_iswhileofdo(look, curwin->w_cursor.lnum))
+- {
+- /*
+- * if we've gone outside the braces entirely,
+- * we must be out of scope...
+- */
+- theirscope = find_start_brace(); /* XXX */
+- if (theirscope == NULL)
+- break;
+-
+- /*
+- * and if the brace enclosing this is further
+- * back than the one enclosing the else, we're
+- * out of luck too.
+- */
+- if (theirscope->lnum < ourscope)
+- break;
+-
+- /*
+- * and if they're enclosed in a *deeper* brace,
+- * then we can ignore it because it's in a
+- * different scope...
+- */
+- if (theirscope->lnum > ourscope)
+- continue;
+-
+- /*
+- * if it was an "else" (that's not an "else if")
+- * then we need to go back to another if, so
+- * increment elselevel
+- */
+- look = cin_skipcomment(ml_get_curline());
+- if (cin_iselse(look))
+- {
+- mightbeif = cin_skipcomment(look + 4);
+- if (!cin_isif(mightbeif))
+- ++elselevel;
+- continue;
+- }
+-
+- /*
+- * if it was a "while" then we need to go back to
+- * another "do", so increment whilelevel. XXX
+- */
+- if (cin_iswhileofdo(look, curwin->w_cursor.lnum))
+- {
+- ++whilelevel;
+- continue;
+- }
+-
+- /* If it's an "if" decrement elselevel */
+- look = cin_skipcomment(ml_get_curline());
+- if (cin_isif(look))
+- {
+- elselevel--;
+- /*
+- * When looking for an "if" ignore "while"s that
+- * get in the way.
+- */
+- if (elselevel == 0 && lookfor == LOOKFOR_IF)
+- whilelevel = 0;
+- }
+-
+- /* If it's a "do" decrement whilelevel */
+- if (cin_isdo(look))
+- whilelevel--;
+-
+- /*
+- * if we've used up all the elses, then
+- * this must be the if that we want!
+- * match the indent level of that if.
+- */
+- if (elselevel <= 0 && whilelevel <= 0)
+- {
+- return OK;
+- }
+- }
+- }
+- return FAIL;
+- }
+-
+- # if defined(FEAT_EVAL) || defined(PROTO)
+- /*
+- * Get indent level from 'indentexpr'.
+- */
+- int
+- get_expr_indent(void)
+- {
+- int indent = -1;
+- char_u *inde_copy;
+- pos_T save_pos;
+- colnr_T save_curswant;
+- int save_set_curswant;
+- int save_State;
+- int use_sandbox = was_set_insecurely((char_u *)"indentexpr",
+- OPT_LOCAL);
+-
+- /* Save and restore cursor position and curswant, in case it was changed
+- * via :normal commands */
+- save_pos = curwin->w_cursor;
+- save_curswant = curwin->w_curswant;
+- save_set_curswant = curwin->w_set_curswant;
+- set_vim_var_nr(VV_LNUM, curwin->w_cursor.lnum);
+- if (use_sandbox)
+- ++sandbox;
+- ++textlock;
+-
+- /* Need to make a copy, the 'indentexpr' option could be changed while
+- * evaluating it. */
+- inde_copy = vim_strsave(curbuf->b_p_inde);
+- if (inde_copy != NULL)
+- {
+- indent = (int)eval_to_number(inde_copy);
+- vim_free(inde_copy);
+- }
+-
+- if (use_sandbox)
+- --sandbox;
+- --textlock;
+-
+- /* Restore the cursor position so that 'indentexpr' doesn't need to.
+- * Pretend to be in Insert mode, allow cursor past end of line for "o"
+- * command. */
+- save_State = State;
+- State = INSERT;
+- curwin->w_cursor = save_pos;
+- curwin->w_curswant = save_curswant;
+- curwin->w_set_curswant = save_set_curswant;
+- check_cursor();
+- State = save_State;
+-
+- /* If there is an error, just keep the current indent. */
+- if (indent < 0)
+- indent = get_indent();
+-
+- return indent;
+- }
+- # endif
+-
+- #endif /* FEAT_CINDENT */
+-
+- #if defined(FEAT_LISP) || defined(PROTO)
+-
+- static int
+- lisp_match(char_u *p)
+- {
+- char_u buf[LSIZE];
+- int len;
+- char_u *word = *curbuf->b_p_lw != NUL ? curbuf->b_p_lw : p_lispwords;
+-
+- while (*word != NUL)
+- {
+- (void)copy_option_part(&word, buf, LSIZE, ",");
+- len = (int)STRLEN(buf);
+- if (STRNCMP(buf, p, len) == 0 && p[len] == ' ')
+- return TRUE;
+- }
+- return FALSE;
+- }
+-
+- /*
+- * When 'p' is present in 'cpoptions, a Vi compatible method is used.
+- * The incompatible newer method is quite a bit better at indenting
+- * code in lisp-like languages than the traditional one; it's still
+- * mostly heuristics however -- Dirk van Deun, dirk@rave.org
+- *
+- * TODO:
+- * Findmatch() should be adapted for lisp, also to make showmatch
+- * work correctly: now (v5.3) it seems all C/C++ oriented:
+- * - it does not recognize the #\( and #\) notations as character literals
+- * - it doesn't know about comments starting with a semicolon
+- * - it incorrectly interprets '(' as a character literal
+- * All this messes up get_lisp_indent in some rare cases.
+- * Update from Sergey Khorev:
+- * I tried to fix the first two issues.
+- */
+- int
+- get_lisp_indent(void)
+- {
+- pos_T *pos, realpos, paren;
+- int amount;
+- char_u *that;
+- colnr_T col;
+- colnr_T firsttry;
+- int parencount, quotecount;
+- int vi_lisp;
+-
+- /* Set vi_lisp to use the vi-compatible method */
+- vi_lisp = (vim_strchr(p_cpo, CPO_LISP) != NULL);
+-
+- realpos = curwin->w_cursor;
+- curwin->w_cursor.col = 0;
+-
+- if ((pos = findmatch(NULL, '(')) == NULL)
+- pos = findmatch(NULL, '[');
+- else
+- {
+- paren = *pos;
+- pos = findmatch(NULL, '[');
+- if (pos == NULL || LT_POSP(pos, &paren))
+- pos = &paren;
+- }
+- if (pos != NULL)
+- {
+- /* Extra trick: Take the indent of the first previous non-white
+- * line that is at the same () level. */
+- amount = -1;
+- parencount = 0;
+-
+- while (--curwin->w_cursor.lnum >= pos->lnum)
+- {
+- if (linewhite(curwin->w_cursor.lnum))
+- continue;
+- for (that = ml_get_curline(); *that != NUL; ++that)
+- {
+- if (*that == ';')
+- {
+- while (*(that + 1) != NUL)
+- ++that;
+- continue;
+- }
+- if (*that == '\\')
+- {
+- if (*(that + 1) != NUL)
+- ++that;
+- continue;
+- }
+- if (*that == '"' && *(that + 1) != NUL)
+- {
+- while (*++that && *that != '"')
+- {
+- /* skipping escaped characters in the string */
+- if (*that == '\\')
+- {
+- if (*++that == NUL)
+- break;
+- if (that[1] == NUL)
+- {
+- ++that;
+- break;
+- }
+- }
+- }
+- }
+- if (*that == '(' || *that == '[')
+- ++parencount;
+- else if (*that == ')' || *that == ']')
+- --parencount;
+- }
+- if (parencount == 0)
+- {
+- amount = get_indent();
+- break;
+- }
+- }
+-
+- if (amount == -1)
+- {
+- curwin->w_cursor.lnum = pos->lnum;
+- curwin->w_cursor.col = pos->col;
+- col = pos->col;
+-
+- that = ml_get_curline();
+-
+- if (vi_lisp && get_indent() == 0)
+- amount = 2;
+- else
+- {
+- char_u *line = that;
+-
+- amount = 0;
+- while (*that && col)
+- {
+- amount += lbr_chartabsize_adv(line, &that, (colnr_T)amount);
+- col--;
+- }
+-
+- /*
+- * Some keywords require "body" indenting rules (the
+- * non-standard-lisp ones are Scheme special forms):
+- *
+- * (let ((a 1)) instead (let ((a 1))
+- * (...)) of (...))
+- */
+-
+- if (!vi_lisp && (*that == '(' || *that == '[')
+- && lisp_match(that + 1))
+- amount += 2;
+- else
+- {
+- that++;
+- amount++;
+- firsttry = amount;
+-
+- while (VIM_ISWHITE(*that))
+- {
+- amount += lbr_chartabsize(line, that, (colnr_T)amount);
+- ++that;
+- }
+-
+- if (*that && *that != ';') /* not a comment line */
+- {
+- /* test *that != '(' to accommodate first let/do
+- * argument if it is more than one line */
+- if (!vi_lisp && *that != '(' && *that != '[')
+- firsttry++;
+-
+- parencount = 0;
+- quotecount = 0;
+-
+- if (vi_lisp
+- || (*that != '"'
+- && *that != '\''
+- && *that != '#'
+- && (*that < '0' || *that > '9')))
+- {
+- while (*that
+- && (!VIM_ISWHITE(*that)
+- || quotecount
+- || parencount)
+- && (!((*that == '(' || *that == '[')
+- && !quotecount
+- && !parencount
+- && vi_lisp)))
+- {
+- if (*that == '"')
+- quotecount = !quotecount;
+- if ((*that == '(' || *that == '[')
+- && !quotecount)
+- ++parencount;
+- if ((*that == ')' || *that == ']')
+- && !quotecount)
+- --parencount;
+- if (*that == '\\' && *(that+1) != NUL)
+- amount += lbr_chartabsize_adv(
+- line, &that, (colnr_T)amount);
+- amount += lbr_chartabsize_adv(
+- line, &that, (colnr_T)amount);
+- }
+- }
+- while (VIM_ISWHITE(*that))
+- {
+- amount += lbr_chartabsize(
+- line, that, (colnr_T)amount);
+- that++;
+- }
+- if (!*that || *that == ';')
+- amount = firsttry;
+- }
+- }
+- }
+- }
+- }
+- else
+- amount = 0; /* no matching '(' or '[' found, use zero indent */
+-
+- curwin->w_cursor = realpos;
+-
+- return amount;
+- }
+- #endif /* FEAT_LISP */
+-
+ void
+ prepare_to_exit(void)
+ {
+--- 5369,5374 ----
+*** ../vim-8.1.0856/src/proto.h 2019-01-26 16:20:44.264683546 +0100
+--- src/proto.h 2019-01-31 13:43:23.356467234 +0100
+***************
+*** 87,92 ****
+--- 87,93 ----
+ # endif
+ # include "hardcopy.pro"
+ # include "hashtab.pro"
++ # include "indent.pro"
+ # include "json.pro"
+ # include "list.pro"
+ # include "blob.pro"
+*** ../vim-8.1.0856/src/proto/edit.pro 2018-11-22 03:07:30.948596188 +0100
+--- src/proto/edit.pro 2019-01-31 13:45:12.275722540 +0100
+***************
+*** 38,46 ****
+ char_u *get_last_insert_save(void);
+ void replace_push(int c);
+ int replace_push_mb(char_u *p);
+- void fixthisline(int (*get_the_indent)(void));
+- void fix_indent(void);
+- int in_cinkeys(int keytyped, int when, int line_is_empty);
+ int hkmap(int c);
+ int bracketed_paste(paste_mode_T mode, int drop, garray_T *gap);
+ void ins_scroll(void);
+--- 38,43 ----
+*** ../vim-8.1.0856/src/proto/indent.pro 2019-01-31 13:47:08.570924989 +0100
+--- src/proto/indent.pro 2019-01-31 13:45:17.403687423 +0100
+***************
+*** 0 ****
+--- 1,16 ----
++ /* indent.c */
++ int cin_is_cinword(char_u *line);
++ pos_T *find_start_comment(int ind_maxcomment);
++ int cindent_on(void);
++ int cin_islabel(void);
++ int cin_iscase(char_u *s, int strict);
++ int cin_isscopedecl(char_u *s);
++ void parse_cino(buf_T *buf);
++ int get_c_indent(void);
++ int get_expr_indent(void);
++ int in_cinkeys(int keytyped, int when, int line_is_empty);
++ int get_lisp_indent(void);
++ void do_c_expr_indent(void);
++ void fixthisline(int (*get_the_indent)(void));
++ void fix_indent(void);
++ /* vim: set ft=c : */
+*** ../vim-8.1.0856/src/proto/misc1.pro 2019-01-02 00:02:07.607556145 +0100
+--- src/proto/misc1.pro 2019-01-31 13:45:20.359667178 +0100
+***************
+*** 83,97 ****
+ char_u *concat_str(char_u *str1, char_u *str2);
+ void add_pathsep(char_u *p);
+ char_u *FullName_save(char_u *fname, int force);
+- pos_T *find_start_comment(int ind_maxcomment);
+- void do_c_expr_indent(void);
+- int cin_islabel(void);
+- int cin_iscase(char_u *s, int strict);
+- int cin_isscopedecl(char_u *s);
+- void parse_cino(buf_T *buf);
+- int get_c_indent(void);
+- int get_expr_indent(void);
+- int get_lisp_indent(void);
+ void prepare_to_exit(void);
+ void preserve_exit(void);
+ int vim_fexists(char_u *fname);
+--- 83,88 ----
+*** ../vim-8.1.0856/src/version.c 2019-01-31 13:22:28.068543628 +0100
+--- src/version.c 2019-01-31 13:45:27.287619720 +0100
+***************
+*** 785,786 ****
+--- 785,788 ----
+ { /* Add new patch number below this line */
++ /**/
++ 857,
+ /**/
+
+--
+ [SIR LAUNCELOT runs back up the stairs, grabs a rope
+ of the wall and swings out over the heads of the CROWD in a
+ swashbuckling manner towards a large window. He stops just short
+ of the window and is left swing pathetically back and forth.]
+LAUNCELOT: Excuse me ... could somebody give me a push ...
+ "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
+
+ /// 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 ///