diff --git a/source/java/org/openoffice/da/comp/writer2latex/ConfigurationDialog.java b/source/java/org/openoffice/da/comp/writer2latex/ConfigurationDialog.java
index a77c363..c078755 100644
--- a/source/java/org/openoffice/da/comp/writer2latex/ConfigurationDialog.java
+++ b/source/java/org/openoffice/da/comp/writer2latex/ConfigurationDialog.java
@@ -20,7 +20,7 @@
*
* All Rights Reserved.
*
- * Version 1.2 (2009-09-23)
+ * Version 1.2 (2009-09-27)
*
*/
@@ -29,6 +29,8 @@ package org.openoffice.da.comp.writer2latex;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.text.Collator;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@@ -828,6 +830,7 @@ public final class ConfigurationDialog extends WeakBase
for (String s : symbolnames) {
sSymbolNames[i++] = s;
}
+ sortStringArray(sSymbolNames);
dlg.setListBoxStringItemList("MathSymbolName", sSymbolNames);
dlg.setListBoxSelectedItem("MathSymbolName", (short)0);
sCurrentMathSymbol = sSymbolNames[0];
@@ -838,6 +841,7 @@ public final class ConfigurationDialog extends WeakBase
for (String s : names) {
sNames[j++] = s;
}
+ sortStringArray(sNames);
dlg.setListBoxStringItemList("TextInput", sNames);
dlg.setListBoxSelectedItem("TextInput", (short)0);
sCurrentText = sNames[0];
@@ -905,5 +909,12 @@ public final class ConfigurationDialog extends WeakBase
}
}
+
+ // Utilities
+ private void sortStringArray(String[] theArray) {
+ // TODO: Get locale from OOo rather than the system
+ Collator collator = Collator.getInstance();
+ Arrays.sort(theArray, collator);
+ }
}
diff --git a/source/java/writer2latex/api/ConverterFactory.java b/source/java/writer2latex/api/ConverterFactory.java
index 970de4e..6c6b031 100644
--- a/source/java/writer2latex/api/ConverterFactory.java
+++ b/source/java/writer2latex/api/ConverterFactory.java
@@ -20,7 +20,7 @@
*
* All Rights Reserved.
*
- * Version 1.2 (2009-09-17)
+ * Version 1.2 (2009-09-28)
*
*/
@@ -33,7 +33,7 @@ public class ConverterFactory {
// Version information
private static final String VERSION = "1.1.1";
- private static final String DATE = "2008-09-17";
+ private static final String DATE = "2009-09-28";
/** Return version information
* @return the Writer2LaTeX version in the form
diff --git a/source/java/writer2latex/latex/LaTeXConfig.java b/source/java/writer2latex/latex/LaTeXConfig.java
index b9159d8..f2b0aa5 100644
--- a/source/java/writer2latex/latex/LaTeXConfig.java
+++ b/source/java/writer2latex/latex/LaTeXConfig.java
@@ -20,14 +20,13 @@
*
* All Rights Reserved.
*
- * Version 1.2 (2009-09-24)
+ * Version 1.2 (2009-09-28)
*
*/
package writer2latex.latex;
import java.util.HashMap;
-import java.util.Enumeration;
import java.util.Map;
import java.util.Set;
@@ -46,12 +45,17 @@ import writer2latex.latex.util.StyleMap;
import writer2latex.util.Misc;
public class LaTeXConfig extends writer2latex.base.ConfigBase {
+ /////////////////////////////////////////////////////////////////////////
+ // I. Define items needed by ConfigBase
+
protected int getOptionCount() { return 63; }
protected String getDefaultConfigPath() { return "/writer2latex/latex/config/"; }
- // Override getter and setter methods for options in order to:
+ /////////////////////////////////////////////////////////////////////////
+ // II. Override getter and setter methods for simple options in order to:
// - Treat the custom preamble like a regular option, even though the xml representation is different
- // - Be backwards compatible (renamed option)
+ // - Be backwards compatible (renamed the option keep_image_size)
+
@Override public void setOption(String sName,String sValue) {
if (sName.equals("custom-preamble")) {
sCustomPreamble = sValue;
@@ -72,6 +76,9 @@ public class LaTeXConfig extends writer2latex.base.ConfigBase {
}
}
+ /////////////////////////////////////////////////////////////////////////
+ // III. Declare all constants
+
// Backend
public static final int GENERIC = 0;
public static final int DVIPS = 1;
@@ -103,8 +110,6 @@ public class LaTeXConfig extends writer2latex.base.ConfigBase {
public static final int CUSTOM = 4;
// Options
- protected int OPTION_COUNT = 63;
-
private static final int BACKEND = 0;
private static final int NO_PREAMBLE = 1;
private static final int NO_INDEX = 2;
@@ -168,21 +173,29 @@ public class LaTeXConfig extends writer2latex.base.ConfigBase {
private static final int SPLIT_TOPLEVEL_SECTIONS = 60;
private static final int SAVE_IMAGES_IN_SUBDIR = 61;
private static final int DEBUG = 62;
-
- protected String sCustomPreamble = "";
- protected StyleMap par = new StyleMap();
- protected StyleMap parBlock = new StyleMap();
- protected StyleMap text = new StyleMap();
- protected StyleMap list = new StyleMap();
- protected StyleMap listItem = new StyleMap();
- protected StyleMap textAttr = new StyleMap();
- protected HeadingMap headingMap = new HeadingMap(5);
+ /////////////////////////////////////////////////////////////////////////
+ // IV. Our options data
+
+ private ComplexOption headingMap;
+ private ComplexOption parMap;
+ private ComplexOption parBlockMap;
+ private ComplexOption listMap;
+ private ComplexOption listItemMap;
+ private ComplexOption textMap;
+ private ComplexOption textAttrMap;
private ComplexOption stringReplace;
private ComplexOption mathSymbols;
+ private String sCustomPreamble = "";
+ /////////////////////////////////////////////////////////////////////////
+ // V. The rather long constructor setting all defaults
+
+ /** Construct a new LaTeXConfig
with default values for all options
+ */
public LaTeXConfig() {
super();
+
// create options with default values
options[NO_PREAMBLE] = new BooleanOption("no_preamble","false");
options[NO_INDEX] = new BooleanOption("no_index","false");
@@ -297,19 +310,49 @@ public class LaTeXConfig extends writer2latex.base.ConfigBase {
options[SPLIT_TOPLEVEL_SECTIONS] = new BooleanOption("split_toplevel_sections","false");
options[SAVE_IMAGES_IN_SUBDIR] = new BooleanOption("save_images_in_subdir","false");
options[DEBUG] = new BooleanOption("debug","false");
- // Headings for article class:
- headingMap.setLevelData(1,"section",1);
- headingMap.setLevelData(2,"subsection",2);
- headingMap.setLevelData(3,"subsubsection",3);
- headingMap.setLevelData(4,"paragraph",4);
- headingMap.setLevelData(5,"subparagraph",5);
+
+ // Complex options - heading map
+ headingMap = addComplexOption("heading-map");
+ Map attr = new HashMap();
+ attr.put("name", "section");
+ attr.put("level", "1");
+ headingMap.put("1", attr);
- // Complex options
+ attr = new HashMap();
+ attr.put("name", "subsection");
+ attr.put("level", "2");
+ headingMap.put("2", attr);
+
+ attr = new HashMap();
+ attr.put("name", "subsubsection");
+ attr.put("level", "3");
+ headingMap.put("3", attr);
+
+ attr = new HashMap();
+ attr.put("name", "paragraph");
+ attr.put("level", "4");
+ headingMap.put("4", attr);
+
+ attr = new HashMap();
+ attr.put("name", "subparagraph");
+ attr.put("level", "5");
+ headingMap.put("5", attr);
+
+ // Complex options - style maps
+ parMap = addComplexOption("paragraph-map");
+ parBlockMap = addComplexOption("paragraph-block-map");
+ listMap = addComplexOption("list-map");
+ listItemMap = addComplexOption("list-item-map");
+ textMap = addComplexOption("text-map");
+ textAttrMap = addComplexOption("text-attribute-map");
+
+ // Complex options - string replace
stringReplace=addComplexOption("string-replace");
+
// Standard string replace:
// Fix french spacing; replace nonbreaking space
// right before em-dash, !, ?, : and ; (babel handles this)
- Map attr = new HashMap();
+ attr = new HashMap();
attr.put("fontenc", "any");
attr.put("latex-code", " \u2014");
stringReplace.put("\u00A0\u2014",attr);
@@ -340,51 +383,81 @@ public class LaTeXConfig extends writer2latex.base.ConfigBase {
//stringReplace.put("\u00AB\u00A0","\u00AB ",I18n.readFontencs("any"));
//stringReplace.put("\u00A0\u00BB"," \u00BB",I18n.readFontencs("any"));
+ // Complex options - math user defined symbols
mathSymbols = addComplexOption("math-symbol-map");
}
+
+ ////////////////////////////////////////////////////////////////////////////
+ // VI. Provide methods to fill in the gaps in the supers read and write methods
protected void readInner(Element elm) {
- if (elm.getTagName().equals("style-map")) {
+ if (elm.getTagName().equals("heading-map")) {
+ // Unlike other complex options, a heading map is completely replaced
+ headingMap.clear();
+ Node child = elm.getFirstChild();
+ while (child!=null) {
+ if (child.getNodeType()==Node.ELEMENT_NODE) {
+ Element childElm = (Element) child;
+ if (childElm.getTagName().equals("heading-level-map")) {
+ if (childElm.hasAttribute("writer-level")) {
+ Map attr = new HashMap();
+ attr.put("name",childElm.getAttribute("name"));
+ attr.put("level",childElm.getAttribute("level"));
+ headingMap.put(childElm.getAttribute("writer-level"), attr);
+ }
+ }
+ }
+ child = child.getNextSibling();
+ }
+ }
+ else if (elm.getTagName().equals("style-map")) {
String sName = elm.getAttribute("name");
String sFamily = elm.getAttribute("family");
if (sFamily.length()==0) { // try old name
sFamily = elm.getAttribute("class");
}
- String sBefore = elm.getAttribute("before");
- String sAfter = elm.getAttribute("after");
- boolean bLineBreak = !"false".equals(elm.getAttribute("line-break"));
- boolean bVerbatim = "true".equals(elm.getAttribute("verbatim"));
+
+ Map attr = new HashMap();
+ attr.put("before", elm.getAttribute("before"));
+ attr.put("after", elm.getAttribute("after"));
+
if ("paragraph".equals(sFamily)) {
- par.put(sName,sBefore,sAfter,bLineBreak,bVerbatim);
+ if (elm.hasAttribute("line-break")) { attr.put("line-break", elm.getAttribute("line-break")); }
+ if (elm.hasAttribute("verbatim")) { attr.put("verbatim", elm.getAttribute("verbatim")); }
+ parMap.put(sName, attr);
}
if ("paragraph-block".equals(sFamily)) {
- String sNext = elm.getAttribute("next");
- parBlock.put(sName,sBefore,sAfter,sNext,bVerbatim);
- }
- else if ("text".equals(sFamily)) {
- text.put(sName,sBefore,sAfter,false,bVerbatim);
+ attr.put("next", elm.getAttribute("next"));
+ if (elm.hasAttribute("verbatim")) { attr.put("verbatim", elm.getAttribute("verbatim")); }
+ parBlockMap.put(sName, attr);
}
else if ("list".equals(sFamily)) {
- list.put(sName,sBefore,sAfter);
+ listMap.put(sName, attr);
}
else if ("listitem".equals(sFamily)) {
- listItem.put(sName,sBefore,sAfter);
+ listItemMap.put(sName, attr);
+ }
+ else if ("text".equals(sFamily)) {
+ if (elm.hasAttribute("verbatim")) { attr.put("verbatim", elm.getAttribute("verbatim")); }
+ textMap.put(sName, attr);
}
else if ("text-attribute".equals(sFamily)) {
- textAttr.put(sName, sBefore, sAfter);
+ textAttrMap.put(sName, attr);
}
}
- else if (elm.getTagName().equals("heading-map")) {
- readHeadingMap(elm);
- }
else if (elm.getTagName().equals("string-replace")) {
- // TODO: ConfigBase should handle this
String sInput = elm.getAttribute("input");
Map attributes = new HashMap();
attributes.put("latex-code", elm.getAttribute("latex-code"));
attributes.put("fontenc", elm.getAttribute("fontenc"));
stringReplace.put(sInput,attributes);
}
+ else if (elm.getTagName().equals("math-symbol-map")) {
+ String sName = elm.getAttribute("name");
+ Map attr = new HashMap();
+ attr.put("latex", elm.getAttribute("latex"));
+ mathSymbols.put(sName, attr);
+ }
else if (elm.getTagName().equals("custom-preamble")) {
StringBuffer buf = new StringBuffer();
Node child = elm.getFirstChild();
@@ -396,61 +469,36 @@ public class LaTeXConfig extends writer2latex.base.ConfigBase {
}
sCustomPreamble = buf.toString();
}
- else if (elm.getTagName().equals("math-symbol-map")) {
- String sName = elm.getAttribute("name");
- Map attr = new HashMap();
- attr.put("latex", elm.getAttribute("latex"));
- mathSymbols.put(sName, attr);
- }
}
- public void readHeadingMap(Element node) {
- int nMaxLevel = Misc.getPosInteger(node.getAttribute("max-level"),0);
- headingMap.reset(nMaxLevel);
- Node child = node.getFirstChild();
- while (child!=null) {
- if (child.getNodeType()==Node.ELEMENT_NODE) {
- Element elm = (Element) child;
- if (elm.getTagName().equals("heading-level-map")) {
- int nWriterLevel = Misc.getPosInteger(elm.getAttribute("writer-level"),1);
- String sName = elm.getAttribute("name");
- int nLevel = Misc.getPosInteger(elm.getAttribute("level"),0);
- headingMap.setLevelData(nWriterLevel,sName,nLevel);
- }
- }
- child = child.getNextSibling();
- }
- }
-
protected void writeInner(Document dom) {
- // Write math symbol map
- for (String sName : mathSymbols.keySet()) {
- String sLatex = mathSymbols.get(sName).get("latex");
- Element msNode = dom.createElement("math-symbol-map");
- msNode.setAttribute("name",sName);
- msNode.setAttribute("latex",sLatex);
- dom.getDocumentElement().appendChild(msNode);
- }
-
- writeStyleMap(dom,par,"paragraph");
- writeStyleMap(dom,parBlock,"paragraph-block");
- writeStyleMap(dom,text,"text");
- writeStyleMap(dom,list,"list");
- writeStyleMap(dom,listItem,"listitem");
- writeStyleMap(dom,textAttr,"text-attribute");
-
+ // Write heading map
+ int nMaxLevel = 0;
+ while (nMaxLevel<10 && headingMap.get(Integer.toString(nMaxLevel+1))!=null) { nMaxLevel++; }
+
Element hmNode = dom.createElement("heading-map");
- hmNode.setAttribute("max-level",Integer.toString(headingMap.getMaxLevel()));
+ // This attribute is not used anymore, but we keep it for backwards compatibility
+ hmNode.setAttribute("max-level",Integer.toString(nMaxLevel));
dom.getDocumentElement().appendChild(hmNode);
- for (int i=1; i<=headingMap.getMaxLevel(); i++) {
+ for (int i=1; i<=nMaxLevel; i++) {
Element hlmNode = dom.createElement("heading-level-map");
- hlmNode.setAttribute("writer-level",Integer.toString(i));
- hlmNode.setAttribute("name",headingMap.getName(i));
- hlmNode.setAttribute("level",Integer.toString(headingMap.getLevel(i)));
+ String sWriterLevel = Integer.toString(i);
+ hlmNode.setAttribute("writer-level",sWriterLevel);
+ Map attr = headingMap.get(sWriterLevel);
+ hlmNode.setAttribute("name",attr.get("name"));
+ hlmNode.setAttribute("level",attr.get("level"));
hmNode.appendChild(hlmNode);
}
- // TODO: ConfigBase should handle this
+ // Write style maps
+ writeStyleMap(dom,parMap,"paragraph");
+ writeStyleMap(dom,parBlockMap,"paragraph-block");
+ writeStyleMap(dom,listMap,"list");
+ writeStyleMap(dom,listItemMap,"listitem");
+ writeStyleMap(dom,textMap,"text");
+ writeStyleMap(dom,textAttrMap,"text-attribute");
+
+ // Write string replace
Set inputStrings = stringReplace.keySet();
for (String sInput : inputStrings) {
Map attributes = stringReplace.get(sInput);
@@ -461,34 +509,82 @@ public class LaTeXConfig extends writer2latex.base.ConfigBase {
dom.getDocumentElement().appendChild(srNode);
}
- Element cp = dom.createElement("custom-preamble");
+ // Write math symbol map
+ for (String sName : mathSymbols.keySet()) {
+ String sLatex = mathSymbols.get(sName).get("latex");
+ Element msNode = dom.createElement("math-symbol-map");
+ msNode.setAttribute("name",sName);
+ msNode.setAttribute("latex",sLatex);
+ dom.getDocumentElement().appendChild(msNode);
+ }
+
+ // Write custom preamble
+ Element cp = dom.createElement("custom-preamble");
cp.appendChild(dom.createTextNode( sCustomPreamble));
dom.getDocumentElement().appendChild(cp);
}
- private void writeStyleMap(Document dom, StyleMap sm, String sFamily) {
- Enumeration smEnum = sm.getNames();
- while (smEnum.hasMoreElements()) {
- String sName = smEnum.nextElement();
+ private void writeStyleMap(Document dom, ComplexOption co, String sFamily) {
+ for (String sName : co.keySet()) {
+ Map attr = co.get(sName);
Element smNode = dom.createElement("style-map");
smNode.setAttribute("name",sName);
smNode.setAttribute("family",sFamily);
- smNode.setAttribute("before",sm.getBefore(sName));
- smNode.setAttribute("after",sm.getAfter(sName));
- if (sm.getNext(sName)!=null) {
- smNode.setAttribute("next",sm.getNext(sName));
+ smNode.setAttribute("before",attr.containsKey("before") ? attr.get("before") : "");
+ smNode.setAttribute("after",attr.containsKey("after") ? attr.get("after") : "");
+ if (attr.containsKey("next")) {
+ smNode.setAttribute("next",attr.get("next"));
}
- if (!sm.getLineBreak(sName)) {
- smNode.setAttribute("line-break","false");
+ if (attr.containsKey("line-break")) {
+ smNode.setAttribute("line-break",attr.get("line-break"));
}
- if (sm.getVerbatim(sName)) {
- smNode.setAttribute("verbatim","true");
+ if (attr.containsKey("verbatim")) {
+ smNode.setAttribute("verbatim",attr.get("verbatim"));
}
dom.getDocumentElement().appendChild(smNode);
}
}
- // Convenience accessor methods
+ /////////////////////////////////////////////////////////////////////////
+ // VII. Convenience accessor methods
+
+ public HeadingMap getHeadingMap() {
+ int nMaxLevel = 0;
+ while (nMaxLevel<10 && headingMap.get(Integer.toString(nMaxLevel+1))!=null) { nMaxLevel++; }
+
+ HeadingMap map = new HeadingMap(nMaxLevel);
+ for (int i=1; i<=nMaxLevel; i++) {
+ String sWriterLevel = Integer.toString(i);
+ Map attr = headingMap.get(sWriterLevel);
+ String sName = attr.get("name");
+ int nLevel = Misc.getPosInteger(attr.get("level"),0);
+ map.setLevelData(i, sName, nLevel);
+ }
+ return map;
+ }
+
+ // Get style maps
+ public StyleMap getParStyleMap() { return getStyleMap(parMap); }
+ public StyleMap getParBlockStyleMap() { return getStyleMap(parBlockMap); }
+ public StyleMap getListStyleMap() { return getStyleMap(listMap); }
+ public StyleMap getListItemStyleMap() { return getStyleMap(listItemMap); }
+ public StyleMap getTextAttributeStyleMap() { return getStyleMap(textAttrMap); }
+ public StyleMap getTextStyleMap() { return getStyleMap(textMap); }
+
+ private StyleMap getStyleMap(ComplexOption co) {
+ StyleMap map = new StyleMap();
+ for (String sName : co.keySet()) {
+ Map attr = co.get(sName);
+ String sBefore = attr.containsKey("before") ? attr.get("before") : "";
+ String sAfter = attr.containsKey("after") ? attr.get("after") : "";
+ String sNext = attr.containsKey("next") ? attr.get("next") : "";
+ boolean bLineBreak = !"false".equals(attr.get("line-break"));
+ boolean bVerbatim = "true".equals(attr.get("verbatim"));
+ map.put(sName, sBefore, sAfter, sNext, bLineBreak, bVerbatim);
+ }
+ return map;
+ }
+
// Return current string replace as a trie
public ReplacementTrie getStringReplace() {
@@ -503,6 +599,17 @@ public class LaTeXConfig extends writer2latex.base.ConfigBase {
return trie;
}
+ // Get the math symbols as a simple Map
+ public Map getMathSymbols() {
+ Map map = new HashMap();
+ for (String sName : mathSymbols.keySet()) {
+ String sLatex = mathSymbols.get(sName).get("latex");
+ map.put(sName, sLatex);
+ }
+ return map;
+ }
+
+ // Get the custom preamble
public String getCustomPreamble() { return sCustomPreamble; }
// Common options
@@ -589,22 +696,5 @@ public class LaTeXConfig extends writer2latex.base.ConfigBase {
public boolean splitToplevelSections() { return ((BooleanOption) options[SPLIT_TOPLEVEL_SECTIONS]).getValue(); }
public boolean saveImagesInSubdir() { return ((BooleanOption) options[SAVE_IMAGES_IN_SUBDIR]).getValue(); }
- public Map getMathSymbols() {
- Map map = new HashMap();
- for (String sName : mathSymbols.keySet()) {
- String sLatex = mathSymbols.get(sName).get("latex");
- map.put(sName, sLatex);
- }
- return map;
- }
-
- public StyleMap getParStyleMap() { return par; }
- public StyleMap getParBlockStyleMap() { return parBlock; }
- public StyleMap getTextStyleMap() { return text; }
- public StyleMap getListStyleMap() { return list; }
- public StyleMap getListItemStyleMap() { return listItem; }
- public StyleMap getTextAttributeStyleMap() { return textAttr; }
- public HeadingMap getHeadingMap() { return headingMap; }
-
}
diff --git a/source/java/writer2latex/latex/util/StyleMap.java b/source/java/writer2latex/latex/util/StyleMap.java
index eae5aac..beff59d 100644
--- a/source/java/writer2latex/latex/util/StyleMap.java
+++ b/source/java/writer2latex/latex/util/StyleMap.java
@@ -16,11 +16,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
- * Copyright: 2002-2007 by Henrik Just
+ * Copyright: 2002-2009 by Henrik Just
*
* All Rights Reserved.
*
- * Version 1.0 (2007-07-30)
+ * Version 1.2 (2009-09-28)
*
*/
@@ -32,6 +32,16 @@ import java.util.Enumeration;
public class StyleMap {
private Hashtable items = new Hashtable();
+ public void put(String sName, String sBefore, String sAfter, String sNext, boolean bLineBreak, boolean bVerbatim) {
+ StyleMapItem item = new StyleMapItem();
+ item.sBefore = sBefore;
+ item.sAfter = sAfter;
+ item.sNext = ";"+sNext+";";
+ item.bLineBreak = bLineBreak;
+ item.bVerbatim = bVerbatim;
+ items.put(sName,item);
+ }
+
public void put(String sName, String sBefore, String sAfter, boolean bLineBreak, boolean bVerbatim) {
StyleMapItem item = new StyleMapItem();
item.sBefore = sBefore;
diff --git a/source/oxt/writer2latex/W2LDialogs2/Formatting.xdl b/source/oxt/writer2latex/W2LDialogs2/Formatting.xdl
index d3406dc..ddc8766 100644
--- a/source/oxt/writer2latex/W2LDialogs2/Formatting.xdl
+++ b/source/oxt/writer2latex/W2LDialogs2/Formatting.xdl
@@ -24,5 +24,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/source/oxt/writer2latex/W2LDialogs2/Styles.xdl b/source/oxt/writer2latex/W2LDialogs2/Styles.xdl
index 063a244..a983710 100644
--- a/source/oxt/writer2latex/W2LDialogs2/Styles.xdl
+++ b/source/oxt/writer2latex/W2LDialogs2/Styles.xdl
@@ -3,34 +3,33 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
\ No newline at end of file