blob: 19e03c4da747685095b9d11437031b12a4ac8dbe [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* vi:set ts=8 sts=4 sw=4:
2 *
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
24static struct dir_stack_T *dir_stack = NULL;
25
26/*
Bram Moolenaar68b76a62005-03-25 21:53:48 +000027 * For each error the next struct is allocated and linked in a list.
Bram Moolenaar071d4272004-06-13 20:20:40 +000028 */
Bram Moolenaar68b76a62005-03-25 21:53:48 +000029typedef struct qfline_S qfline_T;
30struct qfline_S
Bram Moolenaar071d4272004-06-13 20:20:40 +000031{
Bram Moolenaar68b76a62005-03-25 21:53:48 +000032 qfline_T *qf_next; /* pointer to next error in the list */
33 qfline_T *qf_prev; /* pointer to previous error in the list */
34 linenr_T qf_lnum; /* line number where the error occurred */
35 int qf_fnum; /* file number for the line */
36 int qf_col; /* column where the error occurred */
37 int qf_nr; /* error number */
38 char_u *qf_pattern; /* search pattern for the error */
39 char_u *qf_text; /* description of the error */
40 char_u qf_viscol; /* set to TRUE if qf_col is screen column */
41 char_u qf_cleared; /* set to TRUE if line has been deleted */
42 char_u qf_type; /* type of the error (mostly 'E'); 1 for
Bram Moolenaar071d4272004-06-13 20:20:40 +000043 :helpgrep */
Bram Moolenaar68b76a62005-03-25 21:53:48 +000044 char_u qf_valid; /* valid error message detected */
Bram Moolenaar071d4272004-06-13 20:20:40 +000045};
46
47/*
48 * There is a stack of error lists.
49 */
50#define LISTCOUNT 10
51
Bram Moolenaard12f5c12006-01-25 22:10:52 +000052typedef struct qf_list_S
Bram Moolenaar071d4272004-06-13 20:20:40 +000053{
Bram Moolenaar68b76a62005-03-25 21:53:48 +000054 qfline_T *qf_start; /* pointer to the first error */
55 qfline_T *qf_ptr; /* pointer to the current error */
56 int qf_count; /* number of errors (0 means no error list) */
57 int qf_index; /* current index in the error list */
58 int qf_nonevalid; /* TRUE if not a single valid entry found */
Bram Moolenaard12f5c12006-01-25 22:10:52 +000059} qf_list_T;
Bram Moolenaar071d4272004-06-13 20:20:40 +000060
Bram Moolenaard12f5c12006-01-25 22:10:52 +000061struct qf_info_S
62{
63 /*
64 * Count of references to this list. Used only for location lists.
65 * When a location list window reference this list, qf_refcount
66 * will be 2. Otherwise, qf_refcount will be 1. When qf_refcount
67 * reaches 0, the list is freed.
68 */
69 int qf_refcount;
70 int qf_listcount; /* current number of lists */
71 int qf_curlist; /* current error list */
72 qf_list_T qf_lists[LISTCOUNT];
73};
74
75static qf_info_T ql_info; /* global quickfix list */
Bram Moolenaar071d4272004-06-13 20:20:40 +000076
Bram Moolenaar68b76a62005-03-25 21:53:48 +000077#define FMT_PATTERNS 10 /* maximum number of % recognized */
Bram Moolenaar071d4272004-06-13 20:20:40 +000078
79/*
80 * Structure used to hold the info of one part of 'errorformat'
81 */
Bram Moolenaar01265852006-03-20 21:50:15 +000082typedef struct efm_S efm_T;
83struct efm_S
Bram Moolenaar071d4272004-06-13 20:20:40 +000084{
85 regprog_T *prog; /* pre-formatted part of 'errorformat' */
Bram Moolenaar01265852006-03-20 21:50:15 +000086 efm_T *next; /* pointer to next (NULL if last) */
Bram Moolenaar071d4272004-06-13 20:20:40 +000087 char_u addr[FMT_PATTERNS]; /* indices of used % patterns */
88 char_u prefix; /* prefix of this format line: */
89 /* 'D' enter directory */
90 /* 'X' leave directory */
91 /* 'A' start of multi-line message */
92 /* 'E' error message */
93 /* 'W' warning message */
94 /* 'I' informational message */
95 /* 'C' continuation line */
96 /* 'Z' end of multi-line message */
97 /* 'G' general, unspecific message */
98 /* 'P' push file (partial) message */
99 /* 'Q' pop/quit file (partial) message */
100 /* 'O' overread (partial) message */
101 char_u flags; /* additional flags given in prefix */
102 /* '-' do not include this line */
Bram Moolenaar4770d092006-01-12 23:22:24 +0000103 /* '+' include whole line in message */
Bram Moolenaar01265852006-03-20 21:50:15 +0000104 int conthere; /* %> used */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000105};
106
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000107static int qf_init_ext __ARGS((qf_info_T *qi, char_u *efile, buf_T *buf, typval_T *tv, char_u *errorformat, int newlist, linenr_T lnumfirst, linenr_T lnumlast));
108static void qf_new_list __ARGS((qf_info_T *qi));
109static int qf_add_entry __ARGS((qf_info_T *qi, qfline_T **prevp, char_u *dir, char_u *fname, char_u *mesg, long lnum, int col, int vis_col, char_u *pattern, int nr, int type, int valid));
110static void qf_msg __ARGS((qf_info_T *qi));
111static void qf_free __ARGS((qf_info_T *qi, int idx));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000112static char_u *qf_types __ARGS((int, int));
113static int qf_get_fnum __ARGS((char_u *, char_u *));
114static char_u *qf_push_dir __ARGS((char_u *, struct dir_stack_T **));
115static char_u *qf_pop_dir __ARGS((struct dir_stack_T **));
116static char_u *qf_guess_filepath __ARGS((char_u *));
117static void qf_fmt_text __ARGS((char_u *text, char_u *buf, int bufsize));
118static void qf_clean_dir_stack __ARGS((struct dir_stack_T **));
119#ifdef FEAT_WINDOWS
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000120static int qf_win_pos_update __ARGS((qf_info_T *qi, int old_qf_index));
Bram Moolenaar9c102382006-05-03 21:26:49 +0000121static int is_qf_win __ARGS((win_T *win, qf_info_T *qi));
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000122static win_T *qf_find_win __ARGS((qf_info_T *qi));
123static buf_T *qf_find_buf __ARGS((qf_info_T *qi));
124static void qf_update_buffer __ARGS((qf_info_T *qi));
125static void qf_fill_buffer __ARGS((qf_info_T *qi));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000126#endif
127static char_u *get_mef_name __ARGS((void));
Bram Moolenaar81695252004-12-29 20:58:21 +0000128static buf_T *load_dummy_buffer __ARGS((char_u *fname));
129static void wipe_dummy_buffer __ARGS((buf_T *buf));
130static void unload_dummy_buffer __ARGS((buf_T *buf));
Bram Moolenaarc7453f52006-02-10 23:20:28 +0000131static qf_info_T *ll_get_or_alloc_list __ARGS((win_T *));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000132
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000133/* Quickfix window check helper macro */
134#define IS_QF_WINDOW(wp) (bt_quickfix(wp->w_buffer) && wp->w_llist_ref == NULL)
135/* Location list window check helper macro */
136#define IS_LL_WINDOW(wp) (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL)
137/*
138 * Return location list for window 'wp'
139 * For location list window, return the referenced location list
140 */
141#define GET_LOC_LIST(wp) (IS_LL_WINDOW(wp) ? wp->w_llist_ref : wp->w_llist)
142
Bram Moolenaar071d4272004-06-13 20:20:40 +0000143/*
Bram Moolenaar86b68352004-12-27 21:59:20 +0000144 * Read the errorfile "efile" into memory, line by line, building the error
145 * list.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000146 * Return -1 for error, number of errors for success.
147 */
148 int
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000149qf_init(wp, efile, errorformat, newlist)
150 win_T *wp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000151 char_u *efile;
152 char_u *errorformat;
153 int newlist; /* TRUE: start a new error list */
154{
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000155 qf_info_T *qi = &ql_info;
156
Bram Moolenaar86b68352004-12-27 21:59:20 +0000157 if (efile == NULL)
158 return FAIL;
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000159
160 if (wp != NULL)
Bram Moolenaarc7453f52006-02-10 23:20:28 +0000161 {
162 qi = ll_get_or_alloc_list(wp);
163 if (qi == NULL)
164 return FAIL;
165 }
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000166
167 return qf_init_ext(qi, efile, curbuf, NULL, errorformat, newlist,
Bram Moolenaar86b68352004-12-27 21:59:20 +0000168 (linenr_T)0, (linenr_T)0);
169}
170
171/*
172 * Read the errorfile "efile" into memory, line by line, building the error
173 * list.
174 * Alternative: when "efile" is null read errors from buffer "buf".
175 * Always use 'errorformat' from "buf" if there is a local value.
176 * Then lnumfirst and lnumlast specify the range of lines to use.
177 * Return -1 for error, number of errors for success.
178 */
179 static int
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000180qf_init_ext(qi, efile, buf, tv, errorformat, newlist, lnumfirst, lnumlast)
181 qf_info_T *qi;
Bram Moolenaar86b68352004-12-27 21:59:20 +0000182 char_u *efile;
183 buf_T *buf;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000184 typval_T *tv;
Bram Moolenaar86b68352004-12-27 21:59:20 +0000185 char_u *errorformat;
186 int newlist; /* TRUE: start a new error list */
187 linenr_T lnumfirst; /* first line number to use */
188 linenr_T lnumlast; /* last line number to use */
189{
Bram Moolenaar071d4272004-06-13 20:20:40 +0000190 char_u *namebuf;
191 char_u *errmsg;
Bram Moolenaar68b76a62005-03-25 21:53:48 +0000192 char_u *pattern;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000193 char_u *fmtstr = NULL;
194 int col = 0;
Bram Moolenaar05159a02005-02-26 23:04:13 +0000195 char_u use_viscol = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000196 int type = 0;
197 int valid;
Bram Moolenaar86b68352004-12-27 21:59:20 +0000198 linenr_T buflnum = lnumfirst;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000199 long lnum = 0L;
200 int enr = 0;
Bram Moolenaar86b68352004-12-27 21:59:20 +0000201 FILE *fd = NULL;
Bram Moolenaar68b76a62005-03-25 21:53:48 +0000202 qfline_T *qfprev = NULL; /* init to make SASC shut up */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000203 char_u *efmp;
Bram Moolenaar01265852006-03-20 21:50:15 +0000204 efm_T *fmt_first = NULL;
205 efm_T *fmt_last = NULL;
206 efm_T *fmt_ptr;
207 efm_T *fmt_start = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000208 char_u *efm;
209 char_u *ptr;
210 char_u *srcptr;
211 int len;
212 int i;
213 int round;
214 int idx = 0;
215 int multiline = FALSE;
216 int multiignore = FALSE;
217 int multiscan = FALSE;
218 int retval = -1; /* default: return error flag */
219 char_u *directory = NULL;
220 char_u *currfile = NULL;
221 char_u *tail = NULL;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000222 char_u *p_str = NULL;
223 listitem_T *p_li = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000224 struct dir_stack_T *file_stack = NULL;
225 regmatch_T regmatch;
226 static struct fmtpattern
227 {
228 char_u convchar;
229 char *pattern;
230 } fmt_pat[FMT_PATTERNS] =
231 {
Bram Moolenaare344bea2005-09-01 20:46:49 +0000232 {'f', ".\\+"}, /* only used when at end */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000233 {'n', "\\d\\+"},
234 {'l', "\\d\\+"},
235 {'c', "\\d\\+"},
236 {'t', "."},
237 {'m', ".\\+"},
238 {'r', ".*"},
239 {'p', "[- .]*"},
Bram Moolenaar68b76a62005-03-25 21:53:48 +0000240 {'v', "\\d\\+"},
241 {'s', ".\\+"}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000242 };
243
Bram Moolenaar071d4272004-06-13 20:20:40 +0000244 namebuf = alloc(CMDBUFFSIZE + 1);
245 errmsg = alloc(CMDBUFFSIZE + 1);
Bram Moolenaar68b76a62005-03-25 21:53:48 +0000246 pattern = alloc(CMDBUFFSIZE + 1);
247 if (namebuf == NULL || errmsg == NULL || pattern == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000248 goto qf_init_end;
249
Bram Moolenaar86b68352004-12-27 21:59:20 +0000250 if (efile != NULL && (fd = mch_fopen((char *)efile, "r")) == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000251 {
252 EMSG2(_(e_openerrf), efile);
253 goto qf_init_end;
254 }
255
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000256 if (newlist || qi->qf_curlist == qi->qf_listcount)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000257 /* make place for a new list */
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000258 qf_new_list(qi);
259 else if (qi->qf_lists[qi->qf_curlist].qf_count > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000260 /* Adding to existing list, find last entry. */
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000261 for (qfprev = qi->qf_lists[qi->qf_curlist].qf_start;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000262 qfprev->qf_next != qfprev; qfprev = qfprev->qf_next)
263 ;
264
265/*
266 * Each part of the format string is copied and modified from errorformat to
267 * regex prog. Only a few % characters are allowed.
268 */
269 /* Use the local value of 'errorformat' if it's set. */
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000270 if (errorformat == p_efm && tv == NULL && *buf->b_p_efm != NUL)
Bram Moolenaar86b68352004-12-27 21:59:20 +0000271 efm = buf->b_p_efm;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000272 else
273 efm = errorformat;
274 /*
275 * Get some space to modify the format string into.
276 */
277 i = (FMT_PATTERNS * 3) + ((int)STRLEN(efm) << 2);
278 for (round = FMT_PATTERNS; round > 0; )
279 i += (int)STRLEN(fmt_pat[--round].pattern);
280#ifdef COLON_IN_FILENAME
281 i += 12; /* "%f" can become twelve chars longer */
282#else
283 i += 2; /* "%f" can become two chars longer */
284#endif
285 if ((fmtstr = alloc(i)) == NULL)
286 goto error2;
287
Bram Moolenaar01265852006-03-20 21:50:15 +0000288 while (efm[0] != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000289 {
290 /*
291 * Allocate a new eformat structure and put it at the end of the list
292 */
Bram Moolenaar01265852006-03-20 21:50:15 +0000293 fmt_ptr = (efm_T *)alloc_clear((unsigned)sizeof(efm_T));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000294 if (fmt_ptr == NULL)
295 goto error2;
296 if (fmt_first == NULL) /* first one */
297 fmt_first = fmt_ptr;
298 else
299 fmt_last->next = fmt_ptr;
300 fmt_last = fmt_ptr;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000301
302 /*
303 * Isolate one part in the 'errorformat' option
304 */
305 for (len = 0; efm[len] != NUL && efm[len] != ','; ++len)
306 if (efm[len] == '\\' && efm[len + 1] != NUL)
307 ++len;
308
309 /*
310 * Build regexp pattern from current 'errorformat' option
311 */
312 ptr = fmtstr;
313 *ptr++ = '^';
Bram Moolenaar01265852006-03-20 21:50:15 +0000314 round = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000315 for (efmp = efm; efmp < efm + len; ++efmp)
316 {
317 if (*efmp == '%')
318 {
319 ++efmp;
320 for (idx = 0; idx < FMT_PATTERNS; ++idx)
321 if (fmt_pat[idx].convchar == *efmp)
322 break;
323 if (idx < FMT_PATTERNS)
324 {
325 if (fmt_ptr->addr[idx])
326 {
327 sprintf((char *)errmsg,
328 _("E372: Too many %%%c in format string"), *efmp);
329 EMSG(errmsg);
330 goto error2;
331 }
332 if ((idx
333 && idx < 6
334 && vim_strchr((char_u *)"DXOPQ",
335 fmt_ptr->prefix) != NULL)
336 || (idx == 6
337 && vim_strchr((char_u *)"OPQ",
338 fmt_ptr->prefix) == NULL))
339 {
340 sprintf((char *)errmsg,
341 _("E373: Unexpected %%%c in format string"), *efmp);
342 EMSG(errmsg);
343 goto error2;
344 }
345 fmt_ptr->addr[idx] = (char_u)++round;
346 *ptr++ = '\\';
347 *ptr++ = '(';
348#ifdef BACKSLASH_IN_FILENAME
349 if (*efmp == 'f')
350 {
351 /* Also match "c:" in the file name, even when
352 * checking for a colon next: "%f:".
353 * "\%(\a:\)\=" */
354 STRCPY(ptr, "\\%(\\a:\\)\\=");
355 ptr += 10;
356 }
357#endif
Bram Moolenaare344bea2005-09-01 20:46:49 +0000358 if (*efmp == 'f' && efmp[1] != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000359 {
Bram Moolenaare344bea2005-09-01 20:46:49 +0000360 if (efmp[1] != '\\' && efmp[1] != '%')
361 {
362 /* A file name may contain spaces, but this isn't
363 * in "\f". For "%f:%l:%m" there may be a ":" in
364 * the file name. Use ".\{-1,}x" instead (x is
365 * the next character), the requirement that :999:
366 * follows should work. */
367 STRCPY(ptr, ".\\{-1,}");
368 ptr += 7;
369 }
370 else
371 {
372 /* File name followed by '\\' or '%': include as
373 * many file name chars as possible. */
374 STRCPY(ptr, "\\f\\+");
375 ptr += 4;
376 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000377 }
378 else
379 {
380 srcptr = (char_u *)fmt_pat[idx].pattern;
381 while ((*ptr = *srcptr++) != NUL)
382 ++ptr;
383 }
384 *ptr++ = '\\';
385 *ptr++ = ')';
386 }
387 else if (*efmp == '*')
388 {
389 if (*++efmp == '[' || *efmp == '\\')
390 {
391 if ((*ptr++ = *efmp) == '[') /* %*[^a-z0-9] etc. */
392 {
393 if (efmp[1] == '^')
394 *ptr++ = *++efmp;
395 if (efmp < efm + len)
396 {
397 *ptr++ = *++efmp; /* could be ']' */
398 while (efmp < efm + len
399 && (*ptr++ = *++efmp) != ']')
400 /* skip */;
401 if (efmp == efm + len)
402 {
403 EMSG(_("E374: Missing ] in format string"));
404 goto error2;
405 }
406 }
407 }
408 else if (efmp < efm + len) /* %*\D, %*\s etc. */
409 *ptr++ = *++efmp;
410 *ptr++ = '\\';
411 *ptr++ = '+';
412 }
413 else
414 {
415 /* TODO: scanf()-like: %*ud, %*3c, %*f, ... ? */
416 sprintf((char *)errmsg,
417 _("E375: Unsupported %%%c in format string"), *efmp);
418 EMSG(errmsg);
419 goto error2;
420 }
421 }
422 else if (vim_strchr((char_u *)"%\\.^$~[", *efmp) != NULL)
423 *ptr++ = *efmp; /* regexp magic characters */
424 else if (*efmp == '#')
425 *ptr++ = '*';
Bram Moolenaar01265852006-03-20 21:50:15 +0000426 else if (*efmp == '>')
427 fmt_ptr->conthere = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000428 else if (efmp == efm + 1) /* analyse prefix */
429 {
430 if (vim_strchr((char_u *)"+-", *efmp) != NULL)
431 fmt_ptr->flags = *efmp++;
432 if (vim_strchr((char_u *)"DXAEWICZGOPQ", *efmp) != NULL)
433 fmt_ptr->prefix = *efmp;
434 else
435 {
436 sprintf((char *)errmsg,
437 _("E376: Invalid %%%c in format string prefix"), *efmp);
438 EMSG(errmsg);
439 goto error2;
440 }
441 }
442 else
443 {
444 sprintf((char *)errmsg,
445 _("E377: Invalid %%%c in format string"), *efmp);
446 EMSG(errmsg);
447 goto error2;
448 }
449 }
450 else /* copy normal character */
451 {
452 if (*efmp == '\\' && efmp + 1 < efm + len)
453 ++efmp;
454 else if (vim_strchr((char_u *)".*^$~[", *efmp) != NULL)
455 *ptr++ = '\\'; /* escape regexp atoms */
456 if (*efmp)
457 *ptr++ = *efmp;
458 }
459 }
460 *ptr++ = '$';
461 *ptr = NUL;
462 if ((fmt_ptr->prog = vim_regcomp(fmtstr, RE_MAGIC + RE_STRING)) == NULL)
463 goto error2;
464 /*
465 * Advance to next part
466 */
467 efm = skip_to_option_part(efm + len); /* skip comma and spaces */
468 }
469 if (fmt_first == NULL) /* nothing found */
470 {
471 EMSG(_("E378: 'errorformat' contains no pattern"));
472 goto error2;
473 }
474
475 /*
476 * got_int is reset here, because it was probably set when killing the
477 * ":make" command, but we still want to read the errorfile then.
478 */
479 got_int = FALSE;
480
481 /* Always ignore case when looking for a matching error. */
482 regmatch.rm_ic = TRUE;
483
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000484 if (tv != NULL)
485 {
486 if (tv->v_type == VAR_STRING)
487 p_str = tv->vval.v_string;
488 else if (tv->v_type == VAR_LIST)
489 p_li = tv->vval.v_list->lv_first;
490 }
491
Bram Moolenaar071d4272004-06-13 20:20:40 +0000492 /*
493 * Read the lines in the error file one by one.
494 * Try to recognize one of the error formats in each line.
495 */
Bram Moolenaar86b68352004-12-27 21:59:20 +0000496 while (!got_int)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000497 {
Bram Moolenaar86b68352004-12-27 21:59:20 +0000498 /* Get the next line. */
499 if (fd == NULL)
500 {
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000501 if (tv != NULL)
502 {
503 int len;
504
505 if (tv->v_type == VAR_STRING)
506 {
507 /* Get the next line from the supplied string */
508 char_u *p;
509
510 if (!*p_str) /* Reached the end of the string */
511 break;
512
513 p = vim_strchr(p_str, '\n');
514 if (p)
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000515 len = (int)(p - p_str + 1);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000516 else
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000517 len = (int)STRLEN(p_str);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000518
519 if (len > CMDBUFFSIZE - 2)
520 vim_strncpy(IObuff, p_str, CMDBUFFSIZE - 2);
521 else
522 vim_strncpy(IObuff, p_str, len);
523
524 p_str += len;
525 }
526 else if (tv->v_type == VAR_LIST)
527 {
528 /* Get the next line from the supplied list */
529 while (p_li && p_li->li_tv.v_type != VAR_STRING)
530 p_li = p_li->li_next; /* Skip non-string items */
531
532 if (!p_li) /* End of the list */
533 break;
534
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000535 len = (int)STRLEN(p_li->li_tv.vval.v_string);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000536 if (len > CMDBUFFSIZE - 2)
537 len = CMDBUFFSIZE - 2;
538
539 vim_strncpy(IObuff, p_li->li_tv.vval.v_string, len);
540
541 p_li = p_li->li_next; /* next item */
542 }
543 }
544 else
545 {
546 /* Get the next line from the supplied buffer */
547 if (buflnum > lnumlast)
548 break;
549 vim_strncpy(IObuff, ml_get_buf(buf, buflnum++, FALSE),
550 CMDBUFFSIZE - 2);
551 }
Bram Moolenaar86b68352004-12-27 21:59:20 +0000552 }
553 else if (fgets((char *)IObuff, CMDBUFFSIZE - 2, fd) == NULL)
554 break;
555
Bram Moolenaar071d4272004-06-13 20:20:40 +0000556 IObuff[CMDBUFFSIZE - 2] = NUL; /* for very long lines */
557 if ((efmp = vim_strrchr(IObuff, '\n')) != NULL)
558 *efmp = NUL;
559#ifdef USE_CRNL
560 if ((efmp = vim_strrchr(IObuff, '\r')) != NULL)
561 *efmp = NUL;
562#endif
563
Bram Moolenaar01265852006-03-20 21:50:15 +0000564 /* If there was no %> item start at the first pattern */
565 if (fmt_start == NULL)
566 fmt_ptr = fmt_first;
567 else
568 {
569 fmt_ptr = fmt_start;
570 fmt_start = NULL;
571 }
572
Bram Moolenaar071d4272004-06-13 20:20:40 +0000573 /*
574 * Try to match each part of 'errorformat' until we find a complete
575 * match or no match.
576 */
577 valid = TRUE;
578restofline:
Bram Moolenaar01265852006-03-20 21:50:15 +0000579 for ( ; fmt_ptr != NULL; fmt_ptr = fmt_ptr->next)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000580 {
581 idx = fmt_ptr->prefix;
582 if (multiscan && vim_strchr((char_u *)"OPQ", idx) == NULL)
583 continue;
584 namebuf[0] = NUL;
Bram Moolenaar68b76a62005-03-25 21:53:48 +0000585 pattern[0] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000586 if (!multiscan)
587 errmsg[0] = NUL;
588 lnum = 0;
589 col = 0;
Bram Moolenaar05159a02005-02-26 23:04:13 +0000590 use_viscol = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000591 enr = -1;
592 type = 0;
593 tail = NULL;
594
595 regmatch.regprog = fmt_ptr->prog;
596 if (vim_regexec(&regmatch, IObuff, (colnr_T)0))
597 {
598 if ((idx == 'C' || idx == 'Z') && !multiline)
599 continue;
600 if (vim_strchr((char_u *)"EWI", idx) != NULL)
601 type = idx;
602 else
603 type = 0;
604 /*
605 * Extract error message data from matched line
606 */
607 if ((i = (int)fmt_ptr->addr[0]) > 0) /* %f */
608 {
Bram Moolenaar35c54e52005-05-20 21:25:31 +0000609 int c = *regmatch.endp[i];
610
611 /* Expand ~/file and $HOME/file to full path. */
612 *regmatch.endp[i] = NUL;
613 expand_env(regmatch.startp[i], namebuf, CMDBUFFSIZE);
614 *regmatch.endp[i] = c;
615
Bram Moolenaar071d4272004-06-13 20:20:40 +0000616 if (vim_strchr((char_u *)"OPQ", idx) != NULL
Bram Moolenaar35c54e52005-05-20 21:25:31 +0000617 && mch_getperm(namebuf) == -1)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000618 continue;
619 }
620 if ((i = (int)fmt_ptr->addr[1]) > 0) /* %n */
621 enr = (int)atol((char *)regmatch.startp[i]);
622 if ((i = (int)fmt_ptr->addr[2]) > 0) /* %l */
623 lnum = atol((char *)regmatch.startp[i]);
624 if ((i = (int)fmt_ptr->addr[3]) > 0) /* %c */
625 col = (int)atol((char *)regmatch.startp[i]);
626 if ((i = (int)fmt_ptr->addr[4]) > 0) /* %t */
627 type = *regmatch.startp[i];
Bram Moolenaar4770d092006-01-12 23:22:24 +0000628 if (fmt_ptr->flags == '+' && !multiscan) /* %+ */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000629 STRCPY(errmsg, IObuff);
630 else if ((i = (int)fmt_ptr->addr[5]) > 0) /* %m */
631 {
632 len = (int)(regmatch.endp[i] - regmatch.startp[i]);
Bram Moolenaarbbebc852005-07-18 21:47:53 +0000633 vim_strncpy(errmsg, regmatch.startp[i], len);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000634 }
635 if ((i = (int)fmt_ptr->addr[6]) > 0) /* %r */
636 tail = regmatch.startp[i];
637 if ((i = (int)fmt_ptr->addr[7]) > 0) /* %p */
638 {
639 col = (int)(regmatch.endp[i] - regmatch.startp[i] + 1);
640 if (*((char_u *)regmatch.startp[i]) != TAB)
Bram Moolenaar05159a02005-02-26 23:04:13 +0000641 use_viscol = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000642 }
643 if ((i = (int)fmt_ptr->addr[8]) > 0) /* %v */
644 {
645 col = (int)atol((char *)regmatch.startp[i]);
Bram Moolenaar05159a02005-02-26 23:04:13 +0000646 use_viscol = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000647 }
Bram Moolenaar68b76a62005-03-25 21:53:48 +0000648 if ((i = (int)fmt_ptr->addr[9]) > 0) /* %s */
649 {
650 len = (int)(regmatch.endp[i] - regmatch.startp[i]);
651 if (len > CMDBUFFSIZE - 5)
652 len = CMDBUFFSIZE - 5;
653 STRCPY(pattern, "^\\V");
654 STRNCAT(pattern, regmatch.startp[i], len);
655 pattern[len + 3] = '\\';
656 pattern[len + 4] = '$';
657 pattern[len + 5] = NUL;
658 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000659 break;
660 }
661 }
662 multiscan = FALSE;
Bram Moolenaar01265852006-03-20 21:50:15 +0000663
Bram Moolenaar4770d092006-01-12 23:22:24 +0000664 if (fmt_ptr == NULL || idx == 'D' || idx == 'X')
Bram Moolenaar071d4272004-06-13 20:20:40 +0000665 {
Bram Moolenaar4770d092006-01-12 23:22:24 +0000666 if (fmt_ptr != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000667 {
668 if (idx == 'D') /* enter directory */
669 {
670 if (*namebuf == NUL)
671 {
672 EMSG(_("E379: Missing or empty directory name"));
673 goto error2;
674 }
675 if ((directory = qf_push_dir(namebuf, &dir_stack)) == NULL)
676 goto error2;
677 }
678 else if (idx == 'X') /* leave directory */
679 directory = qf_pop_dir(&dir_stack);
680 }
681 namebuf[0] = NUL; /* no match found, remove file name */
682 lnum = 0; /* don't jump to this line */
683 valid = FALSE;
684 STRCPY(errmsg, IObuff); /* copy whole line to error message */
Bram Moolenaar4770d092006-01-12 23:22:24 +0000685 if (fmt_ptr == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000686 multiline = multiignore = FALSE;
687 }
Bram Moolenaar4770d092006-01-12 23:22:24 +0000688 else if (fmt_ptr != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000689 {
Bram Moolenaar01265852006-03-20 21:50:15 +0000690 /* honor %> item */
691 if (fmt_ptr->conthere)
692 fmt_start = fmt_ptr;
693
Bram Moolenaar071d4272004-06-13 20:20:40 +0000694 if (vim_strchr((char_u *)"AEWI", idx) != NULL)
695 multiline = TRUE; /* start of a multi-line message */
696 else if (vim_strchr((char_u *)"CZ", idx) != NULL)
697 { /* continuation of multi-line msg */
698 if (qfprev == NULL)
699 goto error2;
700 if (*errmsg && !multiignore)
701 {
702 len = (int)STRLEN(qfprev->qf_text);
703 if ((ptr = alloc((unsigned)(len + STRLEN(errmsg) + 2)))
704 == NULL)
705 goto error2;
706 STRCPY(ptr, qfprev->qf_text);
707 vim_free(qfprev->qf_text);
708 qfprev->qf_text = ptr;
709 *(ptr += len) = '\n';
710 STRCPY(++ptr, errmsg);
711 }
712 if (qfprev->qf_nr == -1)
713 qfprev->qf_nr = enr;
714 if (vim_isprintc(type) && !qfprev->qf_type)
715 qfprev->qf_type = type; /* only printable chars allowed */
716 if (!qfprev->qf_lnum)
717 qfprev->qf_lnum = lnum;
718 if (!qfprev->qf_col)
719 qfprev->qf_col = col;
Bram Moolenaar05159a02005-02-26 23:04:13 +0000720 qfprev->qf_viscol = use_viscol;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000721 if (!qfprev->qf_fnum)
722 qfprev->qf_fnum = qf_get_fnum(directory,
723 *namebuf || directory ? namebuf
724 : currfile && valid ? currfile : 0);
725 if (idx == 'Z')
726 multiline = multiignore = FALSE;
727 line_breakcheck();
728 continue;
729 }
730 else if (vim_strchr((char_u *)"OPQ", idx) != NULL)
731 {
732 /* global file names */
733 valid = FALSE;
734 if (*namebuf == NUL || mch_getperm(namebuf) >= 0)
735 {
736 if (*namebuf && idx == 'P')
737 currfile = qf_push_dir(namebuf, &file_stack);
738 else if (idx == 'Q')
739 currfile = qf_pop_dir(&file_stack);
740 *namebuf = NUL;
741 if (tail && *tail)
742 {
743 STRCPY(IObuff, skipwhite(tail));
744 multiscan = TRUE;
745 goto restofline;
746 }
747 }
748 }
749 if (fmt_ptr->flags == '-') /* generally exclude this line */
750 {
751 if (multiline)
752 multiignore = TRUE; /* also exclude continuation lines */
753 continue;
754 }
755 }
756
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000757 if (qf_add_entry(qi, &qfprev,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000758 directory,
Bram Moolenaar9d75c832005-01-25 21:57:23 +0000759 (*namebuf || directory)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000760 ? namebuf
Bram Moolenaar9d75c832005-01-25 21:57:23 +0000761 : ((currfile && valid) ? currfile : (char_u *)NULL),
Bram Moolenaar071d4272004-06-13 20:20:40 +0000762 errmsg,
763 lnum,
764 col,
Bram Moolenaar05159a02005-02-26 23:04:13 +0000765 use_viscol,
Bram Moolenaar68b76a62005-03-25 21:53:48 +0000766 pattern,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000767 enr,
768 type,
769 valid) == FAIL)
770 goto error2;
771 line_breakcheck();
772 }
Bram Moolenaar86b68352004-12-27 21:59:20 +0000773 if (fd == NULL || !ferror(fd))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000774 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000775 if (qi->qf_lists[qi->qf_curlist].qf_index == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000776 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000777 /* no valid entry found */
778 qi->qf_lists[qi->qf_curlist].qf_ptr =
779 qi->qf_lists[qi->qf_curlist].qf_start;
780 qi->qf_lists[qi->qf_curlist].qf_index = 1;
781 qi->qf_lists[qi->qf_curlist].qf_nonevalid = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000782 }
783 else
784 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000785 qi->qf_lists[qi->qf_curlist].qf_nonevalid = FALSE;
786 if (qi->qf_lists[qi->qf_curlist].qf_ptr == NULL)
787 qi->qf_lists[qi->qf_curlist].qf_ptr =
788 qi->qf_lists[qi->qf_curlist].qf_start;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000789 }
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000790 /* return number of matches */
791 retval = qi->qf_lists[qi->qf_curlist].qf_count;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000792 goto qf_init_ok;
793 }
794 EMSG(_(e_readerrf));
795error2:
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000796 qf_free(qi, qi->qf_curlist);
797 qi->qf_listcount--;
798 if (qi->qf_curlist > 0)
799 --qi->qf_curlist;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000800qf_init_ok:
Bram Moolenaar86b68352004-12-27 21:59:20 +0000801 if (fd != NULL)
802 fclose(fd);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000803 for (fmt_ptr = fmt_first; fmt_ptr != NULL; fmt_ptr = fmt_first)
804 {
805 fmt_first = fmt_ptr->next;
806 vim_free(fmt_ptr->prog);
807 vim_free(fmt_ptr);
808 }
809 qf_clean_dir_stack(&dir_stack);
810 qf_clean_dir_stack(&file_stack);
811qf_init_end:
812 vim_free(namebuf);
813 vim_free(errmsg);
Bram Moolenaar68b76a62005-03-25 21:53:48 +0000814 vim_free(pattern);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000815 vim_free(fmtstr);
816
817#ifdef FEAT_WINDOWS
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000818 qf_update_buffer(qi);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000819#endif
820
821 return retval;
822}
823
824/*
825 * Prepare for adding a new quickfix list.
826 */
827 static void
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000828qf_new_list(qi)
829 qf_info_T *qi;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000830{
831 int i;
832
833 /*
834 * If the current entry is not the last entry, delete entries below
835 * the current entry. This makes it possible to browse in a tree-like
836 * way with ":grep'.
837 */
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000838 while (qi->qf_listcount > qi->qf_curlist + 1)
839 qf_free(qi, --qi->qf_listcount);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000840
841 /*
842 * When the stack is full, remove to oldest entry
843 * Otherwise, add a new entry.
844 */
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000845 if (qi->qf_listcount == LISTCOUNT)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000846 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000847 qf_free(qi, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000848 for (i = 1; i < LISTCOUNT; ++i)
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000849 qi->qf_lists[i - 1] = qi->qf_lists[i];
850 qi->qf_curlist = LISTCOUNT - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000851 }
852 else
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000853 qi->qf_curlist = qi->qf_listcount++;
854 qi->qf_lists[qi->qf_curlist].qf_index = 0;
855 qi->qf_lists[qi->qf_curlist].qf_count = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000856}
857
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000858/*
859 * Free a location list
860 */
861 static void
862ll_free_all(pqi)
863 qf_info_T **pqi;
Bram Moolenaarf461c8e2005-06-25 23:04:51 +0000864{
865 int i;
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000866 qf_info_T *qi;
Bram Moolenaarf461c8e2005-06-25 23:04:51 +0000867
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000868 qi = *pqi;
869 if (qi == NULL)
870 return;
871 *pqi = NULL; /* Remove reference to this list */
872
873 qi->qf_refcount--;
874 if (qi->qf_refcount < 1)
875 {
876 /* No references to this location list */
877 for (i = 0; i < qi->qf_listcount; ++i)
878 qf_free(qi, i);
879 vim_free(qi);
880 }
Bram Moolenaarf461c8e2005-06-25 23:04:51 +0000881}
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000882
883 void
884qf_free_all(wp)
885 win_T *wp;
886{
887 int i;
888 qf_info_T *qi = &ql_info;
889
890 if (wp != NULL)
891 {
892 /* location list */
893 ll_free_all(&wp->w_llist);
894 ll_free_all(&wp->w_llist_ref);
895 }
896 else
897 /* quickfix list */
898 for (i = 0; i < qi->qf_listcount; ++i)
899 qf_free(qi, i);
900}
Bram Moolenaarf461c8e2005-06-25 23:04:51 +0000901
Bram Moolenaar071d4272004-06-13 20:20:40 +0000902/*
903 * Add an entry to the end of the list of errors.
904 * Returns OK or FAIL.
905 */
906 static int
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000907qf_add_entry(qi, prevp, dir, fname, mesg, lnum, col, vis_col, pattern, nr, type,
Bram Moolenaar68b76a62005-03-25 21:53:48 +0000908 valid)
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000909 qf_info_T *qi; /* quickfix list */
Bram Moolenaar68b76a62005-03-25 21:53:48 +0000910 qfline_T **prevp; /* pointer to previously added entry or NULL */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000911 char_u *dir; /* optional directory name */
912 char_u *fname; /* file name or NULL */
913 char_u *mesg; /* message */
914 long lnum; /* line number */
915 int col; /* column */
Bram Moolenaar05159a02005-02-26 23:04:13 +0000916 int vis_col; /* using visual column */
Bram Moolenaar68b76a62005-03-25 21:53:48 +0000917 char_u *pattern; /* search pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000918 int nr; /* error number */
919 int type; /* type character */
920 int valid; /* valid entry */
921{
Bram Moolenaar68b76a62005-03-25 21:53:48 +0000922 qfline_T *qfp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000923
Bram Moolenaar68b76a62005-03-25 21:53:48 +0000924 if ((qfp = (qfline_T *)alloc((unsigned)sizeof(qfline_T))) == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000925 return FAIL;
926 qfp->qf_fnum = qf_get_fnum(dir, fname);
927 if ((qfp->qf_text = vim_strsave(mesg)) == NULL)
928 {
929 vim_free(qfp);
930 return FAIL;
931 }
932 qfp->qf_lnum = lnum;
933 qfp->qf_col = col;
Bram Moolenaar05159a02005-02-26 23:04:13 +0000934 qfp->qf_viscol = vis_col;
Bram Moolenaar68b76a62005-03-25 21:53:48 +0000935 if (pattern == NULL || *pattern == NUL)
936 qfp->qf_pattern = NULL;
937 else if ((qfp->qf_pattern = vim_strsave(pattern)) == NULL)
938 {
939 vim_free(qfp->qf_text);
940 vim_free(qfp);
941 return FAIL;
942 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000943 qfp->qf_nr = nr;
944 if (type != 1 && !vim_isprintc(type)) /* only printable chars allowed */
945 type = 0;
946 qfp->qf_type = type;
947 qfp->qf_valid = valid;
948
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000949 if (qi->qf_lists[qi->qf_curlist].qf_count == 0)
950 /* first element in the list */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000951 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000952 qi->qf_lists[qi->qf_curlist].qf_start = qfp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000953 qfp->qf_prev = qfp; /* first element points to itself */
954 }
955 else
956 {
957 qfp->qf_prev = *prevp;
958 (*prevp)->qf_next = qfp;
959 }
960 qfp->qf_next = qfp; /* last element points to itself */
961 qfp->qf_cleared = FALSE;
962 *prevp = qfp;
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000963 ++qi->qf_lists[qi->qf_curlist].qf_count;
964 if (qi->qf_lists[qi->qf_curlist].qf_index == 0 && qfp->qf_valid)
965 /* first valid entry */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000966 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000967 qi->qf_lists[qi->qf_curlist].qf_index =
968 qi->qf_lists[qi->qf_curlist].qf_count;
969 qi->qf_lists[qi->qf_curlist].qf_ptr = qfp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000970 }
971
972 return OK;
973}
974
975/*
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000976 * Allocate a new location list
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000977 */
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000978 static qf_info_T *
979ll_new_list()
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000980{
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000981 qf_info_T *qi;
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000982
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000983 qi = (qf_info_T *)alloc((unsigned)sizeof(qf_info_T));
984 if (qi != NULL)
985 {
986 vim_memset(qi, 0, (size_t)(sizeof(qf_info_T)));
987 qi->qf_refcount++;
988 }
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000989
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000990 return qi;
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000991}
992
993/*
994 * Return the location list for window 'wp'.
995 * If not present, allocate a location list
996 */
997 static qf_info_T *
998ll_get_or_alloc_list(wp)
999 win_T *wp;
1000{
1001 if (IS_LL_WINDOW(wp))
1002 /* For a location list window, use the referenced location list */
1003 return wp->w_llist_ref;
1004
1005 /*
1006 * For a non-location list window, w_llist_ref should not point to a
1007 * location list.
1008 */
1009 ll_free_all(&wp->w_llist_ref);
1010
1011 if (wp->w_llist == NULL)
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00001012 wp->w_llist = ll_new_list(); /* new location list */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001013 return wp->w_llist;
1014}
1015
1016/*
1017 * Copy the location list from window "from" to window "to".
1018 */
1019 void
1020copy_loclist(from, to)
1021 win_T *from;
1022 win_T *to;
1023{
1024 qf_info_T *qi;
1025 int idx;
1026 int i;
1027
1028 /*
1029 * When copying from a location list window, copy the referenced
1030 * location list. For other windows, copy the location list for
1031 * that window.
1032 */
1033 if (IS_LL_WINDOW(from))
1034 qi = from->w_llist_ref;
1035 else
1036 qi = from->w_llist;
1037
1038 if (qi == NULL) /* no location list to copy */
1039 return;
1040
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00001041 /* allocate a new location list */
1042 if ((to->w_llist = ll_new_list()) == NULL)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001043 return;
1044
1045 to->w_llist->qf_listcount = qi->qf_listcount;
1046
1047 /* Copy the location lists one at a time */
1048 for (idx = 0; idx < qi->qf_listcount; idx++)
1049 {
1050 qf_list_T *from_qfl;
1051 qf_list_T *to_qfl;
1052
1053 to->w_llist->qf_curlist = idx;
1054
1055 from_qfl = &qi->qf_lists[idx];
1056 to_qfl = &to->w_llist->qf_lists[idx];
1057
1058 /* Some of the fields are populated by qf_add_entry() */
1059 to_qfl->qf_nonevalid = from_qfl->qf_nonevalid;
1060 to_qfl->qf_count = 0;
1061 to_qfl->qf_index = 0;
1062 to_qfl->qf_start = NULL;
1063 to_qfl->qf_ptr = NULL;
1064
1065 if (from_qfl->qf_count)
1066 {
1067 qfline_T *from_qfp;
1068 qfline_T *prevp = NULL;
1069
1070 /* copy all the location entries in this list */
1071 for (i = 0, from_qfp = from_qfl->qf_start; i < from_qfl->qf_count;
1072 ++i, from_qfp = from_qfp->qf_next)
1073 {
1074 if (qf_add_entry(to->w_llist, &prevp,
1075 NULL,
1076 NULL,
1077 from_qfp->qf_text,
1078 from_qfp->qf_lnum,
1079 from_qfp->qf_col,
1080 from_qfp->qf_viscol,
1081 from_qfp->qf_pattern,
1082 from_qfp->qf_nr,
1083 0,
1084 from_qfp->qf_valid) == FAIL)
1085 {
1086 qf_free_all(to);
1087 return;
1088 }
1089 /*
1090 * qf_add_entry() will not set the qf_num field, as the
1091 * directory and file names are not supplied. So the qf_fnum
1092 * field is copied here.
1093 */
1094 prevp->qf_fnum = from_qfp->qf_fnum; /* file number */
1095 prevp->qf_type = from_qfp->qf_type; /* error type */
1096 if (from_qfl->qf_ptr == from_qfp)
1097 to_qfl->qf_ptr = prevp; /* current location */
1098 }
1099 }
1100
1101 to_qfl->qf_index = from_qfl->qf_index; /* current index in the list */
1102
1103 /* When no valid entries are present in the list, qf_ptr points to
1104 * the first item in the list */
1105 if (to_qfl->qf_nonevalid == TRUE)
1106 to_qfl->qf_ptr = to_qfl->qf_start;
1107 }
1108
1109 to->w_llist->qf_curlist = qi->qf_curlist; /* current list */
1110}
1111
1112/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00001113 * get buffer number for file "dir.name"
1114 */
1115 static int
1116qf_get_fnum(directory, fname)
1117 char_u *directory;
1118 char_u *fname;
1119{
1120 if (fname == NULL || *fname == NUL) /* no file name */
1121 return 0;
1122 {
1123#ifdef RISCOS
1124 /* Name is reported as `main.c', but file is `c.main' */
1125 return ro_buflist_add(fname);
1126#else
1127 char_u *ptr;
1128 int fnum;
1129
1130# ifdef VMS
1131 vms_remove_version(fname);
1132# endif
1133# ifdef BACKSLASH_IN_FILENAME
1134 if (directory != NULL)
1135 slash_adjust(directory);
1136 slash_adjust(fname);
1137# endif
1138 if (directory != NULL && !vim_isAbsName(fname)
1139 && (ptr = concat_fnames(directory, fname, TRUE)) != NULL)
1140 {
1141 /*
1142 * Here we check if the file really exists.
1143 * This should normally be true, but if make works without
1144 * "leaving directory"-messages we might have missed a
1145 * directory change.
1146 */
1147 if (mch_getperm(ptr) < 0)
1148 {
1149 vim_free(ptr);
1150 directory = qf_guess_filepath(fname);
1151 if (directory)
1152 ptr = concat_fnames(directory, fname, TRUE);
1153 else
1154 ptr = vim_strsave(fname);
1155 }
1156 /* Use concatenated directory name and file name */
1157 fnum = buflist_add(ptr, 0);
1158 vim_free(ptr);
1159 return fnum;
1160 }
1161 return buflist_add(fname, 0);
1162#endif
1163 }
1164}
1165
1166/*
1167 * push dirbuf onto the directory stack and return pointer to actual dir or
1168 * NULL on error
1169 */
1170 static char_u *
1171qf_push_dir(dirbuf, stackptr)
1172 char_u *dirbuf;
1173 struct dir_stack_T **stackptr;
1174{
1175 struct dir_stack_T *ds_new;
1176 struct dir_stack_T *ds_ptr;
1177
1178 /* allocate new stack element and hook it in */
1179 ds_new = (struct dir_stack_T *)alloc((unsigned)sizeof(struct dir_stack_T));
1180 if (ds_new == NULL)
1181 return NULL;
1182
1183 ds_new->next = *stackptr;
1184 *stackptr = ds_new;
1185
1186 /* store directory on the stack */
1187 if (vim_isAbsName(dirbuf)
1188 || (*stackptr)->next == NULL
1189 || (*stackptr && dir_stack != *stackptr))
1190 (*stackptr)->dirname = vim_strsave(dirbuf);
1191 else
1192 {
1193 /* Okay we don't have an absolute path.
1194 * dirbuf must be a subdir of one of the directories on the stack.
1195 * Let's search...
1196 */
1197 ds_new = (*stackptr)->next;
1198 (*stackptr)->dirname = NULL;
1199 while (ds_new)
1200 {
1201 vim_free((*stackptr)->dirname);
1202 (*stackptr)->dirname = concat_fnames(ds_new->dirname, dirbuf,
1203 TRUE);
1204 if (mch_isdir((*stackptr)->dirname) == TRUE)
1205 break;
1206
1207 ds_new = ds_new->next;
1208 }
1209
1210 /* clean up all dirs we already left */
1211 while ((*stackptr)->next != ds_new)
1212 {
1213 ds_ptr = (*stackptr)->next;
1214 (*stackptr)->next = (*stackptr)->next->next;
1215 vim_free(ds_ptr->dirname);
1216 vim_free(ds_ptr);
1217 }
1218
1219 /* Nothing found -> it must be on top level */
1220 if (ds_new == NULL)
1221 {
1222 vim_free((*stackptr)->dirname);
1223 (*stackptr)->dirname = vim_strsave(dirbuf);
1224 }
1225 }
1226
1227 if ((*stackptr)->dirname != NULL)
1228 return (*stackptr)->dirname;
1229 else
1230 {
1231 ds_ptr = *stackptr;
1232 *stackptr = (*stackptr)->next;
1233 vim_free(ds_ptr);
1234 return NULL;
1235 }
1236}
1237
1238
1239/*
1240 * pop dirbuf from the directory stack and return previous directory or NULL if
1241 * stack is empty
1242 */
1243 static char_u *
1244qf_pop_dir(stackptr)
1245 struct dir_stack_T **stackptr;
1246{
1247 struct dir_stack_T *ds_ptr;
1248
1249 /* TODO: Should we check if dirbuf is the directory on top of the stack?
1250 * What to do if it isn't? */
1251
1252 /* pop top element and free it */
1253 if (*stackptr != NULL)
1254 {
1255 ds_ptr = *stackptr;
1256 *stackptr = (*stackptr)->next;
1257 vim_free(ds_ptr->dirname);
1258 vim_free(ds_ptr);
1259 }
1260
1261 /* return NEW top element as current dir or NULL if stack is empty*/
1262 return *stackptr ? (*stackptr)->dirname : NULL;
1263}
1264
1265/*
1266 * clean up directory stack
1267 */
1268 static void
1269qf_clean_dir_stack(stackptr)
1270 struct dir_stack_T **stackptr;
1271{
1272 struct dir_stack_T *ds_ptr;
1273
1274 while ((ds_ptr = *stackptr) != NULL)
1275 {
1276 *stackptr = (*stackptr)->next;
1277 vim_free(ds_ptr->dirname);
1278 vim_free(ds_ptr);
1279 }
1280}
1281
1282/*
1283 * Check in which directory of the directory stack the given file can be
1284 * found.
1285 * Returns a pointer to the directory name or NULL if not found
1286 * Cleans up intermediate directory entries.
1287 *
1288 * TODO: How to solve the following problem?
1289 * If we have the this directory tree:
1290 * ./
1291 * ./aa
1292 * ./aa/bb
1293 * ./bb
1294 * ./bb/x.c
1295 * and make says:
1296 * making all in aa
1297 * making all in bb
1298 * x.c:9: Error
1299 * Then qf_push_dir thinks we are in ./aa/bb, but we are in ./bb.
1300 * qf_guess_filepath will return NULL.
1301 */
1302 static char_u *
1303qf_guess_filepath(filename)
1304 char_u *filename;
1305{
1306 struct dir_stack_T *ds_ptr;
1307 struct dir_stack_T *ds_tmp;
1308 char_u *fullname;
1309
1310 /* no dirs on the stack - there's nothing we can do */
1311 if (dir_stack == NULL)
1312 return NULL;
1313
1314 ds_ptr = dir_stack->next;
1315 fullname = NULL;
1316 while (ds_ptr)
1317 {
1318 vim_free(fullname);
1319 fullname = concat_fnames(ds_ptr->dirname, filename, TRUE);
1320
1321 /* If concat_fnames failed, just go on. The worst thing that can happen
1322 * is that we delete the entire stack.
1323 */
1324 if ((fullname != NULL) && (mch_getperm(fullname) >= 0))
1325 break;
1326
1327 ds_ptr = ds_ptr->next;
1328 }
1329
1330 vim_free(fullname);
1331
1332 /* clean up all dirs we already left */
1333 while (dir_stack->next != ds_ptr)
1334 {
1335 ds_tmp = dir_stack->next;
1336 dir_stack->next = dir_stack->next->next;
1337 vim_free(ds_tmp->dirname);
1338 vim_free(ds_tmp);
1339 }
1340
1341 return ds_ptr==NULL? NULL: ds_ptr->dirname;
1342
1343}
1344
1345/*
1346 * jump to a quickfix line
1347 * if dir == FORWARD go "errornr" valid entries forward
1348 * if dir == BACKWARD go "errornr" valid entries backward
1349 * if dir == FORWARD_FILE go "errornr" valid entries files backward
1350 * if dir == BACKWARD_FILE go "errornr" valid entries files backward
1351 * else if "errornr" is zero, redisplay the same line
1352 * else go to entry "errornr"
1353 */
1354 void
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00001355qf_jump(qi, dir, errornr, forceit)
1356 qf_info_T *qi;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001357 int dir;
1358 int errornr;
1359 int forceit;
1360{
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001361 qf_info_T *ll_ref;
Bram Moolenaar68b76a62005-03-25 21:53:48 +00001362 qfline_T *qf_ptr;
1363 qfline_T *old_qf_ptr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001364 int qf_index;
1365 int old_qf_fnum;
1366 int old_qf_index;
1367 int prev_index;
1368 static char_u *e_no_more_items = (char_u *)N_("E553: No more items");
1369 char_u *err = e_no_more_items;
1370 linenr_T i;
1371 buf_T *old_curbuf;
1372 linenr_T old_lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001373 colnr_T screen_col;
1374 colnr_T char_col;
1375 char_u *line;
1376#ifdef FEAT_WINDOWS
Bram Moolenaar71fe80d2006-01-22 23:25:56 +00001377 char_u *old_swb = p_swb;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001378 int opened_window = FALSE;
1379 win_T *win;
1380 win_T *altwin;
1381#endif
1382 int print_message = TRUE;
1383 int len;
1384#ifdef FEAT_FOLDING
1385 int old_KeyTyped = KeyTyped; /* getting file may reset it */
1386#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001387 int ok = OK;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001388 int usable_win;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001389
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00001390 if (qi == NULL)
1391 qi = &ql_info;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001392
1393 if (qi->qf_curlist >= qi->qf_listcount
1394 || qi->qf_lists[qi->qf_curlist].qf_count == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001395 {
1396 EMSG(_(e_quickfix));
1397 return;
1398 }
1399
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001400 qf_ptr = qi->qf_lists[qi->qf_curlist].qf_ptr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001401 old_qf_ptr = qf_ptr;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001402 qf_index = qi->qf_lists[qi->qf_curlist].qf_index;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001403 old_qf_index = qf_index;
1404 if (dir == FORWARD || dir == FORWARD_FILE) /* next valid entry */
1405 {
1406 while (errornr--)
1407 {
1408 old_qf_ptr = qf_ptr;
1409 prev_index = qf_index;
1410 old_qf_fnum = qf_ptr->qf_fnum;
1411 do
1412 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001413 if (qf_index == qi->qf_lists[qi->qf_curlist].qf_count
Bram Moolenaar071d4272004-06-13 20:20:40 +00001414 || qf_ptr->qf_next == NULL)
1415 {
1416 qf_ptr = old_qf_ptr;
1417 qf_index = prev_index;
1418 if (err != NULL)
1419 {
1420 EMSG(_(err));
1421 goto theend;
1422 }
1423 errornr = 0;
1424 break;
1425 }
1426 ++qf_index;
1427 qf_ptr = qf_ptr->qf_next;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001428 } while ((!qi->qf_lists[qi->qf_curlist].qf_nonevalid
1429 && !qf_ptr->qf_valid)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001430 || (dir == FORWARD_FILE && qf_ptr->qf_fnum == old_qf_fnum));
1431 err = NULL;
1432 }
1433 }
1434 else if (dir == BACKWARD || dir == BACKWARD_FILE) /* prev. valid entry */
1435 {
1436 while (errornr--)
1437 {
1438 old_qf_ptr = qf_ptr;
1439 prev_index = qf_index;
1440 old_qf_fnum = qf_ptr->qf_fnum;
1441 do
1442 {
1443 if (qf_index == 1 || qf_ptr->qf_prev == NULL)
1444 {
1445 qf_ptr = old_qf_ptr;
1446 qf_index = prev_index;
1447 if (err != NULL)
1448 {
1449 EMSG(_(err));
1450 goto theend;
1451 }
1452 errornr = 0;
1453 break;
1454 }
1455 --qf_index;
1456 qf_ptr = qf_ptr->qf_prev;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001457 } while ((!qi->qf_lists[qi->qf_curlist].qf_nonevalid
1458 && !qf_ptr->qf_valid)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001459 || (dir == BACKWARD_FILE && qf_ptr->qf_fnum == old_qf_fnum));
1460 err = NULL;
1461 }
1462 }
1463 else if (errornr != 0) /* go to specified number */
1464 {
1465 while (errornr < qf_index && qf_index > 1 && qf_ptr->qf_prev != NULL)
1466 {
1467 --qf_index;
1468 qf_ptr = qf_ptr->qf_prev;
1469 }
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001470 while (errornr > qf_index && qf_index <
1471 qi->qf_lists[qi->qf_curlist].qf_count
Bram Moolenaar071d4272004-06-13 20:20:40 +00001472 && qf_ptr->qf_next != NULL)
1473 {
1474 ++qf_index;
1475 qf_ptr = qf_ptr->qf_next;
1476 }
1477 }
1478
1479#ifdef FEAT_WINDOWS
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001480 qi->qf_lists[qi->qf_curlist].qf_index = qf_index;
1481 if (qf_win_pos_update(qi, old_qf_index))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001482 /* No need to print the error message if it's visible in the error
1483 * window */
1484 print_message = FALSE;
1485
1486 /*
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001487 * For ":helpgrep" find a help window or open one.
1488 */
Bram Moolenaar80a94a52006-02-23 21:26:58 +00001489 if (qf_ptr->qf_type == 1 && (!curwin->w_buffer->b_help || cmdmod.tab != 0))
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001490 {
1491 win_T *wp;
1492 int n;
1493
Bram Moolenaar80a94a52006-02-23 21:26:58 +00001494 if (cmdmod.tab != 0)
1495 wp = NULL;
1496 else
1497 for (wp = firstwin; wp != NULL; wp = wp->w_next)
1498 if (wp->w_buffer != NULL && wp->w_buffer->b_help)
1499 break;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001500 if (wp != NULL && wp->w_buffer->b_nwindows > 0)
1501 win_enter(wp, TRUE);
1502 else
1503 {
1504 /*
1505 * Split off help window; put it at far top if no position
1506 * specified, the current window is vertically split and narrow.
1507 */
1508 n = WSP_HELP;
1509# ifdef FEAT_VERTSPLIT
1510 if (cmdmod.split == 0 && curwin->w_width != Columns
1511 && curwin->w_width < 80)
1512 n |= WSP_TOP;
1513# endif
1514 if (win_split(0, n) == FAIL)
1515 goto theend;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00001516 opened_window = TRUE; /* close it when fail */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001517
1518 if (curwin->w_height < p_hh)
1519 win_setheight((int)p_hh);
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00001520
1521 if (qi != &ql_info) /* not a quickfix list */
1522 {
1523 /* The new window should use the supplied location list */
1524 qf_free_all(curwin);
1525 curwin->w_llist = qi;
1526 qi->qf_refcount++;
1527 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001528 }
1529
1530 if (!p_im)
1531 restart_edit = 0; /* don't want insert mode in help file */
1532 }
1533
1534 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +00001535 * If currently in the quickfix window, find another window to show the
1536 * file in.
1537 */
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00001538 if (bt_quickfix(curbuf) && !opened_window)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001539 {
1540 /*
1541 * If there is no file specified, we don't know where to go.
1542 * But do advance, otherwise ":cn" gets stuck.
1543 */
1544 if (qf_ptr->qf_fnum == 0)
1545 goto theend;
1546
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001547 /* Locate a window showing a normal buffer */
1548 usable_win = 0;
1549 FOR_ALL_WINDOWS(win)
1550 if (win->w_buffer->b_p_bt[0] == NUL)
1551 {
1552 usable_win = 1;
1553 break;
1554 }
1555
Bram Moolenaar071d4272004-06-13 20:20:40 +00001556 /*
1557 * If there is only one window, create a new one above the quickfix
1558 * window.
1559 */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001560 if (firstwin == lastwin || !usable_win)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001561 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001562 ll_ref = curwin->w_llist_ref;
1563
Bram Moolenaar071d4272004-06-13 20:20:40 +00001564 if (win_split(0, WSP_ABOVE) == FAIL)
1565 goto failed; /* not enough room for window */
1566 opened_window = TRUE; /* close it when fail */
1567 p_swb = empty_option; /* don't split again */
1568# ifdef FEAT_SCROLLBIND
1569 curwin->w_p_scb = FALSE;
1570# endif
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001571 if (ll_ref != NULL)
1572 {
1573 /* The new window should use the location list from the
1574 * location list window */
1575 qf_free_all(curwin);
1576 curwin->w_llist = ll_ref;
1577 ll_ref->qf_refcount++;
1578 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001579 }
1580 else
1581 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001582 if (curwin->w_llist_ref != NULL)
1583 {
1584 /* In a location window */
1585 ll_ref = curwin->w_llist_ref;
1586
1587 /* Find the window with the same location list */
1588 FOR_ALL_WINDOWS(win)
1589 if (win->w_llist == ll_ref)
1590 break;
1591 if (win == NULL)
1592 {
1593 /* Find the window showing the selected file */
1594 FOR_ALL_WINDOWS(win)
1595 if (win->w_buffer->b_fnum == qf_ptr->qf_fnum)
1596 break;
1597 if (win == NULL)
1598 {
1599 /* Find a previous usable window */
1600 win = curwin;
1601 do
1602 {
1603 if (win->w_buffer->b_p_bt[0] == NUL)
1604 break;
1605 if (win->w_prev == NULL)
1606 win = lastwin; /* wrap around the top */
1607 else
1608 win = win->w_prev; /* go to previous window */
1609 } while (win != curwin);
1610 }
1611 }
1612 win_goto(win);
1613
1614 /* If the location list for the window is not set, then set it
1615 * to the location list from the location window */
1616 if (win->w_llist == NULL)
1617 {
1618 win->w_llist = ll_ref;
1619 ll_ref->qf_refcount++;
1620 }
1621 }
1622 else
1623 {
1624
Bram Moolenaar071d4272004-06-13 20:20:40 +00001625 /*
1626 * Try to find a window that shows the right buffer.
1627 * Default to the window just above the quickfix buffer.
1628 */
1629 win = curwin;
1630 altwin = NULL;
1631 for (;;)
1632 {
1633 if (win->w_buffer->b_fnum == qf_ptr->qf_fnum)
1634 break;
1635 if (win->w_prev == NULL)
1636 win = lastwin; /* wrap around the top */
1637 else
1638 win = win->w_prev; /* go to previous window */
1639
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001640 if (IS_QF_WINDOW(win))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001641 {
1642 /* Didn't find it, go to the window before the quickfix
1643 * window. */
1644 if (altwin != NULL)
1645 win = altwin;
1646 else if (curwin->w_prev != NULL)
1647 win = curwin->w_prev;
1648 else
1649 win = curwin->w_next;
1650 break;
1651 }
1652
1653 /* Remember a usable window. */
1654 if (altwin == NULL && !win->w_p_pvw
1655 && win->w_buffer->b_p_bt[0] == NUL)
1656 altwin = win;
1657 }
1658
1659 win_goto(win);
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001660 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001661 }
1662 }
1663#endif
1664
1665 /*
1666 * If there is a file name,
1667 * read the wanted file if needed, and check autowrite etc.
1668 */
1669 old_curbuf = curbuf;
1670 old_lnum = curwin->w_cursor.lnum;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001671
1672 if (qf_ptr->qf_fnum != 0)
1673 {
1674 if (qf_ptr->qf_type == 1)
1675 {
1676 /* Open help file (do_ecmd() will set b_help flag, readfile() will
1677 * set b_p_ro flag). */
1678 if (!can_abandon(curbuf, forceit))
1679 {
1680 EMSG(_(e_nowrtmsg));
1681 ok = FALSE;
1682 }
1683 else
1684 ok = do_ecmd(qf_ptr->qf_fnum, NULL, NULL, NULL, (linenr_T)1,
1685 ECMD_HIDE + ECMD_SET_HELP);
1686 }
1687 else
1688 ok = buflist_getfile(qf_ptr->qf_fnum,
1689 (linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit);
1690 }
1691
1692 if (ok == OK)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001693 {
1694 /* When not switched to another buffer, still need to set pc mark */
1695 if (curbuf == old_curbuf)
1696 setpcmark();
1697
Bram Moolenaar68b76a62005-03-25 21:53:48 +00001698 if (qf_ptr->qf_pattern == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001699 {
Bram Moolenaar68b76a62005-03-25 21:53:48 +00001700 /*
1701 * Go to line with error, unless qf_lnum is 0.
1702 */
1703 i = qf_ptr->qf_lnum;
1704 if (i > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001705 {
Bram Moolenaar68b76a62005-03-25 21:53:48 +00001706 if (i > curbuf->b_ml.ml_line_count)
1707 i = curbuf->b_ml.ml_line_count;
1708 curwin->w_cursor.lnum = i;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001709 }
Bram Moolenaar68b76a62005-03-25 21:53:48 +00001710 if (qf_ptr->qf_col > 0)
1711 {
1712 curwin->w_cursor.col = qf_ptr->qf_col - 1;
1713 if (qf_ptr->qf_viscol == TRUE)
1714 {
1715 /*
1716 * Check each character from the beginning of the error
1717 * line up to the error column. For each tab character
1718 * found, reduce the error column value by the length of
1719 * a tab character.
1720 */
1721 line = ml_get_curline();
1722 screen_col = 0;
1723 for (char_col = 0; char_col < curwin->w_cursor.col; ++char_col)
1724 {
1725 if (*line == NUL)
1726 break;
1727 if (*line++ == '\t')
1728 {
1729 curwin->w_cursor.col -= 7 - (screen_col % 8);
1730 screen_col += 8 - (screen_col % 8);
1731 }
1732 else
1733 ++screen_col;
1734 }
1735 }
1736 check_cursor();
1737 }
1738 else
1739 beginline(BL_WHITE | BL_FIX);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001740 }
1741 else
Bram Moolenaar68b76a62005-03-25 21:53:48 +00001742 {
1743 pos_T save_cursor;
1744
1745 /* Move the cursor to the first line in the buffer */
1746 save_cursor = curwin->w_cursor;
1747 curwin->w_cursor.lnum = 0;
1748 if (!do_search(NULL, '/', qf_ptr->qf_pattern, (long)1, SEARCH_KEEP))
1749 curwin->w_cursor = save_cursor;
1750 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001751
1752#ifdef FEAT_FOLDING
1753 if ((fdo_flags & FDO_QUICKFIX) && old_KeyTyped)
1754 foldOpenCursor();
1755#endif
1756 if (print_message)
1757 {
1758 /* Update the screen before showing the message */
1759 update_topline_redraw();
1760 sprintf((char *)IObuff, _("(%d of %d)%s%s: "), qf_index,
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001761 qi->qf_lists[qi->qf_curlist].qf_count,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001762 qf_ptr->qf_cleared ? _(" (line deleted)") : "",
1763 (char *)qf_types(qf_ptr->qf_type, qf_ptr->qf_nr));
1764 /* Add the message, skipping leading whitespace and newlines. */
1765 len = (int)STRLEN(IObuff);
1766 qf_fmt_text(skipwhite(qf_ptr->qf_text), IObuff + len, IOSIZE - len);
1767
1768 /* Output the message. Overwrite to avoid scrolling when the 'O'
1769 * flag is present in 'shortmess'; But when not jumping, print the
1770 * whole message. */
1771 i = msg_scroll;
1772 if (curbuf == old_curbuf && curwin->w_cursor.lnum == old_lnum)
1773 msg_scroll = TRUE;
1774 else if (!msg_scrolled && shortmess(SHM_OVERALL))
1775 msg_scroll = FALSE;
1776 msg_attr_keep(IObuff, 0, TRUE);
1777 msg_scroll = i;
1778 }
1779 }
1780 else
1781 {
1782#ifdef FEAT_WINDOWS
1783 if (opened_window)
1784 win_close(curwin, TRUE); /* Close opened window */
1785#endif
1786 if (qf_ptr->qf_fnum != 0)
1787 {
1788 /*
1789 * Couldn't open file, so put index back where it was. This could
1790 * happen if the file was readonly and we changed something.
1791 */
1792#ifdef FEAT_WINDOWS
1793failed:
1794#endif
1795 qf_ptr = old_qf_ptr;
1796 qf_index = old_qf_index;
1797 }
1798 }
1799theend:
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001800 qi->qf_lists[qi->qf_curlist].qf_ptr = qf_ptr;
1801 qi->qf_lists[qi->qf_curlist].qf_index = qf_index;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001802#ifdef FEAT_WINDOWS
1803 if (p_swb != old_swb && opened_window)
1804 {
1805 /* Restore old 'switchbuf' value, but not when an autocommand or
1806 * modeline has changed the value. */
1807 if (p_swb == empty_option)
1808 p_swb = old_swb;
1809 else
1810 free_string_option(old_swb);
1811 }
1812#endif
1813}
1814
1815/*
1816 * ":clist": list all errors
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001817 * ":llist": list all locations
Bram Moolenaar071d4272004-06-13 20:20:40 +00001818 */
1819 void
1820qf_list(eap)
1821 exarg_T *eap;
1822{
Bram Moolenaar68b76a62005-03-25 21:53:48 +00001823 buf_T *buf;
1824 char_u *fname;
1825 qfline_T *qfp;
1826 int i;
1827 int idx1 = 1;
1828 int idx2 = -1;
1829 int need_return = TRUE;
Bram Moolenaar68b76a62005-03-25 21:53:48 +00001830 char_u *arg = eap->arg;
1831 int all = eap->forceit; /* if not :cl!, only show
Bram Moolenaar071d4272004-06-13 20:20:40 +00001832 recognised errors */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001833 qf_info_T *qi = &ql_info;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001834
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001835 if (eap->cmdidx == CMD_llist)
1836 {
1837 qi = GET_LOC_LIST(curwin);
1838 if (qi == NULL)
1839 {
1840 EMSG(_(e_loclist));
1841 return;
1842 }
1843 }
1844
1845 if (qi->qf_curlist >= qi->qf_listcount
1846 || qi->qf_lists[qi->qf_curlist].qf_count == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001847 {
1848 EMSG(_(e_quickfix));
1849 return;
1850 }
1851 if (!get_list_range(&arg, &idx1, &idx2) || *arg != NUL)
1852 {
1853 EMSG(_(e_trailing));
1854 return;
1855 }
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001856 i = qi->qf_lists[qi->qf_curlist].qf_count;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001857 if (idx1 < 0)
1858 idx1 = (-idx1 > i) ? 0 : idx1 + i + 1;
1859 if (idx2 < 0)
1860 idx2 = (-idx2 > i) ? 0 : idx2 + i + 1;
1861
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001862 if (qi->qf_lists[qi->qf_curlist].qf_nonevalid)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001863 all = TRUE;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001864 qfp = qi->qf_lists[qi->qf_curlist].qf_start;
1865 for (i = 1; !got_int && i <= qi->qf_lists[qi->qf_curlist].qf_count; )
Bram Moolenaar071d4272004-06-13 20:20:40 +00001866 {
1867 if ((qfp->qf_valid || all) && idx1 <= i && i <= idx2)
1868 {
1869 if (need_return)
1870 {
1871 msg_putchar('\n');
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001872 if (got_int)
1873 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001874 need_return = FALSE;
1875 }
Bram Moolenaar68b76a62005-03-25 21:53:48 +00001876
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001877 fname = NULL;
1878 if (qfp->qf_fnum != 0
1879 && (buf = buflist_findnr(qfp->qf_fnum)) != NULL)
1880 {
1881 fname = buf->b_fname;
1882 if (qfp->qf_type == 1) /* :helpgrep */
1883 fname = gettail(fname);
1884 }
1885 if (fname == NULL)
1886 sprintf((char *)IObuff, "%2d", i);
1887 else
1888 vim_snprintf((char *)IObuff, IOSIZE, "%2d %s",
1889 i, (char *)fname);
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001890 msg_outtrans_attr(IObuff, i == qi->qf_lists[qi->qf_curlist].qf_index
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001891 ? hl_attr(HLF_L) : hl_attr(HLF_D));
1892 if (qfp->qf_lnum == 0)
1893 IObuff[0] = NUL;
1894 else if (qfp->qf_col == 0)
1895 sprintf((char *)IObuff, ":%ld", qfp->qf_lnum);
1896 else
1897 sprintf((char *)IObuff, ":%ld col %d",
1898 qfp->qf_lnum, qfp->qf_col);
1899 sprintf((char *)IObuff + STRLEN(IObuff), "%s:",
1900 (char *)qf_types(qfp->qf_type, qfp->qf_nr));
1901 msg_puts_attr(IObuff, hl_attr(HLF_N));
1902 if (qfp->qf_pattern != NULL)
1903 {
1904 qf_fmt_text(qfp->qf_pattern, IObuff, IOSIZE);
1905 STRCAT(IObuff, ":");
1906 msg_puts(IObuff);
1907 }
1908 msg_puts((char_u *)" ");
1909
1910 /* Remove newlines and leading whitespace from the text. For an
1911 * unrecognized line keep the indent, the compiler may mark a word
1912 * with ^^^^. */
1913 qf_fmt_text((fname != NULL || qfp->qf_lnum != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001914 ? skipwhite(qfp->qf_text) : qfp->qf_text,
1915 IObuff, IOSIZE);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001916 msg_prt_line(IObuff, FALSE);
1917 out_flush(); /* show one line at a time */
1918 need_return = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001919 }
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001920
1921 qfp = qfp->qf_next;
1922 ++i;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001923 ui_breakcheck();
1924 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001925}
1926
1927/*
1928 * Remove newlines and leading whitespace from an error message.
1929 * Put the result in "buf[bufsize]".
1930 */
1931 static void
1932qf_fmt_text(text, buf, bufsize)
1933 char_u *text;
1934 char_u *buf;
1935 int bufsize;
1936{
1937 int i;
1938 char_u *p = text;
1939
1940 for (i = 0; *p != NUL && i < bufsize - 1; ++i)
1941 {
1942 if (*p == '\n')
1943 {
1944 buf[i] = ' ';
1945 while (*++p != NUL)
1946 if (!vim_iswhite(*p) && *p != '\n')
1947 break;
1948 }
1949 else
1950 buf[i] = *p++;
1951 }
1952 buf[i] = NUL;
1953}
1954
1955/*
1956 * ":colder [count]": Up in the quickfix stack.
1957 * ":cnewer [count]": Down in the quickfix stack.
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001958 * ":lolder [count]": Up in the location list stack.
1959 * ":lnewer [count]": Down in the location list stack.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001960 */
1961 void
1962qf_age(eap)
1963 exarg_T *eap;
1964{
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001965 qf_info_T *qi = &ql_info;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001966 int count;
1967
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001968 if (eap->cmdidx == CMD_lolder || eap->cmdidx == CMD_lnewer)
1969 {
1970 qi = GET_LOC_LIST(curwin);
1971 if (qi == NULL)
1972 {
1973 EMSG(_(e_loclist));
1974 return;
1975 }
1976 }
1977
Bram Moolenaar071d4272004-06-13 20:20:40 +00001978 if (eap->addr_count != 0)
1979 count = eap->line2;
1980 else
1981 count = 1;
1982 while (count--)
1983 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001984 if (eap->cmdidx == CMD_colder || eap->cmdidx == CMD_lolder)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001985 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001986 if (qi->qf_curlist == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001987 {
1988 EMSG(_("E380: At bottom of quickfix stack"));
1989 return;
1990 }
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001991 --qi->qf_curlist;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001992 }
1993 else
1994 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001995 if (qi->qf_curlist >= qi->qf_listcount - 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001996 {
1997 EMSG(_("E381: At top of quickfix stack"));
1998 return;
1999 }
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002000 ++qi->qf_curlist;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002001 }
2002 }
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002003 qf_msg(qi);
2004
Bram Moolenaar071d4272004-06-13 20:20:40 +00002005}
2006
2007 static void
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002008qf_msg(qi)
2009 qf_info_T *qi;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002010{
2011 smsg((char_u *)_("error list %d of %d; %d errors"),
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002012 qi->qf_curlist + 1, qi->qf_listcount,
2013 qi->qf_lists[qi->qf_curlist].qf_count);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002014#ifdef FEAT_WINDOWS
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002015 qf_update_buffer(qi);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002016#endif
2017}
2018
2019/*
Bram Moolenaar77197e42005-12-08 22:00:22 +00002020 * Free error list "idx".
Bram Moolenaar071d4272004-06-13 20:20:40 +00002021 */
2022 static void
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002023qf_free(qi, idx)
2024 qf_info_T *qi;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002025 int idx;
2026{
Bram Moolenaar68b76a62005-03-25 21:53:48 +00002027 qfline_T *qfp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002028
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002029 while (qi->qf_lists[idx].qf_count)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002030 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002031 qfp = qi->qf_lists[idx].qf_start->qf_next;
2032 vim_free(qi->qf_lists[idx].qf_start->qf_text);
2033 vim_free(qi->qf_lists[idx].qf_start->qf_pattern);
2034 vim_free(qi->qf_lists[idx].qf_start);
2035 qi->qf_lists[idx].qf_start = qfp;
2036 --qi->qf_lists[idx].qf_count;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002037 }
2038}
2039
2040/*
2041 * qf_mark_adjust: adjust marks
2042 */
2043 void
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002044qf_mark_adjust(wp, line1, line2, amount, amount_after)
2045 win_T *wp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002046 linenr_T line1;
2047 linenr_T line2;
2048 long amount;
2049 long amount_after;
2050{
Bram Moolenaar68b76a62005-03-25 21:53:48 +00002051 int i;
2052 qfline_T *qfp;
2053 int idx;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002054 qf_info_T *qi = &ql_info;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002055
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002056 if (wp != NULL)
2057 {
2058 if (wp->w_llist == NULL)
2059 return;
2060 qi = wp->w_llist;
2061 }
2062
2063 for (idx = 0; idx < qi->qf_listcount; ++idx)
2064 if (qi->qf_lists[idx].qf_count)
2065 for (i = 0, qfp = qi->qf_lists[idx].qf_start;
2066 i < qi->qf_lists[idx].qf_count; ++i, qfp = qfp->qf_next)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002067 if (qfp->qf_fnum == curbuf->b_fnum)
2068 {
2069 if (qfp->qf_lnum >= line1 && qfp->qf_lnum <= line2)
2070 {
2071 if (amount == MAXLNUM)
2072 qfp->qf_cleared = TRUE;
2073 else
2074 qfp->qf_lnum += amount;
2075 }
2076 else if (amount_after && qfp->qf_lnum > line2)
2077 qfp->qf_lnum += amount_after;
2078 }
2079}
2080
2081/*
2082 * Make a nice message out of the error character and the error number:
2083 * char number message
2084 * e or E 0 " error"
2085 * w or W 0 " warning"
2086 * i or I 0 " info"
2087 * 0 0 ""
2088 * other 0 " c"
2089 * e or E n " error n"
2090 * w or W n " warning n"
2091 * i or I n " info n"
2092 * 0 n " error n"
2093 * other n " c n"
2094 * 1 x "" :helpgrep
2095 */
2096 static char_u *
2097qf_types(c, nr)
2098 int c, nr;
2099{
2100 static char_u buf[20];
2101 static char_u cc[3];
2102 char_u *p;
2103
2104 if (c == 'W' || c == 'w')
2105 p = (char_u *)" warning";
2106 else if (c == 'I' || c == 'i')
2107 p = (char_u *)" info";
2108 else if (c == 'E' || c == 'e' || (c == 0 && nr > 0))
2109 p = (char_u *)" error";
2110 else if (c == 0 || c == 1)
2111 p = (char_u *)"";
2112 else
2113 {
2114 cc[0] = ' ';
2115 cc[1] = c;
2116 cc[2] = NUL;
2117 p = cc;
2118 }
2119
2120 if (nr <= 0)
2121 return p;
2122
2123 sprintf((char *)buf, "%s %3d", (char *)p, nr);
2124 return buf;
2125}
2126
2127#if defined(FEAT_WINDOWS) || defined(PROTO)
2128/*
2129 * ":cwindow": open the quickfix window if we have errors to display,
2130 * close it if not.
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002131 * ":lwindow": open the location list window if we have locations to display,
2132 * close it if not.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002133 */
2134 void
2135ex_cwindow(eap)
2136 exarg_T *eap;
2137{
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002138 qf_info_T *qi = &ql_info;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002139 win_T *win;
2140
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002141 if (eap->cmdidx == CMD_lwindow)
2142 {
2143 qi = GET_LOC_LIST(curwin);
2144 if (qi == NULL)
2145 return;
2146 }
2147
2148 /* Look for an existing quickfix window. */
2149 win = qf_find_win(qi);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002150
2151 /*
2152 * If a quickfix window is open but we have no errors to display,
2153 * close the window. If a quickfix window is not open, then open
2154 * it if we have errors; otherwise, leave it closed.
2155 */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002156 if (qi->qf_lists[qi->qf_curlist].qf_nonevalid
Bram Moolenaard68071d2006-05-02 22:08:30 +00002157 || qi->qf_curlist >= qi->qf_listcount)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002158 {
2159 if (win != NULL)
2160 ex_cclose(eap);
2161 }
2162 else if (win == NULL)
2163 ex_copen(eap);
2164}
2165
2166/*
2167 * ":cclose": close the window showing the list of errors.
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002168 * ":lclose": close the window showing the location list
Bram Moolenaar071d4272004-06-13 20:20:40 +00002169 */
2170/*ARGSUSED*/
2171 void
2172ex_cclose(eap)
2173 exarg_T *eap;
2174{
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002175 win_T *win = NULL;
2176 qf_info_T *qi = &ql_info;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002177
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002178 if (eap->cmdidx == CMD_lclose || eap->cmdidx == CMD_lwindow)
2179 {
2180 qi = GET_LOC_LIST(curwin);
2181 if (qi == NULL)
2182 return;
2183 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002184
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002185 /* Find existing quickfix window and close it. */
2186 win = qf_find_win(qi);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002187 if (win != NULL)
2188 win_close(win, FALSE);
2189}
2190
2191/*
2192 * ":copen": open a window that shows the list of errors.
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002193 * ":lopen": open a window that shows the location list.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002194 */
2195 void
2196ex_copen(eap)
2197 exarg_T *eap;
2198{
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002199 qf_info_T *qi = &ql_info;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002200 int height;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002201 win_T *win;
Bram Moolenaar80a94a52006-02-23 21:26:58 +00002202 tabpage_T *prevtab = curtab;
Bram Moolenaar9c102382006-05-03 21:26:49 +00002203 buf_T *qf_buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002204
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002205 if (eap->cmdidx == CMD_lopen || eap->cmdidx == CMD_lwindow)
2206 {
2207 qi = GET_LOC_LIST(curwin);
2208 if (qi == NULL)
2209 {
2210 EMSG(_(e_loclist));
2211 return;
2212 }
2213 }
2214
Bram Moolenaar071d4272004-06-13 20:20:40 +00002215 if (eap->addr_count != 0)
2216 height = eap->line2;
2217 else
2218 height = QF_WINHEIGHT;
2219
2220#ifdef FEAT_VISUAL
2221 reset_VIsual_and_resel(); /* stop Visual mode */
2222#endif
2223#ifdef FEAT_GUI
2224 need_mouse_correct = TRUE;
2225#endif
2226
2227 /*
2228 * Find existing quickfix window, or open a new one.
2229 */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002230 win = qf_find_win(qi);
2231
Bram Moolenaar80a94a52006-02-23 21:26:58 +00002232 if (win != NULL && cmdmod.tab == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002233 win_goto(win);
2234 else
2235 {
Bram Moolenaar9c102382006-05-03 21:26:49 +00002236 qf_buf = qf_find_buf(qi);
2237
Bram Moolenaar071d4272004-06-13 20:20:40 +00002238 /* The current window becomes the previous window afterwards. */
2239 win = curwin;
2240
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002241 if (eap->cmdidx == CMD_copen || eap->cmdidx == CMD_cwindow)
2242 /* Create the new window at the very bottom. */
2243 win_goto(lastwin);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002244 if (win_split(height, WSP_BELOW) == FAIL)
2245 return; /* not enough room for window */
2246#ifdef FEAT_SCROLLBIND
2247 curwin->w_p_scb = FALSE;
2248#endif
2249
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002250 /* Remove the location list for the quickfix window */
2251 qf_free_all(curwin);
2252
2253 if (eap->cmdidx == CMD_lopen || eap->cmdidx == CMD_lwindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002254 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002255 /*
2256 * For the location list window, create a reference to the
2257 * location list from the window 'win'.
2258 */
2259 curwin->w_llist_ref = win->w_llist;
2260 win->w_llist->qf_refcount++;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002261 }
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002262
Bram Moolenaar9c102382006-05-03 21:26:49 +00002263 if (qf_buf != NULL)
2264 /* Use the existing quickfix buffer */
2265 (void)do_ecmd(qf_buf->b_fnum, NULL, NULL, NULL, ECMD_ONE,
2266 ECMD_HIDE + ECMD_OLDBUF);
2267 else
2268 {
2269 /* Create a new quickfix buffer */
2270 (void)do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE);
2271 /* switch off 'swapfile' */
2272 set_option_value((char_u *)"swf", 0L, NULL, OPT_LOCAL);
2273 set_option_value((char_u *)"bt", 0L, (char_u *)"quickfix",
Bram Moolenaar838bb712006-03-11 21:24:08 +00002274 OPT_LOCAL);
Bram Moolenaar9c102382006-05-03 21:26:49 +00002275 set_option_value((char_u *)"bh", 0L, (char_u *)"wipe", OPT_LOCAL);
2276 set_option_value((char_u *)"diff", 0L, (char_u *)"", OPT_LOCAL);
2277 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002278
Bram Moolenaar80a94a52006-02-23 21:26:58 +00002279 /* Only set the height when still in the same tab page and there is no
2280 * window to the side. */
2281 if (curtab == prevtab
Bram Moolenaar383f9bc2005-01-19 22:18:32 +00002282#ifdef FEAT_VERTSPLIT
Bram Moolenaar80a94a52006-02-23 21:26:58 +00002283 && curwin->w_width == Columns
Bram Moolenaar383f9bc2005-01-19 22:18:32 +00002284#endif
Bram Moolenaar80a94a52006-02-23 21:26:58 +00002285 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00002286 win_setheight(height);
2287 curwin->w_p_wfh = TRUE; /* set 'winfixheight' */
2288 if (win_valid(win))
2289 prevwin = win;
2290 }
2291
2292 /*
2293 * Fill the buffer with the quickfix list.
2294 */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002295 qf_fill_buffer(qi);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002296
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002297 curwin->w_cursor.lnum = qi->qf_lists[qi->qf_curlist].qf_index;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002298 curwin->w_cursor.col = 0;
2299 check_cursor();
2300 update_topline(); /* scroll to show the line */
2301}
2302
2303/*
2304 * Return the number of the current entry (line number in the quickfix
2305 * window).
2306 */
2307 linenr_T
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002308qf_current_entry(wp)
2309 win_T *wp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002310{
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002311 qf_info_T *qi = &ql_info;
2312
2313 if (IS_LL_WINDOW(wp))
2314 /* In the location list window, use the referenced location list */
2315 qi = wp->w_llist_ref;
2316
2317 return qi->qf_lists[qi->qf_curlist].qf_index;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002318}
2319
2320/*
2321 * Update the cursor position in the quickfix window to the current error.
2322 * Return TRUE if there is a quickfix window.
2323 */
2324 static int
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002325qf_win_pos_update(qi, old_qf_index)
2326 qf_info_T *qi;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002327 int old_qf_index; /* previous qf_index or zero */
2328{
2329 win_T *win;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002330 int qf_index = qi->qf_lists[qi->qf_curlist].qf_index;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002331
2332 /*
2333 * Put the cursor on the current error in the quickfix window, so that
2334 * it's viewable.
2335 */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002336 win = qf_find_win(qi);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002337 if (win != NULL
2338 && qf_index <= win->w_buffer->b_ml.ml_line_count
2339 && old_qf_index != qf_index)
2340 {
2341 win_T *old_curwin = curwin;
2342
2343 curwin = win;
2344 curbuf = win->w_buffer;
2345 if (qf_index > old_qf_index)
2346 {
2347 curwin->w_redraw_top = old_qf_index;
2348 curwin->w_redraw_bot = qf_index;
2349 }
2350 else
2351 {
2352 curwin->w_redraw_top = qf_index;
2353 curwin->w_redraw_bot = old_qf_index;
2354 }
2355 curwin->w_cursor.lnum = qf_index;
2356 curwin->w_cursor.col = 0;
2357 update_topline(); /* scroll to show the line */
2358 redraw_later(VALID);
2359 curwin->w_redr_status = TRUE; /* update ruler */
2360 curwin = old_curwin;
2361 curbuf = curwin->w_buffer;
2362 }
2363 return win != NULL;
2364}
2365
2366/*
Bram Moolenaar9c102382006-05-03 21:26:49 +00002367 * Check whether the given window is displaying the specified quickfix/location
2368 * list buffer
2369 */
2370 static int
2371is_qf_win(win, qi)
2372 win_T *win;
2373 qf_info_T *qi;
2374{
2375 /*
2376 * A window displaying the quickfix buffer will have the w_llist_ref field
2377 * set to NULL.
2378 * A window displaying a location list buffer will have the w_llist_ref
2379 * pointing to the location list.
2380 */
2381 if (bt_quickfix(win->w_buffer))
2382 if ((qi == &ql_info && win->w_llist_ref == NULL)
2383 || (qi != &ql_info && win->w_llist_ref == qi))
2384 return TRUE;
2385
2386 return FALSE;
2387}
2388
2389/*
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002390 * Find a window displaying the quickfix/location list 'qi'
Bram Moolenaar9c102382006-05-03 21:26:49 +00002391 * Searches in only the windows opened in the current tab.
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002392 */
2393 static win_T *
2394qf_find_win(qi)
2395 qf_info_T *qi;
2396{
2397 win_T *win;
2398
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002399 FOR_ALL_WINDOWS(win)
Bram Moolenaar9c102382006-05-03 21:26:49 +00002400 if (is_qf_win(win, qi))
2401 break;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002402
2403 return win;
2404}
2405
2406/*
Bram Moolenaar9c102382006-05-03 21:26:49 +00002407 * Find a quickfix buffer.
2408 * Searches in windows opened in all the tabs.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002409 */
2410 static buf_T *
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002411qf_find_buf(qi)
2412 qf_info_T *qi;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002413{
Bram Moolenaar9c102382006-05-03 21:26:49 +00002414 tabpage_T *tp;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002415 win_T *win;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002416
Bram Moolenaar9c102382006-05-03 21:26:49 +00002417 FOR_ALL_TAB_WINDOWS(tp, win)
2418 if (is_qf_win(win, qi))
2419 return win->w_buffer;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002420
Bram Moolenaar9c102382006-05-03 21:26:49 +00002421 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002422}
2423
2424/*
2425 * Find the quickfix buffer. If it exists, update the contents.
2426 */
2427 static void
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002428qf_update_buffer(qi)
2429 qf_info_T *qi;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002430{
2431 buf_T *buf;
2432#ifdef FEAT_AUTOCMD
2433 aco_save_T aco;
2434#else
2435 buf_T *save_curbuf;
2436#endif
2437
2438 /* Check if a buffer for the quickfix list exists. Update it. */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002439 buf = qf_find_buf(qi);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002440 if (buf != NULL)
2441 {
2442#ifdef FEAT_AUTOCMD
2443 /* set curwin/curbuf to buf and save a few things */
2444 aucmd_prepbuf(&aco, buf);
2445#else
2446 save_curbuf = curbuf;
2447 curbuf = buf;
2448#endif
2449
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002450 qf_fill_buffer(qi);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002451
2452#ifdef FEAT_AUTOCMD
2453 /* restore curwin/curbuf and a few other things */
2454 aucmd_restbuf(&aco);
2455#else
2456 curbuf = save_curbuf;
2457#endif
2458
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002459 (void)qf_win_pos_update(qi, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002460 }
2461}
2462
2463/*
2464 * Fill current buffer with quickfix errors, replacing any previous contents.
2465 * curbuf must be the quickfix buffer!
2466 */
2467 static void
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002468qf_fill_buffer(qi)
2469 qf_info_T *qi;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002470{
Bram Moolenaar68b76a62005-03-25 21:53:48 +00002471 linenr_T lnum;
2472 qfline_T *qfp;
2473 buf_T *errbuf;
2474 int len;
2475 int old_KeyTyped = KeyTyped;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002476
2477 /* delete all existing lines */
2478 while ((curbuf->b_ml.ml_flags & ML_EMPTY) == 0)
2479 (void)ml_delete((linenr_T)1, FALSE);
2480
2481 /* Check if there is anything to display */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002482 if (qi->qf_curlist < qi->qf_listcount)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002483 {
2484 /* Add one line for each error */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002485 qfp = qi->qf_lists[qi->qf_curlist].qf_start;
2486 for (lnum = 0; lnum < qi->qf_lists[qi->qf_curlist].qf_count; ++lnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002487 {
2488 if (qfp->qf_fnum != 0
2489 && (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL
2490 && errbuf->b_fname != NULL)
2491 {
2492 if (qfp->qf_type == 1) /* :helpgrep */
2493 STRCPY(IObuff, gettail(errbuf->b_fname));
2494 else
2495 STRCPY(IObuff, errbuf->b_fname);
2496 len = (int)STRLEN(IObuff);
2497 }
2498 else
2499 len = 0;
2500 IObuff[len++] = '|';
2501
2502 if (qfp->qf_lnum > 0)
2503 {
2504 sprintf((char *)IObuff + len, "%ld", qfp->qf_lnum);
2505 len += (int)STRLEN(IObuff + len);
2506
2507 if (qfp->qf_col > 0)
2508 {
2509 sprintf((char *)IObuff + len, " col %d", qfp->qf_col);
2510 len += (int)STRLEN(IObuff + len);
2511 }
2512
2513 sprintf((char *)IObuff + len, "%s",
2514 (char *)qf_types(qfp->qf_type, qfp->qf_nr));
2515 len += (int)STRLEN(IObuff + len);
2516 }
Bram Moolenaar68b76a62005-03-25 21:53:48 +00002517 else if (qfp->qf_pattern != NULL)
2518 {
2519 qf_fmt_text(qfp->qf_pattern, IObuff + len, IOSIZE - len);
2520 len += (int)STRLEN(IObuff + len);
2521 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002522 IObuff[len++] = '|';
2523 IObuff[len++] = ' ';
2524
2525 /* Remove newlines and leading whitespace from the text.
2526 * For an unrecognized line keep the indent, the compiler may
2527 * mark a word with ^^^^. */
2528 qf_fmt_text(len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text,
2529 IObuff + len, IOSIZE - len);
2530
2531 if (ml_append(lnum, IObuff, (colnr_T)STRLEN(IObuff) + 1, FALSE)
2532 == FAIL)
2533 break;
2534 qfp = qfp->qf_next;
2535 }
2536 /* Delete the empty line which is now at the end */
2537 (void)ml_delete(lnum + 1, FALSE);
2538 }
2539
2540 /* correct cursor position */
2541 check_lnums(TRUE);
2542
2543 /* Set the 'filetype' to "qf" each time after filling the buffer. This
2544 * resembles reading a file into a buffer, it's more logical when using
2545 * autocommands. */
2546 set_option_value((char_u *)"ft", 0L, (char_u *)"qf", OPT_LOCAL);
2547 curbuf->b_p_ma = FALSE;
2548
2549#ifdef FEAT_AUTOCMD
2550 apply_autocmds(EVENT_BUFREADPOST, (char_u *)"quickfix", NULL,
2551 FALSE, curbuf);
2552 apply_autocmds(EVENT_BUFWINENTER, (char_u *)"quickfix", NULL,
2553 FALSE, curbuf);
2554#endif
2555
2556 /* make sure it will be redrawn */
2557 redraw_curbuf_later(NOT_VALID);
2558
2559 /* Restore KeyTyped, setting 'filetype' may reset it. */
2560 KeyTyped = old_KeyTyped;
2561}
2562
2563#endif /* FEAT_WINDOWS */
2564
2565/*
2566 * Return TRUE if "buf" is the quickfix buffer.
2567 */
2568 int
2569bt_quickfix(buf)
2570 buf_T *buf;
2571{
2572 return (buf->b_p_bt[0] == 'q');
2573}
2574
2575/*
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002576 * Return TRUE if "buf" is a "nofile" or "acwrite" buffer.
2577 * This means the buffer name is not a file name.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002578 */
2579 int
2580bt_nofile(buf)
2581 buf_T *buf;
2582{
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002583 return (buf->b_p_bt[0] == 'n' && buf->b_p_bt[2] == 'f')
2584 || buf->b_p_bt[0] == 'a';
Bram Moolenaar071d4272004-06-13 20:20:40 +00002585}
2586
2587/*
2588 * Return TRUE if "buf" is a "nowrite" or "nofile" buffer.
2589 */
2590 int
2591bt_dontwrite(buf)
2592 buf_T *buf;
2593{
2594 return (buf->b_p_bt[0] == 'n');
2595}
2596
2597 int
2598bt_dontwrite_msg(buf)
2599 buf_T *buf;
2600{
2601 if (bt_dontwrite(buf))
2602 {
2603 EMSG(_("E382: Cannot write, 'buftype' option is set"));
2604 return TRUE;
2605 }
2606 return FALSE;
2607}
2608
2609/*
2610 * Return TRUE if the buffer should be hidden, according to 'hidden', ":hide"
2611 * and 'bufhidden'.
2612 */
2613 int
2614buf_hide(buf)
2615 buf_T *buf;
2616{
2617 /* 'bufhidden' overrules 'hidden' and ":hide", check it first */
2618 switch (buf->b_p_bh[0])
2619 {
2620 case 'u': /* "unload" */
2621 case 'w': /* "wipe" */
2622 case 'd': return FALSE; /* "delete" */
2623 case 'h': return TRUE; /* "hide" */
2624 }
2625 return (p_hid || cmdmod.hide);
2626}
2627
2628/*
Bram Moolenaar86b68352004-12-27 21:59:20 +00002629 * Return TRUE when using ":vimgrep" for ":grep".
2630 */
2631 int
Bram Moolenaar81695252004-12-29 20:58:21 +00002632grep_internal(cmdidx)
2633 cmdidx_T cmdidx;
Bram Moolenaar86b68352004-12-27 21:59:20 +00002634{
Bram Moolenaar754b5602006-02-09 23:53:20 +00002635 return ((cmdidx == CMD_grep
2636 || cmdidx == CMD_lgrep
2637 || cmdidx == CMD_grepadd
2638 || cmdidx == CMD_lgrepadd)
Bram Moolenaar86b68352004-12-27 21:59:20 +00002639 && STRCMP("internal",
2640 *curbuf->b_p_gp == NUL ? p_gp : curbuf->b_p_gp) == 0);
2641}
2642
2643/*
Bram Moolenaara6557602006-02-04 22:43:20 +00002644 * Used for ":make", ":lmake", ":grep", ":lgrep", ":grepadd", and ":lgrepadd"
Bram Moolenaar071d4272004-06-13 20:20:40 +00002645 */
2646 void
2647ex_make(eap)
2648 exarg_T *eap;
2649{
Bram Moolenaar7c626922005-02-07 22:01:03 +00002650 char_u *fname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002651 char_u *cmd;
2652 unsigned len;
Bram Moolenaara6557602006-02-04 22:43:20 +00002653 win_T *wp = NULL;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002654 qf_info_T *qi = &ql_info;
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00002655 int res;
Bram Moolenaar7c626922005-02-07 22:01:03 +00002656#ifdef FEAT_AUTOCMD
2657 char_u *au_name = NULL;
2658
2659 switch (eap->cmdidx)
2660 {
Bram Moolenaar754b5602006-02-09 23:53:20 +00002661 case CMD_make: au_name = (char_u *)"make"; break;
2662 case CMD_lmake: au_name = (char_u *)"lmake"; break;
2663 case CMD_grep: au_name = (char_u *)"grep"; break;
2664 case CMD_lgrep: au_name = (char_u *)"lgrep"; break;
2665 case CMD_grepadd: au_name = (char_u *)"grepadd"; break;
2666 case CMD_lgrepadd: au_name = (char_u *)"lgrepadd"; break;
Bram Moolenaar7c626922005-02-07 22:01:03 +00002667 default: break;
2668 }
2669 if (au_name != NULL)
2670 {
2671 apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
2672 curbuf->b_fname, TRUE, curbuf);
Bram Moolenaar1e015462005-09-25 22:16:38 +00002673# ifdef FEAT_EVAL
Bram Moolenaar7c626922005-02-07 22:01:03 +00002674 if (did_throw || force_abort)
2675 return;
Bram Moolenaar1e015462005-09-25 22:16:38 +00002676# endif
Bram Moolenaar7c626922005-02-07 22:01:03 +00002677 }
2678#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002679
Bram Moolenaar86b68352004-12-27 21:59:20 +00002680 /* Redirect ":grep" to ":vimgrep" if 'grepprg' is "internal". */
Bram Moolenaar81695252004-12-29 20:58:21 +00002681 if (grep_internal(eap->cmdidx))
Bram Moolenaar86b68352004-12-27 21:59:20 +00002682 {
2683 ex_vimgrep(eap);
2684 return;
2685 }
2686
Bram Moolenaara6557602006-02-04 22:43:20 +00002687 if (eap->cmdidx == CMD_lmake || eap->cmdidx == CMD_lgrep
2688 || eap->cmdidx == CMD_lgrepadd)
Bram Moolenaara6557602006-02-04 22:43:20 +00002689 wp = curwin;
Bram Moolenaara6557602006-02-04 22:43:20 +00002690
Bram Moolenaar071d4272004-06-13 20:20:40 +00002691 autowrite_all();
Bram Moolenaar7c626922005-02-07 22:01:03 +00002692 fname = get_mef_name();
2693 if (fname == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002694 return;
Bram Moolenaar7c626922005-02-07 22:01:03 +00002695 mch_remove(fname); /* in case it's not unique */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002696
2697 /*
2698 * If 'shellpipe' empty: don't redirect to 'errorfile'.
2699 */
2700 len = (unsigned)STRLEN(p_shq) * 2 + (unsigned)STRLEN(eap->arg) + 1;
2701 if (*p_sp != NUL)
Bram Moolenaar7c626922005-02-07 22:01:03 +00002702 len += (unsigned)STRLEN(p_sp) + (unsigned)STRLEN(fname) + 3;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002703 cmd = alloc(len);
2704 if (cmd == NULL)
2705 return;
2706 sprintf((char *)cmd, "%s%s%s", (char *)p_shq, (char *)eap->arg,
2707 (char *)p_shq);
2708 if (*p_sp != NUL)
Bram Moolenaar7c626922005-02-07 22:01:03 +00002709 append_redir(cmd, p_sp, fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002710 /*
2711 * Output a newline if there's something else than the :make command that
2712 * was typed (in which case the cursor is in column 0).
2713 */
2714 if (msg_col == 0)
2715 msg_didout = FALSE;
2716 msg_start();
2717 MSG_PUTS(":!");
2718 msg_outtrans(cmd); /* show what we are doing */
2719
2720 /* let the shell know if we are redirecting output or not */
2721 do_shell(cmd, *p_sp != NUL ? SHELL_DOOUT : 0);
2722
2723#ifdef AMIGA
2724 out_flush();
2725 /* read window status report and redraw before message */
2726 (void)char_avail();
2727#endif
2728
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00002729 res = qf_init(wp, fname, (eap->cmdidx != CMD_make
Bram Moolenaara6557602006-02-04 22:43:20 +00002730 && eap->cmdidx != CMD_lmake) ? p_gefm : p_efm,
2731 (eap->cmdidx != CMD_grepadd
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00002732 && eap->cmdidx != CMD_lgrepadd));
2733#ifdef FEAT_AUTOCMD
2734 if (au_name != NULL)
2735 apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name,
2736 curbuf->b_fname, TRUE, curbuf);
2737#endif
2738 if (res > 0 && !eap->forceit)
Bram Moolenaarc7453f52006-02-10 23:20:28 +00002739 {
2740 if (wp != NULL)
2741 qi = GET_LOC_LIST(wp);
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002742 qf_jump(qi, 0, 0, FALSE); /* display first error */
Bram Moolenaarc7453f52006-02-10 23:20:28 +00002743 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002744
Bram Moolenaar7c626922005-02-07 22:01:03 +00002745 mch_remove(fname);
2746 vim_free(fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002747 vim_free(cmd);
2748}
2749
2750/*
2751 * Return the name for the errorfile, in allocated memory.
2752 * Find a new unique name when 'makeef' contains "##".
2753 * Returns NULL for error.
2754 */
2755 static char_u *
2756get_mef_name()
2757{
2758 char_u *p;
2759 char_u *name;
2760 static int start = -1;
2761 static int off = 0;
2762#ifdef HAVE_LSTAT
2763 struct stat sb;
2764#endif
2765
2766 if (*p_mef == NUL)
2767 {
2768 name = vim_tempname('e');
2769 if (name == NULL)
2770 EMSG(_(e_notmp));
2771 return name;
2772 }
2773
2774 for (p = p_mef; *p; ++p)
2775 if (p[0] == '#' && p[1] == '#')
2776 break;
2777
2778 if (*p == NUL)
2779 return vim_strsave(p_mef);
2780
2781 /* Keep trying until the name doesn't exist yet. */
2782 for (;;)
2783 {
2784 if (start == -1)
2785 start = mch_get_pid();
2786 else
2787 off += 19;
2788
2789 name = alloc((unsigned)STRLEN(p_mef) + 30);
2790 if (name == NULL)
2791 break;
2792 STRCPY(name, p_mef);
2793 sprintf((char *)name + (p - p_mef), "%d%d", start, off);
2794 STRCAT(name, p + 2);
2795 if (mch_getperm(name) < 0
2796#ifdef HAVE_LSTAT
2797 /* Don't accept a symbolic link, its a security risk. */
2798 && mch_lstat((char *)name, &sb) < 0
2799#endif
2800 )
2801 break;
2802 vim_free(name);
2803 }
2804 return name;
2805}
2806
2807/*
2808 * ":cc", ":crewind", ":cfirst" and ":clast".
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002809 * ":ll", ":lrewind", ":lfirst" and ":llast".
Bram Moolenaar071d4272004-06-13 20:20:40 +00002810 */
2811 void
2812ex_cc(eap)
2813 exarg_T *eap;
2814{
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002815 qf_info_T *qi = &ql_info;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002816
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002817 if (eap->cmdidx == CMD_ll
2818 || eap->cmdidx == CMD_lrewind
2819 || eap->cmdidx == CMD_lfirst
2820 || eap->cmdidx == CMD_llast)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002821 {
2822 qi = GET_LOC_LIST(curwin);
2823 if (qi == NULL)
2824 {
2825 EMSG(_(e_loclist));
2826 return;
2827 }
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002828 }
2829
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002830 qf_jump(qi, 0,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002831 eap->addr_count > 0
2832 ? (int)eap->line2
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002833 : (eap->cmdidx == CMD_cc || eap->cmdidx == CMD_ll)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002834 ? 0
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002835 : (eap->cmdidx == CMD_crewind || eap->cmdidx == CMD_lrewind
2836 || eap->cmdidx == CMD_cfirst || eap->cmdidx == CMD_lfirst)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002837 ? 1
2838 : 32767,
2839 eap->forceit);
2840}
2841
2842/*
2843 * ":cnext", ":cnfile", ":cNext" and ":cprevious".
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002844 * ":lnext", ":lNext", ":lprevious", ":lnfile", ":lNfile" and ":lpfile".
Bram Moolenaar071d4272004-06-13 20:20:40 +00002845 */
2846 void
2847ex_cnext(eap)
2848 exarg_T *eap;
2849{
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002850 qf_info_T *qi = &ql_info;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002851
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002852 if (eap->cmdidx == CMD_lnext
2853 || eap->cmdidx == CMD_lNext
2854 || eap->cmdidx == CMD_lprevious
2855 || eap->cmdidx == CMD_lnfile
2856 || eap->cmdidx == CMD_lNfile
2857 || eap->cmdidx == CMD_lpfile)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002858 {
2859 qi = GET_LOC_LIST(curwin);
2860 if (qi == NULL)
2861 {
2862 EMSG(_(e_loclist));
2863 return;
2864 }
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002865 }
2866
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002867 qf_jump(qi, (eap->cmdidx == CMD_cnext || eap->cmdidx == CMD_lnext)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002868 ? FORWARD
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002869 : (eap->cmdidx == CMD_cnfile || eap->cmdidx == CMD_lnfile)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002870 ? FORWARD_FILE
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002871 : (eap->cmdidx == CMD_cpfile || eap->cmdidx == CMD_lpfile
2872 || eap->cmdidx == CMD_cNfile || eap->cmdidx == CMD_lNfile)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002873 ? BACKWARD_FILE
2874 : BACKWARD,
2875 eap->addr_count > 0 ? (int)eap->line2 : 1, eap->forceit);
2876}
2877
2878/*
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00002879 * ":cfile"/":cgetfile"/":caddfile" commands.
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002880 * ":lfile"/":lgetfile"/":laddfile" commands.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002881 */
2882 void
2883ex_cfile(eap)
2884 exarg_T *eap;
2885{
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002886 win_T *wp = NULL;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002887 qf_info_T *qi = &ql_info;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002888
2889 if (eap->cmdidx == CMD_lfile || eap->cmdidx == CMD_lgetfile
2890 || eap->cmdidx == CMD_laddfile)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002891 wp = curwin;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002892
Bram Moolenaar071d4272004-06-13 20:20:40 +00002893 if (*eap->arg != NUL)
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002894 set_string_option_direct((char_u *)"ef", -1, eap->arg, OPT_FREE, 0);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00002895
2896 /*
2897 * This function is used by the :cfile, :cgetfile and :caddfile
2898 * commands.
2899 * :cfile always creates a new quickfix list and jumps to the
2900 * first error.
2901 * :cgetfile creates a new quickfix list but doesn't jump to the
2902 * first error.
2903 * :caddfile adds to an existing quickfix list. If there is no
2904 * quickfix list then a new list is created.
2905 */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002906 if (qf_init(wp, p_ef, p_efm, (eap->cmdidx != CMD_caddfile
2907 && eap->cmdidx != CMD_laddfile)) > 0
2908 && (eap->cmdidx == CMD_cfile
2909 || eap->cmdidx == CMD_lfile))
Bram Moolenaarc7453f52006-02-10 23:20:28 +00002910 {
2911 if (wp != NULL)
2912 qi = GET_LOC_LIST(wp);
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002913 qf_jump(qi, 0, 0, eap->forceit); /* display first error */
Bram Moolenaarc7453f52006-02-10 23:20:28 +00002914 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002915}
2916
2917/*
Bram Moolenaar86b68352004-12-27 21:59:20 +00002918 * ":vimgrep {pattern} file(s)"
Bram Moolenaara6557602006-02-04 22:43:20 +00002919 * ":vimgrepadd {pattern} file(s)"
2920 * ":lvimgrep {pattern} file(s)"
2921 * ":lvimgrepadd {pattern} file(s)"
Bram Moolenaar86b68352004-12-27 21:59:20 +00002922 */
2923 void
2924ex_vimgrep(eap)
2925 exarg_T *eap;
2926{
Bram Moolenaar81695252004-12-29 20:58:21 +00002927 regmmatch_T regmatch;
Bram Moolenaar748bf032005-02-02 23:04:36 +00002928 int fcount;
Bram Moolenaar86b68352004-12-27 21:59:20 +00002929 char_u **fnames;
Bram Moolenaar748bf032005-02-02 23:04:36 +00002930 char_u *s;
2931 char_u *p;
Bram Moolenaar748bf032005-02-02 23:04:36 +00002932 int fi;
Bram Moolenaara6557602006-02-04 22:43:20 +00002933 qf_info_T *qi = &ql_info;
Bram Moolenaar68b76a62005-03-25 21:53:48 +00002934 qfline_T *prevp = NULL;
Bram Moolenaar86b68352004-12-27 21:59:20 +00002935 long lnum;
Bram Moolenaar81695252004-12-29 20:58:21 +00002936 buf_T *buf;
2937 int duplicate_name = FALSE;
2938 int using_dummy;
2939 int found_match;
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00002940 buf_T *first_match_buf = NULL;
2941 time_t seconds = 0;
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00002942 int save_mls;
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00002943#if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2944 char_u *save_ei = NULL;
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00002945#endif
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00002946#ifndef FEAT_AUTOCMD
2947 buf_T *save_curbuf;
2948#else
2949 aco_save_T aco;
Bram Moolenaar7c626922005-02-07 22:01:03 +00002950 char_u *au_name = NULL;
Bram Moolenaar05159a02005-02-26 23:04:13 +00002951 int flags = 0;
2952 colnr_T col;
Bram Moolenaar1f35bf92006-03-07 22:38:47 +00002953 long tomatch;
Bram Moolenaar7c626922005-02-07 22:01:03 +00002954
2955 switch (eap->cmdidx)
2956 {
2957 case CMD_vimgrep: au_name = (char_u *)"vimgrep"; break;
Bram Moolenaara6557602006-02-04 22:43:20 +00002958 case CMD_lvimgrep: au_name = (char_u *)"lvimgrep"; break;
Bram Moolenaar7c626922005-02-07 22:01:03 +00002959 case CMD_vimgrepadd: au_name = (char_u *)"vimgrepadd"; break;
Bram Moolenaara6557602006-02-04 22:43:20 +00002960 case CMD_lvimgrepadd: au_name = (char_u *)"lvimgrepadd"; break;
Bram Moolenaar7c626922005-02-07 22:01:03 +00002961 default: break;
2962 }
2963 if (au_name != NULL)
2964 {
2965 apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
2966 curbuf->b_fname, TRUE, curbuf);
2967 if (did_throw || force_abort)
2968 return;
2969 }
2970#endif
Bram Moolenaar86b68352004-12-27 21:59:20 +00002971
Bram Moolenaar754b5602006-02-09 23:53:20 +00002972 if (eap->cmdidx == CMD_lgrep
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002973 || eap->cmdidx == CMD_lvimgrep
2974 || eap->cmdidx == CMD_lgrepadd
2975 || eap->cmdidx == CMD_lvimgrepadd)
Bram Moolenaara6557602006-02-04 22:43:20 +00002976 {
2977 qi = ll_get_or_alloc_list(curwin);
2978 if (qi == NULL)
2979 return;
Bram Moolenaara6557602006-02-04 22:43:20 +00002980 }
2981
Bram Moolenaar1f35bf92006-03-07 22:38:47 +00002982 if (eap->addr_count > 0)
2983 tomatch = eap->line2;
2984 else
2985 tomatch = MAXLNUM;
2986
Bram Moolenaar81695252004-12-29 20:58:21 +00002987 /* Get the search pattern: either white-separated or enclosed in // */
Bram Moolenaar86b68352004-12-27 21:59:20 +00002988 regmatch.regprog = NULL;
Bram Moolenaar05159a02005-02-26 23:04:13 +00002989 p = skip_vimgrep_pat(eap->arg, &s, &flags);
Bram Moolenaar748bf032005-02-02 23:04:36 +00002990 if (p == NULL)
Bram Moolenaar86b68352004-12-27 21:59:20 +00002991 {
Bram Moolenaar2389c3c2005-05-22 22:07:59 +00002992 EMSG(_(e_invalpat));
Bram Moolenaar748bf032005-02-02 23:04:36 +00002993 goto theend;
Bram Moolenaar81695252004-12-29 20:58:21 +00002994 }
Bram Moolenaar81695252004-12-29 20:58:21 +00002995 regmatch.regprog = vim_regcomp(s, RE_MAGIC);
Bram Moolenaar86b68352004-12-27 21:59:20 +00002996 if (regmatch.regprog == NULL)
2997 goto theend;
Bram Moolenaar5f2bb9f2005-01-11 21:29:04 +00002998 regmatch.rmm_ic = p_ic;
Bram Moolenaar3b56eb32005-07-11 22:40:32 +00002999 regmatch.rmm_maxcol = 0;
Bram Moolenaar86b68352004-12-27 21:59:20 +00003000
3001 p = skipwhite(p);
3002 if (*p == NUL)
3003 {
3004 EMSG(_("E683: File name missing or invalid pattern"));
3005 goto theend;
3006 }
3007
Bram Moolenaar754b5602006-02-09 23:53:20 +00003008 if ((eap->cmdidx != CMD_grepadd && eap->cmdidx != CMD_lgrepadd &&
Bram Moolenaara6557602006-02-04 22:43:20 +00003009 eap->cmdidx != CMD_vimgrepadd && eap->cmdidx != CMD_lvimgrepadd)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003010 || qi->qf_curlist == qi->qf_listcount)
Bram Moolenaar86b68352004-12-27 21:59:20 +00003011 /* make place for a new list */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003012 qf_new_list(qi);
3013 else if (qi->qf_lists[qi->qf_curlist].qf_count > 0)
Bram Moolenaar86b68352004-12-27 21:59:20 +00003014 /* Adding to existing list, find last entry. */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003015 for (prevp = qi->qf_lists[qi->qf_curlist].qf_start;
Bram Moolenaar86b68352004-12-27 21:59:20 +00003016 prevp->qf_next != prevp; prevp = prevp->qf_next)
3017 ;
3018
3019 /* parse the list of arguments */
Bram Moolenaar402d2fe2005-04-15 21:00:38 +00003020 if (get_arglist_exp(p, &fcount, &fnames) == FAIL)
Bram Moolenaar86b68352004-12-27 21:59:20 +00003021 goto theend;
3022 if (fcount == 0)
3023 {
3024 EMSG(_(e_nomatch));
3025 goto theend;
3026 }
3027
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00003028 seconds = (time_t)0;
Bram Moolenaar1f35bf92006-03-07 22:38:47 +00003029 for (fi = 0; fi < fcount && !got_int && tomatch > 0; ++fi)
Bram Moolenaar86b68352004-12-27 21:59:20 +00003030 {
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00003031 if (time(NULL) > seconds)
3032 {
3033 /* Display the file name every second or so. */
3034 seconds = time(NULL);
3035 msg_start();
Bram Moolenaara5373fa2005-09-09 19:47:12 +00003036 p = msg_strtrunc(fnames[fi], TRUE);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00003037 if (p == NULL)
3038 msg_outtrans(fnames[fi]);
3039 else
3040 {
3041 msg_outtrans(p);
3042 vim_free(p);
3043 }
3044 msg_clr_eos();
3045 msg_didout = FALSE; /* overwrite this message */
3046 msg_nowait = TRUE; /* don't wait for this message */
3047 msg_col = 0;
3048 out_flush();
3049 }
3050
Bram Moolenaar81695252004-12-29 20:58:21 +00003051 buf = buflist_findname_exp(fnames[fi]);
3052 if (buf == NULL || buf->b_ml.ml_mfp == NULL)
3053 {
3054 /* Remember that a buffer with this name already exists. */
3055 duplicate_name = (buf != NULL);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00003056 using_dummy = TRUE;
3057
3058#if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
3059 /* Don't do Filetype autocommands to avoid loading syntax and
3060 * indent scripts, a great speed improvement. */
3061 save_ei = au_event_disable(",Filetype");
3062#endif
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00003063 /* Don't use modelines here, it's useless. */
3064 save_mls = p_mls;
3065 p_mls = 0;
Bram Moolenaar81695252004-12-29 20:58:21 +00003066
3067 /* Load file into a buffer, so that 'fileencoding' is detected,
3068 * autocommands applied, etc. */
3069 buf = load_dummy_buffer(fnames[fi]);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00003070
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00003071 p_mls = save_mls;
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00003072#if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
3073 au_event_restore(save_ei);
3074#endif
Bram Moolenaar81695252004-12-29 20:58:21 +00003075 }
3076 else
3077 /* Use existing, loaded buffer. */
3078 using_dummy = FALSE;
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00003079
Bram Moolenaar81695252004-12-29 20:58:21 +00003080 if (buf == NULL)
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00003081 {
3082 if (!got_int)
3083 smsg((char_u *)_("Cannot open file \"%s\""), fnames[fi]);
3084 }
Bram Moolenaar86b68352004-12-27 21:59:20 +00003085 else
3086 {
Bram Moolenaara3227e22006-03-08 21:32:40 +00003087 /* Try for a match in all lines of the buffer.
3088 * For ":1vimgrep" look for first match only. */
Bram Moolenaar81695252004-12-29 20:58:21 +00003089 found_match = FALSE;
Bram Moolenaar1f35bf92006-03-07 22:38:47 +00003090 for (lnum = 1; lnum <= buf->b_ml.ml_line_count && tomatch > 0;
3091 ++lnum)
Bram Moolenaar86b68352004-12-27 21:59:20 +00003092 {
Bram Moolenaar05159a02005-02-26 23:04:13 +00003093 col = 0;
3094 while (vim_regexec_multi(&regmatch, curwin, buf, lnum,
3095 col) > 0)
Bram Moolenaar86b68352004-12-27 21:59:20 +00003096 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003097 if (qf_add_entry(qi, &prevp,
Bram Moolenaar86b68352004-12-27 21:59:20 +00003098 NULL, /* dir */
3099 fnames[fi],
Bram Moolenaar81695252004-12-29 20:58:21 +00003100 ml_get_buf(buf,
3101 regmatch.startpos[0].lnum + lnum, FALSE),
3102 regmatch.startpos[0].lnum + lnum,
3103 regmatch.startpos[0].col + 1,
Bram Moolenaar05159a02005-02-26 23:04:13 +00003104 FALSE, /* vis_col */
Bram Moolenaar68b76a62005-03-25 21:53:48 +00003105 NULL, /* search pattern */
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00003106 0, /* nr */
3107 0, /* type */
3108 TRUE /* valid */
Bram Moolenaar86b68352004-12-27 21:59:20 +00003109 ) == FAIL)
3110 {
3111 got_int = TRUE;
3112 break;
3113 }
Bram Moolenaar1f35bf92006-03-07 22:38:47 +00003114 found_match = TRUE;
3115 if (--tomatch == 0)
3116 break;
Bram Moolenaar05159a02005-02-26 23:04:13 +00003117 if ((flags & VGR_GLOBAL) == 0
3118 || regmatch.endpos[0].lnum > 0)
3119 break;
3120 col = regmatch.endpos[0].col
3121 + (col == regmatch.endpos[0].col);
3122 if (col > STRLEN(ml_get_buf(buf, lnum, FALSE)))
3123 break;
Bram Moolenaar86b68352004-12-27 21:59:20 +00003124 }
Bram Moolenaar86b68352004-12-27 21:59:20 +00003125 line_breakcheck();
Bram Moolenaar81695252004-12-29 20:58:21 +00003126 if (got_int)
3127 break;
Bram Moolenaar86b68352004-12-27 21:59:20 +00003128 }
Bram Moolenaar81695252004-12-29 20:58:21 +00003129
3130 if (using_dummy)
3131 {
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00003132 if (found_match && first_match_buf == NULL)
3133 first_match_buf = buf;
Bram Moolenaar81695252004-12-29 20:58:21 +00003134 if (duplicate_name)
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00003135 {
Bram Moolenaar81695252004-12-29 20:58:21 +00003136 /* Never keep a dummy buffer if there is another buffer
3137 * with the same name. */
3138 wipe_dummy_buffer(buf);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00003139 buf = NULL;
3140 }
Bram Moolenaara3227e22006-03-08 21:32:40 +00003141 else if (!cmdmod.hide
3142 || buf->b_p_bh[0] == 'u' /* "unload" */
3143 || buf->b_p_bh[0] == 'w' /* "wipe" */
3144 || buf->b_p_bh[0] == 'd') /* "delete" */
Bram Moolenaar81695252004-12-29 20:58:21 +00003145 {
Bram Moolenaara3227e22006-03-08 21:32:40 +00003146 /* When no match was found we don't need to remember the
3147 * buffer, wipe it out. If there was a match and it
3148 * wasn't the first one or we won't jump there: only
3149 * unload the buffer.
3150 * Ignore 'hidden' here, because it may lead to having too
3151 * many swap files. */
Bram Moolenaar81695252004-12-29 20:58:21 +00003152 if (!found_match)
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00003153 {
Bram Moolenaar81695252004-12-29 20:58:21 +00003154 wipe_dummy_buffer(buf);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00003155 buf = NULL;
3156 }
Bram Moolenaar05159a02005-02-26 23:04:13 +00003157 else if (buf != first_match_buf || (flags & VGR_NOJUMP))
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00003158 {
Bram Moolenaar81695252004-12-29 20:58:21 +00003159 unload_dummy_buffer(buf);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00003160 buf = NULL;
3161 }
Bram Moolenaar81695252004-12-29 20:58:21 +00003162 }
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00003163
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00003164 if (buf != NULL)
3165 {
3166 /* The buffer is still loaded, the Filetype autocommands
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00003167 * need to be done now, in that buffer. And the modelines
Bram Moolenaara3227e22006-03-08 21:32:40 +00003168 * need to be done (again). But not the window-local
3169 * options! */
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00003170#if defined(FEAT_AUTOCMD)
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00003171 aucmd_prepbuf(&aco, buf);
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00003172#else
3173 save_curbuf = curbuf;
3174 curbuf = buf;
3175 curwin->w_buffer = curbuf;
3176#endif
3177#if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00003178 apply_autocmds(EVENT_FILETYPE, buf->b_p_ft,
3179 buf->b_fname, TRUE, buf);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00003180#endif
Bram Moolenaara3227e22006-03-08 21:32:40 +00003181 do_modelines(OPT_NOWIN);
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00003182#if defined(FEAT_AUTOCMD)
3183 aucmd_restbuf(&aco);
3184#else
3185 curbuf = save_curbuf;
3186 curwin->w_buffer = curbuf;
3187#endif
3188 }
Bram Moolenaar81695252004-12-29 20:58:21 +00003189 }
Bram Moolenaar86b68352004-12-27 21:59:20 +00003190 }
3191 }
3192
3193 FreeWild(fcount, fnames);
3194
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003195 qi->qf_lists[qi->qf_curlist].qf_nonevalid = FALSE;
3196 qi->qf_lists[qi->qf_curlist].qf_ptr = qi->qf_lists[qi->qf_curlist].qf_start;
3197 qi->qf_lists[qi->qf_curlist].qf_index = 1;
Bram Moolenaar86b68352004-12-27 21:59:20 +00003198
3199#ifdef FEAT_WINDOWS
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003200 qf_update_buffer(qi);
Bram Moolenaar86b68352004-12-27 21:59:20 +00003201#endif
3202
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003203#ifdef FEAT_AUTOCMD
3204 if (au_name != NULL)
3205 apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name,
3206 curbuf->b_fname, TRUE, curbuf);
3207#endif
3208
Bram Moolenaar86b68352004-12-27 21:59:20 +00003209 /* Jump to first match. */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003210 if (qi->qf_lists[qi->qf_curlist].qf_count > 0)
Bram Moolenaar05159a02005-02-26 23:04:13 +00003211 {
3212 if ((flags & VGR_NOJUMP) == 0)
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003213 qf_jump(qi, 0, 0, eap->forceit);
Bram Moolenaar05159a02005-02-26 23:04:13 +00003214 }
Bram Moolenaar81695252004-12-29 20:58:21 +00003215 else
3216 EMSG2(_(e_nomatch2), s);
Bram Moolenaar86b68352004-12-27 21:59:20 +00003217
3218theend:
3219 vim_free(regmatch.regprog);
Bram Moolenaar86b68352004-12-27 21:59:20 +00003220}
3221
3222/*
Bram Moolenaar05159a02005-02-26 23:04:13 +00003223 * Skip over the pattern argument of ":vimgrep /pat/[g][j]".
Bram Moolenaar748bf032005-02-02 23:04:36 +00003224 * Put the start of the pattern in "*s", unless "s" is NULL.
Bram Moolenaar05159a02005-02-26 23:04:13 +00003225 * If "flags" is not NULL put the flags in it: VGR_GLOBAL, VGR_NOJUMP.
3226 * If "s" is not NULL terminate the pattern with a NUL.
3227 * Return a pointer to the char just past the pattern plus flags.
Bram Moolenaar748bf032005-02-02 23:04:36 +00003228 */
3229 char_u *
Bram Moolenaar05159a02005-02-26 23:04:13 +00003230skip_vimgrep_pat(p, s, flags)
3231 char_u *p;
3232 char_u **s;
3233 int *flags;
Bram Moolenaar748bf032005-02-02 23:04:36 +00003234{
3235 int c;
3236
3237 if (vim_isIDc(*p))
3238 {
Bram Moolenaar05159a02005-02-26 23:04:13 +00003239 /* ":vimgrep pattern fname" */
Bram Moolenaar748bf032005-02-02 23:04:36 +00003240 if (s != NULL)
3241 *s = p;
Bram Moolenaar05159a02005-02-26 23:04:13 +00003242 p = skiptowhite(p);
3243 if (s != NULL && *p != NUL)
3244 *p++ = NUL;
Bram Moolenaar748bf032005-02-02 23:04:36 +00003245 }
Bram Moolenaar05159a02005-02-26 23:04:13 +00003246 else
3247 {
3248 /* ":vimgrep /pattern/[g][j] fname" */
3249 if (s != NULL)
3250 *s = p + 1;
3251 c = *p;
3252 p = skip_regexp(p + 1, c, TRUE, NULL);
3253 if (*p != c)
3254 return NULL;
3255
3256 /* Truncate the pattern. */
3257 if (s != NULL)
3258 *p = NUL;
3259 ++p;
3260
3261 /* Find the flags */
3262 while (*p == 'g' || *p == 'j')
3263 {
3264 if (flags != NULL)
3265 {
3266 if (*p == 'g')
3267 *flags |= VGR_GLOBAL;
3268 else
3269 *flags |= VGR_NOJUMP;
3270 }
3271 ++p;
3272 }
3273 }
Bram Moolenaar748bf032005-02-02 23:04:36 +00003274 return p;
3275}
3276
3277/*
Bram Moolenaar81695252004-12-29 20:58:21 +00003278 * Load file "fname" into a dummy buffer and return the buffer pointer.
3279 * Returns NULL if it fails.
3280 * Must call unload_dummy_buffer() or wipe_dummy_buffer() later!
3281 */
3282 static buf_T *
3283load_dummy_buffer(fname)
3284 char_u *fname;
3285{
3286 buf_T *newbuf;
3287 int failed = TRUE;
3288#ifdef FEAT_AUTOCMD
3289 aco_save_T aco;
3290#else
3291 buf_T *old_curbuf = curbuf;
3292#endif
3293
3294 /* Allocate a buffer without putting it in the buffer list. */
3295 newbuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY);
3296 if (newbuf == NULL)
3297 return NULL;
3298
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00003299 /* Init the options. */
3300 buf_copy_options(newbuf, BCO_ENTER | BCO_NOHELP);
3301
Bram Moolenaar81695252004-12-29 20:58:21 +00003302#ifdef FEAT_AUTOCMD
3303 /* set curwin/curbuf to buf and save a few things */
3304 aucmd_prepbuf(&aco, newbuf);
3305#else
3306 curbuf = newbuf;
3307 curwin->w_buffer = newbuf;
3308#endif
3309
3310 /* Need to set the filename for autocommands. */
3311 (void)setfname(curbuf, fname, NULL, FALSE);
3312
Bram Moolenaar4770d092006-01-12 23:22:24 +00003313 if (ml_open(curbuf) == OK)
Bram Moolenaar81695252004-12-29 20:58:21 +00003314 {
3315 /* Create swap file now to avoid the ATTENTION message. */
3316 check_need_swap(TRUE);
3317
3318 /* Remove the "dummy" flag, otherwise autocommands may not
3319 * work. */
3320 curbuf->b_flags &= ~BF_DUMMY;
3321
3322 if (readfile(fname, NULL,
3323 (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM,
3324 NULL, READ_NEW | READ_DUMMY) == OK
Bram Moolenaard68071d2006-05-02 22:08:30 +00003325 && !got_int
Bram Moolenaar81695252004-12-29 20:58:21 +00003326 && !(curbuf->b_flags & BF_NEW))
3327 {
3328 failed = FALSE;
3329 if (curbuf != newbuf)
3330 {
3331 /* Bloody autocommands changed the buffer! */
3332 if (buf_valid(newbuf))
3333 wipe_buffer(newbuf, FALSE);
3334 newbuf = curbuf;
3335 }
3336 }
3337 }
3338
3339#ifdef FEAT_AUTOCMD
3340 /* restore curwin/curbuf and a few other things */
3341 aucmd_restbuf(&aco);
3342#else
3343 curbuf = old_curbuf;
3344 curwin->w_buffer = old_curbuf;
3345#endif
3346
3347 if (!buf_valid(newbuf))
3348 return NULL;
3349 if (failed)
3350 {
3351 wipe_dummy_buffer(newbuf);
3352 return NULL;
3353 }
3354 return newbuf;
3355}
3356
3357/*
3358 * Wipe out the dummy buffer that load_dummy_buffer() created.
3359 */
3360 static void
3361wipe_dummy_buffer(buf)
3362 buf_T *buf;
3363{
3364 if (curbuf != buf) /* safety check */
Bram Moolenaard68071d2006-05-02 22:08:30 +00003365 {
3366#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
3367 cleanup_T cs;
3368
3369 /* Reset the error/interrupt/exception state here so that aborting()
3370 * returns FALSE when wiping out the buffer. Otherwise it doesn't
3371 * work when got_int is set. */
3372 enter_cleanup(&cs);
3373#endif
3374
Bram Moolenaar81695252004-12-29 20:58:21 +00003375 wipe_buffer(buf, FALSE);
Bram Moolenaard68071d2006-05-02 22:08:30 +00003376
3377#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
3378 /* Restore the error/interrupt/exception state if not discarded by a
3379 * new aborting error, interrupt, or uncaught exception. */
3380 leave_cleanup(&cs);
3381#endif
3382 }
Bram Moolenaar81695252004-12-29 20:58:21 +00003383}
3384
3385/*
3386 * Unload the dummy buffer that load_dummy_buffer() created.
3387 */
3388 static void
3389unload_dummy_buffer(buf)
3390 buf_T *buf;
3391{
3392 if (curbuf != buf) /* safety check */
3393 close_buffer(NULL, buf, DOBUF_UNLOAD);
3394}
3395
Bram Moolenaar05159a02005-02-26 23:04:13 +00003396#if defined(FEAT_EVAL) || defined(PROTO)
3397/*
3398 * Add each quickfix error to list "list" as a dictionary.
3399 */
3400 int
Bram Moolenaar17c7c012006-01-26 22:25:15 +00003401get_errorlist(wp, list)
3402 win_T *wp;
Bram Moolenaar05159a02005-02-26 23:04:13 +00003403 list_T *list;
3404{
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003405 qf_info_T *qi = &ql_info;
Bram Moolenaar68b76a62005-03-25 21:53:48 +00003406 dict_T *dict;
3407 char_u buf[2];
3408 qfline_T *qfp;
3409 int i;
Bram Moolenaar05159a02005-02-26 23:04:13 +00003410
Bram Moolenaar17c7c012006-01-26 22:25:15 +00003411 if (wp != NULL)
3412 {
3413 qi = GET_LOC_LIST(wp);
3414 if (qi == NULL)
3415 return FAIL;
3416 }
3417
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003418 if (qi->qf_curlist >= qi->qf_listcount
Bram Moolenaar87b5ca52006-03-04 21:55:31 +00003419 || qi->qf_lists[qi->qf_curlist].qf_count == 0)
Bram Moolenaar05159a02005-02-26 23:04:13 +00003420 return FAIL;
Bram Moolenaar05159a02005-02-26 23:04:13 +00003421
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003422 qfp = qi->qf_lists[qi->qf_curlist].qf_start;
3423 for (i = 1; !got_int && i <= qi->qf_lists[qi->qf_curlist].qf_count; ++i)
Bram Moolenaar05159a02005-02-26 23:04:13 +00003424 {
3425 if ((dict = dict_alloc()) == NULL)
3426 return FAIL;
3427 if (list_append_dict(list, dict) == FAIL)
3428 return FAIL;
3429
3430 buf[0] = qfp->qf_type;
3431 buf[1] = NUL;
3432 if ( dict_add_nr_str(dict, "bufnr", (long)qfp->qf_fnum, NULL) == FAIL
3433 || dict_add_nr_str(dict, "lnum", (long)qfp->qf_lnum, NULL) == FAIL
3434 || dict_add_nr_str(dict, "col", (long)qfp->qf_col, NULL) == FAIL
3435 || dict_add_nr_str(dict, "vcol", (long)qfp->qf_viscol, NULL) == FAIL
3436 || dict_add_nr_str(dict, "nr", (long)qfp->qf_nr, NULL) == FAIL
Bram Moolenaar68b76a62005-03-25 21:53:48 +00003437 || dict_add_nr_str(dict, "pattern", 0L, qfp->qf_pattern) == FAIL
Bram Moolenaar05159a02005-02-26 23:04:13 +00003438 || dict_add_nr_str(dict, "text", 0L, qfp->qf_text) == FAIL
3439 || dict_add_nr_str(dict, "type", 0L, buf) == FAIL
3440 || dict_add_nr_str(dict, "valid", (long)qfp->qf_valid, NULL) == FAIL)
3441 return FAIL;
3442
3443 qfp = qfp->qf_next;
3444 }
3445 return OK;
3446}
Bram Moolenaar68b76a62005-03-25 21:53:48 +00003447
3448/*
3449 * Populate the quickfix list with the items supplied in the list
3450 * of dictionaries.
3451 */
3452 int
Bram Moolenaar17c7c012006-01-26 22:25:15 +00003453set_errorlist(wp, list, action)
3454 win_T *wp;
Bram Moolenaar68b76a62005-03-25 21:53:48 +00003455 list_T *list;
Bram Moolenaar35c54e52005-05-20 21:25:31 +00003456 int action;
Bram Moolenaar68b76a62005-03-25 21:53:48 +00003457{
3458 listitem_T *li;
3459 dict_T *d;
3460 char_u *filename, *pattern, *text, *type;
3461 long lnum;
3462 int col, nr;
3463 int vcol;
3464 qfline_T *prevp = NULL;
3465 int valid, status;
3466 int retval = OK;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003467 qf_info_T *qi = &ql_info;
Bram Moolenaar68b76a62005-03-25 21:53:48 +00003468
Bram Moolenaar17c7c012006-01-26 22:25:15 +00003469 if (wp != NULL)
3470 {
Bram Moolenaar280f1262006-01-30 00:14:18 +00003471 qi = ll_get_or_alloc_list(wp);
Bram Moolenaar17c7c012006-01-26 22:25:15 +00003472 if (qi == NULL)
3473 return FAIL;
3474 }
3475
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003476 if (action == ' ' || qi->qf_curlist == qi->qf_listcount)
Bram Moolenaar35c54e52005-05-20 21:25:31 +00003477 /* make place for a new list */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003478 qf_new_list(qi);
3479 else if (action == 'a' && qi->qf_lists[qi->qf_curlist].qf_count > 0)
Bram Moolenaar35c54e52005-05-20 21:25:31 +00003480 /* Adding to existing list, find last entry. */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003481 for (prevp = qi->qf_lists[qi->qf_curlist].qf_start;
Bram Moolenaar35c54e52005-05-20 21:25:31 +00003482 prevp->qf_next != prevp; prevp = prevp->qf_next)
3483 ;
3484 else if (action == 'r')
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003485 qf_free(qi, qi->qf_curlist);
Bram Moolenaar68b76a62005-03-25 21:53:48 +00003486
3487 for (li = list->lv_first; li != NULL; li = li->li_next)
3488 {
3489 if (li->li_tv.v_type != VAR_DICT)
3490 continue; /* Skip non-dict items */
3491
3492 d = li->li_tv.vval.v_dict;
3493 if (d == NULL)
3494 continue;
3495
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003496 filename = get_dict_string(d, (char_u *)"filename", TRUE);
Bram Moolenaar68b76a62005-03-25 21:53:48 +00003497 lnum = get_dict_number(d, (char_u *)"lnum");
3498 col = get_dict_number(d, (char_u *)"col");
3499 vcol = get_dict_number(d, (char_u *)"vcol");
3500 nr = get_dict_number(d, (char_u *)"nr");
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003501 type = get_dict_string(d, (char_u *)"type", TRUE);
3502 pattern = get_dict_string(d, (char_u *)"pattern", TRUE);
3503 text = get_dict_string(d, (char_u *)"text", TRUE);
Bram Moolenaar68b76a62005-03-25 21:53:48 +00003504 if (text == NULL)
3505 text = vim_strsave((char_u *)"");
3506
3507 valid = TRUE;
3508 if (filename == NULL || (lnum == 0 && pattern == NULL))
3509 valid = FALSE;
3510
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003511 status = qf_add_entry(qi, &prevp,
Bram Moolenaar68b76a62005-03-25 21:53:48 +00003512 NULL, /* dir */
3513 filename,
3514 text,
3515 lnum,
3516 col,
3517 vcol, /* vis_col */
3518 pattern, /* search pattern */
3519 nr,
3520 type == NULL ? NUL : *type,
3521 valid);
3522
3523 vim_free(filename);
3524 vim_free(pattern);
3525 vim_free(text);
3526 vim_free(type);
3527
3528 if (status == FAIL)
3529 {
3530 retval = FAIL;
3531 break;
3532 }
3533 }
3534
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003535 qi->qf_lists[qi->qf_curlist].qf_nonevalid = FALSE;
3536 qi->qf_lists[qi->qf_curlist].qf_ptr = qi->qf_lists[qi->qf_curlist].qf_start;
3537 qi->qf_lists[qi->qf_curlist].qf_index = 1;
Bram Moolenaar68b76a62005-03-25 21:53:48 +00003538
3539#ifdef FEAT_WINDOWS
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003540 qf_update_buffer(qi);
Bram Moolenaar68b76a62005-03-25 21:53:48 +00003541#endif
3542
3543 return retval;
3544}
Bram Moolenaar05159a02005-02-26 23:04:13 +00003545#endif
3546
Bram Moolenaar81695252004-12-29 20:58:21 +00003547/*
Bram Moolenaar86b68352004-12-27 21:59:20 +00003548 * ":[range]cbuffer [bufnr]" command.
Bram Moolenaara6557602006-02-04 22:43:20 +00003549 * ":[range]caddbuffer [bufnr]" command.
Bram Moolenaardb552d602006-03-23 22:59:57 +00003550 * ":[range]cgetbuffer [bufnr]" command.
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003551 * ":[range]lbuffer [bufnr]" command.
Bram Moolenaara6557602006-02-04 22:43:20 +00003552 * ":[range]laddbuffer [bufnr]" command.
Bram Moolenaardb552d602006-03-23 22:59:57 +00003553 * ":[range]lgetbuffer [bufnr]" command.
Bram Moolenaar86b68352004-12-27 21:59:20 +00003554 */
3555 void
3556ex_cbuffer(eap)
3557 exarg_T *eap;
3558{
3559 buf_T *buf = NULL;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003560 qf_info_T *qi = &ql_info;
3561
Bram Moolenaardb552d602006-03-23 22:59:57 +00003562 if (eap->cmdidx == CMD_lbuffer || eap->cmdidx == CMD_lgetbuffer
3563 || eap->cmdidx == CMD_laddbuffer)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003564 {
3565 qi = ll_get_or_alloc_list(curwin);
3566 if (qi == NULL)
3567 return;
3568 }
Bram Moolenaar86b68352004-12-27 21:59:20 +00003569
3570 if (*eap->arg == NUL)
3571 buf = curbuf;
3572 else if (*skipwhite(skipdigits(eap->arg)) == NUL)
3573 buf = buflist_findnr(atoi((char *)eap->arg));
3574 if (buf == NULL)
3575 EMSG(_(e_invarg));
3576 else if (buf->b_ml.ml_mfp == NULL)
3577 EMSG(_("E681: Buffer is not loaded"));
3578 else
3579 {
3580 if (eap->addr_count == 0)
3581 {
3582 eap->line1 = 1;
3583 eap->line2 = buf->b_ml.ml_line_count;
3584 }
3585 if (eap->line1 < 1 || eap->line1 > buf->b_ml.ml_line_count
3586 || eap->line2 < 1 || eap->line2 > buf->b_ml.ml_line_count)
3587 EMSG(_(e_invrange));
3588 else
Bram Moolenaar754b5602006-02-09 23:53:20 +00003589 {
Bram Moolenaardb552d602006-03-23 22:59:57 +00003590 if (qf_init_ext(qi, NULL, buf, NULL, p_efm,
3591 (eap->cmdidx != CMD_caddbuffer
3592 && eap->cmdidx != CMD_laddbuffer),
Bram Moolenaar754b5602006-02-09 23:53:20 +00003593 eap->line1, eap->line2) > 0
Bram Moolenaardb552d602006-03-23 22:59:57 +00003594 && (eap->cmdidx == CMD_cbuffer
3595 || eap->cmdidx == CMD_lbuffer))
Bram Moolenaar754b5602006-02-09 23:53:20 +00003596 qf_jump(qi, 0, 0, eap->forceit); /* display first error */
3597 }
Bram Moolenaar86b68352004-12-27 21:59:20 +00003598 }
3599}
3600
Bram Moolenaar1e015462005-09-25 22:16:38 +00003601#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar86b68352004-12-27 21:59:20 +00003602/*
Bram Moolenaardb552d602006-03-23 22:59:57 +00003603 * ":cexpr {expr}", ":cgetexpr {expr}", ":caddexpr {expr}" command.
3604 * ":lexpr {expr}", ":lgetexpr {expr}", ":laddexpr {expr}" command.
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00003605 */
3606 void
3607ex_cexpr(eap)
3608 exarg_T *eap;
3609{
3610 typval_T *tv;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003611 qf_info_T *qi = &ql_info;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003612
Bram Moolenaardb552d602006-03-23 22:59:57 +00003613 if (eap->cmdidx == CMD_lexpr || eap->cmdidx == CMD_lgetexpr
3614 || eap->cmdidx == CMD_laddexpr)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003615 {
3616 qi = ll_get_or_alloc_list(curwin);
3617 if (qi == NULL)
3618 return;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003619 }
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00003620
Bram Moolenaar4770d092006-01-12 23:22:24 +00003621 /* Evaluate the expression. When the result is a string or a list we can
3622 * use it to fill the errorlist. */
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00003623 tv = eval_expr(eap->arg, NULL);
Bram Moolenaar4770d092006-01-12 23:22:24 +00003624 if (tv != NULL)
3625 {
3626 if ((tv->v_type == VAR_STRING && tv->vval.v_string != NULL)
3627 || (tv->v_type == VAR_LIST && tv->vval.v_list != NULL))
3628 {
Bram Moolenaardb552d602006-03-23 22:59:57 +00003629 if (qf_init_ext(qi, NULL, NULL, tv, p_efm,
3630 (eap->cmdidx != CMD_caddexpr
3631 && eap->cmdidx != CMD_laddexpr),
Bram Moolenaar4770d092006-01-12 23:22:24 +00003632 (linenr_T)0, (linenr_T)0) > 0
Bram Moolenaardb552d602006-03-23 22:59:57 +00003633 && (eap->cmdidx == CMD_cexpr
3634 || eap->cmdidx == CMD_lexpr))
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003635 qf_jump(qi, 0, 0, eap->forceit); /* display first error */
Bram Moolenaar4770d092006-01-12 23:22:24 +00003636 }
3637 else
Bram Moolenaara40ceaf2006-01-13 22:35:40 +00003638 EMSG(_("E777: String or List expected"));
Bram Moolenaar4770d092006-01-12 23:22:24 +00003639 free_tv(tv);
3640 }
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00003641}
Bram Moolenaar1e015462005-09-25 22:16:38 +00003642#endif
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00003643
3644/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003645 * ":helpgrep {pattern}"
3646 */
3647 void
3648ex_helpgrep(eap)
3649 exarg_T *eap;
3650{
3651 regmatch_T regmatch;
3652 char_u *save_cpo;
3653 char_u *p;
3654 int fcount;
3655 char_u **fnames;
3656 FILE *fd;
3657 int fi;
Bram Moolenaar68b76a62005-03-25 21:53:48 +00003658 qfline_T *prevp = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003659 long lnum;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003660#ifdef FEAT_MULTI_LANG
3661 char_u *lang;
3662#endif
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003663 qf_info_T *qi = &ql_info;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003664 int new_qi = FALSE;
3665 win_T *wp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003666
3667 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
3668 save_cpo = p_cpo;
3669 p_cpo = (char_u *)"";
3670
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003671#ifdef FEAT_MULTI_LANG
3672 /* Check for a specified language */
3673 lang = check_help_lang(eap->arg);
3674#endif
3675
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003676 if (eap->cmdidx == CMD_lhelpgrep)
3677 {
3678 /* Find an existing help window */
3679 FOR_ALL_WINDOWS(wp)
3680 if (wp->w_buffer != NULL && wp->w_buffer->b_help)
3681 break;
3682
3683 if (wp == NULL) /* Help window not found */
3684 qi = NULL;
3685 else
3686 qi = wp->w_llist;
3687
3688 if (qi == NULL)
3689 {
3690 /* Allocate a new location list for help text matches */
3691 if ((qi = ll_new_list()) == NULL)
3692 return;
3693 new_qi = TRUE;
3694 }
3695 }
3696
Bram Moolenaar071d4272004-06-13 20:20:40 +00003697 regmatch.regprog = vim_regcomp(eap->arg, RE_MAGIC + RE_STRING);
3698 regmatch.rm_ic = FALSE;
3699 if (regmatch.regprog != NULL)
3700 {
3701 /* create a new quickfix list */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003702 qf_new_list(qi);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003703
3704 /* Go through all directories in 'runtimepath' */
3705 p = p_rtp;
3706 while (*p != NUL && !got_int)
3707 {
3708 copy_option_part(&p, NameBuff, MAXPATHL, ",");
3709
3710 /* Find all "*.txt" and "*.??x" files in the "doc" directory. */
3711 add_pathsep(NameBuff);
3712 STRCAT(NameBuff, "doc/*.\\(txt\\|??x\\)");
3713 if (gen_expand_wildcards(1, &NameBuff, &fcount,
3714 &fnames, EW_FILE|EW_SILENT) == OK
3715 && fcount > 0)
3716 {
3717 for (fi = 0; fi < fcount && !got_int; ++fi)
3718 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003719#ifdef FEAT_MULTI_LANG
3720 /* Skip files for a different language. */
3721 if (lang != NULL
3722 && STRNICMP(lang, fnames[fi]
3723 + STRLEN(fnames[fi]) - 3, 2) != 0
3724 && !(STRNICMP(lang, "en", 2) == 0
3725 && STRNICMP("txt", fnames[fi]
3726 + STRLEN(fnames[fi]) - 3, 3) == 0))
3727 continue;
3728#endif
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +00003729 fd = mch_fopen((char *)fnames[fi], "r");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003730 if (fd != NULL)
3731 {
3732 lnum = 1;
3733 while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int)
3734 {
3735 if (vim_regexec(&regmatch, IObuff, (colnr_T)0))
3736 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00003737 int l = (int)STRLEN(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003738
3739 /* remove trailing CR, LF, spaces, etc. */
3740 while (l > 0 && IObuff[l - 1] <= ' ')
3741 IObuff[--l] = NUL;
3742
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003743 if (qf_add_entry(qi, &prevp,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003744 NULL, /* dir */
3745 fnames[fi],
3746 IObuff,
3747 lnum,
Bram Moolenaar81695252004-12-29 20:58:21 +00003748 (int)(regmatch.startp[0] - IObuff)
3749 + 1, /* col */
Bram Moolenaar05159a02005-02-26 23:04:13 +00003750 FALSE, /* vis_col */
Bram Moolenaar68b76a62005-03-25 21:53:48 +00003751 NULL, /* search pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003752 0, /* nr */
3753 1, /* type */
3754 TRUE /* valid */
3755 ) == FAIL)
3756 {
3757 got_int = TRUE;
3758 break;
3759 }
3760 }
3761 ++lnum;
3762 line_breakcheck();
3763 }
3764 fclose(fd);
3765 }
3766 }
3767 FreeWild(fcount, fnames);
3768 }
3769 }
3770 vim_free(regmatch.regprog);
3771
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003772 qi->qf_lists[qi->qf_curlist].qf_nonevalid = FALSE;
3773 qi->qf_lists[qi->qf_curlist].qf_ptr =
3774 qi->qf_lists[qi->qf_curlist].qf_start;
3775 qi->qf_lists[qi->qf_curlist].qf_index = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003776 }
3777
3778 p_cpo = save_cpo;
3779
3780#ifdef FEAT_WINDOWS
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003781 qf_update_buffer(qi);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003782#endif
3783
3784 /* Jump to first match. */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003785 if (qi->qf_lists[qi->qf_curlist].qf_count > 0)
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003786 qf_jump(qi, 0, 0, FALSE);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003787 else
3788 EMSG2(_(e_nomatch2), eap->arg);
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003789
3790 if (eap->cmdidx == CMD_lhelpgrep)
3791 {
3792 /* If the help window is not opened or if it already points to the
Bram Moolenaar754b5602006-02-09 23:53:20 +00003793 * correct location list, then free the new location list. */
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003794 if (!curwin->w_buffer->b_help || curwin->w_llist == qi)
3795 {
3796 if (new_qi)
3797 ll_free_all(&qi);
3798 }
3799 else if (curwin->w_llist == NULL)
3800 curwin->w_llist = qi;
3801 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003802}
3803
3804#endif /* FEAT_QUICKFIX */