Package fi.celia.asciimath

Source Code of fi.celia.asciimath.JAsciiMath

package fi.celia.asciimath;

import java.io.File;

import java.io.BufferedReader;
import java.util.Collections;
import java.util.Comparator;

import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Collection;
import java.util.regex.*;
import java.util.Properties;
import java.util.Set;
import java.util.HashMap;

import java.io.FileReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Serializable;

import fi.celia.asciimath.xml.AsciiMathXml;

/**
* This class is for to modify asciimath sentences after 3 rules. These 3 rules says,
* how an asciimath sentence contains words, aka reserved words or or special
* characters must be replaced into another word or character, or add or remove space,
* how to show numbers etc. These rules values are readed from a config file (.properties).
* <p>
* Above changes are done by with regular expressions, and by calling method:
* string.replaceAll(...,...). Before changing searched expressions, the class is replacing
* "not-replace words" (cnstNOTThiswords) with special (cnstDontModify) word before
* an until actual replace process is starting. An example: search word: int, with also has a
* do-not-change value: int_, then a word "int_" will be replaced
* "x__JAsciiMath_DontModifyconst__x" (cnstDontModify) untill int words has been changed.
* And then actual replace int value will be done, at last x__JAsciiMath_DontModifyconst__x
* strings are replaced back into int_ etc. By using this kind of special mark strings,
* all ready replaced or changed words are marked: "do-not-change-this-any-more" or
* "do-not-change-this-on-this-time". After all changes these kind of special marked
* strings are removed from modified text. Only actual modified characters and strings will
* be remained and a text will returned.
* <p>
* (c) Copyright 2010 Celia, wwww.celia.fi
* published as open source, license xxx
* <p>
* @author tkassila, Tuomas Kassila
*
*/

/*
*  - Modifications: 25.6.10 SpaceAfterButNotBeforeToken-regular string bug fixed
*                           (now: strReplace = "%s "). And test application corrected also.
*  - Modifications: 18.9.10 Fixed none sorted replace-hash-key, which lead to a bug
*                           when replaced iff = omm and if = om. Added sorting into
*                           all arrays. Modified also rules after: "do not modify a
*                           searched word if it contains " strikes at the start and
*                           end of the word.
*  - Modifications: 20.9.10 Fixed used wrong variable bug.
*/
public class JAsciiMath
{
  private AsciiMathBlockValue [] m_arrblok = null;
 
  /**
   * This class is used when sorting hasmap keys and array after searched
   * values. There is best to search/replace or modify at first most length
   * values and after at last a shortest value. Also notice, that a searched
   * value may contains (not: xxx) which are not calculated into the length
   * of an value. See below:
   * 
   * @author tuomas kassila
   *
   */
  private static class StringLengthComparator implements Comparator<String>,
            Serializable {
      public int compare(String o1, String o2)
      {
      String strO1 = getCompareStringWhichContainsCnstNOTThiswords(o1);
      String strO2 = getCompareStringWhichContainsCnstNOTThiswords(o2);
        if (strO1.length() < strO2.length()) {
          return 1;
        } else if (strO1.length() > strO2.length()) {
          return 0;
        } else {
          return -1;
        }
      }
     
      /**
       * Also notice, that a searched
       * value may contains (not: xxx) which are not calculated into the length
       * of an value. See below:
       * @param value
       * @return
       */
      private String
      getCompareStringWhichContainsCnstNOTThiswords(String value)
      {
        int ind = value.indexOf(cnstNOTThiswords);
        if (ind > -1)
          return value.substring(0, ind).trim();
        return value;
      }
  }

  private static String   m_static_strInputFileName = null;
  private static String   m_static_strOutputFileName = null;
  private boolean  bConvertHtmlChars = true;
  private boolean m_bWarningsOn = false;
  private boolean m_bPrintAsciMaths = false;
  private StringBuffer m_sbPrintData = null;
  private boolean m_bCorrectStrikeErrors = false;
  private HashMap<String, List<AsciiMathBlockValue>> m_hm_asciimath_values = null;
 
  // tka added 16.6.2011: from local variable
  // private boolean bRegexTokenWithPossibleLiteral = true;
  private boolean m_bAddBrowserStrikes = false;
  /**
   * When replacing a word with another, with this constant, you
   * say, replace longer words temporally with x__JAsciiMath_DontModifyconst__x
   * string. And after actual changing word has been replaced, change back
   * x__JAsciiMath_DontModifyconst__x into earlier value back again. An example:
   * int (not: int_) means: 1. replace all int_ into x__JAsciiMath_DontModifyconst__x,
   * 2. then replace all int words into another reserved, like in english word,
   * let's say: decimalnumber, 3. replace x__JAsciiMath_DontModifyconst__x into
   * back int_ again, etc. Where x means a sequence number starting from 1 to up.
   */
  private static final String cnstNOTThiswords = "(not: ";
 
  /**
   * Which xml-block is starting an asciimath sentence. This value is
   * only a part from original search value: <span class="Asciimath" >
   */
  public static final String   cnstAsciiMathBlockStart = "<span";
  /**
   * Which xml-block is stopping an asciimath sentence
   */
  public static final String   cnstAsciiMathBlockEnds = "</span>";
  /**
   * This class do not modify word this kind of const.
   */
  private static final String   cnstDontModify = "x__JAsciiMath_DontModifyconst__x";
  /**
   * With this string is starting a block: do not modify words under this work.
   */
  public static final String  cnstDontModifyBegin =
              "x_JAsciiMath_DontModifyconst__begin";
  /**
   * The same kind of literal as upper variable.
   */
  public static final String   cnstDontModifyEnd =
              "end_JAsciiMath_DontModifyconst__x";

  private static final String cnstPropertyFileDoesNotFound =
    "Property file %s does not found!";
  /**
   * configuration property value:
   */
  private static final String cnstSpace_on_both_sides_name = "space_on_both_sides_section_name";
  /**
   * configuration property variable:
   */
  private String m_space_on_both_sides_name;
  /**
   * configuration property value:
   */
  private static final String cnstSpace_on_neigther_sides_name = "space_on_neigther_sides_section_name";
  /**
   * configuration property variable:
   */
  private String m_space_on_neigther_sides_name;
  /**
   * configuration property value:
   */
  private static final String cnstSpace_before_but_not_after_name = "space_before_but_not_after_section_name";
  /**
   * configuration property variable:
   */
  private String m_space_before_but_not_after_name;   
  /**
   * configuration property value:
   */
  private static final String cnstSpace_after_but_not_before_name = "space_after_but_not_before_section_name";
  /**
   * configuration property variable:
   */
  private String m_space_after_but_not_before_name;
 
  /**
   * configuration property value:
   */
  private static final String cnstReplace_reserved_words_section_name = "replace_reserved_words_section_name";
  /**
   * configuration property variable:
   */
  private String m_replace_reserved_words_section_name;
 
  /**
   * configuration property value:
   */
  private static final String cnstRegex_special_meaning_characters = "regex_special_meaning_characters";
  private String m_regex_special_meaning_characters;
 
  private String   m_strInputFileName = null
  private String   m_strOutputFileName = null;
  //private File   m_FileInput = null;
  //private File   m_FileOutput = null;
  private String   m_strInputData = null;
  private int     m_iInputDataLen = 0;
  //private String   m_strOutputData = null;
  /**
   * a data output variable
   */
  private StringBuffer m_sb = null;
  /**
   * an error "string" variable
   */
  private StringBuffer m_sbError = null;
  /*
   * contains read/foundef asciimath block as object array
   */
  private AsciiMathBlockValue [] m_arrErrorAsciiMathBlockValue = null;
  /*
   * an application property file name:
   */
  public final String  cnstReplacePropertiesFileName = "dtbookasciimath.properties";
  private String  m_strReplacePropertiesFileName = cnstReplacePropertiesFileName;
  private File   m_FileReplaceProperty = null;
  /**
   * Config property variable for this class
   */
  private Properties m_propertyReplace = null;
  /**
   * Properties for replacing reserved words
   */
  private Properties m_propertyReplaceReservedWords = null;
  private List<String> m_sortedReplaceReservedWords = null;

  //private List<String> m_listCurrentToken = null;
 
  private RuleConfig m_srcBothSidesSpaceToken = null;
  private RuleConfig m_srcSpaceBeforeButNotAfter = null;
  private RuleConfig m_srcNoSpaciesIntoBohSideToken = null;
  private RuleConfig m_srcSpaceAfterButNotBeforeToken = null;
  private RuleConfig m_listReplace_reserved_wordToken = null;
  private RuleConfig m_listCurrentToken = null;
 
  /**
   * boolean variables for each rules:
   */
  private boolean bConvertAsciiMathDataSpaceRule = false;
  private boolean bConvertAsciiMathDataCommaRule = false;
  private boolean bConvertAsciiMathDataNumberRule = false;
  private boolean bConvertAsciiMathDataReplaceAllReservedWords = false;
  private boolean bCheckStrikeErrors = true;
  /**
   * const and string variables for the comma rule:
   */
  private static final String cnstReplaceAllComma = "replaceAllComma";
  private String m_replaceAllComma = ",";
 
  private static final String cnstReplaceAllWithSemiColon = "replaceAllWithSemiColon";
  private String m_replaceAllWithSemiColon = ";";
 
  private static final String cnstReplaceAllNumberPoint = "replaceAllNumberPoint";
  private static String m_replaceAllNumberPoint = ".";
 
  private static final String cnstReplaceAllNumberComma = "replaceAllNumberComma";
  private static String m_replaceAllNumberComma = ",";

  private HashMap<String, String> hmDontModifyData = null;
 
  public boolean getConvertHtmlChars() { return bConvertHtmlChars; }
  public void setConvertHtmlChars(boolean value) { bConvertHtmlChars = value; }
  public StringBuffer getPrintData() { return m_sbPrintData; }
  final HashMap<String, List<AsciiMathBlockValue>> getAsciimatHashMapValues ()
  {  return m_hm_asciimath_values; }
 
  /**
   * This class stores rule configuration for one rule
   *
   * @author tkassila
   *
   */
  private static class RuleConfig
  {
    private List<String> m_list;
    private String [] m_array;
   
    public RuleConfig()
    {
      m_list = new ArrayList<String>();
    }
   
    public final List<String> getList() { return m_list; }
   
    public String[] getArray()
    {
      if (m_array == null)
        createArray();
      return m_array;
    }
   
    public void addToken(String line)
    {
      m_list.add(line);
    }
   
    public void createArray()
    {
      int max = m_list.size();
      m_array = new String[max];
      String value;
     
      for(int i = 0; i < max; i++)
      {
        value = m_list.get(i);
        if (value == null)
          continue;
        m_array[i] = value;
      }
    }   
   
    public int size()
    {
      if (m_list == null)
        return 0;
      return m_list.size();
    }
  } // end of private class
 
  /**
   * This method is returning "will this rule executed under conversion"
   *
   * @return See above
   */
  public boolean getConvertAsciiMathDatSpaceRule()
  { return bConvertAsciiMathDataSpaceRule; }

  /**
   * This method sets "will this rule executed under conversion"
   */
  public void setConvertAsciiMathDataWithSpaceRules(boolean value)
  {
    bConvertAsciiMathDataSpaceRule = value;
  }

  /**
   * This method is returning "will this rule executed under conversion"
   *
   * @return See above
   */
  public boolean getConvertAsciiMathDataCommaRule()
  { return bConvertAsciiMathDataCommaRule; }

  /**
   * This method sets "will this rule executed under conversion"
   */
  public void setConvertAsciiMathDataCommaRule(boolean value)
  {
    bConvertAsciiMathDataCommaRule = value;
  }
   
  /**
   * This method is returning "will this rule executed under conversion"
   *
   * @return See above
   */
  public boolean getConvertAsciiMathDataNumberRule()
  { return bConvertAsciiMathDataNumberRule; }

  /**
   * This method sets "will this rule executed under conversion"
   */
  public void setConvertAsciiMathDataThousndNumberRule(boolean value)
  {
    bConvertAsciiMathDataNumberRule = value;
  }
 
  /**
   * This method is returning "will this rule executed under conversion"
   *
   * @return See above
   */
  public boolean getConvertAsciiMathDataReplaceAllReservedWords()
  { return bConvertAsciiMathDataReplaceAllReservedWords; }

  /**
   * This method sets "will this rule executed under conversion"
   */
  public void setConvertAsciiMathDataReplaceAllReservedWords(boolean value)
  {
    bConvertAsciiMathDataReplaceAllReservedWords = value;
  }

  /**
   *
   * These values will be used when adding space on both sides
   * of an string
   */
  private String [] m_arrBothSidesSpaceToken;
  /*
    = { ">", "<", "<=", ">=", "sin", "cos", "tan",
      "cot", "sec", "int (not: int_)", "ln",
      "test_substring", "test_substr"
    };
  */

  /**
   *
   * These values will be used when adding space on before of an string
   */
  private String [] m_arrSpaceBeforeButNotAfter;
  /*
    = { "-", "+", "=", "!=", "~~", "*"     
    };
  */
 
  /**
   * Näiden edessä ja takana ei välilyöntejä
   * These values will be used when removing spacies from both sides
   * of an string

   */
  private String [] m_arrNoSpaciesIntoBothSideToken;
  /*
    = { "#"     
    };
  */
 
  /**
   * Näiden takana ei välilyöntejä
   * These values will be used when adding space after but
   * not before of an searched string
   */
  private String [] m_arrSpaceAfterButNotBefore
    = { "("     
    };


  /**
   * regex special characters which must make into literal
   * charachters by adding \ character before character.
   */
  private String [] arrRegexToken
    = { "?", ".", "[", "]", "(", ")", "*", "+", "{", "}", "|", "^" };
 
  /**
   * The constructor of the class.
   * @param p_strReplacePropertiesFileName An absolute path value of the configuration file
   * @throws DtbookAsciiMathException
   * @throws FileNotFoundException
   * @throws IOException
   */
 
  public JAsciiMath(String p_strReplacePropertiesFileName,
      boolean p_bCheckStrikeErrors, boolean p_bCorrectStrikeErrors,
      boolean bAddBrowserStrikes)
  throws DtbookAsciiMathException, FileNotFoundException, IOException
  {
    m_strReplacePropertiesFileName = p_strReplacePropertiesFileName;
    m_bCorrectStrikeErrors = p_bCorrectStrikeErrors;
    bCheckStrikeErrors = p_bCheckStrikeErrors;
    if (m_FileReplaceProperty == null)
      m_FileReplaceProperty = new File(m_strReplacePropertiesFileName);
    m_bAddBrowserStrikes = bAddBrowserStrikes;
    readSectionNamesAndSectionData();   
  }

  public boolean isPrintAsciimathValues() { return m_bPrintAsciMaths; }
  public void setPrintAsciimathValues(boolean value)
  {
    m_bPrintAsciMaths = value;
  }
  public String   getInputFileName()
  {
    return m_strInputFileName;
  }

  public void setInputFileName(String p_strInputFileName)
  {
    m_strInputFileName = p_strInputFileName;
  }

  public String   getOutputFileName()
  {
    return m_strOutputFileName;
  }

  public void setOutputFileName(String p_strOutputFileName)
  {
    m_strOutputFileName = p_strOutputFileName;
  }

  public String getInputData()
  {
    return m_strInputData;
  }

  public void setInputData(String p_strInputData)
  {
    m_strInputData = p_strInputData;
    setInputDataLen();
  }
 
  private void setInputDataLen()
  {
    if (m_strInputData == null)
      m_iInputDataLen = 0;
    else
      m_iInputDataLen = m_strInputData.length();
 

  public String getOutputData()
  {
    if (m_sb == null)
      return null;
    return m_sb.toString();
  }

  public String toStringError()
  {
    if (m_sbError == null)
      return null;
    return m_sbError.toString();
  }

  public AsciiMathBlockValue [] getErrorAsciiMathBlockValueArray()
  {
    if (m_arrErrorAsciiMathBlockValue == null)
      return null;
    return m_arrErrorAsciiMathBlockValue;
  }


  /*
  private void setOutputData(String p_strOutputData)
  {
    m_strOutputData = p_strOutputData;
  }
  */

  /**
   * The method which is starting convertion process after boolean rule attribute
   * and input data has been set
   */
  public int
  replaceAsciiMathBlocks()
  throws NullPointerException, Exception
  {
    if (m_strInputData == null)
      throw new Exception("m_strInputData is null!");
    if (m_strInputData.trim().length() == 0)
      throw new Exception("m_strInputData is empty!");

    //System.err.println("1 m_strInputData.length()=" +m_strInputData.length());
   
    // is there an asciimath xml block:
    int ind = m_strInputData.indexOf(cnstAsciiMathBlockStart);
    if (ind == -1) // does not have ascii-xml start block
    {
      ind = m_strInputData.indexOf(cnstAsciiMathBlockStart.toUpperCase());
      if (ind == -1) // does not have ascii-xml start block
      {
        m_sb = new StringBuffer(m_strInputData);
        return 0;
      }
    }
   
    //System.err.println("2 m_strInputData.length()=" +m_strInputData.length());

    // collect asciimath blocks
    CollectAsciiMathBlocks pamb = new CollectAsciiMathBlocks(this,
        bCheckStrikeErrors, m_bCorrectStrikeErrors);   
    //pamb.setInputData(m_strInputData);
    AsciiMathBlockValue [] arrblok = pamb.getAllAsciiMathBlocks(m_bAddBrowserStrikes);
    if (arrblok == null || arrblok.length == 0)
    { // no ascimmath blocks has been founded, return unmodified data
      m_sb = new StringBuffer(m_strInputData);
      return -1;
    }
   
    m_arrblok = arrblok;

    //System.err.println("3 m_strInputData.length()=" +m_strInputData.length());

    int max = arrblok.length;
    String strAsciiMathValue, strEndAsciiMathBlock;
    String modifiedMathValue, strStart;
    final int cnstError = 1;
    int ret = cnstError, indNextMathBlockStart;
    int start = 0, end = -1, indInput = 0, indAsciiMathBlockEnds;
    AsciiMathBlockValue prevAsciiMathBlockValue = null, currAMValue = null;
   
    // new output buffer
    m_sb = new StringBuffer ();
    // new error buffer
    m_sbError = new StringBuffer ();
    List<AsciiMathBlockValue> listErrorValues = new ArrayList<AsciiMathBlockValue>();
   
    // m_sbError = null; AsciiMathBlockValue [] m_arrErrorAsciiMathBlockValue = null;

    int i = 0, iPrevAsciiMathBlockValue_BlockEnds, iIndEndofStartBlock;
    String msgError;

    // read config file data
    fullFillArraysWithConfigList();

    HashMap<String, List<AsciiMathBlockValue>> hm_value = new HashMap<String, List<AsciiMathBlockValue>>();
    List<AsciiMathBlockValue> list = null;

    String key = null;

    // loop readed asciimath instancies and do checkings,
    // are there some error or warnings, convert asciimath
    // values
    for(i = 0; i < max; i++)
    {
      currAMValue = arrblok[i];
      if (currAMValue == null)
        continue;
      strAsciiMathValue = currAMValue.getAsciiMathValue();
      if (strAsciiMathValue == null)
        continue;     
     
      key = "" + currAMValue.getRow();
      if (key.trim().length() > 0)
      {
        list = (List<AsciiMathBlockValue>) hm_value.get(key);
        if (list == null)
        {
          list = new ArrayList<AsciiMathBlockValue>();
          hm_value.put(key, list);
        }
        list.add(currAMValue);
      }
     
      if (m_bWarningsOn && strAsciiMathValue.trim().length() == 0)
      {
        listErrorValues.add(currAMValue);
        msgError = "Warning:\nEmpty asciimath: " +strAsciiMathValue +"\n"
        + "row    = " +currAMValue.getRow() +"\n"
        + "column = " +currAMValue.getColumn() +"\n"
        +"--------------------------------------\n\n";
        m_sbError.append(msgError);
        currAMValue.setErrorString(msgError);
      }
     
      modifiedMathValue = getConvertAsciiMatchValue(strAsciiMathValue);
      //if (modifiedMathValue != null)
        //modifiedMathValue = modifiedMathValue.replaceAll("\"", "");
      currAMValue.setModifiedValue(modifiedMathValue);
     
      if (strAsciiMathValue.trim().length() != 0
        && modifiedMathValue.trim().length() == 0)
      {
        listErrorValues.add(currAMValue);
        msgError = "Error:\nEmpty asciimath after convet!!!! Before convert: "
          +strAsciiMathValue +"\n"
        + "row    = " +currAMValue.getRow() +"\n"
        + "column = " +currAMValue.getColumn() +"\n"
        +"--------------------------------------\n\n";
        m_sbError.append(msgError);
        currAMValue.setErrorString(msgError);
      }
      else
      if (m_bWarningsOn && modifiedMathValue.equals(strAsciiMathValue))
      {
        listErrorValues.add(currAMValue);
        msgError = "Warning:\nUnchanged asciimath value after convet!!!!\nBefore convert:\n"
            +strAsciiMathValue +"\n"
        + "row    = " +currAMValue.getRow() +"\n"
        + "column = " +currAMValue.getColumn() +"\n"
        +"--------------------------------------\n\n";
        m_sbError.append(msgError);
        currAMValue.setErrorString(msgError);
      }

      start = currAMValue.getIndEndofStartBlock();
      end   = currAMValue.getIndFoundEnd();     

      if (end <= start)
      {
        listErrorValues.add(currAMValue);
        msgError = "Error:\nEnd is smaller than or equal Start!!!!\n"
            +strAsciiMathValue +"\n"
        + "row    = " +currAMValue.getRow() +"\n"
        + "column = " +currAMValue.getColumn() +"\n"
        + "start = " + start +"\n"
        + "end = " + end +"\n========= data ===========\n"
        + m_strInputData.substring(end, start)
        +"\n========= data ===========\n"
        +"\n--------------------------------------\n\n";
        m_sbError.append(msgError);
        currAMValue.setErrorString(msgError);
      }
     
      iPrevAsciiMathBlockValue_BlockEnds = currAMValue.getPrevAsciiMathBlockValue_BlockEnds();   
      iIndEndofStartBlock = currAMValue.getIndEndofStartBlock();
      /*
      System.out.println("1 m_strInputData.len=" +m_strInputData.length());
      System.out.println("iPrevAsciiMathBlockValue_BlockEnds=" +iPrevAsciiMathBlockValue_BlockEnds);
      System.out.println("iIndEndofStartBlock=" +iIndEndofStartBlock);
      System.out.println();
      */
     
      if (prevAsciiMathBlockValue == null)
        iPrevAsciiMathBlockValue_BlockEnds = 0;
      /*
      else
        iPrevAsciiMathBlockValue_BlockEnds = prevAsciiMathBlockValue.getIndFoundEnd();
        */
      iIndEndofStartBlock = start;
     
      /*
      System.err.println("m_strInputData.len=" +m_strInputData.length());
      System.err.println("iPrevAsciiMathBlockValue_BlockEnds=" +iPrevAsciiMathBlockValue_BlockEnds);
      System.err.println("iIndEndofStartBlock=" +iIndEndofStartBlock);
      System.err.println();
      */
     
      if (iIndEndofStartBlock <= iPrevAsciiMathBlockValue_BlockEnds)
      {
        listErrorValues.add(currAMValue);
        int indSubStart = prevAsciiMathBlockValue.getIndFound();
        int indSubEnd ;
        indSubEnd = currAMValue.getNextAsciiMathBlockValue_EndofStartBlock();
        if (indSubEnd == -1)
          indSubEnd = currAMValue.getIndFoundEnd();
        msgError = "Error:\nIndex value for starting asciimath xml-block is smaller than where a previous ascimatch index value ended!!!!\n"
            +strAsciiMathValue +"\nThis means usually that asmiimath blocks are not correct!!!\n"
        + "row    = " +currAMValue.getRow() +"\n"
        + "column = " +currAMValue.getColumn() +"\n"
        + "iIndEndofStartBlock                = " +iIndEndofStartBlock +"\n"
        + "iPrevAsciiMathBlockValue_BlockEnds = " +iPrevAsciiMathBlockValue_BlockEnds +"\n"
        +"\n========= data ===========\n"
        + m_strInputData.substring(indSubStart,  indSubEnd)
        +"\n========= data ===========\n"
        +"\n--------------------------------------\n\n";
        m_sbError.append(msgError);
        currAMValue.setErrorString(msgError);       
      }
     
      // all done, returning ok
      if (currAMValue == null)
        return 0; // ok
     
      // start substring before current asciimath block and after allready
      // handled text position end
      strStart = m_strInputData.substring(iPrevAsciiMathBlockValue_BlockEnds,       
                        iIndEndofStartBlock);
      m_sb.append(strStart);
      // when convert html chars has been set, then convert html chars
      if (bConvertHtmlChars)
        m_sb.append(getChangeNormalCharactersIntoLTAndGTHtmlCharacters(modifiedMathValue));
      else // do not convert html chars
        m_sb.append(modifiedMathValue);

      if (m_bPrintAsciMaths) // "print" current asciimath block values (gui uses)
        m_sbPrintData = pamb.printAllAsciiMathBloks(arrblok);
     
        /*
      indAsciiMathBlockEnds = currAMValue.getIndAsciiMathBlockEnds();
      indNextMathBlockStart = currAMValue.getNextAsciiMathBlockValue_EndofStartBlock();
      if (indNextMathBlockStart == -1)
        strEndAsciiMathBlock = m_strInputData.substring(indAsciiMathBlockEnds);
      else
        strEndAsciiMathBlock = m_strInputData.substring(indAsciiMathBlockEnds, indNextMathBlockStart);
      if (strEndAsciiMathBlock == null)
        System.err.println("!!");
      else
        m_sb.append(strEndAsciiMathBlock);
      */
      prevAsciiMathBlockValue = currAMValue;
      indInput = end;
    } // end of for
   
    m_hm_asciimath_values = hm_value;
   
    indAsciiMathBlockEnds = m_strInputData.length();
    indNextMathBlockStart = currAMValue.getIndFoundEnd();
    /*
    if (indNextMathBlockStart == -1)
      strEndAsciiMathBlock = m_strInputData.substring(indAsciiMathBlockEnds);
    else
    */
   
    // add possible last text into data buffer
    strEndAsciiMathBlock = m_strInputData.substring(indNextMathBlockStart);
    if (strEndAsciiMathBlock == null)
      System.err.println("!!");
    else
      m_sb.append(strEndAsciiMathBlock);

    // check and convert possible errors
    if (m_sbError != null && m_sbError.length() == 0 && listErrorValues.size() == 0)
    {
      m_sbError = null;
      m_arrErrorAsciiMathBlockValue = null;
    }
    else
    {
      Object arrObj [] = listErrorValues.toArray();
      int size = arrObj.length;
      m_arrErrorAsciiMathBlockValue = new AsciiMathBlockValue[size];
     
      for(int j = 0; j < size; j++)
      {
        m_arrErrorAsciiMathBlockValue[j] = (AsciiMathBlockValue)arrObj[j];
      }
    }

    // if there is no asciimath blocks, then return unmodified text
    if (m_sb.length() == 0)
    {
      m_sb = new StringBuffer(m_strInputData);
      return -1;
    }
   
    ret = 0; // ok   
   
    /*
    if (m_sb.length() != end)
    {
      strStart = m_strInputData.substring(end);
      m_sb.append(strStart);
    }
    */

   
    /*
    // if data is unmodified:
    m_sb = new StringBuffer(m_strInputData);
   
    // start convertion (ind is an index value on
    // next search postion, until -1 reached
    while((ind = seekAndConvertAsciiMathData(ind)) > -1)
        ;
    int ret = 0; // ok
    */
   
    return ret;
   
  }
 
  /*
  private int
  seekAndConvertAsciiMathData(int indFound)
  throws NullPointerException, Exception
  {
    final int cnstStop = -1;
   
    // a paraemter check:
    if (indFound < 0)
      return cnstStop;
    int len = m_sb.length()-1;
    if (indFound > len)
      return cnstStop;
   
    // searching possible asciimath block:
    int indAsciiMathBlockStart = m_sb.indexOf(
        cnstAsciiMathBlockStart, indFound);
    if (indAsciiMathBlockStart == -1)
    {
      // with different charachter size:
      indAsciiMathBlockStart = m_sb.indexOf(
          cnstAsciiMathBlockStart.toUpperCase(), indFound);
      if (indAsciiMathBlockStart == -1)
        return cnstStop;
    }     
     
    // seaching ending character > for start asciimath block:
    int indEndofStartBlock = m_sb.indexOf(">", indAsciiMathBlockStart);
    if (indEndofStartBlock == -1)
      return indAsciiMathBlockStart+1;

    if (len < (indEndofStartBlock+1) )
      return cnstStop;
 
    int indAsciiMathBlockEnds = m_sb.indexOf(
        cnstAsciiMathBlockEnds, indEndofStartBlock+1);
    if (indAsciiMathBlockEnds == -1)
    {
      // with different charachter size:
      indAsciiMathBlockEnds = m_sb.indexOf(
          cnstAsciiMathBlockEnds.toUpperCase(), indEndofStartBlock);
      if (indAsciiMathBlockEnds == -1)
        return cnstStop;
    }

    //String tmp_test = m_sb.substring(indEndofStartBlock+1);
 
    //tmp_test = m_sb.substring(indEndofStartBlock+1, indAsciiMathBlockEnds);
    // is there is an another started asciimath block allready...
    int iAnotherSpanHasStarted = anotherSpanHasStarted(indAsciiMathBlockStart,
                              indAsciiMathBlockEnds);
    if (iAnotherSpanHasStarted > -1)
    {
      // TODO: virheenkäsittely koodi, kerää tiedot, mutta jatkaa silti?!!
      return iAnotherSpanHasStarted;
    }
   
    // is not an ascimath block:
    if (isNotAsciiMathBlock(indAsciiMathBlockStart, indEndofStartBlock))
      return indAsciiMathBlockEnds;

    // a founded asciimath block:
    int indMatchDataStart = indEndofStartBlock +1;
    int indMatchDataEnd = indAsciiMathBlockEnds;
   
    String strAsciiMath = m_sb.substring(
                indMatchDataStart, indMatchDataEnd);
    if (strAsciiMath == null)
      return cnstStop;
   
    String strNewAsciiMath = getConvertAsciiMatchValue(strAsciiMath);
    ?*
    String strNewAsciiMath = getChangeLTAndGTHtmlCharactersIntoNormalCharacters(strAsciiMath);
   
    //String strNewAsciiMath = strAsciiMath; //
   
    // read lists and array from configuration file:
    fullFillArraysWithConfigList();   

    // rule handling:
   
    if (bConvertAsciiMathDataReplaceAllReservedWords)
    {
      strNewAsciiMath = replaceAllReservedWords(strNewAsciiMath);
    }   

    if (bConvertAsciiMathDataCommaRule)
    {
      strNewAsciiMath = convertAsciiMathDataCommaRule(strNewAsciiMath);
    }

    if (bConvertAsciiMathDataNumberRule)
    {
      strNewAsciiMath = convertAsciiMathDataNumberRule(strNewAsciiMath);
    }

    if (bConvertAsciiMathDataSpaceRule)
    {
      //String markedDoNotModifySomeWords = getDontModifyData(strNewAsciiMath);
      strNewAsciiMath = convertAsciiMathDataWithSpaceRule(strNewAsciiMath);
    }
    *?
   
    if (strNewAsciiMath == null)
        return cnstStop;

    // construct a new modified start string and end string between
    // modified ascimath block:
   
    String strStart = m_sb.substring(0, indMatchDataStart);
    int lenNewAsciiMath = strNewAsciiMath.length();
    // m_sb.replace(start, end, str)
    //m_sb.replace((indMatchDataStart), (indMatchDataStart+strStart.length()),
      //     strNewAsciiMath);
    String strEnd = m_sb.substring(indMatchDataEnd);
    //StringBuffer tmp_m_sb =
    m_sb = new StringBuffer(strStart + strNewAsciiMath + strEnd);
    //System.out.println("tmp_m_sb='" +tmp_m_sb.toString() +"'");
    //System.out.println("m_sb='" +m_sb.toString() +"'");
    setInputDataLen();
   
    // calculate a new searching postion for an asciimath block:
    return getNewIndMatchDataEnd(indMatchDataStart,
                   strNewAsciiMath.length());
  }
  */


  /**
   * This method returns a modified String after replaced all reserved words
   * in the paraemeter value. Replaced words and new values for them are located in
   * the .properties file of this class.
   * @param strAsciiMath
   * @return See above
   */
  private String
  replaceAllReservedWords(String strAsciiMath)
  throws DtbookAsciiMathException
  {
    if (strAsciiMath == null || strAsciiMath.trim().length() == 0)
      return strAsciiMath;

    int max = m_sortedReplaceReservedWords.size();
    if (max == 0
      return strAsciiMath;
   
    /*
    while (stepper.hasNext()) {
        current = (String)stepper.next();
        System.out.println(current);
    }
    //listvalues
     *      
     */

   
    String strSearch, strValue;
    // use sorted list, because longest search value will be handled at first etc
    Iterator<String> ite = m_sortedReplaceReservedWords.iterator();
    int ind ;
   
    for(; ite.hasNext(); )
    {
      strSearch = (String)ite.next();
      if (strSearch == null || strSearch.trim().length() == 0)
        continue;
      // get replace value by search value
      strValue = (String)this.m_propertyReplaceReservedWords.get(strSearch);
      if (strValue == null)
        strValue = "";
      ind = strAsciiMath.indexOf(strSearch);
     
      if (ind > -1 /* strAsciiMath.contains(strSearch) */)
      {
        String start, end = "", replacedValue = strValue;
        int len = strSearch.length();
        StringBuffer sb =  new StringBuffer();
        int pos;
       
        while(ind != -1)
        {
          start = strAsciiMath.substring(0, ind);
          if (start == null)
            start = "";
          pos = (ind + len);
          end = strAsciiMath.substring(pos);
          if (end == null)
            end = "";
          sb.append(start + replacedValue);
          strAsciiMath = end;
          ind = strAsciiMath.indexOf(strSearch);
        }
        sb.append(end);
        strAsciiMath = sb.toString();
      }
    }
    return strAsciiMath;
  }

  /**
   * This method is converting an ascimath block value after rules
   * @param strAsciiMath an ascimath block value
   * @return Converted asciimath text
   * @throws DtbookAsciiMathException an error occurred
   * @throws NullPointerException an null pointer error occurred
   * @throws Exception common error occurred
   */
  public String getConvertAsciiMatchValue(String strAsciiMath)
  throws DtbookAsciiMathException, NullPointerException, Exception
  {
    String strNewAsciiMath = getChangeLTAndGTHtmlCharactersIntoNormalCharacters(strAsciiMath);
   
    //String strNewAsciiMath = strAsciiMath; //
   
    // read lists and array from configuration file:
    //fullFillArraysWithConfigList();   

    // rule handling:
   
    // converting is done after boolean flags
    int indDupleStrike = strNewAsciiMath.indexOf('"');
    String strStikeValue = strNewAsciiMath;
    String [] arrStrikeValues = null;
    int len = 0;
    if (indDupleStrike !=  -1)
    {
      arrStrikeValues = strNewAsciiMath.split("\"");
      len = arrStrikeValues.length;
      if (arrStrikeValues.length % 2 != 0 && (arrStrikeValues.length-1) % 2 != 0)
        //indDupleStrike = len -1; // ERROR: NONE PAIR STRIKE!!!
        throw new DtbookAsciiMathException("None Pair\" characters: " +strAsciiMath);
    }
    int i = 0;
    StringBuffer sb = new StringBuffer();
    boolean bNoneStrikes = true;
   
    // System.err.println("len=" +len);
   
    while((indDupleStrike == -1 && i == 0) || (indDupleStrike != -1 && i < len))
    {
      if (indDupleStrike > -1)
      {
        strStikeValue = arrStrikeValues[i];
      }
   
      if (bNoneStrikes)
      {
        if (bConvertAsciiMathDataReplaceAllReservedWords)
        {
          strStikeValue = replaceAllReservedWords(strStikeValue);
        }   
   
        if (bConvertAsciiMathDataCommaRule)
        {
          strStikeValue = convertAsciiMathDataCommaRule(strStikeValue);
        }
   
        if (bConvertAsciiMathDataNumberRule)
        {
          strStikeValue = convertAsciiMathDataNumberRule(strStikeValue);
        }
   
        if (bConvertAsciiMathDataSpaceRule)
        {
          //String markedDoNotModifySomeWords = getDontModifyData(strNewAsciiMath);
          strStikeValue = convertAsciiMathDataWithSpaceRule(strStikeValue);
        }
        sb.append(strStikeValue);
      }
      else
        sb.append("\"" + strStikeValue + "\"");
      i++;
      bNoneStrikes = ! bNoneStrikes;
      }
   
    return sb.toString();
  }
 
  /**
   * This method is converting some html characters into normal characters
   * @param value A value contains possible html characters
   * @return Converted normal text
   */
  public static String
  getChangeLTAndGTHtmlCharactersIntoNormalCharacters(String value)
  {
    if (value != null)
    {
      // replace these html coded < character into normal < characer
      value = value.replaceAll("&lt;", "<");
      value = value.replaceAll("&#60;", "<");
      value = value.replaceAll("&#x3c;", "<");
      // replace all html coded > character into normal > characer
      value = value.replaceAll("&gt;", ">");
      value = value.replaceAll("&#62;", ">");       
      value = value.replaceAll("&#x3e;", ">");
      // replace all html coded & character into normal & characer
      value = value.replaceAll("&amp;", "&");
      value = value.replaceAll("&#38;", "&");
      value = value.replaceAll("&#x26;", "&");
    }
    return value;
  }

  /**
   * This method is converting some normal characters into some html characters
   * @param value Normal text
   * @return Converted text, which may contain some html characcters
   */
  public static String
  getChangeNormalCharactersIntoLTAndGTHtmlCharacters(String value)
  {
    if (value != null)
    {
      // & replace must done before another replacing, because they contains also & character!!:     
      //value = value.replaceAll("&", "&amp;");
      value = value.replaceAll("&amp;", "&");
      // replace all earlier html coded < character back into html coded < characer
      value = value.replaceAll("<", "&lt;");
      // replace all earlier html coded > character back into html coded > characer
      value = value.replaceAll(">", "&gt;");       
    }
    return value;
  }

  /*
  private int
  getNewIndMatchDataEnd(int indMatchDataStart, int iNewAsciiMathLength)
  {   
    return indMatchDataStart + iNewAsciiMathLength
                   +cnstAsciiMathBlockEnds.length(); // ok, continue
  }
  */
 
  /*
  private int
  anotherSpanHasStarted(int indAsciiMathBlockStart, int indAsciiMathBlockEnds)
  {
    int ind2 = indAsciiMathBlockStart + cnstAsciiMathBlockStart.length();
    if (ind2 > (m_sb.length()-1) )
      return -1;
   
    int ind = m_sb.indexOf(cnstAsciiMathBlockStart, ind2);
    if (ind == -1)
    {
      // eri kirjainkoolla:
      ind = m_sb.indexOf(
          cnstAsciiMathBlockStart.toUpperCase(), ind2);
    }
    if (ind > -1 && ind < indAsciiMathBlockEnds)
      return ind;
   
    return -1;  // all is ok, has not started an another span block before ending the first one
  }
  */

  /*
  private boolean
  isNotAsciiMathBlock(int indAsciiMathBlockStart, int indEndofStartBlock)
  {
    // class="asciimath">
    int ind = m_sb.indexOf("class", indAsciiMathBlockStart);
    if (ind == -1 || ind >= indEndofStartBlock)
    {
      ind = m_sb.indexOf("CLASS", indAsciiMathBlockStart);
      if (ind == -1 || ind >= indEndofStartBlock)
        return true;
    }

    int ind2 = m_sb  .indexOf("=", ind);
    if (ind2 == -1 || ind2 >= indEndofStartBlock)
      return true;
   
    char chDelim = '"';
    int ind3 = m_sb.indexOf(""+chDelim, ind2);
    if (ind3 == -1 || ind3 >= indEndofStartBlock)
    {
      chDelim = '\'';
      ind3 = m_sb.indexOf(""+chDelim, ind2);
      if (ind3 == -1 || ind3 >= indEndofStartBlock)
        return true;
    }
    if ((ind3+1) >= indEndofStartBlock || (ind3+1) >  m_sb.length())
      return true;
   
    int ind4 = m_sb.indexOf(""+chDelim, ind3+1);
    if (ind4 == -1 || ind4 >= indEndofStartBlock)
      return true;
    String strAttrib = m_sb.substring(ind3+1, ind4);
    if (strAttrib == null)
      return true;
    if (!strAttrib.toLowerCase().equals("asciimath"))
        return true;
   
    return false; // span is an ASCIIMATH span
  }
  */

  /**
   * This method is converting asciimath block data after comma rule
   * for numbers. The rule is says that all point characters inside
   * numbers must converted into , characters. It is using regexp for that.
   * @param strMathData
   * @return
   * @throws NullPointerException
   * @throws Exception
   */
  private String
  convertAsciiMathDataCommaRule(String strMathData)
  throws PatternSyntaxException, IllegalArgumentException,
         NullPointerException, Exception
  {
    // replace all comma character into "new" comma characters
    String strModifiedMathData = strMathData.replace(m_replaceAllComma, m_replaceAllWithSemiColon);
    String strRegex = "(\\d{1,})\\" + m_replaceAllNumberPoint +"(\\d{1,})";
    String strReplace = "$1" + m_replaceAllNumberComma +"$2";
    strModifiedMathData = strModifiedMathData.replaceAll(strRegex, strReplace);
    return strModifiedMathData;
  }

  /**
   * This method is converting asciimath block data after that numbers must
   * have point characters every 3th charachter and have possible comma
   * character at last within a number before decimal fragment numbers.
   * It is using regexp and java code for that.
   *
   * @param strMathData
   * @return
   * @throws PatternSyntaxException
   * @throws IllegalArgumentException
   * @throws NullPointerException
   * @throws Exception
   */
  private String
  convertAsciiMathDataNumberRule(String strMathData)
  throws PatternSyntaxException, IllegalArgumentException,
      NullPointerException, Exception
  {
    // search number in the form: 999,222:
    try {
      //1.version: Pattern regex = Pattern.compile("(\\d{1,}),(\\d{1,})");
      //2.version: Pattern regex = Pattern.compile("(\\d{1,})((\\,(\\d{1,})){0,1})");
     
      // search all numbers wich may have , or . characters inside a number
      Pattern regex = Pattern.compile("((\\d{1,})([\\,\\.]{0,1})){1,}");
      Matcher regexMatcher = regex.matcher(strMathData);
      //MatchResult matchResult;
      try {
        int iStart, iEnd, istartPartOfNumberLen;
        String number;
        String endPartOfNumber, startPartOfNumber, modiedData;
        StringBuffer sb = new StringBuffer();
        boolean founded = false;
       
        // find numbers and add . or , characters between 3th number characters
        // The , character is set only at last inside of a number
        while(regexMatcher.find())
        {
          founded = true;
          //matchResult = regexMatcher.toMatchResult();
          iStart = regexMatcher.start();
          iEnd = regexMatcher.end();
          number = strMathData.substring(iStart, iEnd);
          if (number == null)
            continue;
         
          // is there , charchter
          int indComma = number.indexOf(',');
          endPartOfNumber = null;
          startPartOfNumber = null;
         
          startPartOfNumber = number;
          if (indComma != -1)
          {
            endPartOfNumber = number.substring(indComma);
            startPartOfNumber = number.substring(0, indComma);
          }
          if (startPartOfNumber == null)
            continue;
          istartPartOfNumberLen = startPartOfNumber.length();
          modiedData = startPartOfNumber;
          if (istartPartOfNumberLen > 0) // if there exists number characters before , or .
            modiedData = getNumberAddedWithPointChar(startPartOfNumber);
          if (endPartOfNumber != null)
            modiedData = modiedData + endPartOfNumber;
          // replace current value with modied data
          regexMatcher.appendReplacement(sb, modiedData);
        } // end of while
       
        String modifiedValue = strMathData;
        if (founded) // at last one number has been founded
        { // append tail text into regex variable and return
          // modified value
          regexMatcher.appendTail(sb);
          modifiedValue = sb.toString();
        }
               
        // 2. searh: mixed search strings; partly right, partly wrong words:
        /* not working:
        founded = false;
        regex = Pattern.compile("((\\d{1,}\\.\\d{0,}\\,\\d{1,}))");
        regexMatcher = regex.matcher(modifiedValue);
        sb = new StringBuffer();
         
        while(regexMatcher.find())
        {
          founded = true;
          matchResult = regexMatcher.toMatchResult();
          iStart = regexMatcher.start();
          iEnd = regexMatcher.end();
          number = strMathData.substring(iStart, iEnd);
          if (number == null)
            continue;
          int indComma = number.indexOf(',');
          endPartOfNumber = null;
          startPartOfNumber = null;
           
          startPartOfNumber = number;
          if (indComma != -1)
          {
            endPartOfNumber = number.substring(indComma);
            startPartOfNumber = number.substring(0, indComma);
          }
          if (startPartOfNumber == null)
            continue;
          istartPartOfNumberLen = startPartOfNumber.length();
          modiedData = startPartOfNumber;
          if (istartPartOfNumberLen > 0)
            modiedData = getNumberAddedWithPointChar(startPartOfNumber);
          if (endPartOfNumber != null)
            modiedData = modiedData + endPartOfNumber;
          regexMatcher.appendReplacement(sb, modiedData);
        }
        if (founded)
        {
          regexMatcher.appendTail(sb);
          modifiedValue = sb.toString();
        }
        */
        return modifiedValue;
      } catch (IllegalArgumentException ex) {
        // Syntax error in the replacement text (unescaped $ signs?)
        throw ex;
      } catch (IndexOutOfBoundsException ex2) {
        // Non-existent backreference used the replacement text
        throw ex2;
      }
    } catch (PatternSyntaxException ex3) {
      // Syntax error in the regular expression
      throw ex3;
    }
  }

  /**
   * This method returns a number string added . character every 3th number
   * character if needed. A parameter number must <b>not</b> have decimal
   * numbers after an , character!
   * @param value
   * @return
   */
  private String
  getNumberAddedWithPointChar(String value)
  {
    if (value != null)
    {
      int len = value.length();
      if (len < 4)
        return value;
     
      String tmp = value.replaceAll("\\.", "");
      len = tmp.length();
      StringBuffer sp = new StringBuffer();
      int iStartNumberChars = (len % 3);
      //int iRemain = (len > (3*iStartNumberChars)) ? (len - (3*iStartNumberChars)) : ((3*iStartNumberChars) - len);
      int iCounter = (len / 3);
      int iStartPart = (iStartNumberChars > 0) ? iStartNumberChars : 0;
     
      String substr = null;
      if (iStartNumberChars > 0)
      {
        substr = tmp.substring(0, iStartNumberChars);
        if (substr != null)
        {
          sp.append(substr);
        }
      }       
      int pos = iStartPart;
      boolean bFirsTime = true;
       
      for(int i = 0; i < iCounter ; i++)
      {
        if (bFirsTime)
        {
          if (iStartPart > 0)
            sp.append("." + tmp.substring(pos, (pos+3)));
          else
            sp.append(tmp.substring(pos, (pos+3)));         
        }
        else
          sp.append("." + tmp.substring(pos, (pos+3)));
        pos = pos +3;
        bFirsTime = false;
      }
      return sp.toString();
    }
   
    return value;
  }
 
  /**
   * This method is converting asciimath block data after what
   * space character rules says. These space rules added, removed
   * space character before or/and after specific words or text.
   * It is using regexp and java code for that.
   *
   * @param strMathData
   * @return
   * @throws NullPointerException
   * @throws Exception
   */
  private String
  convertAsciiMathDataWithSpaceRule(String strMathData)
  throws NullPointerException, Exception
  {
    String strModifiedMathData = new String(strMathData);
    //fullFillArraysWithConfigList();   
    //strModifiedMathData = replaceAllReservedWords(strModifiedMathData);

    String [] arrUsedTokens;
   
    // sort used array after logest words,
    // without 'not:' values:
    arrUsedTokens = getArrBothSidesSpaceToken();
    String strRegex = "(\\s*)%s(\\s*)";
    String strReplace = " %s ";
    strModifiedMathData = getModifyData(strRegex, strReplace,
                      arrUsedTokens, strModifiedMathData);
       
    arrUsedTokens = getArrSpaceBeforeButNotAfter();
    strRegex = "(\\s*)%s(\\s*)";
    strReplace = " %s";
    strModifiedMathData = getModifyData(strRegex, strReplace,
                      arrUsedTokens, strModifiedMathData);   
       
    arrUsedTokens = getArrNoSpaciesIntoBothSideToken();
    strRegex = "(\\s*)%s(\\s*)";
    strReplace = "%s";
    strModifiedMathData = getModifyData(strRegex, strReplace,
                        arrUsedTokens, strModifiedMathData);   
   
    arrUsedTokens = getArrSpaceAfterButNotBeforeToken();
    //strRegex = "%s(\\s*)";
    strRegex = "(\\s*)%s(\\s*)";
    strReplace = "%s ";
    strModifiedMathData = getModifyData(strRegex, strReplace,
                      arrUsedTokens, strModifiedMathData);   

    // ota pois mahdolliset muutettujen kohtien merkkausliteraalit sen jälkeen,
    // kun kaikki muutokset on tehty
    int ind = strModifiedMathData.indexOf(cnstDontModifyBegin);
    if (ind > -1)
      strModifiedMathData = strModifiedMathData.replaceAll(
        cnstDontModifyBegin, "");
    ind = strModifiedMathData.indexOf(cnstDontModifyEnd);
    if (ind > -1)
      strModifiedMathData = strModifiedMathData.replaceAll(
        cnstDontModifyEnd, "");

    return strModifiedMathData;
  }
 
  /**
   * This method is fullfilling config value arrays from corresponding
   * list variable, which are readed from config file. All config values
   * are sorted after the longest value comes at first, etc.
   * 
   * @throws NullPointerException
   * @throws Exception
   */
  private void
  fullFillArraysWithConfigList()
  throws NullPointerException, Exception
  {
    int max = m_srcBothSidesSpaceToken.size();
    m_arrBothSidesSpaceToken = getOrderedArr(m_srcBothSidesSpaceToken.getArray(), -1);

    max = m_srcSpaceBeforeButNotAfter.size();
    m_arrSpaceBeforeButNotAfter = getOrderedArr(m_srcSpaceBeforeButNotAfter.getArray(), -1);

    max = m_srcSpaceAfterButNotBeforeToken.size();
    m_arrSpaceAfterButNotBefore = getOrderedArr(m_srcSpaceAfterButNotBeforeToken.getArray(), -1);

    max = m_srcNoSpaciesIntoBohSideToken.size();
    m_arrNoSpaciesIntoBothSideToken = getOrderedArr(m_srcNoSpaciesIntoBohSideToken.getArray(), -1);
       
    String rowArray [] = m_listReplace_reserved_wordToken.getArray();
   
    m_propertyReplaceReservedWords = new Properties();
   
    if (rowArray != null)
    {
      max = rowArray.length;
      String row, key, value, msgError;
      int ind;
      HashMap<String, String> listvalues = new HashMap<String, String> ();
      List <String> stuff = new ArrayList<String>();
     
      for(int i = 0; i < max; i++)
      {
        row = rowArray[i];
        if (row == null || row.trim().length() == 0)
          continue;
        ind = row.indexOf('=');
        if (ind == -1)
          continue;
        key   = row.substring(0, ind).trim();
        if (key.trim().length() == 0)
        {
          msgError = "Warning:\nEmpty property-key: row '" + row +"'\n"
          +"--------------------------------------\n\n";
          m_sbError.append(msgError);
          continue;
        }
        value = row.substring(ind+1).trim();
        listvalues.put(key, value);
        stuff.add(key);
      }
     
      m_propertyReplaceReservedWords.putAll(listvalues);       
      //System.out.println("---------- Sort by line length");      
      Collections.sort(stuff, new StringLengthComparator());      
      m_sortedReplaceReservedWords = stuff;     
    }
    
  }

  /**
   * This method is returning modified data after space rules.
   * @param strRegex conversion regex value, like: 
   * @param strReplace replace regex value, like:
   * @param arrTokens text values which must added/removed space before or after it
   * @param strModifiedMathData a data must be modified after a space rule
   * @return Modified data
   * @throws NullPointerException Error exception
   * @throws Exception Error exception
   */
  private String
  getModifyData(String strRegex,
          String strReplace,
          String [] arrTokens,
          String strModifiedMathData)
  throws NullPointerException, Exception
  {
    int max = arrTokens.length;
    String strToken;
    String strDontModifyToken;
    boolean bRegexTokenWithPossibleLiteral = true;

    // at first mark those search text, which will not changed during convertion,
    // but which too same kind of searched value. By example: change int, but not
    // int_ . See config file: int (not: int_)
   
    // Text values which must not changed are marked with "not-replace words"
    // (cnstNOTThiswords) with special (cnstDontModify) word before an actual
    // replace will start. An example, search word: int, with also has a
    // do-not-change value: int_, then a word "int_" will be replaced
    // "x__JAsciiMath_DontModifyconst__x" (cnstDontModify). And then actual
    // replace int value will be done. At last x__JAsciiMath_DontModifyconst__x
    // strings are replaced back into int_ etc.
   
    // By using this kind of special mark strings, all ready replaced
    // or changed words are marked: "do-not-change-this-any-more" or
    // "do-not-change-this-on-this-time". After all changes these kind of
    // special marked strings are removed from modified text. Only actual
    // modified characters and strings will be remained and a text will returned.
 
    // it is important that all array values are sorted after longest value
    // at first! So that allready modified value will be marked
    // "do-not-chnage-this-any-more-it-has-been-allready-changed" mark text.
   
    // at last all special mark text are removed
   
    for(int i = 0; i < max; i++)
    {
      // if this search value has dont modify this value
      // if no, then it returs null
      // TODO: if don't modify value has more than just one value, is that working!!
      strDontModifyToken = getDontModifyToken(arrTokens[i]);
      // get serached token, possible change what regexp says about special meta regex characters
      strToken = getNormalToken(arrTokens[i], bRegexTokenWithPossibleLiteral);
      if (strToken == null)
        continue;
      // jos älä muuta dataa, muuta varoiksi mahdollinen merkkijono
      // vakioksi, jota ei ole tekstissä, ja se sitten normaalin muutoksen
      // jälkeen takaisin vakio siksi merkkijonoksi, jota ei saa muuttaa!
      // Tämä merkkijono, jota halutaan muuttaa, on osamerkkijono siitä merkkijonosta, jota ei saa
      // muuttaa. Sellainen ilmoitetaan (not: xxx, xxx2) merkkijonolla. Esim: int saa välilyönnit,
      // paitsi ei int_ merkkjono.

      // if there is do-not-modify-this, replace word with strDontModifyToken
      // before actual change
      if (strDontModifyToken != null)
        strModifiedMathData = getDontModifyMarketedData(strDontModifyToken,
                                strModifiedMathData);
        /*
         * strModifiedMathData.replaceAll(
            strDontModifyToken, cnstDontModify);
         */
     
      // do actual modification with regexp and java code
      strModifiedMathData = getModifiedMathData(strModifiedMathData,
                    strToken, strRegex, // "(\\s*)" +strToken +"(\\s*)",
                    strReplace); // " " + strToken +" ");
      // if there has been used do-not-modify-this, unmodify mark word
      // back into earlier text value within strModifiedMathData
      if (strDontModifyToken != null)
        strModifiedMathData = getUnMarkDontModifyMarketedData(
            strDontModifyToken,
            strModifiedMathData           
            );
        /*    strModifiedMathData.replaceAll(
            cnstDontModify,
            cnstDontModifyBegin + strDontModifyToken
            +cnstDontModifyEnd);
        */
    }
 
    return strModifiedMathData;
  }
 
  /**
   * This method marks one do-not-modify-this-text before actual modification
   * (change text) (after workds it is converted back again.). It is supposing
   * that dont-modify parameter may contains words (splitted after space!)!!!
   * @param strDontModifyToken
   * @param strModifiedMathData Data string
   * @return
   */
  private String
  getDontModifyMarketedData(String strDontModifyToken,
                String strModifiedMathData)
  {
    // TODO: is this supposing right: splitted array after space!!! See method comment also!
    String dontModifyData [] = strDontModifyToken.split(" ");
    if (dontModifyData == null || dontModifyData.length == 0)
      return null;
    if (dontModifyData.length == 1)
      return strModifiedMathData.replaceAll( // tka: added getRegexTokenWithPossibleLiteral( 16.6.2011
        getRegexTokenWithPossibleLiteral(strDontModifyToken), cnstDontModify);
   
    String data;
    int max = dontModifyData.length;
    String dontModifyGeneratedValue;
   
    hmDontModifyData = new HashMap<String, String>();
    for(int i = 0; i < max; i++)
    {
      data = dontModifyData[i];
      if (data == null || data.trim().length() == 0)
        continue;
      dontModifyGeneratedValue = cnstDontModify +i;
      hmDontModifyData.put(data, dontModifyGeneratedValue);
      strModifiedMathData = strModifiedMathData.replaceAll(data, dontModifyGeneratedValue);
    }
   
    return strModifiedMathData;
  }

  /**
   * This method unmarks speciall words (not: xxx, xxx) after marked words and
   * after replacing a changed word.
   * @param strDontModifyToken
   * @param strModifiedMathData
   * @return
   */
  private String
  getUnMarkDontModifyMarketedData(String strDontModifyToken,
        String strModifiedMathData)
  {
    String dontModifyData [] = strDontModifyToken.split(" ");
    if (dontModifyData == null || dontModifyData.length == 0)
      return null;
    if (dontModifyData.length == 1)
      return strModifiedMathData.replaceAll(
        cnstDontModify,
        cnstDontModifyBegin + strDontModifyToken
        +cnstDontModifyEnd);
   
    String data;
    int max = hmDontModifyData.size();
    String dontModifyGeneratedValue;
    Set<String> keys = hmDontModifyData.keySet();
    Iterator<String> ite = keys.iterator();
   
    while(ite.hasNext())
    {
      data = ite.next();
      dontModifyGeneratedValue = hmDontModifyData.get(data);
      strModifiedMathData = strModifiedMathData.replaceAll(dontModifyGeneratedValue, data);
    }
   
    return strModifiedMathData;
  }
 
  /**
   * This method reorderer array after max words first, shorter after it etc.
   * parameter from arrUnOrdered array.
   *
   * @param arrUnOrdered
   * @param iBelowValue
   * @return
   * @throws NullPointerException
   * @throws Exception
   */
  private String []
  getOrderedArr(String [] arrUnOrdered, int iBelowValue)
  throws NullPointerException, Exception
  {
    if (arrUnOrdered == null)
      return arrUnOrdered;
    int maxValueLen = 0;
    List<String> list = new ArrayList<String>();
   
    maxValueLen = seekMaxLenghtOfIndexValue(arrUnOrdered, iBelowValue);
    while(maxValueLen != 0 && (iBelowValue == -1 || maxValueLen < iBelowValue))
    {
      list.addAll(getMaxLenghtOfIndexValue(arrUnOrdered, maxValueLen));
      maxValueLen = seekMaxLenghtOfIndexValue(arrUnOrdered, maxValueLen);
    }

    Collections.sort(list, new StringLengthComparator());

    Object [] arrObj = list.toArray();
    int max2 = arrObj.length;
    String [] arrRet = new String [max2];
   
    for(int j = 0; j < max2; j++)
    {
      arrRet[j] = arrObj[j].toString();
    }
   
    return arrRet;
  }
 
  /**
   * @param arrUnOrdered
   * @param iAllValuesOfLen
   * @return
   * @throws NullPointerException
   * @throws Exception
   */
  private Collection<String>
  getMaxLenghtOfIndexValue(String [] arrUnOrdered, int iAllValuesOfLen)
  throws NullPointerException, Exception
  {
    Collection<String> col = new ArrayList<String>();
    int max = arrUnOrdered.length;
    String strValue;
    int iValueLen, maxValueLen = 0;
    boolean bRegexTokenWithPossibleLiteral = false;
   
    for(int i = 0; i < max; i++)
    {
      strValue = getNormalToken(arrUnOrdered[i], bRegexTokenWithPossibleLiteral);
      if (strValue == null)
        continue;
      iValueLen = strValue.length();
      if (iAllValuesOfLen == iValueLen)
        // palauta alkup. arvo, koska se voi sisältää (paisi: xxx):n, eli mitä arvoa ei muuuteta
        col.add(arrUnOrdered[i]);
         
    }

    return col;
  }
 
  /**
   * This method seeks index value of max length below iBelowValue
   * parameter from arrUnOrdered array.
   * @param arrUnOrdered
   * @param iBelowValue
   * @return
   * @throws NullPointerException
   * @throws Exception
   */
  private int
  seekMaxLenghtOfIndexValue(String [] arrUnOrdered, int iBelowValue)
  throws NullPointerException, Exception
  {
    if (arrUnOrdered == null)
      return 0;
   
    if (iBelowValue == 1)
      return 0;
   
    int iValueLen, maxValueLen = 0;
    int max = arrUnOrdered.length;
    String strValue;
    boolean bRegexTokenWithPossibleLiteral = false;

    for(int i = 0; i < max; i++)
    {
      strValue = getNormalToken(arrUnOrdered[i], bRegexTokenWithPossibleLiteral);
      if (strValue == null)
        continue;
      iValueLen = strValue.length();
      if (iValueLen > maxValueLen &&
        (iBelowValue == -1 || iValueLen < iBelowValue))
        maxValueLen = iValueLen;
    }

    return maxValueLen;
  }
 
  /**
   * See the name of method.
   * @return
   */
  private String []
  getArrBothSidesSpaceToken()
  {
    return m_arrBothSidesSpaceToken;   
  }
 
  /*
   * See the name of method.
   * @return
   */
  private String []
  getArrSpaceBeforeButNotAfter()
  {
    return m_arrSpaceBeforeButNotAfter;   
  }
 
  /**
   * See the name of method.
   * @return
   */
  private String []
     getArrNoSpaciesIntoBothSideToken()
  {
    return m_arrNoSpaciesIntoBothSideToken;   
  }
 
  /**
   * See the name of method.
   * @return
   */
  private String []
  getArrSpaceAfterButNotBeforeToken()
  {
    return m_arrSpaceAfterButNotBefore;
  }
 
  /* ok for 14.9.2010, regex search method:
   *
   */
 
  /**
   * This method converts data after the parameters with regexp and java code.
   * @param strModifiedMathData Data or part of it
   * @param strToken A text to changed
   * @param strRegex Used regular expression
   * @param strReplace Replace value (like: " %s", " %s " etc)
   * @return Modified data
   * @throws NullPointerException An error
   */
  private String
  getModifiedMathData(String strModifiedMathData,
            String strToken,
            String strRegex,
            String strReplace)
  throws NullPointerException
  {
    // parameter checking
    if (strModifiedMathData == null)
      return strModifiedMathData;
    if (strToken == null)
      throw new NullPointerException("strToken == null");
    if (strRegex == null)
      throw new NullPointerException("strRegex == null");
    if (strReplace == null)
      throw new NullPointerException("strReplace == null");

    String resultString = null, strValue;
    String regexString = null;
    String replaceString = null;

    try {
      //  Replace regex %s value (like: "regexp1%sregexp1", where %s will be strToken value)
      regexString = String.format(strRegex, strToken);
      //  Replace value (like: " %s", " %s " etc where %s has strToken value)
      replaceString = String.format(strReplace, strToken);
      Pattern regex = Pattern.compile(regexString);
      Matcher regexMatcher = regex.matcher(strModifiedMathData);
      int iStart, iEnd;
     
      boolean bPossibleModificationOfMarkStartWord = false;
      boolean bPossibleModificationOfMarkEndWord = false;
     
      // check token has don-modify this xxx
      int indPossibleModificationOfMarkStartWord = cnstDontModifyBegin.indexOf(strToken);
      if (indPossibleModificationOfMarkStartWord > -1)
        bPossibleModificationOfMarkStartWord = true;
      int indPossibleModificationOfMarkEndWord = cnstDontModifyEnd.indexOf(strToken);
      if (indPossibleModificationOfMarkEndWord > -1)
        bPossibleModificationOfMarkEndWord = true;
     
      boolean ret = false;
     
      try {
       
        // find a searched value
        while(regexMatcher.find())
        {
          // get position values of founded value
          iStart = regexMatcher.start();
          iEnd = regexMatcher.end();
         
          // check if there is don-modify-this text value and if it exists
          // then continue (no chnage)
         
          // check if there is don-modify-begin word before it
          if (bPossibleModificationOfMarkStartWord)
          {
            ret = getPossibleModificationOfMarkWord(cnstDontModifyBegin,
                    strToken, strModifiedMathData, iStart, iEnd);
            if (ret)
              continue;
          }
         
          // check if there is don-modify-end word after it
          if (bPossibleModificationOfMarkEndWord)
          {
            ret = getPossibleModificationOfMarkWord(cnstDontModifyEnd,
                strToken, strModifiedMathData, iStart, iEnd);
            if (ret)
              continue;
          }

          // if this foundedf value has not modified-allready-value, then
          // convert it
          if (isNotModifiedToken(strToken, strModifiedMathData, iStart, iEnd,
              bPossibleModificationOfMarkStartWord,
              bPossibleModificationOfMarkEndWord))
          {
            strValue = strModifiedMathData.substring(iStart, iEnd);
            // some data checking
            if (strValue == null)
              throw new NullPointerException("strValue == null");
            resultString =   strValue.replaceAll(regexString, replaceString);
            if (resultString == null)
              throw new NullPointerException("resultString == null");
            String strStart = strModifiedMathData.substring(0, iStart);
            String strEnd = "";
            if (iEnd < (strModifiedMathData.length()))
              strEnd = strModifiedMathData.substring(iEnd);

            // that this token is handled allready:
            if (strEnd == null || strEnd.trim().length() == 0)
            {
              return strStart + cnstDontModifyBegin +
                 resultString + cnstDontModifyEnd
                 + "" ;
            }
            else
            {
              /* if founded value contains " chars at the end and
               * start of it, then do not change anything, but
               * mark this founded: do not chnage any more,
               * at last call recursive this method to the rest of
               * data
               */
              if (strStart != null && strEnd != null
                && strStart.endsWith("\"")
                && strEnd.startsWith("\"") )
              {
                return strStart + cnstDontModifyBegin +
                   strValue + cnstDontModifyEnd +
                   getModifiedMathData(strEnd, strToken, strRegex, strReplace);
              }
              else
              {
                // normal change without " strikes   
                // at last call recursive this method to the rest of data
                return strStart + cnstDontModifyBegin +
                  resultString + cnstDontModifyEnd +
                  getModifiedMathData(strEnd, strToken, strRegex, strReplace);
              }
            }

          }
        }

        return strModifiedMathData;
      } catch (IllegalArgumentException ex) {
        // Syntax error in the replacement text (unescaped $ signs?)
        throw ex;
      } catch (IndexOutOfBoundsException ex) {
        // Non-existent backreference used the replacement text
        throw ex;
      }
    } catch (PatternSyntaxException ex) {
      // Syntax error in the regular expression
      throw ex;
    }

    //return strModifiedMathData.replaceAll(strRegex, strReplace);
  }
 
  /*
   * for testing of an another opportunity to code this function:
   * because there has been problem with regex special characters,
   * are they literated all ways right!
   */
  private String
  getModifiedMathData2(String strModifiedMathData,
            String strToken,
            String strRegex,
            String strReplace)
  throws NullPointerException
  {
    if (strModifiedMathData == null)
      return strModifiedMathData;
    if (strToken == null)
      throw new NullPointerException("strToken == null");
    if (strRegex == null)
      throw new NullPointerException("strRegex == null");
    if (strReplace == null)
      throw new NullPointerException("strReplace == null");

    String resultString = null, strValue;
    String regexString = null;
    String replaceString = null;

    try {
      int ind = strModifiedMathData.indexOf(strToken);
      if (ind == -1)
        return strModifiedMathData;
     
      int iStart, iEnd, indSearch;
     
      boolean bPossibleModificationOfMarkStartWord = false;
      boolean bPossibleModificationOfMarkEndWord = false;
     
      int indPossibleModificationOfMarkStartWord = cnstDontModifyBegin.indexOf(strToken);
      if (indPossibleModificationOfMarkStartWord > -1)
        bPossibleModificationOfMarkStartWord = true;
      int indPossibleModificationOfMarkEndWord = cnstDontModifyEnd.indexOf(strToken);
      if (indPossibleModificationOfMarkEndWord > -1)
        bPossibleModificationOfMarkEndWord = true;
     
      boolean ret = false;
      int iStrLen = strToken.length();
     
      try {
        resultString = String.format(strReplace, strToken);
        ind = -2;
        while(ind != -1)
        {
          if (ind == -2)
            ind = -1;
          ind = strModifiedMathData.indexOf(strToken, ++ind);
          if (ind == -1)
            break;
          iStart = ind;
          iEnd = ind + iStrLen;
         
          if (bPossibleModificationOfMarkStartWord)
          {
            ret = getPossibleModificationOfMarkWord(cnstDontModifyBegin,
                    strToken, strModifiedMathData, iStart, iEnd);
            if (ret)
              continue;
          }
         
          if (bPossibleModificationOfMarkEndWord)
          {
            ret = getPossibleModificationOfMarkWord(cnstDontModifyEnd,
                strToken, strModifiedMathData, iStart, iEnd);
            if (ret)
              continue;
          }

          if (isNotModifiedToken(strToken, strModifiedMathData, iStart, iEnd,
              bPossibleModificationOfMarkStartWord,
              bPossibleModificationOfMarkEndWord))
          {
            strValue = strModifiedMathData.substring(iStart, iEnd);
            if (strValue == null)
              throw new NullPointerException("strValue == null");
            //resultString = strValue.replaceAll(regexString, replaceString);
            if (resultString == null)
              throw new NullPointerException("resultString == null");
            String strStart = strModifiedMathData.substring(0, iStart);
            String strEnd = "";
            if (iEnd < (strModifiedMathData.length()))
              strEnd = strModifiedMathData.substring(iEnd);

            // that this token is handled allready:
            if (strEnd == null || strEnd.trim().length() == 0)
            {
              return strStart + cnstDontModifyBegin +
                 resultString + cnstDontModifyEnd
                 + "";
            }
            else
            {
              /* if founded value contains " chars in the end and
               * start of it, then do not change anything, but
               * mark this founded: do not chnage any more:
               */
              if (strStart != null && strEnd != null
                && strStart.endsWith("\"")
                && strEnd.startsWith("\"") )
                return strStart + cnstDontModifyBegin +
                   strValue + cnstDontModifyEnd +
                   getModifiedMathData(strEnd, strToken, strRegex, strReplace);               
              else // normal change without " strikes:
              {
                /* resultString.startsWith(" ")
                && */
                /*
                if (/strStart.endsWith(" "))
                  strStart = strStart.substring(0, strStart.length()-1);
                if (strEnd.startsWith(" "))
                  strEnd = strEnd.substring(1);
                */
                /* resultString.endsWith(" ")
                && */
                return strStart + cnstDontModifyBegin +
                  resultString + cnstDontModifyEnd +
                  getModifiedMathData(strEnd, strToken, strRegex, strReplace);
              }
            }

          }
        }

        return strModifiedMathData;
      } catch (IllegalArgumentException ex) {
        // Syntax error in the replacement text (unescaped $ signs?)
        throw ex;
      } catch (IndexOutOfBoundsException ex) {
        // Non-existent backreference used the replacement text
        throw ex;
      }
    } catch (PatternSyntaxException ex) {
      // Syntax error in the regular expression
      throw ex;
    }

    //return strModifiedMathData.replaceAll(strRegex, strReplace);
  }
 
  /**
   * This method is returng a boolean value is this token all ready modified.
   *
   * @param strToken
   * @param strModifiedMathData
   * @param iStart
   * @param iEnd
   * @param bPossibleModificationOfMarkStartWord
   * @param bPossibleModificationOfMarkEndWord
   * @return
   */
  private boolean
  isNotModifiedToken(String strToken, String strModifiedMathData, int iStart, int iEnd,
      boolean bPossibleModificationOfMarkStartWord,
      boolean bPossibleModificationOfMarkEndWord)
  {
    if (strModifiedMathData == null)
      return false;
    if (iStart < 0)
      return false;
    int len = strModifiedMathData.length() ;
    if (iEnd > (len))
      return false;
   
    String strValue = strModifiedMathData.substring(iStart, iEnd);
    if (strValue == null)
      return true;
   
    boolean bStartOk = false;
    boolean bEndOk = false;
   
    String strStart = strModifiedMathData.substring(0, iStart);
    if (strStart == null || strStart.trim().length() == 0)
      bStartOk = true;
    else
      bStartOk = getStartNotModified(strStart);
 
    String strEnd = strModifiedMathData.substring(iEnd);
    if (strEnd == null || strEnd.trim().length() == 0)
      bEndOk = true;
    else
      bEndOk = getEndNotModified(strEnd);

    boolean ret = false;   
    //if (!bStartOk && !bEndOk)
 
    if (bStartOk && bEndOk)
      return true;
   
    return ret;
  }
 
  /**
   * @param markValue
   * @param strToken
   * @param strModifiedMathData
   * @param start
   * @param end
   * @return boolean
   */
  public boolean
  getPossibleModificationOfMarkWord(String markValue,
      String strToken, String strModifiedMathData, int start, int end)
  {// cnstDontModifyEnd,
    if (start == end)
      return false;
   
    int lenData = strModifiedMathData.length();
    if (lenData == 0 || lenData == start) // error!?: lenData == start !!
      return false;
   
    String strFounded = strModifiedMathData.substring(start, end);
    if (strFounded == null)
      return false;   
   
    String strValue = strFounded.trim();
    int len = strValue.length();
    if (len == 0)
      return false;
   
    int ind = getMarkValueIndexNearOfFoundToken(strModifiedMathData, markValue, start, end);
    if (ind == -1)
      return false;
   
    int indEnd = ind + markValue.length();
    if (ind <= start && start <= indEnd && ind <= end && end <= indEnd )
      return true;

    return false;
   
  }
 
  /**
   * @param strModifiedMathData
   * @param markValue
   * @param start
   * @param end
   * @return int
   */
  public int
  getMarkValueIndexNearOfFoundToken(String strModifiedMathData,
                    String markValue,
                    int start,
                    int end)
  {
    if (strModifiedMathData == null || markValue == null | start < 0 || end < 0)
      return -1; // = false
   
    int len = strModifiedMathData.length();
    if (len < 1)
      return -1; // = false

    if (start > len)
      return -1; // = false
    if (end > len)
      return -1; // = false

    int markLength = markValue.length();
    if (markLength < 1)
      return -1; // = false
   
    int indStartMark = start - markLength;
    if (indStartMark < 0)
      indStartMark = 0;
    int indEndMark = end + markLength;
    if (indEndMark > len)
      indEndMark = len;
    String strPossibleMarkValue = strModifiedMathData.substring(indStartMark, indEndMark);
    if (strPossibleMarkValue == null || strPossibleMarkValue.trim().length() == 0)
      return -1;
    int lenFoundMarkValue = strPossibleMarkValue.length();
    if (lenFoundMarkValue < markLength)
      return -1;
    int indFoundMarkValue = strPossibleMarkValue.indexOf(markValue);
    if (indFoundMarkValue == -1)
      return -1;
    int indMarkValue = (indStartMark +indFoundMarkValue);
    return indMarkValue;
  }
 
  /**
   * This method returns a boolean value "has a token a dont-modify value"
   * before it.
   * @param strValue text before founded token
   * @return See above.
   */
  private boolean
  getStartNotModified(String strValue)
  {
    if (strValue != null && strValue.trim().length() != 0)
    {     
      int indStart = strValue.lastIndexOf(cnstDontModifyBegin);
      int len = strValue.length();
      if (indStart == -1)
        return true;
      int iPlace = len - cnstDontModifyBegin.length();
      if (indStart == iPlace)
        return false;
      int indEnd = strValue.lastIndexOf(cnstDontModifyEnd);
      // jos ei end-constia, löytynyt begin-consti tämän oma begin-consti:
      if (indEnd == -1)
        return false;
      // jos ei end-constia löytynyt begin-consti jälkeen,
      // ei ole tämän oma begin-consti:
      if (indEnd > indStart )
        return true;
      return false;
    }
   
    return true;
  }

  /**
   * This method returns a boolean value "has a token a dont-modify value"
   * after it.
   * @param strValue text after founded token
   * @return See above.
   */
  private boolean
  getEndNotModified(String strValue)
  {
    if (strValue != null && strValue.trim().length() != 0)
    {
      int indEnd = strValue.indexOf(cnstDontModifyEnd);
      // jos ei end-constia, ei ole tämän oma begin-consti:
      if (indEnd == -1 )
        return true;
     
      if (indEnd == 0)
        return false;
     
      int len = strValue.length();
      //int iPlace = len - cnstDontModifyEnd.length();
      int indStart = strValue.indexOf(cnstDontModifyBegin);
      // jos ei begin-constia, on tämän end-consti
      if (indStart == -1)
        return false;
      // jos ei end-constia löytynyt begin-consti jälkeen,
      // ei ole tämän oma end-consti:
      if (indStart < indEnd   )
        return true;
     
      return false;
    }

    // kun hakee substring:ia, voi vastaus olla väärä, mutta getStartNotModified(...) on tarkka
    return true;
  }

  private String
  getDontModifyToken(String strToken)
  throws NullPointerException, Exception
  {
    if (strToken == null)
      throw new NullPointerException("strToken is null!");
    int ind = strToken.indexOf(cnstNOTThiswords);
    if (ind == -1)
      return null;
    int ind2 = strToken.lastIndexOf(")");
    if (ind2 == -1)
      return null;
    String strNOTThiswords = strToken.substring(
        ind +cnstNOTThiswords.length(), ind2);
    if (strNOTThiswords == null)
      throw new NullPointerException("strNOTThiswords == null!");
    if (strNOTThiswords.trim().length() == 0)
      throw new Exception("strNOTThiswords.trim().length() == 0");
    return strNOTThiswords.trim(); // foundedd cnstNOTThiswords and ')', do not change this
    // word
  }

  /**
   * This method returns normal token value after regex meta character rules
   * @param strToken
   * @param bRegexTokenWithPossibleLiteral
   * @return
   * @throws NullPointerException
   * @throws Exception
   */
  private String
  getNormalToken(String strToken, boolean bRegexTokenWithPossibleLiteral)
  throws NullPointerException, Exception
  {
    String tmp = getDontModifyToken(strToken);
    if (tmp == null) // no strNOTThiswords: value
    {
      if (bRegexTokenWithPossibleLiteral)
        return getRegexTokenWithPossibleLiteral(strToken);
      else
        return strToken;
    }
         
    String [] arrValues = strToken.split(" ");
    if (arrValues[0] == null)
      throw new NullPointerException("arrValues[0] is null!");
    if (bRegexTokenWithPossibleLiteral)
      return getRegexTokenWithPossibleLiteral(arrValues[0]);
    else
      return arrValues[0];
  }
 
  /**
   * This method returns token replaced with \ characters if it contains some
   * meta characters
   * @param strToken
   * @return
   */
  private String
  getRegexTokenWithPossibleLiteral(String strToken)
  {
    int max = arrRegexToken.length;
    String regexToken;
   
    for(int i = 0; i < max; i++)
    {
      regexToken = arrRegexToken[i];
      if (regexToken == null)
        continue;
      // TODO: check this rule, when thinking morphys rule;
      // there migth be some missmachts!: indirect modified after below if,
      // and coming here and match on the next if!!:
      if (regexToken.equals(strToken))
        return "\\" +strToken;
     
      if(strToken.contains(regexToken) && ! regexToken.equals("\\") )
        strToken = strToken.replaceAll("\\"+regexToken, "\\\\"+regexToken);
    }
    return strToken;
  }
 
  /**
   * The main application, for testing purposes
   * @param args
   */
  public static void main(String[] args)
  {
   
    System.out.println("The application has been started.");
    int program_exit = 0;
    try {
      JAsciiMath jAsciiMath = getJAsciiMath(args);
      if (jAsciiMath != null)
      {
        program_exit = jAsciiMath.replaceAsciiMathBlocks();
      }
      System.out.println("The end of the application");
    } catch(Exception e){
      e.printStackTrace();
      program_exit = 1;
      System.out.println("An application error has been occurred!");
    }
    System.exit(program_exit);
  }

  /**
   * @param args
   * @return
   * @throws Exception
   */
  private static JAsciiMath
  getJAsciiMath(String[] args)
  throws Exception
  {
    m_static_strInputFileName = null;
    m_static_strOutputFileName = null;
    checkCommandLineParameters(args);
   
    boolean bCorrectStrikeErrors = false;
    boolean bCheckStrikeErrors = true;
    JAsciiMath jAsciiMath = new JAsciiMath("", bCheckStrikeErrors,
        bCorrectStrikeErrors, false);
    jAsciiMath.setInputFileName(m_static_strInputFileName);
    jAsciiMath.setOutputFileName(m_static_strOutputFileName);
    //jAsciiMath.setConvertAsciiMathDataWithSpaceRules(true);
    return jAsciiMath;
  }
 
  /**
   * Un implemented method.
   * @param args
   * @throws Exception
   */
  private static void
  checkCommandLineParameters(String[] args)
  throws Exception
  {
   
  }

  /**
   * This method returns a modified String after replaced all reserved words
   * in the paraemeter value. Replaced words and new values for them are located in
   * the .properties file of this class.
   * @param strAsciiMath
   * @return See above
   */
  private String
  replaceAllReservedWords_new(String strAsciiMath)
  throws DtbookAsciiMathException
  {
    if (strAsciiMath == null || strAsciiMath.trim().length() == 0)
      return strAsciiMath;

    int dataLen = strAsciiMath.length();
    int max = m_sortedReplaceReservedWords.size();
    if (max == 0
      return strAsciiMath;
   
    int [][] arrIntstrikepairStartStopValues = getPossibleStrikePairs(strAsciiMath);

    /*
    while (stepper.hasNext()) {
        current = (String)stepper.next();
        System.out.println(current);
    }
    //listvalues
     *      
     */
   
    String strSearch, strValue;
    // use sorted list, because longest search value will be handled at first etc
    Iterator<String> ite = m_sortedReplaceReservedWords.iterator();
    int ind ;
    String old_value = new String(strAsciiMath);
   
    for(; ite.hasNext(); )
    {
      strSearch = (String)ite.next();
      dataLen = strAsciiMath.length();
      if (strSearch == null || strSearch.trim().length() == 0)
        continue;
      // get replace value by search value 
      strValue = (String)this.m_propertyReplaceReservedWords.get(strSearch);
      if (strValue == null)
        strValue = "";
      if (!old_value.equals(strAsciiMath))
      {
        arrIntstrikepairStartStopValues = getPossibleStrikePairs(strAsciiMath);
        old_value = new String(strAsciiMath);
      }
      ind = strAsciiMath.indexOf(strSearch);
     
      if (ind > -1 /* strAsciiMath.contains(strSearch) */)
      {
        String start, end = "", replacedValue = strValue;
        int len = strSearch.length();
        StringBuffer sb =  new StringBuffer();
        int pos, iArrIndex = 0, indArr = 0, iCurrent = 0;
       
        while(ind != -1)
        {
          start = strAsciiMath.substring(iCurrent, ind);
          if (start == null)
            start = "";
          pos = (ind + len);
          end = strAsciiMath.substring(pos);
          if (end == null)
            end = "";
          if (arrIntstrikepairStartStopValues == null
             || arrIntstrikepairStartStopValues.length == 0
             || indArr == -1)
          {
            System.err.println("start='" + start +"'");
            System.err.println("start.len='" + start.length() +"'");
            sb.append(start);
            System.err.println("sb.len='" + sb.length() +"'");
            System.err.println("replacedValue.len='" + replacedValue.length() +"'");
            System.err.println("replacedValue='" + replacedValue +"'");
            sb.append(replacedValue);         
            System.err.println("sb.len='" + sb.length() +"'");
            iCurrent = ind + len;
          }
          else
          {
            String strAppend = strAsciiMath.substring(iCurrent, arrIntstrikepairStartStopValues[indArr][1]);
            sb.append(strAppend);
            iCurrent = arrIntstrikepairStartStopValues[indArr][1];
            end = strAsciiMath.substring(iCurrent);
          }   
          if (iCurrent >= dataLen)
            break;
          // strAsciiMath = end;
          ind = strAsciiMath.indexOf(strSearch, iCurrent);
        }
        sb.append(end);
        strAsciiMath = sb.toString();
        if (!old_value.equals(strAsciiMath))
        {
          arrIntstrikepairStartStopValues = getPossibleStrikePairs(strAsciiMath);
          old_value = new String(strAsciiMath);
        }
      }
    }
    return strAsciiMath;
  }

  private int
  getInSideOfStrikes(int ind, int [][] arrIntstrikepairStartStopValues)
  {
    if (arrIntstrikepairStartStopValues == null)
      return -1;
    if (arrIntstrikepairStartStopValues.length == 0)
      return -1;
    if (ind == -1)
      return -1;
    int max = arrIntstrikepairStartStopValues.length;
    for(int i = 0; i < max; i++)
    {
      if (arrIntstrikepairStartStopValues[i][0] <= ind
          && arrIntstrikepairStartStopValues[i][1] >= ind)
        return i;
    }
    return -1;
  }
       
  private int [][] getPossibleStrikePairs(String strAsciiMath)
  {
    if (strAsciiMath == null)
      return null;
    if (strAsciiMath.indexOf('"') == -1)
      return null;
   
    try {
      // search all " " pairs
      Pattern regex = Pattern.compile("\" *([\\w+ ])+ *\"");
      Matcher regexMatcher = regex.matcher(strAsciiMath);
      //MatchResult matchResult;
      try {
        int iCounter = 0;
        boolean founded = false;
        StringBuffer sp = new StringBuffer();
        int start, end;
       
        while(regexMatcher.find())
        {
          founded = true;
          iCounter++;
          start = regexMatcher.start();
          end = regexMatcher.end();
          sp.append("" + start +" " +end +"\n");
        } // end of while

        if (founded)
        {
          int [][] arrIntstrikepairStartStopValues = new int[iCounter][2];
          String [] startStops = sp.toString().split("\n");
          int max = startStops.length;
          String strikepairStartStopValue, strOneValue, strSecondValue;
          String [] arrStrikepairStartStopValue;
         
          for(int i = 0; i < max; i++)
          {
            strikepairStartStopValue = startStops[i];
            if (strikepairStartStopValue == null)
              continue;
            arrStrikepairStartStopValue = strikepairStartStopValue.split(" ");
            strOneValue = arrStrikepairStartStopValue[0];
            if (strOneValue == null)
              continue;
            strSecondValue = arrStrikepairStartStopValue[1];
            if (strSecondValue == null)
              continue;           
            arrIntstrikepairStartStopValues[i][0] = new Integer(strOneValue).intValue();
            arrIntstrikepairStartStopValues[i][1] = new Integer(strSecondValue).intValue();
          }
            /*
          int [][] arrIntstrikepairStartStopValues = getPossibleStrikePairs(strAsciiMath);
        String [] strikepairStartStopValues =
          int max = strikepairStartStopValues.length;
          String strikepairStartStopValue;
         
          String [] strikepairStartStop;
          int [][] arrIntstrikepairStartStopValues = new int [max][2];
         
          for(int i = 0; i < max; i++)
          {
            strikepairStartStopValue = strikepairStartStopValues[i];
            if (strikepairStartStopValue == null)
              continue;
            strikepairStartStop = strikepairStartStopValue.split(" ");
          }
          
           */
          return arrIntstrikepairStartStopValues;
         
        }
        return null;
         
      } catch (IllegalArgumentException ex) {
        // Syntax error in the replacement text (unescaped $ signs?)
        throw ex;
      } catch (IndexOutOfBoundsException ex2) {
        // Non-existent backreference used the replacement text
        throw ex2;
      }
    } catch (PatternSyntaxException ex3) {
      // Syntax error in the regular expression
      throw ex3;
    }
  }

  /**
   * This method returns a marked asciimath string. When some changed word
   * (reserved or not) is a substring of an another replaced or modified string,
   * these words must marked with: _do_not_modify<number> = <replacedword>,
   * with _do_not_modify<number+1> = <replacedword2> etc.
   * @param strAsciiMath
   * @return
   */
  private String
  getDontModifyData(String strAsciiMath)
  {
    return strAsciiMath;
  }
 
  /**
   * This method reads property file of the class. If exceptions occurs it is
   * an error.
   * @throws DtbookAsciiMathException
   * @throws FileNotFoundException
   * @throws IOException
   */
  private void
  readSectionNamesAndSectionData()
  throws DtbookAsciiMathException, FileNotFoundException, IOException
  {
    if (!m_FileReplaceProperty.exists())
      throw new DtbookAsciiMathException(
          String.format(cnstPropertyFileDoesNotFound,
                m_FileReplaceProperty.getAbsolutePath()));
   
    m_propertyReplace = new Properties();
    FileReader fr = new FileReader(m_FileReplaceProperty);
    m_propertyReplace.load(fr);
    fr.close();
    m_space_on_both_sides_name = (String)
        m_propertyReplace.get(cnstSpace_on_both_sides_name);

    m_space_on_neigther_sides_name = (String)
        m_propertyReplace.get(cnstSpace_on_neigther_sides_name);
   
    m_space_before_but_not_after_name = (String)
        m_propertyReplace.get(cnstSpace_before_but_not_after_name);
     
    m_space_after_but_not_before_name = (String)
        m_propertyReplace.get(cnstSpace_after_but_not_before_name);

    m_replace_reserved_words_section_name = (String)
        m_propertyReplace.get(cnstReplace_reserved_words_section_name);

    m_replaceAllComma = (String)m_propertyReplace.get(cnstReplaceAllComma);

    m_replaceAllWithSemiColon = (String)m_propertyReplace.get(cnstReplaceAllWithSemiColon);
   
    m_replaceAllNumberPoint = (String)m_propertyReplace.get(cnstReplaceAllNumberPoint);
   
    m_replaceAllNumberComma = (String)m_propertyReplace.get(cnstReplaceAllNumberComma);
   
    m_regex_special_meaning_characters = (String)m_propertyReplace.get(cnstRegex_special_meaning_characters);
    if (m_regex_special_meaning_characters != null)
    {
      String [] arrRegex = m_regex_special_meaning_characters.trim().split(" ");
      if (arrRegex != null)
      {
        arrRegexToken = arrRegex;
      }
    }
   
    fr = new FileReader(m_FileReplaceProperty);
   
    BufferedReader br = new BufferedReader(fr);
   
    String line;
    //StringBuffer sb = new StringBuffer();
    List<String> listPropertyLines = new ArrayList<String>();
   
    while ( (line = br.readLine()) != null )
    {
      listPropertyLines.add(line);
    }
   
    br.close();
    if (listPropertyLines.size() == 0)
      throw new DtbookAsciiMathException("Property "
          + m_FileReplaceProperty.getAbsolutePath() + " file is etmpty!");
    fr.close();
    readSections(listPropertyLines);
  }
 
  /**
   * This method collects special sections data for a properties (=config) file
   * @param listPropertyLines Data is the form of list
   */
  private void
  readSections(List<String> listPropertyLines)
  {
    String line = null,
         currentSectionName = null,
         newSectionName = null;
    int max = listPropertyLines.size();
    boolean bInsideSection = false;
   
    for(int i = 0; i < max; i++)
    {
      line = listPropertyLines.get(i);
      if (line == null // Skip null, emptys line and comment lines
        || line.trim().length() == 0
        || (!bInsideSection && line.trim().startsWith("#"))
        )
        continue;
     
      //line = line.trim();     
      // if line is not section name and has not finded a first section name:
      newSectionName = getSectionName(line);
      if (! bInsideSection && newSectionName == null)
        continue;   
     
      // if an first section or an old section has finished
      // and a new has been started
      if (!bInsideSection || (currentSectionName != null
        && newSectionName != null
        && ! currentSectionName.equals(newSectionName)) )
      {
        createNewSection(newSectionName, currentSectionName);
        currentSectionName = newSectionName;       
        bInsideSection = true;
        continue;
      }
      addIntoSection(currentSectionName, line);
    }
  }
 
  /**
   * This method creates new variable instancies when collectino config
   * data.
   * @param newSectionName
   * @param currentSectionName
   */
  private void
  createNewSection(String newSectionName, String currentSectionName)
  {
    /*
     j = arrBothSidesSpaceToken
     arrBeforeSpaceToken
     j = arrNoSpaciesIntoBothSideToken
     j = arrNoSpaceAfterToken
    
     space_on_both_sides_name=molemmin_puolin
     space_on_neigther_sides_name=ei_kummallakaan_puolella
     space_before_but_not_after_name=ennen_mutta_ei_jalkeen
     space_after_but_not_before_name=jalkeen_mutta_ei_ennen
     */
    //if (m_listCurrentToken != null)
      ///createTokenArray(currentSectionName);
   
    if (newSectionName.equals(m_space_on_both_sides_name))
    {
      m_arrBothSidesSpaceToken = null;
      m_listCurrentToken = new RuleConfig();
      m_srcBothSidesSpaceToken = m_listCurrentToken;     
    }
    else
    if (newSectionName.equals(m_space_after_but_not_before_name))
    {
      m_arrSpaceAfterButNotBefore = null;
      m_listCurrentToken = new RuleConfig();
      m_srcSpaceAfterButNotBeforeToken = m_listCurrentToken;
    }
    else
    if (newSectionName.equals(m_space_on_neigther_sides_name))
    {
      m_arrNoSpaciesIntoBothSideToken = null;
      m_listCurrentToken = new RuleConfig();
      m_srcNoSpaciesIntoBohSideToken = m_listCurrentToken;     
    }
    else
    if (newSectionName.equals(m_space_before_but_not_after_name))
    {
      m_arrSpaceBeforeButNotAfter = null;
      m_listCurrentToken = new RuleConfig();
      m_srcSpaceBeforeButNotAfter = m_listCurrentToken;   
    }
    else
    if (newSectionName.equals(m_replace_reserved_words_section_name))
    {   
      m_listCurrentToken = new RuleConfig();
      m_listReplace_reserved_wordToken = m_listCurrentToken;
    }
  }
 
  /*
  private void
  createTokenArray(String listCurrentToken)
  {
    // m_listCurrentToken
  }
  */
 
  /**
   * This method adds a line data into current token list
   * @param currentSectionName
   * @param line
   */
  private void
  addIntoSection(String currentSectionName, String line)
  {
    m_listCurrentToken.addToken(line);
  }
 
  /**
   * This method is returning a name of section.
   * @param line A readed line from properties file, spec. versio of properties file
   * @return Returns a string value if has been founded a section name,otherwise it
   * returns a null
   */
  private String
  getSectionName(String line)
  {
    if (line == null)     
      return null;
   
    if ( ! (line.contains(this.m_space_after_but_not_before_name +":")
      ||  line.contains(this.m_space_before_but_not_after_name +":")
      ||  line.contains(this.m_space_on_both_sides_name +":")
      ||  line.contains(this.m_space_on_neigther_sides_name +":")
      ||  line.contains(this.m_replace_reserved_words_section_name +":"))
      )
      return null;
   
    int ind = line.indexOf(':');
    if (ind < 0)
      return null;
   
    String ret = line.substring(0, ind);
    if (ret == null)
      return null;
     
    ret = ret.trim();
    if (ret.length() == 0)
      return null;
   
    return ret;
  }

  /**
   * This method sets warning on or off.
   * @param value
   */
  public void setWarningsOn(boolean value)
  {
    m_bWarningsOn = value;
  }
 
 
  /**
   * This method gets warning boolean value.
   * @return boolean
   */
  public boolean getWarningsOn() { return m_bWarningsOn; }
 
  /**
   * This method is converting asciimath xml blocks within firefox browser
   * into ascimath daisy xml entities.
   *
   * @param templatefilename
   * @param dtbookFileName Dtbook-asciimath file name
   * @param dtbookCharacterSet Used characterset
   * @param jasciiMathPropertyFileName Used asciimath property file name
   * @param asciiMathWWWBrowserApplication
   * @param targetDtbookFileName Target file name
   * @param targetCharacterSet Used target character set
   * @param bPrintXmlStatements
   * @throws DtbookAsciiMathException An error occurred
   * @throws FileNotFoundException File not found error occurred
   * @throws InterruptedException  An error occurred,
   * @throws IOException An io error occurred
   * @throws NullPointerException An null pointer error occurred
   * @throws Exception An error occurred
   */
  public int
  modifyDtbookIntoAsciiMathXml(String templatefilename,
                 String dtbookFileName,
                 String dtbookCharacterSet,
                 String jasciiMathPropertyFileName,
                 String asciiMathWWWBrowserApplication,
                 String targetDtbookFileName,
                 String targetCharacterSet,
                 boolean bPrintXmlStatements,
                 boolean bCheckStrikeErrors,
                 boolean p_bCorrectStrikeErrors)
  throws DtbookAsciiMathException,
  FileNotFoundException,
  InterruptedException,
  IOException,
  NullPointerException,
  Exception
  {
    AsciiMathXml asciimathxml = new AsciiMathXml();
    Properties prop = new Properties();
    File fileProp = new File(jasciiMathPropertyFileName);
    FileReader freader = new FileReader(fileProp);
    prop.load(freader);
    String strSleepCounter = prop.getProperty("sleepconter");
    if (strSleepCounter != null && strSleepCounter.trim().length() > 0)
    {
      try {
        int iSleepCounter = Integer.valueOf(strSleepCounter);
        asciimathxml.setSleepConter(iSleepCounter);
      } catch(Exception inte){
       
      }
    }
    freader.close();
    int result = -1;
    try {
      result = asciimathxml.modifyDtbookIntoAsciiMathXml(templatefilename,
          dtbookFileName, dtbookCharacterSet, jasciiMathPropertyFileName,
          asciiMathWWWBrowserApplication, targetDtbookFileName,
          targetCharacterSet, bPrintXmlStatements,
          bCheckStrikeErrors, p_bCorrectStrikeErrors);
    } catch(Exception e) {
      m_sbError = new StringBuffer(e.getMessage());
      throw e;
    }
      //asciimathxml.
      String printdata = asciimathxml.getPrintData();
      m_sbPrintData = new StringBuffer((printdata == null ? "" : printdata));
      String data = asciimathxml.getOutputData();
      m_sb = new StringBuffer((data == null ? "" : data));
      String error = asciimathxml.getErrorData();
      m_sbError = new StringBuffer((error == null ? "" : error));
      if (asciimathxml.getJAsciiMath() != null)
        m_hm_asciimath_values = asciimathxml.getJAsciiMath().getAsciimatHashMapValues();
      // ???
      return result;
      /*
    } catch(Exception e) {
      m_sbError = new StringBuffer(e.getMessage());
      throw e;     
    }
    */
  }
 
  public AsciiMathBlockValue [] getArrayOfAsciiMathBlocks()
  {
    return m_arrblok;
  }
}
TOP

Related Classes of fi.celia.asciimath.JAsciiMath

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.