blob: fc65ad4a4570ea7c5b511044cb5f252b19b24edf [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar071d4272004-06-13 20:20:40 +00002 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
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.
8 */
9
10/*
11 * quickfix.c: functions for quickfix mode, using a file with error messages
12 */
13
14#include "vim.h"
15
16#if defined(FEAT_QUICKFIX) || defined(PROTO)
17
18struct dir_stack_T
19{
20 struct dir_stack_T *next;
21 char_u *dirname;
22};
23
Bram Moolenaar071d4272004-06-13 20:20:40 +000024/*
Bram Moolenaar68b76a62005-03-25 21:53:48 +000025 * For each error the next struct is allocated and linked in a list.
Bram Moolenaar071d4272004-06-13 20:20:40 +000026 */
Bram Moolenaar68b76a62005-03-25 21:53:48 +000027typedef struct qfline_S qfline_T;
28struct qfline_S
Bram Moolenaar071d4272004-06-13 20:20:40 +000029{
Bram Moolenaar68b76a62005-03-25 21:53:48 +000030 qfline_T *qf_next; /* pointer to next error in the list */
31 qfline_T *qf_prev; /* pointer to previous error in the list */
32 linenr_T qf_lnum; /* line number where the error occurred */
33 int qf_fnum; /* file number for the line */
34 int qf_col; /* column where the error occurred */
35 int qf_nr; /* error number */
36 char_u *qf_pattern; /* search pattern for the error */
37 char_u *qf_text; /* description of the error */
38 char_u qf_viscol; /* set to TRUE if qf_col is screen column */
39 char_u qf_cleared; /* set to TRUE if line has been deleted */
40 char_u qf_type; /* type of the error (mostly 'E'); 1 for
Bram Moolenaar071d4272004-06-13 20:20:40 +000041 :helpgrep */
Bram Moolenaar68b76a62005-03-25 21:53:48 +000042 char_u qf_valid; /* valid error message detected */
Bram Moolenaar071d4272004-06-13 20:20:40 +000043};
44
45/*
46 * There is a stack of error lists.
47 */
48#define LISTCOUNT 10
49
Bram Moolenaar6a8958d2017-06-22 21:33:20 +020050/*
51 * Quickfix/Location list definition
52 * Contains a list of entries (qfline_T). qf_start points to the first entry
53 * and qf_last points to the last entry. qf_count contains the list size.
54 *
55 * Usually the list contains one or more entries. But an empty list can be
56 * created using setqflist()/setloclist() with a title and/or user context
57 * information and entries can be added later using setqflist()/setloclist().
58 */
Bram Moolenaard12f5c12006-01-25 22:10:52 +000059typedef struct qf_list_S
Bram Moolenaar071d4272004-06-13 20:20:40 +000060{
Bram Moolenaara539f4f2017-08-30 20:33:55 +020061 int_u qf_id; /* Unique identifier for this list */
Bram Moolenaar68b76a62005-03-25 21:53:48 +000062 qfline_T *qf_start; /* pointer to the first error */
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +020063 qfline_T *qf_last; /* pointer to the last error */
Bram Moolenaar68b76a62005-03-25 21:53:48 +000064 qfline_T *qf_ptr; /* pointer to the current error */
Bram Moolenaar6a8958d2017-06-22 21:33:20 +020065 int qf_count; /* number of errors (0 means empty list) */
Bram Moolenaar68b76a62005-03-25 21:53:48 +000066 int qf_index; /* current index in the error list */
67 int qf_nonevalid; /* TRUE if not a single valid entry found */
Bram Moolenaar7fd73202010-07-25 16:58:46 +020068 char_u *qf_title; /* title derived from the command that created
Bram Moolenaar6a8958d2017-06-22 21:33:20 +020069 * the error list or set by setqflist */
Bram Moolenaar8f77c5a2017-04-30 14:21:00 +020070 typval_T *qf_ctx; /* context set by setqflist/setloclist */
Bram Moolenaara7df8c72017-07-19 13:23:06 +020071
72 struct dir_stack_T *qf_dir_stack;
73 char_u *qf_directory;
74 struct dir_stack_T *qf_file_stack;
75 char_u *qf_currfile;
76 int qf_multiline;
77 int qf_multiignore;
78 int qf_multiscan;
Bram Moolenaarb254af32017-12-18 19:48:58 +010079 long qf_changedtick;
Bram Moolenaard12f5c12006-01-25 22:10:52 +000080} qf_list_T;
Bram Moolenaar071d4272004-06-13 20:20:40 +000081
Bram Moolenaar6a8958d2017-06-22 21:33:20 +020082/*
83 * Quickfix/Location list stack definition
84 * Contains a list of quickfix/location lists (qf_list_T)
85 */
Bram Moolenaard12f5c12006-01-25 22:10:52 +000086struct qf_info_S
87{
88 /*
89 * Count of references to this list. Used only for location lists.
90 * When a location list window reference this list, qf_refcount
91 * will be 2. Otherwise, qf_refcount will be 1. When qf_refcount
92 * reaches 0, the list is freed.
93 */
94 int qf_refcount;
95 int qf_listcount; /* current number of lists */
96 int qf_curlist; /* current error list */
97 qf_list_T qf_lists[LISTCOUNT];
98};
99
100static qf_info_T ql_info; /* global quickfix list */
Bram Moolenaara539f4f2017-08-30 20:33:55 +0200101static int_u last_qf_id = 0; /* Last used quickfix list id */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000102
Bram Moolenaar68b76a62005-03-25 21:53:48 +0000103#define FMT_PATTERNS 10 /* maximum number of % recognized */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000104
105/*
106 * Structure used to hold the info of one part of 'errorformat'
107 */
Bram Moolenaar01265852006-03-20 21:50:15 +0000108typedef struct efm_S efm_T;
109struct efm_S
Bram Moolenaar071d4272004-06-13 20:20:40 +0000110{
111 regprog_T *prog; /* pre-formatted part of 'errorformat' */
Bram Moolenaar01265852006-03-20 21:50:15 +0000112 efm_T *next; /* pointer to next (NULL if last) */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000113 char_u addr[FMT_PATTERNS]; /* indices of used % patterns */
114 char_u prefix; /* prefix of this format line: */
115 /* 'D' enter directory */
116 /* 'X' leave directory */
117 /* 'A' start of multi-line message */
118 /* 'E' error message */
119 /* 'W' warning message */
120 /* 'I' informational message */
121 /* 'C' continuation line */
122 /* 'Z' end of multi-line message */
123 /* 'G' general, unspecific message */
124 /* 'P' push file (partial) message */
125 /* 'Q' pop/quit file (partial) message */
126 /* 'O' overread (partial) message */
127 char_u flags; /* additional flags given in prefix */
128 /* '-' do not include this line */
Bram Moolenaar4770d092006-01-12 23:22:24 +0000129 /* '+' include whole line in message */
Bram Moolenaar01265852006-03-20 21:50:15 +0000130 int conthere; /* %> used */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000131};
132
Bram Moolenaar63bed3d2016-11-12 15:36:54 +0100133static efm_T *fmt_start = NULL; /* cached across qf_parse_line() calls */
134
Bram Moolenaara7df8c72017-07-19 13:23:06 +0200135static int qf_init_ext(qf_info_T *qi, int qf_idx, char_u *efile, buf_T *buf, typval_T *tv, char_u *errorformat, int newlist, linenr_T lnumfirst, linenr_T lnumlast, char_u *qf_title, char_u *enc);
Bram Moolenaara3921f42017-06-04 15:30:34 +0200136static void qf_store_title(qf_info_T *qi, int qf_idx, char_u *title);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +0100137static void qf_new_list(qf_info_T *qi, char_u *qf_title);
138static void ll_free_all(qf_info_T **pqi);
Bram Moolenaara3921f42017-06-04 15:30:34 +0200139static int qf_add_entry(qf_info_T *qi, int qf_idx, char_u *dir, char_u *fname, int bufnum, char_u *mesg, long lnum, int col, int vis_col, char_u *pattern, int nr, int type, int valid);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +0100140static qf_info_T *ll_new_list(void);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +0100141static void qf_free(qf_info_T *qi, int idx);
142static char_u *qf_types(int, int);
Bram Moolenaara7df8c72017-07-19 13:23:06 +0200143static int qf_get_fnum(qf_info_T *qi, int qf_idx, char_u *, char_u *);
Bram Moolenaar361c8f02016-07-02 15:41:47 +0200144static char_u *qf_push_dir(char_u *, struct dir_stack_T **, int is_file_stack);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +0100145static char_u *qf_pop_dir(struct dir_stack_T **);
Bram Moolenaara7df8c72017-07-19 13:23:06 +0200146static char_u *qf_guess_filepath(qf_info_T *qi, int qf_idx, char_u *);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +0100147static void qf_fmt_text(char_u *text, char_u *buf, int bufsize);
148static void qf_clean_dir_stack(struct dir_stack_T **);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +0100149static int qf_win_pos_update(qf_info_T *qi, int old_qf_index);
150static int is_qf_win(win_T *win, qf_info_T *qi);
151static win_T *qf_find_win(qf_info_T *qi);
152static buf_T *qf_find_buf(qf_info_T *qi);
Bram Moolenaar864293a2016-06-02 13:40:04 +0200153static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +0100154static void qf_set_title_var(qf_info_T *qi);
Bram Moolenaar864293a2016-06-02 13:40:04 +0200155static void qf_fill_buffer(qf_info_T *qi, buf_T *buf, qfline_T *old_last);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +0100156static char_u *get_mef_name(void);
157static void restore_start_dir(char_u *dirname_start);
158static buf_T *load_dummy_buffer(char_u *fname, char_u *dirname_start, char_u *resulting_dir);
159static void wipe_dummy_buffer(buf_T *buf, char_u *dirname_start);
160static void unload_dummy_buffer(buf_T *buf, char_u *dirname_start);
161static qf_info_T *ll_get_or_alloc_list(win_T *);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000162
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000163/* Quickfix window check helper macro */
164#define IS_QF_WINDOW(wp) (bt_quickfix(wp->w_buffer) && wp->w_llist_ref == NULL)
165/* Location list window check helper macro */
166#define IS_LL_WINDOW(wp) (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL)
167/*
168 * Return location list for window 'wp'
169 * For location list window, return the referenced location list
170 */
171#define GET_LOC_LIST(wp) (IS_LL_WINDOW(wp) ? wp->w_llist_ref : wp->w_llist)
172
Bram Moolenaar071d4272004-06-13 20:20:40 +0000173/*
Bram Moolenaar6dd4a532017-05-28 07:56:36 +0200174 * Looking up a buffer can be slow if there are many. Remember the last one
175 * to make this a lot faster if there are multiple matches in the same file.
176 */
Bram Moolenaar45e5fd12017-06-04 14:58:02 +0200177static char_u *qf_last_bufname = NULL;
178static bufref_T qf_last_bufref = {NULL, 0, 0};
Bram Moolenaar6dd4a532017-05-28 07:56:36 +0200179
180/*
Bram Moolenaar86b68352004-12-27 21:59:20 +0000181 * Read the errorfile "efile" into memory, line by line, building the error
Bram Moolenaar7fd73202010-07-25 16:58:46 +0200182 * list. Set the error list's title to qf_title.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000183 * Return -1 for error, number of errors for success.
184 */
185 int
Bram Moolenaaref6b8de2017-09-14 13:57:37 +0200186qf_init(win_T *wp,
187 char_u *efile,
188 char_u *errorformat,
189 int newlist, /* TRUE: start a new error list */
190 char_u *qf_title,
191 char_u *enc)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000192{
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000193 qf_info_T *qi = &ql_info;
194
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000195 if (wp != NULL)
Bram Moolenaarc7453f52006-02-10 23:20:28 +0000196 {
197 qi = ll_get_or_alloc_list(wp);
198 if (qi == NULL)
199 return FAIL;
200 }
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000201
Bram Moolenaara7df8c72017-07-19 13:23:06 +0200202 return qf_init_ext(qi, qi->qf_curlist, efile, curbuf, NULL, errorformat,
203 newlist, (linenr_T)0, (linenr_T)0, qf_title, enc);
Bram Moolenaar86b68352004-12-27 21:59:20 +0000204}
205
206/*
Bram Moolenaar6be8c8e2016-04-30 13:17:09 +0200207 * Maximum number of bytes allowed per line while reading a errorfile.
208 */
209#define LINE_MAXLEN 4096
210
Bram Moolenaar688e3d12016-06-26 22:05:54 +0200211static struct fmtpattern
212{
213 char_u convchar;
214 char *pattern;
215} fmt_pat[FMT_PATTERNS] =
216 {
217 {'f', ".\\+"}, /* only used when at end */
218 {'n', "\\d\\+"},
219 {'l', "\\d\\+"},
220 {'c', "\\d\\+"},
221 {'t', "."},
222 {'m', ".\\+"},
223 {'r', ".*"},
224 {'p', "[- .]*"},
225 {'v', "\\d\\+"},
226 {'s', ".\\+"}
227 };
228
229/*
230 * Converts a 'errorformat' string to regular expression pattern
231 */
232 static int
233efm_to_regpat(
Bram Moolenaaref6b8de2017-09-14 13:57:37 +0200234 char_u *efm,
235 int len,
236 efm_T *fmt_ptr,
237 char_u *regpat,
238 char_u *errmsg)
Bram Moolenaar688e3d12016-06-26 22:05:54 +0200239{
240 char_u *ptr;
241 char_u *efmp;
242 char_u *srcptr;
243 int round;
244 int idx = 0;
245
246 /*
247 * Build regexp pattern from current 'errorformat' option
248 */
249 ptr = regpat;
250 *ptr++ = '^';
251 round = 0;
252 for (efmp = efm; efmp < efm + len; ++efmp)
253 {
254 if (*efmp == '%')
255 {
256 ++efmp;
257 for (idx = 0; idx < FMT_PATTERNS; ++idx)
258 if (fmt_pat[idx].convchar == *efmp)
259 break;
260 if (idx < FMT_PATTERNS)
261 {
262 if (fmt_ptr->addr[idx])
263 {
264 sprintf((char *)errmsg,
265 _("E372: Too many %%%c in format string"), *efmp);
266 EMSG(errmsg);
267 return -1;
268 }
269 if ((idx
270 && idx < 6
271 && vim_strchr((char_u *)"DXOPQ",
272 fmt_ptr->prefix) != NULL)
273 || (idx == 6
274 && vim_strchr((char_u *)"OPQ",
275 fmt_ptr->prefix) == NULL))
276 {
277 sprintf((char *)errmsg,
278 _("E373: Unexpected %%%c in format string"), *efmp);
279 EMSG(errmsg);
280 return -1;
281 }
282 fmt_ptr->addr[idx] = (char_u)++round;
283 *ptr++ = '\\';
284 *ptr++ = '(';
285#ifdef BACKSLASH_IN_FILENAME
286 if (*efmp == 'f')
287 {
288 /* Also match "c:" in the file name, even when
289 * checking for a colon next: "%f:".
290 * "\%(\a:\)\=" */
291 STRCPY(ptr, "\\%(\\a:\\)\\=");
292 ptr += 10;
293 }
294#endif
295 if (*efmp == 'f' && efmp[1] != NUL)
296 {
297 if (efmp[1] != '\\' && efmp[1] != '%')
298 {
299 /* A file name may contain spaces, but this isn't
300 * in "\f". For "%f:%l:%m" there may be a ":" in
301 * the file name. Use ".\{-1,}x" instead (x is
302 * the next character), the requirement that :999:
303 * follows should work. */
304 STRCPY(ptr, ".\\{-1,}");
305 ptr += 7;
306 }
307 else
308 {
309 /* File name followed by '\\' or '%': include as
310 * many file name chars as possible. */
311 STRCPY(ptr, "\\f\\+");
312 ptr += 4;
313 }
314 }
315 else
316 {
317 srcptr = (char_u *)fmt_pat[idx].pattern;
318 while ((*ptr = *srcptr++) != NUL)
319 ++ptr;
320 }
321 *ptr++ = '\\';
322 *ptr++ = ')';
323 }
324 else if (*efmp == '*')
325 {
326 if (*++efmp == '[' || *efmp == '\\')
327 {
328 if ((*ptr++ = *efmp) == '[') /* %*[^a-z0-9] etc. */
329 {
330 if (efmp[1] == '^')
331 *ptr++ = *++efmp;
332 if (efmp < efm + len)
333 {
334 *ptr++ = *++efmp; /* could be ']' */
335 while (efmp < efm + len
336 && (*ptr++ = *++efmp) != ']')
337 /* skip */;
338 if (efmp == efm + len)
339 {
340 EMSG(_("E374: Missing ] in format string"));
341 return -1;
342 }
343 }
344 }
345 else if (efmp < efm + len) /* %*\D, %*\s etc. */
346 *ptr++ = *++efmp;
347 *ptr++ = '\\';
348 *ptr++ = '+';
349 }
350 else
351 {
352 /* TODO: scanf()-like: %*ud, %*3c, %*f, ... ? */
353 sprintf((char *)errmsg,
354 _("E375: Unsupported %%%c in format string"), *efmp);
355 EMSG(errmsg);
356 return -1;
357 }
358 }
359 else if (vim_strchr((char_u *)"%\\.^$~[", *efmp) != NULL)
360 *ptr++ = *efmp; /* regexp magic characters */
361 else if (*efmp == '#')
362 *ptr++ = '*';
363 else if (*efmp == '>')
364 fmt_ptr->conthere = TRUE;
365 else if (efmp == efm + 1) /* analyse prefix */
366 {
367 if (vim_strchr((char_u *)"+-", *efmp) != NULL)
368 fmt_ptr->flags = *efmp++;
369 if (vim_strchr((char_u *)"DXAEWICZGOPQ", *efmp) != NULL)
370 fmt_ptr->prefix = *efmp;
371 else
372 {
373 sprintf((char *)errmsg,
374 _("E376: Invalid %%%c in format string prefix"), *efmp);
375 EMSG(errmsg);
376 return -1;
377 }
378 }
379 else
380 {
381 sprintf((char *)errmsg,
382 _("E377: Invalid %%%c in format string"), *efmp);
383 EMSG(errmsg);
384 return -1;
385 }
386 }
387 else /* copy normal character */
388 {
389 if (*efmp == '\\' && efmp + 1 < efm + len)
390 ++efmp;
391 else if (vim_strchr((char_u *)".*^$~[", *efmp) != NULL)
392 *ptr++ = '\\'; /* escape regexp atoms */
393 if (*efmp)
394 *ptr++ = *efmp;
395 }
396 }
397 *ptr++ = '$';
398 *ptr = NUL;
399
400 return 0;
401}
402
403 static void
404free_efm_list(efm_T **efm_first)
405{
406 efm_T *efm_ptr;
407
408 for (efm_ptr = *efm_first; efm_ptr != NULL; efm_ptr = *efm_first)
409 {
410 *efm_first = efm_ptr->next;
411 vim_regfree(efm_ptr->prog);
412 vim_free(efm_ptr);
413 }
Bram Moolenaar63bed3d2016-11-12 15:36:54 +0100414 fmt_start = NULL;
Bram Moolenaar688e3d12016-06-26 22:05:54 +0200415}
416
417/* Parse 'errorformat' option */
418 static efm_T *
419parse_efm_option(char_u *efm)
420{
421 char_u *errmsg = NULL;
422 int errmsglen;
423 efm_T *fmt_ptr = NULL;
424 efm_T *fmt_first = NULL;
425 efm_T *fmt_last = NULL;
426 char_u *fmtstr = NULL;
427 int len;
428 int i;
429 int round;
430
431 errmsglen = CMDBUFFSIZE + 1;
432 errmsg = alloc_id(errmsglen, aid_qf_errmsg);
433 if (errmsg == NULL)
434 goto parse_efm_end;
435
436 /*
Bram Moolenaare87e6dd2016-07-17 19:25:04 +0200437 * Each part of the format string is copied and modified from errorformat
438 * to regex prog. Only a few % characters are allowed.
439 */
440
441 /*
Bram Moolenaar688e3d12016-06-26 22:05:54 +0200442 * Get some space to modify the format string into.
443 */
444 i = (FMT_PATTERNS * 3) + ((int)STRLEN(efm) << 2);
445 for (round = FMT_PATTERNS; round > 0; )
446 i += (int)STRLEN(fmt_pat[--round].pattern);
Bram Moolenaar0b05e492017-09-24 19:39:09 +0200447#ifdef BACKSLASH_IN_FILENAME
448 i += 12; /* "%f" can become twelve chars longer (see efm_to_regpat) */
Bram Moolenaar688e3d12016-06-26 22:05:54 +0200449#else
450 i += 2; /* "%f" can become two chars longer */
451#endif
452 if ((fmtstr = alloc(i)) == NULL)
453 goto parse_efm_error;
454
455 while (efm[0] != NUL)
456 {
457 /*
458 * Allocate a new eformat structure and put it at the end of the list
459 */
460 fmt_ptr = (efm_T *)alloc_clear((unsigned)sizeof(efm_T));
461 if (fmt_ptr == NULL)
462 goto parse_efm_error;
463 if (fmt_first == NULL) /* first one */
464 fmt_first = fmt_ptr;
465 else
466 fmt_last->next = fmt_ptr;
467 fmt_last = fmt_ptr;
468
469 /*
470 * Isolate one part in the 'errorformat' option
471 */
472 for (len = 0; efm[len] != NUL && efm[len] != ','; ++len)
473 if (efm[len] == '\\' && efm[len + 1] != NUL)
474 ++len;
475
476 if (efm_to_regpat(efm, len, fmt_ptr, fmtstr, errmsg) == -1)
477 goto parse_efm_error;
478 if ((fmt_ptr->prog = vim_regcomp(fmtstr, RE_MAGIC + RE_STRING)) == NULL)
479 goto parse_efm_error;
480 /*
481 * Advance to next part
482 */
483 efm = skip_to_option_part(efm + len); /* skip comma and spaces */
484 }
485
486 if (fmt_first == NULL) /* nothing found */
487 EMSG(_("E378: 'errorformat' contains no pattern"));
488
489 goto parse_efm_end;
490
491parse_efm_error:
492 free_efm_list(&fmt_first);
493
494parse_efm_end:
495 vim_free(fmtstr);
496 vim_free(errmsg);
497
498 return fmt_first;
499}
500
Bram Moolenaare0d37972016-07-15 22:36:01 +0200501enum {
502 QF_FAIL = 0,
503 QF_OK = 1,
504 QF_END_OF_INPUT = 2,
Bram Moolenaare87e6dd2016-07-17 19:25:04 +0200505 QF_NOMEM = 3,
506 QF_IGNORE_LINE = 4
Bram Moolenaare0d37972016-07-15 22:36:01 +0200507};
508
509typedef struct {
510 char_u *linebuf;
511 int linelen;
512 char_u *growbuf;
513 int growbufsiz;
514 FILE *fd;
515 typval_T *tv;
516 char_u *p_str;
517 listitem_T *p_li;
518 buf_T *buf;
519 linenr_T buflnum;
520 linenr_T lnumlast;
Bram Moolenaar2c7292d2017-03-05 17:43:31 +0100521 vimconv_T vc;
Bram Moolenaare0d37972016-07-15 22:36:01 +0200522} qfstate_T;
523
524 static char_u *
525qf_grow_linebuf(qfstate_T *state, int newsz)
526{
527 /*
528 * If the line exceeds LINE_MAXLEN exclude the last
529 * byte since it's not a NL character.
530 */
531 state->linelen = newsz > LINE_MAXLEN ? LINE_MAXLEN - 1 : newsz;
532 if (state->growbuf == NULL)
533 {
534 state->growbuf = alloc(state->linelen + 1);
535 if (state->growbuf == NULL)
536 return NULL;
537 state->growbufsiz = state->linelen;
538 }
539 else if (state->linelen > state->growbufsiz)
540 {
541 state->growbuf = vim_realloc(state->growbuf, state->linelen + 1);
542 if (state->growbuf == NULL)
543 return NULL;
544 state->growbufsiz = state->linelen;
545 }
546 return state->growbuf;
547}
548
549/*
550 * Get the next string (separated by newline) from state->p_str.
551 */
552 static int
553qf_get_next_str_line(qfstate_T *state)
554{
555 /* Get the next line from the supplied string */
556 char_u *p_str = state->p_str;
557 char_u *p;
558 int len;
559
560 if (*p_str == NUL) /* Reached the end of the string */
561 return QF_END_OF_INPUT;
562
563 p = vim_strchr(p_str, '\n');
564 if (p != NULL)
565 len = (int)(p - p_str) + 1;
566 else
567 len = (int)STRLEN(p_str);
568
569 if (len > IOSIZE - 2)
570 {
571 state->linebuf = qf_grow_linebuf(state, len);
572 if (state->linebuf == NULL)
573 return QF_NOMEM;
574 }
575 else
576 {
577 state->linebuf = IObuff;
578 state->linelen = len;
579 }
580 vim_strncpy(state->linebuf, p_str, state->linelen);
581
582 /*
583 * Increment using len in order to discard the rest of the
584 * line if it exceeds LINE_MAXLEN.
585 */
586 p_str += len;
587 state->p_str = p_str;
588
589 return QF_OK;
590}
591
592/*
593 * Get the next string from state->p_Li.
594 */
595 static int
596qf_get_next_list_line(qfstate_T *state)
597{
598 listitem_T *p_li = state->p_li;
599 int len;
600
601 while (p_li != NULL
602 && (p_li->li_tv.v_type != VAR_STRING
603 || p_li->li_tv.vval.v_string == NULL))
604 p_li = p_li->li_next; /* Skip non-string items */
605
606 if (p_li == NULL) /* End of the list */
607 {
608 state->p_li = NULL;
609 return QF_END_OF_INPUT;
610 }
611
612 len = (int)STRLEN(p_li->li_tv.vval.v_string);
613 if (len > IOSIZE - 2)
614 {
615 state->linebuf = qf_grow_linebuf(state, len);
616 if (state->linebuf == NULL)
617 return QF_NOMEM;
618 }
619 else
620 {
621 state->linebuf = IObuff;
622 state->linelen = len;
623 }
624
625 vim_strncpy(state->linebuf, p_li->li_tv.vval.v_string, state->linelen);
626
627 state->p_li = p_li->li_next; /* next item */
628 return QF_OK;
629}
630
631/*
632 * Get the next string from state->buf.
633 */
634 static int
635qf_get_next_buf_line(qfstate_T *state)
636{
637 char_u *p_buf = NULL;
638 int len;
639
640 /* Get the next line from the supplied buffer */
641 if (state->buflnum > state->lnumlast)
642 return QF_END_OF_INPUT;
643
644 p_buf = ml_get_buf(state->buf, state->buflnum, FALSE);
645 state->buflnum += 1;
646
647 len = (int)STRLEN(p_buf);
648 if (len > IOSIZE - 2)
649 {
650 state->linebuf = qf_grow_linebuf(state, len);
651 if (state->linebuf == NULL)
652 return QF_NOMEM;
653 }
654 else
655 {
656 state->linebuf = IObuff;
657 state->linelen = len;
658 }
659 vim_strncpy(state->linebuf, p_buf, state->linelen);
660
661 return QF_OK;
662}
663
664/*
665 * Get the next string from file state->fd.
666 */
667 static int
668qf_get_next_file_line(qfstate_T *state)
669{
670 int discard;
671 int growbuflen;
672
673 if (fgets((char *)IObuff, IOSIZE, state->fd) == NULL)
674 return QF_END_OF_INPUT;
675
676 discard = FALSE;
677 state->linelen = (int)STRLEN(IObuff);
Bram Moolenaar796aa9c2016-08-02 21:41:28 +0200678 if (state->linelen == IOSIZE - 1 && !(IObuff[state->linelen - 1] == '\n'))
Bram Moolenaare0d37972016-07-15 22:36:01 +0200679 {
680 /*
681 * The current line exceeds IObuff, continue reading using
682 * growbuf until EOL or LINE_MAXLEN bytes is read.
683 */
684 if (state->growbuf == NULL)
685 {
686 state->growbufsiz = 2 * (IOSIZE - 1);
687 state->growbuf = alloc(state->growbufsiz);
688 if (state->growbuf == NULL)
689 return QF_NOMEM;
690 }
691
692 /* Copy the read part of the line, excluding null-terminator */
693 memcpy(state->growbuf, IObuff, IOSIZE - 1);
694 growbuflen = state->linelen;
695
696 for (;;)
697 {
698 if (fgets((char *)state->growbuf + growbuflen,
699 state->growbufsiz - growbuflen, state->fd) == NULL)
700 break;
701 state->linelen = (int)STRLEN(state->growbuf + growbuflen);
702 growbuflen += state->linelen;
Bram Moolenaar796aa9c2016-08-02 21:41:28 +0200703 if ((state->growbuf)[growbuflen - 1] == '\n')
Bram Moolenaare0d37972016-07-15 22:36:01 +0200704 break;
705 if (state->growbufsiz == LINE_MAXLEN)
706 {
707 discard = TRUE;
708 break;
709 }
710
711 state->growbufsiz = 2 * state->growbufsiz < LINE_MAXLEN
712 ? 2 * state->growbufsiz : LINE_MAXLEN;
713 state->growbuf = vim_realloc(state->growbuf, state->growbufsiz);
714 if (state->growbuf == NULL)
715 return QF_NOMEM;
716 }
717
718 while (discard)
719 {
720 /*
721 * The current line is longer than LINE_MAXLEN, continue
722 * reading but discard everything until EOL or EOF is
723 * reached.
724 */
725 if (fgets((char *)IObuff, IOSIZE, state->fd) == NULL
726 || (int)STRLEN(IObuff) < IOSIZE - 1
Bram Moolenaar796aa9c2016-08-02 21:41:28 +0200727 || IObuff[IOSIZE - 1] == '\n')
Bram Moolenaare0d37972016-07-15 22:36:01 +0200728 break;
729 }
730
731 state->linebuf = state->growbuf;
732 state->linelen = growbuflen;
733 }
734 else
735 state->linebuf = IObuff;
736
Bram Moolenaar2c7292d2017-03-05 17:43:31 +0100737#ifdef FEAT_MBYTE
738 /* Convert a line if it contains a non-ASCII character. */
Bram Moolenaarb6fa30c2017-03-29 14:19:25 +0200739 if (state->vc.vc_type != CONV_NONE && has_non_ascii(state->linebuf))
740 {
Bram Moolenaar2c7292d2017-03-05 17:43:31 +0100741 char_u *line;
742
743 line = string_convert(&state->vc, state->linebuf, &state->linelen);
744 if (line != NULL)
745 {
746 if (state->linelen < IOSIZE)
747 {
748 STRCPY(state->linebuf, line);
749 vim_free(line);
750 }
751 else
752 {
753 vim_free(state->growbuf);
754 state->linebuf = state->growbuf = line;
755 state->growbufsiz = state->linelen < LINE_MAXLEN
756 ? state->linelen : LINE_MAXLEN;
757 }
758 }
759 }
760#endif
761
Bram Moolenaare0d37972016-07-15 22:36:01 +0200762 return QF_OK;
763}
764
765/*
766 * Get the next string from a file/buffer/list/string.
767 */
768 static int
769qf_get_nextline(qfstate_T *state)
770{
771 int status = QF_FAIL;
772
773 if (state->fd == NULL)
774 {
775 if (state->tv != NULL)
776 {
777 if (state->tv->v_type == VAR_STRING)
778 /* Get the next line from the supplied string */
779 status = qf_get_next_str_line(state);
780 else if (state->tv->v_type == VAR_LIST)
781 /* Get the next line from the supplied list */
782 status = qf_get_next_list_line(state);
783 }
784 else
785 /* Get the next line from the supplied buffer */
786 status = qf_get_next_buf_line(state);
787 }
788 else
789 /* Get the next line from the supplied file */
790 status = qf_get_next_file_line(state);
791
792 if (status != QF_OK)
793 return status;
794
795 /* remove newline/CR from the line */
796 if (state->linelen > 0 && state->linebuf[state->linelen - 1] == '\n')
Bram Moolenaar796aa9c2016-08-02 21:41:28 +0200797 {
Bram Moolenaare0d37972016-07-15 22:36:01 +0200798 state->linebuf[state->linelen - 1] = NUL;
799#ifdef USE_CRNL
Bram Moolenaar796aa9c2016-08-02 21:41:28 +0200800 if (state->linelen > 1 && state->linebuf[state->linelen - 2] == '\r')
801 state->linebuf[state->linelen - 2] = NUL;
Bram Moolenaare0d37972016-07-15 22:36:01 +0200802#endif
Bram Moolenaar796aa9c2016-08-02 21:41:28 +0200803 }
Bram Moolenaare0d37972016-07-15 22:36:01 +0200804
805#ifdef FEAT_MBYTE
806 remove_bom(state->linebuf);
807#endif
808
809 return QF_OK;
810}
811
Bram Moolenaare87e6dd2016-07-17 19:25:04 +0200812typedef struct {
813 char_u *namebuf;
814 char_u *errmsg;
815 int errmsglen;
816 long lnum;
817 int col;
818 char_u use_viscol;
819 char_u *pattern;
820 int enr;
821 int type;
822 int valid;
823} qffields_T;
824
825/*
826 * Parse a line and get the quickfix fields.
827 * Return the QF_ status.
828 */
829 static int
830qf_parse_line(
831 qf_info_T *qi,
Bram Moolenaara7df8c72017-07-19 13:23:06 +0200832 int qf_idx,
Bram Moolenaare87e6dd2016-07-17 19:25:04 +0200833 char_u *linebuf,
834 int linelen,
835 efm_T *fmt_first,
836 qffields_T *fields)
837{
838 efm_T *fmt_ptr;
Bram Moolenaare87e6dd2016-07-17 19:25:04 +0200839 char_u *ptr;
840 int len;
841 int i;
842 int idx = 0;
843 char_u *tail = NULL;
844 regmatch_T regmatch;
Bram Moolenaara7df8c72017-07-19 13:23:06 +0200845 qf_list_T *qfl = &qi->qf_lists[qf_idx];
Bram Moolenaare87e6dd2016-07-17 19:25:04 +0200846
847 /* Always ignore case when looking for a matching error. */
848 regmatch.rm_ic = TRUE;
849
850 /* If there was no %> item start at the first pattern */
851 if (fmt_start == NULL)
852 fmt_ptr = fmt_first;
853 else
854 {
855 fmt_ptr = fmt_start;
856 fmt_start = NULL;
857 }
858
859 /*
860 * Try to match each part of 'errorformat' until we find a complete
861 * match or no match.
862 */
863 fields->valid = TRUE;
864restofline:
865 for ( ; fmt_ptr != NULL; fmt_ptr = fmt_ptr->next)
866 {
867 int r;
868
869 idx = fmt_ptr->prefix;
Bram Moolenaara7df8c72017-07-19 13:23:06 +0200870 if (qfl->qf_multiscan && vim_strchr((char_u *)"OPQ", idx) == NULL)
Bram Moolenaare87e6dd2016-07-17 19:25:04 +0200871 continue;
872 fields->namebuf[0] = NUL;
873 fields->pattern[0] = NUL;
Bram Moolenaara7df8c72017-07-19 13:23:06 +0200874 if (!qfl->qf_multiscan)
Bram Moolenaare87e6dd2016-07-17 19:25:04 +0200875 fields->errmsg[0] = NUL;
876 fields->lnum = 0;
877 fields->col = 0;
878 fields->use_viscol = FALSE;
879 fields->enr = -1;
880 fields->type = 0;
881 tail = NULL;
882
883 regmatch.regprog = fmt_ptr->prog;
884 r = vim_regexec(&regmatch, linebuf, (colnr_T)0);
885 fmt_ptr->prog = regmatch.regprog;
886 if (r)
887 {
Bram Moolenaara7df8c72017-07-19 13:23:06 +0200888 if ((idx == 'C' || idx == 'Z') && !qfl->qf_multiline)
Bram Moolenaare87e6dd2016-07-17 19:25:04 +0200889 continue;
890 if (vim_strchr((char_u *)"EWI", idx) != NULL)
891 fields->type = idx;
892 else
893 fields->type = 0;
894 /*
895 * Extract error message data from matched line.
896 * We check for an actual submatch, because "\[" and "\]" in
897 * the 'errorformat' may cause the wrong submatch to be used.
898 */
899 if ((i = (int)fmt_ptr->addr[0]) > 0) /* %f */
900 {
901 int c;
902
903 if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL)
904 continue;
905
906 /* Expand ~/file and $HOME/file to full path. */
907 c = *regmatch.endp[i];
908 *regmatch.endp[i] = NUL;
909 expand_env(regmatch.startp[i], fields->namebuf, CMDBUFFSIZE);
910 *regmatch.endp[i] = c;
911
912 if (vim_strchr((char_u *)"OPQ", idx) != NULL
913 && mch_getperm(fields->namebuf) == -1)
914 continue;
915 }
916 if ((i = (int)fmt_ptr->addr[1]) > 0) /* %n */
917 {
918 if (regmatch.startp[i] == NULL)
919 continue;
920 fields->enr = (int)atol((char *)regmatch.startp[i]);
921 }
922 if ((i = (int)fmt_ptr->addr[2]) > 0) /* %l */
923 {
924 if (regmatch.startp[i] == NULL)
925 continue;
926 fields->lnum = atol((char *)regmatch.startp[i]);
927 }
928 if ((i = (int)fmt_ptr->addr[3]) > 0) /* %c */
929 {
930 if (regmatch.startp[i] == NULL)
931 continue;
932 fields->col = (int)atol((char *)regmatch.startp[i]);
933 }
934 if ((i = (int)fmt_ptr->addr[4]) > 0) /* %t */
935 {
936 if (regmatch.startp[i] == NULL)
937 continue;
938 fields->type = *regmatch.startp[i];
939 }
Bram Moolenaara7df8c72017-07-19 13:23:06 +0200940 if (fmt_ptr->flags == '+' && !qfl->qf_multiscan) /* %+ */
Bram Moolenaare87e6dd2016-07-17 19:25:04 +0200941 {
Bram Moolenaar253f9122017-05-15 08:45:13 +0200942 if (linelen >= fields->errmsglen)
Bram Moolenaarb6fa30c2017-03-29 14:19:25 +0200943 {
Bram Moolenaare87e6dd2016-07-17 19:25:04 +0200944 /* linelen + null terminator */
945 if ((fields->errmsg = vim_realloc(fields->errmsg,
946 linelen + 1)) == NULL)
947 return QF_NOMEM;
948 fields->errmsglen = linelen + 1;
949 }
950 vim_strncpy(fields->errmsg, linebuf, linelen);
951 }
952 else if ((i = (int)fmt_ptr->addr[5]) > 0) /* %m */
953 {
954 if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL)
955 continue;
956 len = (int)(regmatch.endp[i] - regmatch.startp[i]);
Bram Moolenaar253f9122017-05-15 08:45:13 +0200957 if (len >= fields->errmsglen)
Bram Moolenaarb6fa30c2017-03-29 14:19:25 +0200958 {
Bram Moolenaare87e6dd2016-07-17 19:25:04 +0200959 /* len + null terminator */
960 if ((fields->errmsg = vim_realloc(fields->errmsg, len + 1))
961 == NULL)
962 return QF_NOMEM;
963 fields->errmsglen = len + 1;
964 }
965 vim_strncpy(fields->errmsg, regmatch.startp[i], len);
966 }
967 if ((i = (int)fmt_ptr->addr[6]) > 0) /* %r */
968 {
969 if (regmatch.startp[i] == NULL)
970 continue;
971 tail = regmatch.startp[i];
972 }
973 if ((i = (int)fmt_ptr->addr[7]) > 0) /* %p */
974 {
975 char_u *match_ptr;
976
977 if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL)
978 continue;
979 fields->col = 0;
980 for (match_ptr = regmatch.startp[i];
981 match_ptr != regmatch.endp[i]; ++match_ptr)
982 {
983 ++fields->col;
984 if (*match_ptr == TAB)
985 {
986 fields->col += 7;
987 fields->col -= fields->col % 8;
988 }
989 }
990 ++fields->col;
991 fields->use_viscol = TRUE;
992 }
993 if ((i = (int)fmt_ptr->addr[8]) > 0) /* %v */
994 {
995 if (regmatch.startp[i] == NULL)
996 continue;
997 fields->col = (int)atol((char *)regmatch.startp[i]);
998 fields->use_viscol = TRUE;
999 }
1000 if ((i = (int)fmt_ptr->addr[9]) > 0) /* %s */
1001 {
1002 if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL)
1003 continue;
1004 len = (int)(regmatch.endp[i] - regmatch.startp[i]);
1005 if (len > CMDBUFFSIZE - 5)
1006 len = CMDBUFFSIZE - 5;
1007 STRCPY(fields->pattern, "^\\V");
1008 STRNCAT(fields->pattern, regmatch.startp[i], len);
1009 fields->pattern[len + 3] = '\\';
1010 fields->pattern[len + 4] = '$';
1011 fields->pattern[len + 5] = NUL;
1012 }
1013 break;
1014 }
1015 }
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001016 qfl->qf_multiscan = FALSE;
Bram Moolenaare87e6dd2016-07-17 19:25:04 +02001017
1018 if (fmt_ptr == NULL || idx == 'D' || idx == 'X')
1019 {
1020 if (fmt_ptr != NULL)
1021 {
1022 if (idx == 'D') /* enter directory */
1023 {
1024 if (*fields->namebuf == NUL)
1025 {
1026 EMSG(_("E379: Missing or empty directory name"));
1027 return QF_FAIL;
1028 }
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001029 qfl->qf_directory =
1030 qf_push_dir(fields->namebuf, &qfl->qf_dir_stack, FALSE);
1031 if (qfl->qf_directory == NULL)
Bram Moolenaare87e6dd2016-07-17 19:25:04 +02001032 return QF_FAIL;
1033 }
1034 else if (idx == 'X') /* leave directory */
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001035 qfl->qf_directory = qf_pop_dir(&qfl->qf_dir_stack);
Bram Moolenaare87e6dd2016-07-17 19:25:04 +02001036 }
1037 fields->namebuf[0] = NUL; /* no match found, remove file name */
1038 fields->lnum = 0; /* don't jump to this line */
1039 fields->valid = FALSE;
Bram Moolenaar253f9122017-05-15 08:45:13 +02001040 if (linelen >= fields->errmsglen)
Bram Moolenaarb6fa30c2017-03-29 14:19:25 +02001041 {
Bram Moolenaare87e6dd2016-07-17 19:25:04 +02001042 /* linelen + null terminator */
1043 if ((fields->errmsg = vim_realloc(fields->errmsg,
1044 linelen + 1)) == NULL)
1045 return QF_NOMEM;
1046 fields->errmsglen = linelen + 1;
1047 }
1048 /* copy whole line to error message */
1049 vim_strncpy(fields->errmsg, linebuf, linelen);
1050 if (fmt_ptr == NULL)
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001051 qfl->qf_multiline = qfl->qf_multiignore = FALSE;
Bram Moolenaare87e6dd2016-07-17 19:25:04 +02001052 }
1053 else if (fmt_ptr != NULL)
1054 {
1055 /* honor %> item */
1056 if (fmt_ptr->conthere)
1057 fmt_start = fmt_ptr;
1058
1059 if (vim_strchr((char_u *)"AEWI", idx) != NULL)
1060 {
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001061 qfl->qf_multiline = TRUE; /* start of a multi-line message */
1062 qfl->qf_multiignore = FALSE;/* reset continuation */
Bram Moolenaare87e6dd2016-07-17 19:25:04 +02001063 }
1064 else if (vim_strchr((char_u *)"CZ", idx) != NULL)
1065 { /* continuation of multi-line msg */
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001066 if (!qfl->qf_multiignore)
Bram Moolenaare87e6dd2016-07-17 19:25:04 +02001067 {
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001068 qfline_T *qfprev = qfl->qf_last;
Bram Moolenaare87e6dd2016-07-17 19:25:04 +02001069
Bram Moolenaar9b457942016-10-09 16:10:05 +02001070 if (qfprev == NULL)
1071 return QF_FAIL;
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001072 if (*fields->errmsg && !qfl->qf_multiignore)
Bram Moolenaar9b457942016-10-09 16:10:05 +02001073 {
1074 len = (int)STRLEN(qfprev->qf_text);
1075 if ((ptr = alloc((unsigned)(len + STRLEN(fields->errmsg) + 2)))
1076 == NULL)
1077 return QF_FAIL;
1078 STRCPY(ptr, qfprev->qf_text);
1079 vim_free(qfprev->qf_text);
1080 qfprev->qf_text = ptr;
1081 *(ptr += len) = '\n';
1082 STRCPY(++ptr, fields->errmsg);
1083 }
1084 if (qfprev->qf_nr == -1)
1085 qfprev->qf_nr = fields->enr;
1086 if (vim_isprintc(fields->type) && !qfprev->qf_type)
1087 /* only printable chars allowed */
1088 qfprev->qf_type = fields->type;
1089
1090 if (!qfprev->qf_lnum)
1091 qfprev->qf_lnum = fields->lnum;
1092 if (!qfprev->qf_col)
1093 qfprev->qf_col = fields->col;
1094 qfprev->qf_viscol = fields->use_viscol;
1095 if (!qfprev->qf_fnum)
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001096 qfprev->qf_fnum = qf_get_fnum(qi, qf_idx,
1097 qfl->qf_directory,
1098 *fields->namebuf || qfl->qf_directory != NULL
Bram Moolenaar9b457942016-10-09 16:10:05 +02001099 ? fields->namebuf
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001100 : qfl->qf_currfile != NULL && fields->valid
1101 ? qfl->qf_currfile : 0);
Bram Moolenaar9b457942016-10-09 16:10:05 +02001102 }
Bram Moolenaare87e6dd2016-07-17 19:25:04 +02001103 if (idx == 'Z')
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001104 qfl->qf_multiline = qfl->qf_multiignore = FALSE;
Bram Moolenaare87e6dd2016-07-17 19:25:04 +02001105 line_breakcheck();
1106 return QF_IGNORE_LINE;
1107 }
1108 else if (vim_strchr((char_u *)"OPQ", idx) != NULL)
1109 {
1110 /* global file names */
1111 fields->valid = FALSE;
1112 if (*fields->namebuf == NUL || mch_getperm(fields->namebuf) >= 0)
1113 {
1114 if (*fields->namebuf && idx == 'P')
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001115 qfl->qf_currfile =
1116 qf_push_dir(fields->namebuf, &qfl->qf_file_stack, TRUE);
Bram Moolenaare87e6dd2016-07-17 19:25:04 +02001117 else if (idx == 'Q')
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001118 qfl->qf_currfile = qf_pop_dir(&qfl->qf_file_stack);
Bram Moolenaare87e6dd2016-07-17 19:25:04 +02001119 *fields->namebuf = NUL;
1120 if (tail && *tail)
1121 {
1122 STRMOVE(IObuff, skipwhite(tail));
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001123 qfl->qf_multiscan = TRUE;
Bram Moolenaare87e6dd2016-07-17 19:25:04 +02001124 goto restofline;
1125 }
1126 }
1127 }
1128 if (fmt_ptr->flags == '-') /* generally exclude this line */
1129 {
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001130 if (qfl->qf_multiline)
Bram Moolenaare87e6dd2016-07-17 19:25:04 +02001131 /* also exclude continuation lines */
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001132 qfl->qf_multiignore = TRUE;
Bram Moolenaare87e6dd2016-07-17 19:25:04 +02001133 return QF_IGNORE_LINE;
1134 }
1135 }
1136
1137 return QF_OK;
1138}
1139
Bram Moolenaar6be8c8e2016-04-30 13:17:09 +02001140/*
Bram Moolenaar86b68352004-12-27 21:59:20 +00001141 * Read the errorfile "efile" into memory, line by line, building the error
1142 * list.
Bram Moolenaar864293a2016-06-02 13:40:04 +02001143 * Alternative: when "efile" is NULL read errors from buffer "buf".
1144 * Alternative: when "tv" is not NULL get errors from the string or list.
Bram Moolenaar86b68352004-12-27 21:59:20 +00001145 * Always use 'errorformat' from "buf" if there is a local value.
Bram Moolenaar7fd73202010-07-25 16:58:46 +02001146 * Then "lnumfirst" and "lnumlast" specify the range of lines to use.
1147 * Set the title of the list to "qf_title".
Bram Moolenaar86b68352004-12-27 21:59:20 +00001148 * Return -1 for error, number of errors for success.
1149 */
1150 static int
Bram Moolenaar05540972016-01-30 20:31:25 +01001151qf_init_ext(
1152 qf_info_T *qi,
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001153 int qf_idx,
Bram Moolenaar05540972016-01-30 20:31:25 +01001154 char_u *efile,
1155 buf_T *buf,
1156 typval_T *tv,
1157 char_u *errorformat,
1158 int newlist, /* TRUE: start a new error list */
1159 linenr_T lnumfirst, /* first line number to use */
1160 linenr_T lnumlast, /* last line number to use */
Bram Moolenaar2c7292d2017-03-05 17:43:31 +01001161 char_u *qf_title,
1162 char_u *enc)
Bram Moolenaar86b68352004-12-27 21:59:20 +00001163{
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001164 qf_list_T *qfl;
Bram Moolenaar2c7292d2017-03-05 17:43:31 +01001165 qfstate_T state;
1166 qffields_T fields;
Bram Moolenaar864293a2016-06-02 13:40:04 +02001167 qfline_T *old_last = NULL;
Bram Moolenaar86f100dc2017-06-28 21:26:27 +02001168 int adding = FALSE;
Bram Moolenaar361c8f02016-07-02 15:41:47 +02001169 static efm_T *fmt_first = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001170 char_u *efm;
Bram Moolenaar361c8f02016-07-02 15:41:47 +02001171 static char_u *last_efm = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001172 int retval = -1; /* default: return error flag */
Bram Moolenaare0d37972016-07-15 22:36:01 +02001173 int status;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001174
Bram Moolenaar6dd4a532017-05-28 07:56:36 +02001175 /* Do not used the cached buffer, it may have been wiped out. */
1176 vim_free(qf_last_bufname);
1177 qf_last_bufname = NULL;
1178
Bram Moolenaar2c7292d2017-03-05 17:43:31 +01001179 vim_memset(&state, 0, sizeof(state));
1180 vim_memset(&fields, 0, sizeof(fields));
1181#ifdef FEAT_MBYTE
1182 state.vc.vc_type = CONV_NONE;
1183 if (enc != NULL && *enc != NUL)
1184 convert_setup(&state.vc, enc, p_enc);
1185#endif
Bram Moolenaare87e6dd2016-07-17 19:25:04 +02001186 fields.namebuf = alloc_id(CMDBUFFSIZE + 1, aid_qf_namebuf);
1187 fields.errmsglen = CMDBUFFSIZE + 1;
1188 fields.errmsg = alloc_id(fields.errmsglen, aid_qf_errmsg);
1189 fields.pattern = alloc_id(CMDBUFFSIZE + 1, aid_qf_pattern);
Bram Moolenaar55b69262017-08-13 13:42:01 +02001190 if (fields.namebuf == NULL || fields.errmsg == NULL || fields.pattern == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001191 goto qf_init_end;
1192
Bram Moolenaare0d37972016-07-15 22:36:01 +02001193 if (efile != NULL && (state.fd = mch_fopen((char *)efile, "r")) == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001194 {
1195 EMSG2(_(e_openerrf), efile);
1196 goto qf_init_end;
1197 }
1198
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001199 if (newlist || qf_idx == qi->qf_listcount)
1200 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001201 /* make place for a new list */
Bram Moolenaar94116152012-11-28 17:41:59 +01001202 qf_new_list(qi, qf_title);
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001203 qf_idx = qi->qf_curlist;
1204 }
Bram Moolenaar86f100dc2017-06-28 21:26:27 +02001205 else
Bram Moolenaar864293a2016-06-02 13:40:04 +02001206 {
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02001207 /* Adding to existing list, use last entry. */
Bram Moolenaar2b946c92016-11-12 18:14:44 +01001208 adding = TRUE;
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001209 if (qi->qf_lists[qf_idx].qf_count > 0)
1210 old_last = qi->qf_lists[qf_idx].qf_last;
Bram Moolenaar86f100dc2017-06-28 21:26:27 +02001211 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001212
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001213 qfl = &qi->qf_lists[qf_idx];
1214
Bram Moolenaar071d4272004-06-13 20:20:40 +00001215 /* Use the local value of 'errorformat' if it's set. */
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001216 if (errorformat == p_efm && tv == NULL && *buf->b_p_efm != NUL)
Bram Moolenaar86b68352004-12-27 21:59:20 +00001217 efm = buf->b_p_efm;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001218 else
1219 efm = errorformat;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001220
Bram Moolenaar361c8f02016-07-02 15:41:47 +02001221 /*
Bram Moolenaar361c8f02016-07-02 15:41:47 +02001222 * If the errorformat didn't change between calls, then reuse the
1223 * previously parsed values.
1224 */
1225 if (last_efm == NULL || (STRCMP(last_efm, efm) != 0))
1226 {
1227 /* free the previously parsed data */
1228 vim_free(last_efm);
1229 last_efm = NULL;
1230 free_efm_list(&fmt_first);
1231
1232 /* parse the current 'efm' */
1233 fmt_first = parse_efm_option(efm);
1234 if (fmt_first != NULL)
1235 last_efm = vim_strsave(efm);
1236 }
1237
Bram Moolenaar071d4272004-06-13 20:20:40 +00001238 if (fmt_first == NULL) /* nothing found */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001239 goto error2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001240
1241 /*
1242 * got_int is reset here, because it was probably set when killing the
1243 * ":make" command, but we still want to read the errorfile then.
1244 */
1245 got_int = FALSE;
1246
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001247 if (tv != NULL)
1248 {
1249 if (tv->v_type == VAR_STRING)
Bram Moolenaare0d37972016-07-15 22:36:01 +02001250 state.p_str = tv->vval.v_string;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001251 else if (tv->v_type == VAR_LIST)
Bram Moolenaare0d37972016-07-15 22:36:01 +02001252 state.p_li = tv->vval.v_list->lv_first;
1253 state.tv = tv;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001254 }
Bram Moolenaare0d37972016-07-15 22:36:01 +02001255 state.buf = buf;
Bram Moolenaarbfafb4c2016-07-16 14:20:45 +02001256 state.buflnum = lnumfirst;
1257 state.lnumlast = lnumlast;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001258
Bram Moolenaar071d4272004-06-13 20:20:40 +00001259 /*
1260 * Read the lines in the error file one by one.
1261 * Try to recognize one of the error formats in each line.
1262 */
Bram Moolenaar86b68352004-12-27 21:59:20 +00001263 while (!got_int)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001264 {
Bram Moolenaare0d37972016-07-15 22:36:01 +02001265 /* Get the next line from a file/buffer/list/string */
1266 status = qf_get_nextline(&state);
1267 if (status == QF_NOMEM) /* memory alloc failure */
1268 goto qf_init_end;
1269 if (status == QF_END_OF_INPUT) /* end of input */
1270 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001271
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001272 status = qf_parse_line(qi, qf_idx, state.linebuf, state.linelen,
1273 fmt_first, &fields);
Bram Moolenaare87e6dd2016-07-17 19:25:04 +02001274 if (status == QF_FAIL)
1275 goto error2;
1276 if (status == QF_NOMEM)
1277 goto qf_init_end;
1278 if (status == QF_IGNORE_LINE)
1279 continue;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001280
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02001281 if (qf_add_entry(qi,
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001282 qf_idx,
1283 qfl->qf_directory,
1284 (*fields.namebuf || qfl->qf_directory != NULL)
Bram Moolenaare87e6dd2016-07-17 19:25:04 +02001285 ? fields.namebuf
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001286 : ((qfl->qf_currfile != NULL && fields.valid)
1287 ? qfl->qf_currfile : (char_u *)NULL),
Bram Moolenaar48b66fb2007-02-04 01:58:18 +00001288 0,
Bram Moolenaare87e6dd2016-07-17 19:25:04 +02001289 fields.errmsg,
1290 fields.lnum,
1291 fields.col,
1292 fields.use_viscol,
1293 fields.pattern,
1294 fields.enr,
1295 fields.type,
1296 fields.valid) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001297 goto error2;
1298 line_breakcheck();
1299 }
Bram Moolenaare0d37972016-07-15 22:36:01 +02001300 if (state.fd == NULL || !ferror(state.fd))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001301 {
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001302 if (qfl->qf_index == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001303 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001304 /* no valid entry found */
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001305 qfl->qf_ptr = qfl->qf_start;
1306 qfl->qf_index = 1;
1307 qfl->qf_nonevalid = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001308 }
1309 else
1310 {
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001311 qfl->qf_nonevalid = FALSE;
1312 if (qfl->qf_ptr == NULL)
1313 qfl->qf_ptr = qfl->qf_start;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001314 }
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001315 /* return number of matches */
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001316 retval = qfl->qf_count;
Bram Moolenaarbcf77722016-06-28 21:11:32 +02001317 goto qf_init_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001318 }
1319 EMSG(_(e_readerrf));
1320error2:
Bram Moolenaar2b946c92016-11-12 18:14:44 +01001321 if (!adding)
1322 {
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001323 /* Error when creating a new list. Free the new list */
Bram Moolenaar2b946c92016-11-12 18:14:44 +01001324 qf_free(qi, qi->qf_curlist);
1325 qi->qf_listcount--;
1326 if (qi->qf_curlist > 0)
1327 --qi->qf_curlist;
1328 }
Bram Moolenaarbcf77722016-06-28 21:11:32 +02001329qf_init_end:
Bram Moolenaare0d37972016-07-15 22:36:01 +02001330 if (state.fd != NULL)
1331 fclose(state.fd);
Bram Moolenaare87e6dd2016-07-17 19:25:04 +02001332 vim_free(fields.namebuf);
1333 vim_free(fields.errmsg);
1334 vim_free(fields.pattern);
Bram Moolenaare0d37972016-07-15 22:36:01 +02001335 vim_free(state.growbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001336
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001337 if (qf_idx == qi->qf_curlist)
1338 qf_update_buffer(qi, old_last);
Bram Moolenaar2c7292d2017-03-05 17:43:31 +01001339#ifdef FEAT_MBYTE
1340 if (state.vc.vc_type != CONV_NONE)
1341 convert_setup(&state.vc, NULL, NULL);
1342#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001343
1344 return retval;
1345}
1346
Bram Moolenaarfb604092014-07-23 15:55:00 +02001347 static void
Bram Moolenaara3921f42017-06-04 15:30:34 +02001348qf_store_title(qf_info_T *qi, int qf_idx, char_u *title)
Bram Moolenaarfb604092014-07-23 15:55:00 +02001349{
Bram Moolenaar6a8958d2017-06-22 21:33:20 +02001350 vim_free(qi->qf_lists[qf_idx].qf_title);
1351 qi->qf_lists[qf_idx].qf_title = NULL;
1352
Bram Moolenaarfb604092014-07-23 15:55:00 +02001353 if (title != NULL)
1354 {
1355 char_u *p = alloc((int)STRLEN(title) + 2);
1356
Bram Moolenaara3921f42017-06-04 15:30:34 +02001357 qi->qf_lists[qf_idx].qf_title = p;
Bram Moolenaarfb604092014-07-23 15:55:00 +02001358 if (p != NULL)
1359 sprintf((char *)p, ":%s", (char *)title);
1360 }
1361}
1362
Bram Moolenaar071d4272004-06-13 20:20:40 +00001363/*
Bram Moolenaar55b69262017-08-13 13:42:01 +02001364 * Prepare for adding a new quickfix list. If the current list is in the
1365 * middle of the stack, then all the following lists are freed and then
1366 * the new list is added.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001367 */
1368 static void
Bram Moolenaar05540972016-01-30 20:31:25 +01001369qf_new_list(qf_info_T *qi, char_u *qf_title)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001370{
1371 int i;
1372
1373 /*
Bram Moolenaarfb604092014-07-23 15:55:00 +02001374 * If the current entry is not the last entry, delete entries beyond
Bram Moolenaar071d4272004-06-13 20:20:40 +00001375 * the current entry. This makes it possible to browse in a tree-like
1376 * way with ":grep'.
1377 */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001378 while (qi->qf_listcount > qi->qf_curlist + 1)
1379 qf_free(qi, --qi->qf_listcount);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001380
1381 /*
1382 * When the stack is full, remove to oldest entry
1383 * Otherwise, add a new entry.
1384 */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001385 if (qi->qf_listcount == LISTCOUNT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001386 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001387 qf_free(qi, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001388 for (i = 1; i < LISTCOUNT; ++i)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001389 qi->qf_lists[i - 1] = qi->qf_lists[i];
1390 qi->qf_curlist = LISTCOUNT - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001391 }
1392 else
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001393 qi->qf_curlist = qi->qf_listcount++;
Bram Moolenaara0f299b2012-01-10 17:13:52 +01001394 vim_memset(&qi->qf_lists[qi->qf_curlist], 0, (size_t)(sizeof(qf_list_T)));
Bram Moolenaara3921f42017-06-04 15:30:34 +02001395 qf_store_title(qi, qi->qf_curlist, qf_title);
Bram Moolenaara539f4f2017-08-30 20:33:55 +02001396 qi->qf_lists[qi->qf_curlist].qf_id = ++last_qf_id;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001397}
1398
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001399/*
1400 * Free a location list
1401 */
1402 static void
Bram Moolenaar05540972016-01-30 20:31:25 +01001403ll_free_all(qf_info_T **pqi)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00001404{
1405 int i;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001406 qf_info_T *qi;
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00001407
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001408 qi = *pqi;
1409 if (qi == NULL)
1410 return;
1411 *pqi = NULL; /* Remove reference to this list */
1412
1413 qi->qf_refcount--;
1414 if (qi->qf_refcount < 1)
1415 {
1416 /* No references to this location list */
1417 for (i = 0; i < qi->qf_listcount; ++i)
1418 qf_free(qi, i);
1419 vim_free(qi);
1420 }
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00001421}
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001422
1423 void
Bram Moolenaar05540972016-01-30 20:31:25 +01001424qf_free_all(win_T *wp)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001425{
1426 int i;
1427 qf_info_T *qi = &ql_info;
1428
1429 if (wp != NULL)
1430 {
1431 /* location list */
1432 ll_free_all(&wp->w_llist);
1433 ll_free_all(&wp->w_llist_ref);
1434 }
1435 else
1436 /* quickfix list */
1437 for (i = 0; i < qi->qf_listcount; ++i)
1438 qf_free(qi, i);
1439}
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00001440
Bram Moolenaar071d4272004-06-13 20:20:40 +00001441/*
1442 * Add an entry to the end of the list of errors.
1443 * Returns OK or FAIL.
1444 */
1445 static int
Bram Moolenaar05540972016-01-30 20:31:25 +01001446qf_add_entry(
1447 qf_info_T *qi, /* quickfix list */
Bram Moolenaara3921f42017-06-04 15:30:34 +02001448 int qf_idx, /* list index */
Bram Moolenaar05540972016-01-30 20:31:25 +01001449 char_u *dir, /* optional directory name */
1450 char_u *fname, /* file name or NULL */
1451 int bufnum, /* buffer number or zero */
1452 char_u *mesg, /* message */
1453 long lnum, /* line number */
1454 int col, /* column */
1455 int vis_col, /* using visual column */
1456 char_u *pattern, /* search pattern */
1457 int nr, /* error number */
1458 int type, /* type character */
1459 int valid) /* valid entry */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001460{
Bram Moolenaar68b76a62005-03-25 21:53:48 +00001461 qfline_T *qfp;
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02001462 qfline_T **lastp; /* pointer to qf_last or NULL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001463
Bram Moolenaar68b76a62005-03-25 21:53:48 +00001464 if ((qfp = (qfline_T *)alloc((unsigned)sizeof(qfline_T))) == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001465 return FAIL;
Bram Moolenaar48b66fb2007-02-04 01:58:18 +00001466 if (bufnum != 0)
Bram Moolenaar2f095a42016-06-03 19:05:49 +02001467 {
1468 buf_T *buf = buflist_findnr(bufnum);
1469
Bram Moolenaar48b66fb2007-02-04 01:58:18 +00001470 qfp->qf_fnum = bufnum;
Bram Moolenaar2f095a42016-06-03 19:05:49 +02001471 if (buf != NULL)
Bram Moolenaarc1542742016-07-20 21:44:37 +02001472 buf->b_has_qf_entry |=
1473 (qi == &ql_info) ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY;
Bram Moolenaar2f095a42016-06-03 19:05:49 +02001474 }
Bram Moolenaar48b66fb2007-02-04 01:58:18 +00001475 else
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001476 qfp->qf_fnum = qf_get_fnum(qi, qf_idx, dir, fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001477 if ((qfp->qf_text = vim_strsave(mesg)) == NULL)
1478 {
1479 vim_free(qfp);
1480 return FAIL;
1481 }
1482 qfp->qf_lnum = lnum;
1483 qfp->qf_col = col;
Bram Moolenaar05159a02005-02-26 23:04:13 +00001484 qfp->qf_viscol = vis_col;
Bram Moolenaar68b76a62005-03-25 21:53:48 +00001485 if (pattern == NULL || *pattern == NUL)
1486 qfp->qf_pattern = NULL;
1487 else if ((qfp->qf_pattern = vim_strsave(pattern)) == NULL)
1488 {
1489 vim_free(qfp->qf_text);
1490 vim_free(qfp);
1491 return FAIL;
1492 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001493 qfp->qf_nr = nr;
1494 if (type != 1 && !vim_isprintc(type)) /* only printable chars allowed */
1495 type = 0;
1496 qfp->qf_type = type;
1497 qfp->qf_valid = valid;
1498
Bram Moolenaara3921f42017-06-04 15:30:34 +02001499 lastp = &qi->qf_lists[qf_idx].qf_last;
1500 if (qi->qf_lists[qf_idx].qf_count == 0)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001501 /* first element in the list */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001502 {
Bram Moolenaara3921f42017-06-04 15:30:34 +02001503 qi->qf_lists[qf_idx].qf_start = qfp;
1504 qi->qf_lists[qf_idx].qf_ptr = qfp;
1505 qi->qf_lists[qf_idx].qf_index = 0;
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02001506 qfp->qf_prev = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001507 }
1508 else
1509 {
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02001510 qfp->qf_prev = *lastp;
1511 (*lastp)->qf_next = qfp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001512 }
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02001513 qfp->qf_next = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001514 qfp->qf_cleared = FALSE;
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02001515 *lastp = qfp;
Bram Moolenaara3921f42017-06-04 15:30:34 +02001516 ++qi->qf_lists[qf_idx].qf_count;
1517 if (qi->qf_lists[qf_idx].qf_index == 0 && qfp->qf_valid)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001518 /* first valid entry */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001519 {
Bram Moolenaara3921f42017-06-04 15:30:34 +02001520 qi->qf_lists[qf_idx].qf_index =
1521 qi->qf_lists[qf_idx].qf_count;
1522 qi->qf_lists[qf_idx].qf_ptr = qfp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001523 }
1524
1525 return OK;
1526}
1527
1528/*
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00001529 * Allocate a new location list
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001530 */
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00001531 static qf_info_T *
Bram Moolenaar05540972016-01-30 20:31:25 +01001532ll_new_list(void)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001533{
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00001534 qf_info_T *qi;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001535
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00001536 qi = (qf_info_T *)alloc((unsigned)sizeof(qf_info_T));
1537 if (qi != NULL)
1538 {
1539 vim_memset(qi, 0, (size_t)(sizeof(qf_info_T)));
1540 qi->qf_refcount++;
1541 }
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001542
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00001543 return qi;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001544}
1545
1546/*
1547 * Return the location list for window 'wp'.
1548 * If not present, allocate a location list
1549 */
1550 static qf_info_T *
Bram Moolenaar05540972016-01-30 20:31:25 +01001551ll_get_or_alloc_list(win_T *wp)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001552{
1553 if (IS_LL_WINDOW(wp))
1554 /* For a location list window, use the referenced location list */
1555 return wp->w_llist_ref;
1556
1557 /*
1558 * For a non-location list window, w_llist_ref should not point to a
1559 * location list.
1560 */
1561 ll_free_all(&wp->w_llist_ref);
1562
1563 if (wp->w_llist == NULL)
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00001564 wp->w_llist = ll_new_list(); /* new location list */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001565 return wp->w_llist;
1566}
1567
1568/*
1569 * Copy the location list from window "from" to window "to".
1570 */
1571 void
Bram Moolenaar05540972016-01-30 20:31:25 +01001572copy_loclist(win_T *from, win_T *to)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001573{
1574 qf_info_T *qi;
1575 int idx;
1576 int i;
1577
1578 /*
1579 * When copying from a location list window, copy the referenced
1580 * location list. For other windows, copy the location list for
1581 * that window.
1582 */
1583 if (IS_LL_WINDOW(from))
1584 qi = from->w_llist_ref;
1585 else
1586 qi = from->w_llist;
1587
1588 if (qi == NULL) /* no location list to copy */
1589 return;
1590
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00001591 /* allocate a new location list */
1592 if ((to->w_llist = ll_new_list()) == NULL)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001593 return;
1594
1595 to->w_llist->qf_listcount = qi->qf_listcount;
1596
1597 /* Copy the location lists one at a time */
1598 for (idx = 0; idx < qi->qf_listcount; idx++)
1599 {
1600 qf_list_T *from_qfl;
1601 qf_list_T *to_qfl;
1602
1603 to->w_llist->qf_curlist = idx;
1604
1605 from_qfl = &qi->qf_lists[idx];
1606 to_qfl = &to->w_llist->qf_lists[idx];
1607
1608 /* Some of the fields are populated by qf_add_entry() */
1609 to_qfl->qf_nonevalid = from_qfl->qf_nonevalid;
1610 to_qfl->qf_count = 0;
1611 to_qfl->qf_index = 0;
1612 to_qfl->qf_start = NULL;
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02001613 to_qfl->qf_last = NULL;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001614 to_qfl->qf_ptr = NULL;
Bram Moolenaar7fd73202010-07-25 16:58:46 +02001615 if (from_qfl->qf_title != NULL)
1616 to_qfl->qf_title = vim_strsave(from_qfl->qf_title);
1617 else
1618 to_qfl->qf_title = NULL;
Bram Moolenaar8f77c5a2017-04-30 14:21:00 +02001619 if (from_qfl->qf_ctx != NULL)
1620 {
1621 to_qfl->qf_ctx = alloc_tv();
1622 if (to_qfl->qf_ctx != NULL)
1623 copy_tv(from_qfl->qf_ctx, to_qfl->qf_ctx);
1624 }
1625 else
1626 to_qfl->qf_ctx = NULL;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001627
1628 if (from_qfl->qf_count)
1629 {
1630 qfline_T *from_qfp;
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02001631 qfline_T *prevp;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001632
1633 /* copy all the location entries in this list */
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02001634 for (i = 0, from_qfp = from_qfl->qf_start;
1635 i < from_qfl->qf_count && from_qfp != NULL;
1636 ++i, from_qfp = from_qfp->qf_next)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001637 {
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02001638 if (qf_add_entry(to->w_llist,
Bram Moolenaara3921f42017-06-04 15:30:34 +02001639 to->w_llist->qf_curlist,
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001640 NULL,
1641 NULL,
Bram Moolenaar48b66fb2007-02-04 01:58:18 +00001642 0,
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001643 from_qfp->qf_text,
1644 from_qfp->qf_lnum,
1645 from_qfp->qf_col,
1646 from_qfp->qf_viscol,
1647 from_qfp->qf_pattern,
1648 from_qfp->qf_nr,
1649 0,
1650 from_qfp->qf_valid) == FAIL)
1651 {
1652 qf_free_all(to);
1653 return;
1654 }
1655 /*
1656 * qf_add_entry() will not set the qf_num field, as the
1657 * directory and file names are not supplied. So the qf_fnum
1658 * field is copied here.
1659 */
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02001660 prevp = to->w_llist->qf_lists[to->w_llist->qf_curlist].qf_last;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001661 prevp->qf_fnum = from_qfp->qf_fnum; /* file number */
1662 prevp->qf_type = from_qfp->qf_type; /* error type */
1663 if (from_qfl->qf_ptr == from_qfp)
1664 to_qfl->qf_ptr = prevp; /* current location */
1665 }
1666 }
1667
1668 to_qfl->qf_index = from_qfl->qf_index; /* current index in the list */
1669
Bram Moolenaara539f4f2017-08-30 20:33:55 +02001670 /* Assign a new ID for the location list */
1671 to_qfl->qf_id = ++last_qf_id;
Bram Moolenaarb254af32017-12-18 19:48:58 +01001672 to_qfl->qf_changedtick = 0L;
Bram Moolenaara539f4f2017-08-30 20:33:55 +02001673
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001674 /* When no valid entries are present in the list, qf_ptr points to
1675 * the first item in the list */
Bram Moolenaard236ac02011-05-05 17:14:14 +02001676 if (to_qfl->qf_nonevalid)
Bram Moolenaar730d2c02013-06-30 13:33:58 +02001677 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001678 to_qfl->qf_ptr = to_qfl->qf_start;
Bram Moolenaar730d2c02013-06-30 13:33:58 +02001679 to_qfl->qf_index = 1;
1680 }
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001681 }
1682
1683 to->w_llist->qf_curlist = qi->qf_curlist; /* current list */
1684}
1685
1686/*
Bram Moolenaar7618e002016-11-13 15:09:26 +01001687 * Get buffer number for file "directory/fname".
Bram Moolenaar2f095a42016-06-03 19:05:49 +02001688 * Also sets the b_has_qf_entry flag.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001689 */
1690 static int
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001691qf_get_fnum(qf_info_T *qi, int qf_idx, char_u *directory, char_u *fname)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001692{
Bram Moolenaar82404332016-07-10 17:00:38 +02001693 char_u *ptr = NULL;
Bram Moolenaar2f095a42016-06-03 19:05:49 +02001694 buf_T *buf;
Bram Moolenaar82404332016-07-10 17:00:38 +02001695 char_u *bufname;
Bram Moolenaar2f095a42016-06-03 19:05:49 +02001696
Bram Moolenaar071d4272004-06-13 20:20:40 +00001697 if (fname == NULL || *fname == NUL) /* no file name */
1698 return 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001699
Bram Moolenaare60acc12011-05-10 16:41:25 +02001700#ifdef VMS
Bram Moolenaar2f095a42016-06-03 19:05:49 +02001701 vms_remove_version(fname);
Bram Moolenaare60acc12011-05-10 16:41:25 +02001702#endif
1703#ifdef BACKSLASH_IN_FILENAME
Bram Moolenaar2f095a42016-06-03 19:05:49 +02001704 if (directory != NULL)
1705 slash_adjust(directory);
1706 slash_adjust(fname);
Bram Moolenaare60acc12011-05-10 16:41:25 +02001707#endif
Bram Moolenaar2f095a42016-06-03 19:05:49 +02001708 if (directory != NULL && !vim_isAbsName(fname)
1709 && (ptr = concat_fnames(directory, fname, TRUE)) != NULL)
1710 {
1711 /*
1712 * Here we check if the file really exists.
1713 * This should normally be true, but if make works without
1714 * "leaving directory"-messages we might have missed a
1715 * directory change.
1716 */
1717 if (mch_getperm(ptr) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001718 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001719 vim_free(ptr);
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001720 directory = qf_guess_filepath(qi, qf_idx, fname);
Bram Moolenaar2f095a42016-06-03 19:05:49 +02001721 if (directory)
1722 ptr = concat_fnames(directory, fname, TRUE);
1723 else
1724 ptr = vim_strsave(fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001725 }
Bram Moolenaar2f095a42016-06-03 19:05:49 +02001726 /* Use concatenated directory name and file name */
Bram Moolenaar82404332016-07-10 17:00:38 +02001727 bufname = ptr;
1728 }
1729 else
1730 bufname = fname;
1731
1732 if (qf_last_bufname != NULL && STRCMP(bufname, qf_last_bufname) == 0
Bram Moolenaarb25f9a92016-07-10 18:21:50 +02001733 && bufref_valid(&qf_last_bufref))
Bram Moolenaar82404332016-07-10 17:00:38 +02001734 {
Bram Moolenaarb25f9a92016-07-10 18:21:50 +02001735 buf = qf_last_bufref.br_buf;
Bram Moolenaar2f095a42016-06-03 19:05:49 +02001736 vim_free(ptr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001737 }
Bram Moolenaar2f095a42016-06-03 19:05:49 +02001738 else
Bram Moolenaar82404332016-07-10 17:00:38 +02001739 {
1740 vim_free(qf_last_bufname);
1741 buf = buflist_new(bufname, NULL, (linenr_T)0, BLN_NOOPT);
1742 if (bufname == ptr)
1743 qf_last_bufname = bufname;
1744 else
1745 qf_last_bufname = vim_strsave(bufname);
Bram Moolenaarb25f9a92016-07-10 18:21:50 +02001746 set_bufref(&qf_last_bufref, buf);
Bram Moolenaar82404332016-07-10 17:00:38 +02001747 }
Bram Moolenaar2f095a42016-06-03 19:05:49 +02001748 if (buf == NULL)
1749 return 0;
Bram Moolenaar82404332016-07-10 17:00:38 +02001750
Bram Moolenaarc1542742016-07-20 21:44:37 +02001751 buf->b_has_qf_entry =
1752 (qi == &ql_info) ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY;
Bram Moolenaar2f095a42016-06-03 19:05:49 +02001753 return buf->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001754}
1755
1756/*
Bram Moolenaar38df43b2016-06-20 21:41:12 +02001757 * Push dirbuf onto the directory stack and return pointer to actual dir or
1758 * NULL on error.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001759 */
1760 static char_u *
Bram Moolenaar361c8f02016-07-02 15:41:47 +02001761qf_push_dir(char_u *dirbuf, struct dir_stack_T **stackptr, int is_file_stack)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001762{
1763 struct dir_stack_T *ds_new;
1764 struct dir_stack_T *ds_ptr;
1765
1766 /* allocate new stack element and hook it in */
1767 ds_new = (struct dir_stack_T *)alloc((unsigned)sizeof(struct dir_stack_T));
1768 if (ds_new == NULL)
1769 return NULL;
1770
1771 ds_new->next = *stackptr;
1772 *stackptr = ds_new;
1773
1774 /* store directory on the stack */
1775 if (vim_isAbsName(dirbuf)
1776 || (*stackptr)->next == NULL
Bram Moolenaar361c8f02016-07-02 15:41:47 +02001777 || (*stackptr && is_file_stack))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001778 (*stackptr)->dirname = vim_strsave(dirbuf);
1779 else
1780 {
1781 /* Okay we don't have an absolute path.
1782 * dirbuf must be a subdir of one of the directories on the stack.
1783 * Let's search...
1784 */
1785 ds_new = (*stackptr)->next;
1786 (*stackptr)->dirname = NULL;
1787 while (ds_new)
1788 {
1789 vim_free((*stackptr)->dirname);
1790 (*stackptr)->dirname = concat_fnames(ds_new->dirname, dirbuf,
1791 TRUE);
1792 if (mch_isdir((*stackptr)->dirname) == TRUE)
1793 break;
1794
1795 ds_new = ds_new->next;
1796 }
1797
1798 /* clean up all dirs we already left */
1799 while ((*stackptr)->next != ds_new)
1800 {
1801 ds_ptr = (*stackptr)->next;
1802 (*stackptr)->next = (*stackptr)->next->next;
1803 vim_free(ds_ptr->dirname);
1804 vim_free(ds_ptr);
1805 }
1806
1807 /* Nothing found -> it must be on top level */
1808 if (ds_new == NULL)
1809 {
1810 vim_free((*stackptr)->dirname);
1811 (*stackptr)->dirname = vim_strsave(dirbuf);
1812 }
1813 }
1814
1815 if ((*stackptr)->dirname != NULL)
1816 return (*stackptr)->dirname;
1817 else
1818 {
1819 ds_ptr = *stackptr;
1820 *stackptr = (*stackptr)->next;
1821 vim_free(ds_ptr);
1822 return NULL;
1823 }
1824}
1825
1826
1827/*
1828 * pop dirbuf from the directory stack and return previous directory or NULL if
1829 * stack is empty
1830 */
1831 static char_u *
Bram Moolenaar05540972016-01-30 20:31:25 +01001832qf_pop_dir(struct dir_stack_T **stackptr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001833{
1834 struct dir_stack_T *ds_ptr;
1835
1836 /* TODO: Should we check if dirbuf is the directory on top of the stack?
1837 * What to do if it isn't? */
1838
1839 /* pop top element and free it */
1840 if (*stackptr != NULL)
1841 {
1842 ds_ptr = *stackptr;
1843 *stackptr = (*stackptr)->next;
1844 vim_free(ds_ptr->dirname);
1845 vim_free(ds_ptr);
1846 }
1847
1848 /* return NEW top element as current dir or NULL if stack is empty*/
1849 return *stackptr ? (*stackptr)->dirname : NULL;
1850}
1851
1852/*
1853 * clean up directory stack
1854 */
1855 static void
Bram Moolenaar05540972016-01-30 20:31:25 +01001856qf_clean_dir_stack(struct dir_stack_T **stackptr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001857{
1858 struct dir_stack_T *ds_ptr;
1859
1860 while ((ds_ptr = *stackptr) != NULL)
1861 {
1862 *stackptr = (*stackptr)->next;
1863 vim_free(ds_ptr->dirname);
1864 vim_free(ds_ptr);
1865 }
1866}
1867
1868/*
1869 * Check in which directory of the directory stack the given file can be
1870 * found.
Bram Moolenaaraa23b372015-09-08 18:46:31 +02001871 * Returns a pointer to the directory name or NULL if not found.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001872 * Cleans up intermediate directory entries.
1873 *
1874 * TODO: How to solve the following problem?
1875 * If we have the this directory tree:
1876 * ./
1877 * ./aa
1878 * ./aa/bb
1879 * ./bb
1880 * ./bb/x.c
1881 * and make says:
1882 * making all in aa
1883 * making all in bb
1884 * x.c:9: Error
1885 * Then qf_push_dir thinks we are in ./aa/bb, but we are in ./bb.
1886 * qf_guess_filepath will return NULL.
1887 */
1888 static char_u *
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001889qf_guess_filepath(qf_info_T *qi, int qf_idx, char_u *filename)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001890{
1891 struct dir_stack_T *ds_ptr;
1892 struct dir_stack_T *ds_tmp;
1893 char_u *fullname;
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001894 qf_list_T *qfl = &qi->qf_lists[qf_idx];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001895
1896 /* no dirs on the stack - there's nothing we can do */
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001897 if (qfl->qf_dir_stack == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001898 return NULL;
1899
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001900 ds_ptr = qfl->qf_dir_stack->next;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001901 fullname = NULL;
1902 while (ds_ptr)
1903 {
1904 vim_free(fullname);
1905 fullname = concat_fnames(ds_ptr->dirname, filename, TRUE);
1906
1907 /* If concat_fnames failed, just go on. The worst thing that can happen
1908 * is that we delete the entire stack.
1909 */
1910 if ((fullname != NULL) && (mch_getperm(fullname) >= 0))
1911 break;
1912
1913 ds_ptr = ds_ptr->next;
1914 }
1915
1916 vim_free(fullname);
1917
1918 /* clean up all dirs we already left */
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001919 while (qfl->qf_dir_stack->next != ds_ptr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001920 {
Bram Moolenaara7df8c72017-07-19 13:23:06 +02001921 ds_tmp = qfl->qf_dir_stack->next;
1922 qfl->qf_dir_stack->next = qfl->qf_dir_stack->next->next;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001923 vim_free(ds_tmp->dirname);
1924 vim_free(ds_tmp);
1925 }
1926
1927 return ds_ptr==NULL? NULL: ds_ptr->dirname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001928}
1929
1930/*
Bram Moolenaarffec3c52016-03-23 20:55:42 +01001931 * When loading a file from the quickfix, the auto commands may modify it.
1932 * This may invalidate the current quickfix entry. This function checks
1933 * whether a entry is still present in the quickfix.
1934 * Similar to location list.
1935 */
1936 static int
1937is_qf_entry_present(qf_info_T *qi, qfline_T *qf_ptr)
1938{
1939 qf_list_T *qfl;
1940 qfline_T *qfp;
1941 int i;
1942
1943 qfl = &qi->qf_lists[qi->qf_curlist];
1944
1945 /* Search for the entry in the current list */
1946 for (i = 0, qfp = qfl->qf_start; i < qfl->qf_count;
1947 ++i, qfp = qfp->qf_next)
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02001948 if (qfp == NULL || qfp == qf_ptr)
Bram Moolenaarffec3c52016-03-23 20:55:42 +01001949 break;
1950
1951 if (i == qfl->qf_count) /* Entry is not found */
1952 return FALSE;
1953
1954 return TRUE;
1955}
1956
1957/*
Bram Moolenaaref6b8de2017-09-14 13:57:37 +02001958 * Get the next valid entry in the current quickfix/location list. The search
Bram Moolenaar9cb03712017-09-20 22:43:02 +02001959 * starts from the current entry. Returns NULL on failure.
Bram Moolenaaref6b8de2017-09-14 13:57:37 +02001960 */
1961 static qfline_T *
1962get_next_valid_entry(
1963 qf_info_T *qi,
1964 qfline_T *qf_ptr,
1965 int *qf_index,
1966 int dir)
1967{
1968 int idx;
1969 int old_qf_fnum;
1970
1971 idx = *qf_index;
1972 old_qf_fnum = qf_ptr->qf_fnum;
1973
1974 do
1975 {
1976 if (idx == qi->qf_lists[qi->qf_curlist].qf_count
1977 || qf_ptr->qf_next == NULL)
1978 return NULL;
1979 ++idx;
1980 qf_ptr = qf_ptr->qf_next;
1981 } while ((!qi->qf_lists[qi->qf_curlist].qf_nonevalid
1982 && !qf_ptr->qf_valid)
1983 || (dir == FORWARD_FILE && qf_ptr->qf_fnum == old_qf_fnum));
1984
1985 *qf_index = idx;
1986 return qf_ptr;
1987}
1988
1989/*
1990 * Get the previous valid entry in the current quickfix/location list. The
Bram Moolenaar9cb03712017-09-20 22:43:02 +02001991 * search starts from the current entry. Returns NULL on failure.
Bram Moolenaaref6b8de2017-09-14 13:57:37 +02001992 */
1993 static qfline_T *
1994get_prev_valid_entry(
1995 qf_info_T *qi,
1996 qfline_T *qf_ptr,
1997 int *qf_index,
1998 int dir)
1999{
2000 int idx;
2001 int old_qf_fnum;
2002
2003 idx = *qf_index;
2004 old_qf_fnum = qf_ptr->qf_fnum;
2005
2006 do
2007 {
2008 if (idx == 1 || qf_ptr->qf_prev == NULL)
2009 return NULL;
2010 --idx;
2011 qf_ptr = qf_ptr->qf_prev;
2012 } while ((!qi->qf_lists[qi->qf_curlist].qf_nonevalid
2013 && !qf_ptr->qf_valid)
2014 || (dir == BACKWARD_FILE && qf_ptr->qf_fnum == old_qf_fnum));
2015
2016 *qf_index = idx;
2017 return qf_ptr;
2018}
2019
2020/*
2021 * Get the n'th (errornr) previous/next valid entry from the current entry in
2022 * the quickfix list.
2023 * dir == FORWARD or FORWARD_FILE: next valid entry
2024 * dir == BACKWARD or BACKWARD_FILE: previous valid entry
2025 */
2026 static qfline_T *
2027get_nth_valid_entry(
2028 qf_info_T *qi,
2029 int errornr,
2030 qfline_T *qf_ptr,
2031 int *qf_index,
2032 int dir)
2033{
2034 qfline_T *prev_qf_ptr;
2035 int prev_index;
2036 static char_u *e_no_more_items = (char_u *)N_("E553: No more items");
2037 char_u *err = e_no_more_items;
2038
2039 while (errornr--)
2040 {
2041 prev_qf_ptr = qf_ptr;
2042 prev_index = *qf_index;
2043
2044 if (dir == FORWARD || dir == FORWARD_FILE)
2045 qf_ptr = get_next_valid_entry(qi, qf_ptr, qf_index, dir);
2046 else
2047 qf_ptr = get_prev_valid_entry(qi, qf_ptr, qf_index, dir);
2048 if (qf_ptr == NULL)
2049 {
2050 qf_ptr = prev_qf_ptr;
2051 *qf_index = prev_index;
2052 if (err != NULL)
2053 {
2054 EMSG(_(err));
2055 return NULL;
2056 }
2057 break;
2058 }
2059
2060 err = NULL;
2061 }
2062
2063 return qf_ptr;
2064}
2065
2066/*
Bram Moolenaar9cb03712017-09-20 22:43:02 +02002067 * Get n'th (errornr) quickfix entry
Bram Moolenaaref6b8de2017-09-14 13:57:37 +02002068 */
2069 static qfline_T *
2070get_nth_entry(
2071 qf_info_T *qi,
2072 int errornr,
2073 qfline_T *qf_ptr,
Bram Moolenaar9cb03712017-09-20 22:43:02 +02002074 int *cur_qfidx)
Bram Moolenaaref6b8de2017-09-14 13:57:37 +02002075{
Bram Moolenaar9cb03712017-09-20 22:43:02 +02002076 int qf_idx = *cur_qfidx;
Bram Moolenaaref6b8de2017-09-14 13:57:37 +02002077
Bram Moolenaar9cb03712017-09-20 22:43:02 +02002078 /* New error number is less than the current error number */
Bram Moolenaaref6b8de2017-09-14 13:57:37 +02002079 while (errornr < qf_idx && qf_idx > 1 && qf_ptr->qf_prev != NULL)
2080 {
2081 --qf_idx;
2082 qf_ptr = qf_ptr->qf_prev;
2083 }
Bram Moolenaar9cb03712017-09-20 22:43:02 +02002084 /* New error number is greater than the current error number */
Bram Moolenaaref6b8de2017-09-14 13:57:37 +02002085 while (errornr > qf_idx &&
2086 qf_idx < qi->qf_lists[qi->qf_curlist].qf_count &&
2087 qf_ptr->qf_next != NULL)
2088 {
2089 ++qf_idx;
2090 qf_ptr = qf_ptr->qf_next;
2091 }
2092
Bram Moolenaar9cb03712017-09-20 22:43:02 +02002093 *cur_qfidx = qf_idx;
Bram Moolenaaref6b8de2017-09-14 13:57:37 +02002094 return qf_ptr;
2095}
2096
Bram Moolenaaref6b8de2017-09-14 13:57:37 +02002097/*
2098 * Find a help window or open one.
2099 */
2100 static int
2101jump_to_help_window(qf_info_T *qi, int *opened_window)
2102{
2103 win_T *wp;
2104 int flags;
2105
2106 if (cmdmod.tab != 0)
2107 wp = NULL;
2108 else
2109 FOR_ALL_WINDOWS(wp)
2110 if (bt_help(wp->w_buffer))
2111 break;
2112 if (wp != NULL && wp->w_buffer->b_nwindows > 0)
2113 win_enter(wp, TRUE);
2114 else
2115 {
2116 /*
2117 * Split off help window; put it at far top if no position
2118 * specified, the current window is vertically split and narrow.
2119 */
2120 flags = WSP_HELP;
2121 if (cmdmod.split == 0 && curwin->w_width != Columns
2122 && curwin->w_width < 80)
2123 flags |= WSP_TOP;
2124 if (qi != &ql_info)
2125 flags |= WSP_NEWLOC; /* don't copy the location list */
2126
2127 if (win_split(0, flags) == FAIL)
2128 return FAIL;
2129
2130 *opened_window = TRUE;
2131
2132 if (curwin->w_height < p_hh)
2133 win_setheight((int)p_hh);
2134
2135 if (qi != &ql_info) /* not a quickfix list */
2136 {
2137 /* The new window should use the supplied location list */
2138 curwin->w_llist = qi;
2139 qi->qf_refcount++;
2140 }
2141 }
2142
2143 if (!p_im)
2144 restart_edit = 0; /* don't want insert mode in help file */
2145
2146 return OK;
2147}
Bram Moolenaaref6b8de2017-09-14 13:57:37 +02002148
2149/*
Bram Moolenaar9cb03712017-09-20 22:43:02 +02002150 * Find a suitable window for opening a file (qf_fnum) and jump to it.
2151 * If the file is already opened in a window, jump to it.
2152 */
2153 static int
2154qf_jump_to_usable_window(int qf_fnum, int *opened_window)
2155{
2156 win_T *usable_win_ptr = NULL;
2157 int usable_win;
2158 qf_info_T *ll_ref;
2159 int flags;
2160 win_T *win;
2161 win_T *altwin;
2162
2163 usable_win = 0;
2164
2165 ll_ref = curwin->w_llist_ref;
2166 if (ll_ref != NULL)
2167 {
2168 /* Find a window using the same location list that is not a
2169 * quickfix window. */
2170 FOR_ALL_WINDOWS(usable_win_ptr)
2171 if (usable_win_ptr->w_llist == ll_ref
2172 && !bt_quickfix(usable_win_ptr->w_buffer))
2173 {
2174 usable_win = 1;
2175 break;
2176 }
2177 }
2178
2179 if (!usable_win)
2180 {
2181 /* Locate a window showing a normal buffer */
2182 FOR_ALL_WINDOWS(win)
2183 if (win->w_buffer->b_p_bt[0] == NUL)
2184 {
2185 usable_win = 1;
2186 break;
2187 }
2188 }
2189
2190 /*
2191 * If no usable window is found and 'switchbuf' contains "usetab"
2192 * then search in other tabs.
2193 */
2194 if (!usable_win && (swb_flags & SWB_USETAB))
2195 {
2196 tabpage_T *tp;
2197 win_T *wp;
2198
2199 FOR_ALL_TAB_WINDOWS(tp, wp)
2200 {
2201 if (wp->w_buffer->b_fnum == qf_fnum)
2202 {
2203 goto_tabpage_win(tp, wp);
2204 usable_win = 1;
2205 goto win_found;
2206 }
2207 }
2208 }
2209win_found:
2210
2211 /*
2212 * If there is only one window and it is the quickfix window, create a
2213 * new one above the quickfix window.
2214 */
2215 if ((ONE_WINDOW && bt_quickfix(curbuf)) || !usable_win)
2216 {
2217 flags = WSP_ABOVE;
2218 if (ll_ref != NULL)
2219 flags |= WSP_NEWLOC;
2220 if (win_split(0, flags) == FAIL)
2221 return FAIL; /* not enough room for window */
2222 *opened_window = TRUE; /* close it when fail */
2223 p_swb = empty_option; /* don't split again */
2224 swb_flags = 0;
2225 RESET_BINDING(curwin);
2226 if (ll_ref != NULL)
2227 {
2228 /* The new window should use the location list from the
2229 * location list window */
2230 curwin->w_llist = ll_ref;
2231 ll_ref->qf_refcount++;
2232 }
2233 }
2234 else
2235 {
2236 if (curwin->w_llist_ref != NULL)
2237 {
2238 /* In a location window */
2239 win = usable_win_ptr;
2240 if (win == NULL)
2241 {
2242 /* Find the window showing the selected file */
2243 FOR_ALL_WINDOWS(win)
2244 if (win->w_buffer->b_fnum == qf_fnum)
2245 break;
2246 if (win == NULL)
2247 {
2248 /* Find a previous usable window */
2249 win = curwin;
2250 do
2251 {
2252 if (win->w_buffer->b_p_bt[0] == NUL)
2253 break;
2254 if (win->w_prev == NULL)
2255 win = lastwin; /* wrap around the top */
2256 else
2257 win = win->w_prev; /* go to previous window */
2258 } while (win != curwin);
2259 }
2260 }
2261 win_goto(win);
2262
2263 /* If the location list for the window is not set, then set it
2264 * to the location list from the location window */
2265 if (win->w_llist == NULL)
2266 {
2267 win->w_llist = ll_ref;
2268 ll_ref->qf_refcount++;
2269 }
2270 }
2271 else
2272 {
2273
2274 /*
2275 * Try to find a window that shows the right buffer.
2276 * Default to the window just above the quickfix buffer.
2277 */
2278 win = curwin;
2279 altwin = NULL;
2280 for (;;)
2281 {
2282 if (win->w_buffer->b_fnum == qf_fnum)
2283 break;
2284 if (win->w_prev == NULL)
2285 win = lastwin; /* wrap around the top */
2286 else
2287 win = win->w_prev; /* go to previous window */
2288
2289 if (IS_QF_WINDOW(win))
2290 {
2291 /* Didn't find it, go to the window before the quickfix
2292 * window. */
2293 if (altwin != NULL)
2294 win = altwin;
2295 else if (curwin->w_prev != NULL)
2296 win = curwin->w_prev;
2297 else
2298 win = curwin->w_next;
2299 break;
2300 }
2301
2302 /* Remember a usable window. */
2303 if (altwin == NULL && !win->w_p_pvw
2304 && win->w_buffer->b_p_bt[0] == NUL)
2305 altwin = win;
2306 }
2307
2308 win_goto(win);
2309 }
2310 }
2311
2312 return OK;
2313}
2314
2315/*
2316 * Edit the selected file or help file.
2317 */
2318 static int
2319qf_jump_edit_buffer(
2320 qf_info_T *qi,
2321 qfline_T *qf_ptr,
2322 int forceit,
2323 win_T *oldwin,
2324 int *opened_window,
2325 int *abort)
2326{
2327 int retval = OK;
2328
2329 if (qf_ptr->qf_type == 1)
2330 {
2331 /* Open help file (do_ecmd() will set b_help flag, readfile() will
2332 * set b_p_ro flag). */
2333 if (!can_abandon(curbuf, forceit))
2334 {
2335 no_write_message();
2336 retval = FALSE;
2337 }
2338 else
2339 retval = do_ecmd(qf_ptr->qf_fnum, NULL, NULL, NULL, (linenr_T)1,
2340 ECMD_HIDE + ECMD_SET_HELP,
2341 oldwin == curwin ? curwin : NULL);
2342 }
2343 else
2344 {
2345 int old_qf_curlist = qi->qf_curlist;
2346
2347 retval = buflist_getfile(qf_ptr->qf_fnum,
2348 (linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit);
2349 if (qi != &ql_info && !win_valid_any_tab(oldwin))
2350 {
2351 EMSG(_("E924: Current window was closed"));
2352 *abort = TRUE;
2353 *opened_window = FALSE;
2354 }
2355 else if (old_qf_curlist != qi->qf_curlist
2356 || !is_qf_entry_present(qi, qf_ptr))
2357 {
2358 if (qi == &ql_info)
2359 EMSG(_("E925: Current quickfix was changed"));
2360 else
2361 EMSG(_("E926: Current location list was changed"));
2362 *abort = TRUE;
2363 }
2364
2365 if (*abort)
2366 retval = FALSE;
2367 }
2368
2369 return retval;
2370}
2371
2372/*
2373 * Goto the error line in the current file using either line/column number or a
2374 * search pattern.
2375 */
2376 static void
2377qf_jump_goto_line(
2378 linenr_T qf_lnum,
2379 int qf_col,
2380 char_u qf_viscol,
2381 char_u *qf_pattern)
2382{
2383 linenr_T i;
2384 char_u *line;
2385 colnr_T screen_col;
2386 colnr_T char_col;
2387
2388 if (qf_pattern == NULL)
2389 {
2390 /*
2391 * Go to line with error, unless qf_lnum is 0.
2392 */
2393 i = qf_lnum;
2394 if (i > 0)
2395 {
2396 if (i > curbuf->b_ml.ml_line_count)
2397 i = curbuf->b_ml.ml_line_count;
2398 curwin->w_cursor.lnum = i;
2399 }
2400 if (qf_col > 0)
2401 {
2402 curwin->w_cursor.col = qf_col - 1;
2403#ifdef FEAT_VIRTUALEDIT
2404 curwin->w_cursor.coladd = 0;
2405#endif
2406 if (qf_viscol == TRUE)
2407 {
2408 /*
2409 * Check each character from the beginning of the error
2410 * line up to the error column. For each tab character
2411 * found, reduce the error column value by the length of
2412 * a tab character.
2413 */
2414 line = ml_get_curline();
2415 screen_col = 0;
2416 for (char_col = 0; char_col < curwin->w_cursor.col; ++char_col)
2417 {
2418 if (*line == NUL)
2419 break;
2420 if (*line++ == '\t')
2421 {
2422 curwin->w_cursor.col -= 7 - (screen_col % 8);
2423 screen_col += 8 - (screen_col % 8);
2424 }
2425 else
2426 ++screen_col;
2427 }
2428 }
2429 check_cursor();
2430 }
2431 else
2432 beginline(BL_WHITE | BL_FIX);
2433 }
2434 else
2435 {
2436 pos_T save_cursor;
2437
2438 /* Move the cursor to the first line in the buffer */
2439 save_cursor = curwin->w_cursor;
2440 curwin->w_cursor.lnum = 0;
2441 if (!do_search(NULL, '/', qf_pattern, (long)1,
2442 SEARCH_KEEP, NULL, NULL))
2443 curwin->w_cursor = save_cursor;
2444 }
2445}
2446
2447/*
2448 * Display quickfix list index and size message
2449 */
2450 static void
2451qf_jump_print_msg(
2452 qf_info_T *qi,
2453 int qf_index,
2454 qfline_T *qf_ptr,
2455 buf_T *old_curbuf,
2456 linenr_T old_lnum)
2457{
2458 linenr_T i;
2459 int len;
2460
2461 /* Update the screen before showing the message, unless the screen
2462 * scrolled up. */
2463 if (!msg_scrolled)
2464 update_topline_redraw();
2465 sprintf((char *)IObuff, _("(%d of %d)%s%s: "), qf_index,
2466 qi->qf_lists[qi->qf_curlist].qf_count,
2467 qf_ptr->qf_cleared ? _(" (line deleted)") : "",
2468 (char *)qf_types(qf_ptr->qf_type, qf_ptr->qf_nr));
2469 /* Add the message, skipping leading whitespace and newlines. */
2470 len = (int)STRLEN(IObuff);
2471 qf_fmt_text(skipwhite(qf_ptr->qf_text), IObuff + len, IOSIZE - len);
2472
2473 /* Output the message. Overwrite to avoid scrolling when the 'O'
2474 * flag is present in 'shortmess'; But when not jumping, print the
2475 * whole message. */
2476 i = msg_scroll;
2477 if (curbuf == old_curbuf && curwin->w_cursor.lnum == old_lnum)
2478 msg_scroll = TRUE;
2479 else if (!msg_scrolled && shortmess(SHM_OVERALL))
2480 msg_scroll = FALSE;
2481 msg_attr_keep(IObuff, 0, TRUE);
2482 msg_scroll = i;
2483}
2484
2485/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00002486 * jump to a quickfix line
2487 * if dir == FORWARD go "errornr" valid entries forward
2488 * if dir == BACKWARD go "errornr" valid entries backward
2489 * if dir == FORWARD_FILE go "errornr" valid entries files backward
2490 * if dir == BACKWARD_FILE go "errornr" valid entries files backward
2491 * else if "errornr" is zero, redisplay the same line
2492 * else go to entry "errornr"
2493 */
2494 void
Bram Moolenaaref6b8de2017-09-14 13:57:37 +02002495qf_jump(qf_info_T *qi,
2496 int dir,
2497 int errornr,
2498 int forceit)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002499{
Bram Moolenaar68b76a62005-03-25 21:53:48 +00002500 qfline_T *qf_ptr;
2501 qfline_T *old_qf_ptr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002502 int qf_index;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002503 int old_qf_index;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002504 buf_T *old_curbuf;
2505 linenr_T old_lnum;
Bram Moolenaar71fe80d2006-01-22 23:25:56 +00002506 char_u *old_swb = p_swb;
Bram Moolenaar446cb832008-06-24 21:56:24 +00002507 unsigned old_swb_flags = swb_flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002508 int opened_window = FALSE;
Bram Moolenaar701f7af2008-11-15 13:12:07 +00002509 win_T *oldwin = curwin;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002510 int print_message = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002511#ifdef FEAT_FOLDING
2512 int old_KeyTyped = KeyTyped; /* getting file may reset it */
2513#endif
Bram Moolenaar9cb03712017-09-20 22:43:02 +02002514 int retval = OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002515
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002516 if (qi == NULL)
2517 qi = &ql_info;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002518
2519 if (qi->qf_curlist >= qi->qf_listcount
2520 || qi->qf_lists[qi->qf_curlist].qf_count == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002521 {
2522 EMSG(_(e_quickfix));
2523 return;
2524 }
2525
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002526 qf_ptr = qi->qf_lists[qi->qf_curlist].qf_ptr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002527 old_qf_ptr = qf_ptr;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002528 qf_index = qi->qf_lists[qi->qf_curlist].qf_index;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002529 old_qf_index = qf_index;
Bram Moolenaarfc2b2702017-09-15 22:43:07 +02002530 if (dir != 0) /* next/prev valid entry */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002531 {
Bram Moolenaaref6b8de2017-09-14 13:57:37 +02002532 qf_ptr = get_nth_valid_entry(qi, errornr, qf_ptr, &qf_index, dir);
2533 if (qf_ptr == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002534 {
Bram Moolenaaref6b8de2017-09-14 13:57:37 +02002535 qf_ptr = old_qf_ptr;
2536 qf_index = old_qf_index;
2537 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002538 }
2539 }
2540 else if (errornr != 0) /* go to specified number */
Bram Moolenaaref6b8de2017-09-14 13:57:37 +02002541 qf_ptr = get_nth_entry(qi, errornr, qf_ptr, &qf_index);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002542
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002543 qi->qf_lists[qi->qf_curlist].qf_index = qf_index;
2544 if (qf_win_pos_update(qi, old_qf_index))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002545 /* No need to print the error message if it's visible in the error
2546 * window */
2547 print_message = FALSE;
2548
2549 /*
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002550 * For ":helpgrep" find a help window or open one.
2551 */
Bram Moolenaard28cc3f2017-07-27 22:03:50 +02002552 if (qf_ptr->qf_type == 1 && (!bt_help(curwin->w_buffer) || cmdmod.tab != 0))
Bram Moolenaaref6b8de2017-09-14 13:57:37 +02002553 if (jump_to_help_window(qi, &opened_window) == FAIL)
2554 goto theend;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002555
2556 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +00002557 * If currently in the quickfix window, find another window to show the
2558 * file in.
2559 */
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002560 if (bt_quickfix(curbuf) && !opened_window)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002561 {
2562 /*
2563 * If there is no file specified, we don't know where to go.
2564 * But do advance, otherwise ":cn" gets stuck.
2565 */
2566 if (qf_ptr->qf_fnum == 0)
2567 goto theend;
2568
Bram Moolenaar9cb03712017-09-20 22:43:02 +02002569 if (qf_jump_to_usable_window(qf_ptr->qf_fnum, &opened_window) == FAIL)
2570 goto failed;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002571 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002572
2573 /*
2574 * If there is a file name,
2575 * read the wanted file if needed, and check autowrite etc.
2576 */
2577 old_curbuf = curbuf;
2578 old_lnum = curwin->w_cursor.lnum;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002579
2580 if (qf_ptr->qf_fnum != 0)
2581 {
Bram Moolenaar9cb03712017-09-20 22:43:02 +02002582 int abort = FALSE;
Bram Moolenaarffec3c52016-03-23 20:55:42 +01002583
Bram Moolenaar9cb03712017-09-20 22:43:02 +02002584 retval = qf_jump_edit_buffer(qi, qf_ptr, forceit, oldwin,
2585 &opened_window, &abort);
2586 if (abort)
2587 {
2588 qi = NULL;
2589 qf_ptr = NULL;
Bram Moolenaar0899d692016-03-19 13:35:03 +01002590 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002591 }
2592
Bram Moolenaar9cb03712017-09-20 22:43:02 +02002593 if (retval == OK)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002594 {
2595 /* When not switched to another buffer, still need to set pc mark */
2596 if (curbuf == old_curbuf)
2597 setpcmark();
2598
Bram Moolenaar9cb03712017-09-20 22:43:02 +02002599 qf_jump_goto_line(qf_ptr->qf_lnum, qf_ptr->qf_col, qf_ptr->qf_viscol,
2600 qf_ptr->qf_pattern);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002601
2602#ifdef FEAT_FOLDING
2603 if ((fdo_flags & FDO_QUICKFIX) && old_KeyTyped)
2604 foldOpenCursor();
2605#endif
2606 if (print_message)
Bram Moolenaar9cb03712017-09-20 22:43:02 +02002607 qf_jump_print_msg(qi, qf_index, qf_ptr, old_curbuf, old_lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002608 }
2609 else
2610 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002611 if (opened_window)
2612 win_close(curwin, TRUE); /* Close opened window */
Bram Moolenaar0899d692016-03-19 13:35:03 +01002613 if (qf_ptr != NULL && qf_ptr->qf_fnum != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002614 {
2615 /*
2616 * Couldn't open file, so put index back where it was. This could
2617 * happen if the file was readonly and we changed something.
2618 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002619failed:
Bram Moolenaar071d4272004-06-13 20:20:40 +00002620 qf_ptr = old_qf_ptr;
2621 qf_index = old_qf_index;
2622 }
2623 }
2624theend:
Bram Moolenaar0899d692016-03-19 13:35:03 +01002625 if (qi != NULL)
2626 {
2627 qi->qf_lists[qi->qf_curlist].qf_ptr = qf_ptr;
2628 qi->qf_lists[qi->qf_curlist].qf_index = qf_index;
2629 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002630 if (p_swb != old_swb && opened_window)
2631 {
2632 /* Restore old 'switchbuf' value, but not when an autocommand or
2633 * modeline has changed the value. */
2634 if (p_swb == empty_option)
Bram Moolenaar446cb832008-06-24 21:56:24 +00002635 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002636 p_swb = old_swb;
Bram Moolenaar446cb832008-06-24 21:56:24 +00002637 swb_flags = old_swb_flags;
2638 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002639 else
2640 free_string_option(old_swb);
2641 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002642}
2643
2644/*
2645 * ":clist": list all errors
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002646 * ":llist": list all locations
Bram Moolenaar071d4272004-06-13 20:20:40 +00002647 */
2648 void
Bram Moolenaar05540972016-01-30 20:31:25 +01002649qf_list(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002650{
Bram Moolenaar68b76a62005-03-25 21:53:48 +00002651 buf_T *buf;
2652 char_u *fname;
2653 qfline_T *qfp;
2654 int i;
2655 int idx1 = 1;
2656 int idx2 = -1;
Bram Moolenaar68b76a62005-03-25 21:53:48 +00002657 char_u *arg = eap->arg;
Bram Moolenaare8fea072016-07-01 14:48:27 +02002658 int plus = FALSE;
Bram Moolenaar93a32e22017-11-23 22:05:45 +01002659 int qfFileAttr;
2660 int qfSepAttr;
2661 int qfLineAttr;
Bram Moolenaar68b76a62005-03-25 21:53:48 +00002662 int all = eap->forceit; /* if not :cl!, only show
Bram Moolenaar071d4272004-06-13 20:20:40 +00002663 recognised errors */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002664 qf_info_T *qi = &ql_info;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002665
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002666 if (eap->cmdidx == CMD_llist)
2667 {
2668 qi = GET_LOC_LIST(curwin);
2669 if (qi == NULL)
2670 {
2671 EMSG(_(e_loclist));
2672 return;
2673 }
2674 }
2675
2676 if (qi->qf_curlist >= qi->qf_listcount
2677 || qi->qf_lists[qi->qf_curlist].qf_count == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002678 {
2679 EMSG(_(e_quickfix));
2680 return;
2681 }
Bram Moolenaare8fea072016-07-01 14:48:27 +02002682 if (*arg == '+')
2683 {
2684 ++arg;
2685 plus = TRUE;
2686 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002687 if (!get_list_range(&arg, &idx1, &idx2) || *arg != NUL)
2688 {
2689 EMSG(_(e_trailing));
2690 return;
2691 }
Bram Moolenaare8fea072016-07-01 14:48:27 +02002692 if (plus)
2693 {
2694 i = qi->qf_lists[qi->qf_curlist].qf_index;
2695 idx2 = i + idx1;
2696 idx1 = i;
2697 }
2698 else
2699 {
2700 i = qi->qf_lists[qi->qf_curlist].qf_count;
2701 if (idx1 < 0)
2702 idx1 = (-idx1 > i) ? 0 : idx1 + i + 1;
2703 if (idx2 < 0)
2704 idx2 = (-idx2 > i) ? 0 : idx2 + i + 1;
2705 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002706
Bram Moolenaar93a32e22017-11-23 22:05:45 +01002707 /*
2708 * Get the attributes for the different quickfix highlight items. Note
2709 * that this depends on syntax items defined in the qf.vim syntax file
2710 */
2711 qfFileAttr = syn_name2attr((char_u *)"qfFileName");
2712 if (qfFileAttr == 0)
2713 qfFileAttr = HL_ATTR(HLF_D);
2714 qfSepAttr = syn_name2attr((char_u *)"qfSeparator");
2715 if (qfSepAttr == 0)
2716 qfSepAttr = HL_ATTR(HLF_D);
2717 qfLineAttr = syn_name2attr((char_u *)"qfLineNr");
2718 if (qfLineAttr == 0)
2719 qfLineAttr = HL_ATTR(HLF_N);
2720
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002721 if (qi->qf_lists[qi->qf_curlist].qf_nonevalid)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002722 all = TRUE;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002723 qfp = qi->qf_lists[qi->qf_curlist].qf_start;
2724 for (i = 1; !got_int && i <= qi->qf_lists[qi->qf_curlist].qf_count; )
Bram Moolenaar071d4272004-06-13 20:20:40 +00002725 {
2726 if ((qfp->qf_valid || all) && idx1 <= i && i <= idx2)
2727 {
Bram Moolenaar2660c0e2010-01-19 14:59:56 +01002728 msg_putchar('\n');
2729 if (got_int)
2730 break;
Bram Moolenaar68b76a62005-03-25 21:53:48 +00002731
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00002732 fname = NULL;
2733 if (qfp->qf_fnum != 0
2734 && (buf = buflist_findnr(qfp->qf_fnum)) != NULL)
2735 {
2736 fname = buf->b_fname;
2737 if (qfp->qf_type == 1) /* :helpgrep */
2738 fname = gettail(fname);
2739 }
2740 if (fname == NULL)
2741 sprintf((char *)IObuff, "%2d", i);
2742 else
2743 vim_snprintf((char *)IObuff, IOSIZE, "%2d %s",
2744 i, (char *)fname);
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002745 msg_outtrans_attr(IObuff, i == qi->qf_lists[qi->qf_curlist].qf_index
Bram Moolenaar93a32e22017-11-23 22:05:45 +01002746 ? HL_ATTR(HLF_QFL) : qfFileAttr);
2747
2748 if (qfp->qf_lnum != 0)
2749 msg_puts_attr((char_u *)":", qfSepAttr);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00002750 if (qfp->qf_lnum == 0)
2751 IObuff[0] = NUL;
2752 else if (qfp->qf_col == 0)
Bram Moolenaar93a32e22017-11-23 22:05:45 +01002753 sprintf((char *)IObuff, "%ld", qfp->qf_lnum);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00002754 else
Bram Moolenaar93a32e22017-11-23 22:05:45 +01002755 sprintf((char *)IObuff, "%ld col %d",
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00002756 qfp->qf_lnum, qfp->qf_col);
Bram Moolenaar93a32e22017-11-23 22:05:45 +01002757 sprintf((char *)IObuff + STRLEN(IObuff), "%s",
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00002758 (char *)qf_types(qfp->qf_type, qfp->qf_nr));
Bram Moolenaar93a32e22017-11-23 22:05:45 +01002759 msg_puts_attr(IObuff, qfLineAttr);
2760 msg_puts_attr((char_u *)":", qfSepAttr);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00002761 if (qfp->qf_pattern != NULL)
2762 {
2763 qf_fmt_text(qfp->qf_pattern, IObuff, IOSIZE);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00002764 msg_puts(IObuff);
Bram Moolenaar93a32e22017-11-23 22:05:45 +01002765 msg_puts_attr((char_u *)":", qfSepAttr);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00002766 }
2767 msg_puts((char_u *)" ");
2768
2769 /* Remove newlines and leading whitespace from the text. For an
2770 * unrecognized line keep the indent, the compiler may mark a word
2771 * with ^^^^. */
2772 qf_fmt_text((fname != NULL || qfp->qf_lnum != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002773 ? skipwhite(qfp->qf_text) : qfp->qf_text,
2774 IObuff, IOSIZE);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00002775 msg_prt_line(IObuff, FALSE);
2776 out_flush(); /* show one line at a time */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002777 }
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00002778
2779 qfp = qfp->qf_next;
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02002780 if (qfp == NULL)
2781 break;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00002782 ++i;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002783 ui_breakcheck();
2784 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002785}
2786
2787/*
2788 * Remove newlines and leading whitespace from an error message.
2789 * Put the result in "buf[bufsize]".
2790 */
2791 static void
Bram Moolenaar05540972016-01-30 20:31:25 +01002792qf_fmt_text(char_u *text, char_u *buf, int bufsize)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002793{
2794 int i;
2795 char_u *p = text;
2796
2797 for (i = 0; *p != NUL && i < bufsize - 1; ++i)
2798 {
2799 if (*p == '\n')
2800 {
2801 buf[i] = ' ';
2802 while (*++p != NUL)
Bram Moolenaar1c465442017-03-12 20:10:05 +01002803 if (!VIM_ISWHITE(*p) && *p != '\n')
Bram Moolenaar071d4272004-06-13 20:20:40 +00002804 break;
2805 }
2806 else
2807 buf[i] = *p++;
2808 }
2809 buf[i] = NUL;
2810}
2811
Bram Moolenaarf6acffb2016-07-16 16:54:24 +02002812 static void
2813qf_msg(qf_info_T *qi, int which, char *lead)
2814{
2815 char *title = (char *)qi->qf_lists[which].qf_title;
2816 int count = qi->qf_lists[which].qf_count;
2817 char_u buf[IOSIZE];
2818
2819 vim_snprintf((char *)buf, IOSIZE, _("%serror list %d of %d; %d errors "),
2820 lead,
2821 which + 1,
2822 qi->qf_listcount,
2823 count);
2824
2825 if (title != NULL)
2826 {
Bram Moolenaar16ec3c92016-07-18 22:22:39 +02002827 size_t len = STRLEN(buf);
2828
2829 if (len < 34)
2830 {
2831 vim_memset(buf + len, ' ', 34 - len);
2832 buf[34] = NUL;
2833 }
2834 vim_strcat(buf, (char_u *)title, IOSIZE);
Bram Moolenaarf6acffb2016-07-16 16:54:24 +02002835 }
2836 trunc_string(buf, buf, Columns - 1, IOSIZE);
2837 msg(buf);
2838}
2839
Bram Moolenaar071d4272004-06-13 20:20:40 +00002840/*
2841 * ":colder [count]": Up in the quickfix stack.
2842 * ":cnewer [count]": Down in the quickfix stack.
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002843 * ":lolder [count]": Up in the location list stack.
2844 * ":lnewer [count]": Down in the location list stack.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002845 */
2846 void
Bram Moolenaar05540972016-01-30 20:31:25 +01002847qf_age(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002848{
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002849 qf_info_T *qi = &ql_info;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002850 int count;
2851
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002852 if (eap->cmdidx == CMD_lolder || eap->cmdidx == CMD_lnewer)
2853 {
2854 qi = GET_LOC_LIST(curwin);
2855 if (qi == NULL)
2856 {
2857 EMSG(_(e_loclist));
2858 return;
2859 }
2860 }
2861
Bram Moolenaar071d4272004-06-13 20:20:40 +00002862 if (eap->addr_count != 0)
2863 count = eap->line2;
2864 else
2865 count = 1;
2866 while (count--)
2867 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002868 if (eap->cmdidx == CMD_colder || eap->cmdidx == CMD_lolder)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002869 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002870 if (qi->qf_curlist == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002871 {
2872 EMSG(_("E380: At bottom of quickfix stack"));
Bram Moolenaar82e803b2013-05-11 15:50:33 +02002873 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002874 }
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002875 --qi->qf_curlist;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002876 }
2877 else
2878 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002879 if (qi->qf_curlist >= qi->qf_listcount - 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002880 {
2881 EMSG(_("E381: At top of quickfix stack"));
Bram Moolenaar82e803b2013-05-11 15:50:33 +02002882 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002883 }
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002884 ++qi->qf_curlist;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002885 }
2886 }
Bram Moolenaarf6acffb2016-07-16 16:54:24 +02002887 qf_msg(qi, qi->qf_curlist, "");
Bram Moolenaar864293a2016-06-02 13:40:04 +02002888 qf_update_buffer(qi, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002889}
2890
Bram Moolenaarf6acffb2016-07-16 16:54:24 +02002891 void
2892qf_history(exarg_T *eap)
2893{
2894 qf_info_T *qi = &ql_info;
2895 int i;
2896
2897 if (eap->cmdidx == CMD_lhistory)
2898 qi = GET_LOC_LIST(curwin);
2899 if (qi == NULL || (qi->qf_listcount == 0
2900 && qi->qf_lists[qi->qf_curlist].qf_count == 0))
2901 MSG(_("No entries"));
2902 else
2903 for (i = 0; i < qi->qf_listcount; ++i)
2904 qf_msg(qi, i, i == qi->qf_curlist ? "> " : " ");
2905}
2906
Bram Moolenaar071d4272004-06-13 20:20:40 +00002907/*
Bram Moolenaar6a8958d2017-06-22 21:33:20 +02002908 * Free all the entries in the error list "idx". Note that other information
2909 * associated with the list like context and title are not freed.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002910 */
2911 static void
Bram Moolenaar6a8958d2017-06-22 21:33:20 +02002912qf_free_items(qf_info_T *qi, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002913{
Bram Moolenaar68b76a62005-03-25 21:53:48 +00002914 qfline_T *qfp;
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02002915 qfline_T *qfpnext;
Bram Moolenaar81484f42012-12-05 15:16:47 +01002916 int stop = FALSE;
Bram Moolenaara7df8c72017-07-19 13:23:06 +02002917 qf_list_T *qfl = &qi->qf_lists[idx];
Bram Moolenaar071d4272004-06-13 20:20:40 +00002918
Bram Moolenaara7df8c72017-07-19 13:23:06 +02002919 while (qfl->qf_count && qfl->qf_start != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002920 {
Bram Moolenaara7df8c72017-07-19 13:23:06 +02002921 qfp = qfl->qf_start;
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02002922 qfpnext = qfp->qf_next;
Bram Moolenaar7adf06f2017-08-27 15:23:41 +02002923 if (!stop)
Bram Moolenaarc83a44b2012-11-28 15:25:34 +01002924 {
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02002925 vim_free(qfp->qf_text);
2926 stop = (qfp == qfpnext);
2927 vim_free(qfp->qf_pattern);
2928 vim_free(qfp);
Bram Moolenaar81484f42012-12-05 15:16:47 +01002929 if (stop)
2930 /* Somehow qf_count may have an incorrect value, set it to 1
2931 * to avoid crashing when it's wrong.
2932 * TODO: Avoid qf_count being incorrect. */
Bram Moolenaara7df8c72017-07-19 13:23:06 +02002933 qfl->qf_count = 1;
Bram Moolenaarc83a44b2012-11-28 15:25:34 +01002934 }
Bram Moolenaara7df8c72017-07-19 13:23:06 +02002935 qfl->qf_start = qfpnext;
2936 --qfl->qf_count;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002937 }
Bram Moolenaar6a8958d2017-06-22 21:33:20 +02002938
Bram Moolenaara7df8c72017-07-19 13:23:06 +02002939 qfl->qf_index = 0;
2940 qfl->qf_start = NULL;
2941 qfl->qf_last = NULL;
2942 qfl->qf_ptr = NULL;
2943 qfl->qf_nonevalid = TRUE;
Bram Moolenaar361c8f02016-07-02 15:41:47 +02002944
Bram Moolenaara7df8c72017-07-19 13:23:06 +02002945 qf_clean_dir_stack(&qfl->qf_dir_stack);
2946 qfl->qf_directory = NULL;
2947 qf_clean_dir_stack(&qfl->qf_file_stack);
2948 qfl->qf_currfile = NULL;
2949 qfl->qf_multiline = FALSE;
2950 qfl->qf_multiignore = FALSE;
2951 qfl->qf_multiscan = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002952}
2953
2954/*
Bram Moolenaar6a8958d2017-06-22 21:33:20 +02002955 * Free error list "idx". Frees all the entries in the quickfix list,
2956 * associated context information and the title.
2957 */
2958 static void
2959qf_free(qf_info_T *qi, int idx)
2960{
Bram Moolenaara7df8c72017-07-19 13:23:06 +02002961 qf_list_T *qfl = &qi->qf_lists[idx];
2962
Bram Moolenaar6a8958d2017-06-22 21:33:20 +02002963 qf_free_items(qi, idx);
2964
Bram Moolenaara7df8c72017-07-19 13:23:06 +02002965 vim_free(qfl->qf_title);
2966 qfl->qf_title = NULL;
2967 free_tv(qfl->qf_ctx);
2968 qfl->qf_ctx = NULL;
Bram Moolenaara539f4f2017-08-30 20:33:55 +02002969 qfl->qf_id = 0;
Bram Moolenaarb254af32017-12-18 19:48:58 +01002970 qfl->qf_changedtick = 0L;
Bram Moolenaar6a8958d2017-06-22 21:33:20 +02002971}
2972
2973/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00002974 * qf_mark_adjust: adjust marks
2975 */
2976 void
Bram Moolenaar05540972016-01-30 20:31:25 +01002977qf_mark_adjust(
Bram Moolenaaref6b8de2017-09-14 13:57:37 +02002978 win_T *wp,
2979 linenr_T line1,
2980 linenr_T line2,
2981 long amount,
2982 long amount_after)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002983{
Bram Moolenaar68b76a62005-03-25 21:53:48 +00002984 int i;
2985 qfline_T *qfp;
2986 int idx;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002987 qf_info_T *qi = &ql_info;
Bram Moolenaar2f095a42016-06-03 19:05:49 +02002988 int found_one = FALSE;
Bram Moolenaarc1542742016-07-20 21:44:37 +02002989 int buf_has_flag = wp == NULL ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002990
Bram Moolenaarc1542742016-07-20 21:44:37 +02002991 if (!(curbuf->b_has_qf_entry & buf_has_flag))
Bram Moolenaar2f095a42016-06-03 19:05:49 +02002992 return;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002993 if (wp != NULL)
2994 {
2995 if (wp->w_llist == NULL)
2996 return;
2997 qi = wp->w_llist;
2998 }
2999
3000 for (idx = 0; idx < qi->qf_listcount; ++idx)
3001 if (qi->qf_lists[idx].qf_count)
3002 for (i = 0, qfp = qi->qf_lists[idx].qf_start;
Bram Moolenaaref6b8de2017-09-14 13:57:37 +02003003 i < qi->qf_lists[idx].qf_count && qfp != NULL;
3004 ++i, qfp = qfp->qf_next)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003005 if (qfp->qf_fnum == curbuf->b_fnum)
3006 {
Bram Moolenaar2f095a42016-06-03 19:05:49 +02003007 found_one = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003008 if (qfp->qf_lnum >= line1 && qfp->qf_lnum <= line2)
3009 {
3010 if (amount == MAXLNUM)
3011 qfp->qf_cleared = TRUE;
3012 else
3013 qfp->qf_lnum += amount;
3014 }
3015 else if (amount_after && qfp->qf_lnum > line2)
3016 qfp->qf_lnum += amount_after;
3017 }
Bram Moolenaar2f095a42016-06-03 19:05:49 +02003018
3019 if (!found_one)
Bram Moolenaarc1542742016-07-20 21:44:37 +02003020 curbuf->b_has_qf_entry &= ~buf_has_flag;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003021}
3022
3023/*
3024 * Make a nice message out of the error character and the error number:
3025 * char number message
3026 * e or E 0 " error"
3027 * w or W 0 " warning"
3028 * i or I 0 " info"
3029 * 0 0 ""
3030 * other 0 " c"
3031 * e or E n " error n"
3032 * w or W n " warning n"
3033 * i or I n " info n"
3034 * 0 n " error n"
3035 * other n " c n"
3036 * 1 x "" :helpgrep
3037 */
3038 static char_u *
Bram Moolenaar05540972016-01-30 20:31:25 +01003039qf_types(int c, int nr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003040{
3041 static char_u buf[20];
3042 static char_u cc[3];
3043 char_u *p;
3044
3045 if (c == 'W' || c == 'w')
3046 p = (char_u *)" warning";
3047 else if (c == 'I' || c == 'i')
3048 p = (char_u *)" info";
3049 else if (c == 'E' || c == 'e' || (c == 0 && nr > 0))
3050 p = (char_u *)" error";
3051 else if (c == 0 || c == 1)
3052 p = (char_u *)"";
3053 else
3054 {
3055 cc[0] = ' ';
3056 cc[1] = c;
3057 cc[2] = NUL;
3058 p = cc;
3059 }
3060
3061 if (nr <= 0)
3062 return p;
3063
3064 sprintf((char *)buf, "%s %3d", (char *)p, nr);
3065 return buf;
3066}
3067
Bram Moolenaar071d4272004-06-13 20:20:40 +00003068/*
3069 * ":cwindow": open the quickfix window if we have errors to display,
3070 * close it if not.
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003071 * ":lwindow": open the location list window if we have locations to display,
3072 * close it if not.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003073 */
3074 void
Bram Moolenaar05540972016-01-30 20:31:25 +01003075ex_cwindow(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003076{
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003077 qf_info_T *qi = &ql_info;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003078 win_T *win;
3079
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003080 if (eap->cmdidx == CMD_lwindow)
3081 {
3082 qi = GET_LOC_LIST(curwin);
3083 if (qi == NULL)
3084 return;
3085 }
3086
3087 /* Look for an existing quickfix window. */
3088 win = qf_find_win(qi);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003089
3090 /*
3091 * If a quickfix window is open but we have no errors to display,
3092 * close the window. If a quickfix window is not open, then open
3093 * it if we have errors; otherwise, leave it closed.
3094 */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003095 if (qi->qf_lists[qi->qf_curlist].qf_nonevalid
Bram Moolenaard236ac02011-05-05 17:14:14 +02003096 || qi->qf_lists[qi->qf_curlist].qf_count == 0
Bram Moolenaard68071d2006-05-02 22:08:30 +00003097 || qi->qf_curlist >= qi->qf_listcount)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003098 {
3099 if (win != NULL)
3100 ex_cclose(eap);
3101 }
3102 else if (win == NULL)
3103 ex_copen(eap);
3104}
3105
3106/*
3107 * ":cclose": close the window showing the list of errors.
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003108 * ":lclose": close the window showing the location list
Bram Moolenaar071d4272004-06-13 20:20:40 +00003109 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003110 void
Bram Moolenaar05540972016-01-30 20:31:25 +01003111ex_cclose(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003112{
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003113 win_T *win = NULL;
3114 qf_info_T *qi = &ql_info;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003115
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003116 if (eap->cmdidx == CMD_lclose || eap->cmdidx == CMD_lwindow)
3117 {
3118 qi = GET_LOC_LIST(curwin);
3119 if (qi == NULL)
3120 return;
3121 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003122
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003123 /* Find existing quickfix window and close it. */
3124 win = qf_find_win(qi);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003125 if (win != NULL)
3126 win_close(win, FALSE);
3127}
3128
3129/*
3130 * ":copen": open a window that shows the list of errors.
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003131 * ":lopen": open a window that shows the location list.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003132 */
3133 void
Bram Moolenaar05540972016-01-30 20:31:25 +01003134ex_copen(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003135{
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003136 qf_info_T *qi = &ql_info;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003137 int height;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003138 win_T *win;
Bram Moolenaar80a94a52006-02-23 21:26:58 +00003139 tabpage_T *prevtab = curtab;
Bram Moolenaar9c102382006-05-03 21:26:49 +00003140 buf_T *qf_buf;
Bram Moolenaar701f7af2008-11-15 13:12:07 +00003141 win_T *oldwin = curwin;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003142
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003143 if (eap->cmdidx == CMD_lopen || eap->cmdidx == CMD_lwindow)
3144 {
3145 qi = GET_LOC_LIST(curwin);
3146 if (qi == NULL)
3147 {
3148 EMSG(_(e_loclist));
3149 return;
3150 }
3151 }
3152
Bram Moolenaar071d4272004-06-13 20:20:40 +00003153 if (eap->addr_count != 0)
3154 height = eap->line2;
3155 else
3156 height = QF_WINHEIGHT;
3157
Bram Moolenaar071d4272004-06-13 20:20:40 +00003158 reset_VIsual_and_resel(); /* stop Visual mode */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003159#ifdef FEAT_GUI
3160 need_mouse_correct = TRUE;
3161#endif
3162
3163 /*
3164 * Find existing quickfix window, or open a new one.
3165 */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003166 win = qf_find_win(qi);
3167
Bram Moolenaar80a94a52006-02-23 21:26:58 +00003168 if (win != NULL && cmdmod.tab == 0)
Bram Moolenaar15886412014-03-27 17:02:27 +01003169 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00003170 win_goto(win);
Bram Moolenaar15886412014-03-27 17:02:27 +01003171 if (eap->addr_count != 0)
3172 {
Bram Moolenaar15886412014-03-27 17:02:27 +01003173 if (cmdmod.split & WSP_VERT)
3174 {
Bram Moolenaar02631462017-09-22 15:20:32 +02003175 if (height != win->w_width)
Bram Moolenaar15886412014-03-27 17:02:27 +01003176 win_setwidth(height);
3177 }
Bram Moolenaar44a2f922016-03-19 22:11:51 +01003178 else if (height != win->w_height)
Bram Moolenaar15886412014-03-27 17:02:27 +01003179 win_setheight(height);
3180 }
3181 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003182 else
3183 {
Bram Moolenaar9c102382006-05-03 21:26:49 +00003184 qf_buf = qf_find_buf(qi);
3185
Bram Moolenaar071d4272004-06-13 20:20:40 +00003186 /* The current window becomes the previous window afterwards. */
3187 win = curwin;
3188
Bram Moolenaar77642c02012-11-20 17:55:10 +01003189 if ((eap->cmdidx == CMD_copen || eap->cmdidx == CMD_cwindow)
3190 && cmdmod.split == 0)
3191 /* Create the new window at the very bottom, except when
3192 * :belowright or :aboveleft is used. */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003193 win_goto(lastwin);
Bram Moolenaar884ae642009-02-22 01:37:59 +00003194 if (win_split(height, WSP_BELOW | WSP_NEWLOC) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003195 return; /* not enough room for window */
Bram Moolenaar3368ea22010-09-21 16:56:35 +02003196 RESET_BINDING(curwin);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003197
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003198 if (eap->cmdidx == CMD_lopen || eap->cmdidx == CMD_lwindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003199 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003200 /*
3201 * For the location list window, create a reference to the
3202 * location list from the window 'win'.
3203 */
3204 curwin->w_llist_ref = win->w_llist;
3205 win->w_llist->qf_refcount++;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003206 }
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003207
Bram Moolenaar701f7af2008-11-15 13:12:07 +00003208 if (oldwin != curwin)
3209 oldwin = NULL; /* don't store info when in another window */
Bram Moolenaar9c102382006-05-03 21:26:49 +00003210 if (qf_buf != NULL)
3211 /* Use the existing quickfix buffer */
3212 (void)do_ecmd(qf_buf->b_fnum, NULL, NULL, NULL, ECMD_ONE,
Bram Moolenaar701f7af2008-11-15 13:12:07 +00003213 ECMD_HIDE + ECMD_OLDBUF, oldwin);
Bram Moolenaar9c102382006-05-03 21:26:49 +00003214 else
3215 {
3216 /* Create a new quickfix buffer */
Bram Moolenaar701f7af2008-11-15 13:12:07 +00003217 (void)do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, oldwin);
Bram Moolenaar9c102382006-05-03 21:26:49 +00003218 /* switch off 'swapfile' */
3219 set_option_value((char_u *)"swf", 0L, NULL, OPT_LOCAL);
3220 set_option_value((char_u *)"bt", 0L, (char_u *)"quickfix",
Bram Moolenaar838bb712006-03-11 21:24:08 +00003221 OPT_LOCAL);
Bram Moolenaar9c102382006-05-03 21:26:49 +00003222 set_option_value((char_u *)"bh", 0L, (char_u *)"wipe", OPT_LOCAL);
Bram Moolenaar4161dcc2010-12-02 15:33:21 +01003223 RESET_BINDING(curwin);
Bram Moolenaar04c0f8a2009-04-29 09:52:12 +00003224#ifdef FEAT_DIFF
3225 curwin->w_p_diff = FALSE;
3226#endif
3227#ifdef FEAT_FOLDING
3228 set_option_value((char_u *)"fdm", 0L, (char_u *)"manual",
3229 OPT_LOCAL);
3230#endif
Bram Moolenaar9c102382006-05-03 21:26:49 +00003231 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003232
Bram Moolenaar80a94a52006-02-23 21:26:58 +00003233 /* Only set the height when still in the same tab page and there is no
3234 * window to the side. */
Bram Moolenaar44a2f922016-03-19 22:11:51 +01003235 if (curtab == prevtab && curwin->w_width == Columns)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003236 win_setheight(height);
3237 curwin->w_p_wfh = TRUE; /* set 'winfixheight' */
3238 if (win_valid(win))
3239 prevwin = win;
3240 }
3241
Bram Moolenaar81278ef2015-05-04 12:34:22 +02003242 qf_set_title_var(qi);
3243
Bram Moolenaar071d4272004-06-13 20:20:40 +00003244 /*
3245 * Fill the buffer with the quickfix list.
3246 */
Bram Moolenaar864293a2016-06-02 13:40:04 +02003247 qf_fill_buffer(qi, curbuf, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003248
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003249 curwin->w_cursor.lnum = qi->qf_lists[qi->qf_curlist].qf_index;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003250 curwin->w_cursor.col = 0;
3251 check_cursor();
3252 update_topline(); /* scroll to show the line */
3253}
3254
3255/*
Bram Moolenaardcb17002016-07-07 18:58:59 +02003256 * Move the cursor in the quickfix window to "lnum".
3257 */
3258 static void
3259qf_win_goto(win_T *win, linenr_T lnum)
3260{
3261 win_T *old_curwin = curwin;
3262
3263 curwin = win;
3264 curbuf = win->w_buffer;
3265 curwin->w_cursor.lnum = lnum;
3266 curwin->w_cursor.col = 0;
3267#ifdef FEAT_VIRTUALEDIT
3268 curwin->w_cursor.coladd = 0;
3269#endif
3270 curwin->w_curswant = 0;
3271 update_topline(); /* scroll to show the line */
3272 redraw_later(VALID);
3273 curwin->w_redr_status = TRUE; /* update ruler */
3274 curwin = old_curwin;
3275 curbuf = curwin->w_buffer;
3276}
3277
3278/*
Bram Moolenaar537ef082016-07-09 17:56:19 +02003279 * :cbottom/:lbottom commands.
Bram Moolenaardcb17002016-07-07 18:58:59 +02003280 */
3281 void
3282ex_cbottom(exarg_T *eap UNUSED)
3283{
Bram Moolenaar537ef082016-07-09 17:56:19 +02003284 qf_info_T *qi = &ql_info;
3285 win_T *win;
Bram Moolenaardcb17002016-07-07 18:58:59 +02003286
Bram Moolenaar537ef082016-07-09 17:56:19 +02003287 if (eap->cmdidx == CMD_lbottom)
3288 {
3289 qi = GET_LOC_LIST(curwin);
3290 if (qi == NULL)
3291 {
3292 EMSG(_(e_loclist));
3293 return;
3294 }
3295 }
3296
3297 win = qf_find_win(qi);
Bram Moolenaardcb17002016-07-07 18:58:59 +02003298 if (win != NULL && win->w_cursor.lnum != win->w_buffer->b_ml.ml_line_count)
3299 qf_win_goto(win, win->w_buffer->b_ml.ml_line_count);
3300}
3301
3302/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003303 * Return the number of the current entry (line number in the quickfix
3304 * window).
3305 */
3306 linenr_T
Bram Moolenaar05540972016-01-30 20:31:25 +01003307qf_current_entry(win_T *wp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003308{
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003309 qf_info_T *qi = &ql_info;
3310
3311 if (IS_LL_WINDOW(wp))
3312 /* In the location list window, use the referenced location list */
3313 qi = wp->w_llist_ref;
3314
3315 return qi->qf_lists[qi->qf_curlist].qf_index;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003316}
3317
3318/*
3319 * Update the cursor position in the quickfix window to the current error.
3320 * Return TRUE if there is a quickfix window.
3321 */
3322 static int
Bram Moolenaar05540972016-01-30 20:31:25 +01003323qf_win_pos_update(
3324 qf_info_T *qi,
3325 int old_qf_index) /* previous qf_index or zero */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003326{
3327 win_T *win;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003328 int qf_index = qi->qf_lists[qi->qf_curlist].qf_index;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003329
3330 /*
3331 * Put the cursor on the current error in the quickfix window, so that
3332 * it's viewable.
3333 */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003334 win = qf_find_win(qi);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003335 if (win != NULL
3336 && qf_index <= win->w_buffer->b_ml.ml_line_count
3337 && old_qf_index != qf_index)
3338 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00003339 if (qf_index > old_qf_index)
3340 {
Bram Moolenaardcb17002016-07-07 18:58:59 +02003341 win->w_redraw_top = old_qf_index;
3342 win->w_redraw_bot = qf_index;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003343 }
3344 else
3345 {
Bram Moolenaardcb17002016-07-07 18:58:59 +02003346 win->w_redraw_top = qf_index;
3347 win->w_redraw_bot = old_qf_index;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003348 }
Bram Moolenaardcb17002016-07-07 18:58:59 +02003349 qf_win_goto(win, qf_index);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003350 }
3351 return win != NULL;
3352}
3353
3354/*
Bram Moolenaar9c102382006-05-03 21:26:49 +00003355 * Check whether the given window is displaying the specified quickfix/location
3356 * list buffer
3357 */
3358 static int
Bram Moolenaar05540972016-01-30 20:31:25 +01003359is_qf_win(win_T *win, qf_info_T *qi)
Bram Moolenaar9c102382006-05-03 21:26:49 +00003360{
3361 /*
3362 * A window displaying the quickfix buffer will have the w_llist_ref field
3363 * set to NULL.
3364 * A window displaying a location list buffer will have the w_llist_ref
3365 * pointing to the location list.
3366 */
3367 if (bt_quickfix(win->w_buffer))
3368 if ((qi == &ql_info && win->w_llist_ref == NULL)
3369 || (qi != &ql_info && win->w_llist_ref == qi))
3370 return TRUE;
3371
3372 return FALSE;
3373}
3374
3375/*
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003376 * Find a window displaying the quickfix/location list 'qi'
Bram Moolenaar9c102382006-05-03 21:26:49 +00003377 * Searches in only the windows opened in the current tab.
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003378 */
3379 static win_T *
Bram Moolenaar05540972016-01-30 20:31:25 +01003380qf_find_win(qf_info_T *qi)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003381{
3382 win_T *win;
3383
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003384 FOR_ALL_WINDOWS(win)
Bram Moolenaar9c102382006-05-03 21:26:49 +00003385 if (is_qf_win(win, qi))
3386 break;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003387
3388 return win;
3389}
3390
3391/*
Bram Moolenaar9c102382006-05-03 21:26:49 +00003392 * Find a quickfix buffer.
3393 * Searches in windows opened in all the tabs.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003394 */
3395 static buf_T *
Bram Moolenaar05540972016-01-30 20:31:25 +01003396qf_find_buf(qf_info_T *qi)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003397{
Bram Moolenaar9c102382006-05-03 21:26:49 +00003398 tabpage_T *tp;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003399 win_T *win;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003400
Bram Moolenaar9c102382006-05-03 21:26:49 +00003401 FOR_ALL_TAB_WINDOWS(tp, win)
3402 if (is_qf_win(win, qi))
3403 return win->w_buffer;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003404
Bram Moolenaar9c102382006-05-03 21:26:49 +00003405 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003406}
3407
3408/*
Bram Moolenaard823fa92016-08-12 16:29:27 +02003409 * Update the w:quickfix_title variable in the quickfix/location list window
3410 */
3411 static void
3412qf_update_win_titlevar(qf_info_T *qi)
3413{
3414 win_T *win;
3415 win_T *curwin_save;
3416
3417 if ((win = qf_find_win(qi)) != NULL)
3418 {
3419 curwin_save = curwin;
3420 curwin = win;
3421 qf_set_title_var(qi);
3422 curwin = curwin_save;
3423 }
3424}
3425
3426/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003427 * Find the quickfix buffer. If it exists, update the contents.
3428 */
3429 static void
Bram Moolenaar864293a2016-06-02 13:40:04 +02003430qf_update_buffer(qf_info_T *qi, qfline_T *old_last)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003431{
3432 buf_T *buf;
Bram Moolenaarc95e3262011-08-10 18:36:54 +02003433 win_T *win;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003434 aco_save_T aco;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003435
3436 /* Check if a buffer for the quickfix list exists. Update it. */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003437 buf = qf_find_buf(qi);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003438 if (buf != NULL)
3439 {
Bram Moolenaar864293a2016-06-02 13:40:04 +02003440 linenr_T old_line_count = buf->b_ml.ml_line_count;
3441
3442 if (old_last == NULL)
3443 /* set curwin/curbuf to buf and save a few things */
3444 aucmd_prepbuf(&aco, buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003445
Bram Moolenaard823fa92016-08-12 16:29:27 +02003446 qf_update_win_titlevar(qi);
Bram Moolenaarc95e3262011-08-10 18:36:54 +02003447
Bram Moolenaar864293a2016-06-02 13:40:04 +02003448 qf_fill_buffer(qi, buf, old_last);
Bram Moolenaara8788f42017-07-19 17:06:20 +02003449 ++CHANGEDTICK(buf);
Bram Moolenaar6920c722016-01-22 22:44:10 +01003450
Bram Moolenaar864293a2016-06-02 13:40:04 +02003451 if (old_last == NULL)
3452 {
Bram Moolenaarc1808d52016-04-18 20:04:00 +02003453 (void)qf_win_pos_update(qi, 0);
Bram Moolenaar864293a2016-06-02 13:40:04 +02003454
3455 /* restore curwin/curbuf and a few other things */
3456 aucmd_restbuf(&aco);
3457 }
3458
3459 /* Only redraw when added lines are visible. This avoids flickering
3460 * when the added lines are not visible. */
3461 if ((win = qf_find_win(qi)) != NULL && old_line_count < win->w_botline)
3462 redraw_buf_later(buf, NOT_VALID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003463 }
3464}
3465
Bram Moolenaar81278ef2015-05-04 12:34:22 +02003466/*
3467 * Set "w:quickfix_title" if "qi" has a title.
3468 */
Bram Moolenaarc95e3262011-08-10 18:36:54 +02003469 static void
Bram Moolenaar05540972016-01-30 20:31:25 +01003470qf_set_title_var(qf_info_T *qi)
Bram Moolenaarc95e3262011-08-10 18:36:54 +02003471{
Bram Moolenaar81278ef2015-05-04 12:34:22 +02003472 if (qi->qf_lists[qi->qf_curlist].qf_title != NULL)
3473 set_internal_string_var((char_u *)"w:quickfix_title",
Bram Moolenaarc95e3262011-08-10 18:36:54 +02003474 qi->qf_lists[qi->qf_curlist].qf_title);
3475}
3476
Bram Moolenaar071d4272004-06-13 20:20:40 +00003477/*
3478 * Fill current buffer with quickfix errors, replacing any previous contents.
3479 * curbuf must be the quickfix buffer!
Bram Moolenaar864293a2016-06-02 13:40:04 +02003480 * If "old_last" is not NULL append the items after this one.
3481 * When "old_last" is NULL then "buf" must equal "curbuf"! Because
3482 * ml_delete() is used and autocommands will be triggered.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003483 */
3484 static void
Bram Moolenaar864293a2016-06-02 13:40:04 +02003485qf_fill_buffer(qf_info_T *qi, buf_T *buf, qfline_T *old_last)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003486{
Bram Moolenaar68b76a62005-03-25 21:53:48 +00003487 linenr_T lnum;
3488 qfline_T *qfp;
3489 buf_T *errbuf;
3490 int len;
3491 int old_KeyTyped = KeyTyped;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003492
Bram Moolenaar864293a2016-06-02 13:40:04 +02003493 if (old_last == NULL)
3494 {
3495 if (buf != curbuf)
3496 {
Bram Moolenaar95f09602016-11-10 20:01:45 +01003497 internal_error("qf_fill_buffer()");
Bram Moolenaar864293a2016-06-02 13:40:04 +02003498 return;
3499 }
3500
3501 /* delete all existing lines */
3502 while ((curbuf->b_ml.ml_flags & ML_EMPTY) == 0)
3503 (void)ml_delete((linenr_T)1, FALSE);
3504 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003505
3506 /* Check if there is anything to display */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003507 if (qi->qf_curlist < qi->qf_listcount)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003508 {
3509 /* Add one line for each error */
Bram Moolenaar864293a2016-06-02 13:40:04 +02003510 if (old_last == NULL)
3511 {
3512 qfp = qi->qf_lists[qi->qf_curlist].qf_start;
3513 lnum = 0;
3514 }
3515 else
3516 {
3517 qfp = old_last->qf_next;
3518 lnum = buf->b_ml.ml_line_count;
3519 }
3520 while (lnum < qi->qf_lists[qi->qf_curlist].qf_count)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003521 {
3522 if (qfp->qf_fnum != 0
3523 && (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL
3524 && errbuf->b_fname != NULL)
3525 {
3526 if (qfp->qf_type == 1) /* :helpgrep */
3527 STRCPY(IObuff, gettail(errbuf->b_fname));
3528 else
3529 STRCPY(IObuff, errbuf->b_fname);
3530 len = (int)STRLEN(IObuff);
3531 }
3532 else
3533 len = 0;
3534 IObuff[len++] = '|';
3535
3536 if (qfp->qf_lnum > 0)
3537 {
3538 sprintf((char *)IObuff + len, "%ld", qfp->qf_lnum);
3539 len += (int)STRLEN(IObuff + len);
3540
3541 if (qfp->qf_col > 0)
3542 {
3543 sprintf((char *)IObuff + len, " col %d", qfp->qf_col);
3544 len += (int)STRLEN(IObuff + len);
3545 }
3546
3547 sprintf((char *)IObuff + len, "%s",
3548 (char *)qf_types(qfp->qf_type, qfp->qf_nr));
3549 len += (int)STRLEN(IObuff + len);
3550 }
Bram Moolenaar68b76a62005-03-25 21:53:48 +00003551 else if (qfp->qf_pattern != NULL)
3552 {
3553 qf_fmt_text(qfp->qf_pattern, IObuff + len, IOSIZE - len);
3554 len += (int)STRLEN(IObuff + len);
3555 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003556 IObuff[len++] = '|';
3557 IObuff[len++] = ' ';
3558
3559 /* Remove newlines and leading whitespace from the text.
3560 * For an unrecognized line keep the indent, the compiler may
3561 * mark a word with ^^^^. */
3562 qf_fmt_text(len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text,
3563 IObuff + len, IOSIZE - len);
3564
Bram Moolenaar864293a2016-06-02 13:40:04 +02003565 if (ml_append_buf(buf, lnum, IObuff,
3566 (colnr_T)STRLEN(IObuff) + 1, FALSE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003567 break;
Bram Moolenaar864293a2016-06-02 13:40:04 +02003568 ++lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003569 qfp = qfp->qf_next;
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02003570 if (qfp == NULL)
3571 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003572 }
Bram Moolenaar864293a2016-06-02 13:40:04 +02003573
3574 if (old_last == NULL)
3575 /* Delete the empty line which is now at the end */
3576 (void)ml_delete(lnum + 1, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003577 }
3578
3579 /* correct cursor position */
3580 check_lnums(TRUE);
3581
Bram Moolenaar864293a2016-06-02 13:40:04 +02003582 if (old_last == NULL)
3583 {
3584 /* Set the 'filetype' to "qf" each time after filling the buffer.
3585 * This resembles reading a file into a buffer, it's more logical when
3586 * using autocommands. */
Bram Moolenaar18141832017-06-25 21:17:25 +02003587#ifdef FEAT_AUTOCMD
3588 ++curbuf_lock;
3589#endif
Bram Moolenaar864293a2016-06-02 13:40:04 +02003590 set_option_value((char_u *)"ft", 0L, (char_u *)"qf", OPT_LOCAL);
3591 curbuf->b_p_ma = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003592
3593#ifdef FEAT_AUTOCMD
Bram Moolenaar864293a2016-06-02 13:40:04 +02003594 keep_filetype = TRUE; /* don't detect 'filetype' */
3595 apply_autocmds(EVENT_BUFREADPOST, (char_u *)"quickfix", NULL,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003596 FALSE, curbuf);
Bram Moolenaar864293a2016-06-02 13:40:04 +02003597 apply_autocmds(EVENT_BUFWINENTER, (char_u *)"quickfix", NULL,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003598 FALSE, curbuf);
Bram Moolenaar864293a2016-06-02 13:40:04 +02003599 keep_filetype = FALSE;
Bram Moolenaar18141832017-06-25 21:17:25 +02003600 --curbuf_lock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003601#endif
Bram Moolenaar864293a2016-06-02 13:40:04 +02003602 /* make sure it will be redrawn */
3603 redraw_curbuf_later(NOT_VALID);
3604 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003605
3606 /* Restore KeyTyped, setting 'filetype' may reset it. */
3607 KeyTyped = old_KeyTyped;
3608}
3609
Bram Moolenaarb254af32017-12-18 19:48:58 +01003610 static void
3611qf_list_changed(qf_info_T *qi, int qf_idx)
3612{
3613 qi->qf_lists[qf_idx].qf_changedtick++;
3614}
3615
Bram Moolenaar071d4272004-06-13 20:20:40 +00003616/*
Bram Moolenaar86b68352004-12-27 21:59:20 +00003617 * Return TRUE when using ":vimgrep" for ":grep".
3618 */
3619 int
Bram Moolenaar05540972016-01-30 20:31:25 +01003620grep_internal(cmdidx_T cmdidx)
Bram Moolenaar86b68352004-12-27 21:59:20 +00003621{
Bram Moolenaar754b5602006-02-09 23:53:20 +00003622 return ((cmdidx == CMD_grep
3623 || cmdidx == CMD_lgrep
3624 || cmdidx == CMD_grepadd
3625 || cmdidx == CMD_lgrepadd)
Bram Moolenaar86b68352004-12-27 21:59:20 +00003626 && STRCMP("internal",
3627 *curbuf->b_p_gp == NUL ? p_gp : curbuf->b_p_gp) == 0);
3628}
3629
3630/*
Bram Moolenaara6557602006-02-04 22:43:20 +00003631 * Used for ":make", ":lmake", ":grep", ":lgrep", ":grepadd", and ":lgrepadd"
Bram Moolenaar071d4272004-06-13 20:20:40 +00003632 */
3633 void
Bram Moolenaar05540972016-01-30 20:31:25 +01003634ex_make(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003635{
Bram Moolenaar7c626922005-02-07 22:01:03 +00003636 char_u *fname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003637 char_u *cmd;
Bram Moolenaar2c7292d2017-03-05 17:43:31 +01003638 char_u *enc = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003639 unsigned len;
Bram Moolenaara6557602006-02-04 22:43:20 +00003640 win_T *wp = NULL;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003641 qf_info_T *qi = &ql_info;
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003642 int res;
Bram Moolenaar7c626922005-02-07 22:01:03 +00003643#ifdef FEAT_AUTOCMD
3644 char_u *au_name = NULL;
3645
Bram Moolenaard88e02d2011-04-28 17:27:09 +02003646 /* Redirect ":grep" to ":vimgrep" if 'grepprg' is "internal". */
3647 if (grep_internal(eap->cmdidx))
3648 {
3649 ex_vimgrep(eap);
3650 return;
3651 }
3652
Bram Moolenaar7c626922005-02-07 22:01:03 +00003653 switch (eap->cmdidx)
3654 {
Bram Moolenaar754b5602006-02-09 23:53:20 +00003655 case CMD_make: au_name = (char_u *)"make"; break;
3656 case CMD_lmake: au_name = (char_u *)"lmake"; break;
3657 case CMD_grep: au_name = (char_u *)"grep"; break;
3658 case CMD_lgrep: au_name = (char_u *)"lgrep"; break;
3659 case CMD_grepadd: au_name = (char_u *)"grepadd"; break;
3660 case CMD_lgrepadd: au_name = (char_u *)"lgrepadd"; break;
Bram Moolenaar7c626922005-02-07 22:01:03 +00003661 default: break;
3662 }
Bram Moolenaar21662be2016-11-06 14:46:44 +01003663 if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
3664 curbuf->b_fname, TRUE, curbuf))
Bram Moolenaar7c626922005-02-07 22:01:03 +00003665 {
Bram Moolenaar1e015462005-09-25 22:16:38 +00003666# ifdef FEAT_EVAL
Bram Moolenaar21662be2016-11-06 14:46:44 +01003667 if (aborting())
Bram Moolenaar7c626922005-02-07 22:01:03 +00003668 return;
Bram Moolenaar1e015462005-09-25 22:16:38 +00003669# endif
Bram Moolenaar7c626922005-02-07 22:01:03 +00003670 }
3671#endif
Bram Moolenaar2c7292d2017-03-05 17:43:31 +01003672#ifdef FEAT_MBYTE
3673 enc = (*curbuf->b_p_menc != NUL) ? curbuf->b_p_menc : p_menc;
3674#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003675
Bram Moolenaara6557602006-02-04 22:43:20 +00003676 if (eap->cmdidx == CMD_lmake || eap->cmdidx == CMD_lgrep
3677 || eap->cmdidx == CMD_lgrepadd)
Bram Moolenaara6557602006-02-04 22:43:20 +00003678 wp = curwin;
Bram Moolenaara6557602006-02-04 22:43:20 +00003679
Bram Moolenaar071d4272004-06-13 20:20:40 +00003680 autowrite_all();
Bram Moolenaar7c626922005-02-07 22:01:03 +00003681 fname = get_mef_name();
3682 if (fname == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003683 return;
Bram Moolenaar7c626922005-02-07 22:01:03 +00003684 mch_remove(fname); /* in case it's not unique */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003685
3686 /*
3687 * If 'shellpipe' empty: don't redirect to 'errorfile'.
3688 */
3689 len = (unsigned)STRLEN(p_shq) * 2 + (unsigned)STRLEN(eap->arg) + 1;
3690 if (*p_sp != NUL)
Bram Moolenaar7c626922005-02-07 22:01:03 +00003691 len += (unsigned)STRLEN(p_sp) + (unsigned)STRLEN(fname) + 3;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003692 cmd = alloc(len);
3693 if (cmd == NULL)
3694 return;
3695 sprintf((char *)cmd, "%s%s%s", (char *)p_shq, (char *)eap->arg,
3696 (char *)p_shq);
3697 if (*p_sp != NUL)
Bram Moolenaar5fd0ca72009-05-13 16:56:33 +00003698 append_redir(cmd, len, p_sp, fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003699 /*
3700 * Output a newline if there's something else than the :make command that
3701 * was typed (in which case the cursor is in column 0).
3702 */
3703 if (msg_col == 0)
3704 msg_didout = FALSE;
3705 msg_start();
3706 MSG_PUTS(":!");
3707 msg_outtrans(cmd); /* show what we are doing */
3708
3709 /* let the shell know if we are redirecting output or not */
3710 do_shell(cmd, *p_sp != NUL ? SHELL_DOOUT : 0);
3711
3712#ifdef AMIGA
3713 out_flush();
3714 /* read window status report and redraw before message */
3715 (void)char_avail();
3716#endif
3717
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003718 res = qf_init(wp, fname, (eap->cmdidx != CMD_make
Bram Moolenaara6557602006-02-04 22:43:20 +00003719 && eap->cmdidx != CMD_lmake) ? p_gefm : p_efm,
3720 (eap->cmdidx != CMD_grepadd
Bram Moolenaar7fd73202010-07-25 16:58:46 +02003721 && eap->cmdidx != CMD_lgrepadd),
Bram Moolenaar2c7292d2017-03-05 17:43:31 +01003722 *eap->cmdlinep, enc);
Bram Moolenaarefa8e802011-05-19 17:42:59 +02003723 if (wp != NULL)
3724 qi = GET_LOC_LIST(wp);
Bram Moolenaarb254af32017-12-18 19:48:58 +01003725 if (res >= 0 && qi != NULL)
3726 qf_list_changed(qi, qi->qf_curlist);
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003727#ifdef FEAT_AUTOCMD
3728 if (au_name != NULL)
Bram Moolenaarefa8e802011-05-19 17:42:59 +02003729 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003730 apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name,
3731 curbuf->b_fname, TRUE, curbuf);
Bram Moolenaarefa8e802011-05-19 17:42:59 +02003732 if (qi->qf_curlist < qi->qf_listcount)
3733 res = qi->qf_lists[qi->qf_curlist].qf_count;
3734 else
3735 res = 0;
3736 }
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003737#endif
3738 if (res > 0 && !eap->forceit)
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003739 qf_jump(qi, 0, 0, FALSE); /* display first error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003740
Bram Moolenaar7c626922005-02-07 22:01:03 +00003741 mch_remove(fname);
3742 vim_free(fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003743 vim_free(cmd);
3744}
3745
3746/*
3747 * Return the name for the errorfile, in allocated memory.
3748 * Find a new unique name when 'makeef' contains "##".
3749 * Returns NULL for error.
3750 */
3751 static char_u *
Bram Moolenaar05540972016-01-30 20:31:25 +01003752get_mef_name(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003753{
3754 char_u *p;
3755 char_u *name;
3756 static int start = -1;
3757 static int off = 0;
3758#ifdef HAVE_LSTAT
Bram Moolenaar8767f522016-07-01 17:17:39 +02003759 stat_T sb;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003760#endif
3761
3762 if (*p_mef == NUL)
3763 {
Bram Moolenaare5c421c2015-03-31 13:33:08 +02003764 name = vim_tempname('e', FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003765 if (name == NULL)
3766 EMSG(_(e_notmp));
3767 return name;
3768 }
3769
3770 for (p = p_mef; *p; ++p)
3771 if (p[0] == '#' && p[1] == '#')
3772 break;
3773
3774 if (*p == NUL)
3775 return vim_strsave(p_mef);
3776
3777 /* Keep trying until the name doesn't exist yet. */
3778 for (;;)
3779 {
3780 if (start == -1)
3781 start = mch_get_pid();
3782 else
3783 off += 19;
3784
3785 name = alloc((unsigned)STRLEN(p_mef) + 30);
3786 if (name == NULL)
3787 break;
3788 STRCPY(name, p_mef);
3789 sprintf((char *)name + (p - p_mef), "%d%d", start, off);
3790 STRCAT(name, p + 2);
3791 if (mch_getperm(name) < 0
3792#ifdef HAVE_LSTAT
Bram Moolenaar9af41842016-09-25 21:45:05 +02003793 /* Don't accept a symbolic link, it's a security risk. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003794 && mch_lstat((char *)name, &sb) < 0
3795#endif
3796 )
3797 break;
3798 vim_free(name);
3799 }
3800 return name;
3801}
3802
3803/*
Bram Moolenaaraa23b372015-09-08 18:46:31 +02003804 * Returns the number of valid entries in the current quickfix/location list.
3805 */
3806 int
Bram Moolenaar05540972016-01-30 20:31:25 +01003807qf_get_size(exarg_T *eap)
Bram Moolenaaraa23b372015-09-08 18:46:31 +02003808{
3809 qf_info_T *qi = &ql_info;
3810 qfline_T *qfp;
3811 int i, sz = 0;
3812 int prev_fnum = 0;
3813
3814 if (eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo)
3815 {
3816 /* Location list */
3817 qi = GET_LOC_LIST(curwin);
3818 if (qi == NULL)
3819 return 0;
3820 }
3821
3822 for (i = 0, qfp = qi->qf_lists[qi->qf_curlist].qf_start;
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02003823 i < qi->qf_lists[qi->qf_curlist].qf_count && qfp != NULL;
Bram Moolenaaraa23b372015-09-08 18:46:31 +02003824 ++i, qfp = qfp->qf_next)
3825 {
3826 if (qfp->qf_valid)
3827 {
3828 if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo)
3829 sz++; /* Count all valid entries */
3830 else if (qfp->qf_fnum > 0 && qfp->qf_fnum != prev_fnum)
3831 {
3832 /* Count the number of files */
3833 sz++;
3834 prev_fnum = qfp->qf_fnum;
3835 }
3836 }
3837 }
3838
3839 return sz;
3840}
3841
3842/*
3843 * Returns the current index of the quickfix/location list.
3844 * Returns 0 if there is an error.
3845 */
3846 int
Bram Moolenaar05540972016-01-30 20:31:25 +01003847qf_get_cur_idx(exarg_T *eap)
Bram Moolenaaraa23b372015-09-08 18:46:31 +02003848{
3849 qf_info_T *qi = &ql_info;
3850
3851 if (eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo)
3852 {
3853 /* Location list */
3854 qi = GET_LOC_LIST(curwin);
3855 if (qi == NULL)
3856 return 0;
3857 }
3858
3859 return qi->qf_lists[qi->qf_curlist].qf_index;
3860}
3861
3862/*
3863 * Returns the current index in the quickfix/location list (counting only valid
3864 * entries). If no valid entries are in the list, then returns 1.
3865 */
3866 int
Bram Moolenaar05540972016-01-30 20:31:25 +01003867qf_get_cur_valid_idx(exarg_T *eap)
Bram Moolenaaraa23b372015-09-08 18:46:31 +02003868{
3869 qf_info_T *qi = &ql_info;
3870 qf_list_T *qfl;
3871 qfline_T *qfp;
3872 int i, eidx = 0;
3873 int prev_fnum = 0;
3874
3875 if (eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo)
3876 {
3877 /* Location list */
3878 qi = GET_LOC_LIST(curwin);
3879 if (qi == NULL)
3880 return 1;
3881 }
3882
3883 qfl = &qi->qf_lists[qi->qf_curlist];
3884 qfp = qfl->qf_start;
3885
3886 /* check if the list has valid errors */
3887 if (qfl->qf_count <= 0 || qfl->qf_nonevalid)
3888 return 1;
3889
3890 for (i = 1; i <= qfl->qf_index && qfp!= NULL; i++, qfp = qfp->qf_next)
3891 {
3892 if (qfp->qf_valid)
3893 {
3894 if (eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo)
3895 {
3896 if (qfp->qf_fnum > 0 && qfp->qf_fnum != prev_fnum)
3897 {
3898 /* Count the number of files */
3899 eidx++;
3900 prev_fnum = qfp->qf_fnum;
3901 }
3902 }
3903 else
3904 eidx++;
3905 }
3906 }
3907
3908 return eidx ? eidx : 1;
3909}
3910
3911/*
3912 * Get the 'n'th valid error entry in the quickfix or location list.
3913 * Used by :cdo, :ldo, :cfdo and :lfdo commands.
3914 * For :cdo and :ldo returns the 'n'th valid error entry.
3915 * For :cfdo and :lfdo returns the 'n'th valid file entry.
3916 */
3917 static int
Bram Moolenaar05540972016-01-30 20:31:25 +01003918qf_get_nth_valid_entry(qf_info_T *qi, int n, int fdo)
Bram Moolenaaraa23b372015-09-08 18:46:31 +02003919{
3920 qf_list_T *qfl = &qi->qf_lists[qi->qf_curlist];
3921 qfline_T *qfp = qfl->qf_start;
3922 int i, eidx;
3923 int prev_fnum = 0;
3924
3925 /* check if the list has valid errors */
3926 if (qfl->qf_count <= 0 || qfl->qf_nonevalid)
3927 return 1;
3928
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02003929 for (i = 1, eidx = 0; i <= qfl->qf_count && qfp != NULL;
Bram Moolenaaraa23b372015-09-08 18:46:31 +02003930 i++, qfp = qfp->qf_next)
3931 {
3932 if (qfp->qf_valid)
3933 {
3934 if (fdo)
3935 {
3936 if (qfp->qf_fnum > 0 && qfp->qf_fnum != prev_fnum)
3937 {
3938 /* Count the number of files */
3939 eidx++;
3940 prev_fnum = qfp->qf_fnum;
3941 }
3942 }
3943 else
3944 eidx++;
3945 }
3946
3947 if (eidx == n)
3948 break;
3949 }
3950
3951 if (i <= qfl->qf_count)
3952 return i;
3953 else
3954 return 1;
3955}
3956
3957/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003958 * ":cc", ":crewind", ":cfirst" and ":clast".
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003959 * ":ll", ":lrewind", ":lfirst" and ":llast".
Bram Moolenaaraa23b372015-09-08 18:46:31 +02003960 * ":cdo", ":ldo", ":cfdo" and ":lfdo"
Bram Moolenaar071d4272004-06-13 20:20:40 +00003961 */
3962 void
Bram Moolenaar05540972016-01-30 20:31:25 +01003963ex_cc(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003964{
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003965 qf_info_T *qi = &ql_info;
Bram Moolenaaraa23b372015-09-08 18:46:31 +02003966 int errornr;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003967
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003968 if (eap->cmdidx == CMD_ll
3969 || eap->cmdidx == CMD_lrewind
3970 || eap->cmdidx == CMD_lfirst
Bram Moolenaaraa23b372015-09-08 18:46:31 +02003971 || eap->cmdidx == CMD_llast
3972 || eap->cmdidx == CMD_ldo
3973 || eap->cmdidx == CMD_lfdo)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003974 {
3975 qi = GET_LOC_LIST(curwin);
3976 if (qi == NULL)
3977 {
3978 EMSG(_(e_loclist));
3979 return;
3980 }
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003981 }
3982
Bram Moolenaaraa23b372015-09-08 18:46:31 +02003983 if (eap->addr_count > 0)
3984 errornr = (int)eap->line2;
3985 else
3986 {
3987 if (eap->cmdidx == CMD_cc || eap->cmdidx == CMD_ll)
3988 errornr = 0;
3989 else if (eap->cmdidx == CMD_crewind || eap->cmdidx == CMD_lrewind
3990 || eap->cmdidx == CMD_cfirst || eap->cmdidx == CMD_lfirst)
3991 errornr = 1;
3992 else
3993 errornr = 32767;
3994 }
3995
3996 /* For cdo and ldo commands, jump to the nth valid error.
3997 * For cfdo and lfdo commands, jump to the nth valid file entry.
3998 */
Bram Moolenaar55b69262017-08-13 13:42:01 +02003999 if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo
4000 || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo)
Bram Moolenaaraa23b372015-09-08 18:46:31 +02004001 errornr = qf_get_nth_valid_entry(qi,
4002 eap->addr_count > 0 ? (int)eap->line1 : 1,
4003 eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo);
4004
4005 qf_jump(qi, 0, errornr, eap->forceit);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004006}
4007
4008/*
4009 * ":cnext", ":cnfile", ":cNext" and ":cprevious".
Bram Moolenaard12f5c12006-01-25 22:10:52 +00004010 * ":lnext", ":lNext", ":lprevious", ":lnfile", ":lNfile" and ":lpfile".
Bram Moolenaaraa23b372015-09-08 18:46:31 +02004011 * Also, used by ":cdo", ":ldo", ":cfdo" and ":lfdo" commands.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004012 */
4013 void
Bram Moolenaar05540972016-01-30 20:31:25 +01004014ex_cnext(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004015{
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00004016 qf_info_T *qi = &ql_info;
Bram Moolenaaraa23b372015-09-08 18:46:31 +02004017 int errornr;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00004018
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00004019 if (eap->cmdidx == CMD_lnext
4020 || eap->cmdidx == CMD_lNext
4021 || eap->cmdidx == CMD_lprevious
4022 || eap->cmdidx == CMD_lnfile
4023 || eap->cmdidx == CMD_lNfile
Bram Moolenaaraa23b372015-09-08 18:46:31 +02004024 || eap->cmdidx == CMD_lpfile
4025 || eap->cmdidx == CMD_ldo
4026 || eap->cmdidx == CMD_lfdo)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00004027 {
4028 qi = GET_LOC_LIST(curwin);
4029 if (qi == NULL)
4030 {
4031 EMSG(_(e_loclist));
4032 return;
4033 }
Bram Moolenaard12f5c12006-01-25 22:10:52 +00004034 }
4035
Bram Moolenaar55b69262017-08-13 13:42:01 +02004036 if (eap->addr_count > 0
4037 && (eap->cmdidx != CMD_cdo && eap->cmdidx != CMD_ldo
4038 && eap->cmdidx != CMD_cfdo && eap->cmdidx != CMD_lfdo))
Bram Moolenaaraa23b372015-09-08 18:46:31 +02004039 errornr = (int)eap->line2;
4040 else
4041 errornr = 1;
4042
4043 qf_jump(qi, (eap->cmdidx == CMD_cnext || eap->cmdidx == CMD_lnext
4044 || eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004045 ? FORWARD
Bram Moolenaaraa23b372015-09-08 18:46:31 +02004046 : (eap->cmdidx == CMD_cnfile || eap->cmdidx == CMD_lnfile
4047 || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004048 ? FORWARD_FILE
Bram Moolenaard12f5c12006-01-25 22:10:52 +00004049 : (eap->cmdidx == CMD_cpfile || eap->cmdidx == CMD_lpfile
4050 || eap->cmdidx == CMD_cNfile || eap->cmdidx == CMD_lNfile)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004051 ? BACKWARD_FILE
4052 : BACKWARD,
Bram Moolenaaraa23b372015-09-08 18:46:31 +02004053 errornr, eap->forceit);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004054}
4055
4056/*
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00004057 * ":cfile"/":cgetfile"/":caddfile" commands.
Bram Moolenaard12f5c12006-01-25 22:10:52 +00004058 * ":lfile"/":lgetfile"/":laddfile" commands.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004059 */
4060 void
Bram Moolenaar05540972016-01-30 20:31:25 +01004061ex_cfile(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004062{
Bram Moolenaar2c7292d2017-03-05 17:43:31 +01004063 char_u *enc = NULL;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00004064 win_T *wp = NULL;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00004065 qf_info_T *qi = &ql_info;
Bram Moolenaar8ec1f852012-03-07 20:13:49 +01004066#ifdef FEAT_AUTOCMD
4067 char_u *au_name = NULL;
4068#endif
Bram Moolenaar1ed22762017-11-28 18:03:44 +01004069 int res;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00004070
4071 if (eap->cmdidx == CMD_lfile || eap->cmdidx == CMD_lgetfile
Bram Moolenaar8ec1f852012-03-07 20:13:49 +01004072 || eap->cmdidx == CMD_laddfile)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00004073 wp = curwin;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00004074
Bram Moolenaar8ec1f852012-03-07 20:13:49 +01004075#ifdef FEAT_AUTOCMD
4076 switch (eap->cmdidx)
4077 {
4078 case CMD_cfile: au_name = (char_u *)"cfile"; break;
4079 case CMD_cgetfile: au_name = (char_u *)"cgetfile"; break;
4080 case CMD_caddfile: au_name = (char_u *)"caddfile"; break;
4081 case CMD_lfile: au_name = (char_u *)"lfile"; break;
4082 case CMD_lgetfile: au_name = (char_u *)"lgetfile"; break;
4083 case CMD_laddfile: au_name = (char_u *)"laddfile"; break;
4084 default: break;
4085 }
4086 if (au_name != NULL)
4087 apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, NULL, FALSE, curbuf);
4088#endif
Bram Moolenaar2c7292d2017-03-05 17:43:31 +01004089#ifdef FEAT_MBYTE
4090 enc = (*curbuf->b_p_menc != NUL) ? curbuf->b_p_menc : p_menc;
4091#endif
Bram Moolenaar9028b102010-07-11 16:58:51 +02004092#ifdef FEAT_BROWSE
4093 if (cmdmod.browse)
4094 {
4095 char_u *browse_file = do_browse(0, (char_u *)_("Error file"), eap->arg,
4096 NULL, NULL, BROWSE_FILTER_ALL_FILES, NULL);
4097 if (browse_file == NULL)
4098 return;
4099 set_string_option_direct((char_u *)"ef", -1, browse_file, OPT_FREE, 0);
4100 vim_free(browse_file);
4101 }
4102 else
4103#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004104 if (*eap->arg != NUL)
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00004105 set_string_option_direct((char_u *)"ef", -1, eap->arg, OPT_FREE, 0);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00004106
4107 /*
4108 * This function is used by the :cfile, :cgetfile and :caddfile
4109 * commands.
4110 * :cfile always creates a new quickfix list and jumps to the
4111 * first error.
4112 * :cgetfile creates a new quickfix list but doesn't jump to the
4113 * first error.
4114 * :caddfile adds to an existing quickfix list. If there is no
4115 * quickfix list then a new list is created.
4116 */
Bram Moolenaar1ed22762017-11-28 18:03:44 +01004117 res = qf_init(wp, p_ef, p_efm, (eap->cmdidx != CMD_caddfile
4118 && eap->cmdidx != CMD_laddfile), *eap->cmdlinep, enc);
Bram Moolenaarb254af32017-12-18 19:48:58 +01004119 if (wp != NULL)
4120 qi = GET_LOC_LIST(wp);
4121 if (res >= 0 && qi != NULL)
4122 qf_list_changed(qi, qi->qf_curlist);
Bram Moolenaar8ec1f852012-03-07 20:13:49 +01004123#ifdef FEAT_AUTOCMD
Bram Moolenaar1ed22762017-11-28 18:03:44 +01004124 if (au_name != NULL)
4125 apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, NULL, FALSE, curbuf);
Bram Moolenaar8ec1f852012-03-07 20:13:49 +01004126#endif
Bram Moolenaar1ed22762017-11-28 18:03:44 +01004127 if (res > 0 && (eap->cmdidx == CMD_cfile || eap->cmdidx == CMD_lfile))
4128 {
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00004129 qf_jump(qi, 0, 0, eap->forceit); /* display first error */
Bram Moolenaarc7453f52006-02-10 23:20:28 +00004130 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004131}
4132
4133/*
Bram Moolenaar86b68352004-12-27 21:59:20 +00004134 * ":vimgrep {pattern} file(s)"
Bram Moolenaara6557602006-02-04 22:43:20 +00004135 * ":vimgrepadd {pattern} file(s)"
4136 * ":lvimgrep {pattern} file(s)"
4137 * ":lvimgrepadd {pattern} file(s)"
Bram Moolenaar86b68352004-12-27 21:59:20 +00004138 */
4139 void
Bram Moolenaar05540972016-01-30 20:31:25 +01004140ex_vimgrep(exarg_T *eap)
Bram Moolenaar86b68352004-12-27 21:59:20 +00004141{
Bram Moolenaar81695252004-12-29 20:58:21 +00004142 regmmatch_T regmatch;
Bram Moolenaar748bf032005-02-02 23:04:36 +00004143 int fcount;
Bram Moolenaar86b68352004-12-27 21:59:20 +00004144 char_u **fnames;
Bram Moolenaard089d9b2007-09-30 12:02:55 +00004145 char_u *fname;
Bram Moolenaar5584df62016-03-18 21:00:51 +01004146 char_u *title;
Bram Moolenaar748bf032005-02-02 23:04:36 +00004147 char_u *s;
4148 char_u *p;
Bram Moolenaar748bf032005-02-02 23:04:36 +00004149 int fi;
Bram Moolenaara6557602006-02-04 22:43:20 +00004150 qf_info_T *qi = &ql_info;
Bram Moolenaar321a9ec2012-12-12 15:55:20 +01004151#ifdef FEAT_AUTOCMD
4152 qfline_T *cur_qf_start;
4153#endif
Bram Moolenaar86b68352004-12-27 21:59:20 +00004154 long lnum;
Bram Moolenaar81695252004-12-29 20:58:21 +00004155 buf_T *buf;
4156 int duplicate_name = FALSE;
4157 int using_dummy;
Bram Moolenaar1042fa32007-09-16 11:27:42 +00004158 int redraw_for_dummy = FALSE;
Bram Moolenaar81695252004-12-29 20:58:21 +00004159 int found_match;
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004160 buf_T *first_match_buf = NULL;
4161 time_t seconds = 0;
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00004162 int save_mls;
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004163#if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
4164 char_u *save_ei = NULL;
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004165#endif
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00004166 aco_save_T aco;
Bram Moolenaar05159a02005-02-26 23:04:13 +00004167 int flags = 0;
4168 colnr_T col;
Bram Moolenaar1f35bf92006-03-07 22:38:47 +00004169 long tomatch;
Bram Moolenaard9462e32011-04-11 21:35:11 +02004170 char_u *dirname_start = NULL;
4171 char_u *dirname_now = NULL;
Bram Moolenaard089d9b2007-09-30 12:02:55 +00004172 char_u *target_dir = NULL;
Bram Moolenaar15bfa092008-07-24 16:45:38 +00004173#ifdef FEAT_AUTOCMD
4174 char_u *au_name = NULL;
Bram Moolenaar7c626922005-02-07 22:01:03 +00004175
4176 switch (eap->cmdidx)
4177 {
Bram Moolenaard88e02d2011-04-28 17:27:09 +02004178 case CMD_vimgrep: au_name = (char_u *)"vimgrep"; break;
4179 case CMD_lvimgrep: au_name = (char_u *)"lvimgrep"; break;
4180 case CMD_vimgrepadd: au_name = (char_u *)"vimgrepadd"; break;
Bram Moolenaara6557602006-02-04 22:43:20 +00004181 case CMD_lvimgrepadd: au_name = (char_u *)"lvimgrepadd"; break;
Bram Moolenaard88e02d2011-04-28 17:27:09 +02004182 case CMD_grep: au_name = (char_u *)"grep"; break;
4183 case CMD_lgrep: au_name = (char_u *)"lgrep"; break;
4184 case CMD_grepadd: au_name = (char_u *)"grepadd"; break;
4185 case CMD_lgrepadd: au_name = (char_u *)"lgrepadd"; break;
Bram Moolenaar7c626922005-02-07 22:01:03 +00004186 default: break;
4187 }
Bram Moolenaar21662be2016-11-06 14:46:44 +01004188 if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
4189 curbuf->b_fname, TRUE, curbuf))
Bram Moolenaar7c626922005-02-07 22:01:03 +00004190 {
Bram Moolenaar21662be2016-11-06 14:46:44 +01004191# ifdef FEAT_EVAL
4192 if (aborting())
Bram Moolenaar7c626922005-02-07 22:01:03 +00004193 return;
Bram Moolenaar21662be2016-11-06 14:46:44 +01004194# endif
Bram Moolenaar7c626922005-02-07 22:01:03 +00004195 }
4196#endif
Bram Moolenaar86b68352004-12-27 21:59:20 +00004197
Bram Moolenaar754b5602006-02-09 23:53:20 +00004198 if (eap->cmdidx == CMD_lgrep
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00004199 || eap->cmdidx == CMD_lvimgrep
4200 || eap->cmdidx == CMD_lgrepadd
4201 || eap->cmdidx == CMD_lvimgrepadd)
Bram Moolenaara6557602006-02-04 22:43:20 +00004202 {
4203 qi = ll_get_or_alloc_list(curwin);
4204 if (qi == NULL)
4205 return;
Bram Moolenaara6557602006-02-04 22:43:20 +00004206 }
4207
Bram Moolenaar1f35bf92006-03-07 22:38:47 +00004208 if (eap->addr_count > 0)
4209 tomatch = eap->line2;
4210 else
4211 tomatch = MAXLNUM;
4212
Bram Moolenaar81695252004-12-29 20:58:21 +00004213 /* Get the search pattern: either white-separated or enclosed in // */
Bram Moolenaar86b68352004-12-27 21:59:20 +00004214 regmatch.regprog = NULL;
Bram Moolenaar5584df62016-03-18 21:00:51 +01004215 title = vim_strsave(*eap->cmdlinep);
Bram Moolenaar05159a02005-02-26 23:04:13 +00004216 p = skip_vimgrep_pat(eap->arg, &s, &flags);
Bram Moolenaar748bf032005-02-02 23:04:36 +00004217 if (p == NULL)
Bram Moolenaar86b68352004-12-27 21:59:20 +00004218 {
Bram Moolenaar2389c3c2005-05-22 22:07:59 +00004219 EMSG(_(e_invalpat));
Bram Moolenaar748bf032005-02-02 23:04:36 +00004220 goto theend;
Bram Moolenaar81695252004-12-29 20:58:21 +00004221 }
Bram Moolenaar60abe752013-03-07 16:32:54 +01004222
4223 if (s != NULL && *s == NUL)
4224 {
4225 /* Pattern is empty, use last search pattern. */
4226 if (last_search_pat() == NULL)
4227 {
4228 EMSG(_(e_noprevre));
4229 goto theend;
4230 }
4231 regmatch.regprog = vim_regcomp(last_search_pat(), RE_MAGIC);
4232 }
4233 else
4234 regmatch.regprog = vim_regcomp(s, RE_MAGIC);
4235
Bram Moolenaar86b68352004-12-27 21:59:20 +00004236 if (regmatch.regprog == NULL)
4237 goto theend;
Bram Moolenaar5f2bb9f2005-01-11 21:29:04 +00004238 regmatch.rmm_ic = p_ic;
Bram Moolenaar3b56eb32005-07-11 22:40:32 +00004239 regmatch.rmm_maxcol = 0;
Bram Moolenaar86b68352004-12-27 21:59:20 +00004240
4241 p = skipwhite(p);
4242 if (*p == NUL)
4243 {
4244 EMSG(_("E683: File name missing or invalid pattern"));
4245 goto theend;
4246 }
4247
Bram Moolenaar55b69262017-08-13 13:42:01 +02004248 if ((eap->cmdidx != CMD_grepadd && eap->cmdidx != CMD_lgrepadd
4249 && eap->cmdidx != CMD_vimgrepadd && eap->cmdidx != CMD_lvimgrepadd)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00004250 || qi->qf_curlist == qi->qf_listcount)
Bram Moolenaar86b68352004-12-27 21:59:20 +00004251 /* make place for a new list */
Bram Moolenaar5584df62016-03-18 21:00:51 +01004252 qf_new_list(qi, title != NULL ? title : *eap->cmdlinep);
Bram Moolenaar86b68352004-12-27 21:59:20 +00004253
4254 /* parse the list of arguments */
Bram Moolenaar8f5c6f02012-06-29 12:57:06 +02004255 if (get_arglist_exp(p, &fcount, &fnames, TRUE) == FAIL)
Bram Moolenaar86b68352004-12-27 21:59:20 +00004256 goto theend;
4257 if (fcount == 0)
4258 {
4259 EMSG(_(e_nomatch));
4260 goto theend;
4261 }
4262
Bram Moolenaarb86a3432016-01-10 16:00:53 +01004263 dirname_start = alloc_id(MAXPATHL, aid_qf_dirname_start);
4264 dirname_now = alloc_id(MAXPATHL, aid_qf_dirname_now);
Bram Moolenaard9462e32011-04-11 21:35:11 +02004265 if (dirname_start == NULL || dirname_now == NULL)
Bram Moolenaar61ff4dd2016-01-18 20:30:17 +01004266 {
4267 FreeWild(fcount, fnames);
Bram Moolenaard9462e32011-04-11 21:35:11 +02004268 goto theend;
Bram Moolenaar61ff4dd2016-01-18 20:30:17 +01004269 }
Bram Moolenaard9462e32011-04-11 21:35:11 +02004270
Bram Moolenaard089d9b2007-09-30 12:02:55 +00004271 /* Remember the current directory, because a BufRead autocommand that does
4272 * ":lcd %:p:h" changes the meaning of short path names. */
4273 mch_dirname(dirname_start, MAXPATHL);
4274
Bram Moolenaar321a9ec2012-12-12 15:55:20 +01004275#ifdef FEAT_AUTOCMD
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02004276 /* Remember the value of qf_start, so that we can check for autocommands
Bram Moolenaar321a9ec2012-12-12 15:55:20 +01004277 * changing the current quickfix list. */
4278 cur_qf_start = qi->qf_lists[qi->qf_curlist].qf_start;
4279#endif
4280
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004281 seconds = (time_t)0;
Bram Moolenaar1f35bf92006-03-07 22:38:47 +00004282 for (fi = 0; fi < fcount && !got_int && tomatch > 0; ++fi)
Bram Moolenaar86b68352004-12-27 21:59:20 +00004283 {
Bram Moolenaard089d9b2007-09-30 12:02:55 +00004284 fname = shorten_fname1(fnames[fi]);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004285 if (time(NULL) > seconds)
4286 {
Bram Moolenaard089d9b2007-09-30 12:02:55 +00004287 /* Display the file name every second or so, show the user we are
4288 * working on it. */
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004289 seconds = time(NULL);
4290 msg_start();
Bram Moolenaard089d9b2007-09-30 12:02:55 +00004291 p = msg_strtrunc(fname, TRUE);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004292 if (p == NULL)
Bram Moolenaard089d9b2007-09-30 12:02:55 +00004293 msg_outtrans(fname);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004294 else
4295 {
4296 msg_outtrans(p);
4297 vim_free(p);
4298 }
4299 msg_clr_eos();
4300 msg_didout = FALSE; /* overwrite this message */
4301 msg_nowait = TRUE; /* don't wait for this message */
4302 msg_col = 0;
4303 out_flush();
4304 }
4305
Bram Moolenaar81695252004-12-29 20:58:21 +00004306 buf = buflist_findname_exp(fnames[fi]);
4307 if (buf == NULL || buf->b_ml.ml_mfp == NULL)
4308 {
4309 /* Remember that a buffer with this name already exists. */
4310 duplicate_name = (buf != NULL);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004311 using_dummy = TRUE;
Bram Moolenaar1042fa32007-09-16 11:27:42 +00004312 redraw_for_dummy = TRUE;
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004313
4314#if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
4315 /* Don't do Filetype autocommands to avoid loading syntax and
4316 * indent scripts, a great speed improvement. */
4317 save_ei = au_event_disable(",Filetype");
4318#endif
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00004319 /* Don't use modelines here, it's useless. */
4320 save_mls = p_mls;
4321 p_mls = 0;
Bram Moolenaar81695252004-12-29 20:58:21 +00004322
4323 /* Load file into a buffer, so that 'fileencoding' is detected,
4324 * autocommands applied, etc. */
Bram Moolenaar7f51a822012-04-25 18:57:21 +02004325 buf = load_dummy_buffer(fname, dirname_start, dirname_now);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004326
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00004327 p_mls = save_mls;
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004328#if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
4329 au_event_restore(save_ei);
4330#endif
Bram Moolenaar81695252004-12-29 20:58:21 +00004331 }
4332 else
4333 /* Use existing, loaded buffer. */
4334 using_dummy = FALSE;
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004335
Bram Moolenaar321a9ec2012-12-12 15:55:20 +01004336#ifdef FEAT_AUTOCMD
4337 if (cur_qf_start != qi->qf_lists[qi->qf_curlist].qf_start)
4338 {
4339 int idx;
4340
4341 /* Autocommands changed the quickfix list. Find the one we were
4342 * using and restore it. */
4343 for (idx = 0; idx < LISTCOUNT; ++idx)
4344 if (cur_qf_start == qi->qf_lists[idx].qf_start)
4345 {
4346 qi->qf_curlist = idx;
4347 break;
4348 }
4349 if (idx == LISTCOUNT)
4350 {
4351 /* List cannot be found, create a new one. */
4352 qf_new_list(qi, *eap->cmdlinep);
4353 cur_qf_start = qi->qf_lists[qi->qf_curlist].qf_start;
4354 }
4355 }
4356#endif
4357
Bram Moolenaar81695252004-12-29 20:58:21 +00004358 if (buf == NULL)
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004359 {
4360 if (!got_int)
Bram Moolenaard089d9b2007-09-30 12:02:55 +00004361 smsg((char_u *)_("Cannot open file \"%s\""), fname);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004362 }
Bram Moolenaar86b68352004-12-27 21:59:20 +00004363 else
4364 {
Bram Moolenaara3227e22006-03-08 21:32:40 +00004365 /* Try for a match in all lines of the buffer.
4366 * For ":1vimgrep" look for first match only. */
Bram Moolenaar81695252004-12-29 20:58:21 +00004367 found_match = FALSE;
Bram Moolenaar1f35bf92006-03-07 22:38:47 +00004368 for (lnum = 1; lnum <= buf->b_ml.ml_line_count && tomatch > 0;
4369 ++lnum)
Bram Moolenaar86b68352004-12-27 21:59:20 +00004370 {
Bram Moolenaar05159a02005-02-26 23:04:13 +00004371 col = 0;
4372 while (vim_regexec_multi(&regmatch, curwin, buf, lnum,
Bram Moolenaarfbd0b0a2017-06-17 18:44:21 +02004373 col, NULL, NULL) > 0)
Bram Moolenaar86b68352004-12-27 21:59:20 +00004374 {
Bram Moolenaar015102e2016-07-16 18:24:56 +02004375 /* Pass the buffer number so that it gets used even for a
4376 * dummy buffer, unless duplicate_name is set, then the
4377 * buffer will be wiped out below. */
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02004378 if (qf_add_entry(qi,
Bram Moolenaara3921f42017-06-04 15:30:34 +02004379 qi->qf_curlist,
Bram Moolenaar86b68352004-12-27 21:59:20 +00004380 NULL, /* dir */
Bram Moolenaard089d9b2007-09-30 12:02:55 +00004381 fname,
Bram Moolenaar015102e2016-07-16 18:24:56 +02004382 duplicate_name ? 0 : buf->b_fnum,
Bram Moolenaar81695252004-12-29 20:58:21 +00004383 ml_get_buf(buf,
4384 regmatch.startpos[0].lnum + lnum, FALSE),
4385 regmatch.startpos[0].lnum + lnum,
4386 regmatch.startpos[0].col + 1,
Bram Moolenaar05159a02005-02-26 23:04:13 +00004387 FALSE, /* vis_col */
Bram Moolenaar68b76a62005-03-25 21:53:48 +00004388 NULL, /* search pattern */
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00004389 0, /* nr */
4390 0, /* type */
4391 TRUE /* valid */
Bram Moolenaar86b68352004-12-27 21:59:20 +00004392 ) == FAIL)
4393 {
4394 got_int = TRUE;
4395 break;
4396 }
Bram Moolenaar1f35bf92006-03-07 22:38:47 +00004397 found_match = TRUE;
4398 if (--tomatch == 0)
4399 break;
Bram Moolenaar05159a02005-02-26 23:04:13 +00004400 if ((flags & VGR_GLOBAL) == 0
4401 || regmatch.endpos[0].lnum > 0)
4402 break;
4403 col = regmatch.endpos[0].col
4404 + (col == regmatch.endpos[0].col);
Bram Moolenaar2c4278f2009-05-17 11:33:22 +00004405 if (col > (colnr_T)STRLEN(ml_get_buf(buf, lnum, FALSE)))
Bram Moolenaar05159a02005-02-26 23:04:13 +00004406 break;
Bram Moolenaar86b68352004-12-27 21:59:20 +00004407 }
Bram Moolenaar86b68352004-12-27 21:59:20 +00004408 line_breakcheck();
Bram Moolenaar81695252004-12-29 20:58:21 +00004409 if (got_int)
4410 break;
Bram Moolenaar86b68352004-12-27 21:59:20 +00004411 }
Bram Moolenaar321a9ec2012-12-12 15:55:20 +01004412#ifdef FEAT_AUTOCMD
4413 cur_qf_start = qi->qf_lists[qi->qf_curlist].qf_start;
4414#endif
Bram Moolenaar81695252004-12-29 20:58:21 +00004415
4416 if (using_dummy)
4417 {
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004418 if (found_match && first_match_buf == NULL)
4419 first_match_buf = buf;
Bram Moolenaar81695252004-12-29 20:58:21 +00004420 if (duplicate_name)
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004421 {
Bram Moolenaar81695252004-12-29 20:58:21 +00004422 /* Never keep a dummy buffer if there is another buffer
4423 * with the same name. */
Bram Moolenaar7f51a822012-04-25 18:57:21 +02004424 wipe_dummy_buffer(buf, dirname_start);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004425 buf = NULL;
4426 }
Bram Moolenaara3227e22006-03-08 21:32:40 +00004427 else if (!cmdmod.hide
4428 || buf->b_p_bh[0] == 'u' /* "unload" */
4429 || buf->b_p_bh[0] == 'w' /* "wipe" */
4430 || buf->b_p_bh[0] == 'd') /* "delete" */
Bram Moolenaar81695252004-12-29 20:58:21 +00004431 {
Bram Moolenaara3227e22006-03-08 21:32:40 +00004432 /* When no match was found we don't need to remember the
4433 * buffer, wipe it out. If there was a match and it
4434 * wasn't the first one or we won't jump there: only
4435 * unload the buffer.
4436 * Ignore 'hidden' here, because it may lead to having too
4437 * many swap files. */
Bram Moolenaar81695252004-12-29 20:58:21 +00004438 if (!found_match)
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004439 {
Bram Moolenaar7f51a822012-04-25 18:57:21 +02004440 wipe_dummy_buffer(buf, dirname_start);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004441 buf = NULL;
4442 }
Bram Moolenaar05159a02005-02-26 23:04:13 +00004443 else if (buf != first_match_buf || (flags & VGR_NOJUMP))
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004444 {
Bram Moolenaar7f51a822012-04-25 18:57:21 +02004445 unload_dummy_buffer(buf, dirname_start);
Bram Moolenaar015102e2016-07-16 18:24:56 +02004446 /* Keeping the buffer, remove the dummy flag. */
4447 buf->b_flags &= ~BF_DUMMY;
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004448 buf = NULL;
4449 }
Bram Moolenaar81695252004-12-29 20:58:21 +00004450 }
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004451
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004452 if (buf != NULL)
4453 {
Bram Moolenaar015102e2016-07-16 18:24:56 +02004454 /* Keeping the buffer, remove the dummy flag. */
4455 buf->b_flags &= ~BF_DUMMY;
4456
Bram Moolenaard089d9b2007-09-30 12:02:55 +00004457 /* If the buffer is still loaded we need to use the
4458 * directory we jumped to below. */
4459 if (buf == first_match_buf
4460 && target_dir == NULL
4461 && STRCMP(dirname_start, dirname_now) != 0)
4462 target_dir = vim_strsave(dirname_now);
4463
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004464 /* The buffer is still loaded, the Filetype autocommands
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00004465 * need to be done now, in that buffer. And the modelines
Bram Moolenaara3227e22006-03-08 21:32:40 +00004466 * need to be done (again). But not the window-local
4467 * options! */
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004468 aucmd_prepbuf(&aco, buf);
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00004469#if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004470 apply_autocmds(EVENT_FILETYPE, buf->b_p_ft,
4471 buf->b_fname, TRUE, buf);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00004472#endif
Bram Moolenaara3227e22006-03-08 21:32:40 +00004473 do_modelines(OPT_NOWIN);
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00004474 aucmd_restbuf(&aco);
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00004475 }
Bram Moolenaar81695252004-12-29 20:58:21 +00004476 }
Bram Moolenaar86b68352004-12-27 21:59:20 +00004477 }
4478 }
4479
4480 FreeWild(fcount, fnames);
4481
Bram Moolenaard12f5c12006-01-25 22:10:52 +00004482 qi->qf_lists[qi->qf_curlist].qf_nonevalid = FALSE;
4483 qi->qf_lists[qi->qf_curlist].qf_ptr = qi->qf_lists[qi->qf_curlist].qf_start;
4484 qi->qf_lists[qi->qf_curlist].qf_index = 1;
Bram Moolenaarb254af32017-12-18 19:48:58 +01004485 qf_list_changed(qi, qi->qf_curlist);
Bram Moolenaar86b68352004-12-27 21:59:20 +00004486
Bram Moolenaar864293a2016-06-02 13:40:04 +02004487 qf_update_buffer(qi, NULL);
Bram Moolenaar86b68352004-12-27 21:59:20 +00004488
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00004489#ifdef FEAT_AUTOCMD
4490 if (au_name != NULL)
4491 apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name,
4492 curbuf->b_fname, TRUE, curbuf);
4493#endif
4494
Bram Moolenaar86b68352004-12-27 21:59:20 +00004495 /* Jump to first match. */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00004496 if (qi->qf_lists[qi->qf_curlist].qf_count > 0)
Bram Moolenaar05159a02005-02-26 23:04:13 +00004497 {
4498 if ((flags & VGR_NOJUMP) == 0)
Bram Moolenaar1042fa32007-09-16 11:27:42 +00004499 {
4500 buf = curbuf;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00004501 qf_jump(qi, 0, 0, eap->forceit);
Bram Moolenaar1042fa32007-09-16 11:27:42 +00004502 if (buf != curbuf)
4503 /* If we jumped to another buffer redrawing will already be
4504 * taken care of. */
4505 redraw_for_dummy = FALSE;
Bram Moolenaard089d9b2007-09-30 12:02:55 +00004506
4507 /* Jump to the directory used after loading the buffer. */
4508 if (curbuf == first_match_buf && target_dir != NULL)
4509 {
4510 exarg_T ea;
4511
4512 ea.arg = target_dir;
4513 ea.cmdidx = CMD_lcd;
4514 ex_cd(&ea);
4515 }
Bram Moolenaar1042fa32007-09-16 11:27:42 +00004516 }
Bram Moolenaar05159a02005-02-26 23:04:13 +00004517 }
Bram Moolenaar81695252004-12-29 20:58:21 +00004518 else
4519 EMSG2(_(e_nomatch2), s);
Bram Moolenaar86b68352004-12-27 21:59:20 +00004520
Bram Moolenaar1042fa32007-09-16 11:27:42 +00004521 /* If we loaded a dummy buffer into the current window, the autocommands
4522 * may have messed up things, need to redraw and recompute folds. */
4523 if (redraw_for_dummy)
4524 {
4525#ifdef FEAT_FOLDING
4526 foldUpdateAll(curwin);
4527#else
4528 redraw_later(NOT_VALID);
4529#endif
4530 }
4531
Bram Moolenaar86b68352004-12-27 21:59:20 +00004532theend:
Bram Moolenaar5584df62016-03-18 21:00:51 +01004533 vim_free(title);
Bram Moolenaard9462e32011-04-11 21:35:11 +02004534 vim_free(dirname_now);
4535 vim_free(dirname_start);
Bram Moolenaard089d9b2007-09-30 12:02:55 +00004536 vim_free(target_dir);
Bram Moolenaar473de612013-06-08 18:19:48 +02004537 vim_regfree(regmatch.regprog);
Bram Moolenaar86b68352004-12-27 21:59:20 +00004538}
4539
4540/*
Bram Moolenaar7f51a822012-04-25 18:57:21 +02004541 * Restore current working directory to "dirname_start" if they differ, taking
4542 * into account whether it is set locally or globally.
4543 */
4544 static void
Bram Moolenaar05540972016-01-30 20:31:25 +01004545restore_start_dir(char_u *dirname_start)
Bram Moolenaar7f51a822012-04-25 18:57:21 +02004546{
4547 char_u *dirname_now = alloc(MAXPATHL);
4548
4549 if (NULL != dirname_now)
4550 {
4551 mch_dirname(dirname_now, MAXPATHL);
4552 if (STRCMP(dirname_start, dirname_now) != 0)
4553 {
4554 /* If the directory has changed, change it back by building up an
4555 * appropriate ex command and executing it. */
4556 exarg_T ea;
4557
4558 ea.arg = dirname_start;
4559 ea.cmdidx = (curwin->w_localdir == NULL) ? CMD_cd : CMD_lcd;
4560 ex_cd(&ea);
4561 }
Bram Moolenaarf1354352012-11-28 22:12:44 +01004562 vim_free(dirname_now);
Bram Moolenaar7f51a822012-04-25 18:57:21 +02004563 }
4564}
4565
4566/*
4567 * Load file "fname" into a dummy buffer and return the buffer pointer,
4568 * placing the directory resulting from the buffer load into the
4569 * "resulting_dir" pointer. "resulting_dir" must be allocated by the caller
4570 * prior to calling this function. Restores directory to "dirname_start" prior
4571 * to returning, if autocmds or the 'autochdir' option have changed it.
4572 *
4573 * If creating the dummy buffer does not fail, must call unload_dummy_buffer()
4574 * or wipe_dummy_buffer() later!
4575 *
Bram Moolenaar81695252004-12-29 20:58:21 +00004576 * Returns NULL if it fails.
Bram Moolenaar81695252004-12-29 20:58:21 +00004577 */
4578 static buf_T *
Bram Moolenaar05540972016-01-30 20:31:25 +01004579load_dummy_buffer(
4580 char_u *fname,
4581 char_u *dirname_start, /* in: old directory */
4582 char_u *resulting_dir) /* out: new directory */
Bram Moolenaar81695252004-12-29 20:58:21 +00004583{
4584 buf_T *newbuf;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02004585 bufref_T newbufref;
4586 bufref_T newbuf_to_wipe;
Bram Moolenaar81695252004-12-29 20:58:21 +00004587 int failed = TRUE;
Bram Moolenaar81695252004-12-29 20:58:21 +00004588 aco_save_T aco;
Bram Moolenaar4fb921e2017-12-18 15:33:00 +01004589 int readfile_result;
Bram Moolenaar81695252004-12-29 20:58:21 +00004590
4591 /* Allocate a buffer without putting it in the buffer list. */
4592 newbuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY);
4593 if (newbuf == NULL)
4594 return NULL;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02004595 set_bufref(&newbufref, newbuf);
Bram Moolenaar81695252004-12-29 20:58:21 +00004596
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00004597 /* Init the options. */
4598 buf_copy_options(newbuf, BCO_ENTER | BCO_NOHELP);
4599
Bram Moolenaarf061e0b2009-06-24 15:32:01 +00004600 /* need to open the memfile before putting the buffer in a window */
4601 if (ml_open(newbuf) == OK)
Bram Moolenaar81695252004-12-29 20:58:21 +00004602 {
Bram Moolenaar4fb921e2017-12-18 15:33:00 +01004603 /* Make sure this buffer isn't wiped out by auto commands. */
4604 ++newbuf->b_locked;
4605
Bram Moolenaarf061e0b2009-06-24 15:32:01 +00004606 /* set curwin/curbuf to buf and save a few things */
4607 aucmd_prepbuf(&aco, newbuf);
4608
4609 /* Need to set the filename for autocommands. */
4610 (void)setfname(curbuf, fname, NULL, FALSE);
4611
Bram Moolenaar81695252004-12-29 20:58:21 +00004612 /* Create swap file now to avoid the ATTENTION message. */
4613 check_need_swap(TRUE);
4614
4615 /* Remove the "dummy" flag, otherwise autocommands may not
4616 * work. */
4617 curbuf->b_flags &= ~BF_DUMMY;
4618
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02004619 newbuf_to_wipe.br_buf = NULL;
Bram Moolenaar4fb921e2017-12-18 15:33:00 +01004620 readfile_result = readfile(fname, NULL,
Bram Moolenaar81695252004-12-29 20:58:21 +00004621 (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM,
Bram Moolenaar4fb921e2017-12-18 15:33:00 +01004622 NULL, READ_NEW | READ_DUMMY);
4623 --newbuf->b_locked;
4624 if (readfile_result == OK
Bram Moolenaard68071d2006-05-02 22:08:30 +00004625 && !got_int
Bram Moolenaar81695252004-12-29 20:58:21 +00004626 && !(curbuf->b_flags & BF_NEW))
4627 {
4628 failed = FALSE;
4629 if (curbuf != newbuf)
4630 {
Bram Moolenaar0785ccf2010-11-24 16:32:05 +01004631 /* Bloody autocommands changed the buffer! Can happen when
4632 * using netrw and editing a remote file. Use the current
4633 * buffer instead, delete the dummy one after restoring the
4634 * window stuff. */
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02004635 set_bufref(&newbuf_to_wipe, newbuf);
Bram Moolenaar81695252004-12-29 20:58:21 +00004636 newbuf = curbuf;
4637 }
4638 }
Bram Moolenaar81695252004-12-29 20:58:21 +00004639
Bram Moolenaarf061e0b2009-06-24 15:32:01 +00004640 /* restore curwin/curbuf and a few other things */
4641 aucmd_restbuf(&aco);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02004642 if (newbuf_to_wipe.br_buf != NULL && bufref_valid(&newbuf_to_wipe))
4643 wipe_buffer(newbuf_to_wipe.br_buf, FALSE);
Bram Moolenaarea3f2e72016-07-10 20:27:32 +02004644
4645 /* Add back the "dummy" flag, otherwise buflist_findname_stat() won't
4646 * skip it. */
4647 newbuf->b_flags |= BF_DUMMY;
Bram Moolenaarf061e0b2009-06-24 15:32:01 +00004648 }
Bram Moolenaar81695252004-12-29 20:58:21 +00004649
Bram Moolenaar7f51a822012-04-25 18:57:21 +02004650 /*
4651 * When autocommands/'autochdir' option changed directory: go back.
4652 * Let the caller know what the resulting dir was first, in case it is
4653 * important.
4654 */
4655 mch_dirname(resulting_dir, MAXPATHL);
4656 restore_start_dir(dirname_start);
4657
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02004658 if (!bufref_valid(&newbufref))
Bram Moolenaar81695252004-12-29 20:58:21 +00004659 return NULL;
4660 if (failed)
4661 {
Bram Moolenaar7f51a822012-04-25 18:57:21 +02004662 wipe_dummy_buffer(newbuf, dirname_start);
Bram Moolenaar81695252004-12-29 20:58:21 +00004663 return NULL;
4664 }
4665 return newbuf;
4666}
4667
4668/*
Bram Moolenaar7f51a822012-04-25 18:57:21 +02004669 * Wipe out the dummy buffer that load_dummy_buffer() created. Restores
4670 * directory to "dirname_start" prior to returning, if autocmds or the
4671 * 'autochdir' option have changed it.
Bram Moolenaar81695252004-12-29 20:58:21 +00004672 */
4673 static void
Bram Moolenaar05540972016-01-30 20:31:25 +01004674wipe_dummy_buffer(buf_T *buf, char_u *dirname_start)
Bram Moolenaar81695252004-12-29 20:58:21 +00004675{
4676 if (curbuf != buf) /* safety check */
Bram Moolenaard68071d2006-05-02 22:08:30 +00004677 {
4678#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
4679 cleanup_T cs;
4680
4681 /* Reset the error/interrupt/exception state here so that aborting()
4682 * returns FALSE when wiping out the buffer. Otherwise it doesn't
4683 * work when got_int is set. */
4684 enter_cleanup(&cs);
4685#endif
4686
Bram Moolenaar81695252004-12-29 20:58:21 +00004687 wipe_buffer(buf, FALSE);
Bram Moolenaard68071d2006-05-02 22:08:30 +00004688
4689#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
4690 /* Restore the error/interrupt/exception state if not discarded by a
4691 * new aborting error, interrupt, or uncaught exception. */
4692 leave_cleanup(&cs);
4693#endif
Bram Moolenaar7f51a822012-04-25 18:57:21 +02004694 /* When autocommands/'autochdir' option changed directory: go back. */
4695 restore_start_dir(dirname_start);
Bram Moolenaard68071d2006-05-02 22:08:30 +00004696 }
Bram Moolenaar81695252004-12-29 20:58:21 +00004697}
4698
4699/*
Bram Moolenaar7f51a822012-04-25 18:57:21 +02004700 * Unload the dummy buffer that load_dummy_buffer() created. Restores
4701 * directory to "dirname_start" prior to returning, if autocmds or the
4702 * 'autochdir' option have changed it.
Bram Moolenaar81695252004-12-29 20:58:21 +00004703 */
4704 static void
Bram Moolenaar05540972016-01-30 20:31:25 +01004705unload_dummy_buffer(buf_T *buf, char_u *dirname_start)
Bram Moolenaar81695252004-12-29 20:58:21 +00004706{
4707 if (curbuf != buf) /* safety check */
Bram Moolenaar7f51a822012-04-25 18:57:21 +02004708 {
Bram Moolenaar42ec6562012-02-22 14:58:37 +01004709 close_buffer(NULL, buf, DOBUF_UNLOAD, FALSE);
Bram Moolenaar7f51a822012-04-25 18:57:21 +02004710
4711 /* When autocommands/'autochdir' option changed directory: go back. */
4712 restore_start_dir(dirname_start);
4713 }
Bram Moolenaar81695252004-12-29 20:58:21 +00004714}
4715
Bram Moolenaar05159a02005-02-26 23:04:13 +00004716#if defined(FEAT_EVAL) || defined(PROTO)
4717/*
4718 * Add each quickfix error to list "list" as a dictionary.
Bram Moolenaard823fa92016-08-12 16:29:27 +02004719 * If qf_idx is -1, use the current list. Otherwise, use the specified list.
Bram Moolenaar05159a02005-02-26 23:04:13 +00004720 */
4721 int
Bram Moolenaar7adf06f2017-08-27 15:23:41 +02004722get_errorlist(qf_info_T *qi_arg, win_T *wp, int qf_idx, list_T *list)
Bram Moolenaar05159a02005-02-26 23:04:13 +00004723{
Bram Moolenaar7adf06f2017-08-27 15:23:41 +02004724 qf_info_T *qi = qi_arg;
Bram Moolenaar68b76a62005-03-25 21:53:48 +00004725 dict_T *dict;
4726 char_u buf[2];
4727 qfline_T *qfp;
4728 int i;
Bram Moolenaar48b66fb2007-02-04 01:58:18 +00004729 int bufnum;
Bram Moolenaar05159a02005-02-26 23:04:13 +00004730
Bram Moolenaar7adf06f2017-08-27 15:23:41 +02004731 if (qi == NULL)
Bram Moolenaar17c7c012006-01-26 22:25:15 +00004732 {
Bram Moolenaar7adf06f2017-08-27 15:23:41 +02004733 qi = &ql_info;
4734 if (wp != NULL)
4735 {
4736 qi = GET_LOC_LIST(wp);
4737 if (qi == NULL)
4738 return FAIL;
4739 }
Bram Moolenaar17c7c012006-01-26 22:25:15 +00004740 }
4741
Bram Moolenaard823fa92016-08-12 16:29:27 +02004742 if (qf_idx == -1)
4743 qf_idx = qi->qf_curlist;
4744
4745 if (qf_idx >= qi->qf_listcount
4746 || qi->qf_lists[qf_idx].qf_count == 0)
Bram Moolenaar05159a02005-02-26 23:04:13 +00004747 return FAIL;
Bram Moolenaar05159a02005-02-26 23:04:13 +00004748
Bram Moolenaard823fa92016-08-12 16:29:27 +02004749 qfp = qi->qf_lists[qf_idx].qf_start;
4750 for (i = 1; !got_int && i <= qi->qf_lists[qf_idx].qf_count; ++i)
Bram Moolenaar05159a02005-02-26 23:04:13 +00004751 {
Bram Moolenaar48b66fb2007-02-04 01:58:18 +00004752 /* Handle entries with a non-existing buffer number. */
4753 bufnum = qfp->qf_fnum;
4754 if (bufnum != 0 && (buflist_findnr(bufnum) == NULL))
4755 bufnum = 0;
4756
Bram Moolenaar05159a02005-02-26 23:04:13 +00004757 if ((dict = dict_alloc()) == NULL)
4758 return FAIL;
4759 if (list_append_dict(list, dict) == FAIL)
4760 return FAIL;
4761
4762 buf[0] = qfp->qf_type;
4763 buf[1] = NUL;
Bram Moolenaar48b66fb2007-02-04 01:58:18 +00004764 if ( dict_add_nr_str(dict, "bufnr", (long)bufnum, NULL) == FAIL
Bram Moolenaar05159a02005-02-26 23:04:13 +00004765 || dict_add_nr_str(dict, "lnum", (long)qfp->qf_lnum, NULL) == FAIL
4766 || dict_add_nr_str(dict, "col", (long)qfp->qf_col, NULL) == FAIL
4767 || dict_add_nr_str(dict, "vcol", (long)qfp->qf_viscol, NULL) == FAIL
4768 || dict_add_nr_str(dict, "nr", (long)qfp->qf_nr, NULL) == FAIL
Bram Moolenaar53ed1922006-09-05 13:37:47 +00004769 || dict_add_nr_str(dict, "pattern", 0L,
4770 qfp->qf_pattern == NULL ? (char_u *)"" : qfp->qf_pattern) == FAIL
4771 || dict_add_nr_str(dict, "text", 0L,
4772 qfp->qf_text == NULL ? (char_u *)"" : qfp->qf_text) == FAIL
Bram Moolenaar05159a02005-02-26 23:04:13 +00004773 || dict_add_nr_str(dict, "type", 0L, buf) == FAIL
4774 || dict_add_nr_str(dict, "valid", (long)qfp->qf_valid, NULL) == FAIL)
4775 return FAIL;
4776
4777 qfp = qfp->qf_next;
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02004778 if (qfp == NULL)
4779 break;
Bram Moolenaar05159a02005-02-26 23:04:13 +00004780 }
4781 return OK;
4782}
Bram Moolenaar68b76a62005-03-25 21:53:48 +00004783
4784/*
Bram Moolenaard823fa92016-08-12 16:29:27 +02004785 * Flags used by getqflist()/getloclist() to determine which fields to return.
4786 */
4787enum {
4788 QF_GETLIST_NONE = 0x0,
4789 QF_GETLIST_TITLE = 0x1,
4790 QF_GETLIST_ITEMS = 0x2,
4791 QF_GETLIST_NR = 0x4,
4792 QF_GETLIST_WINID = 0x8,
Bram Moolenaar8f77c5a2017-04-30 14:21:00 +02004793 QF_GETLIST_CONTEXT = 0x10,
Bram Moolenaara539f4f2017-08-30 20:33:55 +02004794 QF_GETLIST_ID = 0x20,
Bram Moolenaarfc2b2702017-09-15 22:43:07 +02004795 QF_GETLIST_IDX = 0x40,
4796 QF_GETLIST_SIZE = 0x80,
Bram Moolenaarb254af32017-12-18 19:48:58 +01004797 QF_GETLIST_TICK = 0x100,
4798 QF_GETLIST_ALL = 0x1FF
Bram Moolenaard823fa92016-08-12 16:29:27 +02004799};
4800
4801/*
Bram Moolenaar7adf06f2017-08-27 15:23:41 +02004802 * Parse text from 'di' and return the quickfix list items
4803 */
4804 static int
Bram Moolenaar36538222017-09-02 19:51:44 +02004805qf_get_list_from_lines(dict_T *what, dictitem_T *di, dict_T *retdict)
Bram Moolenaar7adf06f2017-08-27 15:23:41 +02004806{
4807 int status = FAIL;
4808 qf_info_T *qi;
Bram Moolenaar36538222017-09-02 19:51:44 +02004809 char_u *errorformat = p_efm;
4810 dictitem_T *efm_di;
4811 list_T *l;
Bram Moolenaar7adf06f2017-08-27 15:23:41 +02004812
Bram Moolenaar2c809b72017-09-01 18:34:02 +02004813 /* Only a List value is supported */
4814 if (di->di_tv.v_type == VAR_LIST && di->di_tv.vval.v_list != NULL)
Bram Moolenaar7adf06f2017-08-27 15:23:41 +02004815 {
Bram Moolenaar36538222017-09-02 19:51:44 +02004816 /* If errorformat is supplied then use it, otherwise use the 'efm'
4817 * option setting
4818 */
4819 if ((efm_di = dict_find(what, (char_u *)"efm", -1)) != NULL)
4820 {
4821 if (efm_di->di_tv.v_type != VAR_STRING ||
4822 efm_di->di_tv.vval.v_string == NULL)
4823 return FAIL;
4824 errorformat = efm_di->di_tv.vval.v_string;
4825 }
Bram Moolenaarda732532017-08-31 20:58:02 +02004826
Bram Moolenaar36538222017-09-02 19:51:44 +02004827 l = list_alloc();
Bram Moolenaarda732532017-08-31 20:58:02 +02004828 if (l == NULL)
4829 return FAIL;
4830
Bram Moolenaar7adf06f2017-08-27 15:23:41 +02004831 qi = (qf_info_T *)alloc((unsigned)sizeof(qf_info_T));
4832 if (qi != NULL)
4833 {
4834 vim_memset(qi, 0, (size_t)(sizeof(qf_info_T)));
4835 qi->qf_refcount++;
4836
Bram Moolenaar36538222017-09-02 19:51:44 +02004837 if (qf_init_ext(qi, 0, NULL, NULL, &di->di_tv, errorformat,
Bram Moolenaar7adf06f2017-08-27 15:23:41 +02004838 TRUE, (linenr_T)0, (linenr_T)0, NULL, NULL) > 0)
4839 {
Bram Moolenaarda732532017-08-31 20:58:02 +02004840 (void)get_errorlist(qi, NULL, 0, l);
Bram Moolenaar7adf06f2017-08-27 15:23:41 +02004841 qf_free(qi, 0);
4842 }
4843 free(qi);
4844 }
Bram Moolenaarda732532017-08-31 20:58:02 +02004845 dict_add_list(retdict, "items", l);
4846 status = OK;
Bram Moolenaar7adf06f2017-08-27 15:23:41 +02004847 }
4848
4849 return status;
4850}
4851
4852/*
Bram Moolenaarb4d5fba2017-09-11 19:31:28 +02004853 * Return the quickfix/location list number with the given identifier.
4854 * Returns -1 if list is not found.
4855 */
4856 static int
4857qf_id2nr(qf_info_T *qi, int_u qfid)
4858{
4859 int qf_idx;
4860
4861 for (qf_idx = 0; qf_idx < qi->qf_listcount; qf_idx++)
4862 if (qi->qf_lists[qf_idx].qf_id == qfid)
4863 return qf_idx;
4864 return -1;
4865}
4866
4867/*
Bram Moolenaard823fa92016-08-12 16:29:27 +02004868 * Return quickfix/location list details (title) as a
4869 * dictionary. 'what' contains the details to return. If 'list_idx' is -1,
4870 * then current list is used. Otherwise the specified list is used.
Bram Moolenaar68b76a62005-03-25 21:53:48 +00004871 */
4872 int
Bram Moolenaarb4d5fba2017-09-11 19:31:28 +02004873qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
Bram Moolenaard823fa92016-08-12 16:29:27 +02004874{
4875 qf_info_T *qi = &ql_info;
4876 int status = OK;
4877 int qf_idx;
4878 dictitem_T *di;
4879 int flags = QF_GETLIST_NONE;
4880
Bram Moolenaar2c809b72017-09-01 18:34:02 +02004881 if ((di = dict_find(what, (char_u *)"lines", -1)) != NULL)
Bram Moolenaar36538222017-09-02 19:51:44 +02004882 return qf_get_list_from_lines(what, di, retdict);
Bram Moolenaar7adf06f2017-08-27 15:23:41 +02004883
Bram Moolenaard823fa92016-08-12 16:29:27 +02004884 if (wp != NULL)
Bram Moolenaard823fa92016-08-12 16:29:27 +02004885 qi = GET_LOC_LIST(wp);
Bram Moolenaara539f4f2017-08-30 20:33:55 +02004886
Bram Moolenaara539f4f2017-08-30 20:33:55 +02004887 if (dict_find(what, (char_u *)"all", -1) != NULL)
4888 flags |= QF_GETLIST_ALL;
Bram Moolenaard823fa92016-08-12 16:29:27 +02004889
Bram Moolenaara539f4f2017-08-30 20:33:55 +02004890 if (dict_find(what, (char_u *)"title", -1) != NULL)
4891 flags |= QF_GETLIST_TITLE;
Bram Moolenaard823fa92016-08-12 16:29:27 +02004892
Bram Moolenaara6d48492017-12-12 22:45:31 +01004893 if (dict_find(what, (char_u *)"nr", -1) != NULL)
4894 flags |= QF_GETLIST_NR;
4895
Bram Moolenaara539f4f2017-08-30 20:33:55 +02004896 if (dict_find(what, (char_u *)"winid", -1) != NULL)
4897 flags |= QF_GETLIST_WINID;
Bram Moolenaard823fa92016-08-12 16:29:27 +02004898
Bram Moolenaara539f4f2017-08-30 20:33:55 +02004899 if (dict_find(what, (char_u *)"context", -1) != NULL)
4900 flags |= QF_GETLIST_CONTEXT;
Bram Moolenaar6a8958d2017-06-22 21:33:20 +02004901
Bram Moolenaara6d48492017-12-12 22:45:31 +01004902 if (dict_find(what, (char_u *)"id", -1) != NULL)
4903 flags |= QF_GETLIST_ID;
4904
Bram Moolenaara539f4f2017-08-30 20:33:55 +02004905 if (dict_find(what, (char_u *)"items", -1) != NULL)
4906 flags |= QF_GETLIST_ITEMS;
Bram Moolenaar8f77c5a2017-04-30 14:21:00 +02004907
Bram Moolenaarfc2b2702017-09-15 22:43:07 +02004908 if (dict_find(what, (char_u *)"idx", -1) != NULL)
4909 flags |= QF_GETLIST_IDX;
4910
4911 if (dict_find(what, (char_u *)"size", -1) != NULL)
4912 flags |= QF_GETLIST_SIZE;
4913
Bram Moolenaarb254af32017-12-18 19:48:58 +01004914 if (dict_find(what, (char_u *)"changedtick", -1) != NULL)
4915 flags |= QF_GETLIST_TICK;
4916
Bram Moolenaara6d48492017-12-12 22:45:31 +01004917 if (qi != NULL && qi->qf_listcount != 0)
4918 {
4919 qf_idx = qi->qf_curlist; /* default is the current list */
4920 if ((di = dict_find(what, (char_u *)"nr", -1)) != NULL)
4921 {
4922 /* Use the specified quickfix/location list */
4923 if (di->di_tv.v_type == VAR_NUMBER)
4924 {
4925 /* for zero use the current list */
4926 if (di->di_tv.vval.v_number != 0)
4927 {
4928 qf_idx = di->di_tv.vval.v_number - 1;
4929 if (qf_idx < 0 || qf_idx >= qi->qf_listcount)
4930 qf_idx = -1;
4931 }
4932 }
4933 else if ((di->di_tv.v_type == VAR_STRING)
4934 && (STRCMP(di->di_tv.vval.v_string, "$") == 0))
4935 /* Get the last quickfix list number */
4936 qf_idx = qi->qf_listcount - 1;
4937 else
4938 qf_idx = -1;
4939 flags |= QF_GETLIST_NR;
4940 }
4941
4942 if ((di = dict_find(what, (char_u *)"id", -1)) != NULL)
4943 {
4944 /* Look for a list with the specified id */
4945 if (di->di_tv.v_type == VAR_NUMBER)
4946 {
4947 /*
4948 * For zero, use the current list or the list specifed by 'nr'
4949 */
4950 if (di->di_tv.vval.v_number != 0)
4951 qf_idx = qf_id2nr(qi, di->di_tv.vval.v_number);
4952 flags |= QF_GETLIST_ID;
4953 }
4954 else
4955 qf_idx = -1;
4956 }
4957 }
4958
4959 /* List is not present or is empty */
4960 if (qi == NULL || qi->qf_listcount == 0 || qf_idx == -1)
4961 {
4962 if (flags & QF_GETLIST_TITLE)
4963 status = dict_add_nr_str(retdict, "title", 0L, (char_u *)"");
4964 if ((status == OK) && (flags & QF_GETLIST_ITEMS))
4965 {
4966 list_T *l = list_alloc();
4967 if (l != NULL)
4968 status = dict_add_list(retdict, "items", l);
4969 else
4970 status = FAIL;
4971 }
4972 if ((status == OK) && (flags & QF_GETLIST_NR))
4973 status = dict_add_nr_str(retdict, "nr", 0L, NULL);
4974 if ((status == OK) && (flags & QF_GETLIST_WINID))
4975 status = dict_add_nr_str(retdict, "winid", 0L, NULL);
4976 if ((status == OK) && (flags & QF_GETLIST_CONTEXT))
4977 status = dict_add_nr_str(retdict, "context", 0L, (char_u *)"");
4978 if ((status == OK) && (flags & QF_GETLIST_ID))
4979 status = dict_add_nr_str(retdict, "id", 0L, NULL);
4980 if ((status == OK) && (flags & QF_GETLIST_IDX))
4981 status = dict_add_nr_str(retdict, "idx", 0L, NULL);
4982 if ((status == OK) && (flags & QF_GETLIST_SIZE))
4983 status = dict_add_nr_str(retdict, "size", 0L, NULL);
Bram Moolenaarb254af32017-12-18 19:48:58 +01004984 if ((status == OK) && (flags & QF_GETLIST_TICK))
4985 status = dict_add_nr_str(retdict, "changedtick", 0L, NULL);
Bram Moolenaara6d48492017-12-12 22:45:31 +01004986
4987 return status;
4988 }
4989
Bram Moolenaard823fa92016-08-12 16:29:27 +02004990 if (flags & QF_GETLIST_TITLE)
4991 {
4992 char_u *t;
4993 t = qi->qf_lists[qf_idx].qf_title;
4994 if (t == NULL)
4995 t = (char_u *)"";
4996 status = dict_add_nr_str(retdict, "title", 0L, t);
4997 }
4998 if ((status == OK) && (flags & QF_GETLIST_NR))
4999 status = dict_add_nr_str(retdict, "nr", qf_idx + 1, NULL);
5000 if ((status == OK) && (flags & QF_GETLIST_WINID))
5001 {
5002 win_T *win;
Bram Moolenaar74240d32017-12-10 15:26:15 +01005003 int win_id = 0;
5004
Bram Moolenaard823fa92016-08-12 16:29:27 +02005005 win = qf_find_win(qi);
5006 if (win != NULL)
Bram Moolenaar74240d32017-12-10 15:26:15 +01005007 win_id = win->w_id;
5008 status = dict_add_nr_str(retdict, "winid", win_id, NULL);
Bram Moolenaard823fa92016-08-12 16:29:27 +02005009 }
Bram Moolenaar6a8958d2017-06-22 21:33:20 +02005010 if ((status == OK) && (flags & QF_GETLIST_ITEMS))
5011 {
5012 list_T *l = list_alloc();
5013 if (l != NULL)
5014 {
Bram Moolenaar7adf06f2017-08-27 15:23:41 +02005015 (void)get_errorlist(qi, NULL, qf_idx, l);
Bram Moolenaar6a8958d2017-06-22 21:33:20 +02005016 dict_add_list(retdict, "items", l);
5017 }
Bram Moolenaar86f100dc2017-06-28 21:26:27 +02005018 else
5019 status = FAIL;
Bram Moolenaar6a8958d2017-06-22 21:33:20 +02005020 }
Bram Moolenaard823fa92016-08-12 16:29:27 +02005021
Bram Moolenaar8f77c5a2017-04-30 14:21:00 +02005022 if ((status == OK) && (flags & QF_GETLIST_CONTEXT))
5023 {
5024 if (qi->qf_lists[qf_idx].qf_ctx != NULL)
5025 {
5026 di = dictitem_alloc((char_u *)"context");
5027 if (di != NULL)
5028 {
5029 copy_tv(qi->qf_lists[qf_idx].qf_ctx, &di->di_tv);
Bram Moolenaar86f100dc2017-06-28 21:26:27 +02005030 status = dict_add(retdict, di);
5031 if (status == FAIL)
Bram Moolenaarbeb9cb12017-05-01 14:14:04 +02005032 dictitem_free(di);
Bram Moolenaar8f77c5a2017-04-30 14:21:00 +02005033 }
Bram Moolenaar86f100dc2017-06-28 21:26:27 +02005034 else
5035 status = FAIL;
Bram Moolenaar8f77c5a2017-04-30 14:21:00 +02005036 }
5037 else
5038 status = dict_add_nr_str(retdict, "context", 0L, (char_u *)"");
5039 }
5040
Bram Moolenaara539f4f2017-08-30 20:33:55 +02005041 if ((status == OK) && (flags & QF_GETLIST_ID))
5042 status = dict_add_nr_str(retdict, "id", qi->qf_lists[qf_idx].qf_id,
5043 NULL);
5044
Bram Moolenaarfc2b2702017-09-15 22:43:07 +02005045 if ((status == OK) && (flags & QF_GETLIST_IDX))
5046 {
5047 int idx = qi->qf_lists[qf_idx].qf_index;
5048 if (qi->qf_lists[qf_idx].qf_count == 0)
5049 /* For empty lists, qf_index is set to 1 */
5050 idx = 0;
5051 status = dict_add_nr_str(retdict, "idx", idx, NULL);
5052 }
5053
5054 if ((status == OK) && (flags & QF_GETLIST_SIZE))
5055 status = dict_add_nr_str(retdict, "size",
5056 qi->qf_lists[qf_idx].qf_count, NULL);
5057
Bram Moolenaarb254af32017-12-18 19:48:58 +01005058 if ((status == OK) && (flags & QF_GETLIST_TICK))
5059 status = dict_add_nr_str(retdict, "changedtick",
5060 qi->qf_lists[qf_idx].qf_changedtick, NULL);
5061
Bram Moolenaard823fa92016-08-12 16:29:27 +02005062 return status;
5063}
5064
5065/*
5066 * Add list of entries to quickfix/location list. Each list entry is
5067 * a dictionary with item information.
5068 */
5069 static int
5070qf_add_entries(
5071 qf_info_T *qi,
Bram Moolenaara3921f42017-06-04 15:30:34 +02005072 int qf_idx,
Bram Moolenaard823fa92016-08-12 16:29:27 +02005073 list_T *list,
5074 char_u *title,
5075 int action)
Bram Moolenaar68b76a62005-03-25 21:53:48 +00005076{
5077 listitem_T *li;
5078 dict_T *d;
5079 char_u *filename, *pattern, *text, *type;
Bram Moolenaar48b66fb2007-02-04 01:58:18 +00005080 int bufnum;
Bram Moolenaar68b76a62005-03-25 21:53:48 +00005081 long lnum;
5082 int col, nr;
5083 int vcol;
Bram Moolenaar864293a2016-06-02 13:40:04 +02005084 qfline_T *old_last = NULL;
Bram Moolenaar68b76a62005-03-25 21:53:48 +00005085 int valid, status;
5086 int retval = OK;
Bram Moolenaar48b66fb2007-02-04 01:58:18 +00005087 int did_bufnr_emsg = FALSE;
Bram Moolenaar68b76a62005-03-25 21:53:48 +00005088
Bram Moolenaara3921f42017-06-04 15:30:34 +02005089 if (action == ' ' || qf_idx == qi->qf_listcount)
5090 {
Bram Moolenaar35c54e52005-05-20 21:25:31 +00005091 /* make place for a new list */
Bram Moolenaar94116152012-11-28 17:41:59 +01005092 qf_new_list(qi, title);
Bram Moolenaara3921f42017-06-04 15:30:34 +02005093 qf_idx = qi->qf_curlist;
5094 }
Bram Moolenaara3921f42017-06-04 15:30:34 +02005095 else if (action == 'a' && qi->qf_lists[qf_idx].qf_count > 0)
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02005096 /* Adding to existing list, use last entry. */
Bram Moolenaara3921f42017-06-04 15:30:34 +02005097 old_last = qi->qf_lists[qf_idx].qf_last;
Bram Moolenaar35c54e52005-05-20 21:25:31 +00005098 else if (action == 'r')
Bram Moolenaarfb604092014-07-23 15:55:00 +02005099 {
Bram Moolenaar6a8958d2017-06-22 21:33:20 +02005100 qf_free_items(qi, qf_idx);
Bram Moolenaara3921f42017-06-04 15:30:34 +02005101 qf_store_title(qi, qf_idx, title);
Bram Moolenaarfb604092014-07-23 15:55:00 +02005102 }
Bram Moolenaar68b76a62005-03-25 21:53:48 +00005103
5104 for (li = list->lv_first; li != NULL; li = li->li_next)
5105 {
5106 if (li->li_tv.v_type != VAR_DICT)
5107 continue; /* Skip non-dict items */
5108
5109 d = li->li_tv.vval.v_dict;
5110 if (d == NULL)
5111 continue;
5112
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00005113 filename = get_dict_string(d, (char_u *)"filename", TRUE);
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02005114 bufnum = (int)get_dict_number(d, (char_u *)"bufnr");
5115 lnum = (int)get_dict_number(d, (char_u *)"lnum");
5116 col = (int)get_dict_number(d, (char_u *)"col");
5117 vcol = (int)get_dict_number(d, (char_u *)"vcol");
5118 nr = (int)get_dict_number(d, (char_u *)"nr");
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00005119 type = get_dict_string(d, (char_u *)"type", TRUE);
5120 pattern = get_dict_string(d, (char_u *)"pattern", TRUE);
5121 text = get_dict_string(d, (char_u *)"text", TRUE);
Bram Moolenaar68b76a62005-03-25 21:53:48 +00005122 if (text == NULL)
5123 text = vim_strsave((char_u *)"");
5124
5125 valid = TRUE;
Bram Moolenaar48b66fb2007-02-04 01:58:18 +00005126 if ((filename == NULL && bufnum == 0) || (lnum == 0 && pattern == NULL))
Bram Moolenaar68b76a62005-03-25 21:53:48 +00005127 valid = FALSE;
5128
Bram Moolenaar48b66fb2007-02-04 01:58:18 +00005129 /* Mark entries with non-existing buffer number as not valid. Give the
5130 * error message only once. */
5131 if (bufnum != 0 && (buflist_findnr(bufnum) == NULL))
5132 {
5133 if (!did_bufnr_emsg)
5134 {
5135 did_bufnr_emsg = TRUE;
5136 EMSGN(_("E92: Buffer %ld not found"), bufnum);
5137 }
5138 valid = FALSE;
5139 bufnum = 0;
5140 }
5141
Bram Moolenaarf1d21c82017-04-22 21:20:46 +02005142 /* If the 'valid' field is present it overrules the detected value. */
5143 if ((dict_find(d, (char_u *)"valid", -1)) != NULL)
5144 valid = (int)get_dict_number(d, (char_u *)"valid");
5145
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02005146 status = qf_add_entry(qi,
Bram Moolenaara3921f42017-06-04 15:30:34 +02005147 qf_idx,
Bram Moolenaar68b76a62005-03-25 21:53:48 +00005148 NULL, /* dir */
5149 filename,
Bram Moolenaar48b66fb2007-02-04 01:58:18 +00005150 bufnum,
Bram Moolenaar68b76a62005-03-25 21:53:48 +00005151 text,
5152 lnum,
5153 col,
5154 vcol, /* vis_col */
5155 pattern, /* search pattern */
5156 nr,
5157 type == NULL ? NUL : *type,
5158 valid);
5159
5160 vim_free(filename);
5161 vim_free(pattern);
5162 vim_free(text);
5163 vim_free(type);
5164
5165 if (status == FAIL)
5166 {
5167 retval = FAIL;
5168 break;
5169 }
5170 }
5171
Bram Moolenaara3921f42017-06-04 15:30:34 +02005172 if (qi->qf_lists[qf_idx].qf_index == 0)
Bram Moolenaard236ac02011-05-05 17:14:14 +02005173 /* no valid entry */
Bram Moolenaara3921f42017-06-04 15:30:34 +02005174 qi->qf_lists[qf_idx].qf_nonevalid = TRUE;
Bram Moolenaarf9ddb942010-05-14 18:10:27 +02005175 else
Bram Moolenaara3921f42017-06-04 15:30:34 +02005176 qi->qf_lists[qf_idx].qf_nonevalid = FALSE;
Bram Moolenaarb6fa30c2017-03-29 14:19:25 +02005177 if (action != 'a')
5178 {
Bram Moolenaara3921f42017-06-04 15:30:34 +02005179 qi->qf_lists[qf_idx].qf_ptr =
5180 qi->qf_lists[qf_idx].qf_start;
5181 if (qi->qf_lists[qf_idx].qf_count > 0)
5182 qi->qf_lists[qf_idx].qf_index = 1;
Bram Moolenaarc1808d52016-04-18 20:04:00 +02005183 }
Bram Moolenaar68b76a62005-03-25 21:53:48 +00005184
Bram Moolenaarc1808d52016-04-18 20:04:00 +02005185 /* Don't update the cursor in quickfix window when appending entries */
Bram Moolenaar864293a2016-06-02 13:40:04 +02005186 qf_update_buffer(qi, old_last);
Bram Moolenaar68b76a62005-03-25 21:53:48 +00005187
5188 return retval;
5189}
Bram Moolenaard823fa92016-08-12 16:29:27 +02005190
5191 static int
Bram Moolenaarae338332017-08-11 20:25:26 +02005192qf_set_properties(qf_info_T *qi, dict_T *what, int action, char_u *title)
Bram Moolenaard823fa92016-08-12 16:29:27 +02005193{
5194 dictitem_T *di;
5195 int retval = FAIL;
5196 int qf_idx;
Bram Moolenaar2b529bb2016-08-27 13:35:35 +02005197 int newlist = FALSE;
Bram Moolenaar36538222017-09-02 19:51:44 +02005198 char_u *errorformat = p_efm;
Bram Moolenaar2b529bb2016-08-27 13:35:35 +02005199
5200 if (action == ' ' || qi->qf_curlist == qi->qf_listcount)
5201 newlist = TRUE;
Bram Moolenaard823fa92016-08-12 16:29:27 +02005202
5203 qf_idx = qi->qf_curlist; /* default is the current list */
5204 if ((di = dict_find(what, (char_u *)"nr", -1)) != NULL)
5205 {
5206 /* Use the specified quickfix/location list */
5207 if (di->di_tv.v_type == VAR_NUMBER)
5208 {
Bram Moolenaar6e62da32017-05-28 08:16:25 +02005209 /* for zero use the current list */
5210 if (di->di_tv.vval.v_number != 0)
5211 qf_idx = di->di_tv.vval.v_number - 1;
Bram Moolenaar6a8958d2017-06-22 21:33:20 +02005212
Bram Moolenaar55b69262017-08-13 13:42:01 +02005213 if ((action == ' ' || action == 'a') && qf_idx == qi->qf_listcount)
5214 {
Bram Moolenaar6a8958d2017-06-22 21:33:20 +02005215 /*
5216 * When creating a new list, accept qf_idx pointing to the next
Bram Moolenaar55b69262017-08-13 13:42:01 +02005217 * non-available list and add the new list at the end of the
5218 * stack.
Bram Moolenaar6a8958d2017-06-22 21:33:20 +02005219 */
5220 newlist = TRUE;
Bram Moolenaar55b69262017-08-13 13:42:01 +02005221 qf_idx = qi->qf_listcount - 1;
5222 }
Bram Moolenaar6a8958d2017-06-22 21:33:20 +02005223 else if (qf_idx < 0 || qf_idx >= qi->qf_listcount)
Bram Moolenaard823fa92016-08-12 16:29:27 +02005224 return FAIL;
Bram Moolenaar55b69262017-08-13 13:42:01 +02005225 else if (action != ' ')
Bram Moolenaar6a8958d2017-06-22 21:33:20 +02005226 newlist = FALSE; /* use the specified list */
Bram Moolenaar55b69262017-08-13 13:42:01 +02005227 }
5228 else if (di->di_tv.v_type == VAR_STRING
5229 && STRCMP(di->di_tv.vval.v_string, "$") == 0)
Bram Moolenaar6a8958d2017-06-22 21:33:20 +02005230 {
Bram Moolenaar55b69262017-08-13 13:42:01 +02005231 if (qi->qf_listcount > 0)
5232 qf_idx = qi->qf_listcount - 1;
5233 else if (newlist)
5234 qf_idx = 0;
5235 else
5236 return FAIL;
Bram Moolenaar6a8958d2017-06-22 21:33:20 +02005237 }
Bram Moolenaard823fa92016-08-12 16:29:27 +02005238 else
5239 return FAIL;
Bram Moolenaar2b529bb2016-08-27 13:35:35 +02005240 }
5241
Bram Moolenaara539f4f2017-08-30 20:33:55 +02005242 if (!newlist && (di = dict_find(what, (char_u *)"id", -1)) != NULL)
5243 {
5244 /* Use the quickfix/location list with the specified id */
5245 if (di->di_tv.v_type == VAR_NUMBER)
5246 {
Bram Moolenaarb4d5fba2017-09-11 19:31:28 +02005247 qf_idx = qf_id2nr(qi, di->di_tv.vval.v_number);
5248 if (qf_idx == -1)
Bram Moolenaara539f4f2017-08-30 20:33:55 +02005249 return FAIL; /* List not found */
5250 }
5251 else
5252 return FAIL;
5253 }
5254
Bram Moolenaar2b529bb2016-08-27 13:35:35 +02005255 if (newlist)
5256 {
Bram Moolenaar55b69262017-08-13 13:42:01 +02005257 qi->qf_curlist = qf_idx;
Bram Moolenaarae338332017-08-11 20:25:26 +02005258 qf_new_list(qi, title);
Bram Moolenaar2b529bb2016-08-27 13:35:35 +02005259 qf_idx = qi->qf_curlist;
Bram Moolenaard823fa92016-08-12 16:29:27 +02005260 }
5261
5262 if ((di = dict_find(what, (char_u *)"title", -1)) != NULL)
5263 {
5264 if (di->di_tv.v_type == VAR_STRING)
5265 {
5266 vim_free(qi->qf_lists[qf_idx].qf_title);
5267 qi->qf_lists[qf_idx].qf_title =
5268 get_dict_string(what, (char_u *)"title", TRUE);
5269 if (qf_idx == qi->qf_curlist)
5270 qf_update_win_titlevar(qi);
5271 retval = OK;
5272 }
5273 }
Bram Moolenaar36538222017-09-02 19:51:44 +02005274
Bram Moolenaar6a8958d2017-06-22 21:33:20 +02005275 if ((di = dict_find(what, (char_u *)"items", -1)) != NULL)
5276 {
5277 if (di->di_tv.v_type == VAR_LIST)
5278 {
5279 char_u *title_save = vim_strsave(qi->qf_lists[qf_idx].qf_title);
5280
5281 retval = qf_add_entries(qi, qf_idx, di->di_tv.vval.v_list,
5282 title_save, action == ' ' ? 'a' : action);
Bram Moolenaarb4d5fba2017-09-11 19:31:28 +02005283 if (action == 'r')
5284 {
5285 /*
5286 * When replacing the quickfix list entries using
5287 * qf_add_entries(), the title is set with a ':' prefix.
5288 * Restore the title with the saved title.
5289 */
5290 vim_free(qi->qf_lists[qf_idx].qf_title);
5291 qi->qf_lists[qf_idx].qf_title = vim_strsave(title_save);
5292 }
Bram Moolenaar6a8958d2017-06-22 21:33:20 +02005293 vim_free(title_save);
5294 }
5295 }
Bram Moolenaard823fa92016-08-12 16:29:27 +02005296
Bram Moolenaar36538222017-09-02 19:51:44 +02005297 if ((di = dict_find(what, (char_u *)"efm", -1)) != NULL)
5298 {
5299 if (di->di_tv.v_type != VAR_STRING || di->di_tv.vval.v_string == NULL)
5300 return FAIL;
5301 errorformat = di->di_tv.vval.v_string;
5302 }
5303
Bram Moolenaar2c809b72017-09-01 18:34:02 +02005304 if ((di = dict_find(what, (char_u *)"lines", -1)) != NULL)
Bram Moolenaarae338332017-08-11 20:25:26 +02005305 {
Bram Moolenaar2c809b72017-09-01 18:34:02 +02005306 /* Only a List value is supported */
5307 if (di->di_tv.v_type == VAR_LIST && di->di_tv.vval.v_list != NULL)
Bram Moolenaarae338332017-08-11 20:25:26 +02005308 {
5309 if (action == 'r')
5310 qf_free_items(qi, qf_idx);
Bram Moolenaar36538222017-09-02 19:51:44 +02005311 if (qf_init_ext(qi, qf_idx, NULL, NULL, &di->di_tv, errorformat,
Bram Moolenaarae338332017-08-11 20:25:26 +02005312 FALSE, (linenr_T)0, (linenr_T)0, NULL, NULL) > 0)
5313 retval = OK;
5314 }
5315 else
5316 return FAIL;
5317 }
5318
Bram Moolenaar8f77c5a2017-04-30 14:21:00 +02005319 if ((di = dict_find(what, (char_u *)"context", -1)) != NULL)
5320 {
5321 typval_T *ctx;
Bram Moolenaar875feea2017-06-11 16:07:51 +02005322
Bram Moolenaar6e62da32017-05-28 08:16:25 +02005323 free_tv(qi->qf_lists[qf_idx].qf_ctx);
Bram Moolenaar8f77c5a2017-04-30 14:21:00 +02005324 ctx = alloc_tv();
5325 if (ctx != NULL)
5326 copy_tv(&di->di_tv, ctx);
Bram Moolenaar6e62da32017-05-28 08:16:25 +02005327 qi->qf_lists[qf_idx].qf_ctx = ctx;
Bram Moolenaar86f100dc2017-06-28 21:26:27 +02005328 retval = OK;
Bram Moolenaar8f77c5a2017-04-30 14:21:00 +02005329 }
5330
Bram Moolenaarb254af32017-12-18 19:48:58 +01005331 if (retval == OK)
5332 qf_list_changed(qi, qf_idx);
5333
Bram Moolenaard823fa92016-08-12 16:29:27 +02005334 return retval;
5335}
5336
Bram Moolenaar69f40be2017-04-02 15:15:49 +02005337/*
5338 * Find the non-location list window with the specified location list.
5339 */
5340 static win_T *
5341find_win_with_ll(qf_info_T *qi)
5342{
5343 win_T *wp = NULL;
5344
5345 FOR_ALL_WINDOWS(wp)
5346 if ((wp->w_llist == qi) && !bt_quickfix(wp->w_buffer))
5347 return wp;
5348
5349 return NULL;
5350}
5351
5352/*
5353 * Free the entire quickfix/location list stack.
5354 * If the quickfix/location list window is open, then clear it.
5355 */
Bram Moolenaarb6fa30c2017-03-29 14:19:25 +02005356 static void
5357qf_free_stack(win_T *wp, qf_info_T *qi)
5358{
Bram Moolenaar69f40be2017-04-02 15:15:49 +02005359 win_T *qfwin = qf_find_win(qi);
5360 win_T *llwin = NULL;
5361 win_T *orig_wp = wp;
5362
5363 if (qfwin != NULL)
5364 {
5365 /* If the quickfix/location list window is open, then clear it */
5366 if (qi->qf_curlist < qi->qf_listcount)
5367 qf_free(qi, qi->qf_curlist);
5368 qf_update_buffer(qi, NULL);
5369 }
5370
5371 if (wp != NULL && IS_LL_WINDOW(wp))
5372 {
5373 /* If in the location list window, then use the non-location list
5374 * window with this location list (if present)
5375 */
5376 llwin = find_win_with_ll(qi);
5377 if (llwin != NULL)
5378 wp = llwin;
5379 }
5380
Bram Moolenaarb6fa30c2017-03-29 14:19:25 +02005381 qf_free_all(wp);
5382 if (wp == NULL)
5383 {
5384 /* quickfix list */
5385 qi->qf_curlist = 0;
5386 qi->qf_listcount = 0;
5387 }
Bram Moolenaar69f40be2017-04-02 15:15:49 +02005388 else if (IS_LL_WINDOW(orig_wp))
5389 {
5390 /* If the location list window is open, then create a new empty
5391 * location list */
5392 qf_info_T *new_ll = ll_new_list();
Bram Moolenaar99895ea2017-04-20 22:44:47 +02005393
Bram Moolenaard788f6f2017-04-23 17:19:43 +02005394 /* first free the list reference in the location list window */
5395 ll_free_all(&orig_wp->w_llist_ref);
5396
Bram Moolenaar69f40be2017-04-02 15:15:49 +02005397 orig_wp->w_llist_ref = new_ll;
5398 if (llwin != NULL)
5399 {
5400 llwin->w_llist = new_ll;
5401 new_ll->qf_refcount++;
5402 }
5403 }
Bram Moolenaarb6fa30c2017-03-29 14:19:25 +02005404}
5405
Bram Moolenaard823fa92016-08-12 16:29:27 +02005406/*
5407 * Populate the quickfix list with the items supplied in the list
5408 * of dictionaries. "title" will be copied to w:quickfix_title.
5409 * "action" is 'a' for add, 'r' for replace. Otherwise create a new list.
5410 */
5411 int
5412set_errorlist(
5413 win_T *wp,
5414 list_T *list,
5415 int action,
5416 char_u *title,
5417 dict_T *what)
5418{
5419 qf_info_T *qi = &ql_info;
5420 int retval = OK;
5421
5422 if (wp != NULL)
5423 {
5424 qi = ll_get_or_alloc_list(wp);
5425 if (qi == NULL)
5426 return FAIL;
5427 }
5428
Bram Moolenaarb6fa30c2017-03-29 14:19:25 +02005429 if (action == 'f')
5430 {
5431 /* Free the entire quickfix or location list stack */
5432 qf_free_stack(wp, qi);
5433 }
5434 else if (what != NULL)
Bram Moolenaarae338332017-08-11 20:25:26 +02005435 retval = qf_set_properties(qi, what, action, title);
Bram Moolenaard823fa92016-08-12 16:29:27 +02005436 else
Bram Moolenaarb254af32017-12-18 19:48:58 +01005437 {
Bram Moolenaara3921f42017-06-04 15:30:34 +02005438 retval = qf_add_entries(qi, qi->qf_curlist, list, title, action);
Bram Moolenaarb254af32017-12-18 19:48:58 +01005439 if (retval == OK)
5440 qf_list_changed(qi, qi->qf_curlist);
5441 }
Bram Moolenaard823fa92016-08-12 16:29:27 +02005442
5443 return retval;
5444}
Bram Moolenaar8f77c5a2017-04-30 14:21:00 +02005445
5446 static int
5447mark_quickfix_ctx(qf_info_T *qi, int copyID)
5448{
5449 int i;
5450 int abort = FALSE;
5451 typval_T *ctx;
5452
5453 for (i = 0; i < LISTCOUNT && !abort; ++i)
5454 {
5455 ctx = qi->qf_lists[i].qf_ctx;
Bram Moolenaar55b69262017-08-13 13:42:01 +02005456 if (ctx != NULL && ctx->v_type != VAR_NUMBER
5457 && ctx->v_type != VAR_STRING && ctx->v_type != VAR_FLOAT)
Bram Moolenaar8f77c5a2017-04-30 14:21:00 +02005458 abort = set_ref_in_item(ctx, copyID, NULL, NULL);
5459 }
5460
5461 return abort;
5462}
5463
5464/*
5465 * Mark the context of the quickfix list and the location lists (if present) as
5466 * "in use". So that garabage collection doesn't free the context.
5467 */
5468 int
5469set_ref_in_quickfix(int copyID)
5470{
5471 int abort = FALSE;
5472 tabpage_T *tp;
5473 win_T *win;
5474
5475 abort = mark_quickfix_ctx(&ql_info, copyID);
5476 if (abort)
5477 return abort;
5478
5479 FOR_ALL_TAB_WINDOWS(tp, win)
5480 {
5481 if (win->w_llist != NULL)
5482 {
5483 abort = mark_quickfix_ctx(win->w_llist, copyID);
5484 if (abort)
5485 return abort;
5486 }
5487 }
5488
5489 return abort;
5490}
Bram Moolenaar05159a02005-02-26 23:04:13 +00005491#endif
5492
Bram Moolenaar81695252004-12-29 20:58:21 +00005493/*
Bram Moolenaar86b68352004-12-27 21:59:20 +00005494 * ":[range]cbuffer [bufnr]" command.
Bram Moolenaara6557602006-02-04 22:43:20 +00005495 * ":[range]caddbuffer [bufnr]" command.
Bram Moolenaardb552d602006-03-23 22:59:57 +00005496 * ":[range]cgetbuffer [bufnr]" command.
Bram Moolenaard12f5c12006-01-25 22:10:52 +00005497 * ":[range]lbuffer [bufnr]" command.
Bram Moolenaara6557602006-02-04 22:43:20 +00005498 * ":[range]laddbuffer [bufnr]" command.
Bram Moolenaardb552d602006-03-23 22:59:57 +00005499 * ":[range]lgetbuffer [bufnr]" command.
Bram Moolenaar86b68352004-12-27 21:59:20 +00005500 */
5501 void
Bram Moolenaar05540972016-01-30 20:31:25 +01005502ex_cbuffer(exarg_T *eap)
Bram Moolenaar86b68352004-12-27 21:59:20 +00005503{
5504 buf_T *buf = NULL;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00005505 qf_info_T *qi = &ql_info;
Bram Moolenaar04c4ce62016-09-01 15:45:58 +02005506#ifdef FEAT_AUTOCMD
5507 char_u *au_name = NULL;
5508#endif
Bram Moolenaar1ed22762017-11-28 18:03:44 +01005509 int res;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00005510
Bram Moolenaardb552d602006-03-23 22:59:57 +00005511 if (eap->cmdidx == CMD_lbuffer || eap->cmdidx == CMD_lgetbuffer
5512 || eap->cmdidx == CMD_laddbuffer)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00005513 {
5514 qi = ll_get_or_alloc_list(curwin);
5515 if (qi == NULL)
5516 return;
5517 }
Bram Moolenaar86b68352004-12-27 21:59:20 +00005518
Bram Moolenaar04c4ce62016-09-01 15:45:58 +02005519#ifdef FEAT_AUTOCMD
5520 switch (eap->cmdidx)
5521 {
5522 case CMD_cbuffer: au_name = (char_u *)"cbuffer"; break;
5523 case CMD_cgetbuffer: au_name = (char_u *)"cgetbuffer"; break;
5524 case CMD_caddbuffer: au_name = (char_u *)"caddbuffer"; break;
5525 case CMD_lbuffer: au_name = (char_u *)"lbuffer"; break;
5526 case CMD_lgetbuffer: au_name = (char_u *)"lgetbuffer"; break;
5527 case CMD_laddbuffer: au_name = (char_u *)"laddbuffer"; break;
5528 default: break;
5529 }
Bram Moolenaar21662be2016-11-06 14:46:44 +01005530 if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
5531 curbuf->b_fname, TRUE, curbuf))
Bram Moolenaar04c4ce62016-09-01 15:45:58 +02005532 {
Bram Moolenaar04c4ce62016-09-01 15:45:58 +02005533# ifdef FEAT_EVAL
Bram Moolenaar21662be2016-11-06 14:46:44 +01005534 if (aborting())
Bram Moolenaar04c4ce62016-09-01 15:45:58 +02005535 return;
5536# endif
5537 }
5538#endif
5539
Bram Moolenaar86b68352004-12-27 21:59:20 +00005540 if (*eap->arg == NUL)
5541 buf = curbuf;
5542 else if (*skipwhite(skipdigits(eap->arg)) == NUL)
5543 buf = buflist_findnr(atoi((char *)eap->arg));
5544 if (buf == NULL)
5545 EMSG(_(e_invarg));
5546 else if (buf->b_ml.ml_mfp == NULL)
5547 EMSG(_("E681: Buffer is not loaded"));
5548 else
5549 {
5550 if (eap->addr_count == 0)
5551 {
5552 eap->line1 = 1;
5553 eap->line2 = buf->b_ml.ml_line_count;
5554 }
5555 if (eap->line1 < 1 || eap->line1 > buf->b_ml.ml_line_count
5556 || eap->line2 < 1 || eap->line2 > buf->b_ml.ml_line_count)
5557 EMSG(_(e_invrange));
5558 else
Bram Moolenaar754b5602006-02-09 23:53:20 +00005559 {
Bram Moolenaar7fd73202010-07-25 16:58:46 +02005560 char_u *qf_title = *eap->cmdlinep;
5561
5562 if (buf->b_sfname)
5563 {
5564 vim_snprintf((char *)IObuff, IOSIZE, "%s (%s)",
5565 (char *)qf_title, (char *)buf->b_sfname);
5566 qf_title = IObuff;
5567 }
5568
Bram Moolenaar1ed22762017-11-28 18:03:44 +01005569 res = qf_init_ext(qi, qi->qf_curlist, NULL, buf, NULL, p_efm,
Bram Moolenaardb552d602006-03-23 22:59:57 +00005570 (eap->cmdidx != CMD_caddbuffer
5571 && eap->cmdidx != CMD_laddbuffer),
Bram Moolenaar7fd73202010-07-25 16:58:46 +02005572 eap->line1, eap->line2,
Bram Moolenaar1ed22762017-11-28 18:03:44 +01005573 qf_title, NULL);
Bram Moolenaarb254af32017-12-18 19:48:58 +01005574 if (res >= 0)
5575 qf_list_changed(qi, qi->qf_curlist);
Bram Moolenaar04c4ce62016-09-01 15:45:58 +02005576#ifdef FEAT_AUTOCMD
Bram Moolenaar1ed22762017-11-28 18:03:44 +01005577 if (au_name != NULL)
5578 apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name,
5579 curbuf->b_fname, TRUE, curbuf);
Bram Moolenaar04c4ce62016-09-01 15:45:58 +02005580#endif
Bram Moolenaar1ed22762017-11-28 18:03:44 +01005581 if (res > 0 && (eap->cmdidx == CMD_cbuffer ||
5582 eap->cmdidx == CMD_lbuffer))
5583 qf_jump(qi, 0, 0, eap->forceit); /* display first error */
Bram Moolenaar754b5602006-02-09 23:53:20 +00005584 }
Bram Moolenaar86b68352004-12-27 21:59:20 +00005585 }
5586}
5587
Bram Moolenaar1e015462005-09-25 22:16:38 +00005588#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar86b68352004-12-27 21:59:20 +00005589/*
Bram Moolenaardb552d602006-03-23 22:59:57 +00005590 * ":cexpr {expr}", ":cgetexpr {expr}", ":caddexpr {expr}" command.
5591 * ":lexpr {expr}", ":lgetexpr {expr}", ":laddexpr {expr}" command.
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00005592 */
5593 void
Bram Moolenaar05540972016-01-30 20:31:25 +01005594ex_cexpr(exarg_T *eap)
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00005595{
5596 typval_T *tv;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00005597 qf_info_T *qi = &ql_info;
Bram Moolenaar04c4ce62016-09-01 15:45:58 +02005598#ifdef FEAT_AUTOCMD
5599 char_u *au_name = NULL;
5600#endif
Bram Moolenaar1ed22762017-11-28 18:03:44 +01005601 int res;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00005602
Bram Moolenaardb552d602006-03-23 22:59:57 +00005603 if (eap->cmdidx == CMD_lexpr || eap->cmdidx == CMD_lgetexpr
5604 || eap->cmdidx == CMD_laddexpr)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00005605 {
5606 qi = ll_get_or_alloc_list(curwin);
5607 if (qi == NULL)
5608 return;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00005609 }
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00005610
Bram Moolenaar04c4ce62016-09-01 15:45:58 +02005611#ifdef FEAT_AUTOCMD
5612 switch (eap->cmdidx)
5613 {
5614 case CMD_cexpr: au_name = (char_u *)"cexpr"; break;
5615 case CMD_cgetexpr: au_name = (char_u *)"cgetexpr"; break;
5616 case CMD_caddexpr: au_name = (char_u *)"caddexpr"; break;
5617 case CMD_lexpr: au_name = (char_u *)"lexpr"; break;
5618 case CMD_lgetexpr: au_name = (char_u *)"lgetexpr"; break;
5619 case CMD_laddexpr: au_name = (char_u *)"laddexpr"; break;
5620 default: break;
5621 }
Bram Moolenaar21662be2016-11-06 14:46:44 +01005622 if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
5623 curbuf->b_fname, TRUE, curbuf))
Bram Moolenaar04c4ce62016-09-01 15:45:58 +02005624 {
Bram Moolenaar04c4ce62016-09-01 15:45:58 +02005625# ifdef FEAT_EVAL
Bram Moolenaar21662be2016-11-06 14:46:44 +01005626 if (aborting())
Bram Moolenaar04c4ce62016-09-01 15:45:58 +02005627 return;
5628# endif
5629 }
5630#endif
5631
Bram Moolenaar4770d092006-01-12 23:22:24 +00005632 /* Evaluate the expression. When the result is a string or a list we can
5633 * use it to fill the errorlist. */
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00005634 tv = eval_expr(eap->arg, NULL);
Bram Moolenaar4770d092006-01-12 23:22:24 +00005635 if (tv != NULL)
5636 {
5637 if ((tv->v_type == VAR_STRING && tv->vval.v_string != NULL)
5638 || (tv->v_type == VAR_LIST && tv->vval.v_list != NULL))
5639 {
Bram Moolenaar1ed22762017-11-28 18:03:44 +01005640 res = qf_init_ext(qi, qi->qf_curlist, NULL, NULL, tv, p_efm,
Bram Moolenaardb552d602006-03-23 22:59:57 +00005641 (eap->cmdidx != CMD_caddexpr
5642 && eap->cmdidx != CMD_laddexpr),
Bram Moolenaar2c7292d2017-03-05 17:43:31 +01005643 (linenr_T)0, (linenr_T)0, *eap->cmdlinep,
Bram Moolenaar1ed22762017-11-28 18:03:44 +01005644 NULL);
Bram Moolenaarb254af32017-12-18 19:48:58 +01005645 if (res >= 0)
5646 qf_list_changed(qi, qi->qf_curlist);
Bram Moolenaar04c4ce62016-09-01 15:45:58 +02005647#ifdef FEAT_AUTOCMD
Bram Moolenaar1ed22762017-11-28 18:03:44 +01005648 if (au_name != NULL)
5649 apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name,
5650 curbuf->b_fname, TRUE, curbuf);
Bram Moolenaar04c4ce62016-09-01 15:45:58 +02005651#endif
Bram Moolenaar1ed22762017-11-28 18:03:44 +01005652 if (res > 0 && (eap->cmdidx == CMD_cexpr ||
5653 eap->cmdidx == CMD_lexpr))
5654 qf_jump(qi, 0, 0, eap->forceit); /* display first error */
Bram Moolenaar4770d092006-01-12 23:22:24 +00005655 }
5656 else
Bram Moolenaara40ceaf2006-01-13 22:35:40 +00005657 EMSG(_("E777: String or List expected"));
Bram Moolenaar4770d092006-01-12 23:22:24 +00005658 free_tv(tv);
5659 }
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00005660}
Bram Moolenaar1e015462005-09-25 22:16:38 +00005661#endif
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00005662
5663/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005664 * ":helpgrep {pattern}"
5665 */
5666 void
Bram Moolenaar05540972016-01-30 20:31:25 +01005667ex_helpgrep(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005668{
5669 regmatch_T regmatch;
5670 char_u *save_cpo;
5671 char_u *p;
5672 int fcount;
5673 char_u **fnames;
5674 FILE *fd;
5675 int fi;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005676 long lnum;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005677#ifdef FEAT_MULTI_LANG
5678 char_u *lang;
5679#endif
Bram Moolenaard12f5c12006-01-25 22:10:52 +00005680 qf_info_T *qi = &ql_info;
Bram Moolenaaree85df32017-03-19 14:19:50 +01005681 qf_info_T *save_qi;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00005682 int new_qi = FALSE;
5683 win_T *wp;
Bram Moolenaar73633f82012-01-20 13:39:07 +01005684#ifdef FEAT_AUTOCMD
5685 char_u *au_name = NULL;
5686#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005687
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005688#ifdef FEAT_MULTI_LANG
5689 /* Check for a specified language */
5690 lang = check_help_lang(eap->arg);
5691#endif
5692
Bram Moolenaar73633f82012-01-20 13:39:07 +01005693#ifdef FEAT_AUTOCMD
5694 switch (eap->cmdidx)
5695 {
5696 case CMD_helpgrep: au_name = (char_u *)"helpgrep"; break;
5697 case CMD_lhelpgrep: au_name = (char_u *)"lhelpgrep"; break;
5698 default: break;
5699 }
Bram Moolenaar21662be2016-11-06 14:46:44 +01005700 if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
5701 curbuf->b_fname, TRUE, curbuf))
Bram Moolenaar73633f82012-01-20 13:39:07 +01005702 {
Bram Moolenaar21662be2016-11-06 14:46:44 +01005703# ifdef FEAT_EVAL
5704 if (aborting())
Bram Moolenaar73633f82012-01-20 13:39:07 +01005705 return;
Bram Moolenaar21662be2016-11-06 14:46:44 +01005706# endif
Bram Moolenaar73633f82012-01-20 13:39:07 +01005707 }
5708#endif
5709
5710 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
5711 save_cpo = p_cpo;
5712 p_cpo = empty_option;
5713
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00005714 if (eap->cmdidx == CMD_lhelpgrep)
5715 {
Bram Moolenaard28cc3f2017-07-27 22:03:50 +02005716 /* If the current window is a help window, then use it */
5717 if (bt_help(curwin->w_buffer))
5718 wp = curwin;
5719 else
5720 /* Find an existing help window */
5721 FOR_ALL_WINDOWS(wp)
5722 if (bt_help(wp->w_buffer))
5723 break;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00005724
5725 if (wp == NULL) /* Help window not found */
5726 qi = NULL;
5727 else
5728 qi = wp->w_llist;
5729
5730 if (qi == NULL)
5731 {
5732 /* Allocate a new location list for help text matches */
5733 if ((qi = ll_new_list()) == NULL)
5734 return;
5735 new_qi = TRUE;
5736 }
5737 }
5738
Bram Moolenaaree85df32017-03-19 14:19:50 +01005739 /* Autocommands may change the list. Save it for later comparison */
5740 save_qi = qi;
5741
Bram Moolenaar071d4272004-06-13 20:20:40 +00005742 regmatch.regprog = vim_regcomp(eap->arg, RE_MAGIC + RE_STRING);
5743 regmatch.rm_ic = FALSE;
5744 if (regmatch.regprog != NULL)
5745 {
Bram Moolenaar10b7b392012-01-10 16:28:45 +01005746#ifdef FEAT_MBYTE
5747 vimconv_T vc;
5748
5749 /* Help files are in utf-8 or latin1, convert lines when 'encoding'
5750 * differs. */
5751 vc.vc_type = CONV_NONE;
5752 if (!enc_utf8)
5753 convert_setup(&vc, (char_u *)"utf-8", p_enc);
5754#endif
5755
Bram Moolenaar071d4272004-06-13 20:20:40 +00005756 /* create a new quickfix list */
Bram Moolenaar94116152012-11-28 17:41:59 +01005757 qf_new_list(qi, *eap->cmdlinep);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005758
5759 /* Go through all directories in 'runtimepath' */
5760 p = p_rtp;
5761 while (*p != NUL && !got_int)
5762 {
5763 copy_option_part(&p, NameBuff, MAXPATHL, ",");
5764
5765 /* Find all "*.txt" and "*.??x" files in the "doc" directory. */
5766 add_pathsep(NameBuff);
5767 STRCAT(NameBuff, "doc/*.\\(txt\\|??x\\)");
5768 if (gen_expand_wildcards(1, &NameBuff, &fcount,
5769 &fnames, EW_FILE|EW_SILENT) == OK
5770 && fcount > 0)
5771 {
5772 for (fi = 0; fi < fcount && !got_int; ++fi)
5773 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005774#ifdef FEAT_MULTI_LANG
5775 /* Skip files for a different language. */
5776 if (lang != NULL
5777 && STRNICMP(lang, fnames[fi]
5778 + STRLEN(fnames[fi]) - 3, 2) != 0
5779 && !(STRNICMP(lang, "en", 2) == 0
5780 && STRNICMP("txt", fnames[fi]
5781 + STRLEN(fnames[fi]) - 3, 3) == 0))
5782 continue;
5783#endif
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +00005784 fd = mch_fopen((char *)fnames[fi], "r");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005785 if (fd != NULL)
5786 {
5787 lnum = 1;
5788 while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int)
5789 {
Bram Moolenaar10b7b392012-01-10 16:28:45 +01005790 char_u *line = IObuff;
5791#ifdef FEAT_MBYTE
5792 /* Convert a line if 'encoding' is not utf-8 and
5793 * the line contains a non-ASCII character. */
5794 if (vc.vc_type != CONV_NONE
Bram Moolenaarb6fa30c2017-03-29 14:19:25 +02005795 && has_non_ascii(IObuff))
5796 {
Bram Moolenaar10b7b392012-01-10 16:28:45 +01005797 line = string_convert(&vc, IObuff, NULL);
5798 if (line == NULL)
5799 line = IObuff;
5800 }
5801#endif
5802
5803 if (vim_regexec(&regmatch, line, (colnr_T)0))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005804 {
Bram Moolenaar10b7b392012-01-10 16:28:45 +01005805 int l = (int)STRLEN(line);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005806
5807 /* remove trailing CR, LF, spaces, etc. */
Bram Moolenaar10b7b392012-01-10 16:28:45 +01005808 while (l > 0 && line[l - 1] <= ' ')
5809 line[--l] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005810
Bram Moolenaar83e6d7a2016-06-02 22:08:05 +02005811 if (qf_add_entry(qi,
Bram Moolenaara3921f42017-06-04 15:30:34 +02005812 qi->qf_curlist,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005813 NULL, /* dir */
5814 fnames[fi],
Bram Moolenaar48b66fb2007-02-04 01:58:18 +00005815 0,
Bram Moolenaar10b7b392012-01-10 16:28:45 +01005816 line,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005817 lnum,
Bram Moolenaar10b7b392012-01-10 16:28:45 +01005818 (int)(regmatch.startp[0] - line)
Bram Moolenaar81695252004-12-29 20:58:21 +00005819 + 1, /* col */
Bram Moolenaar05159a02005-02-26 23:04:13 +00005820 FALSE, /* vis_col */
Bram Moolenaar68b76a62005-03-25 21:53:48 +00005821 NULL, /* search pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005822 0, /* nr */
5823 1, /* type */
5824 TRUE /* valid */
5825 ) == FAIL)
5826 {
5827 got_int = TRUE;
Bram Moolenaar10b7b392012-01-10 16:28:45 +01005828#ifdef FEAT_MBYTE
5829 if (line != IObuff)
5830 vim_free(line);
5831#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005832 break;
5833 }
5834 }
Bram Moolenaar10b7b392012-01-10 16:28:45 +01005835#ifdef FEAT_MBYTE
5836 if (line != IObuff)
5837 vim_free(line);
5838#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005839 ++lnum;
5840 line_breakcheck();
5841 }
5842 fclose(fd);
5843 }
5844 }
5845 FreeWild(fcount, fnames);
5846 }
5847 }
Bram Moolenaar10b7b392012-01-10 16:28:45 +01005848
Bram Moolenaar473de612013-06-08 18:19:48 +02005849 vim_regfree(regmatch.regprog);
Bram Moolenaar10b7b392012-01-10 16:28:45 +01005850#ifdef FEAT_MBYTE
5851 if (vc.vc_type != CONV_NONE)
5852 convert_setup(&vc, NULL, NULL);
5853#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005854
Bram Moolenaard12f5c12006-01-25 22:10:52 +00005855 qi->qf_lists[qi->qf_curlist].qf_nonevalid = FALSE;
5856 qi->qf_lists[qi->qf_curlist].qf_ptr =
5857 qi->qf_lists[qi->qf_curlist].qf_start;
5858 qi->qf_lists[qi->qf_curlist].qf_index = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005859 }
5860
Bram Moolenaar9c24ccc2008-07-14 21:05:15 +00005861 if (p_cpo == empty_option)
5862 p_cpo = save_cpo;
5863 else
5864 /* Darn, some plugin changed the value. */
5865 free_string_option(save_cpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005866
Bram Moolenaarb254af32017-12-18 19:48:58 +01005867 qf_list_changed(qi, qi->qf_curlist);
Bram Moolenaar864293a2016-06-02 13:40:04 +02005868 qf_update_buffer(qi, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005869
Bram Moolenaar73633f82012-01-20 13:39:07 +01005870#ifdef FEAT_AUTOCMD
5871 if (au_name != NULL)
5872 {
5873 apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name,
5874 curbuf->b_fname, TRUE, curbuf);
Bram Moolenaaree85df32017-03-19 14:19:50 +01005875 if (!new_qi && qi != save_qi && qf_find_buf(qi) == NULL)
Bram Moolenaar73633f82012-01-20 13:39:07 +01005876 /* autocommands made "qi" invalid */
5877 return;
5878 }
5879#endif
5880
Bram Moolenaar071d4272004-06-13 20:20:40 +00005881 /* Jump to first match. */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00005882 if (qi->qf_lists[qi->qf_curlist].qf_count > 0)
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00005883 qf_jump(qi, 0, 0, FALSE);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005884 else
5885 EMSG2(_(e_nomatch2), eap->arg);
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00005886
5887 if (eap->cmdidx == CMD_lhelpgrep)
5888 {
5889 /* If the help window is not opened or if it already points to the
Bram Moolenaar754b5602006-02-09 23:53:20 +00005890 * correct location list, then free the new location list. */
Bram Moolenaard28cc3f2017-07-27 22:03:50 +02005891 if (!bt_help(curwin->w_buffer) || curwin->w_llist == qi)
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00005892 {
5893 if (new_qi)
5894 ll_free_all(&qi);
5895 }
5896 else if (curwin->w_llist == NULL)
5897 curwin->w_llist = qi;
5898 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005899}
5900
5901#endif /* FEAT_QUICKFIX */