Luca Padovani <lpadovan@cs.unibo.it>
+Paolo Marinelli <pmarinel@cs.unibo.it>
-* replaceChild on document root should work, but it is implemented as
- an insertBefore + removeChild, and the insertBefore is not allowed
- for the document must have xactly _one_ child
-* the code to dispatch the events is wrong, because it stores
- xmlNodes and not gdome wrappers, hence the nodes can be deleted
-* when firing events, self is not always reffed, what is the reason for
- doing it?
-* DOMSubtreeModified must have bubble=yes
-* when setting more event listeners for the same node, with same type
- and same useCapture, the event listener also matters. It seems like
- now one can set only one event per combination type/capture
* /usr/lib is given by gdome-config
* should optimize event propagation, remember only those nodes with
listeners
#EXTRA_DIST = BUGS HISTORY LICENSE aclocal.m4 debian/
-SUBDIRS = src test
+SUBDIRS = src test ocaml
CLEANFILES = core
bin_SCRIPTS = editex-config
GMETADOM_LIBS = @GMETADOM_LIBS@
GTKMATHVIEW_CFLAGS = @GTKMATHVIEW_CFLAGS@
GTKMATHVIEW_LIBS = @GTKMATHVIEW_LIBS@
+HAVE_OCAMLC = @HAVE_OCAMLC@
+HAVE_OCAMLDEP = @HAVE_OCAMLDEP@
+HAVE_OCAMLFIND = @HAVE_OCAMLFIND@
+HAVE_OCAMLMKLIB = @HAVE_OCAMLMKLIB@
+HAVE_OCAMLOPT = @HAVE_OCAMLOPT@
LDFLAGS = @LDFLAGS@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
MAKEINFO = @MAKEINFO@
+MLGDOME_CFLAGS = @MLGDOME_CFLAGS@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OCAMLC = @OCAMLC@
+OCAMLDEP = @OCAMLDEP@
+OCAMLFIND = @OCAMLFIND@
+OCAMLMKLIB = @OCAMLMKLIB@
+OCAMLOPT = @OCAMLOPT@
+OCAMLSTDLIBDIR = @OCAMLSTDLIBDIR@
+OCAMLSTUBDIR = @OCAMLSTUBDIR@
+OCAML_INCLUDE_DIR = @OCAML_INCLUDE_DIR@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
STRIP = @STRIP@
VERSION = @VERSION@
-SUBDIRS = src test
+SUBDIRS = src test ocaml
CLEANFILES = core
bin_SCRIPTS = editex-config
AC_PROG_INSTALL
AC_HEADER_STDC([])
+AC_LANG_PUSH(C++)
+AC_CHECK_HEADERS(hash_map)
+AC_CHECK_HEADERS(ext/hash_map)
+AC_LANG_POP(C++)
+
AC_SUBST(CFLAGS)
AC_SUBST(CPPFLAGS)
AC_SUBST(LDFLAGS)
AC_SUBST(GMETADOM_LIBS)
GDOMEXSLT_CONFIG="gdome_xslt_cpp_smart-config"
-GDOMEXSLT_MIN_VERSION=0.0.1
+GDOMEXSLT_MIN_VERSION=0.0.4
AC_MSG_CHECKING([for gdome_xslt C++ library] >= $GDOMEXSLT_MIN_VERSION)
if test "x$GDOMEXSLT_PREFIX" != "x"
then
AC_SUBST(GTKMATHVIEW_CFLAGS)
AC_SUBST(GTKMATHVIEW_LIBS)
+AC_CHECK_PROG(HAVE_OCAMLC, ocamlc, yes, no)
+if test $HAVE_OCAMLC = "no"; then
+ AC_MSG_ERROR([could not find ocamlc in PATH, please make sure ocaml is installed])
+else
+ OCAMLC=ocamlc
+ OCAMLSTDLIBDIR="`ocamlc -where`"
+ OCAMLSTUBDIR="`ocamlc -where`/stublibs"
+ AC_SUBST(OCAMLC)
+ AC_SUBST(OCAMLSTDLIBDIR)
+ AC_SUBST(OCAMLSTUBDIR)
+fi
+
+AC_CHECK_PROG(HAVE_OCAMLOPT, ocamlopt, yes, no)
+if test $HAVE_OCAMLOPT = "no"; then
+ AC_MSG_WARN([ocaml native libraries won't be compiled since ocamlopt was not found])
+else
+ OCAMLOPT=ocamlopt
+ AC_SUBST(OCAMLOPT)
+fi
+AM_CONDITIONAL(HAVE_OCAMLOPT_COND, test x$HAVE_OCAMLOPT = xyes)
+
+AC_CHECK_PROG(HAVE_OCAMLFIND, ocamlfind, yes, no)
+if test $HAVE_OCAMLFIND = "no"; then
+ AC_MSG_ERROR([could not find ocamlfind in PATH, please make sure findlib is installed])
+else
+ OCAMLFIND=ocamlfind
+ AC_SUBST(OCAMLFIND)
+fi
+
+AC_CHECK_PROG(HAVE_OCAMLDEP, ocamldep, yes, no)
+if test $HAVE_OCAMLDEP = "yes"; then
+ OCAMLDEP=ocamldep
+ AC_SUBST(OCAMLDEP)
+fi
+
+AC_CHECK_PROG(HAVE_OCAMLMKLIB, ocamlmklib, yes, no)
+if test $HAVE_OCAMLMKLIB = "no"; then
+ AC_MSG_ERROR([could not find ocamlmklib in PATH, please make sure ocamlmklib is installed])
+else
+ OCAMLMKLIB=ocamlmklib
+ AC_SUBST(OCAMLMKLIB)
+fi
+
+AC_MSG_CHECKING(for gdome2 ocaml binding)
+ocamlfind query gdome2 ||
+ AC_MSG_ERROR(gdome2 not installed (according to findlib))
+MLGDOME_CFLAGS="`$OCAMLFIND query -i-format gdome2`"
+AC_SUBST(MLGDOME_CFLAGS)
+
+AC_MSG_CHECKING(for the ocaml library dir)
+OCAML_LIB_DIR=`ocamlc -where`
+AC_MSG_RESULT($OCAML_LIB_DIR)
+
+AC_CHECK_FILE(/usr/include/caml/mlvalues.h,
+ OCAML_INCLUDE_DIR=/usr/include/caml,
+ OCAML_INCLUDE_DIR=$OCAML_LIB_DIR/caml
+)
+
+AC_SUBST(OCAML_INCLUDE_DIR)
+
AC_CONFIG_FILES([
Makefile
src/Makefile
test/Makefile
+ ocaml/Makefile
editex-config
])
AC_CONFIG_COMMANDS([default],[[chmod +x editex-config]],[[]])
--- /dev/null
+<?xml version="1.0"?>
+
+<dictionary name="TeX">
+
+ <!-- MACRO for testing -->
+ <entry name="cursor" pattern=""/>
+ <entry name="error" pattern="#1"/>
+
+</dictionary>
--- /dev/null
+<?xml version="1.0"?>
+
+<dictionary name="TeX">
+
+ <include href="dictionary-tex.xml"/>
+
+ <!-- MACRO for testing -->
+ <entry name="red" pattern="{"/>
+ <entry name="green" pattern="#1\over"/>
+ <entry name="duedelim" pattern="#1\over\over#2"/>
+
+</dictionary>
--- /dev/null
+<?xml version="1.0"?>
+
+<dictionary name="TeX">
+
+ <include href="dictionary-basic.xml"/>
+
+ <!-- Greek Letters (lower case) -->
+
+ <entry name="alpha" class="i" val="α"/>
+ <entry name="beta" class="i" val="β"/>
+ <entry name="gamma" class="i" val="γ"/>
+ <entry name="delta" class="i" val="δ"/>
+ <entry name="epsilon" class="i" val="ϵ"/>
+ <entry name="varepsilon" class="i" val="ε"/>
+ <entry name="zeta" class="i" val="ζ"/>
+ <entry name="eta" class="i" val="η"/>
+ <entry name="theta" class="i" val="θ"/>
+ <entry name="vartheta" class="i" val="ϑ"/>
+ <entry name="iota" class="i" val="ι"/>
+ <entry name="kappa" class="i" val="κ"/>
+ <entry name="lambda" class="i" val="λ"/>
+ <entry name="mu" class="i" val="μ"/>
+ <entry name="nu" class="i" val="ν"/>
+ <entry name="xi" class="i" val="ξ"/>
+ <entry name="o" class="i" val="ο"/>
+ <entry name="pi" class="i" val="π"/>
+ <entry name="varpi" class="i" val="ϖ"/>
+ <entry name="rho" class="i" val="ρ"/>
+ <entry name="varrho" class="i" val="ϱ"/>
+ <entry name="sigma" class="i" val="σ"/>
+ <entry name="varsigma" class="i" val="ς"/>
+ <entry name="tau" class="i" val="τ"/>
+ <entry name="upsilon" class="i" val="υ"/>
+ <entry name="phi" class="i" val="ϕ"/>
+ <entry name="varphi" class="i" val="φ"/>
+ <entry name="chi" class="i" val="χ"/>
+ <entry name="psi" class="i" val="ψ"/>
+ <entry name="omega" class="i" val="ω"/>
+
+ <!-- Greek Letters (upper case) -->
+
+ <entry name="Gamma" class="i" val="Γ"/>
+ <entry name="Delta" class="i" val="Δ"/>
+ <entry name="Theta" class="i" val="Θ"/>
+ <entry name="Lambda" class="i" val="Λ"/>
+ <entry name="Xi" class="i" val="Ξ"/>
+ <entry name="Pi" class="i" val="Π"/>
+ <entry name="Sigma" class="i" val="Σ"/>
+ <entry name="Upsilon" class="i" val="ϒ"/>
+ <entry name="Phi" class="i" val="Φ"/>
+ <entry name="Psi" class="i" val="Ψ"/>
+ <entry name="Omega" class="i" val="Ω"/>
+
+ <!-- Symbols of Type Ord -->
+
+ <entry name="aleph" class="i" val="ℵ"/>
+ <entry name="hbar" class="i" val="ℏ︀"/>
+ <entry name="imath" class="i" val="ı"/>
+ <entry name="jmath" class="i" val="j︀"/>
+ <entry name="ell" class="i" val="ℓ"/>
+ <entry name="wp" class="i" val="℘"/>
+ <entry name="Re" class="o" val="ℜ"/>
+ <entry name="Im" class="o" val="ℑ"/>
+ <entry name="partial" class="o" val="∂"/>
+ <entry name="infty" class="i" val="∞"/>
+ <entry name="prime" class="o" val="′"/>
+ <entry name="emptyset" class="i" val="∅︀"/>
+ <entry name="nabla" class="o" val="∇"/>
+ <entry name="surd" class="o" val="????"/>
+ <entry name="top" class="i" val="⊤"/>
+ <entry name="bot" class="i" val="⊥"/>
+ <entry name="|" class="o" val="|" delimiter="1"/>
+ <entry name="angle" class="o" val="∠"/>
+ <entry name="triangle" class="o" val="▵"/>
+ <entry name="backslash" class="o" val="\"/>
+ <entry name="forall" class="o" val="∀"/>
+ <entry name="exists" class="o" val="∃"/>
+ <entry name="neg" class="o" val="¬"/>
+ <entry name="lnot" class="o" val="¬"/>
+ <entry name="flat" class="i" val="♭"/>
+ <entry name="natural" class="i" val="♮"/>
+ <entry name="sharp" class="i" val="♯"/>
+ <entry name="clubsuit" class="i" val="♣"/>
+ <entry name="diamondsuit" class="i" val="♢"/>
+ <entry name="heartsuit" class="i" val="♡"/>
+ <entry name="spadesuit" class="i" val="♠"/>
+
+ <!-- Large Operators -->
+
+ <entry name="sum" class="o" val="∑" limits="1"/>
+ <entry name="prod" class="o" val="∏" limits="1"/>
+ <entry name="coprod" class="o" val="∐" limits="1"/>
+ <entry name="int" class="o" val="∫" limits="1"/>
+ <entry name="oint" class="o" val="∮" limits="1"/>
+ <entry name="bigcap" class="o" val="⋂" limits="1"/>
+ <entry name="bigcup" class="o" val="⋃" limits="1"/>
+ <entry name="bigsqcup" class="o" val="⊔" limits="1"/>
+ <entry name="bigvee" class="o" val="⋁" limits="1"/>
+ <entry name="bigwedge" class="o" val="⋀" limits="1"/>
+ <entry name="bigodot" class="o" val="⊙" limits="1"/>
+ <entry name="bigotimes" class="o" val="⊗" limits="1"/>
+ <entry name="bigoplus" class="o" val="⊕" limits="1"/>
+ <entry name="biguplus" class="o" val="⊎" limits="1"/>
+
+ <!-- Binary Operations -->
+
+ <entry name="pm" class="o" val="±"/>
+ <entry name="mp" class="o" val="∓"/>
+ <entry name="setminus" class="o" val="∖"/>
+ <entry name="cdot" class="o" val="ċ"/>
+ <entry name="times" class="o" val="×"/>
+ <entry name="ast" class="o" val="*"/>
+ <entry name="star" class="o" val="⋆"/>
+ <entry name="diamond" class="o" val="⋄"/>
+ <entry name="circ" class="o" val="^"/>
+ <entry name="bullet" class="o" val="•"/>
+ <entry name="div" class="o" val="÷"/>
+ <entry name="cap" class="o" val="∩"/>
+ <entry name="cup" class="o" val="∪"/>
+ <entry name="uplus" class="o" val="⊎"/>
+ <entry name="sqcap" class="o" val="⊓"/>
+ <entry name="sqcup" class="o" val="⊔"/>
+ <entry name="triangleleft" class="o" val="◃"/>
+ <entry name="triangleright" class="o" val="▹"/>
+ <entry name="wr" class="o" val="≀"/>
+ <entry name="bigcirc" class="o" val="◯"/>
+ <entry name="bigtriangleup" class="o" val="△"/>
+ <entry name="bigtriangledown" class="o" val="▽"/>
+ <entry name="vee" class="o" val="∨"/>
+ <entry name="lor" class="o" val="∨"/>
+ <entry name="wedge" class="o" val="∧"/>
+ <entry name="land" class="o" val="∧"/>
+ <entry name="oplus" class="o" val="⊕"/>
+ <entry name="ominus" class="o" val="⊖"/>
+ <entry name="otimes" class="o" val="⊗"/>
+ <entry name="oslash" class="o" val="ø"/>
+ <entry name="odot" class="o" val="⊙"/>
+ <entry name="dagger" class="o" val="†"/>
+ <entry name="ddagger" class="o" val="‡"/>
+ <entry name="amalg" class="o" val="⨿"/>
+
+ <!-- Relations -->
+
+ <entry name="leq" class="o" val="≤"/>
+ <entry name="le" class="o" val="≤"/>
+ <entry name="prec" class="o" val="≺"/>
+ <entry name="preceq" class="o" val="⪯"/>
+ <entry name="ll" class="o" val="≪"/>
+ <entry name="subset" class="o" val="⊂"/>
+ <entry name="subseteq" class="o" val="⊆"/>
+ <entry name="in" class="o" val="∈"/>
+ <entry name="vdash" class="o" val="⊢"/>
+ <entry name="smile" class="o" val="⌣"/>
+ <entry name="frown" class="o" val="⌢"/>
+ <entry name="propto" class="o" val="∝"/>
+ <entry name="geq" class="o" val="≥"/>
+ <entry name="ge" class="o" val="≥"/>
+ <entry name="succ" class="o" val="≻"/>
+ <entry name="succeq" class="o" val="≽"/>
+ <entry name="gg" class="o" val="≫"/>
+ <entry name="supset" class="o" val="⊃"/>
+ <entry name="supseteq" class="o" val="⊇"/>
+ <entry name="sqsupseteq" class="o" val="⊒"/>
+ <entry name="notin" class="o" val="∉"/>
+ <entry name="dashv" class="o" val="⊣"/>
+ <entry name="mid" class="o" val="∣"/>
+ <entry name="parallet" class="o" val="????;"/>
+ <entry name="equiv" class="o" val="≡"/>
+ <entry name="sim" class="o" val="∼"/>
+ <entry name="simeq" class="o" val="≃"/>
+ <entry name="asymp" class="o" val="≍"/>
+ <entry name="approx" class="o" val="≈"/>
+ <entry name="cong" class="o" val="≅"/>
+ <entry name="bowtie" class="o" val="⋈"/>
+ <entry name="ni" class="o" val="∋"/>
+ <entry name="owns" class="o" val="∋"/>
+ <entry name="models" class="o" val="⊧"/>
+ <entry name="doteq" class="o" val="≐"/>
+ <entry name="perp" class="o" val="⊥"/>
+
+ <entry name="not" pattern="#1" embellishment="1"/>
+ <entry name="ne" class="o" val="≠"/>
+
+ <!-- Arrows -->
+
+ <entry name="leftarrow" class="o" val="←"/>
+ <entry name="gets" class="o" val="←"/>
+ <entry name="Leftarrow" class="o" val="⇐"/>
+ <entry name="rightarrow" class="o" val="→"/>
+ <entry name="to" class="o" val="→"/>
+ <entry name="Rightarrow" class="o" val="⇒"/>
+ <entry name="leftrightarrow" class="o" val="↔"/>
+ <entry name="Leftrightarrow" class="o" val="⇔"/>
+ <entry name="mapsto" class="o" val="↦"/>
+ <entry name="hookleftarrow" class="o" val="↩"/>
+ <entry name="uparrow" class="o" val="↑"/>
+ <entry name="downarrow" class="o" val="↓"/>
+ <entry name="updownarrow" class="o" val="↕"/>
+ <entry name="nearrow" class="o" val="↗"/>
+ <entry name="nwarrow" class="o" val="↖"/>
+ <entry name="longleftarrow" class="o" val="????;"/>
+ <entry name="Longleftarrow" class="o" val="????"/>
+ <entry name="longrightarrow" class="o" val="????"/>
+ <entry name="Longrightarrow" class="o" val="????"/>
+ <entry name="longleftrightarrow" class="o" val="????"/>
+ <entry name="Longleftrightarrow" class="o" val="????"/>
+ <entry name="longmapsto" class="o" val="????"/>
+ <entry name="hookrightarrow" class="o" val="↪"/>
+ <entry name="Uparrow" class="o" val="⇑"/>
+ <entry name="Downarrow" class="o" val="⇓"/>
+ <entry name="searrow" class="o" val="↘"/>
+ <entry name="swarrow" class="o" val="↙"/>
+
+ <entry name="buildrel" pattern="#1\over#2" embellishment="1"/>
+
+ <!-- Delimiters -->
+
+ <entry name="lbrack" class="o" val="[" delimiter="1"/>
+ <entry name="rbrack" class="o" val="]" delimiter="1"/>
+ <entry name="vert" class="o" val="|" delimiter="1"/>
+ <entry name="Vert" class="o" val="‖" delimiter="1"/>
+ <entry name="lbrace" class="o" val="{" delimiter="1"/>
+ <entry name="{" class="o" val="{" delimiter="1"/>
+ <entry name="rbrace" class="o" val="}" delimiter="1"/>
+ <entry name="}" class="o" val="}" delimiter="1"/>
+ <entry name="lfloor" class="o" val="⌊" delimiter="1"/>
+ <entry name="rfloor" class="o" val="⌋" delimiter="1"/>
+ <entry name="langle" class="o" val="〈" delimiter="1"/>
+ <entry name="rangle" class="o" val="〉" delimiter="1"/>
+ <entry name="lceil" class="o" val="⌈" delimiter="1"/>
+ <entry name="rceil" class="o" val="⌉" delimiter="1"/>
+
+ <entry name="left" pattern="#1" embellishment="1" delimiter="1"/>
+ <entry name="right" pattern="#1" embellishment="1" delimiter="1"/>
+ <entry name="bigl" pattern="#1" embellishment="1" delimiter="1"/>
+ <entry name="bigr" pattern="#1" embellishment="1" delimiter="1"/>
+ <entry name="bigm" pattern="#1" embellishment="1" delimiter="1"/>
+ <entry name="big" pattern="#1" embellishment="1" delimiter="1"/>
+ <entry name="Bigl" pattern="#1" embellishment="1" delimiter="1"/>
+ <entry name="Bigr" pattern="#1" embellishment="1" delimiter="1"/>
+ <entry name="Bigm" pattern="#1" embellishment="1" delimiter="1"/>
+ <entry name="biggl" pattern="#1" embellishment="1" delimiter="1"/>
+ <entry name="biggr" pattern="#1" embellishment="1" delimiter="1"/>
+ <entry name="biggm" pattern="#1" embellishment="1" delimiter="1"/>
+ <entry name="Biggl" pattern="#1" embellishment="1" delimiter="1"/>
+ <entry name="Biggr" pattern="#1" embellishment="1" delimiter="1"/>
+ <entry name="Biggm" pattern="#1" embellishment="1" delimiter="1"/>
+
+ <!-- Accents -->
+
+ <entry name="hat" pattern="#1" embellishment="1"/>
+ <entry name="widehat" pattern="#1" embellishment="1"/>
+ <entry name="check" pattern="#1" embellishment="1"/>
+ <entry name="tilde" pattern="#1" embellishment="1"/>
+ <entry name="widetilde" pattern="#1" embellishment="1"/>
+ <entry name="acute" pattern="#1" embellishment="1"/>
+ <entry name="grave" pattern="#1" embellishment="1"/>
+ <entry name="dot" pattern="#1" embellishment="1"/>
+ <entry name="ddot" pattern="#1" embellishment="1"/>
+ <entry name="breve" pattern="#1" embellishment="1"/>
+ <entry name="bar" pattern="#1" embellishment="1"/>
+ <entry name="vec" pattern="#1" embellishment="1"/>
+
+ <!-- Elementary Math Control Sequences -->
+
+ <entry name="overline" pattern="#1"/>
+ <entry name="underline" pattern="#1"/>
+ <entry name="sqrt" pattern="#1"/>
+ <entry name="root" pattern="#1\of#2"/>
+ <entry name="over" pattern="{}"/>
+ <entry name="atop" pattern="{}"/>
+ <entry name="choose" pattern="{}"/>
+ <entry name="brace" pattern="{}"/>
+ <entry name="brack" pattern="{}"/>
+
+ <!-- Style -->
+
+ <entry name="displaystyle" pattern="}"/>
+ <entry name="textstyle" pattern="}"/>
+ <entry name="scriptstyle" pattern="}"/>
+ <entry name="scriptscriptstyle" pattern="}"/>
+
+ <!-- Non-Italic Function Names -->
+
+ <entry name="arccos" class="i" val="arccos"/>
+ <entry name="arcsin" class="i" val="arcsin"/>
+ <entry name="arctan" class="i" val="arctan"/>
+ <entry name="arg" class="i" val="arg"/>
+ <entry name="cos" class="i" val="cos"/>
+ <entry name="cosh" class="i" val="cosh"/>
+ <entry name="cot" class="i" val="cot"/>
+ <entry name="coth" class="i" val="coth"/>
+ <entry name="csc" class="i" val="csc"/>
+ <entry name="exp" class="i" val="exp"/>
+ <entry name="deg" class="i" val="deg"/>
+ <entry name="det" class="o" val="det" limits="1"/>
+ <entry name="dim" class="i" val="dim"/>
+ <entry name="gcd" class="o" val="gcd" limits="1"/>
+ <entry name="hom" class="i" val="hom"/>
+ <entry name="inf" class="o" val="inf" limits="1"/>
+ <entry name="ker" class="i" val="ker"/>
+ <entry name="lg" class="i" val="lg"/>
+ <entry name="lim" class="o" val="lim" limits="1"/>
+ <entry name="liminf" class="o" val="liminf" limits="1"/>
+ <entry name="limsup" class="o" val="limsup" limits="1"/>
+ <entry name="ln" class="i" val="ln"/>
+ <entry name="log" class="i" val="log"/>
+ <entry name="max" class="o" val="max" limits="1"/>
+ <entry name="min" class="o" val="max" limits="1"/>
+ <entry name="Pr" class="o" val="Pr" limits="1"/>
+ <entry name="sec" class="i" val="sec"/>
+ <entry name="sin" class="i" val="sin"/>
+ <entry name="sinh" class="i" val="sinh"/>
+ <entry name="sup" class="o" limits="1"/>
+ <entry name="tan" class="i" val="tan"/>
+ <entry name="tanh" class="i" val="tanh"/>
+ <entry name="pmod" pattern="#1"/>
+ <entry name="bmod" class="o" val="mod"/>
+
+ <!-- Ellipses -->
+
+ <entry name="dots" class="i" val="…"/>
+ <entry name="ldots" class="i" val="…"/>
+ <entry name="cdots" class="i" val="⋯"/>
+ <entry name="vdots" class="i" val="⋮"/>
+ <entry name="ddots" class="i" val="⋱"/>
+
+ <!-- Fonts -->
+
+ <entry name="rm" pattern="}"/>
+ <entry name="bf" pattern="}"/>
+ <entry name="tt" pattern="}"/>
+ <entry name="sl" pattern="}"/>
+ <entry name="it" pattern="}"/>
+
+ <!-- Horizontal Spacing -->
+
+ <entry name=","/>
+ <entry name=">"/>
+ <entry name=";"/>
+ <entry name="!"/>
+
+ <!-- Braces and Matrices -->
+
+ <entry name="matrix" pattern="#1" table="1"/>
+ <entry name="pmatrix" pattern="#1" table="1"/>
+ <entry name="bordermatrix" pattern="#1" table="1"/>
+ <entry name="overbrace" pattern="#1" limits="1"/>
+ <entry name="underbrace" pattern="#1" limits="1"/>
+ <entry name="cases" pattern="#1" table="1"/>
+
+ <!-- MACRO for testing -->
+ <entry name="red" pattern="{"/>
+ <entry name="green" pattern="#1\over"/>
+ <entry name="duedelim" pattern="#1\over\over#2"/>
+
+</dictionary>
-<!ELEMENT dictionary (entry)*>
+<!ELEMENT dictionary ((include)*,(entry*))>
<!ATTLIST dictionary
name CDATA #REQUIRED
>
+<!ELEMENT include EMPTY>
+<!ATTLIST include href CDATA>
+
<!ELEMENT entry EMPTY>
<!ATTLIST entry
name ID #REQUIRED
+++ /dev/null
-<?xml version="1.0"?>
-
-<dictionary name="TeX">
-
- <!-- Greek Letters (lower case) -->
-
- <entry name="alpha" class="i" val="α"/>
- <entry name="beta" class="i" val="β"/>
- <entry name="gamma" class="i" val="γ"/>
- <entry name="delta" class="i" val="δ"/>
- <entry name="epsilon" class="i" val="ϵ"/>
- <entry name="varepsilon" class="i" val="ε"/>
- <entry name="zeta" class="i" val="ζ"/>
- <entry name="eta" class="i" val="η"/>
- <entry name="theta" class="i" val="θ"/>
- <entry name="vartheta" class="i" val="ϑ"/>
- <entry name="iota" class="i" val="ι"/>
- <entry name="kappa" class="i" val="κ"/>
- <entry name="lambda" class="i" val="λ"/>
- <entry name="mu" class="i" val="μ"/>
- <entry name="nu" class="i" val="ν"/>
- <entry name="xi" class="i" val="ξ"/>
- <entry name="o" class="i" val="ο"/>
- <entry name="pi" class="i" val="π"/>
- <entry name="varpi" class="i" val="ϖ"/>
- <entry name="rho" class="i" val="ρ"/>
- <entry name="varrho" class="i" val="ϱ"/>
- <entry name="sigma" class="i" val="σ"/>
- <entry name="varsigma" class="i" val="ς"/>
- <entry name="tau" class="i" val="τ"/>
- <entry name="upsilon" class="i" val="υ"/>
- <entry name="phi" class="i" val="ϕ"/>
- <entry name="varphi" class="i" val="φ"/>
- <entry name="chi" class="i" val="χ"/>
- <entry name="psi" class="i" val="ψ"/>
- <entry name="omega" class="i" val="ω"/>
-
- <!-- Greek Letters (upper case) -->
-
- <entry name="Gamma" class="i" val="Γ"/>
- <entry name="Delta" class="i" val="Δ"/>
- <entry name="Theta" class="i" val="Θ"/>
- <entry name="Lambda" class="i" val="Λ"/>
- <entry name="Xi" class="i" val="Ξ"/>
- <entry name="Pi" class="i" val="Π"/>
- <entry name="Sigma" class="i" val="Σ"/>
- <entry name="Upsilon" class="i" val="ϒ"/>
- <entry name="Phi" class="i" val="Φ"/>
- <entry name="Psi" class="i" val="Ψ"/>
- <entry name="Omega" class="i" val="Ω"/>
-
- <!-- Symbols of Type Ord -->
-
- <entry name="aleph" class="i" val="ℵ"/>
- <entry name="hbar" class="i" val="ℏ︀"/>
- <entry name="imath" class="i" val="ı"/>
- <entry name="jmath" class="i" val="j︀"/>
- <entry name="ell" class="i" val="ℓ"/>
- <entry name="wp" class="i" val="℘"/>
- <entry name="Re" class="o" val="ℜ"/>
- <entry name="Im" class="o" val="ℑ"/>
- <entry name="partial" class="o" val="∂"/>
- <entry name="infty" class="i" val="∞"/>
- <entry name="prime" class="o" val="′"/>
- <entry name="emptyset" class="i" val="∅︀"/>
- <entry name="nabla" class="o" val="∇"/>
- <entry name="surd" class="o" val="????"/>
- <entry name="top" class="i" val="⊤"/>
- <entry name="bot" class="i" val="⊥"/>
- <entry name="|" class="o" val="|" delimiter="1"/>
- <entry name="angle" class="o" val="∠"/>
- <entry name="triangle" class="o" val="▵"/>
- <entry name="backslash" class="o" val="\"/>
- <entry name="forall" class="o" val="∀"/>
- <entry name="exists" class="o" val="∃"/>
- <entry name="neg" class="o" val="¬"/>
- <entry name="lnot" class="o" val="¬"/>
- <entry name="flat" class="i" val="♭"/>
- <entry name="natural" class="i" val="♮"/>
- <entry name="sharp" class="i" val="♯"/>
- <entry name="clubsuit" class="i" val="♣"/>
- <entry name="diamondsuit" class="i" val="♢"/>
- <entry name="heartsuit" class="i" val="♡"/>
- <entry name="spadesuit" class="i" val="♠"/>
-
- <!-- Large Operators -->
-
- <entry name="sum" class="o" val="∑" limits="1"/>
- <entry name="prod" class="o" val="∏" limits="1"/>
- <entry name="coprod" class="o" val="∐" limits="1"/>
- <entry name="int" class="o" val="∫" limits="1"/>
- <entry name="oint" class="o" val="∮" limits="1"/>
- <entry name="bigcap" class="o" val="⋂" limits="1"/>
- <entry name="bigcup" class="o" val="⋃" limits="1"/>
- <entry name="bigsqcup" class="o" val="⊔" limits="1"/>
- <entry name="bigvee" class="o" val="⋁" limits="1"/>
- <entry name="bigwedge" class="o" val="⋀" limits="1"/>
- <entry name="bigodot" class="o" val="⊙" limits="1"/>
- <entry name="bigotimes" class="o" val="⊗" limits="1"/>
- <entry name="bigoplus" class="o" val="⊕" limits="1"/>
- <entry name="biguplus" class="o" val="⊎" limits="1"/>
-
- <!-- Binary Operations -->
-
- <entry name="pm" class="o" val="±"/>
- <entry name="mp" class="o" val="∓"/>
- <entry name="setminus" class="o" val="∖"/>
- <entry name="cdot" class="o" val="ċ"/>
- <entry name="times" class="o" val="×"/>
- <entry name="ast" class="o" val="*"/>
- <entry name="star" class="o" val="⋆"/>
- <entry name="diamond" class="o" val="⋄"/>
- <entry name="circ" class="o" val="^"/>
- <entry name="bullet" class="o" val="•"/>
- <entry name="div" class="o" val="÷"/>
- <entry name="cap" class="o" val="∩"/>
- <entry name="cup" class="o" val="∪"/>
- <entry name="uplus" class="o" val="⊎"/>
- <entry name="sqcap" class="o" val="⊓"/>
- <entry name="sqcup" class="o" val="⊔"/>
- <entry name="triangleleft" class="o" val="◃"/>
- <entry name="triangleright" class="o" val="▹"/>
- <entry name="wr" class="o" val="≀"/>
- <entry name="bigcirc" class="o" val="◯"/>
- <entry name="bigtriangleup" class="o" val="△"/>
- <entry name="bigtriangledown" class="o" val="▽"/>
- <entry name="vee" class="o" val="∨"/>
- <entry name="lor" class="o" val="∨"/>
- <entry name="wedge" class="o" val="∧"/>
- <entry name="land" class="o" val="∧"/>
- <entry name="oplus" class="o" val="⊕"/>
- <entry name="ominus" class="o" val="⊖"/>
- <entry name="otimes" class="o" val="⊗"/>
- <entry name="oslash" class="o" val="ø"/>
- <entry name="odot" class="o" val="⊙"/>
- <entry name="dagger" class="o" val="†"/>
- <entry name="ddagger" class="o" val="‡"/>
- <entry name="amalg" class="o" val="⨿"/>
-
- <!-- Relations -->
-
- <entry name="leq" class="o" val="≤"/>
- <entry name="le" class="o" val="≤"/>
- <entry name="prec" class="o" val="≺"/>
- <entry name="preceq" class="o" val="⪯"/>
- <entry name="ll" class="o" val="≪"/>
- <entry name="subset" class="o" val="⊂"/>
- <entry name="subseteq" class="o" val="⊆"/>
- <entry name="in" class="o" val="∈"/>
- <entry name="vdash" class="o" val="⊢"/>
- <entry name="smile" class="o" val="⌣"/>
- <entry name="frown" class="o" val="⌢"/>
- <entry name="propto" class="o" val="∝"/>
- <entry name="geq" class="o" val="≥"/>
- <entry name="ge" class="o" val="≥"/>
- <entry name="succ" class="o" val="≻"/>
- <entry name="succeq" class="o" val="≽"/>
- <entry name="gg" class="o" val="≫"/>
- <entry name="supset" class="o" val="⊃"/>
- <entry name="supseteq" class="o" val="⊇"/>
- <entry name="sqsupseteq" class="o" val="⊒"/>
- <entry name="notin" class="o" val="∉"/>
- <entry name="dashv" class="o" val="⊣"/>
- <entry name="mid" class="o" val="∣"/>
- <entry name="parallet" class="o" val="????;"/>
- <entry name="equiv" class="o" val="≡"/>
- <entry name="sim" class="o" val="∼"/>
- <entry name="simeq" class="o" val="≃"/>
- <entry name="asymp" class="o" val="≍"/>
- <entry name="approx" class="o" val="≈"/>
- <entry name="cong" class="o" val="≅"/>
- <entry name="bowtie" class="o" val="⋈"/>
- <entry name="ni" class="o" val="∋"/>
- <entry name="owns" class="o" val="∋"/>
- <entry name="models" class="o" val="⊧"/>
- <entry name="doteq" class="o" val="≐"/>
- <entry name="perp" class="o" val="⊥"/>
-
- <entry name="not" pattern="#1" embellishment="1"/>
- <entry name="ne" class="o" val="≠"/>
-
- <!-- Arrows -->
-
- <entry name="leftarrow" class="o" val="←"/>
- <entry name="gets" class="o" val="←"/>
- <entry name="Leftarrow" class="o" val="⇐"/>
- <entry name="rightarrow" class="o" val="→"/>
- <entry name="to" class="o" val="→"/>
- <entry name="Rightarrow" class="o" val="⇒"/>
- <entry name="leftrightarrow" class="o" val="↔"/>
- <entry name="Leftrightarrow" class="o" val="⇔"/>
- <entry name="mapsto" class="o" val="↦"/>
- <entry name="hookleftarrow" class="o" val="↩"/>
- <entry name="uparrow" class="o" val="↑"/>
- <entry name="downarrow" class="o" val="↓"/>
- <entry name="updownarrow" class="o" val="↕"/>
- <entry name="nearrow" class="o" val="↗"/>
- <entry name="nwarrow" class="o" val="↖"/>
- <entry name="longleftarrow" class="o" val="????;"/>
- <entry name="Longleftarrow" class="o" val="????"/>
- <entry name="longrightarrow" class="o" val="????"/>
- <entry name="Longrightarrow" class="o" val="????"/>
- <entry name="longleftrightarrow" class="o" val="????"/>
- <entry name="Longleftrightarrow" class="o" val="????"/>
- <entry name="longmapsto" class="o" val="????"/>
- <entry name="hookrightarrow" class="o" val="↪"/>
- <entry name="Uparrow" class="o" val="⇑"/>
- <entry name="Downarrow" class="o" val="⇓"/>
- <entry name="searrow" class="o" val="↘"/>
- <entry name="swarrow" class="o" val="↙"/>
-
- <entry name="buildrel" pattern="#1\over#2" embellishment="1"/>
-
- <!-- Delimiters -->
-
- <entry name="lbrack" class="o" val="[" delimiter="1"/>
- <entry name="rbrack" class="o" val="]" delimiter="1"/>
- <entry name="vert" class="o" val="|" delimiter="1"/>
- <entry name="Vert" class="o" val="‖" delimiter="1"/>
- <entry name="lbrace" class="o" val="{" delimiter="1"/>
- <entry name="{" class="o" val="{" delimiter="1"/>
- <entry name="rbrace" class="o" val="}" delimiter="1"/>
- <entry name="}" class="o" val="}" delimiter="1"/>
- <entry name="lfloor" class="o" val="⌊" delimiter="1"/>
- <entry name="rfloor" class="o" val="⌋" delimiter="1"/>
- <entry name="langle" class="o" val="〈" delimiter="1"/>
- <entry name="rangle" class="o" val="〉" delimiter="1"/>
- <entry name="lceil" class="o" val="⌈" delimiter="1"/>
- <entry name="rceil" class="o" val="⌉" delimiter="1"/>
-
- <entry name="left" pattern="#1" embellishment="1" delimiter="1"/>
- <entry name="right" pattern="#1" embellishment="1" delimiter="1"/>
- <entry name="bigl" pattern="#1" embellishment="1" delimiter="1"/>
- <entry name="bigr" pattern="#1" embellishment="1" delimiter="1"/>
- <entry name="bigm" pattern="#1" embellishment="1" delimiter="1"/>
- <entry name="big" pattern="#1" embellishment="1" delimiter="1"/>
- <entry name="Bigl" pattern="#1" embellishment="1" delimiter="1"/>
- <entry name="Bigr" pattern="#1" embellishment="1" delimiter="1"/>
- <entry name="Bigm" pattern="#1" embellishment="1" delimiter="1"/>
- <entry name="biggl" pattern="#1" embellishment="1" delimiter="1"/>
- <entry name="biggr" pattern="#1" embellishment="1" delimiter="1"/>
- <entry name="biggm" pattern="#1" embellishment="1" delimiter="1"/>
- <entry name="Biggl" pattern="#1" embellishment="1" delimiter="1"/>
- <entry name="Biggr" pattern="#1" embellishment="1" delimiter="1"/>
- <entry name="Biggm" pattern="#1" embellishment="1" delimiter="1"/>
-
- <!-- Accents -->
-
- <entry name="hat" pattern="#1" embellishment="1"/>
- <entry name="widehat" pattern="#1" embellishment="1"/>
- <entry name="check" pattern="#1" embellishment="1"/>
- <entry name="tilde" pattern="#1" embellishment="1"/>
- <entry name="widetilde" pattern="#1" embellishment="1"/>
- <entry name="acute" pattern="#1" embellishment="1"/>
- <entry name="grave" pattern="#1" embellishment="1"/>
- <entry name="dot" pattern="#1" embellishment="1"/>
- <entry name="ddot" pattern="#1" embellishment="1"/>
- <entry name="breve" pattern="#1" embellishment="1"/>
- <entry name="bar" pattern="#1" embellishment="1"/>
- <entry name="vec" pattern="#1" embellishment="1"/>
-
- <!-- Elementary Math Control Sequences -->
-
- <entry name="overline" pattern="#1"/>
- <entry name="underline" pattern="#1"/>
- <entry name="sqrt" pattern="#1"/>
- <entry name="root" pattern="#1\of#2"/>
- <entry name="over" pattern="{}"/>
- <entry name="atop" pattern="{}"/>
- <entry name="choose" pattern="{}"/>
- <entry name="brace" pattern="{}"/>
- <entry name="brack" pattern="{}"/>
-
- <!-- Style -->
-
- <entry name="displaystyle" pattern="}"/>
- <entry name="textstyle" pattern="}"/>
- <entry name="scriptstyle" pattern="}"/>
- <entry name="scriptscriptstyle" pattern="}"/>
-
- <!-- Non-Italic Function Names -->
-
- <entry name="arccos" class="i" val="arccos"/>
- <entry name="arcsin" class="i" val="arcsin"/>
- <entry name="arctan" class="i" val="arctan"/>
- <entry name="arg" class="i" val="arg"/>
- <entry name="cos" class="i" val="cos"/>
- <entry name="cosh" class="i" val="cosh"/>
- <entry name="cot" class="i" val="cot"/>
- <entry name="coth" class="i" val="coth"/>
- <entry name="csc" class="i" val="csc"/>
- <entry name="exp" class="i" val="exp"/>
- <entry name="deg" class="i" val="deg"/>
- <entry name="det" class="o" val="det" limits="1"/>
- <entry name="dim" class="i" val="dim"/>
- <entry name="gcd" class="o" val="gcd" limits="1"/>
- <entry name="hom" class="i" val="hom"/>
- <entry name="inf" class="o" val="inf" limits="1"/>
- <entry name="ker" class="i" val="ker"/>
- <entry name="lg" class="i" val="lg"/>
- <entry name="lim" class="o" val="lim" limits="1"/>
- <entry name="liminf" class="o" val="liminf" limits="1"/>
- <entry name="limsup" class="o" val="limsup" limits="1"/>
- <entry name="ln" class="i" val="ln"/>
- <entry name="log" class="i" val="log"/>
- <entry name="max" class="o" val="max" limits="1"/>
- <entry name="min" class="o" val="max" limits="1"/>
- <entry name="Pr" class="o" val="Pr" limits="1"/>
- <entry name="sec" class="i" val="sec"/>
- <entry name="sin" class="i" val="sin"/>
- <entry name="sinh" class="i" val="sinh"/>
- <entry name="sup" class="o" limits="1"/>
- <entry name="tan" class="i" val="tan"/>
- <entry name="tanh" class="i" val="tanh"/>
- <entry name="pmod" pattern="#1"/>
- <entry name="bmod" class="o" val="mod"/>
-
- <!-- Ellipses -->
-
- <entry name="dots" class="i" val="…"/>
- <entry name="ldots" class="i" val="…"/>
- <entry name="cdots" class="i" val="⋯"/>
- <entry name="vdots" class="i" val="⋮"/>
- <entry name="ddots" class="i" val="⋱"/>
-
- <!-- Fonts -->
-
- <entry name="rm" pattern="}"/>
- <entry name="bf" pattern="}"/>
- <entry name="tt" pattern="}"/>
- <entry name="sl" pattern="}"/>
- <entry name="it" pattern="}"/>
-
- <!-- Horizontal Spacing -->
-
- <entry name=","/>
- <entry name=">"/>
- <entry name=";"/>
- <entry name="!"/>
-
- <!-- Braces and Matrices -->
-
- <entry name="matrix" pattern="#1" table="1"/>
- <entry name="pmatrix" pattern="#1" table="1"/>
- <entry name="bordermatrix" pattern="#1" table="1"/>
- <entry name="overbrace" pattern="#1" limits="1"/>
- <entry name="underbrace" pattern="#1" limits="1"/>
- <entry name="cases" pattern="#1" table="1"/>
-
- <!-- MACRO for testing -->
- <entry name="red" pattern="{"/>
- <entry name="green" pattern="#1\over"/>
- <entry name="duedelim" pattern="#1\over\over#2"/>
-
-</dictionary>
--- /dev/null
+PKGNAME = mathml-editor
+ARCHIVE = mlmathml-editor
+REQUIRES = gdome2 gdome2-xslt
+OCAMLFIND = @OCAMLFIND@
+OCAMLC = $(OCAMLFIND) @OCAMLC@ -package "$(REQUIRES)"
+OCAMLOPT = $(OCAMLFIND) @OCAMLOPT@ -package "$(REQUIRES)"
+OCAMLDEP = $(OCAMLFIND) @OCAMLDEP@ -package "$(REQUIRES)"
+OCAMLMKLIB = @OCAMLMKLIB@
+DLL = dll$(ARCHIVE).so
+OCAMLSTDLIBDIR = $(DESTDIR)/@OCAMLSTDLIBDIR@
+OCAMLSTUBDIR = $(DESTDIR)/@OCAMLSTUBDIR@
+OCAMLINSTALLDIR = $(OCAMLSTDLIBDIR)/$(PKGNAME)
+MODULES = i_mathml_editor mathml_editor
+INIT =
+CMI_S = $(MODULES:%=%.cmi)
+CMO_S = $(MODULES:%=%.cmo)
+CMX_S = $(MODULES:%=%.cmx)
+O_S = ml_mathml_editor.o
+SHARED_LIBS = $(GMETADOM_LIBS) $(GDOMEXSLT_LIBS)
+BYTE_STUFF = $(ARCHIVE).cma
+NATIVE_STUFF = $(ARCHIVE).cmxa $(ARCHIVE).a
+BYTE_INSTALL_STUFF = \
+ i_mathml_editor.cmi mathml_editor.cmi $(ARCHIVE).cma $(DLL) META
+NATIVE_INSTALL_STUFF = $(ARCHIVE).a $(ARCHIVE).cmxa
+
+EXTRA_DIST = \
+ META.in mathml_editor.ml i_mathml_editor.ml \
+ ml_mathml_editor.h c_mathml_editor.h .depend
+
+if HAVE_OCAMLOPT_COND
+noinst_DATA = $(BYTE_STUFF) $(NATIVE_STUFF)
+else
+noinst_DATA = $(BYTE_STUFF)
+endif
+
+noinst_LTLIBRARIES = libmlmathml_editor.la
+libmlmathml_editor_la_SOURCES = \
+ c_mathml_editor.cc \
+ ml_mathml_editor.c
+
+#test: test.ml $(ARCHIVE).cma
+# $(OCAMLC) -o $@ -linkpkg $(INCLUDES) $<
+
+#test.opt: test.ml $(ARCHIVE).cmxa
+# $(OCAMLOPT) -o $@ -linkpkg $(INCLUDES) $<
+
+if HAVE_OCAMLOPT_COND
+install-data-local: $(BYTE_INSTALL_STUFF) $(NATIVE_INSTALL_STUFF)
+else
+install-data-local: $(BYTE_INSTALL_STUFF)
+endif
+ $(mkinstalldirs) $(OCAMLSTDLIBDIR) $(OCAMLSTUBDIR)
+ chmod -x $(DLL)
+ $(OCAMLFIND) install -destdir $(OCAMLSTDLIBDIR) $(PKGNAME) $^
+ ln -fs $(DLL) $(OCAMLSTUBDIR)/lib$(ARCHIVE).so
+
+CLEANFILES = \
+ $(ARCHIVE).{cma,cmxa,a} $(CMI_S) $(CMO_S) $(CMX_S) ml_mathml_editor.o \
+ $(DLL) $(INIT).cm[iox] libmlmathml_editor.a
+
+INCLUDES = \
+ $(GDOME_CFLAGS) $(MLGDOME_CFLAGS) \
+ $(GMETADOM_CFLAGS) $(GDOMEXSLT_CFLAGS) \
+ -I$(top_srcdir)/src
+
+$(ARCHIVE).cma $(DLL): $(CMO_S)
+ $(OCAMLMKLIB) -o $(ARCHIVE) -L@OCAMLSTUBDIR@ $(CMO_S) $(O_S) $(SHARED_LIBS)
+$(ARCHIVE).cmxa $(ARCHIVE).a: $(CMX_S)
+ $(OCAMLMKLIB) -o $(ARCHIVE) -L@OCAMLSTUBDIR@ $(CMX_S) $(O_S) $(SHARED_LIBS)
+
+%.cmi: %.mli
+ $(OCAMLC) -c $<
+%.cmo %.cmi: %.ml
+ $(OCAMLC) -c $<
+%.cmx: %.ml %.cmi
+ $(OCAMLOPT) -c $<
+
+i_mathml_editor.cmo: i_mathml_editor.ml
+ $(OCAMLC) -c $<
+i_mathml_editor.cmx: i_mathml_editor.ml
+ $(OCAMLOPT) -c $<
+
+depend: *.ml *.mli
+ $(OCAMLDEP) *.ml *.mli >.depend
+include .depend
+
--- /dev/null
+
+#include <GdomeSmartDOMXSLT.hh>
+
+#include "ALogger.hh"
+#include "TDictionary.hh"
+#include "CMathMLFactoryXSLT.hh"
+#include "TPushLexer.hh"
+#include "TPushParser.hh"
+
+class CCallbackLogger : public ALogger
+{
+public:
+ CCallbackLogger(void (*)(int, const char*, void*), void*);
+ virtual ~CCallbackLogger() { };
+
+protected:
+ virtual void message(Level, const std::string&);
+
+private:
+ void (*callback)(int, const char*, void*);
+ void* user_data;
+};
+
+CCallbackLogger::CCallbackLogger(void (*cb)(int, const char*, void*), void* data) : callback(cb), user_data(data)
+{
+ assert(callback);
+}
+
+void
+CCallbackLogger::message(Level l, const std::string& s)
+{
+ assert(callback);
+ callback(l, s.c_str(), user_data);
+}
+
+struct Editor
+{
+ Editor(const DOM::Document&, const DOM::Document&, const DOM::Document&, void (*)(int, const char*, void*), void*);
+ ~Editor();
+
+ ALogger* logger;
+ TDictionary* dictionary;
+ DOMX::XSLTStylesheet* tml_mml;
+ DOMX::XSLTStylesheet* tml_tex;
+ AMathMLFactory* factory;
+ TPushParser* parser;
+ APushLexer* lexer;
+};
+
+Editor::Editor(const DOM::Document& dict, const DOM::Document& mml, const DOM::Document& tex,
+ void (*cb)(int, const char*, void*), void* data)
+{
+ assert(cb);
+ logger = new CCallbackLogger(cb, data);
+ dictionary = new TDictionary(*logger);
+ dictionary->load(DOM::Document(dict));
+ tml_mml = new DOMX::XSLTStylesheet(mml);
+ tml_tex = new DOMX::XSLTStylesheet(tex);
+ factory = new CMathMLFactoryXSLT(*logger, *tml_mml);
+ parser = new TPushParser(*logger, *factory, *dictionary);
+ lexer = new TPushLexer(*logger, *parser);
+}
+
+Editor::~Editor()
+{
+ delete lexer;
+ delete parser;
+ delete factory;
+ delete tml_tex;
+ delete tml_mml;
+ delete dictionary;
+ delete logger;
+}
+
+extern "C" Editor*
+c_mathml_editor_new(GdomeDocument* dictionary,
+ GdomeDocument* tml_mml,
+ GdomeDocument* tml_tex,
+ void (*log_message_cb)(int, const char*, void*),
+ void* user_data)
+{
+ return new Editor(DOM::Document(dictionary),
+ DOM::Document(tml_mml),
+ DOM::Document(tml_tex), log_message_cb, user_data);
+}
+
+extern "C" void
+c_mathml_editor_destroy(Editor* editor)
+{
+ assert(editor);
+ delete editor;
+}
+
+extern "C" int
+c_mathml_editor_freeze(Editor* editor)
+{
+ assert(editor);
+ return editor->parser->freeze();
+}
+
+extern "C" int
+c_mathml_editor_thaw(Editor* editor)
+{
+ assert(editor);
+ return editor->parser->thaw();
+}
+
+extern "C" void
+c_mathml_editor_push(Editor* editor, char ch)
+{
+ assert(editor);
+ editor->lexer->push(ch);
+}
+
+extern "C" void
+c_mathml_editor_drop(Editor* editor, int alt)
+{
+ assert(editor);
+ editor->lexer->drop(alt != 0);
+}
+
+extern "C" char*
+c_mathml_editor_get_tex(const Editor* editor)
+{
+ assert(editor);
+ DOM::Document res = editor->tml_tex->apply(editor->parser->document());
+ DOM::Element root = res.get_documentElement();
+ return strdup(std::string(root.get_nodeValue()).c_str());
+}
+
+extern "C" void
+c_mathml_editor_reset(Editor* editor)
+{
+ assert(editor);
+ editor->parser->reset();
+}
+
+extern "C" GdomeDocument*
+c_mathml_editor_get_tml(const Editor* editor)
+{
+ assert(editor);
+ GdomeNode* n = editor->parser->document().cloneNode(true).gdome_object();
+ GdomeDocument* doc = gdome_cast_doc(n);
+ assert(n && doc);
+ return doc;
+}
+
+extern "C" GdomeDocument*
+c_mathml_editor_get_mml(const Editor* editor)
+{
+ assert(editor);
+ GdomeNode* n = editor->factory->document().gdome_object();
+ GdomeDocument* doc = gdome_cast_doc(n);
+ assert(n && doc);
+ return doc;
+}
+
--- /dev/null
+
+#ifndef __c_mathml_editor_h__
+#define __c_mathml_editor_h__
+
+#include <gdome.h>
+
+typedef struct Editor Editor;
+
+Editor* c_mathml_editor_new(GdomeDocument*, GdomeDocument*, GdomeDocument*, void (*)(int, const char*, void*), void*);
+void c_mathml_editor_destroy(Editor*);
+int c_mathml_editor_freeze(Editor*);
+int c_mathml_editor_thaw(Editor*);
+void c_mathml_editor_reset(Editor*);
+void c_mathml_editor_push(Editor*, char);
+void c_mathml_editor_drop(Editor*, int);
+char* c_mathml_editor_get_tex(const Editor*);
+GdomeDocument* c_mathml_editor_get_tml(const Editor*);
+GdomeDocument* c_mathml_editor_get_mml(const Editor*);
+
+#endif /* __c_mathml_editor_h__ */
--- /dev/null
+
+type t
+
+external create :
+ dictionary:[> `Document] GdomeT.t ->
+ mml: [> `Document] GdomeT.t ->
+ tex: [> `Document] GdomeT.t ->
+ log:(string -> unit) ->
+ t
+ = "ml_mathml_editor_new"
+
+external freeze : editor:t -> bool
+ = "ml_mathml_editor_freeze"
+
+external thaw : editor:t -> bool
+ = "ml_mathml_editor_thaw"
+
+external reset : editor:t -> unit
+ = "ml_mathml_editor_reset"
+
+external push : editor:t -> ch:char -> unit
+ = "ml_mathml_editor_push"
+
+external drop : editor:t -> alt:bool -> unit
+ = "ml_mathml_editor_drop"
+
+external get_tex : editor:t -> string
+ = "ml_mathml_editor_get_tex"
+
+external get_tml : editor:t -> TDocument.t
+ = "ml_mathml_editor_get_tml"
+
+external get_mml : editor:t -> TDocument.t
+ = "ml_mathml_editor_get_mml"
+
--- /dev/null
+
+let create ~dictionary ~mml ~tml ~log =
+ I_mathml_editor.create dictionary#as_Document mml#as_Document tml#as_Document log
+;;
+
+let freeze = I_mathml_editor.freeze
+;;
+
+let thaw = I_mathml_editor.thaw
+;;
+
+let reset = I_mathml_editor.reset
+;;
+
+let push = I_mathml_editor.push
+;;
+
+let drop = I_mathml_editor.drop
+;;
+
+let get_tex = I_mathml_editor.get_tex
+;;
+
+let get_tml ~editor =
+ new Gdome.document (I_mathml_editor.get_tml ~editor)
+;;
+
+let get_mml ~editor =
+ new Gdome.document (I_mathml_editor.get_mml ~editor)
+;;
+
--- /dev/null
+
+#include <caml/memory.h>
+#include <caml/custom.h>
+#include <caml/callback.h>
+
+#include "mlgdomevalue.h"
+
+#include "c_mathml_editor.h"
+
+typedef struct
+{
+ Editor* c_editor;
+ value callback;
+} ml_Editor;
+
+ml_Editor*
+Editor_val(value v)
+{
+ ml_Editor* editor = (ml_Editor*) Data_custom_val(v);
+ assert(editor != NULL);
+ return editor;
+}
+
+static void
+ml_mathml_editor_finalize(value v)
+{
+ ml_Editor* editor = Editor_val(v);
+ assert(editor);
+
+ remove_global_root(&editor->callback);
+ c_mathml_editor_destroy(editor->c_editor);
+}
+
+void
+ml_mathml_editor_log_callback(int level, const char* msg, void* user_data)
+{
+ ml_Editor* ml_editor = (ml_Editor*) user_data;
+ assert(ml_editor);
+ callback2(ml_editor->callback, Val_int(level), copy_string(msg));
+}
+
+value
+ml_mathml_editor_new(value dictionary,
+ value tml_mml,
+ value tml_tex,
+ value log_message_cb)
+{
+ static struct custom_operations ops =
+ {
+ "HELM/MathML Editor",
+ ml_mathml_editor_finalize,
+ custom_compare_default,
+ custom_hash_default,
+ custom_serialize_default,
+ custom_deserialize_default
+ };
+
+ value v = alloc_custom(&ops, sizeof(ml_Editor), 0, 1);
+ ml_Editor* ml_editor = (ml_Editor*) Data_custom_val(v);
+ ml_editor->c_editor = c_mathml_editor_new(Document_val(dictionary),
+ Document_val(tml_mml),
+ Document_val(tml_tex),
+ ml_mathml_editor_log_callback,
+ (void*) ml_editor);
+ ml_editor->callback = log_message_cb;
+ register_global_root(&ml_editor->callback);
+
+ return v;
+}
+
+value
+ml_mathml_editor_freeze(value v)
+{
+ CAMLparam1(v);
+ ml_Editor* editor = Editor_val(v);
+ CAMLreturn(Val_bool(c_mathml_editor_freeze(editor->c_editor)));
+}
+
+value
+ml_mathml_editor_thaw(value v)
+{
+ CAMLparam1(v);
+ ml_Editor* editor = Editor_val(v);
+ CAMLreturn(Val_bool(c_mathml_editor_thaw(editor->c_editor)));
+}
+
+value
+ml_mathml_editor_push(value v, value ch)
+{
+ CAMLparam2(v, ch);
+ ml_Editor* editor = Editor_val(v);
+ c_mathml_editor_push(editor->c_editor, Int_val(ch));
+ CAMLreturn(Val_unit);
+}
+
+value
+ml_mathml_editor_drop(value v, value alt)
+{
+ CAMLparam2(v, alt);
+ ml_Editor* editor = Editor_val(v);
+ c_mathml_editor_drop(editor->c_editor, Bool_val(alt));
+ CAMLreturn(Val_unit);
+}
+
+value
+ml_mathml_editor_get_tex(value v)
+{
+ CAMLparam1(v);
+ ml_Editor* editor = Editor_val(v);
+ char* res = c_mathml_editor_get_tex(editor->c_editor);
+ CAMLlocal1(ml_res);
+ ml_res = copy_string(res);
+ free(res);
+ CAMLreturn(ml_res);
+}
+
+value
+ml_mathml_editor_reset(value v, value s)
+{
+ CAMLparam1(v);
+ ml_Editor* editor = Editor_val(v);
+ c_mathml_editor_reset(editor->c_editor);
+ CAMLreturn(Val_unit);
+}
+
+value
+ml_mathml_editor_get_tml(value v)
+{
+ CAMLparam1(v);
+ ml_Editor* editor = Editor_val(v);
+ GdomeDocument* doc = c_mathml_editor_get_tml(editor->c_editor);
+ CAMLreturn(Val_Document(doc));
+}
+
+value
+ml_mathml_editor_get_mml(value v)
+{
+ CAMLparam1(v);
+ ml_Editor* editor = Editor_val(v);
+ GdomeDocument* doc = c_mathml_editor_get_mml(editor->c_editor);
+ CAMLreturn(Val_Document(doc));
+}
+
class AMathMLFactory
{
public:
- AMathMLFactory(class ALogger& l) : logger(l), consumer(0) { };
- AMathMLFactory(class ALogger& l, class AMathMLConsumer& c) : logger(l), consumer(&c) { };
+ AMathMLFactory(class ALogger& l) : logger(l) { };
virtual ~AMathMLFactory() { };
+ virtual void reset(void) = 0;
virtual void documentModified(class TDocument&) = 0;
virtual DOM::Document document(void) const = 0;
protected:
class ALogger& logger;
- class AMathMLConsumer* consumer;
};
#endif // __AMathMLFactory_hh__
virtual ~APushLexer() { };
virtual void push(char) = 0;
+ virtual void drop(bool = false) = 0;
virtual void reset(void) = 0;
virtual bool error(void) const = 0;
--- /dev/null
+
+#include "APushParser.hh"
+#include "AMathMLFactory.hh"
+
+void
+APushParser::reset()
+{
+ if (factory) factory->reset();
+}
+
+bool
+APushParser::freeze()
+{
+ return freeze_level++ == 0;
+}
+
+bool
+APushParser::thaw()
+{
+ if (freeze_level > 0)
+ return --freeze_level == 0;
+ else
+ return true;
+}
#ifndef __APushParser_hh__
#define __APushParser_hh__
+#include <string>
+
class APushParser
{
public:
- APushParser(class ALogger& l) : logger(l), factory(0) { };
- APushParser(class ALogger& l, class AMathMLFactory& f) : logger(l), factory(&f) { };
-
+ APushParser(class ALogger& l) : logger(l), factory(0), freeze_level(0) { };
+ APushParser(class ALogger& l, class AMathMLFactory& f) : logger(l), factory(&f), freeze_level(0) { };
virtual ~APushParser() { };
- virtual void push(const TToken&) = 0;
+
+ virtual void reset(void);
+ virtual void push(const class TToken&) = 0;
+ virtual std::string drop(void) = 0;
virtual void setCursorHint(const std::string&) = 0;
+ virtual bool freeze(void);
+ virtual bool thaw(void);
+ bool frozen(void) const { return freeze_level > 0; };
+
protected:
class ALogger& logger;
class AMathMLFactory* factory;
+
+private:
+ unsigned freeze_level;
};
#endif // __APushParser_hh__
#include "CMathMLFactoryXSLT.hh"
#include "AMathMLConsumer.hh"
+CMathMLFactoryXSLT::CMathMLFactoryXSLT(ALogger& l, const DOMX::XSLTStylesheet& s)
+ : AMathMLFactory(l), style(s)
+{
+ reset();
+}
+
+void
+CMathMLFactoryXSLT::reset()
+{
+ DOM::DOMImplementation di;
+ DOM::DocumentType dt;
+ result = di.createDocument(MATHML_NS_URI, "m:math", dt);
+}
+
void
CMathMLFactoryXSLT::documentModified(TDocument& doc)
{
if (TNode dirty = doc.dirtyNode())
{
std::vector< std::pair<DOM::GdomeString, DOM::GdomeString> > dirtyId;
- if (result)
+ if (result.get_documentElement().hasAttribute("xref"))
dirtyId.push_back(std::make_pair(DOM::GdomeString("id"),
DOM::GdomeString("'" + std::string(dirty["id"]) + "'")));
DOM::Document res = style.apply(doc.document(), dirtyId);
assert(res);
- //style.save(doc.document(), stdout);
- //style.save(res, stdout);
- if (result)
- {
- DOM::Element root = res.get_documentElement();
- assert(root);
- assert(root.hasAttribute("xref"));
+ style.save(doc.document(), stdout);
+
+ DOM::Element root = res.get_documentElement();
+ assert(root);
+ assert(root.hasAttribute("xref"));
- try
- {
- bool ok = subst(result.get_documentElement(), root.getAttribute("xref"), result.importNode(root, true));
- assert(ok);
- }
- catch (DOM::DOMException& e)
- {
- cout << "!!!!!!!!!!!!!!!! EXCEPTION " << e.code << " " << e.msg << endl;
- assert(0);
- }
+ if (result.get_documentElement().hasAttribute("xref"))
+ {
+ bool ok = subst(result.get_documentElement(), root.getAttribute("xref"), result.importNode(root, true));
+ assert(ok);
}
else
- result = res;
+ result.replaceChild(result.importNode(root, true), result.get_documentElement());
+
+ style.save(result, stdout);
doc.clearDirty();
-
- if (consumer) consumer->documentModified(result);
}
}
#ifndef __CMathMLFactoryXSLT_hh__
#define __CMathMLFactoryXSLT_hh__
+#include <GdomeSmartDOM.hh>
#include "AMathMLFactory.hh"
class CMathMLFactoryXSLT : public AMathMLFactory
{
public:
- CMathMLFactoryXSLT(class ALogger& l, const DOM::XSLTStylesheet& s) : AMathMLFactory(l), style(s) { };
- CMathMLFactoryXSLT(class ALogger& l, class AMathMLConsumer& c, const DOM::XSLTStylesheet& s) : AMathMLFactory(l, c), style(s) { };
+ CMathMLFactoryXSLT(class ALogger&, const class GdomeSmartDOMExt::XSLTStylesheet&);
+ virtual void reset(void);
virtual void documentModified(class TDocument&);
- virtual DOM::Document document(void) const { return result; };
+ virtual GdomeSmartDOM::Document document(void) const { return result; };
private:
- static bool subst(const DOM::Element& e1, const DOM::GdomeString& id, const DOM::Element& e2);
+ static bool subst(const GdomeSmartDOM::Element&, const GdomeSmartDOM::GdomeString&, const GdomeSmartDOM::Element&);
- const DOM::XSLTStylesheet& style;
- DOM::Document result;
+ const class GdomeSmartDOMExt::XSLTStylesheet& style;
+ GdomeSmartDOM::Document result;
};
#endif // __CMathMLFactoryXSLT_hh__
--- /dev/null
+
+#include "dom.hh"
+#include "Diff.hh"
+#include "TNode.hh"
+#include "TDocument.hh"
+#include "CMathMLFactoryXSLTDiff.hh"
+#include "AMathMLConsumer.hh"
+
+CMathMLFactoryXSLTDiff::CMathMLFactoryXSLTDiff(ALogger& l, const DOMX::XSLTStylesheet& s)
+ : AMathMLFactory(l), style(s)
+{
+ reset();
+}
+
+void
+CMathMLFactoryXSLTDiff::reset()
+{
+ DOM::DOMImplementation di;
+ DOM::DocumentType dt;
+ result = di.createDocument(MATHML_NS_URI, "m:math", dt);
+}
+
+void
+CMathMLFactoryXSLTDiff::documentModified(TDocument& doc)
+{
+ if (TNode dirty = doc.dirtyNode())
+ {
+ std::vector< std::pair<DOM::GdomeString, DOM::GdomeString> > dirtyId;
+ if (false && result.get_documentElement().hasAttribute("xref"))
+ dirtyId.push_back(std::make_pair(DOM::GdomeString("id"),
+ DOM::GdomeString("'" + std::string(dirty["id"]) + "'")));
+ DOM::Document res = style.apply(doc.document(), dirtyId);
+ assert(res);
+ //cout << "*** THE DIRTY FRAGMENT HAS ID = " << std::string(dirty["id"]) << endl;
+ //style.save(doc.document(), stdout);
+ cout << "*** THE CURRENT DOCUMENT:" << endl;
+ if (result) style.save(result, stdout);
+ cout << "*** THE NEW DOCUMENT:" << endl;
+ style.save(res, stdout);
+ cout << "*** THE DIFF:" << endl;
+ DOMX::Diff diff = DOMX::Diff::diff(result, res);
+ style.save(diff.document(), stdout);
+ diff.patch();
+#if 0
+ DOM::Element root = res.get_documentElement();
+ assert(root);
+ assert(root.hasAttribute("xref"));
+ if (result.get_documentElement().hasAttribute("xref"))
+ {
+ bool ok = subst(result.get_documentElement(), root.getAttribute("xref"), result.importNode(root, true));
+ assert(ok);
+ }
+ else
+ result = res;
+#endif
+ //style.save(result, stdout);
+
+ doc.clearDirty();
+ }
+}
+
+bool
+CMathMLFactoryXSLTDiff::subst(const DOM::Element& e1, const DOM::GdomeString& id, const DOM::Element& e2)
+{
+ assert(e1);
+ assert(e2);
+ if (e1.getAttribute("xref") == id)
+ {
+ DOMX::Diff diff = DOMX::Diff::diff(e1, e2);
+ style.save(diff.document(), stdout);
+ diff.patch();
+ return true;
+ }
+ else
+ {
+ DOM::Node p = e1.get_firstChild();
+ while (p)
+ {
+ while (p && p.get_nodeType() != DOM::Node::ELEMENT_NODE) p = p.get_nextSibling();
+ if (p)
+ if (subst(p, id, e2)) return true;
+ else p = p.get_nextSibling();
+ }
+ return false;
+ }
+}
+
--- /dev/null
+
+#ifndef __CMathMLFactoryXSLTDiff_hh__
+#define __CMathMLFactoryXSLTDiff_hh__
+
+#include "AMathMLFactory.hh"
+
+class CMathMLFactoryXSLTDiff : public AMathMLFactory
+{
+public:
+ CMathMLFactoryXSLTDiff(class ALogger&, const DOMX::XSLTStylesheet&);
+
+ virtual void reset(void);
+ virtual void documentModified(class TDocument&);
+ virtual DOM::Document document(void) const { return result; };
+
+private:
+ bool subst(const DOM::Element& e1, const DOM::GdomeString& id, const DOM::Element& e2);
+
+ const DOMX::XSLTStylesheet& style;
+ DOM::Document result;
+};
+
+#endif // __CMathMLFactoryXSLT_hh__
--- /dev/null
+
+#include <sstream>
+#include <functional>
+#include <vector>
+#include <algorithm>
+
+#include "Diff.hh"
+
+namespace GdomeSmartDOMExt
+{
+
+ Diff
+ Diff::diff(const Document& dest, const Document& source, flatNodeEq flatEq)
+ {
+ assert(dest);
+ assert(source);
+ assert(flatEq);
+
+ return diff(dest.get_documentElement(), source.get_documentElement(), flatEq);
+ }
+
+ Diff
+ Diff::diff(const Element& dest, const Element& source, flatNodeEq flatEq)
+ {
+ assert(dest);
+ assert(source);
+ assert(flatEq);
+
+ DOMImplementation di;
+ Document doc = di.createDocument(DDIFF_NS_URI, "diff:doc", DocumentType());
+ Element root = doc.get_documentElement();
+ root.setAttributeNS(XMLNS_NS_URI, "xmlns:diff", DDIFF_NS_URI);
+
+ Diff diff(dest, doc, flatEq);
+ if (Node d = diff.diffNodes(dest, source)) root.appendChild(d);
+ else root.appendChild(doc.createElementNS(DDIFF_NS_URI, "diff:same"));
+
+ return diff;
+ }
+
+ struct NodeEqPredicate : std::binary_function<Node,Node,bool>
+ {
+ NodeEqPredicate(Diff::flatNodeEq e) : eq(e) { };
+ bool operator()(const Node& n1, const Node& n2) const { return eq(n1, n2); };
+
+ private:
+ Diff::flatNodeEq eq;
+ };
+
+ std::vector<Node>
+ collectProperAttributes(const Node& n)
+ {
+ assert(n);
+ NamedNodeMap map = n.get_attributes();
+ unsigned len = map.get_length();
+
+ std::vector<Node> res;
+ res.reserve(len);
+ for (unsigned i = 0; i < len; i++)
+ {
+ Node attr = map.item(i);
+ assert(attr);
+ if (attr.get_nodeName() != "xmlns" && attr.get_prefix() != "xmlns") res.push_back(attr);
+ }
+
+ return res;
+ }
+
+ bool
+ Diff::defaultFlatNodeEq(const Node& n1, const Node& n2)
+ {
+ assert(n1);
+ assert(n2);
+
+ unsigned nodeType = n1.get_nodeType();
+ if (nodeType != n2.get_nodeType()) return false;
+
+ GdomeString ns1 = n1.get_namespaceURI();
+ GdomeString ns2 = n2.get_namespaceURI();
+ if (ns1 != ns2) return false;
+
+ switch (nodeType)
+ {
+ case Node::ATTRIBUTE_NODE:
+ if (!ns1.null())
+ {
+ assert(!ns2.null());
+ if (n1.get_localName() != n2.get_localName()) return false;
+ }
+ else
+ {
+ assert(ns2.null());
+ if (n1.get_nodeName() != n2.get_nodeName()) return false;
+ }
+ // WARNING: fallback for checking node value
+ case Node::TEXT_NODE:
+ case Node::CDATA_SECTION_NODE:
+ if (n1.get_nodeValue() != n2.get_nodeValue()) return false;
+ return true;
+ case Node::ELEMENT_NODE:
+ {
+ //cout << "comparing: " << n1.get_nodeName() << " ? " << n2.get_nodeName() << endl;
+ if (!ns1.null())
+ {
+ assert(!ns2.null());
+ if (n1.get_localName() != n2.get_localName()) return false;
+ }
+ else
+ {
+ assert(ns2.null());
+ if (n1.get_nodeName() != n2.get_nodeName()) return false;
+ }
+#if 1
+ std::vector<Node> m1 = collectProperAttributes(n1);
+ std::vector<Node> m2 = collectProperAttributes(n2);
+ if (m1.size() != m2.size()) return false;
+
+ for (unsigned i = 0; i < m1.size(); i++)
+ {
+ std::vector<Node>::iterator p2 = std::find_if(m2.begin(), m2.end(), std::bind2nd(NodeEqPredicate(defaultFlatNodeEq), m1[i]));
+ if (p2 == m2.end()) return false;
+ }
+#endif
+ }
+ return true;
+ default:
+ return true;
+ }
+
+ }
+
+ void
+ Diff::sameChunk(const Node& res, unsigned long n) const
+ {
+ assert(n > 0);
+ Element s = doc.createElementNS(DDIFF_NS_URI, "diff:same");
+ if (n != 1)
+ {
+ std::ostringstream os;
+ os << n;
+ s.setAttribute("count", os.str());
+ }
+ res.appendChild(s);
+ }
+
+ Node
+ Diff::diffNodes(const Node& p1, const Node& p2) const
+ {
+ if (eq(p1, p2))
+ {
+ Element m = doc.createElementNS(DDIFF_NS_URI, "diff:merge");
+ if (diffChildren(p1, p2, m)) return m;
+ else return Node();
+ }
+ else
+ {
+ Element r = doc.createElementNS(DDIFF_NS_URI, "diff:replace");
+ r.appendChild(doc.importNode(p2, true));
+ return r;
+ }
+ }
+
+ bool
+ Diff::diffChildren(const Node& n1, const Node& n2, const Node& res) const
+ {
+ assert(n1);
+ assert(n2);
+ assert(res);
+
+ Node p1 = n1.get_firstChild();
+ Node p2 = n2.get_firstChild();
+ bool same = true;
+ unsigned nSame = 0;
+ while (p1 && p2)
+ {
+ if (Node d = diffNodes(p1, p2))
+ {
+ same = false;
+ if (nSame > 0)
+ {
+ sameChunk(res, nSame);
+ nSame = 0;
+ }
+ res.appendChild(d);
+ }
+ else
+ nSame++;
+
+ p1 = p1.get_nextSibling();
+ p2 = p2.get_nextSibling();
+ }
+
+ if (p1)
+ {
+ same = false;
+ if (nSame > 0)
+ {
+ sameChunk(res, nSame);
+ nSame = 0;
+ }
+
+ unsigned nRemoved = 0;
+ while (p1)
+ {
+ nRemoved++;
+ p1 = p1.get_nextSibling();
+ }
+
+ if (nRemoved > 0)
+ {
+ Element r = doc.createElementNS(DDIFF_NS_URI, "diff:remove");
+ if (nRemoved > 1)
+ {
+ std::ostringstream os;
+ os << nRemoved;
+ r.setAttribute("count", os.str());
+ }
+ res.appendChild(r);
+ }
+ }
+
+ if (p2)
+ {
+ same = false;
+ if (nSame > 0)
+ {
+ sameChunk(res, nSame);
+ nSame = 0;
+ }
+
+ Element i = doc.createElementNS(DDIFF_NS_URI, "diff:insert");
+ while (p2)
+ {
+ i.appendChild(doc.importNode(p2, true));
+ p2 = p2.get_nextSibling();
+ }
+ res.appendChild(i);
+ }
+
+ return !same;
+ }
+
+ static Node
+ getFirstElement(const Node& n)
+ {
+ Node p = n.get_firstChild();
+ while (p && p.get_nodeType() != Node::ELEMENT_NODE)
+ p = p.get_nextSibling();
+ return p;
+ }
+
+ static Node
+ getNextElement(const Node& n)
+ {
+ Node p = n.get_nextSibling();
+ while (p && p.get_nodeType() != Node::ELEMENT_NODE)
+ p = p.get_nextSibling();
+ return p;
+ }
+
+ void
+ Diff::patchRootNode(const Node& node, const Element& elem) const
+ {
+ GdomeString name = elem.get_localName();
+ if (name == "same")
+ {
+ if (elem.hasAttribute("count"))
+ {
+ unsigned count;
+ istringstream is(elem.getAttribute("count"));
+ is >> count;
+ assert(count == 1);
+ }
+ }
+ else if (name == "replace")
+ {
+ Document d1 = node.get_ownerDocument();
+ Node parent = node.get_parentNode();
+ assert(parent);
+#if 0
+ /* the following patch is because of gdome2 bug that prevents from
+ * replacing the root element of a document.
+ */
+ assert(!node.get_previousSibling());
+ assert(!node.get_nextSibling());
+ parent.removeChild(node);
+ parent.appendChild(d1.importNode(getFirstElement(elem), true));
+#endif
+ parent.replaceChild(d1.importNode(getFirstElement(elem), true), node);
+ }
+ else if (name == "merge")
+ patchChildren(node, elem);
+ else
+ assert(0);
+ }
+
+ void
+ Diff::patchChildren(const Node& n1, const Element& e2) const
+ {
+ Node p1 = n1.get_firstChild();
+ Element p2 = getFirstElement(e2);
+ while (p2)
+ {
+ GdomeString name = p2.get_localName();
+ if (name == "same")
+ {
+ unsigned count = 1;
+ if (p2.hasAttribute("count"))
+ {
+ istringstream is(p2.getAttribute("count"));
+ is >> count;
+ }
+ while (count-- > 0)
+ {
+ if (!p1) throw BADDiff("too few nodes in original document (same)");
+ p1 = p1.get_nextSibling();
+ }
+ }
+ else if (name == "replace")
+ {
+ Document d1 = n1.get_ownerDocument();
+ if (!p1) throw BADDiff("no node to replace in original document");
+ Node next = p1.get_nextSibling();
+ n1.replaceChild(d1.importNode(p2.get_firstChild(), true), p1);
+ p1 = next;
+ }
+ else if (name == "insert")
+ {
+ Document d1 = n1.get_ownerDocument();
+ for (Node i = p2.get_firstChild(); i; i = i.get_nextSibling())
+ n1.insertBefore(d1.importNode(i, true), p1);
+ }
+ else if (name == "merge")
+ {
+ if (!p1) throw BADDiff("no node to merge in original document");
+ patchChildren(p1, p2);
+ p1 = p1.get_nextSibling();
+ }
+ else if (name == "remove")
+ {
+ unsigned count = 1;
+ if (p2.hasAttribute("count"))
+ {
+ istringstream is(p2.getAttribute("count"));
+ is >> count;
+ }
+ while (count-- > 0)
+ {
+ if (!p1) throw BADDiff("too few nodes in original document (remove)");
+ Node next = p1.get_nextSibling();
+ n1.removeChild(p1);
+ p1 = next;
+ }
+ }
+ else
+ assert(0);
+
+ p2 = getNextElement(p2);
+ }
+ }
+
+ void
+ Diff::patch() const
+ {
+ patchRootNode(dest, getFirstElement(doc.get_documentElement()));
+ }
+
+}
--- /dev/null
+
+#ifndef __Diff_hh__
+#define __Diff_hh__
+
+#include <GdomeSmartDOM.hh>
+
+#define XMLNS_NS_URI "http://www.w3.org/2000/xmlns/"
+#define DDIFF_NS_URI "http://helm.cs.unibo.it/2002/DDIFF"
+
+namespace GdomeSmartDOMExt
+{
+
+ using namespace GdomeSmartDOM;
+
+ class Diff
+ {
+ public:
+ typedef bool (*flatNodeEq)(const Node&, const Node&);
+ static bool defaultFlatNodeEq(const Node&, const Node&);
+
+ private:
+ Diff(const Node& n, const Document& d, flatNodeEq e) : dest(n), doc(d), eq(e) { };
+
+ public:
+ static Diff diff(const Document&, const Document&, flatNodeEq = defaultFlatNodeEq);
+ static Diff diff(const Element&, const Element&, flatNodeEq = defaultFlatNodeEq);
+
+ Document document(void) const { return doc; };
+ Node node(void) const { return dest; };
+
+ void patch(void) const;
+
+ struct BADDiff
+ {
+ BADDiff(const std::string& s) : msg(s) { };
+ const std::string msg;
+ };
+
+ private:
+ Node diffNodes(const Node&, const Node&) const;
+ bool diffChildren(const Node&, const Node&, const Node&) const;
+ void sameChunk(const Node&, unsigned long) const;
+ void patchRootNode(const Node&, const Element&) const;
+ void patchChildren(const Node&, const Element&) const;
+
+ Document doc;
+ Node dest;
+ flatNodeEq eq;
+ };
+
+}
+
+#endif // __ddiff_hh__
libeditex_la_LDFLAGS = -version-info @EDITEX_VERSION_INFO@
libeditex_la_SOURCES = \
+ Diff.cc \
CLoggerConsole.cc \
TPushLexer.cc \
+ APushParser.cc \
TPushParser.cc \
CMathMLFactoryXSLT.cc \
+ CMathMLFactoryXSLTDiff.cc \
TDictionary.cc \
TDocument.cc \
TNode.cc \
TTokenizer.cc
pkginclude_HEADERS = \
+ Diff.hh \
ALogger.hh \
CLoggerConsole.hh \
APushLexer.hh \
APushParser.hh \
AMathMLFactory.hh \
CMathMLFactoryXSLT.hh \
+ CMathMLFactoryXSLTDiff.hh \
TPushLexer.hh \
TPushParser.hh \
TTokenizer.hh \
GMETADOM_LIBS = @GMETADOM_LIBS@
GTKMATHVIEW_CFLAGS = @GTKMATHVIEW_CFLAGS@
GTKMATHVIEW_LIBS = @GTKMATHVIEW_LIBS@
+HAVE_OCAMLC = @HAVE_OCAMLC@
+HAVE_OCAMLDEP = @HAVE_OCAMLDEP@
+HAVE_OCAMLFIND = @HAVE_OCAMLFIND@
+HAVE_OCAMLMKLIB = @HAVE_OCAMLMKLIB@
+HAVE_OCAMLOPT = @HAVE_OCAMLOPT@
LDFLAGS = @LDFLAGS@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
MAKEINFO = @MAKEINFO@
+MLGDOME_CFLAGS = @MLGDOME_CFLAGS@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OCAMLC = @OCAMLC@
+OCAMLDEP = @OCAMLDEP@
+OCAMLFIND = @OCAMLFIND@
+OCAMLMKLIB = @OCAMLMKLIB@
+OCAMLOPT = @OCAMLOPT@
+OCAMLSTDLIBDIR = @OCAMLSTDLIBDIR@
+OCAMLSTUBDIR = @OCAMLSTUBDIR@
+OCAML_INCLUDE_DIR = @OCAML_INCLUDE_DIR@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
STRIP = @STRIP@
libeditex_la_LDFLAGS = -version-info @EDITEX_VERSION_INFO@
-libeditex_la_SOURCES = CLoggerConsole.cc TPushLexer.cc TPushParser.cc CMathMLFactoryXSLT.cc TDictionary.cc TDocument.cc TNode.cc TTokenizer.cc
+libeditex_la_SOURCES = Diff.cc CLoggerConsole.cc TPushLexer.cc APushParser.cc TPushParser.cc CMathMLFactoryXSLT.cc CMathMLFactoryXSLTDiff.cc TDictionary.cc TDocument.cc TNode.cc TTokenizer.cc
-pkginclude_HEADERS = ALogger.hh CLoggerConsole.hh APushLexer.hh APushParser.hh AMathMLFactory.hh CMathMLFactoryXSLT.hh TPushLexer.hh TPushParser.hh TTokenizer.hh TDictionary.hh TDocument.hh TNode.hh TListener.hh dom.hh
+pkginclude_HEADERS = Diff.hh ALogger.hh CLoggerConsole.hh APushLexer.hh APushParser.hh AMathMLFactory.hh CMathMLFactoryXSLT.hh CMathMLFactoryXSLTDiff.hh TPushLexer.hh TPushParser.hh TTokenizer.hh TDictionary.hh TDocument.hh TNode.hh TListener.hh dom.hh
INCLUDES = $(GMETADOM_CFLAGS) $(GDOMEXSLT_CFLAGS)
DEFS = @DEFS@ -I. -I$(srcdir) -I..
LIBS = @LIBS@
libeditex_la_LIBADD =
-libeditex_la_OBJECTS = CLoggerConsole.lo TPushLexer.lo TPushParser.lo \
-CMathMLFactoryXSLT.lo TDictionary.lo TDocument.lo TNode.lo \
+libeditex_la_OBJECTS = Diff.lo CLoggerConsole.lo TPushLexer.lo \
+APushParser.lo TPushParser.lo CMathMLFactoryXSLT.lo \
+CMathMLFactoryXSLTDiff.lo TDictionary.lo TDocument.lo TNode.lo \
TTokenizer.lo
CXXFLAGS = @CXXFLAGS@
CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
TAR = tar
GZIP_ENV = --best
-DEP_FILES = .deps/CLoggerConsole.P .deps/CMathMLFactoryXSLT.P \
+DEP_FILES = .deps/APushParser.P .deps/CLoggerConsole.P \
+.deps/CMathMLFactoryXSLT.P .deps/CMathMLFactoryXSLTDiff.P .deps/Diff.P \
.deps/TDictionary.P .deps/TDocument.P .deps/TNode.P .deps/TPushLexer.P \
.deps/TPushParser.P .deps/TTokenizer.P
SOURCES = $(libeditex_la_SOURCES)
static TDictionary::Entry undefinedEntry;
void
-TDictionary::load(const char* uri)
+TDictionary::load(const std::string& uri)
{
+ logger.debug("Dictionary: loading `" + uri + "'");
+
DOM::DOMImplementation di;
+ DOM::Document doc = di.createDocumentFromURI(uri.c_str());
+ assert(doc);
+ load(doc);
+}
- DOM::Document doc = di.createDocumentFromURI(uri);
+void
+TDictionary::load(const DOM::Document& doc)
+{
assert(doc);
DOM::Element root = doc.get_documentElement();
TTokenizer tokenizer(logger);
for (DOM::Node p = root.get_firstChild(); p; p = p.get_nextSibling())
- if (p.get_nodeType() == DOM::Node::ELEMENT_NODE && p.get_nodeName() == "entry")
+ if (p.get_nodeType() == DOM::Node::ELEMENT_NODE && p.get_nodeName() == "include")
+ {
+ DOM::Element el = p;
+ assert(el);
+ if (el.hasAttribute("href"))
+ // WARNING: this may result into an infinite loop!
+ load(std::string(el.getAttribute("href")));
+ else
+ logger.warning("Dictionary: include statement with no href attribute (ignored)");
+ }
+ else if (p.get_nodeType() == DOM::Node::ELEMENT_NODE && p.get_nodeName() == "entry")
{
DOM::Element el = p;
assert(el);
std::string name = el.getAttribute("name");
if (entries.find(name) != entries.end())
- cerr << "WARNING: entry `" << name << "' is being redefined" << endl;
+ logger.info("Dictionary: `" + name + "' is being redefined");
Entry entry;
{
entry.value = el.getAttribute("val");
if (entry.cls == MACRO)
- cerr << "WARNING: `" << name << "' has a specified value, but is classified as macro" << endl;
+ logger.warning("Dictionary: `" + name + "' has a specified value, but is classified as macro");
}
if (el.hasAttribute("pattern"))
{
if (entry.cls != MACRO)
- cerr << "WARNING: `" << name << "' has a specified pattern, but is not classified as macro" << endl;
+ logger.warning("Dictionary: `" + name + "' has a specified pattern, but is not classified as macro");
std::string pattern = el.getAttribute("pattern");
if (pattern == "{}")
entry.pattern = tokenizer.tokenize(pattern);
}
+#if 0
if (el.hasAttribute("infix"))
{
std::istringstream is(el.getAttribute("infix"));
if (!el.hasAttribute("prefix")) entry.prefix = postfix;
}
}
+#endif
if (el.hasAttribute("limits"))
{
if (el.hasAttribute("delimiter"))
{
if (entry.cls != OPERATOR && !entry.embellishment)
- cerr << "WARNING: `" << name << "' delimiter ignored for non-operator" << endl;
+ logger.warning("Dictionary: `" + name + "' delimiter ignored for non-operator");
std::istringstream is(el.getAttribute("delimiter"));
unsigned delimiter;
if (el.hasAttribute("table"))
{
if (entry.cls != MACRO)
- cerr << "WARNING: `" << name << "' table ignored for non-macro" << endl;
+ logger.warning("Dictionary: `" + name + "' table ignored for non-macro");
std::istringstream is(el.getAttribute("table"));
unsigned table;
#ifndef __TDictionary_hh__
#define __TDictionary_hh__
+#include <config.h>
+
#include <string>
#include <vector>
#include <hash_map>
+#include "dom.hh"
#include "TToken.hh"
class TDictionary
{
public:
- TDictionary(void) { };
+ TDictionary(class ALogger& l) : logger(l) { };
~TDictionary() { };
enum Form
Entry(void)
{
cls = UNDEFINED;
- infix = prefix = postfix = 0;
table = delimiter = limits = embellishment = leftOpen = rightOpen = 0;
};
unsigned previousParam(unsigned) const;
EntryClass cls;
- unsigned infix : 8;
- unsigned prefix : 8;
- unsigned postfix : 8;
unsigned delimiter : 1;
unsigned limits : 1;
unsigned embellishment : 1;
unsigned table : 1;
};
- void load(const char* uri);
+ void load(const std::string& uri);
+ void load(const DOM::Document& doc);
const Entry& find(const std::string&) const;
private:
{ bool operator()(const std::string&, const class String*) const; };
#endif
+ class ALogger& logger;
+#if defined(HAVE_EXT_HASH_MAP)
+ typedef __gnu_cxx::hash_map< std::string, Entry, StringHash > Dictionary;
+#elif defined(HAVE_HASH_MAP)
typedef std::hash_map< std::string, Entry, StringHash > Dictionary;
+#else
+#error "no hash_map could be found"
+#endif
Dictionary entries;
};
di.saveDocumentToFile(doc, filename, GDOME_SAVE_LIBXML_INDENT);
}
+std::string
+TDocument::makeId(unsigned id)
+{
+ ostringstream os;
+ os << "I" << id;
+ return os.str();
+}
+
TNode
TDocument::create(const std::string& name, unsigned id) const
{
DOM::Element elem = doc.createElementNS(TML_NS_URI, "tml:" + name);
- if (id > 0)
- {
- ostringstream os;
- os << "I" << id;
- elem.setAttribute("id", os.str());
- }
+ if (id > 0) elem.setAttribute("id", makeId(id));
return elem;
}
return DOM::Node(0);
}
+TNode
+TDocument::getNodeByIdAux(const TNode& node, const std::string& id)
+{
+ if (node.hasId(id)) return node;
+ else
+ for (TNode p = node.first(); p; p = p.next())
+ if (TNode res = getNodeByIdAux(p, id)) return res;
+ return TNode();
+}
+
+TNode
+TDocument::getNodeById(unsigned id) const
+{
+ DOM::Element root = doc.get_documentElement();
+ assert(root);
+ return getNodeByIdAux(root, makeId(id));
+}
+
void
TDocument::handleEvent(const DOM::Event& ev)
{
DOM::Document document(void) const { return doc; };
+ TNode getNodeById(unsigned) const;
TNode root(void) { return doc.get_documentElement(); };
TNode dirtyNode(void) const { return dirty; };
void clearDirty(void) { dirty = DOM::Element(0); };
DOM::Element dirty;
virtual void handleEvent(const DOM::Event&);
+ static std::string makeId(unsigned);
+ static TNode getNodeByIdAux(const TNode&, const std::string&);
static unsigned nodeDepth(const DOM::Node&);
static DOM::Node findCommonAncestor(const DOM::Node&, const DOM::Node&);
static DOM::Node findIdNode(const DOM::Node&);
std::string name(void) const { return node.get_localName(); };
std::string nameC(void) const { return node.getAttribute("name"); };
bool hasId(void) const { return node.hasAttribute("id"); };
+ bool hasId(const std::string& id) const { return node.getAttribute("id") == id; };
bool is(const std::string& s) const { return name() == s; };
bool isG(void) const { return is("g"); };
bool isSb(void) const { return is("sb"); };
case ACCEPT:
if (ch == '\\') state = ESCAPE;
else if (ch == '#') state = PARAMETER;
- else if (ch == '\b') parser.push(TToken(TToken::GDELETE));
else if (ch == -1) ;
else transaction(ch, ACCEPT);
break;
buffer.push_back(ch);
state = MACRO;
}
- else if (ch == '\b')
- {
- state = ACCEPT;
- }
else if (ch == -1) error();
else
{
buffer.erase();
state = PARAMETER;
}
- else if (ch == '\b')
- {
- buffer.erase(buffer.length() - 1, 1);
- if (buffer.length() == 0) state = ESCAPE;
- }
else if (isalpha(ch))
buffer.push_back(ch);
else if (ch == -1)
if (ch == '\\') state = ESCAPE;
else if (ch == '#') state = PARAMETER;
else if (isspace(ch)) ;
- else if (ch == '\b') parser.push(TToken(TToken::GDELETE));
else if (ch == -1) state = ACCEPT;
else transaction(ch, ACCEPT);
break;
}
}
+void
+TPushLexer::drop(bool alt)
+{
+ std::string restore = "";
+
+ switch (state)
+ {
+ case ACCEPT:
+ case IGNORE_SPACE:
+ restore = parser.drop();
+ if (restore.length() > 0 && restore[0] == '\\')
+ {
+ buffer = std::string(restore, 1, restore.length() - 1);
+ state = (buffer.length() > 0) ? MACRO : ESCAPE;
+ }
+ break;
+ case ESCAPE:
+ state = ACCEPT;
+ break;
+ case MACRO:
+ if (alt) buffer.erase();
+ else buffer.erase(buffer.length() - 1, 1);
+ if (buffer.length() == 0) state = ESCAPE;
+ break;
+ case PARAMETER:
+ default:
+ assert(0);
+ break;
+ }
+
+ switch (state)
+ {
+ case ESCAPE: parser.setCursorHint("\\"); break;
+ case MACRO: parser.setCursorHint("\\" + buffer); break;
+ case PARAMETER: parser.setCursorHint("#"); break;
+ default: parser.setCursorHint(""); break;
+ }
+}
+
bool
TPushLexer::error() const
{
virtual ~TPushLexer() { };
virtual void push(char);
+ virtual void drop(bool = false);
virtual void reset(void);
virtual void flush(void);
virtual bool error(void) const;
TPushParser::TPushParser(ALogger& l, const TDictionary& d) : APushParser(l), dictionary(d)
{
- init();
+ reset();
}
TPushParser::TPushParser(ALogger& l, AMathMLFactory& f, const TDictionary& d) : APushParser(l, f), dictionary(d)
{
- init();
+ reset();
+}
+
+TPushParser::~TPushParser()
+{
}
void
-TPushParser::init()
+TPushParser::reset()
{
+ APushParser::reset();
nextId = 1;
cursor = doc.create("cursor");
cursor["id"] = "I0";
doc.clearDirty();
doc.root().append(cursor);
- logger.verbosity(ALogger::Debug);
-}
-
-TPushParser::~TPushParser()
-{
}
std::string
case TToken::ACTIVE: do_active(token.value); break;
case TToken::COMMENT: do_comment(); break;
case TToken::CONTROL: do_control(token.value); break;
- case TToken::GDELETE: do_gdelete(); break;
}
}
void
TPushParser::push(const TToken& token)
{
- if (token.category == TToken::GDELETE)
- {
- process(token);
- }
- else
- {
-
- TNode parent = cursor.parent();
- // If the cursor has no parent then it is detached from the editing
- // tree, which means this token will be ignored
-
- if (parent)
- // If the parent is a phantom group and the grand-parent is a
- // control sequence, there are two cases:
- // a. we are parsing a delimited argument of a entry
- // b. we are parsing a side of a right- or left-open entry
- if (parent.isG() && !parent.hasId() && parent.parent().isC())
- {
- // There must be an open frame, for the grand-parent is a control sequence
- assert(!frames.empty());
- Frame& frame = frames.top();
- if (!frame.entry.pattern.empty())
+ TNode parent = cursor.parent();
+ // If the cursor has no parent then it is detached from the editing
+ // tree, which means this token will be ignored
+
+ if (parent)
+ // If the parent is a phantom group and the grand-parent is a
+ // control sequence, there are two cases:
+ // a. we are parsing a delimited argument of a entry
+ // b. we are parsing a side of a right- or left-open entry
+ if (parent.isG() && !parent.hasId() && parent.parent().isC())
+ {
+ // There must be an open frame, for the grand-parent is a control sequence
+ assert(!frames.empty());
+ Frame& frame = frames.top();
+ if (!frame.entry.pattern.empty())
+ {
+ // The entry pattern is not empty. By our conventions this means
+ // the entry cannot be open at either end, hence we are parsing
+ // a delimited argument
+ assert(frame.pos + 1 < frame.entry.pattern.size());
+ assert(frame.entry.pattern[frame.pos + 1].category != TToken::PARAMETER);
+ if (frame.entry.pattern[frame.pos + 1] == token)
{
- // The entry pattern is not empty. By our conventions this means
- // the entry cannot be open at either end, hence we are parsing
- // a delimited argument
- assert(frame.pos + 1 < frame.entry.pattern.size());
- assert(frame.entry.pattern[frame.pos + 1].category != TToken::PARAMETER);
- if (frame.entry.pattern[frame.pos + 1] == token)
- {
- // The token matches with a delimiter of the argument,
- // so we increment the frame.pos
+ // The token matches with a delimiter of the argument,
+ // so we increment the frame.pos
+ frame.pos++;
+
+ if (frame.entry.lastDelimiter(frame.pos))
+ {
+ // this delimiter is the last one for the argumet,
+ // so the argument is completed
+ cursor.remove();
frame.pos++;
- if (frame.entry.lastDelimiter(frame.pos))
+ if (frame.pos == frame.entry.pattern.size())
{
- // this delimiter is the last one for the argumet,
- // so the argument is completed
- cursor.remove();
- frame.pos++;
-
- if (frame.pos == frame.entry.pattern.size())
- {
- // This token has completed the entry
- advance(parent);
- }
- else if (frame.entry.paramDelimited(frame.pos))
- {
- // For the next is a delimited argument we have to place
- // a suitable phantom group with the cursor inside
- TNode g = doc.createG();
- parent.parent().append(g);
- g.append(cursor);
- }
- else
- parent.parent().append(cursor);
+ // This token has completed the entry
+ advance(parent);
}
- }
- else
- {
- // Delimiter mismatch.
- if (frame.entry.pattern[frame.pos].category != TToken::PARAMETER)
+ else if (frame.entry.paramDelimited(frame.pos))
{
- // in this case, there is a sequence of delimiters that delimitates
- // the argument, and the user correctly inserted a portion of this
- // sequence, but now has inserted a wrong delimiter.
- // Here, there are some possibilities:
- // - ignore the token, and wait for the correct delimiter
- // - ignore the token, wait for the correct delimiter and emit an error
- // At the moment, we implement the second possibily
- logger.error("parser: it's not the correct delimiter...you have to type " + frame.entry.pattern[frame.pos + 1].value);
+ // For the next is a delimited argument we have to place
+ // a suitable phantom group with the cursor inside
+ TNode g = doc.createG();
+ parent.parent().append(g);
+ g.append(cursor);
}
else
- {
- // in this case, the sequence of delimiters is composed of one
- // delimiter. It means that we have to process the token
- process(token);
- }
- }
+ parent.parent().append(cursor);
+ }
}
else
{
- // The entry pattern is empty, hence we are parsing a right-open
- // entry. What happens if we actually are in the left side?
- // This could happen only when re-editing an entered expression
- // We'll see...
- assert(frame.entry.rightOpen);
- process(token);
- }
- }
- else if (parent.isC())
- {
- // We are parsing a non-delimited argument entry
- // or a fixed token
- Frame& frame = frames.top();
- assert(frame.pos < frame.entry.pattern.size());
-
- if (frame.entry.pattern[frame.pos].category == TToken::PARAMETER)
- {
- // As by the TeX parsing rules of undelimited parameters,
- // empty spaces are ignored
- if (token.category != TToken::SPACE)
- {
- // We need to increase the frame position here, becase inside
- // process the function advance will be called. At that point
- // it will be important for the parser to know that the entry
- // has been completed in order to place the cursor correctly
- // in the next position
- frame.pos++;
+ // Delimiter mismatch.
+ if (frame.entry.pattern[frame.pos].category != TToken::PARAMETER)
+ {
+ // in this case, there is a sequence of delimiters that delimitates
+ // the argument, and the user correctly inserted a portion of this
+ // sequence, but now has inserted a wrong delimiter.
+ // Here, there are some possibilities:
+ // - ignore the token, and wait for the correct delimiter
+ // - ignore the token, wait for the correct delimiter and emit an error
+ // At the moment, we implement the second possibily
+ logger.error("parser: it's not the correct delimiter...you have to type " + frame.entry.pattern[frame.pos + 1].value);
+ }
+ else
+ {
+ // in this case, the sequence of delimiters is composed of one
+ // delimiter. It means that we have to process the token
process(token);
- }
+ }
}
- else if (frame.entry.pattern[frame.pos] == token)
+ }
+ else
+ {
+ // The entry pattern is empty, hence we are parsing a right-open
+ // entry. What happens if we actually are in the left side?
+ // This could happen only when re-editing an entered expression
+ // We'll see...
+ assert(frame.entry.rightOpen);
+ process(token);
+ }
+ }
+ else if (parent.isC())
+ {
+ // We are parsing a non-delimited argument entry
+ // or a fixed token
+ Frame& frame = frames.top();
+ assert(frame.pos < frame.entry.pattern.size());
+
+ if (frame.entry.pattern[frame.pos].category == TToken::PARAMETER)
+ {
+ // As by the TeX parsing rules of undelimited parameters,
+ // empty spaces are ignored
+ if (token.category != TToken::SPACE)
{
- // The token has been accepted
- frame.pos++;
- if (frame.pos < frame.entry.pattern.size() &&
- frame.entry.paramDelimited(frame.pos))
- {
- // If the next is a delimited argument we have to place
- // the phantom group with the cursor inside
- TNode g = doc.createG();
- cursor.replace(g);
- g.append(cursor);
- }
- else
- advance(parent);
+ // We need to increase the frame position here, becase inside
+ // process the function advance will be called. At that point
+ // it will be important for the parser to know that the entry
+ // has been completed in order to place the cursor correctly
+ // in the next position
+ frame.pos++;
+ process(token);
}
- else
+ }
+ else if (frame.entry.pattern[frame.pos] == token)
+ {
+ // The token has been accepted
+ frame.pos++;
+ if (frame.pos < frame.entry.pattern.size() &&
+ frame.entry.paramDelimited(frame.pos))
{
- // There is a mismatch. Emit an error and ignore the token?
- logger.debug("parser: token ignored: " + token.value);
+ // If the next is a delimited argument we have to place
+ // the phantom group with the cursor inside
+ TNode g = doc.createG();
+ cursor.replace(g);
+ g.append(cursor);
}
+ else
+ advance(parent);
+ }
+ else
+ {
+ // There is a mismatch. Emit an error and ignore the token?
+ logger.debug("parser: token ignored: " + token.value);
+ }
- }
- else
- process(token);
- else
- {
- logger.warning("ignored token");
- }
-
- } // this end corresponds to the else of the if (token.category == TToken::GDELETE)
+ }
+ else
+ process(token);
+ else
+ {
+ logger.warning("ignored token");
+ }
- if (factory) factory->documentModified(doc);
+ if (factory && doc.dirtyNode() && !frozen()) factory->documentModified(doc);
+}
+std::string
+TPushParser::drop()
+{
+ do_gdelete();
+ if (factory && doc.dirtyNode() && !frozen()) factory->documentModified(doc);
+ return "";
}
void
void
TPushParser::setCursorHint(const std::string& c)
{
- cursor["val"] = c;
- if (factory) factory->documentModified(doc);
+ if (cursor["val"] != c)
+ {
+ cursor["val"] = c;
+ if (factory && doc.dirtyNode() && !frozen()) factory->documentModified(doc);
+ }
+}
+
+bool
+TPushParser::thaw()
+{
+ if (APushParser::thaw() && factory && doc.dirtyNode())
+ {
+ factory->documentModified(doc);
+ return true;
+ }
+ else
+ return false;
}
TPushParser(class ALogger&, class AMathMLFactory&, const class TDictionary&);
virtual ~TPushParser();
+ virtual void reset(void);
virtual void push(const TToken&);
+ virtual std::string drop(void);
virtual void setCursorHint(const std::string&);
-protected:
- TDocument document(void) const { return doc; }
+ virtual bool thaw(void);
-private:
- void init(void);
+ DOM::Document document(void) const { return doc.document().cloneNode(true); }
+private:
std::string PRIME(void) const;
bool isPrimes(const TNode&) const;
OTHER,
ACTIVE,
COMMENT,
- CONTROL,
- GDELETE
+ CONTROL
};
TToken(TCat c) : category(c) { };
tokens.push_back(token);
}
+std::string
+TTokenizer::drop()
+{
+ assert(0);
+ return "";
+}
private:
virtual void push(const TToken&);
+ virtual std::string drop(void);
virtual void setCursorHint(const std::string&) { };
std::list<TToken> tokens;
#include <GdomeSmartDOMXSLT.hh>
namespace DOM = GdomeSmartDOM;
+namespace DOMX = GdomeSmartDOMExt;
typedef DOM::Char32 TChar;
typedef DOM::UCS4String TString;
#ifndef __globals_hh__
#define __globals_hh__
-#define TML_NS_URI "http://helm.cs.unibo.it/2002/TML"
-#define XMLNS_NS_URI "http://www.w3.org/2000/xmlns/"
+#define TML_NS_URI "http://helm.cs.unibo.it/2002/TML"
+#define XMLNS_NS_URI "http://www.w3.org/2000/xmlns/"
+#define MATHML_NS_URI "http://www.w3.org/1998/Math/MathML"
#endif // __globals_hh__
GMETADOM_LIBS = @GMETADOM_LIBS@
GTKMATHVIEW_CFLAGS = @GTKMATHVIEW_CFLAGS@
GTKMATHVIEW_LIBS = @GTKMATHVIEW_LIBS@
+HAVE_OCAMLC = @HAVE_OCAMLC@
+HAVE_OCAMLDEP = @HAVE_OCAMLDEP@
+HAVE_OCAMLFIND = @HAVE_OCAMLFIND@
+HAVE_OCAMLMKLIB = @HAVE_OCAMLMKLIB@
+HAVE_OCAMLOPT = @HAVE_OCAMLOPT@
LDFLAGS = @LDFLAGS@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
MAKEINFO = @MAKEINFO@
+MLGDOME_CFLAGS = @MLGDOME_CFLAGS@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OCAMLC = @OCAMLC@
+OCAMLDEP = @OCAMLDEP@
+OCAMLFIND = @OCAMLFIND@
+OCAMLMKLIB = @OCAMLMKLIB@
+OCAMLOPT = @OCAMLOPT@
+OCAMLSTDLIBDIR = @OCAMLSTDLIBDIR@
+OCAMLSTUBDIR = @OCAMLSTUBDIR@
+OCAML_INCLUDE_DIR = @OCAML_INCLUDE_DIR@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
STRIP = @STRIP@
lastS = q;
}
+static DOM::Element
+findElementWithRef(const DOM::Element& el)
+{
+ DOM::Element p = el;
+ while (p && !p.hasAttribute("xref")) p = p.get_parentNode();
+ return p;
+}
+
static DOM::Node
leftmostChild(const DOM::Node& node)
{
extern "C" GdomeElement*
find_common_ancestor(GdomeElement* first, GdomeElement* last)
{
- DOM::Element p(first);
- DOM::Element q(last);
- if (GdomeElement* res = gdome_cast_el(findCommonAncestor(p, q).gdome_object()))
+ if (GdomeNode* n = findCommonAncestor(DOM::Element(first), DOM::Element(last)).gdome_object())
{
- GdomeException exc = 0;
- gdome_el_ref(res, &exc);
- assert(exc == 0);
+ GdomeElement* res = gdome_cast_el(n);
+ g_assert(res != NULL);
return res;
}
else
- return 0;
+ return NULL;
}
extern "C" void
if (lastS != NULL) *lastS = gdome_cast_el(ls.gdome_object());
}
+extern "C" GdomeElement*
+find_element_with_ref(GdomeElement* elem)
+{
+ if (GdomeNode* n = findElementWithRef(DOM::Element(elem)).gdome_object())
+ {
+ GdomeElement* res = gdome_cast_el(n);
+ g_assert(res != NULL);
+ return res;
+ }
+ else
+ return NULL;
+}
+
+extern "C" GdomeElement*
+find_common_ancestor_with_ref(GdomeElement* first, GdomeElement* last)
+{
+ if (GdomeNode* n = findElementWithRef(findCommonAncestor(DOM::Element(first), DOM::Element(last))).gdome_object())
+ {
+ GdomeElement* res = gdome_cast_el(n);
+ g_assert(res != NULL);
+ return res;
+ }
+ else
+ return NULL;
+}
+
extern "C" void
delete_element(GdomeElement* elem)
{
#include "TDictionary.hh"
#include "CLoggerConsole.hh"
#include "CMathMLFactoryXSLT.hh"
+#include "CMathMLFactoryXSLTDiff.hh"
#include "AMathMLConsumer.hh"
#include "guiGTK.h"
-TDictionary dictionary;
-
extern void *parseMathMLFile(char *);
-class CMathMLConsumer : public AMathMLConsumer
-{
-public:
- CMathMLConsumer(void) { firstTime = true; };
-
- virtual void documentModified(const DOM::Document& result)
- {
- if (firstTime)
- {
- if (GUI_load_document(gdome_cast_doc(static_cast<GdomeNode*>(result))) < 0)
- cerr << "c'e' stato un errore" << endl;
- firstTime = false;
- }
- }
-
-private:
- bool firstTime;
-};
-
struct Context
{
- Context(const std::string& s, TPushLexer& l) : buffer(s), i(0), lexer(l) { };
+ Context(const std::string& s, TPushLexer& l, TPushParser& p) : buffer(s), i(0), lexer(l), parser(p) { };
void send(void)
{
std::string buffer;
unsigned i;
TPushLexer& lexer;
+ TPushParser& parser;
};
extern "C" int
}
extern "C" void
-push_char(Context* context, gchar ch)
+edit_push_char(Context* context, gchar ch)
{
+ assert(context != NULL);
GUI_freeze();
cout << "*** SENDING " << ch << endl;
context->lexer.push(ch);
GUI_thaw();
}
+extern "C" void
+edit_push_string(Context* context, const gchar* s)
+{
+ assert(context != NULL);
+ assert(s != NULL);
+ GUI_freeze();
+ context->parser.freeze();
+ for (unsigned i = 0; s[i]; i++) context->lexer.push(s[i]);
+ context->parser.thaw();
+ GUI_thaw();
+}
+
+extern "C" void
+edit_drop(Context* context, gboolean alt)
+{
+ assert(context != NULL);
+ GUI_freeze();
+ context->lexer.drop(alt);
+ GUI_thaw();
+}
+
+void
main(int argc, char* argv[])
{
CLoggerConsole logger;
+ logger.verbosity(ALogger::Debug);
+
+ TDictionary dictionary(logger);
logger.info("loading the dictionary...");
- dictionary.load("dictionary.xml");
+ dictionary.load("dictionary-test.xml");
logger.info("loading the stylesheet...");
DOM::DOMImplementation di;
DOM::Document docStyle = di.createDocumentFromURI("./xsl/tml-mmlp.xsl");
- DOM::XSLTStylesheet style(docStyle);
+ DOMX::XSLTStylesheet style(docStyle);
- CMathMLConsumer consumer;
- CMathMLFactoryXSLT factory(logger, consumer, style);
+ CMathMLFactoryXSLTDiff factory(logger, style);
TPushParser parser(logger, factory, dictionary);
TPushLexer lexer(logger, parser);
style.save(result, stdout);
#endif
- Context context("", lexer);
+ Context context("", lexer, parser);
GUI_init(&argc, &argv, "mathmleditor", 500, 600, &context);
+ GUI_load_document(gdome_cast_doc(static_cast<GdomeNode*>(factory.document())));
GUI_run();
GUI_uninit();
GUI_unload_document();
static GtkWidget* window;
static GtkWidget* main_area;
static GtkWidget* scrolled_area;
-static GtkWidget* status_bar;
static GtkMenuItem* anti_aliasing_item;
static GtkMenuItem* transparency_item;
-static GdkCursor* normal_cursor;
-static GdkCursor* link_cursor;
+static gpointer context = NULL;
static gchar* doc_name = NULL;
+static GdomeElement* first_selected = NULL;
static GdomeElement* root_selected = NULL;
-static guint statusbar_context;
-
static void create_widget_set(gpointer);
static GtkWidget* get_main_menu(void);
static void file_open(GtkWidget*, gpointer);
static void options_verbosity(GtkWidget*, guint);
static void options_anti_aliasing(GtkWidget*, gpointer);
static void options_transparency(GtkWidget*, gpointer);
-static void selection_delete(GtkWidget*, gpointer);
-static void selection_parent(GtkWidget*, gpointer);
-static void selection_reset(GtkWidget*, gpointer);
+static void edit_delete_selection(GtkWidget*, gpointer);
+static void edit_select_parent(GtkWidget*, gpointer);
+static void edit_reset_selection(GtkWidget*, gpointer);
+static void edit_insert(GtkWidget*, gpointer);
static void help_about(GtkWidget*, gpointer);
static GtkItemFactoryEntry menu_items[] = {
{ "/File/sep1", NULL, NULL, 0, "<Separator>" },
{ "/File/_Quit", "<control>Q", gtk_main_quit, 0, NULL },
- { "/_Selection", NULL, NULL, 0, "<Branch>" },
- { "/Selection/Reset", NULL, selection_reset, 0, NULL },
- { "/Selection/Delete", NULL, selection_delete, 0, NULL },
- { "/Selection/Select Parent", NULL, selection_parent, 0, NULL },
+ { "/_Edit", NULL, NULL, 0, "<Branch>" },
+ { "/Edit/Reset Selection", NULL, edit_reset_selection, 0, NULL },
+ { "/Edit/Delete Selection", NULL, edit_delete_selection, 0, NULL },
+ { "/Edit/Select Parent", NULL, edit_select_parent, 0, NULL },
+ { "/Edit/sep1", NULL, NULL, 0, "<Separator>" },
+ { "/Edit/Insert...", "<control>I", edit_insert, 0, NULL },
{ "/_Options", NULL, NULL, 0, "<Branch>" },
{ "/Options/Default _Font Size", NULL, NULL, 0, "<Branch>" },
}
void
-GUI_init(int* argc, char*** argv, char* title, guint width, guint height, gpointer context)
+GUI_init(int* argc, char*** argv, char* title, guint width, guint height, gpointer c)
{
gtk_init(argc, argv);
gtk_widget_show(window);
- normal_cursor = gdk_cursor_new(GDK_TOP_LEFT_ARROW);
- link_cursor = gdk_cursor_new(GDK_HAND2);
-
+ context = c;
/*edit_timeout_id = gtk_timeout_add(400, edit_timeout, context);*/
}
void
GUI_uninit()
{
+ GdomeException exc = 0;
+
+ if (first_selected != NULL)
+ {
+ gdome_el_unref(first_selected, &exc);
+ g_assert(exc == 0);
+ first_selected = NULL;
+ }
+
+ if (root_selected != NULL)
+ {
+ gdome_el_unref(root_selected, &exc);
+ g_assert(exc == 0);
+ root_selected = NULL;
+ }
+
+ context = NULL;
}
int
if (doc_name != NULL) g_free(doc_name);
doc_name = NULL;
-
- gtk_statusbar_pop(GTK_STATUSBAR(status_bar), statusbar_context);
- gtk_statusbar_push(GTK_STATUSBAR(status_bar), statusbar_context, "");
}
void
}
static void
-selection_delete(GtkWidget* widget, gpointer data)
+edit_delete_selection(GtkWidget* widget, gpointer data)
{
if (root_selected != NULL)
{
}
static void
-selection_parent(GtkWidget* widget, gpointer data)
+edit_select_parent(GtkWidget* widget, gpointer data)
{
if (root_selected != NULL)
{
}
static void
-selection_reset(GtkWidget* widget, gpointer data)
+edit_reset_selection(GtkWidget* widget, gpointer data)
{
if (root_selected != NULL)
{
}
}
+static void
+insert_tex(GtkWidget* widget, GtkEntry* entry)
+{
+ gchar* text;
+ g_return_if_fail(entry != NULL);
+
+ text = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
+ edit_push_string(context, text);
+ g_free(text);
+}
+
+static void
+edit_insert(GtkWidget* widget, gpointer data)
+{
+ GtkWidget* dialog;
+ GtkWidget* entry;
+ GtkWidget* ok;
+ GtkWidget* cancel;
+
+ dialog = gtk_dialog_new();
+ entry = gtk_entry_new();
+ ok = gtk_button_new_with_label("OK");
+ cancel = gtk_button_new_with_label("Cancel");
+
+ gtk_signal_connect (GTK_OBJECT (ok), "clicked",
+ GTK_SIGNAL_FUNC (insert_tex), (gpointer) entry);
+
+ gtk_signal_connect_object (GTK_OBJECT (ok), "clicked",
+ GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog);
+
+ gtk_signal_connect_object (GTK_OBJECT (ok), "clicked",
+ GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog);
+
+ gtk_signal_connect_object (GTK_OBJECT (cancel), "clicked",
+ GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog);
+
+ gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), 5);
+
+ gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), entry);
+ gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area), ok);
+ gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area), cancel);
+
+ gtk_widget_show_all (dialog);
+}
+
static void
help_about(GtkWidget* widget, gpointer data)
{
GtkWidget* ok;
dialog = gtk_dialog_new();
- label = gtk_label_new("\n MathML Viewer \n Copyright (C) 2000-2003 Luca Padovani \n");
+ label = gtk_label_new("\n MathML Editor \n Copyright (C) 2003 Luca Padovani \n");
ok = gtk_button_new_with_label("Close");
gtk_signal_connect_object (GTK_OBJECT (ok), "clicked",
}
static void
-change_default_font_size(GtkSpinButton* widget, GtkSpinButton* spin)
+change_default_font_size(GtkWidget* widget, GtkSpinButton* spin)
{
g_return_if_fail(spin != NULL);
gtk_math_view_set_font_size( GTK_MATH_VIEW(main_area), gtk_spin_button_get_value_as_int(spin));
gtk_widget_show_all (dialog);
}
-#if 0
-#if defined(HAVE_GMETADOM)
static void
-element_changed(GtkMathView* math_view, GdomeElement* elem)
+select_begin(GtkMathView* math_view, GdomeElement* first, gint state)
{
- GdomeDOMString* link = NULL;
-
- g_return_if_fail(math_view != NULL);
- g_return_if_fail(GTK_IS_MATH_VIEW(math_view));
-
-/* printf("pointer is on %p\n", elem); */
+ GdomeException exc = 0;
- link = find_hyperlink(elem, XLINK_NS_URI, "href");
- if (link != NULL)
- gdk_window_set_cursor(GTK_WIDGET(math_view)->window, link_cursor);
- else
- gdk_window_set_cursor(GTK_WIDGET(math_view)->window, normal_cursor);
-
- if (link != NULL)
- gdome_str_unref(link);
-}
-#endif
-#endif
-
-static void
-selection_changed(GtkMathView* math_view, GdomeElement* first, GdomeElement* last)
-{
g_return_if_fail(math_view != NULL);
g_return_if_fail(GTK_IS_MATH_VIEW(math_view));
g_return_if_fail(first != NULL);
-/* printf("selection changed %p %p\n", first, last); */
+ gtk_math_view_freeze(math_view);
- if (last != NULL)
+ if (root_selected != NULL)
{
- GdomeException exc = 0;
+ gtk_math_view_unselect(math_view, root_selected);
+ gdome_el_unref(root_selected, &exc);
+ g_assert(exc == 0);
+ }
- if (root_selected != NULL)
- {
- gdome_el_unref(root_selected, &exc);
- g_assert(exc == 0);
- }
+ root_selected = first_selected = find_element_with_ref(first);
- root_selected = find_common_ancestor(first, last);
-/* printf("selecting root %p\n", first, last, root_selected); */
- /* gtk_math_view_set_selection(math_view, root_selected); */
+ if (root_selected != NULL)
+ {
+ gtk_math_view_select(math_view, root_selected);
+ gdome_el_ref(root_selected, &exc);
g_assert(exc == 0);
}
+
+ gtk_math_view_thaw(math_view);
}
-#if 0
-#if defined(HAVE_GMETADOM)
static void
-clicked(GtkMathView* math_view, GdomeElement* elem)
+select_over(GtkMathView* math_view, GdomeElement* elem, gint state)
{
- GdomeException exc;
- GdomeDOMString* name;
- GdomeDOMString* ns_uri;
- GdomeElement* p;
+ GdomeElement* new_selected = NULL;
+ GdomeException exc = 0;
g_return_if_fail(math_view != NULL);
+ g_return_if_fail(GTK_IS_MATH_VIEW(math_view));
+ g_return_if_fail(elem != NULL);
- /* printf("clicked on %p\n", elem); */
+ if (first_selected == NULL || elem == NULL)
+ new_selected = NULL;
+ else
+ new_selected = find_common_ancestor_with_ref(first_selected, elem);
- if (elem != NULL)
+ if (new_selected != root_selected)
{
- GdomeElement* action;
- GdomeDOMString* href = find_hyperlink(elem, XLINK_NS_URI, "href");
- if (href != NULL)
- {
-/* printf("hyperlink %s\n", href->str); */
- gdome_str_unref(href);
- }
-
- action = find_self_or_ancestor(elem, MATHML_NS_URI, "maction");
-/* printf("action? %p\n", action); */
- if (action != NULL)
+ gtk_math_view_freeze(math_view);
+ if (root_selected != NULL)
{
- gtk_math_view_freeze(math_view);
- action_toggle(action);
- gtk_math_view_thaw(math_view);
- gdome_el_unref(action, &exc);
+ gtk_math_view_unselect(math_view, root_selected);
+ gdome_el_unref(root_selected, &exc);
g_assert(exc == 0);
}
+ root_selected = new_selected;
+ if (root_selected != NULL)
+ gtk_math_view_select(math_view, root_selected);
+ gtk_math_view_thaw(math_view);
+ }
+ else if (new_selected != NULL)
+ {
+ gdome_el_unref(new_selected, &exc);
+ g_assert(exc == 0);
}
+
}
-#endif
-#endif
static gboolean
-key_press_event(gpointer context,
+key_press_event(gpointer c,
GdkEventKey* event,
GtkWidget* widget)
{
if (event->type != GDK_KEY_PRESS) return FALSE;
- switch (event->keyval) {
- case GDK_Up:
- case GDK_KP_Up:
- break;
- case GDK_Down:
- case GDK_KP_Down:
- break;
- case GDK_Left:
- case GDK_KP_Left:
- break;
- case GDK_Right:
- case GDK_KP_Right:
- break;
- case GDK_Page_Up:
- case GDK_KP_Page_Up:
- break;
- case GDK_Page_Down:
- case GDK_KP_Page_Down:
- break;
- case GDK_Home:
- case GDK_KP_Home:
- break;
- case GDK_End:
- case GDK_KP_End:
- break;
- case GDK_BackSpace: push_char(context, event->keyval); break;
- default:
- if (event->keyval < 0x80) push_char(context, event->keyval);
- return FALSE;
- }
+ switch (event->keyval)
+ {
+ case GDK_BackSpace:
+ edit_drop(context, event->state & GDK_MOD1_MASK);
+ break;
+ default:
+ if ((event->state & (~GDK_SHIFT_MASK)) == 0 && event->keyval < 0x80)
+ edit_push_char(context, event->keyval);
+ return FALSE;
+ }
return TRUE;
}
//gtk_math_view_set_log_verbosity(GTK_MATH_VIEW(main_area), 3);
-#if 0
gtk_signal_connect_object (GTK_OBJECT (main_area),
- "selection_changed", GTK_SIGNAL_FUNC (selection_changed),
+ "select_begin", GTK_SIGNAL_FUNC (select_begin),
(gpointer) main_area);
gtk_signal_connect_object (GTK_OBJECT (main_area),
- "element_changed", GTK_SIGNAL_FUNC (element_changed),
- (gpointer) main_area);
-
- gtk_signal_connect_object (GTK_OBJECT (main_area),
- "action_changed", GTK_SIGNAL_FUNC (action_changed),
- (gpointer) main_area);
-
- gtk_signal_connect_object (GTK_OBJECT (main_area),
- "clicked", GTK_SIGNAL_FUNC(clicked),
+ "select_over", GTK_SIGNAL_FUNC (select_over),
(gpointer) main_area);
-#endif
gtk_signal_connect_object (GTK_OBJECT(window),
"key_press_event", GTK_SIGNAL_FUNC(key_press_event),
context);
- gtk_widget_add_events(GTK_WIDGET(main_area),
- GDK_BUTTON_PRESS_MASK
- | GDK_BUTTON_RELEASE_MASK
- | GDK_POINTER_MOTION_MASK
- | GDK_KEY_PRESS_MASK);
+ gtk_widget_add_events(GTK_WIDGET(main_area), GDK_KEY_PRESS_MASK);
scrolled_area = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_area),
gtk_container_add(GTK_CONTAINER(scrolled_area), main_area);
gtk_box_pack_start(GTK_BOX(main_vbox), scrolled_area, TRUE, TRUE, 0);
- status_bar = gtk_statusbar_new();
- gtk_widget_show(status_bar);
- gtk_box_pack_start(GTK_BOX(main_vbox), status_bar, FALSE, TRUE, 0);
- statusbar_context = gtk_statusbar_get_context_id(GTK_STATUSBAR(status_bar), "filename");
-
- gtk_widget_show(main_vbox);
-
- if (gtk_math_view_get_anti_aliasing(GTK_MATH_VIEW(main_area)))
- gtk_menu_item_activate(anti_aliasing_item);
-}
-
-#if 0
-static void
-create_widget_set()
-{
- GtkWidget* main_vbox;
- GtkWidget* menu_bar;
-
- main_vbox = gtk_vbox_new(FALSE, 1);
- gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
- gtk_container_add(GTK_CONTAINER(window), main_vbox);
- gtk_widget_show(main_vbox);
-
- menu_bar = get_main_menu();
- gtk_box_pack_start(GTK_BOX(main_vbox), menu_bar, FALSE, TRUE, 0);
- gtk_widget_show(menu_bar);
-
- main_area = gtk_math_view_new(NULL, NULL);
- gtk_widget_show(main_area);
-
- gtk_signal_connect_object (GTK_OBJECT (main_area),
- "selection_changed", GTK_SIGNAL_FUNC (selection_changed),
- (gpointer) main_area);
-
- gtk_signal_connect_object (GTK_OBJECT (main_area),
- "element_changed", GTK_SIGNAL_FUNC (element_changed),
- (gpointer) main_area);
-
- gtk_signal_connect_object (GTK_OBJECT (main_area),
- "clicked", GTK_SIGNAL_FUNC(clicked),
- (gpointer) main_area);
-
- gtk_widget_add_events(GTK_WIDGET(main_area),
- GDK_BUTTON_PRESS_MASK
- | GDK_BUTTON_RELEASE_MASK
- | GDK_POINTER_MOTION_MASK);
-
- scrolled_area = gtk_scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_area),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
- gtk_widget_show(scrolled_area);
- gtk_container_add(GTK_CONTAINER(scrolled_area), main_area);
- gtk_box_pack_start(GTK_BOX(main_vbox), scrolled_area, TRUE, TRUE, 0);
-
- status_bar = gtk_statusbar_new();
- gtk_widget_show(status_bar);
- gtk_box_pack_start(GTK_BOX(main_vbox), status_bar, FALSE, TRUE, 0);
- statusbar_context = gtk_statusbar_get_context_id(GTK_STATUSBAR(status_bar), "filename");
-
gtk_widget_show(main_vbox);
if (gtk_math_view_get_anti_aliasing(GTK_MATH_VIEW(main_area)))
gtk_menu_item_activate(anti_aliasing_item);
}
-#endif
GtkWidget*
get_main_menu()
<xsl:attribute name="xref">
<xsl:value-of select="@id"/>
</xsl:attribute>
- </xsl:if>
- I
- </m:mtext>
+ </xsl:if>I</m:mtext>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:value-of select="@id"/>
</xsl:attribute>
</xsl:if>
- <xsl:apply-templates select="*[2]"/>
- <xsl:apply-templates select="*[1]"/>
+ <xsl:choose>
+ <xsl:when test="count(*) < 2">
+ <m:mrow/>
+ <xsl:apply-templates select="*[1]"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="*[2]"/>
+ <xsl:apply-templates select="*[1]"/>
+ </xsl:otherwise>
+ </xsl:choose>
</m:mroot>
</xsl:template>