Mercurial > vim
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 } |