Heavily modified/added classes:
Config, GlobalPreferenceFrame, GraphBox, GraphFrame, GraphIO, MultipleSelection, MyDropTarget,
ProcessCommand, ProcessThread, ProcessInfoFrame, SaveGraphDialog, TextField, UnitexFrame  

/*
 * Unitex
 *
 * Copyright (C) 2001-2006 Universit� de Marne-la-Vall�e <unitex@univ-mlv.fr>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
 *
 */

package ndosownww.unitex.changes;

import java.awt.*;
import java.io.*;
import java.util.*;
import java.util.regex.*;

import javax.swing.*;

import toposlaw.multiflex.ExecutingMultiflex;



/**
 * This class contains general configuration information. It contains constants
 * used by many other classes.
 * 
 * @author S�bastien Paumier
 *  
 */
public class Config {


	/**
	 * Path of the directory <code>.../Unitex</code>
	 */
	private static File unitexDir;

	/**
	 * Path of the user directory <code>.../(user dir)</code>
	 */
	private static File userDir;

	/**
	 * Current language. Languages must be in English, with the first letter in
	 * uppercase and the others in lowercase. Example: "French"
	 */
	private static String currentLanguage = "Polish";

	/**
	 * Path of the user's current language directory
	 * <code>.../(user dir)/(current language)</code>
	 */
	private static File userCurrentLanguageDir;

	/**
	 * Path of the system's current language directory
	 * <code>.../Unitex/(current language)</code>
	 */
	private static File unitexCurrentLanguageDir;

	/**
	 * Path of the user's corpus directory
	 * <code>.../(user dir)/(current language)/Corpus</code>
	 */
	private static File currentCorpusDir;

	/**
	 * Path of the user's graph directory
	 * <code>.../(user dir)/(current language)/Graphs</code>
	 */
	private static File currentGraphDir;

	/**
	 * Path of the user's current corpus
	 * <code>.../(user dir)/(current language)/Corpus/(my_corpus.snt)</code>
	 */
	private static File currentSnt;

	/**
	 * Path of the user's current corpus directory
	 * <code>.../(user dir)/(current language)/Corpus/(my_corpus_snt)</code>
	 */
	private static File currentSntDir;

	/**
	 * Path of the user's ELAG directory
	 * <code>.../(user dir)/(current language)/Elag</code>
	 */
	private static File currentElagDir;

	/**
	 * Path of the user's current language alphabet file
	 * <code>.../(user dir)/(current language)/Alphabet.txt</code>
	 */
	private static File alphabet = new File(ExecutingMultiflex.getAlphabet());

	public final static int WINDOWS_SYSTEM = 0;
	public final static int LINUX_SYSTEM = 1;
	public final static int MAC_OS_X_SYSTEM = 2;
	public final static int SUN_OS_SYSTEM = 3;

	/**
	 * Limit over which the concordance should be viewed with a web navigator
	 */
	public final static int MAXIMUM_UTTERANCE_NUMBER_TO_DISPLAY_WITH_JAVA = 2000;

	private static String currentSystemName;

	/**
	 * Path of the user's current sentence delimitation graph
	 * <code>.../(user dir)/(current language)/Graphs/Preprocessing/Sentence/Sentence.fst2</code>
	 */
	private static File currentSentenceGraph;

	/**
	 * Path of the user's current replace graph
	 * <code>.../(user dir)/(current language)/Graphs/Preprocessing/Replace/Replace.fst2</code>
	 */
	private static File currentReplaceGraph;

	/**
	 * Constant indicating under which system Unitex is running
	 */
	private static int currentSystem = WINDOWS_SYSTEM;

	private static String userName;

	private static File userFile;

	private static File currentDELA;
	

	/**
	 * Message shown chen a text file is too large to be loaded.
	 */
	public static final String CORPUS_TOO_LARGE_MESSAGE = "This corpus is ready to be manipulated with Unitex, but it is too large to be displayed.\nUse a wordprocessor to view it.";

	public static final String FILE_TOO_LARGE_MESSAGE = "This file is too large to be displayed. Use a wordprocessor to view it.";

	/**
	 * Empty file error message.
	 */
	public static final String EMPTY_FILE_MESSAGE = "This file is empty.";

	/**
	 * File reading error message.
	 */
	public static final String ERROR_WHILE_READING_FILE_MESSAGE = "Cannot read this file.";

	/**
	 * Dialog box used to open or save graphs
	 */
	private static JFileChooser graphDialogBox;
	private static PersonalFileFilter grfFileFilter;

	/**
	 * Dialog box used to choose a ".grf" or ".fst2" graph to be used in pattern
	 * matching
	 */
	private static JFileChooser grfAndFst2DialogBox;

	/**
	 * Dialog box used to choose the 'Sentence' graph 
	 */
	private static JFileChooser sentenceDialogBox;

	/**
	 * Dialog box used to choose the 'Replace' graph
	 */
	private static JFileChooser replaceDialogBox;

	/**
	 * Dialog box used to open ".txt" or ".snt" text files
	 */
	private static JFileChooser corpusDialogBox;

	/**
	 * Dialog box used to open DELAF dictionaries. The file filter of this
	 * dialog box accepts ".dic" files, and also "dlf" and "dlc" files, that are
	 * text dictionaries.
	 */
	private static JFileChooser delaDialogBox;

	/**
	 * Dialog box used to select the directory where the inflection grammars are
	 * supposed to be
	 */
	private static JFileChooser inflectDialogBox;

	/**
	 * Dialog box used to open lexicon-grammars tables
	 */
	private static JFileChooser tableDialogBox;

	/**
	 * Dialog box used to open files to transcode
	 */
	private static JFileChooser transcodeDialogBox;

	/**
	 * Dialog box used to open files to edit
	 */
	private static JFileChooser fileEditionDialogBox;
	
	/**
	 * Dialog box used to select for morpheme and variation result directory
	 */
	private static JFileChooser morphemVariantsDiaglogBox;
	
	/**
	 * Dialog box used to select for derivation directory
	 */
	private static JFileChooser variationDialogBox;

	/**
	 * Dialog box used to select for derivation directory
	 */
	private static JFileChooser derivationDialogBox;

	/**
	 * Dialog box used to choose an output text file for
	 * Fst2Unambig
	 */
	private static JFileChooser fst2UnambigDialogBox;

	private static File applicationDir;


	/**
	 * Initializes the system. This method finds which system is running, which
	 * user is working. Then, it initalizes dialog boxes and ask the user to
	 * choose the initial language he wants to work on.
	 *  
	 */
	public static void initConfig() {
	//	determineWhichSystemIsRunning();

		MyCursors.initCursorsAndIcons();
		//determineCurrentUser();

//		setDefaultPreprocessingGraphs();
	}

	
	private static void updateGraphFileFilters(boolean allowImageFormats) {
		graphDialogBox.resetChoosableFileFilters();
		if (allowImageFormats) {
			graphDialogBox.addChoosableFileFilter(grfFileFilter);
		} else {
			graphDialogBox.removeChoosableFileFilter(grfFileFilter);
		}
	}
	public static JFileChooser getGraphDialogBox(boolean allowImageFormats) {
		if (graphDialogBox != null) {
			updateGraphFileFilters(allowImageFormats);
			return graphDialogBox;
		}
		graphDialogBox = new JFileChooser();
		grfFileFilter=new PersonalFileFilter("grf", "Unicode Graphs");
		
		graphDialogBox.addChoosableFileFilter(grfFileFilter);
		graphDialogBox.setDialogType(JFileChooser.OPEN_DIALOG);
		graphDialogBox.setCurrentDirectory(Config.getCurrentGraphDir());
		graphDialogBox.setMultiSelectionEnabled(true);
		return graphDialogBox;
	}

	public static JFileChooser getGrfAndFst2DialogBox() {
		if (grfAndFst2DialogBox != null)
			return grfAndFst2DialogBox;
		grfAndFst2DialogBox = new JFileChooser();
		grfAndFst2DialogBox.addChoosableFileFilter(new PersonalFileFilter(
				"fst2", "Unicode Compiled Graphs"));
		grfAndFst2DialogBox.addChoosableFileFilter(new PersonalFileFilter(
				"grf", "Unicode Graphs"));
		grfAndFst2DialogBox.setDialogType(JFileChooser.OPEN_DIALOG);
		grfAndFst2DialogBox.setCurrentDirectory(Config.getCurrentGraphDir());
		grfAndFst2DialogBox.setMultiSelectionEnabled(false);
		return grfAndFst2DialogBox;
	}

	public static JFileChooser getSentenceDialogBox() {
		if (sentenceDialogBox != null)
			return sentenceDialogBox;
		sentenceDialogBox = new JFileChooser();
		sentenceDialogBox.addChoosableFileFilter(new PersonalFileFilter(
				"fst2", "Unicode Compiled Graphs"));
		sentenceDialogBox.addChoosableFileFilter(new PersonalFileFilter(
				"grf", "Unicode Graphs"));
		sentenceDialogBox.setDialogType(JFileChooser.OPEN_DIALOG);
		File f=new File(Config.getCurrentGraphDir(),"Preprocessing");
		f=new File(f,"Sentence");
		sentenceDialogBox.setCurrentDirectory(f);
		sentenceDialogBox.setMultiSelectionEnabled(false);
		return sentenceDialogBox;
	}

	public static JFileChooser getReplaceDialogBox() {
		if (replaceDialogBox != null)
			return replaceDialogBox;
		replaceDialogBox = new JFileChooser();
		replaceDialogBox.addChoosableFileFilter(new PersonalFileFilter(
				"fst2", "Unicode Compiled Graphs"));
		replaceDialogBox.addChoosableFileFilter(new PersonalFileFilter(
				"grf", "Unicode Graphs"));
		replaceDialogBox.setDialogType(JFileChooser.OPEN_DIALOG);
		File f=new File(Config.getCurrentGraphDir(),"Preprocessing");
		f=new File(f,"Replace");
		replaceDialogBox.setCurrentDirectory(f);
		replaceDialogBox.setMultiSelectionEnabled(false);
		return replaceDialogBox;
	}

	public static JFileChooser getDelaDialogBox() {
		if (delaDialogBox != null)
			return delaDialogBox;
		delaDialogBox = new JFileChooser();
		delaDialogBox.addChoosableFileFilter(new PersonalFileFilter("dic",
				"Unicode DELA Dictionaries"));
		delaDialogBox.setDialogType(JFileChooser.OPEN_DIALOG);
		delaDialogBox.setCurrentDirectory(new File(Config
				.getUserCurrentLanguageDir(), "Dela"));
		delaDialogBox.setMultiSelectionEnabled(false);
		return delaDialogBox;
	}

	public static JFileChooser getCorpusDialogBox() {
		if (corpusDialogBox != null)
			return corpusDialogBox;
		corpusDialogBox = new JFileChooser();
		corpusDialogBox.addChoosableFileFilter(new PersonalFileFilter("txt",
				"Raw Unicode Texts"));
		corpusDialogBox.addChoosableFileFilter(new PersonalFileFilter("snt",
				"Unitex Texts"));
		corpusDialogBox.setDialogType(JFileChooser.OPEN_DIALOG);
		corpusDialogBox.setCurrentDirectory(Config.getCurrentCorpusDir());
		corpusDialogBox.setMultiSelectionEnabled(false);
		return corpusDialogBox;
	}

	public static JFileChooser getInflectDialogBox() {
		if (inflectDialogBox != null)
			return inflectDialogBox;
		inflectDialogBox = new JFileChooser();
		inflectDialogBox.setDialogTitle("Choose the inflection directory");
		inflectDialogBox.setDialogType(JFileChooser.OPEN_DIALOG);
		inflectDialogBox.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		inflectDialogBox.setCurrentDirectory(new File(Config
				.getUserCurrentLanguageDir(), "Inflection"));
		return inflectDialogBox;
	}
	public static JFileChooser getVarDialogBox() {
		if (variationDialogBox != null)
			return variationDialogBox;
		variationDialogBox = new JFileChooser();
		variationDialogBox.setDialogTitle("Choose the variation directory");
		variationDialogBox.setDialogType(JFileChooser.OPEN_DIALOG);
		variationDialogBox.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		variationDialogBox.setCurrentDirectory(new File(Config
				.getUserCurrentLanguageDir(), "Variation"));
		return variationDialogBox;
	}
	
	public static JFileChooser getDevDialogBox() {
		if (derivationDialogBox != null)
			return derivationDialogBox;
		derivationDialogBox = new JFileChooser();
		derivationDialogBox.setDialogTitle("Choose the derivation directory");
		derivationDialogBox.setDialogType(JFileChooser.OPEN_DIALOG);
		derivationDialogBox.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		derivationDialogBox.setCurrentDirectory(new File(Config
				.getUserCurrentLanguageDir(), "Derivation"));
		return derivationDialogBox;
	}

	public static JFileChooser getTableDialogBox() {
		if (tableDialogBox != null)
			return tableDialogBox;
		tableDialogBox = new JFileChooser();
		tableDialogBox.setFileFilter(new PersonalFileFilter("txt",
				"Unicode Text Tables"));
		tableDialogBox.setDialogType(JFileChooser.OPEN_DIALOG);
		tableDialogBox.setCurrentDirectory(Config.getUserCurrentLanguageDir());
		return tableDialogBox;
	}

	public static JFileChooser getTranscodeDialogBox() {
		if (transcodeDialogBox != null)
			return transcodeDialogBox;
		transcodeDialogBox = new JFileChooser();
		transcodeDialogBox.setDialogType(JFileChooser.OPEN_DIALOG);
		transcodeDialogBox.setMultiSelectionEnabled(true);
		transcodeDialogBox.setDialogTitle("Select files to transcode");
		transcodeDialogBox.setCurrentDirectory(Config.getCurrentCorpusDir());
		return transcodeDialogBox;
	}

	public static JFileChooser getFileEditionDialogBox() {
		if (fileEditionDialogBox != null)
			return fileEditionDialogBox;
		fileEditionDialogBox = new JFileChooser();
		fileEditionDialogBox.setDialogType(JFileChooser.OPEN_DIALOG);
		fileEditionDialogBox.setMultiSelectionEnabled(false);
		fileEditionDialogBox.setCurrentDirectory(Config.getCurrentCorpusDir());
		fileEditionDialogBox.setDialogTitle("Select file to edit");
		return fileEditionDialogBox;
	}

	public static JFileChooser getFst2UnambigDialogBox() {
		if (fst2UnambigDialogBox != null)
			return fst2UnambigDialogBox;
		fst2UnambigDialogBox = new JFileChooser();
		fst2UnambigDialogBox.setFileFilter(new PersonalFileFilter("txt",
				"Unicode Text File"));
		fst2UnambigDialogBox.setDialogType(JFileChooser.OPEN_DIALOG);
		fst2UnambigDialogBox.setCurrentDirectory(Config.getCurrentCorpusDir());
		fst2UnambigDialogBox.setMultiSelectionEnabled(false);
		return fst2UnambigDialogBox;
	}

	
	/**
	 * Updates working directories of dialog boxes. This method is called when
	 * the user changes of working language.
	 *  
	 */
	public static void updateOpenSaveDialogBoxes() {
		if (graphDialogBox != null)
			graphDialogBox.setCurrentDirectory(Config.getCurrentGraphDir());
		if (grfAndFst2DialogBox != null)
			grfAndFst2DialogBox
					.setCurrentDirectory(Config.getCurrentGraphDir());
		if (sentenceDialogBox != null)
			sentenceDialogBox
					.setCurrentDirectory(new File(new File(Config.getCurrentGraphDir(),"Preprocessing"),"Sentence"));
		if (replaceDialogBox != null)
			replaceDialogBox
					.setCurrentDirectory(new File(new File(Config.getCurrentGraphDir(),"Preprocessing"),"Replace"));
		if (corpusDialogBox != null)
			corpusDialogBox.setCurrentDirectory(Config.getCurrentCorpusDir());
		if (delaDialogBox != null)
			delaDialogBox.setCurrentDirectory(new File(Config
					.getUserCurrentLanguageDir(), "Dela"));
		if (inflectDialogBox != null)
			inflectDialogBox.setCurrentDirectory(new File(Config
					.getUserCurrentLanguageDir(), "Inflection"));
		if(Config.isAgglutinativeLanguage()){
			if (morphemVariantsDiaglogBox != null)
				morphemVariantsDiaglogBox.setCurrentDirectory(new File(Config
						.getUserCurrentLanguageDir(), "MorphemVariants"));
			if (variationDialogBox != null)
				variationDialogBox.setCurrentDirectory(new File(Config
					.getUserCurrentLanguageDir(), "Variation"));
			if (derivationDialogBox != null)
				derivationDialogBox.setCurrentDirectory(new File(Config
					.getUserCurrentLanguageDir(), "Derivation"));
			
		}
		if (tableDialogBox != null)
			tableDialogBox.setCurrentDirectory(Config
					.getUserCurrentLanguageDir());
		if (transcodeDialogBox != null)
			transcodeDialogBox
					.setCurrentDirectory(Config.getCurrentCorpusDir());
		if (fileEditionDialogBox != null)
			fileEditionDialogBox.setCurrentDirectory(Config
					.getCurrentCorpusDir());
		if (fst2UnambigDialogBox != null)
			fst2UnambigDialogBox.setCurrentDirectory(Config
					.getCurrentCorpusDir());
	}


	/**
	 * Finds the user's name. If the user works with Unitex for the first time,
	 * he is asked for choosing his private working directory if he works under
	 * Windows. Under Linux or MacOS, his private directory is a directory named
	 * "unitex", created in his home directory.
	 *  
	 */
	public static void determineCurrentUser() {
		userName = System.getProperty("user.name");
		if (currentSystem == WINDOWS_SYSTEM) {
			// configuration procedure under Windows
			File directory = new File(getUnitexDir(), "Users");
			if (!directory.exists()) {
				directory.mkdir();
			}
			userFile = new File(new File(getUnitexDir(), "Users"), userName
					+ ".cfg");
			if (!userFile.exists()) {
				try {
					chooseNewUserDir();
					userFile.createNewFile();
					BufferedWriter bw = new BufferedWriter(new FileWriter(
							userFile));
					bw.write(getUserDir().getAbsolutePath(), 0, getUserDir()
							.getAbsolutePath().length());
					bw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			} else {
				try {
					BufferedReader br = new BufferedReader(new FileReader(
							userFile));
					String s = br.readLine();
					if (s == null || s.equals("")) {
						System.out.println("Error: " + userFile + " is empty!");
						s = null;
					}
					setUserDir(new File(s));
					br.close();
				} catch (IOException e) {
					System.out.println("Error: " + userFile + " is empty!");
					e.printStackTrace();
				}
			}
			return;
		}
		if ((currentSystem == LINUX_SYSTEM)
				|| (currentSystem == MAC_OS_X_SYSTEM)
				|| (currentSystem == SUN_OS_SYSTEM)) {
			File rep = new File(System.getProperty("user.home"), "unitex");
			if (!rep.exists()) {
				// if the directory does not exist, we inform the user
				String message = "Welcome " + getUserName() + "!\n\n";
				message = message
						+ "Your private Unitex directory where you can\nstore your own data is:\n\n";
				message = message + rep + "\n";
				JOptionPane.showMessageDialog(null, message, "Welcome",
						JOptionPane.PLAIN_MESSAGE);
			}
			setUserDir(rep);
		}
	}

	/**
	 * Finds which operating system is used. If the system is not supported by
	 * Unitex, the program stops.
	 *  
	 */
	public static void determineWhichSystemIsRunning() {
		currentSystemName = System.getProperty("os.name");
		if (currentSystemName.equalsIgnoreCase("Windows NT")
				|| currentSystemName.equalsIgnoreCase("Windows 2003")
				|| currentSystemName.equalsIgnoreCase("Windows 2000")
				|| currentSystemName.equalsIgnoreCase("Windows 98")
				|| currentSystemName.equalsIgnoreCase("Windows 95")
				|| currentSystemName.equalsIgnoreCase("Windows XP")
				|| currentSystemName.equalsIgnoreCase("Windows ME")
				|| currentSystemName.equalsIgnoreCase("Windows Vista")
				|| currentSystemName.equalsIgnoreCase("Windows Server 2008")) {
			currentSystem = WINDOWS_SYSTEM;
		} else if (currentSystemName.equalsIgnoreCase("linux")) {
			currentSystem = LINUX_SYSTEM;
		} else if (currentSystemName.equalsIgnoreCase("mac os x")) {
			currentSystem = MAC_OS_X_SYSTEM;
		} else if (currentSystemName.equalsIgnoreCase("sunos")) {
			currentSystem = SUN_OS_SYSTEM;
		} else {
			System.out.println("Unitex cannot run under " + currentSystemName);
			System.exit(1);
		}
		System.out.println("Unitex is running under " + currentSystemName);
	}

	/**
	 * 
	 * @return the current system constant
	 */
	public static int getCurrentSystem() {
		return currentSystem;
	}

	/**
	 * 
	 * @return the current system name
	 */
	public static String getCurrentSystemName() {
		return currentSystemName;
	}

	/**
	 * 
	 * @return the application directory
	 */
	public static File getApplicationDir() {
		if (applicationDir == null) {
			System.err.println("ERROR");
		}
		return applicationDir;
	}

	/**
	 * Sets the application directory
	 * 
	 * @param s
	 *            directory's path
	 */
	public static void setApplicationDir(File s) {
		applicationDir = s;
		setUnitexDir(applicationDir.getParentFile());
	}

	/**
	 * 
	 * @return the Unitex directory
	 */
	public static File getUnitexDir() {
		if (unitexDir == null) {
			System.err.println("ERROR");
		}
		return unitexDir;
	}

	/**
	 * Sets the system directory
	 * 
	 * @param s
	 *            directory's path
	 */
	public static void setUnitexDir(File s) {
		unitexDir = s;
	}

	/**
	 * 
	 * @return the user directory
	 */
	public static File getUserDir() {
		if (userDir == null) {
			System.err.println("ERROR");
		}
		return userDir;
	}

	/**
	 * Sets the user directory
	 * 
	 * @param s
	 *            directory's path
	 */
	public static void setUserDir(File s) {
		userDir = s;
		if (!userDir.exists()) {
			// if the directory does not exists, we create it
			if (!userDir.mkdir()) {
				System.err.println("Fatal error: cannot create directory "
						+ userDir);
				System.exit(1);
			}
		}
	}

	/**
	 * 
	 * @return the current language
	 */
	public static String getCurrentLanguage() {
		if (currentLanguage == null) {
			System.err.println("ERROR");
		}
		return currentLanguage;
	}

	/**
	 * Sets the current language. All directories that depend of this one are
	 * updated. Preferences all also updated
	 * 
	 * @param s
	 *            language's name
	 */
	public static void setCurrentLanguage(String s) {
		currentLanguage = s;
		setUnitexCurrentLanguageDir(new File(getUnitexDir(), currentLanguage));
		setUserCurrentLanguageDir(new File(getUserDir(), currentLanguage));
		setCurrentCorpusDir(new File(getUserCurrentLanguageDir(), "Corpus"));
		setCurrentGraphDir(new File(getUserCurrentLanguageDir(), "Graphs"));
		setCurrentElagDir(new File(getUserCurrentLanguageDir(), "Elag"));
		setAlphabet(new File(getUserCurrentLanguageDir(), "Alphabet.txt"));
		setDefaultPreprocessingGraphs();
		updateOpenSaveDialogBoxes();
		Preferences.reset();
	}

	
	/**
	 * @return the current language to be displayed in the title bar
	 */
	public static String getCurrentLanguageForTitleBar() {
		if (currentLanguage == null) {
			System.err.println("ERROR");
		}
		/* The following is a private joke */
		if (!currentLanguage.equals("Greek (Ancient)") 
				|| (!getUserName().equalsIgnoreCase("bastien") && !getUserName().equalsIgnoreCase("nastasia"))) {
			return currentLanguage;
		}
		switch (new Random().nextInt(12)) {
			case 0: return "Greek (Ancient)";
			case 1: return "grec momifi�";
			case 2: return "grec putr�fi�";
			case 3: return "grec embaum�";
			case 4: return "grec faisand�";
			case 5: return "grec mort";
			case 6: return "vieux grec tout rabougri";
			case 7: return "grec qui sent la naphtaline";
			case 8: return "grec p�rim�";
			case 9: return "grec cadav�rique";
			case 10: return "grec de morgue";
			case 11: return "grec tellement vieux qu'on fr�le la profanation";
		}
		return null;
	}
	
	
	/**
	 * 
	 * @return system's current language directory
	 */
	public static File getUnitexCurrentLanguageDir() {
		if (unitexCurrentLanguageDir == null) {
			System.err.println("ERROR");
		}
		return unitexCurrentLanguageDir;
	}

	/**
	 * Sets the system's current language directory
	 * 
	 * @param s
	 *            directory's path
	 */
	public static void setUnitexCurrentLanguageDir(File s) {
		unitexCurrentLanguageDir = s;
	}

	/**
	 * 
	 * @return the users' current language directory
	 */
	public static File getUserCurrentLanguageDir() {
		if (userCurrentLanguageDir == null) {
			System.err.println("ERROR");
		}
		return userCurrentLanguageDir;
	}

	/**
	 * Sets the user's current language directory. If some sub-directories are
	 * missing, they are copied from the system's current language directory
	 * with all their files, excepting the dictionaries (".bin" and ".inf"
	 * files).
	 * 
	 * @param s
	 *            directory's path
	 */
	public static void setUserCurrentLanguageDir(File s) {
		userCurrentLanguageDir = s;
		// now, we verify if the directory exists
		if (!userCurrentLanguageDir.exists()) {
			// if the path does not exists
			if (!userCurrentLanguageDir.mkdir()) {
				System.err.println("ERROR: cannot create directory "
						+ s.getAbsolutePath());
				System.exit(1);
			}
			copyFileByName(new File(getUnitexCurrentLanguageDir(), "*"),
					getUserCurrentLanguageDir());
		}
		if (deprecatedConfigFile(new File(s,"Config"))) {
			copyFileByName(new File(getUnitexCurrentLanguageDir(), "Config"),
					getUserCurrentLanguageDir());
		}
		// if any of the sub-directories does not exist, we create it
		File f = new File(userCurrentLanguageDir, "Corpus");
		if (!f.exists()) {
			f.mkdir();
			copyFileByName(new File(new File(getUnitexCurrentLanguageDir(),
					"Corpus"), "*"), f);
		}
		f = new File(userCurrentLanguageDir, "Elag");
		if (!f.exists()) {
			copyDirRec(new File(getUnitexCurrentLanguageDir(), "Elag"), f);
		}

		f = new File(userCurrentLanguageDir, "Inflection");
		if (!f.exists()) {
			copyDirRec(new File(getUnitexCurrentLanguageDir(), "Inflection"), f);
		}
		f = new File(userCurrentLanguageDir, "Dela");
		if (!f.exists()) {
			f.mkdir();
		}
		f = new File(userCurrentLanguageDir, "Graphs");
		if (!f.exists()) {
			copyDirRec(new File(getUnitexCurrentLanguageDir(), "Graphs"), f);
		}
		if(Config.isAgglutinativeLanguage()){
			f = new File(userCurrentLanguageDir, "MorphemVariants");
			f.mkdir();
			copyFileByName(new File(new File(getUnitexCurrentLanguageDir(),
					"MorphemVariants"), "*"), f);
			
			f = new File(userCurrentLanguageDir, "Variation");
			f.mkdir();
			copyFileByName(new File(new File(getUnitexCurrentLanguageDir(),
					"Variation"), "*"), f);
			f = new File(userCurrentLanguageDir, "Derivation");
			f.mkdir();
			copyFileByName(new File(new File(getUnitexCurrentLanguageDir(),
					"Derivation"), "*"), f);
			f = new File(userCurrentLanguageDir, "Suffixes");
			if (!f.exists()) {
				copyDirRec(new File(getUnitexCurrentLanguageDir(), "Suffixes"), f);
			}
			f = new File(userCurrentLanguageDir, "Decoding");
			if (!f.exists()) {
				copyDirRec(new File(getUnitexCurrentLanguageDir(), "Decoding"), f);
			}

		}

	}

	/**
	 * @param file
	 * @return true if the configuration file does start with '#' 
	 */
	private static boolean deprecatedConfigFile(File file) {
		if (file==null) {return false;}
		try {
			FileInputStream stream=new FileInputStream(file);
			if (stream.available()==0) {
				stream.close();
				return false;
			}
            int c=stream.read();
            stream.close();
            return (c!='#');
			
		} catch (FileNotFoundException e) {
			return false;
		} catch (IOException e1) {
			return false;
		}
	}

	/**
	 * 
	 * @return user's current corpus directory
	 */
	public static File getCurrentCorpusDir() {
		if (currentCorpusDir == null) {
			System.out.println("ERROR");
		}
		return currentCorpusDir;
	}

	/**
	 * Sets the user's current corpus directory
	 * 
	 * @param s
	 *            directory's path
	 */
	public static void setCurrentCorpusDir(File s) {
		currentCorpusDir = s;
	}

	/**
	 * 
	 * @return user's current graph directory
	 */
	public static File getCurrentGraphDir() {
		if (currentGraphDir == null) {
			System.out.println("ERROR");
		}
		return currentGraphDir;
	}

	/**
	 * Sets the user's current graph directory
	 * 
	 * @param s
	 *            directory's path
	 */
	public static void setCurrentGraphDir(File s) {
		currentGraphDir = s;
	}

	/**
	 * 
	 * @return user's current ELAG directory
	 */
	public static File getCurrentElagDir() {
		if (currentElagDir == null) {
			System.out.println("ERROR");
		}
		return currentElagDir;
	}

	/**
	 * Sets the user's current ELAG directory
	 * 
	 * @param s
	 *            directory's path
	 */
	public static void setCurrentElagDir(File s) {
		currentElagDir = s;
	}

	/**
	 * 
	 * @return user's current alphabet file
	 */
	public static File getAlphabet() {
		if (alphabet == null) {
			System.out.println("ERROR");
		}
		return alphabet;
	}

	/**
	 * Sets user's current alphabet file
	 * 
	 * @param s
	 *            file's path
	 */
	public static void setAlphabet(File s) {
		alphabet = s;
	}

	/**
	 * 
	 * @return user's name
	 */
	public static String getUserName() {
		return userName;
	}

	/**
	 * Asks for the user to select his private directory. IMPORTANT: this method
	 * must be called only when Unitex is running under Windows.
	 *  
	 */
	public static void chooseNewUserDir() {
		String message = "Welcome " + getUserName() + "!\n\n";
		message = message
				+ "To use Unitex, you must choose a private \ndirectory to store your data ";
		message = message + "(that you\ncan change later if you want).";
		message = message + "\n\nClick on OK to choose your directory.";
		JOptionPane.showMessageDialog(null, message, "Welcome",
				JOptionPane.PLAIN_MESSAGE);
		JFileChooser f = new JFileChooser();
		f.setDialogTitle("Choose your private directory");
		f.setDialogType(JFileChooser.OPEN_DIALOG);
		f.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		while (f.showOpenDialog(null) != JFileChooser.APPROVE_OPTION || /*
																		 * areIdenticalDirectories(f.getSelectedFile()
																		 * .getAbsolutePath(),
																		 * getUnitexDir())
																		 */
		f.getSelectedFile().equals(getUnitexDir())) {
			if (f.showOpenDialog(null) != JFileChooser.APPROVE_OPTION) {
				message = "You must choose a private directory.\n\n";
				message = message + "Click on OK to select one or on\n";
				message = message + "Cancel to exit.";
			} else {
				message = "You cannot choose the Unitex directory as your private one";
			}
			Object[] options = {"OK", "Cancel"};
			int n = JOptionPane.showOptionDialog(null, message, "Error",
					JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE, null,
					options, options[0]);
			if (n == 1)
				System.exit(0);
		}
		setUserDir(f.getSelectedFile());
	}

	/**
	 * Asks for the user to change his private directory. IMPORTANT: this method
	 * must be called only when Unitex is running under Windows.
	 */
	public static void changeUserDir() {
		JFileChooser f = new JFileChooser();
		f.setDialogTitle("Choose your private directory");
		f.setDialogType(JFileChooser.OPEN_DIALOG);
		f.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		if (f.showOpenDialog(null) != JFileChooser.APPROVE_OPTION)
			return;
		if (f.getSelectedFile().equals(getUnitexDir())) {
			JOptionPane
					.showMessageDialog(
							null,
							"You cannot choose the Unitex directory as your private one",
							"Error", JOptionPane.ERROR_MESSAGE);
			return;
		}
		setUserDir(f.getSelectedFile());
	}



	
	/**
	 * 
	 * @return current corpus
	 */
	public static File getCurrentSnt() {
		return currentSnt;
	}

	/**
	 * Sets the current corpus
	 * 
	 * @param s
	 *            name of the corpus file
	 */
	public static void setCurrentSnt(File s) {
		currentSnt = s;
		setCurrentSntDir(s);
	}

	/**
	 * 
	 * @return current corpus
	 */
	public static File getCurrentSntDir() {
		return currentSntDir;
	}

	/**
	 * Sets the current corpus
	 * 
	 * @param s
	 *            name of the corpus file
	 */
	public static void setCurrentSntDir(File s) {
		String path;
		path = Util.getFileNameWithoutExtension(s.getAbsolutePath());
		currentSntDir = new File(path + "_snt");
	}

	/**
	 * 
	 * @return current sentence delimitation graph
	 */
	public static File getCurrentSentenceGraph() {
		return currentSentenceGraph;
	}

	/**
	 * Sets current sentence delimitation graph
	 * 
	 * @param s
	 *            graph's name
	 */
	public static void setCurrentSentenceGraph(File s) {
		currentSentenceGraph = s;
	}

	/**
	 * 
	 * @return current replace graph
	 */
	public static File getCurrentReplaceGraph() {
		return currentReplaceGraph;
	}

	/**
	 * Sets current replace graph
	 * 
	 * @param s
	 *            graph's name
	 */
	public static void setCurrentReplaceGraph(File s) {
		currentReplaceGraph = s;
	}

	/**
	 * Sets sentence delimitation and replace graphs
	 *  
	 */
	public static void setDefaultPreprocessingGraphs() {
		File sentence = new File(getUserCurrentLanguageDir(), "Graphs");
		sentence = new File(sentence, "Preprocessing");
		File replace = new File(sentence, "Replace");
		sentence = new File(sentence, "Sentence");
		if (getCurrentLanguage().equals("Thai")) {
			// this is an exception because we do not have anymore
			// the .grf file
			sentence = new File(sentence, "Sentence.fst2");
		}
		else {
			sentence = new File(sentence, "Sentence.grf");
		}
		replace = new File(replace, "Replace.grf");
		setCurrentSentenceGraph(sentence);
		setCurrentReplaceGraph(replace);
	}

	/**
	 * Copies files. The source is specified by a file name that can contain *
	 * and ? jokers.
	 * 
	 * @param src
	 *            source
	 * @param dest
	 *            destination
	 */
	public static void copyFileByName(File src, File dest) {
		File path_src = src.getParentFile();
		String expression = src.getName();
		if (dest.isDirectory()) {
			File files_list[] = path_src
					.listFiles(new RegFileFilter(expression));
			if (files_list != null) {
				for (int i = 0; i < files_list.length; i++) {
					File F = files_list[i];
					if (!F.isDirectory()) {
						copyFile(F, new File(dest, F.getName()));
					}
				}
			}
		} else
			copyFile(src, dest);
	}

	/**
	 * Copies a directory recursively.
	 * 
	 * @param src
	 *            source directory
	 * @param dest
	 *            destination directory
	 */

	public static void copyDirRec(File src, File dest) {

		if (!src.isDirectory()) {
			return;
		}
		if (!dest.exists()) {
			dest.mkdirs();
		}
		File files_list[] = src.listFiles();
		if (files_list == null) {
			return;
		}
		for (int i = 0; i < files_list.length; i++) {
			File f = files_list[i];
			if (f.isDirectory()) {
				copyDirRec(f, new File(dest, f.getName()));
			} else if (f.isFile()) {
				copyFile(f, new File(dest, f.getName()));
			}
		}
	}

	/**
	 * Deletes files. The source is specified by a file name that can contain *
	 * and ? jokers.
	 * 
	 * @param src
	 *            source
	 */
	public static void deleteFileByName(File src) {
		File path_src = src.getParentFile();
		String expression = src.getName();
		File files_list[] = path_src.listFiles(new RegFileFilter(
				expression));
		if (files_list != null) {
			for (int i = 0; i < files_list.length; i++) {
				files_list[i].delete();
			}
		}
	}

	/**
	 * Deletes files. The source is specified by a file name that can contains *
	 * and ? jokers. This method differs from deleteFileByName because it cannot
	 * delete directories.
	 * 
	 * @param src
	 *            source
	 */
	public static void removeFile(File src) {
		File path_src = src.getParentFile();
		String expression = src.getName();
		File files_list[] = path_src.listFiles(new RegFileFilter(
				expression));
		for (int i = 0; i < files_list.length; i++) {
			File F;
			if (!(F = files_list[i]).isDirectory()) {
				F.delete();
			}
		}
	}

	static class RegFileFilter implements FilenameFilter {

		public String expression;

		RegFileFilter(String exp) {
			expression = exp.replaceAll("\u002C", "\\.");
			expression = expression.replaceAll("\\*", ".*");
			expression = expression.replaceAll("\\?", ".");
		}

		public boolean accept(File dir, String f) {
			return Pattern.matches(expression, f);
		}
	}

	/**
	 * Copy one file.
	 * 
	 * @param src
	 *            source file
	 * @param dest
	 *            destination file
	 */
	public static void copyFile(File src, File dest) {
		try {
			FileInputStream fis = new FileInputStream(src);
			FileOutputStream fos = new FileOutputStream(dest);
			copyStream(fis, fos);
			fis.close();
			fos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void copyStream(InputStream fis, OutputStream fos) {
		try {
			byte[] buf = new byte[2048];
			int i = 0;
			while ((i = fis.read(buf)) != -1) {
				fos.write(buf, 0, i);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Sets current DELA
	 * 
	 * @param s
	 *            dictionary name
	 */
	public static void setCurrentDELA(File s) {
		currentDELA = s;
	}

	/**
	 * 
	 * @return current DELA's name
	 */
	public static File getCurrentDELA() {
		return currentDELA;
	}

	/**
	 * 
	 * @return current font used to display texts
	 */
	public static Font getCurrentTextFont() {
		return Preferences.getCloneOfPreferences().textFont;
	}
	
	
	
	
	public static boolean isCharByCharLanguage() {
		return Preferences.pref.charByChar;
	}

	public static boolean isRightToLeftLanguage() {
		return Preferences.pref.rightToLeft;
	}

	public static boolean isKorean() {
		return Config.getCurrentLanguage().equals("Korean");
	}
	
	public static boolean isAgglutinativeLanguage() {
		String s = Config.getCurrentLanguage();
		return s.equals("Hungarian") || s.equals("Korean")
				|| s.equals("Malagasy");
	}

}
/*
 * Unitex
 *
 * Copyright (C) 2001-2009 Universit� Paris-Est Marne-la-Vall�e <unitex@univ-mlv.fr>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
 *
 */

package ndosownww.unitex.changes;

import java.awt.*;
import java.io.*;
import java.util.*;
import java.awt.font.TextLayout;

import javax.swing.*;

import ndosownww.grafy.exceptions.NoClosingQuoteException;

import toposlaw.graphs.tools.Etiquettes;
import toposlaw.graphs.tools.unitex.PathHighlight;


/**
 * This class describes a box of a graph or a sentence graph.
 * 
 * @author S�bastien Paumier
 *  
 */
public abstract class GenericGraphBox {

	/**
	 * Box X coordinate
	 */
	public int x;

	/**
	 * Box Y coordinate
	 */
	public int Y;

	/**
	 * Box type (initial, final or normal)
	 */
	public int type;

	public final static int INITIAL = 0;
	public final static int FINAL = 1;
	public final static int NORMAL = 2;

	/**
	 * Indicates if the box contains a start or end of a variable
	 */
	public boolean variable;

	/**
	 * Indicates if the box contains a context limit
	 */
	public boolean contextMark;

	/**
	 * Indicates if the box contains a morphological mode tag 
	 */
	public boolean morphologicalModeMark;

	/**
	 * Indicates if the box is currently selected
	 */
	protected boolean selected;

	/**
	 * Indicates if the box is in comment (no input/output transition)
	 */
	public boolean comment;

	/**
	 * Indicates if there is at least one transition that goes out this box
	 */
	public boolean hasOutgoingTransitions;

	/**
	 * Indicates if there is at least one transition that comes in this box
	 */
	public int hasIncomingTransitions;

	/**
	 * Indicates if the box is being dragged alone
	 */
	protected boolean singleDragging;

	/**
	 * X coordinate of the box input point
	 */
	public int X_in;

	/**
	 * Y coordinate of the box input point
	 */
	public int Y_in;

	/**
	 * X coordinate of the box output point
	 */
	public int X_out;

	/**
	 * Y coordinate of the box output point
	 */
	public int Y_out;

	/**
	 * Text contained in the box, as it can be viewed when the box is edited
	 */
	
	// previously protected
	public String content;

	/**
	 * Tokenized box lines
	 */
	public ArrayList<String> lines;

	/**
	 * greyed[i]==true if the line i is a subgraph call
	 */
	public ArrayList<Boolean> greyed;

	/**
	 * Transduction text, if exists
	 */
	public String transduction;

	/**
	 * Number of visible lines in the box: 0 if the box contains only the
	 * espilon symbol, the number of lines otherwise
	 */
	public int n_lines; // number of visible lines in the box

	/**
	 * X coordinate of the upper left corner of the box frame
	 */
	public int X1;

	/**
	 * Y coordinate of the upper left corner of the box frame
	 */
	public int Y1;

	/**
	 * Width of the box frame
	 */
	public int Width;

	/**
	 * Height of the box frame
	 */
	public int Height;

	/**
	 * Height of a box line
	 */
	public int h_ligne;

	/**
	 * Heigth of the bottom of letters like j, q or g
	 */
	protected int descent;

	/**
	 * <code>GenericGraphicalZone</code> object that contains the box
	 */
	public GenericGraphicalZone parentGraphicalZone;

	/**
	 * Numbers of boxes that can be reached with transitions going out this box
	 */
	protected ArrayList<GenericGraphBox> transitions;

	public static Font variableFont = new Font("Times New Roman", Font.BOLD, 30);

	public Graphics2D context;

	/**
	 * Number of the box
	 */
	public int identificationNumber; // number used to numerote the state

	/**
	 * Constructs a new box
	 * 
	 * @param x
	 *            X coordinate of the input point of the box
	 * @param y
	 *            Y coordinate of the input point of the box
	 * @param type
	 *            indicates if the box is initial, final or normal
	 * @param p
	 *            component on which the box will be drawn
	 */
	public GenericGraphBox(int x, int y, int type, GenericGraphicalZone p) {
		this.x = x;
		Y = y;
		parentGraphicalZone = p;
		this.type = type;
		content = "<E>";
		transduction = "";
		variable = false;
		n_lines = 0;
		h_ligne = 15;
		lines = new ArrayList<String>();
		greyed = new ArrayList<Boolean>();
		transitions = new ArrayList<GenericGraphBox>();
		Width = 15;
		Height = 20;
		if (type == FINAL) {
			X_in = x;
			Y_in = Y;
			X1 = x;
			Y1 = Y - 10;
			Y_out = Y_in;
			X_out = X_in + 25;
		} else {
			X1 = x;
			Y1 = Y;
			X_in = x;
			Y_in = Y /*-Height/2*/;
			X_out = x + Width + 5;
			Y_out = Y_in;
		}
		selected = false;
		singleDragging = false;
		comment = true;
		hasOutgoingTransitions = false;
		hasIncomingTransitions = 0;
		identificationNumber = -1;
	}

	/**
	 * Tests if the click point was in a sub-graph call area. In that case, it
	 * returns the sub-graph's name
	 * 
	 * @param y
	 *            Y coordinate of the click point
	 * @return the sub-graph's name, or the empty string if no graph was pointed
	 *         out by the click
	 */
	public File getGraphClicked(int y) {
		int n;
		String s;
		Boolean b;
		n = (y - Y1 - 4) / (h_ligne);
		b = greyed.get(n);
		if (b.booleanValue()) {
			s = lines.get(n);
			if (!s.endsWith(".grf")) {
				s = s + ".grf";
			}
			/* replace ':' by '/' resp. '\\' */
			if (s.startsWith(":")) {
				// if the graph is located in the package repository
				s  = s.replace(':', File.separatorChar);
				return new File(Preferences.pref.packagePath,s.substring(1));
			}
			// otherwise
		    File f = new File(s);
			if (Config.getCurrentSystem()==Config.WINDOWS_SYSTEM && 
				f.isAbsolute()) {
				// first we test if we have an absolute windows pathname,
				// in order to avoid wrong transformations like:
				//
				// C:\\foo\foo.grf  =>  C\\\foo\foo.grf 
				//
				return f;
			}
			s=s.replace(':',File.separatorChar);
			if (!f.isAbsolute()) {
				System.out.println();
				File currentGraph=((GraphFrame) parentGraphicalZone.parentFrame).getGraph();
				if (currentGraph==null) {
					// if we try to open a subgraph inside a newly created graph with no name 
					f=null;
					JOptionPane
					.showMessageDialog(null, "Cannot resolve relative graph path:\n\n"
							+s+"\n\nbecause the location of the current graph is\n" +
									"not defined (the graph has never been saved).", "Error",
							JOptionPane.ERROR_MESSAGE);
				} else {
					f = new File(currentGraph.getParentFile(), s);
				}
			}
			return f;
		}
		return null;
	}

	/**
	 * Adds a transition to a box. If there is allready a transition to this
	 * box, it is removed.
	 * 
	 * @param g
	 *            the destination box
	 */
	public void addTransitionTo(GenericGraphBox g) {
		int i;
		if (this.type == FINAL) {
			// if it is the final, we don't allow parent.pref.output transitions
			return;
		}
		i = transitions.indexOf(g);
		if (i == -1) {
			// if the transition to g does not exist, we create it
			transitions.add(g);
			g.hasIncomingTransitions++;
		} else {
			// else, we remove it
			transitions.remove(i);
			g.hasIncomingTransitions--;
		}
		if (transitions.isEmpty())
			hasOutgoingTransitions = false;
		else
			hasOutgoingTransitions = true;
		comment = (!hasOutgoingTransitions && hasIncomingTransitions == 0);
		g.comment = (!g.hasOutgoingTransitions && g.hasIncomingTransitions == 0);
	}

	/**
	 * Adds a transition to a box. If there is allready a transition to this
	 * box, it is not removed.
	 * 
	 * @param g
	 *            the destination box
	 */

	public void onlyAddTransitionTo(GenericGraphBox g) {
		int i;
		if (this.type == FINAL) {
			// if it is the final, we don't allow parent.pref.output transitions
			return;
		}
		i = transitions.indexOf(g);
		if (i == -1) {
			// if the transition to g does not exist, we create it
			transitions.add(g);
			g.hasIncomingTransitions++;
		}
		if (transitions.isEmpty())
			hasOutgoingTransitions = false;
		else
			hasOutgoingTransitions = true;
		comment = (!hasOutgoingTransitions && hasIncomingTransitions == 0);
		g.comment = (!g.hasOutgoingTransitions && g.hasIncomingTransitions == 0);
	}

	/**
	 * removes a box transition
	 * 
	 * @param g
	 *            the transition's destination box
	 */
	public void removeTransitionTo(GenericGraphBox g) {

		int i = transitions.indexOf(g);
		if (i != -1) {
			transitions.remove(i);
			g.hasIncomingTransitions--;
		}
		if (transitions.isEmpty())
			hasOutgoingTransitions = false;
		else
			hasOutgoingTransitions = true;

		comment = (!hasOutgoingTransitions && hasIncomingTransitions == 0);
		g.comment = (!g.hasOutgoingTransitions && g.hasIncomingTransitions == 0);
	}

	/**
	 * Translates the box
	 * 
	 * @param dx
	 *            length of X shift in pixels
	 * @param dy
	 *            length of Y shift in pixels
	 */
	public void translate(int dx, int dy) {
		x = x + dx;
		Y = Y + dy;
		X_in = X_in + dx;
		Y_in = Y_in + dy;
		X_out = X_out + dx;
		Y_out = Y_out + dy;
		X1 = X1 + dx;
		Y1 = Y1 + dy;
	}

	/**
	 * Tests if the box is selected by a rectangle
	 * 
	 * @param Xr
	 *            X coordinate of the upper left corner of the rectangle
	 * @param Yr
	 *            Y coordinate of the upper left corner of the rectangle
	 * @param Wr
	 *            width of the rectangle
	 * @param Hr
	 *            height of the rectangle
	 * @return <code>true</code> if the intersection between the box and the
	 *         rectangle is not empty, <code>false</code> otherwise
	 */
	public boolean isSelectedByRectangle(int Xr, int Yr, int Wr, int Hr) {
		return !((X1 > (Xr + Wr)) || ((X1 + Width) < Xr) || (Y1 > (Yr + Hr)) || ((Y1 + Height) < Yr));
	}

	/**
	 * Draws a transition to a box
	 * 
	 * @param g
	 *            the graphical context
	 * @param dest
	 *            the destination box
	 */
	public void drawTransition(Graphics2D g, GenericGraphBox dest) {
	    g.setColor(parentGraphicalZone.pref.foregroundColor);
		if (!parentGraphicalZone.pref.rightToLeft) {
			if (dest.X_in > this.X_out) {
				// easiest case: drawing a line
				GraphicalToolBox.drawLine(g, this.X_out, this.Y_out, dest.X_in, dest.Y_in);
				return;
			}
			if (this.equals(dest)) {
				// if the box is relied to itself
				int diametre1 = 10 + Height / 2;
				GraphicalToolBox.drawArc(g, X_out - diametre1 / 2, Y_out - diametre1, diametre1,
						diametre1, 90, -180);
				GraphicalToolBox.drawArc(g, dest.X_in - diametre1 / 2, dest.Y_in - diametre1,
						diametre1, diametre1, 90, 180);
				GraphicalToolBox.drawLine(g, X_in, Y_in - diametre1, X_out, Y_out - diametre1);
				return;
			}
			if ((Y1 < (dest.Y1 + dest.Height)) && ((Y1 + Height) > dest.Y1)) {
				int diametre1 = 10 + Height / 2;
				GraphicalToolBox.drawArc(g, X_out - diametre1 / 2, Y_out - diametre1, diametre1,
						diametre1, 90, -180);
				int diametre2 = 10 + dest.Height / 2;
				GraphicalToolBox.drawArc(g, dest.X_in - diametre2 / 2, dest.Y_in - diametre2,
						diametre2, diametre2, 90, 180);
				int Xpoint1, Ypoint1, Xpoint2, Ypoint2;
				Xpoint1 = dest.X_in;
				Ypoint1 = dest.Y_in - diametre2;
				Xpoint2 = X_out;
				Ypoint2 = Y_out - diametre1;
				int Xmilieu, Ymilieu, largeurLimite;
				Xmilieu = (Xpoint2 + Xpoint1) / 2;
				Ymilieu = (Ypoint2 + Ypoint1) / 2;
				largeurLimite = diametre1 + diametre2;
				GraphicalToolBox.drawCurve(g, Xpoint1, Ypoint1, Xpoint1 + largeurLimite,
						Ypoint1, Xmilieu, Ymilieu);
				GraphicalToolBox.drawCurve(g, Xpoint2, Ypoint2, Xpoint2 - largeurLimite,
						Ypoint2, Xmilieu, Ymilieu);
				return;
			}
			if (Y1 < (dest.Y1 + dest.Height)) {
				int diametre1 = 10 + Height / 2;
				GraphicalToolBox.drawArc(g, X_out - diametre1 / 2, Y_out, diametre1, diametre1,
						0, 90);
				int diametre2 = 10 + dest.Height / 2;
				GraphicalToolBox.drawArc(g, dest.X_in - diametre2 / 2, dest.Y_in - diametre2,
						diametre2, diametre2, 180, 90);
				int Xpoint1, Ypoint1, Xpoint2, Ypoint2;
				Xpoint1 = dest.X_in - diametre2 / 2;
				Ypoint1 = dest.Y_in - diametre2 / 2;
				Xpoint2 = X_out + 1 + diametre1 / 2;
				Ypoint2 = Y_out + 1 + diametre1 / 2;
				int hauteurLimite = diametre1 + diametre2 - 20;
				int Xmilieu, Ymilieu;
				Xmilieu = (Xpoint2 + Xpoint1) / 2;
				Ymilieu = (Ypoint2 + Ypoint1) / 2;
				GraphicalToolBox.drawCurve(g, Xpoint1, Ypoint1, Xpoint1,
						Ypoint1 - hauteurLimite, Xmilieu, Ymilieu);
				GraphicalToolBox.drawCurve(g, Xpoint2, Ypoint2, Xpoint2,
						Ypoint2 + hauteurLimite, Xmilieu, Ymilieu);
				return;
			}
			int diametre1 = 10 + Height / 2;
			GraphicalToolBox.drawArc(g, X_out - diametre1 / 2, Y_out - diametre1, diametre1,
					diametre1, 270, 90);
			int diametre2 = 10 + dest.Height / 2;
			GraphicalToolBox.drawArc(g, dest.X_in - diametre2 / 2, dest.Y_in, diametre2,
					diametre2, 90, 90);
			int Xpoint1, Ypoint1, Xpoint2, Ypoint2;
			Xpoint1 = dest.X_in - diametre2 / 2;
			Ypoint1 = dest.Y_in + diametre2 / 2;
			Xpoint2 = X_out + 1 + diametre1 / 2;
			Ypoint2 = Y_out + 1 - diametre1 / 2;
			int hauteurLimite = diametre1 + diametre2 - 20;
			int Xmilieu, Ymilieu;
			Xmilieu = (Xpoint2 + Xpoint1) / 2;
			Ymilieu = (Ypoint2 + Ypoint1) / 2;
			GraphicalToolBox.drawCurve(g, Xpoint1, Ypoint1, Xpoint1, Ypoint1 + hauteurLimite,
					Xmilieu, Ymilieu);
			GraphicalToolBox.drawCurve(g, Xpoint2, Ypoint2, Xpoint2, Ypoint2 - hauteurLimite,
					Xmilieu, Ymilieu);
			return;
		}
		// end of the left to right mode
		if (dest.X_out - 5 < this.X_in - 5) {
			// easiest case: drawing a line
			GraphicalToolBox.drawLine(g, this.X_in - 5, this.Y_in, dest.X_out - 5, dest.Y_out);
			return;
		}
		if (this.equals(dest)) {
			// if the box is relied to itself
			int diametre1 = 10 + Height / 2;
			GraphicalToolBox.drawArc(g, X_in - 5 - diametre1 / 2, Y_in - diametre1, diametre1,
					diametre1, 90, 180);
			GraphicalToolBox.drawArc(g, dest.X_out - 5 - diametre1 / 2, dest.Y_out - diametre1,
					diametre1, diametre1, 90, -180);
			GraphicalToolBox.drawLine(g,X_out - 5, Y_out - diametre1, X_in - 5, Y_in
							- diametre1);
			return;
		}
		if ((Y1 < (dest.Y1 + dest.Height)) && ((Y1 + Height) > dest.Y1)) {
			int diametre1 = 10 + Height / 2;
			GraphicalToolBox.drawArc(g, X_in - 5 - diametre1 / 2, Y_in - diametre1, diametre1,
					diametre1, 90, 180);
			int diametre2 = 10 + dest.Height / 2;
			GraphicalToolBox.drawArc(g, dest.X_out - 5 - diametre2 / 2, dest.Y_out - diametre2,
					diametre2, diametre2, 90, -180);
			int Xpoint1, Ypoint1, Xpoint2, Ypoint2;
			Xpoint2 = dest.X_out - 5;
			Ypoint2 = dest.Y_out - diametre2;
			Xpoint1 = X_in - 5;
			Ypoint1 = Y_in - diametre1;
			int Xmilieu, Ymilieu, largeurLimite;
			Xmilieu = (Xpoint2 + Xpoint1) / 2;
			Ymilieu = (Ypoint2 + Ypoint1) / 2;
			largeurLimite = diametre1 + diametre2;
			GraphicalToolBox.drawCurve(g, Xpoint1, Ypoint1, Xpoint1 + largeurLimite, Ypoint1,
					Xmilieu, Ymilieu);
			GraphicalToolBox.drawCurve(g, Xpoint2, Ypoint2, Xpoint2 - largeurLimite, Ypoint2,
					Xmilieu, Ymilieu);
			return;
		}
		if (Y1 < (dest.Y1 + dest.Height)) {
			int diametre1 = 10 + Height / 2;
			GraphicalToolBox.drawArc(g, X_in - 5 - diametre1 / 2, Y_in, diametre1, diametre1,
					90, 90);
			int diametre2 = 10 + dest.Height / 2;
			GraphicalToolBox.drawArc(g, dest.X_out - 5 - diametre2 / 2, dest.Y_out - diametre2,
					diametre2, diametre2, 270, 90);
			int Xpoint1, Ypoint1, Xpoint2, Ypoint2;
			Xpoint1 = dest.X_out + 1 - 5 + diametre2 / 2;
			Ypoint1 = dest.Y_out - diametre2 / 2;
			Xpoint2 = X_in - 5 - diametre1 / 2;
			Ypoint2 = Y_in + diametre1 / 2;
			int hauteurLimite = diametre1 + diametre2 - 20;
			int Xmilieu, Ymilieu;
			Xmilieu = (Xpoint2 + Xpoint1) / 2;
			Ymilieu = (Ypoint2 + Ypoint1) / 2;
			GraphicalToolBox.drawCurve(g, Xpoint1, Ypoint1, Xpoint1, Ypoint1 - hauteurLimite,
					Xmilieu, Ymilieu);
			GraphicalToolBox.drawCurve(g, Xpoint2, Ypoint2, Xpoint2, Ypoint2 + hauteurLimite,
					Xmilieu, Ymilieu);
			return;
		}
		int diametre1 = 10 + Height / 2;
		GraphicalToolBox.drawArc(g, X_in - 5 - diametre1 / 2, Y_in - diametre1, diametre1,
				diametre1, 270, -90);
		int diametre2 = 10 + dest.Height / 2;
		GraphicalToolBox.drawArc(g, dest.X_out - 5 - diametre2 / 2, dest.Y_out, diametre2,
				diametre2, 90, -90);
		int Xpoint1, Ypoint1, Xpoint2, Ypoint2;
		Xpoint1 = dest.X_out - 5 + diametre2 / 2;
		Ypoint1 = dest.Y_out + 1 + diametre2 / 2;
		Xpoint2 = X_in - 5 - diametre1 / 2;
		Ypoint2 = Y_in - diametre1 / 2;
		int hauteurLimite = diametre1 + diametre2 - 20;
		int Xmilieu, Ymilieu;
		Xmilieu = (Xpoint2 + Xpoint1) / 2;
		Ymilieu = (Ypoint2 + Ypoint1) / 2;
		GraphicalToolBox.drawCurve(g, Xpoint1, Ypoint1, Xpoint1, Ypoint1 + hauteurLimite,
				Xmilieu, Ymilieu);
		GraphicalToolBox.drawCurve(g, Xpoint2, Ypoint2, Xpoint2, Ypoint2 - hauteurLimite,
				Xmilieu, Ymilieu);
	}

	/**
	 * Draws all transitions that go out of the box
	 * 
	 * @param gr
	 *            the graphical context
	 */
	public void drawTransitions(Graphics2D gr) {
		updateWithContext(gr);
		int i, L;
		GenericGraphBox g;
		if (transitions.isEmpty())
			return;
		L = transitions.size();
		for (i = 0; i < L; i++) {
			g = transitions.get(i);
			drawTransition(gr, g);
		}
	}

	void drawOtherSingleDrag(Graphics2D g) {
		if (comment)
			g.setColor(parentGraphicalZone.pref.commentColor);
		else
			g.setColor(parentGraphicalZone.pref.foregroundColor);
		// drawing the box
		if (n_lines == 0) {
			GraphicalToolBox.drawLine(g, X_in, Y_in, X_in + 15, Y_in);
			if (parentGraphicalZone.pref.rightToLeft == false)
				GraphicalToolBox.drawLine(g, X_in + 15, Y1, X_in + 15, Y1 + Height);
			else
				GraphicalToolBox.drawLine(g, X_in, Y1, X_in, Y1 + Height);
		} else {
			GraphicalToolBox.drawRect(g, X1, Y1, Width, Height);
		}
		// and the triangle if necessary
		if (hasOutgoingTransitions || type == INITIAL) {
			if (parentGraphicalZone.pref.rightToLeft == false) {
				GraphicalToolBox.drawLine(g, X_out, Y_out, X1 + Width, Y1);
				GraphicalToolBox.drawLine(g, X1 + Width, Y1, X1 + Width, Y1 + Height);
				GraphicalToolBox.drawLine(g, X1 + Width, Y1 + Height, X_out, Y_out);
			} else {
				GraphicalToolBox.drawLine(g, X_in - 5, Y_in, X1, Y1);
				GraphicalToolBox.drawLine(g, X1, Y1, X1, Y1 + Height);
				GraphicalToolBox.drawLine(g, X1, Y1 + Height, X_in - 5, Y_in);
			}
		}
	}

	private void drawInitialSingleDrag(Graphics2D g) {
		g.setColor(parentGraphicalZone.pref.foregroundColor);
		// drawing the box
		if (n_lines == 0) {
			GraphicalToolBox.drawLine(g, X_in, Y_in, X_in + 15, Y_in);
		} else {
			GraphicalToolBox.drawRect(g, X1, Y1, Width, Height);
		}
		// drawing the entry line
		if (parentGraphicalZone.pref.rightToLeft == false)
			GraphicalToolBox.drawLine(g, X_in, Y_in, X_in - 10, Y_in);
		else
			GraphicalToolBox.drawLine(g, X_out - 5, Y_out, X_out + 5, Y_out);
		// and the triangle if necessary
		if (hasOutgoingTransitions || type == INITIAL) {
			if (parentGraphicalZone.pref.rightToLeft == false) {
				GraphicalToolBox.drawLine(g, X_out, Y_out, X1 + Width, Y1);
				GraphicalToolBox.drawLine(g, X1 + Width, Y1, X1 + Width, Y1 + Height);
				GraphicalToolBox.drawLine(g, X1 + Width, Y1 + Height, X_out, Y_out);
			} else {
				GraphicalToolBox.drawLine(g, X_in - 5, Y_in, X1, Y1);
				GraphicalToolBox.drawLine(g, X1, Y1, X1, Y1 + Height);
				GraphicalToolBox.drawLine(g, X1, Y1 + Height, X_in - 5, Y_in);
			}
		}
	}

	private void drawFinalSingleDrag(Graphics2D g) {
		drawFinal(g);
	}

	void drawOtherComment(Graphics2D g) {
		int i;
		Boolean is_greyed;
		String l;
		if (variable) {
			drawVariableComment(g);
			return;
		}
		if (contextMark) {
			drawContextMarkComment(g);
			return;
		}
		g.setColor(parentGraphicalZone.pref.commentColor);
		// print lines if the box is empty
		if (n_lines == 0) {
			GraphicalToolBox.drawLine(g, X_in, Y_in, X_in + 15, Y_in);
			if (parentGraphicalZone.pref.rightToLeft == false)
				GraphicalToolBox.drawLine(g, X_in + 15, Y1, X_in + 15, Y1 + Height);
			else
				GraphicalToolBox.drawLine(g, X_in, Y1, X_in, Y1 + Height);
		} else {
			g.setColor(parentGraphicalZone.pref.backgroundColor);
			GraphicalToolBox.fillRect(g, X1 + 1, Y1 + 1, Width - 2, Height - 2);
			g.setColor(parentGraphicalZone.pref.commentColor);
		}
		// prints the lines of the box
		for (i = 0; i < n_lines; i++) {
			is_greyed = greyed.get(i);
			l = lines.get(i);
			if (is_greyed.booleanValue()) {
				g.setColor(parentGraphicalZone.pref.subgraphColor);
				if (l.startsWith(":")) {
					// if we have a subgraph within a package
					g.setColor(parentGraphicalZone.pref.packageColor);
				}
				GraphicalToolBox.fillRect(g, X1 + 3, Y1 + 4 + (i) * h_ligne, Width - 4, h_ligne);
				g.setColor(parentGraphicalZone.pref.commentColor);
				
				TextLayout textlayout = new TextLayout(l, parentGraphicalZone.pref.input, g.getFontRenderContext());
				textlayout.draw(g, X1 + 5, Y1 - descent + 3 + (i + 1) * h_ligne);
			} else {
				TextLayout textlayout = new TextLayout(l, parentGraphicalZone.pref.input, g.getFontRenderContext());
				textlayout.draw(g, X1 + 5, Y1 - descent + 3 + (i + 1) * h_ligne);
			}
		}
		// prints the transduction, if exists
		g.setColor(parentGraphicalZone.pref.foregroundColor);
		if (!transduction.equals("")) {
			g.setFont(parentGraphicalZone.pref.output);
			g.drawString(transduction, X1 + 5, Y1 + Height
					+ g.getFontMetrics().getHeight());
		}
	}

	private void drawFinal(Graphics2D g) {
		g.setColor(parentGraphicalZone.pref.backgroundColor);
		GraphicalToolBox.fillEllipse(g, x, Y - 10, 21, 21);
		g.setColor(parentGraphicalZone.pref.foregroundColor);
		GraphicalToolBox.drawEllipse(g, x, Y - 10, 21, 21);
		GraphicalToolBox.drawRect(g, x + 5, Y - 5, 10, 10);
	}

	private void drawFinalSelected(Graphics2D g) {
		g.setColor(parentGraphicalZone.pref.selectedColor);
		GraphicalToolBox.fillEllipse(g, x, Y - 10, 21, 21);
		g.setColor(parentGraphicalZone.pref.backgroundColor);
		GraphicalToolBox.drawRect(g, x + 5, Y - 5, 10, 10);
	}

	private void drawVariable(Graphics2D g) {
		g.setColor(parentGraphicalZone.pref.commentColor);
		g.setFont(variableFont);
		g.drawString(lines.get(0), X1 + 5, Y1
				- g.getFontMetrics().getDescent() + get_h_variable_ligne());
		g.setFont(parentGraphicalZone.pref.output);
		g.drawString(transduction, X1 + 10, Y1 + Height
				+ g.getFontMetrics().getHeight());
	}

	private void drawVariableSelected(Graphics2D g) {
		g.setColor(parentGraphicalZone.pref.selectedColor);
		GraphicalToolBox.fillRect(g, X1, Y1, Width, Height);
		g.setColor(parentGraphicalZone.pref.commentColor);
		g.setFont(variableFont);
		g.drawString(lines.get(0), X1 + 5, Y1
				- g.getFontMetrics().getDescent() + get_h_variable_ligne());

		g.setColor(parentGraphicalZone.pref.selectedColor);
		GraphicalToolBox.fillRect(g, X1 + 5, Y1 + Height + g.getFontMetrics().getDescent(), g
				.getFontMetrics(parentGraphicalZone.pref.output).stringWidth(
						transduction), g.getFontMetrics(
				parentGraphicalZone.pref.output).getHeight() + 1);
		g.setColor(parentGraphicalZone.pref.backgroundColor);
		g.setFont(parentGraphicalZone.pref.output);
		g.drawString(transduction, X1 + 5, Y1 + Height
				+ g.getFontMetrics().getHeight());
	}

	private void drawVariableComment(Graphics2D g) {
		drawVariable(g);
	}

	private void drawContextMark(Graphics2D g) {
		g.setColor(parentGraphicalZone.pref.contextColor);
		g.setFont(variableFont);
		g.drawString(lines.get(0), X1 + 5, Y1
				- g.getFontMetrics().getDescent() + get_h_variable_ligne());
	}

	private void drawContextMarkSelected(Graphics2D g) {
		drawVariableSelected(g);
	}

	private void drawContextMarkComment(Graphics2D g) {
		drawContextMark(g);
	}

	private void drawMorphologicalModeMark(Graphics2D g) {
		g.setColor(parentGraphicalZone.pref.morphologicalModeColor);
		g.setFont(variableFont);
		g.drawString(lines.get(0), X1 + 5, Y1
				- g.getFontMetrics().getDescent() + get_h_variable_ligne());
	}

	private void drawMorphologicalModeMarkSelected(Graphics2D g) {
		drawVariableSelected(g);
	}

	void drawOther(Graphics2D g) {
		int i;
		Boolean is_greyed;
		String l;
		if (variable) {
			drawVariable(g);
			return;
		}
		if (contextMark) {
			drawContextMark(g);
			return;
		}
		if (morphologicalModeMark) {
			drawMorphologicalModeMark(g);
			return;
		}
		g.setColor(parentGraphicalZone.pref.foregroundColor);
		// drawing the box
		if (n_lines == 0) {
			GraphicalToolBox.drawLine(g, X_in, Y_in, X_in + 15, Y_in);
			if (parentGraphicalZone.pref.rightToLeft == false)
				GraphicalToolBox.drawLine(g, X_in + 15, Y1, X_in + 15, Y1 + Height);
			else
				GraphicalToolBox.drawLine(g, X_in, Y1, X_in, Y1 + Height);
		} else {
			g.setColor(parentGraphicalZone.pref.backgroundColor);
			GraphicalToolBox.fillRect(g, X1 + 1, Y1 + 1, Width - 2, Height - 2);
			g.setColor(parentGraphicalZone.pref.foregroundColor);
			GraphicalToolBox.drawRect(g, X1, Y1, Width, Height);
		}
		// and the triangle if necessary
		if (hasOutgoingTransitions || type == INITIAL) {
			if (parentGraphicalZone.pref.rightToLeft == false) {
				int a = X1 + Width;
				int b = Y1 + Height;
				GraphicalToolBox.drawLine(g, X_out, Y_out, a, Y1);
				GraphicalToolBox.drawLine(g, a, Y1, a, b);
				GraphicalToolBox.drawLine(g, a, b, X_out, Y_out);
			} else {
				GraphicalToolBox.drawLine(g, X_in - 5, Y_in, X1, Y1);
				GraphicalToolBox.drawLine(g, X1, Y1, X1, Y1 + Height);
				GraphicalToolBox.drawLine(g, X1, Y1 + Height, X_in - 5, Y_in);
			}
		}
		// prints the lines of the box
		for (i = 0; i < n_lines; i++) {
			is_greyed = greyed.get(i);
			l = lines.get(i);
			if (is_greyed.booleanValue()) {
				g.setColor(parentGraphicalZone.pref.subgraphColor);
				if (l.startsWith(":")) {
					// if we have a subgraph within a package
					g.setColor(parentGraphicalZone.pref.packageColor);
				}
				GraphicalToolBox.fillRect(g, X1 + 3, Y1 + 4 + (i) * h_ligne, Width - 4, h_ligne);
				g.setColor(parentGraphicalZone.pref.foregroundColor);
				TextLayout textlayout = new TextLayout(l, parentGraphicalZone.pref.input, g.getFontRenderContext());
				textlayout.draw(g, X1 + 5, Y1 - descent + 3 + (i + 1) * h_ligne);
			} else {
				TextLayout textlayout = new TextLayout(l, parentGraphicalZone.pref.input, g.getFontRenderContext());
				textlayout.draw(g, X1 + 5, Y1 - descent + 3 + (i + 1) * h_ligne);
			}
		}
		// prints the transduction, if exists
		g.setColor(parentGraphicalZone.pref.foregroundColor);
		if (!transduction.equals("")) {
			g.setFont(parentGraphicalZone.pref.output);
			g.drawString(transduction, X1 + 5, Y1 + Height
					+ g.getFontMetrics().getHeight());
		}
		
		// prints the etiquette, if applicable
		Etiquettes.drawEtiquette(this,g,n_lines,lines);
		
	}

	void drawOtherSelected(Graphics2D g) {
		int i;
		String l;
		if (variable) {
			drawVariableSelected(g);
			return;
		}
		if (contextMark) {
			drawContextMarkSelected(g);
			return;
		}
		if (morphologicalModeMark) {
			drawMorphologicalModeMarkSelected(g);
			return;
		}
		g.setColor(parentGraphicalZone.pref.foregroundColor);
		// drawing the box
		if (n_lines == 0) {
			g.setColor(parentGraphicalZone.pref.selectedColor);
			GraphicalToolBox.fillRect(g, X_in, Y_in - 10, 15, 20);
			g.setColor(parentGraphicalZone.pref.backgroundColor);
			GraphicalToolBox.drawLine(g, X_in, Y_in, X_in + 15, Y_in);
		} else {
			g.setColor(parentGraphicalZone.pref.selectedColor);
			GraphicalToolBox.fillRect(g, X1, Y1, Width, Height);
		}
		// and the triangle if necessary
		if (hasOutgoingTransitions || type == INITIAL) {
			g.setColor(parentGraphicalZone.pref.foregroundColor);
			if (parentGraphicalZone.pref.rightToLeft == false) {
				GraphicalToolBox.drawLine(g, X_out, Y_out, X1 + Width, Y1);
				GraphicalToolBox.drawLine(g, X1 + Width, Y1, X1 + Width, Y1 + Height);
				GraphicalToolBox.drawLine(g, X1 + Width, Y1 + Height, X_out, Y_out);
			} else {
				GraphicalToolBox.drawLine(g, X_in - 5, Y_in, X1, Y1);
				GraphicalToolBox.drawLine(g, X1, Y1, X1, Y1 + Height);
				GraphicalToolBox.drawLine(g, X1, Y1 + Height, X_in - 5, Y_in);
			}
		}
		// prints the lines of the box
		g.setColor(parentGraphicalZone.pref.backgroundColor);
		for (i = 0; i < n_lines; i++) {
			l = lines.get(i);
			TextLayout textlayout = new TextLayout(l, parentGraphicalZone.pref.input, g.getFontRenderContext());
			textlayout.draw(g, X1 + 5, Y1 - descent + 3 + (i + 1) * h_ligne);
		}
		// prints the transduction, if exists
		if (!transduction.equals("")) {
			g.setColor(parentGraphicalZone.pref.selectedColor);
			GraphicalToolBox.fillRect(g, X1 + 5, Y1 + Height + g.getFontMetrics().getDescent(),
					g.getFontMetrics(parentGraphicalZone.pref.output)
							.stringWidth(transduction), g.getFontMetrics(
							parentGraphicalZone.pref.output).getHeight() + 1);
			g.setColor(parentGraphicalZone.pref.backgroundColor);
			g.setFont(parentGraphicalZone.pref.output);
			g.drawString(transduction, X1 + 5, Y1 + Height
					+ g.getFontMetrics().getHeight());
		}
	}

	private void drawInitial(Graphics2D g) {
		drawOther(g);
		if (parentGraphicalZone.pref.rightToLeft == false)
			GraphicalToolBox.drawLine(g, X_in, Y_in, X_in - 10, Y_in);
		else
			GraphicalToolBox.drawLine(g, X_out - 5, Y_out, X_out + 5, Y_out);
	}

	private void drawInitialSelected(Graphics2D g) {
		drawOtherSelected(g);
		g.setColor(parentGraphicalZone.pref.foregroundColor);
		if (parentGraphicalZone.pref.rightToLeft == false)
			GraphicalToolBox.drawLine(g, X_in - 1, Y_in, X_in - 10, Y_in);
		else
			GraphicalToolBox.drawLine(g, X_out - 5, Y_out, X_out + 5, Y_out);
	}

	/**
	 * Draws the box
	 * 
	 * @param g
	 *            the graphical context
	 */
	public void draw(Graphics2D g) {
		updateWithContext(g);
		g.setFont(parentGraphicalZone.pref.input);
		h_ligne = g.getFontMetrics().getHeight();
		descent = g.getFontMetrics().getDescent();
		if (singleDragging == true) {
			// if the box is being dragged just under the mouse,
			// we just draw its frame
			if (type == FINAL)
				drawFinalSingleDrag(g);
			else if (type == NORMAL)
				drawOtherSingleDrag(g);
			else
				drawInitialSingleDrag(g);
		} else if (selected == true) {
			// if the box was selected before (blue box)
			if (type == FINAL)
				drawFinalSelected(g);
			else if (type == NORMAL)
				drawOtherSelected(g);
			else
				drawInitialSelected(g);
		} else if (comment == true) {
			// if the box is in comment and not selected
			if (type == FINAL)
				drawFinal(g);
			else if (type == NORMAL)
				drawOtherComment(g);
			else
				drawInitial(g);
		} else {
			// the box is normal
			if (type == FINAL) {
				drawFinal(g);
			}
			else if (type == NORMAL) {
				drawOther(g);
			}
			else {
				drawInitial(g);
			}
		}
	}

	/**
	 * Returns the height of a line of the box.
	 * 
	 * @return the height
	 */
	int get_h_ligne() {
		if (context == null) {
			return 0;
		}
		context.setFont(parentGraphicalZone.pref.input);
		return context.getFontMetrics().getHeight();
	}

	/**
	 * Returns the height of a variable d�finition line like <code>$a(</code>.
	 * 
	 * @return the height
	 */
	int get_h_variable_ligne() {
		if (context == null) {
			return 0;
		}
		context.setFont(variableFont);
		return context.getFontMetrics().getHeight();
	}

	/**
	 * Returns the width of the box's largest line.
	 * 
	 * @return the width
	 */
	public int maxLineWidth() {
		if (context == null) {
			return 0;
		}
		int i, max = 0;
		String s;
		max = 0;
		FontMetrics f = context.getFontMetrics(parentGraphicalZone.pref.input);
		for (i = 0; i < n_lines; i++) {
			s = lines.get(i);
			if (max < f.stringWidth(s))
				max = f.stringWidth(s);
		}
		return max;
	}

	/**
	 * Sets the content of the box
	 * 
	 * @param s
	 *            the content
	 * @throws NoClosingQuoteException 
	 */
	public abstract void setContent(String s);

	/**
	 * Updates the box by calling the <code>setContent</code> method with the
	 * current box content, which refresh the box properties. It used to
	 * recompute box properties, for example when the user has changed font
	 * sizes.
	 * @throws NoClosingQuoteException 
	 *  
	 */
	public void update(){
		// this method is used to resize the box after a font change
		setContent(content);
	}

	public ArrayList<GenericGraphBox> getTransitions() {
		return transitions;
	}

	public int getX() {
		return x;
	}

	public int getY() {
		return Y;
	}

	/**
	 * @return the box content as it appears in the text edition field
	 */
	public String getContent() {
		return content;
	}

	/**
	 * Translate a box to the x,y position
	 * 
	 * @param xPos
	 * @param yPos
	 */
	public void translateToPosition(int xPos, int yPos) {

		x = xPos;
		Y = yPos;

		if (type == FINAL) {
			X_in = xPos;
			Y_in = Y;
			X1 = xPos;
			Y1 = Y - 10;
			Y_out = Y_in;
			X_out = X_in + 25;
		} else {
			X1 = xPos;
			Y1 = Y;
			X_in = xPos;
			Y_in = Y + Height / 2;
			X_out = xPos + Width + 5;
			Y_out = Y_in;
		}

	}

	public boolean hasTransitionToItself() {
		//	self transition checking
		Iterator<GenericGraphBox> it = getTransitions().iterator();
		GenericGraphBox g;
		while (it.hasNext()) {
			g = it.next();
			if (g == this)
				return true;
		}
		return false;
	}

	public boolean isSelected() {
		return selected;
	}

	/**
	 * @param b
	 */
	public void setSelected(boolean b) {
		selected = b;
	}

	public void setX(int x1) {
		x = x1;
	}

	public void setY(int y) {
		Y = y;
	}

	public int getWidth() {
		return Width;
	}

	public int getX_in() {
		return X_in;
	}

	public void setX_in(int x_in) {
		X_in = x_in;
	}

	public int getX_out() {
		return X_out;
	}

	public void setX_out(int x_out) {
		X_out = x_out;
	}

	public int getX1() {
		return X1;
	}

	public void setX1(int x1) {
		X1 = x1;
	}

	public int getY1() {
		return Y1;
	}

	public void setY1(int y1) {
		Y1 = y1;
	}

	public int getY_in() {
		return Y_in;
	}

	public void setY_in(int y_in) {
		Y_in = y_in;
	}

	public int getY_out() {
		return Y_out;
	}

	public void setY_out(int y_out) {
		Y_out = y_out;
	}

	public int getType() {
		return type;
	}
	public void setType(int type) {
		this.type = type;
	}

	public void setTransitions(ArrayList<GenericGraphBox> transitions) {
		this.transitions = transitions;
	}

	void updateWithContext(Graphics2D g){
		if (context != null) {
			return;
		}
		context = g;
		update();
	}
}
/*
 * Unitex
 * 
 * Copyright (C) 2001-2006 Universit� de Marne-la-Vall�e <unitex@univ-mlv.fr>
 * 
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 * 
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 *  
 */

package ndosownww.unitex.changes;

import java.awt.*;
import java.awt.event.*;
import java.io.*;

import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;

/**
 * This class describes a frame that offers to the user to set his preferences.
 * 
 * @author S�bastien Paumier
 *  
 */
public class GlobalPreferenceFrame extends JInternalFrame {

	static GlobalPreferenceFrame frame;

	JTextField privateDirectory = new JTextField("");

	protected JTextField textFont = new JTextField("");

	JTextField concordanceFont = new JTextField("");

	JTextField htmlViewer = new JTextField("");

	NumericTextField maxTextFileSize = new NumericTextField("");

	JCheckBox antialiasingCheckBox = new JCheckBox(
			"Enable antialising for rendering graphs", false);

	JCheckBox dateCheckBox = new JCheckBox();

	JCheckBox filenameCheckBox = new JCheckBox();

	JCheckBox pathnameCheckBox = new JCheckBox();

	JCheckBox frameCheckBox = new JCheckBox();

	JCheckBox rightToLeftCheckBox = new JCheckBox(
			"Right to left rendering for corpus and graphs");

	JCheckBox charByCharCheckBox = new JCheckBox(
			"Analyze this language char by char");

	JButton color1 = new JButton("      ");

	JButton color2 = new JButton("      ");

	JButton color3 = new JButton("      ");

	JButton color4 = new JButton("      ");

	JButton color5 = new JButton("      ");

	JLabel inputLabel = new JLabel("", SwingConstants.LEFT);

	JLabel outputLabel = new JLabel("", SwingConstants.LEFT);

	JRadioButton westRadioBox = new JRadioButton("West", false);

	JRadioButton eastRadioBox = new JRadioButton("East", false);

	JRadioButton northRadioBox = new JRadioButton("North", false);

	JRadioButton southRadioBox = new JRadioButton("South", false);

	JRadioButton noneRadioBox = new JRadioButton("None", false);

	JTextField packageDirectory = new JTextField("");

	static Preferences pref;

	private GlobalPreferenceFrame() {
		super("", false, true, false, false);
		setContentPane(constructPanel());
		pack();
		setBounds(200, 200, 400, 450);
		setVisible(false);
		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		addInternalFrameListener(new InternalFrameAdapter() {

			public void internalFrameClosing(InternalFrameEvent arg0) {
				setVisible(false);
			}
		});
	}

	/**
	 * Initializes the frame
	 *  
	 */
	private static void init() {
		frame = new GlobalPreferenceFrame();
		GrafMainFrame.addInternalFrame(frame);
	}

	/**
	 * @return the frame
	 */
	public static GlobalPreferenceFrame getFrame() {
		return frame;
	}

	/**
	 * Shows the frame
	 *  
	 */
	public static void showFrame() {
		if (frame == null) {
			init();
		}
		pref = Preferences.getCloneOfPreferences();
		System.out.println();
		frame.setTitle("Preferences for " + Config.getCurrentLanguage());
		frame.privateDirectory.setText(Config.getUserDir().getAbsolutePath());

		frame.refresh();
		frame.setVisible(true);
		try {
			frame.setSelected(true);
		} catch (java.beans.PropertyVetoException e2) {
			e2.printStackTrace();
		}
	}

	private JPanel constructPanel() {
		JPanel panel = new JPanel(new BorderLayout());
		panel.setOpaque(true);
		panel.add(constructUpPanel(), BorderLayout.CENTER);
		panel.add(constructDownPanel(), BorderLayout.SOUTH);
		return panel;
	}

	private JPanel constructUpPanel() {
		JPanel upPanel = new JPanel(new BorderLayout());
		JTabbedPane tabbedPane = new JTabbedPane(SwingConstants.TOP);
		tabbedPane.addTab("Directories", constructPage1());
		tabbedPane.addTab("Text Presentation", constructPage2());
		tabbedPane.addTab("Graph Presentation", constructPage3());
		upPanel.add(tabbedPane);
		return upPanel;
	}

	private JPanel constructDownPanel() {
		JPanel downPanel = new JPanel(new BorderLayout());
		JPanel tmp = new JPanel();
		tmp.setBorder(new EmptyBorder(2, 2, 2, 2));
		tmp.setLayout(new GridLayout(1, 2));
		JPanel tmp1 = new JPanel();
		JPanel tmp2 = new JPanel();
		tmp1.setBorder(new EmptyBorder(5, 5, 5, 5));
		tmp2.setBorder(new EmptyBorder(5, 5, 5, 5));
		tmp1.setLayout(new BorderLayout());
		tmp2.setLayout(new BorderLayout());

		Action okAction = new AbstractAction("OK") {

			public void actionPerformed(ActionEvent arg0) {
				pref.antialiasing = frame.antialiasingCheckBox.isSelected();
				if (frame.htmlViewer.getText().equals(""))
					pref.htmlViewer = null;
				else
					pref.htmlViewer = new File(frame.htmlViewer.getText());
				pref.date = frame.dateCheckBox.isSelected();
				pref.filename = frame.filenameCheckBox.isSelected();
				pref.pathname = frame.pathnameCheckBox.isSelected();
				pref.frame = frame.frameCheckBox.isSelected();
				pref.rightToLeft = frame.rightToLeftCheckBox.isSelected();
				if (frame.westRadioBox.isSelected()) {
					pref.iconBarPosition = Preferences.ICON_BAR_WEST;
				} else if (frame.eastRadioBox.isSelected()) {
					pref.iconBarPosition = Preferences.ICON_BAR_EAST;
				} else if (frame.northRadioBox.isSelected()) {
					pref.iconBarPosition = Preferences.ICON_BAR_NORTH;
				} else if (frame.southRadioBox.isSelected()) {
					pref.iconBarPosition = Preferences.ICON_BAR_SOUTH;
				} else if (frame.noneRadioBox.isSelected()) {
					pref.iconBarPosition = Preferences.NO_ICON_BAR;
				} else {
					pref.iconBarPosition = Preferences.ICON_BAR_DEFAULT;
				}
				if (!frame.maxTextFileSize.getText().equals("")
						&& new Integer(frame.maxTextFileSize.getText())
								.intValue() != 0) {
					pref.MAX_TEXT_FILE_SIZE = new Integer(
							frame.maxTextFileSize.getText()).intValue() * 1024;
				}
				pref.charByChar = frame.charByCharCheckBox.isSelected();
				if (frame.packageDirectory.getText().equals(""))
					pref.packagePath = null;
				else {
					File f=new File(frame.packageDirectory.getText());
					if (!f.exists()) {
						JOptionPane
						.showMessageDialog(
								null,
								"The graph repository\ndoes not exist.",
								"Error", JOptionPane.ERROR_MESSAGE);
						return;
					}
					if (!f.isDirectory()) {
						JOptionPane
						.showMessageDialog(
								null,
								"The path given for the graph repository\n is not a directory path.",
								"Error", JOptionPane.ERROR_MESSAGE);
						return;
					}
					pref.packagePath = f;
				}
				Preferences.savePreferences(pref);
				if (Config.getCurrentSystem() == Config.WINDOWS_SYSTEM) {
					// if we are under Windows, we must save the user dir
					if (privateDirectory.getText() != null
							&& !privateDirectory.getText().equals("")) {
						File rep = new File(privateDirectory.getText());
						if (!rep.equals(Config.getUserDir())) {
							File userFile = new File(Config.getUnitexDir(),
									"Users");
							userFile = new File(userFile, Config.getUserName()
									+ ".cfg");
							if (userFile.exists())
								userFile.delete();
							try {
								userFile.createNewFile();
								BufferedWriter bw = new BufferedWriter(
										new FileWriter(userFile));
								bw.write(rep.getAbsolutePath(), 0, rep
										.getAbsolutePath().length());
								bw.close();
							} catch (IOException e2) {
								e2.printStackTrace();
							}
							String message = "Your private Unitex directory is now:\n\n";
							message = message + rep + "\n\n";
							message = message
									+ "You must relaunch Unitex to take this change into account.";
							JOptionPane.showMessageDialog(null, message, "",
									JOptionPane.PLAIN_MESSAGE);
						}
					}
				}
				setVisible(false);
			}
		};
		Action cancelAction = new AbstractAction("Cancel") {

			public void actionPerformed(ActionEvent arg0) {
				setVisible(false);
			}
		};
		JButton OK = new JButton(okAction);
		JButton CANCEL = new JButton(cancelAction);
		tmp1.add(OK);
		tmp2.add(CANCEL);
		tmp.add(tmp1);
		tmp.add(tmp2);
		downPanel.add(tmp, BorderLayout.EAST);
		return downPanel;
	}

	
	private JComponent constructPage1() {
		JPanel page1 = new JPanel(new GridBagLayout());
		page1.setBorder(new EmptyBorder(5, 5, 5, 5));

		JLabel label = new JLabel(
				"Private Unitex directory (where all user's data is to be stored):");

		privateDirectory.setEditable(false);
		privateDirectory.setBackground(Color.WHITE);
		Action privateDirAction = new AbstractAction("Set...") {
			public void actionPerformed(ActionEvent arg0) {
				JFileChooser f = new JFileChooser();
				f.setDialogTitle("Choose your private directory");
				f.setDialogType(JFileChooser.OPEN_DIALOG);
				f.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
				if (f.showOpenDialog(null) != JFileChooser.APPROVE_OPTION)
					return;
				if (f.getSelectedFile().equals(Config.getUnitexDir())) {
					JOptionPane
							.showMessageDialog(
									null,
									"You cannot choose the Unitex directory as your private one",
									"Error", JOptionPane.ERROR_MESSAGE);
					return;
				}
				privateDirectory.setText(f.getSelectedFile().getAbsolutePath());
			}
		};
		JButton setPrivateDirectory = new JButton(privateDirAction);
		if (Config.getCurrentSystem()!=Config.WINDOWS_SYSTEM) {
			setPrivateDirectory.setEnabled(false);
		}
		GridBagConstraints gbc = new GridBagConstraints();

		gbc.insets = new Insets(2, 2, 2, 2);
		gbc.anchor = GridBagConstraints.WEST;
		gbc.gridwidth = GridBagConstraints.REMAINDER;
		gbc.fill = GridBagConstraints.NONE;
		page1.add(label, gbc);

		gbc.gridwidth = 1;
		gbc.weightx = 1;
		gbc.fill = GridBagConstraints.HORIZONTAL;
		page1.add(privateDirectory, gbc);

		gbc.weightx = 0;
		gbc.fill = GridBagConstraints.NONE;
		gbc.gridwidth = GridBagConstraints.REMAINDER;
		page1.add(setPrivateDirectory, gbc);

		//--------------------------------------------------------

		JLabel label2 = new JLabel("Graph repository:");

		packageDirectory.setBackground(Color.WHITE);
		Action packageDirAction = new AbstractAction("Set...") {
			public void actionPerformed(ActionEvent arg0) {
				JFileChooser f = new JFileChooser();
				f.setDialogTitle("Choose your graph package directory");
				f.setDialogType(JFileChooser.OPEN_DIALOG);
				f.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
				if (f.showOpenDialog(null) != JFileChooser.APPROVE_OPTION) {
					return;
				}
				packageDirectory.setText(f.getSelectedFile().getAbsolutePath());
			}
		};
		JButton setPackageDirectory = new JButton(packageDirAction);

		gbc.insets = new Insets(20, 2, 2, 2);
		gbc.anchor = GridBagConstraints.WEST;
		gbc.gridwidth = GridBagConstraints.REMAINDER;
		gbc.fill = GridBagConstraints.NONE;
		page1.add(label2, gbc);

		gbc.insets = new Insets(2, 2, 2, 2);
		gbc.gridwidth = 1;
		gbc.weightx = 1;
		gbc.fill = GridBagConstraints.HORIZONTAL;
		page1.add(packageDirectory, gbc);

		gbc.weightx = 0;
		gbc.fill = GridBagConstraints.NONE;
		gbc.gridwidth = GridBagConstraints.REMAINDER;
		page1.add(setPackageDirectory, gbc);

		gbc.weighty = 1;
		page1.add(new JComponent() {/**/
		}, gbc);

		return page1;
	}

	private JPanel constructPage2() {
		JPanel page2 = new JPanel(new GridLayout(5, 1));

		textFont.setEnabled(false);
		concordanceFont.setEnabled(false);
		textFont.setDisabledTextColor(Color.black);
		concordanceFont.setDisabledTextColor(Color.black);

		page2.setBorder(new EmptyBorder(5, 5, 5, 5));
		JPanel yuyu = new JPanel(new GridLayout(2, 1));

		yuyu.add(charByCharCheckBox);
		yuyu.add(rightToLeftCheckBox);
		page2.add(yuyu);

		JPanel tmp = new JPanel();
		tmp.setPreferredSize(new Dimension(180, 60));
		tmp.setLayout(new GridLayout(2, 1));
		tmp.add(new JLabel("Text Font:"));
		JPanel tmp2 = new JPanel();
		tmp2.setLayout(new BorderLayout());
		tmp2.add(textFont, BorderLayout.CENTER);
		Action textFontAction = new AbstractAction("Set...") {

			public void actionPerformed(ActionEvent arg0) {
			
				new TextFontMenu(pref, TextFontMenu.TEXT_FONT);
			}
		};
		JButton setTextFont = new JButton(textFontAction);
		tmp2.add(setTextFont, BorderLayout.EAST);
		tmp.add(tmp2);
		//page2.add(new JLabel(""));
		page2.add(tmp);

		JPanel tmp_ = new JPanel();
		tmp_.setPreferredSize(new Dimension(180, 60));
		tmp_.setLayout(new GridLayout(2, 1));
		tmp_.add(new JLabel("Concordance Font:"));
		JPanel tmp2_ = new JPanel();
		tmp2_.setLayout(new BorderLayout());
		tmp2_.add(concordanceFont, BorderLayout.CENTER);
		tmp_.add(tmp2_);
		page2.add(tmp_);

		JPanel tmp__ = new JPanel();
		tmp__.setPreferredSize(new Dimension(180, 60));
		tmp__.setLayout(new GridLayout(2, 1));
		tmp__.add(new JLabel("Html Viewer:"));
		JPanel tmp3_ = new JPanel();
		tmp3_.setLayout(new BorderLayout());
		Action html = new AbstractAction("Set...") {

			public void actionPerformed(ActionEvent arg0) {
				SwingUtilities.invokeLater(new Runnable() {

					public void run() {
						JFileChooser f = new JFileChooser();
						f.setDialogTitle("Choose your html viewer");
						f.setDialogType(JFileChooser.OPEN_DIALOG);
						if (f.showOpenDialog(null) != JFileChooser.APPROVE_OPTION)
							return;
						htmlViewer.setText(f.getSelectedFile()
								.getAbsolutePath());
					}
				});
			}
		};
		JButton setHtmlViewer = new JButton(html);
		tmp3_.add(htmlViewer, BorderLayout.CENTER);
		tmp3_.add(setHtmlViewer, BorderLayout.EAST);
		tmp__.add(tmp3_);
		page2.add(tmp__);
		JPanel tmp4 = new JPanel();
		tmp4.setPreferredSize(new Dimension(180, 60));
		tmp4.setLayout(new GridLayout(2, 1));
		tmp4.add(new JLabel("Maximum Text File Size:"));
		JPanel tmp4_ = new JPanel();
		tmp4_.setLayout(new BorderLayout());
		tmp4_.add(maxTextFileSize, BorderLayout.CENTER);
		tmp4_.add(new JLabel("  Kbytes     "), BorderLayout.EAST);
		tmp4.add(tmp4_);
		page2.add(tmp4);
		return page2;
	}

	private JPanel constructPage3() {
		GridBagLayout g = new GridBagLayout();
		JPanel page3 = new JPanel(g);
		page3.setBorder(new EmptyBorder(5, 5, 5, 5));
		GridBagConstraints c = new GridBagConstraints();
		c.gridwidth = GridBagConstraints.REMAINDER;
		c.fill = GridBagConstraints.BOTH;
		c.anchor = GridBagConstraints.NORTH;
		JPanel upPanel_ = constructUpPanel_();
		g.setConstraints(upPanel_, c);
		page3.add(upPanel_);
		c.fill = GridBagConstraints.BOTH;
		JPanel downPanel_ = constructDownPanel_();
		g.setConstraints(downPanel_, c);
		page3.add(downPanel_);
		return page3;
	}

	private JPanel constructUpPanel_() {
		JPanel upPanel_ = new JPanel(new BorderLayout());
		upPanel_.setBorder(new EmptyBorder(0, 0, 0, 0));
		upPanel_.add(constructDisplayPanel(), BorderLayout.WEST);
		upPanel_.add(constructColorPanel(), BorderLayout.CENTER);
		return upPanel_;
	}

	private JPanel constructDownPanel_() {
		JPanel downPanel_ = new JPanel(new BorderLayout());
		downPanel_.setBorder(new EmptyBorder(0, 0, 0, 0));
		downPanel_.add(constructAntialiasingPanel(), BorderLayout.NORTH);
		downPanel_.add(constructFontPanel(), BorderLayout.CENTER);
		downPanel_.add(constructButtonPanel(), BorderLayout.EAST);
		return downPanel_;
	}

	private JPanel constructDisplayPanel() {
		JPanel displayPanel = new JPanel(new GridLayout(5, 1));
		displayPanel.setBorder(new TitledBorder("Display"));
		JPanel display1 = new JPanel(new BorderLayout());
		JPanel display2 = new JPanel(new BorderLayout());
		JPanel display3 = new JPanel(new BorderLayout());
		JPanel display4 = new JPanel(new BorderLayout());
		JPanel display5 = new JPanel(new BorderLayout());
		display1.add(dateCheckBox, BorderLayout.WEST);
		display1.add(new JLabel("Date  "), BorderLayout.CENTER);
		display2.add(filenameCheckBox, BorderLayout.WEST);
		display2.add(new JLabel("File Name  "), BorderLayout.CENTER);
		display3.add(pathnameCheckBox, BorderLayout.WEST);
		display3.add(new JLabel("Pathname  "), BorderLayout.CENTER);
		display4.add(frameCheckBox, BorderLayout.WEST);
		display4.add(new JLabel("Frame  "), BorderLayout.CENTER);
		//display5.add(rightToLeftCheckBox, BorderLayout.WEST);
		//display5.add(new JLabel("Right to Left  "), BorderLayout.CENTER);
		displayPanel.add(display1);
		displayPanel.add(display2);
		displayPanel.add(display3);
		displayPanel.add(display4);
		displayPanel.add(display5);
		return displayPanel;
	}

	private void build(GridBagConstraints c, int gx, int gy, int gw, int gh,
			int wx, int wy) {
		c.gridx = gx;
		c.gridy = gy;
		c.gridwidth = gw;
		c.gridheight = gh;
		c.weightx = wx;
		c.weighty = wy;
	}

	private JPanel constructColorPanel() {
		GridBagLayout g = new GridBagLayout();
		JPanel colorPanel = new JPanel(g);
		colorPanel.setBorder(new TitledBorder("Colors"));
		Action backgroundAction = new AbstractAction("Set...") {

			public void actionPerformed(ActionEvent arg0) {
				pref.backgroundColor = JColorChooser.showDialog(
						GrafMainFrame.mainFrame, "Background Color",
						pref.backgroundColor);
				refresh();
			}
		};
		JButton background = new JButton(backgroundAction);
		Action foregroundAction = new AbstractAction("Set...") {

			public void actionPerformed(ActionEvent arg0) {
				pref.foregroundColor = JColorChooser.showDialog(
						GrafMainFrame.mainFrame, "Foreground Color",
						pref.foregroundColor);
				refresh();
			}
		};
		JButton foreground = new JButton(foregroundAction);
		Action subgraphAction = new AbstractAction("Set...") {

			public void actionPerformed(ActionEvent arg0) {
				pref.subgraphColor = JColorChooser.showDialog(
						GrafMainFrame.mainFrame, "Auxiliary Nodes Color",
						pref.subgraphColor);
				refresh();
			}
		};
		JButton subgraph = new JButton(subgraphAction);
		Action selectedAction = new AbstractAction("Set...") {

			public void actionPerformed(ActionEvent arg0) {
				pref.selectedColor = JColorChooser.showDialog(
						GrafMainFrame.mainFrame, "Selected Nodes Color",
						pref.selectedColor);
				refresh();
			}
		};
		JButton selected = new JButton(selectedAction);
		Action commentAction = new AbstractAction("Set...") {

			public void actionPerformed(ActionEvent arg0) {
				pref.commentColor = JColorChooser.showDialog(
						GrafMainFrame.mainFrame, "Comment Nodes Color",
						pref.commentColor);
				refresh();
			}
		};
		JButton comment = new JButton(commentAction);
		GridBagConstraints c = new GridBagConstraints();
		build(c, 0, 0, 1, 1, 60, 15);
		c.fill = GridBagConstraints.NONE;
		c.anchor = GridBagConstraints.EAST;
		JLabel label1 = new JLabel("  Background:  ", SwingConstants.LEFT);
		JLabel label2 = new JLabel("  Foreground:  ", SwingConstants.LEFT);
		JLabel label3 = new JLabel("  Auxiliary Nodes:  ", SwingConstants.LEFT);
		JLabel label4 = new JLabel("  Selected Nodes:  ", SwingConstants.LEFT);
		JLabel label5 = new JLabel("  Comment Nodes:  ", SwingConstants.LEFT);

		g.setConstraints(label1, c);
		colorPanel.add(label1);
		build(c, 1, 0, 1, 1, 20, 0);
		c.fill = GridBagConstraints.HORIZONTAL;
		g.setConstraints(color1, c);
		colorPanel.add(color1);
		build(c, 2, 0, 1, 1, 20, 0);
		c.fill = GridBagConstraints.HORIZONTAL;
		g.setConstraints(background, c);
		colorPanel.add(background);
		build(c, 0, 1, 1, 1, 60, 15);
		c.fill = GridBagConstraints.NONE;
		c.anchor = GridBagConstraints.EAST;
		g.setConstraints(label2, c);
		colorPanel.add(label2);
		build(c, 1, 1, 1, 1, 20, 0);
		c.fill = GridBagConstraints.HORIZONTAL;
		g.setConstraints(color2, c);
		colorPanel.add(color2);
		build(c, 2, 1, 1, 1, 20, 0);
		c.fill = GridBagConstraints.HORIZONTAL;
		g.setConstraints(foreground, c);
		colorPanel.add(foreground);
		build(c, 0, 2, 1, 1, 60, 15);
		c.fill = GridBagConstraints.NONE;
		c.anchor = GridBagConstraints.EAST;
		g.setConstraints(label3, c);
		colorPanel.add(label3);
		build(c, 1, 2, 1, 1, 20, 0);
		c.fill = GridBagConstraints.HORIZONTAL;
		g.setConstraints(color3, c);
		colorPanel.add(color3);
		build(c, 2, 2, 1, 1, 20, 0);
		c.fill = GridBagConstraints.HORIZONTAL;
		g.setConstraints(subgraph, c);
		colorPanel.add(subgraph);
		build(c, 0, 3, 1, 1, 60, 15);
		c.fill = GridBagConstraints.NONE;
		c.anchor = GridBagConstraints.EAST;
		g.setConstraints(label4, c);
		colorPanel.add(label4);
		build(c, 1, 3, 1, 1, 20, 0);
		c.fill = GridBagConstraints.HORIZONTAL;
		g.setConstraints(color4, c);
		colorPanel.add(color4);
		build(c, 2, 3, 1, 1, 20, 0);
		c.fill = GridBagConstraints.HORIZONTAL;
		g.setConstraints(selected, c);
		colorPanel.add(selected);
		build(c, 0, 4, 1, 1, 60, 15);
		c.fill = GridBagConstraints.NONE;
		c.anchor = GridBagConstraints.EAST;
		g.setConstraints(label5, c);
		colorPanel.add(label5);
		build(c, 1, 4, 1, 1, 20, 0);
		c.fill = GridBagConstraints.HORIZONTAL;
		g.setConstraints(color5, c);
		colorPanel.add(color5);
		build(c, 2, 4, 1, 1, 20, 0);
		c.fill = GridBagConstraints.HORIZONTAL;
		g.setConstraints(comment, c);
		colorPanel.add(comment);
		return colorPanel;
	}

	private JPanel constructAntialiasingPanel() {
		JPanel antialiasingPanel = new JPanel(new GridLayout(2, 1));
		JPanel temp = new JPanel(new BorderLayout());
		temp.setBorder(new TitledBorder("Antialiasing"));
		temp.add(antialiasingCheckBox, BorderLayout.CENTER);
		JPanel temp2 = new JPanel(new GridLayout(1, 5));
		ButtonGroup g = new ButtonGroup();
		g.add(westRadioBox);
		g.add(eastRadioBox);
		g.add(northRadioBox);
		g.add(southRadioBox);
		g.add(noneRadioBox);
		temp2.setBorder(new TitledBorder("Icon Bar Position"));
		temp2.add(westRadioBox);
		temp2.add(northRadioBox);
		temp2.add(eastRadioBox);
		temp2.add(southRadioBox);
		temp2.add(noneRadioBox);
		antialiasingPanel.add(temp);
		antialiasingPanel.add(temp2);
		return antialiasingPanel;
	}

	private JPanel constructFontPanel() {
		GridBagLayout g = new GridBagLayout();
		JPanel fontPanel = new JPanel(g);
		fontPanel.setBorder(new TitledBorder("Fonts"));
		GridBagConstraints c = new GridBagConstraints();
		Action inputAction = new AbstractAction("Input") {

			public void actionPerformed(ActionEvent arg0) {
				new FontMenu(true, true, pref);
			}
		};
		JButton input = new JButton(inputAction);
		Action outputAction = new AbstractAction("Output") {

			public void actionPerformed(ActionEvent arg0) {
				new FontMenu(false, true, pref);
				refresh();
			}
		};
		JButton output = new JButton(outputAction);
		build(c, 0, 0, 1, 1, 60, 15);
		c.fill = GridBagConstraints.BOTH;
		c.anchor = GridBagConstraints.WEST;
		g.setConstraints(input, c);
		fontPanel.add(input);
		build(c, 1, 0, 1, 1, 20, 0);
		c.fill = GridBagConstraints.VERTICAL;
		c.anchor = GridBagConstraints.WEST;
		g.setConstraints(inputLabel, c);
		fontPanel.add(inputLabel);
		build(c, 0, 1, 1, 1, 60, 15);
		c.fill = GridBagConstraints.BOTH;
		c.anchor = GridBagConstraints.WEST;
		g.setConstraints(output, c);
		fontPanel.add(output);
		build(c, 1, 1, 1, 1, 20, 0);
		c.fill = GridBagConstraints.VERTICAL;
		c.anchor = GridBagConstraints.WEST;
		g.setConstraints(outputLabel, c);
		fontPanel.add(outputLabel);
		return fontPanel;
	}

	private JPanel constructButtonPanel() {
		JPanel buttonPanel = new JPanel(new BorderLayout());
		buttonPanel.setBorder(new EmptyBorder(8, 5, 1, 1));
		Action resetAction = new AbstractAction("Reset to Default") {

			public void actionPerformed(ActionEvent arg0) {
				pref = Preferences.getCloneOfPreferences();
				refresh();
			}
		};
		JButton RESET_TO_DEFAULT = new JButton(resetAction);
		buttonPanel.add(RESET_TO_DEFAULT, BorderLayout.CENTER);
		return buttonPanel;
	}

	/**
	 * Refreshes the frame.
	 *  
	 */
	public void refresh() {
		textFont.setText("" + pref.textFont.getFontName() + "  "
				+ pref.textFontSize + "");
		concordanceFont.setText("" + pref.htmlFontName + "  "
				+ pref.htmlFontSize + "");
		inputLabel.setText("  " + pref.input.getFontName() + "  "
				+ pref.inputSize + "  ");
		outputLabel.setText("  " + pref.output.getFontName() + "  "
				+ pref.outputSize + "  ");
		color1.setBackground(pref.backgroundColor);
		color2.setBackground(pref.foregroundColor);
		color3.setBackground(pref.subgraphColor);
		color4.setBackground(pref.selectedColor);
		color5.setBackground(pref.commentColor);
		dateCheckBox.setSelected(pref.date);
		filenameCheckBox.setSelected(pref.filename);
		pathnameCheckBox.setSelected(pref.pathname);
		frameCheckBox.setSelected(pref.frame);
		rightToLeftCheckBox.setSelected(pref.rightToLeft);
		antialiasingCheckBox.setSelected(pref.antialiasing);
		if (pref.iconBarPosition.equals(Preferences.ICON_BAR_WEST)) {
			westRadioBox.setSelected(true);
		} else if (pref.iconBarPosition.equals(Preferences.ICON_BAR_EAST)) {
			eastRadioBox.setSelected(true);
		} else if (pref.iconBarPosition.equals(Preferences.ICON_BAR_NORTH)) {
			northRadioBox.setSelected(true);
		} else if (pref.iconBarPosition.equals(Preferences.ICON_BAR_SOUTH)) {
			southRadioBox.setSelected(true);
		} else if (pref.iconBarPosition.equals(Preferences.NO_ICON_BAR)) {
			noneRadioBox.setSelected(true);
		} else {
			westRadioBox.setSelected(true);
		}
		if (pref.htmlViewer == null) {
			htmlViewer.setText("");
		} else {
			htmlViewer.setText(pref.htmlViewer.getAbsolutePath());
		}
		maxTextFileSize.setText(pref.MAX_TEXT_FILE_SIZE / 1024);
		charByCharCheckBox.setSelected(pref.charByChar);
		if (pref.packagePath==null) {
			packageDirectory.setText("");
		}
		else {
			packageDirectory.setText(pref.packagePath.getAbsolutePath());
		}
		repaint();
	}

}
 /*
  * Unitex
  *
  * Copyright (C) 2001-2006 Universit� de Marne-la-Vall�e <unitex@univ-mlv.fr>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  * 
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  *
  */

package ndosownww.unitex.changes;

import java.awt.*;
import java.util.*;

import ndosownww.grafy.exceptions.*;

/**
 * This class describes a box of a graph.
 * 
 * @author S�bastien Paumier
 *  
 */
public class GraphBox extends GenericGraphBox {

	/**
	 * Constructs a new box
	 * 
	 * @param x
	 *            X coordinate of the input point of the box
	 * @param y
	 *            Y coordinate of the input point of the box
	 * @param type
	 *            indicates if the box is initial, final or normal
	 * @param p
	 *            component on which the box will be drawn
	 */
	public GraphBox(int x, int y, int type, GraphicalZone p) {
		super(x, y, type, p);
	}


	/*
	 * The following methods are used to manipulate the box text
	 *  
	 */

	private int test_transduction(char s[], int i) {
		int compteur;

		if (s[i] != '/')
			return 0;
		i--;
		compteur = 0;
		while (i >= 0 && s[i] == '\\') {
			compteur++;
			i--;
		}
		if ((compteur % 2) != 0)
			return 0;
		return 1;
	}

	private static boolean isAPlusChar(char c) {
		return (c == '+' || c == '\uff0b');
	}

	private void tokenizeTextWithoutTransduction(String s)
			throws BackSlashAtEndOfLineException, MissingGraphNameException,
			NoClosingQuoteException, NoClosingSupException,
			NoClosingRoundBracketException {
		int L = s.length(), i = 0;
		String tmp;
		char ligne[] = new char[10000];
		ligne = s.toCharArray();

		while (i < L) {
			tmp = "";
			if (ligne[i] == ':') {
				// case of a sub graph call
				i++;
				while ((i < L) && !isAPlusChar(ligne[i]) /* (ligne[i]!='+') */
				) {
					if (ligne[i] == '\\') {
						tmp = tmp.concat(String.valueOf(ligne[i++]));
						if (i >= L) {
							BackSlashAtEndOfLineException e = new BackSlashAtEndOfLineException();
							throw e;
						}
					}
					tmp = tmp.concat(String.valueOf(ligne[i++]));
				}
				if (tmp.length() == 0) {
					MissingGraphNameException e = new MissingGraphNameException();
					throw e;
				}
				// if we had a + separator char (even a japanese one), we put a
				// standard + instead
				if (i < L)
					ligne[i] = '+';
				i++;
				n_lines++;
				lines.add(tmp);
				greyed.add(new Boolean(true));
			} else {
				// all other cases
				while ((i < L) && !isAPlusChar(ligne[i]) /* (ligne[i]!='+') */
				) {
					if (ligne[i] == '"') {
						// case of a quote expression
						tmp = tmp.concat(String.valueOf(ligne[i++]));
						while ((i < L) && ligne[i] != '"') {
							if (ligne[i] == '\\') {
								tmp = tmp.concat(String.valueOf(ligne[i++]));
								if (i >= L) {
									BackSlashAtEndOfLineException e = new BackSlashAtEndOfLineException();
									throw e;
								}
							}
							tmp = tmp.concat(String.valueOf(ligne[i++]));
						}
						if (i >= L) {
							NoClosingQuoteException e = new NoClosingQuoteException();
							throw e;
						}
						tmp = tmp.concat(String.valueOf(ligne[i++]));
					} else if (ligne[i] == '<') {
						// case of a <...> expression
						tmp = tmp.concat(String.valueOf(ligne[i++]));
						while ((i < L) && ligne[i] != '>') {
							if (ligne[i] == '\\') {
								tmp = tmp.concat(String.valueOf(ligne[i++]));
								if (i >= L) {
									BackSlashAtEndOfLineException e = new BackSlashAtEndOfLineException();
									throw e;
								}
							}
							tmp = tmp.concat(String.valueOf(ligne[i++]));
						}
						if (i >= L) {
							NoClosingSupException e = new NoClosingSupException();
							throw e;
						}
						tmp = tmp.concat(String.valueOf(ligne[i++]));
					} else if (ligne[i] == '{') {
						// case of a {...} expression
						tmp = tmp.concat(String.valueOf(ligne[i++]));
						while ((i < L) && ligne[i] != '}') {
							if (ligne[i] == '\\') {
								tmp = tmp.concat(String.valueOf(ligne[i++]));
								if (i >= L) {
									BackSlashAtEndOfLineException e = new BackSlashAtEndOfLineException();
									throw e;
								}
							}
							tmp = tmp.concat(String.valueOf(ligne[i++]));
						}
						if (i >= L) {
							NoClosingRoundBracketException e = new NoClosingRoundBracketException();
							throw e;
						}
						tmp = tmp.concat(String.valueOf(ligne[i++]));
					} else {
						if (ligne[i] == '\\') {
							tmp = tmp.concat(String.valueOf(ligne[i++]));
							if (i >= L) {
								BackSlashAtEndOfLineException e = new BackSlashAtEndOfLineException();
								throw e;
							}
						}
						tmp = tmp.concat(String.valueOf(ligne[i++]));
					}
				}
				if (i < L)
					ligne[i] = '+';
				n_lines++;
				lines.add(tmp);
				greyed.add(new Boolean(false));
				i++;
			}
		}
	}


	private int maxVariableLineWidth() {
    if (context==null) {
       return 0;   
    }
		FontMetrics f = context.getFontMetrics(variableFont);
		return f.stringWidth("(");
	}

	private int maxContextMarkLineWidth(String mark) {
	    if (context==null) {
	       return 0;   
	    }
			FontMetrics f = context.getFontMetrics(variableFont);
			return f.stringWidth(mark);
		}

	/**
	 * Sets the box content.
	 * 
	 * @param s
	 *            the content
	 * @throws NoClosingQuoteException 
	 */
	public void setContent(String s) {
		if (type == 1)
			return; // nothing to do if we consider the final state
		content = s;
		char ligne[] = new char[10000];
		String tmp = "";
		int i, L;

		ligne = content.toCharArray();
		i = 0;
		L = content.length();
		if (ligne[0] == '$' && (ligne[L - 1] == '(' || ligne[L - 1] == ')')) {
			////////////////////////////////////////////
			// case of $a( or $a)
			////////////////////////////////////////////
			variable = true;
			lines.clear();
			greyed.clear();
			lines.add(String.valueOf(ligne[L - 1]));
			greyed.add(new Boolean(false));
			transduction = content.substring(1, L - 1);
			n_lines = 1;
			Height = get_h_variable_ligne() + 3;
			Width = maxVariableLineWidth() + 5;
			Y1 = Y - Height / 2;
			X_out = x + Width + 2;
			return;
		}
		variable = false;
		if (content.equals("$[") || content.equals("$![")
			|| content.equals("$]") || content.equals("$*")) {
			////////////////////////////////////////////
			// case of context marks ($[ or $![) :
			// ab $[ cd $]  => ab followed by cd
			// ab $![ cd $] => ab not followed by cd
			////////////////////////////////////////////
			contextMark = true;
			lines.clear();
			greyed.clear();
			String sub=content.substring(1);
			lines.add(sub);
			greyed.add(new Boolean(false));
			transduction = "";
			n_lines = 1;
			Height = get_h_variable_ligne() + 3;
			Width = maxContextMarkLineWidth(sub) + 5;
			Y1 = Y - Height / 2;
			X_out = x + Width + 2;
			return;
		}
		contextMark=false;
		if (content.equals("$<") || content.equals("$>")) {
				////////////////////////////////////////////
				// case of morphological mode marks ($< and $>)
				////////////////////////////////////////////
				morphologicalModeMark = true;
				lines.clear();
				greyed.clear();
				String sub=content.substring(1);
				lines.add(sub);
				greyed.add(new Boolean(false));
				transduction = "";
				n_lines = 1;
				Height = get_h_variable_ligne() + 3;
				Width = maxContextMarkLineWidth(sub) + 5;
				Y1 = Y - Height / 2;
				X_out = x + Width + 2;
				return;
			}
		morphologicalModeMark=false;
		while ((i != L) && (test_transduction(ligne, i) == 0))
			tmp = tmp.concat(String.valueOf(ligne[i++]));
		transduction = "";
		if (i != L) {
			i++;
			while (i != L)
				transduction = transduction.concat(String.valueOf(ligne[i++]));
		}
		n_lines = 0;
		lines.clear();
		greyed.clear();
		try {
			if (!tmp.equals("<E>"))
				tokenizeTextWithoutTransduction(tmp);
		} catch (BackSlashAtEndOfLineException e) {
			e.printStackTrace();
		} catch (MissingGraphNameException e) {
			e.printStackTrace();
		} catch (NoClosingQuoteException e) {
			e.printStackTrace();
		} catch (NoClosingRoundBracketException e) {
			e.printStackTrace();
		} catch (NoClosingSupException e) {
			e.printStackTrace();
		}
		if (!tmp.equals("<E>")) {
			// dimensions of a full box
			Width = maxLineWidth() + 10;
			Height = n_lines * get_h_ligne() + 6;
		} else {
			// dimensions of an empty box
			Height = 20;
			Width = 15;
		}
		Y1 = Y - Height / 2;
		X_out = x + Width + 5;
	}


	private int strcmp(String a, String b) {
		if (a.compareTo("<E>") == 0) {
			if (b.compareTo("<E>") == 0)
				return 0;
			return -1;
		}
		if (b.compareTo("<E>") == 0)
			return 1;
		return a.compareTo(b);
	}

	private int partition_pour_quicksort(ArrayList<String> v, ArrayList<Boolean> v2, int m, int n) {
		String pivot;
		String stringTmp;
		Boolean booleanTmp;
		int i = m - 1;
		int j = n + 1;
		pivot = v.get((m + n) / 2);
		while (true) {
			do
				j--;
			while ((j > (m - 1)) && (strcmp(pivot, v.get(j)) < 0));
			do
				i++;
			while ((i < n + 1) && (strcmp(v.get(i), pivot) < 0));
			if (i < j) {
				stringTmp = v.get(i);
				v.set(i,v.get(j));
				v.set(j,stringTmp);
				booleanTmp = v2.get(i);
				v2.set(i,v2.get(j));
				v2.set(j,booleanTmp);
			} else
				return j;
		}
	}

	private void quicksort(ArrayList<String> v, ArrayList<Boolean> v2, int m, int n) {
		int p;
		if (m < n) {
			p = partition_pour_quicksort(v, v2, m, n);
			quicksort(v, v2, m, p);
			quicksort(v, v2, p + 1, n);
		}
	}

	/**
	 * Sorts the lines of the box. If there is an output, it is not taken in
	 * account.
	 *  
	 */
	public void sortNodeLabel() {
		if (!lines.isEmpty()) {
			quicksort(lines, greyed, 0, lines.size() - 1);
			content = lines.get(0);
			for (int i = 1; i < lines.size(); i++) {
				content = content + "+" + lines.get(i);
			}
		}
	}

}

/* end of GraphBox */
/*
 * Unitex
 *
 * Copyright (C) 2001-2006 Universit� de Marne-la-Vall�e <unitex@univ-mlv.fr>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
 *
 */

package ndosownww.unitex.changes;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;

import javax.imageio.*;
import javax.imageio.stream.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.undo.*;

import toposlaw.ToposlawConfig;
import toposlaw.graphs.tools.unitex.NazwaGrafuTextField;
import toposlaw.model.ListaGrafowModel;
import toposlaw.multiflex.ExecutingMultiflex;




/**
 * This class describes a frame used to display and edit a graph.
 * 
 * @author S�bastien Paumier
 *  
 */
public class GraphFrame extends JInternalFrame {

	static int openFrameCount = 0;

	static final int offset = 30;

	/**
	 * Text field used to edit box content
	 */
	public TextField texte;

	/**
	 * Drawing area
	 */
	public GraphicalZone graphicalZone;

	/**
	 * The graph file
	 */
	private File grf;

	/**
	 * Indicates if the graph must be saved
	 */
	public boolean modified = false;

	/** undo redo manager */
	UndoManager manager;

	/** redo button */
	private JButton redoButton;

	/** undo button */
	private JButton undoButton;

	JScrollPane scroll;

	boolean nonEmptyGraph = false;

	/**
	 * Component used to listen frame changes. It is used to adapt the zoom
	 * factor to the frame's dimensions when the zoom mode is "Fit in Windows"
	 */
	public ComponentListener compListener = null;

	/**
	 * The frame's tool bar that contains icons
	 */
	private JToolBar myToolBar;

	/**
	 * Constructs a new <code>GraphFrame</code>
	 * 
	 * @param nonEmpty
	 *            indicates if the graph is non empty
	 */
	public GraphFrame(boolean nonEmpty) {
		super("", false, false, false, false);
		MyDropTarget.newDropTarget(this);
		nonEmptyGraph = nonEmpty;
		openFrameCount++;
		setTitle("Graph");
		JPanel mainPanel = new JPanel();
		mainPanel.setLayout(new BorderLayout());
		mainPanel.setBorder(new EmptyBorder(10, 10, 10, 10));

		JPanel top = new JPanel();
		top.setLayout(new BorderLayout());
	//	top.add(buildNazwaGrafuPanel(), BorderLayout.NORTH);
		top.add(buildTextPanel(), BorderLayout.NORTH);
		graphicalZone = new GraphicalZone(1188, 840, texte, this);
		graphicalZone.setPreferredSize(new Dimension(
				(int) (1188 * graphicalZone.scaleFactor),
				(int) (840 * graphicalZone.scaleFactor)));

		manager = new UndoManager();
		manager.setLimit(30);

		graphicalZone.addUndoableEditListener(manager);

		createToolBar();

		scroll = new JScrollPane(graphicalZone);
		scroll.setOpaque(true);
		scroll.getHorizontalScrollBar().setUnitIncrement(20);
		scroll.getVerticalScrollBar().setUnitIncrement(20);
		scroll.setPreferredSize(new Dimension(1188, 840));
		top.add(scroll, BorderLayout.CENTER);
		texte.setFont(graphicalZone.pref.input);
		if (!(graphicalZone.pref.iconBarPosition
				.equals(Preferences.NO_ICON_BAR))) {
			mainPanel.add(myToolBar, graphicalZone.pref.iconBarPosition);
		}
		mainPanel.add(top, BorderLayout.CENTER);
		setContentPane(mainPanel);
		pack();
		addInternalFrameListener(new MyInternalFrameListener());
//		setBounds(offset * (openFrameCount % 6), offset * (openFrameCount % 6),
	//			800 + 40, 600 + 80);
		setBounds(0,0,1000,660);
		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
	}

	private JPanel buildNazwaGrafuPanel() {
		JPanel p = new JPanel(new BorderLayout());
		NazwaGrafuTextField text = new NazwaGrafuTextField(25, this);
		p.add(text);
		return p;
	}


	private void createToolBar() {
		myToolBar = new JToolBar("Tools");
		if (Preferences.getCloneOfPreferences().iconBarPosition
				.equals(Preferences.ICON_BAR_WEST)
				|| Preferences.getCloneOfPreferences().iconBarPosition
						.equals(Preferences.ICON_BAR_EAST)) {
			myToolBar.setOrientation(SwingConstants.VERTICAL);
		} else {
			myToolBar.setOrientation(SwingConstants.HORIZONTAL);
		}
		myToolBar.setMargin(new Insets(0, 0, 0, 0));
		JButton save = new JButton(MyCursors.saveIcon);
		save.setMaximumSize(new Dimension(36, 36));
		save.setMinimumSize(new Dimension(36, 36));
		save.setPreferredSize(new Dimension(36, 36));
		JButton compile = new JButton(MyCursors.compilationIcon);
		compile.setMaximumSize(new Dimension(36, 36));
		compile.setMinimumSize(new Dimension(36, 36));
		compile.setPreferredSize(new Dimension(36, 36));

		JButton copy = new JButton(MyCursors.copyIcon);
		JButton cut = new JButton(MyCursors.cutIcon);
		JButton paste = new JButton(MyCursors.pasteIcon);
		copy.setMaximumSize(new Dimension(36, 36));
		cut.setMaximumSize(new Dimension(36, 36));
		paste.setMaximumSize(new Dimension(36, 36));
		copy.setMinimumSize(new Dimension(36, 36));
		cut.setMinimumSize(new Dimension(36, 36));
		paste.setMinimumSize(new Dimension(36, 36));
		copy.setPreferredSize(new Dimension(36, 36));
		cut.setPreferredSize(new Dimension(36, 36));
		paste.setPreferredSize(new Dimension(36, 36));

		redoButton = new JButton(MyCursors.redoIcon);
		undoButton = new JButton(MyCursors.undoIcon);
		redoButton.setToolTipText("Redo");
		undoButton.setToolTipText("Undo");

		redoButton.addActionListener(new RedoIt());
		redoButton.setMaximumSize(new Dimension(36, 36));
		redoButton.setMinimumSize(new Dimension(36, 36));
		redoButton.setPreferredSize(new Dimension(36, 36));

		undoButton.addActionListener(new UndoIt());
		undoButton.setMaximumSize(new Dimension(36, 36));
		undoButton.setMinimumSize(new Dimension(36, 36));
		undoButton.setPreferredSize(new Dimension(36, 36));

		JToggleButton normal = new JToggleButton(MyCursors.arrowIcon);
		normal.setMaximumSize(new Dimension(36, 36));
		normal.setMinimumSize(new Dimension(36, 36));
		normal.setPreferredSize(new Dimension(36, 36));

		JToggleButton create = new JToggleButton(MyCursors.createBoxesIcon);
		create.setMaximumSize(new Dimension(36, 36));
		create.setMinimumSize(new Dimension(36, 36));
		create.setPreferredSize(new Dimension(36, 36));
		JToggleButton kill = new JToggleButton(MyCursors.killBoxesIcon);
		kill.setMaximumSize(new Dimension(36, 36));
		kill.setMinimumSize(new Dimension(36, 36));
		kill.setPreferredSize(new Dimension(36, 36));
		JToggleButton link = new JToggleButton(MyCursors.linkBoxesIcon);
		link.setMaximumSize(new Dimension(36, 36));
		link.setMinimumSize(new Dimension(36, 36));
		link.setPreferredSize(new Dimension(36, 36));
		JToggleButton reverseLink = new JToggleButton(
				MyCursors.reverseLinkBoxesIcon);
		reverseLink.setMaximumSize(new Dimension(36, 36));
		reverseLink.setMinimumSize(new Dimension(36, 36));
		reverseLink.setPreferredSize(new Dimension(36, 36));
		JToggleButton openSubgraph = new JToggleButton(
				MyCursors.openSubgraphIcon);
		openSubgraph.setMaximumSize(new Dimension(36, 36));
		openSubgraph.setMinimumSize(new Dimension(36, 36));
		openSubgraph.setPreferredSize(new Dimension(36, 36));

		JButton configuration = new JButton(MyCursors.configurationIcon);
		configuration.setMaximumSize(new Dimension(36, 36));
		configuration.setMinimumSize(new Dimension(36, 36));
		configuration.setPreferredSize(new Dimension(36, 36));

		save.setToolTipText("Save graph");
		compile.setToolTipText("Compile graph");

		copy.setToolTipText("Copy");
		cut.setToolTipText("Cut");
		paste.setToolTipText("Paste");

		normal.setToolTipText("Normal editing mode");
		create.setToolTipText("Create a new box");
		kill.setToolTipText("Remove a box");
		link.setToolTipText("Link boxes");
		reverseLink.setToolTipText("Reversed link between boxes");
		openSubgraph.setToolTipText("Open a sub-graph");

		configuration.setToolTipText("Graph configuration");

		save.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				String grafName = 
					GrafMainFrame.mainFrame.getKodNazwy() +
					NazwaGrafuTextField.getInstance().getText();
				if (ListaGrafowModel.getModel().czyGrafIstnieje(grafName) 
						&& GrafMainFrame.mainFrame.mode!=GrafMainFrame.MODE_EDYTUJ 
						&& GrafMainFrame.mainFrame.mode!=GrafMainFrame.MODE_PODGLAD) {
					
					JOptionPane.showMessageDialog(GrafMainFrame.mainFrame,
				    "Graf o takiej nazwie już istnieje w słowniku.\n"+
				    "Graf nie został nadpisany. Proszę zmienić nazwę.",
				    "Wiadomość", //$NON-NLS-1$
				    JOptionPane.PLAIN_MESSAGE);
					return;
					
				}
				GrafMainFrame.mainFrame.mySaveGraph(new File(ToposlawConfig.getGraphDir()+grafName+".grf"));
				NazwaGrafuTextField.getInstance().initText(NazwaGrafuTextField.getInstance().getText());
			}
		});
		compile.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
						GrafMainFrame.mainFrame.myCompileGraph();
						System.out.println("Tuuu");
			}
		});
		copy.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				final ActionEvent E = e;
				SwingUtilities.invokeLater(new Runnable() {
					public void run() {
						((TextField) graphicalZone.texte).specialCopy
								.actionPerformed(E);
						repaint();
					}
				});
			}
		});
		cut.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				final ActionEvent E = e;
				SwingUtilities.invokeLater(new Runnable() {
					public void run() {
						((TextField) graphicalZone.texte).cut
								.actionPerformed(E);
						repaint();
					}
				});
			}
		});
		paste.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				final ActionEvent E = e;
				SwingUtilities.invokeLater(new Runnable() {
					public void run() {
						((TextField) graphicalZone.texte).specialPaste
								.actionPerformed(E);
						repaint();
					}
				});
			}
		});
		normal.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				graphicalZone.setCursor(MyCursors.normalCursor);
				graphicalZone.EDITING_MODE = MyCursors.NORMAL;
				repaint();
			}
		});
		create.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				graphicalZone.setCursor(MyCursors.createBoxesCursor);
				graphicalZone.EDITING_MODE = MyCursors.CREATE_BOXES;
				repaint();
			}
		});
		kill.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				graphicalZone.setCursor(MyCursors.killBoxesCursor);
				graphicalZone.EDITING_MODE = MyCursors.KILL_BOXES;
				graphicalZone.unSelectAllBoxes();
				texte.validateTextField();
			}
		});
		link.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				graphicalZone.setCursor(MyCursors.linkBoxesCursor);
				graphicalZone.EDITING_MODE = MyCursors.LINK_BOXES;
				repaint();
			}
		});
		reverseLink.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				graphicalZone.setCursor(MyCursors.reverseLinkBoxesCursor);
				graphicalZone.EDITING_MODE = MyCursors.REVERSE_LINK_BOXES;
				repaint();
			}
		});
		openSubgraph.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				graphicalZone.setCursor(MyCursors.openSubgraphCursor);
				graphicalZone.EDITING_MODE = MyCursors.OPEN_SUBGRAPH;
				texte.validateTextField();
			}
		});
		configuration.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				SwingUtilities.invokeLater(new Runnable() {
					public void run() {
						new GraphPresentationMenu();
					}
				});
			}
		});

		ButtonGroup bg = new ButtonGroup();
		bg.add(normal);
		bg.add(create);
		bg.add(kill);
		bg.add(link);
		bg.add(reverseLink);
		bg.add(openSubgraph);

		normal.setSelected(true);
		myToolBar.add(save);
		myToolBar.add(compile);

		myToolBar.addSeparator();
		myToolBar.addSeparator();

		myToolBar.add(copy);
		myToolBar.add(cut);
		myToolBar.add(paste);
		myToolBar.add(redoButton);
		myToolBar.add(undoButton);

		myToolBar.addSeparator();
		myToolBar.addSeparator();

		myToolBar.add(normal);
		myToolBar.add(create);
		myToolBar.add(kill);
		myToolBar.add(link);
		myToolBar.add(reverseLink);
		myToolBar.add(openSubgraph);

		myToolBar.addSeparator();
		myToolBar.addSeparator();

		myToolBar.add(configuration);
	}

	private JPanel buildTextPanel() {
		JPanel p = new JPanel(new BorderLayout());
		NazwaGrafuTextField text = new NazwaGrafuTextField(25, this);
		
		JLabel nazwaGrafuLabel = new JLabel("Nazwa grafu : " + GrafMainFrame.mainFrame.getKodNazwy());
		Dimension dim = nazwaGrafuLabel.getPreferredSize();
		nazwaGrafuLabel.setPreferredSize(new Dimension(dim.width+10,dim.height));
		texte = new TextField(25, this);
		p.add(nazwaGrafuLabel,BorderLayout.LINE_START);
		
		p.add(text,BorderLayout.CENTER);
		p.add(texte,BorderLayout.PAGE_END);
		return p;
	}

	class MyInternalFrameListener extends InternalFrameAdapter {

		public void internalFrameActivated(InternalFrameEvent e) {
			texte.requestFocus();
			texte.getCaret().setVisible(true);
		}

		public void internalFrameClosing(InternalFrameEvent e) {
			if (modified) {
				Object[] options_on_exit = { "Save", "Don't save" };
				Object[] normal_options = { "Save", "Don't save", "Cancel" };
				int n;
				if (GrafMainFrame.closing) {
					n = JOptionPane
							.showOptionDialog(
									GraphFrame.this,
									"Graph has been modified. Do you want to save it ?",
									"", JOptionPane.YES_NO_CANCEL_OPTION,
									JOptionPane.QUESTION_MESSAGE, null,
									options_on_exit, options_on_exit[0]);
				} else {
					n = JOptionPane
							.showOptionDialog(
									GraphFrame.this,
									"Graph has been modified. Do you want to save it ?",
									"", JOptionPane.YES_NO_CANCEL_OPTION,
									JOptionPane.QUESTION_MESSAGE, null,
									normal_options, normal_options[0]);
				}
				if (n == JOptionPane.CLOSED_OPTION)
					return;
				/*
				if (n == 0) {
					if (!GrafMainFrame.mainFrame.saveGraph(GraphFrame.this))
						return;
				}*/
				if (n != 2) {
					GraphFrame.this.setVisible(false);
					GraphFrame.this.dispose();
					return;
				}
				GraphFrame.this.setVisible(true);
				try {
					GraphFrame.this.setSelected(true);
					GraphFrame.this.setIcon(false);
				} catch (java.beans.PropertyVetoException e2) {
					e2.printStackTrace();
				}
				return;
			}
			GraphFrame.this.setVisible(false);
			GrafMainFrame.removeInternalFrame(GraphFrame.this);
		}
	}

	/**
	 * Resizes the drawing area
	 * 
	 * @param x
	 * @param y
	 */
	public void reSizeGraphicalZone(int x, int y) {
		graphicalZone.Width = x;
		graphicalZone.Height = y;
		graphicalZone.setPreferredSize(new Dimension(x, y));
		graphicalZone.revalidate();
		graphicalZone.repaint();
	}

	/**
	 * Sets the <code>modified</code> field
	 * 
	 * @param b
	 *            <code>true</code> if the graph must be marked as modified,
	 *            <code>false</code> otherwise
	 */
	public void setModified(boolean b) {
		modified = b;
		if (grf != null) {
			if (modified)
				setTitle(grf.getName() + " (Unsaved)");
			else
				setTitle(grf.getName());
		} else {
			if (modified)
				setTitle(" (Unsaved)");
			else
				setTitle("Graph");
		}
	}

	/**
	 * Sets the zoom scale factor
	 * 
	 * @param d
	 *            scale factor
	 */
	public void setScaleFactor(double d) {
		graphicalZone.scaleFactor = d;
		graphicalZone.setPreferredSize(new Dimension(
				(int) (graphicalZone.Width * graphicalZone.scaleFactor),
				(int) (graphicalZone.Height * graphicalZone.scaleFactor)));
		graphicalZone.revalidate();
		graphicalZone.repaint();
	}

	/**
	 * Sorts lines of all selected boxes
	 *  
	 */
	public void sortNodeLabel() {
		if (graphicalZone.selectedBoxes.isEmpty())
			return;
		for (int i = 0; i < graphicalZone.selectedBoxes.size(); i++) {
			GraphBox g = (GraphBox) graphicalZone.selectedBoxes.get(i);
			g.sortNodeLabel();
		}
		graphicalZone.unSelectAllBoxes();
		texte.initText("");
		graphicalZone.repaint();
	}

	/**
	 * Inverts the antialiasing flag
	 *  
	 */
	public void changeAntialiasingValue() {
		graphicalZone.pref.antialiasing = !graphicalZone.pref.antialiasing;
		graphicalZone.repaint();
	}

	/**
	 *  
	 */
	private void updateDoUndoButtons() {

		if (undoButton != null && redoButton != null) {
			undoButton.setEnabled(manager.canUndo());
			redoButton.setEnabled(manager.canRedo());
		}

	}

	class UndoIt implements ActionListener {
		public void actionPerformed(ActionEvent ev) {
			try {
				manager.undo();
			} catch (CannotUndoException ex) {
				ex.printStackTrace();
			} finally {
				repaint();
			}
		}

	}

	class RedoIt implements ActionListener {
		public void actionPerformed(ActionEvent ev) {
			try {
				manager.redo();
			} catch (CannotRedoException ex) {
				ex.printStackTrace();
			} finally {
				repaint();
			}
		}
	}

	public void repaint() {
		super.repaint();
		updateDoUndoButtons();
	}

	public void setRedoEnabled(boolean b) {
		redoButton.setEnabled(b);
	}

	public void setUndoEnabled(boolean b) {
		undoButton.setEnabled(b);
	}

	public File getGraph() {
		return grf;
	}

	public void setGraph(File grf) {
		this.grf = grf;
		this.setTitle(grf.getName());
	}

	public void saveGraphAsAnImage(File output) {
		BufferedImage image=new BufferedImage(graphicalZone.Width,graphicalZone.Height,BufferedImage.TYPE_INT_RGB);
		Graphics g=image.getGraphics();
		graphicalZone.paintAll(g);
		try {
			ImageOutputStream stream=ImageIO.createImageOutputStream(output);
			ImageIO.write(image,"png",stream);
			stream.close();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		g.dispose();
	}
	
} /* end of GraphFrame */
 /*
  * Unitex
  *
  * Copyright (C) 2001-2006 Universit� de Marne-la-Vall�e <unitex@univ-mlv.fr>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  * 
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  *
  */

package ndosownww.unitex.changes;

import java.awt.*;
import java.io.*;
import java.util.*;

import javax.swing.*;

import ndosownww.grafy.exceptions.*;
import ndosownww.grafy.*;


/**
 * This class provides methods for loading and saving graphs.
 * @author S�bastien Paumier
 *
 */
public class GraphIO {

   /**
    * Boxes of a graph 
    */
   public ArrayList<GenericGraphBox> boxes;

   /**
    * Rendering properties of a graph 
    */
   public Preferences pref= new Preferences();

   /**
    * Width of a graph 
    */
   public int width;

   /**
    * Height of a graph 
    */
   public int height;

   /**
    * Number of boxes of a graph 
    */
   public int nBoxes;

   /**
    * This method loads a graph. 
    * @param grfFile name of the graph 
    * @return a <code>GraphIO</code> object describing the graph
    */
   public static GraphIO loadGraph(File grfFile) {
      GraphIO res= new GraphIO();
      FileInputStream source;
      if (!grfFile.exists()) {
         JOptionPane.showMessageDialog(
            null,
            "Cannot find " + grfFile.getAbsolutePath(),
            "Error",
            JOptionPane.ERROR_MESSAGE);
         return null;
      }
      if (!grfFile.canRead()) {
         JOptionPane.showMessageDialog(
            null,
            "Cannot read " + grfFile.getAbsolutePath(),
            "Error",
            JOptionPane.ERROR_MESSAGE);
         return null;
      }
      if (grfFile.length() <= 2) {
         JOptionPane.showMessageDialog(
            null,
            grfFile.getAbsolutePath() + " is empty",
            "Error",
            JOptionPane.ERROR_MESSAGE);
         return null;
      }
      try {
         source= UnicodeIO.openUnicodeLittleEndianFileInputStream(grfFile);
         UnicodeIO.skipLine(source); // ignoring #...
         res.readSize(source);
         res.readInputFont(source);
         res.readOutputFont(source);
         res.readBackgroundColor(source);
         res.readForegroundColor(source);
         res.readSubgraphColor(source);
         res.readCommentColor(source);
         res.readSelectedColor(source);
         UnicodeIO.skipLine(source); // ignoring DBOXES
         res.readDrawFrame(source);
         res.readDate(source);
         res.readFile(source);
         res.readDirectory(source);
         res.readRightToLeft(source);
         UnicodeIO.skipLine(source); // ignoring DRST
         UnicodeIO.skipLine(source); // ignoring FITS
         UnicodeIO.skipLine(source); // ignoring PORIENT
         UnicodeIO.skipLine(source); // ignoring #
         res.readBoxNumber(source);
         res.boxes= new ArrayList<GenericGraphBox>();
         // adding initial state
         res.boxes.add(new GraphBox(0, 0, 0,null));
         // adding final state
         res.boxes.add(new GraphBox(0, 0, 1, null));
         // adding other states
         for (int i= 2; i < res.nBoxes; i++)
            res.boxes.add(new GraphBox(0, 0, 2, null));
         for (int i= 0; i < res.nBoxes; i++)
            res.readGraphLine(source, i);
         source.close();
      } catch (NotAUnicodeLittleEndianFileException e) {
         JOptionPane.showMessageDialog(
            null,
            grfFile.getAbsolutePath() + " is not a Unicode Little-Endian graph",
            "Error",
            JOptionPane.ERROR_MESSAGE);
         return null;
      } catch (FileNotFoundException e) {
         e.printStackTrace();
         return null;
      } catch (IOException e) {
         e.printStackTrace();
         return null;
      }
      return res;
   }

   private void readSize(FileInputStream f) {
      // skipping the chars preceeding the width and height
      UnicodeIO.skipChars(f, 5);
      char c;
      // reading width
      width= 0;
      while (UnicodeIO.isDigit((c= (char)UnicodeIO.readChar(f))))
         width= width * 10 + (c - '0');
      // reading height
      while (UnicodeIO.isDigit((c= (char)UnicodeIO.readChar(f))))
         height= height * 10 + (c - '0');
   }

   private void readInputFont(FileInputStream f) {
      UnicodeIO.skipChars(f, 5);
      String s= "";
      char c;
      while ((c= (char)UnicodeIO.readChar(f)) != ':')
         s= s + c;
      boolean bold= (UnicodeIO.readChar(f) == 'B');
      boolean italic= (UnicodeIO.readChar(f) == 'I');
      int size= 0;
      while (UnicodeIO.isDigit((c= (char)UnicodeIO.readChar(f))))
         size= size * 10 + (c - '0');
      pref.inputSize= size;
      int style;
      if (bold && italic)
         style= Font.BOLD | Font.ITALIC;
      else
         if (bold)
            style= Font.BOLD;
         else
            if (italic)
               style= Font.ITALIC;
            else
               style= Font.PLAIN;
      pref.input= new Font(s, style, (int) (size / 0.72));
   }

   private void readOutputFont(FileInputStream f) {
      UnicodeIO.skipChars(f, 6);
      String s= "";
      char c;
      while ((c= (char)UnicodeIO.readChar(f)) != ':')
         s= s + c;
      boolean bold= (UnicodeIO.readChar(f) == 'B');
      boolean italic= (UnicodeIO.readChar(f) == 'I');
      int size= 0;
      while (UnicodeIO.isDigit((c= (char)UnicodeIO.readChar(f))))
         size= size * 10 + (c - '0');
      pref.outputSize= size;
      int style;
      if (bold && italic)
         style= Font.BOLD | Font.ITALIC;
      else
         if (bold)
            style= Font.BOLD;
         else
            if (italic)
               style= Font.ITALIC;
            else
               style= Font.PLAIN;
      pref.output= new Font(s, style, (int) (size / 0.72));
   }

   private void readBackgroundColor(FileInputStream f) {
      UnicodeIO.skipChars(f, 7);
      char c;
      int n= 0;
      while (UnicodeIO.isDigit((c= (char)UnicodeIO.readChar(f))))
         n= n * 10 + (c - '0');
      pref.backgroundColor= new Color(n);
   }

   private void readForegroundColor(FileInputStream f) {
      UnicodeIO.skipChars(f, 7);
      char c;
      int n= 0;
      while (UnicodeIO.isDigit((c= (char)UnicodeIO.readChar(f))))
         n= n * 10 + (c - '0');
      pref.foregroundColor= new Color(n);
   }

   private void readSubgraphColor(FileInputStream f) {
      UnicodeIO.skipChars(f, 7);
      char c;
      int n= 0;
      while (UnicodeIO.isDigit((c= (char)UnicodeIO.readChar(f))))
         n= n * 10 + (c - '0');
      pref.subgraphColor= new Color(n);
   }

   private void readSelectedColor(FileInputStream f) {
      UnicodeIO.skipChars(f, 7);
      char c;
      int n= 0;
      while (UnicodeIO.isDigit((c= (char)UnicodeIO.readChar(f))))
         n= n * 10 + (c - '0');
      pref.selectedColor= new Color(n);
   }

   private void readCommentColor(FileInputStream f) {
      UnicodeIO.skipChars(f, 7);
      char c;
      int n= 0;
      while (UnicodeIO.isDigit((c= (char)UnicodeIO.readChar(f))))
         n= n * 10 + (c - '0');
      pref.commentColor= new Color(n);
   }

   private void readDrawFrame(FileInputStream f) {
      UnicodeIO.skipChars(f, 7);
      pref.frame= (UnicodeIO.readChar(f) == 'y');
      UnicodeIO.readChar(f);
   }

   private void readDate(FileInputStream f) {
      UnicodeIO.skipChars(f, 6);
      pref.date= (UnicodeIO.readChar(f) == 'y');
      UnicodeIO.readChar(f);
   }

   private void readFile(FileInputStream f) {
      UnicodeIO.skipChars(f, 6);
      pref.filename= (UnicodeIO.readChar(f) == 'y');
      UnicodeIO.readChar(f);
   }

   private void readDirectory(FileInputStream f) {
      UnicodeIO.skipChars(f, 5);
      pref.pathname= (UnicodeIO.readChar(f) == 'y');
      UnicodeIO.readChar(f);
   }

   private void readRightToLeft(FileInputStream f) {
      UnicodeIO.skipChars(f, 5);
      pref.rightToLeft= (UnicodeIO.readChar(f) == 'y');
      UnicodeIO.readChar(f);
   }

   private void readBoxNumber(FileInputStream f) {
      char c;
      nBoxes= 0;
      while (UnicodeIO.isDigit((c= (char)UnicodeIO.readChar(f))))
         nBoxes= nBoxes * 10 + (c - '0');
   }

   private void readGraphLine(FileInputStream f, int n) {
      GenericGraphBox g= boxes.get(n);
      if (UnicodeIO.readChar(f) == 's') {
         // is a "s" was read, then we read the " char
         UnicodeIO.readChar(f);
      }
      String s= "";
      char c;
      while ((c= (char)UnicodeIO.readChar(f)) != '"') {
         if (c == '\\') {
            c= (char)UnicodeIO.readChar(f);
            if (c != '\\') {
               // case of \: \+ and \"
               if (c == '"')
                  s= s + c;
               else
                  s= s + "\\" + c;
            } else {
               // case of \\\" that must be transformed into \"
               c= (char)UnicodeIO.readChar(f);
               if (c == '\\') {
                  // we are in the case \\\" -> \"
                  c= (char)UnicodeIO.readChar(f);
                  s= s + "\\" + c;
               } else {
                  // we are in the case \\a -> \\a
                  s= s + "\\\\";
                  if (c!='"') s=s+c;
                  else break;
               }
            }
         } else
            s= s + c;
      }
      // skipping the space after "
      UnicodeIO.readChar(f);
      // reading the X coordinate
      int x= 0;
      int neg= 1;
      c= (char)UnicodeIO.readChar(f);
      if (c == '-') {
         neg= -1;
      } else
         if (UnicodeIO.isDigit(c)) {
            x= (c - '0');
         }
      while (UnicodeIO.isDigit((c= (char)UnicodeIO.readChar(f)))) {
         x= x * 10 + (c - '0');
      }
      x=x*neg;
      // reading the Y coordinate
      int y= 0;
      neg=1;
      c= (char)UnicodeIO.readChar(f);
            if (c == '-') {
               neg= -1;
            } else
               if (UnicodeIO.isDigit(c)) {
                  y= (c - '0');
               }
      while (UnicodeIO.isDigit((c= (char)UnicodeIO.readChar(f)))) {
         y= y * 10 + (c - '0');
      }
      y=y*neg;
      g.setX(x);
      g.setY(y);
      g.setX1(g.getX());
      g.setY1(g.getY());
      g.setX_in(g.getX());
      g.setY_in(g.getY());
      g.setX_out(g.getX() + g.getWidth() + 5);
      g.setY_out(g.getY_in());
      if (n != 1) {
         // 1 is the final state, which content is <E>
         g.setContent(s);
         // we will need to call g.update() to size the box according to the text
      } else {
         g.setContent("<E>");
         g.setX_in(g.getX());
         g.setY_in(g.getY());
         g.setX1(g.getX());
         g.setY1(g.getY() - 10);
         g.setY_out(g.getY_in());
         g.setX_out(g.getX_in() + 25);
      }
      int trans= 0;
      while (UnicodeIO.isDigit((c= (char)UnicodeIO.readChar(f))))
         trans= trans * 10 + (c - '0');
      for (int j= 0; j < trans; j++) {
         int dest= 0;
         while (UnicodeIO.isDigit((c= (char)UnicodeIO.readChar(f))))
            dest= dest * 10 + (c - '0');
         g.addTransitionTo(boxes.get(dest));
      }
      // skipping the end-of-line
      UnicodeIO.readChar(f);
   }

   /**
    * Saves the graph referenced by the field of this <code>GraphIO</code> object
    * @param grfFile graph file
    */
   public void saveGraph(File grfFile) {
      FileOutputStream dest;
      try {
         if (!grfFile.exists())
            grfFile.createNewFile();
      } catch (IOException e) {
         JOptionPane.showMessageDialog(
            null,
            "Cannot write " + grfFile.getAbsolutePath(),
            "Error",
            JOptionPane.ERROR_MESSAGE);
         return;
      }
      if (!grfFile.canWrite()) {
         JOptionPane.showMessageDialog(
            null,
            "Cannot write " + grfFile.getAbsolutePath(),
            "Error",
            JOptionPane.ERROR_MESSAGE);
         return;
      }
      try {
         dest= new FileOutputStream(grfFile);
         UnicodeIO.writeChar(dest, (char)0xFEFF);
         UnicodeIO.writeString(dest, "#Unigraph\n");
         UnicodeIO.writeString(
            dest,
            "SIZE "
               + String.valueOf(width)
               + " "
               + String.valueOf(height)
               + "\n");
         UnicodeIO.writeString(dest, "FONT " + pref.input.getName() + ":");
         if (pref.input.getStyle() == Font.PLAIN)
            UnicodeIO.writeString(dest, "  ");
         else
            if (pref.input.getStyle() == Font.BOLD)
               UnicodeIO.writeString(dest, "B ");
            else
               if (pref.input.getStyle() == Font.ITALIC)
                  UnicodeIO.writeString(dest, " I");
               else
                  UnicodeIO.writeString(dest, "BI");
         UnicodeIO.writeString(dest, String.valueOf(pref.inputSize) + "\n");
         UnicodeIO.writeString(dest, "OFONT " + pref.output.getName() + ":");
         if (pref.output.getStyle() == Font.PLAIN)
            UnicodeIO.writeString(dest, "  ");
         else
            if (pref.output.getStyle() == Font.BOLD)
               UnicodeIO.writeString(dest, "B ");
            else
               if (pref.output.getStyle() == Font.ITALIC)
                  UnicodeIO.writeString(dest, " I");
               else
                  UnicodeIO.writeString(dest, "BI");
         UnicodeIO.writeString(dest, String.valueOf(pref.outputSize) + "\n");
         UnicodeIO.writeString(
            dest,
            "BCOLOR "
               + String.valueOf(16777216 + pref.backgroundColor.getRGB())
               + "\n");
         UnicodeIO.writeString(
            dest,
            "FCOLOR "
               + String.valueOf(16777216 + pref.foregroundColor.getRGB())
               + "\n");
         UnicodeIO.writeString(
            dest,
            "ACOLOR "
               + String.valueOf(16777216 + pref.subgraphColor.getRGB())
               + "\n");
         UnicodeIO.writeString(
            dest,
            "SCOLOR "
               + String.valueOf(16777216 + pref.commentColor.getRGB())
               + "\n");
         UnicodeIO.writeString(
            dest,
            "CCOLOR "
               + String.valueOf(16777216 + pref.selectedColor.getRGB())
               + "\n");
         UnicodeIO.writeString(dest, "DBOXES y\n");
         if (pref.frame)
            UnicodeIO.writeString(dest, "DFRAME y\n");
         else
            UnicodeIO.writeString(dest, "DFRAME n\n");
         if (pref.date)
            UnicodeIO.writeString(dest, "DDATE y\n");
         else
            UnicodeIO.writeString(dest, "DDATE n\n");
         if (pref.filename)
            UnicodeIO.writeString(dest, "DFILE y\n");
         else
            UnicodeIO.writeString(dest, "DFILE n\n");
         if (pref.pathname)
            UnicodeIO.writeString(dest, "DDIR y\n");
         else
            UnicodeIO.writeString(dest, "DDIR n\n");
         if (pref.rightToLeft)
            UnicodeIO.writeString(dest, "DRIG y\n");
         else
            UnicodeIO.writeString(dest, "DRIG n\n");
         UnicodeIO.writeString(dest, "DRST n\n");
         UnicodeIO.writeString(dest, "FITS 100\n");
         UnicodeIO.writeString(dest, "PORIENT L\n");
         UnicodeIO.writeString(dest, "#\n");
         nBoxes= boxes.size();
         UnicodeIO.writeString(dest, String.valueOf(nBoxes) + "\n");
         for (int i= 0; i < nBoxes; i++) {
            GenericGraphBox g= boxes.get(i);
            UnicodeIO.writeChar(dest, '"');
            if (g.getType() != 1)
               write_content(dest, g.getContent());
            int N= g.getTransitions().size();
            UnicodeIO.writeString(
               dest,
               "\" "
                  + String.valueOf(g.getX())
                  + " "
                  + String.valueOf(g.getY())
                  + " "
                  + String.valueOf(N)
                  + " ");
            for (int j= 0; j < N; j++) {
               GenericGraphBox tmp= (GenericGraphBox)g.getTransitions().get(j);
               UnicodeIO.writeString(
                  dest,
                  String.valueOf(boxes.indexOf(tmp)) + " ");
            }
            UnicodeIO.writeChar(dest, '\n');
         }
         dest.close();
      } catch (FileNotFoundException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      }
   }

   private void write_content(FileOutputStream f, String s) {
      int L= s.length();
      char c;
      for (int i= 0; i < L; i++) {
         c= s.charAt(i);
         if (c == '"') {
            // case of char "
            if (i == 0 || s.charAt(i - 1) != '\\') {
               // the " is the "abc" one; it must be saved as \"
               UnicodeIO.writeChar(f, '\\');
               UnicodeIO.writeChar(f, '"');
            } else {
               // it is the \" char that must be saved as \\\"
               // we only write 2 \ because the third has been saved at the pos i-1
               UnicodeIO.writeChar(f, '\\');
               UnicodeIO.writeChar(f, '\\');
               UnicodeIO.writeChar(f, '"');
            }
         } else {
            UnicodeIO.writeChar(f, c);
         }
      }
   }

}
 /*
  * Unitex
  *
  * Copyright (C) 2001-2006 Universit� de Marne-la-Vall�e <unitex@univ-mlv.fr>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  * 
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  *
  */

package ndosownww.unitex.changes;

import java.util.*;

/**
 * This class is used to create a clipboard content from a vector of selected boxes.
 * @author S�bastien Paumier
 *
 */
public class MultipleSelection {

   int n= 0;

   ArrayList elem;

   /**
    * Creates a new <code>MultipleSelection</code> from a <code>GraphBox</code> vector 
    * @param v
    */
   public MultipleSelection(ArrayList v,boolean graphBoxes) {
      if (graphBoxes) {
        multipleSelectionGraphBoxes(v);
      }
      }
   
   
   public void multipleSelectionGraphBoxes(ArrayList v) {
      int L= v.size();
      elem= new ArrayList();
      for (int i= 0; i < L; i++) {
         // here we numerote the selected states
         GraphBox g= (GraphBox)v.get(i);
         g.identificationNumber= i;
         // and create the corresponding GraphBoxInfo
         GraphBoxInfo gbi= new GraphBoxInfo();
         gbi.X= g.x;
         gbi.Y= g.Y;
         gbi.content= g.content;
         gbi.reachableBoxes= new Vector();
         elem.add(gbi);
      }
      for (int i= 0; i < L; i++) {
         // here we create relative transitions
         GraphBox g= (GraphBox)v.get(i);
         GraphBoxInfo gbi= (GraphBoxInfo)elem.get(i);
         ArrayList temp= g.transitions;
         int k= temp.size();
         for (int j= 0; j < k; j++) {
            GraphBox dest= (GraphBox)temp.get(j);
            if (dest.identificationNumber != -1) {
               // we only consider the transitions that lead to box into the selection
               gbi.reachableBoxes.add(new Integer(dest.identificationNumber));
            }
         }
      }
      for (int i= 0; i < L; i++) {
         // finally, we put the numero value back to -1
         GraphBox g= (GraphBox)v.get(i);
         g.identificationNumber= -1;
      }
   }

  
}
 /*
  * Unitex
  *
  * Copyright (C) 2001-2006 Universit� de Marne-la-Vall�e <unitex@univ-mlv.fr>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  * 
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  *
  */

package ndosownww.unitex.changes;

import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.io.*;

import javax.swing.*;

import ndosownww.grafy.conversion.*;
import ndosownww.grafy.io.*;
import ndosownww.grafy.process.*;

/**
 * This class is used to listen drag and drop events. Files that can be dragged
 * are texts (".txt" and ".snt", graphs (".grf") and dictionaries (".dic", "dlf"
 * and "dlc"). If you want to allow drag and drop on a component, you must add a
 * <code>DropTarget</code> field to this component like the following:
 * 
 * <p>
 * <code>
 * public DropTarget dropTarget= MyDropTarget.newDropTarget(this);
 * </code>
 * 
 * @author S�bastien Paumier
 *  
 */

public class MyDropTarget {

	static DropTargetListener dropTargetListener;
	static DropTargetListener transcodeDropTargetListener;

	static DataFlavor dragNDropFlavor;

	static {
		try {
			dragNDropFlavor = new DataFlavor(
					"application/x-java-file-list; class=java.util.List");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		dropTargetListener = new DragNDropListener();
		transcodeDropTargetListener = new TranscodeDragNDropListener();
	}

	/**
	 * Creates and returns a <code>DropTarget</code> object that only accepts
	 * files supported by Unitex
	 * 
	 * @param c
	 *            the component that will be the drop target
	 * @return the <code>DropTarget</code> object
	 */
	public static DropTarget newDropTarget(Component c) {
		return new DropTarget(c, DnDConstants.ACTION_COPY_OR_MOVE,
				dropTargetListener, true);
	}

	/**
	 * Creates and returns a <code>DropTarget</code> object that accepts all
	 * files for transcoding
	 * 
	 * @param c
	 *            the component that will be the drop target
	 * @return the <code>DropTarget</code> object
	 */
	public static DropTarget newTranscodeDropTarget(Component c) {
		return new DropTarget(c, DnDConstants.ACTION_COPY_OR_MOVE,
				transcodeDropTargetListener, true);
	}

	static class DragNDropListener implements DropTargetListener {

		private boolean weCanDrag(DropTargetDragEvent e) {
			if (!e.isDataFlavorSupported(MyDropTarget.dragNDropFlavor)) {
				return false;
			}
			return ((e.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE) != 0);
		}

		public void dragEnter(DropTargetDragEvent e) {
			if (!weCanDrag(e)) {
				e.rejectDrag();
				return;
			}
			e.acceptDrag(e.getDropAction());
		}

		public void dragOver(DropTargetDragEvent e) {
			if (!weCanDrag(e)) {
				e.rejectDrag();
				return;
			}
			e.acceptDrag(e.getDropAction());
		}

		public void dropActionChanged(DropTargetDragEvent e) {
			if (!weCanDrag(e)) {
				e.rejectDrag();
				return;
			}
			e.acceptDrag(e.getDropAction());
		}

		public void dragExit(DropTargetEvent e) {
			// nothing to do
		}

		public void drop(DropTargetDropEvent e) {
			Object data = null;
			try {
				e.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
				data = e.getTransferable().getTransferData(dragNDropFlavor);
				if (data == null)
					throw new NullPointerException();
			} catch (Exception e2) {
				e2.printStackTrace();
				e.dropComplete(false);
				return;
			}
			if (data instanceof java.util.List) {
				processDropList((java.util.List) data);
				e.dropComplete(true);
			} else {
				e.dropComplete(false);
			}
		}

		private void processDropList(java.util.List list) {
			if (list.size() == 0)
				return;
			Object o;
			File f;
			String extension;
			o = list.get(0);
			if (!(o instanceof File))
				return;
			f = (File) o;
			extension = Util.getFileNameExtension(f);
		
			if (extension.compareToIgnoreCase("grf") == 0) {
				ConvertOneFileFrame.reset();
				for (int i = 0; i < list.size(); i++) {
					if (Util.getFileNameExtension(f).compareToIgnoreCase("grf") == 0) {
						final File file = (File)list.get(i);
						try {
							GrafMainFrame.mainFrame.loadGraph(file);
						} catch (FileNotFoundException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}
				return;
			}
		}

		/* end of DragNDropListener class */
	}
	static class TranscodeDragNDropListener implements DropTargetListener {

		private boolean weCanDrag(DropTargetDragEvent e) {
			if (!e.isDataFlavorSupported(MyDropTarget.dragNDropFlavor)) {
				return false;
			}
			return ((e.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE) != 0);
		}

		public void dragEnter(DropTargetDragEvent e) {
			if (!weCanDrag(e)) {
				e.rejectDrag();
				return;
			}
			e.acceptDrag(e.getDropAction());
		}

		public void dragOver(DropTargetDragEvent e) {
			if (!weCanDrag(e)) {
				e.rejectDrag();
				return;
			}
			e.acceptDrag(e.getDropAction());
		}

		public void dropActionChanged(DropTargetDragEvent e) {
			if (!weCanDrag(e)) {
				e.rejectDrag();
				return;
			}
			e.acceptDrag(e.getDropAction());
		}

		public void dragExit(DropTargetEvent e) {
			// nothing to do
		}

		public void drop(DropTargetDropEvent e) {
			Object data = null;
			try {
				e.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
				data = e.getTransferable().getTransferData(dragNDropFlavor);
				if (data == null)
					throw new NullPointerException();
			} catch (Exception e2) {
				e2.printStackTrace();
				e.dropComplete(false);
				return;
			}
			if (data instanceof java.util.List) {
				processDropList((java.util.List) data);
				e.dropComplete(true);
			} else {
				e.dropComplete(false);
			}
		}

		private void processDropList(java.util.List list) {
			if (!ConversionFrame.isFrameVisible()) {
				// this case should never happen
				return;
			}
			Object o;
			File f;
			for (int i = 0; i < list.size(); i++) {
				o = list.get(i);
				if (!(o instanceof File)) {
					return;
				}
				f = (File) o;
				DefaultListModel model = ConversionFrame.getListModel();
				if (!model.contains(f)) {
					model.addElement(f);
				}
			}
		}

		/* end of UnrestrictedDragNDropListener class */
	}

	/* end of MyDropTarget class */
}
package ndosownww.unitex.changes;

import javax.swing.SwingUtilities;

import ndosownww.grafy.GrafMainFrame;

public class ProcessCommand {
	MultiCommands commands;
	Process p;
	public ProcessCommand(CommandBuilder c) {
		commands = new MultiCommands(c);
	}
	

	public void launchBuilderCommands() {
		if (commands == null)
			return;
		new Thread() {
			public void run() {
				boolean problem = false;
				CommandBuilder command;
				for (int i = 0; (!problem) && i < commands.numberOfCommands(); i++)
					if ((command = commands.getCommand(i)) != null) {
						switch (command.getType()) {
						case CommandBuilder.PROGRAM: {
						//	Console.addCommand(command.getCommandLine());
							String[] comm = command.getCommandArguments();
							try {
								for (int j=0;j<comm.length;++j) {
									System.out.println(comm[j]);
								}
								p = Runtime.getRuntime().exec(comm);
								try {
									p.waitFor();
								} catch (java.lang.InterruptedException e) {
									
									problem = true;
								}
							} catch (java.io.IOException e) {
								final String programName = comm[0];
								
								
									problem = true;
								
							}
							try {
								if (p == null) {
								
										problem = true;
						
								} else if (p.exitValue() != 0) {
									System.err.print("The exit value of the program "
													+ comm[0]
													+ " is "
													+ p.exitValue() + "\n");
							
										problem = true;
								
								}
							} catch (IllegalThreadStateException e) {
								p.destroy();
							}
						}
							break;
						}// end of program command
					}// end of switch
				if (problem == true) {
					
				} else {
				
				}
				if (!problem) {
					
				
				}
				
			}
		}.start();
	}
}
 /*
  * Unitex
  *
  * Copyright (C) 2001-2006 Universit� de Marne-la-Vall�e <unitex@univ-mlv.fr>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  * 
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  *
  */

package ndosownww.unitex.changes;

import java.io.*;

import javax.swing.*;

/**
 * This class is used to monitor stdout and stderr messages of external processes.
 * @author S�bastien Paumier
 *
 */
public class ProcessThread extends Thread {

   JTextArea txt;
   BufferedReader stream;
   boolean close_on_finish;
   ProcessInfoFrame parent_frame;
   JScrollBar scroll_bar;
   JScrollPane scrollPane;

   /**
    * Creates a new <code>ProcessInfoThread</code> 
    * @param t the text area to display messages
    * @param s the stream to monitor
    * @param close indicate if the parent frame must be closed after the completion of the process
    * @param f parent frame
    * @param scroll scroll bar of the text area
    * @param scr scroll pane that contains the text area
    */
   public ProcessThread(
      JTextArea t,
      InputStream s,
      boolean close,
      ProcessInfoFrame f,
      JScrollBar scroll,
      JScrollPane scr) {
      super();
      txt= t;
      close_on_finish= close;
      parent_frame= f;
      scroll_bar= scroll;
      scrollPane= scr;
      stream= new BufferedReader(new InputStreamReader(s));
   }

   /**
    * Runs the monitoring thread 
    */
   public void run() {
      String s;
      try {
         while ((s= stream.readLine()) != null) {
            if (!s.equals("")) {
               final String s2= s;
               SwingUtilities.invokeLater(new Runnable() {
                  public void run() {
                     txt.append(s2 + "\n");
                     scroll_bar.setValue(scroll_bar.getMaximum());
                     scrollPane.repaint();
                  }
               });
            }
         }
      } catch (IOException e) {
    	  e.printStackTrace();
      }
      if (close_on_finish) {
         parent_frame.setVisible(false);
         parent_frame= null;
      } else {
         scroll_bar.setValue(scroll_bar.getMaximum());
      }
   }

}
/*
 * Unitex
 *
 * Copyright (C) 2001-2006 Universit� de Marne-la-Vall�e <unitex@univ-mlv.fr>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
 *
 */

package ndosownww.unitex.changes;

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

import ndosownww.grafy.*;

/**
 * This class describes a frame used to execute shell commands and display
 * stdout and stderr messages produced by these processes.
 * 
 * @author S�bastien Paumier
 *  
 */
public class ProcessInfoFrame extends JInternalFrame {
	Process p;

	JTextArea text_stdout = new JTextArea();

	JScrollPane scroll;

	JTextArea text_stderr = new JTextArea();

	JScrollPane errorScroll;

	boolean close_on_finish;

	boolean stop_if_problem;

	MultiCommands commands = null;

	ToDoAbstract DO;

	/**
	 * Creates a new <code>ProcessInfoFrame</code>
	 * 
	 * @param c
	 *            array containing the shell commands to run
	 * @param close
	 *            indicates if the frame must be closed after the completion of
	 *            all commands
	 * @param myDo
	 *            object describing actions to do after the completion of all
	 *            commands
	 */
	public ProcessInfoFrame(MultiCommands c, boolean close, ToDoAbstract myDo) {
		this(c, close, myDo, true);
	}

	/**
	 * Creates a new <code>ProcessInfoFrame</code>
	 * 
	 * @param c
	 *            array containing the shell commands to run
	 * @param close
	 *            indicates if the frame must be closed after the completion of
	 *            all commands
	 * @param myDo
	 *            object describing actions to do after the completion of all
	 *            commands
	 * @param stopIfProblem
	 *            indicates if the failure of a command must stop all commands
	 */
	public ProcessInfoFrame(MultiCommands c, boolean close, ToDoAbstract myDo,
			boolean stopIfProblem) {
		super("Working...", true, false, false);
		commands = c;
		close_on_finish = close;
		stop_if_problem = stopIfProblem;
		DO = myDo;
		JPanel top = new JPanel();
		top.setOpaque(true);
		top.setLayout(new BorderLayout());
		scroll = new JScrollPane(text_stdout);
		text_stderr.setForeground(Color.RED);
		errorScroll = new JScrollPane(text_stderr);
		JPanel tmp = new JPanel();
		tmp.setOpaque(true);
		tmp.setLayout(new BorderLayout());
		tmp.setBorder(BorderFactory.createLoweredBevelBorder());
		tmp.add(scroll, BorderLayout.CENTER);
		JPanel tmp2 = new JPanel();
		tmp2.setOpaque(true);
		tmp2.setLayout(new BorderLayout());
		tmp2.setBorder(BorderFactory.createLoweredBevelBorder());
		tmp2.add(errorScroll, BorderLayout.CENTER);
		JSplitPane middle = new JSplitPane(JSplitPane.VERTICAL_SPLIT, tmp, tmp2);
		middle.setDividerLocation(250);
		top.add(middle, BorderLayout.CENTER);
		Action okAction = new AbstractAction("OK") {
			public void actionPerformed(ActionEvent arg0) {
				if (p != null) {
					try {
						p.exitValue();
					} catch (IllegalThreadStateException ex) {
						return;
					}
				}
				setVisible(false);
				GrafMainFrame.removeInternalFrame(ProcessInfoFrame.this);
			}
		};
		JButton ok = new JButton(okAction);
		Action cancelAction = new AbstractAction("Cancel") {
			public void actionPerformed(ActionEvent arg0) {
				if (p != null)
					p.destroy();
				setVisible(false);
				GrafMainFrame.removeInternalFrame(ProcessInfoFrame.this);
			}
		};
		JButton cancel = new JButton(cancelAction);
		JPanel buttons = new JPanel(new GridLayout(1, 2));
		buttons.setOpaque(true);
		buttons.add(ok);
		buttons.add(cancel);
		top.add(buttons, BorderLayout.SOUTH);
		setContentPane(top);
		pack();
		setBounds(100, 100, 600, 400);
		GrafMainFrame.addInternalFrame(this);
		setVisible(true);
		try {
			setSelected(true);
			setIcon(false);
		} catch (java.beans.PropertyVetoException e) {
			e.printStackTrace();
		}
		launchBuilderCommands();
	}

	/**
	 * Creates a new <code>ProcessInfoFrame</code>
	 * 
	 * @param c
	 *            array containing the shell commands to run
	 * @param close
	 *            indicates if the frame must be closed after the completion of
	 *            all commands
	 */
	public ProcessInfoFrame(MultiCommands c, boolean close) {
		this(c, close, null);
	}

	/**
	 * Creates a new <code>ProcessInfoFrame</code>
	 * 
	 * @param c
	 *            the shell command to run
	 * @param close
	 *            indicates if the frame must be closed after the completion of
	 *            all commands
	 */
	public ProcessInfoFrame(CommandBuilder c, boolean close) {
		this(new MultiCommands(c), close, null);
	}

	/**
	 * Creates a new <code>ProcessInfoFrame</code>
	 * 
	 * @param c
	 *            the shell commands to run
	 * @param close
	 *            indicates if the frame must be closed after the completion of
	 *            all commands
	 * @param DO
	 *            object describing actions to do after the completion of all
	 *            commands
	 */
	public ProcessInfoFrame(CommandBuilder c, boolean close, ToDoAbstract DO) {
		this(new MultiCommands(c), close, DO);
	}

	private void launchBuilderCommands() {
		if (commands == null)
			return;
		new Thread() {
			public void run() {
				boolean problem = false;
				CommandBuilder command;
				for (int i = 0; (!problem) && i < commands.numberOfCommands(); i++)
					if ((command = commands.getCommand(i)) != null) {
						switch (command.getType()) {
						case CommandBuilder.MESSAGE: {
							text_stdout
							.append(((MessageCommand)command).getMessage());
							break;
						} 
						case CommandBuilder.ERROR_MESSAGE: {
							text_stderr
							.append(((MessageCommand)command).getMessage());
							break;
						}
						case CommandBuilder.PROGRAM: {
						//	Console.addCommand(command.getCommandLine());
							String[] comm = command.getCommandArguments();
							try {
								p = Runtime.getRuntime().exec(comm);
								new ProcessInfoThread(text_stdout, p
										.getInputStream(), false,
										ProcessInfoFrame.this, scroll
												.getVerticalScrollBar(), scroll)
										.start();
								new ProcessInfoThread(text_stderr, p
										.getErrorStream(), false,
										ProcessInfoFrame.this, errorScroll
												.getVerticalScrollBar(),
										errorScroll).start();
								try {
									p.waitFor();
								} catch (java.lang.InterruptedException e) {
									if (stop_if_problem)
										text_stderr.append("The program "
												+ comm[0]
												+ " has been interrupted\n");
									scroll.getVerticalScrollBar().setValue(
											scroll.getVerticalScrollBar()
													.getMaximum());
									errorScroll.repaint();
									problem = true;
								}
							} catch (java.io.IOException e) {
								final String programName = comm[0];
								SwingUtilities.invokeLater(new Runnable() {
									public void run() {
										text_stderr
												.append("Cannot launch the program "
														+ programName + "\n");
										scroll.getVerticalScrollBar().setValue(
												scroll.getVerticalScrollBar()
														.getMaximum());
										errorScroll.repaint();
									}
								});
								if (stop_if_problem) {
									problem = true;
								}
							}
							try {
								if (p == null) {
									if (stop_if_problem) {
										problem = true;
									}
								} else if (p.exitValue() != 0) {
									/*text_stderr
											.append("The exit value of the program "
													+ comm[0]
													+ " is "
													+ p.exitValue() + "\n");
									scroll.getVerticalScrollBar().setValue(
											scroll.getVerticalScrollBar()
													.getMaximum());
									errorScroll.repaint();*/
									if (stop_if_problem) {
										problem = true;
									}
								}
							} catch (IllegalThreadStateException e) {
								p.destroy();
							}
						}
							break;
						}// end of program command
					}// end of switch
				if (problem == true) {
					setTitle("ERROR");
				} else {
					setTitle("");
				}
				if (!problem && close_on_finish) {
					ProcessInfoFrame.this.setVisible(false);
					GrafMainFrame.removeInternalFrame(ProcessInfoFrame.this);
				}
				if (!problem && DO != null) {
					DO.toDo();
				}
			}
		}.start();
	}

}
package ndosownww.unitex.changes;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;

import toposlaw.gui.menu.DodajNazweDialog;


public class SaveGraphDialog extends JDialog {

	 	private javax.swing.JButton cancelGrafBtn;
	    private javax.swing.JLabel grafLabel;
	    private javax.swing.JTextField grafTextField;
	    private javax.swing.JButton nieZapiszGrafBtn;
	    private javax.swing.JButton zapiszGrafBtn;

	
	    public static String grafName = null;
	    private static int result = 0;
	    
	public SaveGraphDialog(JFrame frame) {
		super(frame);
		this.setName("this"); // NOI18N

		cancelGrafBtn = new JButton();
	    grafLabel = new JLabel();
	    grafTextField = new JTextField();
	    nieZapiszGrafBtn = new JButton();
	    zapiszGrafBtn = new JButton();
	    
		
		setPreferredSize(new Dimension(360, 360));
		setModal(true);
		
      //  grafLabel.setText(resourceMap.getString("grafLabel.text")); // NOI18N
		grafLabel.setText("Wpisz nazwę grafu");
        grafLabel.setName("grafLabel"); // NOI18N

        //grafTextField.setText(resourceMap.getString("grafTextField.text")); // NOI18N
        grafTextField.setName("grafTextField"); // NOI18N

        //zapiszGrafBtn.setText(resourceMap.getString("zapiszGrafBtn.text")); // NOI18N
        zapiszGrafBtn.setText("Zapisz"); // NOI18N
        zapiszGrafBtn.setName("zapiszGrafBtn"); // NOI18N
        zapiszGrafBtn.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				result = 1;
				grafName = grafTextField.getText();
				dispose();
			}
			
		});


        //nieZapiszGrafBtn.setText(resourceMap.getString("nieZapiszGrafBtn.text")); // NOI18N
        nieZapiszGrafBtn.setText("Nie zapisuj"); // NOI18N
        nieZapiszGrafBtn.setName("nieZapiszGrafBtn"); // NOI18N
        nieZapiszGrafBtn.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				result = -1;
				dispose();
			}
			
		});
        nieZapiszGrafBtn.setEnabled(false);

        //cancelGrafBtn.setText(resourceMap.getString("cancelGrafBtn.text")); // NOI18N
        cancelGrafBtn.setText("Anuluj");
        cancelGrafBtn.setName("cancelGrafBtn"); // NOI18N
    	cancelGrafBtn.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				result = 0;
				dispose();
			}
			
		});

        javax.swing.GroupLayout thisLayout = new javax.swing.GroupLayout(this.getContentPane());
        this.getContentPane().setLayout(thisLayout);
        thisLayout.setHorizontalGroup(
            thisLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(thisLayout.createSequentialGroup()
                .addGap(41, 41, 41)
                .addGroup(thisLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(grafLabel)
                    .addGroup(thisLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                        .addGroup(javax.swing.GroupLayout.Alignment.LEADING, thisLayout.createSequentialGroup()
                        	.addComponent(nieZapiszGrafBtn)
                            .addGap(43, 43, 43)
                            .addComponent(zapiszGrafBtn)
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(cancelGrafBtn))
                        .addComponent(grafTextField, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 298, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap(61, Short.MAX_VALUE))
        );
        thisLayout.setVerticalGroup(
            thisLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(thisLayout.createSequentialGroup()
                .addGap(64, 64, 64)
                .addComponent(grafLabel)
                .addGap(18, 18, 18)
                .addComponent(grafTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(38, 38, 38)
                .addGroup(thisLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(zapiszGrafBtn)
                    .addComponent(cancelGrafBtn)
                    .addComponent(nieZapiszGrafBtn))
                .addContainerGap(123, Short.MAX_VALUE))
        );
	}
	
	public static int invokeSaveGraphDialog(JFrame ramka) {
		grafName = null;
		SaveGraphDialog dialog = new SaveGraphDialog(ramka);
		dialog.pack();
		Point loc = ramka.getLocation();
		loc.translate(40, 40);
		dialog.setLocation(loc);
		dialog.setVisible(true);
		return result;
	}
	
	
	
}
 /*
  * Unitex
  *
  * Copyright (C) 2001-2006 Universit� de Marne-la-Vall�e <unitex@univ-mlv.fr>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  * 
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  *
  */

package ndosownww.unitex.changes;

import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.io.*;

import javax.swing.*;
import javax.swing.text.*;

/**
 * This class describes the text field used to get the box text in a graph.
 * @author S�bastien Paumier
 *
 */
public class TextField extends JTextField {

   /**
    * Frame that contains this component 
    */
   public GraphFrame parent;

   /**
    * Indicates if the text field content has been modified 
    */
   public boolean modified= false;

   /**
    * Left context for multiple word copy 
    */
   public static String leftContext;

   /**
    * Right context for multiple word copy 
    */
   public static String rightContext;

   /**
    * <code>TextAction</code> that defines what to do for a "paste" operation 
    */
   public SpecialPaste specialPaste;

   /**
    * <code>TextAction</code> that defines what to do for a "copy" operation 
    */
   public SpecialCopy specialCopy;

   /**
    * <code>TextAction</code> that defines what to do for a "select all" operation 
    */
   public SelectAll selectAll;

   /**
    * <code>TextAction</code> that defines what to do for a "cut" operation 
    */
   public Cut cut;

   /**
    * <code>TextAction</code> that shows the graph presentation frame
    */
   public Presentation presentation;

   /**
    * <code>TextAction</code> that shows a dialog box to open a graph
    */
   public Open OPEN;

   /**
    * <code>TextAction</code> that saves the current graph
    */
   public Save SAVE;

   /**
    * Constructs a new <code>TextField</code> 
    * @param n number of columns
    * @param p frame that contains this component
    */
   public TextField(int n, GraphFrame p) {
      super(n);
      setEditable(false);
      modified= false;
      parent= p;
      leftContext= "";
      rightContext= "";
      setDisabledTextColor(Color.white);
      setBackground(Color.white);
      Keymap k= getKeymap();
      k= addKeymap("textfield-keymap", k);
      k.removeKeyStrokeBinding(KeyStroke.getKeyStroke('l', Event.CTRL_MASK));
      k.removeKeyStrokeBinding(KeyStroke.getKeyStroke('L', Event.CTRL_MASK));
      k.removeKeyStrokeBinding(KeyStroke.getKeyStroke('k', Event.CTRL_MASK));
      k.removeKeyStrokeBinding(KeyStroke.getKeyStroke('K', Event.CTRL_MASK));
      k.removeKeyStrokeBinding(KeyStroke.getKeyStroke('o', Event.CTRL_MASK));
      k.removeKeyStrokeBinding(KeyStroke.getKeyStroke('O', Event.CTRL_MASK));
      k.removeKeyStrokeBinding(KeyStroke.getKeyStroke('s', Event.CTRL_MASK));
      k.removeKeyStrokeBinding(KeyStroke.getKeyStroke('S', Event.CTRL_MASK));
      k.removeKeyStrokeBinding(KeyStroke.getKeyStroke('p', Event.CTRL_MASK));
      k.removeKeyStrokeBinding(KeyStroke.getKeyStroke('P', Event.CTRL_MASK));
      k.removeKeyStrokeBinding(KeyStroke.getKeyStroke('m', Event.CTRL_MASK));
      k.removeKeyStrokeBinding(KeyStroke.getKeyStroke('M', Event.CTRL_MASK));
      k.removeKeyStrokeBinding(KeyStroke.getKeyStroke('r', Event.CTRL_MASK));
      k.removeKeyStrokeBinding(KeyStroke.getKeyStroke('R', Event.CTRL_MASK));
      k.removeKeyStrokeBinding(KeyStroke.getKeyStroke('x', Event.CTRL_MASK));
      k.removeKeyStrokeBinding(KeyStroke.getKeyStroke('X', Event.CTRL_MASK));
      k.removeKeyStrokeBinding(KeyStroke.getKeyStroke('c', Event.CTRL_MASK));
      k.removeKeyStrokeBinding(KeyStroke.getKeyStroke('C', Event.CTRL_MASK));
      k.removeKeyStrokeBinding(KeyStroke.getKeyStroke('v', Event.CTRL_MASK));
      k.removeKeyStrokeBinding(KeyStroke.getKeyStroke('V', Event.CTRL_MASK));
      k.removeKeyStrokeBinding(KeyStroke.getKeyStroke('a', Event.CTRL_MASK));
      k.removeKeyStrokeBinding(KeyStroke.getKeyStroke('A', Event.CTRL_MASK));
      specialPaste= new SpecialPaste("special-paste");
      specialCopy= new SpecialCopy("special-copy");
      presentation= new Presentation("presentation");
      selectAll= new SelectAll("select all");
      cut= new Cut("cut");
      OPEN= new Open("open");
      SAVE= new Save("save");

      k.addActionForKeyStroke(
         KeyStroke.getKeyStroke('v', Event.CTRL_MASK),
         specialPaste);
      k.addActionForKeyStroke(
         KeyStroke.getKeyStroke('V', Event.CTRL_MASK),
         specialPaste);
      k.addActionForKeyStroke(
         KeyStroke.getKeyStroke('c', Event.CTRL_MASK),
         specialCopy);
      k.addActionForKeyStroke(
         KeyStroke.getKeyStroke('C', Event.CTRL_MASK),
         specialCopy);

      k.addActionForKeyStroke(
         KeyStroke.getKeyStroke('r', Event.CTRL_MASK),
         presentation);
      k.addActionForKeyStroke(
         KeyStroke.getKeyStroke('R', Event.CTRL_MASK),
         presentation);

      k.addActionForKeyStroke(
         KeyStroke.getKeyStroke('o', Event.CTRL_MASK),
         OPEN);
      k.addActionForKeyStroke(
         KeyStroke.getKeyStroke('O', Event.CTRL_MASK),
         OPEN);

      k.addActionForKeyStroke(
         KeyStroke.getKeyStroke('s', Event.CTRL_MASK),
         SAVE);
      k.addActionForKeyStroke(
         KeyStroke.getKeyStroke('S', Event.CTRL_MASK),
         SAVE);

      k.addActionForKeyStroke(
         KeyStroke.getKeyStroke('a', Event.CTRL_MASK),
         selectAll);
      k.addActionForKeyStroke(
         KeyStroke.getKeyStroke('A', Event.CTRL_MASK),
         selectAll);

      k.addActionForKeyStroke(
         KeyStroke.getKeyStroke('x', Event.CTRL_MASK),
         cut);
      k.addActionForKeyStroke(
         KeyStroke.getKeyStroke('X', Event.CTRL_MASK),
         cut);

      this.setKeymap(k);

      addKeyListener(new MyKeyListener());
   }

   GraphFrame parent() {
      return GrafMainFrame.getCurrentFocusedGraphFrame();
   }

   class SpecialCopy extends TextAction implements ClipboardOwner {
      public SpecialCopy(String s) {
         super(s);
      }

      public void actionPerformed(ActionEvent e) {
         if (parent().graphicalZone.selectedBoxes.isEmpty()
            || parent().graphicalZone.selectedBoxes.size() < 2) {
            // is there is no or one box selected, we copy normally
            copy();
            GrafMainFrame.clip.setContents(null, this);
            return;
         }
         GrafMainFrame.clip.setContents(
            new MultipleBoxesSelection(
               new MultipleSelection(parent().graphicalZone.selectedBoxes,true)),
            this);
      }

      public void lostOwnership(Clipboard c, Transferable d) {
    	  // nothing to do
      }
   }

   class SelectAll extends TextAction implements ClipboardOwner {
      public SelectAll(String s) {
         super(s);
      }

      public void actionPerformed(ActionEvent e) {
         if (!parent().graphicalZone.selectedBoxes.isEmpty()
            && parent().graphicalZone.selectedBoxes.size() == 1)
            selectAll();
         else
            parent().graphicalZone.selectAllBoxes();
      }

      public void lostOwnership(Clipboard c, Transferable d) {
    	  // nothing
      }
   }

   class Cut extends TextAction implements ClipboardOwner {
      public Cut(String s) {
         super(s);
      }

      public void actionPerformed(ActionEvent e) {
         if (!parent().graphicalZone.selectedBoxes.isEmpty()
            && parent().graphicalZone.selectedBoxes.size() == 1) {
            cut();
         } else {
            GrafMainFrame.clip.setContents(
               new MultipleBoxesSelection(
                  new MultipleSelection(parent().graphicalZone.selectedBoxes,true)),
               this);
            parent().graphicalZone.removeSelected();
            setText("");
         }
      }

      public void lostOwnership(Clipboard c, Transferable d) {
    	  // nothing to do
      }
   }

   class SpecialPaste extends TextAction {
      public SpecialPaste(String s) {
         super(s);
      }

      public void actionPerformed(ActionEvent e) {
         Transferable data;
         MultipleSelection res= null;
         data= GrafMainFrame.clip.getContents(this);
         try {
            if (data != null)
               res=
                  (MultipleSelection)data.getTransferData(
                     new DataFlavor("unitex/boxes", "Unitex dataflavor"));
         } catch (UnsupportedFlavorException e2) {
        	 e2.printStackTrace();
         } catch (IOException e2) {
        	 e2.printStackTrace();
         }
         if (res == null || TextField.this.modified == true) {
            // if there is no boxes to copy we do a simple paste
            paste();
            return;
         }
         res.n++;
         parent().graphicalZone.pasteSelection(res);
      }
   }

   class Presentation extends TextAction {
      public Presentation(String s) {
         super(s);
      }

      public void actionPerformed(ActionEvent e) {
         new GraphPresentationMenu();
      }
   }

   class Open extends TextAction {
      public Open(String s) {
         super(s);
      }

      public void actionPerformed(ActionEvent e) {
        // GrafMainFrame.mainFrame.openGraph();
      }
   }

   class Save extends TextAction {
      public Save(String s) {
         super(s);
      }

      public void actionPerformed(ActionEvent e) {
         GraphFrame f=GrafMainFrame.getCurrentFocusedGraphFrame();
     /*    if (f!=null) {
            GrafMainFrame.mainFrame.saveGraph(f);
         }*/
      }
   }

   /**
    * Initializes the text field with a string 
    * @param s the new text content
    */
   public void initText(String s) {
      modified= false;
      setEditable(true);
      setText(s);
      requestFocus();
      getCaret().setVisible(true);
      selectAll();
   }

   /**
    * Returns a new <code>ListDocument</code> object.
    * @return the <code>ListDocument</code>
    */
   public Document createDefaultModel() {
      return new ListDocument();
   }

   /**
    * Validates the content of the text field as the content of selected boxes. 
    * @return <code>true</code> if boxes have actually been modified, <code>false</code> otherwise 
    */
   public boolean validateTextField() {
      if (!hasChangedTextField())
         return false;
      if (isValidGraphBoxContent(getText())) {
         parent().setModified(true);
         parent().graphicalZone.setTextForSelected(getText());
         parent().graphicalZone.unSelectAllBoxes();
         setText("");
         parent().repaint();
         setEditable(false);
         return true;
      }
      return false;
   }

   class MyKeyListener extends KeyAdapter {
      public void keyPressed(KeyEvent e) {
         if (e.isControlDown() || e.isAltDown()) {
            // if the control key or alt key is pressed, we do nothing: the event we be caught by the ActionListeners
            return;
         }
         if (e.getKeyCode() == 10)         
            validateTextField();
         
         modified= true;
      }
   }

   /**
    * Tests if the content of the text field has changed. 
    * @return <code>true</code> if the content has changed, <code>false</code> otherwise 
    */
   public boolean hasChangedTextField() {
      return modified;
   }

   private int test_transduction(char s[], int i) {
      int compteur;
      if (s[i] != '/')
         return 0;
      i--;
      compteur= 0;
      while (i >= 0 && s[i] == '\\') {
         compteur++;
         i--;
      }
      if ((compteur % 2) != 0)
         return 0;
      return 1;
   }

   private boolean tokenize(String s) {
      int L= s.length(), i= 0;
      String tmp;
      char ligne[]= new char[10000];
      ligne= s.toCharArray();
      if (ligne[0] == '+') {
         JOptionPane.showMessageDialog(
            null,
            "Unexpected \"+\" as first character of the line",
            "Error",
            JOptionPane.ERROR_MESSAGE);
         return false;
      }
      if (L>=2 && ligne[L-1] == '+' && ligne[L-2]!='\\') {
         JOptionPane.showMessageDialog(
            null,
            "Unexpected \"+\" as last character of the line",
            "Error",
            JOptionPane.ERROR_MESSAGE);
         return false;
      }
      while (i < L) {
         tmp= "";
         if (ligne[i] == ':') {
            // case of a sub graph call
            i++;
            while ((i < L) && (ligne[i] != '+')) {
               if (ligne[i] == '\\') {
                  tmp= tmp.concat(String.valueOf(ligne[i++]));
                  if (i >= L) {
                     JOptionPane.showMessageDialog(
                        null,
                        "Unexpected \"\\\" at end of line",
                        "Error",
                        JOptionPane.ERROR_MESSAGE);
                     return false;
                  }
               }
               tmp= tmp.concat(String.valueOf(ligne[i++]));
            }
            if (tmp.length() == 0) {
               JOptionPane.showMessageDialog(
                  null,
                  "Missing graph name after \":\"",
                  "Error",
                  JOptionPane.ERROR_MESSAGE);
               return false;
            }
            i++;
         } else {
            // all other cases
            if (ligne[i] == '+') {
               // if we find a + just after a + it is an error
               JOptionPane.showMessageDialog(
                  null,
                  "Empty line error: \"++\"",
                  "Error",
                  JOptionPane.ERROR_MESSAGE);
               return false;
            }
            while ((i < L) && (ligne[i] != '+')) {
               if (ligne[i] == '"') {
                  // case of a quote expression
                  tmp= tmp.concat(String.valueOf(ligne[i++]));
                  while ((i < L) && ligne[i] != '"') {
                     if (ligne[i] == '\\') {
                        tmp= tmp.concat(String.valueOf(ligne[i++]));
                        if (i >= L) {
                           JOptionPane.showMessageDialog(
                              null,
                              "Unexpected \"\\\" at end of line",
                              "Error",
                              JOptionPane.ERROR_MESSAGE);
                           return false;
                        }
                     }
                     tmp= tmp.concat(String.valueOf(ligne[i++]));
                  }
                  if (i >= L) {
                     JOptionPane.showMessageDialog(
                        null,
                        "No closing \"",
                        "Error",
                        JOptionPane.ERROR_MESSAGE);
                     return false;
                  }
                  tmp= tmp.concat(String.valueOf(ligne[i++]));
               } else
                  if (ligne[i] == '<') {
                     // case of a <...> expression
                     tmp= tmp.concat(String.valueOf(ligne[i++]));
                     while ((i < L) && ligne[i] != '>') {
                        if (ligne[i] == '\\') {
                           tmp= tmp.concat(String.valueOf(ligne[i++]));
                           if (i >= L) {
                              JOptionPane.showMessageDialog(
                                 null,
                                 "Unexpected \"\\\" at end of line",
                                 "Error",
                                 JOptionPane.ERROR_MESSAGE);
                              return false;
                           }
                        }
                        tmp= tmp.concat(String.valueOf(ligne[i++]));
                     }
                     if (i >= L) {
                        JOptionPane.showMessageDialog(
                           null,
                           "No closing \">\"",
                           "Error",
                           JOptionPane.ERROR_MESSAGE);
                        return false;
                     }
                     tmp= tmp.concat(String.valueOf(ligne[i++]));
                  } else
                     if (ligne[i] == '{') {
                        // case of a {...} expression
                        tmp= tmp.concat(String.valueOf(ligne[i++]));
                        while ((i < L) && ligne[i] != '}') {
                           if (ligne[i] == '\\') {
                              tmp= tmp.concat(String.valueOf(ligne[i++]));
                              if (i >= L) {
                                 JOptionPane.showMessageDialog(
                                    null,
                                    "Unexpected \"\\\" at end of line",
                                    "Error",
                                    JOptionPane.ERROR_MESSAGE);
                                 return false;
                              }
                           }
                           tmp= tmp.concat(String.valueOf(ligne[i++]));
                        }
                        if (i >= L) {
                           JOptionPane.showMessageDialog(
                              null,
                              "No closing \"}\"",
                              "Error",
                              JOptionPane.ERROR_MESSAGE);
                           return false;
                        }
                        tmp= tmp.concat(String.valueOf(ligne[i++]));
                     } else {
                        if (ligne[i] == '\\') {
                           tmp= tmp.concat(String.valueOf(ligne[i++]));
                           if (i >= L) {
                              JOptionPane.showMessageDialog(
                                 null,
                                 "Unexpected \"\\\" at end of line",
                                 "Error",
                                 JOptionPane.ERROR_MESSAGE);
                              return false;
                           }
                        }
                        tmp= tmp.concat(String.valueOf(ligne[i++]));
                     }
            }
            i++;
         }
      }
      return true;
   }

   /**
    * Tests if a content is a valid content for a graph box.
    * @param s the content to test 
    * @return <code>true</code> if the content is valid, <code>false</code> otherwise 
    */
   public boolean isValidGraphBoxContent(String s) {
      if (s.equals(""))
         return true;
      char ligne[]= new char[10000];
      String tmp= "";
      int i, L;

      ligne= s.toCharArray();
      i= 0;
      L= s.length();
      if (L == 2 && ligne[0] == '$' && (ligne[1] == '(' || ligne[1] == ')')) {
         JOptionPane.showMessageDialog(
            null,
            "You must indicate a variable name between $ and ( or )",
            "Error",
            JOptionPane.ERROR_MESSAGE);
         return false;
      }
      while ((i != L) && (test_transduction(ligne, i) == 0))
         tmp= tmp.concat(String.valueOf(ligne[i++]));
      if ((i != L) && (i == 0)) {
         JOptionPane.showMessageDialog(
            null,
            "Empty text before \"/\"",
            "Error",
            JOptionPane.ERROR_MESSAGE);
         return false;
      }
      if (L > 2
         && ligne[0] == '$'
         && (ligne[L - 1] == '(' || ligne[L - 1] == ')')
         && s.lastIndexOf('+') == -1) {
         // case of a variable start $a( or end $a)
         for (int k= 1; k < L - 1; k++)
            if (ligne[k] != '_'
               && !(ligne[k] >= '0' && ligne[k] <= '9')
               && !(ligne[k] >= 'a' && ligne[k] <= 'z')
               && !(ligne[k] >= 'A' && ligne[k] <= 'Z')) {
               JOptionPane.showMessageDialog(
                  null,
                  "A variable name can only contain the following characters:\nA..Z,a..z,0..9 and the underscore '_'",
                  "Error",
                  JOptionPane.ERROR_MESSAGE);
               return false;
            }
         return true;
      }
      if (tokenize(tmp))
         return true;
      return false;
   }

}
package ndosownww.unitex.changes;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.dnd.DropTarget;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.print.PageFormat;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Iterator;
import java.util.Vector;

import javax.swing.ButtonGroup;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.border.TitledBorder;

import toposlaw.ToposlawConfig;
import toposlaw.NarzedzieMsg;
import toposlaw.NarzedzieView;
import toposlaw.akcje.GrafyActions;
import toposlaw.graphs.tools.GraphRaw;
import toposlaw.graphs.tools.GraphRepresentation;
import toposlaw.graphs.tools.GraphRepresentationIO;
import toposlaw.graphs.tools.KompilacjaGrafu;
import toposlaw.graphs.tools.unitex.NazwaGrafuTextField;
import toposlaw.gui.tools.GlassScreen;
import toposlaw.managers.GraphManager;
import toposlaw.model.ListaGrafowModel;
import toposlaw.model.NarzedzieModel;

import ndosownww.grafy.conversion.ConvertOneFileFrame;
import ndosownww.grafy.io.GraphIO;
import ndosownww.grafy.io.UnicodeIO;
import ndosownww.grafy.process.ConvertCommand;
import ndosownww.grafy.process.FlattenCommand;
import ndosownww.grafy.process.Grf2Fst2Command;
import ndosownww.grafy.process.MultiCommands;
import ndosownww.grafy.process.ProcessCommand;
import ndosownww.grafy.process.ProcessInfoFrame;
import ndosownww.grafy.process.Syl2JamoCommand;
import ndosownww.obiekty.Czlon;
import ndosownww.obiekty.Graf;

public class UnitexFrame extends JFrame {

	
	private static final int MODE_NOWY = 0;
	static final int MODE_EDYTUJ = 1;
	private static final int MODE_NOWY_NA_PODSTAWIE = 2;
	static final int MODE_PODGLAD = 3;
	
	int mode;
	File grafFile;
	public static String grafName;
	private static Graf staryGraf;
	private static String staraTrescGrafu;
	String kodNazwyGrafu = null;
	
	/**
	 * This object is used to enable drag-and-drop, so that the user can pick up
	 * texts, graphs and dictionaries from a file explorer.
	 */
	public DropTarget dropTarget = MyDropTarget.newDropTarget(this);
	JMenuBar menuBar;
	/**
	 * The desktop of the frame.
	 */
	public static JDesktopPane desktop;

	/**
	 * Layer used to display document internal frames
	 */
	public static final Integer DOCLAYER = new Integer(5);
	static final Integer TOOLLAYER = new Integer(6);
	static final Integer HELPLAYER = new Integer(7);
	/**
	 * The clipboard used to copy and paste text and graph box selections.
	 */
	public static Clipboard clip = new Clipboard("Unitex clipboard");
	
	public static UnitexFrame mainFrame;
	static Dimension screenSize;
	PrinterJob printerJob;
	PageFormat pageFormat;
	static boolean closing = false;
	private static String staraNazwaGrafu;
	
	public UnitexFrame() {
		super();
		
		GlassScreen ekran = new GlassScreen(this,"Ta część interfejsu jest nieaktywna w trybie podglądu");
	    getGlassPane().addMouseListener(ekran);
	    getGlassPane().addMouseMotionListener(ekran);
	    getGlassPane().addFocusListener(ekran);
	    
		final int inset = 50;
		screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		setBounds(inset, inset, screenSize.width - inset * 2, screenSize.height
				- inset * 2);
		buildContent();
		buildMenus();
		mainFrame = this;
		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				quit();
			}
		});
		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		setTitle("Edycja grafów na podstawie Unitexa");
	}
	
	public static void addInternalFrame(JInternalFrame frame) {
		desktop.add(frame, DOCLAYER);
	}

	/**
	 * Builds the menu bar.
	 */
	public void buildMenus() {
		menuBar = new JMenuBar();

		menuBar.setOpaque(true);

		JMenu fsGraph = buildFsGraphMenu();
		JMenu edit = buildEditMenu();
//		JMenu windows = buildWindowsMenu();

		fsGraph.setMnemonic(KeyEvent.VK_G);
		edit.setMnemonic(KeyEvent.VK_E);
	//	windows.setMnemonic(KeyEvent.VK_W);


		menuBar.add(fsGraph);
		menuBar.add(edit);
/*
		FileEditionMenu fileEditionMenu = new FileEditionMenu();
		fileEditionMenu.setMnemonic(KeyEvent.VK_F);
		menuBar.add(fileEditionMenu);
*/
	//	menuBar.add(windows);
		setJMenuBar(menuBar);
	}
/*
	
	AbstractAction quitUnitex;

	
	quitUnitex = new AbstractAction("Quit Unitex") {
			public void actionPerformed(ActionEvent e) {
				quit();
			}
		};
*/
	
	/**
	 * Creates the "FSGraph" menu.
	 * 
	 * @return this menu.
	 */
	public JMenu buildFsGraphMenu() {
		JMenu fsGraph = new JMenu("FSGraph");
		JMenuItem New = new JMenuItem("New");
		New.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				createNewGraphFrame();
			}
		});
		/*
		JMenuItem openGraph = new JMenuItem("Open...");
		openGraph.setAccelerator(KeyStroke.getKeyStroke('O', Event.CTRL_MASK));
		openGraph.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				openGraph();
			}
		});
		
		JMenuItem save = new JMenuItem("Save");
		save.setAccelerator(KeyStroke.getKeyStroke('S', Event.CTRL_MASK));
		save.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				GraphFrame f = UnitexFrame.getCurrentFocusedGraphFrame();
				if (f != null)
					saveGraph(f);
			}
		});
		JMenuItem saveAs = new JMenuItem("Save as...");
		saveAs.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				GraphFrame f = UnitexFrame.getCurrentFocusedGraphFrame();
				if (f != null)
					saveAsGraph(f);
			}
		});
		*/
		JMenuItem saveAll = new JMenuItem("Save All");
		saveAll.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				saveAllGraphs();
			}
		});
		JMenuItem setup = new JMenuItem("Page Setup");
		setup.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				pageSetup();
			}
		});
		JMenuItem print = new JMenuItem("Print...");
		print.setAccelerator(KeyStroke.getKeyStroke('P', Event.CTRL_MASK));
		print.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				GraphFrame f = UnitexFrame.getCurrentFocusedGraphFrame();
				if (f != null) {
					printFrame(f);
				} 
			}
		});
		JMenuItem printAll = new JMenuItem("Print All...");
		printAll.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				printAllFrames();
			}
		});
		JMenu tools = new JMenu("Tools");
		JMenuItem sortNodeLabel = new JMenuItem("Sort Node Label");
		sortNodeLabel.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				GraphFrame f = UnitexFrame.getCurrentFocusedGraphFrame();
				if (f != null) {
					f.sortNodeLabel();
				}
			}
		});
		JMenuItem explorePaths = new JMenuItem("Explore graph paths");
		explorePaths.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				GraphFrame f = UnitexFrame.getCurrentFocusedGraphFrame();
				if (f != null) {
					GraphPathFrame.showFrame();
				}
			}
		});
		JMenuItem compileFST = new JMenuItem("Compile FST2");
		compileFST.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				compileGraph();
			}
		});
		JMenuItem flatten = new JMenuItem("Compile & Flatten FST2");
		flatten.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				compileAndFlattenGraph();
			}
		});
		JMenuItem graphCollection = new JMenuItem("Build Graph Collection");
		graphCollection.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				new GraphCollectionDialog();
			}
		});
		tools.add(sortNodeLabel);
		tools.add(explorePaths);
		tools.addSeparator();
		tools.add(compileFST);
		tools.add(flatten);
		tools.addSeparator();
		tools.add(graphCollection);

		
		JMenu format = new JMenu("Format");
		JMenuItem alignment = new JMenuItem("Alignment...");
		alignment.setAccelerator(KeyStroke.getKeyStroke('M', Event.CTRL_MASK));
		alignment.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				GraphFrame f = UnitexFrame.getCurrentFocusedGraphFrame();
				if (f != null) {
					new GraphAlignmentMenu(f.graphicalZone.isGrid,
							f.graphicalZone.nPixels);
				}
			}
		});
		JMenuItem antialiasing = new JMenuItem("Antialiasing...");
		antialiasing.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				GraphFrame f = UnitexFrame.getCurrentFocusedGraphFrame();
				if (f != null) {
					f.changeAntialiasingValue();
				} 
			}
		});
		JMenuItem presentation = new JMenuItem("Presentation...");
		presentation.setAccelerator(KeyStroke
				.getKeyStroke('R', Event.CTRL_MASK));
		presentation.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				GraphFrame f = UnitexFrame.getCurrentFocusedGraphFrame();
				if (f != null) {
					new GraphPresentationMenu();
				}
			}
		});
		JMenuItem graphSize = new JMenuItem("Graph Size...");
		graphSize.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				GraphFrame f = UnitexFrame.getCurrentFocusedGraphFrame();
				if (f != null) {
					new GraphSizeMenu();
				}
			}
		});
		format.add(antialiasing);
		format.addSeparator();
		format.add(alignment);
		format.add(presentation);
		format.add(graphSize);
		JMenu zoom = new JMenu("Zoom");
		ButtonGroup groupe = new ButtonGroup();
		JRadioButtonMenuItem fitInScreen = new JRadioButtonMenuItem(
				"Fit in screen");
		JRadioButtonMenuItem fitInWindow = new JRadioButtonMenuItem(
				"Fit in window");
		JRadioButtonMenuItem fit60 = new JRadioButtonMenuItem("60%");
		JRadioButtonMenuItem fit80 = new JRadioButtonMenuItem("80%");
		JRadioButtonMenuItem fit100 = new JRadioButtonMenuItem("100%");
		JRadioButtonMenuItem fit120 = new JRadioButtonMenuItem("120%");
		JRadioButtonMenuItem fit140 = new JRadioButtonMenuItem("140%");
		groupe.add(fitInScreen);
		groupe.add(fitInWindow);
		groupe.add(fit60);
		groupe.add(fit80);
		groupe.add(fit100);
		fit100.setSelected(true);
		groupe.add(fit120);
		groupe.add(fit140);
		fitInScreen.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				GraphFrame f = UnitexFrame.getCurrentFocusedGraphFrame();
				if (f != null) {
					f.removeComponentListener(f.compListener);
					double scale_x = (double) screenSize.width
							/ (double) f.graphicalZone.Width;
					double scale_y = (double) screenSize.height
							/ (double) f.graphicalZone.Height;
					if (scale_x < scale_y)
						f.setScaleFactor(scale_x);
					else
						f.setScaleFactor(scale_y);
				}
			}
		});
		fitInWindow.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				final GraphFrame f = UnitexFrame.getCurrentFocusedGraphFrame();
				if (f != null) {
					Dimension d = f.scroll.getSize();
					double scale_x = (double) (d.width - 3)
							/ (double) f.graphicalZone.Width;
					double scale_y = (double) (d.height - 3)
							/ (double) f.graphicalZone.Height;
					if (scale_x < scale_y)
						f.setScaleFactor(scale_x);
					else
						f.setScaleFactor(scale_y);
					f.compListener = new ComponentAdapter() {
						public void componentResized(ComponentEvent e2) {
							Dimension d2 = f.scroll.getSize();
							double scale_x2 = (double) (d2.width - 3)
									/ (double) f.graphicalZone.Width;
							double scale_y2 = (double) (d2.height - 3)
									/ (double) f.graphicalZone.Height;
							if (scale_x2 < scale_y2)
								f.setScaleFactor(scale_x2);
							else
								f.setScaleFactor(scale_y2);
						}
					};
					f.addComponentListener(f.compListener);
				}
			}
		});
		fit60.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				GraphFrame f = UnitexFrame.getCurrentFocusedGraphFrame();
				if (f != null) {
					f.removeComponentListener(f.compListener);
					f.setScaleFactor(0.6);
				}
			}
		});
		fit80.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				GraphFrame f = UnitexFrame.getCurrentFocusedGraphFrame();
				if (f != null) {
					f.removeComponentListener(f.compListener);
					f.setScaleFactor(0.8);
				}
			}
		});
		fit100.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				GraphFrame f = UnitexFrame.getCurrentFocusedGraphFrame();
				if (f != null) {
					f.removeComponentListener(f.compListener);
					f.setScaleFactor(1.0);
				}
			}
		});
		fit120.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				GraphFrame f = UnitexFrame.getCurrentFocusedGraphFrame();
				if (f != null) {
					f.removeComponentListener(f.compListener);
					f.setScaleFactor(1.2);
				}
			}
		});
		fit140.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				GraphFrame f = UnitexFrame.getCurrentFocusedGraphFrame();
				if (f != null) {
					f.removeComponentListener(f.compListener);
					f.setScaleFactor(1.4);
				}
			}
		});
		zoom.add(fitInScreen);
		zoom.add(fitInWindow);
		zoom.add(fit60);
		zoom.add(fit80);
		zoom.add(fit100);
		zoom.add(fit120);
		zoom.add(fit140);
		JMenuItem closeAll = new JMenuItem("Close all");
		closeAll.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				closeAll();
			}
		});
	//	fsGraph.add(New);
		//fsGraph.add(openGraph);
	//	fsGraph.addSeparator();
//		fsGraph.add(save);
	//	fsGraph.add(saveAs);
	//	fsGraph.add(saveAll);
	//	fsGraph.addSeparator();
	//	fsGraph.add(setup);
	//	fsGraph.add(print);
	//	fsGraph.add(printAll);
	//	fsGraph.addSeparator();
	//	fsGraph.add(tools);
		fsGraph.add(format);
		fsGraph.add(zoom);
		fsGraph.addSeparator();
//		fsGraph.add(closeAll);
		return fsGraph;
	}

	/**
	 * Creates the "Edit" menu.
	 * 
	 * @return this menu.
	 */
	public JMenu buildEditMenu() {
		JMenu edit = new JMenu("Edit");
		JMenuItem cut = new JMenuItem("Cut");
		cut.setAccelerator(KeyStroke.getKeyStroke('X', Event.CTRL_MASK));
		cut.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				final ActionEvent E = e;
				
					GraphFrame f = UnitexFrame.getCurrentFocusedGraphFrame();
					if (f != null) {
						((TextField) (f.graphicalZone.texte)).cut
								.actionPerformed(E);
						f.graphicalZone.repaint();
					}
				
			}
		});
		cut.setEnabled(true);
		JMenuItem copy = new JMenuItem("Copy");
		copy.setAccelerator(KeyStroke.getKeyStroke('C', Event.CTRL_MASK));
		copy.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				final ActionEvent E = e;
			
					GraphFrame f = UnitexFrame.getCurrentFocusedGraphFrame();
					if (f != null) {
						((TextField) (f.graphicalZone.texte)).specialCopy
								.actionPerformed(E);
						f.graphicalZone.repaint();
					}
				
			}
		});
		copy.setEnabled(true);
		JMenuItem paste = new JMenuItem("Paste");
		paste.setAccelerator(KeyStroke.getKeyStroke('V', Event.CTRL_MASK));
		paste.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				final ActionEvent E = e;
				
					GraphFrame f = UnitexFrame.getCurrentFocusedGraphFrame();
					if (f != null) {
						((TextField) (f.graphicalZone.texte)).specialPaste
								.actionPerformed(E);
						f.graphicalZone.repaint();
					}
				
			}
		});
		paste.setEnabled(true);
		JMenuItem selectAll = new JMenuItem("Select All");
		selectAll.setAccelerator(KeyStroke.getKeyStroke('A', Event.CTRL_MASK));
		selectAll.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				
					GraphFrame f = UnitexFrame.getCurrentFocusedGraphFrame();
					if (f != null) {
						f.graphicalZone.selectAllBoxes();
						f.graphicalZone.repaint();
					}
				
			}
		});
		selectAll.setEnabled(true);
		edit.add(cut);
		edit.add(copy);
		edit.add(paste);
		edit.add(selectAll);
		return edit;
	}

	/**
	 * Creates the "Windows" menu.
	 * 
	 * @return this menu.
	 */
	public JMenu buildWindowsMenu() {
		JMenu windows = new JMenu("Windows");
		JMenuItem tile = new JMenuItem("Tile");
		tile.setEnabled(true);
		tile.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				tileFrames();
			}
		});
		JMenuItem cascade = new JMenuItem("Cascade");
		cascade.setEnabled(true);
		cascade.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				cascadeFrames();
			}
		});
		JMenuItem arrangeIcons = new JMenuItem("Arrange Icons");
		arrangeIcons.setEnabled(true);
		arrangeIcons.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				arrangeIcons();
			}
		});
		windows.add(tile);
		windows.add(cascade);
		windows.add(arrangeIcons);
		return windows;
	}

	void buildContent() {
		desktop = new JDesktopPane();
		setContentPane(desktop);
	}


	

	/**
	 * Creates and adds to the desktop a new <code>GraphFrame</code>.
	 *  
	 */
	public void createNewGraphFrame() {
		GraphFrame doc = new GraphFrame(false);
		desktop.add(doc, DOCLAYER);
		try {
			doc.setVisible(true);
			doc.setSelected(true);
			doc.setIcon(false);
		} catch (java.beans.PropertyVetoException e2) {
			e2.printStackTrace();
		}
	}
	/**
	 * Launch the page setup for printing.
	 *  
	 */
	public void pageSetup() {
		if (printerJob == null) {
			printerJob = PrinterJob.getPrinterJob();
		}
		if (pageFormat == null) {
			pageFormat = printerJob.defaultPage();
		}
		pageFormat = printerJob.pageDialog(pageFormat);
	}

	/**
	 * Prints a <code>GraphFrame</code>.
	 * 
	 * @param g
	 *            the <code>GraphFrame</code> to be printed.
	 */
	public void printFrame(GraphFrame g) {
		if (printerJob == null) {
			printerJob = PrinterJob.getPrinterJob();
		}
		if (pageFormat == null) {
			pageFormat = printerJob.defaultPage();
		}
		printerJob.setPrintable(g.graphicalZone, pageFormat);
		if (printerJob.printDialog()) {
			try {
				printerJob.print();
			} catch (PrinterException e) {
				JOptionPane.showMessageDialog(null,
						"Error while printing graph", "Error",
						JOptionPane.ERROR_MESSAGE);
			}
		}
	}

	

	/**
	 * Prints all the <code>GraphFrame</code> s that are on the desktop.
	 */
	public void printAllFrames() {
		JInternalFrame[] frames = desktop.getAllFrames();
		if (frames.length == 0)
			return;
		if (printerJob == null) {
			printerJob = PrinterJob.getPrinterJob();
		}
		if (pageFormat == null) {
			pageFormat = printerJob.defaultPage();
		}
		if (!printerJob.printDialog())
			return;
		for (int i = 0; i < frames.length; i++) {
			if (frames[i] instanceof GraphFrame) {
				printerJob.setPrintable(((GraphFrame) frames[i]).graphicalZone,
						pageFormat);
				try {
					printerJob.print();
				} catch (PrinterException e) {
					JOptionPane.showMessageDialog(null,
							"Error while printing graph", "Error",
							JOptionPane.ERROR_MESSAGE);
				}
			}
		}
	}
	/**
	 * Shows a dialog box to select on or more graphs. The selected graphs are
	 * opened with a call to the <code>loadGraph(String,String,String)</code>
	 * method.
	 * @throws FileNotFoundException 
	 */
	public void openGraph(Graf graf) throws FileNotFoundException {
		
		ConvertOneFileFrame.reset();
		File graph = GraphManager.getFile(graf);
		
			String s = graph.getAbsolutePath();
			if (!s.endsWith(".grf")) {
				s = s + ".grf";
				graph = new File(s);
			}
			Config.setCurrentGraphDir(graph.getParentFile());
			loadGraph(graph);
			staraTrescGrafu = graf.getContent();
		
	}

	/**
	 * Tests if a graph is allready open on the desktop.
	 * 
	 * @param grf
	 *            the name of the graph
	 * @return the <code>GraphFrame</code> if the graph is allready open, or
	 *         <code>null</code> otherwise
	 */
	public GraphFrame graphIsAllreadyOpen(File grf) {
		JInternalFrame[] frames = desktop.getAllFrames();
		for (int i = 0; i < frames.length; i++) {
			if (frames[i] instanceof GraphFrame) {
				GraphFrame f = (GraphFrame) frames[i];
				if (grf.equals(f.getGraph())) {
					return f;
				}
			}
		}
		return null;
	}

	class LoadGraphDo extends ToDoAbstract {
		File file;

		LoadGraphDo(File s) {
			file = s;
		}

		public void toDo() {
			SwingUtilities.invokeLater(new Runnable() {
				public void run() {
					try {
						UnitexFrame.mainFrame.loadGraph(file);
					} catch (FileNotFoundException e) {
						
						e.printStackTrace();
					}
				}
			});
		}

	}

	/**
	 * loads a graph. If the graph is allready open, its <code>GraphFrame</code>
	 * is focused, otherwise, a new <code>GraphFrame</code> is created, added
	 * to the desktop and focused.
	 * 
	 * @param grf
	 *            the complete name of the graph: path and file name
	 * @throws FileNotFoundException 
	 */
	public void loadGraph(File grf) throws FileNotFoundException {
		GraphFrame doc;
		if ((doc = graphIsAllreadyOpen(grf)) != null) {
			// we verify if the graph is allready opened
			// in this case, we bring it back to front
			try {
				doc.setVisible(true);
				doc.setSelected(true);
				doc.setIcon(false);
			} catch (java.beans.PropertyVetoException e2) {
				e2.printStackTrace();
			}
			return;
		}
//		try {
			if (!UnicodeIO.isAUnicodeLittleEndianFile(grf)) {
				ConvertCommand res = ConvertOneFileFrame
						.getCommandLineForConversion(grf);
				if (res == null) {
					return;
				}
				new ProcessInfoFrame(res, true, new LoadGraphDo(grf));
				return;
			}/*
		} catch (FileNotFoundException e) {
			JOptionPane
					.showMessageDialog(null, "Cannot open "
							+ grf.getAbsolutePath(), "Error",
							JOptionPane.ERROR_MESSAGE);
			return;
		}*/
		GraphIO g = GraphIO.loadGraph(grf);
		if (g == null)
			return;
		doc = new GraphFrame(true);
		doc.graphicalZone.pref = g.pref;
		doc.graphicalZone.pref.antialiasing = Preferences.getCloneOfPreferences().antialiasing;
		doc.texte.setFont(doc.graphicalZone.pref.input);
		doc.graphicalZone.Width = g.width;
		doc.graphicalZone.Height = g.height;
		doc.graphicalZone.graphBoxes = g.boxes;
		doc.scroll.setPreferredSize(new Dimension(g.width, g.height));
		doc.graphicalZone.setPreferredSize(new Dimension(g.width, g.height));
		doc.setGraph(grf);
		doc.setTitle(grf.getAbsolutePath());
		UnitexFrame.addInternalFrame(doc);
		try {
			doc.setVisible(true);
			doc.setSelected(true);
			doc.setIcon(false);
		} catch (java.beans.PropertyVetoException e2) {
			e2.printStackTrace();
		}
	}

	/**
	 * Opens a "Save As" dialog box to save a graph. The graph is actually saved
	 * by a call to the <code>GraphFrame.saveGraph(String)</code> method.
	 * 
	 * @param f
	 *            the <code>GraphFrame</code> to be saved
	 */
	@SuppressWarnings("unchecked")
	public boolean saveAsGraph(GraphFrame f) {
		if (f == null)
			return false;
		GraphIO g = new GraphIO();
		g.boxes = f.graphicalZone.graphBoxes;
		g.pref = f.graphicalZone.pref;
		g.width = f.graphicalZone.Width;
		g.height = f.graphicalZone.Height;
		
		/*
		JFileChooser fc=Config.getGraphDialogBox(true);
		fc.setMultiSelectionEnabled(false);
		fc.setDialogType(JFileChooser.SAVE_DIALOG);
		int returnVal = fc.showSaveDialog(this);
		fc.setMultiSelectionEnabled(true);
		if (returnVal != JFileChooser.APPROVE_OPTION) {
			// we return if the user has clicked on CANCEL
			return false;
		}
		File file = fc.getSelectedFile();
		*/
		int res = SaveGraphDialog.invokeSaveGraphDialog(this);
		if (res==0) return false; /* anuluj - wracamy */
		if (res<0) return true; /* nie zapisuj - wychodzimy bez zapisywania */
		
		File file = new File(ToposlawConfig.getGraphDir()+SaveGraphDialog.grafName+".grf");
		String name = file.getAbsolutePath();
		// if the user wants to save the graph as an image 
		if (name.endsWith(".png") || name.endsWith(".PNG")) {
			// we do not change the "modified" status and the title of the
			// frame 
			f.saveGraphAsAnImage(file);
			return true;
		}

		if (!name.endsWith(".grf")) {
			file = new File(name + ".grf");
		}
		f.modified = false;
		g.saveGraph(file);
		f.setGraph(file);
		f.setTitle(file.getAbsolutePath());
		return true;
	}

	/**
	 * If the graph has no name, the <code>saveAsGraph(GraphFrame)</code> is
	 * called. Otherwise, the graph is saved by a call to the
	 * <code>GraphFrame.saveGraph(String)</code> method.
	 * 
	 * @param f
	 *            the <code>GraphFrame</code> to be saved
	 * @param grafFile2 
	 */
	@SuppressWarnings("unchecked")
	public boolean saveGraph(GraphFrame f, File grafFile2) {
		if (f == null)
			return false;
		File file = f.getGraph();
		if (file == null) {
			file = grafFile2;
		}
		GraphIO g = new GraphIO();
		g.boxes = f.graphicalZone.graphBoxes;
		g.pref = f.graphicalZone.pref;
		g.width = f.graphicalZone.Width;
		g.height = f.graphicalZone.Height;
		f.modified = false;
		g.saveGraph(file);
		f.setTitle(file.getAbsolutePath());
		return true;
	}

	/**
	 * Saves all <code>GraphFrame</code> s that are on the desktop.
	 *  
	 */
	public void saveAllGraphs() {
		JInternalFrame[] frames = desktop.getAllFrames();
		for (int i = 0; i < frames.length; i++) {
		/*	if (frames[i] instanceof GraphFrame) {
				saveGraph((GraphFrame) frames[i]);
			}*/
		}
	}

	/**
	 * Closes all <code>GraphFrame</code> s that are on the desktop.
	 *  
	 */
	public void closeAll() {
		JInternalFrame[] frames = desktop.getAllFrames();
		for (int i = 0; i < frames.length; i++) {
			if (frames[i] instanceof GraphFrame) {
				((GraphFrame) frames[i]).doDefaultCloseAction();
			}
		}
	}



	/**
	 * Shows a window that offers the user to compile and flatten a graph. If
	 * the user clicks on the "OK" button, the compilation process is launched
	 * through the creation of a <code>ProcessInfoFrame</code> object.
	 *  
	 */
	public void compileAndFlattenGraph() {
		GraphFrame currentFrame = getCurrentFocusedGraphFrame();
		if (currentFrame == null)
			return;
		if (currentFrame.modified == true) {
			JOptionPane.showMessageDialog(null,
					"Save graph before compiling it", "Error",
					JOptionPane.ERROR_MESSAGE);
			return;
		}
		File grf = currentFrame.getGraph();
		if (grf == null) {
			JOptionPane.showMessageDialog(null,
					"Cannot compile a graph with no name", "Error",
					JOptionPane.ERROR_MESSAGE);
			return;
		}
		JPanel mainpane = new JPanel();
		mainpane.setLayout(new BorderLayout());
		JPanel pane = new JPanel();
		pane.setLayout(new GridLayout(2, 1));
		pane.setBorder(new TitledBorder("Expected result grammar format:"));
		JRadioButton rtn = new JRadioButton(
				"equivalent FST2 (subgraph calls may remain)");
		JRadioButton fst = new JRadioButton(
				"Finite State Transducer (can be just an approximation)");
		ButtonGroup bg = new ButtonGroup();
		bg.add(rtn);
		bg.add(fst);
		rtn.setSelected(true);
		/*JPanel subpane = new JPanel();
		subpane.setBorder(new TitledBorder("Flattening depth:"));
		subpane.setLayout(new FlowLayout(SwingConstants.HORIZONTAL));
		subpane.add(new JLabel("Maximum flattening depth: "));
		NumericTextField depth = new NumericTextField(4, String.valueOf(10));
		subpane.add(depth);*/
		pane.add(rtn);
		pane.add(fst);
		mainpane.add(pane, BorderLayout.CENTER);
		//mainpane.add(subpane, BorderLayout.SOUTH);

		Object[] options = {"OK", "Cancel"};
		if (0 == JOptionPane.showOptionDialog(null, mainpane,
				"Compile & Flatten", JOptionPane.YES_NO_OPTION,
				JOptionPane.QUESTION_MESSAGE, null, options, options[0])) {
			/*if (depth.getText().equals("") || depth.getText().equals("0")) {
				JOptionPane.showMessageDialog(null, "Invalid depth value",
						"Error", JOptionPane.ERROR_MESSAGE);
				return;
			}*/
			String name_fst2 = grf.getAbsolutePath().substring(0,
					grf.getAbsolutePath().length() - 4);
			name_fst2 = name_fst2 + ".fst2";

			MultiCommands commands = new MultiCommands();
			commands.addCommand(new Grf2Fst2Command().grf(grf).tokenizationMode().library());
			commands.addCommand(new FlattenCommand().fst2(new File(name_fst2))
					.resultType(!rtn.isSelected())
					//.depth("depth.getText()"));
					.depth(1));
			if(Config.isKorean()) {
				File map_encoder = new File(Config.getUserCurrentLanguageDir(),"jamoTable.txt");
				if(map_encoder.exists()){
					Syl2JamoCommand sy2jamoConv = new Syl2JamoCommand()
					.optionForIncludeJamo()
					.optionForMapJamo(map_encoder)
					.optionRemplace()
					.src(new File(name_fst2));
					
					commands.addCommand(sy2jamoConv);
			
				}
			}

			new ProcessInfoFrame(commands, false);
		}
	}
	/**
	 * Shows a window that offers the user to compile graphs with head graph. If
	 * the user clicks on the "OK" button, the compilation process is launched
	 * through the creation of a <code>ProcessInfoFrame</code> object.
	 *  
	 */
	JTextField destDirectory = new JTextField("");


	/**
	 * Tiles all the frames that are on the desktop and that are not iconified.
	 *  
	 */
	public void tileFrames() {
		JInternalFrame[] f = desktop.getAllFrames();
		int openFrameCount = 0;
		for (int i = 0; i < f.length; i++) {
			if (f[i].isVisible() && !f[i].isIcon()) {
				openFrameCount++;
			}
		}
		if (openFrameCount == 0)
			return;
		Dimension bounds = getContentPane().getSize();
		if (openFrameCount == 1) {
			for (int i = 0; i < f.length; i++) {
				try {
					JInternalFrame F = f[i];
					if (F.isVisible() && !F.isIcon()) {
						F.setBounds(0, 0, bounds.width, bounds.height);
					}
				} catch (ClassCastException e) {
					// nothing to do
				}
				return;
			}
		}
		if (openFrameCount == 2) {
			for (int i = 0; i < f.length; i++) {
				try {
					JInternalFrame F = f[i];
					if (F.isVisible() && !F.isIcon()) {
						if (openFrameCount == 2)
							F.setBounds(0, 0, bounds.width, bounds.height / 2);
						else
							F.setBounds(0, bounds.height / 2, bounds.width,
									bounds.height / 2);
					}
					openFrameCount--;
				} catch (ClassCastException e) {
					// nothing to do
				}
			}
			return;
		}
		if (openFrameCount == 3) {
			for (int i = 0; i < f.length; i++) {
				try {
					JInternalFrame F = f[i];
					if (F.isVisible() && !F.isIcon()) {
						if (openFrameCount == 3)
							F.setBounds(0, 0, bounds.width, bounds.height / 3);
						else if (openFrameCount == 2)
							F.setBounds(0, bounds.height / 3, bounds.width,
									bounds.height / 3);
						else
							F.setBounds(0, 2 * bounds.height / 3, bounds.width,
									bounds.height / 3);
					}
					openFrameCount--;
				} catch (ClassCastException e) {
					// nothing to do
				}
			}
			return;
		}
		int premiere_moitie = openFrameCount / 2;
		int seconde_moitie = openFrameCount - premiere_moitie;
		openFrameCount = 0;
		// drawing frames on the first half of screen
		int i;
		for (i = 0; i < f.length && openFrameCount < premiere_moitie; i++) {
			try {
				JInternalFrame F = f[i];
				if (F.isVisible() && !F.isIcon()) {
					F.setBounds(0, openFrameCount * bounds.height
							/ premiere_moitie, bounds.width / 2, bounds.height
							/ premiere_moitie);
				}
				openFrameCount++;
			} catch (ClassCastException e) {
				// nothing to do
			}
		}
		// drawing frames on the second half of screen
		openFrameCount = 0;
		for (; i < f.length && openFrameCount < seconde_moitie; i++) {
			try {
				JInternalFrame F = f[i];
				if (F.isVisible() && !F.isIcon()) {
					F.setBounds(bounds.width / 2, openFrameCount
							* bounds.height / seconde_moitie, bounds.width / 2,
							bounds.height / seconde_moitie);
				}
				openFrameCount++;
			} catch (ClassCastException e) {
				// nothing to do
			}
		}
	}

	/**
	 * Cascades all the frames that are on the desktop and that are not
	 * iconified.
	 *  
	 */
	public void cascadeFrames() {
		Component[] f = desktop.getComponents();
		int openFrameCount = 0;
		final int offset = 30;
		for (int i = 0; i < f.length; i++) {
			try {
				JInternalFrame F = (JInternalFrame) f[i];
				if (F.isVisible() && !F.isIcon()) {
					openFrameCount++;
					F.setBounds(offset * (openFrameCount % 6), offset
							* (openFrameCount % 6), 800, 600);
					try {
						F.setSelected(true);
					} catch (java.beans.PropertyVetoException e) {
						e.printStackTrace();
					}
				}
			} catch (ClassCastException e) {
				// nothing to do
			}
		}
	}

	/**
	 * Arranges all the iconified frames that are on the desktop.
	 *  
	 */
	public void arrangeIcons() {
		Component[] f = desktop.getComponents();
		int openFrameCount = 0;
		Dimension desktop_bounds = getContentPane().getSize();
		for (int i = 0; i < f.length; i++) {
			try {
				JInternalFrame.JDesktopIcon F = (JInternalFrame.JDesktopIcon) f[i];
				if (F.isVisible()) {
					Dimension icon_bounds = F.getSize();
					int X, Y;
					int n_icons_by_line = (desktop_bounds.width)
							/ (icon_bounds.width);
					if (n_icons_by_line == 0)
						n_icons_by_line = 1;
					X = openFrameCount % n_icons_by_line;
					Y = openFrameCount / n_icons_by_line;
					F.setBounds(X * icon_bounds.width, desktop_bounds.height
							- (Y + 1) * icon_bounds.height, icon_bounds.width,
							icon_bounds.height);
					openFrameCount++;
				}
			} catch (ClassCastException e) {
				// nothing to do
			}
		}
	}


	public static JDesktopPane getDesktop() {
		return desktop;
	}

	public static JInternalFrame getCurrentFocusedFrame() {
		return desktop.getSelectedFrame();
	}

	public static GraphFrame getCurrentFocusedGraphFrame() {
		JInternalFrame frame = getCurrentFocusedFrame();
		if (frame instanceof GraphFrame)
			return (GraphFrame) frame;
		return null;
	}

	public static void removeInternalFrame(JInternalFrame f) {
		desktop.remove(f);
	}

	/*
	 * modifications follow 
	 */

	/**
	 * Compiles the current focused <code>GraphFrame</code>. If the graph is
	 * unsaved, an error message is shown and nothing is done; otherwise the
	 * compilation process is launched through the creation of a
	 * <code>ProcessInfoFrame</code> object.
	 *  
	 */
	public void compileGraph() {
		GraphFrame currentFrame = getCurrentFocusedGraphFrame();
		if (currentFrame == null)
			return;
		if (currentFrame.modified == true) {
			JOptionPane.showMessageDialog(null,
					"Save graph before compiling it", "Error",
					JOptionPane.ERROR_MESSAGE);
			return;
		}
		if (currentFrame.getGraph() == null) {
			JOptionPane.showMessageDialog(null,
					"Cannot compile a graph with no name", "Error",
					JOptionPane.ERROR_MESSAGE);
			return;
		}
		if(Config.isKorean()) {
			MultiCommands commands = new MultiCommands();
			File grf = new File(currentFrame.getGraph().getAbsolutePath());
			String name_fst_sans_ex= grf.getAbsolutePath().substring(0,
					grf.getAbsolutePath().length() - 4);
			
			Grf2Fst2Command command = new Grf2Fst2Command().grf(grf).tokenizationMode().library();
			commands.addCommand(command);

			File map_encoder = new File(Config.getUserCurrentLanguageDir()
					,"jamoTable.txt");
			if(map_encoder.exists()){
				Syl2JamoCommand sy2jamoConv = new Syl2JamoCommand()
				.optionForIncludeJamo()
				.optionForMapJamo(map_encoder)
				.optionRemplace()
				.src(new File(name_fst_sans_ex + ".fst2"));
				commands.addCommand(sy2jamoConv);
			}

			new ProcessInfoFrame(commands, false);

		} else {
			Grf2Fst2Command command = new Grf2Fst2Command().grf(currentFrame.getGraph()).tokenizationMode().library();
			ProcessCommand p= new ProcessCommand(command);
			p.launchBuilderCommands();
			
		}

	}

	
	
	public static void invokeEdit(Graf _staryGraf, boolean newGraph, boolean overwrite, boolean dontEdit) {
		
		
		
		Config.initConfig();
		staryGraf = _staryGraf;
		UnitexFrame frame = new UnitexFrame();
		if (dontEdit) frame.mode=MODE_PODGLAD;
		else 
		if (newGraph) {
			frame.mode = MODE_NOWY;
		}
		else {
			if (overwrite) frame.mode = MODE_EDYTUJ;
			else frame.mode = MODE_NOWY_NA_PODSTAWIE;
		}

		frame.setVisible(true);
		if (_staryGraf!=null) {
			try {
				GraphManager.prepareGraph(_staryGraf);
			} catch (IOException e) {
				e.printStackTrace();
				frame.quit();
				return;
			}
			frame.grafFile = GraphManager.getFile(_staryGraf);
		}
		
		NazwaGrafuTextField poleNazwy; 
		
		if (frame.mode!=MODE_NOWY) {
			GraphRepresentation gr = GraphRepresentationIO.loadGraphRepresentation(staryGraf);
			if (!gr.nameFitsTheGraph()) {
				frame.message("Nazwa grafu nie odpowiada jego treści!");
			}
		}
		
		switch (frame.mode) {
		case MODE_NOWY:
			try {
				frame.openGraph(_staryGraf);
				poleNazwy =  NazwaGrafuTextField.getInstance();
				poleNazwy.initText("");
			} catch (FileNotFoundException e1) {
				e1.printStackTrace();
			}
			
			
			break;
		case MODE_NOWY_NA_PODSTAWIE:			
			try {
				frame.openGraph(_staryGraf);
			}
			catch (Exception e) {
				NarzedzieMsg.error("Nie odnaleziono pliku z grafem.", e);
				frame.myDispose();
				return;
			}

			poleNazwy =  NazwaGrafuTextField.getInstance();
			poleNazwy.initText(frame.obetnijKodNazwy(_staryGraf.getName()));
			break;
		case MODE_EDYTUJ:
			try {
				staraNazwaGrafu = staryGraf.getName();
				staraTrescGrafu = GraphRaw.getRawGrfFileContent(GraphManager.getFile(_staryGraf));
				frame.openGraph(_staryGraf);
			} catch (Exception e) {
			//	e.printStackTrace();
				NarzedzieMsg.error("Nie odnaleziono pliku z grafem.", e);
				frame.myDispose();
				return;
			}

			poleNazwy =  NazwaGrafuTextField.getInstance();
			poleNazwy.initText(frame.obetnijKodNazwy(_staryGraf.getName()));
			break;
		case MODE_PODGLAD:
			try {
				frame.openGraph(_staryGraf);
			}
			catch (Exception e) {
				NarzedzieMsg.error("Nie odnaleziono pliku z grafem.", e);
				frame.myDispose();
				return;
			}
			poleNazwy =  NazwaGrafuTextField.getInstance();
			poleNazwy.initText(frame.obetnijKodNazwy(_staryGraf.getName()));
			Component glass = frame.getGlassPane();
			glass.requestFocus();
			glass.setVisible(true);
			break;
		}
		frame.repaint();
		
	}
	
	public boolean myCompileGraph() {
		NazwaGrafuTextField poleNazwy = NazwaGrafuTextField.getInstance();
		String grafName1 = getKodNazwy() + poleNazwy.getText();
		File grafFile1 = new File(ToposlawConfig.getGraphDir()+grafName1+".grf");
		
		try {
			return KompilacjaGrafu.kompilujGraf(grafFile1);
		}
		catch (Exception e) {
			NarzedzieMsg.error("Nie powiodła się kompilacja grafu z powodu wyjątku:", e);
			return false;
		}
		
	}
	
	
	public boolean mySaveGraph(File _grafFile) {
		getCurrentFocusedGraphFrame().setGraph(_grafFile);
		saveGraph(getCurrentFocusedGraphFrame(), _grafFile);
		try {
			return KompilacjaGrafu.kompilujGraf(_grafFile);
		}
		catch (Exception e) {
			NarzedzieMsg.error("Nie powiodła się kompilacja grafu z powodu wyjątku:", e);
			return false;
		}
		
	}
	
	public void myDispose() {
		this.dispose();
		NarzedzieView.getInstance().blokowanieWszystkiego(false);
	}
	
	/**
	 * This method is called when the user tries to close the main window, or
	 * when he clicks on the "Quit Unitex" item in the "Text" menu.
	 *  
	 */
	public void quit() { 

		GrafyActions akcje = new GrafyActions();
		NazwaGrafuTextField poleNazwy = NazwaGrafuTextField.getInstance();
		grafName = getKodNazwy() + poleNazwy.getText();
		grafFile = new File(ToposlawConfig.getGraphDir()+grafName+".grf");
		
		if (grafName.compareTo("")==0) {
			if (NarzedzieMsg.question("Jeśli chcesz zapisać graf, musisz wpierw wpisać jego nazwę.\n"+
						"Czy chcesz wrócić do edycji grafu by zapisać jego nazwę?",this))
				return;
			myDispose();
			return;
		}
		boolean czyGrafIstnieje = ListaGrafowModel.getModel().czyGrafIstnieje(grafName);
		if (czyGrafIstnieje && mode!=MODE_PODGLAD && ((mode!=MODE_EDYTUJ) || (mode==MODE_EDYTUJ && !staraNazwaGrafu.equals(grafName)))) {
			String[] options = {"Wyjdź bez zapisywania","Wróć do edycji"};
			String nieEdycja = "Istnieje już graf o podanej nazwie.\n";
			String edycja = "Nazwa grafu została zmieniona na nazwę innego istniejącego grafu.\n"+
							"Nie można go w ten sposób nadpisać.";
			String opcja = "";	
			if (mode==MODE_EDYTUJ) opcja = edycja;
			else opcja = nieEdycja;
			int n = JOptionPane.showOptionDialog(this,
					 opcja +
					"",
				    "Pytanie",
				    JOptionPane.YES_NO_OPTION,
				    JOptionPane.QUESTION_MESSAGE,
				    null,     //do not use a custom Icon
				    options,  //the titles of buttons
				    options[1]);
			if (n==JOptionPane.YES_OPTION) {
				myDispose();
			}
			return;
			
		}
		
		if (czyGrafIstnieje && mode==MODE_EDYTUJ && !staraNazwaGrafu.equals(grafName)) {
			String[] options = {"Wyjdź bez zapisywania","Wróć do edycji"};
			int n = JOptionPane.showOptionDialog(this,
					"Istnieje już graf o podanej nazwie.\n" +
					"",
				    "Pytanie",
				    JOptionPane.YES_NO_OPTION,
				    JOptionPane.QUESTION_MESSAGE,
				    null,     //do not use a custom Icon
				    options,  //the titles of buttons
				    options[1]);
			if (n==JOptionPane.YES_OPTION) {
				myDispose();
			}
			return;
		}
			
		
		switch (mode) {
		case MODE_NOWY:
			mySaveGraph(grafFile);
			akcje.dodajNowyGraf(grafName);
			this.myDispose();
			break;
		case MODE_NOWY_NA_PODSTAWIE:
			mySaveGraph(grafFile);
			akcje.dodajNowyGraf(grafName);
			this.myDispose();
			break;
		case MODE_EDYTUJ:
			int odp = NarzedzieMsg.ODP_TAK;
			if (getCurrentFocusedGraphFrame().modified || NazwaGrafuTextField.getInstance().isModified()) {
			 odp = NarzedzieMsg.question3("Czy na pewno chcesz zapisać zmiany w grafie?",this);
			}
			//else odp = -20;
			switch (odp) {
			case NarzedzieMsg.ODP_TAK:
				mySaveGraph(grafFile);
				grafName = getKodNazwy()+ NazwaGrafuTextField.getInstance().getText();
				akcje.edytujGraf(grafName,staryGraf,staraTrescGrafu);
					myDispose();
				break;

			case NarzedzieMsg.ODP_NIE:
					myDispose();
				break;
			
			case NarzedzieMsg.ODP_ANULUJ:
				
				break;
				
			default:
					myDispose();
				break;
			}
			break;
		case MODE_PODGLAD:
			myDispose();
			break;
		}
	}
	
	String getKodNazwy() {
		if (kodNazwyGrafu==null) {
			String kodNazwy = "NC-";
			Vector<Czlon> czlony = NarzedzieModel.getModel().getNazwa().getCzlony();
			Iterator<Czlon> i = czlony.iterator();
			while (i.hasNext()) {
				Czlon cz = i.next();
				switch (cz.getOdmienny()) {
					case NIEODMIENNY: kodNazwy += "N" ; break;
					case ODMIENNY: kodNazwy += "O" ; break;
					case SPACJA: kodNazwy += "_" ; break;
				}
			}
			kodNazwyGrafu = kodNazwy;
		}
		return kodNazwyGrafu;
	}
	
	//boolean nowyKod = false;
	String obetnijKodNazwy(String input) {
		String result = "";
		String kodNazwy = getKodNazwy();
		//TODO: ask for confirmation if kod nazwy changes
		if (!input.startsWith(kodNazwy) && mode==MODE_EDYTUJ)	{
		//	nowyKod = true;
			message("Uwaga! Automatycznie generowany prefiks nazwy jest inny niż w oryginalnym grafie.");
			getCurrentFocusedGraphFrame().modified = true;
		}
		if (input.length()>kodNazwy.length())
			result = input.substring(kodNazwy.length());
		return result;
	}

	public void message(String string) {
		JOptionPane.showMessageDialog(this,
			    string,
			    "Wiadomość", //$NON-NLS-1$
			    JOptionPane.PLAIN_MESSAGE);
	}
	
}
package ndosownww.unitex.changes;



	import java.io.*;
	import java.util.regex.*;

	/**
	 * This class provides methods to get information about files, like path, file
	 * name or extension.
	 * 
	 * @author Sébastien Paumier
	 *  
	 */
	public class Util {

		/**
		 * Returns the name without extension of a file.
		 * 
		 * @param s
		 *            the file name
		 * @return the name without extension
		 */
		public static String getFileNameWithoutExtension(String s) {
			int n = s.lastIndexOf('.');
			if ((n == -1) || (n < s.lastIndexOf(File.separatorChar)))
				return s;
			return s.substring(0, n);
		}
		
		/**
		 * Returns the name without extension of a file.
		 * 
		 * @param f
		 *            the file name
		 * @return the name without extension
		 */
		public static String getFileNameWithoutExtension(File f) {
			return getFileNameWithoutExtension(f.getAbsolutePath());
		}
		/**
		 * Returns the extension of a file.
		 * 
		 * @param s
		 *            the file name
		 * @return the extension if there is one, the empty string otherwise
		 */
		public static String getFileNameExtension(String s) {
			int n = s.lastIndexOf('.');
			if ((n == -1) || (n < s.lastIndexOf(File.separatorChar)))
				return "";
			return s.substring(n + 1);
		}

		/**
		 * Returns the extension of a file. This method is equivalent to a call to
		 * <code>Util.getFileNameExtension(f.getName())</code>.
		 * 
		 * @param f
		 *            the file
		 * @return the extension if there is one, the empty string otherwise
		 */
		public static String getFileNameExtension(File f) {
			return getFileNameExtension(f.getName());
		}

		/**
		 * Returns the path name of a file, without the file name.
		 * 
		 * @param s
		 *            the file name
		 * @return the path
		 */
		public static String getFilePathWithoutFileName(String s) {
			int n = s.lastIndexOf(File.separatorChar);
			if (n == -1)
				return "";
			return s.substring(0, n + 1);
		}

		/**
		 * Returns the path name of a file, without the file name. This method is
		 * equivalent to a call to
		 * <code>getFilePathWithoutFileName(f.getName())</code>.
		 * 
		 * @param f
		 *            the file
		 * @return the path
		 */
		public static String getFilePathWithoutFileName(File f) {
			return getFilePathWithoutFileName(f.getAbsolutePath());
		}

		/**
		 * Returns the file name of a file, without the path.
		 * 
		 * @param f
		 *            the file
		 * @return the file name, without the path
		 */
		public static String getFileNameWithoutFilePath(File f) {
			return f.getName();
		}

		/**
		 * Returns the file name of a file, without the path. This method is
		 * equivalent to a call to
		 * <code>getFileNameWithoutFilePath(new File(s))</code>.
		 * 
		 * @param s
		 *            the file name
		 * @return the file name, without the path
		 */
		public static String getFileNameWithoutFilePath(String s) {
			return getFileNameWithoutFilePath(new File(s));
		}

		/**
		 * Returns the extension in lower case of a file
		 * 
		 * @param s
		 *            file name
		 * @return the extension
		 */
		public static String getExtensionInLowerCase(String s) {
			return getExtensionInLowerCase(new File(s));
		}

		/**
		 * Returns the extension in lower case of a file
		 * 
		 * @param f
		 *            the file
		 * @return the extension
		 */
		public static String getExtensionInLowerCase(File f) {
			String ext = "";
			String s = f.getName();
			int i = s.lastIndexOf('.');
			if (i > 0 && i < s.length() - 1) {
				ext = s.substring(i + 1).toLowerCase();
			}
			return ext;
		}

		public static int toInt(String s) {
			int j = 0;
			for (int i = 0; i < s.length(); i++)
				j = j * 10 + s.charAt(i) - '0';
			return j;
		}

		/**
	   * Takes a file and looks for the text between the tags <code>&lt;title&gt;</code>
	   * and <code>&lt;/title&gt;</code>. 
	   * 
	   * WARNING: the result string is taken rawly and
	   * might be wrongly encoded if the title is not in ASCII.
		 * @param file
		 *            the HTML file
		 * @return the title of the page; <code>null</code> if the pattern is not found in the 
	   *         first 200 bytes of the file
		 */
		public static String getHtmlPageTitle(File file) {
			Pattern p = Pattern.compile("<title>(.*)</title>");
			FileInputStream input;
			byte[] bytes = new byte[200];
			try {
				input = new FileInputStream(file);
				input.read(bytes, 0, 200);
				input.close();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
	      return null;
			} catch (IOException e) {
				e.printStackTrace();
	      return null;
			}
			String charBuffer = new String(bytes);
			Matcher matcher = p.matcher(charBuffer);
			if (matcher.find()) {
				return charBuffer.subSequence(matcher.start(1), matcher.end(1))
						.toString();
			}
			return null;
		}

	}
