Index: tmp/org.txm.tigersearch.rcp/groovy/org/txm/macro/tiger/exploit/TIGERSVOSummaryMacro.groovy
===================================================================
--- tmp/org.txm.tigersearch.rcp/groovy/org/txm/macro/tiger/exploit/TIGERSVOSummaryMacro.groovy	(revision 2930)
+++ tmp/org.txm.tigersearch.rcp/groovy/org/txm/macro/tiger/exploit/TIGERSVOSummaryMacro.groovy	(revision 2931)
@@ -169,11 +169,13 @@
 			}
 		}
 		
-		writer.writeLine(lineToWrite)
+		def row = writer.writeLine(lineToWrite)
+		row.setHeight(50, true)
 	}
 }
 
 writer.save()
 cpb.done()
+println "Results save in "+new_ods_file.getAbsolutePath()
 
 return results
\ No newline at end of file
Index: tmp/org.txm.tigersearch.rcp/src/org/txm/function/tigersearch/TIGERSearch.java
===================================================================
--- tmp/org.txm.tigersearch.rcp/src/org/txm/function/tigersearch/TIGERSearch.java	(revision 2930)
+++ tmp/org.txm.tigersearch.rcp/src/org/txm/function/tigersearch/TIGERSearch.java	(revision 2931)
@@ -254,7 +254,8 @@
 		}
 		tsresult = tscorpus.query(pQuery);
 		tsresult.getFirst();
-		return true;
+		
+		return tsresult.getNumberOfMatch() > 0;
 	}
 	
 	@Override
Index: tmp/org.txm.tigersearch.rcp/src/org/txm/searchengine/ts/TSCorpus.java
===================================================================
--- tmp/org.txm.tigersearch.rcp/src/org/txm/searchengine/ts/TSCorpus.java	(revision 2930)
+++ tmp/org.txm.tigersearch.rcp/src/org/txm/searchengine/ts/TSCorpus.java	(revision 2931)
@@ -53,39 +53,47 @@
  * The Class TSCorpus.
  */
 public class TSCorpus {
-
+	
 	/** The id. */
 	String id;
-
+	
 	/** The managers. */
 	public TSCorpusManager tsmanager;
+	
 	public InternalCorpusQueryManagerLocal2 manager = null;
+	
 	ExportManager exporter;
-
+	
 	/** The config. */
 	TIGERGraphViewerConfiguration config;
-
+	
 	/** The initok. */
 	boolean initok = false;
-
+	
 	/** The results. */
-	HashMap<Integer, TSResult> results = new HashMap<Integer, TSResult>();
-
+	HashMap<Integer, TSResult> results = new HashMap<>();
+	
 	// Additional data for corpus alignment with TXM base corpus (CQP corpus)
 	RandomAccessFile offsetsRAFile = null;
+	
 	FileChannel offsetsFileChannel = null;
+	
 	MappedByteBuffer offsetsMapped = null; // one offset per tiger position
+	
 	RandomAccessFile presencesRAFile = null;
+	
 	FileChannel presencesFileChannel = null;
+	
 	MappedByteBuffer presencesMapped = null; // one 0/1 boolean per tiger position
-
+	
 	private int[] sentence_starts;
-
+	
 	@Override
 	public void finalize() {
 		try {
 			close();
-		} catch(Exception e) {
+		}
+		catch (Exception e) {
 			e.printStackTrace();
 		}
 	}
@@ -97,7 +105,7 @@
 	 * @param tsmanager the tsmanager
 	 */
 	public TSCorpus(String corpusId, TSCorpusManager tsmanager) {
-
+		
 		String regpath = tsmanager.getRegistryPath();
 		String confpath = tsmanager.getconfPath();
 		try {
@@ -107,27 +115,28 @@
 			
 			manager.getQueryProcessor();
 			config = new TIGERGraphViewerConfiguration(confpath, confpath, confpath);
-			this.id = corpusId;		
+			this.id = corpusId;
 			initok = opencorpus();
 			exporter = new ExportManager(manager, ""); //$NON-NLS-1$
-
-			File offsetsFile = new File(regpath, corpusId+"/offsets.data");
+			
+			File offsetsFile = new File(regpath, corpusId + "/offsets.data");
 			if (offsetsFile.exists()) {
 				offsetsRAFile = new RandomAccessFile(offsetsFile, "rw");
 				offsetsFileChannel = offsetsRAFile.getChannel();
 				offsetsMapped = offsetsFileChannel.map(FileChannel.MapMode.READ_ONLY, 0, offsetsFileChannel.size());
 			}
-
-			//out.putInt(positions[i])
-
-			File presencesFile = new File(regpath, corpusId+"/presences.data");
-
+			
+			// out.putInt(positions[i])
+			
+			File presencesFile = new File(regpath, corpusId + "/presences.data");
+			
 			if (presencesFile.exists()) {
 				presencesRAFile = new RandomAccessFile(presencesFile, "rw");
 				presencesFileChannel = presencesRAFile.getChannel();
 				presencesMapped = presencesFileChannel.map(FileChannel.MapMode.READ_ONLY, 0, presencesFileChannel.size());
 			}
-		} catch (Exception e) {
+		}
+		catch (Exception e) {
 			// TODO Auto-generated catch block
 			org.txm.utils.logger.Log.printStackTrace(e);
 		}
@@ -136,7 +145,7 @@
 	public String getID() {
 		return this.id;
 	}
-
+	
 	public void close() {
 		try {
 			if (presencesRAFile != null) presencesRAFile.close();
@@ -145,170 +154,169 @@
 			if (offsetsFileChannel != null) offsetsFileChannel.close();
 			if (sentence_starts != null) sentence_starts = null;
 			if (results != null) results.clear();
-		} catch (IOException e) {
+		}
+		catch (IOException e) {
 			// TODO Auto-generated catch block
 			e.printStackTrace();
 		}
 	}
-
+	
 	public int getOffset(int tigerPosition) {
 		if (offsetsMapped != null) {
-			return offsetsMapped.getInt(tigerPosition*Integer.BYTES);
-		} else {
+			return offsetsMapped.getInt(tigerPosition * Integer.BYTES);
+		}
+		else {
 			return 0;
 		}
 	}
-
+	
 	public int[] getOffsets(int tigerPositions[]) {
 		int[] ret = new int[tigerPositions.length];
 		if (offsetsMapped != null) {
-			for (int i = 0 ; i < tigerPositions.length ; i++) {
-				ret[i] =  offsetsMapped.getInt(tigerPositions[i]*Integer.BYTES);
+			for (int i = 0; i < tigerPositions.length; i++) {
+				ret[i] = offsetsMapped.getInt(tigerPositions[i] * Integer.BYTES);
 			}
 		}
-
+		
 		return ret;
 	}
-
+	
 	public MappedByteBuffer getOffsetsMapped() {
 		return offsetsMapped;
 	}
-
+	
 	public MappedByteBuffer getPresencesMapped() {
 		return presencesMapped;
 	}
-
+	
 	public int getPresence(int tigerPosition) {
 		if (presencesMapped != null) {
-			return presencesMapped.getInt(tigerPosition*Integer.BYTES);
-		} else {
+			return presencesMapped.getInt(tigerPosition * Integer.BYTES);
+		}
+		else {
 			return 0;
 		}
 	}
-
+	
 	public int[] getPresences(int tigerPositions[]) {
 		int[] ret = new int[tigerPositions.length];
 		if (presencesMapped != null) {
-			for (int i = 0 ; i < tigerPositions.length ; i++) {
-				ret[i] =  presencesMapped.getInt(tigerPositions[i]*Integer.BYTES);
+			for (int i = 0; i < tigerPositions.length; i++) {
+				ret[i] = presencesMapped.getInt(tigerPositions[i] * Integer.BYTES);
 			}
 		}
-
+		
 		return ret;
 	}
-
+	
 	public static boolean createLogPropFile(File directory) {
 		directory.mkdirs();
 		File logprop = new File(directory, "tigersearch.logprop");
 		try {
-			IOUtils.write(logprop, "# Default log configuration of the TIGERSearch suite\n" + 
-					"log4j.rootLogger=SEVERE,Logfile\n" + 
-					"log4j.logger.ims.tiger.gui.tigersearch.TIGERSearch=SEVERE\n" + 
-					"log4j.appender.Logfile=org.apache.log4j.RollingFileAppender\n" + 
-					"log4j.appender.Logfile.File=\\${user.home}/tigersearch/tigersearch.log\n" + 
-					"log4j.appender.Logfile.MaxFileSize=500KB\n" + 
-					"log4j.appender.Logfile.MaxBackupIndex=1\n" + 
-					"log4j.appender.Logfile.layout=org.apache.log4j.PatternLayout\n" + 
+			IOUtils.write(logprop, "# Default log configuration of the TIGERSearch suite\n" +
+					"log4j.rootLogger=SEVERE,Logfile\n" +
+					"log4j.logger.ims.tiger.gui.tigersearch.TIGERSearch=SEVERE\n" +
+					"log4j.appender.Logfile=org.apache.log4j.RollingFileAppender\n" +
+					"log4j.appender.Logfile.File=\\${user.home}/tigersearch/tigersearch.log\n" +
+					"log4j.appender.Logfile.MaxFileSize=500KB\n" +
+					"log4j.appender.Logfile.MaxBackupIndex=1\n" +
+					"log4j.appender.Logfile.layout=org.apache.log4j.PatternLayout\n" +
 					"log4j.appender.Logfile.layout.ConversionPattern=%5r %-5p [%t] %c{2} - %m%n");
-		} catch (Exception e) {
+		}
+		catch (Exception e) {
 			// TODO Auto-generated catch block
 			e.printStackTrace();
 			return false;
 		}
 		return true;
 	}
-
+	
 	public void setDisplayProperties(Header header, List<String> tprops, String ntprop) {
-		config.setDisplayedTFeatures(header, tprops);       
+		config.setDisplayedTFeatures(header, tprops);
 		config.setDisplayedNTFeature(header, ntprop);
 	}
-
-	public InternalCorpusQueryManager getInternalManager()
-	{
+	
+	public InternalCorpusQueryManager getInternalManager() {
 		return manager;
 	}
-
-	public List<String> getNTFeatures()
-	{
-
+	
+	public List<String> getNTFeatures() {
+		
 		return manager.getHeader().getAllNTFeatureNames();
-
+		
 	}
-
-	public List<String> getTFeatures()
-	{
+	
+	public List<String> getTFeatures() {
 		return manager.getHeader().getAllTFeatureNames();
 	}
-
+	
 	/**
 	 * contains a lot of informations about the corpus
+	 * 
 	 * @return
 	 */
-	public Header getHeader()
-	{
+	public Header getHeader() {
 		return manager.getHeader();
 	}
-
+	
 	/**
 	 * Opencorpus.
 	 *
 	 * @return true, if successful
 	 */
-	public boolean opencorpus()
-	{
+	public boolean opencorpus() {
 		try {
 			manager.loadCorpus(id);
-			//manager.getC
 			return true;
 		}
-		catch (Exception e) { System.out.println(TXMCoreMessages.couldntReadCorpusColon+e.getMessage());}
+		catch (Exception e) {
+			System.out.println(TXMCoreMessages.couldntReadCorpusColon + e.getMessage());
+		}
 		return false;
 	}
-
+	
 	/**
 	 * Query.
 	 *
 	 * @param query the query
 	 * @return the tS result
-	 * @throws Exception 
+	 * @throws Exception
 	 */
-	public TSResult query(String query) throws Exception
-	{
+	public TSResult query(String query) throws Exception {
 		return query(query, -1, -1, -1);
 	}
-
+	
 	/**
 	 * Query.
 	 *
 	 * @param query the query
 	 * @return the tS result
-	 * @throws Exception 
+	 * @throws Exception
 	 */
-	public TSResult query(String query, int sent_min, int sent_max, int match_max) throws Exception
-	{
+	public TSResult query(String query, int sent_min, int sent_max, int match_max) throws Exception {
 		if (results.containsKey(query.hashCode()))
 			return results.get(query.hashCode());
-
+		
 		TSResult rez = new TSResult(query, this, sent_min, sent_max, match_max);
 		results.put(query.hashCode(), rez);
 		return rez;
 	}
-
+	
 	/**
 	 * Checks if is ok.
 	 *
 	 * @return true, if is ok
 	 */
-	public boolean isOk() {	
+	public boolean isOk() {
 		return initok;
 	}
-
+	
 	public Index getIndex() {
 		InternalCorpusQueryManagerLocal2 tigermanager = this.manager;
 		CorpusQueryProcessor processor = tigermanager.getQueryProcessor();
 		return processor.getIndex();
 	}
-
+	
 	public int[] getSentenceStartPositions() throws IndexException {
 		if (sentence_starts != null) {
 			return sentence_starts;
@@ -316,10 +324,10 @@
 		Index index = getIndex();
 		
 		sentence_starts = new int[index.getNumberOfGraphs()];
-		for (int i = 0 ; i < index.getNumberOfGraphs() ; i++) {
+		for (int i = 0; i < index.getNumberOfGraphs(); i++) {
 			sentence_starts[i] = 0;
 			if (i > 0) {
-				sentence_starts[i] += index.getNumberOfTNodes(i-1) + sentence_starts[i-1];
+				sentence_starts[i] += index.getNumberOfTNodes(i - 1) + sentence_starts[i - 1];
 			}
 		}
 		
@@ -333,4 +341,4 @@
 	public TSProperty getNTProperty(String name) {
 		return new TSProperty(this, name, false);
 	}
-}
\ No newline at end of file
+}
Index: tmp/org.txm.tigersearch.rcp/src/org/txm/searchengine/ts/TSResult.java
===================================================================
--- tmp/org.txm.tigersearch.rcp/src/org/txm/searchengine/ts/TSResult.java	(revision 2930)
+++ tmp/org.txm.tigersearch.rcp/src/org/txm/searchengine/ts/TSResult.java	(revision 2931)
@@ -54,284 +54,282 @@
  * The Class TSResult.
  */
 public class TSResult {
-
+	
 	/** The result. */
 	MatchResult result;
-
+	
 	/** The forest. */
 	ResultForest forest;
-
+	
 	/** The header. */
 	Header header;
-
+	
 	/** The ts corpus. */
 	TSCorpus tsCorpus;
-
+	
 	/** The matches. */
 	TSMatch[] matches;
-
-//	/** The current match. */
-//	int currentMatchNo = 0;
-//	TSMatch currentMatch;
-
+	
+	// /** The current match. */
+	// int currentMatchNo = 0;
+	// TSMatch currentMatch;
+	
 	/** The query. */
 	private String query;
-
+	
 	/** The manager. */
 	private InternalCorpusQueryManager manager;
-
+	
 	/** The corpus. */
-	//private TSCorpus corpus;
-
+	// private TSCorpus corpus;
+	
 	/** The tsquerytosvg. */
 	QueryToSvg tsquerytosvg = null;
-
+	
 	/**
 	 * Instantiates a new tS result.
 	 *
 	 * @param query the query
 	 * @param tsCorpus the ts corpus
-	 * @throws QueryFilterException 
-	 * @throws QueryOptimizationException 
-	 * @throws QueryIndexException 
-	 * @throws QueryEvaluationException 
-	 * @throws QueryNormalizationException 
-	 * @throws Exception 
+	 * @throws QueryFilterException
+	 * @throws QueryOptimizationException
+	 * @throws QueryIndexException
+	 * @throws QueryEvaluationException
+	 * @throws QueryNormalizationException
+	 * @throws Exception
 	 */
 	public TSResult(String query, TSCorpus tsCorpus, int sent_min, int sent_max, int match_max) throws Exception {
-
+		
 		this.query = query;
 		this.manager = tsCorpus.manager;
-		//this.corpus = tsCorpus;
+		// this.corpus = tsCorpus;
 		this.tsCorpus = tsCorpus;
-
+		
 		result = tsCorpus.manager.processQuery(query, sent_min, sent_max, match_max);
 		
 		if (result.size() > 0) {
 			forest = new ResultForest(result, tsCorpus.manager);
 			header = forest.getHeader();
-
+			
 			matches = new TSMatch[result.size()];
 			tsquerytosvg = new QueryToSvg(manager, result, forest, header, tsCorpus.config);
 		}
+		else {
+			matches = new TSMatch[0];
+		}
 	}
-
+	
 	public ResultForest getForest() {
 		return forest;
 	}
-
+	
 	public MatchResult getMatchResult() {
 		return result;
 	}
-
+	
 	public InternalCorpusQueryManager getManager() {
 		return manager;
 	}
-
+	
 	/**
 	 * Gets the number of match.
 	 *
 	 * @return the number of match
 	 */
-	public int getNumberOfMatch()
-	{
+	public int getNumberOfMatch() {
 		return result.size();
 	}
-
-//	/**
-//	 * return the no of match, begins with 1.
-//	 *
-//	 * @return the current match no
-//	 */
-//	public int getCurrentMatchNo() {
-//		return currentMatchNo;
-//	}
-//
-//	/**
-//	 * return the no of match, begins with 1.
-//	 *
-//	 * @return the current match no
-//	 */
-//	public TSMatch getCurrentMatch() {
-//		return currentMatch;
-//	}
-
-//	/**
-//	 * return the no of match, begins with 1.
-//	 *
-//	 * @return the current sentence no
-//	 */
-//	public int getCurrentSentenceNo() {
-//		System.out.println(TXMCoreMessages.numberOfMatch+this.getNumberOfMatch());
-//		System.out.println("current match "+this.getCurrentMatchNo()); //$NON-NLS-1$
-//		System.out.println(TXMCoreMessages.numberOfSubMatch+this.getCurrentMatch().getNumberOfSubGraph());
-//		System.out.println("current sub graph "+this.getCurrentMatch().getCurrentSubMatchNo()); //$NON-NLS-1$
-//		return result.getSentenceNumberAt(this.currentMatchNo); // + 1 ?
-//	}
-
+	
+	// /**
+	// * return the no of match, begins with 1.
+	// *
+	// * @return the current match no
+	// */
+	// public int getCurrentMatchNo() {
+	// return currentMatchNo;
+	// }
+	//
+	// /**
+	// * return the no of match, begins with 1.
+	// *
+	// * @return the current match no
+	// */
+	// public TSMatch getCurrentMatch() {
+	// return currentMatch;
+	// }
+	
+	// /**
+	// * return the no of match, begins with 1.
+	// *
+	// * @return the current sentence no
+	// */
+	// public int getCurrentSentenceNo() {
+	// System.out.println(TXMCoreMessages.numberOfMatch+this.getNumberOfMatch());
+	// System.out.println("current match "+this.getCurrentMatchNo()); //$NON-NLS-1$
+	// System.out.println(TXMCoreMessages.numberOfSubMatch+this.getCurrentMatch().getNumberOfSubGraph());
+	// System.out.println("current sub graph "+this.getCurrentMatch().getCurrentSubMatchNo()); //$NON-NLS-1$
+	// return result.getSentenceNumberAt(this.currentMatchNo); // + 1 ?
+	// }
+	
 	/**
 	 * Gets the match.
 	 *
 	 * @param matchNo the no
 	 * @return the match
 	 */
-	public TSMatch getMatch(int matchNo)
-	{
+	public TSMatch getMatch(int matchNo) {
 		if (matches[matchNo] == null) {
 			TSMatch m = new TSMatch(matchNo, this.tsquerytosvg, this);
 			matches[matchNo] = m;
 		}
-
-		return matches[matchNo] ;
+		
+		return matches[matchNo];
 	}
-
+	
 	public void setDisplayProperties(List<String> tprops, String feature) {
 		tsCorpus.setDisplayProperties(this.header, tprops, feature);
 	}
-
+	
 	/**
 	 * Gets the first.
 	 *
 	 * @return the first
 	 */
-	public TSMatch getFirst()
-	{
+	public TSMatch getFirst() {
 		if (result.size() > 0) {
-//			currentMatchNo = 0;
-//			currentMatch = getMatch(0);
+			// currentMatchNo = 0;
+			// currentMatch = getMatch(0);
 			return getMatch(0);
-		} else {
+		}
+		else {
 			return null;
 		}
 	}
-
+	
 	/**
 	 * Gets the last.
 	 *
 	 * @return the last
 	 */
-	public TSMatch getLast()
-	{
+	public TSMatch getLast() {
 		if (result.size() > 0) {
-//			currentMatchNo = result.size() -1;
-//			currentMatch = getMatch(result.size() -1);
-			return getMatch(result.size() -1);
-		} else {
+			// currentMatchNo = result.size() -1;
+			// currentMatch = getMatch(result.size() -1);
+			return getMatch(result.size() - 1);
+		}
+		else {
 			return null;
 		}
 	}
-//
-//	/**
-//	 * Gets the next.
-//	 *
-//	 * @return the next
-//	 */
-//	public TSMatch getNext()
-//	{
-//		int next = currentMatchNo + 1;
-//		if (result.size() > next) {
-//			currentMatchNo = next;
-//			currentMatch = getMatch(next);
-//			return currentMatch;
-//		} else {
-//			return null;
-//		}
-//	}
-//
-//	/**
-//	 * Gets the previous.
-//	 *
-//	 * @return the previous
-//	 */
-//	public TSMatch getPrevious()
-//	{
-//		int next = currentMatchNo - 1;
-//		if (next >= 0 && result.size() > 0) {
-//			currentMatchNo = next;
-//			currentMatch = getMatch(next);
-//			return currentMatch;
-//		} else {
-//			return null;
-//		}
-//	}
-//
-//	public TSMatch setCurrentMatch(int graphNo) {
-//		currentMatch = this.getMatch(graphNo);
-//		currentMatchNo = graphNo;
-//		return currentMatch;
-//	}
-
-	public boolean toXml(File outfile, File xmlFile, File xslFile) throws ExportException, ExportStopException, IOException, TransformerException
-	{
+	//
+	// /**
+	// * Gets the next.
+	// *
+	// * @return the next
+	// */
+	// public TSMatch getNext()
+	// {
+	// int next = currentMatchNo + 1;
+	// if (result.size() > next) {
+	// currentMatchNo = next;
+	// currentMatch = getMatch(next);
+	// return currentMatch;
+	// } else {
+	// return null;
+	// }
+	// }
+	//
+	// /**
+	// * Gets the previous.
+	// *
+	// * @return the previous
+	// */
+	// public TSMatch getPrevious()
+	// {
+	// int next = currentMatchNo - 1;
+	// if (next >= 0 && result.size() > 0) {
+	// currentMatchNo = next;
+	// currentMatch = getMatch(next);
+	// return currentMatch;
+	// } else {
+	// return null;
+	// }
+	// }
+	//
+	// public TSMatch setCurrentMatch(int graphNo) {
+	// currentMatch = this.getMatch(graphNo);
+	// currentMatchNo = graphNo;
+	// return currentMatch;
+	// }
+	
+	public boolean toXml(File outfile, File xmlFile, File xslFile) throws ExportException, ExportStopException, IOException, TransformerException {
 		return toXml(outfile, xmlFile, xslFile, false, 30, new ArrayList<String>(), new ArrayList<String>());
 	}
-
-	//TODO move this code somewhere
-	//	public static String CONCSIMPLE = "concordance_simple"; //$NON-NLS-1$
-	//	public static String CONCMOTPIVOT = "concordance_mot-pivot"; //$NON-NLS-1$
-	//	public static String CONCBLOCKS = "concordance_blocks"; //$NON-NLS-1$
-	//	public static String[] EXPORTMETHODS = {CONCSIMPLE, CONCMOTPIVOT, CONCBLOCKS};
-	//	public boolean toConcordance(File csvFile, String method, int cx, List<String> list, List<String> list2, boolean punct) throws Exception
-	//	{
-	//		if (!Arrays.asList(EXPORTMETHODS).contains(method)) {
-	//			Log.severe(TXMCoreMessages.TSResult_7+method+TXMCoreMessages.TSResult_8+Arrays.toString(EXPORTMETHODS));
-	//			return false;
-	//		}
+	
+	// TODO move this code somewhere
+	// public static String CONCSIMPLE = "concordance_simple"; //$NON-NLS-1$
+	// public static String CONCMOTPIVOT = "concordance_mot-pivot"; //$NON-NLS-1$
+	// public static String CONCBLOCKS = "concordance_blocks"; //$NON-NLS-1$
+	// public static String[] EXPORTMETHODS = {CONCSIMPLE, CONCMOTPIVOT, CONCBLOCKS};
+	// public boolean toConcordance(File csvFile, String method, int cx, List<String> list, List<String> list2, boolean punct) throws Exception
+	// {
+	// if (!Arrays.asList(EXPORTMETHODS).contains(method)) {
+	// Log.severe(TXMCoreMessages.TSResult_7+method+TXMCoreMessages.TSResult_8+Arrays.toString(EXPORTMETHODS));
+	// return false;
+	// }
 	//
-	//		File xmlFile = File.createTempFile(csvFile.getName(), "EXPORTBRUT.xml", csvFile.getParentFile()); //$NON-NLS-1$
-	//		boolean rez = false;
-	//		if (punct) { 
-	//			// export match
-	//			//System.out.println("save matches in "+xmlFile);
-	//			this.toXml(xmlFile, false, true, false, false, true, false, 0);
-	//			//FileCopy.copy(xmlFile, new File(xmlFile.getParentFile(), "EXPORTBRUT.xml"));
-	//			// merge with TigerXMLPOSPNC
-	//			File tmp = File.createTempFile("txm", "AFTERMINJECT.xml", xmlFile.getParentFile()); //$NON-NLS-1$ //$NON-NLS-2$
-	//			File tigerXml = new File(tsCorpus.tsmanager.getRegistryPath(), "TigerPnc.xml"); //$NON-NLS-1$
-	//			//System.out.println("TIGER XML: "+tigerXml);
-	//			if (!tigerXml.exists()) {
-	//				System.out.println(TXMCoreMessages.TSResult_13+tigerXml.getAbsolutePath());
-	//				return false;
-	//			}
-	//			//System.out.println("Match inject: in "+tmp);
-	//			new MatchInject().script(tigerXml, xmlFile, tmp);
-	//			xmlFile.delete();
-	//			tmp.renameTo(xmlFile);
-	//			//FileCopy.copy(xmlFile, new File(xmlFile.getParentFile(), "AFTERMINJECT.xml"));
-	//		} else {
-	//			this.toXml(xmlFile); // export match + corpus
-	//			//FileCopy.copy(xmlFile, new File(xmlFile.getParentFile(), "FULLEXPORT.xml"));
-	//		}
+	// File xmlFile = File.createTempFile(csvFile.getName(), "EXPORTBRUT.xml", csvFile.getParentFile()); //$NON-NLS-1$
+	// boolean rez = false;
+	// if (punct) {
+	// // export match
+	// //System.out.println("save matches in "+xmlFile);
+	// this.toXml(xmlFile, false, true, false, false, true, false, 0);
+	// //FileCopy.copy(xmlFile, new File(xmlFile.getParentFile(), "EXPORTBRUT.xml"));
+	// // merge with TigerXMLPOSPNC
+	// File tmp = File.createTempFile("txm", "AFTERMINJECT.xml", xmlFile.getParentFile()); //$NON-NLS-1$ //$NON-NLS-2$
+	// File tigerXml = new File(tsCorpus.tsmanager.getRegistryPath(), "TigerPnc.xml"); //$NON-NLS-1$
+	// //System.out.println("TIGER XML: "+tigerXml);
+	// if (!tigerXml.exists()) {
+	// System.out.println(TXMCoreMessages.TSResult_13+tigerXml.getAbsolutePath());
+	// return false;
+	// }
+	// //System.out.println("Match inject: in "+tmp);
+	// new MatchInject().script(tigerXml, xmlFile, tmp);
+	// xmlFile.delete();
+	// tmp.renameTo(xmlFile);
+	// //FileCopy.copy(xmlFile, new File(xmlFile.getParentFile(), "AFTERMINJECT.xml"));
+	// } else {
+	// this.toXml(xmlFile); // export match + corpus
+	// //FileCopy.copy(xmlFile, new File(xmlFile.getParentFile(), "FULLEXPORT.xml"));
+	// }
 	//
-	//		if (!xmlFile.exists()) { System.out.println(TXMCoreMessages.TSResult_14); return false;}
+	// if (!xmlFile.exists()) { System.out.println(TXMCoreMessages.TSResult_14); return false;}
 	//
-	//		if (method.equals("concordance_blocks")) { //$NON-NLS-1$
-	//			ConcordanceBlocks builder = new ConcordanceBlocks();
-	//			rez = builder.process(xmlFile, csvFile, cx, list, list2);
-	//		} else { // XSL method
-	//			File xslDir = new File(TBXPreferences.getInstance().getString(TBXPreferences.USER_TXM_HOME), "xsl"); //$NON-NLS-1$
-	//			File xslFile = new File(xslDir, method+".xsl"); //$NON-NLS-1$
-	//			if (!xslFile.exists()) {
-	//				Log.severe(TXMCoreMessages.TSResult_7+xslFile);
-	//				return false;
-	//			}
+	// if (method.equals("concordance_blocks")) { //$NON-NLS-1$
+	// ConcordanceBlocks builder = new ConcordanceBlocks();
+	// rez = builder.process(xmlFile, csvFile, cx, list, list2);
+	// } else { // XSL method
+	// File xslDir = new File(TBXPreferences.getInstance().getString(TBXPreferences.USER_TXM_HOME), "xsl"); //$NON-NLS-1$
+	// File xslFile = new File(xslDir, method+".xsl"); //$NON-NLS-1$
+	// if (!xslFile.exists()) {
+	// Log.severe(TXMCoreMessages.TSResult_7+xslFile);
+	// return false;
+	// }
 	//
-	//			rez = toXml(csvFile, xmlFile, xslFile, punct, cx, list, list2);
-	//		}
-	//		xmlFile.delete(); // no more needed
-	//		return rez;
-	//	}
-
-	public boolean toXml(File outfile) throws ExportException, ExportStopException
-	{
+	// rez = toXml(csvFile, xmlFile, xslFile, punct, cx, list, list2);
+	// }
+	// xmlFile.delete(); // no more needed
+	// return rez;
+	// }
+	
+	public boolean toXml(File outfile) throws ExportException, ExportStopException {
 		toXml(outfile, true, true);
 		return true;
 	}
-
-	public boolean toXml(File outfile, boolean includeNonMatch, boolean includeMatch, 
-			boolean includeXmlHeader, boolean includeXMLSentenceStructure, 
-			boolean includeXMLMatchInformation, boolean refineSchema, int referSchema) throws ExportException, ExportStopException
-	{
+	
+	public boolean toXml(File outfile, boolean includeNonMatch, boolean includeMatch,
+			boolean includeXmlHeader, boolean includeXMLSentenceStructure,
+			boolean includeXMLMatchInformation, boolean refineSchema, int referSchema) throws ExportException, ExportStopException {
 		this.tsCorpus.exporter.setConfiguration(includeXmlHeader,
 				includeXMLSentenceStructure,
 				includeXMLMatchInformation,
@@ -340,74 +338,74 @@
 		this.tsCorpus.exporter.saveMatchAsXML(result, outfile, includeNonMatch, includeMatch);
 		return true;
 	}
-
-	public boolean toXml(File outfile, boolean includeNonMatch, boolean includeMatch) throws ExportException, ExportStopException
-	{
+	
+	public boolean toXml(File outfile, boolean includeNonMatch, boolean includeMatch) throws ExportException, ExportStopException {
 		boolean includeXmlHeader = true;
 		boolean includeXMLSentenceStructure = true;
 		boolean includeXMLMatchInformation = true;
 		boolean refineSchema = false;
 		int referSchema = 0;
-
+		
 		return toXml(outfile, includeNonMatch, includeMatch, includeXmlHeader, includeXMLSentenceStructure, includeXMLMatchInformation, refineSchema, referSchema);
 	}
-
-	//	@Deprecated
-	//	private void injectPunct(File xmlfile)
-	//	{
-	//		System.out.println(TXMCoreMessages.TSResult_18);
-	//		String corpus = this.tsCorpus.id.toUpperCase();
-	//		try {
-	//			Document dom = DomUtils.load(xmlfile);
-	//			//System.out.println("Getting words of "+corpus);
-	//			Object words = PunctInject.getWords(corpus, ""); //$NON-NLS-1$
+	
+	// @Deprecated
+	// private void injectPunct(File xmlfile)
+	// {
+	// System.out.println(TXMCoreMessages.TSResult_18);
+	// String corpus = this.tsCorpus.id.toUpperCase();
+	// try {
+	// Document dom = DomUtils.load(xmlfile);
+	// //System.out.println("Getting words of "+corpus);
+	// Object words = PunctInject.getWords(corpus, ""); //$NON-NLS-1$
 	//
-	//			//			int i = 0;
-	//			//			for(String[] word : (ArrayList<String[]>)words)
-	//			//			{
-	//			//				if(i++ % 10 == 0) System.out.println();
-	//			//				System.out.print("[\""+word[0]+"\", \""+word[1].replace("\"", "\\\"")+"\"], ");
-	//			//			}
-	//			File outfile = File.createTempFile("punct", ".xml", xmlfile.getParentFile()); //$NON-NLS-1$ //$NON-NLS-2$
-	//			//System.out.println("Processing "+xmlfile+" to "+outfile);
-	//			Document doc = (Document) new PunctInject().process(dom, words);
-	//			//System.out.println("Saving file");
-	//			DomUtils.save(doc, outfile);
+	// // int i = 0;
+	// // for(String[] word : (ArrayList<String[]>)words)
+	// // {
+	// // if(i++ % 10 == 0) System.out.println();
+	// // System.out.print("[\""+word[0]+"\", \""+word[1].replace("\"", "\\\"")+"\"], ");
+	// // }
+	// File outfile = File.createTempFile("punct", ".xml", xmlfile.getParentFile()); //$NON-NLS-1$ //$NON-NLS-2$
+	// //System.out.println("Processing "+xmlfile+" to "+outfile);
+	// Document doc = (Document) new PunctInject().process(dom, words);
+	// //System.out.println("Saving file");
+	// DomUtils.save(doc, outfile);
 	//
-	//			//			FileCopy.copy(outfile, new File(outfile.getParentFile(), "afterinject.xml"));
+	// // FileCopy.copy(outfile, new File(outfile.getParentFile(), "afterinject.xml"));
 	//
-	//			xmlfile.delete();
-	//			outfile.renameTo(xmlfile);
-	//		} catch (UnsupportedEncodingException e) {
-	//			// TODO Auto-generated catch block
-	//			org.txm.utils.logger.Log.printStackTrace(e);
-	//		} catch (FileNotFoundException e) {
-	//			// TODO Auto-generated catch block
-	//			org.txm.utils.logger.Log.printStackTrace(e);
-	//		} catch (ParserConfigurationException e) {
-	//			// TODO Auto-generated catch block
-	//			org.txm.utils.logger.Log.printStackTrace(e);
-	//		} catch (SAXException e) {
-	//			// TODO Auto-generated catch block
-	//			org.txm.utils.logger.Log.printStackTrace(e);
-	//		} catch (IOException e) {
-	//			// TODO Auto-generated catch block
-	//			org.txm.utils.logger.Log.printStackTrace(e);
-	//		}
+	// xmlfile.delete();
+	// outfile.renameTo(xmlfile);
+	// } catch (UnsupportedEncodingException e) {
+	// // TODO Auto-generated catch block
+	// org.txm.utils.logger.Log.printStackTrace(e);
+	// } catch (FileNotFoundException e) {
+	// // TODO Auto-generated catch block
+	// org.txm.utils.logger.Log.printStackTrace(e);
+	// } catch (ParserConfigurationException e) {
+	// // TODO Auto-generated catch block
+	// org.txm.utils.logger.Log.printStackTrace(e);
+	// } catch (SAXException e) {
+	// // TODO Auto-generated catch block
+	// org.txm.utils.logger.Log.printStackTrace(e);
+	// } catch (IOException e) {
+	// // TODO Auto-generated catch block
+	// org.txm.utils.logger.Log.printStackTrace(e);
+	// }
 	//
 	//
-	//	}
-
-	public boolean toXml(File outFile, File xmlFile, File xslFile, boolean punct, int cxsize, List<String> list, List<String> list2) throws ExportException, ExportStopException, IOException, TransformerException
-	{
+	// }
+	
+	public boolean toXml(File outFile, File xmlFile, File xslFile, boolean punct, int cxsize, List<String> list, List<String> list2) throws ExportException, ExportStopException, IOException,
+			TransformerException {
 		ApplyXsl2 xslProc = new ApplyXsl2(xslFile);
 		xslProc.setParam("cx", cxsize); //$NON-NLS-1$
 		xslProc.setParam("ntTypes", list.toString().replaceAll("[\\[\\],]", "")); // ["pos", "lem"] //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 		xslProc.setParam("tTypes", list2.toString().replaceAll("[\\[\\],]", "")); // ["truc", "machin"] //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 		if (xslProc.process(xmlFile, outFile)) {
 			return outFile.exists();
-		} else {
+		}
+		else {
 			return false;
 		}
 	}
-}
\ No newline at end of file
+}
Index: tmp/org.txm.tigersearch.rcp/src/org/txm/tigersearch/editors/TIGERSearchEditor.java
===================================================================
--- tmp/org.txm.tigersearch.rcp/src/org/txm/tigersearch/editors/TIGERSearchEditor.java	(revision 2930)
+++ tmp/org.txm.tigersearch.rcp/src/org/txm/tigersearch/editors/TIGERSearchEditor.java	(revision 2931)
@@ -310,16 +310,17 @@
 			// this.syncExec(new Runnable() {
 			// @Override
 			// public void run() {
+			if (ts.getNSentences() > 0) {
+				sentCounterLabel.setText("/" + ts.getNSentences());
+				subCounterLabel.setText("/" + ts.getNSubGraph(0));
+				sentSpinner.setSelection(1);
+				sentSpinner.setMaximum(ts.getNSentences());
+				subSpinner.setSelection(1);
+				subSpinner.setMaximum(ts.getNSubGraph(0));
+				
+				reloadGraph();
+			}
 			
-			sentCounterLabel.setText("/" + ts.getNSentences());
-			subCounterLabel.setText("/" + ts.getNSubGraph(0));
-			sentSpinner.setSelection(1);
-			sentSpinner.setMaximum(ts.getNSentences());
-			subSpinner.setSelection(1);
-			subSpinner.setMaximum(ts.getNSubGraph(0));
-			
-			reloadGraph();
-			
 			CorporaView.refresh();
 			CorporaView.expand(corpus);
 			QueriesView.refresh();
Index: tmp/org.txm.tigersearch.rcp/src/org/txm/tigersearch/commands/ImportTIGERAnnotations.java
===================================================================
--- tmp/org.txm.tigersearch.rcp/src/org/txm/tigersearch/commands/ImportTIGERAnnotations.java	(revision 2930)
+++ tmp/org.txm.tigersearch.rcp/src/org/txm/tigersearch/commands/ImportTIGERAnnotations.java	(revision 2931)
@@ -32,8 +32,8 @@
 import java.io.RandomAccessFile;
 import java.nio.MappedByteBuffer;
 import java.nio.channels.FileChannel;
-import java.util.Arrays;
 
+import org.apache.log4j.BasicConfigurator;
 import org.eclipse.core.commands.AbstractHandler;
 import org.eclipse.core.commands.ExecutionEvent;
 import org.eclipse.core.commands.ExecutionException;
@@ -52,71 +52,149 @@
 import org.txm.searchengine.ts.InternalCorpusQueryManagerLocal2;
 import org.txm.searchengine.ts.TSCorpus;
 import org.txm.searchengine.ts.TSCorpusManager;
+import org.txm.utils.ConsoleProgressBar;
 import org.txm.utils.DeleteDir;
 import org.txm.utils.io.FileCopy;
+import org.txm.utils.io.IOUtils;
 import org.txm.utils.logger.Log;
 
 import ims.tiger.corpus.Sentence;
 import ims.tiger.corpus.T_Node;
 import ims.tiger.index.reader.Index;
 import ims.tiger.index.reader.IndexException;
+import ims.tiger.index.writer.IndexBuilderErrorHandler;
+import ims.tiger.index.writer.SimpleErrorHandler;
+import ims.tiger.index.writer.XMLIndexing;
 import ims.tiger.query.api.QueryIndexException;
 import ims.tiger.query.processor.CorpusQueryProcessor;
 
-
-// TODO: Auto-generated Javadoc
 /**
- * open the TIGERSearch Editor 
+ * Import TIGERSearch annotations into a TXM corpus
+ * 
+ * IF the corpus alreasy wontains TIGER annotations, they are replaced
+ * 
+ * The annotations are given using a TIGERSEarch binary corpus OR a TIGER source directory using a "main.xml" file
+ * 
  * @author mdecorde.
  */
 public class ImportTIGERAnnotations extends AbstractHandler {
-
+	
 	public static final String ID = "org.txm.rcp.commands.function.ComputeTSIndex"; //$NON-NLS-1$
-
-	/* (non-Javadoc)
+	
+	/*
+	 * (non-Javadoc)
 	 * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent)
 	 */
 	@Override
 	public Object execute(final ExecutionEvent event) throws ExecutionException {
-
+		
 		IStructuredSelection selection = (IStructuredSelection) HandlerUtil.getCurrentSelection(event);
-
+		
 		Object s = selection.getFirstElement();
-		if (s instanceof CQPCorpus) {
-			CQPCorpus corpus = (CQPCorpus)s;
+		if (s instanceof MainCorpus) {
+			CQPCorpus corpus = (CQPCorpus) s;
 			MainCorpus mainCorpus = corpus.getMainCorpus();
 			
 			File tigerCorpusDirectory = null;
 			DirectoryDialog dialog = new DirectoryDialog(HandlerUtil.getActiveShell(event), SWT.OPEN);
 			String path = dialog.open();
 			if (path == null) {
+				Log.warning("Aborting annotation importation.");
 				return null;
-			} else {
+			}
+			else {
 				tigerCorpusDirectory = new File(path);
 			}
 			
-			File tigerDirectory = new File(corpus.getProjectDirectory(), "tiger");
+			File tigerDirectory = new File(mainCorpus.getProjectDirectory(), "tiger");
 			File tigerCorpusExistingDirectory = new File(tigerDirectory, tigerCorpusDirectory.getName());
 			if (tigerCorpusExistingDirectory.exists()) {
 				boolean doIt = MessageDialog.openConfirm(HandlerUtil.getActiveShell(event), "Replace existing annotations", "TIGERSearch annotations already exists, replace them ?");
 				if (!doIt) {
-					Log.warning("Aborting annotations import.");
+					Log.warning("Aborting annotation importation.");
 					return null;
 				}
 			}
+			
+			if (new File(tigerCorpusDirectory, "word.lexicon").exists() && new File(tigerCorpusDirectory, "corpus_config.xml").exists()) {
+				// ok this is a TIGERSearch binary corpus
+			}
+			else {
+				
+				// need to build a TIGERSearch binary corpus
+				File tigerBinaryCorpusDirectory = new File(tigerCorpusDirectory, "tiger");
+				if (!buildTIGERCorpus(mainCorpus, tigerCorpusDirectory, tigerBinaryCorpusDirectory)) {
+					Log.warning("Aborting annotation importation.");
+					return null;
+				}
+				tigerCorpusDirectory = new File(tigerBinaryCorpusDirectory, corpus.getName());
+			}
+			
 			try {
-				return importAnnotations(mainCorpus, tigerCorpusDirectory);
-			} catch (Exception e) {
-				// TODO Auto-generated catch block
+				return importAnnotations(mainCorpus, tigerCorpusDirectory, "editionId");
+			}
+			catch (Exception e) {
 				e.printStackTrace();
 				return null;
 			}
-		} else {
+		}
+		else {
 			Log.warning("Selection is not a corpus. Aborting.");
 			return null;
 		}
 	}
-
+	
+	private boolean buildTIGERCorpus(MainCorpus corpus, File sourceDirectory, File tigerDir) {
+		tigerDir.mkdirs();
+		
+		File configfile = new File(tigerDir, "tigersearch.logprop");
+		if (!configfile.exists()) {
+			TSCorpus.createLogPropFile(tigerDir);
+		}
+		
+		BasicConfigurator.configure();
+		File master = new File(sourceDirectory, "main.xml");
+		if (!master.exists()) master = new File(sourceDirectory, "master.xml");
+		
+		if (!master.exists()) {
+			Log.warning("Error: Can't create TIGERSearch corpus: no main or master file found in " + sourceDirectory);
+			return false;
+		}
+		String uri = master.getAbsolutePath(); // TIGER corpus source root file
+		File tigerBinDir = new File(tigerDir, corpus.getName());
+		tigerBinDir.mkdirs();
+		try {
+			IndexBuilderErrorHandler handler = new SimpleErrorHandler(tigerBinDir.getAbsolutePath()) {
+				
+				@Override
+				public void setMessage(String message) {}
+				
+				@Override
+				public void setNumberOfSentences(int number) {}
+				
+				@Override
+				public void setProgressBar(int value) {}
+			};
+			
+			XMLIndexing indexing = new XMLIndexing(corpus.getName(), uri, tigerBinDir.getAbsolutePath(), handler, false);
+			
+			indexing.startIndexing();
+			
+			File logs = new File(tigerBinDir, "indexing.log");
+			
+			String txt = IOUtils.getText(logs);
+			if (txt.contains("Error in corpus graph ")) {
+				Log.warning("Error while importing TIGER corpus: " + txt);
+				return false;
+			}
+		}
+		catch (Exception e) {
+			System.out.println(e.getMessage());
+			return false;
+		}
+		return true;
+	}
+	
 	/**
 	 * 
 	 * if aTIGER corpus with the same name already exists, it is replaced
@@ -124,18 +202,20 @@
 	 * @param corpus
 	 * @param tigerCorpusDirectory
 	 * @return the number of imported annotations
-	 * @throws IndexException 
-	 * @throws QueryIndexException 
-	 * @throws CqiClientException 
-	 * @throws CqiServerError 
-	 * @throws IOException 
-	 * @throws UnexpectedAnswerException 
+	 * @throws IndexException
+	 * @throws QueryIndexException
+	 * @throws CqiClientException
+	 * @throws CqiServerError
+	 * @throws IOException
+	 * @throws UnexpectedAnswerException
 	 */
-	public static int importAnnotations(MainCorpus corpus, File tigerCorpusDirectory) throws IndexException, QueryIndexException, UnexpectedAnswerException, IOException, CqiServerError, CqiClientException {
+	public static int importAnnotations(MainCorpus corpus, File tigerCorpusDirectory, String wordIdAttribute) throws IndexException, QueryIndexException, UnexpectedAnswerException, IOException,
+			CqiServerError,
+			CqiClientException {
 		
 		// TXM corpus files
 		File tigerDirectory = new File(corpus.getProjectDirectory(), "tiger");
-		File tigerCorpusExistingDirectory = new File(tigerDirectory, tigerCorpusDirectory.getName());
+		File tigerCorpusExistingDirectory = new File(tigerDirectory, corpus.getName());
 		DeleteDir.deleteDirectory(tigerCorpusExistingDirectory);
 		tigerCorpusExistingDirectory.mkdirs();
 		
@@ -147,119 +227,131 @@
 		AbstractCqiClient CQI = CQPSearchEngine.getCqiClient();
 		
 		TSCorpusManager manager = new TSCorpusManager(tigerCorpusDirectory.getParentFile(), configfile);
-
+		
 		TSCorpus tcorpus = manager.getCorpus(tigerCorpusDirectory.getName());
 		InternalCorpusQueryManagerLocal2 tigermanager = tcorpus.manager;
 		CorpusQueryProcessor processor = tigermanager.getQueryProcessor();
 		
 		Index index = processor.getIndex();
 		int size = 0;
-		for (int nr = 0 ; nr < index.getNumberOfGraphs() ; nr++) {
+		for (int nr = 0; nr < index.getNumberOfGraphs(); nr++) {
 			size += index.getNumberOfTNodes(nr);
 		}
 		
 		if (size == 0) {
-			Log.warning("No word found in the TIGERSearch corpus: "+tigerCorpusDirectory+". Aborting.");
+			Log.warning("No word found in the TIGERSearch corpus: " + tigerCorpusDirectory + ". Aborting.");
 			return 0;
 		}
 		
-		Log.info("Importing "+size+" word annotations...");
+		Log.info("Importing " + size + " word annotations...");
 		
 		// compute start position of sentences
 		int[] starts = new int[index.getNumberOfGraphs()];
-		for (int i = 0 ; i < index.getNumberOfGraphs() ; i++) {
+		for (int i = 0; i < index.getNumberOfGraphs(); i++) {
 			starts[i] = 0;
 			if (i > 0) {
-				starts[i] += index.getNumberOfTNodes(i-1) + starts[i-1];
+				starts[i] += index.getNumberOfTNodes(i - 1) + starts[i - 1];
 			}
 		}
 		
 		File offsetsFile = new File(tigerCorpusExistingDirectory, "offsets.data");
 		RandomAccessFile offsetsRAFile = new RandomAccessFile(offsetsFile, "rw");
 		FileChannel offsetsFileChannel = offsetsRAFile.getChannel();
-		MappedByteBuffer offsetsMapped = offsetsFileChannel.map(FileChannel.MapMode.READ_WRITE, 0, size*Integer.BYTES);
-		//out.putInt(positions[i])
-
+		MappedByteBuffer offsetsMapped = offsetsFileChannel.map(FileChannel.MapMode.READ_WRITE, 0, size * Integer.BYTES);
+		// out.putInt(positions[i])
+		
 		File presencesFile = new File(tigerCorpusExistingDirectory, "presences.data");
 		RandomAccessFile presencesRAFile = new RandomAccessFile(presencesFile, "rw");
 		FileChannel presencesFileChannel = presencesRAFile.getChannel();
 		MappedByteBuffer presencesMapped = presencesFileChannel.map(FileChannel.MapMode.READ_WRITE, 0, size);
-
-		int numberOfWordsAnntoated = 0;
 		
+		int numberOfWordsAnnotated = 0;
+		
 		// for each sentence
-		for (int nr = 0 ; nr < index.getNumberOfGraphs() ; nr++) {
+		ConsoleProgressBar cpb = new ConsoleProgressBar(index.getNumberOfGraphs());
+		for (int nr = 0; nr < index.getNumberOfGraphs(); nr++) {
+			cpb.tick();
 			int sent_size = index.getNumberOfTNodes(nr);
 			Sentence sent = tcorpus.manager.getSentence(nr);
 			
 			String[] ids = new String[sent_size];
 			int[] tigerPositions = new int[sent_size];
-			for (int t = 0 ; t < sent_size ; t++) {
-				T_Node terminal = (T_Node)sent.getTerminalAt(t);
-				ids[t] = terminal.getFeature("editionId");
+			for (int t = 0; t < sent_size; t++) {
+				T_Node terminal = (T_Node) sent.getTerminalAt(t);
+				ids[t] = terminal.getFeature(wordIdAttribute);
 				
 				// try fixing ID
 				if (ids[t].startsWith("w")) {
 					if (!ids[t].startsWith("w_")) {
-						ids[t] = "w_"+ids[t].substring(1);
+						ids[t] = "w_" + ids[t].substring(1);
 					}
-				} else {
-					ids[t] = "w_"+ids[t];
 				}
-				tigerPositions[t] = starts[nr]+t;
-				//System.out.println("T id="+terminal.getID());
+				else {
+					ids[t] = "w_" + ids[t];
+				}
+				tigerPositions[t] = starts[nr] + t;
+				// System.out.println("T id="+terminal.getID());
 			}
 			
 			int[] ids_idx = CQI.str2Id(corpus.getProperty("id").getQualifiedName(), ids);
 			Integer[] cqpPositions = new Integer[sent_size];
 			Integer[] offsets = new Integer[sent_size];
-			for (int t = 0 ; t < sent_size ; t++) {
+			for (int t = 0; t < sent_size; t++) {
 				if (ids_idx[t] >= 0) {
 					int[] positions = CQI.id2Cpos(corpus.getProperty("id").getQualifiedName(), ids_idx[t]);
 					if (positions.length > 1) {
-						Log.warning("Warning: multiple CQP positions for word_id="+ids[t]);
+						Log.warning("Warning: multiple CQP positions for word_id=" + ids[t]);
 					}
 					cqpPositions[t] = positions[0]; // take the first position
-				} else { // word not in the CQP corpus
+				}
+				else { // word not in the CQP corpus
+					Log.warning("Could not find word for id=" + ids[t]);
 					cqpPositions[t] = null;
 				}
 				
 				if (cqpPositions[t] != null) {
 					offsets[t] = cqpPositions[t] - tigerPositions[t];
-				} else {
-					offsets[t] = 0;
 				}
+				else {
+					offsets[t] = null;
+				}
 			}
-//			System.out.println("ids="+Arrays.toString(ids));
-//			System.out.println("cqp indexes="+Arrays.toString(ids_idx));
-//			System.out.println("tiger positions="+Arrays.toString(tigerPositions));
-//			System.out.println("cqp positions="+Arrays.toString(cqpPositions));
-//			System.out.println("offsets="+Arrays.toString(offsets));
+			// System.out.println("ids="+Arrays.toString(ids));
+			// System.out.println("cqp indexes="+Arrays.toString(ids_idx));
+			// System.out.println("tiger positions="+Arrays.toString(tigerPositions));
+			// System.out.println("cqp positions="+Arrays.toString(cqpPositions));
+			// System.out.println("offsets="+Arrays.toString(offsets));
 			
 			// writing data to offset and presences files
-			for (int t = 0 ; t < sent_size ; t++) {
-				offsetsMapped.putInt(offsets[t]);
+			for (int t = 0; t < sent_size; t++) {
+				
 				if (offsets[t] != null) {
-					numberOfWordsAnntoated++;
-					presencesMapped.put((byte)1);
-				} else {
-					presencesMapped.put((byte)0);
+					numberOfWordsAnnotated++;
+					presencesMapped.put((byte) 1);
+					offsetsMapped.putInt(offsets[t]);
 				}
+				else {
+					presencesMapped.put((byte) 0);
+					offsetsMapped.putInt(0);
+				}
 			}
 		}
+		cpb.done();
 		
 		offsetsFileChannel.close();
 		offsetsRAFile.close();
 		presencesFileChannel.close();
 		presencesRAFile.close();
 		
-		if (numberOfWordsAnntoated > 0) {
+		Log.info("Finalizing TIGERSearch corpus");
+		if (numberOfWordsAnnotated > 0) {
 			FileCopy.copyFiles(tigerCorpusDirectory, tigerCorpusExistingDirectory);
-			Log.warning("Done. "+numberOfWordsAnntoated+" words annotated.");
-		} else {
+			Log.info("Done. " + numberOfWordsAnnotated + " words annotated.");
+		}
+		else {
 			Log.warning("Warning: no words could be aligned with the CQP corpus. Aborting");
 		}
 		
-		return numberOfWordsAnntoated;
+		return numberOfWordsAnnotated;
 	}
 }
Index: tmp/org.txm.analec.rcp/src/org/txm/annotation/urs/export/ExportToGlozzMacro.java
===================================================================
--- tmp/org.txm.analec.rcp/src/org/txm/annotation/urs/export/ExportToGlozzMacro.java	(revision 2930)
+++ tmp/org.txm.analec.rcp/src/org/txm/annotation/urs/export/ExportToGlozzMacro.java	(revision 2931)
@@ -20,35 +20,37 @@
 import visuAnalec.donnees.Structure;
 import visuAnalec.elements.Unite;
 import visuAnalec.fichiers.FichiersGlozz.ModelGlozzPrinter;
+
 /**
  * @author: Bruno Oberlé
  * 
- * v1.0.0 2017-08-28
+ *          v1.0.0 2017-08-28
  * 
- * adapted and included in TXM by mdecorde
-
- * Cette macro exporte le corpus sélectionné et ses annotations vers deux fichiers de format Glozz:
- * - un fichier .ac contenant le corpus brut,
- * - un fichier .aa contenant les annotations au format XML utilisé par Glozz,
- * - un fichier .aam contenant la structure d'annotation.
+ *          adapted and included in TXM by mdecorde
  * 
- * Le corpus sélectionné dans TXM devrait contenir une structure Analec avec au moins un type d'unité défini (e.g. MENTION, maillon, etc.). S'il n'y a pas de structure,
- * ce n'est pas grave: le fichier est exporter, mais aucune annotation n'est créer. Cela permet d'exporter n'importe quel corpus au format Glozz.
+ *          Cette macro exporte le corpus sélectionné et ses annotations vers deux fichiers de format Glozz:
+ *          - un fichier .ac contenant le corpus brut,
+ *          - un fichier .aa contenant les annotations au format XML utilisé par Glozz,
+ *          - un fichier .aam contenant la structure d'annotation.
  * 
- * Pour exporter un texte au format Glozz *sans* les annotations qu'il contient, simplement mettre un unit_type qui n'existe pas (e.g. "foobar" au lieu de "MENTION").
+ *          Le corpus sélectionné dans TXM devrait contenir une structure Analec avec au moins un type d'unité défini (e.g. MENTION, maillon, etc.). S'il n'y a pas de structure,
+ *          ce n'est pas grave: le fichier est exporter, mais aucune annotation n'est créer. Cela permet d'exporter n'importe quel corpus au format Glozz.
  * 
- * deprecated: La macro ne produit pour l'instant pas automatiquement de modèle Glozz (fichier .aam). Cela n'est pas un problème pour ouvrir le résultat dans Glozz ou Analec.
+ *          Pour exporter un texte au format Glozz *sans* les annotations qu'il contient, simplement mettre un unit_type qui n'existe pas (e.g. "foobar" au lieu de "MENTION").
+ * 
+ *          deprecated: La macro ne produit pour l'instant pas automatiquement de modèle Glozz (fichier .aam). Cela n'est pas un problème pour ouvrir le résultat dans Glozz ou Analec.
  **/
 public class ExportToGlozzMacro {
-
+	
 	public void doExport(MainCorpus corpus, String unit_type, String filename) throws NumberFormatException, IOException, CqiServerError, CqiClientException {
-
+		
 		// export the annotation structure as a glozz model
 		Corpus analecCorpus = URSCorpora.getCorpus(corpus);
 		if (analecCorpus == null) {
 			System.out.println("No Analec corpus associated with $corpus");
 			return;
 		}
+		System.out.println("Writing annotation structure...");
 		PrintWriter model = null;
 		File fichierModel = new File(filename + ".aam");
 		try {
@@ -56,13 +58,15 @@
 			model = new PrintWriter(fichierModel, "UTF-8");
 			ModelGlozzPrinter gp = new ModelGlozzPrinter(structure, model);
 			gp.ecrireModel();
-		} catch (Exception ex) {
-			System.out.println("Erreur d'écriture de fichier: "+ex);
-		} finally {
-			if (model!=null) model.close();
-			System.out.println(NLS.bind("Corpus written to ''{0}''.", fichierModel));
 		}
-
+		catch (Exception ex) {
+			System.out.println("Erreur d'écriture de fichier: " + ex);
+		}
+		finally {
+			if (model != null) model.close();
+			System.out.println(NLS.bind("Annotations structure written to ''{0}''.", fichierModel));
+		}
+		
 		int size = corpus.getSize(); // you may also use:
 		// corpus.getTextEndLimits() (= index of
 		// last token = size-1)
@@ -73,16 +77,16 @@
 		// pn = corpus.getProperty("pn")
 		// if (pn == null) pn = corpus.getProperty("div")
 		Property pn = corpus.getProperty("lbn");
-
+		
 		// BUILD THE RAW TEXT, THE POSITIONS AND FIND THE PARAGRAPHS
-
+		
 		String rawText = ""; // the corpus for the .ac file
-		ArrayList<int[]> positions = new ArrayList<int[]>(); // each element is an array
+		ArrayList<int[]> positions = new ArrayList<>(); // each element is an array
 		// [start, end] indicating the
 		// position in the rawText
 		int pnCount = 0; // the par counter, used for indexing the pns array
 		int lastPn = -1; // the last paragraph number
-		ArrayList<int[]> pns = new ArrayList<int[]>(); // each element is an array [start,
+		ArrayList<int[]> pns = new ArrayList<>(); // each element is an array [start,
 		// end] representing the start and
 		// end of the paragraph in the
 		// rawText
@@ -92,7 +96,8 @@
 			int p = 0;
 			if (pn == null) {
 				p = 1;
-			} else {
+			}
+			else {
 				p = Integer.parseInt(CQI.cpos2Str(pn.getQualifiedName(), new int[] { i })[0]);
 			}
 			int start = rawText.length();
@@ -102,45 +107,46 @@
 				if (pnCount > 1 && pns.size() > 0) {
 					pns.get(pnCount - 2)[1] = end;
 				}
-				pns.add(new int[]{start, 0});
+				pns.add(new int[] { start, 0 });
 			}
 			lastPn = p;
 			end = rawText.length(); // must be after setting it up in pns!
 			if (i != size - 1)
 				rawText += " ";
-			positions.add(new int[]{start, end});
+			positions.add(new int[] { start, end });
 		}
 		pns.get(pnCount - 1)[1] = end;
 		System.out.println(pnCount + " paragraph(s) found.");
-
+		
 		// CORPUS ANALEC (GET THE ANNOTATIONS)
-
+		
 		// note that unit_type has been defined with an option of the dialog at
 		// the beginning
-
-
+		
+		
 		// list of properties
-
+		
 		Structure struct = analecCorpus.getStructure();
 		HashSet<String> propertyList = struct.getUniteProperties(unit_type);
-
+		
 		// export to file (corpus)
-
+		
+		System.out.println("Writing corpus...");
 		String corpusFilename = filename + ".ac";
 		File corpusFile = new File(corpusFilename);
 		PrintWriter corpusFileWriter = IOUtils.getWriter(corpusFile);
 		corpusFileWriter.write(rawText);
 		corpusFileWriter.close();
 		System.out.println("Corpus written to `" + corpusFilename + "'.");
-
+		
 		// export to file (annotations)
-
+		System.out.println("Writing annotations...");
 		String annotFilename = filename + ".aa";
 		File annotFile = new File(annotFilename);
 		PrintWriter annotFileWriter = IOUtils.getWriter(annotFile);
 		annotFileWriter.println("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<annotations>"); // erase
 		int counter = 0;
-
+		
 		// export paragraphs
 		for (int i = 0; i < pns.size(); i++) {
 			int start = pns.get(i)[0];
@@ -152,7 +158,7 @@
 			annotFileWriter.println("</unit>");
 			counter++;
 		}
-
+		
 		// export units
 		ArrayList<Unite> units = analecCorpus.getUnites(unit_type);
 		// units.sort() { a, b -> a.getDeb() <=> b.getDeb() ?: a.getFin() <=>
@@ -179,8 +185,8 @@
 		annotFileWriter.println("</annotations>");
 		annotFileWriter.close();
 		System.out.println(unitCount + " unit(s) found.");
-
+		
 		System.out.println("Annotations written to `" + annotFile + "'.");
 	}
-
-}
\ No newline at end of file
+	
+}
Index: tmp/org.txm.utils/src/org/txm/utils/TableReader.java
===================================================================
--- tmp/org.txm.utils/src/org/txm/utils/TableReader.java	(revision 2930)
+++ tmp/org.txm.utils/src/org/txm/utils/TableReader.java	(revision 2931)
@@ -120,7 +120,7 @@
 			tsvReader.close();
 		} else if (excelReader != null) {
 			excelReader.close();
-		}  else if (odsReader != null) {
+		} else if (odsReader != null) {
 			odsReader.close();
 		}
 	}
Index: tmp/org.txm.libs.msoffice/src/org/txm/libs/msoffice/ReadExcel.java
===================================================================
--- tmp/org.txm.libs.msoffice/src/org/txm/libs/msoffice/ReadExcel.java	(revision 2930)
+++ tmp/org.txm.libs.msoffice/src/org/txm/libs/msoffice/ReadExcel.java	(revision 2931)
@@ -119,10 +119,8 @@
 	}
 	
 	/**
-	 * extract lines and columns following rules.
+	 * search and replace lines utils
 	 * 
-	 * don't forget to save the ReadeExcel object
-	 * 
 	 * @param excel2
 	 * @param lineRules
 	 * @param columnsSelection
@@ -141,6 +139,148 @@
 	}
 	
 	/**
+	 * extract lines and columns following rules.
+	 * 
+	 * don't forget to save the ReadeExcel object
+	 * 
+	 * @param excel2
+	 * @param lineRules
+	 * @param columnsSelection
+	 * @return
+	 * @throws EncryptedDocumentException
+	 * @throws InvalidFormatException
+	 * @throws IOException
+	 */
+	public boolean copyColumns(HashMap<String, String> columnsToCopy) throws EncryptedDocumentException, InvalidFormatException, IOException {
+		Row headers = ws.getRow(0);
+		if (headers == null) return false;
+		
+		int colMax = headers.getLastCellNum();
+		int nRows = ws.getPhysicalNumberOfRows();
+		
+		HashMap<String, Integer> searchColumns = new HashMap<>();
+		for (int colIndex = 0; colIndex < colMax; colIndex++) {
+			Cell cell = headers.getCell(colIndex);
+			if (cell != null) {
+				String value = cellToString(cell).trim();
+				if (columnsToCopy.containsKey(value)) {
+					searchColumns.put(value, colIndex);
+				}
+			}
+		}
+		
+		if (searchColumns.keySet().size() != columnsToCopy.keySet().size()) {
+			System.out.println("Error: not all columns found=" + searchColumns.keySet() + " of " + columnsToCopy.keySet());
+			ArrayList<String> notFound = new ArrayList<>(columnsToCopy.keySet());
+			notFound.removeAll(searchColumns.keySet());
+			System.out.println("NOT FOUND: " + notFound);
+			return false;
+		}
+		
+		System.out.println("N Rows to update: " + nRows);
+		int nRowWritten = 0;
+		
+		for (int rowIndex = 0; rowIndex < nRows; rowIndex++) { // update all rows, starting from the second row (first row is the header)
+			Row row = ws.getRow(rowIndex);
+			if (row == null) continue;
+			
+			int icol = 0;
+			for (String col : columnsToCopy.keySet()) {
+				int colIndex = searchColumns.get(col);
+				
+				Cell cell = row.getCell(colIndex);
+				if (cell != null) {
+					Cell newCell = row.createCell(colMax + icol);
+					if (rowIndex == 0) {
+						newCell.setCellValue(columnsToCopy.get(col)); // first column must be renamed
+					}
+					else {
+						newCell.setCellValue(cellToString(cell).trim());
+					}
+				}
+				icol++;
+			}
+			
+			nRowWritten++;
+		}
+		
+		System.out.println("" + nRowWritten + " rows updated.");
+		return nRowWritten > 0;
+	}
+	
+	/**
+	 * extract lines and columns following rules.
+	 * 
+	 * don't forget to save the ReadeExcel object
+	 * 
+	 * @param excel2
+	 * @param lineRules
+	 * @param columnsSelection
+	 * @return
+	 * @throws EncryptedDocumentException
+	 * @throws InvalidFormatException
+	 * @throws IOException
+	 */
+	public boolean searchAndReplaceInLines(HashMap<String, String[]> searchAndReplaceRules) throws EncryptedDocumentException, InvalidFormatException, IOException {
+		Row headers = ws.getRow(0);
+		if (headers == null) return false;
+		
+		int colMax = headers.getLastCellNum();
+		int nRows = ws.getPhysicalNumberOfRows();
+		
+		HashMap<String, Integer> searchColumns = new HashMap<>();
+		for (int colIndex = 0; colIndex < colMax; colIndex++) {
+			Cell cell = headers.getCell(colIndex);
+			if (cell != null) {
+				String value = cellToString(cell).trim();
+				if (searchAndReplaceRules.containsKey(value)) {
+					searchColumns.put(value, colIndex);
+				}
+			}
+		}
+		
+		if (searchColumns.keySet().size() != searchAndReplaceRules.keySet().size()) {
+			System.out.println("Error: not all columns found=" + searchColumns.keySet() + " of " + searchAndReplaceRules.keySet());
+			ArrayList<String> notFound = new ArrayList<>(searchAndReplaceRules.keySet());
+			notFound.removeAll(searchColumns.keySet());
+			System.out.println("NOT FOUND: " + notFound);
+			return false;
+		}
+		
+		System.out.println("N Rows to update: " + nRows);
+		int nRowWritten = 0;
+		
+		for (int rowIndex = 0; rowIndex < nRows; rowIndex++) { // update all rows, starting from the second row (first row is the header)
+			Row row = ws.getRow(rowIndex);
+			if (row == null) continue;
+			
+			boolean change = false;
+			for (String col : searchAndReplaceRules.keySet()) {
+				int colIndex = searchColumns.get(col);
+				
+				Cell cell = row.getCell(colIndex);
+				if (cell != null) {
+					String value = cellToString(cell).trim();
+					String[] replace = searchAndReplaceRules.get(col);
+					String newValue = value.replaceAll(replace[0], replace[1]);
+					if (!value.equals(newValue)) {
+						cell.setCellValue(newValue);
+						change = true;
+					}
+				}
+			}
+			
+			if (change) {
+				nRowWritten++;
+			}
+		}
+		
+		System.out.println("" + nRowWritten + " rows updated.");
+		
+		return true;
+	}
+	
+	/**
 	 * one rule (regex test) per column
 	 * all lines are processed
 	 * 
@@ -208,8 +348,7 @@
 					String value = cellToString(cell).trim();
 					if (value.matches(columnsTest.get(i))) {
 						
-						// write new line
-						
+						// write new line in Sheet ws2
 						row2 = ws2.createRow(nRowWritten);
 						nCell = 0;
 						for (int iCol : columnIdxToWrite) {
Index: tmp/org.txm.libs.office/src/org/txm/libs/office/WriteODS.java
===================================================================
--- tmp/org.txm.libs.office/src/org/txm/libs/office/WriteODS.java	(revision 2930)
+++ tmp/org.txm.libs.office/src/org/txm/libs/office/WriteODS.java	(revision 2931)
@@ -19,6 +19,7 @@
 	public WriteODS(File newODSFile) throws Exception {
 		this.newODSFile = newODSFile;
 		this.spreadsheet = SpreadsheetDocument.newSpreadsheetDocument();
+		this.table = spreadsheet.getTableList().get(0);
 	}
 	
 	public void newTable(String name) {
@@ -36,7 +37,7 @@
 	 * @param nColumns columns are inserted if nColumns > 0
 	 */
 	public void declareRowsAndColumns(int nRows, int nColumns) {
-		if (table == null) throw new IllegalStateException("no table set with 'newtTable(...)'");
+		if (table == null) throw new IllegalStateException("no table set with 'newTable(...)'");
 		if (nRows > 0) {
 			table.appendRows(nRows);
 		}
@@ -47,7 +48,7 @@
 	}
 	
 	protected void writeLine(Object[] line, Row row) {
-		if (table == null) throw new IllegalStateException("no table set with 'newtTable(...)'");
+		if (table == null) throw new IllegalStateException("no table set with 'newTable(...)'");
 		for (int iCol = 0; iCol < line.length; iCol++) {
 			Cell cell = row.getCellByIndex(iCol);
 			if (cell != null) {
@@ -59,7 +60,7 @@
 		}
 	}
 	
-	public void writeLine(Object[] line, int iRow) {
+	public Row writeLine(Object[] line, int iRow) {
 		if (table == null) throw new IllegalStateException("no table set with 'newtTable(...)'");
 		Row row = table.getRowByIndex(iRow);
 		if (row != null) {
@@ -68,10 +69,13 @@
 		else {
 			throw new IllegalStateException("cannot get row at " + iRow);
 		}
+		return row;
 	}
 	
-	public void writeLine(ArrayList<?> line, int iRow) {
+	public Row writeLine(ArrayList<?> line, int iRow) {
+		
 		if (table == null) throw new IllegalStateException("no table set with 'newtTable(...)'");
+		
 		Row row = table.getRowByIndex(iRow);
 		if (row != null) {
 			writeLine(line.toArray(), row);
@@ -79,18 +83,25 @@
 		else {
 			throw new IllegalStateException("cannot get row at " + iRow);
 		}
+		return row;
 	}
 	
-	public void writeLine(Object[] line) {
-		if (table == null) throw new IllegalStateException("no table set with 'newtTable(...)'");
+	public Row writeLine(Object[] line) {
+		
+		if (table == null) throw new IllegalStateException("no table set with 'newTable(...)'");
+		
 		Row row = table.appendRow();
 		writeLine(line, row);
+		return row;
 	}
 	
-	public void writeLine(ArrayList<?> line) {
-		if (table == null) throw new IllegalStateException("no table set with 'newtTable(...)'");
+	public Row writeLine(ArrayList<?> line) {
+		
+		if (table == null) throw new IllegalStateException("no table set with 'newTable(...)'");
+		
 		Row row = table.appendRow();
 		writeLine(line.toArray(), row);
+		return row;
 	}
 	
 	public void save() throws Exception {
@@ -162,7 +173,7 @@
 	public static void main(String[] args) throws Exception {
 		
 		File file = new File("/home/mdecorde/TEMP/test_writing.ods");
-		ArrayList<ArrayList<String>> table = new ArrayList<ArrayList<String>>();
+		ArrayList<ArrayList<String>> table = new ArrayList<>();
 		
 	}
 }
Index: tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/transcriber/FixINAXML.groovy
===================================================================
--- tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/transcriber/FixINAXML.groovy	(revision 2930)
+++ tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/transcriber/FixINAXML.groovy	(revision 2931)
@@ -1,20 +0,0 @@
-import org.txm.utils.ConsoleProgressBar
-
-def directory = new File(System.getProperty("user.home"), "TEMP/ANTRACT/AF")
-println "Fixing $directory"
-def files = directory.listFiles()
-ConsoleProgressBar cpb = new ConsoleProgressBar(files.size())
-for (File trsFile : files) {
-//File trsFile = new File(directory, "AFE86004868.trs")
-	cpb.tick()
-	if (!trsFile.getName().endsWith(".trs")) {
-		continue;
-	}
-	String content = trsFile.getText("UTF-8")
-	content = content.replaceAll("punct=\"([^\"]+)\"\">", "punct=\"\$1\">")
-	content = content.replaceAll("<unk>", "???")
-	content = content.replaceAll(" Time=\"", " time=\"")
-	trsFile.setText(content, "UTF-8")
-}
-cpb.done()
-println "Done"
\ No newline at end of file
Index: tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/transcriber/AddSections.groovy
===================================================================
--- tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/transcriber/AddSections.groovy	(revision 2930)
+++ tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/transcriber/AddSections.groovy	(revision 2931)
@@ -1,228 +0,0 @@
-import java.nio.charset.Charset
-
-import java.time.LocalTime
-import java.time.format.DateTimeFormatter
-import org.txm.utils.*
-
-File metadataFile = new File("/home/mdecorde/TEMP/ANTRACT/AF/sujets.xlsx")
-File trsDirectory = new File("/home/mdecorde/TEMP/ANTRACT/AF/trs")
-
-def joinTRSColumn = "Lien notice principale"
-def typeColumns = ["Titre propre"]
-def topicColumns = ["Date de diffusion"]
-def startTimeColumn = "antract_debut"
-def endTimeColumn = "antract_fin"
-//def metadataColumns = ["Identifiant de la notice", "Titre propre", "antract_debut", "antract_fin"]
-def metadataColumns = [
-				"Titre propre", "Date de diffusion", "Identifiant de la notice", "Notes du titre", "Type de date", "Durée", "Genre", "Langue VO / VE", "Nature de production", "Producteurs (Aff.)", "Thématique",
-				"Nom fichier segmenté (info)", "antract_video", "antract_debut","antract_fin","antract_duree","antract_tc_type","antract_tc_date",
-				"Résumé", "Séquences", "Descripteurs (Aff. Lig.)", "Générique (Aff. Lig.)"]
-def metadataColumnsGroups = [
-	"metadata", "metadata", "metadata", "metadata", "metadata", "metadata", "metadata", "metadata", "metadata", "metadata", "metadata",
-	"secondary", "secondary", "secondary","secondary","secondary","secondary","secondary",
-	"text", "text", "text", "text"]
-
-if (metadataColumns.size() != metadataColumnsGroups.size()) {
-	println "ERROR in metadata declarations&groups:"
-	println "COLUMNS: "+metadataColumns
-	println "GROUPS : "+metadataColumnsGroups
-	return
-}
-
-if (!trsDirectory.exists()) {
-	println "$trsDirectory not found"
-	return
-}
-
-println "Loading data from $metadataFile..."
-TableReader reader = new TableReader(metadataFile)//, "\t".charAt(0), Charset.forName("UTF-8")
-reader.readHeaders()
-def header = reader.getHeaders()
-if (!header.contains(joinTRSColumn)) {
-	println "No TRS ID $joinTRSColumn column found"
-	return
-}
-if (!header.contains(startTimeColumn)) {
-	println "No start time $startTimeColumn column found"
-	return
-}
-if (!header.contains(endTimeColumn)) {
-	println "No end time $endTimeColumn column found"
-	return
-}
-for (def col : metadataColumns) {
-	if (!header.contains(endTimeColumn)) {
-		println "No $col column found"
-		return
-	}
-}
-for (def col : typeColumns) {
-	if (!header.contains(endTimeColumn)) {
-		println "No type $col column found"
-		return
-	}
-}
-for (def col : topicColumns) {
-	if (!header.contains(endTimeColumn)) {
-		println "No topic $col column found"
-		return
-	}
-}
-
-File outputDirectory = new File(trsDirectory, "out")
-println "Writing result to $outputDirectory..."
-
-dateTimeFormatter = DateTimeFormatter.ISO_LOCAL_TIME
-def strTotime(def str) {
-	if (str.lastIndexOf(":") == -1) {
-		return null
-	}
-	
-	bonusFrame = Integer.parseInt(str.substring(str.lastIndexOf(":")+1))
-	//if (str.contains("135475")) println "ERROR $str in $infos -> $bonusFrame"
-	if (bonusFrame > 25) {
-		bonusFrame=0;
-	}
-	totalFrame = str.substring(0, str.lastIndexOf(":"))
-	
-	LocalTime time1 = LocalTime.parse(totalFrame, dateTimeFormatter)
-	totalFrame = (time1.getHour()*60*60) + (time1.getMinute()*60) + time1.getSecond()
-
-		def ret = totalFrame + (bonusFrame/25)
-		return ret
-	}
-
-def sectionGroupsToInsert = [:]
-println "Reading data..."
-while (reader.readRecord()) {
-	String id = reader.get(joinTRSColumn).trim()
-	if (id.endsWith(".mp4")) id = id.substring(0, id.length()-4)
-	if (id.length() == 0) continue;
-		
-	if (!sectionGroupsToInsert.containsKey(id)) {
-		sectionGroupsToInsert[id] = []
-	}
-	def section = sectionGroupsToInsert[id]
-	
-	if (reader.get(startTimeColumn) != null && reader.get(startTimeColumn).length() > 0) { // ignore non timed sections
-		
-		def m = [:]
-		
-		for (def todo : ["topic":topicColumns, "type":typeColumns]) {
-			def data = []
-			for (def col : todo.value) {
-				if (reader.get(col).trim().length() > 0) {
-					data << reader.get(col).trim().replace("\n", "")
-				}
-			}
-			m[todo.key] = data.join("\t")
-		}
-		def metadataList = []
-		def metadataGroupList = []
-		for (int i = 0 ;  i < metadataColumns.size() ; i++) {
-			def col = metadataColumns[i]
-			String c = AsciiUtils.buildAttributeId(col)
-			m[c] = reader.get(col)
-			metadataList << c
-			metadataGroupList << metadataColumnsGroups[i]
-		}
-		m["metadata"] = metadataList.join("|") 
-		m["metadata_groups"] = metadataGroupList.join("|")
-		
-		m["startTime"] = strTotime(reader.get(startTimeColumn))
-		m["endTime"] = strTotime(reader.get(endTimeColumn))
-		m["synchronized"] = "true"
-				
-		section << [m["startTime"], m["endTime"], m]
-	}
-}
-
-println "Inserting sections... "+sectionGroupsToInsert.size()
-
-ConsoleProgressBar cpb = new ConsoleProgressBar(sectionGroupsToInsert.keySet().size())
-for (String id : sectionGroupsToInsert.keySet()) {
-	cpb.tick()
-	File trsFile = new File(trsDirectory, id+".trs")
-	if (!trsFile.exists()) {
-		continue
-	}
-	//println "Processing $id..."
-	def sections = sectionGroupsToInsert[id]
-	sections = sections.sort() { a, b -> a[0] <=> b[0] ?: a[1] <=> b[1] }
-	
-	// Open input file
-	def slurper = new XmlParser();
-	slurper.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false)
-		
-	def trs = slurper.parse(trsFile.toURI().toString())
-	def trsEpisodes = trs.Episode // 1
-	if (trsEpisodes.size() > 1) {
-		println "multiple Episode node in $trsFile"
-		continue
-	}
-	def trsEpisode = trsEpisodes[0]
-	def trsSections =  trs.Episode.Section // 1
-	if (trsSections.size() > 1) {
-		println "multiple Section node in $trsFile"
-		continue
-	}
-	def trsSection = trsSections[0]
-	
-	def turns = trsSection.Turn
-	def newSections = []
-	def iSection = 0;
-	def currentSection = null
-	def currentNode = null
-
-	for (def turn : turns) {
-		def start = Float.parseFloat(turn.@startTime)
-		def end = Float.parseFloat(turn.@endTime)
-		
-		def found = null;
-		for (int i = iSection ; i < sections.size() ; i++) {
-			if (end < sections[i][0]) { // Turn is before section
-				
-			} else if (sections[i][1] < start) { // Turn is before section
-				
-			} else {
-				found = sections[i]
-				iSection = i
-				break; // stop searching and set iSection to accelerate next search
-			}
-		}
-		
-		if (found == null) {
-			if (currentSection != null || currentNode == null) {
-				currentNode = new Node(trsEpisode, "Section", ["type":"Sujet non synchronisé", "startTime":turn.@startTime, "endTime":"", "synchronized":"false"] )
-				currentSection = null;
-			}
-		} else {
-			if (found != currentSection) {
-				if (currentNode != null && currentNode.@synchronized == "false") {
-					def tmp = currentNode.Turn
-					currentNode.@endTime = tmp[-1].@endTime
-				}
-				
-				currentSection = found
-				currentNode = new Node(trsEpisode, "Section", currentSection[2])
-			}
-		}
-		trsSection.remove(turn)
-		currentNode.append(turn)
-	}
-	
-	//remove the initial section
-	trsEpisode.remove(trsSection)
-	
-	outputDirectory.mkdir()
-	File outfile = new File(outputDirectory, trsFile.getName())
-	outfile.withWriter("UTF-8") { writer ->
-		writer.write('<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE Trans SYSTEM "trans-14.dtd">\n')
-		def printer = new groovy.util.XmlNodePrinter(new PrintWriter(writer))
-		printer.setPreserveWhitespace(true)
-		printer.print(trs)
-	}
-}
-cpb.done()
-reader.close()
-println "Done."
Index: tmp/org.txm.groovy.core/src/groovy/org/txm/macro/prototypes/transcription/FixINATRS.groovy
===================================================================
--- tmp/org.txm.groovy.core/src/groovy/org/txm/macro/prototypes/transcription/FixINATRS.groovy	(revision 0)
+++ tmp/org.txm.groovy.core/src/groovy/org/txm/macro/prototypes/transcription/FixINATRS.groovy	(revision 2931)
@@ -0,0 +1,27 @@
+import org.txm.utils.ConsoleProgressBar
+import org.kohsuke.args4j.*
+import groovy.transform.Field
+import org.txm.rcp.swt.widget.parameters.*
+
+@Field @Option(name="trsDirectory", usage="Dossier qui contient les fichiers TRS à corriger", widget="Folder", required=true, def="AF")
+def trsDirectory
+
+if (!ParametersDialog.open(this)) return;
+
+println "Fixing $trsDirectory"
+def files = trsDirectory.listFiles()
+ConsoleProgressBar cpb = new ConsoleProgressBar(files.size())
+for (File trsFile : files) {
+//File trsFile = new File(directory, "AFE86004868.trs")
+	cpb.tick()
+	if (!trsFile.getName().endsWith(".trs")) {
+		continue;
+	}
+	String content = trsFile.getText("UTF-8")
+	content = content.replaceAll("punct=\"([^\"]+)\"\">", "punct=\"\$1\">")
+	content = content.replaceAll("<unk>", "???")
+	content = content.replaceAll(" Time=\"", " time=\"")
+	trsFile.setText(content, "UTF-8")
+}
+cpb.done()
+println "Done"
\ No newline at end of file
Index: tmp/org.txm.groovy.core/src/groovy/org/txm/macro/prototypes/transcription/BuildAFMetadataMacro.groovy
===================================================================
--- tmp/org.txm.groovy.core/src/groovy/org/txm/macro/prototypes/transcription/BuildAFMetadataMacro.groovy	(revision 0)
+++ tmp/org.txm.groovy.core/src/groovy/org/txm/macro/prototypes/transcription/BuildAFMetadataMacro.groovy	(revision 2931)
@@ -0,0 +1,111 @@
+import java.io.File
+import java.nio.charset.Charset
+
+import java.time.LocalTime
+import java.time.format.DateTimeFormatter
+import java.util.Arrays
+import java.util.HashMap
+import java.util.List
+
+import org.txm.libs.msoffice.ReadExcel
+import org.txm.utils.*
+
+@Field @Option(name="tableFile", usage="Tableau des metadonnées de sections", widget="FileOpen", required=true, def="all.xlsx") // /home/mdecorde/TEMP/ANTRACT/AF/all.xlsx
+File tableFile;
+
+@Field @Option(name="buildSujetsMetadata", usage="Build the sujets metadata", widget="Boolean", required=true, def="true")
+boolean buildSujetsMetadata;
+
+@Field @Option(name="buildEmissionsMetadata", usage="Build the emissions metadata", widget="Boolean", required=true, def="true")
+boolean buildEmissionsMetadata;
+
+if (!ParametersDialog.open(this)) return;
+
+File table2File = null;
+
+System.out.println("opening $tableFile...");
+ReadExcel excel = new ReadExcel(tableFile, null);
+
+if (buildEmissionsMetadata) {
+	//emissions
+	table2File = new File(tableFile.getParentFile(), "emissions.xlsx");
+	HashMap<String, String> lineRules = new HashMap<>(); // line tests to select line to keep
+	List<String> columnsSelection; // list of columns to keep
+	HashMap<String, String> columnsToCopy = new HashMap<>();
+	HashMap<String, String> columnsToRenameRules = new HashMap<>();
+	HashMap<String, String[]> searchAndReplaceRules = new HashMap<>();
+	
+	columnsSelection = Arrays.asList(
+	"Identifiant de la notice", "Titre propre", "Notes du titre", "Date de diffusion", "Durée", "Nom fichier segmenté (info)", "antract_video",
+	"antract_debut","antract_fin","antract_duree","antract_tc_type","antract_tc_date");
+
+	lineRules.put("Type de notice", "Notice sommaire");
+	
+	columnsToRenameRules.put("Identifiant de la notice", "id");
+	
+	columnsToCopy.put("Notes du titre", "subtitle");
+	columnsToCopy.put("Titre propre", "title"); 
+	columnsToCopy.put("Date de diffusion", "textorder");
+	columnsToCopy.put("Date de diffusion", "annee");
+	
+	searchAndReplaceRules.put("textorder", ["([0-9][0-9])/([0-9][0-9])/([0-9][0-9][0-9][0-9])", '$3$2$1'] as String[]); // not working yet
+	searchAndReplaceRules.put("annee", ["([0-9][0-9])/([0-9][0-9])/([0-9][0-9][0-9][0-9])", '$3'] as String[]); // not working yet
+	
+	process(excel, table2File, lineRules, columnsSelection, columnsToCopy, searchAndReplaceRules, columnsToRenameRules)
+}
+
+if (buildSujetsMetadata) {
+	// sujets
+	table2File = new File(tableFile.getParentFile(), "sujets.xlsx");
+	HashMap<String, String> lineRules = new HashMap<>(); // line tests to select line to keep
+	List<String> columnsSelection; // list of columns to keep
+	HashMap<String, String> columnsToCopy = new HashMap<>();
+	HashMap<String, String> columnsToRenameRules = new HashMap<>();
+	HashMap<String, String[]> searchAndReplaceRules = new HashMap<>();
+	
+	columnsSelection = Arrays.asList(
+		"Identifiant de la notice", "Titre propre", "Notes du titre", "Lien notice principale",
+		"Date de diffusion", "Type de date", "Durée", "Genre", "Langue VO / VE", "Nature de production", "Producteurs (Aff.)", "Thématique",
+		"Nom fichier segmenté (info)", "antract_video", "antract_debut", "antract_fin", "antract_duree", "antract_tc_type", "antract_tc_date",
+		"Résumé", "Séquences", "Descripteurs (Aff. Lig.)", "Générique (Aff. Lig.)");
+	
+	lineRules.put("Type de notice", "Notice sujet");
+	
+	process(excel, table2File, lineRules, columnsSelection, columnsToCopy, searchAndReplaceRules, columnsToRenameRules)
+}
+
+def process(ReadExcel excel, File table2File, def lineRules, def columnsSelection, def columnsToCopy, def searchAndReplaceRules, def columnsToRenameRules) {
+	System.out.println("Writing: $table2File");
+	
+	table2File.delete();
+	ReadExcel excel2 = new ReadExcel(table2File, null);
+	println " Selecting $columnsSelection with lines matching $lineRules"
+	if (!excel.extractTo(excel2, lineRules, columnsSelection)) {
+		System.out.println("FAIL");
+		return;
+	}
+	
+	if (columnsToCopy.size() > 0) {
+		System.out.println(" Copying column: " + columnsToCopy);
+		excel2.copyColumns(columnsToCopy);
+		println " WARNING: ReadExcel.copyColumns() not implemented"
+	}
+	
+	if (searchAndReplaceRules.size() > 0) {
+		System.out.println(" Search&replace column: " + searchAndReplaceRules);
+		excel2.searchAndReplaceInLines(searchAndReplaceRules);
+	}
+	
+	if (columnsToRenameRules.size() > 0) {
+		System.out.println(" Renaming column: " + columnsToRenameRules);
+		excel2.renameColumns(columnsToRenameRules);
+	}
+	
+	System.out.println(" Saving&Closing...");
+	excel2.save();
+	excel2.close();
+	excel.close();
+	System.out.println("Done: $table2File");
+	
+	return table2File.exists()
+}
Index: tmp/org.txm.groovy.core/src/groovy/org/txm/macro/prototypes/transcription/AddSectionsFromTableMacro.groovy
===================================================================
--- tmp/org.txm.groovy.core/src/groovy/org/txm/macro/prototypes/transcription/AddSectionsFromTableMacro.groovy	(revision 0)
+++ tmp/org.txm.groovy.core/src/groovy/org/txm/macro/prototypes/transcription/AddSectionsFromTableMacro.groovy	(revision 2931)
@@ -0,0 +1,243 @@
+import java.nio.charset.Charset
+
+import java.time.LocalTime
+import java.time.format.DateTimeFormatter
+import org.txm.utils.*
+
+@Field @Option(name="metadataFile", usage="Tableau des metadonnées de sections", widget="FileOpen", required=true, def="")
+File metadataFile;
+
+@Field @Option(name="trsDirectory", usage="Dossier qui contient les fichiers TRS", widget="Folder", required=true, def="")
+File trsDirectory;
+
+@Field @Option(name="joinTRSColumn", usage="Colonne de jointure de transcription", widget="String", required=true, def="Lien notice principale")
+def joinTRSColumn
+
+@Field @Option(name="startTimeColumn", usage="Colonne de timing de début de section", widget="String", required=true, def="antract_debut")
+def startTimeColumn = "antract_debut"
+
+@Field @Option(name="endTimeColumn", usage="Colonne de timing de fin de section", widget="String", required=true, def="antract_fin")
+def endTimeColumn = "antract_fin"
+
+@Field @Option(name="typeColumns", usage="Colonnes des métadonnées de type de section", widget="String", required=true, def="Titre propre")
+def typeColumns
+
+@Field @Option(name="topicColumns", usage="Colonnes des métadonnées de topic de section", widget="String", required=true, def="Date de diffusion")
+def topicColumns
+
+@Field @Option(name="metadataColumns", usage="Colonnes de metadonnées de section", widget="String", required=true, def="Titre propre;Date de diffusion;Identifiant de la notice;Notes du titre;Type de date;Durée;Genre;Langue VO / VE;Nature de production;Producteurs (Aff.);Thématique;Nom fichier segmenté (info);antract_video;antract_debut;antract_fin;antract_duree;antract_tc_type;antract_tc_date;Résumé;Séquences;Descripteurs (Aff. Lig.);Générique (Aff. Lig.)")
+def metadataColumns
+
+@Field @Option(name="metadataColumnsGroups", usage="Colonnes des gruopes de metadonnées de section", widget="String", required=true, def="metadata;metadata;metadata;metadata;metadata;metadata;metadata;metadata;metadata;metadata;metadata;secondary;secondary;secondary;secondary;secondary;secondary;secondary;text;text;text;text")
+def metadataColumnsGroups
+
+if (!ParametersDialog.open(this)) return;
+typeColumns = typeColumns.split(";")
+topicColumns = topicColumns.split(";")
+metadataColumns = metadataColumns.split(";")
+metadataColumnsGroups = metadataColumnsGroups.split(";")
+
+if (metadataColumns.size() != metadataColumnsGroups.size()) {
+	println "ERROR in metadata declarations&groups:"
+	println "COLUMNS: "+metadataColumns
+	println "GROUPS : "+metadataColumnsGroups
+	return
+}
+
+if (!trsDirectory.exists()) {
+	println "$trsDirectory not found"
+	return
+}
+
+println "Loading data from $metadataFile..."
+TableReader reader = new TableReader(metadataFile)//, "\t".charAt(0), Charset.forName("UTF-8")
+reader.readHeaders()
+def header = reader.getHeaders()
+if (!header.contains(joinTRSColumn)) {
+	println "No TRS ID $joinTRSColumn column found"
+	return
+}
+if (!header.contains(startTimeColumn)) {
+	println "No start time $startTimeColumn column found"
+	return
+}
+if (!header.contains(endTimeColumn)) {
+	println "No end time $endTimeColumn column found"
+	return
+}
+for (def col : metadataColumns) {
+	if (!header.contains(endTimeColumn)) {
+		println "No $col column found"
+		return
+	}
+}
+for (def col : typeColumns) {
+	if (!header.contains(endTimeColumn)) {
+		println "No type $col column found"
+		return
+	}
+}
+for (def col : topicColumns) {
+	if (!header.contains(endTimeColumn)) {
+		println "No topic $col column found"
+		return
+	}
+}
+
+File outputDirectory = new File(trsDirectory, "out")
+println "Writing result to $outputDirectory..."
+
+dateTimeFormatter = DateTimeFormatter.ISO_LOCAL_TIME
+def strTotime(def str) {
+	if (str.lastIndexOf(":") == -1) {
+		return null
+	}
+	
+	bonusFrame = Integer.parseInt(str.substring(str.lastIndexOf(":")+1))
+	//if (str.contains("135475")) println "ERROR $str in $infos -> $bonusFrame"
+	if (bonusFrame > 25) {
+		bonusFrame=0;
+	}
+	totalFrame = str.substring(0, str.lastIndexOf(":"))
+	
+	LocalTime time1 = LocalTime.parse(totalFrame, dateTimeFormatter)
+	totalFrame = (time1.getHour()*60*60) + (time1.getMinute()*60) + time1.getSecond()
+
+		def ret = totalFrame + (bonusFrame/25)
+		return ret
+	}
+
+def sectionGroupsToInsert = [:]
+println "Reading data..."
+while (reader.readRecord()) {
+	String id = reader.get(joinTRSColumn).trim()
+	if (id.endsWith(".mp4")) id = id.substring(0, id.length()-4)
+	if (id.length() == 0) continue;
+		
+	if (!sectionGroupsToInsert.containsKey(id)) {
+		sectionGroupsToInsert[id] = []
+	}
+	def section = sectionGroupsToInsert[id]
+	
+	if (reader.get(startTimeColumn) != null && reader.get(startTimeColumn).length() > 0) { // ignore non timed sections
+		
+		def m = [:]
+		
+		for (def todo : ["topic":topicColumns, "type":typeColumns]) {
+			def data = []
+			for (def col : todo.value) {
+				if (reader.get(col).trim().length() > 0) {
+					data << reader.get(col).trim().replace("\n", "")
+				}
+			}
+			m[todo.key] = data.join("\t")
+		}
+		def metadataList = []
+		def metadataGroupList = []
+		for (int i = 0 ;  i < metadataColumns.size() ; i++) {
+			def col = metadataColumns[i]
+			String c = AsciiUtils.buildAttributeId(col)
+			m[c] = reader.get(col)
+			metadataList << c
+			metadataGroupList << metadataColumnsGroups[i]
+		}
+		m["metadata"] = metadataList.join("|") 
+		m["metadata_groups"] = metadataGroupList.join("|")
+		
+		m["startTime"] = strTotime(reader.get(startTimeColumn))
+		m["endTime"] = strTotime(reader.get(endTimeColumn))
+		m["synchronized"] = "true"
+				
+		section << [m["startTime"], m["endTime"], m]
+	}
+}
+
+println "Inserting sections... "+sectionGroupsToInsert.size()
+
+ConsoleProgressBar cpb = new ConsoleProgressBar(sectionGroupsToInsert.keySet().size())
+for (String id : sectionGroupsToInsert.keySet()) {
+	cpb.tick()
+	File trsFile = new File(trsDirectory, id+".trs")
+	if (!trsFile.exists()) {
+		continue
+	}
+	//println "Processing $id..."
+	def sections = sectionGroupsToInsert[id]
+	sections = sections.sort() { a, b -> a[0] <=> b[0] ?: a[1] <=> b[1] }
+	
+	// Open input file
+	def slurper = new groovy.util.XmlParser(false, true, true);
+	slurper.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false) // allow DTD declaration
+	slurper.setProperty("http://javax.xml.XMLConstants/property/accessExternalDTD", "all"); // allow to read DTD from local file
+	def trs = slurper.parse(trsFile.toURI().toString())
+	def trsEpisodes = trs.Episode // 1
+	if (trsEpisodes.size() > 1) {
+		println "multiple Episode node in $trsFile"
+		continue
+	}
+	def trsEpisode = trsEpisodes[0]
+	def trsSections =  trs.Episode.Section // 1
+	if (trsSections.size() > 1) {
+		println "multiple Section node in $trsFile"
+		continue
+	}
+	def trsSection = trsSections[0]
+	
+	def turns = trsSection.Turn
+	def newSections = []
+	def iSection = 0;
+	def currentSection = null
+	def currentNode = null
+
+	for (def turn : turns) {
+		def start = Float.parseFloat(turn.@startTime)
+		def end = Float.parseFloat(turn.@endTime)
+		
+		def found = null;
+		for (int i = iSection ; i < sections.size() ; i++) {
+			if (end < sections[i][0]) { // Turn is before section
+				
+			} else if (sections[i][1] < start) { // Turn is before section
+				
+			} else {
+				found = sections[i]
+				iSection = i
+				break; // stop searching and set iSection to accelerate next search
+			}
+		}
+		
+		if (found == null) {
+			if (currentSection != null || currentNode == null) {
+				currentNode = new Node(trsEpisode, "Section", ["type":"Sujet non synchronisé", "startTime":turn.@startTime, "endTime":"", "synchronized":"false"] )
+				currentSection = null;
+			}
+		} else {
+			if (found != currentSection) {
+				if (currentNode != null && currentNode.@synchronized == "false") {
+					def tmp = currentNode.Turn
+					currentNode.@endTime = tmp[-1].@endTime
+				}
+				
+				currentSection = found
+				currentNode = new Node(trsEpisode, "Section", currentSection[2])
+			}
+		}
+		trsSection.remove(turn)
+		currentNode.append(turn)
+	}
+	
+	//remove the initial section
+	trsEpisode.remove(trsSection)
+	
+	outputDirectory.mkdir()
+	File outfile = new File(outputDirectory, trsFile.getName())
+	outfile.withWriter("UTF-8") { writer ->
+		writer.write('<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE Trans SYSTEM "trans-14.dtd">\n')
+		def printer = new groovy.util.XmlNodePrinter(new PrintWriter(writer))
+		printer.setPreserveWhitespace(true)
+		printer.print(trs)
+	}
+}
+cpb.done()
+reader.close()
+println "Done."
