Quantcast

[Jlatexmath] Automatic Linebreaks

classic Classic list List threaded Threaded
7 messages Options
Felix Natter Felix Natter
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[Jlatexmath] Automatic Linebreaks

hi,

we (freeplane.sourceforge.net) are using JLaTeXMath to render contents
of (special) mindmap nodes, thanks for the excellent software!

We would like to implement automatic linebreaking ("folding"), but
we ran across two issues (sample source code attached).

1. ExampleSplitHBox.java: "interline" [spacing] seems to work for the
first line only:

- String latex = "aaaaaaa\\-bbbbbbb\\-cccccccc";
=>
aaaaaaa


bbbbbbb
ccccccc

2. ExampleSplitVBox.java: Splitting does not work on VBoxes:
- String latex = "aaaa\\\\aaa\\-bbbbbbb\\-cccccccc";
=>
aaaa
aaabbbbbbbcccccccc

=> results in this VBox:
| aaaa              |
--------------------
|bbbbbbbb\\-cccccccc|
and BreakFormula.split() only works on HBoxes!

We tried to fix #2 by refactoring and adding BreakFormula.split() for
VBoxes:
---------------------------------------------
public static Box split(Box box, float width, float interline) {
        if (box instanceof HorizontalBox) {
         HorizontalBox hbox = (HorizontalBox) box;
         return split(hbox, width, interline);
        }
        else if (box instanceof VerticalBox) {
         VerticalBox vbox = (VerticalBox) box;
         return split(vbox, width, interline);
        }
        else {
            return box;
        }

    }

 private static Box split(HorizontalBox hbox, float width, float interline) {
  VerticalBox vbox = new VerticalBox();
        HorizontalBox first;
        HorizontalBox second = null;
        Stack<Position> positions = new Stack<Position>();

        while (hbox.width > width && canBreak(positions, hbox, width) != hbox.width) {
            Position pos = positions.pop();
            HorizontalBox[] hboxes = pos.hbox.split(pos.index - 1);
            first = hboxes[0];
            second = hboxes[1];
            while (!positions.isEmpty()) {
                pos = positions.pop();
                hboxes = pos.hbox.splitRemove(pos.index);
                hboxes[0].add(first);
                hboxes[1].add(0, second);
                first = hboxes[0];
                second = hboxes[1];
            }
            vbox.add(first, interline);
            hbox = second;
        }

        if (second != null) {
            vbox.add(second, interline);
            return vbox;
        }

        return hbox;
 }

 private static Box split(VerticalBox vbox, float width, float interline) {
  VerticalBox newBox = new VerticalBox();
  for(Box box:vbox.children){
   newBox.add(split(box, width, interline));
  }
  return newBox;
 
 }
=> why does this not work?
---------------------------------------------

Can you help us fix #1 and #2?

Once this is fixed, we plan to insert a BreakMarkAtom not only for
TeXParser.ESCAPE (in parse()) but also for whitespace. (Our debugging
shows that BreakMarkAtom is inserted for "\-").
Is that a good direction?

Thanks!
--
Felix Natter

/* Example1.java
 * =========================================================================
 * This file is part of the JLaTeXMath Library - http://jlatexmath.sourceforge.net
 *
 * Copyright (C) 2009 DENIZET Calixte
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * A copy of the GNU General Public License can be found in the file
 * LICENSE.txt provided with the source distribution of this program (see
 * the META-INF directory in the source jar). This license can also be
 * found on the GNU website at http://www.gnu.org/licenses/gpl.html.
 *
 * If you did not receive a copy of the GNU General Public License along
 * with this program, contact the lead developer, or write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 *
 */

import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.JLabel;

import org.scilab.forge.jlatexmath.TeXConstants;
import org.scilab.forge.jlatexmath.TeXFormula;
import org.scilab.forge.jlatexmath.TeXIcon;

/**
 * A class to test LaTeX rendering.
 **/
public class ExampleSplitHBox {
    public static void main(String[] args) {
       
    String latex = "aaaaaaa\\-bbbbbbb\\-cccccccc";
       
        TeXFormula formula = new TeXFormula(latex);
// TeXIcon icon = formula.createTeXIcon(TeXConstants.STYLE_DISPLAY, 20);
// TeXIcon icon = formula.createTeXIcon(TeXConstants.STYLE_DISPLAY, 20, TeXConstants.UNIT_PIXEL, 8f, TeXConstants.ALIGN_LEFT);
        TeXIcon icon = formula.createTeXIcon(TeXConstants.STYLE_DISPLAY, 20, TeXConstants.UNIT_PIXEL, 48f,
                        TeXConstants.ALIGN_LEFT,
                        TeXConstants.UNIT_PIXEL, 48f);
        icon.setInsets(new Insets(5, 5, 5, 5));
       
        BufferedImage image = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = image.createGraphics();
        g2.setColor(Color.white);
        g2.fillRect(0,0,icon.getIconWidth(),icon.getIconHeight());
        JLabel jl = new JLabel();
        jl.setForeground(new Color(0, 0, 0));
        icon.paintIcon(jl, g2, 0, 0);
        File file = new File("ExampleSplitHBox.png");
        try {
            ImageIO.write(image, "png", file.getAbsoluteFile());
        } catch (IOException ex) { }
    }    
}
/* Example1.java
 * =========================================================================
 * This file is part of the JLaTeXMath Library - http://jlatexmath.sourceforge.net
 *
 * Copyright (C) 2009 DENIZET Calixte
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * A copy of the GNU General Public License can be found in the file
 * LICENSE.txt provided with the source distribution of this program (see
 * the META-INF directory in the source jar). This license can also be
 * found on the GNU website at http://www.gnu.org/licenses/gpl.html.
 *
 * If you did not receive a copy of the GNU General Public License along
 * with this program, contact the lead developer, or write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 *
 */

import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.JLabel;

import org.scilab.forge.jlatexmath.TeXConstants;
import org.scilab.forge.jlatexmath.TeXFormula;
import org.scilab.forge.jlatexmath.TeXIcon;

/**
 * A class to test LaTeX rendering.
 **/
public class ExampleSplitVBox {
    public static void main(String[] args) {
       
    String latex = "aaaa\\\\aaa\\-bbbbbbb\\-cccccccc";
       
        TeXFormula formula = new TeXFormula(latex);
// TeXIcon icon = formula.createTeXIcon(TeXConstants.STYLE_DISPLAY, 20);
// TeXIcon icon = formula.createTeXIcon(TeXConstants.STYLE_DISPLAY, 20, TeXConstants.UNIT_PIXEL, 8f, TeXConstants.ALIGN_LEFT);
        TeXIcon icon = formula.createTeXIcon(TeXConstants.STYLE_DISPLAY, 20, TeXConstants.UNIT_PIXEL, 8f,
                        TeXConstants.ALIGN_LEFT,
                        TeXConstants.UNIT_PIXEL, 48f);
        icon.setInsets(new Insets(5, 5, 5, 5));
       
        BufferedImage image = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = image.createGraphics();
        g2.setColor(Color.white);
        g2.fillRect(0,0,icon.getIconWidth(),icon.getIconHeight());
        JLabel jl = new JLabel();
        jl.setForeground(new Color(0, 0, 0));
        icon.paintIcon(jl, g2, 0, 0);
        File file = new File("ExampleSplitVBox.png");
        try {
            ImageIO.write(image, "png", file.getAbsoluteFile());
        } catch (IOException ex) { }
    }    
}
_______________________________________________
jlatexmath mailing list
[hidden email]
http://lists.scilab.org/mailman/listinfo/jlatexmath
Calixte DENIZET Calixte DENIZET
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [Jlatexmath] Automatic Linebreaks

Hi Felix,

I fixed the two issues in this commit
http://forge.scilab.org/index.php/p/jlatexmath/source/commit/49dc08e201494992732671fe0859fa735bd7473d/

I added your code to handle verticalbox.

Thanks

Best regards

Calixte

On 06/10/2012 21:10, Felix Natter wrote:
hi,

we (freeplane.sourceforge.net) are using JLaTeXMath to render contents
of (special) mindmap nodes, thanks for the excellent software!

We would like to implement automatic linebreaking ("folding"), but
we ran across two issues (sample source code attached).

1. ExampleSplitHBox.java: "interline" [spacing] seems to work for the
first line only:

- String latex = "aaaaaaa\\-bbbbbbb\\-cccccccc";
=>
aaaaaaa


bbbbbbb
ccccccc

2. ExampleSplitVBox.java: Splitting does not work on VBoxes:
- String latex = "aaaa\\\\aaa\\-bbbbbbb\\-cccccccc";
=>
aaaa
aaabbbbbbbcccccccc

=> results in this VBox:
| aaaa              |
--------------------
|bbbbbbbb\\-cccccccc|
and BreakFormula.split() only works on HBoxes!

We tried to fix #2 by refactoring and adding BreakFormula.split() for
VBoxes:
---------------------------------------------
public static Box split(Box box, float width, float interline) {
        if (box instanceof HorizontalBox) {
         HorizontalBox hbox = (HorizontalBox) box;
         return split(hbox, width, interline);
        }
        else if (box instanceof VerticalBox) {
         VerticalBox vbox = (VerticalBox) box;
         return split(vbox, width, interline);
        }
        else {
            return box;
        }

    }

 private static Box split(HorizontalBox hbox, float width, float interline) {
  VerticalBox vbox = new VerticalBox();
        HorizontalBox first;
        HorizontalBox second = null;
        Stack<Position> positions = new Stack<Position>();

        while (hbox.width > width && canBreak(positions, hbox, width) != hbox.width) {
            Position pos = positions.pop();
            HorizontalBox[] hboxes = pos.hbox.split(pos.index - 1);
            first = hboxes[0];
            second = hboxes[1];
            while (!positions.isEmpty()) {
                pos = positions.pop();
                hboxes = pos.hbox.splitRemove(pos.index);
                hboxes[0].add(first);
                hboxes[1].add(0, second);
                first = hboxes[0];
                second = hboxes[1];
            }
            vbox.add(first, interline);
            hbox = second;
        }

        if (second != null) {
            vbox.add(second, interline);
            return vbox;
        }

        return hbox;
 }

 private static Box split(VerticalBox vbox, float width, float interline) {
  VerticalBox newBox = new VerticalBox();
  for(Box box:vbox.children){
   newBox.add(split(box, width, interline));
  }
  return newBox;
  
 }
=> why does this not work?
---------------------------------------------

Can you help us fix #1 and #2?

Once this is fixed, we plan to insert a BreakMarkAtom not only for
TeXParser.ESCAPE (in parse()) but also for whitespace. (Our debugging
shows that BreakMarkAtom is inserted for "\-").
Is that a good direction?

Thanks!


_______________________________________________
jlatexmath mailing list
[hidden email]
http://lists.scilab.org/mailman/listinfo/jlatexmath


-- 
Calixte Denizet
Software Development Engineer
-----------------------------------------------------------
Scilab Enterprises
143bis rue Yves Le Coz - 78000 Versailles, France
http://www.scilab-enterprises.com

_______________________________________________
jlatexmath mailing list
[hidden email]
http://lists.scilab.org/mailman/listinfo/jlatexmath
Calixte DENIZET Calixte DENIZET
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [Jlatexmath] Automatic Linebreaks

In reply to this post by Felix Natter
I added automatically a break mark just after a whitespace in text mode:
http://forge.scilab.org/index.php/p/jlatexmath/source/commit/cec79e637bb08f9066e3548ef2dc3025c2c67d1a/

Is it good for you ?

C

On 06/10/2012 21:10, Felix Natter wrote:
hi,

we (freeplane.sourceforge.net) are using JLaTeXMath to render contents
of (special) mindmap nodes, thanks for the excellent software!

We would like to implement automatic linebreaking ("folding"), but
we ran across two issues (sample source code attached).

1. ExampleSplitHBox.java: "interline" [spacing] seems to work for the
first line only:

- String latex = "aaaaaaa\\-bbbbbbb\\-cccccccc";
=>
aaaaaaa


bbbbbbb
ccccccc

2. ExampleSplitVBox.java: Splitting does not work on VBoxes:
- String latex = "aaaa\\\\aaa\\-bbbbbbb\\-cccccccc";
=>
aaaa
aaabbbbbbbcccccccc

=> results in this VBox:
| aaaa              |
--------------------
|bbbbbbbb\\-cccccccc|
and BreakFormula.split() only works on HBoxes!

We tried to fix #2 by refactoring and adding BreakFormula.split() for
VBoxes:
---------------------------------------------
public static Box split(Box box, float width, float interline) {
        if (box instanceof HorizontalBox) {
         HorizontalBox hbox = (HorizontalBox) box;
         return split(hbox, width, interline);
        }
        else if (box instanceof VerticalBox) {
         VerticalBox vbox = (VerticalBox) box;
         return split(vbox, width, interline);
        }
        else {
            return box;
        }

    }

 private static Box split(HorizontalBox hbox, float width, float interline) {
  VerticalBox vbox = new VerticalBox();
        HorizontalBox first;
        HorizontalBox second = null;
        Stack<Position> positions = new Stack<Position>();

        while (hbox.width > width && canBreak(positions, hbox, width) != hbox.width) {
            Position pos = positions.pop();
            HorizontalBox[] hboxes = pos.hbox.split(pos.index - 1);
            first = hboxes[0];
            second = hboxes[1];
            while (!positions.isEmpty()) {
                pos = positions.pop();
                hboxes = pos.hbox.splitRemove(pos.index);
                hboxes[0].add(first);
                hboxes[1].add(0, second);
                first = hboxes[0];
                second = hboxes[1];
            }
            vbox.add(first, interline);
            hbox = second;
        }

        if (second != null) {
            vbox.add(second, interline);
            return vbox;
        }

        return hbox;
 }

 private static Box split(VerticalBox vbox, float width, float interline) {
  VerticalBox newBox = new VerticalBox();
  for(Box box:vbox.children){
   newBox.add(split(box, width, interline));
  }
  return newBox;
  
 }
=> why does this not work?
---------------------------------------------

Can you help us fix #1 and #2?

Once this is fixed, we plan to insert a BreakMarkAtom not only for
TeXParser.ESCAPE (in parse()) but also for whitespace. (Our debugging
shows that BreakMarkAtom is inserted for "\-").
Is that a good direction?

Thanks!


_______________________________________________
jlatexmath mailing list
[hidden email]
http://lists.scilab.org/mailman/listinfo/jlatexmath


-- 
Calixte Denizet
Software Development Engineer
-----------------------------------------------------------
Scilab Enterprises
143bis rue Yves Le Coz - 78000 Versailles, France
http://www.scilab-enterprises.com

_______________________________________________
jlatexmath mailing list
[hidden email]
http://lists.scilab.org/mailman/listinfo/jlatexmath
Felix Natter Felix Natter
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [Jlatexmath] Automatic Linebreaks

Calixte Denizet <[hidden email]> writes:

hello Calixte,

> I added automatically a break mark just after a whitespace in text mode:
> http://forge.scilab.org/index.php/p/jlatexmath/source/commit/cec79e637bb08f9066e3548ef2dc3025c2c67d1a/
>
> Is it good for you ?

thanks a lot for fixing these issues!

I have one change for this (requires \mbox handling changes, see below):

                case ' ' :
                    pos++;
                    if (!isInMbox()) // we're not in an \mbox{...}
                    {
                    formula.add(new BreakMarkAtom());
                    }
                    if (!ignoresWhiteSpace()) {// spaces are significant
                    [...]

=> With this change, it is possible to break at non-significant
whitespace, e.g. in "$x_1=1, x_2=2, x_3=3...$".
                   
Also, there is one problem left to be addressed: linebreaks are not
allowed in \mbox{...}. I have attached a patch, but this definitely
needs review and changes.

- The idea is that TeXParser remembers -- as is already done for "ignore
  whitespace" -- whether the parser is in an \mbox{...}. In order to
  group this context information, a new class TeXParserContext was
  introduced with nice OO feel (immutable, e.g. context.inMbox() creates
  a new context with inMbox=true and the current setting for "Ignore WS").

- the context is fed into a TeXParser instance by a new TeXFormula
  constructor

- Often the default context (ignoreWS=true, inMbox=false) is assumed,
  not sure whether this is correct.

- The context is passed to subformulas (and to CharAtom /
  CumulativeScriptsAtom, see below) and evaluated in ch == ' '.

- MatrixAtom creates a TeXParser object. We assume that since the parser
  is used for matrix cells(?), the default context shall be used.

- Concerning PredefMacros.java: We assume that:

  - mbox_macro should start with mbox-context (ignoreWS=false,
    inMbox=true)

  - text_macro should start with text context (ignoreWS=false,
    inMbox=false)

  - intertext_macro should start with text context

  - bf/tt/sf/it/rm_macro: should inherit context of tp (first arg)

  - changes for CharAtom/CumulativeScriptsAtom may not be necessary (see
    below)

  - size_macro: should inherit context of tp (first arg)

  - in all other macros, the default context should be used

- In RowAtom.createBox() there is logic for allowing to break before
  numerals. In order to forbid this in an \mbox{...}, changes to
  CharAtom and CumulativeScriptsAtom were needed (idea: the
  CharAtom-ctor should know whether it's allowed to be break before its
  char). Is this still necessary now that we can break at
  non-significant whitespace (see above)?

Please tell me if you want a different patch format and/or how we can
fix things.

Thanks and Best Regards,
--
Felix Natter

diff --git a/src/org/scilab/forge/jlatexmath/CharAtom.java b/src/org/scilab/forge/jlatexmath/CharAtom.java
index 440b9d6..6142542 100644
--- a/src/org/scilab/forge/jlatexmath/CharAtom.java
+++ b/src/org/scilab/forge/jlatexmath/CharAtom.java
@@ -40,6 +40,8 @@ public class CharAtom extends CharSymbol {
     
     // text style (null means the default text style)
     private String textStyle;
+    
+    private final boolean inMbox;
 
     /**
      * Creates a CharAtom that will represent the given character in the given text style.
@@ -48,9 +50,10 @@ public class CharAtom extends CharSymbol {
      * @param c the alphanumeric character
      * @param textStyle the text style in which the character should be drawn
      */
-    public CharAtom(char c, String textStyle) {
- this.c = c;
- this.textStyle = textStyle;
+    public CharAtom(char c, String textStyle, final boolean inMbox) {
+     this.c = c;
+     this.textStyle = textStyle;
+     this.inMbox = inMbox;
     }
 
     public Box createBox(TeXEnvironment env) {
@@ -95,4 +98,9 @@ public class CharAtom extends CharSymbol {
     public CharFont getCharFont(TeXFont tf) {
  return getChar(tf, TeXConstants.STYLE_DISPLAY, false).getCharFont();
     }
+    
+    public boolean canBreakBefore()
+    {
+     return !inMbox && Character.isDigit(getCharacter());
+    }
 }
diff --git a/src/org/scilab/forge/jlatexmath/CumulativeScriptsAtom.java b/src/org/scilab/forge/jlatexmath/CumulativeScriptsAtom.java
index ae9690d..3720423 100644
--- a/src/org/scilab/forge/jlatexmath/CumulativeScriptsAtom.java
+++ b/src/org/scilab/forge/jlatexmath/CumulativeScriptsAtom.java
@@ -37,7 +37,7 @@ public class CumulativeScriptsAtom extends Atom {
     private RowAtom sup;
     private RowAtom sub;
 
-    public CumulativeScriptsAtom(Atom base, Atom sub, Atom sup) {
+    public CumulativeScriptsAtom(Atom base, Atom sub, Atom sup, final boolean inMbox) {
  super();
  if (base instanceof CumulativeScriptsAtom) {
     CumulativeScriptsAtom at = (CumulativeScriptsAtom) base;
@@ -48,7 +48,7 @@ public class CumulativeScriptsAtom extends Atom {
     this.sub = at.sub;
  } else {
     if (base == null) {
- this.base = new PhantomAtom(new CharAtom('M', "mathnormal"), false, true, true);
+ this.base = new PhantomAtom(new CharAtom('M', "mathnormal", inMbox), false, true, true);
     } else {
  this.base = base;
     }
diff --git a/src/org/scilab/forge/jlatexmath/MatrixAtom.java b/src/org/scilab/forge/jlatexmath/MatrixAtom.java
index 99d03cf..bfe053d 100644
--- a/src/org/scilab/forge/jlatexmath/MatrixAtom.java
+++ b/src/org/scilab/forge/jlatexmath/MatrixAtom.java
@@ -163,7 +163,7 @@ public class MatrixAtom extends Atom {
             case '@' :
                 pos++;
                 tf = new TeXFormula();
-                tp = new TeXParser(isPartial, opt.substring(pos), tf, false);
+                tp = new TeXParser(isPartial, opt.substring(pos), tf, false, TeXParserContext.createDefaultParserContext());
                 Atom at = tp.getArgument();
                 matrix.col++;
                 for (int j = 0; j < matrix.row; j++) {
@@ -177,7 +177,7 @@ public class MatrixAtom extends Atom {
             case '*' :
                 pos++;
                 tf = new TeXFormula();
-                tp = new TeXParser(isPartial, opt.substring(pos), tf, false);
+                tp = new TeXParser(isPartial, opt.substring(pos), tf, false, TeXParserContext.createDefaultParserContext());
                 String[] args = tp.getOptsArgs(2, 0);
                 pos += tp.getPos();
                 int nrep =  Integer.parseInt(args[1]);
diff --git a/src/org/scilab/forge/jlatexmath/PredefMacros.java b/src/org/scilab/forge/jlatexmath/PredefMacros.java
index 7f8cf9d..94cdf33 100644
--- a/src/org/scilab/forge/jlatexmath/PredefMacros.java
+++ b/src/org/scilab/forge/jlatexmath/PredefMacros.java
@@ -417,12 +417,12 @@ public class PredefMacros {
     }
 
     public static final Atom mbox_macro(final TeXParser tp, final String[] args) throws ParseException {
-        Atom group = new RomanAtom(new TeXFormula(tp, args[1], "mathnormal", false, false).root);
+        Atom group = new RomanAtom(new TeXFormula(tp, args[1], "mathnormal", false, TeXParserContext.createMboxParserContext()).root);
         return new StyleAtom(TeXConstants.STYLE_TEXT, group);
     }
 
     public static final Atom text_macro(final TeXParser tp, final String[] args) throws ParseException {
-        return new RomanAtom(new TeXFormula(tp, args[1], "mathnormal", false, false).root);
+        return new RomanAtom(new TeXFormula(tp, args[1], "mathnormal", false, TeXParserContext.createTextParserContext()).root);
     }
 
     public static final Atom underscore_macro(final TeXParser tp, final String[] args) throws ParseException {
@@ -735,7 +735,7 @@ public class PredefMacros {
 
         String str = args[1].replaceAll("\\^\\{\\\\prime\\}", "\'");
         str = str.replaceAll("\\^\\{\\\\prime\\\\prime\\}", "\'\'");
-        Atom at = new RomanAtom(new TeXFormula(tp, str, "mathnormal", false, false).root);
+        Atom at = new RomanAtom(new TeXFormula(tp, str, "mathnormal", false, TeXParserContext.createTextParserContext()).root);
         at.type = TeXConstants.TYPE_INTERTEXT;
         tp.addAtom(at);
         tp.addRow();
@@ -1009,7 +1009,7 @@ public class PredefMacros {
     }
 
     public static final Atom rm_macro(final TeXParser tp, final String[] args) throws ParseException {
-        return new RomanAtom(new TeXFormula(tp, tp.getOverArgument(), null, false, tp.isIgnoreWhiteSpace()).root);
+        return new RomanAtom(new TeXFormula(tp, tp.getOverArgument(), null, false, tp.getContext().copy()).root);
     }
 
     public static final Atom mathbf_macro(final TeXParser tp, final String[] args) throws ParseException {
@@ -1017,7 +1017,7 @@ public class PredefMacros {
     }
 
     public static final Atom bf_macro(final TeXParser tp, final String[] args) throws ParseException {
-        return new BoldAtom(new RomanAtom(new TeXFormula(tp, tp.getOverArgument(), null, false, tp.isIgnoreWhiteSpace()).root));
+        return new BoldAtom(new RomanAtom(new TeXFormula(tp, tp.getOverArgument(), null, false, tp.getContext().copy()).root));
     }
 
     public static final Atom mathtt_macro(final TeXParser tp, final String[] args) throws ParseException {
@@ -1025,7 +1025,7 @@ public class PredefMacros {
     }
 
     public static final Atom tt_macro(final TeXParser tp, final String[] args) throws ParseException {
-        return new TtAtom(new TeXFormula(tp, tp.getOverArgument(), null, false, tp.isIgnoreWhiteSpace()).root);
+        return new TtAtom(new TeXFormula(tp, tp.getOverArgument(), null, false, tp.getContext().copy()).root);
     }
 
     public static final Atom mathit_macro(final TeXParser tp, final String[] args) throws ParseException {
@@ -1033,7 +1033,7 @@ public class PredefMacros {
     }
 
     public static final Atom it_macro(final TeXParser tp, final String[] args) throws ParseException {
-        return new ItAtom(new TeXFormula(tp, tp.getOverArgument(), null, false, tp.isIgnoreWhiteSpace()).root);
+        return new ItAtom(new TeXFormula(tp, tp.getOverArgument(), null, false, tp.getContext().copy()).root);
     }
 
     public static final Atom mathsf_macro(final TeXParser tp, final String[] args) throws ParseException {
@@ -1041,7 +1041,7 @@ public class PredefMacros {
     }
 
     public static final Atom sf_macro(final TeXParser tp, final String[] args) throws ParseException {
-        return new SsAtom(new TeXFormula(tp, tp.getOverArgument(), null, false, tp.isIgnoreWhiteSpace()).root);
+        return new SsAtom(new TeXFormula(tp, tp.getOverArgument(), null, false, tp.getContext().copy()).root);
     }
 
     public static final Atom LaTeX_macro(final TeXParser tp, final String[] args) throws ParseException {
@@ -1384,15 +1384,15 @@ public class PredefMacros {
             f = 2.5f;
         }
 
-        return new MonoScaleAtom(new TeXFormula(tp, tp.getOverArgument(), null, false, tp.isIgnoreWhiteSpace()).root, f);
+        return new MonoScaleAtom(new TeXFormula(tp, tp.getOverArgument(), null, false, tp.getContext().copy()).root, f);
     }
 
     public static final Atom jlatexmathcumsup_macro(final TeXParser tp, final String[] args) throws ParseException {
-        return new CumulativeScriptsAtom(tp.getLastAtom(), null, new TeXFormula(tp, args[1]).root);
+        return new CumulativeScriptsAtom(tp.getLastAtom(), null, new TeXFormula(tp, args[1]).root, tp.getContext().isInMbox());
     }
 
     public static final Atom jlatexmathcumsub_macro(final TeXParser tp, final String[] args) throws ParseException {
-        return new CumulativeScriptsAtom(tp.getLastAtom(), new TeXFormula(tp, args[1]).root, null);
+        return new CumulativeScriptsAtom(tp.getLastAtom(), new TeXFormula(tp, args[1]).root, null, tp.getContext().isInMbox());
     }
 
     public static final Atom dotminus_macro(final TeXParser tp, final String[] args) throws ParseException {
@@ -1559,7 +1559,7 @@ public class PredefMacros {
         VRowAtom vra = new VRowAtom(new LapedAtom(ra, 'r'));
         vra.setRaise(TeXConstants.UNIT_EX, -0.1f);
         RowAtom at = new RowAtom(vra);
-        at.add(new RomanAtom(new CharAtom('h', tp.formula.textStyle)));
+        at.add(new RomanAtom(new CharAtom('h', tp.formula.textStyle, tp.getContext().isInMbox())));
         return at;
     }
 
@@ -1569,7 +1569,7 @@ public class PredefMacros {
         VRowAtom vra = new VRowAtom(new LapedAtom(ra, 'r'));
         vra.setRaise(TeXConstants.UNIT_EX, 0.55f);
         RowAtom at = new RowAtom(vra);
-        at.add(new RomanAtom(new CharAtom('H', tp.formula.textStyle)));
+        at.add(new RomanAtom(new CharAtom('H', tp.formula.textStyle, tp.getContext().isInMbox())));
         return at;
     }
 
@@ -1579,7 +1579,7 @@ public class PredefMacros {
         VRowAtom vra = new VRowAtom(new LapedAtom(ra, 'r'));
         vra.setRaise(TeXConstants.UNIT_EX, -0.1f);
         RowAtom at = new RowAtom(vra);
-        at.add(new RomanAtom(new CharAtom('d', tp.formula.textStyle)));
+        at.add(new RomanAtom(new CharAtom('d', tp.formula.textStyle, tp.getContext().isInMbox())));
         return at;
     }
 
@@ -1589,7 +1589,7 @@ public class PredefMacros {
         VRowAtom vra = new VRowAtom(new LapedAtom(ra, 'r'));
         vra.setRaise(TeXConstants.UNIT_EX, -0.55f);
         RowAtom at = new RowAtom(vra);
-        at.add(new RomanAtom(new CharAtom('D', tp.formula.textStyle)));
+        at.add(new RomanAtom(new CharAtom('D', tp.formula.textStyle, tp.getContext().isInMbox())));
         return at;
     }
 
@@ -1651,7 +1651,7 @@ public class PredefMacros {
     }
 
     public static final Atom sc_macro(final TeXParser tp, final String[] args) throws ParseException {
-        return new SmallCapAtom(new TeXFormula(tp, tp.getOverArgument(), null, false, tp.isIgnoreWhiteSpace()).root);
+        return new SmallCapAtom(new TeXFormula(tp, tp.getOverArgument(), null, false, tp.getContext().copy()).root);
     }
 
     public static final Atom quad_macro(final TeXParser tp, final String[] args) throws ParseException {
diff --git a/src/org/scilab/forge/jlatexmath/RowAtom.java b/src/org/scilab/forge/jlatexmath/RowAtom.java
index b7b7bab..249bf7e 100644
--- a/src/org/scilab/forge/jlatexmath/RowAtom.java
+++ b/src/org/scilab/forge/jlatexmath/RowAtom.java
@@ -209,7 +209,7 @@ public class RowAtom extends Atom implements Row {
             // insert atom's box
             atom.setPreviousAtom(previousAtom);
             Box b = atom.createBox(env);
-    if (markAdded || (at instanceof CharAtom && Character.isDigit(((CharAtom) at).getCharacter()))) {
+    if (markAdded || (at instanceof CharAtom && ((CharAtom)at).canBreakBefore())) {
  hBox.addBreakPosition(hBox.children.size());
     }
             hBox.add(b);
diff --git a/src/org/scilab/forge/jlatexmath/TeXFormula.java b/src/org/scilab/forge/jlatexmath/TeXFormula.java
index 1c4970a..32b51b6 100644
--- a/src/org/scilab/forge/jlatexmath/TeXFormula.java
+++ b/src/org/scilab/forge/jlatexmath/TeXFormula.java
@@ -211,7 +211,7 @@ public class TeXFormula {
      *
      */
     public TeXFormula() {
-        parser = new TeXParser("", this, false);
+        parser = new TeXParser("", this, false, TeXParserContext.createDefaultParserContext());
     }
 
     /**
@@ -223,7 +223,7 @@ public class TeXFormula {
     public TeXFormula(String s, Map<String, String> map) throws ParseException {
         this.jlmXMLMap = map;
         this.textStyle = textStyle;
-        parser = new TeXParser(s, this);
+        parser = new TeXParser(s, this, TeXParserContext.createDefaultParserContext());
         parser.parse();
     }
 
@@ -239,7 +239,7 @@ public class TeXFormula {
 
     public TeXFormula(String s, boolean firstpass) throws ParseException {
         this.textStyle = null;
-        parser = new TeXParser(s, this, firstpass);
+        parser = new TeXParser(s, this, firstpass, TeXParserContext.createDefaultParserContext());
         parser.parse();
     }
 
@@ -249,13 +249,13 @@ public class TeXFormula {
      */
     public TeXFormula(String s, String textStyle) throws ParseException {
         this.textStyle = textStyle;
-        parser = new TeXParser(s, this);
+        parser = new TeXParser(s, this, TeXParserContext.createDefaultParserContext());
         parser.parse();
     }
 
-    public TeXFormula(String s, String textStyle, boolean firstpass, boolean space) throws ParseException {
+    public TeXFormula(String s, String textStyle, boolean firstpass, final TeXParserContext context) throws ParseException {
         this.textStyle = textStyle;
-        parser = new TeXParser(s, this, firstpass, space);
+        parser = new TeXParser(s, this, firstpass, context);
         parser.parse();
     }
 
@@ -278,7 +278,7 @@ public class TeXFormula {
      */
     protected TeXFormula(TeXParser tp) {
         this.jlmXMLMap = tp.formula.jlmXMLMap;
-        parser = new TeXParser(tp.getIsPartial(), "", this, false);
+        parser = new TeXParser(tp.getIsPartial(), "", this, false, TeXParserContext.createDefaultParserContext());
     }
 
     /**
@@ -290,12 +290,16 @@ public class TeXFormula {
     protected TeXFormula(TeXParser tp, String s) throws ParseException {
         this(tp, s, null);
     }
-
+    
     protected TeXFormula(TeXParser tp, String s, boolean firstpass) throws ParseException {
+     this(tp, s, firstpass, TeXParserContext.createDefaultParserContext());
+    }
+
+    protected TeXFormula(TeXParser tp, String s, boolean firstpass, final TeXParserContext context) throws ParseException {
         this.textStyle = null;
         this.jlmXMLMap = tp.formula.jlmXMLMap;
         boolean isPartial = tp.getIsPartial();
-        parser = new TeXParser(isPartial, s, this, firstpass);
+        parser = new TeXParser(isPartial, s, this, firstpass, context);
         if (isPartial) {
             try {
                 parser.parse();
@@ -313,7 +317,7 @@ public class TeXFormula {
         this.textStyle = textStyle;
         this.jlmXMLMap = tp.formula.jlmXMLMap;
         boolean isPartial = tp.getIsPartial();
-        parser = new TeXParser(isPartial, s, this);
+        parser = new TeXParser(isPartial, s, this, TeXParserContext.createDefaultParserContext());
         if (isPartial) {
             try {
                 parser.parse();
@@ -327,11 +331,11 @@ public class TeXFormula {
         }
     }
 
-    protected TeXFormula(TeXParser tp, String s, String textStyle, boolean firstpass, boolean space) throws ParseException {
+    protected TeXFormula(TeXParser tp, String s, String textStyle, boolean firstpass, final TeXParserContext context) throws ParseException {
         this.textStyle = textStyle;
         this.jlmXMLMap = tp.formula.jlmXMLMap;
         boolean isPartial = tp.getIsPartial();
-        parser = new TeXParser(isPartial, s, this, firstpass, space);
+        parser = new TeXParser(isPartial, s, this, firstpass, context);
         if (isPartial) {
             try {
                 parser.parse();
@@ -355,7 +359,7 @@ public class TeXFormula {
         String[] arr = text.split("\n|\\\\\\\\|\\\\cr");
         ArrayOfAtoms atoms = new ArrayOfAtoms();
         for (String s : arr) {
-            TeXFormula f = new TeXFormula(s, "mathnormal", true, false);
+            TeXFormula f = new TeXFormula(s, "mathnormal", true, TeXParserContext.createTextParserContext());
             atoms.add(new RomanAtom(f.root));
             atoms.addRow();
         }
@@ -375,7 +379,7 @@ public class TeXFormula {
             f.add(new EmptyAtom());
             return f;
         }
-        TeXParser parser = new TeXParser(true, formula, f);
+        TeXParser parser = new TeXParser(true, formula, f, TeXParserContext.createDefaultParserContext());
         try {
             parser.parse();
         } catch (Exception e) {
@@ -449,7 +453,7 @@ public class TeXFormula {
 
     public TeXFormula append(boolean isPartial, String s) throws ParseException {
         if (s != null && s.length() != 0) {
-            TeXParser tp = new TeXParser(isPartial, s, this);
+            TeXParser tp = new TeXParser(isPartial, s, this, TeXParserContext.createDefaultParserContext());
             tp.parse();
         }
         return this;
diff --git a/src/org/scilab/forge/jlatexmath/TeXParser.java b/src/org/scilab/forge/jlatexmath/TeXParser.java
index 88e21b1..ae4824d 100644
--- a/src/org/scilab/forge/jlatexmath/TeXParser.java
+++ b/src/org/scilab/forge/jlatexmath/TeXParser.java
@@ -51,9 +51,11 @@ public class TeXParser {
     private boolean insertion;
     private int atIsLetter;
     private boolean arrayMode;
-    private boolean ignoreWhiteSpace = true;
+//    private boolean ignoreWhiteSpace = true;
+//    private boolean inMbox = false;
+    private TeXParserContext context = TeXParserContext.createDefaultParserContext();
     private boolean isPartial;
-    private boolean autoNumberBreaking;
+    private boolean autoNumberBreaking; // TODO: remove?
 
     // the escape character
     private static final char ESCAPE = '\\';
@@ -130,8 +132,8 @@ public class TeXParser {
      * @param formula the formula where to put the atoms
      * @throws ParseException if the string could not be parsed correctly
      */
-    public TeXParser(String parseString, TeXFormula formula) {
-        this(parseString, formula, true);
+    public TeXParser(String parseString, TeXFormula formula, final TeXParserContext context) {
+        this(parseString, formula, true, context);
     }
 
     /**
@@ -142,8 +144,8 @@ public class TeXParser {
      * @param formula the formula where to put the atoms
      * @throws ParseException if the string could not be parsed correctly
      */
-    public TeXParser(boolean isPartial, String parseString, TeXFormula formula) {
-        this(parseString, formula, false);
+    public TeXParser(boolean isPartial, String parseString, TeXFormula formula, final TeXParserContext context) {
+        this(parseString, formula, false, context);
         this.isPartial = isPartial;
         firstpass();
     }
@@ -156,9 +158,11 @@ public class TeXParser {
      * @param firstpass a boolean to indicate if the parser must replace the user-defined macros by their content
      * @throws ParseException if the string could not be parsed correctly
      */
-    public TeXParser(boolean isPartial, String parseString, TeXFormula formula, boolean firstpass) {
+    public TeXParser(boolean isPartial, String parseString, TeXFormula formula, boolean firstpass,
+     final TeXParserContext context) {
         this.formula = formula;
         this.isPartial = isPartial;
+        this.context = context;
         if (parseString != null) {
             this.parseString = new StringBuffer(parseString);
             this.len = parseString.length();
@@ -180,8 +184,8 @@ public class TeXParser {
      * @param firstpass a boolean to indicate if the parser must replace the user-defined macros by their content
      * @throws ParseException if the string could not be parsed correctly
      */
-    public TeXParser(String parseString, TeXFormula formula, boolean firstpass) {
-        this(false, parseString, formula, firstpass);
+    public TeXParser(String parseString, TeXFormula formula, boolean firstpass, final TeXParserContext context) {
+        this(false, parseString, formula, firstpass, context);
     }
 
     /**
@@ -194,7 +198,7 @@ public class TeXParser {
      * @throws ParseException if the string could not be parsed correctly
      */
     public TeXParser(boolean isPartial, String parseString, ArrayOfAtoms aoa, boolean firstpass) {
-        this(isPartial, parseString, (TeXFormula) aoa, firstpass);
+        this(isPartial, parseString, (TeXFormula) aoa, firstpass, TeXParserContext.createDefaultParserContext());
         arrayMode = true;
     }
 
@@ -207,34 +211,7 @@ public class TeXParser {
      * @throws ParseException if the string could not be parsed correctly
      */
     public TeXParser(String parseString, ArrayOfAtoms aoa, boolean firstpass) {
-        this(false, parseString, (TeXFormula) aoa, firstpass);
-    }
-
-    /**
-     * Create a new TeXParser which ignores or not the white spaces, it's useful for mbox command
-     *
-     * @param isPartial if true certains exceptions are not thrown
-     * @param parseString the string to be parsed
-     * @param firstpass a boolean to indicate if the parser must replace the user-defined macros by their content
-     * @param space a boolean to indicate if the parser must ignore or not the white space
-     * @throws ParseException if the string could not be parsed correctly
-     */
-    public TeXParser(boolean isPartial, String parseString, TeXFormula formula, boolean firstpass, boolean space) {
-        this(isPartial, parseString, formula, firstpass);
-        this.ignoreWhiteSpace = space;
-    }
-
-    /**
-     * Create a new TeXParser which ignores or not the white spaces, it's useful for mbox command
-     *
-     * @param parseString the string to be parsed
-     * @param firstpass a boolean to indicate if the parser must replace the user-defined macros by their content
-     * @param space a boolean to indicate if the parser must ignore or not the white space
-     * @throws ParseException if the string could not be parsed correctly
-     */
-    public TeXParser(String parseString, TeXFormula formula, boolean firstpass, boolean space) {
-        this(false, parseString, formula, firstpass);
-        this.ignoreWhiteSpace = space;
+        this(false, parseString, (TeXFormula) aoa, firstpass, TeXParserContext.createDefaultParserContext());
     }
 
     /**
@@ -252,7 +229,7 @@ public class TeXParser {
         insertion = false;
         atIsLetter = 0;
         arrayMode = false;
-        ignoreWhiteSpace = true;
+        context = TeXParserContext.createDefaultParserContext();
         firstpass();
     }
 
@@ -328,14 +305,26 @@ public class TeXParser {
 
     /** Return a boolean indicating if the parser must ignore white spaces
      */
-    public boolean isIgnoreWhiteSpace() {
-        return ignoreWhiteSpace;
+    public boolean ignoresWhiteSpace() {
+        return context.ignoresSpaces();
     }
 
     /** Return a boolean indicating if the parser is in math mode
      */
     public boolean isMathMode() {
-        return ignoreWhiteSpace;
+        return context.ignoresSpaces();
+    }
+
+    /**
+     * Are we inside an \mbox{...}
+     * @return
+     */
+    public boolean isInMbox() {
+     return context.isInMbox();
+    }
+    
+    public TeXParserContext getContext() {
+     return context;
     }
 
     /** Return the current position in the parsed string
@@ -647,9 +636,12 @@ public class TeXParser {
                     break;
                 case ' ' :
                     pos++;
-                    if (!ignoreWhiteSpace) {// We are in a mbox
+                    if (!isInMbox()) // we're not in an \mbox{...}
+                    {
+                     formula.add(new BreakMarkAtom());
+                    }
+                    if (!ignoresWhiteSpace()) {// spaces are significant
                         formula.add(new SpaceAtom());
-                        formula.add(new BreakMarkAtom());
                         while (pos < len) {
                             ch = parseString.charAt(pos);
                             if (ch != ' ' || ch != '\t' || ch != '\r')
@@ -660,7 +652,7 @@ public class TeXParser {
                     break;
                 case DOLLAR :
                     pos++;
-                    if (!ignoreWhiteSpace) {// We are in a mbox
+                    if (!ignoresWhiteSpace()) {
                         int style = TeXConstants.STYLE_TEXT;
                         boolean doubleDollar = false;
                         if (parseString.charAt(pos) == DOLLAR) {
@@ -669,7 +661,7 @@ public class TeXParser {
                             pos++;
                         }
 
-                        formula.add(new MathAtom(new TeXFormula(this, getDollarGroup(DOLLAR), false).root, style));
+                        formula.add(new MathAtom(new TeXFormula(this, getDollarGroup(DOLLAR), false, context.ignoreSpaces()).root, style));
                         if (doubleDollar) {
                             if (parseString.charAt(pos) == DOLLAR) {
                                 pos++;
@@ -704,7 +696,7 @@ public class TeXParser {
                     formula.add(getScripts(ch));
                     break;
                 case SUB_SCRIPT :
-                    if (ignoreWhiteSpace) {
+                    if (ignoresWhiteSpace()) {
                         formula.add(getScripts(ch));
                     } else {
                         formula.add(new UnderscoreAtom());
@@ -718,25 +710,25 @@ public class TeXParser {
                     pos++;
                     break;
                 case PRIME :
-                    if (ignoreWhiteSpace) {
-                        formula.add(new CumulativeScriptsAtom(getLastAtom(), null, SymbolAtom.get("prime")));
+                    if (ignoresWhiteSpace()) {
+                        formula.add(new CumulativeScriptsAtom(getLastAtom(), null, SymbolAtom.get("prime"), context.isInMbox()));
                     } else {
                         formula.add(convertCharacter(PRIME, true));
                     }
                     pos++;
                     break;
                 case BACKPRIME :
-                    if (ignoreWhiteSpace) {
-                        formula.add(new CumulativeScriptsAtom(getLastAtom(), null, SymbolAtom.get("backprime")));
+                    if (ignoresWhiteSpace()) {
+                        formula.add(new CumulativeScriptsAtom(getLastAtom(), null, SymbolAtom.get("backprime"), context.isInMbox()));
                     } else {
                         formula.add(convertCharacter(BACKPRIME, true));
                     }
                     pos++;
                     break;
                 case DQUOTE :
-                    if (ignoreWhiteSpace) {
-                        formula.add(new CumulativeScriptsAtom(getLastAtom(), null, SymbolAtom.get("prime")));
-                        formula.add(new CumulativeScriptsAtom(getLastAtom(), null, SymbolAtom.get("prime")));
+                    if (ignoresWhiteSpace()) {
+                        formula.add(new CumulativeScriptsAtom(getLastAtom(), null, SymbolAtom.get("prime"), context.isInMbox()));
+                        formula.add(new CumulativeScriptsAtom(getLastAtom(), null, SymbolAtom.get("prime"), context.isInMbox()));
                     } else {
                         formula.add(convertCharacter(PRIME, true));
                         formula.add(convertCharacter(PRIME, true));
@@ -783,7 +775,7 @@ public class TeXParser {
         if (formula.root instanceof RowAtom) {
             at = ((RowAtom)formula.root).getLastAtom();
         } else if (formula.root == null) {
-            at = new PhantomAtom(new CharAtom('M', "mathnormal"), false, true, true);
+            at = new PhantomAtom(new CharAtom('M', "mathnormal", context.isInMbox()), false, true, true);
         } else {
             at = formula.root;
             formula.root = null;
@@ -1076,7 +1068,7 @@ public class TeXParser {
      * @throws ParseException if the character is unknown
      */
     public Atom convertCharacter(char c, boolean oneChar) throws ParseException {
-        if (ignoreWhiteSpace) {// The Unicode Greek letters in math mode are not drawn with the Greek font
+        if (ignoresWhiteSpace()) {// The Unicode Greek letters in math mode are not drawn with the Greek font
             if (c >= 945 && c <= 969) {
                 return SymbolAtom.get(TeXFormula.symbolMappings[c]);
             } else if (c >= 913 && c <= 937) {
@@ -1118,7 +1110,7 @@ public class TeXParser {
                     return new ColorAtom(new RomanAtom(new TeXFormula("\\text{(Unknown char " + ((int) c) + ")}").root), null, Color.RED);
                 }
             } else {
-                if (!ignoreWhiteSpace) {// we are in text mode
+                if (!ignoresWhiteSpace()) {// we are in text mode
                     if (TeXFormula.symbolTextMappings[c] != null) {
                         return SymbolAtom.get(TeXFormula.symbolTextMappings[c]).setUnicode(c);
                     }
@@ -1155,7 +1147,7 @@ public class TeXParser {
                 }
                 return new JavaFontRenderingAtom(parseString.substring(start, end + 1), fontInfos);
             }
-            return new CharAtom(c, formula.textStyle);
+            return new CharAtom(c, formula.textStyle, context.isInMbox());
         }
     }
 
@@ -1283,7 +1275,7 @@ public class TeXParser {
                 }
             }
 
-            if (ignoreWhiteSpace) {
+            if (ignoresWhiteSpace()) {
                 skipWhiteSpace();
             }
         }
diff --git a/src/org/scilab/forge/jlatexmath/TeXParserContext.java b/src/org/scilab/forge/jlatexmath/TeXParserContext.java
index e69de29..b4cbbc4 100644
--- a/src/org/scilab/forge/jlatexmath/TeXParserContext.java
+++ b/src/org/scilab/forge/jlatexmath/TeXParserContext.java
@@ -0,0 +1,63 @@
+package org.scilab.forge.jlatexmath;
+
+public class TeXParserContext {
+
+ final private boolean ignoreSpaces;
+ final private boolean inMbox;
+
+ public TeXParserContext(final boolean ignoreSpaces, final boolean inMbox)
+ {
+ this.ignoreSpaces = ignoreSpaces;
+ this.inMbox = inMbox;
+ }
+
+ public boolean ignoresSpaces()
+ {
+ return ignoreSpaces;
+ }
+
+ public boolean isInMbox()
+ {
+ return inMbox;
+ }
+
+ public TeXParserContext copy()
+ {
+ return new TeXParserContext(ignoresSpaces(), isInMbox());
+ }
+
+ public static TeXParserContext createDefaultParserContext()
+ {
+ return new TeXParserContext(true, false);
+ }
+
+ public static TeXParserContext createTextParserContext()
+ {
+ return new TeXParserContext(false, false);
+ }
+
+ public static TeXParserContext createMboxParserContext()
+ {
+ return new TeXParserContext(false, true);
+ }
+
+ public TeXParserContext inMbox()
+ {
+ return new TeXParserContext(ignoreSpaces, true);
+ }
+
+ public TeXParserContext outsideMbox()
+ {
+ return new TeXParserContext(ignoreSpaces, false);
+ }
+
+ public TeXParserContext ignoreSpaces()
+ {
+ return new TeXParserContext(true, inMbox);
+ }
+
+ public TeXParserContext honorSpaces()
+ {
+ return new TeXParserContext(false, inMbox);
+ }
+}

_______________________________________________
jlatexmath mailing list
[hidden email]
http://lists.scilab.org/mailman/listinfo/jlatexmath
Felix Natter Felix Natter
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [Jlatexmath] Automatic Linebreaks

Felix Natter <[hidden email]> writes:

> Calixte Denizet <[hidden email]> writes:
>
> hello Calixte,

hello again Calixte,

could you please reply to my mail about "\mbox handling"?

> I have one change for this (requires \mbox handling changes, see below):
>
>                 case ' ' :
>                     pos++;
>                     if (!isInMbox()) // we're not in an \mbox{...}
>                     {
>                     formula.add(new BreakMarkAtom());
>                     }
>                     if (!ignoresWhiteSpace()) {// spaces are significant
>                     [...]
>
> => With this change, it is possible to break at non-significant
> whitespace, e.g. in "$x_1=1, x_2=2, x_3=3...$".

Unfortunately, this is not standard (La)TeX behavior: TeX usually breaks
at (binary) operators (AFAIK!), but also not at/before digits (current
behavior). What was the motivation behind the current behavior?
Do we want to implement the correct LaTeX behavior?

Thank you!
--
Felix Natter
_______________________________________________
jlatexmath mailing list
[hidden email]
http://lists.scilab.org/mailman/listinfo/jlatexmath
Calixte DENIZET Calixte DENIZET
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [Jlatexmath] Automatic Linebreaks

On 04/11/2012 17:26, Felix Natter wrote:
Felix Natter [hidden email] writes:

Calixte Denizet [hidden email] writes:

hello Calixte,
hello again Calixte,

could you please reply to my mail about "\mbox handling"?

I have one change for this (requires \mbox handling changes, see below):

                case ' ' :
                    pos++;
                    if (!isInMbox()) // we're not in an \mbox{...}
                    {
                    	formula.add(new BreakMarkAtom());
                    }
                    if (!ignoresWhiteSpace()) {// spaces are significant
                    [...]

=> With this change, it is possible to break at non-significant
whitespace, e.g. in "$x_1=1, x_2=2, x_3=3...$".
Unfortunately, this is not standard (La)TeX behavior: TeX usually breaks
at (binary) operators (AFAIK!), but also not at/before digits (current
behavior). What was the motivation behind the current behavior?
Do we want to implement the correct LaTeX behavior?

Hi Felix,

Sorry for the lag... always a lot of work.

In this commit:
http://forge.scilab.org/index.php/p/jlatexmath/source/commit/21b6942a332d3a9f390d928ddcc2e010ac1d12a6/

I added auto-break after bin op and relation op and fix few bugs in mbox and cr.
You can put a break mark in using \\- in math mode or not. In mbox, a break mark is added after each whitespace.

Is it what you expected ?

C

Thank you!


-- 
Calixte Denizet
Software Development Engineer
-----------------------------------------------------------
Scilab Enterprises
143bis rue Yves Le Coz - 78000 Versailles, France
http://www.scilab-enterprises.com

_______________________________________________
jlatexmath mailing list
[hidden email]
http://lists.scilab.org/mailman/listinfo/jlatexmath
Felix Natter Felix Natter
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [Jlatexmath] Automatic Linebreaks

Calixte Denizet <[hidden email]> writes:

> On 04/11/2012 17:26, Felix Natter wrote:
>
>     Felix Natter <[hidden email]> writes:
>
>         Calixte Denizet <[hidden email]> writes:
>        
>         hello Calixte,
>        
>     hello again Calixte,
>    
>     could you please reply to my mail about "\mbox handling"?
>
>         I have one change for this (requires \mbox handling changes, see below):
>        
>                         case ' ' :
>                             pos++;
>                             if (!isInMbox()) // we're not in an \mbox{...}
>                             {
>                               formula.add(new BreakMarkAtom());
>                             }
>                             if (!ignoresWhiteSpace()) {// spaces are significant
>                             [...]
>        
>         => With this change, it is possible to break at non-significant
>         whitespace, e.g. in "$x_1=1, x_2=2, x_3=3...$".
>        
>     Unfortunately, this is not standard (La)TeX behavior: TeX usually breaks
>     at (binary) operators (AFAIK!), but also not at/before digits (current
>     behavior). What was the motivation behind the current behavior?
>     Do we want to implement the correct LaTeX behavior?
>
> Hi Felix,

hello Calixte,

> Sorry for the lag... always a lot of work.
>
> In this commit:
> http://forge.scilab.org/index.php/p/jlatexmath/source/commit/21b6942a332d3a9f390d928ddcc2e010ac1d12a6/
>
> I added auto-break after bin op and relation op

This seems to work fine, thanks.

> and fix few bugs in mbox and cr.
> You can put a break mark in using \\- in math mode or not.

> In mbox, a break mark is added after each whitespace.

The rule in LaTeX is that in an \mbox{...}, line breaking is NOT
allowed. Currently, JLaTeXMath allows to break there.

Your comment in TeXParser.java seems to be incorrect:
                case ' ' :
                    pos++;
                    if (!ignoreWhiteSpace) {// We are in a mbox
                        formula.add(new SpaceAtom());
                        formula.add(new BreakMarkAtom());
=> that whitespace is significant (e.g. text mode) does not
mean we're in an mbox.

In fact, the two states "significant whitespace" (e.g. text mode) and "line
breaks not allowed" (e.g. in \mbox{...}) are independent:
- whitespace significant, linebreaks allowed: "abc def"
  (text mode)
- whitespace insignificant, linebreaks allowed: "$abc+def$"
  (math mode)
- whitespace significant, linebreaks disallowed: "\mbox{abc def}"
  (text mode with mbox)
- whitespace insignificant, linebreaks disallowed: "${abc+def}$"
  ({...} is like \mbox for math mode)

(These examples have been tested with:
pdfTeX, Version 3.1415926-2.4-1.40.13 (TeX Live 2012/Debian))

That's why we proposed a patch (not finished, needs review) with a
TeXParserContext that contains the two status bools mentioned above
(mail from Wed, 17 Oct 2012 22:14:28 +0200).

Here are the basics mentioned in that mail:

- The idea is that TeXParser remembers -- as is already done for "ignore
  whitespace" -- whether the parser is in an \mbox{...}. In order to
  group this context information, a new class TeXParserContext was
  introduced with nice OO feel (immutable, e.g. context.inMbox() creates
  a new context with inMbox=true and the current setting for "Ignore WS").

- the context is fed into a TeXParser instance by a new TeXFormula
  constructor

- Often the default context (ignoreWS=true, inMbox=false) is assumed,
  not sure whether this is correct.

- The context is passed to subformulas (and to CharAtom /
  CumulativeScriptsAtom, see below) and evaluated in ch == ' '.

- MatrixAtom creates a TeXParser object. We assume that since the parser
  is used for matrix cells(?), the default context shall be used.

- Concerning PredefMacros.java: We assume that:

  - mbox_macro should start with mbox-context (ignoreWS=false,
    inMbox=true)

  - text_macro should start with text context (ignoreWS=false,
    inMbox=false)

  - intertext_macro should start with text context

  - bf/tt/sf/it/rm_macro: should inherit context of tp (first arg)

  - changes for CharAtom/CumulativeScriptsAtom may not be necessary (see
    below)

  - size_macro: should inherit context of tp (first arg)

  - in all other macros, the default context should be used

- In RowAtom.createBox() there is logic for allowing to break before
  numerals. In order to forbid this in an \mbox{...}, changes to
  CharAtom and CumulativeScriptsAtom were needed (idea: the
  CharAtom-ctor should know whether it's allowed to be break before its
  char). Is this still necessary now that we can break at
  non-significant whitespace (see above)?

Please tell me if you want a different patch format and/or how we can
fix things.

BTW: actually JLaTexMath is not LaTeX-compatible wrt \text{...} because
LaTeX seems to treat \text{...} as \text{\mbox{...}}
(try this: \text{hello world hello world hello world hello world hello
world hello world hello world hello world})
=> but I think it's okay not to change this, because it's useful
to simply always wrap the (embedded) equation in \text{...} to allow for
a mixture of text+math with linebreaks.

Thank you!
--
Felix Natter
_______________________________________________
jlatexmath mailing list
[hidden email]
http://lists.scilab.org/mailman/listinfo/jlatexmath
Loading...