xref: /vim-8.2.3635/src/viminfo.c (revision 736cd2cf)
1 /* vi:set ts=8 sts=4 sw=4 noet:
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  * viminfo.c: viminfo related functions
12  */
13 
14 #include "vim.h"
15 #include "version.h"
16 
17 #if defined(FEAT_VIMINFO) || defined(PROTO)
18 
19 static int  viminfo_errcnt;
20 
21 /*
22  * Find the parameter represented by the given character (eg ''', ':', '"', or
23  * '/') in the 'viminfo' option and return a pointer to the string after it.
24  * Return NULL if the parameter is not specified in the string.
25  */
26     static char_u *
27 find_viminfo_parameter(int type)
28 {
29     char_u  *p;
30 
31     for (p = p_viminfo; *p; ++p)
32     {
33 	if (*p == type)
34 	    return p + 1;
35 	if (*p == 'n')		    // 'n' is always the last one
36 	    break;
37 	p = vim_strchr(p, ',');	    // skip until next ','
38 	if (p == NULL)		    // hit the end without finding parameter
39 	    break;
40     }
41     return NULL;
42 }
43 
44 /*
45  * Find the parameter represented by the given character (eg ', :, ", or /),
46  * and return its associated value in the 'viminfo' string.
47  * Only works for number parameters, not for 'r' or 'n'.
48  * If the parameter is not specified in the string or there is no following
49  * number, return -1.
50  */
51     int
52 get_viminfo_parameter(int type)
53 {
54     char_u  *p;
55 
56     p = find_viminfo_parameter(type);
57     if (p != NULL && VIM_ISDIGIT(*p))
58 	return atoi((char *)p);
59     return -1;
60 }
61 
62 /*
63  * Get the viminfo file name to use.
64  * If "file" is given and not empty, use it (has already been expanded by
65  * cmdline functions).
66  * Otherwise use "-i file_name", value from 'viminfo' or the default, and
67  * expand environment variables.
68  * Returns an allocated string.  NULL when out of memory.
69  */
70     static char_u *
71 viminfo_filename(char_u *file)
72 {
73     if (file == NULL || *file == NUL)
74     {
75 	if (*p_viminfofile != NUL)
76 	    file = p_viminfofile;
77 	else if ((file = find_viminfo_parameter('n')) == NULL || *file == NUL)
78 	{
79 #ifdef VIMINFO_FILE2
80 # ifdef VMS
81 	    if (mch_getenv((char_u *)"SYS$LOGIN") == NULL)
82 # else
83 #  ifdef MSWIN
84 	    // Use $VIM only if $HOME is the default "C:/".
85 	    if (STRCMP(vim_getenv((char_u *)"HOME", NULL), "C:/") == 0
86 		    && mch_getenv((char_u *)"HOME") == NULL)
87 #  else
88 	    if (mch_getenv((char_u *)"HOME") == NULL)
89 #  endif
90 # endif
91 	    {
92 		// don't use $VIM when not available.
93 		expand_env((char_u *)"$VIM", NameBuff, MAXPATHL);
94 		if (STRCMP("$VIM", NameBuff) != 0)  // $VIM was expanded
95 		    file = (char_u *)VIMINFO_FILE2;
96 		else
97 		    file = (char_u *)VIMINFO_FILE;
98 	    }
99 	    else
100 #endif
101 		file = (char_u *)VIMINFO_FILE;
102 	}
103 	expand_env(file, NameBuff, MAXPATHL);
104 	file = NameBuff;
105     }
106     return vim_strsave(file);
107 }
108 
109 /*
110  * write string to viminfo file
111  * - replace CTRL-V with CTRL-V CTRL-V
112  * - replace '\n'   with CTRL-V 'n'
113  * - add a '\n' at the end
114  *
115  * For a long line:
116  * - write " CTRL-V <length> \n " in first line
117  * - write " < <string> \n "	  in second line
118  */
119     static void
120 viminfo_writestring(FILE *fd, char_u *p)
121 {
122     int		c;
123     char_u	*s;
124     int		len = 0;
125 
126     for (s = p; *s != NUL; ++s)
127     {
128 	if (*s == Ctrl_V || *s == '\n')
129 	    ++len;
130 	++len;
131     }
132 
133     // If the string will be too long, write its length and put it in the next
134     // line.  Take into account that some room is needed for what comes before
135     // the string (e.g., variable name).  Add something to the length for the
136     // '<', NL and trailing NUL.
137     if (len > LSIZE / 2)
138 	fprintf(fd, IF_EB("\026%d\n<", CTRL_V_STR "%d\n<"), len + 3);
139 
140     while ((c = *p++) != NUL)
141     {
142 	if (c == Ctrl_V || c == '\n')
143 	{
144 	    putc(Ctrl_V, fd);
145 	    if (c == '\n')
146 		c = 'n';
147 	}
148 	putc(c, fd);
149     }
150     putc('\n', fd);
151 }
152 
153 /*
154  * Write a string in quotes that barline_parse() can read back.
155  * Breaks the line in less than LSIZE pieces when needed.
156  * Returns remaining characters in the line.
157  */
158     static int
159 barline_writestring(FILE *fd, char_u *s, int remaining_start)
160 {
161     char_u *p;
162     int	    remaining = remaining_start;
163     int	    len = 2;
164 
165     // Count the number of characters produced, including quotes.
166     for (p = s; *p != NUL; ++p)
167     {
168 	if (*p == NL)
169 	    len += 2;
170 	else if (*p == '"' || *p == '\\')
171 	    len += 2;
172 	else
173 	    ++len;
174     }
175     if (len > remaining - 2)
176     {
177 	fprintf(fd, ">%d\n|<", len);
178 	remaining = LSIZE - 20;
179     }
180 
181     putc('"', fd);
182     for (p = s; *p != NUL; ++p)
183     {
184 	if (*p == NL)
185 	{
186 	    putc('\\', fd);
187 	    putc('n', fd);
188 	    --remaining;
189 	}
190 	else if (*p == '"' || *p == '\\')
191 	{
192 	    putc('\\', fd);
193 	    putc(*p, fd);
194 	    --remaining;
195 	}
196 	else
197 	    putc(*p, fd);
198 	--remaining;
199 
200 	if (remaining < 3)
201 	{
202 	    putc('\n', fd);
203 	    putc('|', fd);
204 	    putc('<', fd);
205 	    // Leave enough space for another continuation.
206 	    remaining = LSIZE - 20;
207 	}
208     }
209     putc('"', fd);
210     return remaining - 2;
211 }
212 
213 /*
214  * Check string read from viminfo file.
215  * Remove '\n' at the end of the line.
216  * - replace CTRL-V CTRL-V with CTRL-V
217  * - replace CTRL-V 'n'    with '\n'
218  *
219  * Check for a long line as written by viminfo_writestring().
220  *
221  * Return the string in allocated memory (NULL when out of memory).
222  */
223     static char_u *
224 viminfo_readstring(
225     vir_T	*virp,
226     int		off,		    // offset for virp->vir_line
227     int		convert UNUSED)	    // convert the string
228 {
229     char_u	*retval;
230     char_u	*s, *d;
231     long	len;
232 
233     if (virp->vir_line[off] == Ctrl_V && vim_isdigit(virp->vir_line[off + 1]))
234     {
235 	len = atol((char *)virp->vir_line + off + 1);
236 	retval = lalloc(len, TRUE);
237 	if (retval == NULL)
238 	{
239 	    // Line too long?  File messed up?  Skip next line.
240 	    (void)vim_fgets(virp->vir_line, 10, virp->vir_fd);
241 	    return NULL;
242 	}
243 	(void)vim_fgets(retval, (int)len, virp->vir_fd);
244 	s = retval + 1;	    // Skip the leading '<'
245     }
246     else
247     {
248 	retval = vim_strsave(virp->vir_line + off);
249 	if (retval == NULL)
250 	    return NULL;
251 	s = retval;
252     }
253 
254     // Change CTRL-V CTRL-V to CTRL-V and CTRL-V n to \n in-place.
255     d = retval;
256     while (*s != NUL && *s != '\n')
257     {
258 	if (s[0] == Ctrl_V && s[1] != NUL)
259 	{
260 	    if (s[1] == 'n')
261 		*d++ = '\n';
262 	    else
263 		*d++ = Ctrl_V;
264 	    s += 2;
265 	}
266 	else
267 	    *d++ = *s++;
268     }
269     *d = NUL;
270 
271     if (convert && virp->vir_conv.vc_type != CONV_NONE && *retval != NUL)
272     {
273 	d = string_convert(&virp->vir_conv, retval, NULL);
274 	if (d != NULL)
275 	{
276 	    vim_free(retval);
277 	    retval = d;
278 	}
279     }
280 
281     return retval;
282 }
283 
284 /*
285  * Read a line from the viminfo file.
286  * Returns TRUE for end-of-file;
287  */
288     static int
289 viminfo_readline(vir_T *virp)
290 {
291     return vim_fgets(virp->vir_line, LSIZE, virp->vir_fd);
292 }
293 
294     static int
295 read_viminfo_bufferlist(
296     vir_T	*virp,
297     int		writing)
298 {
299     char_u	*tab;
300     linenr_T	lnum;
301     colnr_T	col;
302     buf_T	*buf;
303     char_u	*sfname;
304     char_u	*xline;
305 
306     // Handle long line and escaped characters.
307     xline = viminfo_readstring(virp, 1, FALSE);
308 
309     // don't read in if there are files on the command-line or if writing:
310     if (xline != NULL && !writing && ARGCOUNT == 0
311 				       && find_viminfo_parameter('%') != NULL)
312     {
313 	// Format is: <fname> Tab <lnum> Tab <col>.
314 	// Watch out for a Tab in the file name, work from the end.
315 	lnum = 0;
316 	col = 0;
317 	tab = vim_strrchr(xline, '\t');
318 	if (tab != NULL)
319 	{
320 	    *tab++ = '\0';
321 	    col = (colnr_T)atoi((char *)tab);
322 	    tab = vim_strrchr(xline, '\t');
323 	    if (tab != NULL)
324 	    {
325 		*tab++ = '\0';
326 		lnum = atol((char *)tab);
327 	    }
328 	}
329 
330 	// Expand "~/" in the file name at "line + 1" to a full path.
331 	// Then try shortening it by comparing with the current directory
332 	expand_env(xline, NameBuff, MAXPATHL);
333 	sfname = shorten_fname1(NameBuff);
334 
335 	buf = buflist_new(NameBuff, sfname, (linenr_T)0, BLN_LISTED);
336 	if (buf != NULL)	// just in case...
337 	{
338 	    buf->b_last_cursor.lnum = lnum;
339 	    buf->b_last_cursor.col = col;
340 	    buflist_setfpos(buf, curwin, lnum, col, FALSE);
341 	}
342     }
343     vim_free(xline);
344 
345     return viminfo_readline(virp);
346 }
347 
348 /*
349  * Return TRUE if "name" is on removable media (depending on 'viminfo').
350  */
351     static int
352 removable(char_u *name)
353 {
354     char_u  *p;
355     char_u  part[51];
356     int	    retval = FALSE;
357     size_t  n;
358 
359     name = home_replace_save(NULL, name);
360     if (name != NULL)
361     {
362 	for (p = p_viminfo; *p; )
363 	{
364 	    copy_option_part(&p, part, 51, ", ");
365 	    if (part[0] == 'r')
366 	    {
367 		n = STRLEN(part + 1);
368 		if (MB_STRNICMP(part + 1, name, n) == 0)
369 		{
370 		    retval = TRUE;
371 		    break;
372 		}
373 	    }
374 	}
375 	vim_free(name);
376     }
377     return retval;
378 }
379 
380     static void
381 write_viminfo_bufferlist(FILE *fp)
382 {
383     buf_T	*buf;
384     win_T	*win;
385     tabpage_T	*tp;
386     char_u	*line;
387     int		max_buffers;
388 
389     if (find_viminfo_parameter('%') == NULL)
390 	return;
391 
392     // Without a number -1 is returned: do all buffers.
393     max_buffers = get_viminfo_parameter('%');
394 
395     // Allocate room for the file name, lnum and col.
396 #define LINE_BUF_LEN (MAXPATHL + 40)
397     line = alloc(LINE_BUF_LEN);
398     if (line == NULL)
399 	return;
400 
401     FOR_ALL_TAB_WINDOWS(tp, win)
402 	set_last_cursor(win);
403 
404     fputs(_("\n# Buffer list:\n"), fp);
405     FOR_ALL_BUFFERS(buf)
406     {
407 	if (buf->b_fname == NULL
408 		|| !buf->b_p_bl
409 #ifdef FEAT_QUICKFIX
410 		|| bt_quickfix(buf)
411 #endif
412 #ifdef FEAT_TERMINAL
413 		|| bt_terminal(buf)
414 #endif
415 		|| removable(buf->b_ffname))
416 	    continue;
417 
418 	if (max_buffers-- == 0)
419 	    break;
420 	putc('%', fp);
421 	home_replace(NULL, buf->b_ffname, line, MAXPATHL, TRUE);
422 	vim_snprintf_add((char *)line, LINE_BUF_LEN, "\t%ld\t%d",
423 			(long)buf->b_last_cursor.lnum,
424 			buf->b_last_cursor.col);
425 	viminfo_writestring(fp, line);
426     }
427     vim_free(line);
428 }
429 
430 #if defined(FEAT_CMDHIST) || defined(PROTO)
431 /*
432  * Buffers for history read from a viminfo file.  Only valid while reading.
433  */
434 static histentry_T *viminfo_history[HIST_COUNT] =
435 					       {NULL, NULL, NULL, NULL, NULL};
436 static int	viminfo_hisidx[HIST_COUNT] = {0, 0, 0, 0, 0};
437 static int	viminfo_hislen[HIST_COUNT] = {0, 0, 0, 0, 0};
438 static int	viminfo_add_at_front = FALSE;
439 
440 /*
441  * Translate a history type number to the associated character.
442  */
443     static int
444 hist_type2char(
445     int	    type,
446     int	    use_question)	    // use '?' instead of '/'
447 {
448     if (type == HIST_CMD)
449 	return ':';
450     if (type == HIST_SEARCH)
451     {
452 	if (use_question)
453 	    return '?';
454 	else
455 	    return '/';
456     }
457     if (type == HIST_EXPR)
458 	return '=';
459     return '@';
460 }
461 
462 /*
463  * Prepare for reading the history from the viminfo file.
464  * This allocates history arrays to store the read history lines.
465  */
466     static void
467 prepare_viminfo_history(int asklen, int writing)
468 {
469     int	    i;
470     int	    num;
471     int	    type;
472     int	    len;
473     int	    hislen;
474 
475     init_history();
476     hislen = get_hislen();
477     viminfo_add_at_front = (asklen != 0 && !writing);
478     if (asklen > hislen)
479 	asklen = hislen;
480 
481     for (type = 0; type < HIST_COUNT; ++type)
482     {
483 	histentry_T *histentry = get_histentry(type);
484 
485 	// Count the number of empty spaces in the history list.  Entries read
486 	// from viminfo previously are also considered empty.  If there are
487 	// more spaces available than we request, then fill them up.
488 	for (i = 0, num = 0; i < hislen; i++)
489 	    if (histentry[i].hisstr == NULL || histentry[i].viminfo)
490 		num++;
491 	len = asklen;
492 	if (num > len)
493 	    len = num;
494 	if (len <= 0)
495 	    viminfo_history[type] = NULL;
496 	else
497 	    viminfo_history[type] = LALLOC_MULT(histentry_T, len);
498 	if (viminfo_history[type] == NULL)
499 	    len = 0;
500 	viminfo_hislen[type] = len;
501 	viminfo_hisidx[type] = 0;
502     }
503 }
504 
505 /*
506  * Accept a line from the viminfo, store it in the history array when it's
507  * new.
508  */
509     static int
510 read_viminfo_history(vir_T *virp, int writing)
511 {
512     int		type;
513     long_u	len;
514     char_u	*val;
515     char_u	*p;
516 
517     type = hist_char2type(virp->vir_line[0]);
518     if (viminfo_hisidx[type] < viminfo_hislen[type])
519     {
520 	val = viminfo_readstring(virp, 1, TRUE);
521 	if (val != NULL && *val != NUL)
522 	{
523 	    int sep = (*val == ' ' ? NUL : *val);
524 
525 	    if (!in_history(type, val + (type == HIST_SEARCH),
526 					  viminfo_add_at_front, sep, writing))
527 	    {
528 		// Need to re-allocate to append the separator byte.
529 		len = STRLEN(val);
530 		p = alloc(len + 2);
531 		if (p != NULL)
532 		{
533 		    if (type == HIST_SEARCH)
534 		    {
535 			// Search entry: Move the separator from the first
536 			// column to after the NUL.
537 			mch_memmove(p, val + 1, (size_t)len);
538 			p[len] = sep;
539 		    }
540 		    else
541 		    {
542 			// Not a search entry: No separator in the viminfo
543 			// file, add a NUL separator.
544 			mch_memmove(p, val, (size_t)len + 1);
545 			p[len + 1] = NUL;
546 		    }
547 		    viminfo_history[type][viminfo_hisidx[type]].hisstr = p;
548 		    viminfo_history[type][viminfo_hisidx[type]].time_set = 0;
549 		    viminfo_history[type][viminfo_hisidx[type]].viminfo = TRUE;
550 		    viminfo_history[type][viminfo_hisidx[type]].hisnum = 0;
551 		    viminfo_hisidx[type]++;
552 		}
553 	    }
554 	}
555 	vim_free(val);
556     }
557     return viminfo_readline(virp);
558 }
559 
560 /*
561  * Accept a new style history line from the viminfo, store it in the history
562  * array when it's new.
563  */
564     static void
565 handle_viminfo_history(
566 	garray_T    *values,
567 	int	    writing)
568 {
569     int		type;
570     long_u	len;
571     char_u	*val;
572     char_u	*p;
573     bval_T	*vp = (bval_T *)values->ga_data;
574 
575     // Check the format:
576     // |{bartype},{histtype},{timestamp},{separator},"text"
577     if (values->ga_len < 4
578 	    || vp[0].bv_type != BVAL_NR
579 	    || vp[1].bv_type != BVAL_NR
580 	    || (vp[2].bv_type != BVAL_NR && vp[2].bv_type != BVAL_EMPTY)
581 	    || vp[3].bv_type != BVAL_STRING)
582 	return;
583 
584     type = vp[0].bv_nr;
585     if (type >= HIST_COUNT)
586 	return;
587     if (viminfo_hisidx[type] < viminfo_hislen[type])
588     {
589 	val = vp[3].bv_string;
590 	if (val != NULL && *val != NUL)
591 	{
592 	    int sep = type == HIST_SEARCH && vp[2].bv_type == BVAL_NR
593 						      ? vp[2].bv_nr : NUL;
594 	    int idx;
595 	    int overwrite = FALSE;
596 
597 	    if (!in_history(type, val, viminfo_add_at_front, sep, writing))
598 	    {
599 		// If lines were written by an older Vim we need to avoid
600 		// getting duplicates. See if the entry already exists.
601 		for (idx = 0; idx < viminfo_hisidx[type]; ++idx)
602 		{
603 		    p = viminfo_history[type][idx].hisstr;
604 		    if (STRCMP(val, p) == 0
605 			  && (type != HIST_SEARCH || sep == p[STRLEN(p) + 1]))
606 		    {
607 			overwrite = TRUE;
608 			break;
609 		    }
610 		}
611 
612 		if (!overwrite)
613 		{
614 		    // Need to re-allocate to append the separator byte.
615 		    len = vp[3].bv_len;
616 		    p = alloc(len + 2);
617 		}
618 		else
619 		    len = 0; // for picky compilers
620 		if (p != NULL)
621 		{
622 		    viminfo_history[type][idx].time_set = vp[1].bv_nr;
623 		    if (!overwrite)
624 		    {
625 			mch_memmove(p, val, (size_t)len + 1);
626 			// Put the separator after the NUL.
627 			p[len + 1] = sep;
628 			viminfo_history[type][idx].hisstr = p;
629 			viminfo_history[type][idx].hisnum = 0;
630 			viminfo_history[type][idx].viminfo = TRUE;
631 			viminfo_hisidx[type]++;
632 		    }
633 		}
634 	    }
635 	}
636     }
637 }
638 
639 /*
640  * Concatenate history lines from viminfo after the lines typed in this Vim.
641  */
642     static void
643 concat_history(int type)
644 {
645     int		idx;
646     int		i;
647     int		hislen = get_hislen();
648     histentry_T *histentry = get_histentry(type);
649     int		*hisidx = get_hisidx(type);
650     int		*hisnum = get_hisnum(type);
651 
652     idx = *hisidx + viminfo_hisidx[type];
653     if (idx >= hislen)
654 	idx -= hislen;
655     else if (idx < 0)
656 	idx = hislen - 1;
657     if (viminfo_add_at_front)
658 	*hisidx = idx;
659     else
660     {
661 	if (*hisidx == -1)
662 	    *hisidx = hislen - 1;
663 	do
664 	{
665 	    if (histentry[idx].hisstr != NULL || histentry[idx].viminfo)
666 		break;
667 	    if (++idx == hislen)
668 		idx = 0;
669 	} while (idx != *hisidx);
670 	if (idx != *hisidx && --idx < 0)
671 	    idx = hislen - 1;
672     }
673     for (i = 0; i < viminfo_hisidx[type]; i++)
674     {
675 	vim_free(histentry[idx].hisstr);
676 	histentry[idx].hisstr = viminfo_history[type][i].hisstr;
677 	histentry[idx].viminfo = TRUE;
678 	histentry[idx].time_set = viminfo_history[type][i].time_set;
679 	if (--idx < 0)
680 	    idx = hislen - 1;
681     }
682     idx += 1;
683     idx %= hislen;
684     for (i = 0; i < viminfo_hisidx[type]; i++)
685     {
686 	histentry[idx++].hisnum = ++*hisnum;
687 	idx %= hislen;
688     }
689 }
690 
691     static int
692 sort_hist(const void *s1, const void *s2)
693 {
694     histentry_T *p1 = *(histentry_T **)s1;
695     histentry_T *p2 = *(histentry_T **)s2;
696 
697     if (p1->time_set < p2->time_set) return -1;
698     if (p1->time_set > p2->time_set) return 1;
699     return 0;
700 }
701 
702 /*
703  * Merge history lines from viminfo and lines typed in this Vim based on the
704  * timestamp;
705  */
706     static void
707 merge_history(int type)
708 {
709     int		max_len;
710     histentry_T **tot_hist;
711     histentry_T *new_hist;
712     int		i;
713     int		len;
714     int		hislen = get_hislen();
715     histentry_T *histentry = get_histentry(type);
716     int		*hisidx = get_hisidx(type);
717     int		*hisnum = get_hisnum(type);
718 
719     // Make one long list with all entries.
720     max_len = hislen + viminfo_hisidx[type];
721     tot_hist = ALLOC_MULT(histentry_T *, max_len);
722     new_hist = ALLOC_MULT(histentry_T, hislen);
723     if (tot_hist == NULL || new_hist == NULL)
724     {
725 	vim_free(tot_hist);
726 	vim_free(new_hist);
727 	return;
728     }
729     for (i = 0; i < viminfo_hisidx[type]; i++)
730 	tot_hist[i] = &viminfo_history[type][i];
731     len = i;
732     for (i = 0; i < hislen; i++)
733 	if (histentry[i].hisstr != NULL)
734 	    tot_hist[len++] = &histentry[i];
735 
736     // Sort the list on timestamp.
737     qsort((void *)tot_hist, (size_t)len, sizeof(histentry_T *), sort_hist);
738 
739     // Keep the newest ones.
740     for (i = 0; i < hislen; i++)
741     {
742 	if (i < len)
743 	{
744 	    new_hist[i] = *tot_hist[i];
745 	    tot_hist[i]->hisstr = NULL;
746 	    if (new_hist[i].hisnum == 0)
747 		new_hist[i].hisnum = ++*hisnum;
748 	}
749 	else
750 	    clear_hist_entry(&new_hist[i]);
751     }
752     *hisidx = (i < len ? i : len) - 1;
753 
754     // Free what is not kept.
755     for (i = 0; i < viminfo_hisidx[type]; i++)
756 	vim_free(viminfo_history[type][i].hisstr);
757     for (i = 0; i < hislen; i++)
758 	vim_free(histentry[i].hisstr);
759     vim_free(histentry);
760     set_histentry(type, new_hist);
761     vim_free(tot_hist);
762 }
763 
764 /*
765  * Finish reading history lines from viminfo.  Not used when writing viminfo.
766  */
767     static void
768 finish_viminfo_history(vir_T *virp)
769 {
770     int	type;
771     int merge = virp->vir_version >= VIMINFO_VERSION_WITH_HISTORY;
772 
773     for (type = 0; type < HIST_COUNT; ++type)
774     {
775 	if (get_histentry(type) == NULL)
776 	    continue;
777 
778 	if (merge)
779 	    merge_history(type);
780 	else
781 	    concat_history(type);
782 
783 	VIM_CLEAR(viminfo_history[type]);
784 	viminfo_hisidx[type] = 0;
785     }
786 }
787 
788 /*
789  * Write history to viminfo file in "fp".
790  * When "merge" is TRUE merge history lines with a previously read viminfo
791  * file, data is in viminfo_history[].
792  * When "merge" is FALSE just write all history lines.  Used for ":wviminfo!".
793  */
794     static void
795 write_viminfo_history(FILE *fp, int merge)
796 {
797     int	    i;
798     int	    type;
799     int	    num_saved;
800     int     round;
801     int	    hislen;
802 
803     init_history();
804     hislen = get_hislen();
805     if (hislen == 0)
806 	return;
807     for (type = 0; type < HIST_COUNT; ++type)
808     {
809 	histentry_T *histentry = get_histentry(type);
810 	int	    *hisidx = get_hisidx(type);
811 
812 	num_saved = get_viminfo_parameter(hist_type2char(type, FALSE));
813 	if (num_saved == 0)
814 	    continue;
815 	if (num_saved < 0)  // Use default
816 	    num_saved = hislen;
817 	fprintf(fp, _("\n# %s History (newest to oldest):\n"),
818 			    type == HIST_CMD ? _("Command Line") :
819 			    type == HIST_SEARCH ? _("Search String") :
820 			    type == HIST_EXPR ? _("Expression") :
821 			    type == HIST_INPUT ? _("Input Line") :
822 					_("Debug Line"));
823 	if (num_saved > hislen)
824 	    num_saved = hislen;
825 
826 	/*
827 	 * Merge typed and viminfo history:
828 	 * round 1: history of typed commands.
829 	 * round 2: history from recently read viminfo.
830 	 */
831 	for (round = 1; round <= 2; ++round)
832 	{
833 	    if (round == 1)
834 		// start at newest entry, somewhere in the list
835 		i = *hisidx;
836 	    else if (viminfo_hisidx[type] > 0)
837 		// start at newest entry, first in the list
838 		i = 0;
839 	    else
840 		// empty list
841 		i = -1;
842 	    if (i >= 0)
843 		while (num_saved > 0
844 			&& !(round == 2 && i >= viminfo_hisidx[type]))
845 		{
846 		    char_u  *p;
847 		    time_t  timestamp;
848 		    int	    c = NUL;
849 
850 		    if (round == 1)
851 		    {
852 			p = histentry[i].hisstr;
853 			timestamp = histentry[i].time_set;
854 		    }
855 		    else
856 		    {
857 			p = viminfo_history[type] == NULL ? NULL
858 					    : viminfo_history[type][i].hisstr;
859 			timestamp = viminfo_history[type] == NULL ? 0
860 					  : viminfo_history[type][i].time_set;
861 		    }
862 
863 		    if (p != NULL && (round == 2
864 				       || !merge
865 				       || !histentry[i].viminfo))
866 		    {
867 			--num_saved;
868 			fputc(hist_type2char(type, TRUE), fp);
869 			// For the search history: put the separator in the
870 			// second column; use a space if there isn't one.
871 			if (type == HIST_SEARCH)
872 			{
873 			    c = p[STRLEN(p) + 1];
874 			    putc(c == NUL ? ' ' : c, fp);
875 			}
876 			viminfo_writestring(fp, p);
877 
878 			{
879 			    char    cbuf[NUMBUFLEN];
880 
881 			    // New style history with a bar line. Format:
882 			    // |{bartype},{histtype},{timestamp},{separator},"text"
883 			    if (c == NUL)
884 				cbuf[0] = NUL;
885 			    else
886 				sprintf(cbuf, "%d", c);
887 			    fprintf(fp, "|%d,%d,%ld,%s,", BARTYPE_HISTORY,
888 						 type, (long)timestamp, cbuf);
889 			    barline_writestring(fp, p, LSIZE - 20);
890 			    putc('\n', fp);
891 			}
892 		    }
893 		    if (round == 1)
894 		    {
895 			// Decrement index, loop around and stop when back at
896 			// the start.
897 			if (--i < 0)
898 			    i = hislen - 1;
899 			if (i == *hisidx)
900 			    break;
901 		    }
902 		    else
903 		    {
904 			// Increment index. Stop at the end in the while.
905 			++i;
906 		    }
907 		}
908 	}
909 	for (i = 0; i < viminfo_hisidx[type]; ++i)
910 	    if (viminfo_history[type] != NULL)
911 		vim_free(viminfo_history[type][i].hisstr);
912 	VIM_CLEAR(viminfo_history[type]);
913 	viminfo_hisidx[type] = 0;
914     }
915 }
916 #endif // FEAT_CMDHIST
917 
918     static void
919 write_viminfo_barlines(vir_T *virp, FILE *fp_out)
920 {
921     int		i;
922     garray_T	*gap = &virp->vir_barlines;
923     int		seen_useful = FALSE;
924     char	*line;
925 
926     if (gap->ga_len > 0)
927     {
928 	fputs(_("\n# Bar lines, copied verbatim:\n"), fp_out);
929 
930 	// Skip over continuation lines until seeing a useful line.
931 	for (i = 0; i < gap->ga_len; ++i)
932 	{
933 	    line = ((char **)(gap->ga_data))[i];
934 	    if (seen_useful || line[1] != '<')
935 	    {
936 		fputs(line, fp_out);
937 		seen_useful = TRUE;
938 	    }
939 	}
940     }
941 }
942 
943 /*
944  * Parse a viminfo line starting with '|'.
945  * Add each decoded value to "values".
946  * Returns TRUE if the next line is to be read after using the parsed values.
947  */
948     static int
949 barline_parse(vir_T *virp, char_u *text, garray_T *values)
950 {
951     char_u  *p = text;
952     char_u  *nextp = NULL;
953     char_u  *buf = NULL;
954     bval_T  *value;
955     int	    i;
956     int	    allocated = FALSE;
957     int	    eof;
958     char_u  *sconv;
959     int	    converted;
960 
961     while (*p == ',')
962     {
963 	++p;
964 	if (ga_grow(values, 1) == FAIL)
965 	    break;
966 	value = (bval_T *)(values->ga_data) + values->ga_len;
967 
968 	if (*p == '>')
969 	{
970 	    // Need to read a continuation line.  Put strings in allocated
971 	    // memory, because virp->vir_line is overwritten.
972 	    if (!allocated)
973 	    {
974 		for (i = 0; i < values->ga_len; ++i)
975 		{
976 		    bval_T  *vp = (bval_T *)(values->ga_data) + i;
977 
978 		    if (vp->bv_type == BVAL_STRING && !vp->bv_allocated)
979 		    {
980 			vp->bv_string = vim_strnsave(vp->bv_string, vp->bv_len);
981 			vp->bv_allocated = TRUE;
982 		    }
983 		}
984 		allocated = TRUE;
985 	    }
986 
987 	    if (vim_isdigit(p[1]))
988 	    {
989 		size_t len;
990 		size_t todo;
991 		size_t n;
992 
993 		// String value was split into lines that are each shorter
994 		// than LSIZE:
995 		//     |{bartype},>{length of "{text}{text2}"}
996 		//     |<"{text1}
997 		//     |<{text2}",{value}
998 		// Length includes the quotes.
999 		++p;
1000 		len = getdigits(&p);
1001 		buf = alloc((int)(len + 1));
1002 		if (buf == NULL)
1003 		    return TRUE;
1004 		p = buf;
1005 		for (todo = len; todo > 0; todo -= n)
1006 		{
1007 		    eof = viminfo_readline(virp);
1008 		    if (eof || virp->vir_line[0] != '|'
1009 						  || virp->vir_line[1] != '<')
1010 		    {
1011 			// File was truncated or garbled. Read another line if
1012 			// this one starts with '|'.
1013 			vim_free(buf);
1014 			return eof || virp->vir_line[0] == '|';
1015 		    }
1016 		    // Get length of text, excluding |< and NL chars.
1017 		    n = STRLEN(virp->vir_line);
1018 		    while (n > 0 && (virp->vir_line[n - 1] == NL
1019 					     || virp->vir_line[n - 1] == CAR))
1020 			--n;
1021 		    n -= 2;
1022 		    if (n > todo)
1023 		    {
1024 			// more values follow after the string
1025 			nextp = virp->vir_line + 2 + todo;
1026 			n = todo;
1027 		    }
1028 		    mch_memmove(p, virp->vir_line + 2, n);
1029 		    p += n;
1030 		}
1031 		*p = NUL;
1032 		p = buf;
1033 	    }
1034 	    else
1035 	    {
1036 		// Line ending in ">" continues in the next line:
1037 		//     |{bartype},{lots of values},>
1038 		//     |<{value},{value}
1039 		eof = viminfo_readline(virp);
1040 		if (eof || virp->vir_line[0] != '|'
1041 					      || virp->vir_line[1] != '<')
1042 		    // File was truncated or garbled. Read another line if
1043 		    // this one starts with '|'.
1044 		    return eof || virp->vir_line[0] == '|';
1045 		p = virp->vir_line + 2;
1046 	    }
1047 	}
1048 
1049 	if (isdigit(*p))
1050 	{
1051 	    value->bv_type = BVAL_NR;
1052 	    value->bv_nr = getdigits(&p);
1053 	    ++values->ga_len;
1054 	}
1055 	else if (*p == '"')
1056 	{
1057 	    int	    len = 0;
1058 	    char_u  *s = p;
1059 
1060 	    // Unescape special characters in-place.
1061 	    ++p;
1062 	    while (*p != '"')
1063 	    {
1064 		if (*p == NL || *p == NUL)
1065 		    return TRUE;  // syntax error, drop the value
1066 		if (*p == '\\')
1067 		{
1068 		    ++p;
1069 		    if (*p == 'n')
1070 			s[len++] = '\n';
1071 		    else
1072 			s[len++] = *p;
1073 		    ++p;
1074 		}
1075 		else
1076 		    s[len++] = *p++;
1077 	    }
1078 	    ++p;
1079 	    s[len] = NUL;
1080 
1081 	    converted = FALSE;
1082 	    if (virp->vir_conv.vc_type != CONV_NONE && *s != NUL)
1083 	    {
1084 		sconv = string_convert(&virp->vir_conv, s, NULL);
1085 		if (sconv != NULL)
1086 		{
1087 		    if (s == buf)
1088 			vim_free(s);
1089 		    s = sconv;
1090 		    buf = s;
1091 		    converted = TRUE;
1092 		}
1093 	    }
1094 
1095 	    // Need to copy in allocated memory if the string wasn't allocated
1096 	    // above and we did allocate before, thus vir_line may change.
1097 	    if (s != buf && allocated)
1098 		s = vim_strsave(s);
1099 	    value->bv_string = s;
1100 	    value->bv_type = BVAL_STRING;
1101 	    value->bv_len = len;
1102 	    value->bv_allocated = allocated || converted;
1103 	    ++values->ga_len;
1104 	    if (nextp != NULL)
1105 	    {
1106 		// values following a long string
1107 		p = nextp;
1108 		nextp = NULL;
1109 	    }
1110 	}
1111 	else if (*p == ',')
1112 	{
1113 	    value->bv_type = BVAL_EMPTY;
1114 	    ++values->ga_len;
1115 	}
1116 	else
1117 	    break;
1118     }
1119     return TRUE;
1120 }
1121 
1122     static void
1123 write_viminfo_version(FILE *fp_out)
1124 {
1125     fprintf(fp_out, "# Viminfo version\n|%d,%d\n\n",
1126 					    BARTYPE_VERSION, VIMINFO_VERSION);
1127 }
1128 
1129     static int
1130 no_viminfo(void)
1131 {
1132     // "vim -i NONE" does not read or write a viminfo file
1133     return STRCMP(p_viminfofile, "NONE") == 0;
1134 }
1135 
1136 /*
1137  * Report an error for reading a viminfo file.
1138  * Count the number of errors.	When there are more than 10, return TRUE.
1139  */
1140     static int
1141 viminfo_error(char *errnum, char *message, char_u *line)
1142 {
1143     vim_snprintf((char *)IObuff, IOSIZE, _("%sviminfo: %s in line: "),
1144 							     errnum, message);
1145     STRNCAT(IObuff, line, IOSIZE - STRLEN(IObuff) - 1);
1146     if (IObuff[STRLEN(IObuff) - 1] == '\n')
1147 	IObuff[STRLEN(IObuff) - 1] = NUL;
1148     emsg((char *)IObuff);
1149     if (++viminfo_errcnt >= 10)
1150     {
1151 	emsg(_("E136: viminfo: Too many errors, skipping rest of file"));
1152 	return TRUE;
1153     }
1154     return FALSE;
1155 }
1156 
1157 /*
1158  * Compare the 'encoding' value in the viminfo file with the current value of
1159  * 'encoding'.  If different and the 'c' flag is in 'viminfo', setup for
1160  * conversion of text with iconv() in viminfo_readstring().
1161  */
1162     static int
1163 viminfo_encoding(vir_T *virp)
1164 {
1165     char_u	*p;
1166     int		i;
1167 
1168     if (get_viminfo_parameter('c') != 0)
1169     {
1170 	p = vim_strchr(virp->vir_line, '=');
1171 	if (p != NULL)
1172 	{
1173 	    // remove trailing newline
1174 	    ++p;
1175 	    for (i = 0; vim_isprintc(p[i]); ++i)
1176 		;
1177 	    p[i] = NUL;
1178 
1179 	    convert_setup(&virp->vir_conv, p, p_enc);
1180 	}
1181     }
1182     return viminfo_readline(virp);
1183 }
1184 
1185 #if defined(FEAT_EVAL) || defined(PROTO)
1186 /*
1187  * Restore global vars that start with a capital from the viminfo file
1188  */
1189     static int
1190 read_viminfo_varlist(vir_T *virp, int writing)
1191 {
1192     char_u	*tab;
1193     int		type = VAR_NUMBER;
1194     typval_T	tv;
1195     funccal_entry_T funccal_entry;
1196 
1197     if (!writing && (find_viminfo_parameter('!') != NULL))
1198     {
1199 	tab = vim_strchr(virp->vir_line + 1, '\t');
1200 	if (tab != NULL)
1201 	{
1202 	    *tab++ = '\0';	// isolate the variable name
1203 	    switch (*tab)
1204 	    {
1205 		case 'S': type = VAR_STRING; break;
1206 #ifdef FEAT_FLOAT
1207 		case 'F': type = VAR_FLOAT; break;
1208 #endif
1209 		case 'D': type = VAR_DICT; break;
1210 		case 'L': type = VAR_LIST; break;
1211 		case 'B': type = VAR_BLOB; break;
1212 		case 'X': type = VAR_SPECIAL; break;
1213 	    }
1214 
1215 	    tab = vim_strchr(tab, '\t');
1216 	    if (tab != NULL)
1217 	    {
1218 		tv.v_type = type;
1219 		if (type == VAR_STRING || type == VAR_DICT
1220 			|| type == VAR_LIST || type == VAR_BLOB)
1221 		    tv.vval.v_string = viminfo_readstring(virp,
1222 				       (int)(tab - virp->vir_line + 1), TRUE);
1223 #ifdef FEAT_FLOAT
1224 		else if (type == VAR_FLOAT)
1225 		    (void)string2float(tab + 1, &tv.vval.v_float);
1226 #endif
1227 		else
1228 		    tv.vval.v_number = atol((char *)tab + 1);
1229 		if (type == VAR_DICT || type == VAR_LIST)
1230 		{
1231 		    typval_T *etv = eval_expr(tv.vval.v_string, NULL);
1232 
1233 		    if (etv == NULL)
1234 			// Failed to parse back the dict or list, use it as a
1235 			// string.
1236 			tv.v_type = VAR_STRING;
1237 		    else
1238 		    {
1239 			vim_free(tv.vval.v_string);
1240 			tv = *etv;
1241 			vim_free(etv);
1242 		    }
1243 		}
1244 		else if (type == VAR_BLOB)
1245 		{
1246 		    blob_T *blob = string2blob(tv.vval.v_string);
1247 
1248 		    if (blob == NULL)
1249 			// Failed to parse back the blob, use it as a string.
1250 			tv.v_type = VAR_STRING;
1251 		    else
1252 		    {
1253 			vim_free(tv.vval.v_string);
1254 			tv.v_type = VAR_BLOB;
1255 			tv.vval.v_blob = blob;
1256 		    }
1257 		}
1258 
1259 		// when in a function use global variables
1260 		save_funccal(&funccal_entry);
1261 		set_var(virp->vir_line + 1, &tv, FALSE);
1262 		restore_funccal();
1263 
1264 		if (tv.v_type == VAR_STRING)
1265 		    vim_free(tv.vval.v_string);
1266 		else if (tv.v_type == VAR_DICT || tv.v_type == VAR_LIST ||
1267 			tv.v_type == VAR_BLOB)
1268 		    clear_tv(&tv);
1269 	    }
1270 	}
1271     }
1272 
1273     return viminfo_readline(virp);
1274 }
1275 
1276 /*
1277  * Write global vars that start with a capital to the viminfo file
1278  */
1279     static void
1280 write_viminfo_varlist(FILE *fp)
1281 {
1282     hashitem_T	*hi;
1283     dictitem_T	*this_var;
1284     int		todo;
1285     char	*s = "";
1286     char_u	*p;
1287     char_u	*tofree;
1288     char_u	numbuf[NUMBUFLEN];
1289 
1290     if (find_viminfo_parameter('!') == NULL)
1291 	return;
1292 
1293     fputs(_("\n# global variables:\n"), fp);
1294 
1295     todo = (int)globvarht.ht_used;
1296     for (hi = globvarht.ht_array; todo > 0; ++hi)
1297     {
1298 	if (!HASHITEM_EMPTY(hi))
1299 	{
1300 	    --todo;
1301 	    this_var = HI2DI(hi);
1302 	    if (var_flavour(this_var->di_key) == VAR_FLAVOUR_VIMINFO)
1303 	    {
1304 		switch (this_var->di_tv.v_type)
1305 		{
1306 		    case VAR_STRING: s = "STR"; break;
1307 		    case VAR_NUMBER: s = "NUM"; break;
1308 		    case VAR_FLOAT:  s = "FLO"; break;
1309 		    case VAR_DICT:   s = "DIC"; break;
1310 		    case VAR_LIST:   s = "LIS"; break;
1311 		    case VAR_BLOB:   s = "BLO"; break;
1312 		    case VAR_SPECIAL: s = "XPL"; break;
1313 
1314 		    case VAR_UNKNOWN:
1315 		    case VAR_FUNC:
1316 		    case VAR_PARTIAL:
1317 		    case VAR_JOB:
1318 		    case VAR_CHANNEL:
1319 				     continue;
1320 		}
1321 		fprintf(fp, "!%s\t%s\t", this_var->di_key, s);
1322 		if (this_var->di_tv.v_type == VAR_SPECIAL)
1323 		{
1324 		    sprintf((char *)numbuf, "%ld",
1325 					  (long)this_var->di_tv.vval.v_number);
1326 		    p = numbuf;
1327 		    tofree = NULL;
1328 		}
1329 		else
1330 		    p = echo_string(&this_var->di_tv, &tofree, numbuf, 0);
1331 		if (p != NULL)
1332 		    viminfo_writestring(fp, p);
1333 		vim_free(tofree);
1334 	    }
1335 	}
1336     }
1337 }
1338 #endif // FEAT_EVAL
1339 
1340     static int
1341 read_viminfo_sub_string(vir_T *virp, int force)
1342 {
1343     if (force || get_old_sub() == NULL)
1344 	set_old_sub(viminfo_readstring(virp, 1, TRUE));
1345     return viminfo_readline(virp);
1346 }
1347 
1348     static void
1349 write_viminfo_sub_string(FILE *fp)
1350 {
1351     char_u *old_sub = get_old_sub();
1352 
1353     if (get_viminfo_parameter('/') != 0 && old_sub != NULL)
1354     {
1355 	fputs(_("\n# Last Substitute String:\n$"), fp);
1356 	viminfo_writestring(fp, old_sub);
1357     }
1358 }
1359 
1360 /*
1361  * Functions relating to reading/writing the search pattern from viminfo
1362  */
1363 
1364     static int
1365 read_viminfo_search_pattern(vir_T *virp, int force)
1366 {
1367     char_u	*lp;
1368     int		idx = -1;
1369     int		magic = FALSE;
1370     int		no_scs = FALSE;
1371     int		off_line = FALSE;
1372     int		off_end = 0;
1373     long	off = 0;
1374     int		setlast = FALSE;
1375 #ifdef FEAT_SEARCH_EXTRA
1376     static int	hlsearch_on = FALSE;
1377 #endif
1378     char_u	*val;
1379     spat_T	*spat;
1380 
1381     // Old line types:
1382     // "/pat", "&pat": search/subst. pat
1383     // "~/pat", "~&pat": last used search/subst. pat
1384     // New line types:
1385     // "~h", "~H": hlsearch highlighting off/on
1386     // "~<magic><smartcase><line><end><off><last><which>pat"
1387     // <magic>: 'm' off, 'M' on
1388     // <smartcase>: 's' off, 'S' on
1389     // <line>: 'L' line offset, 'l' char offset
1390     // <end>: 'E' from end, 'e' from start
1391     // <off>: decimal, offset
1392     // <last>: '~' last used pattern
1393     // <which>: '/' search pat, '&' subst. pat
1394     lp = virp->vir_line;
1395     if (lp[0] == '~' && (lp[1] == 'm' || lp[1] == 'M'))	// new line type
1396     {
1397 	if (lp[1] == 'M')		// magic on
1398 	    magic = TRUE;
1399 	if (lp[2] == 's')
1400 	    no_scs = TRUE;
1401 	if (lp[3] == 'L')
1402 	    off_line = TRUE;
1403 	if (lp[4] == 'E')
1404 	    off_end = SEARCH_END;
1405 	lp += 5;
1406 	off = getdigits(&lp);
1407     }
1408     if (lp[0] == '~')		// use this pattern for last-used pattern
1409     {
1410 	setlast = TRUE;
1411 	lp++;
1412     }
1413     if (lp[0] == '/')
1414 	idx = RE_SEARCH;
1415     else if (lp[0] == '&')
1416 	idx = RE_SUBST;
1417 #ifdef FEAT_SEARCH_EXTRA
1418     else if (lp[0] == 'h')	// ~h: 'hlsearch' highlighting off
1419 	hlsearch_on = FALSE;
1420     else if (lp[0] == 'H')	// ~H: 'hlsearch' highlighting on
1421 	hlsearch_on = TRUE;
1422 #endif
1423     if (idx >= 0)
1424     {
1425 	spat = get_spat(idx);
1426 	if (force || spat->pat == NULL)
1427 	{
1428 	    val = viminfo_readstring(virp, (int)(lp - virp->vir_line + 1),
1429 									TRUE);
1430 	    if (val != NULL)
1431 	    {
1432 		set_last_search_pat(val, idx, magic, setlast);
1433 		vim_free(val);
1434 		spat->no_scs = no_scs;
1435 		spat->off.line = off_line;
1436 		spat->off.end = off_end;
1437 		spat->off.off = off;
1438 #ifdef FEAT_SEARCH_EXTRA
1439 		if (setlast)
1440 		    set_no_hlsearch(!hlsearch_on);
1441 #endif
1442 	    }
1443 	}
1444     }
1445     return viminfo_readline(virp);
1446 }
1447 
1448     static void
1449 wvsp_one(
1450     FILE	*fp,	// file to write to
1451     int		idx,	// spats[] index
1452     char	*s,	// search pat
1453     int		sc)	// dir char
1454 {
1455     spat_T	*spat = get_spat(idx);
1456     if (spat->pat != NULL)
1457     {
1458 	fprintf(fp, _("\n# Last %sSearch Pattern:\n~"), s);
1459 	// off.dir is not stored, it's reset to forward
1460 	fprintf(fp, "%c%c%c%c%ld%s%c",
1461 		spat->magic    ? 'M' : 'm',	// magic
1462 		spat->no_scs   ? 's' : 'S',	// smartcase
1463 		spat->off.line ? 'L' : 'l',	// line offset
1464 		spat->off.end  ? 'E' : 'e',	// offset from end
1465 		spat->off.off,			// offset
1466 		get_spat_last_idx() == idx ? "~" : "",	// last used pat
1467 		sc);
1468 	viminfo_writestring(fp, spat->pat);
1469     }
1470 }
1471 
1472     static void
1473 write_viminfo_search_pattern(FILE *fp)
1474 {
1475     if (get_viminfo_parameter('/') != 0)
1476     {
1477 #ifdef FEAT_SEARCH_EXTRA
1478 	fprintf(fp, "\n# hlsearch on (H) or off (h):\n~%c",
1479 	    (no_hlsearch || find_viminfo_parameter('h') != NULL) ? 'h' : 'H');
1480 #endif
1481 	wvsp_one(fp, RE_SEARCH, "", '/');
1482 	wvsp_one(fp, RE_SUBST, _("Substitute "), '&');
1483     }
1484 }
1485 
1486 /*
1487  * Functions relating to reading/writing registers from viminfo
1488  */
1489 
1490 static yankreg_T *y_read_regs = NULL;
1491 
1492 #define REG_PREVIOUS 1
1493 #define REG_EXEC 2
1494 
1495 /*
1496  * Prepare for reading viminfo registers when writing viminfo later.
1497  */
1498     static void
1499 prepare_viminfo_registers(void)
1500 {
1501      y_read_regs = ALLOC_CLEAR_MULT(yankreg_T, NUM_REGISTERS);
1502 }
1503 
1504     static void
1505 finish_viminfo_registers(void)
1506 {
1507     int		i;
1508     int		j;
1509 
1510     if (y_read_regs != NULL)
1511     {
1512 	for (i = 0; i < NUM_REGISTERS; ++i)
1513 	    if (y_read_regs[i].y_array != NULL)
1514 	    {
1515 		for (j = 0; j < y_read_regs[i].y_size; j++)
1516 		    vim_free(y_read_regs[i].y_array[j]);
1517 		vim_free(y_read_regs[i].y_array);
1518 	    }
1519 	VIM_CLEAR(y_read_regs);
1520     }
1521 }
1522 
1523     static int
1524 read_viminfo_register(vir_T *virp, int force)
1525 {
1526     int		eof;
1527     int		do_it = TRUE;
1528     int		size;
1529     int		limit;
1530     int		i;
1531     int		set_prev = FALSE;
1532     char_u	*str;
1533     char_u	**array = NULL;
1534     int		new_type = MCHAR; // init to shut up compiler
1535     colnr_T	new_width = 0; // init to shut up compiler
1536     yankreg_T	*y_current_p;
1537 
1538     // We only get here (hopefully) if line[0] == '"'
1539     str = virp->vir_line + 1;
1540 
1541     // If the line starts with "" this is the y_previous register.
1542     if (*str == '"')
1543     {
1544 	set_prev = TRUE;
1545 	str++;
1546     }
1547 
1548     if (!ASCII_ISALNUM(*str) && *str != '-')
1549     {
1550 	if (viminfo_error("E577: ", _("Illegal register name"), virp->vir_line))
1551 	    return TRUE;	// too many errors, pretend end-of-file
1552 	do_it = FALSE;
1553     }
1554     get_yank_register(*str++, FALSE);
1555     y_current_p = get_y_current();
1556     if (!force && y_current_p->y_array != NULL)
1557 	do_it = FALSE;
1558 
1559     if (*str == '@')
1560     {
1561 	// "x@: register x used for @@
1562 	if (force || get_execreg_lastc() == NUL)
1563 	    set_execreg_lastc(str[-1]);
1564     }
1565 
1566     size = 0;
1567     limit = 100;	// Optimized for registers containing <= 100 lines
1568     if (do_it)
1569     {
1570 	// Build the new register in array[].
1571 	// y_array is kept as-is until done.
1572 	// The "do_it" flag is reset when something is wrong, in which case
1573 	// array[] needs to be freed.
1574 	if (set_prev)
1575 	    set_y_previous(y_current_p);
1576 	array = ALLOC_MULT(char_u *, limit);
1577 	str = skipwhite(skiptowhite(str));
1578 	if (STRNCMP(str, "CHAR", 4) == 0)
1579 	    new_type = MCHAR;
1580 	else if (STRNCMP(str, "BLOCK", 5) == 0)
1581 	    new_type = MBLOCK;
1582 	else
1583 	    new_type = MLINE;
1584 	// get the block width; if it's missing we get a zero, which is OK
1585 	str = skipwhite(skiptowhite(str));
1586 	new_width = getdigits(&str);
1587     }
1588 
1589     while (!(eof = viminfo_readline(virp))
1590 		    && (virp->vir_line[0] == TAB || virp->vir_line[0] == '<'))
1591     {
1592 	if (do_it)
1593 	{
1594 	    if (size == limit)
1595 	    {
1596 		char_u **new_array = (char_u **)
1597 					   alloc(limit * 2 * sizeof(char_u *));
1598 
1599 		if (new_array == NULL)
1600 		{
1601 		    do_it = FALSE;
1602 		    break;
1603 		}
1604 		for (i = 0; i < limit; i++)
1605 		    new_array[i] = array[i];
1606 		vim_free(array);
1607 		array = new_array;
1608 		limit *= 2;
1609 	    }
1610 	    str = viminfo_readstring(virp, 1, TRUE);
1611 	    if (str != NULL)
1612 		array[size++] = str;
1613 	    else
1614 		// error, don't store the result
1615 		do_it = FALSE;
1616 	}
1617     }
1618 
1619     if (do_it)
1620     {
1621 	// free y_array[]
1622 	for (i = 0; i < y_current_p->y_size; i++)
1623 	    vim_free(y_current_p->y_array[i]);
1624 	vim_free(y_current_p->y_array);
1625 
1626 	y_current_p->y_type = new_type;
1627 	y_current_p->y_width = new_width;
1628 	y_current_p->y_size = size;
1629 	y_current_p->y_time_set = 0;
1630 	if (size == 0)
1631 	{
1632 	    y_current_p->y_array = NULL;
1633 	}
1634 	else
1635 	{
1636 	    // Move the lines from array[] to y_array[].
1637 	    y_current_p->y_array = ALLOC_MULT(char_u *, size);
1638 	    for (i = 0; i < size; i++)
1639 	    {
1640 		if (y_current_p->y_array == NULL)
1641 		    vim_free(array[i]);
1642 		else
1643 		    y_current_p->y_array[i] = array[i];
1644 	    }
1645 	}
1646     }
1647     else
1648     {
1649 	// Free array[] if it was filled.
1650 	for (i = 0; i < size; i++)
1651 	    vim_free(array[i]);
1652     }
1653     vim_free(array);
1654 
1655     return eof;
1656 }
1657 
1658 /*
1659  * Accept a new style register line from the viminfo, store it when it's new.
1660  */
1661     static void
1662 handle_viminfo_register(garray_T *values, int force)
1663 {
1664     bval_T	*vp = (bval_T *)values->ga_data;
1665     int		flags;
1666     int		name;
1667     int		type;
1668     int		linecount;
1669     int		width;
1670     time_t	timestamp;
1671     yankreg_T	*y_ptr;
1672     yankreg_T	*y_regs_p = get_y_regs();
1673     int		i;
1674 
1675     // Check the format:
1676     // |{bartype},{flags},{name},{type},
1677     //      {linecount},{width},{timestamp},"line1","line2"
1678     if (values->ga_len < 6
1679 	    || vp[0].bv_type != BVAL_NR
1680 	    || vp[1].bv_type != BVAL_NR
1681 	    || vp[2].bv_type != BVAL_NR
1682 	    || vp[3].bv_type != BVAL_NR
1683 	    || vp[4].bv_type != BVAL_NR
1684 	    || vp[5].bv_type != BVAL_NR)
1685 	return;
1686     flags = vp[0].bv_nr;
1687     name = vp[1].bv_nr;
1688     if (name < 0 || name >= NUM_REGISTERS)
1689 	return;
1690     type = vp[2].bv_nr;
1691     if (type != MCHAR && type != MLINE && type != MBLOCK)
1692 	return;
1693     linecount = vp[3].bv_nr;
1694     if (values->ga_len < 6 + linecount)
1695 	return;
1696     width = vp[4].bv_nr;
1697     if (width < 0)
1698 	return;
1699 
1700     if (y_read_regs != NULL)
1701 	// Reading viminfo for merging and writing.  Store the register
1702 	// content, don't update the current registers.
1703 	y_ptr = &y_read_regs[name];
1704     else
1705 	y_ptr = &y_regs_p[name];
1706 
1707     // Do not overwrite unless forced or the timestamp is newer.
1708     timestamp = (time_t)vp[5].bv_nr;
1709     if (y_ptr->y_array != NULL && !force
1710 			 && (timestamp == 0 || y_ptr->y_time_set > timestamp))
1711 	return;
1712 
1713     if (y_ptr->y_array != NULL)
1714 	for (i = 0; i < y_ptr->y_size; i++)
1715 	    vim_free(y_ptr->y_array[i]);
1716     vim_free(y_ptr->y_array);
1717 
1718     if (y_read_regs == NULL)
1719     {
1720 	if (flags & REG_PREVIOUS)
1721 	    set_y_previous(y_ptr);
1722 	if ((flags & REG_EXEC) && (force || get_execreg_lastc() == NUL))
1723 	    set_execreg_lastc(get_register_name(name));
1724     }
1725     y_ptr->y_type = type;
1726     y_ptr->y_width = width;
1727     y_ptr->y_size = linecount;
1728     y_ptr->y_time_set = timestamp;
1729     if (linecount == 0)
1730     {
1731 	y_ptr->y_array = NULL;
1732 	return;
1733     }
1734     y_ptr->y_array = ALLOC_MULT(char_u *, linecount);
1735     if (y_ptr->y_array == NULL)
1736     {
1737 	y_ptr->y_size = 0; // ensure object state is consistent
1738 	return;
1739     }
1740     for (i = 0; i < linecount; i++)
1741     {
1742 	if (vp[i + 6].bv_allocated)
1743 	{
1744 	    y_ptr->y_array[i] = vp[i + 6].bv_string;
1745 	    vp[i + 6].bv_string = NULL;
1746 	}
1747 	else
1748 	    y_ptr->y_array[i] = vim_strsave(vp[i + 6].bv_string);
1749     }
1750 }
1751 
1752     static void
1753 write_viminfo_registers(FILE *fp)
1754 {
1755     int		i, j;
1756     char_u	*type;
1757     char_u	c;
1758     int		num_lines;
1759     int		max_num_lines;
1760     int		max_kbyte;
1761     long	len;
1762     yankreg_T	*y_ptr;
1763     yankreg_T	*y_regs_p = get_y_regs();;
1764 
1765     fputs(_("\n# Registers:\n"), fp);
1766 
1767     // Get '<' value, use old '"' value if '<' is not found.
1768     max_num_lines = get_viminfo_parameter('<');
1769     if (max_num_lines < 0)
1770 	max_num_lines = get_viminfo_parameter('"');
1771     if (max_num_lines == 0)
1772 	return;
1773     max_kbyte = get_viminfo_parameter('s');
1774     if (max_kbyte == 0)
1775 	return;
1776 
1777     for (i = 0; i < NUM_REGISTERS; i++)
1778     {
1779 #ifdef FEAT_CLIPBOARD
1780 	// Skip '*'/'+' register, we don't want them back next time
1781 	if (i == STAR_REGISTER || i == PLUS_REGISTER)
1782 	    continue;
1783 #endif
1784 #ifdef FEAT_DND
1785 	// Neither do we want the '~' register
1786 	if (i == TILDE_REGISTER)
1787 	    continue;
1788 #endif
1789 	// When reading viminfo for merging and writing: Use the register from
1790 	// viminfo if it's newer.
1791 	if (y_read_regs != NULL
1792 		&& y_read_regs[i].y_array != NULL
1793 		&& (y_regs_p[i].y_array == NULL ||
1794 			    y_read_regs[i].y_time_set > y_regs_p[i].y_time_set))
1795 	    y_ptr = &y_read_regs[i];
1796 	else if (y_regs_p[i].y_array == NULL)
1797 	    continue;
1798 	else
1799 	    y_ptr = &y_regs_p[i];
1800 
1801 	// Skip empty registers.
1802 	num_lines = y_ptr->y_size;
1803 	if (num_lines == 0
1804 		|| (num_lines == 1 && y_ptr->y_type == MCHAR
1805 					&& *y_ptr->y_array[0] == NUL))
1806 	    continue;
1807 
1808 	if (max_kbyte > 0)
1809 	{
1810 	    // Skip register if there is more text than the maximum size.
1811 	    len = 0;
1812 	    for (j = 0; j < num_lines; j++)
1813 		len += (long)STRLEN(y_ptr->y_array[j]) + 1L;
1814 	    if (len > (long)max_kbyte * 1024L)
1815 		continue;
1816 	}
1817 
1818 	switch (y_ptr->y_type)
1819 	{
1820 	    case MLINE:
1821 		type = (char_u *)"LINE";
1822 		break;
1823 	    case MCHAR:
1824 		type = (char_u *)"CHAR";
1825 		break;
1826 	    case MBLOCK:
1827 		type = (char_u *)"BLOCK";
1828 		break;
1829 	    default:
1830 		semsg(_("E574: Unknown register type %d"), y_ptr->y_type);
1831 		type = (char_u *)"LINE";
1832 		break;
1833 	}
1834 	if (get_y_previous() == &y_regs_p[i])
1835 	    fprintf(fp, "\"");
1836 	c = get_register_name(i);
1837 	fprintf(fp, "\"%c", c);
1838 	if (c == get_execreg_lastc())
1839 	    fprintf(fp, "@");
1840 	fprintf(fp, "\t%s\t%d\n", type, (int)y_ptr->y_width);
1841 
1842 	// If max_num_lines < 0, then we save ALL the lines in the register
1843 	if (max_num_lines > 0 && num_lines > max_num_lines)
1844 	    num_lines = max_num_lines;
1845 	for (j = 0; j < num_lines; j++)
1846 	{
1847 	    putc('\t', fp);
1848 	    viminfo_writestring(fp, y_ptr->y_array[j]);
1849 	}
1850 
1851 	{
1852 	    int	    flags = 0;
1853 	    int	    remaining;
1854 
1855 	    // New style with a bar line. Format:
1856 	    // |{bartype},{flags},{name},{type},
1857 	    //      {linecount},{width},{timestamp},"line1","line2"
1858 	    // flags: REG_PREVIOUS - register is y_previous
1859 	    //	      REG_EXEC - used for @@
1860 	    if (get_y_previous() == &y_regs_p[i])
1861 		flags |= REG_PREVIOUS;
1862 	    if (c == get_execreg_lastc())
1863 		flags |= REG_EXEC;
1864 	    fprintf(fp, "|%d,%d,%d,%d,%d,%d,%ld", BARTYPE_REGISTER, flags,
1865 		    i, y_ptr->y_type, num_lines, (int)y_ptr->y_width,
1866 		    (long)y_ptr->y_time_set);
1867 	    // 11 chars for type/flags/name/type, 3 * 20 for numbers
1868 	    remaining = LSIZE - 71;
1869 	    for (j = 0; j < num_lines; j++)
1870 	    {
1871 		putc(',', fp);
1872 		--remaining;
1873 		remaining = barline_writestring(fp, y_ptr->y_array[j],
1874 								   remaining);
1875 	    }
1876 	    putc('\n', fp);
1877 	}
1878     }
1879 }
1880 
1881 /*
1882  * Functions relating to reading/writing marks from viminfo
1883  */
1884 
1885 static xfmark_T *vi_namedfm = NULL;
1886 #ifdef FEAT_JUMPLIST
1887 static xfmark_T *vi_jumplist = NULL;
1888 static int vi_jumplist_len = 0;
1889 #endif
1890 
1891     static void
1892 write_one_mark(FILE *fp_out, int c, pos_T *pos)
1893 {
1894     if (pos->lnum != 0)
1895 	fprintf(fp_out, "\t%c\t%ld\t%d\n", c, (long)pos->lnum, (int)pos->col);
1896 }
1897 
1898     static void
1899 write_buffer_marks(buf_T *buf, FILE *fp_out)
1900 {
1901     int		i;
1902     pos_T	pos;
1903 
1904     home_replace(NULL, buf->b_ffname, IObuff, IOSIZE, TRUE);
1905     fprintf(fp_out, "\n> ");
1906     viminfo_writestring(fp_out, IObuff);
1907 
1908     // Write the last used timestamp as the lnum of the non-existing mark '*'.
1909     // Older Vims will ignore it and/or copy it.
1910     pos.lnum = (linenr_T)buf->b_last_used;
1911     pos.col = 0;
1912     write_one_mark(fp_out, '*', &pos);
1913 
1914     write_one_mark(fp_out, '"', &buf->b_last_cursor);
1915     write_one_mark(fp_out, '^', &buf->b_last_insert);
1916     write_one_mark(fp_out, '.', &buf->b_last_change);
1917 #ifdef FEAT_JUMPLIST
1918     // changelist positions are stored oldest first
1919     for (i = 0; i < buf->b_changelistlen; ++i)
1920     {
1921 	// skip duplicates
1922 	if (i == 0 || !EQUAL_POS(buf->b_changelist[i - 1],
1923 							 buf->b_changelist[i]))
1924 	    write_one_mark(fp_out, '+', &buf->b_changelist[i]);
1925     }
1926 #endif
1927     for (i = 0; i < NMARKS; i++)
1928 	write_one_mark(fp_out, 'a' + i, &buf->b_namedm[i]);
1929 }
1930 
1931 /*
1932  * Return TRUE if marks for "buf" should not be written.
1933  */
1934     static int
1935 skip_for_viminfo(buf_T *buf)
1936 {
1937     return
1938 #ifdef FEAT_TERMINAL
1939 	    bt_terminal(buf) ||
1940 #endif
1941 	    removable(buf->b_ffname);
1942 }
1943 
1944 /*
1945  * Write all the named marks for all buffers.
1946  * When "buflist" is not NULL fill it with the buffers for which marks are to
1947  * be written.
1948  */
1949     static void
1950 write_viminfo_marks(FILE *fp_out, garray_T *buflist)
1951 {
1952     buf_T	*buf;
1953     int		is_mark_set;
1954     int		i;
1955     win_T	*win;
1956     tabpage_T	*tp;
1957 
1958     // Set b_last_cursor for the all buffers that have a window.
1959     FOR_ALL_TAB_WINDOWS(tp, win)
1960 	set_last_cursor(win);
1961 
1962     fputs(_("\n# History of marks within files (newest to oldest):\n"), fp_out);
1963     FOR_ALL_BUFFERS(buf)
1964     {
1965 	// Only write something if buffer has been loaded and at least one
1966 	// mark is set.
1967 	if (buf->b_marks_read)
1968 	{
1969 	    if (buf->b_last_cursor.lnum != 0)
1970 		is_mark_set = TRUE;
1971 	    else
1972 	    {
1973 		is_mark_set = FALSE;
1974 		for (i = 0; i < NMARKS; i++)
1975 		    if (buf->b_namedm[i].lnum != 0)
1976 		    {
1977 			is_mark_set = TRUE;
1978 			break;
1979 		    }
1980 	    }
1981 	    if (is_mark_set && buf->b_ffname != NULL
1982 		      && buf->b_ffname[0] != NUL
1983 		      && !skip_for_viminfo(buf))
1984 	    {
1985 		if (buflist == NULL)
1986 		    write_buffer_marks(buf, fp_out);
1987 		else if (ga_grow(buflist, 1) == OK)
1988 		    ((buf_T **)buflist->ga_data)[buflist->ga_len++] = buf;
1989 	    }
1990 	}
1991     }
1992 }
1993 
1994     static void
1995 write_one_filemark(
1996     FILE	*fp,
1997     xfmark_T	*fm,
1998     int		c1,
1999     int		c2)
2000 {
2001     char_u	*name;
2002 
2003     if (fm->fmark.mark.lnum == 0)	// not set
2004 	return;
2005 
2006     if (fm->fmark.fnum != 0)		// there is a buffer
2007 	name = buflist_nr2name(fm->fmark.fnum, TRUE, FALSE);
2008     else
2009 	name = fm->fname;		// use name from .viminfo
2010     if (name != NULL && *name != NUL)
2011     {
2012 	fprintf(fp, "%c%c  %ld  %ld  ", c1, c2, (long)fm->fmark.mark.lnum,
2013 						    (long)fm->fmark.mark.col);
2014 	viminfo_writestring(fp, name);
2015 
2016 	// Barline: |{bartype},{name},{lnum},{col},{timestamp},{filename}
2017 	// size up to filename: 8 + 3 * 20
2018 	fprintf(fp, "|%d,%d,%ld,%ld,%ld,", BARTYPE_MARK, c2,
2019 		(long)fm->fmark.mark.lnum, (long)fm->fmark.mark.col,
2020 		(long)fm->time_set);
2021 	barline_writestring(fp, name, LSIZE - 70);
2022 	putc('\n', fp);
2023     }
2024 
2025     if (fm->fmark.fnum != 0)
2026 	vim_free(name);
2027 }
2028 
2029     static void
2030 write_viminfo_filemarks(FILE *fp)
2031 {
2032     int		i;
2033     char_u	*name;
2034     buf_T	*buf;
2035     xfmark_T	*namedfm_p = get_namedfm();
2036     xfmark_T	*fm;
2037     int		vi_idx;
2038     int		idx;
2039 
2040     if (get_viminfo_parameter('f') == 0)
2041 	return;
2042 
2043     fputs(_("\n# File marks:\n"), fp);
2044 
2045     // Write the filemarks 'A - 'Z
2046     for (i = 0; i < NMARKS; i++)
2047     {
2048 	if (vi_namedfm != NULL
2049 			&& (vi_namedfm[i].time_set > namedfm_p[i].time_set
2050 			    || namedfm_p[i].fmark.mark.lnum == 0))
2051 	    fm = &vi_namedfm[i];
2052 	else
2053 	    fm = &namedfm_p[i];
2054 	write_one_filemark(fp, fm, '\'', i + 'A');
2055     }
2056 
2057     // Find a mark that is the same file and position as the cursor.
2058     // That one, or else the last one is deleted.
2059     // Move '0 to '1, '1 to '2, etc. until the matching one or '9
2060     // Set the '0 mark to current cursor position.
2061     if (curbuf->b_ffname != NULL && !skip_for_viminfo(curbuf))
2062     {
2063 	name = buflist_nr2name(curbuf->b_fnum, TRUE, FALSE);
2064 	for (i = NMARKS; i < NMARKS + EXTRA_MARKS - 1; ++i)
2065 	    if (namedfm_p[i].fmark.mark.lnum == curwin->w_cursor.lnum
2066 		    && (namedfm_p[i].fname == NULL
2067 			    ? namedfm_p[i].fmark.fnum == curbuf->b_fnum
2068 			    : (name != NULL
2069 				    && STRCMP(name, namedfm_p[i].fname) == 0)))
2070 		break;
2071 	vim_free(name);
2072 
2073 	vim_free(namedfm_p[i].fname);
2074 	for ( ; i > NMARKS; --i)
2075 	    namedfm_p[i] = namedfm_p[i - 1];
2076 	namedfm_p[NMARKS].fmark.mark = curwin->w_cursor;
2077 	namedfm_p[NMARKS].fmark.fnum = curbuf->b_fnum;
2078 	namedfm_p[NMARKS].fname = NULL;
2079 	namedfm_p[NMARKS].time_set = vim_time();
2080     }
2081 
2082     // Write the filemarks '0 - '9.  Newest (highest timestamp) first.
2083     vi_idx = NMARKS;
2084     idx = NMARKS;
2085     for (i = NMARKS; i < NMARKS + EXTRA_MARKS; i++)
2086     {
2087 	xfmark_T *vi_fm = vi_namedfm != NULL ? &vi_namedfm[vi_idx] : NULL;
2088 
2089 	if (vi_fm != NULL
2090 		&& vi_fm->fmark.mark.lnum != 0
2091 		&& (vi_fm->time_set > namedfm_p[idx].time_set
2092 		    || namedfm_p[idx].fmark.mark.lnum == 0))
2093 	{
2094 	    fm = vi_fm;
2095 	    ++vi_idx;
2096 	}
2097 	else
2098 	{
2099 	    fm = &namedfm_p[idx++];
2100 	    if (vi_fm != NULL
2101 		  && vi_fm->fmark.mark.lnum == fm->fmark.mark.lnum
2102 		  && vi_fm->time_set == fm->time_set
2103 		  && ((vi_fm->fmark.fnum != 0
2104 			  && vi_fm->fmark.fnum == fm->fmark.fnum)
2105 		      || (vi_fm->fname != NULL
2106 			  && fm->fname != NULL
2107 			  && STRCMP(vi_fm->fname, fm->fname) == 0)))
2108 		++vi_idx;  // skip duplicate
2109 	}
2110 	write_one_filemark(fp, fm, '\'', i - NMARKS + '0');
2111     }
2112 
2113 #ifdef FEAT_JUMPLIST
2114     // Write the jumplist with -'
2115     fputs(_("\n# Jumplist (newest first):\n"), fp);
2116     setpcmark();	// add current cursor position
2117     cleanup_jumplist(curwin, FALSE);
2118     vi_idx = 0;
2119     idx = curwin->w_jumplistlen - 1;
2120     for (i = 0; i < JUMPLISTSIZE; ++i)
2121     {
2122 	xfmark_T	*vi_fm;
2123 
2124 	fm = idx >= 0 ? &curwin->w_jumplist[idx] : NULL;
2125 	vi_fm = vi_idx < vi_jumplist_len ? &vi_jumplist[vi_idx] : NULL;
2126 	if (fm == NULL && vi_fm == NULL)
2127 	    break;
2128 	if (fm == NULL || (vi_fm != NULL && fm->time_set < vi_fm->time_set))
2129 	{
2130 	    fm = vi_fm;
2131 	    ++vi_idx;
2132 	}
2133 	else
2134 	    --idx;
2135 	if (fm->fmark.fnum == 0
2136 		|| ((buf = buflist_findnr(fm->fmark.fnum)) != NULL
2137 		    && !skip_for_viminfo(buf)))
2138 	    write_one_filemark(fp, fm, '-', '\'');
2139     }
2140 #endif
2141 }
2142 
2143 /*
2144  * Compare functions for qsort() below, that compares b_last_used.
2145  */
2146     static int
2147 buf_compare(const void *s1, const void *s2)
2148 {
2149     buf_T *buf1 = *(buf_T **)s1;
2150     buf_T *buf2 = *(buf_T **)s2;
2151 
2152     if (buf1->b_last_used == buf2->b_last_used)
2153 	return 0;
2154     return buf1->b_last_used > buf2->b_last_used ? -1 : 1;
2155 }
2156 
2157 /*
2158  * Handle marks in the viminfo file:
2159  * fp_out != NULL: copy marks, in time order with buffers in "buflist".
2160  * fp_out == NULL && (flags & VIF_WANT_MARKS): read marks for curbuf only
2161  * fp_out == NULL && (flags & VIF_GET_OLDFILES | VIF_FORCEIT): fill v:oldfiles
2162  */
2163     static void
2164 copy_viminfo_marks(
2165     vir_T	*virp,
2166     FILE	*fp_out,
2167     garray_T	*buflist,
2168     int		eof,
2169     int		flags)
2170 {
2171     char_u	*line = virp->vir_line;
2172     buf_T	*buf;
2173     int		num_marked_files;
2174     int		load_marks;
2175     int		copy_marks_out;
2176     char_u	*str;
2177     int		i;
2178     char_u	*p;
2179     char_u	*name_buf;
2180     pos_T	pos;
2181 #ifdef FEAT_EVAL
2182     list_T	*list = NULL;
2183 #endif
2184     int		count = 0;
2185     int		buflist_used = 0;
2186     buf_T	*buflist_buf = NULL;
2187 
2188     if ((name_buf = alloc(LSIZE)) == NULL)
2189 	return;
2190     *name_buf = NUL;
2191 
2192     if (fp_out != NULL && buflist->ga_len > 0)
2193     {
2194 	// Sort the list of buffers on b_last_used.
2195 	qsort(buflist->ga_data, (size_t)buflist->ga_len,
2196 						sizeof(buf_T *), buf_compare);
2197 	buflist_buf = ((buf_T **)buflist->ga_data)[0];
2198     }
2199 
2200 #ifdef FEAT_EVAL
2201     if (fp_out == NULL && (flags & (VIF_GET_OLDFILES | VIF_FORCEIT)))
2202     {
2203 	list = list_alloc();
2204 	if (list != NULL)
2205 	    set_vim_var_list(VV_OLDFILES, list);
2206     }
2207 #endif
2208 
2209     num_marked_files = get_viminfo_parameter('\'');
2210     while (!eof && (count < num_marked_files || fp_out == NULL))
2211     {
2212 	if (line[0] != '>')
2213 	{
2214 	    if (line[0] != '\n' && line[0] != '\r' && line[0] != '#')
2215 	    {
2216 		if (viminfo_error("E576: ", _("Missing '>'"), line))
2217 		    break;	// too many errors, return now
2218 	    }
2219 	    eof = vim_fgets(line, LSIZE, virp->vir_fd);
2220 	    continue;		// Skip this dud line
2221 	}
2222 
2223 	// Handle long line and translate escaped characters.
2224 	// Find file name, set str to start.
2225 	// Ignore leading and trailing white space.
2226 	str = skipwhite(line + 1);
2227 	str = viminfo_readstring(virp, (int)(str - virp->vir_line), FALSE);
2228 	if (str == NULL)
2229 	    continue;
2230 	p = str + STRLEN(str);
2231 	while (p != str && (*p == NUL || vim_isspace(*p)))
2232 	    p--;
2233 	if (*p)
2234 	    p++;
2235 	*p = NUL;
2236 
2237 #ifdef FEAT_EVAL
2238 	if (list != NULL)
2239 	    list_append_string(list, str, -1);
2240 #endif
2241 
2242 	// If fp_out == NULL, load marks for current buffer.
2243 	// If fp_out != NULL, copy marks for buffers not in buflist.
2244 	load_marks = copy_marks_out = FALSE;
2245 	if (fp_out == NULL)
2246 	{
2247 	    if ((flags & VIF_WANT_MARKS) && curbuf->b_ffname != NULL)
2248 	    {
2249 		if (*name_buf == NUL)	    // only need to do this once
2250 		    home_replace(NULL, curbuf->b_ffname, name_buf, LSIZE, TRUE);
2251 		if (fnamecmp(str, name_buf) == 0)
2252 		    load_marks = TRUE;
2253 	    }
2254 	}
2255 	else // fp_out != NULL
2256 	{
2257 	    // This is slow if there are many buffers!!
2258 	    FOR_ALL_BUFFERS(buf)
2259 		if (buf->b_ffname != NULL)
2260 		{
2261 		    home_replace(NULL, buf->b_ffname, name_buf, LSIZE, TRUE);
2262 		    if (fnamecmp(str, name_buf) == 0)
2263 			break;
2264 		}
2265 
2266 	    // Copy marks if the buffer has not been loaded.
2267 	    if (buf == NULL || !buf->b_marks_read)
2268 	    {
2269 		int	did_read_line = FALSE;
2270 
2271 		if (buflist_buf != NULL)
2272 		{
2273 		    // Read the next line.  If it has the "*" mark compare the
2274 		    // time stamps.  Write entries from "buflist" that are
2275 		    // newer.
2276 		    if (!(eof = viminfo_readline(virp)) && line[0] == TAB)
2277 		    {
2278 			did_read_line = TRUE;
2279 			if (line[1] == '*')
2280 			{
2281 			    long	ltime;
2282 
2283 			    sscanf((char *)line + 2, "%ld ", &ltime);
2284 			    while ((time_T)ltime < buflist_buf->b_last_used)
2285 			    {
2286 				write_buffer_marks(buflist_buf, fp_out);
2287 				if (++count >= num_marked_files)
2288 				    break;
2289 				if (++buflist_used == buflist->ga_len)
2290 				{
2291 				    buflist_buf = NULL;
2292 				    break;
2293 				}
2294 				buflist_buf =
2295 				   ((buf_T **)buflist->ga_data)[buflist_used];
2296 			    }
2297 			}
2298 			else
2299 			{
2300 			    // No timestamp, must be written by an older Vim.
2301 			    // Assume all remaining buffers are older then
2302 			    // ours.
2303 			    while (count < num_marked_files
2304 					    && buflist_used < buflist->ga_len)
2305 			    {
2306 				buflist_buf = ((buf_T **)buflist->ga_data)
2307 							     [buflist_used++];
2308 				write_buffer_marks(buflist_buf, fp_out);
2309 				++count;
2310 			    }
2311 			    buflist_buf = NULL;
2312 			}
2313 
2314 			if (count >= num_marked_files)
2315 			{
2316 			    vim_free(str);
2317 			    break;
2318 			}
2319 		    }
2320 		}
2321 
2322 		fputs("\n> ", fp_out);
2323 		viminfo_writestring(fp_out, str);
2324 		if (did_read_line)
2325 		    fputs((char *)line, fp_out);
2326 
2327 		count++;
2328 		copy_marks_out = TRUE;
2329 	    }
2330 	}
2331 	vim_free(str);
2332 
2333 	pos.coladd = 0;
2334 	while (!(eof = viminfo_readline(virp)) && line[0] == TAB)
2335 	{
2336 	    if (load_marks)
2337 	    {
2338 		if (line[1] != NUL)
2339 		{
2340 		    unsigned u;
2341 
2342 		    sscanf((char *)line + 2, "%ld %u", &pos.lnum, &u);
2343 		    pos.col = u;
2344 		    switch (line[1])
2345 		    {
2346 			case '"': curbuf->b_last_cursor = pos; break;
2347 			case '^': curbuf->b_last_insert = pos; break;
2348 			case '.': curbuf->b_last_change = pos; break;
2349 			case '+':
2350 #ifdef FEAT_JUMPLIST
2351 				  // changelist positions are stored oldest
2352 				  // first
2353 				  if (curbuf->b_changelistlen == JUMPLISTSIZE)
2354 				      // list is full, remove oldest entry
2355 				      mch_memmove(curbuf->b_changelist,
2356 					    curbuf->b_changelist + 1,
2357 					    sizeof(pos_T) * (JUMPLISTSIZE - 1));
2358 				  else
2359 				      ++curbuf->b_changelistlen;
2360 				  curbuf->b_changelist[
2361 					   curbuf->b_changelistlen - 1] = pos;
2362 #endif
2363 				  break;
2364 
2365 				  // Using the line number for the last-used
2366 				  // timestamp.
2367 			case '*': curbuf->b_last_used = pos.lnum; break;
2368 
2369 			default:  if ((i = line[1] - 'a') >= 0 && i < NMARKS)
2370 				      curbuf->b_namedm[i] = pos;
2371 		    }
2372 		}
2373 	    }
2374 	    else if (copy_marks_out)
2375 		fputs((char *)line, fp_out);
2376 	}
2377 
2378 	if (load_marks)
2379 	{
2380 #ifdef FEAT_JUMPLIST
2381 	    win_T	*wp;
2382 
2383 	    FOR_ALL_WINDOWS(wp)
2384 	    {
2385 		if (wp->w_buffer == curbuf)
2386 		    wp->w_changelistidx = curbuf->b_changelistlen;
2387 	    }
2388 #endif
2389 	    break;
2390 	}
2391     }
2392 
2393     if (fp_out != NULL)
2394 	// Write any remaining entries from buflist.
2395 	while (count < num_marked_files && buflist_used < buflist->ga_len)
2396 	{
2397 	    buflist_buf = ((buf_T **)buflist->ga_data)[buflist_used++];
2398 	    write_buffer_marks(buflist_buf, fp_out);
2399 	    ++count;
2400 	}
2401 
2402     vim_free(name_buf);
2403 }
2404 
2405 /*
2406  * Read marks for the current buffer from the viminfo file, when we support
2407  * buffer marks and the buffer has a name.
2408  */
2409     void
2410 check_marks_read(void)
2411 {
2412     if (!curbuf->b_marks_read && get_viminfo_parameter('\'') > 0
2413 						  && curbuf->b_ffname != NULL)
2414 	read_viminfo(NULL, VIF_WANT_MARKS);
2415 
2416     // Always set b_marks_read; needed when 'viminfo' is changed to include
2417     // the ' parameter after opening a buffer.
2418     curbuf->b_marks_read = TRUE;
2419 }
2420 
2421     static int
2422 read_viminfo_filemark(vir_T *virp, int force)
2423 {
2424     char_u	*str;
2425     xfmark_T	*namedfm_p = get_namedfm();
2426     xfmark_T	*fm;
2427     int		i;
2428 
2429     // We only get here if line[0] == '\'' or '-'.
2430     // Illegal mark names are ignored (for future expansion).
2431     str = virp->vir_line + 1;
2432     if (
2433 #ifndef EBCDIC
2434 	    *str <= 127 &&
2435 #endif
2436 	    ((*virp->vir_line == '\'' && (VIM_ISDIGIT(*str) || isupper(*str)))
2437 	     || (*virp->vir_line == '-' && *str == '\'')))
2438     {
2439 	if (*str == '\'')
2440 	{
2441 #ifdef FEAT_JUMPLIST
2442 	    // If the jumplist isn't full insert fmark as oldest entry
2443 	    if (curwin->w_jumplistlen == JUMPLISTSIZE)
2444 		fm = NULL;
2445 	    else
2446 	    {
2447 		for (i = curwin->w_jumplistlen; i > 0; --i)
2448 		    curwin->w_jumplist[i] = curwin->w_jumplist[i - 1];
2449 		++curwin->w_jumplistidx;
2450 		++curwin->w_jumplistlen;
2451 		fm = &curwin->w_jumplist[0];
2452 		fm->fmark.mark.lnum = 0;
2453 		fm->fname = NULL;
2454 	    }
2455 #else
2456 	    fm = NULL;
2457 #endif
2458 	}
2459 	else if (VIM_ISDIGIT(*str))
2460 	    fm = &namedfm_p[*str - '0' + NMARKS];
2461 	else
2462 	    fm = &namedfm_p[*str - 'A'];
2463 	if (fm != NULL && (fm->fmark.mark.lnum == 0 || force))
2464 	{
2465 	    str = skipwhite(str + 1);
2466 	    fm->fmark.mark.lnum = getdigits(&str);
2467 	    str = skipwhite(str);
2468 	    fm->fmark.mark.col = getdigits(&str);
2469 	    fm->fmark.mark.coladd = 0;
2470 	    fm->fmark.fnum = 0;
2471 	    str = skipwhite(str);
2472 	    vim_free(fm->fname);
2473 	    fm->fname = viminfo_readstring(virp, (int)(str - virp->vir_line),
2474 								       FALSE);
2475 	    fm->time_set = 0;
2476 	}
2477     }
2478     return vim_fgets(virp->vir_line, LSIZE, virp->vir_fd);
2479 }
2480 
2481 /*
2482  * Prepare for reading viminfo marks when writing viminfo later.
2483  */
2484     static void
2485 prepare_viminfo_marks(void)
2486 {
2487     vi_namedfm = ALLOC_CLEAR_MULT(xfmark_T, NMARKS + EXTRA_MARKS);
2488 #ifdef FEAT_JUMPLIST
2489     vi_jumplist = ALLOC_CLEAR_MULT(xfmark_T, JUMPLISTSIZE);
2490     vi_jumplist_len = 0;
2491 #endif
2492 }
2493 
2494     static void
2495 finish_viminfo_marks(void)
2496 {
2497     int		i;
2498 
2499     if (vi_namedfm != NULL)
2500     {
2501 	for (i = 0; i < NMARKS + EXTRA_MARKS; ++i)
2502 	    vim_free(vi_namedfm[i].fname);
2503 	VIM_CLEAR(vi_namedfm);
2504     }
2505 #ifdef FEAT_JUMPLIST
2506     if (vi_jumplist != NULL)
2507     {
2508 	for (i = 0; i < vi_jumplist_len; ++i)
2509 	    vim_free(vi_jumplist[i].fname);
2510 	VIM_CLEAR(vi_jumplist);
2511     }
2512 #endif
2513 }
2514 
2515 /*
2516  * Accept a new style mark line from the viminfo, store it when it's new.
2517  */
2518     static void
2519 handle_viminfo_mark(garray_T *values, int force)
2520 {
2521     bval_T	*vp = (bval_T *)values->ga_data;
2522     int		name;
2523     linenr_T	lnum;
2524     colnr_T	col;
2525     time_t	timestamp;
2526     xfmark_T	*fm = NULL;
2527 
2528     // Check the format:
2529     // |{bartype},{name},{lnum},{col},{timestamp},{filename}
2530     if (values->ga_len < 5
2531 	    || vp[0].bv_type != BVAL_NR
2532 	    || vp[1].bv_type != BVAL_NR
2533 	    || vp[2].bv_type != BVAL_NR
2534 	    || vp[3].bv_type != BVAL_NR
2535 	    || vp[4].bv_type != BVAL_STRING)
2536 	return;
2537 
2538     name = vp[0].bv_nr;
2539     if (name != '\'' && !VIM_ISDIGIT(name) && !ASCII_ISUPPER(name))
2540 	return;
2541     lnum = vp[1].bv_nr;
2542     col = vp[2].bv_nr;
2543     if (lnum <= 0 || col < 0)
2544 	return;
2545     timestamp = (time_t)vp[3].bv_nr;
2546 
2547     if (name == '\'')
2548     {
2549 #ifdef FEAT_JUMPLIST
2550 	if (vi_jumplist != NULL)
2551 	{
2552 	    if (vi_jumplist_len < JUMPLISTSIZE)
2553 		fm = &vi_jumplist[vi_jumplist_len++];
2554 	}
2555 	else
2556 	{
2557 	    int idx;
2558 	    int i;
2559 
2560 	    // If we have a timestamp insert it in the right place.
2561 	    if (timestamp != 0)
2562 	    {
2563 		for (idx = curwin->w_jumplistlen - 1; idx >= 0; --idx)
2564 		    if (curwin->w_jumplist[idx].time_set < timestamp)
2565 		    {
2566 			++idx;
2567 			break;
2568 		    }
2569 		// idx cannot be zero now
2570 		if (idx < 0 && curwin->w_jumplistlen < JUMPLISTSIZE)
2571 		    // insert as the oldest entry
2572 		    idx = 0;
2573 	    }
2574 	    else if (curwin->w_jumplistlen < JUMPLISTSIZE)
2575 		// insert as oldest entry
2576 		idx = 0;
2577 	    else
2578 		idx = -1;
2579 
2580 	    if (idx >= 0)
2581 	    {
2582 		if (curwin->w_jumplistlen == JUMPLISTSIZE)
2583 		{
2584 		    // Drop the oldest entry.
2585 		    --idx;
2586 		    vim_free(curwin->w_jumplist[0].fname);
2587 		    for (i = 0; i < idx; ++i)
2588 			curwin->w_jumplist[i] = curwin->w_jumplist[i + 1];
2589 		}
2590 		else
2591 		{
2592 		    // Move newer entries forward.
2593 		    for (i = curwin->w_jumplistlen; i > idx; --i)
2594 			curwin->w_jumplist[i] = curwin->w_jumplist[i - 1];
2595 		    ++curwin->w_jumplistidx;
2596 		    ++curwin->w_jumplistlen;
2597 		}
2598 		fm = &curwin->w_jumplist[idx];
2599 		fm->fmark.mark.lnum = 0;
2600 		fm->fname = NULL;
2601 		fm->time_set = 0;
2602 	    }
2603 	}
2604 #endif
2605     }
2606     else
2607     {
2608 	int		idx;
2609 	xfmark_T	*namedfm_p = get_namedfm();
2610 
2611 	if (VIM_ISDIGIT(name))
2612 	{
2613 	    if (vi_namedfm != NULL)
2614 		idx = name - '0' + NMARKS;
2615 	    else
2616 	    {
2617 		int i;
2618 
2619 		// Do not use the name from the viminfo file, insert in time
2620 		// order.
2621 		for (idx = NMARKS; idx < NMARKS + EXTRA_MARKS; ++idx)
2622 		    if (namedfm_p[idx].time_set < timestamp)
2623 			break;
2624 		if (idx == NMARKS + EXTRA_MARKS)
2625 		    // All existing entries are newer.
2626 		    return;
2627 		i = NMARKS + EXTRA_MARKS - 1;
2628 
2629 		vim_free(namedfm_p[i].fname);
2630 		for ( ; i > idx; --i)
2631 		    namedfm_p[i] = namedfm_p[i - 1];
2632 		namedfm_p[idx].fname = NULL;
2633 	    }
2634 	}
2635 	else
2636 	    idx = name - 'A';
2637 	if (vi_namedfm != NULL)
2638 	    fm = &vi_namedfm[idx];
2639 	else
2640 	    fm = &namedfm_p[idx];
2641     }
2642 
2643     if (fm != NULL)
2644     {
2645 	if (vi_namedfm != NULL || fm->fmark.mark.lnum == 0
2646 					  || fm->time_set < timestamp || force)
2647 	{
2648 	    fm->fmark.mark.lnum = lnum;
2649 	    fm->fmark.mark.col = col;
2650 	    fm->fmark.mark.coladd = 0;
2651 	    fm->fmark.fnum = 0;
2652 	    vim_free(fm->fname);
2653 	    if (vp[4].bv_allocated)
2654 	    {
2655 		fm->fname = vp[4].bv_string;
2656 		vp[4].bv_string = NULL;
2657 	    }
2658 	    else
2659 		fm->fname = vim_strsave(vp[4].bv_string);
2660 	    fm->time_set = timestamp;
2661 	}
2662     }
2663 }
2664 
2665     static int
2666 read_viminfo_barline(vir_T *virp, int got_encoding, int force, int writing)
2667 {
2668     char_u	*p = virp->vir_line + 1;
2669     int		bartype;
2670     garray_T	values;
2671     bval_T	*vp;
2672     int		i;
2673     int		read_next = TRUE;
2674 
2675     /*
2676      * The format is: |{bartype},{value},...
2677      * For a very long string:
2678      *     |{bartype},>{length of "{text}{text2}"}
2679      *     |<{text1}
2680      *     |<{text2},{value}
2681      * For a long line not using a string
2682      *     |{bartype},{lots of values},>
2683      *     |<{value},{value}
2684      */
2685     if (*p == '<')
2686     {
2687 	// Continuation line of an unrecognized item.
2688 	if (writing)
2689 	    ga_add_string(&virp->vir_barlines, virp->vir_line);
2690     }
2691     else
2692     {
2693 	ga_init2(&values, sizeof(bval_T), 20);
2694 	bartype = getdigits(&p);
2695 	switch (bartype)
2696 	{
2697 	    case BARTYPE_VERSION:
2698 		// Only use the version when it comes before the encoding.
2699 		// If it comes later it was copied by a Vim version that
2700 		// doesn't understand the version.
2701 		if (!got_encoding)
2702 		{
2703 		    read_next = barline_parse(virp, p, &values);
2704 		    vp = (bval_T *)values.ga_data;
2705 		    if (values.ga_len > 0 && vp->bv_type == BVAL_NR)
2706 			virp->vir_version = vp->bv_nr;
2707 		}
2708 		break;
2709 
2710 	    case BARTYPE_HISTORY:
2711 		read_next = barline_parse(virp, p, &values);
2712 		handle_viminfo_history(&values, writing);
2713 		break;
2714 
2715 	    case BARTYPE_REGISTER:
2716 		read_next = barline_parse(virp, p, &values);
2717 		handle_viminfo_register(&values, force);
2718 		break;
2719 
2720 	    case BARTYPE_MARK:
2721 		read_next = barline_parse(virp, p, &values);
2722 		handle_viminfo_mark(&values, force);
2723 		break;
2724 
2725 	    default:
2726 		// copy unrecognized line (for future use)
2727 		if (writing)
2728 		    ga_add_string(&virp->vir_barlines, virp->vir_line);
2729 	}
2730 	for (i = 0; i < values.ga_len; ++i)
2731 	{
2732 	    vp = (bval_T *)values.ga_data + i;
2733 	    if (vp->bv_type == BVAL_STRING && vp->bv_allocated)
2734 		vim_free(vp->bv_string);
2735 	}
2736 	ga_clear(&values);
2737     }
2738 
2739     if (read_next)
2740 	return viminfo_readline(virp);
2741     return FALSE;
2742 }
2743 
2744 /*
2745  * read_viminfo_up_to_marks() -- Only called from do_viminfo().  Reads in the
2746  * first part of the viminfo file which contains everything but the marks that
2747  * are local to a file.  Returns TRUE when end-of-file is reached. -- webb
2748  */
2749     static int
2750 read_viminfo_up_to_marks(
2751     vir_T	*virp,
2752     int		forceit,
2753     int		writing)
2754 {
2755     int		eof;
2756     buf_T	*buf;
2757     int		got_encoding = FALSE;
2758 
2759 #ifdef FEAT_CMDHIST
2760     prepare_viminfo_history(forceit ? 9999 : 0, writing);
2761 #endif
2762 
2763     eof = viminfo_readline(virp);
2764     while (!eof && virp->vir_line[0] != '>')
2765     {
2766 	switch (virp->vir_line[0])
2767 	{
2768 		// Characters reserved for future expansion, ignored now
2769 	    case '+': // "+40 /path/dir file", for running vim without args
2770 	    case '^': // to be defined
2771 	    case '<': // long line - ignored
2772 		// A comment or empty line.
2773 	    case NUL:
2774 	    case '\r':
2775 	    case '\n':
2776 	    case '#':
2777 		eof = viminfo_readline(virp);
2778 		break;
2779 	    case '|':
2780 		eof = read_viminfo_barline(virp, got_encoding,
2781 							    forceit, writing);
2782 		break;
2783 	    case '*': // "*encoding=value"
2784 		got_encoding = TRUE;
2785 		eof = viminfo_encoding(virp);
2786 		break;
2787 	    case '!': // global variable
2788 #ifdef FEAT_EVAL
2789 		eof = read_viminfo_varlist(virp, writing);
2790 #else
2791 		eof = viminfo_readline(virp);
2792 #endif
2793 		break;
2794 	    case '%': // entry for buffer list
2795 		eof = read_viminfo_bufferlist(virp, writing);
2796 		break;
2797 	    case '"':
2798 		// When registers are in bar lines skip the old style register
2799 		// lines.
2800 		if (virp->vir_version < VIMINFO_VERSION_WITH_REGISTERS)
2801 		    eof = read_viminfo_register(virp, forceit);
2802 		else
2803 		    do {
2804 			eof = viminfo_readline(virp);
2805 		    } while (!eof && (virp->vir_line[0] == TAB
2806 						|| virp->vir_line[0] == '<'));
2807 		break;
2808 	    case '/':	    // Search string
2809 	    case '&':	    // Substitute search string
2810 	    case '~':	    // Last search string, followed by '/' or '&'
2811 		eof = read_viminfo_search_pattern(virp, forceit);
2812 		break;
2813 	    case '$':
2814 		eof = read_viminfo_sub_string(virp, forceit);
2815 		break;
2816 	    case ':':
2817 	    case '?':
2818 	    case '=':
2819 	    case '@':
2820 #ifdef FEAT_CMDHIST
2821 		// When history is in bar lines skip the old style history
2822 		// lines.
2823 		if (virp->vir_version < VIMINFO_VERSION_WITH_HISTORY)
2824 		    eof = read_viminfo_history(virp, writing);
2825 		else
2826 #endif
2827 		    eof = viminfo_readline(virp);
2828 		break;
2829 	    case '-':
2830 	    case '\'':
2831 		// When file marks are in bar lines skip the old style lines.
2832 		if (virp->vir_version < VIMINFO_VERSION_WITH_MARKS)
2833 		    eof = read_viminfo_filemark(virp, forceit);
2834 		else
2835 		    eof = viminfo_readline(virp);
2836 		break;
2837 	    default:
2838 		if (viminfo_error("E575: ", _("Illegal starting char"),
2839 			    virp->vir_line))
2840 		    eof = TRUE;
2841 		else
2842 		    eof = viminfo_readline(virp);
2843 		break;
2844 	}
2845     }
2846 
2847 #ifdef FEAT_CMDHIST
2848     // Finish reading history items.
2849     if (!writing)
2850 	finish_viminfo_history(virp);
2851 #endif
2852 
2853     // Change file names to buffer numbers for fmarks.
2854     FOR_ALL_BUFFERS(buf)
2855 	fmarks_check_names(buf);
2856 
2857     return eof;
2858 }
2859 
2860 /*
2861  * do_viminfo() -- Should only be called from read_viminfo() & write_viminfo().
2862  */
2863     static void
2864 do_viminfo(FILE *fp_in, FILE *fp_out, int flags)
2865 {
2866     int		eof = FALSE;
2867     vir_T	vir;
2868     int		merge = FALSE;
2869     int		do_copy_marks = FALSE;
2870     garray_T	buflist;
2871 
2872     if ((vir.vir_line = alloc(LSIZE)) == NULL)
2873 	return;
2874     vir.vir_fd = fp_in;
2875     vir.vir_conv.vc_type = CONV_NONE;
2876     ga_init2(&vir.vir_barlines, (int)sizeof(char_u *), 100);
2877     vir.vir_version = -1;
2878 
2879     if (fp_in != NULL)
2880     {
2881 	if (flags & VIF_WANT_INFO)
2882 	{
2883 	    if (fp_out != NULL)
2884 	    {
2885 		// Registers and marks are read and kept separate from what
2886 		// this Vim is using.  They are merged when writing.
2887 		prepare_viminfo_registers();
2888 		prepare_viminfo_marks();
2889 	    }
2890 
2891 	    eof = read_viminfo_up_to_marks(&vir,
2892 					 flags & VIF_FORCEIT, fp_out != NULL);
2893 	    merge = TRUE;
2894 	}
2895 	else if (flags != 0)
2896 	    // Skip info, find start of marks
2897 	    while (!(eof = viminfo_readline(&vir))
2898 		    && vir.vir_line[0] != '>')
2899 		;
2900 
2901 	do_copy_marks = (flags &
2902 			   (VIF_WANT_MARKS | VIF_GET_OLDFILES | VIF_FORCEIT));
2903     }
2904 
2905     if (fp_out != NULL)
2906     {
2907 	// Write the info:
2908 	fprintf(fp_out, _("# This viminfo file was generated by Vim %s.\n"),
2909 							  VIM_VERSION_MEDIUM);
2910 	fputs(_("# You may edit it if you're careful!\n\n"), fp_out);
2911 	write_viminfo_version(fp_out);
2912 	fputs(_("# Value of 'encoding' when this file was written\n"), fp_out);
2913 	fprintf(fp_out, "*encoding=%s\n\n", p_enc);
2914 	write_viminfo_search_pattern(fp_out);
2915 	write_viminfo_sub_string(fp_out);
2916 #ifdef FEAT_CMDHIST
2917 	write_viminfo_history(fp_out, merge);
2918 #endif
2919 	write_viminfo_registers(fp_out);
2920 	finish_viminfo_registers();
2921 #ifdef FEAT_EVAL
2922 	write_viminfo_varlist(fp_out);
2923 #endif
2924 	write_viminfo_filemarks(fp_out);
2925 	finish_viminfo_marks();
2926 	write_viminfo_bufferlist(fp_out);
2927 	write_viminfo_barlines(&vir, fp_out);
2928 
2929 	if (do_copy_marks)
2930 	    ga_init2(&buflist, sizeof(buf_T *), 50);
2931 	write_viminfo_marks(fp_out, do_copy_marks ? &buflist : NULL);
2932     }
2933 
2934     if (do_copy_marks)
2935     {
2936 	copy_viminfo_marks(&vir, fp_out, &buflist, eof, flags);
2937 	if (fp_out != NULL)
2938 	    ga_clear(&buflist);
2939     }
2940 
2941     vim_free(vir.vir_line);
2942     if (vir.vir_conv.vc_type != CONV_NONE)
2943 	convert_setup(&vir.vir_conv, NULL, NULL);
2944     ga_clear_strings(&vir.vir_barlines);
2945 }
2946 
2947 /*
2948  * read_viminfo() -- Read the viminfo file.  Registers etc. which are already
2949  * set are not over-written unless "flags" includes VIF_FORCEIT. -- webb
2950  */
2951     int
2952 read_viminfo(
2953     char_u	*file,	    // file name or NULL to use default name
2954     int		flags)	    // VIF_WANT_INFO et al.
2955 {
2956     FILE	*fp;
2957     char_u	*fname;
2958 
2959     if (no_viminfo())
2960 	return FAIL;
2961 
2962     fname = viminfo_filename(file);	// get file name in allocated buffer
2963     if (fname == NULL)
2964 	return FAIL;
2965     fp = mch_fopen((char *)fname, READBIN);
2966 
2967     if (p_verbose > 0)
2968     {
2969 	verbose_enter();
2970 	smsg(_("Reading viminfo file \"%s\"%s%s%s"),
2971 		fname,
2972 		(flags & VIF_WANT_INFO) ? _(" info") : "",
2973 		(flags & VIF_WANT_MARKS) ? _(" marks") : "",
2974 		(flags & VIF_GET_OLDFILES) ? _(" oldfiles") : "",
2975 		fp == NULL ? _(" FAILED") : "");
2976 	verbose_leave();
2977     }
2978 
2979     vim_free(fname);
2980     if (fp == NULL)
2981 	return FAIL;
2982 
2983     viminfo_errcnt = 0;
2984     do_viminfo(fp, NULL, flags);
2985 
2986     fclose(fp);
2987     return OK;
2988 }
2989 
2990 /*
2991  * Write the viminfo file.  The old one is read in first so that effectively a
2992  * merge of current info and old info is done.  This allows multiple vims to
2993  * run simultaneously, without losing any marks etc.
2994  * If "forceit" is TRUE, then the old file is not read in, and only internal
2995  * info is written to the file.
2996  */
2997     void
2998 write_viminfo(char_u *file, int forceit)
2999 {
3000     char_u	*fname;
3001     FILE	*fp_in = NULL;	// input viminfo file, if any
3002     FILE	*fp_out = NULL;	// output viminfo file
3003     char_u	*tempname = NULL;	// name of temp viminfo file
3004     stat_T	st_new;		// mch_stat() of potential new file
3005 #if defined(UNIX) || defined(VMS)
3006     mode_t	umask_save;
3007 #endif
3008 #ifdef UNIX
3009     int		shortname = FALSE;	// use 8.3 file name
3010     stat_T	st_old;		// mch_stat() of existing viminfo file
3011 #endif
3012 #ifdef MSWIN
3013     int		hidden = FALSE;
3014 #endif
3015 
3016     if (no_viminfo())
3017 	return;
3018 
3019     fname = viminfo_filename(file);	// may set to default if NULL
3020     if (fname == NULL)
3021 	return;
3022 
3023     fp_in = mch_fopen((char *)fname, READBIN);
3024     if (fp_in == NULL)
3025     {
3026 	int fd;
3027 
3028 	// if it does exist, but we can't read it, don't try writing
3029 	if (mch_stat((char *)fname, &st_new) == 0)
3030 	    goto end;
3031 
3032 	// Create the new .viminfo non-accessible for others, because it may
3033 	// contain text from non-accessible documents. It is up to the user to
3034 	// widen access (e.g. to a group). This may also fail if there is a
3035 	// race condition, then just give up.
3036 	fd = mch_open((char *)fname,
3037 			    O_CREAT|O_EXTRA|O_EXCL|O_WRONLY|O_NOFOLLOW, 0600);
3038 	if (fd < 0)
3039 	    goto end;
3040 	fp_out = fdopen(fd, WRITEBIN);
3041     }
3042     else
3043     {
3044 	/*
3045 	 * There is an existing viminfo file.  Create a temporary file to
3046 	 * write the new viminfo into, in the same directory as the
3047 	 * existing viminfo file, which will be renamed once all writing is
3048 	 * successful.
3049 	 */
3050 #ifdef UNIX
3051 	/*
3052 	 * For Unix we check the owner of the file.  It's not very nice to
3053 	 * overwrite a user's viminfo file after a "su root", with a
3054 	 * viminfo file that the user can't read.
3055 	 */
3056 	st_old.st_dev = (dev_t)0;
3057 	st_old.st_ino = 0;
3058 	st_old.st_mode = 0600;
3059 	if (mch_stat((char *)fname, &st_old) == 0
3060 		&& getuid() != ROOT_UID
3061 		&& !(st_old.st_uid == getuid()
3062 			? (st_old.st_mode & 0200)
3063 			: (st_old.st_gid == getgid()
3064 				? (st_old.st_mode & 0020)
3065 				: (st_old.st_mode & 0002))))
3066 	{
3067 	    int	tt = msg_didany;
3068 
3069 	    // avoid a wait_return for this message, it's annoying
3070 	    semsg(_("E137: Viminfo file is not writable: %s"), fname);
3071 	    msg_didany = tt;
3072 	    fclose(fp_in);
3073 	    goto end;
3074 	}
3075 #endif
3076 #ifdef MSWIN
3077 	// Get the file attributes of the existing viminfo file.
3078 	hidden = mch_ishidden(fname);
3079 #endif
3080 
3081 	/*
3082 	 * Make tempname, find one that does not exist yet.
3083 	 * Beware of a race condition: If someone logs out and all Vim
3084 	 * instances exit at the same time a temp file might be created between
3085 	 * stat() and open().  Use mch_open() with O_EXCL to avoid that.
3086 	 * May try twice: Once normal and once with shortname set, just in
3087 	 * case somebody puts his viminfo file in an 8.3 filesystem.
3088 	 */
3089 	for (;;)
3090 	{
3091 	    int		next_char = 'z';
3092 	    char_u	*wp;
3093 
3094 	    tempname = buf_modname(
3095 #ifdef UNIX
3096 				    shortname,
3097 #else
3098 				    FALSE,
3099 #endif
3100 				    fname,
3101 #ifdef VMS
3102 				    (char_u *)"-tmp",
3103 #else
3104 				    (char_u *)".tmp",
3105 #endif
3106 				    FALSE);
3107 	    if (tempname == NULL)		// out of memory
3108 		break;
3109 
3110 	    /*
3111 	     * Try a series of names.  Change one character, just before
3112 	     * the extension.  This should also work for an 8.3
3113 	     * file name, when after adding the extension it still is
3114 	     * the same file as the original.
3115 	     */
3116 	    wp = tempname + STRLEN(tempname) - 5;
3117 	    if (wp < gettail(tempname))	    // empty file name?
3118 		wp = gettail(tempname);
3119 	    for (;;)
3120 	    {
3121 		/*
3122 		 * Check if tempfile already exists.  Never overwrite an
3123 		 * existing file!
3124 		 */
3125 		if (mch_stat((char *)tempname, &st_new) == 0)
3126 		{
3127 #ifdef UNIX
3128 		    /*
3129 		     * Check if tempfile is same as original file.  May happen
3130 		     * when modname() gave the same file back.  E.g.  silly
3131 		     * link, or file name-length reached.  Try again with
3132 		     * shortname set.
3133 		     */
3134 		    if (!shortname && st_new.st_dev == st_old.st_dev
3135 						&& st_new.st_ino == st_old.st_ino)
3136 		    {
3137 			VIM_CLEAR(tempname);
3138 			shortname = TRUE;
3139 			break;
3140 		    }
3141 #endif
3142 		}
3143 		else
3144 		{
3145 		    // Try creating the file exclusively.  This may fail if
3146 		    // another Vim tries to do it at the same time.
3147 #ifdef VMS
3148 		    // fdopen() fails for some reason
3149 		    umask_save = umask(077);
3150 		    fp_out = mch_fopen((char *)tempname, WRITEBIN);
3151 		    (void)umask(umask_save);
3152 #else
3153 		    int	fd;
3154 
3155 		    // Use mch_open() to be able to use O_NOFOLLOW and set file
3156 		    // protection:
3157 		    // Unix: same as original file, but strip s-bit.  Reset
3158 		    // umask to avoid it getting in the way.
3159 		    // Others: r&w for user only.
3160 # ifdef UNIX
3161 		    umask_save = umask(0);
3162 		    fd = mch_open((char *)tempname,
3163 			    O_CREAT|O_EXTRA|O_EXCL|O_WRONLY|O_NOFOLLOW,
3164 					(int)((st_old.st_mode & 0777) | 0600));
3165 		    (void)umask(umask_save);
3166 # else
3167 		    fd = mch_open((char *)tempname,
3168 			     O_CREAT|O_EXTRA|O_EXCL|O_WRONLY|O_NOFOLLOW, 0600);
3169 # endif
3170 		    if (fd < 0)
3171 		    {
3172 			fp_out = NULL;
3173 # ifdef EEXIST
3174 			// Avoid trying lots of names while the problem is lack
3175 			// of permission, only retry if the file already
3176 			// exists.
3177 			if (errno != EEXIST)
3178 			    break;
3179 # endif
3180 		    }
3181 		    else
3182 			fp_out = fdopen(fd, WRITEBIN);
3183 #endif // VMS
3184 		    if (fp_out != NULL)
3185 			break;
3186 		}
3187 
3188 		// Assume file exists, try again with another name.
3189 		if (next_char == 'a' - 1)
3190 		{
3191 		    // They all exist?  Must be something wrong! Don't write
3192 		    // the viminfo file then.
3193 		    semsg(_("E929: Too many viminfo temp files, like %s!"),
3194 								     tempname);
3195 		    break;
3196 		}
3197 		*wp = next_char;
3198 		--next_char;
3199 	    }
3200 
3201 	    if (tempname != NULL)
3202 		break;
3203 	    // continue if shortname was set
3204 	}
3205 
3206 #if defined(UNIX) && defined(HAVE_FCHOWN)
3207 	if (tempname != NULL && fp_out != NULL)
3208 	{
3209 		stat_T	tmp_st;
3210 
3211 	    /*
3212 	     * Make sure the original owner can read/write the tempfile and
3213 	     * otherwise preserve permissions, making sure the group matches.
3214 	     */
3215 	    if (mch_stat((char *)tempname, &tmp_st) >= 0)
3216 	    {
3217 		if (st_old.st_uid != tmp_st.st_uid)
3218 		    // Changing the owner might fail, in which case the
3219 		    // file will now owned by the current user, oh well.
3220 		    vim_ignored = fchown(fileno(fp_out), st_old.st_uid, -1);
3221 		if (st_old.st_gid != tmp_st.st_gid
3222 			&& fchown(fileno(fp_out), -1, st_old.st_gid) == -1)
3223 		    // can't set the group to what it should be, remove
3224 		    // group permissions
3225 		    (void)mch_setperm(tempname, 0600);
3226 	    }
3227 	    else
3228 		// can't stat the file, set conservative permissions
3229 		(void)mch_setperm(tempname, 0600);
3230 	}
3231 #endif
3232     }
3233 
3234     /*
3235      * Check if the new viminfo file can be written to.
3236      */
3237     if (fp_out == NULL)
3238     {
3239 	semsg(_("E138: Can't write viminfo file %s!"),
3240 		       (fp_in == NULL || tempname == NULL) ? fname : tempname);
3241 	if (fp_in != NULL)
3242 	    fclose(fp_in);
3243 	goto end;
3244     }
3245 
3246     if (p_verbose > 0)
3247     {
3248 	verbose_enter();
3249 	smsg(_("Writing viminfo file \"%s\""), fname);
3250 	verbose_leave();
3251     }
3252 
3253     viminfo_errcnt = 0;
3254     do_viminfo(fp_in, fp_out, forceit ? 0 : (VIF_WANT_INFO | VIF_WANT_MARKS));
3255 
3256     if (fclose(fp_out) == EOF)
3257 	++viminfo_errcnt;
3258 
3259     if (fp_in != NULL)
3260     {
3261 	fclose(fp_in);
3262 
3263 	// In case of an error keep the original viminfo file.  Otherwise
3264 	// rename the newly written file.  Give an error if that fails.
3265 	if (viminfo_errcnt == 0)
3266 	{
3267 	    if (vim_rename(tempname, fname) == -1)
3268 	    {
3269 		++viminfo_errcnt;
3270 		semsg(_("E886: Can't rename viminfo file to %s!"), fname);
3271 	    }
3272 # ifdef MSWIN
3273 	    // If the viminfo file was hidden then also hide the new file.
3274 	    else if (hidden)
3275 		mch_hide(fname);
3276 # endif
3277 	}
3278 	if (viminfo_errcnt > 0)
3279 	    mch_remove(tempname);
3280     }
3281 
3282 end:
3283     vim_free(fname);
3284     vim_free(tempname);
3285 }
3286 
3287 /*
3288  * ":rviminfo" and ":wviminfo".
3289  */
3290     void
3291 ex_viminfo(
3292     exarg_T	*eap)
3293 {
3294     char_u	*save_viminfo;
3295 
3296     save_viminfo = p_viminfo;
3297     if (*p_viminfo == NUL)
3298 	p_viminfo = (char_u *)"'100";
3299     if (eap->cmdidx == CMD_rviminfo)
3300     {
3301 	if (read_viminfo(eap->arg, VIF_WANT_INFO | VIF_WANT_MARKS
3302 				  | (eap->forceit ? VIF_FORCEIT : 0)) == FAIL)
3303 	    emsg(_("E195: Cannot open viminfo file for reading"));
3304     }
3305     else
3306 	write_viminfo(eap->arg, eap->forceit);
3307     p_viminfo = save_viminfo;
3308 }
3309 
3310 #endif // FEAT_VIMINFO
3311