Mercurial > vim
comparison src/quickfix.c @ 30803:bba8d0f45cb8 v9.0.0736
patch 9.0.0736: quickfix listing does not handle very long messages
Commit: https://github.com/vim/vim/commit/f8412c9d7cc487dacf47a217ae947da68a525c53
Author: Yegappan Lakshmanan <yegappan@yahoo.com>
Date: Thu Oct 13 11:59:22 2022 +0100
patch 9.0.0736: quickfix listing does not handle very long messages
Problem: Quickfix listing does not handle very long messages.
Solution: Use a growarray instead of a fixed size buffer. (Yegappan
Lakshmanan, closes #11357)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Thu, 13 Oct 2022 13:00:07 +0200 |
parents | b01273bbc75e |
children | d7066cbac096 |
comparison
equal
deleted
inserted
replaced
30802:15130b9714c5 | 30803:bba8d0f45cb8 |
---|---|
174 static int qf_get_fnum(qf_list_T *qfl, char_u *, char_u *); | 174 static int qf_get_fnum(qf_list_T *qfl, char_u *, char_u *); |
175 static char_u *qf_push_dir(char_u *, struct dir_stack_T **, int is_file_stack); | 175 static char_u *qf_push_dir(char_u *, struct dir_stack_T **, int is_file_stack); |
176 static char_u *qf_pop_dir(struct dir_stack_T **); | 176 static char_u *qf_pop_dir(struct dir_stack_T **); |
177 static char_u *qf_guess_filepath(qf_list_T *qfl, char_u *); | 177 static char_u *qf_guess_filepath(qf_list_T *qfl, char_u *); |
178 static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, int newwin); | 178 static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, int newwin); |
179 static void qf_fmt_text(char_u *text, char_u *buf, int bufsize); | 179 static void qf_fmt_text(garray_T *gap, char_u *text); |
180 static void qf_range_text(qfline_T *qfp, char_u *buf, int bufsize); | 180 static void qf_range_text(garray_T *gap, qfline_T *qfp); |
181 static int qf_win_pos_update(qf_info_T *qi, int old_qf_index); | 181 static int qf_win_pos_update(qf_info_T *qi, int old_qf_index); |
182 static win_T *qf_find_win(qf_info_T *qi); | 182 static win_T *qf_find_win(qf_info_T *qi); |
183 static buf_T *qf_find_buf(qf_info_T *qi); | 183 static buf_T *qf_find_buf(qf_info_T *qi); |
184 static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last); | 184 static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last); |
185 static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int qf_winid); | 185 static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int qf_winid); |
3284 qfline_T *qf_ptr, | 3284 qfline_T *qf_ptr, |
3285 buf_T *old_curbuf, | 3285 buf_T *old_curbuf, |
3286 linenr_T old_lnum) | 3286 linenr_T old_lnum) |
3287 { | 3287 { |
3288 linenr_T i; | 3288 linenr_T i; |
3289 int len; | 3289 garray_T ga; |
3290 | 3290 |
3291 // Update the screen before showing the message, unless the screen | 3291 // Update the screen before showing the message, unless the screen |
3292 // scrolled up. | 3292 // scrolled up. |
3293 if (!msg_scrolled) | 3293 if (!msg_scrolled) |
3294 update_topline_redraw(); | 3294 update_topline_redraw(); |
3295 sprintf((char *)IObuff, _("(%d of %d)%s%s: "), qf_index, | 3295 vim_snprintf((char *)IObuff, IOSIZE, _("(%d of %d)%s%s: "), qf_index, |
3296 qf_get_curlist(qi)->qf_count, | 3296 qf_get_curlist(qi)->qf_count, |
3297 qf_ptr->qf_cleared ? _(" (line deleted)") : "", | 3297 qf_ptr->qf_cleared ? _(" (line deleted)") : "", |
3298 (char *)qf_types(qf_ptr->qf_type, qf_ptr->qf_nr)); | 3298 (char *)qf_types(qf_ptr->qf_type, qf_ptr->qf_nr)); |
3299 // Add the message, skipping leading whitespace and newlines. | 3299 // Add the message, skipping leading whitespace and newlines. |
3300 len = (int)STRLEN(IObuff); | 3300 ga_init2(&ga, 1, 256); |
3301 qf_fmt_text(skipwhite(qf_ptr->qf_text), IObuff + len, IOSIZE - len); | 3301 ga_concat(&ga, IObuff); |
3302 qf_fmt_text(&ga, skipwhite(qf_ptr->qf_text)); | |
3302 | 3303 |
3303 // Output the message. Overwrite to avoid scrolling when the 'O' | 3304 // Output the message. Overwrite to avoid scrolling when the 'O' |
3304 // flag is present in 'shortmess'; But when not jumping, print the | 3305 // flag is present in 'shortmess'; But when not jumping, print the |
3305 // whole message. | 3306 // whole message. |
3306 i = msg_scroll; | 3307 i = msg_scroll; |
3307 if (curbuf == old_curbuf && curwin->w_cursor.lnum == old_lnum) | 3308 if (curbuf == old_curbuf && curwin->w_cursor.lnum == old_lnum) |
3308 msg_scroll = TRUE; | 3309 msg_scroll = TRUE; |
3309 else if (!msg_scrolled && shortmess(SHM_OVERALL)) | 3310 else if (!msg_scrolled && shortmess(SHM_OVERALL)) |
3310 msg_scroll = FALSE; | 3311 msg_scroll = FALSE; |
3311 msg_attr_keep((char *)IObuff, 0, TRUE); | 3312 msg_attr_keep((char *)ga.ga_data, 0, TRUE); |
3312 msg_scroll = i; | 3313 msg_scroll = i; |
3314 ga_clear(&ga); | |
3313 } | 3315 } |
3314 | 3316 |
3315 /* | 3317 /* |
3316 * Find a usable window for opening a file from the quickfix/location list. If | 3318 * Find a usable window for opening a file from the quickfix/location list. If |
3317 * a window is not found then open a new window. If 'newwin' is TRUE, then open | 3319 * a window is not found then open a new window. If 'newwin' is TRUE, then open |
3572 qf_list_entry(qfline_T *qfp, int qf_idx, int cursel) | 3574 qf_list_entry(qfline_T *qfp, int qf_idx, int cursel) |
3573 { | 3575 { |
3574 char_u *fname; | 3576 char_u *fname; |
3575 buf_T *buf; | 3577 buf_T *buf; |
3576 int filter_entry; | 3578 int filter_entry; |
3579 garray_T ga; | |
3577 | 3580 |
3578 fname = NULL; | 3581 fname = NULL; |
3579 if (qfp->qf_module != NULL && *qfp->qf_module != NUL) | 3582 if (qfp->qf_module != NULL && *qfp->qf_module != NUL) |
3580 vim_snprintf((char *)IObuff, IOSIZE, "%2d %s", qf_idx, | 3583 vim_snprintf((char *)IObuff, IOSIZE, "%2d %s", qf_idx, |
3581 (char *)qfp->qf_module); | 3584 (char *)qfp->qf_module); |
3612 msg_putchar('\n'); | 3615 msg_putchar('\n'); |
3613 msg_outtrans_attr(IObuff, cursel ? HL_ATTR(HLF_QFL) : qfFileAttr); | 3616 msg_outtrans_attr(IObuff, cursel ? HL_ATTR(HLF_QFL) : qfFileAttr); |
3614 | 3617 |
3615 if (qfp->qf_lnum != 0) | 3618 if (qfp->qf_lnum != 0) |
3616 msg_puts_attr(":", qfSepAttr); | 3619 msg_puts_attr(":", qfSepAttr); |
3620 ga_init2(&ga, 1, 256); | |
3617 if (qfp->qf_lnum == 0) | 3621 if (qfp->qf_lnum == 0) |
3618 IObuff[0] = NUL; | 3622 ga_append(&ga, NUL); |
3619 else | 3623 else |
3620 qf_range_text(qfp, IObuff, IOSIZE); | 3624 qf_range_text(&ga, qfp); |
3621 sprintf((char *)IObuff + STRLEN(IObuff), "%s", | 3625 ga_concat(&ga, qf_types(qfp->qf_type, qfp->qf_nr)); |
3622 (char *)qf_types(qfp->qf_type, qfp->qf_nr)); | 3626 ga_append(&ga, NUL); |
3623 msg_puts_attr((char *)IObuff, qfLineAttr); | 3627 msg_puts_attr((char *)ga.ga_data, qfLineAttr); |
3628 ga_clear(&ga); | |
3624 msg_puts_attr(":", qfSepAttr); | 3629 msg_puts_attr(":", qfSepAttr); |
3625 if (qfp->qf_pattern != NULL) | 3630 if (qfp->qf_pattern != NULL) |
3626 { | 3631 { |
3627 qf_fmt_text(qfp->qf_pattern, IObuff, IOSIZE); | 3632 qf_fmt_text(&ga, qfp->qf_pattern); |
3628 msg_puts((char *)IObuff); | 3633 msg_puts((char *)ga.ga_data); |
3634 ga_clear(&ga); | |
3629 msg_puts_attr(":", qfSepAttr); | 3635 msg_puts_attr(":", qfSepAttr); |
3630 } | 3636 } |
3631 msg_puts(" "); | 3637 msg_puts(" "); |
3632 | 3638 |
3633 { | 3639 { |
3634 char_u *tbuf = IObuff; | |
3635 size_t tbuflen = IOSIZE; | |
3636 size_t len = STRLEN(qfp->qf_text) + 3; | |
3637 | |
3638 if (len > IOSIZE) | |
3639 { | |
3640 tbuf = alloc(len); | |
3641 if (tbuf != NULL) | |
3642 tbuflen = len; | |
3643 else | |
3644 tbuf = IObuff; | |
3645 } | |
3646 | |
3647 // Remove newlines and leading whitespace from the text. For an | 3640 // Remove newlines and leading whitespace from the text. For an |
3648 // unrecognized line keep the indent, the compiler may mark a word | 3641 // unrecognized line keep the indent, the compiler may mark a word |
3649 // with ^^^^. | 3642 // with ^^^^. |
3650 qf_fmt_text((fname != NULL || qfp->qf_lnum != 0) | 3643 qf_fmt_text(&ga, (fname != NULL || qfp->qf_lnum != 0) |
3651 ? skipwhite(qfp->qf_text) : qfp->qf_text, | 3644 ? skipwhite(qfp->qf_text) : qfp->qf_text); |
3652 tbuf, (int)tbuflen); | 3645 msg_prt_line((char_u *)ga.ga_data, FALSE); |
3653 msg_prt_line(tbuf, FALSE); | 3646 ga_clear(&ga); |
3654 | |
3655 if (tbuf != IObuff) | |
3656 vim_free(tbuf); | |
3657 } | 3647 } |
3658 out_flush(); // show one line at a time | 3648 out_flush(); // show one line at a time |
3659 } | 3649 } |
3660 | 3650 |
3661 /* | 3651 /* |
3736 } | 3726 } |
3737 } | 3727 } |
3738 | 3728 |
3739 /* | 3729 /* |
3740 * Remove newlines and leading whitespace from an error message. | 3730 * Remove newlines and leading whitespace from an error message. |
3741 * Put the result in "buf[bufsize]". | 3731 * Add the result to the grow array "gap". |
3742 */ | 3732 */ |
3743 static void | 3733 static void |
3744 qf_fmt_text(char_u *text, char_u *buf, int bufsize) | 3734 qf_fmt_text(garray_T *gap, char_u *text) |
3745 { | 3735 { |
3746 int i; | |
3747 char_u *p = text; | 3736 char_u *p = text; |
3748 | 3737 |
3749 for (i = 0; *p != NUL && i < bufsize - 1; ++i) | 3738 while (*p != NUL) |
3750 { | 3739 { |
3751 if (*p == '\n') | 3740 if (*p == '\n') |
3752 { | 3741 { |
3753 buf[i] = ' '; | 3742 ga_append(gap, ' '); |
3754 while (*++p != NUL) | 3743 while (*++p != NUL) |
3755 if (!VIM_ISWHITE(*p) && *p != '\n') | 3744 if (!VIM_ISWHITE(*p) && *p != '\n') |
3756 break; | 3745 break; |
3757 } | 3746 } |
3758 else | 3747 else |
3759 buf[i] = *p++; | 3748 ga_append(gap, *p++); |
3760 } | 3749 } |
3761 buf[i] = NUL; | 3750 |
3762 } | 3751 ga_append(gap, NUL); |
3763 | 3752 } |
3764 /* | 3753 |
3765 * Range information from lnum, col, end_lnum, and end_col. | 3754 /* |
3766 * Put the result in "buf[bufsize]". | 3755 * Add the range information from the lnum, col, end_lnum, and end_col values |
3756 * of a quickfix entry to the grow array "gap". | |
3767 */ | 3757 */ |
3768 static void | 3758 static void |
3769 qf_range_text(qfline_T *qfp, char_u *buf, int bufsize) | 3759 qf_range_text(garray_T *gap, qfline_T *qfp) |
3770 { | 3760 { |
3761 char_u *buf = IObuff; | |
3762 int bufsize = IOSIZE; | |
3771 int len; | 3763 int len; |
3764 | |
3772 vim_snprintf((char *)buf, bufsize, "%ld", qfp->qf_lnum); | 3765 vim_snprintf((char *)buf, bufsize, "%ld", qfp->qf_lnum); |
3773 len = (int)STRLEN(buf); | 3766 len = (int)STRLEN(buf); |
3774 | 3767 |
3775 if (qfp->qf_end_lnum > 0 && qfp->qf_lnum != qfp->qf_end_lnum) | 3768 if (qfp->qf_end_lnum > 0 && qfp->qf_lnum != qfp->qf_end_lnum) |
3776 { | 3769 { |
3788 "-%d", qfp->qf_end_col); | 3781 "-%d", qfp->qf_end_col); |
3789 len += (int)STRLEN(buf + len); | 3782 len += (int)STRLEN(buf + len); |
3790 } | 3783 } |
3791 } | 3784 } |
3792 buf[len] = NUL; | 3785 buf[len] = NUL; |
3786 | |
3787 ga_concat_len(gap, buf, len); | |
3793 } | 3788 } |
3794 | 3789 |
3795 /* | 3790 /* |
3796 * Display information (list number, list size and the title) about a | 3791 * Display information (list number, list size and the title) about a |
3797 * quickfix/location list. | 3792 * quickfix/location list. |
4595 qfline_T *qfp, | 4590 qfline_T *qfp, |
4596 char_u *dirname, | 4591 char_u *dirname, |
4597 int first_bufline, | 4592 int first_bufline, |
4598 char_u *qftf_str) | 4593 char_u *qftf_str) |
4599 { | 4594 { |
4600 int len; | |
4601 buf_T *errbuf; | 4595 buf_T *errbuf; |
4596 garray_T ga; | |
4597 | |
4598 ga_init2(&ga, 1, 256); | |
4602 | 4599 |
4603 // If the 'quickfixtextfunc' function returned a non-empty custom string | 4600 // If the 'quickfixtextfunc' function returned a non-empty custom string |
4604 // for this entry, then use it. | 4601 // for this entry, then use it. |
4605 if (qftf_str != NULL && *qftf_str != NUL) | 4602 if (qftf_str != NULL && *qftf_str != NUL) |
4606 vim_strncpy(IObuff, qftf_str, IOSIZE - 1); | 4603 ga_concat(&ga, qftf_str); |
4607 else | 4604 else |
4608 { | 4605 { |
4609 if (qfp->qf_module != NULL) | 4606 if (qfp->qf_module != NULL) |
4610 { | 4607 ga_concat(&ga, qfp->qf_module); |
4611 vim_strncpy(IObuff, qfp->qf_module, IOSIZE - 1); | |
4612 len = (int)STRLEN(IObuff); | |
4613 } | |
4614 else if (qfp->qf_fnum != 0 | 4608 else if (qfp->qf_fnum != 0 |
4615 && (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL | 4609 && (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL |
4616 && errbuf->b_fname != NULL) | 4610 && errbuf->b_fname != NULL) |
4617 { | 4611 { |
4618 if (qfp->qf_type == 1) // :helpgrep | 4612 if (qfp->qf_type == 1) // :helpgrep |
4619 vim_strncpy(IObuff, gettail(errbuf->b_fname), IOSIZE - 1); | 4613 ga_concat(&ga, gettail(errbuf->b_fname)); |
4620 else | 4614 else |
4621 { | 4615 { |
4622 // Shorten the file name if not done already. | 4616 // Shorten the file name if not done already. |
4623 // For optimization, do this only for the first entry in a | 4617 // For optimization, do this only for the first entry in a |
4624 // buffer. | 4618 // buffer. |
4627 { | 4621 { |
4628 if (*dirname == NUL) | 4622 if (*dirname == NUL) |
4629 mch_dirname(dirname, MAXPATHL); | 4623 mch_dirname(dirname, MAXPATHL); |
4630 shorten_buf_fname(errbuf, dirname, FALSE); | 4624 shorten_buf_fname(errbuf, dirname, FALSE); |
4631 } | 4625 } |
4632 vim_strncpy(IObuff, errbuf->b_fname, IOSIZE - 1); | 4626 ga_concat(&ga, errbuf->b_fname); |
4633 } | 4627 } |
4634 len = (int)STRLEN(IObuff); | 4628 } |
4635 } | 4629 |
4636 else | 4630 ga_append(&ga, '|'); |
4637 len = 0; | |
4638 | |
4639 if (len < IOSIZE - 1) | |
4640 IObuff[len++] = '|'; | |
4641 | 4631 |
4642 if (qfp->qf_lnum > 0) | 4632 if (qfp->qf_lnum > 0) |
4643 { | 4633 { |
4644 qf_range_text(qfp, IObuff + len, IOSIZE - len); | 4634 qf_range_text(&ga, qfp); |
4645 len += (int)STRLEN(IObuff + len); | 4635 ga_concat(&ga, qf_types(qfp->qf_type, qfp->qf_nr)); |
4646 | |
4647 vim_snprintf((char *)IObuff + len, IOSIZE - len, "%s", | |
4648 (char *)qf_types(qfp->qf_type, qfp->qf_nr)); | |
4649 len += (int)STRLEN(IObuff + len); | |
4650 } | 4636 } |
4651 else if (qfp->qf_pattern != NULL) | 4637 else if (qfp->qf_pattern != NULL) |
4652 { | 4638 qf_fmt_text(&ga, qfp->qf_pattern); |
4653 qf_fmt_text(qfp->qf_pattern, IObuff + len, IOSIZE - len); | 4639 ga_append(&ga, '|'); |
4654 len += (int)STRLEN(IObuff + len); | 4640 ga_append(&ga, ' '); |
4655 } | |
4656 if (len < IOSIZE - 2) | |
4657 { | |
4658 IObuff[len++] = '|'; | |
4659 IObuff[len++] = ' '; | |
4660 } | |
4661 | 4641 |
4662 // Remove newlines and leading whitespace from the text. | 4642 // Remove newlines and leading whitespace from the text. |
4663 // For an unrecognized line keep the indent, the compiler may | 4643 // For an unrecognized line keep the indent, the compiler may |
4664 // mark a word with ^^^^. | 4644 // mark a word with ^^^^. |
4665 qf_fmt_text(len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text, | 4645 qf_fmt_text(&ga, ga.ga_len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text); |
4666 IObuff + len, IOSIZE - len); | 4646 } |
4667 } | 4647 |
4668 | 4648 ga_append(&ga, NUL); |
4669 if (ml_append_buf(buf, lnum, IObuff, | 4649 |
4670 (colnr_T)STRLEN(IObuff) + 1, FALSE) == FAIL) | 4650 if (ml_append_buf(buf, lnum, ga.ga_data, ga.ga_len + 1, FALSE) == FAIL) |
4671 return FAIL; | 4651 return FAIL; |
4652 | |
4653 ga_clear(&ga); | |
4672 | 4654 |
4673 return OK; | 4655 return OK; |
4674 } | 4656 } |
4675 | 4657 |
4676 /* | 4658 /* |