blob: cd3bbb65c6ed854951d7f116f5e0bc2136a31f55 [file] [log] [blame]
Bram Moolenaardefa0672019-07-21 19:25:37 +02001/* 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
19static int viminfo_errcnt;
20
21/*
Bram Moolenaarc3328162019-07-23 22:15:25 +020022 * 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 *
27find_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
52get_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/*
Bram Moolenaardefa0672019-07-21 19:25:37 +020063 * 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 *
71viminfo_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
Bram Moolenaarc3328162019-07-23 22:15:25 +0200109/*
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
120viminfo_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
159barline_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 *
224viminfo_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
289viminfo_readline(vir_T *virp)
290{
291 return vim_fgets(virp->vir_line, LSIZE, virp->vir_fd);
292}
293
Bram Moolenaardefa0672019-07-21 19:25:37 +0200294 static int
295read_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
Bram Moolenaarc3328162019-07-23 22:15:25 +0200348/*
349 * Return TRUE if "name" is on removable media (depending on 'viminfo').
350 */
351 static int
352removable(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
Bram Moolenaardefa0672019-07-21 19:25:37 +0200380 static void
381write_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
Bram Moolenaar5f32ece2019-07-21 21:51:59 +0200430#if defined(FEAT_CMDHIST) || defined(PROTO)
431/*
432 * Buffers for history read from a viminfo file. Only valid while reading.
433 */
434static histentry_T *viminfo_history[HIST_COUNT] =
435 {NULL, NULL, NULL, NULL, NULL};
436static int viminfo_hisidx[HIST_COUNT] = {0, 0, 0, 0, 0};
437static int viminfo_hislen[HIST_COUNT] = {0, 0, 0, 0, 0};
438static int viminfo_add_at_front = FALSE;
439
440/*
441 * Translate a history type number to the associated character.
442 */
443 static int
444hist_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
467prepare_viminfo_history(int asklen, int writing)
468{
469 int i;
470 int num;
471 int type;
472 int len;
Bram Moolenaar26b654a2019-07-22 20:50:17 +0200473 int hislen;
Bram Moolenaar5f32ece2019-07-21 21:51:59 +0200474
475 init_history();
Bram Moolenaar26b654a2019-07-22 20:50:17 +0200476 hislen = get_hislen();
Bram Moolenaar5f32ece2019-07-21 21:51:59 +0200477 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
510read_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
565handle_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
643concat_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
692sort_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
707merge_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);
Bram Moolenaar26b654a2019-07-22 20:50:17 +0200722 new_hist = ALLOC_MULT(histentry_T, hislen);
Bram Moolenaar5f32ece2019-07-21 21:51:59 +0200723 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
768finish_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
795write_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}
Bram Moolenaarc3328162019-07-23 22:15:25 +0200916#endif // FEAT_CMDHIST
Bram Moolenaar5f32ece2019-07-21 21:51:59 +0200917
Bram Moolenaardefa0672019-07-21 19:25:37 +0200918 static void
919write_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
949barline_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
Bram Moolenaardefa0672019-07-21 19:25:37 +02001122 static void
1123write_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
1130no_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 */
Bram Moolenaarc3328162019-07-23 22:15:25 +02001140 static int
Bram Moolenaardefa0672019-07-21 19:25:37 +02001141viminfo_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
1163viminfo_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
1190read_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
1280write_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
Bram Moolenaarc3328162019-07-23 22:15:25 +02001340 static int
1341read_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
1349write_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
1365read_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 spat = get_spat(idx);
1424 if (idx >= 0)
1425 {
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
1449wvsp_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
1473write_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
1490static 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
1499prepare_viminfo_registers(void)
1500{
1501 y_read_regs = ALLOC_CLEAR_MULT(yankreg_T, NUM_REGISTERS);
1502}
1503
1504 static void
1505finish_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
1524read_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
1662handle_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
1753write_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
1885static xfmark_T *vi_namedfm = NULL;
1886#ifdef FEAT_JUMPLIST
1887static xfmark_T *vi_jumplist = NULL;
1888static int vi_jumplist_len = 0;
1889#endif
1890
1891 static void
1892write_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
1899write_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
1935skip_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
1950write_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
1995write_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
2030write_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
2147buf_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
2164copy_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
2410check_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
2422read_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
2485prepare_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
2495finish_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
2519handle_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
2666read_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
Bram Moolenaardefa0672019-07-21 19:25:37 +02002744/*
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
2750read_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
2864do_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
2952read_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
2998write_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
3282end:
3283 vim_free(fname);
3284 vim_free(tempname);
3285}
3286
3287/*
Bram Moolenaardefa0672019-07-21 19:25:37 +02003288 * ":rviminfo" and ":wviminfo".
3289 */
3290 void
3291ex_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
Bram Moolenaardefa0672019-07-21 19:25:37 +02003310#endif // FEAT_VIMINFO