Example #1
0
int
is_valid_mark(const int index)
{
	const char m = index2mark(index);
	const mark_t *const mark = get_mark_by_name(m);
	return is_mark_valid(mark);
}
Example #2
0
File: info.c Project: cfillion/vifm
/* Writes marks to vifminfo file.  marks is a list of length nmarks marks read
 * from vifminfo. */
static void
write_marks(FILE *const fp, const char non_conflicting_marks[],
		char *marks[], const int timestamps[], int nmarks)
{
	int active_marks[NUM_MARKS];
	const int len = init_active_marks(valid_marks, active_marks);
	int i;

	fputs("\n# Marks:\n", fp);
	for(i = 0; i < len; ++i)
	{
		const int index = active_marks[i];
		const char m = index2mark(index);
		if(!is_spec_mark(index) && char_is_one_of(non_conflicting_marks, m))
		{
			const mark_t *const mark = get_mark(index);

			fprintf(fp, "%c%c\n", LINE_TYPE_MARK, m);
			fprintf(fp, "\t%s\n", mark->directory);
			fprintf(fp, "\t%s\n", mark->file);
			fprintf(fp, "%lld\n", (long long)mark->timestamp);
		}
	}
	for(i = 0; i < nmarks; i += 3)
	{
		fprintf(fp, "%c%c\n", LINE_TYPE_MARK, marks[i][0]);
		fprintf(fp, "\t%s\n", marks[i + 1]);
		fprintf(fp, "\t%s\n", marks[i + 2]);
		fprintf(fp, "%d\n", timestamps[i/3]);
	}
}
Example #3
0
int
is_valid_bookmark(const int bmark_index)
{
	const char mark = index2mark(bmark_index);
	const bookmark_t *const bmark = get_bookmark(mark);
	return is_bmark_valid(bmark);
}
Example #4
0
int
init_active_bookmarks(const char marks[], int active_bookmarks[])
{
	int i, x;

	i = 0;
	for(x = 0; x < NUM_BOOKMARKS; ++x)
	{
		if(!char_is_one_of(marks, index2mark(x)))
			continue;
		if(is_bmark_empty(&bookmarks[x]))
			continue;
		active_bookmarks[i++] = x;
	}
	return i;
}
Example #5
0
int
init_active_marks(const char marks[], int active_marks[])
{
	int i, x;

	i = 0;
	for(x = 0; x < NUM_MARKS; ++x)
	{
		if(!char_is_one_of(marks, index2mark(x)))
			continue;
		if(is_empty(get_mark(x)))
			continue;
		active_marks[i++] = x;
	}
	return i;
}
Example #6
0
int
is_spec_bookmark(const int x)
{
	const char mark = index2mark(x);
	return char_is_one_of(spec_bookmarks, mark);
}
Example #7
0
int
is_spec_mark(const int x)
{
	return char_is_one_of(spec_marks, index2mark(x));
}
Example #8
0
void
write_config_file(void)
{
	FILE *fp;
	int x = 0;
	char config_file[PATH_MAX];
	struct stat stat_buf;


	/* None of the user settings have changed. */
	if ((!curr_stats.setting_change) && (!cfg.using_default_config))
		return;

	curr_stats.getting_input = 1;

	snprintf(config_file, sizeof(config_file), "%s/vifmrc", cfg.config_dir);

	if(stat(config_file, &stat_buf) == 0) 
	{
		if ((stat_buf.st_mtime > curr_stats.config_file_mtime) &&
				(!cfg.using_default_config))
		{
			if (! query_user_menu(" Vifmrc file has been modified ",
				 "File has been modified would you still like to write to file? "))
				return;
		}
	}

	if((fp = fopen(config_file, "w")) == NULL)
		return;

	fprintf(fp, "# You can edit this file by hand.\n");
	fprintf(fp, "# The # character at the beginning of a line comments out the line.\n");
	fprintf(fp, "# Blank lines are ignored.\n");
	fprintf(fp, "# The basic format for each item is shown with an example.\n");
	fprintf(fp,
		"# The '=' character is used to separate fields within a single line.\n");
	fprintf(fp, "# Most settings are true = 1 or false = 0.\n");
	
	fprintf(fp, "\n# This is the actual command used to start vi.  The default is vi.\n");
	fprintf(fp,
			"# If you would like to use another vi clone such as Vim, Elvis, or Vile\n");
	fprintf(fp, "# you will need to change this setting.\n");
	fprintf(fp, "\nVI_COMMAND=%s", cfg.vi_command);
	fprintf(fp, "\n# VI_COMMAND=vim");
	fprintf(fp, "\n# VI_COMMAND=elvis -G termcap");
	fprintf(fp, "\n# VI_COMMAND=vile");
	fprintf(fp, "\n");
	fprintf(fp, "\n# Trash Directory\n");
	fprintf(fp, "# The default is to move files that are deleted with dd or :d to\n");
	fprintf(fp, "# the trash directory.  1 means use the trash directory 0 means\n");
	fprintf(fp, "# just use rm.  If you change this you will not be able to move\n");
	fprintf(fp, "# files by deleting them and then using p to put the file in the new location.\n");
	fprintf(fp, "# I recommend not changing this until you are familiar with vifm.\n");
	fprintf(fp, "# This probably shouldn't be an option.\n");
	fprintf(fp, "\nUSE_TRASH=%d\n", cfg.use_trash);

	fprintf(fp, "\n# Show only one Window\n");
	fprintf(fp, "# If you would like to start vifm with only one window set this to 1\n");
	fprintf(fp, "\nUSE_ONE_WINDOW=%d\n", curr_stats.number_of_windows == 1 ? 1 : 0);

	fprintf(fp, "\n# Screen configuration.  If you would like to use vifm with\n"); 
	fprintf(fp, "# the screen program set this to 1.\n");
	fprintf(fp, "\nUSE_SCREEN=%d\n", cfg.use_screen);

	fprintf(fp, "\n# 1 means use color if the terminal supports it.\n");
	fprintf(fp, "# 0 means don't use color even if supported.\n");

	fprintf(fp, "\n# This is how many files to show in the directory history menu.\n");
	fprintf(fp, "\nHISTORY_LENGTH=%d\n", cfg.history_len);

	fprintf(fp, "\n# The sort type is how the files will be sorted in the file listing.\n");
	fprintf(fp, "# Sort by File Extension = 0\n");
	fprintf(fp, "# Sort by File Name = 1\n");
	fprintf(fp, "# Sort by Group ID = 2\n");
	fprintf(fp, "# Sort by Group Name = 3\n");
	fprintf(fp, "# Sort by Mode = 4\n");
	fprintf(fp, "# Sort by Owner ID = 5\n");
	fprintf(fp, "# Sort by Owner Name = 6\n");
	fprintf(fp, "# Sort by Size (Ascending) = 7\n");
	fprintf(fp, "# Sort by Size (Descending) = 8\n");

	fprintf(fp, "# Sort by Time Accessed =9\n");
	fprintf(fp, "# Sort by Time Changed =10\n");
	fprintf(fp, "# Sort by Time Modified =11\n");
	fprintf(fp, "# This can be set with the :sort command in vifm.\n");
	fprintf(fp, "\nLEFT_WINDOW_SORT_TYPE=%d\n", lwin.sort_type);
	fprintf(fp, "\nRIGHT_WINDOW_SORT_TYPE=%d\n", rwin.sort_type);

	fprintf(fp, "\n# The regular expression used to filter files out of\n");
	fprintf(fp, "# the directory listings.\n");
	fprintf(fp, "# LWIN_FILTER=\\.o$ and LWIN_INVERT=1 would filter out all\n");
	fprintf(fp, "# of the .o files from the directory listing. LWIN_INVERT=0\n");
	fprintf(fp, "# would show only the .o files\n");
	fprintf(fp, "\nLWIN_FILTER=%s\n", lwin.filename_filter);
	fprintf(fp, "LWIN_INVERT=%d\n", lwin.invert);
	fprintf(fp, "RWIN_FILTER=%s\n", rwin.filename_filter);
	fprintf(fp, "RWIN_INVERT=%d\n", rwin.invert);

	fprintf(fp, "\n# If you installed the vim.txt help file change this to 1.\n");
	fprintf(fp, "# If would rather use a plain text help file set this to 0.\n");
	fprintf(fp, "\nUSE_VIM_HELP=%d\n", cfg.use_vim_help);

	fprintf(fp, "\n# If you would like to run an executable file when you \n");
	fprintf(fp, "# press return on the file name set this to 1.\n");
	fprintf(fp, "\nRUN_EXECUTABLE=%d\n", cfg.auto_execute);

	fprintf(fp, "\n# BOOKMARKS=mark=/full/directory/path=filename\n\n");
	for(x = 0; x < NUM_BOOKMARKS; x++)
	{
		if (is_bookmark(x))
		{
			fprintf(fp, "BOOKMARKS=%c=%s=%s\n",
					index2mark(x),
					bookmarks[x].directory, bookmarks[x].file);
		}
	}

	fprintf(fp, "\n# COMMAND=command_name=action\n");
	fprintf(fp, "# The following macros can be used in a command\n");
	fprintf(fp, "# %%a is replaced with the user arguments.\n");
	fprintf(fp, "# %%f the current selected file, or files.\n");
	fprintf(fp, "# %%F the current selected file, or files in the other directoy.\n");
	fprintf(fp, "# %%d the current directory name.\n");
	fprintf(fp, "# %%D the other window directory name.\n");
	fprintf(fp, "# %%m run the command in a menu window\n\n");
	for(x = 0; x < cfg.command_num; x++)
	{
		fprintf(fp, "COMMAND=%s=%s\n", command_list[x].name, 
				command_list[x].action);
	}

	fprintf(fp, "\n# The file type is for the default programs to be used with\n");
	fprintf(fp, "# a file extension. \n");
	fprintf(fp, "# FILETYPE=description=extension1,extension2=defaultprogram, program2\n");
	fprintf(fp, "# FILETYPE=Web=html,htm,shtml=links,mozilla,elvis\n");
	fprintf(fp, "# would set links as the default program for .html .htm .shtml files\n");
	fprintf(fp, "# The other programs for the file type can be accessed with the :file command\n");
	fprintf(fp, "# The command macros %%f, %%F, %%d, %%F may be used in the commands.\n");
	fprintf(fp, "# The %%a macro is ignored.  To use a %% you must put %%%%.\n\n");
	for(x = 0; x < cfg.filetypes_num; x++)
	{
		fprintf(fp, "FILETYPE=%s=%s=%s\n", filetypes[x].type, filetypes[x].ext, filetypes[x].programs);
	}

/*_SZ_BEGIN_*/
	fprintf(fp, "\n# For automated FUSE mounts, you must register an extension with FILETYPE=..\n"); 
	fprintf(fp, "# in the following format:\n");
	fprintf(fp, "# FILETYPE=description=extensions=FUSE_MOUNT|some_mount_command using %%SOURCE_FILE and %%DESTINATION_DIR variables\n");
	fprintf(fp, "# %%SOURCE_FILE and %%DESTINATION_DIR are filled in by vifm at runtime.\n");
	fprintf(fp, "# A sample line might look like this:\n");
	fprintf(fp, "# FILETYPE=FuseZipMount=zip,jar,war,ear=FUSE_MOUNT|fuse-zip %%SOURCE_FILE %%DESTINATION_DIR\n\n");
	fprintf(fp, "# The FUSE_HOME directory will be used as a root dir for all FUSE mounts.\n");
	fprintf(fp, "# Unless it exists with write/exec permissions set, vifm will attempt to create it.\n");
	fprintf(fp, "\nFUSE_HOME=%s\n", cfg.fuse_home);
/*_SZ_END_*/

	fclose(fp);

	curr_stats.getting_input = 0;
}
Example #9
0
/* Reads contents of the filename file as an info file and updates it with the
 * state of current instance. */
static void
update_info_file(const char filename[])
{
	/* TODO: refactor this function update_info_file() */

	FILE *fp;
	char ** list;
	int nlist = -1;
	char **ft = NULL, **fx = NULL , **fv = NULL, **cmds = NULL, **marks = NULL;
	char **lh = NULL, **rh = NULL, **cmdh = NULL, **srch = NULL, **regs = NULL;
	int *lhp = NULL, *rhp = NULL;
	size_t nlhp = 0, nrhp = 0;
	char **prompt = NULL, **trash = NULL;
	int nft = 0, nfx = 0, nfv = 0, ncmds = 0, nmarks = 0, nlh = 0, nrh = 0;
	int ncmdh = 0, nsrch = 0, nregs = 0, nprompt = 0, ntrash = 0;
	int i;

	if(cfg.vifm_info == 0)
		return;

	list = list_udf();
	while(list[++nlist] != NULL);

	if((fp = fopen(filename, "r")) != NULL)
	{
		char *line = NULL, *line2 = NULL, *line3 = NULL;
		while((line = read_vifminfo_line(fp, line)) != NULL)
		{
			const char type = line[0];
			const char *const line_val = line + 1;

			if(type == LINE_TYPE_COMMENT || type == '\0')
				continue;

			if(type == LINE_TYPE_FILETYPE)
			{
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					assoc_record_t prog;
					if(get_default_program_for_file(line_val, &prog))
					{
						free_assoc_record(&prog);
						continue;
					}
					nft = add_to_string_array(&ft, nft, 2, line_val, line2);
				}
			}
			else if(type == LINE_TYPE_XFILETYPE)
			{
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					assoc_record_t x_prog;
					if(get_default_program_for_file(line_val, &x_prog))
					{
						assoc_record_t console_prog;
						if(get_default_program_for_file(line_val, &console_prog))
						{
							if(strcmp(x_prog.command, console_prog.command) == 0)
							{
								free_assoc_record(&console_prog);
								free_assoc_record(&x_prog);
								continue;
							}
						}
						free_assoc_record(&x_prog);
					}
					nfx = add_to_string_array(&fx, nfx, 2, line_val, line2);
				}
			}
			else if(type == LINE_TYPE_FILEVIEWER)
			{
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					if(get_viewer_for_file(line_val) != NULL)
						continue;
					nfv = add_to_string_array(&fv, nfv, 2, line_val, line2);
				}
			}
			else if(type == LINE_TYPE_COMMAND)
			{
				if(line_val[0] == '\0')
					continue;
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					const char *p = line_val;
					for(i = 0; i < nlist; i += 2)
					{
						int cmp = strcmp(list[i], p);
						if(cmp < 0)
							continue;
						if(cmp == 0)
							p = NULL;
						break;
					}
					if(p == NULL)
						continue;
					ncmds = add_to_string_array(&cmds, ncmds, 2, line_val, line2);
				}
			}
			else if(type == LINE_TYPE_LWIN_HIST)
			{
				if(line_val[0] == '\0')
					continue;
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					int pos;

					if(lwin.history_pos + nlh/2 == cfg.history_len - 1)
						continue;
					if(is_in_view_history(&lwin, line_val))
						continue;

					pos = read_possible_possible_pos(fp);
					nlh = add_to_string_array(&lh, nlh, 2, line_val, line2);
					if(nlh/2 > nlhp)
					{
						nlhp = add_to_int_array(&lhp, nlhp, pos);
						nlhp = MIN(nlh/2, nlhp);
					}
				}
			}
			else if(type == LINE_TYPE_RWIN_HIST)
			{
				if(line_val[0] == '\0')
					continue;
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					int pos;

					if(rwin.history_pos + nrh/2 == cfg.history_len - 1)
						continue;
					if(is_in_view_history(&rwin, line_val))
						continue;

					pos = read_possible_possible_pos(fp);
					nrh = add_to_string_array(&rh, nrh, 2, line_val, line2);
					if(nrh/2 > nrhp)
					{
						nrhp = add_to_int_array(&rhp, nrhp, pos);
						nrhp = MIN(nrh/2, nrhp);
					}
				}
			}
			else if(type == LINE_TYPE_BOOKMARK)
			{
				const char mark = line_val[0];
				if(line_val[1] != '\0')
				{
					LOG_ERROR_MSG("Expected end of line, but got: %s", line_val + 1);
				}
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					if((line3 = read_vifminfo_line(fp, line3)) != NULL)
					{
						const char mark_str[] = { mark, '\0' };
						if(!char_is_one_of(valid_bookmarks, mark))
							continue;
						if(!is_bookmark_empty(mark2index(mark)))
							continue;
						nmarks = add_to_string_array(&marks, nmarks, 3, mark_str, line2,
								line3);
					}
				}
			}
			else if(type == LINE_TYPE_TRASH)
			{
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					if(!path_exists_at(cfg.trash_dir, line_val))
						continue;
					if(is_in_trash(line_val))
						continue;
					ntrash = add_to_string_array(&trash, ntrash, 2, line_val, line2);
				}
			}
			else if(type == LINE_TYPE_CMDLINE_HIST)
			{
				if(cfg.cmd_history_num >= 0 && is_in_string_array(cfg.cmd_history,
						cfg.cmd_history_num + 1, line_val))
					continue;
				ncmdh = add_to_string_array(&cmdh, ncmdh, 1, line_val);
			}
			else if(type == LINE_TYPE_SEARCH_HIST)
			{
				if(cfg.search_history_num >= 0 && is_in_string_array(cfg.search_history,
						cfg.search_history_num + 1, line_val))
					continue;
				nsrch = add_to_string_array(&srch, nsrch, 1, line_val);
			}
			else if(type == LINE_TYPE_PROMPT_HIST)
			{
				if(cfg.prompt_history_num >= 0 && is_in_string_array(cfg.prompt_history,
						cfg.prompt_history_num + 1, line_val))
					continue;
				nprompt = add_to_string_array(&prompt, nprompt, 1, line_val);
			}
			else if(type == LINE_TYPE_REG)
			{
				if(register_exists(line_val[0]))
					continue;
				nregs = add_to_string_array(&regs, nregs, 1, line);
			}
		}
		free(line);
		free(line2);
		free(line3);
		fclose(fp);
	}

	if((fp = fopen(filename, "w")) == NULL)
	{
		return;
	}

	fprintf(fp, "# You can edit this file by hand, but it's recommended not to do that.\n");

	if(cfg.vifm_info & VIFMINFO_OPTIONS)
	{
		fputs("\n# Options:\n", fp);
		fprintf(fp, "=aproposprg=%s\n", escape_spaces(cfg.apropos_prg));
		fprintf(fp, "=%sautochpos\n", cfg.auto_ch_pos ? "" : "no");
		fprintf(fp, "=columns=%d\n", cfg.columns);
		fprintf(fp, "=%sconfirm\n", cfg.confirm ? "" : "no");
		fprintf(fp, "=cpoptions=%s%s%s\n",
				cfg.filter_inverted_by_default ? "f" : "",
				cfg.selection_is_primary ? "s" : "",
				cfg.tab_switches_pane ? "t" : "");
		fprintf(fp, "=%sfastrun\n", cfg.fast_run ? "" : "no");
		fprintf(fp, "=findprg=%s\n", escape_spaces(cfg.find_prg));
		fprintf(fp, "=%sfollowlinks\n", cfg.follow_links ? "" : "no");
		fprintf(fp, "=fusehome=%s\n", escape_spaces(cfg.fuse_home));
		fprintf(fp, "=%sgdefault\n", cfg.gdefault ? "" : "no");
		fprintf(fp, "=grepprg=%s\n", escape_spaces(cfg.grep_prg));
		fprintf(fp, "=history=%d\n", cfg.history_len);
		fprintf(fp, "=%shlsearch\n", cfg.hl_search ? "" : "no");
		fprintf(fp, "=%siec\n", cfg.use_iec_prefixes ? "" : "no");
		fprintf(fp, "=%signorecase\n", cfg.ignore_case ? "" : "no");
		fprintf(fp, "=%sincsearch\n", cfg.inc_search ? "" : "no");
		fprintf(fp, "=%slaststatus\n", cfg.last_status ? "" : "no");
		fprintf(fp, "=lines=%d\n", cfg.lines);
		fprintf(fp, "=locateprg=%s\n", escape_spaces(cfg.locate_prg));
		fprintf(fp, "=rulerformat=%s\n", escape_spaces(cfg.ruler_format));
		fprintf(fp, "=%srunexec\n", cfg.auto_execute ? "" : "no");
		fprintf(fp, "=%sscrollbind\n", cfg.scroll_bind ? "" : "no");
		fprintf(fp, "=scrolloff=%d\n", cfg.scroll_off);
		fprintf(fp, "=shell=%s\n", escape_spaces(cfg.shell));
		fprintf(fp, "=shortmess=%s\n", cfg.trunc_normal_sb_msgs ? "T" : "");
#ifndef _WIN32
		fprintf(fp, "=slowfs=%s\n", escape_spaces(cfg.slow_fs_list));
#endif
		fprintf(fp, "=%ssmartcase\n", cfg.smart_case ? "" : "no");
		fprintf(fp, "=%ssortnumbers\n", cfg.sort_numbers ? "" : "no");
		fprintf(fp, "=statusline=%s\n", escape_spaces(cfg.status_line));
		fprintf(fp, "=tabstop=%d\n", cfg.tab_stop);
		fprintf(fp, "=timefmt=%s\n", escape_spaces(cfg.time_format + 1));
		fprintf(fp, "=timeoutlen=%d\n", cfg.timeout_len);
		fprintf(fp, "=%strash\n", cfg.use_trash ? "" : "no");
		fprintf(fp, "=undolevels=%d\n", cfg.undo_levels);
		fprintf(fp, "=vicmd=%s%s\n", escape_spaces(cfg.vi_command),
				cfg.vi_cmd_bg ? " &" : "");
		fprintf(fp, "=vixcmd=%s%s\n", escape_spaces(cfg.vi_x_command),
				cfg.vi_cmd_bg ? " &" : "");
		fprintf(fp, "=%swrapscan\n", cfg.wrap_scan ? "" : "no");
		fprintf(fp, "=[viewcolumns=%s\n", escape_spaces(lwin.view_columns));
		fprintf(fp, "=]viewcolumns=%s\n", escape_spaces(rwin.view_columns));
		fprintf(fp, "=[%slsview\n", lwin.ls_view ? "" : "no");
		fprintf(fp, "=]%slsview\n", rwin.ls_view ? "" : "no");

		fprintf(fp, "%s", "=dotdirs=");
		if(cfg.dot_dirs & DD_ROOT_PARENT)
			fprintf(fp, "%s", "rootparent,");
		if(cfg.dot_dirs & DD_NONROOT_PARENT)
			fprintf(fp, "%s", "nonrootparent,");
		fprintf(fp, "\n");

		fprintf(fp, "=classify=%s\n", escape_spaces(classify_to_str()));

		fprintf(fp, "=vifminfo=options");
		if(cfg.vifm_info & VIFMINFO_FILETYPES)
			fprintf(fp, ",filetypes");
		if(cfg.vifm_info & VIFMINFO_COMMANDS)
			fprintf(fp, ",commands");
		if(cfg.vifm_info & VIFMINFO_BOOKMARKS)
			fprintf(fp, ",bookmarks");
		if(cfg.vifm_info & VIFMINFO_TUI)
			fprintf(fp, ",tui");
		if(cfg.vifm_info & VIFMINFO_DHISTORY)
			fprintf(fp, ",dhistory");
		if(cfg.vifm_info & VIFMINFO_STATE)
			fprintf(fp, ",state");
		if(cfg.vifm_info & VIFMINFO_CS)
			fprintf(fp, ",cs");
		if(cfg.vifm_info & VIFMINFO_SAVEDIRS)
			fprintf(fp, ",savedirs");
		if(cfg.vifm_info & VIFMINFO_CHISTORY)
			fprintf(fp, ",chistory");
		if(cfg.vifm_info & VIFMINFO_SHISTORY)
			fprintf(fp, ",shistory");
		if(cfg.vifm_info & VIFMINFO_PHISTORY)
			fprintf(fp, ",phistory");
		if(cfg.vifm_info & VIFMINFO_DIRSTACK)
			fprintf(fp, ",dirstack");
		if(cfg.vifm_info & VIFMINFO_REGISTERS)
			fprintf(fp, ",registers");
		fprintf(fp, "\n");

		fprintf(fp, "=%svimhelp\n", cfg.use_vim_help ? "" : "no");
		fprintf(fp, "=%swildmenu\n", cfg.wild_menu ? "" : "no");
		fprintf(fp, "=%swrap\n", cfg.wrap_quick_view ? "" : "no");
	}

	if(cfg.vifm_info & VIFMINFO_FILETYPES)
	{
		fputs("\n# Filetypes:\n", fp);
		for(i = 0; i < filetypes.count; i++)
		{
			int j;
			assoc_t ft_assoc = filetypes.list[i];
			for(j = 0; j < ft_assoc.records.count; j++)
			{
				assoc_record_t ft_record = ft_assoc.records.list[j];
				/* The type check is to prevent builtin fake associations to be written
				 * into vifminfo file */
				if(ft_record.command[0] != '\0' && ft_record.type != ART_BUILTIN)
				{
					fprintf(fp, ".%s\n\t{%s}%s\n", ft_assoc.pattern,
							ft_record.description, ft_record.command);
				}
			}
		}
		for(i = 0; i < nft; i += 2)
			fprintf(fp, ".%s\n\t%s\n", ft[i], ft[i + 1]);

		fputs("\n# X Filetypes:\n", fp);
		for(i = 0; i < xfiletypes.count; i++)
		{
			int j;
			assoc_t xft_assoc = xfiletypes.list[i];
			for(j = 0; j < xft_assoc.records.count; j++)
			{
				assoc_record_t xft_record = xft_assoc.records.list[j];
				if(xft_record.command[0] != '\0')
				{
					fprintf(fp, "x%s\n\t{%s}%s\n", xft_assoc.pattern,
							xft_record.description, xft_record.command);
				}
			}
		}
		for(i = 0; i < nfx; i += 2)
			fprintf(fp, ".%s\n\t%s\n", fx[i], fx[i + 1]);

		fputs("\n# Fileviewers:\n", fp);
		for(i = 0; i < fileviewers.count; i++)
		{
			int j;
			assoc_t fv_assoc = fileviewers.list[i];
			for(j = 0; j < fv_assoc.records.count; j++)
			{
				assoc_record_t fv_record = fileviewers.list[i].records.list[j];
				if(fv_record.command[0] != '\0')
				{
					fprintf(fp, ",%s\n\t%s\n", fv_assoc.pattern, fv_record.command);
				}
			}
		}
		for(i = 0; i < nfv; i += 2)
			fprintf(fp, ",%s\n\t%s\n", fv[i], fv[i + 1]);
	}

	if(cfg.vifm_info & VIFMINFO_COMMANDS)
	{
		fputs("\n# Commands:\n", fp);
		for(i = 0; list[i] != NULL; i += 2)
			fprintf(fp, "!%s\n\t%s\n", list[i], list[i + 1]);
		for(i = 0; i < ncmds; i += 2)
			fprintf(fp, "!%s\n\t%s\n", cmds[i], cmds[i + 1]);
	}

	if(cfg.vifm_info & VIFMINFO_BOOKMARKS)
	{
		int len = init_active_bookmarks(valid_bookmarks);

		fputs("\n# Bookmarks:\n", fp);
		for(i = 0; i < len; i++)
		{
			int j = active_bookmarks[i];
			if(is_spec_bookmark(j))
				continue;
			fprintf(fp, "'%c\n\t%s\n\t", index2mark(j), bookmarks[j].directory);
			fprintf(fp, "%s\n", bookmarks[j].file);
		}
		for(i = 0; i < nmarks; i += 3)
			fprintf(fp, "'%c\n\t%s\n\t%s\n", marks[i][0], marks[i + 1], marks[i + 2]);
	}

	if(cfg.vifm_info & VIFMINFO_TUI)
	{
		fputs("\n# TUI:\n", fp);
		fprintf(fp, "a%c\n", (curr_view == &rwin) ? 'r' : 'l');
		fprintf(fp, "q%d\n", curr_stats.view);
		fprintf(fp, "v%d\n", curr_stats.number_of_windows);
		fprintf(fp, "o%c\n", (curr_stats.split == VSPLIT) ? 'v' : 'h');
		fprintf(fp, "m%d\n", curr_stats.splitter_pos);

		put_sort_info(fp, 'l', &lwin);
		put_sort_info(fp, 'r', &rwin);
	}

	if((cfg.vifm_info & VIFMINFO_DHISTORY) && cfg.history_len > 0)
	{
		save_view_history(&lwin, NULL, NULL, -1);
		fputs("\n# Left window history (oldest to newest):\n", fp);
		for(i = 0; i < nlh; i += 2)
			fprintf(fp, "d%s\n\t%s\n%d\n", lh[i], lh[i + 1], lhp[i/2]);
		for(i = 0; i <= lwin.history_pos; i++)
			fprintf(fp, "d%s\n\t%s\n%d\n", lwin.history[i].dir, lwin.history[i].file,
					lwin.history[i].rel_pos);
		if(cfg.vifm_info & VIFMINFO_SAVEDIRS)
			fprintf(fp, "d\n");

		save_view_history(&rwin, NULL, NULL, -1);
		fputs("\n# Right window history (oldest to newest):\n", fp);
		for(i = 0; i < nrh; i += 2)
			fprintf(fp, "D%s\n\t%s\n%d\n", rh[i], rh[i + 1], rhp[i/2]);
		for(i = 0; i <= rwin.history_pos; i++)
			fprintf(fp, "D%s\n\t%s\n%d\n", rwin.history[i].dir, rwin.history[i].file,
					rwin.history[i].rel_pos);
		if(cfg.vifm_info & VIFMINFO_SAVEDIRS)
			fprintf(fp, "D\n");
	}

	if(cfg.vifm_info & VIFMINFO_CHISTORY)
	{
		fputs("\n# Command line history (oldest to newest):\n", fp);
		for(i = 0; i < MIN(ncmdh, cfg.history_len - cfg.cmd_history_num); i++)
			fprintf(fp, ":%s\n", cmdh[i]);
		for(i = cfg.cmd_history_num; i >= 0; i--)
			fprintf(fp, ":%s\n", cfg.cmd_history[i]);
	}

	if(cfg.vifm_info & VIFMINFO_SHISTORY)
	{
		fputs("\n# Search history (oldest to newest):\n", fp);
		for(i = 0; i < nsrch; i++)
			fprintf(fp, "/%s\n", srch[i]);
		for(i = cfg.search_history_num; i >= 0; i--)
			fprintf(fp, "/%s\n", cfg.search_history[i]);
	}

	if(cfg.vifm_info & VIFMINFO_PHISTORY)
	{
		fputs("\n# Prompt history (oldest to newest):\n", fp);
		for(i = 0; i < nprompt; i++)
			fprintf(fp, "p%s\n", prompt[i]);
		for(i = cfg.prompt_history_num; i >= 0; i--)
			fprintf(fp, "p%s\n", cfg.prompt_history[i]);
	}

	if(cfg.vifm_info & VIFMINFO_REGISTERS)
	{
		fputs("\n# Registers:\n", fp);
		for(i = 0; i < nregs; i++)
			fprintf(fp, "%s\n", regs[i]);
		for(i = 0; valid_registers[i] != '\0'; i++)
		{
			int j;
			registers_t *reg = find_register(valid_registers[i]);
			if(reg == NULL)
				continue;
			for(j = 0; j < reg->num_files; j++)
			{
				if(reg->files[j] == NULL)
					continue;
				fprintf(fp, "\"%c%s\n", reg->name, reg->files[j]);
			}
		}
	}

	if(cfg.vifm_info & VIFMINFO_DIRSTACK)
	{
		fputs("\n# Directory stack (oldest to newest):\n", fp);
		for(i = 0; i < stack_top; i++)
		{
			fprintf(fp, "S%s\n\t%s\n", stack[i].lpane_dir, stack[i].lpane_file);
			fprintf(fp, "S%s\n\t%s\n", stack[i].rpane_dir, stack[i].rpane_file);
		}
	}

	fputs("\n# Trash content:\n", fp);
	for(i = 0; i < nentries; i++)
		fprintf(fp, "t%s\n\t%s\n", trash_list[i].trash_name, trash_list[i].path);
	for(i = 0; i < ntrash; i += 2)
		fprintf(fp, "t%s\n\t%s\n", trash[i], trash[i + 1]);

	if(cfg.vifm_info & VIFMINFO_STATE)
	{
		fputs("\n# State:\n", fp);
		fprintf(fp, "f%s\n", lwin.filename_filter);
		fprintf(fp, "i%d\n", lwin.invert);
		fprintf(fp, "[.%d\n", lwin.hide_dot);
		fprintf(fp, "F%s\n", rwin.filename_filter);
		fprintf(fp, "I%d\n", rwin.invert);
		fprintf(fp, "].%d\n", rwin.hide_dot);
		fprintf(fp, "s%d\n", cfg.use_screen);
	}

	if(cfg.vifm_info & VIFMINFO_CS)
	{
		fputs("\n# Color scheme:\n", fp);
		fprintf(fp, "c%s\n", cfg.cs.name);
	}

	fclose(fp);

	free_string_array(ft, nft);
	free_string_array(fv, nfv);
	free_string_array(fx, nfx);
	free_string_array(cmds, ncmds);
	free_string_array(marks, nmarks);
	free_string_array(list, nlist);
	free_string_array(lh, nlh);
	free_string_array(rh, nrh);
	free(lhp);
	free(rhp);
	free_string_array(cmdh, ncmdh);
	free_string_array(srch, nsrch);
	free_string_array(regs, nregs);
	free_string_array(prompt, nprompt);
	free_string_array(trash, ntrash);
}