Mercurial > vim
comparison src/quickfix.c @ 12503:4d40b2644e92 v8.0.1130
patch 8.0.1130: the qf_jump() function is still too long
commit https://github.com/vim/vim/commit/9cb03716c963338f9a98d2ebc7aa3ac8b9c1eea6
Author: Bram Moolenaar <Bram@vim.org>
Date: Wed Sep 20 22:43:02 2017 +0200
patch 8.0.1130: the qf_jump() function is still too long
Problem: The qf_jump() function is still too long.
Solution: Split of parts to separate functions. (Yegappan Lakshmanan)
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Wed, 20 Sep 2017 22:45:04 +0200 |
parents | 68d7bc045dbe |
children | 972ea22c946f |
comparison
equal
deleted
inserted
replaced
12502:ed85dd1b8c80 | 12503:4d40b2644e92 |
---|---|
1952 return TRUE; | 1952 return TRUE; |
1953 } | 1953 } |
1954 | 1954 |
1955 /* | 1955 /* |
1956 * Get the next valid entry in the current quickfix/location list. The search | 1956 * Get the next valid entry in the current quickfix/location list. The search |
1957 * starts from the current entry. If next_file is TRUE, then return the next | 1957 * starts from the current entry. Returns NULL on failure. |
1958 * valid entry in the next file in the list. Returns NULL on failure. | |
1959 */ | 1958 */ |
1960 static qfline_T * | 1959 static qfline_T * |
1961 get_next_valid_entry( | 1960 get_next_valid_entry( |
1962 qf_info_T *qi, | 1961 qf_info_T *qi, |
1963 qfline_T *qf_ptr, | 1962 qfline_T *qf_ptr, |
1985 return qf_ptr; | 1984 return qf_ptr; |
1986 } | 1985 } |
1987 | 1986 |
1988 /* | 1987 /* |
1989 * Get the previous valid entry in the current quickfix/location list. The | 1988 * Get the previous valid entry in the current quickfix/location list. The |
1990 * search starts from the current entry. If prev_file is TRUE, then return the | 1989 * search starts from the current entry. Returns NULL on failure. |
1991 * previous valid entry in the previous file in the list. Returns NULL on | |
1992 * failure. | |
1993 */ | 1990 */ |
1994 static qfline_T * | 1991 static qfline_T * |
1995 get_prev_valid_entry( | 1992 get_prev_valid_entry( |
1996 qf_info_T *qi, | 1993 qf_info_T *qi, |
1997 qfline_T *qf_ptr, | 1994 qfline_T *qf_ptr, |
2063 | 2060 |
2064 return qf_ptr; | 2061 return qf_ptr; |
2065 } | 2062 } |
2066 | 2063 |
2067 /* | 2064 /* |
2068 * Get n'th quickfix entry | 2065 * Get n'th (errornr) quickfix entry |
2069 */ | 2066 */ |
2070 static qfline_T * | 2067 static qfline_T * |
2071 get_nth_entry( | 2068 get_nth_entry( |
2072 qf_info_T *qi, | 2069 qf_info_T *qi, |
2073 int errornr, | 2070 int errornr, |
2074 qfline_T *qf_ptr, | 2071 qfline_T *qf_ptr, |
2075 int *qf_index) | 2072 int *cur_qfidx) |
2076 { | 2073 { |
2077 int qf_idx = *qf_index; | 2074 int qf_idx = *cur_qfidx; |
2078 | 2075 |
2076 /* New error number is less than the current error number */ | |
2079 while (errornr < qf_idx && qf_idx > 1 && qf_ptr->qf_prev != NULL) | 2077 while (errornr < qf_idx && qf_idx > 1 && qf_ptr->qf_prev != NULL) |
2080 { | 2078 { |
2081 --qf_idx; | 2079 --qf_idx; |
2082 qf_ptr = qf_ptr->qf_prev; | 2080 qf_ptr = qf_ptr->qf_prev; |
2083 } | 2081 } |
2082 /* New error number is greater than the current error number */ | |
2084 while (errornr > qf_idx && | 2083 while (errornr > qf_idx && |
2085 qf_idx < qi->qf_lists[qi->qf_curlist].qf_count && | 2084 qf_idx < qi->qf_lists[qi->qf_curlist].qf_count && |
2086 qf_ptr->qf_next != NULL) | 2085 qf_ptr->qf_next != NULL) |
2087 { | 2086 { |
2088 ++qf_idx; | 2087 ++qf_idx; |
2089 qf_ptr = qf_ptr->qf_next; | 2088 qf_ptr = qf_ptr->qf_next; |
2090 } | 2089 } |
2091 | 2090 |
2092 *qf_index = qf_idx; | 2091 *cur_qfidx = qf_idx; |
2093 return qf_ptr; | 2092 return qf_ptr; |
2094 } | 2093 } |
2095 | 2094 |
2096 /* | 2095 /* |
2097 * Find a help window or open one. | 2096 * Find a help window or open one. |
2144 | 2143 |
2145 return OK; | 2144 return OK; |
2146 } | 2145 } |
2147 | 2146 |
2148 /* | 2147 /* |
2149 * jump to a quickfix line | 2148 * Find a suitable window for opening a file (qf_fnum) and jump to it. |
2150 * if dir == FORWARD go "errornr" valid entries forward | 2149 * If the file is already opened in a window, jump to it. |
2151 * if dir == BACKWARD go "errornr" valid entries backward | 2150 */ |
2152 * if dir == FORWARD_FILE go "errornr" valid entries files backward | 2151 static int |
2153 * if dir == BACKWARD_FILE go "errornr" valid entries files backward | 2152 qf_jump_to_usable_window(int qf_fnum, int *opened_window) |
2154 * else if "errornr" is zero, redisplay the same line | 2153 { |
2155 * else go to entry "errornr" | 2154 win_T *usable_win_ptr = NULL; |
2156 */ | 2155 int usable_win; |
2157 void | 2156 qf_info_T *ll_ref; |
2158 qf_jump(qf_info_T *qi, | 2157 int flags; |
2159 int dir, | 2158 win_T *win; |
2160 int errornr, | 2159 win_T *altwin; |
2161 int forceit) | 2160 |
2162 { | 2161 usable_win = 0; |
2163 qf_info_T *ll_ref; | 2162 |
2164 qfline_T *qf_ptr; | 2163 ll_ref = curwin->w_llist_ref; |
2165 qfline_T *old_qf_ptr; | 2164 if (ll_ref != NULL) |
2166 int qf_index; | 2165 { |
2167 int old_qf_index; | 2166 /* Find a window using the same location list that is not a |
2168 linenr_T i; | 2167 * quickfix window. */ |
2169 buf_T *old_curbuf; | 2168 FOR_ALL_WINDOWS(usable_win_ptr) |
2170 linenr_T old_lnum; | 2169 if (usable_win_ptr->w_llist == ll_ref |
2171 colnr_T screen_col; | 2170 && !bt_quickfix(usable_win_ptr->w_buffer)) |
2172 colnr_T char_col; | 2171 { |
2173 char_u *line; | 2172 usable_win = 1; |
2174 char_u *old_swb = p_swb; | 2173 break; |
2175 unsigned old_swb_flags = swb_flags; | 2174 } |
2176 int opened_window = FALSE; | 2175 } |
2177 win_T *win; | 2176 |
2178 win_T *altwin; | 2177 if (!usable_win) |
2179 int flags; | 2178 { |
2180 win_T *oldwin = curwin; | 2179 /* Locate a window showing a normal buffer */ |
2181 int print_message = TRUE; | 2180 FOR_ALL_WINDOWS(win) |
2182 int len; | 2181 if (win->w_buffer->b_p_bt[0] == NUL) |
2183 #ifdef FEAT_FOLDING | 2182 { |
2184 int old_KeyTyped = KeyTyped; /* getting file may reset it */ | 2183 usable_win = 1; |
2185 #endif | 2184 break; |
2186 int ok = OK; | 2185 } |
2187 int usable_win; | 2186 } |
2188 | |
2189 if (qi == NULL) | |
2190 qi = &ql_info; | |
2191 | |
2192 if (qi->qf_curlist >= qi->qf_listcount | |
2193 || qi->qf_lists[qi->qf_curlist].qf_count == 0) | |
2194 { | |
2195 EMSG(_(e_quickfix)); | |
2196 return; | |
2197 } | |
2198 | |
2199 qf_ptr = qi->qf_lists[qi->qf_curlist].qf_ptr; | |
2200 old_qf_ptr = qf_ptr; | |
2201 qf_index = qi->qf_lists[qi->qf_curlist].qf_index; | |
2202 old_qf_index = qf_index; | |
2203 if (dir != 0) /* next/prev valid entry */ | |
2204 { | |
2205 qf_ptr = get_nth_valid_entry(qi, errornr, qf_ptr, &qf_index, dir); | |
2206 if (qf_ptr == NULL) | |
2207 { | |
2208 qf_ptr = old_qf_ptr; | |
2209 qf_index = old_qf_index; | |
2210 goto theend; | |
2211 } | |
2212 } | |
2213 else if (errornr != 0) /* go to specified number */ | |
2214 qf_ptr = get_nth_entry(qi, errornr, qf_ptr, &qf_index); | |
2215 | |
2216 qi->qf_lists[qi->qf_curlist].qf_index = qf_index; | |
2217 if (qf_win_pos_update(qi, old_qf_index)) | |
2218 /* No need to print the error message if it's visible in the error | |
2219 * window */ | |
2220 print_message = FALSE; | |
2221 | 2187 |
2222 /* | 2188 /* |
2223 * For ":helpgrep" find a help window or open one. | 2189 * If no usable window is found and 'switchbuf' contains "usetab" |
2190 * then search in other tabs. | |
2224 */ | 2191 */ |
2225 if (qf_ptr->qf_type == 1 && (!bt_help(curwin->w_buffer) || cmdmod.tab != 0)) | 2192 if (!usable_win && (swb_flags & SWB_USETAB)) |
2226 { | 2193 { |
2227 if (jump_to_help_window(qi, &opened_window) == FAIL) | 2194 tabpage_T *tp; |
2228 goto theend; | 2195 win_T *wp; |
2229 } | 2196 |
2197 FOR_ALL_TAB_WINDOWS(tp, wp) | |
2198 { | |
2199 if (wp->w_buffer->b_fnum == qf_fnum) | |
2200 { | |
2201 goto_tabpage_win(tp, wp); | |
2202 usable_win = 1; | |
2203 goto win_found; | |
2204 } | |
2205 } | |
2206 } | |
2207 win_found: | |
2230 | 2208 |
2231 /* | 2209 /* |
2232 * If currently in the quickfix window, find another window to show the | 2210 * If there is only one window and it is the quickfix window, create a |
2233 * file in. | 2211 * new one above the quickfix window. |
2234 */ | 2212 */ |
2235 if (bt_quickfix(curbuf) && !opened_window) | 2213 if ((ONE_WINDOW && bt_quickfix(curbuf)) || !usable_win) |
2236 { | 2214 { |
2237 win_T *usable_win_ptr = NULL; | 2215 flags = WSP_ABOVE; |
2238 | |
2239 /* | |
2240 * If there is no file specified, we don't know where to go. | |
2241 * But do advance, otherwise ":cn" gets stuck. | |
2242 */ | |
2243 if (qf_ptr->qf_fnum == 0) | |
2244 goto theend; | |
2245 | |
2246 usable_win = 0; | |
2247 | |
2248 ll_ref = curwin->w_llist_ref; | |
2249 if (ll_ref != NULL) | 2216 if (ll_ref != NULL) |
2250 { | 2217 flags |= WSP_NEWLOC; |
2251 /* Find a window using the same location list that is not a | 2218 if (win_split(0, flags) == FAIL) |
2252 * quickfix window. */ | 2219 return FAIL; /* not enough room for window */ |
2253 FOR_ALL_WINDOWS(usable_win_ptr) | 2220 *opened_window = TRUE; /* close it when fail */ |
2254 if (usable_win_ptr->w_llist == ll_ref | 2221 p_swb = empty_option; /* don't split again */ |
2255 && !bt_quickfix(usable_win_ptr->w_buffer)) | 2222 swb_flags = 0; |
2223 RESET_BINDING(curwin); | |
2224 if (ll_ref != NULL) | |
2225 { | |
2226 /* The new window should use the location list from the | |
2227 * location list window */ | |
2228 curwin->w_llist = ll_ref; | |
2229 ll_ref->qf_refcount++; | |
2230 } | |
2231 } | |
2232 else | |
2233 { | |
2234 if (curwin->w_llist_ref != NULL) | |
2235 { | |
2236 /* In a location window */ | |
2237 win = usable_win_ptr; | |
2238 if (win == NULL) | |
2239 { | |
2240 /* Find the window showing the selected file */ | |
2241 FOR_ALL_WINDOWS(win) | |
2242 if (win->w_buffer->b_fnum == qf_fnum) | |
2243 break; | |
2244 if (win == NULL) | |
2256 { | 2245 { |
2257 usable_win = 1; | 2246 /* Find a previous usable window */ |
2258 break; | 2247 win = curwin; |
2259 } | 2248 do |
2260 } | 2249 { |
2261 | 2250 if (win->w_buffer->b_p_bt[0] == NUL) |
2262 if (!usable_win) | 2251 break; |
2263 { | 2252 if (win->w_prev == NULL) |
2264 /* Locate a window showing a normal buffer */ | 2253 win = lastwin; /* wrap around the top */ |
2265 FOR_ALL_WINDOWS(win) | 2254 else |
2266 if (win->w_buffer->b_p_bt[0] == NUL) | 2255 win = win->w_prev; /* go to previous window */ |
2267 { | 2256 } while (win != curwin); |
2268 usable_win = 1; | |
2269 break; | |
2270 } | |
2271 } | |
2272 | |
2273 /* | |
2274 * If no usable window is found and 'switchbuf' contains "usetab" | |
2275 * then search in other tabs. | |
2276 */ | |
2277 if (!usable_win && (swb_flags & SWB_USETAB)) | |
2278 { | |
2279 tabpage_T *tp; | |
2280 win_T *wp; | |
2281 | |
2282 FOR_ALL_TAB_WINDOWS(tp, wp) | |
2283 { | |
2284 if (wp->w_buffer->b_fnum == qf_ptr->qf_fnum) | |
2285 { | |
2286 goto_tabpage_win(tp, wp); | |
2287 usable_win = 1; | |
2288 goto win_found; | |
2289 } | 2257 } |
2290 } | 2258 } |
2291 } | 2259 win_goto(win); |
2292 win_found: | 2260 |
2293 | 2261 /* If the location list for the window is not set, then set it |
2294 /* | 2262 * to the location list from the location window */ |
2295 * If there is only one window and it is the quickfix window, create a | 2263 if (win->w_llist == NULL) |
2296 * new one above the quickfix window. | |
2297 */ | |
2298 if ((ONE_WINDOW && bt_quickfix(curbuf)) || !usable_win) | |
2299 { | |
2300 flags = WSP_ABOVE; | |
2301 if (ll_ref != NULL) | |
2302 flags |= WSP_NEWLOC; | |
2303 if (win_split(0, flags) == FAIL) | |
2304 goto failed; /* not enough room for window */ | |
2305 opened_window = TRUE; /* close it when fail */ | |
2306 p_swb = empty_option; /* don't split again */ | |
2307 swb_flags = 0; | |
2308 RESET_BINDING(curwin); | |
2309 if (ll_ref != NULL) | |
2310 { | 2264 { |
2311 /* The new window should use the location list from the | 2265 win->w_llist = ll_ref; |
2312 * location list window */ | |
2313 curwin->w_llist = ll_ref; | |
2314 ll_ref->qf_refcount++; | 2266 ll_ref->qf_refcount++; |
2315 } | 2267 } |
2316 } | 2268 } |
2317 else | 2269 else |
2318 { | 2270 { |
2319 if (curwin->w_llist_ref != NULL) | |
2320 { | |
2321 /* In a location window */ | |
2322 win = usable_win_ptr; | |
2323 if (win == NULL) | |
2324 { | |
2325 /* Find the window showing the selected file */ | |
2326 FOR_ALL_WINDOWS(win) | |
2327 if (win->w_buffer->b_fnum == qf_ptr->qf_fnum) | |
2328 break; | |
2329 if (win == NULL) | |
2330 { | |
2331 /* Find a previous usable window */ | |
2332 win = curwin; | |
2333 do | |
2334 { | |
2335 if (win->w_buffer->b_p_bt[0] == NUL) | |
2336 break; | |
2337 if (win->w_prev == NULL) | |
2338 win = lastwin; /* wrap around the top */ | |
2339 else | |
2340 win = win->w_prev; /* go to previous window */ | |
2341 } while (win != curwin); | |
2342 } | |
2343 } | |
2344 win_goto(win); | |
2345 | |
2346 /* If the location list for the window is not set, then set it | |
2347 * to the location list from the location window */ | |
2348 if (win->w_llist == NULL) | |
2349 { | |
2350 win->w_llist = ll_ref; | |
2351 ll_ref->qf_refcount++; | |
2352 } | |
2353 } | |
2354 else | |
2355 { | |
2356 | 2271 |
2357 /* | 2272 /* |
2358 * Try to find a window that shows the right buffer. | 2273 * Try to find a window that shows the right buffer. |
2359 * Default to the window just above the quickfix buffer. | 2274 * Default to the window just above the quickfix buffer. |
2360 */ | 2275 */ |
2361 win = curwin; | 2276 win = curwin; |
2362 altwin = NULL; | 2277 altwin = NULL; |
2363 for (;;) | 2278 for (;;) |
2364 { | 2279 { |
2365 if (win->w_buffer->b_fnum == qf_ptr->qf_fnum) | 2280 if (win->w_buffer->b_fnum == qf_fnum) |
2366 break; | 2281 break; |
2367 if (win->w_prev == NULL) | 2282 if (win->w_prev == NULL) |
2368 win = lastwin; /* wrap around the top */ | 2283 win = lastwin; /* wrap around the top */ |
2369 else | 2284 else |
2370 win = win->w_prev; /* go to previous window */ | 2285 win = win->w_prev; /* go to previous window */ |
2382 break; | 2297 break; |
2383 } | 2298 } |
2384 | 2299 |
2385 /* Remember a usable window. */ | 2300 /* Remember a usable window. */ |
2386 if (altwin == NULL && !win->w_p_pvw | 2301 if (altwin == NULL && !win->w_p_pvw |
2387 && win->w_buffer->b_p_bt[0] == NUL) | 2302 && win->w_buffer->b_p_bt[0] == NUL) |
2388 altwin = win; | 2303 altwin = win; |
2389 } | 2304 } |
2390 | 2305 |
2391 win_goto(win); | 2306 win_goto(win); |
2307 } | |
2308 } | |
2309 | |
2310 return OK; | |
2311 } | |
2312 | |
2313 /* | |
2314 * Edit the selected file or help file. | |
2315 */ | |
2316 static int | |
2317 qf_jump_edit_buffer( | |
2318 qf_info_T *qi, | |
2319 qfline_T *qf_ptr, | |
2320 int forceit, | |
2321 win_T *oldwin, | |
2322 int *opened_window, | |
2323 int *abort) | |
2324 { | |
2325 int retval = OK; | |
2326 | |
2327 if (qf_ptr->qf_type == 1) | |
2328 { | |
2329 /* Open help file (do_ecmd() will set b_help flag, readfile() will | |
2330 * set b_p_ro flag). */ | |
2331 if (!can_abandon(curbuf, forceit)) | |
2332 { | |
2333 no_write_message(); | |
2334 retval = FALSE; | |
2335 } | |
2336 else | |
2337 retval = do_ecmd(qf_ptr->qf_fnum, NULL, NULL, NULL, (linenr_T)1, | |
2338 ECMD_HIDE + ECMD_SET_HELP, | |
2339 oldwin == curwin ? curwin : NULL); | |
2340 } | |
2341 else | |
2342 { | |
2343 int old_qf_curlist = qi->qf_curlist; | |
2344 | |
2345 retval = buflist_getfile(qf_ptr->qf_fnum, | |
2346 (linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit); | |
2347 if (qi != &ql_info && !win_valid_any_tab(oldwin)) | |
2348 { | |
2349 EMSG(_("E924: Current window was closed")); | |
2350 *abort = TRUE; | |
2351 *opened_window = FALSE; | |
2352 } | |
2353 else if (old_qf_curlist != qi->qf_curlist | |
2354 || !is_qf_entry_present(qi, qf_ptr)) | |
2355 { | |
2356 if (qi == &ql_info) | |
2357 EMSG(_("E925: Current quickfix was changed")); | |
2358 else | |
2359 EMSG(_("E926: Current location list was changed")); | |
2360 *abort = TRUE; | |
2361 } | |
2362 | |
2363 if (*abort) | |
2364 retval = FALSE; | |
2365 } | |
2366 | |
2367 return retval; | |
2368 } | |
2369 | |
2370 /* | |
2371 * Goto the error line in the current file using either line/column number or a | |
2372 * search pattern. | |
2373 */ | |
2374 static void | |
2375 qf_jump_goto_line( | |
2376 linenr_T qf_lnum, | |
2377 int qf_col, | |
2378 char_u qf_viscol, | |
2379 char_u *qf_pattern) | |
2380 { | |
2381 linenr_T i; | |
2382 char_u *line; | |
2383 colnr_T screen_col; | |
2384 colnr_T char_col; | |
2385 | |
2386 if (qf_pattern == NULL) | |
2387 { | |
2388 /* | |
2389 * Go to line with error, unless qf_lnum is 0. | |
2390 */ | |
2391 i = qf_lnum; | |
2392 if (i > 0) | |
2393 { | |
2394 if (i > curbuf->b_ml.ml_line_count) | |
2395 i = curbuf->b_ml.ml_line_count; | |
2396 curwin->w_cursor.lnum = i; | |
2397 } | |
2398 if (qf_col > 0) | |
2399 { | |
2400 curwin->w_cursor.col = qf_col - 1; | |
2401 #ifdef FEAT_VIRTUALEDIT | |
2402 curwin->w_cursor.coladd = 0; | |
2403 #endif | |
2404 if (qf_viscol == TRUE) | |
2405 { | |
2406 /* | |
2407 * Check each character from the beginning of the error | |
2408 * line up to the error column. For each tab character | |
2409 * found, reduce the error column value by the length of | |
2410 * a tab character. | |
2411 */ | |
2412 line = ml_get_curline(); | |
2413 screen_col = 0; | |
2414 for (char_col = 0; char_col < curwin->w_cursor.col; ++char_col) | |
2415 { | |
2416 if (*line == NUL) | |
2417 break; | |
2418 if (*line++ == '\t') | |
2419 { | |
2420 curwin->w_cursor.col -= 7 - (screen_col % 8); | |
2421 screen_col += 8 - (screen_col % 8); | |
2422 } | |
2423 else | |
2424 ++screen_col; | |
2425 } | |
2392 } | 2426 } |
2393 } | 2427 check_cursor(); |
2428 } | |
2429 else | |
2430 beginline(BL_WHITE | BL_FIX); | |
2431 } | |
2432 else | |
2433 { | |
2434 pos_T save_cursor; | |
2435 | |
2436 /* Move the cursor to the first line in the buffer */ | |
2437 save_cursor = curwin->w_cursor; | |
2438 curwin->w_cursor.lnum = 0; | |
2439 if (!do_search(NULL, '/', qf_pattern, (long)1, | |
2440 SEARCH_KEEP, NULL, NULL)) | |
2441 curwin->w_cursor = save_cursor; | |
2442 } | |
2443 } | |
2444 | |
2445 /* | |
2446 * Display quickfix list index and size message | |
2447 */ | |
2448 static void | |
2449 qf_jump_print_msg( | |
2450 qf_info_T *qi, | |
2451 int qf_index, | |
2452 qfline_T *qf_ptr, | |
2453 buf_T *old_curbuf, | |
2454 linenr_T old_lnum) | |
2455 { | |
2456 linenr_T i; | |
2457 int len; | |
2458 | |
2459 /* Update the screen before showing the message, unless the screen | |
2460 * scrolled up. */ | |
2461 if (!msg_scrolled) | |
2462 update_topline_redraw(); | |
2463 sprintf((char *)IObuff, _("(%d of %d)%s%s: "), qf_index, | |
2464 qi->qf_lists[qi->qf_curlist].qf_count, | |
2465 qf_ptr->qf_cleared ? _(" (line deleted)") : "", | |
2466 (char *)qf_types(qf_ptr->qf_type, qf_ptr->qf_nr)); | |
2467 /* Add the message, skipping leading whitespace and newlines. */ | |
2468 len = (int)STRLEN(IObuff); | |
2469 qf_fmt_text(skipwhite(qf_ptr->qf_text), IObuff + len, IOSIZE - len); | |
2470 | |
2471 /* Output the message. Overwrite to avoid scrolling when the 'O' | |
2472 * flag is present in 'shortmess'; But when not jumping, print the | |
2473 * whole message. */ | |
2474 i = msg_scroll; | |
2475 if (curbuf == old_curbuf && curwin->w_cursor.lnum == old_lnum) | |
2476 msg_scroll = TRUE; | |
2477 else if (!msg_scrolled && shortmess(SHM_OVERALL)) | |
2478 msg_scroll = FALSE; | |
2479 msg_attr_keep(IObuff, 0, TRUE); | |
2480 msg_scroll = i; | |
2481 } | |
2482 | |
2483 /* | |
2484 * jump to a quickfix line | |
2485 * if dir == FORWARD go "errornr" valid entries forward | |
2486 * if dir == BACKWARD go "errornr" valid entries backward | |
2487 * if dir == FORWARD_FILE go "errornr" valid entries files backward | |
2488 * if dir == BACKWARD_FILE go "errornr" valid entries files backward | |
2489 * else if "errornr" is zero, redisplay the same line | |
2490 * else go to entry "errornr" | |
2491 */ | |
2492 void | |
2493 qf_jump(qf_info_T *qi, | |
2494 int dir, | |
2495 int errornr, | |
2496 int forceit) | |
2497 { | |
2498 qfline_T *qf_ptr; | |
2499 qfline_T *old_qf_ptr; | |
2500 int qf_index; | |
2501 int old_qf_index; | |
2502 buf_T *old_curbuf; | |
2503 linenr_T old_lnum; | |
2504 char_u *old_swb = p_swb; | |
2505 unsigned old_swb_flags = swb_flags; | |
2506 int opened_window = FALSE; | |
2507 win_T *oldwin = curwin; | |
2508 int print_message = TRUE; | |
2509 #ifdef FEAT_FOLDING | |
2510 int old_KeyTyped = KeyTyped; /* getting file may reset it */ | |
2511 #endif | |
2512 int retval = OK; | |
2513 | |
2514 if (qi == NULL) | |
2515 qi = &ql_info; | |
2516 | |
2517 if (qi->qf_curlist >= qi->qf_listcount | |
2518 || qi->qf_lists[qi->qf_curlist].qf_count == 0) | |
2519 { | |
2520 EMSG(_(e_quickfix)); | |
2521 return; | |
2522 } | |
2523 | |
2524 qf_ptr = qi->qf_lists[qi->qf_curlist].qf_ptr; | |
2525 old_qf_ptr = qf_ptr; | |
2526 qf_index = qi->qf_lists[qi->qf_curlist].qf_index; | |
2527 old_qf_index = qf_index; | |
2528 if (dir != 0) /* next/prev valid entry */ | |
2529 { | |
2530 qf_ptr = get_nth_valid_entry(qi, errornr, qf_ptr, &qf_index, dir); | |
2531 if (qf_ptr == NULL) | |
2532 { | |
2533 qf_ptr = old_qf_ptr; | |
2534 qf_index = old_qf_index; | |
2535 goto theend; | |
2536 } | |
2537 } | |
2538 else if (errornr != 0) /* go to specified number */ | |
2539 qf_ptr = get_nth_entry(qi, errornr, qf_ptr, &qf_index); | |
2540 | |
2541 qi->qf_lists[qi->qf_curlist].qf_index = qf_index; | |
2542 if (qf_win_pos_update(qi, old_qf_index)) | |
2543 /* No need to print the error message if it's visible in the error | |
2544 * window */ | |
2545 print_message = FALSE; | |
2546 | |
2547 /* | |
2548 * For ":helpgrep" find a help window or open one. | |
2549 */ | |
2550 if (qf_ptr->qf_type == 1 && (!bt_help(curwin->w_buffer) || cmdmod.tab != 0)) | |
2551 if (jump_to_help_window(qi, &opened_window) == FAIL) | |
2552 goto theend; | |
2553 | |
2554 /* | |
2555 * If currently in the quickfix window, find another window to show the | |
2556 * file in. | |
2557 */ | |
2558 if (bt_quickfix(curbuf) && !opened_window) | |
2559 { | |
2560 /* | |
2561 * If there is no file specified, we don't know where to go. | |
2562 * But do advance, otherwise ":cn" gets stuck. | |
2563 */ | |
2564 if (qf_ptr->qf_fnum == 0) | |
2565 goto theend; | |
2566 | |
2567 if (qf_jump_to_usable_window(qf_ptr->qf_fnum, &opened_window) == FAIL) | |
2568 goto failed; | |
2394 } | 2569 } |
2395 | 2570 |
2396 /* | 2571 /* |
2397 * If there is a file name, | 2572 * If there is a file name, |
2398 * read the wanted file if needed, and check autowrite etc. | 2573 * read the wanted file if needed, and check autowrite etc. |
2400 old_curbuf = curbuf; | 2575 old_curbuf = curbuf; |
2401 old_lnum = curwin->w_cursor.lnum; | 2576 old_lnum = curwin->w_cursor.lnum; |
2402 | 2577 |
2403 if (qf_ptr->qf_fnum != 0) | 2578 if (qf_ptr->qf_fnum != 0) |
2404 { | 2579 { |
2405 if (qf_ptr->qf_type == 1) | 2580 int abort = FALSE; |
2406 { | 2581 |
2407 /* Open help file (do_ecmd() will set b_help flag, readfile() will | 2582 retval = qf_jump_edit_buffer(qi, qf_ptr, forceit, oldwin, |
2408 * set b_p_ro flag). */ | 2583 &opened_window, &abort); |
2409 if (!can_abandon(curbuf, forceit)) | 2584 if (abort) |
2410 { | 2585 { |
2411 no_write_message(); | 2586 qi = NULL; |
2412 ok = FALSE; | 2587 qf_ptr = NULL; |
2413 } | 2588 } |
2414 else | 2589 } |
2415 ok = do_ecmd(qf_ptr->qf_fnum, NULL, NULL, NULL, (linenr_T)1, | 2590 |
2416 ECMD_HIDE + ECMD_SET_HELP, | 2591 if (retval == OK) |
2417 oldwin == curwin ? curwin : NULL); | |
2418 } | |
2419 else | |
2420 { | |
2421 int old_qf_curlist = qi->qf_curlist; | |
2422 int is_abort = FALSE; | |
2423 | |
2424 ok = buflist_getfile(qf_ptr->qf_fnum, | |
2425 (linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit); | |
2426 if (qi != &ql_info && !win_valid_any_tab(oldwin)) | |
2427 { | |
2428 EMSG(_("E924: Current window was closed")); | |
2429 is_abort = TRUE; | |
2430 opened_window = FALSE; | |
2431 } | |
2432 else if (old_qf_curlist != qi->qf_curlist | |
2433 || !is_qf_entry_present(qi, qf_ptr)) | |
2434 { | |
2435 if (qi == &ql_info) | |
2436 EMSG(_("E925: Current quickfix was changed")); | |
2437 else | |
2438 EMSG(_("E926: Current location list was changed")); | |
2439 is_abort = TRUE; | |
2440 } | |
2441 | |
2442 if (is_abort) | |
2443 { | |
2444 ok = FALSE; | |
2445 qi = NULL; | |
2446 qf_ptr = NULL; | |
2447 } | |
2448 } | |
2449 } | |
2450 | |
2451 if (ok == OK) | |
2452 { | 2592 { |
2453 /* When not switched to another buffer, still need to set pc mark */ | 2593 /* When not switched to another buffer, still need to set pc mark */ |
2454 if (curbuf == old_curbuf) | 2594 if (curbuf == old_curbuf) |
2455 setpcmark(); | 2595 setpcmark(); |
2456 | 2596 |
2457 if (qf_ptr->qf_pattern == NULL) | 2597 qf_jump_goto_line(qf_ptr->qf_lnum, qf_ptr->qf_col, qf_ptr->qf_viscol, |
2458 { | 2598 qf_ptr->qf_pattern); |
2459 /* | |
2460 * Go to line with error, unless qf_lnum is 0. | |
2461 */ | |
2462 i = qf_ptr->qf_lnum; | |
2463 if (i > 0) | |
2464 { | |
2465 if (i > curbuf->b_ml.ml_line_count) | |
2466 i = curbuf->b_ml.ml_line_count; | |
2467 curwin->w_cursor.lnum = i; | |
2468 } | |
2469 if (qf_ptr->qf_col > 0) | |
2470 { | |
2471 curwin->w_cursor.col = qf_ptr->qf_col - 1; | |
2472 #ifdef FEAT_VIRTUALEDIT | |
2473 curwin->w_cursor.coladd = 0; | |
2474 #endif | |
2475 if (qf_ptr->qf_viscol == TRUE) | |
2476 { | |
2477 /* | |
2478 * Check each character from the beginning of the error | |
2479 * line up to the error column. For each tab character | |
2480 * found, reduce the error column value by the length of | |
2481 * a tab character. | |
2482 */ | |
2483 line = ml_get_curline(); | |
2484 screen_col = 0; | |
2485 for (char_col = 0; char_col < curwin->w_cursor.col; ++char_col) | |
2486 { | |
2487 if (*line == NUL) | |
2488 break; | |
2489 if (*line++ == '\t') | |
2490 { | |
2491 curwin->w_cursor.col -= 7 - (screen_col % 8); | |
2492 screen_col += 8 - (screen_col % 8); | |
2493 } | |
2494 else | |
2495 ++screen_col; | |
2496 } | |
2497 } | |
2498 check_cursor(); | |
2499 } | |
2500 else | |
2501 beginline(BL_WHITE | BL_FIX); | |
2502 } | |
2503 else | |
2504 { | |
2505 pos_T save_cursor; | |
2506 | |
2507 /* Move the cursor to the first line in the buffer */ | |
2508 save_cursor = curwin->w_cursor; | |
2509 curwin->w_cursor.lnum = 0; | |
2510 if (!do_search(NULL, '/', qf_ptr->qf_pattern, (long)1, | |
2511 SEARCH_KEEP, NULL, NULL)) | |
2512 curwin->w_cursor = save_cursor; | |
2513 } | |
2514 | 2599 |
2515 #ifdef FEAT_FOLDING | 2600 #ifdef FEAT_FOLDING |
2516 if ((fdo_flags & FDO_QUICKFIX) && old_KeyTyped) | 2601 if ((fdo_flags & FDO_QUICKFIX) && old_KeyTyped) |
2517 foldOpenCursor(); | 2602 foldOpenCursor(); |
2518 #endif | 2603 #endif |
2519 if (print_message) | 2604 if (print_message) |
2520 { | 2605 qf_jump_print_msg(qi, qf_index, qf_ptr, old_curbuf, old_lnum); |
2521 /* Update the screen before showing the message, unless the screen | |
2522 * scrolled up. */ | |
2523 if (!msg_scrolled) | |
2524 update_topline_redraw(); | |
2525 sprintf((char *)IObuff, _("(%d of %d)%s%s: "), qf_index, | |
2526 qi->qf_lists[qi->qf_curlist].qf_count, | |
2527 qf_ptr->qf_cleared ? _(" (line deleted)") : "", | |
2528 (char *)qf_types(qf_ptr->qf_type, qf_ptr->qf_nr)); | |
2529 /* Add the message, skipping leading whitespace and newlines. */ | |
2530 len = (int)STRLEN(IObuff); | |
2531 qf_fmt_text(skipwhite(qf_ptr->qf_text), IObuff + len, IOSIZE - len); | |
2532 | |
2533 /* Output the message. Overwrite to avoid scrolling when the 'O' | |
2534 * flag is present in 'shortmess'; But when not jumping, print the | |
2535 * whole message. */ | |
2536 i = msg_scroll; | |
2537 if (curbuf == old_curbuf && curwin->w_cursor.lnum == old_lnum) | |
2538 msg_scroll = TRUE; | |
2539 else if (!msg_scrolled && shortmess(SHM_OVERALL)) | |
2540 msg_scroll = FALSE; | |
2541 msg_attr_keep(IObuff, 0, TRUE); | |
2542 msg_scroll = i; | |
2543 } | |
2544 } | 2606 } |
2545 else | 2607 else |
2546 { | 2608 { |
2547 if (opened_window) | 2609 if (opened_window) |
2548 win_close(curwin, TRUE); /* Close opened window */ | 2610 win_close(curwin, TRUE); /* Close opened window */ |