Mercurial > vim
comparison src/viminfo.c @ 17464:3e708b5c0509 v8.1.1730
patch 8.1.1730: wrong place for mark viminfo support
commit https://github.com/vim/vim/commit/1e78e69680a5f52970d9b1ef60710e556b09b8c2
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon Jul 22 20:18:27 2019 +0200
patch 8.1.1730: wrong place for mark viminfo support
Problem: Wrong place for mark viminfo support.
Solution: Move it to viminfo.c. (Yegappan Lakshmanan, closes https://github.com/vim/vim/issues/4716)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Mon, 22 Jul 2019 20:30:05 +0200 |
parents | e43f0c0c491c |
children | 15de78cb9f39 |
comparison
equal
deleted
inserted
replaced
17463:16f01738068b | 17464:3e708b5c0509 |
---|---|
1906 else | 1906 else |
1907 write_viminfo(eap->arg, eap->forceit); | 1907 write_viminfo(eap->arg, eap->forceit); |
1908 p_viminfo = save_viminfo; | 1908 p_viminfo = save_viminfo; |
1909 } | 1909 } |
1910 | 1910 |
1911 int | |
1912 read_viminfo_filemark(vir_T *virp, int force) | |
1913 { | |
1914 char_u *str; | |
1915 xfmark_T *namedfm_p = get_namedfm(); | |
1916 xfmark_T *fm; | |
1917 int i; | |
1918 | |
1919 // We only get here if line[0] == '\'' or '-'. | |
1920 // Illegal mark names are ignored (for future expansion). | |
1921 str = virp->vir_line + 1; | |
1922 if ( | |
1923 #ifndef EBCDIC | |
1924 *str <= 127 && | |
1925 #endif | |
1926 ((*virp->vir_line == '\'' && (VIM_ISDIGIT(*str) || isupper(*str))) | |
1927 || (*virp->vir_line == '-' && *str == '\''))) | |
1928 { | |
1929 if (*str == '\'') | |
1930 { | |
1931 #ifdef FEAT_JUMPLIST | |
1932 // If the jumplist isn't full insert fmark as oldest entry | |
1933 if (curwin->w_jumplistlen == JUMPLISTSIZE) | |
1934 fm = NULL; | |
1935 else | |
1936 { | |
1937 for (i = curwin->w_jumplistlen; i > 0; --i) | |
1938 curwin->w_jumplist[i] = curwin->w_jumplist[i - 1]; | |
1939 ++curwin->w_jumplistidx; | |
1940 ++curwin->w_jumplistlen; | |
1941 fm = &curwin->w_jumplist[0]; | |
1942 fm->fmark.mark.lnum = 0; | |
1943 fm->fname = NULL; | |
1944 } | |
1945 #else | |
1946 fm = NULL; | |
1947 #endif | |
1948 } | |
1949 else if (VIM_ISDIGIT(*str)) | |
1950 fm = &namedfm_p[*str - '0' + NMARKS]; | |
1951 else | |
1952 fm = &namedfm_p[*str - 'A']; | |
1953 if (fm != NULL && (fm->fmark.mark.lnum == 0 || force)) | |
1954 { | |
1955 str = skipwhite(str + 1); | |
1956 fm->fmark.mark.lnum = getdigits(&str); | |
1957 str = skipwhite(str); | |
1958 fm->fmark.mark.col = getdigits(&str); | |
1959 fm->fmark.mark.coladd = 0; | |
1960 fm->fmark.fnum = 0; | |
1961 str = skipwhite(str); | |
1962 vim_free(fm->fname); | |
1963 fm->fname = viminfo_readstring(virp, (int)(str - virp->vir_line), | |
1964 FALSE); | |
1965 fm->time_set = 0; | |
1966 } | |
1967 } | |
1968 return vim_fgets(virp->vir_line, LSIZE, virp->vir_fd); | |
1969 } | |
1970 | |
1971 static xfmark_T *vi_namedfm = NULL; | |
1972 #ifdef FEAT_JUMPLIST | |
1973 static xfmark_T *vi_jumplist = NULL; | |
1974 static int vi_jumplist_len = 0; | |
1975 #endif | |
1976 | |
1977 /* | |
1978 * Prepare for reading viminfo marks when writing viminfo later. | |
1979 */ | |
1980 void | |
1981 prepare_viminfo_marks(void) | |
1982 { | |
1983 vi_namedfm = ALLOC_CLEAR_MULT(xfmark_T, NMARKS + EXTRA_MARKS); | |
1984 #ifdef FEAT_JUMPLIST | |
1985 vi_jumplist = ALLOC_CLEAR_MULT(xfmark_T, JUMPLISTSIZE); | |
1986 vi_jumplist_len = 0; | |
1987 #endif | |
1988 } | |
1989 | |
1990 void | |
1991 finish_viminfo_marks(void) | |
1992 { | |
1993 int i; | |
1994 | |
1995 if (vi_namedfm != NULL) | |
1996 { | |
1997 for (i = 0; i < NMARKS + EXTRA_MARKS; ++i) | |
1998 vim_free(vi_namedfm[i].fname); | |
1999 VIM_CLEAR(vi_namedfm); | |
2000 } | |
2001 #ifdef FEAT_JUMPLIST | |
2002 if (vi_jumplist != NULL) | |
2003 { | |
2004 for (i = 0; i < vi_jumplist_len; ++i) | |
2005 vim_free(vi_jumplist[i].fname); | |
2006 VIM_CLEAR(vi_jumplist); | |
2007 } | |
2008 #endif | |
2009 } | |
2010 | |
2011 /* | |
2012 * Accept a new style mark line from the viminfo, store it when it's new. | |
2013 */ | |
2014 void | |
2015 handle_viminfo_mark(garray_T *values, int force) | |
2016 { | |
2017 bval_T *vp = (bval_T *)values->ga_data; | |
2018 int name; | |
2019 linenr_T lnum; | |
2020 colnr_T col; | |
2021 time_t timestamp; | |
2022 xfmark_T *fm = NULL; | |
2023 | |
2024 // Check the format: | |
2025 // |{bartype},{name},{lnum},{col},{timestamp},{filename} | |
2026 if (values->ga_len < 5 | |
2027 || vp[0].bv_type != BVAL_NR | |
2028 || vp[1].bv_type != BVAL_NR | |
2029 || vp[2].bv_type != BVAL_NR | |
2030 || vp[3].bv_type != BVAL_NR | |
2031 || vp[4].bv_type != BVAL_STRING) | |
2032 return; | |
2033 | |
2034 name = vp[0].bv_nr; | |
2035 if (name != '\'' && !VIM_ISDIGIT(name) && !ASCII_ISUPPER(name)) | |
2036 return; | |
2037 lnum = vp[1].bv_nr; | |
2038 col = vp[2].bv_nr; | |
2039 if (lnum <= 0 || col < 0) | |
2040 return; | |
2041 timestamp = (time_t)vp[3].bv_nr; | |
2042 | |
2043 if (name == '\'') | |
2044 { | |
2045 #ifdef FEAT_JUMPLIST | |
2046 if (vi_jumplist != NULL) | |
2047 { | |
2048 if (vi_jumplist_len < JUMPLISTSIZE) | |
2049 fm = &vi_jumplist[vi_jumplist_len++]; | |
2050 } | |
2051 else | |
2052 { | |
2053 int idx; | |
2054 int i; | |
2055 | |
2056 // If we have a timestamp insert it in the right place. | |
2057 if (timestamp != 0) | |
2058 { | |
2059 for (idx = curwin->w_jumplistlen - 1; idx >= 0; --idx) | |
2060 if (curwin->w_jumplist[idx].time_set < timestamp) | |
2061 { | |
2062 ++idx; | |
2063 break; | |
2064 } | |
2065 // idx cannot be zero now | |
2066 if (idx < 0 && curwin->w_jumplistlen < JUMPLISTSIZE) | |
2067 // insert as the oldest entry | |
2068 idx = 0; | |
2069 } | |
2070 else if (curwin->w_jumplistlen < JUMPLISTSIZE) | |
2071 // insert as oldest entry | |
2072 idx = 0; | |
2073 else | |
2074 idx = -1; | |
2075 | |
2076 if (idx >= 0) | |
2077 { | |
2078 if (curwin->w_jumplistlen == JUMPLISTSIZE) | |
2079 { | |
2080 // Drop the oldest entry. | |
2081 --idx; | |
2082 vim_free(curwin->w_jumplist[0].fname); | |
2083 for (i = 0; i < idx; ++i) | |
2084 curwin->w_jumplist[i] = curwin->w_jumplist[i + 1]; | |
2085 } | |
2086 else | |
2087 { | |
2088 // Move newer entries forward. | |
2089 for (i = curwin->w_jumplistlen; i > idx; --i) | |
2090 curwin->w_jumplist[i] = curwin->w_jumplist[i - 1]; | |
2091 ++curwin->w_jumplistidx; | |
2092 ++curwin->w_jumplistlen; | |
2093 } | |
2094 fm = &curwin->w_jumplist[idx]; | |
2095 fm->fmark.mark.lnum = 0; | |
2096 fm->fname = NULL; | |
2097 fm->time_set = 0; | |
2098 } | |
2099 } | |
2100 #endif | |
2101 } | |
2102 else | |
2103 { | |
2104 int idx; | |
2105 xfmark_T *namedfm_p = get_namedfm(); | |
2106 | |
2107 if (VIM_ISDIGIT(name)) | |
2108 { | |
2109 if (vi_namedfm != NULL) | |
2110 idx = name - '0' + NMARKS; | |
2111 else | |
2112 { | |
2113 int i; | |
2114 | |
2115 // Do not use the name from the viminfo file, insert in time | |
2116 // order. | |
2117 for (idx = NMARKS; idx < NMARKS + EXTRA_MARKS; ++idx) | |
2118 if (namedfm_p[idx].time_set < timestamp) | |
2119 break; | |
2120 if (idx == NMARKS + EXTRA_MARKS) | |
2121 // All existing entries are newer. | |
2122 return; | |
2123 i = NMARKS + EXTRA_MARKS - 1; | |
2124 | |
2125 vim_free(namedfm_p[i].fname); | |
2126 for ( ; i > idx; --i) | |
2127 namedfm_p[i] = namedfm_p[i - 1]; | |
2128 namedfm_p[idx].fname = NULL; | |
2129 } | |
2130 } | |
2131 else | |
2132 idx = name - 'A'; | |
2133 if (vi_namedfm != NULL) | |
2134 fm = &vi_namedfm[idx]; | |
2135 else | |
2136 fm = &namedfm_p[idx]; | |
2137 } | |
2138 | |
2139 if (fm != NULL) | |
2140 { | |
2141 if (vi_namedfm != NULL || fm->fmark.mark.lnum == 0 | |
2142 || fm->time_set < timestamp || force) | |
2143 { | |
2144 fm->fmark.mark.lnum = lnum; | |
2145 fm->fmark.mark.col = col; | |
2146 fm->fmark.mark.coladd = 0; | |
2147 fm->fmark.fnum = 0; | |
2148 vim_free(fm->fname); | |
2149 if (vp[4].bv_allocated) | |
2150 { | |
2151 fm->fname = vp[4].bv_string; | |
2152 vp[4].bv_string = NULL; | |
2153 } | |
2154 else | |
2155 fm->fname = vim_strsave(vp[4].bv_string); | |
2156 fm->time_set = timestamp; | |
2157 } | |
2158 } | |
2159 } | |
2160 | |
2161 /* | |
2162 * Return TRUE if marks for "buf" should not be written. | |
2163 */ | |
2164 static int | |
2165 skip_for_viminfo(buf_T *buf) | |
2166 { | |
2167 return | |
2168 #ifdef FEAT_TERMINAL | |
2169 bt_terminal(buf) || | |
2170 #endif | |
2171 removable(buf->b_ffname); | |
2172 } | |
2173 | |
2174 static void | |
2175 write_one_filemark( | |
2176 FILE *fp, | |
2177 xfmark_T *fm, | |
2178 int c1, | |
2179 int c2) | |
2180 { | |
2181 char_u *name; | |
2182 | |
2183 if (fm->fmark.mark.lnum == 0) // not set | |
2184 return; | |
2185 | |
2186 if (fm->fmark.fnum != 0) // there is a buffer | |
2187 name = buflist_nr2name(fm->fmark.fnum, TRUE, FALSE); | |
2188 else | |
2189 name = fm->fname; // use name from .viminfo | |
2190 if (name != NULL && *name != NUL) | |
2191 { | |
2192 fprintf(fp, "%c%c %ld %ld ", c1, c2, (long)fm->fmark.mark.lnum, | |
2193 (long)fm->fmark.mark.col); | |
2194 viminfo_writestring(fp, name); | |
2195 | |
2196 // Barline: |{bartype},{name},{lnum},{col},{timestamp},{filename} | |
2197 // size up to filename: 8 + 3 * 20 | |
2198 fprintf(fp, "|%d,%d,%ld,%ld,%ld,", BARTYPE_MARK, c2, | |
2199 (long)fm->fmark.mark.lnum, (long)fm->fmark.mark.col, | |
2200 (long)fm->time_set); | |
2201 barline_writestring(fp, name, LSIZE - 70); | |
2202 putc('\n', fp); | |
2203 } | |
2204 | |
2205 if (fm->fmark.fnum != 0) | |
2206 vim_free(name); | |
2207 } | |
2208 | |
2209 void | |
2210 write_viminfo_filemarks(FILE *fp) | |
2211 { | |
2212 int i; | |
2213 char_u *name; | |
2214 buf_T *buf; | |
2215 xfmark_T *namedfm_p = get_namedfm(); | |
2216 xfmark_T *fm; | |
2217 int vi_idx; | |
2218 int idx; | |
2219 | |
2220 if (get_viminfo_parameter('f') == 0) | |
2221 return; | |
2222 | |
2223 fputs(_("\n# File marks:\n"), fp); | |
2224 | |
2225 // Write the filemarks 'A - 'Z | |
2226 for (i = 0; i < NMARKS; i++) | |
2227 { | |
2228 if (vi_namedfm != NULL | |
2229 && (vi_namedfm[i].time_set > namedfm_p[i].time_set | |
2230 || namedfm_p[i].fmark.mark.lnum == 0)) | |
2231 fm = &vi_namedfm[i]; | |
2232 else | |
2233 fm = &namedfm_p[i]; | |
2234 write_one_filemark(fp, fm, '\'', i + 'A'); | |
2235 } | |
2236 | |
2237 // Find a mark that is the same file and position as the cursor. | |
2238 // That one, or else the last one is deleted. | |
2239 // Move '0 to '1, '1 to '2, etc. until the matching one or '9 | |
2240 // Set the '0 mark to current cursor position. | |
2241 if (curbuf->b_ffname != NULL && !skip_for_viminfo(curbuf)) | |
2242 { | |
2243 name = buflist_nr2name(curbuf->b_fnum, TRUE, FALSE); | |
2244 for (i = NMARKS; i < NMARKS + EXTRA_MARKS - 1; ++i) | |
2245 if (namedfm_p[i].fmark.mark.lnum == curwin->w_cursor.lnum | |
2246 && (namedfm_p[i].fname == NULL | |
2247 ? namedfm_p[i].fmark.fnum == curbuf->b_fnum | |
2248 : (name != NULL | |
2249 && STRCMP(name, namedfm_p[i].fname) == 0))) | |
2250 break; | |
2251 vim_free(name); | |
2252 | |
2253 vim_free(namedfm_p[i].fname); | |
2254 for ( ; i > NMARKS; --i) | |
2255 namedfm_p[i] = namedfm_p[i - 1]; | |
2256 namedfm_p[NMARKS].fmark.mark = curwin->w_cursor; | |
2257 namedfm_p[NMARKS].fmark.fnum = curbuf->b_fnum; | |
2258 namedfm_p[NMARKS].fname = NULL; | |
2259 namedfm_p[NMARKS].time_set = vim_time(); | |
2260 } | |
2261 | |
2262 // Write the filemarks '0 - '9. Newest (highest timestamp) first. | |
2263 vi_idx = NMARKS; | |
2264 idx = NMARKS; | |
2265 for (i = NMARKS; i < NMARKS + EXTRA_MARKS; i++) | |
2266 { | |
2267 xfmark_T *vi_fm = vi_namedfm != NULL ? &vi_namedfm[vi_idx] : NULL; | |
2268 | |
2269 if (vi_fm != NULL | |
2270 && vi_fm->fmark.mark.lnum != 0 | |
2271 && (vi_fm->time_set > namedfm_p[idx].time_set | |
2272 || namedfm_p[idx].fmark.mark.lnum == 0)) | |
2273 { | |
2274 fm = vi_fm; | |
2275 ++vi_idx; | |
2276 } | |
2277 else | |
2278 { | |
2279 fm = &namedfm_p[idx++]; | |
2280 if (vi_fm != NULL | |
2281 && vi_fm->fmark.mark.lnum == fm->fmark.mark.lnum | |
2282 && vi_fm->time_set == fm->time_set | |
2283 && ((vi_fm->fmark.fnum != 0 | |
2284 && vi_fm->fmark.fnum == fm->fmark.fnum) | |
2285 || (vi_fm->fname != NULL | |
2286 && fm->fname != NULL | |
2287 && STRCMP(vi_fm->fname, fm->fname) == 0))) | |
2288 ++vi_idx; // skip duplicate | |
2289 } | |
2290 write_one_filemark(fp, fm, '\'', i - NMARKS + '0'); | |
2291 } | |
2292 | |
2293 #ifdef FEAT_JUMPLIST | |
2294 // Write the jumplist with -' | |
2295 fputs(_("\n# Jumplist (newest first):\n"), fp); | |
2296 setpcmark(); // add current cursor position | |
2297 cleanup_jumplist(curwin, FALSE); | |
2298 vi_idx = 0; | |
2299 idx = curwin->w_jumplistlen - 1; | |
2300 for (i = 0; i < JUMPLISTSIZE; ++i) | |
2301 { | |
2302 xfmark_T *vi_fm; | |
2303 | |
2304 fm = idx >= 0 ? &curwin->w_jumplist[idx] : NULL; | |
2305 vi_fm = vi_idx < vi_jumplist_len ? &vi_jumplist[vi_idx] : NULL; | |
2306 if (fm == NULL && vi_fm == NULL) | |
2307 break; | |
2308 if (fm == NULL || (vi_fm != NULL && fm->time_set < vi_fm->time_set)) | |
2309 { | |
2310 fm = vi_fm; | |
2311 ++vi_idx; | |
2312 } | |
2313 else | |
2314 --idx; | |
2315 if (fm->fmark.fnum == 0 | |
2316 || ((buf = buflist_findnr(fm->fmark.fnum)) != NULL | |
2317 && !skip_for_viminfo(buf))) | |
2318 write_one_filemark(fp, fm, '-', '\''); | |
2319 } | |
2320 #endif | |
2321 } | |
2322 | |
2323 /* | |
2324 * Return TRUE if "name" is on removable media (depending on 'viminfo'). | |
2325 */ | |
2326 int | |
2327 removable(char_u *name) | |
2328 { | |
2329 char_u *p; | |
2330 char_u part[51]; | |
2331 int retval = FALSE; | |
2332 size_t n; | |
2333 | |
2334 name = home_replace_save(NULL, name); | |
2335 if (name != NULL) | |
2336 { | |
2337 for (p = p_viminfo; *p; ) | |
2338 { | |
2339 copy_option_part(&p, part, 51, ", "); | |
2340 if (part[0] == 'r') | |
2341 { | |
2342 n = STRLEN(part + 1); | |
2343 if (MB_STRNICMP(part + 1, name, n) == 0) | |
2344 { | |
2345 retval = TRUE; | |
2346 break; | |
2347 } | |
2348 } | |
2349 } | |
2350 vim_free(name); | |
2351 } | |
2352 return retval; | |
2353 } | |
2354 | |
2355 static void | |
2356 write_one_mark(FILE *fp_out, int c, pos_T *pos) | |
2357 { | |
2358 if (pos->lnum != 0) | |
2359 fprintf(fp_out, "\t%c\t%ld\t%d\n", c, (long)pos->lnum, (int)pos->col); | |
2360 } | |
2361 | |
2362 | |
2363 static void | |
2364 write_buffer_marks(buf_T *buf, FILE *fp_out) | |
2365 { | |
2366 int i; | |
2367 pos_T pos; | |
2368 | |
2369 home_replace(NULL, buf->b_ffname, IObuff, IOSIZE, TRUE); | |
2370 fprintf(fp_out, "\n> "); | |
2371 viminfo_writestring(fp_out, IObuff); | |
2372 | |
2373 // Write the last used timestamp as the lnum of the non-existing mark '*'. | |
2374 // Older Vims will ignore it and/or copy it. | |
2375 pos.lnum = (linenr_T)buf->b_last_used; | |
2376 pos.col = 0; | |
2377 write_one_mark(fp_out, '*', &pos); | |
2378 | |
2379 write_one_mark(fp_out, '"', &buf->b_last_cursor); | |
2380 write_one_mark(fp_out, '^', &buf->b_last_insert); | |
2381 write_one_mark(fp_out, '.', &buf->b_last_change); | |
2382 #ifdef FEAT_JUMPLIST | |
2383 // changelist positions are stored oldest first | |
2384 for (i = 0; i < buf->b_changelistlen; ++i) | |
2385 { | |
2386 // skip duplicates | |
2387 if (i == 0 || !EQUAL_POS(buf->b_changelist[i - 1], | |
2388 buf->b_changelist[i])) | |
2389 write_one_mark(fp_out, '+', &buf->b_changelist[i]); | |
2390 } | |
2391 #endif | |
2392 for (i = 0; i < NMARKS; i++) | |
2393 write_one_mark(fp_out, 'a' + i, &buf->b_namedm[i]); | |
2394 } | |
2395 | |
2396 /* | |
2397 * Write all the named marks for all buffers. | |
2398 * When "buflist" is not NULL fill it with the buffers for which marks are to | |
2399 * be written. | |
2400 */ | |
2401 void | |
2402 write_viminfo_marks(FILE *fp_out, garray_T *buflist) | |
2403 { | |
2404 buf_T *buf; | |
2405 int is_mark_set; | |
2406 int i; | |
2407 win_T *win; | |
2408 tabpage_T *tp; | |
2409 | |
2410 // Set b_last_cursor for the all buffers that have a window. | |
2411 FOR_ALL_TAB_WINDOWS(tp, win) | |
2412 set_last_cursor(win); | |
2413 | |
2414 fputs(_("\n# History of marks within files (newest to oldest):\n"), fp_out); | |
2415 FOR_ALL_BUFFERS(buf) | |
2416 { | |
2417 // Only write something if buffer has been loaded and at least one | |
2418 // mark is set. | |
2419 if (buf->b_marks_read) | |
2420 { | |
2421 if (buf->b_last_cursor.lnum != 0) | |
2422 is_mark_set = TRUE; | |
2423 else | |
2424 { | |
2425 is_mark_set = FALSE; | |
2426 for (i = 0; i < NMARKS; i++) | |
2427 if (buf->b_namedm[i].lnum != 0) | |
2428 { | |
2429 is_mark_set = TRUE; | |
2430 break; | |
2431 } | |
2432 } | |
2433 if (is_mark_set && buf->b_ffname != NULL | |
2434 && buf->b_ffname[0] != NUL | |
2435 && !skip_for_viminfo(buf)) | |
2436 { | |
2437 if (buflist == NULL) | |
2438 write_buffer_marks(buf, fp_out); | |
2439 else if (ga_grow(buflist, 1) == OK) | |
2440 ((buf_T **)buflist->ga_data)[buflist->ga_len++] = buf; | |
2441 } | |
2442 } | |
2443 } | |
2444 } | |
2445 | |
2446 /* | |
2447 * Compare functions for qsort() below, that compares b_last_used. | |
2448 */ | |
2449 static int | |
2450 buf_compare(const void *s1, const void *s2) | |
2451 { | |
2452 buf_T *buf1 = *(buf_T **)s1; | |
2453 buf_T *buf2 = *(buf_T **)s2; | |
2454 | |
2455 if (buf1->b_last_used == buf2->b_last_used) | |
2456 return 0; | |
2457 return buf1->b_last_used > buf2->b_last_used ? -1 : 1; | |
2458 } | |
2459 | |
2460 /* | |
2461 * Handle marks in the viminfo file: | |
2462 * fp_out != NULL: copy marks, in time order with buffers in "buflist". | |
2463 * fp_out == NULL && (flags & VIF_WANT_MARKS): read marks for curbuf only | |
2464 * fp_out == NULL && (flags & VIF_GET_OLDFILES | VIF_FORCEIT): fill v:oldfiles | |
2465 */ | |
2466 void | |
2467 copy_viminfo_marks( | |
2468 vir_T *virp, | |
2469 FILE *fp_out, | |
2470 garray_T *buflist, | |
2471 int eof, | |
2472 int flags) | |
2473 { | |
2474 char_u *line = virp->vir_line; | |
2475 buf_T *buf; | |
2476 int num_marked_files; | |
2477 int load_marks; | |
2478 int copy_marks_out; | |
2479 char_u *str; | |
2480 int i; | |
2481 char_u *p; | |
2482 char_u *name_buf; | |
2483 pos_T pos; | |
2484 #ifdef FEAT_EVAL | |
2485 list_T *list = NULL; | |
2486 #endif | |
2487 int count = 0; | |
2488 int buflist_used = 0; | |
2489 buf_T *buflist_buf = NULL; | |
2490 | |
2491 if ((name_buf = alloc(LSIZE)) == NULL) | |
2492 return; | |
2493 *name_buf = NUL; | |
2494 | |
2495 if (fp_out != NULL && buflist->ga_len > 0) | |
2496 { | |
2497 // Sort the list of buffers on b_last_used. | |
2498 qsort(buflist->ga_data, (size_t)buflist->ga_len, | |
2499 sizeof(buf_T *), buf_compare); | |
2500 buflist_buf = ((buf_T **)buflist->ga_data)[0]; | |
2501 } | |
2502 | |
2503 #ifdef FEAT_EVAL | |
2504 if (fp_out == NULL && (flags & (VIF_GET_OLDFILES | VIF_FORCEIT))) | |
2505 { | |
2506 list = list_alloc(); | |
2507 if (list != NULL) | |
2508 set_vim_var_list(VV_OLDFILES, list); | |
2509 } | |
2510 #endif | |
2511 | |
2512 num_marked_files = get_viminfo_parameter('\''); | |
2513 while (!eof && (count < num_marked_files || fp_out == NULL)) | |
2514 { | |
2515 if (line[0] != '>') | |
2516 { | |
2517 if (line[0] != '\n' && line[0] != '\r' && line[0] != '#') | |
2518 { | |
2519 if (viminfo_error("E576: ", _("Missing '>'"), line)) | |
2520 break; // too many errors, return now | |
2521 } | |
2522 eof = vim_fgets(line, LSIZE, virp->vir_fd); | |
2523 continue; // Skip this dud line | |
2524 } | |
2525 | |
2526 // Handle long line and translate escaped characters. | |
2527 // Find file name, set str to start. | |
2528 // Ignore leading and trailing white space. | |
2529 str = skipwhite(line + 1); | |
2530 str = viminfo_readstring(virp, (int)(str - virp->vir_line), FALSE); | |
2531 if (str == NULL) | |
2532 continue; | |
2533 p = str + STRLEN(str); | |
2534 while (p != str && (*p == NUL || vim_isspace(*p))) | |
2535 p--; | |
2536 if (*p) | |
2537 p++; | |
2538 *p = NUL; | |
2539 | |
2540 #ifdef FEAT_EVAL | |
2541 if (list != NULL) | |
2542 list_append_string(list, str, -1); | |
2543 #endif | |
2544 | |
2545 // If fp_out == NULL, load marks for current buffer. | |
2546 // If fp_out != NULL, copy marks for buffers not in buflist. | |
2547 load_marks = copy_marks_out = FALSE; | |
2548 if (fp_out == NULL) | |
2549 { | |
2550 if ((flags & VIF_WANT_MARKS) && curbuf->b_ffname != NULL) | |
2551 { | |
2552 if (*name_buf == NUL) // only need to do this once | |
2553 home_replace(NULL, curbuf->b_ffname, name_buf, LSIZE, TRUE); | |
2554 if (fnamecmp(str, name_buf) == 0) | |
2555 load_marks = TRUE; | |
2556 } | |
2557 } | |
2558 else // fp_out != NULL | |
2559 { | |
2560 // This is slow if there are many buffers!! | |
2561 FOR_ALL_BUFFERS(buf) | |
2562 if (buf->b_ffname != NULL) | |
2563 { | |
2564 home_replace(NULL, buf->b_ffname, name_buf, LSIZE, TRUE); | |
2565 if (fnamecmp(str, name_buf) == 0) | |
2566 break; | |
2567 } | |
2568 | |
2569 // Copy marks if the buffer has not been loaded. | |
2570 if (buf == NULL || !buf->b_marks_read) | |
2571 { | |
2572 int did_read_line = FALSE; | |
2573 | |
2574 if (buflist_buf != NULL) | |
2575 { | |
2576 // Read the next line. If it has the "*" mark compare the | |
2577 // time stamps. Write entries from "buflist" that are | |
2578 // newer. | |
2579 if (!(eof = viminfo_readline(virp)) && line[0] == TAB) | |
2580 { | |
2581 did_read_line = TRUE; | |
2582 if (line[1] == '*') | |
2583 { | |
2584 long ltime; | |
2585 | |
2586 sscanf((char *)line + 2, "%ld ", <ime); | |
2587 while ((time_T)ltime < buflist_buf->b_last_used) | |
2588 { | |
2589 write_buffer_marks(buflist_buf, fp_out); | |
2590 if (++count >= num_marked_files) | |
2591 break; | |
2592 if (++buflist_used == buflist->ga_len) | |
2593 { | |
2594 buflist_buf = NULL; | |
2595 break; | |
2596 } | |
2597 buflist_buf = | |
2598 ((buf_T **)buflist->ga_data)[buflist_used]; | |
2599 } | |
2600 } | |
2601 else | |
2602 { | |
2603 // No timestamp, must be written by an older Vim. | |
2604 // Assume all remaining buffers are older then | |
2605 // ours. | |
2606 while (count < num_marked_files | |
2607 && buflist_used < buflist->ga_len) | |
2608 { | |
2609 buflist_buf = ((buf_T **)buflist->ga_data) | |
2610 [buflist_used++]; | |
2611 write_buffer_marks(buflist_buf, fp_out); | |
2612 ++count; | |
2613 } | |
2614 buflist_buf = NULL; | |
2615 } | |
2616 | |
2617 if (count >= num_marked_files) | |
2618 { | |
2619 vim_free(str); | |
2620 break; | |
2621 } | |
2622 } | |
2623 } | |
2624 | |
2625 fputs("\n> ", fp_out); | |
2626 viminfo_writestring(fp_out, str); | |
2627 if (did_read_line) | |
2628 fputs((char *)line, fp_out); | |
2629 | |
2630 count++; | |
2631 copy_marks_out = TRUE; | |
2632 } | |
2633 } | |
2634 vim_free(str); | |
2635 | |
2636 pos.coladd = 0; | |
2637 while (!(eof = viminfo_readline(virp)) && line[0] == TAB) | |
2638 { | |
2639 if (load_marks) | |
2640 { | |
2641 if (line[1] != NUL) | |
2642 { | |
2643 unsigned u; | |
2644 | |
2645 sscanf((char *)line + 2, "%ld %u", &pos.lnum, &u); | |
2646 pos.col = u; | |
2647 switch (line[1]) | |
2648 { | |
2649 case '"': curbuf->b_last_cursor = pos; break; | |
2650 case '^': curbuf->b_last_insert = pos; break; | |
2651 case '.': curbuf->b_last_change = pos; break; | |
2652 case '+': | |
2653 #ifdef FEAT_JUMPLIST | |
2654 // changelist positions are stored oldest | |
2655 // first | |
2656 if (curbuf->b_changelistlen == JUMPLISTSIZE) | |
2657 // list is full, remove oldest entry | |
2658 mch_memmove(curbuf->b_changelist, | |
2659 curbuf->b_changelist + 1, | |
2660 sizeof(pos_T) * (JUMPLISTSIZE - 1)); | |
2661 else | |
2662 ++curbuf->b_changelistlen; | |
2663 curbuf->b_changelist[ | |
2664 curbuf->b_changelistlen - 1] = pos; | |
2665 #endif | |
2666 break; | |
2667 | |
2668 // Using the line number for the last-used | |
2669 // timestamp. | |
2670 case '*': curbuf->b_last_used = pos.lnum; break; | |
2671 | |
2672 default: if ((i = line[1] - 'a') >= 0 && i < NMARKS) | |
2673 curbuf->b_namedm[i] = pos; | |
2674 } | |
2675 } | |
2676 } | |
2677 else if (copy_marks_out) | |
2678 fputs((char *)line, fp_out); | |
2679 } | |
2680 | |
2681 if (load_marks) | |
2682 { | |
2683 #ifdef FEAT_JUMPLIST | |
2684 win_T *wp; | |
2685 | |
2686 FOR_ALL_WINDOWS(wp) | |
2687 { | |
2688 if (wp->w_buffer == curbuf) | |
2689 wp->w_changelistidx = curbuf->b_changelistlen; | |
2690 } | |
2691 #endif | |
2692 break; | |
2693 } | |
2694 } | |
2695 | |
2696 if (fp_out != NULL) | |
2697 // Write any remaining entries from buflist. | |
2698 while (count < num_marked_files && buflist_used < buflist->ga_len) | |
2699 { | |
2700 buflist_buf = ((buf_T **)buflist->ga_data)[buflist_used++]; | |
2701 write_buffer_marks(buflist_buf, fp_out); | |
2702 ++count; | |
2703 } | |
2704 | |
2705 vim_free(name_buf); | |
2706 } | |
1911 #endif // FEAT_VIMINFO | 2707 #endif // FEAT_VIMINFO |