﻿/* Filter by Column for Directory Opus
**Filter Bar for all columns**
Copyright (c) 2023-2024  Christian Arellano García

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/
var script_name = 'FilterbyColumn';
var script_label = 'Filter by Column';
var script_version = '1.4.9b1';
var g_custom_col = false;
// Called by Directory Opus to initialize the script
function OnInit(initData) {
	initData.name = script_name;
	initData.version = script_version;
	initData.copyright = '(c) 2023-2024 Christian Arellano García';
	initData.desc = 'Filter Bar for all columns';
	initData.url = 'https://resource.dopus.com/t/filter-by-column-filter-bar-for-all-columns/47559';
	initData.default_enable = true;
	initData.min_version = '13.3.2';
	initData.config_desc = DOpus.Create.Map();
	initData.config_groups = DOpus.Create.Map();
	AddConfig('debug', DOpus.Create.Vector(2, 'ALL', 'STANDARD', 'WARNING', 'OFF'), DOpus.strings.Get('debug'), 'Script Logs');
	AddConfig('custom_columns_categories', DOpus.Create.Vector(), DOpus.strings.Get('custom_columns_categories'), 'Script/Evaluator/Shell Columns');
	AddConfig('flags_quickkey', '?', DOpus.strings.Get('flags_quickkey'), 'General');
	AddConfig('default_implicit_column', DOpus.Create.Vector(0, 'name', 'current sorted', 'user_defined_implicit_column value', 'current highlighted'), DOpus.strings.Get('default_implicit_column'), 'General');
	AddConfig('preferred_filter_mode', DOpus.Create.Vector(0, 'Textual Filters', 'Rename Preset'), DOpus.strings.Get('preferred_filter_mode'), 'Script/Evaluator/Shell Columns');
	AddConfig('enable_wildcards', false, DOpus.strings.Get('enable_wildcards'), 'Filter Mode Options');
	AddConfig('max_history_size', 20, DOpus.strings.Get('max_history_size'), 'General');
	AddConfig('user_defined_implicit_column', '', DOpus.strings.Get('user_defined_implicit_column'), 'General');
	AddConfig('custom_columns_names', DOpus.Create.Vector(), DOpus.strings.Get('custom_columns_names'), 'General');
	AddConfig('labels_access', DOpus.Create.Vector(1, 'All (including status)', 'As shown in Column'), DOpus.strings.Get('labels_access'), 'Filter Mode Options');
	AddConfig('add column', true, DOpus.strings.Get('add_column'), 'Search Mode Options');
	AddConfig('collection name', '', DOpus.strings.Get('collection_name'), 'Search Mode Options');
	AddConfig('create subcollections', false, DOpus.strings.Get('create_subcollections'), 'Search Mode Options');
	return;

	function AddConfig(name, value, desc, group) {
		initData.config[name] = value;
		initData.config_desc(name) = desc;
		initData.config_groups(name) = group;
	}

}

function OnAddCommands(addCmdData) {
	var cmd = addCmdData.AddCommand();
	cmd.name = script_name;
	cmd.method = 'OnColFilter';
	cmd.desc = 'Filter Bar for all columns';
	cmd.label = script_label;
	cmd.template = 'REGEXP/S,WHOLEWORDS/S,CASE/S,NODIACRITICS/S,USEWILD/S,FILTER/O[visible],QUERY/K/R,DIALOG/K[filterall,accessed,accesseddate,accessedtime,created,createddate,createdtime,modified,modifieddate,modifiedtime,attr,ext,extdir,sizeauto,size,sizekb,fullpath,label,owner,type,perms,availability,desc,keywords,name,parent,parentlocation,parentpath,path,pathrel,userdesc,pathlen,copyright,producer,picdepth,mp3bpm,mp3disc,mp3disk,mp3track,compilation,mp3album,mp3albumartist,mp3comment,mp3encoder,mp3encodingsoftware,mp3info,mp3drm,doccreateddate,docedittime,doclastsaveddate,pages,category,comments,creator,doclastsavedby,modversion,prodversion,moddesc,prodname,fontname,datedigitized,datetaken,35mmfocallength,altitude,apertureval,digitalzoom,exposurebias,exposuretime,fnumber,focallength,latitude,longitude,picphysx,picphysy,picresx,picresy,rotation,shutterspeed,subjectdistance,cameramake,cameramodel,colormodel,colorspace,contrast,coords,exposureprogram,flash,imagedesc,imagequality,instructions,isospeed,lensmake,lensmodel,macromode,meteringmode,picres,saturation,scenecapturetype,scenemode,sharpness,software,whitebalance,broadcastdate,recordingtime,audiocount,channel,datarate,framerate,subtitlecount,videocount,alllangs,audiolangs,credits,director,episodename,fourcc,hdrtypes,ishd,isrepeat,publisher,station,subtitlelangs,videocodec,videolangs,encodedby,rating,target,duration,releasedate,mp3bitrate,mp3samplerate,mp3year,audiocodec,composers,conductors,mp3genre,mp3mode,mp3title,mp3type,initialkey,companyname,subject,picsize,aspectratiogroup,picphyssize,aspectratio,picheight,picwidth,mp3artists,author,title]';
	cmd.hide = false;
	cmd.icon = 'script';
	var fayt = cmd.fayt;
	fayt.enable = true;
	fayt.key = '$';
	fayt.backcolor = '#ffad5b';
	fayt.textcolor = '#000000';
	fayt.label = script_label;
	fayt.realtime = true;
	fayt.flags = DOpus.Create.Map();
	fayt.flags[(1 << 0)] = DOpus.strings.Get('flag0'); //Case sensitive
	fayt.flags[(1 << 1)] = DOpus.strings.Get('flag1'); //Whole words
	fayt.flags[(1 << 2)] = DOpus.strings.Get('flag2'); //Regular expressions
	fayt.flags[(1 << 3)] = DOpus.strings.Get('flag3'); //Ignore diacritics
	fayt.flags[(1 << 4)] = DOpus.strings.Get('flag4'); //Ignore columns
	fayt.flags[(1 << 5)] = DOpus.strings.Get('flag5'); //Filter only visible
	fayt.flags[(1 << 6)] = DOpus.strings.Get('flag6'); //Search Mode
}

var str_tools, g_flags, g_ini_timer, FSU, search_mode, use_wildcards, custom_name, is_default_filter, quickKey, first, custom_categories_map, custom_names_map;

function OnColFilter(scriptFAYTData) {
	if (!str_tools) str_tools = DOpus.Create.StringTools();
	var from_dialog;
	if (scriptFAYTData.fayt !== script_name) {
		if (Script.config.debug < 2) {
			Log(2, '=======' + script_label + ' v' + script_version + '=====================================');
			Log(2, 'Command mode            : ' + scriptFAYTData.cmdline);
		}
		var tab = scriptFAYTData.func.sourcetab;
		if (!FSU) FSU = DOpus.FSUtil();
		//needs query,g_flags,tab,search_mode to continue
		if (!tab || /(shell|mtp|ftp|plugin)/.test(FSU.PathType(tab.path))) { //don't work in shell, mtp, plugin
			Log(4, '"' + script_name + '" is not valid or is not supossed to work in this type of path : shell, mtp, plugin');
			return;
		}
		if (scriptFAYTData.func.args.got_arg.dialog) {
			from_dialog = true;
			var query = BuildFilterFromDialog(tab, scriptFAYTData.func.command, scriptFAYTData.func.args.dialog);
		}
		else {
			if (!scriptFAYTData.func.args.got_arg.query) return;
			var query = scriptFAYTData.func.args.query;
			g_flags = 0;
			if (scriptFAYTData.func.args.got_arg['case']) g_flags += (1 << 0);
			if (scriptFAYTData.func.args.got_arg.wholewords) g_flags += (1 << 1);
			if (scriptFAYTData.func.args.got_arg.regexp) g_flags += (1 << 2);
			if (scriptFAYTData.func.args.got_arg.nodiacritics) g_flags += (1 << 3);
			if (scriptFAYTData.func.args.got_arg.usewild) use_wildcards = true;
			if (scriptFAYTData.func.args.got_arg.filter) {
				search_mode = false;
				if (String(scriptFAYTData.func.args.filter).toLowerCase() === 'visible') g_flags += (1 << 5);
			}
			else search_mode = true;
		}
	}
	else {
		if (scriptFAYTData.quickkey) quickKey = scriptFAYTData.quickkey;
		var query = scriptFAYTData.cmdline;
		if (is_default_filter === undefined || !quickKey) {
			is_default_filter = CheckDefaultFilter();
		}
		if (!quickKey) {
			Log(4, 'Unexpected FAYT         : quick key can\'t be empty!');
			return;
		}

		if (is_default_filter && query.charAt(0) == quickKey) {
			var append_key = quickKey;
			query = query.slice(1);
		}
		else var append_key = '';

		if (query === '' || query === quickKey) scriptFAYTData.tab.UpdateFAYTSuggestions(getSuggestions(append_key + query, true)); //only suggest custom names
		else scriptFAYTData.tab.UpdateFAYTSuggestions(getSuggestions(append_key + (query.charAt(0) === quickKey ? quickKey : ''), false));

		if (!query || scriptFAYTData.key !== 'return') //No return key was pressed
			return;
		var flags_quickkey = Script.config.flags_quickkey;
		if (Script.config.debug < 2) {
			Log(2, '=======' + script_label + ' v' + script_version + '=====================================');
			Log(1, 'FAYT cmdline            : ' + query);
			Log(2, 'quickKey                : ' + quickKey);
			Log(2, 'is default filter       : ' + is_default_filter);
			Log(1, 'flags_quickkey          : ' + flags_quickkey);
		}

		if (quickKey == flags_quickkey) {
			Log(3, 'flags_quickkey can\'t be the same as ' + quickKey);
			flags_quickkey = '';
		}
		if (query == quickKey) { // query is the same key as quick key so Print cols info
			Log(2, 'Printing cols name for all visible columns...');
			printCols(scriptFAYTData.tab.format.columns, scriptFAYTData.tab);
			return;
		}
		search_mode = false;
		if (query.charAt(0) == quickKey) {
			search_mode = true;
			query = query.slice(1);
		}
		g_flags = scriptFAYTData.flags;
		if (g_flags & (1 << 6)) search_mode = !search_mode; //toggle between filter and search
		var tab = scriptFAYTData.tab;
		if (flags_quickkey && query == flags_quickkey) { //user activated flags dialog window
			Log(2, 'Flags configuration activated');
			configFlags(tab.lister, g_flags);
			return;
		}
		Log(2, 'active tab              : ' + tab.path);
		if (!FSU) FSU = DOpus.FSUtil();
		//needs query,g_flags,tab,search_mode to continue
		if (!tab || /(shell|mtp|plugin)/.test(FSU.PathType(tab.path))) { //don't work in shell, mtp, plugin
			Log(4, '"' + script_label + '" is not valid or is not supossed to work in this type of path : shell, mtp, plugin');
			return;
		}
		Log(1, 'default_implicit_column : ' + Script.config.default_implicit_column);
		Log(1, 'preferred_filter_mode   : ' + (Script.config.preferred_filter_mode === 0 ? 'Textual Filters' : 'Rename Preset'));
		Log(1, 'user_implicit_column    : ' + Script.config.user_defined_implicit_column);
		Log(1, 'labels_access           : ' + (Script.config.labels_access === 0 ? 'All (including status)' : 'As shown in Column'));
	}
	g_ini_timer = new Date();
	if (query) {
		// if (!scriptFAYTData.func.args.got_arg.dialog) alert(tab, 'Missing arguments!', 3);
		if (use_wildcards === undefined) use_wildcards = Script.config.enable_wildcards;
		if (Script.config.debug < 2) {
			Log(2, 'query                   : "' + query + '"');
			Log(1, 'Add column              : ' + Script.config['add column']);
			Log(1, 'collection name         : ' + Script.config['collection name']);
			Log(1, 'create subcollections   : ' + Script.config['create subcollections']);
			Log(1, 'Case sensitive          : ' + (g_flags & (1 << 0) ? 'true' : 'false'));
			Log(1, 'Whole words             : ' + (g_flags & (1 << 1) ? 'true' : 'false'));
			Log(1, 'Regular expressions     : ' + (g_flags & (1 << 2) ? 'true' : 'false'));
			Log(1, 'Ignore diacritics       : ' + (g_flags & (1 << 3) ? 'true' : 'false'));
			Log(1, 'Ignore columns          : ' + (g_flags & (1 << 4) ? 'true' : 'false'));
			Log(1, 'Use wilcards            : ' + use_wildcards);
			Log(2, 'Search Mode             : ' + search_mode);
			Log(1, '==================================================================');
		}

		var col_obj = getColObj(tab, query); //Get name, category and valid operators for the column to use
		if (col_obj !== null) {
			var query_obj = getQueryObj(query, col_obj); // Get converted query, raw query and operators from user input
			if (query_obj !== null) {
				var cmd = DOpus.Create.Command();
				cmd.SetSourceTab(tab);
				if (search_mode) BuildListFromFilter(tab, cmd, query_obj, col_obj, false);
				else {
					if (g_flags & (1 << 5) && tab.stats.items > 0) Log(2, 'Using only currently displayed items...');
					else cmd.RunCommand('SELECT NOPATTERN SHOWHIDDEN');
					if (!g_custom_col) use_wildcards ? BuildListFromFilter(tab, cmd, query_obj, col_obj, true) : BuildListFromTab(tab, cmd, query_obj, col_obj);
					else Script.config.preferred_filter_mode === 0 ? BuildListFromFilter(tab, cmd, query_obj, col_obj, true) : BuildListFromPreset(tab, cmd, query_obj, col_obj);
				}
				saveQuery(query, custom_name ? col_obj.name : '');
				query_obj = null;
				cmd = null;
			}
			else Log(4, 'Input is not valid');
			col_obj = null;
		}
	}
	else if (!from_dialog) alert(tab, 'Missing arguments!', 3);
	Log(2, 'COMMAND FINNISHED       : ' + (new Date() - g_ini_timer) + ' ms');
	Log(2, '===================================================================');
	tab = null;
	FSU = null;
	str_tools = null;
	g_ini_timer = null;
	CollectGarbage();
	return true;
}

//Get info about the selected column. return null if not valid column
function getColObj(tab, query) {
	Log(2, 'PARSING COL TO OBJECT   : ' + (new Date() - g_ini_timer) + ' ms');
	custom_name = false;
	var cat, metatype, property, operator, name;
	property = metatype = false;
	var col = false;
	//Check if input makes reference to a particular column number
	var match = query.match(/^[cC](\d+) *((>=|=>|<=|=<|!=|==|=|<|>).*)/);
	//input is in the form C[#]<operator>query
	if (match) {
		Log(2, '   Explicit column      : C' + match[1]);
		try {
			if (tab.format.columns(0).name === 'index') //first columns is index so we just ignore it
				col = tab.format.columns(match[1]);
			else col = tab.format.columns(match[1] - 1);
			query = match[2];
		}
		catch (e) {
			Log(3, '   Not such column number could be found!!!');
			col = null;
		}
	}
	else {
		//Check if input makes reference to a custom column name
		if (custom_names_map === undefined) custom_names_map = Script.config.custom_columns_names.empty ? null : (Script.Vars.Exists('custom_columns_names') ? Script.Vars.Get('custom_columns_names') : getCustomMap('custom_columns_names', true, true));
		match = query.match(/^(.+?) *((?:>=|=>|<=|=<|!=|==|=|<|>).*)/);
		if (match) {
			Log(2, '   Explicit custom name : ' + match[1]);
			if (custom_names_map !== null && custom_names_map.Exists(match[1])) {
				custom_name = true;
				try {
					col = 'forced';
					name = custom_names_map(match[1]).toLowerCase();
					query = match[2];
				}
				catch (err) {
					Log(3, '   Column "' + match[1] + '" can\'t be found. Check if is a valid column');
					col = null;
				}
			}
			else {
				Log(1, '   "' + match[1] + '" seems is not registered or is invalid. Trying to use it anyway');
				col = 'forced';
				name = match[1].toLowerCase();
				query = match[2];
			}
		}
		if (col === false) { //no explicit reference, use default column
			Log(2, '   Implicit column mode');
			switch (Script.config.default_implicit_column) {
				case 1:
					col = tab.format.sort_field;
					break;
				case 2:
					var f_col = Script.config.user_defined_implicit_column;
					if (f_col) {
						col = 'forced';
						name = f_col.toLowerCase();
					}
					break;
				case 3:
					try {
						var first_hgh = tab.all(0).highlighted;
						if (first_hgh.count > 0) {
							col = 'forced';
							name = first_hgh(0).column.toLowerCase();
						}
						else Log(2, '   No columns highlighted available');
					}
					catch (err) {
						Log(3, '   Unable to get column highlighted name : ' + err.description);
						col = false;
					}
					break;
			}
			query = false;
			try {
				if (col === false) {
					Log(1, '   Using Name column as default');
					col = tab.format.columns('name');
				}
			}
			catch (e) {
				Log(3, '   Can\'t retrieve Name column info!');
				col = null;
			}
			custom_name = true;
		}
	}
	match = null;
	if (col === null) return null;
	if (col !== 'forced') name = col.name.toLowerCase();
	switch (name) { //list of unsupported columns
		case 'group':
		case 'md5sum':
		case 'shasum':
		case 'blake3sum':
		case 'crc32sum':
		case 'sha256sum':
		case 'sha512sum':
		case 'thumbnail':
		case 'status':
		case 'sizerel':
		case 'disksizeauto':
		case 'disksize':
		case 'disksizekb':
		case 'disksizerel':
		case 'uncompressedsize':
		case 'dircounttotal':
		case 'filecounttotal':
			Log(3, '   "' + name + '" column is not supported for filter');
			return null;
	}
	//check if column is a script/Evaluator/shell/special column
	if (name === 'label' && Script.config.labels_access === 1) g_custom_col = true;
	else if (name === 'availability' || name === 'dircount' || name === 'perms' || name === 'filecount') g_custom_col = true;
	else if (/^scp:.*$/.test(name)) g_custom_col = 'script';
	else if (/^eval:.*/.test(name)) g_custom_col = 'eval';
	else if (/^sh:.*/.test(name)) g_custom_col = 'shell';
	if (typeof g_custom_col === 'string') { //for non built-in columns
		if (!Script.config.custom_columns_categories.empty) { //check for custom categories
			Log(2, '   Searching category in custom_columns_categories...');
			if (custom_categories_map === undefined) custom_categories_map = Script.Vars.Exists('custom_columns_categories') ? Script.Vars.Get('custom_columns_categories') : getCustomMap('custom_columns_categories', false, true);
			if (custom_categories_map.Exists(name)) cat = custom_categories_map(name);
			//no category for this column, default to string
			else if (g_custom_col != 'eval') {
				Log(3, '   "' + name + '" column doesn\'t have a registered category type. Using "STRING" as default');
				cat = 'string';
			}
		}
		//no custom category registered for Evaluator columns, get declared
		if (!cat && g_custom_col === 'eval') cat = getCatEvalCol(name.slice(5));
	}
	else { //Get category for built-in columns
		info = getColumnData(name);
		if (info !== null) {
			cat = info('category');
			metatype = info('metatype');
			property = info('property');
			info = null;
		}
	}
	if (!cat) {
		Log(3, '   Column "' + name + '" doesn\'t have a valid category');
		return null;
	}
	operator = (cat === 'string') ? /^(!=|==)$/ : /^(!=|>=|<=|==|<|>)$/;
	name = name.replace(/\s/g, '');
	Log(2, '   name                 : ' + name);
	Log(2, '   category             : ' + cat);
	Log(1, '   query                : ' + query);
	Log(1, '   metatype             : ' + metatype);
	Log(1, '   property             : ' + property);
	Log(1, '   operator             : ' + operator);
	Log(2, 'PARSING COL FINNISHED   : ' + (new Date() - g_ini_timer) + ' ms');
	return {
		'name': name,
		'category': cat,
		'query': query,
		'metatype': metatype,
		'property': property,
		'operator': operator
	};
}
//Get info about used input
function getQueryObj(query, obj_col) {
	//if the input contains reference to a column, get the new input from col obj
	if (obj_col.query != false) query = obj_col.query;
	Log(2, 'PARSING INPUT TO OBJ    : ' + (new Date() - g_ini_timer) + ' ms');
	var quote = false;
	var operator = '';
	var currentPart = '';
	var helper = '';
	var op_regex = obj_col.category === 'string' ? /!|=/ : /!|>|<|=/;
	query = query.trim();
	for (var i = 0; i < query.length; i++) {
		var c = query.charAt(i);
		if (c === '"') quote = !quote;
		else if (!quote && op_regex.test(c)) operator += c;
		else currentPart += c;
	}
	if (operator === '' && obj_col.query == false) operator = '=='; //only allow implicit operator if column is implicit
	if (operator === '=' || operator == '!') operator += '=';
	else if (operator === '=>') operator = '>=';
	else if (operator === '=<') operator = '<=';

	if (operator === '' || !obj_col.operator.test(operator)) {
		Log(3, '   No valid operator detected. Valid operators for ' + obj_col.category + ' column types are : ' + obj_col.operator.source.substring(2, obj_col.operator.source.length - 2));
		return null;
	}
	currentPart = currentPart.trim();
	//in case column type is date, make support for some special syntax
	if (obj_col.category == 'date') {
		if ((operator == '==' || operator == '!=') && (c = currentPart.match(/^((?:1[6-9]|2[0-9])\d{2}) *(?:-|\.\.) *((?:1[6-9]|2[0-9])\d{2})$/))) { //is a range of 2 years
			Log(1, '   ' + currentPart + ' is a range of 2 years in yyyy format');
			helper = 'ryear';
			currentPart = c;
		}
		else if (/^(1[6-9]|2[0-9])\d{2}$/.test(currentPart)) { //is a 4-digit number
			Log(1, '   ' + currentPart + ' is a year in yyyy format');
			helper = 'year';
		}
		else if ((operator == '==' || operator == '!=') && (c = currentPart.match(/^([1-9]|0[1-9]|1[0-2])[-/]((?:1[6-9]|2[0-9])\d{2}) *(?:\.\.) *([1-9]|0[1-9]|1[0-2])[-/]((?:1[6-9]|2[0-9])\d{2})$/))) { //is a 6-digit number with the format MM-yyyy or MM/yyyy
			Log(1, '   ' + currentPart + ' is a range of 2 dates MM-yyyy');
			helper = 'rmyear';
			currentPart = c;
		}
		else if (c = currentPart.match(/^([1-9]|0[1-9]|1[0-2])[-/]((?:1[6-9]|2[0-9])\d{2})$/)) { //is a 6-digit number with the format MM-yyyy or MM/yyyy
			Log(1, '   ' + currentPart + ' is a 6-digit number with the format MM-yyyy');
			helper = 'month';
			currentPart = c;
		}
		else if ((operator == '==' || operator == '!=') && (c = currentPart.match(/^([12]\d|3[01]|0?[1-9])[-/]([1-9]|0[1-9]|1[0-2])[-/]((?:1[6-9]|2[0-9])\d{2}) *(?:\.\.) *([12]\d|3[01]|0?[1-9])[-/]([1-9]|0[1-9]|1[0-2])[-/]((?:1[6-9]|2[0-9])\d{2})$/))) { //is a range of two dates dd-MM-yyyy
			Log(1, '   ' + currentPart + ' is a range of two dates with the format dd-MM-yyyy');
			helper = 'rdate';
			currentPart = c;
		}
		else if ((operator == '==' || operator == '!=') && (c = currentPart.match(/^((?:1[6-9]|2[0-9])\d{2})[-/]([1-9]|0[1-9]|1[0-2])[-/]([12]\d|3[01]|0?[1-9]) *(?:\.\.) *((?:1[6-9]|2[0-9])\d{2})[-/]([1-9]|0[1-9]|1[0-2])[-/]([12]\d|3[01]|0?[1-9])$/))) { //is a range of two dates yyyy-MM-dd
			Log(1, '   ' + currentPart + ' is a range of two dates with the format yyyy-MM-dd');
			helper = 'rdate';
			currentPart = c;
		}
		else if (c = currentPart.match(/^(\d+) *[hH][aA]$/)) { //is a number followed by 'ha' means x hours ago from now
			Log(1, '   ' + currentPart + ' means ' + c[1] + ' hours ago from now');
			currentPart = c[1];
			helper = 'ha';
		}
		else if (c = currentPart.match(/^(\d+) *[dD][aA]$/)) { //is a number followed by 'da' means x days ago from now
			Log(1, '   ' + currentPart + ' means ' + c[1] + ' days ago from now');
			currentPart = c[1];
			helper = 'da';
		}
		else if (c = currentPart.match(/^(\d+) *[mM][aA]$/)) { //is a number followed by 'ma' means x months ago from now
			Log(1, '   ' + currentPart + ' means ' + c[1] + ' months ago from now');
			currentPart = c[1];
			helper = 'Ma';
		}
		else if (c = currentPart.match(/^(\d+) *[yY][aA]$/)) { //is a number followed by 'ya' means x months ago from now
			Log(1, '   ' + currentPart + ' means ' + c[1] + ' years ago from now');
			currentPart = c[1];
			helper = 'ya';
		}
		else if ((operator == '==' || operator == '!=') && (c = currentPart.match(/^([12]\d|3[01]|0?[1-9]) *(?:-|\.\.) *([12]\d|3[01]|0?[1-9]) *[dD]$/))) { //is [1-31][-..][1-31]d
			Log(1, '   ' + currentPart + ' is a range of days');
			currentPart = c;
			helper = 'day';
		}
		else if (c = currentPart.match(/^([12]\d|3[01]|0?[1-9]) *[dD]$/)) { //is a number between 1 and 31 followed by 'd'
			Log(1, '   ' + c[1] + ' is a number between 1 and 31 followed by d');
			currentPart = c[1];
			helper = 'day';
		}
		else if (c = currentPart.match(/^([1-9]|0[1-9]|1[0-2]) *(?:-|\.\.) *([1-9]|0[1-9]|1[0-2]) *[mM]$/)) { //is a number between 1 and 12 followed by 'm'
			Log(1, '   ' + currentPart + ' is a range of months');
			currentPart = c;
			helper = 'm';
		}
		else if (c = currentPart.match(/^([1-9]|0[1-9]|1[0-2]) *[mM]$/)) { //is a number between 1 and 12 followed by 'm'
			Log(1, '   ' + c[1] + ' is a number between 1 and 12 followed by m');
			currentPart = c[1];
			helper = 'm';
		}
		else if (/^([1-9]|0[1-9]|1[0-2])$/.test(currentPart)) { //is a number between 1 and 12
			Log(1, '   ' + currentPart + ' is a number referring a month');
			helper = 'month';
		}
		else if ((operator == '==' || operator == '!=') && (c = currentPart.match(/^(0?[1-9]|[12][0-9]|3[01])[-/](0?[1-9]|1[0-2])[-/]((?:1[6-9]|2[0-9])\d{2}) (0?\d|1\d|2[0-3]):([0-5]?\d)(?::([0-5]?\d))? *(?:\.\.) *(0?[1-9]|[12][0-9]|3[01])[-/](0?[1-9]|1[0-2])[-/]((?:1[6-9]|2[0-9])\d{2}) (0?\d|1\d|2[0-3]):([0-5]?\d)(?::([0-5]?\d))?$/))) {
			Log(1, '   ' + currentPart + ' is a range of two dates with the format dd-MM-yyyy HH:mm:ss or HH:mm');
			helper = 'rwhole';
			currentPart = c;
		}
		else if ((operator == '==' || operator == '!=') && (c = currentPart.match(/^((?:1[6-9]|2[0-9])\d{2})[-/](0?[1-9]|1[0-2])[-/](0?[1-9]|[12][0-9]|3[01]) (0?\d|1\d|2[0-3]):([0-5]?\d)(?::([0-5]?\d))? *(?:\.\.) *((?:1[6-9]|2[0-9])\d{2})[-/](0?[1-9]|1[0-2])[-/](0?[1-9]|[12][0-9]|3[01]) (0?\d|1\d|2[0-3]):([0-5]?\d)(?::([0-5]?\d))?$/))) {
			Log(1, '   ' + currentPart + ' is a range of two dates with the format yyyy-MM-dd HH:mm:ss or HH:mm');
			helper = 'rwhole';
			currentPart = c;
		}
		else if (c = currentPart.match(/^\d+([/\-:])\d+.*$/)) { //only numbers , '/-:' are present
			Log(1, '   ' + currentPart + ' contains only numbers , /-: are present');
			helper = currentPart;
			currentPart = DOpus.Create.Date(currentPart);
			if (c[1] != ':') helper = (/[:\.]/.test(helper)) ? ((!currentPart.sec) ? 'sD' : 'whole') : 'd'; //value contains date only or date and time
			else helper = (!currentPart.sec) ? 'tsD' : 't'; //is time only, with or without seconds
		}
		else {
			Log(1, '   ' + currentPart + ' is a constant');
			helper = currentPart.toLowerCase(); //is a constant value
			currentPart = '';
		}
	}
	else if ((obj_col.category == 'number' || obj_col.category == 'size') && (operator == '==' || operator == '!=') && /-|\.\./.test(currentPart)) {
		//means a range between 2 values
		currentPart = currentPart.split(/-|\.\./);
	}
	else if (obj_col.category == 'duration') {
		helper = currentPart;
		if ((operator == '==' || operator == '!=') && /-|\.\./.test(currentPart))
			currentPart = currentPart.split(/-|\.\./); //means a range between 2 values
		if (/^(accessedtime|createdtime|modifiedtime)$/.test(obj_col.name)) {
			if (typeof currentPart == 'object') {
				for (var i = 0; i < currentPart.length; i++)
					if ((currentPart[i].match(/:/g) || []).length < 3) currentPart[i] += ':00';
			}
			else {
				if ((currentPart.match(/:/g) || []).length < 3) currentPart += ':00';
			}
		}
	}
	else if (obj_col.category == 'string' && obj_col.name == 'name' && /:/.test(currentPart)) {
		//means filter by filetype group
		currentPart = currentPart.split(':');
	}
	//Convert input to column type
	currentPart = convertType(obj_col.category, currentPart, helper);
	//If can't convert input to selected category
	if (currentPart == null) {
		Log(3, "   Filter input can't be converted to " + obj_col.category);
		return null;
	}
	if (Script.config.debug === 0) {
		if (DOpus.TypeOf(currentPart) === 'object.Vector') {
			if (DOpus.TypeOf(currentPart(0)) === 'object.FileSize') Log(1, '   lower : ' + currentPart(0).fmt + '   upper : ' + currentPart(1).fmt);
			else if (DOpus.TypeOf(currentPart(0)) === 'object.Date') Log(1, '   lower : ' + currentPart(0).Format('', 'n') + '   upper : ' + currentPart(1).Format('', 'n'));
			else Log(1, '   lower : ' + currentPart(0) + '   upper : ' + currentPart(1));
		}
		else if (DOpus.TypeOf(currentPart) == 'object.FileSize') Log(1, '   query                : ' + currentPart.fmt);
		else if (DOpus.TypeOf(currentPart) == 'object.Date') Log(1, '   query                : ' + currentPart.Format('', 'n'));
		else Log(1, '   query                : ' + currentPart);
		Log(1, '   raw_query            : ' + helper);
		Log(1, '   operator             : ' + operator);
		Log(2, 'PARSING INPUT FINNISHED : ' + (new Date() - g_ini_timer) + ' ms');
	}
	return {
		'query': currentPart,
		'raw_query': helper,
		'operator': operator
	};
}
//Filter function for built-in columns
function BuildListFromTab(tab, cmd, obj_query, obj_col) {
	Log(2, 'FILTERING IN COLUMN "' + obj_col.name + '" FOR: ' + tab.all.count + ' ITEMS');
	var res = DOpus.Create.Vector();
	var item, a, helper, query, operator, metatype;
	operator = obj_query.operator;
	query = obj_query.query;
	if (operator == '') operator = '=';
	if (operator == '=' || operator == '!') operator += '=';
	if (obj_col.name == 'extdir') { //translated value for <dir>
		helper = str_tools.LanguageStr(2132);
		helper = helper.replace(/[<>]/g, '');
	}
	var ign_col = (g_flags & 1 << 4) ? true : false;
	for (var i = 0; i < tab.all.count; i++) {
		item = tab.all(i);
		a = false;
		try {
			if (obj_col.property == false) { //means required a pre treatment//have different sources for the column value
				switch (obj_col.name) {
					case 'name':
						if (DOpus.TypeOf(query) == 'object.Vector') a = compareGroup(item, query, operator);
						else a = compareStrings(tab.format.hide_ext ? item.name_stem_m : item.name, query, operator);
						break;
					case 'extdir':
						a = compareStrings((item.is_dir) ? helper : item.ext, query, operator);
						break;
						// case 'fullpath':
						// 	a = compareStrings(String(item.realpath), query, operator);
						// 	break;
					case 'keywords':
						helper = '';
						for (var k = 0; k < item.metadata.tags.count; k++) helper += item.metadata.tags(k) + ';';
						a = compareStrings(helper.slice(0, -1), query, operator);
						break;
					case 'label':
						helper = '';
						v = item.Labels();
						for (var k = 0; k < v.count; k++) helper += v(k) + ';';
						a = compareStrings(helper.slice(0, -1), query, operator);
						break;
					case 'owner':
						a = compareStrings(item.ShellProp('System.FileOwner', 'r'), query, operator);
						break;
					case 'type':
						a = compareStrings(item.ShellProp('System.ItemTypeText', 'r'), query, operator);
						break;
					case 'parent':
						a = compareStrings(item.realpath.Parent().filepart, query, operator);
						break;
					case 'parentlocation':
						a = compareStrings(item.realpath.Parent().filepart + ' (' + item.realpath.Parent().pathpart + ')', query, operator);
						break;
					case 'parentpath':
						a = compareStrings(item.realpath.Parent().pathpart, query, operator);
						break;
					case 'path':
						a = compareStrings(item.realpath.pathpart, query, operator);
						break;
					case 'pathlen':
						a = compare(String(item).length, query, operator);
						break;
					case 'pathrel':
						a = compareStrings(String(item.realpath).replace(String(tab.path), ''), query, operator);
						break;
					case 'desc':
						helper = item.metadata.other.usercomment ? item.metadata.other.usercomment : '';
						helper += (item.metadata.other.autodesc ? ((helper ? ' - ' : '') + item.metadata.other.autodesc) : '');
						a = compareStrings(helper, query, operator);
						break;
						// case 'userdesc':
						// 	if (item.metadata == 'none') return false;
						// 	a = compareStrings(item.metadata.other[obj_col.type] || '', query, operator);
						// 	break;
						// case 'copyright':
						// 	if (obj_col.metatype.test(item.metadata)) a = compareStrings(item.metadata[item.metadata][obj_col.name], query, operator);
						// 	else if (!ign_col) a = compareStrings(item.metadata.doc.copyright, query, operator);
						// 	break;
						// case 'picdepth':
						// 	if (obj_col.metatype.test(item.metadata)) a = compare(item.metadata[item.metadata][obj_col.name], query, operator);
						// 	else if (!ign_col) a = compare(item.metadata.image.picdepth, query, operator);
						// 	break;
					case 'accessedtime':
					case 'createdtime':
					case 'modifiedtime':
						helper = item[obj_col.property];
						a = compare(helper.hour * 3600 + helper.min * 60 + helper.sec, query, operator);
						break;
				}
			}
			else {
				metatype = obj_col.metatype;
				if (metatype === true) helper = item.metadata[item.metadata + ''][obj_col.property];
				else if (metatype && typeof metatype === 'string') helper = item.metadata[metatype][obj_col.property];
				else helper = item[obj_col.property];
				switch (obj_col.category) {
					case 'string':
						if (!metatype) a = compareStrings(helper, query, operator);
						else if (helper || !ign_col) a = compareStrings(helper, query, operator);
						break;
					case 'number':
					case 'duration':
						if (helper || !ign_col) a = compare(helper, query, operator);
						break;
					case 'size':
						a = compareSizes(helper, query, operator);
						break;
					case 'date':
						if (!metatype) a = compareDates(helper, query, obj_query.raw_query, operator);
						else if (helper || !ign_col) a = compareDates(helper, query, obj_query.raw_query, operator);
						break;
				}
			}
		}
		catch (err) {
			Log(3, 'Error when trying to get ' + obj_col.name + ' info for ' + item);
		}
		if (a == true) {
			if (item.nested) {
				helper = item.path;
				while (String(helper) != String(tab.path)) {
					res.push_back(String(helper));
					if (!helper.Parent()) break;
				}
			}
			res.push_back(item);
		}
	}
	if (!res.empty) {
		Log(2, 'RESULTS                 : ' + res.count);
		cmd.SetFiles(res);
		cmd.RunCommand('SELECT FROMSCRIPT HIDEUNSEL DESELECTNOMATCH');
		cmd.RunCommand('SELECT FIRST');
	}
	else {
		Log(2, 'No results could be found');
		cmd.RunCommand('SELECT NONE HIDEUNSEL');
	}
	res = null;
	item = null;
}

function BuildListFromPreset(tab, cmd, obj_query, obj_col) {
	Log(2, 'FILTERING VIA RENAME IN COLUMN "' + obj_col.name + '" FOR: ' + tab.all.count + ' ITEMS');
	var res = DOpus.Create.Vector();
	var DOvar = 'colsearch_helper';
	var item, a, eval_map;
	cmd.SetFiles(tab.all);
	DOpus.Vars.Delete(DOvar);
	try {
		if (CreateRenamePresetTxt(DOvar, '{=Val("' + obj_col.name + '")=}')) {
			cmd.RunCommand('RENAME PRESET="' + DOvar + '"');
			if (DOpus.Vars.Exists(DOvar)) {
				eval_map = DOpus.Vars.Get(DOvar);
				Log(1, 'ITEMS RETRIEVED         : ' + eval_map.length);
			}
			else
				Log(3, 'DOpus var ' + DOvar + ' doesn\'t exist!');
		}
		else
			Log(3, 'Unable to write rename preset file !!!');
		if (eval_map.length > 0) {
			for (var e = new Enumerator(eval_map); !e.atEnd(); e.moveNext()) {
				a = false;
				try {
					item = (obj_col.category == 'string') ? eval_map(e.item()) : convertType(obj_col.category, eval_map(e.item()));
					if (!item || item == null) {
						continue;
					}
					switch (obj_col.category) {
						case 'date':
							a = compareDates(item, obj_query.query, obj_query.raw_query, obj_query.operator);
							break;
						case 'duration':
						case 'number':
							a = compare(item, obj_query.query, obj_query.operator);
							break;
						case 'size':
							a = compareSizes(item, obj_query.query, obj_query.operator);
							break;
						default:
							a = compareStrings(item, obj_query.query, obj_query.operator);
					}
				}
				catch (err) {
					Log(3, 'Error when trying to get ' + obj_col.name + ' info for ' + item);
				}
				if (a) {
					item = FSU.GetItem(e.item());
					if (item.nested) {
						helper = item.path;
						while (String(helper) != String(tab.path)) {
							res.push_back(String(helper));
							if (!helper.Parent()) break;
						}
					}
					res.push_back(item);
				}
			}
		}
	}
	catch (e) {
		Log(3, 'Error when trying to get values for column ' + obj_col.name);
	}
	if (!res.empty) {
		Log(2, 'RESULTS                 : ' + res.count);
		cmd.SetFiles(res);
		cmd.RunCommand('SELECT FROMSCRIPT HIDEUNSEL DESELECTNOMATCH');
		cmd.RunCommand('SELECT FIRST');
	}
	else {
		Log(2, 'No results could be found');
		cmd.RunCommand('SELECT NONE HIDEUNSEL');
	}
	//Delete the global var used
	DOpus.Vars.Delete(DOvar);
	//Delete the renmae preset created
	DOvar = DOpus.Aliases('dopusdata').path + '\\Rename Presets\\' + DOvar + '.orp';
	cmd.ClearFiles();
	cmd.RunCommand('DELETE "' + DOvar + '" NORECYCLE FORCE QUIET');
	eval_map = null;
	res = null;
}

function BuildFilterFromDialog(tab, cmd, arg_values) {
	Log(2, 'dialog                  : ' + arg_values);
	if (typeof arg_values !== 'string') {
		Log(4, 'Unable to continue without a column!');
		return '';
	}
	arg_values = arg_values.toLowerCase().split(',');
	var colname, show_all;
	if (custom_names_map === undefined) custom_names_map = Script.config.custom_columns_names.empty ? null : (Script.Vars.Exists('custom_columns_names') ? Script.Vars.Get('custom_columns_names') : getCustomMap('custom_columns_names', true, true));
	for (var i = 0; i < arg_values.length; i++) {
		if (arg_values[i] === 'filterall') show_all = true;
		else if (custom_names_map !== null && custom_names_map.Exists(arg_values[i])) {
			Log(1, arg_values[i] + ' => ' + custom_names_map(arg_values[i]));
			colname = custom_names_map(arg_values[i]);
		}
		else colname = arg_values[i];
	}
	arg_values = null;
	if (!colname) {
		Log(4, 'Unable to continue without a column!');
		return '';
	}
	var colheader;
	if (custom_categories_map === undefined) custom_categories_map = Script.Vars.Exists('custom_columns_categories') ? Script.Vars.Get('custom_columns_categories') : getCustomMap('custom_columns_categories', false, true);
	var map_columns = MapColHeaders();
	Log(1, 'Checking "' + colname + '" data...');
	if (colname.indexOf(':') !== -1) { //Evaluator,script,Shell column
		try {
			colheader = tab.format.columns(colname).header;
		}
		catch (err) {
			colheader = colname + ' ';
		}
		Log(1, 'Storing ' + colheader + ' in map');
		map_columns.Set(colheader, colname);
		map_columns.Set(colname, DOpus.Create.Map());
	}
	else if (!map_columns.Exists(colname)) {
		Log(4, 'Unable to continue without a column!');
		return '';
	}

	var dlg = {};
	dlg.gui = tab.Dlg();
	dlg.gui.template = 'simple';
	dlg.gui.title = script_label + ' v' + script_version;
	// dlg.gui.disable_window = tab;
	dlg.gui.Create();
	dlg.name = dlg.gui.Control('name_combo');
	dlg.query_edit = dlg.gui.Control('query_edit');
	dlg.clear_btn = dlg.gui.Control('clear_btn');
	dlg.category = dlg.gui.Control('category_combo');
	dlg.listview = dlg.gui.Control('listview');
	dlg.list_and = dlg.gui.Control('use_and_checkbox');
	dlg.more = dlg.gui.Control('more_options');
	dlg.message = dlg.gui.Control('message');
	dlg.total_title = dlg.gui.Control('total_title');
	dlg.to_coll = dlg.gui.Control('tocoll_btn');
	dlg.other_btn = dlg.gui.Control('other_btn');
	var colObj = DOpus.Create.Map();
	var values_map = DOpus.Create.Map();
	var files = DOpus.Create.UnorderedSet();
	var sel_values = DOpus.Create.UnorderedSet();
	var map_columns_enum = new Enumerator(map_columns);

	var collection_name = getCollPath('FilterByColumn');

	if (FSU.ComparePath(collection_name, tab.path, 'p')) {
		dlg.to_coll.enabled = false;
		collection_name = '';
	}

	updateNameCombo(dlg.name.value, true);

	dlg.listview.AddGroup('Checked', 1);
	dlg.listview.AddGroup('Values', 0);
	dlg.listview.EnableGroupView(true);

	dlg.gui.AddHotkey('focus_name', 'f2');
	dlg.gui.AddHotkey('focus_query', 'f3');
	dlg.gui.AddHotkey('custom_dialog', 'f4');
	dlg.gui.AddHotkey('refresh', 'f5');
	dlg.gui.AddHotkey('esc', 'Escape');
	dlg.gui.WatchTab(tab, 'navigate,activate,srcdst');
	dlg.gui.LoadPosition('fbc_dialog_simple');
	dlg.gui.Show();
	LoadValues(show_all, '');
	var msg, query, cat, max_item_length;
	var menu = DOpus.Create.Map();
	menu('string') = DOpus.Create.Vector('Start with...', 'Not start with...', 'Customize...');
	menu('number') = DOpus.Create.Vector('Between...', 'Customize...');
	menu('size') = DOpus.Create.Vector('Between...', 'Customize...');
	menu('duration') = DOpus.Create.Vector('Between...', 'Customize...');
	menu('date') = DOpus.Create.Vector('Today', 'Yesterday', 'This week', 'This month', 'This year', 'In month...', 'In day...', 'Time ago...', 'Between...', 'Customize...');
	while (true) {
		msg = dlg.gui.GetMsg();
		if (!msg.result) break;
		// Log(1, ' event : ' + msg.event + '; control : ' + msg.control);
		if (msg.event === 'tab') {
			// Log(1, ' tab change : ' + msg.value);
			if (msg.value)
				dlg.gui.EndDlg(0);
		}
		else if (msg.event === 'selchange' && msg.control === 'name_combo') {
			dlg.gui.KillTimer('update_list_timer');
			colheader = msg.value;
			colname = map_columns(colheader);
			Log(1, 'Changing to : ' + colname + '; header : ' + colheader);
			LoadValues(false, '');
		}
		else if (msg.event === 'editchange') {
			if (msg.control === 'query_edit')
				dlg.gui.SetTimer((dlg.query_edit.value !== '') ? 250 : 20, 'update_list_timer');
			else if (msg.control === 'name_combo')
				dlg.gui.SetTimer(400, 'update_name_timer');
		}

		else if (msg.control === 'listview') {
			if (msg.event === 'checked') {
				SelectFromDlg(msg.value, false, dlg.list_and.value);
			}
			else if (msg.event === 'dblclk') {
				SelectFromDlg(msg.value, 2, dlg.list_and.value);
			}
		}
		else if (msg.event === 'timer') {
			if (msg.control === 'update_list_timer')
				updateSugList(dlg.query_edit.value);
			else if (msg.control === 'update_name_timer')
				updateNameCombo(dlg.name.value);
		}
		else if (msg.event === 'hotkey') {
			if (msg.control === 'focus_name') dlg.name.focus = true;
			else if (msg.control === 'focus_query') dlg.query_edit.focus = true;
			else if (msg.control === 'esc') dlg.gui.EndDlg(0);
			else if (msg.control === 'refresh') LoadValues(true, dlg.query_edit.value);
			else if (msg.control === 'custom_dialog') {
				cat = dlg.category.value.name;
				query = showSubDialog(menu(cat).length, cat);
				if (query) {
					if (search_mode) dlg.gui.EndDlg(1);
					else {
						cmd.RunCommand('FilterbyColumn FILTER=visible' + query);
						query = '';
					}
				}
			}
		}
		else if (msg.event === 'click') {
			if (msg.control === 'tocoll_btn' && msg.focus) {
				try {
					tab.Update();
					cmd.SetFiles(tab.all);
					if (cmd.filecount) {
						if (FSU.Exists(collection_name)) cmd.RunCommand('@runonce Delete FILE="' + collection_name + '" FORCE QUIET');
						if (cmd.RunCommand('Copy COPYTOCOLL=member CREATEFOLDER="' + collection_name + '"')) {
							Log(2, 'Copied ' + cmd.filecount + ' items to ' + collection_name);
							cmd.RunCommand('@runonce Go "' + collection_name + '" NEWTAB=findexisting' + (msg.qualifiers === 'shift' ? ',nofocus' : ',tofront'));
						}
					}
				}
				catch (err) {
					Log(4, 'Unable to save items to collection! : ' + err.description);
				}
			}
			else if (msg.control === 'use_and_checkbox' && msg.focus) {
				SelectFromDlg(null, false, msg.data);
			}
			else if (msg.control === 'clear_btn' && msg.focus) {
				dlg.query_edit.value = '';
			}
			else if (msg.control === 'save_cat_btn' && msg.focus) {
				Log(2, 'Adding "' + colname + '":"' + dlg.category.value.name + '"');
				custom_categories_map(colname) = dlg.category.value.name;
				try {
					var saved_categories = Script.Vars.Exists('saved_categories') ? Script.Vars.Get('saved_categories') : DOpus.Create.Vector();
					saved_categories.push_back('"' + colname + '":"' + dlg.category.value.name + '"');
					Script.Vars.Set('saved_categories', saved_categories);
					if (!Script.Vars('saved_categories').persist) Script.Vars('saved_categories').persist = true;
					saved_categories = null;
				}
				catch (err) {
					Log(3, 'Unable to save category in config for this column : ' + err.description);
				}
			}
			else if (msg.control === 'other_btn') {
				if (msg.value === 'refresh') LoadValues(true, dlg.query_edit.value);
				else if (msg.value === 'clear') SelectFromDlg(null, 0, msg.data);
				else if (msg.value === 'swap') SelectFromDlg(null, 2, msg.data);
			}
			else if (msg.control === 'more_options') {
				cat = dlg.category.value.name;
				var dlgMenu = DOpus.Dlg();
				dlgMenu.choices = menu(cat);
				dlgMenu.menu = 0;
				query = showSubDialog(dlgMenu.Show(), cat);
				dlgMenu = null;
				if (query) {
					if (search_mode) dlg.gui.EndDlg(1);
					else {
						cmd.RunCommand('FilterbyColumn FILTER=visible' + query);
						query = '';
					}
				}
			}
		}

	}
	if (dlg.gui.result === 0) query = '';
	dlg.gui.SavePosition('fbc_dialog_simple');
	colObj = null;
	dlg = null;
	values_map = null;
	files = null;
	map_enum = null;
	map_columns = null;
	return query;

	function showSubDialog(entry, category) {
		Log(1, 'Selected option :' + entry);
		if (entry === 0) return '';
		var value;
		if (category === 'date' && entry <= 5) //'Today', 'Yesterday', 'This week', 'This month', 'This year'
			return ' QUERY ' + colname + '==' + menu(category)(entry - 1).toLowerCase().replace(' ', '');
		else if (category === 'date' && entry <= 7) { //'In month...', 'In day...'
			var dlgMenu = DOpus.Dlg();
			dlgMenu.choices = entry === 6 ? DOpus.Create.Vector('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December') :
				DOpus.Create.Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31);
			dlgMenu.menu = 0;
			value = dlgMenu.Show();
			dlgMenu = null;
			return value !== 0 ? (' QUERY ' + colname + '==' + value + (entry === 6 ? 'm' : 'd')) : '';
		}
		var error = false;
		var customized = menu(category)(entry - 1) === 'Customize...';
		var between = menu(category)(entry - 1) === 'Between...';
		var time_ago = menu(category)(entry - 1) === 'Time ago...';
		var customize_str = customized && category === 'string' && entry > 2;
		var dlg_height = customize_str ? 66 : 42;
		var dlg_width = time_ago ? 176 : 268;

		template = '<resources><resource name="subdialog" type="dialog">';
		template += '<dialog fontsize="9" height="' + dlg_height + '" lang="english" standard_buttons="cancel" width="' + dlg_width + '">';
		template += '<languages><language height="' + dlg_height + '" lang="esm" width="' + dlg_width + '" /></languages>';
		if (customized || category === 'string') {
			template += '<control height="40" ' + (customized ? '' : 'enable="no" ') + 'name="operator_combo" type="combo" width="26" x="6" y="8" />';
			template += '<control edit="yes" height="40" name="query_combo" resize="w" type="combo" width="228" x="36" y="8" />';
			if (customize_str) {
				template += '<control height="10" name="casem_chk" title="' + DOpus.strings.Get('flag0') + '" type="check" width="76" x="10" y="22" />';
				template += '<control height="10" name="ign_chk" title="' + DOpus.strings.Get('flag3') + '" type="check" width="76" x="102" y="22" />';
				template += '<control height="10" name="ww_chk" title="' + DOpus.strings.Get('flag1') + '" type="check" width="76" x="182" y="22" />';
				template += '<control height="10" name="regex_chk" title="' + DOpus.strings.Get('flag2') + '" type="check" width="76" x="10" y="34" />';
				template += '<control height="10" name="wild_chk" title="' + DOpus.strings.Get('flag5') + '" type="check" width="100" x="102" y="34" />';
			}
		}
		else if (time_ago) {
			template += '<control name="lower_combo" halign="left" height="12" number="yes" type="edit" width="28" x="28" y="8" />';
			template += '<control name="upper_combo" type="combo" edit="yes" height="40" width="110" x="60" y="8" />';
			template += '<control name="static1" halign="center" type="static" valign="center" height="8" title="&gt;=" width="20" x="6" y="10">';
			template += '<languages><language lang="esm" height="8" title="&gt;=" width="20" x="126" y="10" /></languages></control>';
		}
		else {
			template += '<control name="lower_combo" edit="yes" height="40" type="combo" width="100" x="6" y="8" />';
			template += '<control name="upper_combo" type="combo" edit="yes" height="40" width="100" x="164" y="8" />';
			template += '<control name="static1" halign="center" type="static" valign="center" height="8" title="and" width="20" x="126" y="10">';
			template += '<languages><language height="8" lang="esm" title="y" width="20" x="126" y="10" /></languages></control>';
		}
		dlg_height -= 18;
		dlg_width -= 106;
		template += '<control height="14" name="search_btn" title="Search" type="button" width="50" x="' + dlg_width + '" y="' + dlg_height + '">';
		template += '<languages><language height="14" lang="esm" title="&amp;Buscar" width="50" x="' + dlg_width + '" y="' + dlg_height + '" /></languages></control>';
		dlg_width -= 52;
		template += '<control default="yes" height="14" name="filter_btn" title="Filter" type="button" width="50" x="' + dlg_width + '" y="' + dlg_height + '">';
		template += '<languages><language height="14" lang="esm" title="&amp;Filtrar" width="50" x="' + dlg_width + '" y="' + dlg_height + '" /></languages></control>';
		template += '</dialog></resource></resources>';

		var dlgsub = {};
		try {
			dlgsub.gui = DOpus.Dlg();
			dlgsub.gui.template = template;
			dlgsub.gui.title = script_label + ' v' + script_version + ' - ' + colheader + ' : ' + menu(category)(entry - 1);
			dlgsub.gui.window = dlg.gui;
			dlgsub.gui.disable_window = dlg.gui;
			dlgsub.gui.Create();
		}
		catch (err) {
			Log(4, 'Unable to create the dialog!');
			error = true;
		}
		if (error) return '';
		if (between || time_ago) {
			dlgsub.lower = dlgsub.gui.Control('lower_combo');
			dlgsub.upper = dlgsub.gui.Control('upper_combo');
			if (between) {
				setSubValues(dlgsub.lower);
				setSubValues(dlgsub.upper);
			}
			else {
				dlgsub.upper.AddItem('hours ago from now');
				dlgsub.upper.AddItem('days ago from now');
				dlgsub.upper.AddItem('months ago from now');
				dlgsub.upper.AddItem('years ago from now');
			}
		}
		else {
			dlgsub.query = dlgsub.gui.Control('query_combo');
			setSubValues(dlgsub.query);
		}
		if (customized) {
			dlgsub.operator = dlgsub.gui.Control('operator_combo');
			setOperators(dlgsub.operator, category);
		}
		dlgsub.filter = dlgsub.gui.Control('filter_btn');
		dlgsub.search = dlgsub.gui.Control('search_btn');
		dlgsub.filter.enabled = dlgsub.search.enabled = false;
		dlgsub.gui.WatchTab(tab, 'navigate,activate,srcdst');
		dlgsub.gui.Show();
		var msg, value, query = '';
		while (true) {
			msg = dlgsub.gui.GetMsg();
			if (!msg.result) break;
			// Log(1, ' event : ' + msg.event + '; control : ' + msg.control);
			if (msg.event === 'tab') {
				if (msg.value)
					dlgsub.gui.EndDlg(0);
			}
			else if (msg.event === 'editchange' || msg.event === 'selchange') {
				if (msg.control === 'query_combo')
					dlgsub.filter.enabled = dlgsub.search.enabled = msg.value ? true : false;
				else if (msg.control === 'lower_combo' || msg.control === 'upper_combo') {
					if (time_ago) value = dlgsub.lower.value && dlgsub.upper.value.name ? true : false;
					else value = dlgsub.lower.value.name && dlgsub.upper.value.name ? true : false;
					dlgsub.filter.enabled = dlgsub.search.enabled = value;
				}
			}
			if (msg.event === 'click') {
				if (msg.control === 'regex_chk' && msg.focus) {
					if (msg.data) dlgsub.gui.Control('wild_chk').value = false;
				}
				else if (msg.control === 'wild_chk' && msg.focus) {
					if (msg.data) dlgsub.gui.Control('regex_chk').value = false;
				}
				else if (msg.control.slice(-4) === '_btn') {
					query = '';
					search_mode = msg.control === 'search_btn';
					g_flags = 0;
					if (category === 'string' && entry <= 2) {
						if (search_mode) g_flags += (1 << 2);
						else query = ' REGEXP QUERY ';
						query += colname + (entry === 2 ? '!=^' : '==^') + dlgsub.query.value.name;
					}
					else {
						if (customize_str) {
							if (dlgsub.gui.Control('casem_chk').value) search_mode ? g_flags += (1 << 0) : query += ' CASE';
							if (dlgsub.gui.Control('ww_chk').value) search_mode ? g_flags += (1 << 1) : query += ' WHOLEWORDS';
							if (dlgsub.gui.Control('ign_chk').value) search_mode ? g_flags += (1 << 3) : query += ' NODIACRITICS';
							if (dlgsub.gui.Control('wild_chk').value) search_mode ? use_wildcards = true : query += ' USEWILD';
							if (dlgsub.gui.Control('regex_chk').value) search_mode ? g_flags += (1 << 2) : query += ' REGEXP';
						}
						if (!search_mode) query += ' QUERY ';
						if (between)
							query += colname + '==' + dlgsub.lower.value.name + '..' + dlgsub.upper.value.name;
						else if (time_ago) {
							query += colname + '>=' + dlgsub.lower.value + dlgsub.upper.value.name.charAt(0) + 'a';
						}
						else
							query += colname + dlgsub.operator.value.name + dlgsub.query.value.name;
					}
					dlgsub.gui.EndDlg(1);
				}
			}
		}
		if (dlgsub.gui.result === 0) query = '';
		dlgsub = null;
		return query;
	}

	function LoadValues(reload, query_value) {
		dlg.name.enabled = false;
		dlg.query_edit.enabled = false;
		dlg.clear_btn.enabled = false;
		dlg.listview.enabled = false;
		dlg.category.enabled = false;
		dlg.to_coll.enabled = false;
		dlg.more.visible = false;
		dlg.other_btn.enabled = false;
		values_map.clear();
		sel_values.clear();
		dlg.message.enabled = true;
		dlg.message.visible = true;
		dlg.message.label = 'Gathering values. Please wait...';
		if (!map_columns(colname).empty) {
			Log(1, '   Getting previous saved data');
			colObj.assign(map_columns(colname));
		}
		else {
			if (colname.indexOf(':') !== -1) { //Evaluator,script,Shell column
				// cat = custom_categories_map.Exists(colname) ? custom_categories_map(colname) : '';
				colObj('category') = custom_categories_map.Exists(colname) ? custom_categories_map(colname) : '';
				colObj('builtin') = false;
				colObj('multi') = false;
				colObj('metatype') = null;
				colObj('property') = null;
			}
			else {
				colObj = getColumnData(colname);
				// cat = colObj('category') || '';
			}
			map_columns(colname).assign(colObj);
		}
		Log(1, '   => category : ' + colObj('category') + ' ; builtin : ' + colObj('builtin') + ' ; multi : ' + colObj('multi') + ' ; metatype : ' + colObj('metatype') + ' ; property : ' + colObj('property'));
		if (reload) {
			Log(1, '   Reloading tab data...');
			cmd.RunCommand('SELECT NOPATTERN SHOWHIDDEN');
		}
		tab.Update();

		if (!colObj('category')) {
			Log(3, '   ' + colname + ' doesn\'t have a valid category!');
			dlg.gui.Control('save_cat_btn').enabled = true;
		}
		setCategoryCombo(dlg.category, colObj('category'));

		getColValues(colname);

		map_enum = new Enumerator(values_map);
		max_item_length = 0;
		for (; !map_enum.atEnd(); map_enum.moveNext()) {
			var item = map_enum.item();
			if (max_item_length < values_map(item).count) max_item_length = values_map(item).count;
		}
		max_item_length = String(max_item_length).length;
		Log(1, '   max_item_length : ' + max_item_length);
		dlg.message.label = '';
		dlg.message.enabled = false;
		dlg.message.visible = false;

		dlg.name.enabled = true;
		dlg.query_edit.enabled = true;
		dlg.clear_btn.enabled = true;
		dlg.listview.enabled = true;
		dlg.category.enabled = true;
		dlg.more.visible = true;
		dlg.other_btn.enabled = true;
		if (collection_name && !values_map.empty) dlg.to_coll.enabled = true;
		dlg.list_and.enabled = colObj('multi');
		if (dlg.query_edit.value === query_value) updateSugList(query_value);
		else dlg.query_edit.value = query_value;
		dlg.query_edit.focus = true;
		return;
	}

	function getColValues(colname) {
		Log(1, '   Getting new column values for "' + colname + '" : ' + tab.stats.items + ' items');
		if (colObj('builtin')) getBuiltInValues(colname);
		else getOtherColValues(colname);
		return;
	}

	function getBuiltInValues(colname) {
		var ini = new Date();
		var metatype, item, helper, value, h;
		if (colname === 'extdir') h = str_tools.LanguageStr(2132);
		else if (colname === 'attr') h = DOpus.Create.Map('r', str_tools.LanguageStr(6135), 'h', str_tools.LanguageStr(6134), 's', str_tools.LanguageStr(1215), 'a', str_tools.LanguageStr(6131), 'c', str_tools.LanguageStr(1213), 'o', str_tools.LanguageStr(6177), 'i', str_tools.LanguageStr(6178), 'e', str_tools.LanguageStr(1214), 'p', str_tools.LanguageStr(6179));

		for (var i = 0; i < tab.all.count; i++) {
			if (dlg.gui.result !== undefined) break;
			value = null;
			item = tab.all(i);
			try {
				if (colname === 'name')
					value = tab.format.hide_ext ? item.name_stem_m : item.name;
				else if (colname === 'ext') {
					if (value = item.ext.toLowerCase()) value = value.slice(1);
				}
				else if (colname === 'extdir') {
					if (item.is_dir)
						value = h;
					else if (value = item.ext.toLowerCase()) value = value.slice(1);
				}
				else if (colname === 'attr') {
					helper = item.attr_text.replace(/\-/g, '');
					if (!helper) value = '';
					else {
						for (var k = 0; k < helper.length; k++) {
							if (!values_map.Exists(h(helper.charAt(k)))) values_map(h(helper.charAt(k))) = DOpus.Create.UnorderedSet();
							values_map(h(helper.charAt(k))).insert(item + '');
						}
					}
				}
				else if (colname === 'keywords') {
					helper = item.metadata.tags;
					if (!helper.count) value = '';
					else {
						for (var k = 0; k < helper.count; k++) {
							if (helper(k).toLowerCase()) {
								if (!values_map.Exists(helper(k))) values_map(helper(k)) = DOpus.Create.UnorderedSet();
								values_map(helper(k)).insert(item + '');
							}
						}
					}
				}
				else if (colname === 'label') {
					helper = item.Labels("*", "explicit");
					if (!helper.count) value = '';
					else {
						for (var k = 0; k < helper.count; k++) {
							if (helper = item.metadata.tags(k).toLowerCase()) {
								if (!values_map.Exists(helper)) values_map(helper) = DOpus.Create.UnorderedSet();
								values_map(helper).insert(item + '');
							}
						}
					}
				}
				else if (colname === 'parent')
					value = item.realpath.Parent().filepart;
				else if (colname === 'parentlocation')
					value = item.realpath.Parent().filepart + ' (' + item.realpath.Parent().pathpart + ')';
				else if (colname === 'parentpath')
					value = item.realpath.Parent().pathpart;
				else if (colname === 'path')
					value = item.realpath.pathpart;
				else if (colname === 'pathlen')
					value = String(item).length;
				else if (colname === 'pathrel')
					value = String(item.realpath).replace(String(tab.path), '');
				else if (colname === 'desc') {
					value = item.metadata.other.usercomment ? item.metadata.other.usercomment : '';
					value += (item.metadata.other.autodesc ? ((value ? ' - ' : '') + item.metadata.other.autodesc) : '');
				}
				else if (colname === 'sizeauto')
					value = item[colObj('property')].fmt;
				else if (colname === 'sizekb')
					value = item[colObj('property')] / 1024 + ' kb';
				else if (colname.slice(-4) === 'time' && !colObj('metatype')) {
					value = item[colObj('property')];
					if (value) value = value.Format('t', 'S');
				}
				else {
					metatype = colObj('metatype');
					if (metatype === true) value = item.metadata[item.metadata + ''][colObj('property')];
					else if (metatype && typeof metatype === 'string') value = item.metadata[metatype][colObj('property')];
					else value = item[colObj('property')];
					if (value && DOpus.TypeOf(value) === 'object.Date') {
						value = value.Format('', 'ns');
					}
				}
				if (value !== null) {
					if (value === '') value = '<empty value>';
					if (!values_map.Exists(value)) values_map(value) = DOpus.Create.UnorderedSet();
					values_map(value).insert(item + '');
				}
			}
			catch (err) {
				Log(3, '   => Error reading ' + colname + ' in ' + item + ' : ' + err);
			}
		}
		h = null;
		helper = null;
		Log(1, '   => Built in cols done in : ' + (new Date() - ini) + ' ms');
		return;
	}

	function getOtherColValues(colname) {
		var ini = new Date();
		cmd.SetFiles(tab.all);
		var cmdline = '';
		var value, line;
		cmdline += 'fullpath + "\t" + (Val("' + colname + '") as str) + "\n"';
		DOpus.Vars.Set('fbc', '');
		if (cmdline) {
			cmd.RunCommand('Select NONE');
			cmdline = 'Select FILTERDEF =$glob:fbc+=' + cmdline + '; return false;';
			cmd.RunCommand(cmdline);
			DOpus.Delay(20);
			if (DOpus.Vars.Exists('fbc')) {
				value = DOpus.Vars.Get('fbc').split('\n');
				for (var i = 0; i < value.length; i++) {
					if (value[i]) {
						line = value[i].split('\t');
						// Log(1, 'value : "' + line[1] + '"');
						if (line[1] === '') line[1] = '<empty value>';
						if (!values_map.Exists(line[1])) values_map(line[1]) = DOpus.Create.UnorderedSet();
						values_map(line[1]).insert(line[0]);
					}
				}
			}
		}
		DOpus.Vars.Delete('fbc');
		Log(1, '   => Other cols done in : ' + (new Date() - ini));
		return;
	}

	function setCategoryCombo(control, category) {
		Log(1, '   Setting category...');
		with(control) {
			redraw = false;
			RemoveItem(-1);
			if (category) AddItem(category);
			else {
				AddItem('string');
				AddItem('number');
				AddItem('date');
				AddItem('size');
				AddItem('duration');
			}
			redraw = true;
			value = 0;
		}
		return;
	}

	function setOperators(control, category) {
		with(control) {
			AddItem('==');
			AddItem('!=');
			if (category !== 'string') {
				AddItem('>');
				AddItem('>=');
				AddItem('<');
				AddItem('<=');
			}
			value = 0;
		}
		return;
	}

	function setSubValues(control) {
		map_enum.moveFirst();
		for (; !map_enum.atEnd(); map_enum.moveNext())
			control.AddItem(map_enum.item());
		return;
	}

	function updateNameCombo(ctrl_value, first) {
		Log(1, 'Updating column combobox => value : ' + ctrl_value.name);
		dlg.gui.KillTimer('update_name_timer');
		if (!first && ctrl_value.index !== -1) return;
		var value = ctrl_value.name || '';
		var item;
		if (value) var regex = new RegExp(value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i');
		dlg.name.redraw = false;
		dlg.name.RemoveItem(-1);
		map_columns_enum.moveFirst();
		for (; !map_columns_enum.atEnd(); map_columns_enum.moveNext()) {
			item = map_columns_enum.item();
			if (DOpus.TypeOf(map_columns(item)) === 'object.Map') continue;
			if (value === '' || regex.test(item)) {
				dlg.name.AddItem(item);
				if (!colheader && map_columns(item) === colname)
					colheader = item;
			}
		}
		dlg.name.redraw = true;
		dlg.name.label = ctrl_value.name;
		if (first) dlg.name.value = dlg.name.getItemByName(colheader);
		return;
	}

	function updateSugList(value) {
		Log(1, 'Updating list : ' + colname + '; value : ' + value);
		dlg.gui.KillTimer('update_list_timer');
		dlg.listview.redraw = false;
		dlg.listview.RemoveItem(-1);
		if (value) var regex = new RegExp(str_tools.RemoveDiacritics(value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')), 'i');
		map_enum.moveFirst();
		var total = 0;
		for (; !map_enum.atEnd(); map_enum.moveNext()) {
			item = map_enum.item();
			if (sel_values.Exists(item)) {
				total += values_map(item).count;
				fila = dlg.listview.getItemAt(dlg.listview.AddItem(item, 0, 1));
				fila.checked = 1;
				fila.subitems(0) = ZeroPad(values_map(item).count, max_item_length);

			}
			else if (value === '' || regex.test(item)) {
				fila = dlg.listview.getItemAt(dlg.listview.AddItem(item, 0, 0));
				fila.subitems(0) = ZeroPad(values_map(item).count, max_item_length);
			}
		}
		dlg.listview.columns.autosize();
		dlg.listview.columns.GetColumnAt(1).sort = -1;
		dlg.listview.redraw = true;
		dlg.total_title.label = total + ' / ' + tab.stats.items + ' items';
		return;
	}

	function SelectFromDlg(value, check, is_and) {
		if (typeof value === 'number' && value >= dlg.listview.count) return;
		// Log(1, 'Selecting items => mode : ' + value);
		var fila;
		files.Clear();
		if (value !== -1) {
			dlg.listview.redraw = false;
			var count = value === null ? dlg.listview.count : 1;
			for (var i = 0; i < count; i++) {
				fila = value === null ? dlg.listview.getItemAt(i) : dlg.listview.getItemByName(value);
				if (check !== false) fila.checked = check === 2 ? (fila.checked === 1 ? 0 : 1) : check;
				if (fila.checked === 1) sel_values.insert(fila.name);
				else sel_values.erase(fila.name);
				fila.group = fila.checked;
			}
			dlg.listview.columns.GetColumnAt(1).sort = -1;
			dlg.listview.redraw = true;
		}
		for (var i = 0; i < sel_values.length; i++) {
			if (is_and) {
				if (files.empty) files.assign(values_map(sel_values(i)));
				else {
					var j = 0;
					while (j < files.length) {
						if (!values_map(sel_values(i)).Exists(files(j))) files.erase(files(j));
						else j++;
					}
				}
			}
			else {
				if (files.empty) files.assign(values_map(sel_values(i)));
				else files.merge(values_map(sel_values(i)));
			}
		}
		dlg.total_title.label = files.count + ' / ' + tab.stats.items + ' items';
		cmd.RunCommand('Select NONE SHOWHIDDEN');
		if (!files.empty) {
			cmd.SetFiles(files);
			cmd.RunCommand('Select FROMSCRIPT HIDEUNSEL DESELECTNOMATCH');
			cmd.RunCommand('Select FIRST');
		}
		else if (!sel_values.empty) cmd.RunCommand('Select NOPATTERN HIDEUNSEL');
		else {
			cmd.SetFiles(tab.all);
			cmd.RunCommand('Select FROMSCRIPT HIDEUNSEL DESELECTNOMATCH');
			cmd.RunCommand('Select FIRST');
		}
		return;
	}

}

function BuildListFromFilter(tab, cmd, obj_query, obj_col, isFilter) {
	Log(2, 'FILTERING VIA TEXTUAL FILTERS IN COLUMN "' + obj_col.name + '" FOR: ' + (!isFilter ? tab.path : (tab.all.count + ' ITEMS')));
	var operator = obj_query.operator;
	var query = obj_query.query;
	var cmdline = '';
	if (!isFilter) var desc = '';
	var col_name = obj_col.name.indexOf(':') !== -1 ? 'Val("' + obj_col.name + '")' : obj_col.name;
	switch (obj_col.category) {
		case 'string':
			var flags = (g_flags & (1 << 0) ? 'c' : '') + (g_flags & (1 << 1) ? '' : 'p') + (g_flags & (1 << 3) ? 'i' : '');
			if (DOpus.TypeOf(query) === 'object.Vector') {
				if (g_flags & (1 << 2)) flags += 'r';
				else if (!use_wildcards) {
					var wild = FSU.NewWild();
					query[0] = wild.EscapeString(query[0]);
					query[1] = wild.EscapeString(query[1]);
					wild = null;
				}
				cmdline = ((operator == '!=') ? 'return !(' : 'return (') + 'Match(' + col_name + ',"' + query[0] + '","fpi") and (';
				cmdline += '"' + query[1] + '"=="" or Match(' + col_name + ',"' + query[1] + '"';
				cmdline += flags ? (',"' + flags + '")))') : ')))';
				if (!isFilter) desc = obj_col.name + ' : value ' + operator + obj_query.raw_query;
			}
			else {
				if (g_flags & (1 << 2)) flags += 'r';
				else if (!use_wildcards) {
					var wild = FSU.NewWild();
					query = wild.EscapeString(query);
					wild = null;
				}
				cmdline = ((operator == "!=") ? 'return !' : 'return ') + 'Match(' + col_name + ',"' + query + '"';
				cmdline += flags ? (',"' + flags + '")') : ')';
				if (!isFilter) desc = obj_col.name + ' : value ' + operator + query;
			}
			break;
		case 'duration':
			var regex = '^(\\d+)d (\\d+):(\\d+):(\\d+)$|^(\\d+):(\\d+):(\\d+)$|^(\\d+):(\\d+)$';
			cmdline = 'dur = ' + col_name + ';';
			cmdline += 'day=RegEx(dur, "' + regex + '", "\\1","e") as uint * 86400;';
			cmdline += 'hr=RegEx(dur, "' + regex + '", "\\2\\5","e") as uint * 3600;';
			cmdline += 'minutes=RegEx(dur, "' + regex + '", "\\3\\6\\8","e") as uint * 60;';
			cmdline += 'sec=RegEx(dur, "' + regex + '", "\\4\\7\\9","e") as uint;';
			cmdline += 'dur = day + hr + minutes + sec == 0 ? dur : day + hr + minutes + sec;';
			if (DOpus.TypeOf(query) == 'object.Vector') { //query is a range between 2 values (inclusive)
				cmdline += 'return (dur' + ((operator == "!=") ? '<' : ' >= ') + query(0);
				cmdline += ((operator == "!=") ? ' or ' : ' and ');
				cmdline += 'dur' + ((operator == "!=") ? '>' : ' <= ') + query(1) + ')';
			}
			else {
				cmdline += 'return dur' + operator + " " + query;
			}
			if (!isFilter) desc = obj_col.name + ' : value ' + operator + obj_query.raw_query;
			break;
		case 'number':
		case 'size':
			if (DOpus.TypeOf(query) == 'object.Vector') { //query is a range between 2 values (inclusive)
				cmdline = 'return (' + col_name + ((operator == "!=") ? '<' : ' >= ') + query(0);
				cmdline += ((operator == "!=") ? ' or ' : ' and ');
				cmdline += 'Val("' + obj_col.name + '")' + ((operator == "!=") ? '>' : ' <= ') + query(1) + ')';
			}
			else {
				cmdline = 'return ' + col_name + operator + " " + query;
			}
			if (!isFilter) desc = obj_col.name + ' : value ' + operator + obj_query.raw_query;
			break;
		case 'date':
			switch (obj_query.raw_query) {
				case 'thisyear':
				case 'year':
				case 'lastyear':
				case 'lyear':
					cmdline = 'year=DatePart((' + col_name + ' as date),"yyyy");';
					cmdline += 'return year' + operator + query(0).year;
					if (!isFilter) desc = obj_col.name + ' : value ' + operator + query(0).year;
					break;
				case 'rwhole':
					DateRange('"s"', query(0).Format("D#yyyy-MM-dd T#HH:mm:ss"), query(1).Format("D#yyyy-MM-dd T#HH:mm:ss"), query(0).sec == 0 ? '"D#yyyy-MM-dd T#HH:mm"' : 'date', query(1).sec == 0 ? '"D#yyyy-MM-dd T#HH:mm"' : 'date');
					break;
				case 'ryear':
				case 'rmyear':
				case 'rdate':
				case 'thismonth':
				case 'month':
				case 'lastmonth':
				case 'lmonth':
				case 'thisweek':
				case 'week':
				case 'lastweek':
				case 'lweek':
					DateRange('"d"', query(0).Format("D#yyyy-MM-dd"), query(1).Format("D#yyyy-MM-dd"), 'date', 'date');
					break;
				case 'today':
				case 'yesterday':
				case 'tomorrow':
				case 'ya':
				case 'Ma':
				case 'da':
				case 'd':
					DateDiff(query.Format('D#yyyy-MM-dd'), '"D#yyyy-MM-dd"', 'd');
					break;
				case 'whole':
				case 'ha':
					DateDiff(query.Format('D#yyyy-MM-dd T#HH:mm:ss'), 'date', 's');
					break;
				case 'sD':
					DateDiff(query.Format('D#yyyy-MM-dd T#HH:mm'), '"D#yyyy-MM-dd T#HH:mm"', 's');
					break;
				case 't':
					DateDiff(query.Format('T#HH:mm:ss'), '"T#HH:mm:ss"', 's');
					break;
				case 'day': //query is a number referring to a day
					DatePart(query, 'day', 'd');
					break;
				case 'm': //query is a number referring to a month
					DatePart(query, 'month', 'M');
					break;
				case 'tsD': //query is a number referring to seconds in HH:mm
					cmdline = 'hour=DatePart((' + col_name + ' as date),"H") as int;';
					cmdline += 'minutes=DatePart((' + col_name + ' as date),"m") as int;';
					cmdline += 'return ((hour * 3600 + minutes * 60 )' + operator + query + ')';
					if (!isFilter) desc = obj_col.name + ' : HH:mm in secs' + operator + query;
					break;
			}
			break;
	}
	if (cmdline) {
		cmdline = '=if (IsSet("' + obj_col.name + '")){' + cmdline + ';} else {return false;}';;
		Log(1, '   Filter defined       : ' + cmdline);
		try {
			var collname = getCollPath('FilterByColumn', obj_col.name);
			if (tab.path + '' == collname && !Script.config['create subcollections']) {
				Log(3, '   Unable to use search mode in this path, since is a results collection from a previous search');
				isFilter = true;
			}
			if (isFilter) {
				cmd.SetFiles(tab.all);
				cmd.SetModifier('runonce');
			}
			else if (!Script.config['create subcollections']) cmd.RunCommand('Go TABCLOSE=dest PATH="' + collname + '"');
			cmdline = (isFilter ? 'SELECT DESELECTNOMATCH HIDEUNSEL FILTERDEF ' :
				('FIND IN "' + tab.path + '" RECURSE=yes SHOWRESULTS=dest,tab COLLNAME="' + collname + '" FILTERDEF ')) + cmdline;
			if (cmd.RunCommand(cmdline)) {
				if (isFilter) cmd.RunCommand('SELECT FIRST');
				else {
					Log(1, '   Results collection   : ' + collname);
					cmd.RunCommand('SET FOCUS=Dest');
					if (Script.config['add column']) {
						tab.lister.Update();
						if (tab.lister.activetab.path == collname) {
							cmdline = 'SET COLUMNSADD "' + obj_col.name + '"';
							cmd.SetSourceTab(tab.lister.activetab);
							cmd.RunCommand(cmdline);
						}
					}
					cmdline = 'SetAttr "' + collname + '" DESCRIPTION "' + desc.replace(/"/g, '\'') + '"';
					cmd.RunCommand(cmdline);
				}
			}
			else Log(3, '   Error in :' + cmdline);
		}
		catch (err) {
			Log(3, '   Error running the command : ' + err);
		}
	}
	else Log(4, '   Unable to build a filter!!!');
	return;

	function DateRange(diff, date1, date2, as_value1, as_value2) {
		cmdline = 'diffa=DateDiff(' + diff + ',"' + date1 + '",(' + col_name + ' as ' + as_value1 + '));';
		cmdline += 'diffb=DateDiff(' + diff + ',"' + date2 + '",(' + col_name + ' as ' + as_value2 + '));';
		switch (operator) {
			case '==':
				cmdline += 'return (diffa>=0 and diffb<=0' + ')';
				if (!isFilter) desc = obj_col.name + ' : value >=' + date1 + ' and value <= ' + date2;
				break;
			case '!=':
				cmdline += 'return (diffa<0 or diffb>0' + ')';
				if (!isFilter) desc = obj_col.name + ' : value <' + date1 + ' or value > ' + date2;
				break;
			case '>':
			case '<=':
				cmdline += 'return diffb' + operator + '0';
				if (!isFilter) desc = obj_col.name + ' : value ' + operator + date2;
				break;
			case '>=':
			case '<':
				cmdline += 'return diffa' + operator + '0';
				if (!isFilter) desc = obj_col.name + ' : value ' + operator + date1;
				break;
		}
		return;
	}

	function DateDiff(date, as_value, comp) {
		cmdline = 'diff=DateDiff("' + comp + '","' + date + '",(' + col_name + ' as ' + as_value + '));';
		cmdline += 'return diff' + operator + '0';
		if (!isFilter) desc = obj_col.name + ' : value ' + operator + date;
		return;
	}

	function DatePart(value, value_name, type) {
		cmdline = value_name + '=DatePart((' + col_name + ' as date),"' + type + '");';
		if (DOpus.TypeOf(value) == 'object.Vector') {
			if (operator == '==') {
				cmdline += 'return (' + value_name + ' >= ' + value(0) + ' and ' + value_name + ' <= ' + value(1) + ')';
				if (!isFilter) desc = obj_col.name + ' : ' + value_name + ' >=' + value(0) + ' and ' + value_name + ' <= ' + value(1);
			}
			else {
				cmdline += 'return (' + value_name + ' < ' + value(0) + ' or ' + value_name + ' > ' + value(1) + ')';
				if (!isFilter) desc = obj_col.name + ' : ' + value_name + ' <' + value(0) + ' or ' + value_name + ' > ' + value(1);
			}
		}
		else {
			cmdline += 'return ' + value_name + '' + operator + value;
			if (!isFilter) desc = obj_col.name + ' : ' + value_name + ' ' + operator + value;
		}
		return;
	}
}

function compare(value1, value2, operator) {
	if (value1 == undefined) value1 = 0;
	if (DOpus.TypeOf(value2) == 'object.Vector') { //value2 is a range between 2 values (inclusive)
		return (operator == "!=") ? !(value2(0) <= value1 && value1 <= value2(1)) : (value2(0) <= value1 && value1 <= value2(1));
	}
	else switch (operator) {
		case '>=':
			return (value1 >= value2);
		case '<=':
			return (value1 <= value2);
		case '>':
			return (value1 > value2);
		case '<':
			return (value1 < value2);
		case '!=':
			return (value1 != value2);
		default:
			return (value1 == value2);
	}
}

function compareSizes(item, query, operator) {
	if (DOpus.TypeOf(item) != 'object.FileSize') return false;
	if (DOpus.TypeOf(query) == 'object.Vector') { //query is a range between 2 values (inclusive)
		return (operator == "!=") ? !(compare(item.Compare(query(0)), 0, ">=") && compare(item.Compare(query(1)), 0, "<=")) : (compare(item.Compare(query(0)), 0, ">=") && compare(item.Compare(query(1)), 0, "<="));
	}
	else {
		return compare(item.Compare(query), 0, operator);
	}
}

function compareGroup(item, values, operator) {
	var name = item.name;
	if (name == undefined) name = '';
	else if (g_flags & (1 << 3)) name = str_tools.RemoveDiacritics(name);
	var op = (operator == '==') ? true : false;
	if (item.InGroup(values[0]) && (values[1] == '' || values[1].test(name))) return op ? true : false;
	return op ? false : true;
}

function compareStrings(value, regex, operator) {
	if (value == undefined) value = '';
	else if (g_flags & (1 << 3)) value = str_tools.RemoveDiacritics(value);
	if (operator == '==') return typeof regex == 'string' ? regex == value : regex.test(value);
	else if (operator == '!=') return typeof regex == 'string' ? regex != value : !regex.test(value);
	else return false;
}

function compareDates(item, query, raw_query, operator) {
	if (DOpus.TypeOf(item) != 'object.Date') return false;
	try {
		switch (raw_query) {
			case 'thisyear':
			case 'year':
			case 'lastyear':
			case 'lyear':
				return compare(item.year, query(0).year, operator);
			case 'ryear':
				if (operator == '==')
					return compare(item.year, query(0).year, '>=') && compare(item.year, query(1).year, '<=');
				else
					return compare(item.year, query(0).year, '<') || compare(item.year, query(1).year, '>');
			case 'rwhole':
				if (operator == '==')
					return ((item.compare(query(0), query(0).sec == 0 ? 'sD' : '') >= 0) && (item.compare(query(1), query(1).sec == 0 ? 'sD' : '') <= 0));
				else
					return ((item.compare(query(0), query(0).sec == 0 ? 'sD' : '') < 0) || (item.compare(query(1), query(1).sec == 0 ? 'sD' : '') > 0));
				break;
			case 'rmyear':
			case 'rdate':
			case 'lastmonth':
			case 'lmonth':
			case 'thismonth':
			case 'month':
			case 'week':
			case 'thisweek':
			case 'lastweek':
			case 'lweek':
				switch (operator) {
					case '==':
						return ((item.compare(query(0), 'd') >= 0) && (item.compare(query(1), 'd') <= 0));
					case '!=':
						return ((item.compare(query(0), 'd') < 0) || (item.compare(query(1), 'd') > 0));
					case '>':
					case '<=':
						return compare(item.compare(query(1), 'd'), 0, operator);
					case '>=':
					case '<':
						return compare(item.compare(query(0), 'd'), 0, operator);
				}
				break;
			case 'today':
			case 'yesterday':
			case 'tomorrow':
			case 'ya':
			case 'Ma':
			case 'da':
				return compare(item.compare(query, 'd'), 0, operator); //compare dates value only
			case 'whole':
			case 'ha': //query is a date object with time included
				return compare(item.Compare(query, ''), 0, operator);
			case 'day': //query is a number or range referring a day
				if (DOpus.TypeOf(query) == 'object.Vector') {
					if (operator == '==')
						return compare(item.day, query(0), '>=') && compare(item.day, query(1), '<=');
					else
						return compare(item.day, query(0), '<') || compare(item.day, query(1), '>');
				}
				else return compare(item.day, query, operator);
				break;
			case 'm': //query is a number or range referring a month
				if (DOpus.TypeOf(query) == 'object.Vector') {
					if (operator == '==')
						return compare(item.month, query(0), '>=') && compare(item.month, query(1), '<=');
					else
						return compare(item.month, query(0), '<') || compare(item.month, query(1), '>');
				}
				else return compare(item.month, query, operator);
				break;
			case 'tsD': //query is a number referring the total seconds in a time value
				return compare(item.hour * 3600 + item.min * 60, query, operator);
			default:
				return compare(item.compare(query, raw_query), 0, operator);
		}
	}
	catch (e) {
		Log(3, 'Error when comparing dates in ' + item + ' : ' + e);
		return false;
	}
	return false;
}

function convertType(category, value, cons) {
	Log(1, 'Converting ' + typeof(value) + ' as ' + category);
	try {
		switch (category) {
			case 'number':
				return convertToNumber(value, /\d+/);
				break;
			case 'date':
				if (cons == undefined) cons = 'sD';
				return convertToDate(value, cons);
				break;
			case 'duration':
				return convertToDuration(value, /^(\d+)d (\d+):(\d+):(\d+)$|^(\d+):(\d+):(\d+)$|^(\d+):(\d+)$|^(\d+)$/);
				break;
			case 'size':
				return convertToSize(value, /^([\d,.]+) *([kb|mb|gb|tb|pb]*)$/i);
				break;
			case 'string':
				if (DOpus.TypeOf(value) == 'object') {
					if (value.length != 2) {
						Log(3, 'Wrong format for input');
						return null;
					}
					if (value[0] == '') {
						Log(3, 'No valid filetype group for comparison');
						return null;
					}
					var vec = DOpus.Create.Vector();
					var r = '';
					for (var i = 0; i < value[0].length; i++)
						r += value[0].charAt(i) + '.*';
					r = new RegExp(r.slice(0, -2), 'i');
					var ft = DOpus.filetypegroups;
					for (var i = 0; i < ft.count; i++) {
						if (r.test(ft(i).display_name)) {
							vec.push_back(((use_wildcards || search_mode) ? 'grp:' : 'disp:') + ft(i).display_name);
							break;
						}
					}
					ft = null;
					if (vec.empty) {
						Log(3, 'No valid filetype group for comparison');
						return null;
					}
					vec.push_back(BuildStrPattern(value[1]));
					return vec(1) == null ? null : vec;
				}
				else return BuildStrPattern(value);
				break;
			default:
				return null;
		}
	}
	catch (err) {
		Log(3, 'Error while trying to convert "' + value + '" as "' + category + '" : ' + err);
		return null;
	}
}

function BuildStrPattern(value) {
	//Use Textual Filters is off and is not a Script/Eval/Shell column or preferred method is Rename Presets 
	if (!search_mode && !use_wildcards && (!g_custom_col || Script.config.preferred_filter_mode == 1)) { //Rename Preset is used or is not a script column
		Log(1, '   Aplying flags to string "' + value + '"');
		try {
			if (value == '') return value;
			else {
				if (g_flags & (1 << 3)) value = str_tools.RemoveDiacritics(value);
				if (g_flags & (1 << 1)) var regex = new RegExp('\\b' + ((g_flags & (1 << 2)) ? value : value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')) + '\\b', (g_flags & (1 << 0)) ? '' : 'i');
				else var regex = new RegExp((g_flags & (1 << 2)) ? value : value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), (g_flags & (1 << 0)) ? '' : 'i');
			}
			return regex;
		}
		catch (err) {
			Log(3, '   Error while parsing the string ' + value);
			return null;
		}
	}
	return value;
}

function convertToDate(value, cons) {
	try {
		switch (cons) {
			case 'thisyear':
			case 'year':
			case 'lastyear':
			case 'lyear':
				var ld = DOpus.Create.Date();
				var ud = DOpus.Create.Date();
				ld.month = 1;
				ld.day = 1;
				ud.month = 12;
				ud.day = 31;
				if (cons.charAt(0) == 'l') {
					ld.Sub(1, 'y');
					ud.Sub(1, 'y');
				}
				else if (value !== '')
					ld.year = ud.year = parseInt(value, 10);
				return DOpus.Create.Vector(ld, ud);
			case 'ryear':
				var ld = DOpus.Create.Date('1-1-2001');
				var ud = DOpus.Create.Date('31-12-2001');
				ld.year = parseInt(value[1], 10);
				ud.year = parseInt(value[2], 10);
				if (ld.Compare(ud, 'd') != -1) return null; //not valid range
				return DOpus.Create.Vector(ld, ud);
			case 'rmyear':
				var ld = DOpus.Create.Date('1-1-2001');
				var ud = DOpus.Create.Date('1-1-2001');
				ld.month = parseInt(value[1], 10);
				ld.year = parseInt(value[2], 10);
				ud.month = parseInt(value[3], 10);
				ud.year = parseInt(value[4], 10);
				ud.Add(1, 'M');
				ud.Sub(1, 'd');
				if (ld.Compare(ud) != -1) return null; //not valid range
				return DOpus.Create.Vector(ld, ud);
			case 'rdate':
				var ld = DOpus.Create.Date('1-1-2001');
				var ud = DOpus.Create.Date('1-1-2001');
				ld.month = parseInt(value[2], 10);
				ud.month = parseInt(value[5], 10);
				if (value[1].length == 4) {
					ld.year = parseInt(value[1], 10);
					ld.day = parseInt(value[3], 10);
					ud.year = parseInt(value[4], 10);
					ud.day = parseInt(value[6], 10);
				}
				else {
					ld.year = parseInt(value[3], 10);
					ld.day = parseInt(value[1], 10);
					ud.year = parseInt(value[6], 10);
					ud.day = parseInt(value[4], 10);
				}

				if (ld.Compare(ud) != -1) return null; //not valid range
				return DOpus.Create.Vector(ld, ud);
			case 'rwhole':
				var ld = DOpus.Create.Date('1-1-2001');
				var ud = DOpus.Create.Date('1-1-2001');
				ld.month = parseInt(value[2], 10);
				ud.month = parseInt(value[8], 10);
				if (value[1].length == 4) {
					ld.year = parseInt(value[1], 10);
					ld.day = parseInt(value[3], 10);
					ud.year = parseInt(value[7], 10);
					ud.day = parseInt(value[9], 10);
				}
				else {
					ld.year = parseInt(value[3], 10);
					ld.day = parseInt(value[1], 10);
					ud.year = parseInt(value[9], 10);
					ud.day = parseInt(value[7], 10);
				}
				ld.hour = parseInt(value[4], 10);
				ld.min = parseInt(value[5], 10);
				ld.sec = value[6] == '' ? 0 : parseInt(value[6], 10);
				ud.hour = parseInt(value[10], 10);
				ud.min = parseInt(value[11], 10);
				ud.sec = value[12] == '' ? 0 : parseInt(value[12], 10);
				if (ld.Compare(ud) != -1) return null; //not valid range
				return DOpus.Create.Vector(ld, ud);
			case 'thismonth':
			case 'month':
			case 'lastmonth':
			case 'lmonth':
				var ld = DOpus.Create.Date();
				var ud = DOpus.Create.Date();
				ld.day = 1;
				ud.day = 1;
				if (cons.charAt(0) == 'l') {
					ld.Sub(1, 'M');
					ud.Sub(1, 'd');
				}
				else {
					if (typeof value === 'object') {
						ld.month = ud.month = parseInt(value[1], 10);
						ld.year = ud.year = parseInt(value[2], 10);
					}
					else if (value) ld.month = ud.month = parseInt(value, 10);
					ud.Add(1, 'M');
					ud.Sub(1, 'd');
				}
				return DOpus.Create.Vector(ld, ud);
			case 'thisweek':
			case 'week':
			case 'lastweek':
			case 'lweek':
				var ld = DOpus.Create.Date();
				var ud = DOpus.Create.Date();
				if (cons.charAt(0) == 'l')
					ld.Sub(1, 'w');
				ld.Sub((ld.wday === 0) ? 6 : ld.wday - 1, 'd');
				ud.day = ld.day + 6;
				return DOpus.Create.Vector(ld, ud);
			case 'today':
				return DOpus.Create.Date();
			case 'yesterday':
				var cd = DOpus.Create.Date();
				cd.Sub(1, 'd');
				return cd;
			case 'tomorrow':
				var cd = DOpus.Create.Date();
				cd.Add(1, 'd');
				return cd;
			case 'ya':
			case 'Ma':
			case 'da':
			case 'ha':
				var cd = DOpus.Create.Date();
				cd.Sub(parseInt(value, 10), cons.charAt(0));
				return cd;
			case 'day':
			case 'm': //returns month|day number as int
				if (typeof value == 'object') { //is an array
					value[1] = parseInt(value[1], 10);
					value[2] = parseInt(value[2], 10);
					if (value[1] >= value[2]) return null; //not valid range
					return DOpus.Create.Vector(value[1], value[2]);
				}
				return parseInt(value, 10);
			case 'tsD':
				//value is a Date object with time only
				return value.hour * 3600 + value.min * 60; //returns total seconds
			case 'whole':
			case 'd':
			case 't':
			case 'sD':
				if (DOpus.TypeOf(value) != 'object.Date') return DOpus.Create.Date(value);
				return value; //returns a Date object
			default:
				return null;
		}
	}
	catch (err) {
		Log(3, 'Error converting to date as ' + cons + ':' + err);
		return null;
	}
}

function convertToNumber(value, regex) {
	if (typeof value === 'object') {
		if (value.length > 2) return null; //no  more than 2 values in the range
		var a = DOpus.Create.Vector();
		for (var i = 0; i < 2; i++) {
			Log(1, value[i]);
			v = convertToNumber(value[i], regex);
			if (v === null) return null;
			a.push_back(v);
		}
		if (a(0) >= a(1)) return null; //not valid range
		return a;
	}
	else if (typeof value === 'string') {
		value = value.replace(/,/g, '.');
		var match = value.match(regex);
		if (match) return parseFloat(match[0]);
	}
	else if (!isNaN(value)) return value;
	return null;
}
//convert duration to number (as number of seconds)
function convertToDuration(value, regex) {
	///^(\d+)d (\d+):(\d+):(\d+)$|^(\d+):(\d+):(\d+)$|^(\d+):(\d+)$|^(\d+)$/
	if (typeof value == 'object') { //is a range
		if (value.length > 2) return null; //no  more than 2 values in the range
		var a = DOpus.Create.Vector();
		for (var i = 0; i < 2; i++) {
			v = convertToDuration(value[i], regex);
			if (v == null) return null;
			a.push_back(v);
		}
		if (a(0) >= a(1)) return null; //not valid range
		return a;
	}
	else {
		var match = value.match(regex);
		if (!match) return null;
		var day = parseInt(match[1] || 0, 10);
		var hr = parseInt(match[2] || match[5] || 0, 10);
		var min = parseInt(match[3] || match[6] || match[8] || 0, 10);
		var sec = parseInt(match[4] || match[7] || match[9] || match[10] || 0, 10);
		var totalsec = day * 86400 + hr * 3600 + min * 60 + sec;
		return totalsec;
	}
}

function convertToSize(value, regex) {
	if (typeof value == 'object') {
		if (value.length > 2) return null; //no  more than 2 values in the range
		var a = DOpus.Create.Vector();
		for (var i = 0; i < 2; i++) {
			v = convertToSize(value[i], regex);
			if (v == null) return null;
			a.push_back(v);
		}
		if (a(0).Compare(a(1)) != -1) return null; //not valid range
		return a;
	}
	else {
		var match = value.match(regex);
		if (match) {
			var num = match[1].replace(',', '.');
			var un = match[2].toLowerCase();
			switch (un) {
				case 'kb':
					un = 1024;
					break;
				case 'mb':
					un = 1024 * 1024;
					break;
				case 'gb':
					un = 1024 * 1024 * 1024;
					break;
				case 'tb':
					un = 1024 * 1024 * 1024 * 1024;
					break;
				case 'pb':
					un = 1024 * 1024 * 1024 * 1024 * 1024;
					break;
				default:
					un = 1;
					break;
			};
			return FSU.NewFileSize(num * un);
		}
	}
	return null;
}

function CreateRenamePresetTxt(preset, to, single) {
	Log(2, 'Creating rename preset "' + preset + '"');
	Log(1, 'Rename preset TO        : ' + to);
	to = to.replace(/&/g, '&amp;');
	to = to.replace(/"/g, '&quot;');
	to = to.replace(/</g, '&lt;');
	to = to.replace(/>/g, '&gt;');
	to = to.replace(/'/g, '&apos;');
	var content = '<?xml version="1.0" encoding="UTF-8"?>\r\n';
	content += '<rename_preset applynomatch="yes" case="none" script="yes" type="normal" version="13">\r\n<from></from>\r\n<to>';
	content += to + '</to>\r\n<script>@script JScript\r\n';
	if (single)
		content += 'function OnGetNewName(g){\r\nvar tmp = g.newname;\r\nif (!tmp) {DOpus.vars.Delete("fbc");return true;}\r\nDOpus.vars.Set("fbc", tmp);return true;}';
	else {
		content += 'var map = DOpus.Create.Map();\r\n';
		content += 'function OnGetNewName(g){map.Set(g.item,g.newname);return true;}\r\n';
		content += 'DOpus.Vars.Set(&quot;' + preset + '&quot;, map);\r\n'
	}
	content += '</script>\r\n</rename_preset>';
	preset = DOpus.Aliases('dopusdata').path + '\\Rename Presets\\' + preset + '.orp';
	var file = FSU.OpenFile(preset, 'w');
	if (file.error != 0) return false;
	try {
		var r = file.Write(content);
		file.Close();
	}
	catch (e) {
		Log(3, 'Unable to write ' + preset + ': ' + e.description);
		r = 0;
	}
	file = null;
	if (r != 0) Log(2, 'Rename preset succesfully created: ' + r + ' bytes');
	return r;
}

function configFlags(parent, flags) {
	var dlg = parent.dlg();
	dlg.template = 'configflags';
	dlg.disable_window = parent;
	dlg.detach = true;
	dlg.Create();
	dlg.top = true;
	dlg.title = script_label + ' v' + script_version + ' - Flags configuration';
	for (var i = 0; i < 7; i++) {
		dlg.Control('flag' + i).label = DOpus.strings.Get('flag' + i);
		dlg.Control('flag' + i).value = flags & (1 << i);
	}
	dlg.Show();
	while (true) {
		msg = dlg.GetMsg();
		if (!msg.result) break;
		if (msg.event == 'click' && msg.control == 'ok_btn') dlg.EndDlg(1);
	}
	if (dlg.result == 1) {
		flags = 0;
		for (var i = 0; i < 7; i++) {
			if (dlg.Control('flag' + i).value) flags += (1 << i);
		}
		Script.UpdateFAYTFlags(script_name, flags);
		Log(2, 'Flags saved in configuration!!');
	}
	dlg = null;
}

function getColumnData(value) {
	Log(2, '   Getting data for column "' + value + '"...');
	switch (value) {
		case 'accessed':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', '', 'property', 'access', 'category', 'date');
		case 'accesseddate':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', '', 'property', 'access', 'category', 'date');
		case 'created':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', '', 'property', 'create', 'category', 'date');
		case 'createddate':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', '', 'property', 'create', 'category', 'date');
		case 'modified':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', '', 'property', 'modify', 'category', 'date');
		case 'modifieddate':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', '', 'property', 'modify', 'category', 'date');
		case 'attr':
			return DOpus.Create.Map('builtin', true, 'multi', true, 'metatype', '', 'property', 'attr_text', 'category', 'string');
		case 'ext':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', '', 'property', 'ext', 'category', 'string');
		case 'size':
		case 'sizeauto':
		case 'sizekb':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', '', 'property', 'size', 'category', 'size');
			//SPECIAL CASES
		case 'accessedtime':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', '', 'property', 'access', 'category', 'duration');
		case 'createdtime':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', '', 'property', 'create', 'category', 'duration');
		case 'modifiedtime':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', '', 'property', 'modify', 'category', 'duration');
		case 'extdir':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', '', 'property', 'ext', 'category', 'string');
		case 'fullpath':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', '', 'property', 'realpath', 'category', 'string');
		case 'owner':
			return DOpus.Create.Map('builtin', false, 'multi', false, 'metatype', '', 'property', '', 'category', 'string');
		case 'type':
			return DOpus.Create.Map('builtin', false, 'multi', false, 'metatype', '', 'property', '', 'category', 'string');
		case 'perms':
			return DOpus.Create.Map('builtin', false, 'multi', false, 'metatype', '', 'property', '', 'category', 'string');
		case 'availability':
			return DOpus.Create.Map('builtin', false, 'multi', false, 'metatype', '', 'property', '', 'category', 'string');
		case 'keywords':
			return DOpus.Create.Map('builtin', true, 'multi', true, 'metatype', '', 'property', value, 'category', 'string');
		case 'label':
			return DOpus.Create.Map('builtin', true, 'multi', true, 'metatype', '', 'property', value, 'category', 'string');
		case 'name':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', '', 'property', value, 'category', 'string');
		case 'parent':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', '', 'property', value, 'category', 'string');
		case 'parentlocation':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', '', 'property', value, 'category', 'string');
		case 'parentpath':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', '', 'property', value, 'category', 'string');
		case 'path':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', '', 'property', value, 'category', 'string');
		case 'pathrel':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', '', 'property', value, 'category', 'string');
		case 'desc':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', '', 'property', value, 'category', 'string');
		case 'userdesc':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'other', 'property', 'usercomment', 'category', 'string');
		case 'pathlen':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', '', 'property', '', 'category', 'number');
		case 'copyright':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', true, 'property', value, 'category', 'string');
		case 'producer':
			return DOpus.Create.Map('builtin', true, 'multi', true, 'metatype', true, 'property', value, 'category', 'string');
		case 'picdepth':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', true, 'property', value, 'category', 'number');
			//AUDIO
		case 'mp3bpm':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'audio', 'property', value, 'category', 'number');
		case 'mp3disc':
		case 'mp3disk':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'audio', 'property', value, 'category', 'number');
		case 'mp3track':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'audio', 'property', value, 'category', 'number');
		case 'compilation':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'audio', 'property', value, 'category', 'string');
		case 'mp3album':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'audio', 'property', value, 'category', 'string');
		case 'mp3albumartist':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'audio', 'property', value, 'category', 'string');
		case 'mp3comment':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'audio', 'property', value, 'category', 'string');
		case 'mp3encoder':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'audio', 'property', value, 'category', 'string');
		case 'mp3encodingsoftware':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'audio', 'property', value, 'category', 'string');
		case 'mp3info':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'audio', 'property', value, 'category', 'string');
		case 'mp3drm':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'audio', 'property', value, 'category', 'string');
			//DOCUMENT
		case 'doccreateddate':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'doc', 'property', value, 'category', 'date');
		case 'docedittime':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'doc', 'property', value, 'category', 'date');
		case 'doclastsaveddate':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'doc', 'property', value, 'category', 'date');
		case 'pages':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'doc', 'property', value, 'category', 'number');
		case 'category':
			return DOpus.Create.Map('builtin', true, 'multi', true, 'metatype', 'doc', 'property', value, 'category', 'string');
		case 'comments':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'doc', 'property', value, 'category', 'string');
		case 'creator':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'doc', 'property', value, 'category', 'string');
		case 'doclastsavedby':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'doc', 'property', value, 'category', 'string');
			//PROGRAM
		case 'modversion':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'exe', 'property', value, 'category', 'number');
		case 'prodversion':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'exe', 'property', value, 'category', 'number');
		case 'moddesc':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'exe', 'property', value, 'category', 'string');
		case 'prodname':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'exe', 'property', value, 'category', 'string');
		case 'fontname':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'font', 'property', value, 'category', 'string');
			//IMAGE
		case 'datedigitized':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'date');
		case 'datetaken':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'date');
		case '35mmfocallength':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'number');
		case 'altitude':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'number');
		case 'apertureval':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'number');
		case 'digitalzoom':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'number');
		case 'exposurebias':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'number');
		case 'exposuretime':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'number');
		case 'fnumber':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'number');
		case 'focallength':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'number');
		case 'latitude':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'number');
		case 'longitude':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'number');
		case 'picphysx':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'number');
		case 'picphysy':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'number');
		case 'picresx':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'number');
		case 'picresy':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'number');
		case 'rotation':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'number');
		case 'shutterspeed':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'number');
		case 'subjectdistance':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'number');
		case 'cameramake':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
		case 'cameramodel':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
		case 'colormodel':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
		case 'colorspace':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
		case 'contrast':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
		case 'coords':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
		case 'exposureprogram':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
		case 'flash':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
		case 'imagedesc':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
		case 'imagequality':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
		case 'instructions':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
		case 'isospeed':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
		case 'lensmake':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
		case 'lensmodel':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
		case 'macromode':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
		case 'meteringmode':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
		case 'picres':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
		case 'saturation':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
		case 'scenecapturetype':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
		case 'scenemode':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
		case 'sharpness':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
		case 'software':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
		case 'whitebalance':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image', 'property', value, 'category', 'string');
			//VIDEO
		case 'broadcastdate':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'video', 'property', value, 'category', 'date');
		case 'recordingtime':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'video', 'property', value, 'category', 'duration');
		case 'audiocount':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'video', 'property', value, 'category', 'number');
		case 'channel':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'video', 'property', value, 'category', 'number');
		case 'datarate':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'video', 'property', value, 'category', 'number');
		case 'framerate':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'video', 'property', value, 'category', 'number');
		case 'subtitlecount':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'video', 'property', value, 'category', 'number');
		case 'videocount':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'video', 'property', value, 'category', 'number');
		case 'director':
			return DOpus.Create.Map('builtin', true, 'multi', true, 'metatype', 'video', 'property', value, 'category', 'string');
		case 'alllangs':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'video', 'property', value, 'category', 'string');
		case 'audiolangs':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'video', 'property', value, 'category', 'string');
		case 'credits':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'video', 'property', value, 'category', 'string');
		case 'episodename':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'video', 'property', value, 'category', 'string');
		case 'fourcc':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'video', 'property', value, 'category', 'string');
		case 'hdrtypes':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'video', 'property', value, 'category', 'string');
		case 'ishd':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'video', 'property', value, 'category', 'string');
		case 'isrepeat':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'video', 'property', value, 'category', 'string');
		case 'publisher':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'video', 'property', value, 'category', 'string');
		case 'station':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'video', 'property', value, 'category', 'string');
		case 'subtitlelangs':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'video', 'property', value, 'category', 'string');
		case 'videocodec':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'video', 'property', value, 'category', 'string');
		case 'videolangs':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'video', 'property', value, 'category', 'string');
		case 'encodedby':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'video', 'property', value, 'category', 'string');
			//MULTI	
		case 'rating':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'other', 'property', value, 'category', 'number');
		case 'target':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'other', 'property', value, 'category', 'string');
		case 'duration':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', true, 'property', value, 'category', 'duration');
		case 'releasedate':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', true, 'property', value, 'category', 'date');
		case 'mp3bitrate':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', true, 'property', value, 'category', 'number');
		case 'mp3samplerate':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', true, 'property', value, 'category', 'number');
		case 'mp3year':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', true, 'property', value, 'category', 'number');
		case 'audiocodec':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', true, 'property', value, 'category', 'string');
		case 'composers':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', true, 'property', value, 'category', 'string');
		case 'conductors':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', true, 'property', value, 'category', 'string');
		case 'mp3genre':
			return DOpus.Create.Map('builtin', true, 'multi', true, 'metatype', true, 'property', value, 'category', 'string');
		case 'mp3mode':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', true, 'property', value, 'category', 'string');
		case 'mp3title':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', true, 'property', value, 'category', 'string');
		case 'mp3type':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', true, 'property', value, 'category', 'string');
		case 'initialkey':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', true, 'property', value, 'category', 'string');
		case 'companyname':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', true, 'property', value, 'category', 'string');
		case 'subject':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', true, 'property', value, 'category', 'string');
		case 'picsize':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image_text', 'property', value, 'category', 'string');
		case 'aspectratiogroup':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image_text', 'property', value, 'category', 'string');
		case 'picphyssize':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', 'image_text', 'property', value, 'category', 'string');
		case 'aspectratio':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', true, 'property', value, 'category', 'number');
		case 'picheight':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', true, 'property', value, 'category', 'number');
		case 'picwidth':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', true, 'property', value, 'category', 'number');
		case 'mp3artists':
			return DOpus.Create.Map('builtin', true, 'multi', true, 'metatype', true, 'property', value, 'category', 'string');
		case 'author':
			return DOpus.Create.Map('builtin', true, 'multi', true, 'metatype', true, 'property', value, 'category', 'string');
		case 'title':
			return DOpus.Create.Map('builtin', true, 'multi', false, 'metatype', true, 'property', value, 'category', 'string');
		default:
			Log(3, value + ' is not a recognized column for this command');
			return null;
	}
}

function saveQuery(query, desc) {
	Log(2, 'Saving query            : ' + query);
	var values = DOpus.Create.Vector(query + '\t' + desc);
	if (Script.Vars.Exists('saved_queries')) values.append(Script.Vars.Get('saved_queries'));
	values.unique();
	var max = Script.config.max_history_size;
	if (max == 0) max = 10;
	if (values.size > max) values.resize(10);
	Script.Vars.Set('saved_queries', values);
	Script.Vars('saved_queries').persist = true;
	return;
}

function getCatEvalCol(col_name) {
	Log(2, '   Trying to get category for "' + col_name + '" column from evalcols.oxc...');
	//text,double,signed,notsigned,size,date,time,datetime,rating,graph,percent
	var results = ['string', 'number', 'number', 'number', 'size', 'date', 'date', 'date', 'number', false, false];
	var type = 0;
	try {
		var ev_col_file = DOpus.Aliases('dopusdata').path + '\\ConfigFiles\\evalcols.oxc';
		Log(1, '   Evaluator : Parsing Evaluator columns xml file:' + ev_col_file);
		if (!FSU.Exists(ev_col_file)) return results;
		var xmlDocEv = new ActiveXObject('Msxml2.DOMDocument');
		xmlDocEv.load(ev_col_file);
		if (xmlDocEv.parseError.errorCode == 0) {
			var evalcolumns = xmlDocEv.selectNodes('//prefs/evalcolumns/column');
			for (var i = 0; i < evalcolumns.length; i++) {
				// Get keyword
				var keyword = evalcolumns[i].getAttribute('keyword');
				if (col_name == keyword) {
					type = evalcolumns[i].getAttribute('type');
					break;
				}
			}
		}
		else
			Log(3, '   Evaluator : Error parsing Evaluator xml file');
		xmlDocEv = null;
	}
	catch (err) {
		Log(3, '   Evaluator : Error while trying to get Evaluator columns info : ' + err);
	};
	return results[type];
}

function getCustomMap(name, verify_names, return_map) {
	var map = DOpus.Create.Map();
	var keys = '';
	var match;
	var regex = (verify_names === true) ? /(>=|=>|<=|=<|!=|=|<|>)/ : /^(string|date|number|duration|size)$/i;
	var m = /^ *"(.+)":"(.+)" *$/;
	var vector = Script.config[name];
	if (!verify_names && Script.Vars.Exists('saved_categories')) vector.append(Script.Vars.Get('saved_categories'));
	for (var i = 0; i < vector.length; i++) {
		try {
			if (vector(i) != '') {
				var match = vector(i).match(m);
				if (match) {
					match[1] = match[1].trim();
					match[2] = match[2].trim();
					if (verify_names === true) {
						if (regex.test(match[1])) {
							Log(3, match[1] + ' is not a valid value. Contains an operator in its name');
							continue;
						}
						map.Set(match[1], match[2].toLowerCase());
					}
					else { //verify for correct category
						if (!regex.test(match[2])) {
							Log(3, match[2] + ' is not a valid category. Valid types are string, date, number, duration or size');
							continue;
						}
						map.Set(match[1].toLowerCase(), match[2].toLowerCase());
					}
				}
				else Log(3, vector(i) + ' doesn\'t have a valid syntax');
			}
		}
		catch (error) {
			Log(3, '   Error when parsing ' + vector(i) + ' : ' + error);
			continue;
		};
	}
	Script.Vars.Set(name, map);
	return return_map ? map : true;
}

// Called whenever the user modifies the script's configuration
function OnScriptConfigChange(configChangeData) {
	for (var i = 0; i < configChangeData.changed.length; i++) {
		if (configChangeData.changed(i) === 'custom_columns_categories') getCustomMap('custom_columns_categories', false, false);
		else if (configChangeData.changed(i) === 'custom_columns_names') getCustomMap('custom_columns_names', true, false);
	}
}

function getSuggestions(quick_key, names_only) {
	try {
		var values = DOpus.Create.Vector();
		if (!names_only && Script.Vars.Exists('saved_queries')) {
			var vector = Script.Vars.Get('saved_queries');
			for (var i = 0; i < vector.length; i++) {
				values.push_back(quick_key + vector(i) + '\t(history)');
			}
			vector = null;
		}
		if (custom_names_map === undefined) custom_names_map = Script.config.custom_columns_names.empty ? null : (Script.Vars.Exists('custom_columns_names') ? Script.Vars.Get('custom_columns_names') : getCustomMap('custom_columns_names', true, true));
		if (custom_names_map !== null && !custom_names_map.empty) {
			for (var e = new Enumerator(custom_names_map); !e.atEnd(); e.moveNext()) {
				values.push_back(quick_key + e.item() + '\t' + custom_names_map(e.item()) + ' (custom name)');
			}
			e = null;
		}
	}
	catch (error) {
		Log(3, 'Error when getting suggestions : ' + error.description);
	};
	return values;
}

function CheckDefaultFilter() {
	Log(1, 'Trying to get default filter from prefs.oxc...');
	var result = false;
	try {
		var prefs_file = DOpus.Aliases('dopusdata').path + '\\ConfigFiles\\prefs.oxc';
		var xmlDocEv = new ActiveXObject('Msxml2.DOMDocument');
		xmlDocEv.load(prefs_file);
		if (xmlDocEv.parseError.errorCode == 0) {
			var default_filter = '';
			var fayts = xmlDocEv.selectSingleNode('//prefs/fayt');
			if (fayts) default_filter = fayts.getAttribute('defaultmode');
			Log(1, '   default filter : ' + default_filter);
			if (default_filter === script_name) result = true;
			if (!quickKey) {
				fayts = xmlDocEv.selectSingleNode('//prefs/fayt/modes/mode[@fayt_mode="' + script_name + '"]');
				if (fayts) quickKey = String.fromCharCode(fayts.getAttribute('key'));
			}
		}
		else
			Log(3, 'Error parsing prefs xml file');
		xmlDocEv = null;
	}
	catch (err) {
		Log(3, 'Error while trying to get default filter info : ' + err.description);
	};
	return result;
}

function MapColHeaders() {
	return DOpus.Create.Map(
		str_tools.LanguageStr(100), 'coords',
		str_tools.LanguageStr(101), 'altitude',
		str_tools.LanguageStr(145), 'availability',
		str_tools.LanguageStr(152), 'lensmodel',
		str_tools.LanguageStr(153), 'lensmake',
		str_tools.LanguageStr(25), 'picwidth',
		str_tools.LanguageStr(26), 'picheight',
		str_tools.LanguageStr(29376), 'aspectratiogroup',
		str_tools.LanguageStr(29377), 'audiolangs',
		str_tools.LanguageStr(29378), 'audiocount',
		str_tools.LanguageStr(29389), 'colormodel',
		str_tools.LanguageStr(29390), 'hdrtypes',
		str_tools.LanguageStr(29391), 'perms',
		str_tools.LanguageStr(29381), 'subtitlelangs',
		str_tools.LanguageStr(29382), 'subtitlecount',
		str_tools.LanguageStr(29383), 'videolangs',
		str_tools.LanguageStr(29384), 'videocount',
		str_tools.LanguageStr(30007), 'picres',
		str_tools.LanguageStr(310), 'name',
		str_tools.LanguageStr(311), 'size',
		str_tools.LanguageStr(312), 'type',
		str_tools.LanguageStr(313), 'modifieddate',
		str_tools.LanguageStr(314), 'modifiedtime',
		str_tools.LanguageStr(315), 'attr',
		str_tools.LanguageStr(316), 'createddate',
		str_tools.LanguageStr(317), 'createdtime',
		str_tools.LanguageStr(318), 'accesseddate',
		str_tools.LanguageStr(319), 'accessedtime',
		str_tools.LanguageStr(323), 'ext',
		str_tools.LanguageStr(324), 'desc',
		str_tools.LanguageStr(327), 'picdepth',
		str_tools.LanguageStr(328), 'picsize',
		str_tools.LanguageStr(329), 'mp3type',
		str_tools.LanguageStr(330), 'mp3bitrate',
		str_tools.LanguageStr(331), 'mp3samplerate',
		str_tools.LanguageStr(332), 'mp3mode',
		str_tools.LanguageStr(333), 'mp3genre',
		str_tools.LanguageStr(334), 'mp3title',
		str_tools.LanguageStr(335), 'mp3artists',
		str_tools.LanguageStr(336), 'mp3album',
		str_tools.LanguageStr(337), 'mp3year',
		str_tools.LanguageStr(338), 'mp3comment',
		str_tools.LanguageStr(339), 'path',
		str_tools.LanguageStr(340), 'moddesc',
		str_tools.LanguageStr(341), 'modversion',
		str_tools.LanguageStr(342), 'prodname',
		str_tools.LanguageStr(343), 'prodversion',
		str_tools.LanguageStr(344), 'copyright',
		str_tools.LanguageStr(345), 'companyname',
		str_tools.LanguageStr(346), 'mp3info',
		str_tools.LanguageStr(347), 'owner',
		str_tools.LanguageStr(348), 'sizeauto',
		str_tools.LanguageStr(350), 'duration',
		str_tools.LanguageStr(353), 'sizekb',
		str_tools.LanguageStr(354), 'cameramake',
		str_tools.LanguageStr(355), 'cameramodel',
		str_tools.LanguageStr(356), 'datetaken',
		str_tools.LanguageStr(357), 'apertureval',
		str_tools.LanguageStr(358), 'shutterspeed',
		str_tools.LanguageStr(359), 'isospeed',
		str_tools.LanguageStr(360), 'whitebalance',
		str_tools.LanguageStr(361), 'exposurebias',
		str_tools.LanguageStr(362), 'flash',
		str_tools.LanguageStr(363), 'author',
		str_tools.LanguageStr(364), 'title',
		str_tools.LanguageStr(365), 'subject',
		str_tools.LanguageStr(366), 'category',
		str_tools.LanguageStr(367), 'pages',
		str_tools.LanguageStr(368), 'comments',
		str_tools.LanguageStr(369), 'picresx',
		str_tools.LanguageStr(370), 'picresy',
		str_tools.LanguageStr(371), 'mp3track',
		str_tools.LanguageStr(373), 'focallength',
		str_tools.LanguageStr(374), 'meteringmode',
		str_tools.LanguageStr(375), 'exposureprogram',
		str_tools.LanguageStr(376), 'subjectdistance',
		str_tools.LanguageStr(377), 'exposuretime',
		str_tools.LanguageStr(378), 'fnumber',
		str_tools.LanguageStr(379), 'scenecapturetype',
		str_tools.LanguageStr(380), 'pathrel',
		str_tools.LanguageStr(381), 'extdir',
		str_tools.LanguageStr(382), 'rotation',
		str_tools.LanguageStr(383), 'contrast',
		str_tools.LanguageStr(384), 'saturation',
		str_tools.LanguageStr(385), 'sharpness',
		str_tools.LanguageStr(386), '35mmfocallength',
		str_tools.LanguageStr(387), 'digitalzoom',
		str_tools.LanguageStr(393) + ' (Audio)', 'mp3encoder',
		str_tools.LanguageStr(393), 'encodedby',
		str_tools.LanguageStr(394), 'framerate',
		str_tools.LanguageStr(395), 'datarate',
		str_tools.LanguageStr(402), 'keywords',
		str_tools.LanguageStr(403), 'doccreateddate',
		str_tools.LanguageStr(404), 'doclastsaveddate',
		str_tools.LanguageStr(405), 'docedittime',
		str_tools.LanguageStr(406), 'doclastsavedby',
		str_tools.LanguageStr(408), 'colorspace',
		str_tools.LanguageStr(409), 'fontname',
		str_tools.LanguageStr(410), 'parent',
		str_tools.LanguageStr(411), 'parentpath',
		str_tools.LanguageStr(412), 'parentlocation',
		str_tools.LanguageStr(416), 'aspectratio',
		str_tools.LanguageStr(417), 'software',
		str_tools.LanguageStr(418), 'mp3drm',
		str_tools.LanguageStr(419), 'mp3bpm',
		str_tools.LanguageStr(420), 'rating',
		str_tools.LanguageStr(421), 'scenemode',
		str_tools.LanguageStr(422), 'macromode',
		str_tools.LanguageStr(423), 'imagequality',
		str_tools.LanguageStr(425), 'datedigitized',
		str_tools.LanguageStr(426), 'creator',
		str_tools.LanguageStr(427), 'producer',
		str_tools.LanguageStr(434), 'publisher',
		str_tools.LanguageStr(436), 'composers',
		str_tools.LanguageStr(437), 'conductors',
		str_tools.LanguageStr(441), 'initialkey',
		str_tools.LanguageStr(444), 'director',
		str_tools.LanguageStr(447), 'releasedate',
		str_tools.LanguageStr(448), 'episodename',
		str_tools.LanguageStr(449), 'credits',
		str_tools.LanguageStr(450), 'channel',
		str_tools.LanguageStr(451), 'ishd',
		str_tools.LanguageStr(452), 'isrepeat',
		str_tools.LanguageStr(453), 'broadcastdate',
		str_tools.LanguageStr(454), 'recordingtime',
		str_tools.LanguageStr(455), 'station',
		str_tools.LanguageStr(457), 'label',
		str_tools.LanguageStr(458), 'mp3disk',
		str_tools.LanguageStr(459), 'picphyssize',
		str_tools.LanguageStr(550), 'picphysx',
		str_tools.LanguageStr(551), 'picphysy',
		str_tools.LanguageStr(552), 'mp3albumartist',
		str_tools.LanguageStr(553), 'target',
		str_tools.LanguageStr(554), 'userdesc',
		str_tools.LanguageStr(558), 'fourcc',
		str_tools.LanguageStr(559), 'pathlen',
		str_tools.LanguageStr(561), 'fullpath',
		str_tools.LanguageStr(563), 'imagedesc',
		str_tools.LanguageStr(565), 'modified',
		str_tools.LanguageStr(566), 'created',
		str_tools.LanguageStr(567), 'accessed',
		str_tools.LanguageStr(570), 'mp3encodingsoftware',
		str_tools.LanguageStr(571), 'instructions',
		str_tools.LanguageStr(572), 'compilation',
		str_tools.LanguageStr(7572), 'alllangs',
		str_tools.LanguageStr(92), 'audiocodec',
		str_tools.LanguageStr(93), 'videocodec',
		str_tools.LanguageStr(98), 'latitude',
		str_tools.LanguageStr(99), 'longitude',
		'accessed', DOpus.Create.Map(),
		'accesseddate', DOpus.Create.Map(),
		'created', DOpus.Create.Map(),
		'createddate', DOpus.Create.Map(),
		'modified', DOpus.Create.Map(),
		'modifieddate', DOpus.Create.Map(),
		'attr', DOpus.Create.Map(),
		'ext', DOpus.Create.Map(),
		'sizekb', DOpus.Create.Map(),
		'size', DOpus.Create.Map(),
		'sizeauto', DOpus.Create.Map(),
		'accessedtime', DOpus.Create.Map(),
		'createdtime', DOpus.Create.Map(),
		'modifiedtime', DOpus.Create.Map(),
		'extdir', DOpus.Create.Map(),
		'fullpath', DOpus.Create.Map(),
		'owner', DOpus.Create.Map(),
		'type', DOpus.Create.Map(),
		'perms', DOpus.Create.Map(),
		'availability', DOpus.Create.Map(),
		'keywords', DOpus.Create.Map(),
		'label', DOpus.Create.Map(),
		'name', DOpus.Create.Map(),
		'parent', DOpus.Create.Map(),
		'parentlocation', DOpus.Create.Map(),
		'parentpath', DOpus.Create.Map(),
		'path', DOpus.Create.Map(),
		'pathrel', DOpus.Create.Map(),
		'desc', DOpus.Create.Map(),
		'userdesc', DOpus.Create.Map(),
		'pathlen', DOpus.Create.Map(),
		'copyright', DOpus.Create.Map(),
		'producer', DOpus.Create.Map(),
		'picdepth', DOpus.Create.Map(),
		'mp3bpm', DOpus.Create.Map(),
		'mp3disk', DOpus.Create.Map(),
		'mp3track', DOpus.Create.Map(),
		'compilation', DOpus.Create.Map(),
		'mp3album', DOpus.Create.Map(),
		'mp3albumartist', DOpus.Create.Map(),
		'mp3comment', DOpus.Create.Map(),
		'mp3encoder', DOpus.Create.Map(),
		'mp3encodingsoftware', DOpus.Create.Map(),
		'mp3info', DOpus.Create.Map(),
		'mp3drm', DOpus.Create.Map(),
		'doccreateddate', DOpus.Create.Map(),
		'docedittime', DOpus.Create.Map(),
		'doclastsaveddate', DOpus.Create.Map(),
		'pages', DOpus.Create.Map(),
		'category', DOpus.Create.Map(),
		'comments', DOpus.Create.Map(),
		'creator', DOpus.Create.Map(),
		'doclastsavedby', DOpus.Create.Map(),
		'modversion', DOpus.Create.Map(),
		'prodversion', DOpus.Create.Map(),
		'moddesc', DOpus.Create.Map(),
		'prodname', DOpus.Create.Map(),
		'fontname', DOpus.Create.Map(),
		'datedigitized', DOpus.Create.Map(),
		'datetaken', DOpus.Create.Map(),
		'35mmfocallength', DOpus.Create.Map(),
		'altitude', DOpus.Create.Map(),
		'apertureval', DOpus.Create.Map(),
		'digitalzoom', DOpus.Create.Map(),
		'exposurebias', DOpus.Create.Map(),
		'exposuretime', DOpus.Create.Map(),
		'fnumber', DOpus.Create.Map(),
		'focallength', DOpus.Create.Map(),
		'latitude', DOpus.Create.Map(),
		'longitude', DOpus.Create.Map(),
		'picphysx', DOpus.Create.Map(),
		'picphysy', DOpus.Create.Map(),
		'picresx', DOpus.Create.Map(),
		'picresy', DOpus.Create.Map(),
		'rotation', DOpus.Create.Map(),
		'shutterspeed', DOpus.Create.Map(),
		'subjectdistance', DOpus.Create.Map(),
		'cameramake', DOpus.Create.Map(),
		'cameramodel', DOpus.Create.Map(),
		'colormodel', DOpus.Create.Map(),
		'colorspace', DOpus.Create.Map(),
		'contrast', DOpus.Create.Map(),
		'coords', DOpus.Create.Map(),
		'exposureprogram', DOpus.Create.Map(),
		'flash', DOpus.Create.Map(),
		'imagedesc', DOpus.Create.Map(),
		'imagequality', DOpus.Create.Map(),
		'instructions', DOpus.Create.Map(),
		'isospeed', DOpus.Create.Map(),
		'lensmake', DOpus.Create.Map(),
		'lensmodel', DOpus.Create.Map(),
		'macromode', DOpus.Create.Map(),
		'meteringmode', DOpus.Create.Map(),
		'picres', DOpus.Create.Map(),
		'saturation', DOpus.Create.Map(),
		'scenecapturetype', DOpus.Create.Map(),
		'scenemode', DOpus.Create.Map(),
		'sharpness', DOpus.Create.Map(),
		'software', DOpus.Create.Map(),
		'whitebalance', DOpus.Create.Map(),
		'broadcastdate', DOpus.Create.Map(),
		'recordingtime', DOpus.Create.Map(),
		'audiocount', DOpus.Create.Map(),
		'channel', DOpus.Create.Map(),
		'datarate', DOpus.Create.Map(),
		'framerate', DOpus.Create.Map(),
		'subtitlecount', DOpus.Create.Map(),
		'videocount', DOpus.Create.Map(),
		'director', DOpus.Create.Map(),
		'alllangs', DOpus.Create.Map(),
		'audiolangs', DOpus.Create.Map(),
		'credits', DOpus.Create.Map(),
		'episodename', DOpus.Create.Map(),
		'fourcc', DOpus.Create.Map(),
		'hdrtypes', DOpus.Create.Map(),
		'ishd', DOpus.Create.Map(),
		'isrepeat', DOpus.Create.Map(),
		'publisher', DOpus.Create.Map(),
		'station', DOpus.Create.Map(),
		'subtitlelangs', DOpus.Create.Map(),
		'videocodec', DOpus.Create.Map(),
		'videolangs', DOpus.Create.Map(),
		'encodedby', DOpus.Create.Map(),
		'rating', DOpus.Create.Map(),
		'target', DOpus.Create.Map(),
		'duration', DOpus.Create.Map(),
		'releasedate', DOpus.Create.Map(),
		'mp3bitrate', DOpus.Create.Map(),
		'mp3samplerate', DOpus.Create.Map(),
		'mp3year', DOpus.Create.Map(),
		'audiocodec', DOpus.Create.Map(),
		'composers', DOpus.Create.Map(),
		'conductors', DOpus.Create.Map(),
		'mp3genre', DOpus.Create.Map(),
		'mp3mode', DOpus.Create.Map(),
		'mp3title', DOpus.Create.Map(),
		'mp3type', DOpus.Create.Map(),
		'initialkey', DOpus.Create.Map(),
		'companyname', DOpus.Create.Map(),
		'subject', DOpus.Create.Map(),
		'picsize', DOpus.Create.Map(),
		'aspectratiogroup', DOpus.Create.Map(),
		'picphyssize', DOpus.Create.Map(),
		'aspectratio', DOpus.Create.Map(),
		'picheight', DOpus.Create.Map(),
		'picwidth', DOpus.Create.Map(),
		'mp3artists', DOpus.Create.Map(),
		'author', DOpus.Create.Map(),
		'title', DOpus.Create.Map());
}

function printCols(cols, tab) {
	var cmd = DOpus.Create.Command();
	cmd.SetSourceTab(tab);
	cmd.RunCommand('Set UTILITY=OtherLog');
	DOpus.ClearOutput();
	DOpus.Output('=======' + script_name + ' v' + script_version + '=====================================');
	var max_length = 0;
	var map = {};
	map['Name'] = 'Header';
	for (var i = 0; i < cols.count; i++) {
		map[cols(i).name] = cols(i).header;
		if (cols(i).name.length > max_length) max_length = cols(i).name.length;
	}
	var name_f;
	for (var name in map) {
		name_f = name;
		while (name_f.length < max_length) {
			name_f += ' ';
		}
		DOpus.Output(name_f + '\t\t | ' + map[name]);
	}
	map = null;
	cmd = null;
	return;
}

String.prototype.trim = function() {
	return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
};

function Log(level, text) {
	if (level === 4 || Script.config.debug < level) {
		if (!first) {
			// DOpus.ClearOutput();
			first = true;
		}
		if (level <= 2) DOpus.Output('INFO    => ' + text);
		else if (level === 3) DOpus.Output('WARNING => ' + text);
		else DOpus.Output('ERROR   => ' + text, true);
	}
}

function ZeroPad(value, length) {
	// if (value.length === length) return value;
	var zero = '';
	for (var i = 0; i < length - String(value).length; i++) {
		zero += '0';
	}
	return zero + value;
}

function getCollPath(default_value, subvalue) {
	try {
		var collname = str_tools.MakeLegal(Script.config['collection name'].trim(), 'n');
		if (!collname) collname = default_value;
		collname = 'coll://' + collname;
		if (Script.config['create subcollections']) collname += '/' + (subvalue ? (str_tools.MakeLegal(subvalue, 'n') + '_') : '') + DOpus.Create.Date().Format('D#yyyy-MM-dd T#HHmmss');
	}
	catch (err) {
		return 'coll://' + default_value;
	}
	return collname;
}

function alert(parent, message, level) {
	var dlg = DOpus.Dlg();
	dlg.window = parent;
	dlg.disable_window = parent;
	dlg.message = message;
	dlg.buttons = "&OK";
	dlg.title = script_name + ' v' + script_version;
	if (level === 0) dlg.icon = 'info';
	else if (level === 1) dlg.icon = 'question';
	else if (level === 2) dlg.icon = 'warning';
	else dlg.icon = 'error';
	dlg.Show();
	dlg = null;
}

==SCRIPT RESOURCES
<resources>
	<resource type="strings">
		<strings lang="english">
			<string id="add_column">Add the referenced column to the results tab after the search.</string>
			<string id="collection_name">Collection name for the search results.</string>
			<string id="create_subcollections">Create sub-collections instead of overwriting search results.</string>
			<string id="custom_columns_categories">Here you can define the type of data that a column returns. Used for Script, Evaluator and Shell columns.
Format: &quot;&lt;name&gt;&quot;:&quot;&lt;type&gt;&quot;
&lt;name&gt; must be the same value as the column keyword. 
&lt;type&gt; can be string, date, duration, number or size.</string>
			<string id="custom_columns_names">Define custom names to refer to a specific column, using the following syntax:
&quot;mycolname&quot;:&quot;&lt;col name&gt;&quot;
Where &lt;col name&gt; is the actual column raw name. (Press this command&apos;s quick key twice to show a list of current column&apos;s names.
Don&apos;t use any operator (&lt;,=,&gt; or !) for mycolname value.</string>
			<string id="debug">Logging level to be displayed. OFF to shows none. 
ALL to shows all the messages. STANDARD to only shows the most relevants.
WARNING to shows error conditions that are of consideration.</string>
			<string id="default_implicit_column">If a column is not explicitly specified, choose between searching by name, the current sorted or highlighted column, or user_defined_implicit_column value.</string>
			<string id="enable_wildcards">Set to True to enable compatibility with Opus standard pattern matching.</string>
			<string id="flag0">&amp;Case sensitive</string>
			<string id="flag1">&amp;Whole words</string>
			<string id="flag2">Regular e&amp;xpressions</string>
			<string id="flag3">Ignore &amp;diacritics</string>
			<string id="flag4">Ignore non &amp;qualified items</string>
			<string id="flag5">Filter only what is &amp;visible</string>
			<string id="flag6">&amp;Search Mode</string>
			<string id="flags_quickkey">When typing in the FAYT filter the entered character, an internal dialog for setting flags will be activated.</string>
			<string id="labels_access">Choose whether the filtering by labels should include all or only those visible in the Label Column.</string>
			<string id="max_history_size">Maximum number of entries to be remembered.</string>
			<string id="preferred_filter_mode">Choose the method to get the data from a Script, Evaluator or Shell column.
Textual Filters : Faster, no temporary files.
Rename Preset : Slower, with temporary files. Deprecated, mostly keep it as a legacy.</string>
			<string id="user_defined_implicit_column">In implicit mode, filter by this column, if it exists. If not, the Name column will be used.</string>
		</strings>
		<strings lang="esm">
			<string id="add_column">Tras realizar la búsqueda, añadir la columna referenciada a la pestaña con los resultados.</string>
			<string id="collection_name">Nombre de la colección usada para los resultados.</string>
			<string id="create_subcollections">Crear subcolecciones en lugar de sobreescribir los resultados de la búsqueda.</string>
			<string id="custom_columns_categories">Acá puede definir el tipo de dato que devuelve una columna. Usado para columnas Script, Evaluator y Shell.
Formato: &quot;&lt;nombre&gt;&quot;:&quot;&lt;tipo&gt;&quot;
&lt;nombre&gt; debe ser el mismo valor que el nombre (keyword) de la columna. 
&lt;tipo&gt; puede ser string, date, duration, number o size.</string>
			<string id="custom_columns_names">Defina nombres personalizados para referirse a una columna específica, utilizando la siguiente sintaxis:
mycolname:&lt;nombre col&gt;
Donde &lt;nombre col&gt; es el nombre interno de la columna. (Pulse dos veces la tecla rápida de este comando para mostrar una lista de los nombres de columna actuales.
No utilice ningún operador (&gt;,&lt;,= o !) para el valor de mycolname.</string>
			<string id="debug">Nivel de registro a mostrar. OFF para no mostrar ninguno. 
INFO para mostrar todos los mensajes. STANDARD para mostrar los más relevantes.
WARNING para mostrar errores de consideración.</string>
			<string id="default_implicit_column">Si no se especifica una columna de manera explícita, elegir entre buscar por nombre, según la columna activa/seleccionada o el valor de user_defined_implicit_column.</string>
			<string id="enable_wildcards">Habilitar el soporte para comodines estándar de Opus.</string>
			<string id="flag0">Distinguir &amp;mayúsculas</string>
			<string id="flag1">&amp;Palabras completas</string>
			<string id="flag2">E&amp;xpresiones regulares</string>
			<string id="flag3">Ignorar &amp;diacriticos</string>
			<string id="flag4">Ignorar archivos no &amp;calificables</string>
			<string id="flag5">Filtrar solamente &amp;visibles</string>
			<string id="flag6">Modo &amp;Búsqueda</string>
			<string id="flags_quickkey">Al escribir en el filtro FAYT el caracter introducido, se activará un diálogo interno para la configuración de flags.</string>
			<string id="labels_access">Elija si el filtrado por etiquetas debería incluir todas o solo aquellas visibles en la Columna Etiqueta.</string>
			<string id="max_history_size">Número máximo de entradas a recordar.</string>
			<string id="preferred_filter_mode">Establecer la forma a emplear para obtener los datos de columnas de Script, Evaluator y Shell.
Textual Filters : Más rápido, no hay archivos temporales.
Rename Preset : Más lento, con archivos temporales. Se mantiene por razones de compatibilidad.</string>
			<string id="user_defined_implicit_column">En modo implícito, filtrar por esta columna, si existiese. De lo contrario, se utilizará la columna Nombre.</string>
		</strings>
	</resource>
	<resource name="configflags" type="dialog">
		<dialog fontsize="9" height="110" lang="english" width="180">
			<languages>
				<language height="110" lang="esm" width="180" />
			</languages>
			<control height="10" name="flag0" type="check" width="170" x="4" y="4" />
			<control height="10" name="flag1" type="check" width="170" x="4" y="16" />
			<control height="10" name="flag2" type="check" width="170" x="4" y="28" />
			<control height="10" name="flag3" type="check" width="170" x="4" y="40" />
			<control height="10" name="flag4" type="check" width="170" x="4" y="52" />
			<control height="10" name="flag5" type="check" width="170" x="4" y="64" />
			<control height="10" name="flag6" type="check" width="170" x="4" y="76" />
			<control height="14" name="ok_btn" title="Save" type="button" width="50" x="126" y="92">
				<languages>
					<language height="14" lang="esm" title="Guardar" width="50" x="126" y="92" />
				</languages>
			</control>
		</dialog>
	</resource>
	<resource name="simple" type="dialog">
		<dialog fontsize="9" height="220" lang="english" resize="yes" width="154">
			<languages>
				<language height="220" lang="esm" width="154" />
			</languages>
			<control halign="center" height="8" name="message" resize="w" type="static" valign="center" width="140" x="6" y="134" />
			<control halign="left" height="8" name="category_title" title="Type :" type="static" valign="center" width="20" x="6" y="18">
				<languages>
					<language height="8" lang="esm" title="Tipo :" width="20" x="6" y="18" />
				</languages>
			</control>
			<control height="40" name="category_combo" resize="w" type="combo" width="64" x="30" y="16" />
			<control halign="left" height="12" name="query_edit" resize="w" type="edit" width="128" x="6" y="30" />
			<control height="10" name="use_and_checkbox" title="&amp;Use AND" type="check" width="42" x="4" y="46">
				<languages>
					<language height="10" lang="esm" title="&amp;Usar AND" width="42" x="4" y="46" />
				</languages>
			</control>
			<control checkboxes="auto" fullrow="yes" height="150" multisel="yes" name="listview" resize="wh" type="listview" viewmode="details" width="146" x="4" y="58">
				<columns>
					<item text="Value" />
					<item text="Count" />
				</columns>
			</control>
			<control height="8" name="more_options" resize="x" title="&lt;b&gt;&lt;a id=&quot;more_options&quot;&gt;More options&lt;/a&gt;&lt;/b&gt;" type="markuptext" width="46" x="102" y="46">
				<languages>
					<language height="8" lang="esm" title="&lt;b&gt;&lt;a id=&quot;link&quot;&gt;Más opciones&lt;/a&gt;&lt;/b&gt;" width="46" x="102" y="46" />
				</languages>
			</control>
			<control height="12" name="clear_btn" resize="x" title="❌" type="button" width="15" x="134" y="30" />
			<control enable="no" height="12" name="save_cat_btn" resize="x" title="Save Category" type="button" width="52" x="98" y="16">
				<languages>
					<language height="12" lang="esm" title="Guardar cat." width="52" x="98" y="16" />
				</languages>
			</control>
			<control height="8" name="other_btn" resize="xy" title="&lt;a id=&quot;swap&quot;&gt;&lt;%ddbi:43&gt;&lt;/a&gt;&lt;%sp:18&gt;&lt;a id=&quot;clear&quot;&gt;&lt;%ddbi:1&gt;&lt;/a&gt;&lt;%sp:18&gt;&lt;a id=&quot;refresh&quot;&gt;&lt;%oned:4&gt;&lt;/a&gt;" type="markuptext" width="46" x="104" y="210" />
			<control edit="yes" height="40" name="name_combo" resize="w" sort="yes" type="combo" width="112" x="4" y="2" />
			<control changelinkcolor="no" height="8" icon="1" name="total_title" resize="yw" type="markuptext" width="94" x="4" y="210" />
			<control height="12" name="tocoll_btn" resize="x" title="To &amp;Coll" type="button" width="32" x="118" y="2">
				<languages>
					<language height="12" lang="esm" title="A &amp;Colec." width="32" x="118" y="2" />
				</languages>
			</control>
		</dialog>
	</resource>
</resources>
