comparison src/highlight.c @ 17472:dfd87ef822aa v8.1.1734

patch 8.1.1734: the evalfunc.c file is too big commit https://github.com/vim/vim/commit/29b7d7a9aac591f920edb89241c8cde27378e50b Author: Bram Moolenaar <Bram@vim.org> Date: Mon Jul 22 23:03:57 2019 +0200 patch 8.1.1734: the evalfunc.c file is too big Problem: The evalfunc.c file is too big. Solution: Move some functions to other files.
author Bram Moolenaar <Bram@vim.org>
date Mon, 22 Jul 2019 23:15:05 +0200
parents 5462bb963075
children f8c197962c1e
comparison
equal deleted inserted replaced
17471:c7151df86441 17472:dfd87ef822aa
6 * Do ":help credits" in Vim to see a list of people who contributed. 6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code. 7 * See README.txt for an overview of the Vim source code.
8 */ 8 */
9 9
10 /* 10 /*
11 * Highlighting stuff 11 * Highlighting stuff.
12 * Includes highlighting matches.
12 */ 13 */
13 14
14 #include "vim.h" 15 #include "vim.h"
15 16
16 #define SG_TERM 1 // term has been set 17 #define SG_TERM 1 // term has been set
3651 gui_mch_free_font(gui.ital_font); 3652 gui_mch_free_font(gui.ital_font);
3652 gui_mch_free_font(gui.boldital_font); 3653 gui_mch_free_font(gui.boldital_font);
3653 # endif 3654 # endif
3654 } 3655 }
3655 #endif 3656 #endif
3657
3658
3659 #if defined(FEAT_SEARCH_EXTRA) || defined(PROTO)
3660 /*
3661 * Add match to the match list of window 'wp'. The pattern 'pat' will be
3662 * highlighted with the group 'grp' with priority 'prio'.
3663 * Optionally, a desired ID 'id' can be specified (greater than or equal to 1).
3664 * If no particular ID is desired, -1 must be specified for 'id'.
3665 * Return ID of added match, -1 on failure.
3666 */
3667 int
3668 match_add(
3669 win_T *wp,
3670 char_u *grp,
3671 char_u *pat,
3672 int prio,
3673 int id,
3674 list_T *pos_list,
3675 char_u *conceal_char UNUSED) /* pointer to conceal replacement char */
3676 {
3677 matchitem_T *cur;
3678 matchitem_T *prev;
3679 matchitem_T *m;
3680 int hlg_id;
3681 regprog_T *regprog = NULL;
3682 int rtype = SOME_VALID;
3683
3684 if (*grp == NUL || (pat != NULL && *pat == NUL))
3685 return -1;
3686 if (id < -1 || id == 0)
3687 {
3688 semsg(_("E799: Invalid ID: %d (must be greater than or equal to 1)"), id);
3689 return -1;
3690 }
3691 if (id != -1)
3692 {
3693 cur = wp->w_match_head;
3694 while (cur != NULL)
3695 {
3696 if (cur->id == id)
3697 {
3698 semsg(_("E801: ID already taken: %d"), id);
3699 return -1;
3700 }
3701 cur = cur->next;
3702 }
3703 }
3704 if ((hlg_id = syn_namen2id(grp, (int)STRLEN(grp))) == 0)
3705 {
3706 semsg(_(e_nogroup), grp);
3707 return -1;
3708 }
3709 if (pat != NULL && (regprog = vim_regcomp(pat, RE_MAGIC)) == NULL)
3710 {
3711 semsg(_(e_invarg2), pat);
3712 return -1;
3713 }
3714
3715 /* Find available match ID. */
3716 while (id == -1)
3717 {
3718 cur = wp->w_match_head;
3719 while (cur != NULL && cur->id != wp->w_next_match_id)
3720 cur = cur->next;
3721 if (cur == NULL)
3722 id = wp->w_next_match_id;
3723 wp->w_next_match_id++;
3724 }
3725
3726 /* Build new match. */
3727 m = ALLOC_CLEAR_ONE(matchitem_T);
3728 m->id = id;
3729 m->priority = prio;
3730 m->pattern = pat == NULL ? NULL : vim_strsave(pat);
3731 m->hlg_id = hlg_id;
3732 m->match.regprog = regprog;
3733 m->match.rmm_ic = FALSE;
3734 m->match.rmm_maxcol = 0;
3735 # if defined(FEAT_CONCEAL)
3736 m->conceal_char = 0;
3737 if (conceal_char != NULL)
3738 m->conceal_char = (*mb_ptr2char)(conceal_char);
3739 # endif
3740
3741 /* Set up position matches */
3742 if (pos_list != NULL)
3743 {
3744 linenr_T toplnum = 0;
3745 linenr_T botlnum = 0;
3746 listitem_T *li;
3747 int i;
3748
3749 for (i = 0, li = pos_list->lv_first; li != NULL && i < MAXPOSMATCH;
3750 i++, li = li->li_next)
3751 {
3752 linenr_T lnum = 0;
3753 colnr_T col = 0;
3754 int len = 1;
3755 list_T *subl;
3756 listitem_T *subli;
3757 int error = FALSE;
3758
3759 if (li->li_tv.v_type == VAR_LIST)
3760 {
3761 subl = li->li_tv.vval.v_list;
3762 if (subl == NULL)
3763 goto fail;
3764 subli = subl->lv_first;
3765 if (subli == NULL)
3766 goto fail;
3767 lnum = tv_get_number_chk(&subli->li_tv, &error);
3768 if (error == TRUE)
3769 goto fail;
3770 if (lnum == 0)
3771 {
3772 --i;
3773 continue;
3774 }
3775 m->pos.pos[i].lnum = lnum;
3776 subli = subli->li_next;
3777 if (subli != NULL)
3778 {
3779 col = tv_get_number_chk(&subli->li_tv, &error);
3780 if (error == TRUE)
3781 goto fail;
3782 subli = subli->li_next;
3783 if (subli != NULL)
3784 {
3785 len = tv_get_number_chk(&subli->li_tv, &error);
3786 if (error == TRUE)
3787 goto fail;
3788 }
3789 }
3790 m->pos.pos[i].col = col;
3791 m->pos.pos[i].len = len;
3792 }
3793 else if (li->li_tv.v_type == VAR_NUMBER)
3794 {
3795 if (li->li_tv.vval.v_number == 0)
3796 {
3797 --i;
3798 continue;
3799 }
3800 m->pos.pos[i].lnum = li->li_tv.vval.v_number;
3801 m->pos.pos[i].col = 0;
3802 m->pos.pos[i].len = 0;
3803 }
3804 else
3805 {
3806 emsg(_("List or number required"));
3807 goto fail;
3808 }
3809 if (toplnum == 0 || lnum < toplnum)
3810 toplnum = lnum;
3811 if (botlnum == 0 || lnum >= botlnum)
3812 botlnum = lnum + 1;
3813 }
3814
3815 /* Calculate top and bottom lines for redrawing area */
3816 if (toplnum != 0)
3817 {
3818 if (wp->w_buffer->b_mod_set)
3819 {
3820 if (wp->w_buffer->b_mod_top > toplnum)
3821 wp->w_buffer->b_mod_top = toplnum;
3822 if (wp->w_buffer->b_mod_bot < botlnum)
3823 wp->w_buffer->b_mod_bot = botlnum;
3824 }
3825 else
3826 {
3827 wp->w_buffer->b_mod_set = TRUE;
3828 wp->w_buffer->b_mod_top = toplnum;
3829 wp->w_buffer->b_mod_bot = botlnum;
3830 wp->w_buffer->b_mod_xlines = 0;
3831 }
3832 m->pos.toplnum = toplnum;
3833 m->pos.botlnum = botlnum;
3834 rtype = VALID;
3835 }
3836 }
3837
3838 /* Insert new match. The match list is in ascending order with regard to
3839 * the match priorities. */
3840 cur = wp->w_match_head;
3841 prev = cur;
3842 while (cur != NULL && prio >= cur->priority)
3843 {
3844 prev = cur;
3845 cur = cur->next;
3846 }
3847 if (cur == prev)
3848 wp->w_match_head = m;
3849 else
3850 prev->next = m;
3851 m->next = cur;
3852
3853 redraw_later(rtype);
3854 return id;
3855
3856 fail:
3857 vim_free(m);
3858 return -1;
3859 }
3860
3861 /*
3862 * Delete match with ID 'id' in the match list of window 'wp'.
3863 * Print error messages if 'perr' is TRUE.
3864 */
3865 int
3866 match_delete(win_T *wp, int id, int perr)
3867 {
3868 matchitem_T *cur = wp->w_match_head;
3869 matchitem_T *prev = cur;
3870 int rtype = SOME_VALID;
3871
3872 if (id < 1)
3873 {
3874 if (perr == TRUE)
3875 semsg(_("E802: Invalid ID: %d (must be greater than or equal to 1)"),
3876 id);
3877 return -1;
3878 }
3879 while (cur != NULL && cur->id != id)
3880 {
3881 prev = cur;
3882 cur = cur->next;
3883 }
3884 if (cur == NULL)
3885 {
3886 if (perr == TRUE)
3887 semsg(_("E803: ID not found: %d"), id);
3888 return -1;
3889 }
3890 if (cur == prev)
3891 wp->w_match_head = cur->next;
3892 else
3893 prev->next = cur->next;
3894 vim_regfree(cur->match.regprog);
3895 vim_free(cur->pattern);
3896 if (cur->pos.toplnum != 0)
3897 {
3898 if (wp->w_buffer->b_mod_set)
3899 {
3900 if (wp->w_buffer->b_mod_top > cur->pos.toplnum)
3901 wp->w_buffer->b_mod_top = cur->pos.toplnum;
3902 if (wp->w_buffer->b_mod_bot < cur->pos.botlnum)
3903 wp->w_buffer->b_mod_bot = cur->pos.botlnum;
3904 }
3905 else
3906 {
3907 wp->w_buffer->b_mod_set = TRUE;
3908 wp->w_buffer->b_mod_top = cur->pos.toplnum;
3909 wp->w_buffer->b_mod_bot = cur->pos.botlnum;
3910 wp->w_buffer->b_mod_xlines = 0;
3911 }
3912 rtype = VALID;
3913 }
3914 vim_free(cur);
3915 redraw_later(rtype);
3916 return 0;
3917 }
3918
3919 /*
3920 * Delete all matches in the match list of window 'wp'.
3921 */
3922 void
3923 clear_matches(win_T *wp)
3924 {
3925 matchitem_T *m;
3926
3927 while (wp->w_match_head != NULL)
3928 {
3929 m = wp->w_match_head->next;
3930 vim_regfree(wp->w_match_head->match.regprog);
3931 vim_free(wp->w_match_head->pattern);
3932 vim_free(wp->w_match_head);
3933 wp->w_match_head = m;
3934 }
3935 redraw_later(SOME_VALID);
3936 }
3937
3938 /*
3939 * Get match from ID 'id' in window 'wp'.
3940 * Return NULL if match not found.
3941 */
3942 matchitem_T *
3943 get_match(win_T *wp, int id)
3944 {
3945 matchitem_T *cur = wp->w_match_head;
3946
3947 while (cur != NULL && cur->id != id)
3948 cur = cur->next;
3949 return cur;
3950 }
3951
3952 static int
3953 matchadd_dict_arg(typval_T *tv, char_u **conceal_char, win_T **win)
3954 {
3955 dictitem_T *di;
3956
3957 if (tv->v_type != VAR_DICT)
3958 {
3959 emsg(_(e_dictreq));
3960 return FAIL;
3961 }
3962
3963 if (dict_find(tv->vval.v_dict, (char_u *)"conceal", -1) != NULL)
3964 *conceal_char = dict_get_string(tv->vval.v_dict,
3965 (char_u *)"conceal", FALSE);
3966
3967 if ((di = dict_find(tv->vval.v_dict, (char_u *)"window", -1)) != NULL)
3968 {
3969 *win = find_win_by_nr_or_id(&di->di_tv);
3970 if (*win == NULL)
3971 {
3972 emsg(_(e_invalwindow));
3973 return FAIL;
3974 }
3975 }
3976
3977 return OK;
3978 }
3979 #endif
3980
3981 /*
3982 * "getmatches()" function
3983 */
3984 void
3985 f_getmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
3986 {
3987 #ifdef FEAT_SEARCH_EXTRA
3988 dict_T *dict;
3989 matchitem_T *cur;
3990 int i;
3991 win_T *win = get_optional_window(argvars, 0);
3992
3993 if (rettv_list_alloc(rettv) == FAIL || win == NULL)
3994 return;
3995
3996 cur = win->w_match_head;
3997 while (cur != NULL)
3998 {
3999 dict = dict_alloc();
4000 if (dict == NULL)
4001 return;
4002 if (cur->match.regprog == NULL)
4003 {
4004 /* match added with matchaddpos() */
4005 for (i = 0; i < MAXPOSMATCH; ++i)
4006 {
4007 llpos_T *llpos;
4008 char buf[30]; // use 30 to avoid compiler warning
4009 list_T *l;
4010
4011 llpos = &cur->pos.pos[i];
4012 if (llpos->lnum == 0)
4013 break;
4014 l = list_alloc();
4015 if (l == NULL)
4016 break;
4017 list_append_number(l, (varnumber_T)llpos->lnum);
4018 if (llpos->col > 0)
4019 {
4020 list_append_number(l, (varnumber_T)llpos->col);
4021 list_append_number(l, (varnumber_T)llpos->len);
4022 }
4023 sprintf(buf, "pos%d", i + 1);
4024 dict_add_list(dict, buf, l);
4025 }
4026 }
4027 else
4028 {
4029 dict_add_string(dict, "pattern", cur->pattern);
4030 }
4031 dict_add_string(dict, "group", syn_id2name(cur->hlg_id));
4032 dict_add_number(dict, "priority", (long)cur->priority);
4033 dict_add_number(dict, "id", (long)cur->id);
4034 # if defined(FEAT_CONCEAL)
4035 if (cur->conceal_char)
4036 {
4037 char_u buf[MB_MAXBYTES + 1];
4038
4039 buf[(*mb_char2bytes)((int)cur->conceal_char, buf)] = NUL;
4040 dict_add_string(dict, "conceal", (char_u *)&buf);
4041 }
4042 # endif
4043 list_append_dict(rettv->vval.v_list, dict);
4044 cur = cur->next;
4045 }
4046 #endif
4047 }
4048
4049 /*
4050 * "matchadd()" function
4051 */
4052 void
4053 f_matchadd(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
4054 {
4055 #ifdef FEAT_SEARCH_EXTRA
4056 char_u buf[NUMBUFLEN];
4057 char_u *grp = tv_get_string_buf_chk(&argvars[0], buf); /* group */
4058 char_u *pat = tv_get_string_buf_chk(&argvars[1], buf); /* pattern */
4059 int prio = 10; /* default priority */
4060 int id = -1;
4061 int error = FALSE;
4062 char_u *conceal_char = NULL;
4063 win_T *win = curwin;
4064
4065 rettv->vval.v_number = -1;
4066
4067 if (grp == NULL || pat == NULL)
4068 return;
4069 if (argvars[2].v_type != VAR_UNKNOWN)
4070 {
4071 prio = (int)tv_get_number_chk(&argvars[2], &error);
4072 if (argvars[3].v_type != VAR_UNKNOWN)
4073 {
4074 id = (int)tv_get_number_chk(&argvars[3], &error);
4075 if (argvars[4].v_type != VAR_UNKNOWN
4076 && matchadd_dict_arg(&argvars[4], &conceal_char, &win) == FAIL)
4077 return;
4078 }
4079 }
4080 if (error == TRUE)
4081 return;
4082 if (id >= 1 && id <= 3)
4083 {
4084 semsg(_("E798: ID is reserved for \":match\": %d"), id);
4085 return;
4086 }
4087
4088 rettv->vval.v_number = match_add(win, grp, pat, prio, id, NULL,
4089 conceal_char);
4090 #endif
4091 }
4092
4093 /*
4094 * "matchaddpos()" function
4095 */
4096 void
4097 f_matchaddpos(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
4098 {
4099 #ifdef FEAT_SEARCH_EXTRA
4100 char_u buf[NUMBUFLEN];
4101 char_u *group;
4102 int prio = 10;
4103 int id = -1;
4104 int error = FALSE;
4105 list_T *l;
4106 char_u *conceal_char = NULL;
4107 win_T *win = curwin;
4108
4109 rettv->vval.v_number = -1;
4110
4111 group = tv_get_string_buf_chk(&argvars[0], buf);
4112 if (group == NULL)
4113 return;
4114
4115 if (argvars[1].v_type != VAR_LIST)
4116 {
4117 semsg(_(e_listarg), "matchaddpos()");
4118 return;
4119 }
4120 l = argvars[1].vval.v_list;
4121 if (l == NULL)
4122 return;
4123
4124 if (argvars[2].v_type != VAR_UNKNOWN)
4125 {
4126 prio = (int)tv_get_number_chk(&argvars[2], &error);
4127 if (argvars[3].v_type != VAR_UNKNOWN)
4128 {
4129 id = (int)tv_get_number_chk(&argvars[3], &error);
4130
4131 if (argvars[4].v_type != VAR_UNKNOWN
4132 && matchadd_dict_arg(&argvars[4], &conceal_char, &win) == FAIL)
4133 return;
4134 }
4135 }
4136 if (error == TRUE)
4137 return;
4138
4139 /* id == 3 is ok because matchaddpos() is supposed to substitute :3match */
4140 if (id == 1 || id == 2)
4141 {
4142 semsg(_("E798: ID is reserved for \":match\": %d"), id);
4143 return;
4144 }
4145
4146 rettv->vval.v_number = match_add(win, group, NULL, prio, id, l,
4147 conceal_char);
4148 #endif
4149 }
4150
4151 /*
4152 * "matcharg()" function
4153 */
4154 void
4155 f_matcharg(typval_T *argvars UNUSED, typval_T *rettv)
4156 {
4157 if (rettv_list_alloc(rettv) == OK)
4158 {
4159 #ifdef FEAT_SEARCH_EXTRA
4160 int id = (int)tv_get_number(&argvars[0]);
4161 matchitem_T *m;
4162
4163 if (id >= 1 && id <= 3)
4164 {
4165 if ((m = (matchitem_T *)get_match(curwin, id)) != NULL)
4166 {
4167 list_append_string(rettv->vval.v_list,
4168 syn_id2name(m->hlg_id), -1);
4169 list_append_string(rettv->vval.v_list, m->pattern, -1);
4170 }
4171 else
4172 {
4173 list_append_string(rettv->vval.v_list, NULL, -1);
4174 list_append_string(rettv->vval.v_list, NULL, -1);
4175 }
4176 }
4177 #endif
4178 }
4179 }
4180
4181 /*
4182 * "matchdelete()" function
4183 */
4184 void
4185 f_matchdelete(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
4186 {
4187 #ifdef FEAT_SEARCH_EXTRA
4188 win_T *win = get_optional_window(argvars, 1);
4189
4190 if (win == NULL)
4191 rettv->vval.v_number = -1;
4192 else
4193 rettv->vval.v_number = match_delete(win,
4194 (int)tv_get_number(&argvars[0]), TRUE);
4195 #endif
4196 }