// Title of toolset: Macro Developer Toolset
// 16/10/2006
// Description:
// The "Macro Developer Toolset" ImageJ tool bar icons provides a live update of the ImageJ macros repertory and
// Internet resources access for ImageJ macro programmers. 
// It allows Macros, Tools, and Toolsets editing, and making macros and tool plugin shortcuts.
// Details are given in "about" icons.

// --------
// This toolset is based on the MacrosAndToolsUpdater (available at http://rsb.info.nih.gov/ij/macros/tools/MacrosAndToolsUpdater.txt)
// and on the MacroPluginShortcutsTool (available at http://rsb.info.nih.gov/ij/macros/tools/MacroPluginShortcutsTool.txt)

// Author : Gilles Carpentier
// Faculte des Sciences et Technologies,
// Universite Paris 12 Val de Marne, France.

var distantmacrosrep = "http://rsb.info.nih.gov/ij/macros/";
var distanttoolsrep = "http://rsb.info.nih.gov/ij/macros/tools/";
var distanttoolsetsrep = "http://rsb.info.nih.gov/ij/macros/toolsets/";
var distantfunctionsrep = "http://rsb.info.nih.gov/ij/developer/macro/functions.html";
var distantnews = "http://rsb.info.nih.gov/ij/notes.html";

// set the next line to the url of the macro list
var urllist="http://image.bio.methods.free.fr/ij/ijupdatetest/ListOfMacros.txt";distantmacrolink = "";
var KindOfMacro=0,report=0,updates=0,nMacroinL=0,nToolinL=0,nToolsetsinL=0,TheReport="";

var KindOfMacros= 0,sortoption=0;
var favoritefoldername= "My Favorite Macros";
var macroname= "",optionchoice="Only macro sets and tools",onlinechoice="ImageJ on line MACRO FUNCTIONS list";
var kindchoice="Only macro sets";

macro "On Line Macro Global Update Action Tool-  "{
	requires("1.37t");
	distantmacrolink = urllist;
	if (File.openUrlAsString(distantmacrolink) == "") exit("You need an internet access to run this function.");
	Dialog.create("Macro & Tool Updater");
	Dialog.addMessage("The updater will look for new available macros, tools and toolsets.");
	Dialog.addMessage("\nChoose Updater Options:");
	Dialog.addCheckbox("- Check for macros, tools and toolsets updates (longer query):", 0);
	Dialog.addMessage("This option check for modifications, corrections or improvements \nfor the Macros, Tool and Toolsets already installed onto your \nImageJ version.");
	Dialog.addMessage("\n ");
	Dialog.addCheckbox("- Make an installation report.", 1);
	Dialog.show();
	updates= Dialog.getCheckbox();
	report= Dialog.getCheckbox();
	// To get the contents of the distant list of macros.
	showStatus("Internet link...");
	macrotextnih =File.openUrlAsString(distantmacrolink);
	showStatus("");
	// To obtain the separated lists of macros and tools from the distant file list.
	lines=split(macrotextnih,"\n");
	getMandTNumber (lines);
	lMacro = newArray(nMacroinL); lTool = newArray(nToolinL);  lToolsets = newArray(nToolsetsinL);
	lMacro = lPlace (lines,lMacro,"Macro "); lTool = lPlace (lines,lTool,"Tool "); lToolsets = lPlace (lines,lToolsets,"Toolset ");
	// To get the contents of local ImageJ (Macros, Tools, Toolsets) folders, into separated lists of macros, tools and toolsets.
	if (getDirectory("macros") == "") exit ("Unable to find the macros directory; something wrong in the ImageJ folder.");
	macrosfolder = getDirectory("macros");
	macrostoolslocation = macrosfolder + "tools/";
	if (File.isDirectory(macrostoolslocation) == 0) {
		toolsDir = macrostoolslocation+File.separator;
		File.makeDirectory(toolsDir);
		if (!File.exists(toolsDir)) exit("Unable to create the \" tools \" directory, something wrong in the ImageJ folder");
	}
	macrostoolsetlocation = macrosfolder + "toolsets/";
	if (File.isDirectory(macrostoolsetlocation) == 0) {
		toolsetsDir = macrostoolsetlocation+File.separator;
		File.makeDirectory(toolsetsDir);
		if (!File.exists(toolsetsDir)) exit("Unable to create the \" toolsets \" directory, something wrong in the ImageJ folder");
	}
	listofmacro = getFileList(macrosfolder); listoftools = getFileList(macrostoolslocation);listoftoolsets = getFileList(macrostoolsetlocation);

	NbMacro= getMacroNumber (listofmacro); NbTools= getMacroNumber (listoftools); NbToolsets= getMacroNumber (listoftoolsets); NbToolsandMacros=(NbMacro + NbTools +NbToolsets);
	FMacros = newArray(NbMacro); FTools =newArray(NbTools); FToolsets =newArray(NbToolsets);
	FMacros = lPlace (listofmacro,FMacros,""); FTools = lPlace (listoftools,FTools,""); FToolsets =lPlace (listoftoolsets,FToolsets,"");
 
	// To get the new macros, tools and toolsets present in the list, not present into the local ImageJ .
	nbNewMacro= (nMacroinL - nbThings(lMacro,FMacros)); nbNewTools= (nToolinL - nbThings(lTool,FTools));nbNewToolsets= (nToolsetsinL - nbThings(lToolsets,FToolsets));
	NewMacros = newArray(nbNewMacro); NewTools =newArray(nbNewTools);NewToolsets =newArray(nbNewToolsets);
	NewMacros = PlaceNewThings (lMacro,FMacros,NewMacros); NewTools = PlaceNewThings (lTool,FTools,NewTools);NewToolsets = PlaceNewThings (lToolsets,FToolsets,NewToolsets);

	// To get the new macros and tool updates available for the local ImageJ macros and tools.
	if(updates==1) {
		SortedNewMacros = newArray(NbMacro);
		UpdatedMacro = newArray(Nbmacroupdates (FMacros,lMacro,distantmacrosrep,macrosfolder,SortedNewMacros));
		UpdatedMacro = placeUpdatemacro(UpdatedMacro,FMacros,SortedNewMacros);
		SortedNewTools = newArray(NbTools);
		UpdatedTool = newArray(Nbmacroupdates (FTools,lTool,distanttoolsrep,macrostoolslocation,SortedNewTools));
		UpdatedTool = placeUpdatemacro(UpdatedTool,FTools,SortedNewTools);
		SortedNewToolsets = newArray(NbToolsets);
		UpdatedToolsets = newArray(Nbmacroupdates (FToolsets,lToolsets,distanttoolsetsrep,macrostoolsetlocation,SortedNewToolsets));
		UpdatedToolsets = placeUpdatemacro(UpdatedToolsets,FToolsets,SortedNewToolsets);
 
	} else {UpdatedMacro=0;UpdatedTool=0;UpdatedToolsets=0;}
	// To make a dialog box to the user.
	Messagenew=""; messageupdat="";

	message1="- No Macro, Tool or Toolset update available.";
	message2="- There is no new Macro, Tool or Toolset available.";
	message3="- Macros, Tools and Toolsets Updates were not queried.";
	if ((NewMacros.length + NewTools.length +NewToolsets.length) > 0) {
				Messagenew = "- There are "+ NewMacros.length + " new Macro(s), " + NewTools.length + " new Tool(s) and " + NewToolsets.length + " new Toolset(s), available on line.";
	} else {Messagenew = message2;}

	if(updates==1) {
		if ((UpdatedMacro.length + UpdatedTool.length + UpdatedToolsets.length) > 0) {
			messageupdat="- There are "+ UpdatedMacro.length + " Macro(s), "+ UpdatedTool.length +" Tool(s) and "+ UpdatedToolsets.length +" Toolset(s), updates available on line.";
		} else {messageupdat= message1;}
	} else {messageupdat = message3;} 
	continue = "";
	if ((messageupdat != message3) ||  (Messagenew != message2)) continue = " \n-> Perform the installation?";
	if ((Messagenew== message2) && (messageupdat== message1)) exit("No new macro, tool or toolset update available: your ImageJ Macro folder is up to date.");
	showProgress(1.0);
	showMessageWithCancel("Installation User Confirmation",Messagenew +"\n"+ messageupdat + "\n"+ continue);
	if (continue == "") exit;
	// To perform the installation of the new macros and tools.
	if ((NewMacros.length + NewTools.length + NewToolsets.length) > 0) {
		instalmacro(NewMacros,distantmacrosrep,macrosfolder);
		instalmacro(NewTools,distanttoolsrep,macrostoolslocation);
		instalmacro(NewToolsets,distanttoolsetsrep,macrostoolsetlocation);
	}
	// To update the macros and tools.
	if (updates==1) {
		if ((UpdatedMacro.length + UpdatedTool.length + UpdatedToolsets.length) > 0) {
			archmacros(UpdatedMacro,macrosfolder,"Archived Macros");
			archmacros(UpdatedTool,macrostoolslocation,"Archived Tools");
			archmacros(UpdatedToolsets,macrostoolsetlocation,"Archived Toolsets");
			instalmacro(UpdatedMacro,distantmacrosrep,macrosfolder);
			instalmacro(UpdatedTool,distanttoolsrep,macrostoolslocation);
			instalmacro(UpdatedToolsets,distanttoolsetsrep,macrostoolsetlocation);
		}
	}
	// To make the installation report.
	if (report==1) rapport (FMacros,FTools,FToolsets,lMacro,lTool,lToolsets,NewMacros,NewTools,NewToolsets,UpdatedMacro,UpdatedTool,UpdatedToolsets,macrosfolder,"Update reports");
}
	// Contents of arrays:
	// FMacros, FTools ; lists of macros and tools into your ImageJ.
	// lMacro, lTool, lToolsets ; lists of macros, tools and toolsets into the online ImageJ macro list.
	// NewMacros, NewTools, NewToolsets ; lists of macros, tools and toolsets into the online ImageJ macro list.
	// UpdatedMacro, UpdatedTool, UpdatedToolsets ; lists of macros , tools and toolsets updates available on the ImageJ web site.

macro "On line macros resources Action Tool -  "{
	requires("1.37t");
	if (File.openUrlAsString(urllist) == "") exit("You need an internet access to run this function.");

	Dialog.create("On line macros resources");
	Dialog.addMessage("Get online macros, tools, toolsets, global listing and ImageJ News.");
	Dialog.addMessage("\n- Options:");
	Dialog.addChoice("->",newArray("ImageJ on line MACROS collection","ImageJ on line TOOLS collection","ImageJ on line TOOLSETS collection","ImageJ on line MACRO FUNCTIONS list","ImageJ News","ImageJ macro, tool and toolset listing"),toString(onlinechoice));
	Dialog.show();
	onlinechoice = Dialog.getChoice();
	if (onlinechoice=="ImageJ on line MACROS collection") run("URL...", "url=["+distantmacrosrep+"]");
	if (onlinechoice=="ImageJ on line TOOLS collection") run("URL...", "url=["+distanttoolsrep+"]");
	if (onlinechoice=="ImageJ on line TOOLSETS collection") run("URL...", "url=["+distanttoolsetsrep+"]");
	if (onlinechoice=="ImageJ on line MACRO FUNCTIONS list") run("URL...", "url=["+distantfunctionsrep+"]");
	if (onlinechoice=="ImageJ macro, tool and toolset listing") run("URL...", "url=["+urllist+"]");
	if (onlinechoice=="ImageJ News") run("URL...", "url=["+distantnews+"]");
}

macro "About On Line Macro Global Update Action Tool -  " {
	about1();
}

macro "Install Macro Plugins Shortcuts Action Tool -  "{	// A tool making plugin shortcut for macros and tools:
	// A plugin shortcut is available after ImageJ restarting, in the <Plugins> <My Favorite Macros> menu.
	requires("1.37t");
	choicemenu=newArray("Only macro sets and tools", "All macros");
	Dialog.create("Macro & Tool Sort Choice");
	Dialog.addMessage("Display Macro sets and Tools only, or all kind of macros?\n(\"all macros\" option gives a very long list, less manageable).");
	Dialog.addChoice("->",choicemenu,toString(optionchoice));
	Dialog.show();
	optionchoice= Dialog.getChoice();
	if (optionchoice == "Only macro sets and tools") sortoption=0;
	if (optionchoice == "All macros") sortoption=1;

	macroname = GetMacroListMenu ();
	InstallPluginsStarter(macroname,1);
}

macro "About Install Macro Plugins Shortcuts Action Tool -  " {
	about2();
}

macro "Edit a Macro Action Tool - C059T3e16M" {
	theFolder="";sortoption=0;choicemenu=newArray("Only macro sets", "All macros");
	Dialog.create("Macro & Tool Sort Choice");
	Dialog.addMessage("Display Macro sets only, or all kind of macros?\n(\"all macros\" option gives a very long list, less manageable).");
	Dialog.addChoice("->",choicemenu,toString(kindchoice));
	Dialog.show();
	kindchoice= Dialog.getChoice();
	if (kindchoice == "Only macro sets") {sortoption=0;kind="Macro Set";}
	if (kindchoice == "All macros") {sortoption=1;kind="All Macro";}
	makeapopup (theFolder,sortoption,kind);
}
macro "Edit a Tool Action Tool - C059T3e16T" {
	theFolder="tools/";sortoption=0;kind="Tool";
	makeapopup (theFolder,sortoption,kind);
}
macro "Edit a Toolset Action Tool - C059T0e16TT9e14S" {
	theFolder="toolsets/";sortoption=0;kind="Toolset";
	makeapopup (theFolder,sortoption,kind);
}


// ---- functions ----- //
// Function giving the number (NumberOfMacro) of macros and tools contained a list (lmacros).
function getMacroNumber (lmacros) {
	NumberOfMacro=0;
     	for (i=0; i<lmacros.length; i++) {
         	showProgress(i,lmacros.length);
		if (endsWith(lmacros[i], ".txt") || endsWith(lmacros[i], ".ijm")) NumberOfMacro ++;	}
	return NumberOfMacro;
}

// Function giving the macros number (nMacroinL) and the tools number (nToolinL) containened in an array (lmacros).
// macros are sorted according .txt or .img and 'Macro' or 'Tool' prefixes.
function getMandTNumber (lmacros) {
	nMacroinL=0;nToolinL=0;nToolsetsinL=0;
     	for (i=0; i<lmacros.length; i++) {
         	showProgress(i,lmacros.length);
		if (endsWith(lmacros[i], ".txt") || endsWith(lmacros[i], ".ijm")) {
			if (startsWith(lmacros[i], "Macro ")) nMacroinL ++;
			if (startsWith(lmacros[i], "Tool ")) nToolinL ++;
			if (startsWith(lmacros[i], "Toolset ")) nToolsetsinL ++;
		}		
	}
}

// Function giving the list of macros (Lele) with the prefix (kind) contained in the list (lmacros).
function lPlace (lmacros,Lele,kind) {
	compteur=0;
     	for (i=0; i<lmacros.length; i++) {
         	showProgress(i,lmacros.length);
		if (endsWith(lmacros[i], ".txt") || endsWith(lmacros[i], ".ijm")) {
			if (startsWith(lmacros[i], kind)) {
				Lele[compteur]=substring(lmacros[i],lengthOf(kind),lengthOf(lmacros[i]));
				compteur ++;
			}
		}		
	}
	return Lele;
}

// Function setting in the report  (TheReport) the contents of the list (tab), adding the prefix (prefix).
function listit (tab,prefix) {
	for (i=0; i<tab.length; i++) {
		TheReport=TheReport + "\n"+ prefix+tab[i];
	}
}

// Function giving the number of elements contained in the first list (liste1) and in the second list (liste2).
function nbThings(liste1,liste2) {
	compteur=0;
     	for (i=0; i<liste1.length; i++) {
		showProgress(i,liste1.length);
		for (j=0; j<liste2.length; j++) {
			if (liste1[i]==liste2[j]) compteur ++;
		}
	}
	return compteur;
}

// Function giving the list of elements (New) contained in the first list (liste1) and in the second list (liste2).
function PlaceNewThings (liste1,liste2,New) {
	newcompteur=0;
	test=0;
	for (i=0; i<liste1.length; i++) {
		showProgress(i,liste1.length);
		for (j=0; j<liste2.length; j++) {
			if (liste1[i]==liste2[j]) test ++;
		}
		if (test==0) {
			New[newcompteur]=liste1[i];
			newcompteur ++;
		}
		test=0;
	}
	return New;
}

// Function sorting the number of elements (compteur) which are macros and tools and can be updated (sorted [n], if n=1 the macro is updatable).
function Nbmacroupdates (macrolocalist,macrodistlist,urlrep,localrep,sorted) {
	compteur=0;
	for (i=0; i<macrolocalist.length; i++) {
		showProgress(i,macrolocalist.length);
		for (j=0; j<macrodistlist.length; j++) {
			if (macrolocalist[i]==macrodistlist[j]) {
				macrotextnih=getdistantmacro (macrodistlist[j],urlrep);				macropath = localrep + macrolocalist[i];
				if (File.exists(macropath)) {
					thelocalmacro = File.openAsString(macropath);
					if (thelocalmacro != macrotextnih) {
						compteur=compteur+1;
						sorted[i]=1;
					}
				}
			}
		}
	}
	return compteur;
}

// Function giving the list (listupdate) of macros and tools which can be updated.
function placeUpdatemacro(listupdate,locallist,Sorted) {
	compteur=0;
	for (i=0; i<Sorted.length; i++) {
		if (Sorted[i] == 1) {
			listupdate[compteur]=locallist[i];
			compteur++;
		}
	}
	return listupdate;
}

// Function archiving the old macros.
function archmacros(list,localrep,foldername){
	// Create an Archived Tools directory in tools repertory
	if (list.length > 0) {
		ArchDir = localrep+foldername+File.separator;
		File.makeDirectory(ArchDir);
		if (!File.exists(ArchDir)) exit("Unable to create the "+foldername+" directory, something wrong in the ImageJ folder");
	}
	for (i=0; i<list.length; i++) {
		if (File.exists(localrep+list[i])) {
			thelocalmacro = File.openAsString(localrep+list[i]);
			f= File.open(ArchDir + list[i]);
			print (f,thelocalmacro);
			File.close(f);
		}
	}
}

// Function installing a list (list) of distant macro located at (urlrep), into the local folder (localrep).
function instalmacro(list,urlrep,localrep){
	for (i=0; i<list.length; i++) {
		macrotextnih= getdistantmacro (list[i],urlrep);
		f= File.open(localrep + list[i]);
		print (f,macrotextnih);
		File.close(f);
	}
}

// Function giving the content of a distant macro (name) located at the distant repertory (urlrep).
function getdistantmacro (name,urlrep) {
	distantmacrolink = urlrep + name;
	if (indexOf(distantmacrolink, " ") > -1) {
		while (indexOf(distantmacrolink, " ") > -1) {
			distantmacrolink=substring(distantmacrolink, 0, (indexOf(distantmacrolink, " ")))+"%20"+substring(distantmacrolink, (indexOf(distantmacrolink, " ")+1),lengthOf(distantmacrolink) );
		}
	}
	showStatus("Internet link...");
	macrotextnih =File.openUrlAsString(distantmacrolink);
	showStatus("");
	return macrotextnih;
}

// Function making a detailed report of every list obtained.
function rapport (FMacros,FTools,FToolsets,lMacro,lTool,lToolsets,NewMacros,NewTools,NewToolsets,UpdatedMacro,UpdatedTool,UpdatedToolsets,localrep,foldername) {
	TheReport="";
	getDateAndTime(year, month, dayOfWeek, dayOfMonth, hour, minute, second, msec);
	reportname=  ""+dayOfMonth+"-"+(month+1) +"-"+year+" at "+hour+"."+minute+"."+second+"";
	TheReport=TheReport + "Installation report for the update performed on: "+reportname;
	if ((NewMacros.length+NewTools.length +NewToolsets.length)>0) {
		TheReport=TheReport +"\n\n--- The following new Macros, Tools and Toolsets have been installed: ";
		TheReport=TheReport + "("+(NewMacros.length+NewTools.length+NewToolsets.length)+" Macros: "+NewMacros.length+ " \"macros\" , "+NewTools.length+" \"tools\" & "+NewToolsets.length+" \"toolsets\" ):";
		listit (NewMacros,"Macro ");
		if (NewTools.length > 0) TheReport=TheReport + "\n--------";
		listit (NewTools,"Tool ");
		if (NewToolsets.length > 0) TheReport=TheReport + "\n--------";
		listit (NewToolsets,"Toolset ");
	}
	if(updates==1) {
		TheReport=TheReport + "\n\n--- The following Macros, Tools and Toolsets update have been performed: ";
		TheReport=TheReport +"("+(UpdatedMacro.length+UpdatedTool.length+UpdatedToolsets.length)+" Macros: "+UpdatedMacro.length+ " \"macros\" , "+UpdatedTool.length+" \"tools\" & "+UpdatedToolsets.length+" \"toolsets\"):";
		listit  (UpdatedMacro,"Macro ");
		if (UpdatedTool.length > 0) TheReport=TheReport + "\n--------"; listit (UpdatedTool,"Tool ");
		if (UpdatedToolsets.length > 0) TheReport=TheReport + "\n--------"; listit (UpdatedToolsets,"Toolset ");
	}
	if (updates==0) TheReport=TheReport + "\n\n--- The Macros, Tools and Toolsets updated have not been queried.";
	TheReport=TheReport + "\n\n--- Note: the list of macros, tools and toolsets installed onto you computer before this update ---";
	TheReport=TheReport + "\n      ("+(FMacros.length+FTools.length+ FToolsets.length)+" Macros: "+ FMacros.length + " \"macros\" , "+FTools.length+" \"tools\" & "+ FToolsets.length+" \"toolsets\"):";
	listit (FMacros,"Macro ");TheReport=TheReport +"\n--------";listit (FTools,"Tool ");TheReport=TheReport +"\n--------";listit (FToolsets,"Toolset ");

	TheReport=TheReport +"\n\n--- Note: the list of macros, tools and toolsets available at the ImageJ web site ---";
	TheReport=TheReport + "\n      ("+(lMacro.length+lTool.length+ lToolsets.length)+" Macros: "+ lMacro.length + " \"macros\" , "+lTool.length+" \"tools\" & "+ lToolsets.length +" \"toolsets\"):";
	listit (lMacro,"Macro "); TheReport=TheReport +"\n--------"; listit (lTool,"Tool ");TheReport=TheReport +"\n--------"; listit (lToolsets,"Toolset ");
	UpdateReports = localrep+foldername+File.separator;
	File.makeDirectory(UpdateReports);
	if (!File.exists(UpdateReports)) exit("Unable to create the "+foldername+" directory, something wrong in the ImageJ folder");
	f= File.open(UpdateReports + reportname+".txt" );	print (f,TheReport);
	File.close(f);
	if (File.exists(UpdateReports + reportname+".txt")) open(UpdateReports + reportname+".txt");
}

function about1() {
	about="";
	about=about + "The \"On Line Macro Global Update\" tool bar icon perfoms a live update of the ImageJ macros repertory.";
	about=about + "\n  - It looks for new and updated macros, tools and toolsets, and installs them.";
	about=about + "\n  - The old versions are archived.";
	about=about + "\n  - An installation report is given.";
	about=about + "\nnote: the list of the macros, tools and toolsets available onto the ImageJ website can be obtained";
	about=about + "\nby the \"On line macros resources\" ImageJ tool bar icon.";
	about=about + "\n------------------------------------------------------------------------------------------ ";
	about=about + "\nNotice:";//about=about +"\n  ";
	about=about + "\n- To look for new macros, tools and toolsets, click on the \"Global Macro Updater\" ImageJ tool bar icon,";
	about=about +"\nand keep default settings.";
	about=about +"\n- To look for macros, tools and toolsets updates, click on the \"Global Macro Updater\" ImageJ bar icon,";
	about=about +"\nand select the checkbox \"- Check for macros, tools and toolsets updates (longer query):\".";
	about=about +"\n  ";
	about=about +"\nnote: The update report is stored into the \"Update reports\" repertory (ImageJ/macros/Update reports).";
	about=about +"\nOld macros, tools and toolsets versions are archived at:";
	about=about +"\n- macros: ImageJ/macros/UpdateArchived Macros";
	about=about +"\n- tools: ImageJ/macros/tools/Archived Tools";
	about=about +"\n- toolsets: ImageJ/macros/toolsets/Archived Toolsets";
	about=about + "\n------------------------------------------------------------------------------------------ ";
	about=about +"\nAuthor : Gilles Carpentier"+"\nFaculte des Sciences et Technologies"+"\nUniversite Paris 12 Val de Marne, France.";
	showMessage(about);
}

// functions for the Install Macro Plugins Shortcuts 
function InstallPluginsStarter(macroname,comment) {
	codemacrostarter ="run\(\"Install...\", \"install=[\"+getDirectory(\"macros\")+\"" + macroname + "\]\"\);";
	codetoolstarter = "run\(\"Install...\", \"install=[\"+getDirectory(\"macros\")+\"tools/" + macroname + "\]\"\);";
	StarterDir = getDirectory("startup") + favoritefoldername + "/";
	if (getDirectory("plugins") == "") exit ("Unable to find the Plugins directory; something wrong in the ImageJ folder.");
	pluginlocation = getDirectory("plugins");
	pluginname = ShortMacroName (macroname);
	// Create a <favoritefoldername> repertory in the ImageJ Plugins folder.
	StarterDir = pluginlocation+favoritefoldername+File.separator;
	File.makeDirectory(StarterDir);
	if (!File.exists(StarterDir)) exit ("Unable to create Image Bio Methods Macros directory, something wrong in the ImageJ folder.");
	starterplugin = StarterDir + pluginname +"_ .ijm";
	//Write the new macro
	codestarter=codemacrostarter;
	if (KindOfMacro == 1) codestarter=codetoolstarter;
	f= File.open(starterplugin);
	print (f,codestarter);
	File.close(f);
	if (comment==1) {
		showMessage ("Installation of the Plugin \"" +pluginname+ "\" is completed.\nIt will be available after ImageJ restarting, in the \"Plugins->" + favoritefoldername + "\" menu.");
	}
}

function GetMacroListMenu () {
	if (getDirectory("macros") == "") exit ("Unable to find the macros directory; something wrong in the ImageJ folder.");
	macrostoolslocation = getDirectory("macros") + "tools/";
	if (File.isDirectory(macrostoolslocation) == 0) exit ("Unable to find the tools directory on the macros directory; something wrong in the ImageJ folder.");
	macrosfolder = getDirectory("macros");
	listofmacro = getFileList(macrosfolder); listoftools = getFileList(macrostoolslocation);
	NbMacro= getMacrosNumber (listofmacro,sortoption,macrosfolder); NbTools= getMacrosNumber (listoftools,sortoption,macrostoolslocation); NbToolsandMacros=(NbMacro + NbTools);
	MacrosandTools1 = newArray(NbToolsandMacros+2); MacrosandTools1[0] =-1;
	MacrosandTools2 = newArray(NbToolsandMacros+2); MacrosandTools2[0] ="--- Macro List ---";PlaceOfMacro=1;
	PlaceintheMenu(MacrosandTools1,MacrosandTools2,PlaceOfMacro,listofmacro,0,sortoption,macrosfolder);
	MacrosandTools2[NbMacro+1]="--- Tools List ---";
	PlaceintheMenu(MacrosandTools1,MacrosandTools2,(NbMacro+2),listoftools,1,sortoption,macrostoolslocation);
	macrochosen = "--- Macro List ---";
	showProgress(1.0);
	while (macrochosen == "--- Tools List ---" || macrochosen == "--- Macro List ---"){
		Dialog.create("Macro & Tool Choice");
		Dialog.addMessage("Choose a Macro or a Tool in the popup menu\n(list of macros, following by the list of tools):");
		Dialog.addChoice("->",MacrosandTools2);
		Dialog.addMessage("\nNumber of macros="+ NbToolsandMacros + "  ("+NbMacro+" \"Macros\", "+NbTools+" \"Tools\")");
		Dialog.show();
		macrochosen=  Dialog.getChoice();
		for (i=1; i<=NbToolsandMacros; i++) {
			if (MacrosandTools2[i] == macrochosen) KindOfMacro = MacrosandTools1[i];
		}
	}
	return macrochosen;
}

function ShortMacroName (longname) {
	shortnames = longname;
	if (endsWith(longname, ".txt") || endsWith(longname, ".ijm")) shortnames = substring(longname, 0, (lengthOf(longname)-4));
	return shortnames;
}

function getMacrosNumber (lmacros,sortoption,dirmac) {
	NumberOfMacro=0;
     	for (i=0; i<lmacros.length; i++) {
         	showProgress(i,lmacros.length);
		if (endsWith(lmacros[i], ".txt") || endsWith(lmacros[i], ".ijm")) {
			if (sortoption == 1) NumberOfMacro ++;
			if (sortoption == 0) {
				testmac=sort(dirmac,lmacros[i]);
				if (testmac==1) NumberOfMacro ++;
			}
		}		
	}
	return NumberOfMacro;
}

function PlaceintheMenu (MacrosandTools1,MacrosandTools2,place,listdir,kind,sortoption,dirmac) {
     	for (i=0; i< listdir.length; i++) {
         	showProgress(i, listdir.length);
		if (endsWith(listdir[i], ".txt") || endsWith(listdir[i], ".ijm")) {
			if (sortoption == 1) {
				MacrosandTools1[place]=kind; MacrosandTools2[place] =listdir[i];
				place ++;
			}
			if (sortoption == 0) {
				testmac=sort(dirmac,listdir[i]);
				if (testmac==1) {
					MacrosandTools1[place]=kind; MacrosandTools2[place] =listdir[i];
					place ++;
				}
			}		
		}
	}
	return MacrosandTools1;
	return MacrosandTools2;
}

function sort(dirmac,mac) {
	testmac=0;
	macropath=dirmac+mac;
	macrocontent = File.openAsString(macropath);
	nummacro=nmac(macrocontent, "macro");
	if (nummacro >1)  testmac=1;
	if (indexOf(macrocontent, "Tool")>0) testmac=1;
	return testmac;
}

function nmac(macrotext,kindof) {
	nummac=0;
	while (indexOf(macrotext, kindof)> -1) {
		macrotext=substring(macrotext, (indexOf(macrotext, kindof)+lengthOf(kindof)), lengthOf(macrotext));
		while (indexOf(macrotext, " ") ==0){macrotext=substring(macrotext,1, (lengthOf(macrotext)));}
		if (startsWith(macrotext, "\"") || startsWith(macrotext, "'" )) nummac ++;
	}
	return nummac;
}

function about2() {
	about="";
	about=about + "The \"Install Macro Plugins Shortcuts\" makes plugin shortcuts for macros and tools.";
	about=about +"\nA plugin shortcut is available after ImageJ restarting, in the \"ImageJ\\Plugins\\My Favorite Macros\" menu,";
	about=about +"\nmaking easier the installation of macros and tools often used.";
	about=about + "\n------------------------------------------------------------------------------------------ ";
	about=about + "\nNotice:";//about=about +"\n  ";
	about=about + "\nTo make a so shortcut, click on the \"Install Macro Plugins Shortcuts\" ImageJ menu bar icon.";
	about=about + "\nChoose \"Only macro sets and tools\" or \"All macros\" option:";
	about=about + "\n- \"Only macro sets and tools\" let the choice between all the tools and only the macros containing at least";
	about=about + "\ntwo\"sub-macros\".";
	about=about + "\n- \"All macros\" allows to make a shortcuts for any macro code file or tool.";
	about=about + "\nChoose into the popup menu the appropriate macro or tool (tools are listed after the macros).";
	about=about + "\nAfter restarting ImageI the chosen macro or tool can be installed by its shortcut in the";
 	about=about + "\n\"ImageJ\\Plugins\\My Favorite Macros\" menu.";

	about=about + "\n------------------------------------------------------------------------------------------ ";
	about=about +"\nAuthor : Gilles Carpentier"+"\nFaculte des Sciences et Technologies"+"\nUniversite Paris 12 Val de Marne, France.";
	showMessage (about);
}

//-- Macros, tools and toolsets editing.

function makeapopup (theFolder,sortoption,kind) {
	if (getDirectory ("macros" )+ theFolder == "") exit ("Unable to find the macros directory; something wrong in the ImageJ folder.");
	Thedir= getDirectory ("macros" ) + theFolder;
	if (File.isDirectory (Thedir) == 0) exit ("Unable to find the macros directory; something wrong in the ImageJ folder.");
	listofmacro = getFileList(Thedir);nbMacro=getMacrosNumber(listofmacro,sortoption,Thedir);
	MacrosOrTools=newArray(nbMacro);place=0;
    	for (i=0; i< listofmacro.length; i++) {
         	showProgress(i, listofmacro.length);
		if (endsWith(listofmacro[i], ".txt") || endsWith(listofmacro[i], ".ijm")) {
			if (sortoption == 1) {
				MacrosOrTools[place] = listofmacro[i];
				place ++;
			}
			if (sortoption == 0) {
				testmac=sort(Thedir,listofmacro[i]);
				if (testmac==1) {
					MacrosOrTools[place] = listofmacro[i];
					place ++;
				}
			}		
		}
	}
	showProgress(1.0);
	macrochosen="";
	while (macrochosen == "") {
		Dialog.create(kind +" Choice");
		Dialog.addMessage("Choose a " + kind +" among the "+MacrosOrTools.length+" available in the popup menu:");
		Dialog.addChoice("->",MacrosOrTools);
		Dialog.show();
		macrochosen=  Dialog.getChoice();
	}
	open(Thedir+macrochosen);
}
