patch 7.4.941
Problem:    There is no way to ignore case only for tag searches.
Solution:   Add the 'tagcase' option. (Gary Johnson)
diff --git a/src/Makefile b/src/Makefile
index 90b2f0c..ab1014f 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1930,6 +1930,7 @@
 	test_search_mbyte \
 	test_set \
 	test_signs \
+	test_tagcase \
 	test_textobjects \
 	test_utf8 \
 	test_writefile \
diff --git a/src/buffer.c b/src/buffer.c
index 5d4170f..d1907a4 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1991,6 +1991,7 @@
     clear_string_option(&buf->b_p_ep);
     clear_string_option(&buf->b_p_path);
     clear_string_option(&buf->b_p_tags);
+    clear_string_option(&buf->b_p_tc);
 #ifdef FEAT_INS_EXPAND
     clear_string_option(&buf->b_p_dict);
     clear_string_option(&buf->b_p_tsr);
diff --git a/src/option.c b/src/option.c
index 6f9c5f5..f8cb1ba 100644
--- a/src/option.c
+++ b/src/option.c
@@ -174,6 +174,7 @@
 #define PV_SW		OPT_BUF(BV_SW)
 #define PV_SWF		OPT_BUF(BV_SWF)
 #define PV_TAGS		OPT_BOTH(OPT_BUF(BV_TAGS))
+#define PV_TC		OPT_BOTH(OPT_BUF(BV_TC))
 #define PV_TS		OPT_BUF(BV_TS)
 #define PV_TW		OPT_BUF(BV_TW)
 #define PV_TX		OPT_BUF(BV_TX)
@@ -2602,6 +2603,9 @@
 			    {(char_u *)TRUE, (char_u *)0L}
 #endif
 			    SCRIPTID_INIT},
+    {"tagcase",	    "tc",   P_STRING|P_VIM,
+			    (char_u *)&p_tc, PV_TC,
+			    {(char_u *)"followic", (char_u *)"followic"} SCRIPTID_INIT},
     {"taglength",   "tl",   P_NUM|P_VI_DEF,
 			    (char_u *)&p_tl, PV_NONE,
 			    {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT},
@@ -5363,6 +5367,7 @@
     (void)opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, TRUE);
 #endif
     (void)opt_strings_flags(p_dy, p_dy_values, &dy_flags, TRUE);
+    (void)opt_strings_flags(p_tc, p_tc_values, &tc_flags, FALSE);
 #ifdef FEAT_VIRTUALEDIT
     (void)opt_strings_flags(p_ve, p_ve_values, &ve_flags, TRUE);
 #endif
@@ -5525,6 +5530,7 @@
     check_string_option(&buf->b_p_ep);
     check_string_option(&buf->b_p_path);
     check_string_option(&buf->b_p_tags);
+    check_string_option(&buf->b_p_tc);
 #ifdef FEAT_INS_EXPAND
     check_string_option(&buf->b_p_dict);
     check_string_option(&buf->b_p_tsr);
@@ -7044,6 +7050,30 @@
 	    errmsg = e_invarg;
     }
 
+    /* 'tagcase' */
+    else if (gvarp == &p_tc)
+    {
+	unsigned int	*flags;
+
+	if (opt_flags & OPT_LOCAL)
+	{
+	    p = curbuf->b_p_tc;
+	    flags = &curbuf->b_tc_flags;
+	}
+	else
+	{
+	    p = p_tc;
+	    flags = &tc_flags;
+	}
+
+	if ((opt_flags & OPT_LOCAL) && *p == NUL)
+	    /* make the local value empty: use the global value */
+	    *flags = 0;
+	else if (*p == NUL
+		|| opt_strings_flags(p, p_tc_values, flags, FALSE) != OK)
+	    errmsg = e_invarg;
+    }
+
 #ifdef FEAT_MBYTE
     /* 'casemap' */
     else if (varp == &p_cmp)
@@ -10083,6 +10113,10 @@
 	case PV_TAGS:
 	    clear_string_option(&buf->b_p_tags);
 	    break;
+	case PV_TC:
+	    clear_string_option(&buf->b_p_tc);
+	    buf->b_tc_flags = 0;
+	    break;
 #ifdef FEAT_FIND_ID
 	case PV_DEF:
 	    clear_string_option(&buf->b_p_def);
@@ -10164,6 +10198,7 @@
 	    case PV_PATH: return (char_u *)&(curbuf->b_p_path);
 	    case PV_AR:   return (char_u *)&(curbuf->b_p_ar);
 	    case PV_TAGS: return (char_u *)&(curbuf->b_p_tags);
+	    case PV_TC:   return (char_u *)&(curbuf->b_p_tc);
 #ifdef FEAT_FIND_ID
 	    case PV_DEF:  return (char_u *)&(curbuf->b_p_def);
 	    case PV_INC:  return (char_u *)&(curbuf->b_p_inc);
@@ -10218,6 +10253,8 @@
 				    ? (char_u *)&(curbuf->b_p_ar) : p->var;
 	case PV_TAGS:	return *curbuf->b_p_tags != NUL
 				    ? (char_u *)&(curbuf->b_p_tags) : p->var;
+	case PV_TC:	return *curbuf->b_p_tc != NUL
+				    ? (char_u *)&(curbuf->b_p_tc) : p->var;
 	case PV_BKC:	return *curbuf->b_p_bkc != NUL
 				    ? (char_u *)&(curbuf->b_p_bkc) : p->var;
 #ifdef FEAT_FIND_ID
@@ -10826,6 +10863,8 @@
 	    buf->b_p_kp = empty_option;
 	    buf->b_p_path = empty_option;
 	    buf->b_p_tags = empty_option;
+	    buf->b_p_tc = empty_option;
+	    buf->b_tc_flags = 0;
 #ifdef FEAT_FIND_ID
 	    buf->b_p_def = empty_option;
 	    buf->b_p_inc = empty_option;
diff --git a/src/option.h b/src/option.h
index c6a3e60..d994d2d 100644
--- a/src/option.h
+++ b/src/option.h
@@ -820,6 +820,14 @@
 #define SWB_NEWTAB		0x008
 #define SWB_VSPLIT		0x010
 EXTERN int	p_tbs;		/* 'tagbsearch' */
+EXTERN char_u	*p_tc;		/* 'tagcase' */
+EXTERN unsigned tc_flags;       /* flags from 'tagcase' */
+#ifdef IN_OPTION_C
+static char *(p_tc_values[]) = {"followic", "ignore", "match", NULL};
+#endif
+#define TC_FOLLOWIC		0x01
+#define TC_IGNORE		0x02
+#define TC_MATCH		0x04
 EXTERN long	p_tl;		/* 'taglength' */
 EXTERN int	p_tr;		/* 'tagrelative' */
 EXTERN char_u	*p_tags;	/* 'tags' */
@@ -1081,6 +1089,7 @@
     , BV_SW
     , BV_SWF
     , BV_TAGS
+    , BV_TC
     , BV_TS
     , BV_TW
     , BV_TX
diff --git a/src/structs.h b/src/structs.h
index addc212..0c06401 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -1674,6 +1674,8 @@
     char_u	*b_p_path;	/* 'path' local value */
     int		b_p_ar;		/* 'autoread' local value */
     char_u	*b_p_tags;	/* 'tags' local value */
+    char_u	*b_p_tc;	/* 'tagcase' local value */
+    unsigned	b_tc_flags;     /* flags for 'tagcase' */
 #ifdef FEAT_INS_EXPAND
     char_u	*b_p_dict;	/* 'dictionary' local value */
     char_u	*b_p_tsr;	/* 'thesaurus' local value */
@@ -2063,7 +2065,7 @@
 				       current virtual column */
 
     /*
-     * the next six are used to update the visual part
+     * the next seven are used to update the visual part
      */
     char	w_old_visual_mode;  /* last known VIsual_mode */
     linenr_T	w_old_cursor_lnum;  /* last known end of visual part */
diff --git a/src/tag.c b/src/tag.c
index 8aaa86b..25a3692 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -1385,6 +1385,18 @@
     int		use_cscope = (flags & TAG_CSCOPE);
 #endif
     int		verbose = (flags & TAG_VERBOSE);
+    int		save_p_ic = p_ic;
+
+    /*
+     * Change the value of 'ignorecase' according to 'tagcase' for the
+     * duration of this function.
+     */
+    switch (curbuf->b_tc_flags ? curbuf->b_tc_flags : tc_flags)
+    {
+	case TC_FOLLOWIC:               break;
+	case TC_IGNORE:   p_ic = TRUE;  break;
+	case TC_MATCH:    p_ic = FALSE; break;
+    }
 
     help_save = curbuf->b_help;
     orgpat.pat = pat;
@@ -2552,6 +2564,8 @@
     vim_free(saved_pat);
 #endif
 
+    p_ic = save_p_ic;
+
     return retval;
 }
 
diff --git a/src/testdir/Make_amiga.mak b/src/testdir/Make_amiga.mak
index af27919..1d7b07c 100644
--- a/src/testdir/Make_amiga.mak
+++ b/src/testdir/Make_amiga.mak
@@ -66,6 +66,7 @@
 		test_search_mbyte.out \
 		test_set.out \
 		test_signs.out \
+		test_tagcase.out \
 		test_textobjects.out \
 		test_utf8.out
 
@@ -221,5 +222,6 @@
 test_search_mbyte.out: test_search_mbyte.in
 test_set.out: test_set.in
 test_signs.out: test_signs.in
+test_tagcase.out: test_tagcase.in
 test_textobjects.out: test_textobjects.in
 test_utf8.out: test_utf8.in
diff --git a/src/testdir/Make_dos.mak b/src/testdir/Make_dos.mak
index abef950..30325ea 100644
--- a/src/testdir/Make_dos.mak
+++ b/src/testdir/Make_dos.mak
@@ -65,6 +65,7 @@
 		test_search_mbyte.out \
 		test_set.out \
 		test_signs.out \
+		test_tagcase.out \
 		test_textobjects.out \
 		test_utf8.out
 
diff --git a/src/testdir/Make_ming.mak b/src/testdir/Make_ming.mak
index aa59a01..a32f3ed 100644
--- a/src/testdir/Make_ming.mak
+++ b/src/testdir/Make_ming.mak
@@ -87,6 +87,7 @@
 		test_search_mbyte.out \
 		test_set.out \
 		test_signs.out \
+		test_tagcase.out \
 		test_textobjects.out \
 		test_utf8.out
 
diff --git a/src/testdir/Make_os2.mak b/src/testdir/Make_os2.mak
index 9150af7..d593bb2 100644
--- a/src/testdir/Make_os2.mak
+++ b/src/testdir/Make_os2.mak
@@ -67,6 +67,7 @@
 		test_search_mbyte.out \
 		test_set.out \
 		test_signs.out \
+		test_tagcase.out \
 		test_textobjects.out \
 		test_utf8.out
 
diff --git a/src/testdir/Make_vms.mms b/src/testdir/Make_vms.mms
index a716d03..0fd26c1 100644
--- a/src/testdir/Make_vms.mms
+++ b/src/testdir/Make_vms.mms
@@ -126,6 +126,7 @@
 	 test_search_mbyte.out \
 	 test_set.out \
 	 test_signs.out \
+	 test_tagcase.out \
 	 test_textobjects.out \
 	 test_utf8.out
 
diff --git a/src/testdir/Makefile b/src/testdir/Makefile
index 39d8388..d46718f 100644
--- a/src/testdir/Makefile
+++ b/src/testdir/Makefile
@@ -63,6 +63,7 @@
 		test_search_mbyte.out \
 		test_set.out \
 		test_signs.out \
+		test_tagcase.out \
 		test_textobjects.out \
 		test_utf8.out
 
diff --git a/src/testdir/test_tagcase.in b/src/testdir/test_tagcase.in
new file mode 100644
index 0000000..322d769
--- /dev/null
+++ b/src/testdir/test_tagcase.in
@@ -0,0 +1,55 @@
+Tests for 'tagcase' option
+
+STARTTEST
+:/^start text$/+1,/^end text$/w! Xtext
+:/^start tags$/+1,/^end tags$/-1w! Xtags
+:set tags=Xtags
+:e Xtext
+:"
+:" Verify default values.
+:set ic& | setg tc& | setl tc&
+:call append('$', "ic=".&ic." g:tc=".&g:tc." l:tc=".&l:tc." tc=".&tc)
+:"
+:" Verify that the local setting accepts <empty> but that the global setting
+:" does not.  The first of these (setting the local value to <empty>) should
+:" succeed; the other two should fail.
+:let v:errmsg = ""
+:setl tc=
+:call append('$', v:errmsg)
+:let v:errmsg = ""
+:setg tc=
+:call append('$', v:errmsg)
+:let v:errmsg = ""
+:set tc=
+:call append('$', v:errmsg)
+:"
+:" Verify that the correct number of matching tags is found for all values of
+:" 'ignorecase' and global and local values 'tagcase', in all combinations.
+:for &ic in [0, 1]
+:  for &g:tc in ["followic", "ignore", "match"]
+:    for &l:tc in ["", "followic", "ignore", "match"]
+:      call append('$', "ic=".&ic." g:tc=".&g:tc." l:tc=".&l:tc." tc=".&tc)
+:      call append('$', len(taglist("^foo$")))
+:      call append('$', len(taglist("^Foo$")))
+:    endfor
+:  endfor
+:endfor
+:"
+:1,/^end text$/d
+:w! test.out
+:qa!
+ENDTEST
+
+start text
+
+Foo
+Bar
+foo
+
+end text
+
+start tags
+Bar	Xtext	3
+Foo	Xtext	2
+foo	Xtext	4
+end tags
diff --git a/src/testdir/test_tagcase.ok b/src/testdir/test_tagcase.ok
new file mode 100644
index 0000000..fe161cf
--- /dev/null
+++ b/src/testdir/test_tagcase.ok
@@ -0,0 +1,76 @@
+ic=0 g:tc=followic l:tc=followic tc=followic
+
+E474: Invalid argument: tc=
+E474: Invalid argument: tc=
+ic=0 g:tc=followic l:tc= tc=followic
+1
+1
+ic=0 g:tc=followic l:tc=followic tc=followic
+1
+1
+ic=0 g:tc=followic l:tc=ignore tc=ignore
+2
+2
+ic=0 g:tc=followic l:tc=match tc=match
+1
+1
+ic=0 g:tc=ignore l:tc= tc=ignore
+2
+2
+ic=0 g:tc=ignore l:tc=followic tc=followic
+1
+1
+ic=0 g:tc=ignore l:tc=ignore tc=ignore
+2
+2
+ic=0 g:tc=ignore l:tc=match tc=match
+1
+1
+ic=0 g:tc=match l:tc= tc=match
+1
+1
+ic=0 g:tc=match l:tc=followic tc=followic
+1
+1
+ic=0 g:tc=match l:tc=ignore tc=ignore
+2
+2
+ic=0 g:tc=match l:tc=match tc=match
+1
+1
+ic=1 g:tc=followic l:tc= tc=followic
+2
+2
+ic=1 g:tc=followic l:tc=followic tc=followic
+2
+2
+ic=1 g:tc=followic l:tc=ignore tc=ignore
+2
+2
+ic=1 g:tc=followic l:tc=match tc=match
+1
+1
+ic=1 g:tc=ignore l:tc= tc=ignore
+2
+2
+ic=1 g:tc=ignore l:tc=followic tc=followic
+2
+2
+ic=1 g:tc=ignore l:tc=ignore tc=ignore
+2
+2
+ic=1 g:tc=ignore l:tc=match tc=match
+1
+1
+ic=1 g:tc=match l:tc= tc=match
+1
+1
+ic=1 g:tc=match l:tc=followic tc=followic
+2
+2
+ic=1 g:tc=match l:tc=ignore tc=ignore
+2
+2
+ic=1 g:tc=match l:tc=match tc=match
+1
+1
diff --git a/src/version.c b/src/version.c
index db728e2..d437f50 100644
--- a/src/version.c
+++ b/src/version.c
@@ -742,6 +742,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    941,
+/**/
     940,
 /**/
     939,