184538079SBram Moolenaar /* vi:set ts=8 sts=4 sw=4 noet:
284538079SBram Moolenaar *
384538079SBram Moolenaar * VIM - Vi IMproved by Bram Moolenaar
484538079SBram Moolenaar *
584538079SBram Moolenaar * Do ":help uganda" in Vim to read copying and usage conditions.
684538079SBram Moolenaar * Do ":help credits" in Vim to see a list of people who contributed.
784538079SBram Moolenaar * See README.txt for an overview of the Vim source code.
884538079SBram Moolenaar */
984538079SBram Moolenaar
1084538079SBram Moolenaar /*
1184538079SBram Moolenaar * session.c: session related functions
1284538079SBram Moolenaar */
1384538079SBram Moolenaar
1484538079SBram Moolenaar #include "vim.h"
1584538079SBram Moolenaar
1684538079SBram Moolenaar #if defined(FEAT_SESSION) || defined(PROTO)
1784538079SBram Moolenaar
1884538079SBram Moolenaar static int did_lcd; // whether ":lcd" was produced for a session
1984538079SBram Moolenaar
2084538079SBram Moolenaar /*
2184538079SBram Moolenaar * Write a file name to the session file.
2284538079SBram Moolenaar * Takes care of the "slash" option in 'sessionoptions' and escapes special
2384538079SBram Moolenaar * characters.
2484538079SBram Moolenaar * Returns FAIL if writing fails or out of memory.
2584538079SBram Moolenaar */
2684538079SBram Moolenaar static int
ses_put_fname(FILE * fd,char_u * name,unsigned * flagp)2784538079SBram Moolenaar ses_put_fname(FILE *fd, char_u *name, unsigned *flagp)
2884538079SBram Moolenaar {
2984538079SBram Moolenaar char_u *sname;
3084538079SBram Moolenaar char_u *p;
3184538079SBram Moolenaar int retval = OK;
3284538079SBram Moolenaar
3384538079SBram Moolenaar sname = home_replace_save(NULL, name);
3484538079SBram Moolenaar if (sname == NULL)
3584538079SBram Moolenaar return FAIL;
3684538079SBram Moolenaar
3784538079SBram Moolenaar if (*flagp & SSOP_SLASH)
3884538079SBram Moolenaar {
3984538079SBram Moolenaar // change all backslashes to forward slashes
4084538079SBram Moolenaar for (p = sname; *p != NUL; MB_PTR_ADV(p))
4184538079SBram Moolenaar if (*p == '\\')
4284538079SBram Moolenaar *p = '/';
4384538079SBram Moolenaar }
4484538079SBram Moolenaar
4584538079SBram Moolenaar // escape special characters
46*21c1a0c2SBram Moolenaar p = vim_strsave_fnameescape(sname, VSE_NONE);
4784538079SBram Moolenaar vim_free(sname);
4884538079SBram Moolenaar if (p == NULL)
4984538079SBram Moolenaar return FAIL;
5084538079SBram Moolenaar
5184538079SBram Moolenaar // write the result
5284538079SBram Moolenaar if (fputs((char *)p, fd) < 0)
5384538079SBram Moolenaar retval = FAIL;
5484538079SBram Moolenaar
5584538079SBram Moolenaar vim_free(p);
5684538079SBram Moolenaar return retval;
5784538079SBram Moolenaar }
5884538079SBram Moolenaar
5984538079SBram Moolenaar /*
6084538079SBram Moolenaar * Write a buffer name to the session file.
6184538079SBram Moolenaar * Also ends the line, if "add_eol" is TRUE.
6284538079SBram Moolenaar * Returns FAIL if writing fails.
6384538079SBram Moolenaar */
6484538079SBram Moolenaar static int
ses_fname(FILE * fd,buf_T * buf,unsigned * flagp,int add_eol)6584538079SBram Moolenaar ses_fname(FILE *fd, buf_T *buf, unsigned *flagp, int add_eol)
6684538079SBram Moolenaar {
6784538079SBram Moolenaar char_u *name;
6884538079SBram Moolenaar
6984538079SBram Moolenaar // Use the short file name if the current directory is known at the time
7084538079SBram Moolenaar // the session file will be sourced.
7184538079SBram Moolenaar // Don't do this for ":mkview", we don't know the current directory.
7284538079SBram Moolenaar // Don't do this after ":lcd", we don't keep track of what the current
7384538079SBram Moolenaar // directory is.
7484538079SBram Moolenaar if (buf->b_sfname != NULL
7584538079SBram Moolenaar && flagp == &ssop_flags
7684538079SBram Moolenaar && (ssop_flags & (SSOP_CURDIR | SSOP_SESDIR))
7784538079SBram Moolenaar #ifdef FEAT_AUTOCHDIR
7884538079SBram Moolenaar && !p_acd
7984538079SBram Moolenaar #endif
8084538079SBram Moolenaar && !did_lcd)
8184538079SBram Moolenaar name = buf->b_sfname;
8284538079SBram Moolenaar else
8384538079SBram Moolenaar name = buf->b_ffname;
8484538079SBram Moolenaar if (ses_put_fname(fd, name, flagp) == FAIL
8584538079SBram Moolenaar || (add_eol && put_eol(fd) == FAIL))
8684538079SBram Moolenaar return FAIL;
8784538079SBram Moolenaar return OK;
8884538079SBram Moolenaar }
8984538079SBram Moolenaar
9084538079SBram Moolenaar /*
9184538079SBram Moolenaar * Write an argument list to the session file.
9284538079SBram Moolenaar * Returns FAIL if writing fails.
9384538079SBram Moolenaar */
9484538079SBram Moolenaar static int
ses_arglist(FILE * fd,char * cmd,garray_T * gap,int fullname,unsigned * flagp)9584538079SBram Moolenaar ses_arglist(
9684538079SBram Moolenaar FILE *fd,
9784538079SBram Moolenaar char *cmd,
9884538079SBram Moolenaar garray_T *gap,
9984538079SBram Moolenaar int fullname, // TRUE: use full path name
10084538079SBram Moolenaar unsigned *flagp)
10184538079SBram Moolenaar {
10284538079SBram Moolenaar int i;
10384538079SBram Moolenaar char_u *buf = NULL;
10484538079SBram Moolenaar char_u *s;
10584538079SBram Moolenaar
10684538079SBram Moolenaar if (fputs(cmd, fd) < 0 || put_eol(fd) == FAIL)
10784538079SBram Moolenaar return FAIL;
10884538079SBram Moolenaar if (put_line(fd, "%argdel") == FAIL)
10984538079SBram Moolenaar return FAIL;
11084538079SBram Moolenaar for (i = 0; i < gap->ga_len; ++i)
11184538079SBram Moolenaar {
11284538079SBram Moolenaar // NULL file names are skipped (only happens when out of memory).
11384538079SBram Moolenaar s = alist_name(&((aentry_T *)gap->ga_data)[i]);
11484538079SBram Moolenaar if (s != NULL)
11584538079SBram Moolenaar {
11684538079SBram Moolenaar if (fullname)
11784538079SBram Moolenaar {
11884538079SBram Moolenaar buf = alloc(MAXPATHL);
11984538079SBram Moolenaar if (buf != NULL)
12084538079SBram Moolenaar {
12184538079SBram Moolenaar (void)vim_FullName(s, buf, MAXPATHL, FALSE);
12284538079SBram Moolenaar s = buf;
12384538079SBram Moolenaar }
12484538079SBram Moolenaar }
12584538079SBram Moolenaar if (fputs("$argadd ", fd) < 0
12684538079SBram Moolenaar || ses_put_fname(fd, s, flagp) == FAIL
12784538079SBram Moolenaar || put_eol(fd) == FAIL)
12884538079SBram Moolenaar {
12984538079SBram Moolenaar vim_free(buf);
13084538079SBram Moolenaar return FAIL;
13184538079SBram Moolenaar }
13284538079SBram Moolenaar vim_free(buf);
13384538079SBram Moolenaar }
13484538079SBram Moolenaar }
13584538079SBram Moolenaar return OK;
13684538079SBram Moolenaar }
13784538079SBram Moolenaar
13884538079SBram Moolenaar /*
13984538079SBram Moolenaar * Return non-zero if window "wp" is to be stored in the Session.
14084538079SBram Moolenaar */
14184538079SBram Moolenaar static int
ses_do_win(win_T * wp)14284538079SBram Moolenaar ses_do_win(win_T *wp)
14384538079SBram Moolenaar {
14484538079SBram Moolenaar #ifdef FEAT_TERMINAL
14584538079SBram Moolenaar if (bt_terminal(wp->w_buffer))
14684538079SBram Moolenaar return !term_is_finished(wp->w_buffer)
14784538079SBram Moolenaar && (ssop_flags & SSOP_TERMINAL)
14884538079SBram Moolenaar && term_should_restore(wp->w_buffer);
14984538079SBram Moolenaar #endif
15084538079SBram Moolenaar if (wp->w_buffer->b_fname == NULL
15184538079SBram Moolenaar #ifdef FEAT_QUICKFIX
15284538079SBram Moolenaar // When 'buftype' is "nofile" can't restore the window contents.
15384538079SBram Moolenaar || bt_nofilename(wp->w_buffer)
15484538079SBram Moolenaar #endif
15584538079SBram Moolenaar )
15684538079SBram Moolenaar return (ssop_flags & SSOP_BLANK);
15784538079SBram Moolenaar if (bt_help(wp->w_buffer))
15884538079SBram Moolenaar return (ssop_flags & SSOP_HELP);
15984538079SBram Moolenaar return TRUE;
16084538079SBram Moolenaar }
16184538079SBram Moolenaar
16284538079SBram Moolenaar /*
16384538079SBram Moolenaar * Return TRUE if frame "fr" has a window somewhere that we want to save in
16484538079SBram Moolenaar * the Session.
16584538079SBram Moolenaar */
16684538079SBram Moolenaar static int
ses_do_frame(frame_T * fr)16784538079SBram Moolenaar ses_do_frame(frame_T *fr)
16884538079SBram Moolenaar {
16984538079SBram Moolenaar frame_T *frc;
17084538079SBram Moolenaar
17184538079SBram Moolenaar if (fr->fr_layout == FR_LEAF)
17284538079SBram Moolenaar return ses_do_win(fr->fr_win);
17384538079SBram Moolenaar FOR_ALL_FRAMES(frc, fr->fr_child)
17484538079SBram Moolenaar if (ses_do_frame(frc))
17584538079SBram Moolenaar return TRUE;
17684538079SBram Moolenaar return FALSE;
17784538079SBram Moolenaar }
17884538079SBram Moolenaar
17984538079SBram Moolenaar /*
18084538079SBram Moolenaar * Skip frames that don't contain windows we want to save in the Session.
18184538079SBram Moolenaar * Returns NULL when there none.
18284538079SBram Moolenaar */
18384538079SBram Moolenaar static frame_T *
ses_skipframe(frame_T * fr)18484538079SBram Moolenaar ses_skipframe(frame_T *fr)
18584538079SBram Moolenaar {
18684538079SBram Moolenaar frame_T *frc;
18784538079SBram Moolenaar
18884538079SBram Moolenaar FOR_ALL_FRAMES(frc, fr)
18984538079SBram Moolenaar if (ses_do_frame(frc))
19084538079SBram Moolenaar break;
19184538079SBram Moolenaar return frc;
19284538079SBram Moolenaar }
19384538079SBram Moolenaar
19484538079SBram Moolenaar /*
19584538079SBram Moolenaar * Write commands to "fd" to recursively create windows for frame "fr",
19684538079SBram Moolenaar * horizontally and vertically split.
19784538079SBram Moolenaar * After the commands the last window in the frame is the current window.
19884538079SBram Moolenaar * Returns FAIL when writing the commands to "fd" fails.
19984538079SBram Moolenaar */
20084538079SBram Moolenaar static int
ses_win_rec(FILE * fd,frame_T * fr)20184538079SBram Moolenaar ses_win_rec(FILE *fd, frame_T *fr)
20284538079SBram Moolenaar {
20384538079SBram Moolenaar frame_T *frc;
20484538079SBram Moolenaar int count = 0;
20584538079SBram Moolenaar
20684538079SBram Moolenaar if (fr->fr_layout != FR_LEAF)
20784538079SBram Moolenaar {
20884538079SBram Moolenaar // Find first frame that's not skipped and then create a window for
20984538079SBram Moolenaar // each following one (first frame is already there).
21084538079SBram Moolenaar frc = ses_skipframe(fr->fr_child);
21184538079SBram Moolenaar if (frc != NULL)
21284538079SBram Moolenaar while ((frc = ses_skipframe(frc->fr_next)) != NULL)
21384538079SBram Moolenaar {
21484538079SBram Moolenaar // Make window as big as possible so that we have lots of room
21584538079SBram Moolenaar // to split.
21684538079SBram Moolenaar if (put_line(fd, "wincmd _ | wincmd |") == FAIL
21784538079SBram Moolenaar || put_line(fd, fr->fr_layout == FR_COL
21884538079SBram Moolenaar ? "split" : "vsplit") == FAIL)
21984538079SBram Moolenaar return FAIL;
22084538079SBram Moolenaar ++count;
22184538079SBram Moolenaar }
22284538079SBram Moolenaar
22384538079SBram Moolenaar // Go back to the first window.
22484538079SBram Moolenaar if (count > 0 && (fprintf(fd, fr->fr_layout == FR_COL
22584538079SBram Moolenaar ? "%dwincmd k" : "%dwincmd h", count) < 0
22684538079SBram Moolenaar || put_eol(fd) == FAIL))
22784538079SBram Moolenaar return FAIL;
22884538079SBram Moolenaar
22984538079SBram Moolenaar // Recursively create frames/windows in each window of this column or
23084538079SBram Moolenaar // row.
23184538079SBram Moolenaar frc = ses_skipframe(fr->fr_child);
23284538079SBram Moolenaar while (frc != NULL)
23384538079SBram Moolenaar {
23484538079SBram Moolenaar ses_win_rec(fd, frc);
23584538079SBram Moolenaar frc = ses_skipframe(frc->fr_next);
23684538079SBram Moolenaar // Go to next window.
23784538079SBram Moolenaar if (frc != NULL && put_line(fd, "wincmd w") == FAIL)
23884538079SBram Moolenaar return FAIL;
23984538079SBram Moolenaar }
24084538079SBram Moolenaar }
24184538079SBram Moolenaar return OK;
24284538079SBram Moolenaar }
24384538079SBram Moolenaar
24484538079SBram Moolenaar static int
ses_winsizes(FILE * fd,int restore_size,win_T * tab_firstwin)24584538079SBram Moolenaar ses_winsizes(
24684538079SBram Moolenaar FILE *fd,
24784538079SBram Moolenaar int restore_size,
24884538079SBram Moolenaar win_T *tab_firstwin)
24984538079SBram Moolenaar {
25084538079SBram Moolenaar int n = 0;
25184538079SBram Moolenaar win_T *wp;
25284538079SBram Moolenaar
25384538079SBram Moolenaar if (restore_size && (ssop_flags & SSOP_WINSIZE))
25484538079SBram Moolenaar {
25584538079SBram Moolenaar for (wp = tab_firstwin; wp != NULL; wp = wp->w_next)
25684538079SBram Moolenaar {
25784538079SBram Moolenaar if (!ses_do_win(wp))
25884538079SBram Moolenaar continue;
25984538079SBram Moolenaar ++n;
26084538079SBram Moolenaar
26184538079SBram Moolenaar // restore height when not full height
26284538079SBram Moolenaar if (wp->w_height + wp->w_status_height < topframe->fr_height
26384538079SBram Moolenaar && (fprintf(fd,
26484538079SBram Moolenaar "exe '%dresize ' . ((&lines * %ld + %ld) / %ld)",
26584538079SBram Moolenaar n, (long)wp->w_height, Rows / 2, Rows) < 0
26684538079SBram Moolenaar || put_eol(fd) == FAIL))
26784538079SBram Moolenaar return FAIL;
26884538079SBram Moolenaar
26984538079SBram Moolenaar // restore width when not full width
27084538079SBram Moolenaar if (wp->w_width < Columns && (fprintf(fd,
27184538079SBram Moolenaar "exe 'vert %dresize ' . ((&columns * %ld + %ld) / %ld)",
27284538079SBram Moolenaar n, (long)wp->w_width, Columns / 2, Columns) < 0
27384538079SBram Moolenaar || put_eol(fd) == FAIL))
27484538079SBram Moolenaar return FAIL;
27584538079SBram Moolenaar }
27684538079SBram Moolenaar }
27784538079SBram Moolenaar else
27884538079SBram Moolenaar {
27984538079SBram Moolenaar // Just equalise window sizes
28084538079SBram Moolenaar if (put_line(fd, "wincmd =") == FAIL)
28184538079SBram Moolenaar return FAIL;
28284538079SBram Moolenaar }
28384538079SBram Moolenaar return OK;
28484538079SBram Moolenaar }
28584538079SBram Moolenaar
28684538079SBram Moolenaar static int
put_view_curpos(FILE * fd,win_T * wp,char * spaces)28784538079SBram Moolenaar put_view_curpos(FILE *fd, win_T *wp, char *spaces)
28884538079SBram Moolenaar {
28984538079SBram Moolenaar int r;
29084538079SBram Moolenaar
29184538079SBram Moolenaar if (wp->w_curswant == MAXCOL)
29284538079SBram Moolenaar r = fprintf(fd, "%snormal! $", spaces);
29384538079SBram Moolenaar else
29484538079SBram Moolenaar r = fprintf(fd, "%snormal! 0%d|", spaces, wp->w_virtcol + 1);
29584538079SBram Moolenaar return r < 0 || put_eol(fd) == FAIL ? FALSE : OK;
29684538079SBram Moolenaar }
29784538079SBram Moolenaar
29884538079SBram Moolenaar /*
29984538079SBram Moolenaar * Write commands to "fd" to restore the view of a window.
30084538079SBram Moolenaar * Caller must make sure 'scrolloff' is zero.
30184538079SBram Moolenaar */
30284538079SBram Moolenaar static int
put_view(FILE * fd,win_T * wp,int add_edit,unsigned * flagp,int current_arg_idx,hashtab_T * terminal_bufs UNUSED)30384538079SBram Moolenaar put_view(
30484538079SBram Moolenaar FILE *fd,
30584538079SBram Moolenaar win_T *wp,
30684538079SBram Moolenaar int add_edit, // add ":edit" command to view
30784538079SBram Moolenaar unsigned *flagp, // vop_flags or ssop_flags
308c2c82056SBram Moolenaar int current_arg_idx, // current argument index of the window,
309c2c82056SBram Moolenaar // use -1 if unknown
310c2c82056SBram Moolenaar hashtab_T *terminal_bufs UNUSED) // already encountered terminal buffers,
311c2c82056SBram Moolenaar // can be NULL
31284538079SBram Moolenaar {
31384538079SBram Moolenaar win_T *save_curwin;
31484538079SBram Moolenaar int f;
31584538079SBram Moolenaar int do_cursor;
31684538079SBram Moolenaar int did_next = FALSE;
31784538079SBram Moolenaar
31884538079SBram Moolenaar // Always restore cursor position for ":mksession". For ":mkview" only
31984538079SBram Moolenaar // when 'viewoptions' contains "cursor".
32084538079SBram Moolenaar do_cursor = (flagp == &ssop_flags || *flagp & SSOP_CURSOR);
32184538079SBram Moolenaar
32284538079SBram Moolenaar // Local argument list.
32384538079SBram Moolenaar if (wp->w_alist == &global_alist)
32484538079SBram Moolenaar {
32584538079SBram Moolenaar if (put_line(fd, "argglobal") == FAIL)
32684538079SBram Moolenaar return FAIL;
32784538079SBram Moolenaar }
32884538079SBram Moolenaar else
32984538079SBram Moolenaar {
33084538079SBram Moolenaar if (ses_arglist(fd, "arglocal", &wp->w_alist->al_ga,
33184538079SBram Moolenaar flagp == &vop_flags
33284538079SBram Moolenaar || !(*flagp & SSOP_CURDIR)
33384538079SBram Moolenaar || wp->w_localdir != NULL, flagp) == FAIL)
33484538079SBram Moolenaar return FAIL;
33584538079SBram Moolenaar }
33684538079SBram Moolenaar
33784538079SBram Moolenaar // Only when part of a session: restore the argument index. Some
33884538079SBram Moolenaar // arguments may have been deleted, check if the index is valid.
33984538079SBram Moolenaar if (wp->w_arg_idx != current_arg_idx && wp->w_arg_idx < WARGCOUNT(wp)
34084538079SBram Moolenaar && flagp == &ssop_flags)
34184538079SBram Moolenaar {
34284538079SBram Moolenaar if (fprintf(fd, "%ldargu", (long)wp->w_arg_idx + 1) < 0
34384538079SBram Moolenaar || put_eol(fd) == FAIL)
34484538079SBram Moolenaar return FAIL;
34584538079SBram Moolenaar did_next = TRUE;
34684538079SBram Moolenaar }
34784538079SBram Moolenaar
34884538079SBram Moolenaar // Edit the file. Skip this when ":next" already did it.
34984538079SBram Moolenaar if (add_edit && (!did_next || wp->w_arg_idx_invalid))
35084538079SBram Moolenaar {
35184538079SBram Moolenaar # ifdef FEAT_TERMINAL
35284538079SBram Moolenaar if (bt_terminal(wp->w_buffer))
35384538079SBram Moolenaar {
3540e655111SBram Moolenaar if (term_write_session(fd, wp, terminal_bufs) == FAIL)
35584538079SBram Moolenaar return FAIL;
35684538079SBram Moolenaar }
35784538079SBram Moolenaar else
35884538079SBram Moolenaar # endif
35984538079SBram Moolenaar // Load the file.
36084538079SBram Moolenaar if (wp->w_buffer->b_ffname != NULL
36184538079SBram Moolenaar # ifdef FEAT_QUICKFIX
36284538079SBram Moolenaar && !bt_nofilename(wp->w_buffer)
36384538079SBram Moolenaar # endif
36484538079SBram Moolenaar )
36584538079SBram Moolenaar {
36684538079SBram Moolenaar // Editing a file in this buffer: use ":edit file".
36784538079SBram Moolenaar // This may have side effects! (e.g., compressed or network file).
36884538079SBram Moolenaar //
36984538079SBram Moolenaar // Note, if a buffer for that file already exists, use :badd to
37084538079SBram Moolenaar // edit that buffer, to not lose folding information (:edit resets
37184538079SBram Moolenaar // folds in other buffers)
37284538079SBram Moolenaar if (fputs("if bufexists(\"", fd) < 0
37384538079SBram Moolenaar || ses_fname(fd, wp->w_buffer, flagp, FALSE) == FAIL
37484538079SBram Moolenaar || fputs("\") | buffer ", fd) < 0
37584538079SBram Moolenaar || ses_fname(fd, wp->w_buffer, flagp, FALSE) == FAIL
37684538079SBram Moolenaar || fputs(" | else | edit ", fd) < 0
37784538079SBram Moolenaar || ses_fname(fd, wp->w_buffer, flagp, FALSE) == FAIL
37884538079SBram Moolenaar || fputs(" | endif", fd) < 0
37984538079SBram Moolenaar || put_eol(fd) == FAIL)
38084538079SBram Moolenaar return FAIL;
38184538079SBram Moolenaar }
38284538079SBram Moolenaar else
38384538079SBram Moolenaar {
38484538079SBram Moolenaar // No file in this buffer, just make it empty.
38584538079SBram Moolenaar if (put_line(fd, "enew") == FAIL)
38684538079SBram Moolenaar return FAIL;
38784538079SBram Moolenaar #ifdef FEAT_QUICKFIX
38884538079SBram Moolenaar if (wp->w_buffer->b_ffname != NULL)
38984538079SBram Moolenaar {
39084538079SBram Moolenaar // The buffer does have a name, but it's not a file name.
39184538079SBram Moolenaar if (fputs("file ", fd) < 0
39284538079SBram Moolenaar || ses_fname(fd, wp->w_buffer, flagp, TRUE) == FAIL)
39384538079SBram Moolenaar return FAIL;
39484538079SBram Moolenaar }
39584538079SBram Moolenaar #endif
39684538079SBram Moolenaar do_cursor = FALSE;
39784538079SBram Moolenaar }
39884538079SBram Moolenaar }
39984538079SBram Moolenaar
40059d8e56eSBram Moolenaar if (wp->w_alt_fnum)
40159d8e56eSBram Moolenaar {
40259d8e56eSBram Moolenaar buf_T *alt = buflist_findnr(wp->w_alt_fnum);
40359d8e56eSBram Moolenaar
4040756f757SBram Moolenaar // Set the alternate file if the buffer is listed.
405139348f3SBram Moolenaar if ((flagp == &ssop_flags)
406139348f3SBram Moolenaar && alt != NULL
40759d8e56eSBram Moolenaar && alt->b_fname != NULL
40859d8e56eSBram Moolenaar && *alt->b_fname != NUL
4090756f757SBram Moolenaar && alt->b_p_bl
41059d8e56eSBram Moolenaar && (fputs("balt ", fd) < 0
41159d8e56eSBram Moolenaar || ses_fname(fd, alt, flagp, TRUE) == FAIL))
41259d8e56eSBram Moolenaar return FAIL;
41359d8e56eSBram Moolenaar }
41459d8e56eSBram Moolenaar
41584538079SBram Moolenaar // Local mappings and abbreviations.
41684538079SBram Moolenaar if ((*flagp & (SSOP_OPTIONS | SSOP_LOCALOPTIONS))
41784538079SBram Moolenaar && makemap(fd, wp->w_buffer) == FAIL)
41884538079SBram Moolenaar return FAIL;
41984538079SBram Moolenaar
42084538079SBram Moolenaar // Local options. Need to go to the window temporarily.
42184538079SBram Moolenaar // Store only local values when using ":mkview" and when ":mksession" is
42284538079SBram Moolenaar // used and 'sessionoptions' doesn't include "options".
42384538079SBram Moolenaar // Some folding options are always stored when "folds" is included,
42484538079SBram Moolenaar // otherwise the folds would not be restored correctly.
42584538079SBram Moolenaar save_curwin = curwin;
42684538079SBram Moolenaar curwin = wp;
42784538079SBram Moolenaar curbuf = curwin->w_buffer;
42884538079SBram Moolenaar if (*flagp & (SSOP_OPTIONS | SSOP_LOCALOPTIONS))
42984538079SBram Moolenaar f = makeset(fd, OPT_LOCAL,
43084538079SBram Moolenaar flagp == &vop_flags || !(*flagp & SSOP_OPTIONS));
43184538079SBram Moolenaar #ifdef FEAT_FOLDING
43284538079SBram Moolenaar else if (*flagp & SSOP_FOLDS)
43384538079SBram Moolenaar f = makefoldset(fd);
43484538079SBram Moolenaar #endif
43584538079SBram Moolenaar else
43684538079SBram Moolenaar f = OK;
43784538079SBram Moolenaar curwin = save_curwin;
43884538079SBram Moolenaar curbuf = curwin->w_buffer;
43984538079SBram Moolenaar if (f == FAIL)
44084538079SBram Moolenaar return FAIL;
44184538079SBram Moolenaar
44284538079SBram Moolenaar #ifdef FEAT_FOLDING
44384538079SBram Moolenaar // Save Folds when 'buftype' is empty and for help files.
44484538079SBram Moolenaar if ((*flagp & SSOP_FOLDS)
44584538079SBram Moolenaar && wp->w_buffer->b_ffname != NULL
44684538079SBram Moolenaar && (bt_normal(wp->w_buffer) || bt_help(wp->w_buffer)))
44784538079SBram Moolenaar {
44884538079SBram Moolenaar if (put_folds(fd, wp) == FAIL)
44984538079SBram Moolenaar return FAIL;
45084538079SBram Moolenaar }
45184538079SBram Moolenaar #endif
45284538079SBram Moolenaar
45384538079SBram Moolenaar // Set the cursor after creating folds, since that moves the cursor.
45484538079SBram Moolenaar if (do_cursor)
45584538079SBram Moolenaar {
45684538079SBram Moolenaar
45784538079SBram Moolenaar // Restore the cursor line in the file and relatively in the
45884538079SBram Moolenaar // window. Don't use "G", it changes the jumplist.
459b6c2e9a0SBram Moolenaar if (wp->w_height <= 0)
460b6c2e9a0SBram Moolenaar {
461b6c2e9a0SBram Moolenaar if (fprintf(fd, "let s:l = %ld", (long)wp->w_cursor.lnum) < 0)
462b6c2e9a0SBram Moolenaar return FAIL;
463b6c2e9a0SBram Moolenaar }
464b6c2e9a0SBram Moolenaar else if (fprintf(fd,
465b6c2e9a0SBram Moolenaar "let s:l = %ld - ((%ld * winheight(0) + %ld) / %ld)",
46684538079SBram Moolenaar (long)wp->w_cursor.lnum,
46784538079SBram Moolenaar (long)(wp->w_cursor.lnum - wp->w_topline),
468b6c2e9a0SBram Moolenaar (long)wp->w_height / 2, (long)wp->w_height) < 0)
469b6c2e9a0SBram Moolenaar return FAIL;
470b6c2e9a0SBram Moolenaar
471b6c2e9a0SBram Moolenaar if (put_eol(fd) == FAIL
47284538079SBram Moolenaar || put_line(fd, "if s:l < 1 | let s:l = 1 | endif") == FAIL
4733482be6aSBram Moolenaar || put_line(fd, "keepjumps exe s:l") == FAIL
47484538079SBram Moolenaar || put_line(fd, "normal! zt") == FAIL
4753482be6aSBram Moolenaar || fprintf(fd, "keepjumps %ld", (long)wp->w_cursor.lnum) < 0
47684538079SBram Moolenaar || put_eol(fd) == FAIL)
47784538079SBram Moolenaar return FAIL;
47884538079SBram Moolenaar // Restore the cursor column and left offset when not wrapping.
47984538079SBram Moolenaar if (wp->w_cursor.col == 0)
48084538079SBram Moolenaar {
48184538079SBram Moolenaar if (put_line(fd, "normal! 0") == FAIL)
48284538079SBram Moolenaar return FAIL;
48384538079SBram Moolenaar }
48484538079SBram Moolenaar else
48584538079SBram Moolenaar {
48684538079SBram Moolenaar if (!wp->w_p_wrap && wp->w_leftcol > 0 && wp->w_width > 0)
48784538079SBram Moolenaar {
48884538079SBram Moolenaar if (fprintf(fd,
48984538079SBram Moolenaar "let s:c = %ld - ((%ld * winwidth(0) + %ld) / %ld)",
49084538079SBram Moolenaar (long)wp->w_virtcol + 1,
49184538079SBram Moolenaar (long)(wp->w_virtcol - wp->w_leftcol),
49284538079SBram Moolenaar (long)wp->w_width / 2, (long)wp->w_width) < 0
49384538079SBram Moolenaar || put_eol(fd) == FAIL
49484538079SBram Moolenaar || put_line(fd, "if s:c > 0") == FAIL
49584538079SBram Moolenaar || fprintf(fd,
49684538079SBram Moolenaar " exe 'normal! ' . s:c . '|zs' . %ld . '|'",
49784538079SBram Moolenaar (long)wp->w_virtcol + 1) < 0
49884538079SBram Moolenaar || put_eol(fd) == FAIL
49984538079SBram Moolenaar || put_line(fd, "else") == FAIL
50084538079SBram Moolenaar || put_view_curpos(fd, wp, " ") == FAIL
50184538079SBram Moolenaar || put_line(fd, "endif") == FAIL)
50284538079SBram Moolenaar return FAIL;
50384538079SBram Moolenaar }
50484538079SBram Moolenaar else if (put_view_curpos(fd, wp, "") == FAIL)
50584538079SBram Moolenaar return FAIL;
50684538079SBram Moolenaar }
50784538079SBram Moolenaar }
50884538079SBram Moolenaar
50984538079SBram Moolenaar // Local directory, if the current flag is not view options or the "curdir"
51084538079SBram Moolenaar // option is included.
51184538079SBram Moolenaar if (wp->w_localdir != NULL
51284538079SBram Moolenaar && (flagp != &vop_flags || (*flagp & SSOP_CURDIR)))
51384538079SBram Moolenaar {
51484538079SBram Moolenaar if (fputs("lcd ", fd) < 0
51584538079SBram Moolenaar || ses_put_fname(fd, wp->w_localdir, flagp) == FAIL
51684538079SBram Moolenaar || put_eol(fd) == FAIL)
51784538079SBram Moolenaar return FAIL;
51884538079SBram Moolenaar did_lcd = TRUE;
51984538079SBram Moolenaar }
52084538079SBram Moolenaar
52184538079SBram Moolenaar return OK;
52284538079SBram Moolenaar }
52384538079SBram Moolenaar
52484538079SBram Moolenaar #ifdef FEAT_EVAL
52584538079SBram Moolenaar static int
store_session_globals(FILE * fd)52684538079SBram Moolenaar store_session_globals(FILE *fd)
52784538079SBram Moolenaar {
528da6c0334SBram Moolenaar hashtab_T *gvht = get_globvar_ht();
52984538079SBram Moolenaar hashitem_T *hi;
53084538079SBram Moolenaar dictitem_T *this_var;
53184538079SBram Moolenaar int todo;
53284538079SBram Moolenaar char_u *p, *t;
53384538079SBram Moolenaar
534da6c0334SBram Moolenaar todo = (int)gvht->ht_used;
535da6c0334SBram Moolenaar for (hi = gvht->ht_array; todo > 0; ++hi)
53684538079SBram Moolenaar {
53784538079SBram Moolenaar if (!HASHITEM_EMPTY(hi))
53884538079SBram Moolenaar {
53984538079SBram Moolenaar --todo;
54084538079SBram Moolenaar this_var = HI2DI(hi);
54184538079SBram Moolenaar if ((this_var->di_tv.v_type == VAR_NUMBER
54284538079SBram Moolenaar || this_var->di_tv.v_type == VAR_STRING)
54384538079SBram Moolenaar && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION)
54484538079SBram Moolenaar {
54584538079SBram Moolenaar // Escape special characters with a backslash. Turn a LF and
54684538079SBram Moolenaar // CR into \n and \r.
54784538079SBram Moolenaar p = vim_strsave_escaped(tv_get_string(&this_var->di_tv),
54884538079SBram Moolenaar (char_u *)"\\\"\n\r");
54984538079SBram Moolenaar if (p == NULL) // out of memory
55084538079SBram Moolenaar break;
55184538079SBram Moolenaar for (t = p; *t != NUL; ++t)
55284538079SBram Moolenaar if (*t == '\n')
55384538079SBram Moolenaar *t = 'n';
55484538079SBram Moolenaar else if (*t == '\r')
55584538079SBram Moolenaar *t = 'r';
55684538079SBram Moolenaar if ((fprintf(fd, "let %s = %c%s%c",
55784538079SBram Moolenaar this_var->di_key,
55884538079SBram Moolenaar (this_var->di_tv.v_type == VAR_STRING) ? '"'
55984538079SBram Moolenaar : ' ',
56084538079SBram Moolenaar p,
56184538079SBram Moolenaar (this_var->di_tv.v_type == VAR_STRING) ? '"'
56284538079SBram Moolenaar : ' ') < 0)
56384538079SBram Moolenaar || put_eol(fd) == FAIL)
56484538079SBram Moolenaar {
56584538079SBram Moolenaar vim_free(p);
56684538079SBram Moolenaar return FAIL;
56784538079SBram Moolenaar }
56884538079SBram Moolenaar vim_free(p);
56984538079SBram Moolenaar }
57084538079SBram Moolenaar #ifdef FEAT_FLOAT
57184538079SBram Moolenaar else if (this_var->di_tv.v_type == VAR_FLOAT
57284538079SBram Moolenaar && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION)
57384538079SBram Moolenaar {
57484538079SBram Moolenaar float_T f = this_var->di_tv.vval.v_float;
57584538079SBram Moolenaar int sign = ' ';
57684538079SBram Moolenaar
57784538079SBram Moolenaar if (f < 0)
57884538079SBram Moolenaar {
57984538079SBram Moolenaar f = -f;
58084538079SBram Moolenaar sign = '-';
58184538079SBram Moolenaar }
58284538079SBram Moolenaar if ((fprintf(fd, "let %s = %c%f",
58384538079SBram Moolenaar this_var->di_key, sign, f) < 0)
58484538079SBram Moolenaar || put_eol(fd) == FAIL)
58584538079SBram Moolenaar return FAIL;
58684538079SBram Moolenaar }
58784538079SBram Moolenaar #endif
58884538079SBram Moolenaar }
58984538079SBram Moolenaar }
59084538079SBram Moolenaar return OK;
59184538079SBram Moolenaar }
59284538079SBram Moolenaar #endif
59384538079SBram Moolenaar
59484538079SBram Moolenaar /*
59584538079SBram Moolenaar * Write openfile commands for the current buffers to an .exrc file.
59684538079SBram Moolenaar * Return FAIL on error, OK otherwise.
59784538079SBram Moolenaar */
59884538079SBram Moolenaar static int
makeopens(FILE * fd,char_u * dirnow)59984538079SBram Moolenaar makeopens(
60084538079SBram Moolenaar FILE *fd,
60184538079SBram Moolenaar char_u *dirnow) // Current directory name
60284538079SBram Moolenaar {
60384538079SBram Moolenaar buf_T *buf;
60484538079SBram Moolenaar int only_save_windows = TRUE;
60584538079SBram Moolenaar int nr;
60684538079SBram Moolenaar int restore_size = TRUE;
60784538079SBram Moolenaar win_T *wp;
60884538079SBram Moolenaar char_u *sname;
60984538079SBram Moolenaar win_T *edited_win = NULL;
61084538079SBram Moolenaar int tabnr;
61184538079SBram Moolenaar int restore_stal = FALSE;
61284538079SBram Moolenaar win_T *tab_firstwin;
61384538079SBram Moolenaar frame_T *tab_topframe;
61484538079SBram Moolenaar int cur_arg_idx = 0;
61584538079SBram Moolenaar int next_arg_idx = 0;
6160e655111SBram Moolenaar int ret = FAIL;
6170e655111SBram Moolenaar #ifdef FEAT_TERMINAL
6180e655111SBram Moolenaar hashtab_T terminal_bufs;
6190e655111SBram Moolenaar
6200e655111SBram Moolenaar hash_init(&terminal_bufs);
6210e655111SBram Moolenaar #endif
62284538079SBram Moolenaar
62384538079SBram Moolenaar if (ssop_flags & SSOP_BUFFERS)
62484538079SBram Moolenaar only_save_windows = FALSE; // Save ALL buffers
62584538079SBram Moolenaar
62684538079SBram Moolenaar // Begin by setting the this_session variable, and then other
62784538079SBram Moolenaar // sessionable variables.
62884538079SBram Moolenaar #ifdef FEAT_EVAL
62984538079SBram Moolenaar if (put_line(fd, "let v:this_session=expand(\"<sfile>:p\")") == FAIL)
6300e655111SBram Moolenaar goto fail;
63184538079SBram Moolenaar if (ssop_flags & SSOP_GLOBALS)
63284538079SBram Moolenaar if (store_session_globals(fd) == FAIL)
6330e655111SBram Moolenaar goto fail;
63484538079SBram Moolenaar #endif
63584538079SBram Moolenaar
63684538079SBram Moolenaar // Close all windows and tabs but one.
63784538079SBram Moolenaar if (put_line(fd, "silent only") == FAIL)
6380e655111SBram Moolenaar goto fail;
63984538079SBram Moolenaar if ((ssop_flags & SSOP_TABPAGES)
64084538079SBram Moolenaar && put_line(fd, "silent tabonly") == FAIL)
6410e655111SBram Moolenaar goto fail;
64284538079SBram Moolenaar
64384538079SBram Moolenaar // Now a :cd command to the session directory or the current directory
64484538079SBram Moolenaar if (ssop_flags & SSOP_SESDIR)
64584538079SBram Moolenaar {
64684538079SBram Moolenaar if (put_line(fd, "exe \"cd \" . escape(expand(\"<sfile>:p:h\"), ' ')")
64784538079SBram Moolenaar == FAIL)
6480e655111SBram Moolenaar goto fail;
64984538079SBram Moolenaar }
65084538079SBram Moolenaar else if (ssop_flags & SSOP_CURDIR)
65184538079SBram Moolenaar {
65284538079SBram Moolenaar sname = home_replace_save(NULL, globaldir != NULL ? globaldir : dirnow);
65384538079SBram Moolenaar if (sname == NULL
65484538079SBram Moolenaar || fputs("cd ", fd) < 0
65584538079SBram Moolenaar || ses_put_fname(fd, sname, &ssop_flags) == FAIL
65684538079SBram Moolenaar || put_eol(fd) == FAIL)
65784538079SBram Moolenaar {
65884538079SBram Moolenaar vim_free(sname);
6590e655111SBram Moolenaar goto fail;
66084538079SBram Moolenaar }
66184538079SBram Moolenaar vim_free(sname);
66284538079SBram Moolenaar }
66384538079SBram Moolenaar
66484538079SBram Moolenaar // If there is an empty, unnamed buffer we will wipe it out later.
66584538079SBram Moolenaar // Remember the buffer number.
66684538079SBram Moolenaar if (put_line(fd, "if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == ''") == FAIL)
6670e655111SBram Moolenaar goto fail;
66884538079SBram Moolenaar if (put_line(fd, " let s:wipebuf = bufnr('%')") == FAIL)
6690e655111SBram Moolenaar goto fail;
67084538079SBram Moolenaar if (put_line(fd, "endif") == FAIL)
6710e655111SBram Moolenaar goto fail;
67284538079SBram Moolenaar
67384538079SBram Moolenaar // Now save the current files, current buffer first.
67484538079SBram Moolenaar if (put_line(fd, "set shortmess=aoO") == FAIL)
6750e655111SBram Moolenaar goto fail;
67684538079SBram Moolenaar
67784538079SBram Moolenaar // the global argument list
67884538079SBram Moolenaar if (ses_arglist(fd, "argglobal", &global_alist.al_ga,
67984538079SBram Moolenaar !(ssop_flags & SSOP_CURDIR), &ssop_flags) == FAIL)
6800e655111SBram Moolenaar goto fail;
68184538079SBram Moolenaar
68284538079SBram Moolenaar if (ssop_flags & SSOP_RESIZE)
68384538079SBram Moolenaar {
68484538079SBram Moolenaar // Note: after the restore we still check it worked!
68584538079SBram Moolenaar if (fprintf(fd, "set lines=%ld columns=%ld" , Rows, Columns) < 0
68684538079SBram Moolenaar || put_eol(fd) == FAIL)
6870e655111SBram Moolenaar goto fail;
68884538079SBram Moolenaar }
68984538079SBram Moolenaar
69084538079SBram Moolenaar #ifdef FEAT_GUI
69184538079SBram Moolenaar if (gui.in_use && (ssop_flags & SSOP_WINPOS))
69284538079SBram Moolenaar {
69384538079SBram Moolenaar int x, y;
69484538079SBram Moolenaar
69584538079SBram Moolenaar if (gui_mch_get_winpos(&x, &y) == OK)
69684538079SBram Moolenaar {
69784538079SBram Moolenaar // Note: after the restore we still check it worked!
69884538079SBram Moolenaar if (fprintf(fd, "winpos %d %d", x, y) < 0 || put_eol(fd) == FAIL)
6990e655111SBram Moolenaar goto fail;
70084538079SBram Moolenaar }
70184538079SBram Moolenaar }
70284538079SBram Moolenaar #endif
70384538079SBram Moolenaar
70484538079SBram Moolenaar // When there are two or more tabpages and 'showtabline' is 1 the tabline
70584538079SBram Moolenaar // will be displayed when creating the next tab. That resizes the windows
70684538079SBram Moolenaar // in the first tab, which may cause problems. Set 'showtabline' to 2
70784538079SBram Moolenaar // temporarily to avoid that.
70884538079SBram Moolenaar if (p_stal == 1 && first_tabpage->tp_next != NULL)
70984538079SBram Moolenaar {
71084538079SBram Moolenaar if (put_line(fd, "set stal=2") == FAIL)
7110e655111SBram Moolenaar goto fail;
71284538079SBram Moolenaar restore_stal = TRUE;
71384538079SBram Moolenaar }
71484538079SBram Moolenaar
71584538079SBram Moolenaar // May repeat putting Windows for each tab, when "tabpages" is in
71684538079SBram Moolenaar // 'sessionoptions'.
71784538079SBram Moolenaar // Don't use goto_tabpage(), it may change directory and trigger
71884538079SBram Moolenaar // autocommands.
71984538079SBram Moolenaar tab_firstwin = firstwin; // first window in tab page "tabnr"
72084538079SBram Moolenaar tab_topframe = topframe;
72184538079SBram Moolenaar if ((ssop_flags & SSOP_TABPAGES))
72284538079SBram Moolenaar {
72384538079SBram Moolenaar tabpage_T *tp;
72484538079SBram Moolenaar
72584538079SBram Moolenaar // Similar to ses_win_rec() below, populate the tab pages first so
72684538079SBram Moolenaar // later local options won't be copied to the new tabs.
72784538079SBram Moolenaar FOR_ALL_TABPAGES(tp)
72884538079SBram Moolenaar if (tp->tp_next != NULL && put_line(fd, "tabnew") == FAIL)
7290e655111SBram Moolenaar goto fail;
73084538079SBram Moolenaar if (first_tabpage->tp_next != NULL && put_line(fd, "tabrewind") == FAIL)
7310e655111SBram Moolenaar goto fail;
73284538079SBram Moolenaar }
73384538079SBram Moolenaar for (tabnr = 1; ; ++tabnr)
73484538079SBram Moolenaar {
73584538079SBram Moolenaar tabpage_T *tp = NULL;
73684538079SBram Moolenaar int need_tabnext = FALSE;
73784538079SBram Moolenaar int cnr = 1;
73884538079SBram Moolenaar
73984538079SBram Moolenaar if ((ssop_flags & SSOP_TABPAGES))
74084538079SBram Moolenaar {
74184538079SBram Moolenaar tp = find_tabpage(tabnr);
74284538079SBram Moolenaar
74384538079SBram Moolenaar if (tp == NULL)
74484538079SBram Moolenaar break; // done all tab pages
74584538079SBram Moolenaar if (tp == curtab)
74684538079SBram Moolenaar {
74784538079SBram Moolenaar tab_firstwin = firstwin;
74884538079SBram Moolenaar tab_topframe = topframe;
74984538079SBram Moolenaar }
75084538079SBram Moolenaar else
75184538079SBram Moolenaar {
75284538079SBram Moolenaar tab_firstwin = tp->tp_firstwin;
75384538079SBram Moolenaar tab_topframe = tp->tp_topframe;
75484538079SBram Moolenaar }
75584538079SBram Moolenaar if (tabnr > 1)
75684538079SBram Moolenaar need_tabnext = TRUE;
75784538079SBram Moolenaar }
75884538079SBram Moolenaar
75984538079SBram Moolenaar // Before creating the window layout, try loading one file. If this
76084538079SBram Moolenaar // is aborted we don't end up with a number of useless windows.
76184538079SBram Moolenaar // This may have side effects! (e.g., compressed or network file).
76284538079SBram Moolenaar for (wp = tab_firstwin; wp != NULL; wp = wp->w_next)
76384538079SBram Moolenaar {
76484538079SBram Moolenaar if (ses_do_win(wp)
76584538079SBram Moolenaar && wp->w_buffer->b_ffname != NULL
76684538079SBram Moolenaar && !bt_help(wp->w_buffer)
76784538079SBram Moolenaar #ifdef FEAT_QUICKFIX
76884538079SBram Moolenaar && !bt_nofilename(wp->w_buffer)
76984538079SBram Moolenaar #endif
77084538079SBram Moolenaar )
77184538079SBram Moolenaar {
77284538079SBram Moolenaar if (need_tabnext && put_line(fd, "tabnext") == FAIL)
7730e655111SBram Moolenaar goto fail;
77484538079SBram Moolenaar need_tabnext = FALSE;
77584538079SBram Moolenaar
77684538079SBram Moolenaar if (fputs("edit ", fd) < 0
77784538079SBram Moolenaar || ses_fname(fd, wp->w_buffer, &ssop_flags, TRUE)
77884538079SBram Moolenaar == FAIL)
7790e655111SBram Moolenaar goto fail;
78084538079SBram Moolenaar if (!wp->w_arg_idx_invalid)
78184538079SBram Moolenaar edited_win = wp;
78284538079SBram Moolenaar break;
78384538079SBram Moolenaar }
78484538079SBram Moolenaar }
78584538079SBram Moolenaar
78684538079SBram Moolenaar // If no file got edited create an empty tab page.
78784538079SBram Moolenaar if (need_tabnext && put_line(fd, "tabnext") == FAIL)
7880e655111SBram Moolenaar goto fail;
78984538079SBram Moolenaar
7900995c81fSBram Moolenaar if (tab_topframe->fr_layout != FR_LEAF)
7910995c81fSBram Moolenaar {
79284538079SBram Moolenaar // Save current window layout.
7930995c81fSBram Moolenaar if (put_line(fd, "let s:save_splitbelow = &splitbelow") == FAIL
7940995c81fSBram Moolenaar || put_line(fd, "let s:save_splitright = &splitright")
7950995c81fSBram Moolenaar == FAIL)
7960995c81fSBram Moolenaar goto fail;
79784538079SBram Moolenaar if (put_line(fd, "set splitbelow splitright") == FAIL)
7980e655111SBram Moolenaar goto fail;
79984538079SBram Moolenaar if (ses_win_rec(fd, tab_topframe) == FAIL)
8000e655111SBram Moolenaar goto fail;
8010995c81fSBram Moolenaar if (put_line(fd, "let &splitbelow = s:save_splitbelow") == FAIL
8020995c81fSBram Moolenaar || put_line(fd, "let &splitright = s:save_splitright")
8030995c81fSBram Moolenaar == FAIL)
8040e655111SBram Moolenaar goto fail;
8050995c81fSBram Moolenaar }
80684538079SBram Moolenaar
80784538079SBram Moolenaar // Check if window sizes can be restored (no windows omitted).
80884538079SBram Moolenaar // Remember the window number of the current window after restoring.
80984538079SBram Moolenaar nr = 0;
81084538079SBram Moolenaar for (wp = tab_firstwin; wp != NULL; wp = W_NEXT(wp))
81184538079SBram Moolenaar {
81284538079SBram Moolenaar if (ses_do_win(wp))
81384538079SBram Moolenaar ++nr;
81484538079SBram Moolenaar else
81584538079SBram Moolenaar restore_size = FALSE;
81684538079SBram Moolenaar if (curwin == wp)
81784538079SBram Moolenaar cnr = nr;
81884538079SBram Moolenaar }
81984538079SBram Moolenaar
8200995c81fSBram Moolenaar if (tab_firstwin->w_next != NULL)
8210995c81fSBram Moolenaar {
82284538079SBram Moolenaar // Go to the first window.
82384538079SBram Moolenaar if (put_line(fd, "wincmd t") == FAIL)
8240e655111SBram Moolenaar goto fail;
82584538079SBram Moolenaar
82684538079SBram Moolenaar // If more than one window, see if sizes can be restored.
8270995c81fSBram Moolenaar // First set 'winheight' and 'winwidth' to 1 to avoid the windows
8280995c81fSBram Moolenaar // being resized when moving between windows.
82984538079SBram Moolenaar // Do this before restoring the view, so that the topline and the
83084538079SBram Moolenaar // cursor can be set. This is done again below.
8310995c81fSBram Moolenaar // winminheight and winminwidth need to be set to avoid an error if
8320995c81fSBram Moolenaar // the user has set winheight or winwidth.
8330995c81fSBram Moolenaar if (put_line(fd, "let s:save_winminheight = &winminheight") == FAIL
8340995c81fSBram Moolenaar || put_line(fd, "let s:save_winminwidth = &winminwidth")
8350995c81fSBram Moolenaar == FAIL)
8360995c81fSBram Moolenaar goto fail;
83784538079SBram Moolenaar if (put_line(fd, "set winminheight=0") == FAIL
83884538079SBram Moolenaar || put_line(fd, "set winheight=1") == FAIL
83984538079SBram Moolenaar || put_line(fd, "set winminwidth=0") == FAIL
84084538079SBram Moolenaar || put_line(fd, "set winwidth=1") == FAIL)
8410e655111SBram Moolenaar goto fail;
8420995c81fSBram Moolenaar }
84384538079SBram Moolenaar if (nr > 1 && ses_winsizes(fd, restore_size, tab_firstwin) == FAIL)
8440e655111SBram Moolenaar goto fail;
84584538079SBram Moolenaar
84684538079SBram Moolenaar // Restore the tab-local working directory if specified
84784538079SBram Moolenaar // Do this before the windows, so that the window-local directory can
84884538079SBram Moolenaar // override the tab-local directory.
84984538079SBram Moolenaar if (tp != NULL && tp->tp_localdir != NULL && ssop_flags & SSOP_CURDIR)
85084538079SBram Moolenaar {
85184538079SBram Moolenaar if (fputs("tcd ", fd) < 0
85284538079SBram Moolenaar || ses_put_fname(fd, tp->tp_localdir, &ssop_flags) == FAIL
85384538079SBram Moolenaar || put_eol(fd) == FAIL)
8540e655111SBram Moolenaar goto fail;
85584538079SBram Moolenaar did_lcd = TRUE;
85684538079SBram Moolenaar }
85784538079SBram Moolenaar
85884538079SBram Moolenaar // Restore the view of the window (options, file, cursor, etc.).
85984538079SBram Moolenaar for (wp = tab_firstwin; wp != NULL; wp = wp->w_next)
86084538079SBram Moolenaar {
86184538079SBram Moolenaar if (!ses_do_win(wp))
86284538079SBram Moolenaar continue;
863c2c82056SBram Moolenaar if (put_view(fd, wp, wp != edited_win, &ssop_flags, cur_arg_idx,
8640e655111SBram Moolenaar #ifdef FEAT_TERMINAL
865c2c82056SBram Moolenaar &terminal_bufs
866c2c82056SBram Moolenaar #else
867c2c82056SBram Moolenaar NULL
8680e655111SBram Moolenaar #endif
8690e655111SBram Moolenaar ) == FAIL)
8700e655111SBram Moolenaar goto fail;
87184538079SBram Moolenaar if (nr > 1 && put_line(fd, "wincmd w") == FAIL)
8720e655111SBram Moolenaar goto fail;
87384538079SBram Moolenaar next_arg_idx = wp->w_arg_idx;
87484538079SBram Moolenaar }
87584538079SBram Moolenaar
87684538079SBram Moolenaar // The argument index in the first tab page is zero, need to set it in
87784538079SBram Moolenaar // each window. For further tab pages it's the window where we do
87884538079SBram Moolenaar // "tabedit".
87984538079SBram Moolenaar cur_arg_idx = next_arg_idx;
88084538079SBram Moolenaar
88184538079SBram Moolenaar // Restore cursor to the current window if it's not the first one.
88284538079SBram Moolenaar if (cnr > 1 && (fprintf(fd, "%dwincmd w", cnr) < 0
88384538079SBram Moolenaar || put_eol(fd) == FAIL))
8840e655111SBram Moolenaar goto fail;
88584538079SBram Moolenaar
88684538079SBram Moolenaar // Restore window sizes again after jumping around in windows, because
88784538079SBram Moolenaar // the current window has a minimum size while others may not.
88884538079SBram Moolenaar if (nr > 1 && ses_winsizes(fd, restore_size, tab_firstwin) == FAIL)
8890e655111SBram Moolenaar goto fail;
89084538079SBram Moolenaar
89184538079SBram Moolenaar // Don't continue in another tab page when doing only the current one
89284538079SBram Moolenaar // or when at the last tab page.
89384538079SBram Moolenaar if (!(ssop_flags & SSOP_TABPAGES))
89484538079SBram Moolenaar break;
89584538079SBram Moolenaar }
89684538079SBram Moolenaar
89784538079SBram Moolenaar if (ssop_flags & SSOP_TABPAGES)
89884538079SBram Moolenaar {
89984538079SBram Moolenaar if (fprintf(fd, "tabnext %d", tabpage_index(curtab)) < 0
90084538079SBram Moolenaar || put_eol(fd) == FAIL)
9010e655111SBram Moolenaar goto fail;
90284538079SBram Moolenaar }
90384538079SBram Moolenaar if (restore_stal && put_line(fd, "set stal=1") == FAIL)
9040e655111SBram Moolenaar goto fail;
90584538079SBram Moolenaar
90684538079SBram Moolenaar // Now put the remaining buffers into the buffer list.
90784538079SBram Moolenaar // This is near the end, so that when 'hidden' is set we don't create extra
90884538079SBram Moolenaar // buffers. If the buffer was already created with another command the
90984538079SBram Moolenaar // ":badd" will have no effect.
91084538079SBram Moolenaar FOR_ALL_BUFFERS(buf)
91184538079SBram Moolenaar {
91284538079SBram Moolenaar if (!(only_save_windows && buf->b_nwindows == 0)
91384538079SBram Moolenaar && !(buf->b_help && !(ssop_flags & SSOP_HELP))
91484538079SBram Moolenaar #ifdef FEAT_TERMINAL
91584538079SBram Moolenaar // Skip terminal buffers: finished ones are not useful, others
91684538079SBram Moolenaar // will be resurrected and result in a new buffer.
91784538079SBram Moolenaar && !bt_terminal(buf)
91884538079SBram Moolenaar #endif
91984538079SBram Moolenaar && buf->b_fname != NULL
92084538079SBram Moolenaar && buf->b_p_bl)
92184538079SBram Moolenaar {
92284538079SBram Moolenaar if (fprintf(fd, "badd +%ld ", buf->b_wininfo == NULL ? 1L
92384538079SBram Moolenaar : buf->b_wininfo->wi_fpos.lnum) < 0
92484538079SBram Moolenaar || ses_fname(fd, buf, &ssop_flags, TRUE) == FAIL)
9250e655111SBram Moolenaar goto fail;
92684538079SBram Moolenaar }
92784538079SBram Moolenaar }
92884538079SBram Moolenaar
92984538079SBram Moolenaar // Wipe out an empty unnamed buffer we started in.
93084538079SBram Moolenaar if (put_line(fd, "if exists('s:wipebuf') && len(win_findbuf(s:wipebuf)) == 0")
93184538079SBram Moolenaar == FAIL)
9320e655111SBram Moolenaar goto fail;
93384538079SBram Moolenaar if (put_line(fd, " silent exe 'bwipe ' . s:wipebuf") == FAIL)
9340e655111SBram Moolenaar goto fail;
93584538079SBram Moolenaar if (put_line(fd, "endif") == FAIL)
9360e655111SBram Moolenaar goto fail;
93784538079SBram Moolenaar if (put_line(fd, "unlet! s:wipebuf") == FAIL)
9380e655111SBram Moolenaar goto fail;
93984538079SBram Moolenaar
94084538079SBram Moolenaar // Re-apply 'winheight', 'winwidth' and 'shortmess'.
94184538079SBram Moolenaar if (fprintf(fd, "set winheight=%ld winwidth=%ld shortmess=%s",
94284538079SBram Moolenaar p_wh, p_wiw, p_shm) < 0 || put_eol(fd) == FAIL)
9430e655111SBram Moolenaar goto fail;
9440995c81fSBram Moolenaar if (tab_firstwin->w_next != NULL)
9450995c81fSBram Moolenaar {
9460995c81fSBram Moolenaar // Restore 'winminheight' and 'winminwidth'.
9470995c81fSBram Moolenaar if (put_line(fd, "let &winminheight = s:save_winminheight") == FAIL
9480995c81fSBram Moolenaar || put_line(fd, "let &winminwidth = s:save_winminwidth") == FAIL)
9490e655111SBram Moolenaar goto fail;
9500995c81fSBram Moolenaar }
95184538079SBram Moolenaar
95284538079SBram Moolenaar // Lastly, execute the x.vim file if it exists.
95384538079SBram Moolenaar if (put_line(fd, "let s:sx = expand(\"<sfile>:p:r\").\"x.vim\"") == FAIL
954c5f33db8SBram Moolenaar || put_line(fd, "if filereadable(s:sx)") == FAIL
95584538079SBram Moolenaar || put_line(fd, " exe \"source \" . fnameescape(s:sx)") == FAIL
95684538079SBram Moolenaar || put_line(fd, "endif") == FAIL)
9570e655111SBram Moolenaar goto fail;
95884538079SBram Moolenaar
9590e655111SBram Moolenaar ret = OK;
9600e655111SBram Moolenaar fail:
9610e655111SBram Moolenaar #ifdef FEAT_TERMINAL
9620e655111SBram Moolenaar hash_clear_all(&terminal_bufs, 0);
9630e655111SBram Moolenaar #endif
9640e655111SBram Moolenaar return ret;
96584538079SBram Moolenaar }
96684538079SBram Moolenaar
96784538079SBram Moolenaar /*
96884538079SBram Moolenaar * Get the name of the view file for the current buffer.
96984538079SBram Moolenaar */
97084538079SBram Moolenaar static char_u *
get_view_file(int c)97184538079SBram Moolenaar get_view_file(int c)
97284538079SBram Moolenaar {
97384538079SBram Moolenaar int len = 0;
97484538079SBram Moolenaar char_u *p, *s;
97584538079SBram Moolenaar char_u *retval;
97684538079SBram Moolenaar char_u *sname;
97784538079SBram Moolenaar
97884538079SBram Moolenaar if (curbuf->b_ffname == NULL)
97984538079SBram Moolenaar {
980e29a27f6SBram Moolenaar emsg(_(e_no_file_name));
98184538079SBram Moolenaar return NULL;
98284538079SBram Moolenaar }
98384538079SBram Moolenaar sname = home_replace_save(NULL, curbuf->b_ffname);
98484538079SBram Moolenaar if (sname == NULL)
98584538079SBram Moolenaar return NULL;
98684538079SBram Moolenaar
98784538079SBram Moolenaar // We want a file name without separators, because we're not going to make
98884538079SBram Moolenaar // a directory.
98984538079SBram Moolenaar // "normal" path separator -> "=+"
99084538079SBram Moolenaar // "=" -> "=="
99184538079SBram Moolenaar // ":" path separator -> "=-"
99284538079SBram Moolenaar for (p = sname; *p; ++p)
99384538079SBram Moolenaar if (*p == '=' || vim_ispathsep(*p))
99484538079SBram Moolenaar ++len;
99584538079SBram Moolenaar retval = alloc(STRLEN(sname) + len + STRLEN(p_vdir) + 9);
99684538079SBram Moolenaar if (retval != NULL)
99784538079SBram Moolenaar {
99884538079SBram Moolenaar STRCPY(retval, p_vdir);
99984538079SBram Moolenaar add_pathsep(retval);
100084538079SBram Moolenaar s = retval + STRLEN(retval);
100184538079SBram Moolenaar for (p = sname; *p; ++p)
100284538079SBram Moolenaar {
100384538079SBram Moolenaar if (*p == '=')
100484538079SBram Moolenaar {
100584538079SBram Moolenaar *s++ = '=';
100684538079SBram Moolenaar *s++ = '=';
100784538079SBram Moolenaar }
100884538079SBram Moolenaar else if (vim_ispathsep(*p))
100984538079SBram Moolenaar {
101084538079SBram Moolenaar *s++ = '=';
101184538079SBram Moolenaar #if defined(BACKSLASH_IN_FILENAME) || defined(AMIGA) || defined(VMS)
101284538079SBram Moolenaar if (*p == ':')
101384538079SBram Moolenaar *s++ = '-';
101484538079SBram Moolenaar else
101584538079SBram Moolenaar #endif
101684538079SBram Moolenaar *s++ = '+';
101784538079SBram Moolenaar }
101884538079SBram Moolenaar else
101984538079SBram Moolenaar *s++ = *p;
102084538079SBram Moolenaar }
102184538079SBram Moolenaar *s++ = '=';
102284538079SBram Moolenaar *s++ = c;
102384538079SBram Moolenaar STRCPY(s, ".vim");
102484538079SBram Moolenaar }
102584538079SBram Moolenaar
102684538079SBram Moolenaar vim_free(sname);
102784538079SBram Moolenaar return retval;
102884538079SBram Moolenaar }
102984538079SBram Moolenaar
103084538079SBram Moolenaar /*
103184538079SBram Moolenaar * ":loadview [nr]"
103284538079SBram Moolenaar */
103384538079SBram Moolenaar void
ex_loadview(exarg_T * eap)103484538079SBram Moolenaar ex_loadview(exarg_T *eap)
103584538079SBram Moolenaar {
103684538079SBram Moolenaar char_u *fname;
103784538079SBram Moolenaar
103884538079SBram Moolenaar fname = get_view_file(*eap->arg);
103984538079SBram Moolenaar if (fname != NULL)
104084538079SBram Moolenaar {
10418a7d6542SBram Moolenaar do_source(fname, FALSE, DOSO_NONE, NULL);
104284538079SBram Moolenaar vim_free(fname);
104384538079SBram Moolenaar }
104484538079SBram Moolenaar }
104584538079SBram Moolenaar
1046d17a57a4SBram Moolenaar # if defined(FEAT_GUI_GNOME) \
1047ac02a638SBram Moolenaar || (defined(GUI_MAY_SPAWN) && defined(EXPERIMENTAL_GUI_CMD)) \
1048ac02a638SBram Moolenaar || defined(PROTO)
104984538079SBram Moolenaar /*
105084538079SBram Moolenaar * Generate a script that can be used to restore the current editing session.
105184538079SBram Moolenaar * Save the value of v:this_session before running :mksession in order to make
105284538079SBram Moolenaar * automagic session save fully transparent. Return TRUE on success.
105384538079SBram Moolenaar */
105484538079SBram Moolenaar int
write_session_file(char_u * filename)105584538079SBram Moolenaar write_session_file(char_u *filename)
105684538079SBram Moolenaar {
105784538079SBram Moolenaar char_u *escaped_filename;
105884538079SBram Moolenaar char *mksession_cmdline;
105984538079SBram Moolenaar unsigned int save_ssop_flags;
106084538079SBram Moolenaar int failed;
106184538079SBram Moolenaar
106284538079SBram Moolenaar // Build an ex command line to create a script that restores the current
106384538079SBram Moolenaar // session if executed. Escape the filename to avoid nasty surprises.
106484538079SBram Moolenaar escaped_filename = vim_strsave_escaped(filename, escape_chars);
106584538079SBram Moolenaar if (escaped_filename == NULL)
106684538079SBram Moolenaar return FALSE;
106784538079SBram Moolenaar mksession_cmdline = alloc(10 + (int)STRLEN(escaped_filename) + 1);
106884538079SBram Moolenaar if (mksession_cmdline == NULL)
106984538079SBram Moolenaar {
107084538079SBram Moolenaar vim_free(escaped_filename);
107184538079SBram Moolenaar return FALSE;
107284538079SBram Moolenaar }
107384538079SBram Moolenaar strcpy(mksession_cmdline, "mksession ");
107484538079SBram Moolenaar STRCAT(mksession_cmdline, escaped_filename);
107584538079SBram Moolenaar vim_free(escaped_filename);
107684538079SBram Moolenaar
107784538079SBram Moolenaar // Use a reasonable hardcoded set of 'sessionoptions' flags to avoid
107884538079SBram Moolenaar // unpredictable effects when the session is saved automatically. Also,
107984538079SBram Moolenaar // we definitely need SSOP_GLOBALS to be able to restore v:this_session.
108084538079SBram Moolenaar // Don't use SSOP_BUFFERS to prevent the buffer list from becoming
108184538079SBram Moolenaar // enormously large if the GNOME session feature is used regularly.
108284538079SBram Moolenaar save_ssop_flags = ssop_flags;
108384538079SBram Moolenaar ssop_flags = (SSOP_BLANK|SSOP_CURDIR|SSOP_FOLDS|SSOP_GLOBALS
108484538079SBram Moolenaar |SSOP_HELP|SSOP_OPTIONS|SSOP_WINSIZE|SSOP_TABPAGES);
108584538079SBram Moolenaar
108684538079SBram Moolenaar do_cmdline_cmd((char_u *)"let Save_VV_this_session = v:this_session");
108784538079SBram Moolenaar failed = (do_cmdline_cmd((char_u *)mksession_cmdline) == FAIL);
108884538079SBram Moolenaar do_cmdline_cmd((char_u *)"let v:this_session = Save_VV_this_session");
108984538079SBram Moolenaar do_unlet((char_u *)"Save_VV_this_session", TRUE);
109084538079SBram Moolenaar
109184538079SBram Moolenaar ssop_flags = save_ssop_flags;
109284538079SBram Moolenaar vim_free(mksession_cmdline);
109384538079SBram Moolenaar
109484538079SBram Moolenaar // Reopen the file and append a command to restore v:this_session,
109584538079SBram Moolenaar // as if this save never happened. This is to avoid conflicts with
109684538079SBram Moolenaar // the user's own sessions. FIXME: It's probably less hackish to add
109784538079SBram Moolenaar // a "stealth" flag to 'sessionoptions' -- gotta ask Bram.
109884538079SBram Moolenaar if (!failed)
109984538079SBram Moolenaar {
110084538079SBram Moolenaar FILE *fd;
110184538079SBram Moolenaar
110284538079SBram Moolenaar fd = open_exfile(filename, TRUE, APPENDBIN);
110384538079SBram Moolenaar
110484538079SBram Moolenaar failed = (fd == NULL
110584538079SBram Moolenaar || put_line(fd, "let v:this_session = Save_VV_this_session")
110684538079SBram Moolenaar == FAIL
110784538079SBram Moolenaar || put_line(fd, "unlet Save_VV_this_session") == FAIL);
110884538079SBram Moolenaar
110984538079SBram Moolenaar if (fd != NULL && fclose(fd) != 0)
111084538079SBram Moolenaar failed = TRUE;
111184538079SBram Moolenaar
111284538079SBram Moolenaar if (failed)
111384538079SBram Moolenaar mch_remove(filename);
111484538079SBram Moolenaar }
111584538079SBram Moolenaar
111684538079SBram Moolenaar return !failed;
111784538079SBram Moolenaar }
111884538079SBram Moolenaar # endif
111984538079SBram Moolenaar
112084538079SBram Moolenaar #endif // FEAT_SESSION
112184538079SBram Moolenaar
112284538079SBram Moolenaar #if defined(FEAT_SESSION) && defined(USE_CRNL)
112384538079SBram Moolenaar # define MKSESSION_NL
112484538079SBram Moolenaar static int mksession_nl = FALSE; // use NL only in put_eol()
112584538079SBram Moolenaar #endif
112684538079SBram Moolenaar
112784538079SBram Moolenaar /*
112884538079SBram Moolenaar * ":mkexrc", ":mkvimrc", ":mkview" and ":mksession".
112984538079SBram Moolenaar */
113084538079SBram Moolenaar void
ex_mkrc(exarg_T * eap)113184538079SBram Moolenaar ex_mkrc(exarg_T *eap)
113284538079SBram Moolenaar {
113384538079SBram Moolenaar FILE *fd;
113484538079SBram Moolenaar int failed = FALSE;
113584538079SBram Moolenaar char_u *fname;
113684538079SBram Moolenaar #ifdef FEAT_BROWSE
113784538079SBram Moolenaar char_u *browseFile = NULL;
113884538079SBram Moolenaar #endif
113984538079SBram Moolenaar #ifdef FEAT_SESSION
114084538079SBram Moolenaar int view_session = FALSE;
114184538079SBram Moolenaar int using_vdir = FALSE; // using 'viewdir'?
114284538079SBram Moolenaar char_u *viewFile = NULL;
114384538079SBram Moolenaar unsigned *flagp;
114484538079SBram Moolenaar #endif
114584538079SBram Moolenaar
114684538079SBram Moolenaar if (eap->cmdidx == CMD_mksession || eap->cmdidx == CMD_mkview)
114784538079SBram Moolenaar {
114884538079SBram Moolenaar #ifdef FEAT_SESSION
114984538079SBram Moolenaar view_session = TRUE;
115084538079SBram Moolenaar #else
115184538079SBram Moolenaar ex_ni(eap);
115284538079SBram Moolenaar return;
115384538079SBram Moolenaar #endif
115484538079SBram Moolenaar }
115584538079SBram Moolenaar
115684538079SBram Moolenaar #ifdef FEAT_SESSION
115784538079SBram Moolenaar // Use the short file name until ":lcd" is used. We also don't use the
115884538079SBram Moolenaar // short file name when 'acd' is set, that is checked later.
115984538079SBram Moolenaar did_lcd = FALSE;
116084538079SBram Moolenaar
116184538079SBram Moolenaar // ":mkview" or ":mkview 9": generate file name with 'viewdir'
116284538079SBram Moolenaar if (eap->cmdidx == CMD_mkview
116384538079SBram Moolenaar && (*eap->arg == NUL
116484538079SBram Moolenaar || (vim_isdigit(*eap->arg) && eap->arg[1] == NUL)))
116584538079SBram Moolenaar {
116684538079SBram Moolenaar eap->forceit = TRUE;
116784538079SBram Moolenaar fname = get_view_file(*eap->arg);
116884538079SBram Moolenaar if (fname == NULL)
116984538079SBram Moolenaar return;
117084538079SBram Moolenaar viewFile = fname;
117184538079SBram Moolenaar using_vdir = TRUE;
117284538079SBram Moolenaar }
117384538079SBram Moolenaar else
117484538079SBram Moolenaar #endif
117584538079SBram Moolenaar if (*eap->arg != NUL)
117684538079SBram Moolenaar fname = eap->arg;
117784538079SBram Moolenaar else if (eap->cmdidx == CMD_mkvimrc)
117884538079SBram Moolenaar fname = (char_u *)VIMRC_FILE;
117984538079SBram Moolenaar #ifdef FEAT_SESSION
118084538079SBram Moolenaar else if (eap->cmdidx == CMD_mksession)
118184538079SBram Moolenaar fname = (char_u *)SESSION_FILE;
118284538079SBram Moolenaar #endif
118384538079SBram Moolenaar else
118484538079SBram Moolenaar fname = (char_u *)EXRC_FILE;
118584538079SBram Moolenaar
118684538079SBram Moolenaar #ifdef FEAT_BROWSE
1187e1004401SBram Moolenaar if (cmdmod.cmod_flags & CMOD_BROWSE)
118884538079SBram Moolenaar {
118984538079SBram Moolenaar browseFile = do_browse(BROWSE_SAVE,
119084538079SBram Moolenaar # ifdef FEAT_SESSION
119184538079SBram Moolenaar eap->cmdidx == CMD_mkview ? (char_u *)_("Save View") :
119284538079SBram Moolenaar eap->cmdidx == CMD_mksession ? (char_u *)_("Save Session") :
119384538079SBram Moolenaar # endif
119484538079SBram Moolenaar (char_u *)_("Save Setup"),
119584538079SBram Moolenaar fname, (char_u *)"vim", NULL,
119684538079SBram Moolenaar (char_u *)_(BROWSE_FILTER_MACROS), NULL);
119784538079SBram Moolenaar if (browseFile == NULL)
119884538079SBram Moolenaar goto theend;
119984538079SBram Moolenaar fname = browseFile;
120084538079SBram Moolenaar eap->forceit = TRUE; // since dialog already asked
120184538079SBram Moolenaar }
120284538079SBram Moolenaar #endif
120384538079SBram Moolenaar
120484538079SBram Moolenaar #if defined(FEAT_SESSION) && defined(vim_mkdir)
120584538079SBram Moolenaar // When using 'viewdir' may have to create the directory.
120684538079SBram Moolenaar if (using_vdir && !mch_isdir(p_vdir))
120784538079SBram Moolenaar vim_mkdir_emsg(p_vdir, 0755);
120884538079SBram Moolenaar #endif
120984538079SBram Moolenaar
121084538079SBram Moolenaar fd = open_exfile(fname, eap->forceit, WRITEBIN);
121184538079SBram Moolenaar if (fd != NULL)
121284538079SBram Moolenaar {
121384538079SBram Moolenaar #ifdef FEAT_SESSION
121484538079SBram Moolenaar if (eap->cmdidx == CMD_mkview)
121584538079SBram Moolenaar flagp = &vop_flags;
121684538079SBram Moolenaar else
121784538079SBram Moolenaar flagp = &ssop_flags;
121884538079SBram Moolenaar #endif
121984538079SBram Moolenaar
122084538079SBram Moolenaar #ifdef MKSESSION_NL
122184538079SBram Moolenaar // "unix" in 'sessionoptions': use NL line separator
122284538079SBram Moolenaar if (view_session && (*flagp & SSOP_UNIX))
122384538079SBram Moolenaar mksession_nl = TRUE;
122484538079SBram Moolenaar #endif
122584538079SBram Moolenaar
122684538079SBram Moolenaar // Write the version command for :mkvimrc
122784538079SBram Moolenaar if (eap->cmdidx == CMD_mkvimrc)
122884538079SBram Moolenaar (void)put_line(fd, "version 6.0");
122984538079SBram Moolenaar
123084538079SBram Moolenaar #ifdef FEAT_SESSION
123184538079SBram Moolenaar if (eap->cmdidx == CMD_mksession)
123284538079SBram Moolenaar {
123384538079SBram Moolenaar if (put_line(fd, "let SessionLoad = 1") == FAIL)
123484538079SBram Moolenaar failed = TRUE;
123584538079SBram Moolenaar }
123684538079SBram Moolenaar
123784538079SBram Moolenaar if (eap->cmdidx != CMD_mkview)
123884538079SBram Moolenaar #endif
123984538079SBram Moolenaar {
124084538079SBram Moolenaar // Write setting 'compatible' first, because it has side effects.
124184538079SBram Moolenaar // For that same reason only do it when needed.
124284538079SBram Moolenaar if (p_cp)
124384538079SBram Moolenaar (void)put_line(fd, "if !&cp | set cp | endif");
124484538079SBram Moolenaar else
124584538079SBram Moolenaar (void)put_line(fd, "if &cp | set nocp | endif");
124684538079SBram Moolenaar }
124784538079SBram Moolenaar
124884538079SBram Moolenaar #ifdef FEAT_SESSION
124984538079SBram Moolenaar if (!view_session
125084538079SBram Moolenaar || (eap->cmdidx == CMD_mksession
125184538079SBram Moolenaar && (*flagp & SSOP_OPTIONS)))
125284538079SBram Moolenaar #endif
1253635bd608SBram Moolenaar {
1254635bd608SBram Moolenaar int flags = OPT_GLOBAL;
1255635bd608SBram Moolenaar
1256635bd608SBram Moolenaar #ifdef FEAT_SESSION
1257635bd608SBram Moolenaar if (eap->cmdidx == CMD_mksession && (*flagp & SSOP_SKIP_RTP))
1258635bd608SBram Moolenaar flags |= OPT_SKIPRTP;
1259635bd608SBram Moolenaar #endif
126084538079SBram Moolenaar failed |= (makemap(fd, NULL) == FAIL
1261635bd608SBram Moolenaar || makeset(fd, flags, FALSE) == FAIL);
1262635bd608SBram Moolenaar }
126384538079SBram Moolenaar
126484538079SBram Moolenaar #ifdef FEAT_SESSION
126584538079SBram Moolenaar if (!failed && view_session)
126684538079SBram Moolenaar {
126738890835SBram Moolenaar if (put_line(fd, "let s:so_save = &g:so | let s:siso_save = &g:siso | setg so=0 siso=0 | setl so=-1 siso=-1") == FAIL)
126884538079SBram Moolenaar failed = TRUE;
126984538079SBram Moolenaar if (eap->cmdidx == CMD_mksession)
127084538079SBram Moolenaar {
127184538079SBram Moolenaar char_u *dirnow; // current directory
127284538079SBram Moolenaar
127384538079SBram Moolenaar dirnow = alloc(MAXPATHL);
127484538079SBram Moolenaar if (dirnow == NULL)
127584538079SBram Moolenaar failed = TRUE;
127684538079SBram Moolenaar else
127784538079SBram Moolenaar {
127884538079SBram Moolenaar // Change to session file's dir.
127984538079SBram Moolenaar if (mch_dirname(dirnow, MAXPATHL) == FAIL
128084538079SBram Moolenaar || mch_chdir((char *)dirnow) != 0)
128184538079SBram Moolenaar *dirnow = NUL;
128284538079SBram Moolenaar if (*dirnow != NUL && (ssop_flags & SSOP_SESDIR))
128384538079SBram Moolenaar {
128484538079SBram Moolenaar if (vim_chdirfile(fname, NULL) == OK)
128584538079SBram Moolenaar shorten_fnames(TRUE);
128684538079SBram Moolenaar }
128784538079SBram Moolenaar else if (*dirnow != NUL
128884538079SBram Moolenaar && (ssop_flags & SSOP_CURDIR) && globaldir != NULL)
128984538079SBram Moolenaar {
129084538079SBram Moolenaar if (mch_chdir((char *)globaldir) == 0)
129184538079SBram Moolenaar shorten_fnames(TRUE);
129284538079SBram Moolenaar }
129384538079SBram Moolenaar
129484538079SBram Moolenaar failed |= (makeopens(fd, dirnow) == FAIL);
129584538079SBram Moolenaar
129684538079SBram Moolenaar // restore original dir
129784538079SBram Moolenaar if (*dirnow != NUL && ((ssop_flags & SSOP_SESDIR)
129884538079SBram Moolenaar || ((ssop_flags & SSOP_CURDIR) && globaldir != NULL)))
129984538079SBram Moolenaar {
130084538079SBram Moolenaar if (mch_chdir((char *)dirnow) != 0)
130184538079SBram Moolenaar emsg(_(e_prev_dir));
130284538079SBram Moolenaar shorten_fnames(TRUE);
130384538079SBram Moolenaar }
130484538079SBram Moolenaar vim_free(dirnow);
130584538079SBram Moolenaar }
130684538079SBram Moolenaar }
130784538079SBram Moolenaar else
130884538079SBram Moolenaar {
1309c2c82056SBram Moolenaar failed |= (put_view(fd, curwin, !using_vdir, flagp, -1, NULL)
1310c2c82056SBram Moolenaar == FAIL);
131184538079SBram Moolenaar }
131238890835SBram Moolenaar if (put_line(fd, "let &g:so = s:so_save | let &g:siso = s:siso_save")
131384538079SBram Moolenaar == FAIL)
131484538079SBram Moolenaar failed = TRUE;
131584538079SBram Moolenaar #ifdef FEAT_SEARCH_EXTRA
131684538079SBram Moolenaar if (no_hlsearch && put_line(fd, "nohlsearch") == FAIL)
131784538079SBram Moolenaar failed = TRUE;
131884538079SBram Moolenaar #endif
131984538079SBram Moolenaar if (put_line(fd, "doautoall SessionLoadPost") == FAIL)
132084538079SBram Moolenaar failed = TRUE;
132184538079SBram Moolenaar if (eap->cmdidx == CMD_mksession)
132284538079SBram Moolenaar {
132384538079SBram Moolenaar if (put_line(fd, "unlet SessionLoad") == FAIL)
132484538079SBram Moolenaar failed = TRUE;
132584538079SBram Moolenaar }
132684538079SBram Moolenaar }
132784538079SBram Moolenaar #endif
132884538079SBram Moolenaar if (put_line(fd, "\" vim: set ft=vim :") == FAIL)
132984538079SBram Moolenaar failed = TRUE;
133084538079SBram Moolenaar
133184538079SBram Moolenaar failed |= fclose(fd);
133284538079SBram Moolenaar
133384538079SBram Moolenaar if (failed)
133484538079SBram Moolenaar emsg(_(e_write));
1335f96ae0b5SBram Moolenaar #if defined(FEAT_SESSION)
133684538079SBram Moolenaar else if (eap->cmdidx == CMD_mksession)
133784538079SBram Moolenaar {
133884538079SBram Moolenaar // successful session write - set this_session var
133984538079SBram Moolenaar char_u *tbuf;
134084538079SBram Moolenaar
134184538079SBram Moolenaar tbuf = alloc(MAXPATHL);
134284538079SBram Moolenaar if (tbuf != NULL)
134384538079SBram Moolenaar {
134484538079SBram Moolenaar if (vim_FullName(fname, tbuf, MAXPATHL, FALSE) == OK)
134584538079SBram Moolenaar set_vim_var_string(VV_THIS_SESSION, tbuf, -1);
134684538079SBram Moolenaar vim_free(tbuf);
134784538079SBram Moolenaar }
134884538079SBram Moolenaar }
134984538079SBram Moolenaar #endif
135084538079SBram Moolenaar #ifdef MKSESSION_NL
135184538079SBram Moolenaar mksession_nl = FALSE;
135284538079SBram Moolenaar #endif
135384538079SBram Moolenaar }
135484538079SBram Moolenaar
135584538079SBram Moolenaar #ifdef FEAT_BROWSE
135684538079SBram Moolenaar theend:
135784538079SBram Moolenaar vim_free(browseFile);
135884538079SBram Moolenaar #endif
135984538079SBram Moolenaar #ifdef FEAT_SESSION
136084538079SBram Moolenaar vim_free(viewFile);
136184538079SBram Moolenaar #endif
136284538079SBram Moolenaar }
136384538079SBram Moolenaar
1364f96ae0b5SBram Moolenaar #if (defined(FEAT_VIMINFO) || defined(FEAT_SESSION)) || defined(PROTO)
136584538079SBram Moolenaar var_flavour_T
var_flavour(char_u * varname)136684538079SBram Moolenaar var_flavour(char_u *varname)
136784538079SBram Moolenaar {
136884538079SBram Moolenaar char_u *p = varname;
136984538079SBram Moolenaar
137084538079SBram Moolenaar if (ASCII_ISUPPER(*p))
137184538079SBram Moolenaar {
137284538079SBram Moolenaar while (*(++p))
137384538079SBram Moolenaar if (ASCII_ISLOWER(*p))
137484538079SBram Moolenaar return VAR_FLAVOUR_SESSION;
137584538079SBram Moolenaar return VAR_FLAVOUR_VIMINFO;
137684538079SBram Moolenaar }
137784538079SBram Moolenaar else
137884538079SBram Moolenaar return VAR_FLAVOUR_DEFAULT;
137984538079SBram Moolenaar }
138084538079SBram Moolenaar #endif
138184538079SBram Moolenaar
138284538079SBram Moolenaar /*
138384538079SBram Moolenaar * Write end-of-line character(s) for ":mkexrc", ":mkvimrc" and ":mksession".
138484538079SBram Moolenaar * Return FAIL for a write error.
138584538079SBram Moolenaar */
138684538079SBram Moolenaar int
put_eol(FILE * fd)138784538079SBram Moolenaar put_eol(FILE *fd)
138884538079SBram Moolenaar {
138984538079SBram Moolenaar if (
139084538079SBram Moolenaar #ifdef USE_CRNL
139184538079SBram Moolenaar (
139284538079SBram Moolenaar # ifdef MKSESSION_NL
139384538079SBram Moolenaar !mksession_nl &&
139484538079SBram Moolenaar # endif
139584538079SBram Moolenaar (putc('\r', fd) < 0)) ||
139684538079SBram Moolenaar #endif
139784538079SBram Moolenaar (putc('\n', fd) < 0))
139884538079SBram Moolenaar return FAIL;
139984538079SBram Moolenaar return OK;
140084538079SBram Moolenaar }
140184538079SBram Moolenaar
140284538079SBram Moolenaar /*
140384538079SBram Moolenaar * Write a line to "fd".
140484538079SBram Moolenaar * Return FAIL for a write error.
140584538079SBram Moolenaar */
140684538079SBram Moolenaar int
put_line(FILE * fd,char * s)140784538079SBram Moolenaar put_line(FILE *fd, char *s)
140884538079SBram Moolenaar {
140984538079SBram Moolenaar if (fputs(s, fd) < 0 || put_eol(fd) == FAIL)
141084538079SBram Moolenaar return FAIL;
141184538079SBram Moolenaar return OK;
141284538079SBram Moolenaar }
1413